Merge branch 'master' into feature/esfm
This commit is contained in:
commit
56d774bb3b
123 changed files with 2732 additions and 707 deletions
|
|
@ -81,7 +81,18 @@ const char** DivPlatformAmiga::getRegisterSheet() {
|
|||
|
||||
void DivPlatformAmiga::acquire(short** buf, size_t len) {
|
||||
thread_local int outL, outR, output;
|
||||
|
||||
for (size_t h=0; h<len; h++) {
|
||||
if (--delay<0) delay=0;
|
||||
if (!writes.empty() && delay<=0) {
|
||||
QueuedWrite w=writes.front();
|
||||
|
||||
if (w.addr==0x96 && !(w.val&0x8000)) delay=4096/AMIGA_DIVIDER;
|
||||
|
||||
amiga.write(w.addr,w.val);
|
||||
writes.pop();
|
||||
}
|
||||
|
||||
bool hsync=bypassLimits;
|
||||
outL=0;
|
||||
outR=0;
|
||||
|
|
@ -99,7 +110,8 @@ void DivPlatformAmiga::acquire(short** buf, size_t len) {
|
|||
}
|
||||
for (int i=0; i<4; i++) {
|
||||
// run DMA
|
||||
if (amiga.dmaEn && amiga.audEn[i] && !amiga.audIr[i]) {
|
||||
if (amiga.audEn[i]) amiga.mustDMA[i]=true;
|
||||
if (amiga.dmaEn && amiga.mustDMA[i] && !amiga.audIr[i]) {
|
||||
amiga.audTick[i]-=AMIGA_DIVIDER;
|
||||
if (amiga.audTick[i]<0) {
|
||||
amiga.audTick[i]+=MAX(AMIGA_DIVIDER,amiga.audPer[i]);
|
||||
|
|
@ -114,6 +126,8 @@ void DivPlatformAmiga::acquire(short** buf, size_t len) {
|
|||
amiga.audWord[i]=!amiga.audWord[i];
|
||||
}
|
||||
|
||||
amiga.mustDMA[i]=amiga.audEn[i];
|
||||
|
||||
amiga.audByte[i]=!amiga.audByte[i];
|
||||
if (!amiga.audByte[i] && (amiga.useV[i] || amiga.useP[i])) {
|
||||
amiga.nextOut2[i]=((unsigned char)amiga.audDat[0][i])<<8|((unsigned char)amiga.audDat[1][i]);
|
||||
|
|
@ -130,7 +144,7 @@ void DivPlatformAmiga::acquire(short** buf, size_t len) {
|
|||
amiga.audPer[i+1]=amiga.nextOut2[i];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
} else if (!amiga.useV[i] && !amiga.useP[i]) {
|
||||
amiga.nextOut[i]=amiga.audDat[amiga.audByte[i]][i];
|
||||
}
|
||||
}
|
||||
|
|
@ -154,12 +168,12 @@ void DivPlatformAmiga::acquire(short** buf, size_t len) {
|
|||
|
||||
// output
|
||||
if (!isMuted[i]) {
|
||||
if (amiga.audVol[i]>=64) {
|
||||
if ((amiga.audVol[i]&127)>=64) {
|
||||
output=amiga.nextOut[i]<<6;
|
||||
} else if (amiga.audVol[i]<=0) {
|
||||
} else if ((amiga.audVol[i]&127)==0) {
|
||||
output=0;
|
||||
} else {
|
||||
output=amiga.nextOut[i]*volTable[amiga.audVol[i]][amiga.volPos];
|
||||
output=amiga.nextOut[i]*volTable[amiga.audVol[i]&63][amiga.volPos];
|
||||
}
|
||||
if (i==0 || i==3) {
|
||||
outL+=(output*sep1)>>7;
|
||||
|
|
@ -168,7 +182,7 @@ void DivPlatformAmiga::acquire(short** buf, size_t len) {
|
|||
outL+=(output*sep2)>>7;
|
||||
outR+=(output*sep1)>>7;
|
||||
}
|
||||
oscBuf[i]->data[oscBuf[i]->needle++]=(amiga.nextOut[i]*MIN(64,amiga.audVol[i]))<<1;
|
||||
oscBuf[i]->data[oscBuf[i]->needle++]=(amiga.nextOut[i]*MIN(64,amiga.audVol[i]&127))<<1;
|
||||
} else {
|
||||
oscBuf[i]->data[oscBuf[i]->needle++]=0;
|
||||
}
|
||||
|
|
@ -190,11 +204,6 @@ void DivPlatformAmiga::irq(int ch) {
|
|||
if (chan[ch].irLocL==0x400 && chan[ch].irLocH==0 && chan[ch].irLen==1) {
|
||||
// turn off DMA
|
||||
rWrite(0x96,1<<ch);
|
||||
} else {
|
||||
// write latched loc/len
|
||||
chWrite(ch,0,chan[ch].irLocH);
|
||||
chWrite(ch,2,chan[ch].irLocL);
|
||||
chWrite(ch,4,chan[ch].irLen);
|
||||
}
|
||||
|
||||
// acknowledge interrupt
|
||||
|
|
@ -202,111 +211,96 @@ void DivPlatformAmiga::irq(int ch) {
|
|||
}
|
||||
|
||||
#define UPDATE_DMA(x) \
|
||||
amiga.dmaLen[x]=amiga.audLen[x]; \
|
||||
amiga.dmaLoc[x]=amiga.audLoc[x]; \
|
||||
amiga.audByte[x]=true; \
|
||||
amiga.audTick[x]=0;
|
||||
dmaLen[x]=audLen[x]; \
|
||||
dmaLoc[x]=audLoc[x]; \
|
||||
audByte[x]=true; \
|
||||
audTick[x]=0;
|
||||
|
||||
void DivPlatformAmiga::rWrite(unsigned short addr, unsigned short val) {
|
||||
void DivPlatformAmiga::Amiga::write(unsigned short addr, unsigned short val) {
|
||||
if (addr&1) return;
|
||||
|
||||
//logV("%.3x = %.4x",addr,val);
|
||||
regPool[addr>>1]=val;
|
||||
|
||||
if (!skipRegisterWrites && dumpWrites) {
|
||||
addWrite(addr,val);
|
||||
}
|
||||
|
||||
switch (addr&0x1fe) {
|
||||
case 0x96: { // DMACON
|
||||
if (val&32768) {
|
||||
if (val&1) amiga.audEn[0]=true;
|
||||
if (val&2) amiga.audEn[1]=true;
|
||||
if (val&4) amiga.audEn[2]=true;
|
||||
if (val&8) amiga.audEn[3]=true;
|
||||
if (val&512) amiga.dmaEn=true;
|
||||
if (val&1) audEn[0]=true;
|
||||
if (val&2) audEn[1]=true;
|
||||
if (val&4) audEn[2]=true;
|
||||
if (val&8) audEn[3]=true;
|
||||
if (val&512) dmaEn=true;
|
||||
} else {
|
||||
if (val&1) {
|
||||
amiga.audEn[0]=false;
|
||||
UPDATE_DMA(0);
|
||||
audEn[0]=false;
|
||||
}
|
||||
if (val&2) {
|
||||
amiga.audEn[1]=false;
|
||||
UPDATE_DMA(1);
|
||||
audEn[1]=false;
|
||||
}
|
||||
if (val&4) {
|
||||
amiga.audEn[2]=false;
|
||||
UPDATE_DMA(2);
|
||||
audEn[2]=false;
|
||||
}
|
||||
if (val&8) {
|
||||
amiga.audEn[3]=false;
|
||||
UPDATE_DMA(3);
|
||||
audEn[3]=false;
|
||||
}
|
||||
if (val&512) {
|
||||
amiga.dmaEn=false;
|
||||
dmaEn=false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 0x9a: { // INTENA
|
||||
if (val&32768) {
|
||||
if (val&128) amiga.audInt[0]=true;
|
||||
if (val&256) amiga.audInt[1]=true;
|
||||
if (val&512) amiga.audInt[2]=true;
|
||||
if (val&1024) amiga.audInt[3]=true;
|
||||
if (val&128) audInt[0]=true;
|
||||
if (val&256) audInt[1]=true;
|
||||
if (val&512) audInt[2]=true;
|
||||
if (val&1024) audInt[3]=true;
|
||||
} else {
|
||||
if (val&128) amiga.audInt[0]=false;
|
||||
if (val&256) amiga.audInt[1]=false;
|
||||
if (val&512) amiga.audInt[2]=false;
|
||||
if (val&1024) amiga.audInt[3]=false;
|
||||
if (val&128) audInt[0]=false;
|
||||
if (val&256) audInt[1]=false;
|
||||
if (val&512) audInt[2]=false;
|
||||
if (val&1024) audInt[3]=false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 0x9c: { // INTREQ
|
||||
if (val&32768) {
|
||||
if (val&128) {
|
||||
amiga.audIr[0]=true;
|
||||
irq(0);
|
||||
audIr[0]=true;
|
||||
}
|
||||
if (val&256) {
|
||||
amiga.audIr[1]=true;
|
||||
irq(1);
|
||||
audIr[1]=true;
|
||||
}
|
||||
if (val&512) {
|
||||
amiga.audIr[2]=true;
|
||||
irq(2);
|
||||
audIr[2]=true;
|
||||
}
|
||||
if (val&1024) {
|
||||
amiga.audIr[3]=true;
|
||||
irq(3);
|
||||
audIr[3]=true;
|
||||
}
|
||||
} else {
|
||||
if (val&128) amiga.audIr[0]=false;
|
||||
if (val&256) amiga.audIr[1]=false;
|
||||
if (val&512) amiga.audIr[2]=false;
|
||||
if (val&1024) amiga.audIr[3]=false;
|
||||
if (val&128) audIr[0]=false;
|
||||
if (val&256) audIr[1]=false;
|
||||
if (val&512) audIr[2]=false;
|
||||
if (val&1024) audIr[3]=false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 0x9e: { // ADKCON
|
||||
if (val&32768) {
|
||||
if (val&1) amiga.useV[0]=true;
|
||||
if (val&2) amiga.useV[1]=true;
|
||||
if (val&4) amiga.useV[2]=true;
|
||||
if (val&8) amiga.useV[3]=true;
|
||||
if (val&16) amiga.useP[0]=true;
|
||||
if (val&32) amiga.useP[1]=true;
|
||||
if (val&64) amiga.useP[2]=true;
|
||||
if (val&128) amiga.useP[3]=true;
|
||||
if (val&1) useV[0]=true;
|
||||
if (val&2) useV[1]=true;
|
||||
if (val&4) useV[2]=true;
|
||||
if (val&8) useV[3]=true;
|
||||
if (val&16) useP[0]=true;
|
||||
if (val&32) useP[1]=true;
|
||||
if (val&64) useP[2]=true;
|
||||
if (val&128) useP[3]=true;
|
||||
} else {
|
||||
if (val&1) amiga.useV[0]=false;
|
||||
if (val&2) amiga.useV[1]=false;
|
||||
if (val&4) amiga.useV[2]=false;
|
||||
if (val&8) amiga.useV[3]=false;
|
||||
if (val&16) amiga.useP[0]=false;
|
||||
if (val&32) amiga.useP[1]=false;
|
||||
if (val&64) amiga.useP[2]=false;
|
||||
if (val&128) amiga.useP[3]=false;
|
||||
if (val&1) useV[0]=false;
|
||||
if (val&2) useV[1]=false;
|
||||
if (val&4) useV[2]=false;
|
||||
if (val&8) useV[3]=false;
|
||||
if (val&16) useP[0]=false;
|
||||
if (val&32) useP[1]=false;
|
||||
if (val&64) useP[2]=false;
|
||||
if (val&128) useP[3]=false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -316,31 +310,31 @@ void DivPlatformAmiga::rWrite(unsigned short addr, unsigned short val) {
|
|||
bool updateDMA=false;
|
||||
switch (addr&15) {
|
||||
case 0: // LCH
|
||||
amiga.audLoc[ch]&=0xffff;
|
||||
amiga.audLoc[ch]|=val<<16;
|
||||
audLoc[ch]&=0xffff;
|
||||
audLoc[ch]|=val<<16;
|
||||
updateDMA=true;
|
||||
break;
|
||||
case 2: // LCL
|
||||
amiga.audLoc[ch]&=0xffff0000;
|
||||
amiga.audLoc[ch]|=val&0xfffe;
|
||||
audLoc[ch]&=0xffff0000;
|
||||
audLoc[ch]|=val&0xfffe;
|
||||
updateDMA=true;
|
||||
break;
|
||||
case 4: // LEN
|
||||
amiga.audLen[ch]=val;
|
||||
audLen[ch]=val;
|
||||
updateDMA=true;
|
||||
break;
|
||||
case 6: // PER
|
||||
amiga.audPer[ch]=val;
|
||||
audPer[ch]=val;
|
||||
break;
|
||||
case 8: // VOL
|
||||
amiga.audVol[ch]=val;
|
||||
audVol[ch]=val;
|
||||
break;
|
||||
case 10: // DAT
|
||||
amiga.audDat[0][ch]=val&0xff;
|
||||
amiga.audDat[1][ch]=val>>8;
|
||||
audDat[0][ch]=val&0xff;
|
||||
audDat[1][ch]=val>>8;
|
||||
break;
|
||||
}
|
||||
if (updateDMA && !amiga.audEn[ch]) {
|
||||
if (updateDMA && !mustDMA[ch]) {
|
||||
UPDATE_DMA(ch);
|
||||
}
|
||||
}
|
||||
|
|
@ -349,6 +343,20 @@ void DivPlatformAmiga::rWrite(unsigned short addr, unsigned short val) {
|
|||
}
|
||||
}
|
||||
|
||||
void DivPlatformAmiga::rWrite(unsigned short addr, unsigned short val) {
|
||||
if (addr&1) return;
|
||||
|
||||
//logV("%.3x = %.4x",addr,val);
|
||||
if (!skipRegisterWrites) {
|
||||
writes.push(QueuedWrite(addr,val));
|
||||
regPool[addr>>1]=val;
|
||||
|
||||
if (dumpWrites) {
|
||||
addWrite(addr,val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DivPlatformAmiga::updateWave(int ch) {
|
||||
for (int i=0; i<MIN(256,(chan[ch].audLen<<1)); i++) {
|
||||
sampleMem[(ch<<8)|i]=chan[ch].ws.output[i]^0x80;
|
||||
|
|
@ -417,6 +425,13 @@ void DivPlatformAmiga::tick(bool sysTick) {
|
|||
|
||||
if (dmaOff) rWrite(0x96,dmaOff);
|
||||
|
||||
for (int i=0; i<4; i++) {
|
||||
if (chan[i].updateWave) {
|
||||
chan[i].updateWave=false;
|
||||
updateWave(i);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i=0; i<4; i++) {
|
||||
double off=1.0;
|
||||
if (!chan[i].useWave && chan[i].sample>=0 && chan[i].sample<parent->song.sampleLen) {
|
||||
|
|
@ -509,9 +524,16 @@ void DivPlatformAmiga::tick(bool sysTick) {
|
|||
if (dmaOn) rWrite(0x96,0x8000|dmaOn);
|
||||
|
||||
for (int i=0; i<4; i++) {
|
||||
if ((dmaOn&(1<<i)) && !chan[i].useWave && dumpWrites) {
|
||||
addWrite(0x200+i,(chan[i].irLocH<<16)|chan[i].irLocL);
|
||||
addWrite(0x204+i,chan[i].irLen);
|
||||
if ((dmaOn&(1<<i)) && !chan[i].useWave) {
|
||||
// write latched loc/len
|
||||
if (dumpWrites) {
|
||||
addWrite(0x200+i,(chan[i].irLocH<<16)|chan[i].irLocL);
|
||||
addWrite(0x204+i,chan[i].irLen);
|
||||
} else {
|
||||
chWrite(i,0,chan[i].irLocH);
|
||||
chWrite(i,2,chan[i].irLocL);
|
||||
chWrite(i,4,chan[i].irLen);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -520,10 +542,6 @@ void DivPlatformAmiga::tick(bool sysTick) {
|
|||
chan[i].writeVol=false;
|
||||
chWrite(i,8,chan[i].outVol);
|
||||
}
|
||||
if (chan[i].updateWave) {
|
||||
chan[i].updateWave=false;
|
||||
updateWave(i);
|
||||
}
|
||||
}
|
||||
|
||||
if (updateADKCon) {
|
||||
|
|
@ -720,6 +738,7 @@ void DivPlatformAmiga::forceIns() {
|
|||
for (int i=0; i<4; i++) {
|
||||
chan[i].insChanged=true;
|
||||
chan[i].freqChanged=true;
|
||||
chan[i].writeVol=true;
|
||||
/*chan[i].keyOn=false;
|
||||
chan[i].keyOff=false;
|
||||
chan[i].sample=-1;*/
|
||||
|
|
@ -738,6 +757,7 @@ DivDispatchOscBuffer* DivPlatformAmiga::getOscBuffer(int ch) {
|
|||
}
|
||||
|
||||
void DivPlatformAmiga::reset() {
|
||||
writes.clear();
|
||||
memset(regPool,0,256*sizeof(unsigned short));
|
||||
for (int i=0; i<4; i++) {
|
||||
chan[i]=DivPlatformAmiga::Channel();
|
||||
|
|
@ -750,6 +770,7 @@ void DivPlatformAmiga::reset() {
|
|||
filterOn=false;
|
||||
filtConst=filterOn?filtConstOn:filtConstOff;
|
||||
updateADKCon=true;
|
||||
delay=0;
|
||||
|
||||
amiga=Amiga();
|
||||
// enable DMA
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
#define _AMIGA_H
|
||||
|
||||
#include "../dispatch.h"
|
||||
#include "../../fixedQueue.h"
|
||||
#include "../waveSynth.h"
|
||||
|
||||
class DivPlatformAmiga: public DivDispatch {
|
||||
|
|
@ -59,12 +60,14 @@ class DivPlatformAmiga: public DivDispatch {
|
|||
bool amigaModel;
|
||||
bool filterOn;
|
||||
bool updateADKCon;
|
||||
short delay;
|
||||
|
||||
struct Amiga {
|
||||
// register state
|
||||
bool audInt[4]; // interrupt on
|
||||
bool audIr[4]; // interrupt request
|
||||
bool audEn[4]; // audio DMA on
|
||||
bool mustDMA[4]; // audio DMA must run
|
||||
bool useP[4]; // period modulation
|
||||
bool useV[4]; // volume modulation
|
||||
|
||||
|
|
@ -91,6 +94,8 @@ class DivPlatformAmiga: public DivDispatch {
|
|||
unsigned short hPos; // horizontal position of beam
|
||||
unsigned char state[4]; // current channel state
|
||||
|
||||
void write(unsigned short addr, unsigned short val);
|
||||
|
||||
Amiga() {
|
||||
memset(this,0,sizeof(*this));
|
||||
}
|
||||
|
|
@ -113,6 +118,14 @@ class DivPlatformAmiga: public DivDispatch {
|
|||
|
||||
int sep1, sep2;
|
||||
|
||||
struct QueuedWrite {
|
||||
unsigned short addr;
|
||||
unsigned short val;
|
||||
QueuedWrite(): addr(0), val(9) {}
|
||||
QueuedWrite(unsigned short a, unsigned short v): addr(a), val(v) {}
|
||||
};
|
||||
FixedQueue<QueuedWrite,512> writes;
|
||||
|
||||
friend void putDispatchChip(void*,int);
|
||||
friend void putDispatchChan(void*,int,int);
|
||||
friend class DivExportAmigaValidation;
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
#include "c64.h"
|
||||
#include "../engine.h"
|
||||
#include "sound/c64_fp/siddefs-fp.h"
|
||||
#include "IconsFontAwesome4.h"
|
||||
#include <math.h>
|
||||
#include "../../ta-log.h"
|
||||
|
||||
|
|
@ -158,21 +159,10 @@ void DivPlatformC64::tick(bool sysTick) {
|
|||
|
||||
chan[i].std.next();
|
||||
if (chan[i].std.vol.had) {
|
||||
DivInstrument* ins=parent->getIns(chan[i].ins,DIV_INS_C64);
|
||||
if (ins->c64.volIsCutoff) {
|
||||
if (ins->c64.filterIsAbs) {
|
||||
filtCut=MIN(2047,chan[i].std.vol.val);
|
||||
} else {
|
||||
filtCut-=((signed char)chan[i].std.vol.val)*7;
|
||||
if (filtCut>2047) filtCut=2047;
|
||||
if (filtCut<0) filtCut=0;
|
||||
}
|
||||
willUpdateFilter=true;
|
||||
} else {
|
||||
vol=MIN(15,chan[i].std.vol.val);
|
||||
willUpdateFilter=true;
|
||||
}
|
||||
vol=MIN(15,chan[i].std.vol.val);
|
||||
willUpdateFilter=true;
|
||||
}
|
||||
|
||||
if (NEW_ARP_STRAT) {
|
||||
chan[i].handleArp();
|
||||
} else if (chan[i].std.arp.had) {
|
||||
|
|
@ -186,14 +176,18 @@ void DivPlatformC64::tick(bool sysTick) {
|
|||
if (ins->c64.dutyIsAbs) {
|
||||
chan[i].duty=chan[i].std.duty.val;
|
||||
} else {
|
||||
chan[i].duty-=((signed char)chan[i].std.duty.val)*4;
|
||||
if (multiplyRel) {
|
||||
chan[i].duty-=((signed char)chan[i].std.duty.val)*4;
|
||||
} else {
|
||||
chan[i].duty-=chan[i].std.duty.val;
|
||||
}
|
||||
}
|
||||
rWrite(i*7+2,chan[i].duty&0xff);
|
||||
rWrite(i*7+3,chan[i].duty>>8);
|
||||
}
|
||||
if (chan[i].std.wave.had) {
|
||||
chan[i].wave=chan[i].std.wave.val;
|
||||
rWrite(i*7+4,(chan[i].wave<<4)|(chan[i].test<<3)|(chan[i].ring<<2)|(chan[i].sync<<1)|(int)(chan[i].active));
|
||||
rWrite(i*7+4,(chan[i].wave<<4)|(chan[i].test<<3)|(chan[i].ring<<2)|(chan[i].sync<<1)|(int)(chan[i].active && chan[i].gate));
|
||||
}
|
||||
if (chan[i].std.pitch.had) {
|
||||
if (chan[i].std.pitch.mode) {
|
||||
|
|
@ -204,6 +198,21 @@ void DivPlatformC64::tick(bool sysTick) {
|
|||
}
|
||||
chan[i].freqChanged=true;
|
||||
}
|
||||
if (chan[i].std.alg.had) { // new cutoff macro
|
||||
DivInstrument* ins=parent->getIns(chan[i].ins,DIV_INS_C64);
|
||||
if (ins->c64.filterIsAbs) {
|
||||
filtCut=MIN(2047,chan[i].std.alg.val);
|
||||
} else {
|
||||
if (multiplyRel) {
|
||||
filtCut+=((signed char)chan[i].std.alg.val)*7;
|
||||
} else {
|
||||
filtCut+=chan[i].std.alg.val;
|
||||
}
|
||||
if (filtCut>2047) filtCut=2047;
|
||||
if (filtCut<0) filtCut=0;
|
||||
}
|
||||
willUpdateFilter=true;
|
||||
}
|
||||
if (chan[i].std.ex1.had) {
|
||||
filtControl=chan[i].std.ex1.val&15;
|
||||
willUpdateFilter=true;
|
||||
|
|
@ -212,15 +221,33 @@ void DivPlatformC64::tick(bool sysTick) {
|
|||
filtRes=chan[i].std.ex2.val&15;
|
||||
willUpdateFilter=true;
|
||||
}
|
||||
if (chan[i].std.ex3.had) {
|
||||
chan[i].sync=chan[i].std.ex3.val&1;
|
||||
chan[i].ring=chan[i].std.ex3.val&2;
|
||||
chan[i].freqChanged=true;
|
||||
rWrite(i*7+4,(chan[i].wave<<4)|(chan[i].test<<3)|(chan[i].ring<<2)|(chan[i].sync<<1)|(int)(chan[i].active));
|
||||
}
|
||||
if (chan[i].std.ex4.had) {
|
||||
chan[i].test=chan[i].std.ex4.val&1;
|
||||
rWrite(i*7+4,(chan[i].wave<<4)|(chan[i].test<<3)|(chan[i].ring<<2)|(chan[i].sync<<1)|(int)(chan[i].active));
|
||||
chan[i].gate=chan[i].std.ex4.val&1;
|
||||
chan[i].sync=chan[i].std.ex4.val&2;
|
||||
chan[i].ring=chan[i].std.ex4.val&4;
|
||||
chan[i].test=chan[i].std.ex4.val&8;
|
||||
chan[i].freqChanged=true;
|
||||
rWrite(i*7+4,(chan[i].wave<<4)|(chan[i].test<<3)|(chan[i].ring<<2)|(chan[i].sync<<1)|(int)(chan[i].active && chan[i].gate));
|
||||
}
|
||||
|
||||
if (chan[i].std.ex5.had) {
|
||||
chan[i].attack=chan[i].std.ex5.val&15;
|
||||
rWrite(i*7+5,(chan[i].attack<<4)|(chan[i].decay));
|
||||
}
|
||||
|
||||
if (chan[i].std.ex6.had) {
|
||||
chan[i].decay=chan[i].std.ex6.val&15;
|
||||
rWrite(i*7+5,(chan[i].attack<<4)|(chan[i].decay));
|
||||
}
|
||||
|
||||
if (chan[i].std.ex7.had) {
|
||||
chan[i].sustain=chan[i].std.ex7.val&15;
|
||||
rWrite(i*7+6,(chan[i].sustain<<4)|(chan[i].release));
|
||||
}
|
||||
|
||||
if (chan[i].std.ex8.had) {
|
||||
chan[i].release=chan[i].std.ex8.val&15;
|
||||
rWrite(i*7+6,(chan[i].sustain<<4)|(chan[i].release));
|
||||
}
|
||||
|
||||
if (sysTick) {
|
||||
|
|
@ -243,7 +270,7 @@ void DivPlatformC64::tick(bool sysTick) {
|
|||
if (chan[i].keyOn) {
|
||||
rWrite(i*7+5,(chan[i].attack<<4)|(chan[i].decay));
|
||||
rWrite(i*7+6,(chan[i].sustain<<4)|(chan[i].release));
|
||||
rWrite(i*7+4,(chan[i].wave<<4)|(chan[i].test<<3)|(chan[i].ring<<2)|(chan[i].sync<<1)|1);
|
||||
rWrite(i*7+4,(chan[i].wave<<4)|(chan[i].test<<3)|(chan[i].ring<<2)|(chan[i].sync<<1)|(chan[i].gate?1:0));
|
||||
}
|
||||
if (chan[i].keyOff) {
|
||||
rWrite(i*7+5,(chan[i].attack<<4)|(chan[i].decay));
|
||||
|
|
@ -387,7 +414,7 @@ int DivPlatformC64::dispatch(DivCommand c) {
|
|||
break;
|
||||
case DIV_CMD_WAVE:
|
||||
chan[c.chan].wave=c.value;
|
||||
rWrite(c.chan*7+4,(chan[c.chan].wave<<4)|(chan[c.chan].test<<3)|(chan[c.chan].ring<<2)|(chan[c.chan].sync<<1)|(int)(chan[c.chan].active));
|
||||
rWrite(c.chan*7+4,(chan[c.chan].wave<<4)|(chan[c.chan].test<<3)|(chan[c.chan].ring<<2)|(chan[c.chan].sync<<1)|(int)(chan[c.chan].active && chan[c.chan].gate));
|
||||
break;
|
||||
case DIV_CMD_LEGATO:
|
||||
chan[c.chan].baseFreq=NOTE_FREQUENCY(c.value+((HACKY_LEGATO_MESS)?(chan[c.chan].std.arp.val):(0)));
|
||||
|
|
@ -396,7 +423,7 @@ int DivPlatformC64::dispatch(DivCommand c) {
|
|||
break;
|
||||
case DIV_CMD_PRE_PORTA:
|
||||
if (chan[c.chan].active && c.value2) {
|
||||
if (parent->song.resetMacroOnPorta || !chan[c.chan].inPorta) {
|
||||
if (parent->song.resetMacroOnPorta || parent->song.preNoteNoEffect) {
|
||||
chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_C64));
|
||||
chan[c.chan].keyOn=true;
|
||||
}
|
||||
|
|
@ -481,11 +508,11 @@ int DivPlatformC64::dispatch(DivCommand c) {
|
|||
break;
|
||||
case 4:
|
||||
chan[c.chan].ring=c.value;
|
||||
rWrite(c.chan*7+4,(chan[c.chan].wave<<4)|(chan[c.chan].test<<3)|(chan[c.chan].ring<<2)|(chan[c.chan].sync<<1)|(int)(chan[c.chan].active));
|
||||
rWrite(c.chan*7+4,(chan[c.chan].wave<<4)|(chan[c.chan].test<<3)|(chan[c.chan].ring<<2)|(chan[c.chan].sync<<1)|(int)(chan[c.chan].active && chan[c.chan].gate));
|
||||
break;
|
||||
case 5:
|
||||
chan[c.chan].sync=c.value;
|
||||
rWrite(c.chan*7+4,(chan[c.chan].wave<<4)|(chan[c.chan].test<<3)|(chan[c.chan].ring<<2)|(chan[c.chan].sync<<1)|(int)(chan[c.chan].active));
|
||||
rWrite(c.chan*7+4,(chan[c.chan].wave<<4)|(chan[c.chan].test<<3)|(chan[c.chan].ring<<2)|(chan[c.chan].sync<<1)|(int)(chan[c.chan].active && chan[c.chan].gate));
|
||||
break;
|
||||
case 6:
|
||||
filtControl&=7;
|
||||
|
|
@ -568,6 +595,24 @@ DivMacroInt* DivPlatformC64::getChanMacroInt(int ch) {
|
|||
return &chan[ch].std;
|
||||
}
|
||||
|
||||
DivChannelModeHints DivPlatformC64::getModeHints(int ch) {
|
||||
DivChannelModeHints ret;
|
||||
ret.count=1;
|
||||
ret.hint[0]=ICON_FA_BELL_SLASH_O;
|
||||
ret.type[0]=0;
|
||||
if (ch==2 && (filtControl&8)) {
|
||||
ret.type[0]=7;
|
||||
} else if (chan[ch].test && !chan[ch].gate) {
|
||||
ret.type[0]=5;
|
||||
} else if (chan[ch].test) {
|
||||
ret.type[0]=6;
|
||||
} else if (!chan[ch].gate) {
|
||||
ret.type[0]=4;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
DivDispatchOscBuffer* DivPlatformC64::getOscBuffer(int ch) {
|
||||
return oscBuf[ch];
|
||||
}
|
||||
|
|
@ -616,7 +661,18 @@ void DivPlatformC64::reset() {
|
|||
needInitTables=false;
|
||||
} else if (sidCore==1) {
|
||||
sid_fp->reset();
|
||||
sid_fp->clockSilent(16000);
|
||||
for (int i=0; i<3; i++) {
|
||||
sid_fp->write(i*7+5,testAD);
|
||||
sid_fp->write(i*7+6,testSR);
|
||||
sid_fp->write(i*7+4,8);
|
||||
}
|
||||
sid_fp->clockSilent(30000);
|
||||
for (int i=0; i<3; i++) {
|
||||
sid_fp->write(i*7+5,testAD);
|
||||
sid_fp->write(i*7+6,testSR);
|
||||
sid_fp->write(i*7+4,0);
|
||||
}
|
||||
sid_fp->clockSilent(30000);
|
||||
} else {
|
||||
sid->reset();
|
||||
}
|
||||
|
|
@ -627,7 +683,7 @@ void DivPlatformC64::reset() {
|
|||
filtControl=7;
|
||||
filtRes=0;
|
||||
filtCut=2047;
|
||||
resetTime=1;
|
||||
resetTime=initResetTime;
|
||||
vol=15;
|
||||
|
||||
chanOrder[0]=0;
|
||||
|
|
@ -675,8 +731,11 @@ void DivPlatformC64::setFlags(const DivConfig& flags) {
|
|||
}
|
||||
keyPriority=flags.getBool("keyPriority",true);
|
||||
no1EUpdate=flags.getBool("no1EUpdate",false);
|
||||
multiplyRel=flags.getBool("multiplyRel",false);
|
||||
testAD=((flags.getInt("testAttack",0)&15)<<4)|(flags.getInt("testDecay",0)&15);
|
||||
testSR=((flags.getInt("testSustain",0)&15)<<4)|(flags.getInt("testRelease",0)&15);
|
||||
initResetTime=flags.getInt("initResetTime",2);
|
||||
if (initResetTime<0) initResetTime=1;
|
||||
|
||||
// init fake filter table
|
||||
// taken from dSID
|
||||
|
|
|
|||
|
|
@ -26,13 +26,17 @@
|
|||
#include "sound/c64_fp/SID.h"
|
||||
#include "sound/c64_d/dsid.h"
|
||||
|
||||
// TODO:
|
||||
// - ex3 (special) unify with ex4 (gate/test)
|
||||
// - ex4 (test) compatibility
|
||||
|
||||
class DivPlatformC64: public DivDispatch {
|
||||
struct Channel: public SharedChannel<signed char> {
|
||||
int prevFreq, testWhen;
|
||||
unsigned char sweep, wave, attack, decay, sustain, release;
|
||||
short duty;
|
||||
bool sweepChanged, filter;
|
||||
bool resetMask, resetFilter, resetDuty, ring, sync, test;
|
||||
bool resetMask, resetFilter, resetDuty, gate, ring, sync, test;
|
||||
Channel():
|
||||
SharedChannel<signed char>(15),
|
||||
prevFreq(65535),
|
||||
|
|
@ -49,6 +53,7 @@ class DivPlatformC64: public DivDispatch {
|
|||
resetMask(false),
|
||||
resetFilter(false),
|
||||
resetDuty(false),
|
||||
gate(true),
|
||||
ring(false),
|
||||
sync(false),
|
||||
test(false) {}
|
||||
|
|
@ -70,9 +75,9 @@ class DivPlatformC64: public DivDispatch {
|
|||
unsigned char filtControl, filtRes, vol;
|
||||
unsigned char writeOscBuf;
|
||||
unsigned char sidCore;
|
||||
int filtCut, resetTime;
|
||||
int filtCut, resetTime, initResetTime;
|
||||
|
||||
bool keyPriority, sidIs6581, needInitTables, no1EUpdate;
|
||||
bool keyPriority, sidIs6581, needInitTables, no1EUpdate, multiplyRel;
|
||||
unsigned char chanOrder[3];
|
||||
unsigned char testAD, testSR;
|
||||
|
||||
|
|
@ -108,6 +113,7 @@ class DivPlatformC64: public DivDispatch {
|
|||
bool isVolGlobal();
|
||||
float getPostAmp();
|
||||
DivMacroInt* getChanMacroInt(int ch);
|
||||
DivChannelModeHints getModeHints(int chan);
|
||||
void notifyInsDeletion(void* ins);
|
||||
void poke(unsigned int addr, unsigned short val);
|
||||
void poke(std::vector<DivRegWrite>& wlist);
|
||||
|
|
|
|||
|
|
@ -800,7 +800,7 @@ DivMacroInt* DivPlatformGenesisExt::getChanMacroInt(int ch) {
|
|||
}
|
||||
|
||||
unsigned short DivPlatformGenesisExt::getPan(int ch) {
|
||||
if (ch==csmChan) return 0;
|
||||
if (ch==4+csmChan) return 0;
|
||||
if (ch>=4+extChanOffs) return DivPlatformGenesis::getPan(ch-3);
|
||||
if (ch>=extChanOffs) {
|
||||
if (extMode) {
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
#include "pce.h"
|
||||
#include "../engine.h"
|
||||
#include "furIcons.h"
|
||||
#include <math.h>
|
||||
|
||||
//#define rWrite(a,v) pendingWrites[a]=v;
|
||||
|
|
@ -512,6 +513,18 @@ unsigned short DivPlatformPCE::getPan(int ch) {
|
|||
return ((chan[ch].pan&0xf0)<<4)|(chan[ch].pan&15);
|
||||
}
|
||||
|
||||
DivChannelModeHints DivPlatformPCE::getModeHints(int ch) {
|
||||
DivChannelModeHints ret;
|
||||
if (ch<4) return ret;
|
||||
ret.count=1;
|
||||
ret.hint[0]=ICON_FUR_NOISE;
|
||||
ret.type[0]=0;
|
||||
|
||||
if (chan[ch].noise) ret.type[0]=4;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
DivSamplePos DivPlatformPCE::getSamplePos(int ch) {
|
||||
if (ch>=6) return DivSamplePos();
|
||||
if (!chan[ch].pcm) return DivSamplePos();
|
||||
|
|
|
|||
|
|
@ -83,6 +83,7 @@ class DivPlatformPCE: public DivDispatch {
|
|||
void* getChanState(int chan);
|
||||
DivMacroInt* getChanMacroInt(int ch);
|
||||
unsigned short getPan(int chan);
|
||||
DivChannelModeHints getModeHints(int chan);
|
||||
DivSamplePos getSamplePos(int ch);
|
||||
DivDispatchOscBuffer* getOscBuffer(int chan);
|
||||
unsigned char* getRegisterPool();
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
#include "snes.h"
|
||||
#include "../engine.h"
|
||||
#include "../../ta-log.h"
|
||||
#include "furIcons.h"
|
||||
#include <math.h>
|
||||
|
||||
#define CHIP_FREQBASE 131072
|
||||
|
|
@ -710,6 +711,63 @@ DivChannelPair DivPlatformSNES::getPaired(int ch) {
|
|||
return DivChannelPair();
|
||||
}
|
||||
|
||||
DivChannelModeHints DivPlatformSNES::getModeHints(int ch) {
|
||||
DivChannelModeHints ret;
|
||||
ret.count=1;
|
||||
ret.hint[0]="-";
|
||||
ret.type[0]=0;
|
||||
|
||||
const SPC_DSP::voice_t* v=dsp.get_voice(ch);
|
||||
if (v!=NULL) {
|
||||
if (v->regs[5]&128) {
|
||||
switch (v->env_mode) {
|
||||
case SPC_DSP::env_attack:
|
||||
ret.hint[0]=ICON_FUR_ADSR_A;
|
||||
ret.type[0]=12;
|
||||
break;
|
||||
case SPC_DSP::env_decay:
|
||||
ret.hint[0]=ICON_FUR_ADSR_D;
|
||||
ret.type[0]=13;
|
||||
break;
|
||||
case SPC_DSP::env_sustain:
|
||||
ret.hint[0]=ICON_FUR_ADSR_S;
|
||||
ret.type[0]=14;
|
||||
break;
|
||||
case SPC_DSP::env_release:
|
||||
ret.hint[0]=ICON_FUR_ADSR_R;
|
||||
ret.type[0]=15;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (v->regs[7]&128) {
|
||||
switch (v->regs[7]&0x60) {
|
||||
case 0:
|
||||
ret.hint[0]=ICON_FUR_DEC_LINEAR;
|
||||
ret.type[0]=16;
|
||||
break;
|
||||
case 32:
|
||||
ret.hint[0]=ICON_FUR_DEC_EXP;
|
||||
ret.type[0]=17;
|
||||
break;
|
||||
case 64:
|
||||
ret.hint[0]=ICON_FUR_INC_LINEAR;
|
||||
ret.type[0]=18;
|
||||
break;
|
||||
case 96:
|
||||
ret.hint[0]=ICON_FUR_INC_BENT;
|
||||
ret.type[0]=19;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
ret.hint[0]=ICON_FUR_VOL_DIRECT;
|
||||
ret.type[0]=20;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
DivSamplePos DivPlatformSNES::getSamplePos(int ch) {
|
||||
if (ch>=8) return DivSamplePos();
|
||||
if (!chan[ch].active) return DivSamplePos();
|
||||
|
|
|
|||
|
|
@ -102,6 +102,7 @@ class DivPlatformSNES: public DivDispatch {
|
|||
DivMacroInt* getChanMacroInt(int ch);
|
||||
unsigned short getPan(int chan);
|
||||
DivChannelPair getPaired(int chan);
|
||||
DivChannelModeHints getModeHints(int chan);
|
||||
DivSamplePos getSamplePos(int ch);
|
||||
DivDispatchOscBuffer* getOscBuffer(int chan);
|
||||
unsigned char* getRegisterPool();
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@
|
|||
|
||||
#include "swan.h"
|
||||
#include "../engine.h"
|
||||
#include "furIcons.h"
|
||||
#include "IconsFontAwesome4.h"
|
||||
#include <math.h>
|
||||
|
||||
#define rWrite(a,v) if (!skipRegisterWrites) {writes.push(QueuedWrite(a,v)); if (dumpWrites) {addWrite(a,v);}}
|
||||
|
|
@ -480,6 +482,30 @@ unsigned short DivPlatformSwan::getPan(int ch) {
|
|||
return ((chan[ch].pan&0xf0)<<4)|(chan[ch].pan&15);
|
||||
}
|
||||
|
||||
DivChannelModeHints DivPlatformSwan::getModeHints(int ch) {
|
||||
DivChannelModeHints ret;
|
||||
|
||||
switch (ch) {
|
||||
case 1: // PCM
|
||||
ret.count=1;
|
||||
ret.hint[0]=ICON_FA_VOLUME_UP;
|
||||
ret.type[0]=pcm?4:0;
|
||||
break;
|
||||
case 2: // sweep
|
||||
ret.count=1;
|
||||
ret.hint[0]=ICON_FUR_SAW;
|
||||
ret.type[0]=sweep?2:0;
|
||||
break;
|
||||
case 3: // noise
|
||||
ret.count=1;
|
||||
ret.hint[0]=ICON_FUR_NOISE;
|
||||
ret.type[0]=noise?4:0;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
DivDispatchOscBuffer* DivPlatformSwan::getOscBuffer(int ch) {
|
||||
return oscBuf[ch];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@ class DivPlatformSwan: public DivDispatch {
|
|||
void* getChanState(int chan);
|
||||
DivMacroInt* getChanMacroInt(int ch);
|
||||
unsigned short getPan(int chan);
|
||||
DivChannelModeHints getModeHints(int chan);
|
||||
DivDispatchOscBuffer* getOscBuffer(int chan);
|
||||
unsigned char* getRegisterPool();
|
||||
int getRegisterPoolSize();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue