[Scummvm-cvs-logs] SF.net SVN: scummvm: [32930] scummvm/trunk

eriktorbjorn at users.sourceforge.net eriktorbjorn at users.sourceforge.net
Sun Jul 6 20:37:52 CEST 2008


Revision: 32930
          http://scummvm.svn.sourceforge.net/scummvm/?rev=32930&view=rev
Author:   eriktorbjorn
Date:     2008-07-06 11:37:52 -0700 (Sun, 06 Jul 2008)

Log Message:
-----------
Implemented Good Enough(TM) XMIDI looping. This is used by Kyrandia 2 (the
loop hack is no longer needed, and has been removed), and will be used by
Discworld.

Modified Paths:
--------------
    scummvm/trunk/engines/kyra/sound.cpp
    scummvm/trunk/sound/midiparser_xmidi.cpp

Modified: scummvm/trunk/engines/kyra/sound.cpp
===================================================================
--- scummvm/trunk/engines/kyra/sound.cpp	2008-07-06 17:33:37 UTC (rev 32929)
+++ scummvm/trunk/engines/kyra/sound.cpp	2008-07-06 18:37:52 UTC (rev 32930)
@@ -249,21 +249,6 @@
 }
 
 void SoundMidiPC::send(uint32 b) {
-	// HACK: For Kyrandia, we make the simplifying assumption that a song
-	// either loops in its entirety, or not at all. So if we see a FOR_LOOP
-	// controller event, we turn on looping even if there isn't any
-	// corresponding NEXT_BREAK event.
-	//
-	// This is a gross over-simplification of how XMIDI handles loops. If
-	// anyone feels like doing a proper implementation, please refer to
-	// the Exult project, and do it in midiparser_xmidi.cpp
-
-	if ((b & 0xFFF0) == 0x74B0 && _eventFromMusic) {
-		debugC(9, kDebugLevelMain | kDebugLevelSound, "SoundMidiPC: Looping song");
-		_musicParser->property(MidiParser::mpAutoLoop, true);
-		return;
-	}
-
 	if (_passThrough) {
 		if ((b & 0xFFF0) == 0x007BB0)
 			return;

Modified: scummvm/trunk/sound/midiparser_xmidi.cpp
===================================================================
--- scummvm/trunk/sound/midiparser_xmidi.cpp	2008-07-06 17:33:37 UTC (rev 32929)
+++ scummvm/trunk/sound/midiparser_xmidi.cpp	2008-07-06 18:37:52 UTC (rev 32930)
@@ -38,6 +38,14 @@
 	NoteTimer _notes_cache[32];
 	uint32 _inserted_delta; // Track simulated deltas for note-off events
 
+	struct Loop {
+		byte *pos;
+		byte repeat;
+	};
+
+	Loop _loop[4];
+	int _loopCount;
+
 protected:
 	uint32 readVLQ2(byte * &data);
 	void resetTracking();
@@ -83,11 +91,51 @@
 		info.basic.param2 = 0;
 		break;
 
-	case 0x8: case 0xA: case 0xB: case 0xE:
+	case 0xB:
 		info.basic.param1 = *(_position._play_pos++);
 		info.basic.param2 = *(_position._play_pos++);
+
+		// Simplified XMIDI looping.
+		//
+		// I would really like to turn the loop events into some sort
+		// of NOP event (perhaps a dummy META event?), but for now we
+		// just pass them on to the MIDI driver. That has worked in the
+		// past, so it shouldn't cause any actual damage...
+
+		if (info.basic.param1 == 0x74) {
+			// XMIDI_CONTROLLER_FOR_LOOP
+			byte *pos = _position._play_pos - 3;
+			if (_loopCount < 0 || _loop[_loopCount].pos != pos) {
+				if (_loopCount < ARRAYSIZE(_loop) - 1)
+					_loopCount++;
+
+				_loop[_loopCount].pos = pos;
+				_loop[_loopCount].repeat = info.basic.param2;
+			}
+		} else if (info.basic.param1 == 0x75) {
+			// XMIDI_CONTROLLER_NEXT_BREAK
+			if (_loopCount >= 0) {
+				if (info.basic.param2 < 64) {
+					_loopCount--;
+				}
+
+				if (_loopCount >= 0) {
+					_position._play_pos = _loop[_loopCount].pos;
+					// Repeat 0 means "loop forever".
+					if (_loop[_loopCount].repeat) {
+						if (--_loop[_loopCount].repeat == 0)
+							_loopCount--;
+					}
+				}
+			}
+		}
 		break;
 
+	case 0x8: case 0xA: case 0xE:
+		info.basic.param1 = *(_position._play_pos++);
+		info.basic.param2 = *(_position._play_pos++);
+		break;
+
 	case 0xF: // Meta or SysEx event
 		switch (info.event & 0x0F) {
 		case 0x2: // Song Position Pointer
@@ -136,6 +184,8 @@
 	uint32 chunk_len;
 	char buf[32];
 
+	_loopCount = -1;
+
 	unloadMusic();
 	byte *pos = data;
 


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