added basic support for sounds playback in Amiga versions (only tested with the demos)

svn-id: r26837
This commit is contained in:
Gregory Montoir 2007-05-13 16:11:19 +00:00
parent e6ef2348a4
commit b5aa521a75
7 changed files with 221 additions and 23 deletions

View File

@ -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;

View File

@ -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;

View File

@ -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);
}
}

View File

@ -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();

View File

@ -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();

View File

@ -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

View File

@ -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