1 // OKI MSM6295 module
2 // Emulation by Jan Klaassen
3
4 #include <math.h>
5 #include "burnint.h"
6 #include "msm6295.h"
7 #include <stddef.h>
8
9 UINT8* MSM6295ROM;
10
11 UINT32 nMSM6295Status[MAX_MSM6295];
12
13 struct MSM6295ChannelInfo {
14 INT32 nOutput;
15 INT32 nVolume;
16 INT32 nPosition;
17 INT32 nSampleCount;
18 INT32 nSample;
19 INT32 nStep;
20 INT32 nDelta;
21
22 INT32 nBufPos;
23 INT32 nPlaying;
24 };
25
26 struct MSM6295Struct {
27 // All current settings for each channel
28 MSM6295ChannelInfo ChannelInfo[4];
29
30 // Used for sending commands
31 bool bIsCommand;
32 INT32 nSampleInfo;
33
34 // Not scanned.
35 INT32 nVolume;
36 INT32 nOutputDir;
37 INT32 nSampleRate;
38 INT32 nSampleSize;
39 INT32 nFractionalPosition;
40
41 };
42
43 static struct MSM6295Struct MSM6295[MAX_MSM6295];
44
45 static UINT8 *pBankPointer[MAX_MSM6295][0x40000/0x100];
46 INT32 nLastMSM6295Chip;
47
MSM6295SetBank(INT32 nChip,UINT8 * pRomData,INT32 nStart,INT32 nEnd)48 void MSM6295SetBank(INT32 nChip, UINT8 *pRomData, INT32 nStart, INT32 nEnd)
49 {
50 #if defined FBA_DEBUG
51 if (!DebugSnd_MSM6295Initted) bprintf(PRINT_ERROR, _T("MSM6295SetBank called without init\n"));
52 if (nChip > nLastMSM6295Chip) bprintf(PRINT_ERROR, _T("MSM6295SetBank called with invalid chip number %x\n"), nChip);
53 if (nStart >= nEnd || nStart < 0 || nStart >= 0x40000) bprintf(PRINT_ERROR, _T("MSM6295SetBank (Chip %d) called with invalid nStart %x\n"), nChip, nStart);
54 if (nStart >= nEnd || nEnd < 0 || nEnd >= 0x40000) bprintf(PRINT_ERROR, _T("MSM6295SetBank (Chip %d) called with invalid nEnd %x\n"), nChip, nEnd);
55 #endif
56
57 if (pRomData == NULL) return;
58
59 // if (nEnd >= nStart) return;
60 // if (nEnd >= 0x40000) nEnd = 0x40000;
61
62 for (INT32 i = 0; i < ((nEnd - nStart) >> 8) + 1; i++)
63 {
64 pBankPointer[nChip][(nStart >> 8) + i] = pRomData + (i << 8);
65 }
66 }
67
68 #if defined FBA_DEBUG
MSM6295ReadData(INT32 nChip,UINT32 nAddress)69 static inline UINT8 MSM6295ReadData(INT32 nChip, UINT32 nAddress)
70 {
71 nAddress &= 0x3ffff;
72
73 if (pBankPointer[nChip][(nAddress >> 8)]) {
74 return pBankPointer[nChip][(nAddress >> 8)][(nAddress & 0xff)];
75 } else {
76 return 0;
77 }
78 }
79 #else
80 #define MSM6295ReadData(chip, addr) \
81 pBankPointer[chip][((addr) >> 8) & 0x3ff][((addr) & 0xff)]
82 #endif
83
84 static UINT32 MSM6295VolumeTable[16];
85 static INT32 MSM6295DeltaTable[49 * 16];
86 static INT32 MSM6295StepShift[8] = {-1, -1, -1, -1, 2, 4, 6, 8};
87
88 static INT32* MSM6295ChannelData[MAX_MSM6295][4];
89
90 static INT32* pLeftBuffer = NULL;
91 static INT32* pRightBuffer = NULL;
92
93 static INT32 nPreviousSample[MAX_MSM6295], nCurrentSample[MAX_MSM6295];
94
95 static bool bAdd;
96
MSM6295Reset(INT32 nChip)97 void MSM6295Reset(INT32 nChip)
98 {
99 #if defined FBA_DEBUG
100 if (!DebugSnd_MSM6295Initted) bprintf(PRINT_ERROR, _T("MSM6295Reset called without init\n"));
101 if (nChip > nLastMSM6295Chip) bprintf(PRINT_ERROR, _T("MSM6295Reset called with invalid chip number %x\n"), nChip);
102 #endif
103
104 nMSM6295Status[nChip] = 0;
105 MSM6295[nChip].bIsCommand = false;
106
107 MSM6295[nChip].nFractionalPosition = 0;
108
109 memset(&nPreviousSample, 0, sizeof(nPreviousSample));
110 memset(&nCurrentSample, 0, sizeof(nCurrentSample));
111
112 for (INT32 nChannel = 0; nChannel < 4; nChannel++) {
113 MSM6295[nChip].ChannelInfo[nChannel].nPlaying = 0;
114 memset(MSM6295ChannelData[nChip][nChannel], 0, 0x1000 * sizeof(INT32));
115 MSM6295[nChip].ChannelInfo[nChannel].nBufPos = 4;
116 }
117
118 // set bank data only if DataPointer has not already been set
119 if (pBankPointer[nChip][0] == NULL) {
120 MSM6295SetBank(nChip, MSM6295ROM + (nChip * 0x0100000), 0, 0x3ffff); // set initial bank (compatibility)
121 }
122 }
123
MSM6295Reset()124 void MSM6295Reset()
125 {
126 #if defined FBA_DEBUG
127 if (!DebugSnd_MSM6295Initted) bprintf(PRINT_ERROR, _T("MSM6295Reset called without init\n"));
128 #endif
129 for (INT32 nChip = 0; nChip <= nLastMSM6295Chip; nChip++)
130 {
131 MSM6295Reset(nChip);
132 }
133 }
134
MSM6295Scan(INT32,INT32 *)135 void MSM6295Scan(INT32 , INT32 *)
136 {
137 #if defined FBA_DEBUG
138 if (!DebugSnd_MSM6295Initted) bprintf(PRINT_ERROR, _T("MSM6295Scan called without init\n"));
139 #endif
140
141 for (INT32 nChip = 0; nChip <= nLastMSM6295Chip; nChip++)
142 {
143 ScanVar(&MSM6295[nChip], STRUCT_SIZE_HELPER(struct MSM6295Struct, nSampleInfo), "MSM6295 Chip");
144 SCAN_VAR(nMSM6295Status[nChip]);
145 }
146 }
147
MSM6295Render_Linear(INT32 nChip,INT32 * pLeftBuf,INT32 * pRightBuf,INT32 nSegmentLength)148 static void MSM6295Render_Linear(INT32 nChip, INT32* pLeftBuf, INT32 *pRightBuf, INT32 nSegmentLength)
149 {
150 INT32 nVolume = MSM6295[nChip].nVolume;
151 INT32 nFractionalPosition = MSM6295[nChip].nFractionalPosition;
152
153 INT32 nChannel, nDelta, nSample;
154 MSM6295ChannelInfo* pChannelInfo;
155
156 while (nSegmentLength--) {
157 if (nFractionalPosition >= 0x1000) {
158
159 nPreviousSample[nChip] = nCurrentSample[nChip];
160
161 do {
162 nCurrentSample[nChip] = 0;
163
164 for (nChannel = 0; nChannel < 4; nChannel++) {
165 if (nMSM6295Status[nChip] & (1 << nChannel)) {
166 pChannelInfo = &MSM6295[nChip].ChannelInfo[nChannel];
167
168 // Check for end of sample
169 if (pChannelInfo->nSampleCount-- == 0) {
170 nMSM6295Status[nChip] &= ~(1 << nChannel);
171 MSM6295[nChip].ChannelInfo[nChannel].nPlaying = 0;
172 continue;
173 }
174
175 // Get new delta from ROM
176 if (pChannelInfo->nPosition & 1) {
177 nDelta = pChannelInfo->nDelta & 0x0F;
178 } else {
179 pChannelInfo->nDelta = MSM6295ReadData(nChip, (pChannelInfo->nPosition >> 1) & 0x3ffff);
180 nDelta = pChannelInfo->nDelta >> 4;
181 }
182
183 // Compute new sample
184 nSample = pChannelInfo->nSample + MSM6295DeltaTable[(pChannelInfo->nStep << 4) + nDelta];
185 if (nSample > 2047) {
186 nSample = 2047;
187 } else {
188 if (nSample < -2048) {
189 nSample = -2048;
190 }
191 }
192 pChannelInfo->nSample = nSample;
193 pChannelInfo->nOutput = (nSample * pChannelInfo->nVolume);
194
195 // Update step value
196 pChannelInfo->nStep = pChannelInfo->nStep + MSM6295StepShift[nDelta & 7];
197 if (pChannelInfo->nStep > 48) {
198 pChannelInfo->nStep = 48;
199 } else {
200 if (pChannelInfo->nStep < 0) {
201 pChannelInfo->nStep = 0;
202 }
203 }
204
205 nCurrentSample[nChip] += pChannelInfo->nOutput / 16;
206
207 // Advance sample position
208 pChannelInfo->nPosition++;
209 }
210 }
211
212 nFractionalPosition -= 0x1000;
213
214 } while (nFractionalPosition >= 0x1000);
215 }
216
217 // Compute linearly interpolated sample
218 nSample = nPreviousSample[nChip] + (((nCurrentSample[nChip] - nPreviousSample[nChip]) * nFractionalPosition) >> 12);
219
220 // Scale all 4 channels
221 nSample *= nVolume;
222
223 if ((MSM6295[nChip].nOutputDir & BURN_SND_ROUTE_LEFT) == BURN_SND_ROUTE_LEFT) {
224 *pLeftBuf++ += nSample;
225 }
226 if ((MSM6295[nChip].nOutputDir & BURN_SND_ROUTE_RIGHT) == BURN_SND_ROUTE_RIGHT) {
227 *pRightBuf++ += nSample;
228 }
229
230 nFractionalPosition += MSM6295[nChip].nSampleSize;
231 }
232
233 MSM6295[nChip].nFractionalPosition = nFractionalPosition;
234 }
235
MSM6295Render_Cubic(INT32 nChip,INT32 * pLeftBuf,INT32 * pRightBuf,INT32 nSegmentLength)236 static void MSM6295Render_Cubic(INT32 nChip, INT32* pLeftBuf, INT32 *pRightBuf, INT32 nSegmentLength)
237 {
238 INT32 nVolume = MSM6295[nChip].nVolume;
239 INT32 nFractionalPosition;
240
241 INT32 nChannel, nDelta, nSample, nOutput;
242 MSM6295ChannelInfo* pChannelInfo;
243
244 while (nSegmentLength--) {
245
246 nOutput = 0;
247
248 for (nChannel = 0; nChannel < 4; nChannel++) {
249 pChannelInfo = &MSM6295[nChip].ChannelInfo[nChannel];
250 nFractionalPosition = MSM6295[nChip].nFractionalPosition;
251
252 if (nMSM6295Status[nChip] & (1 << nChannel)) {
253
254 while (nFractionalPosition >= 0x1000) {
255
256 // Check for end of sample
257 if (pChannelInfo->nSampleCount-- <= 0) {
258 if (pChannelInfo->nSampleCount <= -2) {
259 nMSM6295Status[nChip] &= ~(1 << nChannel);
260 MSM6295[nChip].ChannelInfo[nChannel].nPlaying = 0;
261 }
262
263 MSM6295ChannelData[nChip][nChannel][pChannelInfo->nBufPos++] = pChannelInfo->nOutput / 16;
264
265 break;
266
267 } else {
268 // Get new delta from ROM
269 if (pChannelInfo->nPosition & 1) {
270 nDelta = pChannelInfo->nDelta & 0x0F;
271 } else {
272 pChannelInfo->nDelta = MSM6295ReadData(nChip, (pChannelInfo->nPosition >> 1) & 0x3ffff);
273 nDelta = pChannelInfo->nDelta >> 4;
274 }
275
276 // Compute new sample
277 nSample = pChannelInfo->nSample + MSM6295DeltaTable[(pChannelInfo->nStep << 4) + nDelta];
278 if (nSample > 2047) {
279 nSample = 2047;
280 } else {
281 if (nSample < -2048) {
282 nSample = -2048;
283 }
284 }
285 pChannelInfo->nSample = nSample;
286 pChannelInfo->nOutput = nSample * pChannelInfo->nVolume;
287
288 // Update step value
289 pChannelInfo->nStep = pChannelInfo->nStep + MSM6295StepShift[nDelta & 7];
290 if (pChannelInfo->nStep > 48) {
291 pChannelInfo->nStep = 48;
292 } else {
293 if (pChannelInfo->nStep < 0) {
294 pChannelInfo->nStep = 0;
295 }
296 }
297
298 // The interpolator needs a 16-bit sample, pChannelInfo->nOutput is now a 20-bit number
299 MSM6295ChannelData[nChip][nChannel][pChannelInfo->nBufPos++] = pChannelInfo->nOutput / 16;
300
301 // Advance sample position
302 pChannelInfo->nPosition++;
303 nFractionalPosition -= 0x1000;
304 }
305 }
306
307 if (pChannelInfo->nBufPos > 0x0FF0) {
308 MSM6295ChannelData[nChip][nChannel][0] = MSM6295ChannelData[nChip][nChannel][pChannelInfo->nBufPos - 4];
309 MSM6295ChannelData[nChip][nChannel][1] = MSM6295ChannelData[nChip][nChannel][pChannelInfo->nBufPos - 3];
310 MSM6295ChannelData[nChip][nChannel][2] = MSM6295ChannelData[nChip][nChannel][pChannelInfo->nBufPos - 2];
311 MSM6295ChannelData[nChip][nChannel][3] = MSM6295ChannelData[nChip][nChannel][pChannelInfo->nBufPos - 1];
312 pChannelInfo->nBufPos = 4;
313 }
314
315 nOutput += INTERPOLATE4PS_16BIT(nFractionalPosition & 0x0FFF,
316 MSM6295ChannelData[nChip][nChannel][pChannelInfo->nBufPos - 4],
317 MSM6295ChannelData[nChip][nChannel][pChannelInfo->nBufPos - 3],
318 MSM6295ChannelData[nChip][nChannel][pChannelInfo->nBufPos - 2],
319 MSM6295ChannelData[nChip][nChannel][pChannelInfo->nBufPos - 1]);
320 } else {
321 // Ramp channel output to 0
322 if (pChannelInfo->nOutput != 0) {
323 INT32 nRamp = 2048 * 256 * 256 / nBurnSoundRate;
324 if (pChannelInfo->nOutput > 0) {
325 if (pChannelInfo->nOutput > nRamp) {
326 pChannelInfo->nOutput -= nRamp;
327 } else {
328 pChannelInfo->nOutput = 0;
329 }
330 } else {
331 if (pChannelInfo->nOutput < -nRamp) {
332 pChannelInfo->nOutput += nRamp;
333 } else {
334 pChannelInfo->nOutput = 0;
335 }
336 }
337 nOutput += pChannelInfo->nOutput / 16;
338 }
339 }
340 }
341
342 nOutput *= nVolume;
343
344 //*pLeftBuf++ += nOutput;
345 if ((MSM6295[nChip].nOutputDir & BURN_SND_ROUTE_LEFT) == BURN_SND_ROUTE_LEFT) {
346 *pLeftBuf++ += nOutput;
347 }
348 if ((MSM6295[nChip].nOutputDir & BURN_SND_ROUTE_RIGHT) == BURN_SND_ROUTE_RIGHT) {
349 *pRightBuf++ += nOutput;
350 }
351
352 MSM6295[nChip].nFractionalPosition = (MSM6295[nChip].nFractionalPosition & 0x0FFF) + MSM6295[nChip].nSampleSize;
353 }
354 }
355
MSM6295Render(INT32 nChip,INT16 * pSoundBuf,INT32 nSegmentLength)356 INT32 MSM6295Render(INT32 nChip, INT16* pSoundBuf, INT32 nSegmentLength) // render per-chip
357 {
358 #if defined FBA_DEBUG
359 if (!DebugSnd_MSM6295Initted) bprintf(PRINT_ERROR, _T("MSM6295Render called without init\n"));
360 if (nChip > nLastMSM6295Chip) bprintf(PRINT_ERROR, _T("MSM6295Render called with invalid chip number %x\n"), nChip);
361 #endif
362
363 if (nChip == 0) {
364 memset(pLeftBuffer, 0, nSegmentLength * sizeof(INT32));
365 memset(pRightBuffer, 0, nSegmentLength * sizeof(INT32));
366 }
367
368 if (nInterpolation >= 3) {
369 MSM6295Render_Cubic(nChip, pLeftBuffer, pRightBuffer, nSegmentLength);
370 } else {
371 MSM6295Render_Linear(nChip, pLeftBuffer, pRightBuffer, nSegmentLength);
372 }
373
374 if (nChip == nLastMSM6295Chip) {
375 for (INT32 i = 0; i < nSegmentLength; i++) {
376 if (bAdd) {
377 pSoundBuf[0] = BURN_SND_CLIP(pSoundBuf[0] + (pLeftBuffer[i] >> 8));
378 pSoundBuf[1] = BURN_SND_CLIP(pSoundBuf[1] + (pRightBuffer[i] >> 8));
379 } else {
380 pSoundBuf[0] = BURN_SND_CLIP(pLeftBuffer[i] >> 8);
381 pSoundBuf[1] = BURN_SND_CLIP(pRightBuffer[i] >> 8);
382 }
383 pSoundBuf += 2;
384 }
385 }
386
387 return 0;
388 }
389
MSM6295Render(INT16 * pSoundBuf,INT32 nSegmentLength)390 INT32 MSM6295Render(INT16* pSoundBuf, INT32 nSegmentLength) // render all chips
391 {
392 #if defined FBA_DEBUG
393 if (!DebugSnd_MSM6295Initted) bprintf(PRINT_ERROR, _T("MSM6295Render called without init\n"));
394 #endif
395
396 for (INT32 nChip = 0; nChip <= nLastMSM6295Chip; nChip++)
397 {
398 MSM6295Render(nChip, pSoundBuf, nSegmentLength);
399 }
400
401 return 0;
402 }
403
MSM6295Write(INT32 nChip,UINT8 nCommand)404 void MSM6295Write(INT32 nChip, UINT8 nCommand)
405 {
406 #if defined FBA_DEBUG
407 if (!DebugSnd_MSM6295Initted) bprintf(PRINT_ERROR, _T("MSM6295Write called without init\n"));
408 if (nChip > nLastMSM6295Chip) bprintf(PRINT_ERROR, _T("MSM6295Write called with invalid chip number %x\n"), nChip);
409 #endif
410
411 if (MSM6295[nChip].bIsCommand) {
412 // Process second half of command
413 INT32 nChannel, nSampleStart, nSampleCount;
414 INT32 nVolume = nCommand & 0x0F;
415 nCommand >>= 4;
416
417 MSM6295[nChip].bIsCommand = false;
418
419 for (nChannel = 0; nChannel < 4; nChannel++) {
420 if (nCommand & (0x01 << nChannel)) {
421 if (MSM6295[nChip].ChannelInfo[nChannel].nPlaying == 0) {
422
423 nSampleStart = MSM6295ReadData(nChip, (MSM6295[nChip].nSampleInfo & 0x03ff) + 0) << 17;
424 nSampleStart |= MSM6295ReadData(nChip, (MSM6295[nChip].nSampleInfo & 0x03ff) + 1) << 9;
425 nSampleStart |= MSM6295ReadData(nChip, (MSM6295[nChip].nSampleInfo & 0x03ff) + 2) << 1;
426
427 nSampleCount = MSM6295ReadData(nChip, (MSM6295[nChip].nSampleInfo & 0x03ff) + 3) << 17;
428 nSampleCount |= MSM6295ReadData(nChip, (MSM6295[nChip].nSampleInfo & 0x03ff) + 4) << 9;
429 nSampleCount |= MSM6295ReadData(nChip, (MSM6295[nChip].nSampleInfo & 0x03ff) + 5) << 1;
430
431 MSM6295[nChip].nSampleInfo &= 0xFF;
432
433 nSampleCount -= nSampleStart;
434
435 if (nSampleCount < 0x80000) {
436 // Start playing channel
437 MSM6295[nChip].ChannelInfo[nChannel].nVolume = MSM6295VolumeTable[nVolume];
438 MSM6295[nChip].ChannelInfo[nChannel].nPosition = nSampleStart;
439 MSM6295[nChip].ChannelInfo[nChannel].nSampleCount = nSampleCount;
440 MSM6295[nChip].ChannelInfo[nChannel].nStep = 0;
441 MSM6295[nChip].ChannelInfo[nChannel].nSample = -1;
442 MSM6295[nChip].ChannelInfo[nChannel].nPlaying = 1;
443 MSM6295[nChip].ChannelInfo[nChannel].nOutput = 0;
444
445 nMSM6295Status[nChip] |= nCommand;
446
447 if (nInterpolation >= 3) {
448 MSM6295ChannelData[nChip][nChannel][0] = 0;
449 MSM6295ChannelData[nChip][nChannel][1] = 0;
450 MSM6295ChannelData[nChip][nChannel][2] = 0;
451 MSM6295ChannelData[nChip][nChannel][3] = 0;
452 MSM6295[nChip].ChannelInfo[nChannel].nBufPos = 4;
453 }
454 }
455 }
456 }
457 }
458
459 } else {
460 // Process command
461 if (nCommand & 0x80) {
462 MSM6295[nChip].nSampleInfo = (nCommand & 0x7F) << 3;
463 MSM6295[nChip].bIsCommand = true;
464 } else {
465 // Stop playing samples
466 INT32 nChannel;
467 nCommand >>= 3;
468 nMSM6295Status[nChip] &= ~nCommand;
469
470 for (nChannel = 0; nChannel < 4; nChannel++, nCommand>>=1) {
471 if (nCommand & 1) {
472 MSM6295[nChip].ChannelInfo[nChannel].nPlaying = 0;
473 }
474 }
475 }
476 }
477 }
478
MSM6295Exit(INT32 nChip)479 void MSM6295Exit(INT32 nChip)
480 {
481 #if defined FBA_DEBUG
482 if (!DebugSnd_MSM6295Initted) bprintf(PRINT_ERROR, _T("MSM6295Exit called without init\n"));
483 if (nChip > nLastMSM6295Chip) bprintf(PRINT_ERROR, _T("MSM6295Exit called with invalid chip number %x\n"), nChip);
484 #endif
485
486 if (!DebugSnd_MSM6295Initted) return;
487
488 if (pLeftBuffer) BurnFree(pLeftBuffer);
489 if (pRightBuffer) BurnFree(pRightBuffer);
490 pLeftBuffer = NULL;
491 pRightBuffer = NULL;
492
493 for (INT32 nChannel = 0; nChannel < 4; nChannel++) {
494 BurnFree(MSM6295ChannelData[nChip][nChannel]);
495 }
496
497 if (nChip == nLastMSM6295Chip) DebugSnd_MSM6295Initted = 0;
498 }
499
MSM6295Exit()500 void MSM6295Exit()
501 {
502 #if defined FBA_DEBUG
503 if (!DebugSnd_MSM6295Initted) bprintf(PRINT_ERROR, _T("MSM6295Exit called without init\n"));
504 #endif
505 for (INT32 nChip = 0; nChip <= nLastMSM6295Chip; nChip++)
506 {
507 MSM6295Exit(nChip);
508 }
509 }
510
MSM6295SetSamplerate(INT32 nChip,INT32 nSamplerate)511 void MSM6295SetSamplerate(INT32 nChip, INT32 nSamplerate)
512 {
513 MSM6295[nChip].nSampleRate = nSamplerate;
514 if (nBurnSoundRate > 0) {
515 MSM6295[nChip].nSampleSize = (nSamplerate << 12) / nBurnSoundRate;
516 } else {
517 MSM6295[nChip].nSampleSize = (nSamplerate << 12) / 11025;
518 }
519 }
520
MSM6295Init(INT32 nChip,INT32 nSamplerate,bool bAddSignal)521 INT32 MSM6295Init(INT32 nChip, INT32 nSamplerate, bool bAddSignal)
522 {
523 DebugSnd_MSM6295Initted = 1;
524
525 if (nBurnSoundRate > 0) {
526 if (pLeftBuffer == NULL) {
527 pLeftBuffer = (INT32*)BurnMalloc(nBurnSoundRate * sizeof(INT32));
528 }
529 if (pRightBuffer == NULL) {
530 pRightBuffer = (INT32*)BurnMalloc(nBurnSoundRate * sizeof(INT32));
531 }
532 }
533
534 if (nChip == 0) {
535 memset(&MSM6295, 0, sizeof(MSM6295));
536
537 bAdd = bAddSignal;
538 }
539
540 // Convert volume from percentage
541 MSM6295[nChip].nVolume = INT32(100.0 * 256.0 / 100.0 + 0.5);
542
543 MSM6295[nChip].nSampleRate = nSamplerate;
544 if (nBurnSoundRate > 0) {
545 MSM6295[nChip].nSampleSize = (nSamplerate << 12) / nBurnSoundRate;
546 } else {
547 MSM6295[nChip].nSampleSize = (nSamplerate << 12) / 11025;
548 }
549
550 MSM6295[nChip].nFractionalPosition = 0;
551
552 nMSM6295Status[nChip] = 0;
553 MSM6295[nChip].bIsCommand = false;
554
555 if (nChip == 0) {
556 nLastMSM6295Chip = 0;
557 } else {
558 if (nLastMSM6295Chip < nChip) {
559 nLastMSM6295Chip = nChip;
560 }
561 }
562
563 // Compute sample deltas
564 for (INT32 i = 0; i < 49; i++) {
565 INT32 nStep = (INT32)(pow(1.1, (double)i) * 16.0);
566 for (INT32 n = 0; n < 16; n++) {
567 INT32 nDelta = nStep >> 3;
568 if (n & 1) {
569 nDelta += nStep >> 2;
570 }
571 if (n & 2) {
572 nDelta += nStep >> 1;
573 }
574 if (n & 4) {
575 nDelta += nStep;
576 }
577 if (n & 8) {
578 nDelta = -nDelta;
579 }
580 MSM6295DeltaTable[(i << 4) + n] = nDelta;
581 }
582 }
583
584 // Compute volume levels
585 for (INT32 i = 0; i < 16; i++) {
586 double nVolume = 256.0;
587 for (INT32 n = i; n > 0; n--) {
588 nVolume /= 1.412537545;
589 }
590 MSM6295VolumeTable[i] = (UINT32)(nVolume + 0.5);
591 }
592
593 for (INT32 nChannel = 0; nChannel < 4; nChannel++) {
594 MSM6295ChannelData[nChip][nChannel] = (INT32*)BurnMalloc(0x1000 * sizeof(INT32));
595 }
596
597 MSM6295[nChip].nOutputDir = BURN_SND_ROUTE_BOTH;
598
599 memset (pBankPointer[nChip], 0, (0x40000/0x100) * sizeof(UINT8*));
600
601 MSM6295Reset(nChip);
602
603 return 0;
604 }
605
MSM6295SetRoute(INT32 nChip,double nVolume,INT32 nRouteDir)606 void MSM6295SetRoute(INT32 nChip, double nVolume, INT32 nRouteDir)
607 {
608 #if defined FBA_DEBUG
609 if (!DebugSnd_MSM6295Initted) bprintf(PRINT_ERROR, _T("MSM6295SetRoute called without init\n"));
610 if (nChip > nLastMSM6295Chip) bprintf(PRINT_ERROR, _T("MSM6295SetRoute called with invalid chip %i\n"), nChip);
611 #endif
612
613 MSM6295[nChip].nVolume = INT32(nVolume * 256.0 + 0.5);
614 MSM6295[nChip].nOutputDir = nRouteDir;
615 }
616