summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/sound/2610intf.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/emu/sound/2610intf.c')
-rw-r--r--src/emu/sound/2610intf.c520
1 files changed, 520 insertions, 0 deletions
diff --git a/src/emu/sound/2610intf.c b/src/emu/sound/2610intf.c
new file mode 100644
index 00000000000..d180da6607c
--- /dev/null
+++ b/src/emu/sound/2610intf.c
@@ -0,0 +1,520 @@
+/***************************************************************************
+
+ 2610intf.c
+
+ The YM2610 emulator supports up to 2 chips.
+ Each chip has the following connections:
+ - Status Read / Control Write A
+ - Port Read / Data Write A
+ - Control Write B
+ - Data Write B
+
+***************************************************************************/
+
+#include "sndintrf.h"
+#include "streams.h"
+#include "ay8910.h"
+#include "2610intf.h"
+#include "fm.h"
+
+static sound_type chip_type = SOUND_YM2610;
+struct ym2610_info
+{
+ sound_stream * stream;
+ emu_timer * timer[2];
+ void * chip;
+ void * psg;
+ const struct YM2610interface *intf;
+};
+
+
+static void psg_set_clock(void *param, int clock)
+{
+ struct ym2610_info *info = param;
+ ay8910_set_clock_ym(info->psg, clock);
+}
+
+static void psg_write(void *param, int address, int data)
+{
+ struct ym2610_info *info = param;
+ ay8910_write_ym(info->psg, address, data);
+}
+
+static int psg_read(void *param)
+{
+ struct ym2610_info *info = param;
+ return ay8910_read_ym(info->psg);
+}
+
+static void psg_reset(void *param)
+{
+ struct ym2610_info *info = param;
+ ay8910_reset_ym(info->psg);
+}
+
+static const struct ssg_callbacks psgintf =
+{
+ psg_set_clock,
+ psg_write,
+ psg_read,
+ psg_reset
+};
+
+/*------------------------- TM2610 -------------------------------*/
+/* IRQ Handler */
+static void IRQHandler(void *param,int irq)
+{
+ struct ym2610_info *info = param;
+ if(info->intf->handler) info->intf->handler(irq);
+}
+
+/* Timer overflow callback from timer.c */
+static TIMER_CALLBACK_PTR( timer_callback_0 )
+{
+ struct ym2610_info *info = param;
+ YM2610TimerOver(info->chip,0);
+}
+
+static TIMER_CALLBACK_PTR( timer_callback_1 )
+{
+ struct ym2610_info *info = param;
+ YM2610TimerOver(info->chip,1);
+}
+
+static void timer_handler(void *param,int c,int count,int clock)
+{
+ struct ym2610_info *info = param;
+ if( count == 0 )
+ { /* Reset FM Timer */
+ timer_enable(info->timer[c], 0);
+ }
+ else
+ { /* Start FM Timer */
+ attotime period = attotime_mul(ATTOTIME_IN_HZ(clock), count);
+
+ if (!timer_enable(info->timer[c], 1))
+ timer_adjust_ptr(info->timer[c], period, attotime_zero);
+ }
+}
+
+/* update request from fm.c */
+void YM2610UpdateRequest(void *param)
+{
+ struct ym2610_info *info = param;
+ stream_update(info->stream);
+}
+
+#if BUILD_YM2610
+static void ym2610_stream_update(void *param, stream_sample_t **inputs, stream_sample_t **buffers, int length)
+{
+ struct ym2610_info *info = param;
+ YM2610UpdateOne(info->chip, buffers, length);
+}
+
+
+static void ym2610_postload(void *param)
+{
+ struct ym2610_info *info = param;
+ YM2610Postload(info->chip);
+}
+
+
+static void *ym2610_start(int sndindex, int clock, const void *config)
+{
+ static const struct YM2610interface generic_2610 = { 0 };
+ const struct YM2610interface *intf = config ? config : &generic_2610;
+ int rate = clock/72;
+ void *pcmbufa,*pcmbufb;
+ int pcmsizea,pcmsizeb;
+ struct ym2610_info *info;
+
+ chip_type = SOUND_YM2610;
+
+ info = auto_malloc(sizeof(*info));
+ memset(info, 0, sizeof(*info));
+
+ info->intf = intf;
+ info->psg = ay8910_start_ym(SOUND_YM2610, sndindex, clock, 1, NULL, NULL, NULL, NULL);
+ if (!info->psg) return NULL;
+
+ /* Timer Handler set */
+ info->timer[0] = timer_alloc_ptr(timer_callback_0, info);
+ info->timer[1] = timer_alloc_ptr(timer_callback_1, info);
+
+ /* stream system initialize */
+ info->stream = stream_create(0,2,rate,info,ym2610_stream_update);
+ /* setup adpcm buffers */
+ pcmbufa = (void *)(memory_region(info->intf->pcmroma));
+ pcmsizea = memory_region_length(info->intf->pcmroma);
+ pcmbufb = (void *)(memory_region(info->intf->pcmromb));
+ pcmsizeb = memory_region_length(info->intf->pcmromb);
+
+ /**** initialize YM2610 ****/
+ info->chip = YM2610Init(info,sndindex,clock,rate,
+ pcmbufa,pcmsizea,pcmbufb,pcmsizeb,
+ timer_handler,IRQHandler,&psgintf);
+
+ state_save_register_func_postload_ptr(ym2610_postload, info);
+
+ if (info->chip)
+ return info;
+
+ /* error */
+ return NULL;
+}
+#endif
+
+#if BUILD_YM2610B
+static void ym2610b_stream_update(void *param, stream_sample_t **inputs, stream_sample_t **buffers, int length)
+{
+ struct ym2610_info *info = param;
+ YM2610BUpdateOne(info->chip, buffers, length);
+}
+
+static void *ym2610b_start(int sndindex, int clock, const void *config)
+{
+ static const struct YM2610interface generic_2610 = { 0 };
+ const struct YM2610interface *intf = config ? config : &generic_2610;
+ int rate = clock/72;
+ void *pcmbufa,*pcmbufb;
+ int pcmsizea,pcmsizeb;
+ struct ym2610_info *info;
+
+ chip_type = SOUND_YM2610B;
+
+ info = auto_malloc(sizeof(*info));
+ memset(info, 0, sizeof(*info));
+
+ info->intf = intf;
+ info->psg = ay8910_start_ym(SOUND_YM2610B, sndindex, clock, 1, NULL, NULL, NULL, NULL);
+ if (!info->psg) return NULL;
+
+ /* Timer Handler set */
+ info->timer[0] =timer_alloc_ptr(timer_callback_0, info);
+ info->timer[1] =timer_alloc_ptr(timer_callback_1, info);
+
+ /* stream system initialize */
+ info->stream = stream_create(0,2,rate,info,ym2610b_stream_update);
+ /* setup adpcm buffers */
+ pcmbufa = (void *)(memory_region(info->intf->pcmroma));
+ pcmsizea = memory_region_length(info->intf->pcmroma);
+ pcmbufb = (void *)(memory_region(info->intf->pcmromb));
+ pcmsizeb = memory_region_length(info->intf->pcmromb);
+
+ /**** initialize YM2610 ****/
+ info->chip = YM2610Init(info,sndindex,clock,rate,
+ pcmbufa,pcmsizea,pcmbufb,pcmsizeb,
+ timer_handler,IRQHandler,&psgintf);
+ if (info->chip)
+ return info;
+
+ /* error */
+ return NULL;
+}
+#endif
+
+static void ym2610_stop(void *token)
+{
+ struct ym2610_info *info = token;
+ YM2610Shutdown(info->chip);
+ ay8910_stop_ym(info->psg);
+}
+
+static void ym2610_reset(void *token)
+{
+ struct ym2610_info *info = token;
+ YM2610ResetChip(info->chip);
+}
+
+/************************************************/
+/* Status Read for YM2610 - Chip 0 */
+/************************************************/
+READ8_HANDLER( YM2610_status_port_0_A_r )
+{
+//logerror("PC %04x: 2610 S0A=%02X\n",activecpu_get_pc(),YM2610Read(sndti_token(chip_type,0,0));
+ struct ym2610_info *info = sndti_token(chip_type,0);
+ return YM2610Read(info->chip,0);
+}
+
+READ16_HANDLER( YM2610_status_port_0_A_lsb_r )
+{
+//logerror("PC %04x: 2610 S0A=%02X\n",activecpu_get_pc(),YM2610Read(sndti_token(chip_type,0,0));
+ struct ym2610_info *info = sndti_token(chip_type,0);
+ return YM2610Read(info->chip,0);
+}
+
+READ8_HANDLER( YM2610_status_port_0_B_r )
+{
+//logerror("PC %04x: 2610 S0B=%02X\n",activecpu_get_pc(),YM2610Read(sndti_token(chip_type,0,2));
+ struct ym2610_info *info = sndti_token(chip_type,0);
+ return YM2610Read(info->chip,2);
+}
+
+READ16_HANDLER( YM2610_status_port_0_B_lsb_r )
+{
+//logerror("PC %04x: 2610 S0B=%02X\n",activecpu_get_pc(),YM2610Read(sndti_token(chip_type,0,2));
+ struct ym2610_info *info = sndti_token(chip_type,0);
+ return YM2610Read(info->chip,2);
+}
+
+/************************************************/
+/* Status Read for YM2610 - Chip 1 */
+/************************************************/
+READ8_HANDLER( YM2610_status_port_1_A_r ) {
+ struct ym2610_info *info = sndti_token(chip_type,1);
+ return YM2610Read(info->chip,0);
+}
+
+READ16_HANDLER( YM2610_status_port_1_A_lsb_r ) {
+ struct ym2610_info *info = sndti_token(chip_type,1);
+ return YM2610Read(info->chip,0);
+}
+
+READ8_HANDLER( YM2610_status_port_1_B_r ) {
+ struct ym2610_info *info = sndti_token(chip_type,1);
+ return YM2610Read(info->chip,2);
+}
+
+READ16_HANDLER( YM2610_status_port_1_B_lsb_r ) {
+ struct ym2610_info *info = sndti_token(chip_type,1);
+ return YM2610Read(info->chip,2);
+}
+
+/************************************************/
+/* Port Read for YM2610 - Chip 0 */
+/************************************************/
+READ8_HANDLER( YM2610_read_port_0_r ){
+ struct ym2610_info *info = sndti_token(chip_type,0);
+ return YM2610Read(info->chip,1);
+}
+
+READ16_HANDLER( YM2610_read_port_0_lsb_r ){
+ struct ym2610_info *info = sndti_token(chip_type,0);
+ return YM2610Read(info->chip,1);
+}
+
+/************************************************/
+/* Port Read for YM2610 - Chip 1 */
+/************************************************/
+READ8_HANDLER( YM2610_read_port_1_r ){
+ struct ym2610_info *info = sndti_token(chip_type,1);
+ return YM2610Read(info->chip,1);
+}
+
+READ16_HANDLER( YM2610_read_port_1_lsb_r ){
+ struct ym2610_info *info = sndti_token(chip_type,1);
+ return YM2610Read(info->chip,1);
+}
+
+/************************************************/
+/* Control Write for YM2610 - Chip 0 */
+/* Consists of 2 addresses */
+/************************************************/
+WRITE8_HANDLER( YM2610_control_port_0_A_w )
+{
+//logerror("PC %04x: 2610 Reg A %02X",activecpu_get_pc(),data);
+ struct ym2610_info *info = sndti_token(chip_type,0);
+ YM2610Write(info->chip,0,data);
+}
+
+WRITE16_HANDLER( YM2610_control_port_0_A_lsb_w )
+{
+//logerror("PC %04x: 2610 Reg A %02X",activecpu_get_pc(),data);
+ if (ACCESSING_LSB)
+ {
+ struct ym2610_info *info = sndti_token(chip_type,0);
+ YM2610Write(info->chip,0,data);
+ }
+}
+
+WRITE8_HANDLER( YM2610_control_port_0_B_w )
+{
+//logerror("PC %04x: 2610 Reg B %02X",activecpu_get_pc(),data);
+ struct ym2610_info *info = sndti_token(chip_type,0);
+ YM2610Write(info->chip,2,data);
+}
+
+WRITE16_HANDLER( YM2610_control_port_0_B_lsb_w )
+{
+//logerror("PC %04x: 2610 Reg B %02X",activecpu_get_pc(),data);
+ if (ACCESSING_LSB)
+ {
+ struct ym2610_info *info = sndti_token(chip_type,0);
+ YM2610Write(info->chip,2,data);
+ }
+}
+
+/************************************************/
+/* Control Write for YM2610 - Chip 1 */
+/* Consists of 2 addresses */
+/************************************************/
+WRITE8_HANDLER( YM2610_control_port_1_A_w ){
+ struct ym2610_info *info = sndti_token(chip_type,1);
+ YM2610Write(info->chip,0,data);
+}
+
+WRITE16_HANDLER( YM2610_control_port_1_A_lsb_w ){
+ if (ACCESSING_LSB)
+ {
+ struct ym2610_info *info = sndti_token(chip_type,1);
+ YM2610Write(info->chip,0,data);
+ }
+}
+
+WRITE8_HANDLER( YM2610_control_port_1_B_w ){
+ struct ym2610_info *info = sndti_token(chip_type,1);
+ YM2610Write(info->chip,2,data);
+}
+
+WRITE16_HANDLER( YM2610_control_port_1_B_lsb_w ){
+ if (ACCESSING_LSB)
+ {
+ struct ym2610_info *info = sndti_token(chip_type,1);
+ YM2610Write(info->chip,2,data);
+ }
+}
+
+/************************************************/
+/* Data Write for YM2610 - Chip 0 */
+/* Consists of 2 addresses */
+/************************************************/
+WRITE8_HANDLER( YM2610_data_port_0_A_w )
+{
+//logerror(" =%02X\n",data);
+ struct ym2610_info *info = sndti_token(chip_type,0);
+ YM2610Write(info->chip,1,data);
+}
+
+WRITE16_HANDLER( YM2610_data_port_0_A_lsb_w )
+{
+//logerror(" =%02X\n",data);
+ if (ACCESSING_LSB)
+ {
+ struct ym2610_info *info = sndti_token(chip_type,0);
+ YM2610Write(info->chip,1,data);
+ }
+}
+
+WRITE8_HANDLER( YM2610_data_port_0_B_w )
+{
+//logerror(" =%02X\n",data);
+ struct ym2610_info *info = sndti_token(chip_type,0);
+ YM2610Write(info->chip,3,data);
+}
+
+WRITE16_HANDLER( YM2610_data_port_0_B_lsb_w )
+{
+//logerror(" =%02X\n",data);
+ if (ACCESSING_LSB)
+ {
+ struct ym2610_info *info = sndti_token(chip_type,0);
+ YM2610Write(info->chip,3,data);
+ }
+}
+
+/************************************************/
+/* Data Write for YM2610 - Chip 1 */
+/* Consists of 2 addresses */
+/************************************************/
+WRITE8_HANDLER( YM2610_data_port_1_A_w ){
+ struct ym2610_info *info = sndti_token(chip_type,1);
+ YM2610Write(info->chip,1,data);
+}
+
+WRITE16_HANDLER( YM2610_data_port_1_A_lsb_w ){
+ if (ACCESSING_LSB)
+ {
+ struct ym2610_info *info = sndti_token(chip_type,1);
+ YM2610Write(info->chip,1,data);
+ }
+}
+
+WRITE8_HANDLER( YM2610_data_port_1_B_w ){
+ struct ym2610_info *info = sndti_token(chip_type,1);
+ YM2610Write(info->chip,3,data);
+}
+
+WRITE16_HANDLER( YM2610_data_port_1_B_lsb_w ){
+ if (ACCESSING_LSB)
+ {
+ struct ym2610_info *info = sndti_token(chip_type,1);
+ YM2610Write(info->chip,3,data);
+ }
+}
+
+/**************** end of file ****************/
+
+
+/**************************************************************************
+ * Generic get_info
+ **************************************************************************/
+
+#if BUILD_YM2610
+static void ym2610_set_info(void *token, UINT32 state, sndinfo *info)
+{
+ switch (state)
+ {
+ /* no parameters to set */
+ }
+}
+
+
+void ym2610_get_info(void *token, UINT32 state, sndinfo *info)
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case SNDINFO_PTR_SET_INFO: info->set_info = ym2610_set_info; break;
+ case SNDINFO_PTR_START: info->start = ym2610_start; break;
+ case SNDINFO_PTR_STOP: info->stop = ym2610_stop; break;
+ case SNDINFO_PTR_RESET: info->reset = ym2610_reset; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case SNDINFO_STR_NAME: info->s = "YM2610"; break;
+ case SNDINFO_STR_CORE_FAMILY: info->s = "Yamaha FM"; break;
+ case SNDINFO_STR_CORE_VERSION: info->s = "1.0"; break;
+ case SNDINFO_STR_CORE_FILE: info->s = __FILE__; break;
+ case SNDINFO_STR_CORE_CREDITS: info->s = "Copyright (c) 2004, The MAME Team"; break;
+ }
+}
+#endif
+
+
+/**************************************************************************
+ * Generic get_info
+ **************************************************************************/
+
+#if BUILD_YM2610B
+static void ym2610b_set_info(void *token, UINT32 state, sndinfo *info)
+{
+ switch (state)
+ {
+ /* no parameters to set */
+ }
+}
+
+
+void ym2610b_get_info(void *token, UINT32 state, sndinfo *info)
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case SNDINFO_PTR_SET_INFO: info->set_info = ym2610b_set_info; break;
+ case SNDINFO_PTR_START: info->start = ym2610b_start; break;
+ case SNDINFO_PTR_STOP: info->stop = ym2610_stop; break;
+ case SNDINFO_PTR_RESET: info->reset = ym2610_reset; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case SNDINFO_STR_NAME: info->s = "YM2610B"; break;
+ case SNDINFO_STR_CORE_FAMILY: info->s = "Yamaha FM"; break;
+ case SNDINFO_STR_CORE_VERSION: info->s = "1.0"; break;
+ case SNDINFO_STR_CORE_FILE: info->s = __FILE__; break;
+ case SNDINFO_STR_CORE_CREDITS: info->s = "Copyright (c) 2004, The MAME Team"; break;
+ }
+}
+
+#endif