1 /******************************************************************************
2 * FILE
3 *   Yamaha 3812 emulator interface - MAME VERSION
4 *
5 * CREATED BY
6 *   Ernesto Corvi
7 *
8 * UPDATE LOG
9 *   JB  28-04-2002  Fixed simultaneous usage of all three different chip types.
10 *                       Used real sample rate when resample filter is active.
11 *       AAT 12-28-2001  Protected Y8950 from accessing unmapped port and keyboard handlers.
12 *   CHS 1999-01-09  Fixes new ym3812 emulation interface.
13 *   CHS 1998-10-23  Mame streaming sound chip update
14 *   EC  1998        Created Interface
15 *
16 * NOTES
17 *
18 ******************************************************************************/
19 #include <stddef.h>	// for NULL
20 #include "mamedef.h"
21 //#include "attotime.h"
22 //#include "sndintrf.h"
23 //#include "streams.h"
24 //#include "cpuintrf.h"
25 #include "3812intf.h"
26 #ifdef ENABLE_ALL_CORES
27 #include "fmopl.h"
28 #endif
29 
30 #define OPLTYPE_IS_OPL2
31 #include "adlibemu.h"
32 
33 
34 #define EC_DBOPL	0x00	// DosBox OPL (AdLibEmu)
35 #ifdef ENABLE_ALL_CORES
36 #define EC_MAME		0x01	// YM3826 core from MAME
37 #endif
38 
39 typedef struct _ym3812_state ym3812_state;
40 struct _ym3812_state
41 {
42 	//sound_stream *	stream;
43 	//emu_timer *		timer[2];
44 	void *			chip;
45 	//const ym3812_interface *intf;
46 	//const device_config *device;
47 };
48 
49 
50 extern UINT8 CHIP_SAMPLING_MODE;
51 extern INT32 CHIP_SAMPLE_RATE;
52 static UINT8 EMU_CORE = 0x00;
53 
54 #define MAX_CHIPS	0x02
55 static ym3812_state YM3812Data[MAX_CHIPS];
56 
57 /*INLINE ym3812_state *get_safe_token(const device_config *device)
58 {
59 	assert(device != NULL);
60 	assert(device->token != NULL);
61 	assert(device->type == SOUND);
62 	assert(sound_get_type(device) == SOUND_YM3812);
63 	return (ym3812_state *)device->token;
64 }*/
65 
66 
67 
IRQHandler(void * param,int irq)68 static void IRQHandler(void *param,int irq)
69 {
70 	ym3812_state *info = (ym3812_state *)param;
71 	//if (info->intf->handler) (info->intf->handler)(info->device, irq ? ASSERT_LINE : CLEAR_LINE);
72 	//if (info->intf->handler) (info->intf->handler)(irq ? ASSERT_LINE : CLEAR_LINE);
73 }
74 /*static TIMER_CALLBACK( timer_callback_0 )
75 {
76 	ym3812_state *info = (ym3812_state *)ptr;
77 	ym3812_timer_over(info->chip,0);
78 }
79 
80 static TIMER_CALLBACK( timer_callback_1 )
81 {
82 	ym3812_state *info = (ym3812_state *)ptr;
83 	ym3812_timer_over(info->chip,1);
84 }*/
85 
86 //static void TimerHandler(void *param,int c,attotime period)
TimerHandler(void * param,int c,int period)87 static void TimerHandler(void *param,int c,int period)
88 {
89 	ym3812_state *info = (ym3812_state *)param;
90 	//if( attotime_compare(period, attotime_zero) == 0 )
91 	if( period == 0 )
92 	{	/* Reset FM Timer */
93 		//timer_enable(info->timer[c], 0);
94 	}
95 	else
96 	{	/* Start FM Timer */
97 		//timer_adjust_oneshot(info->timer[c], period, 0);
98 	}
99 }
100 
101 
102 //static STREAM_UPDATE( ym3812_stream_update )
ym3812_stream_update(UINT8 ChipID,stream_sample_t ** outputs,int samples)103 void ym3812_stream_update(UINT8 ChipID, stream_sample_t **outputs, int samples)
104 {
105 	//ym3812_state *info = (ym3812_state *)param;
106 	ym3812_state *info = &YM3812Data[ChipID];
107 	switch(EMU_CORE)
108 	{
109 #ifdef ENABLE_ALL_CORES
110 	case EC_MAME:
111 		ym3812_update_one(info->chip, outputs, samples);
112 		break;
113 #endif
114 	case EC_DBOPL:
115 		adlib_OPL2_getsample(info->chip, outputs, samples);
116 		break;
117 	}
118 }
119 
_stream_update(void * param)120 static void _stream_update(void * param/*, int interval*/)
121 {
122 	ym3812_state *info = (ym3812_state *)param;
123 	//stream_update(info->stream);
124 
125 	switch(EMU_CORE)
126 	{
127 #ifdef ENABLE_ALL_CORES
128 	case EC_MAME:
129 		ym3812_update_one(info->chip, DUMMYBUF, 0);
130 		break;
131 #endif
132 	case EC_DBOPL:
133 		adlib_OPL2_getsample(info->chip, DUMMYBUF, 0);
134 		break;
135 	}
136 }
137 
138 
139 //static DEVICE_START( ym3812 )
device_start_ym3812(UINT8 ChipID,int clock)140 int device_start_ym3812(UINT8 ChipID, int clock)
141 {
142 	//static const ym3812_interface dummy = { 0 };
143 	//ym3812_state *info = get_safe_token(device);
144 	ym3812_state *info;
145 	int rate;
146 
147 	if (ChipID >= MAX_CHIPS)
148 		return 0;
149 
150 	info = &YM3812Data[ChipID];
151 	rate = (clock & 0x7FFFFFFF)/72;
152 	if ((CHIP_SAMPLING_MODE == 0x01 && rate < CHIP_SAMPLE_RATE) ||
153 		CHIP_SAMPLING_MODE == 0x02)
154 		rate = CHIP_SAMPLE_RATE;
155 	//info->intf = device->static_config ? (const ym3812_interface *)device->static_config : &dummy;
156 	//info->intf = &dummy;
157 	//info->device = device;
158 
159 	/* stream system initialize */
160 	switch(EMU_CORE)
161 	{
162 #ifdef ENABLE_ALL_CORES
163 	case EC_MAME:
164 		info->chip = ym3812_init(clock & 0x7FFFFFFF,rate);
165 		//assert_always(info->chip != NULL, "Error creating YM3812 chip");
166 
167 		//info->stream = stream_create(device,0,1,rate,info,ym3812_stream_update);
168 
169 		/* YM3812 setup */
170 		ym3812_set_timer_handler (info->chip, TimerHandler, info);
171 		ym3812_set_irq_handler   (info->chip, IRQHandler, info);
172 		ym3812_set_update_handler(info->chip, _stream_update, info);
173 
174 		//info->timer[0] = timer_alloc(device->machine, timer_callback_0, info);
175 		//info->timer[1] = timer_alloc(device->machine, timer_callback_1, info);
176 		break;
177 #endif
178 	case EC_DBOPL:
179 		info->chip = adlib_OPL2_init(clock & 0x7FFFFFFF, rate, _stream_update, info);
180 		break;
181 	}
182 
183 	return rate;
184 }
185 
186 //static DEVICE_STOP( ym3812 )
device_stop_ym3812(UINT8 ChipID)187 void device_stop_ym3812(UINT8 ChipID)
188 {
189 	//ym3812_state *info = get_safe_token(device);
190 	ym3812_state *info = &YM3812Data[ChipID];
191 	switch(EMU_CORE)
192 	{
193 #ifdef ENABLE_ALL_CORES
194 	case EC_MAME:
195 		ym3812_shutdown(info->chip);
196 		break;
197 #endif
198 	case EC_DBOPL:
199 		adlib_OPL2_stop(info->chip);
200 		break;
201 	}
202 }
203 
204 //static DEVICE_RESET( ym3812 )
device_reset_ym3812(UINT8 ChipID)205 void device_reset_ym3812(UINT8 ChipID)
206 {
207 	//ym3812_state *info = get_safe_token(device);
208 	ym3812_state *info = &YM3812Data[ChipID];
209 	switch(EMU_CORE)
210 	{
211 #ifdef ENABLE_ALL_CORES
212 	case EC_MAME:
213 		ym3812_reset_chip(info->chip);
214 		break;
215 #endif
216 	case EC_DBOPL:
217 		adlib_OPL2_reset(info->chip);
218 		break;
219 	}
220 }
221 
222 
223 //READ8_DEVICE_HANDLER( ym3812_r )
ym3812_r(UINT8 ChipID,offs_t offset)224 UINT8 ym3812_r(UINT8 ChipID, offs_t offset)
225 {
226 	//ym3812_state *info = get_safe_token(device);
227 	ym3812_state *info = &YM3812Data[ChipID];
228 	switch(EMU_CORE)
229 	{
230 #ifdef ENABLE_ALL_CORES
231 	case EC_MAME:
232 		return ym3812_read(info->chip, offset & 1);
233 #endif
234 	case EC_DBOPL:
235 		return adlib_OPL2_reg_read(info->chip, offset & 0x01);
236 	default:
237 		return 0x00;
238 	}
239 }
240 
241 //WRITE8_DEVICE_HANDLER( ym3812_w )
ym3812_w(UINT8 ChipID,offs_t offset,UINT8 data)242 void ym3812_w(UINT8 ChipID, offs_t offset, UINT8 data)
243 {
244 	//ym3812_state *info = get_safe_token(device);
245 	ym3812_state *info = &YM3812Data[ChipID];
246 	switch(EMU_CORE)
247 	{
248 #ifdef ENABLE_ALL_CORES
249 	case EC_MAME:
250 		ym3812_write(info->chip, offset & 1, data);
251 		break;
252 #endif
253 	case EC_DBOPL:
254 		adlib_OPL2_writeIO(info->chip, offset & 1, data);
255 		break;
256 	}
257 }
258 
259 //READ8_DEVICE_HANDLER( ym3812_status_port_r )
ym3812_status_port_r(UINT8 ChipID,offs_t offset)260 UINT8 ym3812_status_port_r(UINT8 ChipID, offs_t offset)
261 {
262 	return ym3812_r(ChipID, 0);
263 }
264 //READ8_DEVICE_HANDLER( ym3812_read_port_r )
ym3812_read_port_r(UINT8 ChipID,offs_t offset)265 UINT8 ym3812_read_port_r(UINT8 ChipID, offs_t offset)
266 {
267 	return ym3812_r(ChipID, 1);
268 }
269 //WRITE8_DEVICE_HANDLER( ym3812_control_port_w )
ym3812_control_port_w(UINT8 ChipID,offs_t offset,UINT8 data)270 void ym3812_control_port_w(UINT8 ChipID, offs_t offset, UINT8 data)
271 {
272 	ym3812_w(ChipID, 0, data);
273 }
274 //WRITE8_DEVICE_HANDLER( ym3812_write_port_w )
ym3812_write_port_w(UINT8 ChipID,offs_t offset,UINT8 data)275 void ym3812_write_port_w(UINT8 ChipID, offs_t offset, UINT8 data)
276 {
277 	ym3812_w(ChipID, 1, data);
278 }
279 
280 
ym3812_set_emu_core(UINT8 Emulator)281 void ym3812_set_emu_core(UINT8 Emulator)
282 {
283 #ifdef ENABLE_ALL_CORES
284 	EMU_CORE = (Emulator < 0x02) ? Emulator : 0x00;
285 #else
286 	EMU_CORE = EC_DBOPL;
287 #endif
288 
289 	return;
290 }
291 
ym3812_set_mute_mask(UINT8 ChipID,UINT32 MuteMask)292 void ym3812_set_mute_mask(UINT8 ChipID, UINT32 MuteMask)
293 {
294 	ym3812_state *info = &YM3812Data[ChipID];
295 	switch(EMU_CORE)
296 	{
297 #ifdef ENABLE_ALL_CORES
298 	case EC_MAME:
299 		opl_set_mute_mask(info->chip, MuteMask);
300 		break;
301 #endif
302 	case EC_DBOPL:
303 		adlib_OPL2_set_mute_mask(info->chip, MuteMask);
304 		break;
305 	}
306 
307 	return;
308 }
309 
310 
311 /**************************************************************************
312  * Generic get_info
313  **************************************************************************/
314 
315 /*DEVICE_GET_INFO( ym3812 )
316 {
317 	switch (state)
318 	{
319 		// --- the following bits of info are returned as 64-bit signed integers ---
320 		case DEVINFO_INT_TOKEN_BYTES:					info->i = sizeof(ym3812_state);				break;
321 
322 		// --- the following bits of info are returned as pointers to data or functions ---
323 		case DEVINFO_FCT_START:							info->start = DEVICE_START_NAME( ym3812 );				break;
324 		case DEVINFO_FCT_STOP:							info->stop = DEVICE_STOP_NAME( ym3812 );				break;
325 		case DEVINFO_FCT_RESET:							info->reset = DEVICE_RESET_NAME( ym3812 );				break;
326 
327 		// --- the following bits of info are returned as NULL-terminated strings ---
328 		case DEVINFO_STR_NAME:							strcpy(info->s, "YM3812");							break;
329 		case DEVINFO_STR_FAMILY:					strcpy(info->s, "Yamaha FM");						break;
330 		case DEVINFO_STR_VERSION:					strcpy(info->s, "1.0");								break;
331 		case DEVINFO_STR_SOURCE_FILE:						strcpy(info->s, __FILE__);							break;
332 		case DEVINFO_STR_CREDITS:					strcpy(info->s, "Copyright Nicola Salmoria and the MAME Team"); break;
333 	}
334 }*/
335