April 20th, 2026
like2 reactions

How did code handle 24-bit-per-pixel formats when using video cards with bank-switched memory?

On the topic of what happens if an access violation straddles multiple pages, Gil-Ad Ben Or wonders how code handled 24-bit-per-pixel formats when using video cards with bank-switched memory. “The issue is that since 64k bytes is not divisible by 3, and you usually need a pixel granularity if you aren’t using some kind of buffering.”

This is referring to an older article about the Windows 95 VFLATD video driver helper which emulated a flat video address space even though the underlying video card used bank-switched memory by mapping the active bank into a location in the address that corresponds to its emulated flat address, and responding to page faults by switching banks and moving the mapping to the emulated flat address of the new bank.

The trick falls apart if somebody makes a memory access that straddles two banks, because that leads to an infinite cycle of bank switching: The CPU raises an access violation on the first bank, and the driver maps that bank in and invalidates the second bank. But since the memory access straddles two banks, then the CPU raises an access violation on the second bank, and the act of remapping that bank causes the first bank to become unmapped, and the cycle repeats.

So how did code deal with pixels that straddles two banks?

The underlying rule is that all accesses to memory must be properly-aligned. No properly-aligned memory access will straddle a page boundary.

Managing this requirement was just the cost of doing business. People who wrote code that accessed video memory knew that they couldn’t use tricks like “read a 32-bit value and ignore the top 8 bits.” If you have a pixel that straddles a boundary, you’ll have to break it up into three byte accesses, or at least a byte access and a word access (where the word access is properly aligned). In practice, it’s not worth the effort to do the work to decide whether to split the pixel as byte+word vs. word+byte, and everybody just did it as three bytes.

Now, if you were operating on an entire row of pixels, you could use aligned 32-bit reads and writes to access the entire row: Copy bytes until the address is 32-bit aligned, and then use 32-bit reads for the bulk of the row, and then copy any leftover bytes at the end. The 32-bit reads will straddle pixel boundaries, but that’s okay because they don’t straddle page boundaries.

In other words, the answer is that they handled it by handling it.

Topics

Author

Raymond has been involved in the evolution of Windows for more than 30 years. In 2003, he began a Web site known as The Old New Thing which has grown in popularity far beyond his wildest imagination, a development which still gives him the heebie-jeebies. The Web site spawned a book, coincidentally also titled The Old New Thing (Addison Wesley 2007). He occasionally appears on the Windows Dev Docs Twitter account to tell stories which convey no useful information.

1 comment

Sort by :
  • Georg Rottensteiner

    Oh boy, I'm getting flash backs to bank switched graphic memory access (under DOS).
    We wrote a game using a 640 x 480 super VGA mode where the full graphic page wouldn't fit into the memory window at $a000:0000. It was tile based, and we wanted to have tile effects like mirror h/v, rotate, etc.
    So you could only access a 64kb page of the memory. This means going over page boundaries having to switch banks in between. Some tiles would straddle these boundaries. Urgh.
    I remember hand crafting assembler routines for every single tile mode.

    I would have killed for...

    Read more