diff options
Diffstat (limited to 'engines/scumm/imuse')
-rw-r--r-- | engines/scumm/imuse/imuse.cpp | 128 | ||||
-rw-r--r-- | engines/scumm/imuse/imuse.h | 4 | ||||
-rw-r--r-- | engines/scumm/imuse/imuse_internal.h | 15 | ||||
-rw-r--r-- | engines/scumm/imuse/imuse_part.cpp | 6 | ||||
-rw-r--r-- | engines/scumm/imuse/imuse_player.cpp | 50 | ||||
-rw-r--r-- | engines/scumm/imuse/instrument.cpp | 3 | ||||
-rw-r--r-- | engines/scumm/imuse/instrument.h | 3 | ||||
-rw-r--r-- | engines/scumm/imuse/sysex.h | 3 | ||||
-rw-r--r-- | engines/scumm/imuse/sysex_samnmax.cpp | 3 | ||||
-rw-r--r-- | engines/scumm/imuse/sysex_scumm.cpp | 12 |
10 files changed, 99 insertions, 128 deletions
diff --git a/engines/scumm/imuse/imuse.cpp b/engines/scumm/imuse/imuse.cpp index 07fd99c809..7d971f5ca4 100644 --- a/engines/scumm/imuse/imuse.cpp +++ b/engines/scumm/imuse/imuse.cpp @@ -18,9 +18,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * - * $URL$ - * $Id$ - * */ @@ -33,6 +30,7 @@ #include "scumm/imuse/imuse.h" #include "scumm/imuse/imuse_internal.h" #include "scumm/imuse/instrument.h" +#include "scumm/resource.h" #include "scumm/saveload.h" #include "scumm/scumm.h" @@ -50,7 +48,6 @@ _enable_gs(false), _sc55(false), _midi_adlib(NULL), _midi_native(NULL), -_base_sounds(NULL), _sysex(NULL), _paused(false), _initialized(false), @@ -102,12 +99,11 @@ IMuseInternal::~IMuseInternal() { } } -byte *IMuseInternal::findStartOfSound(int sound) { - byte *ptr = NULL; +byte *IMuseInternal::findStartOfSound(int sound, int ct) { int32 size, pos; + static uint32 id[] = { 'MThd', 'FORM', 'MDhd', 'MDpg' }; - if (_base_sounds) - ptr = _base_sounds[sound]; + byte *ptr = g_scumm->_res->_types[rtSound][sound]._address; if (ptr == NULL) { debug(1, "IMuseInternal::findStartOfSound(): Sound %d doesn't exist", sound); @@ -115,12 +111,13 @@ byte *IMuseInternal::findStartOfSound(int sound) { } // Check for old-style headers first, like 'RO' - if (ptr[4] == 'R' && ptr[5] == 'O'&& ptr[6] != 'L') - return ptr + 4; - if (ptr[8] == 'S' && ptr[9] == 'O') - return ptr + 8; + int trFlag = (kMThd | kFORM); + if (ptr[0] == 'R' && ptr[1] == 'O'&& ptr[2] != 'L') + return ct == trFlag ? ptr : 0; + if (ptr[4] == 'S' && ptr[5] == 'O') + return ct == trFlag ? ptr + 4 : 0; - ptr += 8; + ptr += 4; size = READ_BE_UINT32(ptr); ptr += 4; @@ -129,26 +126,25 @@ byte *IMuseInternal::findStartOfSound(int sound) { size = 48; // Arbitrary; we should find our tag within the first 48 bytes of the resource pos = 0; while (pos < size) { - if (!memcmp(ptr + pos, "MThd", 4) || !memcmp(ptr + pos, "FORM", 4)) - return ptr + pos; + for (int i = 0; i < ARRAYSIZE(id); ++i) { + if ((ct & (1 << i)) && (READ_BE_UINT32(ptr + pos) == id[i])) + return ptr + pos; + } ++pos; // We could probably iterate more intelligently } - debug(3, "IMuseInternal::findStartOfSound(): Failed to align on sound %d", sound); + if (ct == (kMThd | kFORM)) + debug(3, "IMuseInternal::findStartOfSound(): Failed to align on sound %d", sound); + return 0; } bool IMuseInternal::isMT32(int sound) { - byte *ptr = NULL; - uint32 tag; - - if (_base_sounds) - ptr = _base_sounds[sound]; - + byte *ptr = g_scumm->_res->_types[rtSound][sound]._address; if (ptr == NULL) return false; - tag = READ_BE_UINT32(ptr + 4); + uint32 tag = READ_BE_UINT32(ptr); switch (tag) { case MKTAG('A','D','L',' '): case MKTAG('A','S','F','X'): // Special AD class for old AdLib sound effects @@ -167,17 +163,17 @@ bool IMuseInternal::isMT32(int sound) { case MKTAG('M','I','D','I'): // Occurs in Sam & Max // HE games use Roland music - if (ptr[12] == 'H' && ptr[13] == 'S') + if (ptr[8] == 'H' && ptr[9] == 'S') return true; else return false; } // Old style 'RO' has equivalent properties to 'ROL' - if (ptr[4] == 'R' && ptr[5] == 'O') + if (ptr[0] == 'R' && ptr[1] == 'O') return true; // Euphony tracks show as 'SO' and have equivalent properties to 'ADL' - if (ptr[8] == 'S' && ptr[9] == 'O') + if (ptr[4] == 'S' && ptr[5] == 'O') return false; error("Unknown music type: '%c%c%c%c'", (char)tag >> 24, (char)tag >> 16, (char)tag >> 8, (char)tag); @@ -186,16 +182,11 @@ bool IMuseInternal::isMT32(int sound) { } bool IMuseInternal::isMIDI(int sound) { - byte *ptr = NULL; - uint32 tag; - - if (_base_sounds) - ptr = _base_sounds[sound]; - + byte *ptr = g_scumm->_res->_types[rtSound][sound]._address; if (ptr == NULL) return false; - tag = READ_BE_UINT32(ptr + 4); + uint32 tag = READ_BE_UINT32(ptr); switch (tag) { case MKTAG('A','D','L',' '): case MKTAG('A','S','F','X'): // Special AD class for old AdLib sound effects @@ -215,11 +206,11 @@ bool IMuseInternal::isMIDI(int sound) { } // Old style 'RO' has equivalent properties to 'ROL' - if (ptr[4] == 'R' && ptr[5] == 'O') + if (ptr[0] == 'R' && ptr[1] == 'O') return true; // Euphony tracks show as 'SO' and have equivalent properties to 'ADL' // FIXME: Right now we're pretending it's GM. - if (ptr[8] == 'S' && ptr[9] == 'O') + if (ptr[4] == 'S' && ptr[5] == 'O') return true; error("Unknown music type: '%c%c%c%c'", (char)tag >> 24, (char)tag >> 16, (char)tag >> 8, (char)tag); @@ -426,11 +417,6 @@ int32 IMuseInternal::doCommand(int numargs, int a[]) { return doCommand_internal(numargs, a); } -void IMuseInternal::setBase(byte **base) { - Common::StackLock lock(_mutex, "IMuseInternal::setBase()"); - _base_sounds = base; -} - uint32 IMuseInternal::property(int prop, uint32 value) { Common::StackLock lock(_mutex, "IMuseInternal::property()"); switch (prop) { @@ -576,7 +562,7 @@ bool IMuseInternal::startSound_internal(int sound, int offset) { return false; } - void *ptr = findStartOfSound(sound); + byte *ptr = findStartOfSound(sound); if (!ptr) { debug(2, "IMuseInternal::startSound(): Couldn't find sound %d", sound); return false; @@ -596,8 +582,11 @@ bool IMuseInternal::startSound_internal(int sound, int offset) { // Bug #590511 and Patch #607175 (which was reversed to fix // an FOA regression: Bug #622606). Player *player = findActivePlayer(sound); - if (!player) - player = allocate_player(128); + if (!player) { + ptr = findStartOfSound(sound, IMuseInternal::kMDhd); + player = allocate_player(ptr ? (READ_BE_UINT32(&ptr[4]) && ptr[10] ? ptr[10] : 128) : 128); + } + if (!player) return false; @@ -645,6 +634,7 @@ int IMuseInternal::stopSound_internal(int sound) { } int IMuseInternal::stopAllSounds_internal() { + clear_queue(); Player *player = _players; for (int i = ARRAYSIZE(_players); i; i--, player++) { if (player->isActive()) @@ -945,54 +935,22 @@ void IMuseInternal::sequencer_timers(MidiDriver *midi) { } void IMuseInternal::handle_marker(uint id, byte data) { - uint16 *p = 0; - uint pos; - - if (_queue_adding && _queue_sound == id && data == _queue_marker) + if ((_queue_end == _queue_pos) || (_queue_adding && _queue_sound == id && data == _queue_marker)) return; - // Fix for bug #733401, revised for bug #761637: - // It would seem that sometimes a marker is in the queue - // but not at the head position. In the case of our bug, - // this seems to be the result of commands in the queue - // for songs that are no longer playing. So we skip - // ahead to the appropriate marker, effectively chomping - // anything in the queue before it. This fixes the FOA - // end credits music, but needs to be tested for inappopriate - // behavior elsewhere. - pos = _queue_end; - while (pos != _queue_pos) { - p = _cmd_queue[pos].array; - if (p[0] == TRIGGER_ID && p[1] == id && p[2] == data) - break; - pos = (pos + 1) % ARRAYSIZE(_cmd_queue); - } - - if (pos == _queue_pos) + uint16 *p = _cmd_queue[_queue_end].array; + if (p[0] != TRIGGER_ID || id != p[1] || data != p[2]) return; - if (pos != _queue_end) - debug(0, "Skipping entries in iMuse command queue to reach marker"); - _trigger_count--; _queue_cleared = false; - do { - pos = (pos + 1) % ARRAYSIZE(_cmd_queue); - if (_queue_pos == pos) - break; - p = _cmd_queue[pos].array; - if (*p++ != COMMAND_ID) - break; - _queue_end = pos; - - doCommand_internal(p[0], p[1], p[2], p[3], p[4], p[5], p[6], 0); - - if (_queue_cleared) - return; - pos = _queue_end; - } while (1); - - _queue_end = pos; + _queue_end = (_queue_end + 1) % ARRAYSIZE(_cmd_queue); + + while (_queue_end != _queue_pos && _cmd_queue[_queue_end].array[0] == COMMAND_ID && !_queue_cleared) { + p = _cmd_queue[_queue_end].array; + doCommand_internal(p[1], p[2], p[3], p[4], p[5], p[6], p[7], 0); + _queue_end = (_queue_end + 1) % ARRAYSIZE(_cmd_queue); + } } int IMuseInternal::get_channel_volume(uint a) { diff --git a/engines/scumm/imuse/imuse.h b/engines/scumm/imuse/imuse.h index 1e3b0fd756..8014b13409 100644 --- a/engines/scumm/imuse/imuse.h +++ b/engines/scumm/imuse/imuse.h @@ -18,9 +18,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * - * $URL$ - * $Id$ - * */ #ifndef SCUMM_IMUSE_H @@ -68,7 +65,6 @@ public: virtual bool get_sound_active(int sound) const = 0; virtual int32 doCommand(int numargs, int args[]) = 0; virtual int clear_queue() = 0; - virtual void setBase(byte **base) = 0; virtual uint32 property(int prop, uint32 value) = 0; virtual void addSysexHandler (byte mfgID, sysexfunc handler) = 0; diff --git a/engines/scumm/imuse/imuse_internal.h b/engines/scumm/imuse/imuse_internal.h index 7d46650d2e..8808a3655a 100644 --- a/engines/scumm/imuse/imuse_internal.h +++ b/engines/scumm/imuse/imuse_internal.h @@ -17,9 +17,6 @@ * 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. - * - * $URL$ - * $Id$ */ #ifndef SCUMM_IMUSE_INTERNAL @@ -232,6 +229,7 @@ protected: // Sequencer part int start_seq_sound(int sound, bool reset_vars = true); + void loadStartParameters(int sound); int query_param(int param); public: @@ -397,7 +395,6 @@ protected: TimerCallbackInfo _timer_info_native; uint32 _game_id; - byte **_base_sounds; // Plug-in SysEx handling. Right now this only supports one // custom SysEx handler for the hardcoded IMUSE_SYSEX_ID @@ -449,7 +446,14 @@ protected: static void midiTimerCallback(void *data); void on_timer(MidiDriver *midi); - byte *findStartOfSound(int sound); + enum ChunkType { + kMThd = 1, + kFORM = 2, + kMDhd = 4, // Used in MI2 and INDY4. Contain certain start parameters (priority, volume, etc. ) for the player. + kMDpg = 8 // These chunks exist in DOTT and SAMNMAX. They don't get processed, however. + }; + + byte *findStartOfSound(int sound, int ct = (kMThd | kFORM)); bool isMT32(int sound); bool isMIDI(int sound); int get_queue_sound_status(int sound) const; @@ -513,7 +517,6 @@ public: int save_or_load(Serializer *ser, ScummEngine *scumm); bool get_sound_active(int sound) const; int32 doCommand(int numargs, int args[]); - void setBase(byte **base); uint32 property(int prop, uint32 value); virtual void addSysexHandler(byte mfgID, sysexfunc handler); diff --git a/engines/scumm/imuse/imuse_part.cpp b/engines/scumm/imuse/imuse_part.cpp index 487429c294..5df8407a96 100644 --- a/engines/scumm/imuse/imuse_part.cpp +++ b/engines/scumm/imuse/imuse_part.cpp @@ -18,9 +18,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * - * $URL$ - * $Id$ - * */ @@ -140,7 +137,8 @@ void Part::set_pan(int8 pan) { } void Part::set_transpose(int8 transpose) { - _transpose_eff = transpose_clamp((_transpose = transpose) + _player->getTranspose(), -24, 24); + _transpose = transpose; + _transpose_eff = (_transpose == -128) ? 0 : transpose_clamp(_transpose + _player->getTranspose(), -24, 24); sendPitchBend(); } diff --git a/engines/scumm/imuse/imuse_player.cpp b/engines/scumm/imuse/imuse_player.cpp index 4d185d94d7..0b084f3116 100644 --- a/engines/scumm/imuse/imuse_player.cpp +++ b/engines/scumm/imuse/imuse_player.cpp @@ -17,9 +17,6 @@ * 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. - * - * $URL$ - * $Id$ */ @@ -93,7 +90,7 @@ Player::~Player() { } bool Player::startSound(int sound, MidiDriver *midi) { - void *ptr; + byte *ptr; int i; // Not sure what the old code was doing, @@ -111,13 +108,8 @@ bool Player::startSound(int sound, MidiDriver *midi) { _active = true; _midi = midi; _id = sound; - _priority = 0x80; - _volume = 0x7F; - _vol_chan = 0xFFFF; - _vol_eff = (_se->get_channel_volume(0xFFFF) << 7) >> 7; - _pan = 0; - _transpose = 0; - _detune = 0; + + loadStartParameters(sound); for (i = 0; i < ARRAYSIZE(_parameterFaders); ++i) _parameterFaders[i].init(); @@ -128,7 +120,7 @@ bool Player::startSound(int sound, MidiDriver *midi) { _midi = NULL; return false; } - + debugC(DEBUG_IMUSE, "Starting music %d", sound); return true; } @@ -202,11 +194,43 @@ int Player::start_seq_sound(int sound, bool reset_vars) { _parser->property(MidiParser::mpSmartJump, 1); _parser->loadMusic(ptr, 0); _parser->setTrack(_track_index); - setSpeed(reset_vars ? 128 : _speed); + + ptr = _se->findStartOfSound(sound, IMuseInternal::kMDhd); + setSpeed(reset_vars ? (ptr ? (READ_BE_UINT32(&ptr[4]) && ptr[15] ? ptr[15] : 128) : 128) : _speed); return 0; } +void Player::loadStartParameters(int sound) { + _priority = 0x80; + _volume = 0x7F; + _vol_chan = 0xFFFF; + _vol_eff = (_se->get_channel_volume(0xFFFF) << 7) >> 7; + _pan = 0; + _transpose = 0; + _detune = 0; + + byte *ptr = _se->findStartOfSound(sound, IMuseInternal::kMDhd); + uint32 size = 0; + + if (ptr) { + ptr += 4; + size = READ_BE_UINT32(ptr); + ptr += 4; + + // MDhd chunks don't get used in MI1 and contain only zeroes. + // We check for volume, priority and speed settings of zero here. + if (size && (ptr[2] | ptr[3] | ptr[7])) { + _priority = ptr[2]; + _volume = ptr[3]; + _pan = ptr[4]; + _transpose = ptr[5]; + _detune = ptr[6]; + setSpeed(ptr[7]); + } + } +} + void Player::uninit_parts() { assert(!_parts || _parts->_player == this); diff --git a/engines/scumm/imuse/instrument.cpp b/engines/scumm/imuse/instrument.cpp index 02996c53d3..955700fc2b 100644 --- a/engines/scumm/imuse/instrument.cpp +++ b/engines/scumm/imuse/instrument.cpp @@ -17,9 +17,6 @@ * 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. - * - * $URL$ - * $Id$ */ diff --git a/engines/scumm/imuse/instrument.h b/engines/scumm/imuse/instrument.h index f6108daf16..3555d319e6 100644 --- a/engines/scumm/imuse/instrument.h +++ b/engines/scumm/imuse/instrument.h @@ -17,9 +17,6 @@ * 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. - * - * $URL$ - * $Id$ */ #ifndef SCUMM_IMUSE_INSTRUMENT_H diff --git a/engines/scumm/imuse/sysex.h b/engines/scumm/imuse/sysex.h index bff80de9e7..7dd38e785e 100644 --- a/engines/scumm/imuse/sysex.h +++ b/engines/scumm/imuse/sysex.h @@ -17,9 +17,6 @@ * 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. - * - * $URL$ - * $Id$ */ #ifndef SCUMM_IMUSE_SYSEX_H diff --git a/engines/scumm/imuse/sysex_samnmax.cpp b/engines/scumm/imuse/sysex_samnmax.cpp index cdae767abf..4c4219e7bb 100644 --- a/engines/scumm/imuse/sysex_samnmax.cpp +++ b/engines/scumm/imuse/sysex_samnmax.cpp @@ -17,9 +17,6 @@ * 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. - * - * $URL$ - * $Id$ */ diff --git a/engines/scumm/imuse/sysex_scumm.cpp b/engines/scumm/imuse/sysex_scumm.cpp index 78028c6056..4eb3bee93c 100644 --- a/engines/scumm/imuse/sysex_scumm.cpp +++ b/engines/scumm/imuse/sysex_scumm.cpp @@ -17,9 +17,6 @@ * 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. - * - * $URL$ - * $Id$ */ @@ -67,6 +64,11 @@ void sysexHandler_Scumm(Player *player, const byte *msg, uint16 len) { // BYTE 14: Pitchbend range(lower 4 bits) [bug #1088045] // BYTE 15: Program(upper 4 bits) // BYTE 16: Program(lower 4 bits) + + // athrxx (05-21-2011): + // BYTE 9, 10: Transpose (if set to 0x80, this means that part->_transpose_eff will be 0 (also ignoring player->_transpose) + // BYTE 11, 12: Detune + part = player->getPart(p[0] & 0x0F); if (part) { part->set_onoff(p[2] & 0x01); @@ -74,7 +76,9 @@ void sysexHandler_Scumm(Player *player, const byte *msg, uint16 len) { part->set_pri(p[4]); part->volume((p[5] & 0x0F) << 4 |(p[6] & 0x0F)); part->set_pan((p[7] & 0x0F) << 4 | (p[8] & 0x0F)); - part->_percussion = player->_isMIDI ? ((p[9] & 0x08) > 0) : false; + part->_percussion = player->_isMIDI ? ((p[9] & 0x08) > 0) : false; + part->set_transpose((p[9] & 0x0F) << 4 | (p[10] & 0x0F)); + part->set_detune((p[11] & 0x0F) << 4 | (p[12] & 0x0F)); part->pitchBendFactor((p[13] & 0x0F) << 4 | (p[14] & 0x0F)); if (part->_percussion) { if (part->_mc) { |