summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/sound/swp30.h
blob: 56e24b453f0839a474bd65c1b5d95d0574bd1ba8 (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
// license:BSD-3-Clause
// copyright-holders:Olivier Galibert

// Yamaha SWP30/30B, rompler/dsp combo

#ifndef DEVICES_SOUND_SWP30_H
#define DEVICES_SOUND_SWP30_H

#pragma once

class swp30_device : public device_t, public device_sound_interface, public device_rom_interface
{
public:
	swp30_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 33868800);

	void map(address_map &map);

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

private:
	sound_stream *m_stream;

	s32 m_sample_increment[0x4000];
	s32 m_linear_attenuation[0x100];
	s16 m_sample_log8[0x100];

	u64 m_program[0x180];
	u64 m_keyon_mask, m_active_mask;
	u32 m_pre_size[0x40], m_post_size[0x40], m_address[0x40];

	s32 m_sample_pos[64];
	s32 m_sample_history[0x40][2][2];

	u16 m_program_pfp[0x180], m_program_pint[0x80], m_program_plfo[0x80];

	u16 m_volume[0x40], m_freq[0x40], m_pan[0x40], m_dry_rev[0x40], m_cho_var[0x40];
	u16 m_envelope[0x40][3];
	u16 m_lpf_cutoff[0x40], m_lpf_cutoff_inc[0x40], m_lpf_reso[0x40], m_hpf_cutoff[0x40];
	s16 m_eq_filter[0x40][6];
	u16 m_routing[0x40][3];
	u16 m_map[8];

	u16 m_program_address;

	// AWM2 per-channel registers
	u16 lpf_cutoff_r(offs_t offset);
	void lpf_cutoff_w(offs_t offset, u16 data);
	u16 lpf_cutoff_inc_r(offs_t offset);
	void lpf_cutoff_inc_w(offs_t offset, u16 data);
	u16 hpf_cutoff_r(offs_t offset);
	void hpf_cutoff_w(offs_t offset, u16 data);
	u16 lpf_reso_r(offs_t offset);
	void lpf_reso_w(offs_t offset, u16 data);
	template<int sel> u16 envelope_r(offs_t offset);
	template<int sel> void envelope_w(offs_t offset, u16 data);
	template<int coef> u16 eq_filter_r(offs_t offset);
	template<int coef> void eq_filter_w(offs_t offset, u16 data);
	u16 volume_r(offs_t offset);
	void volume_w(offs_t offset, u16 data);
	u16 freq_r(offs_t offset);
	void freq_w(offs_t offset, u16 data);
	u16 pre_size_h_r(offs_t offset);
	u16 pre_size_l_r(offs_t offset);
	void pre_size_h_w(offs_t offset, u16 data);
	void pre_size_l_w(offs_t offset, u16 data);
	u16 post_size_h_r(offs_t offset);
	u16 post_size_l_r(offs_t offset);
	void post_size_h_w(offs_t offset, u16 data);
	void post_size_l_w(offs_t offset, u16 data);
	u16 address_h_r(offs_t offset);
	u16 address_l_r(offs_t offset);
	void address_h_w(offs_t offset, u16 data);
	void address_l_w(offs_t offset, u16 data);
	u16 pan_r(offs_t offset);
	void pan_w(offs_t offset, u16 data);
	u16 dry_rev_r(offs_t offset);
	void dry_rev_w(offs_t offset, u16 data);
	u16 cho_var_r(offs_t offset);
	void cho_var_w(offs_t offset, u16 data);
	template<int sel> u16 routing_r(offs_t offset);
	template<int sel> void routing_w(offs_t offset, u16 data);

	// Control registers
	template<int sel> u16 keyon_mask_r();
	template<int sel> void keyon_mask_w(u16 data);
	u16 keyon_r();
	void keyon_w(u16);
	u16 prg_address_r();
	void prg_address_w(u16 data);
	template<int sel> u16 prg_r();
	template<int sel> void prg_w(u16 data);
	template<int sel> u16 map_r();
	template<int sel> void map_w(u16 data);

	// MEG registers
	template<int sel> u16 prg_fp_r(offs_t offset);
	template<int sel> void prg_fp_w(offs_t offset, u16 data);
	template<int sel> u16 prg_int_r(offs_t offset);
	template<int sel> void prg_int_w(offs_t offset, u16 data);
	template<int sel> u16 prg_lfo_r(offs_t offset);
	template<int sel> void prg_lfo_w(offs_t offset, u16 data);


	// Generic catch-all
	u16 snd_r(offs_t offset);
	void snd_w(offs_t offset, u16 data);

	inline auto &rchan(address_map &map, int idx) {
		return map(idx*2, idx*2+1).select(0x1f80);
	}

	inline auto &rctrl(address_map &map, int idx) {
		int slot = 0x40*(idx >> 1) | 0xe | (idx & 1);
		return map(slot*2, slot*2+1);
	}
};

DECLARE_DEVICE_TYPE(SWP30, swp30_device)

#endif