Ticket #8800: player2a.dif

File player2a.dif, 26.7 KB (added by SF/quietust, 17 years ago)

Amiga V2 sound patch

Line 
1Index: engines/scumm/player_v2a.cpp
2===================================================================
3--- engines/scumm/player_v2a.cpp (revision 30875)
4+++ engines/scumm/player_v2a.cpp (working copy)
5@@ -73,7 +73,7 @@
6 public:
7 V2A_Sound_Unsupported() { }
8 virtual void start(Player_MOD *mod, int id, const byte *data) {
9- warning("player_v2a - sound %i not supported yet", id);
10+ warning("player_v2a - sound %i not supported!", id);
11 }
12 virtual bool update() { return false; }
13 virtual void stop() { }
14@@ -375,9 +375,9 @@
15
16 // plays a single looped waveform starting at a specific frequency/volume, dropping in frequency and fading volume to zero
17 // used when Maniac Mansion explodes
18-class V2A_Sound_Special_ManiacNuclear : public V2A_Sound_Base<1> {
19+class V2A_Sound_Special_Maniac69 : public V2A_Sound_Base<1> {
20 public:
21- V2A_Sound_Special_ManiacNuclear(uint16 offset, uint16 size, uint16 freq, uint8 vol) :
22+ V2A_Sound_Special_Maniac69(uint16 offset, uint16 size, uint16 freq, uint8 vol) :
23 V2A_Sound_Base<1>(offset, size), _freq(freq), _vol(vol) { }
24 virtual void start(Player_MOD *mod, int id, const byte *data) {
25 _mod = mod;
26@@ -528,9 +528,9 @@
27
28 // plays a single looped waveform, starting at one frequency, bending down to another frequency, and then back up to the original frequency
29 // used for electronic noises
30-class V2A_Sound_Special_ManiacElectric : public V2A_Sound_Base<1> {
31+class V2A_Sound_Special_Maniac59 : public V2A_Sound_Base<1> {
32 public:
33- V2A_Sound_Special_ManiacElectric(uint16 offset, uint16 size, uint16 freq1, uint16 freq2, uint16 step, uint8 vol) :
34+ V2A_Sound_Special_Maniac59(uint16 offset, uint16 size, uint16 freq1, uint16 freq2, uint16 step, uint8 vol) :
35 V2A_Sound_Base<1>(offset, size), _freq1(freq1), _freq2(freq2), _step(step), _vol(vol) { }
36 virtual void start(Player_MOD *mod, int id, const byte *data) {
37 _mod = mod;
38@@ -573,7 +573,6 @@
39
40 // plays a single looped waveform, simultaneously bending the frequency downward and slowly fading volume to zero
41 // don't remember where this one is used
42-// old name: SlowPitchbendDownAndFadeout
43 class V2A_Sound_Special_Maniac61 : public V2A_Sound_Base<1> {
44 public:
45 V2A_Sound_Special_Maniac61(uint16 offset, uint16 size, uint16 freq1, uint16 freq2) :
46@@ -663,9 +662,9 @@
47
48 // intermittently plays a single waveform for a specified duration
49 // used when applying a wrench to a pipe
50-class V2A_Sound_Special_ManiacWrench : public V2A_Sound_Base<1> {
51+class V2A_Sound_Special_Maniac46 : public V2A_Sound_Base<1> {
52 public:
53- V2A_Sound_Special_ManiacWrench(uint16 offset, uint16 size, uint16 freq, uint8 vol, uint8 loopwidth, uint8 numloops) :
54+ V2A_Sound_Special_Maniac46(uint16 offset, uint16 size, uint16 freq, uint8 vol, uint8 loopwidth, uint8 numloops) :
55 V2A_Sound_Base<1>(offset, size), _freq(freq), _vol(vol), _loopwidth(loopwidth), _numloops(numloops) { }
56 virtual void start(Player_MOD *mod, int id, const byte *data) {
57 _mod = mod;
58@@ -755,7 +754,6 @@
59
60 // plays two looped waveforms pitch bending up at various predefined rates
61 // used for some sort of siren-like noise in Maniac Mansion
62-// old name: TwinSirenMulti
63 class V2A_Sound_Special_Maniac44 : public V2A_Sound_Base<2> {
64 public:
65 V2A_Sound_Special_Maniac44(uint16 offset1, uint16 size1, uint16 offset2, uint16 size2, uint16 freq1, uint16 freq2, uint8 vol) :
66@@ -821,9 +819,9 @@
67
68 // plays 4 looped waveforms, each at modulating frequencies
69 // used for the siren noise in Maniac Mansion
70-class V2A_Sound_Special_ManiacSiren : public V2A_Sound_Base<4> {
71+class V2A_Sound_Special_Maniac32 : public V2A_Sound_Base<4> {
72 public:
73- V2A_Sound_Special_ManiacSiren(uint16 offset1, uint16 size1, uint16 offset2, uint16 size2, uint8 vol) :
74+ V2A_Sound_Special_Maniac32(uint16 offset1, uint16 size1, uint16 offset2, uint16 size2, uint8 vol) :
75 _offset1(offset1), _size1(size1), _offset2(offset2), _size2(size2), _vol(vol) { }
76 virtual void start(Player_MOD *mod, int id, const byte *data) {
77 _mod = mod;
78@@ -894,7 +892,6 @@
79
80 // plays 4 looped waveforms
81 // some sort of laserbeam-like sound effect in Zak
82-// old name: QuadFreqLooped
83 class V2A_Sound_Special_Zak70 : public V2A_Sound_Base<4> {
84 public:
85 V2A_Sound_Special_Zak70(uint16 offset, uint16 size, uint16 freq1, uint16 freq2, uint16 freq3, uint16 freq4, uint8 vol) :
86@@ -930,7 +927,6 @@
87
88 // plays 4 looped waveforms and fades volume to zero after a specific delay
89 // some whooshing-type sound in Zak
90-// old name: QuadFreqFadeout
91 class V2A_Sound_Special_Zak101 : public V2A_Sound_Special_Zak70 {
92 public:
93 V2A_Sound_Special_Zak101(uint16 offset, uint16 size, uint16 freq1, uint16 freq2, uint16 freq3, uint16 freq4, uint8 vol, uint16 dur) :
94@@ -959,7 +955,6 @@
95
96 // plays a single looped waveform and slowly fades volume to zero
97 // another whooshing-type noise in Zak
98-// old name: SingleFadeout
99 class V2A_Sound_Special_Zak37 : public V2A_Sound_Base<1> {
100 public:
101 V2A_Sound_Special_Zak37(uint16 offset, uint16 size, uint16 freq, uint8 vol) :
102@@ -1092,10 +1087,10 @@
103 };
104
105 // plays a single looped waveform, bending the frequency upward at a varying rate
106-// used in Zak for the tram on Mars (?)
107-class V2A_Sound_Special_ZakTram : public V2A_Sound_Base<1> {
108+// used for the tram on Mars (?)
109+class V2A_Sound_Special_Zak99 : public V2A_Sound_Base<1> {
110 public:
111- V2A_Sound_Special_ZakTram(uint16 offset, uint16 size, uint16 freq1, uint16 freq2, uint8 vol) :
112+ V2A_Sound_Special_Zak99(uint16 offset, uint16 size, uint16 freq1, uint16 freq2, uint8 vol) :
113 V2A_Sound_Base<1>(offset, size), _freq1(freq1), _freq2(freq2), _vol(vol) { }
114 virtual void start(Player_MOD *mod, int id, const byte *data) {
115 _mod = mod;
116@@ -1158,7 +1153,8 @@
117 _vol--;
118 if (_vol)
119 _mod->setChannelVol(_id, _vol);
120- else return false;
121+ else
122+ return false;
123 } else if (!--_loop) {
124 _mod->stopChannel(_id);
125 char *tmp_data = (char *)malloc(_size2);
126@@ -1179,8 +1175,566 @@
127 int _loop;
128 };
129
130-#define CRCToSound(CRC, SOUND) \
131- if (crc == CRC) \
132+// plays 2 looped waveforms at different frequencies, pulsing at different frequencies and ramping the volume up and down once
133+// probably used for some sort of alarm sound
134+class V2A_Sound_Special_Zak110 : public V2A_Sound_Base<2> {
135+public:
136+ V2A_Sound_Special_Zak110(uint16 offset1, uint16 size1, uint16 offset2, uint16 size2, uint16 freq1, uint16 freq2) :
137+ _offset1(offset1), _size1(size1), _offset2(offset2), _size2(size2), _freq1(freq1), _freq2(freq2) { }
138+ virtual void start(Player_MOD *mod, int id, const byte *data) {
139+ _mod = mod;
140+ _id = id;
141+ _data = (char *)malloc(READ_LE_UINT16(data));
142+ memcpy(_data, data, READ_LE_UINT16(data));
143+
144+ _loopnum = 0;
145+ _vol = 0x1500;
146+ _beepcount = 0;
147+ }
148+ virtual bool update() {
149+ char *tmp_data;
150+ assert(_id);
151+
152+ int vol = (((_vol >> 7) & 0x7E) | ((_vol >> 15) & 0x01));
153+ _beepcount++;
154+
155+ switch (_beepcount & 0x3)
156+ {
157+ case 0:
158+ _mod->stopChannel(_id | 0x000);
159+ break;
160+ case 1:
161+ tmp_data = (char *)malloc(_size1);
162+ memcpy(tmp_data, _data + _offset1, _size1);
163+ _mod->startChannel(_id | 0x000, tmp_data, _size1, BASE_FREQUENCY / _freq1, vol, 0, _size1, -127);
164+ break;
165+ default:
166+ _mod->setChannelVol(_id | 0x000, vol);
167+ break;
168+ }
169+
170+ switch (_beepcount & 0x7)
171+ {
172+ case 0:
173+ _mod->stopChannel(_id | 0x100);
174+ break;
175+ case 1:
176+ tmp_data = (char *)malloc(_size2);
177+ memcpy(tmp_data, _data + _offset2, _size2);
178+ _mod->startChannel(_id | 0x100, tmp_data, _size2, BASE_FREQUENCY / _freq2, vol, 0, _size2, 127);
179+ break;
180+ default:
181+ _mod->setChannelVol(_id | 0x100, vol);
182+ break;
183+ }
184+
185+ if (_loopnum == 0) {
186+ _vol += 0x80;
187+ if (_vol == 0x4000) {
188+ _vol = 0x3F00;
189+ _loopnum = 1;
190+ }
191+ } else if (_loopnum == 1) {
192+ _vol -= 0x20;
193+ if (_vol == 0x2000)
194+ _loopnum = 2;
195+ }
196+ return true;
197+ }
198+private:
199+ const uint16 _offset1;
200+ const uint16 _size1;
201+ const uint16 _offset2;
202+ const uint16 _size2;
203+ const uint16 _freq1;
204+ const uint16 _freq2;
205+
206+ uint16 _loopnum;
207+ uint16 _vol;
208+ uint16 _beepcount;
209+};
210+
211+// plays a stereo siren, sweeping up and down quickly several times before sweeping up slowly, stopping, and then going silent
212+// probably used for some sort of alarm sound
213+class V2A_Sound_Special_Zak32 : public V2A_Sound_Base<2> {
214+public:
215+ V2A_Sound_Special_Zak32(uint16 offset1, uint16 offset2, uint16 size1, uint16 size2) :
216+ _offset1(offset1), _offset2(offset2), _size1(size1), _size2(size2) { }
217+ virtual void start(Player_MOD *mod, int id, const byte *data) {
218+ _mod = mod;
219+ _id = id;
220+ _data = (char *)malloc(READ_LE_UINT16(data));
221+ memcpy(_data, data, READ_LE_UINT16(data));
222+
223+ _loopnum = 1;
224+ _freqmod = -4;
225+ _freq = 0x00C8;
226+
227+ char *tmp_data1 = (char *)malloc(_size1);
228+ char *tmp_data2 = (char *)malloc(_size1);
229+ memcpy(tmp_data1, _data + _offset1, _size1);
230+ memcpy(tmp_data2, _data + _offset1, _size1);
231+ _mod->startChannel(_id | 0x000, tmp_data1, _size1, BASE_FREQUENCY / _freq, 0x7F, 0, _size1, -127);
232+ _mod->startChannel(_id | 0x100, tmp_data2, _size1, BASE_FREQUENCY / (_freq + 3), 0x7F, 0, _size1, 127);
233+ }
234+ virtual bool update() {
235+ assert(_id);
236+
237+ if (_loopnum < 7) {
238+ _mod->setChannelFreq(_id | 0x000, BASE_FREQUENCY / _freq);
239+ _mod->setChannelFreq(_id | 0x100, BASE_FREQUENCY / (_freq + 3));
240+ _freq += _freqmod;
241+ if (_freq <= 0x80)
242+ _freqmod = -_freqmod;
243+ else if (_freq >= 0xC8) {
244+ _freqmod = -_freqmod;
245+ _loopnum++;
246+ if (_loopnum == 7) {
247+ _freq = 0x00C8;
248+ _freqmod = 2;
249+ }
250+ }
251+ return true;
252+ } else {
253+ if (_loopnum == 7) {
254+ _mod->stopChannel(_id | 0x000);
255+ _mod->stopChannel(_id | 0x100);
256+
257+ char *tmp_data1 = (char *)malloc(_size2);
258+ char *tmp_data2 = (char *)malloc(_size2);
259+ memcpy(tmp_data1, _data + _offset2, _size2);
260+ memcpy(tmp_data2, _data + _offset2, _size2);
261+ _mod->startChannel(_id | 0x000, tmp_data1, _size2, BASE_FREQUENCY / (_freq), 0x7F, 0, _size2, -127);
262+ _mod->startChannel(_id | 0x100, tmp_data2, _size2, BASE_FREQUENCY / (_freq + 3), 0x7F, 0, _size2, 127);
263+ _loopnum++;
264+ } else {
265+ _mod->setChannelFreq(_id | 0x000, BASE_FREQUENCY / _freq);
266+ _mod->setChannelFreq(_id | 0x100, BASE_FREQUENCY / (_freq + 3));
267+ }
268+ _freq -= _freqmod;
269+ if (_freq > 0)
270+ return true;
271+ else
272+ return false;
273+ }
274+ }
275+private:
276+ const uint16 _offset1;
277+ const uint16 _offset2;
278+ const uint16 _size1;
279+ const uint16 _size2;
280+
281+ uint16 _loopnum;
282+ int16 _freqmod;
283+ uint16 _freq;
284+};
285+
286+// plays a looped waveform, increasing frequency and reducing volume once the frequency reaches a certain point
287+// probably used for some sort of vehicle sound
288+class V2A_Sound_Special_Zak52 : public V2A_Sound_Base<1> {
289+public:
290+ V2A_Sound_Special_Zak52(uint16 offset, uint16 size) :
291+ _offset(offset), _size(size) { }
292+ virtual void start(Player_MOD *mod, int id, const byte *data) {
293+ _mod = mod;
294+ _id = id;
295+ _data = (char *)malloc(READ_LE_UINT16(data));
296+ memcpy(_data, data, READ_LE_UINT16(data));
297+
298+ _curfreq = 0x0312;
299+
300+ char *tmp_data = (char *)malloc(_size);
301+ memcpy(tmp_data, _data + _offset, _size);
302+ _mod->startChannel(_id | 0x000, tmp_data, _size, BASE_FREQUENCY / _curfreq, 0xFF, 0, _size, -127);
303+ }
304+ virtual bool update() {
305+ assert(_id);
306+ int vol = (_curfreq - 0xC8) >> 3;
307+ if (vol > 0x3F)
308+ vol = 0x3F;
309+ vol = (vol << 2) | (vol >> 4);
310+ _mod->setChannelFreq(_id | 0x000, BASE_FREQUENCY / _curfreq);
311+ _mod->setChannelVol(_id | 0x000, vol);
312+ _curfreq--;
313+ if (_curfreq >= 0x107)
314+ return true;
315+ else
316+ return false;
317+ }
318+private:
319+ const uint16 _offset;
320+ const uint16 _size;
321+
322+ uint16 _curfreq;
323+};
324+
325+// plays a looped waveform, sweeping the frequency up while modulating it (alternating which channel updates) and fading volume out
326+// dunno what it's for
327+class V2A_Sound_Special_Zak61 : public V2A_Sound_Base<2> {
328+public:
329+ V2A_Sound_Special_Zak61(uint16 offset, uint16 size) :
330+ _offset(offset), _size(size) { }
331+ virtual void start(Player_MOD *mod, int id, const byte *data) {
332+ _mod = mod;
333+ _id = id;
334+ _data = (char *)malloc(READ_LE_UINT16(data));
335+ memcpy(_data, data, READ_LE_UINT16(data));
336+
337+ _loop = 1;
338+ _curfreq = 0x01F4;
339+
340+ char *tmp_data = (char *)malloc(_size);
341+ memcpy(tmp_data, _data + _offset, _size);
342+ _mod->startChannel(_id | 0x000, tmp_data, _size, BASE_FREQUENCY / _curfreq, 0x7F, 0, _size, -127);
343+ // start 2nd channel silent
344+ _mod->startChannel(_id | 0x100, tmp_data, _size, BASE_FREQUENCY / _curfreq, 0, 0, _size, 127);
345+ }
346+ virtual bool update() {
347+ assert(_id);
348+ int freq = (_loop << 4) + _curfreq;
349+ int vol = freq - 0x76;
350+ if (vol > 0x3F)
351+ vol = 0x3F;
352+ vol = (vol << 1) | (vol >> 5);
353+ switch (_loop)
354+ {
355+ case 0:
356+ _mod->setChannelFreq(_id | 0x000, BASE_FREQUENCY / freq);
357+ _mod->setChannelVol(_id | 0x000, vol);
358+ break;
359+ case 1:
360+ _mod->setChannelFreq(_id | 0x100, BASE_FREQUENCY / freq);
361+ _mod->setChannelVol(_id | 0x100, vol);
362+ break;
363+ }
364+ _loop = (_loop + 1) & 3;
365+ if (!_loop) {
366+ _curfreq -= 4;
367+ if (_curfreq <= 0x80)
368+ return false;
369+ }
370+ return true;
371+ }
372+private:
373+ const uint16 _offset;
374+ const uint16 _size;
375+
376+ uint16 _loop;
377+ uint16 _curfreq;
378+};
379+
380+// just like Zak61, but sweeps frequency in the other direction
381+// dunno what it's for
382+class V2A_Sound_Special_Zak62 : public V2A_Sound_Base<2> {
383+public:
384+ V2A_Sound_Special_Zak62(uint16 offset, uint16 size) :
385+ _offset(offset), _size(size) { }
386+ virtual void start(Player_MOD *mod, int id, const byte *data) {
387+ _mod = mod;
388+ _id = id;
389+ _data = (char *)malloc(READ_LE_UINT16(data));
390+ memcpy(_data, data, READ_LE_UINT16(data));
391+
392+ _loop = 1;
393+ _curfreq = 0x0080;
394+
395+ char *tmp_data = (char *)malloc(_size);
396+ memcpy(tmp_data, _data + _offset, _size);
397+ _mod->startChannel(_id | 0x000, tmp_data, _size, BASE_FREQUENCY / _curfreq, 0x7F, 0, _size, -127);
398+ // start 2nd channel silent
399+ _mod->startChannel(_id | 0x100, tmp_data, _size, BASE_FREQUENCY / _curfreq, 0, 0, _size, 127);
400+ }
401+ virtual bool update() {
402+ assert(_id);
403+ int freq = (_loop << 4) + _curfreq;
404+ int vol = 0x0200 - freq;
405+ if (vol > 0x3F)
406+ vol = 0x3F;
407+ vol = (vol << 1) | (vol >> 5);
408+ switch (_loop)
409+ {
410+ case 0:
411+ _mod->setChannelFreq(_id | 0x000, BASE_FREQUENCY / freq);
412+ _mod->setChannelVol(_id | 0x000, vol);
413+ break;
414+ case 1:
415+ _mod->setChannelFreq(_id | 0x100, BASE_FREQUENCY / freq);
416+ _mod->setChannelVol(_id | 0x100, vol);
417+ break;
418+ }
419+ _loop = (_loop + 1) & 3;
420+ if (!_loop) {
421+ _curfreq += 4;
422+ if (_curfreq >= 0x01F4)
423+ return false;
424+ }
425+ return true;
426+ }
427+private:
428+ const uint16 _offset;
429+ const uint16 _size;
430+
431+ uint16 _loop;
432+ uint16 _curfreq;
433+};
434+
435+// plays a series of double-looped sounds at varying frequencies and delays, very specialized
436+// sounds like some sort of creature growl/scream
437+class V2A_Sound_Special_Zak82 : public V2A_Sound_Base<4> {
438+public:
439+ V2A_Sound_Special_Zak82(uint16 offset, uint16 size) :
440+ _offset(offset), _size(size) { }
441+ virtual void start(Player_MOD *mod, int id, const byte *data) {
442+ _mod = mod;
443+ _id = id;
444+ _data = (char *)malloc(READ_LE_UINT16(data));
445+ memcpy(_data, data, READ_LE_UINT16(data));
446+
447+ // Wait values were to insure playing an integral number of loops on each sample
448+ // and have been adjusted to reflect the actual duration spent playing
449+ _loop = 0;
450+ _playctr = 240;
451+ _wait1 = 76; // was 39, extended to loop twice
452+ _wait2 = 10000;
453+ _wait3 = 10000;
454+ _wait4 = 10000;
455+
456+ int size = 2000;
457+ int offset = _offset;
458+ assert(offset + size < _offset + _size);
459+ char *tmp_data = (char *)malloc(size);
460+ memcpy(tmp_data, _data + offset, size);
461+ _mod->startChannel(_id | 0x000, tmp_data, size, BASE_FREQUENCY / 0x0479, 0xFF, 0, size);
462+ }
463+ virtual bool update() {
464+ assert(_id);
465+ char *tmp_data1, *tmp_data2;
466+ int size, offset = _offset;
467+
468+ if (!--_wait1) {
469+ _wait1 = 10000;
470+ _mod->stopChannel(_id | 0x000);
471+ } else if (!--_wait2) {
472+ _wait2 = 10000;
473+ _mod->stopChannel(_id | 0x000);
474+ } else if (!--_wait3) {
475+ _wait3 = 10000;
476+ _mod->stopChannel(_id | 0x200);
477+ } else if (!--_wait4) {
478+ _wait4 = 10000;
479+ _mod->stopChannel(_id | 0x100);
480+ _mod->stopChannel(_id | 0x300);
481+ }
482+ if (--_playctr)
483+ return true;
484+
485+ switch (++_loop)
486+ {
487+ case 1:
488+ size = 6300;
489+ offset += 0x07D0;
490+ assert(offset + size <_offset + _size);
491+ tmp_data1 = (char *)malloc(size);
492+ memcpy(tmp_data1, _data + offset, size);
493+ _mod->startChannel(_id | 0x000, tmp_data1, size, BASE_FREQUENCY / 0x0479, 0x7F, 0, size, -127);
494+ _wait2 = 241; // was 120, extended to loop twice
495+ _playctr = 10;
496+ break;
497+ case 2:
498+ size = 6292;
499+ offset += 0x206C;
500+ assert(offset + size < _offset + _size);
501+ tmp_data1 = (char *)malloc(size);
502+ memcpy(tmp_data1, _data + offset, size);
503+ _mod->startChannel(_id | 0x200, tmp_data1, size, BASE_FREQUENCY / 0x0384, 0x7F, 0, size, 127);
504+ _wait3 = 189; // was 94, extended to loop twice
505+ _playctr = 20;
506+ break;
507+ case 3:
508+ size = 6300;
509+ offset += 0x07D0;
510+ assert(offset + size < _offset + _size);
511+ tmp_data1 = (char *)malloc(size);
512+ tmp_data2 = (char *)malloc(size);
513+ memcpy(tmp_data1, _data + offset, size);
514+ memcpy(tmp_data2, _data + offset, size);
515+ _mod->startChannel(_id | 0x100, tmp_data1, size, BASE_FREQUENCY / 0x01E0, 0x7F, 0, size, 127);
516+ _mod->startChannel(_id | 0x300, tmp_data2, size, BASE_FREQUENCY / 0x01E0, 0x7F, 0, size, -127);
517+ _wait4 = 101; // was 50, extended to loop twice
518+ _playctr = 120;
519+ break;
520+ default:
521+ return false;
522+ }
523+ return true;
524+ }
525+private:
526+ const uint16 _offset;
527+ const uint16 _size;
528+
529+ uint16 _loop;
530+ uint16 _playctr;
531+ uint16 _wait1;
532+ uint16 _wait2;
533+ uint16 _wait3;
534+ uint16 _wait4;
535+};
536+
537+// plays a "ding" (volume 0-max-0) followed by a sound sample, a pause, then loops again
538+// dunno what this is for
539+class V2A_Sound_Special_Zak86 : public V2A_Sound_Base<1> {
540+public:
541+ V2A_Sound_Special_Zak86(uint16 offset, uint16 size) :
542+ _offset(offset), _size(size) { }
543+ virtual void start(Player_MOD *mod, int id, const byte *data) {
544+ _mod = mod;
545+ _id = id;
546+ _data = (char *)malloc(READ_LE_UINT16(data));
547+ memcpy(_data, data, READ_LE_UINT16(data));
548+
549+ _mode = 0;
550+ _vol = 0;
551+ _volmod = 16;
552+
553+ int size = 32;
554+ int offset = _offset + 0x2B8E;
555+ assert(offset + size < _offset + _size);
556+ char *tmp_data = (char *)malloc(size);
557+ memcpy(tmp_data, _data + offset, size);
558+ _mod->startChannel(_id | 0x000, tmp_data, size, BASE_FREQUENCY / 0x0096, 0, 0, size, 0);
559+ }
560+ virtual bool update() {
561+ assert(_id);
562+ int size, offset;
563+ char *tmp_data;
564+
565+ switch (_mode)
566+ {
567+ case 0:
568+ _mod->setChannelVol(_id | 0x000, (_vol << 2) | (_vol >> 4));
569+ if (_vol + _volmod > 0) {
570+ _vol += _volmod;
571+ if (_vol > 0x3F) {
572+ _vol = 0x3F;
573+ _volmod = -4;
574+ }
575+ return true;
576+ }
577+ _mod->stopChannel(_id | 0x000);
578+ _mode = 1;
579+
580+ size = 0x2B8E;
581+ offset = _offset;
582+ assert(offset + size < _offset + _size);
583+ tmp_data = (char *)malloc(size);
584+ memcpy(tmp_data, _data + offset, size);
585+ _mod->startChannel(_id | 0x000, tmp_data, size, BASE_FREQUENCY / 0x0152, 0x3F);
586+ _volmod = 100;
587+ break;
588+ case 1:
589+ if (!--_volmod) {
590+ size = 32;
591+ offset = _offset + 0x2B8E;
592+ assert(offset + size < _offset + _size);
593+ tmp_data = (char *)malloc(size);
594+ memcpy(tmp_data, _data + offset, size);
595+ _mod->startChannel(_id | 0x000, tmp_data, size, BASE_FREQUENCY / 0x0096, 0, 0, size, 0);
596+ _mode = 0;
597+ _vol = 0;
598+ _volmod = 16;
599+ }
600+ break;
601+ }
602+ return true;
603+ }
604+private:
605+ const uint16 _offset;
606+ const uint16 _size;
607+
608+ uint16 _mode;
609+ uint16 _vol;
610+ int16 _volmod;
611+};
612+
613+// modulates volume on 4 samples, frequency on only 2 of them
614+// some sort of droning machine, perhaps?
615+class V2A_Sound_Special_Zak98 : public V2A_Sound_Base<4> {
616+public:
617+ V2A_Sound_Special_Zak98(uint16 offset, uint16 size) :
618+ _offset(offset), _size(size) { }
619+ virtual void start(Player_MOD *mod, int id, const byte *data) {
620+ _mod = mod;
621+ _id = id;
622+ _data = (char *)malloc(READ_LE_UINT16(data));
623+ memcpy(_data, data, READ_LE_UINT16(data));
624+
625+ _freq[0] = 0x1E0;
626+ _freq[1] = 0x3E8;
627+ _freq[2] = 0x200;
628+ _freq[3] = 0x408;
629+ _vol[0] = 0x3F;
630+ _vol[1] = 0x3F;
631+ _vol[2] = 0x3F;
632+ _vol[3] = 0x3F;
633+ _freqmod = 4;
634+ _volmod[0] = -2;
635+ _volmod[1] = -1;
636+
637+ char *tmp_data1 = (char *)malloc(_size);
638+ char *tmp_data2 = (char *)malloc(_size);
639+ char *tmp_data3 = (char *)malloc(_size);
640+ char *tmp_data4 = (char *)malloc(_size);
641+ memcpy(tmp_data1, _data + _offset, _size);
642+ memcpy(tmp_data2, _data + _offset, _size);
643+ memcpy(tmp_data3, _data + _offset, _size);
644+ memcpy(tmp_data4, _data + _offset, _size);
645+ _mod->startChannel(_id | 0x000, tmp_data1, _size, BASE_FREQUENCY / _freq[0], _vol[0], 0, _size, -127);
646+ _mod->startChannel(_id | 0x100, tmp_data2, _size, BASE_FREQUENCY / _freq[1], _vol[1], 0, _size, 127);
647+ _mod->startChannel(_id | 0x200, tmp_data3, _size, BASE_FREQUENCY / _freq[2], _vol[2], 0, _size, 127);
648+ _mod->startChannel(_id | 0x300, tmp_data4, _size, BASE_FREQUENCY / _freq[3], _vol[3], 0, _size, -127);
649+ }
650+ virtual bool update() {
651+ assert(_id);
652+ const uint16 _minvol[2] = {0x2E,0x32};
653+ int i;
654+ for (i = 0; i < 4; i++) {
655+ _mod->setChannelFreq(_id | (i << 8), BASE_FREQUENCY / _freq[i]);
656+ _mod->setChannelVol(_id | (i << 8), _vol[i]);
657+ }
658+ for (i = 0; i < 2; i++) {
659+ _vol[i] += _volmod[i];
660+ if (_vol[i] > 0x3F) {
661+ _vol[i] = 0x3F;
662+ _volmod[i] = -_volmod[i];
663+ } else if (_vol[i] < _minvol[i]) {
664+ _vol[i] = _minvol[i];
665+ _volmod[i] = -_volmod[i];
666+ }
667+ _vol[i+2] = _vol[i];
668+ }
669+ _freq[0] += _freqmod;
670+ if (_freq[0] > 0x2BC) {
671+ _freq[0] = 0x2BC;
672+ _freqmod = -_freqmod;
673+ } else if (_freq[0] < 0x1E0) {
674+ _freq[0] = 0x1E0;
675+ _freqmod = -_freqmod;
676+ }
677+ _freq[2] = _freq[0] + 0x20;
678+ return true;
679+ }
680+private:
681+ const uint16 _offset;
682+ const uint16 _size;
683+
684+ uint16 _freq[4];
685+ uint16 _vol[4];
686+ int16 _freqmod;
687+ int16 _volmod[2];
688+};
689+
690+#define CRCToSound(CRC, SOUND) \
691+ if (crc == CRC) \
692 return new SOUND
693
694 static V2A_Sound *findSound (unsigned long crc) {
695@@ -1210,18 +1764,18 @@
696 CRCToSound(0x62D5B11F, V2A_Sound_Single(0x00AE,0x165C,0x01CB,0x3F)); // Maniac 27
697 CRCToSound(0x3AB22CB5, V2A_Sound_Single(0x00AE,0x294E,0x012A,0x3F)); // Maniac 62
698 CRCToSound(0x2D70BBE9, V2A_Sound_SingleLoopedPitchbend(0x00B4,0x1702,0x03E8,0x0190,0x3F,5)); // Maniac 64
699- CRCToSound(0xFA4C1B1C, V2A_Sound_Special_ManiacNuclear(0x00B2,0x1702,0x0190,0x3F)); // Maniac 69
700+ CRCToSound(0xFA4C1B1C, V2A_Sound_Special_Maniac69(0x00B2,0x1702,0x0190,0x3F)); // Maniac 69
701 CRCToSound(0x19D50D67, V2A_Sound_Special_ManiacDing(0x00B6,0x0020,0x00C8,16,2)); // Maniac 14
702 CRCToSound(0x3E6FBE15, V2A_Sound_Special_ManiacTentacle(0x00B2,0x0010,0x007C,0x016D,1)); // Maniac 25
703 CRCToSound(0x5305753C, V2A_Sound_Special_ManiacTentacle(0x00B2,0x0010,0x007C,0x016D,7)); // Maniac 36
704- CRCToSound(0x28895106, V2A_Sound_Special_ManiacElectric(0x00C0,0x00FE,0x00E9,0x0111,4,0x0A)); // Maniac 59
705+ CRCToSound(0x28895106, V2A_Sound_Special_Maniac59(0x00C0,0x00FE,0x00E9,0x0111,4,0x0A)); // Maniac 59
706 CRCToSound(0xB641ACF6, V2A_Sound_Special_Maniac61(0x00C8,0x0100,0x00C8,0x01C2)); // Maniac 61
707 CRCToSound(0xE1A91583, V2A_Sound_Special_ManiacPhone(0x00D0,0x0040,0x007C,0x3F,0x007B,0x3F,0x3C,5,6)); // Maniac 23
708 CRCToSound(0x64816ED5, V2A_Sound_Special_ManiacPhone(0x00D0,0x0040,0x00BE,0x37,0x00BD,0x37,0x3C,5,6)); // Maniac 24
709- CRCToSound(0x639D72C2, V2A_Sound_Special_ManiacWrench(0x00D0,0x10A4,0x0080,0x3F,0x28,3)); // Maniac 46
710+ CRCToSound(0x639D72C2, V2A_Sound_Special_Maniac46(0x00D0,0x10A4,0x0080,0x3F,0x28,3)); // Maniac 46
711 CRCToSound(0xE8826D92, V2A_Sound_Special_ManiacTypewriter(0x00EC,0x025A,0x023C,0x3F,8,(const uint8 *)"\x20\x41\x04\x21\x08\x10\x13\x07", true)); // Maniac 45
712 CRCToSound(0xEDFF3D41, V2A_Sound_Single(0x00F8,0x2ADE,0x01F8,0x3F)); // Maniac 42 (this should echo, but it's barely noticeable and I don't feel like doing it)
713- CRCToSound(0x15606D06, V2A_Sound_Special_ManiacSiren(0x0148,0x0020,0x0168,0x0020,0x3F)); // Maniac 32
714+ CRCToSound(0x15606D06, V2A_Sound_Special_Maniac32(0x0148,0x0020,0x0168,0x0020,0x3F)); // Maniac 32
715 CRCToSound(0x753EAFE3, V2A_Sound_Special_Maniac44(0x017C,0x0010,0x018C,0x0020,0x00C8,0x0080,0x3F)); // Maniac 44
716 CRCToSound(0xB1AB065C, V2A_Sound_Music(0x0032,0x00B2,0x08B2,0x1222,0x1A52,0x23C2,0x3074,false)); // Maniac 50
717 CRCToSound(0x091F5D9C, V2A_Sound_Music(0x0032,0x0132,0x0932,0x1802,0x23D2,0x3EA2,0x4F04,false)); // Maniac 58
718@@ -1267,21 +1821,21 @@
719 CRCToSound(0xC0DD2089, V2A_Sound_Special_ZakStereoDing(0x00BE,0x0020,0x009C,0x009B,8,1)); // Zak 75
720 CRCToSound(0x627DFD92, V2A_Sound_Special_ZakStereoDing(0x00BE,0x0020,0x008B,0x008A,8,1)); // Zak 76
721 CRCToSound(0x703E05C1, V2A_Sound_Special_ZakStereoDing(0x00BE,0x0020,0x007C,0x007B,8,1)); // Zak 77
722- CRCToSound(0xB0F77006, V2A_Sound_Unsupported()); // Zak 52
723+ CRCToSound(0xB0F77006, V2A_Sound_Special_Zak52(0x00B0,0x01BC)); // Zak 52
724 CRCToSound(0x5AE9D6A7, V2A_Sound_Special_ZakAirplane(0x00CA,0x22A4,0x0113,0x0227)); // Zak 109
725 CRCToSound(0xABE0D3B0, V2A_Sound_Special_ZakAirplane(0x00CE,0x22A4,0x0227,0x0113)); // Zak 105
726 CRCToSound(0x788CC749, V2A_Sound_Special_Zak71(0x00C8,0x0B37)); // Zak 71
727- CRCToSound(0x2E2AB1FA, V2A_Sound_Special_ZakTram(0x00D4,0x04F0,0x0FE3,0x0080,0x3F)); // Zak 99
728+ CRCToSound(0x2E2AB1FA, V2A_Sound_Special_Zak99(0x00D4,0x04F0,0x0FE3,0x0080,0x3F)); // Zak 99
729 CRCToSound(0x1304CF20, V2A_Sound_Special_ManiacTypewriter(0x00DC,0x0624,0x023C,0x3C,2,(const uint8 *)"\x14\x11",false)); // Zak 79
730 CRCToSound(0xAE68ED91, V2A_Sound_Special_Zak54(0x00D4,0x1A25,0x1E1E,0x0B80,0x01F4)); // Zak 54
731- CRCToSound(0xA4F40F97, V2A_Sound_Unsupported()); // Zak 61
732- CRCToSound(0x348F85CE, V2A_Sound_Unsupported()); // Zak 62
733+ CRCToSound(0xA4F40F97, V2A_Sound_Special_Zak61(0x00E4,0x0020)); // Zak 61
734+ CRCToSound(0x348F85CE, V2A_Sound_Special_Zak62(0x00E4,0x0020)); // Zak 62
735 CRCToSound(0xD473AB86, V2A_Sound_Special_ManiacTypewriter(0x0122,0x03E8,0x00BE,0x3F,7,(const uint8 *)"\x0F\x0B\x04\x0F\x1E\x0F\x66",false)); // Zak 46
736- CRCToSound(0x84A0BA90, V2A_Sound_Unsupported()); // Zak 110
737- CRCToSound(0x92680D9F, V2A_Sound_Unsupported()); // Zak 32
738- CRCToSound(0xABFFDB02, V2A_Sound_Unsupported()); // Zak 86
739- CRCToSound(0x41045447, V2A_Sound_Unsupported()); // Zak 98
740- CRCToSound(0xC8EEBD34, V2A_Sound_Unsupported()); // Zak 82
741+ CRCToSound(0x84A0BA90, V2A_Sound_Special_Zak110(0x0126,0x0040,0x0136,0x0080,0x007C,0x0087)); // Zak 110
742+ CRCToSound(0x92680D9F, V2A_Sound_Special_Zak32(0x0140,0x0150,0x0010,0x0010)); // Zak 32
743+ CRCToSound(0xABFFDB02, V2A_Sound_Special_Zak86(0x01A2,0x2BAE)); // Zak 86
744+ CRCToSound(0x41045447, V2A_Sound_Special_Zak98(0x017A,0x0020)); // Zak 98
745+ CRCToSound(0xC8EEBD34, V2A_Sound_Special_Zak82(0x01A6,0x3900)); // Zak 82
746 CRCToSound(0x42F9469F, V2A_Sound_Music(0x05F6,0x0636,0x0456,0x0516,0x05D6,0x05E6,0x0A36,true)); // Zak 96
747 CRCToSound(0x038BBD78, V2A_Sound_Music(0x054E,0x05CE,0x044E,0x04BE,0x052E,0x053E,0x0BCE,true)); // Zak 85
748 CRCToSound(0x06FFADC5, V2A_Sound_Music(0x0626,0x0686,0x0446,0x04F6,0x0606,0x0616,0x0C86,true)); // Zak 87