1 // license:BSD-3-Clause
2 // copyright-holders:Zsolt Vasvari, hap
3 /*
4  *  Carnival audio routines
5  */
6 
7 #include "emu.h"
8 #include "includes/vicdual.h"
9 
10 
11 /* output port 0x01 definitions - sound effect drive outputs */
12 #define OUT_PORT_1_RIFLE        0x01
13 #define OUT_PORT_1_CLANG        0x02
14 #define OUT_PORT_1_DUCK1        0x04
15 #define OUT_PORT_1_DUCK2        0x08
16 #define OUT_PORT_1_DUCK3        0x10
17 #define OUT_PORT_1_PIPEHIT      0x20
18 #define OUT_PORT_1_BONUS1       0x40
19 #define OUT_PORT_1_BONUS2       0x80
20 
21 /* output port 0x02 definitions - sound effect drive outputs */
22 #define OUT_PORT_2_BEAR         0x04
23 #define OUT_PORT_2_RANKING      0x20
24 
25 
26 #define PLAY(samp,id,loop)      samp->start( id, id, loop )
27 #define STOP(samp,id)           samp->stop( id )
28 
29 
30 /* sample file names */
31 static const char *const carnival_sample_names[] =
32 {
33 	"*carnival",
34 	"bear",
35 	"bonus1",
36 	"bonus2",
37 	"clang",
38 	"duck1",
39 	"duck2",
40 	"duck3",
41 	"pipehit",
42 	"ranking",
43 	"rifle",
44 	nullptr
45 };
46 
47 
48 /* sample IDs - must match sample file name table above */
49 enum
50 {
51 	SND_BEAR = 0,
52 	SND_BONUS1,
53 	SND_BONUS2,
54 	SND_CLANG,
55 	SND_DUCK1,
56 	SND_DUCK2,
57 	SND_DUCK3,
58 	SND_PIPEHIT,
59 	SND_RANKING,
60 	SND_RIFLE
61 };
62 
63 
carnival_audio_1_w(uint8_t data)64 void carnival_state::carnival_audio_1_w(uint8_t data)
65 {
66 	int bitsChanged;
67 	int bitsGoneHigh;
68 	int bitsGoneLow;
69 
70 	bitsChanged  = m_port1State ^ data;
71 	bitsGoneHigh = bitsChanged & data;
72 	bitsGoneLow  = bitsChanged & ~data;
73 
74 	m_port1State = data;
75 
76 	if ( bitsGoneLow & OUT_PORT_1_RIFLE )
77 	{
78 		PLAY( m_samples, SND_RIFLE, 0 );
79 	}
80 
81 	if ( bitsGoneLow & OUT_PORT_1_CLANG )
82 	{
83 		PLAY( m_samples, SND_CLANG, 0 );
84 	}
85 
86 	if ( bitsGoneLow & OUT_PORT_1_DUCK1 )
87 	{
88 		PLAY( m_samples, SND_DUCK1, 1 );
89 	}
90 	if ( bitsGoneHigh & OUT_PORT_1_DUCK1 )
91 	{
92 		STOP( m_samples, SND_DUCK1 );
93 	}
94 
95 	if ( bitsGoneLow & OUT_PORT_1_DUCK2 )
96 	{
97 		PLAY( m_samples, SND_DUCK2, 1 );
98 	}
99 	if ( bitsGoneHigh & OUT_PORT_1_DUCK2 )
100 	{
101 		STOP( m_samples, SND_DUCK2 );
102 	}
103 
104 	if ( bitsGoneLow & OUT_PORT_1_DUCK3 )
105 	{
106 		PLAY( m_samples, SND_DUCK3, 1 );
107 	}
108 	if ( bitsGoneHigh & OUT_PORT_1_DUCK3 )
109 	{
110 		STOP( m_samples, SND_DUCK3 );
111 	}
112 
113 	if ( bitsGoneLow & OUT_PORT_1_PIPEHIT )
114 	{
115 		PLAY( m_samples, SND_PIPEHIT, 0 );
116 	}
117 
118 	if ( bitsGoneLow & OUT_PORT_1_BONUS1 )
119 	{
120 		PLAY( m_samples, SND_BONUS1, 0 );
121 	}
122 
123 	if ( bitsGoneLow & OUT_PORT_1_BONUS2 )
124 	{
125 		PLAY( m_samples, SND_BONUS2, 0 );
126 	}
127 }
128 
carnival_audio_2_w(uint8_t data)129 void carnival_state::carnival_audio_2_w(uint8_t data)
130 {
131 	int bitsChanged;
132 	//int bitsGoneHigh;
133 	int bitsGoneLow;
134 
135 	bitsChanged  = m_port2State ^ data;
136 	//bitsGoneHigh = bitsChanged & data;
137 	bitsGoneLow  = bitsChanged & ~data;
138 
139 	m_port2State = data;
140 
141 	if ( bitsGoneLow & OUT_PORT_2_BEAR )
142 	{
143 		PLAY( m_samples, SND_BEAR, 0 );
144 	}
145 
146 	if ( bitsGoneLow & OUT_PORT_2_RANKING )
147 	{
148 		PLAY( m_samples, SND_RANKING, 0 );
149 	}
150 
151 	// d4: music board MCU reset
152 	m_audiocpu->set_input_line(INPUT_LINE_RESET, (data & 0x10) ? CLEAR_LINE : ASSERT_LINE);
153 }
154 
155 
156 /* Music board */
157 
158 // common
159 
mboard_map(address_map & map)160 void carnival_state::mboard_map(address_map &map)
161 {
162 	map(0x0000, 0x03ff).rom();
163 }
164 
READ_LINE_MEMBER(carnival_state::carnival_music_port_t1_r)165 READ_LINE_MEMBER( carnival_state::carnival_music_port_t1_r )
166 {
167 	// T1: comms from audio port 2 d3
168 	return ~m_port2State >> 3 & 1;
169 }
170 
171 
172 // AY8912 music
173 
carnival_psg_latch()174 void carnival_state::carnival_psg_latch()
175 {
176 	if (m_musicBus & 1)
177 	{
178 		// BDIR W, BC1 selects address or data
179 		if (m_musicBus & 2)
180 			m_psg->address_w(m_musicData);
181 		else
182 			m_psg->data_w(m_musicData);
183 	}
184 }
185 
carnivala_music_port_1_w(uint8_t data)186 void carnival_state::carnivala_music_port_1_w(uint8_t data)
187 {
188 	// P1: AY8912 d0-d7
189 	m_musicData = data;
190 	carnival_psg_latch();
191 }
192 
carnivala_music_port_2_w(uint8_t data)193 void carnival_state::carnivala_music_port_2_w(uint8_t data)
194 {
195 	// P2 d6: AY8912 BDIR(R/W)
196 	// P2 d7: AY8912 BC1
197 	m_musicBus = data >> 6 & 3;
198 	carnival_psg_latch();
199 }
200 
carnivala_audio(machine_config & config)201 void carnival_state::carnivala_audio(machine_config &config)
202 {
203 	/* music board */
204 	I8035(config, m_audiocpu, XTAL(3'579'545));
205 	m_audiocpu->set_addrmap(AS_PROGRAM, &carnival_state::mboard_map);
206 	m_audiocpu->p1_out_cb().set(FUNC(carnival_state::carnivala_music_port_1_w));
207 	m_audiocpu->p2_out_cb().set(FUNC(carnival_state::carnivala_music_port_2_w));
208 	m_audiocpu->t1_in_cb().set(FUNC(carnival_state::carnival_music_port_t1_r));
209 
210 	AY8912(config, m_psg, XTAL(3'579'545)/3).add_route(ALL_OUTPUTS, "mono", 0.25); // also seen with AY-3-8910, daughterboard has place for either chip
211 
212 	/* samples */
213 	SAMPLES(config, m_samples);
214 	m_samples->set_channels(10);
215 	m_samples->set_samples_names(carnival_sample_names);
216 	m_samples->add_route(ALL_OUTPUTS, "mono", 0.5);
217 }
218 
219 
220 // PIT8253 music
221 
carnivalb_music_port_1_w(uint8_t data)222 void carnival_state::carnivalb_music_port_1_w(uint8_t data)
223 {
224 	// P1: PIT8253 d0-d7
225 	m_musicData = data;
226 }
227 
carnivalb_music_port_2_w(uint8_t data)228 void carnival_state::carnivalb_music_port_2_w(uint8_t data)
229 {
230 	// P2 d7: PIT8253 write strobe
231 	// P2 d5,d6: PIT8253 A0,A1
232 	if (~m_musicBus & data & 0x80)
233 		m_pit->write(data >> 5 & 3, m_musicData);
234 
235 	m_musicBus = data;
236 }
237 
carnivalb_audio(machine_config & config)238 void carnival_state::carnivalb_audio(machine_config &config)
239 {
240 	// already inherited carnivala_audio
241 	config.device_remove("psg");
242 
243 	m_audiocpu->p1_out_cb().set(FUNC(carnival_state::carnivalb_music_port_1_w));
244 	m_audiocpu->p2_out_cb().set(FUNC(carnival_state::carnivalb_music_port_2_w));
245 
246 	PIT8253(config, m_pit, 0);
247 	m_pit->set_clk<0>(XTAL(3'579'545)/3);
248 	m_pit->set_clk<1>(XTAL(3'579'545)/3);
249 	m_pit->set_clk<2>(XTAL(3'579'545)/3);
250 
251 	m_pit->out_handler<0>().set(m_dac[0], FUNC(dac_bit_interface::write));
252 	m_pit->out_handler<1>().set(m_dac[1], FUNC(dac_bit_interface::write));
253 	m_pit->out_handler<2>().set(m_dac[2], FUNC(dac_bit_interface::write));
254 
255 	for (int i = 0; i < 3; i++)
256 		DAC_1BIT(config, m_dac[i]).add_route(ALL_OUTPUTS, "mono", 0.15);
257 }
258