Sync to master

This commit is contained in:
cam900 2022-09-25 18:32:34 +09:00
parent 0a49d4bfd0
commit 8e1ce1abb1
21 changed files with 238 additions and 3298 deletions

View file

@ -27,7 +27,7 @@
#define NOTE_ES5506(c,note) (parent->calcBaseFreq(chipClock,chan[c].pcm.freqOffs,note,false))
#define rWrite(a,...) {if(!skipRegisterWrites) {hostIntf32.emplace(4,(a),__VA_ARGS__); }}
#define rRead(a,...) {hostIntf32.emplace(4,(a),__VA_ARGS__);}
#define rRead(a,st,...) {hostIntf32.emplace(st,4,(a),__VA_ARGS__);}
#define immWrite(a,...) {hostIntf32.emplace(4,(a),__VA_ARGS__);}
#define pageWrite(p,a,...) \
if (!skipRegisterWrites) { \
@ -47,13 +47,13 @@
rWrite((a),__VA_ARGS__); \
}
#define pageReadMask(p,pm,a,...) \
#define pageReadMask(p,pm,a,st,...) \
if (!skipRegisterWrites) { \
if ((curPage&(pm))!=((p)&(pm))) { \
curPage=(curPage&~(pm))|((p)&(pm)); \
rWrite(0xf,curPage,(pm)); \
} \
rRead((a),__VA_ARGS__); \
rRead(st,(a),__VA_ARGS__); \
}
@ -112,90 +112,16 @@ const char** DivPlatformES5506::getRegisterSheet() {
return regCheatSheetES5506;
}
const char* DivPlatformES5506::getEffectName(unsigned char effect) {
switch (effect) {
case 0x10:
return "10xx: Change waveform or sample, transwave index";
break;
case 0x11:
return "11xx: Set filter mode (00 to 03)";
break;
case 0x12:
return "120x: Set pause (bit 0)";
break;
case 0x13:
return "130x: Set transwave slice mode (bit 0)";
break;
case 0x14:
return "14xx: Set filter coefficient K1 low byte";
break;
case 0x15:
return "15xx: Set filter coefficient K1 high byte";
break;
case 0x16:
return "16xx: Set filter coefficient K2 low byte";
break;
case 0x17:
return "17xx: Set filter coefficient K2 high byte";
break;
case 0x18:
return "18xx: Set filter coefficient K1 slide up";
break;
case 0x19:
return "19xx: Set filter coefficient K1 slide down";
break;
case 0x1a:
return "1axx: Set filter coefficient K2 slide up";
break;
case 0x1b:
return "1bxx: Set filter coefficient K2 slide down";
break;
case 0x20:
return "20xx: Set envelope count (000 to 0FF)";
break;
case 0x21:
return "21xx: Set envelope count (100 to 1FF)";
break;
case 0x22:
return "22xx: Set envelope left volume ramp (signed)";
break;
case 0x23:
return "23xx: Set envelope right volume ramp (signed)";
break;
case 0x24:
return "24xx: Set envelope filter coefficient k1 ramp (signed)";
break;
case 0x25:
return "25xx: Set envelope filter coefficient k1 ramp (signed, slower)";
break;
case 0x26:
return "26xx: Set envelope filter coefficient k2 ramp (signed)";
break;
case 0x27:
return "27xx: Set envelope filter coefficient k2 ramp (signed, slower)";
break;
default:
if ((effect&0xf0)==0x30) {
return "3xxx: Set filter coefficient K1";
} else if ((effect&0xf0)==0x40) {
return "4xxx: Set filter coefficient K2";
} else if ((effect&0xf0)==0x50) {
return "5xxx: Set transwave slice point";
}
break;
}
return NULL;
}
void DivPlatformES5506::acquire(short* bufL, short* bufR, size_t start, size_t len) {
for (size_t h=start; h<start+len; h++) {
// convert 32 bit access to 8 bit host interface
while (!hostIntf32.empty()) {
QueuedHostIntf w=hostIntf32.front();
if (w.isRead && (w.read!=NULL)) {
hostIntf8.emplace(0,w.addr,w.read,w.mask);
hostIntf8.emplace(1,w.addr,w.read,w.mask);
hostIntf8.emplace(2,w.addr,w.read,w.mask);
hostIntf8.emplace(3,w.addr,w.read,w.mask,w.delay);
hostIntf8.emplace(w.state,0,w.addr,w.read,w.mask);
hostIntf8.emplace(w.state,1,w.addr,w.read,w.mask);
hostIntf8.emplace(w.state,2,w.addr,w.read,w.mask);
hostIntf8.emplace(w.state,3,w.addr,w.read,w.mask,w.delay);
} else {
hostIntf8.emplace(0,w.addr,w.val,w.mask);
hostIntf8.emplace(1,w.addr,w.val,w.mask);
@ -244,6 +170,7 @@ void DivPlatformES5506::e_pin(bool state)
if (w.delay>0) {
cycle+=w.delay;
}
queuedReadState.emplace(w.read,w.state);
isReaded=true;
} else {
isReaded=false;
@ -272,116 +199,127 @@ void DivPlatformES5506::e_pin(bool state)
}
}
}
if (isReaded) {
isReaded=false;
if (irqTrigger) {
irqTrigger=false;
if ((irqv&0x80)==0) {
unsigned char ch=irqv&0x1f;
if (chan[ch].isReverseLoop) { // Reversed loop
pageWriteMask(0x00|ch,0x5f,0x00,(chan[ch].pcm.reversed?0x0000:0x0040)|0x08,0x78);
chan[ch].isReverseLoop=false;
if (!queuedReadState.empty()) {
QueuedReadState w=queuedReadState.front();
const unsigned char state=w.state;
if (state&0x80) {
if (irqTrigger) {
if ((irqv&0x80)==0) {
queuedRead.emplace(irqv&0x1f);
}
if (chan[ch].transwaveIRQ) {
if ((chan[ch].cr&0x37)==0x34) { // IRQE = 1, BLE = 1, LPE = 0, LEI = 1
DivInstrument* ins=parent->getIns(chan[ch].ins);
if (!ins->amiga.useNoteMap && ins->amiga.transWave.enable) {
const int next=chan[ch].pcm.next;
if (next>=0 && next<(int)ins->amiga.transWaveMap.size()) {
DivInstrumentAmiga::TransWaveMap& transWaveInd=ins->amiga.transWaveMap[next];
int sample=transWaveInd.ind;
if (sample>=0 && sample<parent->song.sampleLen) {
chan[ch].pcm.index=sample;
chan[ch].transWave.ind=next;
DivSample* s=parent->getSample(sample);
// get frequency offset
double off=1.0;
double center=(double)s->centerRate;
if (center<1) {
off=1.0;
} else {
off=(double)center/8363.0;
}
// get loop mode, transwave loop
double loopStart=(double)s->loopStart;
double loopEnd=(double)s->loopEnd;
DivSampleLoopMode loopMode=s->isLoopable()?s->loopMode:DIV_SAMPLE_LOOPMODE_ONESHOT;
if (transWaveInd.loopMode!=DIV_SAMPLE_LOOPMODE_ONESHOT) {
loopMode=transWaveInd.loopMode;
} else if ((chan[ch].pcm.loopMode==DIV_SAMPLE_LOOPMODE_ONESHOT) || (!s->isLoopable())) { // default
loopMode=DIV_SAMPLE_LOOPMODE_PINGPONG;
}
// get loop position
loopStart=(double)transWaveInd.loopStart;
loopEnd=(double)transWaveInd.loopEnd;
if (ins->amiga.transWave.sliceEnable) { // sliced loop position?
chan[ch].transWave.updateSize(s->samples,loopStart,loopEnd);
chan[ch].transWave.slicePos(double(chan[ch].transWave.slice)/4095.0);
loopStart=transWaveInd.sliceStart;
loopEnd=transWaveInd.sliceEnd;
}
// get reversed
bool reversed=ins->amiga.reversed;
if (transWaveInd.reversed!=2) {
reversed=transWaveInd.reversed;
}
const unsigned int start=s->offES5506<<10;
const unsigned int length=s->samples-1;
const unsigned int end=start+(length<<11);
const double nextFreqOffs=PITCH_OFFSET*off;
chan[ch].pcm.loopMode=loopMode;
chan[ch].pcm.reversed=reversed;
chan[ch].pcm.bank=(s->offES5506>>22)&3;
chan[ch].pcm.start=start;
chan[ch].pcm.loopStart=(start+(unsigned int)(loopStart*2048.0))&0xfffff800;
chan[ch].pcm.loopEnd=(start+(unsigned int)((loopEnd-1.0)*2048.0))&0xffffff80;
chan[ch].pcm.end=end;
chan[ch].pcm.length=length;
pageWrite(0x20|ch,0x01,chan[ch].pcm.loopStart);
pageWrite(0x20|ch,0x02,chan[ch].pcm.loopEnd);
pageWrite(0x20|ch,0x03,(chan[ch].pcm.reversed)?chan[ch].pcm.loopEnd:chan[ch].pcm.loopStart);
unsigned int loopFlag=(chan[ch].pcm.bank<<14)|(chan[ch].pcm.reversed?0x0040:0x0000);
chan[ch].isReverseLoop=false;
switch (chan[ch].pcm.loopMode) {
case DIV_SAMPLE_LOOPMODE_ONESHOT: // One shot (no loop)
default:
break;
case DIV_SAMPLE_LOOPMODE_FORWARD: // Foward loop
loopFlag|=0x0008;
break;
case DIV_SAMPLE_LOOPMODE_BACKWARD: // Backward loop: IRQ enable
loopFlag|=0x0038;
chan[ch].isReverseLoop=true;
break;
case DIV_SAMPLE_LOOPMODE_PINGPONG: // Pingpong loop: Hardware support
loopFlag|=0x0018;
break;
}
// Set loop mode & Bank
pageWriteMask(0x00|ch,0x5f,0x00,loopFlag,0xfcfc);
if (chan[ch].pcm.nextFreqOffs!=nextFreqOffs) {
chan[ch].pcm.nextFreqOffs=nextFreqOffs;
chan[ch].noteChanged.offs=1;
}
irqTrigger=false;
}
} else {
unsigned char ch=w.state&0x1f;
if (chan[ch].transwaveIRQ) {
if ((chan[ch].cr&0x37)==0x34) { // IRQE = 1, BLE = 1, LPE = 0, LEI = 1
DivInstrument* ins=parent->getIns(chan[ch].ins);
if (!ins->amiga.useNoteMap && ins->amiga.transWave.enable) {
const int next=chan[ch].pcm.next;
if (next>=0 && next<(int)ins->amiga.transWaveMap.size()) {
DivInstrumentAmiga::TransWaveMap& transWaveInd=ins->amiga.transWaveMap[next];
int sample=transWaveInd.ind;
if (sample>=0 && sample<parent->song.sampleLen) {
chan[ch].pcm.index=sample;
chan[ch].transWave.ind=next;
DivSample* s=parent->getSample(sample);
// get frequency offset
double off=1.0;
double center=(double)s->centerRate;
if (center<1) {
off=1.0;
} else {
off=(double)center/8363.0;
}
// get loop mode, transwave loop
double loopStart=(double)s->loopStart;
double loopEnd=(double)s->loopEnd;
DivSampleLoopMode loopMode=s->isLoopable()?s->loopMode:DIV_SAMPLE_LOOP_MAX;
if (transWaveInd.loopMode!=DIV_SAMPLE_LOOP_MAX) {
loopMode=transWaveInd.loopMode;
} else if ((chan[ch].pcm.loopMode==DIV_SAMPLE_LOOP_MAX) || (!s->isLoopable())) { // default
loopMode=DIV_SAMPLE_LOOP_PINGPONG;
}
// get loop position
loopStart=(double)transWaveInd.loopStart;
loopEnd=(double)transWaveInd.loopEnd;
if (ins->amiga.transWave.sliceEnable) { // sliced loop position?
chan[ch].transWave.updateSize(s->samples,loopStart,loopEnd);
chan[ch].transWave.slicePos(double(chan[ch].transWave.slice)/4095.0);
loopStart=transWaveInd.sliceStart;
loopEnd=transWaveInd.sliceEnd;
}
// get reversed
bool reversed=ins->amiga.reversed;
if (transWaveInd.reversed!=2) {
reversed=transWaveInd.reversed;
}
const unsigned int start=s->offES5506<<10;
const unsigned int length=s->samples-1;
const unsigned int end=start+(length<<11);
const double nextFreqOffs=PITCH_OFFSET*off;
chan[ch].pcm.loopMode=loopMode;
chan[ch].pcm.reversed=reversed;
chan[ch].pcm.bank=(s->offES5506>>22)&3;
chan[ch].pcm.start=start;
chan[ch].pcm.loopStart=(start+(unsigned int)(loopStart*2048.0))&0xfffff800;
chan[ch].pcm.loopEnd=(start+(unsigned int)((loopEnd-1.0)*2048.0))&0xffffff80;
chan[ch].pcm.end=end;
chan[ch].pcm.length=length;
pageWrite(0x20|ch,0x01,chan[ch].pcm.loopStart);
pageWrite(0x20|ch,0x02,chan[ch].pcm.loopEnd);
pageWrite(0x20|ch,0x03,(chan[ch].pcm.reversed)?chan[ch].pcm.loopEnd:chan[ch].pcm.loopStart);
unsigned int loopFlag=(chan[ch].pcm.bank<<14)|(chan[ch].pcm.reversed?0x0040:0x0000);
chan[ch].isReverseLoop=false;
switch (chan[ch].pcm.loopMode) {
case DIV_SAMPLE_LOOP_MAX: // One shot (no loop)
default:
break;
case DIV_SAMPLE_LOOP_FORWARD: // Foward loop
loopFlag|=0x0008;
break;
case DIV_SAMPLE_LOOP_BACKWARD: // Backward loop: IRQ enable
loopFlag|=0x0038;
chan[ch].isReverseLoop=true;
break;
case DIV_SAMPLE_LOOP_PINGPONG: // Pingpong loop: Hardware support
loopFlag|=0x0018;
break;
}
// Set loop mode & Bank
pageWriteMask(0x00|ch,0x5f,0x00,loopFlag,0xfcfc);
if (chan[ch].pcm.nextFreqOffs!=nextFreqOffs) {
chan[ch].pcm.nextFreqOffs=nextFreqOffs;
chan[ch].noteChanged.offs=1;
}
}
chan[ch].pcmChanged.changed=0;
}
chan[ch].pcmChanged.changed=0;
}
chan[ch].transwaveIRQ=false;
}
if (chan[ch].isTranswave) {
pageReadMask(0x00|ch,0x5f,0x00,&chan[ch].cr);
chan[ch].transwaveIRQ=true;
chan[ch].isTranswave=false;
}
chan[ch].transwaveIRQ=false;
}
}
queuedReadState.pop();
}
if (!queuedRead.empty()) {
unsigned char ch=queuedRead.front()&0x1f;
if (chan[ch].isReverseLoop) { // Reversed loop
pageWriteMask(0x00|ch,0x5f,0x00,(chan[ch].pcm.reversed?0x0000:0x0040)|0x08,0x78);
chan[ch].isReverseLoop=false;
}
if (chan[ch].isTranswave) {
pageReadMask(0x00|ch,0x5f,0x00,ch,&chan[ch].cr);
chan[ch].transwaveIRQ=true;
chan[ch].isTranswave=false;
}
queuedRead.pop();
}
isReaded=false;
}
void DivPlatformES5506::irqb(bool state) {
rRead(0x0e,&irqv,0x9f);
rRead(0x0e,0x80,&irqv,0x9f);
irqTrigger=true;
}
@ -392,7 +330,7 @@ void DivPlatformES5506::tick(bool sysTick) {
signed int k1=chan[i].k1Prev,k2=chan[i].k2Prev;
// volume/panning macros
if (chan[i].std.vol.had) {
const unsigned int nextVol=((chan[i].vol&0xff)*MIN(0xffff,(0xffff*chan[i].std.vol.val)/chan[i].volMacroMax))/0xff;
const unsigned int nextVol=VOL_SCALE_LOG((0xffff*chan[i].vol)/0xff,(0xffff*chan[i].std.vol.val)/chan[i].volMacroMax,0xffff);
if (chan[i].outVol!=nextVol) {
chan[i].outVol=nextVol;
if (!isMuted[i]) {
@ -401,7 +339,7 @@ void DivPlatformES5506::tick(bool sysTick) {
}
}
if (chan[i].std.panL.had) {
const unsigned int nextLVol=(((ins->es5506.lVol*(chan[i].lVol&0xff))/0xff)*MIN(0xffff,(0xffff*chan[i].std.panL.val)/chan[i].panMacroMax))/0xffff;
const unsigned int nextLVol=VOL_SCALE_LOG((0xffff*chan[i].lVol)/0xff,(0xffff*chan[i].std.panL.val)/chan[i].panMacroMax,0xffff);
if (chan[i].outLVol!=nextLVol) {
chan[i].outLVol=nextLVol;
if (!isMuted[i]) {
@ -410,7 +348,7 @@ void DivPlatformES5506::tick(bool sysTick) {
}
}
if (chan[i].std.panR.had) {
const unsigned int nextRVol=(((ins->es5506.rVol*(chan[i].rVol&0xff))/0xff)*MIN(0xffff,(0xffff*chan[i].std.panR.val)/chan[i].panMacroMax))/0xffff;
const unsigned int nextRVol=VOL_SCALE_LOG((0xffff*chan[i].rVol)/0xff,(0xffff*chan[i].std.panR.val)/chan[i].panMacroMax,0xffff);
if (chan[i].outRVol!=nextRVol) {
chan[i].outRVol=nextRVol;
if (!isMuted[i]) {
@ -458,18 +396,19 @@ void DivPlatformES5506::tick(bool sysTick) {
}
if (chan[i].std.ex1.had) {
switch (chan[i].std.ex1.mode) {
case 0: // relative
if (chan[i].k1Offs!=chan[i].std.ex1.val) {
chan[i].k1Offs=chan[i].std.ex1.val;
chan[i].filterChanged.k1=1;
}
break;
case 1: // absolute
case 0: // absolute
if (chan[i].filter.k1!=(chan[i].std.ex1.val&0xffff)) {
chan[i].filter.k1=chan[i].std.ex1.val&0xffff;
chan[i].filterChanged.k1=1;
}
break;
case 1: // relative
if (chan[i].k1Offs!=chan[i].std.ex1.val) {
chan[i].k1Offs=chan[i].std.ex1.val;
chan[i].filterChanged.k1=1;
}
break;
/*
case 2: { // delta
const signed int next_k1=CLAMP(chan[i].k1Offs+chan[i].std.ex1.val,-65535,65535);
if (chan[i].k1Offs!=next_k1) {
@ -478,24 +417,26 @@ void DivPlatformES5506::tick(bool sysTick) {
}
break;
}
*/
default:
break;
}
}
if (chan[i].std.ex2.had) {
switch (chan[i].std.ex2.mode) {
case 0: // relative
if (chan[i].k2Offs!=chan[i].std.ex1.val) {
chan[i].k2Offs=chan[i].std.ex1.val;
chan[i].filterChanged.k2=1;
}
break;
case 1: // absolute
case 0: // absolute
if (chan[i].filter.k2!=(chan[i].std.ex2.val&0xffff)) {
chan[i].filter.k2=chan[i].std.ex2.val&0xffff;
chan[i].filterChanged.k2=1;
}
break;
case 1: // relative
if (chan[i].k2Offs!=chan[i].std.ex1.val) {
chan[i].k2Offs=chan[i].std.ex1.val;
chan[i].filterChanged.k2=1;
}
break;
/*
case 2: { // delta
const signed int next_k2=CLAMP(chan[i].k2Offs+chan[i].std.ex2.val,-65535,65535);
if (chan[i].k2Offs!=next_k2) {
@ -504,6 +445,7 @@ void DivPlatformES5506::tick(bool sysTick) {
}
break;
}
*/
default:
break;
}
@ -621,13 +563,13 @@ void DivPlatformES5506::tick(bool sysTick) {
if (chan[i].volChanged.changed) {
if (!isMuted[i]) { // calculate volume (16 bit)
if (chan[i].volChanged.lVol) {
chan[i].resLVol=(chan[i].outVol*chan[i].outLVol)/0xffff;
chan[i].resLVol=VOL_SCALE_LOG(chan[i].outVol,chan[i].outLVol,0xffff);
if (!chan[i].keyOn) {
pageWrite(0x00|i,0x02,chan[i].resLVol);
}
}
if (chan[i].volChanged.rVol) {
chan[i].resRVol=(chan[i].outVol*chan[i].outRVol)/0xffff;
chan[i].resRVol=VOL_SCALE_LOG(chan[i].outVol,chan[i].outRVol,0xffff);
if (!chan[i].keyOn) {
pageWrite(0x00|i,0x04,chan[i].resRVol);
}
@ -655,11 +597,11 @@ void DivPlatformES5506::tick(bool sysTick) {
// get loop mode, transwave loop
double loopStart=(double)s->loopStart;
double loopEnd=(double)s->loopEnd;
DivSampleLoopMode loopMode=s->isLoopable()?s->loopMode:DIV_SAMPLE_LOOPMODE_ONESHOT;
if (transWaveInd.loopMode!=DIV_SAMPLE_LOOPMODE_ONESHOT) {
DivSampleLoopMode loopMode=s->isLoopable()?s->loopMode:DIV_SAMPLE_LOOP_MAX;
if (transWaveInd.loopMode!=DIV_SAMPLE_LOOP_MAX) {
loopMode=transWaveInd.loopMode;
} else if ((chan[i].pcm.loopMode==DIV_SAMPLE_LOOPMODE_ONESHOT) || (!s->isLoopable())) { // default
loopMode=DIV_SAMPLE_LOOPMODE_PINGPONG;
} else if ((chan[i].pcm.loopMode==DIV_SAMPLE_LOOP_MAX) || (!s->isLoopable())) { // default
loopMode=DIV_SAMPLE_LOOP_PINGPONG;
}
// get loop position
loopStart=(double)transWaveInd.loopStart;
@ -693,13 +635,13 @@ void DivPlatformES5506::tick(bool sysTick) {
if (((ins->amiga.useNoteMap && !ins->amiga.transWave.enable) && (next>=0 && next<120)) ||
((!ins->amiga.useNoteMap && ins->amiga.transWave.enable) && (next>=0 && next<(int)ins->amiga.transWaveMap.size())) ||
((!ins->amiga.useNoteMap && !ins->amiga.transWave.enable) && (next>=0 && next<parent->song.sampleLen))) {
DivInstrumentAmiga::NoteMap& noteMapind=ins->amiga.noteMap[next];
DivInstrumentAmiga::SampleMap& noteMapind=ins->amiga.noteMap[next];
DivInstrumentAmiga::TransWaveMap& transWaveInd=ins->amiga.transWaveMap[next];
int sample=next;
if (ins->amiga.transWave.enable) {
sample=transWaveInd.ind;
} else if (ins->amiga.useNoteMap) {
sample=noteMapind.ind;
sample=noteMapind.map;
}
if (sample>=0 && sample<parent->song.sampleLen) {
sampleVaild=true;
@ -723,12 +665,12 @@ void DivPlatformES5506::tick(bool sysTick) {
// get loop mode, transwave loop
double loopStart=(double)s->loopStart;
double loopEnd=(double)s->loopEnd;
DivSampleLoopMode loopMode=s->isLoopable()?s->loopMode:DIV_SAMPLE_LOOPMODE_ONESHOT;
DivSampleLoopMode loopMode=s->isLoopable()?s->loopMode:DIV_SAMPLE_LOOP_MAX;
if (ins->amiga.transWave.enable) {
if (transWaveInd.loopMode!=DIV_SAMPLE_LOOPMODE_ONESHOT) {
if (transWaveInd.loopMode!=DIV_SAMPLE_LOOP_MAX) {
loopMode=transWaveInd.loopMode;
} else if ((chan[i].pcm.loopMode==DIV_SAMPLE_LOOPMODE_ONESHOT) || (!s->isLoopable())) { // default
loopMode=DIV_SAMPLE_LOOPMODE_PINGPONG;
} else if ((chan[i].pcm.loopMode==DIV_SAMPLE_LOOP_MAX) || (!s->isLoopable())) { // default
loopMode=DIV_SAMPLE_LOOP_PINGPONG;
}
// get loop position
loopStart=(double)transWaveInd.loopStart;
@ -805,8 +747,8 @@ void DivPlatformES5506::tick(bool sysTick) {
}
if (chan[i].pcmChanged.position) {
if (!chan[i].keyOn) {
pageWrite(0x20|i,0x01,(chan[i].pcm.loopMode==DIV_SAMPLE_LOOPMODE_ONESHOT)?chan[i].pcm.start:chan[i].pcm.loopStart);
pageWrite(0x20|i,0x02,(chan[i].pcm.loopMode==DIV_SAMPLE_LOOPMODE_ONESHOT)?chan[i].pcm.end:chan[i].pcm.loopEnd);
pageWrite(0x20|i,0x01,(chan[i].pcm.loopMode==DIV_SAMPLE_LOOP_MAX)?chan[i].pcm.start:chan[i].pcm.loopStart);
pageWrite(0x20|i,0x02,(chan[i].pcm.loopMode==DIV_SAMPLE_LOOP_MAX)?chan[i].pcm.end:chan[i].pcm.loopEnd);
}
chan[i].pcmChanged.position=0;
}
@ -815,17 +757,17 @@ void DivPlatformES5506::tick(bool sysTick) {
unsigned int loopFlag=(chan[i].pcm.bank<<14)|(chan[i].pcm.reversed?0x0040:0x0000);
chan[i].isReverseLoop=false;
switch (chan[i].pcm.loopMode) {
case DIV_SAMPLE_LOOPMODE_ONESHOT: // One shot (no loop)
case DIV_SAMPLE_LOOP_MAX: // One shot (no loop)
default:
break;
case DIV_SAMPLE_LOOPMODE_FORWARD: // Foward loop
case DIV_SAMPLE_LOOP_FORWARD: // Foward loop
loopFlag|=0x0008;
break;
case DIV_SAMPLE_LOOPMODE_BACKWARD: // Backward loop: IRQ enable
case DIV_SAMPLE_LOOP_BACKWARD: // Backward loop: IRQ enable
loopFlag|=0x0038;
chan[i].isReverseLoop=true;
break;
case DIV_SAMPLE_LOOPMODE_PINGPONG: // Pingpong loop: Hardware support
case DIV_SAMPLE_LOOP_PINGPONG: // Pingpong loop: Hardware support
loopFlag|=0x0018;
break;
}
@ -844,14 +786,14 @@ void DivPlatformES5506::tick(bool sysTick) {
pageWriteMask(0x00|i,0x5f,0x00,(chan[i].filter.mode<<8),0x0300);
}
if (chan[i].filterChanged.k2) {
if (chan[i].std.ex2.mode!=1) { // Relative
if (chan[i].std.ex2.mode!=0) { // Relative
k2=CLAMP(chan[i].filter.k2+chan[i].k2Offs,0,65535);
} else {
k2=chan[i].filter.k2;
}
}
if (chan[i].filterChanged.k1) {
if (chan[i].std.ex1.mode!=1) { // Relative
if (chan[i].std.ex1.mode!=0) { // Relative
k1=CLAMP(chan[i].filter.k1+chan[i].k1Offs,0,65535);
} else {
k1=chan[i].filter.k1;
@ -921,8 +863,8 @@ void DivPlatformES5506::tick(bool sysTick) {
pageWrite(0x00|i,0x07,0xffff); // Set K1 and K2 to 0xffff
pageWrite(0x00|i,0x09,0xffff,~0,(chanMax+1)*4*2); // needs to 4 sample period delay
pageWrite(0x00|i,0x01,chan[i].freq);
pageWrite(0x20|i,0x01,(chan[i].pcm.loopMode==DIV_SAMPLE_LOOPMODE_ONESHOT)?chan[i].pcm.start:chan[i].pcm.loopStart);
pageWrite(0x20|i,0x02,(chan[i].pcm.loopMode==DIV_SAMPLE_LOOPMODE_ONESHOT)?chan[i].pcm.end:chan[i].pcm.loopEnd);
pageWrite(0x20|i,0x01,(chan[i].pcm.loopMode==DIV_SAMPLE_LOOP_MAX)?chan[i].pcm.start:chan[i].pcm.loopStart);
pageWrite(0x20|i,0x02,(chan[i].pcm.loopMode==DIV_SAMPLE_LOOP_MAX)?chan[i].pcm.end:chan[i].pcm.loopEnd);
// initialize envelope
pageWrite(0x00|i,0x03,((unsigned char)chan[i].envelope.lVRamp)<<8);
pageWrite(0x00|i,0x05,((unsigned char)chan[i].envelope.rVRamp)<<8);
@ -930,14 +872,14 @@ void DivPlatformES5506::tick(bool sysTick) {
pageWrite(0x00|i,0x08,(((unsigned char)chan[i].envelope.k2Ramp)<<8)|(chan[i].envelope.k2Slow?1:0));
// initialize filter
pageWriteMask(0x00|i,0x5f,0x00,(chan[i].pcm.bank<<14)|(chan[i].filter.mode<<8),0xc300);
if ((chan[i].std.ex2.mode!=1) && (chan[i].std.ex2.had)) {
if ((chan[i].std.ex2.mode!=0) && (chan[i].std.ex2.had)) {
k2=CLAMP(chan[i].filter.k2+chan[i].k2Offs,0,65535);
} else {
k2=chan[i].filter.k2;
}
pageWrite(0x00|i,0x07,k2);
chan[i].k2Prev=k2;
if ((chan[i].std.ex1.mode!=1) && (chan[i].std.ex1.had)) {
if ((chan[i].std.ex1.mode!=0) && (chan[i].std.ex1.had)) {
k1=CLAMP(chan[i].filter.k1+chan[i].k1Offs,0,65535);
} else {
k1=chan[i].filter.k1;
@ -949,17 +891,17 @@ void DivPlatformES5506::tick(bool sysTick) {
unsigned int loopFlag=chan[i].pcm.reversed?0x0040:0x0000;
chan[i].isReverseLoop=false;
switch (chan[i].pcm.loopMode) {
case DIV_SAMPLE_LOOPMODE_ONESHOT: // One shot (no loop)
case DIV_SAMPLE_LOOP_MAX: // One shot (no loop)
default:
break;
case DIV_SAMPLE_LOOPMODE_FORWARD: // Foward loop
case DIV_SAMPLE_LOOP_FORWARD: // Foward loop
loopFlag|=0x0008;
break;
case DIV_SAMPLE_LOOPMODE_BACKWARD: // Backward loop: IRQ enable
case DIV_SAMPLE_LOOP_BACKWARD: // Backward loop: IRQ enable
loopFlag|=0x0038;
chan[i].isReverseLoop=true;
break;
case DIV_SAMPLE_LOOPMODE_PINGPONG: // Pingpong loop: Hardware support
case DIV_SAMPLE_LOOP_PINGPONG: // Pingpong loop: Hardware support
loopFlag|=0x0018;
break;
}
@ -1001,13 +943,13 @@ int DivPlatformES5506::dispatch(DivCommand c) {
if (((ins->amiga.useNoteMap && !ins->amiga.transWave.enable) && (c.value>=0 && c.value<120)) ||
((!ins->amiga.useNoteMap && ins->amiga.transWave.enable) && (ins->amiga.transWave.ind>=0 && ins->amiga.transWave.ind<(int)ins->amiga.transWaveMap.size())) ||
((!ins->amiga.useNoteMap && !ins->amiga.transWave.enable) && (ins->amiga.initSample>=0 && ins->amiga.initSample<parent->song.sampleLen))) {
DivInstrumentAmiga::NoteMap& noteMapind=ins->amiga.noteMap[c.value];
DivInstrumentAmiga::SampleMap& noteMapind=ins->amiga.noteMap[c.value];
DivInstrumentAmiga::TransWaveMap& transWaveInd=ins->amiga.transWaveMap[ins->amiga.transWave.ind];
int sample=ins->amiga.initSample;
if (ins->amiga.transWave.enable) {
sample=transWaveInd.ind;
} else if (ins->amiga.useNoteMap) {
sample=noteMapind.ind;
sample=noteMapind.map;
}
if (sample>=0 && sample<parent->song.sampleLen) {
sampleVaild=true;
@ -1033,12 +975,12 @@ int DivPlatformES5506::dispatch(DivCommand c) {
// get loop mode, transwave loop
double loopStart=(double)s->loopStart;
double loopEnd=(double)s->loopEnd;
DivSampleLoopMode loopMode=s->isLoopable()?s->loopMode:DIV_SAMPLE_LOOPMODE_ONESHOT;
DivSampleLoopMode loopMode=s->isLoopable()?s->loopMode:DIV_SAMPLE_LOOP_MAX;
if (ins->amiga.transWave.enable) {
if (transWaveInd.loopMode!=DIV_SAMPLE_LOOPMODE_ONESHOT) {
if (transWaveInd.loopMode!=DIV_SAMPLE_LOOP_MAX) {
loopMode=transWaveInd.loopMode;
} else if ((chan[c.chan].pcm.loopMode==DIV_SAMPLE_LOOPMODE_ONESHOT) || (!s->isLoopable())) { // default
loopMode=DIV_SAMPLE_LOOPMODE_PINGPONG;
} else if ((chan[c.chan].pcm.loopMode==DIV_SAMPLE_LOOP_MAX) || (!s->isLoopable())) { // default
loopMode=DIV_SAMPLE_LOOP_PINGPONG;
}
// get loop position
loopStart=(double)transWaveInd.loopStart;
@ -1093,10 +1035,10 @@ int DivPlatformES5506::dispatch(DivCommand c) {
chan[c.chan].outVol=(0xffff*chan[c.chan].vol)/0xff;
}
if (!chan[c.chan].std.panL.will) {
chan[c.chan].outLVol=(ins->es5506.lVol*chan[c.chan].lVol)/0xff;
chan[c.chan].outLVol=(0xffff*chan[c.chan].lVol)/0xff;
}
if (!chan[c.chan].std.panR.will) {
chan[c.chan].outRVol=(ins->es5506.rVol*chan[c.chan].rVol)/0xff;
chan[c.chan].outRVol=(0xffff*chan[c.chan].rVol)/0xff;
}
chan[c.chan].active=true;
chan[c.chan].keyOn=true;
@ -1142,7 +1084,7 @@ int DivPlatformES5506::dispatch(DivCommand c) {
if (chan[c.chan].lVol!=(unsigned int)(c.value)) {
chan[c.chan].lVol=c.value;
if (!chan[c.chan].std.panL.has) {
chan[c.chan].outLVol=(ins->es5506.lVol*c.value)/0xff;
chan[c.chan].outLVol=(0xffff*c.value)/0xff;
if (!isMuted[c.chan]) {
chan[c.chan].volChanged.lVol=1;
}
@ -1152,7 +1094,7 @@ int DivPlatformES5506::dispatch(DivCommand c) {
if (chan[c.chan].rVol!=(unsigned int)(c.value2)) {
chan[c.chan].rVol=c.value2;
if (!chan[c.chan].std.panR.has) {
chan[c.chan].outRVol=(ins->es5506.rVol*c.value2)/0xff;
chan[c.chan].outRVol=(0xffff*c.value2)/0xff;
if (!isMuted[c.chan]) {
chan[c.chan].volChanged.rVol=1;
}
@ -1336,6 +1278,8 @@ DivMacroInt* DivPlatformES5506::getChanMacroInt(int ch) {
void DivPlatformES5506::reset() {
while (!hostIntf32.empty()) hostIntf32.pop();
while (!hostIntf8.empty()) hostIntf8.pop();
while (!queuedRead.empty()) queuedRead.pop();
while (!queuedReadState.empty()) queuedReadState.pop();
for (int i=0; i<32; i++) {
chan[i]=DivPlatformES5506::Channel();
chan[i].std.setEngine(parent);