earliest pattern view

This commit is contained in:
tildearrow 2021-12-13 02:03:36 -05:00
parent 9a1683bb45
commit efde2c5798
3 changed files with 172 additions and 67 deletions

View file

@ -210,6 +210,8 @@ int DivEngine::getMaxDuty() {
return 31; return 31;
case DIV_SYSTEM_C64_6581: case DIV_SYSTEM_C64_8580: case DIV_SYSTEM_C64_6581: case DIV_SYSTEM_C64_8580:
return 8; return 8;
case DIV_SYSTEM_PCE:
return 0;
default: default:
return 3; return 3;
} }
@ -219,15 +221,15 @@ int DivEngine::getMaxDuty() {
int DivEngine::getMaxWave() { int DivEngine::getMaxWave() {
switch (song.system) { switch (song.system) {
case DIV_SYSTEM_PCE: case DIV_SYSTEM_GB: case DIV_SYSTEM_PCE: case DIV_SYSTEM_GB:
return 31; return 63;
case DIV_SYSTEM_YM2610: case DIV_SYSTEM_YM2610_EXT: case DIV_SYSTEM_YM2610: case DIV_SYSTEM_YM2610_EXT:
return 7; return 7;
case DIV_SYSTEM_C64_6581: case DIV_SYSTEM_C64_8580: case DIV_SYSTEM_C64_6581: case DIV_SYSTEM_C64_8580:
return 8; return 8;
default: default:
return 1; return 0;
} }
return 1; return 0;
} }
bool DivEngine::load(void* f, size_t slen) { bool DivEngine::load(void* f, size_t slen) {
@ -1089,6 +1091,7 @@ void DivEngine::play() {
curRow=0; curRow=0;
clockDrift=0; clockDrift=0;
cycles=0; cycles=0;
ticks=1;
speedAB=false; speedAB=false;
playing=true; playing=true;
isBusy.unlock(); isBusy.unlock();
@ -1122,6 +1125,7 @@ void DivEngine::setOrder(unsigned char order) {
curRow=0; curRow=0;
clockDrift=0; clockDrift=0;
cycles=0; cycles=0;
ticks=1;
speedAB=false; speedAB=false;
} }
isBusy.unlock(); isBusy.unlock();

View file

@ -4,6 +4,7 @@
#include "fonts.h" #include "fonts.h"
#include "../ta-log.h" #include "../ta-log.h"
#include "imgui.h" #include "imgui.h"
#include "imgui_internal.h"
#include "misc/cpp/imgui_stdlib.h" #include "misc/cpp/imgui_stdlib.h"
#include <cstdio> #include <cstdio>
#include <fmt/printf.h> #include <fmt/printf.h>
@ -22,10 +23,34 @@ const int opOrder[4]={
0, 2, 1, 3 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) { void FurnaceGUI::bindEngine(DivEngine* eng) {
e=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() { bool FurnaceGUI::loop() {
while (!quit) { while (!quit) {
SDL_Event ev; SDL_Event ev;
@ -361,73 +386,79 @@ bool FurnaceGUI::loop() {
} }
// duty macro // duty macro
ImGui::Separator(); int dutyMax=e->getMaxDuty();
if (e->song.system==DIV_SYSTEM_C64_6581 || e->song.system==DIV_SYSTEM_C64_8580) { if (dutyMax>0) {
ImGui::Text("Relative Duty Macro"); ImGui::Separator();
} else if (e->song.system==DIV_SYSTEM_YM2610 || e->song.system==DIV_SYSTEM_YM2610_EXT) { if (e->song.system==DIV_SYSTEM_C64_6581 || e->song.system==DIV_SYSTEM_C64_8580) {
ImGui::Text("Noise Frequency Macro"); ImGui::Text("Relative Duty Macro");
} else { } else if (e->song.system==DIV_SYSTEM_YM2610 || e->song.system==DIV_SYSTEM_YM2610_EXT) {
ImGui::Text("Duty/Noise Mode Macro"); ImGui::Text("Noise Frequency Macro");
} } else {
for (int i=0; i<ins->std.dutyMacroLen; i++) { ImGui::Text("Duty/Noise Mode Macro");
asFloat[i]=ins->std.dutyMacro[i]; }
loopIndicator[i]=(ins->std.dutyMacroLoop!=-1 && i>=ins->std.dutyMacroLoop); for (int i=0; i<ins->std.dutyMacroLen; i++) {
} asFloat[i]=ins->std.dutyMacro[i];
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding,ImVec2(0.0f,0.0f)); loopIndicator[i]=(ins->std.dutyMacroLoop!=-1 && i>=ins->std.dutyMacroLoop);
int dutyMax=e->getMaxDuty();; }
ImGui::PlotHistogram("##IDutyMacro",asFloat,ins->std.dutyMacroLen,0,NULL,0,dutyMax,ImVec2(400.0f*dpiScale,200.0f*dpiScale)); ImGui::PushStyleVar(ImGuiStyleVar_FramePadding,ImVec2(0.0f,0.0f));
if (ImGui::IsItemClicked(ImGuiMouseButton_Left)) {
macroDragStart=ImGui::GetItemRectMin(); ImGui::PlotHistogram("##IDutyMacro",asFloat,ins->std.dutyMacroLen,0,NULL,0,dutyMax,ImVec2(400.0f*dpiScale,200.0f*dpiScale));
macroDragAreaSize=ImVec2(400.0f*dpiScale,200.0f*dpiScale); if (ImGui::IsItemClicked(ImGuiMouseButton_Left)) {
macroDragMin=0; macroDragStart=ImGui::GetItemRectMin();
macroDragMax=dutyMax; macroDragAreaSize=ImVec2(400.0f*dpiScale,200.0f*dpiScale);
macroDragLen=ins->std.dutyMacroLen; macroDragMin=0;
macroDragActive=true; macroDragMax=dutyMax;
macroDragTarget=ins->std.dutyMacro; macroDragLen=ins->std.dutyMacroLen;
} macroDragActive=true;
ImGui::PlotHistogram("##IDutyMacroLoop",loopIndicator,ins->std.dutyMacroLen,0,NULL,0,1,ImVec2(400.0f*dpiScale,16.0f*dpiScale)); macroDragTarget=ins->std.dutyMacro;
if (ImGui::IsItemClicked(ImGuiMouseButton_Left)) { }
macroLoopDragStart=ImGui::GetItemRectMin(); ImGui::PlotHistogram("##IDutyMacroLoop",loopIndicator,ins->std.dutyMacroLen,0,NULL,0,1,ImVec2(400.0f*dpiScale,16.0f*dpiScale));
macroLoopDragAreaSize=ImVec2(400.0f*dpiScale,16.0f*dpiScale); if (ImGui::IsItemClicked(ImGuiMouseButton_Left)) {
macroLoopDragLen=ins->std.dutyMacroLen; macroLoopDragStart=ImGui::GetItemRectMin();
macroLoopDragTarget=&ins->std.dutyMacroLoop; macroLoopDragAreaSize=ImVec2(400.0f*dpiScale,16.0f*dpiScale);
macroLoopDragActive=true; macroLoopDragLen=ins->std.dutyMacroLen;
} macroLoopDragTarget=&ins->std.dutyMacroLoop;
ImGui::PopStyleVar(); macroLoopDragActive=true;
if (ImGui::InputScalar("Length##IDutyMacroL",ImGuiDataType_U8,&ins->std.dutyMacroLen,&_ONE,&_THREE)) { }
if (ins->std.dutyMacroLen>127) ins->std.dutyMacroLen=127; 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 // wave macro
ImGui::Separator();
ImGui::Text("Waveform Macro");
for (int i=0; i<ins->std.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(); int waveMax=e->getMaxWave();
ImGui::PlotHistogram("##IWaveMacro",asFloat,ins->std.waveMacroLen,0,NULL,0,waveMax,ImVec2(400.0f*dpiScale,200.0f*dpiScale)); if (waveMax>0) {
if (ImGui::IsItemClicked(ImGuiMouseButton_Left)) { ImGui::Separator();
macroDragStart=ImGui::GetItemRectMin(); ImGui::Text("Waveform Macro");
macroDragAreaSize=ImVec2(400.0f*dpiScale,200.0f*dpiScale); for (int i=0; i<ins->std.waveMacroLen; i++) {
macroDragMin=0; asFloat[i]=ins->std.waveMacro[i];
macroDragMax=waveMax; loopIndicator[i]=(ins->std.waveMacroLoop!=-1 && i>=ins->std.waveMacroLoop);
macroDragLen=ins->std.waveMacroLen; }
macroDragActive=true; ImGui::PushStyleVar(ImGuiStyleVar_FramePadding,ImVec2(0.0f,0.0f));
macroDragTarget=ins->std.waveMacro;
} ImGui::PlotHistogram("##IWaveMacro",asFloat,ins->std.waveMacroLen,0,NULL,0,waveMax,ImVec2(400.0f*dpiScale,200.0f*dpiScale));
ImGui::PlotHistogram("##IWaveMacroLoop",loopIndicator,ins->std.waveMacroLen,0,NULL,0,1,ImVec2(400.0f*dpiScale,16.0f*dpiScale)); if (ImGui::IsItemClicked(ImGuiMouseButton_Left)) {
if (ImGui::IsItemClicked(ImGuiMouseButton_Left)) { macroDragStart=ImGui::GetItemRectMin();
macroLoopDragStart=ImGui::GetItemRectMin(); macroDragAreaSize=ImVec2(400.0f*dpiScale,200.0f*dpiScale);
macroLoopDragAreaSize=ImVec2(400.0f*dpiScale,16.0f*dpiScale); macroDragMin=0;
macroLoopDragLen=ins->std.waveMacroLen; macroDragMax=waveMax;
macroLoopDragTarget=&ins->std.waveMacroLoop; macroDragLen=ins->std.waveMacroLen;
macroLoopDragActive=true; macroDragActive=true;
} macroDragTarget=ins->std.waveMacro;
ImGui::PopStyleVar(); }
if (ImGui::InputScalar("Length##IWaveMacroL",ImGuiDataType_U8,&ins->std.waveMacroLen,&_ONE,&_THREE)) { ImGui::PlotHistogram("##IWaveMacroLoop",loopIndicator,ins->std.waveMacroLen,0,NULL,0,1,ImVec2(400.0f*dpiScale,16.0f*dpiScale));
if (ins->std.waveMacroLen>127) ins->std.waveMacroLen=127; 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(); ImGui::End();
if (ImGui::Begin("Pattern")) { 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; i<chans; i++) {
ImGui::TableSetupColumn(fmt::sprintf("c%d",i).c_str(),ImGuiTableColumnFlags_WidthFixed);
}
ImGui::TableNextRow();
ImGui::TableNextColumn();
for (int i=0; i<chans; i++) {
ImGui::TableNextColumn();
ImGui::Text("%s",e->getChannelShortName(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; i<e->song.patLen; i++) {
ImGui::TableNextRow();
ImGui::TableNextColumn();
ImGui::Text("%3d ",i);
for (int j=0; j<chans; j++) {
DivPattern* pat=e->song.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; k<e->song.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(); ImGui::End();

View file

@ -37,6 +37,7 @@ class FurnaceGUI {
bool macroLoopDragActive; bool macroLoopDragActive;
public: public:
const char* noteName(short note, short octave);
void bindEngine(DivEngine* eng); void bindEngine(DivEngine* eng);
bool loop(); bool loop();
bool init(); bool init();