summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/audio/gamate.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mame/audio/gamate.c')
-rw-r--r--src/mame/audio/gamate.c253
1 files changed, 253 insertions, 0 deletions
diff --git a/src/mame/audio/gamate.c b/src/mame/audio/gamate.c
new file mode 100644
index 00000000000..19555dd7c44
--- /dev/null
+++ b/src/mame/audio/gamate.c
@@ -0,0 +1,253 @@
+// license:GPL-2.0+
+// copyright-holders:Peter Trauner
+/***************************************************************************
+ gamate sound hardware
+
+ PeT mess@utanet.at 2015
+***************************************************************************/
+
+#include "emu.h"
+#include "includes/gamate.h"
+#include "ui/ui.h"
+
+
+enum { ClockDelay=32 };
+
+// device type definition
+const device_type GAMATE_SND = &device_creator<gamate_sound_device>;
+
+const int gamate_sound_device::DAConverter[]={ 0, 3, 7, 13, 23, 41, 75, 137, 249, 453, 825, 1499, 2726, 4956, 9011, 16383 }; // (*.55) on the real below index 8 bareless measureable
+const UINT8 Mask[]={ 0xff, 0x0f, 0xff, 0x0f, 0xff, 0x0f, 0x1f, 0x3f, 0x1f, 0x1f, 0x1f, 0xff, 0xff, 0xf };
+const int EnvelopeVolumes[]={ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// gamate_sound_device - constructor
+//-------------------------------------------------
+
+gamate_sound_device::gamate_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, GAMATE_SND, "Gamate Audio Custom", tag, owner, clock, "gamate_sound", __FILE__)
+ , device_sound_interface(mconfig, *this)
+ , m_mixer_channel(NULL)
+ {}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void gamate_sound_device::device_start()
+{
+ // bind callbacks
+// m_irq_cb.bind_relative_to(*owner());
+
+ memset(m_channels, 0, sizeof(m_channels));
+ memset(reg, 0, sizeof(reg));
+
+ m_mixer_channel = stream_alloc(0, 2, machine().sample_rate());
+}
+
+
+//-------------------------------------------------
+// sound_stream_update - handle a stream update
+//-------------------------------------------------
+
+void gamate_sound_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
+{
+ stream_sample_t *left=outputs[0], *right=outputs[1];
+ int i, j;
+ Tone *channel;
+
+ for (i = 0; i < samples; i++, left++, right++)
+ {
+ noise.pos += noise.step;
+ while (noise.pos >= 1.0)
+ {
+ // guess (white noise register taken from supervision)
+ noise.level = noise.state & 0x40 ? 1 : 0;
+ bool b1 = (noise.state & 0x40) != 0, b2 = (noise.state & 0x20) != 0;
+ noise.state=(noise.state<<1)+(b1!=b2?1:0);
+ noise.pos -= 1;
+ }
+
+ envelope.pos += envelope.step;
+ while (envelope.pos >= 1.0) {
+ envelope.pos -= 1;
+ envelope.index++;
+ switch (envelope.control)
+ {
+ case 0: case 1: case 2: case 3:
+ case 4: case 5: case 6: case 7:
+ case 8: case 9: case 0xb:
+ case 0xd: case 0xf:
+ if (envelope.index>=ARRAY_LENGTH(EnvelopeVolumes)/2)
+ {
+ envelope.index=0;
+ envelope.first=false;
+ }
+ break;
+ default:
+ if (envelope.index>=ARRAY_LENGTH(EnvelopeVolumes))
+ {
+ envelope.index=0;
+ envelope.first=false;
+ }
+ break;
+ }
+ }
+
+ *left = 0;
+ *right = 0;
+ for (channel=m_channels, j=0; j<ARRAY_LENGTH(m_channels); j++, channel++)
+ {
+ if (channel->size != 0)
+ {
+ channel->level= channel->pos <= channel->size / 2;
+ bool l= channel->full_cycle? true: channel->level;
+ if (!channel->tone)
+ l= l && noise.level;
+ int volume=0;
+ if (l)
+ {
+ if (channel->envelope_on)
+ {
+ switch (envelope.control)
+ {
+ case 0: case 1: case 2: case 3:
+ case 0x9: // one time falling, low
+ if (envelope.first && channel->level)
+ volume=0xf-EnvelopeVolumes[envelope.index];
+ break;
+ case 4: case 5: case 6: case 7:
+ case 0xf: // one time rising, low
+ if (envelope.first && channel->level)
+ volume=EnvelopeVolumes[envelope.index];
+ break;
+ case 8: // falling
+ if (channel->level)
+ volume=0xf-EnvelopeVolumes[envelope.index];
+ break;
+ case 0xa: // rising, falling
+ if (channel->level)
+ volume=0xf-EnvelopeVolumes[envelope.index]; // cube up
+ break;
+ case 0xb: // one time falling, high
+ if (channel->level)
+ volume=envelope.first ? 0xf-EnvelopeVolumes[envelope.index] : 0xf;
+ break;
+ case 0xc: // rising, low
+ if (channel->level)
+ volume=envelope.index<ARRAY_LENGTH(EnvelopeVolumes)/2 ? EnvelopeVolumes[envelope.index] : 0;
+ break;
+ case 0xd: // one time rising, high
+ if (channel->level)
+ volume=envelope.first ? EnvelopeVolumes[envelope.index] : 0xf;
+ break;
+ case 0xe: // falling, rising
+ if (channel->level)
+ volume=0xf-EnvelopeVolumes[envelope.index];
+ break;
+ }
+ }
+ else
+ {
+ volume=channel->volume;
+ }
+ }
+ if (j == Right)
+ *right += Value2Volume(volume);
+ else
+ if (j==Left)
+ *left += Value2Volume(volume);
+ else
+ {
+ *right += Value2Volume(volume);
+ *left += Value2Volume(volume);
+ }
+ channel->pos++;
+ if (channel->pos >= channel->size)
+ channel->pos = 0;
+ }
+ }
+ }
+}
+
+WRITE8_MEMBER( gamate_sound_device::device_w )
+{
+ UINT16 size;
+
+ m_mixer_channel->update();
+ reg[offset] = data;
+ int chan=-1;
+
+ switch (offset&0xf)
+ {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ chan=offset/2;
+ size = reg[chan*2] | ((reg[chan*2+1] & 0xf) << 8);
+ if (size)
+ {
+ m_channels[chan].size= (int) (machine().sample_rate() * size*ClockDelay / m_clock);
+ }
+ else
+ {
+ m_channels[chan].size = 0;
+ }
+ m_channels[chan].pos = 0;
+ break;
+ case 6:
+ size=data&0x1f;
+ if (size==0)
+ size=1;
+ noise.step= m_clock / (1.0*ClockDelay*machine().sample_rate()*size);
+ break;
+ case 7:
+ m_channels[Right].full_cycle=data&1;
+ m_channels[Right].tone=data&8;
+ m_channels[Left].full_cycle=data&2;
+ m_channels[Left].tone=data&0x10;
+ m_channels[Both].full_cycle=data&4;
+ m_channels[Both].tone=data&0x20;
+ noise.state=1;
+ noise.pos=0.0;
+ noise.level=false;
+ break;
+ case 8:
+ case 9:
+ case 0xa:
+ chan=offset-8;
+ m_channels[chan].envelope_on = data & 0x10; // buggy aussetzer cube up
+ m_channels[chan].volume = data & 0xf;
+ break;
+ case 0xb: case 0xc:
+ size = reg[0xb] | ((reg[0xc]) << 8);
+ if (size==0)
+ size=1;
+ envelope.step= m_clock / (1.0*ClockDelay*machine().sample_rate()*size);
+ break;
+ case 0xd:
+ envelope.control=data&0xf;
+ envelope.pos=0;
+ envelope.index=0;
+ envelope.first=true;
+ break;
+
+ }
+ envelope.pos=0; // guess
+ envelope.index=0;
+ envelope.first=true;
+}
+
+READ8_MEMBER( gamate_sound_device::device_r )
+{
+ UINT8 data=0;
+ if ((offset&0xf)<ARRAY_LENGTH(Mask))
+ data=reg[offset&0xf]&Mask[offset&0xf]; // unused bits set to last write value? in this area
+ return data;
+}