VOGONS


NVIDIA Kepler/Maxwell/Pascal VESA Bios Bug (workaround found)

Topic actions

Reply 240 of 258, by Falcosoft

User metadata
Rank l33t
Rank
l33t
Marco Pistella wrote on 2026-05-23, 08:01:
First of all, a big thank you to everyone who has been testing NEWAX 0.11 and providing feedback. Your reports are extremely val […]
Show full quote

First of all, a big thank you to everyone who has been testing NEWAX 0.11 and providing feedback. Your reports are extremely valuable and are directly driving the development of the next version.
A specific request: if you have pre-G80 hardware, please test latest NEWAX version (linked above - not GitHub version) and report your results. The current Detect_Supported_Nvidia routine has a known false positive on NV44 discrete (GeForce 6200 confirmed), and improving the detection for pre-G80 hardware requires real-world data from as many cards as possible. PCI_ID, revision and SUBSYS_ID from the /S output are particularly useful.

@Falcosoft

Hi Falcosoft, thank you for sharing the TSR — the approach is interesting and the vsync loop logic is correct in principle. However I found this issues:
1. BL=82h → BL=02h conversion is incorrect and potentially serious
BL=82h (schedule display start, VESA 3.0 asynchronous) has completely different semantics and parameters from BL=02h (set display start during retrace, synchronous). Silently converting one to the other produces incorrect behavior on any VBIOS that implements BL=02h correctly, and the caller has no way to know the conversion happened.
2. Hang on monochrome systems
The vsync loop reads unconditionally from port 3DAh. On monochrome systems the status register is at 3BAh — the loop will wait forever for a transition that will never come on that port.
3. Hang on Intel HD graphics and similar
On many Intel integrated GPUs (SandyBridge, IvyBridge, Haswell and later) port 3DAh does not behave as a standard VGA status register. The vsync loop will hang indefinitely — ironically on exactly the hardware you mentioned as having vsync problems.
4. BL not preserved on return
The caller passes BL=80h. The TSR modifies it to BL=00h before PUSHA, calls the VBIOS, then IRET. The caller receives BL=00h on return instead of the original BL=80h. A TSR must preserve input registers that are not defined as output by the VESA specification.
5. Spurious POP AX at tsrinit entry
JMP does not push anything on the stack. The POP AX at the start of tsrinit consumes the DOS initial return address (0000h) that was pushed by DOS at program load — this is harmless in practice but fragile and unnecessary.

Hi,
1. OK, I thought the 02h/82h variants are only differ in the expected data type (that is 00h/80h expects pixel data while 02h/82h expects byte data).
2. I cannot confirm this hanging problem. It works correctly on my Intel Pentium B940, I7-3632QM and I7-4770K both with X-VESA and FALSSAN3. So some other conditions have to be present on your system(s) that cause infinite loops.
It is not true that 'generally' port 3DAh does not behave as a standard VGA status register (at least it behaves as such on all of my tested Intel GFX systems). More feedback from others with Intel integrated GFX are welcome to investigate this issue further.

@Edit:
Here is my test video from my i7-3632QM Ivy Bridge system (as can be seen at 1st run there is no v-sync in either X-VESA or FALSSAN3 but after running VSYNCFIX v-sync works in both):
https://youtu.be/yolIVmB-ZwE
(BTW, Have you just read about this infinite loop problem somewhere or you actually tested and experienced it?)

3.I do not think monochrome systems are practically relevant in the context of this TSR 😀
4. Yes, but according to VBE specification the content of BL is not defined at output (only BH that is not modified). Also in case of many VBE functions it is explicitly stated that "All other registers are preserved" but Function 07 is NOT one of them. So I do not think and I also do not experience that software would rely on it.
5. Yep, it could be fixed.

Website, Youtube
Falcosoft Soundfont Midi Player + Munt VSTi + BassMidi VSTi
VST Midi Driver Midi Mapper
x86 microarchitecture benchmark (MandelX)

Reply 241 of 258, by ockiller

User metadata
Rank Newbie
Rank
Newbie

I tested NEWAX 0.11 on the Quadro FX540 (GF6), and it still installs without forcing. Here is the status:

Details
Nvidia kEpler/maxWell/pAscal fiX - NEWAX 0.11� - NVIDIA mode
PCI version: 3.0
PCI specification: 001
PCI buses: 045
Original Logical Scanline Length (4F06h): Supported
Original Display Start Address/Panning (4F07h): Supported
Nvidia graphic card: Detected
PCI_ID: 10DE_014E - Revision: A2 - SUBSYS_ID: 10DE_02D1
Bus number: 042 - Device: 00 - Function 0
NEWAX: Installed
One page mode: Disabled
VESA 2.0: Disabled
VBE/PMI: Disabled
Vsync status: Default

Also, here is the status for the RTX 4060 Ti:

Details
Nvidia kEpler/maxWell/pAscal fiX - NEWAX 0.11� - NVIDIA mode
PCI version: 3.0
PCI specification: 001
PCI buses: 045
Original Logical Scanline Length (4F06h): Fail
Original Display Start Address/Panning (4F07h): Fail
Nvidia graphic card: Detected
PCI_ID: 10DE_2803 - Revision: A1 - SUBSYS_ID: 10B0_F314
Bus number: 004 - Device: 00 - Function 0
NEWAX: Installed
One page mode: Disabled
VESA 2.0: Disabled
VBE/PMI: Disabled
Vsync status: Default

I've tested VSYNCFIX on the FX540 and it does fix the flickering on X-VESA and Quake, but not Duke3D.

Reply 242 of 258, by Marco Pistella

User metadata
Rank Member
Rank
Member

System: Asus X556UA
CPU: DualCore Intel Core i5-6200U, 2800 MHz (28 x 100)
Chipset: Intel Skylake-U IMC
GPU: Intel Skylake-U GT2 - Integrated Graphics Controller
PCI_ID: 8086-1916 / 1043-1C7D (Rev 07)

After loading VSYNCFIX.COM FALSSANI.EXE hangs the system.

Reply 243 of 258, by Falcosoft

User metadata
Rank l33t
Rank
l33t
Marco Pistella wrote on 2026-05-23, 10:32:
System: Asus X556UA CPU: DualCore Intel Core i5-6200U, 2800 MHz (28 x 100) Chipset: Intel Skylake-U IMC GPU: Intel Skylake-U GT2 […]
Show full quote

System: Asus X556UA
CPU: DualCore Intel Core i5-6200U, 2800 MHz (28 x 100)
Chipset: Intel Skylake-U IMC
GPU: Intel Skylake-U GT2 - Integrated Graphics Controller
PCI_ID: 8086-1916 / 1043-1C7D (Rev 07)

After loading VSYNCFIX.COM FALSSANI.EXE hangs the system.

Neither of the above listed systems are Sandy, Ivy Bridge or Haswell 😀
So the problem must be present on Broadwell+ systems.

I explicitly stated that I experienced the v-sync problem
and tested the fix on Sandy, Ivy Bridge, Haswell.
And you said it caused infinite loops on Sandy, Ivy Bridge, Haswell:

On many Intel integrated GPUs (SandyBridge, IvyBridge, Haswell and later) port 3DAh does not behave as a standard VGA status register. The vsync loop will hang indefinitely— ironically on exactly the hardware you mentioned as having vsync problems.

Then I said I could not confirm the problem (on SandyBridge, IvyBridge, Haswell).
And finally you sent the results of Skylake systems. But your tested systems are not related to my original claims since they are later than Haswell.

Overall according to the test results so far the situation is this:
On SandyBridge, IvyBridge, and Haswell port 3DAh does behave as a standard VGA status register and thus the v-sync TSR can work.
On later Broadwell/Skylake+ systems 3DAh does NOT behave as a standard VGA status register and thus the v-sync TSR cannot work (resulting in infinite loops).

BTW, SandyBridge, IvyBridge, and Haswell are the last really relevant systems in terms of native DOS VESA VBE usage since as zyzzle reported on your X-VESA topic on Broadwell/Skylake+ systems LFB write-combining and even some VGA compatibility are seriously broken.

Website, Youtube
Falcosoft Soundfont Midi Player + Munt VSTi + BassMidi VSTi
VST Midi Driver Midi Mapper
x86 microarchitecture benchmark (MandelX)

Reply 244 of 258, by Falcosoft

User metadata
Rank l33t
Rank
l33t

Here is another fix for SandyBridge, IvyBridge, and Haswell integrated GFX systems:

The attachment RESETDAC.zip is no longer available

In case of some programs that use VESA VBE modes with 8-bit DAC on returning to text mode you can get a dark/faint screen and seemingly only a restart can help. It's because according to specification returning from VBE mode the DAC should be set to default state but Intel integrated GFX does not do this. So if the program does not reset the DAC to 6-bit on exit you get this dark/faint screen. The above little utility resets the DAC so you can get back the normal/brighter screen.
Here you can see an example about the problem:
https://youtu.be/06F1SNhS0PQ?si=nkYZ61fmalJ8VS7M&t=262

Here is an example benchmark program (PERF.EXE - it needs available dos4gw in order to work) that demonstrates the above described behavior on Intel GFX systems:

The attachment PERF.zip is no longer available

Website, Youtube
Falcosoft Soundfont Midi Player + Munt VSTi + BassMidi VSTi
VST Midi Driver Midi Mapper
x86 microarchitecture benchmark (MandelX)

Reply 245 of 258, by Marco Pistella

User metadata
Rank Member
Rank
Member

NEWAX 0.11.1 - Beta test release
NEWAX 0.11.1 introduces an improved Nvidia card detection routine that better distinguishes supported (G80 and later) from unsupported (pre-G80) hardware.
The previous detection method produced false positives on some pre-G80 cards (GeForce 6200 and Quadro FX 540 confirmed). The new routine uses VESA function 4F06h as an oracle to verify whether writing to CRTC register 3Bh actually affects the scanline length — a behavior that is only possible on G80 and later architectures where the extended CRTC registers are properly implemented.
The executable is attached to this post. Source code will be published on GitHub with the final release.
This release is aimed at all testers, but particularly at owners of pre-G80 Nvidia cards.
Expected behavior:

Pre-G80 cards (GeForce 6 series and earlier): NEWAX should refuse installation with the message "Incompatible Nvidia graphic card"
G80 and later (GeForce 8 series through current): NEWAX should install correctly as before

Please run NEWAX /S and post your results including the full output. PCI_ID, revision and SUBSYS_ID are essential for building the compatibility database.
Thank you to everyone participating in the testing.

The attachment NEWAX0111.ZIP is no longer available

Reply 246 of 258, by DoZator

User metadata
Rank Member
Rank
Member
Marco Pistella wrote on Yesterday, 09:21:
NEWAX 0.11.1 - Beta test release NEWAX 0.11.1 introduces an improved Nvidia card detection routine that better distinguishes sup […]
Show full quote

NEWAX 0.11.1 - Beta test release
NEWAX 0.11.1 introduces an improved Nvidia card detection routine that better distinguishes supported (G80 and later) from unsupported (pre-G80) hardware.
The previous detection method produced false positives on some pre-G80 cards (GeForce 6200 and Quadro FX 540 confirmed). The new routine uses VESA function 4F06h as an oracle to verify whether writing to CRTC register 3Bh actually affects the scanline length — a behavior that is only possible on G80 and later architectures where the extended CRTC registers are properly implemented.
The executable is attached to this post. Source code will be published on GitHub with the final release.
This release is aimed at all testers, but particularly at owners of pre-G80 Nvidia cards.
Expected behavior:

Pre-G80 cards (GeForce 6 series and earlier): NEWAX should refuse installation with the message "Incompatible Nvidia graphic card"
G80 and later (GeForce 8 series through current): NEWAX should install correctly as before

Please run NEWAX /S and post your results including the full output. PCI_ID, revision and SUBSYS_ID are essential for building the compatibility database.
Thank you to everyone participating in the testing.

The attachment NEWAX0111.ZIP is no longer available

Hello. I tested this on a G70 and it seems to be working:

Nvidia kEpler/maxWell/pAscal fiX - NEWAX 0.11.1а - NVIDIA mode
Nvidia kEpler/maxWell/pAscal fiX - NEWAX 0.11.1а - NVIDIA mode
PCI version: 3.0
PCI specification: 001
PCI buses: 006
Original Logical Scanline Length (4F06h): Supported
Original Display Start Address/Panning (4F07h): Supported
Nvidia graphic card: Detected
NEWAX support: Incompatible Nvidia graphic card detected
PCI_ID: 10DE_009D - Revision: A1 - SUBSYS_ID: 10DE_0322
Bus number: 001 - Device: 00 - Function 0
NEWAX: Not installed

I would also like to ask you something at the same time: in your opinion, is it possible to use TSR to override the monitor's EDID under DOS (The first 128 bytes of the EDID that affect the screen refresh rate under DOS, with DVI connection, on GeForce 6800 cards and later? Where information about the video mode and refresh rate is taken from "EDID - > Detailed Data -> Preferred Timing Block"). It could look something like this: TSR.EXE /EDID=example.(bin\dat) and it would load the first 128 bytes of the EDID file and/or redefine only what the monitor sends to the video card when connected via DVI (i.e., only the data from the "Preferred Timing Block"). To make the new EDID take effect, simply switch the video mode or turn the monitor on and off.

The fact is that currently, in order to change the refresh rate in any DOS program or game, when using DVI connectivity, on nVidia cards based on NV40 (and above), as well as on integrated Intel graphics, regardless of the graphics mode selected in the game (whether it's 320x200 or 800x600), you need to flash a modified EDID to the monitor. For Quake, for example, 72hz is optimal, as the original Quake has a 72FPS limit and always enables vertical sync by default (vid_wait=2 and vid_nopageflip=0), resulting in a very smooth image (but it jitters at 60hz because 60hz and 72FPS cannot be synchronized). For Duke3D, for example, 120hz is well suited, so that the picture looks very smooth and in general, each game has its own specific frequency, depending on the FPS). Instead of flashing the monitor (using PowerStrip, for example), you can also use a hardware EDID emulator that supports different EDID profiles and is connected between the monitor and the video card, but I have a different question: is it possible to override the EDID for DVI connections programmatically using TSR (while the TSR is in memory)? I think this would be a very convenient option. Thank you.

Reply 247 of 258, by ockiller

User metadata
Rank Newbie
Rank
Newbie

I confirm it now refuses to install on the Quadro FX 540. I don't put the new status information as it's pretty much the same as last time.

Reply 248 of 258, by Marco Pistella

User metadata
Rank Member
Rank
Member

Hi DoZator, thank you for testing — G70 confirmed as correctly detected as incompatible, exactly as expected.
Also a thank you to ockiller for confirming the fix on the Quadro FX 540.
Regarding the EDID override question: I have already worked on this exact problem. Here is the project:
https://github.com/Marco-Pistella/IPEREDID
However I have to be honest about the limitations: on DVI connections with G80 and later Nvidia cards the approach is unlikely to work. The key question is whether the VBIOS calls INT 10h 4F15h internally during 4F02h to read the EDID before programming the video timings — if it does, IPEREDID intercepts that call and works. If instead the VBIOS reads the EDID directly via I2C hardware without going through 4F15h, IPEREDID is never involved in the process and has no effect.
On G80+ with DVI my expectation is the latter — the VBIOS reads the EDID directly at hardware level, bypassing any software interception. On analog VGA connections and older hardware the situation may be different.
For your specific use case on GeForce 6800 and later with DVI, a hardware EDID emulator remains the most reliable solution. IPEREDID is worth trying but I would not expect it to work on that configuration.

If you want a detailed analysis of your monitor's EDID data, X-VESA includes a complete EDID inspector accessible via the F9 key

Reply 249 of 258, by Falcosoft

User metadata
Rank l33t
Rank
l33t
ockiller wrote on 2026-05-23, 09:47:

...
I've tested VSYNCFIX on the FX540 and it does fix the flickering on X-VESA and Quake, but not Duke3D.

Hi,
I have checked Duke3D and it is a special case. It seems it never used the modified VSYNCFIX code path since:
1. If in the ModeAttributes field bit 5 is not set (meaning the video mode is VGA compatible) then Duke3D does not use Function 07h with BL = 80h but uses its own code for handling v-sync.
2. If Function 0Ah is supported then it bypasses int 10h calls and uses the VBE 2.0 Protected Mode Interface.

Here is a version of VSYNCFIX that tries the mitigate the above described 2 problems:

The attachment VSYNCFIX02.zip is no longer available

According to my tests it works with Intel SandyBridge, IvyBridge, and Haswell as well as with Geforce 6600.
While v-sync works this way I experienced wild frame rate fluctuations between 60 and 120 FPS that makes movement slower/faster as the frame rate changes. But the exact same problem is also present with NEWAX and Duke3D.

Website, Youtube
Falcosoft Soundfont Midi Player + Munt VSTi + BassMidi VSTi
VST Midi Driver Midi Mapper
x86 microarchitecture benchmark (MandelX)

Reply 250 of 258, by LSS10999

User metadata
Rank Oldbie
Rank
Oldbie

NEWAX 0.11.1 correctly installs on my RTX A4000. No apparent regressions in this part.
Did some more tests with this version and found the following.

1. If /2 is being used (forcing VBE2.0), attempting to detect resolution in X-VESA resulted in a loss of video signal. Without /2 (VBE3.0) no issue happens. This is without using /M.
2. In VBETEST, some resolutions in Banked mode may not clean the video buffer properly, resulting in garbage when it transitions from horizontal scrolling test to vertical scrolling test. The following resolutions are affected: 800x600, 1024x768, both 8-bit and 32-bit.
This issue does not manifest in other resolutions in Banked mode, and all resolutions in Linear mode do not have this issue.
3. FALSSAN3 works, but at higher resolutions, 16MB of usable VRAM is likely not enough to draw the test image, as starting with 1280x1024x32, the image is missing the lower portion, with the missing area completely black (no garbage).
4. Forcing more memory with /M, such as /M:32768, allowed FALSSAN3 to draw everything at 1920x1080x32, and the test works without apparent garbage. However, as soon as the program exits, the monitor signal drops down to 640x480, and I can no longer access higher resolutions anymore.

EDIT: Re-tested 2-4 without /2 and there's no difference. The good part, however, is that VBETEST virtual resolution (scrolling) tests in 32-bit modes now works without /2 (Double Buffering still doesn't work yet).

Reply 251 of 258, by Marco Pistella

User metadata
Rank Member
Rank
Member

Hi LSS10999, thank you for the detailed report.
1. This is expected behavior — when X-VESA detects VESA 2.0 it treats it the same as VESA 3.0 retest unlimited, since with VESA 2.0 there is no reliable upper VRAM boundary from 4F00h. This is a known behavior already documented on the A4000.
2. I will investigate.
3. Expected.
4. This is likely caused by the GPU using the VRAM area above 16MB for internal data storage — possibly including a cached copy of the monitor EDID. Forcing /M:32768 overwrites that area, corrupting the internal data. On the next mode change the VBIOS cannot find a valid EDID and falls back to 640×480. — /M should be used with caution on this card.

Reply 252 of 258, by Falcosoft

User metadata
Rank l33t
Rank
l33t

Here is another experimental version for exclusively Duke3D and older NVIDIA cards that are not supported by NEWAX.
This version uses a code path that is never used by NVIDIA cards with Duke3D by default since NVIDIA VBIOS does not report high resolution VESA modes as VGA compatible.
According to my tests on Geforce 6600 this code path avoids the slower/faster movement due to FPS fluctuations that can be experienced both with NEWAX and VSYNCFIX 0.2.
But to tell you the truth it seems for Duke 3D the best overall solution is the original one used by MSKVBEF7 and NEWAX /1.

The attachment VSYNCFIX02b.zip is no longer available

BTW, both VSYNCFIX 0.2 and VSYNCFIX 0.2b should be tested up to 1024x768 since it seems Duke3D requires at least 3 pages to produce flicker free results and by default from 1280x1024 only 2 pages are reported as available on NVIDIA.

Website, Youtube
Falcosoft Soundfont Midi Player + Munt VSTi + BassMidi VSTi
VST Midi Driver Midi Mapper
x86 microarchitecture benchmark (MandelX)

Reply 253 of 258, by ockiller

User metadata
Rank Newbie
Rank
Newbie
Falcosoft wrote on Yesterday, 19:21:

BTW, both VSYNCFIX 0.2 and VSYNCFIX 0.2b should be tested up to 1024x768 since it seems Duke3D requires at least 3 pages to produce flicker free results and by default from 1280x1024 only 2 pages are reported as available on NVIDIA.

Interesting! Indeed up to 1024x768 I notice that the flickering is far less pronounced, either without any fix or with VSYNCFIX 1 and 2b (which don't have any visible effect on my Quadro FX 540). VSYNCFIX 2 solves the remaining flickering but as you noticed the game is in a kind of variable slow motion.

Falcosoft wrote on Yesterday, 19:21:

But to tell you the truth it seems for Duke 3D the best overall solution is the original one used by MSKVBEF7 and NEWAX /1.

Agreed. And as I got interested on the subject thanks to all the new discoveries, I looked at your source and was surprised that MSKVBEF7 doesn't do any hacking regarding function 07h anymore, and thus doesn't do anything specific to some problematic nVidia generations. It just seems to be a good fix for any relatively modern machine with fast CPU/RAM and bus transfer speed I guess. Just to say that your tool's name is a bit misleading and doesn't do it justice IMHO 😉

Reply 254 of 258, by Marco Pistella

User metadata
Rank Member
Rank
Member

NEWAX Updated v0.12 (beta)
- Added 4F07h BL=02h: set display start address, linear offset, byte granularity
- Added 4F07h BL=82h: set display start address during retrace, linear offset, byte granularity
- Added 4F07h BL=04h: get display start address status (returns completed)
- Improved Detect_Supported_Nvidia: replaced XOR FFh CRTC test with 4F06h oracle,
eliminating false positives on pre-G80 hardware (GeForce 6200, Quadro FX 540 confirmed)
- Fixed Quake and VBETEST compatibility via complete 4F07h implementation

https://github.com/Marco-Pistella/NEWAX

Reply 255 of 258, by DoZator

User metadata
Rank Member
Rank
Member
Marco Pistella wrote on Yesterday, 14:19:

Hi DoZator, thank you for testing — G70 confirmed as correctly detected as incompatible, exactly as expected.

Here's another fresh batch of tests (on the new version):

GeForce 7300

Nvidia kEpler/maxWell/pAscal fiX - NEWAX 0.12.á - NVIDIA mode
Nvidia kEpler/maxWell/pAscal fiX - NEWAX 0.12.á - NVIDIA mode
PCI version: 3.0
PCI specification: 001
PCI buses: 006
Original Logical Scanline Length (4F06h): Supported
Original Display Start Address/Panning (4F07h): Supported
Nvidia graphic card: Detected
NEWAX support: Incompatible Nvidia graphic card detected
PCI_ID: 10DE_01D1 - Revision: A1 - SUBSYS_ID: 1043_81F4
Bus number: 001 - Device: 00 - Function 0
NEWAX: Not installed

GeForce 6200TC

Nvidia kEpler/maxWell/pAscal fiX - NEWAX 0.12.á - NVIDIA mode
Nvidia kEpler/maxWell/pAscal fiX - NEWAX 0.12.á - NVIDIA mode
PCI version: 3.0
PCI specification: 001
PCI buses: 006
Original Logical Scanline Length (4F06h): Supported
Original Display Start Address/Panning (4F07h): Supported
Nvidia graphic card: Detected
NEWAX support: Incompatible Nvidia graphic card detected
PCI_ID: 10DE_0161 - Revision: A1 - SUBSYS_ID: 1458_3415
Bus number: 001 - Device: 00 - Function 0
NEWAX: Not installed

GeForce PCX 5900

Nvidia kEpler/maxWell/pAscal fiX - NEWAX 0.12.á - NVIDIA mode
Nvidia kEpler/maxWell/pAscal fiX - NEWAX 0.12.á - NVIDIA mode
PCI version: 3.0
PCI specification: 001
PCI buses: 006
Original Logical Scanline Length (4F06h): Supported
Original Display Start Address/Panning (4F07h): Supported
Nvidia graphic card: Detected
NEWAX support: Incompatible Nvidia graphic card detected
PCI_ID: 10DE_00FB - Revision: A2 - SUBSYS_ID: 1043_8176
Bus number: 001 - Device: 00 - Function 0
NEWAX: Not installed
Marco Pistella wrote on Yesterday, 14:19:
Regarding the EDID override question: I have already worked on this exact problem. Here is the project: https://github.com/Marco […]
Show full quote

Regarding the EDID override question: I have already worked on this exact problem. Here is the project:
https://github.com/Marco-Pistella/IPEREDID
However I have to be honest about the limitations: on DVI connections with G80 and later Nvidia cards the approach is unlikely to work. The key question is whether the VBIOS calls INT 10h 4F15h internally during 4F02h to read the EDID before programming the video timings — if it does, IPEREDID intercepts that call and works. If instead the VBIOS reads the EDID directly via I2C hardware without going through 4F15h, IPEREDID is never involved in the process and has no effect.
On G80+ with DVI my expectation is the latter — the VBIOS reads the EDID directly at hardware level, bypassing any software interception. On analog VGA connections and older hardware the situation may be different.
For your specific use case on GeForce 6800 and later with DVI, a hardware EDID emulator remains the most reliable solution. IPEREDID is worth trying but I would not expect it to work on that configuration.

If you want a detailed analysis of your monitor's EDID data, X-VESA includes a complete EDID inspector accessible via the F9 key

That's very interesting, thank you for sharing. Thank you for the detailed explanation. I tried "IPEREDID" and it initially rejected my corrected EDID, which had previously been successfully tested on the monitor itself, but after reducing it from 256 to 128 bytes (by removing the "CEA Extension block"), everything seemed to load correctly:

IperEDID V1.1 by M.Pistella (15/01/2026)

Status: Controller Load EDID Override Disable BIOS Disable Monitor
----------------------------------------------------------
0 YES YES NO NO
1 YES YES NO NO
2 YES YES NO NO
3 YES YES NO NO
4 YES YES NO NO
5 YES YES NO NO
6 YES YES NO NO
7 YES YES NO NO

And the utility "X-VESA" by pressing "F9" recognized the loaded EDID and showed parameters that clearly refer only to it (which confirms the correctness of loading a new EDID). However, on video modes in DOS programs it did not affect in any way. If I did everything correctly and did not miss something, then most likely, as you wrote earlier, IPEREDID does not have an impact (In this case).

I was also thinking about how it would work if I temporarily disabled I2C (by convincing the VBIOS that the monitor does not support this connection), and if it would switch to an alternative compatibility mode. I assume that nVidia may have implemented backup mechanisms in the VBIOS code in case the I2C connection is not supported by the monitor or if I2C is not working for other reasons. At least the "DDC/CI" feature is present in the monitor's settings and is enabled by default. Probably VBIOS prefers I2C, if possible. But what will happen if there is no such possibility?

In addition, I noticed another interesting feature that can help in this case. Any EDIDs support up to four "Preferred Timing Block" blocks (According to the specification, it is permissible to allocate only two blocks for this purpose, but in fact you can also allocate three or even four). And these four blocks can be used as four different profiles (with different frequencies and resolutions). Here's an example of an EDID monitor that uses two blocks at once:

The attachment EDID_CHD.PNG is no longer available

I currently have an EDID monitor with two preferred sync blocks (with different resolutions and frequencies). So, I noticed that NVIDIA cards starting with NV40 and above always select the first block in DOS; Intel's integrated graphics prefer the second block (which has a higher resolution); and, surprisingly, the GeForce PCX 5900 also prefers the second block in DOS! This raises the question: can we use TSR to force video cards (NV40 and above) to select a specific (required) preferred synchronization block (one of two, three, or four)? If it is possible, it will be enough to flash the monitor with EDID with two - four blocks and will get four different image profiles (With different frequencies and resolutions) and they can be switched using TSR. Is it possible?

Reply 256 of 258, by LSS10999

User metadata
Rank Oldbie
Rank
Oldbie
Marco Pistella wrote on Today, 12:11:
NEWAX Updated v0.12 (beta) - Added 4F07h BL=02h: set display start address, linear offset, byte granularity - Added 4F07h BL=82h […]
Show full quote

NEWAX Updated v0.12 (beta)
- Added 4F07h BL=02h: set display start address, linear offset, byte granularity
- Added 4F07h BL=82h: set display start address during retrace, linear offset, byte granularity
- Added 4F07h BL=04h: get display start address status (returns completed)
- Improved Detect_Supported_Nvidia: replaced XOR FFh CRTC test with 4F06h oracle,
eliminating false positives on pre-G80 hardware (GeForce 6200, Quadro FX 540 confirmed)
- Fixed Quake and VBETEST compatibility via complete 4F07h implementation

https://github.com/Marco-Pistella/NEWAX

Tested this new build on my RTX A4000. Double Buffering test in VBETEST now works without /2.

The garbage issue I reported with Banked 800x600 and 1024x768 at both 8-bit and 32-bit still happens as before (regardless of /2).
- With 8-bit, when transitioning to vertical scrolling test, stuffs previously drawn in horizontal scrolling test stays on screen, with new stuffs (vertical lines) being drawn on top of them, resulting in a total mess (though scrolling itself works).
- With 32-bit, when transitioning to vertical scrolling test, stuffs previously drawn in horizontal scrolling test stays on screen, but new stuffs will completely overwrite them leaving nothing of the previous test remains.

However, during a few test attempts with Banked 1024x768x32, I noticed the vertical scrolling test would abort when I press a key. It only happened like 2-3 times but after doing a few tests with other resolutions (where the abort did not happen), I no longer encounter the abort with this particular mode. Not sure what kind of combinations might have triggered it.

Reply 257 of 258, by LSS10999

User metadata
Rank Oldbie
Rank
Oldbie
Marco Pistella wrote on Yesterday, 14:19:
Regarding the EDID override question: I have already worked on this exact problem. Here is the project: https://github.com/Marco […]
Show full quote

Regarding the EDID override question: I have already worked on this exact problem. Here is the project:
https://github.com/Marco-Pistella/IPEREDID
However I have to be honest about the limitations: on DVI connections with G80 and later Nvidia cards the approach is unlikely to work. The key question is whether the VBIOS calls INT 10h 4F15h internally during 4F02h to read the EDID before programming the video timings — if it does, IPEREDID intercepts that call and works. If instead the VBIOS reads the EDID directly via I2C hardware without going through 4F15h, IPEREDID is never involved in the process and has no effect.
On G80+ with DVI my expectation is the latter — the VBIOS reads the EDID directly at hardware level, bypassing any software interception. On analog VGA connections and older hardware the situation may be different.
For your specific use case on GeForce 6800 and later with DVI, a hardware EDID emulator remains the most reliable solution. IPEREDID is worth trying but I would not expect it to work on that configuration.

If you want a detailed analysis of your monitor's EDID data, X-VESA includes a complete EDID inspector accessible via the F9 key

I'm interested in the EDID part as well. Since I mainly use HDMI and DP connections I noticed these behaviors with my monitor (ASUS XG27UQR).

1. For nVidia cards, the first timing is preferred, though it'll look for other timings if the first timing is not compatible with the signal spec. My monitor has 4K 60Hz as the first timing with 1440p 60Hz and 120Hz as secondary ones which older cards such as Fermi might pick up.
2. 1920x1080 gets a special black border treatment with Fermi and also AMD Northern Islands. Other resolutions e.g. 1680x1050 and 1920x1200 work without issues with Fermi, but Northern Islands only permits a select few resolution and refresh rate combinations for DOS (VGA) output (1152x864 75Hz was such an example). Some timings defined in EDID (be it primary or secondary) can be recognized and utilized by VESA drivers such as VBEMP in Windows, however.
3. The aforementioned behaviors (in 2) no longer hold true since Kepler and AMD Southern Islands. 1920x1080 outputs correctly on both without black borders.
4. My monitor's EDID holds only data up to 4K 60Hz that would be up to HDMI 2.0 and DP 1.2 specs. While the monitor supports DP 1.4 (with DSC/HDR/G-Sync), it doesn't have any EDID data regarding those. If I enable EDID Emulation in Windows using exported EDID data, I lose access to features higher than DP 1.2. EDID Emulation is only officially available on workstation video cards and is useful when using output switches among several PCs (notably to prevent Windows from detaching the screen when switched away which would lead to rearrangement of windows and icons, as well as possible misbehaviors of running full-screen programs).
5. My monitor doesn't support 144Hz with lower resolutions such as 1080p by default, regardless of HDMI 2.0 or DP 1.4 ports. Using reprogrammed HDMI EDID dongles with correct data, it's possible to make 1920x1080 144Hz available and with Kepler and Souther Islands I can even make DOS and Windows (VBEMP) output everything at 144Hz. Right now I only have tools to reprogram HDMI EDID dongles. I haven't found anything similar for DP connections at the moment.

EDIT: I should add that on newer video cards (since Kepler and Southern Islands), in VGA/VESA environments, once the BIOS start outputting at the preferred timing read from EDID, they rarely renegotiate output timings of the display connection when setting new modes, and would instead upscale everything smaller than the current resolution so the monitor won't actually go blank (switching to another resolution/timing per OSD). At least this is the case with HDMI/DP connections, and perhaps DVI also.

Last edited by LSS10999 on 2026-05-25, 16:00. Edited 2 times in total.

Reply 258 of 258, by Marco Pistella

User metadata
Rank Member
Rank
Member

@DoZator

First of all, thank you for your detailed testing and for the NEWAX reports you posted earlier — they were extremely useful.
Your observations about EDID behaviour on NVIDIA cards pushed me to investigate the problem more deeply, and I think the following technical breakdown may help clarify what is really happening under DOS.

1) VBE function 4F02h does seem to adapt video timings based on the monitor’s EDID
This behaviour is reproducible on several NVIDIA cards (e.g., GT 1030):
when a VESA mode is set through 4F02h, the refresh rate is adjusted according to the monitor’s EDID capabilities.
So the VBIOS clearly has access to EDID data at that moment.

2) But where does 4F02h get the 128‑byte EDID block from?
EDID is always 128 bytes (or 256 with extensions), and the I²C/DDC protocol requires reading it sequentially.
You cannot “peek” individual bytes; you must have a full 128‑byte buffer available.

So the VBIOS must have a place in real‑mode memory where it stores the EDID.

3) It cannot use the application’s stack
I initially suspected that the VBIOS might temporarily borrow the caller’s stack, but this is impossible in practice:

many DOS programs (e.g., Quake) have extremely small stacks (sometimes < 50 bytes)

NEWAX’s tracing confirms that the VBIOS uses the caller’s SS:SP for push/pop

therefore, the VBIOS cannot allocate a 128‑byte EDID buffer on the caller’s stack

So the EDID must be stored elsewhere, not on the application stack.

4) The Intel HD VBIOS provides the key insight
On an Intel HD system connected to a Samsung SyncMaster 943, I dumped the video BIOS (via X‑VESA F10+S).
Inside the ROM image, at offset C000:5F80h, the full 128‑byte EDID block of the monitor is present.

This proves that:

the Intel VBIOS reads the EDID during initialization

it unlocks the shadowed C000h region

it writes the EDID into the ROM shadow

then it locks the region again

This gives the VBIOS a permanent, easily accessible EDID copy in real‑mode memory.

5) Intel can do this because it is an integrated GPU
An integrated GPU knows exactly how the chipset handles shadow RAM, so it can safely:

unlock C0000h–CFFFFh

write the EDID

re‑lock the region

This avoids the need for any RAM allocation during 4F02h.

6) Therefore, when 4F02h needs EDID data, it simply reads it from the ROM shadow
No I²C access is needed during mode‑setting.
No temporary buffer is needed.
Everything is already stored in C000h.

This explains why Intel’s VBE implementation can adapt timings dynamically without touching the caller’s stack.

7) But a discrete NVIDIA card cannot modify the ROM shadow
Unlike Intel, a discrete NVIDIA GPU:

cannot unlock the system’s shadow RAM

cannot write into C000h

cannot store the EDID in the ROM image

So it must store the EDID somewhere else.

My current hypothesis is that NVIDIA copies the EDID into VRAM, most likely in the region above 16 MB (or between 14336 KB and 16384 KB), during the very early initialization phase (the JMP to C000:0003h).

This would give the VBIOS a private buffer for the EDID without touching system RAM.

😎 Evidence supporting the “EDID in VRAM” hypothesis
User LSS10999 reported that when experimenting with NEWAX to force VRAM sizes beyond 16 MB, the monitor would:

lose sync

or fall back to 640×480

This strongly suggests that some part of the high VRAM region is used internally by the VBIOS — possibly for:

EDID storage

timing tables

mode descriptors

If that region is overwritten, the VBIOS loses the data it relies on for mode‑setting.

This is not a proof, but it is a very strong correlation.

Conclusion
My working theory is:

Intel stores the EDID in the ROM shadow (C000h).

NVIDIA cannot do that, so it stores the EDID (or its parsed timing tables) in VRAM or in an internal SRAM area.

VBE function 4F02h does not read the EDID via I²C each time; it uses the cached copy created during initialization.

This explains why IPEREDID has no effect in DOS: the VBIOS never re‑reads the EDID after POST.

If this hypothesis is correct, it might even be possible to modify NVIDIA’s cached EDID “on the fly” under DOS by patching the VRAM region where it is stored — without needing a TSR.
But this requires further investigation.

If anyone is interested in digging deeper, I’m absolutely open to collaborate.

@LSS10999
Thank you again for testing the new build on your RTX A4000 — your reports are extremely valuable for understanding how NVIDIA’s VBE behaves across different generations.

* Double Buffering in VBETEST now works without /2

This confirms that the new implementation of VBE function 4F07h (including the linear variants 02h/82h) is now fully compatible with VBETEST’s expectations.

* Banked 800×600 and 1024×768 issues remain unchanged

I have been looking for a possible bug in NEWAX that could explain this behaviour, but so far I haven’t been able to find anything suspicious. I will investigate this more deeply.

The attachment INTELHD_BIOS.ZIP is no longer available