dev115 - automatic system detection

This commit is contained in:
tildearrow 2022-09-21 19:27:42 -05:00
parent a17f499384
commit e22d7484cb
11 changed files with 150 additions and 12 deletions

View file

@ -32,6 +32,7 @@ these fields are 0 in format versions prior to 100 (0.6pre1).
the format versions are:
- 115: Furnace dev115
- 114: Furnace dev114
- 113: Furnace dev113
- 112: Furnace dev112
@ -342,7 +343,9 @@ size | description
1 | SN periods under 8 are treated as 1 (>=108) or reserved
1 | cut/delay effect policy (>=110) 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**
2 | virtual tempo numerator 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 | ksr
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**
1 | volume
1 | direction

View file

@ -46,8 +46,8 @@
#define BUSY_BEGIN_SOFT softLocked=true; isBusy.lock();
#define BUSY_END isBusy.unlock(); softLocked=false;
#define DIV_VERSION "dev114"
#define DIV_ENGINE_VERSION 114
#define DIV_VERSION "dev115"
#define DIV_ENGINE_VERSION 115
// for imports
#define DIV_VERSION_MOD 0xff01
#define DIV_VERSION_FC 0xff02

View file

@ -1085,6 +1085,9 @@ bool DivEngine::loadFur(unsigned char* file, size_t len) {
if (ds.version<113) {
ds.jumpTreatment=1;
}
if (ds.version<115) {
ds.autoSystem=false;
}
ds.isDMF=false;
reader.readS(); // reserved
@ -1512,7 +1515,12 @@ bool DivEngine::loadFur(unsigned char* file, size_t len) {
} else {
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();
}
}
@ -1549,6 +1557,7 @@ bool DivEngine::loadFur(unsigned char* file, size_t len) {
ds.categoryJ=reader.readString();
} else {
ds.systemName=getSongSystemLegacyName(ds,!getConfInt("noMultiSystem",0));
ds.autoSystem=true;
}
// read subsongs
@ -3751,7 +3760,8 @@ SafeWriter* DivEngine::saveFur(bool notPrimary) {
w->writeC(song.snNoLowPeriods);
w->writeC(song.delayBehavior);
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);
}

View file

@ -72,9 +72,10 @@ void DivInstrument::putInsData(SafeWriter* w) {
w->writeC(op.ksr);
w->writeC(op.enable);
w->writeC(op.kvs);
// reserved
for (int k=0; k<11; k++) {
for (int k=0; k<10; k++) {
w->writeC(0);
}
}
@ -724,8 +725,15 @@ DivDataErrors DivInstrument::readInsData(SafeReader& reader, short version) {
reader.readC();
}
if (version>=115) {
op.kvs=reader.readC();
} else {
op.kvs=2;
reader.readC();
}
// reserved
for (int k=0; k<11; k++) reader.readC();
for (int k=0; k<10; k++) reader.readC();
}
// GB

View file

@ -87,6 +87,7 @@ struct DivInstrumentFM {
bool enable;
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 kvs;
Operator():
enable(true),
am(0),
@ -108,7 +109,8 @@ struct DivInstrumentFM {
sus(0),
vib(0),
ws(0),
ksr(0) {}
ksr(0),
kvs(2) {}
} op[4];
DivInstrumentFM():
alg(0),

View file

@ -511,6 +511,7 @@ struct DivSong {
bool e1e2StopOnSameNote;
bool brokenPortaArp;
bool snNoLowPeriods;
bool autoSystem;
std::vector<DivInstrument*> ins;
std::vector<DivWavetable*> wave;
@ -614,7 +615,8 @@ struct DivSong {
brokenOutVol(false),
e1e2StopOnSameNote(false),
brokenPortaArp(false),
snNoLowPeriods(false) {
snNoLowPeriods(false),
autoSystem(true) {
for (int i=0; i<32; i++) {
system[i]=DIV_SYSTEM_NULL;
systemVol[i]=64;

View file

@ -584,6 +584,78 @@ void FurnaceGUI::updateWindowTitle() {
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) {
switch (settings.channelColors) {
case 0:
@ -3262,6 +3334,9 @@ bool FurnaceGUI::loop() {
showError("cannot add chip! ("+e->getLastError()+")");
}
ImGui::CloseCurrentPopup();
if (e->song.autoSystem) {
autoDetectSystem();
}
updateWindowTitle();
}
ImGui::EndMenu();
@ -3282,6 +3357,9 @@ bool FurnaceGUI::loop() {
DivSystem picked=systemPicker();
if (picked!=DIV_SYSTEM_NULL) {
e->changeSystem(i,picked,preserveChanPos);
if (e->song.autoSystem) {
autoDetectSystem();
}
updateWindowTitle();
ImGui::CloseCurrentPopup();
}
@ -3297,6 +3375,10 @@ bool FurnaceGUI::loop() {
if (!e->removeSystem(i,preserveChanPos)) {
showError("cannot remove chip! ("+e->getLastError()+")");
}
if (e->song.autoSystem) {
autoDetectSystem();
updateWindowTitle();
}
}
}
ImGui::EndMenu();
@ -4415,6 +4497,10 @@ bool FurnaceGUI::loop() {
case GUI_WARN_SYSTEM_DEL:
if (ImGui::Button("Yes")) {
e->removeSystem(sysToDelete,preserveChanPos);
if (e->song.autoSystem) {
autoDetectSystem();
updateWindowTitle();
}
ImGui::CloseCurrentPopup();
}
ImGui::SameLine();
@ -5069,6 +5155,7 @@ FurnaceGUI::FurnaceGUI():
macroPointSize(16),
waveEditStyle(0),
mobileMenuPos(0.0f),
autoButtonSize(0.0f),
curSysSection(NULL),
pendingRawSampleDepth(8),
pendingRawSampleChannels(1),

View file

@ -1018,7 +1018,7 @@ class FurnaceGUI {
int drawHalt;
int macroPointSize;
int waveEditStyle;
float mobileMenuPos;
float mobileMenuPos, autoButtonSize;
const int* curSysSection;
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);
void updateWindowTitle();
void autoDetectSystem();
void prepareLayout();
ImVec4 channelColor(int ch);
ImVec4 channelTextColor(int ch);

View file

@ -77,11 +77,23 @@ void FurnaceGUI::drawSongInfo() {
ImGui::TableNextColumn();
ImGui::Text("System");
ImGui::TableNextColumn();
ImGui::SetNextItemWidth(avail);
ImGui::SetNextItemWidth(MAX(16.0f*dpiScale,avail-autoButtonSize-ImGui::GetStyle().ItemSpacing.x));
if (ImGui::InputText("##SystemName",&e->song.systemName)) {
MARK_MODIFIED;
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();
}

View file

@ -765,6 +765,9 @@ void FurnaceGUI::drawSysConf(int chan, DivSystem type, unsigned int& flags, bool
if (copyOfFlags!=flags) {
if (chan>=0) {
e->setSysFlags(chan,copyOfFlags,restart);
if (e->song.autoSystem) {
autoDetectSystem();
}
updateWindowTitle();
} else {
flags=copyOfFlags;

View file

@ -82,6 +82,9 @@ void FurnaceGUI::drawSysManager() {
DivSystem picked=systemPicker();
if (picked!=DIV_SYSTEM_NULL) {
e->changeSystem(i,picked,preserveChanPos);
if (e->song.autoSystem) {
autoDetectSystem();
}
updateWindowTitle();
ImGui::CloseCurrentPopup();
}
@ -110,6 +113,9 @@ void FurnaceGUI::drawSysManager() {
if (!e->addSystem(picked)) {
showError("cannot add chip! ("+e->getLastError()+")");
}
if (e->song.autoSystem) {
autoDetectSystem();
}
updateWindowTitle();
ImGui::CloseCurrentPopup();
}