// license:BSD-3-Clause
// copyright-holders:Olivier Galibert, R. Belmont
/***************************************************************************
ymz770.h
***************************************************************************/
#ifndef MAME_SOUND_YMZ770_H
#define MAME_SOUND_YMZ770_H
#pragma once
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
// forward definition
class mpeg_audio;
// ======================> ymz770_device
class ymz770_device : public device_t, public device_sound_interface
{
public:
// construction/destruction
ymz770_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
DECLARE_WRITE8_MEMBER(write);
protected:
// device-level overrides
virtual void device_start() override;
virtual void device_reset() override;
virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) override;
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();
uint8_t get_rom_byte(uint32_t offset) { return m_rom[offset % m_rom.bytes()]; }; // need optimise or its good as is ?
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 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;
struct ymz_channel
{
uint16_t phrase;
uint8_t pan;
uint8_t pan_delay;
uint8_t pan1;
uint8_t pan1_delay;
int32_t volume;
uint8_t volume_target;
uint8_t volume_delay;
uint8_t volume2;
uint8_t loop;
bool is_playing, last_block, is_paused;
mpeg_audio *decoder;
int16_t output_data[0x1000];
int output_remaining;
int output_ptr;
int atbl;
int pptr;
};
struct ymz_sequence
{
uint32_t delay;
uint16_t sequence;
uint16_t timer;
uint16_t stopchan;
uint8_t loop;
uint32_t offset;
uint8_t bank;
bool is_playing;
bool is_paused;
};
struct ymz_sqc
{
uint8_t sqc;
uint8_t loop;
uint32_t offset;
bool is_playing;
bool is_waiting;
};
ymz_channel m_channels[16];
ymz_sequence m_sequences[8];
ymz_sqc m_sqcs[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; };
uint32_t get_sqc_offs(int sqc) { int sq = sqc * 4 + 0x6000; 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