aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJamieson Christian2003-05-25 03:19:21 +0000
committerJamieson Christian2003-05-25 03:19:21 +0000
commit6cb01ce15c5cd120c041d607e17fddaba769c759 (patch)
treebdc82b963bb9a1b1f056345d961a8b7714e65726
parentbe93277b65f38563f03fa9cc1cb8e6e33385c19e (diff)
downloadscummvm-rg350-6cb01ce15c5cd120c041d607e17fddaba769c759.tar.gz
scummvm-rg350-6cb01ce15c5cd120c041d607e17fddaba769c759.tar.bz2
scummvm-rg350-6cb01ce15c5cd120c041d607e17fddaba769c759.zip
Added music support for simon1demo
svn-id: r7927
-rw-r--r--simon/midi.cpp39
-rw-r--r--simon/midi.h1
-rw-r--r--simon/midiparser_s1d.cpp171
-rw-r--r--simon/simon.cpp14
4 files changed, 224 insertions, 1 deletions
diff --git a/simon/midi.cpp b/simon/midi.cpp
index b1129e15b8..663769ec55 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 2c6c6acbf8..95637f2c91 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 0000000000..1f327d19a3
--- /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 970cb3454c..8a238294a9 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.)