aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
authorTorbjörn Andersson2006-08-03 13:11:16 +0000
committerTorbjörn Andersson2006-08-03 13:11:16 +0000
commit44dd6a386e9342e4088125fef680b1232da35692 (patch)
tree94568330c195b4b4910709c2171c42a06358b219 /engines
parentd304e7b4766f2c3321493c046283eb8b7d018a77 (diff)
downloadscummvm-rg350-44dd6a386e9342e4088125fef680b1232da35692.tar.gz
scummvm-rg350-44dd6a386e9342e4088125fef680b1232da35692.tar.bz2
scummvm-rg350-44dd6a386e9342e4088125fef680b1232da35692.zip
Committed my own patch #1533833 (minus one line that was left over from an
earlier experimental version) after discussing it with LordHoto. This works around a bug in the "Pool of Sorrow" Adlib data which caused the channels to drift more and more out of sync for each time the music looped. The patch forces the channels involved to jump in sync. As with all such workarounds, it may cause regressions. But it shouldn't. svn-id: r23659
Diffstat (limited to 'engines')
-rw-r--r--engines/kyra/sound_adlib.cpp55
1 files changed, 53 insertions, 2 deletions
diff --git a/engines/kyra/sound_adlib.cpp b/engines/kyra/sound_adlib.cpp
index 48945cab9c..786595061b 100644
--- a/engines/kyra/sound_adlib.cpp
+++ b/engines/kyra/sound_adlib.cpp
@@ -73,6 +73,8 @@ public:
bool endOfData() const { return false; }
int getRate() const { return _mixer->getOutputRate(); }
+ void setSyncJumpMask(uint16 mask) { _syncJumpMask = mask; }
+
private:
struct OpcodeEntry {
typedef int (AdlibDriver::*DriverOpcode)(va_list &list);
@@ -127,6 +129,7 @@ private:
// unk41 - Sound-effect. Used for primaryEffect2()
struct Channel {
+ bool lock; // New to ScummVM
uint8 opExtraLevel2;
uint8 *dataptr;
uint8 duration;
@@ -378,6 +381,8 @@ private:
static const uint8 _unkTable2_3[];
static const uint8 _unkTables[][32];
+ uint16 _syncJumpMask;
+
Common::Mutex _mutex;
Audio::Mixer *_mixer;
@@ -421,6 +426,8 @@ AdlibDriver::AdlibDriver(Audio::Mixer *mixer) {
_samplesPerCallbackRemainder = getRate() % CALLBACKS_PER_SECOND;
_samplesTillCallback = 0;
_samplesTillCallbackRemainder = 0;
+
+ _syncJumpMask = 0;
}
AdlibDriver::~AdlibDriver() {
@@ -628,6 +635,11 @@ void AdlibDriver::setupPrograms() {
unkOutput2(chan);
}
+ // What we have set up now is, probably, the controlling
+ // channel for the sound. It is assumed that this program will
+ // set up all the other channels it needs, clearing their locks
+ // along the way.
+
++_lastProcessed;
_lastProcessed &= 0x0F;
}
@@ -670,7 +682,29 @@ void AdlibDriver::setupPrograms() {
void AdlibDriver::executePrograms() {
// Each channel runs its own program. There are ten channels: One for
// each Adlib channel (0-8), plus one "control channel" (9) which is
- // the one that tells the other channels what to do.
+ // the one that tells the other channels what to do.
+
+ // This is where we ensure that channels that are made to jump "in
+ // sync" do so.
+
+ if (_syncJumpMask) {
+ bool forceUnlock = true;
+
+ for (_curChannel = 9; _curChannel >= 0; --_curChannel) {
+ if ((_syncJumpMask & (1 << _curChannel)) == 0)
+ continue;
+
+ if (_channels[_curChannel].dataptr && !_channels[_curChannel].lock) {
+ forceUnlock = false;
+ }
+ }
+
+ if (forceUnlock) {
+ for (_curChannel = 9; _curChannel >= 0; --_curChannel)
+ if (_syncJumpMask & (1 << _curChannel))
+ _channels[_curChannel].lock = false;
+ }
+ }
for (_curChannel = 9; _curChannel >= 0; --_curChannel) {
int result = 1;
@@ -678,6 +712,10 @@ void AdlibDriver::executePrograms() {
if (!_channels[_curChannel].dataptr) {
continue;
}
+
+ if (_channels[_curChannel].lock && (_syncJumpMask & (1 << _curChannel))) {
+ continue;
+ }
Channel &channel = _channels[_curChannel];
_curRegOffset = _regOffset[_curChannel];
@@ -784,6 +822,7 @@ void AdlibDriver::initChannel(Channel &channel) {
channel.primaryEffect = 0;
channel.secondaryEffect = 0;
channel.spacing1 = 1;
+ channel.lock = false;
}
void AdlibDriver::noteOff(Channel &channel) {
@@ -1246,6 +1285,8 @@ int AdlibDriver::update_jump(uint8 *&dataptr, Channel &channel, uint8 value) {
--dataptr;
int16 add = READ_LE_UINT16(dataptr); dataptr += 2;
dataptr += add;
+ if (_syncJumpMask & (1 << (&channel - _channels)))
+ channel.lock = true;
return 0;
}
@@ -2195,8 +2236,18 @@ void SoundAdlibPC::loadMusicFile(const char *file) {
}
void SoundAdlibPC::playTrack(uint8 track) {
- if (_musicEnabled)
+ if (_musicEnabled) {
+ // WORKAROUND: There is a bug in the Kyra 1 "Pool of Sorrow"
+ // music which causes the channels to get progressively out of
+ // sync for each loop. To avoid that, we declare that all four
+ // of the song channels have to jump "in sync".
+
+ if (track == 4 && _soundFileLoaded == "KYRA1B")
+ _driver->setSyncJumpMask(0x000F);
+ else
+ _driver->setSyncJumpMask(0);
play(track);
+ }
}
void SoundAdlibPC::haltTrack() {