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