diff options
Diffstat (limited to 'engines/scumm')
-rw-r--r-- | engines/scumm/imuse/imuse.cpp | 27 | ||||
-rw-r--r-- | engines/scumm/imuse/imuse_internal.h | 10 | ||||
-rw-r--r-- | engines/scumm/imuse/imuse_part.cpp | 3 | ||||
-rw-r--r-- | engines/scumm/imuse/imuse_player.cpp | 47 | ||||
-rw-r--r-- | engines/scumm/imuse/sysex_scumm.cpp | 8 |
5 files changed, 73 insertions, 22 deletions
diff --git a/engines/scumm/imuse/imuse.cpp b/engines/scumm/imuse/imuse.cpp index fe23b88e52..7d971f5ca4 100644 --- a/engines/scumm/imuse/imuse.cpp +++ b/engines/scumm/imuse/imuse.cpp @@ -99,8 +99,9 @@ IMuseInternal::~IMuseInternal() { } } -byte *IMuseInternal::findStartOfSound(int sound) { +byte *IMuseInternal::findStartOfSound(int sound, int ct) { int32 size, pos; + static uint32 id[] = { 'MThd', 'FORM', 'MDhd', 'MDpg' }; byte *ptr = g_scumm->_res->_types[rtSound][sound]._address; @@ -110,10 +111,11 @@ byte *IMuseInternal::findStartOfSound(int sound) { } // Check for old-style headers first, like 'RO' + int trFlag = (kMThd | kFORM); if (ptr[0] == 'R' && ptr[1] == 'O'&& ptr[2] != 'L') - return ptr; + return ct == trFlag ? ptr : 0; if (ptr[4] == 'S' && ptr[5] == 'O') - return ptr + 4; + return ct == trFlag ? ptr + 4 : 0; ptr += 4; size = READ_BE_UINT32(ptr); @@ -124,12 +126,16 @@ 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; } @@ -556,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; @@ -576,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; diff --git a/engines/scumm/imuse/imuse_internal.h b/engines/scumm/imuse/imuse_internal.h index ec60b22509..8808a3655a 100644 --- a/engines/scumm/imuse/imuse_internal.h +++ b/engines/scumm/imuse/imuse_internal.h @@ -229,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: @@ -445,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; diff --git a/engines/scumm/imuse/imuse_part.cpp b/engines/scumm/imuse/imuse_part.cpp index 808af23dde..5df8407a96 100644 --- a/engines/scumm/imuse/imuse_part.cpp +++ b/engines/scumm/imuse/imuse_part.cpp @@ -137,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 e7ee935130..0b084f3116 100644 --- a/engines/scumm/imuse/imuse_player.cpp +++ b/engines/scumm/imuse/imuse_player.cpp @@ -90,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, @@ -108,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(); @@ -125,7 +120,7 @@ bool Player::startSound(int sound, MidiDriver *midi) { _midi = NULL; return false; } - + debugC(DEBUG_IMUSE, "Starting music %d", sound); return true; } @@ -199,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/sysex_scumm.cpp b/engines/scumm/imuse/sysex_scumm.cpp index 6ab71c2fa5..4eb3bee93c 100644 --- a/engines/scumm/imuse/sysex_scumm.cpp +++ b/engines/scumm/imuse/sysex_scumm.cpp @@ -64,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); @@ -71,7 +76,8 @@ 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) { |