diff --git a/src/engine/engine.h b/src/engine/engine.h index ba6a770e..958508a3 100644 --- a/src/engine/engine.h +++ b/src/engine/engine.h @@ -278,7 +278,8 @@ class DivEngine { // save as .dmf. SafeWriter* saveDMF(unsigned char version); // save as .fur. - SafeWriter* saveFur(); + // if notPrimary is true then the song will not be altered + SafeWriter* saveFur(bool notPrimary=false); // build a ROM file (TODO). // specify system to build ROM for. SafeWriter* buildROM(int sys); diff --git a/src/engine/fileOps.cpp b/src/engine/fileOps.cpp index 23570c47..afe5df63 100644 --- a/src/engine/fileOps.cpp +++ b/src/engine/fileOps.cpp @@ -1728,7 +1728,7 @@ bool DivEngine::load(unsigned char* f, size_t slen) { return false; } -SafeWriter* DivEngine::saveFur() { +SafeWriter* DivEngine::saveFur(bool notPrimary) { int insPtr[256]; int wavePtr[256]; int samplePtr[256]; @@ -1736,8 +1736,10 @@ SafeWriter* DivEngine::saveFur() { size_t ptrSeek; warnings=""; - song.isDMF=false; - song.version=DIV_ENGINE_VERSION; + if (!notPrimary) { + song.isDMF=false; + song.version=DIV_ENGINE_VERSION; + } SafeWriter* w=new SafeWriter; w->init(); diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index b1dfc987..eb62f5d1 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -52,11 +52,13 @@ extern "C" { #include #include "../utfutils.h" #define LAYOUT_INI "\\layout.ini" +#define BACKUP_FUR "\\backup.fur" #else #include #include #include #define LAYOUT_INI "/layout.ini" +#define BACKUP_FUR "/backup.fur" #endif bool Particle::update(float frameTime) { @@ -4802,11 +4804,13 @@ void FurnaceGUI::openFileDialog(FurnaceGUIFileDialogs type) { int FurnaceGUI::save(String path, int dmfVersion) { SafeWriter* w; + backupLock.lock(); if (dmfVersion) { w=e->saveDMF(dmfVersion); } else { w=e->saveFur(); } + backupLock.unlock(); if (w==NULL) { lastError=e->getLastError(); return 3; @@ -6411,6 +6415,41 @@ bool FurnaceGUI::loop() { ImGui::EndPopup(); } + // backup trigger + if (modified) { + if (backupTimer>0) { + backupTimer-=ImGui::GetIO().DeltaTime; + if (backupTimer<=0) { + backupTask=std::async(std::launch::async,[this]() -> bool { + if (backupPath==curFileName) { + logD("backup file open. not saving backup.\n"); + return true; + } + logD("saving backup...\n"); + backupLock.lock(); + SafeWriter* w=e->saveFur(true); + backupLock.unlock(); + + if (w!=NULL) { + FILE* outFile=ps_fopen(backupPath.c_str(),"wb"); + if (outFile!=NULL) { + if (fwrite(w->getFinalBuf(),1,w->size(),outFile)!=w->size()) { + logW("did not write backup entirely: %s!\n",strerror(errno)); + fclose(outFile); + w->finish(); + } + } else { + logW("could not save backup: %s!\n",strerror(errno)); + w->finish(); + } + } + backupTimer=30.0; + return true; + }); + } + } + } + SDL_SetRenderDrawColor(sdlRend,uiColors[GUI_COLOR_BACKGROUND].x*255, uiColors[GUI_COLOR_BACKGROUND].y*255, uiColors[GUI_COLOR_BACKGROUND].z*255, @@ -6930,6 +6969,7 @@ bool FurnaceGUI::init() { } strncpy(finalLayoutPath,(e->getConfigPath()+String(LAYOUT_INI)).c_str(),4095); + backupPath=e->getConfigPath()+String(BACKUP_FUR); prepareLayout(); ImGui::GetIO().ConfigFlags|=ImGuiConfigFlags_DockingEnable; @@ -6969,6 +7009,7 @@ bool FurnaceGUI::init() { #ifdef __APPLE__ SDL_RaiseWindow(sdlWin); #endif + return true; } @@ -7020,6 +7061,11 @@ bool FurnaceGUI::finish() { for (int i=0; i #include #include +#include +#include #include #include "fileDialog.h" @@ -512,6 +514,11 @@ class FurnaceGUI { double aboutScroll, aboutSin; float aboutHue; + double backupTimer; + std::future backupTask; + std::mutex backupLock; + String backupPath; + ImFont* mainFont; ImFont* iconFont; ImFont* patFont; @@ -875,6 +882,7 @@ class FurnaceGUI { void updateScroll(int amount); void addScroll(int amount); void setFileName(String name); + void runBackupThread(); bool loop(); bool finish(); bool init();