diff --git a/papers/format.md b/papers/format.md index e4b01d2f9..076729ec6 100644 --- a/papers/format.md +++ b/papers/format.md @@ -410,14 +410,14 @@ a connection is represented as an unsigned int in the following format: a port is in the following format (hexadecimal): `xxxy` -- `xxx` (bit 4 to 15) represents an entity. -- `y` (bit 0 to 3) is the port of that entity. +- `xxx` (bit 4 to 15) represents a portset. +- `y` (bit 0 to 3) is the port in that portset. -reserved input entities: +reserved input portsets: - `000`: system outputs -- `FFF`: "null" entity +- `FFF`: "null" portset -reserved output entities: +reserved output portsets: - `000` through `01F`: chip outputs # subsong diff --git a/src/engine/engine.cpp b/src/engine/engine.cpp index de04a1894..a99e443f9 100644 --- a/src/engine/engine.cpp +++ b/src/engine/engine.cpp @@ -1466,6 +1466,7 @@ void DivEngine::createNew(const char* description, String sysName, bool inBase64 BUSY_END; initDispatch(); BUSY_BEGIN; + autoPatchbay(); renderSamples(); reset(); BUSY_END; @@ -3773,6 +3774,26 @@ bool DivEngine::moveSampleDown(int which) { return true; } +void DivEngine::autoPatchbay() { + song.patchbay.clear(); + for (unsigned int i=0; igetOutputCount(); + if (outs>16) outs=16; + if (outs<2) { + for (unsigned int j=0; j=chans) return; BUSY_BEGIN; @@ -4333,6 +4354,7 @@ bool DivEngine::init() { } initDispatch(); + if (!hasLoadedSomething || song.version<135) autoPatchbay(); renderSamples(); reset(); active=true; diff --git a/src/engine/engine.h b/src/engine/engine.h index a06684d97..0e5147a0d 100644 --- a/src/engine/engine.h +++ b/src/engine/engine.h @@ -835,6 +835,9 @@ class DivEngine { bool moveWaveDown(int which); bool moveSampleDown(int which); + // automatic patchbay + void autoPatchbay(); + // play note void noteOn(int chan, int ins, int note, int vol=-1); diff --git a/src/engine/fileOps.cpp b/src/engine/fileOps.cpp index a2591f014..0503d03fb 100644 --- a/src/engine/fileOps.cpp +++ b/src/engine/fileOps.cpp @@ -987,6 +987,7 @@ bool DivEngine::loadDMF(unsigned char* file, size_t len) { if (active) { initDispatch(); BUSY_BEGIN; + autoPatchbay(); renderSamples(); reset(); BUSY_END; @@ -2584,6 +2585,7 @@ bool DivEngine::loadFur(unsigned char* file, size_t len) { if (active) { initDispatch(); BUSY_BEGIN; + if (song.version<135) autoPatchbay(); renderSamples(); reset(); BUSY_END; @@ -3006,6 +3008,7 @@ bool DivEngine::loadMod(unsigned char* file, size_t len) { if (active) { initDispatch(); BUSY_BEGIN; + autoPatchbay(); renderSamples(); reset(); BUSY_END; @@ -3176,7 +3179,7 @@ bool DivEngine::loadFC(unsigned char* file, size_t len) { ds.systemLen=1; ds.system[0]=DIV_SYSTEM_AMIGA; - ds.systemVol[0]=64; + ds.systemVol[0]=1.0f; ds.systemPan[0]=0; ds.systemFlags[0].set("clockSel",1); // PAL ds.systemFlags[0].set("stereoSep",80); @@ -3689,6 +3692,7 @@ bool DivEngine::loadFC(unsigned char* file, size_t len) { if (active) { initDispatch(); BUSY_BEGIN; + autoPatchbay(); renderSamples(); reset(); BUSY_END; diff --git a/src/engine/playback.cpp b/src/engine/playback.cpp index ad9a34709..f2c9098c9 100644 --- a/src/engine/playback.cpp +++ b/src/engine/playback.cpp @@ -1720,30 +1720,53 @@ void DivEngine::nextBuf(float** in, float** out, int inChans, int outChans, unsi disCont[i].fillBuf(disCont[i].runtotal,disCont[i].lastAvail,size-disCont[i].lastAvail); } - // TODO: patchbay - for (int i=0; igetPostAmp(); - volR*=disCont[i].dispatch->getPostAmp(); - if (disCont[i].dispatch->getOutputCount()>1) { - for (size_t j=0; jgetOutputCount()); - for (int k=0; k>16; + const unsigned short destPort=i&0xffff; + + const unsigned short srcPortSet=srcPort>>4; + const unsigned short destPortSet=destPort>>4; + const unsigned char srcSubPort=srcPort&15; + const unsigned char destSubPort=destPort&15; + + // null portset + if (destPortSet==0xfff) continue; + + // system outputs + if (destPortSet==0x000) { + if (destSubPort>=outChans) continue; + + // chip outputs + if (srcPortSetgetOutputCount()) { + float vol=song.systemVol[srcPortSet]*disCont[srcPortSet].dispatch->getPostAmp()*song.masterVol; + + switch (destSubPort&3) { + case 0: + vol*=MIN(1.0f,1.0f-song.systemPan[srcPortSet])*MIN(1.0f,1.0f-song.systemPanFR[srcPortSet]); + break; + case 1: + vol*=MIN(1.0f,1.0f+song.systemPan[srcPortSet])*MIN(1.0f,1.0f-song.systemPanFR[srcPortSet]); + break; + case 2: + vol*=MIN(1.0f,1.0f-song.systemPan[srcPortSet])*MIN(1.0f,1.0f+song.systemPanFR[srcPortSet]); + break; + case 3: + vol*=MIN(1.0f,1.0f+song.systemPan[srcPortSet])*MIN(1.0f,1.0f+song.systemPanFR[srcPortSet]); + break; + } + + for (size_t j=0; j