TI-Chess Team HQ


FAT-Engine - SDK (c) 2001/2002 TiCT
API v1.10 (Application Programming Interface)

Disclaimer

The FAT-Engine, its features, the demo examples, the sourcecode and the documentation are provided AS-IS. Please don't ask for other features or extensions or for more detailed documentations.

If you don't understand a feature or its usage check the sourcecode of the corresponding demo. It shouldn't be hard to find out how the actual features of the FAT-Engine can be used.

Especially the sourcecode of the engine is provided AS-IS. The internals are too complicated to explain them in a few sentences and I have NOT enough time to explain them in details. Sorry.

Bug reports and similar are VERY welcome. Please use our Messageboard at

http://pub26.ezboard.com/btichessteamhq for this.




Necessary and/or useful Programs and Links to Further Readings

The following Software was (is) used by me to develop The FAT-Engine:
A very good tutorial on Raycasting itself can be found at:

http://www.permadi.com/tutorial/raycast

Another very useful resource if you try to understand the techniques behind a raycasting engine is the sourcecode of Wolfenstein3D, DOOM and Quake which can be found here:

http://www.idsoftware.com/archives/sourcearc.html



Features and Limitations of the FAT-Engine

Due to the restriction of the calculator a raycasting engine like the FAT-Engine is somewhat limited. Here is a list of the limitations:

And here is the list of the features which are already build in:

Due to the restrictions of the AMS 2.0x versions every program which will use the FAT-Engine has to be located in ghostspace. This can be performed by either starting the program from the TICT-Explorer or with the use of a simple launcher program.
Since TIGCC 0.90 the compiler supports the commandline option -pack which can be used to exepack a program and generate a launcher program automatically. In my opinion this is the simpliest method to build a launcher and it gives your program the additionally benefit of being packed (needs less memory).

The following line shows how a program may be build exe-packed supposing the programs name is demo and the generated packed file should be called demodat:

tigcc -O3 -pack demodat demo.c



Getting started

The simplest possible program which uses the FAT engine may look like this (it just outputs the version number of the FAT engine):

#define USE_TI89
#define USE_TI92P
#define USE_V200

#include "fat.h"


void _main(void) {
     if (FAT_LoadEngine() != FAT_LOADOKAY) {
         ST_helpMsg("loading FAT engine failed");
     }
     else {
         ST_helpMsg(FAT_GetVersionString());
         FAT_UnloadEngine();
     }
}

Note that the include statement (include "fat.h") has to be almost the first line of your program. Only "#define SAVE_SCREEN" or the USE_XXX defines are allowed BEFORE it. Internally fat.h sets NO_EXIT_SUPPORT and includes tigcclib.h. So your program don't need any other include statements.

IMPORTANT: Make sure that your program DON'T USE "#define OPTIMIZE_ROM_CALLS". Otherwise your program may crash.

Function FAT_LoadEngine tries to resolve the FAT-Engine (fatlib.dll). It traverses the complete VAT to find a fitting version of this file (so it is not necessary that fatlib.dll is in the same directory than your program).

FAT_LoadEngine() may return one of these values:

Only if FAT_LoadEngine returns FAT_LOADOKAY it is valid to proceed and to use functions of the FAT engine! No further checking is done by the functions of the engine and your program will very likely crash if FAT_LoadEngine hasn't returned FAT_LOADOKAY.

Additionally: DON'T forget to call FAT_UnloadEngine BEFORE returning from main (only if loading was successful).


Due to the fact that is a very critical point I repeat it once again (in big letters this time ;-):

Don't use ANY function of the FAT-Engine BEFORE you have called FAT_LoadEngine(), otherwise your program will very likely crash!

Since v1.10 your program will not crash immediately if you call a FAT function before FAT_LoadEngine(). You will see a flashing screen and a message ("FATAL: FAT-Engine not loaded") will be displayed in the status bar. Nevertheless it is very likely that your program will crash later on, because your program will not get the expected return value (if there is any). You should never see that flashing screen. If you see it, you know you have to call FAT_LoadEngine() sooner in your program.




The World as the FAT-Engine sees it

The FAT-Engine lives in its own world which consists of squares and which is specified by a map. The map used in Demo 1 looks like this:

char map[16*16] = {
     1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1,
     1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3,
     2, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 2, 0, 3,
     3, 0, 2, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 2, 0, 3,
     1, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 3,
     1, 0, 2, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 2, 0, 3,
     1, 0, 1, 1, 1, 1, 1, 0, 0, 3, 1, 3, 1, 2, 0, 3,
     1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3,
     2, 0, 3, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 3,
     2, 0, 3, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 3,
     2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 3,
     2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 3,
     1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 2, 0, 3,
     2, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 3, 1, 2, 0, 3,
     3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3,
     1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 1, 3, 1, 1, 1, 1 };

Each entry in this map specifies if the corresponding square is empty (0) or filled with a cube which is textured on all sides with the specified texture number. Negative entries are ignored by the engine and treated as empty (0). You can use negative entries in the map to mark squares for your own game logic. For example: you could use negative entries to mark a square that it holds ammo of some type or a health pack. This way you don't have to use a separate map for stuff like this which saves some memory depending how large the used map is.
127 (CLOSED_DOOR_TILE) and -127 (OPEN_DOOR_TILE) are special values related to doors. Don't use them for anything else. For details about doors please read section "Doors Support" below.

Beside this logically setup the world of the FAT-Engine has the following constrains:




Functions, Tables and Structures

Beside FAT_LoadEngine() and FAT_UnloadEngine() the FAT-Engine supplies the following functions:




The most important part of the FAT-Engine is the render function and structure FATCONFIG. Structure FATCONFIG is defined like this:

typedef struct {
    short           map_width;       // width of the map
    short           map_height;      // height of the map
    char*           map_data;        // pointer to the map data itself (negative values gets ignored!)
    TEXCONFIG*      textures;        // pointer to the used textures (see section "Texture Formats")
    short           nr_sprites;      // number of sprites
    FATSPRITE*      sprites;         // the sprite array
    short           cam_xpos;        // camera position x
    short           cam_ypos;        // camera position y
    short           cam_orientation; // camera orientation (0 .. 575)
    unsigned short* dest_plane0;     // destination plane0 to copy result into (240x128)
    unsigned short* dest_plane1;     // destination plane1 to copy result into (240x128)
    unsigned short* background;      // pointer to image with 96x96 pixels and 2 planes
    unsigned long   frame_counter;   // frame counter (gets incremented by engine)
} FATCONFIG;

NOTE: dest_plane0 and dest_plane1 have to be pointers to even addresses (!!!) for speedup reasons. If you setup them with the results of GetPlane(0) and GetPlane(1) the display will be drawn at the left part of the LCD.

NOTE2: please read section "Texture Formats" to see how the 64x64 pixel textures and the background image have to be structured (At least the background image has to be supplied in a very special format).

NOTE3: Only camera orientation values between 0 and 575 are valid!

Special Angle Values

For speedup reasons the camera orientation ranges from 0 to 575. Headerfile fat.h contains the following defines for special angle values:

#define ANGLE_000    0
#define ANGLE_015   24
#define ANGLE_030   48
#define ANGLE_045   72
#define ANGLE_060   96
#define ANGLE_090  144
#define ANGLE_180  288
#define ANGLE_270  432
#define ANGLE_360  576   // DON'T (!!!) use this value, use ANGLE_000 instead

//-----------------------------------------------------------------------------
// angles when you look on the map as it is coded ...
//-----------------------------------------------------------------------------
#define ANGLE_NORTH  ANGLE_270
#define ANGLE_EAST   ANGLE_000
#define ANGLE_SOUTH  ANGLE_090
#define ANGLE_WEST   ANGLE_180

If you modify the camera orientation, please make sure that the angle is always in the valid range (0..575). You can do this for example by the following two lines:

while (angle<ANGLE_000) angle+=ANGLE_360;
while (angle>=ANGLE_360) angle-=ANGLE_360;   // note the EQUAL sign in the comparison here!
A more comfortable way is to use macro FAT_ClampAngle(). The macro will NOT modify its input parameter, but it returns the clamped value of its input. If you want to modify it's input use it like this:
angle = FAT_ClampAngle(angle);



Debugging Support and FAT-Console

Please read the following document: How To Debug Client Programs using the FAT-Console


Texture Formats

IMPORTANT NOTE: Every texture used with the FAT-Engine has to start on an even address!!

Background Image Format (96x96 pixels)

Due to speedups in version 0.63 of the FAT-Engine the 96x96 pixel background image which can be set in the FATCONFIG structure has to be supplied in a very special format. Instead of handing just a "normal" 96x96 pixel picture with 2 planes over to the engine each plane has to be supplied in a 6-strips format, where each strip is 16 pixel wide (2 bytes).
Suppose the following normal input data (the spacing will show already the strips):
unsigned char bg[96*12] = {
  1, 2,   3, 4,   5, 6,   7, 8,   9,10,  11,12,  // 1. line (6*2 bytes)
 13,14,  15,16,  17,18,  19,20,  21,22,  23,24,  // 2. line (6*2 bytes)
 25,26,  27,28,  29,30,  31,32,  33,34,  35,36,  // 3. line (6*2 bytes)
 37,38,  39,40,  41,42,  43,44,  45,46,  47,48,  // 4. line (6*2 bytes)
 49,50,  51,52,  53,54,  55,56,  57,58,  59,60,  // 5. line (6*2 bytes)
 61,62,  63,64,  65,66,  67,68,  69,70,  71,72,  // 6. line (6*2 bytes)
 ....
 ....
};
then the image has to be converted in the following format:
unsigned char bg[96*2] = {
  1, 2,13,14,25,26, .................  // 1. strip (96*2 bytes)
  3, 4,15,16,27,28, .................  // 2. strip (96*2 bytes)
  5, 6,17,18,29,30, .................  // 3. strip (96*2 bytes)
  7, 8,19,20,31,32, .................  // 4. strip (96*2 bytes)
  9,10,21,22,33,34, .................  // 5. strip (96*2 bytes)
 11,12,23,24,35,36, .................  // 6. strip (96*2 bytes)
};

I'll hope you guess what I mean.

Other Textures and Mask Planes

Since API 0.63 all used textures and mask planes have to rotated 90 degrees to the left. In directory src/tools you can find a tool called fixtex64 which performs this rotation on a 64x64 pixel ImageStudio export file (B/W or grayscale).
The FAT-Engine uses generally 64x64 pixel textures for it operations. Due to the fact that a single grayscale 64x64 texture takes 1024 bytes re-using of textures is necessary to keep the memory constrains at a moderate level. To support the re-using of textures not the pure plane data is handed over to the FAT-Engine, but an array of texture configuration structures has to be used.

The texture configuration structure (TEXCONFIG) is defined this way:

typedef struct {
    unsigned short* lightdata;   // pointer to a 16 "columns" wide strip of 64x64 texture (light plane data)
    unsigned short* darkdata;    // pointer to a 16 "columns" wide strip of 64x64 texture (dark  plane data)
    unsigned short* maskdata;    // a possible mask for it or NULL (ONLY USED FOR SPRITES!)
    unsigned short  mirrored;    // if set to STRIP_NORMAL this strip is rendered normal
                                 // if set to STRIP_MIRRORED this strip is rendered mirrored
                                 // if set to STRIP_IGNORE this strip will be ignored (not rendered)
                                 // IMPORTANT NOTE: STRIP_IGNORE works for sprite textures ONLY!
                                 //                 for wall textures STRIP_IGNORE is treated like STRIP_MIRROR!
}
TEXSTRIP;

typedef struct {
    TEXSTRIP strips[4]; // 4 texture strips
} TEXCONFIG;

Examine the demo programs to see how to setup the texture structures correctly.




Doors Support

Since v1.07 the FAT-Engine supports sliding doors. Doors have no depth and are rendered in the center of block either horizontally or vertically. By setting a position value between 0 and 64 the client can specify much a door is open (0 - completely closed / 64 - completely open).
Each door needs two adjacenting walls to be rendered correctly. The Adjacenting walls are rendered with a different texture than the texture which is defined for the complete adjacenting block.

In the map tiles which holds a door have to be marked with value CLOSED_DOOR_TILE (127). If a door is completely open you can set the value of the corresponding map tile to OPEN_DOOR_TILE (-127) to speedup rendering (but it is not necessary to set value OPEN_DOOR_TILE for correct rendering). Beside setting the map tile to value CLOSED_DOOR_TILE, you have to call function FAT_AddDoor() once to setup all necessary parameters for a door like textures and similar. Internally a door is represented by the following structure:
typedef struct {
    short              xtile;       // x position of door
    short              ytile;       // y position of door
    unsigned char      type;        // DOOR_HORIZONTAL or DOOR_VERTICAL (types for pushable walls will follow!)
    unsigned char      state;       // DOOR_OPEN, DOOR_OPENING, DOOR_CLOSED, or DOOR_CLOSING
                                    // Note: state is not evaluated by the engine, its only
                                    //       for the client to keep track of the state of a door
    short              position;    // 0 = closed, 64 or higher = open, between = partially open
    TEXCONFIG*         doortexture; // pointer to door texture
    TEXCONFIG*         sidetexture; // pointer to side texture

                                    //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    void*              clientdata;  // maybe used freely by the client program to
                                    // store any data it wants (NOT USED BY ENGINE)
                                    //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
} FATDOOR;
Up to MAX_NR_DOORS (64) doors can be used in a level. The following functions are related to doors:
FAT_AddDoor()         ... add door to level
FAT_GetDoor()         ... get door at tile (x,y)
FAT_GetDoorsArray()   ... get FATDOOR array of all added doors (sorted by y)
FAT_GetNrDoors()      ... get number of added doors
FAT_RemoveAllDoors()  ... remove all added doors (for example if you load another level)
See the API docs above for more details about the doors related functions.

The FAT-Engine will not modify the entries within the FATDOOR structures. It is up to the client to "animate" the doors by updating their position value. This way the client can fully control how fast a door opens/closes as well as if doors could be partitionally opened (for example: stuck half-open).

AGAIN: To add a door which should be rendered by the FAT-Engine you have to use value CLOSED_DOOR_TILE (127) in the map AND you have to call FAT_AddDoor() once specifying the rest of the door data like textures and similar.



Sprite Support

The FAT-Engine supports sprites as well. The graphics data of sprites is defined by a number of TEXCONFIG entries: One TEXCONFIG entry for each supported viewing direction (a sprite should look like different if you view in from the front than from the back, isn't it?). Actually the engine supports any number of directions which are a power of 2 (1,2,4,8,16 ...), but it is optimized for 1 and 8-directional sprites.

Before you setup ANY field in a FATSPRITE structure, please make sure that you call function FAT_InitSprite(FATSPRITE* pointer_to_sprite) once and hand over a pointer to your FATSPRITE structure. This will fill all fields of the structures with 0.

The next important step during sprite setup is to set field drawmode of your FATSPRITE structure to one of the following values:

SPRITEMODE_UNUSEDdon't render this sprite
SPRITEMODE_SIZE64render full 64-bit height of sprite
SPRITEMODE_UPPER32render only 32-bit upper part of sprite
SPRITEMODE_LOWER32render only 32-bit lower part of sprite


As you can see from the above table it is possible to render only the upper or lower part of a sprite. The idea behind is that for small objects like medipaks which are lying on the ground it is a waste of time to render the 32-bit upper part of it, because it will be fully transparent. Nevertheless such a "half" sprite will need 64x64 textures, but you gain rendering speed.

For sprites field mirrored in structure TEXSTRIP can hold the following 3 different values:

STRIP_NORMALrender strip normally
STRIP_MIRRORrender strip mirrored
STRIP_IGNOREignore strip (don't render it)


IMPORTANT NOTE: STRIP_IGNORE is only handled for sprites yet (not for wall textures). A ignored strip is completely transparent which results in a great speedup during rendering. If your sprites contains empty strips it is a good idea to set the mirrored field to STRIP_IGNORE.

After you have initialized your FATSPRITE structure and you have set the drawmode, the most important step is to setup field sprites of the FATCONFIG structure to point to an array FATSPRITE structures and to set field nr_sprites to tell the engine the size of this array.

There is not much to know about the rest of FATSPRITE structure. Beside some internal data fields it contains the following ones (all entries which are important for a client program):
    short              xpos;        // x position of sprite
    short              ypos;        // y position of sprite
    short              orientation; // orientation of sprite (0 ... 575)
    short              nr_textures; // number of textures used for this sprite
                                    // (for example: 8 for 8 directional sprites)
    TEXCONFIG*         textures;    // pointer to start of TEXCONFIG array
    short              height;      // filled by FAT engine
    short              centerx;     // filled by FAT engine
    unsigned char*     clientdata;  // this pointer can be used freely by the client program
    unsigned short     drawmode;    // sprite drawing mode to use
    short              angle;       // filled by FAT engine

    struct _FATSPRITE* prev;        // used by FAT engine for reversed Z drawing
                                    // (if this is NULL, than the actual sprite is the
                                    // farthest away sprite which is still visible)

    struct _FATSPRITE* next;        // used by FAT engine for reversed Z drawing
                                    // (starting from the farthest away sprite this
                                    //  points to the next nearest sprite OR NULL if
                                    //  there are no more visible sprites)

Entry height will be filled by the engine during rendering. It contains the height in pixel of the sprite as seen from the actual point of view. If a sprite is not visible on the screen height will be set to -1

Entry centerx is filled by the engine during rendering, too. It contains the vertical position of the sprite in the 96x96 pixels FAT-Engine's view. If a sprite is not visible on the screen centerx will be set to -1.

Entry angle is filled by the engine during rendering and contains the angle between the camera orientation and the sprite. If a sprite is not visible on the screen angle will be set to -1.

Entries prev and next are used by the FAT-Engine for reversed Z drawing (The Engine draws the farthest away sprite first) and will be set "calculated" by the engine during rendering. Just follow pointer prev until it contains NULL. This sprite entry is the farthest away sprite which gets still drawn. Starting from the farthest away sprite you can follow pointer next to proceed to the next sprite in the sorted list until next contains NULL.
Normally a client program needs more informations about a sprite depending on the logic of the program. To store any information about the sprite you can use pointer clientdata. Just define an own structure for the necessary data and setup clientdata to point to an instance of this data.

Yet the FAT-Engine doesn't support different sprite states like "standing", "walking" or "running". The logic for states like this have to be implemented in the client program. The fastest way to handle the different graphics data of, for example, a walking sprite, just replace pointer textures periodically by another one.

For the TEXCONFIG array indices of 8-directional sprites fat.h contains the following useful defines:
#define TEX_AWAY          0
#define TEX_RIGHT_AWAY    1
#define TEX_RIGHT         2
#define TEX_RIGHT_TOWARD  3
#define TEX_TOWARD        4
#define TEX_LEFT_TOWARD   5
#define TEX_LEFT          6
#define TEX_LEFT_AWAY     7





[BACK TO DOCUMENTATION INDEX]


Thomas Nussbaumer Graz,Austria 07/05/2002