aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTorbjörn Andersson2008-08-10 17:59:42 +0000
committerTorbjörn Andersson2008-08-10 17:59:42 +0000
commitd08c3ba66ba81a06ef681ea9a49334a80d296609 (patch)
treeb9f521c67cfbff94018135a23947e2224ba5da2a
parent327ae17095edb51b2df0ada8cd8eba28463c5127 (diff)
downloadscummvm-rg350-d08c3ba66ba81a06ef681ea9a49334a80d296609.tar.gz
scummvm-rg350-d08c3ba66ba81a06ef681ea9a49334a80d296609.tar.bz2
scummvm-rg350-d08c3ba66ba81a06ef681ea9a49334a80d296609.zip
Committed my patch #2040074 ("XMIDI callback control events"). At the moment, I'm
not aware of any game that actually uses this XMIDI feature, so its primary function right now is to silence lots of warnings while running the DOS version of Simon the Sorcerer 2. svn-id: r33763
-rw-r--r--engines/agos/midi.cpp6
-rw-r--r--sound/midiparser.h6
-rw-r--r--sound/midiparser_xmidi.cpp66
3 files changed, 55 insertions, 23 deletions
diff --git a/engines/agos/midi.cpp b/engines/agos/midi.cpp
index 3114b24549..891e9bde95 100644
--- a/engines/agos/midi.cpp
+++ b/engines/agos/midi.cpp
@@ -538,7 +538,11 @@ void MidiPlayer::loadXMIDI(Common::File *in, bool sfx) {
error("Expected 'FORM' tag but found '%c%c%c%c' instead", buf[0], buf[1], buf[2], buf[3]);
}
- MidiParser *parser = MidiParser::createParser_XMIDI();
+ // In the DOS version of Simon the Sorcerer 2, the music contains lots
+ // of XMIDI callback controller events. As far as we know, they aren't
+ // actually used, so we disable the callback handler explicitly.
+
+ MidiParser *parser = MidiParser::createParser_XMIDI(NULL);
parser->setMidiDriver(this);
parser->setTimerRate(_driver->getBaseTempo());
if (!parser->loadMusic(p->data, size))
diff --git a/sound/midiparser.h b/sound/midiparser.h
index d5209acb10..304a9d9f82 100644
--- a/sound/midiparser.h
+++ b/sound/midiparser.h
@@ -352,6 +352,8 @@ public:
};
public:
+ typedef void (*XMidiCallbackProc)(byte eventData, void *refCon);
+
MidiParser();
virtual ~MidiParser() { allNotesOff(); }
@@ -370,8 +372,10 @@ public:
uint32 getPPQN() { return _ppqn; }
virtual uint32 getTick() { return _position._play_tick; }
+ static void defaultXMidiCallback(byte eventData, void *refCon);
+
static MidiParser *createParser_SMF();
- static MidiParser *createParser_XMIDI();
+ static MidiParser *createParser_XMIDI(XMidiCallbackProc proc = defaultXMidiCallback, void *refCon = 0);
static void timerCallback(void *data) { ((MidiParser *) data)->onTimer(); }
};
diff --git a/sound/midiparser_xmidi.cpp b/sound/midiparser_xmidi.cpp
index abc1e20076..0180322927 100644
--- a/sound/midiparser_xmidi.cpp
+++ b/sound/midiparser_xmidi.cpp
@@ -46,13 +46,16 @@ protected:
Loop _loop[4];
int _loopCount;
+ XMidiCallbackProc _callbackProc;
+ void *_callbackData;
+
protected:
uint32 readVLQ2(byte * &data);
void resetTracking();
void parseNextEvent(EventInfo &info);
public:
- MidiParser_XMIDI() : _inserted_delta(0) {}
+ MidiParser_XMIDI(XMidiCallbackProc proc, void *data) : _inserted_delta(0), _callbackProc(proc), _callbackData(data) {}
~MidiParser_XMIDI() { }
bool loadMusic(byte *data, uint32 size);
@@ -103,23 +106,22 @@ void MidiParser_XMIDI::parseNextEvent(EventInfo &info) {
info.basic.param1 = *(_position._play_pos++);
info.basic.param2 = *(_position._play_pos++);
+ // This isn't a full XMIDI implementation, but it should
+ // hopefully be "good enough" for most things.
+
+ switch (info.basic.param1) {
// 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;
- 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
+ case 0x74: { // XMIDI_CONTROLLER_FOR_LOOP
+ byte *pos = _position._play_pos;
+ if (_loopCount < ARRAYSIZE(_loop) - 1)
+ _loopCount++;
+
+ _loop[_loopCount].pos = pos;
+ _loop[_loopCount].repeat = info.basic.param2;
+ break;
+ }
+
+ case 0x75: // XMIDI_CONTORLLER_NEXT_BREAK
if (_loopCount >= 0) {
if (info.basic.param2 < 64) {
// End the current loop.
@@ -133,10 +135,26 @@ void MidiParser_XMIDI::parseNextEvent(EventInfo &info) {
}
}
}
- } else if (info.basic.param1 >= 0x6e && info.basic.param1 <= 0x78) {
- warning("Unsupported XMIDI controller %d (0x%2x)",
- info.basic.param1, info.basic.param1);
+ break;
+
+ case 0x77: // XMIDI_CONTROLLER_CALLBACK_TRIG
+ if (_callbackProc)
+ _callbackProc(info.basic.param2, _callbackData);
+ break;
+
+ default:
+ if (info.basic.param1 >= 0x6e && info.basic.param1 <= 0x78) {
+ warning("Unsupported XMIDI controller %d (0x%2x)",
+ info.basic.param1, info.basic.param1);
+ }
+ break;
}
+
+ // Should we really keep passing the XMIDI controller events to
+ // the MIDI driver, or should we turn them into some kind of
+ // NOP events? (Dummy meta events, perhaps?) Ah well, it has
+ // worked so far, so it shouldn't cause any damage...
+
break;
case 0xF: // Meta or SysEx event
@@ -336,4 +354,10 @@ void MidiParser_XMIDI::resetTracking() {
_inserted_delta = 0;
}
-MidiParser *MidiParser::createParser_XMIDI() { return new MidiParser_XMIDI; }
+void MidiParser::defaultXMidiCallback(byte eventData, void *data) {
+ warning("MidiParser: defaultXMidiCallback(%d)", eventData);
+}
+
+MidiParser *MidiParser::createParser_XMIDI(XMidiCallbackProc proc, void *data) {
+ return new MidiParser_XMIDI(proc, data);
+}