summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/audio/exidy440.h
blob: b7ce86da71e1bb070e1bdf2711838f53ba802f2e (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
// license:BSD-3-Clause
// copyright-holders:Aaron Giles
#ifndef MAME_AUDIO_EXIDY440_H
#define MAME_AUDIO_EXIDY440_H

#pragma once

#define EXIDY440_AUDIO_CLOCK    (XTAL(12'979'200) / 4)
#define EXIDY440_MC3418_CLOCK   (EXIDY440_AUDIO_CLOCK / 4 / 16)
#define EXIDY440_MC3417_CLOCK   (EXIDY440_AUDIO_CLOCK / 4 / 32)


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_t clock);
	~exidy440_sound_device() {}

	DECLARE_READ8_MEMBER(sound_command_r);
	DECLARE_READ8_MEMBER(sound_volume_r);
	DECLARE_WRITE8_MEMBER(sound_volume_w);
	DECLARE_WRITE_LINE_MEMBER(sound_interrupt_w);
	DECLARE_WRITE8_MEMBER(sound_interrupt_clear_w);
	DECLARE_WRITE_LINE_MEMBER(sound_reset_w);
	DECLARE_READ8_MEMBER(m6844_r);
	DECLARE_WRITE8_MEMBER(m6844_w);
	DECLARE_WRITE8_MEMBER(sound_banks_w);

	void exidy440_sound_command(uint8_t param);
	uint8_t exidy440_sound_command_ack();
protected:
	// device-level overrides
	virtual void device_add_mconfig(machine_config &config) override;
	virtual void device_start() override;
	virtual void device_stop() override;

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

private:
	void exidy440_audio_map(address_map &map);

	/* channel_data structure holds info about each 6844 DMA channel */
	struct m6844_channel_data
	{
		int active;
		int address;
		int counter;
		uint8_t control;
		int start_address;
		int start_counter;
	};


	/* channel_data structure holds info about each active sound channel */
	struct sound_channel_data
	{
		int16_t *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_t data[1];
	};

	required_device<cpu_device> m_audiocpu;
	required_region_ptr<uint8_t> m_samples;

	// internal state
	uint8_t m_sound_command;
	uint8_t m_sound_command_ack;

	uint8_t m_sound_banks[4];
	//uint8_t m_m6844_data[0x20];
	uint8_t m_sound_volume[0x10];
	std::unique_ptr<int32_t[]> m_mixer_buffer_left;
	std::unique_ptr<int32_t[]> 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_t m_m6844_priority;
	uint8_t m_m6844_interrupt;
	uint8_t 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_t *add_to_sound_cache(uint8_t *input, int address, int length, int bits, int frequency);
	int16_t *find_or_add_to_sound_cache(int address, int length, int bits, int frequency);

	void decode_and_filter_cvsd(uint8_t *data, int bytes, int maskbits, int frequency, int16_t *dest);
	void fir_filter(int32_t *input, int16_t *output, int count);

	void add_and_scale_samples(int ch, int32_t *dest, int samples, int volume);
	void mix_to_16(int length, stream_sample_t *dest_left, stream_sample_t *dest_right);
};

DECLARE_DEVICE_TYPE(EXIDY440, exidy440_sound_device)


#endif // MAME_AUDIO_EXIDY440_H