Merge branch 'master' of https://github.com/tildearrow/furnace into es5506_alt

This commit is contained in:
cam900 2022-10-22 10:17:00 +09:00
commit 487607b6ae
110 changed files with 1707 additions and 854 deletions

View file

@ -22,6 +22,9 @@
void DivDispatch::acquire(short* bufL, short* bufR, size_t start, size_t len) {
}
void DivDispatch::fillStream(std::vector<DivDelayedWrite>& stream, int sRate, size_t len) {
}
void DivDispatch::tick(bool sysTick) {
}

View file

@ -27,11 +27,11 @@
#define IS_REALLY_MUTED(x) (isMuted[x] && (x<5 || !softPCM || (isMuted[5] && isMuted[6])))
void DivPlatformGenesis::processDAC() {
void DivPlatformGenesis::processDAC(int iRate) {
if (softPCM) {
softPCMTimer+=chipClock/576;
if (softPCMTimer>rate) {
softPCMTimer-=rate;
if (softPCMTimer>iRate) {
softPCMTimer-=iRate;
int sample=0;
for (int i=5; i<7; i++) {
@ -75,14 +75,14 @@ void DivPlatformGenesis::processDAC() {
} else {
if (!chan[5].dacReady) {
chan[5].dacDelay+=32000;
if (chan[5].dacDelay>=rate) {
chan[5].dacDelay-=rate;
if (chan[5].dacDelay>=iRate) {
chan[5].dacDelay-=iRate;
chan[5].dacReady=true;
}
}
if (chan[5].dacMode && chan[5].dacSample!=-1) {
chan[5].dacPeriod+=chan[5].dacRate;
if (chan[5].dacPeriod>=rate) {
if (chan[5].dacPeriod>=iRate) {
DivSample* s=parent->getSample(chan[5].dacSample);
if (s->samples>0) {
if (!isMuted[5]) {
@ -106,7 +106,7 @@ void DivPlatformGenesis::processDAC() {
rWrite(0x2b,0);
}
}
while (chan[5].dacPeriod>=rate) chan[5].dacPeriod-=rate;
while (chan[5].dacPeriod>=iRate) chan[5].dacPeriod-=iRate;
} else {
chan[5].dacSample=-1;
}
@ -120,7 +120,7 @@ void DivPlatformGenesis::acquire_nuked(short* bufL, short* bufR, size_t start, s
static int os[2];
for (size_t h=start; h<start+len; h++) {
processDAC();
processDAC(rate);
os[0]=0; os[1]=0;
for (int i=0; i<6; i++) {
@ -180,7 +180,7 @@ void DivPlatformGenesis::acquire_ymfm(short* bufL, short* bufR, size_t start, si
ymfm::ym2612::fm_engine* fme=fm_ymfm->debug_engine();
for (size_t h=start; h<start+len; h++) {
processDAC();
processDAC(rate);
os[0]=0; os[1]=0;
if (!writes.empty()) {
@ -237,6 +237,20 @@ void DivPlatformGenesis::acquire(short* bufL, short* bufR, size_t start, size_t
}
}
void DivPlatformGenesis::fillStream(std::vector<DivDelayedWrite>& stream, int sRate, size_t len) {
while (!writes.empty()) writes.pop_front();
for (size_t i=0; i<len; i++) {
processDAC(sRate);
while (!writes.empty()) {
QueuedWrite& w=writes.front();
stream.push_back(DivDelayedWrite(i,w.addr,w.val));
writes.pop_front();
}
}
regWrites.clear();
}
void DivPlatformGenesis::tick(bool sysTick) {
for (int i=0; i<(softPCM?7:6); i++) {
if (i==2 && extMode) continue;

View file

@ -124,12 +124,13 @@ class DivPlatformGenesis: public DivPlatformOPN {
friend void putDispatchChip(void*,int);
friend void putDispatchChan(void*,int,int);
inline void processDAC();
inline void processDAC(int iRate);
void acquire_nuked(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);
void fillStream(std::vector<DivDelayedWrite>& stream, int sRate, size_t len);
int dispatch(DivCommand c);
void* getChanState(int chan);
DivMacroInt* getChanMacroInt(int ch);

View file

@ -416,12 +416,10 @@ int DivPlatformNES::dispatch(DivCommand c) {
if (!parent->song.brokenOutVol && !chan[c.chan].std.vol.will) {
chan[c.chan].outVol=chan[c.chan].vol;
}
if (!parent->song.brokenOutVol2) {
if (c.chan==2) {
rWrite(0x4000+c.chan*4,0xff);
} else {
rWrite(0x4000+c.chan*4,0x30|chan[c.chan].vol|((chan[c.chan].duty&3)<<6));
}
if (c.chan==2) {
rWrite(0x4000+c.chan*4,0xff);
} else if (!parent->song.brokenOutVol2) {
rWrite(0x4000+c.chan*4,0x30|chan[c.chan].vol|((chan[c.chan].duty&3)<<6));
}
break;
case DIV_CMD_NOTE_OFF:

View file

@ -25,8 +25,6 @@
//#define rWrite(a,v) pendingWrites[a]=v;
#define rWrite(a,v) if (!skipRegisterWrites) {writes.emplace(a,v); if (dumpWrites) {addWrite(a,v);} }
#define CHIP_DIVIDER 16
const char* regCheatSheetT6W28[]={
"Data0", "0",
"Data1", "1",
@ -72,14 +70,21 @@ void DivPlatformT6W28::acquire(short* bufL, short* bufR, size_t start, size_t le
}
void DivPlatformT6W28::writeOutVol(int ch) {
int left=15-CLAMP(chan[ch].outVol+chan[ch].panL-15,0,15);
int right=15-CLAMP(chan[ch].outVol+chan[ch].panR-15,0,15);
rWrite(0,0x90|(ch<<5)|(isMuted[ch]?15:left));
rWrite(1,0x90|(ch<<5)|(isMuted[ch]?15:right));
if (chan[ch].active) {
int left=15-CLAMP(chan[ch].outVol+chan[ch].panL-15,0,15);
int right=15-CLAMP(chan[ch].outVol+chan[ch].panR-15,0,15);
rWrite(0,0x90|(ch<<5)|(isMuted[ch]?15:left));
rWrite(1,0x90|(ch<<5)|(isMuted[ch]?15:right));
} else {
rWrite(0,0x9f|(ch<<5));
rWrite(1,0x9f|(ch<<5));
}
}
void DivPlatformT6W28::tick(bool sysTick) {
for (int i=0; i<4; i++) {
double CHIP_DIVIDER=16;
if (i==3) CHIP_DIVIDER=15;
chan[i].std.next();
if (chan[i].std.vol.had) {
chan[i].outVol=VOL_SCALE_LOG(chan[i].vol&15,MIN(15,chan[i].std.vol.val),15);
@ -91,6 +96,12 @@ void DivPlatformT6W28::tick(bool sysTick) {
}
chan[i].freqChanged=true;
}
if (i==3 && chan[i].std.duty.had) {
if (chan[i].duty!=chan[i].std.duty.val) {
chan[i].duty=((chan[i].std.duty.val==1)?4:0)|3;
rWrite(1,0xe0+chan[i].duty);
}
}
if (chan[i].std.panL.had) {
chan[i].panL=chan[i].std.panL.val&15;
}
@ -109,12 +120,13 @@ void DivPlatformT6W28::tick(bool sysTick) {
}
chan[i].freqChanged=true;
}
if (chan[i].std.phaseReset.had) {
rWrite(1,0xe0+chan[i].duty);
}
if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) {
//DivInstrument* ins=parent->getIns(chan[i].ins,DIV_INS_PCE);
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true,0,chan[i].pitch2,chipClock,CHIP_DIVIDER);
if (chan[i].freq>1023) chan[i].freq=1023;
if (i==3) {
rWrite(1,0xe7);
rWrite(1,0x80|(2<<5)|(chan[3].freq&15));
rWrite(1,chan[3].freq>>4);
} else {
@ -129,6 +141,8 @@ void DivPlatformT6W28::tick(bool sysTick) {
}
int DivPlatformT6W28::dispatch(DivCommand c) {
double CHIP_DIVIDER=16;
if (c.chan==3) CHIP_DIVIDER=15;
switch (c.cmd) {
case DIV_CMD_NOTE_ON: {
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_PCE);
@ -142,6 +156,7 @@ int DivPlatformT6W28::dispatch(DivCommand c) {
chan[c.chan].macroInit(ins);
if (!parent->song.brokenOutVol && !chan[c.chan].std.vol.will) {
chan[c.chan].outVol=chan[c.chan].vol;
writeOutVol(c.chan);
}
chan[c.chan].insChanged=false;
break;
@ -150,6 +165,7 @@ int DivPlatformT6W28::dispatch(DivCommand c) {
chan[c.chan].active=false;
chan[c.chan].keyOff=true;
chan[c.chan].macroInit(NULL);
writeOutVol(c.chan);
break;
case DIV_CMD_NOTE_OFF_ENV:
case DIV_CMD_ENV_RELEASE:
@ -166,8 +182,7 @@ int DivPlatformT6W28::dispatch(DivCommand c) {
chan[c.chan].vol=c.value;
if (!chan[c.chan].std.vol.has) {
chan[c.chan].outVol=c.value;
if (chan[c.chan].active) {
}
writeOutVol(c.chan);
}
}
break;
@ -205,7 +220,9 @@ int DivPlatformT6W28::dispatch(DivCommand c) {
break;
}
case DIV_CMD_STD_NOISE_MODE:
chan[c.chan].noise=c.value;
if (c.chan!=3) break;
chan[c.chan].duty=(((c.value&15)==1)?4:0)|3;
rWrite(1,0xe0+chan[c.chan].duty);
break;
case DIV_CMD_PANNING: {
chan[c.chan].panL=c.value>>4;
@ -226,7 +243,7 @@ int DivPlatformT6W28::dispatch(DivCommand c) {
chan[c.chan].inPorta=c.value;
break;
case DIV_CMD_GET_VOLMAX:
return 31;
return 15;
break;
case DIV_ALWAYS_SET_VOLUME:
return 1;
@ -289,6 +306,8 @@ void DivPlatformT6W28::reset() {
cycles=0;
curChan=-1;
delay=0;
// default noise mode
rWrite(1,0xe7);
}
bool DivPlatformT6W28::isStereo() {

View file

@ -29,8 +29,8 @@ class DivPlatformT6W28: public DivDispatch {
struct Channel {
int freq, baseFreq, pitch, pitch2, note;
int ins;
unsigned char panL, panR;
bool active, insChanged, freqChanged, keyOn, keyOff, inPorta, noise;
unsigned char panL, panR, duty;
bool active, insChanged, freqChanged, keyOn, keyOff, inPorta;
signed char vol, outVol;
DivMacroInt std;
void macroInit(DivInstrument* which) {
@ -46,13 +46,13 @@ class DivPlatformT6W28: public DivDispatch {
ins(-1),
panL(15),
panR(15),
duty(7),
active(false),
insChanged(true),
freqChanged(false),
keyOn(false),
keyOff(false),
inPorta(false),
noise(false),
vol(15),
outVol(15) {}
};

View file

@ -84,6 +84,8 @@ const char* regCheatSheetVB[]={
"S6EV0", "550",
"S6EV1", "554",
"S6RAM", "558",
"RESET", "580",
NULL
};
@ -148,6 +150,13 @@ void DivPlatformVB::tick(bool sysTick) {
}
chan[i].freqChanged=true;
}
if (i==5 && chan[i].std.duty.had) {
if ((chan[i].std.duty.val&7)!=((chan[i].envHigh>>4)&7)) {
chan[i].envHigh&=~0x70;
chan[i].envHigh|=(chan[i].std.duty.val&7)<<4;
writeEnv(i,true);
}
}
if (chan[i].std.wave.had) {
if (chan[i].wave!=chan[i].std.wave.val || chan[i].ws.activeChanged()) {
chan[i].wave=chan[i].std.wave.val;
@ -176,7 +185,7 @@ void DivPlatformVB::tick(bool sysTick) {
chan[i].freqChanged=true;
}
if (chan[i].std.phaseReset.had && chan[i].std.phaseReset.val==1) {
// ???
chWrite(i,0x00,0x80);
}
if (chan[i].active) {
if (chan[i].ws.tick() || (chan[i].std.phaseReset.had && chan[i].std.phaseReset.val==1)) {
@ -310,12 +319,12 @@ int DivPlatformVB::dispatch(DivCommand c) {
break;
case DIV_CMD_FDS_MOD_DEPTH: // set modulation
if (c.chan!=4) break;
modulation=(c.value<<4)&15;
modulation=(c.value&15)<<4;
modType=true;
chWrite(4,0x07,modulation);
if (modulation!=0) {
chan[c.chan].envHigh&=~0x70;
chan[c.chan].envHigh|=0x40|((c.value&15)<<4);
chan[c.chan].envHigh|=0x40|(c.value&0xf0);
} else {
chan[c.chan].envHigh&=~0x70;
}
@ -328,7 +337,7 @@ int DivPlatformVB::dispatch(DivCommand c) {
chWrite(4,0x07,modulation);
if (modulation!=0) {
chan[c.chan].envHigh&=~0x70;
chan[c.chan].envHigh|=0x10;
chan[c.chan].envHigh|=0x40;
} else {
chan[c.chan].envHigh&=~0x70;
}

View file

@ -174,6 +174,7 @@ void DivPlatformVERA::tick(bool sysTick) {
if (i<16) {
if (chan[i].std.panL.had) {
chan[i].pan=chan[i].std.panL.val&3;
chan[i].pan=((chan[i].pan&1)<<1)|((chan[i].pan&2)>>1);
rWriteHi(i,2,isMuted[i]?0:chan[i].pan);
}
}
@ -329,7 +330,7 @@ int DivPlatformVERA::dispatch(DivCommand c) {
if (chan[c.chan].active && c.value2) {
if (parent->song.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_VERA));
}
if (!chan[c.chan].inPorta && c.value && !parent->song.brokenPortaArp && chan[c.chan].std.arp.will) chan[c.chan].baseFreq=calcNoteFreq(c.chan,chan[c.chan].note);
if (!chan[c.chan].inPorta && c.value && chan[c.chan].std.arp.will) chan[c.chan].baseFreq=calcNoteFreq(c.chan,chan[c.chan].note);
chan[c.chan].inPorta=c.value;
break;
case DIV_CMD_STD_NOISE_MODE: