
Oldschool planar graphics and why they were a good idea - bibyte
https://codeplusplus.blogspot.com/2019/02/oldschool-planar-graphics-and-why-they.html
======
adrianmonk
Another trick I believe you can do with planar graphics is overlays.

Suppose you have 6 bits per pixel. One thing you could do is have 64 colors.
Another thing you could do is use 3 bits for one color palette, giving you 8
colors, but designate one of those colors as a transparency value. If the 3
bits match the transparency color, then refer to the other 3 bits.

This allows you to do stuff like redraw or scroll a lower or upper layer
without changing the bits for the other layer. It takes less processing power
and memory bandwidth to update 3 bits than it does to update all 6.

Oh also, even if the hardware doesn't have an overlay mode, you can make this
happen by filling up your 64-entry color palette carefully.

For example, if you want 000 to be the 3-bit value indicating transparency,
and you want 001 to be pink, you copy the RGB for pink into the palette at
every index that begins with 001. So you set pink in 8 color palette entries
(001000, 001001, 001010, 001011, 001100, 001101, 001110, and 001111). For the
8 colors that make up the other level of your overlay, you just set them once
in the 8 positions that start with your transparency color.

~~~
mrec
Even without overlays, being able to reuse the same bitmap with multiple
stretches of the palette (by combining it with a solid colour as palette
offset) was nice. It got you a bit more variety in the scene when memory was
tight, and memory was always tight.

Back in my greenhorn days on the Amiga, I remember feeling very pleased with
myself for "inventing" (hah!) a cheesy semi-dynamic lighting system using a
1-bit stippled gradient plane to effectively switch the main bitmap between
"bright" and "dark" sub-palettes, at no performance cost.

I'm sure this wasn't original, of course, but back before the Web most
hobbyists were trapped in their own little silos reinventing the wheel over
and over again. It was fun. Then Quake came out with its -ahem- rather better
lightmapping and... yeah, couldn't really kid yourself any more.

~~~
Moru
Yes, I did the same on my Atari, fun times :-)

------
bitwize
Planar graphics was also a thing because of the slow RAM bandwidth of the day.
RAM was fast enough to allow the video hardware to stream a 1bpp image at the
rate needed by the electron beam of a typical CRT -- but higher rates like 4
or 8bpp were troublesome and 24bpp was out of the question. However, by
arranging the data in planar format, you could pull the bits for a single
pixel from more than one RAM chip at a time, and through such parallelism
achieve the much higher throughput it took to display high-color images.
Innovations in the late 80s/early 90s, like high-speed VRAM, made true-color
"chunky" graphics practical.

Of course this also made the Amiga's HAM mode even more impressive, as they
managed to squeeze out 4096-color (effective 12bpp) imagery out of the slow
RAM of the day by allowing each successive pixel to be encoded in six bits by
modifying only one component of the previous pixel (the famous Hold and Modify
technique).

The major downside was that you had to do some computational contortions to
build an on-screen image out of computed pixel data, but of course if you were
lucky enough to have a hardware blitter (pc suxx0rz!), planar graphics was no
impediment to drawing lines or compositing images at arbitrary positions
quickly.

~~~
newnewpdro
Yep, this is consistent with my understanding, I'd never heard the rationale
put forth in the linked post.

------
rasz
They werent, and pretty much signed Amigas death warrant. Planar is a cute
trick when you are moving around static, limited in color shapes on the
screen(less colors less writes), but fails miserably at single pixel
addressing. All of a sudden updating one pixel costs you 5(ocs), 6(ecs) or
8(aga) individual writes! thus no Wolfenstein3d/Doom on Amiga. Commodore
finally tackled this problem 7 months before going bankrupt, just in time as
it ran out of money to actually manufacture new product, while still paying
its CEO better than IBM.

>Imagine a 320x200 screen with 32 colors. If we had padded each pixel out, it
would require 64,000 bytes.

>but you cannot really cut up an array of bytes into 5-bit chunks easily. You
could pad it

Sure you can! Nothing forces you to put full 8 bits of actual memory inside
video address space. You could transparently translate memory accesses between
5/6 bit and 8 bit in the background, mapping 40-48KB real ram area into 64KB
byte addressable window. You could even transparently translate between planar
and "chunky" (Akiko). Those were never technical problems, but a result of a
lack of affluent leadership. Projects at Commodore were mainly driven by
accountants (lets get rid of all the outdated garbage in the storage = C128)
and ignorant non technical execs.

~~~
Retric
Like many optimizations it’s hardware dependent.

As you gain more bandwidth, memory, and computing power you want different
tradeoffs. Look at the history of DirectX for example and you see a huge range
of different approaches show up and then get discarded.

Trying to keep up with this curve takes a lot of resources for R&D which is
why so much consolidation happened.

~~~
rasz
"mapping 40-48KB real ram area into 64KB byte addressable window" is couple
hundred transistors to implement. VGA came out in 1987.

~~~
Retric
That’s not really the issue. With a 16 color pallet and planor graphics you
can update one byte to change 8 pixels from one pallet to another. This also
means you can really cheaply compress images if you only need say 8 colors.

These trick becomes far less useful if you have cycles to spare.

------
nategri
The Apple II's somewhat exotic "hires" mode didn't even HAVE an indexed
palette. Instead you just wrote 1s and 0s for pixels directly to the display
memory, and their _arrangement on the screen_ determined their color. This all
owing to the fact that the Apple II only had color at all due to some crazy
phase-based hacking of the NTSC color standard.

EDIT: Oops I partially messed up this description. The MSB in each byte of the
display memory did set the "palette" (phase, actually, according to Wikpedia)
for each set of 6 pixels. So you could either have blue/orange or green/purple
in that set with the exact color depending on whether or not you had one
alternating pattern of bits or another.

~~~
function_seven
You have any links for this? It sounds both terrifying and clever as hell.

Similar to the Amiga's HAM mode[1], where you could get 4,096 simultaneous
colors, but the restriction was that the succeeding pixel could only differ
from the preceding in just one of the R, G, or B values.

[1] [https://en.wikipedia.org/wiki/Hold-And-
Modify](https://en.wikipedia.org/wiki/Hold-And-Modify)

~~~
dbcurtis
"terrifying and clever" describes a lot of the Woz's work...

So I am a little fuzzy on the NTSC standard, because it has been a while since
I looked at it... but the hack goes something like this:

Monochrome TV puts video on an upper vestigial sideband with the carrier at
(IIRC) 1.25 MHz up from the lower edge of the 6 MHz channel. (The high
frequency parts of the lower sideband of the video signal are whacked off with
a filter.) The FM sound subcarrier is up closer to the top edge, I forget what
the offset is exactly.

Then color came along... so they added a color subcarrier just below the sound
subcarrier. This reduced the bandwidth available for luminance, but got you
color in return. The color subcarrier IIRC is kind of a flavor of independent
sideband, but is really two double sideband signals on the same carrier, 90
degrees out of phase with each other, one skinny, and the other fat but with a
notch filter applied to allow the skinny signal to ride in the middle. Or
something like that.

Anyway... if you send a monochrome signal with high-frequency components (high
frequency == high dot rate) that fall in the range of the color sub-carrier,
you will get color artifacts. This is because the color decoder simply
responds to the rf it is getting, whether on a proper subcarrier or not.

Another thing I used to know but am fuzzy about is I am pretty sure you need
to put out the standard color burst on the back porch of the horizontal sync.
Otherwise, the TV receiver will not sync to the "color subcarrier" that you
are faking with artifacts.

~~~
ddingus
You are correct. Something like a colorburst must be there. Turns out you can
abuse that very considerably. And still get stable, useful displays.

------
Lerc
I once worked on a project that ran 4 monitors off one Amiga.

Using a graphics card to do a byte per pixel main display (polygon + scaled
sprite 3d), and three monochrome displays taken from the red green and blue
output of the Amiga's standard video out. Each of the monochrome displays used
a single bitplane plus shared a random static bitplane. By adjusting the
palette you could individually control which monitor the image appeared on,
how bright it was and how much static interference to display. Various other
failure modes were also added via copper tricks (roll, glitching etc.) without
modifying the base bitmap.

------
tom_
This arrangement is highly questionable, but it does have one advantage,
touched on in the last paragraph: you can write a 1bpp drawing routine that
does whatever you need, and it can deal with any number of planes. Like, if
you've got 4 planes, and you need to draw a line in colour 7, you just use
your 1bpp line drawing routine to draw a 1 in planes 0, 1 and 2, and a 0 in
plane 3.

------
xioxox
I remember working with the Amstrad PCW, which had an interesting layout for
the video memory. The pixels in the 90x32 character monochrome display were
stored in character order. The 1st 8 bytes were the leftmost character, the
next 8 were the character to the right, and so on. This wasn't the only
complexity as there was a lookup table to give the memory location of each of
the 32 screen lines. The advantage of this table was very quick character
scrolling, at the expense of computing the location of individual pixels. It
was rather tricky to write quick Z80 code to draw line with this quirky setup,
but some people managed some rather nice vector games, such as Starglider.

~~~
JdeBP
The BBC Micro had a similar arrangement in some of its screen modes.

~~~
theclaw
I think both machines must use a Motorola 6845 CRT controller, which is
intended for character-based screens. It does not scan the video RAM
sequentially, but in the way described by the GP, (all first char rows, then
all second char rows, etc, with each chars rows stored sequentially in RAM)

~~~
theclaw
I spent some time looking into this and found I was wrong - CRTC does generate
linear addresses but the beeb (and possibly the CPC) translates them to the
character-based screen format in hardware.

------
ChuckMcM
Bit planes are pretty easy to implement in hardware. One of the nice things is
that the bit calculation is the same for each plane so you feed that value,
bit offset, and plane start address into a barrel shifter and out pops the bit
you want. those you gang together into a register and poof you can read them
all at once. The ARM Cortex-M bit mapping memory region does this computation.

It also means you can build things like pixel copy of arbitrary width pixels
with a single bit copy engine running 'n' times.

With memory and transistors getting cheap though, all of that became
unnecessary it seems.

------
miohtama
Does anyone know why VGA ”hacks" 320x240x256 and 320x400x256 modes operated
planar instead of paged like 320x200x256?

It makes sense for less than 8-bit per pixel colour modes, but now for 256
colours.

Pondering this question after 20 years.

~~~
pavlov
I think it had something to do with the 64K segment limit in real mode x86...?

~~~
rasz
If anything it would be ISA VGA being visible thru a 64KB aperture at A0000,
and even that wasnt it. Why would you specifically program VGA into planar
instead of nice "chunky" pages? It was an artifact of the way VGA CRTC worked.

------
pcwalton
> but you cannot really cut up an array of bytes into 5-bit chunks easily

But you can do RGB 565, which is exactly what mobile GPUs do (or used to do,
back when memory cost and bandwidth were more limited).

~~~
boomlinde
Two bytes per pixel for, say, a single 640x256 pixel screen would already use
more RAM than available on a 256k Amiga 1000.

RAM size only ha to double a few times for this to become an entirely outdated
concern, but that's what they had to work with at the time they designed the
chipset. Still no excuse for AGA!

------
magicalhippo
This is like Array of Structures vs Structure of Arrays[1].

As mentioned, with a SoA approach it's much easier to replace a subset of the
entire data. If you have control over the array pointers you could simply swap
pointers, leading to an essentially free update.

Downside is that it's a lot more work (and usually less cache friendly) if you
need to update all the data.

[1]:
[https://en.wikipedia.org/wiki/AOS_and_SOA](https://en.wikipedia.org/wiki/AOS_and_SOA)

~~~
adrianmonk
I guess column-oriented databases are also conceptually similar, though
structure of arrays is certainly a closer analog.

Back in the days of planar graphics, usually cache didn't matter because there
wasn't one. The difference between CPU and memory speeds was not so lopsided
as it is today. Or you could say, memory was fast enough because CPUs were
very slow.

~~~
nicoburns
> I guess column-oriented databases are also conceptually similar, though
> structure of arrays is certainly a closer analog.

Isn't a column oriented database pretty much just an SoA on disk. And a row
oriented database is pretty an AoS on disk. modulo some complexity around
indexes?

------
jabl
How times change. Back in the day OpenGL had a paletted texture extension
(EXT_paletted_textures), but nothing supports it anymore. I guess the extra
indirection doesn't work well with GPU hw architectures?

~~~
lstodd
It's trivially done in shaders, there's nowhere to extend that.

~~~
miohtama
Do game engines still use palettized textures to save memory?

------
patman
This takes me back many years. I remember writing code to display pcx images
from the pcx spec for ega and vga displays. This was pre-web so no help there.
Some of the best fun I've ever had coding.

------
adrianratnapala
I am surprised the reasons for planes being to fit in odd bit sizes. Although
I suppose that is _a_ reason.

Planes are a nice abstraction, because they allow you to use the concept of a
raster surface for all kinds of things. These things might be bits of colour,
but they might be metadata in an image analysis program, or a masks in a
graphics editing program, z-buffers for 3-d graphics, or really anything.

(Admittedly, I am talking about an abstract concept of "plane", whereas the
original article is presumably talking about the concrete behaviour of
hardware.)

------
MultiPlane
I'm glad someone finally explained this! It makes some sense, but I'm curious,
was the combining of the bits of the plane to get the index to look-up done in
hardware? Because it sounds like storing 3 5-bit pixels in the expected way in
2 bytes (with a bit left over) wouldn't be any harder in software than
combining 5 bits from different planes. But if the hardware handled assembling
the various bits, then I guess it would probably be faster. Am I understanding
that correctly?

~~~
dbt00
Even if it was done in software, it was still easier to write against planes
because you had to run on hardware with wildly different hardware
capabilities, so drawing routines were far easier to parameterize over planes
than over various bit packing mechanisms.

~~~
rasz
>wildly different hardware

what do you mean? NES never changed, Amiga was always compatible with itself,
nothing changed.

------
wkearney99
Pfft, you kids with your frame buffers. Try having to reload the display line-
by-line during the blanking interval, like on an Atari 2600.

------
valtism
I believe that this is the same techniques that were covered in the excelent
series "How oldschool graphics worked"[1]

[1]
[https://www.youtube.com/watch?v=Tfh0ytz8S0k](https://www.youtube.com/watch?v=Tfh0ytz8S0k)

------
skocznymroczny
Planar graphics are still a thing, in YUV (YCbCr) formats. The Y component is
usually stored separately and UV are interleaved in a second plane.

------
ngcc_hk
Interesting. First time no graphic no code just English clearly explain
graphic code.

Together with two posts below about ram speed and >64k, seems quite clear.
Thx.

------
snarfy
We stopped where we are at because the eye cannot see more colors. The same
goes for 4K displays. More resolution doesn't make sense. 4K pixels is more
pixels than there are cones in your eyes.

~~~
dTal
Go look at any CIE chart. The human eye is far more sensitive than the
standard sRGB colorspace. For that matter, it's _impossible_ to represent the
full perceptible colorspace with just three colors. And even if you use a wide
gamut, 8 bits per channel is not enough to prevent banding. Particularly over
the full brightness range the eye can perceive, which is considerable. That's
why "HDR" screens are at least 10 bit nowadays. We didn't stop at all.

As for 4k displays - most of those cones are in the center of your FOV, and
eye movement is part of human vision (saccades). That's why 4k VR headsets
still look pixelated. Also, you don't just sit in front of your screen staring
straight ahead like a zombie (at least, I don't). You move your head. You lean
in. By your logic, the edges of a screen shouldn't even be in _color_!

It's like saying a keyboard with more than 10 keys doesn't make sense because
we only have 10 fingers.

