xLIBC

xLIBC is a hybrid TI-BASIC graphics library for the color-screen TI-84 Plus C Silver Edition, and included in Doors CSE 8.0 and above.

Developer Notes #

The TI-84+CSE version of xLIB has some key differences from its previous counterparts. One of the most obvious ones is the facility to utilise ‘internal user variables’ for data storage and calculations as opposed to using TIOS variables. Note that most functions have versions (usually version ‘A’ (like ‘DRAWMAPA’ for example) still take TIOS variables as arguments. These user vars help xLIB update data in the functions themselves and can save calculation time in your program.

IMPORTANT - User variables are only temporary and are stored at PlotsScreen (MEM: $987C). Please ensure that you are not using this memory area while executing your program as it may produce unexpected results.

The other issue is the way xLIB uses GRAM as a frame buffer as opposed to using RAM. This helps speed up drawing (as it avoids full screen copies) however there are some design issues presented for programmers. You must be mindful of the background behind sprites, whether it be a tilemap, a bgpic or a solid colour.

When drawing sprites over tilemaps it is faster to simply draw the tiles that were behind the sprite instead of redrawing the entire map. Drawing the tiles behind the sprite will effectively ’erase’ the sprite. The typical program flow for a tilemap+sprites demo would be:

Load tile graphics into memory
Set sprite coordinates
Copy sprite coordinates to temp coordinates
Draw tilemap, update LCD (switch buffers)
Draw tilemap, don't update LCD (drawing to back buffer) <-- now both sides of GRAM have the tilemap drawn
Loop start:
  Draw sprite, update LCD (switch buffers)
  Draw tile as sprite to temp coordinates (old sprite position in back buffer) <-- use drawsprite+gettile
  Copy sprite coordinates to temp coordinates
  Update sprite coordinates
 Loop end

The map is initially drawn to both sides of GRAM outside of the main loop. Drawing maps is slow on the TI-84+CSE due to the higher resolution. The sprite is drawn in the main loop to the back buffer, then the LCD is updated to show the sprite on screen This swaps the old sprite (that was in the front buffer (on screen)) to the back buffer (off screen). We can then draw over this sprite using drawsprite and the gettile function. We keep track of the old sprite coords every frame and pass those to the gettile function. We then draw the resultant tile at this position and the sprite is effectively ’erased’, restoring the map to its original state. Then we simply copy the current sprite coords to our temp coords before we update them with keypresses etc.

This works because each tile in a tile map is an index in a tilepic (which is loaded into RAM). The sprite function takes a index to a tilepic as well so you can use these functions together. This can greatly improve performance.

xLIBC Program Example #

This is an example of a very simple tilemap+sprite program. This example code uses TIOS variables for data storage:

This will draw a tilemap background to both GRAM buffers and loop sprite drawing + key detection. There are no checks for collisions in this example:

:prgmTESTMAP
:real(0,1,1
:"TESTTILE
:real(5,0,0
:32->X
:16->Y
:X->S
:Y->T
:real(3,0,0,0,20,9,0,0,19,14,1
:real(3,0,0,0,20,9,0,0,19,14,0
:0->K
:Repeat K=15
:real(2,0,0)->K
:real(4,0,X,Y,1,1,0,0,248,1,0,127
:real(4,0,S,T,1,1,0,0,1,0,0,real(3,2,S,T,20,9,0,0
:X->S
:Y->T
:X+8(K=3)-8(K=2)->X
:Y+8(K=1)-8(K=4)->Y
:End
:real(0,1,0,1

Code breakdown:

:prgmTESTMAP

This program simply copies tilemap data (in hex encoded ASCII) to Str9 for use with tilemap functions. You can load map data into a TIOS string any way you wish

:real(0,1,1

This line sets the calculator to 160 mode, which is required for drawing routines

:"TESTTILE
:real(5,0,0

These lines load a tilepic appvar named “TESTTILE” into temp RAM slot 0

:32->X
:16->Y
:X->S
:Y->T

These lines set the X/Y/TEMPX/TEMPY coordinates for the sprite

:real(3,0,0,0,20,9,0,0,19,14,1
:real(3,0,0,0,20,9,0,0,19,14,0

These lines first draw a fullscreen tilemap stored in Str9 to GRAM. The first line updates the LCD (swaps buffers) and the second line redraws the same map (without updating the LCD) so that both sides of GRAM are the same. Note that this line expects your tilemap to have a width of 20(tiles).

:0->K
:Repeat K=15

K is used to hold the current keypress and we loop until ‘Clear’ is pressed (Clear keycode=15)

:real(2,0,0)->K

This line calls the getkey function and stores the result in TIOS variable ‘K’

:real(4,0,X,Y,1,1,0,0,248,1,0,127

This line calls the drawsprite function. It draws an 8x8 (width=1, height=1) sprite with a pic index of 127 and transparent colour index of 248 at position X,Y. This also updates the LCD

:real(4,0,S,T,1,1,0,0,1,0,0,real(3,2,S,T,20,9,0,0

This line also calls the drawsprite function. However this time it draws an 8x8 sprite with a pic index that is returned from the inline use of the ‘gettile’ function (the real(3,2,S,T,20,9,0,0 portion). Since we are moving the sprite in 8 pixel increments we only need to get the 1 tile underneath the sprite to erase it (since the sprite is aligned to the map). The transparent index for this sprite is 1 since the tileset doesn’t use this colour in any of its data (so there is no risk of accidental transparency). The LCD is not updated this time as well are restoring this frame in GRAM to its original state so that it is ready to be drawn on in the next loop iteration.

:X->S
:Y->T

These lines copy the current sprite X/Y coordinates the TEMPX/TEMPY variables

:X+8(K=3)-8(K=2)->X
:Y+8(K=1)-8(K=4)->Y

These lines are used for key movement. Note that we move in multiples of 8 pixels.

:End

Here we end the loop

:real(0,1,0,1

Before exiting the program we MUST turn off 160 mode and restore the LCD to what the TIOS expects. This will also redraw the status bar at the top of the screen.