summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/audio/exidy440.h
blob: 2dcd3d7b30426f40b5317dd9c598bad02cd5fdee (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
/* channel_data structure holds info about each 6844 DMA channel */
struct m6844_channel_data
{
	int active;
	int address;
	int counter;
	UINT8 control;
	int start_address;
	int start_counter;
};


/* channel_data structure holds info about each active sound channel */
struct sound_channel_data
{
	INT16 *base;
	int offset;
	int remaining;
};


/* sound_cache_entry structure contains info on each decoded sample */
struct sound_cache_entry
{
	struct sound_cache_entry *next;
	int address;
	int length;
	int bits;
	int frequency;
	INT16 data[1];
};

class exidy440_sound_device : public device_t,
									public device_sound_interface
{
public:
	exidy440_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
	~exidy440_sound_device() {}

	DECLARE_READ8_MEMBER( sound_command_r );
	DECLARE_READ8_MEMBER( sound_volume_r );
	DECLARE_WRITE8_MEMBER( sound_volume_w );
	DECLARE_WRITE8_MEMBER( sound_interrupt_clear_w );
	DECLARE_READ8_MEMBER( m6844_r );
	DECLARE_WRITE8_MEMBER( m6844_w );
	DECLARE_WRITE8_MEMBER( sound_banks_w );
	
	void exidy440_sound_command(UINT8 param);
	UINT8 exidy440_sound_command_ack();
	
protected:
	// device-level overrides
	virtual void device_config_complete();
	virtual void device_start();
	virtual void device_stop();

	// sound stream update overrides
	virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples);

private:
	// internal state
	UINT8 m_sound_command;
	UINT8 m_sound_command_ack;

	UINT8 m_sound_banks[4];
	UINT8 m_m6844_data[0x20];
	UINT8 m_sound_volume[0x10];
	INT32 *m_mixer_buffer_left;
	INT32 *m_mixer_buffer_right;
	sound_cache_entry *m_sound_cache;
	sound_cache_entry *m_sound_cache_end;
	sound_cache_entry *m_sound_cache_max;

	/* 6844 description */
	m6844_channel_data m_m6844_channel[4];
	UINT8 m_m6844_priority;
	UINT8 m_m6844_interrupt;
	UINT8 m_m6844_chain;

	/* sound interface parameters */
	sound_stream *m_stream;
	sound_channel_data m_sound_channel[4];

	/* debugging */
	FILE *m_debuglog;

	/* channel frequency is configurable */
	int m_channel_frequency[4];
	
	void m6844_update();
	void m6844_finished(m6844_channel_data *channel);
	void play_cvsd(int ch);
	void stop_cvsd(int ch);

	void reset_sound_cache();
	INT16 *add_to_sound_cache(UINT8 *input, int address, int length, int bits, int frequency);
	INT16 *find_or_add_to_sound_cache(int address, int length, int bits, int frequency);

	void decode_and_filter_cvsd(UINT8 *data, int bytes, int maskbits, int frequency, INT16 *dest);
	void fir_filter(INT32 *input, INT16 *output, int count);
	
	void add_and_scale_samples(int ch, INT32 *dest, int samples, int volume);
	void mix_to_16(int length, stream_sample_t *dest_left, stream_sample_t *dest_right);
};

extern const device_type EXIDY440;

MACHINE_CONFIG_EXTERN( exidy440_audio );