dev115 - automatic system detection
This commit is contained in:
parent
a17f499384
commit
e22d7484cb
|
@ -32,6 +32,7 @@ these fields are 0 in format versions prior to 100 (0.6pre1).
|
||||||
|
|
||||||
the format versions are:
|
the format versions are:
|
||||||
|
|
||||||
|
- 115: Furnace dev115
|
||||||
- 114: Furnace dev114
|
- 114: Furnace dev114
|
||||||
- 113: Furnace dev113
|
- 113: Furnace dev113
|
||||||
- 112: Furnace dev112
|
- 112: Furnace dev112
|
||||||
|
@ -342,7 +343,9 @@ size | description
|
||||||
1 | SN periods under 8 are treated as 1 (>=108) or reserved
|
1 | SN periods under 8 are treated as 1 (>=108) or reserved
|
||||||
1 | cut/delay effect policy (>=110) or reserved
|
1 | cut/delay effect policy (>=110) or reserved
|
||||||
1 | 0B/0D effect treatment (>=113) or reserved
|
1 | 0B/0D effect treatment (>=113) or reserved
|
||||||
4 | reserved
|
1 | automatic system name detection (>=115) or reserved
|
||||||
|
| - this one isn't a compatibility flag, but it's here for convenience...
|
||||||
|
3 | reserved
|
||||||
--- | **virtual tempo data**
|
--- | **virtual tempo data**
|
||||||
2 | virtual tempo numerator of first song (>=96) or reserved
|
2 | virtual tempo numerator of first song (>=96) or reserved
|
||||||
2 | virtual tempo denominator of first song (>=96) or reserved
|
2 | virtual tempo denominator of first song (>=96) or reserved
|
||||||
|
@ -499,7 +502,11 @@ size | description
|
||||||
1 | ws
|
1 | ws
|
||||||
1 | ksr
|
1 | ksr
|
||||||
1 | operator enabled (>=114) or reserved
|
1 | operator enabled (>=114) or reserved
|
||||||
11 | reserved
|
1 | KVS mode (>=115) or reserved
|
||||||
|
| - 0: off
|
||||||
|
| - 1: on
|
||||||
|
| - 2: auto (depending on alg)
|
||||||
|
10 | reserved
|
||||||
--- | **Game Boy instrument data**
|
--- | **Game Boy instrument data**
|
||||||
1 | volume
|
1 | volume
|
||||||
1 | direction
|
1 | direction
|
||||||
|
|
|
@ -46,8 +46,8 @@
|
||||||
#define BUSY_BEGIN_SOFT softLocked=true; isBusy.lock();
|
#define BUSY_BEGIN_SOFT softLocked=true; isBusy.lock();
|
||||||
#define BUSY_END isBusy.unlock(); softLocked=false;
|
#define BUSY_END isBusy.unlock(); softLocked=false;
|
||||||
|
|
||||||
#define DIV_VERSION "dev114"
|
#define DIV_VERSION "dev115"
|
||||||
#define DIV_ENGINE_VERSION 114
|
#define DIV_ENGINE_VERSION 115
|
||||||
// for imports
|
// for imports
|
||||||
#define DIV_VERSION_MOD 0xff01
|
#define DIV_VERSION_MOD 0xff01
|
||||||
#define DIV_VERSION_FC 0xff02
|
#define DIV_VERSION_FC 0xff02
|
||||||
|
|
|
@ -1085,6 +1085,9 @@ bool DivEngine::loadFur(unsigned char* file, size_t len) {
|
||||||
if (ds.version<113) {
|
if (ds.version<113) {
|
||||||
ds.jumpTreatment=1;
|
ds.jumpTreatment=1;
|
||||||
}
|
}
|
||||||
|
if (ds.version<115) {
|
||||||
|
ds.autoSystem=false;
|
||||||
|
}
|
||||||
ds.isDMF=false;
|
ds.isDMF=false;
|
||||||
|
|
||||||
reader.readS(); // reserved
|
reader.readS(); // reserved
|
||||||
|
@ -1512,7 +1515,12 @@ bool DivEngine::loadFur(unsigned char* file, size_t len) {
|
||||||
} else {
|
} else {
|
||||||
reader.readC();
|
reader.readC();
|
||||||
}
|
}
|
||||||
for (int i=0; i<4; i++) {
|
if (ds.version>=115) {
|
||||||
|
ds.autoSystem=reader.readC();
|
||||||
|
} else {
|
||||||
|
reader.readC();
|
||||||
|
}
|
||||||
|
for (int i=0; i<3; i++) {
|
||||||
reader.readC();
|
reader.readC();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1549,6 +1557,7 @@ bool DivEngine::loadFur(unsigned char* file, size_t len) {
|
||||||
ds.categoryJ=reader.readString();
|
ds.categoryJ=reader.readString();
|
||||||
} else {
|
} else {
|
||||||
ds.systemName=getSongSystemLegacyName(ds,!getConfInt("noMultiSystem",0));
|
ds.systemName=getSongSystemLegacyName(ds,!getConfInt("noMultiSystem",0));
|
||||||
|
ds.autoSystem=true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// read subsongs
|
// read subsongs
|
||||||
|
@ -3751,7 +3760,8 @@ SafeWriter* DivEngine::saveFur(bool notPrimary) {
|
||||||
w->writeC(song.snNoLowPeriods);
|
w->writeC(song.snNoLowPeriods);
|
||||||
w->writeC(song.delayBehavior);
|
w->writeC(song.delayBehavior);
|
||||||
w->writeC(song.jumpTreatment);
|
w->writeC(song.jumpTreatment);
|
||||||
for (int i=0; i<4; i++) {
|
w->writeC(song.autoSystem);
|
||||||
|
for (int i=0; i<3; i++) {
|
||||||
w->writeC(0);
|
w->writeC(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -72,9 +72,10 @@ void DivInstrument::putInsData(SafeWriter* w) {
|
||||||
w->writeC(op.ksr);
|
w->writeC(op.ksr);
|
||||||
|
|
||||||
w->writeC(op.enable);
|
w->writeC(op.enable);
|
||||||
|
w->writeC(op.kvs);
|
||||||
|
|
||||||
// reserved
|
// reserved
|
||||||
for (int k=0; k<11; k++) {
|
for (int k=0; k<10; k++) {
|
||||||
w->writeC(0);
|
w->writeC(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -724,8 +725,15 @@ DivDataErrors DivInstrument::readInsData(SafeReader& reader, short version) {
|
||||||
reader.readC();
|
reader.readC();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (version>=115) {
|
||||||
|
op.kvs=reader.readC();
|
||||||
|
} else {
|
||||||
|
op.kvs=2;
|
||||||
|
reader.readC();
|
||||||
|
}
|
||||||
|
|
||||||
// reserved
|
// reserved
|
||||||
for (int k=0; k<11; k++) reader.readC();
|
for (int k=0; k<10; k++) reader.readC();
|
||||||
}
|
}
|
||||||
|
|
||||||
// GB
|
// GB
|
||||||
|
|
|
@ -87,6 +87,7 @@ struct DivInstrumentFM {
|
||||||
bool enable;
|
bool enable;
|
||||||
unsigned char am, ar, dr, mult, rr, sl, tl, dt2, rs, dt, d2r, ssgEnv;
|
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/OPL/OPZ
|
unsigned char dam, dvb, egt, ksl, sus, vib, ws, ksr; // YMU759/OPL/OPZ
|
||||||
|
unsigned char kvs;
|
||||||
Operator():
|
Operator():
|
||||||
enable(true),
|
enable(true),
|
||||||
am(0),
|
am(0),
|
||||||
|
@ -108,7 +109,8 @@ struct DivInstrumentFM {
|
||||||
sus(0),
|
sus(0),
|
||||||
vib(0),
|
vib(0),
|
||||||
ws(0),
|
ws(0),
|
||||||
ksr(0) {}
|
ksr(0),
|
||||||
|
kvs(2) {}
|
||||||
} op[4];
|
} op[4];
|
||||||
DivInstrumentFM():
|
DivInstrumentFM():
|
||||||
alg(0),
|
alg(0),
|
||||||
|
|
|
@ -511,6 +511,7 @@ struct DivSong {
|
||||||
bool e1e2StopOnSameNote;
|
bool e1e2StopOnSameNote;
|
||||||
bool brokenPortaArp;
|
bool brokenPortaArp;
|
||||||
bool snNoLowPeriods;
|
bool snNoLowPeriods;
|
||||||
|
bool autoSystem;
|
||||||
|
|
||||||
std::vector<DivInstrument*> ins;
|
std::vector<DivInstrument*> ins;
|
||||||
std::vector<DivWavetable*> wave;
|
std::vector<DivWavetable*> wave;
|
||||||
|
@ -614,7 +615,8 @@ struct DivSong {
|
||||||
brokenOutVol(false),
|
brokenOutVol(false),
|
||||||
e1e2StopOnSameNote(false),
|
e1e2StopOnSameNote(false),
|
||||||
brokenPortaArp(false),
|
brokenPortaArp(false),
|
||||||
snNoLowPeriods(false) {
|
snNoLowPeriods(false),
|
||||||
|
autoSystem(true) {
|
||||||
for (int i=0; i<32; i++) {
|
for (int i=0; i<32; i++) {
|
||||||
system[i]=DIV_SYSTEM_NULL;
|
system[i]=DIV_SYSTEM_NULL;
|
||||||
systemVol[i]=64;
|
systemVol[i]=64;
|
||||||
|
|
|
@ -584,6 +584,78 @@ void FurnaceGUI::updateWindowTitle() {
|
||||||
if (sdlWin!=NULL) SDL_SetWindowTitle(sdlWin,title.c_str());
|
if (sdlWin!=NULL) SDL_SetWindowTitle(sdlWin,title.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FurnaceGUI::autoDetectSystem() {
|
||||||
|
std::map<DivSystem,int> sysCountMap;
|
||||||
|
for (int i=0; i<e->song.systemLen; i++) {
|
||||||
|
try {
|
||||||
|
sysCountMap.at(e->song.system[i])++;
|
||||||
|
} catch (std::exception& ex) {
|
||||||
|
sysCountMap[e->song.system[i]]=1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
logV("sysCountMap:");
|
||||||
|
for (std::pair<DivSystem,int> k: sysCountMap) {
|
||||||
|
logV("%s: %d",e->getSystemName(k.first),k.second);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isMatch=false;
|
||||||
|
std::map<DivSystem,int> defCountMap;
|
||||||
|
for (FurnaceGUISysCategory& i: sysCategories) {
|
||||||
|
for (FurnaceGUISysDef& j: i.systems) {
|
||||||
|
defCountMap.clear();
|
||||||
|
for (size_t k=0; k<j.definition.size(); k+=4) {
|
||||||
|
if (j.definition[k]==0) break;
|
||||||
|
try {
|
||||||
|
defCountMap.at((DivSystem)j.definition[k])++;
|
||||||
|
} catch (std::exception& ex) {
|
||||||
|
defCountMap[(DivSystem)j.definition[k]]=1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (defCountMap.size()!=sysCountMap.size()) continue;
|
||||||
|
isMatch=true;
|
||||||
|
logV("trying on defCountMap: %s",j.name);
|
||||||
|
for (std::pair<DivSystem,int> k: defCountMap) {
|
||||||
|
logV("- %s: %d",e->getSystemName(k.first),k.second);
|
||||||
|
}
|
||||||
|
for (std::pair<DivSystem,int> k: defCountMap) {
|
||||||
|
try {
|
||||||
|
if (sysCountMap.at(k.first)!=k.second) {
|
||||||
|
isMatch=false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} catch (std::exception& ex) {
|
||||||
|
isMatch=false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isMatch) {
|
||||||
|
logV("match found!");
|
||||||
|
e->song.systemName=j.name;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isMatch) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isMatch) {
|
||||||
|
bool isFirst=true;
|
||||||
|
e->song.systemName="";
|
||||||
|
for (std::pair<DivSystem,int> k: sysCountMap) {
|
||||||
|
if (!isFirst) e->song.systemName+=" + ";
|
||||||
|
if (k.second>1) {
|
||||||
|
e->song.systemName+=fmt::sprintf("%d×",k.second);
|
||||||
|
}
|
||||||
|
if (k.first==DIV_SYSTEM_N163) {
|
||||||
|
e->song.systemName+=settings.c163Name;
|
||||||
|
} else {
|
||||||
|
e->song.systemName+=e->getSystemName(k.first);
|
||||||
|
}
|
||||||
|
isFirst=false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ImVec4 FurnaceGUI::channelColor(int ch) {
|
ImVec4 FurnaceGUI::channelColor(int ch) {
|
||||||
switch (settings.channelColors) {
|
switch (settings.channelColors) {
|
||||||
case 0:
|
case 0:
|
||||||
|
@ -3262,6 +3334,9 @@ bool FurnaceGUI::loop() {
|
||||||
showError("cannot add chip! ("+e->getLastError()+")");
|
showError("cannot add chip! ("+e->getLastError()+")");
|
||||||
}
|
}
|
||||||
ImGui::CloseCurrentPopup();
|
ImGui::CloseCurrentPopup();
|
||||||
|
if (e->song.autoSystem) {
|
||||||
|
autoDetectSystem();
|
||||||
|
}
|
||||||
updateWindowTitle();
|
updateWindowTitle();
|
||||||
}
|
}
|
||||||
ImGui::EndMenu();
|
ImGui::EndMenu();
|
||||||
|
@ -3282,6 +3357,9 @@ bool FurnaceGUI::loop() {
|
||||||
DivSystem picked=systemPicker();
|
DivSystem picked=systemPicker();
|
||||||
if (picked!=DIV_SYSTEM_NULL) {
|
if (picked!=DIV_SYSTEM_NULL) {
|
||||||
e->changeSystem(i,picked,preserveChanPos);
|
e->changeSystem(i,picked,preserveChanPos);
|
||||||
|
if (e->song.autoSystem) {
|
||||||
|
autoDetectSystem();
|
||||||
|
}
|
||||||
updateWindowTitle();
|
updateWindowTitle();
|
||||||
ImGui::CloseCurrentPopup();
|
ImGui::CloseCurrentPopup();
|
||||||
}
|
}
|
||||||
|
@ -3297,6 +3375,10 @@ bool FurnaceGUI::loop() {
|
||||||
if (!e->removeSystem(i,preserveChanPos)) {
|
if (!e->removeSystem(i,preserveChanPos)) {
|
||||||
showError("cannot remove chip! ("+e->getLastError()+")");
|
showError("cannot remove chip! ("+e->getLastError()+")");
|
||||||
}
|
}
|
||||||
|
if (e->song.autoSystem) {
|
||||||
|
autoDetectSystem();
|
||||||
|
updateWindowTitle();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ImGui::EndMenu();
|
ImGui::EndMenu();
|
||||||
|
@ -4415,6 +4497,10 @@ bool FurnaceGUI::loop() {
|
||||||
case GUI_WARN_SYSTEM_DEL:
|
case GUI_WARN_SYSTEM_DEL:
|
||||||
if (ImGui::Button("Yes")) {
|
if (ImGui::Button("Yes")) {
|
||||||
e->removeSystem(sysToDelete,preserveChanPos);
|
e->removeSystem(sysToDelete,preserveChanPos);
|
||||||
|
if (e->song.autoSystem) {
|
||||||
|
autoDetectSystem();
|
||||||
|
updateWindowTitle();
|
||||||
|
}
|
||||||
ImGui::CloseCurrentPopup();
|
ImGui::CloseCurrentPopup();
|
||||||
}
|
}
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
|
@ -5069,6 +5155,7 @@ FurnaceGUI::FurnaceGUI():
|
||||||
macroPointSize(16),
|
macroPointSize(16),
|
||||||
waveEditStyle(0),
|
waveEditStyle(0),
|
||||||
mobileMenuPos(0.0f),
|
mobileMenuPos(0.0f),
|
||||||
|
autoButtonSize(0.0f),
|
||||||
curSysSection(NULL),
|
curSysSection(NULL),
|
||||||
pendingRawSampleDepth(8),
|
pendingRawSampleDepth(8),
|
||||||
pendingRawSampleChannels(1),
|
pendingRawSampleChannels(1),
|
||||||
|
|
|
@ -1018,7 +1018,7 @@ class FurnaceGUI {
|
||||||
int drawHalt;
|
int drawHalt;
|
||||||
int macroPointSize;
|
int macroPointSize;
|
||||||
int waveEditStyle;
|
int waveEditStyle;
|
||||||
float mobileMenuPos;
|
float mobileMenuPos, autoButtonSize;
|
||||||
const int* curSysSection;
|
const int* curSysSection;
|
||||||
|
|
||||||
String pendingRawSample;
|
String pendingRawSample;
|
||||||
|
@ -1610,6 +1610,7 @@ class FurnaceGUI {
|
||||||
bool CWVSliderInt(const char* label, const ImVec2& size, int* v, int v_min, int v_max, const char* format="%d", ImGuiSliderFlags flags=0);
|
bool CWVSliderInt(const char* label, const ImVec2& size, int* v, int v_min, int v_max, const char* format="%d", ImGuiSliderFlags flags=0);
|
||||||
|
|
||||||
void updateWindowTitle();
|
void updateWindowTitle();
|
||||||
|
void autoDetectSystem();
|
||||||
void prepareLayout();
|
void prepareLayout();
|
||||||
ImVec4 channelColor(int ch);
|
ImVec4 channelColor(int ch);
|
||||||
ImVec4 channelTextColor(int ch);
|
ImVec4 channelTextColor(int ch);
|
||||||
|
|
|
@ -77,11 +77,23 @@ void FurnaceGUI::drawSongInfo() {
|
||||||
ImGui::TableNextColumn();
|
ImGui::TableNextColumn();
|
||||||
ImGui::Text("System");
|
ImGui::Text("System");
|
||||||
ImGui::TableNextColumn();
|
ImGui::TableNextColumn();
|
||||||
ImGui::SetNextItemWidth(avail);
|
ImGui::SetNextItemWidth(MAX(16.0f*dpiScale,avail-autoButtonSize-ImGui::GetStyle().ItemSpacing.x));
|
||||||
if (ImGui::InputText("##SystemName",&e->song.systemName)) {
|
if (ImGui::InputText("##SystemName",&e->song.systemName)) {
|
||||||
MARK_MODIFIED;
|
MARK_MODIFIED;
|
||||||
updateWindowTitle();
|
updateWindowTitle();
|
||||||
|
e->song.autoSystem=false;
|
||||||
}
|
}
|
||||||
|
ImGui::SameLine();
|
||||||
|
pushToggleColors(e->song.autoSystem);
|
||||||
|
if (ImGui::Button("Auto")) {
|
||||||
|
e->song.autoSystem=!e->song.autoSystem;
|
||||||
|
if (e->song.autoSystem) {
|
||||||
|
autoDetectSystem();
|
||||||
|
updateWindowTitle();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
popToggleColors();
|
||||||
|
autoButtonSize=ImGui::GetItemRectSize().x;
|
||||||
|
|
||||||
ImGui::EndTable();
|
ImGui::EndTable();
|
||||||
}
|
}
|
||||||
|
|
|
@ -765,6 +765,9 @@ void FurnaceGUI::drawSysConf(int chan, DivSystem type, unsigned int& flags, bool
|
||||||
if (copyOfFlags!=flags) {
|
if (copyOfFlags!=flags) {
|
||||||
if (chan>=0) {
|
if (chan>=0) {
|
||||||
e->setSysFlags(chan,copyOfFlags,restart);
|
e->setSysFlags(chan,copyOfFlags,restart);
|
||||||
|
if (e->song.autoSystem) {
|
||||||
|
autoDetectSystem();
|
||||||
|
}
|
||||||
updateWindowTitle();
|
updateWindowTitle();
|
||||||
} else {
|
} else {
|
||||||
flags=copyOfFlags;
|
flags=copyOfFlags;
|
||||||
|
|
|
@ -82,6 +82,9 @@ void FurnaceGUI::drawSysManager() {
|
||||||
DivSystem picked=systemPicker();
|
DivSystem picked=systemPicker();
|
||||||
if (picked!=DIV_SYSTEM_NULL) {
|
if (picked!=DIV_SYSTEM_NULL) {
|
||||||
e->changeSystem(i,picked,preserveChanPos);
|
e->changeSystem(i,picked,preserveChanPos);
|
||||||
|
if (e->song.autoSystem) {
|
||||||
|
autoDetectSystem();
|
||||||
|
}
|
||||||
updateWindowTitle();
|
updateWindowTitle();
|
||||||
ImGui::CloseCurrentPopup();
|
ImGui::CloseCurrentPopup();
|
||||||
}
|
}
|
||||||
|
@ -110,6 +113,9 @@ void FurnaceGUI::drawSysManager() {
|
||||||
if (!e->addSystem(picked)) {
|
if (!e->addSystem(picked)) {
|
||||||
showError("cannot add chip! ("+e->getLastError()+")");
|
showError("cannot add chip! ("+e->getLastError()+")");
|
||||||
}
|
}
|
||||||
|
if (e->song.autoSystem) {
|
||||||
|
autoDetectSystem();
|
||||||
|
}
|
||||||
updateWindowTitle();
|
updateWindowTitle();
|
||||||
ImGui::CloseCurrentPopup();
|
ImGui::CloseCurrentPopup();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue