diff --git a/source/options.cpp b/source/options.cpp index dd3330a..26fe9b3 100644 --- a/source/options.cpp +++ b/source/options.cpp @@ -25,12 +25,12 @@ namespace Options { Keyboard keyboard; // Opciones para el teclado PendingChanges pending_changes; // Opciones que se aplican al cerrar std::vector postfx_presets = { - {"CRT", 0.6F, 0.7F, 0.15F, 0.5F, 0.5F, 0.0F, 0.0F, 0.0F}, + {"CRT", 0.15F, 0.7F, 0.2F, 0.5F, 0.1F, 0.0F, 0.0F, 0.0F}, {"NTSC", 0.4F, 0.5F, 0.2F, 0.3F, 0.3F, 0.0F, 0.6F, 0.0F}, - {"CURVED", 0.5F, 0.6F, 0.1F, 0.4F, 0.4F, 0.8F, 0.0F, 0.0F}, - {"SCANLINES", 0.0F, 0.8F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F}, - {"SUBTLE", 0.3F, 0.4F, 0.05F, 0.0F, 0.2F, 0.0F, 0.0F, 0.0F}, - {"CRT LIVE", 0.5F, 0.6F, 0.3F, 0.3F, 0.4F, 0.3F, 0.4F, 0.8F}, + {"Curved", 0.5F, 0.6F, 0.1F, 0.4F, 0.4F, 0.8F, 0.0F, 0.0F}, + {"Scanlines", 0.0F, 0.8F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F}, + {"Subtle", 0.3F, 0.4F, 0.05F, 0.0F, 0.2F, 0.0F, 0.0F, 0.0F}, + {"CRT Live", 0.15F, 0.6F, 0.3F, 0.3F, 0.1F, 0.0F, 0.4F, 0.8F}, }; std::string postfx_file_path; std::vector crtpi_presets; @@ -144,11 +144,11 @@ namespace Options { file << "\n"; file << "presets:\n"; file << " - name: \"CRT\"\n"; - file << " vignette: 0.6\n"; + file << " vignette: 0.15\n"; file << " scanlines: 0.7\n"; - file << " chroma: 0.15\n"; + file << " chroma: 0.2\n"; file << " mask: 0.5\n"; - file << " gamma: 0.5\n"; + file << " gamma: 0.1\n"; file << " curvature: 0.0\n"; file << " bleeding: 0.0\n"; file << " flicker: 0.0\n"; @@ -161,7 +161,7 @@ namespace Options { file << " curvature: 0.0\n"; file << " bleeding: 0.6\n"; file << " flicker: 0.0\n"; - file << " - name: \"CURVED\"\n"; + file << " - name: \"Curved\"\n"; file << " vignette: 0.5\n"; file << " scanlines: 0.6\n"; file << " chroma: 0.1\n"; @@ -170,7 +170,7 @@ namespace Options { file << " curvature: 0.8\n"; file << " bleeding: 0.0\n"; file << " flicker: 0.0\n"; - file << " - name: \"SCANLINES\"\n"; + file << " - name: \"Scanlines\"\n"; file << " vignette: 0.0\n"; file << " scanlines: 0.8\n"; file << " chroma: 0.0\n"; @@ -179,7 +179,7 @@ namespace Options { file << " curvature: 0.0\n"; file << " bleeding: 0.0\n"; file << " flicker: 0.0\n"; - file << " - name: \"SUBTLE\"\n"; + file << " - name: \"Subtle\"\n"; file << " vignette: 0.3\n"; file << " scanlines: 0.4\n"; file << " chroma: 0.05\n"; @@ -188,13 +188,13 @@ namespace Options { file << " curvature: 0.0\n"; file << " bleeding: 0.0\n"; file << " flicker: 0.0\n"; - file << " - name: \"CRT LIVE\"\n"; - file << " vignette: 0.5\n"; + file << " - name: \"CRT Live\"\n"; + file << " vignette: 0.15\n"; file << " scanlines: 0.6\n"; file << " chroma: 0.3\n"; file << " mask: 0.3\n"; - file << " gamma: 0.4\n"; - file << " curvature: 0.3\n"; + file << " gamma: 0.1\n"; + file << " curvature: 0.0\n"; file << " bleeding: 0.4\n"; file << " flicker: 0.8\n"; @@ -204,12 +204,12 @@ namespace Options { // Cargar los presets recién escritos postfx_presets.clear(); - postfx_presets.push_back({"CRT", 0.6F, 0.7F, 0.15F, 0.5F, 0.5F, 0.0F, 0.0F, 0.0F}); + postfx_presets.push_back({"CRT", 0.15F, 0.7F, 0.2F, 0.5F, 0.1F, 0.0F, 0.0F, 0.0F}); postfx_presets.push_back({"NTSC", 0.4F, 0.5F, 0.2F, 0.3F, 0.3F, 0.0F, 0.6F, 0.0F}); - postfx_presets.push_back({"CURVED", 0.5F, 0.6F, 0.1F, 0.4F, 0.4F, 0.8F, 0.0F, 0.0F}); - postfx_presets.push_back({"SCANLINES", 0.0F, 0.8F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F}); - postfx_presets.push_back({"SUBTLE", 0.3F, 0.4F, 0.05F, 0.0F, 0.2F, 0.0F, 0.0F, 0.0F}); - postfx_presets.push_back({"CRT LIVE", 0.5F, 0.6F, 0.3F, 0.3F, 0.4F, 0.3F, 0.4F, 0.8F}); + postfx_presets.push_back({"Curved", 0.5F, 0.6F, 0.1F, 0.4F, 0.4F, 0.8F, 0.0F, 0.0F}); + postfx_presets.push_back({"Scanlines", 0.0F, 0.8F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F}); + postfx_presets.push_back({"Subtle", 0.3F, 0.4F, 0.05F, 0.0F, 0.2F, 0.0F, 0.0F, 0.0F}); + postfx_presets.push_back({"CRT Live", 0.15F, 0.6F, 0.3F, 0.3F, 0.1F, 0.0F, 0.4F, 0.8F}); video.shader.current_postfx_preset = 0; return true; @@ -236,10 +236,10 @@ namespace Options { // Rellena los presets CrtPi por defecto static void populateDefaultCrtPiPresets() { crtpi_presets.clear(); - crtpi_presets.push_back({"DEFAULT", 6.0F, 0.12F, 3.5F, 2.4F, 2.2F, 0.80F, 0.05F, 0.10F, 2, true, true, true, false, false}); - crtpi_presets.push_back({"CURVED", 6.0F, 0.12F, 3.5F, 2.4F, 2.2F, 0.80F, 0.05F, 0.10F, 2, true, true, true, true, false}); - crtpi_presets.push_back({"SHARP", 6.0F, 0.12F, 3.5F, 2.4F, 2.2F, 0.80F, 0.05F, 0.10F, 2, true, false, true, false, true}); - crtpi_presets.push_back({"MINIMAL", 8.0F, 0.05F, 2.0F, 2.4F, 2.2F, 1.00F, 0.0F, 0.0F, 0, true, false, false, false, false}); + crtpi_presets.push_back({"Default", 6.0F, 0.12F, 3.5F, 2.4F, 2.2F, 0.80F, 0.05F, 0.10F, 2, true, true, true, false, false}); + crtpi_presets.push_back({"Curved", 6.0F, 0.12F, 3.5F, 2.4F, 2.2F, 0.80F, 0.05F, 0.10F, 2, true, true, true, true, false}); + crtpi_presets.push_back({"Sharp", 6.0F, 0.12F, 3.5F, 2.4F, 2.2F, 0.80F, 0.05F, 0.10F, 2, true, false, true, false, true}); + crtpi_presets.push_back({"Minimal", 8.0F, 0.05F, 2.0F, 2.4F, 2.2F, 1.00F, 0.0F, 0.0F, 0, true, false, false, false, false}); } // Escribe los presets CrtPi por defecto al fichero @@ -261,10 +261,10 @@ namespace Options { file << "# mask_type: 0=none, 1=green/magenta, 2=RGB phosphor\n"; file << "# enable_scanlines/multisample/gamma/curvature/sharper: true/false\n"; file << "\npresets:\n"; - file << " - name: \"DEFAULT\"\n scanline_weight: 6.0\n scanline_gap_brightness: 0.12\n bloom_factor: 3.5\n input_gamma: 2.4\n output_gamma: 2.2\n mask_brightness: 0.80\n curvature_x: 0.05\n curvature_y: 0.10\n mask_type: 2\n enable_scanlines: true\n enable_multisample: true\n enable_gamma: true\n enable_curvature: false\n enable_sharper: false\n"; - file << " - name: \"CURVED\"\n scanline_weight: 6.0\n scanline_gap_brightness: 0.12\n bloom_factor: 3.5\n input_gamma: 2.4\n output_gamma: 2.2\n mask_brightness: 0.80\n curvature_x: 0.05\n curvature_y: 0.10\n mask_type: 2\n enable_scanlines: true\n enable_multisample: true\n enable_gamma: true\n enable_curvature: true\n enable_sharper: false\n"; - file << " - name: \"SHARP\"\n scanline_weight: 6.0\n scanline_gap_brightness: 0.12\n bloom_factor: 3.5\n input_gamma: 2.4\n output_gamma: 2.2\n mask_brightness: 0.80\n curvature_x: 0.05\n curvature_y: 0.10\n mask_type: 2\n enable_scanlines: true\n enable_multisample: false\n enable_gamma: true\n enable_curvature: false\n enable_sharper: true\n"; - file << " - name: \"MINIMAL\"\n scanline_weight: 8.0\n scanline_gap_brightness: 0.05\n bloom_factor: 2.0\n input_gamma: 2.4\n output_gamma: 2.2\n mask_brightness: 1.00\n curvature_x: 0.0\n curvature_y: 0.0\n mask_type: 0\n enable_scanlines: true\n enable_multisample: false\n enable_gamma: false\n enable_curvature: false\n enable_sharper: false\n"; + file << " - name: \"Default\"\n scanline_weight: 6.0\n scanline_gap_brightness: 0.12\n bloom_factor: 3.5\n input_gamma: 2.4\n output_gamma: 2.2\n mask_brightness: 0.80\n curvature_x: 0.05\n curvature_y: 0.10\n mask_type: 2\n enable_scanlines: true\n enable_multisample: true\n enable_gamma: true\n enable_curvature: false\n enable_sharper: false\n"; + file << " - name: \"Curved\"\n scanline_weight: 6.0\n scanline_gap_brightness: 0.12\n bloom_factor: 3.5\n input_gamma: 2.4\n output_gamma: 2.2\n mask_brightness: 0.80\n curvature_x: 0.05\n curvature_y: 0.10\n mask_type: 2\n enable_scanlines: true\n enable_multisample: true\n enable_gamma: true\n enable_curvature: true\n enable_sharper: false\n"; + file << " - name: \"Sharp\"\n scanline_weight: 6.0\n scanline_gap_brightness: 0.12\n bloom_factor: 3.5\n input_gamma: 2.4\n output_gamma: 2.2\n mask_brightness: 0.80\n curvature_x: 0.05\n curvature_y: 0.10\n mask_type: 2\n enable_scanlines: true\n enable_multisample: false\n enable_gamma: true\n enable_curvature: false\n enable_sharper: true\n"; + file << " - name: \"Minimal\"\n scanline_weight: 8.0\n scanline_gap_brightness: 0.05\n bloom_factor: 2.0\n input_gamma: 2.4\n output_gamma: 2.2\n mask_brightness: 1.00\n curvature_x: 0.0\n curvature_y: 0.0\n mask_type: 0\n enable_scanlines: true\n enable_multisample: false\n enable_gamma: false\n enable_curvature: false\n enable_sharper: false\n"; file.close(); SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "CrtPi file created with defaults: %s", crtpi_file_path.c_str()); populateDefaultCrtPiPresets(); @@ -431,48 +431,24 @@ namespace Options { video.shader.current_crtpi_preset_name = sh["crtpi_preset"].get_value(); } catch (...) {} } - } else if (vid.contains("postfx")) { - // Backward compat: formato antiguo plano - try { - video.shader.enabled = vid["postfx"].get_value(); - } catch (...) {} - if (vid.contains("postfx_preset")) { - try { - int preset = vid["postfx_preset"].get_value(); - if (preset >= 0) { video.shader.current_postfx_preset = preset; } - } catch (...) {} - } } // --- Supersampling --- if (vid.contains("supersampling")) { const auto& ss_node = vid["supersampling"]; - if (ss_node.is_mapping()) { - // Nuevo formato anidado - if (ss_node.contains("enabled")) { - try { - video.supersampling.enabled = ss_node["enabled"].get_value(); - } catch (...) {} - } - if (ss_node.contains("linear_upscale")) { - try { - video.supersampling.linear_upscale = ss_node["linear_upscale"].get_value(); - } catch (...) {} - } - if (ss_node.contains("downscale_algo")) { - try { - video.supersampling.downscale_algo = ss_node["downscale_algo"].get_value(); - } catch (...) {} - } - } else { - // Backward compat: bool o int + if (ss_node.contains("enabled")) { try { - if (ss_node.is_boolean()) { - video.supersampling.enabled = ss_node.get_value(); - } else { - int factor = ss_node.get_value(); - video.supersampling.enabled = factor >= 2; - } + video.supersampling.enabled = ss_node["enabled"].get_value(); + } catch (...) {} + } + if (ss_node.contains("linear_upscale")) { + try { + video.supersampling.linear_upscale = ss_node["linear_upscale"].get_value(); + } catch (...) {} + } + if (ss_node.contains("downscale_algo")) { + try { + video.supersampling.downscale_algo = ss_node["downscale_algo"].get_value(); } catch (...) {} } } @@ -617,6 +593,20 @@ namespace Options { try { auto yaml = fkyaml::node::deserialize(content); + // Comprobar versión: si no coincide, regenerar config por defecto + int file_version = 0; + if (yaml.contains("version")) { + try { + file_version = yaml["version"].get_value(); + } catch (...) {} + } + if (file_version != Settings::CURRENT_CONFIG_VERSION) { + SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "Config version %d != expected %d. Recreating defaults.", file_version, Settings::CURRENT_CONFIG_VERSION); + init(); + saveToFile(); + return true; + } + loadWindowFromYaml(yaml); loadVideoFromYaml(yaml); loadAudioFromYaml(yaml); diff --git a/source/options.hpp b/source/options.hpp index 572c110..093e617 100644 --- a/source/options.hpp +++ b/source/options.hpp @@ -110,7 +110,8 @@ namespace Options { }; struct Settings { - int config_version = 2; // Versión del archivo de configuración + static constexpr int CURRENT_CONFIG_VERSION = 3; // Versión esperada del fichero + int config_version = CURRENT_CONFIG_VERSION; // Versión del archivo de configuración Difficulty::Code difficulty = Difficulty::Code::NORMAL; // Dificultad del juego Lang::Code language = Lang::Code::VALENCIAN; // Idioma usado en el juego bool autofire = Defaults::Settings::AUTOFIRE; // Indicador de autofire diff --git a/source/screen.cpp b/source/screen.cpp index a439472..6670d20 100644 --- a/source/screen.cpp +++ b/source/screen.cpp @@ -13,11 +13,13 @@ #include "options.hpp" // Para Video, video, Window, window #include "param.hpp" // Para Param, param, ParamGame, ParamDebug #include "rendering/sdl3gpu/sdl3gpu_shader.hpp" // Para SDL3GPUShader +#include "resource.hpp" // Para Resource #include "text.hpp" // Para Text #include "texture.hpp" // Para Texture #include "ui/logger.hpp" // Para info #include "ui/notifier.hpp" // Para Notifier #include "ui/service_menu.hpp" // Para ServiceMenu +#include "utils.hpp" // Para toLower // Singleton Screen* Screen::instance = nullptr; @@ -240,15 +242,44 @@ void Screen::renderShake() { // Muestra información por pantalla void Screen::renderInfo() const { if (debug_info_.show) { - // Resolution - debug_info_.text->writeDX(Text::COLOR | Text::STROKE, param.game.width - debug_info_.text->length(Options::video.info) - 2, 1, Options::video.info, 1, param.debug.color, 1, param.debug.color.DARKEN(150)); + const Color GOLD(0xFF, 0xD7, 0x00); + const Color GOLD_SHADOW = GOLD.DARKEN(150); + + // Construir texto: fps - driver - preset + std::string info_text = std::to_string(fps_.last_value) + " fps"; + + // Driver GPU + if (shader_backend_ && shader_backend_->isHardwareAccelerated()) { + const std::string DRIVER = shader_backend_->getDriverName(); + if (!DRIVER.empty()) { + info_text += " - " + toLower(DRIVER); + } + } else { + info_text += " - sdl"; + } + + // Shader + preset + if (Options::video.shader.enabled) { + if (Options::video.shader.current_shader == Rendering::ShaderType::CRTPI) { + const std::string PRESET_NAME = Options::crtpi_presets.empty() ? "" : Options::crtpi_presets.at(static_cast(Options::video.shader.current_crtpi_preset)).name; + info_text += " - crtpi " + toLower(PRESET_NAME); + } else { + const std::string PRESET_NAME = Options::postfx_presets.empty() ? "" : Options::postfx_presets.at(static_cast(Options::video.shader.current_postfx_preset)).name; + info_text += " - postfx " + toLower(PRESET_NAME); + if (Options::video.supersampling.enabled) { info_text += " (ss)"; } + } + } + + // Centrado arriba + const int TEXT_WIDTH = debug_info_.text->length(info_text); + const int X_POS = (static_cast(param.game.width) - TEXT_WIDTH) / 2; + debug_info_.text->writeDX(Text::COLOR | Text::STROKE, X_POS, 1, info_text, 1, GOLD, 1, GOLD_SHADOW); - // FPS - const std::string FPS_TEXT = std::to_string(fps_.last_value) + " FPS"; - debug_info_.text->writeDX(Text::COLOR | Text::STROKE, param.game.width - debug_info_.text->length(FPS_TEXT) - 2, 1 + debug_info_.text->getCharacterSize(), FPS_TEXT, 1, param.debug.color, 1, param.debug.color.DARKEN(150)); #ifdef RECORDING - // RECORDING - debug_info_.text->writeDX(Text::COLOR | Text::STROKE, param.game.width - debug_info_.text->length("RECORDING"), 2 * (1 + debug_info_.text->getCharacterSize()), "RECORDING", 1, param.debug.color, 1, param.debug.color.DARKEN(150)); + const std::string REC_TEXT = "recording"; + const int REC_WIDTH = debug_info_.text->length(REC_TEXT); + const int REC_X = (static_cast(param.game.width) - REC_WIDTH) / 2; + debug_info_.text->writeDX(Text::COLOR | Text::STROKE, REC_X, 1 + debug_info_.text->getCharacterSize(), REC_TEXT, 1, GOLD, 1, GOLD_SHADOW); #endif } } @@ -594,6 +625,15 @@ void Screen::setVSync(bool enabled) { void Screen::getSingletons() { service_menu_ = ServiceMenu::get(); notifier_ = Notifier::get(); +#ifdef _DEBUG + // Actualizar la fuente de debug a 8bithud (ahora Resource está disponible) + if (Resource::get() != nullptr) { + auto hud_text = Resource::get()->getText("8bithud"); + if (hud_text) { + debug_info_.text = hud_text; + } + } +#endif } // Aplica los valores de las opciones