forked from jaildesigner-jailgames/jaildoctors_dilemma
210 lines
7.5 KiB
C++
210 lines
7.5 KiB
C++
#include "options.h"
|
|
#include <SDL2/SDL_video.h> // for SDL_WINDOW_FULLSCREEN, SDL_WINDOW_FULLSC...
|
|
#include <fstream> // for basic_ostream, operator<<, basic_ofstream
|
|
#include <functional> // for function
|
|
#include <iostream> // for cout, cerr
|
|
#include <unordered_map> // for unordered_map, operator==, _Node_const_i...
|
|
#include <utility> // for pair
|
|
#include <sstream>
|
|
#include <string>
|
|
#include <algorithm>
|
|
|
|
// Variables
|
|
Options options;
|
|
|
|
bool setOptions(const std::string &var, const std::string &value);
|
|
|
|
// Crea e inicializa las opciones del programa
|
|
void initOptions()
|
|
{
|
|
options = Options();
|
|
|
|
#ifdef DEBUG
|
|
options.section = SectionState(Section::TITLE, Subsection::NONE);
|
|
options.console = true;
|
|
#else
|
|
options.section = SectionState(Section::LOGO, Subsection::LOGO_TO_INTRO);
|
|
options.console = false;
|
|
#endif
|
|
}
|
|
|
|
// Carga las opciones desde un fichero
|
|
bool loadOptionsFromFile(const std::string &file_path)
|
|
{
|
|
// Indicador de éxito en la carga
|
|
bool success = true;
|
|
|
|
// Versión actual del fichero
|
|
const std::string configVersion = options.version;
|
|
options.version = "";
|
|
|
|
// Variables para manejar el fichero
|
|
std::string line;
|
|
std::ifstream file(file_path);
|
|
|
|
// Si el fichero se puede abrir
|
|
if (file.good())
|
|
{
|
|
// Procesa el fichero línea a línea
|
|
if (options.console)
|
|
{
|
|
std::cout << "Reading file config.txt\n";
|
|
}
|
|
while (std::getline(file, line))
|
|
{
|
|
// Elimina espacios en blanco iniciales y finales
|
|
line = std::string(std::find_if(line.begin(), line.end(), [](int ch) { return !std::isspace(ch); }), line.end());
|
|
line.erase(std::find_if(line.rbegin(), line.rend(), [](int ch) { return !std::isspace(ch); }).base(), line.end());
|
|
|
|
// Ignora líneas vacías o comentarios
|
|
if (line.empty() || line[0] == '#')
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// Usa un stringstream para dividir la línea en dos partes
|
|
std::istringstream iss(line);
|
|
std::string key, value;
|
|
|
|
if (iss >> key >> value)
|
|
{
|
|
if (!setOptions(key, value))
|
|
{
|
|
if (options.console)
|
|
{
|
|
std::cout << "Warning: file config.txt\n";
|
|
std::cout << "unknown parameter " << key << std::endl;
|
|
}
|
|
success = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Cierra el fichero
|
|
if (options.console)
|
|
{
|
|
std::cout << "Closing file config.txt\n\n";
|
|
}
|
|
file.close();
|
|
}
|
|
else
|
|
{
|
|
// Crea el fichero con los valores por defecto
|
|
saveOptionsToFile(file_path);
|
|
}
|
|
|
|
// Si la versión de fichero no coincide, crea un fichero nuevo con los valores por defecto
|
|
if (configVersion != options.version)
|
|
{
|
|
initOptions();
|
|
saveOptionsToFile(file_path);
|
|
if (options.console)
|
|
{
|
|
std::cout << "Wrong config file: initializing options.\n\n";
|
|
}
|
|
}
|
|
|
|
return success;
|
|
}
|
|
|
|
|
|
// Guarda las opciones en un fichero
|
|
bool saveOptionsToFile(const std::string &file_path)
|
|
{
|
|
// Crea y abre el fichero de texto
|
|
std::ofstream file(file_path);
|
|
bool success = file.is_open(); // Verifica si el archivo se abrió correctamente
|
|
|
|
if (!success) // Si no se pudo abrir el archivo, muestra un mensaje de error y devuelve false
|
|
{
|
|
if (options.console)
|
|
{
|
|
std::cerr << "Error: Unable to open file " << file_path << " for writing." << std::endl;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
if (options.console)
|
|
{
|
|
std::cout << file_path << " open for writing" << std::endl;
|
|
}
|
|
|
|
// Escribe en el fichero
|
|
file << "# Versión de la configuración\n";
|
|
file << "version " << options.version << "\n";
|
|
|
|
file << "\n## CONTROL\n";
|
|
file << "# Esquema de control: 0 = Cursores, 1 = OPQ, 2 = WAD\n";
|
|
file << "keys " << static_cast<int>(options.keys) << "\n";
|
|
|
|
file << "\n## WINDOW\n";
|
|
file << "# Zoom de la ventana: 1 = Normal, 2 = Doble, 3 = Triple, ...\n";
|
|
file << "window.zoom " << options.window.zoom << "\n";
|
|
|
|
file << "\n## VIDEO\n";
|
|
file << "# Modo de video: 0 = Ventana, 1 = Pantalla completa, 2 = Pantalla completa (escritorio)\n";
|
|
file << "video.mode " << options.video.mode << "\n";
|
|
file << "# Filtro de pantalla: 0 = Nearest, 1 = Linear\n";
|
|
file << "video.filter " << static_cast<int>(options.video.filter) << "\n";
|
|
file << "# Shaders: 1 = Activado, 0 = Desactivado\n";
|
|
file << "video.shaders " << boolToString(options.video.shaders) << "\n";
|
|
file << "# Sincronización vertical: 1 = Activado, 0 = Desactivado\n";
|
|
file << "video.vertical_sync " << boolToString(options.video.vertical_sync) << "\n";
|
|
file << "# Escalado entero: 1 = Activado, 0 = Desactivado\n";
|
|
file << "video.integer_scale " << boolToString(options.video.integer_scale) << "\n";
|
|
file << "# Mantener aspecto: 1 = Activado, 0 = Desactivado\n";
|
|
file << "video.keep_aspect " << boolToString(options.video.keep_aspect) << "\n";
|
|
file << "# Borde: 1 = Activado, 0 = Desactivado\n";
|
|
file << "video.border.enabled " << boolToString(options.video.border.enabled) << "\n";
|
|
file << "# Ancho del borde\n";
|
|
file << "video.border.width " << options.video.border.width << "\n";
|
|
file << "# Alto del borde\n";
|
|
file << "video.border.height " << options.video.border.height << "\n";
|
|
file << "# Paleta: 0 = ZX Spectrum, 1 = ZX Arne\n";
|
|
file << "video.palette " << static_cast<int>(options.video.palette) << "\n";
|
|
|
|
// Cierra el fichero
|
|
file.close();
|
|
|
|
return success;
|
|
}
|
|
|
|
// Establece las opciones
|
|
bool setOptions(const std::string &var, const std::string &value)
|
|
{
|
|
static const std::unordered_map<std::string, std::function<void(std::string)>> optionHandlers = {
|
|
{"version", [](std::string v)
|
|
{ options.version = v; }},
|
|
{"keys", [](std::string v)
|
|
{ options.keys = static_cast<ControlScheme>(safeStoi(v, static_cast<int>(ControlScheme::CURSOR))); }},
|
|
{"window.zoom", [](std::string v)
|
|
{ options.window.zoom = safeStoi(v, 1); }},
|
|
{"video.mode", [](std::string v)
|
|
{ options.video.mode = safeStoi(v, 0); }},
|
|
{"video.filter", [](std::string v)
|
|
{ options.video.filter = static_cast<ScreenFilter>(safeStoi(v, static_cast<int>(DEFAULT_VIDEO_FILTER))); }},
|
|
{"video.shaders", [](std::string v)
|
|
{ options.video.shaders = stringToBool(v); }},
|
|
{"video.vertical_sync", [](std::string v)
|
|
{ options.video.vertical_sync = stringToBool(v); }},
|
|
{"video.integer_scale", [](std::string v)
|
|
{ options.video.integer_scale = stringToBool(v); }},
|
|
{"video.keep_aspect", [](std::string v)
|
|
{ options.video.keep_aspect = stringToBool(v); }},
|
|
{"video.border.enabled", [](std::string v)
|
|
{ options.video.border.enabled = stringToBool(v); }},
|
|
{"video.border.width", [](std::string v)
|
|
{ options.video.border.width = safeStoi(v, 32); }},
|
|
{"video.border.height", [](std::string v)
|
|
{ options.video.border.height = safeStoi(v, 24); }},
|
|
{"video.palette", [](std::string v)
|
|
{ options.video.palette = static_cast<Palette>(safeStoi(v, static_cast<int>(DEFAULT_PALETTE))); }}};
|
|
|
|
auto it = optionHandlers.find(var);
|
|
if (it != optionHandlers.end())
|
|
{
|
|
it->second(value);
|
|
return true;
|
|
}
|
|
return false;
|
|
} |