From efde2c57985a07bd4dd439544b0c24a02532af83 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Mon, 13 Dec 2021 02:03:36 -0500 Subject: [PATCH] earliest pattern view --- src/engine/engine.cpp | 10 +- src/gui/gui.cpp | 228 ++++++++++++++++++++++++++++++------------ src/gui/gui.h | 1 + 3 files changed, 172 insertions(+), 67 deletions(-) diff --git a/src/engine/engine.cpp b/src/engine/engine.cpp index 166832a7..66b9dea3 100644 --- a/src/engine/engine.cpp +++ b/src/engine/engine.cpp @@ -210,6 +210,8 @@ int DivEngine::getMaxDuty() { return 31; case DIV_SYSTEM_C64_6581: case DIV_SYSTEM_C64_8580: return 8; + case DIV_SYSTEM_PCE: + return 0; default: return 3; } @@ -219,15 +221,15 @@ int DivEngine::getMaxDuty() { int DivEngine::getMaxWave() { switch (song.system) { case DIV_SYSTEM_PCE: case DIV_SYSTEM_GB: - return 31; + return 63; case DIV_SYSTEM_YM2610: case DIV_SYSTEM_YM2610_EXT: return 7; case DIV_SYSTEM_C64_6581: case DIV_SYSTEM_C64_8580: return 8; default: - return 1; + return 0; } - return 1; + return 0; } bool DivEngine::load(void* f, size_t slen) { @@ -1089,6 +1091,7 @@ void DivEngine::play() { curRow=0; clockDrift=0; cycles=0; + ticks=1; speedAB=false; playing=true; isBusy.unlock(); @@ -1122,6 +1125,7 @@ void DivEngine::setOrder(unsigned char order) { curRow=0; clockDrift=0; cycles=0; + ticks=1; speedAB=false; } isBusy.unlock(); diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index 899443d0..954f0fba 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -4,6 +4,7 @@ #include "fonts.h" #include "../ta-log.h" #include "imgui.h" +#include "imgui_internal.h" #include "misc/cpp/imgui_stdlib.h" #include #include @@ -22,10 +23,34 @@ const int opOrder[4]={ 0, 2, 1, 3 }; +const char* noteNames[120]={ + "C-0", "C#0", "D-0", "D#0", "E-0", "F-0", "F#0", "G-0", "G#0", "A-0", "A#0", "B-0", + "C-1", "C#1", "D-1", "D#1", "E-1", "F-1", "F#1", "G-1", "G#1", "A-1", "A#1", "B-1", + "C-2", "C#2", "D-2", "D#2", "E-2", "F-2", "F#2", "G-2", "G#2", "A-2", "A#2", "B-2", + "C-3", "C#3", "D-3", "D#3", "E-3", "F-3", "F#3", "G-3", "G#3", "A-3", "A#3", "B-3", + "C-4", "C#4", "D-4", "D#4", "E-4", "F-4", "F#4", "G-4", "G#4", "A-4", "A#4", "B-4", + "C-5", "C#5", "D-5", "D#5", "E-5", "F-5", "F#5", "G-5", "G#5", "A-5", "A#5", "B-5", + "C-6", "C#6", "D-6", "D#6", "E-6", "F-6", "F#6", "G-6", "G#6", "A-6", "A#6", "B-6", + "C-7", "C#7", "D-7", "D#7", "E-7", "F-7", "F#7", "G-7", "G#7", "A-7", "A#7", "B-7", + "C-8", "C#8", "D-8", "D#8", "E-8", "F-8", "F#8", "G-8", "G#8", "A-8", "A#8", "B-8", + "C-9", "C#9", "D-9", "D#9", "E-9", "F-9", "F#9", "G-9", "G#9", "A-9", "A#9", "B-9" +}; + void FurnaceGUI::bindEngine(DivEngine* eng) { e=eng; } +const char* FurnaceGUI::noteName(short note, short octave) { + if (note==100) { + return "OFF"; + } else if (octave==0 && note==0) { + return "..."; + } + int seek=note+octave*12; + if (seek>=120) return "???"; + return noteNames[seek]; +} + bool FurnaceGUI::loop() { while (!quit) { SDL_Event ev; @@ -361,73 +386,79 @@ bool FurnaceGUI::loop() { } // duty macro - ImGui::Separator(); - if (e->song.system==DIV_SYSTEM_C64_6581 || e->song.system==DIV_SYSTEM_C64_8580) { - ImGui::Text("Relative Duty Macro"); - } else if (e->song.system==DIV_SYSTEM_YM2610 || e->song.system==DIV_SYSTEM_YM2610_EXT) { - ImGui::Text("Noise Frequency Macro"); - } else { - ImGui::Text("Duty/Noise Mode Macro"); - } - for (int i=0; istd.dutyMacroLen; i++) { - asFloat[i]=ins->std.dutyMacro[i]; - loopIndicator[i]=(ins->std.dutyMacroLoop!=-1 && i>=ins->std.dutyMacroLoop); - } - ImGui::PushStyleVar(ImGuiStyleVar_FramePadding,ImVec2(0.0f,0.0f)); - int dutyMax=e->getMaxDuty();; - ImGui::PlotHistogram("##IDutyMacro",asFloat,ins->std.dutyMacroLen,0,NULL,0,dutyMax,ImVec2(400.0f*dpiScale,200.0f*dpiScale)); - if (ImGui::IsItemClicked(ImGuiMouseButton_Left)) { - macroDragStart=ImGui::GetItemRectMin(); - macroDragAreaSize=ImVec2(400.0f*dpiScale,200.0f*dpiScale); - macroDragMin=0; - macroDragMax=dutyMax; - macroDragLen=ins->std.dutyMacroLen; - macroDragActive=true; - macroDragTarget=ins->std.dutyMacro; - } - ImGui::PlotHistogram("##IDutyMacroLoop",loopIndicator,ins->std.dutyMacroLen,0,NULL,0,1,ImVec2(400.0f*dpiScale,16.0f*dpiScale)); - if (ImGui::IsItemClicked(ImGuiMouseButton_Left)) { - macroLoopDragStart=ImGui::GetItemRectMin(); - macroLoopDragAreaSize=ImVec2(400.0f*dpiScale,16.0f*dpiScale); - macroLoopDragLen=ins->std.dutyMacroLen; - macroLoopDragTarget=&ins->std.dutyMacroLoop; - macroLoopDragActive=true; - } - ImGui::PopStyleVar(); - if (ImGui::InputScalar("Length##IDutyMacroL",ImGuiDataType_U8,&ins->std.dutyMacroLen,&_ONE,&_THREE)) { - if (ins->std.dutyMacroLen>127) ins->std.dutyMacroLen=127; + int dutyMax=e->getMaxDuty(); + if (dutyMax>0) { + ImGui::Separator(); + if (e->song.system==DIV_SYSTEM_C64_6581 || e->song.system==DIV_SYSTEM_C64_8580) { + ImGui::Text("Relative Duty Macro"); + } else if (e->song.system==DIV_SYSTEM_YM2610 || e->song.system==DIV_SYSTEM_YM2610_EXT) { + ImGui::Text("Noise Frequency Macro"); + } else { + ImGui::Text("Duty/Noise Mode Macro"); + } + for (int i=0; istd.dutyMacroLen; i++) { + asFloat[i]=ins->std.dutyMacro[i]; + loopIndicator[i]=(ins->std.dutyMacroLoop!=-1 && i>=ins->std.dutyMacroLoop); + } + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding,ImVec2(0.0f,0.0f)); + + ImGui::PlotHistogram("##IDutyMacro",asFloat,ins->std.dutyMacroLen,0,NULL,0,dutyMax,ImVec2(400.0f*dpiScale,200.0f*dpiScale)); + if (ImGui::IsItemClicked(ImGuiMouseButton_Left)) { + macroDragStart=ImGui::GetItemRectMin(); + macroDragAreaSize=ImVec2(400.0f*dpiScale,200.0f*dpiScale); + macroDragMin=0; + macroDragMax=dutyMax; + macroDragLen=ins->std.dutyMacroLen; + macroDragActive=true; + macroDragTarget=ins->std.dutyMacro; + } + ImGui::PlotHistogram("##IDutyMacroLoop",loopIndicator,ins->std.dutyMacroLen,0,NULL,0,1,ImVec2(400.0f*dpiScale,16.0f*dpiScale)); + if (ImGui::IsItemClicked(ImGuiMouseButton_Left)) { + macroLoopDragStart=ImGui::GetItemRectMin(); + macroLoopDragAreaSize=ImVec2(400.0f*dpiScale,16.0f*dpiScale); + macroLoopDragLen=ins->std.dutyMacroLen; + macroLoopDragTarget=&ins->std.dutyMacroLoop; + macroLoopDragActive=true; + } + ImGui::PopStyleVar(); + if (ImGui::InputScalar("Length##IDutyMacroL",ImGuiDataType_U8,&ins->std.dutyMacroLen,&_ONE,&_THREE)) { + if (ins->std.dutyMacroLen>127) ins->std.dutyMacroLen=127; + } } // wave macro - ImGui::Separator(); - ImGui::Text("Waveform Macro"); - for (int i=0; istd.waveMacroLen; i++) { - asFloat[i]=ins->std.waveMacro[i]; - loopIndicator[i]=(ins->std.waveMacroLoop!=-1 && i>=ins->std.waveMacroLoop); - } - ImGui::PushStyleVar(ImGuiStyleVar_FramePadding,ImVec2(0.0f,0.0f)); int waveMax=e->getMaxWave(); - ImGui::PlotHistogram("##IWaveMacro",asFloat,ins->std.waveMacroLen,0,NULL,0,waveMax,ImVec2(400.0f*dpiScale,200.0f*dpiScale)); - if (ImGui::IsItemClicked(ImGuiMouseButton_Left)) { - macroDragStart=ImGui::GetItemRectMin(); - macroDragAreaSize=ImVec2(400.0f*dpiScale,200.0f*dpiScale); - macroDragMin=0; - macroDragMax=waveMax; - macroDragLen=ins->std.waveMacroLen; - macroDragActive=true; - macroDragTarget=ins->std.waveMacro; - } - ImGui::PlotHistogram("##IWaveMacroLoop",loopIndicator,ins->std.waveMacroLen,0,NULL,0,1,ImVec2(400.0f*dpiScale,16.0f*dpiScale)); - if (ImGui::IsItemClicked(ImGuiMouseButton_Left)) { - macroLoopDragStart=ImGui::GetItemRectMin(); - macroLoopDragAreaSize=ImVec2(400.0f*dpiScale,16.0f*dpiScale); - macroLoopDragLen=ins->std.waveMacroLen; - macroLoopDragTarget=&ins->std.waveMacroLoop; - macroLoopDragActive=true; - } - ImGui::PopStyleVar(); - if (ImGui::InputScalar("Length##IWaveMacroL",ImGuiDataType_U8,&ins->std.waveMacroLen,&_ONE,&_THREE)) { - if (ins->std.waveMacroLen>127) ins->std.waveMacroLen=127; + if (waveMax>0) { + ImGui::Separator(); + ImGui::Text("Waveform Macro"); + for (int i=0; istd.waveMacroLen; i++) { + asFloat[i]=ins->std.waveMacro[i]; + loopIndicator[i]=(ins->std.waveMacroLoop!=-1 && i>=ins->std.waveMacroLoop); + } + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding,ImVec2(0.0f,0.0f)); + + ImGui::PlotHistogram("##IWaveMacro",asFloat,ins->std.waveMacroLen,0,NULL,0,waveMax,ImVec2(400.0f*dpiScale,200.0f*dpiScale)); + if (ImGui::IsItemClicked(ImGuiMouseButton_Left)) { + macroDragStart=ImGui::GetItemRectMin(); + macroDragAreaSize=ImVec2(400.0f*dpiScale,200.0f*dpiScale); + macroDragMin=0; + macroDragMax=waveMax; + macroDragLen=ins->std.waveMacroLen; + macroDragActive=true; + macroDragTarget=ins->std.waveMacro; + } + ImGui::PlotHistogram("##IWaveMacroLoop",loopIndicator,ins->std.waveMacroLen,0,NULL,0,1,ImVec2(400.0f*dpiScale,16.0f*dpiScale)); + if (ImGui::IsItemClicked(ImGuiMouseButton_Left)) { + macroLoopDragStart=ImGui::GetItemRectMin(); + macroLoopDragAreaSize=ImVec2(400.0f*dpiScale,16.0f*dpiScale); + macroLoopDragLen=ins->std.waveMacroLen; + macroLoopDragTarget=&ins->std.waveMacroLoop; + macroLoopDragActive=true; + } + ImGui::PopStyleVar(); + if (ImGui::InputScalar("Length##IWaveMacroL",ImGuiDataType_U8,&ins->std.waveMacroLen,&_ONE,&_THREE)) { + if (ins->std.waveMacroLen>127) ins->std.waveMacroLen=127; + } } } } @@ -435,7 +466,76 @@ bool FurnaceGUI::loop() { ImGui::End(); if (ImGui::Begin("Pattern")) { - ImGui::Text("TODO"); + char id[32]; + ImGui::PushFont(patFont); + unsigned char ord=e->getOrder(); + int chans=e->getChannelCount(e->song.system); + if (ImGui::BeginTable("PatternView",chans+1,ImGuiTableFlags_BordersInnerV|ImGuiTableFlags_ScrollX|ImGuiTableFlags_ScrollY|ImGuiTableFlags_NoPadInnerX)) { + ImGui::TableSetupColumn("pos",ImGuiTableColumnFlags_WidthFixed); + ImGui::TableSetupScrollFreeze(1,1); + for (int i=0; igetChannelShortName(i)); + } + float oneCharSize=ImGui::CalcTextSize("A").x; + float lineHeight=(ImGui::GetTextLineHeight()+2*dpiScale); + ImVec2 threeChars=ImVec2(oneCharSize*3.0f,lineHeight); + ImVec2 twoChars=ImVec2(oneCharSize*2.0f,lineHeight); + ImVec2 oneChar=ImVec2(oneCharSize,lineHeight); + for (int i=0; isong.patLen; i++) { + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::Text("%3d ",i); + for (int j=0; jsong.pat[j]->getPattern(e->song.orders.ord[j][ord],true); + ImGui::TableNextColumn(); + + sprintf(id,"%s##PN_%d_%d",noteName(pat->data[i][0],pat->data[i][1]),i,j); + ImGui::Selectable(id,false,ImGuiSelectableFlags_NoPadWithHalfSpacing,threeChars); + + if (pat->data[i][2]==-1) { + sprintf(id,"..##PI_%d_%d",i,j); + } else { + sprintf(id,"%.2X##PI_%d_%d",pat->data[i][2],i,j); + } + ImGui::SameLine(0.0f,0.0f); + ImGui::Selectable(id,false,ImGuiSelectableFlags_NoPadWithHalfSpacing,twoChars); + + if (pat->data[i][3]==-1) { + sprintf(id,"..##PV_%d_%d",i,j); + } else { + sprintf(id,"%.2X##PV_%d_%d",pat->data[i][3],i,j); + } + ImGui::SameLine(0.0f,0.0f); + ImGui::Selectable(id,false,ImGuiSelectableFlags_NoPadWithHalfSpacing,twoChars); + + for (int k=0; ksong.pat[j]->effectRows; k++) { + int index=4+(k<<1); + if (pat->data[i][index]==-1) { + sprintf(id,"..##PE%d_%d_%d",k,i,j); + } else { + sprintf(id,"%.2X##PE%d_%d_%d",pat->data[i][index],k,i,j); + } + ImGui::SameLine(0.0f,0.0f); + ImGui::Selectable(id,false,ImGuiSelectableFlags_NoPadWithHalfSpacing,twoChars); + if (pat->data[i][index+1]==-1) { + sprintf(id,"..##PF%d_%d_%d",k,i,j); + } else { + sprintf(id,"%.2X##PF%d_%d_%d",pat->data[i][index+1],k,i,j); + } + ImGui::SameLine(0.0f,0.0f); + ImGui::Selectable(id,false,ImGuiSelectableFlags_NoPadWithHalfSpacing,twoChars); + } + } + } + } + ImGui::EndTable(); + ImGui::PopFont(); } ImGui::End(); diff --git a/src/gui/gui.h b/src/gui/gui.h index 6e327d49..ba04b36b 100644 --- a/src/gui/gui.h +++ b/src/gui/gui.h @@ -37,6 +37,7 @@ class FurnaceGUI { bool macroLoopDragActive; public: + const char* noteName(short note, short octave); void bindEngine(DivEngine* eng); bool loop(); bool init();