1 // license:BSD-3-Clause
2 // copyright-holders:Nicola Salmoria
3 /***************************************************************************
4 
5     Sega Zaxxon hardware
6 
7 ****************************************************************************
8 
9     Sound interface is provided by an 8255. The 8255 is a parallel peripheral
10     interface, used also in Scramble. It has three 8-bit outputs.
11     All sounds are generated by discrete circuits. Each sound is triggered by
12     an output pin of the 8255.
13 
14     Zaxxon Sound Information: (from the schematics)
15     by Frank Palazzolo
16 
17     There are four registers in the 8255. they are mapped to
18     (111x xxxx 0011 11pp) by Zaxxon.  Zaxxon writes to these
19     at FF3C-FF3F.
20 
21     There are three modes of the 8255, but by the schematics I
22     can see that Zaxxon is using "Mode 0", which is very simple.
23 
24     Important Note:
25     These are all Active-Low outputs.
26     A 1 De-activates the sound, while a 0 Activates/Triggers it
27 
28     Port A Output:
29     FF3C bit7 Battleship
30          bit6 Laser
31          bit5 Base Missle
32          bit4 Homing Missle
33          bit3 Player Ship D
34          bit2 Player Ship C
35          bit1 Player Ship B
36          bit0 Player Ship A
37 
38     Port B Output:
39     FF3D bit7 Cannon
40          bit6 N/C
41          bit5 M-Exp
42          bit4 S-Exp
43          bit3 N/C
44          bit2 N/C
45          bit1 N/C
46          bit0 N/C
47 
48     Port C Output:
49     FF3E bit7 N/C
50          bit6 N/C
51          bit5 N/C
52          bit4 N/C
53          bit3 Alarm 3
54          bit2 Alarm 2
55          bit1 N/C
56          bit0 Shot
57 
58     Control Byte:
59     FF3F Should be written an 0x80 for Mode 0
60          (Very Simple) operation of the 8255
61 
62 ***************************************************************************/
63 
64 #include "emu.h"
65 #include "sound/samples.h"
66 #include "includes/zaxxon.h"
67 
68 
69 
70 /*************************************
71  *
72  *  Zaxxon sound hardware description
73  *
74  *************************************/
75 
76 static const char *const zaxxon_sample_names[] =
77 {
78 	"*zaxxon",
79 	"03",   /* 0 - Homing Missile */
80 	"02",   /* 1 - Base Missile */
81 	"01",   /* 2 - Laser (force field) */
82 	"00",   /* 3 - Battleship (end of level boss) */
83 	"11",   /* 4 - S-Exp (enemy explosion) */
84 	"10",   /* 5 - M-Exp (ship explosion) */
85 	"08",   /* 6 - Cannon (ship fire) */
86 	"23",   /* 7 - Shot (enemy fire) */
87 	"21",   /* 8 - Alarm 2 (target lock) */
88 	"20",   /* 9 - Alarm 3 (low fuel) */
89 	"05",   /* 10 - initial background noise */
90 	"04",   /* 11 - looped asteroid noise */
91 	nullptr
92 };
93 
94 
zaxxon_samples(machine_config & config)95 void zaxxon_state::zaxxon_samples(machine_config &config)
96 {
97 	SAMPLES(config, m_samples);
98 	m_samples->set_channels(12);
99 	m_samples->set_samples_names(zaxxon_sample_names);
100 	m_samples->add_route(ALL_OUTPUTS, "speaker", 0.25);
101 }
102 
103 
104 
105 /*************************************
106  *
107  *  Zaxxon PPI write handlers
108  *
109  *************************************/
110 
zaxxon_sound_a_w(uint8_t data)111 void zaxxon_state::zaxxon_sound_a_w(uint8_t data)
112 {
113 	uint8_t diff = data ^ m_sound_state[0];
114 	m_sound_state[0] = data;
115 
116 	/* PLAYER SHIP A/B: volume */
117 	m_samples->set_volume(10, 0.5 + 0.157 * (data & 0x03));
118 	m_samples->set_volume(11, 0.5 + 0.157 * (data & 0x03));
119 
120 	/* PLAYER SHIP C: channel 10 */
121 	if ((diff & 0x04) && !(data & 0x04)) m_samples->start(10, 10, true);
122 	if ((diff & 0x04) &&  (data & 0x04)) m_samples->stop(10);
123 
124 	/* PLAYER SHIP D: channel 11 */
125 	if ((diff & 0x08) && !(data & 0x08)) m_samples->start(11, 11, true);
126 	if ((diff & 0x08) &&  (data & 0x08)) m_samples->stop(11);
127 
128 	/* HOMING MISSILE: channel 0 */
129 	if ((diff & 0x10) && !(data & 0x10)) m_samples->start(0, 0, true);
130 	if ((diff & 0x10) &&  (data & 0x10)) m_samples->stop(0);
131 
132 	/* BASE MISSILE: channel 1 */
133 	if ((diff & 0x20) && !(data & 0x20)) m_samples->start(1, 1);
134 
135 	/* LASER: channel 2 */
136 	if ((diff & 0x40) && !(data & 0x40)) m_samples->start(2, 2, true);
137 	if ((diff & 0x40) &&  (data & 0x40)) m_samples->stop(2);
138 
139 	/* BATTLESHIP: channel 3 */
140 	if ((diff & 0x80) && !(data & 0x80)) m_samples->start(3, 3, true);
141 	if ((diff & 0x80) &&  (data & 0x80)) m_samples->stop(3);
142 }
143 
144 
zaxxon_sound_b_w(uint8_t data)145 void zaxxon_state::zaxxon_sound_b_w(uint8_t data)
146 {
147 	uint8_t diff = data ^ m_sound_state[1];
148 	m_sound_state[1] = data;
149 
150 	/* S-EXP: channel 4 */
151 	if ((diff & 0x10) && !(data & 0x10)) m_samples->start(4, 4);
152 
153 	/* M-EXP: channel 5 */
154 	if ((diff & 0x20) && !(data & 0x20) && !m_samples->playing(5)) m_samples->start(5, 5);
155 
156 	/* CANNON: channel 6 */
157 	if ((diff & 0x80) && !(data & 0x80)) m_samples->start(6, 6);
158 }
159 
160 
zaxxon_sound_c_w(uint8_t data)161 void zaxxon_state::zaxxon_sound_c_w(uint8_t data)
162 {
163 	uint8_t diff = data ^ m_sound_state[2];
164 	m_sound_state[2] = data;
165 
166 	/* SHOT: channel 7 */
167 	if ((diff & 0x01) && !(data & 0x01)) m_samples->start(7, 7);
168 
169 	/* ALARM2: channel 8 */
170 	if ((diff & 0x04) && !(data & 0x04)) m_samples->start(8, 8);
171 
172 	/* ALARM3: channel 9 */
173 	if ((diff & 0x08) && !(data & 0x08) && !m_samples->playing(9)) m_samples->start(9, 9);
174 }
175 
176 
177 
178 /*************************************
179  *
180  *  Congo sound hardware description
181  *
182  *************************************/
183 
184 static const char *const congo_sample_names[] =
185 {
186 	"*congo",
187 	"gorilla",  /* 0 */
188 	"bass",     /* 1 */
189 	"congal",   /* 2 */
190 	"congah",   /* 3 */
191 	"rim",      /* 4 */
192 	nullptr
193 };
194 
195 
congo_samples(machine_config & config)196 void zaxxon_state::congo_samples(machine_config &config)
197 {
198 	SAMPLES(config, m_samples);
199 	m_samples->set_channels(5);
200 	m_samples->set_samples_names(congo_sample_names);
201 	m_samples->add_route(ALL_OUTPUTS, "speaker", 0.25);
202 }
203 
204 
205 
206 /*************************************
207  *
208  *  Congo PPI write handlers
209  *
210  *************************************/
211 
congo_sound_b_w(uint8_t data)212 void zaxxon_state::congo_sound_b_w(uint8_t data)
213 {
214 	uint8_t diff = data ^ m_sound_state[1];
215 	m_sound_state[1] = data;
216 
217 	/* bit 7 = mute */
218 
219 	/* GORILLA: channel 0 */
220 	if ((diff & 0x02) && !(data & 0x02) && !m_samples->playing(0)) m_samples->start(0, 0);
221 }
222 
223 
congo_sound_c_w(uint8_t data)224 void zaxxon_state::congo_sound_c_w(uint8_t data)
225 {
226 	uint8_t diff = data ^ m_sound_state[2];
227 	m_sound_state[2] = data;
228 
229 	/* BASS DRUM: channel 1 */
230 	if ((diff & 0x01) && !(data & 0x01)) m_samples->start(1, 1);
231 	if ((diff & 0x01) &&  (data & 0x01)) m_samples->stop(1);
232 
233 	/* CONGA (LOW): channel 2 */
234 	if ((diff & 0x02) && !(data & 0x02)) m_samples->start(2, 2);
235 	if ((diff & 0x02) &&  (data & 0x02)) m_samples->stop(2);
236 
237 	/* CONGA (HIGH): channel 3 */
238 	if ((diff & 0x04) && !(data & 0x04)) m_samples->start(3, 3);
239 	if ((diff & 0x04) &&  (data & 0x04)) m_samples->stop(3);
240 
241 	/* RIM: channel 4 */
242 	if ((diff & 0x08) && !(data & 0x08)) m_samples->start(4, 4);
243 	if ((diff & 0x08) &&  (data & 0x08)) m_samples->stop(4);
244 }
245