Common YM2612 operations

This is a quick overview of which things you need to do with the YM2612 for common stuff like playing a note or setting the volume. Check the YM2612 reference for more details, and remember to respect the delays needed after each register write.

Load an instrument

The concept of "instrument" varies from driver to driver, but usually each driver's format is a dump of every affected YM2612 register (at least $B0 and $30+ to $8C+, usually a few more). Either way the basic procedure is as follows:

  1. Stop channel if needed (to avoid stray noises)
  2. Write all the relevant registers (according to the format)

Note that doing the above will likely reset the volume, so if you want to preserve it across instrument changes you will need to do the same value changes to TL as when you set the volume.

Key-on (start note)

  1. Key-off (register $28 with bits 7-4 clear)
  2. Set high byte of frequency (register $A4+)
  3. Set low byte of frequency (register $A0+)
  4. Key-on (register $28 with bits 7-4 set)

Key-off (stop note)

  1. Key-off (register $28 with bits 7-4 clear)

Pitch bend

  1. Set high byte of frequency (register $A4+)
  2. Set low byte of frequency (register $A0+)

Change volume

There isn't a "volume" register for each channel, but rather you have to rewrite the envelopes. In particular, the TL value of each output operator needs to be changed (not the modulator ones, as that'd change how it sounds instead).

The attenuation should be added to the operator's TL, e.g. if you want to attenuate by 3dB (0.75dB × 4) and the instrument's TL is 8, you'd have to write 8 + 4 = 12. And be careful to not go too quiet (if result is larger than 127 then just write 127 instead).

Change panning

Write to register $B4 with the following values in bits 7 and 6:

Stop channel

The operations below will quickly stop a FM channel's output. Note that this will overwrite part of the instrument's envelope, so if you want to reuse the instrument you will need to restore the values after the fact.

  1. Write $0F to all RR values (registers $80+, $84+, $88+, $8C+)
  2. Key-off (register $28 with bits 7-4 clear)

This is not instantaneous. It can take up to 128 YM2612 samples (about 2.4ms), which may as well be instantaneous to the ear but is not to the CPUs (it's 18432 cycles for 68000 or 8601.6 cycles for Z80). Don't do anything that relies on the envelope getting fully reset within the next sample because it won't work.

Playing PCM samples

Playing PCM over the YM2612 is a whole topic on its own. You have to enable DAC mode and then write samples the exact moment they should be output. At its core, it boils down to these steps:

  1. Writing $80 to register $2B to switch to DAC mode.
  2. Writing samples to register $2A at regular intervals.
  3. Writing $00 to register $2B when you're done.

How you approach the second step is up to you (some games cache samples in Z80 RAM and some don't, while some store the entire drumset in Z80 RAM and leave everything else to the 68000, some use YM2612 timer A and some use cycle counting, etc.). There are many trade-offs to each approach and ensuring you figure out a good balance is critical to playback quality.

You absolutely want to do this with the Z80 however. Don't do like Tiertex did in Strider II, where the entire game has to freeze to do PCM playback because the 68000 takes over the job.