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