public void SetupProgram(byte[] data, byte mLevelPara, byte tLevelPara)
{
// This driver uses only 2 operators and 2 algorithms (algorithm 5 and 7),
// since it is just a modified AdLib driver. It also uses AdLib programs.
// There are no FM-TOWNS specific programs. This is the reason for the low quality of the FM-TOWNS
// music (unsuitable data is just forced into the wrong audio device).
byte[] mul = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 12, 12, 15, 15 };
byte chan = _chanMap[_chan];
byte mulAmsFms1 = _driver._chanState[chan].mulAmsFms = data[0];
byte tl1 = _driver._chanState[chan].tl = (byte)((data[1] | 0x3f) - mLevelPara);
byte attDec1 = _driver._chanState[chan].attDec = (byte)~data[2];
byte sus1 = _driver._chanState[chan].sus = (byte)~data[3];
_driver._chanState[chan].unk2 = data[4];
chan += 3;
@out(0x30, mul[mulAmsFms1 & 0x0f]);
@out(0x40, (byte)((tl1 & 0x3f) + 15));
@out(0x50, (byte)(((attDec1 >> 4) << 1) | ((attDec1 >> 4) & 1)));
@out(0x60, (byte)(((attDec1 << 1) | (attDec1 & 1)) & 0x1f));
@out(0x70, (byte)((((mulAmsFms1 & 0x20) ^ 0x20) != 0) ? (((sus1 & 0x0f) << 1) | 1) : 0));
@out(0x80, sus1);
byte mulAmsFms2 = _driver._chanState[chan].mulAmsFms = data[5];
byte tl2 = _driver._chanState[chan].tl = (byte)((data[6] | 0x3f) - tLevelPara);
byte attDec2 = _driver._chanState[chan].attDec = (byte)~data[7];
byte sus2 = _driver._chanState[chan].sus = (byte)~data[8];
_driver._chanState[chan].unk2 = data[9];
byte mul2 = mul[mulAmsFms2 & 0x0f];
tl2 = (byte)((tl2 & 0x3f) + 15);
byte ar2 = (byte)(((attDec2 >> 4) << 1) | ((attDec2 >> 4) & 1));
byte dec2 = (byte)(((attDec2 << 1) | (attDec2 & 1)) & 0x1f);
byte sus2r = (byte)((((mulAmsFms2 & 0x20) ^ 0x20) != 0) ? (((sus2 & 0x0f) << 1) | 1) : 0);
for (int i = 4; i < 16; i += 4)
{
@out((byte)(0x30 + i), mul2);
@out((byte)(0x40 + i), tl2);
@out((byte)(0x50 + i), ar2);
@out((byte)(0x60 + i), dec2);
@out((byte)(0x70 + i), sus2r);
@out((byte)(0x80 + i), sus2);
}
_driver._chanState[chan].fgAlg = data[10];
byte alg = (byte)(5 + 2 * (data[10] & 1));
byte fb = (byte)(4 * (data[10] & 0x0e));
@out(0xb0, (byte)(fb | alg));
byte t = (byte)(mulAmsFms1 | mulAmsFms2);
@out(0xb4, (byte)(0xc0 | ((t & 0x80) >> 3) | ((t & 0x40) >> 5)));
}