Home About me PC TI-Calcs Music Guestbook News


GAME ENGINE

Take me to the demo at once!

HUH?
...I hear you say. So what is this all about? Good question. More than 18 months ago I started with a project that would, when finished, make all existing side-scroller games for the TI-86 look dull. The actual project was not to make a game (that would come later), but rather a set of super-optimzed routines which all side-scrollers require. This includes mainly the scrolling (the core) and the putting of sprites. In this unfinished version, only one pretty simple sprite routine has been done (although it IS the fastest one currently available), but the actual scrolling is almost finished.

SO WHAT?
"Horizontal scrolling is simple! Just a bunch of rl (hl) instructions." Well, this has been the standard approach used in all games I know of. Sure, it is simple, and usually fast enough. Usually... Another big drawback is that you can only scroll one pixel at a time. Scrolling two pixels would most likely be smooth enough, but this ain't possible using this approach - you are required to execute twice as many rl (hl) instructions, and the gain is minimal. If you combine horizontal and vertical scrolling, it's even slower.

So how can you perform scrolling (both horizontal and vertical) faster? In order to answer this, lets look at a system which incorprates hardware scrolling, the Nintendo Game Boy. The screen on the GB consist of 160x144 pixels, although the actual video RAM consist of 256x256 pixels. The GB has two hardware registrers, SCX and SCY, telling the system what part of this 256x256 area should be shown. For instance, if SCX=23 and SCY=37, the rectangle (23,27)-(182,170) is displayed on the screen. All you have to do to scroll is change the SCX and SCY registers and the screen scrolls automatically. Wouldn't it be nice if this was possible on the TI-86 too? Since we obviously lack the hardware, we would have to do this "rectangle copying" on our own. This can easily be done, as long as we're working with aligned scrolling. But is it really that hard to do in the general case as well? That is, from a virtual screen of a certain size (bigger than 128x64) rip out 128 pixels, align them correctly and display them onto the video memory? Of course, it's all a question about speed. We obviosuly can't align using the rotate instruction, since we then would be back at the "old way" (and much slower so). The solution here is lookup tables. With good coding, it's possible to rotate a register and indirect number of times in two machine cycles! Of course a lot more than this is involved (like masking), but this is all a matter of clever coding and usage of registerss.

This is what this Game Engine is all about. You set up a virtual screen, and do all your work on the virtual screen. When you want to update the real screen, you just call a function (UpdateScreen); you control the scrolling with two variables similiar to SCX and SCY mentioned above. As a result, you can scroll any number of pixels in any direction at once! As a bonus, you don't have to take care of stuff like double buffering, clipping of sprites etc as this are built-in features when using a virtual screen.

Another goal with this Game Engine was flexibility. The size of the virtual screen can be set to any size (limited by the memory) when initializing the engine. Also, many games probably won't use the whole 128x64 area for scrolling; usually some part is reserved for status information. The Game Engine lets you decide the size and position of the output window during startup, and this can be even changed while the engine is running!

As previously mentioned, only one sprite routine has been done, putting sprites of size 8 in horizontal width using the XOR method. The routine is extremely fast; 3600 8x8 sprites/second and 2100 8x16 sprites/seconds are my results, which is faster than for me any known sprite routine.

IS THIS REALLY SO GREAT?
Probably not :) If you intend to write a simple scroller which only has two-way scrolling (ie left-right) and where the screen doesn't have to scroll very fast, the rl (hl) method should be good enough. However, if you intend to write a fast four-way scroller (say, a fast spaceship flying around in a large area with lots of enemies), this is what you need.

Other things to consider is that you can adjust the screen updating frequency depending on how much is going on. For instance, if you hook the UpdateScreen call to an interrupt, you could let it run at, say, 25hz, and then reduce this to 20hz when it starts to go slow. This could of course be set by the user. Shrinking the window size in order to increase speed is also a thing the user could do (like you can do in all PC games nowadays).

LIMITATIONS
Quite a lot of RAM is used by the routine. To be more precise, 4096 bytes is used (in RAM page 1) for lookup tables and such stuff. This leaves about 12000 bytes for the virtual screen, which is the same as 12 128x64 screens. This will most likely not be sufficient for most games, BUT you can easily reload non-visible parts of the screen with new data and "jump back" with the scroll variables. Since the reload can be done tilewise (aligned that is), this is very fast.

WHAT'S MISSING?
Larger virtual screen I was thinking of allocating another RAM page (RAM page 7, by moving the symbol table - VAT - to the end of RAM page 6 if mroe than 16k RAM is free), and stuff it in the $4000-$7FFF area during UpdateScreen, in order to allow biiig virtual screens.

Wrapping However, you still won't fit really big levels, so you need a fast way of updating non-visible parts of the memory which can be reused. The best way to do this is to allow wrapping of the virtual memory. For example, if SCX=240 and SCY=0 on the Game Boy, it would display pixels 240-255 followed by 0-143 on the top row. Supporting this would make the UpdateScreen function slower though.

Grayscale In order for this to happen, allocating another RAM page for a virtual screen is almost a must, since the graphics takes twice as much space.

Automatic sprite updating This is another idea which most console systems and older computer systems had built into the hardware. Instead of calling PutSprite all the time to update the sprite (and making sure it's removed before moving it), all you would do is change the sprite coordinates in a sprite table, and the next time you call UpdateScreen, the sprites would be at their new locations.

HERE IT IS

  • scroll.86p Compiled version of the demo
  • scroll.zip Source code to the Game Engine (scroll.h) and the demo program (scroll.asm)

The screen is scrolled with the arrow keys. Holding down 2ND while scrolling doubles the scrolling speed. Holding down ALPHA changes the size of the scroll window, and holding down X-VAR moves the scroll window.

BYEEE
This is most likely my last contribution to the TI community. I really wanted to finish this engine, and make a game like Metroid based upon it. However, time went on and other, more important stuff, came in the way, and I've slowly come to realize that I most likely never will finish this. Since I thought maybe someone else could continue working on it, or use it as it is, I decided to release the current version.

If this was an ideal world, where there was infinite time and no need to make a living, I would continue doing TI-86 stuff. Unfortunately this world is nothing like that.

[ Home | About Me | PC | TI-Calcs | Music | Guestbook | E-mail | NEWS ]