HTML Design by Ruslan Gustokashin, LHS Network
INTRODUCTION
The chip I am going to describe is getting more and more common, but
programming information is still scarce, so I have decided to fill in this
gap. All information contained in this file is a result of my experience in
Adlib programming, research (read: reverse engineering) and finally of my
effort to write down everything necessary to understand and use this piece
of hardware. No official sources (i.e. development kits, books about this
topic, etc.) were available to me except:
The information below is a combination of known features of Adlib (alias Yamaha YM 3812/OPL2) and my own uncountable experiments and failures, which brought out a lot of important details you have to know about the chip.
As far as I know, there are four major sound cards based on OPL3 chip:
Note: I assume some knowledge of FM music programming (mainly Adlib FM synthesizer) in this manual. If you are new to this topic I recommend you try Adlib first before going higher. Anyway, OPL3 is a direct descendant of OPL2 (what a surprise), so most features of OPL2 are also present on OPL3.
So let's clear some facts. First, OPL3 has only thirty-six (36) operators which can be combined in several ways:
From the table above you can see that not all channels can be used in four- operator (4-OP) mode -- only a part of the synthesizer is really capable of making 4-OP sounds -- the rest uses traditional two-operator (2-OP) mode.
Second, the manual states this card is capable of "stereo" music. Yes, the quotes are necessary, because the stereo capabilities are very limited. You are given ability to control output going to left or right channel by turning it on and off. That's all. So the sound can flow from very left side, center and very right side. No sound panning, no special stereo effects. :-(
Well, flaming apart, back to the main topic.
+-------------+ | Operator 1 |----------+ +-------------+ | +-----------+ +--->| Output | +-------------+ | +-----------+ | Operator 2 |----------+ +-------------+
+------------+ +------------+ | Operator 1 +-------->| Operator 2 +--------> Output |(Modulator) | | (Carrier) | +------------+ +------------+
--------- --------- --------- --------- | Op. 1 |--->| Op. 2 |--->| Op. 3 |--->| Op. 4 |---> Output --------- --------- --------- ---------
+-------+ | Op. 1 +-----------------------------------+ +-------+ | | +-------+ +-------+ +-------+ | | Op. 2 +----->| Op. 3 +----->| Op. 4 +-----+------> Output +-------+ +-------+ +-------+
+-------+ +-------+ | Op. 1 +----->| Op. 2 +-----+ +-------+ +-------+ | +-------> Output +-------+ +-------+ | | Op. 3 |----->| Op. 4 +-----+ +-------+ +-------+
+-------+ | Op. 1 +--------------------+ +-------+ | | +-------+ +-------+ | | Op. 2 +----->| Op. 3 +-----+------> Output +-------+ +-------+ | | +-------+ | | Op. 4 +--------------------+ +-------+
The only way I think this can be written is a math formula. Symbol + (plus) means additive synthesis, and * (asterisk) means frequency modulation (Op1 * Op2 means operator 1 modulates operator 2, not vice versa). Here they are:
This mode is identical with that of OPL2. For more details see ADLIB.DOC.
Sound Blaster Pro II 220h or 240h (selectable), also 388h
Adlib Gold 388h
Pro Audio Spectrum Plus/16 ? (if you have a PAS you should know it)
The chip occupies four I/O addresses:
base+0 Primary index register (write), Status register (read)
base+1 Primary data register (write-only)
base+2 Secondary index register (write)
base+3 Secondary data register (write-only)
Unlike Adlib (OPL2), OPL3 doesn't need delay between register writes. With OPL2 you had to wait 3.3 æs after index register write and another 23 æs after data register write. On the contrary OPL3 doesn't need (almost) any delay after index register write and only 0.28 æs after data register write. This means you can neglect the delays and slightly speed up your music driver. But using reasonable delays will certainly do no harm.
(The register map is nearly the same so I dared to copy it from ADLIB.DOC.)
Status Register (base+0):
D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 |
IRQFlag | T1Flag | T2Flag |
Data Registers (base+1, base+3):
REG | D7 | D6 | D4 | D3 | D2 | D1 | D0 | |
WSEnable | ||||||||
04* | IRQReset | T1Mask | T2Mask | T2 Start | T1 Start | |||
04** | 4-OP B-E | 4-OP A-D | 4-OP 9-C | 4-OP 2-5 | 4-OP 1-4 | 4-OP 0-3 | ||
05** | OPL3 | |||||||
08 | CSW | NOTE-SEL | ||||||
20-35 | Tremolo | Vibrato | Sustain | KSR | Frequency Multiplication Factor | |||
40-55 | Key Scale Level | Output Level | ||||||
60-75 | Attack Rate | Decay Rate | ||||||
80-95 | Sustain Level | Release Rate | ||||||
A0-A8 | Frequency Number ( Lower 8 bits ) | |||||||
B0-B8 | KEY-ON | Block Number | F-Num (hi bits) | |||||
BD | Trem Dep | Vibr Dep | PercMode | BD On | SD On | TT On | CY On | HH On |
C0-C8 | Right | Left | FeedBack Modulation Factor | SynthTyp | ||||
E0-F5 | Waveform Select |
Op. | Set/Offset | Op. | Set/Offset |
0 | 0/00 | 18 | 1/00 |
1 | 0/01 | 19 | 1/01 |
2 | 0/02 | 20 | 1/02 |
3 | 0/03 | 21 | 1/03 |
4 | 0/04 | 22 | 1/04 |
5 | 0/05 | 23 | 1/05 |
6 | 0/08 | 24 | 1/08 |
7 | 0/09 | 25 | 1/09 |
8 | 0/0A | 26 | 1/0A |
9 | 0/0B | 27 | 1/0B |
10 | 0/0C | 28 | 1/0C |
11 | 0/0D | 29 | 1/0D |
12 | 0/10 | 30 | 1/10 |
13 | 0/11 | 31 | 1/11 |
14 | 0/12 | 32 | 1/12 |
15 | 0/13 | 33 | 1/13 |
16 | 0/14 | 34 | 1/14 |
17 | 0/15 | 35 | 1/15 |
Channel |
|
||||||||||||||||||||||||||||||||||||||
|
|
Channel | 0 | 1 | 2 | 3 | 4 | 5 | BD | SD | TT | CY | HH | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 |
Operator 1 | 0 | 1 | 2 | 6 | 7 | 8 | 12 | 16 | 14 | 17 | 13 | 18 | 19 | 20 | 24 | 25 | 26 | 30 | 31 | 32 |
Operator 2 | 3 | 4 | 5 | 9 | 10 | 11 | 15 | 21 | 22 | 23 | 27 | 28 | 29 | 33 | 34 | 35 |
Channel | 0 | 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 15 | 16 | 17 |
Operator 1 | 0 | 1 | 2 | 12 | 13 | 14 | 18 | 19 | 20 | 30 | 31 | 32 |
Operator 2 | 3 | 4 | 5 | 15 | 16 | 17 | 21 | 22 | 23 | 33 | 34 | 35 |
Operator 3 | 6 | 7 | 8 | 24 | 25 | 26 | ||||||
Operator 4 | 9 | 10 | 11 | 27 | 28 | 29 |
Channels 3, 4, 5 and 12, 13, 14 can't be used separately because their operators became part of channels 0, 1, 2 and 9, 10, 11 respectively. For instance a four-operator channel 1 consists of two two-operator channels number 1 and 4. (The second 2-OP channel number is always the first 2-OP channel number plus three.)
OPL3 allows you to enable/disable 4-OP mode separately for any of channels 0, 1, 2, 9, 10 and 11 (see register 104h in the reference below). This means for instance when you switch only channel 2 into 4-OP mode, channels number 0, 1, 3, 4, 6, 7, 8, 9, etc. will be still independent 2-OP channels.
Channels 6, 7, 8 and 15, 16, 17 are always two-operator ones. They can't be grouped to form four-operator channels.
Channel | 0 | 1 | 2 | BD | SD | TT | CY | HH | 9 | 10 | 11 | 15 | 16 | 17 |
Operator 1 | 0 | 1 | 2 | 12 | 16 | 14 | 17 | 13 | 18 | 19 | 20 | 30 | 31 | 32 |
Operator 2 | 3 | 4 | 5 | 15 | 21 | 22 | 23 | 33 | 34 | 35 | ||||
Operator 3 | 6 | 7 | 8 | 24 | 25 | 26 | ||||||||
Operator 4 | 9 | 10 | 11 | 27 | 28 | 29 |
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
IRQ | T1 | T2 | Not used |
Timer interrupts are not wired to any IRQ (why??). The timers can be used to detect the OPL2/OPL3 chip (see Appendix B).
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
WSE | Test Register |
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
Rst | T1M | T2M | T2S | T1S |
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
ChB | ChA | Ch9 | Ch2 | Ch1 | Ch0 |
If reset to zero, OPL3 can produce 18 two-operator sounds at a time.
If nonzero, OPL3 produces four-operator sound in appropriate channel pair.
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
OPL |
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
CSW | N-S |
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
Tre | Vib | Sus | KSR | Multiplication |
MULTI | Factor |
0 | 1/2 |
1 | 1 |
2 | 2 |
3 | 3 |
4 | 4 |
5 | 5 |
6 | 6 |
7 | 7 |
8 | 8 |
9 | 9 |
10 | 10 |
11 | 10 |
12 | 12 |
13 | 12 |
14 | 15 |
15 | 15 |
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
KSL | Output Level |
KSL | Attenuation |
0 | - |
1 | 1.5 dB/oct |
2 | 3.0 dB/oct |
3 | 6.0 dB/oct |
Mode | Op 1 | Op 2 | Op 3 | Op 4 |
AM | + | + | N/A | N/A |
FM | - | + | N/A | N/A |
FM-FM | - | - | - | + |
AM-FM | + | - | - | + |
FM-AM | - | + | - | + |
AM-AM | + | - | + | + |
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
Attack Rate | Decay Rate |
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
Sustain Level | Release Rate |
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
KEY | Block Num. | Freq |
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
Tre | Vib | Per | BD | SD | TT | CY | HH |
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
R | L | FeedBack | Syn |
FeedBack | Factor |
0 | 0 |
1 | y/16 |
2 | y/8 |
3 | y/4 |
4 | y/2 |
5 | y |
6 | 2y |
7 | 4y |
Op 1&2 | Op 3&4 | Type |
0 | NONE | FM |
1 | NONE | AM |
0 | 0 | FM-FM |
1 | 0 | AM-FM |
0 | 1 | FM-AM |
1 | 1 | AM-AM |
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
WaveForm |
--------------------------------- cut here ---------------------------------
// I prefer using these Assembler-like types typedef unsigned int WORD; typedef unsigned char BYTE; /* * FM Synthesizer base port. SB Pro II - 0x220, Adlib 0x388 */ WORD FMport = 0x220; /* * Enables OPL3 extensions. */ WORD OPL3 = 1; /* * Direct write to any Adlib/SB Pro II FM synthetiser register. * reg - register number (range 0x001-0x0F5 and 0x101-0x1F5). When high byte * of reg is zero, data go to port FMport, otherwise to FMport+2 * data - register value to be written */ BYTE FMwriteReg(WORD reg, BYTE data) { asm { mov dx,FMport mov ax,reg or ah,ah // high byte is nonzero -- write to port base+2 jz out1 inc dx inc dx } out1: asm { out dx,al mov cx,6 } loop1:asm { // delay between writes in al,dx loop loop1 inc dx mov al,data out dx,al dec dx mov cx,36 } loop2:asm { // delay after data write in al,dx loop loop2 } return _AL; } /* * Write to an operator pair. To be used for register bases of 0x20, 0x40, * 0x60, 0x80 and 0xE0. */ void FMwriteChannel(BYTE regbase, BYTE channel, BYTE data1, BYTE data2) { static BYTE adlib_op[] = {0, 1, 2, 8, 9, 10, 16, 17, 18}; static BYTE sbpro_op[] = { 0, 1, 2, 6, 7, 8, 12, 13, 14, 18, 19, 20, 24, 25, 26, 30, 31, 32}; static WORD rg[] = {0x000,0x001,0x002,0x003,0x004,0x005, 0x008,0x009,0x00A,0x00B,0x00C,0x00D, 0x010,0x011,0x012,0x013,0x014,0x015, 0x100,0x101,0x102,0x103,0x104,0x105, 0x108,0x109,0x10A,0x10B,0x10C,0x10D, 0x110,0x111,0x112,0x113,0x114,0x115}; if (OPL3) { register WORD reg = sbpro_op[channel]; FMwriteReg(rg[reg]+regbase, data1); FMwriteReg(rg[reg+3]+regbase, data2); } else { register WORD reg = regbase+adlib_op[channel]; FMwriteReg(reg, data1); FMwriteReg(reg+3, data2); } } /* * Write to channel a single value. To be used for register bases of * 0xA0, 0xB0 and 0xC0. */ void FMwriteValue(BYTE regbase, BYTE channel, BYTE value) { static WORD ch[] = {0x000,0x001,0x002,0x003,0x004,0x005,0x006,0x007,0x008, 0x100,0x101,0x102,0x103,0x104,0x105,0x106,0x107,0x108}; register WORD chan; if (OPL3) chan = ch[channel]; else chan = channel; FMwriteReg(regbase + chan, value); } --------------------------------- cut here ---------------------------------
Another possible detection method for distinguishing between SB Pro I and SB Pro II would be to try to detect OPL2 at I/O port base+0 and then at port base+2. The first test should succeed and the second should fail if OPL3 is present. (Remember: SB Pro I contains twin OPL2 chips at addresses base+0 and base+2, while SB Pro II contains one OPL3 chip at I/O address base+0 thru base+3).
The variable has this format: