A lot of the Commodore articles I’ve written here involve arcane timing on when it is safe or useful to shift values in the graphics registers. I haven’t really gone into any detail as to why you might want to do this.
The answer for this is almost always the same: this is for engineering various kinds of split-screen display. You need to simultaneously display different kinds of information, and they need different video modes to work, so you divvy up the vertical space on the screen and cange the modes as needed. Easy enough, in theory, but the devil is as always in the details.
For my sample code so far in previous articles I’ve been working purely with the background color (register $D021), which has the nice properties of being both easy to see and of updating more or less instantly. As the VIC article shows, though, a lot of things we care about end up getting cached. Changing values mid-scanline is kind of a sucker’s game anyway, especially if you’re in America; I’ll get into that in more detail in a later article. Let’s just stick with the easy stuff for now.
- Changing the character set, the horizontal scroll value, or the display mode (multicolor, extended color, text, or bitmap) is instantaneous. It is completely legitimate to have half a character be uppercase and the other half be lowercase, or to split it in half with the horizontal scroll. If you set this while the screen is not displaying you will have full raster-line precision.
- Changing a character in screen memory or, more plausibly, the actual location of screen memory will not be visible until the next row of characters is displayed. The VIC-II reads in which characters to draw for screen memory during a badline, and then caches it until the next badline. Which means…
- Changing the vertical scroll value ends up being… kind of messy.
If you’ve got a horizontal-scrolling display with a fixed status line, a la Super Mario Brothers, you’re pretty much in clover here. You can shift the video matrix at any point in the last 8 scanlines of your status line display and then set the horizontal scroll to wherever your scrolling screen demands. (You’ll probably need to also change screen memory—it turns out 1Mhz isn’t a fast enough processor to scroll the whole screen during VBLANK so you’ll want to double-buffer—but that happens outside of the raster interrupts.) There isn’t really anything conceptually complicated here.
Vertical scrolling, though, we actually run into a specification problem right off the bat. What does it mean to change vertical scrolling mid-character? One could imagine several answers to that, and in the end it falls to the vagaries of the panning hardware to answer it for us. For the VIC-II, altering the vertical scroll value means altering when the badlines happen, and thus altering when the next row of characters will appear. Mishandled, it can produce memory corruption due to a flaw in the design of the chips—we had covered that in the previous article.
If you’ve set it up so that you’re doing a mid-character vertical scroll down, you will have added a few graphically idle lines between your current line and the next one. Such lines use default graphics data that happens to be loaded from the top of the VIC-II’s memory range (usually $3FFF) and which is always black in color. Combining this with the invalid video modes that never display anything at all despite keeping memory accesses up to date and you can get a servicable vertical-scrolling split-screen with eight rows of buffering. And since badlines never pick up in the middle of a character, if your non-scrolling section is at the top of the screen, this is pretty much the best you can do.
Things get more interesting if you set it up so the next badline cuts your current character short. This produces a rescan of screen memory for a new set of characters, but it doesn’t advance the screen memory pointer, so it is a repeat of the previous line. Unless, that is, you’ve changed the screen memory pointer since then via $D018, in which case it will scan the same line but from the new screen memory. That’s pretty promising! It implies that if the stable part of the display is at the bottom, we can have the scrolling display extend right up to the edge of our status screen. We might have to wobble the text up and down a line, since when the scrolling display is exactly synchronized with our status window, we don’t get line repetition, but that’s not so bad.
What is, however, so bad, is when we need to get two badlines in a row. If we’re scrolling one pixel at a time, that happens once every eight frames. We’ll attack that case next time.