mirror of
https://github.com/tildearrow/furnace.git
synced 2024-11-04 20:05:05 +00:00
add parameter parsing
This commit is contained in:
parent
fa445d8614
commit
f7080bb2c1
7 changed files with 192 additions and 6 deletions
|
@ -64,6 +64,7 @@ target_link_libraries(furnace ${HAVE_SDL2} ${HAVE_Z})
|
||||||
|
|
||||||
if (HAVE_JACK)
|
if (HAVE_JACK)
|
||||||
target_link_libraries(furnace ${HAVE_JACK})
|
target_link_libraries(furnace ${HAVE_JACK})
|
||||||
|
target_compile_definitions(furnace PUBLIC HAVE_JACK)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
|
|
|
@ -17,8 +17,9 @@ this is a work-in-progress chip music player (currently) for the .dmf format.
|
||||||
- CMake
|
- CMake
|
||||||
- SDL2
|
- SDL2
|
||||||
- zlib
|
- zlib
|
||||||
|
- JACK (optional)
|
||||||
|
|
||||||
the latter two are included as submodules for Windows and macOS.
|
SDL2 and zlib are included as submodules for Windows and macOS.
|
||||||
|
|
||||||
## compilation
|
## compilation
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,9 @@
|
||||||
#include "safeReader.h"
|
#include "safeReader.h"
|
||||||
#include "../ta-log.h"
|
#include "../ta-log.h"
|
||||||
#include "../audio/sdl.h"
|
#include "../audio/sdl.h"
|
||||||
|
#ifdef HAVE_JACK
|
||||||
|
#include "../audio/jack.h"
|
||||||
|
#endif
|
||||||
#include "platform/genesis.h"
|
#include "platform/genesis.h"
|
||||||
#include "platform/genesisext.h"
|
#include "platform/genesisext.h"
|
||||||
#include "platform/sms.h"
|
#include "platform/sms.h"
|
||||||
|
@ -677,15 +680,38 @@ void DivEngine::play() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DivEngine::setAudio(DivAudioEngines which) {
|
||||||
|
audioEngine=which;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DivEngine::setView(DivStatusView which) {
|
||||||
|
view=which;
|
||||||
|
}
|
||||||
|
|
||||||
bool DivEngine::init() {
|
bool DivEngine::init() {
|
||||||
|
switch (audioEngine) {
|
||||||
|
case DIV_AUDIO_JACK:
|
||||||
|
#ifndef HAVE_JACK
|
||||||
|
logE("Furnace was not compiled with JACK support!\n");
|
||||||
|
return false;
|
||||||
|
#else
|
||||||
|
output=new TAAudioJACK;
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
case DIV_AUDIO_SDL:
|
||||||
output=new TAAudioSDL;
|
output=new TAAudioSDL;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
logE("invalid audio engine!\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
want.bufsize=1024;
|
want.bufsize=1024;
|
||||||
want.rate=44100;
|
want.rate=44100;
|
||||||
want.fragments=2;
|
want.fragments=2;
|
||||||
want.inChans=0;
|
want.inChans=0;
|
||||||
want.outChans=2;
|
want.outChans=2;
|
||||||
want.outFormat=TA_AUDIO_FORMAT_F32;
|
want.outFormat=TA_AUDIO_FORMAT_F32;
|
||||||
want.name="DivAudio";
|
want.name="Furnace";
|
||||||
|
|
||||||
output->setCallback(process,this);
|
output->setCallback(process,this);
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,11 @@ enum DivStatusView {
|
||||||
DIV_STATUS_COMMANDS
|
DIV_STATUS_COMMANDS
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum DivAudioEngines {
|
||||||
|
DIV_AUDIO_JACK=0,
|
||||||
|
DIV_AUDIO_SDL
|
||||||
|
};
|
||||||
|
|
||||||
struct DivChannelState {
|
struct DivChannelState {
|
||||||
std::vector<DivDelayedCommand> delayed;
|
std::vector<DivDelayedCommand> delayed;
|
||||||
int note, pitch, portaSpeed, portaNote;
|
int note, pitch, portaSpeed, portaNote;
|
||||||
|
@ -54,6 +59,7 @@ class DivEngine {
|
||||||
int changeOrd, changePos, totalTicks, totalCmds, lastCmds, cmdsPerSecond;
|
int changeOrd, changePos, totalTicks, totalCmds, lastCmds, cmdsPerSecond;
|
||||||
DivStatusView view;
|
DivStatusView view;
|
||||||
DivChannelState chan[17];
|
DivChannelState chan[17];
|
||||||
|
DivAudioEngines audioEngine;
|
||||||
|
|
||||||
short vibTable[64];
|
short vibTable[64];
|
||||||
|
|
||||||
|
@ -83,6 +89,12 @@ class DivEngine {
|
||||||
// play
|
// play
|
||||||
void play();
|
void play();
|
||||||
|
|
||||||
|
// set the audio system.
|
||||||
|
void setAudio(DivAudioEngines which);
|
||||||
|
|
||||||
|
// set the view mode.
|
||||||
|
void setView(DivStatusView which);
|
||||||
|
|
||||||
// initialize the engine.
|
// initialize the engine.
|
||||||
bool init();
|
bool init();
|
||||||
|
|
||||||
|
@ -101,6 +113,7 @@ class DivEngine {
|
||||||
lastCmds(0),
|
lastCmds(0),
|
||||||
cmdsPerSecond(0),
|
cmdsPerSecond(0),
|
||||||
view(DIV_STATUS_PATTERN),
|
view(DIV_STATUS_PATTERN),
|
||||||
|
audioEngine(DIV_AUDIO_SDL),
|
||||||
temp{0,0},
|
temp{0,0},
|
||||||
prevSample{0,0} {}
|
prevSample{0,0} {}
|
||||||
};
|
};
|
||||||
|
|
|
@ -76,7 +76,6 @@ static const int16_t Phase_Filter[2][7] =
|
||||||
|
|
||||||
inline void PCE_PSG::UpdateOutputSub(const int32_t timestamp, psg_channel *ch, const int32_t samp0, const int32_t samp1)
|
inline void PCE_PSG::UpdateOutputSub(const int32_t timestamp, psg_channel *ch, const int32_t samp0, const int32_t samp1)
|
||||||
{
|
{
|
||||||
if (samp0!=0)
|
|
||||||
HRBufs[0][0]+=samp0;
|
HRBufs[0][0]+=samp0;
|
||||||
HRBufs[1][0]+=samp1;
|
HRBufs[1][0]+=samp1;
|
||||||
/*
|
/*
|
||||||
|
|
134
src/main.cpp
134
src/main.cpp
|
@ -13,6 +13,94 @@
|
||||||
|
|
||||||
DivEngine e;
|
DivEngine e;
|
||||||
|
|
||||||
|
std::vector<TAParam> params;
|
||||||
|
|
||||||
|
bool pHelp(String) {
|
||||||
|
printf("usage: furnace [params] [filename]\n"
|
||||||
|
"you may specify the following parameters:\n");
|
||||||
|
for (auto& i: params) {
|
||||||
|
if (i.value) {
|
||||||
|
printf(" -%s %s: %s\n",i.name.c_str(),i.valName.c_str(),i.desc.c_str());
|
||||||
|
} else {
|
||||||
|
printf(" -%s: %s\n",i.name.c_str(),i.desc.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool pAudio(String val) {
|
||||||
|
if (val=="jack") {
|
||||||
|
e.setAudio(DIV_AUDIO_JACK);
|
||||||
|
} else if (val=="sdl") {
|
||||||
|
e.setAudio(DIV_AUDIO_SDL);
|
||||||
|
} else {
|
||||||
|
logE("invalid value for audio engine! valid values are: jack, sdl.\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool pView(String val) {
|
||||||
|
if (val=="pattern") {
|
||||||
|
e.setView(DIV_STATUS_PATTERN);
|
||||||
|
} else if (val=="commands") {
|
||||||
|
e.setView(DIV_STATUS_COMMANDS);
|
||||||
|
} else if (val=="nothing") {
|
||||||
|
e.setView(DIV_STATUS_NOTHING);
|
||||||
|
} else {
|
||||||
|
logE("invalid value for view type! valid values are: pattern, commands, nothing.\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool pVersion(String) {
|
||||||
|
printf("Furnace version " DIV_VERSION ".\n\n");
|
||||||
|
printf("developed by tildearrow. copyright (C) 2021.\n");
|
||||||
|
printf("licensed under the GNU General Public License version 2\n");
|
||||||
|
printf("<https://www.gnu.org/licenses/old-licenses/gpl-2.0.html>.\n\n");
|
||||||
|
printf("this is free software with ABSOLUTELY NO WARRANTY.\n");
|
||||||
|
printf("pass the -warranty parameter for more information.\n\n");
|
||||||
|
printf("DISCLAIMER: this program is not affiliated with Delek in any form.\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool pWarranty(String) {
|
||||||
|
printf("This program is free software; you can redistribute it and/or\n"
|
||||||
|
"modify it under the terms of the GNU General Public License\n"
|
||||||
|
"as published by the Free Software Foundation; either version 2\n"
|
||||||
|
"of the License, or (at your option) any later version.\n\n"
|
||||||
|
|
||||||
|
"This program is distributed in the hope that it will be useful,\n"
|
||||||
|
"but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
|
||||||
|
"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
|
||||||
|
"GNU General Public License for more details.\n\n"
|
||||||
|
|
||||||
|
"You should have received a copy of the GNU General Public License\n"
|
||||||
|
"along with this program; if not, write to the Free Software\n"
|
||||||
|
"Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool needsValue(String param) {
|
||||||
|
for (size_t i=0; i<params.size(); i++) {
|
||||||
|
if (params[i].name==param) {
|
||||||
|
return params[i].value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void initParams() {
|
||||||
|
params.push_back(TAParam("h","help",false,pHelp,"","display this help"));
|
||||||
|
|
||||||
|
params.push_back(TAParam("a","audio",true,pAudio,"jack|sdl","set audio engine (SDL by default)"));
|
||||||
|
params.push_back(TAParam("v","view",true,pView,"pattern|commands|nothing","set visualization (pattern by default)"));
|
||||||
|
|
||||||
|
params.push_back(TAParam("V","version",false,pVersion,"","view information about Furnace."));
|
||||||
|
params.push_back(TAParam("W","warranty",false,pWarranty,"","view warranty disclaimer."));
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
HANDLE winin=GetStdHandle(STD_INPUT_HANDLE);
|
HANDLE winin=GetStdHandle(STD_INPUT_HANDLE);
|
||||||
|
@ -26,13 +114,55 @@ int main(int argc, char** argv) {
|
||||||
SetConsoleMode(winout,termprop);
|
SetConsoleMode(winout,termprop);
|
||||||
SetConsoleMode(winin,termpropi);
|
SetConsoleMode(winin,termpropi);
|
||||||
#endif
|
#endif
|
||||||
if (argc<2) {
|
|
||||||
|
initParams();
|
||||||
|
|
||||||
|
// parse arguments
|
||||||
|
String arg, val, fileName;
|
||||||
|
size_t eqSplit, argStart;
|
||||||
|
for (int i=1; i<argc; i++) {
|
||||||
|
arg=""; val="";
|
||||||
|
if (argv[i][0]=='-') {
|
||||||
|
if (argv[i][1]=='-') {
|
||||||
|
argStart=2;
|
||||||
|
} else {
|
||||||
|
argStart=1;
|
||||||
|
}
|
||||||
|
arg=&argv[i][argStart];
|
||||||
|
eqSplit=arg.find_first_of('=');
|
||||||
|
if (eqSplit==String::npos) {
|
||||||
|
if (needsValue(arg)) {
|
||||||
|
if ((i+1)<argc) {
|
||||||
|
val=argv[i+1];
|
||||||
|
i++;
|
||||||
|
} else {
|
||||||
|
logE("incomplete param %s.\n",arg.c_str());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
val=arg.substr(eqSplit+1);
|
||||||
|
arg=arg.substr(0,eqSplit);
|
||||||
|
}
|
||||||
|
for (size_t j=0; j<params.size(); j++) {
|
||||||
|
if (params[j].name==arg || params[j].shortName==arg) {
|
||||||
|
if (!params[j].func(val)) return 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fileName=argv[i];
|
||||||
|
printf("fn: %s\n",fileName.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fileName.empty()) {
|
||||||
logI("usage: %s file\n",argv[0]);
|
logI("usage: %s file\n",argv[0]);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
logI("Furnace version " DIV_VERSION ".\n");
|
logI("Furnace version " DIV_VERSION ".\n");
|
||||||
logI("loading module...\n");
|
logI("loading module...\n");
|
||||||
FILE* f=fopen(argv[1],"rb");
|
FILE* f=fopen(fileName.c_str(),"rb");
|
||||||
if (f==NULL) {
|
if (f==NULL) {
|
||||||
perror("error");
|
perror("error");
|
||||||
return 1;
|
return 1;
|
||||||
|
|
|
@ -14,4 +14,20 @@ typedef std::string String;
|
||||||
typedef SSIZE_T ssize_t;
|
typedef SSIZE_T ssize_t;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
struct TAParam {
|
||||||
|
String shortName;
|
||||||
|
String name;
|
||||||
|
String valName;
|
||||||
|
String desc;
|
||||||
|
bool value;
|
||||||
|
bool (*func)(String);
|
||||||
|
TAParam(String sn, String n, bool v, bool (*f)(String), String vn, String d):
|
||||||
|
shortName(sn),
|
||||||
|
name(n),
|
||||||
|
valName(vn),
|
||||||
|
desc(d),
|
||||||
|
value(v),
|
||||||
|
func(f) {}
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue