From 39923742ab29714abd17c43c7442d87eaabe7a91 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Sun, 18 Aug 2024 17:20:17 -0500 Subject: [PATCH] ZSM export: move to ROM export framework --- CMakeLists.txt | 3 +- src/engine/engine.h | 3 +- src/engine/export.cpp | 4 + src/engine/{ => export}/zsm.cpp | 309 +++++++++++++++++++++++++++++++- src/engine/export/zsm.h | 38 ++++ src/engine/zsm.h | 92 ---------- src/engine/zsmOps.cpp | 208 --------------------- src/gui/exportOptions.cpp | 58 +++--- src/gui/gui.cpp | 62 ------- src/gui/gui.h | 8 +- src/main.cpp | 38 +--- 11 files changed, 382 insertions(+), 441 deletions(-) rename src/engine/{ => export}/zsm.cpp (64%) create mode 100644 src/engine/export/zsm.h delete mode 100644 src/engine/zsm.h delete mode 100644 src/engine/zsmOps.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index d02350b16..59f04d451 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -717,8 +717,6 @@ src/engine/wavetable.cpp src/engine/waveSynth.cpp src/engine/wavOps.cpp src/engine/vgmOps.cpp -src/engine/zsmOps.cpp -src/engine/zsm.cpp src/engine/platform/abstract.cpp src/engine/platform/genesis.cpp @@ -797,6 +795,7 @@ src/engine/platform/dummy.cpp src/engine/export/abstract.cpp src/engine/export/amigaValidation.cpp src/engine/export/tiuna.cpp +src/engine/export/zsm.cpp src/engine/effect/abstract.cpp src/engine/effect/dummy.cpp diff --git a/src/engine/engine.h b/src/engine/engine.h index ac897d136..a845cb0e1 100644 --- a/src/engine/engine.h +++ b/src/engine/engine.h @@ -669,6 +669,7 @@ class DivEngine { friend class DivROMExport; friend class DivExportAmigaValidation; friend class DivExportTiuna; + friend class DivExportZSM; public: DivSong song; @@ -721,8 +722,6 @@ class DivEngine { // - -1 to auto-determine trailing // - -2 to add a whole loop of trailing SafeWriter* saveVGM(bool* sysToExport=NULL, bool loop=true, int version=0x171, bool patternHints=false, bool directStream=false, int trailingTicks=-1); - // dump to ZSM. - SafeWriter* saveZSM(unsigned int zsmrate=60, bool loop=true, bool optimize=true); // dump to TIunA. SafeWriter* saveTiuna(const bool* sysToExport, const char* baseLabel, int firstBankSize, int otherBankSize); // dump command stream. diff --git a/src/engine/export.cpp b/src/engine/export.cpp index 33544e252..5a3700097 100644 --- a/src/engine/export.cpp +++ b/src/engine/export.cpp @@ -21,6 +21,7 @@ #include "export/amigaValidation.h" #include "export/tiuna.h" +#include "export/zsm.h" DivROMExport* DivEngine::buildROM(DivROMExportOptions sys) { DivROMExport* exporter=NULL; @@ -31,6 +32,9 @@ DivROMExport* DivEngine::buildROM(DivROMExportOptions sys) { case DIV_ROM_TIUNA: exporter=new DivExportTiuna; break; + case DIV_ROM_ZSM: + exporter=new DivExportZSM; + break; default: exporter=new DivROMExport; break; diff --git a/src/engine/zsm.cpp b/src/engine/export/zsm.cpp similarity index 64% rename from src/engine/zsm.cpp rename to src/engine/export/zsm.cpp index 75cc3d9da..81c5021a0 100644 --- a/src/engine/zsm.cpp +++ b/src/engine/export/zsm.cpp @@ -18,9 +18,77 @@ */ #include "zsm.h" +#include "../engine.h" #include "../ta-log.h" -#include "../utfutils.h" -#include "song.h" +#include + +/// DivZSM definitions + +#define ZSM_HEADER_SIZE 16 +#define ZSM_VERSION 1 +#define ZSM_YM_CMD 0x40 +#define ZSM_DELAY_CMD 0x80 +#define ZSM_YM_MAX_WRITES 63 +#define ZSM_SYNC_MAX_WRITES 31 +#define ZSM_DELAY_MAX 127 +#define ZSM_EOF ZSM_DELAY_CMD + +#define ZSM_EXT ZSM_YM_CMD +#define ZSM_EXT_PCM 0x00 +#define ZSM_EXT_CHIP 0x40 +#define ZSM_EXT_SYNC 0x80 +#define ZSM_EXT_CUSTOM 0xC0 + +enum YM_STATE { ym_PREV, ym_NEW, ym_STATES }; +enum PSG_STATE { psg_PREV, psg_NEW, psg_STATES }; + +class DivZSM { + private: + struct S_pcmInst { + int geometry; + unsigned int offset, length, loopPoint; + bool isLooped; + }; + SafeWriter* w; + int ymState[ym_STATES][256]; + int psgState[psg_STATES][64]; + int pcmRateCache; + int pcmCtrlRVCache; + int pcmCtrlDCCache; + unsigned int pcmLoopPointCache; + bool pcmIsLooped; + std::vector ymwrites; + std::vector pcmMeta; + std::vector pcmData; + std::vector pcmCache; + std::vector pcmInsts; + std::vector syncCache; + int loopOffset; + int numWrites; + int ticks; + int tickRate; + int ymMask; + int psgMask; + bool optimize; + public: + DivZSM(); + ~DivZSM(); + void init(unsigned int rate = 60); + int getoffset(); + void writeYM(unsigned char a, unsigned char v); + void writePSG(unsigned char a, unsigned char v); + void writePCM(unsigned char a, unsigned char v); + void writeSync(unsigned char a, unsigned char v); + void setOptimize(bool o); + void tick(int numticks = 1); + void setLoopPoint(); + SafeWriter* finish(); + private: + void flushWrites(); + void flushTicks(); +}; + +/// DivZSM implementation DivZSM::DivZSM() { w=NULL; @@ -447,3 +515,240 @@ void DivZSM::flushTicks() { } ticks=0; } + +/// ZSM export + +constexpr int MASTER_CLOCK_PREC=(sizeof(void*)==8)?8:0; +constexpr int MASTER_CLOCK_MASK=(sizeof(void*)==8)?0xff:0; + +void DivExportZSM::run() { + // settings + unsigned int zsmrate=conf.getInt("zsmrate",60); + bool loop=conf.getBool("loop",true); + bool optimize=conf.getBool("optimize",true); + + // system IDs + int VERA=-1; + int YM=-1; + int IGNORED=0; + + // find indexes for YM and VERA. Ignore other systems. + for (int i=0; isong.systemLen; i++) { + switch (e->song.system[i]) { + case DIV_SYSTEM_VERA: + if (VERA>=0) { + IGNORED++; + break; + } + VERA=i; + logAppendf("VERA detected as chip id %d",i); + break; + case DIV_SYSTEM_YM2151: + if (YM>=0) { + IGNORED++; + break; + } + YM=i; + logAppendf("YM detected as chip id %d",i); + break; + default: + IGNORED++; + logAppendf("Ignoring chip %d systemID %d",i,(int)e->song.system[i]); + break; + } + } + if (VERA<0 && YM<0) { + logAppend("ERROR: No supported systems for ZSM"); + failed=true; + running=false; + return; + } + if (IGNORED>0) { + logAppendf("ZSM export ignoring %d unsupported system%c",IGNORED,IGNORED>1?'s':' '); + } + + DivZSM zsm; + + e->stop(); + e->repeatPattern=false; + e->setOrder(0); + e->synchronizedSoft([&]() { + double origRate=e->got.rate; + e->got.rate=zsmrate&0xffff; + + // determine loop point + int loopOrder=0; + int loopRow=0; + int loopEnd=0; + e->walkSong(loopOrder,loopRow,loopEnd); + logAppendf("loop point: %d %d",loopOrder,loopRow); + + zsm.init(zsmrate); + + // reset the playback state + e->curOrder=0; + e->freelance=false; + e->playing=false; + e->extValuePresent=false; + e->remainingLoops=-1; + + // Prepare to write song data + e->playSub(false); + //size_t tickCount=0; + bool done=false; + bool loopNow=false; + int loopPos=-1; + int fracWait=0; // accumulates fractional ticks + if (VERA>=0) e->disCont[VERA].dispatch->toggleRegisterDump(true); + if (YM>=0) { + e->disCont[YM].dispatch->toggleRegisterDump(true); + // emit LFO initialization commands + zsm.writeYM(0x18,0); // freq=0 + zsm.writeYM(0x19,0x7F); // AMD =7F + zsm.writeYM(0x19,0xFF); // PMD =7F + // TODO: incorporate the Furnace meta-command for init data and filter + // out writes to otherwise-unused channels. + } + // Indicate the song's tuning as a sync meta-event + // specified in terms of how many 1/256th semitones + // the song is offset from standard A-440 tuning. + // This is mainly to benefit visualizations in players + // for non-standard tunings so that they can avoid + // displaying the entire song held in pitch bend. + // Tunings offsets that exceed a half semitone + // will simply be represented in a different key + // by nature of overflowing the signed char value + signed char tuningoffset=(signed char)(round(3072*(log(e->song.tuning/440.0)/log(2))))&0xff; + zsm.writeSync(0x01,tuningoffset); + // Set optimize flag, which mainly buffers PSG writes + // whenever the channel is silent + zsm.setOptimize(optimize); + + while (!done) { + if (loopPos==-1) { + if (loopOrder==e->curOrder && loopRow==e->curRow && loop) + loopNow=true; + if (loopNow) { + // If Virtual Tempo is in use, our exact loop point + // might be skipped due to quantization error. + // If this happens, the tick immediately following is our loop point. + if (e->ticks==1 || !(loopOrder==e->curOrder && loopRow==e->curRow)) { + loopPos=zsm.getoffset(); + zsm.setLoopPoint(); + loopNow=false; + } + } + } + if (e->nextTick() || !e->playing) { + done=true; + if (!loop) { + for (int i=0; isong.systemLen; i++) { + e->disCont[i].dispatch->getRegisterWrites().clear(); + } + break; + } + if (!e->playing) { + loopPos=-1; + } + } + // get register dumps + for (int j=0; j<2; j++) { + int i=0; + // dump YM writes first + if (j==0) { + if (YM<0) { + continue; + } else { + i=YM; + } + } + // dump VERA writes second + if (j==1) { + if (VERA<0) { + continue; + } else { + i=VERA; + } + } + std::vector& writes=e->disCont[i].dispatch->getRegisterWrites(); + if (writes.size()>0) + logD("zsmOps: Writing %d messages to chip %d",writes.size(),i); + for (DivRegWrite& write: writes) { + if (i==YM) zsm.writeYM(write.addr&0xff,write.val); + if (i==VERA) { + if (done && write.addr>=64) continue; // don't process any PCM or sync events on the loop lookahead + zsm.writePSG(write.addr&0xff,write.val); + } + } + writes.clear(); + } + + // write wait + int totalWait=e->cycles>>MASTER_CLOCK_PREC; + fracWait+=e->cycles&MASTER_CLOCK_MASK; + totalWait+=fracWait>>MASTER_CLOCK_PREC; + fracWait&=MASTER_CLOCK_MASK; + if (totalWait>0 && !done) { + zsm.tick(totalWait); + //tickCount+=totalWait; + } + } + // end of song + + // done - close out. + e->got.rate=origRate; + if (VERA>=0) e->disCont[VERA].dispatch->toggleRegisterDump(false); + if (YM>=0) e->disCont[YM].dispatch->toggleRegisterDump(false); + + e->remainingLoops=-1; + e->playing=false; + e->freelance=false; + e->extValuePresent=false; + }); + + progress[0].amount=1.0f; + + logAppend("finished!"); + + output.push_back(DivROMExportOutput("out.zsm",zsm.finish())); + running=false; +} + +/// DivExpottZSM - FRONTEND + +bool DivExportZSM::go(DivEngine* eng) { + progress[0].name="Generate"; + progress[0].amount=0.0f; + + e=eng; + running=true; + failed=false; + mustAbort=false; + exportThread=new std::thread(&DivExportZSM::run,this); + return true; +} + +void DivExportZSM::wait() { + if (exportThread!=NULL) { + exportThread->join(); + delete exportThread; + } +} + +void DivExportZSM::abort() { + mustAbort=true; + wait(); +} + +bool DivExportZSM::isRunning() { + return running; +} + +bool DivExportZSM::hasFailed() { + return failed; +} + +DivROMExportProgress DivExportZSM::getProgress(int index) { + if (index<0 || index>1) return progress[1]; + return progress[index]; +} diff --git a/src/engine/export/zsm.h b/src/engine/export/zsm.h new file mode 100644 index 000000000..fd6468608 --- /dev/null +++ b/src/engine/export/zsm.h @@ -0,0 +1,38 @@ +/** + * Furnace Tracker - multi-system chiptune tracker + * Copyright (C) 2021-2024 tildearrow and contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "../export.h" + +#include + +class DivExportZSM: public DivROMExport { + DivEngine* e; + std::thread* exportThread; + DivROMExportProgress progress[2]; + bool running, failed, mustAbort; + void run(); + public: + bool go(DivEngine* e); + bool isRunning(); + bool hasFailed(); + void abort(); + void wait(); + DivROMExportProgress getProgress(int index=0); + ~DivExportZSM() {} +}; diff --git a/src/engine/zsm.h b/src/engine/zsm.h deleted file mode 100644 index d1fd8ec04..000000000 --- a/src/engine/zsm.h +++ /dev/null @@ -1,92 +0,0 @@ -/** - * Furnace Tracker - multi-system chiptune tracker - * Copyright (C) 2021-2024 tildearrow and contributors - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef _ZSM_H -#define _ZSM_H - -//#include "engine.h" -#include "safeWriter.h" -#include "dispatch.h" -#include - -#define ZSM_HEADER_SIZE 16 -#define ZSM_VERSION 1 -#define ZSM_YM_CMD 0x40 -#define ZSM_DELAY_CMD 0x80 -#define ZSM_YM_MAX_WRITES 63 -#define ZSM_SYNC_MAX_WRITES 31 -#define ZSM_DELAY_MAX 127 -#define ZSM_EOF ZSM_DELAY_CMD - -#define ZSM_EXT ZSM_YM_CMD -#define ZSM_EXT_PCM 0x00 -#define ZSM_EXT_CHIP 0x40 -#define ZSM_EXT_SYNC 0x80 -#define ZSM_EXT_CUSTOM 0xC0 - -enum YM_STATE { ym_PREV, ym_NEW, ym_STATES }; -enum PSG_STATE { psg_PREV, psg_NEW, psg_STATES }; - -class DivZSM { - private: - struct S_pcmInst { - int geometry; - unsigned int offset, length, loopPoint; - bool isLooped; - }; - SafeWriter* w; - int ymState[ym_STATES][256]; - int psgState[psg_STATES][64]; - int pcmRateCache; - int pcmCtrlRVCache; - int pcmCtrlDCCache; - unsigned int pcmLoopPointCache; - bool pcmIsLooped; - std::vector ymwrites; - std::vector pcmMeta; - std::vector pcmData; - std::vector pcmCache; - std::vector pcmInsts; - std::vector syncCache; - int loopOffset; - int numWrites; - int ticks; - int tickRate; - int ymMask; - int psgMask; - bool optimize; - public: - DivZSM(); - ~DivZSM(); - void init(unsigned int rate = 60); - int getoffset(); - void writeYM(unsigned char a, unsigned char v); - void writePSG(unsigned char a, unsigned char v); - void writePCM(unsigned char a, unsigned char v); - void writeSync(unsigned char a, unsigned char v); - void setOptimize(bool o); - void tick(int numticks = 1); - void setLoopPoint(); - SafeWriter* finish(); - private: - void flushWrites(); - void flushTicks(); -}; - -#endif diff --git a/src/engine/zsmOps.cpp b/src/engine/zsmOps.cpp deleted file mode 100644 index a2f9385ba..000000000 --- a/src/engine/zsmOps.cpp +++ /dev/null @@ -1,208 +0,0 @@ -/** - * Furnace Tracker - multi-system chiptune tracker - * Copyright (C) 2021-2024 tildearrow and contributors - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "engine.h" -#include "../ta-log.h" -#include "../utfutils.h" -#include "song.h" -#include "zsm.h" - -constexpr int MASTER_CLOCK_PREC=(sizeof(void*)==8)?8:0; -constexpr int MASTER_CLOCK_MASK=(sizeof(void*)==8)?0xff:0; - -SafeWriter* DivEngine::saveZSM(unsigned int zsmrate, bool loop, bool optimize) { - int VERA=-1; - int YM=-1; - int IGNORED=0; - - // find indexes for YM and VERA. Ignore other systems. - for (int i=0; i=0) { - IGNORED++; - break; - } - VERA=i; - logD("VERA detected as chip id %d",i); - break; - case DIV_SYSTEM_YM2151: - if (YM>=0) { - IGNORED++; - break; - } - YM=i; - logD("YM detected as chip id %d",i); - break; - default: - IGNORED++; - logD("Ignoring chip %d systemID %d",i,(int)song.system[i]); - break; - } - } - if (VERA<0 && YM<0) { - logE("No supported systems for ZSM"); - return NULL; - } - if (IGNORED>0) { - logW("ZSM export ignoring %d unsupported system%c",IGNORED,IGNORED>1?'s':' '); - } - - stop(); - repeatPattern=false; - setOrder(0); - BUSY_BEGIN_SOFT; - - double origRate=got.rate; - got.rate=zsmrate&0xffff; - - // determine loop point - int loopOrder=0; - int loopRow=0; - int loopEnd=0; - walkSong(loopOrder,loopRow,loopEnd); - logI("loop point: %d %d",loopOrder,loopRow); - warnings=""; - - DivZSM zsm; - zsm.init(zsmrate); - - // reset the playback state - curOrder=0; - freelance=false; - playing=false; - extValuePresent=false; - remainingLoops=-1; - - // Prepare to write song data - playSub(false); - //size_t tickCount=0; - bool done=false; - bool loopNow=false; - int loopPos=-1; - int fracWait=0; // accumulates fractional ticks - if (VERA>=0) disCont[VERA].dispatch->toggleRegisterDump(true); - if (YM>=0) { - disCont[YM].dispatch->toggleRegisterDump(true); - // emit LFO initialization commands - zsm.writeYM(0x18,0); // freq=0 - zsm.writeYM(0x19,0x7F); // AMD =7F - zsm.writeYM(0x19,0xFF); // PMD =7F - // TODO: incorporate the Furnace meta-command for init data and filter - // out writes to otherwise-unused channels. - } - // Indicate the song's tuning as a sync meta-event - // specified in terms of how many 1/256th semitones - // the song is offset from standard A-440 tuning. - // This is mainly to benefit visualizations in players - // for non-standard tunings so that they can avoid - // displaying the entire song held in pitch bend. - // Tunings offsets that exceed a half semitone - // will simply be represented in a different key - // by nature of overflowing the signed char value - signed char tuningoffset=(signed char)(round(3072*(log(song.tuning/440.0)/log(2))))&0xff; - zsm.writeSync(0x01,tuningoffset); - // Set optimize flag, which mainly buffers PSG writes - // whenever the channel is silent - zsm.setOptimize(optimize); - - while (!done) { - if (loopPos==-1) { - if (loopOrder==curOrder && loopRow==curRow && loop) - loopNow=true; - if (loopNow) { - // If Virtual Tempo is in use, our exact loop point - // might be skipped due to quantization error. - // If this happens, the tick immediately following is our loop point. - if (ticks==1 || !(loopOrder==curOrder && loopRow==curRow)) { - loopPos=zsm.getoffset(); - zsm.setLoopPoint(); - loopNow=false; - } - } - } - if (nextTick() || !playing) { - done=true; - if (!loop) { - for (int i=0; igetRegisterWrites().clear(); - } - break; - } - if (!playing) { - loopPos=-1; - } - } - // get register dumps - for (int j=0; j<2; j++) { - int i=0; - // dump YM writes first - if (j==0) { - if (YM<0) { - continue; - } else { - i=YM; - } - } - // dump VERA writes second - if (j==1) { - if (VERA<0) { - continue; - } else { - i=VERA; - } - } - std::vector& writes=disCont[i].dispatch->getRegisterWrites(); - if (writes.size()>0) - logD("zsmOps: Writing %d messages to chip %d",writes.size(),i); - for (DivRegWrite& write: writes) { - if (i==YM) zsm.writeYM(write.addr&0xff,write.val); - if (i==VERA) { - if (done && write.addr>=64) continue; // don't process any PCM or sync events on the loop lookahead - zsm.writePSG(write.addr&0xff,write.val); - } - } - writes.clear(); - } - - // write wait - int totalWait=cycles>>MASTER_CLOCK_PREC; - fracWait+=cycles&MASTER_CLOCK_MASK; - totalWait+=fracWait>>MASTER_CLOCK_PREC; - fracWait&=MASTER_CLOCK_MASK; - if (totalWait>0 && !done) { - zsm.tick(totalWait); - //tickCount+=totalWait; - } - } - // end of song - - // done - close out. - got.rate=origRate; - if (VERA>=0) disCont[VERA].dispatch->toggleRegisterDump(false); - if (YM>=0) disCont[YM].dispatch->toggleRegisterDump(false); - - remainingLoops=-1; - playing=false; - freelance=false; - extValuePresent=false; - - BUSY_END; - return zsm.finish(); -} diff --git a/src/gui/exportOptions.cpp b/src/gui/exportOptions.cpp index bb223aac4..7b6e699dd 100644 --- a/src/gui/exportOptions.cpp +++ b/src/gui/exportOptions.cpp @@ -319,6 +319,29 @@ void FurnaceGUI::drawExportROM(bool onWindow) { } break; } + case DIV_ROM_ZSM: { + int zsmExportTickRate=romConfig.getInt("zsmrate",60); + bool zsmExportLoop=romConfig.getBool("loop",true); + bool zsmExportOptimize=romConfig.getBool("optimize",true); + + if (ImGui::InputInt(_("Tick Rate (Hz)"),&zsmExportTickRate,1,2)) { + if (zsmExportTickRate<1) zsmExportTickRate=1; + if (zsmExportTickRate>44100) zsmExportTickRate=44100; + altered=true; + } + if (ImGui::Checkbox(_("loop"),&zsmExportLoop)) { + altered=true; + } + if (ImGui::Checkbox(_("optimize size"),&zsmExportOptimize)) { + altered=true; + } + if (altered) { + romConfig.set("zsmrate",zsmExportTickRate); + romConfig.set("loop",zsmExportLoop); + romConfig.set("optimize",zsmExportOptimize); + } + break; + } case DIV_ROM_ABSTRACT: ImGui::TextWrapped("%s",_("select a target from the menu at the top of this dialog.")); break; @@ -340,28 +363,6 @@ void FurnaceGUI::drawExportROM(bool onWindow) { } } -void FurnaceGUI::drawExportZSM(bool onWindow) { - exitDisabledTimer=1; - - ImGui::Text(_("Commander X16 Zsound Music File")); - if (ImGui::InputInt(_("Tick Rate (Hz)"),&zsmExportTickRate,1,2)) { - if (zsmExportTickRate<1) zsmExportTickRate=1; - if (zsmExportTickRate>44100) zsmExportTickRate=44100; - } - ImGui::Checkbox(_("loop"),&zsmExportLoop); - ImGui::SameLine(); - ImGui::Checkbox(_("optimize size"),&zsmExportOptimize); - if (onWindow) { - ImGui::Separator(); - if (ImGui::Button(_("Cancel"),ImVec2(200.0f*dpiScale,0))) ImGui::CloseCurrentPopup(); - ImGui::SameLine(); - } - if (ImGui::Button(_("Export"),ImVec2(200.0f*dpiScale,0))) { - openFileDialog(GUI_FILE_EXPORT_ZSM); - ImGui::CloseCurrentPopup(); - } -} - void FurnaceGUI::drawExportText(bool onWindow) { exitDisabledTimer=1; @@ -444,16 +445,6 @@ void FurnaceGUI::drawExport() { ImGui::EndTabItem(); } } - int numZSMCompat=0; - for (int i=0; isong.systemLen; i++) { - if ((e->song.system[i]==DIV_SYSTEM_VERA) || (e->song.system[i]==DIV_SYSTEM_YM2151)) numZSMCompat++; - } - if (numZSMCompat>0) { - if (ImGui::BeginTabItem(_("ZSM"))) { - drawExportZSM(true); - ImGui::EndTabItem(); - } - } if (ImGui::BeginTabItem(_("Text"))) { drawExportText(true); ImGui::EndTabItem(); @@ -478,9 +469,6 @@ void FurnaceGUI::drawExport() { case GUI_EXPORT_ROM: drawExportROM(true); break; - case GUI_EXPORT_ZSM: - drawExportZSM(true); - break; case GUI_EXPORT_TEXT: drawExportText(true); break; diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index 95e8ffd36..6a8514a1b 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -2022,16 +2022,6 @@ void FurnaceGUI::openFileDialog(FurnaceGUIFileDialogs type) { (settings.autoFillSave)?shortName:"" ); break; - case GUI_FILE_EXPORT_ZSM: - if (!dirExists(workingDirZSMExport)) workingDirZSMExport=getHomeDir(); - hasOpened=fileDialog->openSave( - _("Export ZSM"), - {_("ZSM file"), "*.zsm"}, - workingDirZSMExport, - dpiScale, - (settings.autoFillSave)?shortName:"" - ); - break; case GUI_FILE_EXPORT_TEXT: if (!dirExists(workingDirROMExport)) workingDirROMExport=getHomeDir(); hasOpened=fileDialog->openSave( @@ -4405,16 +4395,6 @@ bool FurnaceGUI::loop() { ImGui::EndMenu(); } } - int numZSMCompat=0; - for (int i=0; isong.systemLen; i++) { - if ((e->song.system[i]==DIV_SYSTEM_VERA) || (e->song.system[i]==DIV_SYSTEM_YM2151)) numZSMCompat++; - } - if (numZSMCompat>0) { - if (ImGui::BeginMenu(_("export ZSM..."))) { - drawExportZSM(); - ImGui::EndMenu(); - } - } if (ImGui::BeginMenu(_("export text..."))) { drawExportText(); ImGui::EndMenu(); @@ -4442,16 +4422,6 @@ bool FurnaceGUI::loop() { displayExport=true; } } - int numZSMCompat=0; - for (int i=0; isong.systemLen; i++) { - if ((e->song.system[i]==DIV_SYSTEM_VERA) || (e->song.system[i]==DIV_SYSTEM_YM2151)) numZSMCompat++; - } - if (numZSMCompat>0) { - if (ImGui::MenuItem(_("export ZSM..."))) { - curExportType=GUI_EXPORT_ZSM; - displayExport=true; - } - } if (ImGui::MenuItem(_("export text..."))) { curExportType=GUI_EXPORT_TEXT; displayExport=true; @@ -5034,9 +5004,6 @@ bool FurnaceGUI::loop() { case GUI_FILE_EXPORT_VGM: workingDirVGMExport=fileDialog->getPath()+DIR_SEPARATOR_STR; break; - case GUI_FILE_EXPORT_ZSM: - workingDirZSMExport=fileDialog->getPath()+DIR_SEPARATOR_STR; - break; case GUI_FILE_EXPORT_ROM: case GUI_FILE_EXPORT_TEXT: case GUI_FILE_EXPORT_CMDSTREAM: @@ -5136,9 +5103,6 @@ bool FurnaceGUI::loop() { if (curFileDialog==GUI_FILE_EXPORT_ROM) { checkExtension(romFilterExt.c_str()); } - if (curFileDialog==GUI_FILE_EXPORT_ZSM) { - checkExtension(".zsm"); - } if (curFileDialog==GUI_FILE_EXPORT_TEXT) { checkExtension(".txt"); } @@ -5614,27 +5578,6 @@ bool FurnaceGUI::loop() { } break; } - case GUI_FILE_EXPORT_ZSM: { - SafeWriter* w=e->saveZSM(zsmExportTickRate,zsmExportLoop,zsmExportOptimize); - if (w!=NULL) { - FILE* f=ps_fopen(copyOfName.c_str(),"wb"); - if (f!=NULL) { - fwrite(w->getFinalBuf(),1,w->size(),f); - fclose(f); - pushRecentSys(copyOfName.c_str()); - } else { - showError(_("could not open file!")); - } - w->finish(); - delete w; - if (!e->getWarnings().empty()) { - showWarning(e->getWarnings(),GUI_WARN_GENERIC); - } - } else { - showError(fmt::sprintf(_("Could not write ZSM! (%s)"),e->getLastError())); - } - break; - } case GUI_FILE_EXPORT_ROM: romExportPath=copyOfName; pendingExport=e->buildROM(romTarget); @@ -7879,7 +7822,6 @@ void FurnaceGUI::syncState() { workingDirSample=e->getConfString("lastDirSample",workingDir); workingDirAudioExport=e->getConfString("lastDirAudioExport",workingDir); workingDirVGMExport=e->getConfString("lastDirVGMExport",workingDir); - workingDirZSMExport=e->getConfString("lastDirZSMExport",workingDir); workingDirROMExport=e->getConfString("lastDirROMExport",workingDir); workingDirFont=e->getConfString("lastDirFont",workingDir); workingDirColors=e->getConfString("lastDirColors",workingDir); @@ -8038,7 +7980,6 @@ void FurnaceGUI::commitState(DivConfig& conf) { conf.set("lastDirSample",workingDirSample); conf.set("lastDirAudioExport",workingDirAudioExport); conf.set("lastDirVGMExport",workingDirVGMExport); - conf.set("lastDirZSMExport",workingDirZSMExport); conf.set("lastDirROMExport",workingDirROMExport); conf.set("lastDirFont",workingDirFont); conf.set("lastDirColors",workingDirColors); @@ -8256,8 +8197,6 @@ FurnaceGUI::FurnaceGUI(): displayError(false), displayExporting(false), vgmExportLoop(true), - zsmExportLoop(true), - zsmExportOptimize(true), vgmExportPatternHints(false), vgmExportDirectStream(false), displayInsTypeList(false), @@ -8300,7 +8239,6 @@ FurnaceGUI::FurnaceGUI(): vgmExportVersion(0x171), vgmExportTrailingTicks(-1), drawHalt(10), - zsmExportTickRate(60), macroPointSize(16), waveEditStyle(0), displayInsTypeListMakeInsSample(-1), diff --git a/src/gui/gui.h b/src/gui/gui.h index 59413e3e1..adc066229 100644 --- a/src/gui/gui.h +++ b/src/gui/gui.h @@ -598,7 +598,6 @@ enum FurnaceGUIFileDialogs { GUI_FILE_EXPORT_AUDIO_PER_SYS, GUI_FILE_EXPORT_AUDIO_PER_CHANNEL, GUI_FILE_EXPORT_VGM, - GUI_FILE_EXPORT_ZSM, GUI_FILE_EXPORT_CMDSTREAM, GUI_FILE_EXPORT_TEXT, GUI_FILE_EXPORT_ROM, @@ -651,7 +650,6 @@ enum FurnaceGUIExportTypes { GUI_EXPORT_AUDIO=0, GUI_EXPORT_VGM, GUI_EXPORT_ROM, - GUI_EXPORT_ZSM, GUI_EXPORT_CMD_STREAM, GUI_EXPORT_TEXT, GUI_EXPORT_DMF @@ -1594,7 +1592,7 @@ class FurnaceGUI { String workingDir, fileName, clipboard, warnString, errorString, lastError, curFileName, nextFile, sysSearchQuery, newSongQuery, paletteQuery, sampleBankSearchQuery; String workingDirSong, workingDirIns, workingDirWave, workingDirSample, workingDirAudioExport; - String workingDirVGMExport, workingDirZSMExport, workingDirROMExport; + String workingDirVGMExport, workingDirROMExport; String workingDirFont, workingDirColors, workingDirKeybinds; String workingDirLayout, workingDirROM, workingDirTest; String workingDirConfig; @@ -1613,7 +1611,7 @@ class FurnaceGUI { std::vector availRenderDrivers; std::vector availAudioDrivers; - bool quit, warnQuit, willCommit, edit, editClone, isPatUnique, modified, displayError, displayExporting, vgmExportLoop, zsmExportLoop, zsmExportOptimize, vgmExportPatternHints; + bool quit, warnQuit, willCommit, edit, editClone, isPatUnique, modified, displayError, displayExporting, vgmExportLoop, vgmExportPatternHints; bool vgmExportDirectStream, displayInsTypeList, displayWaveSizeList; bool portrait, injectBackUp, mobileMenuOpen, warnColorPushed; bool wantCaptureKeyboard, oldWantCaptureKeyboard, displayMacroMenu; @@ -1634,7 +1632,6 @@ class FurnaceGUI { int vgmExportTrailingTicks; int cvHiScore; int drawHalt; - int zsmExportTickRate; int macroPointSize; int waveEditStyle; int displayInsTypeListMakeInsSample; @@ -2700,7 +2697,6 @@ class FurnaceGUI { void drawExportAudio(bool onWindow=false); void drawExportVGM(bool onWindow=false); void drawExportROM(bool onWindow=false); - void drawExportZSM(bool onWindow=false); void drawExportText(bool onWindow=false); void drawExportCommand(bool onWindow=false); void drawExportDMF(bool onWindow=false); diff --git a/src/main.cpp b/src/main.cpp index ac6e231b2..30b551a83 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -85,7 +85,6 @@ FurnaceCLI cli; String outName; String vgmOutName; -String zsmOutName; String cmdOutName; int benchMode=0; int subsong=-1; @@ -429,12 +428,6 @@ TAParamResult pVGMOut(String val) { return TA_PARAM_SUCCESS; } -TAParamResult pZSMOut(String val) { - zsmOutName=val; - e.setAudio(DIV_AUDIO_DUMMY); - return TA_PARAM_SUCCESS; -} - TAParamResult pCmdOut(String val) { cmdOutName=val; e.setAudio(DIV_AUDIO_DUMMY); @@ -457,7 +450,6 @@ void initParams() { params.push_back(TAParam("o","output",true,pOutput,"","output audio to file")); 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("Z","zsmout",true,pZSMOut,"","output .zsm data for Commander X16 Zsound")); params.push_back(TAParam("C","cmdout",true,pCmdOut,"","output command stream")); 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)")); @@ -560,7 +552,6 @@ int main(int argc, char** argv) { #endif outName=""; vgmOutName=""; - zsmOutName=""; cmdOutName=""; // load config for locale @@ -729,14 +720,14 @@ int main(int argc, char** argv) { return 1; } - if (fileName.empty() && (benchMode || infoMode || outName!="" || vgmOutName!="" || zsmOutName!="" || cmdOutName!="")) { + if (fileName.empty() && (benchMode || infoMode || outName!="" || vgmOutName!="" || cmdOutName!="")) { logE("provide a file!"); return 1; } #ifdef HAVE_GUI - if (e.preInit(consoleMode || benchMode || infoMode || outName!="" || vgmOutName!="" || zsmOutName!="" || cmdOutName!="")) { - if (consoleMode || benchMode || infoMode || outName!="" || vgmOutName!="" || zsmOutName!="" || cmdOutName!="") { + if (e.preInit(consoleMode || benchMode || infoMode || outName!="" || vgmOutName!="" || cmdOutName!="")) { + if (consoleMode || benchMode || infoMode || outName!="" || vgmOutName!="" || cmdOutName!="") { logW("engine wants safe mode, but Furnace GUI is not going to start."); } else { safeMode=true; @@ -748,7 +739,7 @@ int main(int argc, char** argv) { } #endif - if (safeMode && (consoleMode || benchMode || infoMode || outName!="" || vgmOutName!="" || zsmOutName!="" || cmdOutName!="")) { + if (safeMode && (consoleMode || benchMode || infoMode || outName!="" || vgmOutName!="" || cmdOutName!="")) { logE("you can't use safe mode and console/export mode together."); return 1; } @@ -757,7 +748,7 @@ int main(int argc, char** argv) { e.setAudio(DIV_AUDIO_DUMMY); } - if (!fileName.empty() && ((!e.getConfBool("tutIntroPlayed",TUT_INTRO_PLAYED)) || e.getConfInt("alwaysPlayIntro",0)!=3 || consoleMode || benchMode || infoMode || outName!="" || vgmOutName!="" || zsmOutName!="" || cmdOutName!="")) { + if (!fileName.empty() && ((!e.getConfBool("tutIntroPlayed",TUT_INTRO_PLAYED)) || e.getConfInt("alwaysPlayIntro",0)!=3 || consoleMode || benchMode || infoMode || outName!="" || vgmOutName!="" || cmdOutName!="")) { logI("loading module..."); FILE* f=ps_fopen(fileName.c_str(),"rb"); if (f==NULL) { @@ -849,7 +840,7 @@ int main(int argc, char** argv) { return 0; } - if (outName!="" || vgmOutName!="" || zsmOutName!="" || cmdOutName!="") { + if (outName!="" || vgmOutName!="" || cmdOutName!="") { if (cmdOutName!="") { SafeWriter* w=e.saveCommand(); if (w!=NULL) { @@ -882,23 +873,6 @@ int main(int argc, char** argv) { reportError(_("could not write VGM!")); } } - if (zsmOutName!="") { - // TODO: changing parameters - SafeWriter* w=e.saveZSM(60,true,true); - if (w!=NULL) { - FILE* f=ps_fopen(zsmOutName.c_str(),"wb"); - if (f!=NULL) { - fwrite(w->getFinalBuf(),1,w->size(),f); - fclose(f); - } else { - reportError(fmt::sprintf(_("could not open file! (%s)"),e.getLastError())); - } - w->finish(); - delete w; - } else { - reportError(fmt::sprintf(_("could not write ZSM! (%s)"),e.getLastError())); - } - } if (outName!="") { e.setConsoleMode(true); e.saveAudio(outName.c_str(),exportOptions);