From eae81c4623f5711b77ec405edb239aebcb168290 Mon Sep 17 00:00:00 2001 From: Logan McNaughton <848146+loganmc10@users.noreply.github.com> Date: Tue, 14 Jan 2025 23:23:26 +0100 Subject: [PATCH] Add integer scaling option (#150) * Add integer scaling option * more * more * more --- parallel-rdp/interface.cpp | 52 ++++++++++++++++++------------ parallel-rdp/interface.hpp | 2 +- src/ui/config.rs | 2 ++ src/ui/gui.rs | 66 ++++++++++++++++++++++---------------- src/ui/video.rs | 3 +- 5 files changed, 75 insertions(+), 50 deletions(-) diff --git a/parallel-rdp/interface.cpp b/parallel-rdp/interface.cpp index 61385a14..b621c56f 100644 --- a/parallel-rdp/interface.cpp +++ b/parallel-rdp/interface.cpp @@ -51,6 +51,7 @@ enum vi_registers }; static bool fullscreen; +static bool integer_scaling; static SDL_Window *window; static RDP::CommandProcessor *processor; static SDL_WSIPlatform *wsi_platform; @@ -166,13 +167,14 @@ int sdl_event_filter(void *userdata, SDL_Event *event) return 0; } -void rdp_init(void *_window, GFX_INFO _gfx_info, bool _fullscreen, bool _upscale) +void rdp_init(void *_window, GFX_INFO _gfx_info, bool _upscale, bool _integer_scaling, bool _fullscreen) { window = (SDL_Window *)_window; SDL_AddEventWatch(sdl_event_filter, nullptr); gfx_info = _gfx_info; fullscreen = _fullscreen; + integer_scaling = _integer_scaling; bool window_vsync = 0; wsi = new WSI; wsi_platform = new SDL_WSIPlatform; @@ -234,34 +236,42 @@ void rdp_close() static void calculate_viewport(float *x, float *y, float *width, float *height) { - bool window_widescreen = false; - int32_t display_width = (window_widescreen ? 854 : 640); - int32_t display_height = 480; + const int32_t display_width = 320; + const int32_t display_height = 240; int w, h; SDL_GetWindowSize(window, &w, &h); - *width = w; - *height = h; - *x = 0; - *y = 0; - int32_t hw = display_height * *width; - int32_t wh = display_width * *height; + if (integer_scaling) + { + // Integer scaling path + int scale_x = w / display_width; + int scale_y = h / display_height; + int scale = (scale_x < scale_y) ? scale_x : scale_y; + if (scale < 1) + scale = 1; - // add letterboxes or pillarboxes if the window has a different aspect ratio - // than the current display mode - if (hw > wh) - { - int32_t w_max = wh / display_height; - *x += (*width - w_max) / 2; - *width = w_max; + // Calculate scaled dimensions + int scaled_width = display_width * scale; + int scaled_height = display_height * scale; + + *width = scaled_width; + *height = scaled_height; } - else if (hw < wh) + else { - int32_t h_max = hw / display_width; - *y += (*height - h_max) / 2; - *height = h_max; + // Regular scaling path - maintain aspect ratio + float scale_x = w / (float)display_width; + float scale_y = h / (float)display_height; + float scale = (scale_x < scale_y) ? scale_x : scale_y; + + *width = display_width * scale; + *height = display_height * scale; } + + // Center the viewport + *x = (w - *width) / 2.0f; + *y = (h - *height) / 2.0f; } static void render_frame(Vulkan::Device &device) diff --git a/parallel-rdp/interface.hpp b/parallel-rdp/interface.hpp index 1f7b101f..67075e8d 100644 --- a/parallel-rdp/interface.hpp +++ b/parallel-rdp/interface.hpp @@ -23,7 +23,7 @@ extern "C" uint32_t *VI_WIDTH_REG; } GFX_INFO; - void rdp_init(void *_window, GFX_INFO _gfx_info, bool _fullscreen, bool _upscale); + void rdp_init(void *_window, GFX_INFO _gfx_info, bool _upscale, bool _integer_scaling, bool _fullscreen); void rdp_close(); void rdp_set_vi_register(uint32_t reg, uint32_t value); bool rdp_update_screen(); diff --git a/src/ui/config.rs b/src/ui/config.rs index a209da47..b54a7e17 100644 --- a/src/ui/config.rs +++ b/src/ui/config.rs @@ -21,6 +21,7 @@ pub struct Input { #[derive(serde::Serialize, serde::Deserialize)] pub struct Video { pub upscale: bool, + pub integer_scaling: bool, pub fullscreen: bool, } #[derive(serde::Serialize, serde::Deserialize)] @@ -48,6 +49,7 @@ impl Config { }, video: Video { upscale: false, + integer_scaling: false, fullscreen: false, }, } diff --git a/src/ui/gui.rs b/src/ui/gui.rs index f6ff47ce..e635f1bc 100644 --- a/src/ui/gui.rs +++ b/src/ui/gui.rs @@ -14,6 +14,7 @@ pub struct GopherEguiApp { input_profiles: Vec, controller_enabled: [bool; 4], upscale: bool, + integer_scaling: bool, fullscreen: bool, emulate_vru: bool, show_vru_dialog: bool, @@ -22,6 +23,16 @@ pub struct GopherEguiApp { vru_word_list: Vec, } +struct SaveConfig { + selected_controller: [i32; 4], + selected_profile: [String; 4], + controller_enabled: [bool; 4], + upscale: bool, + integer_scaling: bool, + fullscreen: bool, + emulate_vru: bool, +} + fn get_input_profiles(game_ui: &ui::Ui) -> Vec { let mut profiles = vec![]; for key in game_ui.config.input.input_profiles.keys() { @@ -85,6 +96,7 @@ impl GopherEguiApp { input_profiles: get_input_profiles(&game_ui), controller_enabled: game_ui.config.input.controller_enabled, upscale: game_ui.config.video.upscale, + integer_scaling: game_ui.config.video.integer_scaling, fullscreen: game_ui.config.video.fullscreen, emulate_vru: game_ui.config.input.emulate_vru, show_vru_dialog: false, @@ -95,17 +107,9 @@ impl GopherEguiApp { } } -fn save_config( - game_ui: &mut ui::Ui, - selected_controller: [i32; 4], - selected_profile: [String; 4], - controller_enabled: [bool; 4], - upscale: bool, - fullscreen: bool, - emulate_vru: bool, -) { +fn save_config(game_ui: &mut ui::Ui, save_config_items: SaveConfig) { let joystick_subsystem = game_ui.joystick_subsystem.as_ref().unwrap(); - for (pos, item) in selected_controller.iter().enumerate() { + for (pos, item) in save_config_items.selected_controller.iter().enumerate() { if *item != -1 { game_ui.config.input.controller_assignment[pos] = Some( joystick_subsystem @@ -118,26 +122,28 @@ fn save_config( } } - game_ui.config.input.input_profile_binding = selected_profile; - game_ui.config.input.controller_enabled = controller_enabled; + game_ui.config.input.input_profile_binding = save_config_items.selected_profile; + game_ui.config.input.controller_enabled = save_config_items.controller_enabled; - game_ui.config.video.fullscreen = fullscreen; - game_ui.config.video.upscale = upscale; - game_ui.config.input.emulate_vru = emulate_vru; + game_ui.config.video.upscale = save_config_items.upscale; + game_ui.config.video.integer_scaling = save_config_items.integer_scaling; + game_ui.config.video.fullscreen = save_config_items.fullscreen; + game_ui.config.input.emulate_vru = save_config_items.emulate_vru; } impl Drop for GopherEguiApp { fn drop(&mut self) { let mut game_ui = ui::Ui::new(self.config_dir.clone()); - save_config( - &mut game_ui, - self.selected_controller, - self.selected_profile.clone(), - self.controller_enabled, - self.upscale, - self.fullscreen, - self.emulate_vru, - ); + let save_config_items = SaveConfig { + selected_controller: self.selected_controller, + selected_profile: self.selected_profile.clone(), + controller_enabled: self.controller_enabled, + upscale: self.upscale, + integer_scaling: self.integer_scaling, + fullscreen: self.fullscreen, + emulate_vru: self.emulate_vru, + }; + save_config(&mut game_ui, save_config_items); } } @@ -186,6 +192,7 @@ impl eframe::App for GopherEguiApp { let selected_profile = self.selected_profile.clone(); let controller_enabled = self.controller_enabled; let upscale = self.upscale; + let integer_scaling = self.integer_scaling; let fullscreen = self.fullscreen; let emulate_vru = self.emulate_vru; let config_dir = self.config_dir.clone(); @@ -221,15 +228,18 @@ impl eframe::App for GopherEguiApp { panic!("could not create running file: {}", result.err().unwrap()) } let mut device = device::Device::new(config_dir); - save_config( - &mut device.ui, + + let save_config_items = SaveConfig { selected_controller, selected_profile, controller_enabled, upscale, + integer_scaling, fullscreen, emulate_vru, - ); + }; + save_config(&mut device.ui, save_config_items); + if emulate_vru { device.vru.window_notifier = Some(vru_window_notifier); device.vru.word_receiver = Some(vru_word_receiver); @@ -306,7 +316,9 @@ impl eframe::App for GopherEguiApp { }); ui.add_space(32.0); ui.checkbox(&mut self.upscale, "High-Res Graphics"); + ui.checkbox(&mut self.integer_scaling, "Integer Scaling"); ui.checkbox(&mut self.fullscreen, "Fullscreen (Esc closes game)"); + ui.add_space(32.0); ui.checkbox( &mut self.emulate_vru, "Emulate VRU (connects VRU to controller port 4)", diff --git a/src/ui/video.rs b/src/ui/video.rs index 2d28e972..43cc824b 100644 --- a/src/ui/video.rs +++ b/src/ui/video.rs @@ -38,8 +38,9 @@ pub fn init(device: &mut device::Device, fullscreen: bool) { rdp_init( device.ui.window.as_ref().unwrap().raw() as *mut std::ffi::c_void, gfx_info, - fullscreen, device.ui.config.video.upscale, + device.ui.config.video.integer_scaling, + fullscreen, ) } }