d9e74a6f |
1 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
2 | * Mupen64plus-rsp-hle - ucode2.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 | # include <stdio.h> |
25 | |
26 | extern "C" { |
27 | #include "m64p_types.h" |
28 | #include "hle.h" |
29 | #include "alist_internal.h" |
30 | } |
31 | |
32 | extern u8 BufferSpace[0x10000]; |
33 | |
34 | static void SPNOOP (u32 inst1, u32 inst2) { |
35 | DebugMessage(M64MSG_ERROR, "Unknown/Unimplemented Audio Command %i in ABI 2", (int)(inst1 >> 24)); |
36 | } |
37 | extern u16 AudioInBuffer; // 0x0000(T8) |
38 | extern u16 AudioOutBuffer; // 0x0002(T8) |
39 | extern u16 AudioCount; // 0x0004(T8) |
40 | extern u32 loopval; // 0x0010(T8) |
41 | extern u32 SEGMENTS[0x10]; |
42 | |
43 | extern u16 adpcmtable[0x88]; |
44 | |
45 | extern const u16 ResampleLUT [0x200]; |
46 | |
47 | bool isMKABI = false; |
48 | bool isZeldaABI = false; |
49 | |
50 | extern "C" void init_ucode2() { isMKABI = isZeldaABI = false; } |
51 | |
52 | static void LOADADPCM2 (u32 inst1, u32 inst2) { // Loads an ADPCM table - Works 100% Now 03-13-01 |
53 | u32 v0; |
54 | v0 = (inst2 & 0xffffff);// + SEGMENTS[(inst2>>24)&0xf]; |
55 | u16 *table = (u16 *)(rsp.RDRAM+v0); // Zelda2 Specific... |
56 | |
57 | for (u32 x = 0; x < ((inst1&0xffff)>>0x4); x++) { |
58 | adpcmtable[(0x0+(x<<3))^S] = table[0]; |
59 | adpcmtable[(0x1+(x<<3))^S] = table[1]; |
60 | |
61 | adpcmtable[(0x2+(x<<3))^S] = table[2]; |
62 | adpcmtable[(0x3+(x<<3))^S] = table[3]; |
63 | |
64 | adpcmtable[(0x4+(x<<3))^S] = table[4]; |
65 | adpcmtable[(0x5+(x<<3))^S] = table[5]; |
66 | |
67 | adpcmtable[(0x6+(x<<3))^S] = table[6]; |
68 | adpcmtable[(0x7+(x<<3))^S] = table[7]; |
69 | table += 8; |
70 | } |
71 | } |
72 | |
73 | static void SETLOOP2 (u32 inst1, u32 inst2) { |
74 | loopval = inst2 & 0xffffff; // No segment? |
75 | } |
76 | |
77 | static void SETBUFF2 (u32 inst1, u32 inst2) { |
78 | AudioInBuffer = u16(inst1); // 0x00 |
79 | AudioOutBuffer = u16((inst2 >> 0x10)); // 0x02 |
80 | AudioCount = u16(inst2); // 0x04 |
81 | } |
82 | |
83 | static void ADPCM2 (u32 inst1, u32 inst2) { // Verified to be 100% Accurate... |
84 | unsigned char Flags=(u8)(inst1>>16)&0xff; |
85 | //unsigned short Gain=(u16)(inst1&0xffff); |
86 | unsigned int Address=(inst2 & 0xffffff);// + SEGMENTS[(inst2>>24)&0xf]; |
87 | unsigned short inPtr=0; |
88 | //short *out=(s16 *)(testbuff+(AudioOutBuffer>>2)); |
89 | short *out=(short *)(BufferSpace+AudioOutBuffer); |
90 | //unsigned char *in=(unsigned char *)(BufferSpace+AudioInBuffer); |
91 | short count=(short)AudioCount; |
92 | unsigned char icode; |
93 | unsigned char code; |
94 | int vscale; |
95 | unsigned short index; |
96 | unsigned short j; |
97 | int a[8]; |
98 | short *book1,*book2; |
99 | |
100 | u8 srange; |
101 | u8 mask1; |
102 | u8 mask2; |
103 | u8 shifter; |
104 | |
105 | memset(out,0,32); |
106 | |
107 | if (Flags & 0x4) { // Tricky lil Zelda MM and ABI2!!! hahaha I know your secrets! :DDD |
108 | srange = 0xE; |
109 | mask1 = 0xC0; |
110 | mask2 = 0x30; |
111 | shifter = 10; |
112 | } else { |
113 | srange = 0xC; |
114 | mask1 = 0xf0; |
115 | mask2 = 0x0f; |
116 | shifter = 12; |
117 | } |
118 | |
119 | if(!(Flags&0x1)) |
120 | { |
121 | if(Flags&0x2) |
122 | {/* |
123 | for(int i=0;i<16;i++) |
124 | { |
125 | out[i]=*(short *)&rsp.RDRAM[(loopval+i*2)^2]; |
126 | }*/ |
127 | memcpy(out,&rsp.RDRAM[loopval],32); |
128 | } |
129 | else |
130 | {/* |
131 | for(int i=0;i<16;i++) |
132 | { |
133 | out[i]=*(short *)&rsp.RDRAM[(Address+i*2)^2]; |
134 | }*/ |
135 | memcpy(out,&rsp.RDRAM[Address],32); |
136 | } |
137 | } |
138 | |
139 | int l1=out[14^S]; |
140 | int l2=out[15^S]; |
141 | int inp1[8]; |
142 | int inp2[8]; |
143 | out+=16; |
144 | while(count>0) { |
145 | code=BufferSpace[(AudioInBuffer+inPtr)^S8]; |
146 | index=code&0xf; |
147 | index<<=4; |
148 | book1=(short *)&adpcmtable[index]; |
149 | book2=book1+8; |
150 | code>>=4; |
151 | vscale=(0x8000>>((srange-code)-1)); |
152 | |
153 | inPtr++; |
154 | j=0; |
155 | |
156 | while(j<8) { |
157 | icode=BufferSpace[(AudioInBuffer+inPtr)^S8]; |
158 | inPtr++; |
159 | |
160 | inp1[j]=(s16)((icode&mask1) << 8); // this will in effect be signed |
161 | if(code<srange) inp1[j]=((int)((int)inp1[j]*(int)vscale)>>16); |
162 | //else int catchme=1; |
163 | j++; |
164 | |
165 | inp1[j]=(s16)((icode&mask2)<<shifter); |
166 | if(code<srange) inp1[j]=((int)((int)inp1[j]*(int)vscale)>>16); |
167 | //else int catchme=1; |
168 | j++; |
169 | |
170 | if (Flags & 4) { |
171 | inp1[j]=(s16)((icode&0xC) << 12); // this will in effect be signed |
172 | if(code < 0xE) inp1[j]=((int)((int)inp1[j]*(int)vscale)>>16); |
173 | //else int catchme=1; |
174 | j++; |
175 | |
176 | inp1[j]=(s16)((icode&0x3) << 14); |
177 | if(code < 0xE) inp1[j]=((int)((int)inp1[j]*(int)vscale)>>16); |
178 | //else int catchme=1; |
179 | j++; |
180 | } // end flags |
181 | } // end while |
182 | |
183 | |
184 | |
185 | j=0; |
186 | while(j<8) { |
187 | icode=BufferSpace[(AudioInBuffer+inPtr)^S8]; |
188 | inPtr++; |
189 | |
190 | inp2[j]=(s16)((icode&mask1) << 8); |
191 | if(code<srange) inp2[j]=((int)((int)inp2[j]*(int)vscale)>>16); |
192 | //else int catchme=1; |
193 | j++; |
194 | |
195 | inp2[j]=(s16)((icode&mask2)<<shifter); |
196 | if(code<srange) inp2[j]=((int)((int)inp2[j]*(int)vscale)>>16); |
197 | //else int catchme=1; |
198 | j++; |
199 | |
200 | if (Flags & 4) { |
201 | inp2[j]=(s16)((icode&0xC) << 12); |
202 | if(code < 0xE) inp2[j]=((int)((int)inp2[j]*(int)vscale)>>16); |
203 | //else int catchme=1; |
204 | j++; |
205 | |
206 | inp2[j]=(s16)((icode&0x3) << 14); |
207 | if(code < 0xE) inp2[j]=((int)((int)inp2[j]*(int)vscale)>>16); |
208 | //else int catchme=1; |
209 | j++; |
210 | } // end flags |
211 | } |
212 | |
213 | a[0]= (int)book1[0]*(int)l1; |
214 | a[0]+=(int)book2[0]*(int)l2; |
215 | a[0]+=(int)inp1[0]*(int)2048; |
216 | |
217 | a[1] =(int)book1[1]*(int)l1; |
218 | a[1]+=(int)book2[1]*(int)l2; |
219 | a[1]+=(int)book2[0]*inp1[0]; |
220 | a[1]+=(int)inp1[1]*(int)2048; |
221 | |
222 | a[2] =(int)book1[2]*(int)l1; |
223 | a[2]+=(int)book2[2]*(int)l2; |
224 | a[2]+=(int)book2[1]*inp1[0]; |
225 | a[2]+=(int)book2[0]*inp1[1]; |
226 | a[2]+=(int)inp1[2]*(int)2048; |
227 | |
228 | a[3] =(int)book1[3]*(int)l1; |
229 | a[3]+=(int)book2[3]*(int)l2; |
230 | a[3]+=(int)book2[2]*inp1[0]; |
231 | a[3]+=(int)book2[1]*inp1[1]; |
232 | a[3]+=(int)book2[0]*inp1[2]; |
233 | a[3]+=(int)inp1[3]*(int)2048; |
234 | |
235 | a[4] =(int)book1[4]*(int)l1; |
236 | a[4]+=(int)book2[4]*(int)l2; |
237 | a[4]+=(int)book2[3]*inp1[0]; |
238 | a[4]+=(int)book2[2]*inp1[1]; |
239 | a[4]+=(int)book2[1]*inp1[2]; |
240 | a[4]+=(int)book2[0]*inp1[3]; |
241 | a[4]+=(int)inp1[4]*(int)2048; |
242 | |
243 | a[5] =(int)book1[5]*(int)l1; |
244 | a[5]+=(int)book2[5]*(int)l2; |
245 | a[5]+=(int)book2[4]*inp1[0]; |
246 | a[5]+=(int)book2[3]*inp1[1]; |
247 | a[5]+=(int)book2[2]*inp1[2]; |
248 | a[5]+=(int)book2[1]*inp1[3]; |
249 | a[5]+=(int)book2[0]*inp1[4]; |
250 | a[5]+=(int)inp1[5]*(int)2048; |
251 | |
252 | a[6] =(int)book1[6]*(int)l1; |
253 | a[6]+=(int)book2[6]*(int)l2; |
254 | a[6]+=(int)book2[5]*inp1[0]; |
255 | a[6]+=(int)book2[4]*inp1[1]; |
256 | a[6]+=(int)book2[3]*inp1[2]; |
257 | a[6]+=(int)book2[2]*inp1[3]; |
258 | a[6]+=(int)book2[1]*inp1[4]; |
259 | a[6]+=(int)book2[0]*inp1[5]; |
260 | a[6]+=(int)inp1[6]*(int)2048; |
261 | |
262 | a[7] =(int)book1[7]*(int)l1; |
263 | a[7]+=(int)book2[7]*(int)l2; |
264 | a[7]+=(int)book2[6]*inp1[0]; |
265 | a[7]+=(int)book2[5]*inp1[1]; |
266 | a[7]+=(int)book2[4]*inp1[2]; |
267 | a[7]+=(int)book2[3]*inp1[3]; |
268 | a[7]+=(int)book2[2]*inp1[4]; |
269 | a[7]+=(int)book2[1]*inp1[5]; |
270 | a[7]+=(int)book2[0]*inp1[6]; |
271 | a[7]+=(int)inp1[7]*(int)2048; |
272 | |
273 | for(j=0;j<8;j++) |
274 | { |
275 | a[j^S]>>=11; |
276 | if(a[j^S]>32767) a[j^S]=32767; |
277 | else if(a[j^S]<-32768) a[j^S]=-32768; |
278 | *(out++)=a[j^S]; |
279 | } |
280 | l1=a[6]; |
281 | l2=a[7]; |
282 | |
283 | a[0]= (int)book1[0]*(int)l1; |
284 | a[0]+=(int)book2[0]*(int)l2; |
285 | a[0]+=(int)inp2[0]*(int)2048; |
286 | |
287 | a[1] =(int)book1[1]*(int)l1; |
288 | a[1]+=(int)book2[1]*(int)l2; |
289 | a[1]+=(int)book2[0]*inp2[0]; |
290 | a[1]+=(int)inp2[1]*(int)2048; |
291 | |
292 | a[2] =(int)book1[2]*(int)l1; |
293 | a[2]+=(int)book2[2]*(int)l2; |
294 | a[2]+=(int)book2[1]*inp2[0]; |
295 | a[2]+=(int)book2[0]*inp2[1]; |
296 | a[2]+=(int)inp2[2]*(int)2048; |
297 | |
298 | a[3] =(int)book1[3]*(int)l1; |
299 | a[3]+=(int)book2[3]*(int)l2; |
300 | a[3]+=(int)book2[2]*inp2[0]; |
301 | a[3]+=(int)book2[1]*inp2[1]; |
302 | a[3]+=(int)book2[0]*inp2[2]; |
303 | a[3]+=(int)inp2[3]*(int)2048; |
304 | |
305 | a[4] =(int)book1[4]*(int)l1; |
306 | a[4]+=(int)book2[4]*(int)l2; |
307 | a[4]+=(int)book2[3]*inp2[0]; |
308 | a[4]+=(int)book2[2]*inp2[1]; |
309 | a[4]+=(int)book2[1]*inp2[2]; |
310 | a[4]+=(int)book2[0]*inp2[3]; |
311 | a[4]+=(int)inp2[4]*(int)2048; |
312 | |
313 | a[5] =(int)book1[5]*(int)l1; |
314 | a[5]+=(int)book2[5]*(int)l2; |
315 | a[5]+=(int)book2[4]*inp2[0]; |
316 | a[5]+=(int)book2[3]*inp2[1]; |
317 | a[5]+=(int)book2[2]*inp2[2]; |
318 | a[5]+=(int)book2[1]*inp2[3]; |
319 | a[5]+=(int)book2[0]*inp2[4]; |
320 | a[5]+=(int)inp2[5]*(int)2048; |
321 | |
322 | a[6] =(int)book1[6]*(int)l1; |
323 | a[6]+=(int)book2[6]*(int)l2; |
324 | a[6]+=(int)book2[5]*inp2[0]; |
325 | a[6]+=(int)book2[4]*inp2[1]; |
326 | a[6]+=(int)book2[3]*inp2[2]; |
327 | a[6]+=(int)book2[2]*inp2[3]; |
328 | a[6]+=(int)book2[1]*inp2[4]; |
329 | a[6]+=(int)book2[0]*inp2[5]; |
330 | a[6]+=(int)inp2[6]*(int)2048; |
331 | |
332 | a[7] =(int)book1[7]*(int)l1; |
333 | a[7]+=(int)book2[7]*(int)l2; |
334 | a[7]+=(int)book2[6]*inp2[0]; |
335 | a[7]+=(int)book2[5]*inp2[1]; |
336 | a[7]+=(int)book2[4]*inp2[2]; |
337 | a[7]+=(int)book2[3]*inp2[3]; |
338 | a[7]+=(int)book2[2]*inp2[4]; |
339 | a[7]+=(int)book2[1]*inp2[5]; |
340 | a[7]+=(int)book2[0]*inp2[6]; |
341 | a[7]+=(int)inp2[7]*(int)2048; |
342 | |
343 | for(j=0;j<8;j++) |
344 | { |
345 | a[j^S]>>=11; |
346 | if(a[j^S]>32767) a[j^S]=32767; |
347 | else if(a[j^S]<-32768) a[j^S]=-32768; |
348 | *(out++)=a[j^S]; |
349 | } |
350 | l1=a[6]; |
351 | l2=a[7]; |
352 | |
353 | count-=32; |
354 | } |
355 | out-=16; |
356 | memcpy(&rsp.RDRAM[Address],out,32); |
357 | } |
358 | |
359 | static void CLEARBUFF2 (u32 inst1, u32 inst2) { |
360 | u16 addr = (u16)(inst1 & 0xffff); |
361 | u16 count = (u16)(inst2 & 0xffff); |
362 | if (count > 0) |
363 | memset(BufferSpace+addr, 0, count); |
364 | } |
365 | |
366 | static void LOADBUFF2 (u32 inst1, u32 inst2) { // Needs accuracy verification... |
367 | u32 v0; |
368 | u32 cnt = (((inst1 >> 0xC)+3)&0xFFC); |
369 | v0 = (inst2 & 0xfffffc);// + SEGMENTS[(inst2>>24)&0xf]; |
370 | memcpy (BufferSpace+(inst1&0xfffc), rsp.RDRAM+v0, (cnt+3)&0xFFFC); |
371 | } |
372 | |
373 | static void SAVEBUFF2 (u32 inst1, u32 inst2) { // Needs accuracy verification... |
374 | u32 v0; |
375 | u32 cnt = (((inst1 >> 0xC)+3)&0xFFC); |
376 | v0 = (inst2 & 0xfffffc);// + SEGMENTS[(inst2>>24)&0xf]; |
377 | memcpy (rsp.RDRAM+v0, BufferSpace+(inst1&0xfffc), (cnt+3)&0xFFFC); |
378 | } |
379 | |
380 | |
381 | static void MIXER2 (u32 inst1, u32 inst2) { // Needs accuracy verification... |
382 | u16 dmemin = (u16)(inst2 >> 0x10); |
383 | u16 dmemout = (u16)(inst2 & 0xFFFF); |
384 | u32 count = ((inst1 >> 12) & 0xFF0); |
385 | s32 gain = (s16)(inst1 & 0xFFFF); |
386 | s32 temp; |
387 | |
388 | for (unsigned int x=0; x < count; x+=2) { // I think I can do this a lot easier |
389 | |
390 | temp = (*(s16 *)(BufferSpace+dmemin+x) * gain) >> 15; |
391 | temp += *(s16 *)(BufferSpace+dmemout+x); |
392 | |
393 | if ((s32)temp > 32767) |
394 | temp = 32767; |
395 | if ((s32)temp < -32768) |
396 | temp = -32768; |
397 | |
398 | *(u16 *)(BufferSpace+dmemout+x) = (u16)(temp & 0xFFFF); |
399 | } |
400 | } |
401 | |
402 | |
403 | static void RESAMPLE2 (u32 inst1, u32 inst2) { |
404 | unsigned char Flags=(u8)((inst1>>16)&0xff); |
405 | unsigned int Pitch=((inst1&0xffff))<<1; |
406 | u32 addy = (inst2 & 0xffffff);// + SEGMENTS[(inst2>>24)&0xf]; |
407 | unsigned int Accum=0; |
408 | unsigned int location; |
409 | s16 *lut; |
410 | short *dst; |
411 | s16 *src; |
412 | dst=(short *)(BufferSpace); |
413 | src=(s16 *)(BufferSpace); |
414 | u32 srcPtr=(AudioInBuffer/2); |
415 | u32 dstPtr=(AudioOutBuffer/2); |
416 | s32 temp; |
417 | s32 accum; |
418 | |
419 | if (addy > (1024*1024*8)) |
420 | addy = (inst2 & 0xffffff); |
421 | |
422 | srcPtr -= 4; |
423 | |
424 | if ((Flags & 0x1) == 0) { |
425 | for (int x=0; x < 4; x++) //memcpy (src+srcPtr, rsp.RDRAM+addy, 0x8); |
426 | src[(srcPtr+x)^S] = ((u16 *)rsp.RDRAM)[((addy/2)+x)^S]; |
427 | Accum = *(u16 *)(rsp.RDRAM+addy+10); |
428 | } else { |
429 | for (int x=0; x < 4; x++) |
430 | src[(srcPtr+x)^S] = 0;//*(u16 *)(rsp.RDRAM+((addy+x)^2)); |
431 | } |
432 | |
433 | for(int i=0;i < ((AudioCount+0xf)&0xFFF0)/2;i++) { |
434 | location = (((Accum * 0x40) >> 0x10) * 8); |
435 | //location = (Accum >> 0xa) << 0x3; |
436 | lut = (s16 *)(((u8 *)ResampleLUT) + location); |
437 | |
438 | temp = ((s32)*(s16*)(src+((srcPtr+0)^S))*((s32)((s16)lut[0]))); |
439 | accum = (s32)(temp >> 15); |
440 | |
441 | temp = ((s32)*(s16*)(src+((srcPtr+1)^S))*((s32)((s16)lut[1]))); |
442 | accum += (s32)(temp >> 15); |
443 | |
444 | temp = ((s32)*(s16*)(src+((srcPtr+2)^S))*((s32)((s16)lut[2]))); |
445 | accum += (s32)(temp >> 15); |
446 | |
447 | temp = ((s32)*(s16*)(src+((srcPtr+3)^S))*((s32)((s16)lut[3]))); |
448 | accum += (s32)(temp >> 15); |
449 | |
450 | if (accum > 32767) accum = 32767; |
451 | if (accum < -32768) accum = -32768; |
452 | |
453 | dst[dstPtr^S] = (s16)(accum); |
454 | dstPtr++; |
455 | Accum += Pitch; |
456 | srcPtr += (Accum>>16); |
457 | Accum&=0xffff; |
458 | } |
459 | for (int x=0; x < 4; x++) |
460 | ((u16 *)rsp.RDRAM)[((addy/2)+x)^S] = src[(srcPtr+x)^S]; |
461 | *(u16 *)(rsp.RDRAM+addy+10) = (u16)Accum; |
462 | //memcpy (RSWORK, src+srcPtr, 0x8); |
463 | } |
464 | |
465 | static void DMEMMOVE2 (u32 inst1, u32 inst2) { // Needs accuracy verification... |
466 | u32 v0, v1; |
467 | u32 cnt; |
468 | if ((inst2 & 0xffff)==0) |
469 | return; |
470 | v0 = (inst1 & 0xFFFF); |
471 | v1 = (inst2 >> 0x10); |
472 | //assert ((v1 & 0x3) == 0); |
473 | //assert ((v0 & 0x3) == 0); |
474 | u32 count = ((inst2+3) & 0xfffc); |
475 | //v0 = (v0) & 0xfffc; |
476 | //v1 = (v1) & 0xfffc; |
477 | |
478 | //memcpy (dmem+v1, dmem+v0, count-1); |
479 | for (cnt = 0; cnt < count; cnt++) { |
480 | *(u8 *)(BufferSpace+((cnt+v1)^S8)) = *(u8 *)(BufferSpace+((cnt+v0)^S8)); |
481 | } |
482 | } |
483 | |
484 | static u32 t3, s5, s6; |
485 | static u16 env[8]; |
486 | |
487 | static void ENVSETUP1 (u32 inst1, u32 inst2) { |
488 | u32 tmp; |
489 | |
490 | //fprintf (dfile, "ENVSETUP1: inst1 = %08X, inst2 = %08X\n", inst1, inst2); |
491 | t3 = inst1 & 0xFFFF; |
492 | tmp = (inst1 >> 0x8) & 0xFF00; |
493 | env[4] = (u16)tmp; |
494 | tmp += t3; |
495 | env[5] = (u16)tmp; |
496 | s5 = inst2 >> 0x10; |
497 | s6 = inst2 & 0xFFFF; |
498 | //fprintf (dfile, " t3 = %X / s5 = %X / s6 = %X / env[4] = %X / env[5] = %X\n", t3, s5, s6, env[4], env[5]); |
499 | } |
500 | |
501 | static void ENVSETUP2 (u32 inst1, u32 inst2) { |
502 | u32 tmp; |
503 | |
504 | //fprintf (dfile, "ENVSETUP2: inst1 = %08X, inst2 = %08X\n", inst1, inst2); |
505 | tmp = (inst2 >> 0x10); |
506 | env[0] = (u16)tmp; |
507 | tmp += s5; |
508 | env[1] = (u16)tmp; |
509 | tmp = inst2 & 0xffff; |
510 | env[2] = (u16)tmp; |
511 | tmp += s6; |
512 | env[3] = (u16)tmp; |
513 | //fprintf (dfile, " env[0] = %X / env[1] = %X / env[2] = %X / env[3] = %X\n", env[0], env[1], env[2], env[3]); |
514 | } |
515 | |
516 | static void ENVMIXER2 (u32 inst1, u32 inst2) { |
517 | //fprintf (dfile, "ENVMIXER: inst1 = %08X, inst2 = %08X\n", inst1, inst2); |
518 | |
519 | s16 *bufft6, *bufft7, *buffs0, *buffs1; |
520 | s16 *buffs3; |
521 | s32 count; |
522 | u32 adder; |
523 | |
524 | s16 vec9, vec10; |
525 | |
526 | s16 v2[8]; |
527 | |
528 | buffs3 = (s16 *)(BufferSpace + ((inst1 >> 0x0c)&0x0ff0)); |
529 | bufft6 = (s16 *)(BufferSpace + ((inst2 >> 0x14)&0x0ff0)); |
530 | bufft7 = (s16 *)(BufferSpace + ((inst2 >> 0x0c)&0x0ff0)); |
531 | buffs0 = (s16 *)(BufferSpace + ((inst2 >> 0x04)&0x0ff0)); |
532 | buffs1 = (s16 *)(BufferSpace + ((inst2 << 0x04)&0x0ff0)); |
533 | |
534 | |
535 | v2[0] = 0 - (s16)((inst1 & 0x2) >> 1); |
536 | v2[1] = 0 - (s16)((inst1 & 0x1)); |
537 | v2[2] = 0 - (s16)((inst1 & 0x8) >> 1); |
538 | v2[3] = 0 - (s16)((inst1 & 0x4) >> 1); |
539 | |
540 | count = (inst1 >> 8) & 0xff; |
541 | |
542 | if (!isMKABI) { |
543 | s5 *= 2; s6 *= 2; t3 *= 2; |
544 | adder = 0x10; |
545 | } else { |
546 | inst1 = 0; |
547 | adder = 0x8; |
548 | t3 = 0; |
549 | } |
550 | |
551 | |
552 | while (count > 0) { |
553 | int temp, x; |
554 | for (x=0; x < 0x8; x++) { |
555 | vec9 = (s16)(((s32)buffs3[x^S] * (u32)env[0]) >> 0x10) ^ v2[0]; |
556 | vec10 = (s16)(((s32)buffs3[x^S] * (u32)env[2]) >> 0x10) ^ v2[1]; |
557 | temp = bufft6[x^S] + vec9; |
558 | if (temp > 32767) temp = 32767; if (temp < -32768) temp = -32768; |
559 | bufft6[x^S] = temp; |
560 | temp = bufft7[x^S] + vec10; |
561 | if (temp > 32767) temp = 32767; if (temp < -32768) temp = -32768; |
562 | bufft7[x^S] = temp; |
563 | vec9 = (s16)(((s32)vec9 * (u32)env[4]) >> 0x10) ^ v2[2]; |
564 | vec10 = (s16)(((s32)vec10 * (u32)env[4]) >> 0x10) ^ v2[3]; |
565 | if (inst1 & 0x10) { |
566 | temp = buffs0[x^S] + vec10; |
567 | if (temp > 32767) temp = 32767; if (temp < -32768) temp = -32768; |
568 | buffs0[x^S] = temp; |
569 | temp = buffs1[x^S] + vec9; |
570 | if (temp > 32767) temp = 32767; if (temp < -32768) temp = -32768; |
571 | buffs1[x^S] = temp; |
572 | } else { |
573 | temp = buffs0[x^S] + vec9; |
574 | if (temp > 32767) temp = 32767; if (temp < -32768) temp = -32768; |
575 | buffs0[x^S] = temp; |
576 | temp = buffs1[x^S] + vec10; |
577 | if (temp > 32767) temp = 32767; if (temp < -32768) temp = -32768; |
578 | buffs1[x^S] = temp; |
579 | } |
580 | } |
581 | |
582 | if (!isMKABI) |
583 | for (x=0x8; x < 0x10; x++) { |
584 | vec9 = (s16)(((s32)buffs3[x^S] * (u32)env[1]) >> 0x10) ^ v2[0]; |
585 | vec10 = (s16)(((s32)buffs3[x^S] * (u32)env[3]) >> 0x10) ^ v2[1]; |
586 | temp = bufft6[x^S] + vec9; |
587 | if (temp > 32767) temp = 32767; if (temp < -32768) temp = -32768; |
588 | bufft6[x^S] = temp; |
589 | temp = bufft7[x^S] + vec10; |
590 | if (temp > 32767) temp = 32767; if (temp < -32768) temp = -32768; |
591 | bufft7[x^S] = temp; |
592 | vec9 = (s16)(((s32)vec9 * (u32)env[5]) >> 0x10) ^ v2[2]; |
593 | vec10 = (s16)(((s32)vec10 * (u32)env[5]) >> 0x10) ^ v2[3]; |
594 | if (inst1 & 0x10) { |
595 | temp = buffs0[x^S] + vec10; |
596 | if (temp > 32767) temp = 32767; if (temp < -32768) temp = -32768; |
597 | buffs0[x^S] = temp; |
598 | temp = buffs1[x^S] + vec9; |
599 | if (temp > 32767) temp = 32767; if (temp < -32768) temp = -32768; |
600 | buffs1[x^S] = temp; |
601 | } else { |
602 | temp = buffs0[x^S] + vec9; |
603 | if (temp > 32767) temp = 32767; if (temp < -32768) temp = -32768; |
604 | buffs0[x^S] = temp; |
605 | temp = buffs1[x^S] + vec10; |
606 | if (temp > 32767) temp = 32767; if (temp < -32768) temp = -32768; |
607 | buffs1[x^S] = temp; |
608 | } |
609 | } |
610 | bufft6 += adder; bufft7 += adder; |
611 | buffs0 += adder; buffs1 += adder; |
612 | buffs3 += adder; count -= adder; |
613 | env[0] += (u16)s5; env[1] += (u16)s5; |
614 | env[2] += (u16)s6; env[3] += (u16)s6; |
615 | env[4] += (u16)t3; env[5] += (u16)t3; |
616 | } |
617 | } |
618 | |
619 | static void DUPLICATE2(u32 inst1, u32 inst2) { |
620 | unsigned short Count = (inst1 >> 16) & 0xff; |
621 | unsigned short In = inst1&0xffff; |
622 | unsigned short Out = (inst2>>16); |
623 | |
624 | unsigned short buff[64]; |
625 | |
626 | memcpy(buff,BufferSpace+In,128); |
627 | |
628 | while(Count) { |
629 | memcpy(BufferSpace+Out,buff,128); |
630 | Out+=128; |
631 | Count--; |
632 | } |
633 | } |
634 | /* |
635 | static void INTERL2 (u32 inst1, u32 inst2) { // Make your own... |
636 | short Count = inst1 & 0xffff; |
637 | unsigned short Out = inst2 & 0xffff; |
638 | unsigned short In = (inst2 >> 16); |
639 | |
640 | short *src,*dst,tmp; |
641 | src=(short *)&BufferSpace[In]; |
642 | dst=(short *)&BufferSpace[Out]; |
643 | while(Count) |
644 | { |
645 | *(dst++)=*(src++); |
646 | src++; |
647 | *(dst++)=*(src++); |
648 | src++; |
649 | *(dst++)=*(src++); |
650 | src++; |
651 | *(dst++)=*(src++); |
652 | src++; |
653 | *(dst++)=*(src++); |
654 | src++; |
655 | *(dst++)=*(src++); |
656 | src++; |
657 | *(dst++)=*(src++); |
658 | src++; |
659 | *(dst++)=*(src++); |
660 | src++; |
661 | Count-=8; |
662 | } |
663 | } |
664 | */ |
665 | |
666 | static void INTERL2 (u32 inst1, u32 inst2) { |
667 | short Count = inst1 & 0xffff; |
668 | unsigned short Out = inst2 & 0xffff; |
669 | unsigned short In = (inst2 >> 16); |
670 | |
671 | unsigned char *src,*dst/*,tmp*/; |
672 | src=(unsigned char *)(BufferSpace);//[In]; |
673 | dst=(unsigned char *)(BufferSpace);//[Out]; |
674 | while(Count) { |
675 | *(short *)(dst+(Out^S8)) = *(short *)(src+(In^S8)); |
676 | Out += 2; |
677 | In += 4; |
678 | Count--; |
679 | } |
680 | } |
681 | |
682 | static void INTERLEAVE2 (u32 inst1, u32 inst2) { // Needs accuracy verification... |
683 | u32 inL, inR; |
684 | u16 *outbuff; |
685 | u16 *inSrcR; |
686 | u16 *inSrcL; |
687 | u16 Left, Right, Left2, Right2; |
688 | u32 count; |
689 | count = ((inst1 >> 12) & 0xFF0); |
690 | if (count == 0) { |
691 | outbuff = (u16 *)(AudioOutBuffer+BufferSpace); |
692 | count = AudioCount; |
693 | } else { |
694 | outbuff = (u16 *)((inst1&0xFFFF)+BufferSpace); |
695 | } |
696 | |
697 | inR = inst2 & 0xFFFF; |
698 | inL = (inst2 >> 16) & 0xFFFF; |
699 | |
700 | inSrcR = (u16 *)(BufferSpace+inR); |
701 | inSrcL = (u16 *)(BufferSpace+inL); |
702 | |
703 | for (u32 x = 0; x < (count/4); x++) { |
704 | Left=*(inSrcL++); |
705 | Right=*(inSrcR++); |
706 | Left2=*(inSrcL++); |
707 | Right2=*(inSrcR++); |
708 | |
709 | #ifdef M64P_BIG_ENDIAN |
710 | *(outbuff++)=Right; |
711 | *(outbuff++)=Left; |
712 | *(outbuff++)=Right2; |
713 | *(outbuff++)=Left2; |
714 | #else |
715 | *(outbuff++)=Right2; |
716 | *(outbuff++)=Left2; |
717 | *(outbuff++)=Right; |
718 | *(outbuff++)=Left; |
719 | #endif |
720 | } |
721 | } |
722 | |
723 | static void ADDMIXER (u32 inst1, u32 inst2) { |
724 | short Count = (inst1 >> 12) & 0x00ff0; |
725 | u16 InBuffer = (inst2 >> 16); |
726 | u16 OutBuffer = inst2 & 0xffff; |
727 | |
728 | s16 *inp, *outp; |
729 | s32 temp; |
730 | inp = (s16 *)(BufferSpace + InBuffer); |
731 | outp = (s16 *)(BufferSpace + OutBuffer); |
732 | for (int cntr = 0; cntr < Count; cntr+=2) { |
733 | temp = *outp + *inp; |
734 | if (temp > 32767) temp = 32767; if (temp < -32768) temp = -32768; |
735 | *(outp++) = temp; |
736 | inp++; |
737 | } |
738 | } |
739 | |
740 | static void HILOGAIN (u32 inst1, u32 inst2) { |
741 | u16 cnt = inst1 & 0xffff; |
742 | u16 out = (inst2 >> 16) & 0xffff; |
743 | s16 hi = (s16)((inst1 >> 4) & 0xf000); |
744 | u16 lo = (inst1 >> 20) & 0xf; |
745 | s16 *src; |
746 | |
747 | src = (s16 *)(BufferSpace+out); |
748 | s32 tmp, val; |
749 | |
750 | while(cnt) { |
751 | val = (s32)*src; |
752 | //tmp = ((val * (s32)hi) + ((u64)(val * lo) << 16) >> 16); |
753 | tmp = ((val * (s32)hi) >> 16) + (u32)(val * lo); |
754 | if ((s32)tmp > 32767) tmp = 32767; |
755 | else if ((s32)tmp < -32768) tmp = -32768; |
756 | *src = tmp; |
757 | src++; |
758 | cnt -= 2; |
759 | } |
760 | } |
761 | |
762 | static void FILTER2 (u32 inst1, u32 inst2) { |
763 | static int cnt = 0; |
764 | static s16 *lutt6; |
765 | static s16 *lutt5; |
766 | u8 *save = (rsp.RDRAM+(inst2&0xFFFFFF)); |
767 | u8 t4 = (u8)((inst1 >> 0x10) & 0xFF); |
768 | int x; |
769 | |
770 | if (t4 > 1) { // Then set the cnt variable |
771 | cnt = (inst1 & 0xFFFF); |
772 | lutt6 = (s16 *)save; |
773 | // memcpy (dmem+0xFE0, rsp.RDRAM+(inst2&0xFFFFFF), 0x10); |
774 | return; |
775 | } |
776 | |
777 | if (t4 == 0) { |
778 | // memcpy (dmem+0xFB0, rsp.RDRAM+(inst2&0xFFFFFF), 0x20); |
779 | lutt5 = (short *)(save+0x10); |
780 | } |
781 | |
782 | lutt5 = (short *)(save+0x10); |
783 | |
784 | // lutt5 = (short *)(dmem + 0xFC0); |
785 | // lutt6 = (short *)(dmem + 0xFE0); |
786 | for (x = 0; x < 8; x++) { |
787 | s32 a; |
788 | a = (lutt5[x] + lutt6[x]) >> 1; |
789 | lutt5[x] = lutt6[x] = (short)a; |
790 | } |
791 | short *inp1, *inp2; |
792 | s32 out1[8]; |
793 | s16 outbuff[0x3c0], *outp; |
794 | u32 inPtr = (u32)(inst1&0xffff); |
795 | inp1 = (short *)(save); |
796 | outp = outbuff; |
797 | inp2 = (short *)(BufferSpace+inPtr); |
798 | for (x = 0; x < cnt; x+=0x10) { |
799 | out1[1] = inp1[0]*lutt6[6]; |
800 | out1[1] += inp1[3]*lutt6[7]; |
801 | out1[1] += inp1[2]*lutt6[4]; |
802 | out1[1] += inp1[5]*lutt6[5]; |
803 | out1[1] += inp1[4]*lutt6[2]; |
804 | out1[1] += inp1[7]*lutt6[3]; |
805 | out1[1] += inp1[6]*lutt6[0]; |
806 | out1[1] += inp2[1]*lutt6[1]; // 1 |
807 | |
808 | out1[0] = inp1[3]*lutt6[6]; |
809 | out1[0] += inp1[2]*lutt6[7]; |
810 | out1[0] += inp1[5]*lutt6[4]; |
811 | out1[0] += inp1[4]*lutt6[5]; |
812 | out1[0] += inp1[7]*lutt6[2]; |
813 | out1[0] += inp1[6]*lutt6[3]; |
814 | out1[0] += inp2[1]*lutt6[0]; |
815 | out1[0] += inp2[0]*lutt6[1]; |
816 | |
817 | out1[3] = inp1[2]*lutt6[6]; |
818 | out1[3] += inp1[5]*lutt6[7]; |
819 | out1[3] += inp1[4]*lutt6[4]; |
820 | out1[3] += inp1[7]*lutt6[5]; |
821 | out1[3] += inp1[6]*lutt6[2]; |
822 | out1[3] += inp2[1]*lutt6[3]; |
823 | out1[3] += inp2[0]*lutt6[0]; |
824 | out1[3] += inp2[3]*lutt6[1]; |
825 | |
826 | out1[2] = inp1[5]*lutt6[6]; |
827 | out1[2] += inp1[4]*lutt6[7]; |
828 | out1[2] += inp1[7]*lutt6[4]; |
829 | out1[2] += inp1[6]*lutt6[5]; |
830 | out1[2] += inp2[1]*lutt6[2]; |
831 | out1[2] += inp2[0]*lutt6[3]; |
832 | out1[2] += inp2[3]*lutt6[0]; |
833 | out1[2] += inp2[2]*lutt6[1]; |
834 | |
835 | out1[5] = inp1[4]*lutt6[6]; |
836 | out1[5] += inp1[7]*lutt6[7]; |
837 | out1[5] += inp1[6]*lutt6[4]; |
838 | out1[5] += inp2[1]*lutt6[5]; |
839 | out1[5] += inp2[0]*lutt6[2]; |
840 | out1[5] += inp2[3]*lutt6[3]; |
841 | out1[5] += inp2[2]*lutt6[0]; |
842 | out1[5] += inp2[5]*lutt6[1]; |
843 | |
844 | out1[4] = inp1[7]*lutt6[6]; |
845 | out1[4] += inp1[6]*lutt6[7]; |
846 | out1[4] += inp2[1]*lutt6[4]; |
847 | out1[4] += inp2[0]*lutt6[5]; |
848 | out1[4] += inp2[3]*lutt6[2]; |
849 | out1[4] += inp2[2]*lutt6[3]; |
850 | out1[4] += inp2[5]*lutt6[0]; |
851 | out1[4] += inp2[4]*lutt6[1]; |
852 | |
853 | out1[7] = inp1[6]*lutt6[6]; |
854 | out1[7] += inp2[1]*lutt6[7]; |
855 | out1[7] += inp2[0]*lutt6[4]; |
856 | out1[7] += inp2[3]*lutt6[5]; |
857 | out1[7] += inp2[2]*lutt6[2]; |
858 | out1[7] += inp2[5]*lutt6[3]; |
859 | out1[7] += inp2[4]*lutt6[0]; |
860 | out1[7] += inp2[7]*lutt6[1]; |
861 | |
862 | out1[6] = inp2[1]*lutt6[6]; |
863 | out1[6] += inp2[0]*lutt6[7]; |
864 | out1[6] += inp2[3]*lutt6[4]; |
865 | out1[6] += inp2[2]*lutt6[5]; |
866 | out1[6] += inp2[5]*lutt6[2]; |
867 | out1[6] += inp2[4]*lutt6[3]; |
868 | out1[6] += inp2[7]*lutt6[0]; |
869 | out1[6] += inp2[6]*lutt6[1]; |
870 | outp[1] = /*CLAMP*/((out1[1]+0x4000) >> 0xF); |
871 | outp[0] = /*CLAMP*/((out1[0]+0x4000) >> 0xF); |
872 | outp[3] = /*CLAMP*/((out1[3]+0x4000) >> 0xF); |
873 | outp[2] = /*CLAMP*/((out1[2]+0x4000) >> 0xF); |
874 | outp[5] = /*CLAMP*/((out1[5]+0x4000) >> 0xF); |
875 | outp[4] = /*CLAMP*/((out1[4]+0x4000) >> 0xF); |
876 | outp[7] = /*CLAMP*/((out1[7]+0x4000) >> 0xF); |
877 | outp[6] = /*CLAMP*/((out1[6]+0x4000) >> 0xF); |
878 | inp1 = inp2; |
879 | inp2 += 8; |
880 | outp += 8; |
881 | } |
882 | // memcpy (rsp.RDRAM+(inst2&0xFFFFFF), dmem+0xFB0, 0x20); |
883 | memcpy (save, inp2-8, 0x10); |
884 | memcpy (BufferSpace+(inst1&0xffff), outbuff, cnt); |
885 | } |
886 | |
887 | static void SEGMENT2 (u32 inst1, u32 inst2) { |
888 | if (isZeldaABI) { |
889 | FILTER2 (inst1, inst2); |
890 | return; |
891 | } |
892 | if ((inst1 & 0xffffff) == 0) { |
893 | isMKABI = true; |
894 | //SEGMENTS[(inst2>>24)&0xf] = (inst2 & 0xffffff); |
895 | } else { |
896 | isMKABI = false; |
897 | isZeldaABI = true; |
898 | FILTER2 (inst1, inst2); |
899 | } |
900 | } |
901 | |
902 | static void UNKNOWN (u32 inst1, u32 inst2) { |
903 | } |
904 | /* |
905 | void (*ABI2[0x20])(void) = { |
906 | SPNOOP, ADPCM2, CLEARBUFF2, SPNOOP, SPNOOP, RESAMPLE2, SPNOOP, SEGMENT2, |
907 | SETBUFF2, SPNOOP, DMEMMOVE2, LOADADPCM2, MIXER2, INTERLEAVE2, HILOGAIN, SETLOOP2, |
908 | SPNOOP, INTERL2, ENVSETUP1, ENVMIXER2, LOADBUFF2, SAVEBUFF2, ENVSETUP2, SPNOOP, |
909 | SPNOOP, SPNOOP, SPNOOP, SPNOOP, SPNOOP, SPNOOP, SPNOOP, SPNOOP |
910 | };*/ |
911 | |
912 | extern "C" const acmd_callback_t ABI2[0x20] = { |
913 | SPNOOP , ADPCM2, CLEARBUFF2, UNKNOWN, ADDMIXER, RESAMPLE2, UNKNOWN, SEGMENT2, |
914 | SETBUFF2 , DUPLICATE2, DMEMMOVE2, LOADADPCM2, MIXER2, INTERLEAVE2, HILOGAIN, SETLOOP2, |
915 | SPNOOP, INTERL2 , ENVSETUP1, ENVMIXER2, LOADBUFF2, SAVEBUFF2, ENVSETUP2, SPNOOP, |
916 | HILOGAIN , SPNOOP, DUPLICATE2 , UNKNOWN , SPNOOP , SPNOOP , SPNOOP , SPNOOP |
917 | }; |
918 | /* |
919 | void (*ABI2[0x20])(void) = { |
920 | SPNOOP , ADPCM2, CLEARBUFF2, SPNOOP, SPNOOP, RESAMPLE2 , SPNOOP , SEGMENT2, |
921 | SETBUFF2 , DUPLICATE2, DMEMMOVE2, LOADADPCM2, MIXER2, INTERLEAVE2, SPNOOP, SETLOOP2, |
922 | SPNOOP, INTERL2 , ENVSETUP1, ENVMIXER2, LOADBUFF2, SAVEBUFF2, ENVSETUP2, SPNOOP, |
923 | SPNOOP , SPNOOP, SPNOOP , SPNOOP , SPNOOP , SPNOOP , SPNOOP , SPNOOP |
924 | };*/ |
925 | /* NOTES: |
926 | |
927 | FILTER/SEGMENT - Still needs to be finished up... add FILTER? |
928 | UNKNOWWN #27 - Is this worth doing? Looks like a pain in the ass just for WaveRace64 |
929 | */ |
930 | |