This is still very much a work in progress. So far it's just a place to document some ideas, thoughts and findings.
John Earnest mentions in his proposal
for XO-CHIP
that a theoretical sixteen colours are possible with the plane
opcode:
Encoding is chosen such that it would be possible to provide 4 bitplanes (and thus 16 colors!) in the future should it prove necessary.
However, Octo doesn't implement this theoretical 16-colour feature, and it seems to have been left as an exercise to the reader. This document proposes a concrete specification for the possible colours in XO-CHIP's two additional planes.
Octo has chosen to make the four colours that it does have configurable. Considering the program size contraints of 3.5K / 32K this makes sense; adding the other two bits of colour doubles the size of all image data in your program. But still, programmatically having more colours opens up possibilities that four configurable colours just don't provide, like showing a colourful Mandelbrot set, using colour to indicate different players or enemies, et cetera.
Also, it would be possible to still use two planes, but two different planes
for some sprites, effectively giving those sprites access to a different colour
palette without sacrificing storage space. This means that the colour palette
that we choose should preferably be "useful" when using one, two, three or four
bits of colour, in any plane
permutation.
Things I consider "useful" would for example be:
- Being able to switch palettes to re-use the same sprite for different purposes (the red player and the blue player, the green goblin and the brown goblin)
- Having more vivid colours in another plane than more dull colours. Combined with screen scolling, this allows for a brighter "foreground" and a more subdued "background" that can scroll independently
- The same goes for having a game world with a palette in "earthy" colours with more vivid sprites for entities (players, enemies, pickups)
I thought it valuable for developers implementing this proposal to keep the
least significant plane compatible with standard CHIP-8, which means that in
plane 1
, 0
indicates a non-active pixel (dark) and 1
an active pixel
(light).
Compatibility with Octo's implementation of XO-CHIP is kind of impossible,
because due to its configurability different values in plane 3
can correspond
to any colour. However, we can take a look at the default colours Octo uses:
Bits | Colour |
---|---|
0b00 |
#996600 |
0b01 |
#FFCC00 |
0b10 |
#FF6600 |
0b11 |
#662200 |
As you can see these are fairly warm colours on a spectrum from lighter to
darker. Essentially giving the user four levels of "grayscale", but in a much
less boring palette. There is one issue with this palette though, and that is
that 0b11
is a darker colour than 0b00
, even though we just concluded that
for the CHIP-8 "palette" 0b0
needs to be a non-active pixel. So this colour
would have to be darker than a non-active pixel..? 😄
So trying to get Octo-compatibility out of the box, even in the more liberal sense of using four shades of gray to represent the Octo palette, doesn't really seem to work very well. Combined with Octo's configurability it would seem like a waste of time to worry about this too much. Interpreter developers wanting to support a version of XO-Chip that's really compatible with Octo will have to make the two-bit palette configurable anyway.
There have been plenty of 16-colour palettes on old machines. So let's take a look at what those who came before us have chosen to do.
(I guess I should have done this before I came up with my own Silicon8 v1.0 palette. Oh well 😉)
Microsoft seems to have had a very mathematical approach to dividing up the
colour space. Every combination of the extremes (0x00
and 0xFF
) is
represented, with the in-between colours using 0x80
(128), which is pretty
much exactly in the middle. It lays the colours out in such a way that bit 3
becomes a "brightness toggle", which is nice I guess.
Of course, Apple being Apple, this palette is much more pleasing on the eyes. The colours are laid out in an order that feels like it makes sense, a bit like a rainbow. And they aren't quite so extreme, so the colours seem to "scream" at you a lot less.
The designers of this palette clearly thought that having lots of different levels of gray was important. Which is very nice for some purposes, like good looking fonts, but probably not so great for others, like flashy games.
The CGA palette looks a lot like the Microsoft one, except that it uses a
different in-between value of 0xAA
and reorders the colours a bit. Again, bit
3 is a "brightness toggle".
If I understand correctly the 16 colours in Pico-8 can be mapped to other colours, but these are the 16 system colors the screen palette is mapped to when PICO-8 starts up.
I like how this palette is much more stylized, like the Apple one, but still manages to look very 8-bit-like when used.
The current palette that Silicon8 uses is the following:
This palette looks a lot like the Microsoft and CGA ones, except that my
in-between value is 0x88
(which may or may not be a good idea) and that I
chose a different order for the colours.
Advantages of this palette:
- The grays are in the first four spots, so that XO-Chip programs get four levels of grayscale by default, without any additional effort on the part of the developer of the interpreter (albeit in the "wrong" order)
- The primary colours red, green, blue and yellow can be used by adding just one extra plane to an image
- In use, it very much reminds me of the screamy bright "good old days" of CGA
Disadvantages of this palette:
- Bit 3 doesn't function like a "brightness toggle" like the MS and CGA palettes do (is that a big disadvantage? I don't know)
- The colours aren't as pretty as the Apple or Pico-8 ones
- Individual planes don't represent very useful colours (white, light gray, red, bordeax)
Let's break this palette up in it's "sub-palettes".
# | Binary # | HEX colour | Colour |
---|---|---|---|
0 | 0b0000 |
#000000 |
Black |
1 | 0b0001 |
#FFFFFF |
White |
2 | 0b0010 |
#AAAAAA |
Light gray |
4 | 0b0100 |
#FF0000 |
Red |
8 | 0b1000 |
#880000 |
Bordeaux |
# | Binary # | HEX colour | Colour |
---|---|---|---|
0 | 0b0000 |
#000000 |
Black |
1 | 0b0001 |
#FFFFFF |
White |
2 | 0b0010 |
#AAAAAA |
Light gray |
3 | 0b0011 |
#555555 |
Dark gray |
# | Binary # | HEX colour | Colour |
---|---|---|---|
0 | 0b0000 |
#000000 |
Black |
1 | 0b0001 |
#FFFFFF |
White |
4 | 0b0100 |
#FF0000 |
Red |
5 | 0b0101 |
#00FF00 |
Green |
# | Binary # | HEX colour | Colour |
---|---|---|---|
0 | 0b0000 |
#000000 |
Black |
1 | 0b0001 |
#FFFFFF |
White |
8 | 0b1000 |
#880000 |
Bordeaux |
9 | 0b1001 |
#008800 |
Olive |
# | Binary # | HEX colour | Colour |
---|---|---|---|
0 | 0b0000 |
#000000 |
Black |
2 | 0b0010 |
#AAAAAA |
Light gray |
4 | 0b0100 |
#FF0000 |
Red |
6 | 0b0110 |
#0000FF |
Blue |
# | Binary # | HEX colour | Colour |
---|---|---|---|
0 | 0b0000 |
#000000 |
Black |
2 | 0b0010 |
#AAAAAA |
Light gray |
8 | 0b1000 |
#880000 |
Bordeaux |
10 | 0b1010 |
#000088 |
Navy |
# | Binary # | HEX colour | Colour |
---|---|---|---|
0 | 0b0000 |
#000000 |
Black |
4 | 0b0100 |
#FF0000 |
Red |
8 | 0b1000 |
#880000 |
Bordeaux |
12 | 0b1100 |
#FF00FF |
Pink |
I'm not overly happy with the current "sub-palettes", so I think a redo may be in order. But probably not any time soon 😄