----------------------------------------------------------------------------
OVERVIEW:
----------------------------------------------------------------------------

Pixel Mask (PMASK) is a C library for doing pixel perfect collisions using
bitmasks.  It is intended to be extremely fast and easy to use.  This
library currently supports Allegro BITMAPs and SDL Surfaces.

This is version 4 of PMASK.
The changes from version 1 to version 2 include a change in the behavior
of init_allegro_pmask / init_sdl_pmask, 2 new functions, and some changes
to the documentation.  The functions init_allegro_pmask and init_sdl_pmask
have been modified to match the documentation (i.e. you don't need to call
init_pmask before you call those functions).  The new functions are
draw_allegro_pmask and draw_allegro_pmask_stretch.  These functions are only
enabled if Allegro support is enabled.  They draw PMASKs onto the screen in
a specified color.  Also, the first example program was added.

Changes from version 2 to version 3 include the fixing of a memory leak
in the functions create_allegro_pmask and create_sdl_pmask, and the
addition of the functions serialize_pmask, create_deserialize_pmask,
init_deserialize_pmask.  The first one is used to save a mask to a
platform-independant block of binary data, suitable for writting to disk
or transmitting over a network.  The other two functions do the reverse -
they take a block of platform-independant data produced by serialize_pmask,
and return a functioning pmask data structure instead.  

Changes from version 3 to version 4 include the addition of new higher-level
collision detection functions, and an example program demonstrating how to
use the new higher-level collision detection.  The example is test2.c. 

There are 2 example programs that come with pmask.  Both examples use
the Allegro library.  The first example, test.c, demonstrates low-level
collision detection functions.  It requires files a.bmp and b.bmp.  The
second exmple, test2.c, demonstrates higher-level collision detection
functions.  It requires the file a.dat.  


----------------------------------------------------------------------------
USAGE:
----------------------------------------------------------------------------

The primary datatype this library works with is a struct named "PMASK".
This struct has 3 members, "w", "h", and "mask".  The first 2 members
are the width and height of the mask, the third is an array of binary
data used internally by the library.  Each "PMASK" struct is effectively
a "w" by "h" bitmap with only 2 possible colors (1 bit per pixel).  

Suppose you have 2 Allegro BITMAPs named "bmp1" and "bmp2", and you want to
do pixel-perfect collisions for these bitmaps using the PMASK library.  You
start by creating masks for each sprite.  There are 2 different ways to do
this.

Method 1: Using Create
        //create masks
        struct PMASK *mask1, *mask2;
        mask1 = create_allegro_pmask(bmp1);
        mask2 = create_allegro_pmask(bmp2);
        //use the masks for a while
        blah, blah, blah...
        //delete masks
        destroy_pmask(mask1);
        destroy_pmask(mask2);
Method 2: Using Init
        //create masks
        struct PMASK mask1, mask2;
        init_allegro_pmask(&mask1, bmp1);
        init_allegro_pmask(&mask2, bmp2);
        //use the masks for a while
        blah, blah, blah...
        //delete masks
        deinit_pmask(&mask1);
        deinit_pmask(&mask2);

(needless to say, this is for Allegro BITMAPs... is you prefer SDL
Surfaces, replace "allegro" with "sdl")

Now you know how to get your masks, and how to get rid of them.  The main
thing left is, how do you use them?  Lets say you're drawing "bmp1" on the
screen at 10,10 and "bmp2" at 20,15.  Then you check to see if they're
colliding like this:
        if (check_pmask_collision(mask1, mask2, 10,10, 20,15)) {
                //they collided.  do something
        }
        else {
                //they didn't collide.  do something else
        }

----------------------------------------------------------------------------
USAGE, PART 2:
----------------------------------------------------------------------------

In order to use PMASK, you have to have to do three things:
1.  Compile pmask.c
2.  "include" the file pmask.h
3.  Link with the compiled version of pmask

Steps 1 and 3 are compiler-dependant.  Step 1 only needs to be done once,
whereas steps 2 and 3 need to be done for every program you write that
uses PMASK.

Step 2 is done by adding a line that looks like either this:
#include "pmask.h"
or this:
#include <pmask.h>
at the top of your source code.  The first one is used if you put
pmask.h in the same directory as your source code.  The second
is used if you put pmask.h in a standard include directory.  A
typical standard include directory for DJGPP (gcc/DOS) would be
c:\djgpp\include.  A typical standard include directory for Visual
C++ 6.0 would be c:\Program Files\Microsoft Visual Studios\VC98\include.
The location of the standard include directory(ies) will vary depending
upon your compiler and installation options.

Steps 1 & 3 are closely related.  You can either compile & link with
PMASK as if it were part of your program, or you can compile & link
with it as a library.  To compile and link with it as part of your
program from most IDEs, just add it to your projects list of source
files.  For example, in Visual C++ you would select the "Projects"
menu, the "add to project" sub-menu, the "files" options.  Then you
would select the file "pmask.c" and click "Okay".  Once pmask.c is in
your project, your IDE should automatically make sure that pmask.c
gets compiled and linked.
(er... IDE stands for Integrated Development Environment... basically,
it's a program like Visual Studios or Dev-C++ or RHIDE or somesuch
that makes it easier to use your compiler, linker, and debuggers)

----------------------------------------------------------------------------
PORTABILITY & PLATFORMS:
----------------------------------------------------------------------------

This library is written in plain C, and should work on all compilers.
It should work on machines irregardless of their pointer sizes, integer
sizes, and endianness.  This is all hypothetical: it's only been tested
on x86 using MS VC++ and DJGPP (gcc/DOS).

If used on a 64-bit compiler, you may have to modify pmask.h slightly,
by either changing MASK_WORD_TYPE from "unsigned long int" to
"unsigned int", or by changing MASK_WORD_BITBITS from 5 to 6.  If you do
not do this, the library should fail to compile, producing an error
message about __compile_time_assert_.  

By default, Allegro support is enabled and SDL support is disabled (SDL
support is untested, but compiles fine).  

----------------------------------------------------------------------------
PERFORMANCE TWEAKING:
----------------------------------------------------------------------------

I cannot imagine a situation in which a modern game would be limited, even
a little bit, by the speed of doing pixel-perfect collisions.  However, this
library is intended to be the fastest pixel-perfect collision library ever,
so if for some insane reason you're interested in tweaks that this library
supports, here's the information you're looking for.  

This library has 2 main settings to be adjusted for performance.  The
simpler one is the data type that it works with internally.  In the default
configuration, it uses 32-bit words.  You can, however, alter it to use 64
bit words on most compilers.  This is a compile-time setting, and cannot be
modified at run-time.  If you change it to using 64-bit words, it MAY run
faster, depending upon how smart the compiler is and what the target
instruction set is.  Be warned, however, that using larger word sizes
internal may slightly increase memory usage, particularly for extremely
small sprites, since the number of data elements used is rounded up to an
integer value at the end of every row.  On x86, it might be able to go
faster if the compiler knows how to use MMX registers for 64-bit integers
(we only ever do shifts, bit-wise ands, and bit-wise ors, so MMX registers
can be used efficiently, I think).  On other platforms, it's unlikely to go
faster that way unless they have 64-bit General Purpose Registers.  You
modify it by changing the "#define MASK_WORD_TYPE unsigned long int" in
pmask.h.  You also have to update the #define after it, MASK_WORD_BITBITS,
or otherwise it won't be able to figure out exactly what size the type is,
and will refuse to compile.  

The second adjustable performance setting is more complicated, even though
it has only 2 states: on and off.  There is a #define in pmask.h that is
commented out, called MASK_SINGLE_MEMORY_BLOCK.  If you uncomment it, then
PMASK will change the way it allocates memory and the way it lays out the
structs.  This will probably speed up masks, IF you create your masks using
calls to create_allegro_pmask or create_sdl_pmask or create_pmask.  
However, this will completely break functions like init_allegro_mask,
init_sdl_mask, and init_mask.  Those functions will do terrible evil things
that will crash your program if you call them with the
MASK_SINGLE_MEMORY_BLOCK option enabled, unless you really really really
know exactly what you're doing.  Whether the create_* functions or init_*
functions are faster depends upon what exactly your program does.  

----------------------------------------------------------------------------
CREDITS:
----------------------------------------------------------------------------

PMASK was written by orz, and is loosely based upon PPCOL, which was
written by Ivan Baldo.  

----------------------------------------------------------------------------
LICENSE:
----------------------------------------------------------------------------

Use PMASK for anything you want.  Open-source, closed-source, free,
commercial, I don't mind.  I release my work upon this to the public
domain.  

orz
