10

VGA framebuffer was fixed to 64kB at A0000h. Right after that there’s MDA/CGA framebuffer at B0000h. I am not sure, but I recall VGA did have to support CGA and its framebuffer, but was there any reason why VGA couldn’t use eg 128kB (ie segments A and B) as linear framebuffer for modes such as 320x240x8b?

ModeX and others do imply all VGA boards must’ve had more than 64kB of video ram on board, but it had to be accessed via bank switching. Since VGA would need to claim ownership of B segment for CGA compatibility (but this is not needed if using VGA display modes), I cannot see any reason why they did resort to bank switching.

2
  • 3
    Use of dual monitors, one VGA and one monochrome/Hercules, was not at all uncommon in the early '90s, in my experience. (I certainly did it for many years myself, and not just for software development. It's handy just like being able to have two terminal windows open is handy now.) By that point monochrome graphics cards and their monitors were very cheap, so adding a second card and monitor was a small part of the computer's total cost.
    – cjs
    Jun 5, 2019 at 0:29
  • 1
    Also note that both EGA and VGA had a way to write into different planes at once with mask registers etc., so it should in theory have been possible to access 4 planes mapped into a single 64 KB segment for a total of 256 KB framebuffer. Though those modes were not popular, so I'm not sure at the moment if there were ever enough bits in the corresponding registers to actually do that.
    – dirkt
    Jun 5, 2019 at 5:43

3 Answers 3

7

The VGA design is inherited directly from the EGA design, though with a few extra features. Most considerations apply equally to both.

Although it is possible to treat the EGA or VGA memory as four banks of 65,536 octets, the EGA was designed to let it be treated more usefully as 65,536 groups of four octets, where each group had a single assigned CPU address. Within each group of eight pixels, each pixel would use one bit taken from each octet. The EGA and VGA have a 32-bit buffer that gets loaded from all four groups of pixels whenever an address is read, and each write will store to each group of 32 pixels a pattern which is based upon the value written, the value of some configuration and parameter registers, and the contents of the buffer.

This made it possible to perform many kinds of read-modify-write operations on a group of pixels at a time. The CPU would read a byte, ignore the result, and then write a value that indicated how the group of bytes should be modified. The display card would then combine the value in the buffer with the value that was read and store the modified result to all 32 bits. This allowed for bytes in display memory to be updated with a single read-modify-write sequence.

Alas, a couple aspects made this design far less useful than it could have been. They largely boil down to the fact that for various technical reasons, reading display memory is extremely slow, and every action on a group of 32 pixels would require four individual read-write sequences. If the computer had enough "main" RAM to maintain a copy of the screen, building the display contents in RAM and blindly outputting to the display would almost always be faster than trying to use the display's hardware to expedite the process. On slow machines the display hardware could offer some speed advantage, but as main-CPU speed increased the extra display hardware became more and more useless.

Still, the designers of the EGA and VGA had expected that the ability to update multiple bytes at once would be useful, and thus designed their architecture to facilitate it.

7

When VGA was designed and released, it had only maximum of 256 kbytes of video memory. The memory of VGA is arranged to have 32-bit interface to the VGA chip to have four byte planes in parallel. Therefore there are only 64k addresses of 32-bit video memory, and data of up to four planes can be accessed with a single CPU access.

The VGA board can be configured for a 128k framebuffer at A0000h, but both 64k segments will access the 64k addresses of video RAM identically. The trick that makes standard Mode 13h look linear is implemented in hardware, it only uses every fourth address of video memory, and automatically selects the plane based on lowest 2 CPU addresses. Unchained modes need manual plane selection in software when writing to video memory. It would have taken extra logic to make the whole video memory look like linear, and this was just not so important as it already was quite complex and it was enough make it compatible with EGA.

So in short, the VGA hardware is made to have four bytes accessible via single CPU address so there are only 64k memory addresses the CPU can access.

3

In the 16-bit 8086, addressing of the memory space was done with a two-register pair Segment:Offset. The Segment register (there were four of them) addressed the high 16 bits of the 20-bit addressable memory, and the Offset register addressed the low 16 bits. So The effective address was computed in the CPU by:

EA = 16 * Segment + Offset

So, in order to address more than 64k of memory at once, software would have to change the segment register as well as the offset. This was very inefficient in the CPU, and it was much better to limit memory block access to 64k at a time. The video card designers recognized this, and built the hardware with bank switching so that software would not have to change the CPU segment register to address the whole display memory.

8
  • Do you have a source for this? I don’t recall MOV reg to seg being really slow on 8088. Quick lookup around internets says it was 2 cycles, same as any MOV between registers. I could imagine it being a bit slower on 286+ with all the segment descriptor magic happening behind the scenes.
    – tuomas
    Jun 4, 2019 at 21:26
  • 1
    @tuomas: Just thought of another reason - it was possible to have multiple display adapters in the same machine simultaneously, so you could (for example) debug a game by running the game on the VGA and the debugger interface on a separate monochrome screen. Jun 4, 2019 at 21:47
  • 1
    Programs which would benefit from a larger framebuffer would be manipulating more than 64K of data anyway, so I doubt the pointer arithmetic is a factor. In any case segment loading is faster than bank switching. Jun 4, 2019 at 21:49
  • 4
    Setting up DS and ES appropriately, then using a segment override prefix and a conditional jump over it solves the problem of addressing more than 64k at a time with minimal code bloat.
    – Leo B.
    Jun 4, 2019 at 22:06
  • 1
    Move between segment register and 16 bit register was always 2 clocks (3 on a 486 and up to 12 or so on a Pentium). From memory somewhat slower (12 on 8088 5 on 286). It only got terrible slow with virtual addressing on a 286.
    – Raffzahn
    Jun 4, 2019 at 22:22

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .