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