Extract/Convert Adlib Instruments

General chat related to ScummVM, adventure gaming, and so on.

Moderator: ScummVM Team

tashiy
Posts: 9
Joined: Tue Jun 19, 2012 9:17 am

Post by tashiy » Thu Jun 21, 2012 5:43 pm

Thank you Jepael.

I had problems to see the byteorder In the sourcecode I see the OPL Register addresses like 0x20, 0x40, 0x20. I think data get written there to control the fm synth.

But I don`t understand the order from the the 11 instrument bytes.

If I understand the code right the procedure Player::setupChannel will be invoked with the two parameter channel with datatype uint8_t and instrOffset with datatype uint16_t.
Player::setupOperator will be invoked with the two parameter opr with datatype uint8_t and &instrOffset with datatype uint16_t.

But I don`t understand the things below the first lines from the procedure. I see some addition with the parameter that was given with the procedure and the OPL register addresses.

I have looked at the .sbi file format documentation. I see there the OPL register with datatype and description. But I don`t see where the instrument bytes should be.

Maybe I mixed up chip register and instrument bytes.

jepael
Posts: 26
Joined: Sat Oct 25, 2008 8:16 pm

Post by jepael » Sat Jun 23, 2012 8:51 am

OK, I can explain a bit more. The following register values mean only first OPL channel, but you get the idea.

SBI file format:
First header information, 4+32+16 bytes.
Istrument data, 11 bytes:
data for register 0x20
data for register 0x23
data for register 0x40
data for register 0x43
data for register 0x60
data for register 0x63
data for register 0x80
data for register 0x83
data for register 0xe0
data for register 0xe3
data for register 0xc0
padding: 5 bytes of zeroes

How LordHoto's code loads data into chip (when enough bytes are skipped from start):
data for register 0xc0
data for register 0x20
data for register 0x40
data for register 0x60
data for register 0x80
data for register 0xe0
data for register 0x23
data for register 0x43
data for register 0x63
data for register 0x83
data for register 0xe3

So as you can see, both files contain data for same registers, just the order inside the file is different.

tashiy
Posts: 9
Joined: Tue Jun 19, 2012 9:17 am

Post by tashiy » Sun Jun 24, 2012 8:33 am

Thanks a lot for guiding me through the data jungle :)

In adplayer.cpp I only see the following register adresses:

Player::setupChannel
0xC0

Player::setupOperator
0x20
0x40
0x60
0x80
0xE0

Where are the others you listed?

However I looked at the adplug sources. I have not found mid.c. I also looked in prior versions. But in mid.cpp i found some chip register adresses:

Specially these lines looks interesting (341-379):

Code: Select all

void CmidPlayer::midi_fm_instrument(int voice, unsigned char *inst)
{
    if ((adlib_style&SIERRA_STYLE)!=0)
        midi_write_adlib(0xbd,0);  //just gotta make sure this happens..
                                      //'cause who knows when it'll be
                                      //reset otherwise.


    midi_write_adlib(0x20+adlib_opadd[voice],inst[0]);
    midi_write_adlib(0x23+adlib_opadd[voice],inst[1]);

    if (adlib_style & LUCAS_STYLE) {
        midi_write_adlib(0x43+adlib_opadd[voice],0x3f);
        if ((inst[10] & 1)==0)
            midi_write_adlib(0x40+adlib_opadd[voice],inst[2]);
        else
            midi_write_adlib(0x40+adlib_opadd[voice],0x3f);

    } else if ((adlib_style & SIERRA_STYLE) || (adlib_style & CMF_STYLE)) {
        midi_write_adlib(0x40+adlib_opadd[voice],inst[2]);
        midi_write_adlib(0x43+adlib_opadd[voice],inst[3]);

    } else {
        midi_write_adlib(0x40+adlib_opadd[voice],inst[2]);
        if ((inst[10] & 1)==0)
            midi_write_adlib(0x43+adlib_opadd[voice],inst[3]);
        else
            midi_write_adlib(0x43+adlib_opadd[voice],0);
    }
    midi_write_adlib(0x60+adlib_opadd[voice],inst[4]);
    midi_write_adlib(0x63+adlib_opadd[voice],inst[5]);
    midi_write_adlib(0x80+adlib_opadd[voice],inst[6]);
    midi_write_adlib(0x83+adlib_opadd[voice],inst[7]);
    midi_write_adlib(0xe0+adlib_opadd[voice],inst[8]);
    midi_write_adlib(0xe3+adlib_opadd[voice],inst[9]);

    midi_write_adlib(0xc0+voice,inst[10]);
}
So if I look from top to bottom I see this order:

0x20
0x23
0x40
0x43
0x60
0x63
0x80
0x83
0xe0
0xe3
0xc0

This looks exactly like the SBI Format. As you mention before.
jepael wrote: My guess is the internal order in myinsbank (array of instrument bytes) is same as in .sbi instrument file

jepael
Posts: 26
Joined: Sat Oct 25, 2008 8:16 pm

Post by jepael » Sun Jun 24, 2012 11:22 am

tashiy wrote:Thanks a lot for guiding me through the data jungle :)

In adplayer.cpp I only see the following register adresses:

Player::setupChannel
0xC0

Player::setupOperator
0x20
0x40
0x60
0x80
0xE0

Where are the others you listed?
An OPL channel consists of two operators. Player::setupChannel loads the 0xC0 register and calls Player::setupOperator twice, first with offset 0 to write parameters to first operator and then with offset 3 to write parameters to second operator.
tashiy wrote: However I looked at the adplug sources. I have not found mid.c. I also looked in prior versions. But in mid.cpp i found some chip register adresses:

This looks exactly like the SBI Format. As you mention before.
Sorry, I may have written .c instead of .cpp.
But anyway, I had my thoughts about this. One reason might be that different file formats use similar instrument formats to be compatible with other formats more easily.

tashiy
Posts: 9
Joined: Tue Jun 19, 2012 9:17 am

Post by tashiy » Sun Jun 24, 2012 5:35 pm

jepael wrote: An OPL channel consists of two operators. Player::setupChannel loads the 0xC0 register and calls Player::setupOperator twice, first with offset 0 to write parameters to first operator and then with offset 3 to write parameters to second operator.
Ah ok then all the 0x23,0x43,0x63,0x83,0xE3 are loaded when Player::setupOperator is called the second time.
I see this is how the FM Synth works, with operator and carrier. Where one oscillator modulates the other.
jepael wrote: One reason might be that different file formats use similar instrument formats to be compatible with other formats more easily.
Now the question is how i find the instruments in the .laa file. Cause there must me many more data in there. Like sequencing data (notes).

Sorry it must be a bit tendious for you to help someone that is not experienced in such way. I really appreciate to understand this technologie more.

jepael
Posts: 26
Joined: Sat Oct 25, 2008 8:16 pm

Post by jepael » Sun Jun 24, 2012 6:32 pm

tashiy wrote: Now the question is how i find the instruments in the .laa file. Cause there must me many more data in there. Like sequencing data (notes).
I think I already mentioned Adplug mid.cpp, starting from line 984, the instruments are loaded from the file.

Post Reply