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