Cog/Frameworks/libsidplay/sidplay-residfp-code/.svn/pristine/ad/ad4b307a4d104d5e90a5380e8d33ad0e5e87dfb0.svn-base

487 lines
12 KiB
Text

/*
* This file is part of sidplayfp, a console SID player.
*
* Copyright 2011-2016 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 <string>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cerrno>
#ifndef _WIN32
# include <sys/types.h>
# include <sys/stat.h> /* mkdir */
# include <dirent.h> /* opendir */
#else
# include <windows.h>
#endif
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#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;
}
const TCHAR *IniConfig::DIR_NAME = TEXT("sidplayfp");
const TCHAR *IniConfig::FILE_NAME = TEXT("sidplayfp.ini");
#define SAFE_FREE(p) { if(p) { free (p); (p)=nullptr; } }
IniConfig::IniConfig() :
status(true)
{ // 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; // 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.playback = SidConfig::MONO;
audio_s.precision = 16;
emulation_s.modelDefault = SidConfig::PAL;
emulation_s.modelForced = false;
emulation_s.sidModel = SidConfig::MOS6581;
emulation_s.forceModel = false;
emulation_s.filter = true;
emulation_s.engine.clear();
emulation_s.bias = 0.0;
emulation_s.filterCurve6581 = 0.0;
emulation_s.filterCurve8580 = 0;
}
bool IniConfig::readDouble(iniHandler &ini, const TCHAR *key, double &result)
{
const TCHAR* value = ini.getValue(key);
if (value == 0)
{ // Doesn't exist, add it
ini.addValue(key, TEXT(""));
return false;
}
try
{
result = dataParser::parseDouble(value);
}
catch (dataParser::parseError const &e)
{
debug(TEXT("Error parsing double at "), key);
return false;
}
return true;
}
bool IniConfig::readInt(iniHandler &ini, const TCHAR *key, int &result)
{
const TCHAR* value = ini.getValue(key);
if (value == 0)
{ // Doesn't exist, add it
ini.addValue(key, TEXT(""));
return false;
}
try
{
result = dataParser::parseInt(value);
}
catch (dataParser::parseError const &e)
{
debug(TEXT("Error parsing int at "), key);
return false;
}
return true;
}
bool IniConfig::readString(iniHandler &ini, const TCHAR *key, SID_STRING &result)
{
const TCHAR* value = ini.getValue(key);
if (value == 0)
{
// Doesn't exist, add it
ini.addValue(key, TEXT(""));
debug(TEXT("Key doesn't exist: "), key);
return false;
}
result.assign(value);
return true;
}
bool IniConfig::readBool(iniHandler &ini, const TCHAR *key, bool &result)
{
const TCHAR* value = ini.getValue(key);
if (value == 0)
{ // Doesn't exist, add it
ini.addValue(key, TEXT(""));
return false;
}
try
{
result = dataParser::parseBool(value);
}
catch (dataParser::parseError const &e)
{
debug(TEXT("Error parsing bool at "), key);
return false;
}
return true;
}
bool IniConfig::readChar(iniHandler &ini, const TCHAR *key, char &ch)
{
SID_STRING str;
bool ret = readString(ini, key, str);
if (!ret)
return false;
TCHAR c = 0;
// Check if we have an actual chanracter
if (str[0] == '\'')
{
if (str[2] != '\'')
ret = false;
else
c = str[1];
} // Nope is number
else
{
try
{
c = dataParser::parseInt(str.c_str());
}
catch (dataParser::parseError const &e)
{
debug(TEXT("Error parsing int at "), key);
return false;
}
}
// Clip off special characters
if ((unsigned) c >= 32)
ch = c;
return ret;
}
bool IniConfig::readTime(iniHandler &ini, const TCHAR *key, int &value)
{
SID_STRING str;
bool ret = readString(ini, key, str);
if (!ret)
return false;
int time;
const size_t sep = str.find_first_of(':');
try
{
if (sep == SID_STRING::npos)
{ // User gave seconds
time = dataParser::parseInt(str.c_str());
}
else
{ // Read in MM:SS format
const int min = dataParser::parseInt(str.substr(0, sep).c_str());
if (min < 0 || min > 99)
goto IniCofig_readTime_error;
time = min * 60;
const int sec = dataParser::parseInt(str.substr(sep + 1).c_str());
if (sec < 0 || sec > 59)
goto IniCofig_readTime_error;
time += sec;
}
}
catch (dataParser::parseError const &e)
{
debug(TEXT("Error parsing time at "), key);
return false;
}
value = time;
return ret;
IniCofig_readTime_error:
debug(TEXT("Invalid time at "), key);
return false;
}
bool IniConfig::readSidplay2(iniHandler &ini)
{
if (!ini.setSection(TEXT("SIDPlayfp")))
ini.addSection(TEXT("SIDPlayfp"));
bool ret = true;
int version = sidplay2_s.version;
ret &= readInt (ini, TEXT("Version"), version);
if (version > 0)
sidplay2_s.version = version;
ret &= readString(ini, TEXT("Songlength Database"), sidplay2_s.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 = (uint_least32_t) time;
if (readTime (ini, TEXT("Default Record Length"), time))
sidplay2_s.recordLength = (uint_least32_t) time;
ret &= readString(ini, TEXT("Kernal Rom"), sidplay2_s.kernalRom);
ret &= readString(ini, TEXT("Basic Rom"), sidplay2_s.basicRom);
ret &= readString(ini, TEXT("Chargen Rom"), sidplay2_s.chargenRom);
return ret;
}
bool IniConfig::readConsole(iniHandler &ini)
{
if (!ini.setSection (TEXT("Console")))
ini.addSection(TEXT("Console"));
bool ret = true;
ret &= readBool (ini, TEXT("Ansi"), console_s.ansi);
ret &= readChar (ini, TEXT("Char Top Left"), console_s.topLeft);
ret &= readChar (ini, TEXT("Char Top Right"), console_s.topRight);
ret &= readChar (ini, TEXT("Char Bottom Left"), console_s.bottomLeft);
ret &= readChar (ini, TEXT("Char Bottom Right"), console_s.bottomRight);
ret &= readChar (ini, TEXT("Char Vertical"), console_s.vertical);
ret &= readChar (ini, TEXT("Char Horizontal"), console_s.horizontal);
ret &= readChar (ini, TEXT("Char Junction Left"), console_s.junctionLeft);
ret &= readChar (ini, TEXT("Char Junction Right"), console_s.junctionRight);
return ret;
}
bool IniConfig::readAudio(iniHandler &ini)
{
if (!ini.setSection (TEXT("Audio")))
ini.addSection(TEXT("Audio"));
bool ret = true;
{
int frequency = (int) audio_s.frequency;
ret &= readInt (ini, TEXT("Frequency"), frequency);
audio_s.frequency = (unsigned long) frequency;
}
{
int channels = 0;
ret &= readInt (ini, TEXT("Channels"), channels);
if (channels)
{
audio_s.playback = (channels == 1) ? SidConfig::MONO : SidConfig::STEREO;
}
}
ret &= readInt (ini, TEXT("BitsPerSample"), audio_s.precision);
return ret;
}
bool IniConfig::readEmulation(iniHandler &ini)
{
if (!ini.setSection (TEXT("Emulation")))
ini.addSection(TEXT("Emulation"));
bool ret = true;
ret &= readString (ini, TEXT("Engine"), emulation_s.engine);
{
SID_STRING str;
const bool res = readString (ini, TEXT("C64Model"), str);
if (res)
{
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;
}
ret &= res;
}
ret &= readBool (ini, TEXT("ForceC64Model"), emulation_s.modelForced);
{
SID_STRING str;
const bool res = readString (ini, TEXT("SidModel"), str);
if (res)
{
if (str.compare(TEXT("MOS6581")) == 0)
emulation_s.sidModel = SidConfig::MOS6581;
else if (str.compare(TEXT("MOS8580")) == 0)
emulation_s.sidModel = SidConfig::MOS8580;
}
ret &= res;
}
ret &= readBool (ini, TEXT("ForceSidModel"), emulation_s.forceModel);
ret &= readBool (ini, TEXT("UseFilter"), emulation_s.filter);
ret &= readDouble (ini, TEXT("FilterBias"), emulation_s.bias);
ret &= readDouble (ini, TEXT("FilterCurve6581"), emulation_s.filterCurve6581);
ret &= readInt (ini, TEXT("FilterCurve8580"), emulation_s.filterCurve8580);
return ret;
}
void IniConfig::read()
{
clear();
status = false;
SID_STRING configPath;
try
{
configPath = utils::getConfigPath();
}
catch (utils::error const &e)
{
error(TEXT("Cannot get config path!"));
return;
}
debug(TEXT("Config path: "), configPath.c_str());
configPath.append(SEPARATOR).append(DIR_NAME);
// Make sure the config path exists
#ifndef _WIN32
if (!opendir(configPath.c_str()))
{
if (mkdir(configPath.c_str(), 0755) < 0)
{
error(strerror(errno));
return;
}
}
#else
if (GetFileAttributes(configPath.c_str()) == INVALID_FILE_ATTRIBUTES)
{
if (CreateDirectory(configPath.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);
error(pBuffer);
LocalFree(pBuffer);
return;
}
}
#endif
configPath.append(SEPARATOR).append(FILE_NAME);
debug(TEXT("Config file: "), configPath.c_str());
iniHandler ini;
// Opens an existing file or creates a new one
if (!ini.open(configPath.c_str()))
{
error(TEXT("Error reading config file!"));
return;
}
status = true;
status &= readSidplay2 (ini);
status &= readConsole (ini);
status &= readAudio (ini);
status &= readEmulation (ini);
ini.close();
}