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

                                  






                                                                            
                     
 
 
                         
                                                                                                   
 
 


                                                                            
 


                                                   
 
                                                                                                                           

                                                           


                                                  
                                  
 

 
 


                                                   
 
                                         
 
                                
 


                                                
 
                                                                      

 
 
                                                   
                                                
                                                   
 
                                                                                                                                                          
 

                               
 
                                                
         

                             
                                                                 
                 

                                                       
                         
                                                              
                                 
                                                        
                                                                 

                                                       
                                                                                                     

                                                              
                                                                                                     


                                                              
                                                                                             

                                                              
                                                                                                    


                                                              
                                                                                         
                                                           
                                                                  
                                                    
                                                                  

                                         


                                                                

                         
                                                                  
                 
                                                                                 
                                   
                                         
                                          
                                          
                                          

                                                    
                         
                                                     
                                 
                                                                   



                                                                                              
                                                      
                                                                    
                                                



                                                                                                          
                                 
                                                 

                         
                             
                 


                                                                               

                                                            
                                                                                                         


                            
                                                                                      
                         
                                                      



                                                         
                                       
                                          
                                        
                                          

                                                    
                         

                                                      
                                            

                         

                                              


         
 
                                                                  
 
                                                                                                         










                                                                           
                                                                                                             











                                                                    

 
 
                                                               
 





                                                                                             
                                                                                                       




                                                 
                                                             







                                                                       

 
 
                                            
 





                                     

 
 
                                                                       
 
                                           
                      

                                  
                                   




                       
                                                                            

                                 
                                                                                                      
                                                                                                                


                            
                                                 
                         
                                        

                              


                                                              

                              
                                                 

                              
 
// license:GPL-2.0+
// copyright-holders:Peter Trauner
/***************************************************************************
 supervision sound hardware

 PeT mess@utanet.at
***************************************************************************/

#include "emu.h"
#include "svis_snd.h"


// device type definition
DEFINE_DEVICE_TYPE(SVISION_SND, svision_sound_device, "svision_sound", "Super Vision Custom Sound")


//**************************************************************************
//  LIVE DEVICE
//**************************************************************************

//-------------------------------------------------
//  svision_sound_device - constructor
//-------------------------------------------------

svision_sound_device::svision_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
	: device_t(mconfig, SVISION_SND, tag, owner, clock)
	, device_sound_interface(mconfig, *this)
	, m_irq_cb(*this)
	, m_maincpu(*this, finder_base::DUMMY_TAG)
	, m_cartrom(*this, finder_base::DUMMY_TAG)
	, m_mixer_channel(nullptr)
{
}


//-------------------------------------------------
//  device_start - device-specific startup
//-------------------------------------------------

void svision_sound_device::device_start()
{
	m_irq_cb.resolve_safe();

	memset(&m_dma, 0, sizeof(m_dma));
	memset(&m_noise, 0, sizeof(m_noise));
	memset(m_channel, 0, sizeof(m_channel));

	m_mixer_channel = stream_alloc(0, 2, machine().sample_rate());
}


//-------------------------------------------------
//  sound_stream_update - handle a stream update
//-------------------------------------------------

void svision_sound_device::sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs)
{
	auto &left=outputs[0];
	auto &right=outputs[1];

	for (int i = 0; i < left.samples(); i++)
	{
		s32 lsum = 0;
		s32 rsum = 0;
		for (int j = 0; j < ARRAY_LENGTH(m_channel); j++)
		{
			CHANNEL &channel(m_channel[j]);
			if (channel.size != 0)
			{
				if (channel.on||channel.count)
				{
					bool on = false;
					switch (channel.waveform)
					{
						case 0:
							on = channel.pos <= (28 * channel.size) >> 5;
							break;
						case 1:
							on = channel.pos <= (24 * channel.size) >> 5;
							break;
						default:
						case 2:
							on = channel.pos <= channel.size / 2;
							break;
						case 3:
							on = channel.pos <= (9 * channel.size) >> 5;
							break;
					}
					{
						int16_t s = on ? channel.volume << 8 : 0;
						if (j == 0)
							rsum += s;
						else
							lsum += s;
					}
				}
				channel.pos++;
				if (channel.pos >= channel.size)
					channel.pos = 0;
			}
		}
		if (m_noise.on && (m_noise.play || m_noise.count))
		{
			int16_t s = (m_noise.value ? 1 << 8: 0) * m_noise.volume;
			int b1, b2;
			if (m_noise.left)
				lsum += s;
			if (m_noise.right)
				rsum += s;
			m_noise.pos += m_noise.step;
			if (m_noise.pos >= 1.0)
			{
				switch (m_noise.type)
				{
					case NOISE::Type::Type7Bit:
						m_noise.value = m_noise.state & 0x40 ? 1 : 0;
						b1 = (m_noise.state & 0x40) != 0;
						b2 = (m_noise.state & 0x20) != 0;
						m_noise.state=(m_noise.state<<1)+(b1!=b2?1:0);
						break;
					case NOISE::Type::Type14Bit:
					default:
						m_noise.value = m_noise.state & 0x2000 ? 1 : 0;
						b1 = (m_noise.state & 0x2000) != 0;
						b2 = (m_noise.state & 0x1000) != 0;
						m_noise.state = (m_noise.state << 1) + (b1 != b2 ? 1 : 0);
				}
				m_noise.pos -= 1;
			}
		}
		if (m_dma.on)
		{
			uint8_t sample;
			int16_t s;
			uint16_t addr = m_dma.start + (unsigned) m_dma.pos / 2;
			if (addr >= 0x8000 && addr < 0xc000)
			{
				sample = ((uint8_t*)m_cartrom->base())[(addr & 0x3fff) | m_dma.ca14to16];
			}
			else
			{
				sample = m_maincpu->space(AS_PROGRAM).read_byte(addr);
			}
			if (((unsigned)m_dma.pos) & 1)
				s = (sample & 0xf);
			else
				s = (sample & 0xf0) >> 4;
			s <<= 8;
			if (m_dma.left)
				lsum += s;
			if (m_dma.right)
				rsum += s;
			m_dma.pos += m_dma.step;
			if (m_dma.pos >= m_dma.size)
			{
				m_dma.finished = true;
				m_dma.on = false;
				m_irq_cb(1);
			}
		}
		left.put_int(i, lsum, 32768);
		right.put_int(i, rsum, 32768);
	}
}


void svision_sound_device::sounddma_w(offs_t offset, uint8_t data)
{
	logerror("%.6f svision snddma write %04x %02x\n", machine().time().as_double(),offset+0x18,data);
	m_dma.reg[offset] = data;
	switch (offset)
	{
		case 0:
		case 1:
			m_dma.start = (m_dma.reg[0] | (m_dma.reg[1] << 8));
			break;
		case 2:
			m_dma.size = (data ? data : 0x100) * 32;
			break;
		case 3:
			m_dma.step = unscaled_clock() / (256.0 * machine().sample_rate() * (1 + (data & 3)));
			m_dma.right = data & 4;
			m_dma.left = data & 8;
			m_dma.ca14to16 = ((data & 0x70) >> 4) << 14;
			break;
		case 4:
			m_dma.on = data & 0x80;
			if (m_dma.on)
			{
				m_dma.pos = 0.0;
			}
			break;
	}
}


void svision_sound_device::noise_w(offs_t offset, uint8_t data)
{
	//  logerror("%.6f svision noise write %04x %02x\n",machine.time(),offset+0x28,data);
	m_noise.reg[offset]=data;
	switch (offset)
	{
		case 0:
			m_noise.volume=data&0xf;
			m_noise.step= unscaled_clock() / (256.0*machine().sample_rate()*(1+(data>>4)));
			break;
		case 1:
			m_noise.count = data + 1;
			break;
		case 2:
			m_noise.type = NOISE::Type(data & 1);
			m_noise.play = data & 2;
			m_noise.right = data & 4;
			m_noise.left = data & 8;
			m_noise.on = data & 0x10; /* honey bee start */
			m_noise.state = 1;
			break;
	}
	m_noise.pos=0.0;
}


void svision_sound_device::sound_decrement()
{
	if (m_channel[0].count > 0)
		m_channel[0].count--;
	if (m_channel[1].count > 0)
		m_channel[1].count--;
	if (m_noise.count > 0)
		m_noise.count--;
}


void svision_sound_device::soundport_w(int which, int offset, int data)
{
	CHANNEL &channel(m_channel[which]);
	uint16_t size;

	m_mixer_channel->update();
	channel.reg[offset] = data;

	switch (offset)
	{
		case 0:
		case 1:
			size = channel.reg[0] | ((channel.reg[1] & 7) << 8);
			if (size)
			{
				//  channel.size=(int)(device->machine().sample_rate()*(size<<5)/4e6);
				channel.size = (int) (machine().sample_rate() * (size << 5) / unscaled_clock());
			}
			else
			{
				channel.size = 0;
			}
			channel.pos = 0;
			break;
		case 2:
			channel.on = data & 0x40;
			channel.waveform = (data & 0x30) >> 4;
			channel.volume = data & 0xf;
			break;
		case 3:
			channel.count = data + 1;
			break;
	}
}