1 #include "burnint.h"
2 #include "burn_ym2610.h"
3
4 void (*BurnYM2610Update)(INT16* pSoundBuf, INT32 nSegmentEnd);
5
6 static INT32 (*BurnYM2610StreamCallback)(INT32 nSoundRate);
7
8 static INT32 nBurnYM2610SoundRate;
9
10 static INT16* pBuffer;
11 static INT16* pYM2610Buffer[6];
12
13 static INT32* pAYBuffer;
14
15 static INT32 nYM2610Position;
16 static INT32 nAY8910Position;
17
18 static UINT32 nSampleSize;
19 static INT32 nFractionalPosition;
20
21 static INT32 bYM2610AddSignal;
22
23 static double YM2610Volumes[3];
24 static INT32 YM2610RouteDirs[3];
25
26 static double YM2610LeftVolumes[3];
27 static double YM2610RightVolumes[3];
28
29 INT32 bYM2610UseSeperateVolumes; // support custom Taito panning hardware
30
31 // ----------------------------------------------------------------------------
32 // Dummy functions
33
YM2610UpdateDummy(INT16 *,INT32)34 static void YM2610UpdateDummy(INT16*, INT32)
35 {
36 return;
37 }
38
YM2610StreamCallbackDummy(INT32)39 static INT32 YM2610StreamCallbackDummy(INT32)
40 {
41 return 0;
42 }
43
44 // ----------------------------------------------------------------------------
45 // Execute YM2610 for part of a frame
46
AY8910Render(INT32 nSegmentLength)47 static void AY8910Render(INT32 nSegmentLength)
48 {
49 #if defined FBA_DEBUG
50 if (!DebugSnd_YM2610Initted) bprintf(PRINT_ERROR, _T("BurnYM2610 AY8910Render called without init\n"));
51 #endif
52
53 if (nAY8910Position >= nSegmentLength) {
54 return;
55 }
56
57 nSegmentLength -= nAY8910Position;
58
59 pYM2610Buffer[2] = pBuffer + 2 * 4096 + 4 + nAY8910Position;
60 pYM2610Buffer[3] = pBuffer + 3 * 4096 + 4 + nAY8910Position;
61 pYM2610Buffer[4] = pBuffer + 4 * 4096 + 4 + nAY8910Position;
62
63 AY8910Update(0, &pYM2610Buffer[2], nSegmentLength);
64
65 nAY8910Position += nSegmentLength;
66 }
67
YM2610Render(INT32 nSegmentLength)68 static void YM2610Render(INT32 nSegmentLength)
69 {
70 #if defined FBA_DEBUG
71 if (!DebugSnd_YM2610Initted) bprintf(PRINT_ERROR, _T("YM2610Render called without init\n"));
72 #endif
73
74 if (nYM2610Position >= nSegmentLength) {
75 return;
76 }
77
78 nSegmentLength -= nYM2610Position;
79
80 pYM2610Buffer[0] = pBuffer + 0 * 4096 + 4 + nYM2610Position;
81 pYM2610Buffer[1] = pBuffer + 1 * 4096 + 4 + nYM2610Position;
82
83 YM2610UpdateOne(0, &pYM2610Buffer[0], nSegmentLength);
84
85 nYM2610Position += nSegmentLength;
86 }
87
88 // ----------------------------------------------------------------------------
89 // Update the sound buffer
90
YM2610UpdateResample(INT16 * pSoundBuf,INT32 nSegmentEnd)91 static void YM2610UpdateResample(INT16* pSoundBuf, INT32 nSegmentEnd)
92 {
93 #if defined FBA_DEBUG
94 if (!DebugSnd_YM2610Initted) bprintf(PRINT_ERROR, _T("YM2610UpdateResample called without init\n"));
95 #endif
96
97 INT32 nSegmentLength = nSegmentEnd;
98 INT32 nSamplesNeeded = nSegmentEnd * nBurnYM2610SoundRate / nBurnSoundRate + 1;
99
100 if (nSamplesNeeded < nAY8910Position) {
101 nSamplesNeeded = nAY8910Position;
102 }
103 if (nSamplesNeeded < nYM2610Position) {
104 nSamplesNeeded = nYM2610Position;
105 }
106
107 if (nSegmentLength > nBurnSoundLen) {
108 nSegmentLength = nBurnSoundLen;
109 }
110 nSegmentLength <<= 1;
111
112 YM2610Render(nSamplesNeeded);
113 AY8910Render(nSamplesNeeded);
114
115 pYM2610Buffer[0] = pBuffer + 0 * 4096 + 4;
116 pYM2610Buffer[1] = pBuffer + 1 * 4096 + 4;
117 pYM2610Buffer[2] = pBuffer + 2 * 4096 + 4;
118 pYM2610Buffer[3] = pBuffer + 3 * 4096 + 4;
119 pYM2610Buffer[4] = pBuffer + 4 * 4096 + 4;
120 pYM2610Buffer[5] = pBuffer + 5 * 4096 + 4;
121
122 for (INT32 i = (nFractionalPosition >> 16) - 4; i < nSamplesNeeded; i++) {
123 pYM2610Buffer[5][i] = BURN_SND_CLIP(pYM2610Buffer[2][i] + pYM2610Buffer[3][i] + pYM2610Buffer[4][i]);
124 }
125
126 for (INT32 i = (nFractionalPosition & 0xFFFF0000) >> 15; i < nSegmentLength; i += 2, nFractionalPosition += nSampleSize) {
127 INT32 nLeftSample[4] = {0, 0, 0, 0};
128 INT32 nRightSample[4] = {0, 0, 0, 0};
129 INT32 nTotalLeftSample, nTotalRightSample;
130
131 if (bYM2610UseSeperateVolumes) {
132 nLeftSample[0] += (INT32)(pYM2610Buffer[5][(nFractionalPosition >> 16) - 3] * YM2610LeftVolumes[BURN_SND_YM2610_AY8910_ROUTE]);
133 nLeftSample[1] += (INT32)(pYM2610Buffer[5][(nFractionalPosition >> 16) - 2] * YM2610LeftVolumes[BURN_SND_YM2610_AY8910_ROUTE]);
134 nLeftSample[2] += (INT32)(pYM2610Buffer[5][(nFractionalPosition >> 16) - 1] * YM2610LeftVolumes[BURN_SND_YM2610_AY8910_ROUTE]);
135 nLeftSample[3] += (INT32)(pYM2610Buffer[5][(nFractionalPosition >> 16) - 0] * YM2610LeftVolumes[BURN_SND_YM2610_AY8910_ROUTE]);
136
137 nLeftSample[0] += (INT32)(pYM2610Buffer[0][(nFractionalPosition >> 16) - 3] * YM2610LeftVolumes[BURN_SND_YM2610_YM2610_ROUTE_1]);
138 nLeftSample[1] += (INT32)(pYM2610Buffer[0][(nFractionalPosition >> 16) - 2] * YM2610LeftVolumes[BURN_SND_YM2610_YM2610_ROUTE_1]);
139 nLeftSample[2] += (INT32)(pYM2610Buffer[0][(nFractionalPosition >> 16) - 1] * YM2610LeftVolumes[BURN_SND_YM2610_YM2610_ROUTE_1]);
140 nLeftSample[3] += (INT32)(pYM2610Buffer[0][(nFractionalPosition >> 16) - 0] * YM2610LeftVolumes[BURN_SND_YM2610_YM2610_ROUTE_1]);
141
142 nLeftSample[0] += (INT32)(pYM2610Buffer[1][(nFractionalPosition >> 16) - 3] * YM2610LeftVolumes[BURN_SND_YM2610_YM2610_ROUTE_2]);
143 nLeftSample[1] += (INT32)(pYM2610Buffer[1][(nFractionalPosition >> 16) - 2] * YM2610LeftVolumes[BURN_SND_YM2610_YM2610_ROUTE_2]);
144 nLeftSample[2] += (INT32)(pYM2610Buffer[1][(nFractionalPosition >> 16) - 1] * YM2610LeftVolumes[BURN_SND_YM2610_YM2610_ROUTE_2]);
145 nLeftSample[3] += (INT32)(pYM2610Buffer[1][(nFractionalPosition >> 16) - 0] * YM2610LeftVolumes[BURN_SND_YM2610_YM2610_ROUTE_2]);
146
147 nRightSample[0] += (INT32)(pYM2610Buffer[5][(nFractionalPosition >> 16) - 3] * YM2610RightVolumes[BURN_SND_YM2610_AY8910_ROUTE]);
148 nRightSample[1] += (INT32)(pYM2610Buffer[5][(nFractionalPosition >> 16) - 2] * YM2610RightVolumes[BURN_SND_YM2610_AY8910_ROUTE]);
149 nRightSample[2] += (INT32)(pYM2610Buffer[5][(nFractionalPosition >> 16) - 1] * YM2610RightVolumes[BURN_SND_YM2610_AY8910_ROUTE]);
150 nRightSample[3] += (INT32)(pYM2610Buffer[5][(nFractionalPosition >> 16) - 0] * YM2610RightVolumes[BURN_SND_YM2610_AY8910_ROUTE]);
151
152 nRightSample[0] += (INT32)(pYM2610Buffer[0][(nFractionalPosition >> 16) - 3] * YM2610RightVolumes[BURN_SND_YM2610_YM2610_ROUTE_1]);
153 nRightSample[1] += (INT32)(pYM2610Buffer[0][(nFractionalPosition >> 16) - 2] * YM2610RightVolumes[BURN_SND_YM2610_YM2610_ROUTE_1]);
154 nRightSample[2] += (INT32)(pYM2610Buffer[0][(nFractionalPosition >> 16) - 1] * YM2610RightVolumes[BURN_SND_YM2610_YM2610_ROUTE_1]);
155 nRightSample[3] += (INT32)(pYM2610Buffer[0][(nFractionalPosition >> 16) - 0] * YM2610RightVolumes[BURN_SND_YM2610_YM2610_ROUTE_1]);
156
157 nRightSample[0] += (INT32)(pYM2610Buffer[1][(nFractionalPosition >> 16) - 3] * YM2610RightVolumes[BURN_SND_YM2610_YM2610_ROUTE_2]);
158 nRightSample[1] += (INT32)(pYM2610Buffer[1][(nFractionalPosition >> 16) - 2] * YM2610RightVolumes[BURN_SND_YM2610_YM2610_ROUTE_2]);
159 nRightSample[2] += (INT32)(pYM2610Buffer[1][(nFractionalPosition >> 16) - 1] * YM2610RightVolumes[BURN_SND_YM2610_YM2610_ROUTE_2]);
160 nRightSample[3] += (INT32)(pYM2610Buffer[1][(nFractionalPosition >> 16) - 0] * YM2610RightVolumes[BURN_SND_YM2610_YM2610_ROUTE_2]);
161 } else {
162 if ((YM2610RouteDirs[BURN_SND_YM2610_AY8910_ROUTE] & BURN_SND_ROUTE_LEFT) == BURN_SND_ROUTE_LEFT) {
163 nLeftSample[0] += (INT32)(pYM2610Buffer[5][(nFractionalPosition >> 16) - 3] * YM2610Volumes[BURN_SND_YM2610_AY8910_ROUTE]);
164 nLeftSample[1] += (INT32)(pYM2610Buffer[5][(nFractionalPosition >> 16) - 2] * YM2610Volumes[BURN_SND_YM2610_AY8910_ROUTE]);
165 nLeftSample[2] += (INT32)(pYM2610Buffer[5][(nFractionalPosition >> 16) - 1] * YM2610Volumes[BURN_SND_YM2610_AY8910_ROUTE]);
166 nLeftSample[3] += (INT32)(pYM2610Buffer[5][(nFractionalPosition >> 16) - 0] * YM2610Volumes[BURN_SND_YM2610_AY8910_ROUTE]);
167 }
168 if ((YM2610RouteDirs[BURN_SND_YM2610_AY8910_ROUTE] & BURN_SND_ROUTE_RIGHT) == BURN_SND_ROUTE_RIGHT) {
169 nRightSample[0] += (INT32)(pYM2610Buffer[5][(nFractionalPosition >> 16) - 3] * YM2610Volumes[BURN_SND_YM2610_AY8910_ROUTE]);
170 nRightSample[1] += (INT32)(pYM2610Buffer[5][(nFractionalPosition >> 16) - 2] * YM2610Volumes[BURN_SND_YM2610_AY8910_ROUTE]);
171 nRightSample[2] += (INT32)(pYM2610Buffer[5][(nFractionalPosition >> 16) - 1] * YM2610Volumes[BURN_SND_YM2610_AY8910_ROUTE]);
172 nRightSample[3] += (INT32)(pYM2610Buffer[5][(nFractionalPosition >> 16) - 0] * YM2610Volumes[BURN_SND_YM2610_AY8910_ROUTE]);
173 }
174
175 if ((YM2610RouteDirs[BURN_SND_YM2610_YM2610_ROUTE_1] & BURN_SND_ROUTE_LEFT) == BURN_SND_ROUTE_LEFT) {
176 nLeftSample[0] += (INT32)(pYM2610Buffer[0][(nFractionalPosition >> 16) - 3] * YM2610Volumes[BURN_SND_YM2610_YM2610_ROUTE_1]);
177 nLeftSample[1] += (INT32)(pYM2610Buffer[0][(nFractionalPosition >> 16) - 2] * YM2610Volumes[BURN_SND_YM2610_YM2610_ROUTE_1]);
178 nLeftSample[2] += (INT32)(pYM2610Buffer[0][(nFractionalPosition >> 16) - 1] * YM2610Volumes[BURN_SND_YM2610_YM2610_ROUTE_1]);
179 nLeftSample[3] += (INT32)(pYM2610Buffer[0][(nFractionalPosition >> 16) - 0] * YM2610Volumes[BURN_SND_YM2610_YM2610_ROUTE_1]);
180 }
181 if ((YM2610RouteDirs[BURN_SND_YM2610_YM2610_ROUTE_1] & BURN_SND_ROUTE_RIGHT) == BURN_SND_ROUTE_RIGHT) {
182 nRightSample[0] += (INT32)(pYM2610Buffer[0][(nFractionalPosition >> 16) - 3] * YM2610Volumes[BURN_SND_YM2610_YM2610_ROUTE_1]);
183 nRightSample[1] += (INT32)(pYM2610Buffer[0][(nFractionalPosition >> 16) - 2] * YM2610Volumes[BURN_SND_YM2610_YM2610_ROUTE_1]);
184 nRightSample[2] += (INT32)(pYM2610Buffer[0][(nFractionalPosition >> 16) - 1] * YM2610Volumes[BURN_SND_YM2610_YM2610_ROUTE_1]);
185 nRightSample[3] += (INT32)(pYM2610Buffer[0][(nFractionalPosition >> 16) - 0] * YM2610Volumes[BURN_SND_YM2610_YM2610_ROUTE_1]);
186 }
187
188 if ((YM2610RouteDirs[BURN_SND_YM2610_YM2610_ROUTE_2] & BURN_SND_ROUTE_LEFT) == BURN_SND_ROUTE_LEFT) {
189 nLeftSample[0] += (INT32)(pYM2610Buffer[1][(nFractionalPosition >> 16) - 3] * YM2610Volumes[BURN_SND_YM2610_YM2610_ROUTE_2]);
190 nLeftSample[1] += (INT32)(pYM2610Buffer[1][(nFractionalPosition >> 16) - 2] * YM2610Volumes[BURN_SND_YM2610_YM2610_ROUTE_2]);
191 nLeftSample[2] += (INT32)(pYM2610Buffer[1][(nFractionalPosition >> 16) - 1] * YM2610Volumes[BURN_SND_YM2610_YM2610_ROUTE_2]);
192 nLeftSample[3] += (INT32)(pYM2610Buffer[1][(nFractionalPosition >> 16) - 0] * YM2610Volumes[BURN_SND_YM2610_YM2610_ROUTE_2]);
193 }
194 if ((YM2610RouteDirs[BURN_SND_YM2610_YM2610_ROUTE_2] & BURN_SND_ROUTE_RIGHT) == BURN_SND_ROUTE_RIGHT) {
195 nRightSample[0] += (INT32)(pYM2610Buffer[1][(nFractionalPosition >> 16) - 3] * YM2610Volumes[BURN_SND_YM2610_YM2610_ROUTE_2]);
196 nRightSample[1] += (INT32)(pYM2610Buffer[1][(nFractionalPosition >> 16) - 2] * YM2610Volumes[BURN_SND_YM2610_YM2610_ROUTE_2]);
197 nRightSample[2] += (INT32)(pYM2610Buffer[1][(nFractionalPosition >> 16) - 1] * YM2610Volumes[BURN_SND_YM2610_YM2610_ROUTE_2]);
198 nRightSample[3] += (INT32)(pYM2610Buffer[1][(nFractionalPosition >> 16) - 0] * YM2610Volumes[BURN_SND_YM2610_YM2610_ROUTE_2]);
199 }
200 }
201
202 nTotalLeftSample = INTERPOLATE4PS_16BIT((nFractionalPosition >> 4) & 0x0fff, nLeftSample[0], nLeftSample[1], nLeftSample[2], nLeftSample[3]);
203 nTotalRightSample = INTERPOLATE4PS_16BIT((nFractionalPosition >> 4) & 0x0fff, nRightSample[0], nRightSample[1], nRightSample[2], nRightSample[3]);
204
205 nTotalLeftSample = BURN_SND_CLIP(nTotalLeftSample);
206 nTotalRightSample = BURN_SND_CLIP(nTotalRightSample);
207
208 if (bYM2610AddSignal) {
209 // pSoundBuf[i + 0] += nTotalLeftSample;
210 // pSoundBuf[i + 1] += nTotalRightSample;
211 pSoundBuf[i + 0] = BURN_SND_CLIP(pSoundBuf[i + 0] + nTotalLeftSample);
212 pSoundBuf[i + 1] = BURN_SND_CLIP(pSoundBuf[i + 1] + nTotalRightSample);
213 } else {
214 pSoundBuf[i + 0] = nTotalLeftSample;
215 pSoundBuf[i + 1] = nTotalRightSample;
216 }
217 }
218
219 if (nSegmentEnd >= nBurnSoundLen) {
220 INT32 nExtraSamples = nSamplesNeeded - (nFractionalPosition >> 16);
221
222 for (INT32 i = -4; i < nExtraSamples; i++) {
223 pYM2610Buffer[0][i] = pYM2610Buffer[0][(nFractionalPosition >> 16) + i];
224 pYM2610Buffer[1][i] = pYM2610Buffer[1][(nFractionalPosition >> 16) + i];
225 pYM2610Buffer[2][i] = pYM2610Buffer[2][(nFractionalPosition >> 16) + i];
226 pYM2610Buffer[3][i] = pYM2610Buffer[3][(nFractionalPosition >> 16) + i];
227 pYM2610Buffer[4][i] = pYM2610Buffer[4][(nFractionalPosition >> 16) + i];
228 }
229
230 nFractionalPosition &= 0xFFFF;
231
232 nYM2610Position = nExtraSamples;
233 nAY8910Position = nExtraSamples;
234
235 dTime += 100.0 / nBurnFPS;
236 }
237 }
238
YM2610UpdateNormal(INT16 * pSoundBuf,INT32 nSegmentEnd)239 static void YM2610UpdateNormal(INT16* pSoundBuf, INT32 nSegmentEnd)
240 {
241 #if defined FBA_DEBUG
242 if (!DebugSnd_YM2610Initted) bprintf(PRINT_ERROR, _T("YM2610UpdateNormal called without init\n"));
243 #endif
244
245 INT32 nSegmentLength = nSegmentEnd;
246
247 if (nSegmentEnd < nAY8910Position) {
248 nSegmentEnd = nAY8910Position;
249 }
250 if (nSegmentEnd < nYM2610Position) {
251 nSegmentEnd = nYM2610Position;
252 }
253
254 if (nSegmentLength > nBurnSoundLen) {
255 nSegmentLength = nBurnSoundLen;
256 }
257
258 YM2610Render(nSegmentEnd);
259 AY8910Render(nSegmentEnd);
260
261 pYM2610Buffer[0] = pBuffer + 4 + 0 * 4096;
262 pYM2610Buffer[1] = pBuffer + 4 + 1 * 4096;
263 pYM2610Buffer[2] = pBuffer + 4 + 2 * 4096;
264 pYM2610Buffer[3] = pBuffer + 4 + 3 * 4096;
265 pYM2610Buffer[4] = pBuffer + 4 + 4 * 4096;
266
267 for (INT32 n = nFractionalPosition; n < nSegmentLength; n++) {
268 INT32 nAYSample, nLeftSample = 0, nRightSample = 0;
269
270 nAYSample = pYM2610Buffer[2][n];
271 nAYSample += pYM2610Buffer[3][n];
272 nAYSample += pYM2610Buffer[4][n];
273
274 if (bYM2610UseSeperateVolumes) {
275 nLeftSample += (INT32)(nAYSample * YM2610LeftVolumes[BURN_SND_YM2610_AY8910_ROUTE]);
276 nLeftSample += (INT32)(pYM2610Buffer[0][n] * YM2610LeftVolumes[BURN_SND_YM2610_YM2610_ROUTE_1]);
277 nLeftSample += (INT32)(pYM2610Buffer[1][n] * YM2610LeftVolumes[BURN_SND_YM2610_YM2610_ROUTE_2]);
278
279 nRightSample += (INT32)(nAYSample * YM2610RightVolumes[BURN_SND_YM2610_AY8910_ROUTE]);
280 nRightSample += (INT32)(pYM2610Buffer[0][n] * YM2610RightVolumes[BURN_SND_YM2610_YM2610_ROUTE_1]);
281 nRightSample += (INT32)(pYM2610Buffer[1][n] * YM2610RightVolumes[BURN_SND_YM2610_YM2610_ROUTE_2]);
282 } else {
283 if ((YM2610RouteDirs[BURN_SND_YM2610_AY8910_ROUTE] & BURN_SND_ROUTE_LEFT) == BURN_SND_ROUTE_LEFT) {
284 nLeftSample += (INT32)(nAYSample * YM2610Volumes[BURN_SND_YM2610_AY8910_ROUTE]);
285 }
286 if ((YM2610RouteDirs[BURN_SND_YM2610_AY8910_ROUTE] & BURN_SND_ROUTE_RIGHT) == BURN_SND_ROUTE_RIGHT) {
287 nRightSample += (INT32)(nAYSample * YM2610Volumes[BURN_SND_YM2610_AY8910_ROUTE]);
288 }
289
290 if ((YM2610RouteDirs[BURN_SND_YM2610_YM2610_ROUTE_1] & BURN_SND_ROUTE_LEFT) == BURN_SND_ROUTE_LEFT) {
291 nLeftSample += (INT32)(pYM2610Buffer[0][n] * YM2610Volumes[BURN_SND_YM2610_YM2610_ROUTE_1]);
292 }
293 if ((YM2610RouteDirs[BURN_SND_YM2610_YM2610_ROUTE_1] & BURN_SND_ROUTE_RIGHT) == BURN_SND_ROUTE_RIGHT) {
294 nRightSample += (INT32)(pYM2610Buffer[0][n] * YM2610Volumes[BURN_SND_YM2610_YM2610_ROUTE_1]);
295 }
296
297 if ((YM2610RouteDirs[BURN_SND_YM2610_YM2610_ROUTE_2] & BURN_SND_ROUTE_LEFT) == BURN_SND_ROUTE_LEFT) {
298 nLeftSample += (INT32)(pYM2610Buffer[1][n] * YM2610Volumes[BURN_SND_YM2610_YM2610_ROUTE_2]);
299 }
300 if ((YM2610RouteDirs[BURN_SND_YM2610_YM2610_ROUTE_2] & BURN_SND_ROUTE_RIGHT) == BURN_SND_ROUTE_RIGHT) {
301 nRightSample += (INT32)(pYM2610Buffer[1][n] * YM2610Volumes[BURN_SND_YM2610_YM2610_ROUTE_2]);
302 }
303 }
304
305 nLeftSample = BURN_SND_CLIP(nLeftSample);
306 nRightSample = BURN_SND_CLIP(nRightSample);
307
308 if (bYM2610AddSignal) {
309 //pSoundBuf[(n << 1) + 0] += nLeftSample;
310 //pSoundBuf[(n << 1) + 1] += nRightSample;
311 pSoundBuf[(n << 1) + 0] = BURN_SND_CLIP(pSoundBuf[(n << 1) + 0] + nLeftSample);
312 pSoundBuf[(n << 1) + 1] = BURN_SND_CLIP(pSoundBuf[(n << 1) + 1] + nRightSample);
313 } else {
314 pSoundBuf[(n << 1) + 0] = nLeftSample;
315 pSoundBuf[(n << 1) + 1] = nRightSample;
316 }
317 }
318
319 nFractionalPosition = nSegmentLength;
320
321 if (nSegmentEnd >= nBurnSoundLen) {
322 INT32 nExtraSamples = nSegmentEnd - nBurnSoundLen;
323
324 for (INT32 i = 0; i < nExtraSamples; i++) {
325 pYM2610Buffer[0][i] = pYM2610Buffer[0][nBurnSoundLen + i];
326 pYM2610Buffer[1][i] = pYM2610Buffer[1][nBurnSoundLen + i];
327 pYM2610Buffer[2][i] = pYM2610Buffer[2][nBurnSoundLen + i];
328 pYM2610Buffer[3][i] = pYM2610Buffer[3][nBurnSoundLen + i];
329 pYM2610Buffer[4][i] = pYM2610Buffer[4][nBurnSoundLen + i];
330 }
331
332 nFractionalPosition = 0;
333
334 nYM2610Position = nExtraSamples;
335 nAY8910Position = nExtraSamples;
336
337 dTime += 100.0 / nBurnFPS;
338 }
339 }
340
341 // ----------------------------------------------------------------------------
342 // Callbacks for YM2610 core
343
BurnYM2610UpdateRequest()344 void BurnYM2610UpdateRequest()
345 {
346 #if defined FBA_DEBUG
347 if (!DebugSnd_YM2610Initted) bprintf(PRINT_ERROR, _T("YM2610UpdateRequest called without init\n"));
348 #endif
349
350 YM2610Render(BurnYM2610StreamCallback(nBurnYM2610SoundRate));
351 }
352
BurnAY8910UpdateRequest()353 static void BurnAY8910UpdateRequest()
354 {
355 #if defined FBA_DEBUG
356 if (!DebugSnd_YM2610Initted) bprintf(PRINT_ERROR, _T("BurnYM2610 BurnAY8910UpdateRequest called without init\n"));
357 #endif
358
359 AY8910Render(BurnYM2610StreamCallback(nBurnYM2610SoundRate));
360 }
361
362 // ----------------------------------------------------------------------------
363 // Initialisation, etc.
364
BurnYM2610Reset()365 void BurnYM2610Reset()
366 {
367 #if defined FBA_DEBUG
368 if (!DebugSnd_YM2610Initted) bprintf(PRINT_ERROR, _T("BurnYM2610Reset called without init\n"));
369 #endif
370
371 BurnTimerReset();
372
373 YM2610ResetChip(0);
374 }
375
BurnYM2610Exit()376 void BurnYM2610Exit()
377 {
378 #if defined FBA_DEBUG
379 if (!DebugSnd_YM2610Initted) bprintf(PRINT_ERROR, _T("BurnYM2610Exit called without init\n"));
380 #endif
381
382 if (!DebugSnd_YM2610Initted) return;
383
384 YM2610Shutdown();
385 AY8910Exit(0);
386
387 BurnTimerExit();
388
389 BurnFree(pBuffer);
390 BurnFree(pAYBuffer);
391
392 bYM2610AddSignal = 0;
393 bYM2610UseSeperateVolumes = 0;
394
395 DebugSnd_YM2610Initted = 0;
396 }
397
BurnYM2610MapADPCMROM(UINT8 * YM2610ADPCMAROM,INT32 nYM2610ADPCMASize,UINT8 * YM2610ADPCMBROM,INT32 nYM2610ADPCMBSize)398 void BurnYM2610MapADPCMROM(UINT8* YM2610ADPCMAROM, INT32 nYM2610ADPCMASize, UINT8* YM2610ADPCMBROM, INT32 nYM2610ADPCMBSize)
399 {
400 #if defined FBA_DEBUG
401 if (!DebugSnd_YM2610Initted) bprintf(PRINT_ERROR, _T("BurnYM2610MapADPCMROM called without init\n"));
402 #endif
403
404 YM2610SetRom(0, YM2610ADPCMAROM, nYM2610ADPCMASize, YM2610ADPCMBROM, nYM2610ADPCMBSize);
405 }
406
BurnYM2610Init(INT32 nClockFrequency,UINT8 * YM2610ADPCMAROM,INT32 * nYM2610ADPCMASize,UINT8 * YM2610ADPCMBROM,INT32 * nYM2610ADPCMBSize,FM_IRQHANDLER IRQCallback,INT32 bAddSignal)407 INT32 BurnYM2610Init(INT32 nClockFrequency, UINT8* YM2610ADPCMAROM, INT32* nYM2610ADPCMASize, UINT8* YM2610ADPCMBROM, INT32* nYM2610ADPCMBSize, FM_IRQHANDLER IRQCallback, INT32 bAddSignal)
408 {
409 return BurnYM2610Init(nClockFrequency, YM2610ADPCMAROM, nYM2610ADPCMASize, YM2610ADPCMBROM, nYM2610ADPCMBSize, IRQCallback, BurnSynchroniseStream, BurnGetTime, bAddSignal);
410 }
411
BurnYM2610Init(INT32 nClockFrequency,UINT8 * YM2610ADPCMAROM,INT32 * nYM2610ADPCMASize,UINT8 * YM2610ADPCMBROM,INT32 * nYM2610ADPCMBSize,FM_IRQHANDLER IRQCallback,INT32 (* StreamCallback)(INT32),double (* GetTimeCallback)(),INT32 bAddSignal)412 INT32 BurnYM2610Init(INT32 nClockFrequency, UINT8* YM2610ADPCMAROM, INT32* nYM2610ADPCMASize, UINT8* YM2610ADPCMBROM, INT32* nYM2610ADPCMBSize, FM_IRQHANDLER IRQCallback, INT32 (*StreamCallback)(INT32), double (*GetTimeCallback)(), INT32 bAddSignal)
413 {
414 DebugSnd_YM2610Initted = 1;
415
416 BurnTimerInit(&YM2610TimerOver, GetTimeCallback);
417
418 if (nBurnSoundRate <= 0) {
419 BurnYM2610StreamCallback = YM2610StreamCallbackDummy;
420
421 BurnYM2610Update = YM2610UpdateDummy;
422
423 AY8910InitYM(0, nClockFrequency, 11025, NULL, NULL, NULL, NULL, BurnAY8910UpdateRequest);
424 YM2610Init(1, nClockFrequency, 11025, (void**)(&YM2610ADPCMAROM), nYM2610ADPCMASize, (void**)(&YM2610ADPCMBROM), nYM2610ADPCMBSize, &BurnOPNTimerCallback, IRQCallback);
425 return 0;
426 }
427
428 BurnYM2610StreamCallback = StreamCallback;
429
430 if (nFMInterpolation == 3) {
431 // Set YM2610 core samplerate to match the hardware
432 nBurnYM2610SoundRate = nClockFrequency / 144;
433 // Bring YM2610 core samplerate within usable range
434 while (nBurnYM2610SoundRate > nBurnSoundRate * 3) {
435 nBurnYM2610SoundRate >>= 1;
436 }
437
438 BurnYM2610Update = YM2610UpdateResample;
439
440 nSampleSize = (UINT32)nBurnYM2610SoundRate * (1 << 16) / nBurnSoundRate;
441 } else {
442 nBurnYM2610SoundRate = nBurnSoundRate;
443
444 BurnYM2610Update = YM2610UpdateNormal;
445 }
446
447 AY8910InitYM(0, nClockFrequency, nBurnYM2610SoundRate, NULL, NULL, NULL, NULL, BurnAY8910UpdateRequest);
448 YM2610Init(1, nClockFrequency, nBurnYM2610SoundRate, (void**)(&YM2610ADPCMAROM), nYM2610ADPCMASize, (void**)(&YM2610ADPCMBROM), nYM2610ADPCMBSize, &BurnOPNTimerCallback, IRQCallback);
449
450 pBuffer = (INT16*)BurnMalloc(4096 * 6 * sizeof(INT16));
451 memset(pBuffer, 0, 4096 * 6 * sizeof(INT16));
452
453 pAYBuffer = (INT32*)BurnMalloc(4096 * sizeof(INT32));
454 memset(pAYBuffer, 0, 4096 * sizeof(INT32));
455
456 nYM2610Position = 0;
457 nAY8910Position = 0;
458
459 nFractionalPosition = 0;
460 bYM2610AddSignal = bAddSignal;
461
462 // default routes
463 YM2610Volumes[BURN_SND_YM2610_YM2610_ROUTE_1] = 1.00;
464 YM2610Volumes[BURN_SND_YM2610_YM2610_ROUTE_2] = 1.00;
465 YM2610Volumes[BURN_SND_YM2610_AY8910_ROUTE] = 1.00;
466 YM2610RouteDirs[BURN_SND_YM2610_YM2610_ROUTE_1] = BURN_SND_ROUTE_LEFT;
467 YM2610RouteDirs[BURN_SND_YM2610_YM2610_ROUTE_2] = BURN_SND_ROUTE_RIGHT;
468 YM2610RouteDirs[BURN_SND_YM2610_AY8910_ROUTE] = BURN_SND_ROUTE_BOTH;
469
470 bYM2610UseSeperateVolumes = 0;
471 YM2610LeftVolumes[BURN_SND_YM2610_YM2610_ROUTE_1] = 1.00;
472 YM2610LeftVolumes[BURN_SND_YM2610_YM2610_ROUTE_2] = 1.00;
473 YM2610LeftVolumes[BURN_SND_YM2610_AY8910_ROUTE] = 1.00;
474 YM2610RightVolumes[BURN_SND_YM2610_YM2610_ROUTE_1] = 1.00;
475 YM2610RightVolumes[BURN_SND_YM2610_YM2610_ROUTE_2] = 1.00;
476 YM2610RightVolumes[BURN_SND_YM2610_AY8910_ROUTE] = 1.00;
477
478 return 0;
479 }
480
BurnYM2610SetRoute(INT32 nIndex,double nVolume,INT32 nRouteDir)481 void BurnYM2610SetRoute(INT32 nIndex, double nVolume, INT32 nRouteDir)
482 {
483 #if defined FBA_DEBUG
484 if (!DebugSnd_YM2610Initted) bprintf(PRINT_ERROR, _T("BurnYM2610SetRoute called without init\n"));
485 if (nIndex < 0 || nIndex > 2) bprintf(PRINT_ERROR, _T("BurnYM2610SetRoute called with invalid index %i\n"), nIndex);
486 #endif
487
488 YM2610Volumes[nIndex] = nVolume;
489 YM2610RouteDirs[nIndex] = nRouteDir;
490 }
491
BurnYM2610SetLeftVolume(INT32 nIndex,double nLeftVolume)492 void BurnYM2610SetLeftVolume(INT32 nIndex, double nLeftVolume)
493 {
494 #if defined FBA_DEBUG
495 if (!DebugSnd_YM2610Initted) bprintf(PRINT_ERROR, _T("BurnYM2610SetLeftVolume called without init\n"));
496 if (nIndex < 0 || nIndex > 2) bprintf(PRINT_ERROR, _T("BurnYM2610SetLeftVolume called with invalid index %i\n"), nIndex);
497 #endif
498
499 YM2610LeftVolumes[nIndex] = nLeftVolume;
500 }
501
BurnYM2610SetRightVolume(INT32 nIndex,double nRightVolume)502 void BurnYM2610SetRightVolume(INT32 nIndex, double nRightVolume)
503 {
504 #if defined FBA_DEBUG
505 if (!DebugSnd_YM2610Initted) bprintf(PRINT_ERROR, _T("BurnYM2610SetRightVolume called without init\n"));
506 if (nIndex < 0 || nIndex > 2) bprintf(PRINT_ERROR, _T("BurnYM2610SetRightVolume called with invalid index %i\n"), nIndex);
507 #endif
508
509 YM2610RightVolumes[nIndex] = nRightVolume;
510 }
511
BurnYM2610Scan(INT32 nAction,INT32 * pnMin)512 void BurnYM2610Scan(INT32 nAction, INT32* pnMin)
513 {
514 #if defined FBA_DEBUG
515 if (!DebugSnd_YM2610Initted) bprintf(PRINT_ERROR, _T("BurnYM2610Scan called without init\n"));
516 #endif
517
518 BurnTimerScan(nAction, pnMin);
519 AY8910Scan(nAction, pnMin);
520
521 if (nAction & ACB_DRIVER_DATA) {
522 SCAN_VAR(nYM2610Position);
523 SCAN_VAR(nAY8910Position);
524 }
525 }
526