aboutsummaryrefslogtreecommitdiff
path: root/engines/lastexpress
diff options
context:
space:
mode:
Diffstat (limited to 'engines/lastexpress')
-rw-r--r--engines/lastexpress/data/snd.cpp81
-rw-r--r--engines/lastexpress/game/savegame.cpp12
-rw-r--r--engines/lastexpress/lastexpress.cpp3
-rw-r--r--engines/lastexpress/lastexpress.h1
-rw-r--r--engines/lastexpress/module.mk2
-rw-r--r--engines/lastexpress/shared.h17
-rw-r--r--engines/lastexpress/sound/entry.cpp6
-rw-r--r--engines/lastexpress/sound/queue.cpp88
-rw-r--r--engines/lastexpress/sound/sound.cpp4
9 files changed, 80 insertions, 134 deletions
diff --git a/engines/lastexpress/data/snd.cpp b/engines/lastexpress/data/snd.cpp
index 28d20df9bd..6845be8808 100644
--- a/engines/lastexpress/data/snd.cpp
+++ b/engines/lastexpress/data/snd.cpp
@@ -38,7 +38,7 @@ namespace LastExpress {
#pragma region Sound filters tables
-static const int filterData[1424] = {
+static const int stepTable[1424] = {
0, 0, 0, 0, 128, 256, 384, 512, 0, 0, 0, 0, 128, 256,
384, 512, 0, 0, 0, 0, 192, 320, 448, 576, 0, 0, 0, 0,
192, 320, 448, 576, 64, 64, 64, 64, 256, 384, 512, 640,
@@ -152,7 +152,7 @@ static const int filterData[1424] = {
4224, 4352, 4480, 4608, 4096, 4096, 4096, 4096, 4288,
4416, 4544, 4672, 4096, 4096, 4096, 4096, 4288, 4416,
4544, 4672, 4160, 4160, 4160, 4160, 4352, 4480, 4608,
- 4.6, 4160, 4160, 4160, 4160, 4352, 4480, 4608, 4736,
+ 4736, 4160, 4160, 4160, 4160, 4352, 4480, 4608, 4736,
4224, 4224, 4224, 4224, 4416, 4544, 4672, 4800, 4224,
4224, 4224, 4224, 4416, 4544, 4672, 4800, 4288, 4288,
4288, 4288, 4480, 4608, 4736, 4864, 4288, 4288, 4288,
@@ -195,7 +195,7 @@ static const int filterData[1424] = {
5632
};
-static const int filterData2[1424] = {
+static const int imaTable[1424] = {
0, 2, 4, 6, 7, 9, 11, 13, 0, -2, -4, -6, -7, -9, -11,
-13, 1, 3, 5, 7, 9, 11, 13, 15, -1, -3, -5, -7, -9,
-11, -13, -15, 1, 3, 5, 7, 10, 12, 14, 16, -1, -3, -5,
@@ -352,16 +352,20 @@ static const int p2s[17] = { 0, 1, 1, 3, 1, 5, 3, 7, 1, 9, 5, 11, 3, 13, 7, 15,
// Last Express ADPCM is similar to MS IMA mono, but inverts its nibbles
// and does not have the 4 byte per channel requirement
-class LastExpress_ADPCMStream : public Audio::Ima_ADPCMStream {
+class LastExpress_ADPCMStream : public Audio::ADPCMStream {
public:
LastExpress_ADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, uint32 blockSize, int32 filterId) :
- Audio::Ima_ADPCMStream(stream, disposeAfterUse, size, 44100, 1, blockSize) {
+ Audio::ADPCMStream(stream, disposeAfterUse, size, 44100, 1, blockSize) {
_currentFilterId = -1;
_nextFilterId = filterId;
}
int readBuffer(int16 *buffer, const int numSamples) {
int samples = 0;
+ // Temporary data
+ int step = 0;
+ int sample = 0;
+ byte idx = 0;
assert(numSamples % 2 == 0);
@@ -369,15 +373,37 @@ public:
if (_blockPos[0] == _blockAlign) {
// read block header
_status.ima_ch[0].last = _stream->readSint16LE();
- _status.ima_ch[0].stepIndex = _stream->readSint16LE();
+ _status.ima_ch[0].stepIndex = _stream->readSint16LE() << 6;
_blockPos[0] = 4;
+
+ // Get current filter
+ _currentFilterId = _nextFilterId;
+ _nextFilterId = -1;
+
+ // No filter: skip decoding
+ if (_currentFilterId == -1)
+ break;
+
+ // Compute step adjustment
+ _stepAdjust1 = p1s[_currentFilterId];
+ _stepAdjust2 = p2s[_currentFilterId];
}
for (; samples < numSamples && _blockPos[0] < _blockAlign && !_stream->eos() && _stream->pos() < _endpos; samples += 2) {
byte data = _stream->readByte();
_blockPos[0]++;
- buffer[samples] = decodeIMA((data >> 4) & 0x0f);
- buffer[samples + 1] = decodeIMA(data & 0x0f);
+
+ // First nibble
+ idx = data >> 4;
+ step = stepTable[idx + _status.ima_ch[0].stepIndex / 4];
+ sample = CLIP(imaTable[idx + _status.ima_ch[0].stepIndex / 4] + _status.ima_ch[0].last, -32767, 32767);
+ buffer[samples] = (_stepAdjust2 * sample) >> _stepAdjust1;
+
+ // Second nibble
+ idx = data & 0xF;
+ _status.ima_ch[0].stepIndex = stepTable[idx + step / 4];
+ _status.ima_ch[0].last = CLIP(imaTable[idx + step / 4] + sample, -32767, 32767);
+ buffer[samples + 1] = (_stepAdjust2 * _status.ima_ch[0].last) >> _stepAdjust1;
}
}
@@ -387,41 +413,10 @@ public:
void setFilterId(int32 filterId) { _nextFilterId = filterId; }
private:
- int32 _currentFilterId;
- int32 _nextFilterId; // the sound filter id, -1 for none
-
- /**
- * Sound filter
- *
- * @param [in] data If non-null, the input data
- * @param [in,out] buffer If non-null, the output buffer.
- * @param p1 The first filter input.
- * @param p2 The second filter input.
- */
- static void soundFilter(byte *data, int16 *buffer, int p1, int p2) {
- int data1, data2, data1p, data2p;
- byte idx;
-
- data2 = data[0];
- data1 = data[1] << 6;
-
- data += 2;
-
- for (int count = 0; count < 735; count++) {
- idx = data[count] >> 4;
-
- data1p = filterData[idx + data1];
- data2p = CLIP(filterData2[idx + data1] + data2, -32767, 32767);
-
- buffer[2 * count] = (p2 * data2p) >> p1;
-
- idx = data[count] & 0xF;
-
- data1 = filterData[idx + data1p];
- data2 = CLIP(filterData2[idx + data1p] + data2p, -32767, 32767);
- buffer[2 * count + 1] = (p2 * data2) >> p1;
- }
- }
+ int32 _currentFilterId;
+ int32 _nextFilterId; // the sound filter id, -1 for none
+ int32 _stepAdjust1;
+ int32 _stepAdjust2;
};
//////////////////////////////////////////////////////////////////////////
diff --git a/engines/lastexpress/game/savegame.cpp b/engines/lastexpress/game/savegame.cpp
index ebada5dd4e..57c18b5697 100644
--- a/engines/lastexpress/game/savegame.cpp
+++ b/engines/lastexpress/game/savegame.cpp
@@ -45,12 +45,12 @@ namespace LastExpress {
static const struct {
const char *saveFile;
} gameInfo[6] = {
- {"blue.egg"},
- {"red.egg"},
- {"green.egg"},
- {"purple.egg"},
- {"teal.egg"},
- {"gold.egg"}
+ {"lastexpress-blue.egg"},
+ {"lastexpress-red.egg"},
+ {"lastexpress-green.egg"},
+ {"lastexpress-purple.egg"},
+ {"lastexpress-teal.egg"},
+ {"lastexpress-gold.egg"}
};
//////////////////////////////////////////////////////////////////////////
diff --git a/engines/lastexpress/lastexpress.cpp b/engines/lastexpress/lastexpress.cpp
index 885ca8b212..250fa0f2d0 100644
--- a/engines/lastexpress/lastexpress.cpp
+++ b/engines/lastexpress/lastexpress.cpp
@@ -42,6 +42,7 @@
#include "common/debug-channels.h"
#include "common/error.h"
#include "common/fs.h"
+#include "common/timer.h"
#include "engines/util.h"
@@ -146,7 +147,7 @@ Common::Error LastExpressEngine::run() {
// Start sound manager and setup timer
_soundMan = new SoundManager(this);
- _timer->installTimerProc(&soundTimer, 17000, this);
+ _timer->installTimerProc(&soundTimer, 17000, this, "lastexpressSound");
// Menu
_menu = new Menu(this);
diff --git a/engines/lastexpress/lastexpress.h b/engines/lastexpress/lastexpress.h
index f8f38788a0..1431b79b9f 100644
--- a/engines/lastexpress/lastexpress.h
+++ b/engines/lastexpress/lastexpress.h
@@ -27,7 +27,6 @@
#include "lastexpress/eventhandler.h"
#include "common/random.h"
-#include "common/timer.h"
#include "engines/engine.h"
diff --git a/engines/lastexpress/module.mk b/engines/lastexpress/module.mk
index a11a7c4b67..8b3287d5d7 100644
--- a/engines/lastexpress/module.mk
+++ b/engines/lastexpress/module.mk
@@ -80,4 +80,4 @@ PLUGIN := 1
endif
# Include common rules
-include $(srcdir)/rules.mk \ No newline at end of file
+include $(srcdir)/rules.mk
diff --git a/engines/lastexpress/shared.h b/engines/lastexpress/shared.h
index 7b640c773a..d60a498447 100644
--- a/engines/lastexpress/shared.h
+++ b/engines/lastexpress/shared.h
@@ -84,29 +84,26 @@ enum SoundFlag {
};
enum SoundState {
- kSoundState0 = 0,
- kSoundState1 = 1,
- kSoundState2 = 2
+ kSoundStateNone = 0,
+ kSoundState1 = 1,
+ kSoundState2 = 2
};
enum SoundStatus {
+ kSoundStatusClear0 = 0x10,
+ kSoundStatusFilter = 0x1F,
kSoundStatus_20 = 0x20,
kSoundStatus_40 = 0x40,
+ kSoundStatusCached = 0x80,
kSoundStatus_180 = 0x180,
kSoundStatusClosed = 0x200,
kSoundStatus_400 = 0x400,
-
+ kSoundStatusClear4 = 0x800,
kSoundStatus_8000 = 0x8000,
kSoundStatus_20000 = 0x20000,
kSoundStatus_100000 = 0x100000,
kSoundStatus_20000000 = 0x20000000,
kSoundStatus_40000000 = 0x40000000,
-
- kSoundStatusClear0 = 0x10,
- kSoundStatusFilter = 0x1F,
- kSoundStatusCached = 0x80,
- kSoundStatusClear3 = 0x200,
- kSoundStatusClear4 = 0x800,
kSoundStatusClearAll = 0xFFFFFFE0
};
diff --git a/engines/lastexpress/sound/entry.cpp b/engines/lastexpress/sound/entry.cpp
index 87d8ccdb30..44cc68a57b 100644
--- a/engines/lastexpress/sound/entry.cpp
+++ b/engines/lastexpress/sound/entry.cpp
@@ -88,8 +88,8 @@ void SoundEntry::close() {
_status.status |= kSoundStatusClosed;
// Loop until ready
- while (!(_status.status1 & 4) && !(getSoundQueue()->getFlag() & 8) && (getSoundQueue()->getFlag() & 1))
- ; // empty loop body
+ //while (!(_status.status1 & 4) && !(getSoundQueue()->getFlag() & 8) && (getSoundQueue()->getFlag() & 1))
+ // ; // empty loop body
// The original game remove the entry from the cache here,
// but since we are called from within an iterator loop
@@ -290,7 +290,7 @@ bool SoundEntry::updateSound() {
}
}
}
- //if (status.status2 & 0x40 && !((uint32)_status.status & 0x180) && v1->soundBuffer)
+ //if (status.status2 & 0x40 && !((uint32)_status.status & 0x180) && v1->soundBuffer)
// Sound_FillSoundBuffer(v1);
}
result = true;
diff --git a/engines/lastexpress/sound/queue.cpp b/engines/lastexpress/sound/queue.cpp
index 0a6442ceed..33b4c06793 100644
--- a/engines/lastexpress/sound/queue.cpp
+++ b/engines/lastexpress/sound/queue.cpp
@@ -102,80 +102,41 @@ void SoundQueue::removeFromQueue(Common::String filename) {
}
void SoundQueue::updateQueue() {
- //Common::StackLock locker(_mutex);
-
- //warning("[Sound::updateQueue] Not implemented");
-
- int maxPriority = 0;
- Common::List<SoundEntry *>::iterator lsnd;
- SoundEntry *msnd;
-
- bool loopedPlaying;
-
- loopedPlaying = 0;
- //++g_sound_flag;
+ Common::StackLock locker(_mutex);
- for (lsnd = _soundList.begin(); lsnd != _soundList.end(); ++lsnd) {
- if ((*lsnd)->getType() == kSoundType1)
- break;
- }
+ ++_flag;
- if (getSoundState() & 1) {
- if (!(*lsnd) || getFlags()->flag_3 || (*lsnd && (*lsnd)->getTime() > getSound()->getLoopingSoundDuration())) {
+ if (getSoundState() & kSoundState1) {
+ SoundEntry *entry = getEntry(kSoundType1);
+ if (!entry || getFlags()->flag_3 || (entry && entry->getTime() > getSound()->getLoopingSoundDuration())) {
getSound()->playLoopingSound(0x45);
} else {
if (getSound()->getData1() && getSound()->getData2() >= getSound()->getData1()) {
- (*lsnd)->update(getSound()->getData0());
+ entry->update(getSound()->getData0());
getSound()->setData1(0);
}
}
}
- msnd = NULL;
-
- for (lsnd = _soundList.begin(); lsnd != _soundList.end(); ++lsnd) {
- if ((*lsnd)->getStatus().status2 & 0x1) { // Sound is stopped
- // original code
- //if ((*lsnd)->soundBuffer)
- // Sound_RemoveSoundDataFromCache(*lsnd);
- //if ((*lsnd)->archive) {
- // Archive_SetStatusNotLoaded((*lsnd)->archive);
- // (*lsnd)->archive = 0;
- // (*lsnd)->field_28 = 3;
- //}
-
- if (_soundList.size() < 6) {
- if ((*lsnd)->getStatus().status1 & 0x1F) {
- int pri = (*lsnd)->getPriority() + ((*lsnd)->getStatus().status1 & 0x1F);
-
- if (pri > maxPriority) {
- msnd = *lsnd;
- maxPriority = pri;
- }
- }
- }
- }
+ for (Common::List<SoundEntry *>::iterator it = _soundList.begin(); it != _soundList.end(); ++it) {
+ SoundEntry *entry = *it;
- if (!(*lsnd)->updateSound() && !((*lsnd)->getStatus().status3 & 0x8)) {
- if (msnd == *lsnd) {
- maxPriority = 0;
- msnd = 0;
- }
- if (*lsnd) {
- (*lsnd)->close();
- SAFE_DELETE(*lsnd);
- lsnd = _soundList.reverse_erase(lsnd);
- }
+ // Original removes the entry data from the cache and sets the archive as not loaded
+ // and if the sound data buffer is not full, loads a new entry to be played based on
+ // its priority and filter id
+
+ if (!entry->updateSound() && !(entry->getStatus().status3 & 0x8)) {
+ entry->close();
+ SAFE_DELETE(entry);
+ it = _soundList.reverse_erase(it);
}
}
-
- // We don't need this
- //if (msnd)
- // msnd->updateEntryInternal();
+ // Original update the current entry, loading another set of samples to be decoded
getFlags()->flag_3 = 0;
- //--g_sound_flag;
+
+ --_flag;
}
void SoundQueue::resetQueue() {
@@ -209,17 +170,10 @@ void SoundQueue::resetQueue(SoundType type1, SoundType type2) {
}
void SoundQueue::clearQueue() {
- _flag |= 4;
-
- // FIXME: Wait a while for a flag to be set
- //for (int i = 0; i < 3000000; i++)
- // if (_flag & 8)
- // break;
+ Common::StackLock locker(_mutex);
_flag |= 8;
- Common::StackLock locker(_mutex);
-
for (Common::List<SoundEntry *>::iterator i = _soundList.begin(); i != _soundList.end(); ++i) {
SoundEntry *entry = (*i);
@@ -240,7 +194,7 @@ void SoundQueue::clearStatus() {
Common::StackLock locker(_mutex);
for (Common::List<SoundEntry *>::iterator i = _soundList.begin(); i != _soundList.end(); ++i)
- (*i)->setStatus((*i)->getStatus().status | kSoundStatusClear3);
+ (*i)->setStatus((*i)->getStatus().status | kSoundStatusClosed);
}
//////////////////////////////////////////////////////////////////////////
diff --git a/engines/lastexpress/sound/sound.cpp b/engines/lastexpress/sound/sound.cpp
index c04b6d361f..2f7bb4a601 100644
--- a/engines/lastexpress/sound/sound.cpp
+++ b/engines/lastexpress/sound/sound.cpp
@@ -1305,8 +1305,8 @@ void SoundManager::playLoopingSound(int param) {
int partNumber = 1;
int fnameLen = 6;
- if (_queue->getSoundState() & 1 && param >= 0x45 && param <= 0x46) {
- if (_queue->getSoundState() & 2) {
+ if (_queue->getSoundState() & kSoundState1 && param >= 0x45 && param <= 0x46) {
+ if (_queue->getSoundState() & kSoundState2) {
strcpy(tmp, "STEAM.SND");
_loopingSoundDuration = 32767;