Closed sezero closed 2 years ago
This is the solution suggested by Thomas Neumann (in C#):
/********************************************************************/
/// <summary>
/// Effect L: Set envelope position
/// </summary>
/********************************************************************/
private int DoXmEffectL(ushort tick, ModuleFlag flags, Mp_Control a, Module mod, short channel)
{
byte dat = uniTrk.UniGetByte();
if ((tick == 0) && (a.Main.I != null))
{
Instrument i = a.Main.I;
Mp_Voice aOut;
if ((aOut = a.Slave) != null)
{
if (aOut.VEnv.Env != null)
SetEnvelopePosition(ref aOut.VEnv, i.VolEnv, dat);
if (aOut.PEnv.Env != null)
{
// Because of a bug in FastTracker II, only the panning envelope
// position is set if the volume sustain flag is set. Other players
// may set the panning all the time
if (((mod.Flags & ModuleFlag.Ft2Quirks) == 0) || ((i.VolFlg & EnvelopeFlag.Sustain) != 0))
SetEnvelopePosition(ref aOut.PEnv, i.PanEnv, dat);
}
}
}
return 0;
}
And you need this helper method:
/********************************************************************/
/// <summary>
/// Set the envelope tick to the position given
/// </summary>
/********************************************************************/
private void SetEnvelopePosition(ref EnvPr t, EnvPt[] p, short pos)
{
if (t.Pts > 0)
{
bool found = false;
for (ushort i = 0; i < t.Pts - 1; i++)
{
if ((pos >= p[i].Pos) && (pos < p[i + 1].Pos))
{
t.A = i;
t.B = (ushort)(i + 1);
t.P = pos;
found = true;
break;
}
}
// If position is after the last envelope point, just set
// it to the last one
if (!found)
{
t.A = (ushort)(t.Pts - 1);
t.B = t.Pts;
t.P = p[t.A].Pos;
}
}
}
I found the attached module here: https://wiki.openmpt.org/Development:_Test_Cases/XM
I do not know if you know anybody who can test it in the real FastTracker II. It cannot be run on Windows 10, but I found a clone, where the attached module sounds the same as with my patch. But it is a clone, so I don't know if it can be used as a real test. I found the clone here:
Comments? @AliceLR?
As reported by Thomas Neumann (@neumatho):