#ifdef _MSC_VER
#define INLINE __forceinline
#define DB_FASTCALL __fastcall
#else
#define INLINE inline __attribute__((always_inline))
#endif
#include <cstdint>
typedef double Real64;
typedef unsigned char Bit8u;
typedef signed char Bit8s;
typedef uint16_t Bit16u;
typedef int16_t Bit16s;
typedef uint32_t Bit32u;
typedef int32_t Bit32s;
typedef uint64_t Bit64u;
typedef int64_t Bit64s;
typedef unsigned int Bitu;
typedef signed int Bits;
typedef unsigned long long Bitp;
#include "adlib.h"
#define WAVE_HANDLER 10
#define WAVE_TABLELOG 11
#define WAVE_TABLEMUL 12
#define DBOPL_WAVE WAVE_TABLEMUL
namespace DBOPL {
struct Chip;
struct Operator;
struct Channel;
#if (DBOPL_WAVE == WAVE_HANDLER)
typedef Bits ( DB_FASTCALL *WaveHandler) ( Bitu i, Bitu volume );
#endif
typedef Bits ( DBOPL::Operator::*VolumeHandler) ( );
typedef Channel* ( DBOPL::Channel::*SynthHandler) ( Chip* chip, Bit32u samples, Bit32s* output );
typedef enum {
sm2AM,
sm2FM,
sm3AM,
sm3FM,
sm4Start,
sm3FMFM,
sm3AMFM,
sm3FMAM,
sm3AMAM,
sm6Start,
sm2Percussion,
sm3Percussion,
} SynthMode;
enum {
SHIFT_KSLBASE = 16,
SHIFT_KEYCODE = 24,
};
struct Operator {
public:
enum {
MASK_KSR = 0x10,
MASK_SUSTAIN = 0x20,
MASK_VIBRATO = 0x40,
MASK_TREMOLO = 0x80,
};
typedef enum {
OFF,
RELEASE,
SUSTAIN,
DECAY,
ATTACK,
} State;
VolumeHandler volHandler;
#if (DBOPL_WAVE == WAVE_HANDLER)
WaveHandler waveHandler; #else
Bit16s* waveBase;
Bit32u waveMask;
Bit32u waveStart;
#endif
Bit32u waveIndex; Bit32u waveAdd; Bit32u waveCurrent;
Bit32u chanData; Bit32u freqMul; Bit32u vibrato; Bit32s sustainLevel; Bit32s totalLevel; Bit32u currentLevel; Bit32s volume;
Bit32u attackAdd; Bit32u decayAdd;
Bit32u releaseAdd;
Bit32u rateIndex;
Bit8u rateZero; Bit8u keyOn; Bit8u reg20, reg40, reg60, reg80, regE0;
Bit8u state;
Bit8u tremoloMask;
Bit8u vibStrength;
Bit8u ksr;
private:
void SetState( Bit8u s );
void UpdateAttack( const Chip* chip );
void UpdateRelease( const Chip* chip );
void UpdateDecay( const Chip* chip );
public:
void UpdateAttenuation();
void UpdateRates( const Chip* chip );
void UpdateFrequency( );
void Write20( const Chip* chip, Bit8u val );
void Write40( const Chip* chip, Bit8u val );
void Write60( const Chip* chip, Bit8u val );
void Write80( const Chip* chip, Bit8u val );
void WriteE0( const Chip* chip, Bit8u val );
bool Silent() const;
void Prepare( const Chip* chip );
void KeyOn( Bit8u mask);
void KeyOff( Bit8u mask);
template< State state>
Bits TemplateVolume( );
Bit32s RateForward( Bit32u add );
Bitu ForwardWave();
Bitu ForwardVolume();
Bits GetSample( Bits modulation );
Bits GetWave( Bitu index, Bitu vol );
public:
Operator();
};
struct Channel {
Operator op[2];
inline Operator* Op( Bitu index ) {
return &( ( this + (index >> 1) )->op[ index & 1 ]);
}
SynthHandler synthHandler;
Bit32u chanData; Bit32s old[2];
Bit8u feedback; Bit8u regB0; Bit8u regC0;
Bit8u fourMask;
Bit8s maskLeft; Bit8s maskRight;
void SetChanData( const Chip* chip, Bit32u data );
void UpdateFrequency( const Chip* chip, Bit8u fourOp );
void WriteA0( const Chip* chip, Bit8u val );
void WriteB0( const Chip* chip, Bit8u val );
void WriteC0( const Chip* chip, Bit8u val );
void ResetC0( const Chip* chip );
template< bool opl3Mode >
void GeneratePercussion( Chip* chip, Bit32s* output );
template<SynthMode mode>
Channel* BlockTemplate( Chip* chip, Bit32u samples, Bit32s* output );
Channel();
};
struct Chip {
Bit32u lfoCounter;
Bit32u lfoAdd;
Bit32u noiseCounter;
Bit32u noiseAdd;
Bit32u noiseValue;
Bit32u freqMul[16];
Bit32u linearRates[76];
Bit32u attackRates[76];
Channel chan[18];
Bit8u reg104;
Bit8u reg08;
Bit8u reg04;
Bit8u regBD;
Bit8u vibratoIndex;
Bit8u tremoloIndex;
Bit8s vibratoSign;
Bit8u vibratoShift;
Bit8u tremoloValue;
Bit8u vibratoStrength;
Bit8u tremoloStrength;
Bit8u waveFormMask;
Bit8s opl3Active;
Bit32u ForwardLFO( Bit32u samples );
Bit32u ForwardNoise();
void WriteBD( Bit8u val );
void WriteReg(Bit32u reg, Bit8u val );
Bit32u WriteAddr( Bit32u port, Bit8u val );
void GenerateBlock2( Bitu samples, Bit32s* output );
void GenerateBlock3( Bitu samples, Bit32s* output );
void Generate( Bit32u samples );
void Setup( Bit32u r );
Chip();
};
};