aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGregory Montoir2007-01-21 22:08:02 +0000
committerGregory Montoir2007-01-21 22:08:02 +0000
commitd2f15566d3dfc0f72e10a74198073f17540e598c (patch)
tree624db310aaa2ec25b0bf6b76db92d5ae6a43cb70
parent3341f494296ddab50aa81ab9d996154f321a421e (diff)
downloadscummvm-rg350-d2f15566d3dfc0f72e10a74198073f17540e598c.tar.gz
scummvm-rg350-d2f15566d3dfc0f72e10a74198073f17540e598c.tar.bz2
scummvm-rg350-d2f15566d3dfc0f72e10a74198073f17540e598c.zip
added handler for sfx sync (abc-slideshow.cup, bda-slideshow.cup) and sfx looping, cleanup
svn-id: r25158
-rw-r--r--engines/scumm/he/cup_player_he.cpp147
-rw-r--r--engines/scumm/he/cup_player_he.h87
-rw-r--r--engines/scumm/he/intern_he.h2
-rw-r--r--engines/scumm/scumm.cpp10
4 files changed, 157 insertions, 89 deletions
diff --git a/engines/scumm/he/cup_player_he.cpp b/engines/scumm/he/cup_player_he.cpp
index 0676f35b2b..f575a894bb 100644
--- a/engines/scumm/he/cup_player_he.cpp
+++ b/engines/scumm/he/cup_player_he.cpp
@@ -30,6 +30,10 @@
namespace Scumm {
+CUP_Player::CUP_Player(OSystem *sys, ScummEngine_vCUPhe *vm, Audio::Mixer *mixer)
+ : _vm(vm), _mixer(mixer), _system(sys) {
+}
+
bool CUP_Player::open(const char *filename) {
bool opened = false;
debug(1, "opening '%s'", filename);
@@ -37,19 +41,34 @@ bool CUP_Player::open(const char *filename) {
uint32 tag = _fd.readUint32BE();
_fd.readUint32BE();
if (tag == MKID_BE('BEAN')) {
- _playbackRate = 66;
- _width = 640;
- _height = 480;
- _offscreenBuffer = (uint8 *)malloc(_width * _height);
- memset(_offscreenBuffer, 0, _width * _height);
+ _playbackRate = kDefaultPlaybackRate;
+ _width = kDefaultVideoWidth;
+ _height = kDefaultVideoHeight;
+
+ memset(_paletteData, 0, sizeof(_paletteData));
_paletteChanged = false;
+ _offscreenBuffer = 0;
+
+ _currentChunkData = 0;
+ _currentChunkSize = 0;
+ _bufferLzssData = 0;
+ _bufferLzssSize = 0;
+
_sfxCount = 0;
_sfxBuffer = 0;
- _sfxHandleTable = 0;
+ for (int i = 0; i < kSfxChannels; ++i) {
+ _sfxChannels[i].sfxNum = -1;
+ }
memset(_sfxQueue, 0, sizeof(_sfxQueue));
_sfxQueuePos = 0;
+ _lastSfxChannel = -1;
+
parseHeaderTags();
debug(1, "rate %d width %d height %d", _playbackRate, _width, _height);
+
+ _offscreenBuffer = (uint8 *)malloc(_width * _height);
+ memset(_offscreenBuffer, 0, _width * _height);
+
opened = true;
}
}
@@ -59,8 +78,9 @@ bool CUP_Player::open(const char *filename) {
void CUP_Player::close() {
_fd.close();
free(_offscreenBuffer);
+ _offscreenBuffer = 0;
free(_sfxBuffer);
- delete[] _sfxHandleTable;
+ _sfxBuffer = 0;
}
uint32 CUP_Player::loadNextChunk() {
@@ -106,13 +126,12 @@ void CUP_Player::parseHeaderTags() {
void CUP_Player::play() {
int ticks = _system->getMillis();
- while (_currentChunkSize != 0 && !_vm->_quit) {
+ while (_currentChunkSize != 0 && !_vm->_quit && !_fd.ioFailed()) {
uint32 tag, size;
parseNextTag(_currentChunkData, tag, size);
if (tag == MKID_BE('BLOK')) {
- bool fastMode = false;
int diff = _system->getMillis() - ticks;
- if (diff >= 0 && diff <= _playbackRate && !fastMode) {
+ if (diff >= 0 && diff <= _playbackRate) {
_system->delayMillis(_playbackRate - diff);
} else {
_system->delayMillis(1);
@@ -145,36 +164,69 @@ void CUP_Player::updateScreen() {
void CUP_Player::updateSfx() {
for (int i = 0; i < _sfxQueuePos; ++i) {
const CUP_Sfx *sfx = &_sfxQueue[i];
- int index;
if (sfx->num == -1) {
- for (index = 0; index < _sfxCount; ++index) {
- if (_mixer->isSoundHandleActive(_sfxHandleTable[index])) {
+ debug(1, "Stopping sound channel %d", _lastSfxChannel);
+ if (_lastSfxChannel != -1) {
+ _mixer->stopHandle(_sfxChannels[_lastSfxChannel].handle);
+ }
+ continue;
+ }
+ if ((sfx->flags & kSfxFlagRestart) == 0) {
+ bool alreadyPlaying = false;
+ for (int ch = 0; ch < kSfxChannels; ++ch) {
+ if (_mixer->isSoundHandleActive(_sfxChannels[ch].handle) && _sfxChannels[ch].sfxNum == sfx->num) {
+ alreadyPlaying = true;
break;
}
}
- if (index == _sfxCount) {
+ if (alreadyPlaying) {
continue;
}
- } else {
- index = sfx->num - 1;
}
- assert(index >= 0 && index < _sfxCount);
- if (!_mixer->isSoundHandleActive(_sfxHandleTable[index]) || (sfx->mode & 2) != 0) {
- if ((sfx->flags & 0x8000) == 0) {
- warning("Unhandled Sfx looping");
- continue;
+ CUP_SfxChannel *sfxChannel = 0;
+ for (int ch = 0; ch < kSfxChannels; ++ch) {
+ if (!_mixer->isSoundHandleActive(_sfxChannels[ch].handle)) {
+ _lastSfxChannel = ch;
+ sfxChannel = &_sfxChannels[ch];
+ sfxChannel->sfxNum = sfx->num;
+ sfxChannel->flags = sfx->flags;
+ break;
}
- uint32 offset = READ_LE_UINT32(_sfxBuffer + index * 4) - 8;
+ }
+ if (sfxChannel) {
+ debug(1, "Start sound %d channel %d flags 0x%X", sfx->num, _lastSfxChannel, sfx->flags);
+ int sfxIndex = sfxChannel->sfxNum - 1;
+ assert(sfxIndex >= 0 && sfxIndex < _sfxCount);
+ uint32 offset = READ_LE_UINT32(_sfxBuffer + sfxIndex * 4) - 8;
uint8 *soundData = _sfxBuffer + offset;
if (READ_BE_UINT32(soundData) == MKID_BE('DATA')) {
uint32 soundSize = READ_BE_UINT32(soundData + 4);
- _mixer->playRaw(&_sfxHandleTable[index], soundData + 8, soundSize - 8, 11025, Audio::Mixer::FLAG_UNSIGNED);
+ uint32 flags = Audio::Mixer::FLAG_UNSIGNED;
+ uint32 loopEnd = 0;
+ if (sfx->flags & kSfxFlagLoop) {
+ flags |= Audio::Mixer::FLAG_LOOP;
+ loopEnd = soundSize - 8;
+ }
+ _mixer->playRaw(&sfxChannel->handle, soundData + 8, soundSize - 8, 11025, flags, -1, 255, 0, 0, loopEnd);
}
+ } else {
+ warning("Unable to find a free channel to play sound %d", sfx->num);
}
}
_sfxQueuePos = 0;
}
+void CUP_Player::waitForSfxChannel(int channel) {
+ assert(channel >= 0 && channel < kSfxChannels);
+ CUP_SfxChannel *sfxChannel = &_sfxChannels[channel];
+ if ((sfxChannel->flags & kSfxFlagLoop) == 0) {
+ while (_mixer->isSoundHandleActive(sfxChannel->handle) && !_vm->_quit) {
+ _vm->parseEvents();
+ _system->delayMillis(10);
+ }
+ }
+}
+
void CUP_Player::parseNextTag(const uint8 *data, uint32 &tag, uint32 &size) {
tag = READ_BE_UINT32(data);
size = READ_BE_UINT32(data + 4);
@@ -211,7 +263,7 @@ void CUP_Player::parseNextTag(const uint8 *data, uint32 &tag, uint32 &size) {
case MKID_BE('WRLE'):
// this is never triggered
default:
- warning("unhandled tag %s", tag2str(tag));
+ warning("Unhandled tag %s", tag2str(tag));
break;
}
}
@@ -232,21 +284,15 @@ void CUP_Player::handleSFXB(const uint8 *data, uint32 dataSize) {
if (_sfxBuffer) {
memcpy(_sfxBuffer, data + 8, dataSize - 16);
}
- _sfxHandleTable = new Audio::SoundHandle[_sfxCount];
}
}
}
}
void CUP_Player::handleRGBS(const uint8 *data, uint32 dataSize) {
- int i;
- uint8 *ptr = _paletteData;
-
- for (i = 0; i < 256; i++) {
- *ptr++ = *data++;
- *ptr++ = *data++;
- *ptr++ = *data++;
- *ptr++ = 0;
+ for (int i = 0; i < 256; i++) {
+ memcpy(&_paletteData[i * 4], data, 3);
+ data += 3;
}
_paletteChanged = true;
}
@@ -378,20 +424,21 @@ uint8 *CUP_Player::handleLZSS(const uint8 *data, uint32 dataSize) {
data += 8;
uint32 offset1 = READ_LE_UINT32(data);
uint32 offset2 = READ_LE_UINT32(data + 4);
- decodeLzssData(_bufferLzssData, data + 8, data + offset1, data + offset2, _tempLzssBuffer);
+ decodeLZSS(_bufferLzssData, data + 8, data + offset1, data + offset2);
return _bufferLzssData;
}
}
return 0;
}
-void CUP_Player::decodeLzssData(uint8 *dst1, const uint8 *src1, const uint8 *src2, const uint8 *src3, uint8 *dst2) {
+void CUP_Player::decodeLZSS(uint8 *dst, const uint8 *src1, const uint8 *src2, const uint8 *src3) {
+ uint8 wnd[4096];
int index = 1;
while (1) {
int code = *src1++;
for (int b = 0; b < 8; ++b) {
if (code & (1 << b)) {
- *dst1++ = dst2[index] = *src2++;
+ *dst++ = wnd[index] = *src2++;
++index;
index &= 0xFFF;
} else {
@@ -402,7 +449,7 @@ void CUP_Player::decodeLzssData(uint8 *dst1, const uint8 *src1, const uint8 *src
return;
}
while (count--) {
- *dst1++ = dst2[index] = dst2[offs];
+ *dst++ = wnd[index] = wnd[offs];
++index;
index &= 0xFFF;
++offs;
@@ -419,14 +466,13 @@ void CUP_Player::handleRATE(const uint8 *data, uint32 dataSize) {
}
void CUP_Player::handleSNDE(const uint8 *data, uint32 dataSize) {
- if (_sfxQueuePos < ARRAYSIZE(_sfxQueue)) {
- CUP_Sfx *sfx = &_sfxQueue[_sfxQueuePos];
- sfx->mode = READ_LE_UINT32(data);
- sfx->num = (int16)READ_LE_UINT16(data + 4);
- // READ_LE_UINT16(data + 6); // unused
- sfx->flags = READ_LE_UINT16(data + 8);
- ++_sfxQueuePos;
- }
+ assert(_sfxQueuePos < kSfxQueueSize);
+ CUP_Sfx *sfx = &_sfxQueue[_sfxQueuePos];
+ sfx->flags = READ_LE_UINT32(data);
+ sfx->num = READ_LE_UINT16(data + 4);
+ uint16 loop = READ_LE_UINT16(data + 8);
+ assert((loop & 0x8000) != 0); // this is never triggered
+ ++_sfxQueuePos;
}
void CUP_Player::handleTOIL(const uint8 *data, uint32 dataSize) {
@@ -443,18 +489,21 @@ void CUP_Player::handleTOIL(const uint8 *data, uint32 dataSize) {
}
switch (code) {
case 1:
+ for (int i = 0; i < kSfxChannels; ++i) {
+ waitForSfxChannel(i);
+ }
_vm->_quit = true;
break;
- case 7: { // pause playback
- int sfxSync = READ_LE_UINT32(data);
- warning("Unhandled playback pause %d", sfxSync);
+ case 7: {
+ int channelSync = READ_LE_UINT32(data);
+ waitForSfxChannel(channelSync);
}
break;
case 2: // display copyright/information messagebox
case 3: // no-op in the original
case 4: // restart playback
case 5: // disable normal screen update
- case 6: // perform offscreen buffers swapping
+ case 6: // enable double buffer rendering
// these are never triggered
default:
warning("Unhandled TOIL code=%d", code);
diff --git a/engines/scumm/he/cup_player_he.h b/engines/scumm/he/cup_player_he.h
index f51496718b..6f2f72ba64 100644
--- a/engines/scumm/he/cup_player_he.h
+++ b/engines/scumm/he/cup_player_he.h
@@ -27,43 +27,33 @@
namespace Scumm {
struct CUP_Sfx {
- int num;
- int mode;
- uint16 flags;
+ int16 num;
+ uint32 flags;
};
-struct CUP_Player {
- Common::File _fd;
- uint32 _dataSize;
- int _playbackRate;
- int _width, _height;
- uint8 _paletteData[256 * 4];
- uint8 *_offscreenBuffer;
- uint8 _tempLzssBuffer[0x1000];
- uint8 *_currentChunkData;
- uint32 _currentChunkSize;
- uint8 *_bufferLzssData;
- uint32 _bufferLzssSize;
- bool _paletteChanged;
- int _sfxCount;
- uint8 *_sfxBuffer;
- Audio::SoundHandle *_sfxHandleTable;
- CUP_Sfx _sfxQueue[16];
- int _sfxQueuePos;
+struct CUP_SfxChannel {
+ Audio::SoundHandle handle;
+ int16 sfxNum;
+ uint32 flags;
+};
- ScummEngine_vCUPhe *_vm;
- Audio::Mixer *_mixer;
- OSystem *_system;
+class CUP_Player {
+public:
+
+ enum {
+ kSfxFlagLoop = 1 << 0,
+ kSfxFlagRestart = 1 << 1
+ };
+
+ enum {
+ kSfxChannels = 8,
+ kSfxQueueSize = 16,
+ kDefaultPlaybackRate = 66,
+ kDefaultVideoWidth = 640,
+ kDefaultVideoHeight = 480
+ };
- CUP_Player(OSystem *sys, ScummEngine_vCUPhe *vm, Audio::Mixer *mixer) {
- _currentChunkData = 0;
- _currentChunkSize = 0;
- _bufferLzssData = 0;
- _bufferLzssSize = 0;
- _vm = vm;
- _mixer = mixer;
- _system = sys;
- }
+ CUP_Player(OSystem *sys, ScummEngine_vCUPhe *vm, Audio::Mixer *mixer);
bool open(const char *filename);
void close();
@@ -73,6 +63,7 @@ struct CUP_Player {
void setDirtyScreenRect(const Common::Rect &r);
void updateScreen();
void updateSfx();
+ void waitForSfxChannel(int channel);
void parseNextTag(const uint8 *data, uint32 &tag, uint32 &size);
void handleHEAD(const uint8 *data, uint32 dataSize);
void handleSFXB(const uint8 *data, uint32 dataSize);
@@ -82,10 +73,38 @@ struct CUP_Player {
void handleSRLE(uint8 *dst, const uint8 *data, uint32 size);
void decodeSRLE(uint8 *dst, const uint8 *colorMap, const uint8 *data, int unpackedSize);
uint8 *handleLZSS(const uint8 *data, uint32 dataSize);
- void decodeLzssData(uint8 *dst1, const uint8 *src1, const uint8 *src2, const uint8 *src3, uint8 *dst2);
+ void decodeLZSS(uint8 *dst, const uint8 *src1, const uint8 *src2, const uint8 *src3);
void handleRATE(const uint8 *data, uint32 dataSize);
void handleSNDE(const uint8 *data, uint32 dataSize);
void handleTOIL(const uint8 *data, uint32 dataSize);
+
+protected:
+
+ ScummEngine_vCUPhe *_vm;
+ Audio::Mixer *_mixer;
+ OSystem *_system;
+
+ Common::File _fd;
+ uint32 _dataSize;
+
+ int _playbackRate;
+ int _width, _height;
+
+ uint8 _paletteData[256 * 4];
+ bool _paletteChanged;
+ uint8 *_offscreenBuffer;
+
+ uint8 *_currentChunkData;
+ uint32 _currentChunkSize;
+ uint8 *_bufferLzssData;
+ uint32 _bufferLzssSize;
+
+ int _sfxCount;
+ uint8 *_sfxBuffer;
+ CUP_SfxChannel _sfxChannels[kSfxChannels];
+ CUP_Sfx _sfxQueue[kSfxQueueSize];
+ int _sfxQueuePos;
+ int _lastSfxChannel;
};
} // End of namespace Scumm
diff --git a/engines/scumm/he/intern_he.h b/engines/scumm/he/intern_he.h
index 54df8f8f48..bb22e04a1d 100644
--- a/engines/scumm/he/intern_he.h
+++ b/engines/scumm/he/intern_he.h
@@ -42,7 +42,7 @@ class ResExtractor;
class LogicHE;
class MoviePlayer;
class Sprite;
-struct CUP_Player;
+class CUP_Player;
#endif
class ScummEngine_v60he : public ScummEngine_v6 {
diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp
index 981a48171f..d510002584 100644
--- a/engines/scumm/scumm.cpp
+++ b/engines/scumm/scumm.cpp
@@ -784,7 +784,7 @@ ScummEngine_vCUPhe::~ScummEngine_vCUPhe() {
int ScummEngine_vCUPhe::init() {
_system->beginGFXTransaction();
- _system->initSize(640, 480);
+ _system->initSize(CUP_Player::kDefaultVideoWidth, CUP_Player::kDefaultVideoHeight);
initCommonGFX(true);
_system->endGFXTransaction();
@@ -792,10 +792,10 @@ int ScummEngine_vCUPhe::init() {
}
int ScummEngine_vCUPhe::go() {
- _cupPlayer->open(_filenamePattern.pattern);
- _cupPlayer->play();
- _cupPlayer->close();
-
+ if (_cupPlayer->open(_filenamePattern.pattern)) {
+ _cupPlayer->play();
+ _cupPlayer->close();
+ }
return 0;
}