#include "options.h" #include // for SDL_GameControllerButton, SDL_C... #include // for max, min #include // for basic_ostream, operator<<, basi... #include // for cout #include // for vector #include "input.h" // for inputs_e, INPUT_USE_ANY, INPUT_... #include "lang.h" // for lang_e #include "screen.h" // for ScreenVideoMode, ScreenFilter #include "utils.h" // for OptionsController, Options, op_... // Variables Options options; // Declaraciones bool setOptions(std::string var, std::string value); // Inicializa las opciones del programa void initOptions() { // Opciones de video #ifdef ANBERNIC options.video.mode = ScreenVideoMode::WINDOW; options.video.window.size = 3; #else options.video.mode = ScreenVideoMode::WINDOW; options.video.window.size = 2; #endif options.video.filter = ScreenFilter::NEAREST; options.video.vSync = true; options.video.shaders = true; // Opciones de las notificaciones options.notification.posV = pos_top; options.notification.posH = pos_left; options.notification.sound = false; options.notification.color = (Color){48, 48, 48}; // Opciones de audio options.audio.music.enabled = true; options.audio.music.volume = 128; options.audio.sound.enabled = true; options.audio.sound.volume = 64; // Opciones de juego options.game.difficulty = GameDifficulty::NORMAL; options.game.language = lang::ba_BA; options.game.autofire = true; // Opciones de control options.controller.clear(); OptionsController c; const int numPlayers = 2; for (int index = 0; index < numPlayers; ++index) { c.index = index; c.playerId = index + 1; c.deviceType = INPUT_USE_GAMECONTROLLER; c.name = "NO NAME"; c.plugged = false; // Inputs que se guardan en las opciones y, por tanto, a disco c.inputs.clear(); c.inputs.push_back(input_fire_left); c.inputs.push_back(input_fire_center); c.inputs.push_back(input_fire_right); c.inputs.push_back(input_start); c.inputs.push_back(input_service); // Botones asociados a los inputs anteriores c.buttons.clear(); c.buttons.push_back(SDL_CONTROLLER_BUTTON_X); c.buttons.push_back(SDL_CONTROLLER_BUTTON_Y); c.buttons.push_back(SDL_CONTROLLER_BUTTON_B); c.buttons.push_back(SDL_CONTROLLER_BUTTON_START); c.buttons.push_back(SDL_CONTROLLER_BUTTON_BACK); options.controller.push_back(c); } options.controller[0].deviceType = INPUT_USE_ANY; // El primer jugador puede usar tanto el teclado como el primer mando } // Carga el fichero de configuración bool loadOptionsFile(std::string filePath) { // Inicializa las opciones del programa initOptions(); // Indicador de éxito en la carga bool success = true; // Variables para manejar el fichero const std::string fileName = filePath.substr(filePath.find_last_of("\\/") + 1); std::ifstream file(filePath); // Si el fichero se puede abrir if (file.good()) { // Procesa el fichero linea a linea #ifdef VERBOSE std::cout << "Reading file: " << fileName << std::endl; #endif std::string line; while (std::getline(file, line)) { // Comprueba que la linea no sea un comentario if (line.substr(0, 1) != "#") { // Encuentra la posición del caracter '=' int pos = line.find("="); // Procesa las dos subcadenas if (!setOptions(line.substr(0, pos), line.substr(pos + 1, line.length()))) { #ifdef VERBOSE std::cout << "Warning: file " << fileName << std::endl; std::cout << "Unknown parameter " << line.substr(0, pos).c_str() << std::endl; #endif success = false; } } } // Cierra el fichero file.close(); } // El fichero no existe else { // Crea el fichero con los valores por defecto saveOptionsFile(filePath); } // Normaliza los valores const bool a = options.video.mode == ScreenVideoMode::WINDOW; const bool b = options.video.mode == ScreenVideoMode::FULLSCREEN; if (!(a || b)) { options.video.mode = ScreenVideoMode::WINDOW; } if (options.video.window.size < 1 || options.video.window.size > 4) { options.video.window.size = 3; } if (options.game.language < 0 || options.game.language > 2) { options.game.language = lang::en_UK; } return success; } // Guarda el fichero de configuración bool saveOptionsFile(std::string filePath) { const std::string fileName = filePath.substr(filePath.find_last_of("\\/") + 1); std::ofstream file(filePath); if (!file.good()) { #ifdef VERBOSE std::cout << fileName << " can't be opened" << std::endl; #endif return false; } #ifdef VERBOSE std::cout << "Writing file: " << fileName << std::endl; #endif // Opciones de video const auto valueVideoModeWinow = std::to_string(static_cast(ScreenVideoMode::WINDOW)); const auto valueVideoModeFullscreen = std::to_string(static_cast(ScreenVideoMode::FULLSCREEN)); const auto valueFilterNearest = std::to_string(static_cast(ScreenFilter::NEAREST)); const auto valueFilterLineal = std::to_string(static_cast(ScreenFilter::LINEAL)); file << "## VIDEO\n"; file << "## video.mode [" << valueVideoModeWinow << ": window, " << valueVideoModeFullscreen << ": fullscreen]\n"; file << "## video.filter [" << valueFilterNearest << ": nearest, " << valueFilterLineal << ": lineal]\n"; file << "\n"; const auto valueVideoMode = std::to_string(static_cast(options.video.mode)); file << "video.mode=" << valueVideoMode << "\n"; file << "video.window.size=" + std::to_string(options.video.window.size) + "\n"; const auto valueFilter = std::to_string(static_cast(options.video.filter)); file << "video.filter=" << valueFilter << "\n"; file << "video.shaders=" + boolToString(options.video.shaders) + "\n"; file << "video.vSync=" + boolToString(options.video.vSync) + "\n"; // Opciones de notificaciones file << "\n\n## NOTIFICATION\n"; file << "## notification.posV [pos_top | pos_bottom]\n"; file << "## notification.posH [pos_left | pos_middle | pos_right]\n"; file << "\n"; if (options.notification.posV == pos_top) { file << "notification.posV=pos_top\n"; } else { file << "notification.posV=pos_bottom\n"; } if (options.notification.posH == pos_left) { file << "notification.posH=pos_left\n"; } else if (options.notification.posH == pos_middle) { file << "notification.posH=pos_middle\n"; } else { file << "notification.posH=pos_right\n"; } file << "notification.sound=" + boolToString(options.notification.sound) + "\n"; // Opciones de audio file << "\n\n## AUDIO\n"; file << "## volume [0 .. 128]\n"; file << "\n"; file << "audio.music.enabled=" + boolToString(options.audio.music.enabled) + "\n"; file << "audio.music.volume=" + std::to_string(options.audio.music.volume) + "\n"; file << "audio.sound.enabled=" + boolToString(options.audio.sound.enabled) + "\n"; file << "audio.sound.volume=" + std::to_string(options.audio.sound.volume) + "\n"; // Opciones del juego const auto valueDifficultyEasy = std::to_string(static_cast(GameDifficulty::EASY)); const auto valueDifficultyNormal = std::to_string(static_cast(GameDifficulty::NORMAL)); const auto valueDifficultyHard = std::to_string(static_cast(GameDifficulty::HARD)); file << "\n\n## GAME\n"; file << "## game.language [0: spanish, 1: valencian, 2: english]\n"; file << "## game.difficulty [" << valueDifficultyEasy << ": easy, " << valueDifficultyNormal << ": normal, " << valueDifficultyHard << ": hard]\n"; file << "\n"; file << "game.language=" + std::to_string(options.game.language) + "\n"; file << "game.difficulty=" + std::to_string(static_cast(options.game.difficulty)) + "\n"; file << "game.autofire=" + boolToString(options.game.autofire) + "\n"; // Opciones de mandos file << "\n\n## CONTROLLERS\n"; file << "\n"; const int numPlayers = 2; for (int index = 0; index < numPlayers; ++index) { const std::string joyIndex = std::to_string(index + 1); file << "controller" + joyIndex + ".name=" + options.controller[index].name + "\n"; file << "controller" + joyIndex + ".player=" + std::to_string(options.controller[index].playerId) + "\n"; file << "controller" + joyIndex + ".button.fire_left=" + std::to_string((int)options.controller[index].buttons[0]) + "\n"; file << "controller" + joyIndex + ".button.fire_center=" + std::to_string((int)options.controller[index].buttons[1]) + "\n"; file << "controller" + joyIndex + ".button.fire_right=" + std::to_string((int)options.controller[index].buttons[2]) + "\n"; file << "controller" + joyIndex + ".button.start=" + std::to_string((int)options.controller[index].buttons[3]) + "\n"; file << "controller" + joyIndex + ".button.service=" + std::to_string((int)options.controller[index].buttons[4]) + "\n"; if (index < numPlayers - 1) { file << "\n"; } } // Cierra el fichero file.close(); return true; } // Asigna variables a partir de dos cadenas bool setOptions(std::string var, std::string value) { // Indicador de éxito en la asignación bool success = true; // Opciones de video if (var == "video.mode") { // options.video.mode = value == std::to_string(static_cast(ScreenVideoMode::WINDOW)) ? ScreenVideoMode::WINDOW : ScreenVideoMode::FULLSCREEN; options.video.mode = static_cast(std::stoi(value)); } else if (var == "video.window.size") { options.video.window.size = std::stoi(value); if ((options.video.window.size < 1) || (options.video.window.size > 4)) { options.video.window.size = 3; } } else if (var == "video.filter") { // options.video.filter = value == std::to_string(static_cast(ScreenFilter::NEAREST)) ? ScreenFilter::NEAREST : ScreenFilter::LINEAL; options.video.filter = static_cast(std::stoi(value)); } else if (var == "video.shaders") { options.video.shaders = stringToBool(value); } else if (var == "video.vSync") { options.video.vSync = stringToBool(value); } // Opciones de notificaciones else if (var == "notification.posH") { if (value == "pos_left") { options.notification.posH = pos_left; } else if (value == "pos_middle") { options.notification.posH = pos_middle; } else { options.notification.posH = pos_right; } } else if (var == "notification.posV") { options.notification.posV = value == "pos_top" ? pos_top : pos_bottom; } else if (var == "notification.sound") { options.notification.sound = stringToBool(value); } // Opciones de audio else if (var == "audio.music.enabled") { options.audio.music.enabled = stringToBool(value); } else if (var == "audio.music.volume") { options.audio.music.volume = std::stoi(value); } else if (var == "audio.sound.enabled") { options.audio.sound.enabled = stringToBool(value); } else if (var == "audio.sound.volume") { options.audio.sound.volume = std::stoi(value); } // Opciones de juego else if (var == "game.language") { options.game.language = std::stoi(value); } else if (var == "game.difficulty") { options.game.difficulty = static_cast(std::stoi(value)); } else if (var == "game.autofire") { options.game.autofire = stringToBool(value); } // Opciones de mandos else if (var == "controller1.name") { options.controller[0].name = value; } else if (var == "controller1.player") { options.controller[0].playerId = std::max(1, std::min(2, std::stoi(value))); } else if (var == "controller1.button.fire_left") { options.controller[0].buttons[0] = (SDL_GameControllerButton)std::stoi(value); } else if (var == "controller1.button.fire_center") { options.controller[0].buttons[1] = (SDL_GameControllerButton)std::stoi(value); } else if (var == "controller1.button.fire_right") { options.controller[0].buttons[2] = (SDL_GameControllerButton)std::stoi(value); } else if (var == "controller1.button.start") { options.controller[0].buttons[3] = (SDL_GameControllerButton)std::stoi(value); } else if (var == "controller1.button.service") { options.controller[0].buttons[4] = (SDL_GameControllerButton)std::stoi(value); } else if (var == "controller2.name") { options.controller[1].name = value; } else if (var == "controller2.player") { options.controller[1].playerId = std::max(1, std::min(2, std::stoi(value))); } else if (var == "controller2.button.fire_left") { options.controller[1].buttons[0] = (SDL_GameControllerButton)std::stoi(value); } else if (var == "controller2.button.fire_center") { options.controller[1].buttons[1] = (SDL_GameControllerButton)std::stoi(value); } else if (var == "controller2.button.fire_right") { options.controller[1].buttons[2] = (SDL_GameControllerButton)std::stoi(value); } else if (var == "controller2.button.start") { options.controller[1].buttons[3] = (SDL_GameControllerButton)std::stoi(value); } else if (var == "controller2.button.service") { options.controller[1].buttons[4] = (SDL_GameControllerButton)std::stoi(value); } // Lineas vacias o que empiezan por comentario else if (var == "" || var.substr(0, 1) == "#") { } else { success = false; } return success; }