sidplayfp-2.2.3/0000755000175100001710000000000014173225352010513 500000000000000sidplayfp-2.2.3/configure.ac0000644000175100001710000000606214173225341012723 00000000000000dnl Process this file with autoconf to produce a configure script. AC_INIT([sidplayfp], [2.2.3], [], [], [https://github.com/libsidplayfp/sidplayfp/]) AC_CONFIG_SRCDIR([src/main.cpp]) AC_CONFIG_AUX_DIR([build-aux]) AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_HEADERS([src/config.h]) AM_INIT_AUTOMAKE AC_CANONICAL_HOST case "$host" in *mingw* ) MINGW32=yes ;; *darwin* ) MACOSX=yes ;; esac AM_CONDITIONAL([MINGW32], [test "x$MINGW32" = "xyes"]) AC_PROG_RANLIB dnl Checks for programs. AC_PROG_CXX dnl Use C++ for tests. AC_LANG([C++]) SID_CXX_COMPILE_STDCXX_11 dnl Checks for typedefs, structures, and compiler characteristics. AC_C_BIGENDIAN AM_ICONV AM_CONDITIONAL([USE_ICONV], [test "x$am_cv_func_iconv" = "xyes"]) dnl Audio subsystem AUDIO_LDFLAGS="" PKG_CHECK_MODULES(ALSA, [alsa >= 1.0], [AC_DEFINE([HAVE_ALSA], 1, [Define to 1 if you have libasound (-lasound).])], [AC_MSG_WARN([$ALSA_PKG_ERRORS])] ) PKG_CHECK_MODULES(PULSE, [libpulse-simple >= 1.0], [AC_DEFINE([HAVE_PULSE], 1, [Define to 1 if you have libpulse-simple (-lpulse-simple).])], [AC_MSG_WARN([$PULSE_PKG_ERRORS])] ) dnl Checks what version of Unix we have and soundcard support AC_CHECK_HEADERS([sys/ioctl.h linux/soundcard.h machine/soundcard.h \ sys/soundcard.h soundcard.h]) AC_CHECK_HEADERS([dsound.h mmsystem.h], [], [], [#include ]) AS_IF([test "$ac_cv_header_dsound_h" = "yes"], [AUDIO_LDFLAGS="$AUDIO_LDFLAGS -ldsound -ldxguid"] ) AS_IF([test "$ac_cv_header_mmsystem_h" = "yes"], [AUDIO_LDFLAGS="$AUDIO_LDFLAGS -lwinmm"] ) # NetBSD/OpenBSD OSS audio emulation AS_IF([test "x$ac_cv_header_soundcard_h" = "xyes"], [AUDIO_LDFLAGS="$AUDIO_LDFLAGS -lossaudio"] ) AC_SUBST(AUDIO_LDFLAGS) AC_CHECK_FUNCS([strncasecmp strcasecmp]) PKG_CHECK_MODULES(SIDPLAYFP, [libsidplayfp >= 1.0]) PKG_CHECK_MODULES(STILVIEW, [libstilview >= 1.0]) USE_LIBOUT123=no AC_ARG_WITH([out123], AS_HELP_STRING([--with-out123], [Build with out123 library (default: disabled)])) # enable ou123 by default only on Mac OSX since we don't have any audio backend there CHECK_OUT123=no AS_IF([test "x$MACOSX" = "xyes" -a "x$with_out123" != "xno"], [CHECK_OUT123=yes], [AS_IF([test "x$with_out123" = "xyes"], [CHECK_OUT123=yes] )] ) AS_IF([test "x$CHECK_OUT123" = "xyes"], [PKG_CHECK_MODULES([OUT123], [libout123 >= 1], [USE_LIBOUT123=yes AC_DEFINE([HAVE_OUT123], [1], [Use libout123])] )] ) AM_CONDITIONAL([USE_LIBOUT123], [test "x$USE_LIBOUT123" = "xyes"]) # hack? saveCPPFLAGS=$CPPFLAGS CPPFLAGS="$CPPFLAGS $SIDPLAYFP_CFLAGS" AC_CHECK_HEADERS([sidplayfp/builders/residfp.h \ sidplayfp/builders/resid.h \ sidplayfp/builders/hardsid.h \ sidplayfp/builders/exsid.h]) CPPFLAGS=$saveCPPFLAGS AC_MSG_CHECKING([for debugging]) AC_ARG_ENABLE(debug, [AS_HELP_STRING([--enable-debug], [compile for debugging @<:@no/yes, default=no@:>@])], [], [enable_debug=no]) AS_IF([test "x$enable_debug" = "xno"], [AC_MSG_RESULT([Build without debugging messages]); debug_flags=-DNDEBUG] ) AC_SUBST([debug_flags]) AC_CONFIG_FILES([ Makefile ]) AC_OUTPUT sidplayfp-2.2.3/src/0000755000175100001710000000000014173225353011303 500000000000000sidplayfp-2.2.3/src/main.cpp0000644000175100001710000000635614173225341012662 00000000000000/* * This file is part of sidplayfp, a console SID player. * * Copyright 2012 Leandro Nini * Copyright 2000 Simon White * * 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 "player.h" #include #include #include using std::cerr; using std::endl; #include "keyboard.h" // Function prototypes static void sighandler (int signum); static ConsolePlayer *g_player; int main(int argc, char *argv[]) { ConsolePlayer player(argv[0]); g_player = &player; {// Decode the command line args const int ret = player.args (argc - 1, const_cast(argv + 1)); if (ret < 0) goto main_error; else if (!ret) goto main_exit; } main_restart: if (!player.open ()) goto main_error; // Install signal error handlers if ((signal (SIGINT, &sighandler) == SIG_ERR) || (signal (SIGABRT, &sighandler) == SIG_ERR) || (signal (SIGTERM, &sighandler) == SIG_ERR)) { displayError(argv[0], ERR_SIGHANDLER); goto main_error; } #ifndef _WIN32 // Configure terminal to allow direct access to key events keyboard_enable_raw (); #endif // Play loop for (;;) { if (!player.play ()) break; } #ifndef _WIN32 keyboard_disable_raw (); #endif // Restore default signal error handlers if ((signal (SIGINT, SIG_DFL) == SIG_ERR) || (signal (SIGABRT, SIG_DFL) == SIG_ERR) || (signal (SIGTERM, SIG_DFL) == SIG_ERR)) { displayError(argv[0], ERR_SIGHANDLER); goto main_error; } if ((player.state() & ~playerFast) == playerRestart) goto main_restart; main_exit: player.close (); return EXIT_SUCCESS; main_error: player.close (); return EXIT_FAILURE; } void sighandler (int signum) { switch (signum) { case SIGINT: case SIGABRT: case SIGTERM: // Exit now! g_player->stop (); break; default: break; } } void displayError (const char *arg0, unsigned int num) { cerr << arg0 << ": "; switch (num) { case ERR_SYNTAX: cerr << "command line syntax error" << endl << "Try `" << arg0 << " --help' for more information." << endl; break; case ERR_NOT_ENOUGH_MEMORY: cerr << "ERROR: Not enough memory." << endl; break; case ERR_SIGHANDLER: cerr << "ERROR: Could not install signal handler." << endl; break; case ERR_FILE_OPEN: cerr << "ERROR: Could not open file for binary input." << endl; break; default: break; } } sidplayfp-2.2.3/src/IniConfig.cpp0000644000175100001710000003265314173225341013602 00000000000000/* * This file is part of sidplayfp, a console SID player. * * Copyright 2011-2022 Leandro Nini * Copyright 2000-2001 Simon White * * 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. */ #ifdef HAVE_CONFIG_H # include "config.h" #endif #include "IniConfig.h" #include #include #include #include #include #ifndef _WIN32 # include # include /* mkdir */ # include /* opendir */ #else # include #endif #ifdef HAVE_UNISTD_H # include #endif #include "utils.h" #include "ini/dataParser.h" #include "sidcxx11.h" inline void debug(const TCHAR *msg, const TCHAR *val) { #ifndef NDEBUG SID_COUT << msg << val << std::endl; #endif } inline void error(const TCHAR *msg) { SID_CERR << msg << std::endl; } inline void error(const TCHAR *msg, const TCHAR *val) { SID_CERR << msg << val << std::endl; } const TCHAR *DIR_NAME = TEXT("sidplayfp"); const TCHAR *FILE_NAME = TEXT("sidplayfp.ini"); IniConfig::IniConfig() { // Initialise everything else clear(); } IniConfig::~IniConfig() { clear(); } void IniConfig::clear() { sidplay2_s.version = 1; // INI File Version sidplay2_s.database.clear(); sidplay2_s.playLength = 0; // INFINITE sidplay2_s.recordLength = (3 * 60 + 30) * 1000; // 3.5 minutes sidplay2_s.kernalRom.clear(); sidplay2_s.basicRom.clear(); sidplay2_s.chargenRom.clear(); console_s.ansi = false; console_s.topLeft = '+'; console_s.topRight = '+'; console_s.bottomLeft = '+'; console_s.bottomRight = '+'; console_s.vertical = '|'; console_s.horizontal = '-'; console_s.junctionLeft = '+'; console_s.junctionRight = '+'; audio_s.frequency = SidConfig::DEFAULT_SAMPLING_FREQ; audio_s.channels = 0; audio_s.precision = 16; emulation_s.modelDefault = SidConfig::PAL; emulation_s.modelForced = false; emulation_s.sidModel = SidConfig::MOS6581; emulation_s.forceModel = false; #ifdef FEAT_CONFIG_CIAMODEL emulation_s.ciaModel = SidConfig::MOS6526; #endif emulation_s.filter = true; emulation_s.engine.clear(); emulation_s.bias = 0.5; emulation_s.filterCurve6581 = 0.5; emulation_s.filterCurve8580 = 0.5; } // static helpers const TCHAR* readKey(iniHandler &ini, const TCHAR *key) { const TCHAR* value = ini.getValue(key); if (value == nullptr) { // Doesn't exist, add it ini.addValue(key, TEXT("")); debug(TEXT("Key doesn't exist: "), key); } else if (!value[0]) { // Ignore empty values return nullptr; } return value; } void readDouble(iniHandler &ini, const TCHAR *key, double &result) { const TCHAR* value = readKey(ini, key); if (value == nullptr) return; try { result = dataParser::parseDouble(value); } catch (dataParser::parseError const &e) { error(TEXT("Error parsing double at "), key); } } void readInt(iniHandler &ini, const TCHAR *key, int &result) { const TCHAR* value = readKey(ini, key); if (value == nullptr) return; try { result = dataParser::parseInt(value); } catch (dataParser::parseError const &e) { error(TEXT("Error parsing int at "), key); } } void readBool(iniHandler &ini, const TCHAR *key, bool &result) { const TCHAR* value = readKey(ini, key); if (value == nullptr) return; try { result = dataParser::parseBool(value); } catch (dataParser::parseError const &e) { error(TEXT("Error parsing bool at "), key); } } SID_STRING readString(iniHandler &ini, const TCHAR *key) { const TCHAR* value = ini.getValue(key); if (value == nullptr) { // Doesn't exist, add it ini.addValue(key, TEXT("")); debug(TEXT("Key doesn't exist: "), key); return SID_STRING(); } return SID_STRING(value); } void readChar(iniHandler &ini, const TCHAR *key, char &ch) { SID_STRING str = readString(ini, key); if (str.empty()) return; TCHAR c = 0; // Check if we have an actual chanracter if (str[0] == '\'') { if (str[2] != '\'') return; else c = str[1]; } // Nope is number else { try { c = dataParser::parseInt(str.c_str()); } catch (dataParser::parseError const &e) { error(TEXT("Error parsing int at "), key); } } // Clip off special characters if ((unsigned) c >= 32) ch = c; } bool readTime(iniHandler &ini, const TCHAR *key, int &value) { SID_STRING str = readString(ini, key); if (str.empty()) return false; int time; int milliseconds = 0; const size_t sep = str.find_first_of(':'); const size_t dot = str.find_first_of('.'); try { if (sep == SID_STRING::npos) { // User gave seconds time = dataParser::parseInt(str.c_str()); } else { // Read in MM:SS.mmm format const int min = dataParser::parseInt(str.substr(0, sep).c_str()); if (min < 0 || min > 99) goto IniCofig_readTime_error; time = min * 60; int sec; if (dot == SID_STRING::npos) { sec = dataParser::parseInt(str.substr(sep + 1).c_str()); } else { sec = dataParser::parseInt(str.substr(sep + 1, dot - sep).c_str()); SID_STRING msec = str.substr(dot + 1); milliseconds = dataParser::parseInt(msec.c_str()); switch (msec.length()) { case 1: milliseconds *= 100; break; case 2: milliseconds *= 10; break; case 3: break; default: goto IniCofig_readTime_error; } } if (sec < 0 || sec > 59) goto IniCofig_readTime_error; time += sec; } } catch (dataParser::parseError const &e) { error(TEXT("Error parsing time at "), key); return false; } value = time * 1000 + milliseconds; return true; IniCofig_readTime_error: error(TEXT("Invalid time at "), key); return false; } void IniConfig::readSidplay2(iniHandler &ini) { if (!ini.setSection(TEXT("SIDPlayfp"))) ini.addSection(TEXT("SIDPlayfp")); int version = sidplay2_s.version; readInt(ini, TEXT("Version"), version); if (version > 0) sidplay2_s.version = version; sidplay2_s.database = readString(ini, TEXT("Songlength Database")); #if !defined _WIN32 && defined HAVE_UNISTD_H if (sidplay2_s.database.empty()) { char buffer[PATH_MAX]; snprintf(buffer, PATH_MAX, "%sSonglengths.txt", PKGDATADIR); if (::access(buffer, R_OK) == 0) sidplay2_s.database.assign(buffer); } #endif int time; if (readTime(ini, TEXT("Default Play Length"), time)) sidplay2_s.playLength = time; if (readTime(ini, TEXT("Default Record Length"), time)) sidplay2_s.recordLength = time; sidplay2_s.kernalRom = readString(ini, TEXT("Kernal Rom")); sidplay2_s.basicRom = readString(ini, TEXT("Basic Rom")); sidplay2_s.chargenRom = readString(ini, TEXT("Chargen Rom")); } void IniConfig::readConsole(iniHandler &ini) { if (!ini.setSection (TEXT("Console"))) ini.addSection(TEXT("Console")); readBool(ini, TEXT("Ansi"), console_s.ansi); readChar(ini, TEXT("Char Top Left"), console_s.topLeft); readChar(ini, TEXT("Char Top Right"), console_s.topRight); readChar(ini, TEXT("Char Bottom Left"), console_s.bottomLeft); readChar(ini, TEXT("Char Bottom Right"), console_s.bottomRight); readChar(ini, TEXT("Char Vertical"), console_s.vertical); readChar(ini, TEXT("Char Horizontal"), console_s.horizontal); readChar(ini, TEXT("Char Junction Left"), console_s.junctionLeft); readChar(ini, TEXT("Char Junction Right"), console_s.junctionRight); } void IniConfig::readAudio(iniHandler &ini) { if (!ini.setSection (TEXT("Audio"))) ini.addSection(TEXT("Audio")); readInt(ini, TEXT("Frequency"), audio_s.frequency); readInt(ini, TEXT("Channels"), audio_s.channels); readInt(ini, TEXT("BitsPerSample"), audio_s.precision); } void IniConfig::readEmulation(iniHandler &ini) { if (!ini.setSection (TEXT("Emulation"))) ini.addSection(TEXT("Emulation")); emulation_s.engine = readString (ini, TEXT("Engine")); { SID_STRING str = readString (ini, TEXT("C64Model")); if (!str.empty()) { if (str.compare(TEXT("PAL")) == 0) emulation_s.modelDefault = SidConfig::PAL; else if (str.compare(TEXT("NTSC")) == 0) emulation_s.modelDefault = SidConfig::NTSC; else if (str.compare(TEXT("OLD_NTSC")) == 0) emulation_s.modelDefault = SidConfig::OLD_NTSC; else if (str.compare(TEXT("DREAN")) == 0) emulation_s.modelDefault = SidConfig::DREAN; } } readBool(ini, TEXT("ForceC64Model"), emulation_s.modelForced); readBool(ini, TEXT("DigiBoost"), emulation_s.digiboost); #ifdef FEAT_CONFIG_CIAMODEL { SID_STRING str = readString(ini, TEXT("CiaModel")); if (!str.empty()) { if (str.compare(TEXT("MOS6526")) == 0) emulation_s.ciaModel = SidConfig::MOS6526; else if (str.compare(TEXT("MOS8521")) == 0) emulation_s.ciaModel = SidConfig::MOS8521; } } #endif { SID_STRING str = readString(ini, TEXT("SidModel")); if (!str.empty()) { if (str.compare(TEXT("MOS6581")) == 0) emulation_s.sidModel = SidConfig::MOS6581; else if (str.compare(TEXT("MOS8580")) == 0) emulation_s.sidModel = SidConfig::MOS8580; } } readBool(ini, TEXT("ForceSidModel"), emulation_s.forceModel); readBool(ini, TEXT("UseFilter"), emulation_s.filter); readDouble(ini, TEXT("FilterBias"), emulation_s.bias); readDouble(ini, TEXT("FilterCurve6581"), emulation_s.filterCurve6581); readDouble(ini, TEXT("FilterCurve8580"), emulation_s.filterCurve8580); } class iniError { private: const SID_STRING msg; public: iniError(const TCHAR* msg) : msg(msg) {} const SID_STRING message() const { return msg; } }; void createDir(const SID_STRING& path) { #ifndef _WIN32 DIR *dir = opendir(path.c_str()); if (dir) { closedir(dir); } else if (errno == ENOENT) { if (mkdir(path.c_str(), 0755) < 0) { throw iniError(strerror(errno)); } } else { throw iniError(strerror(errno)); } #else if (GetFileAttributes(path.c_str()) == INVALID_FILE_ATTRIBUTES) { if (CreateDirectory(path.c_str(), NULL) == 0) { LPTSTR pBuffer; FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&pBuffer, 0, NULL); iniError err(pBuffer); LocalFree(pBuffer); throw err; } } #endif } SID_STRING getConfigPath() { SID_STRING configPath; try { configPath = utils::getConfigPath(); } catch (utils::error const &e) { throw iniError(TEXT("Cannot get config path!")); } debug(TEXT("Config path: "), configPath.c_str()); // Make sure the config path exists createDir(configPath); configPath.append(SEPARATOR).append(DIR_NAME); // Make sure the app config path exists createDir(configPath); configPath.append(SEPARATOR).append(FILE_NAME); debug(TEXT("Config file: "), configPath.c_str()); return configPath; } bool tryOpen(iniHandler &ini) { #ifdef _WIN32 { // Try exec dir first SID_STRING execPath(utils::getExecPath()); execPath.append(SEPARATOR).append(FILE_NAME); if (ini.tryOpen(execPath.c_str())) return true; } #endif return false; } void IniConfig::read() { clear(); iniHandler ini; if (!tryOpen(ini)) { try { SID_STRING configPath = getConfigPath(); // Opens an existing file or creates a new one if (!ini.open(configPath.c_str())) { error(TEXT("Error reading config file!")); return; } } catch (iniError const &e) { error(e.message().c_str()); return; } } readSidplay2 (ini); readConsole (ini); readAudio (ini); readEmulation (ini); ini.close(); } sidplayfp-2.2.3/src/config.h.in0000644000175100001710000000673714173225344013263 00000000000000/* src/config.h.in. Generated from configure.ac by autoheader. */ /* Define if building universal (internal helper macro) */ #undef AC_APPLE_UNIVERSAL_BUILD /* Define to 1 if you have libasound (-lasound). */ #undef HAVE_ALSA /* define if the compiler supports basic C++11 syntax */ #undef HAVE_CXX11 /* Define to 1 if you have the header file. */ #undef HAVE_DSOUND_H /* Define if you have the iconv() function and it works. */ #undef HAVE_ICONV /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H /* Define to 1 if you have the header file. */ #undef HAVE_LINUX_SOUNDCARD_H /* Define to 1 if you have the header file. */ #undef HAVE_MACHINE_SOUNDCARD_H /* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H /* Define to 1 if you have the header file. */ #undef HAVE_MMSYSTEM_H /* Use libout123 */ #undef HAVE_OUT123 /* Define to 1 if you have libpulse-simple (-lpulse-simple). */ #undef HAVE_PULSE /* Define to 1 if you have the header file. */ #undef HAVE_SIDPLAYFP_BUILDERS_EXSID_H /* Define to 1 if you have the header file. */ #undef HAVE_SIDPLAYFP_BUILDERS_HARDSID_H /* Define to 1 if you have the header file. */ #undef HAVE_SIDPLAYFP_BUILDERS_RESIDFP_H /* Define to 1 if you have the header file. */ #undef HAVE_SIDPLAYFP_BUILDERS_RESID_H /* Define to 1 if you have the header file. */ #undef HAVE_SOUNDCARD_H /* Define to 1 if you have the header file. */ #undef HAVE_STDINT_H /* Define to 1 if you have the header file. */ #undef HAVE_STDLIB_H /* Define to 1 if you have the `strcasecmp' function. */ #undef HAVE_STRCASECMP /* Define to 1 if you have the header file. */ #undef HAVE_STRINGS_H /* Define to 1 if you have the header file. */ #undef HAVE_STRING_H /* Define to 1 if you have the `strncasecmp' function. */ #undef HAVE_STRNCASECMP /* Define to 1 if you have the header file. */ #undef HAVE_SYS_IOCTL_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_SOUNDCARD_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_STAT_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TYPES_H /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H /* Define as const if the declaration of iconv() needs const. */ #undef ICONV_CONST /* Name of package */ #undef PACKAGE /* Define to the address where bug reports for this package should be sent. */ #undef PACKAGE_BUGREPORT /* Define to the full name of this package. */ #undef PACKAGE_NAME /* Define to the full name and version of this package. */ #undef PACKAGE_STRING /* Define to the one symbol short name of this package. */ #undef PACKAGE_TARNAME /* Define to the home page for this package. */ #undef PACKAGE_URL /* Define to the version of this package. */ #undef PACKAGE_VERSION /* Define to 1 if you have the ANSI C header files. */ #undef STDC_HEADERS /* Version number of package */ #undef VERSION /* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most significant byte first (like Motorola and SPARC, unlike Intel). */ #if defined AC_APPLE_UNIVERSAL_BUILD # if defined __BIG_ENDIAN__ # define WORDS_BIGENDIAN 1 # endif #else # ifndef WORDS_BIGENDIAN # undef WORDS_BIGENDIAN # endif #endif sidplayfp-2.2.3/src/utils.h0000644000175100001710000000232614173225341012534 00000000000000/* * This file is part of sidplayfp, a console SID player. * * Copyright 2013-2017 Leandro Nini * * 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 UTILS_H #define UTILS_H #include #include "ini/types.h" class utils { public: class error {}; private: #ifdef _WIN32 static SID_STRING getPath(); #else static SID_STRING getPath(const char* id, const char* def); #endif public: static SID_STRING getDataPath(); static SID_STRING getConfigPath(); #ifdef _WIN32 static SID_STRING getExecPath(); #endif }; #endif sidplayfp-2.2.3/src/sidcxx11.h0000644000175100001710000000203314173225341013033 00000000000000/* * This file is part of libsidplayfp, a SID player engine. * * Copyright 2014-2015 Leandro Nini * * 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 SIDCXX11_H #define SIDCXX11_H #ifdef HAVE_CONFIG_H # include "config.h" #endif #ifndef HAVE_CXX11 # define nullptr 0 # define override # define final # define unique_ptr auto_ptr #endif #endif sidplayfp-2.2.3/src/codepages.h0000644000175100001710000000641014173225341013324 00000000000000 #ifndef CODEPAGES_H #define CODEPAGES_H // https://docs.microsoft.com/en-us/windows/win32/intl/code-page-identifiers const char* codepageName(UINT codepage) { switch (codepage) { case 437: return "CP437"; case 708: return "ASMO-708"; case 737: return "CP737"; case 775: return "CP775"; case 850: return "CP850"; case 852: return "CP852"; case 855: return "CP855"; case 857: return "CP857"; case 858: return "CP858"; case 860: return "CP860"; case 861: return "CP861"; case 862: return "CP862"; case 863: return "CP863"; case 864: return "CP864"; case 865: return "CP865"; case 866: return "CP866"; case 869: return "CP869"; case 874: return "CP874"; case 932: return "CP932"; // SHIFT_JIS case 936: return "CP936"; // GB2312 case 949: return "CP949"; // KS_C_5601-1987 case 950: return "CP950"; // BIG5 case 1200: return "UTF-16"; case 1250: return "CP1250"; case 1251: return "CP1251"; case 1252: return "CP1252"; case 1253: return "CP1253"; case 1254: return "CP1254"; case 1255: return "CP1255"; case 1256: return "CP1256"; case 1257: return "CP1257"; case 1258: return "CP1258"; case 1361: return "CP1361"; // JOHAB case 10000: return "MACINTOSH"; case 10004: return "MACARABIC"; case 10005: return "MACHEBREW"; case 10006: return "MACGREEK"; case 10007: return "MACCYRILLIC"; case 10010: return "MACROMANIA"; case 10017: return "MACUKRAINE"; case 10021: return "MACTHAI"; case 10029: return "MACCENTRALEUROPE"; case 10079: return "MACICELAND"; case 10081: return "MACTURKISH"; case 10082: return "MACCROATIAN"; case 12000: return "UTF-32"; case 12001: return "UTF-32BE"; case 20127: return "US-ASCII"; case 20866: return "KOI8-R"; case 20932: return "EUC-JP"; case 21866: return "KOI8-U"; case 28591: return "ISO-8859-1"; case 28592: return "ISO-8859-2"; case 28593: return "ISO-8859-3"; case 28594: return "ISO-8859-4"; case 28595: return "ISO-8859-5"; case 28596: return "ISO-8859-6"; case 28597: return "ISO-8859-7"; case 28598: return "ISO-8859-8"; case 28599: return "ISO-8859-9"; case 28603: return "ISO-8859-13"; case 28605: return "ISO-8859-15"; case 50220: return "ISO-2022-JP"; case 50221: return "CSISO2022JP"; case 50222: return "ISO-2022-JP"; case 50225: return "ISO-2022-KR"; case 51932: return "EUC-JP"; case 51936: return "EUC-CN"; case 51949: return "EUC-KR"; case 52936: return "HZ-GB-2312"; case 54936: return "GB18030"; case 65000: return "UTF-7"; case 65001: return "UTF-8"; default: return ""; } } #endif sidplayfp-2.2.3/src/keyboard.h0000644000175100001710000000276014173225341013176 00000000000000/* * This file is part of sidplayfp, a console SID player. * * Copyright 2012-2015 Leandro Nini * Copyright 2000 Simon White * * 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. */ #ifdef _WIN32 # include #else int _kbhit (void); #endif enum { A_NONE = 0, // Standard Commands A_PREFIX, A_SKIP, A_END_LIST, A_INVALID, // Custom Commands A_LEFT_ARROW, A_RIGHT_ARROW, A_UP_ARROW, A_DOWN_ARROW, A_HOME, A_END, A_PAUSED, A_QUIT, /* Debug */ A_TOGGLE_VOICE1, A_TOGGLE_VOICE2, A_TOGGLE_VOICE3, A_TOGGLE_VOICE4, A_TOGGLE_VOICE5, A_TOGGLE_VOICE6, A_TOGGLE_VOICE7, A_TOGGLE_VOICE8, A_TOGGLE_VOICE9, A_TOGGLE_FILTER }; int keyboard_decode (); #ifndef _WIN32 void keyboard_enable_raw (); void keyboard_disable_raw (); #endif sidplayfp-2.2.3/src/keyboard.cpp0000644000175100001710000001710214173225341013525 00000000000000/* * This file is part of sidplayfp, a console SID player. * * Copyright 2012-2016 Leandro Nini * Copyright 2000 Simon White * * 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 "keyboard.h" #include "sidcxx11.h" #ifndef _WIN32 // Unix console headers # include // bzero requires memset on some platforms # include # include # include # include # include # include # include int _getch (void); #endif #define MAX_CMDLEN 10 #define ESC '\033' // Special Extended Key Definitions enum { PCK_HOME = '\107', PCK_UP = '\110', PCK_LEFT = '\113', PCK_RIGHT = '\115', PCK_END = '\117', PCK_DOWN = '\120', PCK_EXTENDED = '\340' }; static char keytable[] = { // Windows Special Cursors #ifdef _WIN32 PCK_EXTENDED, PCK_RIGHT,0, A_RIGHT_ARROW, PCK_EXTENDED, PCK_LEFT,0, A_LEFT_ARROW, PCK_EXTENDED, PCK_UP,0, A_UP_ARROW, PCK_EXTENDED, PCK_DOWN,0, A_DOWN_ARROW, PCK_EXTENDED, PCK_HOME,0, A_HOME, PCK_EXTENDED, PCK_END,0, A_END, #else // Linux Special Keys ESC,'[','C',0, A_RIGHT_ARROW, ESC,'[','D',0, A_LEFT_ARROW, ESC,'[','A',0, A_UP_ARROW, ESC,'[','B',0, A_DOWN_ARROW, // Hmm, in consile there: ESC,'[','1','~',0, A_HOME, ESC,'[','4','~',0, A_END, // But in X there: ESC,'[','H',0, A_HOME, ESC,'[','F',0, A_END, ESC,'[','1','0',0, A_INVALID, ESC,'[','2','0',0, A_INVALID, #endif /* debug keys. Just use the cursor keys in linux to move in the song */ '1',0, A_TOGGLE_VOICE1, '2',0, A_TOGGLE_VOICE2, '3',0, A_TOGGLE_VOICE3, '4',0, A_TOGGLE_VOICE4, '5',0, A_TOGGLE_VOICE5, '6',0, A_TOGGLE_VOICE6, '7',0, A_TOGGLE_VOICE7, '8',0, A_TOGGLE_VOICE8, '9',0, A_TOGGLE_VOICE9, 'f',0, A_TOGGLE_FILTER, // General Keys 'p',0, A_PAUSED, ESC,ESC,0, A_QUIT, // Old Keys '>',0, A_RIGHT_ARROW, '<',0, A_LEFT_ARROW, '.',0, A_RIGHT_ARROW, ',',0, A_LEFT_ARROW, 0, A_END_LIST }; /* * Search a single command table for the command string in cmd. */ static int keyboard_search (char *cmd) { char *p; char *q; int a; for (p = keytable, q = cmd;; p++, q++) { if (*p == *q) { /* * Current characters match. * If we're at the end of the string, we've found it. * Return the action code, which is the character * after the null at the end of the string * in the command table. */ if (*p == '\0') { a = *++p & 0377; while (a == A_SKIP) a = *++p & 0377; if (a == A_END_LIST) { /* * We get here only if the original * cmd string passed in was empty (""). * I don't think that can happen, * but just in case ... */ break; } return (a); } } else if (*q == '\0') { /* * Hit the end of the user's command, * but not the end of the string in the command table. * The user's command is incomplete. */ return (A_PREFIX); } else { /* * Not a match. * Skip ahead to the next command in the * command table, and reset the pointer * to the beginning of the user's command. */ if (*p == '\0' && p[1] == A_END_LIST) { /* * A_END_LIST is a special marker that tells * us to abort the cmd search. */ break; } while (*p++ != '\0') continue; while (*p == A_SKIP) p++; q = cmd-1; } } /* * No match found in the entire command table. */ return (A_INVALID); } int keyboard_decode () { char cmd[MAX_CMDLEN+1]; int nch = 0; int action = A_NONE; /* * Collect characters in a buffer. * Start with the one we have, and get more if we need them. */ int c = _getch(); if (c == '\0') c = '\340'; // 224 else if (c == ESC) { cmd[nch++] = c; if (_kbhit ()) c = _getch (); } while (c >= 0) { cmd[nch++] = c; cmd[nch] = '\0'; action = keyboard_search (cmd); if (action != A_PREFIX) break; if (!_kbhit ()) break; c = _getch (); } return action; } // Simulate Standard Microsoft Extensions under Unix #ifndef _WIN32 static int infd = -1; int _kbhit (void) { if (infd >= 0) { // Set no delay static struct timeval tv = {0, 0}; fd_set rdfs; // See if key has been pressed FD_ZERO (&rdfs); FD_SET (infd, &rdfs); if (select (infd + 1, &rdfs, nullptr, nullptr, &tv) <= 0) return 0; if (FD_ISSET (infd, &rdfs)) return 1; } return 0; } int _getch (void) { char ch = -1; if (infd >= 0) read (infd, &ch, 1); return ch; } // Set keyboard to raw mode to getch will work static termios term; void keyboard_enable_raw () { // set to non canonical mode, echo off, ignore signals struct termios current; // Already open if (infd >= 0) return; // Determine if stdin/stderr has been redirected if (isatty (STDIN_FILENO)) infd = STDIN_FILENO; else if (isatty (STDERR_FILENO)) infd = STDERR_FILENO; else { // Try opening a terminal directly infd = open("/dev/tty", O_RDONLY); if (infd < 0) return; } // save current terminal settings tcgetattr (infd, ¤t); // set to non canonical mode, echo off, ignore signals term = current; current.c_lflag &= ~(ECHO | ICANON | IEXTEN); current.c_cc[VMIN] = 1; current.c_cc[VTIME] = 0; tcsetattr (infd, TCSAFLUSH, ¤t); } void keyboard_disable_raw () { if (infd >= 0) { // Restore old terminal settings tcsetattr (infd, TCSAFLUSH, &term); switch (infd) { case STDIN_FILENO: case STDERR_FILENO: break; default: close (infd); } infd = -1; } } #endif // HAVE_LINUX sidplayfp-2.2.3/src/IniConfig.h0000644000175100001710000000602314173225341013237 00000000000000/* * This file is part of sidplayfp, a console SID player. * * Copyright 2011-2021 Leandro Nini * Copyright 2000 Simon White * * 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 INICONFIG_H #define INICONFIG_H #include "ini/types.h" #include "ini/iniHandler.h" #include "sidlib_features.h" #include #include /* * Sidplayfp config file reader. */ class IniConfig { public: struct sidplay2_section { int version; SID_STRING database; uint_least32_t playLength; uint_least32_t recordLength; SID_STRING kernalRom; SID_STRING basicRom; SID_STRING chargenRom; }; struct console_section { // INI Section - [Console] bool ansi; char topLeft; char topRight; char bottomLeft; char bottomRight; char vertical; char horizontal; char junctionLeft; char junctionRight; }; struct audio_section { // INI Section - [Audio] int frequency; int channels; int precision; }; struct emulation_section { // INI Section - [Emulation] SID_STRING engine; SidConfig::c64_model_t modelDefault; bool modelForced; SidConfig::sid_model_t sidModel; bool forceModel; #ifdef FEAT_CONFIG_CIAMODEL SidConfig::cia_model_t ciaModel; #endif bool digiboost; bool filter; double bias; double filterCurve6581; double filterCurve8580; }; protected: struct sidplay2_section sidplay2_s; struct console_section console_s; struct audio_section audio_s; struct emulation_section emulation_s; protected: void clear (); void readSidplay2 (iniHandler &ini); void readConsole (iniHandler &ini); void readAudio (iniHandler &ini); void readEmulation (iniHandler &ini); public: IniConfig (); ~IniConfig (); void read (); // Sidplayfp Specific Section const sidplay2_section& sidplay2 () { return sidplay2_s; } const console_section& console () { return console_s; } const audio_section& audio () { return audio_s; } const emulation_section& emulation () { return emulation_s; } }; #endif // INICONFIG_H sidplayfp-2.2.3/src/args.cpp0000644000175100001710000005015114173225341012662 00000000000000/* * This file is part of sidplayfp, a console SID player. * * Copyright 2011-2021 Leandro Nini * Copyright 2000-2001 Simon White * * 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 "player.h" #include #include #include #include #include "ini/types.h" #include "sidlib_features.h" #include "sidcxx11.h" using std::cout; using std::cerr; using std::endl; #ifdef HAVE_SIDPLAYFP_BUILDERS_HARDSID_H # include #endif #ifdef HAVE_SIDPLAYFP_BUILDERS_EXSID_H # include #endif // Wide-chars are not yet supported here #undef SEPARATOR #define SEPARATOR "/" /** * Try load SID tune from HVSC_BASE */ bool ConsolePlayer::tryOpenTune(const char *hvscBase) { std::string newFileName(hvscBase); newFileName.append(SEPARATOR).append(m_filename); m_tune.load(newFileName.c_str()); if (!m_tune.getStatus()) { return false; } m_filename.assign(newFileName); return true; } /** * Try load songlength DB from HVSC_BASE */ bool ConsolePlayer::tryOpenDatabase(const char *hvscBase, const char *suffix) { std::string newFileName(hvscBase); newFileName.append(SEPARATOR).append("DOCUMENTS").append(SEPARATOR).append("Songlengths.").append(suffix); return m_database.open(newFileName.c_str()); } // Convert time from integer bool parseTime(const char *str, uint_least32_t &time) { // Check for empty string if (*str == '\0') return false; uint_least32_t _time; uint_least32_t milliseconds = 0; char *sep = (char *) strstr (str, ":"); if (!sep) { // User gave seconds _time = atoi (str); } else { // Read in MM:SS[.mmm] format int val; *sep = '\0'; val = atoi (str); if (val < 0 || val > 99) return false; _time = (uint_least32_t) val * 60; // parse milliseconds char *milli = (char *) strstr (sep+1, "."); if (milli) { char *start = milli + 1; char *end; milliseconds = strtol(start, &end, 10); switch (end - start) { case 1: milliseconds *= 100; break; case 2: milliseconds *= 10; break; case 3: break; default: return false; } if (milliseconds < 0 || milliseconds > 999) return false; *milli = '\0'; } val = atoi (sep + 1); if (val < 0 || val > 59) return false; _time += (uint_least32_t) val; } time = _time * 1000 + milliseconds; return true; } bool parseAddress(const char *str, uint_least16_t &address) { if (*str == '\0') return false; long x = strtol(str, 0, 0); address = x; return true; } void displayDebugArgs() { std::ostream &out = cout; out << "Debug Options:" << endl << " --cpu-debug display cpu register and assembly dumps" << endl << " --delay= simulate c64 power on delay (default: random)" << endl << " --noaudio no audio output device" << endl << " --nosid no sid emulation" << endl << " --none no audio output device and no sid emulation" << endl; } // Parse command line arguments int ConsolePlayer::args(int argc, const char *argv[]) { if (argc == 0) // at least one argument required { displayArgs (); return -1; } // default arg options m_driver.output = OUT_SOUNDCARD; m_driver.file = false; m_driver.info = false; for (int i=0; i<9; i++) { vMute[i] = false; } int infile = 0; int i = 0; bool err = false; // parse command line arguments while ((i < argc) && (argv[i] != nullptr)) { if ((argv[i][0] == '-') && (argv[i][1] != '\0')) { // help options if ((argv[i][1] == 'h') || !strcmp(&argv[i][1], "-help")) { displayArgs (); return 0; } else if (!strcmp(&argv[i][1], "-help-debug")) { displayDebugArgs (); return 0; } else if (argv[i][1] == 'b') { if (!parseTime (&argv[i][2], m_timer.start)) err = true; } else if (strncmp (&argv[i][1], "ds", 2) == 0) { // Override sidTune and enable the second sid if (!parseAddress (&argv[i][3], m_engCfg.secondSidAddress)) err = true; } #ifdef FEAT_THIRD_SID else if (strncmp (&argv[i][1], "ts", 2) == 0) { // Override sidTune and enable the third sid if (!parseAddress (&argv[i][3], m_engCfg.thirdSidAddress)) err = true; } #endif else if (argv[i][1] == 'f') { if (argv[i][2] == '\0') err = true; m_engCfg.frequency = (uint_least32_t) atoi (argv[i]+2); } // No filter options else if (strncmp (&argv[i][1], "nf", 2) == 0) { if (argv[i][3] == '\0') m_filter.enabled = false; } // Track options else if (strncmp (&argv[i][1], "ols", 3) == 0) { m_track.loop = true; m_track.single = true; m_track.first = atoi(&argv[i][4]); } else if (strncmp (&argv[i][1], "ol", 2) == 0) { m_track.loop = true; m_track.first = atoi(&argv[i][3]); } else if (strncmp (&argv[i][1], "os", 2) == 0) { m_track.single = true; m_track.first = atoi(&argv[i][3]); } else if (argv[i][1] == 'o') { // User forgot track number ? if (argv[i][2] == '\0') err = true; m_track.first = atoi(&argv[i][2]); } // Channel muting else if (argv[i][1] == 'u') { if (argv[i][2] == '\0') err = true; else { const int voice = atoi(&argv[i][2]); if (voice > 0 && voice <= 9) vMute[voice-1] = true; } } else if (argv[i][1] == 'p') { // User forgot precision if (argv[i][2] == '\0') err = true; { uint_least8_t precision = atoi(&argv[i][2]); if (precision <= 16) m_precision = 16; else m_precision = 32; } } else if (argv[i][1] == 'q') { if (argv[i][2] == '\0') m_quietLevel = 1; else m_quietLevel = atoi(&argv[i][2]); } else if (argv[i][1] == 't') { if (!parseTime (&argv[i][2], m_timer.length)) err = true; m_timer.valid = true; } // Resampling Options ---------- else if (strcmp (&argv[i][1], "rif") == 0) { m_engCfg.samplingMethod = SidConfig::INTERPOLATE; m_engCfg.fastSampling = true; } else if (strcmp (&argv[i][1], "rrf") == 0) { m_engCfg.samplingMethod = SidConfig::RESAMPLE_INTERPOLATE; m_engCfg.fastSampling = true; } else if (strcmp (&argv[i][1], "ri") == 0) { m_engCfg.samplingMethod = SidConfig::INTERPOLATE; } else if (strcmp (&argv[i][1], "rr") == 0) { m_engCfg.samplingMethod = SidConfig::RESAMPLE_INTERPOLATE; } // SID model options else if (strcmp (&argv[i][1], "mof") == 0) { m_engCfg.defaultSidModel = SidConfig::MOS6581; m_engCfg.forceSidModel = true; } else if (strcmp (&argv[i][1], "mnf") == 0) { m_engCfg.defaultSidModel = SidConfig::MOS8580; m_engCfg.forceSidModel = true; } else if (strcmp (&argv[i][1], "mo") == 0) { m_engCfg.defaultSidModel = SidConfig::MOS6581; } else if (strcmp (&argv[i][1], "mn") == 0) { m_engCfg.defaultSidModel = SidConfig::MOS8580; } else if (argv[i][1] == 's') { // Stereo Playback m_channels = 2; } else if (argv[i][1] == 'm') { // Mono Playback m_channels = 1; } #ifdef FEAT_DIGIBOOST else if (strcmp (&argv[i][1], "-digiboost") == 0) { m_engCfg.digiBoost = true; } #endif // Video/Verbose Options else if (strcmp (&argv[i][1], "vnf") == 0) { m_engCfg.forceC64Model = true; m_engCfg.defaultC64Model = SidConfig::NTSC; } else if (strcmp (&argv[i][1], "vpf") == 0) { m_engCfg.forceC64Model = true; m_engCfg.defaultC64Model = SidConfig::PAL; } else if (strcmp (&argv[i][1], "vf") == 0) { m_engCfg.forceC64Model = true; } else if (strcmp (&argv[i][1], "vn") == 0) { m_engCfg.defaultC64Model = SidConfig::NTSC; } else if (strcmp (&argv[i][1], "vp") == 0) { m_engCfg.defaultC64Model = SidConfig::PAL; } else if (argv[i][1] == 'v') { if (argv[i][2] == '\0') m_verboseLevel = 1; else m_verboseLevel = atoi(&argv[i][2]); } else if (strncmp (&argv[i][1], "-delay=", 7) == 0) { m_engCfg.powerOnDelay = (uint_least16_t) atoi(&argv[i][8]); } // File format conversions else if (argv[i][1] == 'w') { m_driver.output = OUT_WAV; m_driver.file = true; if (argv[i][2] != '\0') m_outfile = &argv[i][2]; } else if (strncmp (&argv[i][1], "-wav", 4) == 0) { m_driver.output = OUT_WAV; m_driver.file = true; if (argv[i][5] != '\0') m_outfile = &argv[i][5]; } else if (strncmp (&argv[i][1], "-au", 3) == 0) { m_driver.output = OUT_AU; m_driver.file = true; if (argv[i][4] != '\0') m_outfile = &argv[i][4]; } else if (strncmp (&argv[i][1], "-info", 5) == 0) { m_driver.info = true; } #ifdef HAVE_SIDPLAYFP_BUILDERS_RESIDFP_H else if (strcmp (&argv[i][1], "-residfp") == 0) { m_driver.sid = EMU_RESIDFP; } #endif // HAVE_SIDPLAYFP_BUILDERS_RESIDFP_H #ifdef HAVE_SIDPLAYFP_BUILDERS_RESID_H else if (strcmp (&argv[i][1], "-resid") == 0) { m_driver.sid = EMU_RESID; } #endif // HAVE_SIDPLAYFP_BUILDERS_RESID_H // Hardware selection #ifdef HAVE_SIDPLAYFP_BUILDERS_HARDSID_H else if (strcmp (&argv[i][1], "-hardsid") == 0) { m_driver.sid = EMU_HARDSID; m_driver.output = OUT_NULL; } #endif // HAVE_SIDPLAYFP_BUILDERS_HARDSID_H #ifdef HAVE_SIDPLAYFP_BUILDERS_EXSID_H else if (strcmp (&argv[i][1], "-exsid") == 0) { m_driver.sid = EMU_EXSID; m_driver.output = OUT_NULL; } #endif // HAVE_SIDPLAYFP_BUILDERS_EXSID_H // These are for debug else if (strcmp (&argv[i][1], "-none") == 0) { m_driver.sid = EMU_NONE; m_driver.output = OUT_NULL; } else if (strcmp (&argv[i][1], "-nosid") == 0) { m_driver.sid = EMU_NONE; } else if (strcmp (&argv[i][1], "-noaudio") == 0) { m_driver.output = OUT_NULL; } else if (strcmp (&argv[i][1], "-cpu-debug") == 0) { m_cpudebug = true; } else { err = true; } } else { // Reading file name if (infile == 0) infile = i; else err = true; } if (err) { displayArgs (argv[i]); return -1; } i++; // next index } const char* hvscBase = getenv("HVSC_BASE"); // Load the tune m_filename = argv[infile]; m_tune.load(m_filename.c_str()); if (!m_tune.getStatus()) { std::string errorString(m_tune.statusString()); // Try prepending HVSC_BASE if (!hvscBase || !tryOpenTune(hvscBase)) { displayError(errorString.c_str()); return -1; } } // If filename specified we can only convert one song if (m_outfile != nullptr) m_track.single = true; // Can only loop if not creating audio files if (m_driver.output > OUT_SOUNDCARD) m_track.loop = false; // Check to see if we are trying to generate an audio file // whilst using a hardware emulation if (m_driver.file && (m_driver.sid >= EMU_HARDSID)) { displayError ("ERROR: Cannot generate audio files using hardware emulations"); return -1; } if (m_driver.info && m_driver.file) { displayError ("WARNING: metadata can be added only to wav files"); } // Select the desired track m_track.first = m_tune.selectSong (m_track.first); m_track.selected = m_track.first; if (m_track.single) m_track.songs = 1; // If user provided no time then load songlength database // and set default lengths in case it's not found in there. { if (m_driver.file && m_timer.valid && !m_timer.length) { // Time of 0 provided for wav generation displayError ("ERROR: -t0 invalid in record mode"); return -1; } if (!m_timer.valid) { m_timer.length = m_driver.file ? (m_iniCfg.sidplay2()).recordLength : (m_iniCfg.sidplay2()).playLength; bool dbOpened = false; if (hvscBase) { if (tryOpenDatabase(hvscBase, "md5")) { dbOpened = true; newSonglengthDB = true; } else if (tryOpenDatabase(hvscBase, "txt")) { dbOpened = true; } } if (!dbOpened) { // Try load user configured songlength DB if ((m_iniCfg.sidplay2()).database.length() != 0) { // Try loading the database specificed by the user #if defined(_WIN32) && defined(UNICODE) # ifdef FEAT_DB_WCHAR_OPEN const wchar_t *database = (m_iniCfg.sidplay2()).database.c_str(); # else char database[MAX_PATH]; const int ret = wcstombs(database, (m_iniCfg.sidplay2()).database.c_str(), sizeof(database)); if (ret >= MAX_PATH) database[0] = '\0'; # endif #else const char *database = (m_iniCfg.sidplay2()).database.c_str(); #endif if (!m_database.open(database)) { displayError (m_database.error ()); return -1; } if ((m_iniCfg.sidplay2()).database.find(TEXT(".md5")) != SID_STRING::npos) newSonglengthDB = true; } } } } #if HAVE_TSID == 1 // Set TSIDs base directory if (!m_tsid.setBaseDir(true)) { displayError (m_tsid.getError ()); return -1; } #endif // Configure engine with settings if (!m_engine.config (m_engCfg)) { // Config failed displayError (m_engine.error ()); return -1; } return 1; } void ConsolePlayer::displayArgs (const char *arg) { std::ostream &out = arg ? cerr : cout; if (arg) out << "Option Error: " << arg << endl; else out << "Syntax: " << m_name << " [-