[Scummvm-git-logs] scummvm master -> c5ab90d6e7bc3b00cb8d2bde8222e3cef8c4a4a3

athrxx noreply at scummvm.org
Fri Mar 15 20:20:08 UTC 2024


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

Summary:
c5ab90d6e7 SCUMM: (IMS) - improve parameter faders


Commit: c5ab90d6e7bc3b00cb8d2bde8222e3cef8c4a4a3
    https://github.com/scummvm/scummvm/commit/c5ab90d6e7bc3b00cb8d2bde8222e3cef8c4a4a3
Author: athrxx (athrxx at scummvm.org)
Date: 2024-03-15T21:19:01+01:00

Commit Message:
SCUMM: (IMS) - improve parameter faders

The volume and pitch faders should be fine, now.
I haven't fixed the speed fader, since the whole
handling of the speed setting would need to get
examined a bit closer. I think we're doing it wrong
(but maybe correctly for MI2/INDY4/DOTT?), but
this can be fixed separately...

Changed paths:
    audio/adlib.cpp
    audio/mididrv.h
    engines/scumm/imuse/drivers/amiga.cpp
    engines/scumm/imuse/drivers/fmtowns.cpp
    engines/scumm/imuse/drivers/mac_m68k.cpp
    engines/scumm/imuse/drivers/mac_m68k.h
    engines/scumm/imuse/drivers/midi.cpp
    engines/scumm/imuse/drivers/pcspk.cpp
    engines/scumm/imuse/drivers/pcspk.h
    engines/scumm/imuse/imuse.cpp
    engines/scumm/imuse/imuse_internal.h
    engines/scumm/imuse/imuse_part.cpp
    engines/scumm/imuse/imuse_player.cpp
    engines/scumm/saveload.cpp


diff --git a/audio/adlib.cpp b/audio/adlib.cpp
index 88500b0670a..533e8de882d 100644
--- a/audio/adlib.cpp
+++ b/audio/adlib.cpp
@@ -147,7 +147,7 @@ public:
 	void volume(byte value) override;
 	void panPosition(byte value) override;
 	void pitchBendFactor(byte value) override;
-	void detune(byte value) override;
+	void detune(int16 value) override;
 	void transpose(int8 value) override;
 	void priority(byte value) override;
 	void sustain(bool value) override;
@@ -180,7 +180,7 @@ public:
 	// Control Change messages
 	void modulationWheel(byte value) override { }
 	void pitchBendFactor(byte value) override { }
-	void detune(byte value) override { }
+	void detune(int16 value) override { }
 	void priority(byte value) override { }
 	void sustain(bool value) override { }
 
@@ -1212,7 +1212,7 @@ void AdLibPart::pitchBendFactor(byte value) {
 	}
 }
 
-void AdLibPart::detune(byte value) {
+void AdLibPart::detune(int16 value) {
 	// Sam&Max's OPL3 driver uses this for a completly different purpose. It
 	// is related to voice allocation. We ignore this for now.
 	// TODO: We probably need to look how the interpreter side of Sam&Max's
@@ -1227,7 +1227,7 @@ void AdLibPart::detune(byte value) {
 
 	AdLibVoice *voice;
 
-	_detuneEff = value;
+	_detuneEff = (int8)value;
 	for (voice = _voice; voice; voice = voice->_next) {
 		_owner->adlibNoteOn(voice->_channel, voice->_note + _transposeEff,
 							  (_pitchBend * _pitchBendFactor >> 6) + _detuneEff);
diff --git a/audio/mididrv.h b/audio/mididrv.h
index 8166f8dadb3..dd9981847cb 100644
--- a/audio/mididrv.h
+++ b/audio/mididrv.h
@@ -539,7 +539,7 @@ public:
 	virtual void panPosition(byte value) { controlChange(MidiDriver::MIDI_CONTROLLER_PANNING, value); }
 	virtual void pitchBendFactor(byte value) = 0;
 	virtual void transpose(int8 value) {}
-	virtual void detune(byte value) { controlChange(17, value); }
+	virtual void detune(int16 value) { controlChange(17, value & 0xff); }
 	virtual void priority(byte value) { }
 	virtual void sustain(bool value) { controlChange(MidiDriver::MIDI_CONTROLLER_SUSTAIN, value ? 1 : 0); }
 	virtual void effectLevel(byte value) { controlChange(MidiDriver::MIDI_CONTROLLER_REVERB, value); }
diff --git a/engines/scumm/imuse/drivers/amiga.cpp b/engines/scumm/imuse/drivers/amiga.cpp
index f335ecfb71e..015c8fa1d95 100644
--- a/engines/scumm/imuse/drivers/amiga.cpp
+++ b/engines/scumm/imuse/drivers/amiga.cpp
@@ -147,7 +147,7 @@ public:
 	void pitchBend(int16 bend) override;
 	void pitchBendFactor(byte value) override;
 	void transpose(int8 value) override;
-	void detune(uint8 value) override;
+	void detune(int16 value) override;
 
 	void priority(byte value) override;
 	void sysEx_customInstrument(uint32 type, const byte *instr, uint32 dataSize) override {}
@@ -574,7 +574,7 @@ void IMusePart_Amiga::transpose(int8 value) {
 		cur->transposePitchBend(_transpose, ((_pitchBend * _pitchBendSensitivity) >> 6) + _detune);
 }
 
-void IMusePart_Amiga::detune(uint8 value) {
+void IMusePart_Amiga::detune(int16 value) {
 	_detune = (int8)value;
 	for (SoundChannel_Amiga *cur = _out; cur; cur = cur->next())
 		cur->transposePitchBend(_transpose, ((_pitchBend * _pitchBendSensitivity) >> 6) + _detune);
diff --git a/engines/scumm/imuse/drivers/fmtowns.cpp b/engines/scumm/imuse/drivers/fmtowns.cpp
index 25062566980..fcfb9c5e8db 100644
--- a/engines/scumm/imuse/drivers/fmtowns.cpp
+++ b/engines/scumm/imuse/drivers/fmtowns.cpp
@@ -135,7 +135,7 @@ public:
 	void pitchBend(int16 bend) override;
 	void controlChange(byte control, byte value) override;
 	void pitchBendFactor(byte value) override;
-	void detune(byte value) override;
+	void detune(int16 value) override;
 	void transpose(int8 value) override;
 	void priority(byte value) override;
 	void sysEx_customInstrument(uint32 type, const byte *instr, uint32 dataSize) override;
@@ -771,8 +771,8 @@ void TownsMidiInputChannel::pitchBendFactor(byte value) {
 		oc->noteOnPitchBend(oc->_note + oc->_in->_transpose, _freqLSB);
 }
 
-void TownsMidiInputChannel::detune(byte value) {
-	_detune = value;
+void TownsMidiInputChannel::detune(int16 value) {
+	_detune = (int8)value;
 	_freqLSB = ((_pitchBend * _pitchBendFactor) >> 6) + _detune;
 	for (TownsMidiOutputChannel *oc = _out; oc; oc = oc->_next)
 		oc->noteOnPitchBend(oc->_note + oc->_in->_transpose, _freqLSB);
diff --git a/engines/scumm/imuse/drivers/mac_m68k.cpp b/engines/scumm/imuse/drivers/mac_m68k.cpp
index 1dbfbbb98e6..5f9fe34794f 100644
--- a/engines/scumm/imuse/drivers/mac_m68k.cpp
+++ b/engines/scumm/imuse/drivers/mac_m68k.cpp
@@ -426,7 +426,7 @@ void IMuseDriver_MacM68k::MidiChannel_MacM68k::transpose(int8 value) {
 	}
 }
 
-void IMuseDriver_MacM68k::MidiChannel_MacM68k::detune(uint8 value) {
+void IMuseDriver_MacM68k::MidiChannel_MacM68k::detune(int16 value) {
 	_detune = (int8)value;
 	for (VoiceChannel *i = _voice; i; i = i->next) {
 		_owner->setPitch(&i->out, ((i->note + _transpose) << 7) + ((_pitchBend * _pitchBendFactor) >> 6) + _detune);
diff --git a/engines/scumm/imuse/drivers/mac_m68k.h b/engines/scumm/imuse/drivers/mac_m68k.h
index 40fbe3e8420..8c7b665d7a6 100644
--- a/engines/scumm/imuse/drivers/mac_m68k.h
+++ b/engines/scumm/imuse/drivers/mac_m68k.h
@@ -152,7 +152,7 @@ private:
 		void controlChange(byte control, byte value) override;
 		void pitchBendFactor(byte value) override;
 		void transpose(int8 value) override;
-		void detune(byte value) override;
+		void detune(int16 value) override;
 		void priority(byte value) override;
 		void sysEx_customInstrument(uint32 type, const byte *instr, uint32 dataSize) override;
 
diff --git a/engines/scumm/imuse/drivers/midi.cpp b/engines/scumm/imuse/drivers/midi.cpp
index 7a3e802d378..fc038acd8dd 100644
--- a/engines/scumm/imuse/drivers/midi.cpp
+++ b/engines/scumm/imuse/drivers/midi.cpp
@@ -58,7 +58,7 @@ public:
 	// Control Change and SCUMM specific functions
 	void pitchBendFactor(byte value) override { pitchBend(0); _pitchBendSensitivity = value; }
 	void transpose(int8 value) override { _transpose = (int8)value; pitchBend(_pitchBendTemp); }
-	void detune(byte value) override { _detune = (int8)value; pitchBend(_pitchBendTemp); }
+	void detune(int16 value) override { _detune = (int16)value; pitchBend(_pitchBendTemp); }
 	void priority(byte value) override { _prio = value; }
 	void sustain(bool value) override;
 	void allNotesOff() override;
@@ -101,7 +101,7 @@ private:
 	byte _channelUsage;
 	bool _exhaust;
 	byte _prio;
-	int8 _detune;
+	int16 _detune;
 	int8 _transpose;
 	int16 _pitchBendTemp;
 	byte _pitchBendSensitivity;
diff --git a/engines/scumm/imuse/drivers/pcspk.cpp b/engines/scumm/imuse/drivers/pcspk.cpp
index 459c6514968..eed4eeffcda 100644
--- a/engines/scumm/imuse/drivers/pcspk.cpp
+++ b/engines/scumm/imuse/drivers/pcspk.cpp
@@ -340,7 +340,7 @@ void IMuseDriver_PCSpk::MidiChannel_PcSpk::transpose(int8 value) {
 	_pitchBend = (_transpose << 7) + ((_pitchBendTmp * _pitchBendFactor) >> 6) + _detune;
 }
 
-void IMuseDriver_PCSpk::MidiChannel_PcSpk::detune(byte value) {
+void IMuseDriver_PCSpk::MidiChannel_PcSpk::detune(int16 value) {
 	_detune = (int8)value;
 	_pitchBend = (_transpose << 7) + ((_pitchBendTmp * _pitchBendFactor) >> 6) + _detune;
 }
diff --git a/engines/scumm/imuse/drivers/pcspk.h b/engines/scumm/imuse/drivers/pcspk.h
index 64590a244cc..7d30bc337eb 100644
--- a/engines/scumm/imuse/drivers/pcspk.h
+++ b/engines/scumm/imuse/drivers/pcspk.h
@@ -117,7 +117,7 @@ private:
 		void controlChange(byte control, byte value) override;
 		void pitchBendFactor(byte value) override;
 		void transpose(int8 value) override;
-		void detune(byte value) override;
+		void detune(int16 value) override;
 		void priority(byte value) override;
 		void sysEx_customInstrument(uint32 type, const byte *instr, uint32 dataSize) override;
 
diff --git a/engines/scumm/imuse/imuse.cpp b/engines/scumm/imuse/imuse.cpp
index 2043794f82e..d6c4721baeb 100644
--- a/engines/scumm/imuse/imuse.cpp
+++ b/engines/scumm/imuse/imuse.cpp
@@ -853,14 +853,20 @@ int32 IMuseInternal::doCommand_internal(int numargs, int a[]) {
 			error("doCommand(%d [%d/%d], %d, %d, %d, %d, %d, %d, %d) unsupported", a[0], param, cmd, a[1], a[2], a[3], a[4], a[5], a[6], a[7]);
 		}
 	} else if (param == 1) {
+		Part *part = nullptr;
 		if ((1 << cmd) & 0x783FFF) {
 			player = findActivePlayer(a[1]);
 			if (!player)
 				return -1;
-			if ((1 << cmd) & (1 << 11 | 1 << 22)) {
+			if (_newSystem && cmd == 5) {
+				assert(a[3] >= 0 && a[3] <= 15);
+				part = player->getPart(a[2]);
+				if (!part)
+					return -1;
+			} else if (((1 << cmd) & (1 << 11 | 1 << 22))) {
 				assert(a[2] >= 0 && a[2] <= 15);
-				player = (Player *)player->getPart(a[2]);
-				if (!player)
+				part = player->getPart(a[2]);
+				if (!part)
 					return -1;
 			}
 		}
@@ -910,12 +916,20 @@ int32 IMuseInternal::doCommand_internal(int numargs, int a[]) {
 		case 2:
 			return player->setVolume(a[2]);
 		case 3:
-			player->setPan(a[2]);
+			if (_newSystem)
+				player->setSpeed(a[3]);
+			else
+				player->setPan(a[2]);
 			return 0;
 		case 4:
 			return player->setTranspose(a[2], a[3]);
 		case 5:
-			player->setDetune(a[2]);
+			if (_newSystem) {
+				assert(part);
+				part->volControlSensitivity(a[4]);
+			} else {
+				player->setDetune(a[2]);
+			}
 			return 0;
 		case 6:
 			// WORKAROUND for bug #2242. When playing the
@@ -946,7 +960,8 @@ int32 IMuseInternal::doCommand_internal(int numargs, int a[]) {
 			player->clearLoop();
 			return 0;
 		case 11:
-			((Part *)player)->set_onoff(a[3] != 0);
+			assert(part);
+			part->set_onoff(a[3] != 0);
 			return 0;
 		case 12:
 			return player->setHook(a[2], a[3], a[4]);
@@ -965,7 +980,8 @@ int32 IMuseInternal::doCommand_internal(int numargs, int a[]) {
 		case 21:
 			return -1;
 		case 22:
-			((Part *)player)->volume(a[3]);
+			assert(part);
+			part->volume(a[3]);
 			return 0;
 		case 23:
 			return query_queue(a[1]);
diff --git a/engines/scumm/imuse/imuse_internal.h b/engines/scumm/imuse/imuse_internal.h
index a3ccf89298c..1753f075bfb 100644
--- a/engines/scumm/imuse/imuse_internal.h
+++ b/engines/scumm/imuse/imuse_internal.h
@@ -124,12 +124,15 @@ struct ParameterFader {
 	};
 
 	int param;
-	int start;
-	int end;
-	uint32 total_time;
-	uint32 current_time;
-
-	ParameterFader() : param(0), start(0), end(0), total_time(0), current_time(0) {}
+	int8 dir;
+	int16 incr;
+	uint16 ifrac;
+	uint16 irem;
+	uint16 ttime;
+	uint16 cntdwn;
+	int16 state;
+
+	ParameterFader() : param(0), dir(0), incr(0), ifrac(0), irem(0), ttime(0), cntdwn(0), state(0) {}
 	void init() { param = 0; }
 };
 
@@ -196,7 +199,7 @@ protected:
 	byte _volume;
 	int8 _pan;
 	int8 _transpose;
-	int8 _detune;
+	int16 _detune;
 	int _note_offset;
 	byte _vol_eff;
 
@@ -209,6 +212,8 @@ protected:
 	byte _speed;
 	bool _abort;
 
+	uint32 _transitionTimer;
+
 	// This does not get used by us! It is only
 	// here for save/load purposes, and gets
 	// passed on to the MidiParser during
@@ -260,7 +265,7 @@ public:
 	void fixAfterLoad();
 	Part *getActivePart(uint8 part);
 	uint getBeatIndex();
-	int8 getDetune() const { return _detune; }
+	int16 getDetune() const { return _detune; }
 	byte getEffectiveVolume() const { return _vol_eff; }
 	int getID() const { return _id; }
 	MidiDriver *getMidiDriver() const { return _midi; }
@@ -319,7 +324,8 @@ struct Part : public Common::Serializable {
 	byte _volControlSensitivity;
 	int8 _transpose, _transpose_eff;
 	byte _vol, _vol_eff;
-	int8 _detune, _detune_eff;
+	int8 _detune;
+	int16 _detune_eff;
 	int8 _pan, _pan_eff;
 	byte _polyphony;
 	bool _on;
@@ -346,6 +352,7 @@ struct Part : public Common::Serializable {
 	void pitchBend(int16 value);
 	void modulationWheel(byte value);
 	void volume(byte value);
+	void volControlSensitivity(byte value);
 	void pitchBendFactor(byte value);
 	void sustain(bool value);
 	void effectLevel(byte value);
diff --git a/engines/scumm/imuse/imuse_part.cpp b/engines/scumm/imuse/imuse_part.cpp
index 7b4c2ca506d..a125fa375d2 100644
--- a/engines/scumm/imuse/imuse_part.cpp
+++ b/engines/scumm/imuse/imuse_part.cpp
@@ -105,15 +105,13 @@ void Part::saveLoadWithSerializer(Common::Serializer &ser) {
 	ser.syncAsByte(_chorus, VER(8));
 	ser.syncAsByte(_percussion, VER(8));
 	ser.syncAsByte(_bank, VER(8));
+	ser.syncAsByte(_polyphony, VER(116));
+	ser.syncAsByte(_volControlSensitivity, VER(116));
 }
 
 void Part::set_detune(int8 detune) {
-	// Sam&Max does not have detune, so we just ignore this here. We still get
-	// this called, since Sam&Max uses the same controller for a different
-	// purpose.
-	if (_se->_newSystem)
-		return;
-
+	// Sam&Max does not have detune except for the parameter faders, so the argument
+	// here will always be 0 and the only relevant part will be the detune from the player.
 	_detune_eff = clamp((_detune = detune) + _player->getDetune(), -128, 127);
 	sendDetune();
 }
@@ -128,6 +126,13 @@ void Part::volume(byte value) {
 	sendVolume(0);
 }
 
+void Part::volControlSensitivity(byte value) {
+	if (value > 127)
+		return;
+	_volControlSensitivity = value;
+	sendVolume(0);
+}
+
 void Part::set_pri(int8 pri) {
 	_pri_eff = clamp((_pri = pri) + _player->getPriority(), 0, 255);
 	if (_mc)
diff --git a/engines/scumm/imuse/imuse_player.cpp b/engines/scumm/imuse/imuse_player.cpp
index 045075435dd..c86d07a30c9 100644
--- a/engines/scumm/imuse/imuse_player.cpp
+++ b/engines/scumm/imuse/imuse_player.cpp
@@ -82,7 +82,8 @@ Player::Player() :
 	_vol_chan(0),
 	_abort(false),
 	_music_tick(0),
-	_parserType(kParserTypeNone) {
+	_parserType(kParserTypeNone),
+	_transitionTimer(0) {
 }
 
 Player::~Player() {
@@ -136,10 +137,8 @@ int Player::getMusicTimer() const {
 bool Player::isFadingOut() const {
 	int i;
 	for (i = 0; i < ARRAYSIZE(_parameterFaders); ++i) {
-		if (_parameterFaders[i].param == ParameterFader::pfVolume &&
-		        _parameterFaders[i].end == 0) {
+		if (_parameterFaders[i].param == ParameterFader::pfVolume && (_parameterFaders[i].incr || _parameterFaders[i].ifrac))
 			return true;
-		}
 	}
 	return false;
 }
@@ -913,41 +912,33 @@ void Player::onTimer() {
 	_parser->onTimer();
 }
 
-// "time" is referenced as hundredths of a second.
-// IS THAT CORRECT??
-// We convert it to microseconds before proceeding
 int Player::addParameterFader(int param, int target, int time) {
 	int start;
 
 	switch (param) {
 	case ParameterFader::pfVolume:
-		// HACK: If volume is set to 0 with 0 time,
-		// set it so immediately but DON'T clear
-		// the player. This fixes a problem with
-		// music being cleared inappropriately
-		// in S&M when playing with the Dinosaur.
-		if (!target && !time) {
-			setVolume(0);
+		if (!time) {
+			setVolume(target);
 			return 0;
 		}
-
-		// Volume fades are handled differently.
 		start = _volume;
 		break;
 
 	case ParameterFader::pfTranspose:
-		// FIXME: Is this transpose? And what's the scale?
 		// It's set to fade to -2400 in the tunnel of love.
-//		debug(0, "parameterTransition(3) outside Tunnel of Love?");
-		start = _transpose;
-//		target /= 200;
+		// debug(0, "parameterTransition(3) outside Tunnel of Love?");
+		if (!time) {
+			setDetune(target);
+			return 0;
+		}
+		start = _detune;
 		break;
 
 	case ParameterFader::pfSpeed: // impSpeed
 		// FIXME: Is the speed from 0-100?
 		// Right now I convert it to 0-128.
 		start = _speed;
-//		target = target * 128 / 100;
+		target = target * 128 / 100;
 		break;
 
 	case 127: {
@@ -971,7 +962,6 @@ int Player::addParameterFader(int param, int target, int time) {
 	for (i = ARRAYSIZE(_parameterFaders); i; --i, ++ptr) {
 		if (ptr->param == param) {
 			best = ptr;
-			start = ptr->end;
 			break;
 		} else if (!ptr->param) {
 			best = ptr;
@@ -980,13 +970,14 @@ int Player::addParameterFader(int param, int target, int time) {
 
 	if (best) {
 		best->param = param;
-		best->start = start;
-		best->end = target;
-		if (!time)
-			best->total_time = 1;
-		else
-			best->total_time = (uint32)time * 10000;
-		best->current_time = 0;
+		best->state = start;
+		best->ttime = best->cntdwn = time;
+		int diff = target - start;
+		best->dir = (diff >= 0) ? 1 : -1;
+		best->incr = diff / time;
+		best->ifrac = ABS<int>(diff) % time;
+		best->irem = 0;
+
 	} else {
 		debug(0, "IMuse Player %d: Out of parameter faders", _id);
 		return -1;
@@ -997,46 +988,62 @@ int Player::addParameterFader(int param, int target, int time) {
 
 void Player::transitionParameters() {
 	uint32 advance = _midi->getBaseTempo();
-	int value;
 
-	ParameterFader *ptr = &_parameterFaders[0];
-	int i;
-	for (i = ARRAYSIZE(_parameterFaders); i; --i, ++ptr) {
-		if (!ptr->param)
-			continue;
-
-		ptr->current_time += advance;
-		if (ptr->current_time > ptr->total_time)
-			ptr->current_time = ptr->total_time;
-		value = (int32)ptr->start + (int32)(ptr->end - ptr->start) * (int32)ptr->current_time / (int32)ptr->total_time;
-
-		switch (ptr->param) {
-		case ParameterFader::pfVolume:
-			// Volume.
-			if (!value && !ptr->end) {
-				clear();
-				return;
+	_transitionTimer += advance;
+	while (_transitionTimer >= 16667) {
+		_transitionTimer -= 16667;
+
+		ParameterFader *ptr = &_parameterFaders[0];
+		for (int i = ARRAYSIZE(_parameterFaders); i; --i, ++ptr) {
+			if (!ptr->param)
+				continue;
+
+			int32 mod = ptr->incr;
+			ptr->irem += ptr->ifrac;
+			if (ptr->irem >= ptr->ttime) {
+				ptr->irem -= ptr->ttime;
+				mod += ptr->dir;
+			}
+			if (!mod) {
+				if (!ptr->cntdwn || !--ptr->cntdwn)
+					ptr->param = 0;
+				continue;
 			}
-			setVolume((byte)value);
-			break;
 
-		case ParameterFader::pfTranspose:
-			// FIXME: Is this really transpose?
-			setTranspose(0, value / 100);
-			setDetune(value % 100);
-			break;
+			ptr->state += mod;
 
-		case ParameterFader::pfSpeed: // impSpeed:
-			// Speed.
-			setSpeed((byte)value);
-			break;
 
-		default:
-			ptr->param = 0;
-		}
+			switch (ptr->param) {
+			case ParameterFader::pfVolume:
+				// Volume
+				if (ptr->state >= 0 && ptr->state <= 127) {
+					setVolume((byte)ptr->state);
+					if (ptr->state == 0) {
+						clear();
+						return;
+					}
+				}
+				break;
 
-		if (ptr->current_time >= ptr->total_time)
-			ptr->param = 0;
+			case ParameterFader::pfTranspose:
+				if (ptr->state >= -9216 && ptr->state <= 9216)
+					setDetune(ptr->state);
+				break;
+
+			case ParameterFader::pfSpeed:
+				// Speed.
+				if (ptr->state >= 0 && ptr->state <= 127) {
+					setSpeed((byte)ptr->state);
+				}
+				break;
+
+			default:
+				ptr->param = 0;
+			}
+
+			if (!ptr->cntdwn || !--ptr->cntdwn)
+				ptr->param = 0;
+		}
 	}
 }
 
@@ -1085,10 +1092,34 @@ void Player::metaEvent(byte type, byte *msg, uint16 len) {
 
 static void syncWithSerializer(Common::Serializer &s, ParameterFader &pf) {
 	s.syncAsSint16LE(pf.param, VER(17));
-	s.syncAsSint16LE(pf.start, VER(17));
-	s.syncAsSint16LE(pf.end, VER(17));
-	s.syncAsUint32LE(pf.total_time, VER(17));
-	s.syncAsUint32LE(pf.current_time, VER(17));
+	if (s.isLoading() && s.getVersion() < 116) {
+		int16 start, end;
+		uint32 tt, ct;
+		s.syncAsSint16LE(start, VER(17));
+		s.syncAsSint16LE(end, VER(17));
+		s.syncAsUint32LE(tt, VER(17));
+		s.syncAsUint32LE(ct, VER(17));
+		int32 diff = end - start;
+		if (pf.param && diff && tt) {
+			pf.dir = diff / ABS<int>(diff);
+			pf.incr = diff / (tt / 10000);
+			pf.ifrac = ABS<int>(diff) % (tt / 10000);
+			pf.state = (int32)start + diff * (int32)ct / (int32)tt;
+		} else {
+			pf.param = 0;
+		}
+		pf.irem = 0;
+		pf.cntdwn = 0;
+		
+	} else {
+		s.syncAsSByte(pf.dir, VER(116));
+		s.syncAsSint16LE(pf.incr, VER(116));
+		s.syncAsUint16LE(pf.ifrac, VER(116));
+		s.syncAsUint16LE(pf.irem, VER(116));
+		s.syncAsUint16LE(pf.ttime, VER(116));
+		s.syncAsUint16LE(pf.cntdwn, VER(116));
+		s.syncAsSint16LE(pf.state, VER(116));
+	}
 }
 
 void Player::saveLoadWithSerializer(Common::Serializer &s) {
@@ -1114,7 +1145,8 @@ void Player::saveLoadWithSerializer(Common::Serializer &s) {
 	s.syncAsByte(_volume, VER(8));
 	s.syncAsSByte(_pan, VER(8));
 	s.syncAsByte(_transpose, VER(8));
-	s.syncAsSByte(_detune, VER(8));
+	s.syncAsSByte(_detune, VER(8), VER(115));
+	s.syncAsSint16LE(_detune, VER(116));
 	s.syncAsUint16LE(_vol_chan, VER(8));
 	s.syncAsByte(_vol_eff, VER(8));
 	s.syncAsByte(_speed, VER(8));
diff --git a/engines/scumm/saveload.cpp b/engines/scumm/saveload.cpp
index 1f26b094d48..1c3e38d3f43 100644
--- a/engines/scumm/saveload.cpp
+++ b/engines/scumm/saveload.cpp
@@ -69,7 +69,7 @@ struct SaveInfoSection {
 
 #define SaveInfoSectionSize (4+4+4 + 4+4 + 4+2)
 
-#define CURRENT_VER 115
+#define CURRENT_VER 116
 #define INFOSECTION_VERSION 2
 
 #pragma mark -




More information about the Scummvm-git-logs mailing list