Documentation of TileMap Engine v0.3 (01/19/2004)



Introduction


Before describing the functions, I'd rather describe the way the library works.

First, the kinds of programs where using a tilemap engine is relevant are:
The kinds of programs where a tilemap engine shouldn't be used are: The library is useful for games needing a large background, larger than the 92+/V200 screen, in which the screen can be scrolled by down to one pixel at a time.

In this algorithm, the sprite plane (map / level) is a two-dimensional array of char or short; an element of that map is the index of a sprite in an array of 16x16 or 8x8 sprites.
This method has a clear advantage: a sprite can be used multiple times in the map, but the sprite data is defined only once (32 bytes for a 16x16 sprite, 8 bytes for a 8x8 sprite), and a sprite is referenced through its index (1 or 2 bytes depending on the type of the elements in the sprite plane). If the map was not used, then each tile in the map would be 8 or 32 bytes, and the map could become redundant. This way, a lot of space is saved.
Then, drawing the plane on the screen is performed in two steps:
Using an intermediate plane can be seen as unnecessary sometimes, but this method has many advantages. The virtual screen is refreshed only when necessary, when using animated tiles (usually 3 or 4 times per second, i.e. one image out of 5 or 6 for a game running at 20 fps) or when the bounds of the virtual screen are exceeded (which does not happen much more than once or twice per second).
Also, the function drawing the big virtual screen to the real screen can be highly optimized, instead of having to support any size. It is called every cycle and is very fast.

Here is a diagram to help you understand the algorithm:
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|00|00|00|00|00|00|00|00|01|01|01|00|00|00|00|00|00|00|00|00|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|00|00|00|00|00|00|01|01|01|01|01|01|00|00|00|00|00|00|00|00|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|00|00|00|00|00|01|01|01|01|01|01|01|01|01|01|00|00|00|00|00|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|00|00|00|00|00|01|01|01|01|00|00|01|01|01|01|01|00|00|00|00|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|00|00|00|00|01|01|01|01|00|00|00|01|01|01|01|00|00|00|00|00|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|00|00|00|00|01|01|01|01|01|01|00|01|01|01|00|00|00|00|00|00|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|00|00|00|00|00|01|01|01|01|01|01|01|01|01|01|01|00|00|00|00|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|00|00|00|00|00|00|00|00|01|01|01|01|01|01|01|01|01|01|00|00|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|00|00|00|00|00|00|00|00|01|01|01|01|01|01|01|01|01|01|01|00|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|00|00|00|00|00|00|00|00|00|01|01|01|01|01|01|01|01|00|00|00|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|00|00|00|00|00|00|00|00|00|00|00|01|01|01|01|00|00|00|00|00|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|00|00|00|00|00|00|00|00|00|00|00|00|01|00|00|00|00|00|00|00|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
The area we want to draw on the screen is drawn here with red color. In this example, only two different sprites are used, and sprite 1 is in bold so that the shape can be seen more easily. This map could be used in a RPG, to represent an island containing a lake (sprite 0 being water and sprite 1 being land).
Each square represents a 16x16 sprite.
The red area is 272x160 pixels, this means only a part of this area will be drawn on the real screen.

The red area is copied to the big virtual screen, with sprites being drawn from the map indices.
Here is the result on the big virtual screen (not drawn):
              272
     <----------------->
   ^ +-----------------+
   | |    ######       |
   | |   ##########    |
   | |   ####  #####   |
   | |  ####   ####    |
160| |  ###### ###     |
   | |   ###########   |
   | |      ########## |
   | |      ###########|
   | |       ########  |
   | |         ####    |
   v +-----------------+
Sprite 0 is represented by ' ', sprite 1 is represented by '#'.
Now, the only task left is to draw the desired part of the virtual screen to the real screen.
My diagrams aren't precise enough to draw this last step, so I'll draw only a part of the real screen.
Let's say we want to draw the area starting at [35, 21], but the virtual screen contains the map area starting at [32, 0]. Therefore, we have to start fetching the data from the virtual screen at [3, 21].
The result on the real screen will look like:
            16
    <---------------->
  ^ +----------------+----------------+----------------+---------------
  | |             |  |           ^ |  |             |  |             | 
  | |             |  |           | |  |             |  |             | 
  | |             |  |         11| |  |             |  |             | 
16| |      13     |  |           | |  |             |  |             | 
  | |<----------->|  |           v |  |             |  |             | 
  | |-------------+--|-------------+--|-------------+--|-------------+-
  | |             |  |             |  |             |  |             | 
  | |             |  |             |  |             |  |             | 
  v +----------------+----------------+----------------+---------------
    |             |  |             |  |             |  |             | 
    |             |  |             |  |             |  |             | 
    |             |  |             |  |             |  |             | 
    |             |  |             |  |             |  |             | 
    |             |  |             |  |             |  |             | 
    |-------------+--|-------------+--|-------------+--|-------------+-
    |             |  |             |  |             |  |             | 
    |             |  |             |  |             |  |             | 
    +----------------+----------------+----------------+---------------
    |             |  |             |  |             |  |             | 
    |             |  |             |  |             |  |             | 
    |             |  |             |  |             |  |             | 
    |             |  |             |  |             |  |             | 
    |             |  |             |  |             |  |             | 
    |-------------+--|-------------+--|-------------+--|-------------+-
    |             |  |             |  |             |  |             | 
The real screen and the big virtual screen are only shown as 16x16 tile boundaries. The real screen is drawn with black, and the big virtual screen is drawn with light gray.


How to use the tilemap engine in your programs ?

In the TIGCC IDE, add files TileMap.a and Tilemap.h to your project, and add #include "TileMap.h" in your source files.


Description of the functions

The functions provided by the library can be splitted in two categories : low level functions (powerful, but not easy to use) and high level functions (easier to use, but slightly less powerful).
For usual use, high level functions should be enough, but in some cases, you'll need to use low level functions (if you want to make a complex game, or if you program in assembly).
High level functions allow you to do everything which is possible with low level functions, except use of shift arrays.

If you program in assembly, you need to know how the parameters are passed to the functions. They are passed by registers, read the header file to know precisely which register corresponds to which parameter.



  1. Data structures used by the functions
  2. From begining, we mention matrix of tiles, sprite array, big virtual screen, or virtual screen. Here are their details:

    Matrix of tiles
    Matrix of char or short, with two dimensions. Its size must be at least 8 rows and 15 columns with 16x16 sprites, or 16 rows and 30 columns with 8x8 sprites.


    Sprites
    The sprites can be in grayscale or in B/W, and their size can be 16x16 or 8x8 pixels. There are specific functions for each type of sprite, so you must be careful when choosing.
    Black and White sprites are classics : a simple array of 8 char for 8x8 sprites, or an array of 16 short for 16x16 sprites, containing each line of the sprite.
    Grayscale sprites use a more complex format : an array of 16 char for 8x8 sprites, or 32 short for 16x16 sprites, it contains the first line of the sprite for the first plane, the first line for the second plane, the second line of the sprite for the first plane, the second line of the sprite for the second plane, etc... It's called an interlaced format.
    The first plane can be the light or the dark plane, that doesn't matter, but respect the convention in your virtuals screens (see below).


    Sprite array
    The sprite array can be seen like an 1D array containing sprites, but it's actually a 2D array, because sprites are already an 1D array.


    Matrix of animations
    2D array of short : the number of rows is the number of animation steps, and the number of columns is the number of animations. Each cell contains the number of the sprite for a step for an animation.


    Array of horizontal shifts
    Array of char, with one dimension, of 128 elements. Each element is a horizontal shift to add to the current line when the big virtual screen is drawn on the screen. Correct values are between 0 and 16.


    Array of vertical shifts
    Array of short, with one dimension, of 128 elements. Each element is a value to add to the pointer on the source, at the end of each line drawed, when the big virtual screen is drawed on the screen. Any value is allowed, but be careful to not point outside of the big virtual screen.


    Big virtual screen
    Buffer of 5440 bytes in B/W, or 10880 bytes in grayscale (in this case, the 5440 first bytes are the first plane and the 5440 followed bytes are the second plane ; you can choose which plane is the light or the dark plane, but keep this convention in your sprites).


    Virtual screen
    Buffer of 3840 bytes in B/W, or 7680 bytes in grayscales (in this case, like the big virtual screen, the two planes will be followed).


  3. High level functions

  4. Note that prototypes and usage of the tilemap engine functions may/will change in ExtGraph 2.00 Beta 3.



  5. Low level functions
  6. There are several families of functions, which do a specific task in several modes. The library provides 64 different functions, with more than 380 combinations...


    Note that prototypes and usage of the tilemap engine functions may/will change in ExtGraph 2.00 Beta 3.


The description of the functions is finished, so I reccomend that you read the examples provided to understand how using them.
The example 1 (demo13 in ExtGraph) uses high level functions, it shows how to draw more than one plane to give illusion.
The example 2 (demo14 in ExtGraph) is obsolete, it uses low level functions to show how to make a map with animated tiles (for a RPG for example), but without using functions for animated maps (they weren't written when I wrote this example).
The example 3 (demo15 in ExtGraph) is the same than the example 2, but it uses the functions for animated planes.
The exemple 4 (demo16 in ExtGraph) uses low level functions and shifts arrays.


Credits

  • I must thank PpHd, since I copied the algorithm from his tilemap engine.
  • I thank Lionel Debroux and Malcolm Smith for their help with the English translation of the documentation



  • Appendix


    Description of the various drawing modes :

    RPLC
    Completely RePLaCes the destination (clearing it before is useless). You should use this mode to display a background.


    OR
    Logical OR between the source and the destination.


    XOR
    Logical XOR (eXclusive OR) between the source and the destination.


    AND
    Logical AND between the source and the destination.


    BLIT
    This mode uses the field mask of the Plane structure, or the mask is passed to the low-level functions. A logical AND is performed between the mask and the destination, and then the plane is drawn with a logical OR between the source and the destination. This mode can be useful to create transition effects.


    TRANW
    The White color is TRANsparent, the other colors are opaque. This mode is very useful to draw planes over a background.


    TRANB
    The Black color is TRANsparent, the other colors are opaque. This mode is very useful to draw planes over a background.



    Table summarizing the different plane types:

    (elements have type TM_Type)
    2D char arrays2D short arrays
    8x8 sprites16x16 sprites8x8 sprites16x16 sprites
    B/WTM_8BTM_16BTM_8WTM_16W
    GrayscaleTM_G8BTM_G16BTM_G8WTM_G16W



    Table summarizing the different animated plane types:

    (elements have type TM_AnimType)
    2D char arrays2D short arrays
    8x8 sprites16x16 sprites8x8 sprites16x16 sprites
    B/WTM_A8BTM_A16BTM_A8WTM_A16W
    GrayscaleTM_GA8BTM_GA16BTM_GA8WTM_GA16W



    Table summarizing the different drawing modes

    (elements have type TM_Mode)
    RPLCORXORANDBLITTRANWTRANB
    B/WTI92+/V200TM_RPLCTM_ORTM_XORTM_ANDTM_BLIT
    TI89TM_RPLC89TM_OR89TM_XOR89TM_AND89TM_BLIT89
    GrayscaleTI92+/V200TM_GRPLCTM_GORTM_GXORTM_GANDTM_GBLITTM_GTRANWTM_GTRANB
    TI89TM_GRPLC89TM_GOR89TM_GXOR89TM_GAND89TM_GBLIT89TM_GTRANW89TM_GTRANB89



    History

    v0.3 (01/19/2004)
    English translation of the documentation


    v0.2 (12/26/2003)
    Added functions animating tiles automatically, and independent horizontal / vertical shifts for each line.
    Several bugfixes on BLIT functions.


    v0.1b (12/21/2003)
    No function was added, but all functions were rewritten because the size of the large virtual screen was changed, so as to have better adaptability.
    The use of high-level functions shouldn't have changed, but that of low-level functions changed.


    v0.1 (12/19/2003)
    First release.


    Todo

    In a possible next version, here's what I'd add (sorted by priority):
  • More drawing modes (if several persons ask me for a particular mode, I'll add it).
  • On-PC map/sprite editor.
  • Horizontal and vertical flipping.



  • Contact information

    For any comment, suggestion, bug report, etc., you can reach me at:
    Julien Richard-Foy
    julien.rf@wanadoo.fr