Saturday, January 14, 2023

Software Sprite

As often discussed, the Motorola 6847 VDG offers little in terms of assistance for game programmers or other software authors. While many contemporary video chips offered assistance in scrolling backgrounds or in moving objects in the foreground of a display, the 6847 hardware merely provides access to a static framebuffer. As we have seen prviously, anything beyond a still image requires work from the CPU. Fortunately for CoCo people, the Motorola 6809 CPU is reasonably capable, and when used properly it can provide at least some of these video effects.

 

Get Things Moving

Of course  the only way to start is to draw something in the framebuffer memory by using the CPU's usual load and store instructions to copy data out of program storage and into the framebuffer. To create the illusion of motion this must be done rapidly and repeatedly. If care is not taken between draws to remove the previous image then "movement" will create a trail across the screen, corrupting the background image. Various methods exist for doing that cleanup (e.g. saving and restoring the background as part of the sprite draw operation), but this takes both program development time and execution time. The latter in particular is at a premium when so much data is already being moved for the background.

Mask Mandate 

In the 6847's RG3 (4 color, 2 bit per pixel) graphics mode, each byte of buffer memory represents 4 pixels. Since memory writes happen one byte at a time, any image that uses less than 4 pixels in each byte it occupies will interfere with those extra pixels unless care is taken. This is typically observable as the movable object appearing a bit like a postage stamp laid on top of the display.  Unless the object being displayed is rectangular with a pixel width that is a multiple of 4 pixels, then part of the draw operation must include masking. This involves reading the background, using a bitwise mask of the object to combine the object's pixels with the background pixels then writing the resulting data. This operation performs the trimming necessary to preserve the background. There is some execution time lost for the masking, and storing the mask data doubles the amount of memory necessary for storing the graphics objects. But there really is no way around this part.

No Background Check

With the scrolling background demonstration as a base, we can now show a foreground item on top. Since both the foreground item and the background image move in relation to each other, this is not a single draw (or mask and draw) operation. With a normal static framebuffer, displaying a moving foreground itme would require some action to restore any background bits eclipsed by the foreground when the foreground moves. This might require regenerating the background algorithmically or saving the background before drawing the foreground and restoring the background after the foreground is moved. If we draw the foreground item in our source or "render" buffer, then all of the above would be true. But by drawing the foreground item directly in the current "display" buffer, we know that the background will be copied from the render buffer to the next display buffer at the next buffer switch. Since the background is already being redrawn for every frame, we don't need to maintain the background at all, saving all that time that would have been used for maintaining the background image!

So while redrawing the entire background initially seems expensive, that operation turns out to be cheaper than tracking damage to the background image and redrawing the background over and over again. It took me a while to wrap my head around this feature, but hopefully the explanation above makes things clear for you? I hope so.

Hopefully I can keep finding time to turn this discussion into an actual CoCo game. If you want to see where this all goes, then be sure to stay tuned!

Tuesday, January 10, 2023

Scrolling Engine

Well, it's been a while!  Despite the boredom and isolation that came along with the COVID years, I didn't do much that was very impressive in terms of retro programming during that time. In a cruel twist of fate, the boredom (and an ongoing spat with another CoCo media figure) seems to have robbed me of inspiration during that time.  Despite that, I did manage to produce a little technology demo to demonstrate scrolling a full graphical background on a CoCo. Some have asked for more information on how this was done. If that interests you, then please continue reading!


So Much Work

Scrolling a background image with the 6847 VDG is not by itself a huge technical problem. All that is required is to move a lot of data from where it starts to a new location. For a CG3 (128x96) screen that means 3 KB or 3072 bytes of data moved for each frame of video. Many video chips roughly contemporary with the 6847 provided hardware support that allow (usually at the expense of some memory usage) for the illusion of movement by changing the source of the video data between frames. The SAM/VDG combination used in the CoCo offers a rudimentary version of this, but the frame-to-frame jumps would be too coarse and the memory demands too great to be useful by itself for smooth animation.

So Little Time

With no useful hardware support available, brute force must be used to copy bytes around in the video buffer. Computers are fast, but not infinitely fast. How much time do we have? And how long does it the 6809 take to copy 3072 bytes? The VDG generates just under 60 video frames per second. With the normal 0.89 MHz clock speed of the CoCo, that leaves us less than 15000 clocks to move the data for each frame. Unless the CPU can move one byte in five clock cycles (which it cannot), then there is just not enough time.  Even at just 30 frames per second, we still wouldn't be very close.

Switch Things Up

The 6847 generates video output at just under 60 frames per second, and the SAM/VDG combination used in the CoCo does offer a "screen flip" capability. Combining those two details allows us to "double buffer", or to draw in one buffer while the other is used as the display source and then to switch between the buffers. Using two buffers effectively halves our video frame rate but doubles the amount of time available for video data movement and gets us back to a manageable 30 frame updates per second.

Blast Away

One unique feature of the 6809 CPU architecture is the User stack. This provides an efficient means for moving data, particularly when combined with the System stack and used for what is colloquially known as "stack blasting". This feature allows for moving up to 8 bytes at a time in as little as 26 cycles for just two instructions. This would potentially allow us to move a frame's worth of data in roughtly 10000 cycles (depending on the actual code implementation). My implementation depends on some looping and is not quite that efficient. But it does suffice to keep the video update well within the 30 frame per second limit while leaving a generous amount of time available for doing something else (e.g. handling I/O or implementing game logic).

Single Source

The two buffers mentioned above are merely tools for keeping the display looking correct and up-to-date. But both buffers are completely ephemeral. A third buffer is kept for rendering the actual video frame. This buffer is the source for the stack blast copies described above. since both of those buffers will be overdrawn almost immediately, any "permanent" change to the display needs to be done in this "render" buffer. Consequently this is the perfect place to draw any static background items (e.g. anything to be scrolled).

I think that mostly covers it. I originally implemented this back in the Summer of 2020, so hopefully I am not overlooking any big details. But I believe the main points are covered. This technique gets the job done, and it has a few advantages that I hope to exploit in the near future...stay tuned!