implement channel swapping

issue #378
This commit is contained in:
tildearrow 2022-04-28 03:36:15 -05:00
parent d211170e86
commit 859b2cf8db
5 changed files with 114 additions and 8 deletions

View file

@ -644,10 +644,79 @@ void DivEngine::createNew(const int* description) {
BUSY_END;
}
void DivEngine::changeSystem(int index, DivSystem which) {
void DivEngine::swapChannels(int src, int dest) {
logV("swapping channel %d with %d",src,dest);
if (src==dest) {
logV("not swapping channels because it's the same channel!",src,dest);
return;
}
for (int i=0; i<256; i++) {
song.orders.ord[dest][i]^=song.orders.ord[src][i];
song.orders.ord[src][i]^=song.orders.ord[dest][i];
song.orders.ord[dest][i]^=song.orders.ord[src][i];
DivPattern* prev=song.pat[src].data[i];
song.pat[src].data[i]=song.pat[dest].data[i];
song.pat[dest].data[i]=prev;
}
song.pat[src].effectCols^=song.pat[dest].effectCols;
song.pat[dest].effectCols^=song.pat[src].effectCols;
song.pat[src].effectCols^=song.pat[dest].effectCols;
}
void DivEngine::stompChannel(int ch) {
logV("stomping channel %d",ch);
for (int i=0; i<256; i++) {
song.orders.ord[ch][i]=0;
}
song.pat[ch].wipePatterns();
song.pat[ch].effectCols=1;
}
void DivEngine::swapChannelsP(int src, int dest) {
if (src<0 || src>=chans) return;
if (dest<0 || dest>=chans) return;
BUSY_BEGIN;
saveLock.lock();
swapChannels(src,dest);
saveLock.unlock();
BUSY_END;
}
void DivEngine::changeSystem(int index, DivSystem which, bool preserveOrder) {
int chanCount=chans;
quitDispatch();
BUSY_BEGIN;
saveLock.lock();
if (!preserveOrder) {
int firstChan=0;
int chanMovement=getChannelCount(which)-getChannelCount(song.system[index]);
while (dispatchOfChan[firstChan]!=index) firstChan++;
int lastChan=firstChan+getChannelCount(song.system[index]);
if (chanMovement!=0) {
if (chanMovement>0) {
// add channels
for (int i=chanCount+chanMovement-1; i>=lastChan+chanMovement; i--) {
swapChannels(i,i-chanMovement);
}
for (int i=lastChan; i<lastChan+chanMovement; i++) {
stompChannel(i);
}
} else {
// remove channels
for (int i=lastChan+chanMovement; i<lastChan; i++) {
stompChannel(i);
}
for (int i=lastChan+chanMovement; i<chanCount+chanMovement; i++) {
swapChannels(i,i-chanMovement);
}
}
}
}
song.system[index]=which;
song.systemFlags[index]=0;
recalcChans();
@ -688,7 +757,7 @@ bool DivEngine::addSystem(DivSystem which) {
return true;
}
bool DivEngine::removeSystem(int index) {
bool DivEngine::removeSystem(int index, bool preserveOrder) {
if (song.systemLen<=1) {
lastError="cannot remove the last one";
return false;
@ -697,13 +766,29 @@ bool DivEngine::removeSystem(int index) {
lastError="invalid index";
return false;
}
int chanCount=chans;
quitDispatch();
BUSY_BEGIN;
saveLock.lock();
if (!preserveOrder) {
int firstChan=0;
while (dispatchOfChan[firstChan]!=index) firstChan++;
for (int i=0; i<getChannelCount(song.system[index]); i++) {
stompChannel(i+firstChan);
}
for (int i=firstChan+getChannelCount(song.system[index]); i<chanCount; i++) {
swapChannels(i,i-getChannelCount(song.system[index]));
}
}
song.system[index]=DIV_SYSTEM_NULL;
song.systemLen--;
for (int i=index; i<song.systemLen; i++) {
song.system[i]=song.system[i+1];
song.systemVol[i]=song.systemVol[i+1];
song.systemPan[i]=song.systemPan[i+1];
song.systemFlags[i]=song.systemFlags[i+1];
}
recalcChans();
saveLock.unlock();
@ -1059,7 +1144,6 @@ void DivEngine::recalcChans() {
if (sysDefs[song.system[i]]!=NULL) {
if (sysDefs[song.system[i]]->chanInsType[j][0]!=DIV_INS_NULL) {
isInsTypePossible[sysDefs[song.system[i]]->chanInsType[j][0]]=true;
logV("Marking");
}
if (sysDefs[song.system[i]]->chanInsType[j][1]!=DIV_INS_NULL) {

View file

@ -395,6 +395,8 @@ class DivEngine {
void registerSystems();
void exchangeIns(int one, int two);
void swapChannels(int src, int dest);
void stompChannel(int ch);
public:
DivSong song;
@ -762,14 +764,17 @@ class DivEngine {
// public render samples
void renderSamplesP();
// public swap channels
void swapChannelsP(int src, int dest);
// change system
void changeSystem(int index, DivSystem which);
void changeSystem(int index, DivSystem which, bool preserveOrder=true);
// add system
bool addSystem(DivSystem which);
// remove system
bool removeSystem(int index);
bool removeSystem(int index, bool preserveOrder=true);
// write to register on system
void poke(int sys, unsigned int addr, unsigned short val);