                                                         JLib
   
                                             Function Library

                               Copyright 1995,1996 Jonathan Paul Griffiths.
                               All Rights Reserved.
                               Last Updated: Tuesday 29th October

Contents

Introduction                                            
Legal Information                                       
Installation                                            
Building the Library                                    
JLib Design                                             
Function Categories                                     
Conventions                                            
Screen Functions                                       
Buffer Functions                                       
Sprite Functions                                       
Input Functions                                        
Images                                                 
Miscellaneous Functions                                
Debugging                                              
Utilities                                              
Performance                                            
Information                                            
Contributors                                           
Target Information.                                    
Updates & Contacting Me                                

   Introduction
 
 Welcome to this release of JLib. This software package is
intended for people who want to write graphical applications
that port easily to different operating systems.
 
 I think that one of the best ways to learn programming is
to look at other peoples source code, fiddle with it and try
out new ideas. Hopefully the source code for most functions
provided by JLib is simple enough to adapt for use in your
projects, if it isn't what you are after in its current form.
 
 I would like to take this opportunity to thank everyone who
sent me mail about JLib or programming in general. Your
support is encouraging - keep it coming!
 
 JLib is intended to be useful to C and C++ programmers who
want to write portable graphical programs for multiple
platforms. The types of program that will benefit most by
using JLib are those that update lots of elements on-screen
on a regular basis, need sprites, animation or special
effects like fading and scrolling. This covers many type of
programs such as games, drawing and design programs, demos,
graphical simulations, etc.
 
 JLib is used by compiled it for a particular target which
consists of both a graphics mode and a programming
environment. Your application is linked with the library,
allowing use of the functions provided. To port a JLib based
program to another target, the library is rebuilt and your
application is compiled and re-linked for the new target.
This allows programmers to use their favourite application
development environment without limiting the potential
audience for their work to users of that environment.
 
 This document describes the functions available to programs
that use JLib. The design of the library is discussed and
considerations are raised concerning the development of
portable programs. By the time you have finished reading this
document, you should have a good understanding of what JLib
offers and how to use it in your programs.
 
 There are several forms of this document: ASCII text (in
UNIX style format), WORD document format, and HTML (available
as a separate file from JLib distribution sites). The word
processed documentation is much easier to read, especially
when printed. I recommend that you print all of the available
documentation for further reference through the process of
installing and using JLib.

Legal Information
Disclaimer
 
 The information, source code and opinion presented here is
provided as is, without warranty. I make no claims as to its
suitability for a particular purpose or its accuracy. I have
endeavoured to ensure that it works, and presents no danger
to you or your data. However, you choose to use it at your
own risk. Trademarks, copyrights and everything else of
anyone I mention are all the property of the people who own
them respectively. Once again, in legalese:
 
 I, JONATHAN PAUL GRIFFITHS, DISCLAIM ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL I BE LIABLE
FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
Conditions of Use
 
 Except where otherwise noted, The source code in/with this
library is distributed under the following terms and
conditions:
 
 "You may use this source code in any product, whether it is
given away free, or is sold as a commercial product. You must
however, keep existing notices in the source code of this
product, and retain the name of the author(s) of the original
work intact. You may not sell the source code itself,
although you may charge a fee to cover costs in distributing
it. The copyright of the original author remains with this
work. You are granted permission to use this code only if the
above conditions are met. By using this code you are agreeing
to the above terms and conditions."
 
 If you strip code from the library to distribute
separately, please paste the above into each of the separate
program modules you distribute. Putting a pointer to the
library into the source would also be a good idea.

Installation
Decompress the Archive
 
 JLib normally comes compressed using PKZIP 2.04g compatible
software. The file name of the library archive indicates the
version, i.e. jlib_1-6.zip is JLib version 1.6. Before you
can do anything else, you must decompress the archive to
wherever you would like it on your system.
 
 The library archive has a directory structure in it which
includes the base jlib directory. If you are using PKUNZIP to
decompress the archive you must use the "-d" switch to
recreate the directory structure.
 
1.   Go to the directory you would like JLib installed
     in.
2.   Copy the JLib archive file into that directory.
3.   Decompress the archive using one of the following
commands:
     a)   Users of pkunzip: pkunzip -d jlib_X-X.zip
b)   users of unzip: unzip -L jlib_X-X.zip
     Or the appropriate commands for your archive program.
 
 The archive should expand into a directory structure
containing the JLib source code and documentation files.
 
Choose a Target
 
Choose a target from the following list, and change to the
directory listed next to that target.

Compiler           Mode                Directory
djgpp              320x200x256         jlib\source\target
                                       \djv2_13h\
djgpp              640x480x256         jlib\source\target
                                       \djgrx2\
djgpp              800x600x256         jlib\source\target
                                       \djgrx2\
gcc/linux          320x200x256         jlib/source/target
                                       /svgalib/
gcc/linux          640x480x256         jlib/source/target
                                       /svgalib/
gcc/linux          800x600x256         jlib/source/target
                                       /svgalib/
Watcom             320x200x256         jlib/source/target
                                       /watcom13/
Watcom             640x480x256         jlib/source/target
                                       /wat_vesa/
Watcom             800x600x256         jlib/source/target
                                       /wat_vesa/
Ansi, w/X11        320x200x256         jlib/source/target
                                       /x/
Ansi, w/X11        640x480x256         jlib/source/target
                                       /x/
Ansi, w/X11        800x600x256         jlib/source/target
                                       /x/
Ansi Testing       Testing Only        jlib/source/target
library build                          /generic/

1.   There are two header files and a makefile in each
     directory, named jconfig.h, jtarget.h and makefile. Copy
     these to the jlib\source directory.
2.   Change to the jlib\source directory.

Configuration
 
 You may now edit the file jconfig.h to configure the target
if you wish. The following configuration options are
available:
 
1.   If there are multiple modes that the target may be
     built for, then you may select a mode from the list at
     the top of the header file. Ensure that only the mode you
     want is uncommented.
2.   You may comment out  the line reading "#define
JDEBUG" if you wish the library to be built with out
debugging code enabled. This is not recommended until you
begin releasing your aplications.
3.   You may add the line #define JLIB_PRODUCTION to
remove internal library consistency checks. You should
not define JDEBUG if you define this.
4.   You may add the line #define JLIB_PARANOID to make
library internal consistency checks extremely thorough.
This is only useful if JDEBUG is also defined.
5.   You may add the line "#define JLIB_SAFE_SWAP 1" if
you would like integer variable swapping to use a
temporary variable rather than an exclusive-or trick.
6.   You may add the line "#define DEBUG_JLB 1" to have
the JLib image code output debug information if you are
having problems with loading .jlb files.
 
 When you have made your changes, copy the three header
files in the jlib/source directory (jlib.h, jconfig.h, and
jtarget.h) to the standard include directory of your
compiler, so that they may be included in the compilation.
This step may require privileged access on UNIX systems.
(Hint: this directory is <path>\gcc\include for djgpp,
<path>\Watcom\h for Watcom, and usually /usr/include for UNIX
systems).
 
Configure Make Options
 
 You may edit the following components of the file makefile
to change the way the library is built by your compiler:
 
1.   You may change any command line options to the
     compiler by changing the CFLAGS= definition. You may wish
     to put parameters for symbolic debugging code generation
     or code optimisation. Be sure you know what you are doing
     if you choose to perform this customisation.
2.   You should change the LIBDIR definition to point to
     the library file directory used by your compiler. (Hint:
     this is <path>\gcc\lib for djgpp, <path>\Watcom\lib386
     for Watcom, and usually /usr/lib for UNIX systems).
3.   Note that GNU Make can be picky about the placement
     of tabsin makefiles. Be sure that you use an editor that
     does not strip tab characters from text files.

Building the Library
Make the Library
 
1.   Perform any commands to set up your compilation
     environment as you normally would before compiling
     programs.
2.   Ensure that any supplementary libraries that JLib
     uses for your target are set up and configured before you
     attempt to build the library. An example of a
     supplementary library is svgalib for Linux or libgrx for
     some djgpp targets. Read the targets section at the end
     of this document to see if the target you have chosen
     requires any supplementary libraries to be set up.
3.   Run your make program from the jlib\source
     directory. (Hint: Type make for djgpp or UNIX, and wmake
     for Watcom). The library, demonstration programs and
     utilities should compile.
4.   You should probably go and have a cup of tea while
     the library builds, as it can take a while to compile.
     Once the build has finished, you can try the
     demonstration programs (in the sub directories under
     jlib\demo) to see if the target is working.
5.   You can rebuild the library at any time. To rebuild
     just the demos or utilities under djgpp or UNIX, you can
     use the make targets demos or utes. The default target,
     running make with no arguments, builds the library, demos
     and utilities.
 
Clean Up Object Files
 
1.   You may run make with the target clean to remove the
     object files that make up the library, and target
     realclean to remove the demonstration programs and
     utilities.
2.   for UNIX or djgpp users: make clean or make
     realclean
3.   for Watcom users: wmake clean or wmake realclean
4.   Depending on your target and any customisations you
     have made, there may be other ancillary unexpected files
     that were created during the build and not deleted. You
     may delete these if you wish (provided you know what you
     are doing).
 
Now You Can Compile Your Own JLib Programs
 
 Assuming all went well, you are now ready to compile your
own JLib programs. To do this you only need to remember to
#include <jlib.h> in your source and link with the library
and any supplementary libraries when compiling. The CFLAGS=
line of the makefile you used to build the library will have
the correct parameters to pass to your compiler to build JLib
programs, and so it may be used as a guide.

JLib Design
 
 The fundamental concept behind JLib is to remove as many of
the details of graphical interfaces as possible from the
programmer. By abstracting away from hardware considerations,
programs are made simpler to write, understand, and debug.
JLib hides the details of graphical operations from the
programmer. Whether a JLib program is running in a full
screen or in a desktop window, the program always treats user
input and graphical output in the same way.
 
 Some basic concepts about how JLib is designed are helpful
to determine whether you will find it useful. Here, then are
the hard and fast rules behind the behaviour of JLib based
programs:
     256 or less colours.
     One fixed-size(at compile time) output screen to
      draw to.
     Currently, common resolutions of 320x200, 648x480, &
      800x600.
 
 Things JLib Programs can't Do:
     Change to other graphics mode during runtime.
     Perform direct to screen drawing of primitives.
     Take advantage of particular O/S features or API's.
 
 You can do these three things from JLib programs, but you
will have to write the code for it yourself for each target
you hope to port to.
 
Commonly Used Terms
 
Target
 
 A combination of a programming environment and graphics
mode form a JLib target. An example is the MS-DOS based djgpp
compiler package (programming environment), and the mode 13h
(320x200, 256 colour) graphics mode. Targets are identified
by #defines in a library configuration header file. To
compile the library for a particular target, the correct
target header file is installed, then the library is
recompiled. Programs subsequently linked with the library
will use the given graphics mode.
 
Buffer
 
 A buffer is like a drawing pad for JLib programs. Buffers
can be different sizes, and there are many graphics
primitives that can be used to draw onto them. Part or all of
a buffer can be shown on the screen as desired. Anything that
you want to draw on the screen in your program must first be
drawn to a buffer, and then copied to the screen. Often, a
buffer is exactly the same size as the output screen, and is
treated like the screen. When the buffer changes in any way,
the screen is updated to reflect the buffer.
 
Sprite
 
 A sprite is an image or picture that does not overwrite the
area of the screen that it appears on. Sprites are used to
draw cursors, icons and animated images that can move over a
backgrounds as though they are floating in front it.
 
Blitting
 
 Blitting is the process of copying graphics information
from one area to another. Blitting to the screen refers to
copying a buffers contents onto the screen. Blits always use
rectangular areas.


Function Categories
 
 Functions in the library are split into several logical
groupings. Every function within each group is explained in
detail later in this document. The following is an overview
of the function groups:
 
screen functions
 
 Screen function names are preceded by screen_. They operate
on the screen of the target to allow palette functions like
setting a palette and fading in and out. They also include
blitting functions which allow all or parts of buffers to be
copied on to the screen. This group also includes mode
setting functions to enter and leave a graphical state, and
functions to clear the screen or fill it with a colour.
 
palette functions
 
 These functions are palette operations that are not
immediately visible on screen, such as re-mapping image
palettes, loading palettes and creating new palettes.
Functions of this type are preceded by pal_.
 
buffer functions
 
 Buffer function names are preceded by buff_. This group
consists of all the operations that can be performed on
buffers, such as blitting functions that copy graphical data
from one buffer to another, as well as graphics primitives
that allow for drawing shapes and pictures into buffers.
 
sprite functions
 
 All sprite functions are prefixed by sprite_. This category
includes functions for describing, moving and manipulating
sprites and sprite images, as well as loading sprites from
files for use in your programs.
 
input functions
 
 Input function provide a portable way for your application
to respond to a users actions. Available are functions for
reading the mouse, prefixed by mouse_, the keyboard, kb_, and
joysticks, joystick_.
 
image functions
 
 Image functions, prefixed by image_, deal with loading and
saving images to and from files. An image is essentially a
buffer containing a picture which has its own palette.
 
miscellaneous functions
 
 Anything not covered by the above categories belongs to
this category, including error handling and version
information.

Conventions
 
 The following conventions are common throughout all of the
functions in JLib:
    All co-ordinates are relative to the upper left
    corner of a sprite, screen or buffer. Position 0,0 is
    always the top left corner.
    Negative co-ordinates may be used to specify
    positions beyond the top and left hand side of a screen
    or buffer.
     All functions with names ending in NC (No Checking)
    do not perform tests for invalid co-ordinates or other
    parameters, and do not perform clipping on graphics
    operations. Often these functions make assumptions about
    the input format of parameters that are not documented.
    These functions are slightly faster than their clipping
    counterparts, but are considerably more risky if passed
    the wrong information. In most cases a crash will result
    from incorrect usage of these functions. I recommend that
    you use checking functions during program development and
    change to non-checking functions later if efficiency
    becomes an issue. This documentation lists both routines
    but the function description applies only to the checking
    version unless otherwise stated.
     The following basic types are #defined for use by
    JLib programs:
    BYTE 8 bit signed number
    UBYTE 8 bit unsigned number
    SHORT 16 bit signed number
    USHORT 16 bit unsigned number
    LONG 32 bit signed number
    ULONG 32 bit unsigned number
     A point on the screen is referenced by its co-
    ordinates. These are given as an X and Y co-ordinate
    pair. The X co-ordinate is how far across the screen a
    point is, while the Y co-ordinate is how far down the
    screen a point is. Co-ordinates begin at (0,0) which
    corresponds to the upper left corner of the screen, and
    increase downwards (Y) and to the right (X).
     The only header file your programs should include to
    use JLib is <jlib.h>. It includes any other header files
    you will need for graphics work. Of course, you may need
    standard other include files for your program- do not
    rely on JLib including particular system header files for
    you.
     This documentation forms a type of contract about
    the behaviour of JLib routines. As the library is under
    constant development, it might fail to live up to parts
    of this contract for some or all targets in particular
    areas. I will endeavour to document any failings or
    likely failings, non-implemented or planned features, or
    bugs from version to version. My aim is that you will
    eventually rely on this document to definitively tell you
    how JLib behaves in a given circumstance.
     All functions that clip do so in respect to the
    destination sprite, buffer, image or screen they are
    operating on.
    Passing invalid data to a function will usually
    cause the library to exit with an error message. See the
    discussion on library building options for details on how
    to change this default behaviour.
     Any malloc() failures in library code currently
    cause execution to stop. This behaviour may be able to be
    changed at compilation time in a future version of JLib.

Screen Functions
Overview
 
 These functions are designed to give you control over the
appearance of the screen during your programs execution. You
use mode setting functions to initialise the display before
your program runs, and to restore it to its former state when
the program ends. While your program runs you can change the
palette (colour set) of the screen or blit (copy) buffers on
to the screen. A screen may actually be a window or a part of
a larger display area on some targets, but your code and the
library will still behave in the same way as it would if the
whole screen were being used by your program. There is no
need to learn complex window manipulation API's for each
target.
 
 Buffers can be blitted to any screen co-ordinates. Negative
co-ordinates or co-ordinates larger than the current screen
dimensions may mean that part or all of the buffer is
clipped(not shown).
 
Screen Initialisation
void screen_set_app_title(char *title);
 
 This function allows you to control the appearance of your
application when running in windowing environments, and
during abnormal program termination. If you assign a title
using this function before calling screen_set_video_mode(),
the screen will have the given text as a title, if the target
supports this behaviour. Upon abnormal exit, if a title has
been set for the application, it will be printed along with
an error message, hiding JLib's presence from the end user.
If this function is not used, all progarms will have the
default title "JLib Application".
 
These functions set and restore the graphics mode for your
program as it runs. You must call void
screen_set_video_mode(void);
void screen_restore_video_mode(void);
 
 These functions set and restore the graphics mode for your
program as it runs. You must call screen_set_video_mode()
once in your program before you attempt any graphical
operations. This routine will perform the initialisation and
set up activities particular to your target, such as opening
an output window or changing the graphics resolution. You
must always call screen_restore_video_mode() before your
program ends to restore the graphical state of the host
system. Failing to call either of these functions before and
then after performing graphics operations could cause fatal
crashes on some operating systems. The exact behaviour of
programs in this situation is undefined.
 
 Once the video mode is set, you may output to the screen.
The characteristics of the mode JLib was built for are
available to your program as a number of constants.
 
Constant                     Meaning
SCREEN_WIDTH                 Width of the graphics screen
                             in pixels
SCREEN_HEIGHT                Height of the graphics
                             screen in pixels
SCREEN_MAX_X                 Maximum X co-ordinate on the
                             screen
SCREEN_MAX_Y                 Maximum Y co-ordinate on the
                             screen
SCREEN_NUM_COLORS            Number of colours on the
                             screen
SCREEN_NUM_PAGES             The number of screen display
                             pages
 
 You should use these constants in your program rather than
explicit values, as they improve the portability and
readability of your programs.
 
Screen Paging
void screen_set_page(int page);
int screen_get_page(void);
void screen_show_page(int page);
 
 A screen may be thought of as a page to which your programs
output graphical data. On some target systems, a screens
characteristics are such that there are in fact more than one
available screen page to draw on. Typically only one page can
be seen at a time, although any page may be drawn to. By
directing output to a page that is not visible, and then
making it the visible page, graphics output can be made to
look smoother because you do not see the screen layout being
drawn. If the target your program is using supports multiple
pages then the constant SCREEN_NUM_PAGES will be defined to
have a value other than 1.
 
 Each of the JLib screen functions draws to a current page
which the library keeps track of internally. In the case of
targets that don't support paging, this current page is
always the visible screen. The programmer can set the current
output page by calling screen_set_page() with the appropriate
page number. All screen output will then draw to that page.
The number of the current output page can be found by calling
screen_get_page(). By default, page 1 is displayed after a
mode setting function. The function screen_show_page() will
change the visible page to another page. Changing the
displayed page does not affect the current output page (where
screen functions will draw to).
 
 Calling a page setting function with a page number of less
than 1 or greater than SCREEN_NUM_PAGES is a fatal error.
There is currently no function to get the current display
page.
 
Developers Note: No targets utilising pages have yet been
implemented. I plan to write some fake paging code so that
all targets will be able to be treated as though they have
several (probably two minimum) pages.
 
Screen Manipulation
void screen_clear(void);
void screen_fill(UBYTE colour);
void screen_wait_vsync(void);
 
 These functions are designed for elementary manipulation of
the screen. The function screen_clear() will fill the entire
screen with the colour of the background, clearing any
previously drawn graphics from it. This function is always
called automatically by a screen_set_video_mode() call.
 
 The function screen_fill() fills the entire screen with the
given colour, erasing all previously drawn graphics. This
function will not change the border colour of the screen (On
targets where this is applicable). See Screen Functions:
Palette for more information on how colours are used in JLib.
 
 The function screen_wait_vsync() is designed to allow
screens to be updated while the screen redrawing beam or
raster is off screen or in the retrace period. Updates made
during this time are generally smoother because the raster
does not pass the drawing output process resulting in a
momentarily sheared image. This function is implemented as an
empty routine on some targets where retrace checking is not
possible. To use the function, place a call to it before any
screen blitting function. The function will wait until the
retrace period before returning. This wait can slow graphics
operations down, and is more noticeable on slower graphics
cards.
 
Palette Overview
 
 A palette in JLib is an array of colours specified by 8 bit
RGB (red, green and blue component) values. Each colours red,
green, and blue component is given in order before the next,
giving a palette array of UBYTES. Each palette entry is
referred to by its index into the palette. Thus, colour
number zero is defined by the first three bytes of a palette.
The RGB values of a colour in a palette may be changed to
provide effects like fading, glowing or cycling as in fire or
plasma effects.
 
 Depending on the target, your program has SCREEN_NUM_COLORS
colours available for use, numbered from 0 to
(SCREEN_NUM_COLORS-1). For all modes and targets, colour 0
corresponds to the background and border colour of the
screen. In many cases this colour will be black (RBG 0:0:0),
although it may be changed any colour. Colours 15 and 255 (In
256 colour modes) are used for the mouse cursor by default,
so changing these colour entries will change the colour of
the mouse pointer if one is visible. This behaviour came
about through a feature in MS-DOS that I am not capable of
changing yet, so it is an impromptu standard that looks
likely to stay.
 
 JLib screen palette functions are output oriented in that
they do not change any parameters passed to them. Setting or
fading a palette corresponds to changing the screen palette,
and does not change the colour specifications held in the
passed palette array. Changes that you make to a palette
array are reflected on the screen only if the array is passed
to a palette function that sets the palette. Changing a
colour using one of the palette functions affects the screen
immediately, you do not have to redraw the screen to see the
effect.
 
Developers Note: More palette functions are planned, in
particular: palette conversion functions such as colour
reduction,  increase contrast, invert, pseudo colour etc.
 
Screen Palette Functions
void screen_put_pal(UBYTE col,UBYTE red,UBYTE green,UBYTE blue);
void screen_block_set_pal(UBYTE *pal);
void screen_blank_pal(void);
void screen_fade_in_pal(UBYTE *pal,unsigned int delay);
void screen_fade_to_pal(UBYTE *pal1, UBYTE *pal2,unsigned int delay);
void screen_fade_out_pal(UBYTE *pal,unsigned int delay);
 
 The function screen_put_pal() takes a colour number and an
RGB specification and sets the colour of that index to that
specification. screen_block_set_pal() takes a whole palette
array as an argument and sets all SCREEN_NUM_COLORS colours
at once. This is usually significantly faster than
individually changing each palette entry using
screen_put_pal(). You must pass this routine an array which
is big enough to hold SCREEN_NUM_COLORS indexes. You can't
set only half of the palette by passing a shorter array
(trying this will probably result in a memory protection or
corruption error).
 
 The function screen_blank_pal() sets the whole palette to
black. This can be useful when building up a complex screen
image which can then be faded in smoothly. The functions
screen_fade_in_pal() and screen_fade_out_pal() are provided
to allow smooth fading of palettes to and from black. To fade
from one palette to another you can use the function
screen_fade_to_pal().
 
 The delay parameter is the amount of time the fade should
take, expressed as a number of UCLOCK_TICKS_PER_SECOND (see
uclock_init() for details of this value). As an example, if
your fade was meant to take 6 seconds to complete, you would
use the value (UCLOCK_TICKS_PER_SECOND*6). Similarly, a value
of (UCLOCK_TICKS_PER_SECOND/2) would represent half a second.
 
 
Non-Screen Palette Functions
 
 Other palette functions are available to JLib programs that
do not affect the screen output directly. These functions are
prefixed by pal_, and generally involve manipulating palettes
without producing any visible change on screen. This is
useful for loading, converting between palettes, collapsing
palettes and similar functions.
 
UBYTE *pal_init(void);
 
 This function creates space for a new palette and returns a
pointer to it. The space is not initialised.
 
UBYTE *pal_load(char *fname);
UBYTE *pal_load_fp(FILE *fp);
 
 To load a palette from a file you can use the function
pal_load() which returns a palette read from the file fname,
or NULL if an error occurred while reading in the palette
file. You can load a palette from a file which is already
open with the function pal_load_fp(). If you use this
function you will have to close the file containing the
palette yourself, and the file pointer must be positioned at
the correct place to begin reading the palette from. Palette
files are simple dumps of palette arrays with no header
information in the file. Both of these functions allocate the
memory for the palette they return.
 
UBYTE *pal_get_default(void);
 
 This function allocates memory for and returns a pointer to
a palette initialised with default values. The palette
returned is the same across all target platforms. The default
palette is not set by default upon screen initialisation, so
if you are not using a custom palette your application should
set the default palette to enable different colours to be
seen.
 
UBYTE *pal_copy(UBYTE *pal1, UBYTE *pal2);
 
 This function copies pal2 to pal1. It does not allocate any
memory for pal1, so pal1 should be initialised or created
before a copy is attempted.
 
void pal_to_grey(UBYTE *pal);
void pal_to_red(UBYTE *pal);
void pal_to_green(UBYTE *pal);
void pal_to_blue(UBYTE *pal);
 
 These functions take the palette pal and return it with
each RGB colour converted to a grey, red, green, or blue
scale representation of the colour.
 
UBYTE pal_closest_color_rgb(UBYTE *pal,UBYTE r,UBYTE g,UBYTE b);
 
 This function returns the colour index in pal that most
closely represents the RGB specification given by r, g and b.
This function will not return 0 unless pal is NULL, as
mapping a colour to colour zero could later cause the colour
to be shown as transparent, rather than a solid colour.
 
UBYTE *pal_create_remap_index(UBYTE *pal1,UBYTE *pal2);
 
Undocumented.
 
 
Screen Blitting
void screen_blit_buff_to(int x,int y,buffer_rec *buff,int
                            sx1,int sy1,int sx2,int sy2);
void screen_blit_buff_toNC(int x,int y,buffer_rec *buff,int
                            sx1,int sy1,int sx2,int sy2);
void screen_blit_fs_buffer(buffer_rec *sbuff);
 
 Screen blitting functions are the primary way to get
graphics onto the screen using JLib, so you should get to
know them well. The basic idea is that these functions copy
rectangular areas from buffers on to the screen. Anything
that you would like to be seen on the screen should be first
drawn to a buffer and then blitted to the screen.
 
 The function screen_blit_buff_to() and its non-checking
counterpart are designed for blitting buffers that are not
the same size as the screen. Buffers of this nature are often
used for windowing, scrolling, or when a screen is made up of
several parts that are updated at different times. The
functions take the screen x and y co-ordinates to place the
top left hand corner of the source buffer at, a pointer to
the buffer in question, and co-ordinates describing the part
of the source buffer that is to be copied. These source co-
ordinates are the top left hand and bottom right hand corners
of the source rectangle to be copied.
 
 If the co-ordinates given fall outside of the range of the
screen or buffer dimensions then clipping will occur
(provided the NC function is not used). If this happens, only
the part of the source buffer (if any) that falls on the
screen will be blitted across.
 
 If you are working with a buffer that is the same size as
the screen, then you can gain a faster blit by using the
function screen_blit_fs_buffer(). Depending on the target,
this call will usually result in the fastest possible copying
to the screen due to specific optimisations and assumptions
about the size of the buffer. This function copies the buffer
to screen position 0,0. Screen sized buffers can be treated
just like a screen in your application, and blitted to the
output screen as updates occur.
 
 It is important to remember that copying a buffer to a
screen will probably be the slowest part of your program, due
to the big difference in speed between system memory and
video memory, coupled with bus bottlenecks. See the section
Performance: Increasing Speed for more information on
minimising the amount of blitting your program does.
Buffer Functions
Overview
 
 Buffers are user created portions of system memory set
aside to act as screens. They can be almost any width or
height, limited only by available system memory. All graphics
primitives are drawn to buffers before being copied to the
screen.
 
 Due to the peculiarities of some of the targets JLib is
intended to work with, there is a rule that the width of any
buffer that will be drawn to the screen must be a multiple of
four. A width for these buffers that is a multiple of eight
is more desirable, and this may become a hard rule depending
on some planned targets.
 
 Buffer memory is organised as a contiguous block of width x
height UBYTES. Buffer information is kept in a buffer_rec
structure. Pointers to structures of this type are used to
pass buffers around the various library functions. Macros are
provided for accessing information about a particular buffer:
 
Macro                        Information
B_X_SIZE(buff_ptr)           X size of buffer in pixels
B_Y_SIZE(buff_ptr)           Y size of buffer in pixels
B_MAX_X(buff_ptr)            Maximum X co-ordinate in the buffer
B_MAX_Y(buff_ptr)            Maximum Y co-ordinate in the buffer
B_SIZE(buff_ptr)             UBYTES of memory used by buffer data
B_BUFF_PTR(buff_ptr)         A pointer to the buffer memory
B_OFFSET(buff_ptr,y)         A pointer to the buffer memory at line y
 
buffer_rec *buff_init(int width,int height);
buffer_rec *buff_free(buffer_rec *buff);
 
 Buffers are created using the buff_init() function. This
function allocates the memory needed to hold a buffer of the
given width and height and returns a pointer to the structure
suitable for the library graphics primitives. Once a buffer
is no longer needed, it can be disposed of by calling
buff_free(). This function returns a NULL pointer so that any
future accesses of the handle are sure to be detected as
invalid by the library.
 
Buffer Blitting
void buff_blit_buff_to(buffer_rec *dest,int dx,int
dy,buffer_rec*src, int sx1,int sy1,int sx2,int sy2);
void buff_blit_buff_toNC(buffer_rec*dest,int dx,int
dy,buffer_rec*src,int sx1,int sy1,int sx2,int sy2);
 
 This function takes the rectangle outlined by the source
buffer co-ordinates and copies it to position dx, dy in the
destination buffer performing clipping as needed. Buffer
blitting operations are usually orders of magnitude faster
than video blitting operations, so liberal use should not
adversely affect performance.
 
void buff_stencil_buff_to(buffer_rec *dst,int x,int
y,buffer_rec*src, int sx1,int sy1,int sx2,int sy2);
void buff_stencil_buff_toNC(buffer_rec*dst,int x,int
y,buffer_rec*src,int sx1,int sy1,int sx2,int sy2);
 
 This function is just like a buffer to buffer blit except
that any parts of the source buffer that are set to colour 0
(background) are treated as though they are transparent, i.e.
they do not overwrite the destination buffer.
 
Buffer Primitives
void buff_clear(buffer_rec *buff);
void buff_fill(buffer_rec *buff,UBYTE colour);
 
 These two functions both fill the buffer passed to them
with a colour. Buff fill takes a colour parameter to indicate
what colour to fill the buffer with, while buff clear fills
the buffer with the background colour, colour 0. Note that
these functions do not respect any drawn boundaries when
filling. They overwrite the entire contents of the buffer
passed to them.
 
Developers Note: A buff_flood_fill() routine and variants are
planned.
 
 
void buff_draw_point(buffer_rec *buff,int x,int y,UBYTE c);
void buff_draw_pointNC(buffer_rec *buff,int x,int y,UBYTE c);
 
 The function buff_draw_point() plots a coloured pixel at
the location x, y in the given buffer. Note that visible
point co-ordinates are in the range (0-B_MAX_X(buff)),(0-
B_MAX_Y(buff)). Points outside of these ranges will not be
displayed. Any data at the given co-ordinates will be
overwritten.
 
UBYTE buff_get_point(buffer_rec *buff,int x,int y);
UBYTE buff_get_pointNC(buffer_rec *buff,int x,int y);
 
 This function returns the colour of the pixel at co-
ordinates x, y in the buffer passed as a parameter. If the co-
ordinates given do not fall inside the buffer then a value of
0 is always returned.
 
void buff_draw_box(buffer_rec *buff,int x1,int y1,int x2,int y2,UBYTE c);
void buff_draw_boxNC(buffer_rec *buff,int x1,int y1,int x2,int y2,UBYTE c);
 
 This function draws a box outline in the given colour,
described by the top left and bottom right co-ordinates
passed. If any co-ordinates fall outside of the buffer the
box outline will be clipped to the buffer.
 
void buff_draw_rect(buffer_rec *buff,int x1,int y1,int x2,int y2,UBYTE c);
void buff_draw_rectNC(buffer_rec *buff,int x1,int y1,int x2,int y2,UBYTE c);
 
 This function takes the same parameters as buff_draw_box()
but draws a filled rectangle of the given colour rather than
an outline.
 
void buff_draw_char(buffer_rec *buff,UBYTE letter,int x,int y,UBYTE c);
void buff_draw_charNC(buffer_rec *buff,UBYTE letter,int x,int y,UBYTE c);
 
 This function draws an alphanumeric character at position
x, y in colour c. The letter will be clipped if part or all
of it falls outside of the buffer passed. Several macros have
been defined to get information about a character to be
drawn.
 
Macro                        Meaning
CHAR_WIDTH(ch)               Width of a character in pixels.
CHAR_HEIGHT(ch)              Height of a character in pixels.
HAS_FONT(ch)                 Is ch a printable character?
 
 The size of letters changes according to the size of the
screen. The characters used are designed to fit 80x25 onto
the screen. This function is mainly intended for debugging
and utility style code. Only one font is available and the
characters can not be scaled. To get more font-like
functionality, use the JLib Font extension package, available
from JLib distribution sites.
 
void buff_draw_string(buffer_rec *buff,char *string,int x,int y,UBYTE c);
void buff_draw_stringNC(buffer_rec *buff,char *string,int x,int y,UBYTE c);
 
 This function takes a text string and outputs it to the
buffer using the buff_draw_char() function. Any non printing
characters are ignored, and new line characters "\n" cause
the string to move to the next 'line' which is taken to be
CHAR_HEIGHT('A') pixels below the current Y co-ordinate. See
the notes for character drawing functions concerning intended
use.
 
void buff_draw_line(buffer_rec *buff,int x,int y,int x2,int y2,UBYTE c);
void buff_draw_lineNC(buffer_rec *buff,int x,int y,int x2,int y2,UBYTE c);
 
 This function draws a line from the point x, y to point x2,
y2 in the given colour. The line will be clipped if any part
of it lies outside the destination buffer. Drawn lines are
not anti-aliased but are consistent approximations (i.e. the
same two points always give the same line).
 
void buff_draw_h_line(buffer_rec *buff,int x1,int y1,int x2,UBYTE c);
void buff_draw_h_lineNC(buffer_rec *buff,int x1,int y1,int x2,UBYTE c);
 
 This function is an optimised line drawing routine for
horizontal lines. It takes the start and end x co-ordinates
of the line, and the y co-ordinate (which is the same at both
ends).
 
void buff_draw_v_line(buffer_rec *buff,int x1,int y1,int y2,UBYTE c);
void buff_draw_v_lineNC(buffer_rec *buff,int x1,int y1,int y2,UBYTE c);
 
 This function is an optimised line drawing routine for
vertical lines. It takes the start and end y co-ordinates of
the line, and the x co-ordinate (which is the same at both
ends).
 
void buff_draw_ellipse(buffer_rec *buff,int x,int y,int a,int b,UBYTE c);
void buff_draw_ellipseNC(buffer_rec *buff,int x,int y,int a,int b,UBYTE c);
 
 This function draws a hollow ellipse centred around the
point x, y, with a vertical diameter of a, and a horizontal
diameter of b.
 
void buff_filled_ellipse(buffer_rec *buff,int x,int y,int a,int b,UBYTE c);
void buff_filled_ellipseNC(buffer_rec *buff,int x,int y,int a,int b,UBYTE c);
 
 This function is exactly the same as buff_draw_ellipse()
except that a solid ellipse is drawn instead of a hollow
outline.
 
void buff_draw_circle(buffer_rec *buff,int x,int y,int d,UBYTE c);
void buff_draw_circleNC(buffer_rec *buff,int x,int y,int d,UBYTE c);
 
 This function draws a hollow circle centred around the
point x, y, with a diameter of d pixels.
 
void buff_filled_circle(buffer_rec *buff,int x,int y,int d,UBYTE c);
void buff_filled_circleNC(buffer_rec *buff,int x,int y,int d,UBYTE c);
 
 This function draws a filled circle centred around the
point x, y, with a diameter of d pixels.
 
void buff_draw_triangle(buffer_rec *buff,int x1,int y1,int
                        x2,int y2,int x3,int y3,UBYTE c);
void buff_draw_triangleNC(buffer_rec *buff,int x1,int y1,int
                        x2,int y2,int x3,int y3,UBYTE c);
 
 This function draws a hollow triangle from the three points
given.
 
void buff_filled_triangle(buffer_rec *buff,int x1,int y1,int
                        x2,int y2, int x3,int y3,UBYTE c);
void buff_filled_triangleNC(buffer_rec *buff,int x1,int y1,int
                        x2,int y2, int x3,int y3,UBYTE c);
 
 This function draws a filled triangle from the three points
given.
 
void buff_convex_poly(buffer_rec *buff,int n,int *x,int *y,UBYTE c);
void buff_convex_polyNC(buffer_rec *buff,int n,int *x,int *y,UBYTE c);
 
 This function draws a filled convex polygon of n vertices
which are listed in the given arrays of x and y co-ordinates.
Attempting to draw a concave polygon with this function will
have unpredictable results (which may include crashing your
machine).
 
Developers Note: A buff_concave_poly function is planned.
 
void buff_hollow_poly(buffer_rec *buff,int n,int *x,int *y,UBYTE c);
void buff_hollow_polyNC(buffer_rec *buff,int n,int *x,int *y,UBYTE c);
 
 This function draws the outline of a concave or convex
polygon of n vertices which are listed in the given arrays of
x and y co-ordinates.
 
void buff_scale_full_buff_to(buffer_rec *dest,int x1,int y1,int x2,
                             int y2,buffer_rec *src);
void buff_scale_full_buff_toNC(buffer_rec *dest,int x1,int y1, int x2,
                             int y2,buffer_rec *src);
 
 This function takes the buffer src and draws it into the
rectangle (x1,y1),(x2,y2) in dest. The source buffer will be
scaled larger or smaller to fit into the destination
rectangle.
 
void buff_scale_buff_to(buffer_rec*d,int d1,int d2,int d3,int
                        d4,buffer_rec*s,int x1,int y1,int x2,int y2);
void buff_scale_buff_toNC(buffer_rec *d,int d1,int d2,int d3,int
                        d4,buffer_rec*s,int x1,int y1,int x2,int y2);
 
 This function takes the rectangle (x1,y1),(x2,y2) fomr the
source buffer s and draws it into the rectangle
(d1,d2),(d3,d4) in the destination buffer. The source
rectangle will be scaled to fit into the destination rectangle.

Sprite Functions
Overview
 
 Sprites are like little pictures with transparent
backgrounds. When you draw them only the 'solid' part of them
is seen. They are used for things like enemies and bullets in
games, because they move over a background without
overwriting it. The JLib library provides routines to load
and display sprites, as well as animate and move them
automatically.
 
 Utilities are provided in the jlib/utes directory that
enable you to cut sprites from PCX files and edit the sprite
files created. This means that you can design your sprites
with any drawing tool, convert the output to a PCX file, and
then cut the sprites out for use in your game/demo/whatever.
 
 Sprites are positioned in co-ordinates that start from 0,0
in the upper left corner of a buffer. As sprites move into
negative co-ordinates or off the sides of buffers, they are
clipped, so they appear to slide smoothly out of the buffer.
The number of sprites you can have in a JLib program is
limited only by your machines memory.
 
 Sprites are grouped together into a sprite_system
structure, which holds information which sprites are active,
their position and other information. You can have multiple
sprite systems to differentiate between different uses or
types of sprites. Sprite systems also hold information about
what sprites look like. A frame in JLib is a small picture
that a sprite is associated with. When a sprite is drawn, it
looks like the frame. By changing the frame that a sprite is
associated with, the sprite appears to animate. Frames are
loaded from .spr files into a sprite system. Many sprites can
use the same frames at the same time. Frames can also be
stamped or stencilled onto buffers without being involved
with a sprite. A pointer to a sprite_system structure is
passed to sprite functions to tell JLib which sprites the
function should act on.
 
 Sprites themselves are stored as internal records that hold
information such as an x and y position, movement and
animation details and which frame image a sprite is using. It
is important to separate the sprite, which is the object that
floats around the screen, with its frames, which are images
that the sprite looks like at a given moment. Many sprites
can share the same frame, thus they will look the same, but
will not be the same sprite. You can also just draw sprite
frames into buffers without involving a sprite at all. . Each
sprite in JLib has its own movement and animation
information, which can be updated for you by JLib.
 
 Sprites have priority according to their number. Priority
indicates whether a sprite will be drawn behind or in front
of another sprite when the two sprites overlap. The lower a
sprites number, the lower its priority, i.e. sprite 1 will
always be drawn over sprite 0, and the highest priority
sprite is always the last one in the sprite system.
 
Sprite Initialisation
sprite_system *sprite_init(int max_sprites,int max_frames);
 
 This function creates a new sprite system with enough space
to hold max_sprites sprites and max_frames frame images. The
sprite system is initially empty, so you will need to load in
some sprite frames before you can start to put some sprites
on screen. Once a sprite system has been created, the
following macros are available to get information about it:
 
Macro                        Meaning
SPR_MAX_X                    Biggest possible sprite
                             width.
SPR_MAX_Y                    Biggest possible sprite
                             height.
SPR_MAX_SPRITES(spr_sys)     Max. number of sprites you
                             may use.
SPR_MAX_FRAMES(spr_sys)      Max. number of frames you
                             may use.
SPR_NUM_LOADED(spr_sys)      Number of frames currently
                             loaded.
SPR_NUM_ACTIVE(spr_sys)      Number of sprites turned on.
 
 The following macros are defined to get information about a
particular sprite within a sprite system:
 
Macro                        Meaning
SPR_X_SIZE(spr)              X size of the sprite pointed
                             to by spr
SPR_Y_SIZE(spr)              Y size of the sprite pointed
                             to by spr
SPR_IS_ON(sys,num)           Is sprite num in system sys
                             turned on?
SPR_GET_XPOS(sys,num)        X position of sprite number
                             num
SPR_GET_YPOS(sys,num)        Y position of sprite number
                             num
 
 The biggest sprite frame you can use defaults to 64 by 64
pixels, but you can change this if you want by changing the
SPR_MAX_X and SPR_MAX_Y constants in <JLib.h>. You will need
to rebuild the whole library if you change these numbers,
however.
 
sprite_system *sprite_free(sprite_system *sys);
 
 This function releases the resources used by a sprite
system and returns NULL. Since sprite systems can use large
amounts of memory, it is recommended that you use this
function as soon as your application is finished with a
sprite system.
 
int sprite_load(char *fname,sprite_system *sys);
 
 This function opens the file called fname and loads the
frames it holds into the sprite system sys. This function
returns values as follows:
 
Return code                  Meaning
COULDNT_OPEN                 The file passed could not be
                             opened.
TOO_MANY_IN_FILE             Too many frames in the file.
SUCCESS                      The ffile loaded
                             successfully.
 
 You may call this function repeatedly to load more than one
sprite file into a sprite system, provided that the total
number of frames that are loaded will fit into the space
reserved for frames in the sprite system as specified when
sprite_init() was called.
 
Developers Note: Should you wish to write any sprite file
manipulation code yourself, the format for sprites file is
documented in the file sprite/spriteio.c .
 
 
Sprite Manipulation
void sprite_turn_on(sprite_system *spr_sys,int snum);
void sprite_turn_off(sprite_system *spr_sys,int snum);
void sprite_set_xy(sprite_system *spr_sys,int snum,int newx,int
newy);
void sprite_set_an_frame(sprite_system *spr_sys,int snum,int
frame);
void sprite_set_mode(sprite_system *spr_sys,int snum,int mode);
 
 These are the elementary sprite manipulation functions in
JLib, which allow you to change the position, current frame
and on/off status of a sprite snum. These functions are
designed to be called while the sprite being manipulated is
not currently drawn anywhere or is turned off. If these
functions are called while a sprite is drawn into a buffer,
there will probably be corruption of (at least) the sprites
buffer when the library tries to restore the background
behind the sprite that you are updating (as the sprite will
then be at a different position, or have a different frame).
 
 Turning a sprite off and on restores its mode to
SPR_MODE_WHOLE. These functions do not cause the sprite to be
re drawn automatically. You must redraw the sprites manually
within your program, or if you are using one of the
sprite_update_() functions then this will be done for you the
next time it is called.
Sprite Drawing
 
 The process of showing sprites on screen and having them
move or animate follows a pattern in which order is
important. Starting with a sprite turned on, but not drawn
anywhere, the process is as follows:
 
1.   Save the buffer area that the sprite will overwrite.
2.   Draw the sprite into the buffer.
3.   Show the buffer containing the drawn sprite on
     screen.
4.   Restore the buffer area overwritten by the sprite.
5.   Update the sprite's movement or animation details.
6.   Go back to step 1.
 
 Remember that if you are drawing and restoring individual
sprites yourself in your program, you should save, draw and
restore them in the correct order. The _all_ drawing
functions perform these operations in the correct order,
making them much easier to use.
 
void buff_save_sprite(sprite_system *sys,int num,buffer_rec *buff);
void buff_save_spriteNC(sprite_system *sys,int num,buffer_rec *buff);
void buff_save_all_sprites(sprite_system *sys,buffer_rec *buff);

 These functions save the area in buffer buff that the
sprite num (or all sprites in the case of
buff_save_all_sprites()) will overwrite if drawn to the
buffer. This function should be called after any sprite
movement or animation has taken place but before the
sprite(s) are drawn.
 
void buff_draw_sprite(sprite_system *sys,int num,buffer_rec *buff);
void buff_draw_spriteNC(sprite_system *sys,int num,buffer_rec *buff);
void buff_draw_all_sprites(sprite_system *sys,buffer_rec *buff);
 
 These functions draw the sprite num (or all sprites in the
system sys) to the given buffer. This function should be used
after the sprite(s) are saved and before they are moved or
animated further.
 
void buff_rest_sprite(sprite_system *sys,int num,buffer_rec *buff);
void buff_rest_spriteNC(sprite_system *sys,int num,buffer_rec *buff);
void buff_rest_all_sprites(sprite_system *sys,buffer_rec *buff);
 
 These functions restore the area of buffer buff that the
sprite num (or all sprites in the case of
buff_save_all_sprites() had overwritten when drawn to the
buffer. This function should be called after any sprites have
been drawn and displayed, before any movement or animation
takes place.
 
Sprite Movement Overview
 
 There are two possible modes that a sprite may be in:
SPR_MODE_WHOLE or SPR_MODE_FIXED. All sprites start out in
SPR_MODE_WHOLE. The mode of a sprite affects how it moves and
animates; in whole steps or in fixed point fractional steps.
To understand this we need to look at the concept of time-
slices.
 
 A time-slice is exactly what its name suggests, a slice of
time. When you want to have a sprite animated or moved
automatically, you must specify how often movement or
animation is to occur. These times are given in time-slices.
A time-slice passes every time sprites are updated by the
function sprite_update_all_anim_and_move() or manually
updated by you. So if you wanted a sprite to change its
animation frame every time it was updated, you would be
setting it to update every time-slice. The actual elapsed
time between updates is irrelevant - it is the number of
times that an update is performed that determines when
sprites will move or animate.
 
 In the default mode, SPR_MODE_WHOLE, the speed parameter is
treated as a counter that says how many time-slices to wait
before moving or animating . A value of 1 means "do it every
time-slice" while a value of 10 means "do it every 10 time-
slices.
 
 If the sprites mode is SPR_MODE_FIXED, the speed parameter
is treated as a fixed point 4.4 digit number. This means that
the top four bits of the byte are the number of times to
move/animate each time-slice, while the bottom four bits hold
a fractional number of times to move/animate each time-slice.
Using this mode you can specify that a sprite is to move or
animate from once in every 16 time-slices, to 16 times per
time-slice, with many combinations.
 
 For example, to move twice every time-slice you would use a
speed value of (1<<5), to move 2.5 times per time-slice you
would use a speed value of ((1<<5)&(1<<3)). Note that moving
occurs when whole number quantities of time-slices are
reached: moving 2.5 times per time-slice is approximated by
moving 2 times, then 3 times, then 2 times etc.
 
 Regardless of the mode of the sprite, a speed value of zero
indicates that the sprite will stop updating movement or
animation.
 
Sprite Movement Functions
void sprite_set_move_info (sprite_system *sys,int snum,UBYTE
                            speed,int x_inc,int y_inc);
 
 This function tells JLib to update the position of the
sprite snum according to the speed and increment parameters.
The parameters x_inc and y_inc refer to how many pixels to
move in the x and y directions whenever the sprites speed
dictates that it is to move. A negative value for either of
these parameters means moving up and left respectively, while
positive values indicate moving down and right respectively.
The speed, x_inc and y_inc parameters are interpreted
differently depending on the mode of the sprite, but refer to
how many pixels to move in the x and y directions when the
sprite does move.
 
void sprite_set_anim_info(sprite_system *sys,int num,UBYTE
speed,int frames,int *pat);
 
 Within this function speed is interpreted in the same way
as speed in sprite_set_move_info() above. The parameter
frames gives the number of animation frames in the sequence
to be followed by the sprite num. pat is an integer array of
length frames, where each number from pat[0] to pat[frames-1]
is a frame number in the sprite system. When the sprite
reaches the end of the pattern it will begin again at the
start of the animation sequence.
 
void sprite_update_anim_and_move(sprite_system *spr_sys,int snum);
void sprite_update_all_anim_and_move(sprite_system *spr_sys);
void sprite_do_all_anim_and_move_n_times(sprite_system *spr_sys,int n);
 
 These functions automatically update the animation and
movement information of sprites in the sprite system spr_sys
that are turned on, according to the movement and animation
information set by sprite_set_anim_info() and
sprite_set_move_info(). These functions should be called when
the sprite or sprites to be updated are not drawn anywhere.
 
Sprite Frame Drawing
void buff_stencil_sprite(sprite_sys *ssys, int frame, BR *obuff,int x, int y );
void buff_stencil_spriteNC(sprite_sys *ssys, int frame, BR *obuff,int x, int y );
void buff_stamp_sprite(sprite_sys *ssys, int frame, BR *obuff,int x, int y );
void buff_stamp_spriteNC(sprite_sys *ssys, int frame, BR *obuff,int x, int y );
 
 These functions allow sprite frames to be drawn into a
buffer without having to set up a sprite. The
stencil_sprite() function draws a sprite frame with a
transparent background, while stamp_sprite() draws the
background colour 0 as well as the solid parts of the sprite.
 
void buff_stencil_sprite_color(sprite_sys *ssys, int frame, BR
                    *obuff,int x, int y, UBYTE col);
void buff_stencil_sprite_colorNC(sprite_sys *ssys, int frame,
                    BR *obuff,int x, int y, UBYTE col);
void buff_stamp_sprite_color(sprite_sys *ssys, int frame, BR
                    *obuff,int x, int y, UBYTE col);
void buff_stamp_sprite_colorNC(sprite_sys *ssys, int frame, BR
                    *obuff,int x, int y, UBYTE col);
 
 These functions behave exactly like
buff_stencil/stamp_sprite(), except that instead of drawing
the given sprite frame in the colours it was defined in, the
frame is drawn in solid colour. This allows effects like
shadows and fading out on sprite frames.
 
void buff_stencil_sprite_buff(sprite_sys *ssys,int frame,BR
                    *obuff,int x, int y,BR * sbuff);
void buff_stencil_sprite_buffNC  (sprite_sys *ssys,int frame,BR
                    *obuff,int x, int y,BR * sbuff);
void buff_stamp_sprite_buff(sprite_sys *ssys,int frame,BR
                    *obuff,int x, int y,BR * sbuff);
void buff_stamp_sprite_buffNC(sprite_sys *ssys,int frame,BR
                    *obuff,int x, int y,BR * sbuff);
 
 These functions behave exactly like
buff_stencil/stamp_sprite(), except that instead of drawing
the given sprite frame in the colours it was defined in, the
sprite frame is drawn to the buffer obuff as a texture taken
from the buffer sbuff. The source buffer sbuff must be at
least as wide as the sprite frame being drawn.
 
void sprite_build_from_buff(sprite_system *sys,int
                fr,buffer_rec *bf,int x1,int y1,int x2,int y2);
 
 Sprites frames can be "built" out of a buffer's contents
dynamically by using this function. If you have a buffer with
data drawn in it that you would like to make a sprite frame
out of, then you can copy that data into a frame and use it
just like a regular sprite frame. The parameter fr is the
frame you would like the data copied into. If the frame was
already used then it will be overwritten. To find the next
free frame available in the sprite system use the function
sprite_find_first_frame(). You can't build a sprite bigger
than SPR_MAX_X or SPR_MAX_Y. If the co-ordinates given cover
an area bigger than this then the frame will be truncated to
the maximum size. Built sprites are created without any
bounding rectangles. See the function sprite_add_rect() to
add bounding rectangle to sprites at run time.
 
Collision Testing
 
 You can test any two sprites to see if they are colliding.
Each sprite frame has 0-255 rectangles associated with it and
stored in its sprite file. These rectangles are used by JLib
to calculate whether sprites are intersecting. You can use
the utility spr_edit.exe (see Utilities) to examine and
change the bounding rectangles of frames within sprite files.
 
 There are other, more precise methods of collision
detection available than bounding rectangle checks. The
reasons I chose bounding rectangles above any other methods
are speed and accuracy. Bounding rectangles are fast compared
to bit manipulation detection methods. If you want better
accuracy of collisions with other sprites, you can increase
the number of rectangles associated with a sprite frame to
provide more accurate coverage. There is a trade off in
accuracy versus time (just like other methods), but this
trade off can be made on a per-sprite basis. If a sprite
doesn't need collision detection you don't even have to have
a bounding rectangle at all.
 
int sprite_do_intersect(sprite_system *sys,int sprite1,int sprite2);
int sprites_do_intersect(sprite_system *sys1,int sprite1, sprite_system *sys1,int sprite2);
 
 These functions return non zero if sprite1 is colliding
with sprite2. Note that the sprites must both be turned on
for a collision to be detected. Whether the sprites are
currently drawn anywhere or not is not tested when deciding
collisions. Thus sprites being drawn into two different
buffers can still collide if they are turned on and their
bounding rectangle co-ordinates overlap. The first function
given is for testing sprites in the same sprite system, the
second is for situations where two sprites in diferent sprite
systems are to be tested for a collision.
 
Developers Note: Collision functions haven't been optimised
yet. A collision routine that checks every sprite against one
another and then lets you query a table of who is colliding
with who (which will be very fast) is planned. A function to
automatically generate bounding rectangles for sprite frames
is also planned
 
 
Miscellaneous Sprite functions
 
void sprite_add_rect(sprite_system *ssys,int frame,UBYTE
                    x1,UBYTE y1,UBYTE x2,UBYTE y2);
 
 This function adds a bounding rectangle to the specified
sprite frame.
 
int sprite_find_first_free(sprite_system *spr_sys);
 
 This function returns the number of the first unused sprite
(the first sprite turned off) in a sprite system.
 
int sprite_find_first_frame(sprite_system *spr_sys);
 
 This function returns the frame number of the first unused
frame in a sprite system.
 
void sprites_kill_buffers(sprite_system * ssys);
 
 This function destroys the buffers used by a sprite system
to save the area underneath sprites. This is useful to save
memory in cases where you are not using sprites, but are
using sprite frames to stamp or stencil images in your
application.
 

Input Functions
Overview
 
 Input functions are meant to provide a way for your
programs to receive input from the user in a fairly
consistent manner across platforms. Three different devices
are supported: The keyboard, mouse and joystick.
 
 Once you initialise each device, you can read them using
provided functions. Note that if you call an input function
and the device has not been initialised, no action is taken.
You should only initialise an input device once the screen
has been initialised, as some input devices require this to
be the case.
 
Mouse
 
 Functions are available to initialise the mouse and read
its button state and position in screen co-ordinates. To
provide compatibility for the lowest common system, only one
mouse button may be checked.
 
 Your programs can check if the current target provides
mouse support by checking the constant MOUSE_AVAILABLE. If
this is 0 then no mouse support is available. Any non-zero
value for this constant means that the target has support for
a mouse. This does not mean that a mouse is actually
installed on the machine, just that if one is installed, the
mouse functions can be used to get input from it.
 
int mouse_present(void);
 
 This function initialises the mouse if one is present, and
returns MOUSE_PRESENT if there is a mouse available and
initialised. If this routine returns MOUSE_ABSENT, it means
the computer the program is running on does not have a mouse
attached (or it isn't functioning or recognised). You should
always have the screen initialised before calling this
function.
 
void mouse_closedown(void);
 
 This function clears up after the mouse and should always
be called before your program exits and before the screen
mode is restored. To use the mouse after calling this
function you must call mouse_present() again.
 
void mouse_show_pointer(void);
void mouse_hide_pointer(void);
 
 These two functions are designed to allow the mouse pointer
to be hidden. On some systems this may not be possible. The
principle function of these routines is to allow drawing to
the screen to take place without being disturbed by the mouse
cursor. If your system supports this in hardware then these
functions will implemented as stubs. If the mouse is
initialised and the pointer is showing then you should always
hide the mouse cursor before drawing to the screen, and show
the pointer once drawing is completed. If you don't do this,
drawing may be corrupted on some targets.
 
void mouse_get_status(int *x_pos,int *y_pos,int *b_status);
 
 This function stores the status of the mouse in the
integers passed. x_pos and y_pos are filled with the current
x and y position of the mouse in pixels, relative to the top
left of the screen. b_status is filled with the status of the
mouse button. The value returned in b_status can be read as 0
(no button pressed) or 1 (button pressed) by using the macro
BUTTON_DOWN(status).
 
void mouse_set_status(int x,int y);
 
 This function is intended to allow you to position the
mouse pointer on the screen at the given x and y co-
ordinates.
 
Keyboard
 
 The keyboard routines in JLib are intended to provide the
user with more control over reading keys than the standard C
library provides. Two types of keyboard functions are
supported; buffered character input and key-press polling. If
the target supports JLib style keyboard input then the
constant KEYBOARD_AVAILABLE will be non zero. Note that C
standard library keyboard functions are not likely to work
while the keyboard is being used by JLib, so calls to getc()
and fgetc(stdin) should be avoided while the JLib keyboard
routines are being used.
 
 All keyboard input is internally buffered in a 256
character buffer. The oldest elements of the keyboard buffer
are overwritten when buffer overflow occurs.
 
 There are several type of keys as far as the library is
concerned:
     Normal: Keys which correspond to an ASCII character
    code are stored in the keyboard buffer as their ASCII
    value.
     Extended: Keys which have no ASCII code, such as
    CTRL,ALT etc.
 
 When you press a key, its value is stored in the keyboard
buffer. When the key is released, its value is stored with
the most significant bit (bit 15, since the keyboard buffer
is internally USHORTS) set to 1.
 
 The keyboard function you should use depends on the type of
input you are interested in. If you want to simply poll the
keyboard, you should use the kb_keydown() function. If you
want buffered input of normal characters only, you should use
the kb_get_next_key() function. If you want to know whether
CTRL, ALT, a cursor key or SHIFT was pressed as well as
ordinary characters, you should use kb_get_next_ext_key().
Finally, if you need buffered input of key-up and key-down
events of normal and extended keys alike, you should use
kb_get_next_code(). The following table summarises the
possibilities:
 
Function      Constants      Type           Keys
kb_key_hit()                 Buffered       Normal
kb_ext_key_hi                Buffered       Normal &
t()                                         Extended
kb_keydown()  KEY_*          Polling        KEY_*
                                            Constants
kb_get_next_k ASCII chars    Buffered       Normal
ey()
kb_get_next_e ASCII chars &  Buffered       Normal &
xt_key()      EXT_*                         Extended
kb_get_next_c ASCII (w/bit   Buffered       Normal,Extend
ode()         7) & KB_*                     ed,Key-up
 
void kb_init(void);
 
 This function initialises the keyboard device ready to
begin reading key values. You should call this function
before using any other keyboard functions, after the screen
is initialised with screen_set_video_mode(). This function
does not return a success code because if your keyboard is
not functioning it is unlikely that you could even run any
programs at all. The keyboard state is cleared when the
keyboard is initialised, i.e. no key presses made before
initialisation will be available.
 
void kb_closedown(void);
 
 This function returns the keyboard to its former state
whereby it is safe to use C standard library input functions,
and should be called before the screen state is restored by
your program.
 
int kb_keydown(int key);
 
 This function returns non zero if the given key is pressed
down at the moment this function is called. The constants in
<jlib.h> starting with KEY_ are the only suitable parameters
for this function.
 
int kb_key_hit(void);
 
 Returns non zero if any non-extended key has been hit or
released since the last time the keyboard was cleared or
initialised. This function does not remove any keys from the
keyboard buffer, so it may be used to peek ahead to determine
whether or not to call kb_get_next_key().
 
int kb_ext_key_hit(void);
 
 This function returns non zero if any key (normal or
extended) has been hit or released since the last time the
keyboard was cleared or initialised. This function does not
remove any keys from the keyboard buffer, so it may be used
to peek ahead to determine whether or not to call
kb_get_next_ext_key().
 
char kb_get_next_key(void);
 
 Returns the next non-extended key waiting in the input
buffer, or if the buffer is empty, waits for a key to be hit
and returns it. This function behaves very similarly to
getc() or fgetc(stdin).
 
USHORT kb_get_next_ext_key(void);
 
 Returns the next key waiting in the input buffer, or if the
buffer is empty, waits for a key to be hit and returns it.
The lower 8 bits of the value returned contain the character
hit, while the upper 8 bits contain the extended keys pressed
at the same time as the character. If no NORMAL key has been
hit, this function will wait until one has been pressed and
then return it along with any extended keys pressed at that
time.
 
 Cursor keys are treated like normal keys by this routine,
so they are returned as soon as they are encountered in the
buffer, without a normal key having been pressed.
 
 The following constants can be used to check the upper 8
bits of the returned value for extended key presses:
 
Constant                     Extended Key
EXT_SHIFT                    Shift Key
EXT_CTRL                     Control Key
EXT_ALT                      Alt Key
EXT_UP                       Up Key
EXT_DOWN                     Down Key
EXT_LEFT                     Left Key
EXT_RIGHT                    Right Key
 
 Since cursor keys are returned straight away, the lower 8
bits of the value returned from this function are undefined
if any of EXT_UP/DOWN/LEFT/RIGHT are set.
 
USHORT kb_get_next_code(void);
 
 This function returns the next code waiting in the keyboard
buffer. The code returned may be an ASCII character, an ASCII
character with bit 15 set, or a special code. If bit 15 of a
returned code is set, the key indicated was released,
otherwise it was pressed. The macro KB_WAS_RELEASED(code)
evaluate to true if code represents a key that was released.
 
 If the code not an ASCII value with or without bit 15 set,
it is a code for an extended key.
 The macro KB_IS_SPECIAL_CHAR(code) evaluates to true if
code represents an extended key either pressed or released.
The following constants may be used to determine which
extended key was pressed:
 
Key down                     Key up
KB_LSHIFT                    KB_LSHIFT_UP
KB_RSHIFT                    KB_RSHIFT_UP
KB_CTRL                      KB_CTRL_UP
KB_ALT                       KB_ALT_UP
KB_LEFT                      KB_LEFT_UP
KB_RIGHT                     KB_RIGHT_UP
KB_DOWN                      KB_DOWN_UP
KB_UP                        KB_UP_UP
KB_NO_CODE                   No code was waiting in the
                             buffer.
 
 
void kb_clear(void);
 
 This function flushes the keyboard buffer of all
characters, similarly to fflush(stdin). It also clears the
status of any pressed keys, until they are pressed again.
 
Joystick
 
 JLib applications can read the joystick as follows: Your
programs can see whether joystick support is enabled for a
given target by reading the constant JOYSTICK_AVAILABLE which
will be defined as non-zero if joystick support is available
for the target. Note that even though a target supports
joysticks, a given computer may not have any attached to it.
Each joystick has only two buttons which may be read, to
cater for the lowest common denominator. Joysticks are
treated like digital sticks, so you can read a direction
value, but no magnitude. An exception to this statement is
that because you can read raw joystick values, it is possible
to interpret them (pretty much on a target by target basis)
in whatever way you choose. The library supports converting
these raw values into a number representing a direction.
 
int joystick_count(void);
 
 This function returns the number of joysticks connected to
the computer. Each stick is identified by a number starting
from 1. The number returned is the maximum value that you may
pass to the other joystick functions. If 0 is returned you
may not use any further joystick functions, since no
joysticks are available for use. This function must be called
before any other joystick functions such as joystick_init().
 
int joystick_init(int which);
 
 This function initialises the joystick identified by the
number which. If this call returns 0 then an error occurred
initialising the joystick and it can not be used.
 
void joystick_closedown(int which);
 
 When you are finished reading values from a joystick you
should shut it down with this function.
 
void joystick_get_status(int which,int *x_axis,int *y_axis,int
*b_status);
 
 This function will return  raw information about the
joystick position. You may use this raw information on a
target by target basis, or you may have the library convert
the raw data into a direction for you. On targets that
support analogue joysticks, the values returned may indicate
the strength of the joysticks position in the x or y axis. On
targets using digital sticks, the axis numbers are likely to
vary only between -1 and 1.
 
 The button status of a stick can be found with the macros:
 
Macro                        Meaning
FIRE_1_DOWN(status)          Fire button 1 is pressed
FIRE_2_DOWN(status)          Fire button 2 (if any) is
                             pressed
 
 Direction values can be obtained from the axis values by
calling the joystick_get_direction() function.
 
int joystick_get_direction(int which,int x_axis,int y_axis);
 
 Passing the raw values x_axis and y_axis from a call to
joystick_get_status() to this function will return a more
easily usable value representing the direction in with the
stick is being held. This function will only work if the
joystick has previously been calibrated using
joystick_calibrate().
 
 Values returned can be any of:
JOY_CENTER
JOY_NORTH
JOY_SOUTH
JOY_EAST
JOY_WEST
JOY_NORTHEAST
JOY_NORTHWEST
JOY_SOUTHEAST
JOY_SOUTHWEST
 
void joystick_calibrate(int which,int l,int r,int t,int b,int
x_cen,int y_cen);
 
 This function is used to calibrate the joystick in order to
allow JLib to convert raw joystick values to directions. You
pass this function the stick number and the raw values
received when the stick is held to the very left, right, top,
bottom, and x and y centres. It is anticipated that you will
ask the user to do this once at the start of your joystick
using application, record the results and use this function
to calibrate the joystick.
 
 Since joysticks can change their values as they warm up, it
would be advisable to allow re-calibration at any time during
your joystick using application. The demonstration programs
distributed with JLib include simple joystick calibration
procedure.
   Images
Overview
 
 Images are a convenient way for your program to load and
display pictures such as backgrounds and titles. Two image
file formats are supported as of JLib version 1.5, PCX files
and JLib's own file format: .jlb files. I probably won't be
adding any more image functions, as it is a simple task to
convert images to and from PCX files using many public domain
image utilities.
 
Developers Note: There may be some problems with .jlb files
on machines with a different byte order than PC's. The most
likely symptom is demo1 crashing. I suggest that non-PC users
use PCX routines until I get this problem sorted out.
 
Image Functions
image *image_load_pcx(char *filename);
image *image_load_jlb(char *filename);
 
 These two functions load PCX and .jlb files respectively,
create space for storing them in an image record and return a
pointer to that record. If the file given as an argument
can't be loaded then the image pointer is set to NULL. If the
image was loaded correctly then the following macros can be
used to get information about the image:
 
Macro                        Meaning
IMG_WIDTH(image)             Width of the image in
                             pixels.
IMG_HEIGHT(image)            Height of the image in
                             pixels.
IMG_PALETTE(image)           Returns a pointer to the
                             images palette.
 
image *image_free(image *img_ptr);
 
 This function releases the memory used by an image back to
the operating system. Since images can potentially use a lot
of memory, it is recommended that you free the resources used
by an image as soon as you are finished with it.
 
int image_save_jlb(char *filename,buffer_rec *buff,UBYTE *pal);
int image_save_jlb(char *filename,buffer_rec *buff,UBYTE *pal);
 
 If you have a buffer containing some image data you would
like to save as a .jlb or .PCX file you can save it with
either of these functions. You can then reload the buffer as
an image using the appropriate image loading function.
 
void buff_blit_img_to(buffer_rec *dest,int x,int y,image
*img,int ix1,int iy1,int ix2,int iy2);
void buff_blit_img_toNC(buffer_rec *dest,int x,int y,image
*img,int ix1,int iy1,int ix2,int iy2);
 
 This function takes as parameters a destination buffer dest
and the position x, y in that buffer that you want the upper
left corner of the image img blitted to. It also takes the 4
co-ordinates of the rectangle within the image that you would
like copied into the buffer. The specified part of the image
is copied into the buffer, with clipping performed if
required.
Miscellaneous Functions
float jlib_return_version_number(void);
 
 This function returns a floating point value that is the
version of the library that was compiled, i.e. 1.6 for JLib
version 1.6.
 
char *jlib_return_version_string_string(void);
 
 This function returns a string with a brief description of
the version of the library that was compiled.
 
void popup_about(UBYTE fg,UBYTE bg);
 
 Draws an "about" dialogue on screen containing target and
mode information, in colours fg and bg. You must have either
the keyboard or the mouse initialised before calling this
function , or the user will not be able to press a key/click
to move on. If the target has no keyboard or joystick support
the function will use fgetc(stdin) to wait for the user to
press a key.
 
void popup_info(char *text,UBYTE fg,UBYTE bg);
 
 Draw on screen a dialogue containing text. The dialogue
size is adjusted to fit the amount of text to be shown You
must have one of the keyboard or mouse initialised before
calling this function , or the user will not be able to press
a key/click to move on. If the target has no keyboard or
joystick support the function will use fgetc(stdin) to wait
for the user to press a key.
 
void jlib_exit(char *message);
 
 This function restores the system state if possible and
exits to the operating system as gracefully as possible. This
function is called internally by the library whenever a fatal
error occurs. You may call this function from within your
application to handle fatal errors. Note that if a custom
error handler has been set with jlib_set_error_handler() than
that will be called instead of the default error handler.
 
void jlib_set_error_handler(exit_function func);
 
 This function allows you to specify your own exit function
in the event of a fatal library or application error. If you
want to write your own error handler I suggest looking in
source/misc/error.c to get an idea of what to do upon an
error. Your exit function should take one char * parameter
which is a message describing the error that caused the fatal
exit.
 
void jlib_exit_details(char *message);
 
 This function performs most of the processing required from
an error handler. It is advised that custom error handlers
either call this function, or mimic its actions closely. Note
that this call does return, so you must exit() or abort() the
program yourself after calling it.
 
void uclock_init(void);
 
 This function initialises a high resolution timer and
starts it counting. Once initialised, time values can be read
from the timer by calling the function uclock_read(). The
constant UCLOCK_TICKS_PER_SECOND defines how many times per
second the clock is updated.
 
unsigned int uclock_read(void);
 
 This function returns the current value of the high
resolution timer. You must call uclock_init() prior to using
this function. Note that the values returned by this function
will always increase over time. The difference between two
successive calls to this function determines how much time
has passed. Dividing this number by UCLOCK_TICKS_PER_SECOND
will return the time passed in seconds.
   Debugging
Overview
 
 Debugging information can be compiled into JLib programs if
debug support is built into the library when it is built. The
generation of debug support is turned on by defining JDEBUG
in the target header file jconfig.h. Please note that the
library debugging code has nothing at all to do with symbolic
debugging code as generated by your compiler options. The
library debugging facilities may be used in your own programs
to aid development.
 
 Debug support may be default debugging code as described
here, or target specific debug activity (which will be
documented in the targets section of this documentation. If
JDEBUG is not defined when the library is built, all library
debugging code is stripped from the final executable, and all
debugging statements have no effect.
 
 When compiled in, debug support takes the form of a runtime
stack manipulated by the library which is dumped if an error
occurs, allowing you to see which function caused any
problems. In addition, a stream of debug information can be
generated which prints every function entered and left, and
any ancillary debug information included in the program code.
The printing of functions entered and left, and ancillary
debug statements can be activated for all or only parts of
your program .
 
 Once the library has been built with default debugging
enabled, the following macros are available to provide
debugging information:
 
Macro                        Meaning
JLIB_DEBUG_ON                Dump debug information from
                             this point.
JLIB_DEBUG_TRACE             Dump all functions
                             entered/left from this
                             point.
JLIB_DEBUG_OFF               Stop dumping all debugging
                             information.
JLIB_ENTER(x)                Record our entry to function
                             x.
JLIB_LEAVE                   Record our leaving the
                             current function.
                             
These apply after            
JLIB_DEBUG_ON or TRACE
JLIB_DUMP_STACK              Record our leaving the
                             current function.
JLIB_SPRINTF(str,val)        Print the string str with a
                             specifier for val.
JLIB_PRINT_DEBUG_INFO(x)     Print the string x.
 
 You can use the debugging macros in you own programs if you
wish, follow the style of the library source code if you are
unsure of how to go about this.
 
Validity Checking Functions
 
void jlib_check_buffer(buffer_rec *buff);
void jlib_check_sprite_system(sprite_system *sys);
void jlib_check_sprite(sprite_system *sys,int snum);
void jlib_check_frame(sprite_system *sys,int frame);

Undocumented.

   Utilities
Overview
 
   Most of the utilities are still under evolving
construction, so don't expect too much from them. I've taken
the philosophy that if another program exists to do
something, then I might as well use that instead of
reinventing the wheel, e.g. I haven't written a sprite
drawing program. If you want to create sprites I suggest you
use whatever package you prefer (I recommend Satan Paint and
Povray, available free for many platforms), then convert the
output into PCX files and cut them out for inclusion.
 
 The utilities began life when the only targets written were
320x200x256, so they are most useful in that resolution. I
copied low resolution builds of them into my path so I could
use them even after I recompiled the library for higher
resolution graphics modes.
 
textmode.exe
 
 This is a very simple utility, it just puts the screen back
into text mode. It is not useful under Linux or X11, as if
you trash the screen in these environments something fairly
major has probably happened. I use this from DOS with djgpp
and Watcom if my program crashes and leaves the screen in
graphics mode.
 
sprgrab.exe
 
 This program lets you grab sprites from PCX files and
stores them in sprite files. It is pretty non user friendly,
but it works most of the time. Sprites are saved with a
default bounding rectangle which surrounds the whole sprite.
 
autograb.exe
 
 This program lets you grab sprites from PCX files
automatically, providing that you follow certain conventions.
The PCX file containing sprites must be laid out with one
background colour, which does not appear in any of the
sprites in the picture. The sprites to be cut out should not
be bordered by any boxes, just the background colour. Once
run, the utility will surround the each suggested sprite with
a white rectangle. If you press the `Y' key, that sprite will
be saved out. Any other key causes the sprite to be skipped.
   
joinspr.exe
 
 This program joins multiple sprite files together. Because
the number of sprites in a sprite file is kept at the start
of the file, the process involves more than just
concatenating the files together. Sprite files are joined in
the order given on the command line. Once you have joined
your sprite files together you can use spr_edit to put them
in the correct order for loading into your application.
 
strippal.exe
 
 This utility takes the palette out of a PCX or .jlb file
and puts it into a file suitable for loading by the function
pal_load().
 
td2spr.exe
 
 This converts a "twilight dreams" sprite file into a JLib
sprite file. The twilight dreams sprite editor is available
by ftp from x2ftp.oulu.fi. It was written more as an example
of how to convert from one format to another than as an
incredibly useful utility. I would love to see some other
converters come floating my way (hint, hint).
 
spr_edit.exe
 
 This is probably the most ill-named utility. Basically this
program is designed to add and remove bounding rectangles and
reorder sprite files. Its also handy for seeing if you have
cut out sprites correctly. There are a couple of thing to
note about this program: You can only edit the bounding
rectangles of the input (left) file. Any changes you make on
the left are reflected to the right if the same sprite has
been copied to the right. This is because when it copies, it
only copies a pointer and so the right hand sprite is the
same as the left.
 
pcx2jlb.exe
 
 This utility takes a PCX file and converts it into a .jlb
file. You will probably find that JLib files are smaller than
the same image in a PCX. Also, you will never have to worry
about the image format becoming proprietary (does anyone
remember GIF? ).
 
pal_edit.exe and pal_conv.exe
 
 Pal_edit.exe is a palette editor contributed by Lennart
Steinke of Germany. It allows you to manipulate palette
colours and create fades from one palette colour to another.
The palette is saved using the lower 6 bits of the UBYTE RGB
colours, so that PC based paint programs may load and use
them. The pal_conv.exe utility converts pal_edit output files
into a palette file suitable for loading with pal_load().
   Performance
Increasing Speed
 
 Most of the speed in your programs will be lost when the
buffer you are drawing into is blitted to the screen, due to
the slow nature of video operations. You can lessen the
impact of buffer blitting in your programs by drawing as much
as possible into a buffer before you update the screen. If
you are drawing hundreds of dots or circles then you will
gain a speedup by "batch copying" your updates rather than
updating the screen after every drawing operation in your
offscreen buffer.
 
 Another way to speed up drawing to the screen is to only
update those parts of it that have changed. This principle is
known as 'dirty rectangles' and is particularly effective
when you only have a few moving things on screen. The basic
idea is to minimise actual video writes. Also, in some cases
you may be able to draw some parts of the screen less often
than others. If you want 30 frames per second of smooth
scrolling action, no one will notice if you only update the
scoreboard part of the screen twice a second. if the
scoreboard is 1/5th of the screen this could speed up your
program by 15-30%. You should consider optimising your
blitting code on a target by target basis if you need
absolute top performance.
 
Decreasing Memory
 
 It is a good idea for both space and speed efficiency to
only create a sprite system with room for as many sprites as
you will actually use. It is also more efficient to limit the
number of frames to the minimum you need to hold all of your
frames, and keep SPR_MAX_X and SPR_MAX_Y as small as possible
given your projects needs. This will keep down the amount of
memory used by your program, limiting any paging that may
occur, and giving other processes more RAM in multitasking
environments.
 
 The sprite code automatically minimises its memory usage
according to the largest sprite frame in the system. if you
will only be stamping or stencilling sprites, and not using
the drawing/saving/restoring functions, then you can safely
free all buffer memory used by the sprite system
 
 Buffers can also use a large amount of memory, so try to
reuse them where you can, and free any structure (i.e. sprite
system, buffer, image) as soon as you have finished with it.
Good program design is the first step to a memory efficient
program.
 
 When you cut out your sprites remember to cut the minimum
area around each one, as this means the library will do less
work to display it. Use as few bounding rectangles as needed
to outline your sprite for collision detection, as each
rectangle uses more memory and is another collision to check.
Information
djgpp
 
 djgpp is a port of the GNU C compiler (GCC) for MS-DOS
based machines. The GNU C compiler is free and comes with
various utilities for developing C and C++ programs. There is
a version of GNU C for almost every machine on the planet,
making it THE choice for writing portable programs. djgpp is
ANSI compliant and provides a 32 bit flat memory model for
programs. This means we don't have to fluff around with "far"
pointers and all that, and we get access to heaps of memory
(If you'll pardon the pun). In short, its very useful and is
ideal for writing games (as they are such resource hungry
applications). Proof of this comes from ID software, who are
using djgpp to write "Quake"-their successor to "DOOM".
 You can get more djgpp related information from:
 Usenet: comp.os.msdos.djgpp (look for the weekly mini-faq).
 WWW: http://www.delorie.com
 The standard complaint about GCC seems to be that it has
fairly long compilation times. However, the finished
executable always seems to run impressively quickly (and
that's the part we both care about, isn't it?).
 
Linux
 
 Linux is an operating system. I tried, and failed, to come
up with an expression of how cool Linux is. I have now
included the Linux info sheet in the library distribution as
the file linux.txt. It does a far better job of explaining
the great features of linux than I can.
 
The Future
 
 Future developments planned for JLib:
     More Targets-particularly the Macintosh and native
    Windows.
    An order n log n sprite intersection algorithm.
    More palette effects.
    Joystick code for all targets.
    A blow-your-socks-off main demo.
    Library of development graphics to get you writing
apps quicker.
     Some JLib Extensions, bolt-on packages that run over
    JLib and provide stuff like fonts, special effects,
    windows, 3D etc.
     Some more user code included somewhere (you can help
    with this!).
     More primitives.
Contributors
 
 The following is a list of people who have contributed in
some way to the development of JLib, either by sending code,
allowing others to use it, or posting bug reports, fixes or
suggested fixes. Note that I won't put peoples email
addresses in here, to protect their privacy. If you are
featured and want your address put in then write and tell me.
If I left you out, I'm sorry, remind me and I will remedy the
situation.
 
     Mike Manly
    Henrik Schmidt
    Lennart Steinke
    George Resnick
    Shawn Hargreaves
    Charles Sandmann
    Raymond Penners
    Arturo Espinosa
    Nissim Chudnoff
 
 Also a big thank you to those who took time out to report
bugs and make suggestions. You know who you are! Thanks are
also due to the many people who contribute to the development
and distribution of free software of such high quality as
Linux and djgpp.
 
 Thanks to you all.
Target Information.
Overview
 
 This section is intended to detail each of the targets
available for JLib. The peculiarities of the target may limit
or change the expected behaviour of any of the library
functions. Any such behaviour will be noted here.
 I hope to encourage people to add targets as they wish, as
each added target makes the library potentially more useful.
So if you see a target here that isn't fully functional or
lacks a lot of functions, be patient. Someone will be adding
functionality somewhere. If you want to contribute a target,
but only have some of the functions done, contribute it
anyway and let someone else finish it or contribute to it
also.
 
Compiling for multiple targets
 
 If you want to compile for more than one target often on
your machine, It will get very annoying to have to constantly
recompile. I recommend compiling each targets library and
renaming them to something meaningful. Remember to keep the
include files separate also, or you might end up in trouble!
To do this you will have to manually include the header files
at compile time, or define the target on the command line. I
will try to include more details on this in a future release.
 
 
DJGPP_V2: MODE_13H
Author:                      Jonathan Griffiths
Description:                 DJGPP compiler, mode 13h
                             graphics.
Performance:                 Fast even with slow cards.
                             Rocks under local bus.
Compiling:                   Compile with -lj on the
                             command line.
Execution:                   Run under DOS, Windows (all
                             flavours) and OS/2.
Comments:                    This was the first target I
                             wrote.
Bugs:                        Don't seem to be any
                             interrupt problems now.

DJGPP_V2: GRX2_320x200x256, GRX2_640x480x256, GRX2_800x600x256
Author:                      Jonathan Griffiths
Description:                 DJGPP with various modes
                             through libgrx V2.
Performance:                 Fairly slow, acceptable with
                             local bus cards.
Performance:                 If you have a driver for
                             your card it will run
                             faster.
Compiling:                   Compile with -lj and -lgrx20
                             on the command line.
Execution:                   In theory, same as the DOS
                             MODE_13H target.
Comments:                    A bit of a hack, so it's
                             rough, but DPMI compliant.
Comments:                    Check the copyright of the
                             new version.
Comments:                    I'm going to create a VESA
                             target to replace this.
Bugs:                        Mouse shape/colour sometimes
                             corrupted.

LINUX_SVGALIB: SVGA_320x200x256, SVGA_640x480x256,
SVGA_800x600x256
Author:                      Jonathan Griffiths
Description:                 Linux with various modes
                             through svgalib.
Performance:                 Very fast, congratulations
                             to the svgalib team!.
Compiling:                   Compile with -lvga on the
                             command line after -lj.
Execution:                   Static library builds should
                             run on all linux's.
Comments:                    Uses svgalib palette & mode
                             stuff but Blits itself.
Comments:                    Your card needs to be
                             supported by svgalib to use
                             this target.
Bugs:                        None reported.

X_WINDOWS: X_320x200x256, X_640x480x256, X_800x600x256
Author:                      Mike Manly ,Jonathan
                             Griffiths, Henrik Schmidt
Description:                 Hopefully generic X11.
Performance:                 Not functional yet, but
                             should be OK.
Compiling:                   You will probably have to
                             edit the makefile to compile
                             under non-linux based X's.
Execution:                   Will need compiling on each
                             X you want to run on.
Comments:                    Thanks to Henrik Schmidt for
                             his Work on this Target.
Bugs:                        There may be a problem in
                             the compression code.
Missing:                     screen_fill() and
                             screen_clear(),
Missing:                     Generic joystick support, if
                             it exists.

WATCOM: MODE_13H
Author:                      Jonathan Griffiths
Description:                 Watcom C/C++ ver 9.x, mode
                             13h.
Performance:                 As per djgpp/mode 13h
                             target.
Compiling:                   Include JLIB.LIB on the
                             command line.
Execution:                   Should run under most DPMI
                             implementations.
Comments:                    Works with 10.x.
Bugs:                        The makefile puts object
                             files into jlib\source.

WATCOM: VESA_640x480x256, VESA_800x600x256
Author:                      Jonathan Griffiths
Description:                 Watcom C/C++ v 9.x , VESA
                             1.0+.
Performance:                 Good, depends on VESA
                             implementation.
Performance:                 Get univbe if you don't have
                             a VESA card.
Compiling:                   Include JLIB.LIB on the
                             command line.
Execution:                   Should run under most DPMI
                             implementations.
Comments:                    This version is NOT
                             optimised.
Bugs:                        The makefile puts object
                             files jlib\source.
   Updates & Contacting Me
 
 If you want to get the latest version of the library from
me, send me a stamped self addressed envelope with a 1.44 MB
disk and a donation. Your comments and letters are also
welcome. Please note that the donation is merely to offset
the time it takes to prepare a version of the library for
release. The library is free in every other respect (see
above) and doesn't represent a money making venture on my
part.
 
 That said, donations are always welcome, particularly from
anyone who uses library routines in a commercial product.
 
JLib Distribution Sites
 
Primary Site       x2ftp.oulu.fi       /pub/msdos/program
                                       ming/djgpp2/
Secondary Site     sunsite.unc.edu     ?
 
 
Snail Mail
 
 Jonathan Griffiths
 82 Kowhai Rd,
 Campbells Bay,
 Auckland,
 New Zealand.
 
Email
 
 jon@ams.co.nz
 
Dial-Up Email (For Binaries)
 
 jpg@wave.co.nz
 
 I wish you all the best in using JLib, in your projects and
life in general.
 
 Happy Coding,
 Jon Griffiths
