schellingb / dosbox-pure

DOSBox Pure is a new fork of DOSBox built for RetroArch/Libretro aiming for simplicity and ease of use.
GNU General Public License v2.0
749 stars 61 forks source link

[Feature request] Automatic double-scan mode for 240p #512

Open HitoriSensei opened 1 month ago

HitoriSensei commented 1 month ago

I'd like to revive the https://github.com/schellingb/dosbox-pure/issues/165 issue.

The issue mentions a solution using Normal2x filter, and it works great, but only if you know that your software uses low-res all the time.

But when the software switches between 480p and 240p the double-scan becomes a quadruple-scan for high-res 😅

One of the possible scenarios, and the one I'm currently using the core for, is to have the Win95 installed and run DOS games from under it (work flawlessly btw!).

Auto double-scan would be the perfect addition to the core, which would allow a painless use of (S)VGA resolutions along with CGA/QVGA resolutions in single run, and it would then behave exactly as a PC connected to 31khz monitor.

alexb3d commented 1 month ago

The way it handles resolutions and video outputs is the right way.

Double scanning is a feature of some 15Khz interlaced TVs, in PC it does not exist because the output is progressive.

If you are looking to emulate the double line effect seen on monitors, you have several shaders that do the job; crt-blurPi.... draws the double line, crt-geom has options to specify the vertical resolution and koko's bezel shaders have a few dedicated to monitors.

image

HitoriSensei commented 1 month ago

Hello @alexb3d :)

Correct me if I'm wrong, but from what I understand, in order to meet the 31khz requirements of VGA monitors, PC must draw double lines for resolutions like 320x200, otherwise the horizontal rate would be way below the 31khz and VGA monitor would not be able to handle that. Again, correct me if I'm wrong, but the line doubling is actually performed by the VGA card.

This is the behaviour I would need to replicate. I know there are shaders that perform double lines per pixel, but the problem with them is that they do it also for VGA resolutions, where line doubling should not occur on real VGA monitors. The other thing is that there are some amazing shaders like royale that has no such option, as they behave like real CRTs, and in order to look like 31khz VGA monitor they need to be provided the "31khz signal", a line-doubled 320x200 in this case, otherwise they behave and look like a 15khz CGA monitor, not a VGA one.

schellingb commented 1 month ago

To be honest I mostly cared about giving the frontend (i.e. RetroArch) the raw pixelbuffer and let it handle any conversion with shaders and aspect ratio correction as desired by the user. Under the hood currently it is quite simple:

I'm aware that this is far from an accurate representation of the original experience of DOS on an analog VGA monitor. So I'm more than open to enhancing the core perhaps with options to modify that. DOSBox's VGA emulation actually reports two more parameters besides the mentioned "pixel aspect ratio" which are called "double width" and "double height". These two parameters are currently unused by DOSBox Pure and it sounds like you would like to have them incorporated instead of the two last steps mentioned above. Do you think that makes sense?

HitoriSensei commented 1 month ago

Hello @schellingb :)

Thank you for explaining in more detail the inner workings. Those two additional parameters are interesting, I wonder when they are set. If they are set when VGA actually would like to do double-scanning, I think this would be a good indicator as to when to enable the doubling of resolution, either only vertically or both horizontally and vertically. I'm also wondering if changing the aspect ratio reported to the frontend would be sufficient in this case. I'm afraid that it would not work as the framebuffer passed to the shaders would still be 320x200, as an effect, there would still be 200 lines rendered instead of 400, and the screen would be squished horizontally (unless 4:3 ratio could be forced by the frontend).

I'm not familiar enough with RetroArch internals, but I thing the pixel buffer would need to be doubled before passing it to the frontend, unless there is a way to inform the frontend to apply it's own 2x filter on the buffer.

In terms of options, I think it would be nice to turn this new behaviour on/off/auto, where auto would mean that this behaviour is enabled for VGA/SVGA cards and for resolutions lower than 640X480. Maybe Dosbox VGA emulation actually implents this logic and sets the aforementioned "double width" and "double height" parameters when needed? 🤔

schellingb commented 1 month ago

So I made the emulator print out some video mode information and ran a bunch of video tests with all kinds of resolutions and I got this:

Mode        VGA -  160 x 240 @ 108.569Hz - Pixel Ratio 0.550 - DoubleWidth DoubleHeight            => 320 x 480
Mode       TEXT -  160 x 240 @ 108.569Hz - Pixel Ratio 0.550 - DoubleWidth DoubleHeight            => 320 x 480
Mode        VGA -  256 x 256 @  57.320Hz - Pixel Ratio 0.981 - DoubleWidth DoubleHeight            => 512 x 512
Mode       TEXT -  256 x 256 @  57.320Hz - Pixel Ratio 0.981 - DoubleWidth DoubleHeight            => 512 x 512
Mode        VGA -  296 x 220 @  59.713Hz - Pixel Ratio 1.000 - DoubleWidth DoubleHeight            => 592 x 440
Mode       TEXT -  296 x 220 @  59.713Hz - Pixel Ratio 1.000 - DoubleWidth DoubleHeight            => 592 x 440
Mode     TANDY2 -  320 x 200 @  59.923Hz - Pixel Ratio 1.200 - DoubleWidth DoubleHeight            => 640 x 400
Mode     TANDY4 -  320 x 200 @  59.923Hz - Pixel Ratio 1.200 - DoubleWidth DoubleHeight            => 640 x 400
Mode    TANDY16 -  320 x 200 @  59.923Hz - Pixel Ratio 1.200 - DoubleWidth DoubleHeight            => 640 x 400
Mode TANDY_TEXT -  320 x 200 @  59.923Hz - Pixel Ratio 1.200 - DoubleWidth DoubleHeight            => 640 x 400
Mode        EGA -  320 x 200 @  59.923Hz - Pixel Ratio 1.200 - DoubleWidth DoubleHeight DoubleScan => 640 x 400
Mode       TEXT -  320 x 200 @  59.923Hz - Pixel Ratio 1.200 - DoubleWidth DoubleHeight DoubleScan => 640 x 400
Mode       CGA4 -  320 x 200 @  59.923Hz - Pixel Ratio 1.200 - DoubleWidth DoubleHeight DoubleScan => 640 x 400
Mode       CGA2 -  320 x 200 @  59.923Hz - Pixel Ratio 1.200 - DoubleWidth DoubleHeight DoubleScan => 640 x 400
Mode      LIN15 -  320 x 200 @  69.755Hz - Pixel Ratio 1.200 - DoubleWidth DoubleHeight DoubleScan => 640 x 400
Mode      LIN16 -  320 x 200 @  69.755Hz - Pixel Ratio 1.200 - DoubleWidth DoubleHeight DoubleScan => 640 x 400
Mode      LIN32 -  320 x 200 @  69.755Hz - Pixel Ratio 1.200 - DoubleWidth DoubleHeight DoubleScan => 640 x 400
Mode       LIN8 -  320 x 200 @  69.755Hz - Pixel Ratio 1.200 - DoubleWidth DoubleHeight DoubleScan => 640 x 400
Mode       LIN8 -  320 x 200 @  70.086Hz - Pixel Ratio 1.200 - DoubleWidth DoubleHeight            => 640 x 400
Mode        VGA -  320 x 200 @  70.086Hz - Pixel Ratio 1.200 - DoubleWidth DoubleHeight            => 640 x 400
Mode       TEXT -  320 x 200 @  70.086Hz - Pixel Ratio 1.200 - DoubleWidth DoubleHeight            => 640 x 400
Mode        EGA -  320 x 200 @  70.086Hz - Pixel Ratio 1.200 - DoubleWidth DoubleHeight            => 640 x 400
Mode       TEXT -  320 x 200 @  70.086Hz - Pixel Ratio 1.200 - DoubleWidth DoubleHeight DoubleScan => 640 x 400
Mode       CGA4 -  320 x 200 @  70.086Hz - Pixel Ratio 1.200 - DoubleWidth DoubleHeight DoubleScan => 640 x 400
Mode        VGA -  320 x 200 @  70.086Hz - Pixel Ratio 1.200 - DoubleWidth DoubleHeight DoubleScan => 640 x 400
Mode        EGA -  320 x 200 @  70.086Hz - Pixel Ratio 1.200 - DoubleWidth DoubleHeight DoubleScan => 640 x 400
Mode       CGA2 -  320 x 200 @  70.086Hz - Pixel Ratio 1.200 - DoubleWidth DoubleHeight DoubleScan => 640 x 400
Mode        VGA -  320 x 240 @  59.713Hz - Pixel Ratio 1.000 - DoubleWidth DoubleHeight            => 640 x 480
Mode       TEXT -  320 x 240 @  59.713Hz - Pixel Ratio 1.000 - DoubleWidth DoubleHeight            => 640 x 480
Mode      LIN32 -  320 x 240 @  70.005Hz - Pixel Ratio 1.000 - DoubleWidth DoubleHeight DoubleScan => 640 x 480
Mode        VGA -  320 x 240 @  70.007Hz - Pixel Ratio 1.000 - DoubleWidth DoubleHeight DoubleScan => 640 x 480
Mode      LIN16 -  320 x 240 @  70.007Hz - Pixel Ratio 1.000 - DoubleWidth DoubleHeight DoubleScan => 640 x 480
Mode       LIN8 -  320 x 240 @  70.007Hz - Pixel Ratio 1.000 - DoubleWidth DoubleHeight DoubleScan => 640 x 480
Mode      LIN15 -  320 x 240 @  70.007Hz - Pixel Ratio 1.000 - DoubleWidth DoubleHeight DoubleScan => 640 x 480
Mode       TEXT -  320 x 350 @  59.067Hz - Pixel Ratio 0.809 - DoubleWidth                         => 640 x 350
Mode        VGA -  320 x 350 @  70.086Hz - Pixel Ratio 1.371 - DoubleWidth                         => 640 x 350
Mode      LIN32 -  320 x 400 @  69.755Hz - Pixel Ratio 1.200 - DoubleWidth                         => 640 x 400
Mode        VGA -  320 x 400 @  69.755Hz - Pixel Ratio 1.200 - DoubleWidth                         => 640 x 400
Mode      LIN16 -  320 x 400 @  69.755Hz - Pixel Ratio 1.200 - DoubleWidth                         => 640 x 400
Mode       LIN8 -  320 x 400 @  69.755Hz - Pixel Ratio 1.200 - DoubleWidth                         => 640 x 400
Mode      LIN15 -  320 x 400 @  69.755Hz - Pixel Ratio 1.200 - DoubleWidth                         => 640 x 400
Mode       TEXT -  320 x 400 @  70.086Hz - Pixel Ratio 1.200 - DoubleWidth                         => 640 x 400
Mode        VGA -  320 x 400 @  70.086Hz - Pixel Ratio 1.200 - DoubleWidth                         => 640 x 400
Mode       TEXT -  320 x 400 @  70.087Hz - Pixel Ratio 1.200 - DoubleWidth                         => 640 x 400
Mode       LIN8 -  320 x 480 @  70.005Hz - Pixel Ratio 1.000 - DoubleWidth                         => 640 x 480
Mode      LIN32 -  320 x 480 @  70.005Hz - Pixel Ratio 1.000 - DoubleWidth                         => 640 x 480
Mode        VGA -  320 x 480 @  70.007Hz - Pixel Ratio 1.000 - DoubleWidth                         => 640 x 480
Mode      LIN15 -  320 x 480 @  70.007Hz - Pixel Ratio 1.000 - DoubleWidth                         => 640 x 480
Mode       LIN8 -  320 x 480 @  70.007Hz - Pixel Ratio 1.000 - DoubleWidth                         => 640 x 480
Mode      LIN16 -  320 x 480 @  70.007Hz - Pixel Ratio 1.000 - DoubleWidth                         => 640 x 480
Mode        VGA -  360 x 200 @  70.399Hz - Pixel Ratio 1.344 - DoubleWidth DoubleHeight            => 720 x 400
Mode       LIN8 -  360 x 200 @  70.399Hz - Pixel Ratio 1.344 - DoubleWidth DoubleHeight            => 720 x 400
Mode        VGA -  360 x 240 @  59.980Hz - Pixel Ratio 1.120 - DoubleWidth DoubleHeight            => 720 x 480
Mode        VGA -  360 x 270 @  56.244Hz - Pixel Ratio 1.046 - DoubleWidth DoubleHeight            => 720 x 540
Mode       TEXT -  360 x 270 @  56.244Hz - Pixel Ratio 1.046 - DoubleWidth DoubleHeight            => 720 x 540
Mode       LIN8 -  360 x 350 @  70.399Hz - Pixel Ratio 1.536 - DoubleWidth                         => 720 x 350
Mode        VGA -  360 x 350 @  70.399Hz - Pixel Ratio 1.536 - DoubleWidth                         => 720 x 350
Mode        VGA -  360 x 360 @  70.399Hz - Pixel Ratio 1.344 - DoubleWidth                         => 720 x 360
Mode       TEXT -  360 x 360 @  70.399Hz - Pixel Ratio 1.344 - DoubleWidth                         => 720 x 360
Mode       LIN8 -  360 x 400 @  70.399Hz - Pixel Ratio 1.344 - DoubleWidth                         => 720 x 400
Mode        VGA -  360 x 400 @  70.399Hz - Pixel Ratio 1.344 - DoubleWidth                         => 720 x 400
Mode       LIN8 -  360 x 480 @  59.980Hz - Pixel Ratio 1.120 - DoubleWidth                         => 720 x 480
Mode        VGA -  360 x 480 @  59.980Hz - Pixel Ratio 1.120 - DoubleWidth                         => 720 x 480
Mode       TEXT -  360 x 480 @  59.980Hz - Pixel Ratio 1.120 - DoubleWidth                         => 720 x 480
Mode       TEXT -  400 x 300 @  91.470Hz - Pixel Ratio 1.889 - DoubleWidth                         => 800 x 300
Mode        VGA -  400 x 300 @  91.470Hz - Pixel Ratio 1.889 - DoubleWidth                         => 800 x 300
Mode     TANDY4 -  640 x 200 @  59.923Hz - Pixel Ratio 1.200 - DoubleHeight                        => 640 x 400
Mode TANDY_TEXT -  640 x 200 @  59.923Hz - Pixel Ratio 1.200 - DoubleHeight                        => 640 x 400
Mode     TANDY2 -  640 x 200 @  59.923Hz - Pixel Ratio 1.200 - DoubleHeight                        => 640 x 400
Mode        EGA -  640 x 200 @  59.923Hz - Pixel Ratio 1.200 - DoubleHeight DoubleScan             => 640 x 400
Mode       TEXT -  640 x 200 @  59.923Hz - Pixel Ratio 1.200 - DoubleHeight DoubleScan             => 640 x 400
Mode       CGA2 -  640 x 200 @  59.923Hz - Pixel Ratio 1.200 - DoubleHeight DoubleScan             => 640 x 400
Mode       TEXT -  640 x 200 @  70.086Hz - Pixel Ratio 1.200 - DoubleHeight DoubleScan             => 640 x 400
Mode        EGA -  640 x 200 @  70.086Hz - Pixel Ratio 1.200 - DoubleHeight DoubleScan             => 640 x 400
Mode       CGA2 -  640 x 200 @  70.086Hz - Pixel Ratio 1.200 - DoubleHeight DoubleScan             => 640 x 400
Mode       TEXT -  640 x 344 @  59.702Hz - Pixel Ratio 0.801
Mode       CGA4 -  640 x 344 @  59.702Hz - Pixel Ratio 0.801
Mode        EGA -  640 x 350 @  49.359Hz - Pixel Ratio 0.835
Mode        EGA -  640 x 350 @  49.816Hz - Pixel Ratio 0.835
Mode       TEXT -  640 x 350 @  49.816Hz - Pixel Ratio 0.835
Mode   HERC_GFX -  640 x 350 @  55.157Hz - Pixel Ratio 1.371
Mode  HERC_TEXT -  640 x 350 @  55.157Hz - Pixel Ratio 1.371
Mode        EGA -  640 x 350 @  59.702Hz - Pixel Ratio 0.801
Mode       CGA4 -  640 x 350 @  59.702Hz - Pixel Ratio 0.801
Mode       TEXT -  640 x 350 @  59.702Hz - Pixel Ratio 0.801
Mode        EGA -  640 x 350 @  70.086Hz - Pixel Ratio 1.371
Mode       TEXT -  640 x 350 @  70.086Hz - Pixel Ratio 1.371
Mode       LIN8 -  640 x 400 @  69.755Hz - Pixel Ratio 1.200
Mode      LIN32 -  640 x 400 @  69.755Hz - Pixel Ratio 1.200
Mode       TEXT -  640 x 400 @  69.755Hz - Pixel Ratio 1.200
Mode      LIN16 -  640 x 400 @  69.756Hz - Pixel Ratio 1.200
Mode      LIN32 -  640 x 400 @  69.756Hz - Pixel Ratio 1.200
Mode      LIN15 -  640 x 400 @  69.756Hz - Pixel Ratio 1.200
Mode       TEXT -  640 x 400 @  70.087Hz - Pixel Ratio 1.200
Mode       LIN8 -  640 x 400 @  70.087Hz - Pixel Ratio 1.200
Mode        EGA -  640 x 400 @  70.087Hz - Pixel Ratio 1.200
Mode       CGA2 -  640 x 400 @  70.087Hz - Pixel Ratio 1.200
Mode       LIN4 -  640 x 400 @  70.087Hz - Pixel Ratio 1.200
Mode       CGA4 -  640 x 400 @  70.087Hz - Pixel Ratio 1.200
Mode        VGA -  640 x 400 @  70.087Hz - Pixel Ratio 1.200
Mode        EGA -  640 x 480 @  59.940Hz - Pixel Ratio 1.000
Mode       TEXT -  640 x 480 @  59.940Hz - Pixel Ratio 1.000
Mode        VGA -  640 x 480 @  59.940Hz - Pixel Ratio 1.000
Mode       LIN4 -  640 x 480 @  59.940Hz - Pixel Ratio 1.000
Mode      LIN15 -  640 x 480 @  70.007Hz - Pixel Ratio 1.000
Mode       LIN8 -  640 x 480 @  70.007Hz - Pixel Ratio 1.000
Mode       LIN4 -  640 x 480 @  70.007Hz - Pixel Ratio 1.000
Mode       TEXT -  640 x 480 @  70.007Hz - Pixel Ratio 1.000
Mode      LIN32 -  640 x 480 @  70.007Hz - Pixel Ratio 1.000
Mode      LIN16 -  640 x 480 @  70.007Hz - Pixel Ratio 1.000
Mode  HERC_TEXT -  720 x 348 @  50.050Hz - Pixel Ratio 1.552
Mode   HERC_GFX -  720 x 348 @  50.050Hz - Pixel Ratio 1.552
Mode       TEXT -  800 x 600 @  70.168Hz - Pixel Ratio 1.000
Mode       LIN4 -  800 x 600 @  70.168Hz - Pixel Ratio 1.000
Mode      LIN16 -  800 x 600 @  70.168Hz - Pixel Ratio 1.000
Mode       LIN8 -  800 x 600 @  70.168Hz - Pixel Ratio 1.000
Mode      LIN32 -  800 x 600 @  70.168Hz - Pixel Ratio 1.000
Mode      LIN15 -  800 x 600 @  70.168Hz - Pixel Ratio 1.000
Mode      LIN32 -  848 x 480 @  69.944Hz - Pixel Ratio 1.000
Mode       TEXT -  848 x 480 @  69.944Hz - Pixel Ratio 1.000
Mode       LIN8 -  848 x 480 @  69.944Hz - Pixel Ratio 1.000
Mode      LIN15 -  848 x 480 @  69.944Hz - Pixel Ratio 1.000
Mode      LIN15 -  848 x 480 @  69.945Hz - Pixel Ratio 1.000
Mode      LIN16 -  848 x 480 @  69.945Hz - Pixel Ratio 1.000
Mode      LIN32 -  848 x 480 @  69.945Hz - Pixel Ratio 1.000
Mode        VGA - 1024 x 768 @  70.052Hz - Pixel Ratio 1.000
Mode      LIN15 - 1024 x 768 @  70.052Hz - Pixel Ratio 1.000
Mode      LIN16 - 1024 x 768 @  70.052Hz - Pixel Ratio 1.000
Mode       TEXT - 1024 x 768 @  70.052Hz - Pixel Ratio 1.000
Mode       LIN4 - 1024 x 768 @  70.052Hz - Pixel Ratio 1.000
Mode       LIN8 - 1024 x 768 @  70.052Hz - Pixel Ratio 1.000
Mode       TEXT - 1056 x 344 @  70.067Hz - Pixel Ratio 1.920
Mode       TEXT - 1056 x 400 @  70.067Hz - Pixel Ratio 1.920
Mode       TEXT - 1056 x 480 @  69.968Hz - Pixel Ratio 1.000
Mode      LIN15 - 1056 x 480 @  69.968Hz - Pixel Ratio 1.000
Mode      LIN16 - 1152 x 864 @  70.019Hz - Pixel Ratio 1.000
Mode       LIN8 - 1152 x 864 @  70.019Hz - Pixel Ratio 1.000
Mode      LIN15 - 1152 x 864 @  70.019Hz - Pixel Ratio 1.000
Mode      LIN32 - 1152 x 864 @  70.019Hz - Pixel Ratio 1.000
Mode       LIN4 - 1280 x1024 @  69.955Hz - Pixel Ratio 1.000
Mode       TEXT - 1280 x1024 @  69.955Hz - Pixel Ratio 1.000
Mode       LIN8 - 1280 x1024 @  69.955Hz - Pixel Ratio 1.000

So DOSBox's graphics emulation has 3 flags which I think are unused in DOSBox Pure. DoubleWidth, DoubleHeight and DoubleScan. Anything above 640 x 344 never has any of these flags set. The table above has => which lists theoretically at what resolution we would end up if we just apply a factor of 2 to width and/or height according to DoubleWidth and DoubleHeight. Some of the resolutions are a bit weird to me like 320 x 480 or 800 x 300.

schellingb commented 1 month ago

Maybe we can just keep the core options we have but change what the "Aspect Ratio Correction" option affects?

alexb3d commented 1 month ago

I'm no expert, I've been doing a lot of research on PC video. We have come a long way with the CGA. I intend to create some shaders to represent the monitors correctly, although I don't know how to make a shader, but that doesn't concern me now. lol

Yes, the video adapter doubles the resolution, this effect is known as "pixel-doubling and line-doubling". But the scan lines are created by the cathode ray tube.

When adjusted to 4:3 the 640x400 resolution stays at 534x400, and when stretched it fills the whole screen, no black stripes, the only gaming resolution (that I know of) that leaves stripes is the high resolution 640x350 mode. But this can have a problem on a flat screen, the pixels get distorted.

VGA does not produce visible scanlines at 640x480, but at 640x400 it does, and it does not leave black fringes either because the monitors are dual/multisync and fill the entire screen.

Duplicating the 320x200 resolution in the emulator may increase resource consumption. If you want to see scanlines with shaders, it is better to have shaders with this option.

Two of the things you ask for already exist.

There is already an option with duplicated output at 400. In the core options, the VGA adapter supports duplex output and also supports native 640x400 VGA output. This seems to be the only reason for this option to exist.

In these modes the horizontal resolution 320 is equal to 640, that's why the captures with this card are 320x400. This is what we were talking about in the other post. @schellingb

The shader can emulate 31Khz. If the VGA adapter is enabled and the shader has the option to disable interlace, you will see the double lines as on a real monitor.

This is the shader geo, I didn't have much luck with the royal. image

HitoriSensei commented 1 month ago

@schellingb I've been looking at the Dosbox output parameters list and your proposal, and I'm wondering if we could just:

If "aspect correction" is on:

If "aspect correction" is off - follow the current logic:

Would it make sense?

HitoriSensei commented 1 month ago

One more thing I'm wondering about, is the Dosbox reported Pixel ratio.

I'm wondering if in aspect correction: on, instead of constant 4:3 we should report (FB.w / (FB.h * pixel_ratio)) (where FB is the frame buffer AFTER doubling).

Most of the time, it would result in 4:3, but in certain more exotic modes, the ratio would be different. I believe this is why the pixel_ratio parameter exists at all.

HitoriSensei commented 1 month ago

@alexb3d thanks for the elaborate entry :)

Yes, the video adapter doubles the resolution, this effect is known as "pixel-doubling and line-doubling". But the scan lines are created by the cathode ray tube.

That's right, I've incorrectly used "double scan" for line-doubling.

Duplicating the 320x200 resolution in the emulator may increase resource consumption. If you want to see scanlines with shaders, it is better to have shaders with this option.

I agree, the shader-only solution would be ideal. Although currently there are two important issues with that:

Two of the things you ask for already exist.

There is already an option with duplicated output at 400. In the core options, the VGA adapter supports duplex output and also supports native 640x400 VGA output. This seems to be the only reason for this option to exist.

In these modes the horizontal resolution 320 is equal to 640, that's why the captures with this card are 320x400. This is what we were talking about in the other post.

Do you mean that if I choose the VGA adapter instead of SVGA adapter in the video options, the frame buffer will already be line/pixel doubled when needed, according to the aforementioned Dosbox video modes list?

alexb3d commented 1 month ago

I just gave you three and there are about 10. All IBM-PC monitors produce double lines.

The core emulates the hardware, retroarch the inputs and outputs, and the shaders emulate the visual appearance of a CRT.

You can use real CRT monitors with native resolutions, activating CRT-SwitchRes with output at 15 and 31Khz, I was using it for a long time and it is a marvel with PURE.

On flat screens, single or double scanlines, progressive or interlaced, are simulated with shaders. Shaders are very flexible, you can add "Prepend/Append Preset" to any shader and duplicate the image or add a double line.

Yes, as I just told you, the VGA adapter produces pixel-doubling and line-doubling output and supports native 640x400.

schellingb commented 3 weeks ago

Commit 4c5cb55 now implements a change on what the core does when "Aspect Ratio Correction" is enabled:

@HitoriSensei @alexb3d I'd really like your feedback so I'm attaching a Win64 build to this post (dosbox_pure_libretro_win64_dll_git_4c5cb55.zip). If you use another system please tell me and I can look into providing a build (unless you're able to compile the core yourself). For now there's no new core option to control this. We could add a third option to the core option to enable or disable the doubling because, as alexb3d mentioned, it does introduce a slightly heavy processing step. Quake 1 timedemo at 360x240 (doubled up to 720x480) does go down from 143.2 FPS to 141.3 FPS for me when using the new aspect ratio correction.

HitoriSensei commented 3 weeks ago

That is awesome @schellingb 🔥 I'll try it today.

In order to minimize impact done by doubling, we could try to explicitly use SIMD extensions to improve the performance (unless the compiler is clever enough to infer our intent and apply optimizations automatically). I've attached the snippet in https://github.com/schellingb/dosbox-pure/commit/4c5cb553a32c8c7d3ff8e73ce25055295aa15d45#r145382233

schellingb commented 3 weeks ago

I started out with something more optimal but ended up realizing that there is the "Overscan Border Size" which can add a variable pixel sized border around the framebuffer so the top left pixel that wants to be doubled might not align with what SSE etc. would want. But maybe we can enforce the overscan to be at least an even number of pixels wide so we should stay aligned. But it would make sense to benchmark it first how much we're gaining or not by just testing it out without overscan.

HitoriSensei commented 3 weeks ago

Seems to work like a charm!

I've tried playing DOS games on Win98:

Both VGA and SVGA adapters seems to work properly:

I've also tried running 3dfx games, as I've seem that the 3dfx-related code was modified. They also seems to be working fine.

alexb3d commented 3 weeks ago

I use Ubuntu Linux, I have never compiled a core, but I could try, do you have any guide at hand?

If the VGA adapter already exists, what is this option useful for? If it is to select the double scanline automatically it is fine but it can have a disadvantage if it is the other way round...

In a previous comment I said that all monitors produce double lines. I did not express myself well. Sorry for the confusion.

The VGA monitor/adapter when playing an EGA, CGA, etc. game produces double lines (or if the content is x400 VGA native). For backward compatibility it duplicates anything under 240.

An EGA/CGA... game set on an EGA/CGA... adapter produces single lines. This video is referenced.

Captura de pantalla de 2024-08-16 01-48-48

So, if I want to run an EGA, (or any adapter), game in its original format (with single lines) and with the screen at 4:3, are the lines duplicated?

I noticed that the VGA adapter, by doubling (only) the vertical resolution) also increases the load of the emulator. I've been curious about some shader, you can tell it to draw double lines and it doesn't influence the performance.

HitoriSensei commented 3 weeks ago

If the VGA adapter already exists, what is this option useful for?

This option is useful for SVGA adapter, which doesn't perform doubling internally as VGA does, but in my opinion, it should, as SVGA graphics adapters did this on real hardware when connected to a VGA/SVGA monitor (to keep the minimum supported horizontal refresh rate)

I noticed that the VGA adapter, by doubling (only) the vertical resolution) also increases the load of the emulator. I've been curious about some shader, you can tell it to draw double lines and it doesn't influence the performance.

That would be the perfect solution, but it would require long term close cooperation between Dosbox authors, RetroArch core api and RetroArch shader pipeline API in order to pass the runtime "double h/v" flag from dosbox up to the shader. It could be the topic worth opening in RetroArch repo to support that, but due to very limited use (only dosbox would require that) I doubt there would be many people interested in implementing it in RA and all the CRT shaders.

HitoriSensei commented 3 weeks ago

Given the above, I believe the new functionality should actually be under a new option, as it is related to how the content will actually be displayed and is related to how VGA monitors were treated in a day. Maybe the option should be called "Output VGA compatible framebuffer" or "Pre-scale to VGA"? And should be available only for VGA and SVGA adapters, as EGA and CGA should always output without doubling, as that never happened in real life.

What do you think @schellingb ?

alexb3d commented 3 weeks ago

but it would require long term close cooperation between Dosbox authors, RetroArch core api and RetroArch shader pipeline API in order to pass the runtime "double h/v" flag from dosbox up to the shader

OMG! not to be so exaggerated. LOL
Talks are already underway and several things are going to be done.

but in my opinion, it should, as SVGA graphics adapters did this on real hardware when connected to a VGA/SVGA monitor

You hit the nail right on the head. SVGA should not do this. Duplicating lines is a unique feature of VGA.

VGA: 320×200 in 4 or 16 colors (CGA/EGA compatibility) 320×200 in 256 colors (Mode 13h) 640×200 and 640×350 in 16 colors or monochrome (CGA/EGA compatibility) 640×480 in 16 colors or monochrome

SVGA: 640 × 400 or 640 × 480 with 256 colors 800 × 600 with 24-bit color depth 1024 × 768 with 24-bit color depth 1280 × 1024 with 24-bit color depth

In real life when you bought an SVGA card you could see the EGA lines duplicated because the video card and monitor supported both VGA and SVGA.

DOSBox emulates the video standard, not a graphics card.

Abundance doesn't bother and this can work well if someone wants to run an EGA game on an SVGA adapter. But many people like the original experience with simple lines. EGA on EGA monitor and CGA on CGA monitor.

I guess the SVGA only option is activated, but if I want to use other adapters it has to be deactivated?

What would be the difference between having the option or changing the adapter? I don't think I can explain my point any better.

HitoriSensei commented 3 weeks ago

You hit the nail right on the head. SVGA should not do this. Duplicating lines is a unique feature of VGA.

It's not entirely correct. SVGA stsndard is an extension of VGA specification. It standardized the video modes you've mentioned but because it is an extension of the standard, it inherits everything that VGA defines too. There are no "SVGA only" graphics cards, right?

But many people like the original experience with simple lines. EGA on EGA monitor and CGA on CGA monitor.

That's why there are multiple emulated adapters to choose from. The new option works for VGA and SVGA only, as only those adapters performed doubling. Additionally, if the option will be separately toggleable, one can even experience single-line EGA on SVGA adapter, because why not.

schellingb commented 3 weeks ago

As far as I know, original DOSBox always does the scaling internally by the rules our "Aspect Ratio Correction" adheres to now. I don't have the knowledge of video graphics standards and CRT monitors used back in the day so I'm heavily relying on the implementation in DOSBox being correct when setting things up for us. When the graphics mode is switched, according to the chosen graphics adapter (Hercules, CGA, EGA, VGA, SVGA) it decides on various parameters including resolution, frequency and two flags for "width doubling" and "height doubling". Original DOSBox then proceeds to draw every image with the doubling taken into account. DOSBox Pure on the other hand used to ignore the doubling and just tells the frontend to stretch the image. This gets us the same result as long as we're displaying on LCDs and without using shaders.

Maybe the option should be called "Output VGA compatible framebuffer" or "Pre-scale to VGA"? And should be available only for VGA and SVGA adapters, as EGA and CGA should always output without doubling, as that never happened in real life.

What if we offer 3 choices in the "Aspect Ratio Correction" core option (where we currently just have off/on):

So, if I want to run an EGA, (or any adapter), game in its original format (with single lines) and with the screen at 4:3, are the lines duplicated?

How can we confirm this? DOSBox source code has this when an emulated EGA adapter switches to a 320x200 EGA mode:

    if (IS_EGAVGA_ARCH) {
        ...
        else if (IS_VGA_ARCH) { ... }
        else vga.draw.double_scan=(vtotal==262);
    }
    ...
    switch (vga.mode) {
    ...
    case M_EGA:
        doublewidth=(vga.seq.clocking_mode & 0x8) > 0;
        vga.draw.blocks = width;
    ...
    }
    ...
    if (vga.draw.double_scan) {
        ...
        doubleheight=true;
    }

In the 320x200 EGA mode I'm testing here, vtotal is 262 and vga.seq.clocking_mode is 11. So it ends up with both doublewidth and doubleheight enabled and we end up still scaling it up to 640x400 with the new aspect ratio handling. Do you think this is wrong?

I noticed that the VGA adapter, by doubling (only) the vertical resolution) also increases the load of the emulator. I've been curious about some shader, you can tell it to draw double lines and it doesn't influence the performance.

There is an option for the core to employ GPU shaders. In fact we already do so when using the OpenGL backend for the 3dfx Voodoo emulation. Doubling lines and columns could potentially be performed there. The problem is just that the core still wants to run in pure software mode for devices that don't have 3D acceleration so we can't entirely get rid of code that does the doubling on the CPU.

alexb3d commented 2 weeks ago

There are no "SVGA only" graphics cards, right?

SVGA is a clone of XGA. In fact yes, the cards are SVGA only with VGA compatibility but not EGA, and there are many cards without VGA compatibility, but that's another topic.

if the option will be separately toggleable, one can even experience single-line EGA on SVGA adapter, because why not.

This is precisely what SVGA does. It represents the original format of each adapter.

As far as I know, original DOSBox always does the scaling internally by the rules our "Aspect Ratio Correction" adheres to now.

I have never used DOSBox, but it would be a surprise if it doubled the resolution, they are very strict in implementing the standards.

In the list of modes you posted above it shows the vertical frequency what are fps, the Ratio I imagine it is the setting for 4:3.
DoubleWidth and DoubleHeight are the stretching of the image, proportional to not deform the pixel, but it does not alter the internal resolution. It seems to me that they are looking for a more uniform panoramic image because some square resolutions are doubled only horizontally.
What doubles the internal resolution is DoubleScan and it is present in some modes, I imagine it's the VGAonly, because it's the only one that doubles the internal resolution.

What if we offer 3 choices in the "Aspect Ratio Correction" core option (where we currently just have off/on):

It is a great choice!

How can we confirm this? DOSBox source code has this when an emulated EGA adapter switches to a 320x200 EGA mode:

The technical specifications of the hardware, horizontal frequency 15.6kHz for 200/240 lines (similar to a TV) and 21kHz for 350 lines. Double scanlines are after 31kHz. Some monitors support 24kHz for 400 lines like the NEC-PC.

200 scan lines at 60Hz / 15.6kHz / 14.318MHz ("Mode 1") 350 scan lines at 60Hz / 21kHz / 16.257MHz ("Mode 2").

Do you think this is wrong?

I don't understand coding, it seems to me that it is to run an EGA game with a VGA adapter. IS_VGA_ARCH, and activates DoubleScan. else vga.draw.double_scan

62 in vtotal is 262 will be the black stripes that can be seen on EGA and earlier monitors?

DOSBox emulates everything and then trims the excess, I think all emulators do it. If it is the case, in VGA with the double scan it would be 462 or 526? I would like to check the black core frame option further, and compare it to the actual images, but I imagine it does not affect the scan lines.

HitoriSensei commented 2 weeks ago

What if we offer 3 choices in the "Aspect Ratio Correction" core option (where we currently just have off/on):

That's a great idea

In the 320x200 EGA mode I'm testing here, vtotal is 262 and vga.seq.clocking_mode is 11. So it ends up with both doublewidth and doubleheight enabled and we end up still scaling it up to 640x400 with the new aspect ratio handling. Do you think this is wrong?

If the IS_EGAVGA_ARCH flag means running in a EGA mode on a VGA adapter, then I think this is correct, as VGA adapter needs to output VGA resolution. So it needs to double EGA up to 640x400.

schellingb commented 2 weeks ago

No, IS_EGAVGA_ARCH means either EGA or VGA - So it means having the 'Emulated Graphics Chip' core option set to any of SVGA, VGA or EGA.

In the list of modes you posted above it shows the vertical frequency what are fps, the Ratio I imagine it is the setting for 4:3. DoubleWidth and DoubleHeight are the stretching of the image, proportional to not deform the pixel, but it does not alter the internal resolution. It seems to me that they are looking for a more uniform panoramic image because some square resolutions are doubled only horizontally. What doubles the internal resolution is DoubleScan and it is present in some modes, I imagine it's the VGAonly, because it's the only one that doubles the internal resolution.

Interesting, I think you might be right. DoubleWidth/DoubleHeight might be the wrong thing to look at. Or at least depending on the 'Emulated Graphics Chip' core option? Do you think it would make more sense to only do DoubleWidth/DoubleHeight on VGA/SVGA but ignore them on EGA and earlier but double lines on DoubleScan?

HitoriSensei commented 2 weeks ago

Interesting, I think you might be right. DoubleWidth/DoubleHeight might be the wrong thing to look at. Or at least depending on the 'Emulated Graphics Chip' core option? Do you think it would make more sense to only do DoubleWidth/DoubleHeight on VGA/SVGA but ignore them on EGA and earlier but double lines on DoubleScan?

In that case and according to @alexb3d insight on EGA, I think it would the right way to only do DoubleWidth/DoubleHeight on VGA/SVGA. Not sure about line doubling on EGA, @alexb3d what do you think, should EGA line-double in any scenario?

alexb3d commented 2 weeks ago

No, IS_EGAVGA_ARCH means either EGA or VGA - So it means having the 'Emulated Graphics Chip' core option set to any of SVGA, VGA or EGA.

Ok, I understand. In a 200p game with the VGAonly adapter, draw.double_scan will be enabled. With the EGA adapter, double_scan is not activated. Now I realize that this does not happen with CGA games, could it be that it is not compatible? I have to find that out.

DoubleWidth/DoubleHeight might be the wrong thing to look at. Or at least depending on the 'Emulated Graphics Chip' core option?

If this is actually stretching the image, then this is what the window will look like in DOSBox. I don't think it matters too much in RetroArch, just with the exception of the DoubleWidth only, because it transforms 320x350 square images into 640x350 panoramas.

A detail, in the option says "doubled lines/columns (for shaders or CRT displays)", it is only necessary to duplicate the vertical for the effects of the scanlines, the horizontal does not matter, because it is still stretched. This is what VGAonly does, from 320x200 to 320x400.

Do you think it would make more sense to only do DoubleWidth/DoubleHeight on VGA/SVGA but ignore them on EGA and earlier but double lines on DoubleScan?

SVGA only because it supports CGA, EGA and VGA modes and because VGAonly already duplicates it, and if it is duplicated the duplicate goes to 800p. lol

Also, I really think every modes should have DoubleScan. I don't remember if a B&W game for Hercules, had double lines on a SVGA monitor, I don't think I ever tried it, but this is emulation and having the option to explore alternatives would be fantastic.

What I do find convenient is to have the DoubleScan option separated from the 4:3 ratio, because many classic monitors like the IBM were more widescreen than 4:3, there are widescreen monitors like the Sony GDM-FW900, there are also wide TVs with VGA input and many games were made in the 16:10 format. If someone wants to play in widescreen with double scanline, they have the option.

Not sure about line doubling on EGA, @alexb3d what do you think, should EGA line-double in any scenario?

Yes, the scenarios would be to run the game on the original EGA hardwarde with single lines. Or on VGA/SVGA hardware with dual lines.

Then we would have these options... Single lines could be achieved with or with SVGA without double lines enabled or the EGAonly adapter and double lines could be achieved by enabling double lines in SVGA or using the VGAonly adapter.

alexb3d commented 1 week ago

A brief update.

By dabbling in the DOSBox forum, many things have become clearer to me and I have discovered others.

The correct name for line doubling according to the original IBM VGA manual is Double Scan and Border Support also known later in the XGA manual as Double Scanning and Border Support.
Line Doubler is a technology for converting interlaced video to progressive. I guess the confusion is because many 3rd party VGA manuals defined it as line-doubling.

All video adapters work correctly according to the official standard. They are kept separate for hardware fidelity and compatibility with some games. For example, some 640x400 games need VGA because they do not work in SVGA, or, some CGA games only reproduce colored borders and backgrounds on the CGA adapter.

What I shared above are the "modes accepted" by VGA, but not the resolution that the hardware handles. It actually handles only two. 640x400 and 640x480.

VGA takes the 200p and at the moment of drawing the line it doubles it by 2, to enter 640x400. On the other hand, the 350p resolution draws the lines in 400 mode and expands the lines using polarity of the sync signal to eliminate the excess black space (50 lines) and cover the entire monitor.

SVGA does not duplicate the lines, takes the 200p image and places it in 640x400 mode, and expands the image with the polarity of the sync signal, to fill the entire screen. The result is similar in both cases.

Where the difference is noticeable is in CGA/EGA vs VGA/SVGA. 200p in EGA has thick lines and high resolution only EGA, 350p has thin lines. In VGA it is the opposite. 200p is drawn double and has very thin lines, but 350p is drawn in 640x400 space and expands, drawing thick lines.

Hercules is not supported by VGA, and CGA/EGA have limited support. But software can be used to emulate these modes. PCjr and Tandy are CGA optimized, but cannot be used on a VGA monitor because the video adapter does not support it.


So, in favor of using all shaders with double lines and being as faithful as possible, only SVGA duplication would be necessary, which encompasses limited VGA and CGA/EGA, and these are the only modes that can reproduce double lines on a VGA monitor.

But if you think that Hercules and CGA/EGA can be emulated, then it would be convenient to have duplication on these adapters as well. PCjr and Tandy don't have any duplication capabilities, but if you want it would be extra only possible with emulation.