This is an old revision of the document!
YM3812 or OPL2 is the “FM Operator type L (OPLII) synthesizer” used famously in the AdLib Music Synthesizer Card and Sound Blaster family of sound cards. It is a direct superset of (and shares a pin-out with) the YM3526 OPL chip, as used on the C64 FM sound expansion module. Its successor, the YMF262 or OPL3, supported 4-channel output and twice as many channels/operators and twice as many waveforms, as well as 4-op FM synthesis.
OPL Light/Light, aka OPLL, is a cost-reduced version of OPL2 that hard-codes 15 preset instruments and allows for 1 custom instrument to be created. The instrument ROM saves silicon die space compared to registers. One nagging problem with OPLL is that up until recently, there was no known way to extract the instrument ROM contents. Thus, emulation of preset instruments was based on empirical approximations.
There is at present no die image of YM2413. In the near future, whitequark will provide a die image suitable for RE. It is anticipated that the instruments ROM will be an implant ROM. This implies a delayering or staining to read out its contents.
TEST (0x0F) 76543210 |||||||\- DAC test enable (enables DAC output from the top 4 bits of address 0x10 (0x10 is normally the frequency LSB bits for channel 0) ||||||\-- ? |||||\--- ? ||||\---- This bit, if set, silences the FM sound output. How exactly is unknown. (On YM2151 this bit freezes the phase counters and lfo counters) |||\----- ? ||\------ ? |\------- ? \-------- ?
from Nuke.YKT's notes at https://pastebin.com/H5s4WQQ8 : YM2413 test data output format(!!not verified on hardware!!). /CS = 0 /WE = 1 A0 = 0 D0 and D1 serially output test data with internal clock rate Internal clock rate is MCLK/4 Clock 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 D0: P8 P7 P6 P5 P4 P3 P2 P1 P0 E6 E5 E4 E2 E1 E0 0 0 0 D1: C8 C7 C6 C5 C4 C3 C2 C1 C0 0 0 0 0 0 0 0 0 0
Px - Operator 0 phase generator output LSB bits Ex - Operator 17 envelope generator output Cx - Channel 6(?) output
TEST (0x0F) 76543210 |||||||\- if 1, Disables Car/Mod EG units, EG output is forced to 0 (max volume) ||||||\-- if 1, resets (and holds, while active) the Trem and Vib LFO counts to 0 |||||\--- if 1, resets (and holds, while active) the PG count for Car/Mod at 0 (this effectively silences the chip) ||||\---- if 1, the EG unit clock comes from VRC7 'D2' Pin, and the Trem and Vib LFO clock dividers are disabled, so they increment once per clock (x64 and x1024 their usual clock rates, respectively) |||\----- Does nothing? ||\------ Does nothing? |\------- Does nothing? \-------- Does nothing?
TODO (see https://pastebin.com/2gAwGmFT )
<nukeykt> VRC7 D0-D7 are bidirectional. Internally data bus connected to 8-bit multiplexer and with right combination of chip's pins it's possible to configure it. Internal instrument bus connected to this multiplexer, so it's possible to dump it
<nukeykt> For all configs A13(pin 2)=1, M2(pin 47)=0, P15=0, […] For config 0: /CS=1, /WR=1, A0=1, for config 1: /CS=1, /WR=1, A0=0, etc.
Fellow Yamaha enthusiast NukeYKT dumped the instrument and rhythm tables using the aforementioned debug mode. The tables are reproduced here:
/* Order of array = { modulator, carrier } */ typedef struct { Bit8u tl; Bit8u dc; Bit8u dm; Bit8u fb; Bit8u am[2]; Bit8u vib[2]; Bit8u et[2]; Bit8u ksr[2]; Bit8u multi[2]; Bit8u ksl[2]; Bit8u ar[2]; Bit8u dr[2]; Bit8u sl[2]; Bit8u rr[2]; } opll_patch_t; static const opll_patch_t patch_ds1001[opll_patch_max] = { { 0x05, 0x00, 0x00, 0x06,{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x01 },{ 0x00, 0x00 },{ 0x03, 0x01 },{ 0x00, 0x00 },{ 0x0e, 0x08 },{ 0x08, 0x01 },{ 0x04, 0x02 },{ 0x02, 0x07 } }, { 0x14, 0x00, 0x01, 0x05,{ 0x00, 0x00 },{ 0x00, 0x01 },{ 0x00, 0x00 },{ 0x01, 0x00 },{ 0x03, 0x01 },{ 0x00, 0x00 },{ 0x0d, 0x0f },{ 0x08, 0x06 },{ 0x02, 0x01 },{ 0x03, 0x02 } }, { 0x08, 0x00, 0x01, 0x00,{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x01, 0x01 },{ 0x01, 0x01 },{ 0x00, 0x00 },{ 0x0f, 0x0b },{ 0x0a, 0x02 },{ 0x02, 0x01 },{ 0x00, 0x02 } }, { 0x0c, 0x00, 0x00, 0x07,{ 0x00, 0x00 },{ 0x00, 0x01 },{ 0x01, 0x01 },{ 0x01, 0x00 },{ 0x01, 0x01 },{ 0x00, 0x00 },{ 0x0a, 0x06 },{ 0x08, 0x04 },{ 0x06, 0x02 },{ 0x01, 0x07 } }, { 0x1e, 0x00, 0x00, 0x06,{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x01, 0x01 },{ 0x01, 0x00 },{ 0x02, 0x01 },{ 0x00, 0x00 },{ 0x0e, 0x07 },{ 0x01, 0x06 },{ 0x00, 0x02 },{ 0x01, 0x08 } }, { 0x06, 0x00, 0x00, 0x00,{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x02, 0x01 },{ 0x00, 0x00 },{ 0x0a, 0x0e },{ 0x03, 0x02 },{ 0x0f, 0x0f },{ 0x04, 0x04 } }, { 0x1d, 0x00, 0x00, 0x07,{ 0x00, 0x00 },{ 0x00, 0x01 },{ 0x01, 0x01 },{ 0x00, 0x00 },{ 0x01, 0x01 },{ 0x00, 0x00 },{ 0x08, 0x08 },{ 0x02, 0x01 },{ 0x01, 0x00 },{ 0x01, 0x07 } }, { 0x22, 0x01, 0x00, 0x07,{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x01, 0x01 },{ 0x00, 0x00 },{ 0x03, 0x01 },{ 0x00, 0x00 },{ 0x0a, 0x07 },{ 0x02, 0x02 },{ 0x00, 0x01 },{ 0x01, 0x07 } }, { 0x25, 0x00, 0x00, 0x00,{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x01, 0x00 },{ 0x01, 0x01 },{ 0x05, 0x01 },{ 0x00, 0x00 },{ 0x04, 0x07 },{ 0x00, 0x03 },{ 0x07, 0x00 },{ 0x02, 0x01 } }, { 0x0f, 0x00, 0x01, 0x07,{ 0x01, 0x00 },{ 0x00, 0x00 },{ 0x01, 0x00 },{ 0x01, 0x00 },{ 0x05, 0x01 },{ 0x00, 0x00 },{ 0x0a, 0x0a },{ 0x08, 0x05 },{ 0x05, 0x00 },{ 0x01, 0x02 } }, { 0x24, 0x00, 0x00, 0x07,{ 0x00, 0x01 },{ 0x00, 0x01 },{ 0x00, 0x00 },{ 0x01, 0x00 },{ 0x07, 0x01 },{ 0x00, 0x00 },{ 0x0f, 0x0f },{ 0x08, 0x08 },{ 0x02, 0x01 },{ 0x02, 0x02 } }, { 0x11, 0x00, 0x00, 0x06,{ 0x00, 0x00 },{ 0x01, 0x00 },{ 0x01, 0x01 },{ 0x01, 0x00 },{ 0x01, 0x03 },{ 0x00, 0x00 },{ 0x06, 0x07 },{ 0x05, 0x04 },{ 0x01, 0x01 },{ 0x08, 0x06 } }, { 0x13, 0x00, 0x00, 0x05,{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x01, 0x02 },{ 0x03, 0x00 },{ 0x0c, 0x09 },{ 0x09, 0x05 },{ 0x00, 0x00 },{ 0x03, 0x02 } }, { 0x0c, 0x00, 0x00, 0x00,{ 0x00, 0x00 },{ 0x01, 0x01 },{ 0x01, 0x01 },{ 0x00, 0x00 },{ 0x01, 0x03 },{ 0x00, 0x00 },{ 0x09, 0x0c },{ 0x04, 0x00 },{ 0x03, 0x0f },{ 0x03, 0x06 } }, { 0x0d, 0x00, 0x00, 0x00,{ 0x00, 0x00 },{ 0x00, 0x01 },{ 0x01, 0x01 },{ 0x00, 0x01 },{ 0x01, 0x02 },{ 0x00, 0x00 },{ 0x0c, 0x0d },{ 0x01, 0x05 },{ 0x05, 0x00 },{ 0x06, 0x06 } }, /* Rhythm Patches: rows 1 and 4 are bass drum, 2 and 5 are Snare Drum & Hi-Hat, 3 and 6 are Tom and Top Cymbal */ { 0x18, 0x00, 0x01, 0x07,{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x01, 0x00 },{ 0x00, 0x00 },{ 0x0d, 0x00 },{ 0x0f, 0x00 },{ 0x06, 0x00 },{ 0x0a, 0x00 } }, { 0x00, 0x00, 0x00, 0x00,{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x01, 0x00 },{ 0x00, 0x00 },{ 0x0c, 0x00 },{ 0x08, 0x00 },{ 0x0a, 0x00 },{ 0x07, 0x00 } }, { 0x00, 0x00, 0x00, 0x00,{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x05, 0x00 },{ 0x00, 0x00 },{ 0x0f, 0x00 },{ 0x08, 0x00 },{ 0x05, 0x00 },{ 0x09, 0x00 } }, { 0x00, 0x00, 0x00, 0x00,{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x01 },{ 0x00, 0x00 },{ 0x00, 0x0f },{ 0x00, 0x08 },{ 0x00, 0x06 },{ 0x00, 0x0d } }, { 0x00, 0x00, 0x00, 0x00,{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x01 },{ 0x00, 0x00 },{ 0x00, 0x0d },{ 0x00, 0x08 },{ 0x00, 0x06 },{ 0x00, 0x08 } }, { 0x00, 0x00, 0x00, 0x00,{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x00 },{ 0x00, 0x01 },{ 0x00, 0x00 },{ 0x00, 0x0a },{ 0x00, 0x0a },{ 0x00, 0x05 },{ 0x00, 0x05 } } };
This translates into a patchset of:
0: user patch (irrelevant) 1: $03 $21 $05 $06 $E8 $81 $42 $27 2: $13 $41 $14 $0D $D8 $F6 $23 $12 3: $11 $11 $08 $08 $FA $B2 $20 $12 4: $31 $61 $0C $07 $A8 $64 $61 $27 5: $32 $21 $1E $06 $E1 $76 $01 $28 6: $02 $01 $06 $00 $A3 $E2 $F4 $F4 7: $21 $61 $1D $07 $82 $81 $11 $07 8: $23 $21 $22 $17 $A2 $72 $01 $17 9: $35 $11 $25 $00 $40 $73 $72 $01 A: $B5 $01 $0F $0F $A8 $A5 $51 $02 B: $17 $C1 $24 $07 $F8 $F8 $22 $12 C: $71 $23 $11 $06 $65 $74 $18 $16 D: $01 $02 $D3 $05 $C9 $95 $03 $02 E: $61 $63 $0C $00 $94 $C0 $33 $F6 F: $21 $72 $0D $00 $C1 $D5 $56 $06 Drums (silent due to no RO output pin(?) on VRC7, but present internally; these are likely shared with YM2413) BD : $01 $01 $18 $0F $DF $F8 $6A $6D SD/HH: $01 $01 $00 $00 $C8 $D8 $A7 $68 TM/TC: $05 $01 $00 $00 $F8 $AA $59 $55
byte 0: 76543210 ||||\\\\- MULT (Mod) |||\----- Key Scale Rate enable (Mod) ||\------ Env Gen Type (0 = percussion/auto-key-off, 1 = sustain/normal) (Mod) |\------- Vibrato enable (Mod) \-------- Tremolo enable (Mod) byte 1: 76543210 ||||\\\\- MULT (Car) |||\----- Key Scale Rate enable (Car) ||\------ Env Gen Type (0 = percussion/auto-key-off, 1 = sustain/normal) (Car) |\------- Vibrato enable (Car) \-------- Tremolo enable (Car) byte 2: 76543210 ||\\\\\\- Total Level, inverted (Mod) \\------- Key Scale Level (Mod) byte 3: 76543210 |||||\\\- Feedback level (Mod) ||||\---- WF select (sine vs halfsine, Mod) |||\----- WF select (sine vs halfsine, Car) ||\------ Unused \\------- Key Scale Level (Car) byte 4: 76543210 ||||\\\\- Decay Rate, inverted (Mod) \\\\----- Attack Rate, inverted (Mod) byte 5: 76543210 ||||\\\\- Decay Rate, inverted (Car) \\\\----- Attack Rate, inverted (Car) byte 6: 76543210 ||||\\\\- Release Rate, inverted (Mod) \\\\----- Sustain Level, inverted (Mod) byte 7: 76543210 ||||\\\\- Release Rate, inverted (Car) \\\\----- Sustain Level, inverted (Car)