diff --git a/simon/midi.cpp b/simon/midi.cpp
index b1129e15b86..663769ec557 100644
--- a/simon/midi.cpp
+++ b/simon/midi.cpp
@@ -27,6 +27,13 @@
 #include "sound/mixer.h"
 #include "simon/simon.h"
 
+// MidiParser_S1D is not considered part of the standard
+// MidiParser suite, but we still try to mask its details
+// and just provide a factory function.
+extern MidiParser *MidiParser_createS1D();
+
+
+
 MidiPlayer::MidiPlayer (OSystem *system) {
 	// Since initialize() is called every time the music changes,
 	// this is where we'll initialize stuff that must persist
@@ -448,3 +455,35 @@ void MidiPlayer::loadXMIDI (File *in, bool sfx) {
 	p->parser = parser; // That plugs the power cord into the wall
 	_system->unlock_mutex (_mutex);
 }
+
+void MidiPlayer::loadS1D (File *in, bool sfx) {
+	_system->lock_mutex (_mutex);
+	MusicInfo *p = sfx ? &_sfx : &_music;
+	clearConstructs (*p);
+
+	uint32 size = in->readByte() | (in->readByte() << 8);
+	if (size != in->size() - 2) {
+		printf ("ERROR! Size mismatch in simon1demo MUS file (%ld versus reported %d)\n", (long) in->size() - 2, (long) size);
+		_system->unlock_mutex (_mutex);
+		return;
+	}
+
+	p->data = (byte *) calloc (size, 1);
+	in->read (p->data, size);
+
+	MidiParser *parser = MidiParser_createS1D();
+	parser->setMidiDriver (this);
+	parser->setTimerRate (_driver->getBaseTempo());
+	if (!parser->loadMusic (p->data, size)) {
+		printf ("Error reading track!\n");
+		delete parser;
+		parser = 0;
+	}
+
+	if (!sfx) {
+		_currentTrack = 255;
+		memset(_volumeTable, 127, sizeof(_volumeTable));
+	}
+	p->parser = parser; // That plugs the power cord into the wall
+	_system->unlock_mutex (_mutex);
+}
diff --git a/simon/midi.h b/simon/midi.h
index 2c6c6acbf89..95637f2c91d 100644
--- a/simon/midi.h
+++ b/simon/midi.h
@@ -80,6 +80,7 @@ public:
 	void loadSMF (File *in, int song, bool sfx = false);
 	void loadMultipleSMF (File *in, bool sfx = false);
 	void loadXMIDI (File *in, bool sfx = false);
+	void loadS1D (File *in, bool sfx = false);
 
 	void setLoop (bool loop);
 	void startTrack(int track);
diff --git a/simon/midiparser_s1d.cpp b/simon/midiparser_s1d.cpp
new file mode 100644
index 00000000000..1f327d19a39
--- /dev/null
+++ b/simon/midiparser_s1d.cpp
@@ -0,0 +1,171 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2001-2003 The ScummVM project
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * $Header$
+ *
+ */
+
+#include "sound/midiparser.h"
+#include "sound/mididrv.h"
+#include "common/util.h"
+
+#include <stdio.h>
+#include <memory.h>
+
+//////////////////////////////////////////////////
+//
+// Simon 1 Demo version of MidiParser
+//
+//////////////////////////////////////////////////
+
+class MidiParser_S1D : public MidiParser {
+protected:
+	byte *_data;
+	bool _no_delta;
+
+protected:
+	void parseNextEvent (EventInfo &info);
+	void resetTracking();
+	uint32 readVLQ2 (byte * &data);
+
+public:
+	MidiParser_S1D() : _data(0), _no_delta(false) {}
+
+	bool loadMusic (byte *data, uint32 size);
+	void unloadMusic();
+};
+
+
+
+//////////////////////////////////////////////////
+//
+// MidiParser_S1D implementation
+//
+// This parser is the result of eyeballing the
+// one MUS file that's included with simon1demo.
+// So there might be some things missing.
+// I've tried to notate question-mark areas
+// where they occur.
+//
+//////////////////////////////////////////////////
+
+// The VLQs for simon1demo seem to be
+// in Little Endian format.
+uint32 MidiParser_S1D::readVLQ2 (byte * &data) {
+	byte str;
+	uint32 value = 0;
+	int i;
+
+	for (i = 0; i < 4; ++i) {
+		str = data[0];
+		++data;
+		value |= (str & 0x7F) << (i * 7);
+		if (!(str & 0x80))
+			break;
+	}
+	return value;
+}
+
+void MidiParser_S1D::parseNextEvent (EventInfo &info) {
+	info.start = _position._play_pos;
+	info.delta = _no_delta ? 0 : readVLQ2 (_position._play_pos);
+
+	_no_delta = false;
+	info.event = *(_position._play_pos++);
+	if (info.command() < 0x8) {
+		_no_delta = true;
+		info.event += 0x80;
+	}
+
+	switch (info.command()) {
+	case 0x8:
+		info.basic.param1 = *(_position._play_pos++);
+		info.basic.param2 = 0;
+		info.length = 0;
+		break;
+
+	case 0x9:
+		info.basic.param1 = *(_position._play_pos++);
+		info.basic.param2 = *(_position._play_pos++); // I'm ASSUMING this byte is velocity!
+		info.length = 0;
+		break;
+
+	case 0xC:
+		info.basic.param1 = *(_position._play_pos++);
+		info.basic.param2 = 0;
+		++_position._play_pos; // I have NO IDEA what the second byte is for.
+		break;
+
+	case 0xF:
+		if (info.event == 0xFC) {
+			// This means End of Track.
+			// Rewrite in SMF (MIDI transmission) form.
+			info.event = 0xFF;
+			info.ext.type = 0x2F;
+			info.length = 0;
+			break;
+		}
+		// OTherwise fall through to default.
+
+	default:
+		printf ("MidiParser_S1D: Warning! Unexpected byte 0x%02X found!\n", (int) info.event);
+		_abort_parse = true;
+		_position._play_pos = 0;
+	}
+}
+
+bool MidiParser_S1D::loadMusic (byte *data, uint32 size) {
+	unloadMusic();
+
+	byte *pos = data;
+	if (*(pos++) != 0xFC) {
+		printf ("Warning: Expected 0xFC header but found 0x%02X instead\n", (int) *pos);
+		return false;
+	}
+
+	// The next 3 bytes MIGHT be tempo, but we skip them and use the default.
+//	setTempo (*(pos++) | (*(pos++) << 8) | (*(pos++) << 16));
+	pos += 3;
+
+	// And now we're at the actual data. Only one track.
+	_num_tracks = 1;
+	_data = pos;
+	_tracks[0] = pos;
+
+	// Note that we assume the original data passed in
+	// will persist beyond this call, i.e. we do NOT
+	// copy the data to our own buffer. Take warning....
+	resetTracking();
+	setTempo (500000);
+	setTrack (0);
+	return true;
+}
+
+void MidiParser_S1D::resetTracking() {
+	MidiParser::resetTracking();
+	_no_delta = false;
+}
+
+void MidiParser_S1D::unloadMusic() {
+	resetTracking();
+	allNotesOff();
+	_data = 0;
+	_num_tracks = 0;
+	_active_track = 255;
+}
+
+MidiParser *MidiParser_createS1D() { return new MidiParser_S1D; }
\ No newline at end of file
diff --git a/simon/simon.cpp b/simon/simon.cpp
index 970cb3454cc..8a238294a97 100644
--- a/simon/simon.cpp
+++ b/simon/simon.cpp
@@ -5300,7 +5300,19 @@ void SimonState::loadMusic (uint music) {
 			// TODO Add Protracker support for simon1amiga/cd32
 			warning("playMusic - Load %dtune attempt", music);
 		} else if (_game & GF_DEMO) {
-			// TODO Add music support for simon1demo
+			midi.stop();
+			midi.setLoop (true);
+			char buf[50];
+			File *f = new File();
+			sprintf(buf, "MOD%d.MUS", music);
+			f->open(buf, _gameDataPath);
+			if (f->isOpen() == false) {
+				warning("Can't load music from '%s'", buf);
+				return;
+			}
+			midi.loadS1D (f);
+			delete f;
+			midi.startTrack (0);
 		} else {
 			midi.stop();
 			midi.setLoop (true); // Must do this BEFORE loading music. (GMF may have its own override.)