df00ea13 |
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 * |
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 <stdint.h> |
25 | |
26 | #include "m64p_plugin.h" |
27 | #include "hle.h" |
28 | #include "alist_internal.h" |
29 | |
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> |
40 | 0x320..0x35F Segments |
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) |
51 | 0x372 Ramp?? (Left) |
52 | 0x374 Rate?? (Left) |
53 | 0x376 Target Volume (Right) |
54 | 0x378 Ramp?? (Right) |
55 | 0x37A Rate?? (Right) |
56 | 0x37C Dry?? |
57 | 0x37E Wet?? |
58 | 0x380..0x4BF Alist data |
59 | 0x4C0..0x4FF ADPCM CodeBook |
60 | 0x500..0x5BF <Unknown> |
61 | 0x5C0..0xF7F Buffers... |
62 | 0xF80..0xFFF <Unknown> |
63 | ***************************************************/ |
64 | #ifdef USE_EXPANSION |
65 | #define MEMMASK 0x7FFFFF |
66 | #else |
67 | #define MEMMASK 0x3FFFFF |
68 | #endif |
69 | |
70 | static void SPNOOP(uint32_t inst1, uint32_t inst2) |
71 | { |
72 | } |
73 | |
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) */ |
89 | |
90 | uint8_t BufferSpace[0x10000]; |
91 | |
92 | short hleMixerWorkArea[256]; |
93 | uint16_t adpcmtable[0x88]; |
94 | |
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 |
128 | }; |
129 | |
130 | static void CLEARBUFF(uint32_t inst1, uint32_t inst2) |
131 | { |
132 | uint32_t addr = (uint32_t)(inst1 & 0xffff); |
133 | uint32_t count = (uint32_t)(inst2 & 0xffff); |
134 | addr &= 0xFFFC; |
135 | memset(BufferSpace + addr, 0, (count + 3) & 0xFFFC); |
136 | } |
137 | |
138 | static void ENVMIXER(uint32_t inst1, uint32_t inst2) |
139 | { |
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); |
147 | int32_t MainR; |
148 | int32_t MainL; |
149 | int32_t AuxR; |
150 | int32_t AuxL; |
151 | int i1, o1, a1, a2 = 0, a3 = 0; |
152 | unsigned short AuxIncRate = 1; |
153 | short zero[8]; |
154 | int32_t LVol, RVol; |
155 | int32_t LAcc, RAcc; |
156 | int32_t LTrg, RTrg; |
157 | int16_t Wet, Dry; |
158 | uint32_t ptr = 0; |
159 | int32_t RRamp, LRamp; |
160 | int32_t LAdderStart, RAdderStart, LAdderEnd, RAdderEnd; |
161 | int32_t oMainR, oMainL, oAuxR, oAuxL; |
162 | int x, y; |
163 | |
164 | memset(zero, 0, sizeof(zero)); |
165 | |
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; |
177 | LAdderEnd = LVol; |
178 | RAdderEnd = RVol; |
179 | RRamp = VolRamp_Right; |
180 | LRamp = VolRamp_Left; |
181 | } else { |
182 | /* Load LVol, RVol, LAcc, and RAcc (all 32bit) |
183 | * Load Wet, Dry, LTrg, RTrg |
184 | */ |
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 */ |
196 | } |
197 | |
198 | if (!(flags & A_AUX)) { |
199 | AuxIncRate = 0; |
200 | aux2 = aux3 = zero; |
201 | } |
202 | |
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; |
207 | |
208 | for (y = 0; y < AudioCount; y += 0x10) { |
209 | |
210 | if (LAdderStart != LTrg) { |
211 | LAcc = LAdderStart; |
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); |
215 | } else { |
216 | LAcc = LTrg; |
217 | LVol = 0; |
218 | } |
219 | |
220 | if (RAdderStart != RTrg) { |
221 | RAcc = RAdderStart; |
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); |
225 | } else { |
226 | RAcc = RTrg; |
227 | RVol = 0; |
228 | } |
229 | |
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]; |
234 | if (AuxIncRate) { |
235 | a2 = (int)aux2[ptr ^ S]; |
236 | a3 = (int)aux3[ptr ^ S]; |
237 | } |
238 | /* TODO: here... |
239 | * LAcc = LTrg; |
240 | * RAcc = RTrg; |
241 | */ |
242 | |
243 | LAcc += LVol; |
244 | RAcc += RVol; |
245 | |
246 | if (LVol <= 0) { |
247 | /* Decrementing */ |
248 | if (LAcc < LTrg) { |
249 | LAcc = LTrg; |
250 | LAdderStart = LTrg; |
251 | MainL = oMainL; |
252 | AuxL = oAuxL; |
253 | } else { |
254 | MainL = (Dry * ((int32_t)LAcc >> 16) + 0x4000) >> 15; |
255 | AuxL = (Wet * ((int32_t)LAcc >> 16) + 0x4000) >> 15; |
256 | } |
257 | } else { |
258 | if (LAcc > LTrg) { |
259 | LAcc = LTrg; |
260 | LAdderStart = LTrg; |
261 | MainL = oMainL; |
262 | AuxL = oAuxL; |
263 | } else { |
264 | MainL = (Dry * ((int32_t)LAcc >> 16) + 0x4000) >> 15; |
265 | AuxL = (Wet * ((int32_t)LAcc >> 16) + 0x4000) >> 15; |
266 | } |
267 | } |
268 | |
269 | if (RVol <= 0) { |
270 | /* Decrementing */ |
271 | if (RAcc < RTrg) { |
272 | RAcc = RTrg; |
273 | RAdderStart = RTrg; |
274 | MainR = oMainR; |
275 | AuxR = oAuxR; |
276 | } else { |
277 | MainR = (Dry * ((int32_t)RAcc >> 16) + 0x4000) >> 15; |
278 | AuxR = (Wet * ((int32_t)RAcc >> 16) + 0x4000) >> 15; |
279 | } |
280 | } else { |
281 | if (RAcc > RTrg) { |
282 | RAcc = RTrg; |
283 | RAdderStart = RTrg; |
284 | MainR = oMainR; |
285 | AuxR = oAuxR; |
286 | } else { |
287 | MainR = (Dry * ((int32_t)RAcc >> 16) + 0x4000) >> 15; |
288 | AuxR = (Wet * ((int32_t)RAcc >> 16) + 0x4000) >> 15; |
289 | } |
290 | } |
291 | |
292 | o1 += ((i1 * MainR) + 0x4000) >> 15; |
293 | a1 += ((i1 * MainL) + 0x4000) >> 15; |
294 | |
295 | o1 = clamp_s16(o1); |
296 | a1 = clamp_s16(a1); |
297 | |
298 | out[ptr ^ S] = o1; |
299 | aux1[ptr ^ S] = a1; |
300 | if (AuxIncRate) { |
301 | a2 += ((i1 * AuxR) + 0x4000) >> 15; |
302 | a3 += ((i1 * AuxL) + 0x4000) >> 15; |
303 | |
304 | a2 = clamp_s16(a2); |
305 | a3 = clamp_s16(a3); |
306 | |
307 | aux2[ptr ^ S] = a2; |
308 | aux3[ptr ^ S] = a3; |
309 | } |
310 | ptr++; |
311 | } |
312 | } |
313 | |
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); |
325 | } |
326 | |
327 | static void RESAMPLE(uint32_t inst1, uint32_t inst2) |
328 | { |
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; |
334 | int16_t *lut; |
335 | short *dst = (short *)(BufferSpace); |
336 | int16_t *src = (int16_t *)(BufferSpace); |
337 | uint32_t srcPtr = (AudioInBuffer / 2); |
338 | uint32_t dstPtr = (AudioOutBuffer / 2); |
339 | int32_t temp; |
340 | int32_t accum; |
341 | int x, i; |
342 | srcPtr -= 4; |
343 | |
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); |
348 | } else { |
349 | for (x = 0; x < 4; x++) |
350 | src[(srcPtr + x)^S] = 0; |
351 | } |
352 | |
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; |
357 | |
358 | /* imul */ |
359 | temp = ((int32_t) * (int16_t *)(src + ((srcPtr + 0)^S)) * ((int32_t)((int16_t)lut[0]))); |
360 | accum = (int32_t)(temp >> 15); |
361 | |
362 | temp = ((int32_t) * (int16_t *)(src + ((srcPtr + 1)^S)) * ((int32_t)((int16_t)lut[1]))); |
363 | accum += (int32_t)(temp >> 15); |
364 | |
365 | temp = ((int32_t) * (int16_t *)(src + ((srcPtr + 2)^S)) * ((int32_t)((int16_t)lut[2]))); |
366 | accum += (int32_t)(temp >> 15); |
367 | |
368 | temp = ((int32_t) * (int16_t *)(src + ((srcPtr + 3)^S)) * ((int32_t)((int16_t)lut[3]))); |
369 | accum += (int32_t)(temp >> 15); |
370 | |
371 | accum = clamp_s16(accum); |
372 | |
373 | dst[dstPtr ^ S] = (accum); |
374 | dstPtr++; |
375 | Accum += Pitch; |
376 | srcPtr += (Accum >> 16); |
377 | Accum &= 0xffff; |
378 | } |
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; |
382 | } |
383 | |
384 | static void SETVOL(uint32_t inst1, uint32_t inst2) |
385 | { |
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)); |
390 | |
391 | if (flags & A_AUX) { |
392 | Env_Dry = (int16_t)vol; /* m_MainVol */ |
393 | Env_Wet = (int16_t)volrate; /* m_AuxVol */ |
394 | return; |
395 | } |
396 | |
397 | /* Set the Source(start) Volumes */ |
398 | if (flags & A_VOL) { |
399 | if (flags & A_LEFT) |
400 | Vol_Left = (int16_t)vol; |
401 | else |
402 | /* A_RIGHT */ |
403 | Vol_Right = (int16_t)vol; |
404 | return; |
405 | } |
406 | |
407 | /* 0x370 Loop Value (shared location) |
408 | * 0x370 Target Volume (Left) |
409 | */ |
410 | |
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; |
418 | } |
419 | } |
420 | |
421 | static void UNKNOWN(uint32_t inst1, uint32_t inst2) {} |
422 | |
423 | static void SETLOOP(uint32_t inst1, uint32_t inst2) |
424 | { |
425 | loopval = (inst2 & 0xffffff); |
426 | } |
427 | |
428 | /* TODO Work in progress! :) */ |
429 | static void ADPCM(uint32_t inst1, uint32_t inst2) |
430 | { |
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; |
436 | unsigned char icode; |
437 | unsigned char code; |
438 | int vscale; |
439 | unsigned short index; |
440 | unsigned short j; |
441 | int a[8]; |
442 | short *book1, *book2; |
443 | int l1; |
444 | int l2; |
445 | int inp1[8]; |
446 | int inp2[8]; |
447 | |
448 | memset(out, 0, 32); |
449 | |
450 | if (!(Flags & 0x1)) { |
451 | if (Flags & 0x2) |
452 | memcpy(out, &rsp.RDRAM[loopval & MEMMASK], 32); |
453 | else |
454 | memcpy(out, &rsp.RDRAM[Address], 32); |
455 | } |
456 | |
457 | l1 = out[14 ^ S]; |
458 | l2 = out[15 ^ S]; |
459 | out += 16; |
460 | while (count > 0) { |
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 |
465 | */ |
466 | |
467 | code = BufferSpace[(AudioInBuffer + inPtr)^S8]; |
468 | index = code & 0xf; |
469 | /* index into the adpcm code table */ |
470 | index <<= 4; |
471 | book1 = (short *)&adpcmtable[index]; |
472 | book2 = book1 + 8; |
473 | /* upper nibble is scale */ |
474 | code >>= 4; |
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 |
481 | */ |
482 | vscale = (0x8000 >> ((12 - code) - 1)); |
483 | |
484 | /* coded adpcm data lies next */ |
485 | inPtr++; |
486 | j = 0; |
487 | /* loop of 8, for 8 coded nibbles from 4 bytes |
488 | * which yields 8 short pcm values |
489 | */ |
490 | while (j < 8) { |
491 | icode = BufferSpace[(AudioInBuffer + inPtr)^S8]; |
492 | inPtr++; |
493 | |
494 | /* this will in effect be signed */ |
495 | inp1[j] = (int16_t)((icode & 0xf0) << 8); |
496 | if (code < 12) |
497 | inp1[j] = ((int)((int)inp1[j] * (int)vscale) >> 16); |
498 | j++; |
499 | |
500 | inp1[j] = (int16_t)((icode & 0xf) << 12); |
501 | if (code < 12) |
502 | inp1[j] = ((int)((int)inp1[j] * (int)vscale) >> 16); |
503 | j++; |
504 | } |
505 | j = 0; |
506 | while (j < 8) { |
507 | icode = BufferSpace[(AudioInBuffer + inPtr)^S8]; |
508 | inPtr++; |
509 | |
510 | /* this will in effect be signed */ |
511 | inp2[j] = (short)((icode & 0xf0) << 8); |
512 | if (code < 12) |
513 | inp2[j] = ((int)((int)inp2[j] * (int)vscale) >> 16); |
514 | j++; |
515 | |
516 | inp2[j] = (short)((icode & 0xf) << 12); |
517 | if (code < 12) |
518 | inp2[j] = ((int)((int)inp2[j] * (int)vscale) >> 16); |
519 | j++; |
520 | } |
521 | |
522 | a[0] = (int)book1[0] * (int)l1; |
523 | a[0] += (int)book2[0] * (int)l2; |
524 | a[0] += (int)inp1[0] * (int)2048; |
525 | |
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; |
530 | |
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; |
536 | |
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; |
543 | |
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; |
551 | |
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; |
560 | |
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; |
570 | |
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; |
581 | |
582 | for (j = 0; j < 8; j++) { |
583 | a[j ^ S] >>= 11; |
584 | a[j ^ S] = clamp_s16(a[j ^ S]); |
585 | *(out++) = a[j ^ S]; |
586 | } |
587 | l1 = a[6]; |
588 | l2 = a[7]; |
589 | |
590 | a[0] = (int)book1[0] * (int)l1; |
591 | a[0] += (int)book2[0] * (int)l2; |
592 | a[0] += (int)inp2[0] * (int)2048; |
593 | |
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; |
598 | |
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; |
604 | |
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; |
611 | |
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; |
619 | |
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; |
628 | |
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; |
638 | |
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; |
649 | |
650 | for (j = 0; j < 8; j++) { |
651 | a[j ^ S] >>= 11; |
652 | a[j ^ S] = clamp_s16(a[j ^ S]); |
653 | *(out++) = a[j ^ S]; |
654 | } |
655 | l1 = a[6]; |
656 | l2 = a[7]; |
657 | |
658 | count -= 32; |
659 | } |
660 | out -= 16; |
661 | memcpy(&rsp.RDRAM[Address], out, 32); |
662 | } |
663 | |
664 | /* TODO memcpy causes static... endianess issue :( */ |
665 | static void LOADBUFF(uint32_t inst1, uint32_t inst2) |
666 | { |
667 | uint32_t v0; |
668 | if (AudioCount == 0) |
669 | return; |
670 | v0 = (inst2 & 0xfffffc); |
671 | memcpy(BufferSpace + (AudioInBuffer & 0xFFFC), rsp.RDRAM + v0, (AudioCount + 3) & 0xFFFC); |
672 | } |
673 | |
674 | /* TODO memcpy causes static... endianess issue :( */ |
675 | static void SAVEBUFF(uint32_t inst1, uint32_t inst2) |
676 | { |
677 | uint32_t v0; |
678 | if (AudioCount == 0) |
679 | return; |
680 | v0 = (inst2 & 0xfffffc); |
681 | memcpy(rsp.RDRAM + v0, BufferSpace + (AudioOutBuffer & 0xFFFC), (AudioCount + 3) & 0xFFFC); |
682 | } |
683 | |
684 | /* NOTE Should work ;-) */ |
685 | static void SETBUFF(uint32_t inst1, uint32_t inst2) |
686 | { |
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); |
692 | } else { |
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 */ |
697 | } |
698 | } |
699 | |
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) |
702 | { |
703 | uint32_t cnt; |
704 | uint32_t v0 = (inst1 & 0xFFFF); |
705 | uint32_t v1 = (inst2 >> 0x10); |
706 | uint32_t count = ((inst2 + 3) & 0xfffc); |
707 | |
708 | if ((inst2 & 0xffff) == 0) |
709 | return; |
710 | |
711 | for (cnt = 0; cnt < count; cnt++) |
712 | *(uint8_t *)(BufferSpace + ((cnt + v1)^S8)) = *(uint8_t *)(BufferSpace + ((cnt + v0)^S8)); |
713 | } |
714 | |
715 | /* NOTE Loads an ADPCM table - Works 100% Now 03-13-01 */ |
716 | static void LOADADPCM(uint32_t inst1, uint32_t inst2) |
717 | { |
718 | uint32_t v0 = (inst2 & 0xffffff); |
719 | uint32_t x; |
720 | |
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]; |
725 | |
726 | adpcmtable[(0x2 + (x << 3))^S] = table[2]; |
727 | adpcmtable[(0x3 + (x << 3))^S] = table[3]; |
728 | |
729 | adpcmtable[(0x4 + (x << 3))^S] = table[4]; |
730 | adpcmtable[(0x5 + (x << 3))^S] = table[5]; |
731 | |
732 | adpcmtable[(0x6 + (x << 3))^S] = table[6]; |
733 | adpcmtable[(0x7 + (x << 3))^S] = table[7]; |
734 | table += 8; |
735 | } |
736 | } |
737 | |
738 | |
739 | /* NOTE Works... - 3-11-01 */ |
740 | static void INTERLEAVE(uint32_t inst1, uint32_t inst2) |
741 | { |
742 | uint32_t inL, inR; |
743 | uint16_t *outbuff = (uint16_t *)(AudioOutBuffer + BufferSpace); |
744 | uint16_t *inSrcR; |
745 | uint16_t *inSrcL; |
746 | uint16_t Left, Right, Left2, Right2; |
747 | int x; |
748 | |
749 | inL = inst2 & 0xFFFF; |
750 | inR = (inst2 >> 16) & 0xFFFF; |
751 | |
752 | inSrcR = (uint16_t *)(BufferSpace + inR); |
753 | inSrcL = (uint16_t *)(BufferSpace + inL); |
754 | |
755 | for (x = 0; x < (AudioCount / 4); x++) { |
756 | Left = *(inSrcL++); |
757 | Right = *(inSrcR++); |
758 | Left2 = *(inSrcL++); |
759 | Right2 = *(inSrcR++); |
760 | |
761 | #ifdef M64P_BIG_ENDIAN |
762 | *(outbuff++) = Right; |
763 | *(outbuff++) = Left; |
764 | *(outbuff++) = Right2; |
765 | *(outbuff++) = Left2; |
766 | #else |
767 | *(outbuff++) = Right2; |
768 | *(outbuff++) = Left2; |
769 | *(outbuff++) = Right; |
770 | *(outbuff++) = Left; |
771 | #endif |
772 | } |
773 | } |
774 | |
775 | /* NOTE Fixed a sign issue... 03-14-01 */ |
776 | static void MIXER(uint32_t inst1, uint32_t inst2) |
777 | { |
778 | uint32_t dmemin = (uint16_t)(inst2 >> 0x10); |
779 | uint32_t dmemout = (uint16_t)(inst2 & 0xFFFF); |
780 | int32_t gain = (int16_t)(inst1 & 0xFFFF); |
781 | int32_t temp; |
782 | int x; |
783 | |
784 | if (AudioCount == 0) |
785 | return; |
786 | |
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); |
790 | |
791 | temp = clamp_s16((int32_t)temp); |
792 | |
793 | *(uint16_t *)(BufferSpace + dmemout + x) = (uint16_t)(temp & 0xFFFF); |
794 | } |
795 | } |
796 | |
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% |
802 | * |
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% |
807 | */ |
808 | |
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 |
813 | }; |