Skip to content

Conversation

@KDOXG
Copy link

@KDOXG KDOXG commented May 21, 2025

Objective

Adjust how the window works in hybrid screen layout to allow larger screen sizes for the main screen by creating a "Hybrid ratio" setting menu by extending the "Screen gap" setting, and to always display at a pixel-perfect integer scale when the "Force integer scaling" option, located in the "Screen sizing" menu, is enabled.

Disclaimer

I will refer to the DS top screen as screen 1, the DS bottom screen as screen 2, and the larger screen in hybrid layout as the main screen. This naming convention is used consistently throughout this explanation.
I will not cover behavior when "Force integer scaling" is disabled. I also will not consider a possible future implementation of flipped hybrid layout, as discussed in PR #1705; whoever implements that should simply mirror how the current hybrid layout works.

As reference, I reviewed how other emulators handle hybrid layout configurations. The libretro port of melonDS, melonDS DS, has a similar setting, but its screen gap only works in vertical mode. Since standalone melonDS offers more flexible hybrid layout options, I won't base this proposal on melonDS DS implementation — although it would be great to bring this to that version as well in the future.

Similarly, Bizhawk’s melonDS core has flexibility comparable to standalone melonDS, but for some reason its screen gap setting distorts the main screen, producing uneven pixels even at what should be a pixel-perfect aspect ratio. I’m not sure why, but since the Bizhawk core doesn’t run well on my machine (at least in the official release build), I’ve chosen to disregard it for now.

Lastly, some feature requests suggest increasing the hybrid layout screen ratio without using screen gaps, centering the smaller screens beside the main screen. That would require additional frontend positioning changes, and is outside the scope of this proposal. However, this PR is a step toward enabling that functionality in the future.

Problem

Currently, hybrid layout defaults to a 2:1 ratio, where the main screen is twice the size of screens 1 and 2. These two smaller screens are positioned to the right of the main screen in vertical layout.

However, melonDS uses a unified window system. So, a 1x hybrid layout window is treated as a single 768×384 surface — equivalent to a 3:2 ratio in DS screen units.

When the "Screen gap" setting is increased, a gap is introduced between screens 1 and 2, and the main screen is scaled to align:

  • its top edge with the top edge of screen 1, and
  • its bottom edge with the bottom edge of screen 2,
    while preserving its 4:3 aspect ratio.

This causes the overall screen height to grow by the gap value. Because of the unified window system, this also increases the width, stretching the main screen and breaking integer scaling.

When "Force integer scaling" is enabled, screens 1 and 2 correctly retain integer scaling. However, the main screen is scaled according to the fixed 4:3 aspect ratio and the screen gap, which causes it to render at non-integer scale values in the current implementation — even with integer scaling enabled.

Solution

I propose removing the influence of the screen gap setting while in hybrid layout and adding a hybrid ratio setting. This new configuration would appear as a selectable list of screen ratios and can be implemented by cloning the existing "Screen gap" setting, while internally mapping each option to a predefined gap value based on DS screen units (192 pixels tall at 1x).

Specifically:

  • Values ≥192 allow ratios between 3:1 and (2 + screen gap / 192):1
  • Values <192 allow ratios like (2x + 1):x (e.g., 5:2, 7:3)

Proposed ratio options:

Ratio Screen gap Final resolution
2:1 0 768x384
3:1 192 1024x576
4:1 384 1280x768
5:1 576 1536x960
6:1 768 1792x1152
7:1 960 2048x1344
5:2 96 1792x960
7:3 64 2560x1344
9:4 48 3328x1728

You can test these options right now in the current build. After running the emulator once, open your melonDS.toml file (located in the exe folder) and manually set the ScreenGap value under the [Instance.Window] section. The value will be used regardless of what is displayed in the UI.

Since it's just a modification in the front end, I’ve only edited the code related to the emulator window. The emulator now includes a new menu under View → Hybrid ratio, directly below the Screen gap menu. As mentioned earlier, these values override the Screen gap setting only when the Screen layout is set to Hybrid.

Note: Due to hardware limitations (I only have a 1080p display), I could not fully test the 6:1, 7:1, 7:3, and 9:4 options on my system.

@crashGG
Copy link

crashGG commented May 21, 2025

Could add a custom mode for screen layout? Sometimes users want to display dual screen content side by side, but want the main screen to be as large as possible while maintaining integer scaling, and the secondary screen to use the remaining space while also maintaining integer scaling?

An example from Azahar:
1

In this way, the main screen can be set to 2816x2112 resolution (11x integer scaling), and the secondary screen can be set to 1024x768 (4x integer scaling)

@KDOXG
Copy link
Author

KDOXG commented May 21, 2025

Could add a custom mode for screen layout? Sometimes users want to display dual screen content side by side, but want the main screen to be as large as possible while maintaining integer scaling, and the secondary screen to use the remaining space while also maintaining integer scaling?

An example from Azahar: 1

In this way, the main screen can be set to 2816x2112 resolution (11x integer scaling), and the secondary screen can be set to 1024x768 (4x integer scaling)

To do that, the user would need to set a value through the interface, and with that, the system would need to first apply a scale factor to the main screen, then use the remaining space to calculate and apply a different scale to the smaller screens. Directly setting scale factors for the screen is outside the scope of changes I made, as my focus was specifically on adjusting screen ratios. That said, it’s definitely an idea worth exploring in the future, but considering the current state of the interface, I'm not sure how to design where to put these scale factor values for the user to set. Perhaps an option in the same menu as the hybrid ratios, and then rename it to "Hybrid options".

@KDOXG
Copy link
Author

KDOXG commented May 28, 2025

I actually skipped explaining how the screen gap value influences the hybrid view screen ratio, so since there as a comment here about tweaks regarding a ratio for 4K displays, I’ll take the opportunity to clarify that now. That said, keep in mind that this approach is just an easy solution that reuses an existing feature with a new presentation — it’s not that flexible when it comes to customizing even further the screen scaling. Further tweaking requires modifying other parts of melonDS, mainly regarding how the screen alignment works in hybrid layout. I highly recommend going over these kind of solutions instead of tweaking on this, my objective on this PR was to keep it as simple as possible.


Mathematical explanation

The gap calculation for full integer scaling only works with values of the domain I've defined on the PR text, which are the values based in 192, the height of a single DS screen at 1x. In other words, only the multiples and divisors of 192. The reason for that is noticeable when you check a 1x window size after setting the screen gap: it introduces the gap of the size from input between the smaller screens, and then scales the main screen to fit the borders in a 4:3 ratio, as I've explained on the Problem section. Every scale from now on relies on what is done for the final window size we want as a result.

To demonstrate that, lets take for example 7:3, which is the hybrid ratio that has a supported screen gap on the menu of the latest stable build, a screen gap of 64 px.

Calculation:

  • Total Height:
    192 (screen 1) + 192 (screen 2) + 64 (gap) = 448px
  • Main screen width (to preserve 4:3 aspect ratio):
    448 * (4 / 3) ≈ 597.3 → melonDS rounds to 598px
  • Add the main screen width with the smaller screen width (1x):
    598 + 256 = 854px

This is exactly what happens in the latest stable build when you select a 64px screen gap and switch to hybrid mode with a window size of 1x. But that's not integer-scaled, so we have to do another step.

Ensuring Integer Scaling

To achieve proper integer scaling, the screen gap itself must also scale proportionally. The final size of the gap must be an multiple of 192 — exactly enough to fit at least an entire 1x DS screen between the smaller screens without any gap. Continuing the 7:3 example:

  • At 3x scale:
    • Each DS screen = 192 * 3 = 576px (3x DS screen height)
    • Gap = 64 * 3 = 192px (1x DS screen height)
    • Total height = 576 * 2 + 192 = 1344px (7x DS screen height)
  • With the total height, we just calculate the width of the main screen:
    • 1344 * (4 / 3) = 1792 (7x DS screen width)
  • And now we add the width of the smaller screens with the width of the main screen to get the total width:
    • Both DS screens = 256 * 3 = 768 (3x DS screen width)
    • Total width = 1792 + 768 = 2560

With this, the main screen is scaled while maintaining a 4:3 ratio to match a height of 1344px, giving us a size of 1792x1344 and resulting in a 7:3 hybrid ratio with a final window size of 2560x1344. All the screen ratios I proposed in the PR were calculated this way.

@crashGG
Copy link

crashGG commented Jun 8, 2025

After testing it for a while, I found this feature to be great. Could you port the ratio to 2-screen-emphasize? Currently, if use 2-screen-emphasize, the ratio of the two windows cannot be controlled.

@KDOXG
Copy link
Author

KDOXG commented Jun 11, 2025

After testing it for a while, I found this feature to be great. Could you port the ratio to 2-screen-emphasize? Currently, if use 2-screen-emphasize, the ratio of the two windows cannot be controlled.

Is 2-screen-emphasize supposed to be a branch / PR or an actual feature for current melonDS? I searched everywhere and couldn't find anything by that name, but I'm willing to port this implementation if it can help spreading the functionality as a whole.

@crashGG
Copy link

crashGG commented Jun 11, 2025

After testing it for a while, I found this feature to be great. Could you port the ratio to 2-screen-emphasize? Currently, if use 2-screen-emphasize, the ratio of the two windows cannot be controlled.

Is 2-screen-emphasize supposed to be a branch / PR or an actual feature for current melonDS? I searched everywhere and couldn't find anything by that name, but I'm willing to port this implementation if it can help spreading the functionality as a whole.

2-screen-emphasize,it is not a feature, but an effect. It is actually a combination of two feature.
Firt use Screen layout - horizontal / virtical ,now you have 2 screens (horizontally/vertically depending on the your physical monitor).
Second ,use Screen sizing - emphasize top/bottom (top/bottom which screen you want to be the primary screen ).
The final effect looks like this:
2025-06-11_130251
I personally think this is the most comfortable way to play on modern computers.

@KDOXG
Copy link
Author

KDOXG commented Jun 11, 2025

After testing it for a while, I found this feature to be great. Could you port the ratio to 2-screen-emphasize? Currently, if use 2-screen-emphasize, the ratio of the two windows cannot be controlled.

Is 2-screen-emphasize supposed to be a branch / PR or an actual feature for current melonDS? I searched everywhere and couldn't find anything by that name, but I'm willing to port this implementation if it can help spreading the functionality as a whole.

2-screen-emphasize,it is not a feature, but an effect. It is actually a combination of two feature. Firt use Screen layout - horizontal / virtical ,now you have 2 screens (horizontally/vertically depending on the your physical monitor). Second ,use Screen sizing - emphasize top/bottom (top/bottom which screen you want to be the primary screen ). The final effect looks like this: 2025-06-11_130251 I personally think this is the most comfortable way to play on modern computers.

Oh, understood! That would be great to have a ratio list as well. Analyzing here, the difference is that now there are only 2 screens, instead of having a third that acts like a clone, and the gap is added between the main screen (the emphasized one) and the remaining screen. I think I can tweak the math to work here as well, though first I need to understand the scaling behaviour occurring on Emphasize layout mode with integer scaling on. Give me some time and I'll reply here with what I can discover.

@KDOXG
Copy link
Author

KDOXG commented Jun 12, 2025

After testing it for a while, I found this feature to be great. Could you port the ratio to 2-screen-emphasize? Currently, if use 2-screen-emphasize, the ratio of the two windows cannot be controlled.

Is 2-screen-emphasize supposed to be a branch / PR or an actual feature for current melonDS? I searched everywhere and couldn't find anything by that name, but I'm willing to port this implementation if it can help spreading the functionality as a whole.

2-screen-emphasize,it is not a feature, but an effect. It is actually a combination of two feature. Firt use Screen layout - horizontal / virtical ,now you have 2 screens (horizontally/vertically depending on the your physical monitor). Second ,use Screen sizing - emphasize top/bottom (top/bottom which screen you want to be the primary screen ). The final effect looks like this: 2025-06-11_130251 I personally think this is the most comfortable way to play on modern computers.

Oh, understood! That would be great to have a ratio list as well. Analyzing here, the difference is that now there are only 2 screens, instead of having a third that acts like a clone, and the gap is added between the main screen (the emphasized one) and the remaining screen. I think I can tweak the math to work here as well, though first I need to understand the scaling behaviour occurring on Emphasize layout mode with integer scaling on. Give me some time and I'll reply here with what I can discover.

It's done, here is what I discovered.

Notes:

  • With integer scale enabled, both the main and secondary screens are always guaranteed to be using integer scaling. Unlike what's done for the hybrid ratio solution, the tweaks for this feature related to the screen gap are only aimed at allowing the user to choose different scaling options for the screens.
  • In emphasize mode, the priority is to keep the main screen as large as possible. As the screen gap increases, if the screens begin to touch the edges of the window, the secondary screen decreases its scale. If the screen gap increases further and the screens are still touching the edges but the secondary screen is already at 1x scale, then the main screen begins to reduce its scale.
  • The screen gap is also scaled along with the screens: half of it's value is scaled using the main screen's scale, and the other half with the secondary screen's scale. The final screen gap displayed in the window is the sum of those two scaled values. As such, this final screen gap can also be determined by the window resolution and the screen orientation. Given the behavior described above for emphasize mode, it's possible to determine a screen gap that achieves the desired scale for the screens.

Conclusions:

  • A screen gap of 0 already guarantees that both screens will be displayed at the largest possible size. Any change from that will only reduce the scale of at least one of the screens.
  • Because the main screen tends to retain the highest possible scale, and since the final screen gap is also defined by the window resolution, it's not possible to have a global configuration that accommodates a list of ratios for this 2-screen-emphasize mode. Such a list would not work for all window resolutions.

I can think of a few possible solutions that don’t involve creating a global configuration — like having ratio lists with options based on the most common window resolutions — but personally, I don't find the option of reducing scale very appealing, especially since integer scale is already achieved with the mode enabled. As for the example shown in the screenshot, setting a screen gap that reaches a comfortable spacing seems like a highly subjective preference — very different from ensuring integer scale, which is objective: either it is or it isn't.

I think the only interesting solution I can think of would be to have a toggleable option that makes the width of the black area between the screens (i.e., the final screen gap) equal to the width of the black area between each screen and the window edges. To implement this, it would be necessary to modify the layout setup method to ignore the input screen gap value and recalculate it based on the window resolution. This would even allow a degree of control over the screens' scaling behavior by resizing the window during runtime. However, the comfort of using this feature would still be subjective. I think more user feedback would be needed to validate adding such an option.

As for myself, personally, I'd prefer something different. Specifically, I’d like an option for 2-screen-emphasize mode (or even hybrid!) that would center the main screen completely in the window — similar to top/bottom screen only mode — but with the secondary screen still appearing somewhere on the side. This would differ from the current default approach, where melonDS centers the union of both screens (plus the screen gap), leaving each screen slightly off-center. Targeting widescreen windows, the way I see, this solution would work very nice. However, implementing it would require deeper changes to the layout setup method, specifically changing how screen position offsets are calculated. I’m not planning to touch those calculations at the moment.

All these ideas are very cool to explore, and I really enjoy the effort to find better ways to present the DS screens on a single screen. Do you happen to know anyone currently researching layouts for DS and 3DS screens (or even Wii U, assuming there are efforts to reproduce the gamepad screen) so we could use those ideas as reference?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants