1 #include "burnint.h"
2 #include "burn_ym2608.h"
3 
4 void (*BurnYM2608Update)(INT16* pSoundBuf, INT32 nSegmentEnd);
5 
6 static INT32 (*BurnYM2608StreamCallback)(INT32 nSoundRate);
7 
8 static INT32 nBurnYM2608SoundRate;
9 
10 static INT16* pBuffer;
11 static INT16* pYM2608Buffer[6];
12 
13 static INT32* pAYBuffer;
14 
15 static INT32 nYM2608Position;
16 static INT32 nAY8910Position;
17 
18 static UINT32 nSampleSize;
19 static INT32 nFractionalPosition;
20 
21 static INT32 bYM2608AddSignal;
22 
23 static double YM2608Volumes[3];
24 static INT32 YM2608RouteDirs[3];
25 
26 // ----------------------------------------------------------------------------
27 // Dummy functions
28 
YM2608UpdateDummy(INT16 *,INT32)29 static void YM2608UpdateDummy(INT16*, INT32)
30 {
31 	return;
32 }
33 
YM2608StreamCallbackDummy(INT32)34 static INT32 YM2608StreamCallbackDummy(INT32)
35 {
36 	return 0;
37 }
38 
39 // ----------------------------------------------------------------------------
40 // Execute YM2608 for part of a frame
41 
AY8910Render(INT32 nSegmentLength)42 static void AY8910Render(INT32 nSegmentLength)
43 {
44 #if defined FBA_DEBUG
45 	if (!DebugSnd_YM2608Initted) bprintf(PRINT_ERROR, _T("BurnYM2608 AY8910Render called without init\n"));
46 #endif
47 
48 	if (nAY8910Position >= nSegmentLength) {
49 		return;
50 	}
51 
52 	nSegmentLength -= nAY8910Position;
53 
54 	pYM2608Buffer[2] = pBuffer + 2 * 4096 + 4 + nAY8910Position;
55 	pYM2608Buffer[3] = pBuffer + 3 * 4096 + 4 + nAY8910Position;
56 	pYM2608Buffer[4] = pBuffer + 4 * 4096 + 4 + nAY8910Position;
57 
58 	AY8910Update(0, &pYM2608Buffer[2], nSegmentLength);
59 
60 	nAY8910Position += nSegmentLength;
61 }
62 
YM2608Render(INT32 nSegmentLength)63 static void YM2608Render(INT32 nSegmentLength)
64 {
65 #if defined FBA_DEBUG
66 	if (!DebugSnd_YM2608Initted) bprintf(PRINT_ERROR, _T("YM2608Render called without init\n"));
67 #endif
68 
69 	if (nYM2608Position >= nSegmentLength) {
70 		return;
71 	}
72 
73 	nSegmentLength -= nYM2608Position;
74 
75 	pYM2608Buffer[0] = pBuffer + 0 * 4096 + 4 + nYM2608Position;
76 	pYM2608Buffer[1] = pBuffer + 1 * 4096 + 4 + nYM2608Position;
77 
78 	YM2608UpdateOne(0, &pYM2608Buffer[0], nSegmentLength);
79 
80 	nYM2608Position += nSegmentLength;
81 }
82 
83 // ----------------------------------------------------------------------------
84 // Update the sound buffer
85 
YM2608UpdateResample(INT16 * pSoundBuf,INT32 nSegmentEnd)86 static void YM2608UpdateResample(INT16* pSoundBuf, INT32 nSegmentEnd)
87 {
88 #if defined FBA_DEBUG
89 	if (!DebugSnd_YM2608Initted) bprintf(PRINT_ERROR, _T("YM2608UpdateResample called without init\n"));
90 #endif
91 
92 	INT32 nSegmentLength = nSegmentEnd;
93 	INT32 nSamplesNeeded = nSegmentEnd * nBurnYM2608SoundRate / nBurnSoundRate + 1;
94 
95 	if (nSamplesNeeded < nAY8910Position) {
96 		nSamplesNeeded = nAY8910Position;
97 	}
98 	if (nSamplesNeeded < nYM2608Position) {
99 		nSamplesNeeded = nYM2608Position;
100 	}
101 
102 	if (nSegmentLength > nBurnSoundLen) {
103 		nSegmentLength = nBurnSoundLen;
104 	}
105 	nSegmentLength <<= 1;
106 
107 	YM2608Render(nSamplesNeeded);
108 	AY8910Render(nSamplesNeeded);
109 
110 	pYM2608Buffer[0] = pBuffer + 0 * 4096 + 4;
111 	pYM2608Buffer[1] = pBuffer + 1 * 4096 + 4;
112 	pYM2608Buffer[2] = pBuffer + 2 * 4096 + 4;
113 	pYM2608Buffer[3] = pBuffer + 3 * 4096 + 4;
114 	pYM2608Buffer[4] = pBuffer + 4 * 4096 + 4;
115 	pYM2608Buffer[5] = pBuffer + 5 * 4096 + 4;
116 
117 	for (INT32 i = (nFractionalPosition >> 16) - 4; i < nSamplesNeeded; i++) {
118 		pYM2608Buffer[5][i] = (INT32)((pYM2608Buffer[2][i] + pYM2608Buffer[3][i] + pYM2608Buffer[4][i]) * YM2608Volumes[BURN_SND_YM2608_AY8910_ROUTE]);
119 	}
120 
121 	for (INT32 i = (nFractionalPosition & 0xFFFF0000) >> 15; i < nSegmentLength; i += 2, nFractionalPosition += nSampleSize) {
122 		INT32 nLeftSample[4] = {0, 0, 0, 0};
123 		INT32 nRightSample[4] = {0, 0, 0, 0};
124 		INT32 nTotalLeftSample, nTotalRightSample;
125 
126 		if ((YM2608RouteDirs[BURN_SND_YM2608_AY8910_ROUTE] & BURN_SND_ROUTE_LEFT) == BURN_SND_ROUTE_LEFT) {
127 			nLeftSample[0] += pYM2608Buffer[5][(nFractionalPosition >> 16) - 3];
128 			nLeftSample[1] += pYM2608Buffer[5][(nFractionalPosition >> 16) - 2];
129 			nLeftSample[2] += pYM2608Buffer[5][(nFractionalPosition >> 16) - 1];
130 			nLeftSample[3] += pYM2608Buffer[5][(nFractionalPosition >> 16) - 0];
131 		}
132 		if ((YM2608RouteDirs[BURN_SND_YM2608_AY8910_ROUTE] & BURN_SND_ROUTE_RIGHT) == BURN_SND_ROUTE_RIGHT) {
133 			nRightSample[0] += pYM2608Buffer[5][(nFractionalPosition >> 16) - 3];
134 			nRightSample[1] += pYM2608Buffer[5][(nFractionalPosition >> 16) - 2];
135 			nRightSample[2] += pYM2608Buffer[5][(nFractionalPosition >> 16) - 1];
136 			nRightSample[3] += pYM2608Buffer[5][(nFractionalPosition >> 16) - 0];
137 		}
138 
139 		if ((YM2608RouteDirs[BURN_SND_YM2608_YM2608_ROUTE_1] & BURN_SND_ROUTE_LEFT) == BURN_SND_ROUTE_LEFT) {
140 			nLeftSample[0] += (INT32)(pYM2608Buffer[0][(nFractionalPosition >> 16) - 3] * YM2608Volumes[BURN_SND_YM2608_YM2608_ROUTE_1]);
141 			nLeftSample[1] += (INT32)(pYM2608Buffer[0][(nFractionalPosition >> 16) - 2] * YM2608Volumes[BURN_SND_YM2608_YM2608_ROUTE_1]);
142 			nLeftSample[2] += (INT32)(pYM2608Buffer[0][(nFractionalPosition >> 16) - 1] * YM2608Volumes[BURN_SND_YM2608_YM2608_ROUTE_1]);
143 			nLeftSample[3] += (INT32)(pYM2608Buffer[0][(nFractionalPosition >> 16) - 0] * YM2608Volumes[BURN_SND_YM2608_YM2608_ROUTE_1]);
144 		}
145 		if ((YM2608RouteDirs[BURN_SND_YM2608_YM2608_ROUTE_1] & BURN_SND_ROUTE_RIGHT) == BURN_SND_ROUTE_RIGHT) {
146 			nRightSample[0] += (INT32)(pYM2608Buffer[0][(nFractionalPosition >> 16) - 3] * YM2608Volumes[BURN_SND_YM2608_YM2608_ROUTE_1]);
147 			nRightSample[1] += (INT32)(pYM2608Buffer[0][(nFractionalPosition >> 16) - 2] * YM2608Volumes[BURN_SND_YM2608_YM2608_ROUTE_1]);
148 			nRightSample[2] += (INT32)(pYM2608Buffer[0][(nFractionalPosition >> 16) - 1] * YM2608Volumes[BURN_SND_YM2608_YM2608_ROUTE_1]);
149 			nRightSample[3] += (INT32)(pYM2608Buffer[0][(nFractionalPosition >> 16) - 0] * YM2608Volumes[BURN_SND_YM2608_YM2608_ROUTE_1]);
150 		}
151 
152 		if ((YM2608RouteDirs[BURN_SND_YM2608_YM2608_ROUTE_2] & BURN_SND_ROUTE_LEFT) == BURN_SND_ROUTE_LEFT) {
153 			nLeftSample[0] += (INT32)(pYM2608Buffer[1][(nFractionalPosition >> 16) - 3] * YM2608Volumes[BURN_SND_YM2608_YM2608_ROUTE_2]);
154 			nLeftSample[1] += (INT32)(pYM2608Buffer[1][(nFractionalPosition >> 16) - 2] * YM2608Volumes[BURN_SND_YM2608_YM2608_ROUTE_2]);
155 			nLeftSample[2] += (INT32)(pYM2608Buffer[1][(nFractionalPosition >> 16) - 1] * YM2608Volumes[BURN_SND_YM2608_YM2608_ROUTE_2]);
156 			nLeftSample[3] += (INT32)(pYM2608Buffer[1][(nFractionalPosition >> 16) - 0] * YM2608Volumes[BURN_SND_YM2608_YM2608_ROUTE_2]);
157 		}
158 		if ((YM2608RouteDirs[BURN_SND_YM2608_YM2608_ROUTE_2] & BURN_SND_ROUTE_RIGHT) == BURN_SND_ROUTE_RIGHT) {
159 			nRightSample[0] += (INT32)(pYM2608Buffer[1][(nFractionalPosition >> 16) - 3] * YM2608Volumes[BURN_SND_YM2608_YM2608_ROUTE_2]);
160 			nRightSample[1] += (INT32)(pYM2608Buffer[1][(nFractionalPosition >> 16) - 2] * YM2608Volumes[BURN_SND_YM2608_YM2608_ROUTE_2]);
161 			nRightSample[2] += (INT32)(pYM2608Buffer[1][(nFractionalPosition >> 16) - 1] * YM2608Volumes[BURN_SND_YM2608_YM2608_ROUTE_2]);
162 			nRightSample[3] += (INT32)(pYM2608Buffer[1][(nFractionalPosition >> 16) - 0] * YM2608Volumes[BURN_SND_YM2608_YM2608_ROUTE_2]);
163 		}
164 
165 		nTotalLeftSample = INTERPOLATE4PS_16BIT((nFractionalPosition >> 4) & 0x0fff, nLeftSample[0], nLeftSample[1], nLeftSample[2], nLeftSample[3]);
166 		nTotalRightSample = INTERPOLATE4PS_16BIT((nFractionalPosition >> 4) & 0x0fff, nRightSample[0], nRightSample[1], nRightSample[2], nRightSample[3]);
167 
168 		nTotalLeftSample = BURN_SND_CLIP(nTotalLeftSample);
169 		nTotalRightSample = BURN_SND_CLIP(nTotalRightSample);
170 
171 		if (bYM2608AddSignal) {
172 			pSoundBuf[i + 0] += nTotalLeftSample;
173 			pSoundBuf[i + 1] += nTotalRightSample;
174 		} else {
175 			pSoundBuf[i + 0] = nTotalLeftSample;
176 			pSoundBuf[i + 1] = nTotalRightSample;
177 		}
178 	}
179 
180 	if (nSegmentEnd >= nBurnSoundLen) {
181 		INT32 nExtraSamples = nSamplesNeeded - (nFractionalPosition >> 16);
182 
183 		for (INT32 i = -4; i < nExtraSamples; i++) {
184 			pYM2608Buffer[0][i] = pYM2608Buffer[0][(nFractionalPosition >> 16) + i];
185 			pYM2608Buffer[1][i] = pYM2608Buffer[1][(nFractionalPosition >> 16) + i];
186 			pYM2608Buffer[2][i] = pYM2608Buffer[2][(nFractionalPosition >> 16) + i];
187 			pYM2608Buffer[3][i] = pYM2608Buffer[3][(nFractionalPosition >> 16) + i];
188 			pYM2608Buffer[4][i] = pYM2608Buffer[4][(nFractionalPosition >> 16) + i];
189 		}
190 
191 		nFractionalPosition &= 0xFFFF;
192 
193 		nYM2608Position = nExtraSamples;
194 		nAY8910Position = nExtraSamples;
195 
196 		dTime += 100.0 / nBurnFPS;
197 	}
198 }
199 
YM2608UpdateNormal(INT16 * pSoundBuf,INT32 nSegmentEnd)200 static void YM2608UpdateNormal(INT16* pSoundBuf, INT32 nSegmentEnd)
201 {
202 #if defined FBA_DEBUG
203 	if (!DebugSnd_YM2608Initted) bprintf(PRINT_ERROR, _T("YM2608UpdateNormal called without init\n"));
204 #endif
205 
206 	INT32 nSegmentLength = nSegmentEnd;
207 
208 	if (nSegmentEnd < nAY8910Position) {
209 		nSegmentEnd = nAY8910Position;
210 	}
211 	if (nSegmentEnd < nYM2608Position) {
212 		nSegmentEnd = nYM2608Position;
213 	}
214 
215 	if (nSegmentLength > nBurnSoundLen) {
216 		nSegmentLength = nBurnSoundLen;
217 	}
218 
219 	YM2608Render(nSegmentEnd);
220 	AY8910Render(nSegmentEnd);
221 
222 	pYM2608Buffer[0] = pBuffer + 4 + 0 * 4096;
223 	pYM2608Buffer[1] = pBuffer + 4 + 1 * 4096;
224 	pYM2608Buffer[2] = pBuffer + 4 + 2 * 4096;
225 	pYM2608Buffer[3] = pBuffer + 4 + 3 * 4096;
226 	pYM2608Buffer[4] = pBuffer + 4 + 4 * 4096;
227 
228 	for (INT32 n = nFractionalPosition; n < nSegmentLength; n++) {
229 		INT32 nAYSample, nLeftSample = 0, nRightSample = 0;
230 
231 		nAYSample  = pYM2608Buffer[2][n];
232 		nAYSample += pYM2608Buffer[3][n];
233 		nAYSample += pYM2608Buffer[4][n];
234 
235 		if ((YM2608RouteDirs[BURN_SND_YM2608_AY8910_ROUTE] & BURN_SND_ROUTE_LEFT) == BURN_SND_ROUTE_LEFT) {
236 			nLeftSample += (INT32)(nAYSample * YM2608Volumes[BURN_SND_YM2608_AY8910_ROUTE]);
237 		}
238 		if ((YM2608RouteDirs[BURN_SND_YM2608_AY8910_ROUTE] & BURN_SND_ROUTE_RIGHT) == BURN_SND_ROUTE_RIGHT) {
239 			nRightSample += (INT32)(nAYSample * YM2608Volumes[BURN_SND_YM2608_AY8910_ROUTE]);
240 		}
241 
242 		if ((YM2608RouteDirs[BURN_SND_YM2608_YM2608_ROUTE_1] & BURN_SND_ROUTE_LEFT) == BURN_SND_ROUTE_LEFT) {
243 			nLeftSample += (INT32)(pYM2608Buffer[0][n] * YM2608Volumes[BURN_SND_YM2608_YM2608_ROUTE_1]);
244 		}
245 		if ((YM2608RouteDirs[BURN_SND_YM2608_YM2608_ROUTE_1] & BURN_SND_ROUTE_RIGHT) == BURN_SND_ROUTE_RIGHT) {
246 			nRightSample += (INT32)(pYM2608Buffer[0][n] * YM2608Volumes[BURN_SND_YM2608_YM2608_ROUTE_1]);
247 		}
248 
249 		if ((YM2608RouteDirs[BURN_SND_YM2608_YM2608_ROUTE_2] & BURN_SND_ROUTE_LEFT) == BURN_SND_ROUTE_LEFT) {
250 			nLeftSample += (INT32)(pYM2608Buffer[1][n] * YM2608Volumes[BURN_SND_YM2608_YM2608_ROUTE_2]);
251 		}
252 		if ((YM2608RouteDirs[BURN_SND_YM2608_YM2608_ROUTE_2] & BURN_SND_ROUTE_RIGHT) == BURN_SND_ROUTE_RIGHT) {
253 			nRightSample += (INT32)(pYM2608Buffer[1][n] * YM2608Volumes[BURN_SND_YM2608_YM2608_ROUTE_2]);
254 		}
255 
256 		nLeftSample = BURN_SND_CLIP(nLeftSample);
257 		nRightSample = BURN_SND_CLIP(nRightSample);
258 
259 		if (bYM2608AddSignal) {
260 			pSoundBuf[(n << 1) + 0] += nLeftSample;
261 			pSoundBuf[(n << 1) + 1] += nRightSample;
262 		} else {
263 			pSoundBuf[(n << 1) + 0] = nLeftSample;
264 			pSoundBuf[(n << 1) + 1] = nRightSample;
265 		}
266 	}
267 
268 	nFractionalPosition = nSegmentLength;
269 
270 	if (nSegmentEnd >= nBurnSoundLen) {
271 		INT32 nExtraSamples = nSegmentEnd - nBurnSoundLen;
272 
273 		for (INT32 i = 0; i < nExtraSamples; i++) {
274 			pYM2608Buffer[0][i] = pYM2608Buffer[0][nBurnSoundLen + i];
275 			pYM2608Buffer[1][i] = pYM2608Buffer[1][nBurnSoundLen + i];
276 			pYM2608Buffer[2][i] = pYM2608Buffer[2][nBurnSoundLen + i];
277 			pYM2608Buffer[3][i] = pYM2608Buffer[3][nBurnSoundLen + i];
278 			pYM2608Buffer[4][i] = pYM2608Buffer[4][nBurnSoundLen + i];
279 		}
280 
281 		nFractionalPosition = 0;
282 
283 		nYM2608Position = nExtraSamples;
284 		nAY8910Position = nExtraSamples;
285 
286 		dTime += 100.0 / nBurnFPS;
287 	}
288 }
289 
290 // ----------------------------------------------------------------------------
291 // Callbacks for YM2608 core
292 
BurnYM2608UpdateRequest()293 void BurnYM2608UpdateRequest()
294 {
295 #if defined FBA_DEBUG
296 	if (!DebugSnd_YM2608Initted) bprintf(PRINT_ERROR, _T("BurnYM2608UpdateRequest called without init\n"));
297 #endif
298 
299 	YM2608Render(BurnYM2608StreamCallback(nBurnYM2608SoundRate));
300 }
301 
BurnAY8910UpdateRequest()302 static void BurnAY8910UpdateRequest()
303 {
304 #if defined FBA_DEBUG
305 	if (!DebugSnd_YM2608Initted) bprintf(PRINT_ERROR, _T("BurnYM2608 BurnAY8910UpdateRequest called without init\n"));
306 #endif
307 
308 	AY8910Render(BurnYM2608StreamCallback(nBurnYM2608SoundRate));
309 }
310 
311 // ----------------------------------------------------------------------------
312 // Initialisation, etc.
313 
BurnYM2608Reset()314 void BurnYM2608Reset()
315 {
316 #if defined FBA_DEBUG
317 	if (!DebugSnd_YM2608Initted) bprintf(PRINT_ERROR, _T("BurnYM2608Reset called without init\n"));
318 #endif
319 
320 	BurnTimerReset();
321 
322 	YM2608ResetChip(0);
323 }
324 
BurnYM2608Exit()325 void BurnYM2608Exit()
326 {
327 #if defined FBA_DEBUG
328 	if (!DebugSnd_YM2608Initted) bprintf(PRINT_ERROR, _T("BurnYM2608Exit called without init\n"));
329 #endif
330 
331 	if (!DebugSnd_YM2608Initted) return;
332 
333 	YM2608Shutdown();
334 	AY8910Exit(0);
335 
336 	BurnTimerExit();
337 
338 	BurnFree(pBuffer);
339 	BurnFree(pAYBuffer);
340 
341 	bYM2608AddSignal = 0;
342 
343 	DebugSnd_YM2608Initted = 0;
344 }
345 
BurnYM2608Init(INT32 nClockFrequency,UINT8 * YM2608ADPCMROM,INT32 * nYM2608ADPCMSize,UINT8 * YM2608IROM,FM_IRQHANDLER IRQCallback,INT32 bAddSignal)346 INT32 BurnYM2608Init(INT32 nClockFrequency, UINT8* YM2608ADPCMROM, INT32* nYM2608ADPCMSize, UINT8* YM2608IROM, FM_IRQHANDLER IRQCallback, INT32 bAddSignal)
347 {
348 	return BurnYM2608Init(nClockFrequency, YM2608ADPCMROM, nYM2608ADPCMSize, YM2608IROM, IRQCallback, BurnSynchroniseStream, BurnGetTime, bAddSignal);
349 }
350 
BurnYM2608Init(INT32 nClockFrequency,UINT8 * YM2608ADPCMROM,INT32 * nYM2608ADPCMSize,UINT8 * YM2608IROM,FM_IRQHANDLER IRQCallback,INT32 (* StreamCallback)(INT32),double (* GetTimeCallback)(),INT32 bAddSignal)351 INT32 BurnYM2608Init(INT32 nClockFrequency, UINT8* YM2608ADPCMROM, INT32* nYM2608ADPCMSize, UINT8* YM2608IROM, FM_IRQHANDLER IRQCallback, INT32 (*StreamCallback)(INT32), double (*GetTimeCallback)(), INT32 bAddSignal)
352 {
353 	DebugSnd_YM2608Initted = 1;
354 
355 	BurnTimerInit(&YM2608TimerOver, GetTimeCallback);
356 
357 	if (nBurnSoundRate <= 0) {
358 		BurnYM2608StreamCallback = YM2608StreamCallbackDummy;
359 
360 		BurnYM2608Update = YM2608UpdateDummy;
361 
362 		AY8910InitYM(0, nClockFrequency, 11025, NULL, NULL, NULL, NULL, BurnAY8910UpdateRequest);
363 		YM2608Init(1, nClockFrequency, 11025, (void**)(&YM2608ADPCMROM), nYM2608ADPCMSize, YM2608IROM, &BurnOPNTimerCallback, IRQCallback);
364 		return 0;
365 	}
366 
367 	BurnYM2608StreamCallback = StreamCallback;
368 
369 	if (nFMInterpolation == 3) {
370 		// Set YM2608 core samplerate to match the hardware
371 		nBurnYM2608SoundRate = nClockFrequency / 144;
372 		// Bring YM2608 core samplerate within usable range
373 		while (nBurnYM2608SoundRate > nBurnSoundRate * 3) {
374 			nBurnYM2608SoundRate >>= 1;
375 		}
376 
377 		BurnYM2608Update = YM2608UpdateResample;
378 
379 		nSampleSize = (UINT32)nBurnYM2608SoundRate * (1 << 16) / nBurnSoundRate;
380 		nFractionalPosition = 0;
381 	} else {
382 		nBurnYM2608SoundRate = nBurnSoundRate;
383 
384 		BurnYM2608Update = YM2608UpdateNormal;
385 	}
386 
387 	AY8910InitYM(0, nClockFrequency, nBurnYM2608SoundRate, NULL, NULL, NULL, NULL, BurnAY8910UpdateRequest);
388 	YM2608Init(1, nClockFrequency, nBurnYM2608SoundRate, (void**)(&YM2608ADPCMROM), nYM2608ADPCMSize, YM2608IROM, &BurnOPNTimerCallback, IRQCallback);
389 
390 	pBuffer = (INT16*)BurnMalloc(4096 * 6 * sizeof(INT16));
391 	memset(pBuffer, 0, 4096 * 6 * sizeof(INT16));
392 
393 	pAYBuffer = (INT32*)BurnMalloc(4096 * sizeof(INT32));
394 	memset(pAYBuffer, 0, 4096 * sizeof(INT32));
395 
396 	nYM2608Position = 0;
397 	nAY8910Position = 0;
398 
399 	bYM2608AddSignal = bAddSignal;
400 
401 	// default routes
402 	YM2608Volumes[BURN_SND_YM2608_YM2608_ROUTE_1] = 1.00;
403 	YM2608Volumes[BURN_SND_YM2608_YM2608_ROUTE_2] = 1.00;
404 	YM2608Volumes[BURN_SND_YM2608_AY8910_ROUTE] = 1.00;
405 	YM2608RouteDirs[BURN_SND_YM2608_YM2608_ROUTE_1] = BURN_SND_ROUTE_LEFT;
406 	YM2608RouteDirs[BURN_SND_YM2608_YM2608_ROUTE_2] = BURN_SND_ROUTE_RIGHT;
407 	YM2608RouteDirs[BURN_SND_YM2608_AY8910_ROUTE] = BURN_SND_ROUTE_BOTH;
408 
409 	return 0;
410 }
411 
BurnYM2608SetRoute(INT32 nIndex,double nVolume,INT32 nRouteDir)412 void BurnYM2608SetRoute(INT32 nIndex, double nVolume, INT32 nRouteDir)
413 {
414 #if defined FBA_DEBUG
415 	if (!DebugSnd_YM2608Initted) bprintf(PRINT_ERROR, _T("BurnYM2608SetRoute called without init\n"));
416 	if (nIndex < 0 || nIndex > 2) bprintf(PRINT_ERROR, _T("BurnYM2608SetRoute called with invalid index %i\n"), nIndex);
417 #endif
418 
419 	YM2608Volumes[nIndex] = nVolume;
420 	YM2608RouteDirs[nIndex] = nRouteDir;
421 }
422 
BurnYM2608Scan(INT32 nAction,INT32 * pnMin)423 void BurnYM2608Scan(INT32 nAction, INT32* pnMin)
424 {
425 #if defined FBA_DEBUG
426 	if (!DebugSnd_YM2608Initted) bprintf(PRINT_ERROR, _T("BurnYM2608Scan called without init\n"));
427 #endif
428 
429 	BurnTimerScan(nAction, pnMin);
430 	AY8910Scan(nAction, pnMin);
431 
432 	if (nAction & ACB_DRIVER_DATA) {
433 		SCAN_VAR(nYM2608Position);
434 		SCAN_VAR(nAY8910Position);
435 	}
436 }
437