The virtual flat framebuffer driver, or VflatD, was introduced in Windows 95 in order to ease development of display drivers. It was surprisingly poorly documented and the sample drivers did not illustrate its use very well.
A short backgrounder may be in order. Traditional VGA adapters accessed all of their 256KB of video memory through a 64KB aperture at physical address A0000h. Because of the unusual four-plane memory organization, the 64KB aperture was enough for covering four times 64KB, or 256KB. A distinguishing characteristic of Super VGA adapters was that they sported more than 256KB of video memory; perhaps 512KB, perhaps 1MB, perhaps more.
However, accessing that memory was not easy. The 64KB aperture was no longer sufficient to address all video memory. Linear framebuffer access was not always available, in part because it was difficult to use from 16-bit software, in part because mapping a megabyte or more in the 16-megabyte ISA address space was problematic. Super VGA adapters therefore supported bank switching, i.e. controlling which part of the larger framebuffer the 64KB aperture at A0000h accesses. The simplest case was a single read-write “window” which could be positioned with 64KB granularity.
Using banking was quite painful for software, because all drawing algorithms had to be able to switch banks of whatever they were doing. Drawing to a linear framebuffer (a contiguous memory area larger than 64KB) was much simpler, but did not work with Super VGA adapters which only supported banking. To ease the pain, Microsoft shipped VflatD, a virtual device driver (VxD) which emulated a linear framebuffer on top of a banked Super VGA adapter.
The mechanism was relatively simple. VflatD allocated linear address space large enough to cover the actual video memory size. However, this space was not backed with physical memory. Instead, VflatD installed a page fault handler covering the entire area. On the first access (which caused a fault), VflatD calculated the bank number corresponding to the address, selected the desired bank, mapped 64KB at A0000h to a block of linear memory, and removed the page fault handler from that 64KB area.
As long as software was accessing only the memory area corresponding to the currently mapped bank, no page faults were incurred and memory accesses were executed at full speed (not necessarily fast—merely as fast as the hardware allowed). As soon as software attempted to accessed memory outside the currently mapped area, VflatD would select and map a different bank and adjust the mappings. This approach performed reasonably well and greatly simplified the drawing algorithms.
Every driver for a banked Super VGA adapter was expected to use VflatD. For minidrivers utilizing the DIB engine, VflatD was a requirement (for banked modes). Unfortunately, comparing the DDK documentation and actual sample drivers reveals surprisingly large holes.
The documentation did not substantially change since the original Windows 95 DDK release until the end of the Windows 9x line. The DDK documentation isn’t bad per se, but it refers to a file called vflatd.inc which Microsoft never actually shipped (or it was really, really well hidden). As a consequence, the symbolic constants used in documentation can’t be converted to numeric values.
The DDK sample drivers (MINI, FRAMEBUF, S3V) do use VflatD, but in a manner which appears to contradict the documentation. However, careful analysis of the VflatD module shows that the sample code is (as one might expect) correct and the documentation is misleading.
The VflatD documentation provides details for a function called VflatD_Create_Virtual_Frame_Buffer. It is implied that that’s what drivers should be using. However, the sample drivers use the VflatD_Get_Video_Base function instead, even though it’s been declared obsolete ever since the initial Windows 95 DDK! It doesn’t help that the DDK does not provide vflatd.inc, and the drivers therefore declare their own GET_VIDEO_SEL constant to obscure matters further.
VflatD_Get_Video_Base is in fact a less flexible variant of VflatD_Create_Virtual_Frame_Buffer with several restrictions. The bank is assumed to be 64KB at A0000h and the BankSize and BankLocation (EBX/ESI) arguments are therefore not used. The size of the framebuffer is passed (in EAX), but is specified in pages rather than bytes. Aside from these differences, the functions behave the same. For a typical Super VGA, the obsolete VflatD_Get_Video_Base does the job and is slightly easier to call.
For reference, here are the VflatD function IDs which were presumably defined in the missing vflatd.inc:
VflatD_Query 0 VflatD_Get_Video_Base 1 VflatD_Reset 2 VflatD_Create_Virtual_Frame_Buffer 3 VflatD_Create_Physical_Frame_Buffer 4 VflatD_Begin_Linear_Access 5 VflatD_End_Linear_Access 6 VflatD_Query_Bank_Info 7
The above numbers were obtained by disassembling the debug version of VFLATD.VXD for Windows Me and cross-referencing the code with the symbols from the accompanying VFLATD.SYM.
It is apparent that the GET_VIDEO_SEL macro with value of 1 used by DDK sample drivers is in fact a gratuitous alias for VflatD_Get_Video_Base which is mentioned in the DDK documentation.