📄 ym2413.c
字号:
/*
Copyright (C) 2000 Charles Mac Donald
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
YM2413 (OPLL) emulator
by Charles Mac Donald
E-mail: cgfm2@hooked.net
WWW: http://cgfm2.emuviews.com
Change log:
[061300]
- Fixed bug where channel numbers larger than 9 could be written to
register groups $10-18, $20-28, $30-38.
[060800]
- Now the YM2413 chip number is passed to the OPL_WRITE macro,
and the user instrument data is stored in the YM2413 context,
both for multiple YM2413 emulation.
[060100]
- Added alternate instrument table taken from Allegro's 'fm_inst.h'.
- Changed source so it can compile seperately from SMS Plus.
- Added 'ym2413_reset' function and changed ym2413_init.
Known issues:
- The sustain on/off flag (bit 5 of register group $20-28) is not
emulated. According to the manual, the release rate is set to
five when this bit is set.
- The table of fixed instrument values probably need to be compared
against a real YM2413, so they can be hand-tuned.
- The rhythm instruments sound good, but are too loud.
The same settings are used for channels 7, 8, 9, which can't be right.
I based the YM2413 emulation on the following documents. If you want
to improve it or make changes, I'd advise reading the following:
- Yamaha's YMF-272 (OPL-3) programmer's manual. (ymf272.pdf)
(Has useful table of how the operators map to YM3812 registers)
- Yamaha's YM2413 programmer's manual. (ym2413.lzh)
- Vladimir Arnost's OPL-3 programmer's guide. (opl3.txt)
(Explains operator allocation in rhythm mode)
- The YM2413 emulation from MAME. (ym2413.c/2413intf.h)
*/
#include "shared.h"
/* You can replace this to output to another YM3812 emulator
or a perhaps a real OPL-2/OPL-3 sound chip */
#if USE_ADLIB
#define OPL_WRITE(c,r,d) { outp(0x388+c*2, r); outp(0x389+c*2, d); }
#else
#define OPL_WRITE(c,r,d) OPLWriteReg(ym3812, r, d)
#endif
/* YM2413 chip contexts */
t_ym2413 ym2413[MAX_YM2413];
/* Fixed instrument settings, from MAME's YM2413 emulation */
/* This might need some tweaking... */
unsigned char table[16][11] =
{
/* 20 23 40 43 60 63 80 83 E0 E3 C0 */
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
#if 1 /* Instrument settings from MAME */
{ 0x01, 0x22, 0x23, 0x07, 0xF0, 0xF0, 0x07, 0x18, 0x00, 0x00, 0x00 },
{ 0x23, 0x01, 0x68, 0x05, 0xF2, 0x74, 0x6C, 0x89, 0x00, 0x00, 0x00 },
{ 0x13, 0x11, 0x25, 0x00, 0xD2, 0xB2, 0xF4, 0xF4, 0x00, 0x00, 0x00 },
{ 0x22, 0x21, 0x1B, 0x05, 0xC0, 0xA1, 0x18, 0x08, 0x00, 0x00, 0x00 },
{ 0x22, 0x21, 0x2C, 0x03, 0xD2, 0xA1, 0x18, 0x57, 0x00, 0x00, 0x00 },
{ 0x01, 0x22, 0xBA, 0x01, 0xF1, 0xF1, 0x1E, 0x04, 0x00, 0x00, 0x00 },
{ 0x21, 0x21, 0x28, 0x06, 0xF1, 0xF1, 0x6B, 0x3E, 0x00, 0x00, 0x00 },
{ 0x27, 0x21, 0x60, 0x00, 0xF0, 0xF0, 0x0D, 0x0F, 0x00, 0x00, 0x00 },
{ 0x20, 0x21, 0x2B, 0x06, 0x85, 0xF1, 0x6D, 0x89, 0x00, 0x00, 0x00 },
{ 0x01, 0x21, 0xBF, 0x02, 0x53, 0x62, 0x5F, 0xAE, 0x01, 0x00, 0x00 },
{ 0x23, 0x21, 0x70, 0x07, 0xD4, 0xA3, 0x4E, 0x64, 0x01, 0x00, 0x00 },
{ 0x2B, 0x21, 0xA4, 0x07, 0xF6, 0x93, 0x5C, 0x4D, 0x00, 0x00, 0x00 },
{ 0x21, 0x23, 0xAD, 0x07, 0x77, 0xF1, 0x18, 0x37, 0x00, 0x00, 0x00 },
{ 0x21, 0x21, 0x2A, 0x03, 0xF3, 0xE2, 0x29, 0x46, 0x00, 0x00, 0x00 },
{ 0x21, 0x23, 0x37, 0x03, 0xF3, 0xE2, 0x29, 0x46, 0x00, 0x00, 0x00 },
#else /* Instrument settings from Allegro */
{ 0x31, 0x21, 0x15, 0x09, 0xdd, 0x56, 0x13, 0x26, 0x01, 0x00, 0x08 }, /* Violin */
{ 0x03, 0x11, 0x54, 0x09, 0xf3, 0xf1, 0x9a, 0xe7, 0x01, 0x00, 0x0c }, /* Acoustic Guitar(steel) */
{ 0x21, 0x21, 0x8f, 0x0c, 0xf2, 0xf2, 0x45, 0x76, 0x00, 0x00, 0x08 }, /* Acoustic Grand */
{ 0xe1, 0xe1, 0x46, 0x09, 0x88, 0x65, 0x5f, 0x1a, 0x00, 0x00, 0x00 }, /* Flute */
{ 0x32, 0x21, 0x90, 0x09, 0x9b, 0x72, 0x21, 0x17, 0x00, 0x00, 0x04 }, /* Clarinet */
{ 0x21, 0x21, 0x4b, 0x09, 0xaa, 0x8f, 0x16, 0x0a, 0x01, 0x00, 0x08 }, /* Oboe */
{ 0x21, 0x21, 0x92, 0x0a, 0x85, 0x8f, 0x17, 0x09, 0x00, 0x00, 0x0c }, /* Trumpet */
{ 0x23, 0xb1, 0x93, 0x09, 0x97, 0x55, 0x23, 0x14, 0x01, 0x00, 0x04 }, /* Church Organ */
{ 0x21, 0x21, 0x9b, 0x09, 0x61, 0x7f, 0x6a, 0x0a, 0x00, 0x00, 0x02 }, /* French Horn */
{ 0x71, 0x72, 0x57, 0x09, 0x54, 0x7a, 0x05, 0x05, 0x00, 0x00, 0x0c }, /* Synth Voice */
{ 0x21, 0x36, 0x80, 0x17, 0xa2, 0xf1, 0x01, 0xd5, 0x00, 0x00, 0x08 }, /* Harpsichord */
{ 0x18, 0x81, 0x62, 0x09, 0xf3, 0xf2, 0xe6, 0xf6, 0x00, 0x00, 0x00 }, /* Vibraphone */
{ 0x31, 0x31, 0x8b, 0x09, 0xf4, 0xf1, 0xe8, 0x78, 0x00, 0x00, 0x0a }, /* Synth Bass 1 */
{ 0x21, 0xa2, 0x1e, 0x09, 0x94, 0xc3, 0x06, 0xa6, 0x00, 0x00, 0x02 }, /* Acoustic Bass */
{ 0x03, 0x21, 0x87, 0x89, 0xf6, 0xf3, 0x22, 0xf8, 0x01, 0x00, 0x06 }, /* Electric Guitar(clean) */
#endif
};
/*--------------------------------------------------------------------------*/
void ym2413_init(int count)
{
int n;
for(n = 0; n < count; n += 1)
{
/* Reset YM2413 data */
ym2413_reset(n);
}
}
void ym2413_reset(int chip)
{
int n;
/* Point to current YM2413 context */
t_ym2413 *opll = &ym2413[chip];
/* Clear channel data context */
memset(opll, 0, sizeof(t_ym2413));
/* Clear all YM3812 registers */
for(n = 0; n < 0x100; n += 1)
{
OPL_WRITE(chip, n, 0x00);
}
/* Turn off rhythm mode and key-on bits */
opll->rhythm = 0;
OPL_WRITE(chip, 0xBD, 0x00);
/* Enable waveform select */
OPL_WRITE(chip, 0x01, 0x20);
}
void ym2413_write(int chip, int address, int data)
{
/* Point to current YM2413 context */
t_ym2413 *opll = &ym2413[chip];
if(address & 1) /* Data port */
{
/* Store register data */
opll->reg[opll->latch] = data;
switch(opll->latch & 0x30)
{
case 0x00: /* User instrument registers */
switch(opll->latch & 0x0F)
{
case 0x00: /* Misc. ctrl. (modulator) */
case 0x01: /* Misc. ctrl. (carrier) */
case 0x02: /* Key scale level and total level (modulator) */
case 0x04: /* Attack / Decay (modulator) */
case 0x05: /* Attack / Decay (carrier) */
case 0x06: /* Sustain / Release (modulator) */
case 0x07: /* Sustain / Release (carrier) */
opll->user[(opll->latch & 0x07)] = data;
break;
case 0x03: /* Key scale level, carrier/modulator waveform, feedback */
/* Key scale level (carrier) */
/* Don't touch the total level (channel volume) */
opll->user[3] = (opll->user[3] & 0x3F) | (data & 0xC0);
/* Waveform select for the modulator */
opll->user[8] = (data >> 3) & 1;
/* Waveform select for the carrier */
opll->user[9] = (data >> 4) & 1;
/* Store feedback level in YM3812 format */
opll->user[10] = ((data & 0x07) << 1) & 0x0E;
break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -