aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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);
+}