Wednesday, July 25, 2012

Palette Expansion

The graphics output options for the original CoCo are a bit sad when using a static VDG configuration.  We are forced either to give-up half of our available colors (and black) to maximize resolution, or we must give-up half of our available resolution and accept some odd color placement rules to maximize our available colors.  Neither option provides particularly satisfactory results.

CoCo Chameleon

The VDG uses the inputs on a number of pins to determine its current video mode.  On the CoCo, this is used to switch between alphanumeric and semi-graphjcs modes automatically.  The highest-order bit of each byte of screen data is fed back into the pin that selects between those modes, allowing each character to be displayed as intended.  The selection between inverted and non-inverted characters is handled similarly.

In fact, there are other VDG-equipped machines that extend this same technique to control the pin that selects between the available palettes (i.e. the CSS pin).  But for better or for worse, the CoCo has to use software to control the CSS value.  So that begs the question of whether or not the CoCo can change the CSS value quickly enough to produce more colorful displays.  In fact, the CoCo game Dragonfire does exactly this.  While the Dragonfire display is a bit cartoon-ish, it suggests that more colorful displays are possible on the CoCo.

Timing Is Everything

Knowing that we can switch the active palettes "on the fly", we are now faced with the task of doing so in time to display what we want when we want it.  To do that, we have to figure-out how often we can change the CSS value, and when to do so.

Let's start with the 'when' part...  The CoCo hardware can generate an interrupt for each line of the (almost-)NTSC display, or 262 times for every frame.  Processing these interrupts through the IRQ vector would take a lot of cycles -- enough to miss the beginning of the actively displayed portion of the next line!  Fortunately, the 6809 provides a SYNC instruction that basically halts the processor until the next interrupt is signalled.  This allows us to synchronize with the interrupt timing at a minimal cost of CPU time.  A little extra processing lets us skip the 70 lines during the vertical blanking period (i.e. the non-active portion of the display at the top and bottom of the screen).  After that, some judicious use of NOP instructions and cycle counting allows us to time our CSS updates as necessary.

Each VDG clock cycle corresponds to one "color clock" cycle on the NTSC display, or one color pixel on the screen.  The CoCo CPU clock is the VDG clock divided by 4, so one CPU clock corresponds to 4 color pixels on the screen.  The fastest way I have found to update the CSS value is to preset the A and B registers and then use STA or STB to store the appropriate CSS value to the register that controls the VDG mode (including the CSS input of the VDG).  With the 6809's Direct Page register set appropriately, those STA/STB instructions each take 4 CPU cycles.  That corresponds to 16 color pixels on the screen during each CSS update, allowing for 8 CSS updates per 128-pixel line.  Presetting the CSS value could allow for up to 9 CSS values (the preset CSS value and 8 updates) per line, with each CSS value corresponding to a different palette selection.

Putting Things Together

With all that figured-out, it seems prudent to write something to prove that this all works!  So, I wrote some boilerplate code to properly time the CSS updates and to divide each line into eight 16-pixel sections.  I added some code that initialized the screen buffer to include the appropriate pixel data for a rainbow of colors, accounting for the changing palettes in each section.

8 On-Screen Colors from VDG

Keep in mind that for any given byte of screen data, only four colors are available.  Yet, there are eight colors displayed on each line.  Now we are getting somewhere!  Stay tuned to hear about how I use this to improve the display of a real-life image... :-)

2 comments:

  1. Beautiful! Will code (and maybe a tutorial?) be forthcoming once you bring everything together? Also - is black basically impossible to get (I only remember PMODE 4 having black, so that might be true)?

    ReplyDelete
  2. I intend to release a git tree at the end of the month, but I don't promise that it will be particularly user-friendly! With that said, it probably won't be that far away from something that could be usable by "normal" (CoCo using) people. Maybe I could even take patches from the public to improve it and/or make it run under Windows, etc?

    As for the tutorial -- to be honest, the blog is probably as close as I'll get to that. I'm not against spreading the knowledge, I just don't know if the audience is big enough to justify me doing that rather than something else (like working on Fahrfall)!

    As for black -- the VDG just won't output black in the G6C mode (or the other "color" graphics modes). The G6R mode (i.e. PMODE 4) could be an option in place of one of the CSS options, but that complicates the color choices even further -- I might explore that later. I do have something working that gets closer to black, but that will have to wait for a later blog post... :-)

    ReplyDelete