CORE: Few fixes from mupen64plus-ae
[mupen64plus-pandora.git] / source / mupen64plus-rsp-hle / src / ucode1.cpp
CommitLineData
d9e74a6f 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 *
6 * *
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. *
11 * *
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. *
16 * *
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 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
22
23# include <string.h>
24
25extern "C" {
26 #include "hle.h"
27 #include "alist_internal.h"
28}
29
30//#include "rsp.h"
31//#define SAFE_MEMORY
32/*
33#ifndef SAFE_MEMORY
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);
44#else
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);
55#endif
56*/
57/******** DMEM Memory Map for ABI 1 ***************
58Address/Range Description
59------------- -------------------------------
600x000..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?)
660x2C0..0x31F <Unknown>
670x320..0x35F Segments
680x360 Audio In Buffer (Location)
690x362 Audio Out Buffer (Location)
700x364 Audio Buffer Size (Location)
710x366 Initial Volume for Left Channel
720x368 Initial Volume for Right Channel
730x36A Auxillary Buffer #1 (Location)
740x36C Auxillary Buffer #2 (Location)
750x36E Auxillary Buffer #3 (Location)
760x370 Loop Value (shared location)
770x370 Target Volume (Left)
780x372 Ramp?? (Left)
790x374 Rate?? (Left)
800x376 Target Volume (Right)
810x378 Ramp?? (Right)
820x37A Rate?? (Right)
830x37C Dry??
840x37E Wet??
850x380..0x4BF Alist data
860x4C0..0x4FF ADPCM CodeBook
870x500..0x5BF <Unknown>
880x5C0..0xF7F Buffers...
890xF80..0xFFF <Unknown>
90***************************************************/
91#ifdef USE_EXPANSION
92 #define MEMMASK 0x7FFFFF
93#else
94 #define MEMMASK 0x3FFFFF
95#endif
96
97static void SPNOOP (u32 inst1, u32 inst2) {
98 //MessageBox (NULL, "Unknown Audio Command in ABI 1", "Audio HLE Error", MB_OK);
99}
100
101u32 SEGMENTS[0x10]; // 0x0320
102// T8 = 0x360
103u16 AudioInBuffer; // 0x0000(T8)
104u16 AudioOutBuffer; // 0x0002(T8)
105u16 AudioCount; // 0x0004(T8)
106s16 Vol_Left; // 0x0006(T8)
107s16 Vol_Right; // 0x0008(T8)
108u16 AudioAuxA; // 0x000A(T8)
109u16 AudioAuxC; // 0x000C(T8)
110u16 AudioAuxE; // 0x000E(T8)
111u32 loopval; // 0x0010(T8) // Value set by A_SETLOOP : Possible conflict with SETVOLUME???
112s16 VolTrg_Left; // 0x0010(T8)
113s32 VolRamp_Left; // m_LeftVolTarget
114//u16 VolRate_Left; // m_LeftVolRate
115s16 VolTrg_Right; // m_RightVol
116s32 VolRamp_Right; // m_RightVolTarget
117//u16 VolRate_Right; // m_RightVolRate
118s16 Env_Dry; // 0x001C(T8)
119s16 Env_Wet; // 0x001E(T8)
120
121u8 BufferSpace[0x10000];
122
123short hleMixerWorkArea[256];
124u16 adpcmtable[0x88];
125
126extern 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
159};
160
161static void CLEARBUFF (u32 inst1, u32 inst2) {
162 u32 addr = (u32)(inst1 & 0xffff);
163 u32 count = (u32)(inst2 & 0xffff);
164 addr &= 0xFFFC;
165 memset(BufferSpace+addr, 0, (count+3)&0xFFFC);
166}
167
168//FILE *dfile = fopen ("d:\\envmix.txt", "wt");
169
170static 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];
174 //static
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);
178 }*/
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);
185 s32 MainR;
186 s32 MainL;
187 s32 AuxR;
188 s32 AuxL;
189 int i1,o1,a1,a2=0,a3=0;
190 unsigned short AuxIncRate=1;
191 short zero[8];
192 memset(zero,0,16);
193 s32 LVol, RVol;
194 s32 LAcc, RAcc;
195 s32 LTrg, RTrg;
196 s16 Wet, Dry;
197 u32 ptr = 0;
198 s32 RRamp, LRamp;
199 s32 LAdderStart, RAdderStart, LAdderEnd, RAdderEnd;
200 s32 oMainR, oMainL, oAuxR, oAuxL;
201
202 //envmixcnt++;
203
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;
212 LAdderEnd = LVol;
213 RAdderEnd = RVol;
214 RRamp = VolRamp_Right;
215 LRamp = VolRamp_Left;
216 } else {
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
230 }
231
232 if(!(flags&A_AUX)) {
233 AuxIncRate=0;
234 aux2=aux3=zero;
235 }
236
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;
241
242 for (int y = 0; y < AudioCount; y += 0x10) {
243
244 if (LAdderStart != LTrg) {
245 LAcc = LAdderStart;
246 LVol = (LAdderEnd - LAdderStart) >> 3;
247 LAdderEnd = (s32) (((s64)LAdderEnd * (s64)LRamp) >> 16);
248 LAdderStart = (s32) (((s64)LAcc * (s64)LRamp) >> 16);
249 } else {
250 LAcc = LTrg;
251 LVol = 0;
252 }
253
254 if (RAdderStart != RTrg) {
255 RAcc = RAdderStart;
256 RVol = (RAdderEnd - RAdderStart) >> 3;
257 RAdderEnd = (s32) (((s64)RAdderEnd * (s64)RRamp) >> 16);
258 RAdderStart = (s32) (((s64)RAcc * (s64)RRamp) >> 16);
259 } else {
260 RAcc = RTrg;
261 RVol = 0;
262 }
263
264 for (int x = 0; x < 8; x++) {
265 i1=(int)inp[ptr^S];
266 o1=(int)out[ptr^S];
267 a1=(int)aux1[ptr^S];
268 if (AuxIncRate) {
269 a2=(int)aux2[ptr^S];
270 a3=(int)aux3[ptr^S];
271 }
272 // TODO: here...
273 //LAcc = LTrg;
274 //RAcc = RTrg;
275
276 LAcc += LVol;
277 RAcc += RVol;
278
279 if (LVol <= 0) { // Decrementing
280 if (LAcc < LTrg) {
281 LAcc = LTrg;
282 LAdderStart = LTrg;
283 MainL = oMainL;
284 AuxL = oAuxL;
285 } else {
286 MainL = (Dry * ((s32)LAcc>>16) + 0x4000) >> 15;
287 AuxL = (Wet * ((s32)LAcc>>16) + 0x4000) >> 15;
288 }
289 } else {
290 if (LAcc > LTrg) {
291 LAcc = LTrg;
292 LAdderStart = LTrg;
293 MainL = oMainL;
294 AuxL = oAuxL;
295 } else {
296 MainL = (Dry * ((s32)LAcc>>16) + 0x4000) >> 15;
297 AuxL = (Wet * ((s32)LAcc>>16) + 0x4000) >> 15;
298 }
299 }
300
301 if (RVol <= 0) { // Decrementing
302 if (RAcc < RTrg) {
303 RAcc = RTrg;
304 RAdderStart = RTrg;
305 MainR = oMainR;
306 AuxR = oAuxR;
307 } else {
308 MainR = (Dry * ((s32)RAcc>>16) + 0x4000) >> 15;
309 AuxR = (Wet * ((s32)RAcc>>16) + 0x4000) >> 15;
310 }
311 } else {
312 if (RAcc > RTrg) {
313 RAcc = RTrg;
314 RAdderStart = RTrg;
315 MainR = oMainR;
316 AuxR = oAuxR;
317 } else {
318 MainR = (Dry * ((s32)RAcc>>16) + 0x4000) >> 15;
319 AuxR = (Wet * ((s32)RAcc>>16) + 0x4000) >> 15;
320 }
321 }
322
323 //fprintf (dfile, "%04X ", (LAcc>>16));
324
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;*/
329/*
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;*/
338 /*
339 MainR = (Dry * RTrg + 0x10000) >> 15;
340 MainL = (Dry * LTrg + 0x10000) >> 15;
341 AuxR = (Wet * RTrg + 0x8000) >> 16;
342 AuxL = (Wet * LTrg + 0x8000) >> 16;*/
343
344 o1+=(/*(o1*0x7fff)+*/(i1*MainR)+0x4000)>>15;
345 a1+=(/*(a1*0x7fff)+*/(i1*MainL)+0x4000)>>15;
346
347/* o1=((s64)(((s64)o1*0xfffe)+((s64)i1*MainR*2)+0x8000)>>16);
348
349 a1=((s64)(((s64)a1*0xfffe)+((s64)i1*MainL*2)+0x8000)>>16);*/
350
351 if(o1>32767) o1=32767;
352 else if(o1<-32768) o1=-32768;
353
354 if(a1>32767) a1=32767;
355 else if(a1<-32768) a1=-32768;
356
357 out[ptr^S]=o1;
358 aux1[ptr^S]=a1;
359 if (AuxIncRate) {
360 //a2=((s64)(((s64)a2*0xfffe)+((s64)i1*AuxR*2)+0x8000)>>16);
361
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;
365
366 if(a2>32767) a2=32767;
367 else if(a2<-32768) a2=-32768;
368
369 if(a3>32767) a3=32767;
370 else if(a3<-32768) a3=-32768;
371
372 aux2[ptr^S]=a2;
373 aux3[ptr^S]=a3;
374 }
375 ptr++;
376 }
377 }
378
379 /*LAcc = LAdderEnd;
380 RAcc = RAdderEnd;*/
381
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);
393}
394
395static 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;
401 s16 *lut/*, *lut2*/;
402 short *dst;
403 s16 *src;
404 dst=(short *)(BufferSpace);
405 src=(s16 *)(BufferSpace);
406 u32 srcPtr=(AudioInBuffer/2);
407 u32 dstPtr=(AudioOutBuffer/2);
408 s32 temp;
409 s32 accum;
410/*
411 if (addy > (1024*1024*8))
412 addy = (inst2 & 0xffffff);
413*/
414 srcPtr -= 4;
415
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);
421 } else {
422 for (int x=0; x < 4; x++)
423 src[(srcPtr+x)^S] = 0;//*(u16 *)(rsp.RDRAM+((addy+x)^2));
424 }
425
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;
431
432 // mov eax, dword ptr [src+srcPtr];
433 // movsx edx, word ptr [lut];
434 // shl edx, 1
435 // imul edx
436 // test eax, 08000h
437 // setz ecx
438 // shl ecx, 16
439 // xor eax, 08000h
440 // add eax, ecx
441 // and edx, 0f000h
442
443 // imul
444 temp = ((s32)*(s16*)(src+((srcPtr+0)^S))*((s32)((s16)lut[0])));
445 accum = (s32)(temp >> 15);
446
447 temp = ((s32)*(s16*)(src+((srcPtr+1)^S))*((s32)((s16)lut[1])));
448 accum += (s32)(temp >> 15);
449
450 temp = ((s32)*(s16*)(src+((srcPtr+2)^S))*((s32)((s16)lut[2])));
451 accum += (s32)(temp >> 15);
452
453 temp = ((s32)*(s16*)(src+((srcPtr+3)^S))*((s32)((s16)lut[3])));
454 accum += (s32)(temp >> 15);
455
456 if (accum > 32767) accum = 32767;
457 if (accum < -32768) accum = -32768;
458
459 dst[dstPtr^S] = (accum);
460 dstPtr++;
461 Accum += Pitch;
462 srcPtr += (Accum>>16);
463 Accum&=0xffff;
464 }
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;
469}
470
471static 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));
477
478 if (flags & A_AUX) {
479 Env_Dry = (s16)vol; // m_MainVol
480 Env_Wet = (s16)volrate; // m_AuxVol
481 return;
482 }
483
484 if(flags & A_VOL) { // Set the Source(start) Volumes
485 if(flags & A_LEFT) {
486 Vol_Left = (s16)vol; // m_LeftVolume
487 } else { // A_RIGHT
488 Vol_Right = (s16)vol; // m_RightVolume
489 }
490 return;
491 }
492
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
505 } else { // A_RIGHT
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
513 }
514}
515
516static void UNKNOWN (u32 inst1, u32 inst2) {}
517
518static 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
522}
523
524static 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;
533 unsigned char icode;
534 unsigned char code;
535 int vscale;
536 unsigned short index;
537 unsigned short j;
538 int a[8];
539 short *book1,*book2;
540/*
541 if (Address > (1024*1024*8))
542 Address = (inst2 & 0xffffff);
543*/
544 memset(out,0,32);
545
546 if(!(Flags&0x1))
547 {
548 if(Flags&0x2) {
549 memcpy(out,&rsp.RDRAM[loopval&MEMMASK],32);
550 } else {
551 memcpy(out,&rsp.RDRAM[Address],32);
552 }
553 }
554
555 int l1=out[14^S];
556 int l2=out[15^S];
557 int inp1[8];
558 int inp2[8];
559 out+=16;
560 while(count>0)
561 {
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
566
567 code=BufferSpace[(AudioInBuffer+inPtr)^S8];
568 index=code&0xf;
569 index<<=4; // index into the adpcm code table
570 book1=(short *)&adpcmtable[index];
571 book2=book1+8;
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
579
580 inPtr++; // coded adpcm data lies next
581 j=0;
582 while(j<8) // loop of 8, for 8 coded nibbles from 4 bytes
583 // which yields 8 short pcm values
584 {
585 icode=BufferSpace[(AudioInBuffer+inPtr)^S8];
586 inPtr++;
587
588 inp1[j]=(s16)((icode&0xf0)<<8); // this will in effect be signed
589 if(code<12)
590 inp1[j]=((int)((int)inp1[j]*(int)vscale)>>16);
591 /*else
592 int catchme=1;*/
593 j++;
594
595 inp1[j]=(s16)((icode&0xf)<<12);
596 if(code<12)
597 inp1[j]=((int)((int)inp1[j]*(int)vscale)>>16);
598 /*else
599 int catchme=1;*/
600 j++;
601 }
602 j=0;
603 while(j<8)
604 {
605 icode=BufferSpace[(AudioInBuffer+inPtr)^S8];
606 inPtr++;
607
608 inp2[j]=(short)((icode&0xf0)<<8); // this will in effect be signed
609 if(code<12)
610 inp2[j]=((int)((int)inp2[j]*(int)vscale)>>16);
611 /*else
612 int catchme=1;*/
613 j++;
614
615 inp2[j]=(short)((icode&0xf)<<12);
616 if(code<12)
617 inp2[j]=((int)((int)inp2[j]*(int)vscale)>>16);
618 /*else
619 int catchme=1;*/
620 j++;
621 }
622
623 a[0]= (int)book1[0]*(int)l1;
624 a[0]+=(int)book2[0]*(int)l2;
625 a[0]+=(int)inp1[0]*(int)2048;
626
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;
631
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;
637
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;
644
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;
652
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;
661
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;
671
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;
682
683 for(j=0;j<8;j++)
684 {
685 a[j^S]>>=11;
686 if(a[j^S]>32767) a[j^S]=32767;
687 else if(a[j^S]<-32768) a[j^S]=-32768;
688 *(out++)=a[j^S];
689 }
690 l1=a[6];
691 l2=a[7];
692
693 a[0]= (int)book1[0]*(int)l1;
694 a[0]+=(int)book2[0]*(int)l2;
695 a[0]+=(int)inp2[0]*(int)2048;
696
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;
701
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;
707
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;
714
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;
722
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;
731
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;
741
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;
752
753 for(j=0;j<8;j++)
754 {
755 a[j^S]>>=11;
756 if(a[j^S]>32767) a[j^S]=32767;
757 else if(a[j^S]<-32768) a[j^S]=-32768;
758 *(out++)=a[j^S];
759 }
760 l1=a[6];
761 l2=a[7];
762
763 count-=32;
764 }
765 out-=16;
766 memcpy(&rsp.RDRAM[Address],out,32);
767}
768
769static void LOADBUFF (u32 inst1, u32 inst2) { // memcpy causes static... endianess issue :(
770 u32 v0;
771 //u32 cnt;
772 if (AudioCount == 0)
773 return;
774 v0 = (inst2 & 0xfffffc);// + SEGMENTS[(inst2>>24)&0xf];
775 memcpy (BufferSpace+(AudioInBuffer&0xFFFC), rsp.RDRAM+v0, (AudioCount+3)&0xFFFC);
776}
777
778static void SAVEBUFF (u32 inst1, u32 inst2) { // memcpy causes static... endianess issue :(
779 u32 v0;
780 //u32 cnt;
781 if (AudioCount == 0)
782 return;
783 v0 = (inst2 & 0xfffffc);// + SEGMENTS[(inst2>>24)&0xf];
784 memcpy (rsp.RDRAM+v0, BufferSpace+(AudioOutBuffer&0xFFFC), (AudioCount+3)&0xFFFC);
785}
786
787static 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
796 }
797}
798
799static void DMEMMOVE (u32 inst1, u32 inst2) { // Doesn't sound just right?... will fix when HLE is ready - 03-11-01
800 u32 v0, v1;
801 u32 cnt;
802 if ((inst2 & 0xffff)==0)
803 return;
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;
811
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));
815 }
816}
817
818static void LOADADPCM (u32 inst1, u32 inst2) { // Loads an ADPCM table - Works 100% Now 03-13-01
819 u32 v0;
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];
829
830 adpcmtable[(0x2+(x<<3))^S] = table[2];
831 adpcmtable[(0x3+(x<<3))^S] = table[3];
832
833 adpcmtable[(0x4+(x<<3))^S] = table[4];
834 adpcmtable[(0x5+(x<<3))^S] = table[5];
835
836 adpcmtable[(0x6+(x<<3))^S] = table[6];
837 adpcmtable[(0x7+(x<<3))^S] = table[7];
838 table += 8;
839 }
840}
841
842
843static void INTERLEAVE (u32 inst1, u32 inst2) { // Works... - 3-11-01
844 u32 inL, inR;
845 u16 *outbuff = (u16 *)(AudioOutBuffer+BufferSpace);
846 u16 *inSrcR;
847 u16 *inSrcL;
848 u16 Left, Right, Left2, Right2;
849
850 inL = inst2 & 0xFFFF;
851 inR = (inst2 >> 16) & 0xFFFF;
852
853 inSrcR = (u16 *)(BufferSpace+inR);
854 inSrcL = (u16 *)(BufferSpace+inL);
855
856 for (int x = 0; x < (AudioCount/4); x++) {
857 Left=*(inSrcL++);
858 Right=*(inSrcR++);
859 Left2=*(inSrcL++);
860 Right2=*(inSrcR++);
861
862#ifdef M64P_BIG_ENDIAN
863 *(outbuff++)=Right;
864 *(outbuff++)=Left;
865 *(outbuff++)=Right2;
866 *(outbuff++)=Left2;
867#else
868 *(outbuff++)=Right2;
869 *(outbuff++)=Left2;
870 *(outbuff++)=Right;
871 *(outbuff++)=Left;
872#endif
873 }
874}
875
876
877static 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);
882 s32 temp;
883
884 if (AudioCount == 0)
885 return;
886
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);
890
891 if ((s32)temp > 32767)
892 temp = 32767;
893 if ((s32)temp < -32768)
894 temp = -32768;
895
896 *(u16 *)(BufferSpace+dmemout+x) = (u16)(temp & 0xFFFF);
897 }
898}
899
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%
905
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%
910
911
912extern "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
915};
916
917/* BACKUPS
918void 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);
923 u64 temp;
924
925 if (AudioCount == 0)
926 return;
927
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);
930
931 if (temp & 0x8000)
932 temp = (temp^0x8000) + 0x10000;
933 else
934 temp = (temp^0x8000);
935
936 temp = (temp & 0xFFFFFFFFFFFF);
937
938 temp += ((*(s16 *)(BufferSpace+dmemin+x) * (s64)((s16)gain*2))) & 0xFFFFFFFFFFFF;
939
940 temp = (s32)(temp >> 16);
941 if ((s32)temp > 32767)
942 temp = 32767;
943 if ((s32)temp < -32768)
944 temp = -32768;
945
946 *(u16 *)(BufferSpace+dmemout+x) = (u16)(temp & 0xFFFF);
947 }
948}
949*/
950
951