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.

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 types of
programs such as games, drawing and design programs, demos,
graphical simulations, etc.

JLib is compiled for a particular programming environment
before being linked with your application. It allows
programmers to use their favourite development environment
without limiting the potential audience for their work..

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.


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!


Legal Information

Disclaimer

The information, source code and opinion provided with JLib
are without warranty. I make no claims as to JLibs'
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 must 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 copyright 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 conditions into each of the separate

program modules you distribute. Putting a pointer to the
library into the source would also be a good idea.


JLib Design

Some basic concepts about how JLib is designed are helpful
to determine whether you will find it useful.

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.

Debug Support

In addition to compiler generated debugging information,
JLib can be built with four levels of debugging and error
checking support. They are:

Production: No debugging code and hardly any error checking
is used. This level is for building applications for
release.

Normal: No debugging code but most error checking code is
present. Intended for people who are happy with the debug
support from their compilation environment.

Debugging: Support for multiple levels of debugging output,
verbose error descriptions, status reports and error
checking. Intended for most development work.

Paranoid: As for debugging but includes exhaustive tests of
internal validity. Intended for thorough bug investigations
and library development.

See the debugging section for information on how to set up
and use JLib debug support.


JLib Limits:

*256 colours.
*One fixed-size (at compile time) output screen to draw to.
*Currently, common resolutions of 320x200, 648x480, &
800x600.
*Direct screen access for primitive drawing is not always
available.

Installing JLib

The following instructions take you through installing JLib
step by step.


Decompress the archive file

JLib normally comes compressed using PKZIP 2.04g compatible
software. The file name of the library archive indicates the
version. For example, the file jlib_1-8.zip is JLib version
1.8. You must decompress the archive file on your system.

The library archive has the following directory structure:
jlib\
          doc\
          demo\
          source\
                    buff\
                    sprite\
                    misc\
                    target\
                              wat_vesa\
                              dj_vesa\
                              x\
                              generic\
                              svgalib\
          ute\

If you are using PKUNZIP to decompress the archive you must
use the "-d" switch to recreate this directory structure.
Other PKZIP compatible programs expand directories by
default.

Use the following steps to install JLib:

1.Go to the directory you would like JLib installed under.
2.Copy the JLib archive file into that directory.
3.Decompress the archive using one of the following commands
(Or the appropriate commands for your archive program).
     a.Users of PKUNZIP: pkunzip -d jlib_X-X.zip
     b.users of unzip: unzip -L jlib_X-X.zip

Choose a target

Choose a target from the following list, and change to the
directory listed next to that target.

Compiler/Environment     Directory

Djgpp                    jlib\source\target\dj_vesa\
Linux                    jlib/source/target/svgalib/
Watcom                   jlib/source/target/wat_vesa/
X11                      jlib/source/target/x/
Testing                  jlib/source/target/generic/


Copy the header files and makefile

*In the directory for the target you have chosen, there are
two header files (named jconfig.h and jtarget.h) and a make
file (makefile).
*Copy these three files to the jlib\source directory.
*Change your current directory to the jlib\source directory.


Choose target configuration options

*The file jconfig.h contains configuration information,
which is used to control the way the library is built.
*You should customise jconfig.h to your liking. Each line is
commented to allow you to decide which options to use.
*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. This may require privileged access on UNIX
systems.

The standard include directory can be found in the following
places for particular targets:

Compiler/Environment     Directory
Djgpp                    <path>\gcc\include
Unix                     /usr/include
Watcom                   <path>\Watcom\h


Choose make file options

You should edit the make file to change the way the library
is built by your compiler.

*You may change compiler command line options by changing
the CFLAGS= definition. Several definitions will be present
in the file showing options for optimisation and debugging.
*You should change the LIBDIR definition to point to the
library file directory used by your compiler if it is not
correct.

Note: GNU Make can be picky about the placement of tab
characters in makefiles. Be sure that you use an editor that
does not strip tab characters from text files when editing
the make file.


Run "make" to build the library

1.Perform any commands to set up your compilation
environment as you normally would before compiling programs.

2.Run your make program from the jlib\source directory. The
library, demonstration programs and utilities should
compile.

3.Once the build has finished, try running the demonstration
program to check the target.

You can rebuild the library at any time. To build just the
demo or utilities under djgpp or unix, you can use the
commands "make targets", "make demos" or "make utes".


Clean up object files

1.Run "make clean" to remove the library object files.

2.You can run "make realclean" to remove the demonstration
programs and utilities if they are no longer required.


Compile your own JLib programs

You are now ready to compile your own JLib programs.


You should use commands similar to the CFLAGS= line of the
makefile as a guide to building your programs.


Glossary

Target
A target is a combination of a programming environment and
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 usually be drawn to
a buffer first 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
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 the contents of a buffer onto the screen. Blits
always use rectangular areas.


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 Clipping) do not
perform tests for invalid co-ordinates or other parameters,
and do not perform clipping on graphics operations, when the
library is built for production. 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 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

*Points are referenced by an (X, 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 downward (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 other
standard header 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 section on
library debugging options for details on how to change this
behaviour.


*Any memory allocation 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.


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 functions
to enter and leave a graphical state, and 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 functions provide a portable way for your application
to respond to 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 that has its own palette.

Miscellaneous functions
Anything not covered by the above categories belongs to this
category, including error handling and version information.


Screen Functions

Overview

These functions are designed to give your program access to
the screen. You must initialise the screen before you can
safely use most library functions and you must restore the
screen when your program is finished. While your program is
running the available functions allow you to display
information on the screen and change the colour palette in
use by the screen.

Screen Initialisation

void screen_set_app_title(char *title);

This function allows you to specify a title for your
application. When your application runs in a windowed
environment, the title bar of the window will contain the
text "JLib Application" by default. When abnormal program
termination occurs and is handled by the library, the
message "JLib Application: Internal Error" will be shown by
default.

If a title has been set using this function, the text "JLib
Application" will be replaced in both cases with the text of
the parameter title.


This function must be called before the screen is
initialised. Multiple calls to this function overwrite the
application title until the screen is initialised.

void screen_set_video_mode(void);

This function initialises the video screen for graphics
output. You must call this function before calling any other
JLib functions with the exception of screen_set_app_title().
The result of any JLib function when the screen has not been
initialised is undefined (though the error will most likely
be caught in a debugging build of the library).

While the screen is initialised, standard I/O is unlikely to
be seen unless redirected to a file.

Calls to this function are ignored if the screen is already
initialised.

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 because they
improve portability and readability.


void screen_restore_video_mode(void);

This function returns the video screen to its state before
screen_set_video_mode() was called.

You must call this function before your program exits.
Calls to this function are ignored if the screen has already
been restored.


Screen Paging

A screen may be thought of as a page to which your programs
output graphical data. On some systems there is more than
one available screen page to draw on, but only one page can
be seen at a time.

By directing output to a page that is not visible, and then
making it visible, graphics output can be made to look
smoother because you do not see the screen being drawn.


If the target you are using supports this then the constant
SCREEN_NUM_PAGES will be defined to have a value other than 1.


void screen_set_page(int page);

This function sets the output page that the library will
draw to. After calling this function, all screen output will
go to the page specified by the parameter page. If page is
an invalid value a fatal error occurs. Valid page numbers
are in the range from 1 to SCREEN_NUM_PAGES.


If the target system does not support pages this function
has no effect.


int screen_get_page(void);

This function returns the output page that the library is
currently drawing to. This may not be the same as the
current visible page.

If the target system does not support pages this function
returns 1.


void screen_show_page(int page);

This function makes the page specified the visible output
page. Calling this function does not change the current
output page. If the target system does not support pages
this function has no effect.

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 There is also the
potential to add real paging code to some targets which I
have not implemented yet.


Screen Manipulation


void screen_clear(void);

This function clears the screen with the colour index 0. The
screen is always cleared immediately following a call to
screen_set_video_mode().


void screen_fill(UBYTE colour);

This function fills the screen with the colour index
specified by the parameter colour.

This function will not change the border colour of the
screen on targets where this is applicable.


void screen_wait_vsync(void);

This function waits until the screen refresh is in the
vertical synchronisation period if possible.

Updates made during this time are generally smoother because
the raster does not overtake the drawing process resulting
in a sheared image. To use the function, place a call to it
before any screen blitting function.

This function can dramatically slow graphics operations.
On targets where retrace checking is not possible this
function returns immediately.


buffer_rec *screen_buff_init(void);

This function returns a buffer pointer that represents the
screen or NULL if the screen memory cannot be accessed. If
the function returns a non-NULL pointer, the pointer may be
passed to other JLib functions such as buffer primitive
operations. The principle purpose of this feature is to
enable applications to potentially save memory when
constructing a simple screen, by not requiring that an off
screen buffer be created.

Buffers created with this function must be destroyed with
the function screen_buff_free().

The screen must be initialised before this function is
called.


buffer_rec *screen_buff_free(buffer_rec *buffer);

This function frees buffers allocated with the
screen_buff_init() function. The result of using this
function on a buffer that was not allocated with
screen_buff_init() is undefined.


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_COLORS1). 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 screen 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 and pseudo colour.


Screen Palette Functions


void screen_put_pal(UBYTE colour,UBYTE red,UBYTE green,UBYTE blue);

This function changes a single screen colour specified by
the parameter colour to have the given red, green and blue
components.

The screen will be immediately updated to incorporate this
change.


void screen_block_set_pal(UBYTE *palette);

This function changes the screen palette to use the palette
passed as the parameter palette.

The screen will be immediately updated to incorporate this
change. If the palette does not contain SCREEN_NUM_COLORS RGB
entries, a fatal error occurs.


void screen_blank_pal(void);

This function changes the screen palette to an entirely
black palette.

The screen will be immediately updated to incorporate this
change.


void screen_fade_in_pal(UBYTE *palette, unsigned int delay);

This function smoothly fades the screen palette from all
black to the palette specified by the parameter palette.
The screen will be immediately updated to incorporate this
change.

If the palette does not contain SCREEN_NUM_COLORS RGB
entries, a fatal error occurs.

See below for a description of the delay parameter.


void screen_fade_out_pal(UBYTE *palette, unsigned int delay);

This function smoothly fades the screen palette from the
palette specified by the parameter palette to all black.

The screen will be immediately updated to incorporate this
change.

If the palette does not contain SCREEN_NUM_COLORS RGB
entries, a fatal error occurs.


See below for a description of the delay parameter.


void screen_fade_to_pal(UBYTE *start_palette, UBYTE *end_palette,unsigned int delay);

This function smoothly fades the screen palette from the
parameter start_palette to all the parameter end_palette.

The screen will be immediately updated to incorporate this
change.

If either palette does not contain SCREEN_NUM_COLORS RGB
entries, a fatal error occurs.


The parameter delay 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

These palette functions do not affect the screen display.


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 *file_name);
UBYTE *pal_load_fp(FILE *file_pointer);

These functions allow palettes to be loaded from a file.
Palette files are simple dumps of palette arrays with no
header information in the file.

If you have the name of the file you wish to load from you
should call the function pal_load() with the name of the
file.

If you have an open file descriptor for the file you wish to
load from you should call the function pal_load_fp() with
the file descriptor. You must position the file pointer
manually before calling this function. The file will not be
closed after the palette is read.

If an error occurs while reading the palette file NULL is
returned.


UBYTE *pal_get_default(void);

This function returns a consistent palette across all JLib
targets.

The palette returned is not set by default, so if you are
not using a custom palette your application should set this
default palette.

The palette returned should be freed when no longer
required.


UBYTE *pal_copy(UBYTE *destination_palette, UBYTE *source_palette);

This function copies the entries of the parameter
source_palette to destination_palette.

If either palette does not contain SCREEN_NUM_COLORS RGB
entries, a fatal error occurs.


void pal_to_grey(UBYTE *palette);

This function alters the entries of the parameter palette so
that each entry maps to a grey scale.

If palette does not contain SCREEN_NUM_COLORS RGB entries, a
fatal error occurs.


void pal_to_red(UBYTE * palette);

This function alters the entries of the parameter palette so
that each entry maps to a red scale.

If palette does not contain SCREEN_NUM_COLORS RGB entries, a
fatal error occurs.


void pal_to_green(UBYTE * palette);

This function alters the entries of the parameter palette so
that each entry maps to a green scale.

If palette does not contain SCREEN_NUM_COLORS RGB entries, a
fatal error occurs.


void pal_to_blue(UBYTE * palette);

This function alters the entries of the parameter palette so
that each entry maps to a blue scale.

If palette does not contain SCREEN_NUM_COLORS RGB entries, a
fatal error occurs.


UBYTE pal_closest_color_rgb(UBYTE *palette, UBYTE red, UBYTE green ,UBYTE blue);

This function returns the colour from the parameter palette
that most closely matches the red, green and blue components
passed. If palette is NULL, zero is returned. Zero is never
returned otherwise since colour zero is used as a
transparent colour.

If palette is not NULL or does not contain SCREEN_NUM_COLORS
RGB entries, a fatal error occurs.


UBYTE *pal_create_remap_index(UBYTE *new_palette, UBYTE *old_palette);

This function creates an index allowing images drawn with
the given old_palette to be remapped and displayed with
new_palette. An example of when you might want to do this is
if you were showing two different images (with different
palettes) at the same time. If you set the palette based on
one image, the other will look oddly coloured. The solution
is to re-map one of the images to use the other images
palette. This is a two step process: first you create a
remap index from one buffer to another with this function ,
then you remap the buffer using buff_remap_colors().

Colour 0 in each palette is always unmapped, since it is
used for transparency.

If either palette does not contain SCREEN_NUM_COLORS RGB
entries, a fatal error occurs.


Screen Blitting

Screen blitting functions are the primary way to output
graphics on the screen. These functions copy rectangular
areas from buffers to the screen.


void screen_blit_fs_buffer(buffer_rec *source_buffer);

This function copies the buffer source_buffer that is the
same size as the screen to the screen.

This function is optimised to work only with buffers with
the same dimensions as the screen.


If source_buffer is not a valid buffer, a fatal error
occurs.


void screen_blit_buff_to(int dest_x, int dest_y,
     buffer_rec *source_buffer, int x1, int y1, int x2,int y2);

This function copies a rectangle with corners (x1, y1) to
(x2, y2) from source_buffer to the screen at position
(dest_x, dest_y).

This function is designed for blitting buffers that are not
the same size as the screen. Buffers of this nature are used
for windowing, scrolling, or when a screen is made up of
several parts that are updated at different times.

The source co-ordinates x1, y1, x2, y2 are the top left hand
and bottom right hand corners of the rectangle to be copied.

If the co-ordinates given fall outside of the range of the
screen or buffer dimensions then only any part of the source
buffer that falls on the screen will be copied.

See the section Performance: Increasing Speed for more
information on minimising the amount of blitting your
program does.


Buffer Functions

Overview

Buffers are 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. For buffers that will be drawn to the screen, a
width 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.
Operations performed on buffers are clipped by a clipping
region, which can be changed to limit the area of a buffer
that can be drawn to. 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
B_CX1(buff_ptr,y)             Upper X co-ordinate of buffer clipping region
B_CY1(buff_ptr,y)             Upper Y co-ordinate of buffer clipping region
B_CX2(buff_ptr,y)             Lower X co-ordinate of buffer clipping region
B_CY2(buff_ptr,y)             Lower Y co-ordinate of buffer clipping region


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.

A newly created buffer is initially cleared and has its
clipping region reset to include the whole buffer.


buffer_rec *noscreen_buff_init(int width,int height);

This function creates a buffer of the given width and height
and returns a pointer to the structure suitable for the
library graphics primitives. The buffer that is created is
not suitable for copying to the screen with either the
screen_blit_buff_to() or the screen blit_fs_buffer()
functions (Undefined results will occur is this happens).
The buffer is suitable for all other operations.

For targets which do extra work to create buffers that will
be drawn to the screen, using this function will provide a
speed improvement when creating temporary buffers (such as
those used to build up more complicated buffers that are
later blitted to the screen).


Once the buffer returned is no longer needed, it should be
disposed of by calling buff_free().


void buff_reset_clip_region(buffer_rec *buff);

This function sets the clipping region of a buffer to its
default values, so that all of the buffer may be drawn to.


void buff_set_clip_region(buffer_rec *buff, int x1, int y1,int x2, int y2);

This function sets the clipping region of a buffer to the
rectangle enclosed by the co-ordinates passed. For all
clipping primitives drawn into the buffer, only the part of
the buffer enclosed by the clipping region will be drawn to.


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);

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);

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 (0).

The clipping region of the buffer passed affects these
functions. To clear or fill an entire buffer, use the non
clipping versions buff_clearNC() or buff_fillNC().

void buff_draw_point(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. Points outside of the
clipping region of the buffer will not be drawn to.


UBYTE buff_get_point(buffer_rec *buff,int x,int y);

This function returns the colour of the pixel at co-
ordinates (x, y) in the buffer buff.

If the co-ordinates given do not fall inside the clipping
region of the buffer then a value of 0 is returned.


void buff_draw_box(buffer_rec *buff,int x1,int y1,int x2,int y2,UBYTE c);

This function draws a box outline in colour c, described by
the co-ordinates passed. Points outside of the clipping
region of the buffer will not be drawn to.


void buff_draw_rect(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. Points outside of the clipping region of the
buffer will not be drawn to.

void buff_draw_char(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. Points outside
of the clipping region of the buffer will not be drawn to.

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);

This function takes a text string and outputs it to the
buffer using the buff_draw_char() function. Points outside
of the clipping region of the buffer will not be drawn to.

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);

This function draws a line from the point (x, y) to point
(x2, y2) in colour c. Points outside of the clipping region
of the buffer will not be drawn to.

Drawn lines 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);

This function draws a horizontal line from the point (x1,
y1) to point (x2, y1) in colour c. Points outside of the
clipping region of the buffer will not be drawn to.


void buff_draw_v_line(buffer_rec *buff,int x1,int y1,int y2,UBYTE c);

This function draws a vertical line from the point (x1, y1)
to point (x1, y2) in colour c. Points outside of the
clipping region of the buffer will not be drawn to.


void buff_draw_ellipse(buffer_rec *buff,int x,int y,int a,int b,UBYTE c);

This function draws a hollow ellipse centred on the point
(x, y), with a vertical diameter of a, and a horizontal
diameter of b. Points outside of the clipping region of the
buffer will not be drawn to.


void buff_filled_ellipse(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. Points outside of the clipping region of the buffer
will not be drawn to.


void buff_draw_circle(buffer_rec *buff,int x,int y,int d,UBYTE c);

This function draws a hollow circle centred on 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);

This function draws a filled circle centred on 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);

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);

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);

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);

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 coordinates.


void buff_scale_full_buff_to(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);

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 coordinates 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

void 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 file 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 sprites 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_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_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 timeslice. 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
timeslice" 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_stamp_sprite(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_stamp_sprite_color(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_stamp_sprite_buff(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 buffers 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.

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.8 for JLib
version 1.8.

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.

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.

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 JLibs 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_pcx_fp(FILE *fp);
image *image_load_jlb(char *filename);
image *image_load_jlb_fp(FILE *fp);


These 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. The
_fp versions of the functions take a file pointer as an
argument so you can read images from files that have already
been opened. You must use binary mode when opening files
suitable for reading from with these routines.

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_fp(FILE *fp,buffer_rec *buff,UBYTE
*pal); int image_save_pcx(char *filename,buffer_rec
*buff,UBYTE *pal); int image_save_pcx_fp(FILE *fp,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. The
_fp versions of the functions take a file pointer as an
argument so you can save images to files that have already
been opened. You must use binary mode when opening files
suitable for writing to with these routines.

void buff_blit_img_to(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
coordinates 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.

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 isnt 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 yet 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().

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.

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);

These functions are used in debug builds of JLib to check
the internal consistency of library types. If you are
manipulating library structures you should periodically test
them using these functions (in debug builds of your program)
to ensure you are keeping the structures consistent.
Corrupting internal data structures during run time may
cause JLib to fail unexpectedly. You should not call these
functions in production or release versions of your code
since they involve considerable overhead.

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().

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 wont 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, Im 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.


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 dont have to fluff around with
"far" pointers and all that, and we get access to heaps of
memory (If youll 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
thats the part we both care about, isnt 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.
  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.


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 using
sprites_kill_buffers().

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.

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:DJ_320x200x256, DJ_640x480x256, DJ_800x600x256
Author:                       Jonathan Griffiths and
                              Lennart Steinke Description:
DJGPP with various modes
                              through VESA 1.2 or 2.0+
Performance:                  Great with a linear frame
                              buffer.
Compiling:                    Compile with -lj on the
                              command line.
Execution:                    In theory, same as the old
                              DOS MODE_13H target. Comments:
DPMI compliant, will be
                              refined and made cleaner.
Bugs:                         Doesn't lock everything it
                              should yet.

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.
Compiling:                    You need a kernel driver to
                              use joystick support.
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: WAT_320x200x256, WAT_640x480x256, WAT_800x600x256
Author:                       Jonathan Griffiths
Description:                  Watcom C/C++ v 9+, VESA 1.2
                              & 2.0+.
Performance:                  Good, depends on VESA
                              implementation. V2.0+
Performance:                  will give excellent
                              performance.
Compiling:                    Include JLIB.LIB on the
                              command line.
Execution:                    Will run under most DPMI
                              implementations.
Comments:                     Get Univbe 5.1 plus if you
                              dont have VESA.
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 doesnt 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
x2ftp.oulu.fi                 /pub/msdos/programming/djgpp2/
sunsite.unc.edu               /pub/libs/graphucs/
ftp.simtel.net


Snail Mail
Jonathan Griffiths
82 Kowhai Rd,
Campbells Bay,
Auckland,
New Zealand.

Email
jpg@wave.co.nz

I wish you all the best in using JLib, in your projects and
life in general.

Happy Coding,

Jon Griffiths
