1 #include "burnint.h"
2 #include "burn_ym2203.h"
3 
4 #define MAX_YM2203	3
5 
6 void (*BurnYM2203Update)(INT16* pSoundBuf, INT32 nSegmentEnd);
7 
8 static INT32 (*BurnYM2203StreamCallback)(INT32 nSoundRate);
9 
10 static INT32 nBurnYM2203SoundRate;
11 
12 static INT16* pBuffer;
13 static INT16* pYM2203Buffer[4 * MAX_YM2203];
14 
15 static INT32 nYM2203Position;
16 static INT32 nAY8910Position;
17 
18 static UINT32 nSampleSize;
19 static INT32 nFractionalPosition;
20 
21 static INT32 nNumChips = 0;
22 
23 static INT32 bYM2203AddSignal;
24 
25 static double YM2203Volumes[4 * MAX_YM2203];
26 static INT32 YM2203RouteDirs[4 * MAX_YM2203];
27 
28 static double YM2203LeftVolumes[4 * MAX_YM2203];
29 static double YM2203RightVolumes[4 * MAX_YM2203];
30 
31 INT32 bYM2203UseSeperateVolumes; // support custom Taito panning hardware
32 
33 // ----------------------------------------------------------------------------
34 // Dummy functions
35 
YM2203UpdateDummy(INT16 *,INT32)36 static void YM2203UpdateDummy(INT16*, INT32)
37 {
38 	return;
39 }
40 
YM2203StreamCallbackDummy(INT32)41 static INT32 YM2203StreamCallbackDummy(INT32)
42 {
43 	return 0;
44 }
45 
46 // ----------------------------------------------------------------------------
47 // Execute YM2203 for part of a frame
48 
AY8910Render(INT32 nSegmentLength)49 static void AY8910Render(INT32 nSegmentLength)
50 {
51 #if defined FBA_DEBUG
52 	if (!DebugSnd_YM2203Initted) bprintf(PRINT_ERROR, _T("BurnYM2203 AY8910Render called without init\n"));
53 #endif
54 
55 	if (nAY8910Position >= nSegmentLength) {
56 		return;
57 	}
58 
59 	nSegmentLength -= nAY8910Position;
60 
61 	pYM2203Buffer[1] = pBuffer + 1 * 4096 + 4 + nAY8910Position;
62 	pYM2203Buffer[2] = pBuffer + 2 * 4096 + 4 + nAY8910Position;
63 	pYM2203Buffer[3] = pBuffer + 3 * 4096 + 4 + nAY8910Position;
64 
65 	AY8910Update(0, &pYM2203Buffer[1], nSegmentLength);
66 
67 	if (nNumChips > 1) {
68 		pYM2203Buffer[5] = pBuffer + 5 * 4096 + 4 + nAY8910Position;
69 		pYM2203Buffer[6] = pBuffer + 6 * 4096 + 4 + nAY8910Position;
70 		pYM2203Buffer[7] = pBuffer + 7 * 4096 + 4 + nAY8910Position;
71 
72 		AY8910Update(1, &pYM2203Buffer[5], nSegmentLength);
73 	}
74 
75 	if (nNumChips > 2) {
76 		pYM2203Buffer[9] = pBuffer + 9 * 4096 + 4 + nAY8910Position;
77 		pYM2203Buffer[10] = pBuffer + 10 * 4096 + 4 + nAY8910Position;
78 		pYM2203Buffer[11] = pBuffer + 11 * 4096 + 4 + nAY8910Position;
79 
80 		AY8910Update(2, &pYM2203Buffer[9], nSegmentLength);
81 	}
82 
83 	nAY8910Position += nSegmentLength;
84 }
85 
YM2203Render(INT32 nSegmentLength)86 static void YM2203Render(INT32 nSegmentLength)
87 {
88 #if defined FBA_DEBUG
89 	if (!DebugSnd_YM2203Initted) bprintf(PRINT_ERROR, _T("YM2203Render called without init\n"));
90 #endif
91 
92 	if (nYM2203Position >= nSegmentLength) {
93 		return;
94 	}
95 
96 	nSegmentLength -= nYM2203Position;
97 
98 	pYM2203Buffer[0] = pBuffer + 0 * 4096 + 4 + nYM2203Position;
99 
100 	YM2203UpdateOne(0, pYM2203Buffer[0], nSegmentLength);
101 
102 	if (nNumChips > 1) {
103 		pYM2203Buffer[4] = pBuffer + 4 * 4096 + 4 + nYM2203Position;
104 
105 		YM2203UpdateOne(1, pYM2203Buffer[4], nSegmentLength);
106 	}
107 
108 	if (nNumChips > 2) {
109 		pYM2203Buffer[8] = pBuffer + 8 * 4096 + 4 + nYM2203Position;
110 
111 		YM2203UpdateOne(2, pYM2203Buffer[8], nSegmentLength);
112 	}
113 
114 	nYM2203Position += nSegmentLength;
115 }
116 
117 // ----------------------------------------------------------------------------
118 // Update the sound buffer
119 
120 #define INTERPOLATE_ADD_SOUND_LEFT(route, buffer)																	\
121 	if ((YM2203RouteDirs[route] & BURN_SND_ROUTE_LEFT) == BURN_SND_ROUTE_LEFT) {									\
122 		nLeftSample[0] += (INT32)(pYM2203Buffer[buffer][(nFractionalPosition >> 16) - 3] * YM2203Volumes[route]);	\
123 		nLeftSample[1] += (INT32)(pYM2203Buffer[buffer][(nFractionalPosition >> 16) - 2] * YM2203Volumes[route]);	\
124 		nLeftSample[2] += (INT32)(pYM2203Buffer[buffer][(nFractionalPosition >> 16) - 1] * YM2203Volumes[route]);	\
125 		nLeftSample[3] += (INT32)(pYM2203Buffer[buffer][(nFractionalPosition >> 16) - 0] * YM2203Volumes[route]);	\
126 	}
127 
128 #define INTERPOLATE_ADD_SOUND_RIGHT(route, buffer)																	\
129 	if ((YM2203RouteDirs[route] & BURN_SND_ROUTE_RIGHT) == BURN_SND_ROUTE_RIGHT) {									\
130 		nRightSample[0] += (INT32)(pYM2203Buffer[buffer][(nFractionalPosition >> 16) - 3] * YM2203Volumes[route]);	\
131 		nRightSample[1] += (INT32)(pYM2203Buffer[buffer][(nFractionalPosition >> 16) - 2] * YM2203Volumes[route]);	\
132 		nRightSample[2] += (INT32)(pYM2203Buffer[buffer][(nFractionalPosition >> 16) - 1] * YM2203Volumes[route]);	\
133 		nRightSample[3] += (INT32)(pYM2203Buffer[buffer][(nFractionalPosition >> 16) - 0] * YM2203Volumes[route]);	\
134 	}
135 
136 #define SPLIT_INTERPOLATE_ADD_SOUND_LEFT(route, buffer)																\
137 	nLeftSample[0] += (INT32)(pYM2203Buffer[buffer][(nFractionalPosition >> 16) - 3] * YM2203LeftVolumes[route]);	\
138 	nLeftSample[1] += (INT32)(pYM2203Buffer[buffer][(nFractionalPosition >> 16) - 2] * YM2203LeftVolumes[route]);	\
139 	nLeftSample[2] += (INT32)(pYM2203Buffer[buffer][(nFractionalPosition >> 16) - 1] * YM2203LeftVolumes[route]);	\
140 	nLeftSample[3] += (INT32)(pYM2203Buffer[buffer][(nFractionalPosition >> 16) - 0] * YM2203LeftVolumes[route]);
141 
142 #define SPLIT_INTERPOLATE_ADD_SOUND_RIGHT(route, buffer)																\
143 	nRightSample[0] += (INT32)(pYM2203Buffer[buffer][(nFractionalPosition >> 16) - 3] * YM2203RightVolumes[route]);	\
144 	nRightSample[1] += (INT32)(pYM2203Buffer[buffer][(nFractionalPosition >> 16) - 2] * YM2203RightVolumes[route]);	\
145 	nRightSample[2] += (INT32)(pYM2203Buffer[buffer][(nFractionalPosition >> 16) - 1] * YM2203RightVolumes[route]);	\
146 	nRightSample[3] += (INT32)(pYM2203Buffer[buffer][(nFractionalPosition >> 16) - 0] * YM2203RightVolumes[route]);
147 
YM2203UpdateResample(INT16 * pSoundBuf,INT32 nSegmentEnd)148 static void YM2203UpdateResample(INT16* pSoundBuf, INT32 nSegmentEnd)
149 {
150 #if defined FBA_DEBUG
151 	if (!DebugSnd_YM2203Initted) bprintf(PRINT_ERROR, _T("YM2203UpdateResample called without init\n"));
152 #endif
153 
154 	INT32 nSegmentLength = nSegmentEnd;
155 	INT32 nSamplesNeeded = nSegmentEnd * nBurnYM2203SoundRate / nBurnSoundRate + 1;
156 
157 	if (nSamplesNeeded < nAY8910Position) {
158 		nSamplesNeeded = nAY8910Position;
159 	}
160 	if (nSamplesNeeded < nYM2203Position) {
161 		nSamplesNeeded = nYM2203Position;
162 	}
163 
164 	if (nSegmentLength > nBurnSoundLen) {
165 		nSegmentLength = nBurnSoundLen;
166 	}
167 	nSegmentLength <<= 1;
168 
169 	YM2203Render(nSamplesNeeded);
170 	AY8910Render(nSamplesNeeded);
171 
172 	pYM2203Buffer[0] = pBuffer + 0 * 4096 + 4;
173 	pYM2203Buffer[1] = pBuffer + 1 * 4096 + 4;
174 	pYM2203Buffer[2] = pBuffer + 2 * 4096 + 4;
175 	pYM2203Buffer[3] = pBuffer + 3 * 4096 + 4;
176 
177 	if (nNumChips > 1) {
178 		pYM2203Buffer[4] = pBuffer + 4 * 4096 + 4;
179 		pYM2203Buffer[5] = pBuffer + 5 * 4096 + 4;
180 		pYM2203Buffer[6] = pBuffer + 6 * 4096 + 4;
181 		pYM2203Buffer[7] = pBuffer + 7 * 4096 + 4;
182 	}
183 
184 	if (nNumChips > 2) {
185 		pYM2203Buffer[8] = pBuffer + 8 * 4096 + 4;
186 		pYM2203Buffer[9] = pBuffer + 9 * 4096 + 4;
187 		pYM2203Buffer[10] = pBuffer + 10 * 4096 + 4;
188 		pYM2203Buffer[11] = pBuffer + 11 * 4096 + 4;
189 	}
190 
191 	for (INT32 i = (nFractionalPosition & 0xFFFF0000) >> 15; i < nSegmentLength; i += 2, nFractionalPosition += nSampleSize) {
192 		INT32 nLeftSample[4] = {0, 0, 0, 0};
193 		INT32 nRightSample[4] = {0, 0, 0, 0};
194 		INT32 nTotalLeftSample, nTotalRightSample;
195 
196 		if (bYM2203UseSeperateVolumes) {
197 			SPLIT_INTERPOLATE_ADD_SOUND_LEFT  (BURN_SND_YM2203_AY8910_ROUTE_1, 1)
198 			SPLIT_INTERPOLATE_ADD_SOUND_LEFT  (BURN_SND_YM2203_AY8910_ROUTE_2, 2)
199 			SPLIT_INTERPOLATE_ADD_SOUND_LEFT  (BURN_SND_YM2203_AY8910_ROUTE_3, 3)
200 			SPLIT_INTERPOLATE_ADD_SOUND_LEFT  (BURN_SND_YM2203_YM2203_ROUTE  , 0)
201 
202 			SPLIT_INTERPOLATE_ADD_SOUND_RIGHT (BURN_SND_YM2203_AY8910_ROUTE_1, 1)
203 			SPLIT_INTERPOLATE_ADD_SOUND_RIGHT (BURN_SND_YM2203_AY8910_ROUTE_2, 2)
204 			SPLIT_INTERPOLATE_ADD_SOUND_RIGHT (BURN_SND_YM2203_AY8910_ROUTE_3, 3)
205 			SPLIT_INTERPOLATE_ADD_SOUND_RIGHT (BURN_SND_YM2203_YM2203_ROUTE  , 0)
206 
207 			if (nNumChips > 1) {
208 				SPLIT_INTERPOLATE_ADD_SOUND_LEFT  (4 + BURN_SND_YM2203_AY8910_ROUTE_1, 5)
209 				SPLIT_INTERPOLATE_ADD_SOUND_LEFT  (4 + BURN_SND_YM2203_AY8910_ROUTE_2, 6)
210 				SPLIT_INTERPOLATE_ADD_SOUND_LEFT  (4 + BURN_SND_YM2203_AY8910_ROUTE_3, 7)
211 				SPLIT_INTERPOLATE_ADD_SOUND_LEFT  (4 + BURN_SND_YM2203_YM2203_ROUTE  , 4)
212 
213 				SPLIT_INTERPOLATE_ADD_SOUND_RIGHT (4 + BURN_SND_YM2203_AY8910_ROUTE_1, 5)
214 				SPLIT_INTERPOLATE_ADD_SOUND_RIGHT (4 + BURN_SND_YM2203_AY8910_ROUTE_2, 6)
215 				SPLIT_INTERPOLATE_ADD_SOUND_RIGHT (4 + BURN_SND_YM2203_AY8910_ROUTE_3, 7)
216 				SPLIT_INTERPOLATE_ADD_SOUND_RIGHT (4 + BURN_SND_YM2203_YM2203_ROUTE  , 4)
217 			}
218 
219 			if (nNumChips > 2) {
220 				SPLIT_INTERPOLATE_ADD_SOUND_LEFT  (8 + BURN_SND_YM2203_AY8910_ROUTE_1, 9)
221 				SPLIT_INTERPOLATE_ADD_SOUND_LEFT  (8 + BURN_SND_YM2203_AY8910_ROUTE_2, 10)
222 				SPLIT_INTERPOLATE_ADD_SOUND_LEFT  (8 + BURN_SND_YM2203_AY8910_ROUTE_3, 11)
223 				SPLIT_INTERPOLATE_ADD_SOUND_LEFT  (8 + BURN_SND_YM2203_YM2203_ROUTE  , 8)
224 
225 				SPLIT_INTERPOLATE_ADD_SOUND_RIGHT (8 + BURN_SND_YM2203_AY8910_ROUTE_1, 9)
226 				SPLIT_INTERPOLATE_ADD_SOUND_RIGHT (8 + BURN_SND_YM2203_AY8910_ROUTE_2, 10)
227 				SPLIT_INTERPOLATE_ADD_SOUND_RIGHT (8 + BURN_SND_YM2203_AY8910_ROUTE_3, 11)
228 				SPLIT_INTERPOLATE_ADD_SOUND_RIGHT (8 + BURN_SND_YM2203_YM2203_ROUTE  , 8)
229 			}
230 		} else {
231 			INTERPOLATE_ADD_SOUND_LEFT  (BURN_SND_YM2203_AY8910_ROUTE_1, 1)
232 			INTERPOLATE_ADD_SOUND_RIGHT (BURN_SND_YM2203_AY8910_ROUTE_1, 1)
233 			INTERPOLATE_ADD_SOUND_LEFT  (BURN_SND_YM2203_AY8910_ROUTE_2, 2)
234 			INTERPOLATE_ADD_SOUND_RIGHT (BURN_SND_YM2203_AY8910_ROUTE_2, 2)
235 			INTERPOLATE_ADD_SOUND_LEFT  (BURN_SND_YM2203_AY8910_ROUTE_3, 3)
236 			INTERPOLATE_ADD_SOUND_RIGHT (BURN_SND_YM2203_AY8910_ROUTE_3, 3)
237 			INTERPOLATE_ADD_SOUND_LEFT  (BURN_SND_YM2203_YM2203_ROUTE  , 0)
238 			INTERPOLATE_ADD_SOUND_RIGHT (BURN_SND_YM2203_YM2203_ROUTE  , 0)
239 
240 			if (nNumChips > 1) {
241 				INTERPOLATE_ADD_SOUND_LEFT  (4 + BURN_SND_YM2203_AY8910_ROUTE_1, 5)
242 				INTERPOLATE_ADD_SOUND_RIGHT (4 + BURN_SND_YM2203_AY8910_ROUTE_1, 5)
243 				INTERPOLATE_ADD_SOUND_LEFT  (4 + BURN_SND_YM2203_AY8910_ROUTE_2, 6)
244 				INTERPOLATE_ADD_SOUND_RIGHT (4 + BURN_SND_YM2203_AY8910_ROUTE_2, 6)
245 				INTERPOLATE_ADD_SOUND_LEFT  (4 + BURN_SND_YM2203_AY8910_ROUTE_3, 7)
246 				INTERPOLATE_ADD_SOUND_RIGHT (4 + BURN_SND_YM2203_AY8910_ROUTE_3, 7)
247 				INTERPOLATE_ADD_SOUND_LEFT  (4 + BURN_SND_YM2203_YM2203_ROUTE  , 4)
248 				INTERPOLATE_ADD_SOUND_RIGHT (4 + BURN_SND_YM2203_YM2203_ROUTE  , 4)
249 			}
250 
251 			if (nNumChips > 2) {
252 				INTERPOLATE_ADD_SOUND_LEFT  (8 + BURN_SND_YM2203_AY8910_ROUTE_1, 9)
253 				INTERPOLATE_ADD_SOUND_RIGHT (8 + BURN_SND_YM2203_AY8910_ROUTE_1, 9)
254 				INTERPOLATE_ADD_SOUND_LEFT  (8 + BURN_SND_YM2203_AY8910_ROUTE_2, 10)
255 				INTERPOLATE_ADD_SOUND_RIGHT (8 + BURN_SND_YM2203_AY8910_ROUTE_2, 10)
256 				INTERPOLATE_ADD_SOUND_LEFT  (8 + BURN_SND_YM2203_AY8910_ROUTE_3, 11)
257 				INTERPOLATE_ADD_SOUND_RIGHT (8 + BURN_SND_YM2203_AY8910_ROUTE_3, 11)
258 				INTERPOLATE_ADD_SOUND_LEFT  (8 + BURN_SND_YM2203_YM2203_ROUTE  , 8)
259 				INTERPOLATE_ADD_SOUND_RIGHT (8 + BURN_SND_YM2203_YM2203_ROUTE  , 8)
260 			}
261 		}
262 
263 		nTotalLeftSample = INTERPOLATE4PS_CUSTOM((nFractionalPosition >> 4) & 0x0fff, nLeftSample[0], nLeftSample[1], nLeftSample[2], nLeftSample[3], 16384.0);
264 		nTotalRightSample = INTERPOLATE4PS_CUSTOM((nFractionalPosition >> 4) & 0x0fff, nRightSample[0], nRightSample[1], nRightSample[2], nRightSample[3], 16384.0);
265 
266 		nTotalLeftSample = BURN_SND_CLIP(nTotalLeftSample);
267 		nTotalRightSample = BURN_SND_CLIP(nTotalRightSample);
268 
269 		if (bYM2203AddSignal) {
270 			//pSoundBuf[i + 0] += nTotalLeftSample;
271 			//pSoundBuf[i + 1] += nTotalRightSample;
272 			pSoundBuf[i + 0] = BURN_SND_CLIP(pSoundBuf[i + 0] + nTotalLeftSample);
273 			pSoundBuf[i + 1] = BURN_SND_CLIP(pSoundBuf[i + 1] + nTotalRightSample);
274 		} else {
275 			pSoundBuf[i + 0] = nTotalLeftSample;
276 			pSoundBuf[i + 1] = nTotalRightSample;
277 		}
278 
279 	}
280 
281 	if (nSegmentEnd >= nBurnSoundLen) {
282 		INT32 nExtraSamples = nSamplesNeeded - (nFractionalPosition >> 16);
283 
284 		for (INT32 i = -4; i < nExtraSamples; i++) {
285 			pYM2203Buffer[0][i] = pYM2203Buffer[0][(nFractionalPosition >> 16) + i];
286 			pYM2203Buffer[1][i] = pYM2203Buffer[1][(nFractionalPosition >> 16) + i];
287 			pYM2203Buffer[2][i] = pYM2203Buffer[2][(nFractionalPosition >> 16) + i];
288 			pYM2203Buffer[3][i] = pYM2203Buffer[3][(nFractionalPosition >> 16) + i];
289 
290 			if (nNumChips > 1) {
291 				pYM2203Buffer[4][i] = pYM2203Buffer[4][(nFractionalPosition >> 16) + i];
292 				pYM2203Buffer[5][i] = pYM2203Buffer[5][(nFractionalPosition >> 16) + i];
293 				pYM2203Buffer[6][i] = pYM2203Buffer[6][(nFractionalPosition >> 16) + i];
294 				pYM2203Buffer[7][i] = pYM2203Buffer[7][(nFractionalPosition >> 16) + i];
295 			}
296 
297 			if (nNumChips > 2) {
298 				pYM2203Buffer[8][i] = pYM2203Buffer[8][(nFractionalPosition >> 16) + i];
299 				pYM2203Buffer[9][i] = pYM2203Buffer[9][(nFractionalPosition >> 16) + i];
300 				pYM2203Buffer[10][i] = pYM2203Buffer[10][(nFractionalPosition >> 16) + i];
301 				pYM2203Buffer[11][i] = pYM2203Buffer[11][(nFractionalPosition >> 16) + i];
302 			}
303 		}
304 
305 		nFractionalPosition &= 0xFFFF;
306 
307 		nYM2203Position = nExtraSamples;
308 		nAY8910Position = nExtraSamples;
309 
310 		dTime += 100.0 / nBurnFPS;
311 	}
312 }
313 
YM2203UpdateNormal(INT16 * pSoundBuf,INT32 nSegmentEnd)314 static void YM2203UpdateNormal(INT16* pSoundBuf, INT32 nSegmentEnd)
315 {
316 #if defined FBA_DEBUG
317 	if (!DebugSnd_YM2203Initted) bprintf(PRINT_ERROR, _T("YM2203UpdateNormal called without init\n"));
318 #endif
319 
320 	INT32 nSegmentLength = nSegmentEnd;
321 	INT32 i;
322 
323 	if (nSegmentEnd < nAY8910Position) {
324 		nSegmentEnd = nAY8910Position;
325 	}
326 	if (nSegmentEnd < nYM2203Position) {
327 		nSegmentEnd = nYM2203Position;
328 	}
329 
330 	if (nSegmentLength > nBurnSoundLen) {
331 		nSegmentLength = nBurnSoundLen;
332 	}
333 
334 	YM2203Render(nSegmentEnd);
335 	AY8910Render(nSegmentEnd);
336 
337 	pYM2203Buffer[0] = pBuffer + 4 + 0 * 4096;
338 	pYM2203Buffer[1] = pBuffer + 4 + 1 * 4096;
339 	pYM2203Buffer[2] = pBuffer + 4 + 2 * 4096;
340 	pYM2203Buffer[3] = pBuffer + 4 + 3 * 4096;
341 	if (nNumChips > 1) {
342 		pYM2203Buffer[4] = pBuffer + 4 + 4 * 4096;
343 		pYM2203Buffer[5] = pBuffer + 4 + 5 * 4096;
344 		pYM2203Buffer[6] = pBuffer + 4 + 6 * 4096;
345 		pYM2203Buffer[7] = pBuffer + 4 + 7 * 4096;
346 	}
347 	if (nNumChips > 2) {
348 		pYM2203Buffer[8] = pBuffer + 4 + 8 * 4096;
349 		pYM2203Buffer[9] = pBuffer + 4 + 9 * 4096;
350 		pYM2203Buffer[10] = pBuffer + 4 + 10 * 4096;
351 		pYM2203Buffer[11] = pBuffer + 4 + 11 * 4096;
352 	}
353 
354 	for (INT32 n = nFractionalPosition; n < nSegmentLength; n++) {
355 		INT32 nLeftSample = 0, nRightSample = 0;
356 
357 		if (bYM2203UseSeperateVolumes) {
358 			nLeftSample += (INT32)(pYM2203Buffer[1][n] * YM2203LeftVolumes[BURN_SND_YM2203_AY8910_ROUTE_1]);
359 			nLeftSample += (INT32)(pYM2203Buffer[2][n] * YM2203LeftVolumes[BURN_SND_YM2203_AY8910_ROUTE_2]);
360 			nLeftSample += (INT32)(pYM2203Buffer[3][n] * YM2203LeftVolumes[BURN_SND_YM2203_AY8910_ROUTE_3]);
361 			nLeftSample += (INT32)(pYM2203Buffer[0][n] * YM2203LeftVolumes[BURN_SND_YM2203_YM2203_ROUTE]);
362 
363 			nRightSample += (INT32)(pYM2203Buffer[1][n] * YM2203RightVolumes[BURN_SND_YM2203_AY8910_ROUTE_1]);
364 			nRightSample += (INT32)(pYM2203Buffer[2][n] * YM2203RightVolumes[BURN_SND_YM2203_AY8910_ROUTE_2]);
365 			nRightSample += (INT32)(pYM2203Buffer[3][n] * YM2203RightVolumes[BURN_SND_YM2203_AY8910_ROUTE_3]);
366 			nRightSample += (INT32)(pYM2203Buffer[0][n] * YM2203RightVolumes[BURN_SND_YM2203_YM2203_ROUTE]);
367 
368 			if (nNumChips > 1) {
369 				nLeftSample += (INT32)(pYM2203Buffer[5][n] * YM2203LeftVolumes[4 + BURN_SND_YM2203_AY8910_ROUTE_1]);
370 				nLeftSample += (INT32)(pYM2203Buffer[6][n] * YM2203LeftVolumes[4 + BURN_SND_YM2203_AY8910_ROUTE_2]);
371 				nLeftSample += (INT32)(pYM2203Buffer[7][n] * YM2203LeftVolumes[4 + BURN_SND_YM2203_AY8910_ROUTE_3]);
372 				nLeftSample += (INT32)(pYM2203Buffer[4][n] * YM2203LeftVolumes[4 + BURN_SND_YM2203_YM2203_ROUTE]);
373 
374 				nRightSample += (INT32)(pYM2203Buffer[5][n] * YM2203RightVolumes[4 + BURN_SND_YM2203_AY8910_ROUTE_1]);
375 				nRightSample += (INT32)(pYM2203Buffer[6][n] * YM2203RightVolumes[4 + BURN_SND_YM2203_AY8910_ROUTE_2]);
376 				nRightSample += (INT32)(pYM2203Buffer[7][n] * YM2203RightVolumes[4 + BURN_SND_YM2203_AY8910_ROUTE_3]);
377 				nRightSample += (INT32)(pYM2203Buffer[4][n] * YM2203RightVolumes[4 + BURN_SND_YM2203_YM2203_ROUTE]);
378 			}
379 
380 			if (nNumChips > 2) {
381 				nLeftSample += (INT32)(pYM2203Buffer[9][n] * YM2203LeftVolumes[8 + BURN_SND_YM2203_AY8910_ROUTE_1]);
382 				nLeftSample += (INT32)(pYM2203Buffer[10][n] * YM2203LeftVolumes[8 + BURN_SND_YM2203_AY8910_ROUTE_2]);
383 				nLeftSample += (INT32)(pYM2203Buffer[11][n] * YM2203LeftVolumes[8 + BURN_SND_YM2203_AY8910_ROUTE_3]);
384 				nLeftSample += (INT32)(pYM2203Buffer[8][n] * YM2203LeftVolumes[8 + BURN_SND_YM2203_YM2203_ROUTE]);
385 
386 				nRightSample += (INT32)(pYM2203Buffer[9][n] * YM2203RightVolumes[8 + BURN_SND_YM2203_AY8910_ROUTE_1]);
387 				nRightSample += (INT32)(pYM2203Buffer[10][n] * YM2203RightVolumes[8 + BURN_SND_YM2203_AY8910_ROUTE_2]);
388 				nRightSample += (INT32)(pYM2203Buffer[11][n] * YM2203RightVolumes[8 + BURN_SND_YM2203_AY8910_ROUTE_3]);
389 				nRightSample += (INT32)(pYM2203Buffer[8][n] * YM2203RightVolumes[8 + BURN_SND_YM2203_YM2203_ROUTE]);
390 			}
391 		} else {
392 			if ((YM2203RouteDirs[BURN_SND_YM2203_AY8910_ROUTE_1] & BURN_SND_ROUTE_LEFT) == BURN_SND_ROUTE_LEFT) {
393 				nLeftSample += (INT32)(pYM2203Buffer[1][n] * YM2203Volumes[BURN_SND_YM2203_AY8910_ROUTE_1]);
394 			}
395 			if ((YM2203RouteDirs[BURN_SND_YM2203_AY8910_ROUTE_1] & BURN_SND_ROUTE_RIGHT) == BURN_SND_ROUTE_RIGHT) {
396 				nRightSample += (INT32)(pYM2203Buffer[1][n] * YM2203Volumes[BURN_SND_YM2203_AY8910_ROUTE_1]);
397 			}
398 
399 			if ((YM2203RouteDirs[BURN_SND_YM2203_AY8910_ROUTE_2] & BURN_SND_ROUTE_LEFT) == BURN_SND_ROUTE_LEFT) {
400 				nLeftSample += (INT32)(pYM2203Buffer[2][n] * YM2203Volumes[BURN_SND_YM2203_AY8910_ROUTE_2]);
401 			}
402 			if ((YM2203RouteDirs[BURN_SND_YM2203_AY8910_ROUTE_2] & BURN_SND_ROUTE_RIGHT) == BURN_SND_ROUTE_RIGHT) {
403 				nRightSample += (INT32)(pYM2203Buffer[2][n] * YM2203Volumes[BURN_SND_YM2203_AY8910_ROUTE_2]);
404 			}
405 
406 			if ((YM2203RouteDirs[BURN_SND_YM2203_AY8910_ROUTE_3] & BURN_SND_ROUTE_LEFT) == BURN_SND_ROUTE_LEFT) {
407 				nLeftSample += (INT32)(pYM2203Buffer[3][n] * YM2203Volumes[BURN_SND_YM2203_AY8910_ROUTE_3]);
408 			}
409 			if ((YM2203RouteDirs[BURN_SND_YM2203_AY8910_ROUTE_3] & BURN_SND_ROUTE_RIGHT) == BURN_SND_ROUTE_RIGHT) {
410 				nRightSample += (INT32)(pYM2203Buffer[3][n] * YM2203Volumes[BURN_SND_YM2203_AY8910_ROUTE_3]);
411 			}
412 
413 			if ((YM2203RouteDirs[BURN_SND_YM2203_YM2203_ROUTE] & BURN_SND_ROUTE_LEFT) == BURN_SND_ROUTE_LEFT) {
414 				nLeftSample += (INT32)(pYM2203Buffer[0][n] * YM2203Volumes[BURN_SND_YM2203_YM2203_ROUTE]);
415 			}
416 			if ((YM2203RouteDirs[BURN_SND_YM2203_YM2203_ROUTE] & BURN_SND_ROUTE_RIGHT) == BURN_SND_ROUTE_RIGHT) {
417 				nRightSample += (INT32)(pYM2203Buffer[0][n] * YM2203Volumes[BURN_SND_YM2203_YM2203_ROUTE]);
418 			}
419 
420 			if (nNumChips > 1) {
421 				if ((YM2203RouteDirs[4 + BURN_SND_YM2203_AY8910_ROUTE_1] & BURN_SND_ROUTE_LEFT) == BURN_SND_ROUTE_LEFT) {
422 					nLeftSample += (INT32)(pYM2203Buffer[5][n] * YM2203Volumes[4 + BURN_SND_YM2203_AY8910_ROUTE_1]);
423 				}
424 				if ((YM2203RouteDirs[4 + BURN_SND_YM2203_AY8910_ROUTE_1] & BURN_SND_ROUTE_RIGHT) == BURN_SND_ROUTE_RIGHT) {
425 					nRightSample += (INT32)(pYM2203Buffer[5][n] * YM2203Volumes[4 + BURN_SND_YM2203_AY8910_ROUTE_1]);
426 				}
427 
428 				if ((YM2203RouteDirs[4 + BURN_SND_YM2203_AY8910_ROUTE_2] & BURN_SND_ROUTE_LEFT) == BURN_SND_ROUTE_LEFT) {
429 					nLeftSample += (INT32)(pYM2203Buffer[6][n] * YM2203Volumes[4 + BURN_SND_YM2203_AY8910_ROUTE_2]);
430 				}
431 				if ((YM2203RouteDirs[4 + BURN_SND_YM2203_AY8910_ROUTE_2] & BURN_SND_ROUTE_RIGHT) == BURN_SND_ROUTE_RIGHT) {
432 					nRightSample += (INT32)(pYM2203Buffer[6][n] * YM2203Volumes[4 + BURN_SND_YM2203_AY8910_ROUTE_2]);
433 				}
434 
435 				if ((YM2203RouteDirs[4 + BURN_SND_YM2203_AY8910_ROUTE_3] & BURN_SND_ROUTE_LEFT) == BURN_SND_ROUTE_LEFT) {
436 					nLeftSample += (INT32)(pYM2203Buffer[7][n] * YM2203Volumes[4 + BURN_SND_YM2203_AY8910_ROUTE_3]);
437 				}
438 				if ((YM2203RouteDirs[4 + BURN_SND_YM2203_AY8910_ROUTE_3] & BURN_SND_ROUTE_RIGHT) == BURN_SND_ROUTE_RIGHT) {
439 					nRightSample += (INT32)(pYM2203Buffer[7][n] * YM2203Volumes[4 + BURN_SND_YM2203_AY8910_ROUTE_3]);
440 				}
441 
442 				if ((YM2203RouteDirs[4 + BURN_SND_YM2203_YM2203_ROUTE] & BURN_SND_ROUTE_LEFT) == BURN_SND_ROUTE_LEFT) {
443 					nLeftSample += (INT32)(pYM2203Buffer[4][n] * YM2203Volumes[4 + BURN_SND_YM2203_YM2203_ROUTE]);
444 				}
445 				if ((YM2203RouteDirs[4 + BURN_SND_YM2203_YM2203_ROUTE] & BURN_SND_ROUTE_RIGHT) == BURN_SND_ROUTE_RIGHT) {
446 					nRightSample += (INT32)(pYM2203Buffer[4][n] * YM2203Volumes[4 + BURN_SND_YM2203_YM2203_ROUTE]);
447 				}
448 			}
449 
450 			if (nNumChips > 2) {
451 				if ((YM2203RouteDirs[8 + BURN_SND_YM2203_AY8910_ROUTE_1] & BURN_SND_ROUTE_LEFT) == BURN_SND_ROUTE_LEFT) {
452 					nLeftSample += (INT32)(pYM2203Buffer[9][n] * YM2203Volumes[8 + BURN_SND_YM2203_AY8910_ROUTE_1]);
453 				}
454 				if ((YM2203RouteDirs[8 + BURN_SND_YM2203_AY8910_ROUTE_1] & BURN_SND_ROUTE_RIGHT) == BURN_SND_ROUTE_RIGHT) {
455 					nRightSample += (INT32)(pYM2203Buffer[9][n] * YM2203Volumes[8 + BURN_SND_YM2203_AY8910_ROUTE_1]);
456 				}
457 
458 				if ((YM2203RouteDirs[8 + BURN_SND_YM2203_AY8910_ROUTE_2] & BURN_SND_ROUTE_LEFT) == BURN_SND_ROUTE_LEFT) {
459 					nLeftSample += (INT32)(pYM2203Buffer[10][n] * YM2203Volumes[8 + BURN_SND_YM2203_AY8910_ROUTE_2]);
460 				}
461 				if ((YM2203RouteDirs[8 + BURN_SND_YM2203_AY8910_ROUTE_2] & BURN_SND_ROUTE_RIGHT) == BURN_SND_ROUTE_RIGHT) {
462 					nRightSample += (INT32)(pYM2203Buffer[10][n] * YM2203Volumes[8 + BURN_SND_YM2203_AY8910_ROUTE_2]);
463 				}
464 
465 				if ((YM2203RouteDirs[8 + BURN_SND_YM2203_AY8910_ROUTE_3] & BURN_SND_ROUTE_LEFT) == BURN_SND_ROUTE_LEFT) {
466 					nLeftSample += (INT32)(pYM2203Buffer[11][n] * YM2203Volumes[8 + BURN_SND_YM2203_AY8910_ROUTE_3]);
467 				}
468 				if ((YM2203RouteDirs[8 + BURN_SND_YM2203_AY8910_ROUTE_3] & BURN_SND_ROUTE_RIGHT) == BURN_SND_ROUTE_RIGHT) {
469 					nRightSample += (INT32)(pYM2203Buffer[11][n] * YM2203Volumes[8 + BURN_SND_YM2203_AY8910_ROUTE_3]);
470 				}
471 
472 				if ((YM2203RouteDirs[8 + BURN_SND_YM2203_YM2203_ROUTE] & BURN_SND_ROUTE_LEFT) == BURN_SND_ROUTE_LEFT) {
473 					nLeftSample += (INT32)(pYM2203Buffer[8][n] * YM2203Volumes[8 + BURN_SND_YM2203_YM2203_ROUTE]);
474 				}
475 				if ((YM2203RouteDirs[8 + BURN_SND_YM2203_YM2203_ROUTE] & BURN_SND_ROUTE_RIGHT) == BURN_SND_ROUTE_RIGHT) {
476 					nRightSample += (INT32)(pYM2203Buffer[8][n] * YM2203Volumes[8 + BURN_SND_YM2203_YM2203_ROUTE]);
477 				}
478 			}
479 		}
480 
481 		nLeftSample = BURN_SND_CLIP(nLeftSample);
482 		nRightSample = BURN_SND_CLIP(nRightSample);
483 
484 		if (bYM2203AddSignal) {
485 			//pSoundBuf[(n << 1) + 0] += nLeftSample;
486 			//pSoundBuf[(n << 1) + 1] += nRightSample;
487 			pSoundBuf[(n << 1) + 0] = BURN_SND_CLIP(pSoundBuf[(n << 1) + 0] + nLeftSample);
488 			pSoundBuf[(n << 1) + 1] = BURN_SND_CLIP(pSoundBuf[(n << 1) + 1] + nRightSample);
489 		} else {
490 			pSoundBuf[(n << 1) + 0] = nLeftSample;
491 			pSoundBuf[(n << 1) + 1] = nRightSample;
492 		}
493 	}
494 
495 	nFractionalPosition = nSegmentLength;
496 
497 	if (nSegmentEnd >= nBurnSoundLen) {
498 		INT32 nExtraSamples = nSegmentEnd - nBurnSoundLen;
499 
500 		for (i = 0; i < nExtraSamples; i++) {
501 			pYM2203Buffer[0][i] = pYM2203Buffer[0][nBurnSoundLen + i];
502 			pYM2203Buffer[1][i] = pYM2203Buffer[1][nBurnSoundLen + i];
503 			pYM2203Buffer[2][i] = pYM2203Buffer[2][nBurnSoundLen + i];
504 			pYM2203Buffer[3][i] = pYM2203Buffer[3][nBurnSoundLen + i];
505 			if (nNumChips > 1) {
506 				pYM2203Buffer[4][i] = pYM2203Buffer[4][nBurnSoundLen + i];
507 				pYM2203Buffer[5][i] = pYM2203Buffer[5][nBurnSoundLen + i];
508 				pYM2203Buffer[6][i] = pYM2203Buffer[6][nBurnSoundLen + i];
509 				pYM2203Buffer[7][i] = pYM2203Buffer[7][nBurnSoundLen + i];
510 			}
511 			if (nNumChips > 2) {
512 				pYM2203Buffer[8][i] = pYM2203Buffer[8][nBurnSoundLen + i];
513 				pYM2203Buffer[9][i] = pYM2203Buffer[9][nBurnSoundLen + i];
514 				pYM2203Buffer[10][i] = pYM2203Buffer[10][nBurnSoundLen + i];
515 				pYM2203Buffer[11][i] = pYM2203Buffer[11][nBurnSoundLen + i];
516 			}
517 		}
518 
519 		nFractionalPosition = 0;
520 
521 		nYM2203Position = nExtraSamples;
522 		nAY8910Position = nExtraSamples;
523 
524 		dTime += 100.0 / nBurnFPS;
525 	}
526 }
527 
528 // ----------------------------------------------------------------------------
529 // Callbacks for YM2203 core
530 
BurnYM2203UpdateRequest()531 void BurnYM2203UpdateRequest()
532 {
533 #if defined FBA_DEBUG
534 	if (!DebugSnd_YM2203Initted) bprintf(PRINT_ERROR, _T("BurnYM2203UpdateRequest called without init\n"));
535 #endif
536 
537 	YM2203Render(BurnYM2203StreamCallback(nBurnYM2203SoundRate));
538 }
539 
BurnAY8910UpdateRequest()540 static void BurnAY8910UpdateRequest()
541 {
542 #if defined FBA_DEBUG
543 	if (!DebugSnd_YM2203Initted) bprintf(PRINT_ERROR, _T("BurnYM2203 BurnAY8910UpdateRequest called without init\n"));
544 #endif
545 
546 	AY8910Render(BurnYM2203StreamCallback(nBurnYM2203SoundRate));
547 }
548 
549 // ----------------------------------------------------------------------------
550 // Initialisation, etc.
551 
BurnYM2203Reset()552 void BurnYM2203Reset()
553 {
554 #if defined FBA_DEBUG
555 	if (!DebugSnd_YM2203Initted) bprintf(PRINT_ERROR, _T("BurnYM2203Reset called without init\n"));
556 #endif
557 
558 	BurnTimerReset();
559 
560 	for (INT32 i = 0; i < nNumChips; i++) {
561 		YM2203ResetChip(i);
562 		AY8910Reset(i);
563 	}
564 }
565 
BurnYM2203Exit()566 void BurnYM2203Exit()
567 {
568 #if defined FBA_DEBUG
569 	if (!DebugSnd_YM2203Initted) bprintf(PRINT_ERROR, _T("BurnYM2203Exit called without init\n"));
570 #endif
571 
572 	if (!DebugSnd_YM2203Initted) return;
573 
574 	YM2203Shutdown();
575 
576 	for (INT32 i = 0; i < nNumChips; i++) {
577 		AY8910Exit(i);
578 	}
579 
580 	BurnTimerExit();
581 
582 	BurnFree(pBuffer);
583 
584 	nNumChips = 0;
585 	bYM2203AddSignal = 0;
586 	bYM2203UseSeperateVolumes = 0;
587 
588 	DebugSnd_YM2203Initted = 0;
589 }
590 
BurnYM2203Init(INT32 num,INT32 nClockFrequency,FM_IRQHANDLER IRQCallback,INT32 bAddSignal)591 INT32 BurnYM2203Init(INT32 num, INT32 nClockFrequency, FM_IRQHANDLER IRQCallback, INT32 bAddSignal)
592 {
593 	return BurnYM2203Init(num, nClockFrequency, IRQCallback, BurnSynchroniseStream, BurnGetTime, bAddSignal);
594 }
595 
BurnYM2203Init(INT32 num,INT32 nClockFrequency,FM_IRQHANDLER IRQCallback,INT32 (* StreamCallback)(INT32),double (* GetTimeCallback)(),INT32 bAddSignal)596 INT32 BurnYM2203Init(INT32 num, INT32 nClockFrequency, FM_IRQHANDLER IRQCallback, INT32 (*StreamCallback)(INT32), double (*GetTimeCallback)(), INT32 bAddSignal)
597 {
598 	DebugSnd_YM2203Initted = 1;
599 
600 	if (num > MAX_YM2203) num = MAX_YM2203;
601 
602 	BurnTimerInit(&YM2203TimerOver, GetTimeCallback);
603 	if (nBurnSoundRate <= 0) {
604 		BurnYM2203StreamCallback = YM2203StreamCallbackDummy;
605 
606 		BurnYM2203Update = YM2203UpdateDummy;
607 
608 		for (INT32 i = 0; i < num; i++) {
609 			AY8910InitYM(i, nClockFrequency, 11025, NULL, NULL, NULL, NULL, BurnAY8910UpdateRequest);
610 		}
611 		YM2203Init(num, nClockFrequency, 11025, &BurnOPNTimerCallback, IRQCallback);
612 		return 0;
613 	}
614 
615 	BurnYM2203StreamCallback = StreamCallback;
616 
617 	if (nFMInterpolation == 3) {
618 		// Set YM2203 core samplerate to match the hardware
619 		nBurnYM2203SoundRate = nClockFrequency >> 6;
620 		// Bring YM2203 core samplerate within usable range
621 		while (nBurnYM2203SoundRate > nBurnSoundRate * 3) {
622 			nBurnYM2203SoundRate >>= 1;
623 		}
624 
625 		if (nBurnYM2203SoundRate < nBurnSoundRate)
626 			nBurnYM2203SoundRate = nBurnSoundRate;
627 
628 		BurnYM2203Update = YM2203UpdateResample;
629 		nSampleSize = (UINT32)nBurnYM2203SoundRate * (1 << 16) / nBurnSoundRate;
630 
631     } else {
632 		nBurnYM2203SoundRate = nBurnSoundRate;
633 		BurnYM2203Update = YM2203UpdateNormal;
634 	}
635 
636 	for (INT32 i = 0; i < num; i++) {
637 		AY8910InitYM(i, nClockFrequency, nBurnYM2203SoundRate, NULL, NULL, NULL, NULL, BurnAY8910UpdateRequest);
638 	}
639 
640 	YM2203Init(num, nClockFrequency, nBurnYM2203SoundRate, &BurnOPNTimerCallback, IRQCallback);
641 
642 	pBuffer = (INT16*)BurnMalloc(4096 * 4 * num * sizeof(INT16));
643 	memset(pBuffer, 0, 4096 * 4 * num * sizeof(INT16));
644 
645 	nYM2203Position = 0;
646 	nAY8910Position = 0;
647 	nFractionalPosition = 0;
648 
649 	nNumChips = num;
650 	bYM2203AddSignal = bAddSignal;
651 
652 	// default routes
653 	YM2203Volumes[BURN_SND_YM2203_YM2203_ROUTE] = 1.00;
654 	YM2203Volumes[BURN_SND_YM2203_AY8910_ROUTE_1] = 1.00;
655 	YM2203Volumes[BURN_SND_YM2203_AY8910_ROUTE_2] = 1.00;
656 	YM2203Volumes[BURN_SND_YM2203_AY8910_ROUTE_3] = 1.00;
657 	YM2203RouteDirs[BURN_SND_YM2203_YM2203_ROUTE] = BURN_SND_ROUTE_BOTH;
658 	YM2203RouteDirs[BURN_SND_YM2203_AY8910_ROUTE_1] = BURN_SND_ROUTE_BOTH;
659 	YM2203RouteDirs[BURN_SND_YM2203_AY8910_ROUTE_2] = BURN_SND_ROUTE_BOTH;
660 	YM2203RouteDirs[BURN_SND_YM2203_AY8910_ROUTE_3] = BURN_SND_ROUTE_BOTH;
661 
662 	bYM2203UseSeperateVolumes = 0;
663 	YM2203LeftVolumes[BURN_SND_YM2203_YM2203_ROUTE] = 1.00;
664 	YM2203LeftVolumes[BURN_SND_YM2203_AY8910_ROUTE_1] = 1.00;
665 	YM2203LeftVolumes[BURN_SND_YM2203_AY8910_ROUTE_2] = 1.00;
666 	YM2203LeftVolumes[BURN_SND_YM2203_AY8910_ROUTE_3] = 1.00;
667 	YM2203RightVolumes[BURN_SND_YM2203_YM2203_ROUTE] = 1.00;
668 	YM2203RightVolumes[BURN_SND_YM2203_AY8910_ROUTE_1] = 1.00;
669 	YM2203RightVolumes[BURN_SND_YM2203_AY8910_ROUTE_2] = 1.00;
670 	YM2203RightVolumes[BURN_SND_YM2203_AY8910_ROUTE_3] = 1.00;
671 
672 	if (nNumChips > 1) {
673 		YM2203Volumes[4 + BURN_SND_YM2203_YM2203_ROUTE] = 1.00;
674 		YM2203Volumes[4 + BURN_SND_YM2203_AY8910_ROUTE_1] = 1.00;
675 		YM2203Volumes[4 + BURN_SND_YM2203_AY8910_ROUTE_2] = 1.00;
676 		YM2203Volumes[4 + BURN_SND_YM2203_AY8910_ROUTE_3] = 1.00;
677 		YM2203RouteDirs[4 + BURN_SND_YM2203_YM2203_ROUTE] = BURN_SND_ROUTE_BOTH;
678 		YM2203RouteDirs[4 + BURN_SND_YM2203_AY8910_ROUTE_1] = BURN_SND_ROUTE_BOTH;
679 		YM2203RouteDirs[4 + BURN_SND_YM2203_AY8910_ROUTE_2] = BURN_SND_ROUTE_BOTH;
680 		YM2203RouteDirs[4 + BURN_SND_YM2203_AY8910_ROUTE_3] = BURN_SND_ROUTE_BOTH;
681 
682 		YM2203LeftVolumes[4 + BURN_SND_YM2203_YM2203_ROUTE] = 1.00;
683 		YM2203LeftVolumes[4 + BURN_SND_YM2203_AY8910_ROUTE_1] = 1.00;
684 		YM2203LeftVolumes[4 + BURN_SND_YM2203_AY8910_ROUTE_2] = 1.00;
685 		YM2203LeftVolumes[4 + BURN_SND_YM2203_AY8910_ROUTE_3] = 1.00;
686 		YM2203RightVolumes[4 + BURN_SND_YM2203_YM2203_ROUTE] = 1.00;
687 		YM2203RightVolumes[4 + BURN_SND_YM2203_AY8910_ROUTE_1] = 1.00;
688 		YM2203RightVolumes[4 + BURN_SND_YM2203_AY8910_ROUTE_2] = 1.00;
689 		YM2203RightVolumes[4 + BURN_SND_YM2203_AY8910_ROUTE_3] = 1.00;
690 	}
691 
692 	if (nNumChips > 2) {
693 		YM2203Volumes[8 + BURN_SND_YM2203_YM2203_ROUTE] = 1.00;
694 		YM2203Volumes[8 + BURN_SND_YM2203_AY8910_ROUTE_1] = 1.00;
695 		YM2203Volumes[8 + BURN_SND_YM2203_AY8910_ROUTE_2] = 1.00;
696 		YM2203Volumes[8 + BURN_SND_YM2203_AY8910_ROUTE_3] = 1.00;
697 		YM2203RouteDirs[8 + BURN_SND_YM2203_YM2203_ROUTE] = BURN_SND_ROUTE_BOTH;
698 		YM2203RouteDirs[8 + BURN_SND_YM2203_AY8910_ROUTE_1] = BURN_SND_ROUTE_BOTH;
699 		YM2203RouteDirs[8 + BURN_SND_YM2203_AY8910_ROUTE_2] = BURN_SND_ROUTE_BOTH;
700 		YM2203RouteDirs[8 + BURN_SND_YM2203_AY8910_ROUTE_3] = BURN_SND_ROUTE_BOTH;
701 
702 		YM2203LeftVolumes[8 + BURN_SND_YM2203_YM2203_ROUTE] = 1.00;
703 		YM2203LeftVolumes[8 + BURN_SND_YM2203_AY8910_ROUTE_1] = 1.00;
704 		YM2203LeftVolumes[8 + BURN_SND_YM2203_AY8910_ROUTE_2] = 1.00;
705 		YM2203LeftVolumes[8 + BURN_SND_YM2203_AY8910_ROUTE_3] = 1.00;
706 		YM2203RightVolumes[8 + BURN_SND_YM2203_YM2203_ROUTE] = 1.00;
707 		YM2203RightVolumes[8 + BURN_SND_YM2203_AY8910_ROUTE_1] = 1.00;
708 		YM2203RightVolumes[8 + BURN_SND_YM2203_AY8910_ROUTE_2] = 1.00;
709 		YM2203RightVolumes[8 + BURN_SND_YM2203_AY8910_ROUTE_3] = 1.00;
710 	}
711 
712 	return 0;
713 }
714 
BurnYM2203SetRoute(INT32 nChip,INT32 nIndex,double nVolume,INT32 nRouteDir)715 void BurnYM2203SetRoute(INT32 nChip, INT32 nIndex, double nVolume, INT32 nRouteDir)
716 {
717 #if defined FBA_DEBUG
718 	if (!DebugSnd_YM2203Initted) bprintf(PRINT_ERROR, _T("BurnYM2203SetRoute called without init\n"));
719 	if (nIndex < 0 || nIndex > 3) bprintf(PRINT_ERROR, _T("BurnYM2203SetRoute called with invalid index %i\n"), nIndex);
720 	if (nChip >= nNumChips) bprintf(PRINT_ERROR, _T("BurnYM2203SetRoute called with invalid chip %i\n"), nChip);
721 #endif
722 
723 	if (nChip == 0) {
724 		YM2203Volumes[nIndex] = nVolume;
725 		YM2203RouteDirs[nIndex] = nRouteDir;
726 	}
727 
728 	if (nChip == 1) {
729 		YM2203Volumes[4 + nIndex] = nVolume;
730 		YM2203RouteDirs[4 + nIndex] = nRouteDir;
731 	}
732 
733 	if (nChip == 2) {
734 		YM2203Volumes[8 + nIndex] = nVolume;
735 		YM2203RouteDirs[8 + nIndex] = nRouteDir;
736 	}
737 }
738 
BurnYM2203SetLeftVolume(INT32 nChip,INT32 nIndex,double nLeftVolume)739 void BurnYM2203SetLeftVolume(INT32 nChip, INT32 nIndex, double nLeftVolume)
740 {
741 #if defined FBA_DEBUG
742 	if (!DebugSnd_YM2203Initted) bprintf(PRINT_ERROR, _T("BurnYM2203SetLeftVolume called without init\n"));
743 	if (nIndex < 0 || nIndex > 3) bprintf(PRINT_ERROR, _T("BurnYM2203SetLeftVolume called with invalid index %i\n"), nIndex);
744 	if (nChip >= nNumChips) bprintf(PRINT_ERROR, _T("BurnYM2203SetLeftVolume called with invalid chip %i\n"), nChip);
745 #endif
746 
747 	if (nChip == 0) YM2203LeftVolumes[nIndex] = nLeftVolume;
748 	if (nChip == 1) YM2203LeftVolumes[4 + nIndex] = nLeftVolume;
749 	if (nChip == 2) YM2203LeftVolumes[8 + nIndex] = nLeftVolume;
750 }
751 
BurnYM2203SetRightVolume(INT32 nChip,INT32 nIndex,double nRightVolume)752 void BurnYM2203SetRightVolume(INT32 nChip, INT32 nIndex, double nRightVolume)
753 {
754 #if defined FBA_DEBUG
755 	if (!DebugSnd_YM2203Initted) bprintf(PRINT_ERROR, _T("BurnYM2203SetRightVolume called without init\n"));
756 	if (nIndex < 0 || nIndex > 3) bprintf(PRINT_ERROR, _T("BurnYM2203SetRightVolume called with invalid index %i\n"), nIndex);
757 	if (nChip >= nNumChips) bprintf(PRINT_ERROR, _T("BurnYM2203SetRightVolume called with invalid chip %i\n"), nChip);
758 #endif
759 
760 	if (nChip == 0) YM2203RightVolumes[nIndex] = nRightVolume;
761 	if (nChip == 1) YM2203RightVolumes[4 + nIndex] = nRightVolume;
762 	if (nChip == 2) YM2203RightVolumes[8 + nIndex] = nRightVolume;
763 }
764 
BurnYM2203Scan(INT32 nAction,INT32 * pnMin)765 void BurnYM2203Scan(INT32 nAction, INT32* pnMin)
766 {
767 #if defined FBA_DEBUG
768 	if (!DebugSnd_YM2203Initted) bprintf(PRINT_ERROR, _T("BurnYM2203Scan called without init\n"));
769 #endif
770 
771 	BurnTimerScan(nAction, pnMin);
772 	AY8910Scan(nAction, pnMin);
773 
774 	if (nAction & ACB_DRIVER_DATA) {
775 		SCAN_VAR(nYM2203Position);
776 		SCAN_VAR(nAY8910Position);
777 	}
778 }
779 
780 #undef MAX_YM2203
781