[Scummvm-cvs-logs] SF.net SVN: scummvm: [23659] scummvm/trunk/engines/kyra/sound_adlib.cpp

eriktorbjorn at users.sourceforge.net eriktorbjorn at users.sourceforge.net
Thu Aug 3 15:11:22 CEST 2006


Revision: 23659
Author:   eriktorbjorn
Date:     2006-08-03 06:11:16 -0700 (Thu, 03 Aug 2006)
ViewCVS:  http://svn.sourceforge.net/scummvm/?rev=23659&view=rev

Log Message:
-----------
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.

Modified Paths:
--------------
    scummvm/trunk/engines/kyra/sound_adlib.cpp
Modified: scummvm/trunk/engines/kyra/sound_adlib.cpp
===================================================================
--- scummvm/trunk/engines/kyra/sound_adlib.cpp	2006-08-03 12:20:28 UTC (rev 23658)
+++ scummvm/trunk/engines/kyra/sound_adlib.cpp	2006-08-03 13:11:16 UTC (rev 23659)
@@ -73,6 +73,8 @@
 	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 @@
 	// unk41 - Sound-effect. Used for primaryEffect2()
 
 	struct Channel {
+		bool lock;	// New to ScummVM
 		uint8 opExtraLevel2;
 		uint8 *dataptr;
 		uint8 duration;
@@ -378,6 +381,8 @@
 	static const uint8 _unkTable2_3[];
 	static const uint8 _unkTables[][32];
 
+	uint16 _syncJumpMask;
+
 	Common::Mutex _mutex;
 	Audio::Mixer *_mixer;
 
@@ -421,6 +426,8 @@
 	_samplesPerCallbackRemainder = getRate() % CALLBACKS_PER_SECOND;
 	_samplesTillCallback = 0;
 	_samplesTillCallbackRemainder = 0;
+
+	_syncJumpMask = 0;
 }
 
 AdlibDriver::~AdlibDriver() {
@@ -628,6 +635,11 @@
 			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,14 +682,40 @@
 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;
 
 		if (!_channels[_curChannel].dataptr) {
 			continue;
 		}
+
+		if (_channels[_curChannel].lock && (_syncJumpMask & (1 << _curChannel))) {
+			continue;
+		}
 	
 		Channel &channel = _channels[_curChannel];
 		_curRegOffset = _regOffset[_curChannel];
@@ -784,6 +822,7 @@
 	channel.primaryEffect = 0;
 	channel.secondaryEffect = 0;
 	channel.spacing1 = 1;
+	channel.lock = false;
 }
 
 void AdlibDriver::noteOff(Channel &channel) {
@@ -1246,6 +1285,8 @@
 	--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::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() {


This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.





More information about the Scummvm-git-logs mailing list