⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ym2413.c

📁 DC的SEGA_GG模拟器源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
    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 + -