3rdparty/ymfm/GeneralInfo.md
The ymfm emulator ws written from the ground-up using the analysis and deduction by Nemesis as a starting point, particularly in this thread.
The core assumption is that these details apply to all FM variants unless otherwise proven incorrect.
The fine details of this implementation have also been cross-checked against Nemesis' implementation in his Exodus emulator, as well as Alexey Khokholov's "Nuked" implementations based off die shots.
Operator and channel summing/mixing code for OPM and OPN is largely based off of research done by David Viens and Hubert Lamontagne.
The Yamaha FM chips can be broadly categoried into families:
Additionally, several lesser-documented variants exist exclusively in the employ of Yamaha synthesizers:
All of these families are very closely related, and the ymfm engine is designed to be universal to work across all of these families.
Of course, each variant has its own register maps, features, and implementation details which need to be sorted out. Thus, each significant variant listed above is represented by a register class. The register class contains:
This history outlines the progress of adding/removing features across the three main families (OPM, OPN, OPL):
OPM started it all off, featuring:
OPM -> OPN changes:
OPN -> OPNA changes:
OPNA -> OPL changes:
OPL -> OPL2 changes:
OPL2 -> OPLL changes:
OPL2 -> OPL3 changes:
The polyphony of a given chip is determined by the number of channels it supports. This number ranges from as low as 3 to as high as 18. Each channel has either 2 or 4 operators that can be combined in a myriad of ways. On most chips the number of operators per channel is fixed; however, some later OPL chips allow this to be toggled between 2 and 4 at runtime.
The base ymfm engine class maintains an array of channels and operators, while the relationship between the two is described by the register class.
Registers on the Yamaha chips are generally write-only, and can be divided into three distinct categories:
For maximum flexibility, most parameters can be configured at the operator level, with channel-level registers controlling details such as how to combine the operators into the final output. System-wide registers are used to control chip-wide modes and manage onboard timer functions.
Note that since registers are write-only, some ymfm register classes will use "holes" in the register space to store additional values that may be needed.
Most of the computations of the FM engines are done in terms of attenuation, and thus are logarithmic in nature. The maximum resolution used internally is 12 bits, as returned by the sin table:
| Bit | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| dB | -96 | -48 | -24 | -12 | -6 | -3 | -1.5 | -0.75 | -0.375 | -0.1875 | -0.09375 | -0.046875 |
The envelope generator internally uses 10 bits:
| Bit | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|---|---|---|---|---|---|---|---|---|---|---|
| dB | -48 | -24 | -12 | -6 | -3 | -1.5 | -0.75 | -0.375 | -0.1875 | -0.09375 |
Total level for operators is usually represented by 7 bits:
| Bit | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|---|---|---|---|---|---|---|---|
| dB | -48 | -24 | -12 | -6 | -3 | -1.5 | -0.75 |
Sustain level in the envelope generator is usually represented by 4 bits:
| Bit | 3 | 2 | 1 | 0 |
|---|---|---|---|---|
| dB | -24 | -12 | -6 | -3 |
Generically, all chips (except OPLL) support two timers that can be programmed to fire and signal IRQs. These timers also set bits in the status register. The behavior of these bits is shared across all implementations, even if the exact bit positions shift (this is controlled by constants in the registers class).
In addition, several chips incorporate ADPCM decoders which also may set bits in the same status register.
For this reason, it is possible to control various bits in the status register via the set_reset_status() function directly.
Any active bits that are set and which are not masked (mask is controlled by set_irq_mask()), lead to an IRQ being signalled.
Thus, it is possible for the chip-specific implementations to set the mask and control the status register bits such that IRQs are signalled via the same mechanism as timer signals.
In addition, the OPM and OPN families have a "busy" flag, which is set after each write, indicating that another write should not be performed. Historically, the duration of this flag was constant and had nothing to do with the internals of the chip. However, since the details can potentially vary chip-to-chip, it is the chip's responsibility to insert the busy flag into the status before returning it to the caller.
Each of the Yamaha chips works by cycling through all operators one at a time. Thus, the effective output rate of the chips is related to the input clock divided by the number of operators. In addition, the input clock is prescaled by an amount. Generally, this is a fixed value, though some early OPN chips allow this to be selected at runtime from a small number of values.
One major difference between OPM and later families is in how frequencies are specified. OPM specifies frequency via a 3-bit 'block' (aka octave), combined with a 4-bit 'key code' (note number) and a 6-bit 'key fraction'. The key code and fraction are converted on the chip into an x.11 fixed-point value and then shifted by the block to produce the final step value for the phase.
Later families, on the other hand, specify frequencies via a 3-bit 'block' just as on OPM, but combined with a 9-12-bit 'frequency number' or 'fnum', which is directly shifted by the block to produce the step value. So essentially, later chips make the user do the conversion from note value to phase increment, while OPM is programmed in a more 'musical' way, specifying notes and cents.
Internally, this is abstracted away into a 'block_freq' value, which is a 16-bit value containing the block and frequency info concatenated together as follows:
OPM: [3-bit block]:[4-bit keycode]:[6-bit fraction] = 13 bits total
OPZ: [3-bit block]:[12-bit fnum] = 15 bits total
OPN: [3-bit block]:[11-bit fnum] 0 = 15 bits total
OPL: [3-bit block]:[10-bit fnum]:00 = 15 bits total
OPLL: [3-bit block]:[ 9-bit fnum]:000 = 15 bits total
The register classes handle the raw format directly and convert it into a phase increment which can be used by the generic engine.
The LFO engines are different in several key ways. The OPM LFO engine is fairly intricate. It has a 4.4 floating-point rate which allows for a huge range of frequencies, and can select between four different waveforms (sawtooth, square, triangle, or noise). Separate 7-bit depth controls for AM and PM control the amount of modulation applied in each case. This global LFO value is then further controlled at the channel level by a 2-bit AM sensitivity and a 3-bit PM sensitivity, and each operator has a 1-bit AM on/off switch.
For OPN the LFO engine was removed entirely, but a limited version was put back in OPNA and later chips. This stripped-down version offered only a 3-bit rate setting (versus the 4.4 floating-point rate in OPN), and no global depth control. It did bring back the channel-level sensitivity controls and the operator-level on/off control.
For OPL, the LFO is simplified again, with AM and PM running at fixed frequencies, and simple enable flags at the operator level for each controlling their application.
The table below provides some high level functional differences between the differnet families:
| subfamily: | OPM | OPN | OPNA | OPL | OPL2 | OPLL | OPL3 |
|---|---|---|---|---|---|---|---|
| outputs: | 2 | 1 | 2 | 1 | 1 | 1 | 4 |
| channels: | 8 | 3 | 6 | 9 | 9 | 9 | 18 |
| operators: | 32 | 12 | 24 | 18 | 18 | 18 | 36 |
| waveforms: | 1 | 1 | 1 | 1 | 4 | 2 | 8 |
| instruments: | no | no | no | yes | yes | yes | yes |
| ryhthm: | no | no | no | no | no | yes | no |
| dynamic ops: | no | no | no | no | no | no | yes |
| prescale: | 2 | 2/3/6 | 2/3/6 | 4 | 4 | 4 | 8 |
| EG divider: | 3 | 3 | 3 | 1 | 1 | 1 | 1 |
| EG DP: | no | no | no | no | no | yes | no |
| EG SSG: | no | yes | yes | no | no | no | no |
| mod delay: | no | no | no | yes | yes | yes? | no |
| CSM: | yes | ch 2 | ch 2 | yes | yes | yes | no |
| LFO: | yes | no | yes | yes | yes | yes | yes |
| noise: | yes | no | no | no | no | no | no |
While OPM is its own thing, the OPN and OPL families have quite a few specific implementations, with many differing details beyond the core FM parts. Here are some details on the OPN family:
| chip ID: | YM2203 | YM2608 | YMF288 | YM2610 | YM2610B | YM2612 | YM3438 | YMF276 |
|---|---|---|---|---|---|---|---|---|
| aka: | OPN | OPNA | OPN3L | OPNB | OPNB2 | OPN2 | OPN2C | OPN2L |
| FM: | 3 | 6 | 6 | 4 | 6 | 6 | 6 | 6 |
| AY-8910: | 3 | 1 | 1 | 1 | 1 | - | - | - |
| ADPCM-A: | - | 6 int | 6 int | 6 ext | 6 ext | - | - | - |
| ADPCM-B: | - | 1 ext | - | 1 ext | 1 ext | - | - | - |
| DAC: | no | no | no | no | no | yes | yes | yes |
| output: | 10.3fp | 16-bit | 16-bit | 16-bit | 16-bit | 9-bit | 9-bit | 16-bit |
| summing: | adder | adder | adder | adder | adder | muxer | muxer | adder |
OPL has a similar trove of chip variants:
| chip ID: | YM3526 | Y8950 | YM3812 | YM2413 | YMF262 | YMF289B | YMF278B |
|---|---|---|---|---|---|---|---|
| aka: | OPL | MSX-AUDIO | OPL2 | OPLL | OPL3 | OPL3L | OPL4 |
| FM: | 9 | 9 | 9 | 9 | 18 | 18 | 18 |
| ADPCM-B: | - | 1 ext | - | - | - | - | - |
| wavetable: | - | - | - | - | - | - | 24 |
| instruments: | no | no | no | yes | no | no | no |
| output: | 10.3fp | 10.3fp | 10.3fp | 9-bit | 16-bit | 16-bit | 16-bit |
| summing: | adder | adder | adder | muxer | adder | adder | adder |
There are several close variants of the YM2413 with different sets of built-in instruments. These include the YM2423, YMF281, and DS1001 (aka Konami VRC7).