diff options
Diffstat (limited to 'src/mess/audio/lynx.c')
-rw-r--r-- | src/mess/audio/lynx.c | 540 |
1 files changed, 0 insertions, 540 deletions
diff --git a/src/mess/audio/lynx.c b/src/mess/audio/lynx.c deleted file mode 100644 index 2e17abde91f..00000000000 --- a/src/mess/audio/lynx.c +++ /dev/null @@ -1,540 +0,0 @@ -// license:GPL-2.0+ -// copyright-holders:Peter Trauner -/****************************************************************************** - PeT mess@utanet.at 2000,2001 -******************************************************************************/ - -#include "emu.h" -#include "audio/lynx.h" - - -/* accordingly to atari's reference manual - there were no stereo lynx produced (the manual knows only production until mid 1991) - the howard/developement board might have stereo support - the revised lynx 2 hardware might have stereo support at least at the stereo jacks - - some games support stereo -*/ - - -/* -AUDIO_A EQU $FD20 -AUDIO_B EQU $FD28 -AUDIO_C EQU $FD30 -AUDIO_D EQU $FD38 - -VOLUME_CNTRL EQU 0 -FEEDBACK_ENABLE EQU 1 ; enables 11/10/5..0 -OUTPUT_VALUE EQU 2 -SHIFTER_L EQU 3 -AUD_BAKUP EQU 4 -AUD_CNTRL1 EQU 5 -AUD_COUNT EQU 6 -AUD_CNTRL2 EQU 7 - -; AUD_CNTRL1 -FEEDBACK_7 EQU %10000000 -AUD_RESETDONE EQU %01000000 -AUD_INTEGRATE EQU %00100000 -AUD_RELOAD EQU %00010000 -AUD_CNTEN EQU %00001000 -AUD_LINK EQU %00000111 -; link timers (0->2->4 / 1->3->5->7->Aud0->Aud1->Aud2->Aud3->1 -AUD_64us EQU %00000110 -AUD_32us EQU %00000101 -AUD_16us EQU %00000100 -AUD_8us EQU %00000011 -AUD_4us EQU %00000010 -AUD_2us EQU %00000001 -AUD_1us EQU %00000000 - -; AUD_CNTRL2 (read only) -; B7..B4 ; shifter bits 11..8 -; B3 ; who knows -; B2 ; last clock state (0->1 causes count) -; B1 ; borrow in (1 causes count) -; B0 ; borrow out (count EQU 0 and borrow in) - -ATTEN_A EQU $FD40 -ATTEN_B EQU $FD41 -ATTEN_C EQU $FD42 -ATTEN_D EQU $FD43 -; B7..B4 attenuation left ear (0 silent ..15/16 volume) -; B3..B0 " right ear - -MPAN EQU $FD44 -; B7..B4 left ear -; B3..B0 right ear -; B7/B3 EQU Audio D -; a 1 enables attenuation for channel and side - - -MSTEREO EQU $FD50 ; a 1 disables audio connection -AUD_D_LEFT EQU %10000000 -AUD_C_LEFT EQU %01000000 -AUD_B_LEFT EQU %00100000 -AUD_A_LEFT EQU %00010000 -AUD_D_RIGHT EQU %00001000 -AUD_C_RIGHT EQU %00000100 -AUD_B_RIGHT EQU %00000010 -AUD_A_RIGHT EQU %00000001 - - */ - -#define LYNX_AUDIO_CHANNELS 4 - - -// device type definition -const device_type LYNX_SND = &device_creator<lynx_sound_device>; -const device_type LYNX2_SND = &device_creator<lynx2_sound_device>; - -//************************************************************************** -// LIVE DEVICE -//************************************************************************** - -//------------------------------------------------- -// lynx_sound_device - constructor -//------------------------------------------------- - -lynx_sound_device::lynx_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) - : device_t(mconfig, LYNX_SND, "Mikey", tag, owner, clock, "lynx_sound", __FILE__), - device_sound_interface(mconfig, *this) -{ - m_timer_delegate = lynx_sound_timer_delegate(); -} - -lynx_sound_device::lynx_sound_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source) - : device_t(mconfig, type, name, tag, owner, clock, shortname, source), - device_sound_interface(mconfig, *this) -{ -} - - -lynx2_sound_device::lynx2_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) - : lynx_sound_device(mconfig, LYNX2_SND, "Mikey (Lynx II)", tag, owner, clock, "lynx2_sound", __FILE__) -{ -} - -//------------------------------------------------- -// device_config_complete - perform any -// operations now that the configuration is -// complete -//------------------------------------------------- - -void lynx_sound_device::set_timer_delegate(device_t &device, lynx_sound_timer_delegate cb) -{ - lynx_sound_device &dev = downcast<lynx_sound_device &>(device); - dev.m_timer_delegate = cb; -} - -void lynx_sound_device::device_config_complete() -{ -} - -//------------------------------------------------- -// device_start - device-specific startup -//------------------------------------------------- - -void lynx_sound_device::register_save() -{ - save_item(NAME(m_attenuation_enable)); - save_item(NAME(m_master_enable)); - for (int chan = 0; chan < LYNX_AUDIO_CHANNELS; chan++) - { - save_item(NAME(m_audio[chan].reg.volume), chan); - save_item(NAME(m_audio[chan].reg.feedback), chan); - save_item(NAME(m_audio[chan].reg.output), chan); - save_item(NAME(m_audio[chan].reg.shifter), chan); - save_item(NAME(m_audio[chan].reg.bakup), chan); - save_item(NAME(m_audio[chan].reg.control1), chan); - save_item(NAME(m_audio[chan].reg.counter), chan); - save_item(NAME(m_audio[chan].reg.control2), chan); - save_item(NAME(m_audio[chan].attenuation), chan); - save_item(NAME(m_audio[chan].mask), chan); - save_item(NAME(m_audio[chan].shifter), chan); - save_item(NAME(m_audio[chan].ticks), chan); - save_item(NAME(m_audio[chan].count), chan); - } -} - -void lynx_sound_device::init() -{ - m_shift_mask = auto_alloc_array_clear(machine(), int, 512); - m_shift_xor = auto_alloc_array_clear(machine(), int, 4096); - - for (int i = 0; i < 512; i++) - { - m_shift_mask[i] = 0; - if (i & 1) m_shift_mask[i] |= 1; - if (i & 2) m_shift_mask[i] |= 2; - if (i & 4) m_shift_mask[i] |= 4; - if (i & 8) m_shift_mask[i] |= 8; - if (i & 0x10) m_shift_mask[i] |= 0x10; - if (i & 0x20) m_shift_mask[i] |= 0x20; - if (i & 0x40) m_shift_mask[i] |= 0x400; - if (i & 0x80) m_shift_mask[i] |= 0x800; - if (i & 0x100) m_shift_mask[i] |= 0x80; - } - - for (int i = 0; i < 4096; i++) - { - m_shift_xor[i] = 1; - for (int j = 4096/2; j > 0; j >>= 1) - { - if (i & j) - m_shift_xor[i] ^= 1; - } - } -} - -void lynx_sound_device::device_start() -{ - m_mixer_channel = machine().sound().stream_alloc(*this, 0, 1, machine().sample_rate()); - m_usec_per_sample = 1000000 / machine().sample_rate(); - m_timer_delegate.bind_relative_to(*owner()); - init(); - register_save(); -} - - -void lynx2_sound_device::device_start() -{ - m_mixer_channel = machine().sound().stream_alloc(*this, 0, 2, machine().sample_rate()); - m_usec_per_sample = 1000000 / machine().sample_rate(); - m_timer_delegate.bind_relative_to(*owner()); - init(); - register_save(); -} - -//------------------------------------------------- -// device_reset - device-specific reset -//------------------------------------------------- - -void lynx_sound_device::device_reset() -{ - for (int i = 0; i < LYNX_AUDIO_CHANNELS; i++) - { - reset_channel(&m_audio[i]); - } -} - - -void lynx_sound_device::reset_channel(LYNX_AUDIO *channel) -{ - channel->reg.volume = 0; - channel->reg.feedback = 0; - channel->reg.output = 0; - channel->reg.shifter = 0; - channel->reg.bakup = 0; - channel->reg.control1 = 0; - channel->reg.counter = 0; - channel->reg.control2 = 0; - - channel->attenuation = 0; - channel->mask = 0; - channel->shifter = 0; - channel->ticks = 0; - channel->count = 0; -} - -void lynx_sound_device::count_down(int nr) -{ - LYNX_AUDIO *channel = &m_audio[nr]; - if (channel->reg.control1 & 8 && (channel->reg.control1 & 7) != 7) - return; - if (nr == 0) - m_mixer_channel->update(); - //if ((channel->reg.control1 & 0x0f) == 0x0f) //count down if linking enabled and count enabled - channel->count--; -} - -void lynx_sound_device::shift(int chan_nr) -{ - INT16 out_temp; - LYNX_AUDIO *channel; - - assert(chan_nr < 4); - - channel = &m_audio[chan_nr]; - //channel->shifter = ((channel->shifter<<1)&0xffe) | (m_shift_xor[ channel->shifter & channel->mask ]&1); - - // alternative method (functionally the same as above) - UINT8 xor_out = 0; - for (int bit = 0; bit < 12; bit++) - { - if ((channel->mask >> bit) & 1) - xor_out ^= (channel->shifter >> bit) & 1; - } - channel->shifter = ((channel->shifter << 1) & 0xffe) | (xor_out ^ 1); // output of xor is inverted - - - if (channel->reg.control1 & 0x20) // integrate mode enabled - { - if (channel->shifter & 1) - out_temp = channel->reg.output + channel->reg.volume; - else - out_temp = channel->reg.output - channel->reg.volume; - - // clipping - if (out_temp > 127) out_temp = 127; - if (out_temp < -128) out_temp = -128; - channel->reg.output = (INT16)out_temp; - } - - switch (chan_nr) - { - case 0: count_down(1); break; - case 1: count_down(2); break; - case 2: count_down(3); break; - case 3: - if (!m_timer_delegate.isnull()) - m_timer_delegate(); - break; - } -} - -void lynx_sound_device::execute(int chan_nr) -{ - LYNX_AUDIO *channel; - - assert(chan_nr < 4); - - channel = &m_audio[chan_nr]; - - if (channel->reg.control1 & 8) // count enable - { - channel->ticks += m_usec_per_sample; - if ((channel->reg.control1 & 7) == 7) // link - { - if (channel->count < 0) // counter finished - { - //channel->count+=channel->reg.counter; // reload (wrong?) - if (channel->reg.control1 & 0x10) - channel->count = channel->reg.bakup; - shift(chan_nr); - } - } - else - { - int t = 1 << (channel->reg.control1 & 7); // microseconds per count - for (;;) - { - for (; (channel->ticks >= t) && (channel->count >= 0); channel->ticks -= t) // at least one sampled worth of time left, timer not expired - channel->count--; - - if (channel->ticks < t) - break; - - if (channel->count < 0) - { - shift(chan_nr); - if (channel->reg.control1 & 0x10) - channel->count = channel->reg.bakup; - else - break; - } - } - } - - if (!(channel->reg.control1 & 0x20)) // normal mode - { - channel->reg.output = (channel->shifter & 1) ? channel->reg.volume : -channel->reg.volume; - } - } - else - { - channel->ticks = 0; - channel->count = 0; - } -} - -READ8_MEMBER(lynx_sound_device::read) -{ - UINT8 value = 0; - LYNX_AUDIO *channel = &m_audio[(offset >> 3) & 3]; - - m_mixer_channel->update(); - - if (offset < 0x40) - { - switch (offset & 7) - { - case 0: - value = channel->reg.volume; - break; - case 1: - value = channel->reg.feedback; - break; - case 2: - value = channel->reg.output; - break; - case 3: - // current shifter state (lower 8 bits) - value = channel->shifter & 0xff; - break; - case 4: - value = channel->reg.bakup; - break; - case 5: - value = channel->reg.control1; - break; - case 6: - //current timer value - if (channel->count >=0) - value = channel->count; - else - value = 0; - break; - case 7: - // current shifter state (upper 4 bits), status bits - value = (channel->shifter >> 4) & 0xf0; - value |= channel->reg.control2 & 0x0f; - break; - } - } - else - { - switch (offset) // Lynx II stereo control registers - { - case 0x40: case 0x41: case 0x42: case 0x43: - value = m_audio[offset & 3].attenuation; - break; - case 0x44: - value = m_attenuation_enable; - break; - case 0x50: - value = m_master_enable; - break; - } - - } - return value; -} - -WRITE8_MEMBER(lynx_sound_device::write) -{ - //logerror("audio write %.2x %.2x\n", offset, data); - LYNX_AUDIO *channel = &m_audio[(offset >> 3) & 3]; - - m_mixer_channel->update(); - - if (offset < 0x40) - { - switch (offset & 0x07) - { - // Volume control (signed) - case 0: - channel->reg.volume = data; - //logerror("write to volume %d\n", data); - break; - // Shift register feedback enable bits 0-5, 11,10 - case 1: - channel->reg.feedback = data; - channel->mask &= 0x80; - channel->mask |= (data & 0x3f) | ((data & 0xc0)<<4); - break; - // Output value - case 2: - channel->reg.output = data; - //logerror("write to output %d\n", data); - break; - // Lower 8 bits of shift register - case 3: - channel->shifter &= 0xf00; - channel->shifter |= data; - break; - // Audio timer backup value - case 4: - channel->reg.bakup = data; - break; - // Audio control bits - case 5: - channel->mask &= ~0x80; - channel->mask |= (data&0x80); - channel->reg.control1 = data; - break; - // Current count - case 6: - channel->count=data; - break; - // Upper 4 bits of shift register and audio status bits - case 7: - channel->shifter&=0xff; - channel->shifter|=(data&0xf0)<<4; - channel->reg.control2 = data; - break; - } - } - else - { - switch (offset) // Stereo Registers - { - case 0x40: case 0x41: case 0x42: case 0x43: - m_audio[offset&3].attenuation = data; - break; - case 0x44: - m_attenuation_enable = data; - break; - case 0x50: - m_master_enable = data; - break; - } - } -} - - -//------------------------------------------------- -// sound_stream_update - handle a stream update -//------------------------------------------------- - -void lynx_sound_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) -{ - int v; - stream_sample_t *buffer = outputs[0]; - - for (int i = 0; i < samples; i++, buffer++) - { - *buffer = 0; - for (int channel = 0; channel < LYNX_AUDIO_CHANNELS; channel++) - { - execute(channel); - v = m_audio[channel].reg.output; - *buffer += v * 15; // where does the *15 come from? - } - } -} - -//------------------------------------------------- -// sound_stream_update - handle a stream update -//------------------------------------------------- - -void lynx2_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 v; - - for (int i = 0; i < samples; i++, left++, right++) - { - *left = 0; - *right= 0; - for (int channel = 0; channel < LYNX_AUDIO_CHANNELS; channel++) - { - execute(channel); - v = m_audio[channel].reg.output; - if (!(m_master_enable & (0x10 << channel))) - { - if (m_attenuation_enable & (0x10 << channel)) - *left += v * (m_audio[channel].attenuation >> 4); - else - *left += v * 15; - } - if (!(m_master_enable & (1 << channel))) - { - if (m_attenuation_enable & (1 << channel)) - *right += v * (m_audio[channel].attenuation & 0xf); - else - *right += v * 15; - } - } - } -} |