[Scummvm-git-logs] scummvm master -> 4077a9d82d327972a98c592c87da7d41de1a9972

athrxx noreply at scummvm.org
Tue Jun 13 22:40:28 UTC 2023


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

Summary:
e8d21cf93a KYRA: avoid possible nullptr deref
4077a9d82d KYRA: (EOB II/PC98) - sound improvements


Commit: e8d21cf93aa4b616d177535e5e30da60c7e04299
    https://github.com/scummvm/scummvm/commit/e8d21cf93aa4b616d177535e5e30da60c7e04299
Author: athrxx (athrxx at scummvm.org)
Date: 2023-06-14T00:38:51+02:00

Commit Message:
KYRA: avoid possible nullptr deref

Changed paths:
    engines/kyra/graphics/screen_eob.cpp


diff --git a/engines/kyra/graphics/screen_eob.cpp b/engines/kyra/graphics/screen_eob.cpp
index 1cd3c6748ad..25b8fdaf4bd 100644
--- a/engines/kyra/graphics/screen_eob.cpp
+++ b/engines/kyra/graphics/screen_eob.cpp
@@ -208,11 +208,12 @@ void Screen_EoB::setClearScreenDim(int dim) {
 
 void Screen_EoB::clearCurDim() {
 	static const uint8 amigaColorMap[16] = { 0x00, 0x06, 0x1d, 0x1b, 0x1a, 0x17, 0x18, 0x0e, 0x19, 0x1c, 0x1c, 0x1e, 0x13, 0x0a, 0x11, 0x1f };
-	fillRect(_curDim->sx << 3, _curDim->sy, ((_curDim->sx + _curDim->w) << 3) - 1, (_curDim->sy + _curDim->h) - 1, _isAmiga ? amigaColorMap[_curDim->col2] : _use16ColorMode ? 0 : _curDim->col2);
+	if (_curDim)
+		fillRect(_curDim->sx << 3, _curDim->sy, ((_curDim->sx + _curDim->w) << 3) - 1, (_curDim->sy + _curDim->h) - 1, _isAmiga ? amigaColorMap[_curDim->col2] : _use16ColorMode ? 0 : _curDim->col2);
 }
 
 void Screen_EoB::clearCurDimOvl(int pageNum) {
-	if (pageNum > 1 || !_useOverlays)
+	if (pageNum > 1 || !_useOverlays || !_curDim)
 		return;
 	addDirtyRect(_curDim->sx << 3, _curDim->sy, _curDim->w << 3, _curDim->h);
 	clearOverlayRect(pageNum, _curDim->sx << 3, _curDim->sy, _curDim->w << 3, _curDim->h);


Commit: 4077a9d82d327972a98c592c87da7d41de1a9972
    https://github.com/scummvm/scummvm/commit/4077a9d82d327972a98c592c87da7d41de1a9972
Author: athrxx (athrxx at scummvm.org)
Date: 2023-06-14T00:38:58+02:00

Commit Message:
KYRA: (EOB II/PC98) - sound improvements

Changed paths:
    engines/kyra/engine/chargen.cpp
    engines/kyra/sequence/sequences_darkmoon.cpp
    engines/kyra/sound/drivers/capcom98.cpp
    engines/kyra/sound/drivers/capcom98.h
    engines/kyra/sound/sound_intern.h
    engines/kyra/sound/sound_pc98_darkmoon.cpp


diff --git a/engines/kyra/engine/chargen.cpp b/engines/kyra/engine/chargen.cpp
index 3cd03201112..0d029b041d7 100644
--- a/engines/kyra/engine/chargen.cpp
+++ b/engines/kyra/engine/chargen.cpp
@@ -592,7 +592,7 @@ void CharacterGenerator::drawButton(int index, int buttonState) {
 
 	_screen->copyRegion(160, 0, c->destX << 3, c->destY, p->w << 3, p->h, 2, 0, Screen::CR_NO_P_CHECK);
 	_screen->updateScreen();
- }
+}
 
 void CharacterGenerator::processButtonClick(int index) {
 	drawButton(index, 1);
diff --git a/engines/kyra/sequence/sequences_darkmoon.cpp b/engines/kyra/sequence/sequences_darkmoon.cpp
index 93a604a900e..83a95b4064e 100644
--- a/engines/kyra/sequence/sequences_darkmoon.cpp
+++ b/engines/kyra/sequence/sequences_darkmoon.cpp
@@ -346,7 +346,7 @@ void DarkMoonEngine::seq_playIntro() {
 
 	sq.printText(3, textColor1);    // The message was urgent.
 
-	if (_flags.platform == Common::kPlatformPC98)
+	if (!skipFlag() && !shouldQuit() && _flags.platform == Common::kPlatformPC98)
 		snd_playSong(55);
 
 	sq.loadScene(1, 2);
@@ -447,7 +447,7 @@ void DarkMoonEngine::seq_playIntro() {
 
 	sq.animCommand(16);
 
-	if (_flags.platform == Common::kPlatformPC98)
+	if (!skipFlag() && !shouldQuit() && _flags.platform == Common::kPlatformPC98)
 		snd_playSong(56);
 
 	sq.printText(7, textColor2);    // Thank you for coming so quickly
@@ -594,7 +594,7 @@ void DarkMoonEngine::seq_playIntro() {
 	sq.animCommand(20);
 	sq.animCommand(18);
 
-	if (_flags.platform == Common::kPlatformPC98)
+	if (!skipFlag() && !shouldQuit() && _flags.platform == Common::kPlatformPC98)
 		snd_playSong(57);
 
 	sq.fadeText();
diff --git a/engines/kyra/sound/drivers/capcom98.cpp b/engines/kyra/sound/drivers/capcom98.cpp
index 5ac992da59b..e8de05ec2a3 100644
--- a/engines/kyra/sound/drivers/capcom98.cpp
+++ b/engines/kyra/sound/drivers/capcom98.cpp
@@ -40,7 +40,7 @@ public:
 		kSavedState	= 1 << 10
 	};
 
-	CapcomPC98Player(bool playerPrio, uint16 playerFlag, uint16 reservedChanFlags);
+	CapcomPC98Player(bool playerPrio, uint16 playFlags, uint16 chanReserveFlags, uint16 chanDisableFlags);
 	virtual ~CapcomPC98Player() {}
 
 	virtual bool init() = 0;
@@ -51,16 +51,21 @@ public:
 	void startSound(const uint8 *data, uint8 volume, bool loop);
 	void stopSound();
 	uint8 getMarker(uint8 id) const { return _soundMarkers[id & 0x0F]; }
-	static uint16 getPlayerStatus() { return _flags; }
 
+	static uint16 getStatus() { return _flags; }
+
+	void fadeOut(uint16 speed);
+	void allNotesOff(uint16 chanFlags = 0xFFFF);
 	virtual void setMasterVolume (int vol) = 0;
 
 	void nextTick();
-	virtual void processSounds() {}
+	virtual void processSounds() = 0;
 
 protected:
 	uint16 _soundMarkers[16];
-	const uint16 _reservedChanFlags;
+	uint8 _fadeState;
+	const uint16 _chanReserveFlags;
+	const uint16 _chanDisableFlags;
 
 private:
 	virtual void send(uint32 evt) = 0;
@@ -68,9 +73,9 @@ private:
 	void storeEvent(uint32 evt);
 	void restorePlayer();
 	virtual void restoreStateIntern() {}
-	uint16 playFlag() const { return _playerFlag & (kStdPlay | kPrioPlay); }
-	uint16 extraFlag() const { return _playerFlag & kPrioClaim; }
-	uint16 stopFlag() const { return (_playerFlag & (kStdPlay | kPrioPlay)) << 8; }
+	uint16 playFlag() const { return _playFlags & (kStdPlay | kPrioPlay); }
+	uint16 extraFlag() const { return _playFlags & kPrioClaim; }
+	uint16 stopFlag() const { return (_playFlags & (kStdPlay | kPrioPlay)) << 8; }
 
 	const uint8 *_data;
 	const uint8 *_curPos;
@@ -82,10 +87,13 @@ private:
 	static uint16 _flags;
 	bool _loop;
 
+	uint16 _fadeSpeed;
+	uint16 _fadeTicker;
+
 	Common::Array<uint32> _storedEvents;
 
 	const bool _playerPrio;
-	const uint16 _playerFlag;
+	const uint16 _playFlags;
 };
 
 class CapcomPC98_MIDI final : public CapcomPC98Player {
@@ -96,11 +104,13 @@ public:
 	~CapcomPC98_MIDI();
 
 	bool init() override;
-	void deinit() override;
+	void deinit() override {}
 	void reset() override;
 
 	void setMasterVolume (int vol) override;
 
+	void processSounds() override;
+
 private:
 	void send(uint32 evt) override;
 	PC98AudioCore::MutexLock lockMutex() override;
@@ -109,6 +119,8 @@ private:
 	const bool _isMT32;
 	const uint8 *_programMapping;
 
+	uint8 _chanVolume[16];
+
 	static const uint8 _programMapping_mt32ToGM[128];
 
 	MutexProc &_mproc;
@@ -116,7 +128,7 @@ private:
 
 class CapcomPC98_FM_Channel {
 public:
-	CapcomPC98_FM_Channel(uint8 id, PC98AudioCore *&ac, const Common::Array<const uint8*>&instruments);
+	CapcomPC98_FM_Channel(uint8 id, PC98AudioCore *&ac, const Common::Array<const uint8*>&instruments, const uint8 &fadeState);
 	~CapcomPC98_FM_Channel();
 
 	void reset();
@@ -203,10 +215,12 @@ private:
 	PC98AudioCore *&_ac;
 	const Common::Array<const uint8*>&_instruments;
 
+	const uint8 &_fadeState;
+
 	static const uint16 _freqMSBTable[12];
 	static const uint8 _freqLSBTables[12][64];
 	static const uint8 _volTablesInst[4][128];
-	static const uint8 _volTableOut[128];
+	static const uint8 _volTableCarrier[128];
 	static const uint8 _volTablePara[128];
 };
 
@@ -214,7 +228,7 @@ class CapcomPC98_FM final : public CapcomPC98Player, PC98AudioPluginDriver {
 public:
 	typedef Common::Functor0Mem<void, CapcomPC98AudioDriverInternal> CBProc;
 
-	CapcomPC98_FM(Audio::Mixer *mixer, CBProc &cbproc, bool playerPrio, uint16 playerFlag, uint8 reservedChanFlags, bool needsTimer);
+	CapcomPC98_FM(Audio::Mixer *mixer, CBProc &cbproc, bool playerPrio, uint16 playFlags, uint8 chanReserveFlags, uint8 chanDisableFlags, bool needsTimer);
 	~CapcomPC98_FM() override;
 
 	bool init() override;
@@ -228,7 +242,7 @@ public:
 
 private:
 	void send(uint32 evt) override;
-	void timerCallbackB() override;
+	void timerCallbackA() override;
 	void processSounds() override;
 
 	void controlChange(uint8 ch, uint8 control, uint8 val);
@@ -262,10 +276,14 @@ public:
 	void stopSong();
 	void startSoundEffect(const uint8 *data, uint8 volume);
 	void stopSoundEffect();
+
 	int checkSoundMarker() const;
 	bool songIsPlaying() const;
 	bool soundEffectIsPlaying() const;
 
+	void fadeOut();
+	void allNotesOff();
+
 	void setMusicVolume(int volume);
 	void setSoundEffectVolume(int volume);
 
@@ -292,7 +310,8 @@ private:
 
 uint16 CapcomPC98Player::_flags = 0;
 
-CapcomPC98Player::CapcomPC98Player(bool playerPrio, uint16 playerFlag, uint16 reservedChanFlags) : _playerPrio(playerPrio), _playerFlag(playerFlag), _reservedChanFlags(reservedChanFlags), _data(nullptr), _curPos(nullptr), _numEventsTotal(0), _numEventsLeft(0), _volume(0), _midiTicker(0), _loop(false) {
+CapcomPC98Player::CapcomPC98Player(bool playerPrio, uint16 playFlags, uint16 chanReserveFlags, uint16 chanDisableFlags) : _playerPrio(playerPrio), _playFlags(playFlags), _chanReserveFlags(chanReserveFlags), _chanDisableFlags(chanDisableFlags),
+	_data(nullptr), _curPos(nullptr), _numEventsTotal(0), _numEventsLeft(0), _volume(0), _midiTicker(0), _loop(false), _fadeState(0), _fadeSpeed(1), _fadeTicker(0) {
 	memset(_soundMarkers, 0, sizeof(_soundMarkers));
 	_flags = 0;
 }
@@ -303,15 +322,13 @@ void CapcomPC98Player::startSound(const uint8 *data, uint8 volume, bool loop) {
 	PC98AudioCore::MutexLock lock = lockMutex();
 	_numEventsTotal = _numEventsLeft = READ_LE_UINT16(data);
 	_data = _curPos = data + 2;
-	_volume = volume & 0x7f;
+	_volume = volume & 0x7F;
 	_loop = loop;
 	_midiTicker = 0;
 
-	if (_volume != 0x7f) {
-		for (int i = 0; i < 16; ++i) {
-			if ((1 << i) & _reservedChanFlags)
-				send(0x0007B0 | i | (_volume << 16));
-		}
+	for (int i = 0; i < 16; ++i) {
+		if ((1 << i) & _chanReserveFlags)
+			send(0x0007B0 | i | (_volume << 16));
 	}
 
 	_flags &= ~(stopFlag() | kFadeOut);
@@ -320,22 +337,50 @@ void CapcomPC98Player::startSound(const uint8 *data, uint8 volume, bool loop) {
 
 void CapcomPC98Player::stopSound() {
 	while (_flags & playFlag()) {
-		g_system->delayMillis(5);
+		g_system->delayMillis(4);
 		PC98AudioCore::MutexLock lock = lockMutex();
 		_flags |= stopFlag();
 	}
+	g_system->delayMillis(8);
+}
+
+void CapcomPC98Player::fadeOut(uint16 speed) {
+	if (speed) {
+		_fadeTicker =_fadeSpeed = speed;
+		_fadeState = 0;
+		_flags |= kFadeOut;
+	} else {
+		stopSound();
+	}
+}
+
+void CapcomPC98Player::allNotesOff(uint16 chanFlags) {
+	for (int i = 0; i < 16; ++i) {
+		if ((1 << i) & chanFlags)
+			send(0x007BB0 | i);
+	}
 }
 
 void CapcomPC98Player::nextTick() {
 	if (_flags & playFlag()) {
+		if (_flags & kFadeOut) {
+			if (_fadeTicker) {
+				--_fadeTicker;
+			} else {
+				_fadeTicker = _fadeSpeed;
+				if (++_fadeState == 100)
+					_flags |= stopFlag();
+			}
+		} else {
+			_fadeState = 0;
+			_fadeTicker = _fadeSpeed;
+		}
+
 		if (!_playerPrio) {
 			if (_flags & kPrioClaim) {
 				_flags &= ~kPrioClaim;
 				_flags |= kSavedState;
-				for (int i = 0; i < 16; ++i) {
-					if ((1 << i) & ~_reservedChanFlags)
-						send(0x007BB0 | i);
-				}
+				allNotesOff(~_chanReserveFlags);
 			} else if (((_flags & kPrioStop) || !(_flags & kPrioPlay)) && (_flags & kSavedState)) {
 				_flags &= ~kSavedState;
 				restorePlayer();
@@ -343,11 +388,10 @@ void CapcomPC98Player::nextTick() {
 		}
 
 		if (_flags & stopFlag()) {
-			for (int i = 0; i < 16; ++i) {
-				if ((1 << i) & _reservedChanFlags)
-					send(0x007BB0 | i);
-			}
+			allNotesOff((_playerPrio || (_flags & kPrioPlay)) ? _chanReserveFlags : 0xFFFF);
 			_flags &= ~playFlag();
+			if (!(_flags & (kStdPlay | kPrioPlay)))
+				_flags &= ~kFadeOut;
 
 		} else if (_numEventsLeft) {
 			bool eot = false;
@@ -360,12 +404,17 @@ void CapcomPC98Player::nextTick() {
 					break;
 
 				_midiTicker -= (in & 0xFF);
-				if (_playerPrio || !(_flags & kPrioPlay) || ((_flags & kPrioPlay) && ((1 << ((in >> 8) & 0x0f)) & _reservedChanFlags))) {
-					if (_volume == 0x7f || ((in >> 12) & 0xfff) != 0x70B)
-						send(in >> 8);
-				} else {
-					storeEvent(in >> 8);
+				uint8 chanFlag = 1 << ((in >> 8) & 0x0F);
+
+				if (!(chanFlag & _chanDisableFlags)) {
+					if (_playerPrio || !(_flags & kPrioPlay) || ((_flags & kPrioPlay) && (chanFlag & _chanReserveFlags))) {
+						if (_volume == 0x7F || ((in >> 12) & 0xFFF) != 0x07B)
+							send(in >> 8);
+					} else {
+						storeEvent(in >> 8);
+					}
 				}
+
 				_curPos += 4;
 				eot = (--_numEventsLeft == 0);
 			}
@@ -374,12 +423,8 @@ void CapcomPC98Player::nextTick() {
 				if (_loop) {
 					_numEventsLeft = _numEventsTotal;
 					_curPos = _data;
-				} else if (_playerPrio || !(_flags & kPrioPlay)) {
-					for (int i = 0; i < 16; ++i) {
-						if ((1 << i) & _reservedChanFlags)
-							send(0x007BB0 | i);
-					}
-
+				} else {
+					allNotesOff((_playerPrio || (_flags & kPrioPlay)) ? _chanReserveFlags : 0xFFFF);
 					_flags &= ~playFlag();
 				}
 			}
@@ -392,13 +437,13 @@ void CapcomPC98Player::nextTick() {
 }
 
 void CapcomPC98Player::storeEvent(uint32 evt) {
-	if ((1 << (evt & 0x0f)) & _reservedChanFlags)
+	if ((1 << (evt & 0x0F)) & _chanReserveFlags)
 		return;
 
-	uint8 st = evt & 0xff;
+	uint8 st = evt & 0xFF;
 
 	for (Common::Array<uint32>::iterator i = _storedEvents.begin(); i != _storedEvents.end(); ++i) {
-		if ((*i & 0xff) == st) {
+		if ((*i & 0xFF) == st) {
 			*i = evt;
 			return;
 		}
@@ -406,7 +451,7 @@ void CapcomPC98Player::storeEvent(uint32 evt) {
 
 	st >>= 4;
 
-	if (st == 0x0b || st == 0x0c || st == 0x0e)
+	if (st == 0x0B || st == 0x0C || st == 0x0E)
 		_storedEvents.push_back(evt);
 }
 
@@ -417,7 +462,7 @@ void CapcomPC98Player::restorePlayer() {
 	_storedEvents.clear();
 }
 
-CapcomPC98_MIDI::CapcomPC98_MIDI(MidiDriver::DeviceHandle dev, bool isMT32, MutexProc &mutexProc) : CapcomPC98Player(true, kStdPlay, 0xffff), _isMT32(isMT32), _mproc(mutexProc), _midi(nullptr), _programMapping(nullptr) {
+CapcomPC98_MIDI::CapcomPC98_MIDI(MidiDriver::DeviceHandle dev, bool isMT32, MutexProc &mutexProc) : CapcomPC98Player(true, kStdPlay, 0xFFFF, 0), _isMT32(isMT32), _mproc(mutexProc), _midi(nullptr), _programMapping(nullptr) {
 	_midi = MidiDriver::createMidi(dev);
 	uint8 *map = new uint8[128];
 	assert(map);
@@ -430,6 +475,7 @@ CapcomPC98_MIDI::CapcomPC98_MIDI(MidiDriver::DeviceHandle dev, bool isMT32, Mute
 	}
 
 	_programMapping = map;
+	memset(_chanVolume, 0, sizeof(_chanVolume));
 }
 
 CapcomPC98_MIDI::~CapcomPC98_MIDI() {
@@ -458,20 +504,25 @@ bool CapcomPC98_MIDI::init() {
 	return true;
 }
 
-void CapcomPC98_MIDI::deinit() {
-
-}
-
 void CapcomPC98_MIDI::reset() {
-
+	memset(_chanVolume, 0x7F, sizeof(_chanVolume));
 }
 
 void CapcomPC98_MIDI::send(uint32 evt) {
-	if ((evt & 0xF0) == 0xC0) {
-		evt = (evt & 0xFF) | (_programMapping[(evt >> 8) & 0xFF] << 8);
-	} else if ((evt & 0xF0) == 0xB0 && ((evt >> 8) & 0xFF) == 3) {
-		_soundMarkers[evt & 0x0F] = (evt >> 16) & 0xFF;
-		return;
+	uint8 cmd = evt & 0xF0;
+	uint8 ch = evt & 0x0F;
+	uint8 p1 = (evt >> 8) & 0xFF;
+	uint8 p2 = (evt >> 16) & 0xFF;
+
+	if (cmd == 0xC0) {
+		evt = (evt & 0xFF) | (_programMapping[p1] << 8);
+	} else if (cmd == 0xB0) {
+		if (p1 == 3) {
+			_soundMarkers[ch] = p2;
+			return;
+		} else if (((evt >> 8) & 0xFF) == 7) {
+			_chanVolume[ch] = p2;
+		}
 	}
 	_midi->send(evt);
 }
@@ -480,6 +531,13 @@ void CapcomPC98_MIDI::setMasterVolume (int vol) {
 
 }
 
+void CapcomPC98_MIDI::processSounds() {
+	if (_fadeState) {
+		for (int i = 0; i < 16; ++i)
+			_midi->send(0x0007B0 | i | (CLIP<int>(_chanVolume[i] - _fadeState, 0, 127) << 16));
+	}
+}
+
 PC98AudioCore::MutexLock CapcomPC98_MIDI::lockMutex() {
 	if (!_mproc.isValid())
 		error("CapcomPC98_MIDI::lockMutex(): Invalid call");
@@ -498,10 +556,10 @@ const uint8 CapcomPC98_MIDI::_programMapping_mt32ToGM[128] = {
 	0x70, 0x71, 0x72, 0x76, 0x75, 0x74, 0x73, 0x77, 0x78, 0x79, 0x7a, 0x7c, 0x7b, 0x7d, 0x7e, 0x7f
 };
 
-CapcomPC98_FM_Channel::CapcomPC98_FM_Channel(uint8 id, PC98AudioCore *&ac, const Common::Array<const uint8*>&instruments) : _regOffset(id), _ac(ac), _instruments(instruments),
+CapcomPC98_FM_Channel::CapcomPC98_FM_Channel(uint8 id, PC98AudioCore *&ac, const Common::Array<const uint8*>&instruments, const uint8 &fadeState) : _regOffset(id), _ac(ac), _instruments(instruments),
 	_isPlaying(false), _note(0), _carrier(0), _volume(0), _velocity(0), _noteEffCur(0), _program(0), _noteEffPrev(0), _breathControl(0), _frequency(0), _modWheel(0), _pitchBendSensitivity(0),
 	_pitchBendPara(0), _pitchBendEff(0), _vbrState(0), _vbrStep(0), _vbrCycleTicker(0), _vbrDelayTicker(0), _vbrHandler(nullptr), _prtEnable(false),
-	_prtTime(0), _prtState(0), _prtStep(0), _prtCycleLength(0) {
+	_prtTime(0), _prtState(0), _prtStep(0), _prtCycleLength(0), _fadeState(fadeState) {
 	typedef void (CapcomPC98_FM_Channel::*Proc)();
 	static const Proc procs[] = {
 		&CapcomPC98_FM_Channel::vbrHandler0,
@@ -533,7 +591,7 @@ CapcomPC98_FM_Channel::~CapcomPC98_FM_Channel() {
 
 void CapcomPC98_FM_Channel::reset() {
 	_vbrHandler = _vbrHandlers[4];
-	_frequency = 0xffff;
+	_frequency = 0xFFFF;
 	_vbrState = 0;
 	_prtState = 0;
 	_prtCycleLength = 0;
@@ -542,8 +600,8 @@ void CapcomPC98_FM_Channel::reset() {
 	_pitchBendEff = 0;
 	_pitchBendPara = 0;
 	_isPlaying = false;
-	_note = 0xff;
-	_volume = 0x7f;
+	_note = 0xFF;
+	_volume = 0x7F;
 	_velocity = _breathControl = 0x40;
 	_noteEffCur = 60;
 	_modWheel = 0;
@@ -580,10 +638,10 @@ void CapcomPC98_FM_Channel::noteOn(uint8 note, uint8 velo) {
 
 	if (!_isPlaying) {
 		updateVolume();
-		_ac->writeReg(0, 0x28, _regOffset | 0xf0);
+		_ac->writeReg(0, 0x28, _regOffset | 0xF0);
 	}
 
-	_isPlaying = true;	
+	_isPlaying = true;
 }
 
 void CapcomPC98_FM_Channel::programChange(uint8 prg) {
@@ -591,10 +649,9 @@ void CapcomPC98_FM_Channel::programChange(uint8 prg) {
 		return;
 
 	_program = prg;
-
 	loadInstrument(_instruments[prg]);
 
-	_ac->writeReg(0, 0xb0 + _regOffset, _instrument.fbl_alg);
+	_ac->writeReg(0, 0xB0 + _regOffset, _instrument.fbl_alg);
 
 	static const uint8 carriers[] = { 0x08, 0x08, 0x08, 0x08, 0x0C, 0x0E, 0x0E, 0x0F };
 	_carrier = carriers[_instrument.fbl_alg & 7];
@@ -620,6 +677,7 @@ void CapcomPC98_FM_Channel::pitchBend(uint16 pb) {
 
 void CapcomPC98_FM_Channel::restore() {
 	programChange(_program);
+	_frequency = 0xFFFF;
 }
 
 void CapcomPC98_FM_Channel::modWheel(uint8 mw) {
@@ -642,7 +700,8 @@ void CapcomPC98_FM_Channel::portamentoTime(uint8 pt) {
 
 void CapcomPC98_FM_Channel::volume(uint8 vol) {
 	_volume = vol;
-	updateVolume();
+	if (_isPlaying)
+		updateVolume();
 }
 
 void CapcomPC98_FM_Channel::togglePortamento(uint8 enable) {
@@ -652,8 +711,8 @@ void CapcomPC98_FM_Channel::togglePortamento(uint8 enable) {
 void CapcomPC98_FM_Channel::allNotesOff() {
 	_isPlaying = false;
 	for (int i = _regOffset; i < 16 + _regOffset; i += 4) {
-		_ac->writeReg(0, 0x40 + i, 0x7f);
-		_ac->writeReg(0, 0x80 + i, 0xff);
+		_ac->writeReg(0, 0x40 + i, 0x7F);
+		_ac->writeReg(0, 0x80 + i, 0xFF);
 	}
 	_ac->writeReg(0, 0x28, _regOffset);
 }
@@ -666,6 +725,9 @@ void CapcomPC98_FM_Channel::processSounds() {
 		(*_vbrHandler)();
 	updatePortamento();
 	updateFrequency();
+
+	if (_fadeState)
+		updateVolume();
 }
 
 void CapcomPC98_FM_Channel::loadInstrument(const uint8 *in) {
@@ -694,44 +756,50 @@ void CapcomPC98_FM_Channel::updatePitchBend() {
 
 void CapcomPC98_FM_Channel::updateVolume() {
 	uint8 cr = _carrier;
-
+	uint8 dbg[4];
 	const uint8 *s = _instrument.regData;
 	for (int i = _regOffset; i < 16 + _regOffset; i += 4) {
 		uint16 vol = 0;
 		if (cr & 1) {
-			vol += _volTableOut[_volume];
-			//vol += _fadeState;
+			vol += _volTableCarrier[_volume];
+			vol += _fadeState;
 		}
 
 		uint8 a = _breathControl;
 		uint8 b = s[10];
 		if (b & 0x80) {
-			a = ~a & 0x7f;
-			b &= 0x7f;
+			a = ~a & 0x7F;
+			b &= 0x7F;
 		}
-		vol += (((_volTablePara[a] * b) & 0x7fff) >> 7);
+		vol += (((_volTablePara[a] * b) & 0x7FFF) >> 7);
 
 		a = _velocity;
 		b = s[7];
 		if (b & 0x80) {
-			a = ~a & 0x7f;
-			b &= 0x7f;
+			a = ~a & 0x7F;
+			b &= 0x7F;
 		}
-		vol += (((_volTablePara[a] * b) & 0x7fff) >> 7);
+		vol += (((_volTablePara[a] * b) & 0x7FFF) >> 7);
 
 		a = _volTablesInst[s[8] & 3][_noteEffCur];
 		b = s[9];
 		if (b & 0x80) {
-			a = ~a & 0x7f;
-			b &= 0x7f;
+			a = ~a & 0x7F;
+			b &= 0x7F;
 		}
-		vol += (((a * b) & 0x7fff) >> 7);
+		vol += (((a * b) & 0x7FFF) >> 7);
 		vol += s[1];
-		vol = MIN<uint16>(vol, 0x7f);
 
-		_ac->writeReg(0, 0x40 + i, vol & 0xff);
+		if (vol > 0x7f)
+			vol=vol;
+
+		vol = MIN<uint16>(vol, 0x7F);
+
+		_ac->writeReg(0, 0x40 + i, vol & 0xFF);
 		s += 13;
 		cr >>= 1;
+
+		dbg[i >> 2] = vol & 0xff;
 	}
 }
 
@@ -746,21 +814,21 @@ void CapcomPC98_FM_Channel::updatePortamento() {
 
 void CapcomPC98_FM_Channel::updateFrequency() {
 	int16 tone = (MIN<int16>(_modWheel + _instrument.vbrSensitivity, 255) * (_vbrState >> 16)) >> 8;
-	tone = CLIP<int16>(tone + (_noteEffCur << 8), 0, 0x5fff);
-	tone = CLIP<int16>(tone + _pitchBendEff, 0, 0x5fff);
-	tone = CLIP<int16>(tone + (_prtState >> 16), 0, 0x5fff);
+	tone = CLIP<int16>(tone + (_noteEffCur << 8), 0, 0x5FFF);
+	tone = CLIP<int16>(tone + _pitchBendEff, 0, 0x5FFF);
+	tone = CLIP<int16>(tone + (_prtState >> 16), 0, 0x5FFF);
 
 	uint8 block = ((tone >> 8) / 12) & 7;
 	uint8 msb = (tone >> 8) % 12;
-	uint8 lsb = (tone & 0xff) >> 2;
+	uint8 lsb = (tone & 0xFF) >> 2;
 
 	uint16 freq = (block << 11) + _freqMSBTable[msb] + _freqLSBTables[msb][lsb];
 	if (_frequency == freq)
 		return;
 
 	_frequency = freq;
-	_ac->writeReg(0, 0xa4 + _regOffset, freq >> 8);
-	_ac->writeReg(0, 0xa0 + _regOffset, freq & 0xff);
+	_ac->writeReg(0, 0xA4 + _regOffset, freq >> 8);
+	_ac->writeReg(0, 0xA0 + _regOffset, freq & 0xFF);
 }
 
 void CapcomPC98_FM_Channel::setupPortamento() {
@@ -770,7 +838,7 @@ void CapcomPC98_FM_Channel::setupPortamento() {
 		return;
 	}
 
-	int16 diff = (_noteEffCur << 8) - CLIP<int16>((_prtState >> 16) | (_noteEffPrev << 8), 0, 0x5fff);
+	int16 diff = (_noteEffCur << 8) - CLIP<int16>((_prtState >> 16) | (_noteEffPrev << 8), 0, 0x5FFF);
 	_prtCycleLength = _prtTime;
 	_prtStep = (diff << 16) / _prtTime;
 	_prtState = (-diff << 16);
@@ -991,7 +1059,7 @@ const uint8 CapcomPC98_FM_Channel::_volTablesInst[4][128] = {
 	}
 };
 
-const uint8 CapcomPC98_FM_Channel::_volTableOut[] = {
+const uint8 CapcomPC98_FM_Channel::_volTableCarrier[] = {
 	0x2a, 0x2a, 0x29, 0x29, 0x29, 0x28, 0x28, 0x28, 0x27, 0x27, 0x27, 0x26, 0x26, 0x26, 0x25, 0x25,
 	0x25, 0x24, 0x24, 0x24, 0x23, 0x23, 0x23, 0x22, 0x22, 0x22, 0x21, 0x21, 0x21, 0x20, 0x20, 0x20,
 	0x1f, 0x1f, 0x1f, 0x1e, 0x1e, 0x1e, 0x1d, 0x1d, 0x1d, 0x1c, 0x1c, 0x1c, 0x1b, 0x1b, 0x1b, 0x1a,
@@ -1013,13 +1081,13 @@ const uint8 CapcomPC98_FM_Channel::_volTablePara[] = {
 	0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00
 };
 
-CapcomPC98_FM::CapcomPC98_FM(Audio::Mixer *mixer, CBProc &proc, bool playerPrio, uint16 playerFlag, uint8 reservedChanFlags, bool needsTimer) : CapcomPC98Player(playerPrio, playerFlag, reservedChanFlags), PC98AudioPluginDriver(), _cbProc(proc), _ac(nullptr), _chan(nullptr), _ready(false) {
+CapcomPC98_FM::CapcomPC98_FM(Audio::Mixer *mixer, CBProc &proc, bool playerPrio, uint16 playFlags, uint8 chanReserveFlags, uint8 chanDisableFlags, bool needsTimer) : CapcomPC98Player(playerPrio, playFlags, chanReserveFlags, chanDisableFlags), PC98AudioPluginDriver(), _cbProc(proc), _ac(nullptr), _chan(nullptr), _ready(false) {
 	_ac = new PC98AudioCore(mixer, needsTimer ? this : nullptr, kType26);
 	assert(_ac);
 	_chan = new CapcomPC98_FM_Channel*[3];
 	assert(_chan);
 	for (int i = 0; i < 3; ++i)
-		_chan[i] = new CapcomPC98_FM_Channel(i, _ac, _instruments);
+		_chan[i] = new CapcomPC98_FM_Channel(i, _ac, _instruments, _fadeState);
 }
 
 CapcomPC98_FM::~CapcomPC98_FM() {
@@ -1052,8 +1120,9 @@ bool CapcomPC98_FM::init() {
 	for (int i = 0; i < 3; ++i)
 		_ac->writeReg(0, 0xB0 + i, 0xC0);
 
-	_ac->writeReg(0, 0x26, 230);
-	_ac->writeReg(0, 0x27, 0x2a);
+	_ac->writeReg(0, 0x24, 0x91);
+	_ac->writeReg(0, 0x25, 0x00);
+	_ac->writeReg(0, 0x27, 0x15);
 
 	loadInstruments(_initData, 1);
 
@@ -1099,14 +1168,14 @@ PC98AudioCore::MutexLock CapcomPC98_FM::lockMutex() {
 }
 
 void CapcomPC98_FM::send(uint32 evt) {
-	uint8 ch = evt & 0x0f;
-	uint8 p1 = (evt >> 8) & 0xff;
-	uint8 p2 = (evt >> 16) & 0xff;
+	uint8 ch = evt & 0x0F;
+	uint8 p1 = (evt >> 8) & 0xFF;
+	uint8 p2 = (evt >> 16) & 0xFF;
 
 	if (ch > 2)
 		return;
 
-	switch (evt & 0xf0) {
+	switch (evt & 0xF0) {
 	case 0x80:
 		_chan[ch]->noteOff(p1);
 		break;
@@ -1116,14 +1185,14 @@ void CapcomPC98_FM::send(uint32 evt) {
 		else
 			_chan[ch]->noteOff(p1);
 		break;
-	case 0xb0:
+	case 0xB0:
 		controlChange(ch, p1, p2);
 		break;
-	case 0xc0:
+	case 0xC0:
 		_chan[ch]->programChange(p1);
 		break;
-	case 0xe0:
-		_chan[ch]->pitchBend(((p2 & 0x7f) << 7) | (p1 & 0x7f));
+	case 0xE0:
+		_chan[ch]->pitchBend(((p2 & 0x7F) << 7) | (p1 & 0x7F));
 		break;
 	default:
 		break;
@@ -1131,7 +1200,7 @@ void CapcomPC98_FM::send(uint32 evt) {
 }
 
 
-void CapcomPC98_FM::timerCallbackB() {
+void CapcomPC98_FM::timerCallbackA() {
 	if (_ready && _cbProc.isValid()) {
 		PC98AudioCore::MutexLock lock = _ac->stackLockMutex();
 		_cbProc();
@@ -1179,7 +1248,7 @@ void CapcomPC98_FM::controlChange(uint8 ch, uint8 control, uint8 val) {
 
 void CapcomPC98_FM::restoreStateIntern() {
 	for (int i = 0; i < 3; ++i) {
-		if ((1 << i) & _reservedChanFlags)
+		if ((1 << i) & _chanReserveFlags)
 			continue;
 		_chan[i]->restore();
 	}
@@ -1204,11 +1273,11 @@ CapcomPC98AudioDriverInternal::CapcomPC98AudioDriverInternal(Audio::Mixer *mixer
 
 	if (type == MT_MT32 || type == MT_GM) {
 		_players[0] = new CapcomPC98_MIDI(dev, type == MT_MT32, *_mutexProc);
-		_players[1] = _fmDevice = new CapcomPC98_FM(mixer, *_timerProc, true, CapcomPC98Player::kPrioPlay, 7, true);
+		_players[1] = _fmDevice = new CapcomPC98_FM(mixer, *_timerProc, true, CapcomPC98Player::kPrioPlay, 4, (uint8)~4, true);
 		_marker = 1;
 	} else {
-		_players[0] = new CapcomPC98_FM(mixer, *_timerProc, false, CapcomPC98Player::kStdPlay, 3, false);
-		_players[1] = _fmDevice = new CapcomPC98_FM(mixer, *_timerProc, true, CapcomPC98Player::kPrioPlay | CapcomPC98Player::kPrioClaim, 4, true);
+		_players[0] = new CapcomPC98_FM(mixer, *_timerProc, false, CapcomPC98Player::kStdPlay, 3, 0, false);
+		_players[1] = _fmDevice = new CapcomPC98_FM(mixer, *_timerProc, true, CapcomPC98Player::kPrioPlay | CapcomPC98Player::kPrioClaim, 4, (uint8)~4, true);
 	}
 
 	bool ready = true;
@@ -1293,11 +1362,25 @@ int CapcomPC98AudioDriverInternal::checkSoundMarker() const {
 }
 
 bool CapcomPC98AudioDriverInternal::songIsPlaying() const {
-	return CapcomPC98Player::getPlayerStatus() & CapcomPC98Player::kStdPlay;
+	return CapcomPC98Player::getStatus() & CapcomPC98Player::kStdPlay;
 }
 
 bool CapcomPC98AudioDriverInternal::soundEffectIsPlaying() const {
-	return CapcomPC98Player::getPlayerStatus() & CapcomPC98Player::kPrioPlay;
+	return CapcomPC98Player::getStatus() & CapcomPC98Player::kPrioPlay;
+}
+
+void CapcomPC98AudioDriverInternal::fadeOut() {
+	if (!_ready)
+		return;
+	for (int i = 0; i < 2; ++i)
+		_players[i]->fadeOut(1);
+}
+
+void CapcomPC98AudioDriverInternal::allNotesOff() {
+	if (!_ready)
+		return;
+	for (int i = 0; i < 2; ++i)
+		_players[i]->allNotesOff();
 }
 
 void CapcomPC98AudioDriverInternal::setMusicVolume(int volume) {
@@ -1384,6 +1467,16 @@ bool CapcomPC98AudioDriver::soundEffectIsPlaying() const {
 	return _drv ? _drv->soundEffectIsPlaying() : false;
 }
 
+void CapcomPC98AudioDriver::fadeOut() {
+	if (_drv)
+		_drv->fadeOut();
+}
+
+void CapcomPC98AudioDriver::allNotesOff() {
+	if (_drv)
+		_drv->allNotesOff();
+}
+
 void CapcomPC98AudioDriver::setMusicVolume(int volume) {
 	if (_drv)
 		_drv->setMusicVolume(volume);
diff --git a/engines/kyra/sound/drivers/capcom98.h b/engines/kyra/sound/drivers/capcom98.h
index 869f1ac0da3..95c8617d11d 100644
--- a/engines/kyra/sound/drivers/capcom98.h
+++ b/engines/kyra/sound/drivers/capcom98.h
@@ -49,10 +49,14 @@ public:
 	void stopSong();
 	void startSoundEffect(const uint8 *data, uint8 volume);
 	void stopSoundEffect();
+
 	int checkSoundMarker() const;
 	bool songIsPlaying() const;
 	bool soundEffectIsPlaying() const;
 
+	void fadeOut();
+	void allNotesOff();
+
 	void setMusicVolume(int volume);
 	void setSoundEffectVolume(int volume);
 
diff --git a/engines/kyra/sound/sound_intern.h b/engines/kyra/sound/sound_intern.h
index aa0dc70c679..f31cb36a69e 100644
--- a/engines/kyra/sound/sound_intern.h
+++ b/engines/kyra/sound/sound_intern.h
@@ -559,11 +559,12 @@ public:
 
 	void beginFadeOut() override;
 
+	void pause(bool paused) override;
+
 	void updateVolumeSettings() override;
 
 	int checkTrigger() override;
-
-	void resetTrigger() override;
+	void resetTrigger() override {} // This sound class is for EOB II only, this method is not needed there.
 
 private:
 	void restartBackgroundMusic();
diff --git a/engines/kyra/sound/sound_pc98_darkmoon.cpp b/engines/kyra/sound/sound_pc98_darkmoon.cpp
index 0b56e627d9f..1b70b0395e8 100644
--- a/engines/kyra/sound/sound_pc98_darkmoon.cpp
+++ b/engines/kyra/sound/sound_pc98_darkmoon.cpp
@@ -182,16 +182,16 @@ void SoundPC98_Darkmoon::stopAllSoundEffects() {
 }
 
 void SoundPC98_Darkmoon::beginFadeOut() {
-	haltTrack();
-	stopAllSoundEffects();
+	_driver->fadeOut();
 }
 
-int SoundPC98_Darkmoon::checkTrigger() {
-	return _driver ? _driver->checkSoundMarker() : 99;
+void SoundPC98_Darkmoon::pause(bool paused) {
+	if (_ready && paused)
+		_driver->allNotesOff();
 }
 
-void SoundPC98_Darkmoon::resetTrigger() {
-
+int SoundPC98_Darkmoon::checkTrigger() {
+	return _driver ? _driver->checkSoundMarker() : 99;
 }
 
 void SoundPC98_Darkmoon::restartBackgroundMusic() {




More information about the Scummvm-git-logs mailing list