aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
authorGregory Montoir2007-05-13 16:11:19 +0000
committerGregory Montoir2007-05-13 16:11:19 +0000
commitb5aa521a75017a34b97a44fc1abae8afeb9f6da5 (patch)
treef9c0d5360e1545fc11cd79681db8bf962755b102 /engines
parente6ef2348a4cc17fec41556c130045505035adeca (diff)
downloadscummvm-rg350-b5aa521a75017a34b97a44fc1abae8afeb9f6da5.tar.gz
scummvm-rg350-b5aa521a75017a34b97a44fc1abae8afeb9f6da5.tar.bz2
scummvm-rg350-b5aa521a75017a34b97a44fc1abae8afeb9f6da5.zip
added basic support for sounds playback in Amiga versions (only tested with the demos)
svn-id: r26837
Diffstat (limited to 'engines')
-rw-r--r--engines/cine/anim.cpp13
-rw-r--r--engines/cine/cine.cpp11
-rw-r--r--engines/cine/main_loop.cpp2
-rw-r--r--engines/cine/script.cpp95
-rw-r--r--engines/cine/script.h3
-rw-r--r--engines/cine/sound_driver.cpp71
-rw-r--r--engines/cine/sound_driver.h49
7 files changed, 221 insertions, 23 deletions
diff --git a/engines/cine/anim.cpp b/engines/cine/anim.cpp
index 1b452eefc8..a30c2bdff3 100644
--- a/engines/cine/anim.cpp
+++ b/engines/cine/anim.cpp
@@ -395,6 +395,18 @@ void loadSpl(const char *resourceName) {
strcpy(animDataTable[entry].name, currentPartName);
}
+void loadSplAbs(const char *resourceName, uint16 idx) {
+ int16 foundFileIdx;
+ byte *dataPtr;
+ int16 entry;
+
+ foundFileIdx = findFileInBundle(resourceName);
+ dataPtr = readBundleFile(foundFileIdx);
+
+ entry = reserveFrame((uint16) partBuffer[foundFileIdx].unpackedSize, 1, 0, idx);
+ memcpy(animDataTable[entry].ptr1, dataPtr, partBuffer[foundFileIdx].unpackedSize);
+}
+
void loadMsk(const char *resourceName) {
int16 foundFileIdx;
byte *dataPtr;
@@ -877,6 +889,7 @@ void loadAbs(const char *resourceName, uint16 idx) {
loadSeqAbs(resourceName, idx);
return;
} else if (strstr(resourceName, ".SPL")) {
+ loadSplAbs(resourceName, idx);
return;
} else if (strstr(resourceName, ".AMI")) {
return;
diff --git a/engines/cine/cine.cpp b/engines/cine/cine.cpp
index 1a2ae7f53b..c6fde9cbba 100644
--- a/engines/cine/cine.cpp
+++ b/engines/cine/cine.cpp
@@ -95,10 +95,15 @@ int CineEngine::init() {
_system->initSize(320, 200);
_system->endGFXTransaction();
- if (g_cine->getGameType() == GType_FW) {
- g_soundDriver = new AdlibSoundDriverINS(_mixer);
+ if (g_cine->getPlatform() == Common::kPlatformPC) {
+ if (g_cine->getGameType() == GType_FW) {
+ g_soundDriver = new AdlibSoundDriverINS(_mixer);
+ } else {
+ g_soundDriver = new AdlibSoundDriverADL(_mixer);
+ }
} else {
- g_soundDriver = new AdlibSoundDriverADL(_mixer);
+ // Paula chipset for Amiga and Atari versions
+ g_soundDriver = new PaulaSoundDriver(_mixer);
}
g_sfxPlayer = new SfxPlayer(g_soundDriver);
g_saveFileMan = _saveFileMan;
diff --git a/engines/cine/main_loop.cpp b/engines/cine/main_loop.cpp
index 7bf537b17c..33f25a43e4 100644
--- a/engines/cine/main_loop.cpp
+++ b/engines/cine/main_loop.cpp
@@ -32,6 +32,7 @@
#include "cine/sfx_player.h"
#include "cine/various.h"
#include "cine/bg_list.h"
+#include "cine/sound_driver.h"
namespace Cine {
@@ -156,6 +157,7 @@ void manageEvents(int count) {
if (i % 2)
g_system->updateScreen();
g_system->delayMillis(10);
+ g_soundDriver->update();
manageEvents(0);
}
}
diff --git a/engines/cine/script.cpp b/engines/cine/script.cpp
index c0c1e82b10..bff7344bf7 100644
--- a/engines/cine/script.cpp
+++ b/engines/cine/script.cpp
@@ -356,9 +356,9 @@ void setupOpcodes() {
NULL,
NULL,
NULL,
- o1_playSample,
+ o2_playSample,
/* 78 */
- o2_op78,
+ o2_playSampleAlt,
o1_disableSystemMenu,
o1_loadMask5,
o1_unloadMask5,
@@ -1702,16 +1702,31 @@ void o1_loadMusic() {
void o1_playMusic() {
debugC(5, kCineDebugScript, "Line: %d: playMusic()", _currentLine);
+ if (g_cine->getPlatform() == Common::kPlatformAmiga ||
+ g_cine->getPlatform() == Common::kPlatformAtariST) {
+ warning("STUB: o1_playMusic");
+ return;
+ }
g_sfxPlayer->play();
}
void o1_fadeOutMusic() {
debugC(5, kCineDebugScript, "Line: %d: fadeOutMusic()", _currentLine);
+ if (g_cine->getPlatform() == Common::kPlatformAmiga ||
+ g_cine->getPlatform() == Common::kPlatformAtariST) {
+ warning("STUB: o1_fadeOutMusic");
+ return;
+ }
g_sfxPlayer->fadeOut();
}
void o1_stopSample() {
debugC(5, kCineDebugScript, "Line: %d: stopSample()", _currentLine);
+ if (g_cine->getPlatform() == Common::kPlatformAmiga ||
+ g_cine->getPlatform() == Common::kPlatformAtariST) {
+ warning("STUB: o1_stopSample");
+ return;
+ }
g_sfxPlayer->stop();
}
@@ -1737,9 +1752,46 @@ void o1_op73() {
getNextWord();
}
+void o1_playSampleAmiga() {
+ int num = getNextByte();
+ int channel = getNextByte();
+ int freq = getNextWord();
+ int repeat = getNextByte();
+ int volume = getNextWord();
+ int size = getNextWord();
+
+ if (size == 0xFFFF) {
+ size = animDataTable[num].width * animDataTable[num].height;
+ }
+
+ if (channel < 10) { // || _currentOpcode == 0x78
+ int channel1, channel2;
+ if (channel == 0) {
+ channel1 = 0;
+ channel2 = 1;
+ } else {
+ channel1 = 2;
+ channel2 = 3;
+ }
+ ((PaulaSoundDriver *)g_soundDriver)->queueSound(channel1, freq, animDataTable[num].ptr1, size, -1, volume, 63, repeat);
+ ((PaulaSoundDriver *)g_soundDriver)->queueSound(channel2, freq, animDataTable[num].ptr1, size, 1, volume, 0, repeat);
+ } else {
+ channel -= 10;
+ if (volume > 63) {
+ volume = 63;
+ }
+ ((PaulaSoundDriver *)g_soundDriver)->queueSound(channel, freq, animDataTable[num].ptr1, size, 0, 0, volume, repeat);
+ }
+}
+
void o1_playSample() {
debugC(5, kCineDebugScript, "Line: %d: playSample()", _currentLine);
+ if (g_cine->getPlatform() == Common::kPlatformAmiga || g_cine->getPlatform() == Common::kPlatformAtariST) {
+ o1_playSampleAmiga();
+ return;
+ }
+
byte anim = getNextByte();
byte channel = getNextByte();
@@ -1749,12 +1801,6 @@ void o1_playSample() {
int16 volume = getNextWord();
uint16 flag = getNextWord();
- if (g_cine->getPlatform() == Common::kPlatformAmiga ||
- g_cine->getPlatform() == Common::kPlatformAtariST) {
- warning("STUB: o1_playSample");
- return;
- }
-
if (volume > 63)
volume = 63;
if (volume < 0)
@@ -1771,7 +1817,7 @@ void o1_playSample() {
g_sfxPlayer->stop();
if (flag == 0xFFFF) {
- g_soundDriver->playSound(animDataTable[anim].ptr1, channel, volume);
+ g_soundDriver->playSound(animDataTable[anim].ptr1, 0, channel, volume);
} else {
g_soundDriver->resetChannel(channel);
}
@@ -1809,12 +1855,37 @@ void o2_loadPart() {
debugC(5, kCineDebugScript, "Line: %d: loadPart(\"%s\")", _currentLine, param);
}
-void o2_op78() {
- warning("STUB: o2_op78()");
- // This is probably wrong, but preserve the old behaviour for now.
+void o2_playSample() {
+ if (g_cine->getPlatform() == Common::kPlatformAmiga || g_cine->getPlatform() == Common::kPlatformAtariST) {
+ // no-op in these versions
+ _currentPosition += 9;
+ return;
+ }
o1_playSample();
}
+void o2_playSampleAlt() {
+ int num = getNextByte();
+ int channel = getNextByte();
+ int freq = getNextWord();
+ getNextByte();
+ getNextWord();
+ int size = getNextWord();
+
+ if (size == 0xFFFF) {
+ size = animDataTable[num].width * animDataTable[num].height;
+ }
+ if (animDataTable[num].ptr1) {
+ if (g_cine->getPlatform() == Common::kPlatformPC) {
+ // if speaker output is enabled, play sound on it
+ // if it's another device, don't play anything
+ } else {
+ g_soundDriver->setChannelFrequency(channel, freq);
+ g_soundDriver->playSound(animDataTable[num].ptr1, size, channel, 63);
+ }
+ }
+}
+
void o2_addSeqListElement() {
byte param1 = getNextByte();
byte param2 = getNextByte();
diff --git a/engines/cine/script.h b/engines/cine/script.h
index e777c1fb6f..91e403d701 100644
--- a/engines/cine/script.h
+++ b/engines/cine/script.h
@@ -146,7 +146,8 @@ void o1_unloadMask5();
void o2_loadPart();
void o2_addSeqListElement();
void o2_removeSeq();
-void o2_op78();
+void o2_playSample();
+void o2_playSampleAlt();
void o2_op81();
void o2_op82();
void o2_isSeqRunning();
diff --git a/engines/cine/sound_driver.cpp b/engines/cine/sound_driver.cpp
index 5d1c71cef8..19d94e38a3 100644
--- a/engines/cine/sound_driver.cpp
+++ b/engines/cine/sound_driver.cpp
@@ -283,7 +283,7 @@ void AdlibSoundDriverINS::setChannelFrequency(int channel, int frequency) {
}
}
-void AdlibSoundDriverINS::playSound(const byte *data, int channel, int volume) {
+void AdlibSoundDriverINS::playSound(const byte *data, int size, int channel, int volume) {
assert(channel < 4);
_channelsVolumeTable[channel] = 127;
resetChannel(channel);
@@ -356,7 +356,7 @@ void AdlibSoundDriverADL::setChannelFrequency(int channel, int frequency) {
}
}
-void AdlibSoundDriverADL::playSound(const byte *data, int channel, int volume) {
+void AdlibSoundDriverADL::playSound(const byte *data, int size, int channel, int volume) {
assert(channel < 4);
_channelsVolumeTable[channel] = 127;
setupInstrument(data, channel);
@@ -429,4 +429,71 @@ const int AdlibSoundDriver::_voiceOperatorsTable[] = {
const int AdlibSoundDriver::_voiceOperatorsTableCount = ARRAYSIZE(_voiceOperatorsTable);
+
+PaulaSoundDriver::PaulaSoundDriver(Audio::Mixer *mixer)
+ : _mixer(mixer) {
+ memset(_channelsFreqTable, 0, sizeof(_channelsFreqTable));
+ memset(_soundsQueue, 0, sizeof(_soundsQueue));
+}
+
+void PaulaSoundDriver::setupChannel(int channel, const byte *data, int instrument, int volume) {
+}
+
+void PaulaSoundDriver::setChannelFrequency(int channel, int frequency) {
+ assert(frequency > 0);
+ _channelsFreqTable[channel] = PAULA_FREQ / frequency;
+}
+
+void PaulaSoundDriver::stopChannel(int channel) {
+ _mixer->stopHandle(_channelsTable[channel]);
+}
+
+void PaulaSoundDriver::playSound(const byte *data, int size, int channel, int volume) {
+ stopChannel(channel);
+ size = MIN<int>(size - SPL_HDR_SIZE, READ_BE_UINT16(data + 4));
+ data += SPL_HDR_SIZE;
+ if (size > 0) {
+ _mixer->playRaw(Audio::Mixer::kSFXSoundType, &_channelsTable[channel], const_cast<byte *>(data), size, _channelsFreqTable[channel], 0);
+ _mixer->setChannelVolume(_channelsTable[channel], volume * Audio::Mixer::kMaxChannelVolume / 63);
+ }
+}
+
+void PaulaSoundDriver::stopSound() {
+ for (int i = 0; i < NUM_CHANNELS; ++i) {
+ _mixer->stopHandle(_channelsTable[i]);
+ }
+}
+
+void PaulaSoundDriver::queueSound(int channel, int frequency, const uint8 *data, int size, int volumeStep, int stepCount, int volume, int repeat) {
+ SoundQueue *sq = &_soundsQueue[channel];
+ sq->freq = frequency;
+ sq->data = data;
+ sq->size = size;
+ sq->volumeStep = volumeStep;
+ sq->stepCount = stepCount;
+ sq->step = stepCount;
+ sq->repeat = repeat != 0;
+ sq->volume = volume;
+}
+
+void PaulaSoundDriver::update() {
+ // process volume slides and start sound playback
+ for (int i = 0; i < NUM_CHANNELS; ++i) {
+ SoundQueue *sq = &_soundsQueue[i];
+ if (sq->data) {
+ if (sq->step) {
+ --sq->step;
+ continue;
+ }
+ sq->step = sq->stepCount;
+ sq->volume = CLIP(sq->volume + sq->volumeStep, 0, 63);
+ setChannelFrequency(i, sq->freq);
+ playSound(sq->data, sq->size, i, sq->volume);
+ if (!sq->repeat) {
+ sq->data = 0;
+ }
+ }
+ }
+}
+
} // End of namespace Cine
diff --git a/engines/cine/sound_driver.h b/engines/cine/sound_driver.h
index c6fc571f89..6ca1fa8f5a 100644
--- a/engines/cine/sound_driver.h
+++ b/engines/cine/sound_driver.h
@@ -30,7 +30,7 @@
#include "sound/mixer.h"
namespace Cine {
-
+
class SoundDriver {
public:
typedef void (*UpdateCallback)(void *);
@@ -40,9 +40,10 @@ public:
virtual void setupChannel(int channel, const byte *data, int instrument, int volume) = 0;
virtual void setChannelFrequency(int channel, int frequency) = 0;
virtual void stopChannel(int channel) = 0;
- virtual void playSound(const byte *data, int channel, int volume) = 0;
+ virtual void playSound(const byte *data, int size, int channel, int volume) = 0;
virtual void stopSound() = 0;
- virtual const char *getInstrumentExtension() const = 0;
+ virtual const char *getInstrumentExtension() const { return ""; }
+ virtual void update() {}
void setUpdateCallback(UpdateCallback upCb, void *ref);
void resetChannel(int channel);
@@ -123,7 +124,7 @@ public:
virtual const char *getInstrumentExtension() const { return ".INS"; }
virtual void loadInstrument(const byte *data, AdlibSoundInstrument *asi);
virtual void setChannelFrequency(int channel, int frequency);
- virtual void playSound(const byte *data, int channel, int volume);
+ virtual void playSound(const byte *data, int size, int channel, int volume);
};
// Operation Stealth adlib driver
@@ -133,7 +134,45 @@ public:
virtual const char *getInstrumentExtension() const { return ".ADL"; }
virtual void loadInstrument(const byte *data, AdlibSoundInstrument *asi);
virtual void setChannelFrequency(int channel, int frequency);
- virtual void playSound(const byte *data, int channel, int volume);
+ virtual void playSound(const byte *data, int size, int channel, int volume);
+};
+
+class PaulaSoundDriver : public SoundDriver {
+public:
+ PaulaSoundDriver(Audio::Mixer *mixer);
+
+ virtual void setupChannel(int channel, const byte *data, int instrument, int volume);
+ virtual void setChannelFrequency(int channel, int frequency);
+ virtual void stopChannel(int channel);
+ virtual void playSound(const byte *data, int size, int channel, int volume);
+ virtual void stopSound();
+
+ // Future Wars specific
+ void queueSound(int channel, int frequency, const uint8 *data, int size, int volumeStep, int stepCount, int volume, int repeat);
+ virtual void update();
+
+ enum {
+ PAULA_FREQ = 7093789,
+ NUM_CHANNELS = 4,
+ SPL_HDR_SIZE = 22
+ };
+
+ struct SoundQueue {
+ int freq;
+ const uint8 *data;
+ int size;
+ int volumeStep;
+ int stepCount;
+ int step;
+ bool repeat;
+ int volume;
+ };
+
+private:
+ Audio::Mixer *_mixer;
+ Audio::SoundHandle _channelsTable[NUM_CHANNELS];
+ uint _channelsFreqTable[NUM_CHANNELS];
+ SoundQueue _soundsQueue[NUM_CHANNELS];
};
extern SoundDriver *g_soundDriver; // TEMP