diff options
Diffstat (limited to 'src/devices/sound/ay8910.h')
-rw-r--r-- | src/devices/sound/ay8910.h | 89 |
1 files changed, 57 insertions, 32 deletions
diff --git a/src/devices/sound/ay8910.h b/src/devices/sound/ay8910.h index 146c1926522..44ec39649c2 100644 --- a/src/devices/sound/ay8910.h +++ b/src/devices/sound/ay8910.h @@ -66,8 +66,9 @@ public: { PSG_DEFAULT = 0x0, PSG_PIN26_IS_CLKSEL = 0x1, - PSG_EXTENDED_ENVELOPE = 0x2, - PSG_HAS_EXPANDED_MODE = 0x4 + PSG_HAS_INTERNAL_DIVIDER = 0x2, + PSG_EXTENDED_ENVELOPE = 0x4, + PSG_HAS_EXPANDED_MODE = 0x8 }; // construction/destruction @@ -75,7 +76,12 @@ public: // configuration helpers void set_flags(int flags) { m_flags = flags; } - void set_psg_type(psg_type_t psg_type) { set_type(psg_type); } + void set_psg_type(psg_type_t psg_type) + { + // Ignore when AY8930 for now + if (!(m_feature & PSG_HAS_EXPANDED_MODE)) + set_type(psg_type); + } void set_resistors_load(int res_load0, int res_load1, int res_load2) { m_res_load[0] = res_load0; m_res_load[1] = res_load1; m_res_load[2] = res_load2; } auto port_a_read_callback() { return m_port_a_read_cb.bind(); } auto port_b_read_callback() { return m_port_b_read_cb.bind(); } @@ -129,23 +135,21 @@ protected: u32 clock, psg_type_t psg_type, int streams, int ioports, int feature = PSG_DEFAULT); // device-level overrides - virtual void device_start() override; - virtual void device_reset() override; + virtual void device_start() override ATTR_COLD; + virtual void device_reset() override ATTR_COLD; virtual void device_clock_changed() override; // sound stream update overrides - 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) override; - // trampolines for callbacks from fm.cpp - static void psg_set_clock(device_t *device, int clock) { downcast<ay8910_device *>(device)->ay_set_clock(clock); } - static void psg_write(device_t *device, int address, int data) { downcast<ay8910_device *>(device)->ay8910_write_ym(address, data); } - static int psg_read(device_t *device) { return downcast<ay8910_device *>(device)->ay8910_read_ym(); } - static void psg_reset(device_t *device) { downcast<ay8910_device *>(device)->ay8910_reset_ym(); } + void ay8910_write_ym(int addr, u8 data); + u8 ay8910_read_ym(); + void ay8910_reset_ym(); private: static constexpr unsigned NUM_CHANNELS = 3; - /* register id's */ + // register id's enum { AY_AFINE = 0x00, @@ -244,7 +248,7 @@ private: attack = (shape & 0x04) ? mask : 0x00; if ((shape & 0x08) == 0) { - /* if Continue = 0, map the shape to the equivalent one which has Continue = 1 */ + // if Continue = 0, map the shape to the equivalent one which has Continue = 1 hold = 1; alternate = attack; } @@ -259,6 +263,18 @@ private: } }; + inline void noise_rng_tick() + { + // The Random Number Generator of the 8910 is a 17-bit shift + // register. The input to the shift register is bit0 XOR bit3 + // (bit0 is the output). This was verified on AY-3-8910 and YM2149 chips. + + if (m_feature & PSG_HAS_EXPANDED_MODE) // AY8930 LFSR algorithm is slightly different, verified from manual + m_rng = (m_rng >> 1) | ((BIT(m_rng, 0) ^ BIT(m_rng, 2)) << 16); + else + m_rng = (m_rng >> 1) | ((BIT(m_rng, 0) ^ BIT(m_rng, 3)) << 16); + } + // inlines inline bool tone_enable(int chan) { return BIT(m_regs[AY_ENABLE], chan); } inline u8 tone_volume(tone_t *tone) { return tone->volume & (is_expanded_mode() ? 0x1f : 0x0f); } @@ -267,23 +283,22 @@ private: inline u8 get_envelope_chan(int chan) { return is_expanded_mode() ? chan : 0; } inline bool noise_enable(int chan) { return BIT(m_regs[AY_ENABLE], 3 + chan); } - inline u8 noise_period() { return is_expanded_mode() ? m_regs[AY_NOISEPER] & 0xff : (m_regs[AY_NOISEPER] & 0x1f) << 1; } - inline u8 noise_output() { return m_rng & 1; } + inline u8 noise_period() { return is_expanded_mode() ? m_regs[AY_NOISEPER] & 0xff : m_regs[AY_NOISEPER] & 0x1f; } + inline u8 noise_output() { return is_expanded_mode() ? m_noise_out & 1 : m_rng & 1; } inline bool is_expanded_mode() { return ((m_feature & PSG_HAS_EXPANDED_MODE) && ((m_mode & 0xe) == 0xa)); } inline u8 get_register_bank() { return is_expanded_mode() ? (m_mode & 0x1) << 4 : 0; } + inline u8 noise_and() { return m_regs[AY_NOISEAND] & 0xff; } + inline u8 noise_or() { return m_regs[AY_NOISEOR] & 0xff; } + // internal helpers void set_type(psg_type_t psg_type); - inline u16 mix_3D(); + inline sound_stream::sample_t mix_3D(); void ay8910_write_reg(int r, int v); void build_mixer_table(); void ay8910_statesave(); - void ay8910_write_ym(int addr, u8 data); - u8 ay8910_read_ym(); - void ay8910_reset_ym(); - // internal state psg_type_t m_type; int m_streams; @@ -291,28 +306,30 @@ private: int m_ready; sound_stream *m_channel; bool m_active; - s32 m_register_latch; + u8 m_register_latch; u8 m_regs[16 * 2]; - s32 m_last_enable; + u8 m_last_enable; tone_t m_tone[NUM_CHANNELS]; envelope_t m_envelope[NUM_CHANNELS]; u8 m_prescale_noise; - s32 m_count_noise; - s32 m_rng; + s16 m_noise_value; + s16 m_count_noise; + u32 m_rng; + u8 m_noise_out; u8 m_mode; u8 m_env_step_mask; - /* init parameters ... */ + // init parameters ... int m_step; int m_zero_is_off; u8 m_vol_enabled[NUM_CHANNELS]; const ay_ym_param *m_par; const ay_ym_param *m_par_env; - s32 m_vol_table[NUM_CHANNELS][16]; - s32 m_env_table[NUM_CHANNELS][32]; - std::unique_ptr<s32[]> m_vol3d_table; - int m_flags; /* Flags */ - int m_feature; /* Chip specific features */ - int m_res_load[3]; /* Load on channel in ohms */ + sound_stream::sample_t m_vol_table[NUM_CHANNELS][16]; + sound_stream::sample_t m_env_table[NUM_CHANNELS][32]; + std::unique_ptr<sound_stream::sample_t[]> m_vol3d_table; + int m_flags; // Flags + int m_feature; // Chip specific features + int m_res_load[3]; // Load on channel in ohms devcb_read8 m_port_a_read_cb; devcb_read8 m_port_b_read_cb; devcb_write8 m_port_a_write_cb; @@ -342,7 +359,7 @@ class ay8914_device : public ay8910_device public: ay8914_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); - /* AY8914 handlers needed due to different register map */ + // AY8914 handlers needed due to different register map u8 read(offs_t offset); void write(offs_t offset, u8 data); }; @@ -389,5 +406,13 @@ public: DECLARE_DEVICE_TYPE(YMZ294, ymz294_device) +class sunsoft_5b_sound_device : public ay8910_device +{ +public: + sunsoft_5b_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); +}; + +DECLARE_DEVICE_TYPE(SUNSOFT_5B_SOUND, sunsoft_5b_sound_device) + #endif // MAME_DEVICES_SOUND_AY8910_H |