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