char
or short
;char
or short
; an element of that map is the index of a sprite in an array of 16x16 or 8x8 sprites.+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ |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).
272 <-----------------> ^ +-----------------+ | | ###### | | | ########## | | | #### ##### | | | #### #### | 160| | ###### ### | | | ########### | | | ########## | | | ###########| | | ######## | | | #### | v +-----------------+Sprite 0 is represented by ' ', sprite 1 is represented by '#'.
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.
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.char
for 8x8 sprites, or an array of 16 short
for 16x16 sprites, containing each line of the sprite.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.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.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.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.void DrawPlane(short x,short y,Plane *plane,void *dest,TM_Mode mode,TM_Type type);
plane
from x
and y
coordinates on the screen (virtual or not) dest
.plane
, type
and mode
are not ordinary, here are their specifications :plane
is the address of a Plane
structure, which is defined like this :typedef struct { void *matrix; // Matrix of tiles unsigned short width; // Map's width void *sprites; // Sprite array char *big_vscreen; // Big virtual screen long mask; // Contains the mask, when you want to use the BLIT mode long reserved1; // Internal use (do not modify) short force_update; // To force updating the big virtual screen }Plane;
type
indicates the type of the plane : the size of the sprites (16x16 or 8x8), the type of the matrix of tiles and it indicates if the function works in B/W or in grayscales. Its type is TM_Type
, this type is a bit complex, and you don't need to know exactly what it is to use the function, because I wrote macros in the header file which can be used directly like a TM_Type
value. Read the appendix of this document to know all the allowed values.mode
indicates the draw mode : RPLC
, OR
, XOR
, AND
, TRANW
, TRANB
or BLIT
. The type of this parameter is TM_Mode
, this type is complicated too, if you really want to know what it is, look at the header file, but that's not needed to be able to use the functions because I wrote macros in the header file which can be used directly for a parameter TM_Mode
. Read the appendix at the end of this document to know all the allowed values.force_update
field. The DrawBuffer
function will clear this field after it updates the big virtual screen. You must do this in the initialization.BLIT
mode, put the mask value in the field mask
before calling the DrawBuffer
function.type
and mode
.void DrawAnimatedPlane(short x,short y,AnimatedPlane *plane,void *dest,TM_Mode mode,TM_AnimType type);
plane
form x
and y
coordinates to the screen (virtual or not) dest
.plane
parameter is the address of an AnimatedPlane
structure, which is defined like this :typedef struct { Plane p; void *tabanim; // Animation's matrix short nb_anim; // Number of animations short nb_step; // Number of animation's step short step; // Current step number short step_length; // Length of a step (in frames) short frame; // Current frame number for the current step }AnimatedPlane;This structure contains a
Plane
followed by all the necessary informations to animate it.Plane
will not contain sprite numbers, but animation numbers, and the function will find the corresponding sprite number in the animation's matrix tabanim
.mode
works exactly like in the previous function, please look at the appendix to know what are correct values.type
works like in the previous function, but its possible values are not the same, they're given in the apppendix.RefreshBuffer
familyRefreshBuffer
functions update a big virtual screen.void Refresh[Gray]BufferXY(short width,void *tile,void *dest,void *sprts);
Gray
is optional and specifies if the function works in grayscale or not.X
specifies sprite's size, and can only take these values : 16
(sprites of 16x16 pixels) or 8
(sprites of 8x8 pixels).Y
specifies the size of a tile in the matrix of tiles, and can only take these values : W
(matrix of words [2 bytes]) and B
(matrix of bytes).RefreshGrayBuffer16B
.width
: tile matrix width.tile
: address of the first tile to draw on the big virtual screen (the one on the left-up corner).dest
: address of the big virtual screen (its size must be 5440 bytes in black and white, or 10880 bytes in grayscale).sprts
: address of the sprite array.RefreshAnimatedBuffer
FamilyRefreshAnimatedBuffer
functions update a big virtual screen and animate its tiles.void Refresh[Gray]AnimatedBufferXY(short width,void *tile,void *dest,void *sprts,void *animarray);
Gray
is optional and specifies if the function works in grayscale or not.X
specifies sprite's size, and can only take these values : 16
(sprites of 16x16 pixels) or 8
(sprites of 8x8 pixels).Y
specifies the size of a tile in the matrix of tiles, and can only take these values : W
(matrix of words [2 bytes]) and B
(matrix of bytes).RefreshGrayBuffer16B
.width
: tile matrix width.tile
: address of the first tile to draw on the big virtual screen (the one on the left-up corner). This tile will not contain a sprite number, but an animation number.dest
: address of the big virtual screen (its size must be 5440 bytes in black and white, or 10880 bytes in grayscales).sprts
: address of the sprite array.animarray
: address of the sprites numbers array. It's an array of short
. The element n
of this array contains the sprite number of the current step for the animation n
.char matrix[MAP_WIDTH][MAP_HEIGHT]={...}; // Contains animation numbers short anim[NB_STEPS][NB_ANIMS]={...}; // Contains sprite numbers short sprts[NB_SPRITES][16]={...}; // Contains black and white sprites void _main(void) { char big_vscreen[BIG_VSCREEN_SIZE]; short old_sr,n_frame,n_step; old_sr=OSSetSR(0x0200); n_frame=n_step=0; do { if(!n_frame) // If it's the first frame of a step, we update the big virtual screen RefreshAnimatedBuffer(MAP_WIDTH,matrix,big_vscreen,sprts,anim[n_step]); DrawBuffer_RPLC(big_vscreen,0,0,LCD_MEM); if(!(++n_frame % 16)) // Every 16 frames, the animation's step changes n_step = (n_step+1) % NB_STEPS; }while(!_keytest(RR_ESC)); OSSetSR(old_sr); }We can first note that the library is not fully used, because coordinates passed to the DrawBuffer function are both 0. That's only to make the example shorter.
anim
.anim
become redundant. In this case, you should use another way : use only one array of sprite's numbers (instead of NB_STEPS
arrays like in the example), and update directly this array when you want.DrawBuffer
familyDrawBuffer
functions draw a big virtual screen into a screen (virtual or not).void Draw[Gray]Buffer[89]_MODE(void *src,short x,short y,void *dest);
Gray
is optional and indicates if the function works in grayscales or not.89
is optional too, it allows to draw only what is seen on a TI-89 screen (that's faster).MODE
specifies the draw mode, it can take these values : RPLC
, OR
, XOR
, AND
, TRANW
, TRANB
ou BLIT
. The draw modes are described in the appendix, at the end of this file.RPLC
mode, and in grayscales, you must use DrawGrayBuffer_RPLC
function.
: address of the big virtual screen to draw.x
: horizontal shift to apply, in pixels (Warning : must be between 0 and 31).y
: vertical shift to apply, in pixels (Warning : must be 0 and 31).dest
: address of destination screen (its size must be 3840 bytes in black and white, and 7680 bytes in grayscales).BLIT
mode are a little bit different of others, they take another parameter : the mask. Their prototypes look like :void Draw[Gray]Buffer[89]_BLIT(void *src, short x, short y, long mask, void *dest);
mask
contains mask value. Warning : the mask is 32 bits, to provide more flexibility, but it can be source of problems if you don't pay attention.DrawBufferWithShifts
familyDrawBufferWithShifts
functions draw a big virtual screen on a screen, but you can also specify the horizontal shift for each line, and add verticals shifts between lines.void Draw[Gray]BufferWithShifts[89]_MODE(void *src,short x,short y,void *dest,char *hshift,short *vshift);
Gray
is optional and indicates if the function works in grayscales or not.89
is optional too, it allows to draw only what is seen on a TI-89 screen (that's faster).MODE
specifies the draw mode, it can take these values : RPLC
, OR
, XOR
, AND
, TRANW
, TRANB
ou BLIT
. The draw modes are described in the appendix, at the end of this file.src
: address of the big virtual screen to draw.x
: horizontal shift, in pixels (Warning : must be between 0 and 15).y
: vertical shift, in pixels (Warning : must be between 0 and 15).dest
: address of destination screen.hshifts
: address of the array of horizontal shifts. When the function draws the big virtual screen to the destination, for each line, the corresponding value will be added at the horizontal shift.vshifts
: address of the array of verticals shifts. When the function draw the big virtual screen into the destination, at the end of each line drawed, the value of the array will be added at the pointer to the source (the big virtual screen). So, to draw two times the same line, for example, you just need to put the value -34
somewhere in the array (and to skip a line, put 34
).BLIT
mode, are a little bit different, they take another parameter : the mask. Their prototypes look like :void Draw[Gray]BufferWithShifts[89]_BLIT(void *src,short x,short y,long mask,void *dest,char *hshifts,short *vshifts);
mask
contains the mask value.RPLC
OR
XOR
AND
BLIT
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
TRANB
2D char arrays | 2D short arrays | |||
---|---|---|---|---|
8x8 sprites | 16x16 sprites | 8x8 sprites | 16x16 sprites | |
B/W | TM_8B | TM_16B | TM_8W | TM_16W |
Grayscale | TM_G8B | TM_G16B | TM_G8W | TM_G16W |
2D char arrays | 2D short arrays | |||
---|---|---|---|---|
8x8 sprites | 16x16 sprites | 8x8 sprites | 16x16 sprites | |
B/W | TM_A8B | TM_A16B | TM_A8W | TM_A16W |
Grayscale | TM_GA8B | TM_GA16B | TM_GA8W | TM_GA16W |
RPLC | OR | XOR | AND | BLIT | TRANW | TRANB | ||
---|---|---|---|---|---|---|---|---|
B/W | TI92+/V200 | TM_RPLC | TM_OR | TM_XOR | TM_AND | TM_BLIT | ||
TI89 | TM_RPLC89 | TM_OR89 | TM_XOR89 | TM_AND89 | TM_BLIT89 | |||
Grayscale | TI92+/V200 | TM_GRPLC | TM_GOR | TM_GXOR | TM_GAND | TM_GBLIT | TM_GTRANW | TM_GTRANB |
TI89 | TM_GRPLC89 | TM_GOR89 | TM_GXOR89 | TM_GAND89 | TM_GBLIT89 | TM_GTRANW89 | TM_GTRANB89 |
BLIT
functions.
Todo
In a possible next version, here's what I'd add (sorted by priority):
Contact information
For any comment, suggestion, bug report, etc., you can reach me at:
Julien Richard-Foy
julien.rf@wanadoo.fr