dev183 - prepare for better DPCM mapping

This commit is contained in:
tildearrow 2023-10-12 19:52:44 -05:00
parent ddf0e3f368
commit 7ede07e2a4
6 changed files with 461 additions and 278 deletions

View file

@ -54,8 +54,8 @@ class DivWorkPool;
#define DIV_UNSTABLE
#define DIV_VERSION "dev182"
#define DIV_ENGINE_VERSION 182
#define DIV_VERSION "dev183"
#define DIV_ENGINE_VERSION 183
// for imports
#define DIV_VERSION_MOD 0xff01
#define DIV_VERSION_FC 0xff02

View file

@ -719,6 +719,21 @@ void DivInstrument::writeFeatureX1(SafeWriter* w) {
FEATURE_END;
}
void DivInstrument::writeFeatureNE(SafeWriter* w) {
FEATURE_BEGIN("NE");
w->writeC(amiga.useNoteMap?1:0);
if (amiga.useNoteMap) {
for (int note=0; note<120; note++) {
w->writeC(amiga.noteMap[note].dpcmFreq);
w->writeC(amiga.noteMap[note].dpcmDelta);
}
}
FEATURE_END;
}
void DivInstrument::putInsData2(SafeWriter* w, bool fui, const DivSong* song, bool insName) {
size_t blockStartSeek=0;
size_t blockEndSeek=0;
@ -761,6 +776,7 @@ void DivInstrument::putInsData2(SafeWriter* w, bool fui, const DivSong* song, bo
bool featureSU=false;
bool featureES=false;
bool featureX1=false;
bool featureNE=false;
bool checkForWL=false;
@ -904,6 +920,8 @@ void DivInstrument::putInsData2(SafeWriter* w, bool fui, const DivSong* song, bo
featureFM=true;
break;
case DIV_INS_NES:
featureSM=true;
featureNE=true;
break;
case DIV_INS_MSM6258:
featureSM=true;
@ -993,6 +1011,7 @@ void DivInstrument::putInsData2(SafeWriter* w, bool fui, const DivSong* song, bo
}
if (amiga!=defaultIns.amiga) {
featureSM=true;
featureNE=true;
}
if (snes!=defaultIns.snes) {
featureSN=true;
@ -1157,6 +1176,9 @@ void DivInstrument::putInsData2(SafeWriter* w, bool fui, const DivSong* song, bo
if (featureX1) {
writeFeatureX1(w);
}
if (featureNE) {
writeFeatureNE(w);
}
if (fui && (featureSL || featureWL)) {
w->write("EN",2);
@ -2541,6 +2563,21 @@ void DivInstrument::readFeatureX1(SafeReader& reader, short version) {
READ_FEAT_END;
}
void DivInstrument::readFeatureNE(SafeReader& reader, short version) {
READ_FEAT_BEGIN;
amiga.useNoteMap=reader.readC();
if (amiga.useNoteMap) {
for (int note=0; note<120; note++) {
amiga.noteMap[note].dpcmFreq=reader.readC();
amiga.noteMap[note].dpcmDelta=reader.readC();
}
}
READ_FEAT_END;
}
DivDataErrors DivInstrument::readInsDataNew(SafeReader& reader, short version, bool fui, DivSong* song) {
unsigned char featCode[2];
@ -2606,6 +2643,8 @@ DivDataErrors DivInstrument::readInsDataNew(SafeReader& reader, short version, b
readFeatureES(reader,version);
} else if (memcmp(featCode,"X1",2)==0) { // X1-010
readFeatureX1(reader,version);
} else if (memcmp(featCode,"NE",2)==0) { // NES (DPCM)
readFeatureNE(reader,version);
} else {
if (song==NULL && (memcmp(featCode,"SL",2)==0 || (memcmp(featCode,"WL",2)==0))) {
// nothing

View file

@ -452,9 +452,13 @@ struct DivInstrumentAmiga {
struct SampleMap {
int freq;
short map;
SampleMap(int f=0, short m=-1):
signed char dpcmFreq;
signed char dpcmDelta;
SampleMap(int f=0, short m=-1, signed char df=15, signed char dd=-1):
freq(f),
map(m) {}
map(m),
dpcmFreq(df),
dpcmDelta(dd) {}
};
short initSample;
bool useNoteMap;
@ -759,6 +763,7 @@ struct DivInstrument {
void writeFeatureSU(SafeWriter* w);
void writeFeatureES(SafeWriter* w);
void writeFeatureX1(SafeWriter* w);
void writeFeatureNE(SafeWriter* w);
void readFeatureNA(SafeReader& reader, short version);
void readFeatureFM(SafeReader& reader, short version);
@ -778,6 +783,7 @@ struct DivInstrument {
void readFeatureSU(SafeReader& reader, short version);
void readFeatureES(SafeReader& reader, short version);
void readFeatureX1(SafeReader& reader, short version);
void readFeatureNE(SafeReader& reader, short version);
DivDataErrors readInsDataOld(SafeReader& reader, short version);
DivDataErrors readInsDataNew(SafeReader& reader, short version, bool fui, DivSong* song);

View file

@ -695,8 +695,8 @@ void DivEngine::registerSystems() {
{"Pulse 1", "Pulse 2", "Triangle", "Noise", "DPCM"},
{"S1", "S2", "TR", "NO", "DMC"},
{DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_WAVE, DIV_CH_NOISE, DIV_CH_PCM},
{DIV_INS_NES, DIV_INS_NES, DIV_INS_NES, DIV_INS_NES, DIV_INS_AMIGA},
{},
{DIV_INS_NES, DIV_INS_NES, DIV_INS_NES, DIV_INS_NES, DIV_INS_NES},
{DIV_INS_NULL, DIV_INS_NULL, DIV_INS_NULL, DIV_INS_NULL, DIV_INS_AMIGA},
{
{0x11, {DIV_CMD_NES_DMC, "11xx: Write to delta modulation counter (0 to 7F)"}},
{0x12, {DIV_CMD_STD_NOISE_MODE, "12xx: Set duty cycle/noise mode (pulse: 0 to 3; noise: 0 or 1)"}},

View file

@ -2260,6 +2260,8 @@ class FurnaceGUI {
void drawMacros(std::vector<FurnaceGUIMacroDesc>& macros, FurnaceGUIMacroEditState& state);
void alterSampleMap(bool isNote, int val);
void insTabSample(DivInstrument* ins);
void drawOrderButtons();
void actualWaveList();

View file

@ -2272,6 +2272,410 @@ void FurnaceGUI::alterSampleMap(bool isNote, int val) {
ImGui::EndDragDropTarget(); \
}
void FurnaceGUI::insTabSample(DivInstrument* ins) {
const char* sampleTabName="Sample";
if (ins->type==DIV_INS_SU) sampleTabName="Sound Unit";
if (ins->type==DIV_INS_NES) sampleTabName="DPCM";
if (ImGui::BeginTabItem(sampleTabName)) {
String sName;
bool wannaOpenSMPopup=false;
if (ins->amiga.initSample<0 || ins->amiga.initSample>=e->song.sampleLen) {
sName="none selected";
} else {
sName=e->song.sample[ins->amiga.initSample]->name;
}
if (ins->type==DIV_INS_PCE ||
ins->type==DIV_INS_MIKEY ||
ins->type==DIV_INS_X1_010 ||
ins->type==DIV_INS_SWAN ||
ins->type==DIV_INS_AY ||
ins->type==DIV_INS_AY8930 ||
ins->type==DIV_INS_VRC6 ||
ins->type==DIV_INS_SU) {
P(ImGui::Checkbox("Use sample",&ins->amiga.useSample));
if (ins->type==DIV_INS_SU) {
P(ImGui::Checkbox("Switch roles of frequency and phase reset timer",&ins->su.switchRoles));
}
if (ins->type==DIV_INS_X1_010) {
if (ImGui::InputInt("Sample bank slot##BANKSLOT",&ins->x1_010.bankSlot,1,4)) { PARAMETER
if (ins->x1_010.bankSlot<0) ins->x1_010.bankSlot=0;
if (ins->x1_010.bankSlot>=7) ins->x1_010.bankSlot=7;
}
}
}
ImGui::AlignTextToFramePadding();
ImGui::Text("Sample");
ImGui::SameLine();
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
if (ImGui::BeginCombo("##ISample",sName.c_str())) {
String id;
for (int i=0; i<e->song.sampleLen; i++) {
id=fmt::sprintf("%d: %s",i,e->song.sample[i]->name);
if (ImGui::Selectable(id.c_str(),ins->amiga.initSample==i)) { PARAMETER
ins->amiga.initSample=i;
}
}
ImGui::EndCombo();
}
// Wavetable
if (ins->type==DIV_INS_AMIGA || ins->type==DIV_INS_SNES) {
ImGui::BeginDisabled(ins->amiga.useNoteMap);
P(ImGui::Checkbox("Use wavetable (Amiga/SNES/Generic DAC only)",&ins->amiga.useWave));
if (ins->amiga.useWave) {
int len=ins->amiga.waveLen+1;
int origLen=len;
if (ImGui::InputInt("Width",&len,2,16)) {
if (ins->type==DIV_INS_SNES) {
if (len<16) len=16;
if (len>256) len=256;
if (len>origLen) {
ins->amiga.waveLen=((len+15)&(~15))-1;
} else {
ins->amiga.waveLen=(len&(~15))-1;
}
} else {
if (len<2) len=2;
if (len>256) len=256;
ins->amiga.waveLen=(len&(~1))-1;
}
PARAMETER
}
}
ImGui::EndDisabled();
}
// Note map
ImGui::BeginDisabled(ins->amiga.useWave);
P(ImGui::Checkbox("Use sample map",&ins->amiga.useNoteMap));
if (ins->amiga.useNoteMap) {
if (ImGui::IsMouseClicked(ImGuiMouseButton_Left) && ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows)) sampleMapFocused=false;
if (curWindowLast!=GUI_WINDOW_INS_EDIT) sampleMapFocused=false;
if (!sampleMapFocused) sampleMapDigit=0;
if (ImGui::BeginTable("NoteMap",(ins->type==DIV_INS_NES)?5:4,ImGuiTableFlags_ScrollY|ImGuiTableFlags_Borders|ImGuiTableFlags_SizingStretchSame)) {
ImGui::TableSetupColumn("c0",ImGuiTableColumnFlags_WidthFixed);
ImGui::TableSetupColumn("c1",ImGuiTableColumnFlags_WidthFixed);
ImGui::TableSetupColumn("c2",ImGuiTableColumnFlags_WidthFixed);
if (ins->type==DIV_INS_NES) ImGui::TableSetupColumn("c3",ImGuiTableColumnFlags_WidthFixed);
ImGui::TableSetupColumn("c4",ImGuiTableColumnFlags_WidthStretch);
ImGui::TableSetupScrollFreeze(0,1);
ImGui::TableNextRow(ImGuiTableRowFlags_Headers);
ImGui::TableNextColumn();
ImGui::TableNextColumn();
ImGui::Text("#");
if (ins->type==DIV_INS_NES) {
ImGui::TableNextColumn();
ImGui::Text("freq");
ImGui::TableNextColumn();
ImGui::Text("delta");
} else {
ImGui::TableNextColumn();
ImGui::Text("note");
}
ImGui::TableNextColumn();
ImGui::Text("sample name");
int sampleMapMin=sampleMapSelStart;
int sampleMapMax=sampleMapSelEnd;
if (sampleMapMin>sampleMapMax) {
sampleMapMin^=sampleMapMax;
sampleMapMax^=sampleMapMin;
sampleMapMin^=sampleMapMax;
}
ImGui::PushStyleColor(ImGuiCol_Header,ImGui::GetColorU32(ImGuiCol_HeaderHovered));
ImGui::PushStyleColor(ImGuiCol_HeaderActive,ImGui::GetColorU32(ImGuiCol_HeaderHovered));
for (int i=0; i<120; i++) {
DivInstrumentAmiga::SampleMap& sampleMap=ins->amiga.noteMap[i];
ImGui::TableNextRow();
ImGui::TableNextColumn();
ImGui::TableSetBgColor(ImGuiTableBgTarget_CellBg,ImGui::GetColorU32(ImGuiCol_TableHeaderBg));
ImGui::AlignTextToFramePadding();
ImGui::Text("%s",noteNames[60+i]);
ImGui::TableNextColumn();
if (sampleMap.map<0 || sampleMap.map>=e->song.sampleLen) {
sName=fmt::sprintf("---##SM%d",i);
sampleMap.map=-1;
} else {
sName=fmt::sprintf("%3d##SM%d",sampleMap.map,i);
}
ImGui::PushFont(patFont);
ImGui::AlignTextToFramePadding();
ImGui::SetNextItemWidth(ImGui::CalcTextSize("00000").x);
ImGui::Selectable(sName.c_str(),(sampleMapWaitingInput && sampleMapColumn==0 && i>=sampleMapMin && i<=sampleMapMax));
if (ImGui::IsItemClicked(ImGuiMouseButton_Left)) {
sampleMapFocused=true;
sampleMapColumn=0;
sampleMapDigit=0;
sampleMapSelStart=i;
sampleMapSelEnd=i;
sampleMapMin=sampleMapSelStart;
sampleMapMax=sampleMapSelEnd;
if (sampleMapMin>sampleMapMax) {
sampleMapMin^=sampleMapMax;
sampleMapMax^=sampleMapMin;
sampleMapMin^=sampleMapMax;
}
ImGui::InhibitInertialScroll();
}
if (sampleMapFocused && ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem) && ImGui::IsMouseDown(ImGuiMouseButton_Left)) {
sampleMapSelEnd=i;
}
if (ImGui::IsItemClicked(ImGuiMouseButton_Right)) {
if (sampleMapSelStart==sampleMapSelEnd) {
sampleMapFocused=true;
sampleMapColumn=0;
sampleMapDigit=0;
sampleMapSelStart=i;
sampleMapSelEnd=i;
sampleMapMin=sampleMapSelStart;
sampleMapMax=sampleMapSelEnd;
if (sampleMapMin>sampleMapMax) {
sampleMapMin^=sampleMapMax;
sampleMapMax^=sampleMapMin;
sampleMapMin^=sampleMapMax;
}
}
if (sampleMapFocused) {
wannaOpenSMPopup=true;
}
}
ImGui::PopFont();
if (ins->type==DIV_INS_NES) {
// pitch
ImGui::TableNextColumn();
ImGui::PushFont(patFont);
ImGui::AlignTextToFramePadding();
ImGui::SetNextItemWidth(ImGui::CalcTextSize("0000").x);
ImGui::Selectable(" TO ",(sampleMapWaitingInput && sampleMapColumn==1 && i>=sampleMapMin && i<=sampleMapMax));
if (ImGui::IsItemClicked(ImGuiMouseButton_Left)) {
sampleMapFocused=true;
sampleMapColumn=1;
sampleMapDigit=0;
sampleMapSelStart=i;
sampleMapSelEnd=i;
sampleMapMin=sampleMapSelStart;
sampleMapMax=sampleMapSelEnd;
if (sampleMapMin>sampleMapMax) {
sampleMapMin^=sampleMapMax;
sampleMapMax^=sampleMapMin;
sampleMapMin^=sampleMapMax;
}
ImGui::InhibitInertialScroll();
}
if (sampleMapFocused && ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem) && ImGui::IsMouseDown(ImGuiMouseButton_Left)) {
sampleMapSelEnd=i;
}
if (ImGui::IsItemClicked(ImGuiMouseButton_Right)) {
if (sampleMapSelStart==sampleMapSelEnd) {
sampleMapFocused=true;
sampleMapColumn=1;
sampleMapDigit=0;
sampleMapSelStart=i;
sampleMapSelEnd=i;
sampleMapMin=sampleMapSelStart;
sampleMapMax=sampleMapSelEnd;
if (sampleMapMin>sampleMapMax) {
sampleMapMin^=sampleMapMax;
sampleMapMax^=sampleMapMin;
sampleMapMin^=sampleMapMax;
}
}
if (sampleMapFocused) {
wannaOpenSMPopup=true;
}
}
ImGui::PopFont();
// delta
ImGui::TableNextColumn();
ImGui::PushFont(patFont);
ImGui::AlignTextToFramePadding();
ImGui::SetNextItemWidth(ImGui::CalcTextSize("0000").x);
ImGui::Selectable(" DO ",(sampleMapWaitingInput && sampleMapColumn==2 && i>=sampleMapMin && i<=sampleMapMax));
if (ImGui::IsItemClicked(ImGuiMouseButton_Left)) {
sampleMapFocused=true;
sampleMapColumn=2;
sampleMapDigit=0;
sampleMapSelStart=i;
sampleMapSelEnd=i;
sampleMapMin=sampleMapSelStart;
sampleMapMax=sampleMapSelEnd;
if (sampleMapMin>sampleMapMax) {
sampleMapMin^=sampleMapMax;
sampleMapMax^=sampleMapMin;
sampleMapMin^=sampleMapMax;
}
ImGui::InhibitInertialScroll();
}
if (sampleMapFocused && ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem) && ImGui::IsMouseDown(ImGuiMouseButton_Left)) {
sampleMapSelEnd=i;
}
if (ImGui::IsItemClicked(ImGuiMouseButton_Right)) {
if (sampleMapSelStart==sampleMapSelEnd) {
sampleMapFocused=true;
sampleMapColumn=2;
sampleMapDigit=0;
sampleMapSelStart=i;
sampleMapSelEnd=i;
sampleMapMin=sampleMapSelStart;
sampleMapMax=sampleMapSelEnd;
if (sampleMapMin>sampleMapMax) {
sampleMapMin^=sampleMapMax;
sampleMapMax^=sampleMapMin;
sampleMapMin^=sampleMapMax;
}
}
if (sampleMapFocused) {
wannaOpenSMPopup=true;
}
}
ImGui::PopFont();
} else {
ImGui::TableNextColumn();
sName="???";
if ((sampleMap.freq+60)>0 && (sampleMap.freq+60)<180) {
sName=noteNames[sampleMap.freq+60];
}
sName+=fmt::sprintf("##SN%d",i);
ImGui::PushFont(patFont);
ImGui::AlignTextToFramePadding();
ImGui::SetNextItemWidth(ImGui::CalcTextSize("00000").x);
ImGui::Selectable(sName.c_str(),(sampleMapWaitingInput && sampleMapColumn==1 && i>=sampleMapMin && i<=sampleMapMax));
if (ImGui::IsItemClicked(ImGuiMouseButton_Left)) {
sampleMapFocused=true;
sampleMapColumn=1;
sampleMapDigit=0;
sampleMapSelStart=i;
sampleMapSelEnd=i;
sampleMapMin=sampleMapSelStart;
sampleMapMax=sampleMapSelEnd;
if (sampleMapMin>sampleMapMax) {
sampleMapMin^=sampleMapMax;
sampleMapMax^=sampleMapMin;
sampleMapMin^=sampleMapMax;
}
ImGui::InhibitInertialScroll();
}
if (sampleMapFocused && ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem) && ImGui::IsMouseDown(ImGuiMouseButton_Left)) {
sampleMapSelEnd=i;
}
if (ImGui::IsItemClicked(ImGuiMouseButton_Right)) {
if (sampleMapSelStart==sampleMapSelEnd) {
sampleMapFocused=true;
sampleMapColumn=1;
sampleMapDigit=0;
sampleMapSelStart=i;
sampleMapSelEnd=i;
sampleMapMin=sampleMapSelStart;
sampleMapMax=sampleMapSelEnd;
if (sampleMapMin>sampleMapMax) {
sampleMapMin^=sampleMapMax;
sampleMapMax^=sampleMapMin;
sampleMapMin^=sampleMapMax;
}
}
if (sampleMapFocused) {
wannaOpenSMPopup=true;
}
}
ImGui::PopFont();
}
ImGui::TableNextColumn();
String prevName="---";
if (sampleMap.map>=0 && sampleMap.map<e->song.sampleLen) {
prevName=e->song.sample[sampleMap.map]->name;
}
ImGui::PushID(i+2);
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
if (ImGui::BeginCombo("##SMSample",prevName.c_str())) {
if (ImGui::Selectable("---")) {
sampleMap.map=-1;
}
for (int k=0; k<e->song.sampleLen; k++) {
String itemName=fmt::sprintf("%d: %s",k,e->song.sample[k]->name);
if (ImGui::Selectable(itemName.c_str())) {
sampleMap.map=k;
}
}
ImGui::EndCombo();
}
ImGui::PopID();
}
ImGui::PopStyleColor(2);
ImGui::EndTable();
}
} else {
sampleMapFocused=false;
}
ImGui::EndDisabled();
if (wannaOpenSMPopup) {
ImGui::OpenPopup("SampleMapUtils");
}
if (ImGui::BeginPopup("SampleMapUtils",ImGuiWindowFlags_NoMove|ImGuiWindowFlags_AlwaysAutoResize|ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoSavedSettings)) {
if (sampleMapSelStart==sampleMapSelEnd && sampleMapSelStart>=0 && sampleMapSelStart<120) {
if (ins->type==DIV_INS_NES) {
if (ImGui::MenuItem("set entire map to this frequency")) {
}
if (ImGui::MenuItem("set entire map to this delta counter value")) {
}
} else {
if (ImGui::MenuItem("set entire map to this note")) {
if (sampleMapSelStart>=0 && sampleMapSelStart<120) {
for (int i=0; i<120; i++) {
if (i==sampleMapSelStart) continue;
ins->amiga.noteMap[i].freq=ins->amiga.noteMap[sampleMapSelStart].freq;
}
}
}
}
if (ImGui::MenuItem("set entire map to this sample")) {
if (sampleMapSelStart>=0 && sampleMapSelStart<120) {
for (int i=0; i<120; i++) {
if (i==sampleMapSelStart) continue;
ins->amiga.noteMap[i].map=ins->amiga.noteMap[sampleMapSelStart].map;
}
}
}
}
if (ins->type==DIV_INS_NES) {
if (ImGui::MenuItem("clear frequencies")) {
}
if (ImGui::MenuItem("clear delta counter values")) {
}
} else {
if (ImGui::MenuItem("reset notes")) {
for (int i=0; i<120; i++) {
ins->amiga.noteMap[i].freq=i;
}
}
}
if (ImGui::MenuItem("clear map samples")) {
for (int i=0; i<120; i++) {
ins->amiga.noteMap[i].map=-1;
}
}
ImGui::EndPopup();
}
ImGui::EndTabItem();
} else {
sampleMapFocused=false;
}
}
void FurnaceGUI::drawInsEdit() {
if (nextWindow==GUI_WINDOW_INS_EDIT) {
insEditOpen=true;
@ -4547,278 +4951,7 @@ void FurnaceGUI::drawInsEdit() {
ins->type==DIV_INS_K053260 ||
ins->type==DIV_INS_C140 ||
ins->type==DIV_INS_C219) {
if (ImGui::BeginTabItem((ins->type==DIV_INS_SU)?"Sound Unit":"Sample")) {
String sName;
bool wannaOpenSMPopup=false;
if (ins->amiga.initSample<0 || ins->amiga.initSample>=e->song.sampleLen) {
sName="none selected";
} else {
sName=e->song.sample[ins->amiga.initSample]->name;
}
if (ins->type==DIV_INS_PCE ||
ins->type==DIV_INS_MIKEY ||
ins->type==DIV_INS_X1_010 ||
ins->type==DIV_INS_SWAN ||
ins->type==DIV_INS_AY ||
ins->type==DIV_INS_AY8930 ||
ins->type==DIV_INS_VRC6 ||
ins->type==DIV_INS_SU) {
P(ImGui::Checkbox("Use sample",&ins->amiga.useSample));
if (ins->type==DIV_INS_SU) {
P(ImGui::Checkbox("Switch roles of frequency and phase reset timer",&ins->su.switchRoles));
}
if (ins->type==DIV_INS_X1_010) {
if (ImGui::InputInt("Sample bank slot##BANKSLOT",&ins->x1_010.bankSlot,1,4)) { PARAMETER
if (ins->x1_010.bankSlot<0) ins->x1_010.bankSlot=0;
if (ins->x1_010.bankSlot>=7) ins->x1_010.bankSlot=7;
}
}
}
if (ImGui::BeginCombo("Initial Sample",sName.c_str())) {
String id;
for (int i=0; i<e->song.sampleLen; i++) {
id=fmt::sprintf("%d: %s",i,e->song.sample[i]->name);
if (ImGui::Selectable(id.c_str(),ins->amiga.initSample==i)) { PARAMETER
ins->amiga.initSample=i;
}
}
ImGui::EndCombo();
}
// Wavetable
if (ins->type==DIV_INS_AMIGA || ins->type==DIV_INS_SNES) {
ImGui::BeginDisabled(ins->amiga.useNoteMap);
P(ImGui::Checkbox("Use wavetable (Amiga/SNES/Generic DAC only)",&ins->amiga.useWave));
if (ins->amiga.useWave) {
int len=ins->amiga.waveLen+1;
int origLen=len;
if (ImGui::InputInt("Width",&len,2,16)) {
if (ins->type==DIV_INS_SNES) {
if (len<16) len=16;
if (len>256) len=256;
if (len>origLen) {
ins->amiga.waveLen=((len+15)&(~15))-1;
} else {
ins->amiga.waveLen=(len&(~15))-1;
}
} else {
if (len<2) len=2;
if (len>256) len=256;
ins->amiga.waveLen=(len&(~1))-1;
}
PARAMETER
}
}
ImGui::EndDisabled();
}
// Note map
ImGui::BeginDisabled(ins->amiga.useWave);
P(ImGui::Checkbox("Use sample map",&ins->amiga.useNoteMap));
if (ins->amiga.useNoteMap) {
if (ImGui::IsMouseClicked(ImGuiMouseButton_Left) && ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows)) sampleMapFocused=false;
if (curWindowLast!=GUI_WINDOW_INS_EDIT) sampleMapFocused=false;
if (!sampleMapFocused) sampleMapDigit=0;
if (ImGui::BeginTable("NoteMap",4,ImGuiTableFlags_ScrollY|ImGuiTableFlags_Borders|ImGuiTableFlags_SizingStretchSame)) {
ImGui::TableSetupColumn("c0",ImGuiTableColumnFlags_WidthFixed);
ImGui::TableSetupColumn("c1",ImGuiTableColumnFlags_WidthFixed);
ImGui::TableSetupColumn("c2",ImGuiTableColumnFlags_WidthFixed);
ImGui::TableSetupColumn("c3",ImGuiTableColumnFlags_WidthStretch);
ImGui::TableSetupScrollFreeze(0,1);
ImGui::TableNextRow(ImGuiTableRowFlags_Headers);
ImGui::TableNextColumn();
ImGui::TableNextColumn();
ImGui::Text("#");
ImGui::TableNextColumn();
ImGui::Text("note");
ImGui::TableNextColumn();
ImGui::Text("sample name");
int sampleMapMin=sampleMapSelStart;
int sampleMapMax=sampleMapSelEnd;
if (sampleMapMin>sampleMapMax) {
sampleMapMin^=sampleMapMax;
sampleMapMax^=sampleMapMin;
sampleMapMin^=sampleMapMax;
}
ImGui::PushStyleColor(ImGuiCol_Header,ImGui::GetColorU32(ImGuiCol_HeaderHovered));
ImGui::PushStyleColor(ImGuiCol_HeaderActive,ImGui::GetColorU32(ImGuiCol_HeaderHovered));
for (int i=0; i<120; i++) {
DivInstrumentAmiga::SampleMap& sampleMap=ins->amiga.noteMap[i];
ImGui::TableNextRow();
ImGui::TableNextColumn();
ImGui::TableSetBgColor(ImGuiTableBgTarget_CellBg,ImGui::GetColorU32(ImGuiCol_TableHeaderBg));
ImGui::AlignTextToFramePadding();
ImGui::Text("%s",noteNames[60+i]);
ImGui::TableNextColumn();
if (sampleMap.map<0 || sampleMap.map>=e->song.sampleLen) {
sName=fmt::sprintf("---##SM%d",i);
sampleMap.map=-1;
} else {
sName=fmt::sprintf("%3d##SM%d",sampleMap.map,i);
}
ImGui::PushFont(patFont);
ImGui::AlignTextToFramePadding();
ImGui::SetNextItemWidth(ImGui::CalcTextSize("00000").x);
ImGui::Selectable(sName.c_str(),(sampleMapWaitingInput && sampleMapColumn==0 && i>=sampleMapMin && i<=sampleMapMax));
if (ImGui::IsItemClicked(ImGuiMouseButton_Left)) {
sampleMapFocused=true;
sampleMapColumn=0;
sampleMapDigit=0;
sampleMapSelStart=i;
sampleMapSelEnd=i;
sampleMapMin=sampleMapSelStart;
sampleMapMax=sampleMapSelEnd;
if (sampleMapMin>sampleMapMax) {
sampleMapMin^=sampleMapMax;
sampleMapMax^=sampleMapMin;
sampleMapMin^=sampleMapMax;
}
ImGui::InhibitInertialScroll();
}
if (sampleMapFocused && ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem) && ImGui::IsMouseDown(ImGuiMouseButton_Left)) {
sampleMapSelEnd=i;
}
if (ImGui::IsItemClicked(ImGuiMouseButton_Right)) {
if (sampleMapSelStart==sampleMapSelEnd) {
sampleMapFocused=true;
sampleMapColumn=0;
sampleMapDigit=0;
sampleMapSelStart=i;
sampleMapSelEnd=i;
sampleMapMin=sampleMapSelStart;
sampleMapMax=sampleMapSelEnd;
if (sampleMapMin>sampleMapMax) {
sampleMapMin^=sampleMapMax;
sampleMapMax^=sampleMapMin;
sampleMapMin^=sampleMapMax;
}
}
if (sampleMapFocused) {
wannaOpenSMPopup=true;
}
}
ImGui::PopFont();
ImGui::TableNextColumn();
sName="???";
if ((sampleMap.freq+60)>0 && (sampleMap.freq+60)<180) {
sName=noteNames[sampleMap.freq+60];
}
sName+=fmt::sprintf("##SN%d",i);
ImGui::PushFont(patFont);
ImGui::AlignTextToFramePadding();
ImGui::SetNextItemWidth(ImGui::CalcTextSize("00000").x);
ImGui::Selectable(sName.c_str(),(sampleMapWaitingInput && sampleMapColumn==1 && i>=sampleMapMin && i<=sampleMapMax));
if (ImGui::IsItemClicked(ImGuiMouseButton_Left)) {
sampleMapFocused=true;
sampleMapColumn=1;
sampleMapDigit=0;
sampleMapSelStart=i;
sampleMapSelEnd=i;
sampleMapMin=sampleMapSelStart;
sampleMapMax=sampleMapSelEnd;
if (sampleMapMin>sampleMapMax) {
sampleMapMin^=sampleMapMax;
sampleMapMax^=sampleMapMin;
sampleMapMin^=sampleMapMax;
}
ImGui::InhibitInertialScroll();
}
if (sampleMapFocused && ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem) && ImGui::IsMouseDown(ImGuiMouseButton_Left)) {
sampleMapSelEnd=i;
}
if (ImGui::IsItemClicked(ImGuiMouseButton_Right)) {
if (sampleMapSelStart==sampleMapSelEnd) {
sampleMapFocused=true;
sampleMapColumn=1;
sampleMapDigit=0;
sampleMapSelStart=i;
sampleMapSelEnd=i;
sampleMapMin=sampleMapSelStart;
sampleMapMax=sampleMapSelEnd;
if (sampleMapMin>sampleMapMax) {
sampleMapMin^=sampleMapMax;
sampleMapMax^=sampleMapMin;
sampleMapMin^=sampleMapMax;
}
}
if (sampleMapFocused) {
wannaOpenSMPopup=true;
}
}
ImGui::PopFont();
ImGui::TableNextColumn();
String prevName="---";
if (sampleMap.map>=0 && sampleMap.map<e->song.sampleLen) {
prevName=e->song.sample[sampleMap.map]->name;
}
ImGui::PushID(i+2);
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
if (ImGui::BeginCombo("##SMSample",prevName.c_str())) {
if (ImGui::Selectable("---")) {
sampleMap.map=-1;
}
for (int k=0; k<e->song.sampleLen; k++) {
String itemName=fmt::sprintf("%d: %s",k,e->song.sample[k]->name);
if (ImGui::Selectable(itemName.c_str())) {
sampleMap.map=k;
}
}
ImGui::EndCombo();
}
ImGui::PopID();
}
ImGui::PopStyleColor(2);
ImGui::EndTable();
}
} else {
sampleMapFocused=false;
}
ImGui::EndDisabled();
if (wannaOpenSMPopup) {
ImGui::OpenPopup("SampleMapUtils");
}
if (ImGui::BeginPopup("SampleMapUtils",ImGuiWindowFlags_NoMove|ImGuiWindowFlags_AlwaysAutoResize|ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoSavedSettings)) {
if (sampleMapSelStart==sampleMapSelEnd && sampleMapSelStart>=0 && sampleMapSelStart<120) {
if (ImGui::MenuItem("set entire map to this note")) {
if (sampleMapSelStart>=0 && sampleMapSelStart<120) {
for (int i=0; i<120; i++) {
if (i==sampleMapSelStart) continue;
ins->amiga.noteMap[i].freq=ins->amiga.noteMap[sampleMapSelStart].freq;
}
}
}
if (ImGui::MenuItem("set entire map to this sample")) {
if (sampleMapSelStart>=0 && sampleMapSelStart<120) {
for (int i=0; i<120; i++) {
if (i==sampleMapSelStart) continue;
ins->amiga.noteMap[i].map=ins->amiga.noteMap[sampleMapSelStart].map;
}
}
}
}
if (ImGui::MenuItem("reset notes")) {
for (int i=0; i<120; i++) {
ins->amiga.noteMap[i].freq=i;
}
}
if (ImGui::MenuItem("clear map samples")) {
for (int i=0; i<120; i++) {
ins->amiga.noteMap[i].map=-1;
}
}
ImGui::EndPopup();
}
ImGui::EndTabItem();
} else {
sampleMapFocused=false;
}
insTabSample(ins);
}
if (ins->type==DIV_INS_N163) if (ImGui::BeginTabItem("Namco 163")) {
bool preLoad=ins->n163.waveMode&0x1;
@ -6059,6 +6192,9 @@ void FurnaceGUI::drawInsEdit() {
drawMacros(macroList,macroEditStateMacros);
ImGui::EndTabItem();
}
if (ins->type==DIV_INS_NES) {
insTabSample(ins);
}
ImGui::EndTabBar();
}
if (settings.insEditColorize) {