diff options
Diffstat (limited to 'src/devices/sound')
-rw-r--r-- | src/devices/sound/cdp1869.cpp | 1 | ||||
-rw-r--r-- | src/devices/sound/mpeg_audio.cpp | 11 | ||||
-rw-r--r-- | src/devices/sound/mpeg_audio.h | 1 | ||||
-rw-r--r-- | src/devices/sound/okim6295.cpp | 5 | ||||
-rw-r--r-- | src/devices/sound/wave.cpp | 6 | ||||
-rw-r--r-- | src/devices/sound/ymz770.cpp | 406 | ||||
-rw-r--r-- | src/devices/sound/ymz770.h | 66 |
7 files changed, 363 insertions, 133 deletions
diff --git a/src/devices/sound/cdp1869.cpp b/src/devices/sound/cdp1869.cpp index 2a352d01bd8..fa9cdff2d84 100644 --- a/src/devices/sound/cdp1869.cpp +++ b/src/devices/sound/cdp1869.cpp @@ -12,7 +12,6 @@ - white noise - scanline based update - - CMSEL output */ diff --git a/src/devices/sound/mpeg_audio.cpp b/src/devices/sound/mpeg_audio.cpp index 26433ae73e9..0aa9c3192c6 100644 --- a/src/devices/sound/mpeg_audio.cpp +++ b/src/devices/sound/mpeg_audio.cpp @@ -16,6 +16,11 @@ mpeg_audio::mpeg_audio(const void *_base, unsigned int _accepted, bool lsb_first do_gb = lsb_first ? do_gb_lsb : do_gb_msb; position_align = _position_align ? _position_align - 1 : 0; + for (int i = 0; i < 32; i++) { + for (int j = 0; j < 32; j++) + m_cos_cache[i][j] = cos(i*(2 * j + 1)*M_PI / 64); + } + clear(); } @@ -722,10 +727,10 @@ void mpeg_audio::retrieve_subbuffer(int step) void mpeg_audio::idct32(const double *input, double *output) { // Simplest idct32 ever, non-fast at all - for(int i=0; i<32; i++) { + for (int i = 0; i < 32; i++) { double s = 0; - for(int j=0; j<32; j++) - s += input[j] * cos(i*(2*j+1)*M_PI/64); + for (int j = 0; j < 32; j++) + s += input[j] * m_cos_cache[i][j]; output[i] = s; } } diff --git a/src/devices/sound/mpeg_audio.h b/src/devices/sound/mpeg_audio.h index 4641dd9beb0..53738671c16 100644 --- a/src/devices/sound/mpeg_audio.h +++ b/src/devices/sound/mpeg_audio.h @@ -92,6 +92,7 @@ private: double subbuffer[2][32]; double audio_buffer[2][32*32]; int audio_buffer_pos[2]; + double m_cos_cache[32][32]; int current_pos, current_limit; diff --git a/src/devices/sound/okim6295.cpp b/src/devices/sound/okim6295.cpp index 78bf872af3d..4b089eb00a6 100644 --- a/src/devices/sound/okim6295.cpp +++ b/src/devices/sound/okim6295.cpp @@ -35,6 +35,11 @@ ???? abcd = one bit per voice, set to 0 if nothing is playing, or 1 if it is active + OKI Semiconductor produced this chip in two package variants. The + 44-pin QFP version, MSM6295GS, is the original one and by far the more + common of the two. The 42-pin DIP version, MSM6295VRS, omits A17 and + RD, which limits its ROM addressing to one megabit instead of two. + ***************************************************************************/ #include "emu.h" diff --git a/src/devices/sound/wave.cpp b/src/devices/sound/wave.cpp index 7383805d05e..810f537e51d 100644 --- a/src/devices/sound/wave.cpp +++ b/src/devices/sound/wave.cpp @@ -47,13 +47,13 @@ wave_device::wave_device(const machine_config &mconfig, const char *tag, device_ void wave_device::device_start() { - speaker_device_iterator spkiter(machine().root_device()); + speaker_device_iterator spkiter(*owner()); int speakers = spkiter.count(); if (speakers > 1) machine().sound().stream_alloc(*this, 0, 2, machine().sample_rate()); else machine().sound().stream_alloc(*this, 0, 1, machine().sample_rate()); - m_cass = machine().device<cassette_image_device>(m_cassette_tag); + m_cass = owner()->subdevice<cassette_image_device>(m_cassette_tag); } //------------------------------------------------- @@ -69,7 +69,7 @@ void wave_device::sound_stream_update(sound_stream &stream, stream_sample_t **in stream_sample_t *right_buffer = nullptr; int i; - speaker_device_iterator spkiter(m_cass->machine().root_device()); + speaker_device_iterator spkiter(*owner()); int speakers = spkiter.count(); if (speakers>1) right_buffer = outputs[1]; diff --git a/src/devices/sound/ymz770.cpp b/src/devices/sound/ymz770.cpp index 11b30d08eb1..c7a7a91a114 100644 --- a/src/devices/sound/ymz770.cpp +++ b/src/devices/sound/ymz770.cpp @@ -1,21 +1,23 @@ // license:BSD-3-Clause -// copyright-holders:Olivier Galibert, R. Belmont +// copyright-holders:Olivier Galibert, R. Belmont, MetalliC /*************************************************************************** - ymz770.c + Yamaha YMZ770C and YMZ774 - Emulation by R. Belmont + Emulation by R. Belmont and MetalliC AMM decode by Olivier Galibert ----- TODO: -- A lot of unimplemented features, even simple ones like panning, - these should be added once we find out any software that uses it. -- Is channel volume linear(current implementation) or logarithmic? -- Sequencer is very preliminary - What does channel ATBL mean? -- Is YMZ774(and other variants) the same family as this chip? - What are the differences? + 770: +- verify if pan 100% correct +- sequencer timers and triggers not implemented (seems used in Deathsmiles ending tune) + 774: +- find out how volume/pan delayed transition works (used few times in orleg2 attract mode) +- 4 channel output +- Equalizer +- Sequencer (not used) ***************************************************************************/ @@ -24,20 +26,28 @@ TODO: #include "mpeg_audio.h" // device type definition -DEFINE_DEVICE_TYPE(YMZ770, ymz770_device, "ymz770", "Yamaha YMZ770 AMMS-A") +DEFINE_DEVICE_TYPE(YMZ770, ymz770_device, "ymz770", "Yamaha YMZ770C-F AMMS-A") +DEFINE_DEVICE_TYPE(YMZ774, ymz774_device, "ymz774", "Yamaha YMZ774-S AMMS2") //------------------------------------------------- // ymz770_device - constructor //------------------------------------------------- ymz770_device::ymz770_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : device_t(mconfig, YMZ770, tag, owner, clock) + : ymz770_device(mconfig, YMZ770, tag, owner, clock, 16000) +{ +} + +ymz770_device::ymz770_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, uint32_t sclock) + : device_t(mconfig, type, tag, owner, clock) , device_sound_interface(mconfig, *this) , m_stream(nullptr) + , m_sclock(sclock) , m_cur_reg(0) , m_mute(0) , m_doen(0) , m_vlma(0) + , m_vlma1(0) , m_bsl(0) , m_cpl(0) , m_rom(*this, DEVICE_SELF) @@ -52,41 +62,51 @@ ymz770_device::ymz770_device(const machine_config &mconfig, const char *tag, dev void ymz770_device::device_start() { // create the stream - m_stream = machine().sound().stream_alloc(*this, 0, 2, 16000); + m_stream = machine().sound().stream_alloc(*this, 0, 2, m_sclock); - for (auto & elem : m_channels) + for (auto & channel : m_channels) { - elem.is_playing = false; - elem.is_seq_playing = false; - elem.decoder = new mpeg_audio(&m_rom[0], mpeg_audio::AMM, false, 0); + channel.is_playing = false; + channel.decoder = new mpeg_audio(&m_rom[0], mpeg_audio::AMM, false, 0); } + for (auto & sequence : m_sequences) + sequence.is_playing = false; // register for save states save_item(NAME(m_cur_reg)); save_item(NAME(m_mute)); save_item(NAME(m_doen)); save_item(NAME(m_vlma)); + save_item(NAME(m_vlma1)); save_item(NAME(m_bsl)); save_item(NAME(m_cpl)); - for (int ch = 0; ch < 8; ch++) + for (int ch = 0; ch < 16; ch++) // TODO array size { save_item(NAME(m_channels[ch].phrase), ch); save_item(NAME(m_channels[ch].pan), ch); + save_item(NAME(m_channels[ch].pan_delay), ch); + save_item(NAME(m_channels[ch].pan1), ch); + save_item(NAME(m_channels[ch].pan1_delay), ch); save_item(NAME(m_channels[ch].volume), ch); - save_item(NAME(m_channels[ch].control), ch); + save_item(NAME(m_channels[ch].volume_delay), ch); + save_item(NAME(m_channels[ch].volume2), ch); + save_item(NAME(m_channels[ch].loop), ch); save_item(NAME(m_channels[ch].is_playing), ch); save_item(NAME(m_channels[ch].last_block), ch); save_item(NAME(m_channels[ch].output_remaining), ch); save_item(NAME(m_channels[ch].output_ptr), ch); save_item(NAME(m_channels[ch].atbl), ch); save_item(NAME(m_channels[ch].pptr), ch); - save_item(NAME(m_channels[ch].sequence), ch); - save_item(NAME(m_channels[ch].seqcontrol), ch); - save_item(NAME(m_channels[ch].seqdelay), ch); - save_item(NAME(m_channels[ch].is_seq_playing), ch); save_item(NAME(m_channels[ch].output_data), ch); } + for (int ch = 0; ch < 8; ch++) + { + save_item(NAME(m_sequences[ch].sequence), ch); + save_item(NAME(m_sequences[ch].control), ch); + save_item(NAME(m_sequences[ch].delay), ch); + save_item(NAME(m_sequences[ch].is_playing), ch); + } } @@ -96,19 +116,27 @@ void ymz770_device::device_start() void ymz770_device::device_reset() { - for (auto & elem : m_channels) + for (auto & channel : m_channels) { - elem.phrase = 0; - elem.pan = 8; - elem.volume = 0; - elem.control = 0; - elem.sequence = 0; - elem.seqcontrol = 0; - elem.seqdelay = 0; - elem.is_playing = false; - elem.is_seq_playing = false; - elem.output_remaining = 0; - elem.decoder->clear(); + channel.phrase = 0; + channel.pan = 64; + channel.pan_delay = 0; + channel.pan1 = 64; + channel.pan1_delay = 0; + channel.volume = 0; + channel.volume_delay = 0; + channel.volume2 = 0; + channel.loop = 0; + channel.is_playing = false; + channel.output_remaining = 0; + channel.decoder->clear(); + } + for (auto & sequence : m_sequences) + { + sequence.sequence = 0; + sequence.control = 0; + sequence.delay = 0; + sequence.is_playing = false; } } @@ -127,105 +155,142 @@ void ymz770_device::sound_stream_update(sound_stream &stream, stream_sample_t ** for (int i = 0; i < samples; i++) { - // run sequencers (should probably be in separate timer callbacks) - for (auto & elem : m_channels) - { - if (elem.is_seq_playing) - { - if (elem.seqdelay > 0) - { - elem.seqdelay--; - } - else - { - int reg = *elem.seqdata++; - uint8_t data = *elem.seqdata++; - switch (reg) - { - case 0x0f: - if (elem.seqcontrol & 1) - { - // loop sequence - uint8_t sqn = elem.sequence; - uint32_t pptr = m_rom[(4*sqn)+1+0x400]<<16 | m_rom[(4*sqn)+2+0x400]<<8 | m_rom[(4*sqn)+3+0x400]; - elem.seqdata = &m_rom[pptr]; - } - else - { - elem.is_seq_playing = false; - } - break; - case 0x0e: - elem.seqdelay = 32 - 1; - break; - default: - internal_reg_write(reg, data); - break; - } - } - } - } + sequencer(); // process channels - int32_t mix = 0; + int32_t mixl = 0; + int32_t mixr = 0; - for (auto & elem : m_channels) + for (auto & channel : m_channels) { - if (elem.output_remaining > 0) + if (channel.output_remaining > 0) { // force finish current block - mix += (elem.output_data[elem.output_ptr++]*elem.volume); - elem.output_remaining--; - - if (elem.output_remaining == 0 && !elem.is_playing) - elem.decoder->clear(); + int32_t smpl = (channel.output_data[channel.output_ptr++] * channel.volume) >> 7; // volume is linear, 0 - 128 (100%) + smpl = (smpl * channel.volume2) >> 7; + mixr += (smpl * channel.pan) >> 7; // pan seems linear, 0 - 128, where 0 = 100% left, 128 = 100% right, 64 = 50% left 50% right + mixl += (smpl * (128 - channel.pan)) >> 7; + channel.output_remaining--; + + if (channel.output_remaining == 0 && !channel.is_playing) + channel.decoder->clear(); } - else if (elem.is_playing) + else if (channel.is_playing) { retry: - if (elem.last_block) + if (channel.last_block) { - if (elem.control & 1) + if (channel.loop) { + if (channel.loop != 255) + --channel.loop; // loop sample - uint8_t phrase = elem.phrase; - elem.atbl = m_rom[(4*phrase)+0] >> 4 & 7; - elem.pptr = 8*(m_rom[(4*phrase)+1]<<16 | m_rom[(4*phrase)+2]<<8 | m_rom[(4*phrase)+3]); + int phrase = channel.phrase; + channel.atbl = m_rom[(4*phrase)+0] >> 4 & 7; + channel.pptr = 8 * get_phrase_offs(phrase); } else { - elem.is_playing = false; - elem.output_remaining = 0; - elem.decoder->clear(); + channel.is_playing = false; + channel.output_remaining = 0; + channel.decoder->clear(); } } - if (elem.is_playing) + if (channel.is_playing) { // next block int sample_rate, channel_count; - if (!elem.decoder->decode_buffer(elem.pptr, m_rom.bytes()*8, elem.output_data, elem.output_remaining, sample_rate, channel_count) || elem.output_remaining == 0) + if (!channel.decoder->decode_buffer(channel.pptr, m_rom.bytes()*8, channel.output_data, channel.output_remaining, sample_rate, channel_count) || channel.output_remaining == 0) { - elem.is_playing = !elem.last_block; // detect infinite retry loop - elem.last_block = true; - elem.output_remaining = 0; + channel.is_playing = !channel.last_block; // detect infinite retry loop + channel.last_block = true; + channel.output_remaining = 0; goto retry; } - elem.last_block = elem.output_remaining < 1152; - elem.output_remaining--; - elem.output_ptr = 1; + channel.last_block = channel.output_remaining < 1152; + channel.output_remaining--; + channel.output_ptr = 1; - mix += (elem.output_data[0]*elem.volume); + int32_t smpl = (channel.output_data[0] * channel.volume) >> 7; + smpl = (smpl * channel.volume2) >> 7; + mixr += (smpl * channel.pan) >> 7; + mixl += (smpl * (128 - channel.pan)) >> 7; } } } - outL[i] = outR[i] = mix>>8; + mixr *= m_vlma; // main volume is linear, 0 - 255, where 128 = 100% + mixl *= m_vlma; + mixr >>= 7 - m_bsl; + mixl >>= 7 - m_bsl; + // Clip limiter: 0 - off, 1 - 6.02 dB (100%), 2 - 4.86 dB (87.5%), 3 - 3.52 dB (75%). values taken from YMZ773 docs, might be incorrect for YMZ770. + constexpr int32_t ClipMax3 = 32768 * 75 / 100; + constexpr int32_t ClipMax2 = 32768 * 875 / 1000; + switch (m_cpl) + { + case 3: + mixl = (mixl > ClipMax3) ? ClipMax3 : (mixl < -ClipMax3) ? -ClipMax3 : mixl; + mixr = (mixr > ClipMax3) ? ClipMax3 : (mixr < -ClipMax3) ? -ClipMax3 : mixr; + break; + case 2: + mixl = (mixl > ClipMax2) ? ClipMax2 : (mixl < -ClipMax2) ? -ClipMax2 : mixl; + mixr = (mixr > ClipMax2) ? ClipMax2 : (mixr < -ClipMax2) ? -ClipMax2 : mixr; + break; + case 1: + mixl = (mixl > 32767) ? 32767 : (mixl < -32768) ? -32768 : mixl; + mixr = (mixr > 32767) ? 32767 : (mixr < -32768) ? -32768 : mixr; + break; + } + if (m_mute) + mixr = mixl = 0; + outL[i] = mixl; + outR[i] = mixr; } } +void ymz770_device::sequencer() +{ + for (auto & sequence : m_sequences) + { + if (sequence.is_playing) + { + if (sequence.delay > 0) + { + sequence.delay--; + } + else + { + int reg = *sequence.data++; + uint8_t data = *sequence.data++; + switch (reg) + { + case 0x0f: + if (sequence.control & 1) + { + // loop sequence + uint8_t sqn = sequence.sequence; + uint32_t pptr = get_seq_offs(sqn); + sequence.data = &m_rom[pptr]; + } + else + { + sequence.is_playing = false; + } + break; + case 0x0e: + sequence.delay = 32 - 1; + break; + default: + internal_reg_write(reg, data); + break; + } + } + } + } +} //------------------------------------------------- // write - write to the chip's registers @@ -285,10 +350,11 @@ void ymz770_device::internal_reg_write(uint8_t reg, uint8_t data) case 1: m_channels[ch].volume = data; + m_channels[ch].volume2 = 128; break; case 2: - m_channels[ch].pan = data; + m_channels[ch].pan = data << 3; break; case 3: @@ -296,7 +362,7 @@ void ymz770_device::internal_reg_write(uint8_t reg, uint8_t data) { uint8_t phrase = m_channels[ch].phrase; m_channels[ch].atbl = m_rom[(4*phrase)+0] >> 4 & 7; - m_channels[ch].pptr = 8*(m_rom[(4*phrase)+1]<<16 | m_rom[(4*phrase)+2]<<8 | m_rom[(4*phrase)+3]); + m_channels[ch].pptr = 8 * get_phrase_offs(phrase); m_channels[ch].last_block = false; m_channels[ch].is_playing = true; @@ -306,7 +372,7 @@ void ymz770_device::internal_reg_write(uint8_t reg, uint8_t data) m_channels[ch].is_playing = false; } - m_channels[ch].control = data; + m_channels[ch].loop = (data & 1) ? 255 : 0; break; } } @@ -319,23 +385,23 @@ void ymz770_device::internal_reg_write(uint8_t reg, uint8_t data) switch (reg & 0x0f) { case 0: - m_channels[ch].sequence = data; + m_sequences[ch].sequence = data; break; case 1: if (data & 6) { - uint8_t sqn = m_channels[ch].sequence; - uint32_t pptr = m_rom[(4*sqn)+1+0x400]<<16 | m_rom[(4*sqn)+2+0x400]<<8 | m_rom[(4*sqn)+3+0x400]; - m_channels[ch].seqdata = &m_rom[pptr]; - m_channels[ch].seqdelay = 0; - m_channels[ch].is_seq_playing = true; + uint8_t sqn = m_sequences[ch].sequence; + uint32_t pptr = get_seq_offs(sqn); + m_sequences[ch].data = &m_rom[pptr]; + m_sequences[ch].delay = 0; + m_sequences[ch].is_playing = true; } else { - m_channels[ch].is_seq_playing = false; + m_sequences[ch].is_playing = false; } - m_channels[ch].seqcontrol = data; + m_sequences[ch].control = data; break; default: @@ -343,3 +409,123 @@ void ymz770_device::internal_reg_write(uint8_t reg, uint8_t data) } } } + +//------------------------------------------------- +// ymz774_device +//------------------------------------------------- + +ymz774_device::ymz774_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : ymz770_device(mconfig, YMZ774, tag, owner, clock, 44100) +{ +} + +READ8_MEMBER(ymz774_device::read) +{ + if (offset & 1) + { + if (m_cur_reg == 0xe3 || m_cur_reg == 0xe4) + { + m_stream->update(); + uint8_t res = 0; + int bank = (m_cur_reg == 0xe3) ? 8 : 0; + for (int i = 0; i < 8; i++) + if (m_channels[i + bank].is_playing) + res |= 1 << i; + return res; + } + } + logerror("unimplemented read %02X\n", m_cur_reg); + return 0; +} + +void ymz774_device::internal_reg_write(uint8_t reg, uint8_t data) +{ + // playback registers + if (reg < 0x10) // phrase num H and L + { + int ch = ((reg >> 1) & 7) + m_bank * 8; + if (reg & 1) + m_channels[ch].phrase = (m_channels[ch].phrase & 0xff00) | data; + else + m_channels[ch].phrase = (m_channels[ch].phrase & 0x00ff) | ((data & 7) << 8); + } + else if (reg < 0x60) + { + int ch = (reg & 7) + m_bank * 8; + switch (reg & 0xf8) + { + case 0x10: // Volume 1 + m_channels[ch].volume = data; + break; + case 0x18: // Volume 1 delayed transition + if (data) logerror("unimplemented write %02X %02X\n", reg, data); + m_channels[ch].volume_delay = data; + break; + case 0x20: // Volume 2 + m_channels[ch].volume2 = data; + break; + case 0x28: // Pan L/R + m_channels[ch].pan = data; + break; + case 0x30: // Pan L/R delayed transition + if (data) logerror("unimplemented write %02X %02X\n", reg, data); + m_channels[ch].pan_delay = data; + break; + case 0x38: // Pan T/B + m_channels[ch].pan1 = data; + break; + case 0x40: // Pan T/B delayed transition + if (data) logerror("unimplemented write %02X %02X\n", reg, data); + m_channels[ch].pan1_delay = data; + break; + case 0x48: // Loop + m_channels[ch].loop = data; + break; + case 0x50: // Start / Stop + if (data) + { + int phrase = m_channels[ch].phrase; + m_channels[ch].atbl = m_rom[(4 * phrase) + 0] >> 4 & 7; + m_channels[ch].pptr = 8 * get_phrase_offs(phrase); + m_channels[ch].last_block = false; + + m_channels[ch].is_playing = true; + } + else + { + m_channels[ch].is_playing = false; + } + break; + case 0x58: // Pause / Resume + if (data) logerror("pause/resume unimplemented %02X %02X\n", reg, data); + break; + } + } + else if (reg < 0xd0) + { + if (m_bank == 0) // Sequencer, in PGM2 games not used at all + { + if (data) logerror("sequencer unimplemented %02X %02X\n", reg, data); + } + // else bank1 - Equalizer control + } + // global registers + else + { + switch (reg) { + case 0xd0: + m_vlma = data; + break; + case 0xd1: + m_vlma1 = data; + break; + case 0xd2: + m_cpl = data; + break; + case 0xf0: + m_bank = data & 1; + if (data > 1) logerror("Set bank %02X!\n", data); + break; + } + } +} diff --git a/src/devices/sound/ymz770.h b/src/devices/sound/ymz770.h index b7f047dc4b4..03921759cf2 100644 --- a/src/devices/sound/ymz770.h +++ b/src/devices/sound/ymz770.h @@ -12,10 +12,6 @@ #pragma once //************************************************************************** -// CONSTANTS -//************************************************************************** - -//************************************************************************** // INTERFACE CONFIGURATION MACROS //************************************************************************** @@ -25,6 +21,12 @@ #define MCFG_YMZ770_REPLACE(_tag, _clock) \ MCFG_DEVICE_REPLACE(_tag, YMZ770, _clock) +#define MCFG_YMZ774_ADD(_tag, _clock) \ + MCFG_DEVICE_ADD(_tag, YMZ774, _clock) + +#define MCFG_YMZ774_REPLACE(_tag, _clock) \ + MCFG_DEVICE_REPLACE(_tag, YMZ774, _clock) + //************************************************************************** // TYPE DEFINITIONS //************************************************************************** @@ -49,26 +51,37 @@ protected: virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) override; - void internal_reg_write(uint8_t reg, uint8_t data); + virtual void internal_reg_write(uint8_t reg, uint8_t data); + virtual uint32_t get_phrase_offs(int phrase) { return m_rom[(4 * phrase) + 1] << 16 | m_rom[(4 * phrase) + 2] << 8 | m_rom[(4 * phrase) + 3]; }; + virtual uint32_t get_seq_offs(int sqn) { return m_rom[(4 * sqn) + 1 + 0x400] << 16 | m_rom[(4 * sqn) + 2 + 0x400] << 8 | m_rom[(4 * sqn) + 3 + 0x400]; }; + virtual void sequencer(); + + ymz770_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, uint32_t sclock); sound_stream *m_stream; + uint32_t m_sclock; // data uint8_t m_cur_reg; uint8_t m_mute; // mute chip uint8_t m_doen; // digital output enable - uint8_t m_vlma; // overall AAM volume + uint8_t m_vlma; // overall volume L0/R0 + uint8_t m_vlma1; // overall volume L1/R1 uint8_t m_bsl; // boost level uint8_t m_cpl; // clip limiter required_region_ptr<uint8_t> m_rom; -private: struct ymz_channel { - uint8_t phrase; + uint16_t phrase; uint8_t pan; + uint8_t pan_delay; + uint8_t pan1; + uint8_t pan1_delay; uint8_t volume; - uint8_t control; + uint8_t volume_delay; + uint8_t volume2; + uint8_t loop; bool is_playing, last_block; @@ -79,19 +92,40 @@ private: int output_ptr; int atbl; int pptr; - - uint8_t sequence; - uint8_t seqcontrol; - uint8_t seqdelay; - uint8_t *seqdata; - bool is_seq_playing; + }; + struct ymz_sequence + { + uint16_t sequence; + uint8_t control; + uint8_t delay; + uint8_t *data; + bool is_playing; }; - ymz_channel m_channels[8]; + ymz_channel m_channels[16]; + ymz_sequence m_sequences[8]; }; +// ======================> ymz774_device + +class ymz774_device : public ymz770_device +{ +public: + // construction/destruction + ymz774_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + DECLARE_READ8_MEMBER(read); +protected: + virtual void internal_reg_write(uint8_t reg, uint8_t data) override; + virtual uint32_t get_phrase_offs(int phrase) override { int ph = phrase * 4; return ((m_rom[ph] & 0x0f) << 24 | m_rom[ph + 1] << 16 | m_rom[ph + 2] << 8 | m_rom[ph + 3]) * 2; }; + virtual uint32_t get_seq_offs(int sqn) override { int sq = sqn * 4 + 0x2000; return ((m_rom[sq] & 0x0f) << 24 | m_rom[sq + 1] << 16 | m_rom[sq + 2] << 8 | m_rom[sq + 3]) * 2; }; + virtual void sequencer() override {}; +private: + int m_bank; +}; // device type definition DECLARE_DEVICE_TYPE(YMZ770, ymz770_device) +DECLARE_DEVICE_TYPE(YMZ774, ymz774_device) #endif // MAME_SOUND_YMZ770_H |