aboutsummaryrefslogtreecommitdiff
path: root/engines/scumm/player_towns.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/scumm/player_towns.cpp')
-rw-r--r--engines/scumm/player_towns.cpp345
1 files changed, 180 insertions, 165 deletions
diff --git a/engines/scumm/player_towns.cpp b/engines/scumm/player_towns.cpp
index 871bd67546..bb7985f6da 100644
--- a/engines/scumm/player_towns.cpp
+++ b/engines/scumm/player_towns.cpp
@@ -29,15 +29,159 @@
namespace Scumm {
-Player_Towns::Player_Towns(ScummEngine *vm, Audio::Mixer *mixer) : _vm(vm) {
+Player_Towns::Player_Towns(ScummEngine *vm) : _vm(vm) {
+ memset(_pcmCurrentSound, 0, sizeof(_pcmCurrentSound));
+ memset(&_ovrCur, 0, sizeof(SoundOvrParameters));
+ _soundOverride = 0;
+ _unkFlags = 0x33;
+ _intf = 0;
+}
+
+void Player_Towns::saveLoadWithSerializer(Serializer *ser) {
+ static const SaveLoadEntry pcmEntries[] = {
+ MKLINE(PcmCurrentSound, index, sleInt16, VER(81)),
+ MKLINE(PcmCurrentSound, chan, sleInt16, VER(81)),
+ MKLINE(PcmCurrentSound, note, sleUint8, VER(81)),
+ MKLINE(PcmCurrentSound, velo, sleUint8, VER(81)),
+ MKLINE(PcmCurrentSound, pan, sleUint8, VER(81)),
+ MKLINE(PcmCurrentSound, paused, sleUint8, VER(81)),
+ MKLINE(PcmCurrentSound, looping, sleUint8, VER(81)),
+ MKLINE(PcmCurrentSound, priority, sleUint32, VER(81)),
+ MKEND()
+ };
+
+ for (int i = 1; i < 9; i++) {
+ if (!_pcmCurrentSound[i].index)
+ continue;
+
+ if (_intf->callback(40, i + 0x3f))
+ continue;
+
+ _intf->callback(39, i + 0x3f);
+
+ _pcmCurrentSound[i].index = 0;
+ }
+
+ ser->saveLoadArrayOf(_pcmCurrentSound, 9, sizeof(PcmCurrentSound), pcmEntries);
+}
+
+void Player_Towns::restoreAfterLoad() {
+ for (int i = 1; i < 9; i++) {
+ if (!_pcmCurrentSound[i].index)
+ continue;
+
+ uint8 *ptr = _vm->getResourceAddress(rtSound, _pcmCurrentSound[i].index);
+ if (!ptr)
+ continue;
+
+ if (_vm->_game.version != 3)
+ ptr += 2;
+
+ if (ptr[13])
+ continue;
+
+ playPcmTrack(_pcmCurrentSound[i].index, ptr + 6, _pcmCurrentSound[i].velo, _pcmCurrentSound[i].pan, _pcmCurrentSound[i].note);
+ }
+}
+
+void Player_Towns::playPcmTrack(int sound, const uint8 *data, int velo, int pan, int note) {
+ const uint8 *ptr = data;
+ const uint8 *sfxData = ptr + 16;
+
+ int note2, velocity;
+
+ if (velo)
+ velocity = velo;
+ else if (_ovrCur.vLeft + _ovrCur.vRight)
+ velocity = (_ovrCur.vLeft + _ovrCur.vRight) >> 2;
+ else
+ velocity = ptr[8] >> 1;
+
+ int numChan = ptr[14];
+ for (int i = 0; i < numChan; i++) {
+ int chan = getNextFreePcmChannel(sound, i);
+ if (!chan)
+ return;
+
+ _intf->callback(70, _unkFlags);
+ _intf->callback(3, chan + 0x3f, pan);
+
+ if (note)
+ note2 = note;
+ else if (_ovrCur.note)
+ note2 = _ovrCur.note;
+ else
+ note2 = sfxData[28];
+
+ _intf->callback(37, chan + 0x3f, note2, velocity, sfxData);
+
+ _pcmCurrentSound[chan].note = note2;
+ _pcmCurrentSound[chan].velo = velocity;
+ _pcmCurrentSound[chan].pan = pan;
+ _pcmCurrentSound[chan].paused = 0;
+ _pcmCurrentSound[chan].looping = READ_LE_UINT32(&sfxData[20]) ? 1 : 0;
+
+ sfxData += (READ_LE_UINT32(&sfxData[12]) + 32);
+ }
+}
+
+void Player_Towns::stopPcmTrack(int sound) {
+ for (int i = 1; i < 9; i++) {
+ if (sound == _pcmCurrentSound[i].index || !sound) {
+ _intf->callback(39, i + 0x3f);
+ _pcmCurrentSound[i].index = 0;
+ }
+ }
+}
+
+int Player_Towns::getNextFreePcmChannel(int sound, int sfxChanRelIndex) {
+ int chan = 0;
+ for (int i = 8; i; i--) {
+ if (!_pcmCurrentSound[i].index) {
+ chan = i;
+ continue;
+ }
+
+ if (_intf->callback(40, i + 0x3f))
+ continue;
+
+ chan = i;
+ _vm->_sound->stopSound(_pcmCurrentSound[chan].index);
+ }
+
+ if (!chan) {
+ uint16 l = 0xffff;
+ uint8 *ptr = 0;
+ for (int i = 8; i; i--) {
+ ptr = _vm->getResourceAddress(rtSound, _pcmCurrentSound[i].index) + 6;
+ uint16 a = READ_LE_UINT16(ptr + 10);
+ if (a <= l) {
+ chan = i;
+ l = a;
+ }
+ }
+
+ ptr = _vm->getResourceAddress(rtSound, sound) + 6;
+ if (l <= READ_LE_UINT16(ptr + 10))
+ _vm->_sound->stopSound(_pcmCurrentSound[chan].index);
+ else
+ chan = 0;
+ }
+
+ if (chan) {
+ _pcmCurrentSound[chan].index = sound;
+ _pcmCurrentSound[chan].chan = sfxChanRelIndex;
+ }
+
+ return chan;
+}
+
+Player_Towns_v1::Player_Towns_v1(ScummEngine *vm, Audio::Mixer *mixer) : Player_Towns(vm) {
_cdaCurrentSound = _eupCurrentSound = _cdaNumLoops = 0;
_cdaForceRestart = 0;
- memset(_pcmCurrentSound, 0, sizeof(_pcmCurrentSound));
_cdaVolLeft = _cdaVolRight = 0;
_eupVolLeft = _eupVolRight = 0;
- memset(&_ovrCur, 0, sizeof(SoundOvrParameters));
- _soundOverride = 0;
if (_vm->_game.version == 3) {
_soundOverride = new SoundOvrParameters[200];
@@ -45,17 +189,16 @@ Player_Towns::Player_Towns(ScummEngine *vm, Audio::Mixer *mixer) : _vm(vm) {
}
_eupLooping = false;
- _unkFlags = 0x33;
_driver = new TownsEuphonyDriver(mixer);
}
-Player_Towns::~Player_Towns() {
+Player_Towns_v1::~Player_Towns_v1() {
delete[] _soundOverride;
delete _driver;
}
-bool Player_Towns::init() {
+bool Player_Towns_v1::init() {
if (!_driver)
return false;
@@ -63,26 +206,27 @@ bool Player_Towns::init() {
return false;
_driver->reserveSoundEffectChannels(8);
+ _intf = _driver->intf();
// Treat all 6 fm channels and all 8 pcm channels as sound effect channels
// since music seems to exist as CD audio only in the games which use this
// MusicEngine implementation.
- _driver->intf()->setSoundEffectChanMask(-1);
+ _intf->setSoundEffectChanMask(-1);
setVolumeCD(255, 255);
return true;
}
-void Player_Towns::setMusicVolume(int vol) {
+void Player_Towns_v1::setMusicVolume(int vol) {
_driver->setMusicVolume(vol);
}
-void Player_Towns::setSfxVolume(int vol) {
+void Player_Towns_v1::setSfxVolume(int vol) {
_driver->setSoundEffectVolume(vol);
}
-void Player_Towns::startSound(int sound) {
+void Player_Towns_v1::startSound(int sound) {
uint8 *ptr = _vm->getResourceAddress(rtSound, sound);
if (_vm->_game.version != 3) {
ptr += 2;
@@ -103,7 +247,7 @@ void Player_Towns::startSound(int sound) {
memset(&_ovrCur, 0, sizeof(SoundOvrParameters));
}
-void Player_Towns::stopSound(int sound) {
+void Player_Towns_v1::stopSound(int sound) {
if (sound == 0 || sound == _cdaCurrentSound) {
_cdaCurrentSound = 0;
_vm->_sound->stopCD();
@@ -119,7 +263,7 @@ void Player_Towns::stopSound(int sound) {
stopPcmTrack(sound);
}
-void Player_Towns::stopAllSounds() {
+void Player_Towns_v1::stopAllSounds() {
_cdaCurrentSound = 0;
_vm->_sound->stopCD();
_vm->_sound->stopCDTimer();
@@ -131,7 +275,7 @@ void Player_Towns::stopAllSounds() {
stopPcmTrack(0);
}
-int Player_Towns::getSoundStatus(int sound) const {
+int Player_Towns_v1::getSoundStatus(int sound) const {
if (sound == _cdaCurrentSound)
return _vm->_sound->pollCD();
if (sound == _eupCurrentSound)
@@ -143,7 +287,7 @@ int Player_Towns::getSoundStatus(int sound) const {
return 0;
}
-int32 Player_Towns::doCommand(int numargs, int args[]) {
+int32 Player_Towns_v1::doCommand(int numargs, int args[]) {
int32 res = 0;
switch (args[0]) {
@@ -176,40 +320,40 @@ int32 Player_Towns::doCommand(int numargs, int args[]) {
break;
default:
- warning("Player_Towns::doCommand: Unknown command %d", args[0]);
+ warning("Player_Towns_v1::doCommand: Unknown command %d", args[0]);
break;
}
return res;
}
-void Player_Towns::setVolumeCD(int left, int right) {
+void Player_Towns_v1::setVolumeCD(int left, int right) {
_cdaVolLeft = left & 0xff;
_cdaVolRight = right & 0xff;
_driver->setOutputVolume(1, left >> 1, right >> 1);
}
-void Player_Towns::setSoundVolume(int sound, int left, int right) {
+void Player_Towns_v1::setSoundVolume(int sound, int left, int right) {
if (_soundOverride && sound > 0 && sound < 200) {
_soundOverride[sound].vLeft = left;
_soundOverride[sound].vRight = right;
}
}
-void Player_Towns::setSoundNote(int sound, int note) {
+void Player_Towns_v1::setSoundNote(int sound, int note) {
if (_soundOverride && sound > 0 && sound < 200)
_soundOverride[sound].note = note;
}
-void Player_Towns::saveLoadWithSerializer(Serializer *ser) {
+void Player_Towns_v1::saveLoadWithSerializer(Serializer *ser) {
_cdaCurrentSoundTemp = (_vm->_sound->pollCD() && _cdaNumLoops > 1) ? _cdaCurrentSound & 0xff : 0;
_cdaNumLoopsTemp = _cdaNumLoops & 0xff;
static const SaveLoadEntry cdEntries[] = {
- MKLINE(Player_Towns, _cdaCurrentSoundTemp, sleUint8, VER(81)),
- MKLINE(Player_Towns, _cdaNumLoopsTemp, sleUint8, VER(81)),
- MKLINE(Player_Towns, _cdaVolLeft, sleUint8, VER(81)),
- MKLINE(Player_Towns, _cdaVolRight, sleUint8, VER(81)),
+ MKLINE(Player_Towns_v1, _cdaCurrentSoundTemp, sleUint8, VER(81)),
+ MKLINE(Player_Towns_v1, _cdaNumLoopsTemp, sleUint8, VER(81)),
+ MKLINE(Player_Towns_v1, _cdaVolLeft, sleUint8, VER(81)),
+ MKLINE(Player_Towns_v1, _cdaVolRight, sleUint8, VER(81)),
MKEND()
};
@@ -219,43 +363,19 @@ void Player_Towns::saveLoadWithSerializer(Serializer *ser) {
_eupCurrentSound = 0;
static const SaveLoadEntry eupEntries[] = {
- MKLINE(Player_Towns, _eupCurrentSound, sleUint8, VER(81)),
- MKLINE(Player_Towns, _eupLooping, sleUint8, VER(81)),
- MKLINE(Player_Towns, _eupVolLeft, sleUint8, VER(81)),
- MKLINE(Player_Towns, _eupVolRight, sleUint8, VER(81)),
+ MKLINE(Player_Towns_v1, _eupCurrentSound, sleUint8, VER(81)),
+ MKLINE(Player_Towns_v1, _eupLooping, sleUint8, VER(81)),
+ MKLINE(Player_Towns_v1, _eupVolLeft, sleUint8, VER(81)),
+ MKLINE(Player_Towns_v1, _eupVolRight, sleUint8, VER(81)),
MKEND()
};
ser->saveLoadEntries(this, eupEntries);
- static const SaveLoadEntry pcmEntries[] = {
- MKLINE(PcmCurrentSound, index, sleInt16, VER(81)),
- MKLINE(PcmCurrentSound, chan, sleInt16, VER(81)),
- MKLINE(PcmCurrentSound, note, sleUint8, VER(81)),
- MKLINE(PcmCurrentSound, velo, sleUint8, VER(81)),
- MKLINE(PcmCurrentSound, pan, sleUint8, VER(81)),
- MKLINE(PcmCurrentSound, paused, sleUint8, VER(81)),
- MKLINE(PcmCurrentSound, looping, sleUint8, VER(81)),
- MKLINE(PcmCurrentSound, priority, sleUint32, VER(81)),
- MKEND()
- };
-
- for (int i = 1; i < 9; i++) {
- if (!_pcmCurrentSound[i].index)
- continue;
-
- if (_driver->soundEffectIsPlaying(i + 0x3f))
- continue;
-
- _driver->stopSoundEffect(i + 0x3f);
-
- _pcmCurrentSound[i].index = 0;
- }
-
- ser->saveLoadArrayOf(_pcmCurrentSound, 9, sizeof(PcmCurrentSound), pcmEntries);
+ Player_Towns::saveLoadWithSerializer(ser);
}
-void Player_Towns::restoreAfterLoad() {
+void Player_Towns_v1::restoreAfterLoad() {
setVolumeCD(_cdaVolLeft, _cdaVolRight);
if (_cdaCurrentSoundTemp) {
@@ -281,67 +401,12 @@ void Player_Towns::restoreAfterLoad() {
}
}
- for (int i = 1; i < 9; i++) {
- if (!_pcmCurrentSound[i].index)
- continue;
-
- uint8 *ptr = _vm->getResourceAddress(rtSound, _pcmCurrentSound[i].index);
- if (!ptr)
- continue;
-
- if (_vm->_game.version != 3)
- ptr += 2;
-
- if (ptr[13])
- continue;
-
- playPcmTrack(_pcmCurrentSound[i].index, ptr + 6, _pcmCurrentSound[i].velo, _pcmCurrentSound[i].pan, _pcmCurrentSound[i].note);
- }
+ Player_Towns::restoreAfterLoad();
}
-int Player_Towns::getNextFreePcmChannel(int sound, int sfxChanRelIndex) {
- int chan = 0;
- for (int i = 8; i; i--) {
- if (!_pcmCurrentSound[i].index) {
- chan = i;
- continue;
- }
-
- if (_driver->soundEffectIsPlaying(i + 0x3f))
- continue;
-
- chan = i;
- _vm->_sound->stopSound(_pcmCurrentSound[chan].index);
- }
-
- if (!chan) {
- uint16 l = 0xffff;
- uint8 *ptr = 0;
- for (int i = 8; i; i--) {
- ptr = _vm->getResourceAddress(rtSound, _pcmCurrentSound[i].index) + 6;
- uint16 a = READ_LE_UINT16(ptr + 10);
- if (a <= l) {
- chan = i;
- l = a;
- }
- }
-
- ptr = _vm->getResourceAddress(rtSound, sound) + 6;
- if (l <= READ_LE_UINT16(ptr + 10))
- _vm->_sound->stopSound(_pcmCurrentSound[chan].index);
- else
- chan = 0;
- }
-
- if (chan) {
- _pcmCurrentSound[chan].index = sound;
- _pcmCurrentSound[chan].chan = sfxChanRelIndex;
- }
- return chan;
-}
-void Player_Towns::restartLoopingSounds() {
+void Player_Towns_v1::restartLoopingSounds() {
if (_cdaNumLoops && !_cdaForceRestart)
_cdaForceRestart = 1;
@@ -368,7 +433,7 @@ void Player_Towns::restartLoopingSounds() {
_driver->intf()->callback(73, 1);
}
-void Player_Towns::startSoundEx(int sound, int velo, int pan, int note) {
+void Player_Towns_v1::startSoundEx(int sound, int velo, int pan, int note) {
uint8 *ptr = _vm->getResourceAddress(rtSound, sound) + 2;
if (pan > 99)
@@ -405,7 +470,7 @@ void Player_Towns::startSoundEx(int sound, int velo, int pan, int note) {
}
}
-void Player_Towns::stopSoundSuspendLooping(int sound) {
+void Player_Towns_v1::stopSoundSuspendLooping(int sound) {
if (!sound) {
return;
} else if (sound == _cdaCurrentSound) {
@@ -426,7 +491,7 @@ void Player_Towns::stopSoundSuspendLooping(int sound) {
}
}
-void Player_Towns::playEuphonyTrack(int sound, const uint8 *data) {
+void Player_Towns_v1::playEuphonyTrack(int sound, const uint8 *data) {
const uint8 *pos = data + 16;
const uint8 *src = pos + data[14] * 48;
const uint8 *trackData = src + 150;
@@ -474,48 +539,7 @@ void Player_Towns::playEuphonyTrack(int sound, const uint8 *data) {
_eupCurrentSound = sound;
}
-void Player_Towns::playPcmTrack(int sound, const uint8 *data, int velo, int pan, int note) {
- const uint8 *ptr = data;
- const uint8 *sfxData = ptr + 16;
-
- int note2, velocity;
-
- if (velo)
- velocity = velo;
- else if (_ovrCur.vLeft + _ovrCur.vRight)
- velocity = (_ovrCur.vLeft + _ovrCur.vRight) >> 2;
- else
- velocity = ptr[8] >> 1;
-
- int numChan = ptr[14];
- for (int i = 0; i < numChan; i++) {
- int chan = getNextFreePcmChannel(sound, i);
- if (!chan)
- return;
-
- _driver->intf()->callback(70, _unkFlags);
- _driver->chanPanPos(chan + 0x3f, pan);
-
- if (note)
- note2 = note;
- else if (_ovrCur.note)
- note2 = _ovrCur.note;
- else
- note2 = sfxData[28];
-
- _driver->playSoundEffect(chan + 0x3f, note2, velocity, sfxData);
-
- _pcmCurrentSound[chan].note = note2;
- _pcmCurrentSound[chan].velo = velocity;
- _pcmCurrentSound[chan].pan = pan;
- _pcmCurrentSound[chan].paused = 0;
- _pcmCurrentSound[chan].looping = READ_LE_UINT32(&sfxData[20]) ? 1 : 0;
-
- sfxData += (READ_LE_UINT32(&sfxData[12]) + 32);
- }
-}
-
-void Player_Towns::playCdaTrack(int sound, const uint8 *data, bool skipTrackVelo) {
+void Player_Towns_v1::playCdaTrack(int sound, const uint8 *data, bool skipTrackVelo) {
const uint8 *ptr = data;
if (!sound)
@@ -543,14 +567,5 @@ void Player_Towns::playCdaTrack(int sound, const uint8 *data, bool skipTrackVelo
_cdaCurrentSound = sound;
}
-void Player_Towns::stopPcmTrack(int sound) {
- for (int i = 1; i < 9; i++) {
- if (sound == _pcmCurrentSound[i].index || !sound) {
- _driver->stopSoundEffect(i + 0x3f);
- _pcmCurrentSound[i].index = 0;
- }
- }
-}
-
} // End of namespace Scumm