From 55a189444f69b2ed35f9045820dd43e130ba141e Mon Sep 17 00:00:00 2001 From: bbbradsmith Date: Fri, 13 Dec 2024 03:44:52 -0500 Subject: [PATCH] -romout command line export consolidate DivEngine::isROMExportViable function from FurnaceGUI::updateROMExportAvail to avoid copy-paste --- doc/8-advanced/command-line.md | 4 +++ src/engine/engine.h | 2 ++ src/engine/exportDef.cpp | 45 +++++++++++++++++++++++ src/gui/gui.cpp | 53 ++------------------------- src/main.cpp | 65 +++++++++++++++++++++++++++++++++- 5 files changed, 118 insertions(+), 51 deletions(-) diff --git a/doc/8-advanced/command-line.md b/doc/8-advanced/command-line.md index 82473b0e9..ac972a563 100644 --- a/doc/8-advanced/command-line.md +++ b/doc/8-advanced/command-line.md @@ -81,6 +81,10 @@ the following parameters may be used: - `-cmdout path`: output command stream dump to `path`. - you must provide a file, otherwise Furnace will quit. +- `-romout path`: output ROM file export to `path`. + - you must provide a file, otherwise Furnace will quit. + - there must be an available ROM export target for the system. + - `-txtout path`: output text file export to `path`. - you must provide a file, otherwise Furnace will quit. diff --git a/src/engine/engine.h b/src/engine/engine.h index 6a8375d84..a3289e042 100644 --- a/src/engine/engine.h +++ b/src/engine/engine.h @@ -908,6 +908,8 @@ class DivEngine { // get ROM export definition const DivROMExportDef* getROMExportDef(DivROMExportOptions opt); + // check whether ROM export option is viable for current song + bool isROMExportViable(DivROMExportOptions opt); // convert sample rate format int fileToDivRate(int frate); diff --git a/src/engine/exportDef.cpp b/src/engine/exportDef.cpp index 74daa3a5c..428875380 100644 --- a/src/engine/exportDef.cpp +++ b/src/engine/exportDef.cpp @@ -25,6 +25,51 @@ const DivROMExportDef* DivEngine::getROMExportDef(DivROMExportOptions opt) { return romExportDefs[opt]; } +bool DivEngine::isROMExportViable(DivROMExportOptions opt) +{ + const DivROMExportDef* newDef=getROMExportDef(opt); + if (newDef==NULL) { + return false; + } + + unsigned char sysReqCount[DIV_SYSTEM_MAX]; + memset(sysReqCount,0,DIV_SYSTEM_MAX); + for (int i=0; irequisites) { + defReqCount[j]++; + } + + switch (newDef->requisitePolicy) { + case DIV_REQPOL_EXACT: + for (int j=0; jsysReqCount[j]) { + return false; + } + } + break; + case DIV_REQPOL_LAX: + for (DivSystem j: newDef->requisites) { + if (defReqCount[j]<=sysReqCount[j]) { + return true; + } + } + return false; + } + return true; +} + void DivEngine::registerROMExports() { logD("registering ROM exports..."); diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index 5ba032257..879c28939 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -769,60 +769,13 @@ void FurnaceGUI::autoDetectSystem() { } void FurnaceGUI::updateROMExportAvail() { - unsigned char sysReqCount[DIV_SYSTEM_MAX]; - unsigned char defReqCount[DIV_SYSTEM_MAX]; - - memset(sysReqCount,0,DIV_SYSTEM_MAX); - for (int i=0; isong.systemLen; i++) { - sysReqCount[e->song.system[i]]++; - } - memset(romExportAvail,0,sizeof(bool)*DIV_ROM_MAX); romExportExists=false; for (int i=0; igetROMExportDef((DivROMExportOptions)i); - if (newDef!=NULL) { - // check for viability - bool viable=true; - - memset(defReqCount,0,DIV_SYSTEM_MAX); - for (DivSystem j: newDef->requisites) { - defReqCount[j]++; - } - - switch (newDef->requisitePolicy) { - case DIV_REQPOL_EXACT: - for (int j=0; jsysReqCount[j]) { - viable=false; - break; - } - } - break; - case DIV_REQPOL_LAX: - viable=false; - for (DivSystem j: newDef->requisites) { - if (defReqCount[j]<=sysReqCount[j]) { - viable=true; - break; - } - } - break; - } - - if (viable) { - romExportAvail[i]=true; - romExportExists=true; - } + if (e->isROMExportViable((DivROMExportOptions)i)) { + romExportAvail[i]=true; + romExportExists=true; } } diff --git a/src/main.cpp b/src/main.cpp index d15c57598..295bc7156 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -86,6 +86,7 @@ FurnaceCLI cli; String outName; String vgmOutName; String cmdOutName; +String romOutName; String txtOutName; int benchMode=0; int subsong=-1; @@ -438,6 +439,12 @@ TAParamResult pCmdOut(String val) { return TA_PARAM_SUCCESS; } +TAParamResult pROMOut(String val) { + romOutName=val; + e.setAudio(DIV_AUDIO_DUMMY); + return TA_PARAM_SUCCESS; +} + TAParamResult pTxtOut(String val) { txtOutName=val; e.setAudio(DIV_AUDIO_DUMMY); @@ -461,6 +468,7 @@ void initParams() { params.push_back(TAParam("O","vgmout",true,pVGMOut,"","output .vgm data")); params.push_back(TAParam("D","direct",false,pDirect,"","set VGM export direct stream mode")); params.push_back(TAParam("C","cmdout",true,pCmdOut,"","output command stream")); + params.push_back(TAParam("r","romout",true,pROMOut,"","export ROM file")); params.push_back(TAParam("t","txtout",true,pTxtOut,"","export as text file")); params.push_back(TAParam("L","loglevel",true,pLogLevel,"debug|info|warning|error","set the log level (info by default)")); params.push_back(TAParam("v","view",true,pView,"pattern|commands|nothing","set visualization (nothing by default)")); @@ -557,6 +565,7 @@ int main(int argc, char** argv) { outName=""; vgmOutName=""; cmdOutName=""; + romOutName=""; txtOutName=""; // load config for locale @@ -725,7 +734,7 @@ int main(int argc, char** argv) { return 1; } - const bool outputMode = outName!="" || vgmOutName!="" || cmdOutName!="" || txtOutName!=""; + const bool outputMode = outName!="" || vgmOutName!="" || cmdOutName!="" || romOutName!="" || txtOutName!=""; if (fileName.empty() && (benchMode || infoMode || outputMode)) { logE("provide a file!"); @@ -893,6 +902,60 @@ int main(int argc, char** argv) { e.saveAudio(outName.c_str(),exportOptions); e.waitAudioFile(); } + if (romOutName!="") { + e.setConsoleMode(true); + // select ROM target type + DivROMExportOptions romTarget = DIV_ROM_ABSTRACT; + for (int i=0; ifileExt && + romOutName.length()>=strlen(newDef->fileExt) && + !stricmp(newDef->fileExt,romOutName.c_str()+(romOutName.length()-strlen(newDef->fileExt)))) { + romTarget = opt; + break; // extension matched, stop searching + } + if (romTarget == DIV_ROM_ABSTRACT) { + romTarget = opt; // use first viable, but keep searching for extension match + } + } + } + if (romTarget > DIV_ROM_ABSTRACT && romTarget < DIV_ROM_MAX) { + DivConfig romConfig; // TODO: no current way to pass config, maybe serialize them to .fur file? + DivROMExport* pendingExport = e.buildROM(romTarget); + if (pendingExport==NULL) { + reportError(_("could not create exporter! you may want to report this issue...")); + } else { + pendingExport->setConf(romConfig); + if (pendingExport->go(&e)) { + pendingExport->wait(); + if (!pendingExport->hasFailed()) { + for (DivROMExportOutput& i: pendingExport->getResult()) { + String path=romOutName; + if (e.getROMExportDef(romTarget)->multiOutput) { + path+=DIR_SEPARATOR_STR; + path+=i.name; + } + FILE* f=ps_fopen(path.c_str(),"wb"); + if (f!=NULL) { + fwrite(i.data->getFinalBuf(),1,i.data->size(),f); + fclose(f); + } else { + reportError(fmt::sprintf(_("could not open file! (%s)"),strerror(errno))); + } + } + } else { + reportError(fmt::sprintf(_("ROM export failed! (%s)"),e.getLastError())); + } + } else { + reportError(_("could not begin exporting process! TODO: elaborate")); + } + } + } else { + reportError(_("no matching ROM export target is available.")); + } + } if (txtOutName!="") { e.setConsoleMode(true); SafeWriter* w=e.saveText(false);