changeset 2644:c5c9498ff279

Implement integer scaling
author Michael Pavone <pavone@retrodev.com>
date Fri, 28 Feb 2025 22:40:18 -0800
parents 57345f6e18f3
children 620f30af9fdc
files default.cfg nuklear_ui/blastem_nuklear.c render_sdl.c
diffstat 3 files changed, 39 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- a/default.cfg	Wed Feb 26 23:43:58 2025 -0800
+++ b/default.cfg	Fri Feb 28 22:40:18 2025 -0800
@@ -307,6 +307,8 @@
 	scanlines off
 	vsync off
 	fullscreen off
+	#forces an integer ratio between the emulated height and the height on screen
+	integer_scaling off
 	#setting gl to off, will force use of the SDL2 fallback renderer
 	#this is useful for those running on machines with Open GL 2.0 unavailable
 	#so the warning doesn't display on startup
--- a/nuklear_ui/blastem_nuklear.c	Wed Feb 26 23:43:58 2025 -0800
+++ b/nuklear_ui/blastem_nuklear.c	Fri Feb 28 22:40:18 2025 -0800
@@ -2186,6 +2186,7 @@
 		settings_toggle(context, "Fullscreen", "video\0fullscreen\0", 0);
 		settings_toggle(context, "Open GL", "video\0gl\0", 1);
 		settings_toggle(context, "Scanlines", "video\0scanlines\0", 0);
+		settings_toggle(context, "Integer Scaling", "video\0integer_scaling\0", 0);
 		selected_vsync = settings_dropdown_ex(context, "VSync", vsync_opts, vsync_opt_names, num_vsync_opts, selected_vsync, "video\0vsync\0");
 		settings_int_input(context, "Windowed Width", "video\0width\0", "640");
 		nk_label(context, "Shader", NK_TEXT_LEFT);
--- a/render_sdl.c	Wed Feb 26 23:43:58 2025 -0800
+++ b/render_sdl.c	Fri Feb 28 22:40:18 2025 -0800
@@ -620,25 +620,52 @@
 	main_clip.h = main_height;
 	main_clip.x = main_clip.y = 0;
 	if (config_aspect() > 0.0f) {
+		char *integer_scaling_str = tern_find_path_default(config, "video\0integer_scaling\0", (tern_val){.ptrval = "off"}, TVAL_PTR).ptrval;
+		uint8_t integer_scaling = !strcmp(integer_scaling_str, "on");
 		float aspect = (float)main_width / main_height;
-		if (fabs(aspect - config_aspect()) < 0.01f) {
+		if (!integer_scaling && fabs(aspect - config_aspect()) < 0.01f) {
 			//close enough for government work
 			return;
 		}
+		uint32_t height, scale;
+		if (integer_scaling) {
+			height = render_emulated_height();
+			if (aspect >= config_aspect()) {
+				scale = main_height / height;
+			} else {
+				uint32_t aspect_height = 0.5f + (float)main_width / config_aspect();
+				scale = aspect_height / height;
+			}
+		}
 #ifndef DISABLE_OPENGL
 		if (render_gl) {
-			for (int i = 0; i < 4; i++)
-			{
-				if (aspect > config_aspect()) {
-					vertex_data[i*2] *= config_aspect()/aspect;
-				} else {
-					vertex_data[i*2+1] *= aspect/config_aspect();
+			if (integer_scaling) {
+				float vscale = ((float)(scale * height)) / (float)main_height;
+				float hscale = (config_aspect() * (float)(scale * height)) / (float)main_width;
+				for (int i = 0; i < 4; i++)
+				{
+					vertex_data[i*2] *= hscale;
+					vertex_data[i*2+1] *= vscale;
+				}
+			} else {
+				for (int i = 0; i < 4; i++)
+				{
+					if (aspect > config_aspect()) {
+						vertex_data[i*2] *= config_aspect()/aspect;
+					} else {
+						vertex_data[i*2+1] *= aspect/config_aspect();
+					}
 				}
 			}
 		} else {
 #endif
-			main_clip.w = aspect > config_aspect() ? config_aspect() * (float)main_height : main_width;
-			main_clip.h = aspect > config_aspect() ? main_height : main_width / config_aspect();
+			if (integer_scaling) {
+				main_clip.h = height * scale;
+				main_clip.w = main_clip.h * config_aspect();
+			} else {
+				main_clip.w = aspect > config_aspect() ? config_aspect() * (float)main_height : main_width;
+				main_clip.h = aspect > config_aspect() ? main_height : main_width / config_aspect();
+			}
 			main_clip.x = (main_width  - main_clip.w) / 2;
 			main_clip.y = (main_height - main_clip.h) / 2;
 #ifndef DISABLE_OPENGL