aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--engines/sci/console.cpp106
-rw-r--r--engines/sci/console.h1
-rw-r--r--engines/sci/sound/midiparser_sci.cpp42
-rw-r--r--engines/sci/sound/midiparser_sci.h2
4 files changed, 132 insertions, 19 deletions
diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp
index f025c63335..ac165f22b1 100644
--- a/engines/sci/console.cpp
+++ b/engines/sci/console.cpp
@@ -39,6 +39,7 @@
#include "sci/sound/iterator/songlib.h" // for SongLibrary
#include "sci/sound/iterator/iterator.h" // for SCI_SONG_ITERATOR_TYPE_SCI0
#else
+#include "sci/sound/midiparser_sci.h"
#include "sci/sound/music.h"
#endif
#include "sci/sound/drivers/mididriver.h"
@@ -106,6 +107,7 @@ Console::Console(SciEngine *engine) : GUI::Debugger() {
DCmd_Register("list", WRAP_METHOD(Console, cmdList));
DCmd_Register("hexgrep", WRAP_METHOD(Console, cmdHexgrep));
DCmd_Register("verify_scripts", WRAP_METHOD(Console, cmdVerifyScripts));
+ DCmd_Register("verify_midi", WRAP_METHOD(Console, cmdVerifyMidi));
// Game
DCmd_Register("save_game", WRAP_METHOD(Console, cmdSaveGame));
DCmd_Register("restore_game", WRAP_METHOD(Console, cmdRestoreGame));
@@ -326,6 +328,7 @@ bool Console::cmdHelp(int argc, const char **argv) {
DebugPrintf(" list - Lists all the resources of a given type\n");
DebugPrintf(" hexgrep - Searches some resources for a particular sequence of bytes, represented as hexadecimal numbers\n");
DebugPrintf(" verify_scripts - Performs sanity checks on SCI1.1-SCI2.1 game scripts (e.g. if they're up to 64KB in total)\n");
+ DebugPrintf(" verify_midi - Performs checks on MIDI patches, for unmapped instruments\n");
DebugPrintf("\n");
DebugPrintf("Game:\n");
DebugPrintf(" save_game - Saves the current game state to the hard disk\n");
@@ -832,7 +835,7 @@ bool Console::cmdVerifyScripts(int argc, const char **argv) {
if (!script)
DebugPrintf("Error: script %d couldn't be loaded\n", itr->number);
- heap = _engine->getResMan()->findResource(*itr, false);
+ heap = _engine->getResMan()->findResource(ResourceId(kResourceTypeHeap, itr->number), false);
if (!heap)
DebugPrintf("Error: script %d doesn't have a corresponding heap\n", itr->number);
@@ -848,6 +851,107 @@ bool Console::cmdVerifyScripts(int argc, const char **argv) {
return true;
}
+bool Console::cmdVerifyMidi(int argc, const char **argv) {
+ // TODO: Sometimes this goes out of bounds with some songs, as it misses
+ // the EOT signal
+#if 0
+ SciVersion doSoundVersion = _engine->_features->detectDoSoundType();
+ MidiPlayer *player = MidiPlayer_Midi_create(doSoundVersion);
+ MidiParser_SCI *parser = new MidiParser_SCI(doSoundVersion);
+ parser->setMidiDriver(player);
+
+ Common::List<ResourceId> *resources = _engine->getResMan()->listResources(kResourceTypeSound);
+ sort(resources->begin(), resources->end(), ResourceIdLess());
+ Common::List<ResourceId>::iterator itr = resources->begin();
+
+ DebugPrintf("%d sounds found, checking their instrument mappings...\n", resources->size());
+
+ SoundResource *sound;
+
+ while (itr != resources->end()) {
+ sound = new SoundResource(itr->number, _engine->getResMan(), doSoundVersion);
+ int channelFilterMask = sound->getChannelFilterMask(player->getPlayId(), player->hasRhythmChannel());
+ SoundResource::Track *track = sound->getTrackByType(player->getPlayId());
+ if (track->digitalChannelNr != -1) {
+ // Skip digitized sound effects
+ delete sound;
+ continue;
+ }
+
+ parser->loadMusic(track, NULL, channelFilterMask, doSoundVersion);
+ const byte *channelData = parser->getMixedData();
+
+ byte param1 = 0;
+ byte command = 0, prev = 0;
+ byte curEvent = 0;
+ bool endOfTrack = false;
+
+ do {
+ while (*channelData == 0xF8)
+ channelData++;
+
+ channelData++; // delta
+
+ if ((*channelData & 0xF0) >= 0x80)
+ curEvent = *(channelData++);
+ else
+ curEvent = prev;
+ if (curEvent < 0x80)
+ continue;
+
+ prev = curEvent;
+ command = curEvent >> 4;
+
+ switch (command) {
+ case 0xC: // program change
+ param1 = *channelData++;
+ // TODO: verify that the instrument is mapped
+ printf("Song %d, patch %d\n", itr->number, param1);
+ break;
+ case 0xD:
+ case 0xB:
+ param1 = *channelData++;
+ break;
+ case 0x8:
+ case 0x9:
+ case 0xA:
+ case 0xE:
+ param1 = *channelData++;
+ *channelData++; // param2
+ break;
+ case 0xF:
+ if ((curEvent & 0x0F) == 0x2) {
+ param1 = *channelData++;
+ *channelData++; // param2
+ } else if ((curEvent & 0x0F) == 0x3) {
+ param1 = *channelData++;
+ } else if ((curEvent & 0x0F) == 0xF) { // META
+ byte type = *channelData++;
+ if (type == 0x2F) {// end of track reached
+ endOfTrack = true;
+ } else {
+ // no further processing necessary
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ } while (!endOfTrack);
+
+ delete sound;
+ ++itr;
+ }
+
+ delete parser;
+ delete player;
+
+ DebugPrintf("Music check finished\n");
+#endif
+
+ return true;
+}
+
bool Console::cmdList(int argc, const char **argv) {
if (argc < 2) {
DebugPrintf("Lists all the resources of a given type\n");
diff --git a/engines/sci/console.h b/engines/sci/console.h
index 2b13e03ef6..572a62c274 100644
--- a/engines/sci/console.h
+++ b/engines/sci/console.h
@@ -74,6 +74,7 @@ private:
bool cmdList(int argc, const char **argv);
bool cmdHexgrep(int argc, const char **argv);
bool cmdVerifyScripts(int argc, const char **argv);
+ bool cmdVerifyMidi(int argc, const char **argv);
// Game
bool cmdSaveGame(int argc, const char **argv);
bool cmdRestoreGame(int argc, const char **argv);
diff --git a/engines/sci/sound/midiparser_sci.cpp b/engines/sci/sound/midiparser_sci.cpp
index 8f88945888..f852367bfe 100644
--- a/engines/sci/sound/midiparser_sci.cpp
+++ b/engines/sci/sound/midiparser_sci.cpp
@@ -75,7 +75,8 @@ bool MidiParser_SCI::loadMusic(SoundResource::Track *track, MusicEntry *psnd, in
_pSnd = psnd;
_soundVersion = soundVersion;
- setVolume(psnd->volume);
+ if (_pSnd)
+ setVolume(psnd->volume);
if (channelFilterMask) {
// SCI0 only has 1 data stream, but we need to filter out channels depending on music hardware selection
@@ -86,30 +87,35 @@ bool MidiParser_SCI::loadMusic(SoundResource::Track *track, MusicEntry *psnd, in
_num_tracks = 1;
_tracks[0] = _mixedData;
- setTrack(0);
+ if (_pSnd)
+ setTrack(0);
_loopTick = 0;
- if (_soundVersion <= SCI_VERSION_0_LATE) {
- // Set initial voice count
- for (int i = 0; i < 16; ++i) {
- byte voiceCount = 0;
- if (channelFilterMask & (1 << i))
- voiceCount = psnd->soundRes->getInitialVoiceCount(i);
- _driver->send(0xB0 | i, 0x4B, voiceCount);
+ if (_pSnd) {
+ if (_soundVersion <= SCI_VERSION_0_LATE) {
+ // Set initial voice count
+ for (int i = 0; i < 16; ++i) {
+ byte voiceCount = 0;
+ if (channelFilterMask & (1 << i))
+ voiceCount = psnd->soundRes->getInitialVoiceCount(i);
+ _driver->send(0xB0 | i, 0x4B, voiceCount);
+ }
}
- }
- // Send a velocity off signal to all channels
- for (int i = 0; i < 16; ++i) {
- _driver->send(0xB0 | i, 0x4E, 0); // Reset velocity
+ // Send a velocity off signal to all channels
+ for (int i = 0; i < 16; ++i) {
+ _driver->send(0xB0 | i, 0x4E, 0); // Reset velocity
+ }
}
return true;
}
void MidiParser_SCI::unloadMusic() {
- resetTracking();
- allNotesOff();
+ if (_pSnd) {
+ resetTracking();
+ allNotesOff();
+ }
_num_tracks = 0;
_active_track = 255;
_resetOnPause = false;
@@ -120,7 +126,7 @@ void MidiParser_SCI::unloadMusic() {
}
// Center the pitch wheels and hold pedal in preparation for the next piece of music
- if (_driver) {
+ if (_driver && _pSnd) {
for (int i = 0; i < 16; ++i) {
if (isChannelUsed(i)) {
_driver->send(0xE0 | i, 0, 0x40); // Reset pitch wheel
@@ -359,10 +365,10 @@ byte *MidiParser_SCI::midiMixChannels() {
long new_delta;
SoundResource::Channel *channel;
- while ((curr = midiGetNextChannel(ticker)) != 0xFF) { // there is still active channel
+ while ((curr = midiGetNextChannel(ticker)) != 0xFF) { // there is still an active channel
channel = &_track->channels[curr];
curDelta = *channel->data++;
- channel->time += (curDelta == 0xF8 ? 240 : curDelta); // when the comamnd is supposed to occur
+ channel->time += (curDelta == 0xF8 ? 240 : curDelta); // when the command is supposed to occur
if (curDelta == 0xF8)
continue;
new_delta = channel->time - ticker;
diff --git a/engines/sci/sound/midiparser_sci.h b/engines/sci/sound/midiparser_sci.h
index 9d4b5a39da..8384c74cf6 100644
--- a/engines/sci/sound/midiparser_sci.h
+++ b/engines/sci/sound/midiparser_sci.h
@@ -79,6 +79,8 @@ public:
void clearUsedChannels() { _channelsUsed = 0; }
+ const byte *getMixedData() const { return _mixedData; }
+
protected:
bool isChannelUsed(byte channel) const { return _channelsUsed & (1 << channel); }
void setChannelUsed(byte channel) { _channelsUsed |= (1 << channel); }