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).
This commit is contained in:
athrxx 2011-05-22 18:25:29 +02:00 committed by unknown
parent 187ecdd54f
commit 3d42141e9d
5 changed files with 73 additions and 22 deletions

View File

@ -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;

View File

@ -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;

View File

@ -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();
}

View File

@ -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);

View File

@ -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) {