~ubuntu-branches/ubuntu/raring/scummvm/raring

« back to all changes in this revision

Viewing changes to engines/scumm/player_towns.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Moritz Muehlenhoff
  • Date: 2011-05-25 19:02:23 UTC
  • mto: (21.1.2 sid)
  • mto: This revision was merged to the branch mainline in revision 24.
  • Revision ID: james.westby@ubuntu.com-20110525190223-fiqm0oaec714xk31
Tags: upstream-1.3.0
ImportĀ upstreamĀ versionĀ 1.3.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
18
18
 * along with this program; if not, write to the Free Software
19
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20
20
 *
21
 
 * $URL: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/tags/release-1-2-1/engines/scumm/player_towns.cpp $
22
 
 * $Id: player_towns.cpp 52234 2010-08-20 17:37:06Z athrxx $
 
21
 * $URL$
 
22
 * $Id$
23
23
 *
24
24
 */
25
25
 
29
29
 
30
30
namespace Scumm {
31
31
 
32
 
Player_Towns::Player_Towns(ScummEngine *vm, Audio::Mixer *mixer) : _vm(vm) {
 
32
Player_Towns::Player_Towns(ScummEngine *vm, bool isVersion2) : _vm(vm), _v2(isVersion2), _numSoundMax(isVersion2 ? 256 : 200) {
 
33
        memset(_pcmCurrentSound, 0, sizeof(_pcmCurrentSound));
 
34
        _unkFlags = 0x33;
 
35
        _intf = 0;
 
36
}
 
37
 
 
38
void Player_Towns::setSfxVolume(int vol) {
 
39
        if (!_intf)
 
40
                return; 
 
41
        _intf->setSoundEffectVolume(vol);
 
42
}
 
43
 
 
44
int Player_Towns::getSoundStatus(int sound) const {
 
45
        if (!_intf)
 
46
                return 0;
 
47
        for (int i = 1; i < 9; i++) {
 
48
                if (_pcmCurrentSound[i].index == sound)
 
49
                        return _intf->callback(40, 0x3f + i) ? 1 : 0;
 
50
        }
 
51
        return 0;
 
52
}
 
53
 
 
54
void Player_Towns::saveLoadWithSerializer(Serializer *ser) {
 
55
        static const SaveLoadEntry pcmEntries[] = {
 
56
                MKLINE(PcmCurrentSound, index, sleInt16, VER(81)),
 
57
                MKLINE(PcmCurrentSound, chan, sleInt16, VER(81)),
 
58
                MKLINE(PcmCurrentSound, note, sleUint8, VER(81)),
 
59
                MKLINE(PcmCurrentSound, velo, sleUint8, VER(81)),
 
60
                MKLINE(PcmCurrentSound, pan, sleUint8, VER(81)),
 
61
                MKLINE(PcmCurrentSound, paused, sleUint8, VER(81)),
 
62
                MKLINE(PcmCurrentSound, looping, sleUint8, VER(81)),
 
63
                MKLINE(PcmCurrentSound, priority, sleUint32, VER(81)),
 
64
                MKEND()
 
65
        };
 
66
 
 
67
        for (int i = 1; i < 9; i++) {
 
68
                if (!_pcmCurrentSound[i].index)
 
69
                        continue;
 
70
 
 
71
                if (_intf->callback(40, i + 0x3f))
 
72
                        continue;
 
73
 
 
74
                _intf->callback(39, i + 0x3f);
 
75
 
 
76
                _pcmCurrentSound[i].index = 0;
 
77
        }
 
78
 
 
79
        ser->saveLoadArrayOf(_pcmCurrentSound, 9, sizeof(PcmCurrentSound), pcmEntries);
 
80
}
 
81
 
 
82
void Player_Towns::restoreAfterLoad() {
 
83
        for (int i = 1; i < 9; i++) {
 
84
                if (!_pcmCurrentSound[i].index || _pcmCurrentSound[i].index == 0xffff)
 
85
                        continue;
 
86
 
 
87
                uint8 *ptr = _vm->getResourceAddress(rtSound, _pcmCurrentSound[i].index);
 
88
                if (!ptr)
 
89
                        continue;
 
90
 
 
91
                if (_vm->_game.version != 3)
 
92
                        ptr += 2;
 
93
 
 
94
                if (ptr[13])
 
95
                        continue;
 
96
 
 
97
                playPcmTrack(_pcmCurrentSound[i].index, ptr + 6, _pcmCurrentSound[i].velo, _pcmCurrentSound[i].pan, _pcmCurrentSound[i].note, _pcmCurrentSound[i].priority);
 
98
        }
 
99
}
 
100
 
 
101
void Player_Towns::playPcmTrack(int sound, const uint8 *data, int velo, int pan, int note, int priority) {
 
102
        if (!_intf)
 
103
                return;
 
104
 
 
105
        const uint8 *sfxData = data + 16;
 
106
        
 
107
        int numChan = _v2 ? 1 : data[14];
 
108
        for (int i = 0; i < numChan; i++) {
 
109
                int chan = allocatePcmChannel(sound, i, priority);
 
110
                if (!chan)
 
111
                        return;
 
112
                
 
113
                _intf->callback(70, _unkFlags);
 
114
                _intf->callback(3, chan + 0x3f, pan);
 
115
                _intf->callback(37, chan + 0x3f, note, velo, sfxData);
 
116
                
 
117
                _pcmCurrentSound[chan].note = note;
 
118
                _pcmCurrentSound[chan].velo = velo;
 
119
                _pcmCurrentSound[chan].pan = pan;
 
120
                _pcmCurrentSound[chan].paused = 0;
 
121
                _pcmCurrentSound[chan].looping = READ_LE_UINT32(&sfxData[20]) ? 1 : 0;
 
122
 
 
123
                sfxData += (READ_LE_UINT32(&sfxData[12]) + 32);
 
124
        }
 
125
}
 
126
 
 
127
void Player_Towns::stopPcmTrack(int sound) {
 
128
        if (!_intf)
 
129
                return;
 
130
 
 
131
        for (int i = 1; i < 9; i++) {
 
132
                if (sound == _pcmCurrentSound[i].index || !sound) {
 
133
                        _intf->callback(39, i + 0x3f);
 
134
                        _pcmCurrentSound[i].index = 0;
 
135
                }
 
136
        }
 
137
}
 
138
 
 
139
int Player_Towns::allocatePcmChannel(int sound, int sfxChanRelIndex, uint32 priority) {
 
140
        if (!_intf)
 
141
                return 0;
 
142
 
 
143
        int chan = 0;
 
144
 
 
145
        if (_v2 && priority > 255) {
 
146
                chan = 8;
 
147
                if (_intf->callback(40, 0x47))
 
148
                        _intf->callback(39, 0x47);
 
149
        } else {
 
150
                for (int i = 8; i; i--) {
 
151
                        if (!_pcmCurrentSound[i].index) {
 
152
                                chan = i;
 
153
                                continue;
 
154
                        }
 
155
 
 
156
                        if (_intf->callback(40, i + 0x3f))
 
157
                                continue;
 
158
 
 
159
                        chan = i;
 
160
                        if (_pcmCurrentSound[chan].index == 0xffff)
 
161
                                _intf->callback(39, chan + 0x3f);
 
162
                        else
 
163
                                _vm->_sound->stopSound(_pcmCurrentSound[chan].index);
 
164
                }
 
165
 
 
166
                if (!chan) {
 
167
                        for (int i = 1; i < 9; i++) {
 
168
                                if (priority >= _pcmCurrentSound[i].priority)
 
169
                                        chan = i;
 
170
                        }
 
171
                        if (_pcmCurrentSound[chan].index == 0xffff)
 
172
                                _intf->callback(39, chan + 0x3f);
 
173
                        else
 
174
                                _vm->_sound->stopSound(_pcmCurrentSound[chan].index);
 
175
                }
 
176
        }
 
177
 
 
178
        if (chan) {
 
179
                _pcmCurrentSound[chan].index = sound;
 
180
                _pcmCurrentSound[chan].chan = sfxChanRelIndex;
 
181
                _pcmCurrentSound[chan].priority = priority;
 
182
        }
 
183
 
 
184
        return chan;
 
185
}
 
186
 
 
187
Player_Towns_v1::Player_Towns_v1(ScummEngine *vm, Audio::Mixer *mixer) : Player_Towns(vm, false) {
 
188
        _soundOverride = 0;
33
189
        _cdaCurrentSound = _eupCurrentSound = _cdaNumLoops = 0;
34
190
        _cdaForceRestart = 0;
35
 
        memset(_pcmCurrentSound, 0, sizeof(_pcmCurrentSound));
36
191
        _cdaVolLeft = _cdaVolRight = 0;
37
192
 
38
193
        _eupVolLeft = _eupVolRight = 0;
39
 
        memset(&_ovrCur, 0, sizeof(SoundOvrParameters));
40
 
        _soundOverride = 0;
 
194
        _eupLooping = false;
41
195
 
42
196
        if (_vm->_game.version == 3) {
43
 
                _soundOverride = new SoundOvrParameters[200];
44
 
                memset(_soundOverride, 0, 200 * sizeof(SoundOvrParameters));
45
 
        }
46
 
 
47
 
        _eupLooping = false;
48
 
        _unkFlags = 0x33;
 
197
                _soundOverride = new SoundOvrParameters[_numSoundMax];
 
198
                memset(_soundOverride, 0, _numSoundMax * sizeof(SoundOvrParameters));
 
199
        }       
49
200
 
50
201
        _driver = new TownsEuphonyDriver(mixer);
51
202
}
52
203
 
53
 
Player_Towns::~Player_Towns() {
54
 
        delete[] _soundOverride;
 
204
Player_Towns_v1::~Player_Towns_v1() {
55
205
        delete _driver;
 
206
        delete[] _soundOverride;
56
207
}
57
208
 
58
 
bool Player_Towns::init() {
 
209
bool Player_Towns_v1::init() {
59
210
        if (!_driver)
60
211
                return false;
61
212
        
63
214
                return false;
64
215
 
65
216
        _driver->reserveSoundEffectChannels(8);
 
217
        _intf = _driver->intf();
66
218
 
67
219
        // Treat all 6 fm channels and all 8 pcm channels as sound effect channels
68
220
        // since music seems to exist as CD audio only in the games which use this
69
221
        // MusicEngine implementation.
70
 
        _driver->intf()->setSoundEffectChanMask(-1);
 
222
        _intf->setSoundEffectChanMask(-1);
71
223
 
72
224
        setVolumeCD(255, 255);
73
225
 
74
226
        return true;
75
227
}
76
228
 
77
 
void Player_Towns::setMusicVolume(int vol) {
 
229
void Player_Towns_v1::setMusicVolume(int vol) {
78
230
        _driver->setMusicVolume(vol);
79
231
}
80
232
 
81
 
void Player_Towns::setSfxVolume(int vol) {
82
 
        _driver->setSoundEffectVolume(vol);
83
 
}
84
 
 
85
 
void Player_Towns::startSound(int sound) {
 
233
void Player_Towns_v1::startSound(int sound) {
86
234
        uint8 *ptr = _vm->getResourceAddress(rtSound, sound);
87
 
        if (_vm->_game.version != 3) {
 
235
        if (_vm->_game.version != 3)
88
236
                ptr += 2;
89
 
        } else if (_soundOverride && sound > 0 && sound < 200) {
90
 
                memcpy(&_ovrCur, &_soundOverride[sound], sizeof(SoundOvrParameters));
91
 
                memset(&_soundOverride[sound], 0, sizeof(SoundOvrParameters));
92
 
        }
93
237
 
94
238
        int type = ptr[13];
95
239
 
96
240
        if (type == 0) {
97
 
                playPcmTrack(sound, ptr + 6);
 
241
                uint8 velocity = 0;
 
242
                uint8 note = 0;
 
243
                
 
244
                if (_vm->_game.version == 3) {
 
245
                        velocity = (_soundOverride[sound].vLeft + _soundOverride[sound].vRight);
 
246
                        note = _soundOverride[sound].note;
 
247
                }
 
248
 
 
249
                velocity = velocity ? velocity >> 2 : ptr[14] >> 1;             
 
250
                playPcmTrack(sound, ptr + 6, velocity, 64, note ? note : ptr[50], READ_LE_UINT16(ptr + 10));
 
251
 
98
252
        } else if (type == 1) {
99
253
                playEuphonyTrack(sound, ptr + 6);
 
254
 
100
255
        } else if (type == 2) {
101
256
                playCdaTrack(sound, ptr + 6);
102
257
        }
103
 
        memset(&_ovrCur, 0, sizeof(SoundOvrParameters));
 
258
 
 
259
        if (_vm->_game.version == 3)
 
260
                _soundOverride[sound].vLeft = _soundOverride[sound].vRight = _soundOverride[sound].note = 0;
104
261
}
105
262
 
106
 
void Player_Towns::stopSound(int sound) {
 
263
void Player_Towns_v1::stopSound(int sound) {
107
264
        if (sound == 0 || sound == _cdaCurrentSound) {
108
265
                _cdaCurrentSound = 0;
109
266
                _vm->_sound->stopCD();
119
276
        stopPcmTrack(sound);
120
277
}
121
278
 
122
 
void Player_Towns::stopAllSounds() {
 
279
void Player_Towns_v1::stopAllSounds() {
123
280
        _cdaCurrentSound = 0;
124
281
        _vm->_sound->stopCD();
125
282
        _vm->_sound->stopCDTimer();
131
288
        stopPcmTrack(0);
132
289
}
133
290
 
134
 
int Player_Towns::getSoundStatus(int sound) const {
 
291
int Player_Towns_v1::getSoundStatus(int sound) const {
135
292
        if (sound == _cdaCurrentSound)
136
293
                return _vm->_sound->pollCD();
137
294
        if (sound == _eupCurrentSound)
138
295
                return _driver->parserIsPlaying() ? 1 : 0;
139
 
        for (int i = 1; i < 9; i++) {
140
 
                if (_pcmCurrentSound[i].index == sound)
141
 
                        return _driver->soundEffectIsPlaying(i + 0x3f) ? 1 : 0;
142
 
        }
143
 
        return 0;
 
296
        return Player_Towns::getSoundStatus(sound);
144
297
}
145
298
 
146
 
int32 Player_Towns::doCommand(int numargs, int args[]) {
 
299
int32 Player_Towns_v1::doCommand(int numargs, int args[]) {
147
300
        int32 res = 0;
148
301
        
149
302
        switch (args[0]) {
176
329
                break;
177
330
 
178
331
        default:
179
 
                warning("Player_Towns::doCommand: Unknown command %d", args[0]);
 
332
                warning("Player_Towns_v1::doCommand: Unknown command %d", args[0]);
180
333
                break;
181
334
        }
182
335
 
183
336
        return res;
184
337
}
185
338
 
186
 
void Player_Towns::setVolumeCD(int left, int right) {
 
339
void Player_Towns_v1::setVolumeCD(int left, int right) {
187
340
        _cdaVolLeft = left & 0xff;
188
341
        _cdaVolRight = right & 0xff;
189
342
        _driver->setOutputVolume(1, left >> 1, right >> 1);
190
343
}
191
344
 
192
 
void Player_Towns::setSoundVolume(int sound, int left, int right) {
193
 
        if (_soundOverride && sound > 0 && sound < 200) {
 
345
void Player_Towns_v1::setSoundVolume(int sound, int left, int right) {
 
346
        if (_soundOverride && sound > 0 && sound < _numSoundMax) {
194
347
                _soundOverride[sound].vLeft = left;
195
348
                _soundOverride[sound].vRight = right;
196
349
        }
197
350
}
198
351
 
199
 
void Player_Towns::setSoundNote(int sound, int note) {
200
 
        if (_soundOverride && sound > 0 && sound < 200)
 
352
void Player_Towns_v1::setSoundNote(int sound, int note) {
 
353
        if (_soundOverride && sound > 0 && sound < _numSoundMax)
201
354
                _soundOverride[sound].note = note;
202
355
}
203
356
 
204
 
void Player_Towns::saveLoadWithSerializer(Serializer *ser) {
 
357
void Player_Towns_v1::saveLoadWithSerializer(Serializer *ser) {
205
358
        _cdaCurrentSoundTemp = (_vm->_sound->pollCD() && _cdaNumLoops > 1) ? _cdaCurrentSound & 0xff : 0;
206
359
        _cdaNumLoopsTemp = _cdaNumLoops & 0xff;
207
360
 
208
361
        static const SaveLoadEntry cdEntries[] = {
209
 
                MKLINE(Player_Towns, _cdaCurrentSoundTemp, sleUint8, VER(81)),
210
 
                MKLINE(Player_Towns, _cdaNumLoopsTemp, sleUint8, VER(81)),
211
 
                MKLINE(Player_Towns, _cdaVolLeft, sleUint8, VER(81)),
212
 
                MKLINE(Player_Towns, _cdaVolRight, sleUint8, VER(81)),
 
362
                MKLINE(Player_Towns_v1, _cdaCurrentSoundTemp, sleUint8, VER(81)),
 
363
                MKLINE(Player_Towns_v1, _cdaNumLoopsTemp, sleUint8, VER(81)),
 
364
                MKLINE(Player_Towns_v1, _cdaVolLeft, sleUint8, VER(81)),
 
365
                MKLINE(Player_Towns_v1, _cdaVolRight, sleUint8, VER(81)),
213
366
                MKEND()
214
367
        };
215
368
 
219
372
                _eupCurrentSound = 0;
220
373
 
221
374
        static const SaveLoadEntry eupEntries[] = {
222
 
                MKLINE(Player_Towns, _eupCurrentSound, sleUint8, VER(81)),
223
 
                MKLINE(Player_Towns, _eupLooping, sleUint8, VER(81)),
224
 
                MKLINE(Player_Towns, _eupVolLeft, sleUint8, VER(81)),
225
 
                MKLINE(Player_Towns, _eupVolRight, sleUint8, VER(81)),
 
375
                MKLINE(Player_Towns_v1, _eupCurrentSound, sleUint8, VER(81)),
 
376
                MKLINE(Player_Towns_v1, _eupLooping, sleUint8, VER(81)),
 
377
                MKLINE(Player_Towns_v1, _eupVolLeft, sleUint8, VER(81)),
 
378
                MKLINE(Player_Towns_v1, _eupVolRight, sleUint8, VER(81)),
226
379
                MKEND()
227
380
        };
228
381
 
229
382
        ser->saveLoadEntries(this, eupEntries);
230
383
 
231
 
        static const SaveLoadEntry pcmEntries[] = {
232
 
                MKLINE(PcmCurrentSound, index, sleInt16, VER(81)),
233
 
                MKLINE(PcmCurrentSound, chan, sleInt16, VER(81)),
234
 
                MKLINE(PcmCurrentSound, note, sleUint8, VER(81)),
235
 
                MKLINE(PcmCurrentSound, velo, sleUint8, VER(81)),
236
 
                MKLINE(PcmCurrentSound, pan, sleUint8, VER(81)),
237
 
                MKLINE(PcmCurrentSound, paused, sleUint8, VER(81)),
238
 
                MKLINE(PcmCurrentSound, looping, sleUint8, VER(81)),
239
 
                MKLINE(PcmCurrentSound, priority, sleUint32, VER(81)),
240
 
                MKEND()
241
 
        };
242
 
 
243
 
        for (int i = 1; i < 9; i++) {
244
 
                if (!_pcmCurrentSound[i].index)
245
 
                        continue;
246
 
 
247
 
                if (_driver->soundEffectIsPlaying(i + 0x3f))
248
 
                        continue;
249
 
 
250
 
                _driver->stopSoundEffect(i + 0x3f);
251
 
 
252
 
                _pcmCurrentSound[i].index = 0;
253
 
        }
254
 
 
255
 
        ser->saveLoadArrayOf(_pcmCurrentSound, 9, sizeof(PcmCurrentSound), pcmEntries);
 
384
        Player_Towns::saveLoadWithSerializer(ser);
256
385
}
257
386
 
258
 
void Player_Towns::restoreAfterLoad() {
 
387
void Player_Towns_v1::restoreAfterLoad() {
259
388
        setVolumeCD(_cdaVolLeft, _cdaVolRight);
260
389
        
261
390
        if (_cdaCurrentSoundTemp) {
281
410
                }
282
411
        }
283
412
 
284
 
        for (int i = 1; i < 9; i++) {
285
 
                if (!_pcmCurrentSound[i].index)
286
 
                        continue;
287
 
 
288
 
                uint8 *ptr = _vm->getResourceAddress(rtSound, _pcmCurrentSound[i].index);
289
 
                if (!ptr)
290
 
                        continue;
291
 
 
292
 
                if (_vm->_game.version != 3)
293
 
                        ptr += 2;
294
 
 
295
 
                if (ptr[13])
296
 
                        continue;
297
 
 
298
 
                playPcmTrack(_pcmCurrentSound[i].index, ptr + 6, _pcmCurrentSound[i].velo, _pcmCurrentSound[i].pan, _pcmCurrentSound[i].note);
299
 
        }
300
 
}
301
 
 
302
 
int Player_Towns::getNextFreePcmChannel(int sound, int sfxChanRelIndex) {
303
 
        int chan = 0;
304
 
        for (int i = 8; i; i--) {
305
 
                if (!_pcmCurrentSound[i].index) {
306
 
                        chan = i;
307
 
                        continue;
308
 
                }
309
 
 
310
 
                if (_driver->soundEffectIsPlaying(i + 0x3f))
311
 
                        continue;
312
 
 
313
 
                chan = i;
314
 
                _vm->_sound->stopSound(_pcmCurrentSound[chan].index);
315
 
        }
316
 
 
317
 
        if (!chan) {
318
 
                uint16 l = 0xffff;
319
 
                uint8 *ptr = 0;
320
 
                for (int i = 8; i; i--) {
321
 
                        ptr = _vm->getResourceAddress(rtSound, _pcmCurrentSound[i].index) + 6;
322
 
                        uint16 a = READ_LE_UINT16(ptr + 10);
323
 
                        if (a <= l) {
324
 
                                chan = i;
325
 
                                l = a;
326
 
                        }
327
 
                }
328
 
 
329
 
                ptr = _vm->getResourceAddress(rtSound, sound) + 6;
330
 
                if (l <= READ_LE_UINT16(ptr + 10))
331
 
                        _vm->_sound->stopSound(_pcmCurrentSound[chan].index);
332
 
                else
333
 
                        chan = 0;
334
 
        }
335
 
 
336
 
        if (chan) {
337
 
                _pcmCurrentSound[chan].index = sound;
338
 
                _pcmCurrentSound[chan].chan = sfxChanRelIndex;
339
 
        }
340
 
 
341
 
        return chan;
342
 
}
343
 
 
344
 
void Player_Towns::restartLoopingSounds() {
 
413
        Player_Towns::restoreAfterLoad();
 
414
}
 
415
 
 
416
void Player_Towns_v1::restartLoopingSounds() {
345
417
        if (_cdaNumLoops && !_cdaForceRestart)
346
418
                _cdaForceRestart = 1;
347
419
 
368
440
        _driver->intf()->callback(73, 1);
369
441
}
370
442
 
371
 
void Player_Towns::startSoundEx(int sound, int velo, int pan, int note) {
 
443
void Player_Towns_v1::startSoundEx(int sound, int velo, int pan, int note) {
372
444
        uint8 *ptr = _vm->getResourceAddress(rtSound, sound) + 2;
373
445
 
374
446
        if (pan > 99)
376
448
 
377
449
        velo = velo ? (velo * ptr[14] + 50) / 100 : ptr[14];
378
450
        velo = CLIP(velo, 1, 255);
 
451
        uint16 pri = READ_LE_UINT16(ptr + 10);
379
452
 
380
453
        if (ptr[13] == 0) {
381
454
                velo >>= 1;
385
458
 
386
459
                pan = pan ? (((pan << 7) - pan) + 50) / 100 : 64;
387
460
 
388
 
                playPcmTrack(sound, ptr + 6, velo, pan, note);
 
461
                playPcmTrack(sound, ptr + 6, velo ? velo : ptr[14] >> 1, pan, note ? note : ptr[50], pri);
389
462
 
390
463
        } else if (ptr[13] == 2) {
391
464
                int volLeft = velo;
405
478
        }
406
479
}
407
480
 
408
 
void Player_Towns::stopSoundSuspendLooping(int sound) {
 
481
void Player_Towns_v1::stopSoundSuspendLooping(int sound) {
409
482
        if (!sound) {
410
483
                return;
411
484
        } else if (sound == _cdaCurrentSound) {
426
499
        }
427
500
}
428
501
 
429
 
void Player_Towns::playEuphonyTrack(int sound, const uint8 *data) {
 
502
void Player_Towns_v1::playEuphonyTrack(int sound, const uint8 *data) {
430
503
        const uint8 *pos = data + 16;
431
504
        const uint8 *src = pos + data[14] * 48;
432
505
        const uint8 *trackData = src + 150;
451
524
                _driver->intf()->callback(4, i, i);
452
525
        }
453
526
 
454
 
        _eupVolLeft = _ovrCur.vLeft;
455
 
        _eupVolRight = _ovrCur.vRight;
456
 
        int lvl = _ovrCur.vLeft + _ovrCur.vRight;
 
527
        _eupVolLeft = _soundOverride[sound].vLeft;
 
528
        _eupVolRight = _soundOverride[sound].vRight;
 
529
        int lvl = _soundOverride[sound].vLeft + _soundOverride[sound].vRight;
457
530
        if (!lvl)
458
531
                lvl = data[8] + data[9];
459
532
        lvl >>= 2;
474
547
        _eupCurrentSound = sound;
475
548
}
476
549
 
477
 
void Player_Towns::playPcmTrack(int sound, const uint8 *data, int velo, int pan, int note) {
478
 
        const uint8 *ptr = data;
479
 
        const uint8 *sfxData = ptr + 16;
480
 
        
481
 
        int note2, velocity;
482
 
 
483
 
        if (velo)
484
 
                velocity = velo;
485
 
        else if (_ovrCur.vLeft + _ovrCur.vRight)
486
 
                velocity = (_ovrCur.vLeft + _ovrCur.vRight) >> 2;
487
 
        else
488
 
                velocity = ptr[8] >> 1;
489
 
 
490
 
        int numChan = ptr[14];
491
 
        for (int i = 0; i < numChan; i++) {
492
 
                int chan = getNextFreePcmChannel(sound, i);
493
 
                if (!chan)
494
 
                        return;
495
 
                
496
 
                _driver->intf()->callback(70, _unkFlags);
497
 
                _driver->chanPanPos(chan + 0x3f, pan);
498
 
                
499
 
                if (note)
500
 
                        note2 = note;
501
 
                else if (_ovrCur.note)
502
 
                        note2 = _ovrCur.note;
503
 
                else
504
 
                        note2 = sfxData[28];
505
 
                
506
 
                _driver->playSoundEffect(chan + 0x3f, note2, velocity, sfxData);
507
 
                
508
 
                _pcmCurrentSound[chan].note = note2;
509
 
                _pcmCurrentSound[chan].velo = velocity;
510
 
                _pcmCurrentSound[chan].pan = pan;
511
 
                _pcmCurrentSound[chan].paused = 0;
512
 
                _pcmCurrentSound[chan].looping = READ_LE_UINT32(&sfxData[20]) ? 1 : 0;
513
 
 
514
 
                sfxData += (READ_LE_UINT32(&sfxData[12]) + 32);
515
 
        }
516
 
}
517
 
 
518
 
void Player_Towns::playCdaTrack(int sound, const uint8 *data, bool skipTrackVelo) {
 
550
void Player_Towns_v1::playCdaTrack(int sound, const uint8 *data, bool skipTrackVelo) {
519
551
        const uint8 *ptr = data;
520
552
 
521
553
        if (!sound)
522
554
                return;
523
555
 
524
556
        if (!skipTrackVelo) {
525
 
                if (_ovrCur.vLeft + _ovrCur.vRight)
526
 
                        setVolumeCD(_ovrCur.vLeft, _ovrCur.vRight);
527
 
                else
 
557
                if (_vm->_game.version == 3) {
 
558
                        if (_soundOverride[sound].vLeft + _soundOverride[sound].vRight)
 
559
                                setVolumeCD(_soundOverride[sound].vLeft, _soundOverride[sound].vRight);
 
560
                        else
 
561
                                setVolumeCD(ptr[8], ptr[9]);
 
562
                } else {
528
563
                        setVolumeCD(ptr[8], ptr[9]);
 
564
                }
529
565
        }
530
566
 
531
567
        if (sound == _cdaCurrentSound && _vm->_sound->pollCD() == 1)                    
543
579
        _cdaCurrentSound = sound;
544
580
}
545
581
 
546
 
void Player_Towns::stopPcmTrack(int sound) {
547
 
        for (int i = 1; i < 9; i++) {
548
 
                if (sound == _pcmCurrentSound[i].index || !sound) {
549
 
                        _driver->stopSoundEffect(i + 0x3f);
550
 
                        _pcmCurrentSound[i].index = 0;
551
 
                }
552
 
        }
 
582
Player_Towns_v2::Player_Towns_v2(ScummEngine *vm, IMuse *imuse, Audio::Mixer *mixer, bool disposeIMuse) : Player_Towns(vm, true), _imuse(imuse), _imuseDispose(disposeIMuse) {
 
583
        _soundOverride = new SoundOvrParameters[_numSoundMax];
 
584
        memset(_soundOverride, 0, _numSoundMax * sizeof(SoundOvrParameters));
 
585
        _sblData = 0;
 
586
        _intf = new TownsAudioInterface(mixer, 0);
 
587
}
 
588
 
 
589
Player_Towns_v2::~Player_Towns_v2() {
 
590
        delete _intf;
 
591
 
 
592
        if (_imuseDispose)
 
593
                delete _imuse;
 
594
 
 
595
        delete[] _sblData;
 
596
        delete[] _soundOverride;
 
597
}
 
598
 
 
599
bool Player_Towns_v2::init() {
 
600
        if (!_intf)
 
601
                return false;
 
602
        
 
603
        if (!_intf->init())
 
604
                return false;
 
605
 
 
606
        _intf->callback(33, 8);
 
607
        _intf->setSoundEffectChanMask(~0x3f);
 
608
 
 
609
        return true;
 
610
}
 
611
 
 
612
void Player_Towns_v2::setMusicVolume(int vol) {
 
613
        _imuse->setMusicVolume(vol);
 
614
}
 
615
 
 
616
int Player_Towns_v2::getSoundStatus(int sound) const {
 
617
        if (_soundOverride[sound].type == 7)
 
618
                return Player_Towns::getSoundStatus(sound);
 
619
        return _imuse->getSoundStatus(sound);
 
620
}
 
621
 
 
622
void Player_Towns_v2::startSound(int sound) {
 
623
        uint8 *ptr = _vm->getResourceAddress(rtSound, sound);
 
624
 
 
625
        if (READ_BE_UINT32(ptr) == MKTAG('T','O','W','S')) {
 
626
                _soundOverride[sound].type = 7;
 
627
                uint8 velo = _soundOverride[sound].velo ? _soundOverride[sound].velo - 1: (ptr[10] + ptr[11] + 1) >> 1;
 
628
                uint8 pan = _soundOverride[sound].pan ? _soundOverride[sound].pan - 1 : 64;
 
629
                uint8 pri = ptr[9];
 
630
                _soundOverride[sound].velo = _soundOverride[sound].pan = 0;
 
631
                playPcmTrack(sound, ptr + 8, velo, pan, ptr[52], pri);
 
632
 
 
633
        } else if (READ_BE_UINT32(ptr) == MKTAG('S','B','L',' ')) {
 
634
                _soundOverride[sound].type = 5;
 
635
                playVocTrack(ptr + 27);
 
636
 
 
637
        } else {
 
638
                _soundOverride[sound].type = 3;
 
639
                _imuse->startSound(sound);
 
640
        }
 
641
}
 
642
 
 
643
void Player_Towns_v2::stopSound(int sound) {
 
644
        if (_soundOverride[sound].type == 7) {
 
645
                stopPcmTrack(sound);            
 
646
        } else {
 
647
                _imuse->stopSound(sound);
 
648
        }
 
649
}
 
650
 
 
651
void Player_Towns_v2::stopAllSounds() {
 
652
        stopPcmTrack(0);
 
653
        _imuse->stopAllSounds();
 
654
}
 
655
 
 
656
int32 Player_Towns_v2::doCommand(int numargs, int args[]) {
 
657
        int32 res = -1;
 
658
        uint8 *ptr = 0;
 
659
        
 
660
        switch (args[0]) {
 
661
        case 8:
 
662
                startSound(args[1]);
 
663
                res = 0;
 
664
                break;
 
665
 
 
666
        case 9:
 
667
        case 15:
 
668
                stopSound(args[1]);
 
669
                res = 0;
 
670
                break;
 
671
 
 
672
        case 11:
 
673
                stopPcmTrack(0);
 
674
                break;
 
675
 
 
676
        case 13:
 
677
                res = getSoundStatus(args[1]);
 
678
                break;
 
679
 
 
680
        case 258:
 
681
                if (_soundOverride[args[1]].type == 0) {
 
682
                        ptr = _vm->getResourceAddress(rtSound, args[1]);
 
683
                        if (READ_BE_UINT32(ptr) == MKTAG('T','O','W','S')) 
 
684
                                _soundOverride[args[1]].type = 7;
 
685
                }
 
686
                if (_soundOverride[args[1]].type == 7)  {
 
687
                        _soundOverride[args[1]].velo = args[2] + 1;
 
688
                        res = 0;
 
689
                }
 
690
                break;
 
691
        
 
692
        case 259:
 
693
                if (_soundOverride[args[1]].type == 0) {
 
694
                        ptr = _vm->getResourceAddress(rtSound, args[1]);
 
695
                        if (READ_BE_UINT32(ptr) == MKTAG('T','O','W','S')) 
 
696
                                _soundOverride[args[1]].type = 7;
 
697
                }
 
698
                if (_soundOverride[args[1]].type == 7)  {
 
699
                        _soundOverride[args[1]].pan = 64 - CLIP<int>(args[2], -63, 63);
 
700
                        res = 0;
 
701
                }
 
702
                break;
 
703
 
 
704
        default:
 
705
                break;
 
706
        }
 
707
 
 
708
        if (res == -1)
 
709
                return _imuse->doCommand(numargs, args);
 
710
        
 
711
        return res;
 
712
}
 
713
 
 
714
void Player_Towns_v2::saveLoadWithSerializer(Serializer *ser) {
 
715
        if (ser->getVersion() >= 83)
 
716
                Player_Towns::saveLoadWithSerializer(ser);
 
717
}
 
718
 
 
719
void Player_Towns_v2::playVocTrack(const uint8 *data) {
 
720
        static const uint8 header[] = {
 
721
                0x54, 0x61, 0x6C, 0x6B, 0x69, 0x65, 0x20, 0x20,
 
722
                0x78, 0x56, 0x34, 0x12, 0x00, 0x00, 0x00, 0x00,
 
723
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
724
                0x36, 0x04, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00
 
725
        };
 
726
        
 
727
        uint32 len = (READ_LE_UINT32(data) >> 8) - 2;
 
728
        
 
729
        int chan = allocatePcmChannel(0xffff, 0, 0x1000);
 
730
        if (!chan)
 
731
                return;
 
732
 
 
733
        delete[] _sblData;
 
734
        _sblData = new uint8[len + 32];
 
735
 
 
736
        memcpy(_sblData, header, 32);
 
737
        WRITE_LE_UINT32(_sblData + 12, len);
 
738
 
 
739
        const uint8 *src = data + 6;
 
740
        uint8 *dst = _sblData + 32;
 
741
        for (uint32 i = 0; i < len; i++)
 
742
                *dst++ = *src & 0x80 ? (*src++ & 0x7f) : -*src++;
 
743
 
 
744
        _intf->callback(37, 0x3f + chan, 60, 127, _sblData);
 
745
        _pcmCurrentSound[chan].paused = 0;
553
746
}
554
747
 
555
748
} // End of namespace Scumm
556