Chapter 08 - The Graphics Engine (Part 2)
Back in Chapter 2, I described my idea for implementing the Graphics Engine for GunStar, based on the engine I created for my old game Escape Zone for the TRS-80 Model 1 back in 1984.
this chapter, I have taken that engine and refined it for the CoCo3 and
the Hitachi 6309 processor. The 6309 improves on the speed of the
standard 6809 by running many of the opcodes faster (at the same clock
speed) and adds several extra registers and instructions.
importantly, it adds a memory transfer instruction called TFM which is a fast
way of moving a block of memory from one location to another. Essentially a poor man's blitter
and very similar to the LDIR command of the Z-80 processor except that
TFR also supports interrupt operations during the copy process.
instruction alone is what makes this Graphics Engine possible and is
faster and more memory and register efficient than the Stack Blasting technique used with a standard 6809 for fast memory copies.
Read more about the 6309 here: https://en.wikipedia.org/wiki/Hitachi_6309
The 6309 is the best 8-bit CPU of that era and the ideal way to get an easy CPU boost on a CoCo.
Software written to support the 6309 can generally see a 30%
performance improvement and is generally compatible with the 6809 in
its default 6809 emulation mode at power up.
it does require the removal of the CoCo3's 6809 processor which Tandy
had soldered into the machine in order to save a few cents.
What a crime!
there are a few people in the CoCo community with the skills to do a
professional job of desoldering and removing the 6809 by replacing it with a socket to
install a 6309. Many have already done so in order to run software such
as NitrOS-9 and I felt that
there was now a large enough number of upgraded CoCo3's to warrant
switching my game development of GunStar to be 6309 exclusive.
Let the Mind Screwing begin!
The engine utilizes the 6309's fast memory transfer command to create a series of logical layers representing each frame of screen animation very similar to the Cel Animation technique used in old cartoons.
The graphics logically comprise a background and two overlay planes. I can therefore boast that GunStar will have three layer graphics! :)
1. The Background plane keeps a scrolling backdrop.
2. The Sprites plane allows moving objects to be drawn over this background.
3. A third Overlay plane is then used to display score and other information superimposed on top of the other two planes.
Because I have yet to create the graphics tiles for the terrain, I will utilizing dummy graphics to help in the explanation.
Two areas of memory are used as a storage area
for the Background planes. These are not displayable video planes, just
an area of RAM allocated as graphic buffers representing 192x225 pixel (96x225 byte) 21K screens.
|There are two stages to creating the background, each utilizing the 6309 fast memory transfer command.
Buffer 1: Graphics are drawn linearly a scanline at a time. Each new scanline is drawn above the last scanline. After the
very top scanline is drawn, the process loops and continues back at the
bottom, overwriting the old scanlines.
Buffer 2: Buffer 1 is then copied to Buffer 2 and in the process corrects the scanline
ordering so that the older scanlines are below with the newer scanlines appearing above it.
The area from Buffer 1 where the new scanline was drawn and below is copied to the top of Buffer 2.
The area from Buffer 1 above the newly drawn scanline is copied to Buffer 2 below the previous area copied.
This process repeats endlessly giving the
effect (in Buffer 2) that the older scanlines are scrolling downwards and
off the bottom with new scanlines appearing at the top.
Why don't I just do a single memory copy to move the graphics down and draw the new scanline at the top each time?
I need to have two background buffers for reasons that will become apparent as we progress.
It's not efficient to do a whole buffer copy on Buffer 1 to achieve the scroll then another whole buffer copy to create Buffer 2.
The Sprite Plane
Now that we have the Background plane (Buffer 2), I can place
all the Sprites (moving objects) onto this plane using a method best
suited to the job depending on how well I need it to be overlaid.
I could merge the pixels of each sprite using a masking technique or
just write the sprites without pixel masking which would be faster but
may leave black outlines on parts of the sprite. I could store the
sprites in memory and copy them to the Background plane or use the
faster Compiled Sprites technique.
Ultimately, I will be using compiled sprites for speed but may use a
more conventional sprite techniques depending on the complexity and
animation characteristics of each Sprite.
Collision detection is another area I need to consider but this will come later in development.
Background buffers are mapped in memory representing two virtual
192x112 pixel displays. The CoCo3
doesn't produce a display mode such as this. In order to display the
game graphics using a graphic mode that the CoCo3's GIME chip can
output, I need to clip the excess parts of the Background buffer so
that it fits into a chosen resolution.
I have chosen a display resolution of 128x112 pixels with 16 colors
so I therefore need to remove a 16 pixel width area on either side.
Why have I created this wide Background buffer?
To allow objects to appear to move in and out of the field of view cleanly without the need to waste CPU time working out the off-screen parts. (Refer to the image on the right)
Another feature that this clipping provides is the ability to move
the displayed area left and right within the larger buffer space providing panning of the display during the game within a larger area of space.
In clipping the image to the display size, I merely copy the required
area to another area of memory. This opens the door to double buffering
of the display output.
I allocate two areas of memory to hold the clipped image and by cycling
the display between each area, I can create a nice flicker free
While I am displaying the previous game frame from one area of memory,
all this display processing I have covered is happening on the other
area of memory unseen by the game player. When it is complete, the two
display areas reverse roles and the newly created frame is displayed
and the other area is erased and the next frame built.
all the Sprites placed, the last thing we need is the Score
and other Status displays.
This plane has a
higher priority than anything on the Background or Sprite planes and
any graphics here will be overlaid over everything else.
The final results are a very arcade'like screen with moving objects and overlays.
But wait! There's more!
Normally this would be the stage where we need to switch the display buffer roles to prepare
for the next frame by undoing everything we've done and restoring the
background to its original state so that we can place all sprites in
their new positions for the next frame.
But this is where this engine shines. Because there are two background planes, one of which gets
the new terrain drawn and then copied to the second background
plane, it will therefore automatically erase all sprites and restore the background to
the next scrolled position. No need to do anything!
This is where this engine makes up for the time it takes in all the
copying of memory and makes it far easier for the programmer to manage.
It's a wrap!
I now have the code running and scrolling the background. Currently, it is
scrolling random data in RAM until I insert the routine to draw the background
tilemap. It is running smoothly and jitter free while
running the two channel interrupt driven sound effects I created
in chapter 3.
Feature summary so far...
- Double buffered video output
- 1 byte vertical and horizontal scrolling
- Wider virtual bitmap
- 3 logical graphic planes
- 2 channel real-time sound effects
- Sprite simplification
Next on the menu is the tilemap editor and generator so we can see some actual terrain moving. I'll try have a video to show in the next chapter.