SNES: get some of echo working
This commit is contained in:
parent
e5b37db55a
commit
08e23a68cd
|
@ -83,7 +83,7 @@ void DivPlatformSNES::acquire(short* bufL, short* bufR, size_t start, size_t len
|
||||||
bufL[h]=out[0];
|
bufL[h]=out[0];
|
||||||
bufR[h]=out[1];
|
bufR[h]=out[1];
|
||||||
for (int i=0; i<8; i++) {
|
for (int i=0; i<8; i++) {
|
||||||
int next=chOut[i*2]+chOut[i*2+1];
|
int next=(3*(chOut[i*2]+chOut[i*2+1]))>>2;
|
||||||
if (next<-32768) next=-32768;
|
if (next<-32768) next=-32768;
|
||||||
if (next>32767) next=32767;
|
if (next>32767) next=32767;
|
||||||
next=(next*254)/MAX(1,globalVolL+globalVolR);
|
next=(next*254)/MAX(1,globalVolL+globalVolR);
|
||||||
|
@ -228,7 +228,7 @@ void DivPlatformSNES::tick(bool sysTick) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (writeControl) {
|
if (writeControl) {
|
||||||
unsigned char control=noiseFreq&0x1f;
|
unsigned char control=(noiseFreq&0x1f)|(echoOn?0:0x20);
|
||||||
rWrite(0x6c,control);
|
rWrite(0x6c,control);
|
||||||
writeControl=false;
|
writeControl=false;
|
||||||
}
|
}
|
||||||
|
@ -305,7 +305,6 @@ int DivPlatformSNES::dispatch(DivCommand c) {
|
||||||
}
|
}
|
||||||
if (chan[c.chan].insChanged) {
|
if (chan[c.chan].insChanged) {
|
||||||
chan[c.chan].state=ins->snes;
|
chan[c.chan].state=ins->snes;
|
||||||
}
|
|
||||||
if (chan[c.chan].state.useEnv) {
|
if (chan[c.chan].state.useEnv) {
|
||||||
chWrite(c.chan,5,chan[c.chan].state.a|(chan[c.chan].state.d<<4)|0x80);
|
chWrite(c.chan,5,chan[c.chan].state.a|(chan[c.chan].state.d<<4)|0x80);
|
||||||
chWrite(c.chan,6,chan[c.chan].state.r|(chan[c.chan].state.s<<5));
|
chWrite(c.chan,6,chan[c.chan].state.r|(chan[c.chan].state.s<<5));
|
||||||
|
@ -329,6 +328,7 @@ int DivPlatformSNES::dispatch(DivCommand c) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (c.value!=DIV_NOTE_NULL) {
|
if (c.value!=DIV_NOTE_NULL) {
|
||||||
chan[c.chan].baseFreq=round(NOTE_FREQUENCY(c.value));
|
chan[c.chan].baseFreq=round(NOTE_FREQUENCY(c.value));
|
||||||
chan[c.chan].freqChanged=true;
|
chan[c.chan].freqChanged=true;
|
||||||
|
@ -413,7 +413,47 @@ int DivPlatformSNES::dispatch(DivCommand c) {
|
||||||
chan[c.chan].audPos=c.value;
|
chan[c.chan].audPos=c.value;
|
||||||
chan[c.chan].setPos=true;
|
chan[c.chan].setPos=true;
|
||||||
break;
|
break;
|
||||||
// TODO SNES-specific commands
|
case DIV_CMD_SNES_ECHO:
|
||||||
|
chan[c.chan].echo=c.value;
|
||||||
|
writeEcho=true;
|
||||||
|
break;
|
||||||
|
case DIV_CMD_SNES_ECHO_DELAY: {
|
||||||
|
echoDelay=c.value&15;
|
||||||
|
unsigned char esa=0xf8-(echoDelay<<3);
|
||||||
|
if (echoOn) {
|
||||||
|
rWrite(0x6d,esa);
|
||||||
|
rWrite(0x7d,echoDelay);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DIV_CMD_SNES_ECHO_ENABLE:
|
||||||
|
echoOn=c.value;
|
||||||
|
initEcho();
|
||||||
|
break;
|
||||||
|
case DIV_CMD_SNES_ECHO_FEEDBACK:
|
||||||
|
echoFeedback=c.value;
|
||||||
|
if (echoOn) {
|
||||||
|
rWrite(0x0d,echoFeedback);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DIV_CMD_SNES_ECHO_FIR:
|
||||||
|
echoFIR[c.value&7]=c.value2;
|
||||||
|
if (echoOn) {
|
||||||
|
rWrite(0x0f+((c.value&7)<<4),echoFIR[c.value&7]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DIV_CMD_SNES_ECHO_VOL_LEFT:
|
||||||
|
echoVolL=c.value;
|
||||||
|
if (echoOn) {
|
||||||
|
rWrite(0x2c,echoVolL);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DIV_CMD_SNES_ECHO_VOL_RIGHT:
|
||||||
|
echoVolR=c.value;
|
||||||
|
if (echoOn) {
|
||||||
|
rWrite(0x3c,echoVolR);
|
||||||
|
}
|
||||||
|
break;
|
||||||
case DIV_CMD_GET_VOLMAX:
|
case DIV_CMD_GET_VOLMAX:
|
||||||
return 127;
|
return 127;
|
||||||
break;
|
break;
|
||||||
|
@ -469,6 +509,7 @@ void DivPlatformSNES::forceIns() {
|
||||||
writeNoise=true;
|
writeNoise=true;
|
||||||
writePitchMod=true;
|
writePitchMod=true;
|
||||||
writeEcho=true;
|
writeEcho=true;
|
||||||
|
initEcho();
|
||||||
}
|
}
|
||||||
|
|
||||||
void* DivPlatformSNES::getChanState(int ch) {
|
void* DivPlatformSNES::getChanState(int ch) {
|
||||||
|
@ -497,7 +538,28 @@ int DivPlatformSNES::getRegisterPoolSize() {
|
||||||
return 128;
|
return 128;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DivPlatformSNES::initEcho() {
|
||||||
|
unsigned char esa=0xf8-(echoDelay<<3);
|
||||||
|
if (echoOn) {
|
||||||
|
rWrite(0x6d,esa);
|
||||||
|
rWrite(0x7d,echoDelay);
|
||||||
|
rWrite(0x0d,echoFeedback);
|
||||||
|
rWrite(0x2c,echoVolL);
|
||||||
|
rWrite(0x3c,echoVolR);
|
||||||
|
for (int i=0; i<8; i++) {
|
||||||
|
rWrite(0x0f+(i<<4),echoFIR[i]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
rWrite(0x6d,0);
|
||||||
|
rWrite(0x7d,0);
|
||||||
|
rWrite(0x2c,0);
|
||||||
|
rWrite(0x3c,0);
|
||||||
|
}
|
||||||
|
writeControl=true;
|
||||||
|
}
|
||||||
|
|
||||||
void DivPlatformSNES::reset() {
|
void DivPlatformSNES::reset() {
|
||||||
|
memcpy(sampleMem,copyOfSampleMem,65536);
|
||||||
dsp.init(sampleMem);
|
dsp.init(sampleMem);
|
||||||
dsp.set_output(NULL,0);
|
dsp.set_output(NULL,0);
|
||||||
memset(regPool,0,128);
|
memset(regPool,0,128);
|
||||||
|
@ -521,6 +583,22 @@ void DivPlatformSNES::reset() {
|
||||||
writeNoise=false;
|
writeNoise=false;
|
||||||
writePitchMod=false;
|
writePitchMod=false;
|
||||||
writeEcho=false;
|
writeEcho=false;
|
||||||
|
|
||||||
|
echoDelay=0;
|
||||||
|
echoFeedback=0;
|
||||||
|
echoFIR[0]=127;
|
||||||
|
echoFIR[1]=0;
|
||||||
|
echoFIR[2]=0;
|
||||||
|
echoFIR[3]=0;
|
||||||
|
echoFIR[4]=0;
|
||||||
|
echoFIR[5]=0;
|
||||||
|
echoFIR[6]=0;
|
||||||
|
echoFIR[7]=0;
|
||||||
|
echoVolL=127;
|
||||||
|
echoVolR=127;
|
||||||
|
echoOn=false;
|
||||||
|
|
||||||
|
initEcho();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DivPlatformSNES::isStereo() {
|
bool DivPlatformSNES::isStereo() {
|
||||||
|
@ -574,7 +652,7 @@ size_t DivPlatformSNES::getSampleMemUsage(int index) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void DivPlatformSNES::renderSamples() {
|
void DivPlatformSNES::renderSamples() {
|
||||||
memset(sampleMem,0,getSampleMemCapacity());
|
memset(copyOfSampleMem,0,getSampleMemCapacity());
|
||||||
memset(sampleOff,0,256*sizeof(unsigned int));
|
memset(sampleOff,0,256*sizeof(unsigned int));
|
||||||
|
|
||||||
// skip past sample table and wavetable buffer
|
// skip past sample table and wavetable buffer
|
||||||
|
@ -585,12 +663,12 @@ void DivPlatformSNES::renderSamples() {
|
||||||
int actualLength=MIN((int)(getSampleMemCapacity()-memPos)/9*9,length);
|
int actualLength=MIN((int)(getSampleMemCapacity()-memPos)/9*9,length);
|
||||||
if (actualLength>0) {
|
if (actualLength>0) {
|
||||||
sampleOff[i]=memPos;
|
sampleOff[i]=memPos;
|
||||||
memcpy(&sampleMem[memPos],s->dataBRR,actualLength);
|
memcpy(©OfSampleMem[memPos],s->dataBRR,actualLength);
|
||||||
memPos+=actualLength;
|
memPos+=actualLength;
|
||||||
}
|
}
|
||||||
if (actualLength<length) {
|
if (actualLength<length) {
|
||||||
// terminate the sample
|
// terminate the sample
|
||||||
sampleMem[memPos-9]=1;
|
copyOfSampleMem[memPos-9]=1;
|
||||||
logW("out of BRR memory for sample %d!",i);
|
logW("out of BRR memory for sample %d!",i);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -607,13 +685,14 @@ int DivPlatformSNES::init(DivEngine* p, int channels, int sugRate, unsigned int
|
||||||
parent=p;
|
parent=p;
|
||||||
dumpWrites=false;
|
dumpWrites=false;
|
||||||
skipRegisterWrites=false;
|
skipRegisterWrites=false;
|
||||||
for (int i=0; i<8; i++) {
|
|
||||||
oscBuf[i]=new DivDispatchOscBuffer;
|
|
||||||
isMuted[i]=false;
|
|
||||||
}
|
|
||||||
sampleMemLen=0;
|
sampleMemLen=0;
|
||||||
chipClock=1024000;
|
chipClock=1024000;
|
||||||
rate=chipClock/32;
|
rate=chipClock/32;
|
||||||
|
for (int i=0; i<8; i++) {
|
||||||
|
oscBuf[i]=new DivDispatchOscBuffer;
|
||||||
|
oscBuf[i]->rate=rate;
|
||||||
|
isMuted[i]=false;
|
||||||
|
}
|
||||||
setFlags(flags);
|
setFlags(flags);
|
||||||
reset();
|
reset();
|
||||||
return 8;
|
return 8;
|
||||||
|
|
|
@ -77,11 +77,15 @@ class DivPlatformSNES: public DivDispatch {
|
||||||
bool isMuted[8];
|
bool isMuted[8];
|
||||||
int globalVolL, globalVolR;
|
int globalVolL, globalVolR;
|
||||||
unsigned char noiseFreq;
|
unsigned char noiseFreq;
|
||||||
|
signed char echoVolL, echoVolR, echoFeedback;
|
||||||
|
signed char echoFIR[8];
|
||||||
|
unsigned char echoDelay;
|
||||||
size_t sampleTableBase;
|
size_t sampleTableBase;
|
||||||
bool writeControl;
|
bool writeControl;
|
||||||
bool writeNoise;
|
bool writeNoise;
|
||||||
bool writePitchMod;
|
bool writePitchMod;
|
||||||
bool writeEcho;
|
bool writeEcho;
|
||||||
|
bool echoOn;
|
||||||
|
|
||||||
struct QueuedWrite {
|
struct QueuedWrite {
|
||||||
unsigned char addr;
|
unsigned char addr;
|
||||||
|
@ -91,6 +95,7 @@ class DivPlatformSNES: public DivDispatch {
|
||||||
std::queue<QueuedWrite> writes;
|
std::queue<QueuedWrite> writes;
|
||||||
|
|
||||||
signed char sampleMem[65536];
|
signed char sampleMem[65536];
|
||||||
|
signed char copyOfSampleMem[65536];
|
||||||
size_t sampleMemLen;
|
size_t sampleMemLen;
|
||||||
unsigned int sampleOff[256];
|
unsigned int sampleOff[256];
|
||||||
unsigned char regPool[0x80];
|
unsigned char regPool[0x80];
|
||||||
|
@ -126,6 +131,7 @@ class DivPlatformSNES: public DivDispatch {
|
||||||
private:
|
private:
|
||||||
void updateWave(int ch);
|
void updateWave(int ch);
|
||||||
void writeOutVol(int ch);
|
void writeOutVol(int ch);
|
||||||
|
void initEcho();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue