Ticket #9010: dosbox_adlib_v6.patch

File dosbox_adlib_v6.patch, 145.7 KB (added by lordhoto, 11 years ago)

Patch against trunk r40231.

  • engines/sci/sfx/softseq/opl2.cpp

     
    4242
    4343***************************************************************************/
    4444
     45#include "common/util.h"
     46
    4547#include "sci/tools.h"
    4648#include "sci/sfx/iterator.h"
    4749#include "../softseq.h"
     
    7981#define ADLIB_LEFT 0
    8082#define ADLIB_RIGHT 1
    8183
    82 /* #define OPL_INTERNAL_FREQ     3600000 */
    83 #define OPL_INTERNAL_FREQ    3579545
    84 
    8584static int ready = 0;
    8685static int pcmout_stereo = STEREO;
    8786
     
    157156
    158157/* more shamelessly lifted from xmp and adplug.  And altered.  :) */
    159158
    160 static int opl_write_L(int a, int v) {
     159static void opl_write_L(int a, int v) {
    161160        adlib_reg_L[a] = v;
    162161        OPLWrite(ym3812_L, 0x388, a);
    163         return OPLWrite(ym3812_L, 0x389, v);
     162        OPLWrite(ym3812_L, 0x389, v);
    164163}
    165164
    166 static int opl_write_R(int a, int v) {
     165static void opl_write_R(int a, int v) {
    167166        adlib_reg_R[a] = v;
    168167        OPLWrite(ym3812_R, 0x388, a);
    169         return OPLWrite(ym3812_R, 0x389, v);
     168        OPLWrite(ym3812_R, 0x389, v);
    170169}
    171170
    172 static int opl_write(int a, int v) {
     171static void opl_write(int a, int v) {
    173172        opl_write_L(a, v);
    174         return opl_write_R(a, v);
     173        opl_write_R(a, v);
    175174}
    176175
    177176/*
     
    472471   We assume 16-bit stereo frames (ie 4 bytes)
    473472*/
    474473static void opl2_poll(sfx_softseq_t *self, byte *dest, int count) {
    475         int16 *buffer = (int16 *) dest;
    476         int16 *ptr = buffer;
     474        int16 *ptr = (int16 *)dest;
    477475
    478         if (!ready) {
     476        if (!ready)
    479477                error("synth_mixer(): !ready \n");
    480         }
    481478
    482         if (!buffer) {
     479        if (!ptr)
    483480                error("synth_mixer(): !buffer \n");
    484         }
    485481
    486482#if 0
    487483        {
     
    509505#endif
    510506
    511507        if (pcmout_stereo) {
    512                 YM3812UpdateOne(ym3812_L, ptr, count, 1);
    513                 YM3812UpdateOne(ym3812_R, ptr + 1, count, 1);
     508                int16 buffer[512];
     509
     510                while (count > 0) {
     511                        int process = count > ARRAYSIZE(buffer) ? ARRAYSIZE(buffer) : count;
     512                        count -= process;
     513
     514                        YM3812UpdateOne(ym3812_L, buffer, process);
     515                        for (int i = 0; i < process; ++i)
     516                                ptr[(i << 1) + 0] = buffer[i];
     517                       
     518                        YM3812UpdateOne(ym3812_R, buffer, process);
     519                        for (int i = 0; i < process; ++i)
     520                                ptr[(i << 1) + 1] = buffer[i];
     521
     522                        ptr += (count << 1);
     523                }
    514524        } else {
    515                 YM3812UpdateOne(ym3812_L, ptr, count, 0);
     525                YM3812UpdateOne(ym3812_L, ptr, count);
    516526        }
    517527}
    518528
     
    533543                for (i = 48; i < 96; i++)
    534544                        make_sbi((adlib_def *)(data_ptr + 2 + (28 * i)), adlib_sbi[i]);
    535545
    536         OPLBuildTables(FMOPL_ENV_BITS_HQ, FMOPL_EG_ENT_HQ);
    537 
    538         if (!(ym3812_L = OPLCreate(OPL_TYPE_YM3812, OPL_INTERNAL_FREQ, SAMPLE_RATE)) ||
    539                 !(ym3812_R = OPLCreate(OPL_TYPE_YM3812, OPL_INTERNAL_FREQ, SAMPLE_RATE))) {
     546        if (!(ym3812_L = makeAdlibOPL(SAMPLE_RATE)) || !(ym3812_R = makeAdlibOPL(SAMPLE_RATE))) {
    540547                sciprintf("[sfx:seq:opl2] Failure: Emulator init failed!\n");
    541548                return SFX_ERROR;
    542549        }
     
    549556
    550557
    551558static void opl2_exit(sfx_softseq_t *self) {
    552         FM_OPL *opl = ym3812_L;
     559        OPLDestroy(ym3812_L);
    553560        ym3812_L = NULL;
    554         OPLDestroy(opl);
    555         opl = ym3812_R;
     561        OPLDestroy(ym3812_R);
    556562        ym3812_R = NULL;
    557         OPLDestroy(opl);
    558563
    559564        // XXX deregister with pcm layer.
    560565}
  • sound/module.mk

     
    3030        mods/rjp1.o \
    3131        mods/soundfx.o \
    3232        softsynth/adlib.o \
     33        softsynth/opl/dbopl.o \
     34        softsynth/opl/dosbox.o \
     35        softsynth/opl/mame.o \
    3336        softsynth/ym2612.o \
    3437        softsynth/fluidsynth.o \
    3538        softsynth/mt32.o \
  • sound/fmopl.h

     
    88 * modify it under the terms of the GNU General Public License
    99 * as published by the Free Software Foundation; either version 2
    1010 * of the License, or (at your option) any later version.
    11 
     11 *
    1212 * This program is distributed in the hope that it will be useful,
    1313 * but WITHOUT ANY WARRANTY; without even the implied warranty of
    1414 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    1515 * GNU General Public License for more details.
    16 
     16 *
    1717 * You should have received a copy of the GNU General Public License
    1818 * along with this program; if not, write to the Free Software
    1919 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
    2020 *
    2121 * $URL$
    2222 * $Id$
    23  *
    24  * LGPL licensed version of MAMEs fmopl (V0.37a modified) by
    25  * Tatsuyuki Satoh. Included from LGPL'ed AdPlug.
    2623 */
    2724
    28 
    2925#ifndef SOUND_FMOPL_H
    3026#define SOUND_FMOPL_H
    3127
    3228#include "common/scummsys.h"
    33 #include "common/util.h"
    3429
    35 enum {
    36         FMOPL_ENV_BITS_HQ = 16,
    37         FMOPL_ENV_BITS_MQ = 8,
    38         FMOPL_ENV_BITS_LQ = 8,
    39         FMOPL_EG_ENT_HQ = 4096,
    40         FMOPL_EG_ENT_MQ = 1024,
    41         FMOPL_EG_ENT_LQ = 128
    42 };
     30namespace OPL {
    4331
     32class OPL {
     33public:
     34        virtual ~OPL() {}
     35
     36        /**
     37         * OPL type to emulate.
     38         */
     39        enum kOplType {
     40                kOpl2 = 0
     41        };
     42
     43        /**
     44         * Initializes the OPL emulator.
     45         *
     46         * @param rate  output sample rate
     47         * @return              true on success, false on failure
     48         */
     49        virtual bool init(int rate) = 0;
     50
     51        /**
     52         * Reinitializes the OPL emulator
     53         */
     54        virtual void reset() = 0;
     55
     56        /**
     57         * Writes a byte to the given I/O port.
     58         *
     59         * @param a             port address
     60         * @param v             value, which will be written
     61         */
     62        virtual void write(int a, int v) = 0;
     63
     64        /**
     65         * Reads a byte from the given I/O port.
     66         *
     67         * @param a             port address
     68         * @return              value read
     69         */
     70        virtual byte read(int a) = 0;
     71
     72        /**
     73         * Function to directly write to a specific OPL register.
     74         * Note that this will currently only work for OPL2 and
     75         * OPL3 types, not for a Dual OPL2 emulator.
     76         *
     77         * @param r             hardware register number to write to
     78         * @param v             value, which will be written
     79         */
     80        virtual void writeReg(int r, int v) = 0;
     81
     82        /**
     83         * Read up to 'length' samples.
     84         *
     85         * Data will be in native endianess, 16 bit per sample, signed.
     86         * For stereo OPL, buffer will be filled with interleaved
     87         * left and right channel samples, starting with a left sample.
     88         * Furthermore, the samples in the left and right are summed up.
     89         * So if you request 4 samples from a stereo OPL, you will get
     90         * a total of two left channel and two right channel samples.
     91         */
     92        virtual void readBuffer(int16 *buffer, int length) = 0;
    4493
    45 typedef void (*OPL_TIMERHANDLER)(int channel,double interval_Sec);
    46 typedef void (*OPL_IRQHANDLER)(int param,int irq);
    47 typedef void (*OPL_UPDATEHANDLER)(int param,int min_interval_us);
    48 
    49 #define OPL_TYPE_WAVESEL   0x01  /* waveform select    */
    50 
    51 /* Saving is necessary for member of the 'R' mark for suspend/resume */
    52 /* ---------- OPL one of slot  ---------- */
    53 typedef struct fm_opl_slot {
    54         int TL;         /* total level     :TL << 8                             */
    55         int TLL;        /* adjusted now TL                                              */
    56         uint8 KSR;      /* key scale rate  :(shift down bit)    */
    57         int *AR;        /* attack rate     :&AR_TABLE[AR<<2]    */
    58         int *DR;        /* decay rate      :&DR_TABLE[DR<<2]    */
    59         int SL;         /* sustain level   :SL_TABLE[SL]                */
    60         int *RR;        /* release rate    :&DR_TABLE[RR<<2]    */
    61         uint8 ksl;      /* keyscale level  :(shift down bits)   */
    62         uint8 ksr;      /* key scale rate  :kcode>>KSR                  */
    63         uint mul;       /* multiple        :ML_TABLE[ML]                */
    64         uint Cnt;       /* frequency count                                              */
    65         uint Incr;      /* frequency step                                               */
    66 
    67         /* envelope generator state */
    68         uint8 eg_typ;/* envelope type flag                                      */
    69         uint8 evm;      /* envelope phase                                               */
    70         int evc;        /* envelope counter                                             */
    71         int eve;        /* envelope counter end point                   */
    72         int evs;        /* envelope counter step                                */
    73         int evsa;       /* envelope step for AR :AR[ksr]                */
    74         int evsd;       /* envelope step for DR :DR[ksr]                */
    75         int evsr;       /* envelope step for RR :RR[ksr]                */
    76 
    77         /* LFO */
    78         uint8 ams;              /* ams flag                            */
    79         uint8 vib;              /* vibrate flag                        */
    80         /* wave selector */
    81         int **wavetable;
    82 } OPL_SLOT;
    83 
    84 /* ---------- OPL one of channel  ---------- */
    85 typedef struct fm_opl_channel {
    86         OPL_SLOT SLOT[2];
    87         uint8 CON;                      /* connection type                                      */
    88         uint8 FB;                       /* feed back       :(shift down bit)*/
    89         int *connect1;          /* slot1 output pointer                         */
    90         int *connect2;          /* slot2 output pointer                         */
    91         int op1_out[2];         /* slot1 output for selfeedback         */
    92 
    93         /* phase generator state */
    94         uint block_fnum;        /* block+fnum                                           */
    95         uint8 kcode;            /* key code        : KeyScaleCode       */
    96         uint fc;                        /* Freq. Increment base                         */
    97         uint ksl_base;          /* KeyScaleLevel Base step                      */
    98         uint8 keyon;            /* key on/off flag                                      */
    99 } OPL_CH;
    100 
    101 /* OPL state */
    102 typedef struct fm_opl_f {
    103         uint8 type;                     /* chip type                         */
    104         int clock;                      /* master clock  (Hz)                */
    105         int rate;                       /* sampling rate (Hz)                */
    106         double freqbase;        /* frequency base                    */
    107         double TimerBase;       /* Timer base time (==sampling time) */
    108         uint8 address;          /* address register                  */
    109         uint8 status;           /* status flag                       */
    110         uint8 statusmask;       /* status mask                       */
    111         uint mode;                      /* Reg.08 : CSM , notesel,etc.       */
    112 
    113         /* Timer */
    114         int T[2];                       /* timer counter                     */
    115         uint8 st[2];            /* timer enable                      */
    116 
    117         /* FM channel slots */
    118         OPL_CH *P_CH;           /* pointer of CH                     */
    119         int     max_ch;                 /* maximum channel                   */
    120 
    121         /* Rythm sention */
    122         uint8 rythm;            /* Rythm mode , key flag */
    123 
    124         /* time tables */
    125         int AR_TABLE[76];       /* atttack rate tables                          */
    126         int DR_TABLE[76];       /* decay rate tables                            */
    127         uint FN_TABLE[1024];/* fnumber -> increment counter             */
    128 
    129         /* LFO */
    130         int *ams_table;
    131         int *vib_table;
    132         int amsCnt;
    133         int amsIncr;
    134         int vibCnt;
    135         int vibIncr;
    136 
    137         /* wave selector enable flag */
    138         uint8 wavesel;
    139 
    140         /* external event callback handler */
    141         OPL_TIMERHANDLER  TimerHandler;         /* TIMER handler   */
    142         int TimerParam;                                         /* TIMER parameter */
    143         OPL_IRQHANDLER    IRQHandler;           /* IRQ handler    */
    144         int IRQParam;                                           /* IRQ parameter  */
    145         OPL_UPDATEHANDLER UpdateHandler;        /* stream update handler   */
    146         int UpdateParam;                                        /* stream update parameter */
    147 
    148         Common::RandomSource rnd;
    149 } FM_OPL;
    150 
    151 /* ---------- Generic interface section ---------- */
    152 #define OPL_TYPE_YM3526 (0)
    153 #define OPL_TYPE_YM3812 (OPL_TYPE_WAVESEL)
     94        static OPL *create(kOplType type = kOpl2);
     95};
    15496
    155 void OPLBuildTables(int ENV_BITS_PARAM, int EG_ENT_PARAM);
     97} // end of namespace OPL
     98
     99// Legacy API
     100typedef OPL::OPL FM_OPL;
    156101
    157 FM_OPL *OPLCreate(int type, int clock, int rate);
    158102void OPLDestroy(FM_OPL *OPL);
    159 void OPLSetTimerHandler(FM_OPL *OPL, OPL_TIMERHANDLER TimerHandler, int channelOffset);
    160 void OPLSetIRQHandler(FM_OPL *OPL, OPL_IRQHANDLER IRQHandler, int param);
    161 void OPLSetUpdateHandler(FM_OPL *OPL, OPL_UPDATEHANDLER UpdateHandler, int param);
    162103
    163104void OPLResetChip(FM_OPL *OPL);
    164 int OPLWrite(FM_OPL *OPL, int a, int v);
     105void OPLWrite(FM_OPL *OPL, int a, int v);
    165106unsigned char OPLRead(FM_OPL *OPL, int a);
    166 int OPLTimerOver(FM_OPL *OPL, int c);
    167107void OPLWriteReg(FM_OPL *OPL, int r, int v);
    168 void YM3812UpdateOne(FM_OPL *OPL, int16 *buffer, int length, int interleave = 0);
     108void YM3812UpdateOne(FM_OPL *OPL, int16 *buffer, int length);
    169109
    170110// Factory method
    171111FM_OPL *makeAdlibOPL(int rate);
    172112
    173113#endif
     114
  • sound/fmopl.cpp

     
    88 * modify it under the terms of the GNU General Public License
    99 * as published by the Free Software Foundation; either version 2
    1010 * of the License, or (at your option) any later version.
    11 
     11 *
    1212 * This program is distributed in the hope that it will be useful,
    1313 * but WITHOUT ANY WARRANTY; without even the implied warranty of
    1414 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    1515 * GNU General Public License for more details.
    16 
     16 *
    1717 * You should have received a copy of the GNU General Public License
    1818 * along with this program; if not, write to the Free Software
    1919 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
    2020 *
    2121 * $URL$
    2222 * $Id$
    23  *
    24  * LGPL licensed version of MAMEs fmopl (V0.37a modified) by
    25  * Tatsuyuki Satoh. Included from LGPL'ed AdPlug.
    2623 */
    2724
    28 #include <stdio.h>
    29 #include <stdlib.h>
    30 #include <string.h>
    31 #include <stdarg.h>
    32 #include <math.h>
    33 
    3425#include "sound/fmopl.h"
    3526
    36 #if defined (_WIN32_WCE) || defined (__SYMBIAN32__) || defined(PALMOS_MODE) || defined(__GP32__) || defined(GP2X) || defined (__MAEMO__) || defined(__DS__) || defined (__MINT__)
    37 #include "common/config-manager.h"
    38 #endif
    39 
    40 /* -------------------- preliminary define section --------------------- */
    41 /* attack/decay rate time rate */
    42 #define OPL_ARRATE     141280  /* RATE 4 =  2826.24ms @ 3.6MHz */
    43 #define OPL_DRRATE    1956000  /* RATE 4 = 39280.64ms @ 3.6MHz */
    44 
    45 #define FREQ_BITS 24                    /* frequency turn          */
    46 
    47 /* counter bits = 20 , octerve 7 */
    48 #define FREQ_RATE   (1<<(FREQ_BITS-20))
    49 #define TL_BITS    (FREQ_BITS+2)
    50 
    51 /* final output shift , limit minimum and maximum */
    52 #define OPL_OUTSB   (TL_BITS+3-16)              /* OPL output final shift 16bit */
    53 #define OPL_MAXOUT (0x7fff<<OPL_OUTSB)
    54 #define OPL_MINOUT (-0x8000<<OPL_OUTSB)
    55 
    56 /* -------------------- quality selection --------------------- */
    57 
    58 /* sinwave entries */
    59 /* used static memory = SIN_ENT * 4 (byte) */
    60 #ifdef __DS__
    61 #include "dsmain.h"
    62 #define SIN_ENT_SHIFT 8
    63 #else
    64 #define SIN_ENT_SHIFT 11
    65 #endif
    66 #define SIN_ENT (1<<SIN_ENT_SHIFT)
    67 
    68 /* output level entries (envelope,sinwave) */
    69 /* envelope counter lower bits */
    70 int ENV_BITS;
    71 /* envelope output entries */
    72 int EG_ENT;
    73 
    74 /* used dynamic memory = EG_ENT*4*4(byte)or EG_ENT*6*4(byte) */
    75 /* used static  memory = EG_ENT*4 (byte)                     */
    76 int EG_OFF;                                                              /* OFF */
    77 int EG_DED;
    78 int EG_DST;                                                              /* DECAY START */
    79 int EG_AED;
    80 #define EG_AST   0                       /* ATTACK START */
    81 
    82 #define EG_STEP (96.0/EG_ENT) /* OPL is 0.1875 dB step  */
    83 
    84 /* LFO table entries */
    85 #define VIB_ENT 512
    86 #define VIB_SHIFT (32-9)
    87 #define AMS_ENT 512
    88 #define AMS_SHIFT (32-9)
    89 
    90 #define VIB_RATE_SHIFT 8
    91 #define VIB_RATE (1<<VIB_RATE_SHIFT)
    92 
    93 /* -------------------- local defines , macros --------------------- */
    94 
    95 /* register number to channel number , slot offset */
    96 #define SLOT1 0
    97 #define SLOT2 1
    98 
    99 /* envelope phase */
    100 #define ENV_MOD_RR  0x00
    101 #define ENV_MOD_DR  0x01
    102 #define ENV_MOD_AR  0x02
    103 
    104 /* -------------------- tables --------------------- */
    105 static const int slot_array[32] = {
    106          0, 2, 4, 1, 3, 5,-1,-1,
    107          6, 8,10, 7, 9,11,-1,-1,
    108         12,14,16,13,15,17,-1,-1,
    109         -1,-1,-1,-1,-1,-1,-1,-1
    110 };
    111 
    112 static uint KSL_TABLE[8 * 16];
    113 
    114 static const double KSL_TABLE_SEED[8 * 16] = {
    115         /* OCT 0 */
    116         0.000, 0.000, 0.000, 0.000,
    117         0.000, 0.000, 0.000, 0.000,
    118         0.000, 0.000, 0.000, 0.000,
    119         0.000, 0.000, 0.000, 0.000,
    120         /* OCT 1 */
    121         0.000, 0.000, 0.000, 0.000,
    122         0.000, 0.000, 0.000, 0.000,
    123         0.000, 0.750, 1.125, 1.500,
    124         1.875, 2.250, 2.625, 3.000,
    125         /* OCT 2 */
    126         0.000, 0.000, 0.000, 0.000,
    127         0.000, 1.125, 1.875, 2.625,
    128         3.000, 3.750, 4.125, 4.500,
    129         4.875, 5.250, 5.625, 6.000,
    130         /* OCT 3 */
    131         0.000, 0.000, 0.000, 1.875,
    132         3.000, 4.125, 4.875, 5.625,
    133         6.000, 6.750, 7.125, 7.500,
    134         7.875, 8.250, 8.625, 9.000,
    135         /* OCT 4 */
    136         0.000, 0.000, 3.000, 4.875,
    137         6.000, 7.125, 7.875, 8.625,
    138         9.000, 9.750, 10.125, 10.500,
    139         10.875, 11.250, 11.625, 12.000,
    140         /* OCT 5 */
    141         0.000, 3.000, 6.000, 7.875,
    142         9.000, 10.125, 10.875, 11.625,
    143         12.000, 12.750, 13.125, 13.500,
    144         13.875, 14.250, 14.625, 15.000,
    145         /* OCT 6 */
    146         0.000, 6.000, 9.000, 10.875,
    147         12.000, 13.125, 13.875, 14.625,
    148         15.000, 15.750, 16.125, 16.500,
    149         16.875, 17.250, 17.625, 18.000,
    150         /* OCT 7 */
    151         0.000, 9.000, 12.000, 13.875,
    152         15.000, 16.125, 16.875, 17.625,
    153         18.000, 18.750, 19.125, 19.500,
    154         19.875, 20.250, 20.625, 21.000
    155 };
    156 
    157 /* sustain level table (3db per step) */
    158 /* 0 - 15: 0, 3, 6, 9,12,15,18,21,24,27,30,33,36,39,42,93 (dB)*/
     27#include "sound/softsynth/opl/dosbox.h"
     28#include "sound/softsynth/opl/mame.h"
    15929
    160 static int SL_TABLE[16];
     30namespace OPL {
    16131
    162 static const uint SL_TABLE_SEED[16] = {
    163         0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 31
    164 };
    165 
    166 #define TL_MAX (EG_ENT * 2) /* limit(tl + ksr + envelope) + sinwave */
    167 /* TotalLevel : 48 24 12  6  3 1.5 0.75 (dB) */
    168 /* TL_TABLE[ 0      to TL_MAX          ] : plus  section */
    169 /* TL_TABLE[ TL_MAX to TL_MAX+TL_MAX-1 ] : minus section */
    170 static int *TL_TABLE;
    171 
    172 /* pointers to TL_TABLE with sinwave output offset */
    173 static int **SIN_TABLE;
    174 
    175 /* LFO table */
    176 static int *AMS_TABLE;
    177 static int *VIB_TABLE;
    178 
    179 /* envelope output curve table */
    180 /* attack + decay + OFF */
    181 //static int ENV_CURVE[2*EG_ENT+1];
    182 //static int ENV_CURVE[2 * 4096 + 1];   // to keep it static ...
    183 static int *ENV_CURVE;
    184 
    185 
    186 /* multiple table */
    187 #define ML(a) (int)(a * 2)
    188 static const uint MUL_TABLE[16]= {
    189 /* 1/2, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15 */
    190         ML(0.50), ML(1.00), ML(2.00),  ML(3.00), ML(4.00), ML(5.00), ML(6.00), ML(7.00),
    191         ML(8.00), ML(9.00), ML(10.00), ML(10.00),ML(12.00),ML(12.00),ML(15.00),ML(15.00)
    192 };
    193 #undef ML
    194 
    195 /* dummy attack / decay rate ( when rate == 0 ) */
    196 static int RATE_0[16]=
    197 {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
    198 
    199 /* -------------------- static state --------------------- */
    200 
    201 /* lock level of common table */
    202 static int num_lock = 0;
    203 
    204 /* work table */
    205 static void *cur_chip = NULL;   /* current chip point */
    206 /* currenct chip state */
    207 /* static OPLSAMPLE  *bufL,*bufR; */
    208 static OPL_CH *S_CH;
    209 static OPL_CH *E_CH;
    210 OPL_SLOT *SLOT7_1, *SLOT7_2, *SLOT8_1, *SLOT8_2;
    211 
    212 static int outd[1];
    213 static int ams;
    214 static int vib;
    215 int *ams_table;
    216 int *vib_table;
    217 static int amsIncr;
    218 static int vibIncr;
    219 static int feedback2;           /* connect for SLOT 2 */
    220 
    221 /* --------------------- rebuild tables ------------------- */
    222 
    223 #define SC_KSL(mydb) ((uint) (mydb / (EG_STEP / 2)))
    224 #define SC_SL(db) (int)(db * ((3 / EG_STEP) * (1 << ENV_BITS))) + EG_DST
    225 
    226 void OPLBuildTables(int ENV_BITS_PARAM, int EG_ENT_PARAM) {
    227         int i;
    228 
    229         ENV_BITS = ENV_BITS_PARAM;
    230         EG_ENT = EG_ENT_PARAM;
    231         EG_OFF = ((2 * EG_ENT)<<ENV_BITS);  /* OFF          */
    232         EG_DED = EG_OFF;
    233         EG_DST = (EG_ENT << ENV_BITS);     /* DECAY  START */
    234         EG_AED = EG_DST;
    235         //EG_STEP = (96.0/EG_ENT);
    236 
    237         for (i = 0; i < ARRAYSIZE(KSL_TABLE_SEED); i++)
    238                 KSL_TABLE[i] = SC_KSL(KSL_TABLE_SEED[i]);
    239 
    240         for (i = 0; i < ARRAYSIZE(SL_TABLE_SEED); i++)
    241                 SL_TABLE[i] = SC_SL(SL_TABLE_SEED[i]);
    242 }
    243 
    244 #undef SC_KSL
    245 #undef SC_SL
    246 
    247 /* --------------------- subroutines  --------------------- */
    248 
    249 /* status set and IRQ handling */
    250 inline void OPL_STATUS_SET(FM_OPL *OPL, int flag) {
    251         /* set status flag */
    252         OPL->status |= flag;
    253         if(!(OPL->status & 0x80)) {
    254                 if(OPL->status & OPL->statusmask) {     /* IRQ on */
    255                         OPL->status |= 0x80;
    256                         /* callback user interrupt handler (IRQ is OFF to ON) */
    257                         if(OPL->IRQHandler)
    258                                 (OPL->IRQHandler)(OPL->IRQParam,1);
    259                 }
    260         }
     32OPL *OPL::create(kOplType type) {
     33//      return new MAME::OPL_MAME();
     34        return new DOSBox::OPL_DOSBox(type);
    26135}
    26236
    263 /* status reset and IRQ handling */
    264 inline void OPL_STATUS_RESET(FM_OPL *OPL, int flag) {
    265         /* reset status flag */
    266         OPL->status &= ~flag;
    267         if((OPL->status & 0x80)) {
    268                 if (!(OPL->status & OPL->statusmask)) {
    269                         OPL->status &= 0x7f;
    270                         /* callback user interrupt handler (IRQ is ON to OFF) */
    271                         if(OPL->IRQHandler) (OPL->IRQHandler)(OPL->IRQParam,0);
    272                 }
    273         }
    274 }
    275 
    276 /* IRQ mask set */
    277 inline void OPL_STATUSMASK_SET(FM_OPL *OPL, int flag) {
    278         OPL->statusmask = flag;
    279         /* IRQ handling check */
    280         OPL_STATUS_SET(OPL,0);
    281         OPL_STATUS_RESET(OPL,0);
    282 }
    283 
    284 /* ----- key on  ----- */
    285 inline void OPL_KEYON(OPL_SLOT *SLOT) {
    286         /* sin wave restart */
    287         SLOT->Cnt = 0;
    288         /* set attack */
    289         SLOT->evm = ENV_MOD_AR;
    290         SLOT->evs = SLOT->evsa;
    291         SLOT->evc = EG_AST;
    292         SLOT->eve = EG_AED;
    293 }
    294 
    295 /* ----- key off ----- */
    296 inline void OPL_KEYOFF(OPL_SLOT *SLOT) {
    297         if( SLOT->evm > ENV_MOD_RR) {
    298                 /* set envelope counter from envleope output */
    299 
    300                 // WORKAROUND: The Kyra engine does something very strange when
    301                 // starting a new song. For each channel:
    302                 //
    303                 // * The release rate is set to "fastest".
    304                 // * Any note is keyed off.
    305                 // * A very low-frequency note is keyed on.
    306                 //
    307                 // Usually, what happens next is that the real notes is keyed
    308                 // on immediately, in which case there's no problem.
    309                 //
    310                 // However, if the note is again keyed off (because the channel
    311                 // begins on a rest rather than a note), the envelope counter
    312                 // was moved from the very lowest point on the attack curve to
    313                 // the very highest point on the release curve.
    314                 //
    315                 // Again, this might not be a problem, if the release rate is
    316                 // still set to "fastest". But in many cases, it had already
    317                 // been increased. And, possibly because of inaccuracies in the
    318                 // envelope generator, that would cause the note to "fade out"
    319                 // for quite a long time.
    320                 //
    321                 // What we really need is a way to find the correct starting
    322                 // point for the envelope counter, and that may be what the
    323                 // commented-out line below is meant to do. For now, simply
    324                 // handle the pathological case.
    325 
    326                 if (SLOT->evm == ENV_MOD_AR && SLOT->evc == EG_AST)
    327                         SLOT->evc = EG_DED;
    328                 else if( !(SLOT->evc & EG_DST) )
    329                         //SLOT->evc = (ENV_CURVE[SLOT->evc>>ENV_BITS]<<ENV_BITS) + EG_DST;
    330                         SLOT->evc = EG_DST;
    331                 SLOT->eve = EG_DED;
    332                 SLOT->evs = SLOT->evsr;
    333                 SLOT->evm = ENV_MOD_RR;
    334         }
    335 }
    336 
    337 /* ---------- calcrate Envelope Generator & Phase Generator ---------- */
    338 
    339 /* return : envelope output */
    340 inline uint OPL_CALC_SLOT(OPL_SLOT *SLOT) {
    341         /* calcrate envelope generator */
    342         if((SLOT->evc += SLOT->evs) >= SLOT->eve) {
    343                 switch( SLOT->evm ) {
    344                 case ENV_MOD_AR: /* ATTACK -> DECAY1 */
    345                         /* next DR */
    346                         SLOT->evm = ENV_MOD_DR;
    347                         SLOT->evc = EG_DST;
    348                         SLOT->eve = SLOT->SL;
    349                         SLOT->evs = SLOT->evsd;
    350                         break;
    351                 case ENV_MOD_DR: /* DECAY -> SL or RR */
    352                         SLOT->evc = SLOT->SL;
    353                         SLOT->eve = EG_DED;
    354                         if(SLOT->eg_typ) {
    355                                 SLOT->evs = 0;
    356                         } else {
    357                                 SLOT->evm = ENV_MOD_RR;
    358                                 SLOT->evs = SLOT->evsr;
    359                         }
    360                         break;
    361                 case ENV_MOD_RR: /* RR -> OFF */
    362                         SLOT->evc = EG_OFF;
    363                         SLOT->eve = EG_OFF + 1;
    364                         SLOT->evs = 0;
    365                         break;
    366                 }
    367         }
    368         /* calcrate envelope */
    369         return SLOT->TLL + ENV_CURVE[SLOT->evc>>ENV_BITS] + (SLOT->ams ? ams : 0);
    370 }
    371 
    372 /* set algorythm connection */
    373 static void set_algorythm(OPL_CH *CH) {
    374         int *carrier = &outd[0];
    375         CH->connect1 = CH->CON ? carrier : &feedback2;
    376         CH->connect2 = carrier;
    377 }
    378 
    379 /* ---------- frequency counter for operater update ---------- */
    380 inline void CALC_FCSLOT(OPL_CH *CH, OPL_SLOT *SLOT) {
    381         int ksr;
    382 
    383         /* frequency step counter */
    384         SLOT->Incr = CH->fc * SLOT->mul;
    385         ksr = CH->kcode >> SLOT->KSR;
    386 
    387         if( SLOT->ksr != ksr ) {
    388                 SLOT->ksr = ksr;
    389                 /* attack , decay rate recalcration */
    390                 SLOT->evsa = SLOT->AR[ksr];
    391                 SLOT->evsd = SLOT->DR[ksr];
    392                 SLOT->evsr = SLOT->RR[ksr];
    393         }
    394         SLOT->TLL = SLOT->TL + (CH->ksl_base>>SLOT->ksl);
    395 }
    396 
    397 /* set multi,am,vib,EG-TYP,KSR,mul */
    398 inline void set_mul(FM_OPL *OPL, int slot, int v) {
    399         OPL_CH   *CH   = &OPL->P_CH[slot>>1];
    400         OPL_SLOT *SLOT = &CH->SLOT[slot & 1];
    401 
    402         SLOT->mul    = MUL_TABLE[v & 0x0f];
    403         SLOT->KSR    = (v & 0x10) ? 0 : 2;
    404         SLOT->eg_typ = (v & 0x20) >> 5;
    405         SLOT->vib    = (v & 0x40);
    406         SLOT->ams    = (v & 0x80);
    407         CALC_FCSLOT(CH, SLOT);
    408 }
    409 
    410 /* set ksl & tl */
    411 inline void set_ksl_tl(FM_OPL *OPL, int slot, int v) {
    412         OPL_CH   *CH   = &OPL->P_CH[slot>>1];
    413         OPL_SLOT *SLOT = &CH->SLOT[slot & 1];
    414         int ksl = v >> 6; /* 0 / 1.5 / 3 / 6 db/OCT */
    415 
    416         SLOT->ksl = ksl ? 3-ksl : 31;
    417         SLOT->TL  = (int)((v & 0x3f) * (0.75 / EG_STEP)); /* 0.75db step */
    418 
    419         if(!(OPL->mode & 0x80)) {       /* not CSM latch total level */
    420                 SLOT->TLL = SLOT->TL + (CH->ksl_base >> SLOT->ksl);
    421         }
    422 }
    423 
    424 /* set attack rate & decay rate  */
    425 inline void set_ar_dr(FM_OPL *OPL, int slot, int v) {
    426         OPL_CH   *CH   = &OPL->P_CH[slot>>1];
    427         OPL_SLOT *SLOT = &CH->SLOT[slot & 1];
    428         int ar = v >> 4;
    429         int dr = v & 0x0f;
    430 
    431         SLOT->AR = ar ? &OPL->AR_TABLE[ar << 2] : RATE_0;
    432         SLOT->evsa = SLOT->AR[SLOT->ksr];
    433         if(SLOT->evm == ENV_MOD_AR)
    434                 SLOT->evs = SLOT->evsa;
    435 
    436         SLOT->DR = dr ? &OPL->DR_TABLE[dr<<2] : RATE_0;
    437         SLOT->evsd = SLOT->DR[SLOT->ksr];
    438         if(SLOT->evm == ENV_MOD_DR)
    439                 SLOT->evs = SLOT->evsd;
    440 }
    441 
    442 /* set sustain level & release rate */
    443 inline void set_sl_rr(FM_OPL *OPL, int slot, int v) {
    444         OPL_CH   *CH   = &OPL->P_CH[slot>>1];
    445         OPL_SLOT *SLOT = &CH->SLOT[slot & 1];
    446         int sl = v >> 4;
    447         int rr = v & 0x0f;
    448 
    449         SLOT->SL = SL_TABLE[sl];
    450         if(SLOT->evm == ENV_MOD_DR)
    451                 SLOT->eve = SLOT->SL;
    452         SLOT->RR = &OPL->DR_TABLE[rr<<2];
    453         SLOT->evsr = SLOT->RR[SLOT->ksr];
    454         if(SLOT->evm == ENV_MOD_RR)
    455                 SLOT->evs = SLOT->evsr;
    456 }
    457 
    458 /* operator output calcrator */
    459 
    460 #define OP_OUT(slot,env,con)   slot->wavetable[((slot->Cnt + con)>>(24-SIN_ENT_SHIFT)) & (SIN_ENT-1)][env]
    461 /* ---------- calcrate one of channel ---------- */
    462 inline void OPL_CALC_CH(OPL_CH *CH) {
    463         uint env_out;
    464         OPL_SLOT *SLOT;
    465 
    466         feedback2 = 0;
    467         /* SLOT 1 */
    468         SLOT = &CH->SLOT[SLOT1];
    469         env_out=OPL_CALC_SLOT(SLOT);
    470         if(env_out < (uint)(EG_ENT - 1)) {
    471                 /* PG */
    472                 if(SLOT->vib)
    473                         SLOT->Cnt += (SLOT->Incr * vib) >> VIB_RATE_SHIFT;
    474                 else
    475                         SLOT->Cnt += SLOT->Incr;
    476                 /* connection */
    477                 if(CH->FB) {
    478                         int feedback1 = (CH->op1_out[0] + CH->op1_out[1]) >> CH->FB;
    479                         CH->op1_out[1] = CH->op1_out[0];
    480                         *CH->connect1 += CH->op1_out[0] = OP_OUT(SLOT, env_out, feedback1);
    481                 } else {
    482                         *CH->connect1 += OP_OUT(SLOT, env_out, 0);
    483                 }
    484         } else {
    485                 CH->op1_out[1] = CH->op1_out[0];
    486                 CH->op1_out[0] = 0;
    487         }
    488         /* SLOT 2 */
    489         SLOT = &CH->SLOT[SLOT2];
    490         env_out=OPL_CALC_SLOT(SLOT);
    491         if(env_out < (uint)(EG_ENT - 1)) {
    492                 /* PG */
    493                 if(SLOT->vib)
    494                         SLOT->Cnt += (SLOT->Incr * vib) >> VIB_RATE_SHIFT;
    495                 else
    496                         SLOT->Cnt += SLOT->Incr;
    497                 /* connection */
    498                 outd[0] += OP_OUT(SLOT, env_out, feedback2);
    499         }
    500 }
    501 
    502 /* ---------- calcrate rythm block ---------- */
    503 #define WHITE_NOISE_db 6.0
    504 inline void OPL_CALC_RH(FM_OPL *OPL, OPL_CH *CH) {
    505         uint env_tam, env_sd, env_top, env_hh;
    506         // This code used to do int(OPL->rnd.getRandomBit() * (WHITE_NOISE_db / EG_STEP)),
    507         // but EG_STEP = 96.0/EG_ENT, and WHITE_NOISE_db=6.0. So, that's equivalent to
    508         // int(OPL->rnd.getRandomBit() * EG_ENT/16). We know that EG_ENT is 4096, or 1024,
    509         // or 128, so we can safely avoid any FP ops.
    510         int whitenoise = OPL->rnd.getRandomBit() * (EG_ENT>>4);
    511 
    512         int tone8;
     37} // end of namespace OPL
    51338
    514         OPL_SLOT *SLOT;
    515         int env_out;
    516 
    517         /* BD : same as FM serial mode and output level is large */
    518         feedback2 = 0;
    519         /* SLOT 1 */
    520         SLOT = &CH[6].SLOT[SLOT1];
    521         env_out = OPL_CALC_SLOT(SLOT);
    522         if(env_out < EG_ENT-1) {
    523                 /* PG */
    524                 if(SLOT->vib)
    525                         SLOT->Cnt += (SLOT->Incr * vib) >> VIB_RATE_SHIFT;
    526                 else
    527                         SLOT->Cnt += SLOT->Incr;
    528                 /* connection */
    529                 if(CH[6].FB) {
    530                         int feedback1 = (CH[6].op1_out[0] + CH[6].op1_out[1]) >> CH[6].FB;
    531                         CH[6].op1_out[1] = CH[6].op1_out[0];
    532                         feedback2 = CH[6].op1_out[0] = OP_OUT(SLOT, env_out, feedback1);
    533                 }
    534                 else {
    535                         feedback2 = OP_OUT(SLOT, env_out, 0);
    536                 }
    537         } else {
    538                 feedback2 = 0;
    539                 CH[6].op1_out[1] = CH[6].op1_out[0];
    540                 CH[6].op1_out[0] = 0;
    541         }
    542         /* SLOT 2 */
    543         SLOT = &CH[6].SLOT[SLOT2];
    544         env_out = OPL_CALC_SLOT(SLOT);
    545         if(env_out < EG_ENT-1) {
    546                 /* PG */
    547                 if(SLOT->vib)
    548                         SLOT->Cnt += (SLOT->Incr * vib) >> VIB_RATE_SHIFT;
    549                 else
    550                         SLOT->Cnt += SLOT->Incr;
    551                 /* connection */
    552                 outd[0] += OP_OUT(SLOT, env_out, feedback2) * 2;
    553         }
    554 
    555         // SD  (17) = mul14[fnum7] + white noise
    556         // TAM (15) = mul15[fnum8]
    557         // TOP (18) = fnum6(mul18[fnum8]+whitenoise)
    558         // HH  (14) = fnum7(mul18[fnum8]+whitenoise) + white noise
    559         env_sd = OPL_CALC_SLOT(SLOT7_2) + whitenoise;
    560         env_tam =OPL_CALC_SLOT(SLOT8_1);
    561         env_top = OPL_CALC_SLOT(SLOT8_2);
    562         env_hh = OPL_CALC_SLOT(SLOT7_1) + whitenoise;
    563 
    564         /* PG */
    565         if(SLOT7_1->vib)
    566                 SLOT7_1->Cnt += (SLOT7_1->Incr * vib) >> (VIB_RATE_SHIFT-1);
    567         else
    568                 SLOT7_1->Cnt += 2 * SLOT7_1->Incr;
    569         if(SLOT7_2->vib)
    570                 SLOT7_2->Cnt += (CH[7].fc * vib) >> (VIB_RATE_SHIFT-3);
    571         else
    572                 SLOT7_2->Cnt += (CH[7].fc * 8);
    573         if(SLOT8_1->vib)
    574                 SLOT8_1->Cnt += (SLOT8_1->Incr * vib) >> VIB_RATE_SHIFT;
    575         else
    576                 SLOT8_1->Cnt += SLOT8_1->Incr;
    577         if(SLOT8_2->vib)
    578                 SLOT8_2->Cnt += ((CH[8].fc * 3) * vib) >> (VIB_RATE_SHIFT-4);
    579         else
    580                 SLOT8_2->Cnt += (CH[8].fc * 48);
    581 
    582         tone8 = OP_OUT(SLOT8_2,whitenoise,0 );
    583 
    584         /* SD */
    585         if(env_sd < (uint)(EG_ENT - 1))
    586                 outd[0] += OP_OUT(SLOT7_1, env_sd, 0) * 8;
    587         /* TAM */
    588         if(env_tam < (uint)(EG_ENT - 1))
    589                 outd[0] += OP_OUT(SLOT8_1, env_tam, 0) * 2;
    590         /* TOP-CY */
    591         if(env_top < (uint)(EG_ENT - 1))
    592                 outd[0] += OP_OUT(SLOT7_2, env_top, tone8) * 2;
    593         /* HH */
    594         if(env_hh  < (uint)(EG_ENT-1))
    595                 outd[0] += OP_OUT(SLOT7_2, env_hh, tone8) * 2;
    596 }
    597 
    598 /* ----------- initialize time tabls ----------- */
    599 static void init_timetables(FM_OPL *OPL, int ARRATE, int DRRATE) {
    600         int i;
    601         double rate;
    602 
    603         /* make attack rate & decay rate tables */
    604         for (i = 0; i < 4; i++)
    605                 OPL->AR_TABLE[i] = OPL->DR_TABLE[i] = 0;
    606         for (i = 4; i <= 60; i++) {
    607                 rate = OPL->freqbase;                                           /* frequency rate */
    608                 if(i < 60)
    609                         rate *= 1.0 + (i & 3) * 0.25;           /* b0-1 : x1 , x1.25 , x1.5 , x1.75 */
    610                 rate *= 1 << ((i >> 2) - 1);                                            /* b2-5 : shift bit */
    611                 rate *= (double)(EG_ENT << ENV_BITS);
    612                 OPL->AR_TABLE[i] = (int)(rate / ARRATE);
    613                 OPL->DR_TABLE[i] = (int)(rate / DRRATE);
    614         }
    615         for (i = 60; i < 76; i++) {
    616                 OPL->AR_TABLE[i] = EG_AED-1;
    617                 OPL->DR_TABLE[i] = OPL->DR_TABLE[60];
    618         }
    619 }
    620 
    621 /* ---------- generic table initialize ---------- */
    622 static int OPLOpenTable(void) {
    623         int s,t;
    624         double rate;
    625         int i,j;
    626         double pom;
    627 
    628 #ifdef __DS__
    629         DS::fastRamReset();
    630 
    631         TL_TABLE = (int *) DS::fastRamAlloc(TL_MAX * 2 * sizeof(int *));
    632         SIN_TABLE = (int **) DS::fastRamAlloc(SIN_ENT * 4 * sizeof(int *));
    633 #else
    634 
    635         /* allocate dynamic tables */
    636         if((TL_TABLE = (int *)malloc(TL_MAX * 2 * sizeof(int))) == NULL)
    637                 return 0;
    638 
    639         if((SIN_TABLE = (int **)malloc(SIN_ENT * 4 * sizeof(int *))) == NULL) {
    640                 free(TL_TABLE);
    641                 return 0;
    642         }
    643 #endif
    644 
    645         if((AMS_TABLE = (int *)malloc(AMS_ENT * 2 * sizeof(int))) == NULL) {
    646                 free(TL_TABLE);
    647                 free(SIN_TABLE);
    648                 return 0;
    649         }
    650 
    651         if((VIB_TABLE = (int *)malloc(VIB_ENT * 2 * sizeof(int))) == NULL) {
    652                 free(TL_TABLE);
    653                 free(SIN_TABLE);
    654                 free(AMS_TABLE);
    655                 return 0;
    656         }
    657         /* make total level table */
    658         for (t = 0; t < EG_ENT - 1 ; t++) {
    659                 rate = ((1 << TL_BITS) - 1) / pow(10.0, EG_STEP * t / 20);      /* dB -> voltage */
    660                 TL_TABLE[         t] =  (int)rate;
    661                 TL_TABLE[TL_MAX + t] = -TL_TABLE[t];
    662         }
    663         /* fill volume off area */
    664         for (t = EG_ENT - 1; t < TL_MAX; t++) {
    665                 TL_TABLE[t] = TL_TABLE[TL_MAX + t] = 0;
    666         }
    667 
    668         /* make sinwave table (total level offet) */
    669         /* degree 0 = degree 180                   = off */
    670         SIN_TABLE[0] = SIN_TABLE[SIN_ENT /2 ] = &TL_TABLE[EG_ENT - 1];
    671         for (s = 1;s <= SIN_ENT / 4; s++) {
    672                 pom = sin(2 * PI * s / SIN_ENT); /* sin     */
    673                 pom = 20 * log10(1 / pom);         /* decibel */
    674                 j = int(pom / EG_STEP);         /* TL_TABLE steps */
    675 
    676                 /* degree 0   -  90    , degree 180 -  90 : plus section */
    677                 SIN_TABLE[          s] = SIN_TABLE[SIN_ENT / 2 - s] = &TL_TABLE[j];
    678                 /* degree 180 - 270    , degree 360 - 270 : minus section */
    679                 SIN_TABLE[SIN_ENT / 2 + s] = SIN_TABLE[SIN_ENT - s] = &TL_TABLE[TL_MAX + j];
    680         }
    681         for (s = 0;s < SIN_ENT; s++) {
    682                 SIN_TABLE[SIN_ENT * 1 + s] = s < (SIN_ENT / 2) ? SIN_TABLE[s] : &TL_TABLE[EG_ENT];
    683                 SIN_TABLE[SIN_ENT * 2 + s] = SIN_TABLE[s % (SIN_ENT / 2)];
    684                 SIN_TABLE[SIN_ENT * 3 + s] = (s / (SIN_ENT / 4)) & 1 ? &TL_TABLE[EG_ENT] : SIN_TABLE[SIN_ENT * 2 + s];
    685         }
    686 
    687 
    688         ENV_CURVE = (int *)malloc(sizeof(int) * (2*EG_ENT+1));
    689 
    690         /* envelope counter -> envelope output table */
    691         for (i=0; i < EG_ENT; i++) {
    692                 /* ATTACK curve */
    693                 pom = pow(((double)(EG_ENT - 1 - i) / EG_ENT), 8) * EG_ENT;
    694                 /* if( pom >= EG_ENT ) pom = EG_ENT-1; */
    695                 ENV_CURVE[i] = (int)pom;
    696                 /* DECAY ,RELEASE curve */
    697                 ENV_CURVE[(EG_DST >> ENV_BITS) + i]= i;
    698         }
    699         /* off */
    700         ENV_CURVE[EG_OFF >> ENV_BITS]= EG_ENT - 1;
    701         /* make LFO ams table */
    702         for (i=0; i < AMS_ENT; i++) {
    703                 pom = (1.0 + sin(2 * PI * i / AMS_ENT)) / 2; /* sin */
    704                 AMS_TABLE[i]         = (int)((1.0 / EG_STEP) * pom); /* 1dB   */
    705                 AMS_TABLE[AMS_ENT + i] = (int)((4.8 / EG_STEP) * pom); /* 4.8dB */
    706         }
    707         /* make LFO vibrate table */
    708         for (i=0; i < VIB_ENT; i++) {
    709                 /* 100cent = 1seminote = 6% ?? */
    710                 pom = (double)VIB_RATE * 0.06 * sin(2 * PI * i / VIB_ENT); /* +-100sect step */
    711                 VIB_TABLE[i]         = (int)(VIB_RATE + (pom * 0.07)); /* +- 7cent */
    712                 VIB_TABLE[VIB_ENT + i] = (int)(VIB_RATE + (pom * 0.14)); /* +-14cent */
    713         }
    714         return 1;
     39void OPLDestroy(FM_OPL *OPL) {
     40        delete OPL;
    71541}
    71642
    717 static void OPLCloseTable(void) {
    718         free(TL_TABLE);
    719         free(SIN_TABLE);
    720         free(AMS_TABLE);
    721         free(VIB_TABLE);
    722         free(ENV_CURVE);
     43void OPLResetChip(FM_OPL *OPL) {
     44        OPL->reset();
    72345}
    72446
    725 /* CSM Key Controll */
    726 inline void CSMKeyControll(OPL_CH *CH) {
    727         OPL_SLOT *slot1 = &CH->SLOT[SLOT1];
    728         OPL_SLOT *slot2 = &CH->SLOT[SLOT2];
    729         /* all key off */
    730         OPL_KEYOFF(slot1);
    731         OPL_KEYOFF(slot2);
    732         /* total level latch */
    733         slot1->TLL = slot1->TL + (CH->ksl_base>>slot1->ksl);
    734         slot1->TLL = slot1->TL + (CH->ksl_base>>slot1->ksl);
    735         /* key on */
    736         CH->op1_out[0] = CH->op1_out[1] = 0;
    737         OPL_KEYON(slot1);
    738         OPL_KEYON(slot2);
     47void OPLWrite(FM_OPL *OPL, int a, int v) {
     48        OPL->write(a, v);
    73949}
    74050
    741 /* ---------- opl initialize ---------- */
    742 static void OPL_initalize(FM_OPL *OPL) {
    743         int fn;
    744 
    745         /* frequency base */
    746         OPL->freqbase = (OPL->rate) ? ((double)OPL->clock / OPL->rate) / 72 : 0;
    747         /* Timer base time */
    748         OPL->TimerBase = 1.0/((double)OPL->clock / 72.0 );
    749         /* make time tables */
    750         init_timetables(OPL, OPL_ARRATE, OPL_DRRATE);
    751         /* make fnumber -> increment counter table */
    752         for( fn=0; fn < 1024; fn++) {
    753                 OPL->FN_TABLE[fn] = (uint)(OPL->freqbase * fn * FREQ_RATE * (1<<7) / 2);
    754         }
    755         /* LFO freq.table */
    756         OPL->amsIncr = (int)(OPL->rate ? (double)AMS_ENT * (1 << AMS_SHIFT) / OPL->rate * 3.7 * ((double)OPL->clock/3600000) : 0);
    757         OPL->vibIncr = (int)(OPL->rate ? (double)VIB_ENT * (1 << VIB_SHIFT) / OPL->rate * 6.4 * ((double)OPL->clock/3600000) : 0);
     51unsigned char OPLRead(FM_OPL *OPL, int a) {
     52        return OPL->read(a);
    75853}
    75954
    760 /* ---------- write a OPL registers ---------- */
    76155void OPLWriteReg(FM_OPL *OPL, int r, int v) {
    762         OPL_CH *CH;
    763         int slot;
    764         uint block_fnum;
    765 
    766         switch(r & 0xe0) {
    767         case 0x00: /* 00-1f:controll */
    768                 switch(r & 0x1f) {
    769                 case 0x01:
    770                         /* wave selector enable */
    771                         if(OPL->type&OPL_TYPE_WAVESEL) {
    772                                 OPL->wavesel = v & 0x20;
    773                                 if(!OPL->wavesel) {
    774                                         /* preset compatible mode */
    775                                         int c;
    776                                         for(c=0; c<OPL->max_ch; c++) {
    777                                                 OPL->P_CH[c].SLOT[SLOT1].wavetable = &SIN_TABLE[0];
    778                                                 OPL->P_CH[c].SLOT[SLOT2].wavetable = &SIN_TABLE[0];
    779                                         }
    780                                 }
    781                         }
    782                         return;
    783                 case 0x02:      /* Timer 1 */
    784                         OPL->T[0] = (256-v) * 4;
    785                         break;
    786                 case 0x03:      /* Timer 2 */
    787                         OPL->T[1] = (256-v) * 16;
    788                         return;
    789                 case 0x04:      /* IRQ clear / mask and Timer enable */
    790                         if(v & 0x80) {  /* IRQ flag clear */
    791                                 OPL_STATUS_RESET(OPL, 0x7f);
    792                         } else {        /* set IRQ mask ,timer enable*/
    793                                 uint8 st1 = v & 1;
    794                                 uint8 st2 = (v >> 1) & 1;
    795                                 /* IRQRST,T1MSK,t2MSK,EOSMSK,BRMSK,x,ST2,ST1 */
    796                                 OPL_STATUS_RESET(OPL, v & 0x78);
    797                                 OPL_STATUSMASK_SET(OPL,((~v) & 0x78) | 0x01);
    798                                 /* timer 2 */
    799                                 if(OPL->st[1] != st2) {
    800                                         double interval = st2 ? (double)OPL->T[1] * OPL->TimerBase : 0.0;
    801                                         OPL->st[1] = st2;
    802                                         if (OPL->TimerHandler) (OPL->TimerHandler)(OPL->TimerParam + 1, interval);
    803                                 }
    804                                 /* timer 1 */
    805                                 if(OPL->st[0] != st1) {
    806                                         double interval = st1 ? (double)OPL->T[0] * OPL->TimerBase : 0.0;
    807                                         OPL->st[0] = st1;
    808                                         if (OPL->TimerHandler) (OPL->TimerHandler)(OPL->TimerParam + 0, interval);
    809                                 }
    810                         }
    811                         return;
    812                 }
    813                 break;
    814         case 0x20:      /* am,vib,ksr,eg type,mul */
    815                 slot = slot_array[r&0x1f];
    816                 if(slot == -1)
    817                         return;
    818                 set_mul(OPL,slot,v);
    819                 return;
    820         case 0x40:
    821                 slot = slot_array[r&0x1f];
    822                 if(slot == -1)
    823                         return;
    824                 set_ksl_tl(OPL,slot,v);
    825                 return;
    826         case 0x60:
    827                 slot = slot_array[r&0x1f];
    828                 if(slot == -1)
    829                         return;
    830                 set_ar_dr(OPL,slot,v);
    831                 return;
    832         case 0x80:
    833                 slot = slot_array[r&0x1f];
    834                 if(slot == -1)
    835                         return;
    836                 set_sl_rr(OPL,slot,v);
    837                 return;
    838         case 0xa0:
    839                 switch(r) {
    840                 case 0xbd:
    841                         /* amsep,vibdep,r,bd,sd,tom,tc,hh */
    842                         {
    843                         uint8 rkey = OPL->rythm ^ v;
    844                         OPL->ams_table = &AMS_TABLE[v & 0x80 ? AMS_ENT : 0];
    845                         OPL->vib_table = &VIB_TABLE[v & 0x40 ? VIB_ENT : 0];
    846                         OPL->rythm  = v & 0x3f;
    847                         if(OPL->rythm & 0x20) {
    848                                 /* BD key on/off */
    849                                 if(rkey & 0x10) {
    850                                         if(v & 0x10) {
    851                                                 OPL->P_CH[6].op1_out[0] = OPL->P_CH[6].op1_out[1] = 0;
    852                                                 OPL_KEYON(&OPL->P_CH[6].SLOT[SLOT1]);
    853                                                 OPL_KEYON(&OPL->P_CH[6].SLOT[SLOT2]);
    854                                         } else {
    855                                                 OPL_KEYOFF(&OPL->P_CH[6].SLOT[SLOT1]);
    856                                                 OPL_KEYOFF(&OPL->P_CH[6].SLOT[SLOT2]);
    857                                         }
    858                                 }
    859                                 /* SD key on/off */
    860                                 if(rkey & 0x08) {
    861                                         if(v & 0x08)
    862                                                 OPL_KEYON(&OPL->P_CH[7].SLOT[SLOT2]);
    863                                         else
    864                                                 OPL_KEYOFF(&OPL->P_CH[7].SLOT[SLOT2]);
    865                                 }/* TAM key on/off */
    866                                 if(rkey & 0x04) {
    867                                         if(v & 0x04)
    868                                                 OPL_KEYON(&OPL->P_CH[8].SLOT[SLOT1]);
    869                                         else
    870                                                 OPL_KEYOFF(&OPL->P_CH[8].SLOT[SLOT1]);
    871                                 }
    872                                 /* TOP-CY key on/off */
    873                                 if(rkey & 0x02) {
    874                                         if(v & 0x02)
    875                                                 OPL_KEYON(&OPL->P_CH[8].SLOT[SLOT2]);
    876                                         else
    877                                                 OPL_KEYOFF(&OPL->P_CH[8].SLOT[SLOT2]);
    878                                 }
    879                                 /* HH key on/off */
    880                                 if(rkey & 0x01) {
    881                                         if(v & 0x01)
    882                                                 OPL_KEYON(&OPL->P_CH[7].SLOT[SLOT1]);
    883                                         else
    884                                                 OPL_KEYOFF(&OPL->P_CH[7].SLOT[SLOT1]);
    885                                 }
    886                         }
    887                         }
    888                         return;
    889 
    890                 default:
    891                         break;
    892                 }
    893                 /* keyon,block,fnum */
    894                 if((r & 0x0f) > 8)
    895                         return;
    896                 CH = &OPL->P_CH[r & 0x0f];
    897                 if(!(r&0x10)) { /* a0-a8 */
    898                         block_fnum  = (CH->block_fnum & 0x1f00) | v;
    899                 } else {        /* b0-b8 */
    900                         int keyon = (v >> 5) & 1;
    901                         block_fnum = ((v & 0x1f) << 8) | (CH->block_fnum & 0xff);
    902                         if(CH->keyon != keyon) {
    903                                 if((CH->keyon=keyon)) {
    904                                         CH->op1_out[0] = CH->op1_out[1] = 0;
    905                                         OPL_KEYON(&CH->SLOT[SLOT1]);
    906                                         OPL_KEYON(&CH->SLOT[SLOT2]);
    907                                 } else {
    908                                         OPL_KEYOFF(&CH->SLOT[SLOT1]);
    909                                         OPL_KEYOFF(&CH->SLOT[SLOT2]);
    910                                 }
    911                         }
    912                 }
    913                 /* update */
    914                 if(CH->block_fnum != block_fnum) {
    915                         int blockRv = 7 - (block_fnum >> 10);
    916                         int fnum = block_fnum & 0x3ff;
    917                         CH->block_fnum = block_fnum;
    918                         CH->ksl_base = KSL_TABLE[block_fnum >> 6];
    919                         CH->fc = OPL->FN_TABLE[fnum] >> blockRv;
    920                         CH->kcode = CH->block_fnum >> 9;
    921                         if((OPL->mode & 0x40) && CH->block_fnum & 0x100)
    922                                 CH->kcode |=1;
    923                         CALC_FCSLOT(CH,&CH->SLOT[SLOT1]);
    924                         CALC_FCSLOT(CH,&CH->SLOT[SLOT2]);
    925                 }
    926                 return;
    927         case 0xc0:
    928                 /* FB,C */
    929                 if((r & 0x0f) > 8)
    930                         return;
    931                 CH = &OPL->P_CH[r&0x0f];
    932                 {
    933                         int feedback = (v >> 1) & 7;
    934                         CH->FB = feedback ? (8 + 1) - feedback : 0;
    935                         CH->CON = v & 1;
    936                         set_algorythm(CH);
    937                 }
    938                 return;
    939         case 0xe0: /* wave type */
    940                 slot = slot_array[r & 0x1f];
    941                 if(slot == -1)
    942                         return;
    943                 CH = &OPL->P_CH[slot>>1];
    944                 if(OPL->wavesel) {
    945                         CH->SLOT[slot&1].wavetable = &SIN_TABLE[(v & 0x03) * SIN_ENT];
    946                 }
    947                 return;
    948         }
    949 }
    950 
    951 /* lock/unlock for common table */
    952 static int OPL_LockTable(void) {
    953         num_lock++;
    954         if(num_lock>1)
    955                 return 0;
    956         /* first time */
    957         cur_chip = NULL;
    958         /* allocate total level table (128kb space) */
    959         if(!OPLOpenTable()) {
    960                 num_lock--;
    961                 return -1;
    962         }
    963         return 0;
     56        OPL->writeReg(r, v);
    96457}
    96558
    966 static void OPL_UnLockTable(void) {
    967         if(num_lock)
    968                 num_lock--;
    969         if(num_lock)
    970                 return;
    971         /* last time */
    972         cur_chip = NULL;
    973         OPLCloseTable();
    974 }
    975 
    976 /*******************************************************************************/
    977 /*              YM3812 local section                                                   */
    978 /*******************************************************************************/
    979 
    980 /* ---------- update one of chip ----------- */
    981 void YM3812UpdateOne(FM_OPL *OPL, int16 *buffer, int length, int interleave) {
    982         int i;
    983         int data;
    984         int16 *buf = buffer;
    985         uint amsCnt = OPL->amsCnt;
    986         uint vibCnt = OPL->vibCnt;
    987         uint8 rythm = OPL->rythm & 0x20;
    988         OPL_CH *CH, *R_CH;
    989 
    990 
    991         if((void *)OPL != cur_chip) {
    992                 cur_chip = (void *)OPL;
    993                 /* channel pointers */
    994                 S_CH = OPL->P_CH;
    995                 E_CH = &S_CH[9];
    996                 /* rythm slot */
    997                 SLOT7_1 = &S_CH[7].SLOT[SLOT1];
    998                 SLOT7_2 = &S_CH[7].SLOT[SLOT2];
    999                 SLOT8_1 = &S_CH[8].SLOT[SLOT1];
    1000                 SLOT8_2 = &S_CH[8].SLOT[SLOT2];
    1001                 /* LFO state */
    1002                 amsIncr = OPL->amsIncr;
    1003                 vibIncr = OPL->vibIncr;
    1004                 ams_table = OPL->ams_table;
    1005                 vib_table = OPL->vib_table;
    1006         }
    1007         R_CH = rythm ? &S_CH[6] : E_CH;
    1008         for(i = 0; i < length; i++) {
    1009                 /*            channel A         channel B         channel C      */
    1010                 /* LFO */
    1011                 ams = ams_table[(amsCnt += amsIncr) >> AMS_SHIFT];
    1012                 vib = vib_table[(vibCnt += vibIncr) >> VIB_SHIFT];
    1013                 outd[0] = 0;
    1014                 /* FM part */
    1015                 for(CH=S_CH; CH < R_CH; CH++)
    1016                         OPL_CALC_CH(CH);
    1017                 /* Rythn part */
    1018                 if(rythm)
    1019                         OPL_CALC_RH(OPL, S_CH);
    1020                 /* limit check */
    1021                 data = CLIP(outd[0], OPL_MINOUT, OPL_MAXOUT);
    1022                 /* store to sound buffer */
    1023                 buf[i << interleave] = data >> OPL_OUTSB;
    1024         }
    1025 
    1026         OPL->amsCnt = amsCnt;
    1027         OPL->vibCnt = vibCnt;
     59void YM3812UpdateOne(FM_OPL *OPL, int16 *buffer, int length) {
     60        OPL->readBuffer(buffer, length);
    102861}
    102962
    1030 /* ---------- reset a chip ---------- */
    1031 void OPLResetChip(FM_OPL *OPL) {
    1032         int c,s;
    1033         int i;
     63// Factory method
     64FM_OPL *makeAdlibOPL(int rate) {
     65        FM_OPL *opl = OPL::OPL::create();
    103466
    1035         /* reset chip */
    1036         OPL->mode = 0;  /* normal mode */
    1037         OPL_STATUS_RESET(OPL, 0x7f);
    1038         /* reset with register write */
    1039         OPLWriteReg(OPL, 0x01,0); /* wabesel disable */
    1040         OPLWriteReg(OPL, 0x02,0); /* Timer1 */
    1041         OPLWriteReg(OPL, 0x03,0); /* Timer2 */
    1042         OPLWriteReg(OPL, 0x04,0); /* IRQ mask clear */
    1043         for(i = 0xff; i >= 0x20; i--)
    1044                 OPLWriteReg(OPL,i,0);
    1045         /* reset OPerator parameter */
    1046         for(c = 0; c < OPL->max_ch ;c++ ) {
    1047                 OPL_CH *CH = &OPL->P_CH[c];
    1048                 /* OPL->P_CH[c].PAN = OPN_CENTER; */
    1049                 for(s = 0; s < 2; s++ ) {
    1050                         /* wave table */
    1051                         CH->SLOT[s].wavetable = &SIN_TABLE[0];
    1052                         /* CH->SLOT[s].evm = ENV_MOD_RR; */
    1053                         CH->SLOT[s].evc = EG_OFF;
    1054                         CH->SLOT[s].eve = EG_OFF + 1;
    1055                         CH->SLOT[s].evs = 0;
     67        if (opl) {
     68                if (!opl->init(rate)) {
     69                        delete opl;
     70                        opl = 0;
    105671                }
    105772        }
    1058 }
    1059 
    1060 /* ----------  Create a virtual YM3812 ----------       */
    1061 /* 'rate'  is sampling rate and 'bufsiz' is the size of the  */
    1062 FM_OPL *OPLCreate(int type, int clock, int rate) {
    1063         char *ptr;
    1064         FM_OPL *OPL;
    1065         int state_size;
    1066         int max_ch = 9; /* normaly 9 channels */
    106773
    1068         if( OPL_LockTable() == -1)
    1069                 return NULL;
    1070         /* allocate OPL state space */
    1071         state_size  = sizeof(FM_OPL);
    1072         state_size += sizeof(OPL_CH) * max_ch;
    1073 
    1074         /* allocate memory block */
    1075         ptr = (char *)calloc(state_size, 1);
    1076         if(ptr == NULL)
    1077                 return NULL;
    1078 
    1079         /* clear */
    1080         memset(ptr, 0, state_size);
    1081         OPL       = (FM_OPL *)ptr; ptr += sizeof(FM_OPL);
    1082         OPL->P_CH = (OPL_CH *)ptr; ptr += sizeof(OPL_CH) * max_ch;
    1083 
    1084         /* set channel state pointer */
    1085         OPL->type  = type;
    1086         OPL->clock = clock;
    1087         OPL->rate  = rate;
    1088         OPL->max_ch = max_ch;
    1089 
    1090         /* init grobal tables */
    1091         OPL_initalize(OPL);
    1092 
    1093         /* reset chip */
    1094         OPLResetChip(OPL);
    1095         return OPL;
     74        return opl;
    109675}
    109776
    1098 /* ----------  Destroy one of vietual YM3812 ----------       */
    1099 void OPLDestroy(FM_OPL *OPL) {
    1100         OPL_UnLockTable();
    1101         free(OPL);
    1102 }
    1103 
    1104 /* ----------  Option handlers ----------       */
    1105 void OPLSetTimerHandler(FM_OPL *OPL, OPL_TIMERHANDLER TimerHandler,int channelOffset) {
    1106         OPL->TimerHandler   = TimerHandler;
    1107         OPL->TimerParam = channelOffset;
    1108 }
    1109 
    1110 void OPLSetIRQHandler(FM_OPL *OPL, OPL_IRQHANDLER IRQHandler, int param) {
    1111         OPL->IRQHandler     = IRQHandler;
    1112         OPL->IRQParam = param;
    1113 }
    1114 
    1115 void OPLSetUpdateHandler(FM_OPL *OPL, OPL_UPDATEHANDLER UpdateHandler,int param) {
    1116         OPL->UpdateHandler = UpdateHandler;
    1117         OPL->UpdateParam = param;
    1118 }
    1119 
    1120 /* ---------- YM3812 I/O interface ---------- */
    1121 int OPLWrite(FM_OPL *OPL,int a,int v) {
    1122         if(!(a & 1)) {  /* address port */
    1123                 OPL->address = v & 0xff;
    1124         } else {        /* data port */
    1125                 if(OPL->UpdateHandler)
    1126                         OPL->UpdateHandler(OPL->UpdateParam,0);
    1127                 OPLWriteReg(OPL, OPL->address,v);
    1128         }
    1129         return OPL->status >> 7;
    1130 }
    1131 
    1132 unsigned char OPLRead(FM_OPL *OPL,int a) {
    1133         if(!(a & 1)) {  /* status port */
    1134                 return OPL->status & (OPL->statusmask | 0x80);
    1135         }
    1136         /* data port */
    1137         switch(OPL->address) {
    1138         case 0x05: /* KeyBoard IN */
    1139                 warning("OPL:read unmapped KEYBOARD port\n");
    1140                 return 0;
    1141         case 0x19: /* I/O DATA    */
    1142                 warning("OPL:read unmapped I/O port\n");
    1143                 return 0;
    1144         case 0x1a: /* PCM-DATA    */
    1145                 return 0;
    1146         default:
    1147                 break;
    1148         }
    1149         return 0;
    1150 }
    1151 
    1152 int OPLTimerOver(FM_OPL *OPL, int c) {
    1153         if(c) { /* Timer B */
    1154                 OPL_STATUS_SET(OPL, 0x20);
    1155         } else {        /* Timer A */
    1156                 OPL_STATUS_SET(OPL, 0x40);
    1157                 /* CSM mode key,TL controll */
    1158                 if(OPL->mode & 0x80) {  /* CSM mode total level latch and auto key on */
    1159                         int ch;
    1160                         if(OPL->UpdateHandler)
    1161                                 OPL->UpdateHandler(OPL->UpdateParam,0);
    1162                         for(ch = 0; ch < 9; ch++)
    1163                                 CSMKeyControll(&OPL->P_CH[ch]);
    1164                 }
    1165         }
    1166         /* reload timer */
    1167         if (OPL->TimerHandler)
    1168                 (OPL->TimerHandler)(OPL->TimerParam + c, (double)OPL->T[c] * OPL->TimerBase);
    1169         return OPL->status >> 7;
    1170 }
    1171 
    1172 FM_OPL *makeAdlibOPL(int rate) {
    1173         // We need to emulate one YM3812 chip
    1174         int env_bits = FMOPL_ENV_BITS_HQ;
    1175         int eg_ent = FMOPL_EG_ENT_HQ;
    1176 #if defined (_WIN32_WCE) || defined(__SYMBIAN32__) || defined(PALMOS_MODE) || defined(__GP32__) || defined (GP2X) || defined(__MAEMO__) || defined(__DS__) || defined (__MINT__)
    1177         if (ConfMan.hasKey("FM_high_quality") && ConfMan.getBool("FM_high_quality")) {
    1178                 env_bits = FMOPL_ENV_BITS_HQ;
    1179                 eg_ent = FMOPL_EG_ENT_HQ;
    1180         } else if (ConfMan.hasKey("FM_medium_quality") && ConfMan.getBool("FM_medium_quality")) {
    1181                 env_bits = FMOPL_ENV_BITS_MQ;
    1182                 eg_ent = FMOPL_EG_ENT_MQ;
    1183         } else {
    1184                 env_bits = FMOPL_ENV_BITS_LQ;
    1185                 eg_ent = FMOPL_EG_ENT_LQ;
    1186         }
    1187 #endif
    1188 
    1189         OPLBuildTables(env_bits, eg_ent);
    1190         return OPLCreate(OPL_TYPE_YM3812, 3579545, rate);
    1191 }
  • sound/softsynth/opl/dosbox.cpp

     
     1/* ScummVM - Graphic Adventure Engine
     2 *
     3 * ScummVM is the legal property of its developers, whose names
     4 * are too numerous to list here. Please refer to the COPYRIGHT
     5 * file distributed with this source distribution.
     6 *
     7 * This program is free software; you can redistribute it and/or
     8 * modify it under the terms of the GNU General Public License
     9 * as published by the Free Software Foundation; either version 2
     10 * of the License, or (at your option) any later version.
     11 *
     12 * This program is distributed in the hope that it will be useful,
     13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15 * GNU General Public License for more details.
     16 *
     17 * You should have received a copy of the GNU General Public License
     18 * along with this program; if not, write to the Free Software
     19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
     20 *
     21 * $URL$
     22 * $Id$
     23 */
     24
     25/*
     26 * Based on AdLib emulation code of DOSBox
     27 * Copyright (C) 2002-2009  The DOSBox Team
     28 * Licensed under GPLv2+
     29 * http://www.dosbox.com
     30 */
     31
     32#ifndef DISABLE_DOSBOX_OPL
     33
     34#include "dosbox.h"
     35#include "dbopl.h"
     36
     37#include "common/system.h"
     38
     39#include <math.h>
     40#include <string.h>
     41
     42namespace OPL {
     43namespace DOSBox {     
     44
     45Timer::Timer() {
     46        masked = false;
     47        overflow = false;
     48        enabled = false;
     49        counter = 0;
     50        delay = 0;
     51}
     52
     53void Timer::update(double time) {
     54        if (!enabled || !delay)
     55                return;
     56        double deltaStart = time - startTime;
     57        // Only set the overflow flag when not masked
     58        if (deltaStart >= 0 && !masked)
     59                overflow = 1;
     60}
     61
     62void Timer::reset(double time) {
     63        overflow = false;
     64        if (!delay || !enabled)
     65                return;
     66        double delta = (time - startTime);
     67        double rem = fmod(delta, delay);
     68        double next = delay - rem;
     69        startTime = time + next;               
     70}
     71
     72void Timer::stop() {
     73        enabled = false;
     74}
     75
     76void Timer::start(double time, int scale) {
     77        //Don't enable again
     78        if (enabled)
     79                return;
     80        enabled = true;
     81        delay = 0.001 * (256 - counter) * scale;
     82        startTime = time + delay;
     83}
     84
     85bool Chip::write(uint32 reg, uint8 val) {
     86        switch (reg) {
     87        case 0x02:
     88                timer[0].counter = val;
     89                return true;
     90        case 0x03:
     91                timer[1].counter = val;
     92                return true;
     93        case 0x04:
     94                // TODO: I couldn't get behind the PIC_FullIndex logic, but I would guess
     95                // it should be like this...
     96                double time = g_system->getMillis() / 1000.0;
     97
     98                if (val & 0x80) {
     99                        timer[0].reset(time);
     100                        timer[1].reset(time);
     101                } else {
     102                        timer[0].update(time);
     103                        timer[1].update(time);
     104
     105                        if (val & 0x1)
     106                                timer[0].start(time, 80);
     107                        else
     108                                timer[0].stop();
     109
     110                        timer[0].masked = (val & 0x40) > 0;
     111
     112                        if (timer[0].masked)
     113                                timer[0].overflow = false;
     114
     115                        if (val & 0x2)
     116                                timer[1].start(time, 320);
     117                        else
     118                                timer[1].stop();
     119
     120                        timer[1].masked = (val & 0x20) > 0;
     121       
     122                        if (timer[1].masked)
     123                                timer[1].overflow = false;
     124                }
     125                return true;
     126        }
     127        return false;
     128}
     129
     130uint8 Chip::read() {
     131        // TODO: I couldn't get behind the PIC_FullIndex logic, but I would guess
     132        // it should be like this...
     133        double time = g_system->getMillis() / 1000.0;
     134
     135        timer[0].update(time);
     136        timer[1].update(time);
     137
     138        uint8 ret = 0;
     139        //Overflow won't be set if a channel is masked
     140        if (timer[0].overflow) {
     141                ret |= 0x40;
     142                ret |= 0x80;
     143        }
     144        if (timer[1].overflow) {
     145                ret |= 0x20;
     146                ret |= 0x80;
     147        }
     148        return ret;
     149}
     150
     151OPL_DOSBox::OPL_DOSBox(kOplType type) : _type(type), _rate(0), _handler(0) {
     152}
     153
     154OPL_DOSBox::~OPL_DOSBox() {
     155        free();
     156}
     157
     158void OPL_DOSBox::free() {
     159        delete _handler;
     160        _handler = 0;
     161}
     162
     163bool OPL_DOSBox::init(int rate) {
     164        free();
     165
     166        _reg.dual[0] = 0;
     167        _reg.dual[1] = 0;
     168        _reg.normal = 0;
     169
     170        memset(_chip, 0, sizeof(_chip));
     171        switch (_type) {
     172        case kOpl2:
     173                _handler = new DBOPL::Handler();
     174                break;
     175       
     176        default:
     177                return false;
     178        }
     179
     180        _handler->init(rate);
     181        _rate = rate;
     182        return true;
     183}
     184
     185void OPL_DOSBox::reset() {
     186        // TODO: Find a nicer way to reset the emulator
     187        init(_rate);   
     188}
     189
     190void OPL_DOSBox::write(int port, int val) {
     191        if (port&1) {
     192                switch (_type) {
     193                case kOpl2:
     194                //case kOpl3:
     195                        if (!_chip[0].write(_reg.normal, val))
     196                                _handler->writeReg(_reg.normal, val);
     197                        break;
     198                /*case kDualOpl2:
     199                        // Not a 0x??8 port, then write to a specific port
     200                        if (!(port & 0x8)) {
     201                                byte index = (port & 2) >> 1;
     202                                dualWrite(index, _reg.dual[index], val);
     203                        } else {
     204                                //Write to both ports
     205                                dualWrite(0, _reg.dual[0], val);
     206                                dualWrite(1, _reg.dual[1], val);
     207                        }
     208                        break;*/
     209                }
     210        } else {
     211                // Ask the handler to write the address
     212                // Make sure to clip them in the right range
     213                switch (_type) {
     214                case kOpl2:
     215                        _reg.normal = _handler->writeAddr(port, val) & 0xff;
     216                        break;
     217                /*case kOpl3:
     218                        _reg.normal = _handler->writeAddr(port, val) & 0x1ff;
     219                        break;
     220                case kDualOpl2:
     221                        // Not a 0x?88 port, when write to a specific side
     222                        if (!(port & 0x8)) {
     223                                byte index = (port & 2) >> 1;
     224                                _reg.dual[index] = val & 0xff;
     225                        } else {
     226                                _reg.dual[0] = val & 0xff;
     227                                _reg.dual[1] = val & 0xff;
     228                        }
     229                        break;*/
     230                }
     231        }
     232}
     233
     234byte OPL_DOSBox::read(int port) {
     235        switch (_type) {
     236        case kOpl2:
     237                if (!(port & 1))
     238                        //Make sure the low bits are 6 on opl2
     239                        return _chip[0].read() | 0x6;
     240                break;
     241        /*case kOpl3:
     242                if (!(port & 1))
     243                        return _chip[0].read();
     244                break;
     245        case kDualOpl2:
     246                // Only return for the lower ports
     247                if (port & 1)
     248                        return 0xff;
     249                // Make sure the low bits are 6 on opl2
     250                return _chip[(port >> 1) & 1].read() | 0x6;*/
     251        }
     252        return 0;
     253}
     254
     255void OPL_DOSBox::writeReg(int r, int v) {
     256        byte tempReg = 0;
     257        switch (_type) {
     258        case kOpl2:
     259        //case kOpl3:
     260                // We can't use _handler->writeReg here directly, since it would miss timer changes.
     261
     262                // Backup old setup register
     263                tempReg = _reg.normal;
     264
     265                // We need to set the register we want to write to via port 0x388
     266                write(0x388, r);
     267                // Do the real writing to the register
     268                write(0x389, v);
     269                // Restore the old register
     270                write(0x388, tempReg);
     271                break;
     272
     273        //case kDualOpl2:
     274        //      error("Can't use OPL_DOSBox::writeReg on Dual OPL2");
     275        //      break;
     276        };
     277}
     278
     279void OPL_DOSBox::readBuffer(int16 *buffer, int length) {
     280        // For stereo OPL cards, we divide the sample count by 2,
     281        // to match stereo AudioStream behavior.
     282        if (_type != kOpl2)
     283                length >>= 1;
     284
     285        _handler->generate(buffer, length);
     286}
     287
     288} // end of namespace DOSBox
     289} // end of namespace OPL
     290
     291#endif // !DISABLE_DOSBOX_ADLIB
  • sound/softsynth/opl/mame.cpp

     
     1/* ScummVM - Graphic Adventure Engine
     2 *
     3 * ScummVM is the legal property of its developers, whose names
     4 * are too numerous to list here. Please refer to the COPYRIGHT
     5 * file distributed with this source distribution.
     6 *
     7 * This program is free software; you can redistribute it and/or
     8 * modify it under the terms of the GNU General Public License
     9 * as published by the Free Software Foundation; either version 2
     10 * of the License, or (at your option) any later version.
     11
     12 * This program is distributed in the hope that it will be useful,
     13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15 * GNU General Public License for more details.
     16
     17 * You should have received a copy of the GNU General Public License
     18 * along with this program; if not, write to the Free Software
     19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
     20 *
     21 * $URL: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk/sound/fmopl.cpp $
     22 * $Id: fmopl.cpp 38211 2009-02-15 10:07:50Z sev $
     23 *
     24 * LGPL licensed version of MAMEs fmopl (V0.37a modified) by
     25 * Tatsuyuki Satoh. Included from LGPL'ed AdPlug.
     26 */
     27
     28#include <stdio.h>
     29#include <stdlib.h>
     30#include <string.h>
     31#include <stdarg.h>
     32#include <math.h>
     33
     34#include "mame.h"
     35
     36#if defined (_WIN32_WCE) || defined (__SYMBIAN32__) || defined(PALMOS_MODE) || defined(__GP32__) || defined(GP2X) || defined (__MAEMO__) || defined(__DS__) || defined (__MINT__)
     37#include "common/config-manager.h"
     38#endif
     39
     40namespace OPL {
     41namespace MAME {
     42
     43OPL_MAME::~OPL_MAME() {
     44        MAME::OPLDestroy(_opl);
     45        _opl = 0;
     46}
     47
     48bool OPL_MAME::init(int rate) {
     49        if (_opl)
     50                MAME::OPLDestroy(_opl);
     51
     52        _opl = MAME::makeAdlibOPL(rate);
     53        return (_opl != 0);
     54}
     55
     56void OPL_MAME::reset() {
     57        MAME::OPLResetChip(_opl);
     58}
     59
     60void OPL_MAME::write(int a, int v) {
     61        MAME::OPLWrite(_opl, a, v);
     62}
     63
     64byte OPL_MAME::read(int a) {
     65        return MAME::OPLRead(_opl, a);
     66}
     67
     68void OPL_MAME::writeReg(int r, int v) {
     69        MAME::OPLWriteReg(_opl, r, v);
     70}
     71
     72void OPL_MAME::readBuffer(int16 *buffer, int length) {
     73        MAME::YM3812UpdateOne(_opl, buffer, length);
     74}
     75
     76/* -------------------- preliminary define section --------------------- */
     77/* attack/decay rate time rate */
     78#define OPL_ARRATE     141280  /* RATE 4 =  2826.24ms @ 3.6MHz */
     79#define OPL_DRRATE    1956000  /* RATE 4 = 39280.64ms @ 3.6MHz */
     80
     81#define FREQ_BITS 24                    /* frequency turn          */
     82
     83/* counter bits = 20 , octerve 7 */
     84#define FREQ_RATE   (1<<(FREQ_BITS-20))
     85#define TL_BITS    (FREQ_BITS+2)
     86
     87/* final output shift , limit minimum and maximum */
     88#define OPL_OUTSB   (TL_BITS+3-16)              /* OPL output final shift 16bit */
     89#define OPL_MAXOUT (0x7fff<<OPL_OUTSB)
     90#define OPL_MINOUT (-0x8000<<OPL_OUTSB)
     91
     92/* -------------------- quality selection --------------------- */
     93
     94/* sinwave entries */
     95/* used static memory = SIN_ENT * 4 (byte) */
     96#ifdef __DS__
     97#include "dsmain.h"
     98#define SIN_ENT_SHIFT 8
     99#else
     100#define SIN_ENT_SHIFT 11
     101#endif
     102#define SIN_ENT (1<<SIN_ENT_SHIFT)
     103
     104/* output level entries (envelope,sinwave) */
     105/* envelope counter lower bits */
     106int ENV_BITS;
     107/* envelope output entries */
     108int EG_ENT;
     109
     110/* used dynamic memory = EG_ENT*4*4(byte)or EG_ENT*6*4(byte) */
     111/* used static  memory = EG_ENT*4 (byte)                     */
     112int EG_OFF;                                                              /* OFF */
     113int EG_DED;
     114int EG_DST;                                                              /* DECAY START */
     115int EG_AED;
     116#define EG_AST   0                       /* ATTACK START */
     117
     118#define EG_STEP (96.0/EG_ENT) /* OPL is 0.1875 dB step  */
     119
     120/* LFO table entries */
     121#define VIB_ENT 512
     122#define VIB_SHIFT (32-9)
     123#define AMS_ENT 512
     124#define AMS_SHIFT (32-9)
     125
     126#define VIB_RATE_SHIFT 8
     127#define VIB_RATE (1<<VIB_RATE_SHIFT)
     128
     129/* -------------------- local defines , macros --------------------- */
     130
     131/* register number to channel number , slot offset */
     132#define SLOT1 0
     133#define SLOT2 1
     134
     135/* envelope phase */
     136#define ENV_MOD_RR  0x00
     137#define ENV_MOD_DR  0x01
     138#define ENV_MOD_AR  0x02
     139
     140/* -------------------- tables --------------------- */
     141static const int slot_array[32] = {
     142         0, 2, 4, 1, 3, 5,-1,-1,
     143         6, 8,10, 7, 9,11,-1,-1,
     144        12,14,16,13,15,17,-1,-1,
     145        -1,-1,-1,-1,-1,-1,-1,-1
     146};
     147
     148static uint KSL_TABLE[8 * 16];
     149
     150static const double KSL_TABLE_SEED[8 * 16] = {
     151        /* OCT 0 */
     152        0.000, 0.000, 0.000, 0.000,
     153        0.000, 0.000, 0.000, 0.000,
     154        0.000, 0.000, 0.000, 0.000,
     155        0.000, 0.000, 0.000, 0.000,
     156        /* OCT 1 */
     157        0.000, 0.000, 0.000, 0.000,
     158        0.000, 0.000, 0.000, 0.000,
     159        0.000, 0.750, 1.125, 1.500,
     160        1.875, 2.250, 2.625, 3.000,
     161        /* OCT 2 */
     162        0.000, 0.000, 0.000, 0.000,
     163        0.000, 1.125, 1.875, 2.625,
     164        3.000, 3.750, 4.125, 4.500,
     165        4.875, 5.250, 5.625, 6.000,
     166        /* OCT 3 */
     167        0.000, 0.000, 0.000, 1.875,
     168        3.000, 4.125, 4.875, 5.625,
     169        6.000, 6.750, 7.125, 7.500,
     170        7.875, 8.250, 8.625, 9.000,
     171        /* OCT 4 */
     172        0.000, 0.000, 3.000, 4.875,
     173        6.000, 7.125, 7.875, 8.625,
     174        9.000, 9.750, 10.125, 10.500,
     175        10.875, 11.250, 11.625, 12.000,
     176        /* OCT 5 */
     177        0.000, 3.000, 6.000, 7.875,
     178        9.000, 10.125, 10.875, 11.625,
     179        12.000, 12.750, 13.125, 13.500,
     180        13.875, 14.250, 14.625, 15.000,
     181        /* OCT 6 */
     182        0.000, 6.000, 9.000, 10.875,
     183        12.000, 13.125, 13.875, 14.625,
     184        15.000, 15.750, 16.125, 16.500,
     185        16.875, 17.250, 17.625, 18.000,
     186        /* OCT 7 */
     187        0.000, 9.000, 12.000, 13.875,
     188        15.000, 16.125, 16.875, 17.625,
     189        18.000, 18.750, 19.125, 19.500,
     190        19.875, 20.250, 20.625, 21.000
     191};
     192
     193/* sustain level table (3db per step) */
     194/* 0 - 15: 0, 3, 6, 9,12,15,18,21,24,27,30,33,36,39,42,93 (dB)*/
     195
     196static int SL_TABLE[16];
     197
     198static const uint SL_TABLE_SEED[16] = {
     199        0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 31
     200};
     201
     202#define TL_MAX (EG_ENT * 2) /* limit(tl + ksr + envelope) + sinwave */
     203/* TotalLevel : 48 24 12  6  3 1.5 0.75 (dB) */
     204/* TL_TABLE[ 0      to TL_MAX          ] : plus  section */
     205/* TL_TABLE[ TL_MAX to TL_MAX+TL_MAX-1 ] : minus section */
     206static int *TL_TABLE;
     207
     208/* pointers to TL_TABLE with sinwave output offset */
     209static int **SIN_TABLE;
     210
     211/* LFO table */
     212static int *AMS_TABLE;
     213static int *VIB_TABLE;
     214
     215/* envelope output curve table */
     216/* attack + decay + OFF */
     217//static int ENV_CURVE[2*EG_ENT+1];
     218//static int ENV_CURVE[2 * 4096 + 1];   // to keep it static ...
     219static int *ENV_CURVE;
     220
     221
     222/* multiple table */
     223#define ML(a) (int)(a * 2)
     224static const uint MUL_TABLE[16]= {
     225/* 1/2, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15 */
     226        ML(0.50), ML(1.00), ML(2.00),  ML(3.00), ML(4.00), ML(5.00), ML(6.00), ML(7.00),
     227        ML(8.00), ML(9.00), ML(10.00), ML(10.00),ML(12.00),ML(12.00),ML(15.00),ML(15.00)
     228};
     229#undef ML
     230
     231/* dummy attack / decay rate ( when rate == 0 ) */
     232static int RATE_0[16]=
     233{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
     234
     235/* -------------------- static state --------------------- */
     236
     237/* lock level of common table */
     238static int num_lock = 0;
     239
     240/* work table */
     241static void *cur_chip = NULL;   /* current chip point */
     242/* currenct chip state */
     243/* static OPLSAMPLE  *bufL,*bufR; */
     244static OPL_CH *S_CH;
     245static OPL_CH *E_CH;
     246OPL_SLOT *SLOT7_1, *SLOT7_2, *SLOT8_1, *SLOT8_2;
     247
     248static int outd[1];
     249static int ams;
     250static int vib;
     251int *ams_table;
     252int *vib_table;
     253static int amsIncr;
     254static int vibIncr;
     255static int feedback2;           /* connect for SLOT 2 */
     256
     257/* --------------------- rebuild tables ------------------- */
     258
     259#define SC_KSL(mydb) ((uint) (mydb / (EG_STEP / 2)))
     260#define SC_SL(db) (int)(db * ((3 / EG_STEP) * (1 << ENV_BITS))) + EG_DST
     261
     262void OPLBuildTables(int ENV_BITS_PARAM, int EG_ENT_PARAM) {
     263        int i;
     264
     265        ENV_BITS = ENV_BITS_PARAM;
     266        EG_ENT = EG_ENT_PARAM;
     267        EG_OFF = ((2 * EG_ENT)<<ENV_BITS);  /* OFF          */
     268        EG_DED = EG_OFF;
     269        EG_DST = (EG_ENT << ENV_BITS);     /* DECAY  START */
     270        EG_AED = EG_DST;
     271        //EG_STEP = (96.0/EG_ENT);
     272
     273        for (i = 0; i < ARRAYSIZE(KSL_TABLE_SEED); i++)
     274                KSL_TABLE[i] = SC_KSL(KSL_TABLE_SEED[i]);
     275
     276        for (i = 0; i < ARRAYSIZE(SL_TABLE_SEED); i++)
     277                SL_TABLE[i] = SC_SL(SL_TABLE_SEED[i]);
     278}
     279
     280#undef SC_KSL
     281#undef SC_SL
     282
     283/* --------------------- subroutines  --------------------- */
     284
     285/* status set and IRQ handling */
     286inline void OPL_STATUS_SET(FM_OPL *OPL, int flag) {
     287        /* set status flag */
     288        OPL->status |= flag;
     289        if(!(OPL->status & 0x80)) {
     290                if(OPL->status & OPL->statusmask) {     /* IRQ on */
     291                        OPL->status |= 0x80;
     292                        /* callback user interrupt handler (IRQ is OFF to ON) */
     293                        if(OPL->IRQHandler)
     294                                (OPL->IRQHandler)(OPL->IRQParam,1);
     295                }
     296        }
     297}
     298
     299/* status reset and IRQ handling */
     300inline void OPL_STATUS_RESET(FM_OPL *OPL, int flag) {
     301        /* reset status flag */
     302        OPL->status &= ~flag;
     303        if((OPL->status & 0x80)) {
     304                if (!(OPL->status & OPL->statusmask)) {
     305                        OPL->status &= 0x7f;
     306                        /* callback user interrupt handler (IRQ is ON to OFF) */
     307                        if(OPL->IRQHandler) (OPL->IRQHandler)(OPL->IRQParam,0);
     308                }
     309        }
     310}
     311
     312/* IRQ mask set */
     313inline void OPL_STATUSMASK_SET(FM_OPL *OPL, int flag) {
     314        OPL->statusmask = flag;
     315        /* IRQ handling check */
     316        OPL_STATUS_SET(OPL,0);
     317        OPL_STATUS_RESET(OPL,0);
     318}
     319
     320/* ----- key on  ----- */
     321inline void OPL_KEYON(OPL_SLOT *SLOT) {
     322        /* sin wave restart */
     323        SLOT->Cnt = 0;
     324        /* set attack */
     325        SLOT->evm = ENV_MOD_AR;
     326        SLOT->evs = SLOT->evsa;
     327        SLOT->evc = EG_AST;
     328        SLOT->eve = EG_AED;
     329}
     330
     331/* ----- key off ----- */
     332inline void OPL_KEYOFF(OPL_SLOT *SLOT) {
     333        if( SLOT->evm > ENV_MOD_RR) {
     334                /* set envelope counter from envleope output */
     335
     336                // WORKAROUND: The Kyra engine does something very strange when
     337                // starting a new song. For each channel:
     338                //
     339                // * The release rate is set to "fastest".
     340                // * Any note is keyed off.
     341                // * A very low-frequency note is keyed on.
     342                //
     343                // Usually, what happens next is that the real notes is keyed
     344                // on immediately, in which case there's no problem.
     345                //
     346                // However, if the note is again keyed off (because the channel
     347                // begins on a rest rather than a note), the envelope counter
     348                // was moved from the very lowest point on the attack curve to
     349                // the very highest point on the release curve.
     350                //
     351                // Again, this might not be a problem, if the release rate is
     352                // still set to "fastest". But in many cases, it had already
     353                // been increased. And, possibly because of inaccuracies in the
     354                // envelope generator, that would cause the note to "fade out"
     355                // for quite a long time.
     356                //
     357                // What we really need is a way to find the correct starting
     358                // point for the envelope counter, and that may be what the
     359                // commented-out line below is meant to do. For now, simply
     360                // handle the pathological case.
     361
     362                if (SLOT->evm == ENV_MOD_AR && SLOT->evc == EG_AST)
     363                        SLOT->evc = EG_DED;
     364                else if( !(SLOT->evc & EG_DST) )
     365                        //SLOT->evc = (ENV_CURVE[SLOT->evc>>ENV_BITS]<<ENV_BITS) + EG_DST;
     366                        SLOT->evc = EG_DST;
     367                SLOT->eve = EG_DED;
     368                SLOT->evs = SLOT->evsr;
     369                SLOT->evm = ENV_MOD_RR;
     370        }
     371}
     372
     373/* ---------- calcrate Envelope Generator & Phase Generator ---------- */
     374
     375/* return : envelope output */
     376inline uint OPL_CALC_SLOT(OPL_SLOT *SLOT) {
     377        /* calcrate envelope generator */
     378        if((SLOT->evc += SLOT->evs) >= SLOT->eve) {
     379                switch( SLOT->evm ) {
     380                case ENV_MOD_AR: /* ATTACK -> DECAY1 */
     381                        /* next DR */
     382                        SLOT->evm = ENV_MOD_DR;
     383                        SLOT->evc = EG_DST;
     384                        SLOT->eve = SLOT->SL;
     385                        SLOT->evs = SLOT->evsd;
     386                        break;
     387                case ENV_MOD_DR: /* DECAY -> SL or RR */
     388                        SLOT->evc = SLOT->SL;
     389                        SLOT->eve = EG_DED;
     390                        if(SLOT->eg_typ) {
     391                                SLOT->evs = 0;
     392                        } else {
     393                                SLOT->evm = ENV_MOD_RR;
     394                                SLOT->evs = SLOT->evsr;
     395                        }
     396                        break;
     397                case ENV_MOD_RR: /* RR -> OFF */
     398                        SLOT->evc = EG_OFF;
     399                        SLOT->eve = EG_OFF + 1;
     400                        SLOT->evs = 0;
     401                        break;
     402                }
     403        }
     404        /* calcrate envelope */
     405        return SLOT->TLL + ENV_CURVE[SLOT->evc>>ENV_BITS] + (SLOT->ams ? ams : 0);
     406}
     407
     408/* set algorythm connection */
     409static void set_algorythm(OPL_CH *CH) {
     410        int *carrier = &outd[0];
     411        CH->connect1 = CH->CON ? carrier : &feedback2;
     412        CH->connect2 = carrier;
     413}
     414
     415/* ---------- frequency counter for operater update ---------- */
     416inline void CALC_FCSLOT(OPL_CH *CH, OPL_SLOT *SLOT) {
     417        int ksr;
     418
     419        /* frequency step counter */
     420        SLOT->Incr = CH->fc * SLOT->mul;
     421        ksr = CH->kcode >> SLOT->KSR;
     422
     423        if( SLOT->ksr != ksr ) {
     424                SLOT->ksr = ksr;
     425                /* attack , decay rate recalcration */
     426                SLOT->evsa = SLOT->AR[ksr];
     427                SLOT->evsd = SLOT->DR[ksr];
     428                SLOT->evsr = SLOT->RR[ksr];
     429        }
     430        SLOT->TLL = SLOT->TL + (CH->ksl_base>>SLOT->ksl);
     431}
     432
     433/* set multi,am,vib,EG-TYP,KSR,mul */
     434inline void set_mul(FM_OPL *OPL, int slot, int v) {
     435        OPL_CH   *CH   = &OPL->P_CH[slot>>1];
     436        OPL_SLOT *SLOT = &CH->SLOT[slot & 1];
     437
     438        SLOT->mul    = MUL_TABLE[v & 0x0f];
     439        SLOT->KSR    = (v & 0x10) ? 0 : 2;
     440        SLOT->eg_typ = (v & 0x20) >> 5;
     441        SLOT->vib    = (v & 0x40);
     442        SLOT->ams    = (v & 0x80);
     443        CALC_FCSLOT(CH, SLOT);
     444}
     445
     446/* set ksl & tl */
     447inline void set_ksl_tl(FM_OPL *OPL, int slot, int v) {
     448        OPL_CH   *CH   = &OPL->P_CH[slot>>1];
     449        OPL_SLOT *SLOT = &CH->SLOT[slot & 1];
     450        int ksl = v >> 6; /* 0 / 1.5 / 3 / 6 db/OCT */
     451
     452        SLOT->ksl = ksl ? 3-ksl : 31;
     453        SLOT->TL  = (int)((v & 0x3f) * (0.75 / EG_STEP)); /* 0.75db step */
     454
     455        if(!(OPL->mode & 0x80)) {       /* not CSM latch total level */
     456                SLOT->TLL = SLOT->TL + (CH->ksl_base >> SLOT->ksl);
     457        }
     458}
     459
     460/* set attack rate & decay rate  */
     461inline void set_ar_dr(FM_OPL *OPL, int slot, int v) {
     462        OPL_CH   *CH   = &OPL->P_CH[slot>>1];
     463        OPL_SLOT *SLOT = &CH->SLOT[slot & 1];
     464        int ar = v >> 4;
     465        int dr = v & 0x0f;
     466
     467        SLOT->AR = ar ? &OPL->AR_TABLE[ar << 2] : RATE_0;
     468        SLOT->evsa = SLOT->AR[SLOT->ksr];
     469        if(SLOT->evm == ENV_MOD_AR)
     470                SLOT->evs = SLOT->evsa;
     471
     472        SLOT->DR = dr ? &OPL->DR_TABLE[dr<<2] : RATE_0;
     473        SLOT->evsd = SLOT->DR[SLOT->ksr];
     474        if(SLOT->evm == ENV_MOD_DR)
     475                SLOT->evs = SLOT->evsd;
     476}
     477
     478/* set sustain level & release rate */
     479inline void set_sl_rr(FM_OPL *OPL, int slot, int v) {
     480        OPL_CH   *CH   = &OPL->P_CH[slot>>1];
     481        OPL_SLOT *SLOT = &CH->SLOT[slot & 1];
     482        int sl = v >> 4;
     483        int rr = v & 0x0f;
     484
     485        SLOT->SL = SL_TABLE[sl];
     486        if(SLOT->evm == ENV_MOD_DR)
     487                SLOT->eve = SLOT->SL;
     488        SLOT->RR = &OPL->DR_TABLE[rr<<2];
     489        SLOT->evsr = SLOT->RR[SLOT->ksr];
     490        if(SLOT->evm == ENV_MOD_RR)
     491                SLOT->evs = SLOT->evsr;
     492}
     493
     494/* operator output calcrator */
     495
     496#define OP_OUT(slot,env,con)   slot->wavetable[((slot->Cnt + con)>>(24-SIN_ENT_SHIFT)) & (SIN_ENT-1)][env]
     497/* ---------- calcrate one of channel ---------- */
     498inline void OPL_CALC_CH(OPL_CH *CH) {
     499        uint env_out;
     500        OPL_SLOT *SLOT;
     501
     502        feedback2 = 0;
     503        /* SLOT 1 */
     504        SLOT = &CH->SLOT[SLOT1];
     505        env_out=OPL_CALC_SLOT(SLOT);
     506        if(env_out < (uint)(EG_ENT - 1)) {
     507                /* PG */
     508                if(SLOT->vib)
     509                        SLOT->Cnt += (SLOT->Incr * vib) >> VIB_RATE_SHIFT;
     510                else
     511                        SLOT->Cnt += SLOT->Incr;
     512                /* connection */
     513                if(CH->FB) {
     514                        int feedback1 = (CH->op1_out[0] + CH->op1_out[1]) >> CH->FB;
     515                        CH->op1_out[1] = CH->op1_out[0];
     516                        *CH->connect1 += CH->op1_out[0] = OP_OUT(SLOT, env_out, feedback1);
     517                } else {
     518                        *CH->connect1 += OP_OUT(SLOT, env_out, 0);
     519                }
     520        } else {
     521                CH->op1_out[1] = CH->op1_out[0];
     522                CH->op1_out[0] = 0;
     523        }
     524        /* SLOT 2 */
     525        SLOT = &CH->SLOT[SLOT2];
     526        env_out=OPL_CALC_SLOT(SLOT);
     527        if(env_out < (uint)(EG_ENT - 1)) {
     528                /* PG */
     529                if(SLOT->vib)
     530                        SLOT->Cnt += (SLOT->Incr * vib) >> VIB_RATE_SHIFT;
     531                else
     532                        SLOT->Cnt += SLOT->Incr;
     533                /* connection */
     534                outd[0] += OP_OUT(SLOT, env_out, feedback2);
     535        }
     536}
     537
     538/* ---------- calcrate rythm block ---------- */
     539#define WHITE_NOISE_db 6.0
     540inline void OPL_CALC_RH(FM_OPL *OPL, OPL_CH *CH) {
     541        uint env_tam, env_sd, env_top, env_hh;
     542        // This code used to do int(OPL->rnd.getRandomBit() * (WHITE_NOISE_db / EG_STEP)),
     543        // but EG_STEP = 96.0/EG_ENT, and WHITE_NOISE_db=6.0. So, that's equivalent to
     544        // int(OPL->rnd.getRandomBit() * EG_ENT/16). We know that EG_ENT is 4096, or 1024,
     545        // or 128, so we can safely avoid any FP ops.
     546        int whitenoise = OPL->rnd.getRandomBit() * (EG_ENT>>4);
     547
     548        int tone8;
     549
     550        OPL_SLOT *SLOT;
     551        int env_out;
     552
     553        /* BD : same as FM serial mode and output level is large */
     554        feedback2 = 0;
     555        /* SLOT 1 */
     556        SLOT = &CH[6].SLOT[SLOT1];
     557        env_out = OPL_CALC_SLOT(SLOT);
     558        if(env_out < EG_ENT-1) {
     559                /* PG */
     560                if(SLOT->vib)
     561                        SLOT->Cnt += (SLOT->Incr * vib) >> VIB_RATE_SHIFT;
     562                else
     563                        SLOT->Cnt += SLOT->Incr;
     564                /* connection */
     565                if(CH[6].FB) {
     566                        int feedback1 = (CH[6].op1_out[0] + CH[6].op1_out[1]) >> CH[6].FB;
     567                        CH[6].op1_out[1] = CH[6].op1_out[0];
     568                        feedback2 = CH[6].op1_out[0] = OP_OUT(SLOT, env_out, feedback1);
     569                }
     570                else {
     571                        feedback2 = OP_OUT(SLOT, env_out, 0);
     572                }
     573        } else {
     574                feedback2 = 0;
     575                CH[6].op1_out[1] = CH[6].op1_out[0];
     576                CH[6].op1_out[0] = 0;
     577        }
     578        /* SLOT 2 */
     579        SLOT = &CH[6].SLOT[SLOT2];
     580        env_out = OPL_CALC_SLOT(SLOT);
     581        if(env_out < EG_ENT-1) {
     582                /* PG */
     583                if(SLOT->vib)
     584                        SLOT->Cnt += (SLOT->Incr * vib) >> VIB_RATE_SHIFT;
     585                else
     586                        SLOT->Cnt += SLOT->Incr;
     587                /* connection */
     588                outd[0] += OP_OUT(SLOT, env_out, feedback2) * 2;
     589        }
     590
     591        // SD  (17) = mul14[fnum7] + white noise
     592        // TAM (15) = mul15[fnum8]
     593        // TOP (18) = fnum6(mul18[fnum8]+whitenoise)
     594        // HH  (14) = fnum7(mul18[fnum8]+whitenoise) + white noise
     595        env_sd = OPL_CALC_SLOT(SLOT7_2) + whitenoise;
     596        env_tam =OPL_CALC_SLOT(SLOT8_1);
     597        env_top = OPL_CALC_SLOT(SLOT8_2);
     598        env_hh = OPL_CALC_SLOT(SLOT7_1) + whitenoise;
     599
     600        /* PG */
     601        if(SLOT7_1->vib)
     602                SLOT7_1->Cnt += (SLOT7_1->Incr * vib) >> (VIB_RATE_SHIFT-1);
     603        else
     604                SLOT7_1->Cnt += 2 * SLOT7_1->Incr;
     605        if(SLOT7_2->vib)
     606                SLOT7_2->Cnt += (CH[7].fc * vib) >> (VIB_RATE_SHIFT-3);
     607        else
     608                SLOT7_2->Cnt += (CH[7].fc * 8);
     609        if(SLOT8_1->vib)
     610                SLOT8_1->Cnt += (SLOT8_1->Incr * vib) >> VIB_RATE_SHIFT;
     611        else
     612                SLOT8_1->Cnt += SLOT8_1->Incr;
     613        if(SLOT8_2->vib)
     614                SLOT8_2->Cnt += ((CH[8].fc * 3) * vib) >> (VIB_RATE_SHIFT-4);
     615        else
     616                SLOT8_2->Cnt += (CH[8].fc * 48);
     617
     618        tone8 = OP_OUT(SLOT8_2,whitenoise,0 );
     619
     620        /* SD */
     621        if(env_sd < (uint)(EG_ENT - 1))
     622                outd[0] += OP_OUT(SLOT7_1, env_sd, 0) * 8;
     623        /* TAM */
     624        if(env_tam < (uint)(EG_ENT - 1))
     625                outd[0] += OP_OUT(SLOT8_1, env_tam, 0) * 2;
     626        /* TOP-CY */
     627        if(env_top < (uint)(EG_ENT - 1))
     628                outd[0] += OP_OUT(SLOT7_2, env_top, tone8) * 2;
     629        /* HH */
     630        if(env_hh  < (uint)(EG_ENT-1))
     631                outd[0] += OP_OUT(SLOT7_2, env_hh, tone8) * 2;
     632}
     633
     634/* ----------- initialize time tabls ----------- */
     635static void init_timetables(FM_OPL *OPL, int ARRATE, int DRRATE) {
     636        int i;
     637        double rate;
     638
     639        /* make attack rate & decay rate tables */
     640        for (i = 0; i < 4; i++)
     641                OPL->AR_TABLE[i] = OPL->DR_TABLE[i] = 0;
     642        for (i = 4; i <= 60; i++) {
     643                rate = OPL->freqbase;                                           /* frequency rate */
     644                if(i < 60)
     645                        rate *= 1.0 + (i & 3) * 0.25;           /* b0-1 : x1 , x1.25 , x1.5 , x1.75 */
     646                rate *= 1 << ((i >> 2) - 1);                                            /* b2-5 : shift bit */
     647                rate *= (double)(EG_ENT << ENV_BITS);
     648                OPL->AR_TABLE[i] = (int)(rate / ARRATE);
     649                OPL->DR_TABLE[i] = (int)(rate / DRRATE);
     650        }
     651        for (i = 60; i < 76; i++) {
     652                OPL->AR_TABLE[i] = EG_AED-1;
     653                OPL->DR_TABLE[i] = OPL->DR_TABLE[60];
     654        }
     655}
     656
     657/* ---------- generic table initialize ---------- */
     658static int OPLOpenTable(void) {
     659        int s,t;
     660        double rate;
     661        int i,j;
     662        double pom;
     663
     664#ifdef __DS__
     665        DS::fastRamReset();
     666
     667        TL_TABLE = (int *) DS::fastRamAlloc(TL_MAX * 2 * sizeof(int *));
     668        SIN_TABLE = (int **) DS::fastRamAlloc(SIN_ENT * 4 * sizeof(int *));
     669#else
     670
     671        /* allocate dynamic tables */
     672        if((TL_TABLE = (int *)malloc(TL_MAX * 2 * sizeof(int))) == NULL)
     673                return 0;
     674
     675        if((SIN_TABLE = (int **)malloc(SIN_ENT * 4 * sizeof(int *))) == NULL) {
     676                free(TL_TABLE);
     677                return 0;
     678        }
     679#endif
     680
     681        if((AMS_TABLE = (int *)malloc(AMS_ENT * 2 * sizeof(int))) == NULL) {
     682                free(TL_TABLE);
     683                free(SIN_TABLE);
     684                return 0;
     685        }
     686
     687        if((VIB_TABLE = (int *)malloc(VIB_ENT * 2 * sizeof(int))) == NULL) {
     688                free(TL_TABLE);
     689                free(SIN_TABLE);
     690                free(AMS_TABLE);
     691                return 0;
     692        }
     693        /* make total level table */
     694        for (t = 0; t < EG_ENT - 1 ; t++) {
     695                rate = ((1 << TL_BITS) - 1) / pow(10.0, EG_STEP * t / 20);      /* dB -> voltage */
     696                TL_TABLE[         t] =  (int)rate;
     697                TL_TABLE[TL_MAX + t] = -TL_TABLE[t];
     698        }
     699        /* fill volume off area */
     700        for (t = EG_ENT - 1; t < TL_MAX; t++) {
     701                TL_TABLE[t] = TL_TABLE[TL_MAX + t] = 0;
     702        }
     703
     704        /* make sinwave table (total level offet) */
     705        /* degree 0 = degree 180                   = off */
     706        SIN_TABLE[0] = SIN_TABLE[SIN_ENT /2 ] = &TL_TABLE[EG_ENT - 1];
     707        for (s = 1;s <= SIN_ENT / 4; s++) {
     708                pom = sin(2 * PI * s / SIN_ENT); /* sin     */
     709                pom = 20 * log10(1 / pom);         /* decibel */
     710                j = int(pom / EG_STEP);         /* TL_TABLE steps */
     711
     712                /* degree 0   -  90    , degree 180 -  90 : plus section */
     713                SIN_TABLE[          s] = SIN_TABLE[SIN_ENT / 2 - s] = &TL_TABLE[j];
     714                /* degree 180 - 270    , degree 360 - 270 : minus section */
     715                SIN_TABLE[SIN_ENT / 2 + s] = SIN_TABLE[SIN_ENT - s] = &TL_TABLE[TL_MAX + j];
     716        }
     717        for (s = 0;s < SIN_ENT; s++) {
     718                SIN_TABLE[SIN_ENT * 1 + s] = s < (SIN_ENT / 2) ? SIN_TABLE[s] : &TL_TABLE[EG_ENT];
     719                SIN_TABLE[SIN_ENT * 2 + s] = SIN_TABLE[s % (SIN_ENT / 2)];
     720                SIN_TABLE[SIN_ENT * 3 + s] = (s / (SIN_ENT / 4)) & 1 ? &TL_TABLE[EG_ENT] : SIN_TABLE[SIN_ENT * 2 + s];
     721        }
     722
     723
     724        ENV_CURVE = (int *)malloc(sizeof(int) * (2*EG_ENT+1));
     725
     726        /* envelope counter -> envelope output table */
     727        for (i=0; i < EG_ENT; i++) {
     728                /* ATTACK curve */
     729                pom = pow(((double)(EG_ENT - 1 - i) / EG_ENT), 8) * EG_ENT;
     730                /* if( pom >= EG_ENT ) pom = EG_ENT-1; */
     731                ENV_CURVE[i] = (int)pom;
     732                /* DECAY ,RELEASE curve */
     733                ENV_CURVE[(EG_DST >> ENV_BITS) + i]= i;
     734        }
     735        /* off */
     736        ENV_CURVE[EG_OFF >> ENV_BITS]= EG_ENT - 1;
     737        /* make LFO ams table */
     738        for (i=0; i < AMS_ENT; i++) {
     739                pom = (1.0 + sin(2 * PI * i / AMS_ENT)) / 2; /* sin */
     740                AMS_TABLE[i]         = (int)((1.0 / EG_STEP) * pom); /* 1dB   */
     741                AMS_TABLE[AMS_ENT + i] = (int)((4.8 / EG_STEP) * pom); /* 4.8dB */
     742        }
     743        /* make LFO vibrate table */
     744        for (i=0; i < VIB_ENT; i++) {
     745                /* 100cent = 1seminote = 6% ?? */
     746                pom = (double)VIB_RATE * 0.06 * sin(2 * PI * i / VIB_ENT); /* +-100sect step */
     747                VIB_TABLE[i]         = (int)(VIB_RATE + (pom * 0.07)); /* +- 7cent */
     748                VIB_TABLE[VIB_ENT + i] = (int)(VIB_RATE + (pom * 0.14)); /* +-14cent */
     749        }
     750        return 1;
     751}
     752
     753static void OPLCloseTable(void) {
     754        free(TL_TABLE);
     755        free(SIN_TABLE);
     756        free(AMS_TABLE);
     757        free(VIB_TABLE);
     758        free(ENV_CURVE);
     759}
     760
     761/* CSM Key Controll */
     762inline void CSMKeyControll(OPL_CH *CH) {
     763        OPL_SLOT *slot1 = &CH->SLOT[SLOT1];
     764        OPL_SLOT *slot2 = &CH->SLOT[SLOT2];
     765        /* all key off */
     766        OPL_KEYOFF(slot1);
     767        OPL_KEYOFF(slot2);
     768        /* total level latch */
     769        slot1->TLL = slot1->TL + (CH->ksl_base>>slot1->ksl);
     770        slot1->TLL = slot1->TL + (CH->ksl_base>>slot1->ksl);
     771        /* key on */
     772        CH->op1_out[0] = CH->op1_out[1] = 0;
     773        OPL_KEYON(slot1);
     774        OPL_KEYON(slot2);
     775}
     776
     777/* ---------- opl initialize ---------- */
     778static void OPL_initalize(FM_OPL *OPL) {
     779        int fn;
     780
     781        /* frequency base */
     782        OPL->freqbase = (OPL->rate) ? ((double)OPL->clock / OPL->rate) / 72 : 0;
     783        /* Timer base time */
     784        OPL->TimerBase = 1.0/((double)OPL->clock / 72.0 );
     785        /* make time tables */
     786        init_timetables(OPL, OPL_ARRATE, OPL_DRRATE);
     787        /* make fnumber -> increment counter table */
     788        for( fn=0; fn < 1024; fn++) {
     789                OPL->FN_TABLE[fn] = (uint)(OPL->freqbase * fn * FREQ_RATE * (1<<7) / 2);
     790        }
     791        /* LFO freq.table */
     792        OPL->amsIncr = (int)(OPL->rate ? (double)AMS_ENT * (1 << AMS_SHIFT) / OPL->rate * 3.7 * ((double)OPL->clock/3600000) : 0);
     793        OPL->vibIncr = (int)(OPL->rate ? (double)VIB_ENT * (1 << VIB_SHIFT) / OPL->rate * 6.4 * ((double)OPL->clock/3600000) : 0);
     794}
     795
     796/* ---------- write a OPL registers ---------- */
     797void OPLWriteReg(FM_OPL *OPL, int r, int v) {
     798        OPL_CH *CH;
     799        int slot;
     800        uint block_fnum;
     801
     802        switch(r & 0xe0) {
     803        case 0x00: /* 00-1f:controll */
     804                switch(r & 0x1f) {
     805                case 0x01:
     806                        /* wave selector enable */
     807                        if(OPL->type&OPL_TYPE_WAVESEL) {
     808                                OPL->wavesel = v & 0x20;
     809                                if(!OPL->wavesel) {
     810                                        /* preset compatible mode */
     811                                        int c;
     812                                        for(c=0; c<OPL->max_ch; c++) {
     813                                                OPL->P_CH[c].SLOT[SLOT1].wavetable = &SIN_TABLE[0];
     814                                                OPL->P_CH[c].SLOT[SLOT2].wavetable = &SIN_TABLE[0];
     815                                        }
     816                                }
     817                        }
     818                        return;
     819                case 0x02:      /* Timer 1 */
     820                        OPL->T[0] = (256-v) * 4;
     821                        break;
     822                case 0x03:      /* Timer 2 */
     823                        OPL->T[1] = (256-v) * 16;
     824                        return;
     825                case 0x04:      /* IRQ clear / mask and Timer enable */
     826                        if(v & 0x80) {  /* IRQ flag clear */
     827                                OPL_STATUS_RESET(OPL, 0x7f);
     828                        } else {        /* set IRQ mask ,timer enable*/
     829                                uint8 st1 = v & 1;
     830                                uint8 st2 = (v >> 1) & 1;
     831                                /* IRQRST,T1MSK,t2MSK,EOSMSK,BRMSK,x,ST2,ST1 */
     832                                OPL_STATUS_RESET(OPL, v & 0x78);
     833                                OPL_STATUSMASK_SET(OPL,((~v) & 0x78) | 0x01);
     834                                /* timer 2 */
     835                                if(OPL->st[1] != st2) {
     836                                        double interval = st2 ? (double)OPL->T[1] * OPL->TimerBase : 0.0;
     837                                        OPL->st[1] = st2;
     838                                        if (OPL->TimerHandler) (OPL->TimerHandler)(OPL->TimerParam + 1, interval);
     839                                }
     840                                /* timer 1 */
     841                                if(OPL->st[0] != st1) {
     842                                        double interval = st1 ? (double)OPL->T[0] * OPL->TimerBase : 0.0;
     843                                        OPL->st[0] = st1;
     844                                        if (OPL->TimerHandler) (OPL->TimerHandler)(OPL->TimerParam + 0, interval);
     845                                }
     846                        }
     847                        return;
     848                }
     849                break;
     850        case 0x20:      /* am,vib,ksr,eg type,mul */
     851                slot = slot_array[r&0x1f];
     852                if(slot == -1)
     853                        return;
     854                set_mul(OPL,slot,v);
     855                return;
     856        case 0x40:
     857                slot = slot_array[r&0x1f];
     858                if(slot == -1)
     859                        return;
     860                set_ksl_tl(OPL,slot,v);
     861                return;
     862        case 0x60:
     863                slot = slot_array[r&0x1f];
     864                if(slot == -1)
     865                        return;
     866                set_ar_dr(OPL,slot,v);
     867                return;
     868        case 0x80:
     869                slot = slot_array[r&0x1f];
     870                if(slot == -1)
     871                        return;
     872                set_sl_rr(OPL,slot,v);
     873                return;
     874        case 0xa0:
     875                switch(r) {
     876                case 0xbd:
     877                        /* amsep,vibdep,r,bd,sd,tom,tc,hh */
     878                        {
     879                        uint8 rkey = OPL->rythm ^ v;
     880                        OPL->ams_table = &AMS_TABLE[v & 0x80 ? AMS_ENT : 0];
     881                        OPL->vib_table = &VIB_TABLE[v & 0x40 ? VIB_ENT : 0];
     882                        OPL->rythm  = v & 0x3f;
     883                        if(OPL->rythm & 0x20) {
     884                                /* BD key on/off */
     885                                if(rkey & 0x10) {
     886                                        if(v & 0x10) {
     887                                                OPL->P_CH[6].op1_out[0] = OPL->P_CH[6].op1_out[1] = 0;
     888                                                OPL_KEYON(&OPL->P_CH[6].SLOT[SLOT1]);
     889                                                OPL_KEYON(&OPL->P_CH[6].SLOT[SLOT2]);
     890                                        } else {
     891                                                OPL_KEYOFF(&OPL->P_CH[6].SLOT[SLOT1]);
     892                                                OPL_KEYOFF(&OPL->P_CH[6].SLOT[SLOT2]);
     893                                        }
     894                                }
     895                                /* SD key on/off */
     896                                if(rkey & 0x08) {
     897                                        if(v & 0x08)
     898                                                OPL_KEYON(&OPL->P_CH[7].SLOT[SLOT2]);
     899                                        else
     900                                                OPL_KEYOFF(&OPL->P_CH[7].SLOT[SLOT2]);
     901                                }/* TAM key on/off */
     902                                if(rkey & 0x04) {
     903                                        if(v & 0x04)
     904                                                OPL_KEYON(&OPL->P_CH[8].SLOT[SLOT1]);
     905                                        else
     906                                                OPL_KEYOFF(&OPL->P_CH[8].SLOT[SLOT1]);
     907                                }
     908                                /* TOP-CY key on/off */
     909                                if(rkey & 0x02) {
     910                                        if(v & 0x02)
     911                                                OPL_KEYON(&OPL->P_CH[8].SLOT[SLOT2]);
     912                                        else
     913                                                OPL_KEYOFF(&OPL->P_CH[8].SLOT[SLOT2]);
     914                                }
     915                                /* HH key on/off */
     916                                if(rkey & 0x01) {
     917                                        if(v & 0x01)
     918                                                OPL_KEYON(&OPL->P_CH[7].SLOT[SLOT1]);
     919                                        else
     920                                                OPL_KEYOFF(&OPL->P_CH[7].SLOT[SLOT1]);
     921                                }
     922                        }
     923                        }
     924                        return;
     925
     926                default:
     927                        break;
     928                }
     929                /* keyon,block,fnum */
     930                if((r & 0x0f) > 8)
     931                        return;
     932                CH = &OPL->P_CH[r & 0x0f];
     933                if(!(r&0x10)) { /* a0-a8 */
     934                        block_fnum  = (CH->block_fnum & 0x1f00) | v;
     935                } else {        /* b0-b8 */
     936                        int keyon = (v >> 5) & 1;
     937                        block_fnum = ((v & 0x1f) << 8) | (CH->block_fnum & 0xff);
     938                        if(CH->keyon != keyon) {
     939                                if((CH->keyon=keyon)) {
     940                                        CH->op1_out[0] = CH->op1_out[1] = 0;
     941                                        OPL_KEYON(&CH->SLOT[SLOT1]);
     942                                        OPL_KEYON(&CH->SLOT[SLOT2]);
     943                                } else {
     944                                        OPL_KEYOFF(&CH->SLOT[SLOT1]);
     945                                        OPL_KEYOFF(&CH->SLOT[SLOT2]);
     946                                }
     947                        }
     948                }
     949                /* update */
     950                if(CH->block_fnum != block_fnum) {
     951                        int blockRv = 7 - (block_fnum >> 10);
     952                        int fnum = block_fnum & 0x3ff;
     953                        CH->block_fnum = block_fnum;
     954                        CH->ksl_base = KSL_TABLE[block_fnum >> 6];
     955                        CH->fc = OPL->FN_TABLE[fnum] >> blockRv;
     956                        CH->kcode = CH->block_fnum >> 9;
     957                        if((OPL->mode & 0x40) && CH->block_fnum & 0x100)
     958                                CH->kcode |=1;
     959                        CALC_FCSLOT(CH,&CH->SLOT[SLOT1]);
     960                        CALC_FCSLOT(CH,&CH->SLOT[SLOT2]);
     961                }
     962                return;
     963        case 0xc0:
     964                /* FB,C */
     965                if((r & 0x0f) > 8)
     966                        return;
     967                CH = &OPL->P_CH[r&0x0f];
     968                {
     969                        int feedback = (v >> 1) & 7;
     970                        CH->FB = feedback ? (8 + 1) - feedback : 0;
     971                        CH->CON = v & 1;
     972                        set_algorythm(CH);
     973                }
     974                return;
     975        case 0xe0: /* wave type */
     976                slot = slot_array[r & 0x1f];
     977                if(slot == -1)
     978                        return;
     979                CH = &OPL->P_CH[slot>>1];
     980                if(OPL->wavesel) {
     981                        CH->SLOT[slot&1].wavetable = &SIN_TABLE[(v & 0x03) * SIN_ENT];
     982                }
     983                return;
     984        }
     985}
     986
     987/* lock/unlock for common table */
     988static int OPL_LockTable(void) {
     989        num_lock++;
     990        if(num_lock>1)
     991                return 0;
     992        /* first time */
     993        cur_chip = NULL;
     994        /* allocate total level table (128kb space) */
     995        if(!OPLOpenTable()) {
     996                num_lock--;
     997                return -1;
     998        }
     999        return 0;
     1000}
     1001
     1002static void OPL_UnLockTable(void) {
     1003        if(num_lock)
     1004                num_lock--;
     1005        if(num_lock)
     1006                return;
     1007        /* last time */
     1008        cur_chip = NULL;
     1009        OPLCloseTable();
     1010}
     1011
     1012/*******************************************************************************/
     1013/*              YM3812 local section                                                   */
     1014/*******************************************************************************/
     1015
     1016/* ---------- update one of chip ----------- */
     1017void YM3812UpdateOne(FM_OPL *OPL, int16 *buffer, int length, int interleave) {
     1018        int i;
     1019        int data;
     1020        int16 *buf = buffer;
     1021        uint amsCnt = OPL->amsCnt;
     1022        uint vibCnt = OPL->vibCnt;
     1023        uint8 rythm = OPL->rythm & 0x20;
     1024        OPL_CH *CH, *R_CH;
     1025
     1026
     1027        if((void *)OPL != cur_chip) {
     1028                cur_chip = (void *)OPL;
     1029                /* channel pointers */
     1030                S_CH = OPL->P_CH;
     1031                E_CH = &S_CH[9];
     1032                /* rythm slot */
     1033                SLOT7_1 = &S_CH[7].SLOT[SLOT1];
     1034                SLOT7_2 = &S_CH[7].SLOT[SLOT2];
     1035                SLOT8_1 = &S_CH[8].SLOT[SLOT1];
     1036                SLOT8_2 = &S_CH[8].SLOT[SLOT2];
     1037                /* LFO state */
     1038                amsIncr = OPL->amsIncr;
     1039                vibIncr = OPL->vibIncr;
     1040                ams_table = OPL->ams_table;
     1041                vib_table = OPL->vib_table;
     1042        }
     1043        R_CH = rythm ? &S_CH[6] : E_CH;
     1044        for(i = 0; i < length; i++) {
     1045                /*            channel A         channel B         channel C      */
     1046                /* LFO */
     1047                ams = ams_table[(amsCnt += amsIncr) >> AMS_SHIFT];
     1048                vib = vib_table[(vibCnt += vibIncr) >> VIB_SHIFT];
     1049                outd[0] = 0;
     1050                /* FM part */
     1051                for(CH=S_CH; CH < R_CH; CH++)
     1052                        OPL_CALC_CH(CH);
     1053                /* Rythn part */
     1054                if(rythm)
     1055                        OPL_CALC_RH(OPL, S_CH);
     1056                /* limit check */
     1057                data = CLIP(outd[0], OPL_MINOUT, OPL_MAXOUT);
     1058                /* store to sound buffer */
     1059                buf[i << interleave] = data >> OPL_OUTSB;
     1060        }
     1061
     1062        OPL->amsCnt = amsCnt;
     1063        OPL->vibCnt = vibCnt;
     1064}
     1065
     1066/* ---------- reset a chip ---------- */
     1067void OPLResetChip(FM_OPL *OPL) {
     1068        int c,s;
     1069        int i;
     1070
     1071        /* reset chip */
     1072        OPL->mode = 0;  /* normal mode */
     1073        OPL_STATUS_RESET(OPL, 0x7f);
     1074        /* reset with register write */
     1075        OPLWriteReg(OPL, 0x01,0); /* wabesel disable */
     1076        OPLWriteReg(OPL, 0x02,0); /* Timer1 */
     1077        OPLWriteReg(OPL, 0x03,0); /* Timer2 */
     1078        OPLWriteReg(OPL, 0x04,0); /* IRQ mask clear */
     1079        for(i = 0xff; i >= 0x20; i--)
     1080                OPLWriteReg(OPL,i,0);
     1081        /* reset OPerator parameter */
     1082        for(c = 0; c < OPL->max_ch ;c++ ) {
     1083                OPL_CH *CH = &OPL->P_CH[c];
     1084                /* OPL->P_CH[c].PAN = OPN_CENTER; */
     1085                for(s = 0; s < 2; s++ ) {
     1086                        /* wave table */
     1087                        CH->SLOT[s].wavetable = &SIN_TABLE[0];
     1088                        /* CH->SLOT[s].evm = ENV_MOD_RR; */
     1089                        CH->SLOT[s].evc = EG_OFF;
     1090                        CH->SLOT[s].eve = EG_OFF + 1;
     1091                        CH->SLOT[s].evs = 0;
     1092                }
     1093        }
     1094}
     1095
     1096/* ----------  Create a virtual YM3812 ----------       */
     1097/* 'rate'  is sampling rate and 'bufsiz' is the size of the  */
     1098FM_OPL *OPLCreate(int type, int clock, int rate) {
     1099        char *ptr;
     1100        FM_OPL *OPL;
     1101        int state_size;
     1102        int max_ch = 9; /* normaly 9 channels */
     1103
     1104        if( OPL_LockTable() == -1)
     1105                return NULL;
     1106        /* allocate OPL state space */
     1107        state_size  = sizeof(FM_OPL);
     1108        state_size += sizeof(OPL_CH) * max_ch;
     1109
     1110        /* allocate memory block */
     1111        ptr = (char *)calloc(state_size, 1);
     1112        if(ptr == NULL)
     1113                return NULL;
     1114
     1115        /* clear */
     1116        memset(ptr, 0, state_size);
     1117        OPL       = (FM_OPL *)ptr; ptr += sizeof(FM_OPL);
     1118        OPL->P_CH = (OPL_CH *)ptr; ptr += sizeof(OPL_CH) * max_ch;
     1119
     1120        /* set channel state pointer */
     1121        OPL->type  = type;
     1122        OPL->clock = clock;
     1123        OPL->rate  = rate;
     1124        OPL->max_ch = max_ch;
     1125
     1126        /* init grobal tables */
     1127        OPL_initalize(OPL);
     1128
     1129        /* reset chip */
     1130        OPLResetChip(OPL);
     1131        return OPL;
     1132}
     1133
     1134/* ----------  Destroy one of vietual YM3812 ----------       */
     1135void OPLDestroy(FM_OPL *OPL) {
     1136        OPL_UnLockTable();
     1137        free(OPL);
     1138}
     1139
     1140/* ----------  Option handlers ----------       */
     1141void OPLSetTimerHandler(FM_OPL *OPL, OPL_TIMERHANDLER TimerHandler,int channelOffset) {
     1142        OPL->TimerHandler   = TimerHandler;
     1143        OPL->TimerParam = channelOffset;
     1144}
     1145
     1146void OPLSetIRQHandler(FM_OPL *OPL, OPL_IRQHANDLER IRQHandler, int param) {
     1147        OPL->IRQHandler     = IRQHandler;
     1148        OPL->IRQParam = param;
     1149}
     1150
     1151void OPLSetUpdateHandler(FM_OPL *OPL, OPL_UPDATEHANDLER UpdateHandler,int param) {
     1152        OPL->UpdateHandler = UpdateHandler;
     1153        OPL->UpdateParam = param;
     1154}
     1155
     1156/* ---------- YM3812 I/O interface ---------- */
     1157int OPLWrite(FM_OPL *OPL,int a,int v) {
     1158        if(!(a & 1)) {  /* address port */
     1159                OPL->address = v & 0xff;
     1160        } else {        /* data port */
     1161                if(OPL->UpdateHandler)
     1162                        OPL->UpdateHandler(OPL->UpdateParam,0);
     1163                OPLWriteReg(OPL, OPL->address,v);
     1164        }
     1165        return OPL->status >> 7;
     1166}
     1167
     1168unsigned char OPLRead(FM_OPL *OPL,int a) {
     1169        if(!(a & 1)) {  /* status port */
     1170                return OPL->status & (OPL->statusmask | 0x80);
     1171        }
     1172        /* data port */
     1173        switch(OPL->address) {
     1174        case 0x05: /* KeyBoard IN */
     1175                warning("OPL:read unmapped KEYBOARD port\n");
     1176                return 0;
     1177        case 0x19: /* I/O DATA    */
     1178                warning("OPL:read unmapped I/O port\n");
     1179                return 0;
     1180        case 0x1a: /* PCM-DATA    */
     1181                return 0;
     1182        default:
     1183                break;
     1184        }
     1185        return 0;
     1186}
     1187
     1188int OPLTimerOver(FM_OPL *OPL, int c) {
     1189        if(c) { /* Timer B */
     1190                OPL_STATUS_SET(OPL, 0x20);
     1191        } else {        /* Timer A */
     1192                OPL_STATUS_SET(OPL, 0x40);
     1193                /* CSM mode key,TL controll */
     1194                if(OPL->mode & 0x80) {  /* CSM mode total level latch and auto key on */
     1195                        int ch;
     1196                        if(OPL->UpdateHandler)
     1197                                OPL->UpdateHandler(OPL->UpdateParam,0);
     1198                        for(ch = 0; ch < 9; ch++)
     1199                                CSMKeyControll(&OPL->P_CH[ch]);
     1200                }
     1201        }
     1202        /* reload timer */
     1203        if (OPL->TimerHandler)
     1204                (OPL->TimerHandler)(OPL->TimerParam + c, (double)OPL->T[c] * OPL->TimerBase);
     1205        return OPL->status >> 7;
     1206}
     1207
     1208FM_OPL *makeAdlibOPL(int rate) {
     1209        // We need to emulate one YM3812 chip
     1210        int env_bits = FMOPL_ENV_BITS_HQ;
     1211        int eg_ent = FMOPL_EG_ENT_HQ;
     1212#if defined (_WIN32_WCE) || defined(__SYMBIAN32__) || defined(PALMOS_MODE) || defined(__GP32__) || defined (GP2X) || defined(__MAEMO__) || defined(__DS__) || defined (__MINT__)
     1213        if (ConfMan.hasKey("FM_high_quality") && ConfMan.getBool("FM_high_quality")) {
     1214                env_bits = FMOPL_ENV_BITS_HQ;
     1215                eg_ent = FMOPL_EG_ENT_HQ;
     1216        } else if (ConfMan.hasKey("FM_medium_quality") && ConfMan.getBool("FM_medium_quality")) {
     1217                env_bits = FMOPL_ENV_BITS_MQ;
     1218                eg_ent = FMOPL_EG_ENT_MQ;
     1219        } else {
     1220                env_bits = FMOPL_ENV_BITS_LQ;
     1221                eg_ent = FMOPL_EG_ENT_LQ;
     1222        }
     1223#endif
     1224
     1225        OPLBuildTables(env_bits, eg_ent);
     1226        return OPLCreate(OPL_TYPE_YM3812, 3579545, rate);
     1227}
     1228
     1229} // end of namespace MAME
     1230} // end of namespace OPL
     1231
  • sound/softsynth/opl/dbopl.cpp

     
     1/* ScummVM - Graphic Adventure Engine
     2 *
     3 * ScummVM is the legal property of its developers, whose names
     4 * are too numerous to list here. Please refer to the COPYRIGHT
     5 * file distributed with this source distribution.
     6 *
     7 * This program is free software; you can redistribute it and/or
     8 * modify it under the terms of the GNU General Public License
     9 * as published by the Free Software Foundation; either version 2
     10 * of the License, or (at your option) any later version.
     11 *
     12 * This program is distributed in the hope that it will be useful,
     13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15 * GNU General Public License for more details.
     16 *
     17 * You should have received a copy of the GNU General Public License
     18 * along with this program; if not, write to the Free Software
     19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
     20 *
     21 * $URL$
     22 * $Id$
     23 */
     24
     25/*
     26 * Based on AdLib emulation code of DOSBox
     27 * Copyright (C) 2002-2009  The DOSBox Team
     28 * Licensed under GPLv2+
     29 * http://www.dosbox.com
     30
     31 * Original source file header:
     32
     33 *  Copyright (C) 2002-2009  The DOSBox Team
     34 *
     35 *  This program is free software; you can redistribute it and/or modify
     36 *  it under the terms of the GNU General Public License as published by
     37 *  the Free Software Foundation; either version 2 of the License, or
     38 *  (at your option) any later version.
     39 *
     40 *  This program is distributed in the hope that it will be useful,
     41 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
     42 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     43 *  GNU General Public License for more details.
     44 *
     45 *  You should have received a copy of the GNU General Public License
     46 *  along with this program; if not, write to the Free Software
     47 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
     48 */
     49
     50/*
     51        DOSBox implementation of a combined Yamaha YMF262 and Yamaha YM3812 emulator.
     52        Enabling the opl3 bit will switch the emulator to stereo opl3 output instead of regular mono opl2
     53        Except for the table generation it's all integer math
     54        Can choose different types of generators, using muls and bigger tables, try different ones for slower platforms
     55        The generation was based on the MAME implementation but tried to have it use less memory and be faster in general
     56        MAME uses much bigger envelope tables and this will be the biggest cause of it sounding different at times
     57
     58        //TODO Don't delay first operator 1 sample in opl3 mode
     59        //TODO Maybe not use class method pointers but a regular function pointers with operator as first parameter
     60        //TODO Fix panning for the Percussion channels, would any opl3 player use it and actually really change it though?
     61        //TODO don't use variables in work structure for tremolo and vibrato but give the variables as parameters to GetSample
     62        //TODO Since the vibrato takes 1024 samples it's easier to run the emulator in same vibrato chunks, vibrato would be costfree
     63
     64        //DUNNO Keyon in 4op, switch to 2op without keyoff.
     65*/
     66
     67#ifndef DISABLE_DOSBOX_OPL
     68
     69#include "dbopl.h"
     70#include <stddef.h>     // for ptrdiff_t
     71
     72#ifndef PI
     73#define PI 3.14159265358979323846
     74#endif
     75
     76#ifndef INLINE
     77#define INLINE
     78#endif
     79
     80#define OFFS(type,item) (((ptrdiff_t)(&((type*)42)->type::item))-42)
     81
     82namespace OPL {
     83namespace DOSBox {
     84namespace DBOPL {
     85
     86#define MAX_SAMPLES 256
     87#define OPLRATE         ((double)(14318180.0 / 288.0))
     88
     89//Only need 4 valid bits at the top for vibrato
     90#define VIBRATO_SH      ( 32 - 4 )
     91//Need 6 bits of accuracy
     92#define TREMOLO_SH      ( 32 - 6 )
     93#define TREMOLO_TABLE 52
     94
     95//Wave bits available in the top of the 32bit range
     96//Original adlib uses 10.10, we use 12.20
     97//Have to keep some bits in the top to allow for freqmul 0.5
     98#define WAVE_BITS       12
     99#define WAVE_SH         ( 32 - WAVE_BITS )
     100#define WAVE_MASK       ( ( 1 << WAVE_SH ) - 1 )
     101
     102//Maximum amount of attenuation bits
     103//Envelope goes to 511, 9 bits
     104#if (DBOPL_WAVE == WAVE_TABLEMUL )
     105//Uses the value directly
     106#define ENV_BITS        ( 9 )
     107#else
     108//Add 3 bits here for more accuracy and would have to be shifted up either way
     109#define ENV_BITS        ( 9 )
     110#endif
     111//Limits of the envelope with those bits and when the envelope goes silent
     112#define ENV_MIN         0
     113#define ENV_EXTRA       ( ENV_BITS - 9 )
     114#define ENV_MAX         ( 511 << ENV_EXTRA )
     115#define ENV_LIMIT       ( ( 12 * 256) >> ( 3 - ENV_EXTRA ) )
     116#define ENV_SILENT( _X_ ) ( (_X_) >= ENV_LIMIT )
     117
     118//Attack/decay/release rate counter shift
     119#define RATE_SH         24
     120#define RATE_MASK       ( ( 1 << RATE_SH ) - 1 )
     121//Has to fit within 16bit lookuptable
     122#define MUL_SH          16
     123
     124//Check some ranges
     125#if ENV_EXTRA > 3
     126#error Too many envelope bits
     127#endif
     128
     129
     130//How much to substract from the base value for the final attenuation
     131static const Bit8u KslCreateTable[16] = {
     132        //0 will always be be lower than 7 * 8
     133        64, 32, 24, 19,
     134        16, 12, 11, 10,
     135         8,  6,  5,  4,
     136         3,  2,  1,  0,
     137};
     138
     139#define M(_X_) ((Bit8u)( (_X_) * 2))
     140static const Bit8u FreqCreateTable[16] = {
     141        M(0.5), M(1 ), M(2 ), M(3 ), M(4 ), M(5 ), M(6 ), M(7 ),
     142        M(8  ), M(9 ), M(10), M(10), M(12), M(12), M(15), M(15)
     143};
     144#undef M
     145
     146//We're not including the highest attack rate, that gets a special value
     147static const Bit8u AttackSamplesTable[13] = {
     148        69, 55, 46, 40,
     149        35, 29, 23, 20,
     150        19, 15, 11, 10,
     151        9
     152};
     153//On a real opl these values take 8 samples to reach and are based upon larger tables
     154static const Bit8u EnvelopeIncreaseTable[13] = {
     155        4,  5,  6,  7,
     156        8, 10, 12, 14,
     157        16, 20, 24, 28,
     158        32,
     159};
     160
     161#if ( DBOPL_WAVE == WAVE_HANDLER ) || ( DBOPL_WAVE == WAVE_TABLELOG )
     162static Bit16u ExpTable[ 256 ];
     163#endif
     164
     165#if ( DBOPL_WAVE == WAVE_HANDLER )
     166//PI table used by WAVEHANDLER
     167static Bit16u SinTable[ 512 ];
     168#endif
     169
     170#if ( DBOPL_WAVE > WAVE_HANDLER )
     171//Layout of the waveform table in 512 entry intervals
     172//With overlapping waves we reduce the table to half it's size
     173
     174//      |    |//\\|____|WAV7|//__|/\  |____|/\/\|
     175//      |\\//|    |    |WAV7|    |  \/|    |    |
     176//      |06  |0126|17  |7   |3   |4   |4 5 |5   |
     177
     178//6 is just 0 shifted and masked
     179
     180static Bit16s WaveTable[ 8 * 512 ];
     181//Distance into WaveTable the wave starts
     182static const Bit16u WaveBaseTable[8] = {
     183        0x000, 0x200, 0x200, 0x800,
     184        0xa00, 0xc00, 0x100, 0x400,
     185
     186};
     187//Mask the counter with this
     188static const Bit16u WaveMaskTable[8] = {
     189        1023, 1023, 511, 511,
     190        1023, 1023, 512, 1023,
     191};
     192
     193//Where to start the counter on at keyon
     194static const Bit16u WaveStartTable[8] = {
     195        512, 0, 0, 0,
     196        0, 512, 512, 256,
     197};
     198#endif
     199
     200#if ( DBOPL_WAVE == WAVE_TABLEMUL )
     201static Bit16u MulTable[ 384 ];
     202#endif
     203
     204static Bit8u KslTable[ 8 * 16 ];
     205static Bit8u TremoloTable[ TREMOLO_TABLE ];
     206//Start of a channel behind the chip struct start
     207static Bit16u ChanOffsetTable[32];
     208//Start of an operator behind the chip struct start
     209static Bit16u OpOffsetTable[64];
     210
     211//The lower bits are the shift of the operator vibrato value
     212//The highest bit is right shifted to generate -1 or 0 for negation
     213//So taking the highest input value of 7 this gives 3, 7, 3, 0, -3, -7, -3, 0
     214static const Bit8s VibratoTable[ 8 ] = {       
     215        1 - 0x00, 0 - 0x00, 1 - 0x00, 30 - 0x00,
     216        1 - 0x80, 0 - 0x80, 1 - 0x80, 30 - 0x80
     217};
     218
     219//Shift strength for the ksl value determined by ksl strength
     220static const Bit8u KslShiftTable[4] = {
     221        31,1,2,0
     222};
     223
     224//Generate a table index and table shift value using input value from a selected rate
     225static void EnvelopeSelect( Bit8u val, Bit8u& index, Bit8u& shift ) {
     226        if ( val < 13 * 4 ) {                           //Rate 0 - 12
     227                shift = 12 - ( val >> 2 );
     228                index = val & 3;
     229        } else if ( val < 15 * 4 ) {            //rate 13 - 14
     230                shift = 0;
     231                index = val - 12 * 4;
     232        } else {                                                        //rate 15 and up
     233                shift = 0;
     234                index = 12;
     235        }
     236}
     237
     238#if ( DBOPL_WAVE == WAVE_HANDLER )
     239/*
     240        Generate the different waveforms out of the sine/exponetial table using handlers
     241*/
     242static inline Bits MakeVolume( Bitu wave, Bitu volume ) {
     243        Bitu total = wave + volume;
     244        Bitu index = total & 0xff;
     245        Bitu sig = ExpTable[ index ];
     246        Bitu exp = total >> 8;
     247#if 0
     248        //Check if we overflow the 31 shift limit
     249        if ( exp >= 32 ) {
     250                LOG_MSG( "WTF %d %d", total, exp );
     251        }
     252#endif
     253        return (sig >> exp);
     254};
     255
     256static Bits DB_FASTCALL WaveForm0( Bitu i, Bitu volume ) {
     257        Bits neg = 0 - (( i >> 9) & 1);//Create ~0 or 0
     258        Bitu wave = SinTable[i & 511];
     259        return (MakeVolume( wave, volume ) ^ neg) - neg;
     260}
     261static Bits DB_FASTCALL WaveForm1( Bitu i, Bitu volume ) {
     262        Bit32u wave = SinTable[i & 511];
     263        wave |= ( ( (i ^ 512 ) & 512) - 1) >> ( 32 - 12 );
     264        return MakeVolume( wave, volume );
     265}
     266static Bits DB_FASTCALL WaveForm2( Bitu i, Bitu volume ) {
     267        Bitu wave = SinTable[i & 511];
     268        return MakeVolume( wave, volume );
     269}
     270static Bits DB_FASTCALL WaveForm3( Bitu i, Bitu volume ) {
     271        Bitu wave = SinTable[i & 255];
     272        wave |= ( ( (i ^ 256 ) & 256) - 1) >> ( 32 - 12 );
     273        return MakeVolume( wave, volume );
     274}
     275static Bits DB_FASTCALL WaveForm4( Bitu i, Bitu volume ) {
     276        //Twice as fast
     277        i <<= 1;
     278        Bits neg = 0 - (( i >> 9) & 1);//Create ~0 or 0
     279        Bitu wave = SinTable[i & 511];
     280        wave |= ( ( (i ^ 512 ) & 512) - 1) >> ( 32 - 12 );
     281        return (MakeVolume( wave, volume ) ^ neg) - neg;
     282}
     283static Bits DB_FASTCALL WaveForm5( Bitu i, Bitu volume ) {
     284        //Twice as fast
     285        i <<= 1;
     286        Bitu wave = SinTable[i & 511];
     287        wave |= ( ( (i ^ 512 ) & 512) - 1) >> ( 32 - 12 );
     288        return MakeVolume( wave, volume );
     289}
     290static Bits DB_FASTCALL WaveForm6( Bitu i, Bitu volume ) {
     291        Bits neg = 0 - (( i >> 9) & 1);//Create ~0 or 0
     292        return (MakeVolume( 0, volume ) ^ neg) - neg;
     293}
     294static Bits DB_FASTCALL WaveForm7( Bitu i, Bitu volume ) {
     295        //Negative is reversed here
     296        Bits neg = (( i >> 9) & 1) - 1;
     297        Bitu wave = (i << 3);
     298        //When negative the volume also runs backwards
     299        wave = ((wave ^ neg) - neg) & 4095;
     300        return (MakeVolume( wave, volume ) ^ neg) - neg;
     301}
     302
     303static const WaveHandler WaveHandlerTable[8] = {
     304        WaveForm0, WaveForm1, WaveForm2, WaveForm3,
     305        WaveForm4, WaveForm5, WaveForm6, WaveForm7
     306};
     307
     308#endif
     309
     310//Structto hold the data everything well yeh works with
     311static struct {
     312        Bitu samples;
     313        Bits vibrato;
     314        Bits tremolo;
     315        inline void SetVibrato( Bit8s vib ) {
     316                vibrato = vib;
     317                vibrato &= ~0x80;
     318        }
     319        Bit32s output[MAX_SAMPLES * 2];
     320        //Could intermix the vib/trem table for slightly better cache hits
     321        Bit8s vibTable[MAX_SAMPLES];
     322        Bit8s tremTable[MAX_SAMPLES];
     323} Work;
     324
     325/*
     326        Operator
     327*/
     328
     329//We zero out when rate == 0
     330inline void Operator::UpdateAttack( const Chip* chip ) {
     331        Bit8u rate = reg60 >> 4;
     332        if ( rate ) {
     333                Bit8u val = (rate << 2) + ksr;
     334                attackAdd = chip->attackRates[ val ];
     335                rateZero &= ~(1 << ATTACK);
     336        } else {
     337                attackAdd = 0;
     338                rateZero |= (1 << ATTACK);
     339        }
     340}
     341inline void Operator::UpdateDecay( const Chip* chip ) {
     342        Bit8u rate = reg60 & 0xf;
     343        if ( rate ) {
     344                Bit8u val = (rate << 2) + ksr;
     345                decayAdd = chip->linearRates[ val ];
     346                rateZero &= ~(1 << DECAY);
     347        } else {
     348                decayAdd = 0;
     349                rateZero |= (1 << DECAY);
     350        }
     351}
     352inline void Operator::UpdateRelease( const Chip* chip ) {
     353        Bit8u rate = reg80 & 0xf;
     354        if ( rate ) {
     355                Bit8u val = (rate << 2) + ksr;
     356                releaseAdd = chip->linearRates[ val ];
     357                rateZero &= ~(1 << RELEASE);
     358                if ( !(reg20 & MASK_SUSTAIN ) ) {
     359                        rateZero &= ~( 1 << SUSTAIN );
     360                }       
     361        } else {
     362                rateZero |= (1 << RELEASE);
     363                releaseAdd = 0;
     364                if ( !(reg20 & MASK_SUSTAIN ) ) {
     365                        rateZero |= ( 1 << SUSTAIN );
     366                }       
     367        }
     368}
     369
     370inline void Operator::UpdateAttenuation( ) {
     371        Bit8u kslBase = (chanData >> SHIFT_KSLBASE) & 0xff;
     372        Bit32u tl = reg40 & 0x3f;
     373        Bit8u kslShift = KslShiftTable[ reg40 >> 6 ];
     374        //Make sure the attenuation goes to the right bits
     375        totalLevel = tl << ( ENV_BITS - 7 );    //Total level goes 2 bits below max
     376        totalLevel += ( kslBase << ENV_EXTRA ) >> kslShift;
     377}
     378
     379void Operator::UpdateFrequency(  ) {
     380        Bit32u freq = chanData & (( 1 << 10 ) - 1);
     381        Bit32u block = (chanData >> 10) & 0xff;
     382       
     383        waveAdd = (freq << block) * freqMul;
     384        if ( reg20 & MASK_VIBRATO ) {
     385                vibStrength = (Bit8u)(freq >> 7);
     386                vibrato = ( vibStrength << block ) * freqMul;
     387        } else {
     388                vibStrength = 0;
     389                vibrato = 0;
     390        }
     391}
     392
     393void Operator::UpdateRates( const Chip* chip ) {
     394        //Mame seems to reverse this where enabling ksr actually lowers
     395        //the rate, but pdf manuals says otherwise?
     396        Bit8u newKsr = (chanData >> SHIFT_KEYCODE) & 0xff;
     397        if ( !( reg20 & MASK_KSR ) ) {
     398                newKsr >>= 2;
     399        }
     400        if ( ksr == newKsr )
     401                return;
     402        ksr = newKsr;
     403        UpdateAttack( chip );
     404        UpdateDecay( chip );
     405        UpdateRelease( chip );
     406}
     407
     408INLINE Bit32s Operator::RateForward( Bit32u add ) {
     409        rateIndex += add;
     410        Bit32s ret = rateIndex >> RATE_SH;
     411        rateIndex = rateIndex & RATE_MASK;
     412        return ret;
     413}
     414
     415template< Operator::State yes>
     416Bits Operator::TemplateVolume(  ) {
     417        Bit32s vol = activeLevel;
     418        Bit32s change;
     419        switch ( yes ) {
     420        case OFF:
     421                return ENV_MAX;
     422        case ATTACK:
     423                change = RateForward( attackAdd );
     424                if ( !change )
     425                        return vol;
     426                vol += ( (~vol) * change ) >> 3;
     427                if ( vol < ENV_MIN ) {
     428                        activeLevel = ENV_MIN;
     429                        rateIndex = 0;
     430                        SetState( DECAY );
     431                        return ENV_MIN;
     432                }
     433                break;
     434        case DECAY:
     435                vol += RateForward( decayAdd );
     436                if ( vol >= sustainLevel ) {
     437                        //Check if we didn't overshoot max attenuation, then just go off
     438                        if ( vol >= ENV_MAX ) {
     439                                activeLevel = ENV_MAX;
     440                                SetState( OFF );
     441                                return ENV_MAX;
     442                        }
     443                        //Continue as sustain
     444                        rateIndex = 0;
     445                        SetState( SUSTAIN );
     446                }
     447                break;
     448        case SUSTAIN:
     449                if ( reg20 & MASK_SUSTAIN ) {
     450                        return vol;
     451                }
     452                //In sustain phase, but not sustaining, do regular release
     453        case RELEASE:
     454                vol += RateForward( releaseAdd );;
     455                if ( vol >= ENV_MAX ) {
     456                        activeLevel = ENV_MAX;
     457                        SetState( OFF );
     458                        return ENV_MAX;
     459                }
     460                break;
     461        }
     462        activeLevel = vol;
     463        return vol;
     464}
     465
     466static const VolumeHandler VolumeHandlerTable[5] = {
     467        &Operator::TemplateVolume< Operator::OFF >,
     468        &Operator::TemplateVolume< Operator::RELEASE >,
     469        &Operator::TemplateVolume< Operator::SUSTAIN >,
     470        &Operator::TemplateVolume< Operator::DECAY >,
     471        &Operator::TemplateVolume< Operator::ATTACK >
     472};
     473
     474INLINE Bitu Operator::ForwardVolume() {
     475        return  totalLevel + (this->*volHandler)()
     476#if defined ( DBOPL_TREMOLO )
     477                + (Work.tremolo & tremoloMask)
     478#endif
     479        ;
     480}
     481
     482
     483INLINE Bitu Operator::ForwardWave() {
     484#if defined ( DBOPL_VIBRATO )
     485        if ( vibStrength >> (Bit8u)(Work.vibrato) ) {
     486                Bit32s add = vibrato >> (Bit8u)(Work.vibrato);
     487                //Sign extend over the shift value
     488                Bit32s neg = Work.vibrato >> 16;
     489                //Negate the add with -1 or 0
     490                add = ( add ^ neg ) - neg;
     491                waveIndex += add + waveAdd;
     492                return waveIndex >> WAVE_SH;
     493        }
     494#endif
     495        waveIndex += waveAdd;   
     496        return waveIndex >> WAVE_SH;
     497}
     498
     499
     500void Operator::Write20( const Chip* chip, Bit8u val ) {
     501        Bit8u change = (reg20 ^ val );
     502        if ( !change )
     503                return;
     504        reg20 = val;
     505        //Shift the tremolo bit over the entire register, saved a branch, YES!
     506        tremoloMask = (Bit8s)(val) >> 7;
     507        tremoloMask &= ~(( 1 << ENV_EXTRA ) -1);
     508        //Update specific features based on changes
     509        if ( change & MASK_KSR ) {
     510                UpdateRates( chip );
     511        }
     512        //With sustain enable the volume doesn't change
     513        if ( reg20 & MASK_SUSTAIN || ( !releaseAdd ) ) {
     514                rateZero |= ( 1 << SUSTAIN );
     515        } else {
     516                rateZero &= ~( 1 << SUSTAIN );
     517        }
     518        //Frequency multiplier or vibrato changed
     519        if ( change & (0xf | MASK_VIBRATO) ) {
     520                freqMul = chip->freqMul[ val & 0xf ];
     521                UpdateFrequency();
     522        }
     523}
     524
     525void Operator::Write40( const Chip* chip, Bit8u val ) {
     526        if (!(reg40 ^ val ))
     527                return;
     528        reg40 = val;
     529        UpdateAttenuation( );
     530}
     531
     532void Operator::Write60( const Chip* chip, Bit8u val ) {
     533        Bit8u change = reg60 ^ val;
     534        reg60 = val;
     535        if ( change & 0x0f ) {
     536                UpdateDecay( chip );
     537        }
     538        if ( change & 0xf0 ) {
     539                UpdateAttack( chip );
     540        }
     541}
     542
     543void Operator::Write80( const Chip* chip, Bit8u val ) {
     544        Bit8u change = (reg80 ^ val );
     545        if ( !change )
     546                return;
     547        reg80 = val;
     548        Bit8u sustain = val >> 4;
     549        //Turn 0xf into 0x1f
     550        sustain |= ( sustain + 1) & 0x10;
     551        sustainLevel = sustain << ( ENV_BITS - 5 );
     552        if ( change & 0x0f ) {
     553                UpdateRelease( chip );
     554        }
     555}
     556
     557void Operator::WriteE0( const Chip* chip, Bit8u val ) {
     558        if ( !(regE0 ^ val) )
     559                return;
     560        //in opl3 mode you can always selet 7 waveforms regardless of waveformselect
     561        Bit8u waveForm = val & ( ( 0x3 & chip->waveFormMask ) | (0x7 & chip->opl3Active ) );
     562        regE0 = val;
     563#if ( DBOPL_WAVE == WAVE_HANDLER )
     564        waveHandler = WaveHandlerTable[ waveForm ];
     565#else
     566        waveBase = WaveTable + WaveBaseTable[ waveForm ];
     567        waveStart = WaveStartTable[ waveForm ] << WAVE_SH;
     568        waveMask = WaveMaskTable[ waveForm ];
     569#endif
     570}
     571
     572INLINE void Operator::SetState( Bit8u s ) {
     573        state = s;
     574        volHandler = VolumeHandlerTable[ s ];
     575}
     576
     577INLINE bool Operator::Silent() const {
     578        if ( !ENV_SILENT( totalLevel + activeLevel ) )
     579                return false;
     580        if ( !(rateZero & ( 1 << state ) ) )
     581                return false;
     582        return true;
     583}
     584
     585void Operator::KeyOn( Bit8u mask ) {
     586        if ( !keyOn ) {
     587                //Restart the frequency generator
     588#if ( DBOPL_WAVE > WAVE_HANDLER )
     589                waveIndex = waveStart;
     590#else
     591                waveIndex = 0;
     592#endif
     593                rateIndex = 0;
     594                SetState( ATTACK );
     595        }
     596        keyOn |= mask;
     597}
     598
     599void Operator::KeyOff( Bit8u mask ) {
     600        keyOn &= ~mask;
     601        if ( !keyOn ) {
     602                if ( state != OFF ) {
     603                        SetState( RELEASE );
     604                }
     605        }
     606}
     607
     608INLINE Bits Operator::GetWave( Bitu index, Bitu vol ) {
     609#if ( DBOPL_WAVE == WAVE_HANDLER )
     610        return waveHandler( index, vol << ( 3 - ENV_EXTRA ) );
     611#elif ( DBOPL_WAVE == WAVE_TABLEMUL )
     612        return (waveBase[ index & waveMask ] * MulTable[ vol >> ENV_EXTRA ]) >> MUL_SH;
     613#elif ( DBOPL_WAVE == WAVE_TABLELOG )
     614        Bit32s wave = waveBase[ index & waveMask ];
     615        Bit32u total = ( wave & 0x7fff ) + vol << ( 3 - ENV_EXTRA );
     616        Bit32s sig = ExpTable[ total & 0xff ];
     617        Bit32u exp = total >> 8;
     618        Bit32s neg = wave >> 16;
     619        return ((sig ^ neg) - neg) >> exp;
     620#else
     621#error "No valid wave routine"
     622#endif
     623}
     624
     625Bits INLINE Operator::GetSample( Bits modulation ) {
     626        Bitu vol = ForwardVolume();
     627        if ( ENV_SILENT( vol ) ) {
     628                //Simply forward the wave
     629                waveIndex += waveAdd;
     630                return 0;
     631        } else {
     632                Bitu index = ForwardWave();
     633                index += modulation;
     634                return GetWave( index, vol );
     635        }
     636}
     637
     638Operator::Operator() {
     639        chanData = 0;
     640        freqMul = 0;
     641        waveIndex = 0;
     642        waveAdd = 0;
     643        keyOn = 0;
     644        ksr = 0;
     645        reg20 = 0;
     646        reg40 = 0;
     647        reg60 = 0;
     648        reg80 = 0;
     649        regE0 = 0;
     650        SetState( OFF );
     651        rateZero = (1 << OFF);
     652        sustainLevel = ENV_MAX;
     653        activeLevel = ENV_MAX;
     654        totalLevel = ENV_MAX;
     655}
     656
     657/*
     658        Channel
     659*/
     660
     661Channel::Channel() {
     662        old[0] = old[1] = 0;
     663        chanData = 0;
     664        regB0 = 0;
     665        regC0 = 0;
     666        maskLeft = -1;
     667        maskRight = -1;
     668        feedback = 31;
     669        fourMask = 0;
     670        synthHandler = &Channel::BlockTemplate< sm2FM >;
     671}
     672
     673void Channel::SetChanData( const Chip* chip, Bit32u data ) {
     674        Bit32u change = chanData ^ data;
     675        chanData = data;
     676        Op( 0 )->chanData = data;
     677        Op( 1 )->chanData = data;
     678        //Since a frequency update triggered this, always update frequency
     679        Op( 0 )->UpdateFrequency();
     680        Op( 1 )->UpdateFrequency();
     681        if ( change & ( 0xff << SHIFT_KSLBASE ) ) {
     682                Op( 0 )->UpdateAttenuation();
     683                Op( 1 )->UpdateAttenuation();
     684        }
     685        if ( change & ( 0xff << SHIFT_KEYCODE ) ) {
     686                Op( 0 )->UpdateRates( chip );
     687                Op( 1 )->UpdateRates( chip );
     688        }
     689}
     690
     691void Channel::UpdateFrequency( const Chip* chip, Bit8u fourOp ) {
     692        //Extrace the frequency bits
     693        Bit32u data = chanData & 0xffff;
     694        Bit32u kslBase = KslTable[ data >> 6 ];
     695        Bit32u keyCode = ( data & 0x1c00) >> 9;
     696        if ( chip->reg08 & 0x40 ) {
     697                keyCode |= ( data & 0x100)>>8;  /* notesel == 1 */
     698        } else {
     699                keyCode |= ( data & 0x200)>>9;  /* notesel == 0 */
     700        }
     701        //Add the keycode and ksl into the highest bits of chanData
     702        data |= (keyCode << SHIFT_KEYCODE) | ( kslBase << SHIFT_KSLBASE );
     703        ( this + 0 )->SetChanData( chip, data );
     704        if ( fourOp & 0x3f ) {
     705                ( this + 1 )->SetChanData( chip, data );
     706        }
     707}
     708
     709void Channel::WriteA0( const Chip* chip, Bit8u val ) {
     710        Bit8u fourOp = chip->reg104 & chip->opl3Active & fourMask;
     711        //Don't handle writes to silent fourop channels
     712        if ( fourOp > 0x80 )
     713                return;
     714        Bit32u change = (chanData ^ val ) & 0xff;
     715        if ( change ) {
     716                chanData ^= change;
     717                UpdateFrequency( chip, fourOp );
     718        }
     719}
     720
     721void Channel::WriteB0( const Chip* chip, Bit8u val ) {
     722        Bit8u fourOp = chip->reg104 & chip->opl3Active & fourMask;
     723        //Don't handle writes to silent fourop channels
     724        if ( fourOp > 0x80 )
     725                return;
     726        Bitu change = (chanData ^ ( val << 8 ) ) & 0x1f00;
     727        if ( change ) {
     728                chanData ^= change;
     729                UpdateFrequency( chip, fourOp );
     730        }
     731        //Check for a change in the keyon/off state
     732        if ( !(( val ^ regB0) & 0x20))
     733                return;
     734        regB0 = val;
     735        if ( val & 0x20 ) {
     736                Op(0)->KeyOn( 0x1 );
     737                Op(1)->KeyOn( 0x1 );
     738                if ( fourOp & 0x3f ) {
     739                        ( this + 1 )->Op(0)->KeyOn( 1 );
     740                        ( this + 1 )->Op(1)->KeyOn( 1 );
     741                }
     742        } else {
     743                Op(0)->KeyOff( 0x1 );
     744                Op(1)->KeyOff( 0x1 );
     745                if ( fourOp & 0x3f ) {
     746                        ( this + 1 )->Op(0)->KeyOff( 1 );
     747                        ( this + 1 )->Op(1)->KeyOff( 1 );
     748                }
     749        }
     750}
     751
     752void Channel::WriteC0( const Chip* chip, Bit8u val ) {
     753        Bit8u change = val ^ regC0;
     754        if ( !change )
     755                return;
     756        regC0 = val;
     757        feedback = ( val >> 1 ) & 7;
     758        if ( feedback ) {
     759                //We shift the input to the right 10 bit wave index value
     760                feedback = 9 - feedback;
     761        } else {
     762                feedback = 31;
     763        }
     764        //Select the new synth mode
     765        if ( chip->opl3Active ) {
     766                //4-op mode enabled for this channel
     767                if ( (chip->reg104 & fourMask) & 0x3f ) {
     768                        Channel* chan0, *chan1;
     769                        //Check if it's the 2nd channel in a 4-op
     770                        if ( !(fourMask & 0x80 ) ) {
     771                                chan0 = this;
     772                                chan1 = this + 1;
     773                        } else {
     774                                chan0 = this - 1;
     775                                chan1 = this;
     776                        }
     777
     778                        Bit8u synth = ( (chan0->regC0 & 1) << 0 )| (( chan1->regC0 & 1) << 1 );
     779                        switch ( synth ) {
     780                        case 0:
     781                                chan0->synthHandler = &Channel::BlockTemplate< sm3FMFM >;
     782                                break;
     783                        case 1:
     784                                chan0->synthHandler = &Channel::BlockTemplate< sm3AMFM >;
     785                                break;
     786                        case 2:
     787                                chan0->synthHandler = &Channel::BlockTemplate< sm3FMAM >;
     788                                break;
     789                        case 3:
     790                                chan0->synthHandler = &Channel::BlockTemplate< sm3AMAM >;
     791                                break;
     792                        }
     793                //Disable updating percussion channels
     794                } else if ((fourMask & 0x40) && ( chip->regBD & 0x20) ) {
     795
     796                //Regular dual op, am or fm
     797                } else if ( val & 1 ) {
     798                        synthHandler = &Channel::BlockTemplate< sm3AM >;
     799                } else {
     800                        synthHandler = &Channel::BlockTemplate< sm3FM >;
     801                }
     802                maskLeft = ( val & 0x10 ) ? -1 : 0;
     803                maskRight = ( val & 0x20 ) ? -1 : 0;
     804        //opl2 active
     805        } else {
     806                //Disable updating percussion channels
     807                if ( (fourMask & 0x40) && ( chip->regBD & 0x20 ) ) {
     808
     809                //Regular dual op, am or fm
     810                } else if ( val & 1 ) {
     811                        synthHandler = &Channel::BlockTemplate< sm2AM >;
     812                } else {
     813                        synthHandler = &Channel::BlockTemplate< sm2FM >;
     814                }
     815        }
     816}
     817
     818void Channel::ResetC0( const Chip* chip ) {
     819        Bit8u val = regC0;
     820        regC0 ^= 0xff;
     821        WriteC0( chip, val );
     822}
     823
     824template< bool opl3Mode>
     825void Channel::GeneratePercussion( Bit32s* output ) {
     826        Channel* chan = this;
     827
     828        //BassDrum
     829        Bit32s mod = (Bit32u)((old[0] + old[1])) >> feedback;
     830        old[0] = old[1];
     831        old[1] = Op(0)->GetSample( mod );
     832
     833        //When bassdrum is in AM mode first operator is ignoed
     834        if ( chan->regC0 & 1 ) {
     835                mod = 0;
     836        } else {
     837                mod = old[0];
     838        }
     839        Bit32s sample = Op(1)->GetSample( mod );
     840
     841        Operator* op2 = ( this + 1 )->Op(0);
     842        Operator* op4 = ( this + 2 )->Op(0);
     843
     844        //Precalculate stuff used by other oupts
     845        Bit32u noiseBit = rand() & 0x2;
     846        Bit32u c2 = op2->ForwardWave();
     847        //(bit 7 ^ bit 2) | bit 3 -> combined in bit 1
     848        Bit32u phaseBit = ( (c2 >> 6) ^ ( c2 >> 1 ) ) | ( c2 >> 2 );
     849        Bit32u c4 = op4->ForwardWave();
     850        //bit 5 ^ bit 3 to bit 1
     851        Bit32u gateBit = ( c4 >> 4 ) ^ ( c4 >> 3 );
     852        phaseBit = (phaseBit | gateBit) & 0x2;
     853
     854        //Hi-Hat
     855        Bit32u hhVol = op2->ForwardVolume();
     856        if ( !ENV_SILENT( hhVol ) ) {
     857                /* when phase & 0x200 is set and noise=1 then phase = 0x200|0xd0 */
     858                /* when phase & 0x200 is set and noise=0 then phase = 0x200|(0xd0>>2), ie no change */
     859                Bit32u hhIndex = ( phaseBit << 8 ) | ( 0xd0 >> ( phaseBit ^ noiseBit ) );
     860                sample += op2->GetWave( hhIndex, hhVol );
     861        }
     862        //Snare Drum
     863        Operator* op3 = ( this + 1 )->Op(1);
     864        Bit32u sdVol = op3->ForwardVolume();
     865        if ( !ENV_SILENT( sdVol ) ) {
     866                Bit32u sdBits = 0x100 + (c2 & 0x100);
     867                Bit32u sdIndex = sdBits ^ ( noiseBit << 7 );
     868                sample += op3->GetWave( sdIndex, sdVol );
     869        }
     870        //Tom-tom
     871        sample += op4->GetSample( 0 );
     872        //Top-Cymbal
     873        Operator* op5 = ( this + 2 )->Op(1);
     874        Bit32u tcVol = op5->ForwardVolume();
     875        if ( !ENV_SILENT( tcVol ) ) {
     876                Bit32u tcIndex = (1 + phaseBit) << 8;
     877                sample += op5->GetWave( tcIndex, tcVol );
     878        }
     879        sample <<= 1;
     880        if ( opl3Mode ) {
     881                output[0] += sample;
     882                output[1] += sample;
     883        } else {
     884                output[0] += sample;
     885        }
     886}
     887
     888template<SynthMode mode>
     889Channel* Channel::BlockTemplate( ) {
     890        switch( mode ) {
     891        case sm2AM:
     892        case sm3AM:
     893                if ( Op(0)->Silent() && Op(1)->Silent() ) {
     894                        old[0] = old[1] = 0;
     895                        return (this + 1);
     896                }
     897                break;
     898        case sm2FM:
     899        case sm3FM:
     900                if ( Op(1)->Silent() ) {
     901                        old[0] = old[1] = 0;
     902                        return (this + 1);
     903                }
     904                break;
     905        case sm3FMFM:
     906                if ( Op(3)->Silent() ) {
     907                        old[0] = old[1] = 0;
     908                        return (this + 2);
     909                }
     910                break;
     911        case sm3AMFM:
     912                if ( Op(0)->Silent() && Op(3)->Silent() ) {
     913                        old[0] = old[1] = 0;
     914                        return (this + 2);
     915                }
     916                break;
     917        case sm3FMAM:
     918                if ( Op(1)->Silent() && Op(3)->Silent() ) {
     919                        old[0] = old[1] = 0;
     920                        return (this + 2);
     921                }
     922                break;
     923        case sm3AMAM:
     924                if ( Op(0)->Silent() && Op(2)->Silent() && Op(3)->Silent() ) {
     925                        old[0] = old[1] = 0;
     926                        return (this + 2);
     927                }
     928                break;
     929        // TODO: Check this
     930        default:
     931                break;
     932        }
     933        for ( Bitu i = 0; i < Work.samples; i++ ) {
     934                Work.vibrato = Work.vibTable[i];
     935                Work.tremolo = Work.tremTable[i];
     936       
     937                //Early out for percussion handlers
     938                if ( mode == sm2Percussion ) {
     939                        GeneratePercussion<false>( Work.output + i );
     940                        continue;       //Prevent some unitialized value bitching
     941                } else if ( mode == sm3Percussion ) {
     942                        GeneratePercussion<true>( Work.output + i * 2 );
     943                        continue;       //Prevent some unitialized value bitching
     944                }
     945
     946                //Do unsigned shift so we can shift out all bits but still stay in 10 bit range otherwise
     947                Bit32s mod = (Bit32u)((old[0] + old[1])) >> feedback;
     948                old[0] = old[1];
     949                old[1] = Op(0)->GetSample( mod );
     950                Bit32s sample;
     951                Bit32s out0 = old[0];
     952                if ( mode == sm2AM || mode == sm3AM ) {
     953                        sample = out0 + Op(1)->GetSample( 0 );
     954                } else if ( mode == sm2FM || mode == sm3FM ) {
     955                        sample = Op(1)->GetSample( out0 );
     956                } else if ( mode == sm3FMFM ) {
     957                        Bits next = Op(1)->GetSample( out0 );
     958                        next = Op(2)->GetSample( next );
     959                        sample = Op(3)->GetSample( next );
     960                } else if ( mode == sm3AMFM ) {
     961                        sample = out0;
     962                        Bits next = Op(1)->GetSample( 0 );
     963                        next = Op(2)->GetSample( next );
     964                        sample += Op(3)->GetSample( next );
     965                } else if ( mode == sm3FMAM ) {
     966                        sample = Op(1)->GetSample( out0 );
     967                        Bits next = Op(2)->GetSample( 0 );
     968                        sample += Op(3)->GetSample( next );
     969                } else if ( mode == sm3AMAM ) {
     970                        sample = out0;
     971                        Bits next = Op(1)->GetSample( 0 );
     972                        sample += Op(2)->GetSample( next );
     973                        sample += Op(3)->GetSample( 0 );
     974                }
     975                switch( mode ) {
     976                case sm2AM:
     977                case sm2FM:
     978                        Work.output[ i ] += sample;
     979                        break;
     980                case sm3AM:
     981                case sm3FM:
     982                case sm3FMFM:
     983                case sm3AMFM:
     984                case sm3FMAM:
     985                case sm3AMAM:
     986                        Work.output[ i * 2 + 0 ] += sample & maskLeft;
     987                        Work.output[ i * 2 + 1 ] += sample & maskRight;
     988                        break;
     989                // TODO: Check this
     990                default:
     991                        break;
     992                }
     993        }
     994        switch( mode ) {
     995        case sm2AM:
     996        case sm2FM:
     997        case sm3AM:
     998        case sm3FM:
     999                return ( this + 1 );
     1000        case sm3FMFM:
     1001        case sm3AMFM:
     1002        case sm3FMAM:
     1003        case sm3AMAM:
     1004                return( this + 2 );
     1005        case sm2Percussion:
     1006        case sm3Percussion:
     1007                return( this + 3 );
     1008        }
     1009        return 0;
     1010}
     1011
     1012/*
     1013        Chip
     1014*/
     1015
     1016Chip::Chip() {
     1017        reg08 = 0;
     1018        reg04 = 0;
     1019        regBD = 0;
     1020        reg104 = 0;
     1021        opl3Active = 0;
     1022}
     1023
     1024
     1025Bit8u Chip::ForwardTremolo(  ) {
     1026        tremoloCounter += tremoloAdd;
     1027        if ( tremoloCounter >= (uint)(TREMOLO_TABLE << TREMOLO_SH) ) {
     1028                tremoloCounter -= (uint)(TREMOLO_TABLE << TREMOLO_SH);
     1029        }
     1030        Bitu index = tremoloCounter >> TREMOLO_SH;
     1031        return TremoloTable[ index ] >> tremoloShift;
     1032}
     1033
     1034Bit8s Chip::ForwardVibrato(  ) {
     1035        vibratoCounter += vibratoAdd;
     1036        Bitu index = vibratoCounter >> VIBRATO_SH;
     1037        //Vibrato shift, basically makes the shift greater reducing the actual final value
     1038        return VibratoTable[index & 7] + vibratoShift;
     1039}
     1040
     1041void Chip::WriteBD( Bit8u val ) {
     1042        Bit8u change = regBD ^ val;
     1043        if ( !change )
     1044                return;
     1045        regBD = val;
     1046        //TODO could do this with shift and xor?
     1047        vibratoShift = (val & 0x40) ? 0x00 : 0x01;
     1048        tremoloShift = (val & 0x80) ? 0x00 : 0x02;
     1049        if ( val & 0x20 ) {
     1050                //Drum was just enabled, make sure channel 6 has the right synth
     1051                if ( change & 0x20 ) {
     1052                        if ( opl3Active ) {
     1053                                chan[6].synthHandler = &Channel::BlockTemplate< sm3Percussion >;
     1054                        } else {
     1055                                chan[6].synthHandler = &Channel::BlockTemplate< sm2Percussion >;
     1056                        }
     1057                }
     1058                //Bass Drum
     1059                if ( val & 0x10 ) {
     1060                        chan[6].op[0].KeyOn( 0x2 );
     1061                        chan[6].op[1].KeyOn( 0x2 );
     1062                } else {
     1063                        chan[6].op[0].KeyOff( 0x2 );
     1064                        chan[6].op[1].KeyOff( 0x2 );
     1065                }
     1066                //Hi-Hat
     1067                if ( val & 0x1 ) {
     1068                        chan[7].op[0].KeyOn( 0x2 );
     1069                } else {
     1070                        chan[7].op[0].KeyOff( 0x2 );
     1071                }
     1072                //Snare
     1073                if ( val & 0x8 ) {
     1074                        chan[7].op[1].KeyOn( 0x2 );
     1075                } else {
     1076                        chan[7].op[1].KeyOff( 0x2 );
     1077                }
     1078                //Tom-Tom
     1079                if ( val & 0x4 ) {
     1080                        chan[8].op[0].KeyOn( 0x2 );
     1081                } else {
     1082                        chan[8].op[0].KeyOff( 0x2 );
     1083                }
     1084                //Top Cymbal
     1085                if ( val & 0x2 ) {
     1086                        chan[8].op[1].KeyOn( 0x2 );
     1087                } else {
     1088                        chan[8].op[1].KeyOff( 0x2 );
     1089                }
     1090        //Toggle keyoffs when we turn off the percussion
     1091        } else if ( change & 0x20 ) {
     1092                //Trigger a reset to setup the original synth handler
     1093                chan[6].ResetC0( this );
     1094                chan[6].op[0].KeyOff( 0x2 );
     1095                chan[6].op[1].KeyOff( 0x2 );
     1096                chan[7].op[0].KeyOff( 0x2 );
     1097                chan[7].op[1].KeyOff( 0x2 );
     1098                chan[8].op[0].KeyOff( 0x2 );
     1099                chan[8].op[1].KeyOff( 0x2 );
     1100        }
     1101}
     1102
     1103
     1104#define REGOP( _FUNC_ )                                                                                                                 \
     1105        index = ( ( reg >> 3) & 0x20 ) | ( reg & 0x1f );                                                                \
     1106        if ( OpOffsetTable[ index ] ) {                                                                                                 \
     1107                Operator* regOp = (Operator*)( ((char *)this ) + OpOffsetTable[ index ] );      \
     1108                regOp->_FUNC_( this, val );                                                                                                     \
     1109        }
     1110
     1111#define REGCHAN( _FUNC_ )                                                                                                                               \
     1112        index = ( ( reg >> 4) & 0x10 ) | ( reg & 0xf );                                                                         \
     1113        if ( ChanOffsetTable[ index ] ) {                                                                                                       \
     1114                Channel* regChan = (Channel*)( ((char *)this ) + ChanOffsetTable[ index ] );    \
     1115                regChan->_FUNC_( this, val );                                                                                                   \
     1116        }
     1117
     1118void Chip::WriteReg( Bit32u reg, Bit8u val ) {
     1119        Bitu index;
     1120        switch ( (reg & 0xf0) >> 4 ) {
     1121        case 0x00 >> 4:
     1122                if ( reg == 0x01 ) {
     1123                        waveFormMask = ( val & 0x20 ) ? 0x7 : 0x0;
     1124                } else if ( reg == 0x104 ) {
     1125                        //Only detect changes in lowest 6 bits
     1126                        if ( !((reg104 ^ val) & 0x3f) )
     1127                                return;
     1128                        //Always keep the highest bit enabled, for checking > 0x80
     1129                        reg104 = 0x80 | ( val & 0x3f );
     1130                } else if ( reg == 0x105 ) {
     1131                        //MAME says the real opl3 doesn't reset anything on opl3 disable/enable till the next write in another register
     1132                        if ( !((opl3Active ^ val) & 1 ) )
     1133                                return;
     1134                        opl3Active = ( val & 1 ) ? 0xff : 0;
     1135                        //Update the 0xc0 register for all channels to signal the switch to mono/stereo handlers
     1136                        for ( int i = 0; i < 18;i++ ) {
     1137                                chan[i].ResetC0( this );
     1138                        }
     1139                } else if ( reg == 0x08 ) {
     1140                        reg08 = val;
     1141                }
     1142        case 0x10 >> 4:
     1143                break;
     1144        case 0x20 >> 4:
     1145        case 0x30 >> 4:
     1146                REGOP( Write20 );
     1147                break;
     1148        case 0x40 >> 4:
     1149        case 0x50 >> 4:
     1150                REGOP( Write40 );
     1151                break;
     1152        case 0x60 >> 4:
     1153        case 0x70 >> 4:
     1154                REGOP( Write60 );
     1155                break;
     1156        case 0x80 >> 4:
     1157        case 0x90 >> 4:
     1158                REGOP( Write80 );
     1159                break;
     1160        case 0xa0 >> 4:
     1161                REGCHAN( WriteA0 );
     1162                break;
     1163        case 0xb0 >> 4:
     1164                if ( reg == 0xbd ) {
     1165                        WriteBD( val );
     1166                } else {
     1167                        REGCHAN( WriteB0 );
     1168                }
     1169                break;
     1170        case 0xc0 >> 4:
     1171                REGCHAN( WriteC0 );
     1172        case 0xd0 >> 4:
     1173                break;
     1174        case 0xe0 >> 4:
     1175        case 0xf0 >> 4:
     1176                REGOP( WriteE0 );
     1177                break;
     1178        }
     1179}
     1180
     1181
     1182Bit32u Chip::WriteAddr( Bit32u port, Bit8u val ) {
     1183        switch ( port & 3 ) {
     1184        case 0:
     1185                return val;
     1186        case 2:
     1187                if ( opl3Active || (val == 0x05) )
     1188                        return 0x100 | val;
     1189                else
     1190                        return val;
     1191        }
     1192        return 0;
     1193}
     1194
     1195void Chip::GenerateBlock2( Bitu samples  ) {
     1196        Work.samples = samples;
     1197        for ( Bitu i = 0; i < Work.samples; i++ ) {
     1198                Work.vibTable[i] = ForwardVibrato();
     1199                Work.tremTable[i] = ForwardTremolo();
     1200                Work.output[i] = 0;
     1201        }
     1202        int count = 0;
     1203        for( Channel* ch = chan; ch < chan + 9; ) {
     1204                count++;
     1205                ch = (ch->*(ch->synthHandler))();
     1206        }
     1207}
     1208
     1209void Chip::GenerateBlock3( Bitu samples ) {
     1210        Work.samples = samples;
     1211        for ( Bitu i = 0; i < Work.samples; i++ ) {
     1212                Work.vibTable[i] = ForwardVibrato();
     1213                Work.tremTable[i] = ForwardTremolo();
     1214                Work.output[i*2 + 0] = 0;
     1215                Work.output[i*2 + 1] = 0;
     1216        }
     1217        int count = 0;
     1218        for( Channel* ch = chan; ch < chan + 18; ) {
     1219                count++;
     1220                ch = (ch->*(ch->synthHandler))();
     1221        }
     1222}
     1223
     1224void Chip::Setup( Bit32u rate ) {
     1225        //Vibrato forwards every 1024 samples
     1226        vibratoAdd = (Bit32u)((double)rate * (double)( 1 << (VIBRATO_SH - 10) ) / OPLRATE);
     1227        vibratoCounter = 0;
     1228        //tremolo forwards every 64 samples
     1229        //We use a 52 entry table, real is 210, so repeat each sample an extra 4 times
     1230        tremoloAdd = (Bit32u)((double)rate * (double)( 1 << (TREMOLO_SH - 6 - 2) ) / OPLRATE);
     1231        tremoloCounter = 0;
     1232        //10 bits of frequency counter
     1233        //With higher octave this gets shifted up
     1234        //-1 since the freqCreateTable = *2
     1235        double scale = (OPLRATE * (double)( 1 << ( WAVE_SH - 10 - 1))) / rate;
     1236        for ( int i = 0; i < 16; i++ ) {
     1237                //Use rounding with 0.5
     1238                freqMul[i] = (Bit32u)( 0.5 + scale * FreqCreateTable[ i ] );
     1239        }
     1240
     1241        scale = OPLRATE / rate;
     1242        //-3 since the real envelope takes 8 steps to reach the single value we supply
     1243        for ( Bit8u i = 0; i < 76; i++ ) {
     1244                Bit8u index, shift;
     1245                EnvelopeSelect( i, index, shift );
     1246                linearRates[i] = (Bit32u)( scale * (EnvelopeIncreaseTable[ index ] << ( RATE_SH + ENV_EXTRA - shift - 3 )));
     1247        }
     1248        //Generate the best matching attack rate
     1249        for ( Bit8u i = 0; i < 62; i++ ) {
     1250                Bit8u index, shift;
     1251                EnvelopeSelect( i, index, shift );
     1252                //Original amount of samples the attack would take
     1253                Bit32s original = (Bit32u)( (AttackSamplesTable[ index ] << shift) / scale);
     1254                 
     1255                Bit32s guessAdd = (Bit32u)( scale * (EnvelopeIncreaseTable[ index ] << ( RATE_SH - shift - 3 )));
     1256                Bit32s bestAdd;
     1257                Bit32u bestDiff = 1 << 30;
     1258                for( Bit32u passes = 0; passes < 16; passes ++ ) {
     1259                        Bit32s volume = ENV_MAX;
     1260                        Bit32s samples = 0;
     1261                        Bit32u count = 0;
     1262                        while ( volume > 0 && samples < original * 2 ) {
     1263                                count += guessAdd;
     1264                                Bit32s change = count >> RATE_SH;
     1265                                count &= RATE_MASK;
     1266                                if ( change ) {
     1267                                        volume += ( ~volume * change ) >> 3;
     1268                                }
     1269                                samples++;
     1270
     1271                        }
     1272                        Bit32s diff = original - samples;
     1273                        Bit32u lDiff = labs( diff );
     1274                        //Init last on first pass
     1275                        if ( lDiff < bestDiff ) {
     1276                                bestDiff = lDiff;
     1277                                bestAdd = guessAdd;
     1278                                if ( !bestDiff )
     1279                                        break;
     1280                        }
     1281                        //Below our target
     1282                        if ( diff < 0 ) {
     1283                                //Better than the last time
     1284                                Bit32s mul = ((original - diff) << 12) / original;
     1285                                guessAdd = ((guessAdd * mul) >> 12);
     1286                                guessAdd++;
     1287                        } else if ( diff > 0 ) {
     1288                                Bit32s mul = ((original - diff) << 12) / original;
     1289                                guessAdd = (guessAdd * mul) >> 12;
     1290                                guessAdd--;
     1291                        }
     1292                }
     1293                attackRates[i] = bestAdd;
     1294        }
     1295        for ( Bit8u i = 62; i < 76; i++ ) {
     1296                //This should provide instant volume maximizing
     1297                attackRates[i] = 8 << RATE_SH;
     1298        }
     1299        //Setup the channels with the correct four op flags
     1300        //Channels are accessed through a table so they appear linear here
     1301        chan[ 0].fourMask = 0x00 | ( 1 << 0 );
     1302        chan[ 1].fourMask = 0x80 | ( 1 << 0 );
     1303        chan[ 2].fourMask = 0x00 | ( 1 << 1 );
     1304        chan[ 3].fourMask = 0x80 | ( 1 << 1 );
     1305        chan[ 4].fourMask = 0x00 | ( 1 << 2 );
     1306        chan[ 5].fourMask = 0x80 | ( 1 << 2 );
     1307
     1308        chan[ 9].fourMask = 0x00 | ( 1 << 3 );
     1309        chan[10].fourMask = 0x80 | ( 1 << 3 );
     1310        chan[11].fourMask = 0x00 | ( 1 << 4 );
     1311        chan[12].fourMask = 0x80 | ( 1 << 4 );
     1312        chan[13].fourMask = 0x00 | ( 1 << 5 );
     1313        chan[14].fourMask = 0x80 | ( 1 << 5 );
     1314
     1315        //mark the percussion channels
     1316        chan[ 6].fourMask = 0x40;
     1317        chan[ 7].fourMask = 0x40;
     1318        chan[ 8].fourMask = 0x40;
     1319
     1320        //Clear Everything in opl3 mode
     1321        WriteReg( 0x105, 0x1 );
     1322        for ( int i = 0; i < 512; i++ ) {
     1323                if ( i == 0x105 )
     1324                        continue;
     1325                WriteReg( i, 0xff );
     1326                WriteReg( i, 0x0 );
     1327        }
     1328        WriteReg( 0x105, 0x0 );
     1329        //Clear everything in opl2 mode
     1330        for ( int i = 0; i < 255; i++ ) {
     1331                WriteReg( i, 0xff );
     1332                WriteReg( i, 0x0 );
     1333        }
     1334}
     1335
     1336static bool doneTables = false;
     1337void InitTables( void ) {
     1338        if ( doneTables )
     1339                return;
     1340        doneTables = true;
     1341#if ( DBOPL_WAVE == WAVE_HANDLER ) || ( DBOPL_WAVE == WAVE_TABLELOG )
     1342        //Exponential volume table, same as the real adlib
     1343        for ( int i = 0; i < 256; i++ ) {
     1344                //Save them in reverse
     1345                ExpTable[i] = (int)( 0.5 + ( pow(2.0, ( 255 - i) * ( 1.0 /256 ) )-1) * 1024 );
     1346                ExpTable[i] += 1024; //or remove the -1 oh well :)
     1347                //Preshift to the left once so the final volume can shift to the right
     1348                ExpTable[i] *= 2;
     1349        }
     1350#endif
     1351#if ( DBOPL_WAVE == WAVE_HANDLER )
     1352        //Add 0.5 for the trunc rounding of the integer cast
     1353        //Do a PI sinetable instead of the original 0.5 PI
     1354        for ( int i = 0; i < 512; i++ ) {
     1355                SinTable[i] = (Bit16s)( 0.5 - log10( sin( (i + 0.5) * (PI / 512.0) ) ) / log10(2.0)*256 );
     1356        }
     1357#endif
     1358#if ( DBOPL_WAVE == WAVE_TABLEMUL )
     1359        //Multiplication based tables
     1360        for ( int i = 0; i < 384; i++ ) {
     1361                int s = i * 8;
     1362                //TODO maybe keep some of the precision errors of the original table?
     1363                double val = ( 0.5 + ( pow(2, -1 + ( 255 - s) * ( 1.0 /256 ) )) * ( 1 << MUL_SH ));
     1364                MulTable[i] = (Bit16u)(val);
     1365        }
     1366
     1367        //Sine Wave Base
     1368        for ( int i = 0; i < 512; i++ ) {
     1369                WaveTable[ 0x0200 + i ] = (Bit16s)(sin( (i + 0.5) * (PI / 512.0) ) * 4084);
     1370                WaveTable[ 0x0000 + i ] = -WaveTable[ 0x200 + i ];
     1371        }
     1372        //Exponential wave
     1373        for ( int i = 0; i < 256; i++ ) {
     1374                WaveTable[ 0x700 + i ] = (Bit16s)( 0.5 + ( pow(2, -1 + ( 255 - i * 8) * ( 1.0 /256 ) ) ) * 4085 );
     1375                WaveTable[ 0x6ff - i ] = -WaveTable[ 0x700 + i ];
     1376        }
     1377#endif
     1378#if ( DBOPL_WAVE == WAVE_TABLELOG )
     1379        //Sine Wave Base
     1380        for ( int i = 0; i < 512; i++ ) {
     1381                WaveTable[ 0x0200 + i ] = (Bit16s)( 0.5 - log10( sin( (i + 0.5) * (PI / 512.0) ) ) / log10(2.0)*256 );
     1382                WaveTable[ 0x0000 + i ] = ((Bit16s)0x8000) | WaveTable[ 0x200 + i];
     1383        }
     1384        //Exponential wave
     1385        for ( int i = 0; i < 256; i++ ) {
     1386                WaveTable[ 0x700 + i ] = i * 8;
     1387                WaveTable[ 0x6ff - i ] = ((Bit16s)0x8000) | i * 8;
     1388        }
     1389#endif
     1390
     1391        //      |    |//\\|____|WAV7|//__|/\  |____|/\/\|
     1392        //      |\\//|    |    |WAV7|    |  \/|    |    |
     1393        //      |06  |0126|27  |7   |3   |4   |4 5 |5   |
     1394
     1395#if (( DBOPL_WAVE == WAVE_TABLELOG ) || ( DBOPL_WAVE == WAVE_TABLEMUL ))
     1396        for ( int i = 0; i < 256; i++ ) {
     1397                //Fill silence gaps
     1398                WaveTable[ 0x400 + i ] = WaveTable[0];
     1399                WaveTable[ 0x500 + i ] = WaveTable[0];
     1400                WaveTable[ 0x900 + i ] = WaveTable[0];
     1401                WaveTable[ 0xc00 + i ] = WaveTable[0];
     1402                WaveTable[ 0xd00 + i ] = WaveTable[0];
     1403                //Replicate sines in other pieces
     1404                WaveTable[ 0x800 + i ] = WaveTable[ 0x200 + i ];
     1405                //double speed sines
     1406                WaveTable[ 0xa00 + i ] = WaveTable[ 0x200 + i * 2 ];
     1407                WaveTable[ 0xb00 + i ] = WaveTable[ 0x000 + i * 2 ];
     1408                WaveTable[ 0xe00 + i ] = WaveTable[ 0x200 + i * 2 ];
     1409                WaveTable[ 0xf00 + i ] = WaveTable[ 0x200 + i * 2 ];
     1410        }
     1411#endif
     1412
     1413        //Create the ksl table
     1414        for ( int oct = 0; oct < 8; oct++ ) {
     1415                int base = oct * 8;
     1416                for ( int i = 0; i < 16; i++ ) {
     1417                        int val = base - KslCreateTable[i];
     1418                        if ( val < 0 )
     1419                                val = 0;
     1420                        //*4 for the final range to match attenuation range
     1421                        KslTable[ oct * 16 + i ] = val * 4;
     1422                }
     1423        }
     1424        //Create the Tremolo table, just increase and decrease a triangle wave
     1425        for ( Bit8u i = 0; i < TREMOLO_TABLE / 2; i++ ) {
     1426                Bit8u val = i << ENV_EXTRA;
     1427                TremoloTable[i] = val;
     1428                TremoloTable[TREMOLO_TABLE - 1 - i] = val;
     1429        }
     1430        //Create a table with offsets of the channels from the start of the chip
     1431        for ( Bitu i = 0; i < 32; i++ ) {
     1432                Bitu index = i & 0xf;
     1433                if ( index >= 9 ) {
     1434                        ChanOffsetTable[i] = 0;
     1435                        continue;
     1436                }
     1437                //Make sure the four op channels follow eachother
     1438                if ( index < 6 ) {
     1439                        index = (index % 3) * 2 + ( index / 3 );
     1440                }
     1441                //Add back the bits for highest ones
     1442                if ( i >= 16 )
     1443                        index += 9;
     1444                ChanOffsetTable[i] = OFFS(Chip, chan) + index * sizeof(Channel);
     1445        }
     1446        //Same for operators
     1447        for ( Bitu i = 0; i < 64; i++ ) {
     1448                if ( i % 8 >= 6 || ( (i / 8) % 4 == 3 ) ) {
     1449                        OpOffsetTable[i] = 0;
     1450                        continue;
     1451                }
     1452                Bitu chNum = (i / 8) * 3 + (i % 8) % 3;
     1453                //Make sure we use 16 and up for the 2nd range to match the chanoffset gap
     1454                if ( chNum >= 12 )
     1455                        chNum += 16 - 12;
     1456                Bitu opNum = ( i % 8 ) / 3;
     1457                OpOffsetTable[i] = ChanOffsetTable[ chNum ] + OFFS(Channel, op) + opNum * sizeof(Operator);
     1458        }
     1459}
     1460
     1461Bit32u Handler::writeAddr( Bit32u port, Bit8u val ) {
     1462        return chip.WriteAddr( port, val );
     1463
     1464}
     1465void Handler::writeReg( Bit32u addr, Bit8u val ) {
     1466        chip.WriteReg( addr, val );
     1467}
     1468
     1469void Handler::generate( Bit16s *chan, Bitu samples ) {
     1470        // Opl3 is stereo thus we half the number of samples here.
     1471
     1472        while (samples > 0) {
     1473                Bitu todo = samples > MAX_SAMPLES ? MAX_SAMPLES : samples;
     1474                samples -= todo;
     1475                if ( !chip.opl3Active ) {
     1476                        chip.GenerateBlock2( todo );
     1477                        for (uint i = 0; i < todo; ++i)
     1478                                chan[i] = Work.output[i];
     1479                        chan += todo;
     1480                } else {
     1481                        chip.GenerateBlock3( samples );
     1482                        for (uint i = 0; i < (todo << 1); ++i)
     1483                                chan[i] = Work.output[i];
     1484                        chan += (todo << 1);
     1485                }
     1486        }
     1487}
     1488
     1489void Handler::init( Bitu rate ) {
     1490        InitTables();
     1491        chip.Setup( rate );
     1492}
     1493
     1494} // end of namespace DBOPL
     1495} // end of namespace DOSBox
     1496} // end of namespace OPL
     1497
     1498#endif
     1499
  • sound/softsynth/opl/dosbox.h

     
     1/* ScummVM - Graphic Adventure Engine
     2 *
     3 * ScummVM is the legal property of its developers, whose names
     4 * are too numerous to list here. Please refer to the COPYRIGHT
     5 * file distributed with this source distribution.
     6 *
     7 * This program is free software; you can redistribute it and/or
     8 * modify it under the terms of the GNU General Public License
     9 * as published by the Free Software Foundation; either version 2
     10 * of the License, or (at your option) any later version.
     11 *
     12 * This program is distributed in the hope that it will be useful,
     13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15 * GNU General Public License for more details.
     16 *
     17 * You should have received a copy of the GNU General Public License
     18 * along with this program; if not, write to the Free Software
     19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
     20 *
     21 * $URL$
     22 * $Id$
     23 */
     24
     25/*
     26 * Based on OPL emulation code of DOSBox
     27 * Copyright (C) 2002-2009  The DOSBox Team
     28 * Licensed under GPLv2+
     29 * http://www.dosbox.com
     30 */
     31
     32#ifndef SOUND_SOFTSYNTH_OPL_DOSBOX_H
     33#define SOUND_SOFTSYNTH_OPL_DOSBOX_H
     34
     35#ifndef DISABLE_DOSBOX_OPL
     36
     37#include "sound/fmopl.h"
     38
     39namespace OPL {
     40namespace DOSBox {
     41
     42class Handler;
     43
     44struct Timer {
     45        double startTime;
     46        double delay;
     47        bool enabled, overflow, masked;
     48        uint8 counter;
     49
     50        Timer();
     51
     52        //Call update before making any further changes
     53        void update(double time);
     54
     55        //On a reset make sure the start is in sync with the next cycle
     56        void reset(double time);
     57
     58        void stop();
     59
     60        void start(double time, int scale);
     61};
     62
     63struct Chip {
     64        //Last selected register
     65        Timer timer[2];
     66        //Check for it being a write to the timer
     67        bool write(uint32 addr, uint8 val);
     68        //Read the current timer state, will use current double
     69        uint8 read();
     70};
     71
     72class Handler {
     73public:
     74        virtual ~Handler() {}
     75
     76        // Write an address to a chip, returns the address the chip sets
     77        virtual uint32 writeAddr(uint32 port, uint8 val) = 0;
     78        // Write to a specific register in the chip
     79        virtual void writeReg(uint32 addr, uint8 val) = 0;
     80        // Generate a certain amount of samples
     81        virtual void generate(int16 *chan, uint samples) = 0;
     82        // Initialize at a specific sample rate and mode
     83        virtual void init(uint rate) = 0;
     84};
     85
     86class OPL_DOSBox : public OPL {
     87private:
     88        kOplType _type;
     89        uint _rate;
     90
     91        Handler *_handler;
     92        Chip _chip[2];
     93        union {
     94                uint16 normal;
     95                uint8 dual[2];
     96        } _reg;
     97
     98        void free();
     99public:
     100        OPL_DOSBox(kOplType type);
     101        ~OPL_DOSBox();
     102
     103        bool init(int rate);
     104        void reset();
     105
     106        void write(int a, int v);
     107        byte read(int a);
     108
     109        void writeReg(int r, int v);
     110
     111        void readBuffer(int16 *buffer, int length);
     112};
     113
     114} // end of namespace DOSBox
     115} // end of namespace OPL
     116
     117#endif // !DISABLE_DOSBOX_OPL
     118
     119#endif
     120
  • sound/softsynth/opl/mame.h

     
     1/* ScummVM - Graphic Adventure Engine
     2 *
     3 * ScummVM is the legal property of its developers, whose names
     4 * are too numerous to list here. Please refer to the COPYRIGHT
     5 * file distributed with this source distribution.
     6 *
     7 * This program is free software; you can redistribute it and/or
     8 * modify it under the terms of the GNU General Public License
     9 * as published by the Free Software Foundation; either version 2
     10 * of the License, or (at your option) any later version.
     11
     12 * This program is distributed in the hope that it will be useful,
     13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15 * GNU General Public License for more details.
     16
     17 * You should have received a copy of the GNU General Public License
     18 * along with this program; if not, write to the Free Software
     19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
     20 *
     21 * $URL: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk/sound/fmopl.h $
     22 * $Id: fmopl.h 38211 2009-02-15 10:07:50Z sev $
     23 *
     24 * LGPL licensed version of MAMEs fmopl (V0.37a modified) by
     25 * Tatsuyuki Satoh. Included from LGPL'ed AdPlug.
     26 */
     27
     28
     29#ifndef SOUND_SOFTSYNTH_OPL_MAME_H
     30#define SOUND_SOFTSYNTH_OPL_MAME_H
     31
     32#include "common/scummsys.h"
     33#include "common/util.h"
     34
     35#include "sound/fmopl.h"
     36
     37namespace OPL {
     38namespace MAME {
     39
     40enum {
     41        FMOPL_ENV_BITS_HQ = 16,
     42        FMOPL_ENV_BITS_MQ = 8,
     43        FMOPL_ENV_BITS_LQ = 8,
     44        FMOPL_EG_ENT_HQ = 4096,
     45        FMOPL_EG_ENT_MQ = 1024,
     46        FMOPL_EG_ENT_LQ = 128
     47};
     48
     49
     50typedef void (*OPL_TIMERHANDLER)(int channel,double interval_Sec);
     51typedef void (*OPL_IRQHANDLER)(int param,int irq);
     52typedef void (*OPL_UPDATEHANDLER)(int param,int min_interval_us);
     53
     54#define OPL_TYPE_WAVESEL   0x01  /* waveform select    */
     55
     56/* Saving is necessary for member of the 'R' mark for suspend/resume */
     57/* ---------- OPL one of slot  ---------- */
     58typedef struct fm_opl_slot {
     59        int TL;         /* total level     :TL << 8                             */
     60        int TLL;        /* adjusted now TL                                              */
     61        uint8 KSR;      /* key scale rate  :(shift down bit)    */
     62        int *AR;        /* attack rate     :&AR_TABLE[AR<<2]    */
     63        int *DR;        /* decay rate      :&DR_TABLE[DR<<2]    */
     64        int SL;         /* sustain level   :SL_TABLE[SL]                */
     65        int *RR;        /* release rate    :&DR_TABLE[RR<<2]    */
     66        uint8 ksl;      /* keyscale level  :(shift down bits)   */
     67        uint8 ksr;      /* key scale rate  :kcode>>KSR                  */
     68        uint mul;       /* multiple        :ML_TABLE[ML]                */
     69        uint Cnt;       /* frequency count                                              */
     70        uint Incr;      /* frequency step                                               */
     71
     72        /* envelope generator state */
     73        uint8 eg_typ;/* envelope type flag                                      */
     74        uint8 evm;      /* envelope phase                                               */
     75        int evc;        /* envelope counter                                             */
     76        int eve;        /* envelope counter end point                   */
     77        int evs;        /* envelope counter step                                */
     78        int evsa;       /* envelope step for AR :AR[ksr]                */
     79        int evsd;       /* envelope step for DR :DR[ksr]                */
     80        int evsr;       /* envelope step for RR :RR[ksr]                */
     81
     82        /* LFO */
     83        uint8 ams;              /* ams flag                            */
     84        uint8 vib;              /* vibrate flag                        */
     85        /* wave selector */
     86        int **wavetable;
     87} OPL_SLOT;
     88
     89/* ---------- OPL one of channel  ---------- */
     90typedef struct fm_opl_channel {
     91        OPL_SLOT SLOT[2];
     92        uint8 CON;                      /* connection type                                      */
     93        uint8 FB;                       /* feed back       :(shift down bit)*/
     94        int *connect1;          /* slot1 output pointer                         */
     95        int *connect2;          /* slot2 output pointer                         */
     96        int op1_out[2];         /* slot1 output for selfeedback         */
     97
     98        /* phase generator state */
     99        uint block_fnum;        /* block+fnum                                           */
     100        uint8 kcode;            /* key code        : KeyScaleCode       */
     101        uint fc;                        /* Freq. Increment base                         */
     102        uint ksl_base;          /* KeyScaleLevel Base step                      */
     103        uint8 keyon;            /* key on/off flag                                      */
     104} OPL_CH;
     105
     106/* OPL state */
     107typedef struct fm_opl_f {
     108        uint8 type;                     /* chip type                         */
     109        int clock;                      /* master clock  (Hz)                */
     110        int rate;                       /* sampling rate (Hz)                */
     111        double freqbase;        /* frequency base                    */
     112        double TimerBase;       /* Timer base time (==sampling time) */
     113        uint8 address;          /* address register                  */
     114        uint8 status;           /* status flag                       */
     115        uint8 statusmask;       /* status mask                       */
     116        uint mode;                      /* Reg.08 : CSM , notesel,etc.       */
     117
     118        /* Timer */
     119        int T[2];                       /* timer counter                     */
     120        uint8 st[2];            /* timer enable                      */
     121
     122        /* FM channel slots */
     123        OPL_CH *P_CH;           /* pointer of CH                     */
     124        int     max_ch;                 /* maximum channel                   */
     125
     126        /* Rythm sention */
     127        uint8 rythm;            /* Rythm mode , key flag */
     128
     129        /* time tables */
     130        int AR_TABLE[76];       /* atttack rate tables                          */
     131        int DR_TABLE[76];       /* decay rate tables                            */
     132        uint FN_TABLE[1024];/* fnumber -> increment counter             */
     133
     134        /* LFO */
     135        int *ams_table;
     136        int *vib_table;
     137        int amsCnt;
     138        int amsIncr;
     139        int vibCnt;
     140        int vibIncr;
     141
     142        /* wave selector enable flag */
     143        uint8 wavesel;
     144
     145        /* external event callback handler */
     146        OPL_TIMERHANDLER  TimerHandler;         /* TIMER handler   */
     147        int TimerParam;                                         /* TIMER parameter */
     148        OPL_IRQHANDLER    IRQHandler;           /* IRQ handler    */
     149        int IRQParam;                                           /* IRQ parameter  */
     150        OPL_UPDATEHANDLER UpdateHandler;        /* stream update handler   */
     151        int UpdateParam;                                        /* stream update parameter */
     152
     153        Common::RandomSource rnd;
     154} FM_OPL;
     155
     156/* ---------- Generic interface section ---------- */
     157#define OPL_TYPE_YM3526 (0)
     158#define OPL_TYPE_YM3812 (OPL_TYPE_WAVESEL)
     159
     160void OPLBuildTables(int ENV_BITS_PARAM, int EG_ENT_PARAM);
     161
     162FM_OPL *OPLCreate(int type, int clock, int rate);
     163void OPLDestroy(FM_OPL *OPL);
     164void OPLSetTimerHandler(FM_OPL *OPL, OPL_TIMERHANDLER TimerHandler, int channelOffset);
     165void OPLSetIRQHandler(FM_OPL *OPL, OPL_IRQHANDLER IRQHandler, int param);
     166void OPLSetUpdateHandler(FM_OPL *OPL, OPL_UPDATEHANDLER UpdateHandler, int param);
     167
     168void OPLResetChip(FM_OPL *OPL);
     169int OPLWrite(FM_OPL *OPL, int a, int v);
     170unsigned char OPLRead(FM_OPL *OPL, int a);
     171int OPLTimerOver(FM_OPL *OPL, int c);
     172void OPLWriteReg(FM_OPL *OPL, int r, int v);
     173void YM3812UpdateOne(FM_OPL *OPL, int16 *buffer, int length, int interleave = 0);
     174
     175// Factory method
     176FM_OPL *makeAdlibOPL(int rate);
     177
     178// OPL API implementation
     179class OPL_MAME : public OPL {
     180private:
     181        FM_OPL *_opl;
     182public:
     183        OPL_MAME() : _opl(0) {}
     184        ~OPL_MAME();
     185
     186        bool init(int rate);
     187        void reset();
     188
     189        void write(int a, int v);
     190        byte read(int a);
     191
     192        void writeReg(int r, int v);
     193
     194        void readBuffer(int16 *buffer, int length);
     195};
     196
     197} // end of namespace MAME
     198} // end of namespace OPL
     199
     200#endif
  • sound/softsynth/opl/dbopl.h

     
     1/* ScummVM - Graphic Adventure Engine
     2 *
     3 * ScummVM is the legal property of its developers, whose names
     4 * are too numerous to list here. Please refer to the COPYRIGHT
     5 * file distributed with this source distribution.
     6 *
     7 * This program is free software; you can redistribute it and/or
     8 * modify it under the terms of the GNU General Public License
     9 * as published by the Free Software Foundation; either version 2
     10 * of the License, or (at your option) any later version.
     11 *
     12 * This program is distributed in the hope that it will be useful,
     13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15 * GNU General Public License for more details.
     16 *
     17 * You should have received a copy of the GNU General Public License
     18 * along with this program; if not, write to the Free Software
     19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
     20 *
     21 * $URL$
     22 * $Id$
     23 */
     24
     25/*
     26 * Based on AdLib emulation code of DOSBox
     27 * Copyright (C) 2002-2009  The DOSBox Team
     28 * Licensed under GPLv2+
     29 * http://www.dosbox.com
     30
     31 * Original source file header:
     32
     33 *  Copyright (C) 2002-2009  The DOSBox Team
     34 *
     35 *  This program is free software; you can redistribute it and/or modify
     36 *  it under the terms of the GNU General Public License as published by
     37 *  the Free Software Foundation; either version 2 of the License, or
     38 *  (at your option) any later version.
     39 *
     40 *  This program is distributed in the hope that it will be useful,
     41 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
     42 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     43 *  GNU General Public License for more details.
     44 *
     45 *  You should have received a copy of the GNU General Public License
     46 *  along with this program; if not, write to the Free Software
     47 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
     48 */
     49
     50#ifndef DISABLE_DOSBOX_OPL
     51
     52#ifndef SOUND_SOFTSYNTH_OPL_DBOPL_H
     53#define SOUND_SOFTSYNTH_OPL_DBOPL_H
     54
     55#include "common/scummsys.h"
     56#include "dosbox.h"
     57
     58#ifndef DB_FASTCALL
     59#define DB_FASTCALL
     60#endif
     61
     62//Use 8 handlers based on a small logatirmic wavetabe and an exponential table for volume
     63#define WAVE_HANDLER    10
     64//Use a logarithmic wavetable with an exponential table for volume
     65#define WAVE_TABLELOG   11
     66//Use a linear wavetable with a multiply table for volume
     67#define WAVE_TABLEMUL   12
     68
     69//Select the type of wave generator routine
     70#define DBOPL_WAVE WAVE_TABLEMUL
     71//Enable vibrato in the output
     72#define DBOPL_VIBRATO
     73//Enable tremolo in the output
     74#define DBOPL_TREMOLO
     75
     76namespace OPL {
     77namespace DOSBox {
     78namespace DBOPL {
     79
     80// Define types required by DOSBox code
     81typedef int             Bits;
     82typedef uint    Bitu;
     83typedef int8    Bit8s;
     84typedef uint8   Bit8u;
     85typedef int16   Bit16s;
     86typedef uint16  Bit16u;
     87typedef int32   Bit32s;
     88typedef uint32  Bit32u;
     89
     90struct Chip;
     91struct Operator;
     92struct Channel;
     93
     94#if (DBOPL_WAVE == WAVE_HANDLER)
     95typedef Bits ( DB_FASTCALL *WaveHandler) ( Bitu i, Bitu volume );
     96#endif
     97
     98typedef Bits ( DBOPL::Operator::*VolumeHandler) ( );
     99typedef Channel* ( DBOPL::Channel::*SynthHandler) ( );
     100
     101//Different synth modes that can generate blocks of data
     102enum SynthMode {
     103        smNone,
     104        sm2AM,
     105        sm2FM,
     106        sm2Percussion,
     107        sm3AM,
     108        sm3FM,
     109        sm3FMFM,
     110        sm3AMFM,
     111        sm3FMAM,
     112        sm3AMAM,
     113        sm3Percussion
     114};
     115
     116//Shifts for the values contained in chandata variable
     117enum {
     118        SHIFT_KSLBASE = 16,
     119        SHIFT_KEYCODE = 24
     120};
     121
     122struct Operator {
     123public:
     124        //Masks for operator 20 values
     125        enum {
     126                MASK_KSR = 0x10,
     127                MASK_SUSTAIN = 0x20,
     128                MASK_VIBRATO = 0x40,
     129                MASK_TREMOLO = 0x80
     130        };
     131
     132        enum State {
     133                OFF,
     134                RELEASE,
     135                SUSTAIN,
     136                DECAY,
     137                ATTACK
     138        };
     139
     140        VolumeHandler volHandler;
     141
     142#if (DBOPL_WAVE == WAVE_HANDLER)
     143        WaveHandler waveHandler;        //Routine that generate a wave
     144#else
     145        Bit16s* waveBase;
     146        Bit32u waveMask;
     147        Bit32u waveStart;
     148#endif
     149        Bit32u waveIndex;                       //WAVE_BITS shifted counter of the frequency index
     150        Bit32u waveAdd;
     151
     152        Bit32u chanData;                        //Frequency/octave and derived data coming from whatever channel controls this
     153        Bit32u freqMul;                         //Scale channel frequency with this, TODO maybe remove?
     154        Bit32u vibrato;                         //Scaled up vibrato strength
     155        Bit32s sustainLevel;            //When stopping at sustain level stop here
     156        Bit32s totalLevel;                      //totalLeve is added to every generated volume
     157        Bit32s activeLevel;                     //The currently active volume
     158       
     159        Bit32u attackAdd;                       //Timers for the different states of the envelope
     160        Bit32u decayAdd;
     161        Bit32u releaseAdd;
     162        Bit32u rateIndex;                       //Current position of the evenlope
     163
     164        Bit8u rateZero;                         //Bits for the different states of the envelope having no changes
     165        Bit8u keyOn;                            //Bitmask of different values that can generate keyon
     166        //Registers, also used to check for changes
     167        Bit8u reg20, reg40, reg60, reg80, regE0;
     168        //Active part of the envelope we're in
     169        Bit8u state;
     170        //0xff when tremolo is enabled
     171        Bit8u tremoloMask;
     172        //Strength of the vibrato
     173        Bit8u vibStrength;
     174        //Keep track of the calculated KSR so we can check for changes
     175        Bit8u ksr;
     176private:
     177        void SetState( Bit8u s );
     178        void UpdateAttack( const Chip* chip );
     179        void UpdateRelease( const Chip* chip );
     180        void UpdateDecay( const Chip* chip );
     181public:
     182        void UpdateAttenuation();
     183        void UpdateRates( const Chip* chip );
     184        void UpdateFrequency(  );
     185
     186        void Write20( const Chip* chip, Bit8u val );
     187        void Write40( const Chip* chip, Bit8u val );
     188        void Write60( const Chip* chip, Bit8u val );
     189        void Write80( const Chip* chip, Bit8u val );
     190        void WriteE0( const Chip* chip, Bit8u val );
     191
     192        bool Silent() const;
     193        void KeyOn( Bit8u mask);
     194        void KeyOff( Bit8u mask);
     195
     196        template< State state>
     197        Bits TemplateVolume( );
     198
     199        Bit32s RateForward( Bit32u add );
     200        Bitu ForwardWave();
     201        Bitu ForwardVolume();
     202
     203        Bits GetSample( Bits modulation );
     204        Bits GetWave( Bitu index, Bitu vol );
     205public:
     206        Operator();
     207};
     208
     209struct Channel {
     210        Operator op[2];
     211        inline Operator* Op( Bitu index ) {
     212                return &( ( this + (index >> 1) )->op[ index & 1 ]);
     213        }
     214        SynthHandler synthHandler;
     215        Bit32u chanData;                //Frequency/octave and derived values
     216        Bit32s old[2];                  //Old data for feedback
     217
     218        Bit8u feedback;                 //Feedback shift
     219        Bit8u regB0;                    //Register values to check for changes
     220        Bit8u regC0;
     221        //This should correspond with reg104, bit 6 indicates a Percussion channel, bit 7 indicates a silent channel
     222        Bit8u fourMask;
     223        Bit8s maskLeft;         //Sign extended values for both channel's panning
     224        Bit8s maskRight;
     225
     226        //Forward the channel data to the operators of the channel
     227        void SetChanData( const Chip* chip, Bit32u data );
     228        //Change in the chandata, check for new values and if we have to forward to operators
     229        void UpdateFrequency( const Chip* chip, Bit8u fourOp );
     230        void WriteA0( const Chip* chip, Bit8u val );
     231        void WriteB0( const Chip* chip, Bit8u val );
     232        void WriteC0( const Chip* chip, Bit8u val );
     233        void ResetC0( const Chip* chip );
     234
     235        //call this for the first channel
     236        template< bool opl3Mode >
     237        void GeneratePercussion( Bit32s* output );
     238
     239        //Generate blocks of data in specific modes
     240        template<SynthMode mode>
     241        Channel* BlockTemplate( );
     242        Channel();
     243};
     244
     245struct Chip {
     246        //This is used as the base counter for vibrato and tremolo
     247        Bit32u tremoloCounter;
     248        Bit32u tremoloAdd;
     249        Bit32u vibratoCounter;
     250        Bit32u vibratoAdd;
     251
     252        //Frequency scales for the different multiplications
     253        Bit32u freqMul[16];
     254        //Rates for decay and release for rate of this chip
     255        Bit32u linearRates[76];
     256        //Best match attack rates for the rate of this chip
     257        Bit32u attackRates[76];
     258
     259        //18 channels with 2 operators each
     260        Channel chan[18];
     261
     262        Bit8u reg104;
     263        Bit8u reg08;
     264        Bit8u reg04;
     265        Bit8u regBD;
     266        Bit8u vibratoShift;
     267        Bit8u tremoloShift;
     268        //Mask for allowed wave forms
     269        Bit8u waveFormMask;
     270        //0 or -1 when enabled
     271        Bit8s opl3Active;
     272
     273        Bit8u ForwardTremolo();
     274        Bit8s ForwardVibrato();
     275
     276        void WriteBD( Bit8u val );
     277        void WriteReg(Bit32u reg, Bit8u val );
     278
     279        Bit32u WriteAddr( Bit32u port, Bit8u val );
     280
     281        void GenerateBlock2( Bitu samples );
     282        void GenerateBlock3( Bitu samples );
     283
     284        void Generate( Bit32u samples );
     285        void Setup( Bit32u r );
     286
     287        Chip();
     288};
     289
     290struct Handler : public DOSBox::Handler {
     291        DBOPL::Chip chip;
     292
     293        virtual Bit32u writeAddr( Bit32u port, Bit8u val );
     294        virtual void writeReg( Bit32u addr, Bit8u val );
     295        virtual void generate( Bit16s *chan, Bitu samples );
     296        virtual void init( Bitu rate );
     297};
     298
     299} // end of namespace DBOPL
     300} // end of namespace DOSBox
     301} // end of namespace OPL
     302
     303#endif
     304
     305#endif
     306