VOGONS


First post, by cde

User metadata
Rank Member
Rank
Member

TLDR: I patched the VGA BIOS ROM of my 9600 Pro to output 1280x1024@70.08 Hz instead of the VESA default of 75 Hz.

So basically I was looking for a LCD monitor to being able to play DOS games with the best fidelity, with overall disappointing results. Some monitors do not support 720x400@70Hz at all, some do but will output it stretched to full 1920x1080 even when the "preserve aspect ratio" option is enabled. As the video card stretches VGA 320x200 into 720x400, visual distortion (doubled pixels) appears with 1280x1024 LCDs. However the DVI output of the ATi cards I tested is much better since 320x200 is stretched internally to 1280x1024 which is then outputted directly. While nVIDIA has a lot of blur applied, ATi cards are almost pixel-perfect (see Re: Widescreen monitors and 4:3 aspect ratio compatibility thread). DVI is an attractive option especially for 4K screens that lack VGA input.

Unfortunately the VESA standard only requires 1280x1024@75 Hz to be supported in the preconfigured modes, and so my 9600 Pro when connected to my 4K ASUS VP28U screen outputs this resolution (1280x1024@75 Hz). This is not a huge problem for many games, but some games (such as Lotus III) tie their internal logic to the screen refresh rate, and so at 75 Hz Lotus III has slighly too fast music.

Now the VP28UGQ does support 1280x1024@70 Hz: this can be tested under Linux as follows

xrandr --newmode "1280x1024@70" 126 1280 1328 1440 1688 1024 1025 1028 1066 +hsync +vsync
xrandr --addmode DVI-0 "1280x1024@70"
xrandr --output DVI-0 --mode "1280x1024@70"

More precisely, the exact pixel clock required for 70.08 Hz is 126.10 MHz as per http://www.epanorama.net/faq/vga2rgb/calc.html . But how can one force this resolution in DOS? One possibility would be to hack the monitor's EDID, disabling bit 0 of EDID byte 36 (see https://en.wikipedia.org/wiki/Extended_Displa … tification_Data) and adding a custom detailed timing descriptor. That's pretty difficult though as it might require disassembling the display and patching the EEPROM. Another possibility is to plug a fake DVI cable with a specific I2C EEPROM with my custom EDID, wait for the PC to boot, and then plug the real display. In any case there's no guarantee that the card's BIOS ROM would actually use this custom detailed timing descriptor.

Another idead was to use UniRefresh or VBEHz, however this card only supports VBE 2.0 so that's out of the window. Then again another idea is, after DOS has booted, to issue the proper CRTC/PLL register writes to alter the pixel clock. While I believe this idea could work, after spending some time with the radeon drm driver in the Linux kernel, the whole CRTC and PLL parts are pretty complex and difficult to reimplement, so that would have required significant work.

Finally, I thought about patching the VGA BIOS ROM in order to alter the timings, and this approach eventually proved successful. After quite a bit of reverse-engineering, I was able to pinpoint the function responsible for parsing the EDID, and located after it a table of modelines. The first entry in this table is the mode that the ROM prefers (1280x1024@75 Hz) and contains in particular the pixel clock in the first two bytes:

BC 34 00 98 51 00 2A 40 10 90 13 00 00 00 00 00 00 1E

Above 0x34BC corresponds to 13500 which is the pixel clock for 1280x1024@75 Hz. So I changed it to 0x3142 (12610) which corresponds to 126.10 Mhz pixel clock, which is 70.08 Hz vertical refresh rate at 1280x1024:

42 31 00 98 51 00 2A 40 10 90 13 00 00 00 00 00 00 1E

This invalidates the CRC however, so the new ROM has to be fixed. I used for this RaBiT 2.2.1 (Radeon ATI BIOS Tuner, attached) and reflashed the card with atiflash 1.6 (also attached, newer versions do not detect this card).

The result is as expected: the card now outputs 70.08 Hz in DOS (as reported by the monitor itself) and Lotus III has perfect music! 😎

EDIT: the monitor has two HDMI inputs, and it appears only HDMI-2 supports 1280x1024@70 Hz, HDMI-1 says "out of range".

Attachments

  • Filename
    atiflash16.zip
    File size
    203.75 KiB
    Downloads
    71 downloads
    File license
    Fair use/fair dealing exception
  • Filename
    RaBiT-2.2.0.zip
    File size
    168.83 KiB
    Downloads
    74 downloads
    File license
    Fair use/fair dealing exception
Last edited by cde on 2019-08-15, 18:32. Edited 7 times in total.

Reply 2 of 27, by cde

User metadata
Rank Member
Rank
Member
mothergoose729 wrote:

Neat!

Would this effect the speed of any games that rely on the VGA for timing?

Based on running Lotus III at different refresh rates (60 Hz, 70 Hz and 75 Hz) I can confirm the refresh rate alters the music speed for this particular game, so it could surely have an effect on other games that rely on vsync to synchronize their internal logic.

Reply 3 of 27, by mothergoose729

User metadata
Rank Oldbie
Rank
Oldbie

Hm... that's no good. Seems like the best solution would be an external circuit that can synchronize the clocks. That would introduce some lag though.

Perhaps a high refresh rate monitor would be more forgiving?

Reply 4 of 27, by cde

User metadata
Rank Member
Rank
Member

I'm not sure I get what you mean. This particular monitor has no problem dealing with the refresh rates I mentioned, there's no stuttering or tearing in scrollers such as Jazz Jackrabbit and others.

Reply 6 of 27, by cde

User metadata
Rank Member
Rank
Member
mothergoose729 wrote:

Oh I understand now. You didn't change the refresh rate. My apologies.

No problem, indeed this monitor does not support setting up custom resolutions and refresh rates.

By the way, I mentioned above it had no issue handling 70 Hz / 75 Hz but I tried browsing vsynctester.com at those refresh rates and it's a solid fail 🙁 60 Hz is fine but I assume at above refresh rates the monitor just drops frames, so instead if you're looking for a 4K screen consider one that can support higher than 60 Hz without dropping frames (the VP28UQG is only rated up to 60 Hz, so I presume that's why it drops frames).

Reply 7 of 27, by cde

User metadata
Rank Member
Rank
Member

The initial patch I made turned out not to work on a 1280x1024 19" LCD, here the HP EliteDisplay E190i. The reason for that is the ATi ROM code will always prefer the monitor's custom modelines as long as the pixel clock is within what the hardware supports. So I was lucky that my 4K screen had an unsupported custom modeline but also supported 1280x1024@75 Hz in the VESA default modelines, hence simply fixing the pixel clock for that modeline worked. However the ROM will prefer the 1280x1024@60 Hz in the EDID over any VESA modeline.

So I made a slightly more complex patch that now always forces the use of the 1280x1024@70.08 Hz modeline defined in the ROM BIOS regardless of what the EDID contains. I have attached the modified ROM, but note that it is specifically for the 9600 Pro and should only be used if your monitor supports this particular modeline on its DVI input.

Finally, this modification, while providing very good results with the games I tested, is not fully satisfying. The reason is that certain games run at 60 Hz, notably Jazz Jackrabbit and Epic Pinball. Although they seem to work fine with no stutter or tearing, I've timed various repetitive in-game events and they do indeed run a bit faster when the refresh rate is locked at 70.08 Hz (when outputting to DVI, ATi cards will never change the pixel clock from int 10h or VGA register writes after BIOS initialization is done) as the game's internals depend on vsync for timing events. Also I've noted Quake when running at a forced 320x200 @ 70.08 Hz is stutter free and very smooth as compared to 320x200 @ 60 Hz (even though 60Hz is the monitor's refresh rate). The rate was measured with Quake's "timerefresh" which does report 70 Hz.

So I've considered writing a small utility that would write to the relevant PLL registers and allow to switch between different pixel clocks and will update this thread if I manage to create it.

Attachments

  • Filename
    9600.zip
    File size
    64.84 KiB
    Downloads
    82 downloads
    File license
    Fair use/fair dealing exception

Reply 8 of 27, by darry

User metadata
Rank l33t++
Rank
l33t++
cde wrote on 2019-08-15, 18:30:
The initial patch I made turned out not to work on a 1280x1024 19" LCD, here the HP EliteDisplay E190i. The reason for that is t […]
Show full quote

The initial patch I made turned out not to work on a 1280x1024 19" LCD, here the HP EliteDisplay E190i. The reason for that is the ATi ROM code will always prefer the monitor's custom modelines as long as the pixel clock is within what the hardware supports. So I was lucky that my 4K screen had an unsupported custom modeline but also supported 1280x1024@75 Hz in the VESA default modelines, hence simply fixing the pixel clock for that modeline worked. However the ROM will prefer the 1280x1024@60 Hz in the EDID over any VESA modeline.

So I made a slightly more complex patch that now always forces the use of the 1280x1024@70.08 Hz modeline defined in the ROM BIOS regardless of what the EDID contains. I have attached the modified ROM, but note that it is specifically for the 9600 Pro and should only be used if your monitor supports this particular modeline on its DVI input.

Finally, this modification, while providing very good results with the games I tested, is not fully satisfying. The reason is that certain games run at 60 Hz, notably Jazz Jackrabbit and Epic Pinball. Although they seem to work fine with no stutter or tearing, I've timed various repetitive in-game events and they do indeed run a bit faster when the refresh rate is locked at 70.08 Hz (when outputting to DVI, ATi cards will never change the pixel clock from int 10h or VGA register writes after BIOS initialization is done) as the game's internals depend on vsync for timing events. Also I've noted Quake when running at a forced 320x200 @ 70.08 Hz is stutter free and very smooth as compared to 320x200 @ 60 Hz (even though 60Hz is the monitor's refresh rate). The rate was measured with Quake's "timerefresh" which does report 70 Hz.

So I've considered writing a small utility that would write to the relevant PLL registers and allow to switch between different pixel clocks and will update this thread if I manage to create it.

You may want to consider a different method using an EDID emulator, as described here 70Hz in pure DOS at 1600x1200 (or other) over DVI on an old card (FX5900) with modern monitor is possible

It does not work the way I hoped with my Radeon 9700 (works with a Geforce FX 5900), but I have a theory as to why and how to address it. As you have the skills to patch a video ROM, you may be able to confirm whether or not my idea makes sense or not :

My guess is the that logic in the BIOS selects the highest refresh rate available in the EDID's mode list and an then chooses the highest resolution available at that given refresh rate . If that turns out to be true, it should be possible to force 1600x1200 by removing all modes above 70Hz from the EDID

As for the issue with certain DOS software requiring 60Hz, using an EDID emulator with multiple switchable EDIDs would allow to switch to 60Hz mode with just the press of a button and a reboot . The Aten VC060 (DVI) and VC080 (HDMI) are two such models .

Reply 9 of 27, by cde

User metadata
Rank Member
Rank
Member

I haven't looked into the details of how the BIOS chooses the modes from the EDID, sorry. I just disabled the whole portion of code that does this choice in order to force the use internal modelines. I suspect the pixel clock for 1600x1200@70 Hz could be higher than the card's acceptable range and so the modeline gets rejected.

Reply 10 of 27, by darry

User metadata
Rank l33t++
Rank
l33t++
cde wrote on 2020-05-31, 07:57:

I haven't looked into the details of how the BIOS chooses the modes from the EDID, sorry. I just disabled the whole portion of code that does this choice in order to force the use internal modelines. I suspect the pixel clock for 1600x1200@70 Hz could be higher than the card's acceptable range and so the modeline gets rejected.

With reduced blanking, actual pixel pixel clock for 1600x1200 at 70Hz is 152.75Mhz , so less than the single link max . If memory serves, even with a max EDID resolution of 1600x1200 at 60Hz (on a Samsung 204B), the ATI Radeon 9700 still defaulted to 1280x1024 at 75Hz , so if it is a pixel clock limit related issue, the max is likely set to an arbitrarily low value .

Reply 12 of 27, by darry

User metadata
Rank l33t++
Rank
l33t++
cde wrote on 2020-06-01, 07:17:

Yes, that would be surprising. I would suggest booting Linux and try setting your desired modeline with xrandr, while keeping an eye on X.org log messages.

Won't that just bypass the logic in the video BIOS, the same way the Windows driver does ? The card does work fine in Windows, at least at 1600x1200 60 Hz over DVI .

Reply 13 of 27, by darry

User metadata
Rank l33t++
Rank
l33t++

I was able to patch the equivalent modeline in my Radeon 9700 BIOS and can now get 1280x1024 at 70Hz under DOS (My emulated EDID does include a1280x1024 70Hz) . This is almost perfect except for the double scaling and the aspect ratio. My understanding of my 1920x1200 monitor's behaviour in its "preserve aspect ratio" mode is that it treats the received 1280x1024 as a square pixel mode and scales it to 1500x1200 , thus preserving the 5:4 aspect ratio, which is fine if the source image is actually 5:4 (i.e. 1280x1024 under Windows). However, if the source image is 640x400 (double scanned 320x200) with non square pixels, but 4:3 image aspect ratio, it first get scaled to 1280x1024 by the video card and then gets scaled again by the monitor to 1500x1200 in 5:4 image aspect ratio . The double scaling is not the end of the world, IMHO, but the 4:3 image stretched to 5:4 is not ideal .

I tried two approaches to resolve that .

a) Removing all modes above 70Hz and removing all 5:4 (1280x1024) modes from the EDID . This got me 1024x768 at 60Hz . 1024x768@70Hz, 1280x960@70Hz and 1600x1200 @70Hz (with reduced blanking) were all ignored .
b) Attempting to edit the modeline in the video BIOS to force 1600x1200@60Hz as a first test (had it worked I would have tried to use the 1600x1200@70Hz timings). I thought I understood the values for total horizontal lines, total vertical lines, H_FPORCH , H_SYNC , V_BPORCH , etc , but I evidently got it wrong as the resulting modded VBIOS booted with a black screen (I was able to recover and flashed back to the 1280x1024@70Hz modded VBIOS) .

If you have managed to fully understand the vBIOS modelines, and believe what I am suggesting in b) could potentially work if implemented properly, would you be willing to share the info ?

As a side node that may be of interest, certain Radeon 9600/9550 BIOSes actually do seem to output 1600x1200@60Hz if the monitor EDID supports it. If I am not mistaken (hope it's the right file, ROM was saved a while ago and I'd have to test about 6 cards to know which one it came from), I have a BIOS dump of such a card .

Filename
96_4_3.zip
File size
31.8 KiB
Downloads
57 downloads
File license
Fair use/fair dealing exception

Reply 14 of 27, by darry

User metadata
Rank l33t++
Rank
l33t++

I found the modeline for 1024x768@60Hz and upped the pixel clock from 0x1964 (6500) to 0x1D9F (7583) while preserving the other timing values and got 1024x768@70Hz (still using the modded EDID without 1024x1024) in DOS, which solves the aspect ratio issue.

The only potential remaining improvement, for my use case at least, would be getting 1600x1200@70Hz to get rid of the double scaling .

Reply 15 of 27, by cde

User metadata
Rank Member
Rank
Member

Unfortunately I don't know enough about the VBIOS modes to help you further 🙁 you could however port my assembly patch from the 9600 Pro to the 9700 in order to force ignoring the EDID modes.

After a lot of testing with various LCDs and modes I came to the personal conclusion that for 320x240 the best experience was with a 17" or lower CRT, or a 144 Hz LCD with VGA and a 4:3 option like the AOC G2590PX.

That being said I do hope you will find a way to display 1600x1200@70 Hz. By using xrandr in Linux, you should be able to validate that indeed your card is physically capable of outputting this resolution.

Reply 16 of 27, by darry

User metadata
Rank l33t++
Rank
l33t++
cde wrote on 2020-06-02, 18:52:

Unfortunately I don't know enough about the VBIOS modes to help you further 🙁 you could however port my assembly patch from the 9600 Pro to the 9700 in order to force ignoring the EDID modes.

After a lot of testing with various LCDs and modes I came to the personal conclusion that for 320x240 the best experience was with a 17" or lower CRT, or a 144 Hz LCD with VGA and a 4:3 option like the AOC G2590PX.

That being said I do hope you will find a way to display 1600x1200@70 Hz. By using xrandr in Linux, you should be able to validate that indeed your card is physically capable of outputting this resolution.

Thank you for you insight and help . The card actuall does 1600x1200 70Hz in Windows 98 SE with my EDID emulator ,without using Powerstrip, so I know it is physically capable . I'll take a brake from this .

Thanks again for demonstrating how to change the modeline pixel clocks in the vBIOS of those cards .

Reply 17 of 27, by darry

User metadata
Rank l33t++
Rank
l33t++

I tried changing the preferred modeline to 1280x960 60Hz and machine will not post if that resolution is available in EDID .

Next I will try setting 1024x768@70Hz as preferred resolution . If that works, it avoids need for EDID emulator and preserves 4:3 aspect ratio.

Reply 18 of 27, by darry

User metadata
Rank l33t++
Rank
l33t++
darry wrote on 2020-06-02, 20:36:

I tried changing the preferred modeline to 1280x960 60Hz and machine will not post if that resolution is available in EDID .

Next I will try setting 1024x768@70Hz as preferred resolution . If that works, it avoids need for EDID emulator and preserves 4:3 aspect ratio.

1024x768@70Hz works without an EDID emulator on my monitor with this change .

Reply 19 of 27, by darry

User metadata
Rank l33t++
Rank
l33t++

Well, final nail in the coffin for the Radeon 9700, at least as a DOS card for me : it simply does not work with Future Crew's Second Reality (no signal), no matter if its in 60Hz, 70Hz or 75Hz mode .