[Scummvm-git-logs] scummvm master -> 3fb4d67b4e4fc666232da3b2eca60d0fc8781cd0

athrxx athrxx at scummvm.org
Fri Jan 15 18:08:02 UTC 2021


This automated email contains information about 7 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
52faf42934 KYRA: Move delete[] from setSoundData() to caller
d2824f5196 KYRA: Add helper for timer wraparound handling
6d0db570f7 KYRA: Correct comment on instruments table
dbbe5b8717 KYRA: Reduce nesting level in AdLibDriver::executePrograms()
094988e242 KYRA: Add helper to check offsets into _soundData
bfb4a6219f KYRA: Don't depend on struct layout in AdLibDriver::initChannel()
3fb4d67b4e KYRA: Change calling convention of opcode callbacks


Commit: 52faf429348a57fd437e65f9f5a7cb811b05f6c6
    https://github.com/scummvm/scummvm/commit/52faf429348a57fd437e65f9f5a7cb811b05f6c6
Author: Alexander Miller (alex.miller at gmx.de)
Date: 2021-01-15T19:07:47+01:00

Commit Message:
KYRA: Move delete[] from setSoundData() to caller

Free the sound data in SoundPC_v1::internalLoadFile() since it's owned
by this class instead of in the driver's setSoundData() method.

Changed paths:
    engines/kyra/sound/drivers/adlib.cpp
    engines/kyra/sound/drivers/pcspeaker_v1.cpp
    engines/kyra/sound/sound_pc_v1.cpp


diff --git a/engines/kyra/sound/drivers/adlib.cpp b/engines/kyra/sound/drivers/adlib.cpp
index f01a0ec5c6..f5d6d8c5e9 100644
--- a/engines/kyra/sound/drivers/adlib.cpp
+++ b/engines/kyra/sound/drivers/adlib.cpp
@@ -433,7 +433,6 @@ void AdLibDriver::setSoundData(uint8 *data, uint32 size) {
 
 	_sfxPointer = nullptr;
 
-	delete[] _soundData;
 	_soundData = data;
 	_soundDataSize = size;
 }
diff --git a/engines/kyra/sound/drivers/pcspeaker_v1.cpp b/engines/kyra/sound/drivers/pcspeaker_v1.cpp
index 29a5a53997..f148bdd369 100644
--- a/engines/kyra/sound/drivers/pcspeaker_v1.cpp
+++ b/engines/kyra/sound/drivers/pcspeaker_v1.cpp
@@ -137,11 +137,6 @@ void PCSpeakerDriver::setSoundData(uint8 *data, uint32 size) {
 	if (!_ready)
 		return;
 
-	if (_soundData) {
-		delete[] _soundData;
-		_soundData = 0;
-	}
-
 	_soundData = data;
 	_soundDataSize = size;
 }
diff --git a/engines/kyra/sound/sound_pc_v1.cpp b/engines/kyra/sound/sound_pc_v1.cpp
index dc37978a31..67da0e8cd1 100644
--- a/engines/kyra/sound/sound_pc_v1.cpp
+++ b/engines/kyra/sound/sound_pc_v1.cpp
@@ -235,7 +235,6 @@ void SoundPC_v1::internalLoadFile(Common::String file) {
 	playSoundEffect(0);
 
 	_driver->stopAllChannels();
-	_soundDataPtr = 0;
 
 	int soundDataSize = fileSize;
 	uint8 *p = fileData;
@@ -250,16 +249,15 @@ void SoundPC_v1::internalLoadFile(Common::String file) {
 		soundDataSize -= 120;
 	}
 
+	uint8 *oldData = _soundDataPtr;
 	_soundDataPtr = new uint8[soundDataSize];
 	assert(_soundDataPtr);
 
 	memcpy(_soundDataPtr, p, soundDataSize);
+	_driver->setSoundData(_soundDataPtr, soundDataSize);
 
 	delete[] fileData;
-	fileData = p = 0;
-	fileSize = 0;
-
-	_driver->setSoundData(_soundDataPtr, soundDataSize);
+	delete[] oldData;
 
 	_soundFileLoaded = file;
 }


Commit: d2824f51966c883256d35db8f4020d1c74647d79
    https://github.com/scummvm/scummvm/commit/d2824f51966c883256d35db8f4020d1c74647d79
Author: Alexander Miller (alex.miller at gmx.de)
Date: 2021-01-15T19:07:47+01:00

Commit Message:
KYRA: Add helper for timer wraparound handling

Changed paths:
    engines/kyra/sound/drivers/adlib.cpp


diff --git a/engines/kyra/sound/drivers/adlib.cpp b/engines/kyra/sound/drivers/adlib.cpp
index f5d6d8c5e9..6b8500866e 100644
--- a/engines/kyra/sound/drivers/adlib.cpp
+++ b/engines/kyra/sound/drivers/adlib.cpp
@@ -100,7 +100,7 @@ private:
 		uint8 spacing2;
 		uint8 baseFreq;
 		uint8 tempo;
-		uint8 position;
+		uint8 timer;
 		uint8 regAx;
 		uint8 regBx;
 		typedef void (AdLibDriver::*Callback)(Channel&);
@@ -149,7 +149,17 @@ private:
 	uint8 calculateOpLevel1(Channel &channel);
 	uint8 calculateOpLevel2(Channel &channel);
 
-	uint16 checkValue(int16 val) { return CLIP<int16>(val, 0, 0x3F); }
+	static uint16 checkValue(int16 val) { return CLIP<int16>(val, 0, 0x3F); }
+
+	// The driver uses timer/tempo pairs in several places. On every
+	// callback, the tempo is added to the timer. This will frequently
+	// cause the timer to "wrap around", which is the signal to go ahead
+	// and do more stuff.
+	static bool advance(uint8 &timer, uint8 tempo) {
+		uint8 old = timer;
+		timer += tempo;
+		return timer < old;
+	}
 
 	// The sound data has at least two lookup tables:
 	//
@@ -495,9 +505,7 @@ void AdLibDriver::callback() {
 		setupPrograms();
 	executePrograms();
 
-	uint8 temp = _callbackTimer;
-	_callbackTimer += _tempo;
-	if (_callbackTimer < temp) {
+	if (advance(_callbackTimer, _tempo)) {
 		if (!(--_beatDivCnt)) {
 			_beatDivCnt = _beatDivider;
 			++_beatCounter;
@@ -555,7 +563,7 @@ void AdLibDriver::setupPrograms() {
 		channel.priority = priority;
 		channel.dataptr = ptr;
 		channel.tempo = 0xFF;
-		channel.position = 0xFF;
+		channel.timer = 0xFF;
 		channel.duration = 1;
 
 		if (chan <= 5)
@@ -616,16 +624,15 @@ void AdLibDriver::adjustSfxData(uint8 *ptr, int volume) {
 
 // A few words on opcode parsing and timing:
 //
-// First of all, We simulate a timer callback 72 times per second. Each timeout
+// First of all, we simulate a timer callback 72 times per second. Each timeout
 // we update each channel that has something to play.
 //
-// Each channel has its own individual tempo, which is added to its position.
-// This will frequently cause the position to "wrap around" but that is
-// intentional. In fact, it's the signal to go ahead and do more stuff with
-// that channel.
+// Each channel has its own individual tempo and timer. The timer is updated,
+// and when it wraps around, we go ahead and do more stuff with that channel.
+// Otherwise we skip straiht to the effect callbacks.
 //
-// Each channel also has a duration, indicating how much time is left on the
-// its current task. This duration is decreased by one. As long as it still has
+// Each channel also has a duration, indicating how much time is left on its
+// current task. This duration is decreased by one. As long as it still has
 // not reached zero, the only thing that can happen is that the note is turned
 // off depending on manual or automatic note spacing. Once the duration reaches
 // zero, a new set of musical opcodes are executed.
@@ -692,9 +699,7 @@ void AdLibDriver::executePrograms() {
 		if (channel.tempoReset)
 			channel.tempo = _tempo;
 
-		uint8 backup = channel.position;
-		channel.position += channel.tempo;
-		if (channel.position < backup) {
+		if (advance(channel.timer, channel.tempo)) {
 			if (--channel.duration) {
 				if (channel.duration == channel.spacing2)
 					noteOff(channel);
@@ -1073,10 +1078,8 @@ void AdLibDriver::primaryEffectSlide(Channel &channel) {
 	if (_curChannel >= 9)
 		return;
 
-	// Next update is due when slideTimer overflows.
-	uint8 temp = channel.slideTimer;
-	channel.slideTimer += channel.slideTempo;
-	if (channel.slideTimer >= temp)
+	// Time for next frequency update?
+	if (!advance(channel.slideTimer, channel.slideTempo))
 		return;
 
 	// Extract current frequency, (shifted) octave, and "note on" bit into
@@ -1160,10 +1163,8 @@ void AdLibDriver::primaryEffectVibrato(Channel &channel) {
 		return;
 	}
 
-	// Next update is due when vibratoTimer overflows.
-	uint8 temp = channel.vibratoTimer;
-	channel.vibratoTimer += channel.vibratoTempo;
-	if (channel.vibratoTimer < temp) {
+	// Time for an update?
+	if (advance(channel.vibratoTimer, channel.vibratoTempo)) {
 		// Reverse direction every vibratoNumSteps updates
 		if (!(--channel.vibratoStepsCountdown)) {
 			channel.vibratoStep = -channel.vibratoStep;
@@ -1217,9 +1218,7 @@ void AdLibDriver::secondaryEffect1(Channel &channel) {
 	if (_curChannel >= 9)
 		return;
 
-	uint8 temp = channel.secondaryEffectTimer;
-	channel.secondaryEffectTimer += channel.secondaryEffectTempo;
-	if (channel.secondaryEffectTimer < temp) {
+	if (advance(channel.secondaryEffectTimer, channel.secondaryEffectTempo)) {
 		if (--channel.secondaryEffectPos < 0)
 			channel.secondaryEffectPos = channel.secondaryEffectSize;
 		writeOPL(channel.secondaryEffectRegbase + _curRegOffset,
@@ -1349,7 +1348,7 @@ int AdLibDriver::update_setupProgram(const uint8 *&dataptr, Channel &channel, ui
 		channel2.priority = priority;
 		channel2.dataptr = ptr;
 		channel2.tempo = 0xFF;
-		channel2.position = 0xFF;
+		channel2.timer = 0xFF;
 		channel2.duration = 1;
 
 		if (chan <= 5)


Commit: 6d0db570f7baf224393b4a5c240547d189e32bdb
    https://github.com/scummvm/scummvm/commit/6d0db570f7baf224393b4a5c240547d189e32bdb
Author: Alexander Miller (alex.miller at gmx.de)
Date: 2021-01-15T19:07:47+01:00

Commit Message:
KYRA: Correct comment on instruments table

Changed paths:
    engines/kyra/sound/drivers/adlib.cpp


diff --git a/engines/kyra/sound/drivers/adlib.cpp b/engines/kyra/sound/drivers/adlib.cpp
index 6b8500866e..02965e9f00 100644
--- a/engines/kyra/sound/drivers/adlib.cpp
+++ b/engines/kyra/sound/drivers/adlib.cpp
@@ -161,10 +161,9 @@ private:
 		return timer < old;
 	}
 
-	// The sound data has at least two lookup tables:
-	//
+	// The sound data has two lookup tables:
 	// * One for programs, starting at offset 0.
-	// * One for instruments, starting at offset 500.
+	// * One for instruments, starting at offset 300, 500, or 1000.
 
 	const uint8 *getInstrument(int instrumentId) {
 		return getProgram(_numPrograms + instrumentId);


Commit: dbbe5b87174b9a35911e9438af3965480661034c
    https://github.com/scummvm/scummvm/commit/dbbe5b87174b9a35911e9438af3965480661034c
Author: Alexander Miller (alex.miller at gmx.de)
Date: 2021-01-15T19:07:47+01:00

Commit Message:
KYRA: Reduce nesting level in AdLibDriver::executePrograms()

Changed paths:
    engines/kyra/sound/drivers/adlib.cpp


diff --git a/engines/kyra/sound/drivers/adlib.cpp b/engines/kyra/sound/drivers/adlib.cpp
index 02965e9f00..91f208fc6b 100644
--- a/engines/kyra/sound/drivers/adlib.cpp
+++ b/engines/kyra/sound/drivers/adlib.cpp
@@ -659,21 +659,17 @@ void AdLibDriver::executePrograms() {
 	// each AdLib channel (0-8), plus one "control channel" (9) which is
 	// 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;
+		// This is where we ensure that channels that are made to jump
+		// "in sync" do so.
 
 		for (_curChannel = 9; _curChannel >= 0; --_curChannel) {
-			if ((_syncJumpMask & (1 << _curChannel)) == 0)
-				continue;
-
-			if (_channels[_curChannel].dataptr && !_channels[_curChannel].lock)
-				forceUnlock = false;
+			if ((_syncJumpMask & (1 << _curChannel)) && _channels[_curChannel].dataptr && !_channels[_curChannel].lock)
+				break; // don't unlock
 		}
 
-		if (forceUnlock) {
+		if (_curChannel < 0) {
+			// force unlock
 			for (_curChannel = 9; _curChannel >= 0; --_curChannel)
 				if (_syncJumpMask & (1 << _curChannel))
 					_channels[_curChannel].lock = false;
@@ -682,7 +678,6 @@ void AdLibDriver::executePrograms() {
 
 	for (_curChannel = 9; _curChannel >= 0; --_curChannel) {
 		Channel &channel = _channels[_curChannel];
-		int result = 1;
 
 		if (!channel.dataptr)
 			continue;
@@ -698,6 +693,7 @@ void AdLibDriver::executePrograms() {
 		if (channel.tempoReset)
 			channel.tempo = _tempo;
 
+		int result = 1;
 		if (advance(channel.timer, channel.tempo)) {
 			if (--channel.duration) {
 				if (channel.duration == channel.spacing2)
@@ -705,60 +701,50 @@ void AdLibDriver::executePrograms() {
 				if (channel.duration == channel.spacing1 && _curChannel != 9)
 					noteOff(channel);
 			} else {
-				// An opcode is not allowed to modify its own
-				// data pointer except through the 'dataptr'
-				// parameter. To enforce that, we have to work
-				// on a copy of the data pointer.
-				//
-				// This fixes a subtle music bug where the
-				// wrong music would play when getting the
-				// quill in Kyra 1.
-				const uint8 *dataptr = channel.dataptr;
-				while (dataptr) {
-					uint8 opcode, param;
-					// Safety check to avoid illegal access.
-					// Stop channel if not enough data.
-					if (dataptr - _soundData < _soundDataSize)
-						opcode = *dataptr++;
-					else
-						opcode = 0xFF;
-					if (opcode < 0x80 && dataptr - _soundData == _soundDataSize)
-						opcode = 0xFF;
-
-					if (opcode & 0x80) {
-						opcode &= 0x7F;
-						if (opcode >= _parserOpcodeTableSize)
-							opcode = _parserOpcodeTableSize - 1;
-						// Safety check for end of data.
-						if (dataptr - _soundData + _parserOpcodeTable[opcode].values > _soundDataSize)
-							opcode = _parserOpcodeTableSize - 1;
-
-						const ParserOpcode &op = _parserOpcodeTable[opcode];
-						param = op.values ? *dataptr : 0;
-						dataptr++;
-
-						debugC(9, kDebugLevelSound, "Calling opcode '%s' (%d) (channel: %d)", op.name, opcode, _curChannel);
-						result = (this->*(op.function))(dataptr, channel, param);
-						channel.dataptr = dataptr;
-						if (result)
-							break;
-					} else {
-						param = *dataptr++;
-						debugC(9, kDebugLevelSound, "Note on opcode 0x%02X (duration: %d) (channel: %d)", opcode, param, _curChannel);
-						setupNote(opcode, channel);
-						noteOn(channel);
-						setupDuration(param, channel);
-						if (param) {
-							// We need to make sure we are always running the
-							// effects after this. Otherwise some sounds are
-							// wrong. Like the sfx when bumping into a wall in
-							// LoL.
-							result = 1;
-							channel.dataptr = dataptr;
-							break;
-						}
-					}
-				}
+				// Process some opcodes.
+				result = 0;
+			}
+		}
+
+		// An opcode is not allowed to modify its own data pointer
+		// except through the 'dataptr' parameter. To enforce that,
+		// we have to work on a copy of the data pointer.
+		//
+		// This fixes a subtle music bug where the wrong music would
+		// play when getting the quill in Kyra 1.
+
+		for (const uint8 *dataptr = channel.dataptr; dataptr && !result; channel.dataptr = dataptr) {
+			uint8 opcode = 0xFF;
+			// Safety check to avoid illegal access.
+			// Stop channel if not enough data.
+			if (dataptr - _soundData < _soundDataSize)
+				opcode = *dataptr++;
+			if (opcode < 0x80 && dataptr - _soundData == _soundDataSize)
+				opcode = 0xFF;
+
+			if (opcode & 0x80) {
+				opcode = CLIP(opcode & 0x7F, 0, _parserOpcodeTableSize - 1);
+				// Safety check for end of data.
+				if (dataptr - _soundData + _parserOpcodeTable[opcode].values > _soundDataSize)
+					opcode = _parserOpcodeTableSize - 1;
+
+				const ParserOpcode &op = _parserOpcodeTable[opcode];
+				uint8 param = op.values ? *dataptr : 0;
+				dataptr++;
+
+				debugC(9, kDebugLevelSound, "Calling opcode '%s' (%d) (channel: %d)", op.name, opcode, _curChannel);
+				result = (this->*(op.function))(dataptr, channel, param);
+			} else {
+				uint8 param = *dataptr++;
+				debugC(9, kDebugLevelSound, "Note on opcode 0x%02X (duration: %d) (channel: %d)", opcode, param, _curChannel);
+				setupNote(opcode, channel);
+				noteOn(channel);
+				setupDuration(param, channel);
+				// We need to make sure we are always running the
+				// effects after this. Otherwise some sounds are
+				// wrong. Like the sfx when bumping into a wall in
+				// LoL.
+				result = param > 0;
 			}
 		}
 


Commit: 094988e242b551963589f51f680c26cf817598e6
    https://github.com/scummvm/scummvm/commit/094988e242b551963589f51f680c26cf817598e6
Author: Alexander Miller (alex.miller at gmx.de)
Date: 2021-01-15T19:07:47+01:00

Commit Message:
KYRA: Add helper to check offsets into _soundData

Changed paths:
    engines/kyra/sound/drivers/adlib.cpp


diff --git a/engines/kyra/sound/drivers/adlib.cpp b/engines/kyra/sound/drivers/adlib.cpp
index 91f208fc6b..56f8205b29 100644
--- a/engines/kyra/sound/drivers/adlib.cpp
+++ b/engines/kyra/sound/drivers/adlib.cpp
@@ -161,6 +161,15 @@ private:
 		return timer < old;
 	}
 
+	const uint8 *checkDataOffset(const uint8 *ptr, long n) {
+		if (ptr) {
+			long offset = ptr - _soundData;
+			if (n >= -offset && n <= (long)_soundDataSize - offset)
+				return ptr + n;
+		}
+		return nullptr;
+	}
+
 	// The sound data has two lookup tables:
 	// * One for programs, starting at offset 0.
 	// * One for instruments, starting at offset 300, 500, or 1000.
@@ -540,11 +549,11 @@ void AdLibDriver::setupPrograms() {
 	// program, plus 2 more bytes (opcode, _sfxVelocity) for sound effects.
 	// More data is needed, but executePrograms() checks for that.
 	// Also ignore request for invalid channel number.
-	if (!ptr || ptr - _soundData + 2 > _soundDataSize)
+	if (!checkDataOffset(ptr, 2))
 		return;
 
 	const int chan = *ptr;
-	if (chan > 9 || (chan < 9 && ptr - _soundData + 4 > _soundDataSize))
+	if (chan > 9 || (chan < 9 && !checkDataOffset(ptr, 4)))
 		return;
 
 	Channel &channel = _channels[chan];
@@ -717,15 +726,15 @@ void AdLibDriver::executePrograms() {
 			uint8 opcode = 0xFF;
 			// Safety check to avoid illegal access.
 			// Stop channel if not enough data.
-			if (dataptr - _soundData < _soundDataSize)
+			if (checkDataOffset(dataptr, 1))
 				opcode = *dataptr++;
-			if (opcode < 0x80 && dataptr - _soundData == _soundDataSize)
+			if (opcode < 0x80 && !checkDataOffset(dataptr, 1))
 				opcode = 0xFF;
 
 			if (opcode & 0x80) {
 				opcode = CLIP(opcode & 0x7F, 0, _parserOpcodeTableSize - 1);
 				// Safety check for end of data.
-				if (dataptr - _soundData + _parserOpcodeTable[opcode].values > _soundDataSize)
+				if (!checkDataOffset(dataptr, _parserOpcodeTable[opcode].values))
 					opcode = _parserOpcodeTableSize - 1;
 
 				const ParserOpcode &op = _parserOpcodeTable[opcode];
@@ -960,7 +969,7 @@ void AdLibDriver::setupInstrument(uint8 regOffset, const uint8 *dataptr, Channel
 		return;
 
 	// Safety check: need 11 bytes of data.
-	if (dataptr - _soundData + 11 > _soundDataSize)
+	if (!checkDataOffset(dataptr, 11))
 		return;
 
 	// Amplitude Modulation / Vibrato / Envelope Generator Type /
@@ -1288,7 +1297,7 @@ int AdLibDriver::update_checkRepeat(const uint8 *&dataptr, Channel &channel, uin
 		int16 add = READ_LE_UINT16(dataptr - 2);
 
 		// Safety check: ignore jump to invalid address
-		if (add < -(dataptr - _soundData) || _soundData + _soundDataSize - dataptr <= add)
+		if (!checkDataOffset(dataptr, add))
 			warning("AdlibDriver::update_checkRepeat: Ignoring invalid offset %i", add);
 		else
 			dataptr += add;
@@ -1308,7 +1317,7 @@ int AdLibDriver::update_setupProgram(const uint8 *&dataptr, Channel &channel, ui
 	// them.
 	// This, for example, happens in the Lands of Lore intro when Scotia gets
 	// the ring in the intro.
-	if (!ptr || ptr - _soundData + 2 > _soundDataSize) {
+	if (!checkDataOffset(ptr, 2)) {
 		debugC(3, kDebugLevelSound, "AdLibDriver::update_setupProgram: Invalid program %d specified", value);
 		return 0;
 	}
@@ -1355,18 +1364,12 @@ int AdLibDriver::update_setNoteSpacing(const uint8 *&dataptr, Channel &channel,
 int AdLibDriver::update_jump(const uint8 *&dataptr, Channel &channel, uint8 value) {
 	--dataptr;
 	int16 add = READ_LE_UINT16(dataptr); dataptr += 2;
-	if (_version == 1) {
-		// Safety check: ignore jump to invalid address
-		if (add < 191 || add - 191 >= (int32)_soundDataSize)
-			dataptr = nullptr;
-		else
-			dataptr = _soundData + add - 191;
-	} else {
-		if (add < -(dataptr - _soundData) || _soundData + _soundDataSize - dataptr <= add)
-			dataptr = nullptr;
-		else
-			dataptr += add;
-	}
+	// Safety check: ignore jump to invalid address
+	if (_version == 1)
+		dataptr = checkDataOffset(_soundData, add - 191);
+	else
+		dataptr = checkDataOffset(dataptr, add);
+
 	if (!dataptr) {
 		warning("AdlibDriver::update_jump: Invalid offset %i, stopping channel", add);
 		return update_stopChannel(dataptr, channel, 0);
@@ -1386,17 +1389,11 @@ int AdLibDriver::update_jumpToSubroutine(const uint8 *&dataptr, Channel &channel
 		return 0;
 	}
 	channel.dataptrStack[channel.dataptrStackPos++] = dataptr;
-	if (_version < 3) {
-		if (add < 191 || add - 191 >= (int32)_soundDataSize)
-			dataptr = nullptr;
-		else
-			dataptr = _soundData + add - 191;
-	} else {
-		if (add < -(dataptr - _soundData) || _soundData + _soundDataSize - dataptr <= add)
-			dataptr = nullptr;
-		else
-			dataptr += add;
-	}
+	if (_version < 3)
+		dataptr = checkDataOffset(_soundData, add - 191);
+	else
+		dataptr = checkDataOffset(dataptr, add);
+
 	if (!dataptr)
 		dataptr = channel.dataptrStack[--channel.dataptrStackPos];
 	return 0;


Commit: bfb4a6219f92a0bb92670e04398915ab12ab3f07
    https://github.com/scummvm/scummvm/commit/bfb4a6219f92a0bb92670e04398915ab12ab3f07
Author: Alexander Miller (alex.miller at gmx.de)
Date: 2021-01-15T19:07:47+01:00

Commit Message:
KYRA: Don't depend on struct layout in AdLibDriver::initChannel()

Changed paths:
    engines/kyra/sound/drivers/adlib.cpp


diff --git a/engines/kyra/sound/drivers/adlib.cpp b/engines/kyra/sound/drivers/adlib.cpp
index 56f8205b29..78fcbbeb38 100644
--- a/engines/kyra/sound/drivers/adlib.cpp
+++ b/engines/kyra/sound/drivers/adlib.cpp
@@ -800,8 +800,10 @@ void AdLibDriver::writeOPL(byte reg, byte val) {
 
 void AdLibDriver::initChannel(Channel &channel) {
 	debugC(9, kDebugLevelSound, "initChannel(%lu)", (long)(&channel - _channels));
-	memset(&channel.dataptr, 0, sizeof(Channel) - ((char *)&channel.dataptr - (char *)&channel));
+	uint8 backupEL2 = channel.opExtraLevel2;
+	memset(&channel, 0, sizeof(Channel));
 
+	channel.opExtraLevel2 = backupEL2;
 	channel.tempo = 0xFF;
 	channel.priority = 0;
 	// normally here are nullfuncs but we set nullptr for now


Commit: 3fb4d67b4e4fc666232da3b2eca60d0fc8781cd0
    https://github.com/scummvm/scummvm/commit/3fb4d67b4e4fc666232da3b2eca60d0fc8781cd0
Author: Alexander Miller (alex.miller at gmx.de)
Date: 2021-01-15T19:07:47+01:00

Commit Message:
KYRA: Change calling convention of opcode callbacks

Call the opcode functions with a pointer to the parameters instead
of data poiner reference and first parameter. The data pointer is
updated in AdLibDriver::executePrograms() before calling the opcode
function; an opcode can change channel.dataptr if (and only if) it
wants to jump (and is responsible not to change it inadvertently).

Changed paths:
    engines/kyra/sound/drivers/adlib.cpp


diff --git a/engines/kyra/sound/drivers/adlib.cpp b/engines/kyra/sound/drivers/adlib.cpp
index 78fcbbeb38..10ee70d54c 100644
--- a/engines/kyra/sound/drivers/adlib.cpp
+++ b/engines/kyra/sound/drivers/adlib.cpp
@@ -182,7 +182,7 @@ private:
 	void executePrograms();
 
 	struct ParserOpcode {
-		typedef int (AdLibDriver::*POpcode)(const uint8 *&dataptr, Channel &channel, uint8 value);
+		typedef int (AdLibDriver::*POpcode)(Channel &channel, const uint8 *values);
 		POpcode function;
 		const char *name;
 		int values;
@@ -191,61 +191,61 @@ private:
 	static const ParserOpcode _parserOpcodeTable[];
 	static const int _parserOpcodeTableSize;
 
-	int update_setRepeat(const uint8 *&dataptr, Channel &channel, uint8 value);
-	int update_checkRepeat(const uint8 *&dataptr, Channel &channel, uint8 value);
-	int update_setupProgram(const uint8 *&dataptr, Channel &channel, uint8 value);
-	int update_setNoteSpacing(const uint8 *&dataptr, Channel &channel, uint8 value);
-	int update_jump(const uint8 *&dataptr, Channel &channel, uint8 value);
-	int update_jumpToSubroutine(const uint8 *&dataptr, Channel &channel, uint8 value);
-	int update_returnFromSubroutine(const uint8 *&dataptr, Channel &channel, uint8 value);
-	int update_setBaseOctave(const uint8 *&dataptr, Channel &channel, uint8 value);
-	int update_stopChannel(const uint8 *&dataptr, Channel &channel, uint8 value);
-	int update_playRest(const uint8 *&dataptr, Channel &channel, uint8 value);
-	int update_writeAdLib(const uint8 *&dataptr, Channel &channel, uint8 value);
-	int update_setupNoteAndDuration(const uint8 *&dataptr, Channel &channel, uint8 value);
-	int update_setBaseNote(const uint8 *&dataptr, Channel &channel, uint8 value);
-	int update_setupSecondaryEffect1(const uint8 *&dataptr, Channel &channel, uint8 value);
-	int update_stopOtherChannel(const uint8 *&dataptr, Channel &channel, uint8 value);
-	int update_waitForEndOfProgram(const uint8 *&dataptr, Channel &channel, uint8 value);
-	int update_setupInstrument(const uint8 *&dataptr, Channel &channel, uint8 value);
-	int update_setupPrimaryEffectSlide(const uint8 *&dataptr, Channel &channel, uint8 value);
-	int update_removePrimaryEffectSlide(const uint8 *&dataptr, Channel &channel, uint8 value);
-	int update_setBaseFreq(const uint8 *&dataptr, Channel &channel, uint8 value);
-	int update_setupPrimaryEffectVibrato(const uint8 *&dataptr, Channel &channel, uint8 value);
-	int update_setPriority(const uint8 *&dataptr, Channel &channel, uint8 value);
-	int update_setBeat(const uint8 *&dataptr, Channel &channel, uint8 value);
-	int update_waitForNextBeat(const uint8 *&dataptr, Channel &channel, uint8 value);
-	int update_setExtraLevel1(const uint8 *&dataptr, Channel &channel, uint8 value);
-	int update_setupDuration(const uint8 *&dataptr, Channel &channel, uint8 value);
-	int update_playNote(const uint8 *&dataptr, Channel &channel, uint8 value);
-	int update_setFractionalNoteSpacing(const uint8 *&dataptr, Channel &channel, uint8 value);
-	int update_setTempo(const uint8 *&dataptr, Channel &channel, uint8 value);
-	int update_removeSecondaryEffect1(const uint8 *&dataptr, Channel &channel, uint8 value);
-	int update_setChannelTempo(const uint8 *&dataptr, Channel &channel, uint8 value);
-	int update_setExtraLevel3(const uint8 *&dataptr, Channel &channel, uint8 value);
-	int update_setExtraLevel2(const uint8 *&dataptr, Channel &channel, uint8 value);
-	int update_changeExtraLevel2(const uint8 *&dataptr, Channel &channel, uint8 value);
-	int update_setAMDepth(const uint8 *&dataptr, Channel &channel, uint8 value);
-	int update_setVibratoDepth(const uint8 *&dataptr, Channel &channel, uint8 value);
-	int update_changeExtraLevel1(const uint8 *&dataptr, Channel &channel, uint8 value);
-	int update_clearChannel(const uint8 *&dataptr, Channel &channel, uint8 value);
-	int update_changeNoteRandomly(const uint8 *&dataptr, Channel &channel, uint8 value);
-	int update_removePrimaryEffectVibrato(const uint8 *&dataptr, Channel &channel, uint8 value);
-	int update_pitchBend(const uint8 *&dataptr, Channel &channel, uint8 value);
-	int update_resetToGlobalTempo(const uint8 *&dataptr, Channel &channel, uint8 value);
-	int update_nop(const uint8 *&dataptr, Channel &channel, uint8 value);
-	int update_setDurationRandomness(const uint8 *&dataptr, Channel &channel, uint8 value);
-	int update_changeChannelTempo(const uint8 *&dataptr, Channel &channel, uint8 value);
-	int updateCallback46(const uint8 *&dataptr, Channel &channel, uint8 value);
-	int update_setupRhythmSection(const uint8 *&dataptr, Channel &channel, uint8 value);
-	int update_playRhythmSection(const uint8 *&dataptr, Channel &channel, uint8 value);
-	int update_removeRhythmSection(const uint8 *&dataptr, Channel &channel, uint8 value);
-	int update_setRhythmLevel2(const uint8 *&dataptr, Channel &channel, uint8 value);
-	int update_changeRhythmLevel1(const uint8 *&dataptr, Channel &channel, uint8 value);
-	int update_setRhythmLevel1(const uint8 *&dataptr, Channel &channel, uint8 value);
-	int update_setSoundTrigger(const uint8 *&dataptr, Channel &channel, uint8 value);
-	int update_setTempoReset(const uint8 *&dataptr, Channel &channel, uint8 value);
-	int updateCallback56(const uint8 *&dataptr, Channel &channel, uint8 value);
+	int update_setRepeat(Channel &channel, const uint8 *values);
+	int update_checkRepeat(Channel &channel, const uint8 *values);
+	int update_setupProgram(Channel &channel, const uint8 *values);
+	int update_setNoteSpacing(Channel &channel, const uint8 *values);
+	int update_jump(Channel &channel, const uint8 *values);
+	int update_jumpToSubroutine(Channel &channel, const uint8 *values);
+	int update_returnFromSubroutine(Channel &channel, const uint8 *values);
+	int update_setBaseOctave(Channel &channel, const uint8 *values);
+	int update_stopChannel(Channel &channel, const uint8 *values);
+	int update_playRest(Channel &channel, const uint8 *values);
+	int update_writeAdLib(Channel &channel, const uint8 *values);
+	int update_setupNoteAndDuration(Channel &channel, const uint8 *values);
+	int update_setBaseNote(Channel &channel, const uint8 *values);
+	int update_setupSecondaryEffect1(Channel &channel, const uint8 *values);
+	int update_stopOtherChannel(Channel &channel, const uint8 *values);
+	int update_waitForEndOfProgram(Channel &channel, const uint8 *values);
+	int update_setupInstrument(Channel &channel, const uint8 *values);
+	int update_setupPrimaryEffectSlide(Channel &channel, const uint8 *values);
+	int update_removePrimaryEffectSlide(Channel &channel, const uint8 *values);
+	int update_setBaseFreq(Channel &channel, const uint8 *values);
+	int update_setupPrimaryEffectVibrato(Channel &channel, const uint8 *values);
+	int update_setPriority(Channel &channel, const uint8 *values);
+	int update_setBeat(Channel &channel, const uint8 *values);
+	int update_waitForNextBeat(Channel &channel, const uint8 *values);
+	int update_setExtraLevel1(Channel &channel, const uint8 *values);
+	int update_setupDuration(Channel &channel, const uint8 *values);
+	int update_playNote(Channel &channel, const uint8 *values);
+	int update_setFractionalNoteSpacing(Channel &channel, const uint8 *values);
+	int update_setTempo(Channel &channel, const uint8 *values);
+	int update_removeSecondaryEffect1(Channel &channel, const uint8 *values);
+	int update_setChannelTempo(Channel &channel, const uint8 *values);
+	int update_setExtraLevel3(Channel &channel, const uint8 *values);
+	int update_setExtraLevel2(Channel &channel, const uint8 *values);
+	int update_changeExtraLevel2(Channel &channel, const uint8 *values);
+	int update_setAMDepth(Channel &channel, const uint8 *values);
+	int update_setVibratoDepth(Channel &channel, const uint8 *values);
+	int update_changeExtraLevel1(Channel &channel, const uint8 *values);
+	int update_clearChannel(Channel &channel, const uint8 *values);
+	int update_changeNoteRandomly(Channel &channel, const uint8 *values);
+	int update_removePrimaryEffectVibrato(Channel &channel, const uint8 *values);
+	int update_pitchBend(Channel &channel, const uint8 *values);
+	int update_resetToGlobalTempo(Channel &channel, const uint8 *values);
+	int update_nop(Channel &channel, const uint8 *values);
+	int update_setDurationRandomness(Channel &channel, const uint8 *values);
+	int update_changeChannelTempo(Channel &channel, const uint8 *values);
+	int updateCallback46(Channel &channel, const uint8 *values);
+	int update_setupRhythmSection(Channel &channel, const uint8 *values);
+	int update_playRhythmSection(Channel &channel, const uint8 *values);
+	int update_removeRhythmSection(Channel &channel, const uint8 *values);
+	int update_setRhythmLevel2(Channel &channel, const uint8 *values);
+	int update_changeRhythmLevel1(Channel &channel, const uint8 *values);
+	int update_setRhythmLevel1(Channel &channel, const uint8 *values);
+	int update_setSoundTrigger(Channel &channel, const uint8 *values);
+	int update_setTempoReset(Channel &channel, const uint8 *values);
+	int updateCallback56(Channel &channel, const uint8 *values);
 private:
 	// These variables have not yet been named, but some of them are partly
 	// known nevertheless:
@@ -645,14 +645,12 @@ void AdLibDriver::adjustSfxData(uint8 *ptr, int volume) {
 // off depending on manual or automatic note spacing. Once the duration reaches
 // zero, a new set of musical opcodes are executed.
 //
-// An opcode is one byte, followed by a variable number of parameters. Since
-// most opcodes have at least one one-byte parameter, we read that as well. Any
-// opcode that doesn't have that one parameter is responsible for moving the
-// data pointer back again.
-//
+// An opcode is one byte, followed by a variable number of parameters.
 // If the most significant bit of the opcode is 1, it's a function; call it.
-// The opcode functions return either 0 (continue), 1 (stop) or 2 (stop, and do
-// not run the effects callbacks).
+// An opcode function can change control flow by updating the channel's data
+// pointer (which is set to the next opcode before the call). The function's
+// return value is either 0 (continue), 1 (stop) or 2 (stop, and do not run
+// the effects callbacks).
 //
 // If the most significant bit of the opcode is 0, it's a note, and the first
 // parameter is its duration. (There are cases where the duration is modified
@@ -687,8 +685,9 @@ void AdLibDriver::executePrograms() {
 
 	for (_curChannel = 9; _curChannel >= 0; --_curChannel) {
 		Channel &channel = _channels[_curChannel];
+		const uint8 *&dataptr = channel.dataptr;
 
-		if (!channel.dataptr)
+		if (!dataptr)
 			continue;
 
 		if (channel.lock && (_syncJumpMask & (1 << _curChannel)))
@@ -715,45 +714,45 @@ void AdLibDriver::executePrograms() {
 			}
 		}
 
-		// An opcode is not allowed to modify its own data pointer
-		// except through the 'dataptr' parameter. To enforce that,
-		// we have to work on a copy of the data pointer.
-		//
-		// This fixes a subtle music bug where the wrong music would
-		// play when getting the quill in Kyra 1.
-
-		for (const uint8 *dataptr = channel.dataptr; dataptr && !result; channel.dataptr = dataptr) {
+		while (result == 0 && dataptr) {
 			uint8 opcode = 0xFF;
 			// Safety check to avoid illegal access.
 			// Stop channel if not enough data.
 			if (checkDataOffset(dataptr, 1))
 				opcode = *dataptr++;
-			if (opcode < 0x80 && !checkDataOffset(dataptr, 1))
-				opcode = 0xFF;
 
 			if (opcode & 0x80) {
 				opcode = CLIP(opcode & 0x7F, 0, _parserOpcodeTableSize - 1);
-				// Safety check for end of data.
-				if (!checkDataOffset(dataptr, _parserOpcodeTable[opcode].values))
-					opcode = _parserOpcodeTableSize - 1;
-
 				const ParserOpcode &op = _parserOpcodeTable[opcode];
-				uint8 param = op.values ? *dataptr : 0;
-				dataptr++;
+
+				// Safety check for end of data.
+				if (!checkDataOffset(dataptr, op.values)) {
+					result = update_stopChannel(channel, dataptr);
+					break;
+				}
 
 				debugC(9, kDebugLevelSound, "Calling opcode '%s' (%d) (channel: %d)", op.name, opcode, _curChannel);
-				result = (this->*(op.function))(dataptr, channel, param);
+
+				dataptr += op.values;
+				result = (this->*(op.function))(channel, dataptr - op.values);
 			} else {
-				uint8 param = *dataptr++;
-				debugC(9, kDebugLevelSound, "Note on opcode 0x%02X (duration: %d) (channel: %d)", opcode, param, _curChannel);
+				// Safety check for end of data.
+				if (!checkDataOffset(dataptr, 1)) {
+					result = update_stopChannel(channel, dataptr);
+					break;
+				}
+
+				uint8 duration = *dataptr++;
+				debugC(9, kDebugLevelSound, "Note on opcode 0x%02X (duration: %d) (channel: %d)", opcode, duration, _curChannel);
+
 				setupNote(opcode, channel);
 				noteOn(channel);
-				setupDuration(param, channel);
+				setupDuration(duration, channel);
 				// We need to make sure we are always running the
 				// effects after this. Otherwise some sounds are
 				// wrong. Like the sfx when bumping into a wall in
 				// LoL.
-				result = param > 0;
+				result = duration != 0;
 			}
 		}
 
@@ -1288,30 +1287,29 @@ uint8 AdLibDriver::calculateOpLevel2(Channel &channel) {
 
 // parser opcodes
 
-int AdLibDriver::update_setRepeat(const uint8 *&dataptr, Channel &channel, uint8 value) {
-	channel.repeatCounter = value;
+int AdLibDriver::update_setRepeat(Channel &channel, const uint8 *values) {
+	channel.repeatCounter = values[0];
 	return 0;
 }
 
-int AdLibDriver::update_checkRepeat(const uint8 *&dataptr, Channel &channel, uint8 value) {
-	++dataptr;
+int AdLibDriver::update_checkRepeat(Channel &channel, const uint8 *values) {
 	if (--channel.repeatCounter) {
-		int16 add = READ_LE_UINT16(dataptr - 2);
+		int16 add = READ_LE_UINT16(values);
 
 		// Safety check: ignore jump to invalid address
-		if (!checkDataOffset(dataptr, add))
+		if (!checkDataOffset(channel.dataptr, add))
 			warning("AdlibDriver::update_checkRepeat: Ignoring invalid offset %i", add);
 		else
-			dataptr += add;
+			channel.dataptr += add;
 	}
 	return 0;
 }
 
-int AdLibDriver::update_setupProgram(const uint8 *&dataptr, Channel &channel, uint8 value) {
-	if (value == 0xFF)
+int AdLibDriver::update_setupProgram(Channel &channel, const uint8 *values) {
+	if (values[0] == 0xFF)
 		return 0;
 
-	const uint8 *ptr = getProgram(value);
+	const uint8 *ptr = getProgram(values[0]);
 
 	// In case we encounter an invalid program we simply ignore it and do
 	// nothing instead. The original did not care about invalid programs and
@@ -1320,7 +1318,7 @@ int AdLibDriver::update_setupProgram(const uint8 *&dataptr, Channel &channel, ui
 	// This, for example, happens in the Lands of Lore intro when Scotia gets
 	// the ring in the intro.
 	if (!checkDataOffset(ptr, 2)) {
-		debugC(3, kDebugLevelSound, "AdLibDriver::update_setupProgram: Invalid program %d specified", value);
+		debugC(3, kDebugLevelSound, "AdLibDriver::update_setupProgram: Invalid program %d specified", values[0]);
 		return 0;
 	}
 
@@ -1336,10 +1334,18 @@ int AdLibDriver::update_setupProgram(const uint8 *&dataptr, Channel &channel, ui
 	Channel &channel2 = _channels[chan];
 
 	if (priority >= channel2.priority) {
+		// The opcode is not allowed to modify its own data pointer.
+		// To enforce that, we make a copy and restore it later.
+		//
+		// This fixes a subtle music bug where the wrong music would
+		// play when getting the quill in Kyra 1.
+		const uint8 *dataptrBackUp = channel.dataptr;
+
 		// We keep new tracks from being started for two further iterations of
 		// the callback. This assures the correct velocity is used for this
 		// program.
 		_programStartTimeout = 2;
+
 		initChannel(channel2);
 		channel2.priority = priority;
 		channel2.dataptr = ptr;
@@ -1353,105 +1359,103 @@ int AdLibDriver::update_setupProgram(const uint8 *&dataptr, Channel &channel, ui
 			channel2.volumeModifier = _sfxVolume;
 
 		initAdlibChannel(chan);
+
+		channel.dataptr = dataptrBackUp;
 	}
 
 	return 0;
 }
 
-int AdLibDriver::update_setNoteSpacing(const uint8 *&dataptr, Channel &channel, uint8 value) {
-	channel.spacing1 = value;
+int AdLibDriver::update_setNoteSpacing(Channel &channel, const uint8 *values) {
+	channel.spacing1 = values[0];
 	return 0;
 }
 
-int AdLibDriver::update_jump(const uint8 *&dataptr, Channel &channel, uint8 value) {
-	--dataptr;
-	int16 add = READ_LE_UINT16(dataptr); dataptr += 2;
+int AdLibDriver::update_jump(Channel &channel, const uint8 *values) {
+	int16 add = READ_LE_UINT16(values);
 	// Safety check: ignore jump to invalid address
 	if (_version == 1)
-		dataptr = checkDataOffset(_soundData, add - 191);
+		channel.dataptr = checkDataOffset(_soundData, add - 191);
 	else
-		dataptr = checkDataOffset(dataptr, add);
+		channel.dataptr = checkDataOffset(channel.dataptr, add);
 
-	if (!dataptr) {
+	if (!channel.dataptr) {
 		warning("AdlibDriver::update_jump: Invalid offset %i, stopping channel", add);
-		return update_stopChannel(dataptr, channel, 0);
+		return update_stopChannel(channel, values);
 	}
 	if (_syncJumpMask & (1 << (&channel - _channels)))
 		channel.lock = true;
 	return 0;
 }
 
-int AdLibDriver::update_jumpToSubroutine(const uint8 *&dataptr, Channel &channel, uint8 value) {
-	--dataptr;
-	int16 add = READ_LE_UINT16(dataptr); dataptr += 2;
+int AdLibDriver::update_jumpToSubroutine(Channel &channel, const uint8 *values) {
+	int16 add = READ_LE_UINT16(values);
 
 	// Safety checks: ignore jumps when stack is full or address is invalid.
 	if (channel.dataptrStackPos >= ARRAYSIZE(channel.dataptrStack)) {
 		warning("AdLibDriver::update_jumpToSubroutine: Stack overlow");
 		return 0;
 	}
-	channel.dataptrStack[channel.dataptrStackPos++] = dataptr;
+	channel.dataptrStack[channel.dataptrStackPos++] = channel.dataptr;
 	if (_version < 3)
-		dataptr = checkDataOffset(_soundData, add - 191);
+		channel.dataptr = checkDataOffset(_soundData, add - 191);
 	else
-		dataptr = checkDataOffset(dataptr, add);
+		channel.dataptr = checkDataOffset(channel.dataptr, add);
 
-	if (!dataptr)
-		dataptr = channel.dataptrStack[--channel.dataptrStackPos];
+	if (!channel.dataptr)
+		channel.dataptr = channel.dataptrStack[--channel.dataptrStackPos];
 	return 0;
 }
 
-int AdLibDriver::update_returnFromSubroutine(const uint8 *&dataptr, Channel &channel, uint8 value) {
+int AdLibDriver::update_returnFromSubroutine(Channel &channel, const uint8 *values) {
 	// Safety check: stop track when stack is empty.
 	if (!channel.dataptrStackPos) {
 		warning("AdLibDriver::update_returnFromSubroutine: Stack underflow");
-		return update_stopChannel(dataptr, channel, 0);
+		return update_stopChannel(channel, values);
 	}
-	dataptr = channel.dataptrStack[--channel.dataptrStackPos];
+	channel.dataptr = channel.dataptrStack[--channel.dataptrStackPos];
 	return 0;
 }
 
-int AdLibDriver::update_setBaseOctave(const uint8 *&dataptr, Channel &channel, uint8 value) {
-	channel.baseOctave = value;
+int AdLibDriver::update_setBaseOctave(Channel &channel, const uint8 *values) {
+	channel.baseOctave = values[0];
 	return 0;
 }
 
-int AdLibDriver::update_stopChannel(const uint8 *&dataptr, Channel &channel, uint8 value) {
+int AdLibDriver::update_stopChannel(Channel &channel, const uint8 *values) {
 	channel.priority = 0;
 	if (_curChannel != 9)
 		noteOff(channel);
-	dataptr = nullptr;
+	channel.dataptr = nullptr;
 	return 2;
 }
 
-int AdLibDriver::update_playRest(const uint8 *&dataptr, Channel &channel, uint8 value) {
-	setupDuration(value, channel);
+int AdLibDriver::update_playRest(Channel &channel, const uint8 *values) {
+	setupDuration(values[0], channel);
 	noteOff(channel);
-	return (value != 0);
+	return values[0] != 0;
 }
 
-int AdLibDriver::update_writeAdLib(const uint8 *&dataptr, Channel &channel, uint8 value) {
-	writeOPL(value, *dataptr++);
+int AdLibDriver::update_writeAdLib(Channel &channel, const uint8 *values) {
+	writeOPL(values[0], values[1]);
 	return 0;
 }
 
-int AdLibDriver::update_setupNoteAndDuration(const uint8 *&dataptr, Channel &channel, uint8 value) {
-	setupNote(value, channel);
-	value = *dataptr++;
-	setupDuration(value, channel);
-	return (value != 0);
+int AdLibDriver::update_setupNoteAndDuration(Channel &channel, const uint8 *values) {
+	setupNote(values[0], channel);
+	setupDuration(values[1], channel);
+	return values[1] != 0;
 }
 
-int AdLibDriver::update_setBaseNote(const uint8 *&dataptr, Channel &channel, uint8 value) {
-	channel.baseNote = value;
+int AdLibDriver::update_setBaseNote(Channel &channel, const uint8 *values) {
+	channel.baseNote = values[0];
 	return 0;
 }
 
-int AdLibDriver::update_setupSecondaryEffect1(const uint8 *&dataptr, Channel &channel, uint8 value) {
-	channel.secondaryEffectTimer = value;
-	channel.secondaryEffectTempo = value;
-	channel.secondaryEffectSize = channel.secondaryEffectPos = *dataptr++;
-	channel.secondaryEffectRegbase = *dataptr++;
+int AdLibDriver::update_setupSecondaryEffect1(Channel &channel, const uint8 *values) {
+	channel.secondaryEffectTimer = channel.secondaryEffectTempo = values[0];
+	channel.secondaryEffectSize = channel.secondaryEffectPos = values[1];
+	channel.secondaryEffectRegbase = values[2];
 	// WORKAROUND: The original code reads a true offset which later gets translated via xlat (in
 	// the current segment). This means that the outcome depends on the sound data offset.
 	// Unfortunately this offset is different in most implementations of the audio driver and
@@ -1466,8 +1470,7 @@ int AdLibDriver::update_setupSecondaryEffect1(const uint8 *&dataptr, Channel &ch
 	// since the sound data is exactly the same.
 	// In DOSBox the teleporters will sound different in EOB I and II, due to different sound
 	// data offsets.
-	channel.secondaryEffectData = READ_LE_UINT16(dataptr) - 191;
-	dataptr += 2;
+	channel.secondaryEffectData = READ_LE_UINT16(&values[3]) - 191;
 	channel.secondaryEffect = &AdLibDriver::secondaryEffect1;
 
 	// Safety check: don't enable effect when table location is invalid.
@@ -1479,27 +1482,32 @@ int AdLibDriver::update_setupSecondaryEffect1(const uint8 *&dataptr, Channel &ch
 	return 0;
 }
 
-int AdLibDriver::update_stopOtherChannel(const uint8 *&dataptr, Channel &channel, uint8 value) {
+int AdLibDriver::update_stopOtherChannel(Channel &channel, const uint8 *values) {
 	// Safety check
-	if (value > 9) {
-		warning("AdLibDriver::update_stopOtherChannel: Ignoring invalid channel %d", value);
+	if (values[0] > 9) {
+		warning("AdLibDriver::update_stopOtherChannel: Ignoring invalid channel %d", values[0]);
 		return 0;
 	}
 
-	Channel &channel2 = _channels[value];
+	// Don't change our own dataptr!
+	const uint8 *dataptrBackUp = channel.dataptr;
+
+	Channel &channel2 = _channels[values[0]];
 	channel2.duration = 0;
 	channel2.priority = 0;
 	channel2.dataptr = nullptr;
+
+	channel.dataptr = dataptrBackUp;
 	return 0;
 }
 
-int AdLibDriver::update_waitForEndOfProgram(const uint8 *&dataptr, Channel &channel, uint8 value) {
-	const uint8 *ptr = getProgram(value);
+int AdLibDriver::update_waitForEndOfProgram(Channel &channel, const uint8 *values) {
+	const uint8 *ptr = getProgram(values[0]);
 
 	// Safety check in case an invalid program is specified. This would make
 	// getProgram return a nullptr and thus cause invalid memory reads.
 	if (!ptr) {
-		debugC(3, kDebugLevelSound, "AdLibDriver::update_waitForEndOfProgram: Invalid program %d specified", value);
+		debugC(3, kDebugLevelSound, "AdLibDriver::update_waitForEndOfProgram: Invalid program %d specified", values[0]);
 		return 0;
 	}
 
@@ -1508,12 +1516,12 @@ int AdLibDriver::update_waitForEndOfProgram(const uint8 *&dataptr, Channel &chan
 	if (chan > 9 || !_channels[chan].dataptr)
 		return 0;
 
-	dataptr -= 2;
+	channel.dataptr -= 2;
 	return 2;
 }
 
-int AdLibDriver::update_setupInstrument(const uint8 *&dataptr, Channel &channel, uint8 value) {
-	const uint8 *instrument = getInstrument(value);
+int AdLibDriver::update_setupInstrument(Channel &channel, const uint8 *values) {
+	const uint8 *instrument = getInstrument(values[0]);
 
 	// We add a safety check to avoid setting up invalid instruments. This is
 	// not done in the original. However, to avoid crashes due to invalid
@@ -1522,7 +1530,7 @@ int AdLibDriver::update_setupInstrument(const uint8 *&dataptr, Channel &channel,
 	// potion on Zanthia to scare off the rat in the cave in the first chapter
 	// of the game.
 	if (!instrument) {
-		debugC(3, kDebugLevelSound, "AdLibDriver::update_setupInstrument: Invalid instrument %d specified", value);
+		debugC(3, kDebugLevelSound, "AdLibDriver::update_setupInstrument: Invalid instrument %d specified", values[0]);
 		return 0;
 	}
 
@@ -1530,40 +1538,37 @@ int AdLibDriver::update_setupInstrument(const uint8 *&dataptr, Channel &channel,
 	return 0;
 }
 
-int AdLibDriver::update_setupPrimaryEffectSlide(const uint8 *&dataptr, Channel &channel, uint8 value) {
-	channel.slideTempo = value;
-	channel.slideStep = READ_BE_UINT16(dataptr);
-	dataptr += 2;
+int AdLibDriver::update_setupPrimaryEffectSlide(Channel &channel, const uint8 *values) {
+	channel.slideTempo = values[0];
+	channel.slideStep = READ_BE_UINT16(&values[1]);
 	channel.primaryEffect = &AdLibDriver::primaryEffectSlide;
 	channel.slideTimer = 0xFF;
 	return 0;
 }
 
-int AdLibDriver::update_removePrimaryEffectSlide(const uint8 *&dataptr, Channel &channel, uint8 value) {
-	--dataptr;
+int AdLibDriver::update_removePrimaryEffectSlide(Channel &channel, const uint8 *values) {
 	channel.primaryEffect = nullptr;
 	channel.slideStep = 0;
 	return 0;
 }
 
-int AdLibDriver::update_setBaseFreq(const uint8 *&dataptr, Channel &channel, uint8 value) {
-	channel.baseFreq = value;
+int AdLibDriver::update_setBaseFreq(Channel &channel, const uint8 *values) {
+	channel.baseFreq = values[0];
 	return 0;
 }
 
-int AdLibDriver::update_setupPrimaryEffectVibrato(const uint8 *&dataptr, Channel &channel, uint8 value) {
-	channel.vibratoTempo = value;
-	channel.vibratoStepRange = *dataptr++;
-	uint8 temp = *dataptr++;
-	channel.vibratoStepsCountdown = temp + 1;
-	channel.vibratoNumSteps = temp << 1;
-	channel.vibratoDelay = *dataptr++;
+int AdLibDriver::update_setupPrimaryEffectVibrato(Channel &channel, const uint8 *values) {
+	channel.vibratoTempo = values[0];
+	channel.vibratoStepRange = values[1];
+	channel.vibratoStepsCountdown = values[2] + 1;
+	channel.vibratoNumSteps = values[2] << 1;
+	channel.vibratoDelay = values[3];
 	channel.primaryEffect = &AdLibDriver::primaryEffectVibrato;
 	return 0;
 }
 
-int AdLibDriver::update_setPriority(const uint8 *&dataptr, Channel &channel, uint8 value) {
-	channel.priority = value;
+int AdLibDriver::update_setPriority(Channel &channel, const uint8 *values) {
+	channel.priority = values[0];
 	return 0;
 }
 
@@ -1595,103 +1600,99 @@ int AdLibDriver::update_setPriority(const uint8 *&dataptr, Channel &channel, uin
 // in practice sice it can only happen for long delays (big _beatDivider and
 // waiting on one of the higher bits) but could have been prevented easily.
 
-int AdLibDriver::update_setBeat(const uint8 *&dataptr, Channel &channel, uint8 value) {
-	value >>= 1;
-	_beatDivider = _beatDivCnt = value;
+int AdLibDriver::update_setBeat(Channel &channel, const uint8 *values) {
+	_beatDivider = _beatDivCnt = values[0] >> 1;
 	_callbackTimer = 0xFF;
 	_beatCounter = _beatWaiting = 0;
 	return 0;
 }
 
-int AdLibDriver::update_waitForNextBeat(const uint8 *&dataptr, Channel &channel, uint8 value) {
-	if ((_beatCounter & value) && _beatWaiting) {
+int AdLibDriver::update_waitForNextBeat(Channel &channel, const uint8 *values) {
+	if ((_beatCounter & values[0]) && _beatWaiting) {
 		_beatWaiting = 0;
 		return 0;
 	}
 
-	if (!(_beatCounter & value))
+	if (!(_beatCounter & values[0]))
 		++_beatWaiting;
 
-	dataptr -= 2;
+	channel.dataptr -= 2;
 	channel.duration = 1;
 	return 2;
 }
 
-int AdLibDriver::update_setExtraLevel1(const uint8 *&dataptr, Channel &channel, uint8 value) {
-	channel.opExtraLevel1 = value;
+int AdLibDriver::update_setExtraLevel1(Channel &channel, const uint8 *values) {
+	channel.opExtraLevel1 = values[0];
 	adjustVolume(channel);
 	return 0;
 }
 
-int AdLibDriver::update_setupDuration(const uint8 *&dataptr, Channel &channel, uint8 value) {
-	setupDuration(value, channel);
-	return (value != 0);
+int AdLibDriver::update_setupDuration(Channel &channel, const uint8 *values) {
+	setupDuration(values[0], channel);
+	return values[0] != 0;
 }
 
-int AdLibDriver::update_playNote(const uint8 *&dataptr, Channel &channel, uint8 value) {
-	setupDuration(value, channel);
+int AdLibDriver::update_playNote(Channel &channel, const uint8 *values) {
+	setupDuration(values[0], channel);
 	noteOn(channel);
-	return (value != 0);
+	return values[0] != 0;
 }
 
-int AdLibDriver::update_setFractionalNoteSpacing(const uint8 *&dataptr, Channel &channel, uint8 value) {
-	channel.fractionalSpacing = value & 7;
+int AdLibDriver::update_setFractionalNoteSpacing(Channel &channel, const uint8 *values) {
+	channel.fractionalSpacing = values[0] & 7;
 	return 0;
 }
 
-int AdLibDriver::update_setTempo(const uint8 *&dataptr, Channel &channel, uint8 value) {
-	_tempo = value;
+int AdLibDriver::update_setTempo(Channel &channel, const uint8 *values) {
+	_tempo = values[0];
 	return 0;
 }
 
-int AdLibDriver::update_removeSecondaryEffect1(const uint8 *&dataptr, Channel &channel, uint8 value) {
-	--dataptr;
+int AdLibDriver::update_removeSecondaryEffect1(Channel &channel, const uint8 *values) {
 	channel.secondaryEffect = nullptr;
 	return 0;
 }
 
-int AdLibDriver::update_setChannelTempo(const uint8 *&dataptr, Channel &channel, uint8 value) {
-	channel.tempo = value;
+int AdLibDriver::update_setChannelTempo(Channel &channel, const uint8 *values) {
+	channel.tempo = values[0];
 	return 0;
 }
 
-int AdLibDriver::update_setExtraLevel3(const uint8 *&dataptr, Channel &channel, uint8 value) {
-	channel.opExtraLevel3 = value;
+int AdLibDriver::update_setExtraLevel3(Channel &channel, const uint8 *values) {
+	channel.opExtraLevel3 = values[0];
 	return 0;
 }
 
-int AdLibDriver::update_setExtraLevel2(const uint8 *&dataptr, Channel &channel, uint8 value) {
+int AdLibDriver::update_setExtraLevel2(Channel &channel, const uint8 *values) {
 	// Safety check
-	if (value > 9) {
-		warning("AdLibDriver::update_setExtraLevel2: Ignore invalid channel %d", value);
-		dataptr++;
+	if (values[0] > 9) {
+		warning("AdLibDriver::update_setExtraLevel2: Ignore invalid channel %d", values[0]);
 		return 0;
 	}
 
 	int channelBackUp = _curChannel;
 
-	_curChannel = value;
-	Channel &channel2 = _channels[value];
-	channel2.opExtraLevel2 = *dataptr++;
+	_curChannel = values[0];
+	Channel &channel2 = _channels[_curChannel];
+	channel2.opExtraLevel2 = values[1];
 	adjustVolume(channel2);
 
 	_curChannel = channelBackUp;
 	return 0;
 }
 
-int AdLibDriver::update_changeExtraLevel2(const uint8 *&dataptr, Channel &channel, uint8 value) {
+int AdLibDriver::update_changeExtraLevel2(Channel &channel, const uint8 *values) {
 	// Safety check
-	if (value > 9) {
-		warning("AdLibDriver::update_changeExtraLevel2: Ignore invalid channel %d", value);
-		dataptr++;
+	if (values[0] > 9) {
+		warning("AdLibDriver::update_changeExtraLevel2: Ignore invalid channel %d", values[0]);
 		return 0;
 	}
 
 	int channelBackUp = _curChannel;
 
-	_curChannel = value;
-	Channel &channel2 = _channels[value];
-	channel2.opExtraLevel2 += *dataptr++;
+	_curChannel = values[0];
+	Channel &channel2 = _channels[_curChannel];
+	channel2.opExtraLevel2 += values[1];
 	adjustVolume(channel2);
 
 	_curChannel = channelBackUp;
@@ -1701,8 +1702,8 @@ int AdLibDriver::update_changeExtraLevel2(const uint8 *&dataptr, Channel &channe
 // Apart from initializing to zero, these two functions are the only ones that
 // modify _vibratoAndAMDepthBits.
 
-int AdLibDriver::update_setAMDepth(const uint8 *&dataptr, Channel &channel, uint8 value) {
-	if (value & 1)
+int AdLibDriver::update_setAMDepth(Channel &channel, const uint8 *values) {
+	if (values[0] & 1)
 		_vibratoAndAMDepthBits |= 0x80;
 	else
 		_vibratoAndAMDepthBits &= 0x7F;
@@ -1711,8 +1712,8 @@ int AdLibDriver::update_setAMDepth(const uint8 *&dataptr, Channel &channel, uint
 	return 0;
 }
 
-int AdLibDriver::update_setVibratoDepth(const uint8 *&dataptr, Channel &channel, uint8 value) {
-	if (value & 1)
+int AdLibDriver::update_setVibratoDepth(Channel &channel, const uint8 *values) {
+	if (values[0] & 1)
 		_vibratoAndAMDepthBits |= 0x40;
 	else
 		_vibratoAndAMDepthBits &= 0xBF;
@@ -1721,31 +1722,33 @@ int AdLibDriver::update_setVibratoDepth(const uint8 *&dataptr, Channel &channel,
 	return 0;
 }
 
-int AdLibDriver::update_changeExtraLevel1(const uint8 *&dataptr, Channel &channel, uint8 value) {
-	channel.opExtraLevel1 += value;
+int AdLibDriver::update_changeExtraLevel1(Channel &channel, const uint8 *values) {
+	channel.opExtraLevel1 += values[0];
 	adjustVolume(channel);
 	return 0;
 }
 
-int AdLibDriver::update_clearChannel(const uint8 *&dataptr, Channel &channel, uint8 value) {
+int AdLibDriver::update_clearChannel(Channel &channel, const uint8 *values) {
 	// Safety check
-	if (value > 9) {
-		warning("AdLibDriver::update_clearChannel: Ignore invalid channel %d", value);
+	if (values[0] > 9) {
+		warning("AdLibDriver::update_clearChannel: Ignore invalid channel %d", values[0]);
 		return 0;
 	}
 
 	int channelBackUp = _curChannel;
-	_curChannel = value;
+	_curChannel = values[0];
+	// Don't modify our own dataptr!
+	const uint8 *dataptrBackUp = channel.dataptr;
 
 	// Stop channel
-	Channel &channel2 = _channels[value];
+	Channel &channel2 = _channels[_curChannel];
 	channel2.duration = channel2.priority = 0;
 	channel2.dataptr = 0;
 	channel2.opExtraLevel2 = 0;
 
-	if (value != 9) {
+	if (_curChannel != 9) {
 		// Silence channel
-		uint8 regOff = _regOffset[value];
+		uint8 regOff = _regOffset[_curChannel];
 
 		// Feedback strength / Connection type
 		writeOPL(0xC0 + _curChannel, 0x00);
@@ -1761,14 +1764,15 @@ int AdLibDriver::update_clearChannel(const uint8 *&dataptr, Channel &channel, ui
 	}
 
 	_curChannel = channelBackUp;
+	channel.dataptr = dataptrBackUp;
 	return 0;
 }
 
-int AdLibDriver::update_changeNoteRandomly(const uint8 *&dataptr, Channel &channel, uint8 value) {
+int AdLibDriver::update_changeNoteRandomly(Channel &channel, const uint8 *values) {
 	if (_curChannel >= 9)
 		return 0;
 
-	uint16 mask = READ_BE_UINT16(++dataptr - 2);
+	uint16 mask = READ_BE_UINT16(values);
 
 	uint16 note = ((channel.regBx & 0x1F) << 8) | channel.regAx;
 
@@ -1784,56 +1788,53 @@ int AdLibDriver::update_changeNoteRandomly(const uint8 *&dataptr, Channel &chann
 	return 0;
 }
 
-int AdLibDriver::update_removePrimaryEffectVibrato(const uint8 *&dataptr, Channel &channel, uint8 value) {
-	--dataptr;
+int AdLibDriver::update_removePrimaryEffectVibrato(Channel &channel, const uint8 *values) {
 	channel.primaryEffect = nullptr;
 	return 0;
 }
 
-int AdLibDriver::update_pitchBend(const uint8 *&dataptr, Channel &channel, uint8 value) {
-	channel.pitchBend = (int8)value;
+int AdLibDriver::update_pitchBend(Channel &channel, const uint8 *values) {
+	channel.pitchBend = (int8)values[0];
 	setupNote(channel.rawNote, channel, true);
 	return 0;
 }
 
-int AdLibDriver::update_resetToGlobalTempo(const uint8 *&dataptr, Channel &channel, uint8 value) {
-	--dataptr;
+int AdLibDriver::update_resetToGlobalTempo(Channel &channel, const uint8 *values) {
 	channel.tempo = _tempo;
 	return 0;
 }
 
-int AdLibDriver::update_nop(const uint8 *&dataptr, Channel &channel, uint8 value) {
-	--dataptr;
+int AdLibDriver::update_nop(Channel &channel, const uint8 *values) {
 	return 0;
 }
 
-int AdLibDriver::update_setDurationRandomness(const uint8 *&dataptr, Channel &channel, uint8 value) {
-	channel.durationRandomness = value;
+int AdLibDriver::update_setDurationRandomness(Channel &channel, const uint8 *values) {
+	channel.durationRandomness = values[0];
 	return 0;
 }
 
-int AdLibDriver::update_changeChannelTempo(const uint8 *&dataptr, Channel &channel, uint8 value) {
-	channel.tempo = CLIP(channel.tempo + (int8)value, 1, 255);
+int AdLibDriver::update_changeChannelTempo(Channel &channel, const uint8 *values) {
+	channel.tempo = CLIP(channel.tempo + (int8)values[0], 1, 255);
 	return 0;
 }
 
-int AdLibDriver::updateCallback46(const uint8 *&dataptr, Channel &channel, uint8 value) {
-	uint8 entry = *dataptr++;
+int AdLibDriver::updateCallback46(Channel &channel, const uint8 *values) {
+	uint8 entry = values[1];
 
 	// Safety check: prevent illegal table access
 	if (entry + 2 > _unkTable2Size)
 		return 0;
 
-	_tablePtr1 = _unkTable2[entry++];
-	_tablePtr2 = _unkTable2[entry];
-	if (value == 2) {
+	_tablePtr1 = _unkTable2[entry];
+	_tablePtr2 = _unkTable2[entry + 1];
+	if (values[0] == 2) {
 		// Frequency
 		writeOPL(0xA0, _tablePtr2[0]);
 	}
 	return 0;
 }
 
-int AdLibDriver::update_setupRhythmSection(const uint8 *&dataptr, Channel &channel, uint8 value) {
+int AdLibDriver::update_setupRhythmSection(Channel &channel, const uint8 *values) {
 	int channelBackUp = _curChannel;
 	int regOffsetBackUp = _curRegOffset;
 
@@ -1841,22 +1842,22 @@ int AdLibDriver::update_setupRhythmSection(const uint8 *&dataptr, Channel &chann
 	_curRegOffset = _regOffset[6];
 
 	const uint8 *instrument;
-	instrument = getInstrument(value);
+	instrument = getInstrument(values[0]);
 	if (instrument) {
 		setupInstrument(_curRegOffset, instrument, channel);
 	} else {
-		debugC(3, kDebugLevelSound, "AdLibDriver::update_setupRhythmSection: Invalid instrument %d for channel 6 specified", value);
+		debugC(3, kDebugLevelSound, "AdLibDriver::update_setupRhythmSection: Invalid instrument %d for channel 6 specified", values[0]);
 	}
 	_opLevelBD = channel.opLevel2;
 
 	_curChannel = 7;
 	_curRegOffset = _regOffset[7];
 
-	instrument = getInstrument(value = *dataptr++);
+	instrument = getInstrument(values[1]);
 	if (instrument) {
 		setupInstrument(_curRegOffset, instrument, channel);
 	} else {
-		debugC(3, kDebugLevelSound, "AdLibDriver::update_setupRhythmSection: Invalid instrument %d for channel 7 specified", value);
+		debugC(3, kDebugLevelSound, "AdLibDriver::update_setupRhythmSection: Invalid instrument %d for channel 7 specified", values[1]);
 	}
 	_opLevelHH = channel.opLevel1;
 	_opLevelSD = channel.opLevel2;
@@ -1864,28 +1865,28 @@ int AdLibDriver::update_setupRhythmSection(const uint8 *&dataptr, Channel &chann
 	_curChannel = 8;
 	_curRegOffset = _regOffset[8];
 
-	instrument = getInstrument(value = *dataptr++);
+	instrument = getInstrument(values[2]);
 	if (instrument) {
 		setupInstrument(_curRegOffset, instrument, channel);
 	} else {
-		debugC(3, kDebugLevelSound, "AdLibDriver::update_setupRhythmSection: Invalid instrument %d for channel 8 specified", value);
+		debugC(3, kDebugLevelSound, "AdLibDriver::update_setupRhythmSection: Invalid instrument %d for channel 8 specified", values[2]);
 	}
 	_opLevelTT = channel.opLevel1;
 	_opLevelCY = channel.opLevel2;
 
 	// Octave / F-Number / Key-On for channels 6, 7 and 8
 
-	_channels[6].regBx = *dataptr++ & 0x2F;
+	_channels[6].regBx = values[3] & 0x2F;
 	writeOPL(0xB6, _channels[6].regBx);
-	writeOPL(0xA6, *dataptr++);
+	writeOPL(0xA6, values[4]);
 
-	_channels[7].regBx = *dataptr++ & 0x2F;
+	_channels[7].regBx = values[5] & 0x2F;
 	writeOPL(0xB7, _channels[7].regBx);
-	writeOPL(0xA7, *dataptr++);
+	writeOPL(0xA7, values[6]);
 
-	_channels[8].regBx = *dataptr++ & 0x2F;
+	_channels[8].regBx = values[7] & 0x2F;
 	writeOPL(0xB8, _channels[8].regBx);
-	writeOPL(0xA8, *dataptr++);
+	writeOPL(0xA8, values[8]);
 
 	_rhythmSectionBits = 0x20;
 
@@ -1894,28 +1895,27 @@ int AdLibDriver::update_setupRhythmSection(const uint8 *&dataptr, Channel &chann
 	return 0;
 }
 
-int AdLibDriver::update_playRhythmSection(const uint8 *&dataptr, Channel &channel, uint8 value) {
+int AdLibDriver::update_playRhythmSection(Channel &channel, const uint8 *values) {
 	// Any instrument that we want to play, and which was already playing,
 	// is temporarily keyed off. Instruments that were off already, or
 	// which we don't want to play, retain their old on/off status. This is
 	// probably so that the instrument's envelope is played from its
 	// beginning again...
 
-	writeOPL(0xBD, (_rhythmSectionBits & ~(value & 0x1F)) | 0x20);
+	writeOPL(0xBD, (_rhythmSectionBits & ~(values[0] & 0x1F)) | 0x20);
 
 	// ...but since we only set the rhythm instrument bits, and never clear
 	// them (until the entire rhythm section is disabled), I'm not sure how
 	// useful the cleverness above is. We could perhaps simply turn off all
 	// the rhythm instruments instead.
 
-	_rhythmSectionBits |= value;
+	_rhythmSectionBits |= values[0];
 
 	writeOPL(0xBD, _vibratoAndAMDepthBits | 0x20 | _rhythmSectionBits);
 	return 0;
 }
 
-int AdLibDriver::update_removeRhythmSection(const uint8 *&dataptr, Channel &channel, uint8 value) {
-	--dataptr;
+int AdLibDriver::update_removeRhythmSection(Channel &channel, const uint8 *values) {
 	_rhythmSectionBits = 0;
 
 	// All the rhythm bits are cleared. The AM and Vibrato depth bits
@@ -1925,80 +1925,80 @@ int AdLibDriver::update_removeRhythmSection(const uint8 *&dataptr, Channel &chan
 	return 0;
 }
 
-int AdLibDriver::update_setRhythmLevel2(const uint8 *&dataptr, Channel &channel, uint8 value) {
-	uint8 value2 = *dataptr++;
+int AdLibDriver::update_setRhythmLevel2(Channel &channel, const uint8 *values) {
+	uint8 ops = values[0], v = values[1];
 
-	if (value & 1) {
-		_opExtraLevel2HH = value2;
+	if (ops & 1) {
+		_opExtraLevel2HH = v;
 
 		// Channel 7, op1: Level Key Scaling / Total Level
-		writeOPL(0x51, checkValue(value2 + _opLevelHH + _opExtraLevel1HH + _opExtraLevel2HH));
+		writeOPL(0x51, checkValue(v + _opLevelHH + _opExtraLevel1HH + _opExtraLevel2HH));
 	}
 
-	if (value & 2) {
-		_opExtraLevel2CY = value2;
+	if (ops & 2) {
+		_opExtraLevel2CY = v;
 
 		// Channel 8, op2: Level Key Scaling / Total Level
-		writeOPL(0x55, checkValue(value2 + _opLevelCY + _opExtraLevel1CY + _opExtraLevel2CY));
+		writeOPL(0x55, checkValue(v + _opLevelCY + _opExtraLevel1CY + _opExtraLevel2CY));
 	}
 
-	if (value & 4) {
-		_opExtraLevel2TT = value2;
+	if (ops & 4) {
+		_opExtraLevel2TT = v;
 
 		// Channel 8, op1: Level Key Scaling / Total Level
-		writeOPL(0x52, checkValue(value2 + _opLevelTT + _opExtraLevel1TT + _opExtraLevel2TT));
+		writeOPL(0x52, checkValue(v + _opLevelTT + _opExtraLevel1TT + _opExtraLevel2TT));
 	}
 
-	if (value & 8) {
-		_opExtraLevel2SD = value2;
+	if (ops & 8) {
+		_opExtraLevel2SD = v;
 
 		// Channel 7, op2: Level Key Scaling / Total Level
-		writeOPL(0x54, checkValue(value2 + _opLevelSD + _opExtraLevel1SD + _opExtraLevel2SD));
+		writeOPL(0x54, checkValue(v + _opLevelSD + _opExtraLevel1SD + _opExtraLevel2SD));
 	}
 
-	if (value & 16) {
-		_opExtraLevel2BD = value2;
+	if (ops & 16) {
+		_opExtraLevel2BD = v;
 
 		// Channel 6, op2: Level Key Scaling / Total Level
-		writeOPL(0x53, checkValue(value2 + _opLevelBD + _opExtraLevel1BD + _opExtraLevel2BD));
+		writeOPL(0x53, checkValue(v + _opLevelBD + _opExtraLevel1BD + _opExtraLevel2BD));
 	}
 
 	return 0;
 }
 
-int AdLibDriver::update_changeRhythmLevel1(const uint8 *&dataptr, Channel &channel, uint8 value) {
-	uint8 value2 = *dataptr++;
+int AdLibDriver::update_changeRhythmLevel1(Channel &channel, const uint8 *values) {
+	uint8 ops = values[0], v = values[1];
 
-	if (value & 1) {
-		_opExtraLevel1HH = checkValue(value2 + _opLevelHH + _opExtraLevel1HH + _opExtraLevel2HH);
+	if (ops & 1) {
+		_opExtraLevel1HH = checkValue(v + _opLevelHH + _opExtraLevel1HH + _opExtraLevel2HH);
 
 		// Channel 7, op1: Level Key Scaling / Total Level
 		writeOPL(0x51, _opExtraLevel1HH);
 	}
 
-	if (value & 2) {
-		_opExtraLevel1CY = checkValue(value2 + _opLevelCY + _opExtraLevel1CY + _opExtraLevel2CY);
+	if (ops & 2) {
+		_opExtraLevel1CY = checkValue(v + _opLevelCY + _opExtraLevel1CY + _opExtraLevel2CY);
 
 		// Channel 8, op2: Level Key Scaling / Total Level
 		writeOPL(0x55, _opExtraLevel1CY);
 	}
 
-	if (value & 4) {
-		_opExtraLevel1TT = checkValue(value2 + _opLevelTT + _opExtraLevel1TT + _opExtraLevel2TT);
+	if (ops & 4) {
+		_opExtraLevel1TT = checkValue(v + _opLevelTT + _opExtraLevel1TT + _opExtraLevel2TT);
 
 		// Channel 8, op1: Level Key Scaling / Total Level
 		writeOPL(0x52, _opExtraLevel1TT);
 	}
 
-	if (value & 8) {
-		_opExtraLevel1SD = checkValue(value2 + _opLevelSD + _opExtraLevel1SD + _opExtraLevel2SD);
+	if (ops & 8) {
+		_opExtraLevel1SD = checkValue(v + _opLevelSD + _opExtraLevel1SD + _opExtraLevel2SD);
 
 		// Channel 7, op2: Level Key Scaling / Total Level
 		writeOPL(0x54, _opExtraLevel1SD);
 	}
 
-	if (value & 16) {
-		_opExtraLevel1BD = checkValue(value2 + _opLevelBD + _opExtraLevel1BD + _opExtraLevel2BD);
+	if (ops & 16) {
+		_opExtraLevel1BD = checkValue(v + _opLevelBD + _opExtraLevel1BD + _opExtraLevel2BD);
 
 		// Channel 6, op2: Level Key Scaling / Total Level
 		writeOPL(0x53, _opExtraLevel1BD);
@@ -2007,60 +2007,60 @@ int AdLibDriver::update_changeRhythmLevel1(const uint8 *&dataptr, Channel &chann
 	return 0;
 }
 
-int AdLibDriver::update_setRhythmLevel1(const uint8 *&dataptr, Channel &channel, uint8 value) {
-	uint8 value2 = *dataptr++;
+int AdLibDriver::update_setRhythmLevel1(Channel &channel, const uint8 *values) {
+	uint8 ops = values[0], v = values[1];
 
-	if (value & 1) {
-		_opExtraLevel1HH = value2;
+	if (ops & 1) {
+		_opExtraLevel1HH = v;
 
 		// Channel 7, op1: Level Key Scaling / Total Level
-		writeOPL(0x51, checkValue(value2 + _opLevelHH + _opExtraLevel2HH));
+		writeOPL(0x51, checkValue(v + _opLevelHH + _opExtraLevel2HH));
 	}
 
-	if (value & 2) {
-		_opExtraLevel1CY = value2;
+	if (ops & 2) {
+		_opExtraLevel1CY = v;
 
 		// Channel 8, op2: Level Key Scaling / Total Level
-		writeOPL(0x55, checkValue(value2 + _opLevelCY + _opExtraLevel2CY));
+		writeOPL(0x55, checkValue(v + _opLevelCY + _opExtraLevel2CY));
 	}
 
-	if (value & 4) {
-		_opExtraLevel1TT = value2;
+	if (ops & 4) {
+		_opExtraLevel1TT = v;
 
 		// Channel 8, op1: Level Key Scaling / Total Level
-		writeOPL(0x52, checkValue(value2 + _opLevelTT + _opExtraLevel2TT));
+		writeOPL(0x52, checkValue(v + _opLevelTT + _opExtraLevel2TT));
 	}
 
-	if (value & 8) {
-		_opExtraLevel1SD = value2;
+	if (ops & 8) {
+		_opExtraLevel1SD = v;
 
 		// Channel 7, op2: Level Key Scaling / Total Level
-		writeOPL(0x54, checkValue(value2 + _opLevelSD + _opExtraLevel2SD));
+		writeOPL(0x54, checkValue(v + _opLevelSD + _opExtraLevel2SD));
 	}
 
-	if (value & 16) {
-		_opExtraLevel1BD = value2;
+	if (ops & 16) {
+		_opExtraLevel1BD = v;
 
 		// Channel 6, op2: Level Key Scaling / Total Level
-		writeOPL(0x53, checkValue(value2 + _opLevelBD + _opExtraLevel2BD));
+		writeOPL(0x53, checkValue(v + _opLevelBD + _opExtraLevel2BD));
 	}
 
 	return 0;
 }
 
-int AdLibDriver::update_setSoundTrigger(const uint8 *&dataptr, Channel &channel, uint8 value) {
-	_soundTrigger = value;
+int AdLibDriver::update_setSoundTrigger(Channel &channel, const uint8 *values) {
+	_soundTrigger = values[0];
 	return 0;
 }
 
-int AdLibDriver::update_setTempoReset(const uint8 *&dataptr, Channel &channel, uint8 value) {
-	channel.tempoReset = value;
+int AdLibDriver::update_setTempoReset(Channel &channel, const uint8 *values) {
+	channel.tempoReset = values[0];
 	return 0;
 }
 
-int AdLibDriver::updateCallback56(const uint8 *&dataptr, Channel &channel, uint8 value) {
-	channel.unk39 = value;
-	channel.unk40 = *dataptr++;
+int AdLibDriver::updateCallback56(Channel &channel, const uint8 *values) {
+	channel.unk39 = values[0];
+	channel.unk40 = values[1];
 	return 0;
 }
 




More information about the Scummvm-git-logs mailing list