add parameter parsing

This commit is contained in:
tildearrow 2021-06-09 03:33:03 -05:00
parent fa445d8614
commit f7080bb2c1
7 changed files with 192 additions and 6 deletions

View file

@ -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)

View file

@ -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

View file

@ -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);

View file

@ -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} {}
}; };

View file

@ -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;
/* /*

View file

@ -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;

View file

@ -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