aboutsummaryrefslogtreecommitdiff
path: root/engines/scumm/imuse
diff options
context:
space:
mode:
authorathrxx2011-05-22 18:25:29 +0200
committerunknown2011-05-29 01:03:55 +0200
commit3d42141e9dda203a5dae7bb91384405be5abc243 (patch)
treeb1948b4599c02b0ac46eaf628362a0d31ee19a6c /engines/scumm/imuse
parent187ecdd54f94026dd47b959050295f10faa65bb0 (diff)
downloadscummvm-rg350-3d42141e9dda203a5dae7bb91384405be5abc243.tar.gz
scummvm-rg350-3d42141e9dda203a5dae7bb91384405be5abc243.tar.bz2
scummvm-rg350-3d42141e9dda203a5dae7bb91384405be5abc243.zip
SCUMM: implement some missing (very low relevance) imuse code
1) Don't skip transpose setting in sysex command 0. There are only a few sounds where this setting is used (mainly sfx). 2) Make MI2 and INDY4 read certain player start parameters from the sound resource. The start parameters usually match our default parameters (exception: e.g. LeChuck's Fortress). The use of these parameters has been dropped in DOTT (they use default parameters like we do).
Diffstat (limited to 'engines/scumm/imuse')
-rw-r--r--engines/scumm/imuse/imuse.cpp27
-rw-r--r--engines/scumm/imuse/imuse_internal.h10
-rw-r--r--engines/scumm/imuse/imuse_part.cpp3
-rw-r--r--engines/scumm/imuse/imuse_player.cpp47
-rw-r--r--engines/scumm/imuse/sysex_scumm.cpp8
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) {