















                       Sprite & Scrolling Engine Manual

              Copyright (c) 1996 Genesoft.  All rights reserved.










No part of this manual may be reproduced, stored in a retrieval system, or
transmitted by any means, electronic, mechanical, photocopying, recording, or
otherwise, without express written permission from Genesoft. The software
described in this manual is furnished under a license agreement and may be
used or copied only in accordance with the terms of that agreement.

This manual and its associated software are sold without warranties, either
expressed or implied, regarding their merchantability or fitness for any
particular application or purpose.  The information in this manual is subject
to change without notice.  In no event shall Genesoft be liable for any loss
of profit or any other commercial damage, including but not limited to
special, incidental, consequential, or other damages resulting from the use
of or the inability to use this product, even if Genesoft has been notified
of the possibility of such damages.

All brand and product names mentioned in this manual are trademarks or
registered trademarks of their respective holders.



                               Table of Contents
                               -----------------
Chapter 1 -- Introduction

     About the Need for this Library ................................. 4

     About the Engine ................................................ 4

     Video Modes ..................................................... 4


Chapter 2 -- Tiles and Tile Maps

     Tile Basics ..................................................... 5

     Tile Graphic Capturing .......................................... 5

     Creating Tile Maps .............................................. 6

     Tile Animation .................................................. 7


Chapter 3 -- Sprites

     Sprite Basics ................................................... 8

     Sprite Capturing ................................................ 8

     Sprite Animation ................................................ 9


Chapter 4 -- Example Program Flow

     Setting Up ...................................................... 11

     Main Loop ....................................................... 11

     Exiting ......................................................... 12


Chapter 5 -- Direct Video Mode

     Direct Video Basics ............................................. 13

     Status Bar ...................................................... 13

     Using Fonts ..................................................... 13

     Direct Video Techniques ......................................... 14


Chapter 6 -- Palette Effects1

     Palette Basics .................................................. 15

     Palette Registers ............................................... 15

     Setting the Palette ............................................. 15

     Palette Fading .................................................. 15




Chapter 7 -- Keyboard Handler

     Keyboard Handler Basics ......................................... 17

     Key Naming Conventions .......................................... 17


Appendix A -- Programmer's Reference

     SSE.H - Main Header File ........................................ 18

     SSECAPT.H - Sprite and Tile Capturing Functions ................. 20

     SSEDVID.H - Direct Video Functions .............................. 21

     SSEKEYB.H - Keyboard Handler Functions .......................... 22

     SSEPAL.H - Palette Functions .................................... 23

     SSEUTIL.H - General Utility Functions ........................... 23


Appendix B -- Achieving the Best Results ............................. 24



                                                                        Page 4

                           Chapter 1 -- Introduction
                           -------------------------
                                       
                        About the Need for this Library

The major problem software developers have faced working on the PC has been
extremely slow video speed.  With the Sprite & Scrolling Engine Library,
almost anyone can create exceptionally fast 256-color animations.  This
Library is designed to make graphics programming easier and more flexible than
working with any other graphic library.  In addition, this Library is able to
work with ANY VGA-compatible video card in a variety of 256-color video modes.


                               About the Engine

The Sprite & Scrolling Engine Library has been designed to eliminate visible
flickering, tear-lines, jerky-animation and sprite ghosting which are found in
many existing packages today.  To do this, it has been designed to run at the
full frame rate of the selected video mode, and to make use of "Mode-X" (also
called "Tweaked" or "Unchained") modes.  This allows access to all of video
ram, as well as many different resolutions.  The Engine automatically
minimizes the amount of information being sent to the video card each frame.
When possible, it uses video-ram copying and hardware scrolling to further
improve performance.


                                  Video Modes

When the Engine is active it can be run in six different 256-color video
modes:
                    320 x 175      320 x 200 *    320 x 240 **
                    360 x 175      360 x 200      360 x 240

For menus and screens requiring higher resolutions, Direct Video functions
allow access to six more 256-color video modes:
                    320 x 350      320 x 400      320 x 480
                    360 x 350      360 x 400      360 x 480
as well as four 16-color video modes:
             320 x 200      640 x 200      640 x 350      640 x 480 **

Modes with vertical resolutions of 240 or 480 run at 60 frames per second, all
other modes run at 70 frames per second.


* The same resolution used by standard mode 13h
** This mode has a 1:1 aspect ratio (square pixels)
                                                                             
                                                                        Page 5

                       Chapter 2 -- Tiles and Tile Maps
                       --------------------------------

                                  Tile Basics

Tiles are simply rectangular blocks of graphics.  They are usually designed to
fit together in a number different combinations, allowing large worlds to be
created from a relatively small amount of graphics.

The Sprite & Scrolling Engine can handle up to 255 different tiles, and the
tile width must be divisible by four, (i.e. 4, 8, 12...) but the tiles can be
as large as you like.  If you don't want to have a tiled world, you can use a
single tile as your whole map, and make it as large as you need.

Tile Maps define how you would like your tiles to fit together to create your
world.  The section "Creating Tile Maps" below describes different ways of
making Tile Maps for the Engine to use.


                            Tile Graphic Capturing

Tiles used with the Engine must first be captured from one or more PCX files.
The utility provided to do this is called `CAPT-TIL'.  The palette set upon
initialization of the Engine is the palette used in the first PCX file.  This
utility must be given properly formatted PCX files.  The accepted format is as
follows:
   - the PCX can be any size, but must be 256-color and at least as wide and
high as one tile,
   - the tiles to be captured must be arranged edge to edge in order from left
to right and top to bottom;
The capture program WILL IGNORE the following sections of the PCX file:
   - any space on the right edge of the PCX not wide enough for a tile,
   - any space on the bottom edge of the PCX not high enough for a tile,
   - any tile positions past the number of tiles specified,
   - any tiles that are completely made up of color 255;

Example:
C:>CAPT-TIL 70 80 12 PCXONE.PCX PCXTWO.PCX MYTILES.TIL
             ^  ^  ^  ^...                  ^
Tile Width --'  |  |  |                     |
Tile Height ----'  |  |                     `--- Output File
Number of Tiles ---'  `------------------------- Input PCX File(s)

        PCXONE.PCX:                        PCXTWO.PCX:
        +-----+-----+-----+-----+--+       +-----+-----+-----+-----+--+
        |Tile |Tile |Tile |Tile |##|       |Tile |Tile |Tile |Tile |##|
        | [0] | [1] | [2] | [3] |##|       | [7] | [8] | [9] | [10]|##|
        +-----+-----+-----+-----+--+       +-----+-----+-----+-----+--+
        |Tile |Tile |     |Tile |##|       |Tile |#####|#####|#####|##|
        | [4] | [5] |  ^  | [6] |##|       | [11]|#####|##^##|#####|##|
        +-----+-----+--|--+-----+--+       +-----+-----+--|--+-----+--+
        |#####|#####|##|##|#####|##| <-.-> |#####|#####|##|##|#####|##|
        +-----+-----+--|--+-----+--+   |   +-----+-----+--|--+-----+--+
                       |               |                  |
        Solid 255 tiles are ignored.   |   Left-over tiles are ignored.
                                       |
                        Left-over edges are not used.
See Also: "TILES.PCX"
                                                                             
                                                                        Page 6


                              Creating Tile Maps

Most applications that use the Sprite & Scrolling Engine will use different
methods of creating Tile Maps.  A basic map-editor has been included with full
source code.  This editor has been provided "as-is" without extensive
documentation, and there will be no support for its use or modification.  The
structure of Tile Maps has been kept extremely simple in order to make their
creation a straightforward task.

The structure of Tile Maps is as follows:
   - an unsigned int (4 bytes) defining the map's width in tiles.
   - an unsigned int (4 bytes) defining the map's height in tiles.
   - an array of unsigned chars (width x height bytes) listing the map's tiles
from left to right and top to bottom.

For Example, to create a Tile Map in C arranged as follows: (where each number
represents a tile)
                             +---+---+---+---+---+
                             | 0 | 0 | 1 | 2 | 2 |
                             +---+---+---+---+---+
                             | 0 | 0 | 1 | 2 | 1 |
                             +---+---+---+---+---+
                             | 1 | 1 | 2 | 2 | 1 |
                             +---+---+---+---+---+
                             | 4 | 4 | 3 | 3 | 2 |
                             +---+---+---+---+---+

you could use a block of code like this:
-------------------------------------------------------------------------
unsigned int MyWidth = 5;
unsigned int MyHeight = 4;
unsigned char MyMap[ 5 * 4 ] = {
     0, 0, 1, 2, 2,                 /* List off tile numbers from */
     0, 0, 1, 2, 1,                 /* left to right and top to bottom */
     1, 1, 2, 2, 1,
     4, 4, 3, 3, 2 };

sseTileMapInfo * MyTileMap = (sseTileMapInfo*) & MyWidth;
-------------------------------------------------------------------------
And you would use MyTileMap to address the whole Tile Map.

This method works well for small Tile Maps, but for most large projects, you
will need to use a map-editor.  The map-editor provided is a good starting
point for your editor since much of what you will need is already provided.
Any game company will tell you it is a good idea to spend quite a bit of time
on your map-editor, as much of the work on your project is done creating maps
and setting up levels.  There are many ways of automating map-design,
including checking if the edges of chosen tiles 'fit' together, or being able
to tell the map-editor what sort of tile you want where, and letting it choose
the correct tiles.  Even the simplest form of automation can save hours of
work creating maps.
                                                                             
                                                                        Page 7
                                                                              

                                Tile Animation
                                --------------

Basic tile replacement can be achieved by altering the contents of the current
Tile Map within your main loop, as long as the tiles being changed are off-
screen.  If you want to replace any visible tiles, you must call
sseFlagRedrawScreen before the next call to sseUpdateScreen to force the
engine to redraw the entire screen.  Since calling sseFlagRedrawScreen means
the Engine will take much longer updating the screen, it is not recommended
for anything other than a map-editor.

For a tile to be considered off-screen it must have no part crossing the
scrolling area of the screen set when initializing the Engine.  i.e. Tile is
off screen exactly when:
  ( ( TileX + TileWidth <= ScreenX - ScrollX ) or
    ( TileX >= ScreenX + ScreenWidth + ScrollX ) ) and
  ( ( TileY + TileHeight <= ScreenY - ScrollY ) or
    ( TileY >= ScreenY + ScreenHeight + ScrollY ) )
where TileX, TileY are pixel coordinates from the upper-left corner of the
Tile Map, ScreenX, ScreenY are the values set when calling sseUpdateScreen,
and ScrollX, ScrollY are the values set when calling sseInitEngine.

or graphically:
                                        +---+
                            +-----------|On |---+
                     +---+  | +---------+---+-+ |
                     |Off|  | |               | |
                     +---+  / | Visible       | +---+
                          / | |   Screen      | |Off|
                        /   +---+       +---+ | +---+
        Scrolling Area      |On |       |On | | |
                            +---+       +---+ | |
-extends ScrollX pixels     | +---------------+ |
 left and right and ScrollY +---+---+-----------+
 pixels above and below         |Off|
 the Visible Screen.            +---+

By updating sections of the current Tile Map just outside the area being
scrolled into, you can make a very small Tile Map appear to be as large as you
like.  If you need a world that is 2000 x 2000 tiles, for example, it is
probably a better idea to use this method and keep the map on disk, than to
use 4 megabytes to store the map in memory.
                                                                             
                                                                        Page 8

                             Chapter 3 -- Sprites
                             --------------------
                                       
                                 Sprite Basics

Simply put, sprites are objects that appear to `hover' over your map without
destroying it.  They are designed to be created, moved, animated, and erased
very easily.

The sprites used in the Sprite & Scrolling Engine may be of almost any shape
and size, and may have multiple frames for animation.  To use sprites, you
must first understand the two basic concepts used: Sprite Data, and Sprite
Tracking.

Sprite Data is the information the Engine uses to draw and erase a sprite.
Each sprite stores this information in a single .SSP file, created by the CAPT-
SSP utility.  All the Sprite Data files must be loaded and registered (see
"Example Program Flow" below) before the engine can use them.

Sprite Tracking structures are used to tell the Engine what sprites you want
drawn, and where to draw them.  There is currently support for up to 128
active Sprite Tracking structures at one time, and each one may be used to
display one frame of any existing registered Sprite Data.


                               Sprite Capturing

The `CAPT-SSP' utility will convert properly formatted PCX files into .SSP
files for the Engine to use.  Because sprites can have multiple frames, and
each of those frames can be a different size, there must be a way to tell the
location and dimensions of each frame in the PCX.  To do this, the CAPT-SSP
utility looks for a rectangle of a specific Tag color outlining each frame.
It also uses a second color, the Background color, as the `see-through'
section of each frame.

The Background color is defined as the color of the pixel in the top-left
corner of the PCX.  The Tag color is defined as the next color found in the
PCX found in order from left to right and top to bottom.

Example where [x] represents a pixel of color x, and a and b are any color:

   .---+-- Top-Left pixel color is used as the Background color.
   |   |
   |  [a] [a] [a] [a] [a] [a] [a] [a] [a] [a] [a] [a] [a] [a] [a] [a]
   |  [a] [a] [a] [a] [a] [a] [a] [a] [a] [a] [a] [a] [a] [a] [a] [a]
   |  [a] [a] [a] [a] [a] [b] . . .
   |                       |
   `---.   .---------------+-- The next color found is used as the Tag color
       |   |
or    [a] [b] . . .

Once the CAPT-SSP utility has determined your Tag and Background colors, it
then looks for each of your sprite's frames.  The frames are ordered by the
location of their upper-left corner in the PCX.  The utility scans left to
right and top to bottom for frames, and returns them in the order it found
them.
                                                                             
                                                                        Page 9

Example:
C:>CAPT-SSP MYPCX1.PCX MYPCX2.PCX MYSPRITE.SSP
                  ^...            ^
Input PCX File(s)-'               |
Output File ----------------------'

      MYPCX.PCX:
      +-----------------------------------------------------------------+
      |                                                                 |
      |                                    +-----------------+          |
      |   +------------+    +---------+    | First Frame     |          |
      |   | Second     |    | Third   |    |                 |          |
      |   | Frame      |    | Frame   |    |                 |          |
      |   +------------+    |         |    +-----------------+          |
      |                     |         |                                 |
      |     +-----------+   +---------+                  +----------+   |
      |     | Fourth    |                 +-------+      | Fifth    |   |
      |     | Frame     |                 | Sixth |      | Frame    |   |
      |     |           |                 | Frame |      |          |   |
      |     +-----------+                 +-------+      +----------+   |
      |                                                                 |
      +-----------------------------------------------------------------+

See Also: "HELI*.PCX"


                               Sprite Animation

Sprite Animation is achieved by using active Sprite Tracking structures within
the main loop of your program.  Each active Sprite Tracking structure
represents an instance of a sprite somewhere on the map.  To create an
instance of a sprite, you must call sseInitSprite with the following
information:
   - which loaded Sprite Data to use,
   - the sprite's X,Y coordinates relative to the upper-left corner of the
screen,
   - what frame to show,
   - the sprite's priority relative to the other active sprites;

Example: ASprite = sseInitSprite( MySpriteData, 50, 60, 2, 0 );

sseInitSprite returns a pointer to an active Sprite Tracking structure
containing the information you sent it.  Every time your program calls
sseUpdateScreen, it reads all the information from the your active Sprite
Tracking structures to determine how to display each sprite on the screen.
So, by steadily changing a structure's X,Y coordinates each time through the
loop, that sprite will appear to be moving across the screen.  X values
increase to the right, Y values increase downward, and both are in pixels
where (0,0) is the upper-left corner of the screen.

For example, to move ASprite diagonally two pixels up and two pixels right
across the screen, you could use the following line in your main loop:
    ASprite->X += 2; ASprite->Y -= 2;
                                                                             
                                                                       Page 10

In the same way you update a sprite's location, you can also update the image
that the sprite displays with the Header pointer and Frame number.  The Header
pointer must always point to a valid, registered Sprite Header.  The Frame
number can be from 0 (the first frame) to one below the Sprite Header's
NumFrames value (the last frame), or -1 for no image.

For example, to continuously animate through the frames of Asprite you could
use the following line in your main loop:
     if( ++ASprite->Frame == ASprite->Header->NumFrames ) ASprite->Frame = 0;

A sprite's priority determines whether it will appear above or below sprites
that it overlaps.  The sprite with the higher priority will always appear
above the sprite with the lower priority.  To change the sprite's priority
after it has been created, call sseChangeSpritePriority with the sprite's
tracking structure pointer and the its new priority.  Priority values range
from 0 (least priority) to 100 (most priority).

Example: sseChangeSpritePriority( ASprite, 2 );

To disable a sprite, you call sseDisableSprite with a pointer to its Sprite
Tracking structure.

Example: sseDisableSprite( ASprite );


                                                                             
                                                                       Page 11

                       Chapter 4 -- Example Program Flow
                       ---------------------------------

                                  Setting Up

The first thing you must do before initializing the Engine is to make sure
your Tile Map, Tiles, and Sprite Data are in memory.  Your Tiles and Sprite
Data (usually stored as a .TIL and multiple .SSP files respectively) must be
loaded directly into memory that you allocate.  You should then have a
sseTileGraphicInfo pointer that points to your Tiles, and as many
sseSpriteHeader pointers as you need to point to your sprites.  If you have
stored your Tile Map in a separate file (as opposed to the example shown in
"Creating TileMaps" above) it must also be loaded, and pointed to by a
sseTileMapInfo pointer.  For an example of how this is done, see the LoadStuff
and LoadWholeFile functions in "HELIDEMO.C".

Now that you have all your data in memory, you must initialize the Engine by
calling sseInitEngine.  sseInitEngine must be passed information on the video
mode you want to use, the pointers to your Tiles and Tile Map, your maximum
X,Y scrolling distance per update, and the height of your Status Bar.  For
more information on this function, see "Appendix A - SSE.H".  For more
information about Status Bars see "Chapter 5 - Status Bar".

Example: sseInitEngine( MODE_320x240x256, MyTiles, MyMap, 8, 8, 0 );

The Engine has now configured itself to work with your Map and Tiles, but
before you can use any of your sprites, you must register each of them.  You
register sprites by passing each sprite's sseSpriteHeader pointer to the
sseRegisterSprite function.

Example: sseRegisterSprite( MyFirstSprite );
         sseRegisterSprite( MySecondSprite );
         etc.


                                   Main Loop

The main loop of programs using the Sprite & Scrolling Engine are designed to
be executed 60 or 70 times a second (depending on the video mode).  After
updating everything required by your program, the main loop must let the
Engine update all the graphics.  For an example of how this is done, see the
function MainLoop in "HELIDEMO.C".  For tips on how to get your loop to run at
full-speed, see "Appendix A" below.

Your main loop should be set up in the following order:
    1. Set the Palette *,
    2. Update the Status Bar *,
    3. Read user input,
    4. Update sprites,
    5. Calculate the next palette for step 1 *,
    6. Call sseUpdateScreen;

* if applicable
                                                                             
                                                                       Page 12

1. Set the Palette (if applicable): Setting the active palette within your
main loop allows for fading while still animating sprites etc.  This should be
done as soon as possible after calling sseUpdateScreen (step 6) to avoid
"noise" or "snow" on the screen.  For more information see "Chapter 6 -
Setting the Palette" below.

2. Update the Status Bar (if applicable): When using a Status Bar, you should
make any changes to it soon after step 6 to avoid visible flickering.  Note
that any changes made will be visible immediately, not after the next call to
sseUpdateScreen.  For more information about updating the Status Bar, see
"Chapter 5" below.

3. Read user input: At this point you will want to poll the keyboard, mouse,
joysticks and/or any other input devices to determine what the player wants to
do next.  For information about polling the keyboard state, see "Chapter 7"
below.

4. Update Sprites: You can now update all of your active Sprite Tracking
structures' locations and graphics.  For more information see "Chapter 3 -
Sprite Animation" above.

5. Calculate the next palette (if applicable): When steadily changing the
palette within your main loop you should calculate each new palette either
before entering your main loop or before calling sseUpdateScreen.  For more
information see "Chapter 6 - Palette Fading" below.

6. Call sseUpdateScreen: This is how you let the Engine update all the
graphics on the screen.  You must pass sseUpdateScreen your new desired X,Y
coordinates.  X values increase to the right, Y values increase downward, and
are measured in pixels.  Coordinates (0,0) represents the upper-left corner of
the map.  The maximum allowable coordinates are: ( Map Width x Tile Width -1,
Map Height x Tile Height -1 ). For more information see "Appendix A - SSE.H"
below.


                                    Exiting

When exiting, you do not need to disable the engine, or any of your active
sprites.  All that you need to do is free any memory you have allocated. If
you are exiting to the operating system, you should call sseRestoreVideoMode
to restore the video mode enabled the first time you called sseInitEngine or
dvSetDirectMode.
                                                                             
                                                                       Page 13

                           Chapter 5 -- Direct Video
                           -------------------------
                                       
                              Direct Video Basics

Direct Video Modes are provided to allow higher resolutions for menus and
screens requiring high detail, as well as to allow complete control over the
video memory.  To enable a Direct Video Mode, call dvSetDirectMode.

Upon entering a Direct Video Mode, the palette is set to the default VGA
palette, so you will probably want to set it to one of your own.  For more
information about capturing and setting the palette see "Chapter 6 - Setting
the Palette".

The Direct Video X,Y coordinate system starts at 0,0 in the upper left corner
of the screen and extends to Screen Width -1, Screen Height -1 in the lower
right corner (e.g. 359,479 for 360x480 mode).


                                  Status Bar

If you are using a Status Bar while the Engine is active, it is updated the
same way you would a Direct Video Mode.

The X,Y coordinate system starts at 0,0 in the upper left corner of the Status
Bar and extends to Screen Width -1, Status Bar Height (not -1) in the lower
right corner of the screen.  The one extra row is added for compatibility with
certain VGA-compatible cards that halve the height of the top row of pixels,
and add another half-height row at the bottom (the extra row) when using
Status Bars. If the Engine is run on a VGA-compatible card that does not do
this, the last row will not be visible.


                                  Using Fonts

The fonts used in the Sprite & Scrolling Engine may be up to 255 pixels high,
and each character may have a different width up to 255 pixels.  Once a font
is captured and loaded into memory, it can be made active by setting dvFont to
point to it.  With a font active, you can use dvPrintF, dvPutS and dvPutChar
to display text on the screen.

dfPrintF, dvPutS and dvPutChar all read and update dvCursorX and dvCursorY.
These coordinates position the text in pixels relative to the upper-left
corner of the screen (or Status Bar).  No clipping is performed when
displaying fonts, so you must be sure to keep all fonts completely on the
screen.

One method of changing the active font's color is by setting dvFontColor to
the desired color's number.  The other method is to set the elements of the
array dvAssignedColor to the different font colors used, then select the color
in the output as follows:
     dvAssignedColor[0] = 7;
     dvAssignedColor[1] = 4;
     dvPutS( "\a0This is color number 7, \a1And this is number 4." );
The \a character is used by dvPutS and dvPrintF to signal a color change.  The
digit immediately following the \a selects the Assigned Color from 0-9.
                                                                             
                                                                       Page 14

                            Direct Video Techniques

With Direct Video Functions, you are completely responsible for the drawing
and erasing of graphics -- anything you draw will stay there until overwritten
by some other graphics.  To create a counter, for example, you would use one
of the following methods:

1. The numbers used are part of a font, and are drawn on a single-colored
background:
     Write over the previous digits in the background color with the same font
or with dvDrawRectangle, before displaying the new number.
2. The numbers used are tiles:
     Update each number by simply drawing over the old one with dvDrawTile.
3. The numbers used are sprites, and are drawn on a single-colored background:
     Erase the old number with dvDrawRectangle before displaying the new one.
4. The numbers used are sprites or part of a font, and are not drawn on a
single-colored background:
     Capture the sections of graphics where the numbers will appear beforehand
     as either tiles or sprites, then use the appropriate tile or sprite to
     erase each digit before displaying the new number.

Writing directly to visible video memory means that you risk seeing your
program erasing then re-drawing a section of the screen.  To avoid this, you
should time your graphic updating to the vertical retrace (when the monitor is
not updating a visible area of the screen).  In Direct Video Mode you would do
this by calling dvWaitForRetrace before erasing then re-drawing.  When using a
Status Bar, do your updating right after calling sseUpdateScreen.  If you are
setting the palette in either case, you should do that before updating.

For more information on any of these functions, see "Appendix A - SSEDVID.H"
                                                                             
                                                                       Page 15

                          Chapter 6 -- Palette Effects
                          ----------------------------
                                       
                                Palette Basics

All of the video modes used with the Sprite & Scrolling Engine have a maximum
of either 16 or 256 colors.  Each color, or active palette register, can have
individually defined Red, Green and Blue intensities.  The combination of
these values create the actual color visible for each active palette register.
So, by changing the values of the active palette registers, many visual
effects may be achieved without altering the contents of the screen.


                               Palette Registers

Included in every Tile Set is a copy of the palette used by its tiles.  It is
stored in the form of an array of 256 palRegister structures.  sseInitEngine
automatically uses this palette to set the active palette when called.  You
can also capture palettes yourself with the `CAPT-PAL' utility.

Example:
C:>CAPT-PAL MYPCX.PCX MYPAL.PAL

The file generated by this utility is also an array of 256 palRegister
structures.  When creating or changing palRegister structures directly, make
sure to keep the Red, Green and Blue values within the allowed range: from 0
(off) to 63 (full intensity).  All of the palette functions use arrays of
palRegister's.


                              Setting the Palette

Once you have an array of palRegister structures in memory, you can use them
to set the active palette.  This is done by calling palSetActive.  You can
choose to set all of the palette, or only a specific section.

To set the entire active palette to SomePalette, you would type:
     palSetActive( SomePalette, 0, 256 );
Or to set active palette registers 20-25 with the first 5 registers in
SomePalette you would type:
     palSetActive( SomePalette, 20, 5 );


                                Palette Fading

Fading in and fading out are the most commonly used palette effects.  For
convenience, two very simple functions have been provided for these effects:
palFadeInActive and palFadeOutActive.  Both of these functions take control of
the processor throughout the entire sequence, but only need to be called once.
                                                                             
                                                                       Page 16

If you need more flexibility, (e.g. video animation while fading) you can use
one or more of the other palette functions within your main loop as follows:
   - Do normal main loop updating/sprite manipulation,
   - Calculate your desired palette with palBlendWithColor, palBlendPalettes,
palDarken and/or palMakeGrayScale,
   - Call sseUpdateScreen or dvWaitForRetrace,
   - Set the active palette to the calculated palette with palSetActive;
Note that you will need a palRegister array to store the calculated palette.

The functions palBlendWithColor, palBlendPalettes and palDarken are passed a
value ranging from 0 (0%) to 64 (100%) intensity.  This value is simply called
"Amount" in the function descriptions in Appendix A.  To fade to a color, to a
palette, or to black in your main loop you must steadily increase or decrease
this value each time through the loop.

For more information on any of these functions see "Appendix A - SSEPAL.H".

                                                                       Page 17

                         Chapter 7 -- Keyboard Handler
                         -----------------------------
                                       
                            Keyboard Handler Basics

The keyboard handler provided with the Engine is used to let your program know
which keys on the keyboard are being held down at any one moment.  When
active, no standard keyboard input functions (like scanf or getch) will work
properly.  The keyboard handler will also disable the usual effects of
pressing CTRL-BREAK or CTRL-ALT-DELETE.  To install the keyboard handler, you
must call keyInstallHandler, and to remove it you must call keyRemoveHandler.


                             Hardware Limitations

There are some hardware limitations in the average keyboard that appear when
using a keyboard handler.  First, the Pause/Break key found on most keyboards
does not report how long it is held down.  Second, certain combinations or
number of keys being held down will stop other keys reporting that they are
pressed.

To solve the first limitation, a variable called keyPauseFlag has been
provided that toggles between 0 and 1 each time the Pause key is pressed.
Your program should use this value instead of the PAUSE_PRESSED flag which
flips on then off almost instantaneously.

To solve the second limitation, try to avoid using too many keys other than
the arrow keys, SHIFT, CTRL and ALT.  Also, you may want to let the user
configure their keys in case the default combinations conflict on their
keyboard.


                            Key Naming Conventions

When the keyboard handler is active, each key on the keyboard's state is
stored in one of the elements of keyTable as a 1 for pressed or 0 for not
pressed.  To access the proper element easily, a set of define's has been
provided, each corresponding to a key or combination of keys.  The define's
are named as follows:

             A - Z: A_PRESSED - Z_PRESSED
             0 - 9: ZERO_PRESSED - NINE_PRESSED
          F1 - F12: F1_PRESSED - F12_PRESSED
Up,Down,Left,Right: UP_PRESSED, DOWN_PRESSED, LEFT_PRESSED, RIGHT_PRESSED
  Punctuation Keys: PERIOD_PRESSED, FORWARD_SLASH_PRESSED, etc.
        Other Keys: SCROLL_LOCK_PRESSED, INSERT_PRESSED, etc.

If there is more than one key corresponding to the same name (e.g. forward
slash, home, up) then the value of the define is 1 if either key is pressed or
0 if neither is pressed.  To specify just one of the keys, precede the define
with NUM_ for the key on the number-pad or MAIN_ for the key in the main
section of the keyboard.  For example, NUM_FORWARD_SLASH_PRESSED refers to
only the forward slash key on the number pad.

To find the define for a specific key, see the file "SSEKEYB.H".
                                                                             
                                                                       Page 18

                     Appendix A -- Programmer's Reference
                     ------------------------------------
                                       
                           SSE.H - Main Header File

palRegister:  This structure defines a single palette register's red, green
and blue intensities.  Valid values for each are from 0 to 63.  The structure
is as follows:
   - char Red;
   - char Green;
   - char Blue;

sseTileGraphicInfo:  This is the structure found at the beginning of all Tile
Sets.  It contains basic information about the Tile Set, as well as the
palette it uses.  The Tile Set's actual data immediately follows this
structure, and is Width x Height x NumTiles bytes long.  You should not alter
any of the information in the structure or in the data following it from
within your program.  The structure is as follows:
   - int NumTiles;
   - short int Width;
   - short int Height;
   - palRegister Palette[ 256 ];

sseTileMapInfo:  This is the structure found at the beginning of all Tile
Maps.  The Tile Map's actual data immediately follows this structure, and is
Width x Height bytes long.  This structure should not be altered after being
passed to sseInitEngine.  Changing the data following the structure is
allowed, but for any changes to take place on-screen, you must call
sseFlagRedrawScreen before the next sseUpdateScreen.  The structure is as
follows:
   - int Width;
   - int Height;

sseSpriteGraphicInfo:  This is the structure used to describe each frame of a
sprite.  Only the Width, Height, PivotX and PivotY values may be altered.  The
structure consists of the following:
   - int Reserved;
   - short int Width, Height;
   - short int PivotX, PivotY;
   - short int ActualWidth, ActualHeight;

sseSpriteHeader:  This is the structure found at the beginning of each Sprite
Data file.  The sprite's actual data follows this structure, and can be almost
any size.  You should not alter any information in the structure or in the
data following it from within your program.  Information about the sprite's
frames' dimensions can be found in the Frame array.  The structure is as
follows:
   - int IDNumber;
   - short int Type;
   - short int NumFrames;
   - int Flags, Reserved;
   - char * Data;
   - sseSpriteGraphicInfo Frame[ NumFrames ];

                                                                       Page 19

sseSpriteTracking:  This is the structure used to keep track of your instances
of sprites on the screen.  A pointer to an active tracking structure is
returned when you call sseInitSprite.  Any of the information stored in this
structure may be altered by your program.  The Header pointer must always
point to a valid, registered Sprite Header, and the Frame number must be less
than that Header's NumFrames.  The X,Y coordinates are in pixels relative to
the upper-left corner of the map.  The structure is as follows:
   - sseSpriteHeader * Header;
   - int X;
   - int Y;
   - int Frame;

sseModeInfo[]: This array of structures contains information about each
available video mode.  To find frame rate of the 360x240x256 video mode, for
example, you would type sseModeInfo[ MODE_360x240x256 ].FramesPerSecond.  Each
structure contains the following:
   - int HorizontalRes, VerticalRes;
   - int MaxColors;
   - int FramesPerSecond;

void sseInitEngine( int Mode, sseTileGraphicInfo * Tiles, sseTileMapInfo *
Map, int MaxXScroll, int MaxYScroll, int StatusBar ):  This is the function
that must be called to initially set up the Engine, and to change modes, Tile
Sets and/or Maps.  Once called, the function will set the video mode chosen,
set the palette to the one your Tiles use, and reset all internal Sprite
Tracking and scrolling information.  MaxXScroll and MaxYScroll set the maximum
pixels to scroll from one update to the next in the X and Y directions.
StatusBar sets the height of the desired status bar in pixels.  Accepted
values for Mode are:
- MODE_320x175x256       - MODE_320x200x256       - MODE_320x240x256
- MODE_360x175x256       - MODE_360x200x256       - MODE_360x240x256

void sseRegisterSprite( sseSpriteHeader * SprHdr ):  After loading your Sprite
Data and calling sseInitEngine for the first time, you must register all of
your Sprite Data with this function.

sseSpriteTracking * sseInitSprite( sseSpriteHeader * SprHdr, int X, int Y, int
Frame, int Priority ):  This function returns an active Sprite Tracking
structure to be used in your main loop.  The values you pass this function
will be copied into the structure returned.  If there are no free Sprite
Tracking structures, this function will return NULL.

void sseChangeSpritePriority( sseSpriteTracking * Spr, int Priority):  This
function will change an active sprite's priority.

int sseCheckCollision( sseSpriteTracking * Spr1, sseSpriteTracking * Spr2 ):
This function performs a rectangle collision check between two sprites, and
returns 1 if there is a collision, and 0 if there is no collision.

void sseDisableSprite( sseSpriteTracking * Spr ):  This function is used to
tell the Engine when you are done with an active Sprite Tracking structure.
                                                                             
                                                                       Page 20

void sseUpdateScreen( int X, int Y ):  This function does all of the work
involved in displaying the next frame.  The X,Y coordinates define where you
want the screen's upper-left corner to be relative to the upper-left corner of
the map.  The amount of time this function takes depends on the sprites that
need to be erased and drawn, the distance scrolled from the last frame, and
whether or not the screen must be re-drawn.  The screen must be re-drawn if:
   - the Engine has just been initialized,
   - the screen has scrolled further than MaxXScroll pixels in the X direction
or MaxYScroll in the Y direction,
   - the sseFlagRedrawScreen function has been called;

void sseFlagRedrawScreen( void ):  This function is used to force the Engine
to re-draw the screen.  It should only be used in map-editors when an on-
screen part of the Tile Map has been changed.

void sseRestoreVideoMode( void ):  This function sets the video mode back to
the mode that was enabled before calling sseInitEngine or dvSetDirectMode for
the first time.


                SSECAPT.H - Sprite and Tile Capturing Functions
  ** only necessary if you plan on creating modified versions of existing **
  ** capture utilities CAPT-SSP, CAPT-TIL, CAPT-PAL and CAPT-FNT or for   **
  ** capturing graphics from within a program (not recommended).          **

pcxHeader:  This is the structure containing the information about a PCX file.
It is used when loading PCX images to capture from.

imgInfo:  This structure is used to identify images that are sections of
larger images in memory.  The BytesPerRow value refers to the width of the
larger image, and the Data pointer points to the upper-left corner of the
smaller image.  The structure is as follows:
   - int Width, Height;
   - int BytesPerRow;
   - char * Data;

HiddenSpriteInfo:  These internal structures are used by the Engine to locate
a sprite's frames' draw and erase information.  They consist of the following:
   - int Draw;
   - int Erase[ 4 ];

TileLocInfo:  These internal structures are tagged onto the end of captured
Tile Sets for the map editor to use.  They are not necessary for the Engine to
function properly.  They consist of the following:
   - unsigned char FileNum;
   - unsigned char XPos;
   - unsigned short YPos;

void pcxGetHeader( pcxHeader * dest, FILE * fp ):  This function copies the
PCX header from the opened PCX file pointed to by fp to the structure pointed
to by dest.

void pcxDecodeToBuffer( char * dest, unsigned width, unsigned height, FILE *
fp ):  This function decodes the PCX file pointed to by fp to the buffer
pointed to by dest.  The buffer must be able to store width x height bytes.
                                                                             
                                                                       Page 21

void pcxGetPalette( char * dest, FILE * fp ): This function copies the palette
from the PCX file pointed to by fp to the buffer pointed to by dest.  The
buffer must be able to store 768 bytes (256 palRegister's).

imgInfo * imgFindNext( imgInfo * SrcImg, char * CP, unsigned char TagColor ):
This function returns the next image boxed by the color TagColor.  It searches
the larger image SrcImg from left to right and top to bottom, starting at the
pixel pointed to by CP within SrcImg.  If it does not find another image, it
returns NULL.

void captSetupSSPHeader( sseSpriteHeader * hdr, HiddenSpriteInfo * hsi, int
linelength ):  This function prepares an SSP SpriteHeader for capturing.

int captSetupSpriteGraphicInfo( sseSpriteGraphicInfo * SI, HiddenSpriteInfo *
HSI, imgInfo * img, short PivotX, short PivotY, unsigned char BackColor ):
This function prepares a SpriteGraphicInfo structure for capturing.  It
returns 0 on no error or -1 if the image pointed to by img is blank (all
BackColor).

char * captSSPFrame( sseSpriteGraphicInfo * SI, char * BufTop, char * out,
imgInfo * img, unsigned char BackColor, int DestLineLength ):  This function
captures the draw information of a single frame specified by img, using the
prepared SpriteGraphicInfo pointer SI.

char * captEraseFrame( sseSpriteGraphicInfo * SI, char * BufTop, char * out,
imgInfo * img, unsigned char BackColor, int DestLineLength ):  This function
captures the erase information of a single frame specified by img, using the
prepared SpriteGraphicInfo pointer SI.

char * captFontChar( dvFontCharInfo * FI, char * BufTop, char * out, imgInfo *
img, unsigned char BackColor ):  This function captures a single character of
a font specified by img.

char * captTile( char * out, imgInfo * img ):  This function captures a single
tile specified by img.


                      SSEDVID.H - Direct Video Functions

dvFontCharInfo:  These structures contain the exact pixel-widths of each
character in a font.  They consist of the following:
   - int Width;
   - int Reserved;

dvFontHeader:  This is the structure found at the beginning of every font data
file.  Only XMargin and YMargin may be altered.  These values correspond to
the number of pixels left blank between each character horizontally and
vertically.  The structure is as follows:
   - int IDNumber;
   - unsigned char NumChars;
   - unsigned char Height;
   - unsigned char XMargin;
   - unsigned char YMargin;
   - dvFontCharInfo Character[ NumChars ];
                                                                             
                                                                       Page 22
void dvSetDirectMode( int Mode ):  This function sets up a full screen direct
video mode, disables the Engine, and allows direct access to the video memory.
Accepted values for Mode are:
     - MODE_320x350x256       - MODE_320x400x256       - MODE_320x480x256
     - MODE_360x350x256       - MODE_360x400x256       - MODE_360x480x256
     - MODE_320x200x16        - MODE_640x200x16        - MODE_640x350x16
     - MODE_640x480x16
as well as the modes used by sseInitEngine:
     - MODE_320x175x256       - MODE_320x200x256       - MODE_320x240x256
     - MODE_360x175x256       - MODE_360x200x256       - MODE_360x240x256

void dvDrawRectangle( int X, int Y, int Width, int Height, int Color ):  This
function draws a solid filled rectangle in any Direct Video Mode or on a
Status Bar.

void dvDrawSprite( sseSpriteHeader * SprHdr, int X, int Y, int Frame ):  This
function draws a single frame from any loaded Sprite Data in any 256-color
Direct Video Mode or on a Status Bar.

void dvDrawTile( sseTileGraphicInfo * Tiles, int X, int Y, int Number ):  This
function draws a single tile from any loaded Tile Set in any 256-color Direct
Video Mode or on a Status Bar.  Note: the X value must be divisible by four.

dvFontHeader * dvFont:  This pointer is used to select the current font.  It
must be set to a valid font in memory before using dvPrintF, dvPutS or
dvPutChar.

int dvCursorX, dvCursorY:  These coordinates are used for positioning
characters on the screen.  Output from dvPrintF, dvPutS and dvPutChar will
appear immediately below and to the right of this location.

unsigned char dvFontColor:  This value is used to set the current font's
initial color.

unsigned char dvAssignedColor[10]:  This array contains the colors assigned to
the numbers 0-9 when using \a# in dvPrintF and dvPutS.

void dvPrintF( char * format, ... ):  This function prints a printf-style
formatted string to the screen.  No clipping is performed.

void dvPutS( char * string ):  This function prints a string to the screen.
No clipping is performed.

void dvPutChar( char c ):  This function prints an individual character to the
screen.  No clipping is performed.

void dvWaitForRetrace():  This function will wait for the monitor to enter a
vertical retrace before returning.


                    SSEKEYB.H - Keyboard Handler Functions

void keyInstallHandler( void ):  This function replaces the standard BIOS
keyboard handler with the Engine's keyboard handler.  While the keyboard
handler is installed, none of the standard keyboard input functions will work
properly.
                                                                             
                                                                       Page 23

void keyRestoreHandler( void ):  This function restores the standard BIOS
keyboard handler.
                                                                              
volatile char keyPauseFlag:  When the keyboard handler is installed, this
variable is toggled between 0 and 1 each time the pause key is pressed.

volatile char keyTable[128]:  Each entry in this array corresponds to a key on
the keyboard.  When the keyboard handler is installed, each entry will be set
to 1 if its key is pressed or 0 is it is not.  For a list of keys' positions
within this array, see the file "SSEKEYB.H".


                         SSEPAL.H - Palette Functions

void palSetActive( palRegister * SrcPal, int Start, int Registers ):  This
function sets Registers number of active palette registers starting at number
Start from the palRegister array SrcPal.

void palFadeOutActive( palRegister * SrcPal, char Speed ),
void palFadeInActive( palRegister * SrcPal, char Speed ):  These functions
fade SrcPal completely to or from black.  Speed is a value from 0 (slowest) to
5 (fastest).

void palBlendWithColor( palRegister * DestPal, palRegister * SrcPal, char
Amount, palRegister * SrcReg, int Registers ):  This function will blend
Registers number of palRegister's in SrcPal with the palRegister SrcReg and
put the resulting palRegister array in DestPal.  Amount is a value from 0
(100% SrcPal) to 64 (100% SrcReg).

void palDarken( palRegister * DestPal, palRegister * SrcPal, char Amount, int
Registers ):  This function will darken Registers number of palRegister's in
SrcPal and put the resulting palRegister array in DestPal.  Amount is a value
from 0 (not darkened) to 64 (completely black).


void palBlendPalettes( palRegister * DestPal, palRegister * PalOne, char
Amount, palRegister * PalTwo, int Registers ):  This function will blend
Registers number of palRegister's in PalOne with the palRegister's in PalTwo
and put the resulting palRegister array in DestPal.  Amount is a value from 0
(100% PalOne) to 64 (100% PalTwo).

void palMakeGrayScale( palRegister * DestPal, palRegister * InPal, int
Registers ):  This function creates a gray-scale equivalent of Registers
number of palRegister's of InPal and puts it in DestPal.


                     SSEUTIL.H - General Utility Functions

void memCopy( void * Dest, void * Source, int NumBytes ):  This function
copies NumBytes bytes from the location pointed at by Source to the location
pointed at by Dest.  If the Source and Dest areas overlap this function will
not work properly.  To copy overlapping areas of memory, use the standard
function memmove.

void memByteFill( void * Dest, char Value, int NumBytes ):  This function will
fill NumBytes bytes of memory starting at the location pointed at by Dest with
Value.

                                                                             
                                                                       Page 24

                   Appendix B -- Achieving the Best Results
                   ----------------------------------------

The most challenging part of working with the Sprite & Scrolling Engine is
getting your program's look and feel just right.  First you should make sure
your code will run at a full 60 or 70 frames per second on the majority of
systems.  The following are some guidelines to follow if you want maximum
performance from your code, and from the Engine:

1. Avoid DOS and BIOS calls.  This includes most of your compiler's library
functions, as they often call the DOS or BIOS functions themselves.  The
problem with these calls is that they are not designed for speed, and are
usually too slow to be called from within your main loop.  Code that reads
directly from the keyboard, joystick, and mouse is much faster, and can be
better tailored to suit your program's needs.

2. Stagger your load.  When possible, try to spread large jobs across two or
more frames -- try to keep the amount of time spent in your code as even as
possible from frame to frame to lessen the chance of slow-downs.  The music
engine you use should be designed with this in mind.

3. Go easy on the sprites.  The Engine has been designed to keep track of up
to 128 sprites, but the fewer there are, the less time sseUpdateScreen takes.
If you have a large number of sprites, you should always disable the sprites
that go off-screen, and re-initialize them when they come back on.

4. Monitor your scrolling speed.  If the difference between the current screen
coordinates and the previous screen coordinates exceeds the maximum x or y
scrolling distance, the Engine will need to re-draw the whole screen.  If it
does re-draw the whole screen, sseUpdateScreen will take much longer than it
would normally.

Second, you should keep your animation and scrolling as smooth as possible.
The following are some guidelines to follow to avoid jerky movement and
animation:

1. When moving a sprite, or scrolling in a straight line, keep the speed and
direction constant.  Approximating a speed and direction by switching between
two values will cause the sprite or screen appear to vibrate as it moves.

2. When making sprite animation sequences, create a different frame for each
screen update.  So, for a sequence lasting 1/4 of a second in 320x240 mode,
you will need 15 frames.
