Alright, I think I'm finished poring over the disassemblies for now. I'm still waiting for the hardware, but I think I've learned a lot about it from just inspecting the Windows FM drivers so far. I'll leave what I know at this point here, and will get back to it when I have my hands on the actual machine. Some of this is going to be about the hardware itself, and some of it will be just about the MIDI driver.
1. ESSFM.DRV 4.0.950 for ES1688 (source: my Windows 95 CD, CRC BCE1A309)
2. ESFM.DRV 4.04.00.1173 for ES1869 (source: here, CRC32 8F7EB956)
ESSFM.DRV was disappointing. It looked like a very minimal OPL3 and OPL2 compatible MIDI driver. The chip is in the flat melodic mode, so it has 9 or 18 2-op channels available.
Patches are in an embedded resource in the executable. Each patch is 28 bytes:
- $00 - operator 0 opl3 $20
- $01 - operator 0 opl3 $40
- $02 - operator 0 opl3 $60
- $03 - operator 0 opl3 $80
- $04 - operator 0 opl3 $E0
- $05 - operator 1 opl3 $20
- $06 - operator 1 opl3 $40
- $07 - operator 1 opl3 $60
- $08 - operator 1 opl3 $80
- $09 - operator 1 opl3 $E0
- $0A-$13 - $00, presumably for an unused 4-op idea
- $14 - $00, opl3 $A0 (replaced to be used for pitch)
- $15 - $00, unused
- $16 - $10, opl3 $B0 (replaced to be used for pitch)
- $17 - $00, unused
- $18 - voice opl3 $C0 (pan will be adjusted)
- $19 - $00, unused
- $1A - $02, unused
- $1B - $00, unused
There is enough data for 256 patches. The first 128 are the regular instruments. The next 53 are percussion patches for channel 10 (starting at note 35). Each percussion note has a corresponding MIDI note pitch in a table in the first code segment at $0128 (2 byte entries: note pitch, then patch number, though the patch numbers just go from 0-53 anyway).
The driver responds to pitch bend, and a few controllers:
- 7 Volume (coarse)
- 8 Balance (coarse) - same as pan
- 10 Pan (coarse) - hardpans with $30-50 in the centre
- 123 All notes off (124-127 also trigger this)
Anyhow, that's a fairly complete description of what I found in ESSFM.DRV. When I was looking at some of the INF files with other ESS driver packages, I notice some of the later ones refer to this driver as something like "internal OPL2/OPL3 synthesis", rather than calling it "ESSFM" anymore, I think maybe because they'd called their newer enhanced version "ESFM" and wanted to reduce confusion about that.
ESFM.DRV was much more interesting. This is definitely not operating in OPL3 compatibility mode.
From the way it operates, it appears that the "20 voices" it mentions in its data sheet may all be 4-op voices? What I found indicates 18 voices, but 4-ops each (with some weirdness in the last 2 channels that might account for the other 2). So... if that's actually what this is, that's kind of incredible. It's not just an OPL3 with 2 more 2-op voices... I think it's more like some double OPL3 with 18 full 4-op voices!
In native mode the 4 registers seem to be reconfigured:
- FM+0 - Read between other register writes for an appropriate delay, but otherwise should not be written to. (The data sheet claims that any write here will switch it into OPL3 emulation mode.)
- FM+1 - Write data here.
- FM+2 - Write low index here.
- FM+3 - Write high index here.
Interfacing with this has a routine that does the following:
- Write low index to FM+2
- Read FM+0 2 times to delay
- Write high index to FM+3
- Read FM+0 6 times to delay
- Write value to FM+1
- Read FM+0 6 times to delay
So this interface is similar to OPL3 where you write an index to an internal register that you want to write, then send the data to it, with some delays in between, except the index is now a 16-bit value.
The voices and operators themselves, however, are arranged in a very flat, uniform manner. Registers $000-240 are divided into 8 registers per operator, 32 per voice.
- Operator + 0 - OPL3 $20
- Operator + 1 - OPL3 $40
- Operator + 2 - OPL3 $50
- Operator + 3 - OPL3 $80
- Operator + 4 - OPL3 $A0
- Operator + 5 - OPL3 $B0, but without the key-on bit.
- Operator + 6 - OPL3 $C0
- Operator + 7 - OPL3 $E0, but patches seem to use the upper bits?
So $00-$1F is 4 operators for voice 0. $20-3F is voice 1, etc.
For turning the voices on and off there is a dedicated set of registers. Write 1 to key on, 0 to key off. $240-24F each applies to voices 0-15.
Voice 16 and 17 seem to have two registers each for this. I don't really understand what this is for, they might be a special percussion device or something. So voice 16 gets $250 and $251, and voice 17 gets $252 and $253. At least, that's what this driver does. I'll need to investigate this more when I have the hardware. (My tentative guess is that the last two voices have their note-on split as 2-ops each, allowing them to be used as 4 2-op voices.)
This responds to more controllers than the other one:
- 6 Data entry (coarse) - only used for pitch wheel sensitivity via registered parameter 0000 (see below)
- 7 Volume (coarse) - a value of 0 will force all operator outputs attenuation to 63, otherwise it applies a per-operator attenuation described below.
- 8 Balance (coarse) - same as pan
- 10 Pan (coarse) - hardpans with $30-50 in the centre
- 11 Expression (coarse) - affects the strength of some operators according to patch data
- 64 Hold pedal
- 98-99 Non-registered parameter - only used to cancel selection of registered parameter 0000
- 100-101 Registered parameter - can be used to select the pitch wheel sensitivity parameter 0000
- 120 All sound off
- 121 All controllers off
- 124,125 Omni mode off/on - seems to just stop all playing notes if not held by the hold pedal
- 127 Poly operation - just does same as all sound off
Finally the patch data. This is also contained in a resource in the executable. This file starts with 256 2-byte pointer offsets (little-endian) to patches placed later in the resource. The first 128 correspond to the general MIDI instruments, and the next 128 correspond to each possible percussion note on channel 10. A pointer of $0000 indicates an empty instrument.
Patches themselves follow the pointer table at $0200. Each patch is 28 or 56 bytes. The 56 byte patches are a double patch, using 2 voices at once.
- $00 - bit 0 = patch allowed on channel 16,17? bit 1-2 = patch type (see below). bits 4-7 can indicate a fixed pitch for each operator.
- $01 - $00 unused
- $02 - $00 unused
- $03 - relative velocity for each operator
- $04 - operator 0 OPL3 $20
- $05 - operator 0 OPL3 $40 but output level may be adjusted based on $03
- $06 - operator 0 OPL3 $60
- $07 - operator 0 OPL3 $80
- $08 - operator 0 OPL3 $A0 relative: bits 2-6 signed detune, bits 0-1 transpose low. fixed: direct value.
- $09 - operator 0 OPL3 $B0 relative: bits 0-4 transpose high, signed. 5-7 signed octave transpose. fixed: direct value.
- $0A - operator 0 OPL3 $C0 but the left/right bits are replaced by the channel's pan (if they aren't 0,0)
- $0B - operator 0 OPL3 $E0 but seems to use the upper bits too? Not sure what for.
- $0C-13 - operator 1
- $14-1B - operator 2
- $1C-23 - operator 3
- $24-47 - second voice (optional)
So these are pretty interesting patches, and it indicates that each operator has its own pitch control rather than combining them in pairs like OPL3/OPL2 did. I'm not entirely sure where the FM algorithm selection bits are placed, since these are a bit reordered vs OPL3. There might even be extra algorithms available?
Patch byte $00 bits 1-2 indicate 3 kinds of patches: 0 = 1 voice, 1 = 2 voice but the second will be dropped if out of voices, and 2 = 2 voices but the second must always play. A value of 3 is invalid and will skip the note.
Patch byte $00 bit 0 seems to indicate whether or not the patch may use voice 16 or 17, but I don't understand how these two voices are supposed to work, or why they have 2 note-on registers each.
Patch byte $00 bits 4-7 each indicate that an operator might have a fixed pitch instead of a MIDI note relative pitch. Bit 4 for operator 0, bit 5 for operator 1, etc. If set these sill use the values in the patch directly, and will not be affected by the pitch wheel.
Patch byte $03 contains 4 2-bit values, each is a different mode for adjusting the output attenuation of the operator. Bits 0-1 for operator 0, bits 2-3 for operator 1, etc. This lets you choose individually which operators are controlled by note velocity (and it also applies to the same adjustments from the volume controller and expression controller). On a normal instrument you want attenuation for velocity on any output operator, but modulating operators you probably wouldn't unless you want the timbre to dull as the velocity drops. These four modes (0, 1 light, 2 medium, 3 strong but with a taper) all calculate a value to add to the logarithmic attenuation parameter.
- 0 - 0
- 1 - (127-v)/16
- 2 - (127-v)/8
- 3 - (v>=64)?((127-v)/4):(((63-v)/2)+16)
Note velocity, volume control, and expression each separately apply this forumula and get added to the base output attenuation, which clamps at 63. An exception is made for volume control of 0, which forces all operators' attenuation to 63.
Okay, I think that's everything I know from the drivers. There seem to be a lot of versions of both of these drivers, but hopefully other versions will be similar. The implication that it has 72 or maybe 80 operators instead of just 36 is pretty radical! Am excited to get to try out the real thing once it gets here.