1 /*
2 * Berzerk/Frenzy Soundhardware Driver
3 * Copyright Alex Judd 1997/98
4 * V1.1 for Mame 0.31 13March98
5 *
6 * these were the original values but I have adjusted them to take account of the
7 * default sample rate of 22050. I guess the original samples were at 24000.
8 * case 0 : samplefrequency = 19500;
9 * case 1 : samplefrequency = 20800;
10 * case 2 : samplefrequency = 22320;
11 * case 3 : samplefrequency = 24000;
12 * case 4 : samplefrequency = 26000;
13 * case 5 : samplefrequency = 28400;
14 * case 6 : samplefrequency = 31250;
15 * case 7 : samplefrequency = 34700;
16 *
17 */
18
19 #include "driver.h"
20 #include "includes/berzerk.h"
21
22
23 static const char *sample_names[] =
24 {
25 "*berzerk", /* universal samples directory */
26 "",
27 "01.wav", /* "kill"*/
28 "02.wav", /* "attack"*/
29 "03.wav", /* "charge"*/
30 "04.wav", /* "got"*/
31 "05.wav", /* "to"*/
32 "06.wav", /* "get"*/
33 "",
34 "08.wav", /* "alert"*/
35 "09.wav", /* "detected"*/
36 "10.wav", /* "the"*/
37 "11.wav", /* "in"*/
38 "12.wav", /* "it"*/
39 "",
40 "",
41 "15.wav", /* "humanoid"*/
42 "16.wav", /* "coins"*/
43 "17.wav", /* "pocket"*/
44 "18.wav", /* "intruder"*/
45 "",
46 "20.wav", /* "escape"*/
47 "21.wav", /* "destroy"*/
48 "22.wav", /* "must"*/
49 "23.wav", /* "not"*/
50 "24.wav", /* "chicken"*/
51 "25.wav", /* "fight"*/
52 "26.wav", /* "like"*/
53 "27.wav", /* "a"*/
54 "28.wav", /* "robot"*/
55 "",
56 "30.wav", /* player fire*/
57 "31.wav", /* baddie fire*/
58 "32.wav", /* kill baddie*/
59 "33.wav", /* kill human (real)*/
60 "34.wav", /* kill human (cheat)*/
61 0 /* end of array */
62 };
63
64
65 #define VOICE_PITCH_MODULATION /* remove this to disable voice pitch modulation */
66
67 /* Note: We have the ability to replace the real death sound (33) and the
68 * real voices with sample (34) as no good death sample could be obtained.
69 */
70 /*#define FAKE_DEATH_SOUND*/
71
72
73 /* volume and channel controls */
74 #define VOICE_VOLUME 100
75 #define SOUND_VOLUME 80
76 #define SOUND_CHANNEL 1 /* channel for sound effects */
77 #define VOICE_CHANNEL 5 /* special channel for voice sounds only */
78 #define DEATH_CHANNEL 6 /* special channel for fake death sound only */
79
80 /* berzerk sound */
81 static int lastfreq = 0;
82 static int lastnoise = 0;
83 static int lastvoice = 0;
84
85 /* sound controls */
86 static int berzerknoisemulate = 0;
87 static int voicevolume = 100;
88 static long samplefrequency = 22320;
89 static int voice_playing;
90 static int deathsound = 0; /* trigger for playing collision sound */
91 static int nextdata5 = -1;
92
berzerk_sh_start(const struct MachineSound * msound)93 static int berzerk_sh_start(const struct MachineSound *msound)
94 {
95 int i;
96
97
98 berzerknoisemulate = 1;
99
100 if (Machine->samples)
101 {
102 for (i = 0;i < 5;i++)
103 {
104 if (Machine->samples->sample[i])
105 berzerknoisemulate = 0;
106 }
107 }
108 return 0;
109 }
110
WRITE_HANDLER(berzerk_sound_control_a_w)111 WRITE_HANDLER( berzerk_sound_control_a_w )
112 {
113 int noise = 0;
114 int voice = 0;
115 int voicefrequency = 0;
116
117 /* Throw out all the non-need sound info. (for the moment) */
118
119 if (offset < 3) return;
120
121 /* Decode message for voice samples */
122
123 if (offset==4)
124 {
125 if ((data & 0x40) == 0)
126 {
127 voice = data;
128 voice_playing = 0;
129 }
130 else
131 {
132 /* We should use the volume and frequency on the voice samples */
133 voicevolume = ((data & 0x38) >> 3);
134 if (voicevolume > 0) voicevolume=255;
135
136 voicefrequency = (data & 0x07);
137 #ifdef VOICE_PITCH_MODULATION
138 switch(voicefrequency)
139 {
140 case 0 : samplefrequency = 17640; break;
141 case 1 : samplefrequency = 19404; break;
142 case 2 : samplefrequency = 20947; break;
143 case 3 : samplefrequency = 22050; break;
144 case 4 : samplefrequency = 26019; break;
145 case 5 : samplefrequency = 27783; break;
146 case 6 : samplefrequency = 31250; break;
147 case 7 : samplefrequency = 34700; break;
148 default: samplefrequency = 22050; break;
149 }
150 #endif
151 return;
152 }
153 }
154
155 /* Check for player fire sample reset */
156
157 if ((offset==3) || (offset==5))
158 {
159 if (lastnoise==70)
160 {
161 if ((offset==3) && (data==172))
162 {
163 nextdata5 = 25;
164 return;
165 }
166
167 if (offset==5)
168 {
169 if (data==nextdata5)
170 {
171 #ifdef FAKE_DEATH_SOUND
172 deathsound = 1; /* trigger death sound */
173 #else
174 deathsound = 2; /* trigger death sound */
175 #endif
176 lastnoise = 64; /* reset death sound */
177 }
178
179 nextdata5 = -1;
180 }
181
182 return;
183 }
184
185 if (lastnoise==69)
186 {
187 if ((offset==3) && (data==50))
188 {
189 nextdata5 = 50;
190 return;
191 }
192
193 if (offset==5)
194 {
195 if (data==nextdata5)
196 {
197 lastnoise = 64; /* reset laser sound */
198 }
199
200 nextdata5 = -1;
201 }
202 }
203
204 return;
205 }
206
207 /* Check to see what game sound should be playing */
208
209 if ((data > 60) && (data < 72) && (offset==6))
210 noise = data;
211 else
212 noise = lastnoise;
213
214 /* One day I'll do this... */
215
216 if (berzerknoisemulate)
217 {
218 return;
219 if (voicefrequency != 1750*(4-noise))
220 {
221 voicefrequency = 1750*(4-noise);
222 voicevolume = 85*noise;
223 }
224
225 if (noise)
226 {
227 sample_set_freq(2,voicefrequency);
228 sample_set_volume(2,voicevolume);
229 }
230 else
231 {
232 sample_set_volume(2,0);
233 voicevolume = 0;
234 }
235 }
236 else
237 {
238 if ((offset==6) && (lastnoise != noise)) /* Game sound effects */
239 {
240 switch (noise)
241 {
242 case 69 : /* shot sample */
243 sample_start(1,30,0);
244 break;
245 case 70 : /* baddie laser */
246 log_cb(RETRO_LOG_DEBUG, LOGPRE "Trying death sound");
247 switch(deathsound)
248 {
249 case 1 :
250 sample_start(2,33,0);
251 deathsound=0;
252 break;
253 case 2 :
254 sample_start(DEATH_CHANNEL,34,0);
255 deathsound=3;
256 break;
257 case 0 :
258 sample_start(2,31,0);
259 break;
260 }
261 break;
262 case 71 : /* kill baddie */
263 sample_start(3,32,0);
264 break;
265 default :
266 break;
267 }
268 }
269 lastnoise = noise; /* make sure we only play the sound once */
270
271 if (offset==4) /* Game voice sounds */
272 {
273 if (deathsound<2) /* no voices for real death sound */
274 {
275 if (lastvoice==24 && voice==27)
276 {
277 lastvoice=voice; /* catch for the 'chicken ayye' problem */
278 return;
279 }
280 sample_start(VOICE_CHANNEL,voice,0);
281 #ifdef VOICE_PITCH_MODULATION
282 sample_set_freq(VOICE_CHANNEL,samplefrequency);
283 #endif
284 lastvoice=voice;
285 }
286 }
287 } /* End of berzerknoisemulate */
288 }
289
WRITE_HANDLER(berzerk_sound_control_b_w)290 WRITE_HANDLER( berzerk_sound_control_b_w )
291 {
292 log_cb(RETRO_LOG_DEBUG, LOGPRE "B Data value %d and offset %d at %d\n", data, offset, lastfreq);
293 }
294
berzerk_sh_update(void)295 static void berzerk_sh_update(void)
296 {
297 voice_playing = !sample_playing(VOICE_CHANNEL);
298 if (deathsound==3 && sample_playing(DEATH_CHANNEL) == 0 && lastnoise != 70)
299 deathsound=0; /* reset death sound */
300 }
301
302
READ_HANDLER(berzerk_voiceboard_r)303 READ_HANDLER( berzerk_voiceboard_r )
304 {
305 if (!voice_playing)
306 return 0x00;
307 else
308 return 0x40;
309 }
310
311
312 struct Samplesinterface berzerk_samples_interface =
313 {
314 8, /* 8 channels */
315 25, /* volume */
316 sample_names
317 };
318
319 struct CustomSound_interface berzerk_custom_interface =
320 {
321 berzerk_sh_start,
322 0,
323 berzerk_sh_update
324 };
325