1 // This file is taken from the openMSX project. 2 // The file has been modified to be built in the blueMSX environment. 3 4 #ifndef __YMF278_HH__ 5 #define __YMF278_HH__ 6 7 #include <string> 8 9 using namespace std; 10 11 12 typedef unsigned long EmuTime; 13 typedef unsigned char byte; 14 typedef unsigned short word; 15 16 17 #ifndef OPENMSX_SOUNDDEVICE 18 #define OPENMSX_SOUNDDEVICE 19 20 extern "C" { 21 #include "AudioMixer.h" 22 } 23 24 class SoundDevice 25 { 26 public: SoundDevice()27 SoundDevice() : internalMuted(true) {} setVolume(short newVolume)28 void setVolume(short newVolume) { 29 setInternalVolume(newVolume); 30 } 31 32 protected: 33 virtual void setInternalVolume(short newVolume) = 0; setInternalMute(bool muted)34 void setInternalMute(bool muted) { internalMuted = muted; } isInternalMuted()35 bool isInternalMuted() const { return internalMuted; } 36 public: 37 virtual void setSampleRate(int newSampleRate, int Oversampling) = 0; 38 virtual int* updateBuffer(int length) = 0; 39 40 private: 41 bool internalMuted; 42 }; 43 44 #endif 45 46 47 class YMF278Slot 48 { 49 public: 50 YMF278Slot(); 51 void reset(); 52 int compute_rate(int val); 53 unsigned int decay_rate(int num, int sample_rate); 54 void envelope_next(int sample_rate); 55 inline int compute_vib(); 56 inline int compute_am(); 57 void set_lfo(int newlfo); 58 59 short wave; // wavetable number 60 short FN; // f-number 61 char OCT; // octave 62 char PRVB; // pseudo-reverb 63 char LD; // level direct 64 char TL; // total level 65 char pan; // panpot 66 char lfo; // LFO 67 char vib; // vibrato 68 char AM; // AM level 69 70 char AR; 71 char D1R; 72 int DL; 73 char D2R; 74 char RC; // rate correction 75 char RR; 76 77 int step; // fixed-point frequency step 78 int stepptr; // fixed-point pointer into the sample 79 int pos; 80 short sample1, sample2; 81 82 bool active; // slot keyed on 83 byte bits; // width of the samples 84 int startaddr; 85 int loopaddr; 86 int endaddr; 87 88 byte state; 89 int env_vol; 90 unsigned int env_vol_step; 91 unsigned int env_vol_lim; 92 93 bool lfo_active; 94 int lfo_cnt; 95 int lfo_step; 96 int lfo_max; 97 }; 98 99 static const int MASTER_CLK = 33868800; 100 101 class YMF278 : public SoundDevice 102 { 103 public: 104 YMF278(short volume, int ramSize, void* romData, int romSize, 105 const EmuTime &time); 106 virtual ~YMF278(); 107 void reset(const EmuTime &time); 108 void writeRegOPL4(byte reg, byte data, const EmuTime &time); 109 byte peekRegOPL4(byte reg, const EmuTime &time); 110 byte readRegOPL4(byte reg, const EmuTime &time); 111 byte peekStatus(const EmuTime &time); 112 byte readStatus(const EmuTime &time); getRom()113 void* getRom() { return rom; } getRam()114 void* getRam() { return ram; } getRomSize()115 int getRomSize() { return endRom; } getRamSize()116 int getRamSize() { return endRam - endRom; } 117 virtual void setSampleRate(int sampleRate, int Oversampling); 118 virtual void setInternalVolume(short newVolume); 119 virtual int* updateBuffer(int length); 120 121 void loadState(); 122 void saveState(); 123 124 private: 125 byte readMem(unsigned int address); 126 void writeMem(unsigned int address, byte value); 127 short getSample(YMF278Slot &op); 128 void advance(); 129 void checkMute(); 130 bool anyActive(); 131 void keyOnHelper(YMF278Slot& slot); 132 133 int buffer[AUDIO_STEREO_BUFFER_SIZE]; 134 byte* rom; 135 byte* ram; 136 137 int oplOversampling; 138 DoubleT freqbase; 139 140 YMF278Slot slots[24]; 141 142 int ramSize; 143 144 unsigned int eg_cnt; // global envelope generator counter 145 unsigned int eg_timer; // global envelope generator counter 146 unsigned int eg_timer_add; // step of eg_timer 147 unsigned int eg_timer_overflow; // envelope generator timer overlfows every 1 sample (on real chip) 148 149 char wavetblhdr; 150 char memmode; 151 int memadr; 152 153 int fm_l, fm_r; 154 int pcm_l, pcm_r; 155 156 unsigned int endRom; 157 unsigned int endRam; 158 159 // precalculated attenuation values with some marging for 160 // enveloppe and pan levels 161 int volume[256 * 4]; 162 163 byte regs[256]; 164 165 unsigned long LD_Time; 166 unsigned long BUSY_Time; 167 }; 168 169 #endif 170 171