Merge branch 'master' into ZSMv1
This commit is contained in:
commit
40d67d7bb5
757 changed files with 4340 additions and 359 deletions
|
|
@ -109,14 +109,15 @@ const char* DivPlatformC64::getEffectName(unsigned char effect) {
|
|||
}
|
||||
|
||||
void DivPlatformC64::acquire(short* bufL, short* bufR, size_t start, size_t len) {
|
||||
int dcOff=sid.get_dc(0);
|
||||
for (size_t i=start; i<start+len; i++) {
|
||||
sid.clock();
|
||||
bufL[i]=sid.output();
|
||||
if (++writeOscBuf>=8) {
|
||||
writeOscBuf=0;
|
||||
oscBuf[0]->data[oscBuf[0]->needle++]=sid.last_chan_out[0]>>5;
|
||||
oscBuf[1]->data[oscBuf[1]->needle++]=sid.last_chan_out[1]>>5;
|
||||
oscBuf[2]->data[oscBuf[2]->needle++]=sid.last_chan_out[2]>>5;
|
||||
oscBuf[0]->data[oscBuf[0]->needle++]=(sid.last_chan_out[0]-dcOff)>>5;
|
||||
oscBuf[1]->data[oscBuf[1]->needle++]=(sid.last_chan_out[1]-dcOff)>>5;
|
||||
oscBuf[2]->data[oscBuf[2]->needle++]=(sid.last_chan_out[2]-dcOff)>>5;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -104,12 +104,14 @@ class DivPlatformOPN: public DivPlatformFMBase {
|
|||
double fmFreqBase;
|
||||
unsigned int fmDivBase;
|
||||
unsigned int ayDiv;
|
||||
bool extSys;
|
||||
|
||||
DivPlatformOPN(double f=9440540.0, unsigned int d=72, unsigned int a=32):
|
||||
DivPlatformOPN(double f=9440540.0, unsigned int d=72, unsigned int a=32, bool isExtSys=false):
|
||||
DivPlatformFMBase(),
|
||||
fmFreqBase(f),
|
||||
fmDivBase(d),
|
||||
ayDiv(a) {}
|
||||
ayDiv(a),
|
||||
extSys(isExtSys) {}
|
||||
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -342,13 +342,17 @@ void DivPlatformGenesis::acquire(short* bufL, short* bufR, size_t start, size_t
|
|||
}
|
||||
|
||||
void DivPlatformGenesis::tick(bool sysTick) {
|
||||
for (int i=0; i<6; i++) {
|
||||
for (int i=0; i<(softPCM?7:6); i++) {
|
||||
if (i==2 && extMode) continue;
|
||||
chan[i].std.next();
|
||||
|
||||
if (chan[i].std.vol.had) {
|
||||
chan[i].outVol=VOL_SCALE_LOG(chan[i].vol,MIN(127,chan[i].std.vol.val),127);
|
||||
for (int j=0; j<4; j++) {
|
||||
int inVol=chan[i].std.vol.val;
|
||||
if (chan[i].furnaceDac && inVol>0) {
|
||||
inVol+=63;
|
||||
}
|
||||
chan[i].outVol=VOL_SCALE_LOG(chan[i].vol,MIN(127,inVol),127);
|
||||
if (i<6) for (int j=0; j<4; j++) {
|
||||
unsigned short baseAddr=chanOffs[i]|opOffs[j];
|
||||
DivInstrumentFM::Operator& op=chan[i].state.op[j];
|
||||
if (isMuted[i]) {
|
||||
|
|
@ -381,7 +385,9 @@ void DivPlatformGenesis::tick(bool sysTick) {
|
|||
|
||||
if (chan[i].std.panL.had) {
|
||||
chan[i].pan=chan[i].std.panL.val&3;
|
||||
rWrite(chanOffs[i]+ADDR_LRAF,(IS_REALLY_MUTED(i)?0:(chan[i].pan<<6))|(chan[i].state.fms&7)|((chan[i].state.ams&3)<<4));
|
||||
if (i<6) {
|
||||
rWrite(chanOffs[i]+ADDR_LRAF,(IS_REALLY_MUTED(i)?0:(chan[i].pan<<6))|(chan[i].state.fms&7)|((chan[i].state.ams&3)<<4));
|
||||
}
|
||||
}
|
||||
|
||||
if (chan[i].std.pitch.had) {
|
||||
|
|
@ -394,6 +400,8 @@ void DivPlatformGenesis::tick(bool sysTick) {
|
|||
chan[i].freqChanged=true;
|
||||
}
|
||||
|
||||
if (i>=6) continue;
|
||||
|
||||
if (chan[i].std.phaseReset.had) {
|
||||
if (chan[i].std.phaseReset.val==1 && chan[i].active) {
|
||||
chan[i].keyOn=true;
|
||||
|
|
@ -634,9 +642,20 @@ int DivPlatformGenesis::dispatch(DivCommand c) {
|
|||
chan[c.chan].dacPeriod=0;
|
||||
if (c.value!=DIV_NOTE_NULL) {
|
||||
chan[c.chan].baseFreq=parent->calcBaseFreq(1,1,c.value,false);
|
||||
chan[c.chan].portaPause=false;
|
||||
chan[c.chan].note=c.value;
|
||||
chan[c.chan].freqChanged=true;
|
||||
}
|
||||
chan[c.chan].furnaceDac=true;
|
||||
|
||||
chan[c.chan].macroInit(ins);
|
||||
if (!chan[c.chan].std.vol.will) {
|
||||
chan[c.chan].outVol=chan[c.chan].vol;
|
||||
}
|
||||
|
||||
// ???
|
||||
//chan[c.chan].keyOn=true;
|
||||
chan[c.chan].active=true;
|
||||
} else { // compatible mode
|
||||
if (c.value!=DIV_NOTE_NULL) {
|
||||
chan[c.chan].note=c.value;
|
||||
|
|
@ -886,6 +905,13 @@ int DivPlatformGenesis::dispatch(DivCommand c) {
|
|||
chan[c.chan].freqChanged=true;
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_EXTCH: {
|
||||
if (extSys) {
|
||||
extMode=c.value;
|
||||
immWrite(0x27,extMode?0x40:0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_LFO: {
|
||||
if (c.chan>=6) break;
|
||||
lfoValue=(c.value&7)|((c.value>>4)<<3);
|
||||
|
|
|
|||
|
|
@ -34,6 +34,10 @@ int DivPlatformGenesisExt::dispatch(DivCommand c) {
|
|||
}
|
||||
int ch=c.chan-2;
|
||||
int ordch=orderedOps[ch];
|
||||
if (!extMode) {
|
||||
c.chan=2;
|
||||
return DivPlatformGenesis::dispatch(c);
|
||||
}
|
||||
switch (c.cmd) {
|
||||
case DIV_CMD_NOTE_ON: {
|
||||
DivInstrument* ins=parent->getIns(opChan[ch].ins,DIV_INS_FM);
|
||||
|
|
@ -173,6 +177,11 @@ int DivPlatformGenesisExt::dispatch(DivCommand c) {
|
|||
opChan[ch].freqChanged=true;
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_EXTCH: {
|
||||
extMode=c.value;
|
||||
immWrite(0x27,extMode?0x40:0);
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_LFO: {
|
||||
lfoValue=(c.value&7)|((c.value>>4)<<3);
|
||||
rWrite(0x22,lfoValue);
|
||||
|
|
@ -489,7 +498,7 @@ void DivPlatformGenesisExt::forceIns() {
|
|||
for (int j=0; j<4; j++) {
|
||||
unsigned short baseAddr=chanOffs[i]|opOffs[j];
|
||||
DivInstrumentFM::Operator& op=chan[i].state.op[j];
|
||||
if (i==2) { // extended channel
|
||||
if (i==2 && extMode) { // extended channel
|
||||
if (isOpMuted[j]) {
|
||||
rWrite(baseAddr+0x40,127);
|
||||
} else if (isOutput[chan[i].state.alg][j]) {
|
||||
|
|
@ -592,6 +601,7 @@ int DivPlatformGenesisExt::init(DivEngine* parent, int channels, int sugRate, un
|
|||
for (int i=0; i<4; i++) {
|
||||
isOpMuted[i]=false;
|
||||
}
|
||||
extSys=true;
|
||||
|
||||
reset();
|
||||
return 13;
|
||||
|
|
|
|||
|
|
@ -322,7 +322,7 @@ void DivPlatformNamcoWSG::tick(bool sysTick) {
|
|||
}
|
||||
rWrite((i<<3)+0x04,chan[i].freq&0xff);
|
||||
rWrite((i<<3)+0x05,(chan[i].freq>>8)&0xff);
|
||||
rWrite((i<<3)+0x06,((chan[i].freq>>15)&15)|(i<<4));
|
||||
rWrite((i<<3)+0x06,((chan[i].freq>>16)&15)|(i<<4));
|
||||
}
|
||||
break;
|
||||
case 30:
|
||||
|
|
@ -336,7 +336,7 @@ void DivPlatformNamcoWSG::tick(bool sysTick) {
|
|||
}
|
||||
rWrite((i<<3)+0x103,chan[i].freq&0xff);
|
||||
rWrite((i<<3)+0x102,(chan[i].freq>>8)&0xff);
|
||||
rWrite((i<<3)+0x101,((chan[i].freq>>15)&15)|(i<<4));
|
||||
rWrite((i<<3)+0x101,((chan[i].freq>>16)&15)|(i<<4));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -299,18 +299,39 @@ void DivPlatformOPL::acquire_nuked(short* bufL, short* bufR, size_t start, size_
|
|||
}
|
||||
}
|
||||
|
||||
for (int i=0; i<chans; i++) {
|
||||
unsigned char ch=outChanMap[i];
|
||||
if (ch==255) continue;
|
||||
oscBuf[i]->data[oscBuf[i]->needle]=0;
|
||||
if (fm.channel[i].out[0]!=NULL) {
|
||||
oscBuf[i]->data[oscBuf[i]->needle]+=*fm.channel[ch].out[0];
|
||||
if (fm.rhy&0x20) {
|
||||
for (int i=0; i<melodicChans+1; i++) {
|
||||
unsigned char ch=outChanMap[i];
|
||||
if (ch==255) continue;
|
||||
oscBuf[i]->data[oscBuf[i]->needle]=0;
|
||||
if (fm.channel[i].out[0]!=NULL) {
|
||||
oscBuf[i]->data[oscBuf[i]->needle]+=*fm.channel[ch].out[0];
|
||||
}
|
||||
if (fm.channel[i].out[1]!=NULL) {
|
||||
oscBuf[i]->data[oscBuf[i]->needle]+=*fm.channel[ch].out[1];
|
||||
}
|
||||
oscBuf[i]->data[oscBuf[i]->needle]<<=1;
|
||||
oscBuf[i]->needle++;
|
||||
}
|
||||
if (fm.channel[i].out[1]!=NULL) {
|
||||
oscBuf[i]->data[oscBuf[i]->needle]+=*fm.channel[ch].out[1];
|
||||
// special
|
||||
oscBuf[melodicChans+1]->data[oscBuf[melodicChans+1]->needle++]=fm.slot[16].out*6;
|
||||
oscBuf[melodicChans+2]->data[oscBuf[melodicChans+2]->needle++]=fm.slot[14].out*6;
|
||||
oscBuf[melodicChans+3]->data[oscBuf[melodicChans+3]->needle++]=fm.slot[17].out*6;
|
||||
oscBuf[melodicChans+4]->data[oscBuf[melodicChans+4]->needle++]=fm.slot[13].out*6;
|
||||
} else {
|
||||
for (int i=0; i<chans; i++) {
|
||||
unsigned char ch=outChanMap[i];
|
||||
if (ch==255) continue;
|
||||
oscBuf[i]->data[oscBuf[i]->needle]=0;
|
||||
if (fm.channel[i].out[0]!=NULL) {
|
||||
oscBuf[i]->data[oscBuf[i]->needle]+=*fm.channel[ch].out[0];
|
||||
}
|
||||
if (fm.channel[i].out[1]!=NULL) {
|
||||
oscBuf[i]->data[oscBuf[i]->needle]+=*fm.channel[ch].out[1];
|
||||
}
|
||||
oscBuf[i]->data[oscBuf[i]->needle]<<=1;
|
||||
oscBuf[i]->needle++;
|
||||
}
|
||||
oscBuf[i]->data[oscBuf[i]->needle]<<=1;
|
||||
oscBuf[i]->needle++;
|
||||
}
|
||||
|
||||
if (os[0]<-32768) os[0]=-32768;
|
||||
|
|
@ -601,8 +622,9 @@ void DivPlatformOPL::tick(bool sysTick) {
|
|||
if (chan[i].freqChanged) {
|
||||
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,false,octave(chan[i].baseFreq)*2,chan[i].pitch2,chipClock,CHIP_FREQBASE);
|
||||
if (chan[i].fixedFreq>0) chan[i].freq=chan[i].fixedFreq;
|
||||
if (chan[i].freq<0) chan[i].freq=0;
|
||||
if (chan[i].freq>131071) chan[i].freq=131071;
|
||||
int freqt=toFreq(chan[i].freq)+chan[i].pitch2;
|
||||
int freqt=toFreq(chan[i].freq);
|
||||
chan[i].freqH=freqt>>8;
|
||||
chan[i].freqL=freqt&0xff;
|
||||
immWrite(chanMap[i]+ADDR_FREQ,chan[i].freqL);
|
||||
|
|
@ -1778,7 +1800,7 @@ void DivPlatformOPL::setFlags(unsigned int flags) {
|
|||
break;
|
||||
}
|
||||
|
||||
for (int i=0; i<18; i++) {
|
||||
for (int i=0; i<20; i++) {
|
||||
oscBuf[i]->rate=rate;
|
||||
}
|
||||
}
|
||||
|
|
@ -1829,7 +1851,7 @@ int DivPlatformOPL::init(DivEngine* p, int channels, int sugRate, unsigned int f
|
|||
for (int i=0; i<20; i++) {
|
||||
isMuted[i]=false;
|
||||
}
|
||||
for (int i=0; i<18; i++) {
|
||||
for (int i=0; i<20; i++) {
|
||||
oscBuf[i]=new DivDispatchOscBuffer;
|
||||
}
|
||||
setFlags(flags);
|
||||
|
|
@ -1847,7 +1869,7 @@ int DivPlatformOPL::init(DivEngine* p, int channels, int sugRate, unsigned int f
|
|||
}
|
||||
|
||||
void DivPlatformOPL::quit() {
|
||||
for (int i=0; i<18; i++) {
|
||||
for (int i=0; i<20; i++) {
|
||||
delete oscBuf[i];
|
||||
}
|
||||
if (adpcmChan>=0) {
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ class DivPlatformOPL: public DivDispatch {
|
|||
}
|
||||
};
|
||||
Channel chan[20];
|
||||
DivDispatchOscBuffer* oscBuf[18];
|
||||
DivDispatchOscBuffer* oscBuf[20];
|
||||
bool isMuted[20];
|
||||
struct QueuedWrite {
|
||||
unsigned short addr;
|
||||
|
|
|
|||
|
|
@ -97,6 +97,10 @@ const unsigned char drumSlot[11]={
|
|||
0, 0, 0, 0, 0, 0, 6, 7, 8, 8, 7
|
||||
};
|
||||
|
||||
const unsigned char visMapOPLL[9]={
|
||||
6, 7, 8, 3, 4, 5, 0, 1, 2
|
||||
};
|
||||
|
||||
void DivPlatformOPLL::acquire_nuked(short* bufL, short* bufR, size_t start, size_t len) {
|
||||
static int o[2];
|
||||
static int os;
|
||||
|
|
@ -124,10 +128,18 @@ void DivPlatformOPLL::acquire_nuked(short* bufL, short* bufR, size_t start, size
|
|||
OPLL_Clock(&fm,o);
|
||||
unsigned char nextOut=cycleMapOPLL[fm.cycles];
|
||||
if ((nextOut>=6 && properDrums) || !isMuted[nextOut]) {
|
||||
oscBuf[nextOut]->data[oscBuf[nextOut]->needle++]=(o[0]+o[1])<<6;
|
||||
os+=(o[0]+o[1]);
|
||||
if (vrc7 || (fm.rm_enable&0x20)) oscBuf[nextOut]->data[oscBuf[nextOut]->needle++]=(o[0]+o[1])<<6;
|
||||
} else {
|
||||
oscBuf[nextOut]->data[oscBuf[nextOut]->needle++]=0;
|
||||
if (vrc7 || (fm.rm_enable&0x20)) oscBuf[nextOut]->data[oscBuf[nextOut]->needle++]=0;
|
||||
}
|
||||
}
|
||||
if (!(vrc7 || (fm.rm_enable&0x20))) for (int i=0; i<9; i++) {
|
||||
unsigned char ch=visMapOPLL[i];
|
||||
if ((i>=6 && properDrums) || !isMuted[ch]) {
|
||||
oscBuf[ch]->data[oscBuf[ch]->needle++]=(fm.output_ch[i])<<6;
|
||||
} else {
|
||||
oscBuf[ch]->data[oscBuf[ch]->needle++]=0;
|
||||
}
|
||||
}
|
||||
os*=50;
|
||||
|
|
|
|||
|
|
@ -27,11 +27,17 @@
|
|||
#include <sys/select.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#ifdef HAVE_LINUX_INPUT
|
||||
#include <linux/input.h>
|
||||
#endif
|
||||
#ifdef HAVE_LINUX_KD
|
||||
#include <linux/kd.h>
|
||||
#endif
|
||||
#include <time.h>
|
||||
#ifdef HAVE_SYS_IO
|
||||
#include <sys/io.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define PCSPKR_DIVIDER 4
|
||||
#define CHIP_DIVIDER 1
|
||||
|
|
@ -80,6 +86,7 @@ void DivPlatformPCSpeaker::pcSpeakerThread() {
|
|||
}
|
||||
if (beepFD>=0) {
|
||||
switch (realOutMethod) {
|
||||
#ifdef HAVE_LINUX_INPUT
|
||||
case 0: { // evdev
|
||||
static struct input_event ie;
|
||||
ie.time.tv_sec=r.tv_sec;
|
||||
|
|
@ -98,11 +105,14 @@ void DivPlatformPCSpeaker::pcSpeakerThread() {
|
|||
}
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_LINUX_KD
|
||||
case 1: // KIOCSOUND (on tty)
|
||||
if (ioctl(beepFD,KIOCSOUND,r.val)<0) {
|
||||
logW("ioctl error! %s",strerror(errno));
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case 2: { // /dev/port
|
||||
unsigned char bOut;
|
||||
bOut=0;
|
||||
|
|
@ -144,11 +154,14 @@ void DivPlatformPCSpeaker::pcSpeakerThread() {
|
|||
}
|
||||
break;
|
||||
}
|
||||
#ifdef HAVE_LINUX_KD
|
||||
case 3: // KIOCSOUND (on stdout)
|
||||
if (ioctl(beepFD,KIOCSOUND,r.val)<0) {
|
||||
logW("ioctl error! %s",strerror(errno));
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#ifdef HAVE_SYS_IO
|
||||
case 4: // outb()
|
||||
if (r.val==0) {
|
||||
outb(inb(0x61)&(~3),0x61);
|
||||
|
|
@ -163,6 +176,7 @@ void DivPlatformPCSpeaker::pcSpeakerThread() {
|
|||
}
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
//logV("not writing because fd is less than 0");
|
||||
|
|
@ -544,6 +558,7 @@ void DivPlatformPCSpeaker::reset() {
|
|||
break;
|
||||
case 4: // outb()
|
||||
beepFD=-1;
|
||||
#ifdef HAVE_SYS_IO
|
||||
if (ioperm(0x61,8,1)<0) {
|
||||
logW("ioperm 0x61: %s",strerror(errno));
|
||||
break;
|
||||
|
|
@ -557,6 +572,9 @@ void DivPlatformPCSpeaker::reset() {
|
|||
break;
|
||||
}
|
||||
beepFD=STDOUT_FILENO;
|
||||
#else
|
||||
errno=ENOSYS;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
if (beepFD<0) {
|
||||
|
|
|
|||
|
|
@ -48,12 +48,15 @@ const char* DivPlatformSMS::getEffectName(unsigned char effect) {
|
|||
}
|
||||
|
||||
void DivPlatformSMS::acquire_nuked(short* bufL, short* bufR, size_t start, size_t len) {
|
||||
int o=0;
|
||||
int oL=0;
|
||||
int oR=0;
|
||||
for (size_t h=start; h<start+len; h++) {
|
||||
if (!writes.empty()) {
|
||||
QueuedWrite w=writes.front();
|
||||
if (w.addr==0) {
|
||||
YMPSG_Write(&sn_nuked,w.val);
|
||||
} else if (w.addr==1) {
|
||||
YMPSG_WriteStereo(&sn_nuked,w.val);
|
||||
}
|
||||
writes.pop();
|
||||
}
|
||||
|
|
@ -73,10 +76,13 @@ void DivPlatformSMS::acquire_nuked(short* bufL, short* bufR, size_t start, size_
|
|||
YMPSG_Clock(&sn_nuked);
|
||||
YMPSG_Clock(&sn_nuked);
|
||||
YMPSG_Clock(&sn_nuked);
|
||||
o=YMPSG_GetOutput(&sn_nuked);
|
||||
if (o<-32768) o=-32768;
|
||||
if (o>32767) o=32767;
|
||||
bufL[h]=bufR[h]=o;
|
||||
YMPSG_GetOutput(&sn_nuked,&oL,&oR);
|
||||
if (oL<-32768) oL=-32768;
|
||||
if (oL>32767) oL=32767;
|
||||
if (oR<-32768) oR=-32768;
|
||||
if (oR>32767) oR=32767;
|
||||
bufL[h]=oL;
|
||||
bufR[h]=oR;
|
||||
for (int i=0; i<4; i++) {
|
||||
if (isMuted[i]) {
|
||||
oscBuf[i]->data[oscBuf[i]->needle++]=0;
|
||||
|
|
|
|||
|
|
@ -60,6 +60,13 @@ SID::~SID()
|
|||
delete[] fir;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Get DC offset of channel.
|
||||
// ----------------------------------------------------------------------------
|
||||
sound_sample SID::get_dc(int ch) {
|
||||
return voice[ch].getDC();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Mute/unmute channel.
|
||||
// ----------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ public:
|
|||
|
||||
sound_sample last_chan_out[3];
|
||||
|
||||
sound_sample get_dc(int ch);
|
||||
void set_is_muted(int ch, bool val);
|
||||
void set_chip_model(chip_model model);
|
||||
void enable_filter(bool enable);
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ public:
|
|||
// Amplitude modulated waveform output.
|
||||
// Range [-2048*255, 2047*255].
|
||||
RESID_INLINE sound_sample output();
|
||||
RESID_INLINE sound_sample getDC();
|
||||
|
||||
protected:
|
||||
WaveformGenerator wave;
|
||||
|
|
@ -72,6 +73,12 @@ sound_sample Voice::output()
|
|||
return (wave.output() - wave_zero)*envelope.output() + voice_DC;
|
||||
}
|
||||
|
||||
RESID_INLINE
|
||||
sound_sample Voice::getDC()
|
||||
{
|
||||
return voice_DC;
|
||||
}
|
||||
|
||||
#endif // RESID_INLINING || defined(__VOICE_CC__)
|
||||
|
||||
#endif // not __VOICE_H__
|
||||
|
|
|
|||
|
|
@ -20,8 +20,8 @@ void
|
|||
psg_reset(struct VERA_PSG* psg)
|
||||
{
|
||||
memset(psg->channels, 0, sizeof(psg->channels));
|
||||
psg->noiseState=1;
|
||||
psg->noiseOut=0;
|
||||
psg->noiseOut = 0;
|
||||
psg->noiseState = 1;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -54,10 +54,14 @@ render(struct VERA_PSG* psg, int16_t *left, int16_t *right)
|
|||
{
|
||||
int l = 0;
|
||||
int r = 0;
|
||||
psg->noiseOut=((psg->noiseOut<<1)|(psg->noiseState&1))&63;
|
||||
psg->noiseState=(psg->noiseState<<1)|(((psg->noiseState>>1)^(psg->noiseState>>2)^(psg->noiseState>>4)^(psg->noiseState>>15))&1);
|
||||
|
||||
for (int i = 0; i < 16; i++) {
|
||||
// In FPGA implementation, noise values are generated every system clock and
|
||||
// the channel update is run sequentially. So, even if both two channels are
|
||||
// fetching a noise value in the same sample, they should have different values
|
||||
psg->noiseOut = ((psg->noiseOut << 1) | (psg->noiseState & 1)) & 63;
|
||||
psg->noiseState = (psg->noiseState << 1) | (((psg->noiseState >> 1) ^ (psg->noiseState >> 2) ^ (psg->noiseState >> 4) ^ (psg->noiseState >> 15)) & 1);
|
||||
|
||||
struct VERAChannel *ch = &psg->channels[i];
|
||||
|
||||
unsigned new_phase = (ch->phase + ch->freq) & 0x1FFFF;
|
||||
|
|
@ -87,11 +91,11 @@ render(struct VERA_PSG* psg, int16_t *left, int16_t *right)
|
|||
r += val;
|
||||
}
|
||||
|
||||
if (ch->left || ch->right) {
|
||||
ch->lastOut=val;
|
||||
} else {
|
||||
ch->lastOut=0;
|
||||
}
|
||||
if (ch->left || ch->right) {
|
||||
ch->lastOut = val;
|
||||
} else {
|
||||
ch->lastOut = 0;
|
||||
}
|
||||
}
|
||||
|
||||
*left = l;
|
||||
|
|
@ -104,6 +108,6 @@ psg_render(struct VERA_PSG* psg, int16_t *bufL, int16_t *bufR, unsigned num_samp
|
|||
while (num_samples--) {
|
||||
render(psg, bufL, bufR);
|
||||
bufL++;
|
||||
bufR++;
|
||||
bufR++;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -74,10 +74,10 @@ const char* DivPlatformSoundUnit::getEffectName(unsigned char effect) {
|
|||
return "1Dxx: Set cutoff sweep boundary";
|
||||
break;
|
||||
case 0x1e:
|
||||
return "17xx: Set phase reset period low byte";
|
||||
return "1Exx: Set phase reset period low byte";
|
||||
break;
|
||||
case 0x1f:
|
||||
return "18xx: Set phase reset period high byte";
|
||||
return "1Fxx: Set phase reset period high byte";
|
||||
break;
|
||||
case 0x20:
|
||||
return "20xx: Toggle frequency sweep (bit 0-6: speed; bit 7: direction is up)";
|
||||
|
|
|
|||
|
|
@ -659,6 +659,13 @@ int DivPlatformYM2203::dispatch(DivCommand c) {
|
|||
chan[c.chan].freqChanged=true;
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_EXTCH: {
|
||||
if (extSys) {
|
||||
extMode=c.value;
|
||||
immWrite(0x27,extMode?0x40:0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_FB: {
|
||||
if (c.chan>2) break;
|
||||
chan[c.chan].state.fb=c.value&7;
|
||||
|
|
|
|||
|
|
@ -34,6 +34,10 @@ int DivPlatformYM2203Ext::dispatch(DivCommand c) {
|
|||
}
|
||||
int ch=c.chan-2;
|
||||
int ordch=orderedOps[ch];
|
||||
if (!extMode) {
|
||||
c.chan=2;
|
||||
return DivPlatformYM2203::dispatch(c);
|
||||
}
|
||||
switch (c.cmd) {
|
||||
case DIV_CMD_NOTE_ON: {
|
||||
DivInstrument* ins=parent->getIns(opChan[ch].ins,DIV_INS_FM);
|
||||
|
|
@ -151,6 +155,11 @@ int DivPlatformYM2203Ext::dispatch(DivCommand c) {
|
|||
opChan[ch].freqChanged=true;
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_EXTCH: {
|
||||
extMode=c.value;
|
||||
immWrite(0x27,extMode?0x40:0);
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_LFO: {
|
||||
rWrite(0x22,(c.value&7)|((c.value>>4)<<3));
|
||||
break;
|
||||
|
|
@ -514,6 +523,7 @@ int DivPlatformYM2203Ext::init(DivEngine* parent, int channels, int sugRate, uns
|
|||
for (int i=0; i<4; i++) {
|
||||
isOpMuted[i]=false;
|
||||
}
|
||||
extSys=true;
|
||||
|
||||
reset();
|
||||
return 9;
|
||||
|
|
|
|||
|
|
@ -988,6 +988,13 @@ int DivPlatformYM2608::dispatch(DivCommand c) {
|
|||
chan[c.chan].freqChanged=true;
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_EXTCH: {
|
||||
if (extSys) {
|
||||
extMode=c.value;
|
||||
immWrite(0x27,extMode?0x40:0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_LFO: {
|
||||
rWrite(0x22,(c.value&7)|((c.value>>4)<<3));
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -34,6 +34,10 @@ int DivPlatformYM2608Ext::dispatch(DivCommand c) {
|
|||
}
|
||||
int ch=c.chan-2;
|
||||
int ordch=orderedOps[ch];
|
||||
if (!extMode) {
|
||||
c.chan=2;
|
||||
return DivPlatformYM2608::dispatch(c);
|
||||
}
|
||||
switch (c.cmd) {
|
||||
case DIV_CMD_NOTE_ON: {
|
||||
DivInstrument* ins=parent->getIns(opChan[ch].ins,DIV_INS_FM);
|
||||
|
|
@ -151,6 +155,11 @@ int DivPlatformYM2608Ext::dispatch(DivCommand c) {
|
|||
opChan[ch].freqChanged=true;
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_EXTCH: {
|
||||
extMode=c.value;
|
||||
immWrite(0x27,extMode?0x40:0);
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_LFO: {
|
||||
rWrite(0x22,(c.value&7)|((c.value>>4)<<3));
|
||||
break;
|
||||
|
|
@ -528,6 +537,7 @@ int DivPlatformYM2608Ext::init(DivEngine* parent, int channels, int sugRate, uns
|
|||
for (int i=0; i<4; i++) {
|
||||
isOpMuted[i]=false;
|
||||
}
|
||||
extSys=true;
|
||||
|
||||
reset();
|
||||
return 19;
|
||||
|
|
|
|||
|
|
@ -1032,6 +1032,13 @@ int DivPlatformYM2610::dispatch(DivCommand c) {
|
|||
chan[c.chan].freqChanged=true;
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_EXTCH: {
|
||||
if (extSys) {
|
||||
extMode=c.value;
|
||||
immWrite(0x27,extMode?0x40:0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_LFO: {
|
||||
rWrite(0x22,(c.value&7)|((c.value>>4)<<3));
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -1014,6 +1014,13 @@ int DivPlatformYM2610B::dispatch(DivCommand c) {
|
|||
chan[c.chan].freqChanged=true;
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_EXTCH: {
|
||||
if (extSys) {
|
||||
extMode=c.value;
|
||||
immWrite(0x27,extMode?0x40:0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_LFO: {
|
||||
rWrite(0x22,(c.value&7)|((c.value>>4)<<3));
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -34,6 +34,10 @@ int DivPlatformYM2610BExt::dispatch(DivCommand c) {
|
|||
}
|
||||
int ch=c.chan-2;
|
||||
int ordch=orderedOps[ch];
|
||||
if (!extMode) {
|
||||
c.chan=2;
|
||||
return DivPlatformYM2610B::dispatch(c);
|
||||
}
|
||||
switch (c.cmd) {
|
||||
case DIV_CMD_NOTE_ON: {
|
||||
DivInstrument* ins=parent->getIns(opChan[ch].ins,DIV_INS_FM);
|
||||
|
|
@ -151,6 +155,11 @@ int DivPlatformYM2610BExt::dispatch(DivCommand c) {
|
|||
opChan[ch].freqChanged=true;
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_EXTCH: {
|
||||
extMode=c.value;
|
||||
immWrite(0x27,extMode?0x40:0);
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_LFO: {
|
||||
rWrite(0x22,(c.value&7)|((c.value>>4)<<3));
|
||||
break;
|
||||
|
|
@ -427,7 +436,7 @@ void DivPlatformYM2610BExt::forceIns() {
|
|||
for (int j=0; j<4; j++) {
|
||||
unsigned short baseAddr=chanOffs[i]|opOffs[j];
|
||||
DivInstrumentFM::Operator& op=chan[i].state.op[j];
|
||||
if (i==2) { // extended channel
|
||||
if (i==2 && extMode) { // extended channel
|
||||
if (isOpMuted[j]) {
|
||||
rWrite(baseAddr+0x40,127);
|
||||
} else if (isOutput[chan[i].state.alg][j]) {
|
||||
|
|
@ -528,6 +537,7 @@ int DivPlatformYM2610BExt::init(DivEngine* parent, int channels, int sugRate, un
|
|||
for (int i=0; i<4; i++) {
|
||||
isOpMuted[i]=false;
|
||||
}
|
||||
extSys=true;
|
||||
|
||||
reset();
|
||||
return 19;
|
||||
|
|
|
|||
|
|
@ -34,6 +34,10 @@ int DivPlatformYM2610Ext::dispatch(DivCommand c) {
|
|||
}
|
||||
int ch=c.chan-1;
|
||||
int ordch=orderedOps[ch];
|
||||
if (!extMode) {
|
||||
c.chan=2;
|
||||
return DivPlatformYM2610::dispatch(c);
|
||||
}
|
||||
switch (c.cmd) {
|
||||
case DIV_CMD_NOTE_ON: {
|
||||
DivInstrument* ins=parent->getIns(opChan[ch].ins,DIV_INS_FM);
|
||||
|
|
@ -151,6 +155,11 @@ int DivPlatformYM2610Ext::dispatch(DivCommand c) {
|
|||
opChan[ch].freqChanged=true;
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_EXTCH: {
|
||||
extMode=c.value;
|
||||
immWrite(0x27,extMode?0x40:0);
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_LFO: {
|
||||
rWrite(0x22,(c.value&7)|((c.value>>4)<<3));
|
||||
break;
|
||||
|
|
@ -427,7 +436,7 @@ void DivPlatformYM2610Ext::forceIns() {
|
|||
for (int j=0; j<4; j++) {
|
||||
unsigned short baseAddr=chanOffs[i]|opOffs[j];
|
||||
DivInstrumentFM::Operator& op=chan[i].state.op[j];
|
||||
if (i==1) { // extended channel
|
||||
if (i==1 && extMode) { // extended channel
|
||||
if (isOpMuted[j]) {
|
||||
rWrite(baseAddr+0x40,127);
|
||||
} else if (isOutput[chan[i].state.alg][j]) {
|
||||
|
|
@ -528,6 +537,7 @@ int DivPlatformYM2610Ext::init(DivEngine* parent, int channels, int sugRate, uns
|
|||
for (int i=0; i<4; i++) {
|
||||
isOpMuted[i]=false;
|
||||
}
|
||||
extSys=true;
|
||||
|
||||
reset();
|
||||
return 17;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue