Viewing File: <root>/src/mame/audio/irem.c

    1  /***************************************************************************
    2  
    3      Irem M52/M62 sound hardware
    4  
    5  ***************************************************************************/
    6  
    7  #include "emu.h"
    8  #include "cpu/m6800/m6800.h"
    9  #include "sound/ay8910.h"
   10  #include "sound/msm5205.h"
   11  #include "sound/discrete.h"
   12  #include "audio/irem.h"
   13  
   14  struct irem_audio_state
   15  {
   16      UINT8                m_port1;
   17      UINT8                m_port2;
   18  
   19      device_t *m_ay1;
   20      device_t *m_ay2;
   21      device_t *m_adpcm1;
   22      device_t *m_adpcm2;
   23  };
   24  
   25  INLINE irem_audio_state *get_safe_token( device_t *device )
   26  {
   27      assert(device != NULL);
   28      assert(device->type() == IREM_AUDIO);
   29  
   30      return (irem_audio_state *)downcast<irem_audio_device *>(device)->token();
   31  }
   32  
   33  
   34  
   35  /*************************************
   36   *
   37   *  Sound board initialization
   38   *
   39   *************************************/
   40  
   41  static DEVICE_START( irem_audio )
   42  {
   43      irem_audio_state *state = get_safe_token(device);
   44      running_machine &machine = device->machine();
   45  
   46      state->m_adpcm1 = machine.device("msm1");
   47      state->m_adpcm2 = machine.device("msm2");
   48      state->m_ay1 = machine.device("ay1");
   49      state->m_ay2 = machine.device("ay2");
   50  
   51      device->save_item(NAME(state->m_port1));
   52      device->save_item(NAME(state->m_port2));
   53  }
   54  
   55  
   56  
   57  /*************************************
   58   *
   59   *  External writes to the sound
   60   *  command register
   61   *
   62   *************************************/
   63  
   64  WRITE8_HANDLER( irem_sound_cmd_w )
   65  {
   66      driver_device *drvstate = space.machine().driver_data<driver_device>();
   67      if ((data & 0x80) == 0)
   68          drvstate->soundlatch_byte_w(space, 0, data & 0x7f);
   69      else
   70          space.machine().device("iremsound")->execute().set_input_line(0, ASSERT_LINE);
   71  }
   72  
   73  
   74  
   75  /*************************************
   76   *
   77   *  6803 output ports
   78   *
   79   *************************************/
   80  
   81  static WRITE8_DEVICE_HANDLER( m6803_port1_w )
   82  {
   83      irem_audio_state *state = get_safe_token(device);
   84  
   85      state->m_port1 = data;
   86  }
   87  
   88  
   89  static WRITE8_DEVICE_HANDLER( m6803_port2_w )
   90  {
   91      irem_audio_state *state = get_safe_token(device);
   92  
   93      /* write latch */
   94      if ((state->m_port2 & 0x01) && !(data & 0x01))
   95      {
   96          /* control or data port? */
   97          if (state->m_port2 & 0x04)
   98          {
   99              /* PSG 0 or 1? */
  100              if (state->m_port2 & 0x08)
  101                  ay8910_address_w(state->m_ay1, space, 0, state->m_port1);
  102              if (state->m_port2 & 0x10)
  103                  ay8910_address_w(state->m_ay2, space, 0, state->m_port1);
  104          }
  105          else
  106          {
  107              /* PSG 0 or 1? */
  108              if (state->m_port2 & 0x08)
  109                  ay8910_data_w(state->m_ay1, space, 0, state->m_port1);
  110              if (state->m_port2 & 0x10)
  111                  ay8910_data_w(state->m_ay2, space, 0, state->m_port1);
  112          }
  113      }
  114      state->m_port2 = data;
  115  }
  116  
  117  
  118  
  119  /*************************************
  120   *
  121   *  6803 input ports ports
  122   *
  123   *************************************/
  124  
  125  static READ8_DEVICE_HANDLER( m6803_port1_r )
  126  {
  127      irem_audio_state *state = get_safe_token(device);
  128  
  129      /* PSG 0 or 1? */
  130      if (state->m_port2 & 0x08)
  131          return ay8910_r(state->m_ay1, space, 0);
  132      if (state->m_port2 & 0x10)
  133          return ay8910_r(state->m_ay2, space, 0);
  134      return 0xff;
  135  }
  136  
  137  
  138  static READ8_DEVICE_HANDLER( m6803_port2_r )
  139  {
  140      return 0;
  141  }
  142  
  143  
  144  
  145  /*************************************
  146   *
  147   *  AY-8910 output ports
  148   *
  149   *************************************/
  150  
  151  static WRITE8_DEVICE_HANDLER( ay8910_0_portb_w )
  152  {
  153      irem_audio_state *state = get_safe_token(device);
  154  
  155      /* bits 2-4 select MSM5205 clock & 3b/4b playback mode */
  156      msm5205_playmode_w(state->m_adpcm1, (data >> 2) & 7);
  157      if (state->m_adpcm2 != NULL)
  158          msm5205_playmode_w(state->m_adpcm2, ((data >> 2) & 4) | 3); /* always in slave mode */
  159  
  160      /* bits 0 and 1 reset the two chips */
  161      msm5205_reset_w(state->m_adpcm1, data & 1);
  162      if (state->m_adpcm2 != NULL)
  163          msm5205_reset_w(state->m_adpcm2, data & 2);
  164  }
  165  
  166  
  167  static WRITE8_DEVICE_HANDLER( ay8910_1_porta_w )
  168  {
  169  #ifdef MAME_DEBUG
  170      if (data & 0x0f) popmessage("analog sound %x",data&0x0f);
  171  #endif
  172  }
  173  
  174  
  175  
  176  /*************************************
  177   *
  178   *  Memory-mapped accesses
  179   *
  180   *************************************/
  181  
  182  static WRITE8_HANDLER( sound_irq_ack_w )
  183  {
  184      space.machine().device("iremsound")->execute().set_input_line(0, CLEAR_LINE);
  185  }
  186  
  187  
  188  static WRITE8_DEVICE_HANDLER( m52_adpcm_w )
  189  {
  190      irem_audio_state *state = get_safe_token(device);
  191  
  192      if (offset & 1)
  193      {
  194          msm5205_data_w(state->m_adpcm1, data);
  195      }
  196      if (offset & 2)
  197      {
  198          if (state->m_adpcm2 != NULL)
  199              msm5205_data_w(state->m_adpcm2, data);
  200      }
  201  }
  202  
  203  
  204  static WRITE8_DEVICE_HANDLER( m62_adpcm_w )
  205  {
  206      irem_audio_state *state = get_safe_token(device);
  207  
  208      device_t *adpcm = (offset & 1) ? state->m_adpcm2 : state->m_adpcm1;
  209      if (adpcm != NULL)
  210          msm5205_data_w(adpcm, data);
  211  }
  212  
  213  
  214  
  215  /*************************************
  216   *
  217   *  MSM5205 data ready signals
  218   *
  219   *************************************/
  220  
  221  static void adpcm_int(device_t *device)
  222  {
  223      device_t *adpcm2 = device->machine().device("msm2");
  224  
  225      device->machine().device("iremsound")->execute().set_input_line(INPUT_LINE_NMI, PULSE_LINE);
  226  
  227      /* the first MSM5205 clocks the second */
  228      if (adpcm2 != NULL)
  229      {
  230          msm5205_vclk_w(adpcm2, 1);
  231          msm5205_vclk_w(adpcm2, 0);
  232      }
  233  }
  234  
  235  
  236  
  237  /*************************************
  238   *
  239   *  Sound interfaces
  240   *
  241   *************************************/
  242  
  243  /* All 6 (3*2) AY-3-8910 outputs are tied together
  244   * and put with 470 Ohm to gnd.
  245   * The following is a approximation, since
  246   * it does not take cross-chip mixing effects into account.
  247   */
  248  
  249  static const ay8910_interface irem_ay8910_interface_1 =
  250  {
  251      AY8910_SINGLE_OUTPUT | AY8910_DISCRETE_OUTPUT,
  252      {470, 0, 0},
  253      DEVCB_DRIVER_MEMBER(driver_device, soundlatch_byte_r),
  254      DEVCB_NULL,
  255      DEVCB_NULL,
  256      DEVCB_DEVICE_HANDLER("irem_audio", ay8910_0_portb_w)
  257  };
  258  
  259  static const ay8910_interface irem_ay8910_interface_2 =
  260  {
  261      AY8910_SINGLE_OUTPUT | AY8910_DISCRETE_OUTPUT,
  262      {470, 0, 0},
  263      DEVCB_NULL,
  264      DEVCB_NULL,
  265      DEVCB_HANDLER(ay8910_1_porta_w),
  266      DEVCB_NULL
  267  };
  268  
  269  static const msm5205_interface irem_msm5205_interface_1 =
  270  {
  271      adpcm_int,          /* interrupt function */
  272      MSM5205_S96_4B      /* default to 4KHz, but can be changed at run time */
  273  };
  274  
  275  static const msm5205_interface irem_msm5205_interface_2 =
  276  {
  277      0,              /* interrupt function */
  278      MSM5205_SEX_4B      /* default to 4KHz, but can be changed at run time, slave */
  279  };
  280  
  281  /*
  282   * http://newsgroups.derkeiler.com/Archive/Rec/rec.games.video.arcade.collecting/2006-06/msg03108.html
  283   *
  284   * mentions, that moon patrol does work on moon ranger hardware.
  285   * There is no MSM5250, but a 74LS00 producing white noise for explosions
  286   */
  287  
  288  /* Certain values are different from schematics
  289   * I did my test to verify against pcb pictures of "tropical angel"
  290   */
  291  
  292  #define M52_R9      560
  293  #define M52_R10     330
  294  #define M52_R12     RES_K(10)
  295  #define M52_R13     RES_K(10)
  296  #define M52_R14     RES_K(10)
  297  #define M52_R15     RES_K(2.2)  /* schematics RES_K(22) , althought 10-Yard states 2.2 */
  298  #define M52_R19     RES_K(10)
  299  #define M52_R22     RES_K(47)
  300  #define M52_R23     RES_K(2.2)
  301  #define M52_R25     RES_K(10)
  302  #define M52_VR1     RES_K(50)
  303  
  304  #define M52_C28     CAP_U(1)
  305  #define M52_C30     CAP_U(0.022)
  306  #define M52_C32     CAP_U(0.022)
  307  #define M52_C35     CAP_U(47)
  308  #define M52_C37     CAP_U(0.1)
  309  #define M52_C38     CAP_U(0.0068)
  310  
  311  /*
  312   * C35 is disabled, the mixer would just deliver
  313   * no signals if it is enabled.
  314   * TODO: Check discrete mixer
  315   *
  316   */
  317  
  318  static const discrete_mixer_desc m52_sound_c_stage1 =
  319      {DISC_MIXER_IS_RESISTOR,
  320          {M52_R19, M52_R22, M52_R23 },
  321          {      0,       0,       0 },   /* variable resistors   */
  322          {M52_C37,       0,       0 },   /* node capacitors      */
  323                  0,      0,              /* rI, rF               */
  324          M52_C35*0,                      /* cF                   */
  325          0,                              /* cAmp                 */
  326          0, 1};
  327  
  328  static const discrete_op_amp_filt_info m52_sound_c_sallen_key =
  329      { M52_R13, M52_R14, 0, 0, 0,
  330          M52_C32, M52_C38, 0
  331      };
  332  
  333  static const discrete_mixer_desc m52_sound_c_mix1 =
  334      {DISC_MIXER_IS_RESISTOR,
  335          {M52_R25, M52_R15 },
  336          {      0,       0 },    /* variable resistors   */
  337          {      0,       0 },    /* node capacitors      */
  338                  0, M52_VR1,     /* rI, rF               */
  339          0,                      /* cF                   */
  340          CAP_U(1),               /* cAmp                 */
  341          0, 1};
  342  
  343  static DISCRETE_SOUND_START( m52_sound_c )
  344  
  345      /* Chip AY8910/1 */
  346      DISCRETE_INPUTX_STREAM(NODE_01, 0, 1.0, 0)
  347      /* Chip AY8910/2 */
  348      DISCRETE_INPUTX_STREAM(NODE_02, 1, 1.0, 0)
  349      /* Chip MSM5250 */
  350      DISCRETE_INPUTX_STREAM(NODE_03, 2, 1.0, 0)
  351  
  352      /* Just mix the two AY8910s */
  353      DISCRETE_ADDER2(NODE_09, 1, NODE_01, NODE_02)
  354      DISCRETE_DIVIDE(NODE_10, 1, NODE_09, 2.0)
  355  
  356      /* Mix in 5 V to MSM5250 signal */
  357      DISCRETE_MIXER3(NODE_20, 1, NODE_03, 32767.0, 0, &m52_sound_c_stage1)
  358  
  359      /* Sallen - Key Filter */
  360      /* TODO: R12, C30: This looks like a band pass */
  361      DISCRETE_RCFILTER(NODE_25, NODE_20, M52_R12, M52_C30)
  362      DISCRETE_SALLEN_KEY_FILTER(NODE_30, 1, NODE_25, DISC_SALLEN_KEY_LOW_PASS, &m52_sound_c_sallen_key)
  363  
  364      /* Mix signals */
  365      DISCRETE_MIXER2(NODE_40, 1, NODE_10, NODE_25, &m52_sound_c_mix1)
  366      DISCRETE_CRFILTER(NODE_45, NODE_40, M52_R10+M52_R9, M52_C28)
  367  
  368      DISCRETE_OUTPUT(NODE_40, 18.0)
  369  
  370  DISCRETE_SOUND_END
  371  
  372  /*************************************
  373   *
  374   *  Address maps
  375   *
  376   *************************************/
  377  
  378  /* complete address map verified from Moon Patrol/10 Yard Fight schematics */
  379  /* large map uses 8k ROMs, small map uses 4k ROMs; this is selected via a jumper */
  380  static ADDRESS_MAP_START( m52_small_sound_map, AS_PROGRAM, 8, driver_device )
  381      ADDRESS_MAP_GLOBAL_MASK(0x7fff)
  382      AM_RANGE(0x0000, 0x0fff) AM_DEVWRITE_LEGACY("irem_audio", m52_adpcm_w)
  383      AM_RANGE(0x1000, 0x1fff) AM_WRITE_LEGACY(sound_irq_ack_w)
  384      AM_RANGE(0x2000, 0x7fff) AM_ROM
  385  ADDRESS_MAP_END
  386  
  387  static ADDRESS_MAP_START( m52_large_sound_map, AS_PROGRAM, 8, driver_device )
  388      AM_RANGE(0x0000, 0x1fff) AM_DEVWRITE_LEGACY("irem_audio", m52_adpcm_w)
  389      AM_RANGE(0x2000, 0x3fff) AM_WRITE_LEGACY(sound_irq_ack_w)
  390      AM_RANGE(0x4000, 0xffff) AM_ROM
  391  ADDRESS_MAP_END
  392  
  393  
  394  /* complete address map verified from Kid Niki schematics */
  395  static ADDRESS_MAP_START( m62_sound_map, AS_PROGRAM, 8, driver_device )
  396      AM_RANGE(0x0800, 0x0800) AM_MIRROR(0xf7fc) AM_WRITE_LEGACY(sound_irq_ack_w)
  397      AM_RANGE(0x0801, 0x0802) AM_MIRROR(0xf7fc) AM_DEVWRITE_LEGACY("irem_audio", m62_adpcm_w)
  398      AM_RANGE(0x4000, 0xffff) AM_ROM
  399  ADDRESS_MAP_END
  400  
  401  
  402  static ADDRESS_MAP_START( irem_sound_portmap, AS_IO, 8, driver_device )
  403      AM_RANGE(M6801_PORT1, M6801_PORT1) AM_DEVREADWRITE_LEGACY("irem_audio", m6803_port1_r, m6803_port1_w)
  404      AM_RANGE(M6801_PORT2, M6801_PORT2) AM_DEVREADWRITE_LEGACY("irem_audio", m6803_port2_r, m6803_port2_w)
  405  ADDRESS_MAP_END
  406  
  407  
  408  
  409  /*************************************
  410   *
  411   *  Machine drivers
  412   *
  413   *************************************/
  414  
  415  static MACHINE_CONFIG_FRAGMENT( irem_audio_base )
  416  
  417      /* basic machine hardware */
  418      MCFG_CPU_ADD("iremsound", M6803, XTAL_3_579545MHz) /* verified on pcb */
  419      MCFG_CPU_IO_MAP(irem_sound_portmap)
  420  
  421      /* sound hardware */
  422      MCFG_SPEAKER_STANDARD_MONO("mono")
  423  
  424      MCFG_SOUND_ADD("irem_audio", IREM_AUDIO, 0)
  425  
  426      MCFG_SOUND_ADD("ay1", AY8910, XTAL_3_579545MHz/4) /* verified on pcb */
  427      MCFG_SOUND_CONFIG(irem_ay8910_interface_1)
  428      MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.80)
  429  
  430      MCFG_SOUND_ADD("ay2", AY8910, XTAL_3_579545MHz/4) /* verified on pcb */
  431      MCFG_SOUND_CONFIG(irem_ay8910_interface_2)
  432      MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.80)
  433  
  434      MCFG_SOUND_ADD("msm1", MSM5205, XTAL_384kHz) /* verified on pcb */
  435      MCFG_SOUND_CONFIG(irem_msm5205_interface_1)
  436      MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.80)
  437  
  438      MCFG_SOUND_ADD("msm2", MSM5205, XTAL_384kHz) /* verified on pcb */
  439      MCFG_SOUND_CONFIG(irem_msm5205_interface_2)
  440      MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.80)
  441  MACHINE_CONFIG_END
  442  
  443  MACHINE_CONFIG_FRAGMENT( m52_sound_c_audio )
  444  
  445      /* basic machine hardware */
  446      MCFG_CPU_ADD("iremsound", M6803, XTAL_3_579545MHz) /* verified on pcb */
  447      MCFG_CPU_IO_MAP(irem_sound_portmap)
  448      MCFG_CPU_PROGRAM_MAP(m52_small_sound_map)
  449  
  450      /* sound hardware */
  451      MCFG_SPEAKER_STANDARD_MONO("mono")
  452  
  453      MCFG_SOUND_ADD("irem_audio", IREM_AUDIO, 0)
  454  
  455      MCFG_SOUND_ADD("ay1", AY8910, XTAL_3_579545MHz/4) /* verified on pcb */
  456      MCFG_SOUND_CONFIG(irem_ay8910_interface_1)
  457      MCFG_SOUND_ROUTE_EX(0, "filtermix", 1.0, 0)
  458  
  459      MCFG_SOUND_ADD("ay2", AY8910, XTAL_3_579545MHz/4) /* verified on pcb */
  460      MCFG_SOUND_CONFIG(irem_ay8910_interface_2)
  461      MCFG_SOUND_ROUTE_EX(0, "filtermix", 1.0, 1)
  462  
  463      MCFG_SOUND_ADD("msm1", MSM5205, XTAL_384kHz) /* verified on pcb */
  464      MCFG_SOUND_CONFIG(irem_msm5205_interface_1)
  465      MCFG_SOUND_ROUTE_EX(0, "filtermix", 1.0, 2)
  466  
  467      MCFG_SOUND_ADD("filtermix", DISCRETE, 0)
  468      MCFG_SOUND_CONFIG_DISCRETE(m52_sound_c)
  469      MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.0)
  470  
  471  MACHINE_CONFIG_END
  472  
  473  MACHINE_CONFIG_DERIVED( m52_large_audio, irem_audio_base )  /* 10 yard fight */
  474  
  475      /* basic machine hardware */
  476      MCFG_CPU_MODIFY("iremsound")
  477      MCFG_CPU_PROGRAM_MAP(m52_large_sound_map)
  478  MACHINE_CONFIG_END
  479  
  480  
  481  MACHINE_CONFIG_DERIVED( m62_audio, irem_audio_base )
  482  
  483      /* basic machine hardware */
  484      MCFG_CPU_MODIFY("iremsound")
  485      MCFG_CPU_PROGRAM_MAP(m62_sound_map)
  486  MACHINE_CONFIG_END
  487  
  488  const device_type IREM_AUDIO = &device_creator<irem_audio_device>;
  489  
  490  irem_audio_device::irem_audio_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
  491      : device_t(mconfig, IREM_AUDIO, "Irem Audio", tag, owner, clock),
  492          device_sound_interface(mconfig, *this)
  493  {
  494      m_token = global_alloc_clear(irem_audio_state);
  495  }
  496  
  497  //-------------------------------------------------
  498  //  device_config_complete - perform any
  499  //  operations now that the configuration is
  500  //  complete
  501  //-------------------------------------------------
  502  
  503  void irem_audio_device::device_config_complete()
  504  {
  505  }
  506  
  507  //-------------------------------------------------
  508  //  device_start - device-specific startup
  509  //-------------------------------------------------
  510  
  511  void irem_audio_device::device_start()
  512  {
  513      DEVICE_START_NAME( irem_audio )(this);
  514  }
  515  
  516  //-------------------------------------------------
  517  //  sound_stream_update - handle a stream update
  518  //-------------------------------------------------
  519  
  520  void irem_audio_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
  521  {
  522      // should never get here
  523      fatalerror("sound_stream_update called; not applicable to legacy sound devices\n");
  524  }