/** * Furnace Tracker - multi-system chiptune tracker * Copyright (C) 2021-2025 tildearrow and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ // from this point onwards, a mess. #include "engine.h" bool DivEngine::convertLegacySampleMode() { logD("converting legacy sample mode..."); int legacyInsInit=-1; // quit if we don't have space for a legacy sample instrument if (song.ins.size()>254) { logW("no space left on instrument list!"); return false; } auto initSampleInsIfNeeded=[this,&legacyInsInit]() { if (legacyInsInit==-1) { DivInstrument* ins=new DivInstrument; legacyInsInit=(int)song.ins.size(); ins->type=DIV_INS_AMIGA; ins->amiga.useNoteMap=true; ins->name="Legacy Samples"; for (int i=0; i<120; i++) { ins->amiga.noteMap[i].freq=48; // C-4 ins->amiga.noteMap[i].map=i%12; } song.ins.push_back(ins); song.insLen=song.ins.size(); checkAssetDir(song.insDir,song.ins.size()); } }; for (DivSubSong* h: song.subsong) { for (int i=0; iordersLen; j++) { int patIndex=h->orders.ord[i][j]; if (didThisPattern[patIndex]) continue; didThisPattern[patIndex]=true; DivPattern* p=h->pat[i].data[patIndex]; if (p==NULL) continue; for (int k=0; kpatLen; k++) { // check for legacy mode toggle and sample bank changes for (int l=0; lpat[i].effectCols; l++) { int fxVal=p->newData[k][DIV_PAT_FXVAL(l)]; if (fxVal<0) fxVal=0; switch (p->newData[k][DIV_PAT_FX(l)]) { case 0x17: // set legacy sample mode if (fxVal==0) { sampleMode=0; } else { sampleMode=1; } // clear effect p->newData[k][DIV_PAT_FX(l)]=-1; p->newData[k][DIV_PAT_FXVAL(l)]=-1; break; case 0xeb: // set sample bank sampleBank=fxVal; // clear effect p->newData[k][DIV_PAT_FX(l)]=-1; p->newData[k][DIV_PAT_FXVAL(l)]=-1; logV("change bank to %d",sampleBank); break; } } // check for instrument changes if (p->newData[k][DIV_PAT_INS]!=-1) { DivInstrument* ins=getIns(p->newData[k][DIV_PAT_INS]); if (ins->type==DIV_INS_AMIGA || ins->amiga.useSample || ins->type==preferredInsType || ins->type==preferredInsType2) { sampleMode=2; } } if (p->newData[k][DIV_PAT_NOTE]!=-1 && p->newData[k][DIV_PAT_NOTE]!=DIV_NOTE_OFF && p->newData[k][DIV_PAT_NOTE]!=DIV_NOTE_REL && p->newData[k][DIV_PAT_NOTE]!=DIV_MACRO_REL) { // we've got a note if (sampleMode==1) { initSampleInsIfNeeded(); //p->newData[k][DIV_PAT_NOTE]=60+12*sampleBank+(p->newData[k][DIV_PAT_NOTE]%12); p->newData[k][DIV_PAT_INS]=legacyInsInit; } } else if (p->newData[k][DIV_PAT_NOTE]==DIV_NOTE_OFF && noteOffDisablesSampleMode) { sampleMode=0; } } } } } return (legacyInsInit!=-1); }