1 /***************************************************************************
2 
3   2610intf.c
4 
5   The YM2610 emulator supports up to 2 chips.
6   Each chip has the following connections:
7   - Status Read / Control Write A
8   - Port Read / Data Write A
9   - Control Write B
10   - Data Write B
11 
12 ***************************************************************************/
13 
14 #include <memory.h>	// for memset
15 #include <stdlib.h>	// for free
16 #include <stddef.h>	// for NULL
17 #include "mamedef.h"
18 //#include "sndintrf.h"
19 //#include "streams.h"
20 #include "2610intf.h"
21 #include "fm.h"
22 
23 
24 #ifdef ENABLE_ALL_CORES
25 #define EC_MAME		0x01	// AY8910 core from MAME
26 #endif
27 #define EC_EMU2149	0x00
28 
29 typedef struct _ym2610_state ym2610_state;
30 struct _ym2610_state
31 {
32 	//sound_stream *	stream;
33 	//emu_timer *		timer[2];
34 	void *			chip;
35 	void *			psg;
36 	int			AY_EMU_CORE;
37 	//const ym2610_interface *intf;
38 	//const device_config *device;
39 };
40 
41 #define CHTYPE_YM2610	0x22
42 
43 
44 /*INLINE ym2610_state *get_safe_token(const device_config *device)
45 {
46 	assert(device != NULL);
47 	assert(device->token != NULL);
48 	assert(device->type == SOUND);
49 	assert(sound_get_type(device) == SOUND_YM2610 || sound_get_type(device) == SOUND_YM2610B);
50 	return (ym2610_state *)device->token;
51 }*/
52 
53 
psg_set_clock(void * param,int clock)54 static void psg_set_clock(void *param, int clock)
55 {
56 	ym2610_state *info = (ym2610_state *)param;
57 	if (info->psg != NULL)
58 	{
59 		switch(info->AY_EMU_CORE)
60 		{
61 #ifdef ENABLE_ALL_CORES
62 		case EC_MAME:
63 			ay8910_set_clock_ym(info->psg, clock);
64 			break;
65 #endif
66 		case EC_EMU2149:
67 			PSG_set_clock((PSG*)info->psg, clock);
68 			break;
69 		}
70 	}
71 }
72 
psg_write(void * param,int address,int data)73 static void psg_write(void *param, int address, int data)
74 {
75 	ym2610_state *info = (ym2610_state *)param;
76 	if (info->psg != NULL)
77 	{
78 		switch(info->AY_EMU_CORE)
79 		{
80 #ifdef ENABLE_ALL_CORES
81 		case EC_MAME:
82 			ay8910_write_ym(info->psg, address, data);
83 			break;
84 #endif
85 		case EC_EMU2149:
86 			PSG_writeIO((PSG*)info->psg, address, data);
87 			break;
88 		}
89 	}
90 }
91 
psg_read(void * param)92 static int psg_read(void *param)
93 {
94 	ym2610_state *info = (ym2610_state *)param;
95 	if (info->psg != NULL)
96 	{
97 		switch(info->AY_EMU_CORE)
98 		{
99 #ifdef ENABLE_ALL_CORES
100 		case EC_MAME:
101 			return ay8910_read_ym(info->psg);
102 #endif
103 		case EC_EMU2149:
104 			return PSG_readIO((PSG*)info->psg);
105 		}
106 	}
107 	return 0x00;
108 }
109 
psg_reset(void * param)110 static void psg_reset(void *param)
111 {
112 	ym2610_state *info = (ym2610_state *)param;
113 	if (info->psg != NULL)
114 	{
115 		switch(info->AY_EMU_CORE)
116 		{
117 #ifdef ENABLE_ALL_CORES
118 		case EC_MAME:
119 			ay8910_reset_ym(info->psg);
120 			break;
121 #endif
122 		case EC_EMU2149:
123 			PSG_reset((PSG*)info->psg);
124 			break;
125 		}
126 	}
127 }
128 
129 static const ssg_callbacks psgintf =
130 {
131 	psg_set_clock,
132 	psg_write,
133 	psg_read,
134 	psg_reset
135 };
136 
137 /*------------------------- TM2610 -------------------------------*/
138 /* IRQ Handler */
139 /*static void IRQHandler(void *param,int irq)
140 {
141 	ym2610_state *info = (ym2610_state *)param;
142 	//if(info->intf->handler) info->intf->handler(info->device, irq);
143 	//if(info->intf->handler) info->intf->handler(irq);
144 }*/
145 
146 /* Timer overflow callback from timer.c */
147 /*static TIMER_CALLBACK( timer_callback_0 )
148 {
149 	ym2610_state *info = (ym2610_state *)ptr;
150 	ym2610_timer_over(info->chip,0);
151 }
152 
153 static TIMER_CALLBACK( timer_callback_1 )
154 {
155 	ym2610_state *info = (ym2610_state *)ptr;
156 	ym2610_timer_over(info->chip,1);
157 }*/
158 
159 /*static void timer_handler(void *param,int c,int count,int clock)
160 {
161 	ym2610_state *info = (ym2610_state *)param;
162 	if( count == 0 )
163 	{	// Reset FM Timer
164 		//timer_enable(info->timer[c], 0);
165 	}
166 	else
167 	{	// Start FM Timer
168 		//attotime period = attotime_mul(ATTOTIME_IN_HZ(clock), count);
169 
170 		//if (!timer_enable(info->timer[c], 1))
171 		//	timer_adjust_oneshot(info->timer[c], period, 0);
172 	}
173 }*/
174 
175 static stream_sample_t* DUMMYBUF[0x02] = {NULL, NULL};
176 
177 /* update request from fm.c */
ym2610_update_request(void * param)178 void ym2610_update_request(void *param)
179 {
180 	ym2610_state *info = (ym2610_state *)param;
181 	//stream_update(info->stream);
182 
183 	ym2610b_update_one(info->chip, DUMMYBUF, 0);
184 	// Not necessary.
185 	//if (info->psg != NULL)
186 	//	ay8910_update_one(info->psg, DUMMYBUF, 0);
187 }
188 
189 
190 //static STREAM_UPDATE( ym2610_stream_update )
ym2610_stream_update(void * param,stream_sample_t ** outputs,int samples)191 void ym2610_stream_update(void *param, stream_sample_t **outputs, int samples)
192 {
193 	ym2610_state *info = (ym2610_state *)param;
194 	ym2610_update_one(info->chip, outputs, samples);
195 }
196 
197 //static STREAM_UPDATE( ym2610b_stream_update )
ym2610b_stream_update(void * param,stream_sample_t ** outputs,int samples)198 void ym2610b_stream_update(void *param, stream_sample_t **outputs, int samples)
199 {
200 	ym2610_state *info = (ym2610_state *)param;
201 	ym2610b_update_one(info->chip, outputs, samples);
202 }
203 
ym2610_stream_update_ay(void * param,stream_sample_t ** outputs,int samples)204 void ym2610_stream_update_ay(void *param, stream_sample_t **outputs, int samples)
205 {
206 	ym2610_state *info = (ym2610_state *)param;
207 
208 	if (info->psg != NULL)
209 	{
210 		switch(info->AY_EMU_CORE)
211 		{
212 #ifdef ENABLE_ALL_CORES
213 		case EC_MAME:
214 			ay8910_update_one(info->psg, outputs, samples);
215 			break;
216 #endif
217 		case EC_EMU2149:
218 			PSG_calc_stereo((PSG*)info->psg, outputs, samples);
219 			break;
220 		}
221 	}
222 	else
223 	{
224 		memset(outputs[0], 0x00, samples * sizeof(stream_sample_t));
225 		memset(outputs[1], 0x00, samples * sizeof(stream_sample_t));
226 	}
227 }
228 
229 
230 //static STATE_POSTLOAD( ym2610_intf_postload )
231 /*static void ym2610_intf_postload(UINT8 ChipID)
232 {
233 	//ym2610_state *info = (ym2610_state *)param;
234 	ym2610_state *info = &YM2610Data[ChipID];
235 	ym2610_postload(info->chip);
236 }*/
237 
238 
239 //static DEVICE_START( ym2610 )
device_start_ym2610(void ** _info,int AY_EMU_CORE,int clock,UINT8 AYDisable,int * AYrate,int CHIP_SAMPLING_MODE,int CHIP_SAMPLE_RATE)240 int device_start_ym2610(void **_info, int AY_EMU_CORE, int clock, UINT8 AYDisable, int* AYrate, int CHIP_SAMPLING_MODE, int CHIP_SAMPLE_RATE)
241 {
242 	// clock bit 31:	0 - YM2610
243 	//					1 - YM2610B
244 
245 	//static const ym2610_interface generic_2610 = { 0 };
246 	static const ay8910_interface generic_ay8910 =
247 	{
248 		AY8910_LEGACY_OUTPUT | AY8910_SINGLE_OUTPUT,
249 		AY8910_DEFAULT_LOADS
250 		//DEVCB_NULL, DEVCB_NULL, DEVCB_NULL, DEVCB_NULL
251 	};
252 	//const ym2610_interface *intf = device->static_config ? (const ym2610_interface *)device->static_config : &generic_2610;
253 	//const ym2610_interface *intf = &generic_2610;
254 	int rate;
255 	int ay_clock;
256 	//void *pcmbufa,*pcmbufb;
257 	//int  pcmsizea,pcmsizeb;
258 	//ym2610_state *info = get_safe_token(device);
259 	ym2610_state *info;
260 	//astring *name = astring_alloc();
261 	//sound_type type = sound_get_type(device);
262 	unsigned char ChipType;
263 
264 #ifdef ENABLE_ALL_CORES
265 	if (AY_EMU_CORE >= 0x02)
266 		AY_EMU_CORE = EC_EMU2149;
267 #else
268 	AY_EMU_CORE = EC_EMU2149;
269 #endif
270 
271 	info = (ym2610_state *) calloc(1, sizeof(ym2610_state));
272 	*_info = (void *) info;
273 
274 	info->AY_EMU_CORE = AY_EMU_CORE;
275 	ChipType = (clock & 0x80000000) ? 0x01 : 0x00;
276 	clock &= 0x7FFFFFFF;
277 	rate = clock/72;
278 	if ((CHIP_SAMPLING_MODE == 0x01 && rate < CHIP_SAMPLE_RATE) ||
279 		CHIP_SAMPLING_MODE == 0x02)
280 		rate = CHIP_SAMPLE_RATE;
281 	//info->intf = intf;
282 	//info->device = device;
283 	//info->psg = ay8910_start_ym(NULL, sound_get_type(device), device, device->clock, &generic_ay8910);
284 	if (! AYDisable)
285 	{
286 		ay_clock = clock / 4;
287 		*AYrate = ay_clock / 8;
288 		switch(AY_EMU_CORE)
289 		{
290 #ifdef ENABLE_ALL_CORES
291 		case EC_MAME:
292 			info->psg = ay8910_start_ym(NULL, CHTYPE_YM2610 + ChipType, ay_clock, &generic_ay8910);
293 			break;
294 #endif
295 		case EC_EMU2149:
296 			info->psg = PSG_new(ay_clock, *AYrate);
297 			if (info->psg == NULL)
298 				return 0;
299 			PSG_setVolumeMode((PSG*)info->psg, 1);	// YM2149 volume mode
300 			break;
301 		}
302 	}
303 	else
304 	{
305 		info->psg = NULL;
306 		*AYrate = 0;
307 	}
308 	//assert_always(info->psg != NULL, "Error creating YM2610/AY8910 chip");
309 
310 	/* Timer Handler set */
311 	//info->timer[0] = timer_alloc(device->machine, timer_callback_0, info);
312 	//info->timer[1] = timer_alloc(device->machine, timer_callback_1, info);
313 
314 	/* stream system initialize */
315 	//info->stream = stream_create(device,0,2,rate,info,(type == SOUND_YM2610) ? ym2610_stream_update : ym2610b_stream_update);
316 	/* setup adpcm buffers */
317 	//pcmbufa  = device->region;
318 	//pcmsizea = device->regionbytes;
319 	//astring_printf(name, "%s.deltat", device->tag);
320 	//pcmbufb  = (void *)(memory_region(device->machine, astring_c(name)));
321 	//pcmsizeb = memory_region_length(device->machine, astring_c(name));
322 	//astring_free(name);
323 	/*if (pcmbufb == NULL || pcmsizeb == 0)
324 	{
325 		pcmbufb = pcmbufa;
326 		pcmsizeb = pcmsizea;
327 	}*/
328 
329 	/**** initialize YM2610 ****/
330 	//info->chip = ym2610_init(info,device,device->clock,rate,
331 	//	           pcmbufa,pcmsizea,pcmbufb,pcmsizeb,
332 	//	           timer_handler,IRQHandler,&psgintf);
333 	info->chip = ym2610_init(info, clock & 0x7FFFFFFF, rate, NULL, NULL, &psgintf);
334 	//assert_always(info->chip != NULL, "Error creating YM2610 chip");
335 
336 	//state_save_register_postload(device->machine, ym2610_intf_postload, info);
337 
338 	return rate;
339 }
340 
341 //static DEVICE_STOP( ym2610 )
device_stop_ym2610(void * _info)342 void device_stop_ym2610(void *_info)
343 {
344 	//ym2610_state *info = get_safe_token(device);
345 	ym2610_state* info = (ym2610_state *)_info;
346 	ym2610_shutdown(info->chip);
347 	if (info->psg != NULL)
348 	{
349 		switch(info->AY_EMU_CORE)
350 		{
351 #ifdef ENABLE_ALL_CORES
352 		case EC_MAME:
353 			ay8910_stop_ym(info->psg);
354 			break;
355 #endif
356 		case EC_EMU2149:
357 			PSG_delete((PSG*)info->psg);
358 			break;
359 		}
360 		info->psg = NULL;
361 	}
362 	free(info);
363 }
364 
365 //static DEVICE_RESET( ym2610 )
device_reset_ym2610(void * _info)366 void device_reset_ym2610(void *_info)
367 {
368 	//ym2610_state *info = get_safe_token(device);
369 	ym2610_state* info = (ym2610_state *)_info;
370 	ym2610_reset_chip(info->chip);	// also resets the AY clock
371 	//psg_reset(info);	// already done as a callback in ym2610_reset_chip
372 }
373 
374 
375 //READ8_DEVICE_HANDLER( ym2610_r )
ym2610_r(void * _info,offs_t offset)376 UINT8 ym2610_r(void *_info, offs_t offset)
377 {
378 	//ym2610_state *info = get_safe_token(device);
379 	ym2610_state* info = (ym2610_state *)_info;
380 	return ym2610_read(info->chip, offset & 3);
381 }
382 
383 //WRITE8_DEVICE_HANDLER( ym2610_w )
ym2610_w(void * _info,offs_t offset,UINT8 data)384 void ym2610_w(void *_info, offs_t offset, UINT8 data)
385 {
386 	//ym2610_state *info = get_safe_token(device);
387 	ym2610_state* info = (ym2610_state *)_info;
388 	ym2610_write(info->chip, offset & 3, data);
389 }
390 
391 
392 //READ8_DEVICE_HANDLER( ym2610_status_port_a_r )
ym2610_status_port_a_r(void * info,offs_t offset)393 UINT8 ym2610_status_port_a_r(void *info, offs_t offset)
394 {
395 	return ym2610_r(info, 0);
396 }
397 //READ8_DEVICE_HANDLER( ym2610_status_port_b_r )
ym2610_status_port_b_r(void * info,offs_t offset)398 UINT8 ym2610_status_port_b_r(void *info, offs_t offset)
399 {
400 	return ym2610_r(info, 2);
401 }
402 //READ8_DEVICE_HANDLER( ym2610_read_port_r )
ym2610_read_port_r(void * info,offs_t offset)403 UINT8 ym2610_read_port_r(void *info, offs_t offset)
404 {
405 	return ym2610_r(info, 1);
406 }
407 
408 //WRITE8_DEVICE_HANDLER( ym2610_control_port_a_w )
ym2610_control_port_a_w(void * info,offs_t offset,UINT8 data)409 void ym2610_control_port_a_w(void *info, offs_t offset, UINT8 data)
410 {
411 	ym2610_w(info, 0, data);
412 }
413 //WRITE8_DEVICE_HANDLER( ym2610_control_port_b_w )
ym2610_control_port_b_w(void * info,offs_t offset,UINT8 data)414 void ym2610_control_port_b_w(void *info, offs_t offset, UINT8 data)
415 {
416 	ym2610_w(info, 2, data);
417 }
418 //WRITE8_DEVICE_HANDLER( ym2610_data_port_a_w )
ym2610_data_port_a_w(void * info,offs_t offset,UINT8 data)419 void ym2610_data_port_a_w(void *info, offs_t offset, UINT8 data)
420 {
421 	ym2610_w(info, 1, data);
422 }
423 //WRITE8_DEVICE_HANDLER( ym2610_data_port_b_w )
ym2610_data_port_b_w(void * info,offs_t offset,UINT8 data)424 void ym2610_data_port_b_w(void *info, offs_t offset, UINT8 data)
425 {
426 	ym2610_w(info, 3, data);
427 }
428 
429 
ym2610_write_data_pcmrom(void * _info,UINT8 rom_id,offs_t ROMSize,offs_t DataStart,offs_t DataLength,const UINT8 * ROMData)430 void ym2610_write_data_pcmrom(void *_info, UINT8 rom_id, offs_t ROMSize, offs_t DataStart,
431 							  offs_t DataLength, const UINT8* ROMData)
432 {
433 	ym2610_state* info = (ym2610_state *)_info;
434 	ym2610_write_pcmrom(info->chip, rom_id, ROMSize, DataStart, DataLength, ROMData);
435 }
436 
ym2610_set_mute_mask(void * _info,UINT32 MuteMaskFM,UINT32 MuteMaskAY)437 void ym2610_set_mute_mask(void *_info, UINT32 MuteMaskFM, UINT32 MuteMaskAY)
438 {
439 	ym2610_state* info = (ym2610_state *)_info;
440 	ym2610_set_mutemask(info->chip, MuteMaskFM);
441 	if (info->psg != NULL)
442 	{
443 		switch(info->AY_EMU_CORE)
444 		{
445 #ifdef ENABLE_ALL_CORES
446 		case EC_MAME:
447 			ay8910_set_mute_mask_ym(info->psg, MuteMaskAY);
448 			break;
449 #endif
450 		case EC_EMU2149:
451 			PSG_setMask((PSG*)info->psg, MuteMaskAY);
452 			break;
453 		}
454 	}
455 }
456 
457 
458 /**************************************************************************
459  * Generic get_info
460  **************************************************************************/
461 
462 /*DEVICE_GET_INFO( ym2610 )
463 {
464 	switch (state)
465 	{
466 		// --- the following bits of info are returned as 64-bit signed integers ---
467 		case DEVINFO_INT_TOKEN_BYTES:					info->i = sizeof(ym2610_state);				break;
468 
469 		// --- the following bits of info are returned as pointers to data or functions ---
470 		case DEVINFO_FCT_START:							info->start = DEVICE_START_NAME( ym2610 );				break;
471 		case DEVINFO_FCT_STOP:							info->stop = DEVICE_STOP_NAME( ym2610 );				break;
472 		case DEVINFO_FCT_RESET:							info->reset = DEVICE_RESET_NAME( ym2610 );				break;
473 
474 		// --- the following bits of info are returned as NULL-terminated strings ---
475 		case DEVINFO_STR_NAME:							strcpy(info->s, "YM2610");							break;
476 		case DEVINFO_STR_FAMILY:					strcpy(info->s, "Yamaha FM");						break;
477 		case DEVINFO_STR_VERSION:					strcpy(info->s, "1.0");								break;
478 		case DEVINFO_STR_SOURCE_FILE:						strcpy(info->s, __FILE__);							break;
479 		case DEVINFO_STR_CREDITS:					strcpy(info->s, "Copyright Nicola Salmoria and the MAME Team"); break;
480 	}
481 }*/
482 
483 /*DEVICE_GET_INFO( ym2610b )
484 {
485 	switch (state)
486 	{
487 		// --- the following bits of info are returned as NULL-terminated strings ---
488 		case DEVINFO_STR_NAME:							strcpy(info->s, "YM2610B");					break;
489 
490 		default:										DEVICE_GET_INFO_CALL(ym2610);				break;
491 	}
492 }*/
493