summaryrefslogblamecommitdiffstatshomepage
path: root/src/mame/audio/n8080.cpp
blob: d311fe1e21d797ba28808f28ed64d483cf0e45c9 (plain) (tree)
1
2
3
4
5
6
7
8
9

                                       





                                                                            
                
                           
                           
                    
 


                                            
 
 
                                                  



                                  
                            


                                                                 
                            



                                                                 
                                 
 
                               
 



                                  
 
                                    
 
                                        


 
                                                 
 
                           
         
                                       


            
                                       

         


                                  
 
                                    
 
                                         


 
                                         
 
                                  
         
                                                 
         
                                  
         
                                                



         
                                                                  
 
                           
 
                                
 
                                            


 
                                         
 
                           
 
                                
 
                                                     


 
                                                             
 
                              


 
                                               
 
                                                                  


                                 
                                  


                                                
                                  


                                 
                                                                        


                                 
                                                                       


                                 
                                                                       
         


                                                                                             


 
                                              
 
                                                                  


                                 
                                  


                                 
                                                                       


                                 
                                                                       
         


                                                                                             


 
                                               
 
                                                                    
 


                                                           
 

                                                                                           


 
                                      
 





                                              
 
                                              


 
                                             
 
                               






                            





                                                                                         
 
                                  
         
                                                   
                 
                                                    

                 
                                                    

         
                             
 
                               


 
                                                              
 
                               


 
                                             
 
                               

                            

                            
                            
                            
 





                                                                    
 
                                  
                                             

                                               
 
                             


 
                                                              
 
                               


 
                                           
 
                                                                                                                                                    
 
 
                                           
 
                                                                                                                                                    


 
                                          
 
                        
 







                                                        




                   
                                              
 
                                              
 
                                              
 
                                              


 
                                                 
 
                                              
 
                                                 
 
                                              


 
                                                       
 
                        
 



                                                        




                   
                                             
 
                                                                             


 
                                       
 
                                         


 
                                                 
 
                                           



                                      
                                 
         
                                                                                     


            
                                                                                

         
                                                              


 
                                                                     


                           
                           
         
                                                                                          

         
                                     


 
                                                                    
 
                                                                        
 
                                 
         
                                                                 


            
                                                            
         

                                                                            


 
                                        
 


                                                                                                                                       
 




                                           

 
                                        
 
                             
 





                              
 

                           


 
                                       
 

                                                                                                                                       
 




                                           

 
                                       
 
                             
 




                              
 

                           


 
                                        
 






                                               

 
                                        
 
                             
 





                                  
 

                           


 




                                                       

 



                                                                                 

 
                                                 
 

                                                       
 
                                    





                                                                               
 
                                                                                                                     
 
                            
                                                  
 
                                                                                                
                                                                                        
                                                                 
 
                                         












                                                                                            
                                                      
                  

 
                                                
 

                                                      
 
                                    





                                                                               
 
                            
                                                  
 
                                                                                                
                                                                                        
                                                                 
 
                                         












                                                                                            
                                                      
                  

 
                                                 
 

                                                       
 
                                    







                                                                                    
 
                                                                                                                                    
 
                            
                                                  
                                                                                                                      
                                                                                        
                                                                                                                                  
                  
// license:BSD-3-Clause
// copyright-holders:Pierpaolo Prazzoli
/***************************************************************************

  Nintendo 8080 sound emulation

***************************************************************************/

#include "emu.h"
#include "includes/n8080.h"
#include "sound/volt_reg.h"
#include "speaker.h"


constexpr double ATTACK_RATE = 10e-6 * 500;
constexpr double DECAY_RATE = 10e-6 * 16000;


void n8080_state::spacefev_update_SN76477_status()
{
	double dblR0 = RES_M(1.0);
	double dblR1 = RES_M(1.5);

	if (!m_mono_flop[0])
	{
		dblR0 = 1 / (1 / RES_K(150) + 1 / dblR0); /* ? */
	}
	if (!m_mono_flop[1])
	{
		dblR1 = 1 / (1 / RES_K(620) + 1 / dblR1); /* ? */
	}

	m_sn->decay_res_w(dblR0);

	m_sn->vco_res_w(dblR1);

	m_sn->enable_w(
		!m_mono_flop[0] &&
		!m_mono_flop[1] &&
		!m_mono_flop[2]);

	m_sn->vco_w(m_mono_flop[1]);

	m_sn->mixer_b_w(m_mono_flop[0]);
}


void n8080_state::sheriff_update_SN76477_status()
{
	if (m_mono_flop[1])
	{
		m_sn->vco_voltage_w(5);
	}
	else
	{
		m_sn->vco_voltage_w(0);
	}

	m_sn->enable_w(
		!m_mono_flop[0] &&
		!m_mono_flop[1]);

	m_sn->vco_w(m_mono_flop[0]);

	m_sn->mixer_b_w(!m_mono_flop[0]);
}


void n8080_state::update_SN76477_status()
{
	if (m_n8080_hardware == 1)
	{
		spacefev_update_SN76477_status();
	}
	if (m_n8080_hardware == 2)
	{
		sheriff_update_SN76477_status();
	}
}


void n8080_state::start_mono_flop( int n, const attotime &expire )
{
	m_mono_flop[n] = 1;

	update_SN76477_status();

	m_sound_timer[n]->adjust(expire, n);
}


void n8080_state::stop_mono_flop( int n )
{
	m_mono_flop[n] = 0;

	update_SN76477_status();

	m_sound_timer[n]->adjust(attotime::never, n);
}


TIMER_CALLBACK_MEMBER( n8080_state::stop_mono_flop_callback )
{
	stop_mono_flop(param);
}


void n8080_state::spacefev_sound_pins_changed()
{
	uint16_t changes = ~m_curr_sound_pins & m_prev_sound_pins;

	if (changes & (1 << 0x3))
	{
		stop_mono_flop(1);
	}
	if (changes & ((1 << 0x3) | (1 << 0x6)))
	{
		stop_mono_flop(2);
	}
	if (changes & (1 << 0x3))
	{
		start_mono_flop(0, attotime::from_usec(550 * 36 * 100));
	}
	if (changes & (1 << 0x6))
	{
		start_mono_flop(1, attotime::from_usec(550 * 22 * 33));
	}
	if (changes & (1 << 0x4))
	{
		start_mono_flop(2, attotime::from_usec(550 * 22 * 33));
	}

	bool irq_active = (~m_curr_sound_pins & ((1 << 0x2) | (1 << 0x3) | (1 << 0x5))) != 0;
	m_audiocpu->set_input_line(INPUT_LINE_IRQ0, irq_active ? ASSERT_LINE : CLEAR_LINE);
}


void n8080_state::sheriff_sound_pins_changed()
{
	uint16_t changes = ~m_curr_sound_pins & m_prev_sound_pins;

	if (changes & (1 << 0x6))
	{
		stop_mono_flop(1);
	}
	if (changes & (1 << 0x6))
	{
		start_mono_flop(0, attotime::from_usec(550 * 33 * 33));
	}
	if (changes & (1 << 0x4))
	{
		start_mono_flop(1, attotime::from_usec(550 * 33 * 33));
	}

	bool irq_active = (~m_curr_sound_pins & ((1 << 0x2) | (1 << 0x3) | (1 << 0x5))) != 0;
	m_audiocpu->set_input_line(INPUT_LINE_IRQ0, irq_active ? ASSERT_LINE : CLEAR_LINE);
}


void n8080_state::helifire_sound_pins_changed()
{
	//uint16_t changes = ~m_curr_sound_pins & m_prev_sound_pins;

	/* ((m_curr_sound_pins >> 0xa) & 1) not emulated */
	/* ((m_curr_sound_pins >> 0xb) & 1) not emulated */
	/* ((m_curr_sound_pins >> 0xc) & 1) not emulated */

	bool irq_active = (~m_curr_sound_pins & (1 << 6)) != 0;
	m_audiocpu->set_input_line(INPUT_LINE_IRQ0, irq_active ? ASSERT_LINE : CLEAR_LINE);
}


void n8080_state::sound_pins_changed()
{
	if (m_n8080_hardware == 1)
		spacefev_sound_pins_changed();
	if (m_n8080_hardware == 2)
		sheriff_sound_pins_changed();
	if (m_n8080_hardware == 3)
		helifire_sound_pins_changed();

	m_prev_sound_pins = m_curr_sound_pins;
}


void n8080_state::delayed_sound_1( int data )
{
	m_curr_sound_pins &= ~(
		(1 << 0x7) |
		(1 << 0x5) |
		(1 << 0x6) |
		(1 << 0x3) |
		(1 << 0x4) |
		(1 << 0x1));

	if (~data & 0x01) m_curr_sound_pins |= 1 << 0x7;
	if (~data & 0x02) m_curr_sound_pins |= 1 << 0x5; /* pulse */
	if (~data & 0x04) m_curr_sound_pins |= 1 << 0x6; /* pulse */
	if (~data & 0x08) m_curr_sound_pins |= 1 << 0x3; /* pulse (except in Helifire) */
	if (~data & 0x10) m_curr_sound_pins |= 1 << 0x4; /* pulse (except in Helifire) */
	if (~data & 0x20) m_curr_sound_pins |= 1 << 0x1;

	if (m_n8080_hardware == 1)
	{
		if (data & ~m_prev_snd_data & 0x10)
		{
			spacefev_start_red_cannon();
		}

		m_spacefev_red_screen = data & 0x08;
	}

	sound_pins_changed();

	m_prev_snd_data = data;
}


TIMER_CALLBACK_MEMBER( n8080_state::delayed_sound_1_callback )
{
	delayed_sound_1(param);
}


void n8080_state::delayed_sound_2( int data )
{
	m_curr_sound_pins &= ~(
		(1 << 0x8) |
		(1 << 0x9) |
		(1 << 0xa) |
		(1 << 0xb) |
		(1 << 0x2) |
		(1 << 0xc));

	if (~data & 0x01) m_curr_sound_pins |= 1 << 0x8;
	if (~data & 0x02) m_curr_sound_pins |= 1 << 0x9;
	if (~data & 0x04) m_curr_sound_pins |= 1 << 0xa;
	if (~data & 0x08) m_curr_sound_pins |= 1 << 0xb;
	if (~data & 0x10) m_curr_sound_pins |= 1 << 0x2; /* pulse */
	if (~data & 0x20) m_curr_sound_pins |= 1 << 0xc;

	if (m_n8080_hardware == 1)
		flip_screen_set(data & 0x20);
	if (m_n8080_hardware == 3)
		m_helifire_flash = data & 0x20;

	sound_pins_changed();
}


TIMER_CALLBACK_MEMBER( n8080_state::delayed_sound_2_callback )
{
	delayed_sound_2(param);
}


WRITE8_MEMBER(n8080_state::n8080_sound_1_w)
{
	machine().scheduler().synchronize(timer_expired_delegate(FUNC(n8080_state::delayed_sound_1_callback), this), data); /* force CPUs to sync */
}

WRITE8_MEMBER(n8080_state::n8080_sound_2_w)
{
	machine().scheduler().synchronize(timer_expired_delegate(FUNC(n8080_state::delayed_sound_2_callback), this), data); /* force CPUs to sync */
}


READ8_MEMBER(n8080_state::n8080_8035_p1_r)
{
	uint8_t val = 0;

	if ((m_curr_sound_pins >> 0xb) & 1) val |= 0x01;
	if ((m_curr_sound_pins >> 0xa) & 1) val |= 0x02;
	if ((m_curr_sound_pins >> 0x9) & 1) val |= 0x04;
	if ((m_curr_sound_pins >> 0x8) & 1) val |= 0x08;
	if ((m_curr_sound_pins >> 0x5) & 1) val |= 0x10;
	if ((m_curr_sound_pins >> 0x3) & 1) val |= 0x20;
	if ((m_curr_sound_pins >> 0x2) & 1) val |= 0x40;
	if ((m_curr_sound_pins >> 0x1) & 1) val |= 0x80;

	return val;
}


READ_LINE_MEMBER(n8080_state::n8080_8035_t0_r)
{
	return (m_curr_sound_pins >> 0x7) & 1;
}
READ_LINE_MEMBER(n8080_state::n8080_8035_t1_r)
{
	return (m_curr_sound_pins >> 0xc) & 1;
}


READ_LINE_MEMBER(n8080_state::helifire_8035_t0_r)
{
	return (m_curr_sound_pins >> 0x3) & 1;
}
READ_LINE_MEMBER(n8080_state::helifire_8035_t1_r)
{
	return (m_curr_sound_pins >> 0x4) & 1;
}


READ8_MEMBER(n8080_state::helifire_8035_external_ram_r)
{
	uint8_t val = 0;

	if ((m_curr_sound_pins >> 0x7) & 1) val |= 0x01;
	if ((m_curr_sound_pins >> 0x8) & 1) val |= 0x02;
	if ((m_curr_sound_pins >> 0x9) & 1) val |= 0x04;
	if ((m_curr_sound_pins >> 0x1) & 1) val |= 0x08;

	return val;
}


READ8_MEMBER(n8080_state::helifire_8035_p2_r)
{
	return ((m_curr_sound_pins >> 0xc) & 1) ? 0x10 : 0x00; /* not used */
}


WRITE8_MEMBER(n8080_state::n8080_dac_w)
{
	m_n8080_dac->write(BIT(data, 7));
}


WRITE8_MEMBER(n8080_state::helifire_sound_ctrl_w)
{
	m_helifire_dac_phase = data & 0x80;

	/* data & 0x40 not emulated */
	/* data & 0x20 not emulated */

	if (m_helifire_dac_phase)
	{
		m_helifire_dac_timing = ATTACK_RATE * log(1 - m_helifire_dac_volume);
	}
	else
	{
		m_helifire_dac_timing = DECAY_RATE * log(m_helifire_dac_volume);
	}

	m_helifire_dac_timing += machine().time().as_double();
}


TIMER_DEVICE_CALLBACK_MEMBER(n8080_state::spacefev_vco_voltage_timer)
{
	double voltage = 0;

	if (m_mono_flop[2])
	{
		voltage = 5 * (1 - exp(- m_sound_timer[2]->elapsed().as_double() / 0.22));
	}

	m_sn->vco_voltage_w(voltage);
}


TIMER_DEVICE_CALLBACK_MEMBER(n8080_state::helifire_dac_volume_timer)
{
	double t = m_helifire_dac_timing - machine().time().as_double();

	if (m_helifire_dac_phase)
	{
		m_helifire_dac_volume = 1 - exp(t / ATTACK_RATE);
	}
	else
	{
		m_helifire_dac_volume = exp(t / DECAY_RATE);
	}

	m_helifire_dac->set_output_gain(ALL_OUTPUTS, m_helifire_dac_volume);
}


SOUND_START_MEMBER(n8080_state,spacefev)
{
	m_sound_timer[0] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(n8080_state::stop_mono_flop_callback), this));
	m_sound_timer[1] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(n8080_state::stop_mono_flop_callback), this));
	m_sound_timer[2] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(n8080_state::stop_mono_flop_callback), this));

	save_item(NAME(m_prev_snd_data));
	save_item(NAME(m_prev_sound_pins));
	save_item(NAME(m_curr_sound_pins));
	save_item(NAME(m_n8080_hardware));
	save_item(NAME(m_mono_flop));
}

SOUND_RESET_MEMBER(n8080_state,spacefev)
{
	m_n8080_hardware = 1;

	m_mono_flop[0] = 0;
	m_mono_flop[1] = 0;
	m_mono_flop[2] = 0;
	m_prev_snd_data = 0;
	m_prev_sound_pins = 0;
	m_curr_sound_pins = 0;

	delayed_sound_1(0);
	delayed_sound_2(0);
}


SOUND_START_MEMBER(n8080_state,sheriff)
{
	m_sound_timer[0] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(n8080_state::stop_mono_flop_callback), this));
	m_sound_timer[1] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(n8080_state::stop_mono_flop_callback), this));

	save_item(NAME(m_prev_snd_data));
	save_item(NAME(m_prev_sound_pins));
	save_item(NAME(m_curr_sound_pins));
	save_item(NAME(m_n8080_hardware));
	save_item(NAME(m_mono_flop));
}

SOUND_RESET_MEMBER(n8080_state,sheriff)
{
	m_n8080_hardware = 2;

	m_mono_flop[0] = 0;
	m_mono_flop[1] = 0;
	m_prev_snd_data = 0;
	m_prev_sound_pins = 0;
	m_curr_sound_pins = 0;

	delayed_sound_1(0);
	delayed_sound_2(0);
}


SOUND_START_MEMBER(n8080_state,helifire)
{
	save_item(NAME(m_prev_snd_data));
	save_item(NAME(m_prev_sound_pins));
	save_item(NAME(m_curr_sound_pins));
	save_item(NAME(m_n8080_hardware));
	save_item(NAME(m_helifire_dac_volume));
	save_item(NAME(m_helifire_dac_timing));
	save_item(NAME(m_helifire_dac_phase));
}

SOUND_RESET_MEMBER(n8080_state,helifire)
{
	m_n8080_hardware = 3;

	m_helifire_dac_volume = 1;
	m_helifire_dac_timing = 0;
	m_helifire_dac_phase = 0;
	m_prev_snd_data = 0;
	m_prev_sound_pins = 0;
	m_curr_sound_pins = 0;

	delayed_sound_1(0);
	delayed_sound_2(0);
}


void n8080_state::n8080_sound_cpu_map(address_map &map)
{
	map.global_mask(0x3ff);
	map(0x0000, 0x03ff).rom();
}


void n8080_state::helifire_sound_io_map(address_map &map)
{
	map(0x00, 0x7f).r(this, FUNC(n8080_state::helifire_8035_external_ram_r));
}


MACHINE_CONFIG_START(n8080_state::spacefev_sound)

	MCFG_SOUND_START_OVERRIDE(n8080_state,spacefev)
	MCFG_SOUND_RESET_OVERRIDE(n8080_state,spacefev)

	/* basic machine hardware */
	MCFG_DEVICE_ADD("audiocpu", I8035, 6000000)
	MCFG_DEVICE_PROGRAM_MAP(n8080_sound_cpu_map)
	MCFG_MCS48_PORT_T0_IN_CB(READLINE(*this, n8080_state, n8080_8035_t0_r))
	MCFG_MCS48_PORT_T1_IN_CB(READLINE(*this, n8080_state, n8080_8035_t1_r))
	MCFG_MCS48_PORT_P1_IN_CB(READ8(*this, n8080_state, n8080_8035_p1_r))
	MCFG_MCS48_PORT_P2_OUT_CB(WRITE8(*this, n8080_state, n8080_dac_w))

	MCFG_TIMER_DRIVER_ADD_PERIODIC("vco_timer", n8080_state, spacefev_vco_voltage_timer, attotime::from_hz(1000))

	/* sound hardware */
	SPEAKER(config, "speaker").front_center();

	MCFG_DEVICE_ADD("n8080_dac", DAC_1BIT, 0) MCFG_SOUND_ROUTE(ALL_OUTPUTS, "speaker", 0.15)
	MCFG_DEVICE_ADD("vref", VOLTAGE_REGULATOR, 0) MCFG_VOLTAGE_REGULATOR_OUTPUT(5.0)
	MCFG_SOUND_ROUTE(0, "n8080_dac", 1.0, DAC_VREF_POS_INPUT)

	MCFG_DEVICE_ADD("snsnd", SN76477)
	MCFG_SN76477_NOISE_PARAMS(RES_K(36), RES_K(150), CAP_N(1)) // noise + filter
	MCFG_SN76477_DECAY_RES(RES_M(1))                    // decay_res
	MCFG_SN76477_ATTACK_PARAMS(CAP_U(1.0), RES_K(20))   // attack_decay_cap + attack_res
	MCFG_SN76477_AMP_RES(RES_K(150))                    // amplitude_res
	MCFG_SN76477_FEEDBACK_RES(RES_K(47))                // feedback_res
	MCFG_SN76477_VCO_PARAMS(0, CAP_N(1), RES_M(1.5))    // VCO volt + cap + res
	MCFG_SN76477_PITCH_VOLTAGE(0)                       // pitch_voltage
	MCFG_SN76477_SLF_PARAMS(CAP_N(47), RES_M(1))        // slf caps + res
	MCFG_SN76477_ONESHOT_PARAMS(CAP_N(47), RES_K(820))  // oneshot caps + res
	MCFG_SN76477_VCO_MODE(0)                            // VCO mode
	MCFG_SN76477_MIXER_PARAMS(0, 0, 0)                  // mixer A, B, C
	MCFG_SN76477_ENVELOPE_PARAMS(1, 0)                  // envelope 1, 2
	MCFG_SN76477_ENABLE(1)                              // enable
	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "speaker", 0.35)
MACHINE_CONFIG_END


MACHINE_CONFIG_START(n8080_state::sheriff_sound)

	MCFG_SOUND_START_OVERRIDE(n8080_state,sheriff)
	MCFG_SOUND_RESET_OVERRIDE(n8080_state,sheriff)

	/* basic machine hardware */
	MCFG_DEVICE_ADD("audiocpu", I8035, 6000000)
	MCFG_DEVICE_PROGRAM_MAP(n8080_sound_cpu_map)
	MCFG_MCS48_PORT_T0_IN_CB(READLINE(*this, n8080_state, n8080_8035_t0_r))
	MCFG_MCS48_PORT_T1_IN_CB(READLINE(*this, n8080_state, n8080_8035_t1_r))
	MCFG_MCS48_PORT_P1_IN_CB(READ8(*this, n8080_state, n8080_8035_p1_r))
	MCFG_MCS48_PORT_P2_OUT_CB(WRITE8(*this, n8080_state, n8080_dac_w))

	/* sound hardware */
	SPEAKER(config, "speaker").front_center();

	MCFG_DEVICE_ADD("n8080_dac", DAC_1BIT, 0) MCFG_SOUND_ROUTE(ALL_OUTPUTS, "speaker", 0.15)
	MCFG_DEVICE_ADD("vref", VOLTAGE_REGULATOR, 0) MCFG_VOLTAGE_REGULATOR_OUTPUT(5.0)
	MCFG_SOUND_ROUTE(0, "n8080_dac", 1.0, DAC_VREF_POS_INPUT)

	MCFG_DEVICE_ADD("snsnd", SN76477)
	MCFG_SN76477_NOISE_PARAMS(RES_K(36), RES_K(100), CAP_N(1)) // noise + filter
	MCFG_SN76477_DECAY_RES(RES_K(620))                  // decay_res
	MCFG_SN76477_ATTACK_PARAMS(CAP_U(1.0), RES_K(20))   // attack_decay_cap + attack_res
	MCFG_SN76477_AMP_RES(RES_K(150))                    // amplitude_res
	MCFG_SN76477_FEEDBACK_RES(RES_K(47))                // feedback_res
	MCFG_SN76477_VCO_PARAMS(0, CAP_N(1), RES_M(1.5))    // VCO volt + cap + res
	MCFG_SN76477_PITCH_VOLTAGE(0)                       // pitch_voltage
	MCFG_SN76477_SLF_PARAMS(CAP_N(47), RES_M(1.5))      // slf caps + res
	MCFG_SN76477_ONESHOT_PARAMS(CAP_N(47), RES_K(560))  // oneshot caps + res
	MCFG_SN76477_VCO_MODE(0)                            // VCO mode
	MCFG_SN76477_MIXER_PARAMS(0, 0, 0)                  // mixer A, B, C
	MCFG_SN76477_ENVELOPE_PARAMS(1, 0)                  // envelope 1, 2
	MCFG_SN76477_ENABLE(1)                              // enable
	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "speaker", 0.35)
MACHINE_CONFIG_END


MACHINE_CONFIG_START(n8080_state::helifire_sound)

	MCFG_SOUND_START_OVERRIDE(n8080_state,helifire)
	MCFG_SOUND_RESET_OVERRIDE(n8080_state,helifire)

	/* basic machine hardware */
	MCFG_DEVICE_ADD("audiocpu", I8035, 6000000)
	MCFG_DEVICE_PROGRAM_MAP(n8080_sound_cpu_map)
	MCFG_DEVICE_IO_MAP(helifire_sound_io_map)
	MCFG_MCS48_PORT_T0_IN_CB(READLINE(*this, n8080_state, helifire_8035_t0_r))
	MCFG_MCS48_PORT_T1_IN_CB(READLINE(*this, n8080_state, helifire_8035_t1_r))
	MCFG_MCS48_PORT_P2_IN_CB(READ8(*this, n8080_state, helifire_8035_p2_r))
	MCFG_MCS48_PORT_P1_OUT_CB(WRITE8("helifire_dac", dac_byte_interface, write))
	MCFG_MCS48_PORT_P2_OUT_CB(WRITE8(*this, n8080_state, helifire_sound_ctrl_w))

	MCFG_TIMER_DRIVER_ADD_PERIODIC("helifire_dac_volume_timer", n8080_state, helifire_dac_volume_timer, attotime::from_hz(1000))

	/* sound hardware */
	SPEAKER(config, "speaker").front_center();
	MCFG_DEVICE_ADD("helifire_dac", DAC_8BIT_R2R, 0) MCFG_SOUND_ROUTE(ALL_OUTPUTS, "speaker", 0.15) // unknown DAC
	MCFG_DEVICE_ADD("vref", VOLTAGE_REGULATOR, 0) MCFG_VOLTAGE_REGULATOR_OUTPUT(5.0)
	MCFG_SOUND_ROUTE(0, "helifire_dac", 1.0, DAC_VREF_POS_INPUT) MCFG_SOUND_ROUTE(0, "helifire_dac", -1.0, DAC_VREF_NEG_INPUT)
MACHINE_CONFIG_END