Tuesday, August 14, 2018

SAD Graphics

Last time we were left with a problem: too much graphics data.  The original Commodore 64 has 8 bits of bitmap data from system RAM each cycle.  The C640 doubles this by using the colour RAM interface, and doubles it again by having 16 bits per byte.  That gives us 4 bits per pixel in standard mode, and 8 bits in multicolour.

It would be nice to use the extra data to increase resolution, but I haven't been able to think of a good way of doing that.  We want to keep old behaviour when the new bits are 0, and try to avoid adding new modes.

My solution is "Store and Display" graphics.  This is inspired by the Amiga's HAM mode, and the Apple IIGS's fill mode.

In standard mode, we have four bits per pixel: ABCD.  The low bit (D) is stored in the low 8 bits of system RAM, C is in the high 8 bits of system RAM, B in the low 8 bits of colour RAM, and A in the high 8 bits of colour RAM.

CD selects the colour for this pixel, as described before.  A and B control store and display.

  • 00CD: store CD in register C0, display CD
  • 01CD: store CD in register C1, display CD
  • 10CD: display register C0
  • 11CD: display register C1
(I might change the last two to xor the contents of the colour register with CD, depending on how useful it is in practice.  I'm also tempted to add some new registers to set the initial values of C0 and C1 on each line)

If we clear the screen to 1000 with a column of 0000 down the left hand side, that gives us a screen full of the background colour 00 (register $d021).  If we set a single pixel to 0001, then it will display colour 01, and also store 01 in register C0.  Then on the rest of that line, every pixel will be displaying the colour from C0, which is now 01.  By changing a single byte, we have drawn a horizontal line.

If we didn't want to draw to the end of the line, we could write 0000 to a pixel to set C0 back to colour 00.

This gives us the ability to draw single-colour filled polygons by drawing only the pixels along the left and right edges.  But so far that's only using C0, not C1.

Now clear the screen to a checkerboard pattern of 1000 and 1100, ensuring that C0 and C1 are both set to 00 at the start of each line.  This gives us a full screen of the background colour.  If we set two adjacent pixels to 00xx and 01yy, then C0 and C1 will be set to xx and yy respectively, and the rest of the line will alternate between those two colours.  This lets us draw dithered filled polygons, as in the teaser picture from the last post:




Multicolour mode has 8 bits per pixel: ABCDEFGH.  These are stored as follows:

  • GH: system RAM low
  • EF: system RAM high
  • CD: colour RAM low
  • AB: colour RAM high
If A is 0, then BCD is used to select one of eight C registers (C0 to C7), and EFGH is both stored and displayed.  If A is 1, then the contents of the selected register will be displayed instead.  This is the same as standard resolution, but with many more colours to play with.

It probably won't be useful to store split-pixel 'colours' in the C registers, but if there is a use for it, it will work.


Currently, the simulator ignores the low bits when the top bit is 1 (when it is displaying the contents of a C register rather than storing a colour into it).  That feels a bit wasteful.  If those bits were xored with the contents of the displayed register, that would allow overlaying images onto a filled polygon without interfering with the rest of it.  This might be useful.  But it might end up too complicated to actually use.  That decision will have to wait until I've written some more test software.  And that will have to wait, as I've put the simulator aside for now, and moved development onto much more interesting things...