protected int ImSetTrigger(int sound, int id, int a, int b, int c, int d, int e, int f, int g, int h)
{
// Sam & Max: ImSetTrigger.
// Sets a trigger for a particular player and
// marker ID, along with doCommand parameters
// to invoke at the marker. The marker is
// represented by MIDI SysEx block 00 xx(F7)
// where "xx" is the marker ID.
ushort oldest_trigger = 0;
ImTrigger oldest_ptr = null;
ImTrigger trig = null;
int i;
for (i = 0; i < _snm_triggers.Length; i++)
{
trig = _snm_triggers[i];
if (trig.Id == 0)
break;
// We used to only compare 'id' and 'sound' here, but at least
// at the Dino Bungie Memorial that causes the music to stop
// after getting the T-Rex tooth. See bug #888161.
if (trig.Id == id && trig.Sound == sound && trig.Command[0] == a)
break;
ushort diff;
if (trig.Expire <= _snm_trigger_index)
diff = (ushort)(_snm_trigger_index - trig.Expire);
else
diff = (ushort)(0x10000 - trig.Expire + _snm_trigger_index);
if (oldest_ptr == null || oldest_trigger < diff)
{
oldest_ptr = trig;
oldest_trigger = diff;
}
}
// If we didn't find a trigger, see if we can expire one.
if (i == _snm_triggers.Length)
{
if (oldest_ptr == null)
return -1;
trig = oldest_ptr;
}
trig.Id = (byte)id;
trig.Sound = sound;
trig.Expire = (ushort)(++_snm_trigger_index & 0xFFFF);
trig.Command[0] = a;
trig.Command[1] = b;
trig.Command[2] = c;
trig.Command[3] = d;
trig.Command[4] = e;
trig.Command[5] = f;
trig.Command[6] = g;
trig.Command[7] = h;
// If the command is to start a sound, stop that sound if it's already playing.
// This fixes some carnival music problems.
// NOTE: We ONLY do this if the sound that will trigger the command is actually
// playing. Otherwise, there's a problem when exiting and re-entering the
// Bumpusville mansion. Ref Bug #780918.
if (trig.Command[0] == 8 && GetSoundStatusInternal(trig.Command[1], true) != 0 && GetSoundStatusInternal(sound, true) != 0)
StopSoundInternal(trig.Command[1]);
return 0;
}