FDS: possibly final work

the last thing left to do is the filter, but everything works now
This commit is contained in:
tildearrow 2022-04-05 18:18:14 -05:00
parent 4ba50b433a
commit 280cbb3e39
4 changed files with 122 additions and 6 deletions

View file

@ -63,10 +63,10 @@ const char* DivPlatformFDS::getEffectName(unsigned char effect) {
return "11xx: Set modulation depth";
break;
case 0x12:
return "12xy: Set modulation frequency high byte (x: enable; y: value)";
return "12xy: Set modulation speed high byte (x: enable; y: value)";
break;
case 0x13:
return "13xx: Set modulation frequency low byte";
return "13xx: Set modulation speed low byte";
break;
case 0x14:
return "14xx: Set modulator position";
@ -163,6 +163,22 @@ void DivPlatformFDS::tick() {
//if (!chan[i].keyOff) chan[i].keyOn=true;
}
}
if (chan[i].std.hadEx1) { // mod depth
chan[i].modOn=chan[i].std.ex1;
chan[i].modDepth=chan[i].std.ex1;
rWrite(0x4084,(chan[i].modOn<<7)|0x40|chan[i].modDepth);
}
if (chan[i].std.hadEx2) { // mod speed
chan[i].modFreq=chan[i].std.ex2;
rWrite(0x4086,chan[i].modFreq&0xff);
rWrite(0x4087,chan[i].modFreq>>8);
}
if (chan[i].std.hadEx3) { // mod position
chan[i].modPos=chan[i].std.ex3;
rWrite(0x4087,0x80|chan[i].modFreq>>8);
rWrite(0x4085,chan[i].modPos);
rWrite(0x4087,chan[i].modFreq>>8);
}
if (chan[i].sweepChanged) {
chan[i].sweepChanged=false;
if (i==0) {
@ -199,6 +215,42 @@ int DivPlatformFDS::dispatch(DivCommand c) {
chan[c.chan].freqChanged=true;
chan[c.chan].note=c.value;
}
if (chan[c.chan].insChanged) {
DivInstrument* ins=parent->getIns(chan[c.chan].ins);
if (ins->fds.initModTableWithFirstWave) { // compatible
if (chan[c.chan].wave==-1) {
DivWavetable* wt=parent->getWave(0);
for (int i=0; i<32; i++) {
if (wt->max<1 || wt->len<1) {
rWrite(0x4040+i,0);
} else {
int data=wt->data[i*MIN(32,wt->len)/32]*7/wt->max;
if (data<0) data=0;
if (data>7) data=7;
chan[c.chan].modTable[i]=data;
}
}
rWrite(0x4087,0x80|chan[c.chan].modFreq>>8);
for (int i=0; i<32; i++) {
rWrite(0x4088,chan[c.chan].modTable[i]);
}
rWrite(0x4087,chan[c.chan].modFreq>>8);
}
} else { // The Familiar Way
chan[c.chan].modDepth=ins->fds.modDepth;
chan[c.chan].modOn=ins->fds.modDepth;
chan[c.chan].modFreq=ins->fds.modSpeed;
rWrite(0x4084,(chan[c.chan].modOn<<7)|0x40|chan[c.chan].modDepth);
rWrite(0x4086,chan[c.chan].modFreq&0xff);
rWrite(0x4087,0x80|chan[c.chan].modFreq>>8);
for (int i=0; i<32; i++) {
chan[c.chan].modTable[i]=ins->fds.modTable[i]&7;
rWrite(0x4088,chan[c.chan].modTable[i]);
}
rWrite(0x4087,chan[c.chan].modFreq>>8);
}
}
chan[c.chan].active=true;
chan[c.chan].keyOn=true;
chan[c.chan].std.init(parent->getIns(chan[c.chan].ins));
@ -256,7 +308,9 @@ int DivPlatformFDS::dispatch(DivCommand c) {
break;
case DIV_CMD_FDS_MOD_POS:
chan[c.chan].modPos=c.value&0x7f;
// TODO
rWrite(0x4087,0x80|chan[c.chan].modFreq>>8);
rWrite(0x4085,chan[c.chan].modPos);
rWrite(0x4087,chan[c.chan].modFreq>>8);
break;
case DIV_CMD_FDS_MOD_WAVE: {
DivWavetable* wt=parent->getWave(c.value);

View file

@ -2116,8 +2116,11 @@ void FurnaceGUI::drawInsEdit() {
ImGui::EndTabItem();
}
if (ins->type==DIV_INS_FDS) if (ImGui::BeginTabItem("FDS")) {
ImGui::Text("FDS config goes here");
ImGui::Checkbox("Initialize modulation table with first wavetable (compatibility)",&ins->fds.initModTableWithFirstWave);
float modTable[32];
ImGui::Checkbox("Compatibility mode",&ins->fds.initModTableWithFirstWave);
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("only use for compatibility with .dmf modules!\n- initializes modulation table with first wavetable\n- does not alter modulation parameters on instrument change");
}
if (ImGui::InputInt("Modulation depth",&ins->fds.modDepth,1,32)) {
if (ins->fds.modDepth<0) ins->fds.modDepth=0;
if (ins->fds.modDepth>63) ins->fds.modDepth=63;
@ -2127,6 +2130,26 @@ void FurnaceGUI::drawInsEdit() {
if (ins->fds.modSpeed>4095) ins->fds.modSpeed=4095;
}
ImGui::Text("Modulation table");
for (int i=0; i<32; i++) {
modTable[i]=ins->fds.modTable[i];
}
ImVec2 modTableSize=ImVec2(ImGui::GetContentRegionAvail().x,96.0f*dpiScale);
PlotCustom("ModTable",modTable,32,0,NULL,-4,3,modTableSize,sizeof(float),ImVec4(1.0f,1.0f,1.0f,1.0f),0,NULL,true);
if (ImGui::IsItemClicked(ImGuiMouseButton_Left)) {
macroDragStart=ImGui::GetItemRectMin();
macroDragAreaSize=modTableSize;
macroDragMin=-4;
macroDragMax=3;
macroDragBitOff=0;
macroDragBitMode=false;
macroDragInitialValueSet=false;
macroDragInitialValue=false;
macroDragLen=32;
macroDragActive=true;
macroDragCTarget=(unsigned char*)ins->fds.modTable;
macroDragChar=true;
processDrags(ImGui::GetMousePos().x,ImGui::GetMousePos().y); \
}
ImGui::EndTabItem();
}
if (ImGui::BeginTabItem("Macros")) {
@ -2268,6 +2291,10 @@ void FurnaceGUI::drawInsEdit() {
ex1Max=252;
ex2Max=2;
}
if (ins->type==DIV_INS_FDS) {
ex1Max=63;
ex2Max=4095;
}
if (ins->type==DIV_INS_SAA1099) ex1Max=8;
if (settings.macroView==0) { // modern view
@ -2296,6 +2323,8 @@ void FurnaceGUI::drawInsEdit() {
NORMAL_MACRO(ins->std.ex1Macro,ins->std.ex1MacroLen,ins->std.ex1MacroLoop,ins->std.ex1MacroRel,0,ex1Max,"ex1","Envelope Mode",160,ins->std.ex1MacroOpen,true,x1_010EnvBits,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[4],0,ex1Max,NULL,false);
} else if (ins->type==DIV_INS_N163) {
NORMAL_MACRO(ins->std.ex1Macro,ins->std.ex1MacroLen,ins->std.ex1MacroLoop,ins->std.ex1MacroRel,0,ex1Max,"ex1","Waveform len.",160,ins->std.ex1MacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[4],0,ex1Max,NULL,false);
} else if (ins->type==DIV_INS_FDS) {
NORMAL_MACRO(ins->std.ex1Macro,ins->std.ex1MacroLen,ins->std.ex1MacroLoop,ins->std.ex1MacroRel,0,ex1Max,"ex1","Mod Depth",160,ins->std.ex1MacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[4],0,ex1Max,NULL,false);
} else {
NORMAL_MACRO(ins->std.ex1Macro,ins->std.ex1MacroLen,ins->std.ex1MacroLoop,ins->std.ex1MacroRel,0,ex1Max,"ex1","Duty",160,ins->std.ex1MacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[4],0,ex1Max,NULL,false);
}
@ -2305,6 +2334,8 @@ void FurnaceGUI::drawInsEdit() {
NORMAL_MACRO(ins->std.ex2Macro,ins->std.ex2MacroLen,ins->std.ex2MacroLoop,ins->std.ex2MacroRel,0,ex2Max,"ex2","Resonance",64,ins->std.ex2MacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[5],0,ex2Max,NULL,false);
} else if (ins->type==DIV_INS_N163) {
NORMAL_MACRO(ins->std.ex2Macro,ins->std.ex2MacroLen,ins->std.ex2MacroLoop,ins->std.ex2MacroRel,0,ex2Max,"ex2","Waveform update",64,ins->std.ex2MacroOpen,true,n163UpdateBits,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[5],0,ex2Max,NULL,false);
} else if (ins->type==DIV_INS_FDS) {
NORMAL_MACRO(ins->std.ex2Macro,ins->std.ex2MacroLen,ins->std.ex2MacroLoop,ins->std.ex2MacroRel,0,ex2Max,"ex2","Mod Speed",160,ins->std.ex2MacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[5],0,ex2Max,NULL,false);
} else {
NORMAL_MACRO(ins->std.ex2Macro,ins->std.ex2MacroLen,ins->std.ex2MacroLoop,ins->std.ex2MacroRel,0,ex2Max,"ex2","Envelope",ex2Bit?64:160,ins->std.ex2MacroOpen,ex2Bit,ayEnvBits,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[5],0,ex2Max,NULL,false);
}
@ -2327,6 +2358,9 @@ void FurnaceGUI::drawInsEdit() {
NORMAL_MACRO(ins->std.fbMacro,ins->std.fbMacroLen,ins->std.fbMacroLoop,ins->std.fbMacroRel,0,252,"fb","Wave len. to Load",160,ins->std.fbMacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[8],0,252,NULL,false);
NORMAL_MACRO(ins->std.fmsMacro,ins->std.fmsMacroLen,ins->std.fmsMacroLoop,ins->std.fmsMacroRel,0,2,"fms","Waveform load",64,ins->std.fmsMacroOpen,true,n163UpdateBits,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[9],0,2,NULL,false);
}
if (ins->type==DIV_INS_FDS) {
NORMAL_MACRO(ins->std.ex3Macro,ins->std.ex3MacroLen,ins->std.ex3MacroLoop,ins->std.ex3MacroRel,0,127,"ex3","Mod Position",160,ins->std.ex3MacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[6],0,2,NULL,false);
}
MACRO_END;
} else { // classic view

View file

@ -332,6 +332,8 @@ int PlotCustomEx(ImGuiPlotType plot_type, const char* label, float (*values_gett
scale_max = v_max;
}
if (blockMode) scale_max+=1.0f;
ImU32 bgColor=ImGui::GetColorU32(ImVec4(color.x,color.y,color.z,color.w*0.15));
ImGui::RenderFrame(frame_bb.Min, frame_bb.Max, ImGui::GetColorU32(ImGuiCol_FrameBg), true, style.FrameRounding);
@ -372,7 +374,7 @@ int PlotCustomEx(ImGuiPlotType plot_type, const char* label, float (*values_gett
float v0 = values_getter(data, (0) % values_count);
float t0 = 0.0f;
ImVec2 tp0 = ImVec2( t0, 1.0f - ImSaturate((v0 - scale_min) * inv_scale) ); // Point in the normalized space of our target rectangle
float histogram_zero_line_t = (scale_min * scale_max < 0.0f) ? (1 + scale_min * inv_scale) : (scale_min < 0.0f ? 0.0f : 1.0f); // Where does the zero line stands
float histogram_zero_line_t = (scale_min * scale_max < 0.0f) ? (1 + (blockMode?(scale_min-0.5):scale_min) * inv_scale) : (scale_min < 0.0f ? 0.0f : 1.0f); // Where does the zero line stands
const ImU32 col_base = ImGui::GetColorU32(color);
const ImU32 col_hovered = ImGui::GetColorU32(color);