// This file is taken from the openMSX project.
// The file has been modified to be built in the blueMSX environment.
#ifndef __YMF278_HH__
#define __YMF278_HH__
#include "../sysdefs.h"
using namespace std;
typedef unsigned long EmuTime;
typedef unsigned short word;
#ifndef OPENMSX_SOUNDDEVICE
#define OPENMSX_SOUNDDEVICE
#define MAX_BUFFER_SIZE 10000
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 YMF278Slot
{
public:
YMF278Slot();
void reset();
int compute_rate(int val);
unsigned int decay_rate(int num, int sample_rate);
void envelope_next(int sample_rate);
inline int compute_vib();
inline int compute_am();
void set_lfo(int newlfo);
short wave; // wavetable number
short FN; // f-number
char OCT; // octave
char PRVB; // pseudo-reverb
char LD; // level direct
char TL; // total level
char pan; // panpot
char lfo; // LFO
char vib; // vibrato
char AM; // AM level
char AR;
char D1R;
int DL;
char D2R;
char RC; // rate correction
char RR;
int step; // fixed-point frequency step
int stepptr; // fixed-point pointer into the sample
int pos;
short sample1, sample2;
bool active; // slot keyed on
u8 bits; // width of the samples
int startaddr;
int loopaddr;
int endaddr;
u8 state;
int env_vol;
unsigned int env_vol_step;
unsigned int env_vol_lim;
bool lfo_active;
int lfo_cnt;
int lfo_step;
int lfo_max;
};
static const int MASTER_CLK = 33868800;
class YMF278 : public SoundDevice
{
public:
YMF278(short volume, size_t ramSizeKb, size_t romSizeKb,
const EmuTime &time);
virtual ~YMF278();
void reset(const EmuTime &time);
void writeRegOPL4(u8 reg, u8 data, const EmuTime &time);
u8 peekRegOPL4(u8 reg, const EmuTime &time);
u8 readRegOPL4(u8 reg, const EmuTime &time);
u8 peekStatus(const EmuTime &time);
u8 readStatus(const EmuTime &time);
u8 * getRom();
size_t getRomSize();
virtual void setSampleRate(int sampleRate, int Oversampling);
virtual void setInternalVolume(short newVolume);
virtual int* updateBuffer(int length);
private:
void attempt_alloc_rom();
void attempt_alloc_ram();
u8 readMem(unsigned int address);
void writeMem(unsigned int address, u8 value);
short getSample(YMF278Slot &op);
void advance();
void checkMute();
bool anyActive();
void keyOnHelper(YMF278Slot& slot);
int buffer[2 * MAX_BUFFER_SIZE];
size_t ramSize;
size_t romSize;
size_t endRom;
size_t endRam;
u8* rom;
bool rom_alloc_attempted;
u8* ram;
bool ram_alloc_attempted;
int oplOversampling;
double freqbase;
YMF278Slot slots[24];
unsigned int eg_cnt; // global envelope generator counter
unsigned int eg_timer; // global envelope generator counter
unsigned int eg_timer_add; // step of eg_timer
unsigned int eg_timer_overflow; // envelope generator timer overlfows every 1 sample (on real chip)
char wavetblhdr;
char memmode;
int memadr;
int fm_l, fm_r;
int pcm_l, pcm_r;
// precalculated attenuation values with some marging for
// enveloppe and pan levels
int volume[256 * 4];
u8 regs[256];
unsigned long LD_Time;
unsigned long BUSY_Time;
};
#endif