1 /*****************************************************************************
2 ** $Source: /cygdrive/d/Private/_SVNROOT/bluemsx/blueMSX/Src/SoundChips/ym2151.c,v $
3 **
4 ** $Revision: 1.13 $
5 **
6 ** $Date: 2008-03-31 19:42:23 $
7 **
8 ** More info: http://www.bluemsx.com
9 **
10 ** Copyright (C) 2003-2006 Daniel Vik
11 **
12 ** This program is free software; you can redistribute it and/or modify
13 ** it under the terms of the GNU General Public License as published by
14 ** the Free Software Foundation; either version 2 of the License, or
15 ** (at your option) any later version.
16 **
17 ** This program is distributed in the hope that it will be useful,
18 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
19 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 ** GNU General Public License for more details.
21 **
22 ** You should have received a copy of the GNU General Public License
23 ** along with this program; if not, write to the Free Software
24 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 **
26 ******************************************************************************
27 */
28 #include "ym2151.h"
29 #include "MameYM2151.h"
30 #include "Board.h"
31 #include "SaveState.h"
32 #include "IoPort.h"
33 #include "MediaDb.h"
34 #include "DeviceManager.h"
35 #include <stdlib.h>
36 #include <string.h>
37
38 #define FREQUENCY 3579545
39 #define SAMPLERATE (FREQUENCY / 64 )
40 #define TIMER_FREQUENCY (boardFrequency() / (SAMPLERATE / 1)) // Divided by 2 ???
41
42
43 struct YM2151 {
44 Mixer* mixer;
45 Int32 handle;
46 UInt32 rate;
47
48 MameYm2151* opl;
49 BoardTimer* timer1;
50 BoardTimer* timer2;
51 UInt32 timerValue1;
52 UInt32 timerValue2;
53 UInt32 timeout1;
54 UInt32 timeout2;
55 UInt32 timerRunning1;
56 UInt32 timerRunning2;
57 UInt8 address;
58 UInt8 latch;
59 UInt8 irqVector;
60 int irqState;
61 // Variables used for resampling
62 Int32 off;
63 Int32 s1l;
64 Int32 s2l;
65 Int32 s1r;
66 Int32 s2r;
67 Int32 buffer[AUDIO_STEREO_BUFFER_SIZE];
68 };
69
70 void ym2151TimerStart(void* ptr, int timer, int start);
71
72
ym2151TimerSet(void * ref,int timer,int count)73 void ym2151TimerSet(void* ref, int timer, int count)
74 {
75 YM2151* ym2151 = (YM2151*)ref;
76
77 if (timer == 0) {
78 ym2151->timerValue1 = count;
79 }
80 else {
81 ym2151->timerValue2 = count;
82 }
83 }
84
ym2151SetIrq(void * ptr,int timer)85 void ym2151SetIrq(void* ptr, int timer)
86 {
87 YM2151* ym2151 = (YM2151*)ptr;
88 if (ym2151->irqState == 0) {
89 boardSetDataBus(ym2151->irqVector, 0, 0);
90 boardSetInt(0x40);
91 }
92 ym2151->irqState |= timer;
93 }
94
ym2151ClearIrq(void * ptr,int timer)95 void ym2151ClearIrq(void* ptr, int timer)
96 {
97 YM2151* ym2151 = (YM2151*)ptr;
98 ym2151->irqState &= ~timer;
99 if (ym2151->irqState == 0) {
100 boardClearInt(0x40);
101 }
102 }
103
ym2151WritePortCallback(void * ref,UInt32 port,UInt8 value)104 void ym2151WritePortCallback(void* ref, UInt32 port, UInt8 value)
105 {
106 }
107
onTimeout1(void * ptr,UInt32 time)108 static void onTimeout1(void* ptr, UInt32 time)
109 {
110 YM2151* ym2151 = (YM2151*)ptr;
111 ym2151->timerRunning1 = 0;
112 YM2151TimerCallback(ym2151->opl, 0);
113 ym2151TimerStart(ptr, 0, 1);
114 }
115
onTimeout2(void * ptr,UInt32 time)116 static void onTimeout2(void* ptr, UInt32 time)
117 {
118 YM2151* ym2151 = (YM2151*)ptr;
119 ym2151->timerRunning2 = 0;
120 YM2151TimerCallback(ym2151->opl, 1);
121 ym2151TimerStart(ptr, 1, 1);
122 }
123
ym2151TimerStart(void * ptr,int timer,int start)124 void ym2151TimerStart(void* ptr, int timer, int start)
125 {
126 YM2151* ym2151 = (YM2151*)ptr;
127
128 if (timer == 0) {
129 if (start != 0) {
130 if (!ym2151->timerRunning1) {
131 UInt32 systemTime = boardSystemTime();
132 UInt32 adjust = systemTime % TIMER_FREQUENCY;
133 ym2151->timeout1 = systemTime + TIMER_FREQUENCY * ym2151->timerValue1 - adjust;
134 boardTimerAdd(ym2151->timer1, ym2151->timeout1);
135 ym2151->timerRunning1 = 1;
136 }
137 }
138 else {
139 if (ym2151->timerRunning1) {
140 boardTimerRemove(ym2151->timer1);
141 ym2151->timerRunning1 = 0;
142 }
143 }
144 }
145 else {
146 if (start != 0) {
147 if (!ym2151->timerRunning2) {
148 UInt32 systemTime = boardSystemTime();
149 UInt32 adjust = systemTime % (16 * TIMER_FREQUENCY);
150 ym2151->timeout2 = systemTime + TIMER_FREQUENCY * ym2151->timerValue2 - adjust;
151 boardTimerAdd(ym2151->timer2, ym2151->timeout2);
152 ym2151->timerRunning2 = 1;
153 }
154 }
155 else {
156 if (ym2151->timerRunning2) {
157 boardTimerRemove(ym2151->timer2);
158 ym2151->timerRunning2 = 0;
159 }
160 }
161 }
162 }
163
ym2151SetIrqVector(YM2151 * ym2151,UInt8 irqVector)164 void ym2151SetIrqVector(YM2151* ym2151, UInt8 irqVector)
165 {
166 ym2151->irqVector = irqVector;
167 }
168
ym2151Peek(YM2151 * ym2151,UInt16 ioPort)169 UInt8 ym2151Peek(YM2151* ym2151, UInt16 ioPort)
170 {
171 return (UInt8)YM2151ReadStatus(ym2151->opl);
172 }
173
ym2151Read(YM2151 * ym2151,UInt16 ioPort)174 UInt8 ym2151Read(YM2151* ym2151, UInt16 ioPort)
175 {
176 UInt8 value = (UInt8)YM2151ReadStatus(ym2151->opl);
177 return value;
178 }
179
ym2151Write(YM2151 * ym2151,UInt16 ioPort,UInt8 value)180 void ym2151Write(YM2151* ym2151, UInt16 ioPort, UInt8 value)
181 {
182 switch (ioPort & 1) {
183 case 0:
184 ym2151->latch = value;
185 break;
186 case 1:
187 mixerSync(ym2151->mixer);
188 YM2151WriteReg(ym2151->opl, ym2151->latch, value);
189 break;
190 }
191 }
192
ym2151GetDebugInfo(YM2151 * ym2151,DbgDevice * dbgDevice)193 void ym2151GetDebugInfo(YM2151* ym2151, DbgDevice* dbgDevice)
194 {
195 }
196
ym2151Sync(void * ref,UInt32 count)197 static Int32* ym2151Sync(void* ref, UInt32 count)
198 {
199 YM2151* ym2151 = (YM2151*)ref;
200 UInt32 i;
201
202 for (i = 0; i < count; i++) {
203 Int16 sl, sr;
204 ym2151->off -= SAMPLERATE - ym2151->rate;
205 ym2151->s1l = ym2151->s2l;
206 ym2151->s1r = ym2151->s2r;
207 YM2151UpdateOne(ym2151->opl, &sl, &sr, 1);
208 ym2151->s2l = sl;
209 ym2151->s2r = sr;
210 if (ym2151->off < 0) {
211 ym2151->off += ym2151->rate;
212 ym2151->s1l = ym2151->s2l;
213 ym2151->s1r = ym2151->s2r;
214 YM2151UpdateOne(ym2151->opl, &sl, &sr, 1);
215 ym2151->s2l = sl;
216 ym2151->s2r = sr;
217 }
218 ym2151->buffer[2*i+0] = 11*(Int32)((ym2151->s1l * (ym2151->off / 256) + ym2151->s2l * ((SAMPLERATE - ym2151->off) / 256)) / (SAMPLERATE / 256));
219 ym2151->buffer[2*i+1] = 11*(Int32)((ym2151->s1r * (ym2151->off / 256) + ym2151->s2r * ((SAMPLERATE - ym2151->off) / 256)) / (SAMPLERATE / 256));
220 }
221
222 return ym2151->buffer;
223 }
224
225
ym2151SaveState(YM2151 * ym2151)226 void ym2151SaveState(YM2151* ym2151)
227 {
228 SaveState* state = saveStateOpenForWrite("ym2151");
229
230 saveStateSet(state, "address", ym2151->address);
231 saveStateSet(state, "irqState", ym2151->irqState);
232 saveStateSet(state, "latch", ym2151->latch);
233 saveStateSet(state, "timerValue1", ym2151->timerValue1);
234 saveStateSet(state, "timerRunning1", ym2151->timerRunning1);
235 saveStateSet(state, "timeout1", ym2151->timeout1);
236 saveStateSet(state, "timerValue2", ym2151->timerValue2);
237 saveStateSet(state, "timerRunning2", ym2151->timerRunning2);
238 saveStateSet(state, "timeout2", ym2151->timeout2);
239 saveStateSet(state, "irqVector", ym2151->irqVector);
240
241 saveStateClose(state);
242
243 YM2151SaveState(ym2151->opl);
244 }
245
ym2151LoadState(YM2151 * ym2151)246 void ym2151LoadState(YM2151* ym2151)
247 {
248 SaveState* state = saveStateOpenForRead("ym2151");
249
250 ym2151->address = (UInt8)saveStateGet(state, "address", 0);
251 ym2151->irqState = saveStateGet(state, "irqState", 0);
252 ym2151->latch = (UInt8)saveStateGet(state, "latch", 0);
253 ym2151->timerValue1 = saveStateGet(state, "timerValue1", 0);
254 ym2151->timerRunning1 = saveStateGet(state, "timerRunning1", 0);
255 ym2151->timeout1 = saveStateGet(state, "timeout1", 0);
256 ym2151->timerValue2 = saveStateGet(state, "timerValue2", 0);
257 ym2151->timerRunning2 = saveStateGet(state, "timerRunning2", 0);
258 ym2151->timeout2 = saveStateGet(state, "timeout2", 0);
259 ym2151->irqVector = (UInt8)saveStateGet(state, "irqVector", 0);
260
261 saveStateClose(state);
262
263 YM2151LoadState(ym2151->opl);
264
265 if (ym2151->timerRunning1) {
266 boardTimerAdd(ym2151->timer1, ym2151->timeout1);
267 }
268
269 if (ym2151->timerRunning2) {
270 boardTimerAdd(ym2151->timer2, ym2151->timeout2);
271 }
272 }
273
ym2151Destroy(YM2151 * ym2151)274 void ym2151Destroy(YM2151* ym2151)
275 {
276 mixerUnregisterChannel(ym2151->mixer, ym2151->handle);
277 boardTimerDestroy(ym2151->timer1);
278 boardTimerDestroy(ym2151->timer2);
279 YM2151Destroy(ym2151->opl);
280
281 free(ym2151);
282 }
283
ym2151Reset(YM2151 * ym2151)284 void ym2151Reset(YM2151* ym2151)
285 {
286 ym2151->timerRunning1 = 0;
287 ym2151->timerRunning2 = 0;
288 ym2151TimerSet(ym2151, 0, 1024);
289 ym2151TimerSet(ym2151, 1, 16 * 256);
290 ym2151TimerStart(ym2151, 0, 0);
291 ym2151TimerStart(ym2151, 1, 0);
292 // ym2151TimerStart(ym2151, 0, ym2151->timerValue1);
293 // ym2151TimerStart(ym2151, 1, ym2151->timerValue2);
294 YM2151ResetChip(ym2151->opl);
295 ym2151->off = 0;
296 ym2151->s1l = 0;
297 ym2151->s2l = 0;
298 ym2151->s1r = 0;
299 ym2151->s2r = 0;
300 ym2151->latch = 0;
301 ym2151->irqState = 0;
302 }
303
ym2151SetSampleRate(void * ref,UInt32 rate)304 void ym2151SetSampleRate(void* ref, UInt32 rate)
305 {
306 YM2151* ym2151 = (YM2151*)ref;
307 ym2151->rate = rate;
308 }
309
ym2151Create(Mixer * mixer)310 YM2151* ym2151Create(Mixer* mixer)
311 {
312 YM2151* ym2151;
313
314 ym2151 = (YM2151*)calloc(1, sizeof(YM2151));
315
316 ym2151->mixer = mixer;
317
318 ym2151->timer1 = boardTimerCreate(onTimeout1, ym2151);
319 ym2151->timer2 = boardTimerCreate(onTimeout2, ym2151);
320
321 ym2151->handle = mixerRegisterChannel(mixer, MIXER_CHANNEL_YAMAHA_SFG, 1, ym2151Sync, ym2151SetSampleRate, ym2151);
322
323 ym2151->opl = YM2151Create(ym2151, FREQUENCY, SAMPLERATE);
324
325 ym2151->rate = mixerGetSampleRate(mixer);
326
327 ym2151Reset(ym2151);
328
329 return ym2151;
330 }
331
332