1 /* ScummVM - Graphic Adventure Engine
2 *
3 * ScummVM is the legal property of its developers, whose names
4 * are too numerous to list here. Please refer to the COPYRIGHT
5 * file distributed with this source distribution.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 *
21 */
22
23
24 #include "common/scummsys.h"
25 #include "scumm/scumm.h"
26 #include "scumm/imuse_digi/dimuse.h"
27 #include "scumm/imuse_digi/dimuse_tables.h"
28
29 namespace Scumm {
30
31 #define DIG_STATE_OFFSET 11
32 #define DIG_SEQ_OFFSET (DIG_STATE_OFFSET + 65)
33 #define COMI_STATE_OFFSET 3
34
setDigMusicState(int stateId)35 void IMuseDigital::setDigMusicState(int stateId) {
36 int l, num = -1;
37
38 for (l = 0; _digStateMusicTable[l].soundId != -1; l++) {
39 if ((_digStateMusicTable[l].soundId == stateId)) {
40 debug(5, "Set music state: %s, %s", _digStateMusicTable[l].name, _digStateMusicTable[l].filename);
41 num = l;
42 break;
43 }
44 }
45
46 if (num == -1) {
47 for (l = 0; _digStateMusicMap[l].roomId != -1; l++) {
48 if ((_digStateMusicMap[l].roomId == stateId)) {
49 break;
50 }
51 }
52 num = l;
53
54 int offset = _attributes[_digStateMusicMap[num].offset];
55 if (offset == 0) {
56 if (_attributes[_digStateMusicMap[num].attribPos] != 0) {
57 num = _digStateMusicMap[num].stateIndex3;
58 } else {
59 num = _digStateMusicMap[num].stateIndex1;
60 }
61 } else {
62 int stateIndex2 = _digStateMusicMap[num].stateIndex2;
63 if (stateIndex2 == 0) {
64 num = _digStateMusicMap[num].stateIndex1 + offset;
65 } else {
66 num = stateIndex2;
67 }
68 }
69 }
70
71 debug(5, "Set music state: %s, %s", _digStateMusicTable[num].name, _digStateMusicTable[num].filename);
72
73 if (_curMusicState == num)
74 return;
75
76 if (_curMusicSeq == 0) {
77 if (num == 0)
78 playDigMusic(NULL, &_digStateMusicTable[0], num, false);
79 else
80 playDigMusic(_digStateMusicTable[num].name, &_digStateMusicTable[num], num, false);
81 }
82
83 _curMusicState = num;
84 }
85
setDigMusicSequence(int seqId)86 void IMuseDigital::setDigMusicSequence(int seqId) {
87 int l, num = -1;
88
89 if (seqId == 0)
90 seqId = 2000;
91
92 for (l = 0; _digSeqMusicTable[l].soundId != -1; l++) {
93 if ((_digSeqMusicTable[l].soundId == seqId)) {
94 debug(5, "Set music sequence: %s, %s", _digSeqMusicTable[l].name, _digSeqMusicTable[l].filename);
95 num = l;
96 break;
97 }
98 }
99
100 if (num == -1)
101 return;
102
103 if (_curMusicSeq == num)
104 return;
105
106 if (num != 0) {
107 if (_curMusicSeq && ((_digSeqMusicTable[_curMusicSeq].transitionType == 4)
108 || (_digSeqMusicTable[_curMusicSeq].transitionType == 6))) {
109 _nextSeqToPlay = num;
110 return;
111 } else {
112 playDigMusic(_digSeqMusicTable[num].name, &_digSeqMusicTable[num], 0, true);
113 _nextSeqToPlay = 0;
114 _attributes[DIG_SEQ_OFFSET + num] = 1; // _attributes[COMI_SEQ_OFFSET] in Comi are not used as it doesn't have 'room' attributes table
115 }
116 } else {
117 if (_nextSeqToPlay != 0) {
118 playDigMusic(_digSeqMusicTable[_nextSeqToPlay].name, &_digSeqMusicTable[_nextSeqToPlay], 0, true);
119 _attributes[DIG_SEQ_OFFSET + _nextSeqToPlay] = 1; // _attributes[COMI_SEQ_OFFSET] in Comi are not used as it doesn't have 'room' attributes table
120 num = _nextSeqToPlay;
121 _nextSeqToPlay = 0;
122 } else {
123 if (_curMusicState != 0) {
124 playDigMusic(_digStateMusicTable[_curMusicState].name, &_digStateMusicTable[_curMusicState], _curMusicState, true);
125 } else
126 playDigMusic(NULL, &_digStateMusicTable[0], _curMusicState, true);
127 num = 0;
128 }
129 }
130
131 _curMusicSeq = num;
132 }
133
playDigMusic(const char * songName,const imuseDigTable * table,int attribPos,bool sequence)134 void IMuseDigital::playDigMusic(const char *songName, const imuseDigTable *table, int attribPos, bool sequence) {
135 int hookId = 0;
136
137 if (songName != NULL) {
138 if ((_attributes[DIG_SEQ_OFFSET + 38]) && (!_attributes[DIG_SEQ_OFFSET + 41])) {
139 if ((attribPos == 43) || (attribPos == 44))
140 hookId = 3;
141 }
142
143 if ((_attributes[DIG_SEQ_OFFSET + 46] != 0) && (_attributes[DIG_SEQ_OFFSET + 48] == 0)) {
144 if ((attribPos == 38) || (attribPos == 39))
145 hookId = 3;
146 }
147
148 if ((_attributes[DIG_SEQ_OFFSET + 53] != 0)) {
149 if ((attribPos == 50) || (attribPos == 51))
150 hookId = 3;
151 }
152
153 if ((attribPos != 0) && (hookId == 0)) {
154 if (table->attribPos != 0)
155 attribPos = table->attribPos;
156 hookId = _attributes[DIG_STATE_OFFSET + attribPos];
157 if (table->hookId != 0) {
158 if ((hookId != 0) && (table->hookId > 1)) {
159 _attributes[DIG_STATE_OFFSET + attribPos] = 2;
160 } else {
161 _attributes[DIG_STATE_OFFSET + attribPos] = hookId + 1;
162 if (table->hookId < hookId + 1)
163 _attributes[DIG_STATE_OFFSET + attribPos] = 1;
164 }
165 }
166 }
167 }
168
169 if (!songName) {
170 fadeOutMusic(120);
171 return;
172 }
173
174 switch (table->transitionType) {
175 case 0:
176 case 5:
177 break;
178 case 3:
179 case 4:
180 if (table->filename[0] == 0) {
181 fadeOutMusic(60);
182 return;
183 }
184 if (table->transitionType == 4)
185 _stopingSequence = 1;
186 if ((!sequence) && (table->attribPos != 0) &&
187 (table->attribPos == _digStateMusicTable[_curMusicState].attribPos)) {
188 fadeOutMusicAndStartNew(108, table->filename, table->soundId);
189 } else {
190 fadeOutMusic(108);
191 startMusic(table->filename, table->soundId, hookId, 127);
192 }
193 break;
194 case 6:
195 _stopingSequence = 1;
196 break;
197 }
198 }
199
setComiMusicState(int stateId)200 void IMuseDigital::setComiMusicState(int stateId) {
201 int l, num = -1;
202
203 if (stateId == 4) // look into #1881415 bug, ignore stateId == 4 it's seems needed after all
204 return;
205
206 if (stateId == 0)
207 stateId = 1000;
208
209 for (l = 0; _comiStateMusicTable[l].soundId != -1; l++) {
210 if ((_comiStateMusicTable[l].soundId == stateId)) {
211 debug(5, "Set music state: %s, %s", _comiStateMusicTable[l].name, _comiStateMusicTable[l].filename);
212 num = l;
213 break;
214 }
215 }
216
217 if (num == -1)
218 return;
219
220 if (_curMusicState == num)
221 return;
222
223 if (_curMusicSeq == 0) {
224 if (num == 0)
225 playComiMusic(NULL, &_comiStateMusicTable[0], num, false);
226 else
227 playComiMusic(_comiStateMusicTable[num].name, &_comiStateMusicTable[num], num, false);
228 }
229
230 _curMusicState = num;
231 }
232
setComiMusicSequence(int seqId)233 void IMuseDigital::setComiMusicSequence(int seqId) {
234 int l, num = -1;
235
236 if (seqId == 0)
237 seqId = 2000;
238
239 for (l = 0; _comiSeqMusicTable[l].soundId != -1; l++) {
240 if ((_comiSeqMusicTable[l].soundId == seqId)) {
241 debug(5, "Set music sequence: %s, %s", _comiSeqMusicTable[l].name, _comiSeqMusicTable[l].filename);
242 num = l;
243 break;
244 }
245 }
246
247 if (num == -1)
248 return;
249
250 if (_curMusicSeq == num)
251 return;
252
253 if (num != 0) {
254 if (_curMusicSeq && ((_comiSeqMusicTable[_curMusicSeq].transitionType == 4)
255 || (_comiSeqMusicTable[_curMusicSeq].transitionType == 6))) {
256 _nextSeqToPlay = num;
257 return;
258 } else {
259 playComiMusic(_comiSeqMusicTable[num].name, &_comiSeqMusicTable[num], 0, true);
260 _nextSeqToPlay = 0;
261 }
262 } else {
263 if (_nextSeqToPlay != 0) {
264 playComiMusic(_comiSeqMusicTable[_nextSeqToPlay].name, &_comiSeqMusicTable[_nextSeqToPlay], 0, true);
265 num = _nextSeqToPlay;
266 _nextSeqToPlay = 0;
267 } else {
268 if (_curMusicState != 0) {
269 playComiMusic(_comiStateMusicTable[_curMusicState].name, &_comiStateMusicTable[_curMusicState], _curMusicState, true);
270 } else
271 playComiMusic(NULL, &_comiStateMusicTable[0], _curMusicState, true);
272 num = 0;
273 }
274 }
275
276 _curMusicSeq = num;
277 }
278
playComiMusic(const char * songName,const imuseComiTable * table,int attribPos,bool sequence)279 void IMuseDigital::playComiMusic(const char *songName, const imuseComiTable *table, int attribPos, bool sequence) {
280 int hookId = 0;
281
282 if ((songName != NULL) && (attribPos != 0)) {
283 if (table->attribPos != 0)
284 attribPos = table->attribPos;
285 hookId = _attributes[COMI_STATE_OFFSET + attribPos];
286 if (table->hookId != 0) {
287 if ((hookId != 0) && (table->hookId > 1)) {
288 _attributes[COMI_STATE_OFFSET + attribPos] = 2;
289 } else {
290 _attributes[COMI_STATE_OFFSET + attribPos] = hookId + 1;
291 if (table->hookId < hookId + 1)
292 _attributes[COMI_STATE_OFFSET + attribPos] = 1;
293 }
294 }
295 }
296
297 if (!songName) {
298 fadeOutMusic(120);
299 return;
300 }
301
302 switch (table->transitionType) {
303 case 0:
304 break;
305 case 8:
306 setHookIdForMusic(table->hookId);
307 break;
308 case 9:
309 _stopingSequence = 1;
310 setHookIdForMusic(table->hookId);
311 break;
312 case 2:
313 case 3:
314 case 4:
315 case 12:
316 if (table->filename[0] == 0) {
317 fadeOutMusic(60);
318 return;
319 }
320 if (getCurMusicSoundId() == table->soundId)
321 return;
322 if (table->transitionType == 4)
323 _stopingSequence = 1;
324 if (table->transitionType == 2) {
325 fadeOutMusic(table->fadeOutDelay);
326 startMusic(table->filename, table->soundId, table->hookId, 127);
327 return;
328 }
329 if ((!sequence) && (table->attribPos != 0) &&
330 (table->attribPos == _comiStateMusicTable[_curMusicState].attribPos)) {
331 fadeOutMusicAndStartNew(table->fadeOutDelay, table->filename, table->soundId);
332 } else if (table->transitionType == 12) {
333 TriggerParams trigger;
334 strcpy(trigger.marker, "exit"); trigger.fadeOutDelay = table->fadeOutDelay;
335 strcpy(trigger.filename, table->filename); trigger.soundId = table->soundId;
336 trigger.hookId = table->hookId; trigger.volume = 127;
337 setTrigger(&trigger);
338 } else {
339 fadeOutMusic(table->fadeOutDelay);
340 startMusic(table->filename, table->soundId, hookId, 127);
341 }
342 break;
343 }
344 }
345
setFtMusicState(int stateId)346 void IMuseDigital::setFtMusicState(int stateId) {
347 if (stateId > 48)
348 return;
349
350 debug(5, "State music: %s, %s", _ftStateMusicTable[stateId].name, _ftStateMusicTable[stateId].audioName);
351
352 if (_curMusicState == stateId)
353 return;
354
355 if (_curMusicSeq == 0) {
356 if (stateId == 0)
357 playFtMusic(NULL, 0, 0);
358 else
359 playFtMusic(_ftStateMusicTable[stateId].audioName, _ftStateMusicTable[stateId].transitionType, _ftStateMusicTable[stateId].volume);
360 }
361
362 _curMusicState = stateId;
363 }
364
setFtMusicSequence(int seqId)365 void IMuseDigital::setFtMusicSequence(int seqId) {
366 if (seqId > 52)
367 return;
368
369 debug(5, "Sequence music: %s", _ftSeqNames[seqId].name);
370
371 if (_curMusicSeq == seqId)
372 return;
373
374 if (seqId == 0) {
375 if (_curMusicState == 0)
376 playFtMusic(NULL, 0, 0);
377 else {
378 playFtMusic(_ftStateMusicTable[_curMusicState].audioName, _ftStateMusicTable[_curMusicState].transitionType, _ftStateMusicTable[_curMusicState].volume);
379 }
380 } else {
381 int seq = (seqId - 1) * 4;
382 playFtMusic(_ftSeqMusicTable[seq].audioName, _ftSeqMusicTable[seq].transitionType, _ftSeqMusicTable[seq].volume);
383 }
384
385 _curMusicSeq = seqId;
386 _curMusicCue = 0;
387 }
388
setFtMusicCuePoint(int cueId)389 void IMuseDigital::setFtMusicCuePoint(int cueId) {
390 if (cueId > 3)
391 return;
392
393 debug(5, "Cue point sequence: %d", cueId);
394
395 if (_curMusicSeq == 0)
396 return;
397
398 if (_curMusicCue == cueId)
399 return;
400
401 if (cueId == 0)
402 playFtMusic(NULL, 0, 0);
403 else {
404 int seq = ((_curMusicSeq - 1) * 4) + cueId;
405 playFtMusic(_ftSeqMusicTable[seq].audioName, _ftSeqMusicTable[seq].transitionType, _ftSeqMusicTable[seq].volume);
406 }
407
408 _curMusicCue = cueId;
409 }
410
setAudioNames(int32 num,char * names)411 void IMuseDigital::setAudioNames(int32 num, char *names) {
412 free(_audioNames);
413 _numAudioNames = num;
414 _audioNames = names;
415 }
416
getSoundIdByName(const char * soundName)417 int IMuseDigital::getSoundIdByName(const char *soundName) {
418 if (soundName && soundName[0] != 0) {
419 for (int r = 0; r < _numAudioNames; r++) {
420 if (strcmp(soundName, &_audioNames[r * 9]) == 0) {
421 return r;
422 }
423 }
424 }
425
426 return -1;
427 }
428
playFtMusic(const char * songName,int opcode,int volume)429 void IMuseDigital::playFtMusic(const char *songName, int opcode, int volume) {
430 fadeOutMusic(200);
431
432 switch (opcode) {
433 case 0:
434 case 4:
435 break;
436 case 1:
437 case 2:
438 case 3:
439 {
440 int soundId = getSoundIdByName(songName);
441 if (soundId != -1) {
442 startMusic(soundId, volume);
443 }
444 }
445 break;
446 }
447 }
448
449
450 } // End of namespace Scumm
451