Merge branch 'master' of https://github.com/tildearrow/furnace into es5506_alt
This commit is contained in:
commit
96c0bea63b
60 changed files with 19453 additions and 190 deletions
|
|
@ -21,6 +21,7 @@
|
|||
#define _FMSHARED_OPN_H
|
||||
|
||||
#include "fmsharedbase.h"
|
||||
#include "../../../extern/opn/ym3438.h"
|
||||
|
||||
#define PLEASE_HELP_ME(_targetChan) \
|
||||
int boundaryBottom=parent->calcBaseFreq(chipClock,CHIP_FREQBASE,0,false); \
|
||||
|
|
@ -146,26 +147,37 @@ class DivPlatformOPN: public DivPlatformFMBase {
|
|||
pan(3) {}
|
||||
};
|
||||
|
||||
const int extChanOffs, psgChanOffs, adpcmAChanOffs, adpcmBChanOffs, chanNum;
|
||||
|
||||
double fmFreqBase;
|
||||
unsigned int fmDivBase;
|
||||
unsigned int ayDiv;
|
||||
unsigned char csmChan;
|
||||
unsigned char lfoValue;
|
||||
bool extSys;
|
||||
bool extSys, useCombo;
|
||||
|
||||
DivConfig ayFlags;
|
||||
|
||||
friend void putDispatchChip(void*,int);
|
||||
friend void putDispatchChan(void*,int,int);
|
||||
DivPlatformOPN(double f=9440540.0, unsigned int d=72, unsigned int a=32, bool isExtSys=false, unsigned char cc=255):
|
||||
DivPlatformOPN(int ext, int psg, int adpcmA, int adpcmB, int chanCount, double f=9440540.0, unsigned int d=72, unsigned int a=32, bool isExtSys=false, unsigned char cc=255):
|
||||
DivPlatformFMBase(),
|
||||
extChanOffs(ext),
|
||||
psgChanOffs(psg),
|
||||
adpcmAChanOffs(adpcmA),
|
||||
adpcmBChanOffs(adpcmB),
|
||||
chanNum(chanCount),
|
||||
fmFreqBase(f),
|
||||
fmDivBase(d),
|
||||
ayDiv(a),
|
||||
csmChan(cc),
|
||||
lfoValue(0),
|
||||
extSys(isExtSys) {}
|
||||
|
||||
extSys(isExtSys),
|
||||
useCombo(false) {}
|
||||
public:
|
||||
void setCombo(bool combo) {
|
||||
useCombo=combo;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1155,7 +1155,7 @@ void DivPlatformGenesis::reset() {
|
|||
fm_ymfm->reset();
|
||||
}
|
||||
OPN2_Reset(&fm);
|
||||
OPN2_SetChipType(ladder?ym3438_mode_ym2612:0);
|
||||
OPN2_SetChipType(&fm,ladder?ym3438_mode_ym2612:0);
|
||||
if (dumpWrites) {
|
||||
addWrite(0xffffffff,0);
|
||||
}
|
||||
|
|
@ -1253,7 +1253,7 @@ void DivPlatformGenesis::setFlags(const DivConfig& flags) {
|
|||
}
|
||||
ladder=flags.getBool("ladderEffect",false);
|
||||
noExtMacros=flags.getBool("noExtMacros",false);
|
||||
OPN2_SetChipType(ladder?ym3438_mode_ym2612:0);
|
||||
OPN2_SetChipType(&fm,ladder?ym3438_mode_ym2612:0);
|
||||
CHECK_CUSTOM_CLOCK;
|
||||
if (useYMFM) {
|
||||
if (fm_ymfm!=NULL) delete fm_ymfm;
|
||||
|
|
|
|||
|
|
@ -21,7 +21,6 @@
|
|||
#define _GENESIS_H
|
||||
|
||||
#include "fmshared_OPN.h"
|
||||
#include "../../../extern/Nuked-OPN2/ym3438.h"
|
||||
#include "sound/ymfm/ymfm_opn.h"
|
||||
|
||||
|
||||
|
|
@ -131,7 +130,7 @@ class DivPlatformGenesis: public DivPlatformOPN {
|
|||
int init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags);
|
||||
void quit();
|
||||
DivPlatformGenesis():
|
||||
DivPlatformOPN(9440540.0, 72, 32, false, 7) {}
|
||||
DivPlatformOPN(2, 6, 6, 6, 6, 9440540.0, 72, 32, false, 7) {}
|
||||
~DivPlatformGenesis();
|
||||
};
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -248,6 +248,7 @@ void DivPlatformOPLL::tick(bool sysTick) {
|
|||
if (chan[i].freq<0) chan[i].freq=0;
|
||||
if (chan[i].freq>65535) chan[i].freq=65535;
|
||||
int freqt=toFreq(chan[i].freq);
|
||||
if (freqt>2047) freqt=2047;
|
||||
chan[i].freqL=freqt&0xff;
|
||||
if (i>=6 && properDrums && (i<9 || !noTopHatFreq)) {
|
||||
immWrite(0x10+drumSlot[i],freqt&0xff);
|
||||
|
|
@ -257,7 +258,7 @@ void DivPlatformOPLL::tick(bool sysTick) {
|
|||
immWrite(0x10+i,freqt&0xff);
|
||||
}
|
||||
}
|
||||
chan[i].freqH=freqt>>8;
|
||||
chan[i].freqH=(freqt>>8)&15;
|
||||
}
|
||||
if (chan[i].keyOn && i>=6 && properDrums) {
|
||||
if (!isMuted[i]) {
|
||||
|
|
|
|||
|
|
@ -455,6 +455,7 @@ void DivPlatformPOKEY::setFlags(const DivConfig& flags) {
|
|||
oscBuf[i]->rate=rate/2;
|
||||
}
|
||||
altASAP.init(chipClock,rate);
|
||||
altASAP.reset();
|
||||
} else {
|
||||
rate=chipClock;
|
||||
for (int i=0; i<4; i++) {
|
||||
|
|
|
|||
|
|
@ -607,10 +607,23 @@ void DivPlatformSNES::writeEnv(int ch) {
|
|||
if (chan[ch].state.sus) {
|
||||
if (chan[ch].active) {
|
||||
chWrite(ch,5,chan[ch].state.a|(chan[ch].state.d<<4)|0x80);
|
||||
chWrite(ch,6,chan[ch].state.s<<5);
|
||||
} else { // dec linear
|
||||
chWrite(ch,7,0x80|chan[ch].state.r);
|
||||
chWrite(ch,5,0);
|
||||
chWrite(ch,6,(chan[ch].state.s<<5)|(chan[ch].state.d2&31));
|
||||
} else {
|
||||
switch (chan[ch].state.sus) {
|
||||
case 1: // dec linear
|
||||
chWrite(ch,7,0x80|chan[ch].state.r);
|
||||
chWrite(ch,5,0);
|
||||
break;
|
||||
case 2: // dec exp
|
||||
chWrite(ch,7,0xa0|chan[ch].state.r);
|
||||
chWrite(ch,5,0);
|
||||
break;
|
||||
case 3: // update r
|
||||
chWrite(ch,6,(chan[ch].state.s<<5)|(chan[ch].state.r&31));
|
||||
break;
|
||||
default: // what?
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
chWrite(ch,5,chan[ch].state.a|(chan[ch].state.d<<4)|0x80);
|
||||
|
|
|
|||
|
|
@ -157,6 +157,80 @@ const char** DivPlatformYM2203::getRegisterSheet() {
|
|||
}
|
||||
|
||||
void DivPlatformYM2203::acquire(short* bufL, short* bufR, size_t start, size_t len) {
|
||||
if (useCombo) {
|
||||
acquire_combo(bufL,bufR,start,len);
|
||||
} else {
|
||||
acquire_ymfm(bufL,bufR,start,len);
|
||||
}
|
||||
}
|
||||
|
||||
void DivPlatformYM2203::acquire_combo(short* bufL, short* bufR, size_t start, size_t len) {
|
||||
static int os;
|
||||
static short ignored[2];
|
||||
|
||||
for (size_t h=start; h<start+len; h++) {
|
||||
os=0;
|
||||
// Nuked part
|
||||
for (unsigned int i=0; i<nukedMult; i++) {
|
||||
if (!writes.empty()) {
|
||||
if (--delay<1 && !(fm->read(0)&0x80)) {
|
||||
QueuedWrite& w=writes.front();
|
||||
|
||||
if (w.addr<=0x1c || w.addr==0x2d || w.addr==0x2e || w.addr==0x2f) {
|
||||
// ymfm write
|
||||
fm->write(0x0,w.addr);
|
||||
fm->write(0x1,w.val);
|
||||
|
||||
regPool[w.addr&0xff]=w.val;
|
||||
writes.pop_front();
|
||||
delay=1;
|
||||
} else {
|
||||
// Nuked write
|
||||
if (w.addrOrVal) {
|
||||
OPN2_Write(&fm_nuked,0x1,w.val);
|
||||
regPool[w.addr&0xff]=w.val;
|
||||
writes.pop_front();
|
||||
} else {
|
||||
lastBusy++;
|
||||
if (fm_nuked.write_busy==0) {
|
||||
OPN2_Write(&fm_nuked,0x0,w.addr);
|
||||
w.addrOrVal=true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
OPN2_Clock(&fm_nuked,ignored);
|
||||
}
|
||||
os=(
|
||||
(fm_nuked.ch_out[0])+
|
||||
(fm_nuked.ch_out[1])+
|
||||
(fm_nuked.ch_out[2])
|
||||
);
|
||||
|
||||
os&=~3;
|
||||
|
||||
// ymfm part
|
||||
fm->generate(&fmout);
|
||||
|
||||
os+=((fmout.data[1]+fmout.data[2]+fmout.data[3])>>1);
|
||||
if (os<-32768) os=-32768;
|
||||
if (os>32767) os=32767;
|
||||
|
||||
bufL[h]=os;
|
||||
|
||||
for (int i=0; i<3; i++) {
|
||||
oscBuf[i]->data[oscBuf[i]->needle++]=fm_nuked.ch_out[i];
|
||||
}
|
||||
|
||||
for (int i=3; i<6; i++) {
|
||||
oscBuf[i]->data[oscBuf[i]->needle++]=fmout.data[i-2];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DivPlatformYM2203::acquire_ymfm(short* bufL, short* bufR, size_t start, size_t len) {
|
||||
static int os;
|
||||
|
||||
ymfm::ym2203::fm_engine* fme=fm->debug_fm_engine();
|
||||
|
|
@ -857,6 +931,8 @@ void DivPlatformYM2203::reset() {
|
|||
if (dumpWrites) {
|
||||
addWrite(0xffffffff,0);
|
||||
}
|
||||
OPN2_Reset(&fm_nuked);
|
||||
OPN2_SetChipType(&fm_nuked,ym3438_mode_opn);
|
||||
fm->reset();
|
||||
for (int i=0; i<6; i++) {
|
||||
chan[i]=DivPlatformOPN::OPNChannel();
|
||||
|
|
@ -946,18 +1022,21 @@ void DivPlatformYM2203::setFlags(const DivConfig& flags) {
|
|||
fmFreqBase=4720270.0/2.0,
|
||||
fmDivBase=18,
|
||||
ayDiv=8;
|
||||
nukedMult=16;
|
||||
break;
|
||||
case 0x02: // /2
|
||||
prescale=0x2f;
|
||||
fmFreqBase=4720270.0/3.0,
|
||||
fmDivBase=12,
|
||||
ayDiv=4;
|
||||
nukedMult=24;
|
||||
break;
|
||||
default: // /6
|
||||
prescale=0x2d;
|
||||
fmFreqBase=4720270.0,
|
||||
fmDivBase=36,
|
||||
ayDiv=16;
|
||||
nukedMult=8;
|
||||
break;
|
||||
}
|
||||
CHECK_CUSTOM_CLOCK;
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ class DivPlatformYM2203: public DivPlatformOPN {
|
|||
OPNChannel chan[6];
|
||||
DivDispatchOscBuffer* oscBuf[6];
|
||||
bool isMuted[6];
|
||||
ym3438_t fm_nuked;
|
||||
ymfm::ym2203* fm;
|
||||
ymfm::ym2203::output_data fmout;
|
||||
DivYM2203Interface iface;
|
||||
|
|
@ -50,9 +51,13 @@ class DivPlatformYM2203: public DivPlatformOPN {
|
|||
unsigned char sampleBank;
|
||||
|
||||
bool extMode, noExtMacros;
|
||||
unsigned char prescale;
|
||||
unsigned char prescale, nukedMult;
|
||||
|
||||
friend void putDispatchChip(void*,int);
|
||||
|
||||
void acquire_combo(short* bufL, short* bufR, size_t start, size_t len);
|
||||
void acquire_ymfm(short* bufL, short* bufR, size_t start, size_t len);
|
||||
|
||||
public:
|
||||
void acquire(short* bufL, short* bufR, size_t start, size_t len);
|
||||
int dispatch(DivCommand c);
|
||||
|
|
@ -77,7 +82,7 @@ class DivPlatformYM2203: public DivPlatformOPN {
|
|||
int init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags);
|
||||
void quit();
|
||||
DivPlatformYM2203():
|
||||
DivPlatformOPN(4720270.0, 36, 16),
|
||||
DivPlatformOPN(2, 3, 6, 6, 6, 4720270.0, 36, 16),
|
||||
prescale(0x2d) {}
|
||||
~DivPlatformYM2203();
|
||||
};
|
||||
|
|
|
|||
|
|
@ -298,6 +298,116 @@ double DivPlatformYM2608::NOTE_ADPCMB(int note) {
|
|||
}
|
||||
|
||||
void DivPlatformYM2608::acquire(short* bufL, short* bufR, size_t start, size_t len) {
|
||||
if (useCombo) {
|
||||
acquire_combo(bufL,bufR,start,len);
|
||||
} else {
|
||||
acquire_ymfm(bufL,bufR,start,len);
|
||||
}
|
||||
}
|
||||
|
||||
void DivPlatformYM2608::acquire_combo(short* bufL, short* bufR, size_t start, size_t len) {
|
||||
static int os[2];
|
||||
static short ignored[2];
|
||||
|
||||
ymfm::ssg_engine* ssge=fm->debug_ssg_engine();
|
||||
ymfm::adpcm_a_engine* aae=fm->debug_adpcm_a_engine();
|
||||
ymfm::adpcm_b_engine* abe=fm->debug_adpcm_b_engine();
|
||||
|
||||
ymfm::ssg_engine::output_data ssgOut;
|
||||
|
||||
ymfm::adpcm_a_channel* adpcmAChan[6];
|
||||
for (int i=0; i<6; i++) {
|
||||
adpcmAChan[i]=aae->debug_channel(i);
|
||||
}
|
||||
|
||||
for (size_t h=start; h<start+len; h++) {
|
||||
os[0]=0; os[1]=0;
|
||||
// Nuked part
|
||||
for (int i=0; i<nukedMult; i++) {
|
||||
if (!writes.empty()) {
|
||||
if (--delay<1 && !(fm->read(0)&0x80)) {
|
||||
QueuedWrite& w=writes.front();
|
||||
|
||||
if (w.addr<=0x1c || w.addr==0x2d || w.addr==0x2e || w.addr==0x2f || (w.addr>=0x100 && w.addr<=0x12d)) {
|
||||
// ymfm write
|
||||
fm->write(0x0+((w.addr>>8)<<1),w.addr);
|
||||
fm->write(0x1+((w.addr>>8)<<1),w.val);
|
||||
|
||||
regPool[w.addr&0x1ff]=w.val;
|
||||
writes.pop_front();
|
||||
delay=1;
|
||||
} else {
|
||||
// Nuked write
|
||||
if (w.addrOrVal) {
|
||||
OPN2_Write(&fm_nuked,0x1+((w.addr>>8)<<1),w.val);
|
||||
regPool[w.addr&0x1ff]=w.val;
|
||||
writes.pop_front();
|
||||
} else {
|
||||
lastBusy++;
|
||||
if (fm_nuked.write_busy==0) {
|
||||
OPN2_Write(&fm_nuked,0x0+((w.addr>>8)<<1),w.addr);
|
||||
w.addrOrVal=true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
OPN2_Clock(&fm_nuked,ignored);
|
||||
}
|
||||
os[0]=(
|
||||
(fm_nuked.pan_l[0]?fm_nuked.ch_out[0]:0)+
|
||||
(fm_nuked.pan_l[1]?fm_nuked.ch_out[1]:0)+
|
||||
(fm_nuked.pan_l[2]?fm_nuked.ch_out[2]:0)+
|
||||
(fm_nuked.pan_l[3]?fm_nuked.ch_out[3]:0)+
|
||||
(fm_nuked.pan_l[4]?fm_nuked.ch_out[4]:0)+
|
||||
(fm_nuked.pan_l[5]?fm_nuked.ch_out[5]:0)
|
||||
);
|
||||
os[1]=(
|
||||
(fm_nuked.pan_r[0]?fm_nuked.ch_out[0]:0)+
|
||||
(fm_nuked.pan_r[1]?fm_nuked.ch_out[1]:0)+
|
||||
(fm_nuked.pan_r[2]?fm_nuked.ch_out[2]:0)+
|
||||
(fm_nuked.pan_r[3]?fm_nuked.ch_out[3]:0)+
|
||||
(fm_nuked.pan_r[4]?fm_nuked.ch_out[4]:0)+
|
||||
(fm_nuked.pan_r[5]?fm_nuked.ch_out[5]:0)
|
||||
);
|
||||
|
||||
os[0]>>=1;
|
||||
os[1]>>=1;
|
||||
|
||||
// ymfm part
|
||||
fm->generate(&fmout);
|
||||
|
||||
os[0]+=fmout.data[0]+(fmout.data[2]>>1);
|
||||
if (os[0]<-32768) os[0]=-32768;
|
||||
if (os[0]>32767) os[0]=32767;
|
||||
|
||||
os[1]+=fmout.data[1]+(fmout.data[2]>>1);
|
||||
if (os[1]<-32768) os[1]=-32768;
|
||||
if (os[1]>32767) os[1]=32767;
|
||||
|
||||
bufL[h]=os[0];
|
||||
bufR[h]=os[1];
|
||||
|
||||
|
||||
for (int i=0; i<psgChanOffs; i++) {
|
||||
oscBuf[i]->data[oscBuf[i]->needle++]=fm_nuked.ch_out[i];
|
||||
}
|
||||
|
||||
ssge->get_last_out(ssgOut);
|
||||
for (int i=psgChanOffs; i<adpcmAChanOffs; i++) {
|
||||
oscBuf[i]->data[oscBuf[i]->needle++]=ssgOut.data[i-psgChanOffs];
|
||||
}
|
||||
|
||||
for (int i=adpcmAChanOffs; i<adpcmBChanOffs; i++) {
|
||||
oscBuf[i]->data[oscBuf[i]->needle++]=adpcmAChan[i-adpcmAChanOffs]->get_last_out(0)+adpcmAChan[i-adpcmAChanOffs]->get_last_out(1);
|
||||
}
|
||||
|
||||
oscBuf[adpcmBChanOffs]->data[oscBuf[adpcmBChanOffs]->needle++]=abe->get_last_out(0)+abe->get_last_out(1);
|
||||
}
|
||||
}
|
||||
|
||||
void DivPlatformYM2608::acquire_ymfm(short* bufL, short* bufR, size_t start, size_t len) {
|
||||
static int os[2];
|
||||
|
||||
ymfm::ym2608::fm_engine* fme=fm->debug_fm_engine();
|
||||
|
|
@ -1256,6 +1366,8 @@ void DivPlatformYM2608::reset() {
|
|||
if (dumpWrites) {
|
||||
addWrite(0xffffffff,0);
|
||||
}
|
||||
OPN2_Reset(&fm_nuked);
|
||||
OPN2_SetChipType(&fm_nuked,ym3438_mode_opn);
|
||||
fm->reset();
|
||||
for (int i=0; i<16; i++) {
|
||||
chan[i]=DivPlatformOPN::OPNChannelStereo();
|
||||
|
|
@ -1407,18 +1519,21 @@ void DivPlatformYM2608::setFlags(const DivConfig& flags) {
|
|||
fmFreqBase=9440540.0/2.0,
|
||||
fmDivBase=36,
|
||||
ayDiv=16;
|
||||
nukedMult=16;
|
||||
break;
|
||||
case 0x02: // /2
|
||||
prescale=0x2f;
|
||||
fmFreqBase=9440540.0/3.0,
|
||||
fmDivBase=24,
|
||||
ayDiv=8;
|
||||
nukedMult=24;
|
||||
break;
|
||||
default: // /6
|
||||
prescale=0x2d;
|
||||
fmFreqBase=9440540.0,
|
||||
fmDivBase=72,
|
||||
ayDiv=32;
|
||||
nukedMult=8;
|
||||
break;
|
||||
}
|
||||
CHECK_CUSTOM_CLOCK;
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ class DivPlatformYM2608: public DivPlatformOPN {
|
|||
OPNChannelStereo chan[16];
|
||||
DivDispatchOscBuffer* oscBuf[16];
|
||||
bool isMuted[16];
|
||||
ym3438_t fm_nuked;
|
||||
ymfm::ym2608* fm;
|
||||
ymfm::ym2608::output_data fmout;
|
||||
|
||||
|
|
@ -62,12 +63,16 @@ class DivPlatformYM2608: public DivPlatformOPN {
|
|||
int globalRSSVolume;
|
||||
|
||||
bool extMode, noExtMacros;
|
||||
unsigned char prescale;
|
||||
unsigned char prescale, nukedMult;
|
||||
|
||||
double NOTE_OPNB(int ch, int note);
|
||||
double NOTE_ADPCMB(int note);
|
||||
|
||||
friend void putDispatchChip(void*,int);
|
||||
|
||||
void acquire_combo(short* bufL, short* bufR, size_t start, size_t len);
|
||||
void acquire_ymfm(short* bufL, short* bufR, size_t start, size_t len);
|
||||
|
||||
public:
|
||||
void acquire(short* bufL, short* bufR, size_t start, size_t len);
|
||||
int dispatch(DivCommand c);
|
||||
|
|
@ -97,7 +102,7 @@ class DivPlatformYM2608: public DivPlatformOPN {
|
|||
int init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags);
|
||||
void quit();
|
||||
DivPlatformYM2608():
|
||||
DivPlatformOPN(9440540.0, 72, 32),
|
||||
DivPlatformOPN(2, 6, 9, 15, 16, 9440540.0, 72, 32),
|
||||
prescale(0x2d) {}
|
||||
~DivPlatformYM2608();
|
||||
};
|
||||
|
|
|
|||
|
|
@ -233,6 +233,112 @@ const char** DivPlatformYM2610::getRegisterSheet() {
|
|||
}
|
||||
|
||||
void DivPlatformYM2610::acquire(short* bufL, short* bufR, size_t start, size_t len) {
|
||||
if (useCombo) {
|
||||
acquire_combo(bufL,bufR,start,len);
|
||||
} else {
|
||||
acquire_ymfm(bufL,bufR,start,len);
|
||||
}
|
||||
}
|
||||
|
||||
void DivPlatformYM2610::acquire_combo(short* bufL, short* bufR, size_t start, size_t len) {
|
||||
static int os[2];
|
||||
static short ignored[2];
|
||||
|
||||
ymfm::ssg_engine* ssge=fm->debug_ssg_engine();
|
||||
ymfm::adpcm_a_engine* aae=fm->debug_adpcm_a_engine();
|
||||
ymfm::adpcm_b_engine* abe=fm->debug_adpcm_b_engine();
|
||||
|
||||
ymfm::ssg_engine::output_data ssgOut;
|
||||
|
||||
ymfm::adpcm_a_channel* adpcmAChan[6];
|
||||
for (int i=0; i<6; i++) {
|
||||
adpcmAChan[i]=aae->debug_channel(i);
|
||||
}
|
||||
|
||||
for (size_t h=start; h<start+len; h++) {
|
||||
os[0]=0; os[1]=0;
|
||||
// Nuked part
|
||||
for (int i=0; i<24; i++) {
|
||||
if (!writes.empty()) {
|
||||
if (--delay<1 && !(fm->read(0)&0x80)) {
|
||||
QueuedWrite& w=writes.front();
|
||||
|
||||
if (w.addr<=0x1c || (w.addr>=0x100 && w.addr<=0x12d)) {
|
||||
// ymfm write
|
||||
fm->write(0x0+((w.addr>>8)<<1),w.addr);
|
||||
fm->write(0x1+((w.addr>>8)<<1),w.val);
|
||||
|
||||
regPool[w.addr&0x1ff]=w.val;
|
||||
writes.pop_front();
|
||||
delay=32;
|
||||
} else {
|
||||
// Nuked write
|
||||
if (w.addrOrVal) {
|
||||
OPN2_Write(&fm_nuked,0x1+((w.addr>>8)<<1),w.val);
|
||||
regPool[w.addr&0x1ff]=w.val;
|
||||
writes.pop_front();
|
||||
} else {
|
||||
lastBusy++;
|
||||
if (fm_nuked.write_busy==0) {
|
||||
OPN2_Write(&fm_nuked,0x0+((w.addr>>8)<<1),w.addr);
|
||||
w.addrOrVal=true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
OPN2_Clock(&fm_nuked,ignored);
|
||||
}
|
||||
os[0]=(
|
||||
(fm_nuked.pan_l[1]?fm_nuked.ch_out[1]:0)+
|
||||
(fm_nuked.pan_l[2]?fm_nuked.ch_out[2]:0)+
|
||||
(fm_nuked.pan_l[4]?fm_nuked.ch_out[4]:0)+
|
||||
(fm_nuked.pan_l[5]?fm_nuked.ch_out[5]:0)
|
||||
);
|
||||
os[1]=(
|
||||
(fm_nuked.pan_r[1]?fm_nuked.ch_out[1]:0)+
|
||||
(fm_nuked.pan_r[2]?fm_nuked.ch_out[2]:0)+
|
||||
(fm_nuked.pan_r[4]?fm_nuked.ch_out[4]:0)+
|
||||
(fm_nuked.pan_r[5]?fm_nuked.ch_out[5]:0)
|
||||
);
|
||||
|
||||
os[0]>>=1;
|
||||
os[1]>>=1;
|
||||
|
||||
// ymfm part
|
||||
fm->generate(&fmout);
|
||||
|
||||
os[0]+=fmout.data[0]+(fmout.data[2]>>1);
|
||||
if (os[0]<-32768) os[0]=-32768;
|
||||
if (os[0]>32767) os[0]=32767;
|
||||
|
||||
os[1]+=fmout.data[1]+(fmout.data[2]>>1);
|
||||
if (os[1]<-32768) os[1]=-32768;
|
||||
if (os[1]>32767) os[1]=32767;
|
||||
|
||||
bufL[h]=os[0];
|
||||
bufR[h]=os[1];
|
||||
|
||||
|
||||
for (int i=0; i<psgChanOffs; i++) {
|
||||
oscBuf[i]->data[oscBuf[i]->needle++]=fm_nuked.ch_out[bchOffs[i]];
|
||||
}
|
||||
|
||||
ssge->get_last_out(ssgOut);
|
||||
for (int i=psgChanOffs; i<adpcmAChanOffs; i++) {
|
||||
oscBuf[i]->data[oscBuf[i]->needle++]=ssgOut.data[i-psgChanOffs];
|
||||
}
|
||||
|
||||
for (int i=adpcmAChanOffs; i<adpcmBChanOffs; i++) {
|
||||
oscBuf[i]->data[oscBuf[i]->needle++]=adpcmAChan[i-adpcmAChanOffs]->get_last_out(0)+adpcmAChan[i-adpcmAChanOffs]->get_last_out(1);
|
||||
}
|
||||
|
||||
oscBuf[adpcmBChanOffs]->data[oscBuf[adpcmBChanOffs]->needle++]=abe->get_last_out(0)+abe->get_last_out(1);
|
||||
}
|
||||
}
|
||||
|
||||
void DivPlatformYM2610::acquire_ymfm(short* bufL, short* bufR, size_t start, size_t len) {
|
||||
static int os[2];
|
||||
|
||||
ymfm::ym2610::fm_engine* fme=fm->debug_fm_engine();
|
||||
|
|
@ -254,13 +360,13 @@ void DivPlatformYM2610::acquire(short* bufL, short* bufR, size_t start, size_t l
|
|||
for (size_t h=start; h<start+len; h++) {
|
||||
os[0]=0; os[1]=0;
|
||||
if (!writes.empty()) {
|
||||
if (--delay<1) {
|
||||
if (--delay<1 && !(fm->read(0)&0x80)) {
|
||||
QueuedWrite& w=writes.front();
|
||||
fm->write(0x0+((w.addr>>8)<<1),w.addr);
|
||||
fm->write(0x1+((w.addr>>8)<<1),w.val);
|
||||
regPool[w.addr&0x1ff]=w.val;
|
||||
writes.pop_front();
|
||||
delay=4;
|
||||
delay=1;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1275,7 +1381,7 @@ bool DivPlatformYM2610::keyOffAffectsArp(int ch) {
|
|||
}
|
||||
|
||||
void DivPlatformYM2610::notifyInsChange(int ins) {
|
||||
for (int i=0; i<chanNum; i++) {
|
||||
for (int i=0; i<16; i++) {
|
||||
if (chan[i].ins==ins) {
|
||||
chan[i].insChanged=true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@
|
|||
|
||||
#include "ym2610shared.h"
|
||||
|
||||
class DivPlatformYM2610: public DivPlatformYM2610Base<14> {
|
||||
class DivPlatformYM2610: public DivPlatformYM2610Base {
|
||||
protected:
|
||||
const unsigned short chanOffs[4]={
|
||||
0x01, 0x02, 0x101, 0x102
|
||||
|
|
@ -37,6 +37,10 @@ class DivPlatformYM2610: public DivPlatformYM2610Base<14> {
|
|||
};
|
||||
|
||||
friend void putDispatchChip(void*,int);
|
||||
|
||||
void acquire_combo(short* bufL, short* bufR, size_t start, size_t len);
|
||||
void acquire_ymfm(short* bufL, short* bufR, size_t start, size_t len);
|
||||
|
||||
public:
|
||||
void acquire(short* bufL, short* bufR, size_t start, size_t len);
|
||||
int dispatch(DivCommand c);
|
||||
|
|
@ -60,7 +64,7 @@ class DivPlatformYM2610: public DivPlatformYM2610Base<14> {
|
|||
int init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags);
|
||||
void quit();
|
||||
DivPlatformYM2610():
|
||||
DivPlatformYM2610Base<14>(1,4,7,13) {}
|
||||
DivPlatformYM2610Base(1,4,7,13,14) {}
|
||||
~DivPlatformYM2610();
|
||||
};
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -297,6 +297,116 @@ const char** DivPlatformYM2610B::getRegisterSheet() {
|
|||
}
|
||||
|
||||
void DivPlatformYM2610B::acquire(short* bufL, short* bufR, size_t start, size_t len) {
|
||||
if (useCombo) {
|
||||
acquire_combo(bufL,bufR,start,len);
|
||||
} else {
|
||||
acquire_ymfm(bufL,bufR,start,len);
|
||||
}
|
||||
}
|
||||
|
||||
void DivPlatformYM2610B::acquire_combo(short* bufL, short* bufR, size_t start, size_t len) {
|
||||
static int os[2];
|
||||
static short ignored[2];
|
||||
|
||||
ymfm::ssg_engine* ssge=fm->debug_ssg_engine();
|
||||
ymfm::adpcm_a_engine* aae=fm->debug_adpcm_a_engine();
|
||||
ymfm::adpcm_b_engine* abe=fm->debug_adpcm_b_engine();
|
||||
|
||||
ymfm::ssg_engine::output_data ssgOut;
|
||||
|
||||
ymfm::adpcm_a_channel* adpcmAChan[6];
|
||||
for (int i=0; i<6; i++) {
|
||||
adpcmAChan[i]=aae->debug_channel(i);
|
||||
}
|
||||
|
||||
for (size_t h=start; h<start+len; h++) {
|
||||
os[0]=0; os[1]=0;
|
||||
// Nuked part
|
||||
for (int i=0; i<24; i++) {
|
||||
if (!writes.empty()) {
|
||||
if (--delay<1 && !(fm->read(0)&0x80)) {
|
||||
QueuedWrite& w=writes.front();
|
||||
|
||||
if (w.addr<=0x1c || (w.addr>=0x100 && w.addr<=0x12d)) {
|
||||
// ymfm write
|
||||
fm->write(0x0+((w.addr>>8)<<1),w.addr);
|
||||
fm->write(0x1+((w.addr>>8)<<1),w.val);
|
||||
|
||||
regPool[w.addr&0x1ff]=w.val;
|
||||
writes.pop_front();
|
||||
delay=32;
|
||||
} else {
|
||||
// Nuked write
|
||||
if (w.addrOrVal) {
|
||||
OPN2_Write(&fm_nuked,0x1+((w.addr>>8)<<1),w.val);
|
||||
regPool[w.addr&0x1ff]=w.val;
|
||||
writes.pop_front();
|
||||
} else {
|
||||
lastBusy++;
|
||||
if (fm_nuked.write_busy==0) {
|
||||
OPN2_Write(&fm_nuked,0x0+((w.addr>>8)<<1),w.addr);
|
||||
w.addrOrVal=true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
OPN2_Clock(&fm_nuked,ignored);
|
||||
}
|
||||
os[0]=(
|
||||
(fm_nuked.pan_l[0]?fm_nuked.ch_out[0]:0)+
|
||||
(fm_nuked.pan_l[1]?fm_nuked.ch_out[1]:0)+
|
||||
(fm_nuked.pan_l[2]?fm_nuked.ch_out[2]:0)+
|
||||
(fm_nuked.pan_l[3]?fm_nuked.ch_out[3]:0)+
|
||||
(fm_nuked.pan_l[4]?fm_nuked.ch_out[4]:0)+
|
||||
(fm_nuked.pan_l[5]?fm_nuked.ch_out[5]:0)
|
||||
);
|
||||
os[1]=(
|
||||
(fm_nuked.pan_r[0]?fm_nuked.ch_out[0]:0)+
|
||||
(fm_nuked.pan_r[1]?fm_nuked.ch_out[1]:0)+
|
||||
(fm_nuked.pan_r[2]?fm_nuked.ch_out[2]:0)+
|
||||
(fm_nuked.pan_r[3]?fm_nuked.ch_out[3]:0)+
|
||||
(fm_nuked.pan_r[4]?fm_nuked.ch_out[4]:0)+
|
||||
(fm_nuked.pan_r[5]?fm_nuked.ch_out[5]:0)
|
||||
);
|
||||
|
||||
os[0]>>=1;
|
||||
os[1]>>=1;
|
||||
|
||||
// ymfm part
|
||||
fm->generate(&fmout);
|
||||
|
||||
os[0]+=fmout.data[0]+(fmout.data[2]>>1);
|
||||
if (os[0]<-32768) os[0]=-32768;
|
||||
if (os[0]>32767) os[0]=32767;
|
||||
|
||||
os[1]+=fmout.data[1]+(fmout.data[2]>>1);
|
||||
if (os[1]<-32768) os[1]=-32768;
|
||||
if (os[1]>32767) os[1]=32767;
|
||||
|
||||
bufL[h]=os[0];
|
||||
bufR[h]=os[1];
|
||||
|
||||
|
||||
for (int i=0; i<psgChanOffs; i++) {
|
||||
oscBuf[i]->data[oscBuf[i]->needle++]=fm_nuked.ch_out[i];
|
||||
}
|
||||
|
||||
ssge->get_last_out(ssgOut);
|
||||
for (int i=psgChanOffs; i<adpcmAChanOffs; i++) {
|
||||
oscBuf[i]->data[oscBuf[i]->needle++]=ssgOut.data[i-psgChanOffs];
|
||||
}
|
||||
|
||||
for (int i=adpcmAChanOffs; i<adpcmBChanOffs; i++) {
|
||||
oscBuf[i]->data[oscBuf[i]->needle++]=adpcmAChan[i-adpcmAChanOffs]->get_last_out(0)+adpcmAChan[i-adpcmAChanOffs]->get_last_out(1);
|
||||
}
|
||||
|
||||
oscBuf[adpcmBChanOffs]->data[oscBuf[adpcmBChanOffs]->needle++]=abe->get_last_out(0)+abe->get_last_out(1);
|
||||
}
|
||||
}
|
||||
|
||||
void DivPlatformYM2610B::acquire_ymfm(short* bufL, short* bufR, size_t start, size_t len) {
|
||||
static int os[2];
|
||||
|
||||
ymfm::ym2610b::fm_engine* fme=fm->debug_fm_engine();
|
||||
|
|
@ -316,13 +426,13 @@ void DivPlatformYM2610B::acquire(short* bufL, short* bufR, size_t start, size_t
|
|||
for (size_t h=start; h<start+len; h++) {
|
||||
os[0]=0; os[1]=0;
|
||||
if (!writes.empty()) {
|
||||
if (--delay<1) {
|
||||
if (--delay<1 && !(fm->read(0)&0x80)) {
|
||||
QueuedWrite& w=writes.front();
|
||||
fm->write(0x0+((w.addr>>8)<<1),w.addr);
|
||||
fm->write(0x1+((w.addr>>8)<<1),w.val);
|
||||
regPool[w.addr&0x1ff]=w.val;
|
||||
writes.pop_front();
|
||||
delay=4;
|
||||
delay=1;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1342,7 +1452,7 @@ bool DivPlatformYM2610B::keyOffAffectsArp(int ch) {
|
|||
}
|
||||
|
||||
void DivPlatformYM2610B::notifyInsChange(int ins) {
|
||||
for (int i=0; i<chanNum; i++) {
|
||||
for (int i=0; i<16; i++) {
|
||||
if (chan[i].ins==ins) {
|
||||
chan[i].insChanged=true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@
|
|||
|
||||
#include "ym2610shared.h"
|
||||
|
||||
class DivPlatformYM2610B: public DivPlatformYM2610Base<16> {
|
||||
class DivPlatformYM2610B: public DivPlatformYM2610Base {
|
||||
protected:
|
||||
const unsigned short chanOffs[6]={
|
||||
0x00, 0x01, 0x02, 0x100, 0x101, 0x102
|
||||
|
|
@ -33,6 +33,10 @@ class DivPlatformYM2610B: public DivPlatformYM2610Base<16> {
|
|||
};
|
||||
|
||||
friend void putDispatchChip(void*,int);
|
||||
|
||||
void acquire_combo(short* bufL, short* bufR, size_t start, size_t len);
|
||||
void acquire_ymfm(short* bufL, short* bufR, size_t start, size_t len);
|
||||
|
||||
public:
|
||||
void acquire(short* bufL, short* bufR, size_t start, size_t len);
|
||||
int dispatch(DivCommand c);
|
||||
|
|
@ -56,7 +60,7 @@ class DivPlatformYM2610B: public DivPlatformYM2610Base<16> {
|
|||
int init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags);
|
||||
void quit();
|
||||
DivPlatformYM2610B():
|
||||
DivPlatformYM2610Base<16>(2,6,9,15) {}
|
||||
DivPlatformYM2610Base(2,6,9,15,16) {}
|
||||
~DivPlatformYM2610B();
|
||||
};
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -44,12 +44,13 @@ class DivYM2610Interface: public ymfm::ymfm_interface {
|
|||
sampleBank(0) {}
|
||||
};
|
||||
|
||||
template<int ChanNum> class DivPlatformYM2610Base: public DivPlatformOPN {
|
||||
class DivPlatformYM2610Base: public DivPlatformOPN {
|
||||
protected:
|
||||
OPNChannelStereo chan[ChanNum];
|
||||
DivDispatchOscBuffer* oscBuf[ChanNum];
|
||||
bool isMuted[ChanNum];
|
||||
OPNChannelStereo chan[16];
|
||||
DivDispatchOscBuffer* oscBuf[16];
|
||||
bool isMuted[16];
|
||||
|
||||
ym3438_t fm_nuked;
|
||||
ymfm::ym2610b* fm;
|
||||
ymfm::ym2610b::output_data fmout;
|
||||
DivPlatformAY8910* ay;
|
||||
|
|
@ -72,9 +73,6 @@ template<int ChanNum> class DivPlatformYM2610Base: public DivPlatformOPN {
|
|||
unsigned char writeADPCMAOff, writeADPCMAOn;
|
||||
int globalADPCMAVolume;
|
||||
|
||||
const int extChanOffs, psgChanOffs, adpcmAChanOffs, adpcmBChanOffs;
|
||||
const int chanNum=ChanNum;
|
||||
|
||||
double NOTE_OPNB(int ch, int note) {
|
||||
if (ch>=adpcmBChanOffs) { // ADPCM
|
||||
return NOTE_ADPCMB(note);
|
||||
|
|
@ -98,6 +96,9 @@ template<int ChanNum> class DivPlatformYM2610Base: public DivPlatformOPN {
|
|||
writeADPCMAOn=0;
|
||||
globalADPCMAVolume=0x3f;
|
||||
|
||||
OPN2_Reset(&fm_nuked);
|
||||
OPN2_SetChipType(&fm_nuked,ym3438_mode_opn);
|
||||
|
||||
ay->reset();
|
||||
ay->getRegisterWrites().clear();
|
||||
ay->flushWrites();
|
||||
|
|
@ -220,8 +221,8 @@ template<int ChanNum> class DivPlatformYM2610Base: public DivPlatformOPN {
|
|||
}
|
||||
CHECK_CUSTOM_CLOCK;
|
||||
noExtMacros=flags.getBool("noExtMacros",false);
|
||||
rate=chipClock/16;
|
||||
for (int i=0; i<ChanNum; i++) {
|
||||
rate=fm->sample_rate(chipClock);
|
||||
for (int i=0; i<16; i++) {
|
||||
oscBuf[i]->rate=rate;
|
||||
}
|
||||
}
|
||||
|
|
@ -231,7 +232,7 @@ template<int ChanNum> class DivPlatformYM2610Base: public DivPlatformOPN {
|
|||
ayFlags.set("chipType",1);
|
||||
dumpWrites=false;
|
||||
skipRegisterWrites=false;
|
||||
for (int i=0; i<ChanNum; i++) {
|
||||
for (int i=0; i<16; i++) {
|
||||
isMuted[i]=false;
|
||||
oscBuf[i]=new DivDispatchOscBuffer;
|
||||
}
|
||||
|
|
@ -243,7 +244,7 @@ template<int ChanNum> class DivPlatformYM2610Base: public DivPlatformOPN {
|
|||
iface.adpcmBMem=adpcmBMem;
|
||||
iface.sampleBank=0;
|
||||
fm=new ymfm::ym2610b(iface);
|
||||
fm->set_fidelity(ymfm::OPN_FIDELITY_MAX);
|
||||
fm->set_fidelity(ymfm::OPN_FIDELITY_MED);
|
||||
setFlags(flags);
|
||||
// YM2149, 2MHz
|
||||
ay=new DivPlatformAY8910(true,chipClock,32);
|
||||
|
|
@ -253,7 +254,7 @@ template<int ChanNum> class DivPlatformYM2610Base: public DivPlatformOPN {
|
|||
}
|
||||
|
||||
void quit() {
|
||||
for (int i=0; i<ChanNum; i++) {
|
||||
for (int i=0; i<16; i++) {
|
||||
delete oscBuf[i];
|
||||
}
|
||||
ay->quit();
|
||||
|
|
@ -262,12 +263,8 @@ template<int ChanNum> class DivPlatformYM2610Base: public DivPlatformOPN {
|
|||
delete[] adpcmBMem;
|
||||
}
|
||||
|
||||
DivPlatformYM2610Base(int ext, int psg, int adpcmA, int adpcmB):
|
||||
DivPlatformOPN(9440540.0, 72, 32),
|
||||
extChanOffs(ext),
|
||||
psgChanOffs(psg),
|
||||
adpcmAChanOffs(adpcmA),
|
||||
adpcmBChanOffs(adpcmB) {}
|
||||
DivPlatformYM2610Base(int ext, int psg, int adpcmA, int adpcmB, int chanCount):
|
||||
DivPlatformOPN(ext,psg,adpcmA,adpcmB,chanCount,9440540.0, 72, 32) {}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue