1 /***************************************************************************
2
3 2151intf.c
4
5 Support interface YM2151(OPM)
6
7 ***************************************************************************/
8
9 #include "driver.h"
10 #include "fm.h"
11 #include "ym2151.h"
12
13
14 /* for stream system */
15 static int stream[MAX_2151];
16
17 static const struct YM2151interface *intf;
18
19 static int FMMode;
20 #define CHIP_YM2151_DAC 4 /* use Tatsuyuki's FM.C */
21 #define CHIP_YM2151_ALT 5 /* use Jarek's YM2151.C */
22
23
24 #if (HAS_YM2151)
25
26 #define YM2151_NUMBUF 2
27
28 static void *Timer[MAX_2151][2];
29
30 /* IRQ Handler */
IRQHandler(int n,int irq)31 static void IRQHandler(int n,int irq)
32 {
33 if(intf->irqhandler[n]) intf->irqhandler[n](irq);
34 }
35
timer_callback_2151(int param)36 static void timer_callback_2151(int param)
37 {
38 int n=param&0x7f;
39 int c=param>>7;
40
41 Timer[n][c] = 0;
42 YM2151TimerOver(n,c);
43 }
44
45 /* TimerHandler from fm.c */
TimerHandler(int n,int c,int count,timer_tm stepTime)46 static void TimerHandler(int n,int c,int count,timer_tm stepTime)
47 {
48 if( count == 0 )
49 { /* Reset FM Timer */
50 if( Timer[n][c] )
51 {
52 timer_remove (Timer[n][c]);
53 Timer[n][c] = 0;
54 }
55 }
56 else
57 { /* Start FM Timer */
58 timer_tm timeSec = (timer_tm)count * stepTime;
59
60 if( Timer[n][c] == 0 )
61 {
62 Timer[n][c] = timer_set (timeSec, (c<<7)|n, timer_callback_2151 );
63 }
64 }
65 }
66
67 #endif
68
69 /* update request from fm.c */
YM2151UpdateRequest(int chip)70 void YM2151UpdateRequest(int chip)
71 {
72 stream_update(stream[chip],0);
73 }
74
my_YM2151_sh_start(const struct MachineSound * msound,int mode)75 static int my_YM2151_sh_start(const struct MachineSound *msound,int mode)
76 {
77 int i,j;
78 int rate = Machine->sample_rate;
79 char buf[YM2151_NUMBUF][40];
80 const char *name[YM2151_NUMBUF];
81 int mixed_vol,vol[YM2151_NUMBUF];
82
83 if( rate == 0 ) rate = 1000; /* kludge to prevent nasty crashes */
84
85 intf = msound->sound_interface;
86
87 if( mode ) FMMode = CHIP_YM2151_ALT;
88 else FMMode = CHIP_YM2151_DAC;
89
90 switch(FMMode)
91 {
92 #if (HAS_YM2151)
93 case CHIP_YM2151_DAC: /* Tatsuyuki's */
94 /* stream system initialize */
95 for (i = 0;i < intf->num;i++)
96 {
97 mixed_vol = intf->volume[i];
98 /* stream setup */
99 for (j = 0 ; j < YM2151_NUMBUF ; j++)
100 {
101 name[j]=buf[j];
102 vol[j] = mixed_vol & 0xffff;
103 mixed_vol>>=16;
104 sprintf(buf[j],"%s #%d Ch%d",sound_name(msound),i,j+1);
105 }
106 #ifndef MAME_FASTSOUND
107 stream[i] = stream_init_multi(YM2151_NUMBUF,name,vol,rate,i,OPMUpdateOne);
108 #else
109 {
110 extern int fast_sound;
111 if (fast_sound)
112 stream[i] = stream_init_multi(YM2151_NUMBUF,name,vol,rate/2,i,OPMUpdateOne);
113 else
114 stream[i] = stream_init_multi(YM2151_NUMBUF,name,vol,rate,i,OPMUpdateOne);
115 }
116 #endif
117 }
118 /* Set Timer handler */
119 for (i = 0; i < intf->num; i++)
120 Timer[i][0] =Timer[i][1] = 0;
121 i=OPMInit(intf->num,intf->baseclock,Machine->sample_rate,TimerHandler,IRQHandler);
122 if (i == 0)
123 {
124 /* set port handler */
125 for (i = 0; i < intf->num; i++)
126 OPMSetPortHander(i,intf->portwritehandler[i]);
127 return 0;
128 }
129 /* error */
130 return 1;
131 #endif
132 #if (HAS_YM2151_ALT)
133 case CHIP_YM2151_ALT: /* Jarek's */
134 /* stream system initialize */
135 for (i = 0;i < intf->num;i++)
136 {
137 /* stream setup */
138 mixed_vol = intf->volume[i];
139 for (j = 0 ; j < YM2151_NUMBUF ; j++)
140 {
141 name[j]=buf[j];
142 vol[j] = mixed_vol & 0xffff;
143 mixed_vol>>=16;
144 sprintf(buf[j],"%s #%d Ch%d",sound_name(msound),i,j+1);
145 }
146 #ifndef MAME_FASTSOUND
147 stream[i] = stream_init_multi(YM2151_NUMBUF,name,vol,rate,i,YM2151UpdateOne);
148 #else
149 {
150 extern int fast_sound;
151 if (fast_sound)
152 stream[i] = stream_init_multi(YM2151_NUMBUF,name,vol,rate/2,i,YM2151UpdateOne);
153 else
154 stream[i] = stream_init_multi(YM2151_NUMBUF,name,vol,rate,i,YM2151UpdateOne);
155 }
156 #endif
157 }
158 if (YM2151Init(intf->num,intf->baseclock,Machine->sample_rate) == 0)
159 {
160 for (i = 0; i < intf->num; i++)
161 {
162 YM2151SetIrqHandler(i,intf->irqhandler[i]);
163 YM2151SetPortWriteHandler(i,intf->portwritehandler[i]);
164 }
165 return 0;
166 }
167 return 1;
168 #endif
169 }
170 return 1;
171 }
172
173 #if (HAS_YM2151)
YM2151_sh_start(const struct MachineSound * msound)174 int YM2151_sh_start(const struct MachineSound *msound)
175 {
176 return my_YM2151_sh_start(msound,0);
177 }
178 #endif
179 #if (HAS_YM2151_ALT)
YM2151_sh_start(const struct MachineSound * msound)180 int YM2151_sh_start(const struct MachineSound *msound)
181 {
182 return my_YM2151_sh_start(msound,1);
183 }
184 #endif
185
YM2151_sh_stop(void)186 void YM2151_sh_stop(void)
187 {
188 switch(FMMode)
189 {
190 #if (HAS_YM2151)
191 case CHIP_YM2151_DAC:
192 OPMShutdown();
193 break;
194 #endif
195 #if (HAS_YM2151_ALT)
196 case CHIP_YM2151_ALT:
197 YM2151Shutdown();
198 break;
199 #endif
200 }
201 }
202
YM2151_sh_reset(void)203 void YM2151_sh_reset(void)
204 {
205 int i;
206
207 for (i = 0;i < intf->num;i++)
208 switch(FMMode)
209 {
210 #if (HAS_YM2151)
211 case CHIP_YM2151_DAC:
212 OPMResetChip(i);
213 break;
214 #endif
215 #if (HAS_YM2151_ALT)
216 case CHIP_YM2151_ALT:
217 YM2151ResetChip(i);
218 break;
219 #endif
220 }
221
222 }
223
224 static int lastreg0,lastreg1,lastreg2;
225
READ_HANDLER(YM2151_status_port_0_r)226 READ_HANDLER( YM2151_status_port_0_r )
227 {
228 switch(FMMode)
229 {
230 #if (HAS_YM2151)
231 case CHIP_YM2151_DAC:
232 return YM2151Read(0,1);
233 #endif
234 #if (HAS_YM2151_ALT)
235 case CHIP_YM2151_ALT:
236 return YM2151ReadStatus(0);
237 #endif
238 }
239 return 0;
240 }
241
READ_HANDLER(YM2151_status_port_1_r)242 READ_HANDLER( YM2151_status_port_1_r )
243 {
244 switch(FMMode)
245 {
246 #if (HAS_YM2151)
247 case CHIP_YM2151_DAC:
248 return YM2151Read(1,1);
249 #endif
250 #if (HAS_YM2151_ALT)
251 case CHIP_YM2151_ALT:
252 return YM2151ReadStatus(1);
253 #endif
254 }
255 return 0;
256 }
257
READ_HANDLER(YM2151_status_port_2_r)258 READ_HANDLER( YM2151_status_port_2_r )
259 {
260 switch(FMMode)
261 {
262 #if (HAS_YM2151)
263 case CHIP_YM2151_DAC:
264 return YM2151Read(2,1);
265 #endif
266 #if (HAS_YM2151_ALT)
267 case CHIP_YM2151_ALT:
268 return YM2151ReadStatus(2);
269 #endif
270 }
271 return 0;
272 }
273
WRITE_HANDLER(YM2151_register_port_0_w)274 WRITE_HANDLER( YM2151_register_port_0_w )
275 {
276 lastreg0 = data;
277 }
WRITE_HANDLER(YM2151_register_port_1_w)278 WRITE_HANDLER( YM2151_register_port_1_w )
279 {
280 lastreg1 = data;
281 }
WRITE_HANDLER(YM2151_register_port_2_w)282 WRITE_HANDLER( YM2151_register_port_2_w )
283 {
284 lastreg2 = data;
285 }
286
WRITE_HANDLER(YM2151_data_port_0_w)287 WRITE_HANDLER( YM2151_data_port_0_w )
288 {
289 switch(FMMode)
290 {
291 #if (HAS_YM2151)
292 case CHIP_YM2151_DAC:
293 YM2151Write(0,0,lastreg0);
294 YM2151Write(0,1,data);
295 break;
296 #endif
297 #if (HAS_YM2151_ALT)
298 case CHIP_YM2151_ALT:
299 YM2151UpdateRequest(0);
300 YM2151WriteReg(0,lastreg0,data);
301 break;
302 #endif
303 }
304 }
305
WRITE_HANDLER(YM2151_data_port_1_w)306 WRITE_HANDLER( YM2151_data_port_1_w )
307 {
308 switch(FMMode)
309 {
310 #if (HAS_YM2151)
311 case CHIP_YM2151_DAC:
312 YM2151Write(1,0,lastreg1);
313 YM2151Write(1,1,data);
314 break;
315 #endif
316 #if (HAS_YM2151_ALT)
317 case CHIP_YM2151_ALT:
318 YM2151UpdateRequest(1);
319 YM2151WriteReg(1,lastreg1,data);
320 break;
321 #endif
322 }
323 }
324
WRITE_HANDLER(YM2151_data_port_2_w)325 WRITE_HANDLER( YM2151_data_port_2_w )
326 {
327 switch(FMMode)
328 {
329 #if (HAS_YM2151)
330 case CHIP_YM2151_DAC:
331 YM2151Write(2,0,lastreg2);
332 YM2151Write(2,1,data);
333 break;
334 #endif
335 #if (HAS_YM2151_ALT)
336 case CHIP_YM2151_ALT:
337 YM2151UpdateRequest(2);
338 YM2151WriteReg(2,lastreg2,data);
339 break;
340 #endif
341 }
342 }
343