Final Project: Zelda 291: Graphics & Animation

by Will Grzanich



Introduction

Zelda 291 runs under Mode X video and implements page-flipping instead of double-buffering for fast drawing. Sprites and tiles for the game are be loaded from PCX files on disk and placed in arrays.

Problem Description

There are a number of things that proved difficult to achieve concerning the graphics of the game. First of all, the fact that Mode X is unchained and planar (read further down under Implementation for details on this) means that memory cannot be written quickly and linearly to the video buffer; in order to make pixel plotting fast enough, sprites were drawn column-by-column in order to minimize the number of slow calls to GFXSelectPlane. Since we have two video memory pages to keep track of, sprite background scanning was that much more difficult -- two background buffers were required for each object.

Implementation

Mode X

Mode X is a "tweaked" video mode obtained by setting the video mode to the standard 13h VGA mode and then writing certain values to the CRT controller port and the sequencer port to unchain the memory mode and increase the vertical resolution to 240 pixels. This allows our game to have square pixels, since the aspect ratio of the monitor is matched. To illustrate the layout of the unchained video memory used, examine the following image taken from Robert Schmidt's excellent Mode X tutorial:



Page Flipping

When programming in mode 13h, double buffering is the only way to achieve fast flickerless animation. However, in Mode X, this is unreasonable due to the fact that a 320 x 240 double buffer will not fit into a single 64k segment. Fortunately, since we've unchained our video memory, we can implement page flipping!

We have defined in video memory two "pages," each containing 320 x 240 bytes. One page is be active at any given time; this is the page to which we draw all images. The other page is be visible, which means that it is the page that is being displayed on the screen at the moment. When a scene has been rendered on the active page, by swapping the offsets of the two pages from the start of video memory, we make the active page visible, and the visible page active. This is much faster than double-buffering!



Collision Detection

In order for the game objects in the world to be able to interact with each other, we must perform what is known as collision detection. When Link collides with an enemy, for instance, we'll want a number of things to occur -- Link should take damage and recoil, and the corresponding sounds and graphics should be played and displayed. In order to implement collision detection, each sprite will have what's called a bounding box. This box defines the area of the sprite which is considered to be "substantial"; if the bounding box of one sprite overlaps that of another, then a collision has occurred.



Data Structures



Procedures