VOGONS


MartyPC

Topic actions

Reply 340 of 352, by SoftCat

User metadata
Rank Member
Rank
Member
jal wrote on 2024-10-23, 08:23:

Trying to get a higher resolution out of a CGA that only works with an EGA monitor is daft to begin with.

JAL

This is not true. This mode is intended for EGA video card with EGA or CGA (or multisync) monitor.
I like MartyPC and I want it to be better. A good emulator should support everything that the emulated hardware supports. Whether to add it to the emulator or not is up to the author.

Reply 341 of 352, by GloriousCow

User metadata
Rank Member
Rank
Member
SoftCat wrote on 2024-10-23, 12:01:

A good emulator should support everything that the emulated hardware supports. Whether to add it to the emulator or not is up to the author.

By that metric, there are no good emulators. It is always possible to construct some program that breaks any given emulator, for all but the simplest of machines.

MartyPC: A cycle-accurate IBM PC/XT emulator | https://github.com/dbalsom/martypc

Reply 342 of 352, by superfury

User metadata
Rank l33t++
Rank
l33t++
GloriousCow wrote on 2024-10-23, 22:20:
SoftCat wrote on 2024-10-23, 12:01:

A good emulator should support everything that the emulated hardware supports. Whether to add it to the emulator or not is up to the author.

By that metric, there are no good emulators. It is always possible to construct some program that breaks any given emulator, for all but the simplest of machines.

I do try to implement all functionality of the emulated hardware, though, in my emulator, as is documented in the chip documentation.
Not counting bugs of course (which it still has).
Right now, my (S)VGA is the most complete one that exists, to my knowledge. Although not an accurate CRT (monitor) itself unlike MartyPC's. It still shows the hidden areas (borders) for example, which aren't visible on real monitors. Those left/right special areas that are monitor specific (making it uncentered in this case).

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 343 of 352, by GloriousCow

User metadata
Rank Member
Rank
Member
superfury wrote on 2024-10-24, 06:44:

I do try to implement all functionality of the emulated hardware, though, in my emulator, as is documented in the chip documentation.
Not counting bugs of course (which it still has).
Right now, my (S)VGA is the most complete one that exists, to my knowledge. Although not an accurate CRT (monitor) itself unlike MartyPC's. It still shows the hidden areas (borders) for example, which aren't visible on real monitors. Those left/right special areas that are monitor specific (making it uncentered in this case).

I certainly don't mean to imply we don't try our best. There are just always tradeoffs between accuracy, performance, and convenience of implementation to be made, and in those tradeoffs you can find lots of things lurking that make it possible to, if not outright break an emulator, construct software that doesn't work on an emulator.

There's a cheeky demo for the Amstrad CPC by Logon System I believe that tells you the name of the emulator you're using to watch it. The only way it can know is by detecting some deviance from real hardware.

MartyPC: A cycle-accurate IBM PC/XT emulator | https://github.com/dbalsom/martypc

Reply 344 of 352, by GloriousCow

User metadata
Rank Member
Rank
Member

Ok, to summarize:

I've been thinking more about it, and after taking a look at the readouts shown by my rgb2hdmi running the demo, I think SoftCat is probably correct that this would work. Unfortunately 5154 monitors are obscenely expensive so its unlikely I'll ever be able to test for myself.

To handle the various display modes used by 8088MPH and Area 5150, and to properly emulate the overscan, I adopted an aperture into a fixed display field for CGA. This technique worked very well, and has handled everything I've thrown at it basically.

I tried to expand on that concept to implement EGA by creating two display fields for EGA's 14Mhz and 16Mhz clocks, to support the various modes supported by each.
My naive assumption was that we would be in 15Khz scanline frequency when using the 14Mhz clock, and we'd be in 21Khz scanline frequency when using the 16Mhz clock.

As SoftCat has demonstrated I think these assumptions are bad - you can construct a mode in the 16Mhz clock that creates a 15Khz scanline frequency - so the requisite display field isn't necessarily tied to the clock. It's tied to the scanline frequency.

Now, the simplest thing to do is simply go back to a single display field, set to the largest extents of both clocks. We'll waste some memory, but it will essentially be fine. But what I think I ultimately should do is determine the display field extents based on a vertical and horizontal PLL that syncs to the vsync and hsync signals within a reasonable range, comparable to what a real monitor might tolerate. The advantage of this method is that it should handle VGA much better than trying to handle separate display fields for 350, 400 and 480 lines, as well as if I ever bother to do SVGA where there would be basically infinite display fields possible. Plus we can simulate loss of vhold, display bounce when changing video modes, and other fun stuff. There are a few points during effect setup in Area 5150 where we have very short vsync periods, which if you look closely at a hardware capture, you can see the monitor's vertical PLL reject and they show up as black bars on screen.

I think this is the method that Tom Harte's CLK emulator uses. The thought of doing a PLL scared me a while ago, but after making one to read floppy flux images they're really not so bad, but there is an art to them I have yet to master.

There's another advantage here in that it will eliminate a bit of a hack I implemented for Hercules - the MDA monitor lacked a horizontal PLL which is why you have those warnings about potentially damaging a MDA monitor with bad display modes. Some CGA emulators for Hercules took advantage of this by pushing the display timings just slightly out of spec. This meant that I had to slightly expand the display field for Hercules, in a way that is not really derived from its clock timings.

In any case, my main focus for 0.3.0 is getting the new disk support in a stable state. Stable, not complete. I'll probably be fixing floppy and disk format issues for the lifetime of MartyPC going forward.

I'll look at the PLL implementation for 0.3.1, which is a good excuse to bundle it with the reintroduction of VGA.

MartyPC: A cycle-accurate IBM PC/XT emulator | https://github.com/dbalsom/martypc

Reply 345 of 352, by superfury

User metadata
Rank l33t++
Rank
l33t++

So basically, you're measuring the average scanline time (in nanoseconds for example) and use it to clip a horizontal range for resizing bases on monitor specs? And the same for the frame(vertical) timing, which is the time between vertical retraces?

So basically, for VGA you take the emulated maximum time a scanline ticked between retraces for horizontal, the same for vertical (the literal time between retrace starting) to get the physical time of both fields.

Then use some official monitor specs to translate those two timings back into pixels for a screen to obtain the area the user sees (x1,x2,y1,y2 coordinates) and resize that area to 4:3 on some sane buffer resolution (800x600 for VGA for example)?

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 346 of 352, by mkarcher

User metadata
Rank l33t
Rank
l33t
GloriousCow wrote on 2024-10-24, 16:49:

But what I think I ultimately should do is determine the display field extents based on a vertical and horizontal PLL that syncs to the vsync and hsync signals within a reasonable range, comparable to what a real monitor might tolerate.

If you implement that, you might be able to recreate the effect that happens when you connect a 31kHz VGA (or 30-50 kHz SVGA) monitor without IBM-like monitor ID pins to an IBM PS/2 model 30. In that case, the PS/2 model 30 might mis-recognize the monitor as 15kHz monitor (which is a completely undocumented operating mode of that system...) and output CGA/NTSC timings. I had multiple monitors sync to twice the actual horizontal frequency (i.e. 31.2kHz instead of 15.6kHz) if that happened. I don't see any point in skipping every second hsync for VGA monitors, though, even if it works with a couple of monitors at least. I guess it will fail on everything with "digital control".

Reply 347 of 352, by superfury

User metadata
Rank l33t++
Rank
l33t++

I've updated UniPCemu's video support a bit:
- The GPU can now display ranges of display rendering buffer as an alternative to the entire video buffer. So it can specify a x1,y1,x2,y2 rectangle to render as an alternative to the old 0,0,x2,y2 rendering system.
- Screen captures are still performing a full display buffer dump, including said areas. They also aren't resized in any way (thus containing the raw video data the video adapter dumps on it's clocks, from retrace to retrace).
- The video card can set this mode when it's rendering Vertical Retrace. It's currently rendering the full frame. So it can either use the legacy method (full frame) or the new partial frame (x1,y1,x2,y2) method for the rendered frame from the display buffer.
- The video card has the horizontal and vertical resolution, as well as the largest (maximum) horizontal scanline time and the total vertical scanlines time (a sum of all rendered scanlines horizontal time).

So it should be able to somehow create a x1,y1,x2,y2 window based on those two timings and the rendered frame size.
The question is, what should those x1,y1,x2,y2 locations be, based on the display adapter used (MDA, CGA, (S)VGA)?

From what I can see on the MDA display adapter's output, it seems to have no borders at all? The active display starts exactly at coordinate 0,0 at least.

Right now, the timing detected on the MDA text mode is roughly:
- Horizontal: 54253.551269531250ns (18431.97314461513Hz)
- Vertical: 20073813.969726562ns (49.81614363409495Hz)

And on CGA text mode it's:
- Horizontal: 63695.238647460938ns (15699.76062943698Hz)
- Vertical: 16688152.525634766ns (59.9227504940343Hz)

On VGA text mode it's (720x400):
- Horizontal: 31777.418518066406ns (31468.88723611927Hz)
- Vertical: 14236248.187850952ns (70.24322608068806Hz)

Although right now the XT isn't displaying much with CGA/MDA (blank display buffer) and nothing but a blank screen with a cursor blinking on the VGA adapter tested.

The ns timings are simply obtained by looking at the accumulated values in the double-typed floating point variables. Conversion to Hz is simply 1000000000/ns formula (although done in Windows' calculator, which is limited in it's digit inputs compared to UniPCemu's raw floating point value entered manually into the calculator).
CGA for example gets a vertical retrace-to-retrace field rate of 59.922750494034275Hz when calculated from the raw values in the timing variables.
Horizontal timing being 15699.760629436980Hz from the raw variable.

Taking rounding into account on the raw timings (nanoseconds) timed by UniPCemu, it matches (after rounding) to the timings mentioned at https://www.minuszerodegrees.net/mda_cga_ega/mda_cga_ega.htm
With EGA I'm getting (when rounded) those mode 2 timings.

Last edited by superfury on 2024-10-24, 21:11. Edited 5 times in total.

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 348 of 352, by GloriousCow

User metadata
Rank Member
Rank
Member
superfury wrote on 2024-10-24, 18:21:

So basically, you're measuring the average scanline time (in nanoseconds for example) and use it to clip a horizontal range for resizing bases on monitor specs? And the same for the frame(vertical) timing, which is the time between vertical retraces?

So basically, for VGA you take the emulated maximum time a scanline ticked between retraces for horizontal, the same for vertical (the literal time between retrace starting) to get the physical time of both fields.

Then use some official monitor specs to translate those two timings back into pixels for a screen to obtain the area the user sees (x1,x2,y1,y2 coordinates) and resize that area to 4:3 on some sane buffer resolution (800x600 for VGA for example)?

Something like that. I'd calculate a signal clock in Hz based off when the CRTC raises hsync. The monitor PLL will have a clock which is adjusted within a certain window to match the input signal. So maybe the horizontal PLL can lock on to 15Khz +/-15% (i am not sure what the actual tolerance should be). What about 21Khz mode then? Easy, just have two PLLs, have the other try to sync to 21Khz +/- 15%. Whichever PLL is synced determines what mode you're in. I assume a real 5154 would only sync to something close to those two frequencies, as it is oft described as "dual frequency." To remain stable, the PLL has a proportional term which limits how fast it can adjust. So it may take a brief moment to sync to a new video mode, but you'd see a similar thing on a real monitor when changing modes.

If you want a multisync monitor, for VGA and such, just have one horizontal PLL with a wide berth of frequencies and a larger term perhaps.

superfury wrote on 2024-10-24, 20:31:
I've updated UniPCemu's video support a bit: - The GPU can now display ranges of display rendering buffer as an alternative to t […]
Show full quote

I've updated UniPCemu's video support a bit:
- The GPU can now display ranges of display rendering buffer as an alternative to the entire video buffer. So it can specify a x1,y1,x2,y2 rectangle to render as an alternative to the old 0,0,x2,y2 rendering system.

So it should be able to somehow create a x1,y1,x2,y2 window based on those two timings and the rendered frame size.
The question is, what should those x1,y1,x2,y2 locations be, based on the display adapter used (MDA, CGA, (S)VGA)?

From what I can see on the MDA display adapter's output, it seems to have no borders at all? The active display starts exactly at coordinate 0,0 at least.

Sounds like you're entering the 'aperture' territory I've been dealing with in MartyPC. You're correct that there's no appreciable overscan in MDA timings. I define my "cropped" aperture which is designed to show the traditional resolution of a card (for mda, 720x350) with an x1,y1 of (9,4). But this is dependent on how you handle your horizontal and vertical sync timings, so maybe you won't need any.

MartyPC: A cycle-accurate IBM PC/XT emulator | https://github.com/dbalsom/martypc

Reply 349 of 352, by GloriousCow

User metadata
Rank Member
Rank
Member
mkarcher wrote on 2024-10-24, 19:26:

If you implement that, you might be able to recreate the effect that happens when you connect a 31kHz VGA (or 30-50 kHz SVGA) monitor without IBM-like monitor ID pins to an IBM PS/2 model 30. In that case, the PS/2 model 30 might mis-recognize the monitor as 15kHz monitor (which is a completely undocumented operating mode of that system...) and output CGA/NTSC timings. I had multiple monitors sync to twice the actual horizontal frequency (i.e. 31.2kHz instead of 15.6kHz) if that happened. I don't see any point in skipping every second hsync for VGA monitors, though, even if it works with a couple of monitors at least. I guess it will fail on everything with "digital control".

That's pretty interesting. Allowing you to swap monitor types in and out in the configuration could be fun as well, although I'd have to be careful it doesn't cause another source of confusion if people select an incompatible monitor / card combo.

MartyPC: A cycle-accurate IBM PC/XT emulator | https://github.com/dbalsom/martypc

Reply 350 of 352, by superfury

User metadata
Rank l33t++
Rank
l33t++
GloriousCow wrote on 2024-10-24, 20:52:
Something like that. I'd calculate a signal clock in Hz based off when the CRTC raises hsync. The monitor PLL will have a clock […]
Show full quote
superfury wrote on 2024-10-24, 18:21:

So basically, you're measuring the average scanline time (in nanoseconds for example) and use it to clip a horizontal range for resizing bases on monitor specs? And the same for the frame(vertical) timing, which is the time between vertical retraces?

So basically, for VGA you take the emulated maximum time a scanline ticked between retraces for horizontal, the same for vertical (the literal time between retrace starting) to get the physical time of both fields.

Then use some official monitor specs to translate those two timings back into pixels for a screen to obtain the area the user sees (x1,x2,y1,y2 coordinates) and resize that area to 4:3 on some sane buffer resolution (800x600 for VGA for example)?

Something like that. I'd calculate a signal clock in Hz based off when the CRTC raises hsync. The monitor PLL will have a clock which is adjusted within a certain window to match the input signal. So maybe the horizontal PLL can lock on to 15Khz +/-15% (i am not sure what the actual tolerance should be). What about 21Khz mode then? Easy, just have two PLLs, have the other try to sync to 21Khz +/- 15%. Whichever PLL is synced determines what mode you're in. I assume a real 5154 would only sync to something close to those two frequencies, as it is oft described as "dual frequency." To remain stable, the PLL has a proportional term which limits how fast it can adjust. So it may take a brief moment to sync to a new video mode, but you'd see a similar thing on a real monitor when changing modes.

If you want a multisync monitor, for VGA and such, just have one horizontal PLL with a wide berth of frequencies and a larger term perhaps.

superfury wrote on 2024-10-24, 20:31:
I've updated UniPCemu's video support a bit: - The GPU can now display ranges of display rendering buffer as an alternative to t […]
Show full quote

I've updated UniPCemu's video support a bit:
- The GPU can now display ranges of display rendering buffer as an alternative to the entire video buffer. So it can specify a x1,y1,x2,y2 rectangle to render as an alternative to the old 0,0,x2,y2 rendering system.

So it should be able to somehow create a x1,y1,x2,y2 window based on those two timings and the rendered frame size.
The question is, what should those x1,y1,x2,y2 locations be, based on the display adapter used (MDA, CGA, (S)VGA)?

From what I can see on the MDA display adapter's output, it seems to have no borders at all? The active display starts exactly at coordinate 0,0 at least.

Sounds like you're entering the 'aperture' territory I've been dealing with in MartyPC. You're correct that there's no appreciable overscan in MDA timings. I define my "cropped" aperture which is designed to show the traditional resolution of a card (for mda, 720x350) with an x1,y1 of (9,4). But this is dependent on how you handle your horizontal and vertical sync timings, so maybe you won't need any.

Well, the way the timings are handled is pretty simple: during sync, the rendering position is kept at 0 until the sync stops. Then it increases with 1 for every clock/scanline rendered.
So basically if you have 800 horizontal clocks with 80 retrace clocks, the display is filled with 720 pixels.
Though the 8-bit inputting VGA DAC may divide it by 2 or 3 in higher color modes on SVGA adapters (15/16-bit and true color modes for example).

The framebuffer is parsed pretty dumb actually: it's simply resized to the target aspect ratio at various fixed resolutions (for example 800x600 on VGA to obtain 4:3 aspect ratio, larger multiples are possible too: 1024x768, 1440x1080 etc. All at 4:3). Although CGA has a special mode as well (379.83 x 242.5 aspect ratio at 800x600)) as well as a special 4K mode (3840x2160 at an unmodified aspect ratio (the same as the 4K aspect ratio)).
The area to resize to the viewing resolution is either the old x/y resolution (x2,y2), or the full frame size (x1,y1,x2,y2). Everything is simply stretched horizontally and vertically to the configured display resolution and aspect ratio. Most stretch to 4:3 aspect ratio, except the 4K one in this case. Although there's two 4K options: one that stretches to full 4K (getting it's aspect ratio instead) and one that keeps it at 4:3 aspect ratio. All others are always kept at 4:3 aspect ratio (except the CGA display one).
Though I usually have it set simply to 4:3 800x600 (small and fast) or sometimes 1024x768 resolution if I want to get a good look at the output (I'm using a plain 1080p FullHD monitor myself).

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 351 of 352, by SoftCat

User metadata
Rank Member
Rank
Member
GloriousCow wrote on 2024-10-24, 16:49:
Ok, to summarize: […]
Show full quote

Ok, to summarize:

I've been thinking more about it, and after taking a look at the readouts shown by my rgb2hdmi running the demo, I think SoftCat is probably correct that this would work. Unfortunately 5154 monitors are obscenely expensive so its unlikely I'll ever be able to test for myself.

To handle the various display modes used by 8088MPH and Area 5150, and to properly emulate the overscan, I adopted an aperture into a fixed display field for CGA. This technique worked very well, and has handled everything I've thrown at it basically.

I tried to expand on that concept to implement EGA by creating two display fields for EGA's 14Mhz and 16Mhz clocks, to support the various modes supported by each.
My naive assumption was that we would be in 15Khz scanline frequency when using the 14Mhz clock, and we'd be in 21Khz scanline frequency when using the 16Mhz clock.

As SoftCat has demonstrated I think these assumptions are bad - you can construct a mode in the 16Mhz clock that creates a 15Khz scanline frequency - so the requisite display field isn't necessarily tied to the clock. It's tied to the scanline frequency.

Now, the simplest thing to do is simply go back to a single display field, set to the largest extents of both clocks. We'll waste some memory, but it will essentially be fine. But what I think I ultimately should do is determine the display field extents based on a vertical and horizontal PLL that syncs to the vsync and hsync signals within a reasonable range, comparable to what a real monitor might tolerate. The advantage of this method is that it should handle VGA much better than trying to handle separate display fields for 350, 400 and 480 lines, as well as if I ever bother to do SVGA where there would be basically infinite display fields possible. Plus we can simulate loss of vhold, display bounce when changing video modes, and other fun stuff. There are a few points during effect setup in Area 5150 where we have very short vsync periods, which if you look closely at a hardware capture, you can see the monitor's vertical PLL reject and they show up as black bars on screen.

I think this is the method that Tom Harte's CLK emulator uses. The thought of doing a PLL scared me a while ago, but after making one to read floppy flux images they're really not so bad, but there is an art to them I have yet to master.

There's another advantage here in that it will eliminate a bit of a hack I implemented for Hercules - the MDA monitor lacked a horizontal PLL which is why you have those warnings about potentially damaging a MDA monitor with bad display modes. Some CGA emulators for Hercules took advantage of this by pushing the display timings just slightly out of spec. This meant that I had to slightly expand the display field for Hercules, in a way that is not really derived from its clock timings.

In any case, my main focus for 0.3.0 is getting the new disk support in a stable state. Stable, not complete. I'll probably be fixing floppy and disk format issues for the lifetime of MartyPC going forward.

I'll look at the PLL implementation for 0.3.1, which is a good excuse to bundle it with the reintroduction of VGA.

GloriousCow, I'm glad you agreed. I looked at the CRTC parameters in the monochrome mode of EGA Fh (640x350). There is the inverse situation: pixel clock 14.31818 MHz, but 350 lines. This is done specifically for compatibility with a monochrome monitor: frequencies ~18 kHz and ~50 Hz. In general, on EGA you can do all the MDA and Hercules modes with 720 columns. And you can even do better than on Hercules, that is, the 720x350 graphics mode, since the video memory on EGA does not need to be divided between 4 banks.

Reply 352 of 352, by jal

User metadata
Rank Oldbie
Rank
Oldbie

As for testing on a real EGA monitor, I bet there are collectors out there that have one and don't mind testing some simple mode switch (the likes of Trixter). As for VGA overscan: VGA CRT monitors did have some borders, albeit not as wide as CGA, since they hadn't to deal with the signal being displayed on a tv.