mirror of
https://github.com/holub/mame
synced 2025-07-05 18:08:04 +03:00
preliminary Yamaha YMZ774 emulation (nw)
This commit is contained in:
parent
d49ccf883e
commit
d724f49d42
@ -1,10 +1,10 @@
|
|||||||
// license:BSD-3-Clause
|
// license:BSD-3-Clause
|
||||||
// copyright-holders:Olivier Galibert, R. Belmont
|
// copyright-holders:Olivier Galibert, R. Belmont, MetalliC
|
||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
|
|
||||||
ymz770.c
|
ymz770.c
|
||||||
|
|
||||||
Emulation by R. Belmont
|
Emulation by R. Belmont and MetalliC
|
||||||
AMM decode by Olivier Galibert
|
AMM decode by Olivier Galibert
|
||||||
|
|
||||||
-----
|
-----
|
||||||
@ -24,16 +24,23 @@ TODO:
|
|||||||
#include "mpeg_audio.h"
|
#include "mpeg_audio.h"
|
||||||
|
|
||||||
// device type definition
|
// 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 - constructor
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
|
|
||||||
ymz770_device::ymz770_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
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)
|
, device_sound_interface(mconfig, *this)
|
||||||
, m_stream(nullptr)
|
, m_stream(nullptr)
|
||||||
|
, m_sclock(sclock)
|
||||||
, m_cur_reg(0)
|
, m_cur_reg(0)
|
||||||
, m_mute(0)
|
, m_mute(0)
|
||||||
, m_doen(0)
|
, m_doen(0)
|
||||||
@ -52,14 +59,15 @@ ymz770_device::ymz770_device(const machine_config &mconfig, const char *tag, dev
|
|||||||
void ymz770_device::device_start()
|
void ymz770_device::device_start()
|
||||||
{
|
{
|
||||||
// create the stream
|
// 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 & elem : m_channels)
|
||||||
{
|
{
|
||||||
elem.is_playing = false;
|
elem.is_playing = false;
|
||||||
elem.is_seq_playing = false;
|
|
||||||
elem.decoder = new mpeg_audio(&m_rom[0], mpeg_audio::AMM, false, 0);
|
elem.decoder = new mpeg_audio(&m_rom[0], mpeg_audio::AMM, false, 0);
|
||||||
}
|
}
|
||||||
|
for (auto & elem : m_sequences)
|
||||||
|
elem.is_seq_playing = false;
|
||||||
|
|
||||||
// register for save states
|
// register for save states
|
||||||
save_item(NAME(m_cur_reg));
|
save_item(NAME(m_cur_reg));
|
||||||
@ -69,24 +77,27 @@ void ymz770_device::device_start()
|
|||||||
save_item(NAME(m_bsl));
|
save_item(NAME(m_bsl));
|
||||||
save_item(NAME(m_cpl));
|
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].phrase), ch);
|
||||||
save_item(NAME(m_channels[ch].pan), ch);
|
save_item(NAME(m_channels[ch].pan), ch);
|
||||||
save_item(NAME(m_channels[ch].volume), ch);
|
save_item(NAME(m_channels[ch].volume), ch);
|
||||||
save_item(NAME(m_channels[ch].control), ch);
|
save_item(NAME(m_channels[ch].loop), ch);
|
||||||
save_item(NAME(m_channels[ch].is_playing), 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].last_block), ch);
|
||||||
save_item(NAME(m_channels[ch].output_remaining), 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].output_ptr), ch);
|
||||||
save_item(NAME(m_channels[ch].atbl), ch);
|
save_item(NAME(m_channels[ch].atbl), ch);
|
||||||
save_item(NAME(m_channels[ch].pptr), 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);
|
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].seqcontrol), ch);
|
||||||
|
save_item(NAME(m_sequences[ch].seqdelay), ch);
|
||||||
|
save_item(NAME(m_sequences[ch].is_seq_playing), ch);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -101,14 +112,17 @@ void ymz770_device::device_reset()
|
|||||||
elem.phrase = 0;
|
elem.phrase = 0;
|
||||||
elem.pan = 8;
|
elem.pan = 8;
|
||||||
elem.volume = 0;
|
elem.volume = 0;
|
||||||
elem.control = 0;
|
elem.loop = 0;
|
||||||
|
elem.is_playing = false;
|
||||||
|
elem.output_remaining = 0;
|
||||||
|
elem.decoder->clear();
|
||||||
|
}
|
||||||
|
for (auto & elem : m_sequences)
|
||||||
|
{
|
||||||
elem.sequence = 0;
|
elem.sequence = 0;
|
||||||
elem.seqcontrol = 0;
|
elem.seqcontrol = 0;
|
||||||
elem.seqdelay = 0;
|
elem.seqdelay = 0;
|
||||||
elem.is_playing = false;
|
|
||||||
elem.is_seq_playing = false;
|
elem.is_seq_playing = false;
|
||||||
elem.output_remaining = 0;
|
|
||||||
elem.decoder->clear();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,44 +141,7 @@ void ymz770_device::sound_stream_update(sound_stream &stream, stream_sample_t **
|
|||||||
|
|
||||||
for (int i = 0; i < samples; i++)
|
for (int i = 0; i < samples; i++)
|
||||||
{
|
{
|
||||||
// run sequencers (should probably be in separate timer callbacks)
|
sequencer();
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// process channels
|
// process channels
|
||||||
int32_t mixl = 0;
|
int32_t mixl = 0;
|
||||||
@ -176,8 +153,8 @@ void ymz770_device::sound_stream_update(sound_stream &stream, stream_sample_t **
|
|||||||
{
|
{
|
||||||
// force finish current block
|
// force finish current block
|
||||||
int32_t smpl = elem.output_data[elem.output_ptr++] * elem.volume; // volume is linear, 0 - 128 (100%)
|
int32_t smpl = elem.output_data[elem.output_ptr++] * elem.volume; // volume is linear, 0 - 128 (100%)
|
||||||
mixr += (smpl * elem.pan) >> 11; // pan seems linear, 0 - 16, where 0 = 100% left, 16 = 100% right, 8 = 50% left 50% right
|
mixr += (smpl * elem.pan) >> 14; // pan seems linear, 0 - 128, where 0 = 100% left, 128 = 100% right, 64 = 50% left 50% right
|
||||||
mixl += (smpl * (16 - elem.pan)) >> 11;
|
mixl += (smpl * (128 - elem.pan)) >> 14;
|
||||||
elem.output_remaining--;
|
elem.output_remaining--;
|
||||||
|
|
||||||
if (elem.output_remaining == 0 && !elem.is_playing)
|
if (elem.output_remaining == 0 && !elem.is_playing)
|
||||||
@ -189,12 +166,14 @@ void ymz770_device::sound_stream_update(sound_stream &stream, stream_sample_t **
|
|||||||
retry:
|
retry:
|
||||||
if (elem.last_block)
|
if (elem.last_block)
|
||||||
{
|
{
|
||||||
if (elem.control & 1)
|
if (elem.loop)
|
||||||
{
|
{
|
||||||
|
if (elem.loop != 255)
|
||||||
|
--elem.loop;
|
||||||
// loop sample
|
// loop sample
|
||||||
uint8_t phrase = elem.phrase;
|
int phrase = elem.phrase;
|
||||||
elem.atbl = m_rom[(4*phrase)+0] >> 4 & 7;
|
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]);
|
elem.pptr = 8 * get_phrase_offs(phrase);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -221,8 +200,8 @@ retry:
|
|||||||
elem.output_ptr = 1;
|
elem.output_ptr = 1;
|
||||||
|
|
||||||
int32_t smpl = elem.output_data[0] * elem.volume;
|
int32_t smpl = elem.output_data[0] * elem.volume;
|
||||||
mixr += (smpl * elem.pan) >> 11;
|
mixr += (smpl * elem.pan) >> 14;
|
||||||
mixl += (smpl * (16 - elem.pan)) >> 11;
|
mixl += (smpl * (128 - elem.pan)) >> 14;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -256,6 +235,46 @@ retry:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ymz770_device::sequencer()
|
||||||
|
{
|
||||||
|
for (auto & elem : m_sequences)
|
||||||
|
{
|
||||||
|
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 = get_seq_offs(sqn);
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
// write - write to the chip's registers
|
// write - write to the chip's registers
|
||||||
@ -318,7 +337,7 @@ void ymz770_device::internal_reg_write(uint8_t reg, uint8_t data)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
m_channels[ch].pan = data;
|
m_channels[ch].pan = (data & 0x1f) << 3;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 3:
|
case 3:
|
||||||
@ -326,7 +345,7 @@ void ymz770_device::internal_reg_write(uint8_t reg, uint8_t data)
|
|||||||
{
|
{
|
||||||
uint8_t phrase = m_channels[ch].phrase;
|
uint8_t phrase = m_channels[ch].phrase;
|
||||||
m_channels[ch].atbl = m_rom[(4*phrase)+0] >> 4 & 7;
|
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].last_block = false;
|
||||||
|
|
||||||
m_channels[ch].is_playing = true;
|
m_channels[ch].is_playing = true;
|
||||||
@ -336,7 +355,7 @@ void ymz770_device::internal_reg_write(uint8_t reg, uint8_t data)
|
|||||||
m_channels[ch].is_playing = false;
|
m_channels[ch].is_playing = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_channels[ch].control = data;
|
m_channels[ch].loop = (data & 1) ? 255 : 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -349,23 +368,23 @@ void ymz770_device::internal_reg_write(uint8_t reg, uint8_t data)
|
|||||||
switch (reg & 0x0f)
|
switch (reg & 0x0f)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
m_channels[ch].sequence = data;
|
m_sequences[ch].sequence = data;
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
if (data & 6)
|
if (data & 6)
|
||||||
{
|
{
|
||||||
uint8_t sqn = m_channels[ch].sequence;
|
uint8_t sqn = m_sequences[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];
|
uint32_t pptr = get_seq_offs(sqn);
|
||||||
m_channels[ch].seqdata = &m_rom[pptr];
|
m_sequences[ch].seqdata = &m_rom[pptr];
|
||||||
m_channels[ch].seqdelay = 0;
|
m_sequences[ch].seqdelay = 0;
|
||||||
m_channels[ch].is_seq_playing = true;
|
m_sequences[ch].is_seq_playing = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_channels[ch].is_seq_playing = false;
|
m_sequences[ch].is_seq_playing = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_channels[ch].seqcontrol = data;
|
m_sequences[ch].seqcontrol = data;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -373,3 +392,76 @@ 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)
|
||||||
|
{
|
||||||
|
// TODO status read ?
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ymz774_device::internal_reg_write(uint8_t reg, uint8_t data)
|
||||||
|
{
|
||||||
|
// playback registers
|
||||||
|
if (reg < 0x60) {
|
||||||
|
int ch = (reg & 7) + m_bank * 8;
|
||||||
|
switch (reg & 0xf8)
|
||||||
|
{
|
||||||
|
case 0x00: // phrase# H and L
|
||||||
|
case 0x08:
|
||||||
|
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 << 8);
|
||||||
|
break;
|
||||||
|
case 0x10: // Volume 1
|
||||||
|
m_channels[ch].volume = data;
|
||||||
|
break;
|
||||||
|
case 0x28: // Pan L/R
|
||||||
|
m_channels[ch].pan = 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// global registers
|
||||||
|
else if (reg >= 0xd0)
|
||||||
|
{
|
||||||
|
switch (reg) {
|
||||||
|
case 0xd0:
|
||||||
|
m_vlma = data;
|
||||||
|
break;
|
||||||
|
case 0xd2:
|
||||||
|
m_cpl = data;
|
||||||
|
break;
|
||||||
|
case 0xf0:
|
||||||
|
m_bank = data & 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -25,6 +25,12 @@
|
|||||||
#define MCFG_YMZ770_REPLACE(_tag, _clock) \
|
#define MCFG_YMZ770_REPLACE(_tag, _clock) \
|
||||||
MCFG_DEVICE_REPLACE(_tag, YMZ770, _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
|
// TYPE DEFINITIONS
|
||||||
//**************************************************************************
|
//**************************************************************************
|
||||||
@ -49,9 +55,15 @@ protected:
|
|||||||
|
|
||||||
virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) override;
|
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;
|
sound_stream *m_stream;
|
||||||
|
uint32_t m_sclock;
|
||||||
|
|
||||||
// data
|
// data
|
||||||
uint8_t m_cur_reg;
|
uint8_t m_cur_reg;
|
||||||
@ -62,13 +74,12 @@ protected:
|
|||||||
uint8_t m_cpl; // clip limiter
|
uint8_t m_cpl; // clip limiter
|
||||||
required_region_ptr<uint8_t> m_rom;
|
required_region_ptr<uint8_t> m_rom;
|
||||||
|
|
||||||
private:
|
|
||||||
struct ymz_channel
|
struct ymz_channel
|
||||||
{
|
{
|
||||||
uint8_t phrase;
|
uint16_t phrase;
|
||||||
uint8_t pan;
|
uint8_t pan;
|
||||||
uint8_t volume;
|
uint8_t volume;
|
||||||
uint8_t control;
|
uint8_t loop;
|
||||||
|
|
||||||
bool is_playing, last_block;
|
bool is_playing, last_block;
|
||||||
|
|
||||||
@ -79,19 +90,40 @@ private:
|
|||||||
int output_ptr;
|
int output_ptr;
|
||||||
int atbl;
|
int atbl;
|
||||||
int pptr;
|
int pptr;
|
||||||
|
};
|
||||||
uint8_t sequence;
|
struct ymz_sequence
|
||||||
|
{
|
||||||
|
uint16_t sequence;
|
||||||
uint8_t seqcontrol;
|
uint8_t seqcontrol;
|
||||||
uint8_t seqdelay;
|
uint8_t seqdelay;
|
||||||
uint8_t *seqdata;
|
uint8_t *seqdata;
|
||||||
bool is_seq_playing;
|
bool is_seq_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 { return (m_rom[(4 * phrase) + 1] << 16 | m_rom[(4 * phrase) + 2] << 8 | m_rom[(4 * phrase) + 3]) * 2; };
|
||||||
|
virtual uint32_t get_seq_offs(int sqn) override { return (m_rom[(4 * sqn) + 1 + 0x2000] << 16 | m_rom[(4 * sqn) + 2 + 0x2000] << 8 | m_rom[(4 * sqn) + 3 + 0x2000]) * 2; };
|
||||||
|
virtual void sequencer() override {};
|
||||||
|
private:
|
||||||
|
int m_bank;
|
||||||
|
};
|
||||||
|
|
||||||
// device type definition
|
// device type definition
|
||||||
DECLARE_DEVICE_TYPE(YMZ770, ymz770_device)
|
DECLARE_DEVICE_TYPE(YMZ770, ymz770_device)
|
||||||
|
DECLARE_DEVICE_TYPE(YMZ774, ymz774_device)
|
||||||
|
|
||||||
#endif // MAME_SOUND_YMZ770_H
|
#endif // MAME_SOUND_YMZ770_H
|
||||||
|
Loading…
Reference in New Issue
Block a user