Top secrets sources NedoPC pentevo

Rev

Rev 1099 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed | ?url?

// This file is taken from the openMSX project.
// The file has been modified to be built in the blueMSX environment.

#ifndef __YMF262_HH__
#define __YMF262_HH__

#include "../sysdefs.h"

using namespace std;


typedef unsigned long  EmuTime;

#define MAX_BUFFER_SIZE 10000

class TimerCallback
{
        public:
                virtual void callback(u8 value) = 0;
};

template<unsigned timerFreq, u8 flag>
struct Timer
{
    unsigned tStatesPerTick;
    EmuTime timerPeriod;
    EmuTime startTime;
    u8 flags;
    bool isStarted;

    void init(unsigned tStatesPerSecond)
    {
        tStatesPerTick = tStatesPerSecond / timerFreq;
        flags = 0;
        isStarted = false;
    }

    void setValue(u8 value)
    {
        timerPeriod = tStatesPerTick * (256 - value);
    }

    void setStart(bool start, const EmuTime &time)
    {
        isStarted = start;
        startTime = time;
    }

    void resetFlags()
    {
        flags = 0;
    }

    u8 poll(const EmuTime &time)
    {
        if (isStarted)
        {
            EmuTime dt = time - startTime;
            while (dt > timerPeriod)
            {
                dt -= timerPeriod;
                startTime += timerPeriod;
                flags |= (flag | 0x80);
            }
        }

        return flags;
    }
};

#ifndef OPENMSX_SOUNDDEVICE
#define OPENMSX_SOUNDDEVICE

class SoundDevice
{
        public:
        SoundDevice() : internalMuted(true) {}
                void setVolume(short newVolume) {
                setInternalVolume(newVolume);
        }

        protected:
                virtual void setInternalVolume(short newVolume) = 0;
        void setInternalMute(bool muted) { internalMuted = muted; }
        bool isInternalMuted() const { return internalMuted; }
        public:
                virtual void setSampleRate(int newSampleRate, int Oversampling) = 0;
                virtual int* updateBuffer(int length) = 0;

        private:
                bool internalMuted;
};

#endif

class YMF262Slot
{
        public:
                YMF262Slot();
                inline int volume_calc(u8 LFO_AM);
                inline void FM_KEYON(u8 key_set);
                inline void FM_KEYOFF(u8 key_clr);

                u8 ar;  // attack rate: AR<<2
                u8 dr;  // decay rate:  DR<<2
                u8 rr;  // release rate:RR<<2
                u8 KSR; // key scale rate
                u8 ksl; // keyscale level
                u8 ksr; // key scale rate: kcode>>KSR
                u8 mul; // multiple: mul_tab[ML]

                // Phase Generator
                unsigned int Cnt;       // frequency counter
                unsigned int Incr;      // frequency counter step
                u8 FB;  // feedback shift value
                int op1_out[2]; // slot1 output for feedback
                u8 CON; // connection (algorithm) type

                // Envelope Generator
                u8 eg_type;     // percussive/non-percussive mode
                u8 state;       // phase type
                unsigned int TL;        // total level: TL << 2
                int TLL;        // adjusted now TL
                int volume;     // envelope counter
                int sl;         // sustain level: sl_tab[SL]

                unsigned int eg_m_ar;// (attack state)
                u8 eg_sh_ar;    // (attack state)
                u8 eg_sel_ar;   // (attack state)
                unsigned int eg_m_dr;// (decay state)
                u8 eg_sh_dr;    // (decay state)
                u8 eg_sel_dr;   // (decay state)
                unsigned int eg_m_rr;// (release state)
                u8 eg_sh_rr;    // (release state)
                u8 eg_sel_rr;   // (release state)

                u8 key; // 0 = KEY OFF, >0 = KEY ON

                // LFO
                u8  AMmask;     // LFO Amplitude Modulation enable mask
                u8 vib; // LFO Phase Modulation enable flag (active high)

                // waveform select
                u8 waveform_number;
                unsigned int wavetable;

                int connect;    // slot output pointer
};

class YMF262Channel
{
        public:
                YMF262Channel();
                void chan_calc(u8 LFO_AM);
                void chan_calc_ext(u8 LFO_AM);
                void CALC_FCSLOT(YMF262Slot &slot);

                YMF262Slot slots[2];

                int block_fnum; // block+fnum
                int fc;         // Freq. Increment base
                int ksl_base;   // KeyScaleLevel Base step
                u8 kcode;       // key code (for key scaling)

                // there are 12 2-operator channels which can be combined in pairs
                // to form six 4-operator channel, they are:
                //  0 and 3,
                //  1 and 4,
                //  2 and 5,
                //  9 and 12,
                //  10 and 13,
                //  11 and 14
                u8 extended;    // set to 1 if this channel forms up a 4op channel with another channel(only used by first of pair of channels, ie 0,1,2 and 9,10,11)
};

// Bitmask for register 0x04
static const int R04_ST1          = 0x01;       // Timer1 Start
static const int R04_ST2          = 0x02;       // Timer2 Start
static const int R04_MASK_T2      = 0x20;       // Mask Timer2 flag
static const int R04_MASK_T1      = 0x40;       // Mask Timer1 flag
static const int R04_IRQ_RESET    = 0x80;       // IRQ RESET

// Bitmask for status register
static const int STATUS_T2      = R04_MASK_T2;
static const int STATUS_T1      = R04_MASK_T1;

class YMF262 : public SoundDevice, public TimerCallback
{
        public:
                YMF262(short volume, const EmuTime &time);
                virtual ~YMF262();
               
                void reset(const EmuTime &time, unsigned tStatesPerSecond);
                void writeReg(int r, u8 v, const EmuTime &time);
                u8 peekReg(int reg);
                u8 readReg(int reg);
                u8 peekStatus(const EmuTime& time);
                u8 readStatus(const EmuTime& time);
               
                virtual void setInternalVolume(short volume);
                virtual void setSampleRate(int sampleRate, int Oversampling);
                virtual int* updateBuffer(int length);

                void callback(u8 flag);

        private:
                void writeRegForce(int r, u8 v, const EmuTime &time);
                void init_tables(void);
                void setStatus(u8 flag);
                void resetStatus(u8 flag);
                void changeStatusMask(u8 flag);
                void advance_lfo();
                void advance();
                void chan_calc_rhythm(bool noise);
                void set_mul(u8 sl, u8 v);
                void set_ksl_tl(u8 sl, u8 v);
                void set_ar_dr(u8 sl, u8 v);
                void set_sl_rr(u8 sl, u8 v);
                void update_channels(YMF262Channel &ch);
                void checkMute();
                bool checkMuteHelper();

        int buffer[MAX_BUFFER_SIZE];
                Timer<12500, STATUS_T1> timer1; //  80us
                Timer< 3125, STATUS_T2> timer2; // 320us

        int oplOversampling;

        YMF262Channel channels[18];     // OPL3 chips have 18 channels

                u8 reg[512];

        unsigned int pan[18*4];         // channels output masks (0xffffffff = enable); 4 masks per one channel

                unsigned int eg_cnt;            // global envelope generator counter
                unsigned int eg_timer;          // global envelope generator counter works at frequency = chipclock/288 (288=8*36)
                unsigned int eg_timer_add;              // step of eg_timer

                unsigned int fn_tab[1024];              // fnumber->increment counter

                // LFO
                u8 LFO_AM;
                u8 LFO_PM;
               
                u8 lfo_am_depth;
                u8 lfo_pm_depth_range;
                unsigned int lfo_am_cnt;
                unsigned int lfo_am_inc;
                unsigned int lfo_pm_cnt;
                unsigned int lfo_pm_inc;

                unsigned int noise_rng;         // 23 bit noise shift register
                unsigned int noise_p;           // current noise 'phase'
                unsigned int noise_f;           // current noise period

                bool OPL3_mode;                 // OPL3 extension enable flag
                u8 rhythm;                      // Rhythm mode
                u8 nts;                 // NTS (note select)

                u8 status;                      // status flag
                u8 status2;
                u8 statusMask;          // status mask

                int chanout[20];                // 18 channels + two phase modulation
                short maxVolume;
};

#endif