| 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 | |
| 25 | extern "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 *************** |
| 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> |
| 67 | 0x320..0x35F Segments |
| 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) |
| 78 | 0x372 Ramp?? (Left) |
| 79 | 0x374 Rate?? (Left) |
| 80 | 0x376 Target Volume (Right) |
| 81 | 0x378 Ramp?? (Right) |
| 82 | 0x37A Rate?? (Right) |
| 83 | 0x37C Dry?? |
| 84 | 0x37E Wet?? |
| 85 | 0x380..0x4BF Alist data |
| 86 | 0x4C0..0x4FF ADPCM CodeBook |
| 87 | 0x500..0x5BF <Unknown> |
| 88 | 0x5C0..0xF7F Buffers... |
| 89 | 0xF80..0xFFF <Unknown> |
| 90 | ***************************************************/ |
| 91 | #ifdef USE_EXPANSION |
| 92 | #define MEMMASK 0x7FFFFF |
| 93 | #else |
| 94 | #define MEMMASK 0x3FFFFF |
| 95 | #endif |
| 96 | |
| 97 | static void SPNOOP (u32 inst1, u32 inst2) { |
| 98 | //MessageBox (NULL, "Unknown Audio Command in ABI 1", "Audio HLE Error", MB_OK); |
| 99 | } |
| 100 | |
| 101 | u32 SEGMENTS[0x10]; // 0x0320 |
| 102 | // T8 = 0x360 |
| 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) |
| 120 | |
| 121 | u8 BufferSpace[0x10000]; |
| 122 | |
| 123 | short hleMixerWorkArea[256]; |
| 124 | u16 adpcmtable[0x88]; |
| 125 | |
| 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 |
| 159 | }; |
| 160 | |
| 161 | static 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 | |
| 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]; |
| 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 | |
| 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; |
| 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 | |
| 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)); |
| 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 | |
| 516 | static void UNKNOWN (u32 inst1, u32 inst2) {} |
| 517 | |
| 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 |
| 522 | } |
| 523 | |
| 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; |
| 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 | |
| 769 | static 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 | |
| 778 | static 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 | |
| 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 |
| 796 | } |
| 797 | } |
| 798 | |
| 799 | static 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 | |
| 818 | static 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 | |
| 843 | static 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 | |
| 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); |
| 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 | |
| 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 |
| 915 | }; |
| 916 | |
| 917 | /* BACKUPS |
| 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); |
| 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 | |