afegits tots els valors d'escala que dona sdl3
This commit is contained in:
@@ -148,7 +148,7 @@ Follows the pattern from `jaildoctors_dilemma`, persists to YAML:
|
|||||||
| F6 | Toggle supersampling |
|
| F6 | Toggle supersampling |
|
||||||
| F7 | Cycle shader type (PostFX ↔ CRT-Pi) |
|
| F7 | Cycle shader type (PostFX ↔ CRT-Pi) |
|
||||||
| F8 | Cycle shader presets |
|
| F8 | Cycle shader presets |
|
||||||
| F9 | Toggle stretch filter (nearest ↔ linear) |
|
| F9 | Cycle texture filter (nearest ↔ linear) — sempre aplicat, independent de 4:3 |
|
||||||
| F10 | Cycle render info (off → top → bottom → off) |
|
| F10 | Cycle render info (off → top → bottom → off) |
|
||||||
| F11 | Toggle pause (Director skips `scene->tick()` + `JA_PauseMusic`/`JA_ResumeMusic`) |
|
| F11 | Toggle pause (Director skips `scene->tick()` + `JA_PauseMusic`/`JA_ResumeMusic`) |
|
||||||
| F12 | Toggle floating options menu |
|
| F12 | Toggle floating options menu |
|
||||||
@@ -225,7 +225,7 @@ JD8_Flip produces ABGR byte order: `0xFF000000 + R + (G<<8) + (B<<16)`. SDL text
|
|||||||
|
|
||||||
| File | Content |
|
| File | Content |
|
||||||
|------|---------|
|
|------|---------|
|
||||||
| `~/.config/jailgames/aee/config.yaml` | Main config: video (incl. `vsync`, `integer_scale`), audio (incl. `enabled` master + `music_*` + `sound_*`), window, render_info (incl. `show_time`), game, shader selection, controls (només moviment del jugador) |
|
| `~/.config/jailgames/aee/config.yaml` | Main config: video (incl. `vsync`, `scaling_mode`, `texture_filter`), audio (incl. `enabled` master + `music_*` + `sound_*`), window, render_info (incl. `show_time`), game, shader selection, controls (només moviment del jugador) |
|
||||||
| `~/.config/jailgames/aee/keys.yaml` | UI key overrides (només entrades que difereixen del default de [data/input/keys.yaml](data/input/keys.yaml)). Generat per `KeyConfig::saveOverrides()` |
|
| `~/.config/jailgames/aee/keys.yaml` | UI key overrides (només entrades que difereixen del default de [data/input/keys.yaml](data/input/keys.yaml)). Generat per `KeyConfig::saveOverrides()` |
|
||||||
| `~/.config/jailgames/aee/postfx.yaml` | PostFX shader presets (6 defaults: CRT, NTSC, CURVED, SCANLINES, SUBTLE, CRT LIVE) |
|
| `~/.config/jailgames/aee/postfx.yaml` | PostFX shader presets (6 defaults: CRT, NTSC, CURVED, SCANLINES, SUBTLE, CRT LIVE) |
|
||||||
| `~/.config/jailgames/aee/crtpi.yaml` | CRT-Pi shader presets (4 defaults: DEFAULT, CURVED, SHARP, MINIMAL) |
|
| `~/.config/jailgames/aee/crtpi.yaml` | CRT-Pi shader presets (4 defaults: DEFAULT, CURVED, SHARP, MINIMAL) |
|
||||||
|
|||||||
@@ -36,9 +36,9 @@ keys:
|
|||||||
- id: next_shader_preset
|
- id: next_shader_preset
|
||||||
code: "F8"
|
code: "F8"
|
||||||
desc: "Pròxim preset del shader"
|
desc: "Pròxim preset del shader"
|
||||||
- id: toggle_stretch_filter
|
- id: cycle_texture_filter
|
||||||
code: "F9"
|
code: "F9"
|
||||||
desc: "Filtre 4:3 (nearest / linear)"
|
desc: "Filtre de textura (nearest / linear)"
|
||||||
- id: toggle_render_info
|
- id: toggle_render_info
|
||||||
code: "F10"
|
code: "F10"
|
||||||
desc: "Mostra info de renderitzat"
|
desc: "Mostra info de renderitzat"
|
||||||
|
|||||||
@@ -23,10 +23,10 @@ menu:
|
|||||||
aspect_4_3: "Aspecte 4:3"
|
aspect_4_3: "Aspecte 4:3"
|
||||||
supersampling: "Supersampling"
|
supersampling: "Supersampling"
|
||||||
vsync: "Vsync"
|
vsync: "Vsync"
|
||||||
integer_scale: "Escala entera"
|
scaling_mode: "Escala"
|
||||||
shader_type: "Tipus shader"
|
shader_type: "Tipus shader"
|
||||||
preset: "Preset"
|
preset: "Preset"
|
||||||
stretch_filter: "Filtre 4:3"
|
texture_filter: "Filtre textura"
|
||||||
render_info: "Render info"
|
render_info: "Render info"
|
||||||
uptime: "Temps de joc"
|
uptime: "Temps de joc"
|
||||||
master_enable: "Àudio"
|
master_enable: "Àudio"
|
||||||
@@ -55,6 +55,11 @@ menu:
|
|||||||
press_key: "<Prem tecla>"
|
press_key: "<Prem tecla>"
|
||||||
empty: "(Buit)"
|
empty: "(Buit)"
|
||||||
unknown: "---"
|
unknown: "---"
|
||||||
|
scaling_disabled: "Sense escala"
|
||||||
|
scaling_stretch: "Estirada"
|
||||||
|
scaling_letterbox: "Letterbox"
|
||||||
|
scaling_overscan: "Overscan"
|
||||||
|
scaling_integer: "Entera"
|
||||||
|
|
||||||
window:
|
window:
|
||||||
title: "© 2000 Aventures en Egipte — JailDesigner"
|
title: "© 2000 Aventures en Egipte — JailDesigner"
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ namespace GlobalInputs {
|
|||||||
static bool ss_prev = false;
|
static bool ss_prev = false;
|
||||||
static bool next_shader_prev = false;
|
static bool next_shader_prev = false;
|
||||||
static bool next_preset_prev = false;
|
static bool next_preset_prev = false;
|
||||||
static bool stretch_filter_prev = false;
|
static bool texture_filter_prev = false;
|
||||||
static bool render_info_prev = false;
|
static bool render_info_prev = false;
|
||||||
|
|
||||||
auto handle() -> bool {
|
auto handle() -> bool {
|
||||||
@@ -106,14 +106,16 @@ namespace GlobalInputs {
|
|||||||
if (next_preset) consumed = true;
|
if (next_preset) consumed = true;
|
||||||
next_preset_prev = next_preset;
|
next_preset_prev = next_preset;
|
||||||
|
|
||||||
// F9 — Toggle filtre d'estirament 4:3 (NEAREST ↔ LINEAR)
|
// F9 — Cicla filtre de textura (NEAREST ↔ LINEAR), sempre aplicat
|
||||||
bool stretch_filter = JI_KeyPressed(KeyConfig::scancode("toggle_stretch_filter"));
|
bool texture_filter = JI_KeyPressed(KeyConfig::scancode("cycle_texture_filter"));
|
||||||
if (stretch_filter && !stretch_filter_prev) {
|
if (texture_filter && !texture_filter_prev) {
|
||||||
Screen::get()->toggleStretchFilter();
|
Screen::get()->cycleTextureFilter(+1);
|
||||||
Overlay::showNotification(Options::video.stretch_filter_linear ? Locale::get("notifications.filter_linear") : Locale::get("notifications.filter_nearest"));
|
Overlay::showNotification(Options::video.texture_filter == Options::TextureFilter::LINEAR
|
||||||
|
? Locale::get("notifications.filter_linear")
|
||||||
|
: Locale::get("notifications.filter_nearest"));
|
||||||
}
|
}
|
||||||
if (stretch_filter) consumed = true;
|
if (texture_filter) consumed = true;
|
||||||
stretch_filter_prev = stretch_filter;
|
texture_filter_prev = texture_filter;
|
||||||
|
|
||||||
// F10 — Toggle render info (FPS, driver, shader)
|
// F10 — Toggle render info (FPS, driver, shader)
|
||||||
bool render_info = JI_KeyPressed(KeyConfig::scancode("toggle_render_info"));
|
bool render_info = JI_KeyPressed(KeyConfig::scancode("toggle_render_info"));
|
||||||
|
|||||||
@@ -151,9 +151,20 @@ namespace Menu {
|
|||||||
|
|
||||||
p.items.push_back({Locale::get("menu.items.vsync"), ItemKind::Toggle, [] { return onOff(Options::video.vsync); }, [](int) { Screen::get()->toggleVSync(); }, nullptr, nullptr, nullptr});
|
p.items.push_back({Locale::get("menu.items.vsync"), ItemKind::Toggle, [] { return onOff(Options::video.vsync); }, [](int) { Screen::get()->toggleVSync(); }, nullptr, nullptr, nullptr});
|
||||||
|
|
||||||
p.items.push_back({Locale::get("menu.items.integer_scale"), ItemKind::Toggle, [] { return onOff(Options::video.integer_scale); }, [](int) { Screen::get()->toggleIntegerScale(); }, nullptr, nullptr, nullptr});
|
p.items.push_back({Locale::get("menu.items.scaling_mode"), ItemKind::Cycle, [] {
|
||||||
|
switch (Options::video.scaling_mode) {
|
||||||
|
case Options::ScalingMode::DISABLED: return std::string(Locale::get("menu.values.scaling_disabled"));
|
||||||
|
case Options::ScalingMode::STRETCH: return std::string(Locale::get("menu.values.scaling_stretch"));
|
||||||
|
case Options::ScalingMode::LETTERBOX: return std::string(Locale::get("menu.values.scaling_letterbox"));
|
||||||
|
case Options::ScalingMode::OVERSCAN: return std::string(Locale::get("menu.values.scaling_overscan"));
|
||||||
|
case Options::ScalingMode::INTEGER: return std::string(Locale::get("menu.values.scaling_integer"));
|
||||||
|
}
|
||||||
|
return std::string(Locale::get("menu.values.scaling_integer")); }, [](int dir) { Screen::get()->cycleScalingMode(dir); }, nullptr, nullptr, nullptr});
|
||||||
|
|
||||||
p.items.push_back({Locale::get("menu.items.stretch_filter"), ItemKind::Toggle, [] { return std::string(Options::video.stretch_filter_linear ? Locale::get("menu.values.linear") : Locale::get("menu.values.nearest")); }, [](int) { Screen::get()->toggleStretchFilter(); }, nullptr, nullptr, nullptr});
|
p.items.push_back({Locale::get("menu.items.texture_filter"), ItemKind::Cycle, [] {
|
||||||
|
return std::string(Options::video.texture_filter == Options::TextureFilter::LINEAR
|
||||||
|
? Locale::get("menu.values.linear")
|
||||||
|
: Locale::get("menu.values.nearest")); }, [](int dir) { Screen::get()->cycleTextureFilter(dir); }, nullptr, nullptr, nullptr});
|
||||||
|
|
||||||
// Bloc shaders: no disponible a WASM (NO_SHADERS, sense SDL3 GPU a WebGL2)
|
// Bloc shaders: no disponible a WASM (NO_SHADERS, sense SDL3 GPU a WebGL2)
|
||||||
#ifndef __EMSCRIPTEN__
|
#ifndef __EMSCRIPTEN__
|
||||||
|
|||||||
@@ -98,11 +98,10 @@ void Screen::initShaders() {
|
|||||||
std::cout << "GPU driver: " << gpu_driver_ << '\n';
|
std::cout << "GPU driver: " << gpu_driver_ << '\n';
|
||||||
|
|
||||||
// Aplica opcions de vídeo
|
// Aplica opcions de vídeo
|
||||||
shader_backend_->setScaleMode(Options::video.integer_scale);
|
shader_backend_->setScalingMode(Options::video.scaling_mode);
|
||||||
shader_backend_->setVSync(Options::video.vsync);
|
shader_backend_->setVSync(Options::video.vsync);
|
||||||
shader_backend_->setStretchFilter(Options::video.stretch_filter_linear);
|
shader_backend_->setTextureFilter(Options::video.texture_filter);
|
||||||
shader_backend_->setStretch4_3(Options::video.aspect_ratio_4_3);
|
shader_backend_->setStretch4_3(Options::video.aspect_ratio_4_3);
|
||||||
shader_backend_->setLinearUpscale(Options::video.linear_upscale);
|
|
||||||
shader_backend_->setDownscaleAlgo(Options::video.downscale_algo);
|
shader_backend_->setDownscaleAlgo(Options::video.downscale_algo);
|
||||||
|
|
||||||
if (Options::video.supersampling) {
|
if (Options::video.supersampling) {
|
||||||
@@ -211,10 +210,14 @@ void Screen::toggleAspectRatio() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Screen::toggleIntegerScale() {
|
void Screen::cycleScalingMode(int dir) {
|
||||||
Options::video.integer_scale = !Options::video.integer_scale;
|
constexpr int N = 5; // DISABLED, STRETCH, LETTERBOX, OVERSCAN, INTEGER
|
||||||
|
int cur = static_cast<int>(Options::video.scaling_mode);
|
||||||
|
int step = (dir >= 0) ? 1 : -1;
|
||||||
|
cur = ((cur + step) % N + N) % N;
|
||||||
|
Options::video.scaling_mode = static_cast<Options::ScalingMode>(cur);
|
||||||
if (shader_backend_) {
|
if (shader_backend_) {
|
||||||
shader_backend_->setScaleMode(Options::video.integer_scale);
|
shader_backend_->setScalingMode(Options::video.scaling_mode);
|
||||||
} else {
|
} else {
|
||||||
applyFallbackPresentation();
|
applyFallbackPresentation();
|
||||||
}
|
}
|
||||||
@@ -227,10 +230,15 @@ void Screen::toggleVSync() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Screen::toggleStretchFilter() {
|
void Screen::cycleTextureFilter(int dir) {
|
||||||
Options::video.stretch_filter_linear = !Options::video.stretch_filter_linear;
|
// NEAREST <-> LINEAR (només 2 valors, dir no importa més enllà de canviar)
|
||||||
|
(void)dir;
|
||||||
|
Options::video.texture_filter =
|
||||||
|
(Options::video.texture_filter == Options::TextureFilter::LINEAR)
|
||||||
|
? Options::TextureFilter::NEAREST
|
||||||
|
: Options::TextureFilter::LINEAR;
|
||||||
if (shader_backend_) {
|
if (shader_backend_) {
|
||||||
shader_backend_->setStretchFilter(Options::video.stretch_filter_linear);
|
shader_backend_->setTextureFilter(Options::video.texture_filter);
|
||||||
} else {
|
} else {
|
||||||
applyFallbackPresentation();
|
applyFallbackPresentation();
|
||||||
}
|
}
|
||||||
@@ -389,22 +397,27 @@ void Screen::updateRenderInfo() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Screen::applyFallbackPresentation() {
|
void Screen::applyFallbackPresentation() {
|
||||||
// Fallback SDL_Renderer (p.ex. emscripten/WebGL2 sense shaders GPU): tria
|
// Fallback SDL_Renderer (p.ex. emscripten/WebGL2 sense shaders GPU).
|
||||||
// el mode de presentació lògica segons 4:3 i integer_scale, i aplica el
|
// Filtre global (texture_filter) s'aplica sempre, independent de 4:3.
|
||||||
// filtre de la textura segons stretch_filter_linear. Sense açò, el path
|
SDL_ScaleMode scale = (Options::video.texture_filter == Options::TextureFilter::LINEAR)
|
||||||
// fallback mostrava sempre LETTERBOX i ignorava les tres flags.
|
? SDL_SCALEMODE_LINEAR
|
||||||
SDL_ScaleMode scale = Options::video.stretch_filter_linear ? SDL_SCALEMODE_LINEAR : SDL_SCALEMODE_NEAREST;
|
: SDL_SCALEMODE_NEAREST;
|
||||||
if (texture_) SDL_SetTextureScaleMode(texture_, scale);
|
if (texture_) SDL_SetTextureScaleMode(texture_, scale);
|
||||||
|
|
||||||
SDL_RendererLogicalPresentation mode;
|
// Si 4:3 actiu, la finestra ja té aspect 4:3 (alçada × 1.2); STRETCH és
|
||||||
|
// l'única opció viable al path fallback (el GPU path fa l'upscale 4:3 abans
|
||||||
|
// d'escollir el mode de finestra; en fallback no tenim eixa capa intermèdia).
|
||||||
|
SDL_RendererLogicalPresentation mode = SDL_LOGICAL_PRESENTATION_LETTERBOX;
|
||||||
if (Options::video.aspect_ratio_4_3) {
|
if (Options::video.aspect_ratio_4_3) {
|
||||||
// La finestra ja té aspect 4:3 (alçada × 1.2); STRETCH estira la
|
|
||||||
// textura 320×200 fins a omplir-la exactament.
|
|
||||||
mode = SDL_LOGICAL_PRESENTATION_STRETCH;
|
mode = SDL_LOGICAL_PRESENTATION_STRETCH;
|
||||||
} else if (Options::video.integer_scale) {
|
|
||||||
mode = SDL_LOGICAL_PRESENTATION_INTEGER_SCALE;
|
|
||||||
} else {
|
} else {
|
||||||
mode = SDL_LOGICAL_PRESENTATION_LETTERBOX;
|
switch (Options::video.scaling_mode) {
|
||||||
|
case Options::ScalingMode::DISABLED: mode = SDL_LOGICAL_PRESENTATION_DISABLED; break;
|
||||||
|
case Options::ScalingMode::STRETCH: mode = SDL_LOGICAL_PRESENTATION_STRETCH; break;
|
||||||
|
case Options::ScalingMode::LETTERBOX: mode = SDL_LOGICAL_PRESENTATION_LETTERBOX; break;
|
||||||
|
case Options::ScalingMode::OVERSCAN: mode = SDL_LOGICAL_PRESENTATION_OVERSCAN; break;
|
||||||
|
case Options::ScalingMode::INTEGER: mode = SDL_LOGICAL_PRESENTATION_INTEGER_SCALE; break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
SDL_SetRenderLogicalPresentation(renderer_, GAME_WIDTH, GAME_HEIGHT, mode);
|
SDL_SetRenderLogicalPresentation(renderer_, GAME_WIDTH, GAME_HEIGHT, mode);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,9 +26,9 @@ class Screen {
|
|||||||
void toggleShaders();
|
void toggleShaders();
|
||||||
void toggleSupersampling();
|
void toggleSupersampling();
|
||||||
void toggleAspectRatio();
|
void toggleAspectRatio();
|
||||||
void toggleIntegerScale();
|
void cycleScalingMode(int dir); // Cicla DISABLED/STRETCH/LETTERBOX/OVERSCAN/INTEGER
|
||||||
void toggleVSync();
|
void toggleVSync();
|
||||||
void toggleStretchFilter();
|
void cycleTextureFilter(int dir); // Cicla NEAREST/LINEAR
|
||||||
void nextShaderType(); // Cicla PostFX ↔ CrtPi (F7)
|
void nextShaderType(); // Cicla PostFX ↔ CrtPi (F7)
|
||||||
void prevShaderType(); // Cicla al revés
|
void prevShaderType(); // Cicla al revés
|
||||||
void nextPreset(); // Cicla presets del shader actiu (F8)
|
void nextPreset(); // Cicla presets del shader actiu (F8)
|
||||||
|
|||||||
@@ -814,7 +814,7 @@ namespace Rendering {
|
|||||||
|
|
||||||
// ---- Upscale pass: scene_texture_ → scaled_texture_ ----
|
// ---- Upscale pass: scene_texture_ → scaled_texture_ ----
|
||||||
// Si 4:3 actiu, l'estirament s'aplica ací directament (320x200 → W*factor × H*factor*1.2)
|
// Si 4:3 actiu, l'estirament s'aplica ací directament (320x200 → W*factor × H*factor*1.2)
|
||||||
// El filtre per al 4:3 és configurable (stretch_filter_linear_).
|
// El filtre s'aplica sempre (texture_filter_linear_), independent de 4:3.
|
||||||
// L'effective_scene/height reflecteix la textura real que veuen els shaders.
|
// L'effective_scene/height reflecteix la textura real que veuen els shaders.
|
||||||
// Sense SS ni stretch: scene_texture_ a game_height_.
|
// Sense SS ni stretch: scene_texture_ a game_height_.
|
||||||
// Amb SS o stretch: scaled_texture_ a l'alçada escalada (amb o sense 4:3).
|
// Amb SS o stretch: scaled_texture_ a l'alçada escalada (amb o sense 4:3).
|
||||||
@@ -827,9 +827,8 @@ namespace Rendering {
|
|||||||
upscale_target.load_op = SDL_GPU_LOADOP_DONT_CARE;
|
upscale_target.load_op = SDL_GPU_LOADOP_DONT_CARE;
|
||||||
upscale_target.store_op = SDL_GPU_STOREOP_STORE;
|
upscale_target.store_op = SDL_GPU_STOREOP_STORE;
|
||||||
|
|
||||||
// Triar filtre: si 4:3 actiu, usar el filtre configurable per a l'estirament.
|
// Filtre global: s'aplica sempre (ja no depèn de 4:3).
|
||||||
// Si no, usar el filtre d'upscale normal (linear_upscale_).
|
bool use_linear = texture_filter_linear_;
|
||||||
bool use_linear = stretch_4_3_ ? stretch_filter_linear_ : linear_upscale_;
|
|
||||||
|
|
||||||
SDL_GPURenderPass* upass = SDL_BeginGPURenderPass(cmd, &upscale_target, 1, nullptr);
|
SDL_GPURenderPass* upass = SDL_BeginGPURenderPass(cmd, &upscale_target, 1, nullptr);
|
||||||
if (upass != nullptr) {
|
if (upass != nullptr) {
|
||||||
@@ -872,16 +871,38 @@ namespace Rendering {
|
|||||||
float vy = 0.0F;
|
float vy = 0.0F;
|
||||||
float vw = 0.0F;
|
float vw = 0.0F;
|
||||||
float vh = 0.0F;
|
float vh = 0.0F;
|
||||||
if (integer_scale_) {
|
switch (scaling_mode_) {
|
||||||
const int SCALE = std::max(1, std::min(static_cast<int>(sw) / static_cast<int>(logical_w), static_cast<int>(sh) / static_cast<int>(logical_h)));
|
case Options::ScalingMode::DISABLED:
|
||||||
vw = logical_w * static_cast<float>(SCALE);
|
// 1:1, sense escala (pot ser diminut en finestres grans)
|
||||||
vh = logical_h * static_cast<float>(SCALE);
|
vw = logical_w;
|
||||||
} else {
|
vh = logical_h;
|
||||||
const float SCALE = std::min(
|
break;
|
||||||
static_cast<float>(sw) / logical_w,
|
case Options::ScalingMode::STRETCH:
|
||||||
static_cast<float>(sh) / logical_h);
|
// Omple tota la finestra, escala no uniforme
|
||||||
vw = logical_w * SCALE;
|
vw = static_cast<float>(sw);
|
||||||
vh = logical_h * SCALE;
|
vh = static_cast<float>(sh);
|
||||||
|
break;
|
||||||
|
case Options::ScalingMode::LETTERBOX: {
|
||||||
|
const float SCALE = std::min(static_cast<float>(sw) / logical_w,
|
||||||
|
static_cast<float>(sh) / logical_h);
|
||||||
|
vw = logical_w * SCALE;
|
||||||
|
vh = logical_h * SCALE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Options::ScalingMode::OVERSCAN: {
|
||||||
|
const float SCALE = std::max(static_cast<float>(sw) / logical_w,
|
||||||
|
static_cast<float>(sh) / logical_h);
|
||||||
|
vw = logical_w * SCALE;
|
||||||
|
vh = logical_h * SCALE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Options::ScalingMode::INTEGER: {
|
||||||
|
const int SCALE = std::max(1, std::min(static_cast<int>(sw) / static_cast<int>(logical_w),
|
||||||
|
static_cast<int>(sh) / static_cast<int>(logical_h)));
|
||||||
|
vw = logical_w * static_cast<float>(SCALE);
|
||||||
|
vh = logical_h * static_cast<float>(SCALE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
vx = std::floor((static_cast<float>(sw) - vw) * 0.5F);
|
vx = std::floor((static_cast<float>(sw) - vw) * 0.5F);
|
||||||
vy = std::floor((static_cast<float>(sh) - vh) * 0.5F);
|
vy = std::floor((static_cast<float>(sh) - vh) * 0.5F);
|
||||||
@@ -1193,8 +1214,8 @@ namespace Rendering {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDL3GPUShader::setScaleMode(bool integer_scale) {
|
void SDL3GPUShader::setScalingMode(Options::ScalingMode mode) {
|
||||||
integer_scale_ = integer_scale;
|
scaling_mode_ = mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDL3GPUShader::setStretch4_3(bool enabled) {
|
void SDL3GPUShader::setStretch4_3(bool enabled) {
|
||||||
@@ -1221,10 +1242,6 @@ namespace Rendering {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDL3GPUShader::setLinearUpscale(bool linear) {
|
|
||||||
linear_upscale_ = linear;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SDL3GPUShader::setDownscaleAlgo(int algo) {
|
void SDL3GPUShader::setDownscaleAlgo(int algo) {
|
||||||
downscale_algo_ = std::max(0, std::min(algo, 2));
|
downscale_algo_ = std::max(0, std::min(algo, 2));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -96,15 +96,12 @@ namespace Rendering {
|
|||||||
// Activa/desactiva VSync en el swapchain
|
// Activa/desactiva VSync en el swapchain
|
||||||
void setVSync(bool vsync) override;
|
void setVSync(bool vsync) override;
|
||||||
|
|
||||||
// Activa/desactiva escalado entero (integer scale)
|
// Selecciona el mode de presentació lògica (DISABLED/STRETCH/LETTERBOX/OVERSCAN/INTEGER)
|
||||||
void setScaleMode(bool integer_scale) override;
|
void setScalingMode(Options::ScalingMode mode) override;
|
||||||
|
|
||||||
// Establece factor de supersampling (1 = off, 3 = 3×SS)
|
// Establece factor de supersampling (1 = off, 3 = 3×SS)
|
||||||
void setOversample(int factor) override;
|
void setOversample(int factor) override;
|
||||||
|
|
||||||
// Activa/desactiva interpolación LINEAR en el upscale (false = NEAREST)
|
|
||||||
void setLinearUpscale(bool linear) override;
|
|
||||||
|
|
||||||
// Selecciona algoritmo de downscale: 0=bilinear legacy, 1=Lanczos2, 2=Lanczos3
|
// Selecciona algoritmo de downscale: 0=bilinear legacy, 1=Lanczos2, 2=Lanczos3
|
||||||
void setDownscaleAlgo(int algo) override;
|
void setDownscaleAlgo(int algo) override;
|
||||||
|
|
||||||
@@ -123,7 +120,11 @@ namespace Rendering {
|
|||||||
// Estirament vertical 4:3 (fusionat amb l'upscale pass)
|
// Estirament vertical 4:3 (fusionat amb l'upscale pass)
|
||||||
void setStretch4_3(bool enabled) override;
|
void setStretch4_3(bool enabled) override;
|
||||||
[[nodiscard]] auto isStretch4_3() const -> bool override { return stretch_4_3_; }
|
[[nodiscard]] auto isStretch4_3() const -> bool override { return stretch_4_3_; }
|
||||||
void setStretchFilter(bool linear) override { stretch_filter_linear_ = linear; }
|
|
||||||
|
// Filtre de textura global (sempre aplicat, independent de 4:3)
|
||||||
|
void setTextureFilter(Options::TextureFilter filter) override {
|
||||||
|
texture_filter_linear_ = (filter == Options::TextureFilter::LINEAR);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static auto createShaderMSL(SDL_GPUDevice* device,
|
static auto createShaderMSL(SDL_GPUDevice* device,
|
||||||
@@ -176,10 +177,9 @@ namespace Rendering {
|
|||||||
std::string preferred_driver_; // Driver preferido; vacío = auto (SDL elige)
|
std::string preferred_driver_; // Driver preferido; vacío = auto (SDL elige)
|
||||||
bool is_initialized_ = false;
|
bool is_initialized_ = false;
|
||||||
bool vsync_ = true;
|
bool vsync_ = true;
|
||||||
bool integer_scale_ = false;
|
Options::ScalingMode scaling_mode_ = Options::ScalingMode::INTEGER;
|
||||||
bool linear_upscale_ = false; // Upscale NEAREST (false) o LINEAR (true)
|
bool stretch_4_3_ = false; // Estirament vertical 4:3
|
||||||
bool stretch_4_3_ = false; // Estirament vertical 4:3
|
bool texture_filter_linear_ = false; // Filtre global (false=NEAREST, true=LINEAR)
|
||||||
bool stretch_filter_linear_ = false; // Filtre per a l'estirament 4:3 (false=NEAREST, true=LINEAR)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Rendering
|
} // namespace Rendering
|
||||||
|
|||||||
@@ -5,6 +5,8 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
|
#include "game/options.hpp"
|
||||||
|
|
||||||
namespace Rendering {
|
namespace Rendering {
|
||||||
|
|
||||||
/** @brief Identificador del shader de post-procesado activo */
|
/** @brief Identificador del shader de post-procesado activo */
|
||||||
@@ -105,9 +107,9 @@ namespace Rendering {
|
|||||||
virtual void setVSync(bool /*vsync*/) {}
|
virtual void setVSync(bool /*vsync*/) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Activa o desactiva el escalado entero (integer scale)
|
* @brief Selecciona el mode d'escala de la finestra (mapeja SDL_RendererLogicalPresentation).
|
||||||
*/
|
*/
|
||||||
virtual void setScaleMode(bool /*integer_scale*/) {}
|
virtual void setScalingMode(Options::ScalingMode /*mode*/) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Establece el factor de supersampling (1 = off, 3 = 3× SS)
|
* @brief Establece el factor de supersampling (1 = off, 3 = 3× SS)
|
||||||
@@ -116,13 +118,6 @@ namespace Rendering {
|
|||||||
*/
|
*/
|
||||||
virtual void setOversample(int /*factor*/) {}
|
virtual void setOversample(int /*factor*/) {}
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Activa/desactiva interpolación LINEAR en el paso de upscale (SS).
|
|
||||||
* Por defecto NEAREST (false). Solo tiene efecto con supersampling activo.
|
|
||||||
*/
|
|
||||||
virtual void setLinearUpscale(bool /*linear*/) {}
|
|
||||||
[[nodiscard]] virtual auto isLinearUpscale() const -> bool { return false; }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Selecciona el algoritmo de downscale tras el PostFX (SS activo).
|
* @brief Selecciona el algoritmo de downscale tras el PostFX (SS activo).
|
||||||
* 0 = bilinear legacy (comportamiento actual, sin textura intermedia),
|
* 0 = bilinear legacy (comportamiento actual, sin textura intermedia),
|
||||||
@@ -179,9 +174,9 @@ namespace Rendering {
|
|||||||
[[nodiscard]] virtual auto isStretch4_3() const -> bool { return false; }
|
[[nodiscard]] virtual auto isStretch4_3() const -> bool { return false; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Filtre per a l'estirament 4:3 (false=NEAREST, true=LINEAR).
|
* @brief Filtre de textura global per a l'upscale final (sempre aplicat).
|
||||||
*/
|
*/
|
||||||
virtual void setStretchFilter(bool /*linear*/) {}
|
virtual void setTextureFilter(Options::TextureFilter /*filter*/) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Rendering
|
} // namespace Rendering
|
||||||
|
|||||||
@@ -17,12 +17,10 @@ namespace Defaults::Video {
|
|||||||
constexpr bool GPU_ACCELERATION = true;
|
constexpr bool GPU_ACCELERATION = true;
|
||||||
constexpr bool SHADER_ENABLED = false;
|
constexpr bool SHADER_ENABLED = false;
|
||||||
constexpr bool SUPERSAMPLING = false;
|
constexpr bool SUPERSAMPLING = false;
|
||||||
constexpr bool INTEGER_SCALE = true;
|
|
||||||
constexpr bool VSYNC = true;
|
constexpr bool VSYNC = true;
|
||||||
constexpr bool ASPECT_RATIO_4_3 = false; // CRT original estira 200→240
|
constexpr bool ASPECT_RATIO_4_3 = false; // CRT original estira 200→240
|
||||||
constexpr bool STRETCH_FILTER_LINEAR = false; // Filtre per a l'estirament 4:3 (false=NEAREST)
|
constexpr int DOWNSCALE_ALGO = 1; // 0=bilinear, 1=Lanczos2, 2=Lanczos3
|
||||||
constexpr int DOWNSCALE_ALGO = 1; // 0=bilinear, 1=Lanczos2, 2=Lanczos3
|
// TextureFilter i ScalingMode viuen a Options (requereixen #include, evitem dependència circular).
|
||||||
constexpr bool LINEAR_UPSCALE = false;
|
|
||||||
} // namespace Defaults::Video
|
} // namespace Defaults::Video
|
||||||
|
|
||||||
namespace Defaults::Audio {
|
namespace Defaults::Audio {
|
||||||
|
|||||||
@@ -123,18 +123,24 @@ namespace Options {
|
|||||||
video.shader_enabled = node["shader_enabled"].get_value<bool>();
|
video.shader_enabled = node["shader_enabled"].get_value<bool>();
|
||||||
if (node.contains("supersampling"))
|
if (node.contains("supersampling"))
|
||||||
video.supersampling = node["supersampling"].get_value<bool>();
|
video.supersampling = node["supersampling"].get_value<bool>();
|
||||||
if (node.contains("integer_scale"))
|
if (node.contains("scaling_mode")) {
|
||||||
video.integer_scale = node["integer_scale"].get_value<bool>();
|
auto s = node["scaling_mode"].get_value<std::string>();
|
||||||
|
if (s == "disabled") video.scaling_mode = ScalingMode::DISABLED;
|
||||||
|
else if (s == "stretch") video.scaling_mode = ScalingMode::STRETCH;
|
||||||
|
else if (s == "letterbox") video.scaling_mode = ScalingMode::LETTERBOX;
|
||||||
|
else if (s == "overscan") video.scaling_mode = ScalingMode::OVERSCAN;
|
||||||
|
else video.scaling_mode = ScalingMode::INTEGER;
|
||||||
|
}
|
||||||
if (node.contains("vsync"))
|
if (node.contains("vsync"))
|
||||||
video.vsync = node["vsync"].get_value<bool>();
|
video.vsync = node["vsync"].get_value<bool>();
|
||||||
if (node.contains("aspect_ratio_4_3"))
|
if (node.contains("aspect_ratio_4_3"))
|
||||||
video.aspect_ratio_4_3 = node["aspect_ratio_4_3"].get_value<bool>();
|
video.aspect_ratio_4_3 = node["aspect_ratio_4_3"].get_value<bool>();
|
||||||
if (node.contains("stretch_filter_linear"))
|
if (node.contains("texture_filter")) {
|
||||||
video.stretch_filter_linear = node["stretch_filter_linear"].get_value<bool>();
|
auto s = node["texture_filter"].get_value<std::string>();
|
||||||
|
video.texture_filter = (s == "linear") ? TextureFilter::LINEAR : TextureFilter::NEAREST;
|
||||||
|
}
|
||||||
if (node.contains("downscale_algo"))
|
if (node.contains("downscale_algo"))
|
||||||
video.downscale_algo = node["downscale_algo"].get_value<int>();
|
video.downscale_algo = node["downscale_algo"].get_value<int>();
|
||||||
if (node.contains("linear_upscale"))
|
|
||||||
video.linear_upscale = node["linear_upscale"].get_value<bool>();
|
|
||||||
if (node.contains("current_shader"))
|
if (node.contains("current_shader"))
|
||||||
video.current_shader = node["current_shader"].get_value<std::string>();
|
video.current_shader = node["current_shader"].get_value<std::string>();
|
||||||
if (node.contains("current_postfx_preset"))
|
if (node.contains("current_postfx_preset"))
|
||||||
@@ -277,12 +283,21 @@ namespace Options {
|
|||||||
file << " gpu_acceleration: " << (video.gpu_acceleration ? "true" : "false") << "\n";
|
file << " gpu_acceleration: " << (video.gpu_acceleration ? "true" : "false") << "\n";
|
||||||
file << " shader_enabled: " << (video.shader_enabled ? "true" : "false") << "\n";
|
file << " shader_enabled: " << (video.shader_enabled ? "true" : "false") << "\n";
|
||||||
file << " supersampling: " << (video.supersampling ? "true" : "false") << "\n";
|
file << " supersampling: " << (video.supersampling ? "true" : "false") << "\n";
|
||||||
file << " integer_scale: " << (video.integer_scale ? "true" : "false") << "\n";
|
{
|
||||||
|
const char* m = "integer";
|
||||||
|
switch (video.scaling_mode) {
|
||||||
|
case ScalingMode::DISABLED: m = "disabled"; break;
|
||||||
|
case ScalingMode::STRETCH: m = "stretch"; break;
|
||||||
|
case ScalingMode::LETTERBOX: m = "letterbox"; break;
|
||||||
|
case ScalingMode::OVERSCAN: m = "overscan"; break;
|
||||||
|
case ScalingMode::INTEGER: m = "integer"; break;
|
||||||
|
}
|
||||||
|
file << " scaling_mode: " << m << " # disabled|stretch|letterbox|overscan|integer\n";
|
||||||
|
}
|
||||||
file << " vsync: " << (video.vsync ? "true" : "false") << "\n";
|
file << " vsync: " << (video.vsync ? "true" : "false") << "\n";
|
||||||
file << " aspect_ratio_4_3: " << (video.aspect_ratio_4_3 ? "true" : "false") << "\n";
|
file << " aspect_ratio_4_3: " << (video.aspect_ratio_4_3 ? "true" : "false") << "\n";
|
||||||
file << " stretch_filter_linear: " << (video.stretch_filter_linear ? "true" : "false") << " # filtre 4:3: false=nearest, true=linear\n";
|
file << " texture_filter: " << (video.texture_filter == TextureFilter::LINEAR ? "linear" : "nearest") << " # nearest|linear\n";
|
||||||
file << " downscale_algo: " << video.downscale_algo << " # 0=bilinear, 1=Lanczos2, 2=Lanczos3\n";
|
file << " downscale_algo: " << video.downscale_algo << " # 0=bilinear, 1=Lanczos2, 2=Lanczos3\n";
|
||||||
file << " linear_upscale: " << (video.linear_upscale ? "true" : "false") << "\n";
|
|
||||||
file << " current_shader: " << video.current_shader << "\n";
|
file << " current_shader: " << video.current_shader << "\n";
|
||||||
file << " current_postfx_preset: " << video.current_postfx_preset << "\n";
|
file << " current_postfx_preset: " << video.current_postfx_preset << "\n";
|
||||||
file << " current_crtpi_preset: " << video.current_crtpi_preset << "\n";
|
file << " current_crtpi_preset: " << video.current_crtpi_preset << "\n";
|
||||||
|
|||||||
@@ -23,17 +23,28 @@ namespace Options {
|
|||||||
TOP = 1,
|
TOP = 1,
|
||||||
BOTTOM = 2 };
|
BOTTOM = 2 };
|
||||||
|
|
||||||
|
// Filtre de textura per a l'upscale final (sempre, no només en 4:3)
|
||||||
|
enum class TextureFilter { NEAREST = 0,
|
||||||
|
LINEAR = 1 };
|
||||||
|
|
||||||
|
// Mode de presentació lògica (escala finestra): mapeja directament
|
||||||
|
// als valors de SDL_RendererLogicalPresentation.
|
||||||
|
enum class ScalingMode { DISABLED = 0,
|
||||||
|
STRETCH = 1,
|
||||||
|
LETTERBOX = 2,
|
||||||
|
OVERSCAN = 3,
|
||||||
|
INTEGER = 4 };
|
||||||
|
|
||||||
// Opcions de vídeo
|
// Opcions de vídeo
|
||||||
struct Video {
|
struct Video {
|
||||||
bool gpu_acceleration{Defaults::Video::GPU_ACCELERATION};
|
bool gpu_acceleration{Defaults::Video::GPU_ACCELERATION};
|
||||||
bool shader_enabled{Defaults::Video::SHADER_ENABLED};
|
bool shader_enabled{Defaults::Video::SHADER_ENABLED};
|
||||||
bool supersampling{Defaults::Video::SUPERSAMPLING};
|
bool supersampling{Defaults::Video::SUPERSAMPLING};
|
||||||
bool integer_scale{Defaults::Video::INTEGER_SCALE};
|
ScalingMode scaling_mode{ScalingMode::INTEGER};
|
||||||
bool vsync{Defaults::Video::VSYNC};
|
bool vsync{Defaults::Video::VSYNC};
|
||||||
bool aspect_ratio_4_3{Defaults::Video::ASPECT_RATIO_4_3};
|
bool aspect_ratio_4_3{Defaults::Video::ASPECT_RATIO_4_3};
|
||||||
bool stretch_filter_linear{Defaults::Video::STRETCH_FILTER_LINEAR};
|
TextureFilter texture_filter{TextureFilter::NEAREST};
|
||||||
int downscale_algo{Defaults::Video::DOWNSCALE_ALGO};
|
int downscale_algo{Defaults::Video::DOWNSCALE_ALGO};
|
||||||
bool linear_upscale{Defaults::Video::LINEAR_UPSCALE};
|
|
||||||
std::string current_shader{"postfx"}; // "postfx" o "crtpi"
|
std::string current_shader{"postfx"}; // "postfx" o "crtpi"
|
||||||
std::string current_postfx_preset{"CRT"}; // Nom del preset PostFX actiu
|
std::string current_postfx_preset{"CRT"}; // Nom del preset PostFX actiu
|
||||||
std::string current_crtpi_preset{"DEFAULT"}; // Nom del preset CrtPi actiu
|
std::string current_crtpi_preset{"DEFAULT"}; // Nom del preset CrtPi actiu
|
||||||
|
|||||||
@@ -74,8 +74,8 @@ SDL_AppResult SDL_AppInit(void** /*appstate*/, int /*argc*/, char* /*argv*/[]) {
|
|||||||
Options::window.fullscreen = false;
|
Options::window.fullscreen = false;
|
||||||
Options::window.zoom = 1;
|
Options::window.zoom = 1;
|
||||||
Options::video.aspect_ratio_4_3 = true;
|
Options::video.aspect_ratio_4_3 = true;
|
||||||
Options::video.integer_scale = true;
|
Options::video.scaling_mode = Options::ScalingMode::INTEGER;
|
||||||
Options::video.stretch_filter_linear = true;
|
Options::video.texture_filter = Options::TextureFilter::LINEAR;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Carrega textos (idioma per defecte: valencià)
|
// Carrega textos (idioma per defecte: valencià)
|
||||||
|
|||||||
Reference in New Issue
Block a user