MAY 2017

Chapter 02 - The Graphics Engine

Once I get past the idea stage, I then start the process of breaking the development stage into smaller tasks to get a clearer picture of the overall job ahead. I'll isolate which core functions will be needed by the game and these are usually the most CPU intensive parts of the game that simply must work efficiently, reliably and as quick as I can make them.

These functions tend to always be:

  1. The Graphics Engine
  2. The Sound Engine
In this chapter I will talk about the Graphics Engine and what I have developed so far.


Something new from something old

For Gunstar, I will be going "old school" and resurrecting a Graphics Engine I used a long time ago.

I mentioned in the last chapter that back in 1984 when I was still a young high school lad, I created my last TRS-80 Model 1 game called Escape Zone. This was my last game before moving on to the CoCo. This game was a classic vertical scrolling shoot-em-up.

This game featured a Graphics Engine that provided software sprites and overlay functions that were advanced for the time, especially for the TRS-80 Model 1 with its low resolution monochrome graphics. This game also featured impressive sound for a computer with no real sound hardware. All sound was generated by toggling the cassette output for the generation of 1-bit sound and there were no interrupts or fancy hardware to utilize.

But the Graphics Engine that I used in this game had some interesting capabilities that if converted to the CoCo could provide a slightly different way of managing sprites and overlays. Click on the screen below to open a YouTube link that shows Escape Zone in action.


"You have been held captive by the evil Dakors since they first captured your craft during a daring space raid. But the Dakors made a mistake of treating you just as any other human captive and so you manage to escape from confinement and have reached your escape craft. The Dakors are alerted to your escape and now there is no time to lose!
Prepare to thrust your way out of the Dakors' command destroyer and into open space via a tight winding tunnel filled with deadly "Blipop" and "Bizzo" mines. Once in space, destroy the super-fast "Flipps", maneuver through the dangerous meteor shower and dodge your way past the "Reverso" crafts and "Putt-putt" missile ships into the safety of free space!"


ORIGINAL 1984 STORY PRETEXT




How the Graphics Engine worked for Escape Zone

My thinking for this Graphics Engine was based on the idea of creating separate graphic layers... a background layer, a sprite layer and an overlay layer.

The background layer was an actual bitmapped layer but the sprite and overlay layers were just drawn over onto this background layer that logically represented separate layers.

I also incorporated double buffering to hide the user from the actual game screen setup mechanics to eliminate screen redrawing and flickering.

I allocated an area of RAM the same size as the actual video display. On the TRS-80 Model 1, that meant reserving 1024 bytes and this is where I drew all of the background graphics. Then I drew the sprites onto this same background layer. Once all the sprites were drawn and collisions processed, I could then draw any extra graphics such as explosions and things like the superimposed "Escape Zone" text shown in the YouTube video, being overlaid on top of the game demo as it was playing. The size of the sprites and overlays could be large dependant on how fast I wanted the game to be.

This was the completion of one frame and was then a matter of copying the entire 1024 bytes onto the actual 1024 bytes video display RAM. The user did not see any of the individual graphics being drawn, only the completed frame after it was copied to the display using the fastest possible way I could find. The area reserved in memory used to create the initial frame was then erased and the entire process restarted for the next frame to be displayed. This erasure was very important and I will explain why a little further down.

This system worked very well for the TRS-80 Model 1 since it couldn't reposition the display in a different area of RAM and copying the 1024 bytes of RAM was within the processing speed of the 1.774 Mhz Z-80 CPU.


Conversion to the CoCo... BIG FAIL!

When I moved across to the CoCo1 in late 1984, I tried to carry this Graphics Engine across using the new color and higher resolution graphic modes that the CoCo1 provided but problems surfaced almost immediately.

The TRS-80 Model 1 used 1024 bytes for a video display but the CoCo1 high resolution graphics modes used 6144 bytes. But this problem could be offset by the CoCo's ability to reposition the video display anywhere in memory. There was now no need to copy the finished plane to the video display RAM anymore. I could simply keep 2 screens in memory and alternate between the two keeping a doubled buffered system for cleaner output.

But there was still the need to erase a page and this meant clearing 6144 bytes. That was 6 times more RAM than the TRS-80 Model 1. To make matters worst, the CoCo1 was running at a slower processor speed of 0.89 Mhz compared to the 1.774 Mhz of the TRS-80 Model 1.

The Z-80 also had a brilliant command called LDIR (Load Increment Repeat) which allowed a fast block copy of RAM with a single instruction once the source and target locations were defined. The 6809 didn't have that. LDIR was the one command on the Z-80 I sorely missed.

To be fair, there were lower resolution video modes that used less memory that I could have used but this was my first venture into high resolution color graphics and I wanted to move away from the low resolution graphics I was so use to. I also could have used a smaller area of the screen rather than the entire screen but I was fixated at doing the whole screen.  :)

This Graphics Engine was very CPU intensive and my 6809 programming skills were still in their infancy, so I abandoning it and looked for a different method of handling the high resolution graphics.

I wasn't a Jedi yet!   :)


The Verdict

The benefits of this Graphics Engine was that it eliminated the need to keep track of the background that got overwritten by sprites and overlays. This also simplified the graphics routines used to process the sprites and overlays and therefore offset some of the CPU cycles lost during copying and erasure operations. The graphics were also clean and flicker free due to the double buffering.

In the years that followed, I used more common methods for sprite creation basing them on the requirements of each game. It wasn't until 1992 when the desire to create a vertical shoot-em-up again resurfaced. This is when I began developing Cosmic Ambush for the CoCo3. This incomplete game was my first attempt at using the hardware features of the GIME chip to create a seemingly endless hardware vertical scrolling background. It was a reasonable attempt at a vertical shoot-em-up but I wanted more from it.

There was some flicker of the sprite animations and the score overlay had to be constantly redrawn otherwise it too would scroll off the screen. I didn't use double buffering for this game since a screen occupied almost 32K and I was planning this game to be on a ROM cartridge that only required 128K of RAM.

Click on the image on the right to see Stevie Strowbridge's video review of Cosmic Ambush.

Using features such as the hardware scrolling comes with it's own  tricks and traits. What you could do, was dictated by the hardware's capabilities. For example, the hardware vertical (and horizontal) scroll moved the entire screen. I can't set an area of the screen that would remain static as the rest scrolled vertically by. In Pop*Star Pilot, I tricked the hardware to create split screen scrolling but that technique only works in the horizontal direction.

For Gunstar, I need vertical scrolling with many sprites and overlays. This poses a challenge and for this I have summoned my 32 year old Graphics Engine.  In reality, with 512K RAM, I could have expanded on the Cosmic Ambush Graphics Engine and made it work but I had other ideas of what I wanted to do which would have complicated things... besides, this was going to be more fun.  :)


The legend returns!

Before I was to officially start this project, I needed to prove IF it could be done at the desired speed. I was aware of the problems I had encountered with the original and set about to do some trials to evaluate the challenges ahead.
This time, the challenges were even greater.

My favorite and preferred video mode was 320x225x16 colors. This is a 36K screen and I strongly suspected that I would be trying to take the bull by the horns with this one but I had to start somewhere and I chose to start from the top and work my way down.

Firstly, I needed to create the endless vertical scrolling background and here I use the same system as I had used in Cosmic Ambush where I allocate an area of RAM for the  Background Layer  that was two display screens high. I would position my display screen in the bottom half of the background layer and for each frame in the game, draw the next incoming line just off the top of the displayed screen. With the new line in place, I move the video display screen up one line to bring the new line into view then copy the newly displayed line from the top of the screen to just off the bottom of the screen.

This process looped and the page would scroll line by line until the new graphics were displayed in the top half of the background layer.
This therefore also created a copy of the top half into the bottom half as it scrolled upwards. Now, all I had to do once I had reached the top of the background layer was to reposition the displayed video page to the bottom half again and start over, continueing the layering of the new background graphics. This could go on forever as long as I had graphics to put up.

So far so good. Now for the sprite and overlay layers.

At this point, conventional sprite routines would draw the desired sprites directly onto this background layer. They would firstly store the area below each sprite into another area of memory, merge the sprite graphics with the background in whatever way preferred (byte, pixel etc) and when the completed frame was finished and displayed, restore each of the sprite backgrounds back to their original state, repeating the process for the next frame.

Double buffering usually required two sets of  sprite backgrounds to be stored and then restored. The more sprites and overlays, the more background that was stored. Depending on the sprite routines, this could also have meant that the same background area was stored twice in the case when two (or more) sprites were overlapping. This whole business of maintaining the background with double buffering could become complicated and presented some repetition unless you wrote a smart and complex sprite routine to manage it all properly and efficiently.

I'm getting too old for this sort of thing and needed an easier approach.  :)


A more flexible and manageable system

In re-implementing the old Graphics Engine from Escape Zone, I’ve come up with the following…

As well as the background layer as described above, I allocated two areas of memory as  Display Layer 1  and  Display Layer 2 . These will be the areas of RAM where each of the double buffered screens reside.

The double buffering will work by displaying one of the display layers (I call this the active screen) while the other gets redrawn out of view. Once completed, it becomes the new active displayed layer and the other gets redrawn. This cycle continues for the entire game.

Sprites and overlays are drawn during this redrawing process. The part of the background layer that is to be displayed gets copied first to this non-active display layer. Here, we need the absolute fastest copy routine to copy the background. This process automatically erases all previous sprites and overlays leaving a clean, updated and scrolled background ready for the next frame. All sprites are updated, drawn, collisions checked and processed before finishing off by drawing all overlays (explosions, score readouts etc.) over everything to finalize the frame which is then made active and displayed to the user as a fully completed frame. This process cycles over and over.

This simple idea fulfills my desire for a simple, flexible and manageable graphics engine with sprite overlay... at least in theory.

Now to get some real code running to see if it will actually work.


Judgement Day

My biggest concern was whether I could create a fast enough copy routine to transfer a screen worth of memory from the background layer across to the designated display layer. I was essentially trying to create a fast software Blitter memory copy mimicking what the Commodore Amiga had within it's custom hardware. (Of course, the Amiga had real sprites and multiple overlaid bitmaps as well, but on the CoCo we have to program all this)

I'll save you the suspense.... no I couldn't.   :)

But I suspected that. A 36K display screen was just way too much to copy in a fast enough time frame with the CoCo3's 1.79Mhz CPU.

The CoCo3's video is composed of 60 interlaced fields per second. Two fields combine to make a frame. Therefore, the screen runs at a maximum of 30 frames per second. Video data from the CoCo occurs on one of those fields. The other field is blank and this is why we get the black scanlines between live scanlines. If both were live, the CoCo would be producing 450 interlaced lines per screen. It can't and so produces half this number (225) with the other interlaced half as black scanlines in between.

It was clear I had to run a lower resolution so that the 6809 could copy it within one field. This left me another field to create sprites and process the remainder of the game if I wanted to achieve that magic 30 frames per second speed. This was still a tall ask and it was more realistic that I aim for half that at 15 frames per second... but I'll try.  I would not accept anything lower than 15.

I experimented with several resolutions and utilized Stack Blasting to obtain the fastest speed I could muster. This is when I began exploring the 6309 opcodes and I came across a great revelation!

The TFM (Transfer Memory) command! This was the 6309 equivalent of the Z-80 LDIR (Load Increment Repeat) command which I missed so much from my TRS-80 Model 1 days. The TFM command was actually better than the LDIR because it could work with an interrupt service routine and continue to do the memory transfer. Brilliant and perfect for my needs!

I spent a lot of time and tried many methods of transferring data using stack blasting with the 6809 but the 6309 in native mode and the use of TFM would beat it every time. In the end, I made some compromises that brought me close to the 6309 copy speed. Gunstar will implement both and choose the appropriate one dependent on what CPU you are running.

In the end, I found I could use a 128 x 112 pixel x 16 color mode. This is the same mode I used in my game Gate Crasher except with a slightly higher vertical resolution.

The image on the right is a screen capture of the game screen from the VCC emulator with the copy routine running but no graphics to scroll. VCC fills the RAM with alternating 0 and 255 bytes on bootup causing the byte wide (2 pixel each) striped bars. A real CoCo3 fills it with random data.

The narrow display is the same width as the standard 32 column VDG text screen but taller due to the extended vertical resolution. This is fine since most arcade vertical shoot-em-ups actually use a vertically oriented display anyway.  I'm happy to use this display mode for Gunstar.

I drew up some test graphics (the player's spaceship that will be used later in the game) and I liked it. It obviously wasn't as sharp as a 320 x 225 mode but the larger spaceship size had a charm of it's own. I liked it and that will end up being the design used in this game.

I even based the spaceship artwork that you can see at the top of this blog page on it.  :)

I had an acceptable resolution and my copy process was achieved in just under one field for the 6809 version and a bit less on the 6309. The 6309 version will also have horizontal panning. The actual background will be wider than what is displayed and will shift left or right proportionately with your spaceship as it travels vertically. The 6809 version can't quite muster the speed needed to perform this in the same way so it will stick with just vertical movement.

This makes a good reason to upgrade to a 6309 and I hope to add other features that will specifically utilize the 6309 if found. I love the 6309!

The lower resolution of the graphics will hopefully be offset by the amount of detail in the overall animations. If I were to design a game where I wasn't trying to copy an entire screen, a higher resolution may have worked but I have a plan for what I am wanting to achieve which hopefully will become clearer as we progress through the chapters of this blog.


Phew!

That's the end of this blog chapter. I hope I've made sense and not confused everyone.

I must stress that this is not the best Graphics Engine for all games but it's a great Graphics Engine suited to this kind of game and for what I am trying to achieve.

In the next chapter, I will add in the second most time consuming component of the game... the interrupt driven sound.

I need to pull off the Graphics Engine and Interrupt Driven Sound together at a fast enough rate.  Fun times ahead!



Copyright 2017 by Nickolas Marentes