summaryrefslogtreecommitdiffstats
path: root/src/devices/sound/sn76496.h
blob: b173c059de8e483f834c04303393bce31dd889cc (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
// license:BSD-3-Clause
// copyright-holders:Nicola Salmoria
#ifndef MAME_SOUND_SN76496_H
#define MAME_SOUND_SN76496_H

#pragma once


DECLARE_DEVICE_TYPE(SN76496,  sn76496_device)
DECLARE_DEVICE_TYPE(U8106,    u8106_device)
DECLARE_DEVICE_TYPE(Y2404,    y2404_device)
DECLARE_DEVICE_TYPE(SN76489,  sn76489_device)
DECLARE_DEVICE_TYPE(SN76489A, sn76489a_device)
DECLARE_DEVICE_TYPE(SN76494,  sn76494_device)
DECLARE_DEVICE_TYPE(SN94624,  sn94624_device)
DECLARE_DEVICE_TYPE(NCR7496,  ncr7496_device)
DECLARE_DEVICE_TYPE(GAMEGEAR, gamegear_device)
DECLARE_DEVICE_TYPE(SEGAPSG,  segapsg_device)


#define MCFG_SN76496_READY_HANDLER(cb) \
	devcb = &downcast<sn76496_base_device &>(*device).set_ready_handler((DEVCB_##cb));

class sn76496_base_device : public device_t, public device_sound_interface
{
public:
	// configuration helpers
	template <class Object> devcb_base &set_ready_handler(Object &&cb) { return m_ready_handler.set_callback(std::forward<Object>(cb)); }

	DECLARE_WRITE8_MEMBER( stereo_w );
	void write(uint8_t data);
	DECLARE_WRITE8_MEMBER( command_w ) { write(data); }
	DECLARE_READ_LINE_MEMBER( ready_r ) { return m_ready_state ? 1 : 0; }

protected:
	sn76496_base_device(
			const machine_config &mconfig,
			device_type type,
			const char *tag,
			int feedbackmask,
			int noisetap1,
			int noisetap2,
			bool negate,
			bool stereo,
			int clockdivider,
			bool sega,
			device_t *owner,
			uint32_t clock);

	virtual void    device_start() override;
	virtual void    sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) override;

private:
	inline bool     in_noise_mode();
	void            register_for_save_states();
	void            countdown_cycles();

	bool            m_ready_state;

	devcb_write_line m_ready_handler;

	sound_stream*   m_sound;

	const int32_t     m_feedback_mask;    // mask for feedback
	const int32_t     m_whitenoise_tap1;  // mask for white noise tap 1 (higher one, usually bit 14)
	const int32_t     m_whitenoise_tap2;  // mask for white noise tap 2 (lower one, usually bit 13)
	const bool      m_negate;           // output negate flag
	const bool      m_stereo;           // whether we're dealing with stereo or not
	const int32_t     m_clock_divider;    // clock divider
	const bool      m_sega_style_psg;   // flag for if frequency zero acts as if it is one more than max (0x3ff+1) or if it acts like 0; AND if the initial register is pointing to 0x3 instead of 0x0 AND if the volume reg is preloaded with 0xF instead of 0x0

	int32_t           m_vol_table[16];    // volume table (for 4-bit to db conversion)
	int32_t           m_register[8];      // registers
	int32_t           m_last_register;    // last register written
	int32_t           m_volume[4];        // db volume of voice 0-2 and noise
	uint32_t          m_RNG;              // noise generator LFSR
	int32_t           m_current_clock;
	int32_t           m_stereo_mask;      // the stereo output mask
	int32_t           m_period[4];        // Length of 1/2 of waveform
	int32_t           m_count[4];         // Position within the waveform
	int32_t           m_output[4];        // 1-bit output of each channel, pre-volume
	int32_t           m_cycles_to_ready;  // number of cycles until the READY line goes active
};

// SN76496: Whitenoise verified, phase verified, periodic verified (by Michael Zapf)
class sn76496_device : public sn76496_base_device
{
public:
	sn76496_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
};

// U8106 not verified yet. todo: verify; (a custom marked sn76489? only used on mr. do and maybe other universal games)
class u8106_device : public sn76496_base_device
{
public:
	u8106_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
};

// Y2404 not verified yet. todo: verify; (don't be fooled by the Y, it's a TI chip, not Yamaha)
class y2404_device : public sn76496_base_device
{
public:
	y2404_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
};

// SN76489 not verified yet. todo: verify;
class sn76489_device : public sn76496_base_device
{
public:
	sn76489_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
};

// SN76489A: whitenoise verified, phase verified, periodic verified (by plgdavid)
class sn76489a_device : public sn76496_base_device
{
public:
	sn76489a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
};

// SN76494 not verified, (according to datasheet: same as sn76489a but without the /8 divider)
class sn76494_device : public sn76496_base_device
{
public:
	sn76494_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
};

// SN94624 whitenoise verified, phase verified, period verified; verified by PlgDavid
class sn94624_device : public sn76496_base_device
{
public:
	sn94624_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
};

// NCR7496 not verified; info from smspower wiki
class ncr7496_device : public sn76496_base_device
{
public:
	ncr7496_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
};

// Verified by Justin Kerk
class gamegear_device : public sn76496_base_device
{
public:
	gamegear_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
};

// todo: verify; from smspower wiki, assumed to have same invert as gamegear
class segapsg_device : public sn76496_base_device
{
public:
	segapsg_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
};

#endif // MAME_SOUND_SN76496_H