diff --git a/src/engine/dispatchContainer.cpp b/src/engine/dispatchContainer.cpp index 15e03aea2..7ae9da6a2 100644 --- a/src/engine/dispatchContainer.cpp +++ b/src/engine/dispatchContainer.cpp @@ -196,6 +196,7 @@ void DivDispatchContainer::init(DivSystem sys, DivEngine* eng, int chanCount, do break; case DIV_SYSTEM_OPLL: case DIV_SYSTEM_OPLL_DRUMS: + case DIV_SYSTEM_VRC7: dispatch=new DivPlatformOPLL; break; case DIV_SYSTEM_SAA1099: { diff --git a/src/engine/fileOps.cpp b/src/engine/fileOps.cpp index 562c85460..7bb53c408 100644 --- a/src/engine/fileOps.cpp +++ b/src/engine/fileOps.cpp @@ -299,10 +299,16 @@ bool DivEngine::loadDMF(unsigned char* file, size_t len) { for (int j=0; jfm.ops; j++) { ins->fm.op[j].am=reader.readC(); ins->fm.op[j].ar=reader.readC(); + if (ds.system[0]==DIV_SYSTEM_SMS_OPLL || ds.system[0]==DIV_SYSTEM_NES_VRC7) { + ins->fm.op[j].ar&=15; + } if (ds.version<0x13) { ins->fm.op[j].dam=reader.readC(); } ins->fm.op[j].dr=reader.readC(); + if (ds.system[0]==DIV_SYSTEM_SMS_OPLL || ds.system[0]==DIV_SYSTEM_NES_VRC7) { + ins->fm.op[j].dr&=15; + } if (ds.version<0x13) { ins->fm.op[j].dvb=reader.readC(); ins->fm.op[j].egt=reader.readC(); diff --git a/src/engine/instrument.h b/src/engine/instrument.h index bfc60531a..366bd87d6 100644 --- a/src/engine/instrument.h +++ b/src/engine/instrument.h @@ -54,7 +54,7 @@ struct DivInstrumentFM { unsigned char alg, fb, fms, ams, ops, opllPreset; struct Operator { unsigned char am, ar, dr, mult, rr, sl, tl, dt2, rs, dt, d2r, ssgEnv; - unsigned char dam, dvb, egt, ksl, sus, vib, ws, ksr; // YMU759 + unsigned char dam, dvb, egt, ksl, sus, vib, ws, ksr; // YMU759/OPL Operator(): am(0), ar(0), diff --git a/src/engine/platform/opll.cpp b/src/engine/platform/opll.cpp index 205030753..ad3b3a22e 100644 --- a/src/engine/platform/opll.cpp +++ b/src/engine/platform/opll.cpp @@ -85,13 +85,12 @@ void DivPlatformOPLL::acquire_nuked(short* bufL, short* bufR, size_t start, size QueuedWrite& w=writes.front(); if (w.addrOrVal) { OPLL_Write(&fm,1,w.val); - printf("write: %x = %.2x\n",w.addr,w.val); + //printf("write: %x = %.2x\n",w.addr,w.val); regPool[w.addr&0xff]=w.val; writes.pop(); delay=21; } else { //printf("busycounter: %d\n",lastBusy); - //w.addr=rand()&0x3f; OPLL_Write(&fm,0,w.addr); w.addrOrVal=true; delay=3; @@ -240,8 +239,7 @@ void DivPlatformOPLL::tick() { }*/ if (chan[i].keyOn || chan[i].keyOff) { - // TODO: FIX - immWrite(0x20+i,0x00); + immWrite(0x20+i,(chan[i].freqH)|(chan[i].state.alg?0x20:0)); //chan[i].keyOn=false; chan[i].keyOff=false; } @@ -262,31 +260,32 @@ void DivPlatformOPLL::tick() { chan[i].freqH=freqt>>8; chan[i].freqL=freqt&0xff; immWrite(0x10+i,freqt&0xff); - - chan[i].freqChanged=false; } - if (chan[i].keyOn) { + if (chan[i].keyOn || chan[i].freqChanged) { //immWrite(0x28,0xf0|konOffs[i]); - immWrite(0x20+i,(chan[i].freqH)|(chan[i].active<<4)|0x20); + immWrite(0x20+i,(chan[i].freqH)|(chan[i].active<<4)|(chan[i].state.alg?0x20:0)); chan[i].keyOn=false; } + chan[i].freqChanged=false; } } +#define OPLL_C_NUM 343 + int DivPlatformOPLL::octave(int freq) { - if (freq>=32768) { + if (freq>=OPLL_C_NUM*64) { return 128; - } else if (freq>=16384) { + } else if (freq>=OPLL_C_NUM*32) { return 64; - } else if (freq>=8192) { + } else if (freq>=OPLL_C_NUM*16) { return 32; - } else if (freq>=4096) { + } else if (freq>=OPLL_C_NUM*8) { return 16; - } else if (freq>=2048) { + } else if (freq>=OPLL_C_NUM*4) { return 8; - } else if (freq>=1024) { + } else if (freq>=OPLL_C_NUM*2) { return 4; - } else if (freq>=512) { + } else if (freq>=OPLL_C_NUM) { return 2; } else { return 1; @@ -295,19 +294,19 @@ int DivPlatformOPLL::octave(int freq) { } int DivPlatformOPLL::toFreq(int freq) { - if (freq>=32768) { + if (freq>=OPLL_C_NUM*64) { return 0xe00|((freq>>7)&0x1ff); - } else if (freq>=16384) { + } else if (freq>=OPLL_C_NUM*32) { return 0xc00|((freq>>6)&0x1ff); - } else if (freq>=8192) { + } else if (freq>=OPLL_C_NUM*16) { return 0xa00|((freq>>5)&0x1ff); - } else if (freq>=4096) { + } else if (freq>=OPLL_C_NUM*8) { return 0x800|((freq>>4)&0x1ff); - } else if (freq>=2048) { + } else if (freq>=OPLL_C_NUM*4) { return 0x600|((freq>>3)&0x1ff); - } else if (freq>=1024) { + } else if (freq>=OPLL_C_NUM*2) { return 0x400|((freq>>2)&0x1ff); - } else if (freq>=512) { + } else if (freq>=OPLL_C_NUM) { return 0x200|((freq>>1)&0x1ff); } else { return freq&0x1ff; @@ -346,39 +345,23 @@ int DivPlatformOPLL::dispatch(DivCommand c) { chan[c.chan].outVol=chan[c.chan].vol; } - /* - for (int i=0; i<2; i++) { - unsigned short baseAddr=chanOffs[c.chan]|opOffs[i]; - DivInstrumentFM::Operator& op=chan[c.chan].state.op[i]; - if (isMuted[c.chan]) { - rWrite(baseAddr+ADDR_TL,127); - } else { - if (isOutput[chan[c.chan].state.alg][i]) { - if (!chan[c.chan].active || chan[c.chan].insChanged) { - rWrite(baseAddr+ADDR_TL,127-(((127-op.tl)*(chan[c.chan].outVol&0x7f))/127)); - } - } else { - if (chan[c.chan].insChanged) { - rWrite(baseAddr+ADDR_TL,op.tl); - } - } - } - if (chan[c.chan].insChanged) { - rWrite(baseAddr+ADDR_MULT_DT,(op.mult&15)|(dtTable[op.dt&7]<<4)); - rWrite(baseAddr+ADDR_RS_AR,(op.ar&31)|(op.rs<<6)); - rWrite(baseAddr+ADDR_AM_DR,(op.dr&31)|(op.am<<7)); - rWrite(baseAddr+ADDR_DT2_D2R,op.d2r&31); - rWrite(baseAddr+ADDR_SL_RR,(op.rr&15)|(op.sl<<4)); - rWrite(baseAddr+ADDR_SSG,op.ssgEnv&15); - } - } if (chan[c.chan].insChanged) { - rWrite(chanOffs[c.chan]+ADDR_FB_ALG,(chan[c.chan].state.alg&7)|(chan[c.chan].state.fb<<3)); - rWrite(chanOffs[c.chan]+ADDR_LRAF,(isMuted[c.chan]?0:(chan[c.chan].pan<<6))|(chan[c.chan].state.fms&7)|((chan[c.chan].state.ams&3)<<4)); + // update custom preset + if (chan[c.chan].state.opllPreset==0) { + DivInstrumentFM::Operator& mod=chan[c.chan].state.op[0]; + DivInstrumentFM::Operator& car=chan[c.chan].state.op[1]; + rWrite(0x00,(mod.am<<7)|(mod.vib<<6)|((mod.ssgEnv&8)<<2)|(mod.ksr<<4)|(mod.mult)); + rWrite(0x01,(car.am<<7)|(car.vib<<6)|((car.ssgEnv&8)<<2)|(car.ksr<<4)|(car.mult)); + rWrite(0x02,(car.ksl<<6)|(mod.tl&63)); + rWrite(0x03,(mod.ksl<<6)|((chan[c.chan].state.fms&1)<<4)|((chan[c.chan].state.ams&1)<<3)|chan[c.chan].state.fb); + rWrite(0x04,(mod.ar<<4)|(mod.dr)); + rWrite(0x05,(car.ar<<4)|(car.dr)); + rWrite(0x06,(mod.sl<<4)|(mod.rr)); + rWrite(0x07,(car.sl<<4)|(car.rr)); + } + rWrite(0x30+c.chan,(15-(chan[c.chan].outVol*(15-chan[c.chan].state.op[1].tl))/15)|(chan[c.chan].state.opllPreset<<4)); } - */ - // for now - rWrite(0x30+c.chan,0x0|(ins->fm.opllPreset<<4)); + chan[c.chan].insChanged=false; if (c.value!=DIV_NOTE_NULL) { @@ -409,20 +392,7 @@ int DivPlatformOPLL::dispatch(DivCommand c) { if (!chan[c.chan].std.hasVol) { chan[c.chan].outVol=c.value; } - /* - for (int i=0; i<4; i++) { - unsigned short baseAddr=chanOffs[c.chan]|opOffs[i]; - DivInstrumentFM::Operator& op=chan[c.chan].state.op[i]; - if (isMuted[c.chan]) { - rWrite(baseAddr+ADDR_TL,127); - } else { - if (isOutput[chan[c.chan].state.alg][i]) { - rWrite(baseAddr+ADDR_TL,127-(((127-op.tl)*(chan[c.chan].outVol&0x7f))/127)); - } else { - rWrite(baseAddr+ADDR_TL,op.tl); - } - } - }*/ + rWrite(0x30+c.chan,(15-(chan[c.chan].outVol*(15-chan[c.chan].state.op[1].tl))/15)|(chan[c.chan].state.opllPreset<<4)); break; } case DIV_CMD_GET_VOLUME: { @@ -457,12 +427,12 @@ int DivPlatformOPLL::dispatch(DivCommand c) { return2=true; } } - if (!chan[c.chan].portaPause) { + /*if (!chan[c.chan].portaPause) { if (octave(chan[c.chan].baseFreq)!=octave(newFreq)) { chan[c.chan].portaPause=true; break; } - } + }*/ chan[c.chan].baseFreq=newFreq; chan[c.chan].portaPause=false; chan[c.chan].freqChanged=true; @@ -528,7 +498,7 @@ int DivPlatformOPLL::dispatch(DivCommand c) { return 0; break; case DIV_CMD_GET_VOLMAX: - return 127; + return 15; break; case DIV_CMD_PRE_PORTA: chan[c.chan].inPorta=c.value; @@ -543,38 +513,26 @@ int DivPlatformOPLL::dispatch(DivCommand c) { } void DivPlatformOPLL::forceIns() { - /* - for (int i=0; i<6; i++) { - for (int j=0; j<4; j++) { - unsigned short baseAddr=chanOffs[i]|opOffs[j]; - DivInstrumentFM::Operator& op=chan[i].state.op[j]; - if (isMuted[i]) { - rWrite(baseAddr+ADDR_TL,127); - } else { - if (isOutput[chan[i].state.alg][j]) { - rWrite(baseAddr+ADDR_TL,127-(((127-op.tl)*(chan[i].outVol&0x7f))/127)); - } else { - rWrite(baseAddr+ADDR_TL,op.tl); - } - } - rWrite(baseAddr+ADDR_MULT_DT,(op.mult&15)|(dtTable[op.dt&7]<<4)); - rWrite(baseAddr+ADDR_RS_AR,(op.ar&31)|(op.rs<<6)); - rWrite(baseAddr+ADDR_AM_DR,(op.dr&31)|(op.am<<7)); - rWrite(baseAddr+ADDR_DT2_D2R,op.d2r&31); - rWrite(baseAddr+ADDR_SL_RR,(op.rr&15)|(op.sl<<4)); - rWrite(baseAddr+ADDR_SSG,op.ssgEnv&15); + for (int i=0; i<9; i++) { + // update custom preset + if (chan[i].state.opllPreset==0) { + DivInstrumentFM::Operator& mod=chan[i].state.op[0]; + DivInstrumentFM::Operator& car=chan[i].state.op[1]; + rWrite(0x00,(mod.am<<7)|(mod.vib<<6)|((mod.ssgEnv&8)<<2)|(mod.ksr<<4)|(mod.mult)); + rWrite(0x01,(car.am<<7)|(car.vib<<6)|((car.ssgEnv&8)<<2)|(car.ksr<<4)|(car.mult)); + rWrite(0x02,(car.ksl<<6)|(mod.tl&63)); + rWrite(0x03,(mod.ksl<<6)|((chan[i].state.fms&1)<<4)|((chan[i].state.ams&1)<<3)|chan[i].state.fb); + rWrite(0x04,(mod.ar<<4)|(mod.dr)); + rWrite(0x05,(car.ar<<4)|(car.dr)); + rWrite(0x06,(mod.sl<<4)|(mod.rr)); + rWrite(0x07,(car.sl<<4)|(car.rr)); } - rWrite(chanOffs[i]+ADDR_FB_ALG,(chan[i].state.alg&7)|(chan[i].state.fb<<3)); - rWrite(chanOffs[i]+ADDR_LRAF,(isMuted[i]?0:(chan[i].pan<<6))|(chan[i].state.fms&7)|((chan[i].state.ams&3)<<4)); + rWrite(0x30+i,(15-(chan[i].outVol*(15-chan[i].state.op[1].tl))/15)|(chan[i].state.opllPreset<<4)); if (chan[i].active) { chan[i].keyOn=true; chan[i].freqChanged=true; } } - if (dacMode) { - rWrite(0x2b,0x80); - } - immWrite(0x22,lfoValue);*/ } void DivPlatformOPLL::toggleRegisterDump(bool enable) { @@ -590,7 +548,7 @@ unsigned char* DivPlatformOPLL::getRegisterPool() { } int DivPlatformOPLL::getRegisterPoolSize() { - return 256; + return 64; } void DivPlatformOPLL::reset() { diff --git a/src/gui/insEdit.cpp b/src/gui/insEdit.cpp index 22775dbc8..6ead6353a 100644 --- a/src/gui/insEdit.cpp +++ b/src/gui/insEdit.cpp @@ -58,13 +58,13 @@ const char* ssgEnvTypes[8]={ "Down Down Down", "Down.", "Down Up Down Up", "Down UP", "Up Up Up", "Up.", "Up Down Up Down", "Up DOWN" }; -const char* fmParamNames[3][16]={ - {"Algorithm", "Feedback", "LFO > Freq", "LFO > Amp", "Attack", "Decay", "Decay 2", "Release", "Sustain", "Level", "EnvScale", "Multiplier", "Detune", "Detune 2", "SSG-EG", "AM"}, - {"ALG", "FB", "FMS/PMS", "AMS", "AR", "DR", "SR", "RR", "SL", "TL", "KS", "MULT", "DT", "DT2", "SSG-EG", "AM"}, - {"ALG", "FB", "FMS/PMS", "AMS", "AR", "DR", "D2R", "RR", "SL", "TL", "RS", "MULT", "DT", "DT2", "SSG-EG", "AM"} +const char* fmParamNames[3][27]={ + {"Algorithm", "Feedback", "LFO > Freq", "LFO > Amp", "Attack", "Decay", "Decay 2", "Release", "Sustain", "Level", "EnvScale", "Multiplier", "Detune", "Detune 2", "SSG-EG", "AM", "AM Depth", "Vibrato Depth", "EnvAlternate", "EnvAlternate", "LevelScale/key", "Sustain", "Vibrato", "Waveform", "EnvScale/key", "OP2 HalfSine", "OP1 HalfSine"}, + {"ALG", "FB", "FMS/PMS", "AMS", "AR", "DR", "SR", "RR", "SL", "TL", "KS", "MULT", "DT", "DT2", "SSG-EG", "AM", "AMD", "FMD", "EGT", "EGT", "KSL", "SUS", "VIB", "WS", "KSR", "DC", "DM"}, + {"ALG", "FB", "FMS/PMS", "AMS", "AR", "DR", "D2R", "RR", "SL", "TL", "RS", "MULT", "DT", "DT2", "SSG-EG", "AM", "DAM", "DVB", "EGT", "EGS", "KSL", "SUS", "VIB", "WS", "KSR", "DC", "DM"} }; -const char* opllInsNames[18]={ +const char* opllInsNames[17]={ "User", "Violin", "Guitar", @@ -100,7 +100,18 @@ enum FMParams { FM_DT=12, FM_DT2=13, FM_SSG=14, - FM_AM=15 + FM_AM=15, + FM_DAM=16, + FM_DVB=17, + FM_EGT=18, + FM_EGS=19, + FM_KSL=20, + FM_SUS=21, + FM_VIB=22, + FM_WS=23, + FM_KSR=24, + FM_DC=25, + FM_DM=26 }; #define FM_NAME(x) fmParamNames[settings.fmNames][x] @@ -429,6 +440,41 @@ void FurnaceGUI::drawAlgorithm(unsigned char alg, FurnaceGUIFMAlgs algType, cons } } break; + case FM_ALGS_2OP_OPL: + switch (alg) { + case 0: { // 1 > 2 + ImVec2 pos1=ImLerp(rect.Min,rect.Max,ImVec2(0.33,0.5)); + ImVec2 pos2=ImLerp(rect.Min,rect.Max,ImVec2(0.67,0.5)); + dl->AddCircleFilled(pos1,4.0f*dpiScale+1.0f,color); + dl->AddCircle(pos1,6.0f*dpiScale+1.0f,color); + dl->AddLine(pos1,pos2,colorL); + dl->AddCircleFilled(pos2,4.0f*dpiScale+1.0f,color); + + pos1.x-=ImGui::CalcTextSize("2").x+circleRadius+3.0*dpiScale; + pos2.x+=circleRadius+3.0*dpiScale; + pos1.y-=ImGui::CalcTextSize("1").y*0.5; + pos2.y-=ImGui::CalcTextSize("2").y*0.5; + dl->AddText(pos1,color,"1"); + dl->AddText(pos2,color,"2"); + break; + } + case 1: { // 1 + 2 + ImVec2 pos1=ImLerp(rect.Min,rect.Max,ImVec2(0.33,0.5)); + ImVec2 pos2=ImLerp(rect.Min,rect.Max,ImVec2(0.67,0.5)); + dl->AddCircleFilled(pos1,4.0f*dpiScale+1.0f,color); + dl->AddCircle(pos1,6.0f*dpiScale+1.0f,color); + dl->AddCircleFilled(pos2,4.0f*dpiScale+1.0f,color); + + pos1.x-=ImGui::CalcTextSize("2").x+circleRadius+3.0*dpiScale; + pos2.x+=circleRadius+3.0*dpiScale; + pos1.y-=ImGui::CalcTextSize("1").y*0.5; + pos2.y-=ImGui::CalcTextSize("2").y*0.5; + dl->AddText(pos1,color,"1"); + dl->AddText(pos2,color,"2"); + break; + } + } + break; default: break; } @@ -735,7 +781,7 @@ void FurnaceGUI::drawInsEdit() { } if (ImGui::BeginTabBar("insEditTab")) { - if (ins->type==DIV_INS_FM) { + if (ins->type==DIV_INS_FM || ins->type==DIV_INS_OPL || ins->type==DIV_INS_OPLL || ins->type==DIV_INS_OPZ) { char label[32]; float asFloat[256]; int asInt[256]; @@ -746,19 +792,72 @@ void FurnaceGUI::drawInsEdit() { ImGui::TableSetupColumn("c1",ImGuiTableColumnFlags_WidthStretch,0.0); ImGui::TableSetupColumn("c2",ImGuiTableColumnFlags_WidthStretch,0.0); ImGui::TableNextRow(); - ImGui::TableNextColumn(); - P(ImGui::SliderScalar(FM_NAME(FM_FB),ImGuiDataType_U8,&ins->fm.fb,&_ZERO,&_SEVEN)); - P(ImGui::SliderScalar(FM_NAME(FM_FMS),ImGuiDataType_U8,&ins->fm.fms,&_ZERO,&_SEVEN)); - ImGui::TableNextColumn(); - P(ImGui::SliderScalar(FM_NAME(FM_ALG),ImGuiDataType_U8,&ins->fm.alg,&_ZERO,&_SEVEN)); - P(ImGui::SliderScalar(FM_NAME(FM_AMS),ImGuiDataType_U8,&ins->fm.ams,&_ZERO,&_THREE)); - ImGui::TableNextColumn(); - drawAlgorithm(ins->fm.alg,FM_ALGS_4OP,ImVec2(ImGui::GetContentRegionAvail().x,48.0*dpiScale)); + switch (ins->type) { + case DIV_INS_FM: + case DIV_INS_OPZ: + ImGui::TableNextColumn(); + P(ImGui::SliderScalar(FM_NAME(FM_FB),ImGuiDataType_U8,&ins->fm.fb,&_ZERO,&_SEVEN)); + P(ImGui::SliderScalar(FM_NAME(FM_FMS),ImGuiDataType_U8,&ins->fm.fms,&_ZERO,&_SEVEN)); + ImGui::TableNextColumn(); + P(ImGui::SliderScalar(FM_NAME(FM_ALG),ImGuiDataType_U8,&ins->fm.alg,&_ZERO,&_SEVEN)); + P(ImGui::SliderScalar(FM_NAME(FM_AMS),ImGuiDataType_U8,&ins->fm.ams,&_ZERO,&_THREE)); + ImGui::TableNextColumn(); + drawAlgorithm(ins->fm.alg,FM_ALGS_4OP,ImVec2(ImGui::GetContentRegionAvail().x,48.0*dpiScale)); + break; + case DIV_INS_OPL: + case DIV_INS_OPLL: { + bool dc=ins->fm.fms; + bool dm=ins->fm.ams; + bool sus=ins->fm.alg; + ImGui::TableNextColumn(); + ImGui::BeginDisabled(ins->fm.opllPreset!=0); + P(ImGui::SliderScalar(FM_NAME(FM_FB),ImGuiDataType_U8,&ins->fm.fb,&_ZERO,&_SEVEN)); + if (ImGui::Checkbox(FM_NAME(FM_DC),&dc)) { PARAMETER + ins->fm.fms=dc; + } + ImGui::EndDisabled(); + ImGui::TableNextColumn(); + if (ImGui::Checkbox(FM_NAME(FM_SUS),&sus)) { PARAMETER + ins->fm.alg=sus; + } + ImGui::BeginDisabled(ins->fm.opllPreset!=0); + if (ImGui::Checkbox(FM_NAME(FM_DM),&dm)) { PARAMETER + ins->fm.ams=dm; + } + ImGui::EndDisabled(); + ImGui::TableNextColumn(); + drawAlgorithm(0,FM_ALGS_2OP_OPL,ImVec2(ImGui::GetContentRegionAvail().x,24.0*dpiScale)); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + if (ImGui::BeginCombo("##LLPreset",opllInsNames[ins->fm.opllPreset])) { + for (int i=0; i<17; i++) { + if (ImGui::Selectable(opllInsNames[i])) { + ins->fm.opllPreset=i; + } + } + ImGui::EndCombo(); + } + break; + } + default: + break; + } ImGui::EndTable(); } - if (ImGui::BeginTable("FMOperators",2,ImGuiTableFlags_SizingStretchSame)) { - for (int i=0; i<4; i++) { - DivInstrumentFM::Operator& op=ins->fm.op[opOrder[i]]; + + if (ins->type==DIV_INS_OPLL && ins->fm.opllPreset==16) { + ImGui::Text("the Drums patch is only there for compatibility.\nit is highly encouraged you use the OPLL (drums) system instead!"); + } + + bool willDisplayOps=true; + int opCount=4; + if (ins->type==DIV_INS_OPLL && ins->fm.opllPreset!=0) willDisplayOps=false; + if (ins->type==DIV_INS_OPL || ins->type==DIV_INS_OPLL) opCount=2; + if (!willDisplayOps && ins->type==DIV_INS_OPLL) { + P(ImGui::SliderScalar("Volume##TL",ImGuiDataType_U8,&ins->fm.op[1].tl,&_FIFTEEN,&_ZERO)); + } + if (willDisplayOps) if (ImGui::BeginTable("FMOperators",2,ImGuiTableFlags_SizingStretchSame)) { + for (int i=0; ifm.op[(opCount==4)?opOrder[i]:i]; if ((i+1)&1) ImGui::TableNextRow(); ImGui::TableNextColumn(); ImGui::Separator(); @@ -775,13 +874,27 @@ void FurnaceGUI::drawInsEdit() { ImGui::SameLine(); + int maxTl=127; + if (ins->type==DIV_INS_OPLL) { + if (i==1) { + maxTl=15; + } else { + maxTl=63; + } + } + bool ssgOn=op.ssgEnv&8; + bool ksrOn=op.ksr; + bool vibOn=op.vib; unsigned char ssgEnv=op.ssgEnv&7; - if (ImGui::Checkbox("SSG On",&ssgOn)) { PARAMETER + int maxArDr=(ins->type==DIV_INS_FM || ins->type==DIV_INS_OPZ)?31:15; + if (ImGui::Checkbox((ins->type==DIV_INS_OPL || ins->type==DIV_INS_OPLL)?FM_NAME(FM_EGS):"SSG On",&ssgOn)) { PARAMETER op.ssgEnv=(op.ssgEnv&7)|(ssgOn<<3); } - if (ImGui::IsItemHovered()) { - ImGui::SetTooltip("Only for Genesis and Neo Geo systems"); + if (ins->type==DIV_INS_FM) { + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("Only for Genesis and Neo Geo systems"); + } } //52.0 controls vert scaling; default 96 @@ -794,14 +907,14 @@ void FurnaceGUI::drawInsEdit() { ImGui::TableNextRow(); ImGui::TableNextColumn(); ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); - P(ImGui::SliderScalar("##AR",ImGuiDataType_U8,&op.ar,&_THIRTY_ONE,&_ZERO)); + P(ImGui::SliderScalar("##AR",ImGuiDataType_U8,&op.ar,&maxArDr,&_ZERO)); ImGui::TableNextColumn(); ImGui::Text("%s",FM_NAME(FM_AR)); ImGui::TableNextRow(); ImGui::TableNextColumn(); ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); - P(ImGui::SliderScalar("##DR",ImGuiDataType_U8,&op.dr,&_THIRTY_ONE,&_ZERO)); + P(ImGui::SliderScalar("##DR",ImGuiDataType_U8,&op.dr,&maxArDr,&_ZERO)); ImGui::TableNextColumn(); ImGui::Text("%s",FM_NAME(FM_DR)); @@ -812,12 +925,14 @@ void FurnaceGUI::drawInsEdit() { ImGui::TableNextColumn(); ImGui::Text("%s",FM_NAME(FM_SL)); - ImGui::TableNextRow(); - ImGui::TableNextColumn(); - ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); - P(ImGui::SliderScalar("##D2R",ImGuiDataType_U8,&op.d2r,&_THIRTY_ONE,&_ZERO)); - ImGui::TableNextColumn(); - ImGui::Text("%s",FM_NAME(FM_D2R)); + if (ins->type==DIV_INS_FM || ins->type==DIV_INS_OPZ) { + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + P(ImGui::SliderScalar("##D2R",ImGuiDataType_U8,&op.d2r,&_THIRTY_ONE,&_ZERO)); + ImGui::TableNextColumn(); + ImGui::Text("%s",FM_NAME(FM_D2R)); + } ImGui::TableNextRow(); ImGui::TableNextColumn(); @@ -829,7 +944,7 @@ void FurnaceGUI::drawInsEdit() { ImGui::TableNextRow(); ImGui::TableNextColumn(); ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); - P(ImGui::SliderScalar("##TL",ImGuiDataType_U8,&op.tl,&_ONE_HUNDRED_TWENTY_SEVEN,&_ZERO)); + P(ImGui::SliderScalar("##TL",ImGuiDataType_U8,&op.tl,&maxTl,&_ZERO)); ImGui::TableNextColumn(); ImGui::Text("%s",FM_NAME(FM_TL)); @@ -842,9 +957,15 @@ void FurnaceGUI::drawInsEdit() { ImGui::TableNextRow(); ImGui::TableNextColumn(); ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); - P(ImGui::SliderScalar("##RS",ImGuiDataType_U8,&op.rs,&_ZERO,&_THREE)); - ImGui::TableNextColumn(); - ImGui::Text("%s",FM_NAME(FM_RS)); + if (ins->type==DIV_INS_FM || ins->type==DIV_INS_OPZ) { + P(ImGui::SliderScalar("##RS",ImGuiDataType_U8,&op.rs,&_ZERO,&_THREE)); + ImGui::TableNextColumn(); + ImGui::Text("%s",FM_NAME(FM_RS)); + } else { + P(ImGui::SliderScalar("##KSL",ImGuiDataType_U8,&op.ksl,&_ZERO,&_THREE)); + ImGui::TableNextColumn(); + ImGui::Text("%s",FM_NAME(FM_KSL)); + } ImGui::TableNextRow(); ImGui::TableNextColumn(); @@ -853,37 +974,50 @@ void FurnaceGUI::drawInsEdit() { ImGui::TableNextColumn(); ImGui::Text("%s",FM_NAME(FM_MULT)); - int detune=(op.dt&7)-3; - ImGui::TableNextRow(); - ImGui::TableNextColumn(); - ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); - if (ImGui::SliderInt("##DT",&detune,-3,3)) { PARAMETER - op.dt=detune+3; - } - ImGui::TableNextColumn(); - ImGui::Text("%s",FM_NAME(FM_DT)); + if (ins->type==DIV_INS_FM || ins->type==DIV_INS_OPZ) { + int detune=(op.dt&7)-3; + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + if (ImGui::SliderInt("##DT",&detune,-3,3)) { PARAMETER + op.dt=detune+3; + } + ImGui::TableNextColumn(); + ImGui::Text("%s",FM_NAME(FM_DT)); - ImGui::TableNextRow(); - ImGui::TableNextColumn(); - ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); - P(ImGui::SliderScalar("##DT2",ImGuiDataType_U8,&op.dt2,&_ZERO,&_THREE)); - if (ImGui::IsItemHovered()) { - ImGui::SetTooltip("Only for Arcade system"); - } - ImGui::TableNextColumn(); - ImGui::Text("%s",FM_NAME(FM_DT2)); + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + P(ImGui::SliderScalar("##DT2",ImGuiDataType_U8,&op.dt2,&_ZERO,&_THREE)); + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("Only for Arcade system"); + } + ImGui::TableNextColumn(); + ImGui::Text("%s",FM_NAME(FM_DT2)); - ImGui::TableNextRow(); - ImGui::TableNextColumn(); - ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); - if (ImGui::SliderScalar("##SSG",ImGuiDataType_U8,&ssgEnv,&_ZERO,&_SEVEN,ssgEnvTypes[ssgEnv])) { PARAMETER - op.ssgEnv=(op.ssgEnv&8)|(ssgEnv&7); + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + if (ImGui::SliderScalar("##SSG",ImGuiDataType_U8,&ssgEnv,&_ZERO,&_SEVEN,ssgEnvTypes[ssgEnv])) { PARAMETER + op.ssgEnv=(op.ssgEnv&8)|(ssgEnv&7); + } + ImGui::TableNextColumn(); + ImGui::Text("%s",FM_NAME(FM_SSG)); } - ImGui::TableNextColumn(); - ImGui::Text("%s",FM_NAME(FM_SSG)); ImGui::EndTable(); } + + if (ins->type==DIV_INS_OPLL || ins->type==DIV_INS_OPL) { + if (ImGui::Checkbox(FM_NAME(FM_VIB),&vibOn)) { PARAMETER + op.vib=vibOn; + } + ImGui::SameLine(); + if (ImGui::Checkbox(FM_NAME(FM_KSR),&ksrOn)) { PARAMETER + op.ksr=ksrOn; + } + } + ImGui::PopID(); } ImGui::EndTable();