[Scummvm-cvs-logs] SF.net SVN: scummvm:[50073] scummvm/trunk/engines/sci/sound

m_kiewitz at users.sourceforge.net m_kiewitz at users.sourceforge.net
Sun Jun 20 12:25:47 CEST 2010


Revision: 50073
          http://scummvm.svn.sourceforge.net/scummvm/?rev=50073&view=rev
Author:   m_kiewitz
Date:     2010-06-20 10:25:46 +0000 (Sun, 20 Jun 2010)

Log Message:
-----------
SCI: storing all manual midi commands now and actually sending them to driver during onTimer() - fixes mt32 emulation crashing during lsl5 piano scene

Modified Paths:
--------------
    scummvm/trunk/engines/sci/sound/midiparser_sci.cpp
    scummvm/trunk/engines/sci/sound/midiparser_sci.h
    scummvm/trunk/engines/sci/sound/music.cpp

Modified: scummvm/trunk/engines/sci/sound/midiparser_sci.cpp
===================================================================
--- scummvm/trunk/engines/sci/sound/midiparser_sci.cpp	2010-06-20 09:51:11 UTC (rev 50072)
+++ scummvm/trunk/engines/sci/sound/midiparser_sci.cpp	2010-06-20 10:25:46 UTC (rev 50073)
@@ -61,6 +61,8 @@
 	_dataincToAdd = 0;
 	_resetOnPause = false;
 	_pSnd = 0;
+
+	_manualCommandCount = 0;
 }
 
 MidiParser_SCI::~MidiParser_SCI() {
@@ -105,7 +107,7 @@
 				byte voiceCount = 0;
 				if (_channelUsed[i]) {
 					voiceCount = _pSnd->soundRes->getInitialVoiceCount(i);
-					_driver->send(0xB0 | i, 0x4B, voiceCount);
+					sendToDriverQueue(0xB0 | i, 0x4B, voiceCount);
 				}
 			}
 		}
@@ -113,8 +115,7 @@
 
 	// Send a velocity off signal to all channels
 	for (int i = 0; i < 15; ++i) {
-		if (_channelUsed[i])
-			sendToDriver(0xB0 | i, 0x4E, 0);	// Reset velocity
+		sendToDriverQueue(0xB0 | i, 0x4E, 0);	// Reset velocity
 	}
 }
 
@@ -145,19 +146,35 @@
 }
 
 // this is used for scripts sending direct midi commands to us. we verify in that case that the channel is actually
-//  used
-void MidiParser_SCI::sendManuallyToDriver(uint32 b) {
+//  used and actually store the command for getting really sent when being onTimer()
+void MidiParser_SCI::sendToDriverQueue(uint32 b) {
 	byte midiChannel = b & 0xf;
 
 	if (!_channelUsed[midiChannel]) {
-		// scripts trying to send to unused channel
-		//  this happens at least in sq1vga right at the start, it's a script issue
+		// trying to send to an unused channel
+		//  this happens for cmdSendMidi at least in sq1vga right at the start, it's a script issue
 		return;
 	}
 
-	sendToDriver(b);
+	if (_manualCommandCount >= 200)
+		error("driver queue is full");
+	_manualCommands[_manualCommandCount] = b;
+	_manualCommandCount++;
 }
 
+// This sends the stored commands from queue to driver (is supposed to get called only during onTimer())
+//  at least mt32 emulation doesn't like getting note-on commands from main thread (if we directly send, we would get
+//  a crash during piano scene in lsl5)
+void MidiParser_SCI::sendQueueToDriver() {
+	int curCommand = 0;
+
+	while (curCommand < _manualCommandCount) {
+		sendToDriver(_manualCommands[curCommand]);
+		curCommand++;
+	}
+	_manualCommandCount = 0;
+}
+
 void MidiParser_SCI::sendToDriver(uint32 b) {
 	byte midiChannel = b & 0xf;
 
@@ -375,9 +392,8 @@
 	// Turn off all active notes
 	for (i = 0; i < 128; ++i) {
 		for (j = 0; j < 16; ++j) {
-			int16 realChannel = _channelRemap[j];
-			if ((_active_notes[i] & (1 << j)) && realChannel != -1){
-				_driver->send(0x80 | realChannel, i, 0);
+			if ((_active_notes[i] & (1 << j))){
+				sendToDriverQueue(0x80 | j, i, 0);
 			}
 		}
 	}
@@ -385,7 +401,7 @@
 	// Turn off all hanging notes
 	for (i = 0; i < ARRAYSIZE(_hanging_notes); i++) {
 		if (_hanging_notes[i].time_left) {
-			_driver->send(0x80 | _hanging_notes[i].channel, _hanging_notes[i].note, 0);
+			sendToDriverQueue(0x80 | _hanging_notes[i].channel, _hanging_notes[i].note, 0);
 			_hanging_notes[i].time_left = 0;
 		}
 	}
@@ -394,11 +410,8 @@
 	// To be sure, send an "All Note Off" event (but not all MIDI devices
 	// support this...).
 
-	for (i = 0; i < 16; ++i) {
-		int16 realChannel = _channelRemap[i];
-		if (realChannel != -1)
-			_driver->send(0xB0 | realChannel, 0x7b, 0); // All notes off
-	}
+	for (i = 0; i < 16; ++i)
+		sendToDriverQueue(0xB0 | i, 0x7b, 0); // All notes off
 
 	memset(_active_notes, 0, sizeof(_active_notes));
 }
@@ -659,8 +672,7 @@
 		case SCI_VERSION_1_LATE:
 			// sending volume change to all used channels
 			for (int i = 0; i < 15; i++)
-				if (_channelUsed[i])
-					sendToDriver(0xB0 + i, 7, _volume);
+				sendToDriverQueue(0xB0 + i, 7, _volume);
 			break;
 
 		default:

Modified: scummvm/trunk/engines/sci/sound/midiparser_sci.h
===================================================================
--- scummvm/trunk/engines/sci/sound/midiparser_sci.h	2010-06-20 09:51:11 UTC (rev 50072)
+++ scummvm/trunk/engines/sci/sound/midiparser_sci.h	2010-06-20 10:25:46 UTC (rev 50073)
@@ -81,8 +81,13 @@
 	void sendToDriver(byte status, byte firstOp, byte secondOp) {
 		sendToDriver(status | ((uint32)firstOp << 8) | ((uint32)secondOp << 16));
 	}
-	void sendManuallyToDriver(uint32 b);
+	void sendToDriverQueue(uint32 b);
+	void sendToDriverQueue(byte status, byte firstOp, byte secondOp) {
+		sendToDriverQueue(status | ((uint32)firstOp << 8) | ((uint32)secondOp << 16));
+	}
 
+	void sendQueueToDriver();
+
 protected:
 	void parseNextEvent(EventInfo &info);
 	byte *midiMixChannels();
@@ -107,6 +112,9 @@
 	bool _channelUsed[16];
 	int16 _channelRemap[16];
 	bool _channelMuted[16];
+
+	int _manualCommandCount;
+	uint32 _manualCommands[200];
 };
 
 } // End of namespace Sci

Modified: scummvm/trunk/engines/sci/sound/music.cpp
===================================================================
--- scummvm/trunk/engines/sci/sound/music.cpp	2010-06-20 09:51:11 UTC (rev 50072)
+++ scummvm/trunk/engines/sci/sound/music.cpp	2010-06-20 10:25:46 UTC (rev 50073)
@@ -465,7 +465,7 @@
 void SciMusic::sendMidiCommand(MusicEntry *pSnd, uint32 cmd) {
 	Common::StackLock lock(_mutex);
 	if (pSnd->pMidiParser)
-		pSnd->pMidiParser->sendManuallyToDriver(cmd);
+		pSnd->pMidiParser->sendToDriverQueue(cmd);
 	else
 		error("tried to cmdSendMidi on non midi slot (%04x:%04x)", PRINT_REG(pSnd->soundObj));
 }
@@ -573,6 +573,8 @@
 
 	// Only process MIDI streams in this thread, not digital sound effects
 	if (pMidiParser) {
+		// Process manual commands first
+		pMidiParser->sendQueueToDriver();
 		pMidiParser->onTimer();
 		ticker = (uint16)pMidiParser->getTick();
 	}


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




More information about the Scummvm-git-logs mailing list