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