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