aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--engines/toltecs/TODO.txt2
-rw-r--r--engines/toltecs/module.mk1
-rw-r--r--engines/toltecs/music.cpp138
-rw-r--r--engines/toltecs/music.h59
-rw-r--r--engines/toltecs/script.cpp30
-rw-r--r--engines/toltecs/toltecs.cpp3
-rw-r--r--engines/toltecs/toltecs.h2
7 files changed, 227 insertions, 8 deletions
diff --git a/engines/toltecs/TODO.txt b/engines/toltecs/TODO.txt
index 0b9970d314..45b7b6d4e5 100644
--- a/engines/toltecs/TODO.txt
+++ b/engines/toltecs/TODO.txt
@@ -5,7 +5,7 @@ NOTES
TODO
------
-- Add music support (game seems to use XMIDI, MIDI and headerless music...figure out more)
+- Finish music support (game seems to use XMIDI, MIDI and headerless music...figure out more)
- When saving a game, save the whole screen when an animation is playing
e.g. when playing animations (the script controlled ones, not the movies) it should save
the whole screen when the game is saved when such an animation is running since it uses
diff --git a/engines/toltecs/module.mk b/engines/toltecs/module.mk
index 1d9d50ce85..aa4a6f376b 100644
--- a/engines/toltecs/module.mk
+++ b/engines/toltecs/module.mk
@@ -6,6 +6,7 @@ MODULE_OBJS = \
menu.o \
microtiles.o \
movie.o \
+ music.o \
palette.o \
toltecs.o \
render.o \
diff --git a/engines/toltecs/music.cpp b/engines/toltecs/music.cpp
new file mode 100644
index 0000000000..8c88c6ded9
--- /dev/null
+++ b/engines/toltecs/music.cpp
@@ -0,0 +1,138 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+// FIXME: This code is taken from SAGA and needs more work (e.g. setVolume).
+
+#include "toltecs/music.h"
+
+#include "audio/midiparser.h"
+
+namespace Toltecs {
+
+MusicPlayer::MusicPlayer() : _isGM(false), _buffer(NULL) {
+ MidiPlayer::createDriver();
+
+ int ret = _driver->open();
+ if (ret == 0) {
+ if (_nativeMT32)
+ _driver->sendMT32Reset();
+ else
+ _driver->sendGMReset();
+
+ _driver->setTimerCallback(this, &timerCallback);
+ }
+}
+
+void MusicPlayer::send(uint32 b) {
+ if ((b & 0xF0) == 0xC0 && !_isGM && !_nativeMT32) {
+ b = (b & 0xFFFF00FF) | MidiDriver::_mt32ToGm[(b >> 8) & 0xFF] << 8;
+ }
+
+ Audio::MidiPlayer::send(b);
+}
+
+void MusicPlayer::playXMIDI(const byte *data, uint32 size, MusicFlags flags) {
+ Common::StackLock lock(_mutex);
+
+ if (_isPlaying)
+ return;
+
+ stopAndClear();
+
+ _buffer = new byte[size];
+ memcpy(_buffer, data, size);
+
+ // Load XMID resource data
+
+ _isGM = true;
+
+ MidiParser *parser = MidiParser::createParser_XMIDI(NULL);
+ if (parser->loadMusic(_buffer, size)) {
+ parser->setTrack(0);
+ parser->setMidiDriver(this);
+ parser->setTimerRate(_driver->getBaseTempo());
+ parser->property(MidiParser::mpCenterPitchWheelOnUnload, 1);
+ parser->property(MidiParser::mpSendSustainOffOnNotesOff, 1);
+
+ _parser = parser;
+
+ setVolume(127);
+
+ _isLooping = flags & MUSIC_LOOP;
+ _isPlaying = true;
+ } else {
+ delete parser;
+ }
+}
+
+void MusicPlayer::playSMF(const byte *data, uint32 size, MusicFlags flags) {
+ Common::StackLock lock(_mutex);
+
+ if (_isPlaying)
+ return;
+
+ stopAndClear();
+
+ _buffer = new byte[size];
+ memcpy(_buffer, data, size);
+
+ // Load MIDI resource data
+
+ _isGM = true;
+
+ MidiParser *parser = MidiParser::createParser_SMF();
+ if (parser->loadMusic(_buffer, size)) {
+ parser->setTrack(0);
+ parser->setMidiDriver(this);
+ parser->setTimerRate(_driver->getBaseTempo());
+ parser->property(MidiParser::mpCenterPitchWheelOnUnload, 1);
+
+ _parser = parser;
+
+ setVolume(127);
+
+ _isLooping = flags & MUSIC_LOOP;
+ _isPlaying = true;
+ } else {
+ delete parser;
+ }
+}
+
+void MusicPlayer::pause() {
+ setVolume(-1);
+ _isPlaying = false;
+}
+
+void MusicPlayer::resume() {
+ setVolume(127);
+ _isPlaying = true;
+}
+
+void MusicPlayer::stopAndClear() {
+ Common::StackLock lock(_mutex);
+ stop();
+
+ delete[] _buffer;
+ _buffer = NULL;
+}
+
+} // End of namespace Made
diff --git a/engines/toltecs/music.h b/engines/toltecs/music.h
new file mode 100644
index 0000000000..9658633b8a
--- /dev/null
+++ b/engines/toltecs/music.h
@@ -0,0 +1,59 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+// Music class
+
+#ifndef MADE_MUSIC_H
+#define MADE_MUSIC_H
+
+#include "audio/midiplayer.h"
+
+namespace Toltecs {
+
+enum MusicFlags {
+ MUSIC_NORMAL = 0,
+ MUSIC_LOOP = 1
+};
+
+class MusicPlayer : public Audio::MidiPlayer {
+public:
+ MusicPlayer();
+
+ void playXMIDI(const byte *data, uint32 size, MusicFlags flags = MUSIC_NORMAL);
+ void playSMF(const byte *data, uint32 size, MusicFlags flags = MUSIC_NORMAL);
+ void pause();
+ void resume();
+ void stopAndClear();
+
+ // MidiDriver_BASE interface implementation
+ virtual void send(uint32 b);
+
+protected:
+ bool _isGM;
+
+private:
+ byte *_buffer;
+};
+
+} // End of namespace Made
+
+#endif
diff --git a/engines/toltecs/script.cpp b/engines/toltecs/script.cpp
index 780e9ef215..1104c966fe 100644
--- a/engines/toltecs/script.cpp
+++ b/engines/toltecs/script.cpp
@@ -31,6 +31,7 @@
#include "toltecs/animation.h"
#include "toltecs/menu.h"
#include "toltecs/movie.h"
+#include "toltecs/music.h"
#include "toltecs/palette.h"
#include "toltecs/resource.h"
#include "toltecs/script.h"
@@ -1037,17 +1038,32 @@ void ScriptInterpreter::sfStopShakeScreen() {
}
void ScriptInterpreter::sfStartSequence() {
- // TODO
- // DEBUG: Dump music so we know what's in there
int16 sequenceResIndex = arg16(3);
- debug("ScriptInterpreter::sfStartSequence(%d)", sequenceResIndex);
- if (sequenceResIndex >= 0)
- _vm->_arc->dump(sequenceResIndex, "music");
+ //debug("ScriptInterpreter::sfStartSequence(%d)", sequenceResIndex);
+ if (sequenceResIndex >= 0) {
+ //_vm->_arc->dump(sequenceResIndex, "music"); // DEBUG: Dump music so we know what's in there
+
+ int32 resourceSize = _vm->_arc->getResourceSize(sequenceResIndex);
+ byte *data = new byte[resourceSize];
+ _vm->_arc->openResource(sequenceResIndex);
+ _vm->_arc->read(data, resourceSize);
+ _vm->_arc->closeResource();
+
+ if (!memcmp(data, "FORM", 4)) {
+ // TODO: Looping flag
+ _vm->_musicPlayer->playXMIDI(data, resourceSize);
+ } else {
+ // TODO: Where does this occur? Are these SMF MIDI files?
+ warning("sfStartSequence: resource %d isn't XMIDI", sequenceResIndex);
+ }
+
+ delete[] data;
+ }
}
void ScriptInterpreter::sfEndSequence() {
- // TODO
- debug("ScriptInterpreter::sfEndSequence");
+ //debug("ScriptInterpreter::sfEndSequence");
+ _vm->_musicPlayer->stopAndClear();
}
void ScriptInterpreter::sfSetSequenceVolume() {
diff --git a/engines/toltecs/toltecs.cpp b/engines/toltecs/toltecs.cpp
index 37834e8445..7e3a294087 100644
--- a/engines/toltecs/toltecs.cpp
+++ b/engines/toltecs/toltecs.cpp
@@ -41,6 +41,7 @@
#include "toltecs/animation.h"
#include "toltecs/menu.h"
#include "toltecs/movie.h"
+#include "toltecs/music.h"
#include "toltecs/palette.h"
#include "toltecs/render.h"
#include "toltecs/resource.h"
@@ -133,6 +134,7 @@ Common::Error ToltecsEngine::run() {
_palette = new Palette(this);
_segmap = new SegmentMap(this);
_moviePlayer = new MoviePlayer(this);
+ _musicPlayer = new MusicPlayer();
_menuSystem = new MenuSystem(this);
_sound = new Sound(this);
@@ -182,6 +184,7 @@ Common::Error ToltecsEngine::run() {
delete _anim;
delete _palette;
delete _segmap;
+ delete _musicPlayer;
delete _moviePlayer;
delete _menuSystem;
diff --git a/engines/toltecs/toltecs.h b/engines/toltecs/toltecs.h
index 377ef1c2d4..279016cce8 100644
--- a/engines/toltecs/toltecs.h
+++ b/engines/toltecs/toltecs.h
@@ -45,6 +45,7 @@ class ArchiveReader;
class Input;
class MenuSystem;
class MoviePlayer;
+class MusicPlayer;
class Palette;
class ResourceCache;
class ScriptInterpreter;
@@ -134,6 +135,7 @@ public:
Input *_input;
MenuSystem *_menuSystem;
MoviePlayer *_moviePlayer;
+ MusicPlayer *_musicPlayer;
Palette *_palette;
ResourceCache *_res;
ScriptInterpreter *_script;