summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/sound/ay8910.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/sound/ay8910.h')
-rw-r--r--src/devices/sound/ay8910.h89
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