\input texinfo
@setfilename allegro.inf
@settitle Allegro Manual
@setchapternewpage odd
@paragraphindent 0
@setchapternewpage off

@ifinfo
@dircategory Libraries
@direntry
* Allegro: (allegro).                 The Allegro game programming library.
@end direntry
This is the Info version of the Allegro manual

By Shawn Hargreaves
@end ifinfo

@node Top, , (dir), (dir)
@titlepage
@example
     ______   ___    ___
    /\  _  \ /\_ \  /\_ \
    \ \ \L\ \\//\ \ \//\ \      __     __   _ __   ___ 
     \ \  __ \ \ \ \  \ \ \   /'__`\ /'_ `\/\`'__\/ __`\
      \ \ \/\ \ \_\ \_ \_\ \_/\  __//\ \L\ \ \ \//\ \L\ \
       \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
        \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
                                       /\____/
                                       \_/__/     Version 4.2.2


                A game programming library.

             By Shawn Hargreaves, Jul 22, 2007.

                See the AUTHORS file for a
               complete list of contributors.
@end example



#include <std_disclaimer.h>

"I do not accept responsibility for any effects, adverse or otherwise, 
that this code may have on you, your computer, your sanity, your dog, 
and anything else that you can think of. Use it at your own risk."

@end titlepage
@ifinfo
@example
     ______   ___    ___
    /\  _  \ /\_ \  /\_ \
    \ \ \L\ \\//\ \ \//\ \      __     __   _ __   ___ 
     \ \  __ \ \ \ \  \ \ \   /'__`\ /'_ `\/\`'__\/ __`\
      \ \ \/\ \ \_\ \_ \_\ \_/\  __//\ \L\ \ \ \//\ \L\ \
       \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
        \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
                                       /\____/
                                       \_/__/     Version 4.2.2


                A game programming library.

             By Shawn Hargreaves, Jul 22, 2007.

                See the AUTHORS file for a
               complete list of contributors.
@end example



#include <std_disclaimer.h>

"I do not accept responsibility for any effects, adverse or otherwise, 
that this code may have on you, your computer, your sanity, your dog, 
and anything else that you can think of. Use it at your own risk."

@end ifinfo



@menu
* API::                     API
* Platform::                Platform specifics
* Miscellaneous::           Miscellaneous
* Tools::                   Tools
* Community::               Community
* Conclusion::              Conclusion
* Index::                   Index
@end menu



@node API, Using, , Top
@chapter API
@menu
* Using::                   Using Allegro
* Structures::              Structures and types defined by Allegro
* Unicode::                 Unicode routines
* Configuration::           Configuration routines
* Mouse::                   Mouse routines
* Timer::                   Timer routines
* Keyboard::                Keyboard routines
* Joystick::                Joystick routines
* Graphics::                Graphics modes
* Bitmap::                  Bitmap objects
* Loading::                 Loading image files
* Palette::                 Palette routines
* Truecolor::               Truecolor pixel formats
* Drawing::                 Drawing primitives
* Blitting::                Blitting and sprites
* RLE::                     RLE sprites
* Compiled::                Compiled sprites
* Fonts::                   Fonts
* Text::                    Text output
* Polygon::                 Polygon rendering
* Transparency::            Transparency and patterned drawing
* Converting::              Converting between color formats
* Direct::                  Direct access to video memory
* FLIC::                    FLIC routines
* Sound::                   Sound init routines
* Mixer::                   Mixer routines
* Digital::                 Digital sample routines
* Music::                   Music routines (MIDI)
* Audio::                   Audio stream routines
* Recording::               Recording routines
* File::                    File and compression routines
* Datafile::                Datafile routines
* Fixed::                   Fixed point math routines
* 3D::                      3D math routines
* Quaternion::              Quaternion math routines
* GUI::                     GUI routines
@end menu
@node Using, Structures, API, API
@section Using Allegro

See readme.txt for a general introduction, copyright details, and 
information about how to install Allegro and link your program with it.

@menu
* install_allegro::
* allegro_init::
* allegro_exit::
* END_OF_MAIN::
* allegro_id::
* allegro_error::
* ALLEGRO_VERSION::
* ALLEGRO_SUB_VERSION::
* ALLEGRO_WIP_VERSION::
* ALLEGRO_VERSION_STR::
* ALLEGRO_DATE_STR::
* ALLEGRO_DATE::
* AL_ID::
* MAKE_VERSION::
* os_type::
* os_version::
* os_multitasking::
* allegro_message::
* set_window_title::
* set_close_button_callback::
* desktop_color_depth::
* get_desktop_resolution::
* check_cpu::
* cpu_vendor::
* cpu_family::
* cpu_model::
* cpu_capabilities::
@end menu
@node install_allegro, allegro_init, , Using
@subsection install_allegro
@ftable @asis
@item @t{int install_allegro(int system_id, int *errno_ptr, int (*atexit_ptr)());}
Initialises the Allegro library. You must call either this or 
allegro_init() before doing anything other than using the Unicode 
routines. If you want to use a text mode other than UTF-8, you can set
it with set_uformat() before you call this. The other functions that can
be called before this one will be marked explicitly in the documentation,
like set_config_file().

The available system ID codes will vary from one platform to another, but
you will almost always want to pass SYSTEM_AUTODETECT. Alternatively,
SYSTEM_NONE installs a stripped down version of Allegro that won't even
try to touch your hardware or do anything platform specific: this can be
useful for situations where you only want to manipulate memory bitmaps,
such as the text mode datafile tools or the Windows GDI interfacing
functions.

The `errno_ptr' and `atexit_ptr' parameters should point to the errno
variable and atexit function from your libc: these are required because
when Allegro is linked as a DLL, it doesn't have direct access to your
local libc data. `atexit_ptr' may be NULL, in which case it is your
responsibility to call allegro_exit() manually. Example:
@example

install_allegro(SYSTEM_AUTODETECT, &errno, atexit);@end example


This function returns zero on success and non-zero on failure (e.g. no
system driver could be used). Note: in previous versions of Allegro this
function would abort on error.

@end ftable
See also:@*
@xref{allegro_init}.@*
@xref{allegro_exit}.@*
@xref{set_uformat}.@*
@xref{set_config_file}.@*
@node allegro_init, allegro_exit, install_allegro, Using
@subsection allegro_init
@ftable @asis
@item @t{int allegro_init();}
Macro which initialises the Allegro library. This is the same thing as
calling install_allegro(SYSTEM_AUTODETECT, &errno, atexit).

@end ftable
See also:@*
@xref{install_allegro}.@*
@xref{allegro_exit}.@*
@xref{Available, Available Allegro examples}.@*
@node allegro_exit, END_OF_MAIN, allegro_init, Using
@subsection allegro_exit
@ftable @asis
@item @t{void allegro_exit();}
Closes down the Allegro system. This includes returning the system to
text mode and removing whatever mouse, keyboard, and timer routines have
been installed. You don't normally need to bother making an explicit call
to this function, because allegro_init() installs it as an atexit()
routine so it will be called automatically when your program exits.

Note that after you call this function, other functions like
destroy_bitmap() will most likely crash. This is a problem for C++ global
destructors, which usually get called after atexit(), so don't put Allegro
calls in them. You can write the destructor code in another method which
you can manually call before your program exits, avoiding this problem.

@end ftable
See also:@*
@xref{install_allegro}.@*
@xref{allegro_init}.@*
@xref{destroy_bitmap}.@*
@xref{ex3d}.@*
@xref{exscn3d}.@*
@xref{exswitch}.@*
@xref{exxfade}.@*
@xref{exzbuf}.@*
@node END_OF_MAIN, allegro_id, allegro_exit, Using
@subsection END_OF_MAIN
@ftable @asis
@item @t{Macro END_OF_MAIN()}
In order to maintain cross-platform compatibility, you have to put this
macro at the very end of your main function. This macro uses some `magic'
to mangle your main procedure on platforms that need it like Windows,
some flavours of UNIX or MacOS X. On the other platforms this macro 
compiles to nothing, so you don't have to #ifdef around it. Example:
@example

int main(void)
@{
   allegro_init();
   /* more stuff goes here */
   ...
   return 0;
@}
END_OF_MAIN()@end example


@end ftable
See also:@*
@xref{Windows, Windows specifics}.@*
@xref{Unix, Unix specifics}.@*
@xref{MacOS, MacOS X specifics}.@*
@xref{Differences, Differences between platforms}.@*
@xref{Available, Available Allegro examples}.@*
@node allegro_id, allegro_error, END_OF_MAIN, Using
@subsection allegro_id
@ftable @asis
@item @t{extern char allegro_id[];}
Text string containing a date and version number for the library, in case 
you want to display these somewhere.

@end ftable
@node allegro_error, ALLEGRO_VERSION, allegro_id, Using
@subsection allegro_error
@ftable @asis
@item @t{extern char allegro_error[ALLEGRO_ERROR_SIZE];}
Text string used by set_gfx_mode(), install_sound() and other functions to
report error messages. If they fail and you want to tell the user why, this
is the place to look for a description of the problem. Example:
@example

void abort_on_error(const char *message)
@{
   if (screen != NULL)
      set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);

   allegro_message("%s.\nLast Allegro error `%s'\n",
                   message, allegro_error);
   exit(-1);
@}
...
   if (some_allegro_function() == ERROR_CODE)
      abort_on_error("Error calling some function!");@end example

@end ftable
See also:@*
@xref{set_gfx_mode}.@*
@xref{install_sound}.@*
@xref{Available, Available Allegro examples}.@*
@node ALLEGRO_VERSION, ALLEGRO_SUB_VERSION, allegro_error, Using
@subsection ALLEGRO_VERSION
@ftable @asis
@item @t{#define ALLEGRO_VERSION}
Defined to the major version of Allegro. From a version number like
4.1.16, this would be defined to the integer 4.

@end ftable
@node ALLEGRO_SUB_VERSION, ALLEGRO_WIP_VERSION, ALLEGRO_VERSION, Using
@subsection ALLEGRO_SUB_VERSION
@ftable @asis
@item @t{#define ALLEGRO_SUB_VERSION}
Defined to the middle version of Allegro. From a version number like
4.1.16, this would be defined to the integer 1.

@end ftable
@node ALLEGRO_WIP_VERSION, ALLEGRO_VERSION_STR, ALLEGRO_SUB_VERSION, Using
@subsection ALLEGRO_WIP_VERSION
@ftable @asis
@item @t{#define ALLEGRO_WIP_VERSION}
Defined to the minor version of Allegro. From a version number like
4.1.16, this would be defined to the integer 16.

@end ftable
@node ALLEGRO_VERSION_STR, ALLEGRO_DATE_STR, ALLEGRO_WIP_VERSION, Using
@subsection ALLEGRO_VERSION_STR
@ftable @asis
@item @t{#define ALLEGRO_VERSION_STR}
Defined to a text string containing all version numbers and maybe some
additional text. This could be `4.2.1 (SVN)' for an Allegro version
obtained straight from the SVN repository.

@end ftable
@node ALLEGRO_DATE_STR, ALLEGRO_DATE, ALLEGRO_VERSION_STR, Using
@subsection ALLEGRO_DATE_STR
@ftable @asis
@item @t{#define ALLEGRO_DATE_STR}
Defined to a text string containing the year this version of Allegro was
released, like `2004'.

@end ftable
@node ALLEGRO_DATE, AL_ID, ALLEGRO_DATE_STR, Using
@subsection ALLEGRO_DATE
@ftable @asis
@item @t{#define ALLEGRO_DATE}
Defined to an integer containing the release date of Allegro in the packed
format `yyyymmdd'. Example:
@example

const int year = ALLEGRO_DATE / 10000;
const int month = (ALLEGRO_DATE / 100) % 100;
const int day = ALLEGRO_DATE % 100;

allegro_message("Year %d, month %d, day %d\n",
   year, month, day);@end example


@end ftable
@node AL_ID, MAKE_VERSION, ALLEGRO_DATE, Using
@subsection AL_ID
@ftable @asis
@item @t{Macro AL_ID(a,b,c,d)}
This macro can be used to create a packed 32 bit integer from 8 bit
characters, on both 32 and 64 bit machines. These can be used for various 
things, like custom datafile objects or system IDs. Example:
@example

#define OSTYPE_LINUX       AL_ID('T','U','X',' ')@end example


@end ftable
See also:@*
@xref{DAT_ID}.@*
@node MAKE_VERSION, os_type, AL_ID, Using
@subsection MAKE_VERSION
@ftable @asis
@item @t{Macro MAKE_VERSION(a, b, c)}
This macro can be used to check if some Allegro version is (binary)
compatible with the current version. It is safe to use > and < to
check if one version is more recent than another.
The third number is ignored if the second number is even, so
MAKE_VERSION(4, 2, 0) is equivalent to MAKE_VERSION(4, 2, 1).
This is because of our version numbering policy since 4.0.0:
the second number is even for stable releases, which must be
ABI-compatible with earlier versions of the same series.
This macro is mainly useful for addon packages and libraries. See the 
`ABI compatibility information' section of the manual for more detailed 
information. Example:
@example

/* Check if the current version is compatible with Allegro 4.2.0 */
#if (MAKE_VERSION(4, 2, 0) <= MAKE_VERSION(ALLEGRO_VERSION, \
                   ALLEGRO_SUB_VERSION, ALLEGRO_WIP_VERSION))
   /* Allegro 4.2.0 compatibility */
#else
   /* Work-around */
#endif@end example


@end ftable
See also:@*
@xref{ALLEGRO_VERSION}.@*
@xref{ALLEGRO_SUB_VERSION}.@*
@xref{ALLEGRO_WIP_VERSION}.@*
@node os_type, os_version, MAKE_VERSION, Using
@subsection os_type
@ftable @asis
@item @t{extern int os_type;}
Set by allegro_init() to one of the values:
@example

OSTYPE_UNKNOWN    - unknown, or regular MSDOS
OSTYPE_WIN3       - Windows 3.1 or earlier
OSTYPE_WIN95      - Windows 95
OSTYPE_WIN98      - Windows 98
OSTYPE_WINME      - Windows ME
OSTYPE_WINNT      - Windows NT
OSTYPE_WIN2000    - Windows 2000
OSTYPE_WINXP      - Windows XP
OSTYPE_WIN2003    - Windows 2003
OSTYPE_WINVISTA   - Windows Vista
OSTYPE_OS2        - OS/2
OSTYPE_WARP       - OS/2 Warp 3
OSTYPE_DOSEMU     - Linux DOSEMU
OSTYPE_OPENDOS    - Caldera OpenDOS
OSTYPE_LINUX      - Linux
OSTYPE_SUNOS      - SunOS/Solaris
OSTYPE_FREEBSD    - FreeBSD
OSTYPE_NETBSD     - NetBSD
OSTYPE_IRIX       - IRIX
OSTYPE_DARWIN     - Darwin
OSTYPE_QNX        - QNX
OSTYPE_UNIX       - Unknown Unix variant
OSTYPE_BEOS       - BeOS
OSTYPE_MACOS      - MacOS
OSTYPE_MACOSX     - MacOS X@end example


@end ftable
See also:@*
@xref{allegro_init}.@*
@xref{os_version}.@*
@xref{os_multitasking}.@*
@node os_version, os_multitasking, os_type, Using
@subsection os_version
@ftable @asis
@item @t{extern int os_version;}
@end ftable
@ftable @asis
@item @t{extern int os_revision;}
The major and minor version of the Operating System currently running.
Set by allegro_init(). If Allegro for some reason was not able to
retrieve the version of the Operating System, os_version and
os_revision will be set to -1. For example: Under Win98 SE (v4.10.2222)
os_version will be set to 4 and os_revision to 10.

@end ftable
See also:@*
@xref{os_type}.@*
@xref{os_multitasking}.@*
@node os_multitasking, allegro_message, os_version, Using
@subsection os_multitasking
@ftable @asis
@item @t{extern int os_multitasking;}
Set by allegro_init() to either TRUE or FALSE depending on whether your
Operating System is multitasking or not.

@end ftable
See also:@*
@xref{os_type}.@*
@xref{os_version}.@*
@node allegro_message, set_window_title, os_multitasking, Using
@subsection allegro_message
@ftable @asis
@item @t{void allegro_message(const char *text_format, ...);}
Outputs a message, using a printf() format string. Usually you want to
use this to report messages to the user in an OS independent way when some
Allegro subsystem cannot be initialised. But you must not use this function
if you are in a graphic mode, only before calling set_gfx_mode(), or after
a set_gfx_mode(GFX_TEXT). Also, this function depends on a system driver
being installed, which means that it won't display the message at all on
some platforms if Allegro has not been initialised correctly.

On platforms featuring a windowing system, it will bring up a blocking GUI
message box. If there is no windowing system, it will try to print the
string to a text console, attempting to work around codepage differences
by reducing any accented characters to 7-bit ASCII approximations.
Example:
@example

if (allegro_init() != 0)
   exit(1);

if (init_my_data() != 0) @{
   allegro_message("Sorry, missing game data!\n");
   exit(2);
@}@end example


@end ftable
See also:@*
@xref{allegro_init}.@*
@xref{install_allegro}.@*
@xref{set_uformat}.@*
@xref{Available, Available Allegro examples}.@*
@node set_window_title, set_close_button_callback, allegro_message, Using
@subsection set_window_title
@ftable @asis
@item @t{void set_window_title(const char *name);}
On platforms that are capable of it, this routine alters the window title 
for your Allegro program. Note that Allegro cannot set the window title 
when running in a DOS box under Windows. Example:
@example

set_window_title("Allegro rules!");@end example


@end ftable
See also:@*
@xref{set_close_button_callback}.@*
@xref{set_uformat}.@*
@xref{exunicod}.@*
@node set_close_button_callback, desktop_color_depth, set_window_title, Using
@subsection set_close_button_callback
@ftable @asis
@item @t{int set_close_button_callback(void (*proc)(void));}
On platforms that have a close button, this routine installs a callback 
function to handle the close event. In other words, when the user clicks 
the close button on your program's window or any equivalent device, the
function you specify here will be called.

This function should not generally attempt to exit the program or save 
any data itself. The function could be called at any time, and there is 
usually a risk of conflict with the main thread of the program. Instead, 
you should set a flag during this function, and test it on a regular 
basis in the main loop of the program.

Pass NULL as the `proc' argument to this function to disable the close
button functionality, which is the default state.

Note that Allegro cannot intercept the close button of a DOS box in 
Windows.

Also note that the supplied callback is also called under MacOS X when
the user hits Command-Q or selects "Quit" from the application menu.
Example:
@example

volatile int close_button_pressed = FALSE;

void close_button_handler(void)
@{
   close_button_pressed = TRUE;
@}
END_OF_FUNCTION(close_button_handler)
...

allegro_init();
LOCK_FUNCTION(close_button_handler);
set_close_button_callback(close_button_handler);
...
   
while (!close_button_pressed)
   do_stuff();@end example


Returns zero on success and non-zero on failure (e.g. the feature is not
supported by the platform).

@end ftable
See also:@*
@xref{set_window_title}.@*
@node desktop_color_depth, get_desktop_resolution, set_close_button_callback, Using
@subsection desktop_color_depth
@ftable @asis
@item @t{int desktop_color_depth();}
Finds out the currently selected desktop color depth. You can use this
information to make your program use the same color depth as the desktop,
which will likely make it run faster because the graphic driver won't be
doing unnecessary color conversions behind your back.

Under some OSes, switching to a full screen graphics mode may automatically
change the desktop color depth. You have, therefore, to call this function
before setting any graphics mode in order to retrieve the real desktop
color depth. Example:
@example

allegro_init();
...
if ((depth = desktop_color_depth()) != 0) @{
   set_color_depth(depth);
@}@end example


Returns the color depth or zero on platforms where this information is not
available or does not apply.

@end ftable
See also:@*
@xref{get_desktop_resolution}.@*
@xref{set_color_depth}.@*
@xref{set_gfx_mode}.@*
@node get_desktop_resolution, check_cpu, desktop_color_depth, Using
@subsection get_desktop_resolution
@ftable @asis
@item @t{int get_desktop_resolution(int *width, int *height);}
Finds out the currently selected desktop resolution. You can use this
information to avoid creating windows bigger than the current resolution.
This is especially important for some windowed drivers which are unable
to create windows bigger than the desktop. Each parameter is a pointer
to an integer where one dimension of the screen will be stored.

Under some OSes, switching to a full screen graphics mode may automatically
change the desktop resolution. You have, therefore, to call this function
before setting any graphics mode in order to retrieve the real desktop
resolution. Example:
@example

int width, height;

allegro_init();
...
if (get_desktop_resolution(&width, &height) == 0) @{
   /* Got the resolution correctly */
@}@end example


Returns zero on success, or a negative number if this information is not
available or does not apply, in which case the values stored in the
variables you provided for `width' and `height' are undefined.

@end ftable
See also:@*
@xref{desktop_color_depth}.@*
@xref{set_gfx_mode}.@*
@node check_cpu, cpu_vendor, get_desktop_resolution, Using
@subsection check_cpu
@ftable @asis
@item @t{void check_cpu();}
Detects the CPU type, setting the following global variables. You don't 
normally need to call this, because allegro_init() will do it for you.

@end ftable
See also:@*
@xref{cpu_vendor}.@*
@xref{cpu_family}.@*
@xref{cpu_model}.@*
@xref{cpu_capabilities}.@*
@xref{allegro_init}.@*
@node cpu_vendor, cpu_family, check_cpu, Using
@subsection cpu_vendor
@ftable @asis
@item @t{extern char cpu_vendor[];}
On Intel PCs, contains the CPU vendor name if known. On Mac OSX systems 
this contains the PPC subtype name. On other platforms, this may be an empty
string. You can read this variable after you have called check_cpu()
(which is automatically called by allegro_init()).

@end ftable
See also:@*
@xref{check_cpu}.@*
@xref{cpu_family}.@*
@xref{cpu_model}.@*
@xref{cpu_capabilities}.@*
@xref{allegro_init}.@*
@node cpu_family, cpu_model, cpu_vendor, Using
@subsection cpu_family
@ftable @asis
@item @t{extern int cpu_family;}
Contains the Intel type, where applicable. Allegro defines the following
CPU family types:
@example

CPU_FAMILY_UNKNOWN  - The type of processor is unknown
CPU_FAMILY_I386     - The processor is an Intel-compatible 386
CPU_FAMILY_I486     - The processor is an Intel-compatible 486
CPU_FAMILY_I586     - The processor is a Pentium or equivalent
CPU_FAMILY_I686     - The processor is a Pentium Pro, II, III
                      or equivalent
CPU_FAMILY_ITANIUM  - The processor is an Itanium processor
CPU_FAMILY_POWERPC  - The processor is a PowerPC processor
CPU_FAMILY_EXTENDED - The processor type needs to be read
                      from the cpu_model
@end example

You can read this variable after you have called check_cpu()
(which is automatically called by allegro_init()).

@end ftable
See also:@*
@xref{check_cpu}.@*
@xref{cpu_vendor}.@*
@xref{cpu_model}.@*
@xref{cpu_capabilities}.@*
@xref{allegro_init}.@*
@node cpu_model, cpu_capabilities, cpu_family, Using
@subsection cpu_model
@ftable @asis
@item @t{extern int cpu_model;}
Contains the CPU submodel, where applicable. Allegro defines at least the 
following CPU family types (see include/allegro/system.h for a more 
complete list):
@example

CPU_FAMILY_I586:
   CPU_MODEL_PENTIUM, CPU_MODEL_K5, CPU_MODEL_K6

CPU_FAMILY_I686:
   CPU_MODEL_PENTIUMPRO, CPU_MODEL_PENTIUMII,
   CPU_MODEL_PENTIUMIIIKATMAI, CPU_MODEL_PENTIUMIIICOPPERMINE,
   CPU_MODEL_ATHLON, CPU_MODEL_DURON

CPU_FAMILY_EXTENDED:
   CPU_MODEL_PENTIUMIV, CPU_MODEL_XEON,
   CPU_MODEL_ATHLON64, CPU_MODEL_OPTERON

CPU_FAMILY_POWERPC:
   CPU_MODEL_POWERPC_x, for x=601-604, 620, 750, 7400, 7450
@end example

You can read this variable after you have called check_cpu() (which is 
automatically called by allegro_init()). Make sure you check the cpu_family
and cpu_vendor so you know which models make sense to check.

@end ftable
See also:@*
@xref{check_cpu}.@*
@xref{cpu_vendor}.@*
@xref{cpu_family}.@*
@xref{cpu_capabilities}.@*
@xref{allegro_init}.@*
@node cpu_capabilities, fixed, cpu_model, Using
@subsection cpu_capabilities
@ftable @asis
@item @t{extern int cpu_capabilities;}
Contains CPU flags indicating what features are available on the current 
CPU. The flags can be any combination of these:
@example

CPU_ID       - Indicates that the "cpuid" instruction is
               available. If this is set, then all Allegro CPU
               variables are 100% reliable, otherwise there
               may be some mistakes.
CPU_FPU      - An FPU is available.
CPU_IA64     - Running on Intel 64 bit CPU
CPU_AMD64    - Running on AMD 64 bit CPU
CPU_MMX      - Intel MMX  instruction set is available.
CPU_MMXPLUS  - Intel MMX+ instruction set is available.
CPU_SSE      - Intel SSE  instruction set is available.
CPU_SSE2     - Intel SSE2 instruction set is available.
CPU_SSE3     - Intel SSE3 instruction set is available.
CPU_3DNOW    - AMD 3DNow! instruction set is available.
CPU_ENH3DNOW - AMD Enhanced 3DNow! instruction set is
               available.
CPU_CMOV     - Pentium Pro "cmov" instruction is available.
@end example

You can check for multiple features by OR-ing the flags together.
For example, to check if the CPU has an FPU and MMX instructions
available, you'd do:
@example

if ((cpu_capabilities & (CPU_FPU | CPU_MMX)) ==
    (CPU_FPU | CPU_MMX)) @{
   printf("CPU has both an FPU and MMX instructions!\n");
@}
@end example

You can read this variable after you have called check_cpu() (which is
automatically called by allegro_init()).



@end ftable
See also:@*
@xref{check_cpu}.@*
@xref{cpu_vendor}.@*
@xref{cpu_family}.@*
@xref{cpu_model}.@*
@xref{cpu_capabilities}.@*
@xref{allegro_init}.@*
@node Structures, Unicode, Using, API
@section Structures and types defined by Allegro

There are several structures and types defined by Allegro which are used
in many functions (like the BITMAP structure). This section of the manual
describes their useful content from a user point of view when they don't fit
very well any of the existing manual sections, and redirects you to the
appropriate section when it's already described there. Note that unless stated
otherwise, the contents shown here are just for read only purposes, there
might be other internal flags, but you shouldn't depend on them being
available in past/future versions of Allegro.

@menu
* fixed::
* BITMAP::
* RLE_SPRITE::
* COMPILED_SPRITE::
* JOYSTICK_INFO::
* JOYSTICK_BUTTON_INFO::
* JOYSTICK_STICK_INFO::
* JOYSTICK_AXIS_INFO::
* GFX_MODE_LIST::
* GFX_MODE::
* PAL_SIZE::
* PALETTE::
* RGB::
* V3D::
* V3D_f::
* COLOR_MAP::
* RGB_MAP::
* al_ffblk::
* DATAFILE::
* MATRIX::
* MATRIX_f::
* QUAT::
* DIALOG::
* MENU::
* DIALOG_PLAYER::
* MENU_PLAYER::
* FONT::
* ZBUFFER::
* SAMPLE::
* MIDI::
* AUDIOSTREAM::
* PACKFILE::
* PACKFILE_VTABLE::
* LZSS_PACK_DATA::
* LZSS_UNPACK_DATA::
@end menu
@node fixed, BITMAP, cpu_capabilities, Structures
@subsection fixed
@ftable @asis
@item @t{typedef long fixed}
This is a fixed point integer which can replace float with similar results
and is faster than float on low end machines. Read chapter "Fixed point
math routines" for the full explanation.

@end ftable
See also:@*
@xref{Fixed, Fixed point math routines}.@*
@xref{ex12bit}.@*
@xref{ex3buf}.@*
@xref{ex3d}.@*
@xref{excustom}.@*
@xref{exfixed}.@*
@xref{exspline}.@*
@xref{exsprite}.@*
@xref{exstars}.@*
@xref{exupdate}.@*
@node BITMAP, RLE_SPRITE, fixed, Structures
@subsection BITMAP
@ftable @asis
@item @t{typedef struct BITMAP}
@example

int w, h;               - size of the bitmap in pixels
int clip;               - non-zero if clipping is turned on
int cl, cr, ct, cb;     - clip rectangle left, right, top,
                          and bottom
unsigned char *line[];  - pointers to the start of each line
@end example

There is some other stuff in the structure as well, but it is liable to
change and you shouldn't use anything except the above. The `w' and `h'
fields can be used to obtain the size of an existing bitmap:
@example

bmp = load_bitmap("file.bmp", pal);
allegro_message("Bitmap size: (%dx%d)\n", bmp->w, bmp->h);
@end example

The clipping rectangle is inclusive on the left and top (0 allows drawing
to position 0) but exclusive on the right and bottom (10 allows drawing
to position 9, but not to 10). Note this is not the same format as that of
the clipping API, which takes inclusive coordinates for all four corners.
All the values of this structure should be regarded as read-only, with the
exception of the line field, whose access is described in depth in the
"Direct access to video memory" section of the manual. If you want to
modify the clipping region, please refrain from changing this structure.
Use set_clip_rect() instead.

@end ftable
See also:@*
@xref{create_bitmap}.@*
@xref{set_clip_rect}.@*
@xref{bitmap_color_depth}.@*
@xref{RLE_SPRITE}.@*
@xref{COMPILED_SPRITE}.@*
@xref{Direct, Direct access to video memory}.@*
@xref{Available, Available Allegro examples}.@*
@node RLE_SPRITE, COMPILED_SPRITE, BITMAP, Structures
@subsection RLE_SPRITE
@ftable @asis
@item @t{typedef struct RLE_SPRITE}
@example

int w, h;           - width and height in pixels
int color_depth;    - color depth of the image
@end example

RLE sprites store the image in a simple run-length encoded format, where
repeated zero pixels are replaced by a single length count, and strings of
non-zero pixels are preceded by a counter giving the length of the solid
run. Read chapter "RLE sprites" for a description of the restrictions and
how to obtain/use this structure.

@end ftable
See also:@*
@xref{get_rle_sprite}.@*
@xref{BITMAP}.@*
@xref{COMPILED_SPRITE}.@*
@xref{RLE, RLE sprites}.@*
@node COMPILED_SPRITE, JOYSTICK_INFO, RLE_SPRITE, Structures
@subsection COMPILED_SPRITE
@ftable @asis
@item @t{typedef struct COMPILED_SPRITE}
@example

short planar;        - set if it's a planar (mode-X) sprite
short color_depth;   - color depth of the image
short w, h;          - size of the sprite
@end example

Compiled sprites are stored as actual machine code instructions that draw
a specific image onto a bitmap, using mov instructions with immediate data
values. Read chapter "Compiled sprites" for a description of the
restrictions and how to obtain/use this structure.

@end ftable
See also:@*
@xref{get_compiled_sprite}.@*
@xref{BITMAP}.@*
@xref{RLE_SPRITE}.@*
@xref{Compiled, Compiled sprites}.@*
@node JOYSTICK_INFO, JOYSTICK_BUTTON_INFO, COMPILED_SPRITE, Structures
@subsection JOYSTICK_INFO
@ftable @asis
@item @t{typedef struct JOYSTICK_INFO}
@example

int flags;                       - status flags for this
                                   joystick
int num_sticks;                  - how many stick inputs?
int num_buttons;                 - how many buttons?
JOYSTICK_STICK_INFO stick[n];    - stick state information
JOYSTICK_BUTTON_INFO button[n];  - button state information
@end example

Read chapter "Joystick routines" for a description on how to obtain/use
this structure.

@end ftable
See also:@*
@xref{joy}.@*
@xref{Joystick, Joystick routines}.@*
@node JOYSTICK_BUTTON_INFO, JOYSTICK_STICK_INFO, JOYSTICK_INFO, Structures
@subsection JOYSTICK_BUTTON_INFO
@ftable @asis
@item @t{typedef struct JOYSTICK_BUTTON_INFO}
@example

int b;                           - boolean on/off flag
char *name;                      - description of this
                                   button
@end example

Read chapter "Joystick routines" for a description on how to obtain/use
this structure.

@end ftable
See also:@*
@xref{joy}.@*
@xref{Joystick, Joystick routines}.@*
@node JOYSTICK_STICK_INFO, JOYSTICK_AXIS_INFO, JOYSTICK_BUTTON_INFO, Structures
@subsection JOYSTICK_STICK_INFO
@ftable @asis
@item @t{typedef struct JOYSTICK_STICK_INFO}
@example

int flags;                       - status flags for this
                                   input
int num_axis;                    - how many axes do we
                                   have? (note the misspelling)
JOYSTICK_AXIS_INFO axis[n];      - axis state information
char *name;                      - description of this
                                   input
@end example

Read chapter "Joystick routines" for a description on how to obtain/use
this structure.

@end ftable
See also:@*
@xref{joy}.@*
@xref{Joystick, Joystick routines}.@*
@node JOYSTICK_AXIS_INFO, GFX_MODE_LIST, JOYSTICK_STICK_INFO, Structures
@subsection JOYSTICK_AXIS_INFO
@ftable @asis
@item @t{typedef struct JOYSTICK_AXIS_INFO}
@example

int pos;                         - analogue axis position
int d1, d2;                      - digital axis position
char *name;                      - description of this axis
@end example

Read chapter "Joystick routines" for a description on how to obtain/use
this structure.

@end ftable
See also:@*
@xref{joy}.@*
@xref{Joystick, Joystick routines}.@*
@node GFX_MODE_LIST, GFX_MODE, JOYSTICK_AXIS_INFO, Structures
@subsection GFX_MODE_LIST
@ftable @asis
@item @t{typedef struct GFX_MODE_LIST}
@example

int num_modes;
GFX_MODE *mode;
@end example

Structure returned by get_gfx_mode_list, which contains an array of
GFX_MODE structures.

@end ftable
See also:@*
@xref{GFX_MODE}.@*
@xref{get_gfx_mode_list}.@*
@node GFX_MODE, PAL_SIZE, GFX_MODE_LIST, Structures
@subsection GFX_MODE
@ftable @asis
@item @t{typedef struct GFX_MODE}
@example

int width, height, bpp;
@end example

Structure contained in GFX_MODE_LIST.

@end ftable
See also:@*
@xref{GFX_MODE_LIST}.@*
@xref{get_gfx_mode_list}.@*
@node PAL_SIZE, PALETTE, GFX_MODE, Structures
@subsection PAL_SIZE
@ftable @asis
@item @t{#define PAL_SIZE}
Preprocessor constant equal to 256.

@end ftable
See also:@*
@xref{RGB}.@*
@xref{PALETTE}.@*
@xref{COLOR_MAP}.@*
@node PALETTE, RGB, PAL_SIZE, Structures
@subsection PALETTE
@ftable @asis
@item @t{typedef PALETTE RGB[PAL_SIZE]}
Allegro palettes are arrays of PAL_SIZE RGB entries.

@end ftable
See also:@*
@xref{RGB}.@*
@xref{Palette, Palette routines}.@*
@xref{Available, Available Allegro examples}.@*
@node RGB, V3D, PALETTE, Structures
@subsection RGB
@ftable @asis
@item @t{typedef struct RGB}
@example

unsigned char r, g, b;
@end example

Palette entry. It contains an additional field for the purpose of padding
but you should not usually care about it. Read chapter "Palette routines"
for a description on how to obtain/use this structure.

@end ftable
See also:@*
@xref{Palette, Palette routines}.@*
@xref{PALETTE}.@*
@xref{ex12bit}.@*
@xref{ex3d}.@*
@xref{excolmap}.@*
@xref{exconfig}.@*
@xref{expal}.@*
@xref{exrgbhsv}.@*
@xref{exscroll}.@*
@xref{exshade}.@*
@xref{extrans}.@*
@xref{extruec}.@*
@node V3D, V3D_f, RGB, Structures
@subsection V3D
@ftable @asis
@item @t{typedef struct V3D}
@example

fixed x, y, z;       - position
fixed u, v;          - texture map coordinates
int c;               - color
@end example

A vertex structure used by polygon3d and other polygon rendering
functions. Read the description of polygon3d() for a description on how
to obtain/use this structure.

@end ftable
See also:@*
@xref{V3D_f}.@*
@xref{polygon3d}.@*
@xref{Fixed point trig}.@*
@xref{ex3d}.@*
@node V3D_f, COLOR_MAP, V3D, Structures
@subsection V3D_f
@ftable @asis
@item @t{typedef struct V3D_f}
@example

float x, y, z;       - position
float u, v;          - texture map coordinates
int c;               - color
@end example

Like V3D but using float values instead of fixed ones. Read the
description of polygon3d_f() for a description on how to obtain/use this
structure.

@end ftable
See also:@*
@xref{V3D}.@*
@xref{polygon3d, polygon3d_f}.@*
@xref{Fixed point trig}.@*
@xref{excamera}.@*
@xref{exscn3d}.@*
@xref{exzbuf}.@*
@node COLOR_MAP, RGB_MAP, V3D_f, Structures
@subsection COLOR_MAP
@ftable @asis
@item @t{typedef struct COLOR_MAP}
@example

unsigned char data[PAL_SIZE][PAL_SIZE];
@end example

Read chapter "Transparency and patterned drawing", section "256-color
transparency" for a description on how to obtain/use this structure.

@end ftable
See also:@*
@xref{256-color transparency}.@*
@xref{color_map}.@*
@xref{ex3d}.@*
@xref{excolmap}.@*
@xref{exlights}.@*
@xref{exshade}.@*
@xref{extrans}.@*
@node RGB_MAP, al_ffblk, COLOR_MAP, Structures
@subsection RGB_MAP
@ftable @asis
@item @t{typedef struct RGB_MAP}
@example

unsigned char data[32][32][32];
@end example

Read chapter "Converting between color formats" for a description on how
to obtain/use this structure.

@end ftable
See also:@*
@xref{Converting, Converting between color formats}.@*
@xref{create_rgb_table}.@*
@xref{ex3d}.@*
@xref{excolmap}.@*
@xref{exrgbhsv}.@*
@xref{exshade}.@*
@xref{extrans}.@*
@node al_ffblk, DATAFILE, RGB_MAP, Structures
@subsection al_ffblk
@ftable @asis
@item @t{struct al_ffblk}
@example

int attrib;       - actual attributes of the file found
time_t time;      - modification time of file
char name[512];   - name of file
@end example

Read the description of al_findfirst for a description on how to
obtain/use this structure.

@end ftable
See also:@*
@xref{al_findfirst}.@*
@xref{al_ffblk_get_size}.@*
@node DATAFILE, MATRIX, al_ffblk, Structures
@subsection DATAFILE
@ftable @asis
@item @t{typedef struct DATAFILE}
@example

void *dat;     - pointer to the actual data
int type;      - type of the data
long size;     - size of the data in bytes
void *prop;    - list of object properties
@end example

Read chapter "Datafile routines", section "Using datafiles" for a
description on how to obtain/use this structure.

@end ftable
See also:@*
@xref{load_datafile}.@*
@xref{Using datafiles}.@*
@xref{excustom}.@*
@xref{exdata}.@*
@xref{exexedat}.@*
@xref{exgui}.@*
@xref{exsprite}.@*
@xref{exunicod}.@*
@node MATRIX, MATRIX_f, DATAFILE, Structures
@subsection MATRIX
@ftable @asis
@item @t{typedef struct MATRIX}
@example

fixed v[3][3];           - 3x3 scaling and rotation component
fixed t[3];              - x/y/z translation component
@end example

Fixed point matrix structure. Read chapter "3D math routines" for a
description on how to obtain/use this structure.

@end ftable
See also:@*
@xref{MATRIX_f}.@*
@xref{3D, 3D math routines}.@*
@xref{ex12bit}.@*
@xref{ex3d}.@*
@xref{exstars}.@*
@node MATRIX_f, QUAT, MATRIX, Structures
@subsection MATRIX_f
@ftable @asis
@item @t{typedef struct MATRIX_f}
@example

float v[3][3];           - 3x3 scaling and rotation component
float t[3];              - x/y/z translation component
@end example

Floating point matrix structure. Read chapter "3D math routines" for a
description on how to obtain/use this structure.

@end ftable
See also:@*
@xref{MATRIX}.@*
@xref{3D, 3D math routines}.@*
@xref{excamera}.@*
@xref{exquat}.@*
@xref{exscn3d}.@*
@xref{exzbuf}.@*
@node QUAT, DIALOG, MATRIX_f, Structures
@subsection QUAT
@ftable @asis
@item @t{typedef struct QUAT}
@example

float w, x, y, z;
@end example

Read chapter "Quaternion math routines" for a description on how to
obtain/use this structure.

@end ftable
See also:@*
@xref{Quaternion, Quaternion math routines}.@*
@xref{exquat}.@*
@node DIALOG, MENU, QUAT, Structures
@subsection DIALOG
@ftable @asis
@item @t{typedef struct DIALOG}
@example

int (*proc)(int, DIALOG *, int); - dialog procedure
                                   (message handler)
int x, y, w, h;       - position and size of the object
int fg, bg;           - foreground and background colors
int key;              - ASCII keyboard shortcut
int flags;            - flags about the status of the object
int d1, d2;           - whatever you want to use them for
void *dp, *dp2, *dp3; - pointers to more object-specific data
@end example

This is the structure which contains a GUI object. Read chapter "GUI
routines" for a description on how to obtain/use this structure.

@end ftable
See also:@*
@xref{do_dialog}.@*
@xref{GUI, GUI routines}.@*
@xref{excustom}.@*
@xref{exgui}.@*
@xref{exrgbhsv}.@*
@node MENU, DIALOG_PLAYER, DIALOG, Structures
@subsection MENU
@ftable @asis
@item @t{typedef struct MENU}
@example

char *text;          - the text to display for the menu item
int (*proc)(void);   - called when the menu item is clicked
struct MENU *child;  - nested child menu
int flags;           - disabled or checked state
void *dp;            - pointer to any data you need
@end example

Structure used to hold an entry of a menu. Read chapter "GUI routines",
section "GUI menus" for a description on how to obtain/use this structure.

@end ftable
See also:@*
@xref{do_menu}.@*
@xref{GUI menus}.@*
@xref{exgui}.@*
@node DIALOG_PLAYER, MENU_PLAYER, MENU, Structures
@subsection DIALOG_PLAYER
@ftable @asis
@item @t{typedef struct DIALOG_PLAYER}
A structure which holds GUI data used internally by Allegro. Read the
documentation of init_dialog() for a description on how to obtain/use this
structure.

@end ftable
See also:@*
@xref{init_dialog}.@*
@xref{update_dialog}.@*
@xref{shutdown_dialog}.@*
@xref{GUI, GUI routines}.@*
@node MENU_PLAYER, FONT, DIALOG_PLAYER, Structures
@subsection MENU_PLAYER
@ftable @asis
@item @t{typedef struct MENU_PLAYER}
A structure which holds GUI data used internally by Allegro. Read the
documentation of init_menu() for a description on how to obtain/use this
structure.

@end ftable
See also:@*
@xref{init_menu}.@*
@xref{update_menu}.@*
@xref{shutdown_menu}.@*
@xref{GUI menus}.@*
@node FONT, ZBUFFER, MENU_PLAYER, Structures
@subsection FONT
@ftable @asis
@item @t{typedef struct FONT}
A structure holding an Allegro font, usually created beforehand with the
grabber tool or Allegro's default font. Read chapter "Fonts" for a
description on how to load/destroy fonts, and chapter "Text output" for a
description on how to show text.

@end ftable
See also:@*
@xref{font}.@*
@xref{excustom}.@*
@xref{exfont}.@*
@xref{exunicod}.@*
@node ZBUFFER, SAMPLE, FONT, Structures
@subsection ZBUFFER
@ftable @asis
@item @t{typedef struct BITMAP ZBUFFER}
Structure used by Allegro's 3d zbuffered rendering functions. You are not
supposed to mix ZBUFFER with BITMAP even though it is currently possible
to do so. This is just an internal representation, and it may change in
the future.

@end ftable
See also:@*
@xref{Zbuffered rendering}.@*
@xref{BITMAP}.@*
@xref{exzbuf}.@*
@xref{BITMAP}.@*
@node SAMPLE, MIDI, ZBUFFER, Structures
@subsection SAMPLE
@ftable @asis
@item @t{typedef struct SAMPLE}
@example

int bits;                   - 8 or 16
int stereo;                 - sample type flag
int freq;                   - sample frequency
int priority;               - 0-255
unsigned long len;          - length (in samples)
unsigned long loop_start;   - loop start position
unsigned long loop_end;     - loop finish position
void *data;                 - raw sample data
@end example

A sample structure, which holds sound data, used by the digital sample
routines. You can consider all of these fields as read only except
priority, loop_start and loop_end, which you can change them for example
after loading a sample from disk.

The priority is a value from 0 to 255 (by default set to 128) and controls
how hardware voices on the sound card are allocated if you attempt to play
more than the driver can handle. This may be used to ensure that the less
important sounds are cut off while the important ones are preserved.

The variables loop_start and loop_end specify the loop position in sample
units, and are set by default to the start and end of the sample.

If you are creating your own samples on the fly, you might also want to
modify the raw data of the sample pointed by the data field. The sample
data are always in unsigned format. This means that if you are loading a
PCM encoded sound file with signed 16-bit samples, you would have to XOR
every two bytes (i.e. every sample value) with 0x8000 to change the
signedness.

@end ftable
See also:@*
@xref{load_sample}.@*
@xref{Digital, Digital sample routines}.@*
@xref{Voice control}.@*
@xref{exsample}.@*
@node MIDI, AUDIOSTREAM, SAMPLE, Structures
@subsection MIDI
@ftable @asis
@item @t{typedef struct MIDI}
A structure holding MIDI data. Read chapter "Music routines (MIDI)" for a
description on how to obtain/use this structure.

@end ftable
See also:@*
@xref{load_midi}.@*
@xref{Music, Music routines (MIDI)}.@*
@xref{exmidi}.@*
@node AUDIOSTREAM, PACKFILE, MIDI, Structures
@subsection AUDIOSTREAM
@ftable @asis
@item @t{typedef struct AUDIOSTREAM}
@example

int voice;  - the hardware voice used for the sample
@end example

A structure holding an audiostream, which is a convenience wrapper around
a SAMPLE structure to double buffer sounds too big to fit into memory, or
do clever things like generating the sound wave real time.

While you shouldn't modify directly the value of the voice, you can use
all of the voice functions in chapter "Digital sample routines" to modify
the properties of the sound, like the frequency.

@end ftable
See also:@*
@xref{play_audio_stream}.@*
@xref{Audio, Audio stream routines}.@*
@xref{Voice control}.@*
@xref{exstream}.@*
@node PACKFILE, PACKFILE_VTABLE, AUDIOSTREAM, Structures
@subsection PACKFILE
@ftable @asis
@item @t{typedef struct PACKFILE}
A packfile structure, similar to the libc FILE structure. Read chapter
"File and compression routines" for a description on how to obtain/use
this structure. Note that prior to version 4.1.18, some internal fields
were accidentally documented - but PACKFILE should be treated as an
opaque structure, just like the libc FILE type.

@end ftable
See also:@*
@xref{File, File and compression routines}.@*
@xref{pack_fopen}.@*
@xref{pack_fopen_chunk}.@*
@xref{pack_fopen_vtable}.@*
@xref{expackf}.@*
@node PACKFILE_VTABLE, LZSS_PACK_DATA, PACKFILE, Structures
@subsection PACKFILE_VTABLE
@ftable @asis
@item @t{typedef struct PACKFILE_VTABLE}
@example

int pf_fclose(void *userdata);
int pf_getc(void *userdata);
int pf_ungetc(int c, void *userdata);
long pf_fread(void *p, long n, void *userdata);
int pf_putc(int c, void *userdata);
long pf_fwrite(const void *p, long n, void *userdata);
int pf_fseek(void *userdata, int offset);
int pf_feof(void *userdata);
int pf_ferror(void *userdata);
@end example

This is the vtable which must be provided for custom packfiles, which then
can read from and write to wherever you like (eg. files in memory). You
should provide all the entries of the vtable, even if they are empty stubs
doing nothing, to avoid Allegro (or you) calling a NULL method at some
point.

@end ftable
See also:@*
@xref{File, File and compression routines}.@*
@xref{pack_fopen_vtable}.@*
@xref{expackf}.@*
@node LZSS_PACK_DATA, LZSS_UNPACK_DATA, PACKFILE_VTABLE, Structures
@subsection LZSS_PACK_DATA
@ftable @asis
@item @t{typedef struct LZSS_PACK_DATA}
Opaque structure for handling LZSS compression. Read chapter "File and
compression routines for a description on how to obtain/use this
structure.

@end ftable
See also:@*
@xref{File, File and compression routines}.@*
@xref{create_lzss_pack_data}.@*
@node LZSS_UNPACK_DATA, set_uformat, LZSS_PACK_DATA, Structures
@subsection LZSS_UNPACK_DATA
@ftable @asis
@item @t{typedef struct LZSS_UNPACK_DATA}
Opaque structure for handling LZSS decompression. Read chapter "File and
compression routines for a description on how to obtain/use this
structure.



@end ftable
See also:@*
@xref{File, File and compression routines}.@*
@xref{create_lzss_unpack_data}.@*
@node Unicode, Configuration, Structures, API
@section Unicode routines

Allegro can manipulate and display text using any character values from 0 
right up to 2^32-1 (although the current implementation of the grabber can 
only create fonts using characters up to 2^16-1). You can choose between a 
number of different text encoding formats, which controls how strings are 
stored and how Allegro interprets strings that you pass to it. This setting 
affects all aspects of the system: whenever you see a function that returns 
a char * type, or that takes a char * as an argument, that text will be in 
whatever format you have told Allegro to use.

By default, Allegro uses UTF-8 encoded text (U_UTF8). This is a 
variable-width format, where characters can occupy anywhere from one to four
bytes. The nice thing about it is that characters ranging from 0-127 are 
encoded directly as themselves, so UTF-8 is upwardly compatible with 7-bit 
ASCII ("Hello, World!" means the same thing regardless of whether you 
interpret it as ASCII or UTF-8 data). Any character values above 128, such 
as accented vowels, the UK currency symbol, and Arabic or Chinese 
characters, will be encoded as a sequence of two or more bytes, each in the 
range 128-255. This means you will never get what looks like a 7-bit ASCII 
character as part of the encoding of a different character value, which 
makes it very easy to manipulate UTF-8 strings.

There are a few editing programs that understand UTF-8 format text files. 
Alternatively, you can write your strings in plain ASCII or 16-bit Unicode 
formats, and then use the Allegro textconv program to convert them into 
UTF-8.

If you prefer to use some other text format, you can set Allegro to work 
with normal 8-bit ASCII (U_ASCII), or 16-bit Unicode (U_UNICODE) instead, or 
you can provide some handler functions to make it support whatever other 
text encoding you like (for example it would be easy to add support for 32 
bit UCS-4 characters, or the Chinese GB-code format).

There is some limited support for alternative 8-bit codepages, via the 
U_ASCII_CP mode. This is very slow, so you shouldn't use it for serious 
work, but it can be handy as an easy way to convert text between different 
codepages. By default the U_ASCII_CP mode is set up to reduce text to a 
clean 7-bit ASCII format, trying to replace any accented vowels with their 
simpler equivalents (this is used by the allegro_message() function when it 
needs to print an error report onto a text mode DOS screen). If you want to 
work with other codepages, you can do this by passing a character mapping 
table to the set_ucodepage() function.

Note that you can use the Unicode routines before you call install_allegro() 
or allegro_init(). If you want to work in a text mode other than UTF-8, it 
is best to set it with set_uformat() just before you call these.

@menu
* set_uformat::
* get_uformat::
* register_uformat::
* set_ucodepage::
* need_uconvert::
* uconvert_size::
* do_uconvert::
* uconvert::
* uconvert_ascii::
* uconvert_toascii::
* empty_string::
* ugetc::
* ugetx::
* usetc::
* uwidth::
* ucwidth::
* uisok::
* uoffset::
* ugetat::
* usetat::
* uinsert::
* uremove::
* ustrsize::
* ustrsizez::
* uwidth_max::
* utolower::
* utoupper::
* uisspace::
* uisdigit::
* ustrdup::
* _ustrdup::
* ustrcpy::
* ustrzcpy::
* ustrcat::
* ustrzcat::
* ustrlen::
* ustrcmp::
* ustrncpy::
* ustrzncpy::
* ustrncat::
* ustrzncat::
* ustrncmp::
* ustricmp::
* ustrnicmp::
* ustrlwr::
* ustrupr::
* ustrchr::
* ustrrchr::
* ustrstr::
* ustrpbrk::
* ustrtok::
* ustrtok_r::
* uatof::
* ustrtol::
* ustrtod::
* ustrerror::
* usprintf::
* uszprintf::
* uvsprintf::
* uvszprintf::
@end menu
@node set_uformat, get_uformat, LZSS_UNPACK_DATA, Unicode
@subsection set_uformat
@ftable @asis
@item @t{void set_uformat(int type);}
Sets the current text encoding format. This will affect all parts of 
Allegro, wherever you see a function that returns a char *, or takes a 
char * as a parameter. `type' should be one of these values:
@example

U_ASCII     - fixed size, 8-bit ASCII characters
U_ASCII_CP  - alternative 8-bit codepage (see set_ucodepage())
U_UNICODE   - fixed size, 16-bit Unicode characters
U_UTF8      - variable size, UTF-8 format Unicode characters
@end example

Although you can change the text format on the fly, this is not a good 
idea. Many strings, for example the names of your hardware drivers and 
any language translations, are loaded when you call allegro_init(), so if 
you change the encoding format after this, they will be in the wrong 
format, and things will not work properly. Generally you should only call 
set_uformat() once, before allegro_init(), and then leave it on the same 
setting for the duration of your program.

@end ftable
See also:@*
@xref{get_uformat}.@*
@xref{register_uformat}.@*
@xref{set_ucodepage}.@*
@xref{set_uformat}.@*
@xref{uconvert}.@*
@xref{ustrsize}.@*
@xref{ugetc}.@*
@xref{ugetx}.@*
@xref{usetc}.@*
@xref{uwidth}.@*
@xref{ucwidth}.@*
@xref{uisok}.@*
@xref{uoffset}.@*
@xref{ugetat}.@*
@xref{usetat}.@*
@xref{uinsert}.@*
@xref{uremove}.@*
@xref{allegro_init}.@*
@xref{exunicod}.@*
@node get_uformat, register_uformat, set_uformat, Unicode
@subsection get_uformat
@ftable @asis
@item @t{int get_uformat(void);}
Finds out what text encoding format is currently selected. This function
is probably useful only if you are writing an Allegro addon dealing with
text strings and you use a different codepath for each possible format.
Example:
@example

switch(get_uformat()) @{
   case U_ASCII:
      do_something();
      break;
   case U_UTF8:
      do_something_else();
      break;
   ...
@}@end example


Returns the currently selected text encoding format. See the documentation
of set_uformat() for a list of encoding formats.

@end ftable
See also:@*
@xref{set_uformat}.@*
@node register_uformat, set_ucodepage, get_uformat, Unicode
@subsection register_uformat
@ftable @asis
@item @t{void register_uformat(int type, int (*u_getc)(const char *s), int (*u_getx)(char **s), int (*u_setc)(char *s, int c), int (*u_width)(const char *s), int (*u_cwidth)(int c), int (*u_isok)(int c));}
Installs a set of custom handler functions for a new text encoding 
format. The `type' is the ID code for your new format, which should be a
4-character string as produced by the AL_ID() macro, and which can later 
be passed to functions like set_uformat() and uconvert(). The function 
parameters are handlers that implement the character access for your new 
type: see below for details of these.

@end ftable
See also:@*
@xref{set_uformat}.@*
@xref{uconvert}.@*
@xref{ugetc}.@*
@xref{ugetx}.@*
@xref{usetc}.@*
@xref{uwidth}.@*
@xref{ucwidth}.@*
@xref{uisok}.@*
@node set_ucodepage, need_uconvert, register_uformat, Unicode
@subsection set_ucodepage
@ftable @asis
@item @t{void set_ucodepage(const unsigned short *table, const unsigned short *extras);}
When you select the U_ASCII_CP encoding mode, a set of tables are used to 
convert between 8-bit characters and their Unicode equivalents. You can 
use this function to specify a custom set of mapping tables, which allows 
you to support different 8-bit codepages.

The `table' parameter points to an array of 256 shorts, which contain the
Unicode value for each character in your codepage. The `extras' parameter,
if not NULL, points to a list of mapping pairs, which will be used when
reducing Unicode data to your codepage. Each pair consists of a Unicode
value, followed by the way it should be represented in your codepage.
The list is terminated by a zero Unicode value. This allows you to create
a many->one mapping, where many different Unicode characters can be
represented by a single codepage value (eg. for reducing accented vowels
to 7-bit ASCII).

Allegro will use the `table' parameter when it needs to convert an ASCII
string to an Unicode string. But when Allegro converts an Unicode string
to ASCII, it will use both parameters. First, it will loop through the
`table' parameter looking for an index position pointing at the Unicode
value it is trying to convert (ie. the `table' parameter is also used for
reverse matching). If that fails, the `extras' list is used. If that fails
too, Allegro will put the character `^', giving up the conversion.

Note that Allegro comes with a default `table' and `extras' parameters
set internally. The default `table' will convert 8-bit characters to `^'.
The default `extras' list reduces Latin-1 and Extended-A characters to 7
bits in a sensible way (eg. an accented vowel will be reduced to the same
vowel without the accent).

@end ftable
See also:@*
@xref{set_uformat}.@*
@node need_uconvert, uconvert_size, set_ucodepage, Unicode
@subsection need_uconvert
@ftable @asis
@item @t{int need_uconvert(const char *s, int type, int newtype);}
Given a pointer to a string (`s'), a description of the type of the string
(`type'), and the type that you would like this string to be converted into
(`newtype'), this function tells you whether any conversion is required. No
conversion will be needed if `type' and `newtype' are the same, or if one
type is ASCII, the other is UTF-8, and the string contains only character
values less than 128. As a convenience shortcut, you can pass the value
U_CURRENT as either of the type parameters, to represent whatever text
encoding format is currently selected. Example:
@example

if (need_uconvert(text, U_UTF8, U_CURRENT)) @{
   /* conversion is required */
@}@end example


Returns non-zero if any conversion is required or zero otherwise.

@end ftable
See also:@*
@xref{set_uformat}.@*
@xref{get_uformat}.@*
@xref{do_uconvert}.@*
@xref{uconvert}.@*
@node uconvert_size, do_uconvert, need_uconvert, Unicode
@subsection uconvert_size
@ftable @asis
@item @t{int uconvert_size(const char *s, int type, int newtype);}
Finds out how many bytes are required to store the specified string `s'
after a conversion from `type' to `newtype', including the mandatory zero
terminator of the string. You can use U_CURRENT for either `type' or
`newtype' as a shortcut to represent whatever text encoding format is
currently selected. Example:
@example

length = uconvert_size(old_string, U_CURRENT, U_UNICODE);
new_string = malloc(length);
ustrcpy(new_string, old_string);@end example


Returns the number of bytes required to store the string after conversion.

@end ftable
See also:@*
@xref{need_uconvert}.@*
@xref{do_uconvert}.@*
@node do_uconvert, uconvert, uconvert_size, Unicode
@subsection do_uconvert
@ftable @asis
@item @t{void do_uconvert(const char *s, int type, char *buf, int newtype, int size);}
Converts the specified string `s' from `type' to `newtype', storing at most
`size' bytes into the output `buf'. The type parameters can use the value
U_CURRENT as a shortcut to represent the currently selected encoding 
format. Example:
@example

char temp_string[256];
do_uconvert(input_string, U_CURRENT, temp_string, U_ASCII, 256);
@end example

Note that, even for empty strings, your destination string must have at
least enough bytes to store the terminating null character of the string,
and your parameter size must reflect this. Otherwise, the debug version of
Allegro will abort at an assertion, and the release version of Allegro
will overrun the destination buffer.

@end ftable
See also:@*
@xref{uconvert}.@*
@node uconvert, uconvert_ascii, do_uconvert, Unicode
@subsection uconvert
@ftable @asis
@item @t{char *uconvert(const char *s, int type, char *buf, int newtype, int size);}
Higher level function running on top of do_uconvert(). This function 
converts the specified string `s' from `type' to `newtype', storing at most
`size' bytes into the output `buf' (including the terminating null
character), but it checks before doing the conversion, and doesn't bother
if the string formats are already the same (either both types are equal, or
one is ASCII, the other is UTF-8, and the string contains only 7-bit ASCII
characters).

As a convenience, if `buf' is NULL it will convert the string into an
internal static buffer and the `size' parameter will be ignored. You should
be wary of using this feature, though, because that buffer will be
overwritten the next time this routine is called, so don't expect the data
to persist across any other library calls. The static buffer may hold less
than 1024 characters, so you won't be able to convert large chunks of text.
Example:
@example

char *p = uconvert(input_string, U_CURRENT, buffer, U_ASCII, 256);@end example


Returns a pointer to `buf' (or the static buffer if you used NULL) if a
conversion was performed. Otherwise returns a copy of `s'. In any cases,
you should use the return value rather than assuming that the string will
always be moved to `buf'.

@end ftable
See also:@*
@xref{set_uformat}.@*
@xref{need_uconvert}.@*
@xref{uconvert}.@*
@xref{uconvert_ascii}.@*
@xref{uconvert_toascii}.@*
@xref{do_uconvert}.@*
@node uconvert_ascii, uconvert_toascii, uconvert, Unicode
@subsection uconvert_ascii
@ftable @asis
@item @t{char *uconvert_ascii(const char *s, char buf[]);}
Helper macro for converting strings from ASCII into the current encoding 
format. Expands to uconvert(s, U_ASCII, buf, U_CURRENT, sizeof(buf)).

@end ftable
See also:@*
@xref{uconvert}.@*
@xref{exunicod}.@*
@node uconvert_toascii, empty_string, uconvert_ascii, Unicode
@subsection uconvert_toascii
@ftable @asis
@item @t{char *uconvert_toascii(const char *s, char buf[]);}
Helper macro for converting strings from the current encoding format into 
ASCII. Expands to uconvert(s, U_CURRENT, buf, U_ASCII, sizeof(buf)).

@end ftable
See also:@*
@xref{uconvert}.@*
@node empty_string, ugetc, uconvert_toascii, Unicode
@subsection empty_string
@ftable @asis
@item @t{extern char empty_string[];}
You can't just rely on "" to be a valid empty string in any encoding 
format. This global buffer contains a number of consecutive zeros, so it 
will be a valid empty string no matter whether the program is running in 
ASCII, Unicode, or UTF-8 mode.

@end ftable
@node ugetc, ugetx, empty_string, Unicode
@subsection ugetc
@ftable @asis
@item @t{int ugetc(const char *s);}
Low level helper function for reading Unicode text data. Example:
@example

int first_unicode_letter = ugetc(text_string);@end example


Returns the character pointed to by `s' in the current encoding format.

@end ftable
See also:@*
@xref{ugetx}.@*
@xref{usetc}.@*
@xref{uwidth}.@*
@xref{ucwidth}.@*
@xref{uisok}.@*
@node ugetx, usetc, ugetc, Unicode
@subsection ugetx
@ftable @asis
@item @t{int ugetx(char **s);}
@end ftable
@ftable @asis
@item @t{int ugetxc(const char **s);}
Low level helper function for reading Unicode text data. ugetxc is provided
for working with pointer-to-pointer-to-const char data. Example:
@example

char *p = string;
int first_letter, second_letter, third_letter;
first_letter = ugetx(&p);
second_letter = ugetx(&p);
third_letter = ugetx(&p);@end example


Returns the character pointed to by `s' in the current encoding format, and
advances the pointer to the next character after the one just returned.

@end ftable
See also:@*
@xref{ugetc}.@*
@xref{usetc}.@*
@xref{uwidth}.@*
@xref{ucwidth}.@*
@xref{uisok}.@*
@node usetc, uwidth, ugetx, Unicode
@subsection usetc
@ftable @asis
@item @t{int usetc(char *s, int c);}
Low level helper function for writing Unicode text data. Writes the
character `c' to the address pointed to by `s'.

Returns the number of bytes written, which is equal to the width of the
character in the current encoding format.

@end ftable
See also:@*
@xref{ugetc}.@*
@xref{ugetx}.@*
@xref{uwidth}.@*
@xref{ucwidth}.@*
@xref{uisok}.@*
@node uwidth, ucwidth, usetc, Unicode
@subsection uwidth
@ftable @asis
@item @t{int uwidth(const char *s);}
Low level helper function for testing Unicode text data.

Returns the number of bytes occupied by the first character of the
specified string, in the current encoding format.

@end ftable
See also:@*
@xref{uwidth_max}.@*
@xref{ugetc}.@*
@xref{ugetx}.@*
@xref{usetc}.@*
@xref{ucwidth}.@*
@xref{uisok}.@*
@node ucwidth, uisok, uwidth, Unicode
@subsection ucwidth
@ftable @asis
@item @t{int ucwidth(int c);}
Low level helper function for testing Unicode text data.

Returns the number of bytes that would be occupied by the specified
character value, when encoded in the current format.

@end ftable
See also:@*
@xref{uwidth_max}.@*
@xref{ugetc}.@*
@xref{ugetx}.@*
@xref{usetc}.@*
@xref{uwidth}.@*
@xref{uisok}.@*
@node uisok, uoffset, ucwidth, Unicode
@subsection uisok
@ftable @asis
@item @t{int uisok(int c);}
Low level helper function for testing Unicode text data. Finds out if the
character value `c' can be encoded correctly in the current format, which
can be useful if you are converting from Unicode to ASCII or another
encoding format where the range of valid characters is limited.

Returns non-zero if the value can be correctly encoded, zero otherwise.

@end ftable
See also:@*
@xref{ugetc}.@*
@xref{ugetx}.@*
@xref{usetc}.@*
@xref{uwidth}.@*
@xref{ucwidth}.@*
@node uoffset, ugetat, uisok, Unicode
@subsection uoffset
@ftable @asis
@item @t{int uoffset(const char *s, int index);}
Finds out the offset (in bytes from the start of the string) of the
character at the specified `index' in the string `s'. A zero `index'
parameter will return the first character of the string. If `index' is
negative, it counts backward from the end of the string, so an `index' of
`-1' will return an offset to the last character. Example:
@example

int from_third_letter = uoffset(text_string, 2);@end example


Returns the offset in bytes to the specified character.

@end ftable
See also:@*
@xref{ugetat}.@*
@xref{usetat}.@*
@xref{uinsert}.@*
@xref{uremove}.@*
@node ugetat, usetat, uoffset, Unicode
@subsection ugetat
@ftable @asis
@item @t{int ugetat(const char *s, int index);}
Finds out the character value at the specified `index' in the string. A
zero `index' parameter will return the first character of the string. If
`index' is negative, it counts backward from the end of the string, so an
`index' of `-1' will return the last character of the string. Example:
@example

int third_letter = ugetat(text_string, 2);@end example


Returns the character value at the specified index in the string.

@end ftable
See also:@*
@xref{uoffset}.@*
@xref{usetat}.@*
@xref{uinsert}.@*
@xref{uremove}.@*
@node usetat, uinsert, ugetat, Unicode
@subsection usetat
@ftable @asis
@item @t{int usetat(char *s, int index, int c);}
Replaces the character at the specified index in the string with value `c',
handling any adjustments for variable width data (ie. if `c' encodes to a
different width than the previous value at that location). If `index' is
negative, it counts backward from the end of the string. Example:
@example

usetat(text_string, 2, letter_a);@end example


Returns the number of bytes by which the trailing part of the string was
moved. This is of interest only with text encoding formats where
characters have a variable length, like UTF-8.

@end ftable
See also:@*
@xref{uoffset}.@*
@xref{ugetat}.@*
@xref{uinsert}.@*
@xref{uremove}.@*
@node uinsert, uremove, usetat, Unicode
@subsection uinsert
@ftable @asis
@item @t{int uinsert(char *s, int index, int c);}
Inserts the character `c' at the specified `index' in the string, sliding
the rest of the data along to make room. If `index' is negative, it counts
backward from the end of the string. Example:
@example

uinsert(text_string, 0, prefix_letter);@end example


Returns the number of bytes by which the trailing part of the string was
moved.

@end ftable
See also:@*
@xref{uoffset}.@*
@xref{ugetat}.@*
@xref{usetat}.@*
@xref{uremove}.@*
@node uremove, ustrsize, uinsert, Unicode
@subsection uremove
@ftable @asis
@item @t{int uremove(char *s, int index);}
Removes the character at the specified `index' within the string, sliding
the rest of the data back to fill the gap. If `index' is negative, it
counts backward from the end of the string. Example:
@example

int length_in_bytes = ustrsizez(text_string);
...
length_in_bytes -= uremove(text_string, -1);@end example


Returns the number of bytes by which the trailing part of the string was
moved.

@end ftable
See also:@*
@xref{uoffset}.@*
@xref{ugetat}.@*
@xref{usetat}.@*
@xref{uinsert}.@*
@node ustrsize, ustrsizez, uremove, Unicode
@subsection ustrsize
@ftable @asis
@item @t{int ustrsize(const char *s);}
Returns the size of the specified string in bytes, not including the 
trailing null character.

@end ftable
See also:@*
@xref{ustrsizez}.@*
@xref{empty_string}.@*
@xref{exunicod}.@*
@node ustrsizez, uwidth_max, ustrsize, Unicode
@subsection ustrsizez
@ftable @asis
@item @t{int ustrsizez(const char *s);}
Returns the size of the specified string in bytes, including the trailing 
null character.

@end ftable
See also:@*
@xref{ustrsize}.@*
@xref{empty_string}.@*
@xref{exunicod}.@*
@node uwidth_max, utolower, ustrsizez, Unicode
@subsection uwidth_max
@ftable @asis
@item @t{int uwidth_max(int type);}
Low level helper function for working with Unicode text data. Returns the 
largest number of bytes that one character can occupy in the given 
encoding format. Pass U_CURRENT to represent the current format. Example:
@example

char *temp_buffer = malloc(256 * uwidth_max(U_UTF8));@end example


@end ftable
See also:@*
@xref{uwidth}.@*
@xref{ucwidth}.@*
@node utolower, utoupper, uwidth_max, Unicode
@subsection utolower
@ftable @asis
@item @t{int utolower(int c);}
This function returns `c', converting it to lower case if it is upper case.

@end ftable
See also:@*
@xref{utoupper}.@*
@xref{ugetc}.@*
@xref{ugetx}.@*
@xref{usetc}.@*
@xref{uwidth}.@*
@xref{ucwidth}.@*
@xref{uisok}.@*
@node utoupper, uisspace, utolower, Unicode
@subsection utoupper
@ftable @asis
@item @t{int utoupper(int c);}
This function returns `c', converting it to upper case if it is lower case.

@end ftable
See also:@*
@xref{utolower}.@*
@xref{ugetc}.@*
@xref{ugetx}.@*
@xref{usetc}.@*
@xref{uwidth}.@*
@xref{ucwidth}.@*
@xref{uisok}.@*
@node uisspace, uisdigit, utoupper, Unicode
@subsection uisspace
@ftable @asis
@item @t{int uisspace(int c);}
Returns nonzero if `c' is whitespace, that is, carriage return, newline,
form feed, tab, vertical tab, or space. Example:
@example

for (counter = 0; counter < ustrlen(text_string); counter++) @{
   if (uisspace(ugetat(text_string, counter)))
      usetat(text_string, counter, '_');
@}@end example


@end ftable
See also:@*
@xref{uisdigit}.@*
@xref{ugetc}.@*
@xref{usetc}.@*
@xref{uwidth}.@*
@xref{ucwidth}.@*
@xref{uisok}.@*
@node uisdigit, ustrdup, uisspace, Unicode
@subsection uisdigit
@ftable @asis
@item @t{int uisdigit(int c);}
Returns nonzero if `c' is a digit.
@example

for (counter = 0; counter < ustrlen(text_string); counter++) @{
   if (uisdigit(ugetat(text_string, counter)))
      usetat(text_string, counter, '*');
@}@end example


@end ftable
See also:@*
@xref{uisspace}.@*
@xref{ugetc}.@*
@xref{usetc}.@*
@xref{uwidth}.@*
@xref{ucwidth}.@*
@xref{uisok}.@*
@node ustrdup, _ustrdup, uisdigit, Unicode
@subsection ustrdup
@ftable @asis
@item @t{char *ustrdup(const char *src)}
This functions copies the null-terminated string `src' into a newly
allocated area of memory, effectively duplicating it. Example:
@example

void manipulate_string(const char *input_string)
@{
   char *temp_buffer = ustrdup(input_string);
   /* Now we can modify temp_buffer */
   ...@end example


Returns the newly allocated string. This memory must be freed by the
caller. Returns NULL if it cannot allocate space for the duplicated string.

@end ftable
See also:@*
@xref{_ustrdup}.@*
@xref{uconvert}.@*
@xref{ustrsize}.@*
@xref{ustrsizez}.@*
@xref{exconfig}.@*
@node _ustrdup, ustrcpy, ustrdup, Unicode
@subsection _ustrdup
@ftable @asis
@item @t{char *_ustrdup(const char *src, void* (*malloc_func)(size_t))}
Does the same as ustrdup(), but allows the user to specify a custom memory
allocator function.

@end ftable
See also:@*
@xref{ustrdup}.@*
@xref{uconvert}.@*
@xref{ustrsize}.@*
@xref{ustrsizez}.@*
@node ustrcpy, ustrzcpy, _ustrdup, Unicode
@subsection ustrcpy
@ftable @asis
@item @t{char *ustrcpy(char *dest, const char *src);}
This function copies `src' (including the terminating null character into
`dest'. You should try to avoid this function because it is very easy to
overflow the destination buffer. Use ustrzcpy instead.

Returns the value of dest.

@end ftable
See also:@*
@xref{uconvert}.@*
@xref{ustrzcpy}.@*
@xref{ustrncpy}.@*
@xref{exunicod}.@*
@node ustrzcpy, ustrcat, ustrcpy, Unicode
@subsection ustrzcpy
@ftable @asis
@item @t{char *ustrzcpy(char *dest, int size, const char *src);}
This function copies `src' (including the terminating null character) into
`dest', whose length in bytes is specified by `size' and which is
guaranteed to be null-terminated even if `src' is bigger than `size'.

Note that, even for empty strings, your destination string must have at
least enough bytes to store the terminating null character of the string,
and your parameter size must reflect this. Otherwise, the debug version of
Allegro will abort at an assertion, and the release version of Allegro
will overrun the destination buffer.

Returns the value of `dest'.

@end ftable
See also:@*
@xref{uconvert}.@*
@xref{ustrcpy}.@*
@xref{ustrzncpy}.@*
@xref{ex3buf}.@*
@xref{exgui}.@*
@node ustrcat, ustrzcat, ustrzcpy, Unicode
@subsection ustrcat
@ftable @asis
@item @t{char *ustrcat(char *dest, const char *src);}
This function concatenates `src' to the end of `dest`'. You should try to
avoid this function because it is very easy to overflow the destination
buffer, use ustrzcat instead.

Returns the value of `dest'.

@end ftable
See also:@*
@xref{uconvert}.@*
@xref{ustrzcat}.@*
@xref{ustrncat}.@*
@xref{exunicod}.@*
@node ustrzcat, ustrlen, ustrcat, Unicode
@subsection ustrzcat
@ftable @asis
@item @t{char *ustrzcat(char *dest, int size, const char *src);}
This function concatenates `src' to the end of `dest', whose length in
bytes is specified by `size' and which is guaranteed to be null-terminated
even when `src' is bigger than `size'.

Note that, even for empty strings, your destination string must have at
least enough bytes to store the terminating null character of the string,
and your parameter size must reflect this. Otherwise, the debug version of
Allegro will abort at an assertion, and the release version of Allegro
will overrun the destination buffer.

Returns the value of `dest'.

@end ftable
See also:@*
@xref{uconvert}.@*
@xref{ustrcat}.@*
@xref{ustrzncat}.@*
@xref{exgui}.@*
@node ustrlen, ustrcmp, ustrzcat, Unicode
@subsection ustrlen
@ftable @asis
@item @t{int ustrlen(const char *s);}
This function returns the number of characters in `s'. Note that this
doesn't have to equal the string's size in bytes.

@end ftable
See also:@*
@xref{uconvert}.@*
@xref{ustrsize}.@*
@xref{ustrsizez}.@*
@node ustrcmp, ustrncpy, ustrlen, Unicode
@subsection ustrcmp
@ftable @asis
@item @t{int ustrcmp(const char *s1, const char *s2);}
This function compares `s1' and `s2'.

Returns zero if the strings are equal, a positive number if `s1' comes
after `s2' in the ASCII collating sequence, else a negative number.

@end ftable
See also:@*
@xref{uconvert}.@*
@xref{ustrsize}.@*
@xref{ustrsizez}.@*
@xref{ustrncmp}.@*
@xref{ustricmp}.@*
@xref{ustrnicmp}.@*
@node ustrncpy, ustrzncpy, ustrcmp, Unicode
@subsection ustrncpy
@ftable @asis
@item @t{char *ustrncpy(char *dest, const char *src, int n);}
This function is like ustrcpy() except that no more than `n' characters
from `src' are copied into `dest'. If `src' is shorter than `n' characters,
null characters are appended to `dest' as padding until `n' characters have
been written.

Note that if `src' is longer than `n' characters, `dest' will not be
null-terminated.

The return value is the value of `dest'.

@end ftable
See also:@*
@xref{uconvert}.@*
@xref{ustrcpy}.@*
@xref{ustrzncpy}.@*
@node ustrzncpy, ustrncat, ustrncpy, Unicode
@subsection ustrzncpy
@ftable @asis
@item @t{char *ustrzncpy(char *dest, int size, const char *src, int n);}
This function is like ustrzcpy() except that no more than `n' characters
from `src' are copied into `dest'. If `src' is shorter than `n' characters,
null characters are appended to `dest' as padding until `n' characters have
been written. In any case, `dest' is guaranteed to be null-terminated.

Note that, even for empty strings, your destination string must have at
least enough bytes to store the terminating null character of the string,
and your parameter `size' must reflect this. Otherwise, the debug version
of Allegro will abort at an assertion, and the release version of Allegro
will overrun the destination buffer.

The return value is the value of `dest'.

@end ftable
See also:@*
@xref{uconvert}.@*
@xref{ustrzcpy}.@*
@xref{ustrncpy}.@*
@xref{exkeys}.@*
@node ustrncat, ustrzncat, ustrzncpy, Unicode
@subsection ustrncat
@ftable @asis
@item @t{char *ustrncat(char *dest, const char *src, int n);}
This function is like ustrcat() except that no more than `n' characters
from `src' are appended to the end of `dest'. If the terminating null
character in `src' is reached before `n' characters have been written, the
null character is copied, but no other characters are written. If `n'
characters are written before a terminating null is encountered, the
function appends its own null character to `dest', so that `n+1' characters
are written. You should try to avoid this function because it is very
easy to overflow the destination buffer. Use ustrzncat instead.

The return value is the value of `dest'.

@end ftable
See also:@*
@xref{uconvert}.@*
@xref{ustrcat}.@*
@xref{ustrzncat}.@*
@node ustrzncat, ustrncmp, ustrncat, Unicode
@subsection ustrzncat
@ftable @asis
@item @t{char *ustrzncat(char *dest, int size, const char *src, int n);}
This function is like ustrzcat() except that no more than `n' characters
from `src' are appended to the end of `dest'. If the terminating null
character in `src' is reached before `n' characters have been written, the
null character is copied, but no other characters are written. Note that
`dest' is guaranteed to be null-terminated.

The return value is the value of `dest'.

@end ftable
See also:@*
@xref{uconvert}.@*
@xref{ustrzcat}.@*
@xref{ustrncat}.@*
@node ustrncmp, ustricmp, ustrzncat, Unicode
@subsection ustrncmp
@ftable @asis
@item @t{int ustrncmp(const char *s1, const char *s2, int n);}
This function compares up to `n' characters of `s1' and `s2'. Example:
@example

if (ustrncmp(prefix, long_string, ustrlen(prefix)) == 0) @{
   /* long_string starts with prefix */
@}@end example


Returns zero if the substrings are equal, a positive number if `s1' comes
after `s2' in the ASCII collating sequence, else a negative number.

@end ftable
See also:@*
@xref{uconvert}.@*
@xref{ustrsize}.@*
@xref{ustrsizez}.@*
@xref{ustrcmp}.@*
@xref{ustricmp}.@*
@xref{ustrnicmp}.@*
@node ustricmp, ustrnicmp, ustrncmp, Unicode
@subsection ustricmp
@ftable @asis
@item @t{int ustricmp(const char *s1, const char *s2);}
This function compares `s1' and `s2', ignoring case. Example:
@example

if (ustricmp(string, user_input) == 0) @{
   /* string and user_input are equal (ignoring case) */
@}@end example


Returns zero if the strings are equal, a positive number if `s1' comes
after `s2' in the ASCII collating sequence, else a negative number.

@end ftable
See also:@*
@xref{uconvert}.@*
@xref{ustrsize}.@*
@xref{ustrsizez}.@*
@xref{ustrnicmp}.@*
@xref{ustrcmp}.@*
@xref{ustrncmp}.@*
@xref{exconfig}.@*
@node ustrnicmp, ustrlwr, ustricmp, Unicode
@subsection ustrnicmp
@ftable @asis
@item @t{int ustrnicmp(const char *s1, const char *s2, int n);}
This function compares up to `n' characters of `s1' and `s2', ignoring
case. Example:
@example

if (ustrnicmp(prefix, long_string, ustrlen(prefix)) == 0) @{
   /* long_string starts with prefix (ignoring case) */
@}@end example


Returns zero if the strings are equal, a positive number if `s1' comes
after `s2' in the ASCII collating sequence, else a negative number.

@end ftable
See also:@*
@xref{uconvert}.@*
@xref{ustrsize}.@*
@xref{ustrsizez}.@*
@xref{ustricmp}.@*
@xref{ustrcmp}.@*
@xref{ustrncmp}.@*
@node ustrlwr, ustrupr, ustrnicmp, Unicode
@subsection ustrlwr
@ftable @asis
@item @t{char *ustrlwr(char *s);}
This function replaces all upper case letters in `s' with lower case
letters. Example:
@example

char buffer[] = "UPPER CASE STRING";
allegro_message(ustrlwr(buffer));@end example


The return value is the value of `s'.

@end ftable
See also:@*
@xref{uconvert}.@*
@xref{utolower}.@*
@xref{ustrupr}.@*
@node ustrupr, ustrchr, ustrlwr, Unicode
@subsection ustrupr
@ftable @asis
@item @t{char *ustrupr(char *s);}
This function replaces all lower case letters in `s' with upper case
letters. Example:
@example

char buffer[] = "lower case string";
allegro_message(ustrupr(buffer));@end example


The return value is the value of `s'.

@end ftable
See also:@*
@xref{uconvert}.@*
@xref{utolower}.@*
@xref{ustrlwr}.@*
@node ustrchr, ustrrchr, ustrupr, Unicode
@subsection ustrchr
@ftable @asis
@item @t{char *ustrchr(const char *s, int c);}
Finds the first occurrence of the character `c' in the string `s'. Example:
@example

char *p = ustrchr("one,two,three,four", ',');@end example


Returns a pointer to the first occurrence of `c' in `s', or NULL if no
match was found. Note that if `c' is NULL, this will return a pointer to
the end of the string.

@end ftable
See also:@*
@xref{uconvert}.@*
@xref{ustrrchr}.@*
@xref{ustrstr}.@*
@xref{ustrpbrk}.@*
@xref{ustrtok}.@*
@node ustrrchr, ustrstr, ustrchr, Unicode
@subsection ustrrchr
@ftable @asis
@item @t{char *ustrrchr(const char *s, int c);}
Finds the last occurrence of the character `c' in the string `s'. Example:
@example

char *p = ustrrchr("one,two,three,four", ',');@end example


Returns a pointer for the last occurrence of `c' in `s', or NULL if no
match was found.

@end ftable
See also:@*
@xref{uconvert}.@*
@xref{ustrchr}.@*
@xref{ustrstr}.@*
@xref{ustrpbrk}.@*
@xref{ustrtok}.@*
@node ustrstr, ustrpbrk, ustrrchr, Unicode
@subsection ustrstr
@ftable @asis
@item @t{char *ustrstr(const char *s1, const char *s2);}
This function finds the first occurrence of string `s2' in string `s1'.
Example:
@example

char *p = ustrstr("hello world", "world");@end example


Returns a pointer within `s1', or NULL if `s2' wasn't found.

@end ftable
See also:@*
@xref{uconvert}.@*
@xref{ustrchr}.@*
@xref{ustrrchr}.@*
@xref{ustrpbrk}.@*
@xref{ustrtok}.@*
@node ustrpbrk, ustrtok, ustrstr, Unicode
@subsection ustrpbrk
@ftable @asis
@item @t{char *ustrpbrk(const char *s, const char *set);}
This function finds the first character in `s' that matches any character
in `set'. Example:
@example

char *p = ustrpbrk("one,two-three.four", "-. ");@end example


Returns a pointer to the first match, or NULL if none are found.

@end ftable
See also:@*
@xref{uconvert}.@*
@xref{ustrchr}.@*
@xref{ustrrchr}.@*
@xref{ustrstr}.@*
@xref{ustrtok}.@*
@node ustrtok, ustrtok_r, ustrpbrk, Unicode
@subsection ustrtok
@ftable @asis
@item @t{char *ustrtok(char *s, const char *set);}
This function retrieves tokens from `s' which are delimited by characters
from `set'. To initiate the search, pass the string to be searched as `s'.
For the remaining tokens, pass NULL instead. Warning: Since ustrtok alters
the string it is parsing, you should always copy the string to a temporary
buffer before parsing it. Also, this function is not re-entrant (ie. you
cannot parse two strings at the same time). Example:
@example

char *word;
char string[]="some-words with dashes";
char *temp = ustrdup(string);
word = ustrtok(temp, " -");
while (word) @{
   allegro_message("Found `%s'\n", word);
   word = ustrtok(NULL, " -");
@}
free(temp);@end example


Returns a pointer to the token, or NULL if no more are found.

@end ftable
See also:@*
@xref{uconvert}.@*
@xref{ustrchr}.@*
@xref{ustrrchr}.@*
@xref{ustrstr}.@*
@xref{ustrpbrk}.@*
@xref{ustrtok_r}.@*
@xref{allegro_message}.@*
@xref{ustrncpy}.@*
@xref{exgui}.@*
@node ustrtok_r, uatof, ustrtok, Unicode
@subsection ustrtok_r
@ftable @asis
@item @t{char *ustrtok_r(char *s, const char *set, char **last);}
Reentrant version of ustrtok. The `last' parameter is used to keep track
of where the parsing is up to and must be a pointer to a char * variable
allocated by the user that remains the same while parsing the same
string. Example:
@example

char *word, *last;
char string[]="some-words with dashes";
char *temp = ustrdup(string);
word = ustrtok_r(string, " -", &last);
while (word) @{
   allegro_message("Found `%s'\n", word);
   word = ustrtok_r(NULL, " -", &last);
@}
free(temp);@end example


Returns a pointer to the token, or NULL if no more are found. You can free
the memory pointed to by `last' once NULL is returned.

@end ftable
See also:@*
@xref{ustrtok}.@*
@node uatof, ustrtol, ustrtok_r, Unicode
@subsection uatof
@ftable @asis
@item @t{double uatof(const char *s);}
Convert as much of the string as possible to an equivalent double
precision real number. This function is almost like `ustrtod(s, NULL)'.

Returns the equivalent value, or zero if the string does not represent a
number.

@end ftable
See also:@*
@xref{uconvert}.@*
@xref{ustrtol}.@*
@xref{ustrtod}.@*
@node ustrtol, ustrtod, uatof, Unicode
@subsection ustrtol
@ftable @asis
@item @t{long ustrtol(const char *s, char **endp, int base);}
This function converts the initial part of `s' to a signed integer, setting
`*endp' to point to the first unused character, if `endp' is not a NULL
pointer. The `base' argument indicates what base the digits (or letters)
should be treated as. If `base' is zero, the base is determined by looking
for `0x', `0X', or `0' as the first part of the string, and sets the base
used to 16, 16, or 8 if it finds one. The default base is 10 if none of
those prefixes are found. Example:
@example

char *endp, *string = "456.203 askdfg";
int number = ustrtol(string, &endp, 10);@end example


Returns the string converted as a value of type `long int'. If nothing was
converted, returns zero with `*endp' pointing to the beginning of `s'.

@end ftable
See also:@*
@xref{uconvert}.@*
@xref{ustrtod}.@*
@xref{uatof}.@*
@node ustrtod, ustrerror, ustrtol, Unicode
@subsection ustrtod
@ftable @asis
@item @t{double ustrtod(const char *s, char **endp);}
This function converts as many characters of `s' that look like a floating
point number into one, and sets `*endp' to point to the first unused
character, if `endp' is not a NULL pointer. Example:
@example

char *endp, *string = "456.203 askdfg";
double number = ustrtod(string, &endp);@end example


Returns the string converted as a value of type `double'. If nothing was
converted, returns zero with *endp pointing to the beginning of s.

@end ftable
See also:@*
@xref{uconvert}.@*
@xref{ustrtol}.@*
@xref{uatof}.@*
@node ustrerror, usprintf, ustrtod, Unicode
@subsection ustrerror
@ftable @asis
@item @t{const char *ustrerror(int err);}
This function returns a string that describes the error code `err', which
normally comes from the variable `errno'. Example:
@example

PACKFILE *input_file = pack_fopen("badname", "r");
if (input_file == NULL)
   allegro_message("%s\nSorry!\n", ustrerror(errno));@end example


Returns a pointer to a static string that should not be modified or
freed. If you make subsequent calls to ustrerror(), the string will be
overwritten.

@end ftable
See also:@*
@xref{uconvert}.@*
@xref{allegro_error}.@*
@node usprintf, uszprintf, ustrerror, Unicode
@subsection usprintf
@ftable @asis
@item @t{int usprintf(char *buf, const char *format, ...);}
This function writes formatted data into the output buffer. A NULL
character is written to mark the end of the string. You should try to avoid
this function because it is very easy to overflow the destination buffer.
Use uszprintf instead.

Returns the number of characters written, not including the terminating
null character.

@end ftable
See also:@*
@xref{uconvert}.@*
@xref{uszprintf}.@*
@xref{uvsprintf}.@*
@xref{exkeys}.@*
@node uszprintf, uvsprintf, usprintf, Unicode
@subsection uszprintf
@ftable @asis
@item @t{int uszprintf(char *buf, int size, const char *format, ...);}
This function writes formatted data into the output buffer, whose length
in bytes is specified by `size' and which is guaranteed to be NULL
terminated. Example:
@example

char buffer[10];
int player_score;
...
uszprintf(buffer, sizeof(buffer), "Your score is: %d", player_score);@end example


Returns the number of characters that would have been written without
eventual truncation (like with usprintf), not including the terminating
null character.

@end ftable
See also:@*
@xref{uconvert}.@*
@xref{usprintf}.@*
@xref{uvszprintf}.@*
@xref{exgui}.@*
@node uvsprintf, uvszprintf, uszprintf, Unicode
@subsection uvsprintf
@ftable @asis
@item @t{int uvsprintf(char *buf, const char *format, va_list args);}
This is like usprintf(), but you pass the variable argument list directly,
instead of the arguments themselves. You can use this function to implement
printf like functions, also called variadic functions. You should try to
avoid this function because it is very easy to overflow the destination
buffer. Use uvszprintf instead.

Returns the number of characters written, not including the terminating
null character.

@end ftable
See also:@*
@xref{uconvert}.@*
@xref{usprintf}.@*
@xref{uvszprintf}.@*
@node uvszprintf, set_config_file, uvsprintf, Unicode
@subsection uvszprintf
@ftable @asis
@item @t{int uvszprintf(char *buf, int size, const char *format, va_list args);}
This is like uszprintf(), but you pass the variable argument list
directly, instead of the arguments themselves. Example:
@example

#include <stdarg.h>

void log_message(const char *format, ...)
@{
   char buffer[100];
   va_list parameters;
   
   va_start(parameters, format);
   uvszprintf(buffer, sizeof(buffer), format, parameters);
   va_end(parameters);
   
   append_buffer_to_logfile(log_name, buffer);
   send_buffer_to_other_networked_players(multicast_ip, buffer);
   and_also_print_it_on_the_screen(cool_font, buffer);
@}

void some_other_function(void)
@{
   log_message("Hello %s, are you %d years old?\n", "Dave", 25);
@}@end example


Returns the number of characters that would have been written without
eventual truncation (like with uvsprintf), not including the terminating
null character.



@end ftable
See also:@*
@xref{uconvert}.@*
@xref{uszprintf}.@*
@xref{uvsprintf}.@*
@node Configuration, Mouse, Unicode, API
@section Configuration routines

Various parts of Allegro, such as the sound routines and the 
load_joystick_data() function, require some configuration information. This 
data is stored in text files as a collection of `variable=value' lines,
along with comments that begin with a `#' character and continue to the end
of the line. The configuration file may optionally be divided into sections, 
which begin with a `[sectionname]' line. Each section has a unique
namespace, to prevent variable name conflicts, but any variables that aren't 
in a section are considered to belong to all the sections simultaneously.

Note that variable and section names cannot contain spaces.

By default the configuration data is read from a file called `allegro.cfg',
which can be located either in the same directory as the program executable, 
or the directory pointed to by the ALLEGRO environment variable. Under Unix, 
it also checks for `~/allegro.cfg', `~/.allegrorc', `/etc/allegro.cfg', and
`/etc/allegrorc', in that order; under BeOS only the last two are also
checked. MacOS X also checks in the Contents/Resources directory of the
application bundle, if any, before doing the checks above.

If you don't like this approach, you can specify any filename you like, or
use a block of binary configuration data provided by your program (which
could for example be loaded from a datafile). You can also extend the paths
searched for allegro resources with set_allegro_resource_path().

You can store whatever custom information you like in the config file, along 
with the standard variables that are used by Allegro (see below). Allegro
comes with a setup directory where you can find configuration programs. The
standalone setup program is likely to be of interest to final users. It
allows any user to create an `allegro.cfg' file without the need to touch a
text editor and enter values by hand. It also provides a few basic tests like
sound playing for sound card testing. You are welcome to include the setup
program with your game, either as is or with modified graphics to fit better
your game.

@menu
* set_config_file::
* set_config_data::
* override_config_file::
* override_config_data::
* push_config_state::
* pop_config_state::
* flush_config_file::
* reload_config_texts::
* hook_config_section::
* config_is_hooked::
* get_config_string::
* get_config_int::
* get_config_hex::
* get_config_float::
* get_config_id::
* get_config_argv::
* get_config_text::
* set_config_string::
* set_config_int::
* set_config_hex::
* set_config_float::
* set_config_id::
* list_config_entries::
* list_config_sections::
* free_config_entries::
* Standard config variables::
@end menu
@node set_config_file, set_config_data, uvszprintf, Configuration
@subsection set_config_file
@ftable @asis
@item @t{void set_config_file(const char *filename);}
Sets the configuration file to be used by all subsequent config 
functions. If you don't call this function, Allegro will use the default 
`allegro.cfg' file, looking first in the same directory as your program
and then in the directory pointed to by the ALLEGRO environment variable
and the usual platform-specific paths for configuration files. For example
it will look for `/etc/allegro.cfg' under Unix.

All pointers returned by previous calls to get_config_string() and
other related functions are invalidated when you call this function!
You can call this function before install_allegro() to change the
configuration file, but after set_uformat() if you want to use a text 
encoding format other than the default.

@end ftable
See also:@*
@xref{set_config_data}.@*
@xref{override_config_file}.@*
@xref{push_config_state}.@*
@xref{set_uformat}.@*
@xref{Standard config variables}.@*
@xref{set_config_string}.@*
@xref{get_config_string}.@*
@xref{exconfig}.@*
@node set_config_data, override_config_file, set_config_file, Configuration
@subsection set_config_data
@ftable @asis
@item @t{void set_config_data(const char *data, int length);}
Specifies a block of data to be used by all subsequent config functions, 
which you have already loaded from disk (eg. as part of some more 
complicated format of your own, or in a grabber datafile). This routine 
makes a copy of the information, so you can safely free the data after 
calling it.

@end ftable
See also:@*
@xref{set_config_file}.@*
@xref{override_config_data}.@*
@xref{push_config_state}.@*
@xref{Standard config variables}.@*
@xref{set_config_string}.@*
@xref{get_config_string}.@*
@node override_config_file, override_config_data, set_config_data, Configuration
@subsection override_config_file
@ftable @asis
@item @t{void override_config_file(const char *filename);}
Specifies a file containing config overrides. These settings will be used 
in addition to the parameters in the main config file, and where a 
variable is present in both files this version will take priority. This 
can be used by application programmers to override some of the config 
settings from their code, while still leaving the main config file free 
for the end user to customise. For example, you could specify a 
particular sample frequency and IBK instrument file, but the user could 
still use an `allegro.cfg' file to specify the port settings and irq
numbers.

The override config file will not only take precedence when reading, but
will also be used for storing values. When you are done with using the
override config file, you can call override_config_file with a NULL
parameter, so config data will be directly read from the current config
file again.

Note: The override file is completely independent from the current
configuration. You can e.g. call set_config_file, and the override file
will still be active. Also the flush_config_file function will only affect
the current config file (which can be changed with set_config_file), never
the overriding one specified with this function. The modified override
config is written back to disk whenever you call override_config_file.

Example:
@example

override_config_file("my.cfg");
/* This will read from my.cfg, and if it doesn't find a
 * setting, will read from the current config file instead.
 */
language = get_config_string("system", "language", NULL);
/* This will always write to my.cfg, no matter if the
 * settings is already present or not.
 */
set_config_string("system", "language", "RU");
/* This forces the changed setting to be written back to
 * disk. Else it is written back at the next call to
 * override_config_file, or when Allegro shuts down.
 */
override_config_file(NULL);@end example


Note that this function and override_config_data() are mutually exclusive,
i.e. calling one will cancel the effects of the other.

@end ftable
See also:@*
@xref{override_config_data}.@*
@xref{set_config_file}.@*
@node override_config_data, push_config_state, override_config_file, Configuration
@subsection override_config_data
@ftable @asis
@item @t{void override_config_data(const char *data, int length);}
Version of override_config_file() which uses a block of data that has 
already been read into memory. The length of the block has to be specified
in bytes. Example:
@example

/* Force German as system language, Spanish keyboard map. */
const char *override_data = "[system]\n"
   "language=DE\n"
   "keyboard=ES";
override_config_data(override_data, ustrsize(override_data));@end example


Note that this function and override_config_file() are mutually exclusive,
i.e. calling one will cancel the effects of the other.

@end ftable
See also:@*
@xref{override_config_file}.@*
@xref{set_config_data}.@*
@node push_config_state, pop_config_state, override_config_data, Configuration
@subsection push_config_state
@ftable @asis
@item @t{void push_config_state();}
Pushes the current configuration state (filename, variable values, etc). 
onto an internal stack, allowing you to select some other config source 
and later restore the current settings by calling pop_config_state(). 
This function is mostly intended for internal use by other library 
functions, for example when you specify a config filename to the 
save_joystick_data() function, it pushes the config state before 
switching to the file you specified.

@end ftable
See also:@*
@xref{pop_config_state}.@*
@xref{set_config_file}.@*
@xref{save_joystick_data}.@*
@xref{exconfig}.@*
@node pop_config_state, flush_config_file, push_config_state, Configuration
@subsection pop_config_state
@ftable @asis
@item @t{void pop_config_state();}
Pops a configuration state previously stored by push_config_state(), 
replacing the current config source with it.

@end ftable
See also:@*
@xref{push_config_state}.@*
@xref{exconfig}.@*
@node flush_config_file, reload_config_texts, pop_config_state, Configuration
@subsection flush_config_file
@ftable @asis
@item @t{void flush_config_file();}
Writes the current config file to disk if the contents have changed 
since it was loaded or since the latest call to the function.

@end ftable
See also:@*
@xref{set_config_file}.@*
@xref{override_config_file}.@*
@xref{push_config_state}.@*
@node reload_config_texts, hook_config_section, flush_config_file, Configuration
@subsection reload_config_texts
@ftable @asis
@item @t{void reload_config_texts(const char *new_language);}
Reloads the translated strings returned by get_config_text(). This is
useful to switch to another language in your program at runtime. If you
want to modify the `[system]' language configuration variable yourself, or
you have switched configuration files, you will want to pass NULL to
just reload whatever language is currently selected. Or you can pass a
string containing the two letter code of the language you desire to
switch to, and the function will modify the language variable. After you
call this function, the previously returned pointers of get_config_text()
will be invalid. Example:
@example

...
/* The user selects French from a language choice menu. */
reload_config_texts("FR");@end example


@end ftable
See also:@*
@xref{get_config_text}.@*
@xref{get_config_string}.@*
@xref{Standard config variables}.@*
@node hook_config_section, config_is_hooked, reload_config_texts, Configuration
@subsection hook_config_section
@ftable @asis
@item @t{void hook_config_section(const char *section, int (*intgetter)(const char *name, int def), const char *(*stringgetter)(const char *name, const char *def), void (*stringsetter)(const char *name, const char *value));}
Takes control of the specified config file section, so that your hook 
functions will be used to manipulate it instead of the normal disk file 
access. If both the getter and setter functions are NULL, a currently 
present hook will be unhooked. Hooked functions have the highest 
priority. If a section is hooked, the hook will always be called, so you 
can also hook a '#' section: even override_config_file() cannot override 
a hooked section. Example:
@example

int decode_encrypted_int(const char *name, int def)
@{
   ...
@}

const char *decode_encrypted_string(const char *name, const char *def)
@{
   ...
@}

void encode_plaintext_string(const char *name, const char *value)
@{
   ...
@}

int main(int argc, char *argv[])
@{
   ...
   /* Make it harder for users to tinker with the high scores. */
   hook_config_section("high_scores", decode_encrypted_int,
      decode_encrypted_string, encode_plaintext_string);
   ...
@} END_OF_MAIN()@end example


@end ftable
See also:@*
@xref{config_is_hooked}.@*
@node config_is_hooked, get_config_string, hook_config_section, Configuration
@subsection config_is_hooked
@ftable @asis
@item @t{int config_is_hooked(const char *section);}
Returns TRUE if the specified config section has been hooked. Example:
@example

if (config_is_hooked("high_scores")) @{
   hook_config_section("high_scores, NULL, NULL, NULL);
@}@end example


@end ftable
See also:@*
@xref{hook_config_section}.@*
@node get_config_string, get_config_int, config_is_hooked, Configuration
@subsection get_config_string
@ftable @asis
@item @t{const char *get_config_string(const char *section, const char *name, const char *def);}
Retrieves a string variable from the current config file. The section name
may be set to NULL to read variables from the root of the file, or used to
control which set of parameters (eg. sound or joystick) you are interested
in reading. Example:
@example

const char *lang = get_config_string("system", "language", "EN");
@end example


Returns a pointer to the constant string found in the configuration file.
If the named variable cannot be found, or its entry in the config file is
empty, the value of `def' is returned.

@end ftable
See also:@*
@xref{set_config_file}.@*
@xref{set_config_string}.@*
@xref{get_config_argv}.@*
@xref{get_config_float}.@*
@xref{get_config_hex}.@*
@xref{get_config_int}.@*
@xref{get_config_id}.@*
@xref{get_config_text}.@*
@xref{exconfig}.@*
@node get_config_int, get_config_hex, get_config_string, Configuration
@subsection get_config_int
@ftable @asis
@item @t{int get_config_int(const char *section, const char *name, int def);}
Reads an integer variable from the current config file. See the comments 
about get_config_string().

@end ftable
See also:@*
@xref{set_config_file}.@*
@xref{set_config_int}.@*
@xref{get_config_string}.@*
@xref{get_config_argv}.@*
@xref{get_config_float}.@*
@xref{get_config_hex}.@*
@xref{get_config_id}.@*
@xref{exconfig}.@*
@node get_config_hex, get_config_float, get_config_int, Configuration
@subsection get_config_hex
@ftable @asis
@item @t{int get_config_hex(const char *section, const char *name, int def);}
Reads an integer variable from the current config file, in hexadecimal 
format. See the comments about get_config_string().

@end ftable
See also:@*
@xref{set_config_file}.@*
@xref{set_config_hex}.@*
@xref{get_config_string}.@*
@xref{get_config_argv}.@*
@xref{get_config_float}.@*
@xref{get_config_int}.@*
@xref{get_config_id}.@*
@node get_config_float, get_config_id, get_config_hex, Configuration
@subsection get_config_float
@ftable @asis
@item @t{float get_config_float(const char *section, const char *name, float def);}
Reads a floating point variable from the current config file. See the 
comments about get_config_string().

@end ftable
See also:@*
@xref{set_config_file}.@*
@xref{set_config_float}.@*
@xref{get_config_string}.@*
@xref{get_config_argv}.@*
@xref{get_config_hex}.@*
@xref{get_config_int}.@*
@xref{get_config_id}.@*
@node get_config_id, get_config_argv, get_config_float, Configuration
@subsection get_config_id
@ftable @asis
@item @t{int get_config_id(const char *section, const char *name, int def);}
Reads a 4-letter driver ID variable from the current config file. See the 
comments about get_config_string().

@end ftable
See also:@*
@xref{set_config_file}.@*
@xref{set_config_id}.@*
@xref{get_config_string}.@*
@xref{get_config_argv}.@*
@xref{get_config_float}.@*
@xref{get_config_hex}.@*
@xref{get_config_int}.@*
@node get_config_argv, get_config_text, get_config_id, Configuration
@subsection get_config_argv
@ftable @asis
@item @t{char **get_config_argv(const char *section, const char *name, int *argc);}
Reads a token list (words separated by spaces) from the current config
file. The token list is stored in a temporary buffer that will be clobbered
by the next call to get_config_argv(), so the data should not be expected
to persist.

Returns an argv style argument list and sets `argc' to the number of
retrieved tokens. If the variable is not present, returns NULL and sets 
argc to zero.

@end ftable
See also:@*
@xref{set_config_file}.@*
@xref{get_config_string}.@*
@xref{get_config_float}.@*
@xref{get_config_hex}.@*
@xref{get_config_int}.@*
@xref{get_config_id}.@*
@xref{exconfig}.@*
@node get_config_text, set_config_string, get_config_argv, Configuration
@subsection get_config_text
@ftable @asis
@item @t{const char *get_config_text(const char *msg);}
This function is primarily intended for use by internal library code, but 
it may perhaps be helpful to application programmers as well. It uses the 
`language.dat' or `XXtext.cfg' files (where XX is a language code) to look 
up a translated version of the parameter in the currently selected 
language.

This is basically the same thing as calling get_config_string() with 
`[language]' as the section, `msg' as the variable name, and `msg' as the 
default value, but it contains some special code to handle Unicode format 
conversions. The `msg' parameter is always given in ASCII format, but the 
returned string will be converted into the current text encoding, with 
memory being allocated as required, so you can assume that this pointer 
will persist without having to manually allocate storage space for each 
string.

Note that if you are planning on distributing your game on the Unix
platform there is a special issue with how to deal with the `language.dat'
file. Read section "Files shared by Allegro" of the chapter "Unix
specifics" to learn more about this.

Returns a suitable translation if one can be found or a copy of the 
parameter if nothing else is available. 

@end ftable
See also:@*
@xref{get_config_string}.@*
@xref{reload_config_texts}.@*
@xref{Standard config variables}.@*
@node set_config_string, set_config_int, get_config_text, Configuration
@subsection set_config_string
@ftable @asis
@item @t{void set_config_string(const char *section, const char *name, const char *val);}
Writes a string variable to the current config file, replacing any 
existing value it may have, or removes the variable if `val' is NULL. The
section name may be set to NULL to write the variable to the root of the 
file, or used to control which section the variable is inserted into. The 
altered file will be cached in memory, and not actually written to disk 
until you call allegro_exit(). Note that you can only write to files in 
this way, so the function will have no effect if the current config 
source was specified with set_config_data() rather than set_config_file().

As a special case, variable or section names that begin with a '#' 
character are treated specially and will not be read from or written to 
the disk. Addon packages can use this to store version info or other 
status information into the config module, from where it can be read with 
the get_config_string() function.

@end ftable
See also:@*
@xref{set_config_file}.@*
@xref{get_config_string}.@*
@xref{set_config_float}.@*
@xref{set_config_hex}.@*
@xref{set_config_int}.@*
@xref{set_config_id}.@*
@node set_config_int, set_config_hex, set_config_string, Configuration
@subsection set_config_int
@ftable @asis
@item @t{void set_config_int(const char *section, const char *name, int val);}
Writes an integer variable to the current config file. See the comments 
about set_config_string().

@end ftable
See also:@*
@xref{set_config_file}.@*
@xref{get_config_int}.@*
@xref{set_config_string}.@*
@xref{set_config_float}.@*
@xref{set_config_hex}.@*
@xref{set_config_id}.@*
@node set_config_hex, set_config_float, set_config_int, Configuration
@subsection set_config_hex
@ftable @asis
@item @t{void set_config_hex(const char *section, const char *name, int val);}
Writes an integer variable to the current config file, in hexadecimal 
format. See the comments about set_config_string().

@end ftable
See also:@*
@xref{set_config_file}.@*
@xref{get_config_hex}.@*
@xref{set_config_string}.@*
@xref{set_config_float}.@*
@xref{set_config_int}.@*
@xref{set_config_id}.@*
@node set_config_float, set_config_id, set_config_hex, Configuration
@subsection set_config_float
@ftable @asis
@item @t{void set_config_float(const char *section, const char *name, float val);}
Writes a floating point variable to the current config file. See the 
comments about set_config_string().

@end ftable
See also:@*
@xref{set_config_file}.@*
@xref{get_config_float}.@*
@xref{set_config_string}.@*
@xref{set_config_hex}.@*
@xref{set_config_int}.@*
@xref{set_config_id}.@*
@node set_config_id, list_config_entries, set_config_float, Configuration
@subsection set_config_id
@ftable @asis
@item @t{void set_config_id(const char *section, const char *name, int val);}
Writes a 4-letter driver ID variable to the current config file. See the
comments about set_config_string().

@end ftable
See also:@*
@xref{set_config_file}.@*
@xref{get_config_id}.@*
@xref{set_config_string}.@*
@xref{set_config_float}.@*
@xref{set_config_hex}.@*
@xref{set_config_int}.@*
@node list_config_entries, list_config_sections, set_config_id, Configuration
@subsection list_config_entries
@ftable @asis
@item @t{int list_config_entries(const char *section, const char ***names);}
This function can be used to get a list of all entries in the given config
section. The names parameter is a pointer to an array of strings. If it
points to a NULL pointer, the list will be allocated, else it will be
re-allocated. You should free the list again with free_config_entries if you
don't need it anymore, or you can pass it again to list_config_entries and
the memory will be re-used. See the following example for how you can use it,
it will print out the complete contents of the current configuration:
@example

int i, n;
char const **sections = NULL;
char const **entries = NULL;

/* List all entries not in any section. */
n = list_config_entries(NULL, &entries);
for (i = 0; i 
   printf(" %s=\"%s\"\n", entries[i], get_config_string(
          NULL, entries[i], "-"));

/* List all sections (and entries in them). */
n = list_config_sections(&sections);
/* loop through all section names */
for (i = 0; i 
@{
   int j, m;
   printf("%s\n", sections[i]);
   m = list_config_entries(sections[i], &entries);
   /* loop through all entries in the section */
   for (j = 0; j 
   @{
       printf(" %s=\"%s\"\n", entries[j], get_config_string(
          sections[i], entries[j], "-"));
   @}
@}
/* It is enough to free the arrays once at the end. */
free_config_entries(&sections);
free_config_entries(&entries);@end example


Returns the number of valid strings in the names array.

@end ftable
See also:@*
@xref{set_config_file}.@*
@xref{get_config_string}.@*
@xref{list_config_sections}.@*
@xref{free_config_entries}.@*
@node list_config_sections, free_config_entries, list_config_entries, Configuration
@subsection list_config_sections
@ftable @asis
@item @t{int list_config_sections(const char ***names);}
The names parameter is a pointer to an array of strings. If it points to a
NULL pointer, the list will be allocated, else it will be re-allocated. After
the function returns, it will contain the names of all sections in the
current configuration. Use free_config_entries to free the allocated memory
again. See list_config_entries for more information and an example how to use
it.

Returns the number of valid strings in the names array.

@end ftable
See also:@*
@xref{list_config_entries}.@*
@xref{set_config_file}.@*
@xref{get_config_string}.@*
@xref{free_config_entries}.@*
@node free_config_entries, Standard config variables, list_config_sections, Configuration
@subsection free_config_entries
@ftable @asis
@item @t{int free_config_entries(const char ***names);}

Once you are done with the string arrays filled in by list_config_entries and
list_config_sections, you can free them again with this function. The passed
array pointer will be set to NULL, and you directly can pass the same pointer
again to list_config_entries or list_config_sections later - but you also
could pass them again without freeing first, since the memory is re-allocated
when the pointer is not NULL.

See list_config_entries for an example of how to use it.

@end ftable
See also:@*
@xref{list_config_entries}.@*
@xref{list_config_sections}.@*
@node Standard config variables, install_mouse, free_config_entries, Configuration
@subsection Standard config variables
@ftable @asis
@end ftable
Allegro uses these standard variables from the configuration file:

@itemize @bullet
@item 
[system]@*
Section containing general purpose variables:

@itemize @bullet
@item 
system = x@*
Specifies which system driver to use. This is currently only useful on 
Linux, for choosing between the X-Windows ("XWIN") or console ("LNXC") 
modes.
@item 
keyboard = x@*
Specifies which keyboard layout to use. The parameter is the name of a 
keyboard mapping file produced by the keyconf utility, and can either be 
a fully qualified file path or a base name like `us' or `uk'. If the 
latter, Allegro will look first for a separate config file with that name 
(eg. `uk.cfg') and then for an object with that name in the `keyboard.dat'
file (eg. `UK_CFG'). The config file or `keyboard.dat' file can be stored 
in the same directory as the program, or in the location pointed to by 
the ALLEGRO environment variable. Look in the `keyboard.dat' file to see 
what mappings are currently available.
@item 
language = x@*
Specifies which language file to use for error messages and other bits of 
system text. The parameter is the name of a translation file, and can 
either be a fully qualified file path or a base name like `en' or `es'. If
the latter, Allegro will look first for a separate config file with a 
name in the form `entext.cfg', and then for an object with that name in 
the `language.dat' file (eg. `ENTEXT_CFG'). The config file or 
`language.dat' file can be stored in the same directory as the program, or 
in the location pointed to by the ALLEGRO environment variable.

Look in the `language.dat' file to see which mappings are currently
available. If there is none for your language, you can create it using the
English one as model, and even send it to the Allegro development team to
include it in future releases.
@item 
disable_screensaver = x@*
Specifies whether to disable the screensaver: 0 to never disable it, 1 to
disable it in fullscreen mode only and 2 to always disable it. Default is 1.
@item 
menu_opening_delay = x@*
Sets how long the menus take to auto-open. The time is given in
milliseconds (default is `300'). Specifying `-1' will disable the 
auto-opening feature.
@item 
XInitThreads = x@*
If this is set to 0, the X11 port will not call XInitThreads. This can have
slight performance advantages and was required on some broken X11 servers,
but it makes Allegro incompatible with other X11 libraries like Mesa.
@end itemize
@item 
[graphics]@*
Section containing graphics configuration information, using the
variables:

@itemize @bullet
@item 
gfx_card = x@*
Specifies which graphics driver to use when the program requests 
GFX_AUTODETECT. Multiple possible drivers can be suggested with extra 
lines in the form `gfx_card1 = x', `gfx_card2 = x', etc, or you can 
specify different drivers for each mode and color depth with variables in 
the form `gfx_card_24bpp = x', `gfx_card_640x480x16 = x', etc.
@item 
gfx_cardw = x@*
Specifies which graphics driver to use when the program requests 
GFX_AUTODETECT_WINDOWED. This variable functions exactly like
gfx_card in all other respects. If it is not set, Allegro will look
for the gfx_card variable.
@item 
disable_vsync = x@*
Specifies whether to disable synchronization with the vertical blank when
page-flipping (yes or no). Disabling synchronization may increase the
frame rate on slow systems, at the expense of introducing flicker on fast
systems.
@item 
vbeaf_driver = x@*
DOS and Linux only: specifies where to look for the VBE/AF driver 
(vbeaf.drv). If this variable is not set, Allegro will look in the same 
directory as the program, and then fall back on the standard locations 
(`c:\' for DOS, `/usr/local/lib', `/usr/lib', `/lib', and `/' for Linux, or 
the directory specified with the VBEAF_PATH environment variable).
@item 
framebuffer = x@*
Linux only: specifies what device file to use for the fbcon driver. If 
this variable is not set, Allegro checks the FRAMEBUFFER environment 
variable, and then defaults to `/dev/fb0'.
@item 
force_centering = x@*
Unix/X11 only: specifies whether to force window centering in fullscreen
mode when the XWFS driver is used (yes or no). Enabling this setting may
cause some artifacts to appear on KDE desktops.
@item 
disable_direct_updating = x@*
Windows only: specifies whether to disable direct updating when the 
GFX_DIRECTX_WIN driver is used in color conversion mode (yes or no).
Direct updating can cause artifacts to be left on the desktop when the 
window is moved or minimized; disabling it results in a significant
performance loss.
@end itemize
@item 
[mouse]@*
Section containing mouse configuration information, using the variables:

@itemize @bullet
@item 
mouse = x@*
Mouse driver type. Available DOS drivers are:
@example

MICK - mickey mode driver (normally the best)
I33  - int 0x33 callback driver
POLL - timer polling (for use under NT)
@end example

Linux console mouse drivers are:
@example

MS   - Microsoft serial mouse
IMS  - Microsoft serial mouse with Intellimouse extension
LPS2 - PS2 mouse
LIPS - PS2 mouse with Intellimouse extension
GPMD - GPM repeater data (Mouse Systems protocol)
EV   - Event interfaces (EVDEV)@end example

@item 
num_buttons = x@*
Sets the number of mouse buttons viewed by Allegro. You don't normally
need to set this variable because Allegro will autodetect it. You can only
use it to restrict the set of actual mouse buttons to zero or positive
values, negative values will be ignored.
@item 
emulate_three = x@*
Sets whether to emulate a third mouse button by detecting chords of the 
left and right buttons (yes or no). Defaults to no.
@item 
mouse_device = x@*
Linux only: specifies the name of the mouse device file (eg. 
`/dev/mouse').
@item 
ev_absolute = x@*
Linux only: specifies the mode for the default EV input:
0 - relative mode: pointer position changes if the input moves,
1 - absolute mode: pointer position is the input position.
If unspecified, the mode is relative.
If the device supports several tools (such as a graphic tablet), the
default input is the mouse. If the device has only one tool (e.g. a
normal mouse) the default input is this tool. All additional tools
work in absolute mode.
@item 
ev_min_x = x@*
ev_max_x = x@*
ev_min_y = x@*
ev_max_y = x@*
ev_min_z = x@*
ev_max_z = x@*
Linux only: for absolute EV inputs, minimum and maximum value. By default
this information is autodetected.  If you want to use only part of a
tablet, you need to set the entries for X and Y axis by hand.
@item 
ev_abs_to_rel_x = x@*
ev_abs_to_rel_y = x@*
ev_abs_to_rel_z = x@*
Linux only: scaling factor for tablet mouse speed.  Defaults to 1.
This is used only when the input sends absolute events (tablet, joystick,
etc.) and the cursor should behave like a mouse.
If you are using a mouse on a tablet, you need to set these entries
for X and Y axis (try numbers between 1 and 40).
@item 
mouse_accel_factor = x@*
Windows only: specifies the mouse acceleration factor. Defaults to 1.
Set it to 0 in order to disable mouse acceleration. 2 accelerates twice
as much as 1.
@end itemize
@item 
[sound]@*
Section containing sound configuration information, using the variables:

@itemize @bullet
@item 
digi_card = x@*
Sets the driver to use for playing digital samples.
@item 
midi_card = x@*
Sets the driver to use for MIDI music.
@item 
digi_input_card = x@*
Sets the driver to use for digital sample input.
@item 
midi_input_card = x@*
Sets the driver to use for MIDI data input.
@item 
digi_voices = x@*
Specifies the minimum number of voices to reserve for use by the digital 
sound driver. How many are possible depends on the driver.
@item 
midi_voices = x@*
Specifies the minimum number of voices to reserve for use by the MIDI 
sound driver. How many are possible depends on the driver.
@item 
digi_volume = x@*
Sets the volume for digital sample playback, from 0 to 255.
@item 
midi_volume = x@*
Sets the volume for midi music playback, from 0 to 255.
@item 
quality = x@*
Controls the sound quality vs. performance tradeoff for the sample mixing 
code. This can be set to any of the values:@example

0 - fast mixing of 8-bit data into 16-bit buffers
1 - true 16-bit mixing (requires a 16-bit stereo sound card)
2 - interpolated 16-bit mixing@end example

@item 
flip_pan = x@*
Toggling this between 0 and 1 reverses the left/right panning of samples, 
which might be needed because some SB cards get the stereo image the wrong
way round.
@item 
sound_freq = x@*
DOS, Unix and BeOS: sets the sample frequency. With the SB driver, 
possible rates are 11906 (any), 16129 (any), 22727 (SB 2.0 and above), 
and 45454 (only on SB 2.0 or SB16, not the stereo SB Pro driver). On the 
ESS Audiodrive, possible rates are 11363, 17046, 22729, or 44194. On the 
Ensoniq Soundscape, possible rates are 11025, 16000, 22050, or 48000. On 
the Windows Sound System, possible rates are 11025, 22050, 44100, or 
48000. Don't worry if you set some other number by mistake: Allegro will 
automatically round it to the closest supported frequency.
@item 
sound_bits = x@*
Unix and BeOS: sets the preferred number of bits (8 or 16).
@item 
sound_stereo = x@*
Unix and BeOS: selects mono or stereo output (0 or 1).
@item 
sound_port = x@*
DOS only: sets the sound card port address (this is usually 220).
@item 
sound_dma = x@*
DOS only: sets the sound card DMA channel (this is usually 1).
@item 
sound_irq = x@*
DOS only: sets the sound card IRQ number (this is usually 7).
@item 
fm_port = x@*
DOS only: sets the port address of the OPL synth (this is usually 388).
@item 
mpu_port = x@*
DOS only: sets the port address of the MPU-401 MIDI interface (this is 
usually 330).
@item 
mpu_irq = x@*
DOS only: sets the IRQ for the MPU-401 (this is usually the same as 
sound_irq).
@item 
ibk_file = x@*
DOS only: specifies the name of a .IBK file which will be used to replace 
the standard Adlib patch set.
@item 
ibk_drum_file = x@*
DOS only: specifies the name of a .IBK file which will be used to replace 
the standard set of Adlib percussion patches.
@item 
oss_driver = x@*
Unix only: sets the OSS device driver name. Usually `/dev/dsp' or 
`/dev/audio', but could be a particular device (e.g. `/dev/dsp2').
@item 
oss_numfrags = x@*
oss_fragsize = x@*
Unix only: sets number of OSS driver fragments (buffers) and size of each 
buffer in samples. Buffers are filled with data in the interrupts where 
interval between subsequent interrupts is not less than 10 ms. If 
hardware can play all information from buffers faster than 10 ms, then 
there will be clicks, when hardware have played all data and library has 
not prepared new data yet. On the other hand, if it takes too long for 
device driver to play data from all buffers, then there will be delays 
between action which triggers sound and sound itself.
@item 
oss_midi_driver = x@*
Unix only: sets the OSS MIDI device name. Usually `/dev/sequencer'.
@item 
oss_mixer_driver = x@*
Unix only: sets the OSS mixer device name. Usually `/dev/mixer'.
@item 
esd_server = x@*
Unix only: where to find the ESD (Enlightened Sound Daemon) server.
@item 
alsa_card = x@*
alsa_pcmdevice = x@*
Unix only: card number and PCM device for the ALSA 0.5 sound driver.
@item 
alsa_device = x@*
Unix only: device name for the ALSA 0.9 sound driver. The format is
<driver>[:<card>,<device>], for example: `hw:0,1'.
@item 
alsa_mixer_device = x@*
Unix only: mixer device name for the ALSA 0.9 sound driver. The
default is "default".
@item 
alsa_mixer_elem = x@*
Unix only: mixer element name for the ALSA 0.9 driver. The default
is PCM.
@item 
alsa_numfrags = x@*
Unix only: number of ALSA driver fragments (buffers).
@item 
alsa_fragsize = x@*
Unix only: size of each ALSA fragment, in samples.
@item 
alsa_rawmidi_card = x@*
Unix only: card number and device for the ALSA 0.5 midi driver.
@item 
alsa_rawmidi_device = x@*
Unix only: device for the ALSA 0.5 midi driver or device name for
the ALSA 0.9 midi driver (see alsa_device for the format).
@item 
jack_client_name = x@*
Sets the name with which Allegro should identify itself to the Jack
audio server.
@item 
jack_buffer_size = x@*
Forces a buffer size for the transfer buffer from Allegro's mixer
to Jack.
@item 
be_midi_quality = x@*
BeOS only: system MIDI synthesizer instruments quality. 0 uses low
quality 8-bit 11 kHz samples, 1 uses 16-bit 22 kHz samples.
@item 
be_midi_freq = x@*
BeOS only: MIDI sample mixing frequency in Hz. Can be 11025, 22050 or
44100.
@item 
be_midi_interpolation = x@*
BeOS only: specifies the MIDI samples interpolation method. 0 doesn't
interpolate, it's fast but has the worst quality; 1 does a fast
interpolation with better performances, but it's a bit slower than the
previous method; 2 does a linear interpolation between samples, it is the
slowest method but gives the best performances.
@item 
be_midi_reverb = x@*
BeOS only: reverberation intensity, from 0 to 5. 0 disables it, 5 is the
strongest one.
@item 
ca_midi_quality = x@*
MacOS X only: CoreAudio MIDI synthesizer rendering quality, from 0 to 127.
Higher qualities sound better but increase the CPU work load.
@item 
ca_midi_reverb = x@*
MacOS X only: CoreAudio MIDI synthesizer reverberation intensity, from 0
to 5. 0 equals to a small room (low reverb), 5 to a plate (high reverb).
@item 
patches = x@*
Specifies where to find the sample set for the DIGMID driver. This can 
either be a Gravis style directory containing a collection of .pat files 
and a `default.cfg' index, or an Allegro datafile produced by the pat2dat 
utility. If this variable is not set, Allegro will look either for a 
`default.cfg' or `patches.dat' file in the same directory as the program, 
the directory pointed to by the ALLEGRO environment variable, and the 
standard GUS directory pointed to by the ULTRASND environment variable.
@end itemize
@item 
[midimap]@*
If you are using the SB MIDI output or MPU-401 drivers with an external 
synthesiser that is not General MIDI compatible, you can use the midimap 
section of the config file to specify a patch mapping table for 
converting GM patch numbers into whatever bank and program change 
messages will select the appropriate sound on your synth. This is a real 
piece of self-indulgence. I have a Yamaha TG500, which has some great 
sounds but no GM patch set, and I just had to make it work somehow...

This section consists of a set of lines in the form:

@itemize @bullet
@item 
p<n> = bank0 bank1 prog pitch@*
With this statement, n is the GM program change number (1-128), bank0 and 
bank1 are the two bank change messages to send to your synth (on 
controllers #0 and #32), prog is the program change message to send to 
your synth, and pitch is the number of semitones to shift everything that 
is played with that sound. Setting the bank change numbers to -1 will 
prevent them from being sent.

For example, the line:
@example

p36 = 0 34 9 12
@end example

specifies that whenever GM program 36 (which happens to be a fretless 
bass) is selected, Allegro should send a bank change message #0 with a 
parameter of 0, a bank change message #32 with a parameter of 34, a 
program change with a parameter of 9, and then should shift everything up 
by an octave.
@end itemize
@item 
[joystick]@*
Section containing joystick configuration information, using the
variables:

@itemize @bullet
@item 
joytype = x@*
Specifies which joystick driver to use when the program requests 
JOY_TYPE_AUTODETECT.
@item 
joystick_device = x@*
BeOS and Linux only: specifies the name of the joystick device to be used
(as reported in the system joystick preferences under BeOS). The first
device found is used by default. If you want to specify the device for
each joystick, use variables of the form joystick_device_n, where n is
the joystick number.
@item 
throttle_axis = x@*
Linux only: sets the axis number the throttle is located at. This
variable will be used for every detected joystick. If you want to specify
the axis number for each joystick individually, use variables of the form
throttle_axis_n, where n is the joystick number.
@end itemize
@end itemize



See also:@*
@xref{set_config_file}.@*
@xref{set_config_string}.@*
@xref{get_config_string}.@*
@node Mouse, Timer, Configuration, API
@section Mouse routines

Allegro provides functions for reading the mouse state and displaying a mouse
cursor on-screen. You can read the absolute position of the mouse and the 
state of the mouse buttons from global variables. Additionally, you can read
the mouse position difference as mouse mickeys, which is the number of pixels
the cursor moved since the last time this information was read.

Allegro offers three ways to display the mouse cursor:

@itemize @bullet
@item 
Standard Allegro cursor@*
Allegro is responsible for drawing the mouse cursor from a timer. Use 
set_mouse_sprite() and show_mouse() to define your own cursor and display 
it on the screen.
You need to call scare_mouse()/unscare_mouse() to hide the mouse cursor
whenever you draw to the screen.
@item 
Custom operating system cursor (hardware cursor)@*
Allegro will let the operating system draw the mouse cursor. Use
set_mouse_sprite() and show_mouse() (or show_os_cursor) to define your
own cursor and display it on the screen. Not all graphics drivers are
capable of this and some may only be able to display cursors up to a
certain size. Allegro will fall back on its own cursor drawing if it
cannot let the OS handle this. On some platforms, the hardware cursor
is incompatible with get_mouse_mickeys() and it is therefor disabled by
default. In such cases you need to call enable_hardware_cursor() to
enable it explicitly.
@item 
Default operating system cursor@*
Allegro will not draw its own cursor, but use the operating system default
cursor. You can use the select_mouse_cursor() function to select the cursor
shape to display. As with custom operating system cursors, you need to call 
enable_hardware_cursor() before you can use this. Or you can use the
low level show_os_cursor() function.
@end itemize

Not all drivers will support all functionality. See the platform specific
information for more details.

@menu
* install_mouse::
* remove_mouse::
* poll_mouse::
* mouse_needs_poll::
* enable_hardware_cursor::
* disable_hardware_cursor::
* select_mouse_cursor::
* set_mouse_cursor_bitmap::
* mouse_x::
* mouse_sprite::
* show_mouse::
* scare_mouse::
* scare_mouse_area::
* unscare_mouse::
* show_os_cursor::
* freeze_mouse_flag::
* position_mouse::
* position_mouse_z::
* position_mouse_w::
* set_mouse_range::
* set_mouse_speed::
* set_mouse_sprite::
* set_mouse_sprite_focus::
* get_mouse_mickeys::
* mouse_callback::
@end menu
@node install_mouse, remove_mouse, Standard config variables, Mouse
@subsection install_mouse
@ftable @asis
@item @t{int install_mouse();}
Installs the Allegro mouse handler. You must do this before using any 
other mouse functions. 

Returns -1 on failure, zero if the mouse handler is already installed (in
which case this function does nothing) and the number of buttons on the
mouse if the mouse handler has successfully been installed (ie. this is
the first time a handler is installed or you have removed the previous
one).

Note that the number of mouse buttons returned by this function is more
an indication than a physical reality. With most devices there is no way
of telling how many buttons there are, and any user can override the
number of mouse buttons returned by this function with a custom
configuration file and the variable num_buttons. Even if this value is
overridden by the user, the global mouse variables will still report
whatever the hardware is sending.

@end ftable
See also:@*
@xref{remove_mouse}.@*
@xref{poll_mouse}.@*
@xref{mouse_x}.@*
@xref{show_mouse}.@*
@xref{get_mouse_mickeys}.@*
@xref{position_mouse}.@*
@xref{set_mouse_range}.@*
@xref{set_mouse_speed}.@*
@xref{Standard config variables}.@*
@xref{Available, Available Allegro examples}.@*
@node remove_mouse, poll_mouse, install_mouse, Mouse
@subsection remove_mouse
@ftable @asis
@item @t{void remove_mouse();}
Removes the mouse handler. You don't normally need to bother calling 
this, because allegro_exit() will do it for you.

@end ftable
See also:@*
@xref{install_mouse}.@*
@xref{allegro_exit}.@*
@node poll_mouse, mouse_needs_poll, remove_mouse, Mouse
@subsection poll_mouse
@ftable @asis
@item @t{int poll_mouse();}
Wherever possible, Allegro will read the mouse input asynchronously (ie. 
from inside an interrupt handler), but on some platforms that may not be 
possible, in which case you must call this routine at regular intervals 
to update the mouse state variables. To help you test your mouse polling 
code even if you are programming on a platform that doesn't require it, 
after the first time that you call this function Allegro will switch into 
polling mode, so from that point onwards you will have to call this 
routine in order to get any mouse input at all, regardless of whether the 
current driver actually needs to be polled or not. 

Returns zero on success, or a negative number on failure (ie. no mouse 
driver installed).

@end ftable
See also:@*
@xref{mouse_needs_poll}.@*
@xref{install_mouse}.@*
@xref{mouse_x}.@*
@xref{exlights}.@*
@xref{exmouse}.@*
@xref{exshade}.@*
@xref{exspline}.@*
@xref{extrans}.@*
@node mouse_needs_poll, enable_hardware_cursor, poll_mouse, Mouse
@subsection mouse_needs_poll
@ftable @asis
@item @t{int mouse_needs_poll();}
Returns TRUE if the current mouse driver is operating in polling mode.

@end ftable
See also:@*
@xref{poll_mouse}.@*
@xref{install_mouse}.@*
@xref{mouse_x}.@*
@node enable_hardware_cursor, disable_hardware_cursor, mouse_needs_poll, Mouse
@subsection enable_hardware_cursor
@ftable @asis
@item @t{void enable_hardware_cursor(void);}
After calling this function, Allegro will let the operating system draw the
mouse cursor instead of doing it itself. This is not possible with all
graphics drivers though: you'll need to check the gfx_capabilities flags
after calling show_mouse() to see if this works. On some platforms, enabling
the hardware cursor causes get_mouse_mickeys() to return only a limited
range of values, so you should not call this function if you need mouse 
mickeys.

@end ftable
See also:@*
@xref{install_mouse}.@*
@xref{show_mouse}.@*
@xref{set_mouse_sprite}.@*
@xref{get_mouse_mickeys}.@*
@xref{gfx_capabilities}.@*
@xref{disable_hardware_cursor}.@*
@xref{show_os_cursor}.@*
@xref{exsyscur}.@*
@node disable_hardware_cursor, select_mouse_cursor, enable_hardware_cursor, Mouse
@subsection disable_hardware_cursor
@ftable @asis
@item @t{void disable_hardware_cursor(void);}
After calling this function, Allegro will be responsible for drawing the
mouse cursor rather than the operating system. On some platforms calling
enable_hardware_cursor() makes the return values of get_mouse_mickeys()
unreliable. After calling this function, get_mouse_mickeys() returns 
reliable results again.

@end ftable
See also:@*
@xref{install_mouse}.@*
@xref{show_mouse}.@*
@xref{set_mouse_sprite}.@*
@xref{get_mouse_mickeys}.@*
@xref{gfx_capabilities}.@*
@xref{enable_hardware_cursor}.@*
@node select_mouse_cursor, set_mouse_cursor_bitmap, disable_hardware_cursor, Mouse
@subsection select_mouse_cursor
@ftable @asis
@item @t{void select_mouse_cursor(int cursor);}
This function allows you to use the operating system's native mouse
cursors rather than some custom cursor. You will need to enable this
functionality by calling enable_hardware_cursor() beforehand. If the
operating system does not support this functionality, or if it has
not been enabled, then Allegro will substitute its own cursor images.
You can change these substitute images using set_mouse_cursor_bitmap().

Note that the effects of this function are not apparent until show_mouse()
is called.

To know whether the operating system's native cursor is being used,
or if Allegro has made a substitution, you can check the GFX_SYSTEM_CURSOR
flag in gfx_capabilities after calling show_mouse().

The cursor argument selects the type of cursor to be displayed:

MOUSE_CURSOR_NONE@*
Selects an invisible mouse cursor. In that sense, it is similar to calling
show_mouse(NULL);

MOUSE_CURSOR_ALLEGRO@*
Selects the custom Allegro cursor, i.e. the one that you set with
set_mouse_sprite().

MOUSE_CURSOR_ARROW@*
The operating system default arrow cursor.

MOUSE_CURSOR_BUSY@*
The operating system default `busy' cursor (hourglass).

MOUSE_CURSOR_QUESTION@*
The operating system default `question' cursor (arrow with question mark).

MOUSE_CURSOR_EDIT@*
The operating system default `edit' cursor (vertical bar).

Example:
@example

/* initialize mouse sub-system */
install_mouse();
enable_hardware_cursor();

/* Set busy pointer */
select_mouse_cursor(MOUSE_CURSOR_BUSY);
show_mouse(screen);

/* Initialize stuff */
...

/* Set normal arrow pointer */
select_mouse_cursor(MOUSE_CURSOR_ARROW);
@end example


@end ftable
See also:@*
@xref{install_mouse}.@*
@xref{show_mouse}.@*
@xref{set_mouse_sprite}.@*
@xref{gfx_capabilities}.@*
@xref{enable_hardware_cursor}.@*
@xref{set_mouse_cursor_bitmap}.@*
@xref{show_os_cursor}.@*
@xref{exsyscur}.@*
@node set_mouse_cursor_bitmap, mouse_x, select_mouse_cursor, Mouse
@subsection set_mouse_cursor_bitmap
@ftable @asis
@item @t{void set_mouse_cursor_bitmap(int cursor, BITMAP *bmp);}
This function changes the cursor image Allegro uses if
select_mouse_cursor() is called but no native operating system cursor
can be used, e.g. because you did not call enable_hardware_cursor().

The cursor argument can be one of:@*
MOUSE_CURSOR_ALLEGRO@*
MOUSE_CURSOR_ARROW@*
MOUSE_CURSOR_BUSY@*
MOUSE_CURSOR_QUESTION@*
MOUSE_CURSOR_EDIT@*

but not MOUSE_CURSOR_NONE.

The bmp argument can either point to a valid bitmap or it can be NULL.
Passing a bitmap makes Allegro use that image in place of its own
default substitution (should the operating system's native cursor
be unavailable). The bitmap must remain available for the duration
in which it could be used. Passing NULL lets Allegro revert to its
default substitutions.

The effect of this function will not be apparent until show_mouse() is
called.

@end ftable
See also:@*
@xref{install_mouse}.@*
@xref{show_mouse}.@*
@xref{set_mouse_sprite}.@*
@xref{gfx_capabilities}.@*
@xref{enable_hardware_cursor}.@*
@xref{show_os_cursor}.@*
@xref{BITMAP}.@*
@node mouse_x, mouse_sprite, set_mouse_cursor_bitmap, Mouse
@subsection mouse_x
@ftable @asis
@item @t{extern volatile int mouse_x;}
@end ftable
@ftable @asis
@item @t{extern volatile int mouse_y;}
@end ftable
@ftable @asis
@item @t{extern volatile int mouse_z;}
@end ftable
@ftable @asis
@item @t{extern volatile int mouse_w;}
@end ftable
@ftable @asis
@item @t{extern volatile int mouse_b;}
@end ftable
@ftable @asis
@item @t{extern volatile int mouse_pos;}
Global variables containing the current mouse position and button state. 
Wherever possible these values will be updated asynchronously, but if 
mouse_needs_poll() returns TRUE, you must manually call poll_mouse() to 
update them with the current input state. The `mouse_x' and `mouse_y' 
positions are integers ranging from zero to the bottom right corner of 
the screen. The `mouse_z' and `mouse_w' variables hold the current vertical
and horizontal wheel position, when using an input driver that supports
wheel mice. The `mouse_b' variable is a bitfield indicating the state of
each button: bit 0 is the left button,  bit 1 the right, and bit 2 the
middle button. Additional non standard mouse buttons might be available
as higher bits in this variable. Usage example:
@example

if (mouse_b & 1)
   printf("Left button is pressed\n");

if (!(mouse_b & 2))
   printf("Right button is not pressed\n");
@end example

The `mouse_pos' variable has the current X coordinate in the upper 16 bits
and  the Y in the lower 16 bits. This may be useful in tight polling loops 
where a mouse interrupt could occur between your reading of the two
separate variables, since you can copy this value into a local variable
with a single instruction and then split it up at your leisure. Example:
@example

int pos, x, y;

pos = mouse_pos;
x = pos >> 16;
y = pos & 0x0000ffff;
@end example



@end ftable
See also:@*
@xref{install_mouse}.@*
@xref{poll_mouse}.@*
@xref{mouse_needs_poll}.@*
@xref{exalpha}.@*
@xref{exlights}.@*
@xref{exmouse}.@*
@xref{exshade}.@*
@xref{exspline}.@*
@xref{extrans}.@*
@node mouse_sprite, show_mouse, mouse_x, Mouse
@subsection mouse_sprite
@ftable @asis
@item @t{extern BITMAP *mouse_sprite;}
@end ftable
@ftable @asis
@item @t{extern int mouse_x_focus;}
@end ftable
@ftable @asis
@item @t{extern int mouse_y_focus;}
Global variables containing the current mouse sprite and the focus
point.  These are read-only, and only to be modified using the
set_mouse_sprite() and set_mouse_sprite_focus() functions.

@end ftable
See also:@*
@xref{set_mouse_sprite}.@*
@xref{set_mouse_sprite_focus}.@*
@xref{BITMAP}.@*
@node show_mouse, scare_mouse, mouse_sprite, Mouse
@subsection show_mouse
@ftable @asis
@item @t{void show_mouse(BITMAP *bmp);}
Tells Allegro to display a mouse pointer on the screen. This will only 
work if the timer module has been installed. The mouse pointer will be 
drawn onto the specified bitmap, which should normally be `screen' (see 
later for information about bitmaps). To hide the mouse pointer, call 
show_mouse(NULL). 

Warning: if you draw anything onto the screen while the pointer is 
visible, a mouse movement interrupt could occur in the middle of your 
drawing operation. If this happens the mouse buffering and graphics drawing
code will get confused and will leave 'mouse droppings' all over the 
screen. To prevent this, you must make sure you turn off the mouse 
pointer whenever you draw onto the screen. This is not needed if you are
using a hardware cursor.

Note: you must not be showing a mouse pointer on a bitmap at the time that
the bitmap is destroyed with destroy_bitmap(), e.g. call show_mouse(NULL);
before destroying the bitmap. This does not apply to `screen' since you
never destroy `screen' with destroy_bitmap().

@end ftable
See also:@*
@xref{install_mouse}.@*
@xref{install_timer}.@*
@xref{set_mouse_sprite}.@*
@xref{scare_mouse}.@*
@xref{freeze_mouse_flag}.@*
@xref{show_os_cursor}.@*
@xref{exmouse}.@*
@xref{expal}.@*
@xref{exshade}.@*
@xref{exspline}.@*
@xref{exsyscur}.@*
@xref{BITMAP}.@*
@node scare_mouse, scare_mouse_area, show_mouse, Mouse
@subsection scare_mouse
@ftable @asis
@item @t{void scare_mouse();}
Helper for hiding the mouse pointer prior to a drawing operation. This 
will temporarily get rid of the pointer, but only if that is really 
required (ie. the mouse is visible, and is displayed on the physical 
screen rather than some other memory surface, and it is not a hardware 
or OS cursor). The previous mouse state is stored for subsequent calls to 
unscare_mouse().

@end ftable
See also:@*
@xref{unscare_mouse}.@*
@xref{scare_mouse_area}.@*
@xref{show_mouse}.@*
@node scare_mouse_area, unscare_mouse, scare_mouse, Mouse
@subsection scare_mouse_area
@ftable @asis
@item @t{void scare_mouse_area(int x, int y, int w, int h);}
Like scare_mouse(), but will only hide the cursor if it is inside the 
specified rectangle. Otherwise the cursor will simply be frozen in place 
until you call unscare_mouse(), so it cannot interfere with your drawing.

@end ftable
See also:@*
@xref{unscare_mouse}.@*
@xref{scare_mouse}.@*
@xref{show_mouse}.@*
@node unscare_mouse, show_os_cursor, scare_mouse_area, Mouse
@subsection unscare_mouse
@ftable @asis
@item @t{void unscare_mouse();}
Undoes the effect of a previous call to scare_mouse() or 
scare_mouse_area(), restoring the original pointer state.

@end ftable
See also:@*
@xref{scare_mouse}.@*
@xref{scare_mouse_area}.@*
@node show_os_cursor, freeze_mouse_flag, unscare_mouse, Mouse
@subsection show_os_cursor
@ftable @asis
@item @t{int show_os_cursor(int cursor);}
In case you do not need Allegro's mouse cursor API, which automatically
emulates a cursor in software if no other cursor is available, you can
use this low level function to try to display or hide the system cursor
directly. The cursor parameter takes the same values as
select_mouse_cursor. This function is very similar to calling
enable_hardware_cursor, select_mouse_cursor and show_mouse, but will
not try to do anything if no system cursor is available.

The most common use for this function is to just call it once at the
beginning of the program to tell it to display the system cursor inside
the Allegro window. The return value can be used to see if this
succeeded or not. On some systems (e.g. DirectX fullscreen) this is not
supported and the function will always fail, and in other cases only
some of the cursors will work, or in the case of MOUSE_CURSOR_ALLEGRO,
only certain bitmap sizes may be supported.

You never should use show_os_cursor together with the function
show_mouse and other functions affecting it (select_mouse_cursor,
enable_hardware_cursor, disable_hardware_cursor, scare_mouse,
unscare_mouse). They implement the standard high level mouse API, and
don't work together with this low level function.

Returns 0 if a system cursor is being displayed after the function
returns, or -1 otherwise.

@end ftable
See also:@*
@xref{show_mouse}.@*
@xref{set_mouse_cursor_bitmap}.@*
@xref{select_mouse_cursor}.@*
@node freeze_mouse_flag, position_mouse, show_os_cursor, Mouse
@subsection freeze_mouse_flag
@ftable @asis
@item @t{extern volatile int freeze_mouse_flag;}
If this flag is set, the mouse pointer won't be redrawn when the mouse 
moves. This can avoid the need to hide the pointer every time you draw to 
the screen, as long as you make sure your drawing doesn't overlap with 
the current pointer position.

@end ftable
See also:@*
@xref{show_mouse}.@*
@node position_mouse, position_mouse_z, freeze_mouse_flag, Mouse
@subsection position_mouse
@ftable @asis
@item @t{void position_mouse(int x, int y);}
Moves the mouse to the specified screen position. It is safe to call even 
when a mouse pointer is being displayed.

@end ftable
See also:@*
@xref{install_mouse}.@*
@xref{position_mouse_z}.@*
@xref{set_mouse_range}.@*
@xref{set_mouse_speed}.@*
@xref{position_mouse_w}.@*
@node position_mouse_z, position_mouse_w, position_mouse, Mouse
@subsection position_mouse_z
@ftable @asis
@item @t{void position_mouse_z(int z);}
Sets the mouse wheel position variable to the specified value.

@end ftable
See also:@*
@xref{install_mouse}.@*
@xref{position_mouse}.@*
@xref{position_mouse_w}.@*
@node position_mouse_w, set_mouse_range, position_mouse_z, Mouse
@subsection position_mouse_w
@ftable @asis
@item @t{void position_mouse_w(int w);}
Sets the horizontal mouse wheel position to the specified value.

@end ftable
See also:@*
@xref{install_mouse}.@*
@xref{position_mouse}.@*
@node set_mouse_range, set_mouse_speed, position_mouse_w, Mouse
@subsection set_mouse_range
@ftable @asis
@item @t{void set_mouse_range(int x1, int y1, int x2, int y2);}
Sets the area of the screen within which the mouse can move. Pass the top 
left corner and the bottom right corner (inclusive). If you don't call 
this function the range defaults to (0, 0, SCREEN_W-1, SCREEN_H-1).

@end ftable
See also:@*
@xref{install_mouse}.@*
@xref{set_mouse_speed}.@*
@xref{position_mouse}.@*
@node set_mouse_speed, set_mouse_sprite, set_mouse_range, Mouse
@subsection set_mouse_speed
@ftable @asis
@item @t{void set_mouse_speed(int xspeed, int yspeed);}
Sets the mouse speed. Larger values of xspeed and yspeed represent slower 
mouse movement: the default for both is 2.

@end ftable
See also:@*
@xref{install_mouse}.@*
@xref{set_mouse_range}.@*
@xref{position_mouse}.@*
@node set_mouse_sprite, set_mouse_sprite_focus, set_mouse_speed, Mouse
@subsection set_mouse_sprite
@ftable @asis
@item @t{void set_mouse_sprite(BITMAP *sprite);}
You don't like Allegro's mouse pointer? No problem. Use this function to
supply an alternative of your own. If you change the pointer and then want
to get Allegro's lovely arrow back again, call set_mouse_sprite(NULL).

As a bonus, set_mouse_sprite(NULL) uses the current palette in choosing
colors for the arrow. So if your arrow mouse sprite looks ugly after
changing the palette, call set_mouse_sprite(NULL).

@end ftable
See also:@*
@xref{install_mouse}.@*
@xref{show_mouse}.@*
@xref{set_mouse_sprite_focus}.@*
@xref{exmouse}.@*
@xref{BITMAP}.@*
@node set_mouse_sprite_focus, get_mouse_mickeys, set_mouse_sprite, Mouse
@subsection set_mouse_sprite_focus
@ftable @asis
@item @t{void set_mouse_sprite_focus(int x, int y);}
The mouse focus is the bit of the pointer that represents the actual 
mouse position, ie. the (mouse_x, mouse_y) position. By default this is 
the top left corner of the arrow, but if you are using a different mouse 
pointer you might need to alter it.

@end ftable
See also:@*
@xref{set_mouse_sprite}.@*
@xref{exmouse}.@*
@node get_mouse_mickeys, mouse_callback, set_mouse_sprite_focus, Mouse
@subsection get_mouse_mickeys
@ftable @asis
@item @t{void get_mouse_mickeys(int *mickeyx, int *mickeyy);}
Measures how far the mouse has moved since the last call to this 
function. The values of mickeyx and mickeyy will become negative if the 
mouse is moved left or up, respectively. The mouse will continue to 
generate movement mickeys even when it reaches the edge of the screen, so 
this form of input can be useful for games that require an infinite range 
of mouse movement.

Note that the infinite movement may not work in windowed mode, since under 
some platforms the mouse would leave the window, and may not work at all 
if the hardware cursor is in use.

@end ftable
See also:@*
@xref{install_mouse}.@*
@xref{exmouse}.@*
@node mouse_callback, install_timer, get_mouse_mickeys, Mouse
@subsection mouse_callback
@ftable @asis
@item @t{extern void (*mouse_callback)(int flags);}
Called by the interrupt handler whenever the mouse moves or one of the 
buttons changes state. This function must be in locked memory, and must 
execute _very_ quickly! It is passed the event flags that triggered the 
call, which is a bitmask containing any of the values MOUSE_FLAG_MOVE, 
MOUSE_FLAG_LEFT_DOWN, MOUSE_FLAG_LEFT_UP, MOUSE_FLAG_RIGHT_DOWN, 
MOUSE_FLAG_RIGHT_UP, MOUSE_FLAG_MIDDLE_DOWN, MOUSE_FLAG_MIDDLE_UP, and 
MOUSE_FLAG_MOVE_Z. Note that even if the mouse has more than three buttons,
only the first three can be trapped using a callback.



@end ftable
See also:@*
@xref{install_mouse}.@*
@node Timer, Keyboard, Mouse, API
@section Timer routines

Allegro can set up several virtual timer functions, all going at different
speeds.

Under DOS it will constantly reprogram the clock to make sure they are all
called at the correct times. Because they alter the low level timer chip
settings, these routines should not be used together with other DOS timer
functions like the DJGPP uclock() routine. Moreover, the FPU state is not
preserved across Allegro interrupts so you ought not to use floating point
or MMX code inside timer interrupt handlers.

Under other platforms, they are usually implemented using threads, which run
parallel to the main thread. Therefore timer callbacks on such platforms
will not block the main thread when called, so you may need to use
appropriate synchronisation devices (eg. mutexes, semaphores, etc.) when
accessing data that is shared by a callback and the main thread. (Currently
Allegro does not provide such devices.)

@menu
* install_timer::
* remove_timer::
* install_int::
* install_int_ex::
* LOCK_VARIABLE::
* LOCK_FUNCTION::
* END_OF_FUNCTION::
* remove_int::
* install_param_int::
* install_param_int_ex::
* remove_param_int::
* retrace_count::
* rest::
* rest_callback::
@end menu
@node install_timer, remove_timer, mouse_callback, Timer
@subsection install_timer
@ftable @asis
@item @t{int install_timer();}
Installs the Allegro timer interrupt handler. You must do this before 
installing any user timer routines, and also before displaying a mouse 
pointer, playing FLI animations or MIDI music, and using any of the GUI 
routines.

Returns zero on success, or a negative number on failure (but you may
decide not to check the return value as this function is very unlikely to
fail).

@end ftable
See also:@*
@xref{remove_timer}.@*
@xref{install_int}.@*
@xref{Available, Available Allegro examples}.@*
@node remove_timer, install_int, install_timer, Timer
@subsection remove_timer
@ftable @asis
@item @t{void remove_timer();}
Removes the Allegro timer handler (and, under DOS, passes control of the
clock back to the operating system). You don't normally need to bother
calling this, because allegro_exit() will do it for you.

@end ftable
See also:@*
@xref{install_timer}.@*
@xref{allegro_exit}.@*
@node install_int, install_int_ex, remove_timer, Timer
@subsection install_int
@ftable @asis
@item @t{int install_int(void (*proc)(), int speed);}
Installs a user timer handler, with the speed given as the number of 
milliseconds between ticks. This is the same thing as 
install_int_ex(proc, MSEC_TO_TIMER(speed)). If you call this routine 
without having first installed the timer module, install_timer() will be 
called automatically. Calling again this routine with the same timer
handler as parameter allows you to adjust its speed.

Returns zero on success, or a negative number if there is no room to add
a new user timer.

@end ftable
See also:@*
@xref{install_timer}.@*
@xref{remove_int}.@*
@xref{install_int_ex}.@*
@xref{install_param_int}.@*
@xref{exscn3d}.@*
@xref{exswitch}.@*
@xref{extimer}.@*
@xref{exzbuf}.@*
@node install_int_ex, LOCK_VARIABLE, install_int, Timer
@subsection install_int_ex
@ftable @asis
@item @t{int install_int_ex(void (*proc)(), int speed);}
Adds a function to the list of user timer handlers or, if it is already 
installed, retroactively adjusts its speed (i.e makes as though the speed
change occurred precisely at the last tick). The speed is given in hardware
clock ticks, of which there are 1193181 a second. You can convert from 
other time formats to hardware clock ticks with the macros:
@example

SECS_TO_TIMER(secs)  - give the number of seconds between
                       each tick
MSEC_TO_TIMER(msec)  - give the number of milliseconds
                       between ticks
BPS_TO_TIMER(bps)    - give the number of ticks each second
BPM_TO_TIMER(bpm)    - give the number of ticks per minute
@end example

There can only be sixteen timers in use at a time, and some other parts of
Allegro (the GUI code, the mouse pointer display routines, rest(), the FLI
player, and the MIDI player) need to install handlers of their own, so you
should avoid using too many at the same time. If you call this routine
without having first installed the timer module, install_timer() will be
called automatically.

Your function will be called by the Allegro interrupt handler and not 
directly by the processor, so it can be a normal C function and does not 
need a special wrapper. You should be aware, however, that it will be 
called in an interrupt context, which imposes a lot of restrictions on 
what you can do in it. It should not use large amounts of stack, it must 
not make any calls to the operating system, use C library functions, or 
contain any floating point code, and it must execute very quickly. Don't 
try to do lots of complicated code in a timer handler: as a general rule 
you should just set some flags and respond to these later in your main 
control loop.

In a DOS protected mode environment like DJGPP, memory is virtualised and 
can be swapped to disk. Due to the non-reentrancy of DOS, if a disk swap 
occurs inside an interrupt handler the system will die a painful death, 
so you need to make sure you lock all the memory (both code and data) 
that is touched inside timer routines. Allegro will lock everything it 
uses, but you are responsible for locking your handler functions. The 
macros LOCK_VARIABLE (variable), END_OF_FUNCTION (function_name),
END_OF_STATIC_FUNCTION (function_name), and LOCK_FUNCTION (function_name)
can be used to simplify this task. For example, if you want an interrupt 
handler that increments a counter variable, you should write:
@example

volatile int counter;

void my_timer_handler()
@{
   counter++;
@}

END_OF_FUNCTION(my_timer_handler)
@end example

and in your initialisation code you should lock the memory:
@example

LOCK_VARIABLE(counter);
LOCK_FUNCTION(my_timer_handler);
@end example

Obviously this can get awkward if you use complicated data structures and 
call other functions from within your handler, so you should try to keep 
your interrupt routines as simple as possible.

Returns zero on success, or a negative number if there is no room to add
a new user timer.

@end ftable
See also:@*
@xref{install_timer}.@*
@xref{remove_int}.@*
@xref{install_int}.@*
@xref{install_param_int_ex}.@*
@xref{excamera}.@*
@xref{exsprite}.@*
@xref{extimer}.@*
@xref{exunicod}.@*
@xref{exupdate}.@*
@node LOCK_VARIABLE, LOCK_FUNCTION, install_int_ex, Timer
@subsection LOCK_VARIABLE
@ftable @asis
@item @t{Macro LOCK_VARIABLE(variable_name);}
Due to interrupts, you are required to lock all the memory used by your
timer routines. See the description of install_int_ex() for a more
detailed explanation and usage example.

@end ftable
See also:@*
@xref{install_int}.@*
@xref{install_int_ex}.@*
@xref{exscn3d}.@*
@xref{exsprite}.@*
@xref{exswitch}.@*
@xref{extimer}.@*
@xref{exupdate}.@*
@xref{exzbuf}.@*
@node LOCK_FUNCTION, END_OF_FUNCTION, LOCK_VARIABLE, Timer
@subsection LOCK_FUNCTION
@ftable @asis
@item @t{Macro LOCK_FUNCTION(function_name);}
Due to interrupts, you are required to lock all the memory used by your
timer routines. See the description of install_int_ex() for a more
detailed explanation and usage example.

@end ftable
See also:@*
@xref{install_int}.@*
@xref{install_int_ex}.@*
@xref{exkeys}.@*
@xref{exscn3d}.@*
@xref{exsprite}.@*
@xref{exswitch}.@*
@xref{extimer}.@*
@xref{exupdate}.@*
@xref{exzbuf}.@*
@node END_OF_FUNCTION, remove_int, LOCK_FUNCTION, Timer
@subsection END_OF_FUNCTION
@ftable @asis
@item @t{Macro END_OF_FUNCTION(function_name);}
Due to interrupts, you are required to lock all the code used by your
timer routines. See the description of install_int_ex() for a more
detailed explanation and usage example.

@end ftable
See also:@*
@xref{install_int}.@*
@xref{install_int_ex}.@*
@xref{exkeys}.@*
@xref{exscn3d}.@*
@xref{exsprite}.@*
@xref{exswitch}.@*
@xref{extimer}.@*
@xref{exupdate}.@*
@xref{exzbuf}.@*
@node remove_int, install_param_int, END_OF_FUNCTION, Timer
@subsection remove_int
@ftable @asis
@item @t{void remove_int(void (*proc)());}
Removes a function from the list of user interrupt routines. At program 
termination, allegro_exit() does this automatically.

@end ftable
See also:@*
@xref{install_int}.@*
@xref{install_int_ex}.@*
@xref{remove_param_int}.@*
@node install_param_int, install_param_int_ex, remove_int, Timer
@subsection install_param_int
@ftable @asis
@item @t{int install_param_int(void (*proc)(void *), void *param, int speed);}
Like install_int(), but the callback routine will be passed a copy of the 
specified void pointer parameter. To disable the handler, use 
remove_param_int() instead of remove_int().

@end ftable
See also:@*
@xref{install_timer}.@*
@xref{remove_param_int}.@*
@xref{install_param_int_ex}.@*
@xref{install_int}.@*
@node install_param_int_ex, remove_param_int, install_param_int, Timer
@subsection install_param_int_ex
@ftable @asis
@item @t{int install_param_int_ex(void (*proc)(void *), void *param, int speed);}
Like install_int_ex(), but the callback routine will be passed a copy of 
the specified void pointer parameter. To disable the handler, use 
remove_param_int() instead of remove_int().

@end ftable
See also:@*
@xref{install_timer}.@*
@xref{remove_param_int}.@*
@xref{install_param_int}.@*
@xref{install_int_ex}.@*
@node remove_param_int, retrace_count, install_param_int_ex, Timer
@subsection remove_param_int
@ftable @asis
@item @t{void remove_param_int(void (*proc)(void *), void *param);}
Like remove_int(), but for use with timer callbacks that have parameter 
values. If there is more than one copy of the same callback active at a 
time, it identifies which one to remove by checking the parameter value 
(so you can't have more than one copy of a handler using an identical 
parameter).

@end ftable
See also:@*
@xref{install_param_int}.@*
@xref{install_param_int_ex}.@*
@xref{remove_int}.@*
@node retrace_count, rest, remove_param_int, Timer
@subsection retrace_count
@ftable @asis
@item @t{extern volatile int retrace_count;}
If the retrace simulator is installed, this count is incremented on each
vertical retrace; otherwise, if the refresh rate is known, the count is
incremented at the same rate (ignoring retraces); otherwise, it is
incremented 70 times a second. This provides a way of controlling
the speed of your program without installing user timer functions.

@end ftable
See also:@*
@xref{ex3d}.@*
@xref{exblend}.@*
@xref{exdbuf}.@*
@xref{exflip}.@*
@xref{exlights}.@*
@node rest, rest_callback, retrace_count, Timer
@subsection rest
@ftable @asis
@item @t{void rest(unsigned int time);}
This function waits for the specified number of milliseconds.

Passing 0 as parameter will not wait, but just yield. This can be useful
in order to "play nice" with other processes. Other values will cause
CPU time to be dropped on most platforms. This will look better to
users, and also does things like saving battery power and making fans
less noisy.

Note that calling this inside your active game loop is a bad idea, as
you never know when the OS will give you the CPU back, so you could end
up missing the vertical retrace and skipping frames. On the other hand,
on multitasking operating systems it is good form to give up the CPU for
a while if you will not be using it.

@end ftable
See also:@*
@xref{install_timer}.@*
@xref{rest_callback}.@*
@xref{vsync}.@*
@xref{d_yield_proc}.@*
@xref{exkeys}.@*
@xref{exmidi}.@*
@xref{exquat}.@*
@xref{exsample}.@*
@xref{exsprite}.@*
@xref{extimer}.@*
@xref{extrans}.@*
@xref{exunicod}.@*
@node rest_callback, install_keyboard, rest, Timer
@subsection rest_callback
@ftable @asis
@item @t{void rest_callback(long time, void (*callback)())}
Like rest(), but for non-zero values continually calls the specified
function while it is waiting for the required time to elapse. If the
provided `callback' parameter is NULL, this function does exactly the
same thing as calling rest().



@end ftable
See also:@*
@xref{install_timer}.@*
@xref{rest}.@*
@node Keyboard, Joystick, Timer, API
@section Keyboard routines

The Allegro keyboard handler provides both buffered input and a set of flags 
storing the current state of each key. Note that it is not possible to 
correctly detect every combination of keys, due to the design of the PC 
keyboard. Up to two or three keys at a time will work fine, but if you press 
more than that the extras are likely to be ignored (exactly which 
combinations are possible seems to vary from one keyboard to another).

On DOS, Allegro requires the user to specify the language of the keyboard
mapping because it is impossible to obtain this information from the OS,
otherwise the default US keyboard mapping will be used. Allegro comes with a
prepackaged `keyboard.dat' file which you can put along with your binary. If
this file is present, Allegro will be able to extract the keyboard mapping
information stored there. However, the end user still needs to select which
keyboard mapping to use. This can be accomplished through the keyboard variable
of the system section in a standard `allegro.cfg' configuration file. Read
chapter "Configuration routines" for more information about this.

@menu
* install_keyboard::
* remove_keyboard::
* install_keyboard_hooks::
* poll_keyboard::
* keyboard_needs_poll::
* key::
* key_shifts::
* keypressed::
* readkey::
* ureadkey::
* scancode_to_ascii::
* scancode_to_name::
* simulate_keypress::
* simulate_ukeypress::
* keyboard_callback::
* keyboard_ucallback::
* keyboard_lowlevel_callback::
* set_leds::
* set_keyboard_rate::
* clear_keybuf::
* three_finger_flag::
* key_led_flag::
@end menu
@node install_keyboard, remove_keyboard, rest_callback, Keyboard
@subsection install_keyboard
@ftable @asis
@item @t{int install_keyboard();}
Installs the Allegro keyboard interrupt handler. You must call this 
before using any of the keyboard input routines. Once you have set up the 
Allegro handler, you can no longer use operating system calls or C 
library functions to access the keyboard.

Note that on some platforms the keyboard won't work unless you have set a
graphics mode, even if this function returns a success value before
calling set_gfx_mode. This can happen in environments with graphic
windowed modes, since Allegro usually reads the keyboard through the
graphical window (which appears after the set_gfx_mode call). Example:
@example

allegro_init();
install_timer();
install_keyboard();
/* We are not 100% sure we can read the keyboard yet! */
if (set_gfx_mode(GFX_AUTODETECT, 640, 480, 0, 0) != 0)
   abort_on_error("Couldn't set graphic mode!");

/* Now we are guaranteed to be able to read the keyboard. */
readkey();@end example


Returns zero on success, or a negative number on failure (but you may
decide not to check the return value as this function is very unlikely to
fail).

@end ftable
See also:@*
@xref{remove_keyboard}.@*
@xref{poll_keyboard}.@*
@xref{key}.@*
@xref{keypressed}.@*
@xref{readkey}.@*
@xref{ureadkey}.@*
@xref{keyboard_callback}.@*
@xref{keyboard_ucallback}.@*
@xref{keyboard_lowlevel_callback}.@*
@xref{three_finger_flag}.@*
@xref{key_led_flag}.@*
@xref{set_leds}.@*
@xref{set_keyboard_rate}.@*
@xref{set_gfx_mode}.@*
@xref{Standard config variables}.@*
@xref{Available, Available Allegro examples}.@*
@node remove_keyboard, install_keyboard_hooks, install_keyboard, Keyboard
@subsection remove_keyboard
@ftable @asis
@item @t{void remove_keyboard();}
Removes the keyboard handler, returning control to the operating system. 
You don't normally need to bother calling this, because allegro_exit() 
will do it for you. However, you might want to call this during runtime if
you want to change the keyboard mapping on those platforms were keyboard
mappings are needed. You would first modify the configuration variable
holding the keyboard mapping and then reinstall the keyboard handler.
Example:
@example

remove_keyboard();
/* Switch to Spanish keyboard mapping. */
set_config_string("system", "keyboard", "es");
install_keyboard();@end example


@end ftable
See also:@*
@xref{install_keyboard}.@*
@xref{allegro_exit}.@*
@xref{set_config_string}.@*
@node install_keyboard_hooks, poll_keyboard, remove_keyboard, Keyboard
@subsection install_keyboard_hooks
@ftable @asis
@item @t{void install_keyboard_hooks(int (*keypressed)(), int (*readkey)());}
You should only use this function if you *aren't* using the rest of the 
keyboard handler. It should be called in the place of install_keyboard(), 
and lets you provide callback routines to detect and read keypresses, 
which will be used by the main keypressed() and readkey() functions. This 
can be useful if you want to use Allegro's GUI code with a custom 
keyboard handler, as it provides a way for the GUI to get keyboard input 
from your own code, bypassing the normal Allegro input system.

@end ftable
See also:@*
@xref{install_keyboard}.@*
@xref{keypressed}.@*
@xref{readkey}.@*
@node poll_keyboard, keyboard_needs_poll, install_keyboard_hooks, Keyboard
@subsection poll_keyboard
@ftable @asis
@item @t{int poll_keyboard();}
Wherever possible, Allegro will read the keyboard input asynchronously 
(ie. from inside an interrupt handler), but on some platforms that may 
not be possible, in which case you must call this routine at regular 
intervals to update the keyboard state variables.

To help you test your keyboard polling code even if you are programming
on a platform that doesn't require it, after the first time that you
call this function Allegro will switch into polling mode, so from that
point onwards you will have to call this routine in order to get any
keyboard input at all, regardless of whether the current driver actually
needs to be polled or not.

The keypressed(), readkey(), and ureadkey() functions call poll_keyboard()
automatically, so you only need to use this function when accessing the
key[] array and key_shifts variable.

Returns zero on success, or a negative number on failure (ie. no keyboard
driver installed).

@end ftable
See also:@*
@xref{keyboard_needs_poll}.@*
@xref{install_keyboard}.@*
@xref{key}.@*
@xref{key_shifts}.@*
@xref{excamera}.@*
@xref{exsample}.@*
@xref{exstars}.@*
@node keyboard_needs_poll, key, poll_keyboard, Keyboard
@subsection keyboard_needs_poll
@ftable @asis
@item @t{int keyboard_needs_poll();}
Returns TRUE if the current keyboard driver is operating in polling mode.

@end ftable
See also:@*
@xref{poll_keyboard}.@*
@xref{install_keyboard}.@*
@xref{key}.@*
@node key, key_shifts, keyboard_needs_poll, Keyboard
@subsection key
@ftable @asis
@item @t{extern volatile char key[KEY_MAX];}
Array of flags indicating the state of each key, ordered by scancode. 
Wherever possible these values will be updated asynchronously, but if 
keyboard_needs_poll() returns TRUE, you must manually call 
poll_keyboard() to update them with the current input state. The 
scancodes are defined in allegro/keyboard.h as a series of KEY_*
constants (and are also listed below). For example, you could write:
@example

if (key[KEY_SPACE])
   printf("Space is pressed\n");@end example


Note that the array is supposed to represent which keys are physically
held down and which keys are not, so it is semantically read-only.

These are the keyboard scancodes:
@example

KEY_A ... KEY_Z,
KEY_0 ... KEY_9,
KEY_0_PAD ... KEY_9_PAD,
KEY_F1 ... KEY_F12,

KEY_ESC, KEY_TILDE, KEY_MINUS, KEY_EQUALS,
KEY_BACKSPACE, KEY_TAB, KEY_OPENBRACE, KEY_CLOSEBRACE,
KEY_ENTER, KEY_COLON, KEY_QUOTE, KEY_BACKSLASH,
KEY_BACKSLASH2, KEY_COMMA, KEY_STOP, KEY_SLASH,
KEY_SPACE,

KEY_INSERT, KEY_DEL, KEY_HOME, KEY_END, KEY_PGUP,
KEY_PGDN, KEY_LEFT, KEY_RIGHT, KEY_UP, KEY_DOWN,

KEY_SLASH_PAD, KEY_ASTERISK, KEY_MINUS_PAD,
KEY_PLUS_PAD, KEY_DEL_PAD, KEY_ENTER_PAD,

KEY_PRTSCR, KEY_PAUSE,

KEY_ABNT_C1, KEY_YEN, KEY_KANA, KEY_CONVERT, KEY_NOCONVERT,
KEY_AT, KEY_CIRCUMFLEX, KEY_COLON2, KEY_KANJI,

KEY_LSHIFT, KEY_RSHIFT,
KEY_LCONTROL, KEY_RCONTROL,
KEY_ALT, KEY_ALTGR,
KEY_LWIN, KEY_RWIN, KEY_MENU,
KEY_SCRLOCK, KEY_NUMLOCK, KEY_CAPSLOCK

KEY_EQUALS_PAD, KEY_BACKQUOTE, KEY_SEMICOLON, KEY_COMMAND@end example


Finally, you may notice an `odd' behaviour of the KEY_PAUSE key. This key
only generates an interrupt when it is pressed, not when it is released.
For this reason, Allegro pretends the pause key is a `state' key, which
is the only way to make it usable.

@end ftable
See also:@*
@xref{install_keyboard}.@*
@xref{poll_keyboard}.@*
@xref{key_shifts}.@*
@xref{Available, Available Allegro examples}.@*
@node key_shifts, keypressed, key, Keyboard
@subsection key_shifts
@ftable @asis
@item @t{extern volatile int key_shifts;}
Bitmask containing the current state of shift/ctrl/alt, the special 
Windows keys, and the accent escape characters. Wherever possible this 
value will be updated asynchronously, but if keyboard_needs_poll() 
returns TRUE, you must manually call poll_keyboard() to update it with 
the current input state. This can contain any of the flags:
@example

KB_SHIFT_FLAG
KB_CTRL_FLAG
KB_ALT_FLAG
KB_LWIN_FLAG
KB_RWIN_FLAG
KB_MENU_FLAG
KB_COMMAND_FLAG
KB_SCROLOCK_FLAG
KB_NUMLOCK_FLAG
KB_CAPSLOCK_FLAG
KB_INALTSEQ_FLAG
KB_ACCENT1_FLAG
KB_ACCENT2_FLAG
KB_ACCENT3_FLAG
KB_ACCENT4_FLAG@end example


Example:
@example

if (key[KEY_W]) @{
   if (key_shifts & KB_SHIFT_FLAG) @{
      /* User is pressing shift + W. */
   @} else @{
      /* Hmmm... lower case W then. */
   @}
@}@end example


@end ftable
See also:@*
@xref{install_keyboard}.@*
@xref{poll_keyboard}.@*
@xref{key}.@*
@xref{excamera}.@*
@xref{exkeys}.@*
@node keypressed, readkey, key_shifts, Keyboard
@subsection keypressed
@ftable @asis
@item @t{int keypressed();}
Returns TRUE if there are keypresses waiting in the input buffer. You can
use this to see if the next call to readkey() is going to block or to 
simply wait for the user to press a key while you still update the screen
possibly drawing some animation. Example:
@example

while (!keypressed()) @{
   /* Show cool animated logo. */
@}
/* So he skipped our title screen. */@end example


@end ftable
See also:@*
@xref{install_keyboard}.@*
@xref{readkey}.@*
@xref{ureadkey}.@*
@xref{clear_keybuf}.@*
@xref{simulate_keypress}.@*
@xref{simulate_ukeypress}.@*
@xref{Available, Available Allegro examples}.@*
@node readkey, ureadkey, keypressed, Keyboard
@subsection readkey
@ftable @asis
@item @t{int readkey();}
Returns the next character from the keyboard buffer, in ASCII format. If 
the buffer is empty, it waits until a key is pressed. You can see if there
are queued keypresses with keypressed().

The low byte of the return value contains the ASCII code of the key, and
the high byte the scancode. The scancode remains the same whatever the
state of the shift, ctrl and alt keys, while the ASCII code is affected by
shift and ctrl in the normal way (shift changes case, ctrl+letter gives
the position of that letter in the alphabet, eg. ctrl+A = 1, ctrl+B = 2,
etc). Pressing alt+key returns only the scancode, with a zero ASCII code
in the low byte. For example:
@example

int val;
...
val = readkey();
if ((val & 0xff) == 'd')     /* by ASCII code */
   allegro_message("You pressed 'd'\n");

if ((val >> 8) == KEY_SPACE) /* by scancode */
   allegro_message("You pressed Space\n");

if ((val & 0xff) == 3)       /* ctrl+letter */
   allegro_message("You pressed Control+C\n");

if (val == (KEY_X << 8))     /* alt+letter */
   allegro_message("You pressed Alt+X\n");
@end example

This function cannot return character values greater than 255. If you 
need to read Unicode input, use ureadkey() instead.

@end ftable
See also:@*
@xref{install_keyboard}.@*
@xref{ureadkey}.@*
@xref{keypressed}.@*
@xref{clear_keybuf}.@*
@xref{simulate_keypress}.@*
@xref{Available, Available Allegro examples}.@*
@node ureadkey, scancode_to_ascii, readkey, Keyboard
@subsection ureadkey
@ftable @asis
@item @t{int ureadkey(int *scancode);}
Returns the next character from the keyboard buffer, in Unicode format. 
If the buffer is empty, it waits until a key is pressed. You can see if
there are queued keypresses with keypressed(). The return value contains
the Unicode value of the key, and if not NULL, the pointer argument will
be set to the scancode. Unlike readkey(), this function is able to return
character values greater than 255. Example:
@example

int val, scancode;
...
val = ureadkey(&scancode);
if (val == 0x00F1)
   allegro_message("You pressed n with tilde\n");

if (val == 0x00DF)
   allegro_message("You pressed sharp s\n");
@end example

You should be able to find Unicode character maps at
http://www.unicode.org/. Remember that on DOS you must specify a custom
keyboard map (like those found in `keyboard.dat') usually with the help of
a configuration file specifying the language mapping (keyboard variable in
system section of `allegro.cfg'), or you will get the default US keyboard
mapping.

@end ftable
See also:@*
@xref{install_keyboard}.@*
@xref{readkey}.@*
@xref{keypressed}.@*
@xref{clear_keybuf}.@*
@xref{simulate_ukeypress}.@*
@xref{exkeys}.@*
@node scancode_to_ascii, scancode_to_name, ureadkey, Keyboard
@subsection scancode_to_ascii
@ftable @asis
@item @t{int scancode_to_ascii(int scancode);}
Converts the given scancode to an ASCII character for that key (mangling
Unicode values), returning the unshifted uncapslocked result of pressing
the key, or zero if the key isn't a character-generating key or the lookup
can't be done. The lookup cannot be done for keys like the F1-F12 keys or the
cursor keys, and some drivers will only return approximate values. Generally,
if you want to display the name of a key to the user, you should use the
scancode_to_name function.

Example:
@example

int ascii;
...
ascii = scancode_to_ascii(scancode);
allegro_message("You pressed '%c'\n", ascii);@end example


@end ftable
See also:@*
@xref{scancode_to_name}.@*
@node scancode_to_name, simulate_keypress, scancode_to_ascii, Keyboard
@subsection scancode_to_name
@ftable @asis
@item @t{const char *scancode_to_name(int scancode);}
This function returns a string pointer containing the name of they key with
the given scancode. This is useful if you e.g. let the user choose a key for
some action, and want to display something more meaningful than just the
scancode. Example:
@example

char const *keyname = scancode_to_name(scancode);
allegro_message("You pressed the %s key.", keyname);@end example


@end ftable
See also:@*
@xref{scancode_to_ascii}.@*
@xref{exkeys}.@*
@node simulate_keypress, simulate_ukeypress, scancode_to_name, Keyboard
@subsection simulate_keypress
@ftable @asis
@item @t{void simulate_keypress(int key);}
Stuffs a key into the keyboard buffer, just as if the user had pressed 
it. The parameter is in the same format returned by readkey(). Example:
@example

simulate_keypress(KEY_SPACE << 8);
if (readkey() == (KEY_SPACE << 8))
   allegro_message("You simulated Alt+Space\n");@end example


@end ftable
See also:@*
@xref{install_keyboard}.@*
@xref{simulate_ukeypress}.@*
@xref{keypressed}.@*
@xref{readkey}.@*
@node simulate_ukeypress, keyboard_callback, simulate_keypress, Keyboard
@subsection simulate_ukeypress
@ftable @asis
@item @t{void simulate_ukeypress(int key, int scancode);}
Stuffs a key into the keyboard buffer, just as if the user had pressed 
it. The parameter is in the same format returned by ureadkey(). Example:
@example

/* We ignore the scancode simulation. */
simulate_ukeypress(0x00DF, 0);
if (ureadkey(&scancode) == 0x00DF)
   allegro_message("You simulated sharp s\n");@end example


@end ftable
See also:@*
@xref{install_keyboard}.@*
@xref{simulate_keypress}.@*
@xref{keypressed}.@*
@xref{ureadkey}.@*
@node keyboard_callback, keyboard_ucallback, simulate_ukeypress, Keyboard
@subsection keyboard_callback
@ftable @asis
@item @t{extern int (*keyboard_callback)(int key);}
If set, this function is called by the keyboard handler in response to 
every keypress. It is passed a copy of the value that is about to be 
added into the input buffer, and can either return this value unchanged, 
return zero to cause the key to be ignored, or return a modified value to 
change what readkey() will later return. This routine executes in an 
interrupt context, so it must be in locked memory. Example:
@example

int enigma_scrambler(int key)
@{
   /* Add one to both the scancode and ascii values. */
   return (((key >> 8) + 1) 
@}
END_OF_FUNCTION(enigma_scrambler)

...

   install_timer();
   LOCK_FUNCTION(enigma_scrambler);
   install_keyboard();
   keyboard_callback = enigma_scrambler;@end example


Note that this callback will be ignored if you also set the unicode
keyboard callback.

@end ftable
See also:@*
@xref{install_keyboard}.@*
@xref{readkey}.@*
@xref{ureadkey}.@*
@xref{keyboard_ucallback}.@*
@xref{keyboard_lowlevel_callback}.@*
@node keyboard_ucallback, keyboard_lowlevel_callback, keyboard_callback, Keyboard
@subsection keyboard_ucallback
@ftable @asis
@item @t{extern int (*keyboard_ucallback)(int key, int *scancode);}
Unicode-aware version of keyboard_callback(). If set, this function is 
called by the keyboard handler in response to every keypress. It is 
passed the character value and scancode that are about to be added into 
the input buffer, can modify the scancode value, and returns a new or 
modified key code. If it both sets the scancode to zero and returns zero, 
the keypress will be ignored. This routine executes in an interrupt 
context, so it must be in locked memory. Example:
@example

int silence_g_key(int key, int *scancode)
@{
   if (key == 'g') @{
      *scancode = 0;
      return 0;
   @}
   return key;
@} END_OF_FUNCTION(silence_g_key)

...

   install_timer();
   LOCK_FUNCTION(silence_g_key);
   install_keyboard();
   keyboard_ucallback = silence_g_key;@end example


Note that this keyboard callback has priority over the non unicode
callback. If you set both, only the unicode one will work.

@end ftable
See also:@*
@xref{install_keyboard}.@*
@xref{readkey}.@*
@xref{ureadkey}.@*
@xref{keyboard_callback}.@*
@xref{keyboard_lowlevel_callback}.@*
@node keyboard_lowlevel_callback, set_leds, keyboard_ucallback, Keyboard
@subsection keyboard_lowlevel_callback
@ftable @asis
@item @t{extern void (*keyboard_lowlevel_callback)(int scancode);}
If set, this function is called by the keyboard handler in response to 
every keyboard event, both presses (including keyboard repeat rate) and
releases. It will be passed a raw keyboard scancode byte (scancodes are
7 bits long), with the top bit (8th bit) clear if the key has been
pressed or set if it was released. This routine executes in an interrupt
context, so it must be in locked memory. Example:
@example

volatile int key_down, key_up;

void keypress_watcher(int scancode)
@{
   if (scancode & 0x80) @{
      key_up = 1;
   @} else @{
      key_down = 1;
   @}
@} END_OF_FUNCTION(keypress_watcher)

...

   install_timer();
   LOCK_FUNCTION(silence_g_key);
   LOCK_VARIABLE(key_down);
   LOCK_VARIABLE(key_up);
   install_keyboard();
   keyboard_lowlevel_callback = keypress_watcher;
   /* Disable keyboard repeat to get typewriter effect. */
   set_keyboard_rate(0, 0);

...

   while (game_loop) @{
      if (key_down) @{
         key_down = 0;
         /* Play sample of typewriter key press. */
      @}
      if (key_up) @{
         key_up = 0;
         /* Play sample of typewriter key release. */
      @}
   @}@end example


@end ftable
See also:@*
@xref{install_keyboard}.@*
@xref{keyboard_callback}.@*
@xref{keyboard_ucallback}.@*
@xref{exkeys}.@*
@node set_leds, set_keyboard_rate, keyboard_lowlevel_callback, Keyboard
@subsection set_leds
@ftable @asis
@item @t{void set_leds(int leds);}
Overrides the state of the keyboard LED indicators. The parameter is a 
bitmask containing any of the values KB_SCROLOCK_FLAG, KB_NUMLOCK_FLAG, 
and KB_CAPSLOCK_FLAG, or -1 to restore the default behavior. Example:
@example

/* Cycle led indicators. */
set_leds(KB_SCROLOCK_FLAG);
rest(1000);
set_leds(KB_CAPSLOCK_FLAG);
rest(1000);
set_leds(KB_NUMLOCK_FLAG);
rest(1000);
set_leds(-1);
@end example

Note that the led behaviour cannot be guaranteed on some platforms, some
leds might not react, or none at all. Therefore you shouldn't rely only on
them to communicate information to the user, just in case it doesn't get
through.

@end ftable
See also:@*
@xref{install_keyboard}.@*
@xref{key_led_flag}.@*
@node set_keyboard_rate, clear_keybuf, set_leds, Keyboard
@subsection set_keyboard_rate
@ftable @asis
@item @t{void set_keyboard_rate(int delay, int repeat);}
Sets the keyboard repeat rate. Times are given in milliseconds. Passing 
zero times will disable the key repeat.

@end ftable
See also:@*
@xref{install_keyboard}.@*
@xref{readkey}.@*
@xref{ureadkey}.@*
@node clear_keybuf, three_finger_flag, set_keyboard_rate, Keyboard
@subsection clear_keybuf
@ftable @asis
@item @t{void clear_keybuf();}
Empties the keyboard buffer. Usually you want to use this in your program
before reading keys to avoid previously buffered keys to be returned by
calls to readkey() or ureadkey().

@end ftable
See also:@*
@xref{install_keyboard}.@*
@xref{keypressed}.@*
@xref{readkey}.@*
@xref{ureadkey}.@*
@xref{Available, Available Allegro examples}.@*
@node three_finger_flag, key_led_flag, clear_keybuf, Keyboard
@subsection three_finger_flag
@ftable @asis
@item @t{extern int three_finger_flag;}
The DJGPP keyboard handler provides an 'emergency exit' sequence which
you can use to kill off your program. If you are running under DOS this 
is the three finger salute, ctrl+alt+del. Most multitasking OS's will 
trap this combination before it reaches the Allegro handler, in which 
case you can use the alternative ctrl+alt+end. If you want to disable 
this behaviour in release versions of your program, set this flag to 
FALSE.

@end ftable
See also:@*
@xref{install_keyboard}.@*
@node key_led_flag, install_joystick, three_finger_flag, Keyboard
@subsection key_led_flag
@ftable @asis
@item @t{extern int key_led_flag;}
By default, the capslock, numlock, and scroll-lock keys toggle the 
keyboard LED indicators when they are pressed. If you are using these 
keys for input in your game (eg. capslock to fire) this may not be 
desirable, so you can clear this flag to prevent the LED's being updated.



@end ftable
See also:@*
@xref{install_keyboard}.@*
@xref{set_leds}.@*
@node Joystick, Graphics, Keyboard, API
@section Joystick routines

Unlike keyboard or mouse input, which are usually read through hardware
interrupts by Allegro, joystick input functions have to be polled because
there are no hardware interrupts for them on most platforms. This doesn't
mean that you have to poll the joysticks on each line of code you want to
read their values, but you should make sure to poll them at least once per
frame in your game loop. Otherwise you face the possibility of reading stale
incorrect data.

@menu
* install_joystick::
* remove_joystick::
* poll_joystick::
* num_joysticks::
* joy::
* calibrate_joystick_name::
* calibrate_joystick::
* save_joystick_data::
* load_joystick_data::
* initialise_joystick::
@end menu
@node install_joystick, remove_joystick, key_led_flag, Joystick
@subsection install_joystick
@ftable @asis
@item @t{int install_joystick(int type);}
Installs Allegro's joystick handler, and calibrates the centre position
values. The type parameter should usually be JOY_TYPE_AUTODETECT, or see
the platform specific documentation for a list of the available drivers.
You must call this routine before using any other joystick functions, and
you should make sure that all joysticks are in the middle position at the
time. Example:
@example

textout_centre_ex(screen, font,
                  "Center the joystick and press a key",
                  SCREEN_W/2, SCREEN_H/2, red_color, -1);
readkey();
if (install_joystick(JOY_TYPE_AUTODETECT) != 0)
   abort_on_error("Error initialising joystick!");@end example


Returns zero on success. As soon as you have installed the joystick 
module, you will be able to read the button state and digital (on/off 
toggle) direction information, which may be enough for some games. If you 
want to get full analogue input, though, you need to use the 
calibrate_joystick() functions to measure the exact range of the inputs: 
see below.

@end ftable
See also:@*
@xref{remove_joystick}.@*
@xref{num_joysticks}.@*
@xref{load_joystick_data}.@*
@xref{calibrate_joystick}.@*
@xref{calibrate_joystick_name}.@*
@xref{poll_joystick}.@*
@xref{Standard config variables}.@*
@xref{JOY_TYPE_*/DOS}.@*
@xref{JOY_TYPE_*/Windows}.@*
@xref{JOY_TYPE_*/Linux}.@*
@xref{exjoy}.@*
@node remove_joystick, poll_joystick, install_joystick, Joystick
@subsection remove_joystick
@ftable @asis
@item @t{void remove_joystick();}
Removes the joystick handler. You don't normally need to bother calling 
this, because allegro_exit() will do it for you.

@end ftable
See also:@*
@xref{install_joystick}.@*
@xref{allegro_exit}.@*
@node poll_joystick, num_joysticks, remove_joystick, Joystick
@subsection poll_joystick
@ftable @asis
@item @t{int poll_joystick();}
The joystick handler is not interrupt driven, so you need to call this
function every now and again to update the global position values. Example:
@example

do @{
   /* Get joystick input */
   poll_joystick();
   
   /* Process input for the first joystick */
   if (joy[0].button[0].b)
      first_button_pressed();

   if (joy[0].button[1].b)
      second_button_pressed();
   ...
@} while(!done);@end example


Returns zero on success or a negative number on failure (usually because
no joystick driver was installed).

@end ftable
See also:@*
@xref{install_joystick}.@*
@xref{joy}.@*
@xref{num_joysticks}.@*
@xref{exjoy}.@*
@node num_joysticks, joy, poll_joystick, Joystick
@subsection num_joysticks
@ftable @asis
@item @t{extern int num_joysticks;}
Global variable containing the number of active joystick devices. The 
current drivers support a maximum of eight controllers.

@end ftable
See also:@*
@xref{install_joystick}.@*
@xref{joy}.@*
@xref{exjoy}.@*
@node joy, calibrate_joystick_name, num_joysticks, Joystick
@subsection joy
@ftable @asis
@item @t{extern JOYSTICK_INFO joy[n];}
Global array of joystick state information, which is updated by the 
poll_joystick() function. Only the first num_joysticks elements will 
contain meaningful information. The JOYSTICK_INFO structure is defined as:
@example

typedef struct JOYSTICK_INFO
@{
   int flags;                       - status flags for this
                                      joystick
   int num_sticks;                  - how many stick inputs?
   int num_buttons;                 - how many buttons?
   JOYSTICK_STICK_INFO stick[n];    - stick state information
   JOYSTICK_BUTTON_INFO button[n];  - button state information
@} JOYSTICK_INFO;
@end example

The button status is stored in the structure:
@example

typedef struct JOYSTICK_BUTTON_INFO
@{
   int b;                           - boolean on/off flag
   char *name;                      - description of this
                                      button
@} JOYSTICK_BUTTON_INFO;
@end example

You may wish to display the button names as part of an input 
configuration screen to let the user choose what game function will be 
performed by each button, but in simpler situations you can safely assume 
that the first two elements in the button array will always be the main 
trigger controls.

Each joystick will provide one or more stick inputs, of varying types. 
These can be digital controls which snap to specific positions (eg. a 
gamepad controller, the coolie hat on a Flightstick Pro or Wingman 
Extreme, or a normal joystick which hasn't yet been calibrated), or they 
can be full analogue inputs with a smooth range of motion. Sticks may 
also have different numbers of axes, for example a normal directional 
control has two, but the Flightstick Pro throttle is only a single axis, 
and it is possible that the system could be extended in the future to 
support full 3d controllers. A stick input is described by the structure:
@example

typedef struct JOYSTICK_STICK_INFO
@{
   int flags;                       - status flags for this
                                      input
   int num_axis;                    - how many axes do we
                                      have? (note the misspelling)
   JOYSTICK_AXIS_INFO axis[n];      - axis state information
   char *name;                      - description of this
                                      input
@} JOYSTICK_STICK_INFO;
@end example

A single joystick may provide several different stick inputs, but you can 
safely assume that the first element in the stick array will always be 
the main directional controller.

Information about each of the stick axis is stored in the substructure:
@example

typedef struct JOYSTICK_AXIS_INFO
@{
   int pos;                         - analogue axis position
   int d1, d2;                      - digital axis position
   char *name;                      - description of this axis
@} JOYSTICK_AXIS_INFO;
@end example

This provides both analogue input in the pos field (ranging from -128 to 
128 or from 0 to 255, depending on the type of the control), and digital 
values in the d1 and d2 fields. For example, when describing the X-axis 
position, the pos field will hold the horizontal position of the 
joystick, d1 will be set if it is moved left, and d2 will be set if it is 
moved right. Allegro will fill in all these values regardless of whether 
it is using a digital or analogue joystick, emulating the pos field for 
digital inputs by snapping it to the min, middle, and maximum positions, 
and emulating the d1 and d2 values for an analogue stick by comparing the 
current position with the centre point.

The joystick flags field may contain any combination of the bit flags:

JOYFLAG_DIGITAL@*
This control is currently providing digital input.

JOYFLAG_ANALOGUE@*
This control is currently providing analogue input.

JOYFLAG_CALIB_DIGITAL@*
This control will be capable of providing digital input once it has 
been calibrated, but is not doing this at the moment.

JOYFLAG_CALIB_ANALOGUE@*
This control will be capable of providing analogue input once it has 
been calibrated, but is not doing this at the moment.

JOYFLAG_CALIBRATE@*
Indicates that this control needs to be calibrated. Many devices 
require multiple calibration steps, so you should call the 
calibrate_joystick() function from a loop until this flag is cleared.

JOYFLAG_SIGNED@*
Indicates that the analogue axis position is in signed format, ranging 
from -128 to 128. This is the case for all 2d directional controls.

JOYFLAG_UNSIGNED@*
Indicates that the analogue axis position is in unsigned format, 
ranging from 0 to 255. This is the case for all 1d throttle controls.

Note for people who spell funny: in case you don't like having to type 
"analogue", there are some #define aliases in allegro/joystick.h that
will allow you to write "analog" instead.

@end ftable
See also:@*
@xref{install_joystick}.@*
@xref{poll_joystick}.@*
@xref{num_joysticks}.@*
@xref{calibrate_joystick}.@*
@xref{calibrate_joystick_name}.@*
@xref{exjoy}.@*
@xref{JOYSTICK_INFO}.@*
@node calibrate_joystick_name, calibrate_joystick, joy, Joystick
@subsection calibrate_joystick_name
@ftable @asis
@item @t{const char *calibrate_joystick_name(int n);}
Pass the number of the joystick you want to calibrate as the parameter.

Returns a text description for the next type of calibration that will be
done on the specified joystick, or NULL if no more calibration is 
required.

@end ftable
See also:@*
@xref{install_joystick}.@*
@xref{calibrate_joystick}.@*
@xref{joy}.@*
@xref{num_joysticks}.@*
@xref{exjoy}.@*
@node calibrate_joystick, save_joystick_data, calibrate_joystick_name, Joystick
@subsection calibrate_joystick
@ftable @asis
@item @t{int calibrate_joystick(int n);}
Most joysticks need to be calibrated before they can provide full 
analogue input. This function performs the next operation in the 
calibration series for the specified stick, assuming that the joystick 
has been positioned in the manner described by a previous call to 
calibrate_joystick_name(), returning zero on success. For example, a 
simple routine to fully calibrate all the joysticks might look like:
@example

int i;

for (i=0; i<;num_joysticks; i++) @{
   while (joy[i].flags & JOYFLAG_CALIBRATE) @{
      char *msg = calibrate_joystick_name(i);
      textprintf_ex(..., "%s, and press a key\n", msg);
      readkey();
      if (calibrate_joystick(i) != 0) @{
         textprintf_ex(..., "oops!\n");
         readkey();
         exit(1);
      @}
   @}
@}@end example


Returns zero on success, non-zero if the calibration could not be
performed successfully.

@end ftable
See also:@*
@xref{install_joystick}.@*
@xref{calibrate_joystick_name}.@*
@xref{joy}.@*
@xref{num_joysticks}.@*
@xref{exjoy}.@*
@node save_joystick_data, load_joystick_data, calibrate_joystick, Joystick
@subsection save_joystick_data
@ftable @asis
@item @t{int save_joystick_data(const char *filename);}
After all the headache of calibrating the joystick, you may not want to 
make your poor users repeat the process every time they run your program. 
Call this function to save the joystick calibration data into the 
specified configuration file, from which it can later be read by 
load_joystick_data(). Pass a NULL filename to write the data to the 
currently selected configuration file.

Returns zero on success, non-zero if the data could not be saved.

@end ftable
See also:@*
@xref{load_joystick_data}.@*
@xref{set_config_file}.@*
@node load_joystick_data, initialise_joystick, save_joystick_data, Joystick
@subsection load_joystick_data
@ftable @asis
@item @t{int load_joystick_data(const char *filename);}
Restores calibration data previously stored by save_joystick_data() or 
the setup utility. This sets up all aspects of the joystick code: you 
don't even need to call install_joystick() if you are using this 
function. Pass a NULL filename to read the data from the currently 
selected configuration file.

Returns zero on success: if it fails the joystick state is undefined and
you must reinitialise it from scratch.

@end ftable
See also:@*
@xref{install_joystick}.@*
@xref{save_joystick_data}.@*
@xref{set_config_file}.@*
@node initialise_joystick, set_color_depth, load_joystick_data, Joystick
@subsection initialise_joystick
@ftable @asis
@item @t{int initialise_joystick();}
Deprecated. Use install_joystick() instead.



@end ftable
See also:@*
@xref{install_joystick}.@*
@node Graphics, Bitmap, Joystick, API
@section Graphics modes

Graphics modes are the common denominator for most Allegro programs. While it
is possible to write platform specific programs using Allegro which don't set
a graphic mode through the routines provided in this chapter, these are not
very common.

The first thing to note is that due to the wide range of supported platforms,
a graphic mode is the only way to safely communicate with the user. When
Allegro was a DOS only library (versions 3.x and previous), it was frequent
for programmers to use functions from the C standard library to communicate
with the user, like calling printf() before setting a graphic mode or maybe
scanf() to read the user's input. However, what would happen for such a game
running under Windows where there is no default console output or it may be
hidden from the user? Even if the game compiled successfully, it would be
unplayable, especially if there was vital information for the user in those
text only messages.

Allegro provides the allegro_message() function to deal with this problem,
but this is not a very user friendly method of communicating with the user
and its main purpose is displaying small error like messages when no graphic
mode is available. Therefore, the first thing your Allegro program should do
is set a graphic mode, and from there on, use Allegro's text output routines
to display messages to the user, just like `allegro/examples/exhello.c' does.

Setting a graphic mode involves deciding how to allocate the memory of the
video card for your program. On some platforms this means creating a virtual
screen bigger than the physical resolution to do hardware scrolling or page
flipping. Virtual screens can cause a lot of confusion, but they are really
quite simple. Warning: patronising explanation coming up, so you may wish to
skip the rest of this paragraph. Think of video memory as a rectangular piece
of paper which is being viewed through a small hole (your monitor) in a bit of
cardboard. Since the paper is bigger than the hole you can only see part of it
at any one time, but by sliding the cardboard around you can alter which
portion of the image is visible. You could just leave the hole in one position
and ignore the parts of video memory that aren't visible, but you can get all
sorts of useful effects by sliding the screen window around, or by drawing
images in a hidden part of video memory and then flipping across to display
them.

For example, you could select a 640x480 mode in which the monitor acts as a
window onto a 1024x1024 virtual screen, and then move the visible screen
around in this larger area (hardware scrolling). Initially, with the visible
screen positioned at the top left corner of video memory, this setup would
look like:
@example

(0,0)------------(640,0)----(1024,0)
  |                  |           |
  |  visible screen  |           |
  |                  |           |
(0,480)----------(640,480)       |
  |                              |
  |   the rest of video memory   |
  |                              |
(0,1024)--------------------(1024,1024)
@end example

With a virtual screen bigger than the visible screen you can perform smooth
CPU inexpensive scrolling: you draw your graphics once, and then only tell
the video card to show a different portion of the screen. However, virtual
screens are not supported on all platforms, and on some they might be
emulated through software, losing any performance. On top of that, many video
cards only allow horizontal scrolling in steps of 32 bytes. This is not a
problem if your game runs in 24 or 32 bit, but it tends to mean jerky
scrolling for other color depths.

The other reason you could use virtual screens for is page flipping. This
means showing one portion of the virtual screen while your program draws to
the hidden one. When you finish, you show the part you have been drawing to
and repeat the process with the area now hidden. The result is a perfectly
smooth screen update without flickering or other graphical artifacts.

Scrolling manually to one part of the video memory is one non portable way to
accomplish this. The portable way is to use functions like
create_system_bitmap(), create_video_bitmap(), show_video_bitmap(), etc. These
functions divide the memory of the video card in areas and switch between
them, a feature supported on all platforms and video cards (given that they
have enough memory for the screen resolutions you asked for).

The last thing you need to know about setting a graphic mode are drivers.
Each platform has a number of graphic drivers which support a different range
of hardware or behave in different ways. To avoid cluttering your own code
with #ifdefs and dealing with drivers added after you release your program,
Allegro provides several so called magic drivers. These magic drivers don't
really exists, they wrap around a specific kind of functionality.

The magic drivers you can use are:

@itemize @bullet
@item 
GFX_AUTODETECT:@*
Allegro will try to set the specified resolution with the current color
depth in fullscreen mode. Failing that, it will try to repeat the same
operation in windowed mode. If the call to set_gfx_mode() succeeds, you
are guaranteed to have set the specified resolution in the current color
depth, but you don't know if the program is running fullscreen or
windowed.
@item 
GFX_AUTODETECT_FULLSCREEN:@*
Allegro will try to set the specified resolution with the current color
depth in fullscreen mode. If that is not possible, set_gfx_mode() will
fail.
@item 
GFX_AUTODETECT_WINDOWED:@*
Allegro will try to set the specified resolution with the current color
depth in a windowed mode. If that is not possible, set_gfx_mode() will
fail. When it comes to windowed modes, the `specified resolution' actually
means the graphic area your program can draw on, without including window
decorations (if any). Note that in windowed modes running with a color
depth other than the desktop may result in non optimal performance due to
internal color conversions in the graphic driver. Use
desktop_color_depth() to your advantage in these situations.
@item 
GFX_SAFE:@*
Using this driver Allegro guarantees that a graphic mode will always be
set correctly. It will try to select the resolution that you request, and
if that fails, it will fall back upon whatever mode is known to be
reliable on the current platform (this is 320x200 VGA mode under DOS, a
640x480 resolution under Windows, the actual framebuffer's resolution
under Linux if it's supported, etc). If it absolutely cannot set any
graphics mode at all, it will return negative as usual, meaning that
there's no possible video output on the machine, and that you should abort
your program immediately, possibly after notifying this to the user with
allegro_message.

This fake driver is useful for situations where you just want to get into
some kind of workable display mode, and can't be bothered with trying
multiple different resolutions and doing all the error checking yourself.
Note however, that after a successful call to set_gfx_mode with this
driver, you cannot make any assumptions about the width, height or color
depth of the screen: your code will have to deal with this little detail.
@item 
GFX_TEXT:@*
Closes any previously opened graphics mode, making you unable to use the
global variable `screen', and in those environments that have text modes,
sets one previously used or the closest match to that (usually 80x25).
With this driver the size parameters of set_gfx_mode don't mean anything,
so you can leave them all to zero or any other number you prefer.
@end itemize


@menu
* set_color_depth::
* get_color_depth::
* request_refresh_rate::
* get_refresh_rate::
* get_gfx_mode_list::
* destroy_gfx_mode_list::
* set_gfx_mode::
* set_display_switch_mode::
* set_display_switch_callback::
* remove_display_switch_callback::
* get_display_switch_mode::
* is_windowed_mode::
* gfx_capabilities::
* enable_triple_buffer::
* scroll_screen::
* request_scroll::
* poll_scroll::
* show_video_bitmap::
* request_video_bitmap::
* vsync::
@end menu
@node set_color_depth, get_color_depth, initialise_joystick, Graphics
@subsection set_color_depth
@ftable @asis
@item @t{void set_color_depth(int depth);}
Sets the pixel format to be used by subsequent calls to set_gfx_mode() 
and create_bitmap(). Valid depths are 8 (the default), 15, 16, 24, and 32 
bits. Example:
@example

set_color_depth(32);
if (set_gfx_mode(GFX_AUTODETECT, 640, 480, 0, 0) != 0) @{
   abort_on_error("Couldn't set a 32 bit color resolution");
@}
@end example

Note that the screen color depth won't change until the next successful
call to set_gfx_mode().

@end ftable
See also:@*
@xref{get_color_depth}.@*
@xref{set_gfx_mode}.@*
@xref{set_color_conversion}.@*
@xref{makecol}.@*
@xref{getr}.@*
@xref{desktop_color_depth}.@*
@xref{Available, Available Allegro examples}.@*
@node get_color_depth, request_refresh_rate, set_color_depth, Graphics
@subsection get_color_depth
@ftable @asis
@item @t{int get_color_depth(void);}
Returns the current pixel format. This can be very useful to know in order
to write generic functions which select a different code path internally
depending on the color depth being used.

Note that the function returns whatever value you may have set previously
with set_color_depth(), which can be different from the current color
depth of the screen global variable. If you really need to know the color
depth of the screen, use bitmap_color_depth().

@end ftable
See also:@*
@xref{set_color_depth}.@*
@xref{bitmap_color_depth}.@*
@xref{exrgbhsv}.@*
@node request_refresh_rate, get_refresh_rate, get_color_depth, Graphics
@subsection request_refresh_rate
@ftable @asis
@item @t{void request_refresh_rate(int rate);}
Requests that the next call to set_gfx_mode() try to use the specified 
refresh rate, if possible. Not all drivers are able to control this at 
all, and even when they can, not all rates will be possible on all 
hardware, so the actual settings may differ from what you requested. 
After you call set_gfx_mode(), you can use get_refresh_rate() to find out 
what was actually selected. At the moment only the DOS VESA 3.0, X DGA 2.0
and some Windows DirectX drivers support this function. The speed is
specified in Hz, eg. 60, 70. To return to the normal default selection,
pass a rate value of zero. Example:
@example

request_refresh_rate(60);
if (set_gfx_mode(GFX_AUTODETECT, 640, 480, 0, 0) != 0)
   abort_on_error("Couldn't set graphic mode!");
if (get_refresh_rate() != 60)
   abort_on_error("Couldn't set refresh rate to 60Hz!");@end example


@end ftable
See also:@*
@xref{set_gfx_mode}.@*
@xref{get_refresh_rate}.@*
@node get_refresh_rate, get_gfx_mode_list, request_refresh_rate, Graphics
@subsection get_refresh_rate
@ftable @asis
@item @t{int get_refresh_rate(void);}
Returns the current refresh rate, if known (not all drivers are able to 
report this information). Returns zero if the actual rate is unknown.

@end ftable
See also:@*
@xref{request_refresh_rate}.@*
@node get_gfx_mode_list, destroy_gfx_mode_list, get_refresh_rate, Graphics
@subsection get_gfx_mode_list
@ftable @asis
@item @t{GFX_MODE_LIST *get_gfx_mode_list(int card);}
Attempts to create a list of all the supported video modes for a certain
graphics driver, made up from the GFX_MODE_LIST structure, which has the
following definition:
@example

typedef struct GFX_MODE_LIST
@{
   int num_modes;
   GFX_MODE *mode;
@} GFX_MODE_LIST;
@end example

The mode entry  points to the actual list of video modes.
@example

typedef struct GFX_MODE
@{
   int width, height, bpp;
@} GFX_MODE;
@end example

This list of video modes is terminated with an @{ 0, 0, 0 @} entry.

Note that the card parameter must refer to a _real_ driver. This function
fails if you pass GFX_SAFE, GFX_AUTODETECT, or any other "magic" driver.

Returns a pointer to a list structure of the type GFX_MODE_LIST or NULL
if the request could not be satisfied.

@end ftable
See also:@*
@xref{destroy_gfx_mode_list}.@*
@xref{set_gfx_mode}.@*
@xref{set_color_depth}.@*
@xref{GFX_MODE_LIST}.@*
@node destroy_gfx_mode_list, set_gfx_mode, get_gfx_mode_list, Graphics
@subsection destroy_gfx_mode_list
@ftable @asis
@item @t{void destroy_gfx_mode_list(GFX_MODE_LIST *mode_list);}
Removes the mode list created by get_gfx_mode_list() from memory. Use this
once you are done with the generated mode list to avoid memory leaks in
your program.

@end ftable
See also:@*
@xref{get_gfx_mode_list}.@*
@xref{set_gfx_mode}.@*
@xref{set_color_depth}.@*
@xref{GFX_MODE_LIST}.@*
@node set_gfx_mode, set_display_switch_mode, destroy_gfx_mode_list, Graphics
@subsection set_gfx_mode
@ftable @asis
@item @t{int set_gfx_mode(int card, int w, int h, int v_w, int v_h);}
Switches into graphics mode. The card parameter should usually be one of
the Allegro magic drivers (read introduction of chapter "Graphics modes")
or see the platform specific documentation for a list of the available
drivers. The w and h parameters specify what screen resolution you want.
The color depth of the graphic mode has to be specified before calling
this function with set_color_depth().

The v_w and v_h parameters specify the minimum virtual screen size, in 
case you need a large virtual screen for hardware scrolling or page 
flipping. You should set them to zero if you don't care about the virtual 
screen size.

When you call set_gfx_mode(), the v_w and v_h parameters represent the 
minimum size of virtual screen that is acceptable for your program. The 
range of possible sizes is usually very restricted, and Allegro may 
end up creating a virtual screen much larger than the one you request.
Allowed sizes are driver dependent and some drivers do not allow virtual 
screens that are larger than the visible screen at all: don't assume
that whatever you pass will always work.

In mode-X the virtual width can be any multiple of eight greater than or 
equal to the physical screen width, and the virtual height will be set 
accordingly (the VGA has 256k of vram, so the virtual height will be 
256*1024/virtual_width).

Currently, using a big virtual screen for page flipping is considered bad
practice.  There are platforms which don't support virtual screens bigger
than the physical screen but can create different video pages to flip back
and forth. This means that, if you want page flipping and aren't going to
use hardware scrolling, you should call set_gfx_mode() with (0,0) as the
virtual screen size and later create the different video pages with
create_video_bitmap(). Otherwise your program will be limited to the
platforms supporting hardware scrolling.

After you select a graphics mode, the physical and virtual screen sizes 
can be checked with the macros SCREEN_W, SCREEN_H, VIRTUAL_W, and 
VIRTUAL_H.

Returns zero on success. On failure returns a negative number and stores a
description of the problem in allegro_error.

@end ftable
See also:@*
@xref{set_color_depth}.@*
@xref{request_refresh_rate}.@*
@xref{screen}.@*
@xref{gfx_capabilities}.@*
@xref{allegro_error}.@*
@xref{Standard config variables}.@*
@xref{GFX_*/DOS}.@*
@xref{GFX_*/Windows}.@*
@xref{GFX_*/X}.@*
@xref{GFX_*/Linux}.@*
@xref{GFX_*/BeOS}.@*
@xref{GFX_*/MacOSX}.@*
@xref{create_video_bitmap}.@*
@xref{get_desktop_resolution}.@*
@xref{SCREEN_W}.@*
@xref{SCREEN_W, SCREEN_H}.@*
@xref{VIRTUAL_W}.@*
@xref{VIRTUAL_W, VIRTUAL_H}.@*
@xref{Available, Available Allegro examples}.@*
@node set_display_switch_mode, set_display_switch_callback, set_gfx_mode, Graphics
@subsection set_display_switch_mode
@ftable @asis
@item @t{int set_display_switch_mode(int mode);}
Sets how the program should handle being switched into the background, 
if the user tabs away from it. Not all of the possible modes will be
supported by every graphics driver on every platform. The available modes
are:

@itemize @bullet
@item 
SWITCH_NONE@*
Disables switching. This is the default in single-tasking systems like 
DOS. It may be supported on other platforms, but you should use it 
with caution, because your users won't be impressed if they want to 
switch away from your program, but you don't let them!
@item 
SWITCH_PAUSE@*
Pauses the program whenever it is in the background. Execution will be 
resumed as soon as the user switches back to it. This is the default 
in most fullscreen multitasking environments, for example the Linux 
console, but not under Windows.
@item 
SWITCH_AMNESIA@*
Like SWITCH_PAUSE, but this mode doesn't bother to remember the 
contents of video memory, so the screen, and any video bitmaps that 
you have created, will be erased after the user switches away and then 
back to your program. This is not a terribly useful mode to have, but 
it is the default for the fullscreen drivers under Windows because 
DirectDraw is too dumb to implement anything better.
@item 
SWITCH_BACKGROUND@*
The program will carry on running in the background, with the screen 
bitmap temporarily being pointed at a memory buffer for the fullscreen 
drivers. You must take special care when using this mode, because bad 
things will happen if the screen bitmap gets changed around when your 
program isn't expecting it (see below).
@item 
SWITCH_BACKAMNESIA@*
Like SWITCH_BACKGROUND, but this mode doesn't bother to remember the 
contents of video memory (see SWITCH_AMNESIA). It is again the only 
mode supported by the fullscreen drivers under Windows that lets the 
program keep running in the background.
@end itemize

Note that you should be very careful when you are using graphics routines 
in the switching context: you must always call acquire_screen() before the
start of any drawing code onto the screen and not release it until you are
completely finished, because the automatic locking mechanism may not be
good enough to work when the program runs in the background or has just
been raised in the foreground.

Returns zero on success, invalidating at the same time all callbacks
previously registered with set_display_switch_callback(). Returns -1 if
the requested mode is not currently possible.

@end ftable
See also:@*
@xref{set_display_switch_callback}.@*
@xref{get_display_switch_mode}.@*
@xref{exmidi}.@*
@xref{exswitch}.@*
@node set_display_switch_callback, remove_display_switch_callback, set_display_switch_mode, Graphics
@subsection set_display_switch_callback
@ftable @asis
@item @t{int set_display_switch_callback(int dir, void (*cb)());}
Installs a notification callback for the switching mode that was 
previously selected by calling set_display_switch_mode(). The direction 
parameter can either be SWITCH_IN or SWITCH_OUT, depending whether you 
want to be notified about switches away from your program or back to your 
program. You can sometimes install callbacks for both directions at the 
same time, but not every platform supports this. You can install several
switch callbacks, but no more than eight on any platform.

Returns zero on success, decreasing the number of empty callback slots by
one. Returns -1 if the request is impossible for the current platform or
you have reached the maximum number of allowed callbacks.

@end ftable
See also:@*
@xref{remove_display_switch_callback}.@*
@xref{set_display_switch_mode}.@*
@xref{exswitch}.@*
@node remove_display_switch_callback, get_display_switch_mode, set_display_switch_callback, Graphics
@subsection remove_display_switch_callback
@ftable @asis
@item @t{void remove_display_switch_callback(void (*cb)());}
Removes a notification callback that was previously installed by calling 
set_display_switch_callback(). All the callbacks will automatically be 
removed when you call set_display_switch_mode(). You can safely call this
function even if the callback you want to remove is not installed.

@end ftable
See also:@*
@xref{set_display_switch_callback}.@*
@node get_display_switch_mode, is_windowed_mode, remove_display_switch_callback, Graphics
@subsection get_display_switch_mode
@ftable @asis
@item @t{int get_display_switch_mode();}
Returns the current display switching mode, in the same format passed to 
set_display_switch_mode().

@end ftable
See also:@*
@xref{set_display_switch_mode}.@*
@xref{exswitch}.@*
@node is_windowed_mode, gfx_capabilities, get_display_switch_mode, Graphics
@subsection is_windowed_mode
@ftable @asis
@item @t{int is_windowed_mode(void);}
This function can be used to detect whether or not set_gfx_mode() selected
a windowed mode. Example:
@example

if (set_gfx_mode(GFX_AUTODETECT, 640, 480, 0, 0) != 0)
   abort_on_error("Couldn't set graphic mode!");
if (is_windowed_mode()) @{
   /* Windowed mode stuff. */
@} else @{
   /* Fullscreen mode stuff. */
@}@end example


Returns true if the current graphics mode is a windowed mode, or zero if
it is a fullscreen mode. You should not call this function if you are not
in graphics mode.

@end ftable
See also:@*
@xref{set_gfx_mode}.@*
@node gfx_capabilities, enable_triple_buffer, is_windowed_mode, Graphics
@subsection gfx_capabilities
@ftable @asis
@item @t{extern int gfx_capabilities;}
Bitfield describing the capabilities of the current graphics driver and 
video hardware. This may contain combination any of the flags:

GFX_CAN_SCROLL:@*
Indicates that the scroll_screen() function may be used with this 
driver.

GFX_CAN_TRIPLE_BUFFER:@*
Indicates that the request_scroll() and poll_scroll() functions may be 
used with this driver. If this flag is not set, it is possible that 
the enable_triple_buffer() function may be able to activate it.

GFX_HW_CURSOR:@*
Indicates that a hardware mouse cursor is in use. When this flag is 
set, it is safe to draw onto the screen without hiding the mouse 
pointer first. Note that not every cursor graphic can be implemented 
in hardware: in particular VBE/AF only supports 2-color images up to 
32x32 in size, where the second color is an exact inverse of the 
first. This means that Allegro may need to switch between hardware and 
software cursors at any point during the execution of your program, so 
you should not assume that this flag will remain constant for long 
periods of time. It only tells you whether a hardware cursor is in use 
at the current time, and may change whenever you hide/redisplay the 
pointer.

GFX_SYSTEM_CURSOR@*
Indicates that the mouse cursor is the default system cursor, not 
Allegro's custom cursor.

GFX_HW_HLINE:@*
Indicates that the normal opaque version of the hline() function is 
implemented using a hardware accelerator. This will improve the 
performance not only of hline() itself, but also of many other 
functions that use it as a workhorse, for example circlefill(), 
triangle(), and floodfill().

GFX_HW_HLINE_XOR:@*
Indicates that the XOR version of the hline() function, and any other 
functions that use it as a workhorse, are implemented using a hardware 
accelerator.

GFX_HW_HLINE_SOLID_PATTERN:@*
Indicates that the solid and masked pattern modes of the hline() 
function, and any other functions that use it as a workhorse, are 
implemented using a hardware accelerator (see note below).

GFX_HW_HLINE_COPY_PATTERN:@*
Indicates that the copy pattern mode of the hline() function, and any 
other functions that use it as a workhorse, are implemented using a 
hardware accelerator (see note below).

GFX_HW_FILL:@*
Indicates that the opaque version of the rectfill() function, the 
clear_bitmap() routine, and clear_to_color(), are implemented using a
hardware accelerator.

GFX_HW_FILL_XOR:@*
Indicates that the XOR version of the rectfill() function is 
implemented using a hardware accelerator.

GFX_HW_FILL_SOLID_PATTERN:@*
Indicates that the solid and masked pattern modes of the rectfill() 
function are implemented using a hardware accelerator (see note below).

GFX_HW_FILL_COPY_PATTERN:@*
Indicates that the copy pattern mode of the rectfill() function is 
implemented using a hardware accelerator (see note below).

GFX_HW_LINE:@*
Indicates that the opaque mode line() and vline() functions are 
implemented using a hardware accelerator.

GFX_HW_LINE_XOR:@*
Indicates that the XOR version of the line() and vline() functions are 
implemented using a hardware accelerator.

GFX_HW_TRIANGLE:@*
Indicates that the opaque mode triangle() function is implemented 
using a hardware accelerator.

GFX_HW_TRIANGLE_XOR:@*
Indicates that the XOR version of the triangle() function is 
implemented using a hardware accelerator.

GFX_HW_GLYPH:@*
Indicates that monochrome character expansion (for text drawing) is 
implemented using a hardware accelerator.

GFX_HW_VRAM_BLIT:@*
Indicates that blitting from one part of the screen to another is 
implemented using a hardware accelerator. If this flag is set, 
blitting within the video memory will almost certainly be the fastest 
possible way to display an image, so it may be worth storing some of 
your more frequently used graphics in an offscreen portion of the 
video memory.

GFX_HW_VRAM_BLIT_MASKED:@*
Indicates that the masked_blit() routine is capable of a hardware 
accelerated copy from one part of video memory to another, and that 
draw_sprite() will use a hardware copy when given a sub-bitmap of the 
screen or a video memory bitmap as the source image. If this flag is 
set, copying within the video memory will almost certainly be the 
fastest possible way to display an image, so it may be worth storing 
some of your more frequently used sprites in an offscreen portion of 
the video memory.

Warning: if this flag is not set, masked_blit() and draw_sprite() will 
not work correctly when used with a video memory source image! You 
must only try to use these functions to copy within the video memory 
if they are supported in hardware.

GFX_HW_MEM_BLIT:@*
Indicates that blitting from a memory bitmap onto the screen is being 
accelerated in hardware.

GFX_HW_MEM_BLIT_MASKED:@*
Indicates that the masked_blit() and draw_sprite() functions are being 
accelerated in hardware when the source image is a memory bitmap and 
the destination is the physical screen.

GFX_HW_SYS_TO_VRAM_BLIT:@*
Indicates that blitting from a system bitmap onto the screen is being 
accelerated in hardware. Note that some acceleration may be present 
even if this flag is not set, because system bitmaps can benefit from 
normal memory to screen blitting as well. This flag will only be set 
if system bitmaps have further acceleration above and beyond what is 
provided by GFX_HW_MEM_BLIT.

GFX_HW_SYS_TO_VRAM_BLIT_MASKED:@*
Indicates that the masked_blit() and draw_sprite() functions are being 
accelerated in hardware when the source image is a system bitmap and 
the destination is the physical screen. Note that some acceleration 
may be present even if this flag is not set, because system bitmaps 
can benefit from normal memory to screen blitting as well. This flag 
will only be set if system bitmaps have further acceleration above and 
beyond what is provided by GFX_HW_MEM_BLIT_MASKED.

GFX_HW_VRAM_STRETCH_BLIT:@*
Indicates that stretched blitting of video bitmaps onto the screen is
implemented using hardware acceleration. 

GFX_HW_SYS_STRETCH_BLIT:@*
Indicates that stretched blitting of system bitmaps onto the screen is
implemented using hardware acceleration. 

GFX_HW_VRAM_STRETCH_BLIT_MASKED:@*
Indicates that masked stretched blitting (including stretch_sprite) of 
video bitmaps onto the screen is implemented using hardware acceleration.
NOTE: some display drivers may show artifacts when this function is used.
If the image does not look correct try updating your video drivers.

GFX_HW_SYS_STRETCH_BLIT_MASKED:@*
Indicates that masked stretched blitting (including stretch_sprite) of 
system bitmaps onto the screen is implemented using hardware acceleration.
NOTE: some display drivers may show artefact's when this function is used.
If the image does not look correct try updating your video drivers.

Note: even if the capabilities information says that patterned drawing is 
supported by the hardware, it will not be possible for every size of 
pattern. VBE/AF only supports patterns up to 8x8 in size, so Allegro will 
fall back on the original non-accelerated drawing routines whenever you 
use a pattern larger than this.

Note2: these hardware acceleration features will only take effect when 
you are drawing directly onto the screen bitmap, a video memory bitmap, 
or a sub-bitmap thereof. Accelerated hardware is most useful in a page 
flipping or triple buffering setup, and is unlikely to make any 
difference to the classic "draw onto a memory bitmap, then blit to the 
screen" system.

@end ftable
See also:@*
@xref{screen}.@*
@xref{create_video_bitmap}.@*
@xref{scroll_screen}.@*
@xref{request_scroll}.@*
@xref{show_mouse}.@*
@xref{enable_triple_buffer}.@*
@xref{ex3buf}.@*
@xref{exaccel}.@*
@xref{exsyscur}.@*
@xref{exupdate}.@*
@node enable_triple_buffer, scroll_screen, gfx_capabilities, Graphics
@subsection enable_triple_buffer
@ftable @asis
@item @t{int enable_triple_buffer();}
If the GFX_CAN_TRIPLE_BUFFER bit of the gfx_capabilities field is not 
set, you can attempt to enable it by calling this function. In particular 
if you are running in mode-X in a clean DOS environment, this routine 
will enable the timer retrace simulator, which will activate the triple 
buffering functions.

Returns zero if triple buffering is enabled, -1 otherwise.

@end ftable
See also:@*
@xref{gfx_capabilities}.@*
@xref{request_scroll}.@*
@xref{request_video_bitmap}.@*
@xref{ex3buf}.@*
@xref{exupdate}.@*
@node scroll_screen, request_scroll, enable_triple_buffer, Graphics
@subsection scroll_screen
@ftable @asis
@item @t{int scroll_screen(int x, int y);}
Attempts to scroll the hardware screen to display a different part of the 
virtual screen (initially it will be positioned at 0, 0, which is the top 
left corner). You can use this to move the screen display around in a
large virtual screen space, or to page flip back and forth between two
non-overlapping areas of the virtual screen. Note that to draw outside the
original position in the screen bitmap you will have to alter the clipping
rectangle with set_clip_rect().

Mode-X scrolling is reliable and will work on any card, other drivers may
not work or not work reliably. See the platform-specific section of the docs
for more information.

Allegro will handle any necessary vertical retrace synchronisation when 
scrolling the screen, so you don't need to call vsync() before it. This 
means that scroll_screen() has the same time delay effects as vsync().

Returns zero on success. Returns non-zero if the graphics driver can't
handle hardware scrolling or the virtual screen is not large enough.

@end ftable
See also:@*
@xref{set_gfx_mode}.@*
@xref{show_video_bitmap}.@*
@xref{request_scroll}.@*
@xref{request_video_bitmap}.@*
@xref{exscroll}.@*
@node request_scroll, poll_scroll, scroll_screen, Graphics
@subsection request_scroll
@ftable @asis
@item @t{int request_scroll(int x, int y);}
This function is used for triple buffering. It requests a hardware scroll 
to the specified position, but returns immediately rather than waiting 
for a retrace. The scroll will then take place during the next vertical 
retrace, but you can carry on running other code in the meantime and use 
the poll_scroll() routine to detect when the flip has actually taken 
place.

Triple buffering is only possible with certain drivers: you can look at the 
GFX_CAN_TRIPLE_BUFFER bit in the gfx_capabilities flag to see if it will 
work with the current driver.

This function returns zero on success, non-zero otherwise.

@end ftable
See also:@*
@xref{poll_scroll}.@*
@xref{request_video_bitmap}.@*
@xref{gfx_capabilities}.@*
@xref{scroll_screen}.@*
@node poll_scroll, show_video_bitmap, request_scroll, Graphics
@subsection poll_scroll
@ftable @asis
@item @t{int poll_scroll();}
This function is used for triple buffering. It checks the status of a 
hardware scroll previously initiated by the request_scroll() routine.

Returns non-zero if it is still waiting to take place, and zero if the
requested scroll has already happened.

@end ftable
See also:@*
@xref{request_scroll}.@*
@xref{request_video_bitmap}.@*
@xref{ex3buf}.@*
@xref{exupdate}.@*
@node show_video_bitmap, request_video_bitmap, poll_scroll, Graphics
@subsection show_video_bitmap
@ftable @asis
@item @t{int show_video_bitmap(BITMAP *bitmap);}
Attempts to page flip the hardware screen to display the specified video 
bitmap object, which must be the same size as the physical screen, and 
should have been obtained by calling the create_video_bitmap() function. 

Allegro will handle any necessary vertical retrace synchronisation when 
page flipping, so you don't need to call vsync() before it. This means
that show_video_bitmap() has the same time delay effects as vsync() by
default. This can be adjusted with the "disable_vsync" config key in the
[graphics] section of allegro.cfg. Example:
@example

int current_page;
BITMAP *video_page[2];
...
/* Create pages for page flipping */
video_page[0] = create_video_bitmap(SCREEN_W, SCREEN_H);
video_page[1] = create_video_bitmap(SCREEN_W, SCREEN_H);
current_page = 0;
...
/* draw the screen and flip pages */
draw_screen(video_page[current_page]);
show_video_bitmap(video_page[current_page]);
current_page = (current_page+1)%2;
...@end example


Returns zero on success and non-zero on failure.

@end ftable
See also:@*
@xref{scroll_screen}.@*
@xref{create_video_bitmap}.@*
@xref{Standard config variables}.@*
@xref{exaccel}.@*
@xref{exflip}.@*
@xref{exupdate}.@*
@xref{BITMAP}.@*
@node request_video_bitmap, vsync, show_video_bitmap, Graphics
@subsection request_video_bitmap
@ftable @asis
@item @t{int request_video_bitmap(BITMAP *bitmap);}
This function is used for triple buffering. It requests a page flip to 
display the specified video bitmap object, but returns immediately rather 
than waiting for a retrace. The flip will then take place during the next 
vertical retrace, but you can carry on running other code in the meantime 
and use the poll_scroll() routine to detect when the flip has actually 
taken place. Triple buffering is only possible on certain hardware: see 
the comments about request_scroll(). Example:
@example

int current_page;
BITMAP *video_page[3];
...
/* Create pages for page flipping */
video_page[0] = create_video_bitmap(SCREEN_W, SCREEN_H);
video_page[1] = create_video_bitmap(SCREEN_W, SCREEN_H);
video_page[2] = create_video_bitmap(SCREEN_W, SCREEN_H);
current_page = 0;
...
/* draw the screen and flip pages */
draw_screen(video_page[current_page]);
do @{
@} while (poll_scroll());
request_video_bitmap(video_page[current_page]);
current_page = (current_page+1)%3;
...@end example


Returns zero on success and non-zero on failure.

@end ftable
See also:@*
@xref{poll_scroll}.@*
@xref{request_scroll}.@*
@xref{gfx_capabilities}.@*
@xref{create_video_bitmap}.@*
@xref{scroll_screen}.@*
@xref{ex3buf}.@*
@xref{exupdate}.@*
@xref{BITMAP}.@*
@node vsync, screen, request_video_bitmap, Graphics
@subsection vsync
@ftable @asis
@item @t{void vsync();}
Waits for a vertical retrace to begin. The retrace happens when the
electron beam in your monitor has reached the bottom of the screen and is
moving back to the top ready for another scan. During this short period
the graphics card isn't sending any data to the monitor, so you can do
things to it that aren't possible at other times, such as altering the
palette without causing flickering (snow). Allegro will automatically
wait for a retrace before altering the palette or doing any hardware
scrolling, though, so you don't normally need to bother with this
function.



@end ftable
See also:@*
@xref{set_palette}.@*
@xref{scroll_screen}.@*
@xref{Available, Available Allegro examples}.@*
@node Bitmap, Loading, Graphics, API
@section Bitmap objects

Once you have selected a graphics mode, you can draw things onto the display 
via the `screen' bitmap. All the Allegro graphics routines draw onto BITMAP
structures, which are areas of memory containing rectangular images, stored 
as packed byte arrays (in 8-bit modes one byte per pixel, in 15- and 16-bit
modes two bytes per pixel, in 24-bit modes 3 bytes per pixel and in 32-bit
modes 4 bytes per pixel). You can create and manipulate bitmaps in system
RAM, or you can write to the special `screen' bitmap which represents the
video memory in your graphics card.

Read chapter "Direct access to video memory" for information on how to get
direct access to the image memory in a bitmap.

Allegro supports several different types of bitmaps:

@itemize @bullet
@item 
The `screen' bitmap, which represents the hardware video memory. Ultimately
you have to draw onto this in order for your image to be visible. It is
destroyed by any subsequent calls to set_gfx_mode(), so you should never
attempt to destroy it yourself.
@item 
Memory bitmaps, which are located in system RAM and can be used to store
graphics or as temporary drawing spaces for double buffered systems. These
can be obtained by calling create_bitmap(), load_pcx(), or by loading a
grabber datafile.
@item 
Sub-bitmaps. These share image memory with a parent bitmap (which can be
the screen, a video or system bitmap, a memory bitmap, or another
sub-bitmap), so drawing onto them will also change their parent. They can
be of any size and located anywhere within the parent bitmap, and can have
their own clipping rectangles, so they are a useful way of dividing a
bitmap into several smaller units, eg. splitting a large virtual screen
into multiple sections (see examples/exscroll.c).

Warning: Make sure not to destroy a bitmap before all of its sub-bitmaps,
otherwise bad things will happen when you try to access one of these
sub-bitmaps.
@item 
Video memory bitmaps. These are created by the create_video_bitmap()
function, and are usually implemented as sub-bitmaps of the screen object.
They must be destroyed by destroy_bitmap() before any subsequent calls to
set_gfx_mode().
@item 
System bitmaps. These are created by the create_system_bitmap() function,
and are a sort of halfway house between memory and video bitmaps. They
live in system memory, so you aren't limited by the amount of video ram in
your card, but they are stored in a platform-specific format that may
enable better hardware acceleration than is possible with a normal memory
bitmap (see the GFX_HW_SYS_TO_VRAM_BLIT and GFX_HW_SYS_TO_VRAM_BLIT_MASKED
flags in gfx_capabilities). System bitmaps must be accessed in the same way
as video bitmaps, using the bank switch functions and bmp_write*() macros.
Not every platform implements this type of bitmap: if they aren't
available, create_system_bitmap() will function identically to
create_bitmap(). They must be destroyed by destroy_bitmap() before any
subsequent calls to set_gfx_mode().
@end itemize


@menu
* screen::
* SCREEN_W::
* VIRTUAL_W::
* create_bitmap::
* create_bitmap_ex::
* create_sub_bitmap::
* create_video_bitmap::
* create_system_bitmap::
* destroy_bitmap::
* lock_bitmap::
* bitmap_color_depth::
* bitmap_mask_color::
* is_same_bitmap::
* is_planar_bitmap::
* is_linear_bitmap::
* is_memory_bitmap::
* is_screen_bitmap::
* is_video_bitmap::
* is_system_bitmap::
* is_sub_bitmap::
* acquire_bitmap::
* release_bitmap::
* acquire_screen::
* release_screen::
* set_clip_rect::
* get_clip_rect::
* add_clip_rect::
* set_clip_state::
* get_clip_state::
* is_inside_bitmap::
@end menu
@node screen, SCREEN_W, vsync, Bitmap
@subsection screen
@ftable @asis
@item @t{extern BITMAP *screen;}
Global pointer to a bitmap, sized VIRTUAL_W x VIRTUAL_H. This is created 
by set_gfx_mode(), and represents the hardware video memory. Only a part 
of this bitmap will actually be visible, sized SCREEN_W x SCREEN_H. 
Normally this is the top left corner of the larger virtual screen, so you 
can ignore the extra invisible virtual size of the bitmap if you aren't 
interested in hardware scrolling or page flipping. To move the visible 
window to other parts of the screen bitmap, call scroll_screen(). 
Initially the clipping rectangle will be limited to the physical screen 
size, so if you want to draw onto a larger virtual screen space outside 
this rectangle, you will need to adjust the clipping.

For example, to draw a pixel onto the screen you would write:
@example

putpixel(screen, x, y, color);
@end example

Or to implement a double-buffered system:
@example

/* Make a bitmap in RAM. */
BITMAP *bmp = create_bitmap(320, 200);
/* Clean the memory bitmap. */
clear_bitmap(bmp);
/* Draw onto the memory bitmap. */
putpixel(bmp, x, y, color);
/* Copy it to the screen. */
blit(bmp, screen, 0, 0, 0, 0, 320, 200);@end example


Warning: be very careful when using this pointer at the same time as any
bitmaps created by the create_video_bitmap() function (see the description
of this function for more detailed information). And never try to destroy
it with destroy_bitmap().

@end ftable
See also:@*
@xref{set_gfx_mode}.@*
@xref{is_screen_bitmap}.@*
@xref{create_video_bitmap}.@*
@xref{scroll_screen}.@*
@xref{Available, Available Allegro examples}.@*
@xref{BITMAP}.@*
@node SCREEN_W, VIRTUAL_W, screen, Bitmap
@subsection SCREEN_W
@ftable @asis
@item @t{#define SCREEN_W;}
@end ftable
@ftable @asis
@item @t{#define SCREEN_H;}
Global defines that return the width and height of the screen, or zero if
the screen has not been initialised yet. Example:
@example

char buf[100];
...
uszprintf(buf, sizeof(buf),
          "The screen size is %d x %d pixels",
          SCREEN_W, SCREEN_H);@end example


@end ftable
See also:@*
@xref{screen}.@*
@xref{set_gfx_mode}.@*
@xref{VIRTUAL_W}.@*
@xref{VIRTUAL_W, VIRTUAL_H}.@*
@xref{Available, Available Allegro examples}.@*
@node VIRTUAL_W, create_bitmap, SCREEN_W, Bitmap
@subsection VIRTUAL_W
@ftable @asis
@item @t{#define VIRTUAL_W;}
@end ftable
@ftable @asis
@item @t{#define VIRTUAL_H;}
Global defines that return the width and height of the virtual screen, or
zero if the screen has not been initialised yet. Example:
@example

char buf[100];
...
uszprintf(buf, sizeof(buf),
          "The virtual screen size is %d x %d pixels",
          SCREEN_W, SCREEN_H);@end example


@end ftable
See also:@*
@xref{screen}.@*
@xref{set_gfx_mode}.@*
@xref{SCREEN_W}.@*
@xref{SCREEN_W, SCREEN_H}.@*
@node create_bitmap, create_bitmap_ex, VIRTUAL_W, Bitmap
@subsection create_bitmap
@ftable @asis
@item @t{BITMAP *create_bitmap(int width, int height);}
Creates a memory bitmap sized width by height. The bitmap will have
clipping turned on, and the clipping rectangle set to the full size of the
bitmap. The image memory will not be cleared, so it will probably contain
garbage: you should clear the bitmap before using it. This routine always
uses the global pixel format, as specified by calling set_color_depth().
The minimum height of the BITMAP must be 1 and width can't be negative.
Example:
@example

/* Create a 10 pixel tall bitmap, as wide as the screen. */
BITMAP *bmp = create_bitmap(SCREEN_W, 10);
if (!bmp)
   abort_on_error("Couldn't create bitmap!");
/* Use the bitmap. */
...
/* Destroy it when we don't need it any more. */
destroy_bitmap(bmp);@end example


Returns a pointer to the created bitmap, or NULL if the bitmap could not
be created. Remember to free this bitmap later to avoid memory leaks.

@end ftable
See also:@*
@xref{create_bitmap_ex}.@*
@xref{create_sub_bitmap}.@*
@xref{create_video_bitmap}.@*
@xref{create_system_bitmap}.@*
@xref{destroy_bitmap}.@*
@xref{set_color_depth}.@*
@xref{is_memory_bitmap}.@*
@xref{clear_bitmap}.@*
@xref{clear_to_color}.@*
@xref{Available, Available Allegro examples}.@*
@xref{BITMAP}.@*
@node create_bitmap_ex, create_sub_bitmap, create_bitmap, Bitmap
@subsection create_bitmap_ex
@ftable @asis
@item @t{BITMAP *create_bitmap_ex(int color_depth, int width, int height);}
Creates a bitmap in a specific color depth (8, 15, 16, 24 or 32 bits per 
pixel). Example:
@example

/* Create screen sized bitmap in 32 bits per pixel. */
BITMAP *bmp = create_bitmap_ex(32, SCREEN_W, SCREEN_H);
if (!bmp)
   abort_on_error("Couldn't create bitmap!");
/* Use the bitmap. */
...
/* Destroy it when we don't need it any more. */
destroy_bitmap(bmp);@end example


Returns a pointer to the created bitmap, or NULL if the bitmap could not
be created. Remember to free this bitmap later to avoid memory leaks.


@end ftable
See also:@*
@xref{create_bitmap}.@*
@xref{create_sub_bitmap}.@*
@xref{create_video_bitmap}.@*
@xref{create_system_bitmap}.@*
@xref{destroy_bitmap}.@*
@xref{is_memory_bitmap}.@*
@xref{clear_bitmap}.@*
@xref{clear_to_color}.@*
@xref{ex12bit}.@*
@xref{exlights}.@*
@xref{exrgbhsv}.@*
@xref{extrans}.@*
@xref{BITMAP}.@*
@node create_sub_bitmap, create_video_bitmap, create_bitmap_ex, Bitmap
@subsection create_sub_bitmap
@ftable @asis
@item @t{BITMAP *create_sub_bitmap(BITMAP *parent, int x, y, width, height);}
Creates a sub-bitmap, ie. a bitmap sharing drawing memory with a 
pre-existing bitmap, but possibly with a different size and clipping 
settings. When creating a sub-bitmap of the mode-X screen, the x position 
must be a multiple of four. The sub-bitmap width and height can extend 
beyond the right and bottom edges of the parent (they will be clipped), 
but the origin point must lie within the parent region.

Returns a pointer to the created sub bitmap, or NULL if the sub bitmap
could not be created. Remember to free the sub bitmap before freeing
the parent bitmap to avoid memory leaks and potential crashes accessing
memory which has been freed.

@end ftable
See also:@*
@xref{create_bitmap}.@*
@xref{create_bitmap_ex}.@*
@xref{destroy_bitmap}.@*
@xref{is_sub_bitmap}.@*
@xref{clear_bitmap}.@*
@xref{clear_to_color}.@*
@xref{expat}.@*
@xref{exscroll}.@*
@xref{exswitch}.@*
@xref{BITMAP}.@*
@node create_video_bitmap, create_system_bitmap, create_sub_bitmap, Bitmap
@subsection create_video_bitmap
@ftable @asis
@item @t{BITMAP *create_video_bitmap(int width, int height);}
Allocates a video memory bitmap of the specified size. This can be used
to allocate offscreen video memory for storing source graphics ready for
a hardware accelerated blitting operation, or to create multiple video
memory pages which can then be displayed by calling show_video_bitmap().
Read the introduction of this chapter for a comparison with other types
of bitmaps and other specific details.

Warning: video memory bitmaps are usually allocated from the same space
as the screen bitmap, so they may overlap with it; it is therefore not
a good idea to use the global screen at the same time as any surfaces
returned by this function.

Returns a pointer to the bitmap on success, or NULL if you have run out
of video ram. Remember to destroy this bitmap before any subsequent
call to set_gfx_mode().

@end ftable
See also:@*
@xref{create_bitmap}.@*
@xref{create_bitmap_ex}.@*
@xref{create_system_bitmap}.@*
@xref{create_sub_bitmap}.@*
@xref{destroy_bitmap}.@*
@xref{screen}.@*
@xref{show_video_bitmap}.@*
@xref{gfx_capabilities}.@*
@xref{is_video_bitmap}.@*
@xref{clear_bitmap}.@*
@xref{clear_to_color}.@*
@xref{ex3buf}.@*
@xref{exaccel}.@*
@xref{exflip}.@*
@xref{exupdate}.@*
@xref{BITMAP}.@*
@node create_system_bitmap, destroy_bitmap, create_video_bitmap, Bitmap
@subsection create_system_bitmap
@ftable @asis
@item @t{BITMAP *create_system_bitmap(int width, int height);}
Allocates a system memory bitmap of the specified size. Read the
introduction of this chapter for a comparison with other types of bitmaps
and other specific details.

Returns a pointer to the bitmap on success, NULL otherwise. Remember to
destroy this bitmap before any subsequent call to set_gfx_mode().

@end ftable
See also:@*
@xref{create_bitmap}.@*
@xref{create_bitmap_ex}.@*
@xref{create_video_bitmap}.@*
@xref{create_sub_bitmap}.@*
@xref{destroy_bitmap}.@*
@xref{is_system_bitmap}.@*
@xref{clear_bitmap}.@*
@xref{clear_to_color}.@*
@xref{exupdate}.@*
@xref{BITMAP}.@*
@node destroy_bitmap, lock_bitmap, create_system_bitmap, Bitmap
@subsection destroy_bitmap
@ftable @asis
@item @t{void destroy_bitmap(BITMAP *bitmap);}
Destroys a memory bitmap, sub-bitmap, video memory bitmap, or system 
bitmap when you are finished with it. If you pass a NULL pointer this
function won't do anything. See above for the restrictions as to when you
are allowed to destroy the various types of bitmaps.

The bitmap must not have a mouse cursor shown on it at the time it is
destroyed.

@end ftable
See also:@*
@xref{create_bitmap}.@*
@xref{load_bitmap}.@*
@xref{show_mouse}.@*
@xref{Available, Available Allegro examples}.@*
@xref{BITMAP}.@*
@node lock_bitmap, bitmap_color_depth, destroy_bitmap, Bitmap
@subsection lock_bitmap
@ftable @asis
@item @t{void lock_bitmap(BITMAP *bitmap);}
Under DOS, locks all the memory used by a bitmap. You don't normally need
to call this function unless you are doing very weird things in your
program.

@end ftable
@xref{BITMAP}.@*
@node bitmap_color_depth, bitmap_mask_color, lock_bitmap, Bitmap
@subsection bitmap_color_depth
@ftable @asis
@item @t{int bitmap_color_depth(BITMAP *bmp);}
Returns the color depth of the specified bitmap (8, 15, 16, 24, or 32).
Example:
@example

switch (bitmap_color_depth(screen)) @{
   case 8:
      /* Access screen using optimized 8-bit code. */
      break;
   default:
      /* Use generic slow functions. */
      break;
@}@end example


@end ftable
See also:@*
@xref{set_color_depth}.@*
@xref{bitmap_mask_color}.@*
@xref{ex3d}.@*
@xref{exlights}.@*
@xref{exscn3d}.@*
@xref{exswitch}.@*
@xref{extrans}.@*
@xref{exupdate}.@*
@xref{exzbuf}.@*
@xref{BITMAP}.@*
@node bitmap_mask_color, is_same_bitmap, bitmap_color_depth, Bitmap
@subsection bitmap_mask_color
@ftable @asis
@item @t{int bitmap_mask_color(BITMAP *bmp);}
Returns the mask color for the specified bitmap (the value which is 
skipped when drawing sprites). For 256-color bitmaps this is zero, and 
for truecolor bitmaps it is bright pink (maximum red and blue, zero
green). A frequent use of this function is to clear a bitmap with the mask
color so you can later use this bitmap with masked_blit() or
draw_sprite() after drawing other stuff on it. Example:
@example

/* Replace mask color with another color. */
for (y = 0; y h; y++)
   for (x = 0; x w; x++)
      if (getpixel(bmp, x, y) == bitmap_mask_color(bmp))
         putpixel(bmp, x, y, another_color);@end example


@end ftable
See also:@*
@xref{MASK_COLOR_8}.@*
@xref{set_color_depth}.@*
@xref{bitmap_color_depth}.@*
@xref{ex3d}.@*
@xref{exmouse}.@*
@xref{expat}.@*
@xref{BITMAP}.@*
@node is_same_bitmap, is_planar_bitmap, bitmap_mask_color, Bitmap
@subsection is_same_bitmap
@ftable @asis
@item @t{int is_same_bitmap(BITMAP *bmp1, BITMAP *bmp2);}
Returns TRUE if the two bitmaps describe the same drawing surface, ie. 
the pointers are equal, one is a sub-bitmap of the other, or they are 
both sub-bitmaps of a common parent.

@end ftable
See also:@*
@xref{create_sub_bitmap}.@*
@xref{BITMAP}.@*
@node is_planar_bitmap, is_linear_bitmap, is_same_bitmap, Bitmap
@subsection is_planar_bitmap
@ftable @asis
@item @t{int is_planar_bitmap(BITMAP *bmp);}
Returns TRUE if bmp is a planar (mode-X or Xtended mode) screen bitmap.

@end ftable
See also:@*
@xref{is_linear_bitmap}.@*
@xref{is_memory_bitmap}.@*
@xref{BITMAP}.@*
@node is_linear_bitmap, is_memory_bitmap, is_planar_bitmap, Bitmap
@subsection is_linear_bitmap
@ftable @asis
@item @t{int is_linear_bitmap(BITMAP *bmp);}
Returns TRUE if bmp is a linear bitmap, i.e. a bitmap that can be accessed
linearly within each scanline (for example a memory bitmap, the DOS VGA
or SVGA screen, Windows bitmaps, etc). Linear bitmaps can be used with the
_putpixel(), _getpixel(), bmp_write_line(), and bmp_read_line() functions.

Historically there were only linear and planar bitmaps for Allegro, so
is_linear_bitmap() is actually an alias for !is_planar_bitmap().

@end ftable
See also:@*
@xref{is_planar_bitmap}.@*
@xref{is_memory_bitmap}.@*
@xref{BITMAP}.@*
@node is_memory_bitmap, is_screen_bitmap, is_linear_bitmap, Bitmap
@subsection is_memory_bitmap
@ftable @asis
@item @t{int is_memory_bitmap(BITMAP *bmp);}
Returns TRUE if bmp is a memory bitmap, ie. it was created by calling 
create_bitmap() or loaded from a grabber datafile or image file. Memory 
bitmaps can be accessed directly via the line pointers in the bitmap 
structure, eg. bmp->line[y][x] = color.

@end ftable
See also:@*
@xref{is_linear_bitmap}.@*
@xref{is_planar_bitmap}.@*
@xref{BITMAP}.@*
@node is_screen_bitmap, is_video_bitmap, is_memory_bitmap, Bitmap
@subsection is_screen_bitmap
@ftable @asis
@item @t{int is_screen_bitmap(BITMAP *bmp);}
Returns TRUE if bmp is the screen bitmap, or a sub-bitmap of the screen.

@end ftable
See also:@*
@xref{screen}.@*
@xref{create_sub_bitmap}.@*
@xref{BITMAP}.@*
@node is_video_bitmap, is_system_bitmap, is_screen_bitmap, Bitmap
@subsection is_video_bitmap
@ftable @asis
@item @t{int is_video_bitmap(BITMAP *bmp);}
Returns TRUE if bmp is the screen bitmap, a video memory bitmap, or a 
sub-bitmap of either.

@end ftable
See also:@*
@xref{screen}.@*
@xref{create_video_bitmap}.@*
@xref{create_sub_bitmap}.@*
@xref{BITMAP}.@*
@node is_system_bitmap, is_sub_bitmap, is_video_bitmap, Bitmap
@subsection is_system_bitmap
@ftable @asis
@item @t{int is_system_bitmap(BITMAP *bmp);}
Returns TRUE if bmp is a system bitmap object, or a sub-bitmap of one.

@end ftable
See also:@*
@xref{create_system_bitmap}.@*
@xref{create_sub_bitmap}.@*
@xref{BITMAP}.@*
@node is_sub_bitmap, acquire_bitmap, is_system_bitmap, Bitmap
@subsection is_sub_bitmap
@ftable @asis
@item @t{int is_sub_bitmap(BITMAP *bmp);}
Returns TRUE if bmp is a sub-bitmap.

@end ftable
See also:@*
@xref{create_sub_bitmap}.@*
@xref{BITMAP}.@*
@node acquire_bitmap, release_bitmap, is_sub_bitmap, Bitmap
@subsection acquire_bitmap
@ftable @asis
@item @t{void acquire_bitmap(BITMAP *bmp);}
Acquires the specified video bitmap prior to drawing onto it. You never need
to call the function explicitly as it is low level, and will only give you a
speed up if you know what you are doing. Using it wrongly may cause slowdown,
or even lock up your program.

Note: You do never need to use acquire_bitmap on a memory bitmap, i.e. a
normal bitmap created with create_bitmap. It will simply do nothing in that
case.

It still can be useful, because e.g. under the current DirectDraw driver of
Allegro, most drawing functions need to lock a video bitmap before drawing to
it. But doing this is very slow, so you will get much better performance if
you acquire the screen just once at the start of your main redraw function,
then call multiple drawing operations which need the bitmap locked, and only
release it when done.

Multiple acquire calls may be nested, but you must make sure to match up the
acquire_bitmap and release_bitmap calls. Be warned that DirectX and X11
programs activate a mutex lock whenever a surface is locked, which prevents
them from getting any input messages, so you must be sure to release all your
bitmaps before using any timer, keyboard, or other non-graphics routines!

Note that if you are using hardware accelerated VRAM->VRAM functions, you
should not call acquire_bitmap(). Such functions need an unlocked target
bitmap under DirectX, so there is now just the opposite case from before - if
the bitmap is already locked with acquire_bitmap, the drawing
operation has to unlock it.

Note: For backwards compatibility, the unlocking behavior of such functions
is permanent. That is, if you call acquire_bitmap first, then call e.g. an
accelerated blit, the DirectX bitmap will be unlocked internally (it won't
affect the nesting counter of acquire/release calls).

There is no clear cross-platform way in this Allegro version to know which
drawing operations need a locked/unlocked state. For example a normal
rectfill most probably is accelerated under DirectX, and therefore needs the
screen unlocked, but an XOR rectfill, or one with blending activated, most
probably is not, and therefore locks the screen. And while the DirectX driver
will do automatic unlocking, there is no such thing under X11, where the
function is used to synchronize X11 calls from different threads. Your best
bet is to never use acquire_bitmap - changes are you are doing something in
the wrong way if you think you need it.

Warning: This function can be very dangerous to use, since the whole program
may get locked while the bitmap is locked. So the lock should only be held
for a short time, and you should not call anything but drawing operations
onto the locked video bitmap while a lock is in place. Especially don't call
things like show_mouse (or scare_mouse which calls that) or readkey, since
it will most likely deadlock your entire program.

@end ftable
See also:@*
@xref{release_bitmap}.@*
@xref{acquire_screen}.@*
@xref{release_screen}.@*
@xref{ex3buf}.@*
@xref{exaccel}.@*
@xref{expat}.@*
@xref{exquat}.@*
@xref{exscroll}.@*
@xref{exswitch}.@*
@xref{exupdate}.@*
@xref{BITMAP}.@*
@node release_bitmap, acquire_screen, acquire_bitmap, Bitmap
@subsection release_bitmap
@ftable @asis
@item @t{void release_bitmap(BITMAP *bmp);}
Releases a bitmap that was previously locked by calling acquire_bitmap(). 
If the bitmap was locked multiple times, you must release it the same 
number of times before it will truly be unlocked.

@end ftable
See also:@*
@xref{acquire_bitmap}.@*
@xref{acquire_screen}.@*
@xref{release_screen}.@*
@xref{ex3buf}.@*
@xref{exaccel}.@*
@xref{expat}.@*
@xref{exquat}.@*
@xref{exscroll}.@*
@xref{exswitch}.@*
@xref{exupdate}.@*
@xref{BITMAP}.@*
@node acquire_screen, release_screen, release_bitmap, Bitmap
@subsection acquire_screen
@ftable @asis
@item @t{void acquire_screen();}
Shortcut version of acquire_bitmap(screen);

@end ftable
See also:@*
@xref{acquire_bitmap}.@*
@xref{release_bitmap}.@*
@xref{release_screen}.@*
@xref{Available, Available Allegro examples}.@*
@node release_screen, set_clip_rect, acquire_screen, Bitmap
@subsection release_screen
@ftable @asis
@item @t{void release_screen();}
Shortcut version of release_bitmap(screen);

@end ftable
See also:@*
@xref{acquire_bitmap}.@*
@xref{release_bitmap}.@*
@xref{acquire_screen}.@*
@xref{Available, Available Allegro examples}.@*
@node set_clip_rect, get_clip_rect, release_screen, Bitmap
@subsection set_clip_rect
@ftable @asis
@item @t{void set_clip_rect(BITMAP *bitmap, int x1, int y1, int x2, int y2);}
Each bitmap has an associated clipping rectangle, which is the area of 
the image that it is OK to draw onto. Nothing will be drawn to positions
outside this space. This function sets the clipping rectangle for the
specified bitmap. Pass the coordinates of the top-left and bottom-right
corners of the clipping rectangle in this order; these are both inclusive,
i.e. set_clip_rect(bitmap, 16, 16, 32, 32) will allow drawing to (16, 16)
and (32, 32), but not to (15, 15) and (33, 33).

Drawing operations will be performed (at least partially) on the bitmap as
long as the first coordinates of its clipping rectangle are not greater
than the second coordinates and its intersection with the actual image
is non-empty. If either condition is not fulfilled, drawing will be turned
off for the bitmap, e.g.
@example

set_clip_rect(bmp, 0, 0, -1, -1); /* disable drawing on bmp */@end example


Note that passing "out-of-bitmap" coordinates is allowed, but they are
likely to be altered (and so the coordinates returned by get_clip_rect()
will be different). However, such modifications are guaranteed to preserve
the external effect of the clipping rectangle, that is not to modify the
actual area of the image that it is OK to draw onto.

@end ftable
See also:@*
@xref{get_clip_rect}.@*
@xref{add_clip_rect}.@*
@xref{set_clip_state}.@*
@xref{get_clip_state}.@*
@xref{ex12bit}.@*
@xref{excamera}.@*
@xref{BITMAP}.@*
@node get_clip_rect, add_clip_rect, set_clip_rect, Bitmap
@subsection get_clip_rect
@ftable @asis
@item @t{void get_clip_rect(BITMAP *bitmap, int *x1, int *y1, int *x2, int *y2);}
Returns the clipping rectangle for the specified bitmap.

@end ftable
See also:@*
@xref{set_clip_rect}.@*
@xref{add_clip_rect}.@*
@xref{set_clip_state}.@*
@xref{get_clip_state}.@*
@xref{BITMAP}.@*
@node add_clip_rect, set_clip_state, get_clip_rect, Bitmap
@subsection add_clip_rect
@ftable @asis
@item @t{void add_clip_rect(BITMAP *bitmap, int x1, int y1, int x2, int y2);}
Sets the clipping rectangle of the specified bitmap as the intersection of
its current clipping rectangle and the rectangle described by the four
coordinates.

@end ftable
See also:@*
@xref{set_clip_rect}.@*
@xref{get_clip_rect}.@*
@xref{set_clip_state}.@*
@xref{get_clip_state}.@*
@xref{BITMAP}.@*
@node set_clip_state, get_clip_state, add_clip_rect, Bitmap
@subsection set_clip_state
@ftable @asis
@item @t{void set_clip_state(BITMAP *bitmap, int state)}
Turns on (if state is non-zero) or off (if state is zero) clipping for the
specified bitmap. Turning clipping off may slightly speed up some drawing
operations (usually a negligible  difference, although every little helps)
but will result in your program dying a horrible death if you try to draw
beyond the edges of the bitmap.

@end ftable
See also:@*
@xref{set_clip_rect}.@*
@xref{get_clip_rect}.@*
@xref{add_clip_rect}.@*
@xref{get_clip_state}.@*
@xref{BITMAP}.@*
@node get_clip_state, is_inside_bitmap, set_clip_state, Bitmap
@subsection get_clip_state
@ftable @asis
@item @t{int get_clip_state(BITMAP *bitmap)}
Returns non-zero if clipping is turned on for the specified bitmap and
zero otherwise.

@end ftable
See also:@*
@xref{set_clip_rect}.@*
@xref{get_clip_rect}.@*
@xref{add_clip_rect}.@*
@xref{set_clip_state}.@*
@xref{BITMAP}.@*
@node is_inside_bitmap, load_bitmap, get_clip_state, Bitmap
@subsection is_inside_bitmap
@ftable @asis
@item @t{int is_inside_bitmap(BITMAP *bmp, int x, int y, int clip);}
Returns non-zero if point (x, y) lies inside the bitmap. If `clip' is
non-zero, the function compares the coordinates with the clipping
rectangle, that is it returns non-zero if the point lies inside the
clipping rectangle or if clipping is disabled for the bitmap. If `clip'
is zero, the function compares the coordinates with the actual dimensions
of the bitmap.



@end ftable
See also:@*
@xref{set_clip_rect}.@*
@xref{set_clip_state}.@*
@xref{getpixel}.@*
@xref{BITMAP}.@*
@node Loading, Palette, Bitmap, API
@section Loading image files

Warning: when using truecolor images, you should always set the graphics
mode before loading any bitmap data! Otherwise the pixel format (RGB or BGR)
will not be known, so the file may be converted wrongly.

@menu
* load_bitmap::
* load_bmp::
* load_bmp_pf::
* load_lbm::
* load_pcx::
* load_pcx_pf::
* load_tga::
* load_tga_pf::
* save_bitmap::
* save_bmp::
* save_bmp_pf::
* save_pcx::
* save_pcx_pf::
* save_tga::
* save_tga_pf::
* register_bitmap_file_type::
* set_color_conversion::
* get_color_conversion::
@end menu
@node load_bitmap, load_bmp, is_inside_bitmap, Loading
@subsection load_bitmap
@ftable @asis
@item @t{BITMAP *load_bitmap(const char *filename, RGB *pal);}
Loads a bitmap from a file. The palette data will be stored in the second
parameter, which should be an array of 256 RGB structures. At present this
function supports BMP, LBM, PCX, and TGA files, determining the type from
the file extension.

If the file contains a truecolor image, you must set the video mode or
call set_color_conversion() before loading it. In this case, if the
destination color depth is 8-bit, the palette will be generated by calling
generate_optimized_palette() on the bitmap; otherwise, the returned
palette will be generated by calling generate_332_palette().

The pal argument may be NULL. In this case, the palette data are simply
not returned. Additionally, if the file is a truecolor image and the
destination color depth is 8-bit, the color conversion process will use
the current palette instead of generating an optimized one.

Example:
@example

BITMAP *bmp;
PALETTE palette;
...
bmp = load_bitmap("image.pcx", palette);
if (!bmp)
   abort_on_error("Couldn't load image.pcx!");
...
destroy_bitmap(bmp);@end example


Returns a pointer to the bitmap or NULL on error. Remember that you are
responsible for destroying the bitmap when you are finished with it to
avoid memory leaks.

@end ftable
See also:@*
@xref{load_bmp}.@*
@xref{load_lbm}.@*
@xref{load_pcx}.@*
@xref{load_tga}.@*
@xref{destroy_bitmap}.@*
@xref{save_bitmap}.@*
@xref{register_bitmap_file_type}.@*
@xref{set_color_depth}.@*
@xref{set_color_conversion}.@*
@xref{generate_optimized_palette}.@*
@xref{generate_332_palette}.@*
@xref{exaccel}.@*
@xref{exalpha}.@*
@xref{exbitmap}.@*
@xref{exblend}.@*
@xref{exconfig}.@*
@xref{exlights}.@*
@xref{exshade}.@*
@xref{extrans}.@*
@xref{exxfade}.@*
@xref{BITMAP}.@*
@xref{RGB}.@*
@node load_bmp, load_bmp_pf, load_bitmap, Loading
@subsection load_bmp
@ftable @asis
@item @t{BITMAP *load_bmp(const char *filename, RGB *pal);}
Loads an 8-bit, 16-bit, 24-bit or 32-bit Windows or OS/2 BMP file.

Returns a pointer to the bitmap or NULL on error. Remember that you are
responsible for destroying the bitmap when you are finished with it to
avoid memory leaks.

@end ftable
See also:@*
@xref{load_bitmap}.@*
@xref{load_bmp_pf}.@*
@xref{BITMAP}.@*
@xref{RGB}.@*
@node load_bmp_pf, load_lbm, load_bmp, Loading
@subsection load_bmp_pf
@ftable @asis
@item @t{BITMAP *load_bmp_pf(PACKFILE *f, RGB *pal);}
A version of load_bmp() which reads from a packfile. Example:
@example

PACKFILE *packfile;
BITMAP *bmp;

packfile = pack_fopen("mybitmap.bmp", F_READ);
if (!packfile)
   abort_on_error("Couldn't open mybitmap.bmp");
   
bmp = load_bmp_pf(packfile, pal);
if (!bmp)
   abort_on_error("Error loading mybitmap.bmp");@end example


Returns a pointer to the bitmap or NULL on error. Remember that you are
responsible for destroying the bitmap when you are finished with it to
avoid memory leaks.

@end ftable
See also:@*
@xref{load_bmp}.@*
@xref{expackf}.@*
@xref{BITMAP}.@*
@xref{RGB}.@*
@xref{PACKFILE}.@*
@node load_lbm, load_pcx, load_bmp_pf, Loading
@subsection load_lbm
@ftable @asis
@item @t{BITMAP *load_lbm(const char *filename, RGB *pal);}
Loads a 256-color IFF ILBM/PBM file.

Returns a pointer to the bitmap or NULL on error. Remember that you are
responsible for destroying the bitmap when you are finished with it to
avoid memory leaks.

@end ftable
See also:@*
@xref{load_bitmap}.@*
@xref{BITMAP}.@*
@xref{RGB}.@*
@node load_pcx, load_pcx_pf, load_lbm, Loading
@subsection load_pcx
@ftable @asis
@item @t{BITMAP *load_pcx(const char *filename, RGB *pal);}
Loads a 256-color or 24-bit truecolor PCX file.

Returns a pointer to the bitmap or NULL on error. Remember that you are
responsible for destroying the bitmap when you are finished with it to
avoid memory leaks.

@end ftable
See also:@*
@xref{load_bitmap}.@*
@xref{expackf}.@*
@xref{exscale}.@*
@xref{BITMAP}.@*
@xref{RGB}.@*
@node load_pcx_pf, load_tga, load_pcx, Loading
@subsection load_pcx_pf
@ftable @asis
@item @t{BITMAP *load_pcx_pf(PACKFILE *f, RGB *pal);}
A version of load_pcx() which reads from a packfile. Example:
@example

PACKFILE *packfile;
BITMAP *bmp;

packfile = pack_fopen("mybitmap.pcx", F_READ);
if (!packfile)
   abort_on_error("Couldn't open mybitmap.pcx");
   
bmp = load_bmp_pf(packfile, pal);
if (!bmp)
   abort_on_error("Error loading mybitmap.pcx");@end example


Returns a pointer to the bitmap or NULL on error. Remember that you are
responsible for destroying the bitmap when you are finished with it to
avoid memory leaks.

@end ftable
See also:@*
@xref{load_pcx}.@*
@xref{expackf}.@*
@xref{BITMAP}.@*
@xref{RGB}.@*
@xref{PACKFILE}.@*
@node load_tga, load_tga_pf, load_pcx_pf, Loading
@subsection load_tga
@ftable @asis
@item @t{BITMAP *load_tga(const char *filename, RGB *pal);}
Loads a 256-color, 15-bit hicolor, 24-bit truecolor, or 32-bit 
truecolor+alpha TGA file.

Returns a pointer to the bitmap or NULL on error. Remember that you are
responsible for destroying the bitmap when you are finished with it to
avoid memory leaks.

@end ftable
See also:@*
@xref{load_bitmap}.@*
@xref{BITMAP}.@*
@xref{RGB}.@*
@node load_tga_pf, save_bitmap, load_tga, Loading
@subsection load_tga_pf
@ftable @asis
@item @t{BITMAP *load_tga_pf(PACKFILE *f, RGB *pal);}
A version of load_tga() which reads from a packfile. Example:
@example

PACKFILE *packfile;
BITMAP *bmp;

packfile = pack_fopen("mybitmap.tga", F_READ);
if (!packfile)
   abort_on_error("Couldn't open mybitmap.tga");
   
bmp = load_bmp_pf(packfile, pal);
if (!bmp)
   abort_on_error("Error loading mybitmap.tga");@end example


Returns a pointer to the bitmap or NULL on error. Remember that you are
responsible for destroying the bitmap when you are finished with it to
avoid memory leaks.

@end ftable
See also:@*
@xref{load_tga}.@*
@xref{expackf}.@*
@xref{BITMAP}.@*
@xref{RGB}.@*
@xref{PACKFILE}.@*
@node save_bitmap, save_bmp, load_tga_pf, Loading
@subsection save_bitmap
@ftable @asis
@item @t{int save_bitmap(const char *filename, BITMAP *bmp, const RGB *pal);}
Writes a bitmap into a file, using the specified palette, which should be 
an array of 256 RGB structures. The output format is determined from the
filename extension: at present this function supports BMP, PCX and TGA
formats.

Two things to watch out for: on some video cards it may be faster to copy
the screen to a memory bitmap and save the latter, and if you use this to
dump the screen into a file you may end up with an image much larger than
you were expecting, because Allegro often creates virtual screens larger
than the visible screen. You can get around this by using a sub-bitmap to
specify which part of the screen to save, eg:
@example

BITMAP *bmp;
PALETTE pal;
...
get_palette(pal);
bmp = create_sub_bitmap(screen, 0, 0, SCREEN_W, SCREEN_H);
save_bitmap("dump.pcx", bmp, pal);
destroy_bitmap(bmp);@end example


Returns non-zero on error.

@end ftable
See also:@*
@xref{save_bmp}.@*
@xref{save_pcx}.@*
@xref{save_tga}.@*
@xref{load_bitmap}.@*
@xref{register_bitmap_file_type}.@*
@xref{BITMAP}.@*
@xref{RGB}.@*
@node save_bmp, save_bmp_pf, save_bitmap, Loading
@subsection save_bmp
@ftable @asis
@item @t{int save_bmp(const char *filename, BITMAP *bmp, const RGB *pal);}
Writes a bitmap into a 256-color or 24-bit truecolor BMP file.

Returns non-zero on error.

@end ftable
See also:@*
@xref{save_bitmap}.@*
@xref{BITMAP}.@*
@xref{RGB}.@*
@node save_bmp_pf, save_pcx, save_bmp, Loading
@subsection save_bmp_pf
@ftable @asis
@item @t{int save_bmp_pf(PACKFILE *f, BITMAP *bmp, RGB *pal);}
A version of save_bmp which writes to a packfile.

@end ftable
See also:@*
@xref{save_bmp}.@*
@xref{expackf}.@*
@xref{BITMAP}.@*
@xref{RGB}.@*
@xref{PACKFILE}.@*
@node save_pcx, save_pcx_pf, save_bmp_pf, Loading
@subsection save_pcx
@ftable @asis
@item @t{int save_pcx(const char *filename, BITMAP *bmp, const RGB *pal);}
Writes a bitmap into a 256-color or 24-bit truecolor PCX file.

Returns non-zero on error.

@end ftable
See also:@*
@xref{save_bitmap}.@*
@xref{BITMAP}.@*
@xref{RGB}.@*
@node save_pcx_pf, save_tga, save_pcx, Loading
@subsection save_pcx_pf
@ftable @asis
@item @t{int save_pcx_pf(PACKFILE *f, BITMAP *bmp, RGB *pal);}
A version of save_pcx which writes to a packfile.

@end ftable
See also:@*
@xref{save_pcx}.@*
@xref{BITMAP}.@*
@xref{RGB}.@*
@xref{PACKFILE}.@*
@node save_tga, save_tga_pf, save_pcx_pf, Loading
@subsection save_tga
@ftable @asis
@item @t{int save_tga(const char *filename, BITMAP *bmp, const RGB *pal);}
Writes a bitmap into a 256-color, 15-bit hicolor, 24-bit truecolor, or
32-bit truecolor+alpha TGA file.

Returns non-zero on error.

@end ftable
See also:@*
@xref{save_bitmap}.@*
@xref{BITMAP}.@*
@xref{RGB}.@*
@node save_tga_pf, register_bitmap_file_type, save_tga, Loading
@subsection save_tga_pf
@ftable @asis
@item @t{int save_tga_pf(PACKFILE *f, BITMAP *bmp, RGB *pal);}
A version of save_tga which writes to a packfile.

@end ftable
See also:@*
@xref{save_tga}.@*
@xref{expackf}.@*
@xref{BITMAP}.@*
@xref{RGB}.@*
@xref{PACKFILE}.@*
@node register_bitmap_file_type, set_color_conversion, save_tga_pf, Loading
@subsection register_bitmap_file_type
@ftable @asis
@item @t{void register_bitmap_file_type(const char *ext, BITMAP *(*load)(const char *filename, RGB *pal), int (*save)(const char *filename, BITMAP *bmp, const RGB *pal));}
Informs the load_bitmap() and save_bitmap() functions of a new file type, 
providing routines to read and write images in this format (either 
function may be NULL). The functions you supply must follow the same
prototype as load_bitmap() and save_bitmap(). Example:
@example

BITMAP *load_dump(const char *filename, RGB *pal)
@{
   ...
@}

int save_dump(const char *filename, BITMAP *bmp, const RGB *pal)
@{
   ...
@}

   register_bitmap_file_type("dump", load_dump, save_dump);@end example


@end ftable
See also:@*
@xref{load_bitmap}.@*
@xref{save_bitmap}.@*
@xref{BITMAP}.@*
@xref{RGB}.@*
@node set_color_conversion, get_color_conversion, register_bitmap_file_type, Loading
@subsection set_color_conversion
@ftable @asis
@item @t{void set_color_conversion(int mode);}
Specifies how to convert images between the various color depths when 
reading graphics from external bitmap files or datafiles. The mode is a 
bitmask specifying which types of conversion are allowed. If the 
appropriate bit is set, data will be converted into the current pixel 
format (selected by calling the set_color_depth() function), otherwise it 
will be left in the same format as the disk file, leaving you to convert 
it manually before the graphic can be displayed. The default mode is 
total conversion, so that all images will be loaded in the appropriate
format for the current video mode. Valid bit flags are:
@example

COLORCONV_NONE                // disable all format
                              // conversions
COLORCONV_8_TO_15             // expand 8-bit to 15-bit
COLORCONV_8_TO_16             // expand 8-bit to 16-bit
COLORCONV_8_TO_24             // expand 8-bit to 24-bit
COLORCONV_8_TO_32             // expand 8-bit to 32-bit
COLORCONV_15_TO_8             // reduce 15-bit to 8-bit
COLORCONV_15_TO_16            // expand 15-bit to 16-bit
COLORCONV_15_TO_24            // expand 15-bit to 24-bit
COLORCONV_15_TO_32            // expand 15-bit to 32-bit
COLORCONV_16_TO_8             // reduce 16-bit to 8-bit
COLORCONV_16_TO_15            // reduce 16-bit to 15-bit
COLORCONV_16_TO_24            // expand 16-bit to 24-bit
COLORCONV_16_TO_32            // expand 16-bit to 32-bit
COLORCONV_24_TO_8             // reduce 24-bit to 8-bit
COLORCONV_24_TO_15            // reduce 24-bit to 15-bit
COLORCONV_24_TO_16            // reduce 24-bit to 16-bit
COLORCONV_24_TO_32            // expand 24-bit to 32-bit
COLORCONV_32_TO_8             // reduce 32-bit RGB to 8-bit
COLORCONV_32_TO_15            // reduce 32-bit RGB to 15-bit
COLORCONV_32_TO_16            // reduce 32-bit RGB to 16-bit
COLORCONV_32_TO_24            // reduce 32-bit RGB to 24-bit
COLORCONV_32A_TO_8            // reduce 32-bit RGBA to 8-bit
COLORCONV_32A_TO_15           // reduce 32-bit RGBA to 15-bit
COLORCONV_32A_TO_16           // reduce 32-bit RGBA to 16-bit
COLORCONV_32A_TO_24           // reduce 32-bit RGBA to 24-bit
COLORCONV_DITHER_PAL          // dither when reducing to 8-bit
COLORCONV_DITHER_HI           // dither when reducing to
                              // hicolor
COLORCONV_KEEP_TRANS          // keep original transparency
@end example

For convenience, the following macros can be used to select common 
combinations of these flags:
@example

COLORCONV_EXPAND_256          // expand 256-color to hi/truecolor
COLORCONV_REDUCE_TO_256       // reduce hi/truecolor to 256-color
COLORCONV_EXPAND_15_TO_16     // expand 15-bit hicolor to 16-bit
COLORCONV_REDUCE_16_TO_15     // reduce 16-bit hicolor to 15-bit
COLORCONV_EXPAND_HI_TO_TRUE   // expand 15/16-bit to 24/32-bit
COLORCONV_REDUCE_TRUE_TO_HI   // reduce 24/32-bit to 15/16-bit
COLORCONV_24_EQUALS_32        // convert between 24- and 32-bit
COLORCONV_TOTAL               // everything to current format
COLORCONV_PARTIAL             // convert 15 <-> 16-bit and
                              // 24 <-> 32-bit
COLORCONV_MOST                // all but hi/truecolor <-> 256
COLORCONV_DITHER              // dither during all color reductions
COLORCONV_KEEP_ALPHA          // convert everything to current format
                              // unless it would lose alpha information
@end example

If you enable the COLORCONV_DITHER flag, dithering will be performed 
whenever truecolor graphics are converted into a hicolor or paletted 
format, including by the blit() function, and any automatic conversions 
that take place while reading graphics from disk. This can produce much 
better looking results, but is obviously slower than a direct conversion.

If you intend using converted bitmaps with functions like masked_blit() 
or draw_sprite(), you should specify the COLORCONV_KEEP_TRANS flag. It 
will ensure that the masked areas in the bitmap before and after the 
conversion stay exactly the same, by mapping transparent colors to each 
other and adjusting colors which would be converted to the transparent 
color otherwise. It affects every blit() operation between distinct pixel 
formats and every automatic conversion.

@end ftable
See also:@*
@xref{set_color_depth}.@*
@xref{load_bitmap}.@*
@xref{load_datafile}.@*
@xref{fixup_datafile}.@*
@xref{makecol15_dither}.@*
@xref{get_color_conversion}.@*
@xref{exalpha}.@*
@xref{exblend}.@*
@xref{exdata}.@*
@xref{exexedat}.@*
@xref{exlights}.@*
@xref{exxfade}.@*
@node get_color_conversion, set_color, set_color_conversion, Loading
@subsection get_color_conversion
@ftable @asis
@item @t{int get_color_conversion();}
Returns the current color conversion mode.



@end ftable
See also:@*
@xref{set_color_conversion}.@*
@node Palette, Truecolor, Loading, API
@section Palette routines

All the Allegro drawing functions use integer parameters to represent 
colors. In truecolor resolutions these numbers encode the color directly as 
a collection of red, green, and blue bits, but in a regular 256-color mode 
the values are treated as indexes into the current palette, which is a table 
listing the red, green and blue intensities for each of the 256 possible 
colors.

Palette entries are stored in an RGB structure, which contains red, green 
and blue intensities in the VGA hardware format, ranging from 0-63, and is 
defined as:
@example

typedef struct RGB
@{
   unsigned char r, g, b;
@} RGB;
@end example

It contains an additional field for the purpose of padding but you should
not usually care about it. For example:
@example

RGB black = @{ 0,  0,  0  @};
RGB white = @{ 63, 63, 63 @};
RGB green = @{ 0,  63, 0  @};
RGB grey  = @{ 32, 32, 32 @};
@end example

The type PALETTE is defined to be an array of PAL_SIZE RGB structures, where
PAL_SIZE is a preprocessor constant equal to 256.

You may notice that a lot of the code in Allegro spells 'palette' as 
'pallete'. This is because the headers from my old Mark Williams compiler on 
the Atari spelt it with two l's, so that is what I'm used to. Allegro will 
happily accept either spelling, due to some #defines in allegro/alcompat.h
(which can be turned off by defining the ALLEGRO_NO_COMPATIBILITY symbol
before including Allegro headers).

@menu
* set_color::
* _set_color::
* set_palette::
* set_palette_range::
* get_color::
* get_palette::
* get_palette_range::
* fade_interpolate::
* fade_from_range::
* fade_in_range::
* fade_out_range::
* fade_from::
* fade_in::
* fade_out::
* select_palette::
* unselect_palette::
* generate_332_palette::
* generate_optimized_palette::
* default_palette::
* black_palette::
* desktop_palette::
@end menu
@node set_color, _set_color, get_color_conversion, Palette
@subsection set_color
@ftable @asis
@item @t{void set_color(int index, const RGB *p);}
Sets the specified palette entry to the specified RGB triplet. Unlike the 
other palette functions this doesn't do any retrace synchronisation, so 
you should call vsync() before it to prevent snow problems. Example:
@example

RGB rgb;
...
vsync();
set_color(192, &rgb);@end example


@end ftable
See also:@*
@xref{set_palette}.@*
@xref{get_color}.@*
@xref{_set_color}.@*
@xref{ex12bit}.@*
@xref{exrgbhsv}.@*
@xref{exscroll}.@*
@xref{RGB}.@*
@node _set_color, set_palette, set_color, Palette
@subsection _set_color
@ftable @asis
@item @t{void _set_color(int index, const RGB *p);}
This is an inline version of set_color(), intended for use in the
vertical retrace simulator callback function (retrace_proc, which is now
deprecated).

If you really must use _set_color from retrace_proc, note that it should
only be used under DOS, in VGA mode 13h and mode-X. Some SVGA chipsets
aren't VGA compatible (set_color() and set_palette() will use VESA calls on
these cards, but _set_color() doesn't know about that).

@end ftable
See also:@*
@xref{set_color}.@*
@xref{set_gfx_mode}.@*
@xref{ex3buf}.@*
@xref{RGB}.@*
@node set_palette, set_palette_range, _set_color, Palette
@subsection set_palette
@ftable @asis
@item @t{void set_palette(const PALETTE p);}
Sets the entire palette of 256 colors. You should provide an array of 256 
RGB structures. Unlike set_color(), there is no need to call vsync() 
before this function. Example:
@example

BITMAP *bmp;
PALETTE palette;
...
bmp = load_bitmap(filename, palette);
if (!bmp)
   abort_on_error("Couldn't load bitmap!");
set_palette(palette);@end example


@end ftable
See also:@*
@xref{set_gfx_mode}.@*
@xref{set_palette_range}.@*
@xref{set_color}.@*
@xref{get_palette}.@*
@xref{select_palette}.@*
@xref{palette_color}.@*
@xref{Available, Available Allegro examples}.@*
@xref{PALETTE}.@*
@node set_palette_range, get_color, set_palette, Palette
@subsection set_palette_range
@ftable @asis
@item @t{void set_palette_range(const PALETTE p, int from, int to, int vsync);}
Sets the palette entries between from and to (inclusive: pass 0 and 255 
to set the entire palette). If vsync is set it waits for the vertical 
retrace, otherwise it sets the colors immediately. Example:
@example

PALETTE palette;
...
/* Modify the first 16 entries. */
change_first_16_colors(palette);
/* Now update them waiting for vsync. */
set_palette_range(palette, 0, 15, 1);@end example


@end ftable
See also:@*
@xref{set_palette}.@*
@xref{get_palette_range}.@*
@xref{exzbuf}.@*
@xref{PALETTE}.@*
@node get_color, get_palette, set_palette_range, Palette
@subsection get_color
@ftable @asis
@item @t{void get_color(int index, RGB *p);}
Retrieves the specified palette entry. Example:
@example

RGB color;
...
get_color(11, &color);@end example


@end ftable
See also:@*
@xref{get_palette}.@*
@xref{set_color}.@*
@xref{RGB}.@*
@node get_palette, get_palette_range, get_color, Palette
@subsection get_palette
@ftable @asis
@item @t{void get_palette(PALETTE p);}
Retrieves the entire palette of 256 colors. You should provide an array 
of 256 RGB structures to store it in. Example:
@example

PALETTE pal;
...
get_palette(pal);@end example


@end ftable
See also:@*
@xref{get_palette_range}.@*
@xref{get_color}.@*
@xref{set_palette}.@*
@xref{PALETTE}.@*
@node get_palette_range, fade_interpolate, get_palette, Palette
@subsection get_palette_range
@ftable @asis
@item @t{void get_palette_range(PALETTE p, int from, int to);}
Retrieves the palette entries between from and to (inclusive: pass 0 and 
255 to get the entire palette).

@end ftable
See also:@*
@xref{get_palette}.@*
@xref{set_palette_range}.@*
@xref{PALETTE}.@*
@node fade_interpolate, fade_from_range, get_palette_range, Palette
@subsection fade_interpolate
@ftable @asis
@item @t{void fade_interpolate(const PALETTE source, const PALETTE dest, PALETTE output, int pos, int from, int to);}
Calculates a temporary palette part way between source and dest, 
returning it in the output parameter. The position between the two 
extremes is specified by the pos value: 0 returns an exact copy of 
source, 64 returns dest, 32 returns a palette half way between the two, 
etc. This routine only affects colors between from and to (inclusive: 
pass 0 and 255 to interpolate the entire palette).

@end ftable
See also:@*
@xref{fade_in}.@*
@xref{fade_out}.@*
@xref{fade_from}.@*
@xref{PALETTE}.@*
@node fade_from_range, fade_in_range, fade_interpolate, Palette
@subsection fade_from_range
@ftable @asis
@item @t{void fade_from_range(const PALETTE source, const PALETTE dest, int speed, int from, int to);}
Gradually fades a part of the palette from the source palette to the dest 
palette. The speed is from 1 (the slowest) up to 64 (instantaneous). This 
routine only affects colors between from and to (inclusive: pass 0 and 
255 to fade the entire palette).

Note that this function will block your game while the fade is in effect,
and it won't work right visually if you are not in an 8 bit color depth
resolution.

@end ftable
See also:@*
@xref{fade_from}.@*
@xref{PALETTE}.@*
@node fade_in_range, fade_out_range, fade_from_range, Palette
@subsection fade_in_range
@ftable @asis
@item @t{void fade_in_range(const PALETTE p, int speed, int from, int to);}
Gradually fades a part of the palette from a black screen to the 
specified palette. The speed is from 1 (the slowest) up to 64 
(instantaneous). This routine only affects colors between from and to 
(inclusive: pass 0 and 255 to fade the entire palette).

Note that this function will block your game while the fade is in effect,
and it won't work right visually if you are not in an 8 bit color depth
resolution.

@end ftable
See also:@*
@xref{fade_in}.@*
@xref{PALETTE}.@*
@node fade_out_range, fade_from, fade_in_range, Palette
@subsection fade_out_range
@ftable @asis
@item @t{void fade_out_range(int speed, int from, int to);}
Gradually fades a part of the palette from the current palette to a black 
screen. The speed is from 1 (the slowest) up to 64 (instantaneous). This 
routine only affects colors between from and to (inclusive: pass 0 and 
255 to fade the entire palette).

Note that this function will block your game while the fade is in effect,
and it won't work right visually if you are not in an 8 bit color depth
resolution.

@end ftable
See also:@*
@xref{fade_out}.@*
@node fade_from, fade_in, fade_out_range, Palette
@subsection fade_from
@ftable @asis
@item @t{void fade_from(const PALETTE source, const PALETTE dest, int speed);}
Fades gradually from the source palette to the dest palette. The speed is 
from 1 (the slowest) up to 64 (instantaneous).

Note that this function will block your game while the fade is in effect,
and it won't work right visually if you are not in an 8 bit color depth
resolution.

@end ftable
See also:@*
@xref{fade_in}.@*
@xref{fade_out}.@*
@xref{fade_interpolate}.@*
@xref{fade_from_range}.@*
@xref{PALETTE}.@*
@node fade_in, fade_out, fade_from, Palette
@subsection fade_in
@ftable @asis
@item @t{void fade_in(const PALETTE p, int speed);}
Fades gradually from a black screen to the specified palette. The speed 
is from 1 (the slowest) up to 64 (instantaneous).

Note that this function will block your game while the fade is in effect,
and it won't work right visually if you are not in an 8 bit color depth
resolution.

@end ftable
See also:@*
@xref{fade_out}.@*
@xref{fade_from}.@*
@xref{fade_interpolate}.@*
@xref{fade_in_range}.@*
@xref{PALETTE}.@*
@node fade_out, select_palette, fade_in, Palette
@subsection fade_out
@ftable @asis
@item @t{void fade_out(int speed);}
Fades gradually from the current palette to a black screen. The speed is 
from 1 (the slowest) up to 64 (instantaneous).

Note that this function will block your game while the fade is in effect,
and it won't work right visually if you are not in an 8 bit color depth
resolution.

@end ftable
See also:@*
@xref{fade_in}.@*
@xref{fade_from}.@*
@xref{fade_interpolate}.@*
@xref{fade_in_range}.@*
@xref{ex12bit}.@*
@node select_palette, unselect_palette, fade_out, Palette
@subsection select_palette
@ftable @asis
@item @t{void select_palette(const PALETTE p);}
Ugly hack for use in various dodgy situations where you need to convert 
between paletted and truecolor image formats. Sets the internal palette 
table in the same way as the set_palette() function, so the conversion 
will use the specified palette, but without affecting the display 
hardware in any way. The previous palette settings are stored in an 
internal buffer, and can be restored by calling unselect_palette(). If
you call select_palette() again, however, the internal buffer will be
overwritten.

@end ftable
See also:@*
@xref{set_palette}.@*
@xref{unselect_palette}.@*
@xref{exlights}.@*
@xref{PALETTE}.@*
@node unselect_palette, generate_332_palette, select_palette, Palette
@subsection unselect_palette
@ftable @asis
@item @t{void unselect_palette();}
Restores the palette tables that were in use before the last call to 
select_palette().

@end ftable
See also:@*
@xref{select_palette}.@*
@node generate_332_palette, generate_optimized_palette, unselect_palette, Palette
@subsection generate_332_palette
@ftable @asis
@item @t{void generate_332_palette(PALETTE pal);}
Constructs a fake truecolor palette, using three bits for red and green 
and two for the blue. The load_bitmap() function fills the palette
parameter with this if the file does not contain a palette itself (ie. you
are reading a truecolor bitmap).

@end ftable
See also:@*
@xref{generate_optimized_palette}.@*
@xref{set_color_depth}.@*
@xref{excolmap}.@*
@xref{exrgbhsv}.@*
@xref{extruec}.@*
@xref{exupdate}.@*
@xref{PALETTE}.@*
@node generate_optimized_palette, default_palette, generate_332_palette, Palette
@subsection generate_optimized_palette
@ftable @asis
@item @t{int generate_optimized_palette(BITMAP *bmp, PALETTE pal, const char rsvd[PAL_SIZE]);}
Generates a 256-color palette suitable for making a reduced color version 
of the specified truecolor image. The rsvd parameter points to a table 
indicating which colors it is allowed to modify: zero for free colors
which may be set to whatever the optimiser likes, negative values for
reserved colors which cannot be used, and positive values for fixed
palette entries that must not be changed, but can be used in the
optimisation.

Returns the number of different colors recognised in the provided bitmap,
zero if the bitmap is not a truecolor image or there wasn't enough memory
to perform the operation, and negative if there was any internal error in
the color reduction code.

@end ftable
See also:@*
@xref{generate_332_palette}.@*
@xref{set_color_depth}.@*
@xref{BITMAP}.@*
@xref{PALETTE}.@*
@node default_palette, black_palette, generate_optimized_palette, Palette
@subsection default_palette
@ftable @asis
@item @t{extern PALETTE default_palette;}
The default IBM BIOS palette. This will be automatically selected 
whenever you set a new graphics mode. The palette contains 16 basic
colors plus many gradients between them. If you want to see the values,
you can write a small Allegro program which saves a screenshot with this
palette, or open the grabber tool provided with Allegro and create a new
palette object, which will use this palette by default.

@end ftable
See also:@*
@xref{black_palette}.@*
@xref{desktop_palette}.@*
@xref{exjoy}.@*
@xref{PALETTE}.@*
@node black_palette, desktop_palette, default_palette, Palette
@subsection black_palette
@ftable @asis
@item @t{extern PALETTE black_palette;}
A palette containing solid black colors, used by the fade routines.

@end ftable
See also:@*
@xref{default_palette}.@*
@xref{desktop_palette}.@*
@xref{expal}.@*
@xref{PALETTE}.@*
@node desktop_palette, makecol8, black_palette, Palette
@subsection desktop_palette
@ftable @asis
@item @t{extern PALETTE desktop_palette;}
The palette used by the Atari ST low resolution desktop. I'm not quite 
sure why this is still here, except that the grabber and test programs 
use it. It is probably the only Atari legacy code left in Allegro, and it 
would be a shame to remove it :-)

The contents of this palette are 16 colors repeated 16 times. Color entry
zero is equal to color entry 16, which is equal to color entry 24, etc.
@example

Index      Color       RGB values
  0     White          63  63  63
  1     Red            63   0   0
  2     Green           0  63   0
  3     Yellow         63  63   0
  4     Blue            0   0  63
  5     Pink           63   0  63
  6     Cyan            0  63  63
  7     Grey           16  16  16
  8     Light grey     31  31  31
  9     Light red      63  31  31
 10     Light green    31  63  31
 11     Light yellow   63  63  31
 12     Light blue     31  31  63
 13     Light pink     63  31  63
 14     Light cyan     31  63  63
 15     Black           0   0   0@end example




@end ftable
See also:@*
@xref{default_palette}.@*
@xref{black_palette}.@*
@xref{Available, Available Allegro examples}.@*
@xref{PALETTE}.@*
@node Truecolor, Drawing, Palette, API
@section Truecolor pixel formats

In a truecolor video mode the red, green, and blue components for each pixel 
are packed directly into the color value, rather than using a palette lookup 
table. In a 15-bit mode there are 5 bits for each color, in 16-bit modes 
there are 5 bits each of red and blue and six bits of green, and both 24 and 
32-bit modes use 8 bits for each color (the 32-bit pixels simply have an 
extra padding byte to align the data nicely). The layout of these components 
can vary depending on your hardware, but will generally either be RGB or 
BGR. Since the layout is not known until you select the video mode you will 
be using, you must call set_gfx_mode() before using any of the following 
routines!

@menu
* makecol8::
* makeacol32::
* makecol::
* makecol_depth::
* makeacol::
* makecol15_dither::
* getr8::
* geta32::
* getr::
* getr_depth::
* palette_color::
* MASK_COLOR_8::
@end menu
@node makecol8, makeacol32, desktop_palette, Truecolor
@subsection makecol8
@ftable @asis
@item @t{int makecol8(int r, int g, int b);}
@end ftable
@ftable @asis
@item @t{int makecol15(int r, int g, int b);}
@end ftable
@ftable @asis
@item @t{int makecol16(int r, int g, int b);}
@end ftable
@ftable @asis
@item @t{int makecol24(int r, int g, int b);}
@end ftable
@ftable @asis
@item @t{int makecol32(int r, int g, int b);}
These functions convert colors from a hardware independent form (red, 
green, and blue values ranging 0-255) into various display dependent 
pixel formats. Converting to 15, 16, 24, or 32-bit formats only takes a 
few shifts, so it is fairly efficient. Converting to an 8-bit color 
involves searching the palette to find the closest match, which is quite 
slow unless you have set up an RGB mapping table (see below). Example:
@example

/* 16 bit color version of green. */
int green_color = makecol16(0, 255, 0);@end example


Returns the requested RGB triplet in the specified color depth.

@end ftable
See also:@*
@xref{makeacol32}.@*
@xref{makecol}.@*
@xref{makecol_depth}.@*
@xref{makecol15_dither}.@*
@xref{rgb_map}.@*
@xref{bestfit_color}.@*
@xref{set_color_depth}.@*
@xref{exrgbhsv}.@*
@node makeacol32, makecol, makecol8, Truecolor
@subsection makeacol32
@ftable @asis
@item @t{int makeacol32(int r, int g, int b, int a);}
Converts an RGBA color into a 32-bit display pixel format, which includes 
an alpha (transparency) value. There are no versions of this routine for 
other color depths, because only the 32-bit format has enough room to 
store a proper alpha channel. You should only use RGBA format colors as 
the input to draw_trans_sprite() or draw_trans_rle_sprite() after calling 
set_alpha_blender(), rather than drawing them directly to the screen.

@end ftable
See also:@*
@xref{makeacol}.@*
@xref{set_alpha_blender}.@*
@xref{set_write_alpha_blender}.@*
@node makecol, makecol_depth, makeacol32, Truecolor
@subsection makecol
@ftable @asis
@item @t{int makecol(int r, int g, int b);}
Converts colors from a hardware independent format (red, green, and blue 
values ranging 0-255) to the pixel format required by the current video 
mode, calling the preceding 8, 15, 16, 24, or 32-bit makecol functions as 
appropriate. Example:
@example

/* Regardless of color depth, this will look green. */
int green_color = makecol(0, 255, 0);@end example


Returns the requested RGB triplet in the current color depth.

@end ftable
See also:@*
@xref{makeacol}.@*
@xref{makecol8}.@*
@xref{makecol_depth}.@*
@xref{makecol15_dither}.@*
@xref{rgb_map}.@*
@xref{set_color_depth}.@*
@xref{Available, Available Allegro examples}.@*
@node makecol_depth, makeacol, makecol, Truecolor
@subsection makecol_depth
@ftable @asis
@item @t{int makecol_depth(int color_depth, int r, int g, int b);}
Converts colors from a hardware independent format (red, green, and blue 
values ranging 0-255) to the pixel format required by the specified color 
depth. Example:
@example

/* Compose the green color for 15 bit color depth. */
int green_15bit = makecol_depth(15, 0, 255, 0);@end example


Returns the requested RGB triplet in the specified color depth.

@end ftable
See also:@*
@xref{makeacol}.@*
@xref{makecol}.@*
@xref{makecol8}.@*
@xref{makecol15_dither}.@*
@xref{rgb_map}.@*
@xref{set_color_depth}.@*
@node makeacol, makecol15_dither, makecol_depth, Truecolor
@subsection makeacol
@ftable @asis
@item @t{int makeacol(int r, int g, int b, int a);}
@end ftable
@ftable @asis
@item @t{int makeacol_depth(int color_depth, int r, int g, int b, int a);}
Convert RGBA colors into display dependent pixel formats. In anything 
less than a 32-bit mode, these are the same as calling makecol() or 
makecol_depth(), but by using these routines it is possible to create 
32-bit color values that contain a true 8 bit alpha channel along with 
the red, green, and blue components. You should only use RGBA format 
colors as the input to draw_trans_sprite() or draw_trans_rle_sprite() 
after calling set_alpha_blender(), rather than drawing them directly to 
the screen.

Returns the requested RGBA quadruplet.

@end ftable
See also:@*
@xref{makecol}.@*
@xref{makecol_depth}.@*
@xref{set_alpha_blender}.@*
@xref{set_write_alpha_blender}.@*
@node makecol15_dither, getr8, makeacol, Truecolor
@subsection makecol15_dither
@ftable @asis
@item @t{int makecol15_dither(int r, int g, int b, int x, int y);}
@end ftable
@ftable @asis
@item @t{int makecol16_dither(int r, int g, int b, int x, int y);}
Given both a color value and a pixel coordinate, calculate a dithered 15 
or 16-bit RGB value. This can produce better results when reducing images 
from truecolor to hicolor. In addition to calling these functions 
directly, hicolor dithering can be automatically enabled when loading 
graphics by calling the set_color_conversion() function, for example 
set_color_conversion(COLORCONV_REDUCE_TRUE_TO_HI | COLORCONV_DITHER).

Example:
@example

int pixel1, pixel2;

/* The following two color values MAY be different. */
pixel1 = makecol16_dither(255, 192, 64, 0, 0);
pixel2 = makecol16_dither(255, 192, 64, 1, 0);@end example


Returns the RGB value dithered for the specified coordinate.

@end ftable
See also:@*
@xref{makecol}.@*
@xref{makecol8}.@*
@xref{set_color_conversion}.@*
@node getr8, geta32, makecol15_dither, Truecolor
@subsection getr8
@ftable @asis
@item @t{int getr8(int c);}
@end ftable
@ftable @asis
@item @t{int getg8(int c);}
@end ftable
@ftable @asis
@item @t{int getb8(int c);}
@end ftable
@ftable @asis
@item @t{int getr15(int c);}
@end ftable
@ftable @asis
@item @t{int getg15(int c);}
@end ftable
@ftable @asis
@item @t{int getb15(int c);}
@end ftable
@ftable @asis
@item @t{int getr16(int c);}
@end ftable
@ftable @asis
@item @t{int getg16(int c);}
@end ftable
@ftable @asis
@item @t{int getb16(int c);}
@end ftable
@ftable @asis
@item @t{int getr24(int c);}
@end ftable
@ftable @asis
@item @t{int getg24(int c);}
@end ftable
@ftable @asis
@item @t{int getb24(int c);}
@end ftable
@ftable @asis
@item @t{int getr32(int c);}
@end ftable
@ftable @asis
@item @t{int getg32(int c);}
@end ftable
@ftable @asis
@item @t{int getb32(int c);}
Given a color in a display dependent format, these functions extract one 
of the red, green, or blue components (ranging 0-255). Example:
@example

int r, g, b, color_value;

color_value = _getpixel15(screen, 100, 100);
r = getr15(color_value);
g = getg15(color_value);
b = getb15(color_value);@end example


@end ftable
See also:@*
@xref{geta32}.@*
@xref{getr}.@*
@xref{getr_depth}.@*
@xref{makecol}.@*
@xref{set_color_depth}.@*
@node geta32, getr, getr8, Truecolor
@subsection geta32
@ftable @asis
@item @t{int geta32(int c);}
Given a color in a 32-bit pixel format, this function extracts the alpha 
component (ranging 0-255).

@end ftable
See also:@*
@xref{getr8}.@*
@node getr, getr_depth, geta32, Truecolor
@subsection getr
@ftable @asis
@item @t{int getr(int c);}
@end ftable
@ftable @asis
@item @t{int getg(int c);}
@end ftable
@ftable @asis
@item @t{int getb(int c);}
@end ftable
@ftable @asis
@item @t{int geta(int c);}
Given a color in the format being used by the current video mode, these 
functions extract one of the red, green, blue, or alpha components 
(ranging 0-255), calling the preceding 8, 15, 16, 24, or 32-bit get 
functions as appropriate. The alpha part is only meaningful for 32-bit 
pixels. Example:
@example

int r, g, b, color_value;

color_value = getpixel(screen, 100, 100);
r = getr(color_value);
g = getg(color_value);
b = getb(color_value);@end example


@end ftable
See also:@*
@xref{getr8}.@*
@xref{getr_depth}.@*
@xref{makecol}.@*
@xref{set_color_depth}.@*
@xref{exalpha}.@*
@node getr_depth, palette_color, getr, Truecolor
@subsection getr_depth
@ftable @asis
@item @t{int getr_depth(int color_depth, int c);}
@end ftable
@ftable @asis
@item @t{int getg_depth(int color_depth, int c);}
@end ftable
@ftable @asis
@item @t{int getb_depth(int color_depth, int c);}
@end ftable
@ftable @asis
@item @t{int geta_depth(int color_depth, int c);}
Given a color in the format being used by the specified color depth, 
these functions extract one of the red, green, blue, or alpha components 
(ranging 0-255). The alpha part is only meaningful for 32-bit pixels.
Example:
@example

int r, g, b, color_value, bpp;

bpp = bitmap_color_depth(bitmap);
color_value = getpixel(bitmap, 100, 100);
r = getr_depth(bpp, color_value);
g = getg_depth(bpp, color_value);
b = getb_depth(bpp, color_value);@end example


@end ftable
See also:@*
@xref{getr}.@*
@xref{getr8}.@*
@xref{geta32}.@*
@xref{makecol}.@*
@xref{set_color_depth}.@*
@xref{exlights}.@*
@node palette_color, MASK_COLOR_8, getr_depth, Truecolor
@subsection palette_color
@ftable @asis
@item @t{extern int palette_color[256];}
Table mapping palette index colors (0-255) into whatever pixel format is 
being used by the current display mode. In a 256-color mode this just 
maps onto the array index. In truecolor modes it looks up the specified 
entry in the current palette, and converts that RGB value into the 
appropriate packed pixel format. Example:
@example

set_color_depth(32);
...
set_palette(desktop_palette);
/* Put a pixel with the color 2 (green) of the palette */
putpixel(screen, 100, 100, palette_color[2]);@end example


@end ftable
See also:@*
@xref{set_palette}.@*
@xref{makecol}.@*
@xref{set_color_depth}.@*
@xref{Available, Available Allegro examples}.@*
@node MASK_COLOR_8, clear_bitmap, palette_color, Truecolor
@subsection MASK_COLOR_8
@ftable @asis
@item @t{#define MASK_COLOR_8 0}
@end ftable
@ftable @asis
@item @t{#define MASK_COLOR_15 (5.5.5 pink)}
@end ftable
@ftable @asis
@item @t{#define MASK_COLOR_16 (5.6.5 pink)}
@end ftable
@ftable @asis
@item @t{#define MASK_COLOR_24 (8.8.8 pink)}
@end ftable
@ftable @asis
@item @t{#define MASK_COLOR_32 (8.8.8 pink)}
Constants representing the colors used to mask transparent sprite pixels 
for each color depth. In 256-color resolutions this is zero, and in 
truecolor modes it is bright pink (maximum red and blue, zero green).



@end ftable
See also:@*
@xref{bitmap_mask_color}.@*
@xref{makecol}.@*
@xref{draw_sprite}.@*
@xref{masked_blit}.@*
@node Drawing, Blitting, Truecolor, API
@section Drawing primitives

Except for _putpixel(), all these routines are affected by the current 
drawing mode and the clipping rectangle of the destination bitmap. Unless
specified otherwise, all coordinates for drawing operations are inclusive,
and they, as well as lengths, are specified in pixel units.

@menu
* clear_bitmap::
* clear_to_color::
* putpixel::
* _putpixel::
* getpixel::
* _getpixel::
* vline::
* hline::
* do_line::
* line::
* fastline::
* triangle::
* polygon::
* rect::
* rectfill::
* do_circle::
* circle::
* circlefill::
* do_ellipse::
* ellipse::
* ellipsefill::
* do_arc::
* arc::
* calc_spline::
* spline::
* floodfill::
@end menu
@node clear_bitmap, clear_to_color, MASK_COLOR_8, Drawing
@subsection clear_bitmap
@ftable @asis
@item @t{void clear_bitmap(BITMAP *bitmap);}
Clears the bitmap to color 0.

@end ftable
See also:@*
@xref{clear_to_color}.@*
@xref{Available, Available Allegro examples}.@*
@xref{BITMAP}.@*
@node clear_to_color, putpixel, clear_bitmap, Drawing
@subsection clear_to_color
@ftable @asis
@item @t{void clear_to_color(BITMAP *bitmap, int color);}
Clears the bitmap to the specified color. Example:
@example

/* Clear the screen to red. */
clear_to_color(bmp, makecol(255, 0, 0));@end example


@end ftable
See also:@*
@xref{clear_bitmap}.@*
@xref{makecol}.@*
@xref{Available, Available Allegro examples}.@*
@xref{BITMAP}.@*
@node putpixel, _putpixel, clear_to_color, Drawing
@subsection putpixel
@ftable @asis
@item @t{void putpixel(BITMAP *bmp, int x, int y, int color);}
Writes a pixel to the specified position in the bitmap, using the current 
drawing mode and the bitmap's clipping rectangle. Example: 
@example

putpixel(screen, 10, 30, some_color);@end example


@end ftable
See also:@*
@xref{getpixel}.@*
@xref{_putpixel}.@*
@xref{drawing_mode}.@*
@xref{makecol}.@*
@xref{ex12bit}.@*
@xref{exalpha}.@*
@xref{exflame}.@*
@xref{exjoy}.@*
@xref{exstars}.@*
@xref{exswitch}.@*
@xref{BITMAP}.@*
@node _putpixel, getpixel, putpixel, Drawing
@subsection _putpixel
@ftable @asis
@item @t{void _putpixel(BITMAP *bmp, int x, int y, int color);}
@end ftable
@ftable @asis
@item @t{void _putpixel15(BITMAP *bmp, int x, int y, int color);}
@end ftable
@ftable @asis
@item @t{void _putpixel16(BITMAP *bmp, int x, int y, int color);}
@end ftable
@ftable @asis
@item @t{void _putpixel24(BITMAP *bmp, int x, int y, int color);}
@end ftable
@ftable @asis
@item @t{void _putpixel32(BITMAP *bmp, int x, int y, int color);}
Like the regular putpixel(), but much faster because they are implemented 
as an inline assembler functions for specific color depths. These won't 
work in mode-X graphics modes, don't perform any clipping (they will 
crash if you try to draw outside the bitmap!), and ignore the drawing 
mode.

@end ftable
See also:@*
@xref{putpixel}.@*
@xref{makecol}.@*
@xref{BITMAP}.@*
@node getpixel, _getpixel, _putpixel, Drawing
@subsection getpixel
@ftable @asis
@item @t{int getpixel(BITMAP *bmp, int x, int y);}
Reads a pixel from point (x, y) in the bitmap.

Returns -1 if the point lies outside the bitmap (ignoring the clipping
rectangle), otherwise the value of the pixel in the color format of the
bitmap.

Warning: -1 is also a valid value for pixels contained in 32-bit bitmaps
with alpha channel (when R,G,B,A are all equal to 255) so you can't use
the test against -1 as a predicate for such bitmaps. In this cases, the
only reliable predicate is is_inside_bitmap().

To extract the individual color components, use the getr() / getg() /
getb() / geta() family of functions.

@end ftable
See also:@*
@xref{putpixel}.@*
@xref{_getpixel}.@*
@xref{is_inside_bitmap}.@*
@xref{getr}.@*
@xref{getr, getg}.@*
@xref{getr, getb}.@*
@xref{getr, geta}.@*
@xref{Truecolor, Truecolor pixel formats}.@*
@xref{Palette, Palette routines}.@*
@xref{ex12bit}.@*
@xref{exalpha}.@*
@xref{exflame}.@*
@xref{exlights}.@*
@xref{BITMAP}.@*
@node _getpixel, vline, getpixel, Drawing
@subsection _getpixel
@ftable @asis
@item @t{int _getpixel(BITMAP *bmp, int x, int y);}
@end ftable
@ftable @asis
@item @t{int _getpixel15(BITMAP *bmp, int x, int y);}
@end ftable
@ftable @asis
@item @t{int _getpixel16(BITMAP *bmp, int x, int y);}
@end ftable
@ftable @asis
@item @t{int _getpixel24(BITMAP *bmp, int x, int y);}
@end ftable
@ftable @asis
@item @t{int _getpixel32(BITMAP *bmp, int x, int y);}
Faster inline versions of getpixel() for specific color depths. These 
won't work in mode-X, and don't do any clipping, so you must make sure 
the point lies inside the bitmap.

Returns the value of the pixel in the color format you specified.

@end ftable
See also:@*
@xref{getpixel}.@*
@xref{BITMAP}.@*
@node vline, hline, _getpixel, Drawing
@subsection vline
@ftable @asis
@item @t{void vline(BITMAP *bmp, int x, int y1, int y2, int color);}
Draws a vertical line onto the bitmap, from point (x, y1) to (x, y2).

Note: vline() is implemented as an alias to another function.
See ALLEGRO_NO_VHLINE_ALIAS in the `Differences between platforms'
section for details.

@end ftable
See also:@*
@xref{hline}.@*
@xref{line}.@*
@xref{drawing_mode}.@*
@xref{makecol}.@*
@xref{Differences, Differences between platforms}.@*
@xref{exrgbhsv}.@*
@xref{exscroll}.@*
@xref{extruec}.@*
@xref{BITMAP}.@*
@node hline, do_line, vline, Drawing
@subsection hline
@ftable @asis
@item @t{void hline(BITMAP *bmp, int x1, int y, int x2, int color);}
Draws a horizontal line onto the bitmap, from point (x1, y) to (x2, y).

Note: hline() is implemented as an alias to another function.
See ALLEGRO_NO_VHLINE_ALIAS in the `Differences between platforms'
section for details.

@end ftable
See also:@*
@xref{vline}.@*
@xref{line}.@*
@xref{drawing_mode}.@*
@xref{makecol}.@*
@xref{Differences, Differences between platforms}.@*
@xref{exsprite}.@*
@xref{BITMAP}.@*
@node do_line, line, hline, Drawing
@subsection do_line
@ftable @asis
@item @t{void do_line(BITMAP *bmp, int x1, y1, x2, y2, int d,  void (*proc)(BITMAP *bmp, int x, int y, int d));}
Calculates all the points along a line from point (x1, y1) to (x2, y2), 
calling the supplied function for each one. This will be passed a copy of 
the bmp parameter, the x and y position, and a copy of the d parameter, 
so it is suitable for use with putpixel(). Example:
@example

void draw_dust_particle(BITMAP *bmp, int x, int y, int d)
@{
   ...
@}

   do_line(screen, 0, 0, SCREEN_W-1, SCREEN_H-2,
           dust_strength, draw_dust_particle);@end example


@end ftable
See also:@*
@xref{do_circle}.@*
@xref{do_ellipse}.@*
@xref{do_arc}.@*
@xref{line}.@*
@xref{BITMAP}.@*
@node line, fastline, do_line, Drawing
@subsection line
@ftable @asis
@item @t{void line(BITMAP *bmp, int x1, int y1, int x2, int y2, int color);}
Draws a line onto the bitmap, from point (x1, y1) to (x2, y2).

@end ftable
See also:@*
@xref{fastline}.@*
@xref{hline}.@*
@xref{vline}.@*
@xref{do_line}.@*
@xref{drawing_mode}.@*
@xref{makecol}.@*
@xref{Available, Available Allegro examples}.@*
@xref{BITMAP}.@*
@node fastline, triangle, line, Drawing
@subsection fastline
@ftable @asis
@item @t{void fastline(BITMAP *bmp, int x1, int y1, int x2, int y2, int color);}
Faster version of the previous function. Note that pixel correctness is
not guaranteed for this function.

@end ftable
See also:@*
@xref{line}.@*
@xref{hline}.@*
@xref{vline}.@*
@xref{do_line}.@*
@xref{drawing_mode}.@*
@xref{makecol}.@*
@xref{Available, Available Allegro examples}.@*
@xref{BITMAP}.@*
@node triangle, polygon, fastline, Drawing
@subsection triangle
@ftable @asis
@item @t{void triangle(BITMAP *bmp, int x1, y1, x2, y2, x3, y3, int color);}
Draws a filled triangle between the three points.

@end ftable
See also:@*
@xref{polygon}.@*
@xref{triangle3d}.@*
@xref{drawing_mode}.@*
@xref{makecol}.@*
@xref{ex3buf}.@*
@xref{exstars}.@*
@xref{exupdate}.@*
@xref{BITMAP}.@*
@node polygon, rect, triangle, Drawing
@subsection polygon
@ftable @asis
@item @t{void polygon(BITMAP *bmp, int vertices, const int *points, int color);}
Draws a filled polygon with an arbitrary number of corners. Pass the 
number of vertices and an array containing a series of x, y points (a 
total of vertices*2 values). Example:
@example

int points[12] = @{ 50, 50,   100, 100,  100, 150,
                   50, 200,  0,   150,  0,   100 @};
...
clear_to_color(screen, makecol(255, 255, 255));
polygon(screen, 6, points, makecol(0, 0, 0));@end example


@end ftable
See also:@*
@xref{triangle}.@*
@xref{polygon3d}.@*
@xref{drawing_mode}.@*
@xref{makecol}.@*
@xref{excamera}.@*
@xref{BITMAP}.@*
@node rect, rectfill, polygon, Drawing
@subsection rect
@ftable @asis
@item @t{void rect(BITMAP *bmp, int x1, int y1, int x2, int y2, int color);}
Draws an outline rectangle with the two points as its opposite corners.

@end ftable
See also:@*
@xref{rectfill}.@*
@xref{drawing_mode}.@*
@xref{makecol}.@*
@xref{ex3d}.@*
@xref{excamera}.@*
@xref{BITMAP}.@*
@node rectfill, do_circle, rect, Drawing
@subsection rectfill
@ftable @asis
@item @t{void rectfill(BITMAP *bmp, int x1, int y1, int x2, int y2, int color);}
Draws a solid, filled rectangle with the two points as its opposite 
corners.

@end ftable
See also:@*
@xref{rect}.@*
@xref{clear_bitmap}.@*
@xref{drawing_mode}.@*
@xref{makecol}.@*
@xref{exalpha}.@*
@xref{excolmap}.@*
@xref{exkeys}.@*
@xref{exmidi}.@*
@xref{expat}.@*
@xref{exscroll}.@*
@xref{exsprite}.@*
@xref{exstars}.@*
@xref{exswitch}.@*
@xref{extrans}.@*
@xref{BITMAP}.@*
@node do_circle, circle, rectfill, Drawing
@subsection do_circle
@ftable @asis
@item @t{void do_circle(BITMAP *bmp, int x, int y, int radius, int d, void (*proc)(BITMAP *bmp, int x, int y, int d));}
Calculates all the points in a circle around point (x, y) with radius r, 
calling the supplied function for each one. This will be passed a copy of 
the bmp parameter, the x and y position, and a copy of the d parameter, 
so it is suitable for use with putpixel(). Example:
@example

void draw_explosion_ring(BITMAP *bmp, int x, int y, int d)
@{
   ...
@}

   do_circle(screen, SCREEN_W/2, SCREEN_H/2,
             SCREEN_H/16, flame_color,
             draw_explosion_ring);@end example


@end ftable
See also:@*
@xref{do_ellipse}.@*
@xref{do_arc}.@*
@xref{do_line}.@*
@xref{circle}.@*
@xref{circlefill}.@*
@xref{BITMAP}.@*
@node circle, circlefill, do_circle, Drawing
@subsection circle
@ftable @asis
@item @t{void circle(BITMAP *bmp, int x, int y, int radius, int color);}
Draws a circle with the specified centre and radius.

@end ftable
See also:@*
@xref{ellipse}.@*
@xref{arc}.@*
@xref{circlefill}.@*
@xref{do_circle}.@*
@xref{drawing_mode}.@*
@xref{makecol}.@*
@xref{ex12bit}.@*
@xref{exblend}.@*
@xref{excustom}.@*
@xref{exjoy}.@*
@xref{exmem}.@*
@xref{exmouse}.@*
@xref{exquat}.@*
@xref{exsprite}.@*
@xref{BITMAP}.@*
@node circlefill, do_ellipse, circle, Drawing
@subsection circlefill
@ftable @asis
@item @t{void circlefill(BITMAP *bmp, int x, int y, int radius, int color);}
Draws a filled circle with the specified centre and radius.

@end ftable
See also:@*
@xref{ellipsefill}.@*
@xref{circle}.@*
@xref{do_circle}.@*
@xref{drawing_mode}.@*
@xref{makecol}.@*
@xref{excolmap}.@*
@xref{excustom}.@*
@xref{exdbuf}.@*
@xref{exflip}.@*
@xref{exlights}.@*
@xref{expal}.@*
@xref{exspline}.@*
@xref{extrans}.@*
@xref{BITMAP}.@*
@node do_ellipse, ellipse, circlefill, Drawing
@subsection do_ellipse
@ftable @asis
@item @t{void do_ellipse(BITMAP *bmp, int x, int y, int rx, ry, int d, void (*proc)(BITMAP *bmp, int x, int y, int d));}
Calculates all the points in an ellipse around point (x, y) with radius 
rx and ry, calling the supplied function for each one. This will be 
passed a copy of the bmp parameter, the x and y position, and a copy of 
the d parameter, so it is suitable for use with putpixel(). Example:
@example

void draw_explosion_ring(BITMAP *bmp, int x, int y, int d)
@{
   ...
@}

   do_ellipse(screen, SCREEN_W/2, SCREEN_H/2,
             SCREEN_H/16, SCREEN_H/32, flame_color,
             draw_explosion_ring);@end example


@end ftable
See also:@*
@xref{do_circle}.@*
@xref{do_arc}.@*
@xref{do_line}.@*
@xref{ellipse}.@*
@xref{ellipsefill}.@*
@xref{BITMAP}.@*
@node ellipse, ellipsefill, do_ellipse, Drawing
@subsection ellipse
@ftable @asis
@item @t{void ellipse(BITMAP *bmp, int x, int y, int rx, int ry, int color);}
Draws an ellipse with the specified centre and radius.

@end ftable
See also:@*
@xref{circle}.@*
@xref{arc}.@*
@xref{ellipsefill}.@*
@xref{do_ellipse}.@*
@xref{drawing_mode}.@*
@xref{makecol}.@*
@xref{BITMAP}.@*
@node ellipsefill, do_arc, ellipse, Drawing
@subsection ellipsefill
@ftable @asis
@item @t{void ellipsefill(BITMAP *bmp, int x, int y, int rx, int ry, int color);}
Draws a filled ellipse with the specified centre and radius.

@end ftable
See also:@*
@xref{circlefill}.@*
@xref{ellipse}.@*
@xref{do_ellipse}.@*
@xref{drawing_mode}.@*
@xref{makecol}.@*
@xref{ex12bit}.@*
@xref{BITMAP}.@*
@node do_arc, arc, ellipsefill, Drawing
@subsection do_arc
@ftable @asis
@item @t{void do_arc(BITMAP *bmp, int x, int y, fixed a1, fixed a2, int r, int d, void (*proc)(BITMAP *bmp, int x, int y, int d));}
Calculates all the points in a circular arc around point (x, y) with 
radius r, calling the supplied function for each one. This will be passed 
a copy of the bmp parameter, the x and y position, and a copy of the d
parameter, so it is suitable for use with putpixel(). The arc will be 
plotted in an anticlockwise direction starting from the angle a1 and 
ending when it reaches a2. These values are specified in 16.16 fixed 
point format, with 256 equal to a full circle, 64 a right angle, etc. 
Zero is to the right of the centre point, and larger values rotate 
anticlockwise from there. Example:
@example

void draw_explosion_ring(BITMAP *bmp, int x, int y, int d)
@{
   ...
@}
   do_arc(screen, SCREEN_W/2, SCREEN_H/2,
       itofix(-21), itofix(43), 50, flame_color,
       draw_explosion_ring);@end example


@end ftable
See also:@*
@xref{do_circle}.@*
@xref{do_ellipse}.@*
@xref{do_line}.@*
@xref{arc}.@*
@xref{fixed}.@*
@xref{BITMAP}.@*
@node arc, calc_spline, do_arc, Drawing
@subsection arc
@ftable @asis
@item @t{void arc(BITMAP *bmp, int x, y, fixed ang1, ang2, int r, int color);}
Draws a circular arc with centre x, y and radius r, in an anticlockwise 
direction starting from the angle a1 and ending when it reaches a2. These 
values are specified in 16.16 fixed point format, with 256 equal to a 
full circle, 64 a right angle, etc. Zero is to the right of the centre 
point, and larger values rotate anticlockwise from there. Example:
@example

/* Draw a black arc from 4 to 1 o'clock. */
arc(screen, SCREEN_W/2, SCREEN_H/2,
    itofix(-21), itofix(43), 50, makecol(0, 0, 0));@end example


@end ftable
See also:@*
@xref{circle}.@*
@xref{ellipse}.@*
@xref{drawing_mode}.@*
@xref{makecol}.@*
@xref{fixed}.@*
@xref{BITMAP}.@*
@node calc_spline, spline, arc, Drawing
@subsection calc_spline
@ftable @asis
@item @t{void calc_spline(const int points[8], int npts, int *x, int *y);}
Calculates a series of npts values along a Bezier spline, storing them in 
the output x and y arrays. The Bezier curve is specified by the four x/y 
control points in the points array: points[0] and points[1] contain the 
coordinates of the first control point, points[2] and points[3] are the 
second point, etc. Control points 0 and 3 are the ends of the spline, and 
points 1 and 2 are guides. The curve probably won't pass through points 1 
and 2, but they affect the shape of the curve between points 0 and 3 (the 
lines p0-p1 and p2-p3 are tangents to the spline). The easiest way to 
think of it is that the curve starts at p0, heading in the direction of 
p1, but curves round so that it arrives at p3 from the direction of p2. 
In addition to their role as graphics primitives, spline curves can be 
useful for constructing smooth paths around a series of control points, 
as in exspline.c.

@end ftable
See also:@*
@xref{spline}.@*
@xref{exspline}.@*
@node spline, floodfill, calc_spline, Drawing
@subsection spline
@ftable @asis
@item @t{void spline(BITMAP *bmp, const int points[8], int color);}
Draws a Bezier spline using the four control points specified in the 
points array. Read the description of calc_spline() for information on
how to build the points array.

@end ftable
See also:@*
@xref{calc_spline}.@*
@xref{drawing_mode}.@*
@xref{makecol}.@*
@xref{exspline}.@*
@xref{BITMAP}.@*
@node floodfill, blit, spline, Drawing
@subsection floodfill
@ftable @asis
@item @t{void floodfill(BITMAP *bmp, int x, int y, int color);}
Floodfills an enclosed area, starting at point (x, y), with the specified 
color.



@end ftable
See also:@*
@xref{drawing_mode}.@*
@xref{makecol}.@*
@xref{BITMAP}.@*
@node Blitting, RLE, Drawing, API
@section Blitting and sprites

As far as Allegro is concerned, a bitmap and a sprite are the same thing,
but to many people the two words imply slightly different things.  The
function draw_sprite() is called so rather than draw_bitmap() partly because
it indicates that it uses a masked drawing mode (if it existed, you could
expect draw_bitmap() to be a simple block copy), and partly for historical
reasons. In Allegro 1.0 there were actually different structures for sprites
and bitmaps, each with their own set of abilities. Allegro 2.0 merged these
into a single more flexible structure, but retained some names like
draw_sprite().

In wider (non-Allegro) terms, the two words can mean quite different things.
Generally you can say that sprites are a subset of bitmaps, but even that
isn't true in 100% of cases.

BITMAP: a widely accepted term that will be understood by anyone even
remotely connected with computer graphics. It simply means an image built up
from a grid of pixels, ie. just about any picture that you are likely to come
across on a computer (vector graphics formats are the exception, but those
must be rendered into a bitmap format before they can be displayed by most
hardware). A more accurate term but slightly rarer term with the same meaning
is "pixmap" (pixel-map).

SPRITE: a particular usage of bitmapped images, restricted to video games
(other types of programmer probably won't be familiar with this term).
Originally on machines like the C64, sprites were a hardware feature that
allowed a number of small bitmap images to be loaded into special registers,
and they could then be superimposed over the main graphics display and moved
around just by modifying the position register. They were used for the moving
objects (player and enemy characters), and enabled the C64 to do much more
impressive things than would have been possible if all the drawing had to be
done directly by the puny CPU.

Later on, a lot of old C64 programmers upgraded to machines like the Atari
ST, which didn't have any special sprite hardware, but they carried on
referring to their main moving objects as sprites (the routine to draw such a
thing would obviously be called draw_sprite()).  A sprite is really just a
bitmap graphic which is drawn onto the screen, but when you call it a sprite
rather than a bitmap, this suggests it is a gameplay element that can move
freely around the world rather than being a static part of the environment,
and that it will be drawn in a masked overlay mode rather than as a solid
rectangle (there is also a strong implication that a sprite will be animated
by cycling through a number of frames, but that isn't always the case).

In recent years some people have started using "sprite" to refer to any
character graphics, even if they are not in fact drawn as 2d bitmaps, eg.
"this game uses 3d polygonal player sprites". This is a confusing misuse of
the word (Doom uses sprites, Quake does not), but it does happen.

The origin of the term "blit" is also rather interesting. This was originally
BitBlt, an abbreviation of BITmap BLock Transfer, which was a function
designed (possibly) by the people at Xerox who did so much of the pioneering
work on graphics display systems, and subsequently copied by virtually
everybody doing computer graphics (the Microsoft Windows GDI still provides a
BitBlt function with identical functionality to the original). This routine
was a workhorse for all sorts of drawing operations, basically copying bitmap
graphics from one place to another, but including a number of different ROP
modes (Raster OPerations) for doing things like XOR, inverting pixels, etc.
A whole family of related words grew up around the BitBlt function, but "blt"
is impossible to speak (try saying "bltter" or "bltting" :-) so people added
the vowel to make it easier to pronounce.

Therefore, the act of calling the BitBlt function came to be known as "doing a
blit". The obvious next step was to rename the function itself to blit(),
which generally took place at the same time as people decided to simplify the
original, removing the different ROP modes on the grounds that they aren't
needed for games coding and don't work well with anything higher than
monochrome images in any case. This leaves us with a function called blit(),
which is an abbreviation for "block transfer". A strong case could be made
for calling this blot() instead, but somehow that just doesn't sound the
same!

Anyway, all the routines in this chapter are affected by the
clipping rectangle of the destination bitmap.

@menu
* blit::
* stretch_blit::
* masked_blit::
* masked_stretch_blit::
* draw_sprite::
* stretch_sprite::
* draw_sprite_v_flip::
* draw_trans_sprite::
* draw_lit_sprite::
* draw_gouraud_sprite::
* draw_character_ex::
* rotate_sprite::
* rotate_sprite_v_flip::
* rotate_scaled_sprite::
* rotate_scaled_sprite_v_flip::
* pivot_sprite::
* pivot_sprite_v_flip::
* pivot_scaled_sprite::
* pivot_scaled_sprite_v_flip::
@end menu
@node blit, stretch_blit, floodfill, Blitting
@subsection blit
@ftable @asis
@item @t{void blit(BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height);}
Copies a rectangular area of the source bitmap to the destination bitmap. 
The source_x and source_y parameters are the top left corner of the area 
to copy from the source bitmap, and dest_x and dest_y are the 
corresponding position in the destination bitmap. This routine respects 
the destination clipping rectangle, and it will also clip if you try to 
blit from areas outside the source bitmap. Example:
@example

BITMAP *bmp;
...
/* Blit src on the screen. */
blit(bmp, screen, 0, 0, 0, 0, bmp->w, bmp->h);

/* Now copy a chunk to a corner, slightly outside. /*
blit(screen, screen, 100, 100, -10, -10, 25, 30);
@end example

You can blit between any parts of any two bitmaps, even if the two memory 
areas overlap (ie. source and dest are the same, or one is sub-bitmap of 
the other). You should be aware, however, that a lot of SVGA cards don't 
provide separate read and write banks, which means that blitting from one 
part of the screen to another requires the use of a temporary bitmap in 
memory, and is therefore extremely slow. As a general rule you should 
avoid blitting from the screen onto itself in SVGA modes.

In mode-X, on the other hand, blitting from one part of the screen to 
another can be significantly faster than blitting from memory onto the 
screen, as long as the source and destination are correctly aligned with 
each other. Copying between overlapping screen rectangles is slow, but if 
the areas don't overlap, and if they have the same plane alignment (ie. 
(source_x%4) == (dest_x%4)), the VGA latch registers can be used for a 
very fast data transfer. To take advantage of this, in mode-X it is often 
worth storing tile graphics in a hidden area of video memory (using a 
large virtual screen), and blitting them from there onto the visible part 
of the screen.

If the GFX_HW_VRAM_BLIT bit in the gfx_capabilities flag is set, the 
current driver supports hardware accelerated blits from one part of the 
screen onto another. This is extremely fast, so when this flag is set it 
may be worth storing some of your more frequently used graphics in an 
offscreen portion of the video memory.

Unlike most of the graphics routines, blit() allows the source and
destination bitmaps to be of different color depths, so it can be
used to convert images from one pixel format to another. In this
case, the behavior is affected by the COLORCONV_KEEP_TRANS and
COLORCONV_DITHER* flags of the current color conversion mode: see
set_color_conversion() for more information.

@end ftable
See also:@*
@xref{masked_blit}.@*
@xref{stretch_blit}.@*
@xref{draw_sprite}.@*
@xref{gfx_capabilities}.@*
@xref{set_color_conversion}.@*
@xref{Available, Available Allegro examples}.@*
@xref{BITMAP}.@*
@node stretch_blit, masked_blit, blit, Blitting
@subsection stretch_blit
@ftable @asis
@item @t{void stretch_blit(BITMAP *source, BITMAP *dest, int source_x, source_y, source_width, source_height, int dest_x, dest_y, dest_width, dest_height);}
Like blit(), except it can scale images (so the source and destination 
rectangles don't need to be the same size) and requires the source and 
destination bitmaps to be of the same color depth. This routine doesn't 
do as much safety checking as the regular blit(): in particular you must 
take care not to copy from areas outside the source bitmap, and you 
cannot blit between overlapping regions, ie. you must use different 
bitmaps for the source and the destination. Moreover, the source must 
be a memory bitmap. Example:
@example

BITMAP *bmp;
...
/* Stretch bmp to fill the screen. */
stretch_blit(bmp, screen, 0, 0, bmp->w, bmp->h,
             0, 0, SCREEN_W, SCREEN_H);@end example


@end ftable
See also:@*
@xref{blit}.@*
@xref{masked_stretch_blit}.@*
@xref{stretch_sprite}.@*
@xref{exalpha}.@*
@xref{exconfig}.@*
@xref{exscale}.@*
@xref{extrans}.@*
@xref{BITMAP}.@*
@node masked_blit, masked_stretch_blit, stretch_blit, Blitting
@subsection masked_blit
@ftable @asis
@item @t{void masked_blit(BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height);}
Like blit(), but skips transparent pixels, which are marked by a zero in 
256-color modes or bright pink for truecolor data (maximum red and blue, 
zero green), and requires the source and destination bitmaps to be of 
the same color depth. The source and destination regions must not overlap.
Example:
@example

BITMAP *hud_overlay;
...
/* Paint hud overlay on the screen. */
masked_blit(hud_overlay, screen, 0, 0, 0, 0,
            hud_overlay->w, hud_overlay->h);@end example


If the GFX_HW_VRAM_BLIT_MASKED bit in the gfx_capabilities flag is set, 
the current driver supports hardware accelerated masked blits from one 
part of the screen onto another. This is extremely fast, so when this 
flag is set it may be worth storing some of your more frequently used 
sprites in an offscreen portion of the video memory.

Warning: if the hardware acceleration flag is not set, masked_blit() will 
not work correctly when used with a source image in system or video 
memory so the latter must be a memory bitmap.

@end ftable
See also:@*
@xref{blit}.@*
@xref{masked_stretch_blit}.@*
@xref{draw_sprite}.@*
@xref{bitmap_mask_color}.@*
@xref{ex12bit}.@*
@xref{expat}.@*
@xref{BITMAP}.@*
@node masked_stretch_blit, draw_sprite, masked_blit, Blitting
@subsection masked_stretch_blit
@ftable @asis
@item @t{void masked_stretch_blit(BITMAP *source, BITMAP *dest, int source_x, source_y, source_w, source_h, int dest_x, dest_y, dest_w, dest_h);}
Like masked_blit(), except it can scale images (so the source and 
destination rectangles don't need to be the same size). This routine 
doesn't do as much safety checking as the regular masked_blit(): in 
particular you must take care not to copy from areas outside the source 
bitmap. Moreover, the source must be a memory bitmap. Example:
@example

BITMAP *hud_overlay;
...
/* Stretch hud overlay over the screen. */
masked_stretch_blit(hud_overlay, screen, 0, 0,
                    hud_overlay->w, hud_overlay->h,
                    0, 0, SCREEN_W, SCREEN_H);@end example


@end ftable
See also:@*
@xref{blit}.@*
@xref{masked_blit}.@*
@xref{stretch_blit}.@*
@xref{stretch_sprite}.@*
@xref{BITMAP}.@*
@node draw_sprite, stretch_sprite, masked_stretch_blit, Blitting
@subsection draw_sprite
@ftable @asis
@item @t{void draw_sprite(BITMAP *bmp, BITMAP *sprite, int x, int y);}
Draws a copy of the sprite bitmap onto the destination bitmap at the 
specified position. This is almost the same as blit(sprite, bmp, 0, 0, x, 
y, sprite->w, sprite->h), but it uses a masked drawing mode where 
transparent pixels are skipped, so the background image will show through 
the masked parts of the sprite. Transparent pixels are marked by a zero 
in 256-color modes or bright pink for truecolor data (maximum red and 
blue, zero green). Example:
@example

BITMAP *spaceship;
...
draw_sprite(screen, spaceship, x, y);@end example


If the GFX_HW_VRAM_BLIT_MASKED bit in the gfx_capabilities flag is set, 
the current driver supports hardware accelerated sprite drawing when the 
source image is a video memory bitmap or a sub-bitmap of the screen. This 
is extremely fast, so when this flag is set it may be worth storing some 
of your more frequently used sprites in an offscreen portion of the video 
memory.

Warning: if the hardware acceleration flag is not set, draw_sprite() will 
not work correctly when used with a sprite image in system or video 
memory so the latter must be a memory bitmap.

Although generally not supporting graphics of mixed color depths, as a 
special case this function can be used to draw 256-color source images 
onto truecolor destination bitmaps, so you can use palette effects on 
specific sprites within a truecolor program.

@end ftable
See also:@*
@xref{draw_sprite_v_flip}.@*
@xref{draw_trans_sprite}.@*
@xref{draw_lit_sprite}.@*
@xref{draw_gouraud_sprite}.@*
@xref{stretch_sprite}.@*
@xref{rotate_sprite}.@*
@xref{draw_character_ex}.@*
@xref{draw_rle_sprite}.@*
@xref{draw_compiled_sprite}.@*
@xref{masked_blit}.@*
@xref{blit}.@*
@xref{bitmap_mask_color}.@*
@xref{exsprite}.@*
@xref{BITMAP}.@*
@node stretch_sprite, draw_sprite_v_flip, draw_sprite, Blitting
@subsection stretch_sprite
@ftable @asis
@item @t{void stretch_sprite(BITMAP *bmp, BITMAP *sprite, int x, int y, int w, int h);}
Like draw_sprite(), except it can stretch the sprite image to the 
specified width and height and requires the sprite image and destination 
bitmap to be of the same color depth. Moreover, the sprite image must 
be a memory bitmap. Example:
@example

/* Create tunnel like effect. */
for (step = 1; step 
   int width = SCREEN_W / step;
   int height = SCREEN_H / step;
   stretch_sprite(screen, image, SCREEN_W / 2 - width / 2,
                  SCREEN_H / 2 - height / 2, width, height);
@}@end example


@end ftable
See also:@*
@xref{draw_sprite}.@*
@xref{stretch_blit}.@*
@xref{bitmap_mask_color}.@*
@xref{BITMAP}.@*
@node draw_sprite_v_flip, draw_trans_sprite, stretch_sprite, Blitting
@subsection draw_sprite_v_flip
@ftable @asis
@item @t{void draw_sprite_v_flip(BITMAP *bmp, BITMAP *sprite, int x, int y);}
@end ftable
@ftable @asis
@item @t{void draw_sprite_h_flip(BITMAP *bmp, BITMAP *sprite, int x, int y);}
@end ftable
@ftable @asis
@item @t{void draw_sprite_vh_flip(BITMAP *bmp, BITMAP *sprite, int x, int y);}
These are like draw_sprite(), but they additionally flip the image
vertically, horizontally, or both, respectively. Flipping vertically
means that the y-axis is reversed, while flipping horizontally means
that the x-axis is reversed, between the source and the destination.
This produces exact mirror images, which is not the same as rotating the
sprite (and it is a lot faster than the rotation routine). The sprite
must be a memory bitmap. Example:
@example

if (key[KEY_RIGHT])
   draw_sprite(screen, hero_right, pos_x, pos_y);
else if (key[KEY_LEFT])
   draw_sprite_h_flip(screen, hero_right, pos_x, pos_y);
else
   draw_sprite(screen, hero_idle, pos_x, pos_y);@end example


@end ftable
See also:@*
@xref{draw_sprite}.@*
@xref{bitmap_mask_color}.@*
@xref{exsprite}.@*
@xref{BITMAP}.@*
@node draw_trans_sprite, draw_lit_sprite, draw_sprite_v_flip, Blitting
@subsection draw_trans_sprite
@ftable @asis
@item @t{void draw_trans_sprite(BITMAP *bmp, BITMAP *sprite, int x, int y);}
Uses the global color_map table or truecolor blender functions to overlay
the sprite on top of the existing image. This must only be used after you 
have set up the color mapping table (for 256-color modes) or blender 
functions (for truecolor modes). Because it involves reading as well as 
writing the bitmap memory, translucent drawing is very slow if you draw 
directly to video RAM, so wherever possible you should use a memory 
bitmap instead. Example:
@example

/* Some one time initialisation code. */
COLOR_MAP global_trans_table;
create_trans_table(&global_trans_table, my_palette,
                   128, 128, 128, NULL);
...
if (get_color_depth() == 8)
   color_map = &global_trans_table;
else
   set_trans_blender(128, 128, 128, 128);

draw_trans_sprite(buffer, ghost_sprite, x, y);@end example


The bitmap and sprite must normally be in the same color depth, but as a
special case you can draw 32 bit RGBA format sprites onto any hicolor or
truecolor bitmap, as long as you call set_alpha_blender() first, and you
can draw 8-bit alpha images onto a 32-bit RGBA destination, as long as you
call set_write_alpha_blender() first. As draw_sprite() this function skips
transparent pixels, except if the source sprite is an 8-bit image; if this
is the case, you should pay attention to properly set up your color map
table for index 0.

@end ftable
See also:@*
@xref{draw_sprite}.@*
@xref{draw_lit_sprite}.@*
@xref{draw_trans_rle_sprite}.@*
@xref{color_map}.@*
@xref{set_trans_blender}.@*
@xref{set_alpha_blender}.@*
@xref{set_write_alpha_blender}.@*
@xref{bitmap_mask_color}.@*
@xref{exalpha}.@*
@xref{exblend}.@*
@xref{exlights}.@*
@xref{extrans}.@*
@xref{exxfade}.@*
@xref{BITMAP}.@*
@node draw_lit_sprite, draw_gouraud_sprite, draw_trans_sprite, Blitting
@subsection draw_lit_sprite
@ftable @asis
@item @t{void draw_lit_sprite(BITMAP *bmp, BITMAP *sprite, int x, int y, int color);}
In 256-color modes, uses the global color_map table to tint the sprite
image to the specified color or to light it to the level specified by
'color', depending on the function which was used to build the table
(create_trans_table or create_light_table), and draws the resulting image
to the destination bitmap. In truecolor modes, uses the blender functions
to light the sprite image using the alpha level specified by 'color' (the
alpha level which was passed to the blender functions is ignored) and
draws the resulting image to the destination bitmap. The 'color' parameter
must be in the range [0-255] whatever its actual meaning is. This must
only be used after you have set up the color mapping table (for 256-color
modes) or blender functions (for truecolor modes). Example:
@example

/* Some one time initialisation code. */
COLOR_MAP global_light_table;
create_light_table(&global_trans_table, my_palette,
                   10, 10, 60, NULL);
...
if (get_color_depth() == 8)
   color_map = &global_light_table;
else
   set_trans_blender(40, 40, 255, 255);

/* Lit the cape with a blueish light. */
draw_lit_sprite(buffer, colored_cape, x, y, 64);@end example


@end ftable
See also:@*
@xref{draw_sprite}.@*
@xref{draw_trans_sprite}.@*
@xref{draw_gouraud_sprite}.@*
@xref{draw_lit_rle_sprite}.@*
@xref{color_map}.@*
@xref{set_trans_blender}.@*
@xref{bitmap_mask_color}.@*
@xref{exblend}.@*
@xref{BITMAP}.@*
@node draw_gouraud_sprite, draw_character_ex, draw_lit_sprite, Blitting
@subsection draw_gouraud_sprite
@ftable @asis
@item @t{void draw_gouraud_sprite(BITMAP *bmp, BITMAP *sprite, int x, int y, int c1, int c2, int c3, int c4);}
More sophisticated version of draw_lit_sprite(): the 'color' parameter is
not constant across the sprite image anymore but interpolated between the
four specified corner colors. The corner values passed to this function
indicate the strength of the color applied on them, ranging from 0 (no
strength) to 255 (full strength). Example:
@example

/* Some one time initialisation code. */
COLOR_MAP global_light_table;
create_light_table(&global_trans_table, my_palette,
                   0, 0, 0, NULL);
...
if (get_color_depth() == 8)
   color_map = &global_light_table;
else
   set_trans_blender(0, 0, 0, 128);

/* Enemies are in shadow unless lit by torch. */
draw_gouraud_sprite(buffer, menacing_spy, x, y,
                    light_strength_on_corner_1,
                    light_strength_on_corner_2,
                    light_strength_on_corner_3,
                    light_strength_on_corner_4);@end example


@end ftable
See also:@*
@xref{draw_sprite}.@*
@xref{draw_lit_sprite}.@*
@xref{color_map}.@*
@xref{set_trans_blender}.@*
@xref{bitmap_mask_color}.@*
@xref{exshade}.@*
@xref{BITMAP}.@*
@node draw_character_ex, rotate_sprite, draw_gouraud_sprite, Blitting
@subsection draw_character_ex
@ftable @asis
@item @t{void draw_character_ex(BITMAP *bmp, BITMAP *sprite, int x, int y, color, bg);}
Draws a copy of the sprite bitmap onto the destination bitmap at the 
specified position, drawing transparent pixels in the background color
(or skipping them if the background color is -1) and setting all other
pixels to the specified color. Transparent pixels are marked by a zero
in 256-color modes or bright pink for truecolor data (maximum red and
blue, zero green). The sprite must be an 8-bit image, even if the
destination is a truecolor bitmap. Example:
@example

BITMAP *logo;
...
/* Draw the logo silhouette in red. */
draw_character_ex(screen, logo, SCREEN_W / 2, SCREEN_H / 2,
                  makecol(255, 0, 0), -1);@end example


@end ftable
See also:@*
@xref{draw_sprite}.@*
@xref{bitmap_mask_color}.@*
@xref{BITMAP}.@*
@node rotate_sprite, rotate_sprite_v_flip, draw_character_ex, Blitting
@subsection rotate_sprite
@ftable @asis
@item @t{void rotate_sprite(BITMAP *bmp, BITMAP *sprite, int x, int y, fixed angle);}
Draws the sprite image onto the bitmap. It is placed with its top left
corner at the specified position, then rotated by the specified angle
around its centre. The angle is a fixed point 16.16 number in the same
format used by the fixed point trig routines, with 256 equal to a full
circle, 64 a right angle, etc. All rotation functions can draw between any
two bitmaps, even screen bitmaps or bitmaps of different color depth.

Positive increments of the angle will make the sprite rotate clockwise
on the screen, as demonstrated by the Allegro example.

@end ftable
See also:@*
@xref{draw_sprite}.@*
@xref{rotate_scaled_sprite}.@*
@xref{rotate_sprite_v_flip}.@*
@xref{rotate_scaled_sprite_v_flip}.@*
@xref{pivot_sprite}.@*
@xref{pivot_sprite_v_flip}.@*
@xref{pivot_scaled_sprite}.@*
@xref{pivot_scaled_sprite_v_flip}.@*
@xref{itofix}.@*
@xref{Fixed point trig}.@*
@xref{exsprite}.@*
@xref{fixed}.@*
@xref{BITMAP}.@*
@node rotate_sprite_v_flip, rotate_scaled_sprite, rotate_sprite, Blitting
@subsection rotate_sprite_v_flip
@ftable @asis
@item @t{void rotate_sprite_v_flip(BITMAP *bmp, BITMAP *sprite, int x, int y, fixed angle);}
Like rotate_sprite, but flips the image vertically before rotating it. To
flip horizontally, use this routine but add itofix(128) to the angle. To
flip in both directions, use rotate_sprite() and add itofix(128) to its
angle.

@end ftable
See also:@*
@xref{rotate_sprite}.@*
@xref{rotate_scaled_sprite_v_flip}.@*
@xref{pivot_sprite_v_flip}.@*
@xref{pivot_scaled_sprite_v_flip}.@*
@xref{exsprite}.@*
@xref{fixed}.@*
@xref{BITMAP}.@*
@node rotate_scaled_sprite, rotate_scaled_sprite_v_flip, rotate_sprite_v_flip, Blitting
@subsection rotate_scaled_sprite
@ftable @asis
@item @t{void rotate_scaled_sprite(BITMAP *bmp, BITMAP *sprite, int x, int y, fixed angle, fixed scale);}
Like rotate_sprite(), but stretches or shrinks the image at the same time 
as rotating it.

@end ftable
See also:@*
@xref{rotate_sprite}.@*
@xref{rotate_scaled_sprite_v_flip}.@*
@xref{pivot_scaled_sprite}.@*
@xref{pivot_scaled_sprite_v_flip}.@*
@xref{fixed}.@*
@xref{BITMAP}.@*
@node rotate_scaled_sprite_v_flip, pivot_sprite, rotate_scaled_sprite, Blitting
@subsection rotate_scaled_sprite_v_flip
@ftable @asis
@item @t{void rotate_scaled_sprite_v_flip(BITMAP *bmp, BITMAP *sprite, int x, int y, fixed angle, fixed scale);}
Draws the sprite, similar to rotate_scaled_sprite() except that it flips
the sprite vertically first.

@end ftable
See also:@*
@xref{rotate_sprite}.@*
@xref{rotate_scaled_sprite}.@*
@xref{rotate_sprite_v_flip}.@*
@xref{fixed}.@*
@xref{BITMAP}.@*
@node pivot_sprite, pivot_sprite_v_flip, rotate_scaled_sprite_v_flip, Blitting
@subsection pivot_sprite
@ftable @asis
@item @t{void pivot_sprite(BITMAP *bmp, BITMAP *sprite, int x, int y, int cx, int cy, fixed angle);}
Like rotate_sprite(), but aligns the point in the sprite given by (cx, cy)
to (x, y) in the bitmap, then rotates around this point.

@end ftable
See also:@*
@xref{rotate_sprite}.@*
@xref{pivot_scaled_sprite}.@*
@xref{pivot_sprite_v_flip}.@*
@xref{exsprite}.@*
@xref{fixed}.@*
@xref{BITMAP}.@*
@node pivot_sprite_v_flip, pivot_scaled_sprite, pivot_sprite, Blitting
@subsection pivot_sprite_v_flip
@ftable @asis
@item @t{void pivot_sprite_v_flip(BITMAP *bmp, BITMAP *sprite, int x, int y, int cx, int cy, fixed angle);}
Like rotate_sprite_v_flip(), but aligns the point in the sprite given by
(cx, cy) to (x, y) in the bitmap, then rotates around this point.

@end ftable
See also:@*
@xref{rotate_sprite}.@*
@xref{rotate_sprite_v_flip}.@*
@xref{pivot_sprite}.@*
@xref{exsprite}.@*
@xref{fixed}.@*
@xref{BITMAP}.@*
@node pivot_scaled_sprite, pivot_scaled_sprite_v_flip, pivot_sprite_v_flip, Blitting
@subsection pivot_scaled_sprite
@ftable @asis
@item @t{void pivot_scaled_sprite(BITMAP *bmp, BITMAP *sprite, int x, int y, int cx, int cy, fixed angle, fixed scale);}
Like rotate_scaled_sprite(), but aligns the point in the sprite given by
(cx, cy) to (x, y) in the bitmap, then rotates and scales around this
point.

@end ftable
See also:@*
@xref{rotate_sprite}.@*
@xref{rotate_scaled_sprite}.@*
@xref{pivot_sprite}.@*
@xref{pivot_scaled_sprite_v_flip}.@*
@xref{fixed}.@*
@xref{BITMAP}.@*
@node pivot_scaled_sprite_v_flip, get_rle_sprite, pivot_scaled_sprite, Blitting
@subsection pivot_scaled_sprite_v_flip
@ftable @asis
@item @t{void pivot_scaled_sprite_v_flip(BITMAP *bmp, BITMAP *sprite, int x, int y, int cx, int cy, fixed angle, fixed scale);}
Like rotate_scaled_sprite_v_flip(), but aligns the point in the sprite
given by (cx, cy) to (x, y) in the bitmap, then rotates and scales around
this point.



@end ftable
See also:@*
@xref{rotate_sprite}.@*
@xref{rotate_scaled_sprite_v_flip}.@*
@xref{rotate_sprite_v_flip}.@*
@xref{pivot_sprite}.@*
@xref{pivot_scaled_sprite}.@*
@xref{fixed}.@*
@xref{BITMAP}.@*
@node RLE, Compiled, Blitting, API
@section RLE sprites

Because bitmaps can be used in so many different ways, the bitmap structure 
is quite complicated, and it contains a lot of data. In many situations, 
though, you will find yourself storing images that are only ever copied to 
the screen, rather than being drawn onto or used as filling patterns, etc. 
If this is the case you may be better off storing your images in RLE_SPRITE 
(read chapter "Structures and types defined by Allegro" for an internal
description of the RLE_SPRITE structure) or COMPILED_SPRITE (see next
chapter) structures rather than regular bitmaps.

RLE sprites store the image in a simple run-length encoded format, where 
repeated zero pixels are replaced by a single length count, and strings of 
non-zero pixels are preceded by a counter giving the length of the solid 
run. RLE sprites are usually much smaller than normal bitmaps, both because
of the run length compression, and because they avoid most of the overhead 
of the bitmap structure. They are often also faster than normal bitmaps, 
because rather than having to compare every single pixel with zero to 
determine whether it should be drawn, it is possible to skip over a whole 
run of zeros with a single add, or to copy a long run of non-zero pixels 
with fast string instructions.

Every silver lining has a cloud, though, and in the case of RLE sprites it 
is a lack of flexibility. You can't draw onto them, and you can't flip them, 
rotate them, or stretch them. In fact the only thing you can do with them is 
to blast them onto a bitmap with the draw_rle_sprite() function, which is 
equivalent to using draw_sprite() with a regular bitmap. You can convert 
bitmaps into RLE sprites at runtime, or you can create RLE sprite structures 
in grabber datafiles by making a new object of type 'RLE sprite'.

@menu
* get_rle_sprite::
* destroy_rle_sprite::
* draw_rle_sprite::
* draw_trans_rle_sprite::
* draw_lit_rle_sprite::
@end menu
@node get_rle_sprite, destroy_rle_sprite, pivot_scaled_sprite_v_flip, RLE
@subsection get_rle_sprite
@ftable @asis
@item @t{RLE_SPRITE *get_rle_sprite(BITMAP *bitmap);}
Creates an RLE sprite based on the specified bitmap (which must be a 
memory bitmap). Remember to free this RLE sprite later to avoid memory
leaks. Example:
@example

RLE_SPRITE *rle;
BITMAP *bmp;
...
/* Create RLE sprite from an existent bitmap. */
rle = get_rle_sprite(bmp);
if (!rle)
   abort_on_error("Couldn't create RLE sprite!");
   
/* We don't need the bitmap any more.*/
destroy_bitmap(bmp);

/* Use the RLE sprite. */
...
/* Destroy it when we don't need it any more. */
destroy_rle_sprite(rle);@end example


Returns a pointer to the created RLE sprite, or NULL if the RLE sprite
could not be created. Remember to free this RLE sprite later to avoid
memory leaks.

@end ftable
See also:@*
@xref{draw_rle_sprite}.@*
@xref{destroy_rle_sprite}.@*
@xref{BITMAP}.@*
@xref{RLE_SPRITE}.@*
@node destroy_rle_sprite, draw_rle_sprite, get_rle_sprite, RLE
@subsection destroy_rle_sprite
@ftable @asis
@item @t{void destroy_rle_sprite(RLE_SPRITE *sprite);}
Destroys an RLE sprite structure previously returned by get_rle_sprite().
If you pass a NULL pointer this function won't do anything. Use this once
you are done with an RLE sprite to avoid memory leaks in your program.

@end ftable
See also:@*
@xref{get_rle_sprite}.@*
@xref{RLE_SPRITE}.@*
@node draw_rle_sprite, draw_trans_rle_sprite, destroy_rle_sprite, RLE
@subsection draw_rle_sprite
@ftable @asis
@item @t{void draw_rle_sprite(BITMAP *bmp, const RLE_SPRITE *sprite, int x, int y);}
Draws an RLE sprite onto a bitmap at the specified position. Example:
@example

RLE_SPRITE *rle_sprite;
...
draw_rle_sprite(screen, rle_sprite, 100, 100);@end example


@end ftable
See also:@*
@xref{get_rle_sprite}.@*
@xref{draw_sprite}.@*
@xref{draw_compiled_sprite}.@*
@xref{draw_trans_rle_sprite}.@*
@xref{draw_lit_rle_sprite}.@*
@xref{bitmap_mask_color}.@*
@xref{BITMAP}.@*
@xref{RLE_SPRITE}.@*
@node draw_trans_rle_sprite, draw_lit_rle_sprite, draw_rle_sprite, RLE
@subsection draw_trans_rle_sprite
@ftable @asis
@item @t{void draw_trans_rle_sprite(BITMAP *bmp, const RLE_SPRITE *sprite, int x, int y);}
Translucent version of draw_rle_sprite(). See the description of 
draw_trans_sprite(). This must only be used after you have set up the 
color mapping table (for 256-color modes) or blender functions (for 
truecolor modes). The bitmap and sprite must normally be in the same 
color depth, but as a special case you can draw 32-bit RGBA format 
sprites onto any hicolor or truecolor bitmap, as long as you call 
set_alpha_blender() first. Example:
@example

/* Some one time initialisation code. */
COLOR_MAP global_trans_table;
create_trans_table(&global_trans_table, my_palette,
                   128, 128, 128, NULL);
...
if (get_color_depth() == 8)
   color_map = &global_trans_table;
else
   set_trans_blender(128, 128, 128, 128);

draw_trans_rle_sprite(buffer, rle_ghost_sprite, x, y);@end example


@end ftable
See also:@*
@xref{draw_rle_sprite}.@*
@xref{draw_lit_rle_sprite}.@*
@xref{draw_trans_sprite}.@*
@xref{color_map}.@*
@xref{set_trans_blender}.@*
@xref{set_alpha_blender}.@*
@xref{bitmap_mask_color}.@*
@xref{BITMAP}.@*
@xref{RLE_SPRITE}.@*
@node draw_lit_rle_sprite, get_compiled_sprite, draw_trans_rle_sprite, RLE
@subsection draw_lit_rle_sprite
@ftable @asis
@item @t{void draw_lit_rle_sprite(BITMAP *bmp, const RLE_SPRITE *sprite, int x, y, color);}
Tinted version of draw_rle_sprite(). See the description of
draw_lit_sprite(). This must only be used after you have set up the color 
mapping table (for 256-color modes) or blender functions (for truecolor 
modes). Example:
@example

/* Some one time initialisation code. */
COLOR_MAP global_light_table;
create_light_table(&global_trans_table, my_palette,
                   10, 10, 60, NULL);
...
if (get_color_depth() == 8)
   color_map = &global_light_table;
else
   set_trans_blender(40, 40, 255, 255);

/* Lit the cape with a blueish light. */
draw_lit_rle_sprite(buffer, rle_colored_cape, x, y, 64);@end example




@end ftable
See also:@*
@xref{draw_rle_sprite}.@*
@xref{draw_trans_rle_sprite}.@*
@xref{draw_lit_sprite}.@*
@xref{color_map}.@*
@xref{set_trans_blender}.@*
@xref{bitmap_mask_color}.@*
@xref{BITMAP}.@*
@xref{RLE_SPRITE}.@*
@node Compiled, Fonts, RLE, API
@section Compiled sprites

Compiled sprites are stored as actual machine code instructions that draw a 
specific image onto a bitmap, using mov instructions with immediate data 
values. This is the fastest way to draw a masked image: on slow machines,
up to and including a 486, drawing compiled sprites can be about to five
times as fast as using draw_sprite() with a regular bitmap. On newer
machines the difference is usually negligible.

Compiled sprites are big, so if memory is tight you should use RLE sprites
instead, and what you can do with them is even more restricted than with RLE
sprites, because they don't support clipping. If you try to draw one off the
edge of a bitmap, you will corrupt memory and probably crash the system. You
can convert bitmaps into compiled sprites at runtime, or you can create
compiled sprite structures in grabber datafiles by making a new object of
type 'Compiled sprite' or 'Compiled x-sprite'.

@menu
* get_compiled_sprite::
* destroy_compiled_sprite::
* draw_compiled_sprite::
@end menu
@node get_compiled_sprite, destroy_compiled_sprite, draw_lit_rle_sprite, Compiled
@subsection get_compiled_sprite
@ftable @asis
@item @t{COMPILED_SPRITE *get_compiled_sprite(BITMAP *bitmap, int planar);}
Creates a compiled sprite based on the specified bitmap (which must be a 
memory bitmap). Compiled sprites are device-dependent, so you have to 
specify whether to compile it into a linear or planar format. Pass FALSE
as the second parameter if you are going to be drawing it onto memory 
bitmaps or mode 13h and SVGA screen bitmaps, and pass TRUE if you are 
going to draw it onto mode-X or Xtended mode screen bitmaps. Example:
@example

COMPILED_SPRITE *cspr;
BITMAP *bmp;
...
/* Create compiled sprite from an existent bitmap. */
cspr = get_compiled_sprite(bmp, 0);
if (!cspr)
   abort_on_error("Couldn't create compiled sprite!");

/* We don't need the bitmap any more.*/
destroy_bitmap(bmp);

/* Use the compiled sprite. */
...
/* Destroy it when we don't need it any more. */
destroy_compiled_sprite(cspr);
@end example

Returns a pointer to the created compiled sprite, or NULL if the compiled
sprite could not be created. Remember to free this compiled sprite later
to avoid memory leaks.

@end ftable
See also:@*
@xref{draw_compiled_sprite}.@*
@xref{destroy_compiled_sprite}.@*
@xref{BITMAP}.@*
@xref{COMPILED_SPRITE}.@*
@node destroy_compiled_sprite, draw_compiled_sprite, get_compiled_sprite, Compiled
@subsection destroy_compiled_sprite
@ftable @asis
@item @t{void destroy_compiled_sprite(COMPILED_SPRITE *sprite);}
Destroys a compiled sprite structure previously returned by 
get_compiled_sprite(). If you pass a NULL pointer this function won't do
anything. Use this once you are done with a compiled sprite to avoid
memory leaks in your program.

@end ftable
See also:@*
@xref{get_compiled_sprite}.@*
@xref{COMPILED_SPRITE}.@*
@node draw_compiled_sprite, register_font_file_type, destroy_compiled_sprite, Compiled
@subsection draw_compiled_sprite
@ftable @asis
@item @t{void draw_compiled_sprite(BITMAP *bmp, const COMPILED_SPRITE *sprite, int x, int y);}
Draws a compiled sprite onto a bitmap at the specified position. The 
sprite must have been compiled for the correct type of bitmap (linear or 
planar). This function does not support clipping.

Hint: if not being able to clip compiled sprites is a problem, a neat 
trick is to set up a work surface (memory bitmap, mode-X virtual screen, 
or whatever) a bit bigger than you really need, and use the middle of it 
as your screen. That way you can draw slightly off the edge without any 
trouble... 



@end ftable
See also:@*
@xref{get_compiled_sprite}.@*
@xref{draw_sprite}.@*
@xref{draw_rle_sprite}.@*
@xref{bitmap_mask_color}.@*
@xref{BITMAP}.@*
@xref{COMPILED_SPRITE}.@*
@node Fonts, Text, Compiled, API
@section Fonts

Allegro provides routines for loading fonts directly from GRX format .fnt
files, 8x8 or 8x16 BIOS format .fnt files, from bitmap images, from datafiles
or you can import a multiple-range Unicode font by writing a .txt script that
specifies a number of different source files for each range of characters.

By default, Allegro can only use bitmapped (non-scalable) fonts. If you want
to use TrueType fonts, you will need to use an add-on library which allows
you to load them on the fly (like AllegTTF or Glyph Keeper, listed among
others at http://www.allegro.cc/) and render them directly, or generate a
bitmapped version of a TrueType font with tools like TTF2PCX
(http://www.talula.demon.co.uk/ttf2pcx/index.html).

@menu
* register_font_file_type::
* load_font::
* destroy_font::
* make_trans_font::
* is_trans_font::
* is_color_font::
* is_mono_font::
* font_has_alpha::
* is_compatible_font::
* get_font_ranges::
* get_font_range_begin::
* get_font_range_end::
* extract_font_range::
* transpose_font::
* merge_fonts::
* load_dat_font::
* load_bios_font::
* load_grx_font::
* load_grx_or_bios_font::
* load_bitmap_font::
* grab_font_from_bitmap::
* load_txt_font::
@end menu
@node register_font_file_type, load_font, draw_compiled_sprite, Fonts
@subsection register_font_file_type
@ftable @asis
@item @t{void register_font_file_type(const char *ext, FONT *(*load)(const char *filename, RGB *pal, void *param));}
Informs the load_font() functions of a new file type, providing a routine 
to read fonts in this format. The function you supply must follow the 
following prototype:
@example

FONT *load_my_font(const char *filename, RGB *pal, void *param)
@{
   ...
@}
@end example

The pal parameter can optionally be used to return a palette for the FONT.
The parameter param can be anything you like: you can use this to pass
information to your loading routine, such as for instance the font height,
the character range to load or the index number of a font in a datafile.
If you choose to write your own font loading code, your function should be
prepared to deal with a value of NULL for either of these parameters.

@end ftable
See also:@*
@xref{load_font}.@*
@xref{RGB}.@*
@xref{FONT}.@*
@node load_font, destroy_font, register_font_file_type, Fonts
@subsection load_font
@ftable @asis
@item @t{FONT *load_font(const char *filename, RGB *pal, void *param);}
Loads a font from a file. At present, this supports loading fonts from
a GRX format .fnt file, a 8x8 or 8x16 BIOS format .fnt file, a datafile or
any bitmap format that can be loaded by load_bitmap().

If the font contains palette information, then the palette is returned in
the second parameter, which should be an array of 256 RGB structures 
(a PALETTE). The pal argument may be NULL. In this case, the palette data,
if present, is simply not returned.

The third parameter can be used to pass specific information to a custom
loader routine. Normally, you can just leave this as NULL. Note that
another way of loading fonts is embedding them into a datafile and using
the datafile related functions.

Example:
@example

FONT *myfont;
PALETTE palette;
...
myfont = load_font("my_font.pcx", palette, NULL);
if (!myfont)
   abort_on_error("Couldn't load font!");
...
textout_centre_ex(screen, myfont, "This is my own pretty font!",
                  SCREEN_W / 2, SCREEN_H / 2, white, black);
...
destroy_font(myfont);@end example


Returns a pointer to the font or NULL on error. Remember that you are
responsible for destroying the font when you are finished with it to
avoid memory leaks.

@end ftable
See also:@*
@xref{register_font_file_type}.@*
@xref{load_bitmap}.@*
@xref{load_dat_font}.@*
@xref{load_bios_font}.@*
@xref{load_grx_font}.@*
@xref{load_grx_or_bios_font}.@*
@xref{load_bitmap_font}.@*
@xref{load_txt_font}.@*
@xref{destroy_font}.@*
@xref{exfont}.@*
@xref{RGB}.@*
@xref{FONT}.@*
@node destroy_font, make_trans_font, load_font, Fonts
@subsection destroy_font
@ftable @asis
@item @t{void destroy_font(FONT *f);}
Frees the memory being used by a font structure. Don't use this on the
default global Allegro font or any text routines using it could crash. You
should use this only on fonts you have loaded manually after you are done
with them, to prevent memory leaks in your program.

@end ftable
See also:@*
@xref{load_datafile_object}.@*
@xref{load_font}.@*
@xref{exfont}.@*
@xref{FONT}.@*
@node make_trans_font, is_trans_font, destroy_font, Fonts
@subsection make_trans_font
@ftable @asis
@item @t{void make_trans_font(FONT *f);}
This function converts a font to use transparency for drawing. That is, each
glyph in the font will be drawn with draw_trans_sprite, so you can use the
same blenders as with draw_trans_sprite to draw the font. One common use of
this is to load a bitmap font with an alpha channel, and therefore get
anti-aliased text output by using Allegro's alpha blender. Here's an example
how to do that:

@example

FONT *f = load_font("alphafont.tga", NULL, NULL);
make_trans_font(f);
set_alpha_blender();
textprintf_centre_ex(screen, f, 320, 240, -1, -1, "Anti-aliased Font!");@end example


@end ftable
See also:@*
@xref{is_trans_font}.@*
@xref{set_alpha_blender}.@*
@xref{load_font}.@*
@xref{draw_trans_sprite}.@*
@xref{FONT}.@*
@node is_trans_font, is_color_font, make_trans_font, Fonts
@subsection is_trans_font
@ftable @asis
@item @t{int is_trans_font(FONT *f)}
This function checks if the given font is a color font using
draw_trans_sprite to render glyphs.

Returns TRUE if the font uses transparency, FALSE if it does not.

@end ftable
See also:@*
@xref{make_trans_font}.@*
@xref{is_color_font}.@*
@xref{is_mono_font}.@*
@xref{FONT}.@*
@node is_color_font, is_mono_font, is_trans_font, Fonts
@subsection is_color_font
@ftable @asis
@item @t{int is_color_font(FONT *f)}
This function checks if the given font is a color font, as opposed to a
monochrome font.

Returns TRUE if the font is a color font, FALSE if it is not.

@end ftable
See also:@*
@xref{is_trans_font}.@*
@xref{is_mono_font}.@*
@xref{FONT}.@*
@node is_mono_font, font_has_alpha, is_color_font, Fonts
@subsection is_mono_font
@ftable @asis
@item @t{int is_mono_font(FONT *f)}
This function checks if the given font is a mono font, as opposed to a
color font.

Returns TRUE if the font is a monochrome font, FALSE if it is not.

@end ftable
See also:@*
@xref{is_trans_font}.@*
@xref{is_color_font}.@*
@xref{FONT}.@*
@node font_has_alpha, is_compatible_font, is_mono_font, Fonts
@subsection font_has_alpha
@ftable @asis
@item @t{int font_has_alpha(FONT *f)}
This function goes through all pixels of all glyphs in the font and looks for
alpha values.

Returns TRUE if any alpha pixels are found, else FALSE.

@end ftable
See also:@*
@xref{is_trans_font}.@*
@xref{FONT}.@*
@node is_compatible_font, get_font_ranges, font_has_alpha, Fonts
@subsection is_compatible_font
@ftable @asis
@item @t{int *is_compatible_font(FONT *f1, FONT *f2)}
This function compares the two fonts, which you can use to find out if
Allegro is capable of merging them.

Returns TRUE if the two fonts are of the same general type (both are color
fonts or both are monochrome fonts, for instance).

@end ftable
See also:@*
@xref{merge_fonts}.@*
@xref{is_trans_font}.@*
@xref{is_color_font}.@*
@xref{is_mono_font}.@*
@xref{FONT}.@*
@node get_font_ranges, get_font_range_begin, is_compatible_font, Fonts
@subsection get_font_ranges
@ftable @asis
@item @t{int get_font_ranges(FONT *f)}
Use this function to find out the number of character ranges in a font. You
should query each of these ranges with get_font_range_begin() and
get_font_range_end() to find out what characters are available in the
font. Example:
@example

FONT *f;
int range;
int n;
...

range = get_font_ranges(f);
printf("The font has %d character ranges:\n", range);
for (n = 0; n < range; n++)
   printf("Range %d from 0x%03x - 0x%03x\n",
          get_font_range_begin(f, n),
          get_font_range_end(f, n));@end example


Returns the number of continuous character ranges in a font, or -1 if that
information is not available.

@end ftable
See also:@*
@xref{get_font_range_begin}.@*
@xref{get_font_range_end}.@*
@xref{transpose_font}.@*
@xref{FONT}.@*
@node get_font_range_begin, get_font_range_end, get_font_ranges, Fonts
@subsection get_font_range_begin
@ftable @asis
@item @t{int get_font_range_begin(FONT *f, int range)}
This function allows you to find out the start of a specific character
range for a font. You can pass -1 for the `range' parameter if you want to
know the start of the whole font range, or a number from 0 to (but not
including) get_font_ranges(f) to get the start of a specific character
range in the font. Example:
@example

printf("The font has a character range of %d - %d\n",
       get_font_range_begin(font, -1),
       get_font_range_end(font, -1));@end example


Returns the first character in the font range, or -1 if that information
is not available.

@end ftable
See also:@*
@xref{get_font_ranges}.@*
@xref{get_font_range_end}.@*
@xref{transpose_font}.@*
@xref{FONT}.@*
@node get_font_range_end, extract_font_range, get_font_range_begin, Fonts
@subsection get_font_range_end
@ftable @asis
@item @t{int get_font_range_end(FONT *f, int range)}
This function allows you to find out the index to the last character of a
character range for a font. You can pass -1 for the range parameter if you
want to know the start of the whole font range, or a number from 0 to (but
not including) get_font_ranges(f) to get the start of a specific character
range in the font. You should check the start and end of all font ranges to
see if a specific character is actually available in the font. Not all
characters in the range returned by get_font_range_begin(f, -1) and
get_font_range_end(f, -1) need to be available! Example:
@example

printf("The font has a character range of %d - %d\n",
       get_font_range_begin(font, -1),
       get_font_range_end(font, -1));@end example


Returns the last character in the font range, or -1 if that information is
not available.

@end ftable
See also:@*
@xref{get_font_ranges}.@*
@xref{get_font_range_begin}.@*
@xref{transpose_font}.@*
@xref{FONT}.@*
@node extract_font_range, transpose_font, get_font_range_end, Fonts
@subsection extract_font_range
@ftable @asis
@item @t{FONT *extract_font_range(FONT *f, int begin, int end)}
This function extracts a character range from a font and returns a new font
that contains only the range of characters selected by this function. You
can pass -1 for either the lower or upper bound if you want to select all
characters from the start or to the end of the font.
Example:
@example

FONT *myfont;
FONT *capitals;
FONT *fontcopy;
...
/* Create a font of only capital letters */
capitals = extract_font_range(myfont, 'A', 'Z');

/* Create a copy of the font */
fontcopy = extract_font_range(myfont, -1, -1);
...
destroy_font(capitals);
destroy_font(fontcopy);@end example


Returns a pointer to the new font or NULL on error. Remember that you are
responsible for destroying the font when you are finished with it to
avoid memory leaks.

@end ftable
See also:@*
@xref{get_font_range_begin}.@*
@xref{get_font_range_end}.@*
@xref{merge_fonts}.@*
@xref{transpose_font}.@*
@xref{exfont}.@*
@xref{FONT}.@*
@node transpose_font, merge_fonts, extract_font_range, Fonts
@subsection transpose_font
@ftable @asis
@item @t{int transpose_font(FONT *f, int drange)}
This function transposes all characters in a font, effectively remapping the
font. Example:
@example

FONT *myfont;
FONT *capitals;
...
/* Create a font of only capital letters */
capitals = extract_font_range(myfont, 'A', 'Z');

/* Now transpose the characters in the font so that they will be used */
/*  for the lower case letters a-z */
transpose_font(capitals, 'a'-'A');
textout_ex(screen, capitals, "allcaps",
           100, 100, makecol(255,255,255), 0);@end example


Returns 0 on success, -1 on failure.

@end ftable
See also:@*
@xref{get_font_range_begin}.@*
@xref{get_font_range_end}.@*
@xref{merge_fonts}.@*
@xref{extract_font_range}.@*
@xref{FONT}.@*
@node merge_fonts, load_dat_font, transpose_font, Fonts
@subsection merge_fonts
@ftable @asis
@item @t{FONT *merge_fonts(FONT *f1, FONT *f2)}
This function merges the character ranges from two fonts and returns a new
font containing all characters in the old fonts. In general, you cannot
merge fonts of different types (eg, TrueType fonts and bitmapped fonts),
but as a special case, this function can promote a monochrome bitmapped
font to a color font and merge those. Example:
@example

FONT *myfont;
FONT *myfancy_font;
FONT *lower_range;
FONT *upper_range;
FONT *capitals;
FONT *combined_font;
FONT *tempfont;
...
/* Create a font that contains the capitals from  */
/* the fancy font but other characters from myfont */
lower_range = extract_font_range(myfont, -1, 'A'-1);
upper_range = extract_font_range(myfont, 'Z'+1, -1);
capitals = extract_font_range(myfancy_font, 'A', 'Z');

tempfont = merge_fonts(lower_range, capitals);
combined_font = merge_fonts(tempfont, upper_range);

/* Clean up temporary fonts */
destroy_font(lower_range);
destroy_font(upper_range);
destroy_font(capitals);
destroy_font(tempfont);@end example


Returns a pointer to the new font or NULL on error. Remember that you are
responsible for destroying the font when you are finished with it to
avoid memory leaks.

@end ftable
See also:@*
@xref{extract_font_range}.@*
@xref{is_trans_font}.@*
@xref{is_color_font}.@*
@xref{is_mono_font}.@*
@xref{exfont}.@*
@xref{FONT}.@*
@node load_dat_font, load_bios_font, merge_fonts, Fonts
@subsection load_dat_font
@ftable @asis
@item @t{FONT *load_dat_font(const char *filename, RGB *pal, void *param)}
Loads a FONT from an Allegro datafile. You can set param parameter to
point to an array that holds two strings that identify the font and the 
palette in the datafile by name.
The first string in this list is the name of the font. You can pass NULL
here to just load the first font found in the datafile. The second string
can be used to specify the name of the palette associated with the font.
This is only returned if the pal parameter is not NULL. If you pass NULL
for the name of the palette, the last palette found before the font was
found is returned.
You can also pass NULL for param, which is treated as if you had passed
NULL for both strings separately. In this case, the function will simply
load the first font it finds from the datafile and the palette that
precedes it.

For example, suppose you have a datafile named `fonts.dat' with the
following contents:
@example

FONT  FONT_1_DATA
FONT  FONT_2_DATA
FONT  FONT_3_DATA
PAL   FONT_1_PALETTE
PAL   FONT_2_PALETTE
@end example

Then the following code will load FONT_1_DATA as a FONT and return
FONT_1_PALETTE as the palette:
@example

FONT *f;
PALETTE pal;
char *names[] = @{ "FONT_1_DATA", "FONT_1_PALETTE" @}

f = load_dat_font("fonts.dat", pal, names);
@end example

If instead you want to load the second font, FONT_2, from the datafile,
you would use:
@example

FONT *f;
PALETTE pal;
char *names[] = @{ "FONT_2_DATA", "FONT_2_PALETTE" @}

f = load_dat_font("fonts.dat", pal, names);
@end example

If you want to load the third font, but not bother with a palette, use:
@example

FONT *f;
char *names[] = @{ "FONT_3_DATA", NULL @}

f = load_dat_font("fonts.dat", NULL, names);@end example


Returns a pointer to the font or NULL on error. Remember that you are
responsible for destroying the font when you are finished with it to
avoid memory leaks.

@end ftable
See also:@*
@xref{register_font_file_type}.@*
@xref{load_font}.@*
@xref{RGB}.@*
@xref{FONT}.@*
@node load_bios_font, load_grx_font, load_dat_font, Fonts
@subsection load_bios_font
@ftable @asis
@item @t{FONT *load_bios_font(const char *filename, RGB *pal, void *param)}
Loads a 8x8 or 8x16 BIOS format font. You shouldn't normally call this 
routine directly.

Returns a pointer to the font or NULL on error. Remember that you are
responsible for destroying the font when you are finished with it to
avoid memory leaks.

@end ftable
See also:@*
@xref{register_font_file_type}.@*
@xref{load_font}.@*
@xref{RGB}.@*
@xref{FONT}.@*
@node load_grx_font, load_grx_or_bios_font, load_bios_font, Fonts
@subsection load_grx_font
@ftable @asis
@item @t{FONT *load_grx_font(const char *filename, RGB *pal, void *param)}
Loads a GRX format font. You shouldn't normally call this routine
directly.

Returns a pointer to the font or NULL on error. Remember that you are
responsible for destroying the font when you are finished with it to
avoid memory leaks.

@end ftable
See also:@*
@xref{register_font_file_type}.@*
@xref{load_font}.@*
@xref{RGB}.@*
@xref{FONT}.@*
@node load_grx_or_bios_font, load_bitmap_font, load_grx_font, Fonts
@subsection load_grx_or_bios_font
@ftable @asis
@item @t{FONT *load_grx_or_bios_font(const char *filename, RGB *pal, void *param)}
Loads either a BIOS or GRX format font. You shouldn't normally call this 
routine directly.

Returns a pointer to the font or NULL on error. Remember that you are
responsible for destroying the font when you are finished with it to
avoid memory leaks.

@end ftable
See also:@*
@xref{register_font_file_type}.@*
@xref{load_font}.@*
@xref{RGB}.@*
@xref{FONT}.@*
@node load_bitmap_font, grab_font_from_bitmap, load_grx_or_bios_font, Fonts
@subsection load_bitmap_font
@ftable @asis
@item @t{FONT *load_bitmap_font(const char *filename, RGB *pal, void *param)}
Tries to grab a font from a bitmap. The bitmap can be in any format that
load_bitmap understands.

The size of each character is determined by the layout of the image, which
should be a rectangular grid containing all the ASCII characters from
space (32) up to the tilde (126). The way the characters are separated
depends on the color depth of the image file:

@itemize @bullet
@item 
paletted (8 bit) image file
Use color 0 for the transparent portions of the characters and fill the 
spaces between each letter with color 255.  
@item 
High (15/16 bit) and true (24/32 bit) color image file
Use bright pink (maximum red and blue, zero green) for the transparent
portions of the characters and fill the spaces between each letter with
bright yellow (maximum red and green, zero blue).
@end itemize


Note that in each horizontal row the bounding boxes around the characters 
should align and have the same height.

Probably the easiest way to get to grips with how this works is to load up 
the `demo.dat' file and export the TITLE_FONT into a PCX file. Have a look
at the resulting picture in your paint program: that is the format a font
should be in.

Take care with high and true color fonts: Allegro will convert these to the
current color depth when you load the font. If you try to use a font on
a bitmap with a different color depth Allegro will do color conversions on
the fly, which will be rather slow. For optimal performance you should
set the color depth to the color depth you want to use before loading any
fonts.

Returns a pointer to the font or NULL on error. Remember that you are
responsible for destroying the font when you are finished with it to
avoid memory leaks.

@end ftable
See also:@*
@xref{register_font_file_type}.@*
@xref{load_font}.@*
@xref{load_bitmap}.@*
@xref{set_color_depth}.@*
@xref{grab_font_from_bitmap}.@*
@xref{RGB}.@*
@xref{FONT}.@*
@node grab_font_from_bitmap, load_txt_font, load_bitmap_font, Fonts
@subsection grab_font_from_bitmap
@ftable @asis
@item @t{FONT *grab_font_from_bitmap(BITMAP *bmp)}
This function is the work-horse of load_bitmap_font, and can be used to
grab a font from a bitmap in memory. You can use this if you want to
generate or modify a font at runtime. The bitmap should follow the layout
described for load_bitmap_font.

Returns a pointer to the font or NULL on error. Remember that you are
responsible for destroying the font when you are finished with it to
avoid memory leaks.

@end ftable
See also:@*
@xref{load_bitmap_font}.@*
@xref{BITMAP}.@*
@xref{FONT}.@*
@node load_txt_font, font, grab_font_from_bitmap, Fonts
@subsection load_txt_font
@ftable @asis
@item @t{FONT *load_txt_font(const char *filename, RGB *pal, void *param)}
This function can be used to load scripted fonts. The script file
contains a number of lines in the format "filename start end", which
specify the source file for that range of characters, the Unicode value of
the first character in the range, and the end character in the range
(optional, if left out, the entire input file will be grabbed). If the
filename is replaced by a hyphen, more characters will be grabbed from the
previous input file.
For example, the script:
@example

ascii.fnt 0x20 0x7F
- 0xA0 0xFF
dingbats.fnt 0x1000
@end example

would import the first 96 characters from ascii.fnt as the range
0x20-0x7F, the next 96 characters from ascii.fnt as the range 0xA0-0xFF,
and the entire contents of dingbats.fnt starting at Unicode position
0x1000.

Returns a pointer to the font or NULL on error. Remember that you are
responsible for destroying the font when you are finished with it to
avoid memory leaks.



@end ftable
See also:@*
@xref{register_font_file_type}.@*
@xref{load_font}.@*
@xref{RGB}.@*
@xref{FONT}.@*
@node Text, Polygon, Fonts, API
@section Text output

Allegro provides text output routines that work with both monochrome and 
color fonts, which can contain any number of Unicode character ranges. The 
grabber program can create fonts from sets of characters drawn in a bitmap 
file (see grabber.txt for more information), and can also import GRX or BIOS 
format font files. The font structure contains a number of hooks that can be 
used to extend it with your own custom drawing code: see the definition in 
allegro/text.h for details.

@menu
* font::
* allegro_404_char::
* text_length::
* text_height::
* textout_ex::
* textout_centre_ex::
* textout_right_ex::
* textout_justify_ex::
* textprintf_ex::
* textprintf_centre_ex::
* textprintf_right_ex::
* textprintf_justify_ex::
@end menu
@node font, allegro_404_char, load_txt_font, Text
@subsection font
@ftable @asis
@item @t{extern FONT *font;}
A simple 8x8 fixed size font (the mode 13h BIOS default). If you want to 
alter the font used by the GUI routines, change this to point to one of 
your own fonts. This font contains the standard ASCII (U+20 to U+7F), 
Latin-1 (U+A1 to U+FF), and Latin Extended-A (U+0100 to U+017F) character 
ranges.

@end ftable
See also:@*
@xref{textout_ex}.@*
@xref{textprintf_ex}.@*
@xref{Available, Available Allegro examples}.@*
@xref{FONT}.@*
@node allegro_404_char, text_length, font, Text
@subsection allegro_404_char
@ftable @asis
@item @t{extern int allegro_404_char;}
When Allegro cannot find a glyph it needs in a font, it will instead
output the character given in allegro_404_char. By default, this is set to
the caret symbol, `^', but you can change this global to use any other
character instead. Example:
@example

/* Show unknown glyphs with an asterisk. */
allegro_404_char = '*';@end example


@end ftable
See also:@*
@xref{font}.@*
@node text_length, text_height, allegro_404_char, Text
@subsection text_length
@ftable @asis
@item @t{int text_length(const FONT *f, const char *str);}
Returns the length (in pixels) of a string in the specified font. Example:
@example

int width = text_length(font, "I love spam");
...
bmp = create_bitmap(width, height);@end example


@end ftable
See also:@*
@xref{text_height}.@*
@xref{ex12bit}.@*
@xref{exmidi}.@*
@xref{expat}.@*
@xref{exunicod}.@*
@xref{FONT}.@*
@node text_height, textout_ex, text_length, Text
@subsection text_height
@ftable @asis
@item @t{int text_height(const FONT *f)}
Returns the height (in pixels) of the specified font. Example:
@example

int height = text_height(font);
...
bmp = create_bitmap(width, height);@end example


@end ftable
See also:@*
@xref{text_length}.@*
@xref{ex12bit}.@*
@xref{exmidi}.@*
@xref{expackf}.@*
@xref{expat}.@*
@xref{exsprite}.@*
@xref{exsyscur}.@*
@xref{exunicod}.@*
@xref{FONT}.@*
@node textout_ex, textout_centre_ex, text_height, Text
@subsection textout_ex
@ftable @asis
@item @t{void textout_ex(BITMAP *bmp, const FONT *f, const char *s, int x, int y, int color, int bg);}
Writes the string `s' onto the bitmap at position x, y, using the
specified font, foreground color and background color. If the background
color is -1, then the text is written transparently. If the foreground
color is -1 and a color font is in use, it will be drawn using the colors
from the original font bitmap (the one you imported into the grabber
program), which allows multicolored text output. For high and true color
fonts, the foreground color is ignored and always treated as -1. Example:
@example

/* Show the program's version in blue letters. */
textout_ex(screen, font, "v4.2.0-beta2", 10, 10,
           makecol(0, 0, 255), -1);@end example


@end ftable
See also:@*
@xref{font}.@*
@xref{textout_centre_ex}.@*
@xref{textout_right_ex}.@*
@xref{textout_justify_ex}.@*
@xref{textprintf_ex}.@*
@xref{text_height}.@*
@xref{text_length}.@*
@xref{Available, Available Allegro examples}.@*
@xref{BITMAP}.@*
@xref{FONT}.@*
@node textout_centre_ex, textout_right_ex, textout_ex, Text
@subsection textout_centre_ex
@ftable @asis
@item @t{void textout_centre_ex(BITMAP *bmp, const FONT *f, const char *s, int x, y, int color, int bg);}
Like textout_ex(), but interprets the x coordinate as the centre rather
than the left edge of the string. Example:
@example

/* Important texts go in the middle. */
width = text_length("GAME OVER");
textout_centre_ex(screen, font, "GAME OVER",
                  SCREEN_W / 2, SCREEN_H / 2,
                  makecol(255, 0, 0), makecol(0, 0, 0));@end example


@end ftable
See also:@*
@xref{textout_ex}.@*
@xref{textprintf_centre_ex}.@*
@xref{Available, Available Allegro examples}.@*
@xref{BITMAP}.@*
@xref{FONT}.@*
@node textout_right_ex, textout_justify_ex, textout_centre_ex, Text
@subsection textout_right_ex
@ftable @asis
@item @t{void textout_right_ex(BITMAP *bmp, const FONT *f, const char *s, int x, int y, int color, int bg);}
Like textout_ex(), but interprets the x coordinate as the right rather
than the left edge of the string. Example:
@example

textout_right_ex(screen, font, "Look at this color!",
                 SCREEN_W - 10, 10, my_yellow, -1);@end example


@end ftable
See also:@*
@xref{textout_ex}.@*
@xref{textprintf_right_ex}.@*
@xref{BITMAP}.@*
@xref{FONT}.@*
@node textout_justify_ex, textprintf_ex, textout_right_ex, Text
@subsection textout_justify_ex
@ftable @asis
@item @t{void textout_justify_ex(BITMAP *bmp, const FONT *f, const char *s, int x1, int x2, int y, int diff, int color, int bg);}
Draws justified text within the region x1-x2. If the amount of spare
space is greater than the diff value, it will give up and draw regular
left justified text instead. Example:
@example

char *lines[] = @{"Draws justified text",
                 "within the specified",
                 "x2-x1 area. But not",
                 "T H I S !", NULL@};
/* Show the justification marker. */
vline(screen, 200, 0, SCREEN_H-1, makecol(0, 0, 0));
/* Draw all the lines until we reach a NULL entry. */
for (num = 0, y = 0; lines[num]; num++, y += text_height(font))
   textout_justify_ex(screen, font, lines[num], 0, 200,
                      y, 80, makecol(0, 0, 0),
                      makecol(255, 255, 255));@end example


@end ftable
See also:@*
@xref{textout_ex}.@*
@xref{textprintf_justify_ex}.@*
@xref{BITMAP}.@*
@xref{FONT}.@*
@node textprintf_ex, textprintf_centre_ex, textout_justify_ex, Text
@subsection textprintf_ex
@ftable @asis
@item @t{void textprintf_ex(BITMAP *bmp, const FONT *f, int x, int y, int color, int bg, const char *fmt, ...);}
Formatted text output, using a printf() style format string. Due to an
internal limitation, this function can't be used for extremely long texts.
If you happen to reach this limit, you can work around it by using
uszprintf() and textout_ex(), which don't have any. Example:
@example

int player_score;
...
textprintf_ex(screen, font, 10, 10, makecol(255, 100, 200),
              -1, "Score: %d", player_score);@end example


@end ftable
See also:@*
@xref{font}.@*
@xref{textout_ex}.@*
@xref{textprintf_centre_ex}.@*
@xref{textprintf_right_ex}.@*
@xref{textprintf_justify_ex}.@*
@xref{text_height}.@*
@xref{text_length}.@*
@xref{uszprintf}.@*
@xref{Available, Available Allegro examples}.@*
@xref{BITMAP}.@*
@xref{FONT}.@*
@node textprintf_centre_ex, textprintf_right_ex, textprintf_ex, Text
@subsection textprintf_centre_ex
@ftable @asis
@item @t{void textprintf_centre_ex(BITMAP *bmp, const FONT *f, int x, int y, int color, int bg, const char *fmt, ...);}
Like textprintf_ex(), but interprets the x coordinate as the centre rather
than the left edge of the string. This function shares the text length
limitation of textprintf_ex(). Example:
@example

textprintf_centre_ex(screen, font, SCREEN_W / 2, 120,
                     makecol(0, 100, 243), -1,
                     "Your best score so far was %d!",
                     total_max_points);@end example


@end ftable
See also:@*
@xref{textprintf_ex}.@*
@xref{textout_centre_ex}.@*
@xref{Available, Available Allegro examples}.@*
@xref{BITMAP}.@*
@xref{FONT}.@*
@node textprintf_right_ex, textprintf_justify_ex, textprintf_centre_ex, Text
@subsection textprintf_right_ex
@ftable @asis
@item @t{void textprintf_right_ex(BITMAP *bmp, const FONT *f, int x, y, color, bg, const char *fmt, ...);}
Like textprintf_ex(), but interprets the x coordinate as the right rather
than the left edge of the string. This function shares the text length
limitation of textprintf_ex(). Example:
@example

textprintf_right_ex(screen, font, SCREEN_W - 10, 10,
                    makecol(200, 200, 20), -1,
                    "%d bullets left", player_ammo);@end example


@end ftable
See also:@*
@xref{textprintf_ex}.@*
@xref{textout_right_ex}.@*
@xref{exmouse}.@*
@xref{BITMAP}.@*
@xref{FONT}.@*
@node textprintf_justify_ex, POLYTYPE_FLAT, textprintf_right_ex, Text
@subsection textprintf_justify_ex
@ftable @asis
@item @t{void textprintf_justify_ex(BITMAP *bmp, const FONT *f, int x1, x2, y, diff, color, bg, const char *fmt, ...);}
Like textout_justify_ex(), but using a printf() style format string. This
function shares the text length limitation of textprintf_ex(). Example:
@example

char *lines[] = @{"Line %02d: Draws justified text",
                 "Line %02d: within the specified",
                 "Line %02d: x2-x1 area. But not",
                 "Line %02d: T H I S !", NULL@};
/* Show the justification marker. */
vline(screen, 300, 0, SCREEN_H-1, makecol(0, 0, 0));
/* Draw all the lines until we reach a NULL entry. */
for (num = 0, y = 0; lines[num]; num++, y += text_height(font))
   textprintf_justify_ex(screen, font, 0, 300, y, 180,
                         makecol(0, 0, 0), makecol(255, 255, 255),
                         lines[num], num);@end example




@end ftable
See also:@*
@xref{textprintf_ex}.@*
@xref{textout_justify_ex}.@*
@xref{BITMAP}.@*
@xref{FONT}.@*
@node Polygon, Transparency, Text, API
@section Polygon rendering

All the 3d functions that accept a `type' parameter are asking for a polygon
rendering mode, which can be any of the following POLYTYPE_* values. If the
CPU_MMX flag of the cpu_capabilities global variable is set, the GRGB and
truecolor *LIT routines will be optimised using MMX instructions. If the
CPU_3DNOW flag is set, the truecolor PTEX*LIT routines will take advantage of
the 3DNow! CPU extensions.

Using MMX for *LIT routines has a side effect: normally (without MMX), these
routines use the blender functions used also for other lighting functions,
set with set_trans_blender() or set_blender_mode(). The MMX versions only use
the RGB value passed to set_trans_blender() and do the linear interpolation
themselves. Therefore a new set of blender functions passed to
set_blender_mode() is ignored.

@menu
* POLYTYPE_FLAT::
* POLYTYPE_GCOL::
* POLYTYPE_GRGB::
* POLYTYPE_ATEX::
* POLYTYPE_PTEX::
* POLYTYPE_ATEX_MASK::
* POLYTYPE_ATEX_LIT::
* POLYTYPE_ATEX_MASK_LIT::
* POLYTYPE_ATEX_TRANS::
* POLYTYPE_ATEX_MASK_TRANS::
* polygon3d::
* triangle3d::
* quad3d::
* clip3d_f::
* clip3d::
* Zbuffered rendering::
* create_zbuffer::
* create_sub_zbuffer::
* set_zbuffer::
* clear_zbuffer::
* destroy_zbuffer::
* Scene rendering::
* create_scene::
* clear_scene::
* destroy_scene::
* scene_polygon3d::
* render_scene::
* scene_gap::
@end menu
@node POLYTYPE_FLAT, POLYTYPE_GCOL, textprintf_justify_ex, Polygon
@subsection POLYTYPE_FLAT
@ftable @asis
@item @t{#define POLYTYPE_FLAT}
A simple flat shaded polygon, taking the color from the `c' value of the
first vertex. This polygon type is affected by the drawing_mode() function,
so it can be used to render XOR or translucent polygons.

@end ftable
See also:@*
@xref{Polygon, Polygon rendering}.@*
@xref{polygon3d}.@*
@xref{drawing_mode}.@*
@xref{ex3d}.@*
@xref{excamera}.@*
@node POLYTYPE_GCOL, POLYTYPE_GRGB, POLYTYPE_FLAT, Polygon
@subsection POLYTYPE_GCOL
@ftable @asis
@item @t{#define POLYTYPE_GCOL}
A single-color gouraud shaded polygon. The colors for each vertex are taken
from the `c' value, and interpolated across the polygon. This is very fast,
but will only work in 256-color modes if your palette contains a smooth
gradient between the colors. In truecolor modes it interprets the color as
a packed, display-format value as produced by the makecol() function.

@end ftable
See also:@*
@xref{Polygon, Polygon rendering}.@*
@xref{polygon3d}.@*
@xref{makecol}.@*
@xref{ex3d}.@*
@xref{exscn3d}.@*
@xref{exzbuf}.@*
@node POLYTYPE_GRGB, POLYTYPE_ATEX, POLYTYPE_GCOL, Polygon
@subsection POLYTYPE_GRGB
@ftable @asis
@item @t{#define POLYTYPE_GRGB}
A gouraud shaded polygon which interpolates RGB triplets rather than a
single color. In 256-color modes this uses the global rgb_map table to
convert the result to an 8-bit paletted color, so it must only be used
after you have set up the RGB mapping table! The colors for each vertex are
taken from the `c' value, which is interpreted as a 24-bit RGB triplet
(0xFF0000 is red, 0x00FF00 is green, and 0x0000FF is blue).

@end ftable
See also:@*
@xref{Polygon, Polygon rendering}.@*
@xref{polygon3d}.@*
@xref{rgb_map}.@*
@xref{ex3d}.@*
@node POLYTYPE_ATEX, POLYTYPE_PTEX, POLYTYPE_GRGB, Polygon
@subsection POLYTYPE_ATEX
@ftable @asis
@item @t{#define POLYTYPE_ATEX}
An affine texture mapped polygon. This stretches the texture across the
polygon with a simple 2d linear interpolation, which is fast but not
mathematically correct. It can look OK if the polygon is fairly small or
flat-on to the camera, but because it doesn't deal with perspective
foreshortening, it can produce strange warping artifacts. To see what this
means, run Allegro's test program and see what happens to the polygon3d()
test when you zoom in very close to the cube.

@end ftable
See also:@*
@xref{Polygon, Polygon rendering}.@*
@xref{polygon3d}.@*
@xref{ex3d}.@*
@node POLYTYPE_PTEX, POLYTYPE_ATEX_MASK, POLYTYPE_ATEX, Polygon
@subsection POLYTYPE_PTEX
@ftable @asis
@item @t{#define POLYTYPE_PTEX}
A perspective-correct texture mapped polygon. This uses the `z' value from
the vertex structure as well as the u/v coordinates, so textures are
displayed correctly regardless of the angle they are viewed from. Because
it involves division calculations in the inner texture mapping loop, this
mode is a lot slower than POLYTYPE_ATEX, and it uses floating point so it
will be very slow on anything less than a Pentium (even with an FPU, a 486
can't overlap floating point division with other integer operations like
the Pentium can).

@end ftable
See also:@*
@xref{Polygon, Polygon rendering}.@*
@xref{polygon3d}.@*
@xref{POLYTYPE_ATEX}.@*
@xref{ex3d}.@*
@node POLYTYPE_ATEX_MASK, POLYTYPE_ATEX_LIT, POLYTYPE_PTEX, Polygon
@subsection POLYTYPE_ATEX_MASK
@ftable @asis
@item @t{#define POLYTYPE_ATEX_MASK}
@end ftable
@ftable @asis
@item @t{#define POLYTYPE_PTEX_MASK}
Like POLYTYPE_ATEX and POLYTYPE_PTEX, but zero texture map pixels are
skipped, allowing parts of the texture map to be transparent.

@end ftable
See also:@*
@xref{Polygon, Polygon rendering}.@*
@xref{polygon3d}.@*
@xref{POLYTYPE_ATEX}.@*
@xref{POLYTYPE_PTEX}.@*
@xref{ex3d}.@*
@node POLYTYPE_ATEX_LIT, POLYTYPE_ATEX_MASK_LIT, POLYTYPE_ATEX_MASK, Polygon
@subsection POLYTYPE_ATEX_LIT
@ftable @asis
@item @t{#define POLYTYPE_ATEX_LIT}
@end ftable
@ftable @asis
@item @t{#define POLYTYPE_PTEX_LIT}
Like POLYTYPE_ATEX and POLYTYPE_PTEX, but the global color_map table (for
256-color modes) or blender function (for non-MMX truecolor modes) is used
to blend the texture with a light level taken from the `c' value in the
vertex structure. This must only be used after you have set up the color
mapping table or blender functions!

@end ftable
See also:@*
@xref{Polygon, Polygon rendering}.@*
@xref{polygon3d}.@*
@xref{POLYTYPE_ATEX}.@*
@xref{POLYTYPE_PTEX}.@*
@xref{color_map}.@*
@xref{Truecolor transparency}.@*
@xref{ex3d}.@*
@node POLYTYPE_ATEX_MASK_LIT, POLYTYPE_ATEX_TRANS, POLYTYPE_ATEX_LIT, Polygon
@subsection POLYTYPE_ATEX_MASK_LIT
@ftable @asis
@item @t{#define POLYTYPE_ATEX_MASK_LIT}
@end ftable
@ftable @asis
@item @t{#define POLYTYPE_PTEX_MASK_LIT}
Like POLYTYPE_ATEX_LIT and POLYTYPE_PTEX_LIT, but zero texture map pixels
are skipped, allowing parts of the texture map to be transparent.

@end ftable
See also:@*
@xref{Polygon, Polygon rendering}.@*
@xref{polygon3d}.@*
@xref{POLYTYPE_ATEX_LIT}.@*
@xref{POLYTYPE_ATEX_LIT, POLYTYPE_PTEX_LIT}.@*
@xref{ex3d}.@*
@node POLYTYPE_ATEX_TRANS, POLYTYPE_ATEX_MASK_TRANS, POLYTYPE_ATEX_MASK_LIT, Polygon
@subsection POLYTYPE_ATEX_TRANS
@ftable @asis
@item @t{#define POLYTYPE_ATEX_TRANS}
@end ftable
@ftable @asis
@item @t{#define POLYTYPE_PTEX_TRANS}
Render translucent textures. All the general rules for drawing
translucent things apply. However, these modes have a major
limitation: they only work with memory bitmaps or linear frame
buffers (not with banked frame buffers). Don't even try, they do not
check and your program will die horribly (or at least draw wrong
things).

@end ftable
See also:@*
@xref{Polygon, Polygon rendering}.@*
@xref{polygon3d}.@*
@xref{ex3d}.@*
@node POLYTYPE_ATEX_MASK_TRANS, polygon3d, POLYTYPE_ATEX_TRANS, Polygon
@subsection POLYTYPE_ATEX_MASK_TRANS
@ftable @asis
@item @t{#define POLYTYPE_ATEX_MASK_TRANS}
@end ftable
@ftable @asis
@item @t{#define POLYTYPE_PTEX_MASK_TRANS}
Like POLYTYPE_ATEX_TRANS and POLYTYPE_PTEX_TRANS, but zero texture map 
pixels are skipped.

@end ftable
See also:@*
@xref{Polygon, Polygon rendering}.@*
@xref{polygon3d}.@*
@xref{ex3d}.@*
@node polygon3d, triangle3d, POLYTYPE_ATEX_MASK_TRANS, Polygon
@subsection polygon3d
@ftable @asis
@item @t{void polygon3d(BITMAP *bmp, int type, BITMAP *texture, int vc, V3D *vtx[]);}
@end ftable
@ftable @asis
@item @t{void polygon3d_f(BITMAP *bmp, int type, BITMAP *texture, int vc, V3D_f *vtx[]);}
Draw 3d polygons onto the specified bitmap, using the specified rendering 
mode. Unlike the regular polygon() function, these routines don't support 
concave or self-intersecting shapes, and they can't draw onto mode-X 
screen bitmaps (if you want to write 3d code in mode-X, draw onto a 
memory bitmap and then blit to the screen). The width and height of the 
texture bitmap must be powers of two, but can be different, eg. a 64x16 
texture is fine, but a 17x3 one is not. The vertex count parameter (vc) 
should be followed by an array containing the appropriate number of 
pointers to vertex structures: polygon3d() uses the fixed point V3D 
structure, while polygon3d_f() uses the floating point V3D_f structure. 
These are defined as:
@example

typedef struct V3D
@{
   fixed x, y, z;       - position
   fixed u, v;          - texture map coordinates
   int c;               - color
@} V3D;

typedef struct V3D_f
@{
   float x, y, z;       - position
   float u, v;          - texture map coordinates
   int c;               - color
@} V3D_f;
@end example

How the vertex data is used depends on the rendering mode:

The `x' and `y' values specify the position of the vertex in 2d screen
coordinates.

The `z' value is only required when doing perspective correct texture
mapping, and specifies the depth of the point in 3d world coordinates.

The `u' and `v' coordinates are only required when doing texture mapping,
and specify a point on the texture plane to be mapped on to this vertex.
The texture plane is an infinite plane with the texture bitmap tiled
across it. Each vertex in the polygon has a corresponding vertex on the
texture plane, and the image of the resulting polygon in the texture plane
will be mapped on to the polygon on the screen.

We refer to pixels in the texture plane as texels. Each texel is a block, 
not just a point, and whole numbers for u and v refer to the top-left 
corner of a texel. This has a few implications. If you want to draw a 
rectangular polygon and map a texture sized 32x32 on to it, you would use 
the texture coordinates (0,0), (0,32), (32,32) and (32,0), assuming the 
vertices are specified in anticlockwise order. The texture will then be 
mapped perfectly on to the polygon. However, note that when we set u=32, 
the last column of texels seen on the screen is the one at u=31, and the 
same goes for v. This is because the coordinates refer to the top-left 
corner of the texels. In effect, texture coordinates at the right and 
bottom on the texture plane are exclusive.

There is another interesting point here. If you have two polygons side 
by side sharing two vertices (like the two parts of folded piece of 
cardboard), and you want to map a texture across them seamlessly, the 
values of u and v on the vertices at the join will be the same for both 
polygons. For example, if they are both rectangular, one polygon may use 
(0,0), (0,32), (32,32) and (32,0), and the other may use (32,0), (32,32), 
(64,32), (64,0). This would create a seamless join.

Of course you can specify fractional numbers for u and v to indicate a 
point part-way across a texel. In addition, since the texture plane is 
infinite, you can specify larger values than the size of the texture. 
This can be used to tile the texture several times across the polygon.

The `c' value specifies the vertex color, and is interpreted differently
by various rendering modes. Read the beginning of chapter "Polygon
rendering" for a list of rendering types you can use with this function.

@end ftable
See also:@*
@xref{triangle3d}.@*
@xref{quad3d}.@*
@xref{polygon}.@*
@xref{clip3d}.@*
@xref{cpu_capabilities}.@*
@xref{excamera}.@*
@xref{BITMAP}.@*
@xref{V3D}.@*
@xref{V3D_f}.@*
@node triangle3d, quad3d, polygon3d, Polygon
@subsection triangle3d
@ftable @asis
@item @t{void triangle3d(BITMAP *bmp, int type, BITMAP *tex, V3D *v1, *v2, *v3);}
@end ftable
@ftable @asis
@item @t{void triangle3d_f(BITMAP *bmp, int type, BITMAP *tex, V3D_f *v1, *v2, *v3);}
Draw 3d triangles, using either fixed or floating point vertex structures.
Unlike quad3d[_f](), triangle3d[_f]() functions are not wrappers of
polygon3d[_f](). The triangle3d[_f]() functions use their own routines
taking into account the constantness of the gradients. Therefore
triangle3d[_f](bmp, type, tex, v1, v2, v3) is faster than
polygon3d[_f](bmp, type, tex, 3, v[]).

Read the beginning of chapter "Polygon rendering" for a list of rendering
types you can use with this function.

@end ftable
See also:@*
@xref{polygon3d}.@*
@xref{quad3d}.@*
@xref{triangle}.@*
@xref{Polygon, Polygon rendering}.@*
@xref{BITMAP}.@*
@xref{V3D}.@*
@xref{V3D_f}.@*
@node quad3d, clip3d_f, triangle3d, Polygon
@subsection quad3d
@ftable @asis
@item @t{void quad3d(BITMAP *bmp, int type, BITMAP *tex, V3D *v1, *v2, *v3, *v4);}
@end ftable
@ftable @asis
@item @t{void quad3d_f(BITMAP *bmp, int type, BITMAP *tex, V3D_f *v1, *v2, *v3, *v4);}
Draw 3d quads, using either fixed or floating point vertex structures. 
These are equivalent to calling polygon3d(bmp, type, tex, 4, v[]) or
polygon3d_f(bmp, type, tex, 4, v[]).

Read the beginning of chapter "Polygon rendering" for a list of rendering
types you can use with this function.

@end ftable
See also:@*
@xref{polygon3d}.@*
@xref{triangle3d}.@*
@xref{Polygon, Polygon rendering}.@*
@xref{ex3d}.@*
@xref{BITMAP}.@*
@xref{V3D}.@*
@xref{V3D_f}.@*
@node clip3d_f, clip3d, quad3d, Polygon
@subsection clip3d_f
@ftable @asis
@item @t{int clip3d_f(int type, float min_z, float max_z, int vc, const V3D_f *vtx[], V3D_f *vout[], V3D_f *vtmp[], int out[]);}
Clips the polygon given in `vtx'. The number of vertices is `vc', the
result goes in `vout', and `vtmp' and `out' are needed for internal
purposes. The pointers in `vtx', `vout' and `vtmp' must point to valid
V3D_f structures.

As additional vertices may appear in the process of clipping, so the 
size of `vout', `vtmp' and `out' should be at least vc * (1.5 ^ n), where
`n' is the number of clipping planes (5 or 6), and `^' denotes "to the
power of".

The frustum (viewing volume) is defined by -z<x<z, -z<y<z,
0<min_z<z<max_z. If  max_z<=min_z, the z<max_z clipping is
not done. As you can see, clipping is done in the camera space, with
perspective in mind, so this routine should be called after you apply
the camera matrix, but before the perspective projection. The routine
will correctly interpolate u, v, and c in the vertex structure. However,
no provision is made for high/truecolor GCOL.

Returns the number of vertices after clipping is done.

@end ftable
See also:@*
@xref{polygon3d}.@*
@xref{clip3d}.@*
@xref{excamera}.@*
@xref{exscn3d}.@*
@xref{V3D_f}.@*
@node clip3d, Zbuffered rendering, clip3d_f, Polygon
@subsection clip3d
@ftable @asis
@item @t{int clip3d(int type, fixed min_z, fixed max_z, int vc, const V3D *vtx[], V3D *vout[], V3D *vtmp[], int out[]);}
Fixed point version of clip3d_f(). This function should be used with 
caution, due to the limited precision of fixed point arithmetic and high 
chance of rounding errors: the floating point code is better for most 
situations.

Returns the number of vertices after clipping is done.

@end ftable
See also:@*
@xref{polygon3d}.@*
@xref{clip3d_f}.@*
@xref{fixed}.@*
@xref{V3D}.@*
@node Zbuffered rendering, create_zbuffer, clip3d, Polygon
@subsection Zbuffered rendering
@ftable @asis
@end ftable
A Z-buffer stores the depth of each pixel that is drawn on a viewport.
When a 3D object is rendered, the depth of each of its pixels is compared
against the value stored into the Z-buffer: if the pixel is closer it is
drawn, otherwise it is skipped.

No polygon sorting is needed. However, backface culling should be done
because it prevents many invisible polygons being compared against the
Z-buffer. Z-buffered rendering is the only algorithm supported by Allegro
that directly solves penetrating shapes (see example exzbuf.c, for instance).
The price to pay is more complex (and slower) routines.

Z-buffered polygons are designed as an extension of the normal POLYTYPE_*
rendering styles. Just OR the POLYTYPE with the value POLYTYPE_ZBUF, and
the normal polygon3d(), polygon3d_f(), quad3d(), etc. functions will
render z-buffered polygons.

Example:
@example

polygon3d(bmp, POLYTYPE_ATEX | POLYTYPE_ZBUF, tex, vc, vtx);@end example


Of course, the z coordinates have to be valid regardless of rendering style.

A Z-buffered rendering procedure looks like a double-buffered rendering
procedure. You should follow four steps: create a Z-buffer at the beginning
of the program and make the library use it by calling set_zbuffer(). Then,
for each frame, clear the Z-buffer and draw polygons with
POLYTYPE_* | POLYTYPE_ZBUF and finally destroy the Z-buffer when leaving the
program.

Notes on Z-buffered renderers:

@itemize @bullet
@item 
Unlike the normal POLYTYPE_FLAT renderers, the Z-buffered ones don't use
the hline() routine. Therefore DRAW_MODE has no effect.
@item 
The *LIT* routines work the traditional way - through the set of
blender routines.
@item 
All the Z-buffered routines are much slower than their normal counterparts
(they all use the FPU to interpolate and test 1/z values).
@end itemize

@node create_zbuffer, create_sub_zbuffer, Zbuffered rendering, Polygon
@subsection create_zbuffer
@ftable @asis
@item @t{ZBUFFER *create_zbuffer(BITMAP *bmp);}
Creates a Z-buffer using the size of the BITMAP you are planning to draw
on. Several Z-buffers can be defined but only one can be used at the same
time, so you must call set_zbuffer() to make this Z-buffer active.

Returns the pointer to the ZBUFFER or NULL if there was an error. Remember
to destroy the ZBUFFER once you are done with it, to avoid having memory
leaks.

@end ftable
See also:@*
@xref{create_sub_zbuffer}.@*
@xref{set_zbuffer}.@*
@xref{clear_zbuffer}.@*
@xref{destroy_zbuffer}.@*
@xref{exzbuf}.@*
@xref{BITMAP}.@*
@xref{ZBUFFER}.@*
@node create_sub_zbuffer, set_zbuffer, create_zbuffer, Polygon
@subsection create_sub_zbuffer
@ftable @asis
@item @t{ZBUFFER *create_sub_zbuffer(ZBUFFER *parent, int x, int y, int width, int height);}
Creates a sub-z-buffer, ie. a z-buffer sharing drawing memory with a
pre-existing z-buffer, but possibly with a different size. The same rules
as for sub-bitmaps apply: the sub-z-buffer width and height can extend
beyond the right and bottom edges of the parent (they will be clipped), 
but the origin point must lie within the parent region.

When drawing z-buffered to a bitmap, the top left corner of the bitmap is
always mapped to the top left corner of the current z-buffer. So this
function is primarily useful if you want to draw to a sub-bitmap and use
the corresponding sub-area of the z-buffer. In other cases, eg. if you
just want to draw to a sub-bitmap of screen (and not to other parts of
screen), then you would usually want to create a normal z-buffer (not
sub-z-buffer) the size of the visible screen. You don't need to first
create a z-buffer the size of the virtual screen and then a sub-z-buffer
of that.

Returns the pointer to the sub ZBUFFER or NULL if there was an error.
Remember to destroy the ZBUFFER once you are done with it, to avoid having
memory leaks.

@end ftable
See also:@*
@xref{create_zbuffer}.@*
@xref{create_sub_bitmap}.@*
@xref{destroy_zbuffer}.@*
@xref{ZBUFFER}.@*
@node set_zbuffer, clear_zbuffer, create_sub_zbuffer, Polygon
@subsection set_zbuffer
@ftable @asis
@item @t{void set_zbuffer(ZBUFFER *zbuf);}
Makes the given Z-buffer be the active one. This should have been
previously created with create_zbuffer().

@end ftable
See also:@*
@xref{create_zbuffer}.@*
@xref{clear_zbuffer}.@*
@xref{destroy_zbuffer}.@*
@xref{exzbuf}.@*
@xref{ZBUFFER}.@*
@node clear_zbuffer, destroy_zbuffer, set_zbuffer, Polygon
@subsection clear_zbuffer
@ftable @asis
@item @t{void clear_zbuffer(ZBUFFER *zbuf, float z);}
Writes z into the given Z-buffer (0 means far away). This function should
be used to initialize the Z-buffer before each frame. Actually, low-level
routines compare depth of the current pixel with 1/z: for example, if you
want to clip polygons farther than 10, you must call
clear_zbuffer(zbuf, 0.1).

@end ftable
See also:@*
@xref{create_zbuffer}.@*
@xref{set_zbuffer}.@*
@xref{destroy_zbuffer}.@*
@xref{exzbuf}.@*
@xref{ZBUFFER}.@*
@node destroy_zbuffer, Scene rendering, clear_zbuffer, Polygon
@subsection destroy_zbuffer
@ftable @asis
@item @t{void destroy_zbuffer(ZBUFFER *zbuf);}
Destroys the Z-buffer when you are finished with it. Use this to avoid
memory leaks in your program.

@end ftable
See also:@*
@xref{create_zbuffer}.@*
@xref{set_zbuffer}.@*
@xref{clear_zbuffer}.@*
@xref{exzbuf}.@*
@xref{ZBUFFER}.@*
@node Scene rendering, create_scene, destroy_zbuffer, Polygon
@subsection Scene rendering
@ftable @asis
@end ftable
Allegro provides two simple approaches to remove hidden surfaces:

@itemize @bullet
@item 
Z-buffering - (see above)
@item 
Scan-line algorithms - along each scanline on your screen, you keep
track of what polygons you are "in" and which is the nearest. This
status changes only where the scanline crosses some polygon edge. So you
have to juggle an edge list and a polygon list. And you have to sort the
edges for each scanline (this can be countered by keeping the order of
the previous scanline - it won't change much). The BIG advantage is that
you write each pixel only once. If you have a lot of overlapping
polygons you can get incredible speeds compared to any of the previous
algorithms. This algorithm is covered by the *_scene routines.
@end itemize


The scene rendering has approximately the following steps:

@itemize @bullet
@item 
Initialize the scene (set the clip area, clear the bitmap, blit a
background, etc.)
@item 
Call clear_scene().
@item 
Transform all your points to camera space.
@item 
Clip polygons.
@item 
Project with persp_project() or persp_project_f().
@item 
"Draw" polygons with scene_polygon3d() and/or scene_polygon3d_f().
This doesn't do any actual drawing, only initializes tables.
@item 
Render all the polygons defined previously to the bitmap with
render_scene().
@item 
Overlay some non-3D graphics.
@item 
Show the bitmap (blit it to screen, flip the page, etc).
@end itemize


For each horizontal line in the viewport an x-sorted edge list is used to
keep track of what polygons are "in" and which is the nearest. Vertical
coherency is used - the edge list for a scanline is sorted starting from
the previous one - it won't change much. The scene rendering routines use
the same low-level asm routines as normal polygon3d().

Notes on scene rendering:

@itemize @bullet
@item 
Unlike polygon3d(), scene_polygon3d() requires valid z coordinates
for all vertices, regardless of rendering style (unlike
polygon3d(), which only uses z coordinate for *PTEX*).
@item 
All polygons passed to scene_polygon3d() have to be
persp_project()'ed.
@item 
After render_scene() the mode is reset to SOLID.
@end itemize

Using a lot of *MASK* polygons drastically reduces performance, because
when a MASKed polygon is the first in line of sight, the polygons
underneath have to be drawn too. The same applies to FLAT polygons drawn
with DRAW_MODE_TRANS.

Z-buffered rendering works also within the scene renderer. It may be
helpful when you have a few intersecting polygons, but most of the
polygons may be safely rendered by the normal scanline sorting algorithm.
Same as before: just OR the POLYTYPE with POLYTYPE_ZBUF. Also, you
have to clear the z-buffer at the start of the frame. Example:
@example

clear_scene(buffer);
if (some_polys_are_zbuf) clear_zbuffer(0.);
while (polygons) @{
   ...
   if (this_poly_is_zbuf) type |= POLYTYPE_ZBUF;
   scene_polygon3d(type, tex, vc, vtx);
@}
render_scene();@end example


@node create_scene, clear_scene, Scene rendering, Polygon
@subsection create_scene
@ftable @asis
@item @t{int create_scene(int nedge, int npoly);}
Allocates memory for a scene, `nedge' and `npoly' are your estimates of how
many edges and how many polygons you will render (you cannot get over the
limit specified here). If you use same values in successive calls, the
space will be reused (no new malloc()).

The memory allocated is a little less than 150 * (nedge + npoly) bytes.

Returns zero on success, or a negative number if allocations fail.

@end ftable
See also:@*
@xref{scene_polygon3d}.@*
@xref{render_scene}.@*
@xref{clear_scene}.@*
@xref{destroy_scene}.@*
@xref{scene_gap}.@*
@xref{create_zbuffer}.@*
@xref{exscn3d}.@*
@node clear_scene, destroy_scene, create_scene, Polygon
@subsection clear_scene
@ftable @asis
@item @t{void clear_scene(BITMAP *bmp);}
Initializes a scene. The bitmap is the bitmap you will eventually render
on.

@end ftable
See also:@*
@xref{create_scene}.@*
@xref{scene_polygon3d}.@*
@xref{render_scene}.@*
@xref{destroy_scene}.@*
@xref{scene_gap}.@*
@xref{exscn3d}.@*
@xref{BITMAP}.@*
@node destroy_scene, scene_polygon3d, clear_scene, Polygon
@subsection destroy_scene
@ftable @asis
@item @t{void destroy_scene();}
Deallocate memory previously allocated by create_scene. Use this to avoid
memory leaks in your program.

@end ftable
See also:@*
@xref{create_scene}.@*
@xref{scene_polygon3d}.@*
@xref{clear_scene}.@*
@xref{render_scene}.@*
@xref{scene_gap}.@*
@xref{exscn3d}.@*
@node scene_polygon3d, render_scene, destroy_scene, Polygon
@subsection scene_polygon3d
@ftable @asis
@item @t{int scene_polygon3d(int type, BITMAP *texture, int vc, V3D *vtx[]);}
@end ftable
@ftable @asis
@item @t{int scene_polygon3d_f(int type, BITMAP *texture, int vc, V3D_f *vtx[]);}
Puts a polygon in the rendering list. Nothing is really rendered at this
moment. Should be called between clear_scene() and render_scene().

Arguments are the same as for polygon3d(), except the bitmap is missing.
The one passed to clear_scene() will be used.

Unlike polygon3d(), the polygon may be concave or self-intersecting.
Shapes that penetrate one another may look OK, but they are not really
handled by this code.

Note that the texture is stored as a pointer only, and you should keep
the actual bitmap around until render_scene(), where it is used.

Since the FLAT style is implemented with the low-level hline() function,
the FLAT style is subject to DRAW_MODEs. All these modes are valid. Along
with the polygon, this mode will be stored for the rendering moment, and
also all the other related variables (color_map pointer, pattern pointer,
anchor, blender values).

The settings of the CPU_MMX and CPU_3DNOW flags of the cpu_capabilities 
global variable on entry in this routine affect the choice of low-level 
asm routine that will be used by render_scene() for this polygon.

Returns zero on success, or a negative number if it won't be rendered for
lack of a rendering routine.

@end ftable
See also:@*
@xref{create_scene}.@*
@xref{clear_scene}.@*
@xref{render_scene}.@*
@xref{destroy_scene}.@*
@xref{polygon3d}.@*
@xref{cpu_capabilities}.@*
@xref{exscn3d}.@*
@xref{BITMAP}.@*
@xref{V3D}.@*
@xref{V3D_f}.@*
@node render_scene, scene_gap, scene_polygon3d, Polygon
@subsection render_scene
@ftable @asis
@item @t{void render_scene();}
Renders all the specified scene_polygon3d()'s on the bitmap passed to
clear_scene(). Rendering is done one scanline at a time, with no pixel
being processed more than once.

Note that between clear_scene() and render_scene() you shouldn't change
the clip rectangle of the destination bitmap. For speed reasons, you
should set the clip rectangle to the minimum.

Note also that all the textures passed to scene_polygon3d() are stored as
pointers only and actually used in render_scene().

@end ftable
See also:@*
@xref{create_scene}.@*
@xref{clear_scene}.@*
@xref{destroy_scene}.@*
@xref{scene_gap}.@*
@xref{scene_polygon3d}.@*
@xref{exscn3d}.@*
@node scene_gap, drawing_mode, render_scene, Polygon
@subsection scene_gap
@ftable @asis
@item @t{extern float scene_gap;}
This number (default value = 100.0) controls the behaviour of the
z-sorting algorithm. When an edge is very close to another's polygon
plane, there is an interval of uncertainty in which you cannot tell which
object is visible (which z is smaller). This is due to cumulative
numerical errors for edges that have undergone a lot of transformations
and interpolations.

The default value means that if the 1/z values (in projected space)
differ by only 1/100 (one percent), they are considered to be equal and
the x-slopes of the planes are used to find out which plane is getting
closer when we move to the right.

Larger values means narrower margins, and increasing the chance of
missing true adjacent edges/planes. Smaller values means larger margins,
and increasing the chance of mistaking close polygons for adjacent ones.
The value of 100 is close to the optimum. However, the optimum shifts
slightly with resolution, and may be application-dependent. It is here 
for you to fine-tune.



@end ftable
See also:@*
@xref{create_scene}.@*
@xref{clear_scene}.@*
@xref{destroy_scene}.@*
@xref{render_scene}.@*
@xref{scene_polygon3d}.@*
@node Transparency, Converting, Polygon, API
@section Transparency and patterned drawing

@menu
* drawing_mode::
* xor_mode::
* solid_mode::
* 256-color transparency::
* color_map::
* create_trans_table::
* create_light_table::
* create_color_table::
* create_blender_table::
* Truecolor transparency::
* set_trans_blender::
* set_alpha_blender::
* set_write_alpha_blender::
* set_add_blender::
* set_burn_blender::
* set_color_blender::
* set_difference_blender::
* set_dissolve_blender::
* set_dodge_blender::
* set_hue_blender::
* set_invert_blender::
* set_luminance_blender::
* set_multiply_blender::
* set_saturation_blender::
* set_screen_blender::
* set_blender_mode::
* set_blender_mode_ex::
@end menu
@node drawing_mode, xor_mode, scene_gap, Transparency
@subsection drawing_mode
@ftable @asis
@item @t{void drawing_mode(int mode, BITMAP *pattern, int x_anchor, int y_anchor);}
Sets the graphics drawing mode. This only affects the geometric routines 
like putpixel, lines, rectangles, circles, polygons, floodfill, etc, not 
the text output, blitting, or sprite drawing functions. The mode should 
be one of the following constants:
@example

DRAW_MODE_SOLID               - the default, solid color
                                drawing
DRAW_MODE_XOR                 - exclusive-or drawing
DRAW_MODE_COPY_PATTERN        - multicolored pattern fill
DRAW_MODE_SOLID_PATTERN       - single color pattern fill
DRAW_MODE_MASKED_PATTERN      - masked pattern fill
DRAW_MODE_TRANS               - translucent color blending
@end example

In DRAW_MODE_SOLID, pixels of the bitmap being drawn onto are simply 
replaced by those produced by the drawing function.

In DRAW_MODE_XOR, pixels are written to the bitmap with an exclusive-or 
operation rather than a simple copy, so drawing the same shape twice will 
erase it. Because it involves reading as well as writing the bitmap 
memory, xor drawing is a lot slower than the normal replace mode.

With the patterned modes, you provide a pattern bitmap which is tiled 
across the surface of the shape. Allegro stores a pointer to this bitmap 
rather than copying it, so you must not destroy the bitmap while it is 
still selected as the pattern. The width and height of the pattern must 
be powers of two, but they can be different, eg. a 64x16 pattern is fine, 
but a 17x3 one is not. The pattern is tiled in a grid starting at point 
(x_anchor, y_anchor). Normally you should just pass zero for these 
values, which lets you draw several adjacent shapes and have the patterns 
meet up exactly along the shared edges. Zero alignment may look peculiar 
if you are moving a patterned shape around the screen, however, because 
the shape will move but the pattern alignment will not, so in some 
situations you may wish to alter the anchor position.

When you select DRAW_MODE_COPY_PATTERN, pixels are simply copied from the 
pattern bitmap onto the destination bitmap. This allows the use of 
multicolored patterns, and means that the color you pass to the drawing 
routine is ignored. This is the fastest of the patterned modes.

In DRAW_MODE_SOLID_PATTERN, each pixel in the pattern bitmap is compared 
with the mask color, which is zero in 256-color modes or bright pink for 
truecolor data (maximum red and blue, zero green). If the pattern pixel 
is solid, a pixel of the color you passed to the drawing routine is 
written to the destination bitmap, otherwise a zero is written. The 
pattern is thus treated as a monochrome bitmask, which lets you use the 
same pattern to draw different shapes in different colors, but prevents 
the use of multicolored patterns.

DRAW_MODE_MASKED_PATTERN is almost the same as DRAW_MODE_SOLID_PATTERN, 
but the masked pixels are skipped rather than being written as zeros, so 
the background shows through the gaps.

In DRAW_MODE_TRANS, the global color_map table or truecolor blender 
functions are used to overlay pixels on top of the existing image. This 
must only be used after you have set up the color mapping table (for 256 
color modes) or blender functions (for truecolor modes). Because it 
involves reading as well as writing the bitmap memory, translucent 
drawing is very slow if you draw directly to video RAM, so wherever 
possible you should use a memory bitmap instead.

@end ftable
See also:@*
@xref{xor_mode}.@*
@xref{solid_mode}.@*
@xref{color_map}.@*
@xref{set_trans_blender}.@*
@xref{exalpha}.@*
@xref{excolmap}.@*
@xref{exjoy}.@*
@xref{expat}.@*
@xref{extrans}.@*
@xref{BITMAP}.@*
@node xor_mode, solid_mode, drawing_mode, Transparency
@subsection xor_mode
@ftable @asis
@item @t{void xor_mode(int on);}
This is a shortcut for toggling xor drawing mode on and off. Calling 
xor_mode(TRUE) is equivalent to drawing_mode(DRAW_MODE_XOR, NULL, 0, 0).
Calling xor_mode(FALSE) is equivalent to
drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0).

@end ftable
See also:@*
@xref{drawing_mode}.@*
@xref{exspline}.@*
@xref{exupdate}.@*
@node solid_mode, 256-color transparency, xor_mode, Transparency
@subsection solid_mode
@ftable @asis
@item @t{void solid_mode();}
This is a shortcut for selecting solid drawing mode. It is equivalent to 
calling drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0).

@end ftable
See also:@*
@xref{drawing_mode}.@*
@xref{exalpha}.@*
@xref{expat}.@*
@node 256-color transparency, color_map, solid_mode, Transparency
@subsection 256-color transparency
@ftable @asis
@end ftable
In paletted video modes, translucency and lighting are implemented with a 
64k lookup table, which contains the result of combining any two colors c1 
and c2. You must set up this table before you use any of the translucency 
or lighting routines. Depending on how you construct the table, a range of 
different effects are possible. For example, translucency can be implemented 
by using a color halfway between c1 and c2 as the result of the combination. 
Lighting is achieved by treating one of the colors as a light level (0-255) 
rather than a color, and setting up the table appropriately. A range of 
specialised effects are possible, for instance replacing any color with any 
other color and making individual source or destination colors completely 
solid or invisible. Color mapping tables can be precalculated with the
colormap utility, or generated at runtime. Read chapter "Structures and types
defined by Allegro" for an internal description of the COLOR_MAP structure.

@node color_map, create_trans_table, 256-color transparency, Transparency
@subsection color_map
@ftable @asis
@item @t{extern COLOR_MAP *color_map;}
Global pointer to the color mapping table. You must allocate your own
COLOR_MAP either statically or dynamically and set color_map to it 
before using any translucent or lit drawing functions in a 256-color 
video mode! Example:
@example

color_map = malloc(sizeof(COLOR_MAP));
if (!color_map)
   abort_on_error("Not enough memory for color map!");@end example


@end ftable
See also:@*
@xref{create_color_table}.@*
@xref{create_light_table}.@*
@xref{create_trans_table}.@*
@xref{create_blender_table}.@*
@xref{set_trans_blender}.@*
@xref{draw_trans_sprite}.@*
@xref{draw_lit_sprite}.@*
@xref{draw_gouraud_sprite}.@*
@xref{drawing_mode}.@*
@xref{ex3d}.@*
@xref{excolmap}.@*
@xref{exlights}.@*
@xref{exshade}.@*
@xref{extrans}.@*
@xref{COLOR_MAP}.@*
@node create_trans_table, create_light_table, color_map, Transparency
@subsection create_trans_table
@ftable @asis
@item @t{void create_trans_table(COLOR_MAP *table, const PALETTE pal, int r, g, b, void (*callback)(int pos));}
Fills the specified color mapping table with lookup data for doing 
translucency effects with the specified palette. When combining the 
colors c1 and c2 with this table, the result will be a color somewhere 
between the two. The r, g, and b parameters specify the solidity of each 
color component, ranging from 0 (totally transparent) to 255 (totally 
solid). For 50% solidity, pass 128.

This function treats source color #0 as a special case, leaving the
destination unchanged whenever a zero source pixel is encountered, so that
masked sprites will draw correctly. This function will take advantage of
the global rgb_map variable to speed up color conversions. If the callback
function is not NULL, it will be called 256 times during the calculation,
allowing you to display a progress indicator. Example:
@example

COLOR_MAP trans_table;
...
/* Build a color lookup table for translucent drawing. */
create_trans_table(&trans_table, pal, 128, 128, 128, NULL);@end example


@end ftable
See also:@*
@xref{color_map}.@*
@xref{create_light_table}.@*
@xref{create_color_table}.@*
@xref{create_blender_table}.@*
@xref{draw_trans_sprite}.@*
@xref{draw_lit_sprite}.@*
@xref{draw_gouraud_sprite}.@*
@xref{rgb_map}.@*
@xref{ex3d}.@*
@xref{extrans}.@*
@xref{PALETTE}.@*
@xref{COLOR_MAP}.@*
@node create_light_table, create_color_table, create_trans_table, Transparency
@subsection create_light_table
@ftable @asis
@item @t{void create_light_table(COLOR_MAP *table, const PALETTE pal, int r, g, b, void (*callback)(int pos));}
Fills the specified color mapping table with lookup data for doing 
lighting effects with the specified palette. When combining the colors c1 
and c2 with this table, c1 is treated as a light level from 0-255. At 
light level 255 the table will output color c2 unchanged, at light level 
0 it will output the r, g, b value you specify to this function, and at 
intermediate light levels it will output a color somewhere between the 
two extremes. The r, g, and b values are in the range 0-63.

This function will take advantage of the global rgb_ap variable to speed
up color conversions. If the callback function is not NULL, it will be
called 256 times during the calculation, allowing you to display a
progress indicator. Example:
@example

COLOR_MAP light_table;
...
/* Build a color lookup table for lighting effects. */
create_light_table(&light_table, pal, 0, 0, 0, NULL);@end example


@end ftable
See also:@*
@xref{color_map}.@*
@xref{create_trans_table}.@*
@xref{create_color_table}.@*
@xref{create_blender_table}.@*
@xref{draw_trans_sprite}.@*
@xref{draw_lit_sprite}.@*
@xref{draw_gouraud_sprite}.@*
@xref{rgb_map}.@*
@xref{ex3d}.@*
@xref{exshade}.@*
@xref{extrans}.@*
@xref{PALETTE}.@*
@xref{COLOR_MAP}.@*
@node create_color_table, create_blender_table, create_light_table, Transparency
@subsection create_color_table
@ftable @asis
@item @t{void create_color_table(COLOR_MAP *table, const PALETTE pal, void (*blend)(PALETTE pal, int x, int y, RGB *rgb), void (*callback)(int pos));}
Fills the specified color mapping table with lookup data for doing 
customised effects with the specified palette, calling the blend function 
to determine the results of each color combination.

Your blend routine will be passed a pointer to the palette and the two
indices of the colors which are to be combined, and should fill in the RGB
structure with the desired result in 0-63 format. Allegro will then search
the palette for the closest match to the RGB color that you requested, so
it doesn't matter if the palette has no exact match for this color.

If the callback function is not NULL, it will be called 256 times during
the calculation, allowing you to display a progress indicator. Example:
@example

COLOR_MAP greyscale_table;
...
void return_grey_color(const PALETTE pal,
                       int x, int y, RGB *rgb)
@{
   ...
@}
...
   /* Build a color lookup table for greyscale effect. */
   create_color_table(&greyscale_table, pal,
                      return_grey_color, NULL);@end example


@end ftable
See also:@*
@xref{color_map}.@*
@xref{create_light_table}.@*
@xref{create_trans_table}.@*
@xref{create_blender_table}.@*
@xref{draw_trans_sprite}.@*
@xref{draw_lit_sprite}.@*
@xref{draw_gouraud_sprite}.@*
@xref{rgb_map}.@*
@xref{excolmap}.@*
@xref{PALETTE}.@*
@xref{RGB}.@*
@xref{COLOR_MAP}.@*
@node create_blender_table, Truecolor transparency, create_color_table, Transparency
@subsection create_blender_table
@ftable @asis
@item @t{void create_blender_table(COLOR_MAP *table, const PALETTE pal, void (*callback)(int pos));}
Fills the specified color mapping table with lookup data for doing a 
paletted equivalent of whatever truecolor blender mode is currently 
selected. After calling set_trans_blender(), set_blender_mode(), or any 
of the other truecolor blender mode routines, you can use this function 
to create an 8-bit mapping table that will have the same results as 
whatever 24-bit blending mode you have enabled.

@end ftable
See also:@*
@xref{color_map}.@*
@xref{create_light_table}.@*
@xref{create_trans_table}.@*
@xref{create_color_table}.@*
@xref{draw_trans_sprite}.@*
@xref{draw_lit_sprite}.@*
@xref{draw_gouraud_sprite}.@*
@xref{set_trans_blender}.@*
@xref{set_blender_mode}.@*
@xref{PALETTE}.@*
@xref{COLOR_MAP}.@*
@node Truecolor transparency, set_trans_blender, create_blender_table, Transparency
@subsection Truecolor transparency
@ftable @asis
@end ftable
In truecolor video modes, translucency and lighting are implemented by a 
blender function of the form:
@example

unsigned long (*BLENDER_FUNC)(unsigned long x, y, n);@end example


For each pixel to be drawn, this routine is passed two color parameters x 
and y, decomposes them into their red, green and blue components, combines 
them according to some mathematical transformation involving the 
interpolation factor n, and then merges the result back into a single 
return color value, which will be used to draw the pixel onto 
the destination bitmap.

The parameter x represents the blending modifier color and the parameter y 
represents the base color to be modified. The interpolation factor n is in 
the range [0-255] and controls the solidity of the blending.

When a translucent drawing function is used, x is the color of the source, 
y is the color of the bitmap being drawn onto and n is the alpha level   
that was passed to the function that sets the blending mode (the RGB triplet 
that was passed to this function is not taken into account).

When a lit sprite drawing function is used, x is the color represented by 
the RGB triplet that was passed to the function that sets the blending mode 
(the alpha level that was passed to this function is not taken into 
account), y is the color of the sprite and n is the alpha level that was 
passed to the drawing function itself.

Since these routines may be used from various different color depths, there 
are three such callbacks, one for use with 15-bit 5.5.5 pixels, one for 16 
bit 5.6.5 pixels, and one for 24-bit 8.8.8 pixels (this can be shared 
between the 24 and 32-bit code since the bit packing is the same).

@node set_trans_blender, set_alpha_blender, Truecolor transparency, Transparency
@subsection set_trans_blender
@ftable @asis
@item @t{void set_trans_blender(int r, int g, int b, int a);}
Enables a linear interpolator blender mode for combining translucent 
or lit truecolor pixels.

@end ftable
See also:@*
@xref{set_blender_mode}.@*
@xref{set_alpha_blender}.@*
@xref{set_write_alpha_blender}.@*
@xref{color_map}.@*
@xref{draw_trans_sprite}.@*
@xref{draw_lit_sprite}.@*
@xref{drawing_mode}.@*
@xref{set_add_blender}.@*
@xref{set_burn_blender}.@*
@xref{set_color_blender}.@*
@xref{set_difference_blender}.@*
@xref{set_dissolve_blender}.@*
@xref{set_dodge_blender}.@*
@xref{set_hue_blender}.@*
@xref{set_invert_blender}.@*
@xref{set_luminance_blender}.@*
@xref{set_multiply_blender}.@*
@xref{set_saturation_blender}.@*
@xref{set_screen_blender}.@*
@xref{ex3d}.@*
@xref{exblend}.@*
@xref{exshade}.@*
@xref{extrans}.@*
@xref{exxfade}.@*
@node set_alpha_blender, set_write_alpha_blender, set_trans_blender, Transparency
@subsection set_alpha_blender
@ftable @asis
@item @t{void set_alpha_blender();}
Enables the special alpha-channel blending mode, which is used for 
drawing 32-bit RGBA sprites. After calling this function, you can use 
draw_trans_sprite() or draw_trans_rle_sprite() to draw a 32-bit source 
image onto any hicolor or truecolor destination. The alpha values will be 
taken directly from the source graphic, so you can vary the solidity of 
each part of the image. You can't use any of the normal translucency 
functions while this mode is active, though, so you should reset to one 
of the normal blender modes (eg. set_trans_blender()) before drawing 
anything other than 32-bit RGBA sprites.

@end ftable
See also:@*
@xref{set_trans_blender}.@*
@xref{draw_trans_sprite}.@*
@xref{draw_trans_rle_sprite}.@*
@xref{set_write_alpha_blender}.@*
@xref{exalpha}.@*
@xref{extrans}.@*
@node set_write_alpha_blender, set_add_blender, set_alpha_blender, Transparency
@subsection set_write_alpha_blender
@ftable @asis
@item @t{void set_write_alpha_blender();}
Enables the special alpha-channel editing mode, which is used for drawing 
alpha channels over the top of an existing 32-bit RGB sprite, to turn it 
into an RGBA format image. After calling this function, you can set the 
drawing mode to DRAW_MODE_TRANS and then write draw color values (0-255) 
onto a 32-bit image. This will leave the color values unchanged, but 
alter the alpha to whatever values you are writing. After enabling this 
mode you can also use draw_trans_sprite() to superimpose an 8-bit alpha 
mask over the top of an existing 32-bit sprite.

@end ftable
See also:@*
@xref{set_alpha_blender}.@*
@xref{draw_trans_sprite}.@*
@xref{drawing_mode}.@*
@xref{exalpha}.@*
@xref{extrans}.@*
@node set_add_blender, set_burn_blender, set_write_alpha_blender, Transparency
@subsection set_add_blender
@ftable @asis
@item @t{void set_add_blender(int r, int g, int b, int a);}
Enables an additive blender mode for combining translucent or lit 
truecolor pixels.

@end ftable
See also:@*
@xref{set_trans_blender}.@*
@xref{drawing_mode}.@*
@node set_burn_blender, set_color_blender, set_add_blender, Transparency
@subsection set_burn_blender
@ftable @asis
@item @t{void set_burn_blender(int r, int g, int b, int a);}
Enables a burn blender mode for combining translucent or lit truecolor 
pixels. Here the lightness values of the colours of the source image 
reduce the lightness of the destination image, darkening the image.

@end ftable
See also:@*
@xref{set_trans_blender}.@*
@xref{drawing_mode}.@*
@node set_color_blender, set_difference_blender, set_burn_blender, Transparency
@subsection set_color_blender
@ftable @asis
@item @t{void set_color_blender(int r, int g, int b, int a);}
Enables a color blender mode for combining translucent or lit truecolor 
pixels. Applies only the hue and saturation of the source image to the 
destination image. The luminance of the destination image is not affected.

@end ftable
See also:@*
@xref{set_trans_blender}.@*
@xref{drawing_mode}.@*
@node set_difference_blender, set_dissolve_blender, set_color_blender, Transparency
@subsection set_difference_blender
@ftable @asis
@item @t{void set_difference_blender(int r, int g, int b, int a);}
Enables a difference blender mode for combining translucent or lit 
truecolor pixels. This makes an image which has colours calculated by the 
difference between the source and destination colours.

@end ftable
See also:@*
@xref{set_trans_blender}.@*
@xref{drawing_mode}.@*
@node set_dissolve_blender, set_dodge_blender, set_difference_blender, Transparency
@subsection set_dissolve_blender
@ftable @asis
@item @t{void set_dissolve_blender(int r, int g, int b, int a);}
Enables a dissolve blender mode for combining translucent or lit 
truecolor pixels. Randomly replaces the colours of some pixels in the 
destination image with those of the source image. The number of pixels 
replaced depends on the alpha value (higher value, more pixels replaced; 
you get the idea :).

@end ftable
See also:@*
@xref{set_trans_blender}.@*
@xref{drawing_mode}.@*
@node set_dodge_blender, set_hue_blender, set_dissolve_blender, Transparency
@subsection set_dodge_blender
@ftable @asis
@item @t{void set_dodge_blender(int r, int g, int b, int a);}
Enables a dodge blender mode for combining translucent or lit truecolor 
pixels. The lightness of colours in the source lighten the colours of the 
destination. White has the most effect; black has none.

@end ftable
See also:@*
@xref{set_trans_blender}.@*
@xref{drawing_mode}.@*
@node set_hue_blender, set_invert_blender, set_dodge_blender, Transparency
@subsection set_hue_blender
@ftable @asis
@item @t{void set_hue_blender(int r, int g, int b, int a);}
Enables a hue blender mode for combining translucent or lit truecolor 
pixels. This applies the hue of the source to the destination.

@end ftable
See also:@*
@xref{set_trans_blender}.@*
@xref{drawing_mode}.@*
@node set_invert_blender, set_luminance_blender, set_hue_blender, Transparency
@subsection set_invert_blender
@ftable @asis
@item @t{void set_invert_blender(int r, int g, int b, int a);}
Enables an invert blender mode for combining translucent or lit truecolor 
pixels. Blends the inverse (or negative) colour of the source with the 
destination.

@end ftable
See also:@*
@xref{set_trans_blender}.@*
@xref{drawing_mode}.@*
@node set_luminance_blender, set_multiply_blender, set_invert_blender, Transparency
@subsection set_luminance_blender
@ftable @asis
@item @t{void set_luminance_blender(int r, int g, int b, int a);}
Enables a luminance blender mode for combining translucent or lit 
truecolor pixels. Applies the luminance of the source to the destination.
The colour of the destination is not affected.

@end ftable
See also:@*
@xref{set_trans_blender}.@*
@xref{drawing_mode}.@*
@node set_multiply_blender, set_saturation_blender, set_luminance_blender, Transparency
@subsection set_multiply_blender
@ftable @asis
@item @t{void set_multiply_blender(int r, int g, int b, int a);}
Enables a multiply blender mode for combining translucent or lit 
truecolor pixels. Combines the source and destination images, multiplying 
the colours to produce a darker colour. If a colour is multiplied by 
white it remains unchanged; when multiplied by black it also becomes 
black.

@end ftable
See also:@*
@xref{set_trans_blender}.@*
@xref{drawing_mode}.@*
@xref{exalpha}.@*
@node set_saturation_blender, set_screen_blender, set_multiply_blender, Transparency
@subsection set_saturation_blender
@ftable @asis
@item @t{void set_saturation_blender(int r, int g, int b, int a);}
Enables a saturation blender mode for combining translucent or lit 
truecolor pixels. Applies the saturation of the source to the destination 
image.

@end ftable
See also:@*
@xref{set_trans_blender}.@*
@xref{drawing_mode}.@*
@node set_screen_blender, set_blender_mode, set_saturation_blender, Transparency
@subsection set_screen_blender
@ftable @asis
@item @t{void set_screen_blender(int r, int g, int b, int a);}
Enables a screen blender mode for combining translucent or lit truecolor 
pixels. This blender mode lightens the colour of the destination image by 
multiplying the inverse of the source and destination colours. Sort of 
like the opposite of the multiply blender mode.

@end ftable
See also:@*
@xref{set_trans_blender}.@*
@xref{drawing_mode}.@*
@node set_blender_mode, set_blender_mode_ex, set_screen_blender, Transparency
@subsection set_blender_mode
@ftable @asis
@item @t{void set_blender_mode(BLENDER_FUNC b15, b16, b24, int r, g, b, a);}
Specifies a custom set of truecolor blender routines, which can be used 
to implement whatever special interpolation modes you need. This function 
shares a single blender between the 24 and 32-bit modes.

@end ftable
See also:@*
@xref{set_blender_mode_ex}.@*
@xref{set_trans_blender}.@*
@xref{color_map}.@*
@xref{draw_trans_sprite}.@*
@xref{draw_lit_sprite}.@*
@xref{drawing_mode}.@*
@node set_blender_mode_ex, bestfit_color, set_blender_mode, Transparency
@subsection set_blender_mode_ex
@ftable @asis
@item @t{void set_blender_mode_ex(BLENDER_FUNC b15, b16, b24, b32, b15x, b16x, b24x, int r, g, b, a);}
Like set_blender_mode(), but allows you to specify a more complete set of 
blender routines. The b15, b16, b24, and b32 routines are used when 
drawing pixels onto destinations of the same format, while b15x, b16x, 
and b24x are used by draw_trans_sprite() and draw_trans_rle_sprite() when 
drawing RGBA images onto destination bitmaps of another format. These 
blenders will be passed a 32-bit x parameter, along with a y value of a 
different color depth, and must try to do something sensible in response.



@end ftable
See also:@*
@xref{set_blender_mode}.@*
@xref{set_alpha_blender}.@*
@node Converting, Direct, Transparency, API
@section Converting between color formats

In general, Allegro is designed to be used in only one color depth at a 
time, so you will call set_color_depth() once and then store all your 
bitmaps in the same format. If you want to mix several different pixel 
formats, you can use create_bitmap_ex() in place of create_bitmap(), and 
call bitmap_color_depth() to query the format of a specific image. Most of 
the graphics routines require all their input parameters to be in the same 
format (eg. you cannot stretch a 15-bit source bitmap onto a 24-bit 
destination), but there are some exceptions:

@itemize @bullet
@item 
blit() and the rotation routines can copy between bitmaps of any format,
converting the data as required.
@item 
draw_sprite() can draw 256-color source images onto destinations of any
format.
@item 
draw_character_ex() _always_ uses a 256-color source bitmap, whatever the
format of the destination.
@item 
The draw_trans_sprite() and draw_trans_rle_sprite() functions are able to
draw 32-bit RGBA images onto any hicolor or truecolor destination, as long
as you call set_alpha_blender() first.
@item 
The draw_trans_sprite() function is able to draw an 8-bit alpha channel
image over the top of an existing 32-bit image, as long as you call
set_write_alpha_blender() first.
@end itemize

Expanding a 256-color source onto a truecolor destination is fairly fast 
(obviously you must set the correct palette before doing this conversion!). 
Converting between different truecolor formats is slightly slower, and 
reducing truecolor images to a 256-color destination is very slow (it can be 
sped up significantly if you set up the global rgb_map table before doing 
the conversion).

@menu
* bestfit_color::
* rgb_map::
* create_rgb_table::
* hsv_to_rgb::
@end menu
@node bestfit_color, rgb_map, set_blender_mode_ex, Converting
@subsection bestfit_color
@ftable @asis
@item @t{int bestfit_color(const PALETTE pal, int r, int g, int b);}
Searches the specified palette for the closest match to the requested 
color, which are specified in the VGA hardware 0-63 format. Normally you 
should call makecol8() instead, but this lower level function may be 
useful if you need to use a palette other than the currently selected 
one, or specifically don't want to use the rgb_map lookup table.

Returns the index of the palette for the closest match to the requested
color.

@end ftable
See also:@*
@xref{makecol8}.@*
@xref{PALETTE}.@*
@node rgb_map, create_rgb_table, bestfit_color, Converting
@subsection rgb_map
@ftable @asis
@item @t{extern RGB_MAP *rgb_map;}
To speed up reducing RGB values to 8-bit paletted colors, Allegro uses a 
32k lookup table (5 bits for each color component). You must set up this 
table before using the gouraud shading routines, and if present the table 
will also vastly accelerate the makecol8() and some create_*_table()
functions. RGB tables can be precalculated with the rgbmap utility, or
generated at runtime with create_rgb_table().

@end ftable
See also:@*
@xref{create_rgb_table}.@*
@xref{makecol8}.@*
@xref{create_trans_table}.@*
@xref{create_light_table}.@*
@xref{create_color_table}.@*
@xref{ex3d}.@*
@xref{excolmap}.@*
@xref{exrgbhsv}.@*
@xref{exshade}.@*
@xref{extrans}.@*
@xref{RGB_MAP}.@*
@node create_rgb_table, hsv_to_rgb, rgb_map, Converting
@subsection create_rgb_table
@ftable @asis
@item @t{void create_rgb_table(RGB_MAP *table, const PALETTE pal, void (*callback)(int pos));}
Fills the specified RGB mapping table with lookup data for the specified 
palette. If the callback function is not NULL, it will be called 256 
times during the calculation, allowing you to display a progress 
indicator. Example:
@example

RGB_MAP rgb_table;

create_rgb_table(&rgb_table, palette, NULL);
rgb_map = &rgb_table;@end example


@end ftable
See also:@*
@xref{rgb_map}.@*
@xref{ex3d}.@*
@xref{excolmap}.@*
@xref{exrgbhsv}.@*
@xref{exshade}.@*
@xref{extrans}.@*
@xref{PALETTE}.@*
@xref{RGB_MAP}.@*
@node hsv_to_rgb, bmp_write_line, create_rgb_table, Converting
@subsection hsv_to_rgb
@ftable @asis
@item @t{void hsv_to_rgb(float h, float s, float v, int *r, int *g, int *b);}
@end ftable
@ftable @asis
@item @t{void rgb_to_hsv(int r, int g, int b, float *h, float *s, float *v);}
Convert color values between the HSV and RGB color spaces. The RGB values 
range from 0 to 255, hue is from 0 to 360, and saturation and value are 
from 0 to 1. Example:
@example

int r, g, b;
float hue, saturation, value;
...
/* Convert a reddish color to HSV format. */
rgb_to_hsv(255, 0, 128, &hue, &saturation, &value);

/* Now put our tin foil hat, and verify that. */
hsv_to_rgb(hue, saturation, value, &r, &g, &b);
ASSERT(r == 255);
ASSERT(g == 0);
ASSERT(b == 128);@end example




@end ftable
See also:@*
@xref{exlights}.@*
@xref{exrgbhsv}.@*
@node Direct, FLIC, Converting, API
@section Direct access to video memory

Read chapter "Structures and types defined by Allegro" for an internal
description of the BITMAP structure. There are several ways to get direct
access to the image memory of a bitmap, varying in complexity depending on
what sort of bitmap you are using.

The simplest approach will only work with memory bitmaps (obtained from 
create_bitmap(), grabber datafiles, and image files) and sub-bitmaps of 
memory bitmaps. This uses a table of char pointers, called `line', which is
a part of the bitmap structure and contains pointers to the start of each 
line of the image. For example, a simple memory bitmap putpixel function is:
@example

void memory_putpixel(BITMAP *bmp, int x, int y, int color)
@{
   bmp->line[y][x] = color;
@}
@end example

For truecolor modes you need to cast the line pointer to the appropriate
type, for example:
@example

void memory_putpixel_15_or_16_bpp(BITMAP *bmp, int x, int y, int color)
@{
   ((short *)bmp->line[y])[x] = color;
@}

void memory_putpixel_32(BITMAP *bmp, int x, int y, int color)
@{
   ((long *)bmp->line[y])[x] = color;
@}
@end example

If you want to write to the screen as well as to memory bitmaps, you need to
use some helper macros, because the video memory may not be part of your 
normal address space. This simple routine will work for any linear screen, 
eg. a VESA linear framebuffers:
@example

void linear_screen_putpixel(BITMAP *bmp, int x, int y, int color)
@{
   bmp_select(bmp);
   bmp_write8((unsigned long)bmp->line[y]+x, color);
@}
@end example

For truecolor modes you should replace the bmp_write8() with bmp_write16(), 
bmp_write24(), or bmp_write32(), and multiply the x offset by the number of 
bytes per pixel. There are of course similar functions to read a pixel value
from a bitmap, namely bmp_read8(), bmp_read16(), bmp_read24() and
bmp_read32().

This still won't work in banked SVGA modes, however, or on platforms like 
Windows that do special processing inside the bank switching functions. For 
more flexible access to bitmap memory, you need to call the following
routines. They are implemented as inline assembler routines, so they are not
as inefficient as they might seem. If the bitmap doesn't require bank
switching (ie. it is a memory bitmap, mode 13h screen, etc), these functions
just return bmp->line[line].

@menu
* bmp_write_line::
* bmp_read_line::
* bmp_unwrite_line::
* More on banked direct memory access::
@end menu
@node bmp_write_line, bmp_read_line, hsv_to_rgb, Direct
@subsection bmp_write_line
@ftable @asis
@item @t{unsigned long bmp_write_line(BITMAP *bmp, int line);}
Selects the line of a bitmap that you are going to draw onto.

Returns the address of the selected line for writing.

@end ftable
See also:@*
@xref{exflame}.@*
@xref{exlights}.@*
@xref{BITMAP}.@*
@node bmp_read_line, bmp_unwrite_line, bmp_write_line, Direct
@subsection bmp_read_line
@ftable @asis
@item @t{unsigned long bmp_read_line(BITMAP *bmp, int line);}
Selects the line of a bitmap that you are going to read from.

Returns the address of the selected line for reading.

@end ftable
See also:@*
@xref{exflame}.@*
@xref{BITMAP}.@*
@node bmp_unwrite_line, More on banked direct memory access, bmp_read_line, Direct
@subsection bmp_unwrite_line
@ftable @asis
@item @t{void bmp_unwrite_line(BITMAP *bmp);}
Releases the bitmap memory after you are finished with it. You only need 
to call this once at the end of a drawing operation, even if you have 
called bmp_write_line() or bmp_read_line() several times before it.

@end ftable
See also:@*
@xref{exflame}.@*
@xref{exlights}.@*
@xref{BITMAP}.@*
@node More on banked direct memory access, play_fli, bmp_unwrite_line, Direct
@subsection More on banked direct memory access
@ftable @asis

@end ftable
Although SVGA bitmaps are banked, Allegro provides linear access to the 
memory within each scanline, so you only need to pass a y coordinate to 
these functions. Various x positions can be obtained by simply adding the x 
coordinate to the returned address. The return value is an unsigned long 
rather than a char pointer because the bitmap memory may not be in your data 
segment, and you need to access it with far pointers. For example, a 
putpixel using the bank switching functions is:
@example

void banked_putpixel(BITMAP *bmp, int x, int y, int color)
@{
   unsigned long address = bmp_write_line(bmp, y);
   bmp_select(bmp);
   bmp_write8(address+x, color);
   bmp_unwrite_line(bmp);
@}
@end example

You will notice that Allegro provides separate functions for setting the 
read and write banks. It is important that you distinguish between these, 
because on some graphics cards the banks can be set individually, and on 
others the video memory is read and written at different addresses. Life is 
never quite as simple as we might wish it to be, though (this is true even 
when we _aren't_ talking about graphics coding :-) and so of course some 
cards only provide a single bank. On these the read and write bank functions 
will behave identically, so you shouldn't assume that you can read from one 
part of video memory and write to another at the same time. You can call 
bmp_read_line(), and read whatever you like from that line, and then call 
bmp_write_line() with the same or a different line number, and write 
whatever you like to this second line, but you mustn't call bmp_read_line() 
and bmp_write_line() together and expect to be able to read one line and 
write the other simultaneously. It would be nice if this was possible, but 
if you do it, your code won't work on single banked SVGA cards.

And then there's mode-X. If you've never done any mode-X graphics coding, 
you probably won't understand this, but for those of you who want to know 
how Allegro sets up the mode-X screen bitmaps, here goes...

The line pointers are still present, and they contain planar addresses, ie. 
the actual location at which you access the first pixel in the line. These 
addresses are guaranteed to be quad aligned, so you can just set the write 
plane, divide your x coordinate by four, and add it to the line pointer. For 
example, a mode-X putpixel is:
@example

void modex_putpixel(BITMAP *b, int x, int y, int color)
@{
   outportw(0x3C4, (0x100<<(x&3))|2);
   bmp_select(bmp);
   bmp_write8((unsigned long)bmp->line[y]+(x>>2), color);
@}@end example


Oh yeah: the DJGPP nearptr hack. Personally I don't like this very much 
because it disables memory protection and isn't portable to other platforms, 
but a lot of people swear by it because it can give you direct access to the 
screen memory via a normal C pointer. Warning: this method will only work 
with the DJGPP library, when using VGA 13h or a linear framebuffer modes!

In your setup code:
@example

#include <sys/nearptr.h>

unsigned char *screenmemory;
unsigned long screen_base_addr;

__djgpp_nearptr_enable();

__dpmi_get_segment_base_address(screen->seg, &screen_base_addr);

screenmemory = (unsigned char *)(screen_base_addr + 
                                 screen->line[0] -
                                 __djgpp_base_address);
@end example

Then:
@example

void nearptr_putpixel(int x, int y, int color)
@{
   screenmemory[x + y*VIRTUAL_W] = color;
@}
@end example



@node FLIC, Sound, Direct, API
@section FLIC routines

There are two high level functions for playing FLI/FLC animations: 
play_fli(), which reads the data directly from disk, and play_memory_fli(), 
which uses data that has already been loaded into RAM. Apart from the 
different sources of the data, these two functions behave identically. They 
draw the animation onto the specified bitmap, which should normally be the 
screen. Frames will be aligned with the top left corner of the bitmap: if 
you want to position them somewhere else you will need to create a 
sub-bitmap for the FLI player to draw onto.

If the callback function is not NULL it will be called once for each frame,
allowing you to perform background tasks of your own. This callback should
normally return zero: if it returns non-zero the player will terminate (this
is the only way to stop an animation that is playing in looped mode).

The FLI player returns FLI_OK if it reached the end of the file, FLI_ERROR
if something went wrong, and the value returned by the callback function if
that was what stopped it. If you need to distinguish between different return
values, your callback should return positive integers, since FLI_OK is zero
and FLI_ERROR is negative.

Note that the FLI player will only work when the timer module is installed, 
and that it will alter the palette according to whatever palette data is 
present in the animation file.

Occasionally you may need more detailed control over how an FLI is played, 
for example if you want to superimpose a text scroller on top of the 
animation, or to play it back at a different speed. You could do both of 
these with the lower level functions described below.

@menu
* play_fli::
* play_memory_fli::
* open_fli::
* close_fli::
* next_fli_frame::
* fli_bitmap::
* fli_palette::
* fli_bmp_dirty_from::
* fli_pal_dirty_from::
* reset_fli_variables::
* fli_frame::
* fli_timer::
@end menu
@node play_fli, play_memory_fli, More on banked direct memory access, FLIC
@subsection play_fli
@ftable @asis
@item @t{int play_fli(const char *filename, BITMAP *bmp, int loop, int (*callback)());}
Plays an Autodesk Animator FLI or FLC animation file on the specified
BITMAP, reading the data from disk as it is required. If `loop' is not
zero, the player will cycle when it reaches the end of the file, otherwise
it will play through the animation once and then return. Read the beginning
of chapter "FLIC routines" for a description of the callback parameter.
Example:
@example

/* Let users skip looped animations. */
int check_escape_key(void)
@{
   if (key[KEY_ESC])
      return 1;
   else
      return 0;
@}
...
   int ret = play_fli("animlogo.fli", screen, 1,
                       check_escape_key);
   if (ret == FLI_ERROR)
      abort_on_error("Error playing intro!");@end example


The FLI player returns FLI_OK if it reached the end of the file, FLI_ERROR
if something went wrong, and the value returned by the callback function if
that was what stopped it.

@end ftable
See also:@*
@xref{play_memory_fli}.@*
@xref{install_timer}.@*
@xref{fli_frame}.@*
@xref{BITMAP}.@*
@node play_memory_fli, open_fli, play_fli, FLIC
@subsection play_memory_fli
@ftable @asis
@item @t{int play_memory_fli(const void *fli_data, BITMAP *bmp, int loop, int (*callback)());}
Plays an Autodesk Animator FLI or FLC animation on the specified BITMAP,
reading the data from a copy of the file which is held in memory. You can
obtain the `fli_data' pointer by allocating a block of memory and reading
an FLI file into it, or by importing an FLI into a grabber datafile. If
`loop' is not zero, the player will cycle when it reaches the end of the
file, otherwise it will play through the animation once and then return.
Read the beginning of chapter "FLIC routines" for a description of the
callback parameter.

Playing animations from memory is obviously faster than cuing them
directly from disk, and is particularly useful with short, looped FLI's.
Animations can easily get very large, though, so in most cases you will
probably be better just using play_fli(). You can think of this function
as a wrapper on top of open_memory_fli(), next_fli_frame() and close_fli().
Example:
@example

int ret = play_memory_fli(anim_data, screen, 0, NULL);
if (ret == FLI_ERROR)
   abort_on_error("Corrupted animation data?");@end example


The FLI player returns FLI_OK if it reached the end of the file, FLI_ERROR
if something went wrong, and the value returned by the callback function if
that was what stopped it.

@end ftable
See also:@*
@xref{play_fli}.@*
@xref{install_timer}.@*
@xref{fli_frame}.@*
@xref{BITMAP}.@*
@node open_fli, close_fli, play_memory_fli, FLIC
@subsection open_fli
@ftable @asis
@item @t{int open_fli(const char *filename);}
@end ftable
@ftable @asis
@item @t{int open_memory_fli(const void *fli_data);}
Open FLI files ready for playing, reading the data from disk or memory
respectively. Information about the current FLI is held in the global
variables fli_bitmap and fli_palette, which you can use if this function
succeeds. However, you can only have one animation open at a time.
Example:
@example

if (open_fli("intro.fli") == FLI_ERROR)
   abort_on_error("Error playing intro");@end example


Returns FLI_OK on success, FLI_ERROR if something went wrong, like trying
to open another FLI file without closing the previous one.

@end ftable
See also:@*
@xref{close_fli}.@*
@xref{next_fli_frame}.@*
@xref{fli_bitmap}.@*
@xref{fli_palette}.@*
@node close_fli, next_fli_frame, open_fli, FLIC
@subsection close_fli
@ftable @asis
@item @t{void close_fli();}
Closes an FLI file when you have finished reading from it. Remember to do
this to avoid having memory leaks in your program.

@end ftable
See also:@*
@xref{open_fli}.@*
@node next_fli_frame, fli_bitmap, close_fli, FLIC
@subsection next_fli_frame
@ftable @asis
@item @t{int next_fli_frame(int loop);}
Reads the next frame of the current animation file. If `loop' is not zero,
the player will cycle when it reaches the end of the file, otherwise it
will return FLI_EOF. The frame is read into the global variables
fli_bitmap and fli_palette. Example:
@example

while (next_fli_frame(0) == FLI_OK) @{
   /* Do stuff, like play audio stream
      or check keys to skip animation. */
   /* Rest some time until next frame... */
@}@end example


Returns FLI_OK on success, FLI_ERROR or FLI_NOT_OPEN on error, and FLI_EOF
on reaching the end of the file.

@end ftable
See also:@*
@xref{open_fli}.@*
@xref{fli_bitmap}.@*
@xref{fli_palette}.@*
@xref{fli_timer}.@*
@xref{fli_frame}.@*
@node fli_bitmap, fli_palette, next_fli_frame, FLIC
@subsection fli_bitmap
@ftable @asis
@item @t{extern BITMAP *fli_bitmap;}
Contains the current frame of the FLI/FLC animation. If there is no open
animation, its value will be NULL.

@end ftable
See also:@*
@xref{next_fli_frame}.@*
@xref{fli_bmp_dirty_from}.@*
@xref{fli_palette}.@*
@xref{BITMAP}.@*
@node fli_palette, fli_bmp_dirty_from, fli_bitmap, FLIC
@subsection fli_palette
@ftable @asis
@item @t{extern PALETTE fli_palette;}
Contains the current FLI palette.

@end ftable
See also:@*
@xref{next_fli_frame}.@*
@xref{fli_pal_dirty_from}.@*
@xref{fli_bitmap}.@*
@xref{PALETTE}.@*
@node fli_bmp_dirty_from, fli_pal_dirty_from, fli_palette, FLIC
@subsection fli_bmp_dirty_from
@ftable @asis
@item @t{extern int fli_bmp_dirty_from;}
@end ftable
@ftable @asis
@item @t{extern int fli_bmp_dirty_to;}
These variables are set by next_fli_frame() to indicate which part of the 
fli_bitmap has changed since the last call to reset_fli_variables(). If 
fli_bmp_dirty_from is greater than fli_bmp_dirty_to, the bitmap has not 
changed, otherwise lines fli_bmp_dirty_from to fli_bmp_dirty_to 
(inclusive) have altered. You can use these when copying the fli_bitmap 
onto the screen, to avoid moving data unnecessarily. Example:
@example

if (fli_bmp_dirty_from <= fli_bmp_dirty_to)
   blit(fli_bitmap, screen, 0, fli_bmp_dirty_from,
        0, fli_bmp_dirty_from, fli_bitmap->w,
        fli_bmp_dirty_to - fli_bmp_dirty_from + 1);@end example


@end ftable
See also:@*
@xref{fli_bitmap}.@*
@xref{reset_fli_variables}.@*
@node fli_pal_dirty_from, reset_fli_variables, fli_bmp_dirty_from, FLIC
@subsection fli_pal_dirty_from
@ftable @asis
@item @t{extern int fli_pal_dirty_from;}
@end ftable
@ftable @asis
@item @t{extern int fli_pal_dirty_to;}
These variables are set by next_fli_frame() to indicate which part of the 
fli_palette has changed since the last call to reset_fli_variables(). If 
fli_pal_dirty_from is greater than fli_pal_dirty_to, the palette has not 
changed, otherwise colors fli_pal_dirty_from to fli_pal_dirty_to 
(inclusive) have altered. You can use these when updating the hardware 
palette, to avoid unnecessary calls to set_palette(). Example:
@example

if (fli_pal_dirty_from <= fli_pal_dirty_to)
   set_palette_range(fli_palette, fli_pal_dirty_from,
                     fli_pal_dirty_to, 1);@end example


@end ftable
See also:@*
@xref{fli_palette}.@*
@xref{reset_fli_variables}.@*
@node reset_fli_variables, fli_frame, fli_pal_dirty_from, FLIC
@subsection reset_fli_variables
@ftable @asis
@item @t{void reset_fli_variables();}
Once you have done whatever you are going to do with the fli_bitmap and 
fli_palette, call this function to reset the fli_bmp_dirty_* and 
fli_pal_dirty_* variables.

@end ftable
See also:@*
@xref{fli_bmp_dirty_from}.@*
@xref{fli_pal_dirty_from}.@*
@node fli_frame, fli_timer, reset_fli_variables, FLIC
@subsection fli_frame
@ftable @asis
@item @t{extern int fli_frame;}
Global variable containing the current frame number in the FLI file. This 
is useful for synchronising other events with the animation, for instance 
you could check it in a play_fli() callback function and use it to 
trigger a sample at a particular point. Example:
@example

while (next_fli_frame(0) == FLI_OK) @{
   if (fli_frame == 345)
      play_sample(trumpet_sound, 255, 128, 1000, 0);
   /* Rest some time until next frame... */
@}@end example


@end ftable
See also:@*
@xref{play_fli}.@*
@xref{play_memory_fli}.@*
@xref{next_fli_frame}.@*
@node fli_timer, detect_digi_driver, fli_frame, FLIC
@subsection fli_timer
@ftable @asis
@item @t{extern volatile int fli_timer;}
Global variable for timing FLI playback. When you open an FLI file, a 
timer interrupt is installed which increments this variable every time a 
new frame should be displayed. Calling next_fli_frame() decrements it, so 
you can test it and know that it is time to display a new frame if it is 
greater than zero. Example:
@example

while (next_fli_frame(0) == FLI_OK) @{
   /* Do stuff, like play audio stream
      or check keys to skip animation. */
   /* Rest some time until next frame... */
   while (fli_timer <= 0)
      rest(0);
@}@end example




@end ftable
See also:@*
@xref{install_timer}.@*
@xref{next_fli_frame}.@*
@node Sound, Mixer, FLIC, API
@section Sound init routines

Allegro allows you to use the sound hardware in two ways: automatic, or
manual. Usually you should try the automatic version first. This means
calling install_sound() with the autodetection parameters and using the rest
of the sound functions to play samples or music. In this situation, Allegro
will handle the sound devices and mix the samples and/or music the best way
it can.

However, sound hardware has a limitation on the number of samples it may
play all at the same time (from now on, called hardware voices). When you
exceed this limit, Allegro will cut off one of the samples being played and
reproduce the new one. Depending on the type of sounds you are playing, how
many of them you need at the same time and their nature (e.g: vital audio
feedback to the user or useless "ping" when some shrapnel hits a rock in the
scenery) you will want to specify more carefully how hardware voices are
reserved and which samples have priority over others.

The hardware voice reservation phase has to be done before the call to
install_sound(), since it directly affects how Allegro talks to the sound
drivers.

@menu
* detect_digi_driver::
* detect_midi_driver::
* reserve_voices::
* set_volume_per_voice::
* install_sound::
* remove_sound::
* set_volume::
* set_hardware_volume::
* get_volume::
* get_hardware_volume::
@end menu
@node detect_digi_driver, detect_midi_driver, fli_timer, Sound
@subsection detect_digi_driver
@ftable @asis
@item @t{int detect_digi_driver(int driver_id);}
Detects whether the specified digital sound device is available. This
function must be called _before_ install_sound().

Returns the maximum number of voices that the driver can provide, or zero
if the hardware is not present.

@end ftable
See also:@*
@xref{install_sound}.@*
@xref{reserve_voices}.@*
@xref{DIGI_*/DOS}.@*
@xref{DIGI_*/Windows}.@*
@xref{DIGI_*/Unix}.@*
@xref{DIGI_*/BeOS}.@*
@xref{DIGI_*/QNX}.@*
@xref{DIGI_*/MacOSX}.@*
@node detect_midi_driver, reserve_voices, detect_digi_driver, Sound
@subsection detect_midi_driver
@ftable @asis
@item @t{int detect_midi_driver(int driver_id);}
Detects whether the specified MIDI sound device is available. This function
must be called _before_ install_sound().

Returns the maximum number of voices that the driver can provide, or zero
if the hardware is not present.

There are two special-case return values that you should watch out for:
if this function returns -1 it is a note-stealing driver (eg. DIGMID) that
shares voices with the current digital sound driver, and if it returns
0xFFFF it is an external device like an MPU-401 where there is no way to
determine how many voices are available.

@end ftable
See also:@*
@xref{install_sound}.@*
@xref{reserve_voices}.@*
@xref{MIDI_*/DOS}.@*
@xref{MIDI_*/Windows}.@*
@xref{MIDI_*/Unix}.@*
@xref{MIDI_*/BeOS}.@*
@xref{MIDI_*/QNX}.@*
@xref{MIDI_*/MacOSX}.@*
@node reserve_voices, set_volume_per_voice, detect_midi_driver, Sound
@subsection reserve_voices
@ftable @asis
@item @t{void reserve_voices(int digi_voices, int midi_voices);}
Call this function to specify the number of voices that are to be used by
the digital and MIDI sound drivers respectively. This must be done
_before_ calling install_sound(). If you reserve too many voices,
subsequent calls to install_sound() will fail. How many voices are
available depends on the driver, and in some cases you will actually get
more than you reserve (eg. the FM synth drivers will always provide 9
voices on an OPL2 and 18 on an OPL3, and the SB digital driver will round
the number of voices up to the nearest power of two). Pass negative
values to restore the default settings. You should be aware that the
sound quality is usually inversely related to how many voices you use, so
don't reserve any more than you really need.

@end ftable
See also:@*
@xref{set_volume_per_voice}.@*
@xref{install_sound}.@*
@xref{detect_digi_driver}.@*
@xref{detect_midi_driver}.@*
@xref{get_mixer_voices}.@*
@node set_volume_per_voice, install_sound, reserve_voices, Sound
@subsection set_volume_per_voice
@ftable @asis
@item @t{void set_volume_per_voice(int scale);}
By default, Allegro will play a centered sample at half volume on both
the left and right channel. A sample panned to the far right or left
will be played at maximum volume on that channel only. This is done so
you can play a single panned sample without distortion. If you play
multiple samples at full volume, the mixing process can result in
clipping, a noticeable form of distortion. The more samples, the more
likely clipping is to occur, and the more clipping, the worse the output
will sound.

If clipping is a problem - or if the output is too quiet - this function
can be used to adjust the volume of each voice. You should first check
that your speakers are at a reasonable volume, Allegro's global volume
is at maximum (see set_volume() below), and any other mixers such as the
Windows Volume Control are set reasonably. Once you are sure that
Allegro's output level is unsuitable for your application, use this
function to adjust it.

Each time you increase the parameter by one, the volume of each voice
will halve. For example, if you pass 4, you can play up to 16 centred
samples at maximum volume without distortion.

If you pass 0 to this function, each centred sample will play at the
maximum volume possible without distortion, as will all samples played
through a mono driver. Samples at the extreme left and right will distort
if played at full volume. If you wish to play panned samples at full
volume without distortion, you should pass 1 to this function.
Note: this is different from the function's behaviour in WIPs 3.9.34,
3.9.35 and 3.9.36. If you used this function under one of these WIPs,
you will have to increase your parameter by one to get the same volume.

Note: The default behaviour has changed as of Allegro 4.1.15. If you
would like the behaviour of earlier versions of Allegro, pass -1 to this
function. Allegro will choose a value dependent on the number of voices,
so that if you reserve n voices, you can play up to n/2 normalised
samples with centre panning without risking distortion. The exception is
when you have fewer than 8 voices, where the volume remains the same as
for 8 voices. Here are the values, dependent on the number of voices:
@example

1-8 voices - set_volume_per_voice(2)
 16 voices - set_volume_per_voice(3)
 32 voices - set_volume_per_voice(4)
 64 voices - set_volume_per_voice(5)
@end example

Of course this function does not override the volume you specify with
play_sample() or voice_set_volume(). It simply alters the overall output
of the program. If you play samples at lower volumes, or if they are not
normalised, then you can play more of them without distortion.

It is recommended that you hard-code the parameter into your program,
rather than offering it to the user. The user can alter the volume with
the configuration file instead, or you can provide for this with
set_volume().

To restore volume per voice to its default behaviour, pass 1.

@end ftable
See also:@*
@xref{reserve_voices}.@*
@xref{set_volume}.@*
@xref{install_sound}.@*
@xref{detect_digi_driver}.@*
@xref{detect_midi_driver}.@*
@node install_sound, remove_sound, set_volume_per_voice, Sound
@subsection install_sound
@ftable @asis
@item @t{int install_sound(int digi, int midi, const char *cfg_path);}
Initialises the sound module. You should normally pass DIGI_AUTODETECT 
and MIDI_AUTODETECT as the driver parameters to this function, in which 
case Allegro will read hardware settings from the current configuration 
file. This allows the user to select different values with the setup 
utility: see the config section for details. Alternatively, see the 
platform specific documentation for a list of the available drivers. The 
cfg_path parameter is only present for compatibility with previous 
versions of Allegro, and has no effect on anything.

Returns zero if the sound is successfully installed, and -1 on failure.
If it fails it will store a description of the problem in allegro_error.

@end ftable
See also:@*
@xref{remove_sound}.@*
@xref{reserve_voices}.@*
@xref{detect_digi_driver}.@*
@xref{detect_midi_driver}.@*
@xref{set_volume}.@*
@xref{play_sample}.@*
@xref{Voice control}.@*
@xref{play_midi}.@*
@xref{play_audio_stream}.@*
@xref{install_sound_input}.@*
@xref{allegro_error}.@*
@xref{Standard config variables}.@*
@xref{set_mixer_quality}.@*
@xref{DIGI_*/DOS}.@*
@xref{DIGI_*/Windows}.@*
@xref{DIGI_*/Unix}.@*
@xref{DIGI_*/BeOS}.@*
@xref{DIGI_*/QNX}.@*
@xref{DIGI_*/MacOSX}.@*
@xref{MIDI_*/DOS}.@*
@xref{MIDI_*/Windows}.@*
@xref{MIDI_*/Unix}.@*
@xref{MIDI_*/BeOS}.@*
@xref{MIDI_*/QNX}.@*
@xref{MIDI_*/MacOSX}.@*
@xref{exmidi}.@*
@xref{exsample}.@*
@xref{exsprite}.@*
@xref{exstream}.@*
@node remove_sound, set_volume, install_sound, Sound
@subsection remove_sound
@ftable @asis
@item @t{void remove_sound();}
Cleans up after you are finished with the sound routines. You don't 
normally need to call this, because allegro_exit() will do it for you.

@end ftable
See also:@*
@xref{install_sound}.@*
@xref{allegro_exit}.@*
@node set_volume, set_hardware_volume, remove_sound, Sound
@subsection set_volume
@ftable @asis
@item @t{void set_volume(int digi_volume, int midi_volume);}
Alters the global sound output volume. Specify volumes for both digital 
samples and MIDI playback, as integers from 0 to 255, or pass a negative 
value to leave one of the settings unchanged. Values bigger than 255 will
be reduced to 255. This routine will not alter the volume of the hardware
mixer if it exists (i.e. only your application will be affected).

@end ftable
See also:@*
@xref{install_sound}.@*
@xref{set_hardware_volume}.@*
@node set_hardware_volume, get_volume, set_volume, Sound
@subsection set_hardware_volume
@ftable @asis
@item @t{void set_hardware_volume(int digi_volume, int midi_volume);}
Alters the hardware sound output volume. Specify volumes for both digital 
samples and MIDI playback, as integers from 0 to 255, or pass a negative 
value to leave one of the settings unchanged. Values bigger than 255 will
be reduced to 255. This routine will use the hardware mixer to control the
volume if it exists (i.e. the volume of all the applications on your
machine will be affected), otherwise do nothing.

@end ftable
See also:@*
@xref{install_sound}.@*
@xref{set_volume}.@*
@node get_volume, get_hardware_volume, set_hardware_volume, Sound
@subsection get_volume
@ftable @asis
@item @t{void get_volume(int *digi_volume, int *midi_volume);}
Retrieves the global sound output volume, both for digital samples and MIDI
playback, as integers from 0 to 255. Parameters digi_volume and midi_volume
must be valid pointers to int, or NULL if not interested in specific value.

@end ftable
See also:@*
@xref{set_volume}.@*
@xref{get_hardware_volume}.@*
@node get_hardware_volume, set_mixer_quality, get_volume, Sound
@subsection get_hardware_volume
@ftable @asis
@item @t{void get_hardware_volume(int *digi_volume, int *midi_volume);}
Retrieves the hardware sound output volume, both for digital samples and MIDI
playback, as integers from 0 to 255, or -1 if the information is not
available. Parameters digi_volume and midi_volume must be valid pointers to
int, or NULL if not interested in specific value.

@end ftable
See also:@*
@xref{set_hardware_volume}.@*
@xref{get_volume}.@*
@node Mixer, Digital, Sound, API
@section Mixer routines



@menu
* set_mixer_quality::
* get_mixer_quality::
* get_mixer_frequency::
* get_mixer_bits::
* get_mixer_channels::
* get_mixer_voices::
* get_mixer_buffer_length::
@end menu
@node set_mixer_quality, get_mixer_quality, get_hardware_volume, Mixer
@subsection set_mixer_quality
@ftable @asis
@item @t{void set_mixer_quality(int quality);}
Sets the resampling quality of the mixer. Valid values are the same as
the `quality' config variable. Please read chapter "Standard config
variables" for details. You can call this function at any point in your
program, even before allegro_init().

@end ftable
See also:@*
@xref{get_mixer_quality}.@*
@xref{Standard config variables}.@*
@node get_mixer_quality, get_mixer_frequency, set_mixer_quality, Mixer
@subsection get_mixer_quality
@ftable @asis
@item @t{int get_mixer_quality(void);}
Returns the current mixing quality, as specified by the `quality' config
variable, or a previous call to set_mixer_quality().

@end ftable
See also:@*
@xref{set_mixer_quality}.@*
@xref{Standard config variables}.@*
@node get_mixer_frequency, get_mixer_bits, get_mixer_quality, Mixer
@subsection get_mixer_frequency
@ftable @asis
@item @t{int get_mixer_frequency(void);}
Returns the mixer frequency, in Hz.

@end ftable
See also:@*
@xref{Standard config variables}.@*
@node get_mixer_bits, get_mixer_channels, get_mixer_frequency, Mixer
@subsection get_mixer_bits
@ftable @asis
@item @t{int get_mixer_bits(void);}
Returns the mixer bit depth (8 or 16).

@end ftable
See also:@*
@xref{Standard config variables}.@*
@node get_mixer_channels, get_mixer_voices, get_mixer_bits, Mixer
@subsection get_mixer_channels
@ftable @asis
@item @t{int get_mixer_channels(void);}
Returns the number of output channels. 2 for stereo, 1 for mono, 0 if
the mixer isn't active.

@end ftable
See also:@*
@xref{Standard config variables}.@*
@node get_mixer_voices, get_mixer_buffer_length, get_mixer_channels, Mixer
@subsection get_mixer_voices
@ftable @asis
@item @t{int get_mixer_voices(void);}
Returns the number of voices allocated to the mixer.

@end ftable
See also:@*
@xref{reserve_voices}.@*
@node get_mixer_buffer_length, load_sample, get_mixer_voices, Mixer
@subsection get_mixer_buffer_length
@ftable @asis
@item @t{int get_mixer_buffer_length(void);}
Returns the number of samples per channel in the mixer buffer.



@end ftable
See also:@*
@xref{Standard config variables}.@*
@node Digital, Music, Mixer, API
@section Digital sample routines

@menu
* load_sample::
* load_wav::
* load_wav_pf::
* load_voc::
* load_voc_pf::
* save_sample::
* create_sample::
* destroy_sample::
* lock_sample::
* register_sample_file_type::
* play_sample::
* adjust_sample::
* stop_sample::
* Voice control::
* allocate_voice::
* deallocate_voice::
* reallocate_voice::
* release_voice::
* voice_start::
* voice_stop::
* voice_set_priority::
* voice_check::
* voice_get_position::
* voice_set_position::
* voice_set_playmode::
* voice_get_volume::
* voice_set_volume::
* voice_ramp_volume::
* voice_stop_volumeramp::
* voice_get_frequency::
* voice_set_frequency::
* voice_sweep_frequency::
* voice_stop_frequency_sweep::
* voice_get_pan::
* voice_set_pan::
* voice_sweep_pan::
* voice_stop_pan_sweep::
* voice_set_echo::
* voice_set_tremolo::
* voice_set_vibrato::
@end menu
@node load_sample, load_wav, get_mixer_buffer_length, Digital
@subsection load_sample
@ftable @asis
@item @t{SAMPLE *load_sample(const char *filename);}
Loads a sample from a file, supporting both mono and stereo WAV and mono
VOC files, in 8 or 16-bit formats, as well as formats handled by functions
registered using register_sample_file_type(). Example:
@example

SAMPLE *sample = load_sample(user_input);
if (!sample)
   abort_on_error("Couldn't load sample!");@end example


Returns a pointer to the SAMPLE or NULL on error. Remember to free this
sample later to avoid memory leaks.

@end ftable
See also:@*
@xref{destroy_sample}.@*
@xref{load_voc}.@*
@xref{load_wav}.@*
@xref{play_sample}.@*
@xref{save_sample}.@*
@xref{register_sample_file_type}.@*
@xref{Voice control}.@*
@xref{exsample}.@*
@xref{SAMPLE}.@*
@node load_wav, load_wav_pf, load_sample, Digital
@subsection load_wav
@ftable @asis
@item @t{SAMPLE *load_wav(const char *filename);}
Loads a sample from a RIFF WAV file. Example:
@example

SAMPLE *sample = load_wav("scream.wav");
if (!sample)
   abort_on_error("Couldn't scare user!");@end example


Returns a pointer to the SAMPLE or NULL on error. Remember to free this
sample later to avoid memory leaks.

@end ftable
See also:@*
@xref{load_sample}.@*
@xref{register_sample_file_type}.@*
@xref{SAMPLE}.@*
@node load_wav_pf, load_voc, load_wav, Digital
@subsection load_wav_pf
@ftable @asis
@item @t{SAMPLE *load_wav_pf(PACKFILE *f);}
A version of load_wav() which reads from a packfile. Example:
@example

PACKFILE *packfile;
SAMPLE *sample;

packfile = pack_fopen("sound.wav", F_READ);
if (!packfile)
   abort_on_error("Couldn't open sound.wav");

sample = load_wav_pf(packfile);
if (!sample)
   abort_on_error("Error loading sound.wav");@end example


Returns a pointer to the SAMPLE or NULL on error. Remember to free this
sample later to avoid memory leaks.

@end ftable
See also:@*
@xref{load_wav}.@*
@xref{SAMPLE}.@*
@xref{PACKFILE}.@*
@node load_voc, load_voc_pf, load_wav_pf, Digital
@subsection load_voc
@ftable @asis
@item @t{SAMPLE *load_voc(const char *filename);}
Loads a sample from a Creative Labs VOC file. Example:
@example

SAMPLE *sample = load_voc("alarm.voc");
if (!sample)
   abort_on_error("Couldn't alert user!");@end example


Returns a pointer to the SAMPLE or NULL on error. Remember to free this
sample later to avoid memory leaks.

@end ftable
See also:@*
@xref{load_sample}.@*
@xref{register_sample_file_type}.@*
@xref{SAMPLE}.@*
@node load_voc_pf, save_sample, load_voc, Digital
@subsection load_voc_pf
@ftable @asis
@item @t{SAMPLE *load_voc_pf(PACKFILE *f);}
A version of load_voc() which reads from a packfile. Example:
@example

PACKFILE *packfile;
SAMPLE *sample;

packfile = pack_fopen("sound.wav", F_READ);
if (!packfile)
   abort_on_error("Couldn't open sound.wav");

sample = load_wav_pf(packfile);
if (!sample)
   abort_on_error("Error loading sound.wav");@end example


Returns a pointer to the SAMPLE or NULL on error. Remember to free this
sample later to avoid memory leaks.

@end ftable
See also:@*
@xref{load_voc}.@*
@xref{SAMPLE}.@*
@xref{PACKFILE}.@*
@node save_sample, create_sample, load_voc_pf, Digital
@subsection save_sample
@ftable @asis
@item @t{int save_sample(const char *filename, SAMPLE *spl);}
Writes a sample into a file. The output format is determined from the
filename extension. At present Allegro does not natively support the
writing of any sample formats, so you must register a custom saver routine
with register_sample_file_type(). Example:
@example

if (save_sample("sound.wav", sample) != 0)
   abort_on_error("Couldn't save sample!");@end example


Returns zero on success, non-zero otherwise.

@end ftable
See also:@*
@xref{load_sample}.@*
@xref{register_sample_file_type}.@*
@xref{SAMPLE}.@*
@node create_sample, destroy_sample, save_sample, Digital
@subsection create_sample
@ftable @asis
@item @t{SAMPLE *create_sample(int bits, int stereo, int freq, int len);}
Constructs a new sample structure of the specified type. Read chapter
"Structures and types defined by Allegro" for an internal description of
the SAMPLE structure. The `bits' parameter can be 8 or 16, `stereo' can be
zero for mono samples and non-zero for stereo samples, `freq' is the
frequency in hertz, and `len' is the number of samples you want to allocate
for the full sound buffer.

Returns a pointer to the created sample, or NULL if the sample could not
be created. Remember to free this sample later to avoid memory leaks.

@end ftable
See also:@*
@xref{load_sample}.@*
@xref{destroy_sample}.@*
@xref{Structures, Structures and types defined by Allegro}.@*
@xref{SAMPLE}.@*
@node destroy_sample, lock_sample, create_sample, Digital
@subsection destroy_sample
@ftable @asis
@item @t{void destroy_sample(SAMPLE *spl);}
Destroys a sample structure when you are done with it. It is safe to call 
this even when the sample might be playing, because it checks and will 
kill it off if it is active. Use this to avoid memory leaks in your
program.

@end ftable
See also:@*
@xref{load_sample}.@*
@xref{exsample}.@*
@xref{SAMPLE}.@*
@node lock_sample, register_sample_file_type, destroy_sample, Digital
@subsection lock_sample
@ftable @asis
@item @t{void lock_sample(SAMPLE *spl);}
Under DOS, locks all the memory used by a sample. You don't normally need 
to call this function because load_sample() and create_sample() do it for
you.

@end ftable
See also:@*
@xref{load_sample}.@*
@xref{create_sample}.@*
@xref{SAMPLE}.@*
@node register_sample_file_type, play_sample, lock_sample, Digital
@subsection register_sample_file_type
@ftable @asis
@item @t{void register_sample_file_type(const char *ext, SAMPLE *(*load)(const char *filename), int (*save)(const char *filename, SAMPLE *spl));}
Informs the load_sample() function of a new sample file type,
providing routines to read and write samples in this format (either
function may be NULL). Example:
@example

SAMPLE *load_mp3(const char *filename)
@{
   ...
@}

   register_sample_file_type("mp3", load_mp3, NULL);@end example


@end ftable
See also:@*
@xref{load_sample}.@*
@xref{save_sample}.@*
@xref{SAMPLE}.@*
@node play_sample, adjust_sample, register_sample_file_type, Digital
@subsection play_sample
@ftable @asis
@item @t{int play_sample(const SAMPLE *spl, int vol, int pan, int freq, int loop);}
Triggers a sample at the specified volume, pan position, and frequency. 
The parameters `vol' and `pan' range from 0 (min/left) to 255 (max/right).
Frequency is relative rather than absolute: 1000 represents the frequency
that the sample was recorded at, 2000 is twice this, etc. If `loop' is not
zero, the sample will repeat until you call stop_sample(), and can be
manipulated while it is playing by calling adjust_sample(). Example:
@example

/* Scream from the left speaker, twice the freq. */
int sound = play_sample(scream, 255, 0, 2000, 0);@end example


Returns the voice number that was allocated for the sample or negative if
no voices were available.

@end ftable
See also:@*
@xref{install_sound}.@*
@xref{load_sample}.@*
@xref{adjust_sample}.@*
@xref{stop_sample}.@*
@xref{Voice control}.@*
@xref{exsample}.@*
@xref{exsprite}.@*
@xref{SAMPLE}.@*
@node adjust_sample, stop_sample, play_sample, Digital
@subsection adjust_sample
@ftable @asis
@item @t{void adjust_sample(const SAMPLE *spl, int vol, int pan, int freq, int loop);}
Alters the parameters of a sample while it is playing (useful for
manipulating looped sounds). You can alter the volume, pan, and frequency,
and can also clear the loop flag, which will stop the sample when it next
reaches the end of its loop. The values of the parameters are just like
those of play_sample(). If there are several copies of the same sample
playing, this will adjust the first one it comes across. If the sample is
not playing it has no effect.

@end ftable
See also:@*
@xref{play_sample}.@*
@xref{exsample}.@*
@xref{SAMPLE}.@*
@node stop_sample, Voice control, adjust_sample, Digital
@subsection stop_sample
@ftable @asis
@item @t{void stop_sample(const SAMPLE *spl);}
Stop a sample from playing, which is required if you have set a sample
going in looped mode. If there are several copies of the sample playing,
it will stop them all. You must still destroy the sample using
destroy_sample().

@end ftable
See also:@*
@xref{play_sample}.@*
@xref{destroy_sample}.@*
@xref{SAMPLE}.@*
@node Voice control, allocate_voice, stop_sample, Digital
@subsection Voice control
@ftable @asis
@end ftable
If you need more detailed control over how samples are played, you can use 
the lower level voice functions rather than just calling play_sample(). This 
is rather more work, because you have to explicitly allocate and free the 
voices rather than them being automatically released when they finish 
playing, but allows far more precise specification of exactly how you want 
everything to sound. You may also want to modify a couple of fields from the 
SAMPLE structure. Read chapter "Structures and types defined by Allegro" for
its definition.

See also:@*
@xref{install_sound}.@*
@xref{allocate_voice}.@*
@xref{deallocate_voice}.@*
@xref{reallocate_voice}.@*
@xref{release_voice}.@*
@xref{voice_start}.@*
@xref{voice_set_priority}.@*
@xref{voice_check}.@*
@xref{voice_set_position}.@*
@xref{voice_set_playmode}.@*
@xref{voice_set_volume}.@*
@xref{voice_set_frequency}.@*
@xref{voice_set_pan}.@*
@xref{SAMPLE}.@*
@node allocate_voice, deallocate_voice, Voice control, Digital
@subsection allocate_voice
@ftable @asis
@item @t{int allocate_voice(const SAMPLE *spl);}
Allocates a sound card voice and prepares it for playing the specified 
sample, setting up sensible default parameters (maximum volume, centre 
pan, no change of pitch, no looping). When you are finished with the 
voice you must free it by calling deallocate_voice() or release_voice().
Allegro can manage up to 256 simultaneous voices, but that limit may be
lower due to hardware reasons.

Returns the voice number, or -1 if no voices are available.

@end ftable
See also:@*
@xref{Voice control}.@*
@xref{deallocate_voice}.@*
@xref{reallocate_voice}.@*
@xref{release_voice}.@*
@xref{load_sample}.@*
@xref{SAMPLE}.@*
@node deallocate_voice, reallocate_voice, allocate_voice, Digital
@subsection deallocate_voice
@ftable @asis
@item @t{void deallocate_voice(int voice);}
Frees a sound card voice, stopping it from playing and releasing whatever 
resources it is using.

@end ftable
See also:@*
@xref{allocate_voice}.@*
@xref{voice_stop}.@*
@node reallocate_voice, release_voice, deallocate_voice, Digital
@subsection reallocate_voice
@ftable @asis
@item @t{void reallocate_voice(int voice, const SAMPLE *spl);}
Switches an already-allocated voice to use a different sample. Calling 
reallocate_voice(voice, sample) is equivalent to:
@example

deallocate_voice(voice);
voice = allocate_voice(sample);@end example


@end ftable
See also:@*
@xref{allocate_voice}.@*
@xref{deallocate_voice}.@*
@xref{load_sample}.@*
@xref{SAMPLE}.@*
@node release_voice, voice_start, reallocate_voice, Digital
@subsection release_voice
@ftable @asis
@item @t{void release_voice(int voice);}
Releases a sound card voice, indicating that you are no longer interested 
in manipulating it. The sound will continue to play, and any resources 
that it is using will automatically be freed when it finishes. This is 
essentially the same as deallocate_voice(), but it waits for the sound to 
stop playing before taking effect.

@end ftable
See also:@*
@xref{allocate_voice}.@*
@xref{deallocate_voice}.@*
@node voice_start, voice_stop, release_voice, Digital
@subsection voice_start
@ftable @asis
@item @t{void voice_start(int voice);}
Activates a voice, using whatever parameters have been set for it.

@end ftable
See also:@*
@xref{Voice control}.@*
@xref{allocate_voice}.@*
@xref{voice_stop}.@*
@xref{release_voice}.@*
@xref{exstream}.@*
@node voice_stop, voice_set_priority, voice_start, Digital
@subsection voice_stop
@ftable @asis
@item @t{void voice_stop(int voice);}
Stops a voice, storing the current position and state so that it may 
later be resumed by calling voice_start().

@end ftable
See also:@*
@xref{voice_start}.@*
@xref{deallocate_voice}.@*
@xref{release_voice}.@*
@xref{exstream}.@*
@node voice_set_priority, voice_check, voice_stop, Digital
@subsection voice_set_priority
@ftable @asis
@item @t{void voice_set_priority(int voice, int priority);}
Sets the priority of a voice (range 0-255). This is used to decide which 
voices should be chopped off, if you attempt to play more than the 
sound card driver can handle.

@end ftable
See also:@*
@xref{Voice control}.@*
@node voice_check, voice_get_position, voice_set_priority, Digital
@subsection voice_check
@ftable @asis
@item @t{SAMPLE *voice_check(int voice);}
Checks whether a voice is currently allocated.

Returns a pointer to the sample that the voice is using, or NULL if the
voice is inactive (ie. it has been deallocated, or the release_voice()
function has been called and the sample has then finished playing).

@end ftable
See also:@*
@xref{allocate_voice}.@*
@xref{voice_start}.@*
@xref{voice_get_position}.@*
@xref{SAMPLE}.@*
@node voice_get_position, voice_set_position, voice_check, Digital
@subsection voice_get_position
@ftable @asis
@item @t{int voice_get_position(int voice);}
Returns the current position of a voice, in sample units, or -1 if it has 
finished playing.

@end ftable
See also:@*
@xref{Voice control}.@*
@xref{voice_set_position}.@*
@node voice_set_position, voice_set_playmode, voice_get_position, Digital
@subsection voice_set_position
@ftable @asis
@item @t{void voice_set_position(int voice, int position);}
Sets the position of a voice, in sample units.

@end ftable
See also:@*
@xref{Voice control}.@*
@xref{voice_get_position}.@*
@xref{voice_set_playmode}.@*
@node voice_set_playmode, voice_get_volume, voice_set_position, Digital
@subsection voice_set_playmode
@ftable @asis
@item @t{void voice_set_playmode(int voice, int playmode);}
Adjusts the loop status of the specified voice. This can be done while 
the voice is playing, so you can start a sample in looped mode (having 
set the loop start and end positions to the appropriate values), and then 
clear the loop flag when you want to end the sound, which will cause it 
to continue past the loop end, play the subsequent part of the sample, 
and finish in the normal way. The mode parameter is a bitfield containing 
the following values:

@itemize @bullet
@item 
PLAYMODE_PLAY@*
Plays the sample a single time. This is the default if you don't set 
the loop flag.
@item 
PLAYMODE_LOOP@*
Loops repeatedly through the sample, jumping back to the loop start 
position upon reaching the loop end.
@item 
PLAYMODE_FORWARD@*
Plays the sample from beginning to end. This is the default if you 
don't set the backward flag.
@item 
PLAYMODE_BACKWARD@*
Reverses the direction of the sample. If you combine this with the 
loop flag, the sample jumps to the loop end position upon reaching the 
loop start (ie. you do not need to reverse the loop start and end 
values when you play the sample in reverse).
@item 
PLAYMODE_BIDIR@*
When used in combination with the loop flag, causes the sample to 
change direction each time it reaches one of the loop points, so it 
alternates between playing forwards and in reverse.
@end itemize

@end ftable
See also:@*
@xref{Voice control}.@*
@node voice_get_volume, voice_set_volume, voice_set_playmode, Digital
@subsection voice_get_volume
@ftable @asis
@item @t{int voice_get_volume(int voice);}
Returns the current volume of the voice, range 0-255.  Otherwise it
returns -1 if that cannot be determined (because it has finished or
been preempted by a different sound).

@end ftable
See also:@*
@xref{Voice control}.@*
@xref{voice_set_volume}.@*
@node voice_set_volume, voice_ramp_volume, voice_get_volume, Digital
@subsection voice_set_volume
@ftable @asis
@item @t{void voice_set_volume(int voice, int volume);}
Sets the volume of the voice, range 0-255.

@end ftable
See also:@*
@xref{Voice control}.@*
@xref{voice_get_volume}.@*
@xref{voice_ramp_volume}.@*
@node voice_ramp_volume, voice_stop_volumeramp, voice_set_volume, Digital
@subsection voice_ramp_volume
@ftable @asis
@item @t{void voice_ramp_volume(int voice, int time, int endvol);}
Starts a volume ramp (crescendo or diminuendo) from the current volume to 
the specified ending volume, lasting for time milliseconds. The volume is
a value in the range 0-255.

@end ftable
See also:@*
@xref{Voice control}.@*
@xref{voice_set_volume}.@*
@node voice_stop_volumeramp, voice_get_frequency, voice_ramp_volume, Digital
@subsection voice_stop_volumeramp
@ftable @asis
@item @t{void voice_stop_volumeramp(int voice);}
Interrupts a volume ramp operation.

@end ftable
See also:@*
@xref{voice_ramp_volume}.@*
@node voice_get_frequency, voice_set_frequency, voice_stop_volumeramp, Digital
@subsection voice_get_frequency
@ftable @asis
@item @t{int voice_get_frequency(int voice);}
Returns the current pitch of the voice, in Hz.

@end ftable
See also:@*
@xref{Voice control}.@*
@xref{voice_set_frequency}.@*
@node voice_set_frequency, voice_sweep_frequency, voice_get_frequency, Digital
@subsection voice_set_frequency
@ftable @asis
@item @t{void voice_set_frequency(int voice, int frequency);}
Sets the pitch of the voice, in Hz.

@end ftable
See also:@*
@xref{Voice control}.@*
@xref{voice_get_frequency}.@*
@xref{voice_sweep_frequency}.@*
@node voice_sweep_frequency, voice_stop_frequency_sweep, voice_set_frequency, Digital
@subsection voice_sweep_frequency
@ftable @asis
@item @t{void voice_sweep_frequency(int voice, int time, int endfreq);}
Starts a frequency sweep (glissando) from the current pitch to the 
specified ending pitch, lasting for time milliseconds.

@end ftable
See also:@*
@xref{Voice control}.@*
@xref{voice_set_frequency}.@*
@node voice_stop_frequency_sweep, voice_get_pan, voice_sweep_frequency, Digital
@subsection voice_stop_frequency_sweep
@ftable @asis
@item @t{void voice_stop_frequency_sweep(int voice);}
Interrupts a frequency sweep operation.

@end ftable
See also:@*
@xref{voice_sweep_frequency}.@*
@node voice_get_pan, voice_set_pan, voice_stop_frequency_sweep, Digital
@subsection voice_get_pan
@ftable @asis
@item @t{int voice_get_pan(int voice);}
Returns the current pan position, from 0 (left) to 255 (right).

@end ftable
See also:@*
@xref{Voice control}.@*
@xref{voice_set_pan}.@*
@node voice_set_pan, voice_sweep_pan, voice_get_pan, Digital
@subsection voice_set_pan
@ftable @asis
@item @t{void voice_set_pan(int voice, int pan);}
Sets the pan position, ranging from 0 (left) to 255 (right).

@end ftable
See also:@*
@xref{Voice control}.@*
@xref{voice_get_pan}.@*
@xref{voice_sweep_pan}.@*
@node voice_sweep_pan, voice_stop_pan_sweep, voice_set_pan, Digital
@subsection voice_sweep_pan
@ftable @asis
@item @t{void voice_sweep_pan(int voice, int time, int endpan);}
Starts a pan sweep (left <-> right movement) from the current position to
the specified ending position, lasting for time milliseconds.

@end ftable
See also:@*
@xref{Voice control}.@*
@xref{voice_set_pan}.@*
@node voice_stop_pan_sweep, voice_set_echo, voice_sweep_pan, Digital
@subsection voice_stop_pan_sweep
@ftable @asis
@item @t{void voice_stop_pan_sweep(int voice);}
Interrupts a pan sweep operation.

@end ftable
See also:@*
@xref{voice_sweep_pan}.@*
@node voice_set_echo, voice_set_tremolo, voice_stop_pan_sweep, Digital
@subsection voice_set_echo
@ftable @asis
@item @t{void voice_set_echo(int voice, int strength, int delay);}
Sets the echo parameters for a voice (not currently implemented).

@end ftable
See also:@*
@xref{Voice control}.@*
@node voice_set_tremolo, voice_set_vibrato, voice_set_echo, Digital
@subsection voice_set_tremolo
@ftable @asis
@item @t{void voice_set_tremolo(int voice, int rate, int depth);}
Sets the tremolo parameters for a voice (not currently implemented).

@end ftable
See also:@*
@xref{Voice control}.@*
@node voice_set_vibrato, load_midi, voice_set_tremolo, Digital
@subsection voice_set_vibrato
@ftable @asis
@item @t{void voice_set_vibrato(int voice, int rate, int depth);}
Sets the vibrato parameters for a voice (not currently implemented).



@end ftable
See also:@*
@xref{Voice control}.@*
@node Music, Audio, Digital, API
@section Music routines (MIDI)

Allegro allows you to play MIDI files. MIDI files basically contain notes and
the type of instrument that is meant to play them, so they are usually very
small in size. However, it's up to the sound card of the end user to play the
notes, and sound cards have been historically known to have poor MIDI
performance (at least those oriented to the consumer market). Few consumer
cards feature decent MIDI playback. Still, as a game creator you can never be
sure if the music of your game will be played as you meant it, because it
totally depends on the hardware of the user.

For this reason Allegro also provides a DIGMID driver. This is a software
implementation of the so called Wavetable synthesis. Sound cards featuring this
store digital samples of real instruments at different pitches, interpolating
those that are not recorded, thus achieving a high sound quality. Implementing
this in software makes you sure that the quality you hear on your computer is
that which will be heard by end users using the same driver.

The disadvantage of the DIGMID driver is that it uses more CPU than simple
MIDI playback, and it steals some hardware voices from the sound card, which
might be more critical for the end user experience than the background music.
At the Allegro homepage (http://alleg.sourceforge.net/) you can find more
information about DIGMID and where to download digital samples for your MIDI
files.

@menu
* load_midi::
* destroy_midi::
* lock_midi::
* play_midi::
* play_looped_midi::
* stop_midi::
* midi_pause::
* midi_resume::
* midi_seek::
* get_midi_length::
* midi_out::
* load_midi_patches::
* midi_pos::
* midi_time::
* midi_loop_start::
* midi_msg_callback::
* load_ibk::
@end menu
@node load_midi, destroy_midi, voice_set_vibrato, Music
@subsection load_midi
@ftable @asis
@item @t{MIDI *load_midi(const char *filename);}
Loads a MIDI file (handles both format 0 and format 1). Example:
@example

MIDI *music;
music = load_midi("backmus.mid");
if (!music)
   abort_on_error("Couldn't load background music!");@end example


Returns a pointer to a MIDI structure, or NULL on error. Remember to free
this MIDI file later to avoid memory leaks.

@end ftable
See also:@*
@xref{destroy_midi}.@*
@xref{play_midi}.@*
@xref{get_midi_length}.@*
@xref{exmidi}.@*
@xref{MIDI}.@*
@node destroy_midi, lock_midi, load_midi, Music
@subsection destroy_midi
@ftable @asis
@item @t{void destroy_midi(MIDI *midi);}
Destroys a MIDI structure when you are done with it. It is safe to call 
this even when the MIDI file might be playing, because it checks and will 
kill it off if it is active. Use this to avoid memory leaks in your
program.

@end ftable
See also:@*
@xref{load_midi}.@*
@xref{exmidi}.@*
@xref{MIDI}.@*
@node lock_midi, play_midi, destroy_midi, Music
@subsection lock_midi
@ftable @asis
@item @t{void lock_midi(MIDI *midi);}
Under DOS, locks all the memory used by a MIDI file. You don't normally 
need to call this function because load_midi() does it for you.

@end ftable
See also:@*
@xref{load_midi}.@*
@xref{MIDI}.@*
@node play_midi, play_looped_midi, lock_midi, Music
@subsection play_midi
@ftable @asis
@item @t{int play_midi(MIDI *midi, int loop);}
Starts playing the specified MIDI file, first stopping whatever music was 
previously playing. If the loop flag is set to non-zero, the data will be
repeated until replaced with something else, otherwise it will stop at the
end of the file. Passing a NULL pointer will stop whatever music is
currently playing.

Returns non-zero if an error occurs (this may happen if a patch-caching
wavetable driver is unable to load the required samples, or at least it
might in the future when somebody writes some patch-caching wavetable
drivers :-)

@end ftable
See also:@*
@xref{install_sound}.@*
@xref{load_midi}.@*
@xref{play_looped_midi}.@*
@xref{stop_midi}.@*
@xref{midi_pause}.@*
@xref{midi_seek}.@*
@xref{midi_pos}.@*
@xref{midi_time}.@*
@xref{midi_msg_callback}.@*
@xref{exmidi}.@*
@xref{MIDI}.@*
@node play_looped_midi, stop_midi, play_midi, Music
@subsection play_looped_midi
@ftable @asis
@item @t{int play_looped_midi(MIDI *midi, int loop_start, int loop_end);}
Starts playing a MIDI file with a user-defined loop position. When the 
player reaches the loop end position or the end of the file (loop_end may 
be -1 to only loop at EOF), it will wind back to the loop start point. 
Both positions are specified in the same beat number format as the 
midi_pos variable.

The return value has the same meaning as that of play_midi(): non-zero if
an error occurs, zero otherwise.

@end ftable
See also:@*
@xref{play_midi}.@*
@xref{midi_pos}.@*
@xref{midi_loop_start}.@*
@xref{MIDI}.@*
@node stop_midi, midi_pause, play_looped_midi, Music
@subsection stop_midi
@ftable @asis
@item @t{void stop_midi();}
Stops whatever music is currently playing. This is the same thing as 
calling play_midi(NULL, FALSE).

@end ftable
See also:@*
@xref{play_midi}.@*
@xref{midi_pause}.@*
@node midi_pause, midi_resume, stop_midi, Music
@subsection midi_pause
@ftable @asis
@item @t{void midi_pause();}
Pauses the MIDI player.

@end ftable
See also:@*
@xref{play_midi}.@*
@xref{stop_midi}.@*
@xref{midi_resume}.@*
@xref{midi_seek}.@*
@xref{exmidi}.@*
@node midi_resume, midi_seek, midi_pause, Music
@subsection midi_resume
@ftable @asis
@item @t{void midi_resume();}
Resumes playback of a paused MIDI file.

@end ftable
See also:@*
@xref{midi_pause}.@*
@xref{exmidi}.@*
@node midi_seek, get_midi_length, midi_resume, Music
@subsection midi_seek
@ftable @asis
@item @t{int midi_seek(int target);}
Seeks to the given midi_pos in the current MIDI file. If the target is 
earlier in the file than the current midi_pos it seeks from the 
beginning; otherwise it seeks from the current position.

Returns zero if it could successfully seek to the requested position.
Otherwise, a return value of 1 means it stopped playing, and midi_pos is
set to the negative length of the MIDI file (so you can use this function
to determine the length of a MIDI file). A return value of 2 means the
MIDI file looped back to the start.

@end ftable
See also:@*
@xref{play_midi}.@*
@xref{midi_pos}.@*
@node get_midi_length, midi_out, midi_seek, Music
@subsection get_midi_length
@ftable @asis
@item @t{int get_midi_length(MIDI *midi);}
This function will simulate playing the given MIDI, from start to end, to
determine how long it takes to play. After calling this function, midi_pos
will contain the negative number of beats, and midi_time the length of the
midi, in seconds.

Note that any currently playing midi is stopped when you call this function.
Usually you would call it before play_midi, to get the length of the midi to
be played, like in this example:
@example

length = get_midi_length(my_midi);
play_midi(my_midi);
do @{
   pos = midi_time;
   textprintf_ex(screen, font, 0, 0, c, -1, "%d:%02d / %d:%02d\n",
      pos / 60, pos % 60, length / 60, length % 60);
   rest(100);
@} while(pos <= length);@end example


Returns the value of midi_time, the length of the midi.

@end ftable
See also:@*
@xref{load_midi}.@*
@xref{midi_time}.@*
@xref{midi_pos}.@*
@xref{exmidi}.@*
@xref{MIDI}.@*
@node midi_out, load_midi_patches, get_midi_length, Music
@subsection midi_out
@ftable @asis
@item @t{void midi_out(unsigned char *data, int length);}
Streams a block of MIDI commands into the player in real-time, allowing 
you to trigger notes, jingles, etc, over the top of whatever MIDI file is 
currently playing.

@end ftable
See also:@*
@xref{install_sound}.@*
@xref{load_midi_patches}.@*
@xref{midi_recorder}.@*
@node load_midi_patches, midi_pos, midi_out, Music
@subsection load_midi_patches
@ftable @asis
@item @t{int load_midi_patches();}
Forces the MIDI driver to load the entire set of patches ready for use. 
You will not normally need to call this, because Allegro automatically 
loads whatever data is required for the current MIDI file, but you must 
call it before sending any program change messages via the midi_out() 
command.

Returns non-zero if an error occurred.

@end ftable
See also:@*
@xref{install_sound}.@*
@xref{midi_out}.@*
@node midi_pos, midi_time, load_midi_patches, Music
@subsection midi_pos
@ftable @asis
@item @t{extern volatile long midi_pos;}
Stores the current position (beat number) in the MIDI file, or contains 
a negative number if no music is currently playing. Useful for 
synchronising animations with the music, and for checking whether a MIDI 
file has finished playing.

@end ftable
See also:@*
@xref{play_midi}.@*
@xref{midi_msg_callback}.@*
@xref{exmidi}.@*
@node midi_time, midi_loop_start, midi_pos, Music
@subsection midi_time
@ftable @asis
@item @t{extern volatile long midi_time;}
Contains the position in seconds in the currently playing midi. This is
useful if you want to display the current song position in seconds, not as
beat number.

@end ftable
See also:@*
@xref{play_midi}.@*
@xref{midi_pos}.@*
@xref{get_midi_length}.@*
@xref{exmidi}.@*
@node midi_loop_start, midi_msg_callback, midi_time, Music
@subsection midi_loop_start
@ftable @asis
@item @t{extern long midi_loop_start;}
@end ftable
@ftable @asis
@item @t{extern long midi_loop_end;}
The loop start and end points, set by the play_looped_midi() function. 
These may safely be altered while the music is playing, but you should be 
sure they are always set to sensible values (start < end). If you are 
changing them both at the same time, make sure to alter them in the right 
order in case a MIDI interrupt happens to occur in between your two 
writes! Setting these values to -1 represents the start and end of the 
file respectively.

@end ftable
See also:@*
@xref{play_looped_midi}.@*
@node midi_msg_callback, load_ibk, midi_loop_start, Music
@subsection midi_msg_callback
@ftable @asis
@item @t{extern void (*midi_msg_callback)(int msg, int byte1, int byte2);}
@end ftable
@ftable @asis
@item @t{extern void (*midi_meta_callback)(int type, const unsigned char *data, int length);}
@end ftable
@ftable @asis
@item @t{extern void (*midi_sysex_callback)(const unsigned char *data, int length);}
Hook functions allowing you to intercept MIDI player events. If set to 
anything other than NULL, these routines will be called for each MIDI 
message, meta-event, and system exclusive data block respectively. They 
will execute in an interrupt handler context, so all the code and data 
they use should be locked, and they must not call any operating system 
functions. In general you just use these routines to set some flags and 
respond to them later in your mainline code.

@end ftable
See also:@*
@xref{play_midi}.@*
@node load_ibk, play_audio_stream, midi_msg_callback, Music
@subsection load_ibk
@ftable @asis
@item @t{int load_ibk(char *filename, int drums);}
Reads in a .IBK patch definition file for use by the Adlib driver. If 
drums is set, it will load it as a percussion patch set, otherwise it 
will use it as a replacement set of General MIDI instruments. You may 
call this before or after initialising the sound code, or can simply set 
the ibk_file and ibk_drum_file variables in the configuration file to 
have the data loaded automatically. Note that this function has no effect 
on any drivers other than the Adlib one!

Returns non-zero on error.



@end ftable
See also:@*
@xref{install_sound}.@*
@node Audio, Recording, Music, API
@section Audio stream routines

The audio stream functions are for playing digital sounds that are too big 
to fit in a regular SAMPLE structure, either because they are huge files 
that you want to load in pieces as the data is required, or because you are 
doing something clever like generating the waveform on the fly.

You can think of an AUDIOSTREAM structure as a wrapper around two audio
buffers. The first thing you do is fill both buffers with sound data and let
Allegro play them. Once the first buffer has been played, the second starts,
and Allegro lets you know you have to fill the other one (i.e. graphics
double buffering applied to sounds too big to fit into memory).

The implementation of the sound buffers uses normal SAMPLE structures, so you
can use all the voice_*() functions to modify the audio streams. Read chapter
"Digital sample routines", section "Voice control" for a list of additional
functions you can use. Read chapter "Structures and types defined by Allegro"
for the internals of the AUDIOSTREAM structure.

@menu
* play_audio_stream::
* stop_audio_stream::
* get_audio_stream_buffer::
* free_audio_stream_buffer::
@end menu
@node play_audio_stream, stop_audio_stream, load_ibk, Audio
@subsection play_audio_stream
@ftable @asis
@item @t{AUDIOSTREAM *play_audio_stream(int len, int bits, int stereo, int freq, int vol, int pan);}
This function creates a new audio stream and starts playing it. The 
length is the size of each transfer buffer in sample frames (not bytes), 
where a sample frame is a single sample value for mono data or a pair of 
interleaved sample values (left first) for stereo data. The length should 
normally be (but doesn't have to be) a power of 2 somewhere around 1k in 
size. Larger buffers are more efficient and require fewer updates, but 
result in more latency between you providing the data and it actually 
being played.

The `bits' parameter must be 8 or 16. `freq' is the sample rate of the
data in Hertz. The `vol' and `pan' values use the same 0-255 ranges as the
regular sample playing functions. The `stereo' parameter should be set to
1 for stereo streams, or 0 otherwise.

If you want to adjust the pitch, volume, or panning of a stream once it is
playing, you can use the regular voice_*() functions with stream->voice
as a parameter. The format of the sample data is described in the SAMPLE
entry of the "Structures and types defined by Allegro" chapter. The formula
to get the size of the buffers in bytes could be:
@example

bytes = length * (bits / 8) * (stereo ? 2 : 1)@end example

Example:
@example

/* Create a 22KHz 8bit mono audio stream. */
stream = play_audio_stream(1024, 8, FALSE, 22050, 255, 128);
if (!stream)
   abort_on_error("Error creating audio stream!\n");@end example


This function returns a pointer to the audio stream or NULL if it could
not be created.

@end ftable
See also:@*
@xref{install_sound}.@*
@xref{get_audio_stream_buffer}.@*
@xref{stop_audio_stream}.@*
@xref{AUDIOSTREAM}.@*
@xref{Voice control}.@*
@xref{exstream}.@*
@xref{AUDIOSTREAM}.@*
@node stop_audio_stream, get_audio_stream_buffer, play_audio_stream, Audio
@subsection stop_audio_stream
@ftable @asis
@item @t{void stop_audio_stream(AUDIOSTREAM *stream);}
Destroys an audio stream when it is no longer required.

@end ftable
See also:@*
@xref{play_audio_stream}.@*
@xref{exstream}.@*
@xref{AUDIOSTREAM}.@*
@node get_audio_stream_buffer, free_audio_stream_buffer, stop_audio_stream, Audio
@subsection get_audio_stream_buffer
@ftable @asis
@item @t{void *get_audio_stream_buffer(AUDIOSTREAM *stream);}
You must call this function at regular intervals while an audio stream is 
playing, to provide the next buffer of sample data (the smaller the 
stream buffer size, the more often it must be called). This function should
not be called from a timer handler. Example:
@example

void *mem_chunk;
...
while (TRUE) @{
   ...
   mem_chunk = get_audio_stream_buffer(buffer);
   if (mem_chunk != NULL) @{
      /* Refill the stream buffer. */
   @}
@}@end example


If it returns NULL, the stream is still playing the previous lot of data,
so you don't need to do anything. If it returns a value, that is the
location of the next buffer to be played, and you should load the
appropriate number of samples (however many you specified when creating the
stream) to that address, for example using an fread() from a disk file.
After filling the buffer with data, call free_audio_stream_buffer() to
indicate that the new data is now valid.

@end ftable
See also:@*
@xref{play_audio_stream}.@*
@xref{free_audio_stream_buffer}.@*
@xref{exstream}.@*
@xref{AUDIOSTREAM}.@*
@node free_audio_stream_buffer, install_sound_input, get_audio_stream_buffer, Audio
@subsection free_audio_stream_buffer
@ftable @asis
@item @t{void free_audio_stream_buffer(AUDIOSTREAM *stream);}
Call this function after get_audio_stream_buffer() returns a non-NULL 
address, to indicate that you have loaded a new block of samples to that 
location and the data is now ready to be played. Example:
@example

mem_chunk = get_audio_stream_buffer(buffer);
if (mem_chunk != NULL) @{
   /* Refill the stream buffer. */
   ...
   free_audio_stream_buffer(buffer);
@}@end example




@end ftable
See also:@*
@xref{get_audio_stream_buffer}.@*
@xref{exstream}.@*
@xref{AUDIOSTREAM}.@*
@node Recording, File, Audio, API
@section Recording routines

Allegro provides routines to capture sound from the sound card, be it digital
samples or MIDI notes. Ideally this would allow you to create games where
basic speech recognition could be implemented, or voice messages in
multiplayer games over a network. However, many old sound cards are not full
duplex. This means, that the sound device can only be playing or recording,
but not both at the same time.

Any Windows 2000 or better machine comes with a full duplex sound card and
updated drivers. All MacOS X machines allow full duplex recording. Under Unix
your mileage may vary: you can have the right hardware for the task, but the
drivers might not support this feature. Under DOS you should forget about full
duplex altogether.

To find out if your system allows this feature, use the akaitest program,
distributed along with Allegro, in the `tests' directory.

@menu
* install_sound_input::
* remove_sound_input::
* get_sound_input_cap_bits::
* get_sound_input_cap_stereo::
* get_sound_input_cap_rate::
* get_sound_input_cap_parm::
* set_sound_input_source::
* start_sound_input::
* stop_sound_input::
* read_sound_input::
* digi_recorder::
* midi_recorder::
@end menu
@node install_sound_input, remove_sound_input, free_audio_stream_buffer, Recording
@subsection install_sound_input
@ftable @asis
@item @t{int install_sound_input(int digi, int midi);}
Initialises the sound recorder module. You must install the normal sound
playback system before calling this routine. The two card parameters should
use the same constants as install_sound(), including DIGI_NONE and
MIDI_NONE to disable parts of the module, or DIGI_AUTODETECT and
MIDI_AUTODETECT to guess the hardware.

This function returns zero on success, and any other value if the machine
or driver doesn't support sound recording.

@end ftable
See also:@*
@xref{install_sound}.@*
@xref{start_sound_input}.@*
@xref{midi_recorder}.@*
@xref{Standard config variables}.@*
@xref{DIGI_*/DOS}.@*
@xref{DIGI_*/Windows}.@*
@xref{DIGI_*/Unix}.@*
@xref{DIGI_*/BeOS}.@*
@xref{DIGI_*/QNX}.@*
@xref{DIGI_*/MacOSX}.@*
@xref{MIDI_*/DOS}.@*
@xref{MIDI_*/Windows}.@*
@xref{MIDI_*/Unix}.@*
@xref{MIDI_*/BeOS}.@*
@xref{MIDI_*/QNX}.@*
@xref{MIDI_*/MacOSX}.@*
@node remove_sound_input, get_sound_input_cap_bits, install_sound_input, Recording
@subsection remove_sound_input
@ftable @asis
@item @t{void remove_sound_input();}
Cleans up after you are finished with the sound input routines. You don't 
normally need to call this, because remove_sound() and/or allegro_exit() 
will do it for you.

@end ftable
See also:@*
@xref{install_sound_input}.@*
@xref{remove_sound}.@*
@xref{allegro_exit}.@*
@node get_sound_input_cap_bits, get_sound_input_cap_stereo, remove_sound_input, Recording
@subsection get_sound_input_cap_bits
@ftable @asis
@item @t{int get_sound_input_cap_bits();}
Checks which sample formats are supported by the current audio input 
driver, returning one of the bitfield values:
@example

0 = audio input not supported
8 = eight bit audio input is supported
16 = sixteen bit audio input is supported
24 = both eight and sixteen bit audio input are supported@end example

Example:
@example

cap = get_sound_input_cap_bits();
if (cap == 0) @{
   /* Ugh, no audio input supported? */
@} else @{
   if (cap & 8) @{
      /* We have eight bit audio input. */
   @}
   if (cap & 16) @{
      /* We have sixteen bit audio input. */
   @}
@}@end example


@end ftable
See also:@*
@xref{start_sound_input}.@*
@xref{get_sound_input_cap_parm}.@*
@xref{get_sound_input_cap_rate}.@*
@xref{get_sound_input_cap_stereo}.@*
@node get_sound_input_cap_stereo, get_sound_input_cap_rate, get_sound_input_cap_bits, Recording
@subsection get_sound_input_cap_stereo
@ftable @asis
@item @t{int get_sound_input_cap_stereo();}
Checks whether the current audio input driver is capable of stereo 
recording.

Returns non-zero if the driver is capable of stereo recording.

@end ftable
See also:@*
@xref{start_sound_input}.@*
@xref{get_sound_input_cap_parm}.@*
@xref{get_sound_input_cap_bits}.@*
@xref{get_sound_input_cap_rate}.@*
@node get_sound_input_cap_rate, get_sound_input_cap_parm, get_sound_input_cap_stereo, Recording
@subsection get_sound_input_cap_rate
@ftable @asis
@item @t{int get_sound_input_cap_rate(int bits, int stereo);}
Returns the maximum possible sample frequency for recording in the 
specified format, or zero if these settings are not supported. The bits
parameter is the number of bits of the audio, and stereo is a boolean
parameter. Pass zero for mono, non-zero for stereo input. Example:
@example

int max_freq;
...
/* What frequency can we record 8 bits mono at? */
max_freq = get_sound_input_cap_rate(8, 0);
if (max_freq > 22000) @{
   /* Ok, 22KHz and above is good enough. */
@}@end example


@end ftable
See also:@*
@xref{start_sound_input}.@*
@xref{get_sound_input_cap_parm}.@*
@xref{get_sound_input_cap_bits}.@*
@xref{get_sound_input_cap_stereo}.@*
@node get_sound_input_cap_parm, set_sound_input_source, get_sound_input_cap_rate, Recording
@subsection get_sound_input_cap_parm
@ftable @asis
@item @t{int get_sound_input_cap_parm(int rate, int bits, int stereo);}
Checks whether the specified recording frequency, number of bits, and 
mono/stereo mode are supported (and how) by the current audio driver.

The function returns one of the following possible values:
@example

0  = It is impossible to record in this format.
1  = Recording is possible, but audio output
     will be suspended.
2  = Recording is possible at the same time as
     playing other sounds (full duplex sound card).
-n = Sampling rate not supported, but rate 'n'
     would work instead.@end example


@end ftable
See also:@*
@xref{start_sound_input}.@*
@xref{get_sound_input_cap_bits}.@*
@xref{get_sound_input_cap_rate}.@*
@xref{get_sound_input_cap_stereo}.@*
@node set_sound_input_source, start_sound_input, get_sound_input_cap_parm, Recording
@subsection set_sound_input_source
@ftable @asis
@item @t{int set_sound_input_source(int source);}
Selects the audio input source. The parameter should be one of the values:
@example

SOUND_INPUT_MIC
SOUND_INPUT_LINE
SOUND_INPUT_CD@end example


The function returns zero on success, or -1 if the hardware does not
provide an input select register (ie. you have no control over the input
source).

@end ftable
See also:@*
@xref{start_sound_input}.@*
@node start_sound_input, stop_sound_input, set_sound_input_source, Recording
@subsection start_sound_input
@ftable @asis
@item @t{int start_sound_input(int rate, int bits, int stereo);}
Starts recording in the specified format, suspending audio playback as 
necessary if the card is not full duplex.

Returns the buffer size in bytes if successful, or zero on error.

@end ftable
See also:@*
@xref{install_sound_input}.@*
@xref{read_sound_input}.@*
@xref{stop_sound_input}.@*
@xref{digi_recorder}.@*
@xref{set_sound_input_source}.@*
@xref{get_sound_input_cap_parm}.@*
@xref{get_sound_input_cap_bits}.@*
@xref{get_sound_input_cap_rate}.@*
@xref{get_sound_input_cap_stereo}.@*
@node stop_sound_input, read_sound_input, start_sound_input, Recording
@subsection stop_sound_input
@ftable @asis
@item @t{void stop_sound_input();}
Stops audio recording, switching the card back into the normal playback 
mode.

@end ftable
See also:@*
@xref{start_sound_input}.@*
@node read_sound_input, digi_recorder, stop_sound_input, Recording
@subsection read_sound_input
@ftable @asis
@item @t{int read_sound_input(void *buffer);}
Retrieves the most recently recorded audio buffer into the specified 
location. The buffer size can be obtained by checking the return value
from start_sound_input(). You must be sure to call this
function at regular intervals during the recording (typically around 100 
times a second), or some data will be lost. If you are unable to do this 
often enough from the mainline code, use the digi_recorder() callback to 
store the waveform into a larger buffer of your own.

Note: many cards produce a click or popping sound when switching between
record and playback modes, so it is often a good idea to discard the
first buffer after you start a recording. The waveform is always stored
in unsigned format, with stereo data consisting of alternate left/right
samples.

The function will return non-zero if a buffer has been copied or zero if
no new data is yet available (you were too fast checking the input).

@end ftable
See also:@*
@xref{start_sound_input}.@*
@node digi_recorder, midi_recorder, read_sound_input, Recording
@subsection digi_recorder
@ftable @asis
@item @t{extern void (*digi_recorder)();}
If set, this function is called by the input driver whenever a new sample 
buffer becomes available, at which point you can use read_sound_input() 
to copy the data into a more permanent location. It runs in an interrupt
context, so it must execute very quickly, the code and all memory that it
touches must be locked, and you cannot call any operating system routines
or access disk files. This currently works only under DOS.

@end ftable
See also:@*
@xref{install_sound_input}.@*
@xref{start_sound_input}.@*
@node midi_recorder, get_executable_name, digi_recorder, Recording
@subsection midi_recorder
@ftable @asis
@item @t{extern void (*midi_recorder)(unsigned char data);}
If set, this function is called by the MIDI input driver whenever a new 
byte of MIDI data becomes available. It runs in an interrupt context, so 
it must execute very quickly and all the code/data must be locked. This
currently works only under DOS and Windows.



@end ftable
See also:@*
@xref{install_sound_input}.@*
@xref{midi_out}.@*
@node File, Datafile, Recording, API
@section File and compression routines

The following routines implement a fast buffered file I/O system, which 
supports the reading and writing of compressed files using a ring buffer 
algorithm based on the LZSS compressor by Haruhiko Okumura. This does not 
achieve quite such good compression as programs like zip and lha, but 
unpacking is very fast and it does not require much memory. Packed files 
always begin with the 32-bit value F_PACK_MAGIC, and autodetect files with 
the value F_NOPACK_MAGIC.

The following FA_* flags are guaranteed to work:
@example

FA_NONE           - Exclude files that have any attribute set
FA_RDONLY         - Directory entries that are unwritable for current user
FA_HIDDEN         - Hidden flag
FA_DIREC          - Directories
FA_SYSTEM         - Files with system flag set (DOS/Windows only)
FA_LABEL          - Files with volume label flag set (DOS/Windows only)
FA_ARCH           - Files with archive flag set (DOS/Windows only)
FA_ALL            - Match all attributes@end example

Do not use any other flags from DOS/Windows or your code will not compile on 
another platform.
FA_RDONLY is for directory entries with read-only flag on DOS-like systems or 
unwritable by current user on Unix-like systems. Hidden files are directory
entries that have the hidden flag set (DOS/Windows) or have names starting with
'.' (UNIX, excluding '.' and '..').
Flags can be combined using '|' (binary OR operator).

When passed to the functions as the 'attrib' parameter, these flags 
represent an upper set in which the actual flag set of a matching file must 
be included. That is, in order for a file to be matching, its attributes 
may contain any of the specified flags but must not contain any of the 
unspecified flags. In other words, you explicitly exclude the flags that you
do not specify. Thus if you pass 'FA_DIREC | FA_RDONLY', normal files 
and directories will be included as well as read-only files and 
directories, but not hidden files and directories. Similarly, if you pass 
'FA_ARCH' then both archived and non-archived files will be included. If
FA_NONE is passed all attributes are excluded and only files with no attributes
are returned. Conversely, if you pass FA_ALL, no attributes are excluded so all
files are returned (which is what you would usually want).

Functions which accept wildcards as file names support the meta characters
`*' (which means, zero or any quantity of characters) and `?' (which means
any character, but only one).

@menu
* get_executable_name::
* fix_filename_case::
* fix_filename_slashes::
* canonicalize_filename::
* make_absolute_filename::
* make_relative_filename::
* is_relative_filename::
* replace_filename::
* replace_extension::
* append_filename::
* get_filename::
* get_extension::
* put_backslash::
* file_exists::
* exists::
* file_size_ex::
* file_time::
* delete_file::
* for_each_file_ex::
* al_findfirst::
* al_findnext::
* al_findclose::
* al_ffblk_get_size::
* find_allegro_resource::
* set_allegro_resource_path::
* packfile_password::
* pack_fopen::
* pack_fopen_vtable::
* pack_fclose::
* pack_fseek::
* pack_feof::
* pack_ferror::
* pack_getc::
* pack_ungetc::
* pack_putc::
* pack_igetw::
* pack_iputw::
* pack_igetl::
* pack_iputl::
* pack_mgetw::
* pack_mputw::
* pack_mgetl::
* pack_mputl::
* pack_fread::
* pack_fwrite::
* pack_fgets::
* pack_fputs::
* pack_fopen_chunk::
* pack_fclose_chunk::
* create_lzss_pack_data::
* free_lzss_pack_data::
* lzss_write::
* create_lzss_unpack_data::
* free_lzss_unpack_data::
* lzss_read::
@end menu
@node get_executable_name, fix_filename_case, midi_recorder, File
@subsection get_executable_name
@ftable @asis
@item @t{void get_executable_name(char *buf, int size);}
Fills `buf' with the full path to the current executable, writing at most
`size' bytes.  This generally comes from `argv[0]' but on Unix systems it
tries to get the information from the `/proc' filesystem first, searching
the directories specified in `$PATH' if necessary. If this fails too, it
tries to find the executable name from the output of the `ps' command,
using `argv[0]' only as a last resort if all other options fail. Example:
@example

char name[200];
...
get_executable_name(name, sizeof(name));
allegro_message("Running `%s'\n", name);@end example


@end ftable
@node fix_filename_case, fix_filename_slashes, get_executable_name, File
@subsection fix_filename_case
@ftable @asis
@item @t{char *fix_filename_case(char *path);}
Converts the filename stored in `path' to a standardised case. On DOS
platforms, they will be entirely uppercase. On other platforms this
function doesn't do anything. Example:
@example

get_executable_name(name, sizeof(name));
fix_filename_case(name);
allegro_message("Running `%s'\n", name);@end example


Returns a copy of the `path' parameter.

@end ftable
See also:@*
@xref{fix_filename_slashes}.@*
@xref{canonicalize_filename}.@*
@node fix_filename_slashes, canonicalize_filename, fix_filename_case, File
@subsection fix_filename_slashes
@ftable @asis
@item @t{char *fix_filename_slashes(char *path);}
Converts all the directory separators in the filename stored in `path' to
a standard character. On DOS and Windows platforms, this is a backslash.
On most other platforms this is a slash. Example:
@example

char buf[200] = "c:/dos\\backup/weirdo\\test";
...
fix_filename_slashes(buf);
/* Under DOS we would have c:\dos\backup\weirdo\test.
   Under Unix we would have c:/dos/backup/weirdo/test. */@end example


Returns a copy of the `path' parameter.

@end ftable
See also:@*
@xref{fix_filename_case}.@*
@xref{canonicalize_filename}.@*
@node canonicalize_filename, make_absolute_filename, fix_filename_slashes, File
@subsection canonicalize_filename
@ftable @asis
@item @t{char *canonicalize_filename(char *dest, const char *filename, int size);}
Converts any filename into its canonical form, i.e. the minimal absolute
filename describing the same file and fixing incorrect forward/backward
slashes for the current platform, storing at most `size' bytes into the
`dest' buffer. You can use the same buffer both as input and output
because Allegro internally works on a copy of the input before touching
`dest'. Example:
@example

char buf[256];
...
canonicalize_filename(buf, "~/../s22/..\\t3st///hi.c",
                      sizeof(buf));
/* Running this under Unix would
   return: /home/t3st/hi.c */
@end example

Note that this function won't work as expected if the path to canonicalize
comes from another platform (eg. a "c:\something" path will canonicalize
into something really wrong under Unix: "/current/path/c:/something").

Returns a copy of the `dest' parameter.

@end ftable
See also:@*
@xref{fix_filename_case}.@*
@xref{fix_filename_slashes}.@*
@node make_absolute_filename, make_relative_filename, canonicalize_filename, File
@subsection make_absolute_filename
@ftable @asis
@item @t{char *make_absolute_filename(char *dest, const char *path, const char *filename, int size);}
Makes an absolute filename from an absolute path and a relative filename,
storing at most `size' bytes into the `dest' buffer. This is like calling
replace_filename() and then canonicalize_filename(). Example:
@example

char buf[256];
...
make_absolute_filename(buf, "/usr/games/",
                       "../temp.txt", sizeof(buf));
/* This would create /usr/temp.txt */@end example


Returns a copy of the `dest' parameter.

@end ftable
See also:@*
@xref{make_relative_filename}.@*
@xref{is_relative_filename}.@*
@xref{replace_filename}.@*
@xref{canonicalize_filename}.@*
@node make_relative_filename, is_relative_filename, make_absolute_filename, File
@subsection make_relative_filename
@ftable @asis
@item @t{char *make_relative_filename(char *dest, const char *path, const char *filename, int size);}
Attempts to make a relative filename from an absolute path and an absolute
filename, storing at most `size' bytes into the `dest' buffer. This
function won't work if the paths are not canonical under the current
platform (see canonicalize_filename()). Also, `dest' cannot be used as
input value for `path' or `filename'. Example:
@example

char base[] = "/long/absolute/path/program.exe";
char user_input[] = "/nice/and/short.txt";
...
make_relative_filename(buf, base, user_input, sizeof(buf));
/* Under Unix buf would contain:
   ../../../nice/and/short.txt */@end example


Returns a copy of the `dest' parameter if it succeeds or NULL if it fails
(eg. under DOS, one path starts with "C:\" and another with "A:\").

@end ftable
See also:@*
@xref{make_absolute_filename}.@*
@xref{is_relative_filename}.@*
@xref{canonicalize_filename}.@*
@node is_relative_filename, replace_filename, make_relative_filename, File
@subsection is_relative_filename
@ftable @asis
@item @t{int is_relative_filename(const char *filename);}
Returns TRUE if the filename is relative or FALSE if it is absolute. Note
that an absolute filename under DOS (with a device separator) will be
considered as relative under Unix, because there absolute paths always
start with a slash.

@end ftable
See also:@*
@xref{make_absolute_filename}.@*
@xref{make_relative_filename}.@*
@node replace_filename, replace_extension, is_relative_filename, File
@subsection replace_filename
@ftable @asis
@item @t{char *replace_filename(char *dest, const char *path,  const char *filename, int size);}
Replaces the specified path+filename with a new filename tail, storing 
at most `size' bytes into the `dest' buffer. You can use the same buffer
both as input and output because Allegro internally works on a copy of
the input before touching `dest'. Example:
@example

char name[200];
...
get_executable_name(name, sizeof(name));
replace_filename(name, name, "sound.dat", sizeof(name));@end example


Returns a copy of the `dest' parameter.

@end ftable
See also:@*
@xref{get_filename}.@*
@xref{replace_extension}.@*
@xref{append_filename}.@*
@xref{Available, Available Allegro examples}.@*
@node replace_extension, append_filename, replace_filename, File
@subsection replace_extension
@ftable @asis
@item @t{char *replace_extension(char *dest, const char *filename,  const char *ext, int size);}
Replaces the specified filename+extension with a new extension tail,
storing at most `size' bytes into the `dest' buffer. If the filename
doesn't have any extension at all, `ext' will be appended to it, adding
a dot character if needed. You can use the same buffer both as input and
output because Allegro internally works on a copy of the input before
touching `dest'. Example:
@example

replace_extension(buf, "C:\\game\\prog.exe",
                  "dat", sizeof(buf));@end example


Returns a copy of the `dest' parameter.

@end ftable
See also:@*
@xref{get_extension}.@*
@xref{replace_filename}.@*
@node append_filename, get_filename, replace_extension, File
@subsection append_filename
@ftable @asis
@item @t{char *append_filename(char *dest, const char *path,  const char *filename, int size);}
Concatenates the specified filename onto the end of the specified path, 
storing at most `size' bytes into the `dest' buffer. If `path' doesn't
have a trailing path separator, the function will append one if needed.
You can use the same buffer both as input and output because Allegro
internally works on a copy of the input before touching `dest'. Example:
@example

append_filename(buf, "/home/user",
                "prog.bin", sizeof(buf));@end example


Returns a copy of the `dest' parameter.

@end ftable
See also:@*
@xref{replace_filename}.@*
@node get_filename, get_extension, append_filename, File
@subsection get_filename
@ftable @asis
@item @t{char *get_filename(const char *path);}
Finds out the filename portion of a completely specified file path. Both
`\' and `/' are recognized as directory separators under DOS and Windows.
However, only `/' is recognized as directory separator under other
platforms. Example:
@example

get_executable_name(name, sizeof(name));
allegro_message("Running `%s'\n", get_filename(name));
@end example

Note that Allegro won't perform any IO operations during the verification.
This means that if you have `/a/path/like/this/', which doesn't have a
filename, the function will return a pointer to the trailing null
character. However, if you have `/a/path/like/this', Allegro will return
a pointer to `this', even if it is a valid directory.

Returns a pointer to the portion of `path' where the filename starts, or
the beginning of `path' if no valid filename is found (eg. you are
processing a path with backslashes under Unix).

@end ftable
See also:@*
@xref{get_extension}.@*
@xref{put_backslash}.@*
@xref{replace_filename}.@*
@xref{exmidi}.@*
@node get_extension, put_backslash, get_filename, File
@subsection get_extension
@ftable @asis
@item @t{char *get_extension(const char *filename);}
Finds out the extension of the filename (with or without path
information). Example:
@example

get_executable_name(name, sizeof(name));
allegro_message("The binary has the extension `%s'\n",
                get_extension(name));@end example


Returns a pointer to the portion of `filename' where the extension starts,
or a pointer to the trailing null character if there is no filename or it
doesn't have extension.

@end ftable
See also:@*
@xref{get_filename}.@*
@xref{put_backslash}.@*
@xref{replace_extension}.@*
@node put_backslash, file_exists, get_extension, File
@subsection put_backslash
@ftable @asis
@item @t{void put_backslash(char *filename);}
If the last character of the filename is not a `\', `/', `#' or a device
separator (ie. `:' under DOS), this routine will concatenate either a `\'
or `/' on to it (depending on the platform). Note: ignore the function
name, it's out of date.

@end ftable
See also:@*
@xref{get_extension}.@*
@xref{get_filename}.@*
@node file_exists, exists, put_backslash, File
@subsection file_exists
@ftable @asis
@item @t{int file_exists(const char *filename, int attrib, int *aret);}
Checks whether a file matching the given name and attributes (see
beginning of this chapter) exists. If `aret' is not NULL, it will be set
to the attributes of the matching file. Example:
@example

/* Check for a normal file. */
if (file_exists("franken.dat", 0, NULL))
   allegro_message("It is alive!\n");@end example


Returns non-zero if the file exists, or zero if it doesn't or the
specified attributes mask it out.

@end ftable
See also:@*
@xref{exists}.@*
@xref{file_size_ex}.@*
@xref{file_time}.@*
@node exists, file_size_ex, file_exists, File
@subsection exists
@ftable @asis
@item @t{int exists(const char *filename);}
Shortcut version of file_exists(), which checks for normal files, which 
may have the archive or read-only bits set, but are not hidden, 
directories, system files, etc.

Returns non-zero if the file exists, or zero if it doesn't.

@end ftable
See also:@*
@xref{file_exists}.@*
@xref{file_size_ex}.@*
@xref{file_time}.@*
@node file_size_ex, file_time, exists, File
@subsection file_size_ex
@ftable @asis
@item @t{uint64_t file_size_ex(const char *filename);}
Returns the size of a file, in bytes. If the file does not exist or an 
error occurs, it will return zero and store the system error code in 
errno.

@end ftable
See also:@*
@xref{file_exists}.@*
@xref{file_time}.@*
@xref{expackf}.@*
@node file_time, delete_file, file_size_ex, File
@subsection file_time
@ftable @asis
@item @t{time_t file_time(const char *filename);}
Returns the modification time (number of seconds since 00:00:00 GMT 
1/1/1970) of a file. If the file does not exist or an error occurs, it 
will return zero and store the system error code in errno.

@end ftable
See also:@*
@xref{file_exists}.@*
@xref{file_size_ex}.@*
@node delete_file, for_each_file_ex, file_time, File
@subsection delete_file
@ftable @asis
@item @t{int delete_file(const char *filename);}
Removes a file from the disk. You can't delete directories, though.

Returns zero on success, non-zero on failure.

@end ftable
@node for_each_file_ex, al_findfirst, delete_file, File
@subsection for_each_file_ex
@ftable @asis
@item @t{int for_each_file_ex(const char *name, int in_attrib, int out_attrib, int (*callback)(const char *filename, int attrib, void *param), void *param);}
Finds all the files on disk which match the given wildcard specification
and file attributes, and executes callback() once for each. Basically, this
is a convenient wrapper around al_findfirst(), al_findnext() and
al_findclose(). `in_attrib' is a bitmask specifying the attributes the
files must carry, `out_attrib' is a bitmask specifying the attributes the
files must not carry; attributes which are not specified in either bitmasks
are not taken into account for deciding whether callback() is invoked or
not.

The callback function will be passed three arguments: the first is a string
which contains the completed filename (exactly the same string you passed
to for_each_file_ex() but with meta characters), the second is the actual
attributes of the file, and the third is a void pointer which is simply a
copy of `param' (you can use this for whatever you like). The callback must
return zero to let the enumeration proceed, or any non-zero value to stop
it. If an error occurs, the error code will be stored in `errno' but the
enumeration won't stop. Example:
@example

int show_name(const char *filename, int attrib, void *param)
@{
   allegro_message("Caught `%s', attribs %d\n",
                   filename, attrib);
   return 0;
@}
...
   count = for_each_file_ex("data/level*", FA_DIREC,
                            0, show_name, 0);
   allegro_message("%d game directories\n", count);@end example


Returns the number of successful calls made to callback(), that is, the
number of times callback() was called and returned 0.

@end ftable
See also:@*
@xref{al_findfirst}.@*
@xref{al_findnext}.@*
@xref{al_findclose}.@*
@node al_findfirst, al_findnext, for_each_file_ex, File
@subsection al_findfirst
@ftable @asis
@item @t{int al_findfirst(const char *pattern, struct al_ffblk *info, int attrib);}
Low-level function for searching files. This function finds the first 
file which matches the given wildcard specification and file attributes 
(see above). The information about the file (if any) will be put in the 
al_ffblk structure which you have to provide. The al_ffblk structure 
looks like:
@example

struct al_ffblk
@{
   int attrib;       - actual attributes of the file found
   time_t time;      - modification time of file
   char name[512];   - name of file
@};
@end example

There is some other stuff in the structure as well, but it is there for 
internal use only. Example:
@example

struct al_ffblk info;

if (al_findfirst("*.pcx", &info, FA_ALL) != 0) @{
   /* Tell user there are no PCX files. */
   return;
@}@end example


The function returns non-zero if no match is found or if an error occurred
and, in the latter case, sets `errno' accordingly. It returns zero if a
match is found, allocating some memory for internal use in the structure.
Therefore you have to close your search when you are finished to avoid
memory leaks in your program.

@end ftable
See also:@*
@xref{al_findnext}.@*
@xref{al_findclose}.@*
@xref{al_ffblk_get_size}.@*
@xref{al_ffblk}.@*
@node al_findnext, al_findclose, al_findfirst, File
@subsection al_findnext
@ftable @asis
@item @t{int al_findnext(struct al_ffblk *info);}
This finds the next file in a search started by al_findfirst(). Example:
@example

if (al_findfirst("*.pcx", &info, 0) != 0)
   return;

do @{
   /* Do something useful here with info.name. */
@} while (al_findnext(&info) == 0);

al_findclose(&info);@end example


Returns zero if a match is found, non-zero if none is found or if an
error occurred and, in the latter case, sets errno accordingly.

@end ftable
See also:@*
@xref{al_findfirst}.@*
@xref{al_findclose}.@*
@xref{al_ffblk}.@*
@node al_findclose, al_ffblk_get_size, al_findnext, File
@subsection al_findclose
@ftable @asis
@item @t{void al_findclose(struct al_ffblk *info);}
This closes a previously opened search with al_findfirst(). You need to
call this on all successfully opened searches to avoid memory leaks in
your program.

@end ftable
See also:@*
@xref{al_findfirst}.@*
@xref{al_findnext}.@*
@xref{al_ffblk}.@*
@node al_ffblk_get_size, find_allegro_resource, al_findclose, File
@subsection al_ffblk_get_size
@ftable @asis
@item @t{uint64_t al_ffblk_get_size(struct al_ffblk *info);}
This returns the size of the file returned by al_findfirst or al_findnext.

@end ftable
See also:@*
@xref{al_findfirst}.@*
@xref{al_findnext}.@*
@xref{al_ffblk}.@*
@xref{al_ffblk}.@*
@node find_allegro_resource, set_allegro_resource_path, al_ffblk_get_size, File
@subsection find_allegro_resource
@ftable @asis
@item @t{int find_allegro_resource(char *dest, const char *resource,  const char *ext, const char *datafile,  const char *objectname, const char *envvar,  const char *subdir, int size);}
Searches for a support file, eg. `allegro.cfg' or `language.dat'. Passed a
resource string describing what you are looking for, along with extra 
optional information such as the default extension, what datafile to look 
inside, what the datafile object name is likely to be, any special 
environment variable to check, and any subdirectory that you would like 
to check as well as the default location, this function looks in a hell 
of a lot of different places :-). Pass NULL for the parameters you are not
using.

Check the documentation chapter specific to your platform for information
on additional paths this function might search for. Also, don't forget
about set_allegro_resource_path() to extend the searches. Example:
@example

char path[256];
int ret;
ret = find_allegro_resource(path, "scores.cfg", NULL, NULL,
                            NULL, NULL, NULL, sizeof(path));
if (ret == 0) @{
   /* Found system wide scores file. */
@} else @{
   /* No previous scores, create our own file. */
@}@end example


Returns zero on success, and stores a full path to the file (at most size
bytes) into the dest buffer.

@end ftable
See also:@*
@xref{set_allegro_resource_path}.@*
@node set_allegro_resource_path, packfile_password, find_allegro_resource, File
@subsection set_allegro_resource_path
@ftable @asis
@item @t{int set_allegro_resource_path(int priority, const char *path);}
Sometimes Allegro doesn't look in enough places to find a resource. For
those special cases, you can call this function before loading your
resource with additional paths to search for. You set up the priorities,
higher numbers are searched for first. To modify an already setup path,
call this function with the same priority and the new path. To remove an
already setup path, call this function with the priority of the path and
NULL as the path parameter. Example:
@example

set_allegro_resource_path(10, "my_game/configs");
set_allegro_resource_path(0, "users/configs/");
set_allegro_resource_path(-45, "temp");
@end example

These custom paths will be valid until you call allegro_exit(). You can
call this function before install_allegro(), but after set_uformat() if
you want to use a text encoding format other than the default.

Returns non-zero on success, zero if the path could not be added or you
wanted to remove a path and the priority used didn't have any associated
path. Modification of existing paths always succeeds.

@end ftable
See also:@*
@xref{find_allegro_resource}.@*
@node packfile_password, pack_fopen, set_allegro_resource_path, File
@subsection packfile_password
@ftable @asis
@item @t{void packfile_password(const char *password);}
Sets the encryption password to be used for all read/write operations
on files opened in future using Allegro's packfile functions (whether
they are compressed or not), including all the save, load and config
routines. Files written with an encryption password cannot be read
unless the same password is selected, so be careful: if you forget the
key, nobody can make your data come back again! Pass NULL or an empty
string to return to the normal, non-encrypted mode. If you are using
this function to prevent people getting access to your datafiles, be
careful not to store an obvious copy of the password in your executable:
if there are any strings like "I'm the password for the datafile", it
would be fairly easy to get access to your data :-)

Note #1: when writing a packfile, you can change the password to whatever
you want after opening the file, without affecting the write operation.
On the contrary, when writing a sub-chunk of a packfile, you must make
sure that the password that was active at the time the sub-chunk was
opened is still active before closing the sub-chunk. This is guaranteed
to be true if you didn't call the packfile_password() routine in the
meantime. Read operations, either on packfiles or sub-chunks, have no
such restriction.

Note #2: as explained above, the password is used for all read/write
operations on files, including for several functions of the library that
operate on files without explicitly using packfiles (e.g. load_bitmap()).
The unencrypted mode is mandatory in order for those functions to work.
Therefore remember to call packfile_password(NULL) before using them if
you previously changed the password. As a rule of thumb, always call
packfile_password(NULL) when you are done with operations on packfiles.
The only exception to this is custom packfiles created with
pack_fopen_vtable().

@end ftable
See also:@*
@xref{pack_fopen}.@*
@xref{load_datafile}.@*
@xref{pack_fopen_vtable}.@*
@node pack_fopen, pack_fopen_vtable, packfile_password, File
@subsection pack_fopen
@ftable @asis
@item @t{PACKFILE *pack_fopen(const char *filename, const char *mode);}
Opens a file according to mode, which may contain any of the flags:

@itemize @bullet
@item 
`r' - open file for reading.
@item 
`w' - open file for writing, overwriting any existing data.
@item 
`p' - open file in packed mode. Data will be compressed as it is
written to the file, and automatically uncompressed during read 
operations. Files created in this mode will produce garbage if 
they are read without this flag being set. 
@item 
`!' - open file for writing in normal, unpacked mode, but add the
value F_NOPACK_MAGIC to the start of the file, so that it can 
later be opened in packed mode and Allegro will automatically 
detect that the data does not need to be decompressed.
@end itemize

Instead of these flags, one of the constants F_READ, F_WRITE, 
F_READ_PACKED, F_WRITE_PACKED or F_WRITE_NOPACK may be used as the mode 
parameter.

The packfile functions also understand several "magic" filenames that are 
used for special purposes. These are:

@itemize @bullet
@item 
`#' - read data that has been appended to your executable file with
the exedat utility, as if it was a regular independent disk file.
@item 
`filename.dat#object_name' - open a specific object from a datafile,
and read from it as if it was a regular file. You can treat nested 
datafiles exactly like a normal directory structure, for example 
you could open `filename.dat#graphics/level1/mapdata'.
@item 
`#object_name' - combination of the above, reading an object from a
datafile that has been appended onto your executable.
@end itemize

With these special filenames, the contents of a datafile object or 
appended file can be read in an identical way to a normal disk file, so 
any of the file access functions in Allegro (eg. load_pcx() and 
set_config_file()) can be used to read from them. Note that you can't 
write to these special files, though: the fake file is read only. Also, 
you must save your datafile uncompressed or with per-object compression 
if you are planning on loading individual objects from it (otherwise 
there will be an excessive amount of seeking when it is read).

Finally, be aware that the special Allegro object types aren't the same
format as the files you import the data from. When you import data like
bitmaps or samples into the grabber, they are converted into a special
Allegro-specific format, but the `#' marker file syntax reads the objects
as raw binary chunks. This means that if, for example, you want to use 
load_pcx() to read an image from a datafile, you should import it as a
binary block rather than as a BITMAP object.

Example:
@example

PACKFILE *input_file;

input_file = pack_fopen("scores.dat", "rp");
if (!input_file)
   abort_on_error("Couldn't read `scores.dat'!");@end example


On success, pack_fopen() returns a pointer to a PACKFILE structure, and on
error it returns NULL and stores an error code in `errno'. An attempt to
read a normal file in packed mode will cause `errno' to be set to EDOM.

@end ftable
See also:@*
@xref{pack_fclose}.@*
@xref{pack_fopen_chunk}.@*
@xref{packfile_password}.@*
@xref{pack_fread}.@*
@xref{pack_getc}.@*
@xref{file_select_ex}.@*
@xref{pack_fopen_vtable}.@*
@xref{expackf}.@*
@xref{PACKFILE}.@*
@node pack_fopen_vtable, pack_fclose, pack_fopen, File
@subsection pack_fopen_vtable
@ftable @asis
@item @t{PACKFILE *pack_fopen_vtable(const PACKFILE_VTABLE *vtable, void *userdata);}
Creates a new packfile structure that uses the functions specified in
the vtable instead of the standard functions. The data pointer by `vtable'
and `userdata' must remain available for the lifetime of the created
packfile.

While the created packfile structure can be used with other Allegro
functions, there are two limitations. First, opening chunks using
pack_fopen_chunk() on top of the returned packfile is not possible at this
time. And packfile_password() does not have any effect on packfiles opened
with pack_fopen_vtable().

On success, it returns a pointer to a PACKFILE structure, and on error it
returns NULL and stores an error code in `errno'.

@end ftable
See also:@*
@xref{pack_fopen}.@*
@xref{pack_fopen_chunk}.@*
@xref{packfile_password}.@*
@xref{expackf}.@*
@xref{PACKFILE}.@*
@xref{PACKFILE_VTABLE}.@*
@node pack_fclose, pack_fseek, pack_fopen_vtable, File
@subsection pack_fclose
@ftable @asis
@item @t{int pack_fclose(PACKFILE *f);}
Closes the stream `f' previously opened with pack_fopen() or
pack_fopen_vtable(). After you have closed the stream, performing
operations on it will yield errors in your application (e.g. crash it) or
even block your OS.

Returns zero on success. On error, returns an error code which is also
stored in `errno'. This function can fail only when writing to files: if
the file was opened in read mode, it will always succeed.

@end ftable
See also:@*
@xref{pack_fopen}.@*
@xref{pack_fopen_vtable}.@*
@xref{packfile_password}.@*
@xref{expackf}.@*
@xref{PACKFILE}.@*
@node pack_fseek, pack_feof, pack_fclose, File
@subsection pack_fseek
@ftable @asis
@item @t{int pack_fseek(PACKFILE *f, int offset);}
Moves the position indicator of the stream `f'. Unlike the standard fseek()
function, this only supports forward movements relative to the current
position and in read-only streams, so don't use negative offsets. Note that
seeking is very slow when reading compressed files, and so should be
avoided unless you are sure that the file is not compressed. Example:
@example

input_file = pack_fopen("data.bin", "r");
if (!input_file)
   abort_on_error("Couldn't open binary data!");
/* Skip some useless header before reading data. */
pack_fseek(input_file, 32);@end example


Returns zero on success or a negative number on error, storing the error
code in `errno'.

@end ftable
See also:@*
@xref{pack_fopen}.@*
@xref{pack_fopen_chunk}.@*
@xref{expackf}.@*
@xref{PACKFILE}.@*
@node pack_feof, pack_ferror, pack_fseek, File
@subsection pack_feof
@ftable @asis
@item @t{int pack_feof(PACKFILE *f);}
Finds out if you have reached the end of the file. It does not wait for you
to attempt to read beyond the end of the file, contrary to the ISO C feof()
function. The only way to know whether you have read beyond the end of the
file is to check the return value of the read operation you use (and be
wary of pack_*getl() as EOF is also a valid return value with these
functions).

Returns non-zero if you are at the end of the file, zero otherwise.

@end ftable
See also:@*
@xref{pack_fopen}.@*
@xref{pack_fopen_chunk}.@*
@xref{pack_ferror}.@*
@xref{PACKFILE}.@*
@node pack_ferror, pack_getc, pack_feof, File
@subsection pack_ferror
@ftable @asis
@item @t{int pack_ferror(PACKFILE *f);}
Since EOF is used to report errors by some functions, it's often better to
use the pack_feof() function to check explicitly for end of file and
pack_ferror() to check for errors. Both functions check indicators that
are part of the internal state of the stream to detect correctly the
different situations.

Returns nonzero if the error indicator for the stream is set, meaning
that an error has occurred during a previous operation on the stream.

@end ftable
See also:@*
@xref{pack_fopen}.@*
@xref{pack_fopen_chunk}.@*
@xref{PACKFILE}.@*
@node pack_getc, pack_ungetc, pack_ferror, File
@subsection pack_getc
@ftable @asis
@item @t{int pack_getc(PACKFILE *f);}
Returns the next character from the stream `f', or EOF if the end of the
file has been reached.

@end ftable
See also:@*
@xref{pack_fopen}.@*
@xref{pack_fopen_chunk}.@*
@xref{PACKFILE}.@*
@node pack_ungetc, pack_putc, pack_getc, File
@subsection pack_ungetc
@ftable @asis
@item @t{int pack_ungetc(int c, PACKFILE *f);}
Puts a character back to the file's input buffer. Like with ungetc from
libc, only a single push back is guaranteed.

Note: pack_fgets internally uses pack_ungetc, so never use pack_ungetc
directly after using pack_fgets on a PACKFILE.

Returns c on success, or EOF on error.

@end ftable
See also:@*
@xref{pack_getc}.@*
@xref{pack_fgets}.@*
@xref{PACKFILE}.@*
@node pack_putc, pack_igetw, pack_ungetc, File
@subsection pack_putc
@ftable @asis
@item @t{int pack_putc(int c, PACKFILE *f);}
Puts a character in the stream f.

Returns the character written on success, or EOF on error.

@end ftable
See also:@*
@xref{pack_fopen}.@*
@xref{pack_fopen_chunk}.@*
@xref{PACKFILE}.@*
@node pack_igetw, pack_iputw, pack_putc, File
@subsection pack_igetw
@ftable @asis
@item @t{int pack_igetw(PACKFILE *f);}
Like pack_getc, but reads a 16-bit word from a file, using Intel byte
ordering (least significant byte first, a.k.a. little-endian).

@end ftable
See also:@*
@xref{pack_getc}.@*
@xref{PACKFILE}.@*
@node pack_iputw, pack_igetl, pack_igetw, File
@subsection pack_iputw
@ftable @asis
@item @t{int pack_iputw(int c, PACKFILE *f);}
Like pack_putc, but writes a 16-bit word to a file, using Intel byte
ordering (least significant byte first, a.k.a. little-endian).

@end ftable
See also:@*
@xref{pack_putc}.@*
@xref{PACKFILE}.@*
@node pack_igetl, pack_iputl, pack_iputw, File
@subsection pack_igetl
@ftable @asis
@item @t{long pack_igetl(PACKFILE *f);}
Like pack_getc, but reads a 32-bit long from a file, using Intel byte
ordering (least significant byte first, a.k.a. little-endian).

@end ftable
See also:@*
@xref{pack_getc}.@*
@xref{PACKFILE}.@*
@node pack_iputl, pack_mgetw, pack_igetl, File
@subsection pack_iputl
@ftable @asis
@item @t{long pack_iputl(long c, PACKFILE *f);}
Like pack_putc, but writes a 32-bit long to a file, using Intel byte
ordering (least significant byte first, a.k.a. little-endian).

@end ftable
See also:@*
@xref{pack_putc}.@*
@xref{PACKFILE}.@*
@node pack_mgetw, pack_mputw, pack_iputl, File
@subsection pack_mgetw
@ftable @asis
@item @t{int pack_mgetw(PACKFILE *f);}
Like pack_getc, but reads a 16-bit word from a file, using Motorola byte
ordering (most significant byte first, a.k.a. big-endian).

@end ftable
See also:@*
@xref{pack_getc}.@*
@xref{PACKFILE}.@*
@node pack_mputw, pack_mgetl, pack_mgetw, File
@subsection pack_mputw
@ftable @asis
@item @t{int pack_mputw(int c, PACKFILE *f);}
Like pack_putc, but writes a 16-bit word to a file, using Motorola byte
ordering (most significant byte first, a.k.a. big-endian).

@end ftable
See also:@*
@xref{pack_putc}.@*
@xref{PACKFILE}.@*
@node pack_mgetl, pack_mputl, pack_mputw, File
@subsection pack_mgetl
@ftable @asis
@item @t{long pack_mgetl(PACKFILE *f);}
Like pack_getc, but reads a 32-bit long from a file, using Motorola byte
ordering (most significant byte first, a.k.a. big-endian).

@end ftable
See also:@*
@xref{pack_getc}.@*
@xref{PACKFILE}.@*
@node pack_mputl, pack_fread, pack_mgetl, File
@subsection pack_mputl
@ftable @asis
@item @t{long pack_mputl(long c, PACKFILE *f);}
Like pack_putc, but writes a 32-bit long to a file, using Motorola byte
ordering (most significant byte first, a.k.a. big-endian).

@end ftable
See also:@*
@xref{pack_putc}.@*
@xref{PACKFILE}.@*
@node pack_fread, pack_fwrite, pack_mputl, File
@subsection pack_fread
@ftable @asis
@item @t{long pack_fread(void *p, long n, PACKFILE *f);}
Reads `n' bytes from the stream `f', storing them at the memory location
pointed to by `p'. Example:
@example

unsigned char buf[256];
...
if (pack_fread(buf, 256, input_file) != 256)
   abort_on_error("Truncated input file!");@end example


Returns the number of bytes read, which will be less than `n' if EOF is
reached or an error occurs. Error codes are stored in errno.

@end ftable
See also:@*
@xref{pack_fopen}.@*
@xref{pack_fopen_chunk}.@*
@xref{pack_feof}.@*
@xref{expackf}.@*
@xref{PACKFILE}.@*
@node pack_fwrite, pack_fgets, pack_fread, File
@subsection pack_fwrite
@ftable @asis
@item @t{long pack_fwrite(const void *p, long n, PACKFILE *f);}
Writes `n' bytes to the stream `f' from memory location pointed to by `p'.

Returns the number of bytes written, which will be less than n if an
error occurs. Error codes are stored in errno.

@end ftable
See also:@*
@xref{pack_fopen}.@*
@xref{pack_fopen_chunk}.@*
@xref{pack_feof}.@*
@xref{PACKFILE}.@*
@node pack_fgets, pack_fputs, pack_fwrite, File
@subsection pack_fgets
@ftable @asis
@item @t{char *pack_fgets(char *p, int max, PACKFILE *f);}
Reads a line from the stream `f', storing it at location pointed to by
`p'. Stops when a linefeed is encountered, or `max' bytes have been read.
The end of line is handled by detecting the right combination of characters
for the platform. This supports CR-LF (DOS/Windows), LF (Unix), and CR
(Mac) formats. However, the trailing carriage return is not included in the
returned string, in order to provide easy code portability across
platforms. If you need the carriage return, use pack_fread() and/or
pack_getc() instead.

Note: This function internally may make calls to pack_ungetc, so you cannot
use pack_ungetc directly afterwards.

Example:
@example

char buf[256];
...
while (pack_fgets(buf, sizeof(buf), input_file)) @{
   /* Process input line. */
@}
fclose(input_file);@end example


Returns the pointer `p' on success, or NULL on error.

@end ftable
See also:@*
@xref{pack_fopen}.@*
@xref{pack_fopen_chunk}.@*
@xref{pack_fread}.@*
@xref{pack_getc}.@*
@xref{pack_ungetc}.@*
@xref{PACKFILE}.@*
@node pack_fputs, pack_fopen_chunk, pack_fgets, File
@subsection pack_fputs
@ftable @asis
@item @t{int pack_fputs(const char *p, PACKFILE *f);}
Writes a string to the stream `f'. The input string is converted from the
current text encoding format to UTF-8 before writing. Newline characters
are written as `\r\n' on DOS and Windows platforms. If you don't want this
behaviour, use pack_fwrite() and/or pack_putc() instead.

Returns zero on success or a negative number on error.

@end ftable
See also:@*
@xref{pack_fopen}.@*
@xref{pack_fopen_chunk}.@*
@xref{pack_fwrite}.@*
@xref{pack_putc}.@*
@xref{PACKFILE}.@*
@node pack_fopen_chunk, pack_fclose_chunk, pack_fputs, File
@subsection pack_fopen_chunk
@ftable @asis
@item @t{PACKFILE *pack_fopen_chunk(PACKFILE *f, int pack);}
Opens a sub-chunk of a file. Chunks are primarily intended for use by the 
datafile code, but they may also be useful for your own file routines. A 
chunk provides a logical view of part of a file, which can be compressed 
as an individual entity and will automatically insert and check length 
counts to prevent reading past the end of the chunk. The PACKFILE
parameter is a previously opened file, and `pack' is a boolean parameter
which will turn compression on for the sub-chunk if it is non-zero.
Example:
@example

PACKFILE *output = pack_fopen("out.raw", "w!");
...
/* Create a sub-chunk with compression. */
output = pack_fopen(chunk(output, 1);
if (!output)
   abort_on_error("Error saving data!");
/* Write some data to the sub-chunk. */
...
/* Close the sub-chunk, recovering parent file. */
output = pack_fclose_chunk(output);
@end example

The data written to the chunk will be prefixed with two length counts
(32-bit, a.k.a. big-endian). For uncompressed chunks these will both be
set to the size of the data in the chunk. For compressed chunks (created
by setting the `pack' flag), the first length will be the raw size of the
chunk, and the second will be the negative size of the uncompressed data.

To read the chunk, use the following code:
@example

PACKFILE *input = pack_fopen("out.raw", "rp");
...
input = pack_fopen_chunk(input, 1);
/* Read data from the sub-chunk and close it. */
...
input = pack_fclose_chunk(input);
@end example

This sequence will read the length counts created when the chunk was 
written, and automatically decompress the contents of the chunk if it 
was compressed. The length will also be used to prevent reading past the 
end of the chunk (Allegro will return EOF if you attempt this), and to 
automatically skip past any unread chunk data when you call 
pack_fclose_chunk().

Chunks can be nested inside each other by making repeated calls to 
pack_fopen_chunk(). When writing a file, the compression status is 
inherited from the parent file, so you only need to set the pack flag if 
the parent is not compressed but you want to pack the chunk data. If the 
parent file is already open in packed mode, setting the pack flag will 
result in data being compressed twice: once as it is written to the 
chunk, and again as the chunk passes it on to the parent file.

Returns a pointer to the sub-chunked PACKFILE, or NULL if there was some
error (eg. you are using a custom PACKFILE vtable).

@end ftable
See also:@*
@xref{pack_fclose_chunk}.@*
@xref{pack_fopen}.@*
@xref{PACKFILE}.@*
@node pack_fclose_chunk, create_lzss_pack_data, pack_fopen_chunk, File
@subsection pack_fclose_chunk
@ftable @asis
@item @t{PACKFILE *pack_fclose_chunk(PACKFILE *f);}
Closes a sub-chunk of a file, previously obtained by calling 
pack_fopen_chunk().

Returns a pointer to the parent of the sub-chunk you just closed. Returns
NULL if there was some error (eg. you tried to close a PACKFILE which
wasn't sub-chunked).

@end ftable
See also:@*
@xref{pack_fopen_chunk}.@*
@xref{PACKFILE}.@*
@node create_lzss_pack_data, free_lzss_pack_data, pack_fclose_chunk, File
@subsection create_lzss_pack_data
@ftable @asis
@item @t{LZSS_PACK_DATA *create_lzss_pack_data(void);}
Creates an LZSS_PACK_DATA structure, which can be used for LZSS
compression with PACKFILEs.

Returns a pointer to the structure, or NULL if there was an error.

@end ftable
See also:@*
@xref{free_lzss_pack_data}.@*
@xref{LZSS_PACK_DATA}.@*
@node free_lzss_pack_data, lzss_write, create_lzss_pack_data, File
@subsection free_lzss_pack_data
@ftable @asis
@item @t{void free_lzss_pack_data(LZSS_PACK_DATA *dat);}
Frees an LZSS_PACK_DATA structure created with create_lzss_pack_data().

@end ftable
See also:@*
@xref{create_lzss_pack_data}.@*
@xref{LZSS_PACK_DATA}.@*
@node lzss_write, create_lzss_unpack_data, free_lzss_pack_data, File
@subsection lzss_write
@ftable @asis
@item @t{int lzss_write(PACKFILE *file, LZSS_PACK_DATA *dat, int size, unsigned char *buf, int last);}
Packs `size' bytes from `buf', using the pack information contained in
`dat'. The compressed bytes will be stored in `file'.

Returns 0 on success, or EOF if there was an error.

@end ftable
See also:@*
@xref{create_lzss_pack_data}.@*
@xref{free_lzss_pack_data}.@*
@xref{PACKFILE}.@*
@xref{LZSS_PACK_DATA}.@*
@node create_lzss_unpack_data, free_lzss_unpack_data, lzss_write, File
@subsection create_lzss_unpack_data
@ftable @asis
@item @t{LZSS_UNPACK_DATA *create_lzss_unpack_data(void);}
Creates an LZSS_UNPACK_DATA structure, which can be used for LZSS
decompression reading PACKFILEs.

Returns a pointer to the structure, or NULL if there was an error.

@end ftable
See also:@*
@xref{free_lzss_unpack_data}.@*
@xref{LZSS_UNPACK_DATA}.@*
@node free_lzss_unpack_data, lzss_read, create_lzss_unpack_data, File
@subsection free_lzss_unpack_data
@ftable @asis
@item @t{void free_lzss_unpack_data(LZSS_UNPACK_DATA *dat);}
Frees an LZSS_UNPACK_DATA structure created with create_lzss_pack_data.

@end ftable
See also:@*
@xref{create_lzss_unpack_data}.@*
@xref{LZSS_UNPACK_DATA}.@*
@node lzss_read, load_datafile, free_lzss_unpack_data, File
@subsection lzss_read
@ftable @asis
@item @t{int lzss_read(PACKFILE *file, LZSS_UNPACK_DATA *dat, int s, unsigned char *buf);}
Unpacks from `dat' into `buf', until either EOF is reached or `s' bytes
have been extracted from `file'.

Returns the number of bytes added to the buffer `buf'.



@end ftable
See also:@*
@xref{free_lzss_unpack_data}.@*
@xref{PACKFILE}.@*
@xref{LZSS_UNPACK_DATA}.@*
@node Datafile, Fixed, File, API
@section Datafile routines

Datafiles are created by the grabber utility (see grabber.txt for more
information), and have a `.dat' extension. They can contain bitmaps, palettes,
fonts, samples, MIDI music, FLI/FLC animations, and any other binary data that
you import. You could distribute your bitmaps and samples in a myriad of
separate files, but packing them in a few `.dat' binaries has a few
advantages:

@itemize @bullet
@item 
On some platforms loading a single big datafile at once is faster than
loading individual resources one by one.
@item 
Instead of several loops for your resources, you can write a single line of
code with just a single point of failure to take care of.
@item 
You can potentially reduce the size of your data by enabling compression
on your datafiles. Less download time for your end users, less wait during
loading screens!
@item 
If you don't need to load the whole datafile at once, you can still enable
individual file compression. It is slightly worse than global compression,
but it is very fast with loading times because Allegro can easily seek
inside the datafile to find a specific object.
@item 
Even without encryption, most end users of your application won't be able
to look at or modify the resources for your game. A missing sound file or
a modified bitmap could potentially crash the game if you haven't
considered this in your loading code!
@item 
It looks much more professional and convenient to distribute levels! For
example, if you found a bug in a level of your game, just distribute your
new `level4.dat' and tell users to overwrite their old version.
@end itemize

Allegro allows you to load datafiles once and forget about them. But if you
have many levels it can be wise to load only the resources required for the
current level. You can accomplish the later by separating levels in different
datafiles, or using functions like load_datafile_object() to avoid loading
everything at once. You can even read directly from a specific datafile object
with the pack_fopen() function.

On some platforms you can attach datafiles to your binary, potentially
reducing your game distribution down to a single executable file. Try the
example exexedat on your platform to see if this is possible. However, this
is not recommended for big programs: a single update to your code or binary
data would force end users to download again a potentially big file, no matter
how small your change is. The same warning goes for the tools dat2s or dat2c,
which convert datafiles into assembler and C code respectively, prepared to be
included directly in your binary.

Remember that with Allegro truecolor images can only be loaded after you have
set a graphics mode. This is true for datafiles too. Load all your data after
you have set the graphics mode, otherwise the pixel format (RGB or BGR) will
not be known and the datafile may be converted wrongly. Oh, and read carefully
the warning of fixup_datafile() if you plan on switching resolutions during
runtime.

Note: even though Allegro datafiles provide encryption, you should consider
it weak, so don't plan on hiding there the plans for a Death Star or
something. Determinate knowledgeable users will be able to rip your resources
no matter how hard you try to hide them! Use the encryption only as a slight
deterrent towards unwanted tampering of your data. How to crack an encrypted
datafile is left as an exercise to the reader, though.

Using datafiles once they are loaded is quite simple: you access the elements
of the DATAFILE as a normal array. Read below the section "Using datafiles"
below for several examples on how to access their data.

@menu
* load_datafile::
* load_datafile_callback::
* unload_datafile::
* load_datafile_object::
* unload_datafile_object::
* find_datafile_object::
* create_datafile_index::
* load_datafile_object_indexed::
* destroy_datafile_index::
* get_datafile_property::
* register_datafile_object::
* fixup_datafile::
* DAT_ID::
* Using datafiles::
* Custom datafile objects::
@end menu
@node load_datafile, load_datafile_callback, lzss_read, Datafile
@subsection load_datafile
@ftable @asis
@item @t{DATAFILE *load_datafile(const char *filename);}
Loads a datafile into memory in one go. If the datafile has been encrypted,
you must first call packfile_password() to set the appropriate key. If the
datafile contains truecolor graphics, you must set the video mode or call
set_color_conversion() before loading it. Example:
@example

/* Load the resources for our game. */
DATAFILE *dat = load_datafile("game.dat");
if (!dat)
   abort_on_error("Couldn't load sound resources!");
/* Use resources. */
...
/* Destroy them when we don't need them any more. */
unload_datafile(dat);@end example


Returns a pointer to the DATAFILE, or NULL on error. Remember to free this
DATAFILE later to avoid memory leaks.

@end ftable
See also:@*
@xref{load_datafile_callback}.@*
@xref{unload_datafile}.@*
@xref{load_datafile_object}.@*
@xref{set_color_conversion}.@*
@xref{fixup_datafile}.@*
@xref{packfile_password}.@*
@xref{find_datafile_object}.@*
@xref{register_datafile_object}.@*
@xref{Using datafiles}.@*
@xref{excustom}.@*
@xref{exdata}.@*
@xref{exexedat}.@*
@xref{exgui}.@*
@xref{exsprite}.@*
@xref{exunicod}.@*
@xref{DATAFILE}.@*
@node load_datafile_callback, unload_datafile, load_datafile, Datafile
@subsection load_datafile_callback
@ftable @asis
@item @t{DATAFILE *load_datafile_callback(const char *filename, void (*callback)(DATAFILE *d));}
Loads a datafile into memory, calling the specified hook function once for
each object in the file, passing it a pointer to the object just read. You
can use this to implement very simple loading screens where every time the
hook is called, the screen is updated to let the user know your program is
still loading from disk:
@example

void load_callback(DATAFILE *dat_obj)
@{
   static const char indicator[] = "-\\|/-.oOXOo.";
   static int current = 0;
    
   /* Show a different character every time. */
   textprintf_ex(screen, font, 0, 0, makecol(0, 0, 0),
                 makecol(255, 255, 255), "%c Loading %c",
                 indicator[current], indicator[current]);
   /* Increase index and check if we need to reset it. */
   current++;
   if (!indicator[current])
      current = 0;
@}
   ...
   dat = load_datafile_callback("data.dat", load_callback);@end example


Returns a pointer to the DATAFILE or NULL on error. Remember to free this
DATAFILE later to avoid memory leaks.

@end ftable
See also:@*
@xref{load_datafile}.@*
@xref{unload_datafile}.@*
@xref{load_datafile_object}.@*
@xref{set_color_conversion}.@*
@xref{fixup_datafile}.@*
@xref{packfile_password}.@*
@xref{find_datafile_object}.@*
@xref{register_datafile_object}.@*
@xref{DATAFILE}.@*
@node unload_datafile, load_datafile_object, load_datafile_callback, Datafile
@subsection unload_datafile
@ftable @asis
@item @t{void unload_datafile(DATAFILE *dat);}
Frees all the objects in a datafile. Use this to avoid memory leaks in
your program.

@end ftable
See also:@*
@xref{load_datafile}.@*
@xref{excustom}.@*
@xref{exdata}.@*
@xref{exexedat}.@*
@xref{exgui}.@*
@xref{exsprite}.@*
@xref{exunicod}.@*
@xref{DATAFILE}.@*
@node load_datafile_object, unload_datafile_object, unload_datafile, Datafile
@subsection load_datafile_object
@ftable @asis
@item @t{DATAFILE *load_datafile_object(const char *filename,  const char *objectname);}
Loads a specific object from a datafile. This won't work if you strip the 
object names from the file, and it will be very slow if you save the file 
with global compression. Example:
@example

/* Load only the music from the datafile. */
music_object = load_datafile_object("datafile.dat",
                                    "MUSIC");
/* Play it and wait a moment for it. */
play_midi(music_object->dat);
...
/* Destroy unneeded music. */
unload_datafile_object(music_object);@end example


Returns a pointer to a single DATAFILE element whose `dat' member points to
the object, or NULL if there was an error or there was no object with the
requested name. Remember to free this DATAFILE later to avoid memory leaks,
but use the correct unloading function!

@end ftable
See also:@*
@xref{unload_datafile_object}.@*
@xref{load_datafile}.@*
@xref{set_color_conversion}.@*
@xref{find_datafile_object}.@*
@xref{register_datafile_object}.@*
@xref{Using datafiles}.@*
@xref{DATAFILE}.@*
@node unload_datafile_object, find_datafile_object, load_datafile_object, Datafile
@subsection unload_datafile_object
@ftable @asis
@item @t{void unload_datafile_object(DATAFILE *dat);}
Frees an object previously loaded by load_datafile_object(). Use this to
avoid memory leaks in your program.

@end ftable
See also:@*
@xref{load_datafile_object}.@*
@xref{DATAFILE}.@*
@node find_datafile_object, create_datafile_index, unload_datafile_object, Datafile
@subsection find_datafile_object
@ftable @asis
@item @t{DATAFILE *find_datafile_object(const DATAFILE *dat, const char *objectname);}
Searches an already loaded datafile for an object with the specified 
name. In the name you can use `/' and `#' separators for nested datafile
paths. Example:
@example

char level_name[10];
DATAFILE *dat, *level;
...
uszprintf(level_name, sizeof(buffer),
          "LEVEL_%02d", level_number);
level = find_datafile_object(dat, level_name);
if (!level)
   abort_on_error("That level doesn't exist!");@end example


Returns a pointer to a single DATAFILE element whose `dat' member points to
the object, or NULL if the object could not be found.

@end ftable
See also:@*
@xref{load_datafile}.@*
@xref{load_datafile_object}.@*
@xref{DATAFILE}.@*
@node create_datafile_index, load_datafile_object_indexed, find_datafile_object, Datafile
@subsection create_datafile_index
@ftable @asis
@item @t{DATAFILE_INDEX *create_datafile_index(const char *filename);}
Creates an index for a datafile, to speed up loading single objects out of
it. This is mostly useful for big datafiles, which you don't want to load as
a whole. The index will store the offset of all objects inside the datafile,
and then you can load it quickly with "load_datafile_object_indexed" later.
Use destroy_datafile_index to free the memory used by it again.

Note: If the datafile uses global compression, there is no performance gain
from using an index, because seeking to the offset still requires to
uncompress the whole datafile up to that offset.
Example:
@example

DATAFILE_INDEX *index = create_datafile_index("huge.dat");
DATAFILE *object = load_datafile_object_indexed(index, 1234);
...
unload_datafile_object(object);
destroy_datafile_index(index);@end example


A pointer value which you can pass to load_datafile_object_indexed.

@end ftable
See also:@*
@xref{destroy_datafile_index}.@*
@xref{load_datafile_object_indexed}.@*
@xref{Using datafiles}.@*
@node load_datafile_object_indexed, destroy_datafile_index, create_datafile_index, Datafile
@subsection load_datafile_object_indexed
@ftable @asis
@item @t{DATAFILE *load_datafile_object_indexed(const DATAFILE_INDEX *index, int item)}
This loads a single object, using the index created previously with
create_datafile_index. See create_datafile_index for an example.

Returns a pointer to a single DATAFILE element whose "dat" member points to
the object, or NULL if the object could not be loaded.

@end ftable
See also:@*
@xref{create_datafile_index}.@*
@xref{load_datafile_object}.@*
@xref{unload_datafile_object}.@*
@xref{DATAFILE}.@*
@node destroy_datafile_index, get_datafile_property, load_datafile_object_indexed, Datafile
@subsection destroy_datafile_index
@ftable @asis
@item @t{void destroy_datafile_index(DATAFILE_INDEX *index)}
This function frees the memory used by a datafile index created with
create_datafile_index earlier.

@end ftable
See also:@*
@xref{create_datafile_index}.@*
@node get_datafile_property, register_datafile_object, destroy_datafile_index, Datafile
@subsection get_datafile_property
@ftable @asis
@item @t{const char *get_datafile_property(const DATAFILE *dat, int type);}
Finds the property type of a DATAFILE object. The type parameter must be a
value created with the DAT_ID() macro. Example:
@example

const char *name;
...
name = get_datafile_property(game_data,
                             DAT_ID('N','A','M','E'));
if (name == empty_string)
   abort_on_error("Object doesn't have a name!");@end example


Returns a pointer to the text string for the object, or a pointer to the
variable empty_string if the property isn't present.

@end ftable
See also:@*
@xref{Using datafiles}.@*
@xref{DAT_ID}.@*
@xref{empty_string}.@*
@xref{DATAFILE}.@*
@node register_datafile_object, fixup_datafile, get_datafile_property, Datafile
@subsection register_datafile_object
@ftable @asis
@item @t{void register_datafile_object(int id, void *(*load)(PACKFILE *f, long size), void (*destroy)(void *data));}
Used to add custom object types, specifying functions to load and destroy 
objects of this type.

@end ftable
See also:@*
@xref{load_datafile}.@*
@xref{load_datafile_object}.@*
@xref{DAT_ID}.@*
@xref{Custom datafile objects}.@*
@xref{PACKFILE}.@*
@node fixup_datafile, DAT_ID, register_datafile_object, Datafile
@subsection fixup_datafile
@ftable @asis
@item @t{void fixup_datafile(DATAFILE *data);}
If you are using compiled datafiles (produced by the dat2s and dat2c
utilities) on a platform that doesn't support constructors (currently any
non GCC-based platform), or if the datafiles contain truecolor images, you
must call this function once after your set the video mode that you will
be using. This will ensure the datafiles are properly initialised in the
first case and convert the color values into the appropriate format in
the second case. It handles flipping between RGB and BGR formats, and
converting between different color depths whenever that can be done
without changing the size of the image (ie. changing 15<->16-bit
hicolor for both bitmaps and RLE sprites, and 24<->32-bit truecolor
for RLE sprites).

Note that you can only call this once and expect it to work correctly,
because after the call the DATAFILE you fixed up is permanently converted
to whatever is the current component ordering for your screen mode. If you
call fixup_datafile again, the function assumes you have a freshly loaded
datafile. It cannot "undo" the previous conversion.

If your program supports changing resolution and/or color depth during
runtime, you have two choices: either call fixup_datafile() just once and
hope that the component ordering and bit depth doesn't change when the
screen mode changes (unlikely). Or, you can reload your datafiles when the
screen mode changes.

@end ftable
See also:@*
@xref{set_gfx_mode}.@*
@xref{set_color_conversion}.@*
@xref{Differences, Differences between platforms}.@*
@xref{DATAFILE}.@*
@node DAT_ID, Using datafiles, fixup_datafile, Datafile
@subsection DAT_ID
@ftable @asis
@item @t{Macro DAT_ID(a, b, c, d);}
Every object or property in a datafile is identified by a 4 letter ID,
which can be created with this macro. For example, to access the NAME
property of a datafile object, you could use:
@example

get_datafile_property(datob, DAT_ID('N','A','M','E'));
@end example



@end ftable
See also:@*
@xref{register_datafile_object}.@*
@xref{get_datafile_property}.@*
@xref{Custom datafile objects}.@*
@xref{Using datafiles}.@*
@node Using datafiles, Custom datafile objects, DAT_ID, Datafile
@subsection Using datafiles
@ftable @asis

@end ftable
In order to access the contents of a datafile, you will need to know where
each object is located. The easiest way to do this is by integer index,
using an automatically generated header file. With the grabber, type a name
into the "Header:" field, and the object indexes will be written to this
file whenever the datafile is saved. With the dat utility, use the '-h'
option, eg. "dat filename.dat -h filename.h". The header will define C
preprocessor symbols for each object in the datafile, for example:
@example

#define SOME_DATA                        0        /* DATA */
#define SOME_MORE_DATA                   1        /* DATA */
@end example

To prevent name conflicts, you can specify a prefix string for these
definitions by typing it into the "Prefix:" field in the grabber or using 
the '-p' option to dat.

To load a datafile into memory, call the function:
@example

DATAFILE *load_datafile(char *filename);
@end example

This will load the entire file, returning a pointer to it, or NULL on error.
When the data is no longer required, the entire thing can be destroyed by
calling:
@example

void unload_datafile(DATAFILE *dat);
@end example

When you load a datafile, you will obtain a pointer to an array of DATAFILE
structures:
@example

typedef struct DATAFILE
@{
   void *dat;                    - pointer to the actual data
   int type;                     - object type ID
   long size;                    - size of the data, in bytes
   DATAFILE_PROPERTY *prop;      - list of object properties
@} DATAFILE;@end example


The only really important piece of information here is the `dat' field, which
points to the contents of the object. What type of data this is will depend 
on the type of object: for bitmaps it will be an Allegro BITMAP structure, 
for RLE sprites an RLE_SPRITE, for fonts a FONT structure, etc. If you are 
programming in C you can pass this pointer directly to the relevant Allegro 
library functions, but if you are using C++ you will need to cast it to the 
appropriate type to prevent the compiler giving a warning.

For example, if you have a datafile called `myfile.dat', which contains a
bitmap called COOL_PICTURE, and you have used it to produce a header called 
`myfile.h', you could display the bitmap with the code:
@example

#include "myfile.h"

void show_the_bitmap()
@{
   DATAFILE *dat;
   BITMAP *bmp;

   dat = load_datafile("myfile.dat");
   if (!dat) @{
      /* report an error! */
      return;
   @}

   bmp = (BITMAP *)dat[COOL_PICTURE].dat;
   blit(bmp, screen, 0, 0, 0, 0, bmp->w, bmp->h);
   unload_datafile(dat);
@}@end example


If a datafile contains nested child datafiles, the header will prefix the 
names of objects in the sub-files with the name of their parent datafile. It 
will also define a count of the number of objects in the child file, which 
may be useful if for example the child datafile contains several bitmaps 
which form a 'run' animation, and you want your code to automatically 
adjust to the number of frames in the datafile. 

For example, the following datafile:
@example

"FILE" - NESTED_FILE
         |- "BMP" - A_BITMAP
         |- "FONT" - A_FONT
"DATA" - SOME_DATA
"DATA" - SOME_MORE_DATA
@end example

Will produce the header:
@example

#define NESTED_FILE                      0        /* FILE */

#define NESTED_FILE_A_BITMAP             0        /* BMP  */
#define NESTED_FILE_A_FONT               1        /* FONT */
#define NESTED_FILE_COUNT                2

#define SOME_DATA                        1        /* DATA */
#define SOME_MORE_DATA                   2        /* DATA */
@end example

The main datafile contains three objects (NESTED_FILE, SOME_DATA, and 
SOME_MORE_DATA) with consecutive indexes, while the child datafile contains 
the two objects A_BITMAP and A_FONT. To access these objects you need to 
reference both the parent and child datafiles, eg:
@example

DATAFILE *dat = load_datafile("whatever.dat");
DATAFILE *nested = (DATAFILE *)dat[NESTED_FILE].dat;
FONT *thefont = (FONT *)nested[NESTED_FILE_A_FONT].dat;
@end example

If you need to access object property strings from within your program, you
can use the function:
@example

char *get_datafile_property(DATAFILE *dat, int type);
@end example

This will return a pointer to the property string if it can be found, and an
empty string (not null!) if it does not exist. One possible use of this 
function is to locate objects by name, rather than using the indexes from a 
header file. The datafile array is ended by an object of type DAT_END, so to 
search the datafile dat for the object "my_object" you could use the code:
@example

const int name_type = DAT_ID('N','A','M','E');
for (i=0; dat[i].type != DAT_END; i++) @{
   if (stricmp(get_datafile_property(dat+i, name_type),
               "my_object") == 0) @{
      /* found the object at index i */
   @}
@}
/* not found... */
@end example

If you prefer to access objects by name rather than index number, you can
use the function:
@example

DATAFILE *find_datafile_object(DATAFILE *dat, char *objectname);
@end example

This will search an already loaded datafile for an object with the specified
name, returning a pointer to it, or NULL if the object cannot be found. It 
understands '/' and '#' separators for nested datafile paths.

It is also possible to selectively load individual objects from a datafile, 
with the function:
@example

DATAFILE *load_datafile_object(char *filename, char *objectname);
@end example

This searches the datafile for an object with the specified name, so
obviously it won't work if you strip the name properties out of the file. 
Because this function needs to seek through the data, it will be extremely 
slow if you have saved the file with global compression. If you are planning 
to load objects individually, you should save the file uncompressed or with 
individual compression per-object. Because the returned datafile points to a 
single object rather than an array of objects, you should access it with the 
syntax datafile->dat, rather than datafile[index].dat, and when you are done
you should free the object with the function:
@example

void unload_datafile_object(DATAFILE *dat);
@end example

Example:
@example

music_object = load_datafile_object("datafile.dat", "MUSIC");
play_midi(music_object->dat);
...
unload_datafile_object(music_object);
@end example

Alternatively, the packfile functions can open and read directly from the
contents of a datafile object. You do this by calling pack_fopen() with a 
fake filename in the form "filename.dat#object_name". The contents of the 
object can then be read in an identical way to a normal disk file, so any of 
the file access functions in Allegro (eg. load_pcx() and set_config_file()) 
can be used to read from datafile objects. Note that you can't write to 
datafiles in this way: the fake file is read only. Also, you should save the 
file uncompressed or with per-object compression if you are planning on 
using this feature. Finally, be aware that the special Allegro object types 
aren't the same format as the files you import the data from, so if for 
example you want to use load_pcx to read an image from a datafile, you 
should import it as a binary data chunk rather than as a BITMAP object.

If you have appended a datafile to the end of your executable with the 
exedat utility, use load_datafile("#") to read the entire thing into memory, 
load_datafile_object("#", "object_name") to load a specific object, and 
pack_fopen("#object_name", F_READ) to read one of the objects directly with 
your own code. Note that unless you use the previous functions to load the
appended data, the OS will not load it into memory just because you are
running the program, so you shouldn't have problems attaching datafiles to
your binary larger than the available system memory.

By default, all graphic objects loaded from a datafile will be converted 
into the current color depth. This conversion may be both lossy and very 
slow, particularly when reducing from truecolor to 256 color formats, so you 
may wish to disable it by calling set_color_conversion(COLORCONV_NONE) or 
set_color_conversion(COLORCONV_PARTIAL) before your call to load_datafile().



@node Custom datafile objects, itofix, Using datafiles, Datafile
@subsection Custom datafile objects
@ftable @asis

@end ftable
Some of the objects in a datafile, for example palettes and FLI animations, 
are simply treated as blocks of binary data, but others are loaded into 
special formats such as bitmap structures or compiled sprites. It is 
possible to extend the datafile system to support your own custom object 
types, eg. map objects for a tile based engine, or level data for a platform 
game. Obviously the grabber has no way of understanding this data, but it 
will allow you to import binary data from external files, so you can grab 
information produced by your own utilities. If you are happy with the data 
being loaded as a simple binary block, that is all you need to do, but if 
you need to load it into a specific structure, read on...

Your custom objects must be given a unique type ID, which is formed from 
four ASCII characters (by convention all uppercase A-Z). If you don't use 
all four characters, the string should be padded with spaces (ASCII 32). You 
should use this ID when creating the objects in the grabber (select 
New/Other and type in the ID string), and in your code you should define an 
identifier for the type, eg:
@example

#define DAT_MAPDATA  DAT_ID('M','A','P','D')
@end example

You then need to write functions for loading and destroying objects of this
type, in the form:
@example

void *load_mapdata(PACKFILE *f, long size)
@{
   /* Allegro will call this function whenever an object of your custom 
    * type needs to be loaded from a datafile. It will be passed a 
    * pointer to the file from which the data is to be read, and the size 
    * of the object in bytes. It should return a pointer to the loaded 
    * data, which will be stored in the dat field of the datafile object 
    * structure, or NULL if an error occurs. The file will have been 
    * opened as a sub-chunk of the main datafile, so it is safe to read 
    * past the end of the object (if you attempt this, Allegro will 
    * return EOF), and it is also safe to return before reading all the 
    * data in the chunk (if you do this, Allegro will skip any unused 
    * bytes before starting to read the next object). You should _not_ 
    * close the file when you are done: this will be handled by the 
    * calling function. To clarify how all this works, here's an example 
    * implementation of a null-terminated string object:
    */

   #define MAX_LEN  256

   char buf[MAX_LEN];
   char *p;
   int i, c;

   for (i=0; i<;MAX_LEN-1; i++) @{
      if ((c = pack_getc(f)) == EOF)
         break;

      buf[i] = c;
   @}

   buf[i] = 0;

   p = malloc(i+1);
   strcpy(p, buf);

   return p;
@}

void destroy_mapdata(void *data)
@{
   /* Allegro will call this function whenever an object of your custom 
    * type needs to be destroyed. It will be passed a pointer to the 
    * object (as returned by the load function), and should free whatever 
    * memory the object is using. For example, the simple string object 
    * returned by the above loader could be destroyed with the code:
    */

   if (data)
      free(data);
@}
@end example

Finally, before you load your datafile you must tell Allegro about the
custom format, by calling:
@example

register_datafile_object(DAT_MAPDATA, load_mapdata, destroy_mapdata);
@end example

It is also possible to integrate support for custom object types directly
into the grabber and dat utilities, by copying some special files into the 
tools/plugins directory. This can be used to add whole new object types and 
menu commands, or to provide additional import/export routines for the 
existing formats. See `tools/plugins/plugins.txt' for an overview of how to
write your own grabber plugins.



@node Fixed, 3D, Datafile, API
@section Fixed point math routines

Allegro provides some routines for working with fixed point numbers, and
defines the type `fixed' to be a signed 32-bit integer. The high word is 
used for the integer part and the low word for the fraction, giving a range
of -32768 to 32767 and an accuracy of about four or five decimal places.
Fixed point numbers can be assigned, compared, added, subtracted, negated and
shifted (for multiplying or dividing by powers of two) using the normal
integer operators, but you should take care to use the appropriate conversion
routines when mixing fixed point with integer or floating point values.
Writing `fixed_point_1 + fixed_point_2' is OK, but `fixed_point + integer' is
not.

Unfortunately the only advantage of fixed point math routines is that you
don't require a floating point coprocessor to use them. This was great in the
time period of i386 and i486 machines, but stopped being so useful with the
coming of the Pentium class of processors. From Pentium onwards, CPUs have
increased their strength in floating point operations, equaling or even
surpassing integer math performance.

Depending on the type of operations your program may need, using floating
point types may be faster than fixed types if you are targeting a specific
machine class. Allegro comes with a test program in the `allegro/tests'
directory. Its `Misc' menu contains a basic profile test which can give you
an idea of the speed difference between fixed and float types for a few basic
operations on your machine. However, don't forget to profile your program in
real life conditions, tight loop benchmarks are after all artificial.

Fixed point math is considered "add-on" material and is kept only for
backwards compatibility. Whenever a future release of Allegro breaks backwards
compatibility, fixed point math will likely be moved to a separate add-on
package for the very few users who still find it convenient and useful, and
Allegro functions using fixed point math will use other types.

@menu
* itofix::
* fixtoi::
* fixfloor::
* fixceil::
* ftofix::
* fixtof::
* fixmul::
* fixdiv::
* fixadd::
* fixsub::
* Fixed point trig::
* fixtorad_r::
* radtofix_r::
* fixsin::
* fixcos::
* fixtan::
* fixasin::
* fixacos::
* fixatan::
* fixatan2::
* fixsqrt::
* fixhypot::
* Fix class::
@end menu
@node itofix, fixtoi, Custom datafile objects, Fixed
@subsection itofix
@ftable @asis
@item @t{fixed itofix(int x);}
Converts an integer to fixed point. This is the same thing as x<<16.
Remember that overflows (trying to convert an integer greater than 32767)
and underflows (trying to convert an integer lesser than -32768) are not
detected even in debug builds! The values simply "wrap around". Example:
@example

fixed number;
/* This conversion is OK. */
number = itofix(100);
ASSERT(fixtoi(number) == 100);
number = itofix(64000);
/* This check will fail in debug builds. */
ASSERT(fixtoi(number) == 64000);@end example


Returns the value of the integer converted to fixed point ignoring
overflows.

@end ftable
See also:@*
@xref{fixtoi}.@*
@xref{ftofix}.@*
@xref{fixtof}.@*
@xref{ex12bit}.@*
@xref{ex3buf}.@*
@xref{ex3d}.@*
@xref{exblend}.@*
@xref{excustom}.@*
@xref{exfixed}.@*
@xref{exlights}.@*
@xref{exspline}.@*
@xref{exsprite}.@*
@xref{exstars}.@*
@xref{fixed}.@*
@node fixtoi, fixfloor, itofix, Fixed
@subsection fixtoi
@ftable @asis
@item @t{int fixtoi(fixed x);}
Converts fixed point to integer, rounding as required to the nearest
integer. Example:
@example

int result;
/* This will put 33 into `result'. */
result = fixtoi(itofix(100) / 3);
/* But this will round up to 17. */
result = fixtoi(itofix(100) / 6);@end example


@end ftable
See also:@*
@xref{itofix}.@*
@xref{ftofix}.@*
@xref{fixtof}.@*
@xref{fixfloor}.@*
@xref{fixceil}.@*
@xref{ex12bit}.@*
@xref{ex3buf}.@*
@xref{ex3d}.@*
@xref{exblend}.@*
@xref{excustom}.@*
@xref{exlights}.@*
@xref{exspline}.@*
@xref{exstars}.@*
@xref{exupdate}.@*
@xref{fixed}.@*
@node fixfloor, fixceil, fixtoi, Fixed
@subsection fixfloor
@ftable @asis
@item @t{int fixfloor(fixed x);}
Returns the greatest integer not greater than x. That is, it rounds 
towards negative infinity. Example:
@example

int result;
/* This will put 33 into `result'. */
result = fixfloor(itofix(100) / 3);
/* And this will round down to 16. */
result = fixfloor(itofix(100) / 6);@end example


@end ftable
See also:@*
@xref{fixtoi}.@*
@xref{fixceil}.@*
@xref{fixed}.@*
@node fixceil, ftofix, fixfloor, Fixed
@subsection fixceil
@ftable @asis
@item @t{int fixceil(fixed x);}
Returns the smallest integer not less than x. That is, it rounds towards
positive infinity. Example:
@example

int result;
/* This will put 34 into `result'. */
result = fixceil(itofix(100) / 3);
/* This will round up to 17. */
result = fixceil(itofix(100) / 6);@end example


@end ftable
See also:@*
@xref{fixtoi}.@*
@xref{fixfloor}.@*
@xref{fixed}.@*
@node ftofix, fixtof, fixceil, Fixed
@subsection ftofix
@ftable @asis
@item @t{fixed ftofix(double x);}
Converts a floating point value to fixed point. Unlike itofix(), this
function clamps values which could overflow the type conversion, setting
`errno' to ERANGE in the process if this happens. Example:
@example

fixed number;
number = itofix(-40000);
ASSERT(fixfloor(number) == -32768);
number = itofix(64000);
ASSERT(fixfloor(number) == 32767);
ASSERT(!errno); /* This will fail. */@end example


Returns the value of the floating point value converted to fixed point
clamping overflows (and setting `errno').

@end ftable
See also:@*
@xref{fixtof}.@*
@xref{itofix}.@*
@xref{fixtoi}.@*
@xref{exfixed}.@*
@xref{exspline}.@*
@xref{exupdate}.@*
@xref{fixed}.@*
@node fixtof, fixmul, ftofix, Fixed
@subsection fixtof
@ftable @asis
@item @t{double fixtof(fixed x);}
Converts fixed point to floating point. Example:
@example

float result;

/* This will put 33.33333 into `result'. */
result = fixtof(itofix(100) / 3);
/* This will put 16.66666 into `result'. */
result = fixtof(itofix(100) / 6);@end example


@end ftable
See also:@*
@xref{ftofix}.@*
@xref{itofix}.@*
@xref{fixtoi}.@*
@xref{exfixed}.@*
@xref{exspline}.@*
@xref{exstars}.@*
@xref{fixed}.@*
@node fixmul, fixdiv, fixtof, Fixed
@subsection fixmul
@ftable @asis
@item @t{fixed fixmul(fixed x, fixed y);}
A fixed point value can be multiplied or divided by an integer with the 
normal `*' and `/' operators. To multiply two fixed point values, though,
you must use this function.

If an overflow occurs, `errno' will be set and the maximum possible value
will be returned, but `errno' is not cleared if the operation is
successful. This means that if you are going to test for overflow you
should set `errno=0' before calling fixmul(). Example:
@example

fixed result;

/* This will put 30000 into `result'. */
result = fixmul(itofix(10), itofix(3000));
/* But this overflows, and sets `errno'. */
result = fixmul(itofix(100), itofix(3000));
ASSERT(!errno);@end example


Returns the clamped result of multiplying `x' by `y', setting `errno' to
ERANGE if there was an overflow.

@end ftable
See also:@*
@xref{fixadd}.@*
@xref{fixsub}.@*
@xref{fixdiv}.@*
@xref{ex3buf}.@*
@xref{excustom}.@*
@xref{exfixed}.@*
@xref{exspline}.@*
@xref{exstars}.@*
@xref{exupdate}.@*
@xref{fixed}.@*
@node fixdiv, fixadd, fixmul, Fixed
@subsection fixdiv
@ftable @asis
@item @t{fixed fixdiv(fixed x, fixed y);}
A fixed point value can be divided by an integer with the normal `/'
operator. To divide two fixed point values, though, you must use this
function. If a division by zero occurs, `errno' will be set and the
maximum possible value will be returned, but `errno' is not cleared if the
operation is successful. This means that if you are going to test for
division by zero you should set `errno=0' before calling fixdiv(). Example:
@example

fixed result;
/* This will put 0.06060 `result'. */
result = fixdiv(itofix(2), itofix(33));
/* This will put 0 into `result'. */
result = fixdiv(0, itofix(-30));
/* Sets `errno' and puts -32768 into `result'. */
result = fixdiv(itofix(-100), itofix(0));
ASSERT(!errno); /* This will fail. */@end example


Returns the result of dividing `x' by `y'. If `y' is zero, returns the
maximum possible fixed point value and sets `errno' to ERANGE.

@end ftable
See also:@*
@xref{fixadd}.@*
@xref{fixsub}.@*
@xref{fixmul}.@*
@xref{exfixed}.@*
@xref{fixed}.@*
@node fixadd, fixsub, fixdiv, Fixed
@subsection fixadd
@ftable @asis
@item @t{fixed fixadd(fixed x, fixed y);}
Although fixed point numbers can be added with the normal '+' integer 
operator, that doesn't provide any protection against overflow. If overflow
is a problem, you should use this function instead. It is slower than using
integer operators, but if an overflow occurs it will set `errno' and clamp
the result, rather than just letting it wrap. Example:
@example

fixed result;
/* This will put 5035 into `result'. */
result = fixadd(itofix(5000), itofix(35));
/* Sets `errno' and puts -32768 into `result'. */
result = fixadd(itofix(-31000), itofix(-3000));
ASSERT(!errno); /* This will fail. */@end example


Returns the clamped result of adding `x' to `y', setting `errno' to ERANGE
if there was an overflow.

@end ftable
See also:@*
@xref{fixsub}.@*
@xref{fixmul}.@*
@xref{fixdiv}.@*
@xref{fixed}.@*
@node fixsub, Fixed point trig, fixadd, Fixed
@subsection fixsub
@ftable @asis
@item @t{fixed fixsub(fixed x, fixed y);}
Although fixed point numbers can be subtracted with the normal '-' integer
operator, that doesn't provide any protection against overflow. If overflow
is a problem, you should use this function instead. It is slower than using
integer operators, but if an overflow occurs it will set `errno' and clamp
the result, rather than just letting it wrap. Example:
@example

fixed result;
/* This will put 4965 into `result'. */
result = fixsub(itofix(5000), itofix(35));
/* Sets `errno' and puts -32768 into `result'. */
result = fixsub(itofix(-31000), itofix(3000));
ASSERT(!errno); /* This will fail. */@end example


Returns the clamped result of subtracting `y' from `x', setting `errno' to
ERANGE if there was an overflow.

@end ftable
See also:@*
@xref{fixadd}.@*
@xref{fixmul}.@*
@xref{fixdiv}.@*
@xref{fixed}.@*
@node Fixed point trig, fixtorad_r, fixsub, Fixed
@subsection Fixed point trig
@ftable @asis
@end ftable
The fixed point square root, sin, cos, tan, inverse sin, and inverse cos 
functions are implemented using lookup tables, which are very fast but not 
particularly accurate. At the moment the inverse tan uses an iterative 
search on the tan table, so it is a lot slower than the others. Note that on
machines with very good floating point processors using these functions could
be slower in real life code due to cache misses: it may be faster to wait
a few extra cycles for a floating point sine result rather than wait for the
CPU to fetch the precalculated table from main memory. Always profile your
code.

Angles are represented in a binary format with 256 equal to a full circle, 
64 being a right angle and so on. This has the advantage that a simple 
bitwise 'and' can be used to keep the angle within the range zero to a full
circle, eliminating all those tiresome 'if (angle >= 360)' checks.

@node fixtorad_r, radtofix_r, Fixed point trig, Fixed
@subsection fixtorad_r
@ftable @asis
@item @t{extern const fixed fixtorad_r;}
This constant gives a ratio which can be used to convert a fixed point
number in binary angle format to a fixed point number in radians. Example:
@example

fixed rad_angle, binary_angle;
/* Set the binary angle to 90 degrees. */
binary_angle = 64;
/* Now convert to radians (about 1.57). */
rad_angle = fixmul(binary_angle, fixtorad_r);@end example


@end ftable
See also:@*
@xref{fixmul}.@*
@xref{radtofix_r}.@*
@xref{fixed}.@*
@node radtofix_r, fixsin, fixtorad_r, Fixed
@subsection radtofix_r
@ftable @asis
@item @t{extern const fixed radtofix_r;}
This constant gives a ratio which can be used to convert a fixed point
number in radians to a fixed point number in binary angle format. Example:
@example

fixed rad_angle, binary_angle;
...
binary_angle = fixmul(rad_angle, radtofix_r);@end example


@end ftable
See also:@*
@xref{fixmul}.@*
@xref{fixtorad_r}.@*
@xref{fixed}.@*
@node fixsin, fixcos, radtofix_r, Fixed
@subsection fixsin
@ftable @asis
@item @t{fixed fixsin(fixed x);}
This function finds the sine of a value using a lookup table. The input
value must be a fixed point binary angle. Example:
@example

fixed angle;
int result;

/* Set the binary angle to 90 degrees. */
angle = itofix(64);
/* The sine of 90 degrees is one. */
result = fixtoi(fixsin(angle));
ASSERT(result == 1);@end example


Returns the sine of a fixed point binary format angle. The return value
will be in radians.

@end ftable
See also:@*
@xref{Fixed point trig}.@*
@xref{ex12bit}.@*
@xref{ex3buf}.@*
@xref{exblend}.@*
@xref{excustom}.@*
@xref{exspline}.@*
@xref{exupdate}.@*
@xref{fixed}.@*
@node fixcos, fixtan, fixsin, Fixed
@subsection fixcos
@ftable @asis
@item @t{fixed fixcos(fixed x);}
This function finds the cosine of a value using a lookup table. The input
value must be a fixed point binary angle. Example:
@example

fixed angle;
float result;

/* Set the binary angle to 45 degrees. */
angle = itofix(32);
/* The cosine of 45 degrees is about 0.7071. */
result = fixtof(fixcos(angle));
ASSERT(result > 0.7 && result < 0.71);@end example


Returns the cosine of a fixed point binary format angle. The return value
will be in radians.

@end ftable
See also:@*
@xref{Fixed point trig}.@*
@xref{ex12bit}.@*
@xref{ex3buf}.@*
@xref{exblend}.@*
@xref{excustom}.@*
@xref{exspline}.@*
@xref{exupdate}.@*
@xref{fixed}.@*
@node fixtan, fixasin, fixcos, Fixed
@subsection fixtan
@ftable @asis
@item @t{fixed fixtan(fixed x);}
This function finds the tangent of a value using a lookup table. The input
value must be a fixed point binary angle. Example:
@example

fixed angle, res_a, res_b;
float dif;

angle = itofix(37);
/* Prove that tan(angle) == sin(angle) / cos(angle). */
res_a = fixdiv(fixsin(angle), fixcos(angle));
res_b = fixtan(angle);
dif = fixtof(fixsub(res_a, res_b));
allegro_message("Precision error: %f\n", dif);@end example


Returns the tangent of a fixed point binary format angle. The return value
will be in radians.

@end ftable
See also:@*
@xref{Fixed point trig}.@*
@xref{fixed}.@*
@node fixasin, fixacos, fixtan, Fixed
@subsection fixasin
@ftable @asis
@item @t{fixed fixasin(fixed x);}
This function finds the inverse sine of a value using a lookup table. The
input value must be a fixed point value. The inverse sine is defined only
in the domain from `-1' to `1'. Outside of this input range, the function
will set `errno' to EDOM and return zero. Example:
@example

float angle;
fixed val;

/* Sets `val' to a right binary angle (`64'). */
val = fixasin(itofix(1));
/* Sets `angle' to 0.2405. */
angle = fixtof(fixmul(fixasin(ftofix(0.238)), fixtorad_r));
/* This will trigger the assert. */
val = fixasin(ftofix(-1.09));
ASSERT(!errno);@end example


Returns the inverse sine of a fixed point value, measured as fixed point
binary format angle, or zero if the input was out of the range. All return
values of this function will be in the range `-64' to `64'.

@end ftable
See also:@*
@xref{Fixed point trig}.@*
@xref{fixed}.@*
@node fixacos, fixatan, fixasin, Fixed
@subsection fixacos
@ftable @asis
@item @t{fixed fixacos(fixed x);}
This function finds the inverse cosine of a value using a lookup table. The
input value must be a fixed point radian. The inverse cosine is defined
only in the domain from `-1' to `1'. Outside of this input range, the
function will set `errno' to EDOM and return zero. Example:
@example

fixed result;

/* Sets `result' to binary angle 128. */
result = fixacos(itofix(-1));@end example


Returns the inverse sine of a fixed point value, measured as fixed point
binary format angle, or zero if the input was out of range. All return
values of this function will be in the range `0' to `128'.

@end ftable
See also:@*
@xref{Fixed point trig}.@*
@xref{fixed}.@*
@node fixatan, fixatan2, fixacos, Fixed
@subsection fixatan
@ftable @asis
@item @t{fixed fixatan(fixed x);}
This function finds the inverse tangent of a value using a lookup table.
The input value must be a fixed point radian. The inverse tangent is the
value whose tangent is `x'. Example:
@example

fixed result;

/* Sets `result' to binary angle 13. */
result = fixatan(ftofix(0.326));@end example


Returns the inverse tangent of a fixed point value, measured as a fixed
point binary format angle.

@end ftable
See also:@*
@xref{Fixed point trig}.@*
@xref{fixed}.@*
@node fixatan2, fixsqrt, fixatan, Fixed
@subsection fixatan2
@ftable @asis
@item @t{fixed fixatan2(fixed y, fixed x);}
This is a fixed point version of the libc atan2() routine. It computes the
arc tangent of `y / x', but the signs of both arguments are used to
determine the quadrant of the result, and `x' is permitted to be zero. This
function is useful to convert Cartesian coordinates to polar coordinates.
Example:
@example

fixed result;

/* Sets `result' to binary angle 64. */
result = fixatan2(itofix(1), 0);
/* Sets `result' to binary angle -109. */
result = fixatan2(itofix(-1), itofix(-2));
/* Fails the assert. */
result = fixatan2(0, 0);
ASSERT(!errno);@end example


Returns the arc tangent of `y / x' in fixed point binary format angle,
from `-128' to `128'. If both `x' and `y' are zero, returns zero and sets
`errno' to EDOM.

@end ftable
See also:@*
@xref{Fixed point trig}.@*
@xref{exlights}.@*
@xref{exspline}.@*
@xref{fixed}.@*
@node fixsqrt, fixhypot, fixatan2, Fixed
@subsection fixsqrt
@ftable @asis
@item @t{fixed fixsqrt(fixed x);}
This finds out the non negative square root of `x'. If `x' is negative,
`errno' is set to EDOM and the function returns zero.

@end ftable
See also:@*
@xref{Fixed point trig}.@*
@xref{exfixed}.@*
@xref{exlights}.@*
@xref{exspline}.@*
@xref{fixed}.@*
@node fixhypot, Fix class, fixsqrt, Fixed
@subsection fixhypot
@ftable @asis
@item @t{fixed fixhypot(fixed x, fixed y);}
Fixed point hypotenuse (returns the square root of `x*x + y*y'). This
should be better than calculating the formula yourself manually, since
the error is much smaller.

@end ftable
See also:@*
@xref{Fixed point trig}.@*
@xref{fixed}.@*
@node Fix class, identity_matrix, fixhypot, Fixed
@subsection Fix class
@ftable @asis
@end ftable
If you are programming in C++ you can ignore all the above and use the fix 
class instead, which overloads a lot of operators to provide automatic 
conversion to and from integer and floating point values, and calls the 
above routines as they are required. You should not mix the fix class with 
the fixed typedef though, because the compiler will mistake the fixed values 
for regular integers and insert unnecessary conversions. For example, if x 
is an object of class fix, calling fixsqrt(x) will return the wrong result. 
You should use the overloaded sqrt(x) or x.sqrt() instead.

On top of that, the Fix class may be slower than using directly the C
functions because of implicit internal conversions from one type to another
which you otherwise could avoid or minimise. Finally, this is the only bit
of C++ in the whole Allegro library, and the developers are certainly going
to move it into add-on space in the next version of Allegro which breaks
source backwards compatibility.



@node 3D, Quaternion, Fixed, API
@section 3D math routines

Allegro contains some 3d helper functions for manipulating vectors, 
constructing and using transformation matrices, and doing perspective 
projections from 3d space onto the screen. It is not, and never will be, a 
fully fledged 3d library (the goal is to supply generic support routines,
not shrink-wrapped graphics code :-) but these functions may be useful for 
developing your own 3d code.

Allegro uses a right-handed coordinate system, i.e. if you point the thumb 
of your right hand along the x axis, and the index finger along the y axis, 
your middle finger points in the direction of the z axis.

Allegro's world coordinate system typically has the positive x axis right,
the positive y axis up, and the positive z axis out of the screen.  What
all this means is this: Assume, the viewer is located at the origin (0/0/0)
in world space, looks along the negative z axis (0/0/-1), and is oriented
so up is along the positive y axis (0/1/0). Then something located at
(100/200/-300) will be 100 to the right, 200 above, and 300 in front of the
viewer. Just like in OpenGL. (Of course, both OpenGL and Allegro allow to
use a different system.) Here's a short piece of code demonstrating the
transformation pipeline of a point from world space to the screen.

@example

/* First, set up the projection viewport. */
set_projection_viewport (0, 0, SCREEN_W, SCREEN_H);

/* Next, get a camera matrix, depending on the
 * current viewer position and orientation.
 */
get_camera_matrix_f (&m,
   0, 0, 0,  /* Viewer position, in this case, 0/0/0. */
   0, 0, -1, /* Viewer direction, in this case along negative z. */
   0, 1, 0,  /* Up vector, in this case positive y. */
   32,       /* The FOV, here 45°. */
   (float)SCREEN_W / (float)SCREEN_H)); /* Aspect ratio. */

/* Applying the matrix transforms the point 100/200/-300
 * from world space into camera space. The transformation
 * moves and rotates the point so it is relative to the
 * camera, scales it according to the FOV and aspect
 * parameters, and also flips up and front direction -
 * ready to project the point to the viewport.
 */
apply_matrix_f (&m, 100, 200, -300, &x, &y, &z);

/* Finally, the point is projected from
 * camera space to the screen.
 */
persp_project_f (cx, cy, cz, &sx, &sy);@end example


For more details, look at the function descriptions of
set_projection_viewport(), get_camera_matrix(), and persp_project(), as well
as the relevant example programs.

All the 3d math functions are available in two versions: one which uses 
fixed point arithmetic, and another which uses floating point. The syntax 
for these is identical, but the floating point functions and structures are 
postfixed with '_f', eg. the fixed point function cross_product() has a 
floating point equivalent cross_product_f(). If you are programming in C++, 
Allegro also overloads these functions for use with the 'fix' class.

3d transformations are accomplished by the use of a modelling matrix. This 
is a 4x4 array of numbers that can be multiplied with a 3d point to produce 
a different 3d point. By putting the right values into the matrix, it can be 
made to do various operations like translation, rotation, and scaling. The 
clever bit is that you can multiply two matrices together to produce a third 
matrix, and this will have the same effect on points as applying the 
original two matrices one after the other. For example, if you have one 
matrix that rotates a point and another that shifts it sideways, you can 
combine them to produce a matrix that will do the rotation and the shift in 
a single step. You can build up extremely complex transformations in this 
way, while only ever having to multiply each point by a single matrix.

Allegro actually cheats in the way it implements the matrix structure. 
Rotation and scaling of a 3d point can be done with a simple 3x3 matrix, but 
in order to translate it and project it onto the screen, the matrix must be 
extended to 4x4, and the point extended into 4d space by the addition of an 
extra coordinate, w=1. This is a bad thing in terms of efficiency, but 
fortunately an optimisation is possible. Given the 4x4 matrix:
@example

( a, b, c, d )
( e, f, g, h )
( i, j, k, l )
( m, n, o, p )
@end example

a pattern can be observed in which parts of it do what. The top left 3x3 
grid implements rotation and scaling. The three values in the top right 
column (d, h, and l) implement translation, and as long as the matrix is 
only used for affine transformations, m, n and o will always be zero and p 
will always be 1. If you don't know what affine means, read Foley & Van 
Damme: basically it covers scaling, translation, and rotation, but not 
projection. Since Allegro uses a separate function for projection, the 
matrix functions only need to support affine transformations, which means 
that there is no need to store the bottom row of the matrix. Allegro 
implicitly assumes that it contains (0,0,0,1), and optimises the matrix 
manipulation functions accordingly. Read chapter "Structures and types
defined by Allegro" for an internal view of the MATRIX/_f structures.

@menu
* identity_matrix::
* get_translation_matrix::
* get_scaling_matrix::
* get_x_rotate_matrix::
* get_y_rotate_matrix::
* get_z_rotate_matrix::
* get_rotation_matrix::
* get_align_matrix::
* get_align_matrix_f::
* get_vector_rotation_matrix::
* get_transformation_matrix::
* get_transformation_matrix_f::
* get_camera_matrix::
* get_camera_matrix_f::
* qtranslate_matrix::
* qscale_matrix::
* matrix_mul::
* vector_length::
* normalize_vector::
* dot_product::
* cross_product::
* polygon_z_normal::
* apply_matrix::
* set_projection_viewport::
* persp_project::
@end menu
@node identity_matrix, get_translation_matrix, Fix class, 3D
@subsection identity_matrix
@ftable @asis
@item @t{extern MATRIX identity_matrix;}
@end ftable
@ftable @asis
@item @t{extern MATRIX_f identity_matrix_f;}
Global variables containing the 'do nothing' identity matrix. Multiplying 
by the identity matrix has no effect.

@end ftable
@xref{MATRIX}.@*
@xref{MATRIX_f}.@*
@node get_translation_matrix, get_scaling_matrix, identity_matrix, 3D
@subsection get_translation_matrix
@ftable @asis
@item @t{void get_translation_matrix(MATRIX *m, fixed x, fixed y, fixed z);}
@end ftable
@ftable @asis
@item @t{void get_translation_matrix_f(MATRIX_f *m, float x, float y, float z);}
Constructs a translation matrix, storing it in m. When applied to the 
point (px, py, pz), this matrix will produce the point (px+x, py+y, 
pz+z). In other words, it moves things sideways.

@end ftable
See also:@*
@xref{apply_matrix}.@*
@xref{get_transformation_matrix}.@*
@xref{qtranslate_matrix}.@*
@xref{exstars}.@*
@xref{fixed}.@*
@xref{MATRIX}.@*
@xref{MATRIX_f}.@*
@node get_scaling_matrix, get_x_rotate_matrix, get_translation_matrix, 3D
@subsection get_scaling_matrix
@ftable @asis
@item @t{void get_scaling_matrix(MATRIX *m, fixed x, fixed y, fixed z);}
@end ftable
@ftable @asis
@item @t{void get_scaling_matrix_f(MATRIX_f *m, float x, float y, float z);}
Constructs a scaling matrix, storing it in m. When applied to the point 
(px, py, pz), this matrix will produce the point (px*x, py*y, pz*z). In 
other words, it stretches or shrinks things.

@end ftable
See also:@*
@xref{apply_matrix}.@*
@xref{get_transformation_matrix}.@*
@xref{qscale_matrix}.@*
@xref{fixed}.@*
@xref{MATRIX}.@*
@xref{MATRIX_f}.@*
@node get_x_rotate_matrix, get_y_rotate_matrix, get_scaling_matrix, 3D
@subsection get_x_rotate_matrix
@ftable @asis
@item @t{void get_x_rotate_matrix(MATRIX *m, fixed r);}
@end ftable
@ftable @asis
@item @t{void get_x_rotate_matrix_f(MATRIX_f *m, float r);}
Construct X axis rotation matrices, storing them in m. When applied to a 
point, these matrices will rotate it about the X axis by the specified 
angle (given in binary, 256 degrees to a circle format).

@end ftable
See also:@*
@xref{apply_matrix}.@*
@xref{get_rotation_matrix}.@*
@xref{get_y_rotate_matrix}.@*
@xref{get_z_rotate_matrix}.@*
@xref{fixed}.@*
@xref{MATRIX}.@*
@xref{MATRIX_f}.@*
@node get_y_rotate_matrix, get_z_rotate_matrix, get_x_rotate_matrix, 3D
@subsection get_y_rotate_matrix
@ftable @asis
@item @t{void get_y_rotate_matrix(MATRIX *m, fixed r);}
@end ftable
@ftable @asis
@item @t{void get_y_rotate_matrix_f(MATRIX_f *m, float r);}
Construct Y axis rotation matrices, storing them in m. When applied to a 
point, these matrices will rotate it about the Y axis by the specified 
angle (given in binary, 256 degrees to a circle format).

@end ftable
See also:@*
@xref{apply_matrix}.@*
@xref{get_rotation_matrix}.@*
@xref{get_x_rotate_matrix}.@*
@xref{get_z_rotate_matrix}.@*
@xref{fixed}.@*
@xref{MATRIX}.@*
@xref{MATRIX_f}.@*
@node get_z_rotate_matrix, get_rotation_matrix, get_y_rotate_matrix, 3D
@subsection get_z_rotate_matrix
@ftable @asis
@item @t{void get_z_rotate_matrix(MATRIX *m, fixed r);}
@end ftable
@ftable @asis
@item @t{void get_z_rotate_matrix_f(MATRIX_f *m, float r);}
Construct Z axis rotation matrices, storing them in m. When applied to a 
point, these matrices will rotate it about the Z axis by the specified 
angle (given in binary, 256 degrees to a circle format).

@end ftable
See also:@*
@xref{apply_matrix}.@*
@xref{get_rotation_matrix}.@*
@xref{get_x_rotate_matrix}.@*
@xref{get_y_rotate_matrix}.@*
@xref{fixed}.@*
@xref{MATRIX}.@*
@xref{MATRIX_f}.@*
@node get_rotation_matrix, get_align_matrix, get_z_rotate_matrix, 3D
@subsection get_rotation_matrix
@ftable @asis
@item @t{void get_rotation_matrix(MATRIX *m, fixed x, fixed y, fixed z);}
@end ftable
@ftable @asis
@item @t{void get_rotation_matrix_f(MATRIX_f *m, float x, float y, float z);}
Constructs a transformation matrix which will rotate points around all
three axes by the specified amounts (given in binary, 256 degrees to a
circle format). The direction of rotation can simply be found out with
the right-hand rule: Point the dumb of your right hand towards the
origin along the axis of rotation, and the fingers will curl in the
positive direction of rotation. E.g. if you rotate around the y axis,
and look at the scene from above, a positive angle will rotate in
clockwise direction.

@end ftable
See also:@*
@xref{apply_matrix}.@*
@xref{get_transformation_matrix}.@*
@xref{get_vector_rotation_matrix}.@*
@xref{get_x_rotate_matrix}.@*
@xref{get_y_rotate_matrix}.@*
@xref{get_z_rotate_matrix}.@*
@xref{get_align_matrix}.@*
@xref{ex12bit}.@*
@xref{exquat}.@*
@xref{exstars}.@*
@xref{fixed}.@*
@xref{MATRIX}.@*
@xref{MATRIX_f}.@*
@node get_align_matrix, get_align_matrix_f, get_rotation_matrix, 3D
@subsection get_align_matrix
@ftable @asis
@item @t{void get_align_matrix(MATRIX *m, fixed xfront, yfront, zfront,  fixed xup, fixed yup, fixed zup);}
Rotates a matrix so that it is aligned along the specified coordinate 
vectors (they need not be normalized or perpendicular, but the up and 
front must not be equal). A front vector of 0,0,-1 and up vector of 0,1,0 
will return the identity matrix.

@end ftable
See also:@*
@xref{apply_matrix}.@*
@xref{get_camera_matrix}.@*
@xref{fixed}.@*
@xref{MATRIX}.@*
@node get_align_matrix_f, get_vector_rotation_matrix, get_align_matrix, 3D
@subsection get_align_matrix_f
@ftable @asis
@item @t{void get_align_matrix_f(MATRIX *m, float xfront, yfront, zfront,  float xup, yup, zup);}
Floating point version of get_align_matrix().

@end ftable
See also:@*
@xref{get_align_matrix}.@*
@xref{MATRIX}.@*
@node get_vector_rotation_matrix, get_transformation_matrix, get_align_matrix_f, 3D
@subsection get_vector_rotation_matrix
@ftable @asis
@item @t{void get_vector_rotation_matrix(MATRIX *m, fixed x, y, z, fixed a);}
@end ftable
@ftable @asis
@item @t{void get_vector_rotation_matrix_f(MATRIX_f *m, float x, y, z, float a);}
Constructs a transformation matrix which will rotate points around the 
specified x,y,z vector by the specified angle (given in binary, 256 
degrees to a circle format).

@end ftable
See also:@*
@xref{apply_matrix}.@*
@xref{get_rotation_matrix}.@*
@xref{get_align_matrix}.@*
@xref{excamera}.@*
@xref{fixed}.@*
@xref{MATRIX}.@*
@xref{MATRIX_f}.@*
@node get_transformation_matrix, get_transformation_matrix_f, get_vector_rotation_matrix, 3D
@subsection get_transformation_matrix
@ftable @asis
@item @t{void get_transformation_matrix(MATRIX *m, fixed scale, fixed xrot, yrot, zrot, x, y, z);}
Constructs a transformation matrix which will rotate points around all 
three axes by the specified amounts (given in binary, 256 degrees to a 
circle format), scale the result by the specified amount (pass 1 for no 
change of scale), and then translate to the requested x, y, z position.

@end ftable
See also:@*
@xref{apply_matrix}.@*
@xref{get_rotation_matrix}.@*
@xref{get_scaling_matrix}.@*
@xref{get_translation_matrix}.@*
@xref{ex3d}.@*
@xref{exstars}.@*
@xref{fixed}.@*
@xref{MATRIX}.@*
@node get_transformation_matrix_f, get_camera_matrix, get_transformation_matrix, 3D
@subsection get_transformation_matrix_f
@ftable @asis
@item @t{void get_transformation_matrix_f(MATRIX_f *m, float scale, float xrot, yrot, zrot, x, y, z);}
Floating point version of get_transformation_matrix().

@end ftable
See also:@*
@xref{get_transformation_matrix}.@*
@xref{exzbuf}.@*
@xref{MATRIX_f}.@*
@node get_camera_matrix, get_camera_matrix_f, get_transformation_matrix_f, 3D
@subsection get_camera_matrix
@ftable @asis
@item @t{void get_camera_matrix(MATRIX *m, fixed x, y, z, xfront, yfront, zfront, fixed xup, yup, zup, fov, aspect);}
Constructs a camera matrix for translating world-space objects into a
normalised view space, ready for the perspective projection. The x, y,
and z parameters specify the camera position, xfront, yfront, and zfront
are the 'in front' vector specifying which way the camera is facing
(this can be any length: normalisation is not required), and xup, yup,
and zup are the 'up' direction vector.

The fov parameter specifies the field of view (ie. width of the camera
focus) in binary, 256 degrees to the circle format. For typical
projections, a field of view in the region 32-48 will work well. 64
(90°) applies no extra scaling - so something which is one unit away
from the viewer will be directly scaled to the viewport. A bigger FOV
moves you closer to the viewing plane, so more objects will appear. A
smaller FOV moves you away from the viewing plane, which means you see a
smaller part of the world.

Finally, the aspect ratio is used to scale the Y dimensions of the image
relative to the X axis, so you can use it to adjust the proportions of
the output image (set it to 1 for no scaling - but keep in mind that the
projection also performs scaling according to the viewport size).
Typically, you will pass (float)w/(float)h, where w and h are the
parameters you passed to set_projection_viewport.

Note that versions prior to 4.1.0 multiplied this aspect ratio by 4/3.

@end ftable
See also:@*
@xref{apply_matrix}.@*
@xref{get_align_matrix}.@*
@xref{set_projection_viewport}.@*
@xref{persp_project}.@*
@xref{fixed}.@*
@xref{MATRIX}.@*
@node get_camera_matrix_f, qtranslate_matrix, get_camera_matrix, 3D
@subsection get_camera_matrix_f
@ftable @asis
@item @t{void get_camera_matrix_f(MATRIX_f *m, float x, y, z, xfront, yfront, zfront, float xup, yup, zup, fov, aspect);}
Floating point version of get_camera_matrix().

@end ftable
See also:@*
@xref{get_camera_matrix}.@*
@xref{excamera}.@*
@xref{exquat}.@*
@xref{MATRIX_f}.@*
@node qtranslate_matrix, qscale_matrix, get_camera_matrix_f, 3D
@subsection qtranslate_matrix
@ftable @asis
@item @t{void qtranslate_matrix(MATRIX *m, fixed x, fixed y, fixed z);}
@end ftable
@ftable @asis
@item @t{void qtranslate_matrix_f(MATRIX_f *m, float x, float y, float z);}
Optimised routine for translating an already generated matrix: this 
simply adds in the translation offset, so there is no need to build two 
temporary matrices and then multiply them together.

@end ftable
See also:@*
@xref{get_translation_matrix}.@*
@xref{fixed}.@*
@xref{MATRIX}.@*
@xref{MATRIX_f}.@*
@node qscale_matrix, matrix_mul, qtranslate_matrix, 3D
@subsection qscale_matrix
@ftable @asis
@item @t{void qscale_matrix(MATRIX *m, fixed scale);}
@end ftable
@ftable @asis
@item @t{void qscale_matrix_f(MATRIX_f *m, float scale);}
Optimised routine for scaling an already generated matrix: this simply 
adds in the scale factor, so there is no need to build two temporary 
matrices and then multiply them together.

@end ftable
See also:@*
@xref{get_scaling_matrix}.@*
@xref{fixed}.@*
@xref{MATRIX}.@*
@xref{MATRIX_f}.@*
@node matrix_mul, vector_length, qscale_matrix, 3D
@subsection matrix_mul
@ftable @asis
@item @t{void matrix_mul(const MATRIX *m1, const MATRIX *m2, MATRIX *out);}
@end ftable
@ftable @asis
@item @t{void matrix_mul_f(const MATRIX_f *m1, const MATRIX_f *m2, MATRIX_f *out);}
Multiplies two matrices, storing the result in out (this may be a 
duplicate of one of the input matrices, but it is faster when the inputs 
and output are all different). The resulting matrix will have the same 
effect as the combination of m1 and m2, ie. when applied to a point p, (p 
* out) = ((p * m1) * m2). Any number of transformations can be 
concatenated in this way. Note that matrix multiplication is not 
commutative, ie. matrix_mul(m1, m2) != matrix_mul(m2, m1).

@end ftable
See also:@*
@xref{apply_matrix}.@*
@xref{exquat}.@*
@xref{exscn3d}.@*
@xref{MATRIX}.@*
@xref{MATRIX_f}.@*
@node vector_length, normalize_vector, matrix_mul, 3D
@subsection vector_length
@ftable @asis
@item @t{fixed vector_length(fixed x, fixed y, fixed z);}
@end ftable
@ftable @asis
@item @t{float vector_length_f(float x, float y, float z);}
Calculates the length of the vector (x, y, z), using that good 'ole 
Pythagoras theorem.

@end ftable
See also:@*
@xref{normalize_vector}.@*
@xref{fixed}.@*
@node normalize_vector, dot_product, vector_length, 3D
@subsection normalize_vector
@ftable @asis
@item @t{void normalize_vector(fixed *x, fixed *y, fixed *z);}
@end ftable
@ftable @asis
@item @t{void normalize_vector_f(float *x, float *y, float *z);}
Converts the vector (*x, *y, *z) to a unit vector. This points in the 
same direction as the original vector, but has a length of one.

@end ftable
See also:@*
@xref{vector_length}.@*
@xref{dot_product}.@*
@xref{cross_product}.@*
@xref{exstars}.@*
@xref{fixed}.@*
@node dot_product, cross_product, normalize_vector, 3D
@subsection dot_product
@ftable @asis
@item @t{fixed dot_product(fixed x1, y1, z1, x2, y2, z2);}
@end ftable
@ftable @asis
@item @t{float dot_product_f(float x1, y1, z1, x2, y2, z2);}
Calculates the dot product (x1, y1, z1) . (x2, y2, z2), returning the 
result.

@end ftable
See also:@*
@xref{cross_product}.@*
@xref{normalize_vector}.@*
@xref{exstars}.@*
@xref{fixed}.@*
@node cross_product, polygon_z_normal, dot_product, 3D
@subsection cross_product
@ftable @asis
@item @t{void cross_product(fixed x1, y1, z1, x2, y2, z2, *xout, *yout, *zout);}
@end ftable
@ftable @asis
@item @t{void cross_product_f(float x1, y1, z1, x2, y2, z2, *xout, *yout, *zout);}
Calculates the cross product (x1, y1, z1) x (x2, y2, z2), storing the 
result in (*xout, *yout, *zout). The cross product is perpendicular to 
both of the input vectors, so it can be used to generate polygon normals.

@end ftable
See also:@*
@xref{dot_product}.@*
@xref{polygon_z_normal}.@*
@xref{normalize_vector}.@*
@xref{exstars}.@*
@xref{fixed}.@*
@node polygon_z_normal, apply_matrix, cross_product, 3D
@subsection polygon_z_normal
@ftable @asis
@item @t{fixed polygon_z_normal(const V3D *v1, const V3D *v2, const V3D *v3);}
@end ftable
@ftable @asis
@item @t{float polygon_z_normal_f(const V3D_f *v1, const V3D_f *v2, const V3D_f *v3);}
Finds the Z component of the normal vector to the specified three 
vertices (which must be part of a convex polygon). This is used mainly in 
back-face culling. The back-faces of closed polyhedra are never visible 
to the viewer, therefore they never need to be drawn. This can cull on 
average half the polygons from a scene. If the normal is negative the 
polygon can safely be culled. If it is zero, the polygon is perpendicular 
to the screen.

However, this method of culling back-faces must only be used once the X and
Y coordinates have been projected into screen space using persp_project()
(or if an orthographic (isometric) projection is being used). Note that
this function will fail if the three vertices are co-linear (they lie on
the same line) in 3D space.

@end ftable
See also:@*
@xref{cross_product}.@*
@xref{ex3d}.@*
@xref{fixed}.@*
@xref{V3D}.@*
@xref{V3D_f}.@*
@node apply_matrix, set_projection_viewport, polygon_z_normal, 3D
@subsection apply_matrix
@ftable @asis
@item @t{void apply_matrix(const MATRIX *m, fixed x, y, z, *xout, *yout, *zout);}
@end ftable
@ftable @asis
@item @t{void apply_matrix_f(const MATRIX_f *m, float x, y, z, *xout, *yout, *zout);}
Multiplies the point (x, y, z) by the transformation matrix m, storing 
the result in (*xout, *yout, *zout).

@end ftable
See also:@*
@xref{matrix_mul}.@*
@xref{ex12bit}.@*
@xref{ex3d}.@*
@xref{exstars}.@*
@xref{fixed}.@*
@xref{MATRIX}.@*
@xref{MATRIX_f}.@*
@node set_projection_viewport, persp_project, apply_matrix, 3D
@subsection set_projection_viewport
@ftable @asis
@item @t{void set_projection_viewport(int x, int y, int w, int h);}
Sets the viewport used to scale the output of the persp_project()
function. Pass the dimensions of the screen area you want to draw onto,
which will typically be 0, 0, SCREEN_W, and SCREEN_H. Also don't forget
to pass an appropriate aspect ratio to get_camera_matrix later. The
width and height you specify here will determine how big your viewport
is in 3d space. So if an object in your 3D space is w units wide, it
will fill the complete screen when you run into it (i.e., if it has a
distance of 1.0 after the camera matrix was applied. The fov and
aspect-ratio parameters to get_camera_matrix also apply some scaling
though, so this isn't always completely true). If you pass -1/-1/2/2 as
parameters, no extra scaling will be performed by the projection.

@end ftable
See also:@*
@xref{persp_project}.@*
@xref{get_camera_matrix}.@*
@xref{ex3d}.@*
@xref{excamera}.@*
@xref{exquat}.@*
@xref{exscn3d}.@*
@xref{exstars}.@*
@xref{exzbuf}.@*
@node persp_project, identity_quat, set_projection_viewport, 3D
@subsection persp_project
@ftable @asis
@item @t{void persp_project(fixed x, fixed y, fixed z, fixed *xout, fixed *yout);}
@end ftable
@ftable @asis
@item @t{void persp_project_f(float x, float y, float z, float *xout, float *yout);}
Projects the 3d point (x, y, z) into 2d screen space, storing the result 
in (*xout, *yout) and using the scaling parameters previously set by 
calling set_projection_viewport(). This function projects from the 
normalized viewing pyramid, which has a camera at the origin and facing 
along the positive z axis. The x axis runs left/right, y runs up/down, 
and z increases with depth into the screen. The camera has a 90 degree 
field of view, ie. points on the planes x=z and -x=z will map onto the 
left and right edges of the screen, and the planes y=z and -y=z map to 
the top and bottom of the screen. If you want a different field of view 
or camera location, you should transform all your objects with an 
appropriate viewing matrix, eg. to get the effect of panning the camera 
10 degrees to the left, rotate all your objects 10 degrees to the right.



@end ftable
See also:@*
@xref{set_projection_viewport}.@*
@xref{get_camera_matrix}.@*
@xref{ex3d}.@*
@xref{exstars}.@*
@xref{fixed}.@*
@node Quaternion, GUI, 3D, API
@section Quaternion math routines

Quaternions are an alternate way to represent the rotation part of a
transformation, and can be easier to manipulate than matrices. As with a 
matrix, you can encode a geometric transformations in one, concatenate 
several of them to merge multiple transformations, and apply them to a 
vector, but they can only store pure rotations. The big advantage is that 
you can accurately interpolate between two quaternions to get a part-way 
rotation, avoiding the gimbal problems of the more conventional Euler angle 
interpolation.

Quaternions only have floating point versions, without any _f suffix. Other 
than that, most of the quaternion functions correspond with a matrix 
function that performs a similar operation.

Quaternion means 'of four parts', and that's exactly what it is. Here is the 
structure:
@example

typedef struct QUAT
@{
   float w, x, y, z;
@}
@end example

You will have lots of fun figuring out what these numbers actually mean, but 
that is beyond the scope of this documentation. Quaternions do work -- trust 
me.

@menu
* identity_quat::
* get_x_rotate_quat::
* get_rotation_quat::
* get_vector_rotation_quat::
* quat_to_matrix::
* matrix_to_quat::
* quat_mul::
* apply_quat::
* quat_interpolate::
* quat_slerp::
@end menu
@node identity_quat, get_x_rotate_quat, persp_project, Quaternion
@subsection identity_quat
@ftable @asis
@item @t{extern QUAT identity_quat;}
Global variable containing the 'do nothing' identity quaternion. 
Multiplying by the identity quaternion has no effect.

@end ftable
@xref{QUAT}.@*
@node get_x_rotate_quat, get_rotation_quat, identity_quat, Quaternion
@subsection get_x_rotate_quat
@ftable @asis
@item @t{void get_x_rotate_quat(QUAT *q, float r);}
@end ftable
@ftable @asis
@item @t{void get_y_rotate_quat(QUAT *q, float r);}
@end ftable
@ftable @asis
@item @t{void get_z_rotate_quat(QUAT *q, float r);}
Construct axis rotation quaternions, storing them in q. When applied to a 
point, these quaternions will rotate it about the relevant axis by the 
specified angle (given in binary, 256 degrees to a circle format).

@end ftable
@xref{QUAT}.@*
@node get_rotation_quat, get_vector_rotation_quat, get_x_rotate_quat, Quaternion
@subsection get_rotation_quat
@ftable @asis
@item @t{void get_rotation_quat(QUAT *q, float x, float y, float z);}
Constructs a quaternion that will rotate points around all three axes by 
the specified amounts (given in binary, 256 degrees to a circle format).

@end ftable
See also:@*
@xref{exquat}.@*
@xref{QUAT}.@*
@node get_vector_rotation_quat, quat_to_matrix, get_rotation_quat, Quaternion
@subsection get_vector_rotation_quat
@ftable @asis
@item @t{void get_vector_rotation_quat(QUAT *q, float x, y, z, float a);}
Constructs a quaternion that will rotate points around the specified 
x,y,z vector by the specified angle (given in binary, 256 degrees to a 
circle format).

@end ftable
@xref{QUAT}.@*
@node quat_to_matrix, matrix_to_quat, get_vector_rotation_quat, Quaternion
@subsection quat_to_matrix
@ftable @asis
@item @t{void quat_to_matrix(const QUAT *q, MATRIX_f *m);}
Constructs a rotation matrix from a quaternion.

@end ftable
See also:@*
@xref{exquat}.@*
@xref{MATRIX_f}.@*
@xref{QUAT}.@*
@node matrix_to_quat, quat_mul, quat_to_matrix, Quaternion
@subsection matrix_to_quat
@ftable @asis
@item @t{void matrix_to_quat(const MATRIX_f *m, QUAT *q);}
Constructs a quaternion from a rotation matrix. Translation is discarded 
during the conversion. Use get_align_matrix_f() if the matrix is not 
orthonormalized, because strange things may happen otherwise.

@end ftable
@xref{MATRIX_f}.@*
@xref{QUAT}.@*
@node quat_mul, apply_quat, matrix_to_quat, Quaternion
@subsection quat_mul
@ftable @asis
@item @t{void quat_mul(const QUAT *p, const QUAT *q, QUAT *out);}
Multiplies two quaternions, storing the result in out. The resulting 
quaternion will have the same effect as the combination of p and q, ie. 
when applied to a point, (point * out) = ((point * p) * q). Any number of 
rotations can be concatenated in this way. Note that quaternion 
multiplication is not commutative, ie. quat_mul(p, q) != quat_mul(q, p). 

@end ftable
@xref{QUAT}.@*
@node apply_quat, quat_interpolate, quat_mul, Quaternion
@subsection apply_quat
@ftable @asis
@item @t{void apply_quat(const QUAT *q, float x, y, z, *xout, *yout, *zout);}
Multiplies the point (x, y, z) by the quaternion q, storing the result in 
(*xout, *yout, *zout). This is quite a bit slower than apply_matrix_f(), 
so only use it to translate a few points. If you have many points, it is 
much more efficient to call quat_to_matrix() and then use 
apply_matrix_f().

@end ftable
@xref{QUAT}.@*
@node quat_interpolate, quat_slerp, apply_quat, Quaternion
@subsection quat_interpolate
@ftable @asis
@item @t{void quat_interpolate(const QUAT *from, const QUAT *to, float t, QUAT *out);}
Constructs a quaternion that represents a rotation between from and to. 
The argument t can be anything between 0 and 1 and represents where 
between from and to the result will be. 0 returns from, 1 returns to, and 
0.5 will return a rotation exactly in between. The result is copied to 
out. This function will create the short rotation (less than 180 degrees) 
between from and to.

@end ftable
See also:@*
@xref{exquat}.@*
@xref{QUAT}.@*
@node quat_slerp, d_clear_proc, quat_interpolate, Quaternion
@subsection quat_slerp
@ftable @asis
@item @t{void quat_slerp(const QUAT *from, const QUAT *to, float t, QUAT *out, int how);}
The same as quat_interpolate(), but allows more control over how the 
rotation is done. The how parameter can be any one of the values:
@example

QUAT_SHORT  - like quat_interpolate(), use shortest path
QUAT_LONG   - rotation will be greater than 180 degrees
QUAT_CW     - rotate clockwise when viewed from above
QUAT_CCW    - rotate counterclockwise when viewed from above
QUAT_USER   - the quaternions are interpolated exactly as
              given
@end example



@end ftable
@xref{QUAT}.@*
@node GUI, Platform, Quaternion, API
@section GUI routines

Allegro contains an object-oriented dialog manager, which was originally 
based on the Atari GEM system (form_do(), objc_draw(), etc: old ST 
programmers will know what we are talking about :-) You can use the GUI as-is
to knock out simple interfaces for things like the test program and grabber 
utility, or you can use it as a basis for more complicated systems of your 
own. Allegro lets you define your own object types by writing new dialog 
procedures, so you can take complete control over the visual aspects of the 
interface while still using Allegro to handle input from the mouse, 
keyboard, joystick, etc.

A GUI dialog is stored as an array of DIALOG objects, read chapter
"Structures and types defined by Allegro" for an internal description of the
DIALOG structure. The array should end with an object which has the proc
pointer set to NULL. Each object has a flags field which may contain any
combination of the bit flags:
@example

D_EXIT          - this object should close the dialog when it is
                  clicked
D_SELECTED      - this object is selected
D_GOTFOCUS      - this object has got the input focus
D_GOTMOUSE      - the mouse is currently on top of this object
D_HIDDEN        - this object is hidden and inactive
D_DISABLED      - this object is greyed-out and inactive
D_DIRTY         - this object needs to be redrawn
D_INTERNAL      - don't use this! It is for internal use by the
                  library...
D_USER          - any powers of two above this are free for your
                  own use
@end example

Each object is controlled by a dialog procedure, which is stored in the proc 
pointer. This will be called by the dialog manager whenever any action 
concerning the object is required, or you can call it directly with the 
object_message() function. The dialog procedure should follow the form:
@example

int foo(int msg, DIALOG *d, int c);
@end example

It will be passed a flag (msg) indicating what action it should perform, a 
pointer to the object concerned (d), and if msg is MSG_CHAR or MSG_XCHAR, 
the key that was pressed (c). Note that d is a pointer to a specific object, 
and not to the entire dialog.

The dialog procedure should return one of the values:
@example

D_O_K          - normal return status
D_CLOSE        - tells the dialog manager to close the dialog
D_REDRAW       - tells the dialog manager to redraw the entire
                 dialog
D_REDRAWME     - tells the dialog manager to redraw the current
                 object
D_WANTFOCUS    - requests that the input focus be given to this
                 object
D_USED_CHAR    - MSG_CHAR and MSG_XCHAR return this if they used
                 the key
@end example

Dialog procedures may be called with any of the messages:

MSG_START:@*
Tells the object to initialise itself. The dialog manager sends this to 
all the objects in a dialog just before it displays the dialog.

MSG_END:@*
Sent to all objects when closing a dialog, allowing them to perform 
whatever cleanup operations they require.

MSG_DRAW:@*
Tells the object to draw itself onto the screen. The mouse pointer will 
be turned off when this message is sent, so the drawing code does not 
need to worry about it.

MSG_CLICK:@*
Informs the object that a mouse button has been clicked while the mouse 
was on top of the object. Typically an object will perform its own mouse 
tracking as long as the button is held down, and only return from this 
message handler when it is released.

If you process this message, use the functions gui_mouse_*() to read the
state of the mouse.

MSG_DCLICK:@*
Sent when the user double-clicks on an object. A MSG_CLICK will be sent 
when the button is first pressed, then MSG_DCLICK if it is released and 
pressed again within a short space of time.

If you process this message, use the functions gui_mouse_*() to read the
state of the mouse.

MSG_KEY:@*
Sent when the keyboard shortcut for the object is pressed, or if enter, 
space, or a joystick button is pressed while it has the input focus.

MSG_CHAR:@*
When a key is pressed, this message is sent to the object that has the 
input focus, with a readkey() format character code (ASCII value in the 
low byte, scancode in the high byte) as the c parameter. If the object 
deals with the keypress it should return D_USED_CHAR, otherwise it should 
return D_O_K to allow the default keyboard interface to operate. If you 
need to access Unicode character input, you should use MSG_UCHAR instead 
of MSG_CHAR.

MSG_UCHAR:@*
If an object ignores the MSG_CHAR input, this message will be sent 
immediately after it, passed the full Unicode key value as the c 
parameter. This enables you to read character codes greater than 255, but 
cannot tell you anything about the scancode: if you need to know that, 
use MSG_CHAR instead. This handler should return D_USED_CHAR if it 
processed the input, or D_O_K otherwise.

MSG_XCHAR:@*
When a key is pressed, Allegro will send a MSG_CHAR and MSG_UCHAR to the 
object with the input focus. If this object doesn't process the key (ie. 
it returns D_O_K rather than D_USED_CHAR), the dialog manager will look 
for an object with a matching keyboard shortcut in the key field, and 
send it a MSG_KEY. If this fails, it broadcasts a MSG_XCHAR to all 
objects in the dialog, allowing them to respond to special keypresses 
even when they don't have the input focus. Normally you should ignore 
this message (return D_O_K rather than D_USED_CHAR), in which case 
Allegro will perform default actions such as moving the focus in response 
to the arrow keys and closing the dialog if ESC is pressed.

MSG_WANTFOCUS:@*
Queries whether an object is willing to accept the input focus. It should 
return D_WANTFOCUS if it does, or D_O_K if it isn't interested in getting 
user input.

MSG_GOTFOCUS:@*
MSG_LOSTFOCUS:@*
Sent whenever an object gains or loses the input focus. These messages 
will always be followed by a MSG_DRAW, to let objects display themselves 
differently when they have the input focus. If you return D_WANTFOCUS in 
response to a MSG_LOSTFOCUS event, this will prevent your object from 
losing the focus when the mouse moves off it onto the screen background 
or some inert object, so it will only lose the input focus when some 
other object is ready to take over the focus (this trick is used by the 
d_edit_proc() object).

MSG_GOTMOUSE:@*
MSG_LOSTMOUSE:@*
Sent when the mouse moves on top of or away from an object. Unlike the 
focus messages, these are not followed by a MSG_DRAW, so if the object is 
displayed differently when the mouse is on top of it, it is responsible 
for redrawing itself in response to these messages.

MSG_IDLE:@*
Sent whenever the dialog manager has nothing better to do.

MSG_RADIO:@*
Sent by radio button objects to deselect other buttons in the same group 
when they are clicked. The group number is passed in the c message 
parameter.

MSG_WHEEL:@*
Sent to the focused object whenever the mouse wheel moves. The c message 
parameter contains the number of clicks.

MSG_LPRESS, MSG_MPRESS, MSG_RPRESS:@*
Sent when the corresponding mouse button is pressed.

MSG_LRELEASE, MSG_MRELEASE, MSG_RRELEASE:@*
Sent when the corresponding mouse button is released.

MSG_USER:@*
The first free message value. Any numbers from here on (MSG_USER, 
MSG_USER+1, MSG_USER+2, ... MSG_USER+n) are free to use for whatever you 
like.

Allegro provides several standard dialog procedures. You can use these as 
they are to provide simple user interface objects, or you can call them from 
within your own dialog procedures, resulting in a kind of OOP inheritance. 
For instance, you could make an object which calls d_button_proc to draw 
itself, but handles the click message in a different way, or an object which 
calls d_button_proc for everything except drawing itself, so it would behave 
like a normal button but could look completely different.

Since the release of Allegro version 3.9.33 (CVS), some GUI objects and 
menus are being drawn differently unlike in previous Allegro versions. The 
changes are the following:

@itemize @bullet
@item 
Shadows under d_shadow_box_proc and d_button_proc are always black.
@item 
The most important (and immediately visible) change is, that some objects 
are being drawn smaller. The difference is exactly one pixel in both 
height and width, when comparing to previous versions. The reason is, 
that in previous versions these objects were too large on the screen - 
their size was d->w+1 and d->h+1 pixels (and not d->w and d->h, as it
should be). This change affects the following objects :
@example

d_box_proc,
d_shadow_box_proc,
d_button_proc,
d_check_proc,
d_radio_proc,
d_list_proc,
d_text_list_proc and
d_textbox_proc.
@end example

When you want to convert old dialogs to look equally when compiling with 
the new Allegro version, just increase the size of the mentioned objects 
by one pixel in both width and height fields. 
@item 
When a GUI menu item (not in a bar menu) has a child menu, there is a 
small arrow next to the child menu name, pointing to the right - so the 
user can immediately see that this menu item has a child menu - and 
there is no need to use such menu item names as for example "New...", 
to show that it has a child menu. The submenu will be drawn to the right 
of the parent menu, trying not to overlap it.
@end itemize
@*

Menus had been forgotten during the changes for 3.9.33 (CVS), so they were
still drawn too large until version 4.1.0.

@menu
* d_clear_proc::
* d_box_proc::
* d_bitmap_proc::
* d_text_proc::
* d_button_proc::
* d_check_proc::
* d_radio_proc::
* d_icon_proc::
* d_keyboard_proc::
* d_edit_proc::
* d_list_proc::
* d_text_list_proc::
* d_textbox_proc::
* d_slider_proc::
* d_menu_proc::
* d_yield_proc::
* GUI variables::
* gui_mouse_focus::
* gui_fg_color::
* gui_mg_color::
* gui_font_baseline::
* gui_mouse_x::
* GUI font::
* gui_textout_ex::
* gui_strlen::
* gui_set_screen::
* gui_get_screen::
* position_dialog::
* centre_dialog::
* set_dialog_color::
* find_dialog_focus::
* offer_focus::
* object_message::
* dialog_message::
* broadcast_dialog_message::
* do_dialog::
* popup_dialog::
* init_dialog::
* update_dialog::
* shutdown_dialog::
* active_dialog::
* GUI menus::
* do_menu::
* init_menu::
* update_menu::
* shutdown_menu::
* active_menu::
* gui_menu_draw_menu::
* alert::
* alert3::
* file_select_ex::
* gfx_mode_select::
* gfx_mode_select_ex::
* gfx_mode_select_filter::
* gui_shadow_box_proc::
@end menu
@node d_clear_proc, d_box_proc, quat_slerp, GUI
@subsection d_clear_proc
@ftable @asis
@item @t{int d_clear_proc(int msg, DIALOG *d, int c);}
This just clears the screen when it is drawn. Useful as the first object 
in a dialog.

@end ftable
See also:@*
@xref{excustom}.@*
@xref{exgui}.@*
@xref{DIALOG}.@*
@node d_box_proc, d_bitmap_proc, d_clear_proc, GUI
@subsection d_box_proc
@ftable @asis
@item @t{int d_box_proc(int msg, DIALOG *d, int c);}
@end ftable
@ftable @asis
@item @t{int d_shadow_box_proc(int msg, DIALOG *d, int c);}
These draw boxes onto the screen, with or without a shadow.

@end ftable
See also:@*
@xref{exgui}.@*
@xref{exrgbhsv}.@*
@xref{DIALOG}.@*
@node d_bitmap_proc, d_text_proc, d_box_proc, GUI
@subsection d_bitmap_proc
@ftable @asis
@item @t{int d_bitmap_proc(int msg, DIALOG *d, int c);}
This draws a bitmap onto the screen, which should be pointed to by the 
dp field.

@end ftable
See also:@*
@xref{exgui}.@*
@xref{exrgbhsv}.@*
@xref{DIALOG}.@*
@node d_text_proc, d_button_proc, d_bitmap_proc, GUI
@subsection d_text_proc
@ftable @asis
@item @t{int d_text_proc(int msg, DIALOG *d, int c);}
@end ftable
@ftable @asis
@item @t{int d_ctext_proc(int msg, DIALOG *d, int c);}
@end ftable
@ftable @asis
@item @t{int d_rtext_proc(int msg, DIALOG *d, int c);}
These draw text onto the screen. The dp field should point to the string 
to display. d_ctext_proc() centers the string horizontally, and
d_rtext_proc() right aligns it. Any '&' characters in the string will 
be replaced with lines underneath the following character, for displaying 
keyboard shortcuts (as in MS Windows). To display a single ampersand, put 
"&&". To draw the text in something other than the default font, set the 
dp2 field to point to your custom font data.

@end ftable
See also:@*
@xref{exgui}.@*
@xref{exrgbhsv}.@*
@xref{DIALOG}.@*
@node d_button_proc, d_check_proc, d_text_proc, GUI
@subsection d_button_proc
@ftable @asis
@item @t{int d_button_proc(int msg, DIALOG *d, int c);}
A button object (the dp field points to the text string). This object can 
be selected by clicking on it with the mouse or by pressing its keyboard 
shortcut. If the D_EXIT flag is set, selecting it will close the dialog, 
otherwise it will toggle on and off. Like d_text_proc(), ampersands can 
be used to display the keyboard shortcut of the button.

@end ftable
See also:@*
@xref{excustom}.@*
@xref{exgui}.@*
@xref{DIALOG}.@*
@node d_check_proc, d_radio_proc, d_button_proc, GUI
@subsection d_check_proc
@ftable @asis
@item @t{int d_check_proc(int msg, DIALOG *d, int c);}
This is an example of how you can derive objects from other objects. Most 
of the functionality comes from d_button_proc(), but it displays itself 
as a check box. If the d1 field is non-zero, the text will be printed to 
the right of the check, otherwise it will be on the left.

Note: the object width should allow space for the text as well as the
check box (which is square, with sides equal to the object height).

@end ftable
See also:@*
@xref{excustom}.@*
@xref{exgui}.@*
@xref{DIALOG}.@*
@node d_radio_proc, d_icon_proc, d_check_proc, GUI
@subsection d_radio_proc
@ftable @asis
@item @t{int d_radio_proc(int msg, DIALOG *d, int c);}
A radio button object. A dialog can contain any number of radio button 
groups: selecting a radio button causes other buttons within the same 
group to be deselected. The dp field points to the text string, d1 
specifies the group number, and d2 is the button style (0=circle, 
1=square).

@end ftable
See also:@*
@xref{exgui}.@*
@xref{DIALOG}.@*
@node d_icon_proc, d_keyboard_proc, d_radio_proc, GUI
@subsection d_icon_proc
@ftable @asis
@item @t{int d_icon_proc(int msg, DIALOG *d, int c);}
A bitmap button. The fg color is used for the dotted line showing focus, 
and the bg color for the shadow used to fill in the top and left sides of 
the button when "pressed". d1 is the "push depth", ie. the number of 
pixels the icon will be shifted to the right and down when selected 
(default 2) if there is no "selected" image. d2 is the distance by which 
the dotted line showing focus is indented (default 2). dp points to a 
bitmap for the icon, while dp2 and dp3 are the selected and disabled 
images respectively (optional, may be NULL).

@end ftable
See also:@*
@xref{exgui}.@*
@xref{DIALOG}.@*
@node d_keyboard_proc, d_edit_proc, d_icon_proc, GUI
@subsection d_keyboard_proc
@ftable @asis
@item @t{int d_keyboard_proc(int msg, DIALOG *d, int c);}
This is an invisible object for implementing keyboard shortcuts. You can 
put an ASCII code in the key field of the dialog object (a character such 
as 'a' to respond to a simple keypress, or a number 1-26 to respond to a 
control key a-z), or you can put a keyboard scancode in the d1 and/or d2 
fields. When one of these keys is pressed, the object will call the 
function pointed to by dp. This should return an int, which will be 
passed back to the dialog manager, so it can return D_O_K, D_REDRAW, 
D_CLOSE, etc.

@end ftable
See also:@*
@xref{exgui}.@*
@xref{DIALOG}.@*
@node d_edit_proc, d_list_proc, d_keyboard_proc, GUI
@subsection d_edit_proc
@ftable @asis
@item @t{int d_edit_proc(int msg, DIALOG *d, int c);}
An editable text object (the dp field points to the string). When it has 
the input focus (obtained by clicking on it with the mouse), text can be 
typed into this object. The d1 field specifies the maximum number of 
characters that it will accept, and d2 is the text cursor position within 
the string.

Note: dp must point to a buffer at least (d1 + 1) * 4 bytes long because,
depending on the encoding format in use, a single character can occupy
up to 4 bytes and room must be reserved for the terminating null character.

@end ftable
See also:@*
@xref{excustom}.@*
@xref{exgui}.@*
@xref{DIALOG}.@*
@node d_list_proc, d_text_list_proc, d_edit_proc, GUI
@subsection d_list_proc
@ftable @asis
@item @t{int d_list_proc(int msg, DIALOG *d, int c);}
A list box object. This will allow the user to scroll through a list of 
items and to select one by clicking or with the arrow keys. If the D_EXIT 
flag is set, double clicking on a list item will close the dialog. The 
index of the selected item is held in the d1 field, and d2 is used to 
store how far it has scrolled through the list. The dp field points to a 
function which will be called to obtain information about the contents of 
the list. This should follow the form:
@example

char *foobar(int index, int *list_size);
@end example

If index is zero or positive, the function should return a pointer to the 
string which is to be displayed at position index in the list. If index 
is negative, it should return NULL and list_size should be set to the 
number of items in the list. 

To create a multiple selection listbox, set the dp2 field to an array of 
byte flags indicating the selection state of each list item (non-zero for 
selected entries). This table must be at least as big as the number of 
objects in the list!

@end ftable
See also:@*
@xref{exgui}.@*
@xref{DIALOG}.@*
@node d_text_list_proc, d_textbox_proc, d_list_proc, GUI
@subsection d_text_list_proc
@ftable @asis
@item @t{int d_text_list_proc(int msg, DIALOG *d, int c);}
Like d_list_proc, but allows the user to type in the first few characters 
of a listbox entry in order to select it. Uses dp3 internally, so you 
mustn't store anything important there yourself.

@end ftable
See also:@*
@xref{exgui}.@*
@xref{DIALOG}.@*
@node d_textbox_proc, d_slider_proc, d_text_list_proc, GUI
@subsection d_textbox_proc
@ftable @asis
@item @t{int d_textbox_proc(int msg, DIALOG *d, int c);}
A text box object. The dp field points to the text which is to be 
displayed in the box. If the text is long, there will be a vertical 
scrollbar on the right hand side of the object which can be used to 
scroll through the text. The default is to print the text with word 
wrapping, but if the D_SELECTED flag is set, the text will be printed 
with character wrapping. The d1 field is used internally to store the 
number of lines of text, and d2 is used to store how far it has scrolled 
through the text.

@end ftable
See also:@*
@xref{exgui}.@*
@xref{DIALOG}.@*
@node d_slider_proc, d_menu_proc, d_textbox_proc, GUI
@subsection d_slider_proc
@ftable @asis
@item @t{int d_slider_proc(int msg, DIALOG *d, int c);}
A slider control object. This object holds a value in d2, in the range 
from 0 to d1. It will display as a vertical slider if h is greater than 
or equal to w, otherwise it will display as a horizontal slider. The dp 
field can contain an optional bitmap to use for the slider handle, and 
dp2 can contain an optional callback function, which is called each time 
d2 changes. The callback function should have the following prototype:
@example

int function(void *dp3, int d2);
@end example

The d_slider_proc object will return the value of the callback function.

@end ftable
See also:@*
@xref{exgui}.@*
@xref{exrgbhsv}.@*
@xref{DIALOG}.@*
@node d_menu_proc, d_yield_proc, d_slider_proc, GUI
@subsection d_menu_proc
@ftable @asis
@item @t{int d_menu_proc(int msg, DIALOG *d, int c);}
This object is a menu bar which will drop down child menus when it is 
clicked or if an alt+key corresponding to one of the shortcuts in the 
menu is pressed. It ignores a lot of the fields in the dialog structure, 
in particular the color is taken from the gui_*_color variables, and the 
width and height are calculated automatically (the w and h fields from 
the DIALOG are only used as a minimum size.) The dp field points to an 
array of menu structures: see do_menu() for more information. The top 
level menu will be displayed as a horizontal bar, but when child menus 
drop down from it they will be in the normal vertical format used by 
do_menu(). When a menu item is selected, the return value from the menu 
callback function is passed back to the dialog manager, so your callbacks 
should return D_O_K, D_REDRAW, or D_CLOSE.

@end ftable
See also:@*
@xref{GUI menus}.@*
@xref{active_menu}.@*
@xref{gui_menu_draw_menu}.@*
@xref{exgui}.@*
@xref{DIALOG}.@*
@node d_yield_proc, GUI variables, d_menu_proc, GUI
@subsection d_yield_proc
@ftable @asis
@item @t{int d_yield_proc(int msg, DIALOG *d, int c);}
An invisible helper object that yields time slices for the scheduler (if
the system supports it) when the GUI has nothing to do but waiting for
user actions. You should put one instance of this object in each dialog 
array because it may be needed on systems with an unusual scheduling 
algorithm (for instance QNX) in order to make the GUI fully responsive.

@end ftable
See also:@*
@xref{rest}.@*
@xref{exgui}.@*
@xref{DIALOG}.@*
@node GUI variables, gui_mouse_focus, d_yield_proc, GUI
@subsection GUI variables
@ftable @asis
@end ftable
The behaviour of the dialog manager can be controlled by the following
global variables.

@node gui_mouse_focus, gui_fg_color, GUI variables, GUI
@subsection gui_mouse_focus
@ftable @asis
@item @t{extern int gui_mouse_focus;}
If set, the input focus follows the mouse pointer around the dialog, 
otherwise a click is required to move it.

@end ftable
@node gui_fg_color, gui_mg_color, gui_mouse_focus, GUI
@subsection gui_fg_color
@ftable @asis
@item @t{extern int gui_fg_color;}
@end ftable
@ftable @asis
@item @t{extern int gui_bg_color;}
The foreground and background colors for the standard dialogs (alerts, 
menus, and the file selector). They default to 255 and 0.

@end ftable
See also:@*
@xref{gui_mg_color}.@*
@xref{set_dialog_color}.@*
@xref{exgui}.@*
@node gui_mg_color, gui_font_baseline, gui_fg_color, GUI
@subsection gui_mg_color
@ftable @asis
@item @t{extern int gui_mg_color;}
The color used for displaying greyed-out dialog objects (with the 
D_DISABLED flag set). Defaults to 8.

@end ftable
See also:@*
@xref{gui_fg_color}.@*
@xref{set_dialog_color}.@*
@xref{exgui}.@*
@node gui_font_baseline, gui_mouse_x, gui_mg_color, GUI
@subsection gui_font_baseline
@ftable @asis
@item @t{extern int gui_font_baseline;}
If set to a non-zero value, adjusts the keyboard shortcut underscores to 
account for the height of the descenders in your font.

@end ftable
@node gui_mouse_x, GUI font, gui_font_baseline, GUI
@subsection gui_mouse_x
@ftable @asis
@item @t{extern int (*gui_mouse_x)();}
@end ftable
@ftable @asis
@item @t{extern int (*gui_mouse_y)();}
@end ftable
@ftable @asis
@item @t{extern int (*gui_mouse_z)();}
@end ftable
@ftable @asis
@item @t{extern int (*gui_mouse_b)();}
Hook functions, used by the GUI routines whenever they need to access the 
mouse state. By default these just return copies of the mouse_x, mouse_y, 
mouse_z, and mouse_b variables, but they could be used to offset or scale 
the mouse position, or read input from a different source entirely.

@end ftable
@node GUI font, gui_textout_ex, gui_mouse_x, GUI
@subsection GUI font
@ftable @asis
@end ftable
You can change the global 'font' pointer to make the GUI objects use 
something other than the standard 8x8 font. The standard dialog procedures, 
menus, and alert boxes, will work with fonts of any size, but the 
gfx_mode_select() dialog will look wrong with anything other than 8x8 fonts.

@node gui_textout_ex, gui_strlen, GUI font, GUI
@subsection gui_textout_ex
@ftable @asis
@item @t{int gui_textout_ex(BITMAP *bmp, const char *s, int x, y, color, bg, centre);}
Helper function for use by the GUI routines. Draws a text string onto the 
screen, interpreting the '&' character as an underbar for displaying 
keyboard shortcuts. Returns the width of the output string in pixels.

@end ftable
See also:@*
@xref{gui_strlen}.@*
@xref{BITMAP}.@*
@node gui_strlen, gui_set_screen, gui_textout_ex, GUI
@subsection gui_strlen
@ftable @asis
@item @t{int gui_strlen(const char *s);}
Helper function for use by the GUI routines. Returns the length of a 
string in pixels, ignoring '&' characters.

@end ftable
See also:@*
@xref{gui_textout_ex}.@*
@node gui_set_screen, gui_get_screen, gui_strlen, GUI
@subsection gui_set_screen
@ftable @asis
@item @t{void gui_set_screen(BITMAP *bmp);}
This function can be used to change the bitmap surface the GUI routines
draw to. This can be useful if you are using a double buffering or page 
flipping system. Passing NULL will cause the default surface (screen) to
be used again. Example:
@example

BITMAP *page[2];

/* Allocate two pages of video memory */
page[0] = create_video_bitmap(SCREEN_W, SCREEN_H);
page[1] = create_video_bitmap(SCREEN_W, SCREEN_H);

/* Page flip */
show_video_bitmap(page[0]);
gui_set_screen(page[0]);
@end example


@end ftable
See also:@*
@xref{gui_get_screen}.@*
@xref{BITMAP}.@*
@node gui_get_screen, position_dialog, gui_set_screen, GUI
@subsection gui_get_screen
@ftable @asis
@item @t{BITMAP *gui_get_screen(void);}
This function returns the current bitmap surface the GUI routines will
use for drawing. Note that this function will return screen if you have
called gui_set_screen(NULL) previously, and will never return NULL.

@end ftable
See also:@*
@xref{gui_set_screen}.@*
@xref{BITMAP}.@*
@node position_dialog, centre_dialog, gui_get_screen, GUI
@subsection position_dialog
@ftable @asis
@item @t{void position_dialog(DIALOG *dialog, int x, int y);}
Moves an array of dialog objects to the specified screen position 
(specified as the top left corner of the dialog).

@end ftable
See also:@*
@xref{centre_dialog}.@*
@xref{exgui}.@*
@xref{DIALOG}.@*
@node centre_dialog, set_dialog_color, position_dialog, GUI
@subsection centre_dialog
@ftable @asis
@item @t{void centre_dialog(DIALOG *dialog);}
Moves an array of dialog objects so that it is centered in the screen.

@end ftable
See also:@*
@xref{position_dialog}.@*
@xref{set_dialog_color}.@*
@xref{DIALOG}.@*
@node set_dialog_color, find_dialog_focus, centre_dialog, GUI
@subsection set_dialog_color
@ftable @asis
@item @t{void set_dialog_color(DIALOG *dialog, int fg, int bg);}
Sets the foreground and background colors of an array of dialog objects.

@end ftable
See also:@*
@xref{gui_fg_color}.@*
@xref{gui_mg_color}.@*
@xref{centre_dialog}.@*
@xref{exgui}.@*
@xref{DIALOG}.@*
@node find_dialog_focus, offer_focus, set_dialog_color, GUI
@subsection find_dialog_focus
@ftable @asis
@item @t{int find_dialog_focus(DIALOG *dialog);}
Searches the dialog for the object which has the input focus, returning 
an index or -1 if the focus is not set. This is useful if you are calling 
do_dialog() several times in a row and want to leave the focus in the 
same place it was when the dialog was last displayed, as you can call 
do_dialog(dlg, find_dialog_focus(dlg));

@end ftable
See also:@*
@xref{do_dialog}.@*
@xref{init_dialog}.@*
@xref{offer_focus}.@*
@xref{DIALOG}.@*
@node offer_focus, object_message, find_dialog_focus, GUI
@subsection offer_focus
@ftable @asis
@item @t{int offer_focus(DIALOG *dialog, int obj, int *focus_obj, int force);}
Offers the input focus to a particular object. Normally the function sends
the MSG_WANTFOCUS message to query whether the object is willing to accept
the focus. However, passing any non-zero value as force argument instructs
the function to authoritatively set the focus to the object.

@end ftable
See also:@*
@xref{find_dialog_focus}.@*
@xref{DIALOG}.@*
@node object_message, dialog_message, offer_focus, GUI
@subsection object_message
@ftable @asis
@item @t{int object_message(DIALOG *dialog, int msg, int c);}
Sends a message to an object and returns the answer it has generated.
Remember that the first parameter is the dialog object (not a whole
array) that you wish to send the message to. For example, to make the
second object in a dialog draw itself, you might write:
@example

object_message(&dialog[1], MSG_DRAW, 0);
@end example

The function will take care of scaring and unscaring the mouse if the
message is MSG_DRAW.

@end ftable
See also:@*
@xref{dialog_message}.@*
@xref{scare_mouse}.@*
@xref{scare_mouse_area}.@*
@xref{unscare_mouse}.@*
@xref{excustom}.@*
@xref{exrgbhsv}.@*
@xref{DIALOG}.@*
@node dialog_message, broadcast_dialog_message, object_message, GUI
@subsection dialog_message
@ftable @asis
@item @t{int dialog_message(DIALOG *dialog, int msg, int c, int *obj);}
Sends a message to all the objects in an array. If any of the dialog 
procedures return values other than D_O_K, it returns the value and sets 
obj to the index of the object which produced it.

@end ftable
See also:@*
@xref{object_message}.@*
@xref{broadcast_dialog_message}.@*
@xref{DIALOG}.@*
@node broadcast_dialog_message, do_dialog, dialog_message, GUI
@subsection broadcast_dialog_message
@ftable @asis
@item @t{int broadcast_dialog_message(int msg, int c);}
Broadcasts a message to all the objects in the active dialog. If any of 
the dialog procedures return values other than D_O_K, it returns that 
value.

@end ftable
See also:@*
@xref{dialog_message}.@*
@xref{active_dialog}.@*
@node do_dialog, popup_dialog, broadcast_dialog_message, GUI
@subsection do_dialog
@ftable @asis
@item @t{int do_dialog(DIALOG *dialog, int focus_obj);}
The basic dialog manager function. This displays a dialog (an array of 
dialog objects, terminated by one with a NULL dialog procedure), and sets 
the input focus to the focus_obj (-1 if you don't want anything to have 
the focus). It interprets user input and dispatches messages as they are 
required, until one of the dialog procedures tells it to close the 
dialog, at which point it returns the index of the object that caused it 
to exit, or until ESC is pressed, at which point it returns -1.

@end ftable
See also:@*
@xref{popup_dialog}.@*
@xref{init_dialog}.@*
@xref{centre_dialog}.@*
@xref{set_dialog_color}.@*
@xref{find_dialog_focus}.@*
@xref{excustom}.@*
@xref{exgui}.@*
@xref{exrgbhsv}.@*
@xref{DIALOG}.@*
@node popup_dialog, init_dialog, do_dialog, GUI
@subsection popup_dialog
@ftable @asis
@item @t{int popup_dialog(DIALOG *dialog, int focus_obj);}
Like do_dialog(), but it stores the data on the screen before drawing the 
dialog and restores it when the dialog is closed. The screen area to be 
stored is calculated from the dimensions of the first object in the 
dialog, so all the other objects should lie within this one.

@end ftable
See also:@*
@xref{do_dialog}.@*
@xref{DIALOG}.@*
@node init_dialog, update_dialog, popup_dialog, GUI
@subsection init_dialog
@ftable @asis
@item @t{DIALOG_PLAYER *init_dialog(DIALOG *dialog, int focus_obj);}
This function provides lower level access to the same functionality as
do_dialog(), but allows you to combine a dialog box with your own program 
control structures. It initialises a dialog, returning a pointer to a 
player object that can be used with update_dialog() and 
shutdown_dialog(). With these functions, you could implement your own 
version of do_dialog() with the lines:
@example

DIALOG_PLAYER *player = init_dialog(dialog, focus_obj);

while (update_dialog(player))
   ;

return shutdown_dialog(player);@end example


Note that you are responsible for showing and hiding the mouse cursor, which
do_dialog would otherwise do for you, or saving and restoring the screen
contents, as popup_dialog would do for you.

@end ftable
See also:@*
@xref{update_dialog}.@*
@xref{shutdown_dialog}.@*
@xref{do_dialog}.@*
@xref{DIALOG}.@*
@xref{DIALOG_PLAYER}.@*
@node update_dialog, shutdown_dialog, init_dialog, GUI
@subsection update_dialog
@ftable @asis
@item @t{int update_dialog(DIALOG_PLAYER *player);}
Updates the status of a dialog object returned by init_dialog(). Returns 
TRUE if the dialog is still active, or FALSE if it has terminated. Upon a 
return value of FALSE, it is up to you whether to call shutdown_dialog() 
or to continue execution. The object that requested the exit can be 
determined from the player->obj field.

@end ftable
See also:@*
@xref{init_dialog}.@*
@xref{DIALOG_PLAYER}.@*
@node shutdown_dialog, active_dialog, update_dialog, GUI
@subsection shutdown_dialog
@ftable @asis
@item @t{int shutdown_dialog(DIALOG_PLAYER *player);}
Destroys a dialog player object returned by init_dialog(), returning the 
object that caused it to exit (this is the same as the return value from 
do_dialog()).

@end ftable
See also:@*
@xref{init_dialog}.@*
@xref{DIALOG_PLAYER}.@*
@node active_dialog, GUI menus, shutdown_dialog, GUI
@subsection active_dialog
@ftable @asis
@item @t{extern DIALOG *active_dialog;}
Global pointer to the most recent activated dialog. This may be useful if 
an object needs to iterate through a list of all its siblings.

@end ftable
See also:@*
@xref{do_dialog}.@*
@xref{init_dialog}.@*
@xref{broadcast_dialog_message}.@*
@xref{DIALOG}.@*
@node GUI menus, do_menu, active_dialog, GUI
@subsection GUI menus
@ftable @asis
@end ftable
Popup or pulldown menus are created as an array of MENU structures. Read
chapter "Structures and types defined by Allegro" for an internal description
of the MENU structure.

Each menu item contains a text string. This can use the '&' character to 
indicate keyboard shortcuts, or can be an zero-length string to display the 
item as a non-selectable splitter bar. If the string contains a "\t" tab 
character, any text after this will be right-justified, eg. for displaying 
keyboard shortcut information. The proc pointer is a function which will be 
called when the menu item is selected, and child points to another menu, 
allowing you to create nested menus. Both proc and child may be NULL. The 
proc function returns an integer which is ignored if the menu was brought up 
by calling do_menu(), but which is passed back to the dialog manager if it 
was created by a d_menu_proc() object. The array of menu items is terminated 
by an entry with a NULL text pointer.

Menu items can be disabled (greyed-out) by setting the D_DISABLED bit in the 
flags field, and a check mark can be displayed next to them by setting the 
D_SELECTED bit. With the default alignment and font this will usually 
overlap the menu text, so if you are going to use checked menu items it 
would be a good idea to prefix all your options with a space or two, to 
ensure there is room for the check.

See also:@*
@xref{do_menu}.@*
@xref{d_menu_proc}.@*
@xref{gui_menu_draw_menu}.@*
@node do_menu, init_menu, GUI menus, GUI
@subsection do_menu
@ftable @asis
@item @t{int do_menu(MENU *menu, int x, int y);}
Displays and animates a popup menu at the specified screen coordinates 
(these will be adjusted if the menu does not entirely fit on the screen). 
Returns the index of the menu item that was selected, or -1 if the menu 
was cancelled. Note that the return value cannot indicate selection from 
child menus, so you will have to use the callback functions if you want 
multi-level menus.

@end ftable
See also:@*
@xref{GUI menus}.@*
@xref{d_menu_proc}.@*
@xref{active_menu}.@*
@xref{gui_menu_draw_menu}.@*
@xref{update_menu}.@*
@xref{MENU}.@*
@node init_menu, update_menu, do_menu, GUI
@subsection init_menu
@ftable @asis
@item @t{MENU_PLAYER *init_menu(MENU *menu, int x, int y);}
This function provides lower level access to the same functionality as 
do_menu(), but allows you to combine a popup menu with your own program 
control structures. It initialises a menu, returning a pointer to a menu
player object that can be used with update_menu() and shutdown_menu().
With these functions, you could implement your own version of do_menu()
with the lines:
@example

MENU_PLAYER *player = init_menu(menu, x, y);

while (update_menu(player))
   ;

return shutdown_menu(player);@end example


@end ftable
See also:@*
@xref{update_menu}.@*
@xref{shutdown_menu}.@*
@xref{do_menu}.@*
@xref{MENU}.@*
@xref{MENU_PLAYER}.@*
@node update_menu, shutdown_menu, init_menu, GUI
@subsection update_menu
@ftable @asis
@item @t{int update_menu(MENU_PLAYER *player);}
Updates the status of a menu object returned by init_menu(). Returns TRUE
if the menu is still active, or FALSE if it has terminated. Upon a return
value of FALSE, it is up to you to call shutdown_menu() or to continue
execution.

@end ftable
See also:@*
@xref{init_menu}.@*
@xref{shutdown_menu}.@*
@xref{do_menu}.@*
@xref{MENU_PLAYER}.@*
@node shutdown_menu, active_menu, update_menu, GUI
@subsection shutdown_menu
@ftable @asis
@item @t{int shutdown_menu(MENU_PLAYER *player);}
Destroys a menu player object returned by init_menu(), returning the index
of the menu item that was selected, or -1 if the menu was cancelled (this
is the same as the return value from do_menu()).

@end ftable
See also:@*
@xref{init_menu}.@*
@xref{update_menu}.@*
@xref{MENU_PLAYER}.@*
@node active_menu, gui_menu_draw_menu, shutdown_menu, GUI
@subsection active_menu
@ftable @asis
@item @t{extern MENU *active_menu;}
When a menu callback procedure is triggered, this will be set to the menu 
item that was selected, so your routine can determine where it was called 
from.

@end ftable
See also:@*
@xref{GUI menus}.@*
@xref{exgui}.@*
@xref{MENU}.@*
@node gui_menu_draw_menu, alert, active_menu, GUI
@subsection gui_menu_draw_menu
@ftable @asis
@item @t{extern void (*gui_menu_draw_menu)(int x, int y, int w, int h);}
@end ftable
@ftable @asis
@item @t{extern void (*gui_menu_draw_menu_item)(MENU *m, int x, int y, int w, int h, int bar, int sel);}
If set, these functions will be called whenever a menu needs to be
drawn, so you can change how menus look.

gui_menu_draw_menu() is passed the position and size of the
menu. It should draw the background of the menu onto screen.

gui_menu_draw_menu_item() is called once for each menu item that is
to be drawn. bar will be set if the item is part of a top-level
horizontal menu bar, and sel will be set if the menu item is
selected. It should also draw onto screen.

@end ftable
See also:@*
@xref{GUI menus}.@*
@xref{MENU}.@*
@node alert, alert3, gui_menu_draw_menu, GUI
@subsection alert
@ftable @asis
@item @t{int alert(const char *s1, *s2, *s3, const char *b1, *b2, int c1, c2);}
Displays a popup alert box, containing three lines of text (s1-s3), and 
with either one or two buttons. The text for these buttons is passed in 
`b1' and `b2' (`b2' may be NULL), and the keyboard shortcuts in `c1' and
`c2' as ASCII value. Example:
@example

if (!exists(CONFIG_FILE))
   alert(CONFIG_FILE, "not found.", "Using defaults.",
         "&Continue", NULL, 'c', 0);@end example


Returns 1 or 2 depending on which button was clicked. If the alert is 
dismissed by pressing ESC when ESC is not one of the keyboard shortcuts, 
it treats it as a click on the second button (this is consistent with the 
common "Ok", "Cancel" alert).

@end ftable
See also:@*
@xref{alert3}.@*
@xref{gui_fg_color}.@*
@xref{exgui}.@*
@xref{expackf}.@*
@xref{exspline}.@*
@node alert3, file_select_ex, alert, GUI
@subsection alert3
@ftable @asis
@item @t{int alert3(const char *s1, *s2, *s3, const char *b1, *b2, *b3, int c1, c2, c3);}
Like alert(), but with three buttons. Returns 1, 2, or 3.

@end ftable
See also:@*
@xref{alert}.@*
@xref{gui_fg_color}.@*
@node file_select_ex, gfx_mode_select, alert3, GUI
@subsection file_select_ex
@ftable @asis
@item @t{int file_select_ex(const char *message, char *path, const char *ext, int size, int w, int h);}
Displays the Allegro file selector, with the message as caption. The path 
parameter contains the initial filename to display (this can be used to 
set the starting directory, or to provide a default filename for a 
save-as operation). The user selection is returned by altering the path 
buffer, whose maximum capacity in bytes is specified by the size parameter.
Note that it should have room for at least 80 characters (not bytes),
so you should reserve 6x that amount, just to be sure. The list of files
is filtered according to the file extensions in the ext parameter.
Passing NULL includes all files; "PCX;BMP" includes only files with
.PCX or .BMP extensions. If you wish to control files by their attributes,
one of the fields in the extension list can begin with a slash, followed
by a set of attribute characters. Any attribute written on its own, or
with a '+' before it, indicates to include only files which have that
attribute set. Any attribute with a '-' before it indicates to leave out
any files with that attribute. The flag characters are 'r' (read-only),
'h' (hidden), 's' (system), 'd' (directory) and 'a' (archive). For
example, an extension string of "PCX;BMP;/+r-h" will display only PCX or
BMP files that are read-only and not hidden. The directories are not
affected in the same way as the other files by the extension string: the
extensions are never taken into account for them and the other attributes
are taken into account only when 'd' is mentioned in the string; in other
words, all directories are included when 'd' is not mentioned in the
string. The file selector is stretched to the width and height specified
in the w and h parameters, and to the size of the standard Allegro font.
If either the width or height argument is set to zero, it is stretched
to the corresponding screen dimension. This function returns zero if it
was closed with the Cancel button or non-zero if it was OK'd.

@end ftable
See also:@*
@xref{gui_fg_color}.@*
@node gfx_mode_select, gfx_mode_select_ex, file_select_ex, GUI
@subsection gfx_mode_select
@ftable @asis
@item @t{int gfx_mode_select(int *card, int *w, int *h);}
Displays the Allegro graphics mode selection dialog, which allows the 
user to select a screen mode and graphics card. Stores the selection in 
the three variables, and returns zero if it was closed with the Cancel 
button or non-zero if it was OK'd.

The initial values of card, w, h are not used.

@end ftable
See also:@*
@xref{gfx_mode_select_ex}.@*
@xref{gfx_mode_select_filter}.@*
@xref{set_gfx_mode}.@*
@xref{gui_fg_color}.@*
@node gfx_mode_select_ex, gfx_mode_select_filter, gfx_mode_select, GUI
@subsection gfx_mode_select_ex
@ftable @asis
@item @t{int gfx_mode_select_ex(int *card, int *w, int *h, int *color_depth);}
Extended version of the graphics mode selection dialog, which allows the 
user to select the color depth as well as the resolution and hardware 
driver.

This version of the function reads the initial values from the 
parameters when it activates so you can specify the default values.
In fact, you should be sure not to pass in uninitialised values.

@end ftable
See also:@*
@xref{gfx_mode_select}.@*
@xref{gfx_mode_select_filter}.@*
@xref{set_color_depth}.@*
@xref{set_gfx_mode}.@*
@xref{gui_fg_color}.@*
@xref{ex3d}.@*
@xref{exscn3d}.@*
@xref{exswitch}.@*
@xref{exupdate}.@*
@xref{exzbuf}.@*
@node gfx_mode_select_filter, gui_shadow_box_proc, gfx_mode_select_ex, GUI
@subsection gfx_mode_select_filter
@ftable @asis
@item @t{int gfx_mode_select_filter(int *card, int *w, int *h, int *color_depth, int (*filter)(int, int, int, int));}
Even more extended version of the graphics mode selection dialog, which
allows the programmer to customize the contents of the dialog and the user
to select the color depth as well as the resolution and hardware driver.
`filter' will be passed (card, w, h, color_depth) quadruplets and must
return 0 to let the specified quadruplet be added to the list of displayed
modes.

This version of the function reads the initial values from the 
parameters when it activates so you can specify the default values.
In fact, you should be sure not to pass in uninitialised values.

@end ftable
See also:@*
@xref{gfx_mode_select}.@*
@xref{gfx_mode_select_ex}.@*
@xref{set_color_depth}.@*
@xref{set_gfx_mode}.@*
@xref{gui_fg_color}.@*
@node gui_shadow_box_proc, JOY_TYPE_*/DOS, gfx_mode_select_filter, GUI
@subsection gui_shadow_box_proc
@ftable @asis
@item @t{extern int (*gui_shadow_box_proc)(int msg, struct DIALOG *d, int c);}
@end ftable
@ftable @asis
@item @t{extern int (*gui_ctext_proc)(int msg, struct DIALOG *d, int c);}
@end ftable
@ftable @asis
@item @t{extern int (*gui_button_proc)(int msg, struct DIALOG *d, int c);}
@end ftable
@ftable @asis
@item @t{extern int (*gui_edit_proc)(int msg, struct DIALOG *d, int c);}
@end ftable
@ftable @asis
@item @t{extern int (*gui_list_proc)(int msg, struct DIALOG *d, int c);}
@end ftable
@ftable @asis
@item @t{extern int (*gui_text_list_proc)(int msg, struct DIALOG *d, int c);}
If set, these functions will be used by the standard Allegro dialogs.
This allows you to customise the look and feel, much like gui_fg_color
and gui_bg_color, but much more flexibly.



@end ftable
See also:@*
@xref{alert}.@*
@xref{alert3}.@*
@xref{file_select_ex}.@*
@xref{gfx_mode_select}.@*
@xref{gui_fg_color}.@*
@xref{DIALOG}.@*
@node Platform, DOS, GUI, Top
@chapter Platform specifics
@menu
* DOS::                     DOS specifics
* Windows::                 Windows specifics
* Unix::                    Unix specifics
* BeOS::                    BeOS specifics
* QNX::                     QNX specifics
* MacOS::                   MacOS X specifics
* Differences::             Differences between platforms
@end menu
@node DOS, Windows, Platform, Platform
@section DOS specifics

There are four Allegro files which you should redistribute along your program.
These are the files `keyboard.dat', `language.dat', `allegro.cfg' and
`setup.exe'.

The first two contain internationalisation information for keyboard mappings
and system messages to show up localised on the user's computer. The
`setup.exe' program, which comes in Allegro's `setup' directory, is a
standalone tool which you can graphically customise and even embed into your
main binary. The user can generate a configuration file with this tool, to
store special settings or avoid Allegro's autodetection failing on specific
hardware. Even if you distribute `setup.exe', you are recommended to copy too
the empty `allegro.cfg' file, in case the setup program itself is unable to
run and the user has to edit manually the configuration with a text editor.

If you are using get_config_text() in your program to localise text strings,
merge your xxtext.cfg files with the ones provided by Allegro in the
`resource' directory before creating `language.dat', and redistribute this
with your program. This file will contain then both Allegro's system
messages and the strings of your program.

@menu
* JOY_TYPE_*/DOS::
* GFX_*/DOS::
* DIGI_*/DOS::
* MIDI_*/DOS::
* DOS integration routines::
* i_love_bill::
@end menu
@node JOY_TYPE_*/DOS, GFX_*/DOS, gui_shadow_box_proc, DOS
@subsection JOY_TYPE_*/DOS
@ftable @asis
@item @t{Drivers JOY_TYPE_*/DOS}
The DOS library supports the following type parameters for the 
install_joystick() function:

@itemize @bullet
@item 
JOY_TYPE_AUTODETECT@*
Attempts to autodetect your joystick hardware. It isn't possible to 
reliably distinguish between all the possible input setups, so this 
routine can only ever choose the standard joystick, Sidewider, GamePad 
Pro, or GrIP drivers, but it will use information from the 
configuration file if one is available (this can be created using the 
setup utility or by calling the save_joystick_data() function), so you 
can always use JOY_TYPE_AUTODETECT in your code and then select the 
exact hardware type from the setup program.
@item 
JOY_TYPE_NONE@*
Dummy driver for machines without any joystick.
@item 
JOY_TYPE_STANDARD@*
A normal two button stick.
@item 
JOY_TYPE_2PADS@*
Dual joystick mode (two sticks, each with two buttons).
@item 
JOY_TYPE_4BUTTON@*
Enable the extra buttons on a 4-button joystick.
@item 
JOY_TYPE_6BUTTON@*
Enable the extra buttons on a 6-button joystick.
@item 
JOY_TYPE_8BUTTON@*
Enable the extra buttons on an 8-button joystick.
@item 
JOY_TYPE_FSPRO@*
CH Flightstick Pro or compatible stick, which provides four buttons, 
an analogue throttle control, and a 4-direction coolie hat.
@item 
JOY_TYPE_WINGEX@*
A Logitech Wingman Extreme, which should also work with any 
Thrustmaster Mk.I compatible joystick. It provides support for four 
buttons and a coolie hat. This also works with the Wingman Warrior, if 
you plug in the 15 pin plug (remember to unplug the 9-pin plug!) and 
set the tiny switch in front to the "H" position (you will not be able 
to use the throttle or the spinner though).
@item 
JOY_TYPE_SIDEWINDER@*
The Microsoft Sidewinder digital pad (supports up to four controllers, 
each with ten buttons and a digital direction control).
@item 
JOY_TYPE_SIDEWINDER_AG@*
An alternative driver to JOY_TYPE_SIDEWINDER.
Try this if your Sidewinder isn't recognized with JOY_TYPE_SIDEWINDER.
@item 
JOY_TYPE_SIDEWINDER_PP@*
The Microsoft Sidewinder 3D/Precision/Force Feedback Pro joysticks.
@item 
JOY_TYPE_GAMEPAD_PRO@*
The Gravis GamePad Pro (supports up to two controllers, each with ten 
buttons and a digital direction control).
@item 
JOY_TYPE_GRIP@*
Gravis GrIP driver, using the grip.gll driver file.
@item 
JOY_TYPE_GRIP4@*
Version of the Gravis GrIP driver that is constrained to only move 
along the four main axes.
@item 
JOY_TYPE_SNESPAD_LPT1@*
JOY_TYPE_SNESPAD_LPT2@*
JOY_TYPE_SNESPAD_LPT3@*
SNES joypads connected to LPT1, LPT2, and LPT3 respectively.
@item 
JOY_TYPE_PSXPAD_LPT1@*
JOY_TYPE_PSXPAD_LPT2@*
JOY_TYPE_PSXPAD_LPT3@*
PSX joypads connected to LPT1, LPT2, and LPT3 respectively. See 
http://www.ziplabel.com/dpadpro/index.html for information 
about the parallel cable required. The driver automagically detects 
which types of PSX pads are connected out of digital, analog (red or 
green mode), NegCon, multi taps, Namco light guns, Jogcons (force 
feedback steering wheel) and the mouse. If the controller isn't 
recognised it is treated as an analog controller, meaning the driver 
should work with just about anything. You can connect controllers in 
any way you see fit, but only the first 8 will be used.

The Sony Dual Shock or Namco Jogcon will reset themselves (to digital 
mode) after not being polled for 5 seconds. This is normal, the same 
thing happens on a Playstation, it's designed to stop any vibration in 
case the host machine crashes. Other mode switching controllers may 
have similar quirks. However, if this happens to a Jogcon controller 
the mode button is disabled. To reenable the mode button on the Jogcon 
you need to hold down the Start and Select buttons at the same time.

The G-con45 needs to be connected to (and pointed at) a TV type monitor
connected to your computer. The composite video out on my video card 
works fine for this (a Hercules Stingray 128/3D 8Mb). The TV video 
modes in Mame should work too.
@item 
JOY_TYPE_N64PAD_LPT1@*
JOY_TYPE_N64PAD_LPT2@*
JOY_TYPE_N64PAD_LPT3@*
N64 joypads connected to LPT1, LPT2, and LPT3 respectively. See 
http://www.st-hans.de/N64.htm for information about the 
necessary hardware adapter. It supports up to four controllers on a 
single parallel port. There is no need to calibrate the analog stick, 
as this is done by the controller itself when powered up. This means 
that the stick has to be centred when the controller is initialised. 
One possible issue people may have with this driver is that it is 
physically impossible to move the analog stick fully diagonal, but I 
can't see this causing any major problems. This is because of the 
shape of the rim that the analog stick rests against. Like the Gravis 
Game Pad Pro, this driver briefly needs to disable hardware interrupts 
while polling. This causes a noticeable performance hit on my machine 
in both drivers, but there is no way around it. At a (very) rough 
guess I'd say it slows down Mame 5% - 10%.
@item 
JOY_TYPE_DB9_LPT1@*
JOY_TYPE_DB9_LPT2@*
JOY_TYPE_DB9_LPT3@*
A pair of two-button joysticks connected to LPT1, LPT2, and LPT3 
respectively. Port 1 is compatible with Linux joy-db9 driver 
(multisystem 2-button), and port 2 is compatible with Atari interface 
for DirectPad Pro. See the source file (src/dos/multijoy.c) for pinout 
information.
@item 
JOY_TYPE_TURBOGRAFIX_LPT1@*
JOY_TYPE_TURBOGRAFIX_LPT2@*
JOY_TYPE_TURBOGRAFIX_LPT3@*
These drivers support up to 7 joysticks, each one with up to 5 
buttons, connected to LPT1, LPT2, and LPT3 respectively. They use the 
TurboGraFX interface by Steffen Schwenke: see 
http://www.burg-halle.de/~schwenke/parport.html for details 
on how to build this.
@item 
JOY_TYPE_WINGWARRIOR@*
A Wingman Warrior joystick.
@item 
JOY_TYPE_IFSEGA_ISA@*
JOY_TYPE_IFSEGA_PCI@*
JOY_TYPE_IFSEGA_PCI_FAST@*
Drivers for the IF-SEGA joystick interface cards by the IO-DATA 
company (these come in PCI, PCI2, and ISA variants).
@end itemize

@end ftable
See also:@*
@xref{install_joystick}.@*
@node GFX_*/DOS, DIGI_*/DOS, JOY_TYPE_*/DOS, DOS
@subsection GFX_*/DOS
@ftable @asis
@item @t{Drivers GFX_*/DOS}
The DOS library supports the following card parameters for the 
set_gfx_mode() function:

@itemize @bullet
@item 
GFX_TEXT@*
Return to text mode.
@item 
GFX_AUTODETECT@*
Let Allegro pick an appropriate graphics driver.
@item 
GFX_AUTODETECT_FULLSCREEN@*
Autodetects a graphics driver, but will only use fullscreen drivers,
failing if these are not available on current platform.
@item 
GFX_AUTODETECT_WINDOWED@*
Same as above, but uses only windowed drivers. This will always fail
under DOS.
@item 
GFX_SAFE@*
Special driver for when you want to reliably set a graphics mode and 
don't really care what resolution or color depth you get. See the
set_gfx_mode() documentation for details.
@item 
GFX_VGA@*
The standard 256-color VGA mode 13h, using the GFX_VGA driver. This is 
normally sized 320x200, which will work on any VGA but doesn't support 
large virtual screens and hardware scrolling. Allegro also provides 
some tweaked variants of the mode which are able to scroll, sized 
320x100 (with a 200 pixel high virtual screen), 160x120 (with a 409 
pixel high virtual screen), 256x256 (no scrolling), and 80x80 (with a 
819 pixel high virtual screen).
@item 
GFX_MODEX@*
Mode-X will work on any VGA card, and provides a range of different 
256-color tweaked resolutions.

@itemize @bullet
@item 
Stable mode-X resolutions:

@itemize @bullet
@item 
Square aspect ratio: 320x240
@item 
Skewed aspect ratio: 256x224, 256x240, 320x200, 320x400,
320x480, 320x600, 360x200, 360x240,
360x360, 360x400, 360x480
@end itemize

These have worked on every card/monitor that I've tested.
@item 
Unstable mode-X resolutions:

@itemize @bullet
@item 
Square aspect ratio: 360x270, 376x282, 400x300
@item 
Skewed aspect ratio: 256x200, 256x256, 320x350, 360x600,
376x308, 376x564, 400x150, 400x600
@end itemize

These only work on some monitors. They were fine on my old machine, 
but don't get on very well with my new monitor. If you are worried 
about the possibility of damaging your monitor by using these 
modes, don't be. Of course I'm not providing any warranty with any 
of this, and if your hardware does blow up that is tough, but I 
don't think this sort of tweaking can do any damage. From the 
documentation of Robert Schmidt's TWEAK program:

"Some time ago, putting illegal or unsupported values or 
combinations of such into the video card registers might prove 
hazardous to both your monitor and your health. I have *never* 
claimed that bad things can't happen if you use TWEAK, although 
I'm pretty sure it never will. I've never heard of any damage 
arising from trying out TWEAK, or from general VGA tweaking in 
any case."
@end itemize

Most of the mode-X drawing functions are slower than in mode 13h, due 
to the complexity of the planar bitmap organisation, but solid area 
fills and plane-aligned blits from one part of video memory to another 
can be significantly faster, particularly on older hardware. Mode-X 
can address the full 256k of VGA RAM, so hardware scrolling and page 
flipping are possible, and it is possible to split the screen in order 
to scroll the top part of the display but have a static status 
indicator at the bottom.
@item 
GFX_VESA1@*
Use the VESA 1.x driver.
@item 
GFX_VESA2B@*
Use the VBE 2.0 banked mode driver.
@item 
GFX_VESA2L@*
Use the VBE 2.0 linear framebuffer driver.
@item 
GFX_VESA3@*
Use the VBE 3.0 driver. This is the only VESA driver that supports the 
request_refresh_rate() function.

The standard VESA modes are 640x480, 800x600, and 1024x768. These 
ought to work with any SVGA card: if they don't, get a copy of the 
SciTech Display Doctor and see if that fixes it. What color depths are 
available will depend on your hardware. Most cards support both 15 and 
16-bit resolutions, but if at all possible I would advise you to 
support both (it's not hard...) in case one is not available. Some 
cards provide both 24 and 32-bit truecolor, in which case it is a 
choice between 24 (saves memory) or 32 (faster), but many older cards 
have no 32-bit mode and some newer ones don't support 24-bit 
resolutions. Use the vesainfo test program to see what modes your VESA 
driver provides.

Many cards also support 640x400, 1280x1024, and 1600x1200, but these 
aren't available on everything, for example the S3 chipset has no 
640x400 mode. Other weird resolution may be possible, eg. some Tseng 
boards can do 640x350, and the Avance Logic has a 512x512 mode.

The SciTech Display Doctor provides several scrollable low resolution 
modes in a range of different color depths (320x200, 320x240, 320x400, 
320x480, 360x200, 360x240, 360x400, and 360x480 all work on my ET4000 
with 8, 15, or 16 bits per pixel). These are lovely, allowing 
scrolling and page flipping without the complexity of the mode-X 
planar setup, but unfortunately they aren't standard so you will need 
Display Doctor in order to use them.
@item 
GFX_VBEAF@*
VBE/AF is a superset of the VBE 2.0 standard, which provides an API 
for accessing hardware accelerator features. VBE/AF drivers are 
currently only available from the FreeBE/AF project or as part of the 
SciTech Display Doctor package, but they can give dramatic speed 
improvements when used with suitable hardware. For a detailed 
discussion of hardware acceleration issues, refer to the documentation 
for the gfx_capabilities flag.

You can use the afinfo test program to check whether you have a VBE/AF 
driver, and to see what resolutions it supports.

The SciTech VBE/AF drivers require nearptr access to be enabled, so 
any stray pointers are likely to crash your machine while their 
drivers are in use. This means it may be a good idea to use VESA while 
debugging your program, and only switch to VBE/AF once the code is 
working correctly. The FreeBE/AF drivers do not have this problem.
@item 
GFX_XTENDED@*
An unchained 640x400 mode, as described by Mark Feldman in the PCGPE. 
This uses VESA to select an SVGA mode (so it will only work on cards 
supporting the VESA 640x400 resolution), and then unchains the VGA 
hardware as for mode-X. This allows the entire screen to be addressed 
without the need for bank switching, but hardware scrolling and page 
flipping are not possible. This driver will never be autodetected (the 
normal VESA 640x400 mode will be chosen instead), so if you want to 
use it you will have to explicitly pass GFX_XTENDED to set_gfx_mode().
@end itemize

There are a few things you need to be aware of for scrolling:
most VESA implementations can only handle horizontal scrolling in four 
pixel increments, so smooth horizontal panning is impossible in SVGA modes. 
A significant number of VESA implementations seem to be very buggy when it 
comes to scrolling in truecolor video modes, so you shouldn't depend on 
this routine working correctly in the truecolor resolutions unless you can
be sure that SciTech Display Doctor is installed. Hardware scrolling may
also not work at all under Windows.

Triple buffering is only possible with certain drivers: it will work in any
DOS mode-X resolution if the timer retrace simulator is active (but this
doesn't work correctly under Windows 95), plus it is supported by the
VBE 3.0 and VBE/AF drivers for a limited number graphics cards.
@end ftable
See also:@*
@xref{set_gfx_mode}.@*
@node DIGI_*/DOS, MIDI_*/DOS, GFX_*/DOS, DOS
@subsection DIGI_*/DOS
@ftable @asis
@item @t{Drivers DIGI_*/DOS}
The DOS sound functions support the following digital sound cards:
@example

DIGI_AUTODETECT      - let Allegro pick a digital sound driver
DIGI_NONE            - no digital sound
DIGI_SB              - Sound Blaster (autodetect type)
DIGI_SB10            - SB 1.0 (8-bit mono single shot DMA)
DIGI_SB15            - SB 1.5 (8-bit mono single shot DMA)
DIGI_SB20            - SB 2.0 (8-bit mono auto-initialised
                       DMA)
DIGI_SBPRO           - SB Pro (8-bit stereo)
DIGI_SB16            - SB16 (16-bit stereo)
DIGI_AUDIODRIVE      - ESS AudioDrive
DIGI_SOUNDSCAPE      - Ensoniq Soundscape
DIGI_WINSOUNDSYS     - Windows Sound System@end example


@end ftable
See also:@*
@xref{detect_digi_driver}.@*
@xref{install_sound}.@*
@xref{install_sound_input}.@*
@node MIDI_*/DOS, DOS integration routines, DIGI_*/DOS, DOS
@subsection MIDI_*/DOS
@ftable @asis
@item @t{Drivers MIDI_*/DOS}
The DOS sound functions support the following MIDI sound cards:
@example

MIDI_AUTODETECT      - let Allegro pick a MIDI sound driver
MIDI_NONE            - no MIDI sound
MIDI_ADLIB           - Adlib or SB FM synth (autodetect type)
MIDI_OPL2            - OPL2 synth (mono, used in Adlib and SB)
MIDI_2XOPL2          - dual OPL2 synths (stereo, used in
                       SB Pro-I)
MIDI_OPL3            - OPL3 synth (stereo, SB Pro-II
                       and above)
MIDI_SB_OUT          - SB MIDI interface
MIDI_MPU             - MPU-401 MIDI interface
MIDI_DIGMID          - sample-based software wavetable player
MIDI_AWE32           - AWE32 (EMU8000 chip)@end example


@end ftable
See also:@*
@xref{detect_midi_driver}.@*
@xref{install_sound}.@*
@xref{install_sound_input}.@*
@node DOS integration routines, i_love_bill, MIDI_*/DOS, DOS
@subsection DOS integration routines
@ftable @asis

@end ftable
@node i_love_bill, JOY_TYPE_*/Windows, DOS integration routines, DOS
@subsection i_love_bill
@ftable @asis
@item @t{extern int i_love_bill;}
When running in clean DOS mode, the timer handler dynamically reprograms 
the clock chip to generate interrupts at exactly the right times, which 
gives an extremely high accuracy. Unfortunately, this constant speed 
adjustment doesn't work under most multitasking systems (notably 
Windows), so there is an alternative mode that just locks the hardware 
timer interrupt to a speed of 200 ticks per second. This reduces the 
accuracy of the timer (for instance, rest() will round the delay time to 
the nearest 5 milliseconds), and prevents the vertical retrace simulator 
from working, but on the plus side, it makes Allegro programs work under 
Windows. This flag is set by allegro_init() if it detects the presence of
a multitasking OS, and enables the fixed rate timer mode.



@end ftable
See also:@*
@xref{install_timer}.@*
@xref{allegro_init}.@*
@xref{os_type}.@*
@node Windows, Unix, DOS, Platform
@section Windows specifics

In terms of file redistribution, the Windows platform behaves practically the
same as the DOS platform. Read section chapter "Dos specifics" in the manual
to learn more about this.

A Windows program that uses the Allegro library is only required to include
one or more header files from the include/allegro tree, or allegro.h; however,
if it also needs to directly call non portable Win32 API functions, it must
include the Windows-specific header file winalleg.h after the Allegro headers,
and before any Win32 API header file. By default winalleg.h includes the main
Win32 C API header file windows.h. If instead you want to use the C++
interface to the Win32 API (a.k.a. the Microsoft Foundation Classes), define
the preprocessor symbol ALLEGRO_AND_MFC before including any Allegro header
so that afxwin.h will be included. Note that, in this latter case, the Allegro
debugging macros ASSERT() and TRACE() are renamed AL_ASSERT() and AL_TRACE()
respectively.

Windows GUI applications start with a WinMain() entry point, rather than the
standard main() entry point. Allegro is configured to build GUI applications
by default and to do some magic in order to make a regular main() work with
them, but you have to help it out a bit by writing END_OF_MAIN() right after
your main() function. If you don't want to do that, you can just include
winalleg.h and write a WinMain() function. Note that this magic may bring
about conflicts with a few programs using direct calls to Win32 API
functions; for these programs, the regular WinMain() is required and the
magic must be disabled by defining the preprocessor symbol
ALLEGRO_NO_MAGIC_MAIN before including Allegro headers.

If you want to build a console application using Allegro, you have to define
the preprocessor symbol ALLEGRO_USE_CONSOLE before including Allegro headers;
it will instruct the library to use console features and also to disable the
special processing of the main() function described above.

When creating the main window, Allegro searches the executable for an ICON 
resource named "allegro_icon". If it is present, Allegro automatically
loads it and uses it as its application icon; otherwise, Allegro uses the 
default IDI_APPLICATION icon. See the manual of your compiler for a method 
to create an ICON resource, or use the wfixicon utility from the tools/win 
directory.

DirectX requires that system and video bitmaps (including the screen) be 
locked before you can draw onto them. This will be done automatically, but 
you can usually get much better performance by doing it yourself: see the 
acquire_bitmap() function for details.

Due to a major oversight in the design of DirectX, there is no way to 
preserve the contents of video memory when the user switches away from your 
program. You need to be prepared for the fact that your screen contents, and 
the contents of any video memory bitmaps, may be destroyed at any point. You 
can use the set_display_switch_callback() function to find out when this 
happens.

On the Windows platform, the only return values for the desktop_color_depth()
function are 8, 16, 24 and 32. This means that 15-bit and 16-bit desktops 
cannot be differentiated and are both reported as 16-bit desktops. See
below for the consequences for windowed and overlay DirectX drivers.

@menu
* JOY_TYPE_*/Windows::
* GFX_*/Windows::
* DIGI_*/Windows::
* MIDI_*/Windows::
* Windows integration routines::
* win_get_window::
* win_set_window::
* win_set_wnd_create_proc::
* win_get_dc::
* win_release_dc::
* GDI routines::
* set_gdi_color_format::
* set_palette_to_hdc::
* convert_palette_to_hpalette::
* convert_hpalette_to_palette::
* convert_bitmap_to_hbitmap::
* convert_hbitmap_to_bitmap::
* draw_to_hdc::
* blit_to_hdc::
* stretch_blit_to_hdc::
* blit_from_hdc::
* stretch_blit_from_hdc::
@end menu
@node JOY_TYPE_*/Windows, GFX_*/Windows, i_love_bill, Windows
@subsection JOY_TYPE_*/Windows
@ftable @asis
@item @t{Drivers JOY_TYPE_*/Windows}
The Windows library supports the following type parameters for the 
install_joystick() function:

@itemize @bullet
@item 
JOY_TYPE_AUTODETECT@*
Attempts to autodetect your joystick hardware. It will use information 
from the configuration file if one is available (this can be created 
using the setup utility or by calling the save_joystick_data()
function), so you can always use JOY_TYPE_AUTODETECT in your code and
then select the exact hardware type from the setup program.
@item 
JOY_TYPE_NONE@*
Dummy driver for machines without any joystick.
@item 
JOY_TYPE_DIRECTX@*
Use DirectInput to access the joystick.
@item 
JOY_TYPE_WIN32@*
Use the regular Win32 interface rather than DirectInput to access the
joystick.
@end itemize


@end ftable
See also:@*
@xref{install_joystick}.@*
@node GFX_*/Windows, DIGI_*/Windows, JOY_TYPE_*/Windows, Windows
@subsection GFX_*/Windows
@ftable @asis
@item @t{Drivers GFX_*/Windows}
The Windows library supports the following card parameters for the 
set_gfx_mode() function:

@itemize @bullet
@item 
GFX_TEXT@*
This closes any graphics mode previously opened with set_gfx_mode.
@item 
GFX_AUTODETECT@*
Let Allegro pick an appropriate graphics driver.
@item 
GFX_AUTODETECT_FULLSCREEN@*
Autodetects a graphics driver, but will only use fullscreen drivers,
failing if these are not available on current platform.
@item 
GFX_AUTODETECT_WINDOWED@*
Same as above, but uses only windowed drivers.
@item 
GFX_SAFE@*
Special driver for when you want to reliably set a graphics mode and 
don't really care what resolution or color depth you get. See the
set_gfx_mode() documentation for details.
@item 
GFX_DIRECTX@*
Alias for GFX_DIRECTX_ACCEL.
@item 
GFX_DIRECTX_ACCEL@*
The regular fullscreen DirectX driver, running with hardware 
acceleration enabled.
@item 
GFX_DIRECTX_SOFT@*
DirectX fullscreen driver that only uses software drawing, rather than 
any hardware accelerated features.
@item 
GFX_DIRECTX_SAFE@*
Simplified fullscreen DirectX driver that doesn't support any hardware 
acceleration, video or system bitmaps, etc.
@item 
GFX_DIRECTX_WIN@*
The regular windowed DirectX driver, running in color conversion mode 
when the color depth doesn't match that of the Windows desktop. Color 
conversion is much slower than direct drawing and is not supported 
between 15-bit and 16-bit color depths. This limitation is needed to 
work around that of desktop_color_depth() (see above) and allows to 
select the direct drawing mode in a reliable way on desktops reported 
as 16-bit:
@example

if (desktop_color_depth() == 16) @{
   set_color_depth(16);
   if (set_gfx_mode(GFX_DIRECTX_WIN, 640, 480, 0, 0)
       != 0) @{
      set_color_depth(15);
      if (set_gfx_mode(GFX_DIRECTX_WIN, 640, 480, 0, 0)
          != 0) @{
         /* 640x480 direct drawing mode not supported */
         goto Error;
      @}
   @}
   /* ok, we are in direct drawing mode */
@}
@end example

Note that, mainly for performance reasons, this driver requires the
width of the screen to be a multiple of 4.
This driver is capable of displaying a hardware cursor, but there are
size restrictions. Typically, the cursor image cannot be more than
32x32 pixels.
@item 
GFX_DIRECTX_OVL@*
The DirectX overlay driver. It uses special hardware features to run 
your program in a windowed mode: it doesn't work on all hardware, but 
performance is excellent on cards that are capable of it. It requires 
the color depth to be the same as that of the Windows desktop. In light 
of the limitation of desktop_color_depth() (see above), the reliable 
way of setting the overlay driver on desktops reported as 16-bit is:
@example

if (desktop_color_depth() == 16) @{
   set_color_depth(16);
   if (set_gfx_mode(GFX_DIRECTX_OVL, 640, 480, 0, 0)
       != 0) @{
      set_color_depth(15);
      if (set_gfx_mode(GFX_DIRECTX_OVL, 640, 480, 0, 0)
          != 0) @{
         /* 640x480 overlay driver not supported */
         goto Error;
      @}
   @}
   /* ok, the 640x480 overlay driver is running */
@}@end example

@item 
GFX_GDI@*
The windowed GDI driver. It is extremely slow, but is guaranteed to 
work on all hardware, so it can be useful for situations where you 
want to run in a window and don't care about performance. Note that 
this driver features a hardware mouse cursor emulation in order to 
speed up basic mouse operations (like GUI operations).
@end itemize

@end ftable
See also:@*
@xref{set_gfx_mode}.@*
@node DIGI_*/Windows, MIDI_*/Windows, GFX_*/Windows, Windows
@subsection DIGI_*/Windows
@ftable @asis
@item @t{Drivers DIGI_*/Windows}
The Windows sound functions support the following digital sound cards:
@example

DIGI_AUTODETECT      - let Allegro pick a digital sound driver
DIGI_NONE            - no digital sound
DIGI_DIRECTX(n)      - use DirectSound device #n (zero-based)
                       with direct mixing
DIGI_DIRECTAMX(n)    - use DirectSound device #n (zero-based)
                       with Allegro mixing
DIGI_WAVOUTID(n)     - high (n=0) or low (n=1) quality WaveOut
                       device@end example


@end ftable
See also:@*
@xref{detect_digi_driver}.@*
@xref{install_sound}.@*
@xref{install_sound_input}.@*
@node MIDI_*/Windows, Windows integration routines, DIGI_*/Windows, Windows
@subsection MIDI_*/Windows
@ftable @asis
@item @t{Drivers MIDI_*/Windows}
The Windows sound functions support the following MIDI sound cards:
@example

MIDI_AUTODETECT      - let Allegro pick a MIDI sound driver
MIDI_NONE            - no MIDI sound
MIDI_WIN32MAPPER     - use win32 MIDI mapper
MIDI_WIN32(n)        - use win32 device #n (zero-based)
MIDI_DIGMID          - sample-based software wavetable player@end example


@end ftable
See also:@*
@xref{detect_midi_driver}.@*
@xref{install_sound}.@*
@xref{install_sound_input}.@*
@node Windows integration routines, win_get_window, MIDI_*/Windows, Windows
@subsection Windows integration routines
@ftable @asis

@end ftable
The following functions provide a platform specific interface to seamlessly 
integrate Allegro into general purpose Win32 programs. To use these routines, 
you must include winalleg.h after other Allegro headers.

@node win_get_window, win_set_window, Windows integration routines, Windows
@subsection win_get_window
@ftable @asis
@item @t{HWND win_get_window(void);}
Retrieves a handle to the window used by Allegro. Note that Allegro
uses an underlying window even though you don't set any graphics mode,
unless you have installed the neutral system driver (SYSTEM_NONE).

@end ftable
@node win_set_window, win_set_wnd_create_proc, win_get_window, Windows
@subsection win_set_window
@ftable @asis
@item @t{void win_set_window(HWND wnd);}
Registers an user-created window to be used by Allegro. This function is
meant to be called before initialising the library with allegro_init()
or installing the autodetected system driver (SYSTEM_AUTODETECT). It
lets you attach Allegro to any already existing window and prevents the
library from creating its own, thus leaving you total control over the
window; in particular, you are responsible for processing the events as
usual (Allegro will automatically monitor a few of them, but will not
filter out any of them). You can then use every component of the library
(graphics, mouse, keyboard, sound, timers and so on), bearing in mind
that some Allegro functions are blocking (e.g. readkey() if the key buffer
is empty) and thus must be carefully manipulated by the window thread.

However you can also call it after the library has been initialised,
provided that no graphics mode is set. In this case the keyboard, mouse,
joystick, sound and sound recording modules will be restarted.

Passing NULL instructs Allegro to switch back to its built-in window if
an user-created window was registered, or to request a new handle from
Windows for its built-in window if this was already in use.

@end ftable
@node win_set_wnd_create_proc, win_get_dc, win_set_window, Windows
@subsection win_set_wnd_create_proc
@ftable @asis
@item @t{void win_set_wnd_create_proc(HWND (*proc)(WNDPROC));}
Registers an user-defined procedure to be used by Allegro for creating
its window. This function must be called *before* initializing the
library with allegro_init() or installing the autodetected system
driver (SYSTEM_AUTODETECT). It lets you customize Allegro's window but
only by its creation: unlike with win_set_window(), you have no control
over the window once it has been created (in particular, you are not
responsible for processing the events). The registered function will be
passed a window procedure (WNDPROC object) that it must make the 
procedure of the new window of and it must return a handle to the new 
window. You can then use the full-featured library in the regular way.

@end ftable
@node win_get_dc, win_release_dc, win_set_wnd_create_proc, Windows
@subsection win_get_dc
@ftable @asis
@item @t{HDC win_get_dc(BITMAP *bmp);}
Retrieves a handle to the device context of a DirectX video or system
bitmap.

@end ftable
@xref{BITMAP}.@*
@node win_release_dc, GDI routines, win_get_dc, Windows
@subsection win_release_dc
@ftable @asis
@item @t{void win_release_dc(BITMAP *bmp, HDC dc);}
Releases a handle to the device context of the bitmap that was
previously retrieved with win_get_dc().

@end ftable
@xref{BITMAP}.@*
@node GDI routines, set_gdi_color_format, win_release_dc, Windows
@subsection GDI routines
@ftable @asis

@end ftable
The following GDI routines are a very platform specific thing, to allow 
drawing Allegro memory bitmaps onto a Windows device context. When you want 
to use this, you'll have to install the neutral system driver (SYSTEM_NONE) 
or attach Allegro to an external window with win_set_window().

There are two ways to draw your Allegro bitmaps to the Windows GDI. When you 
are using static bitmaps (for example just some pictures loaded from a 
datafile), you can convert them to DDB (device-dependent bitmaps) with 
convert_bitmap_to_hbitmap() and then just use Win32's BitBlt() to draw it.

When you are using dynamic bitmaps (for example some things which react to 
user input), it's better to use set_palette_to_hdc() and blit_to_hdc() 
functions, which work with DIB (device-independent bitmaps).

There are also functions to blit from a device context into an Allegro 
BITMAP, so you can do things like screen capture.

All the drawing and conversion functions use the current palette as a color 
conversion table. You can alter the current palette with the 
set_palette_to_hdc() or select_palette() functions. Warning: when the GDI 
system color palette is explicitly changed, (by another application, for 
example) the current Allegro palette is not updated along with it!

To use these routines, you must include winalleg.h after Allegro headers.

@node set_gdi_color_format, set_palette_to_hdc, GDI routines, Windows
@subsection set_gdi_color_format
@ftable @asis
@item @t{void set_gdi_color_format(void);}
Tells Allegro to use the GDI color layout for truecolor images. This is 
optional, but it will make the conversions work faster. If you are going 
to call this, you should do it right after initialising Allegro and 
before creating any graphics.

@end ftable
@node set_palette_to_hdc, convert_palette_to_hpalette, set_gdi_color_format, Windows
@subsection set_palette_to_hdc
@ftable @asis
@item @t{void set_palette_to_hdc(HDC dc, PALETTE pal);}
Selects and realizes an Allegro palette on the specified device context.

@end ftable
@xref{PALETTE}.@*
@node convert_palette_to_hpalette, convert_hpalette_to_palette, set_palette_to_hdc, Windows
@subsection convert_palette_to_hpalette
@ftable @asis
@item @t{HPALETTE convert_palette_to_hpalette(PALETTE pal);}
Converts an Allegro palette to a Windows palette and returns a handle to 
it. You should call DeleteObject() when you no longer need it.

@end ftable
See also:@*
@xref{convert_hpalette_to_palette}.@*
@xref{PALETTE}.@*
@node convert_hpalette_to_palette, convert_bitmap_to_hbitmap, convert_palette_to_hpalette, Windows
@subsection convert_hpalette_to_palette
@ftable @asis
@item @t{void convert_hpalette_to_palette(HPALETTE hpal, PALETTE pal);}
Converts a Windows palette to an Allegro palette.

@end ftable
See also:@*
@xref{convert_palette_to_hpalette}.@*
@xref{PALETTE}.@*
@node convert_bitmap_to_hbitmap, convert_hbitmap_to_bitmap, convert_hpalette_to_palette, Windows
@subsection convert_bitmap_to_hbitmap
@ftable @asis
@item @t{HBITMAP convert_bitmap_to_hbitmap(BITMAP *bitmap);}
Converts an Allegro memory bitmap to a Windows DDB and returns a handle 
to it. This bitmap uses its own memory, so you can destroy the original 
bitmap without affecting the converted one. You should call 
DeleteObject() when you no longer need this bitmap.

@end ftable
See also:@*
@xref{convert_hbitmap_to_bitmap}.@*
@xref{BITMAP}.@*
@node convert_hbitmap_to_bitmap, draw_to_hdc, convert_bitmap_to_hbitmap, Windows
@subsection convert_hbitmap_to_bitmap
@ftable @asis
@item @t{BITMAP *convert_hbitmap_to_bitmap(HBITMAP bitmap);}
Creates an Allegro memory bitmap from a Windows DDB.

@end ftable
See also:@*
@xref{convert_bitmap_to_hbitmap}.@*
@xref{BITMAP}.@*
@node draw_to_hdc, blit_to_hdc, convert_hbitmap_to_bitmap, Windows
@subsection draw_to_hdc
@ftable @asis
@item @t{void draw_to_hdc(HDC dc, BITMAP *bitmap, int x, int y);}
Draws an entire Allegro bitmap to a Windows device context, using the 
same parameters as the draw_sprite() function.

@end ftable
See also:@*
@xref{blit_to_hdc}.@*
@xref{stretch_blit_to_hdc}.@*
@xref{draw_sprite}.@*
@xref{BITMAP}.@*
@node blit_to_hdc, stretch_blit_to_hdc, draw_to_hdc, Windows
@subsection blit_to_hdc
@ftable @asis
@item @t{void blit_to_hdc(BITMAP *bitmap, HDC dc, int sx, sy, dx, dy, w, h);}
Blits an Allegro memory bitmap to a Windows device context, using the 
same parameters as the blit() function.

@end ftable
See also:@*
@xref{draw_to_hdc}.@*
@xref{stretch_blit_to_hdc}.@*
@xref{blit_from_hdc}.@*
@xref{blit}.@*
@xref{BITMAP}.@*
@node stretch_blit_to_hdc, blit_from_hdc, blit_to_hdc, Windows
@subsection stretch_blit_to_hdc
@ftable @asis
@item @t{void stretch_blit_to_hdc(BITMAP *bitmap, HDC dc, int sx, sy, sw, sh, int dx, dy, dw, dh);}
Blits an Allegro memory bitmap to a Windows device context, using the 
same parameters as the stretch_blit() function.

@end ftable
See also:@*
@xref{draw_to_hdc}.@*
@xref{blit_to_hdc}.@*
@xref{stretch_blit_from_hdc}.@*
@xref{stretch_blit}.@*
@xref{BITMAP}.@*
@node blit_from_hdc, stretch_blit_from_hdc, stretch_blit_to_hdc, Windows
@subsection blit_from_hdc
@ftable @asis
@item @t{void blit_from_hdc(HDC hdc, BITMAP *bitmap, int sx, sy, dx, dy, w, h);}
Blits from a Windows device context to an Allegro memory bitmap, using 
the same parameters as the blit() function. See stretch_blit_from_hdc() 
for details.

@end ftable
See also:@*
@xref{stretch_blit_from_hdc}.@*
@xref{blit_to_hdc}.@*
@xref{blit}.@*
@xref{BITMAP}.@*
@node stretch_blit_from_hdc, JOY_TYPE_*/Linux, blit_from_hdc, Windows
@subsection stretch_blit_from_hdc
@ftable @asis
@item @t{void stretch_blit_from_hdc(HDC hcd, BITMAP *bitmap, int sx, sy, sw, sh, int dx, dy, dw, dh);}
Blits from a Windows device context to an Allegro memory bitmap, using 
the same parameters as the stretch_blit() function. It uses the current 
Allegro palette and does conversion to this palette, regardless of the 
current DC palette. So if you are blitting from 8-bit mode, you should 
first set the DC palette with the set_palette_to_hdc() function.


@end ftable
See also:@*
@xref{blit_from_hdc}.@*
@xref{stretch_blit_to_hdc}.@*
@xref{stretch_blit}.@*
@xref{BITMAP}.@*
@node Unix, BeOS, Windows, Platform
@section Unix specifics

Under Unix you usually have two ways of redistributing your binaries. You
either pack everything in a single directory, even providing Allegro in
binary or source form for the user to compile. Or your program is being
packaged separately from Allegro and stored in different paths. For the
first case of redistribution, read section "Files shared by Allegro" from
the "Dos specifics" chapter to learn more about this.

For the second type, you can ignore redistributing the setup, keyboard
mappings and language datafiles, because they will be already installed in
the system. This, however, is problematic if you are using get_config_text()
to localise your program's text strings.

The problem is that on other platforms you usually mix your program's text
strings with those of Allegro (found in the `resources' directory) to create
a special language.dat. And it is likely that the Allegro library installed
on the user's system already contains a datafile.dat. You can go ahead and
still provide your own language.dat file, but this will mean that if Allegro
is updated, your language.dat file may not contain all the text strings used
by the new version.

Given the slow paced release cycle of Allegro, this might not be a concern.
However, if you want to make it easy on system administrators, instead of
providing your own `language.dat', you should provide the separate
`xxtext.cfg' files it in a separate directory. Then, before showing the
strings to the user you can detect the language setting and use
override_config_file() with the appropriate localisation file and call
reload_config_texts().

In order to locate things like the config and translation files, Allegro
needs to know the path to your executable. Since there is no standard way to 
find that, it needs to capture a copy of your argv[] parameter, and it does 
this with some preprocessor macro trickery. Unfortunately it can't quite 
pull this off without a little bit of your help, so you will have to write 
END_OF_MAIN() right after your main() function. Pretty easy, really, and if 
you forget, you'll get a nice linker error about a missing _mangled_main 
function to remind you :-)

Under Unix resources are searched for in many different paths (see above).
When a configuration resource is looked for, it is usually tried with the
variations `name.cfg' or `.namerc' in multiple paths: the current directory,
the directory pointed to by the ALLEGRO environment variable, the user's home
directory, one or more global system directories which usually only the
root user has access to and any custom paths set up with
set_allegro_resource_path(). Text files, like the main allegro config file or
a language text translation files are looked for in the following places:
@example

./allegro.cfg
$ALLEGRO/allegro.cfg
~/allegro.cfg
~/.allegrorc
/etc/allegro.cfg
/etc/allegrorc
@end example

Binary resources like the language translation files packfile (language.dat)
are looked for in:
@example

./language.dat
$ALLEGRO/language.dat
~/language.dat
/etc/language.dat
/usr/share/allegro/language.dat
/usr/local/share/allegro/language.dat
@end example

Note that if you have installed Allegro from the source distribution with
the typical `make install', global files like `language.dat' and
`allegro.cfg' will not have been installed. As a system administrator you are
required to install them manually wherever you prefer to have them. If you
suspect that an Allegro program is somehow not finding the correct
configuration file, you could try using the following command:
@example

strace program 2>&1|egrep "(open|stat)"
@end example

The strace program traces system calls and signals. By default it outputs
the information to stderr, so that's why we redirect it to stdin with `2>&1'.
Since we are interested only in files being (un)successfully opened, we
restrict the output of the log to stat or open calls with the extended grep
command. You could add another grep to filter only lines with text like
`language' or `allegro'.

@menu
* JOY_TYPE_*/Linux::
* GFX_*/Linux::
* GFX_*/X::
* DIGI_*/Unix::
* MIDI_*/Unix::
* Unix integration routines::
* xwin_set_window_name::
* allegro_icon::
@end menu
@node JOY_TYPE_*/Linux, GFX_*/Linux, stretch_blit_from_hdc, Unix
@subsection JOY_TYPE_*/Linux
@ftable @asis
@item @t{Drivers JOY_TYPE_*/Linux}
The Linux library supports the following type parameters for the 
install_joystick() function:

@itemize @bullet
@item 
JOY_TYPE_AUTODETECT@*
Attempts to autodetect your joystick hardware. It will use information 
from the configuration file if one is available (this can be created 
using the setup utility or by calling the save_joystick_data()
function), so you can always use JOY_TYPE_AUTODETECT in your code and
then select the exact hardware type from the setup program.
@item 
JOY_TYPE_NONE@*
Dummy driver for machines without any joystick.
@item 
JOY_TYPE_LINUX_ANALOGUE@*
Regular joystick interface. Joystick support needs to be enabled in your
kernel.
@end itemize


@end ftable
See also:@*
@xref{install_joystick}.@*
@node GFX_*/Linux, GFX_*/X, JOY_TYPE_*/Linux, Unix
@subsection GFX_*/Linux
@ftable @asis
@item @t{Drivers GFX_*/Linux}
When running in Linux console mode, Allegro supports the following card 
parameters for the set_gfx_mode() function:

@itemize @bullet
@item 
GFX_TEXT@*
Return to text mode.
@item 
GFX_AUTODETECT@*
Let Allegro pick an appropriate graphics driver.
@item 
GFX_AUTODETECT_FULLSCREEN@*
Autodetects a graphics driver, but will only use fullscreen drivers,
failing if these are not available on current platform.
@item 
GFX_AUTODETECT_WINDOWED@*
Same as above, but uses only windowed drivers. This will always fail
under Linux console mode.
@item 
GFX_SAFE@*
Special driver for when you want to reliably set a graphics mode and 
don't really care what resolution or color depth you get. See the
set_gfx_mode() documentation for details.
@item 
GFX_FBCON@*
Use the framebuffer device (eg. /dev/fb0). This requires you to have 
framebuffer support compiled into your kernel, and correctly 
configured for your hardware. It is currently the only console mode 
driver that will work without root permissions, unless you are using
a development version of SVGAlib.
@item 
GFX_VBEAF@*
Use a VBE/AF driver (vbeaf.drv), assuming that you have installed one 
which works under Linux (currently only two of the FreeBE/AF project 
drivers are capable of this: I don't know about the SciTech ones). 
VBE/AF requires root permissions, but is currently the only Linux 
driver which supports hardware accelerated graphics.
@item 
GFX_SVGALIB@*
Use the SVGAlib library for graphics output. This requires root
permissions if your version of SVGAlib requires them.
@item 
GFX_VGA@*
GFX_MODEX@*
Use direct hardware access to set standard VGA or mode-X resolutions, 
supporting the same modes as in the DOS versions of these drivers. 
Requires root permissions.
@end itemize

@end ftable
See also:@*
@xref{set_gfx_mode}.@*
@xref{GFX_*/X}.@*
@node GFX_*/X, DIGI_*/Unix, GFX_*/Linux, Unix
@subsection GFX_*/X
@ftable @asis
@item @t{Drivers GFX_*/X}
When running in X mode, Allegro supports the following card parameters 
for the set_gfx_mode() function:

@itemize @bullet
@item 
GFX_TEXT@*
This closes any graphics mode previously opened with set_gfx_mode.
@item 
GFX_AUTODETECT@*
Let Allegro pick an appropriate graphics driver.
@item 
GFX_AUTODETECT_FULLSCREEN@*
Autodetects a graphics driver, but will only use fullscreen drivers,
failing if these are not available on current platform.
@item 
GFX_AUTODETECT_WINDOWED@*
Same as above, but uses only windowed drivers.
@item 
GFX_SAFE@*
Special driver for when you want to reliably set a graphics mode and 
don't really care what resolution or color depth you get. See the
set_gfx_mode() documentation for details.
@item 
GFX_XWINDOWS@*
The standard X graphics driver. This should work on any Unix system, 
and can operate remotely. It does not require root permissions.
If the ARGB cursor extension is available, this driver is capable
of displaying a hardware cursor. This needs to be enabled by calling
enable_hardware_cursor() because it cannot be used reliably alongside
get_mouse_mickeys().
@item 
GFX_XWINDOWS_FULLSCREEN@*
The same as above, but while GFX_XWINDOWS runs windowed, this one uses
the XF86VidMode extension to make it run in fullscreen mode even
without root permissions. You're still using the standard X protocol
though, so expect the same low performances as with the windowed
driver version.
If the ARGB cursor extension is available, this driver is capable
of displaying a hardware cursor. This needs to be enabled by calling
enable_hardware_cursor() because it cannot be used reliably alongside
get_mouse_mickeys().
@item 
GFX_XDGA2@*
Use new DGA 2.0 extension provided by XFree86 4.0.x. This will work
in fullscreen mode, and it will support hardware acceleration if
available. This driver requires root permissions.
@item 
GFX_XDGA2_SOFT@*
The same as GFX_XDGA2, but turns off hardware acceleration support.
This driver requires root permissions.
@end itemize

@end ftable
See also:@*
@xref{set_gfx_mode}.@*
@xref{GFX_*/Linux}.@*
@node DIGI_*/Unix, MIDI_*/Unix, GFX_*/X, Unix
@subsection DIGI_*/Unix
@ftable @asis
@item @t{Drivers DIGI_*/Unix}
The Unix sound functions support the following digital sound cards:
@example

DIGI_AUTODETECT      - let Allegro pick a digital sound driver
DIGI_NONE            - no digital sound
DIGI_OSS             - Open Sound System
DIGI_ESD             - Enlightened Sound Daemon
DIGI_ARTS            - aRts (Analog Real-Time Synthesizer)
DIGI_ALSA            - ALSA sound driver
DIGI_JACK            - JACK sound driver@end example


@end ftable
See also:@*
@xref{detect_digi_driver}.@*
@xref{install_sound}.@*
@xref{install_sound_input}.@*
@node MIDI_*/Unix, Unix integration routines, DIGI_*/Unix, Unix
@subsection MIDI_*/Unix
@ftable @asis
@item @t{Drivers MIDI_*/Unix}
The Unix sound functions support the following MIDI sound cards:
@example

MIDI_AUTODETECT      - let Allegro pick a MIDI sound driver
MIDI_NONE            - no MIDI sound
MIDI_OSS             - Open Sound System
MIDI_DIGMID          - sample-based software wavetable player
MIDI_ALSA            - ALSA RawMIDI driver@end example


@end ftable
See also:@*
@xref{detect_midi_driver}.@*
@xref{install_sound}.@*
@xref{install_sound_input}.@*
@node Unix integration routines, xwin_set_window_name, MIDI_*/Unix, Unix
@subsection Unix integration routines
@ftable @asis

@end ftable
@node xwin_set_window_name, allegro_icon, Unix integration routines, Unix
@subsection xwin_set_window_name
@ftable @asis
@item @t{void xwin_set_window_name(const char *name, const char *group);}
This function is only available under X. It lets you to specify the
window name and group (or class). They are important because they allow
the window manager to remember the window attributes (position, layer,
etc). Note that the name and the title of the window are two different
things: the title is what appears in the title bar of the window, but
usually has no other effects on the behaviour of the application.

@end ftable
See also:@*
@xref{set_window_title}.@*
@node allegro_icon, GFX_*/BeOS, xwin_set_window_name, Unix
@subsection allegro_icon
@ftable @asis
@item @t{extern void *allegro_icon;}
This is a pointer to the Allegro X11 icon, which is in the format of 
standard .xpm bitmap data.
You do not normally have to bother with this at all: you can use the
xfixicon.sh utility from the tools/x11 directory to convert a true 
colour bitmap to a C file that you only need to link with your own code
to set the icon.



@end ftable
@node BeOS, QNX, Unix, Platform
@section BeOS specifics

In terms of file redistribution, the BeOS platform behaves practically the
same as the DOS platform. Read section chapter "Dos specifics" in the manual
to learn more about this.

@menu
* GFX_*/BeOS::
* DIGI_*/BeOS::
* MIDI_*/BeOS::
@end menu
@node GFX_*/BeOS, DIGI_*/BeOS, allegro_icon, BeOS
@subsection GFX_*/BeOS
@ftable @asis
@item @t{Drivers GFX_*/BeOS}
BeOS Allegro supports the following card parameters for the
set_gfx_mode() function:

@itemize @bullet
@item 
GFX_TEXT@*
This closes any graphics mode previously opened with set_gfx_mode.
@item 
GFX_AUTODETECT@*
Let Allegro pick an appropriate graphics driver.
@item 
GFX_AUTODETECT_FULLSCREEN@*
Autodetects a graphics driver, but will only use fullscreen drivers,
failing if these are not available on current platform.
@item 
GFX_AUTODETECT_WINDOWED@*
Same as above, but uses only windowed drivers.
@item 
GFX_SAFE@*
Special driver for when you want to reliably set a graphics mode and 
don't really care what resolution. See the set_gfx_mode() 
documentation for details.
@item 
GFX_BWINDOWSCREEN_ACCEL@*
Fullscreen exclusive mode. Supports only resolutions higher or equal
to 640x480, and uses hardware acceleration if available.
@item 
GFX_BWINDOWSCREEN@*
Works the same as GFX_BWINDOWSCREEN_ACCEL, but disables acceleration.
@item 
GFX_BDIRECTWINDOW@*
Fast windowed mode using the BDirectWindow class. Not all graphics
cards support this.
@item 
GFX_BWINDOW@*
Normal windowed mode using the BWindow class. Slow but always works.
@item 
GFX_BWINDOW_OVERLAY@*
Fullscreen mode using BWindow with a BBitmap overlay. This mode isn't
supported by all graphics cards, only supports 15, 16 and 32-bit color
depths, but allows any fullscreen resolution, even low ones that are
normally unavailable under BeOS.
@end itemize

@end ftable
See also:@*
@xref{set_gfx_mode}.@*
@node DIGI_*/BeOS, MIDI_*/BeOS, GFX_*/BeOS, BeOS
@subsection DIGI_*/BeOS
@ftable @asis
@item @t{Drivers DIGI_*/BeOS}
The BeOS sound functions support the following digital sound cards:
@example

DIGI_AUTODETECT      - let Allegro pick a digital sound driver
DIGI_NONE            - no digital sound
DIGI_BEOS            - BeOS digital output@end example


@end ftable
See also:@*
@xref{detect_digi_driver}.@*
@xref{install_sound}.@*
@xref{install_sound_input}.@*
@node MIDI_*/BeOS, GFX_*/QNX, DIGI_*/BeOS, BeOS
@subsection MIDI_*/BeOS
@ftable @asis
@item @t{Drivers MIDI_*/BeOS}
The BeOS sound functions support the following MIDI sound cards:
@example

MIDI_AUTODETECT      - let Allegro pick a MIDI sound driver
MIDI_NONE            - no MIDI sound
MIDI_BEOS            - BeOS MIDI output
MIDI_DIGMID          - sample-based software wavetable player
@end example



@end ftable
See also:@*
@xref{detect_midi_driver}.@*
@xref{install_sound}.@*
@xref{install_sound_input}.@*
@node QNX, MacOS, BeOS, Platform
@section QNX specifics

In terms of file redistribution, the QNX platform behaves practically the
same as the DOS platform. Read section chapter "Dos specifics" in the manual
to learn more about this.

@menu
* GFX_*/QNX::
* DIGI_*/QNX::
* MIDI_*/QNX::
* QNX integration routines::
* qnx_get_window::
@end menu
@node GFX_*/QNX, DIGI_*/QNX, MIDI_*/BeOS, QNX
@subsection GFX_*/QNX
@ftable @asis
@item @t{Drivers GFX_*/QNX}
QNX Allegro supports the following card parameters for the
set_gfx_mode() function:

@itemize @bullet
@item 
GFX_TEXT@*
This closes any graphics mode previously opened with set_gfx_mode.
@item 
GFX_AUTODETECT@*
Let Allegro pick an appropriate graphics driver.
@item 
GFX_AUTODETECT_FULLSCREEN@*
Autodetects a graphics driver, but will only use fullscreen drivers,
failing if these are not available on current platform.
@item 
GFX_AUTODETECT_WINDOWED@*
Same as above, but uses only windowed drivers.
@item 
GFX_SAFE@*
Special driver for when you want to reliably set a graphics mode and 
don't really care what resolution. See the set_gfx_mode() 
documentation for details.
@item 
GFX_PHOTON@*
Alias for GFX_PHOTON_ACCEL.
@item 
GFX_PHOTON_ACCEL@*
Fullscreen exclusive mode through Photon, running with hardware 
acceleration enabled.
@item 
GFX_PHOTON_SOFT@*
Fullscreen exclusive mode that only uses software drawing, rather than
any hardware accelerated features.
@item 
GFX_PHOTON_SAFE@*
Simplified fullscreen exclusive driver that doesn't support any
hardware acceleration, video or system bitmaps, etc.
@item 
GFX_PHOTON_WIN@*
The regular windowed Photon driver, running in color conversion mode 
when the color depth doesn't match that of the Photon desktop. Color 
conversion is much slower than direct drawing. Note that, mainly for
performance reasons, this driver requires the width of the screen to
be a multiple of 4.
@end itemize

@end ftable
See also:@*
@xref{set_gfx_mode}.@*
@node DIGI_*/QNX, MIDI_*/QNX, GFX_*/QNX, QNX
@subsection DIGI_*/QNX
@ftable @asis
@item @t{Drivers DIGI_*/QNX}
The QNX sound functions support the following digital sound cards:
@example

DIGI_AUTODETECT      - let Allegro pick a digital sound driver
DIGI_NONE            - no digital sound
DIGI_ALSA            - ALSA sound driver@end example


@end ftable
See also:@*
@xref{detect_digi_driver}.@*
@xref{install_sound}.@*
@xref{install_sound_input}.@*
@node MIDI_*/QNX, QNX integration routines, DIGI_*/QNX, QNX
@subsection MIDI_*/QNX
@ftable @asis
@item @t{Drivers MIDI_*/QNX}
The QNX sound functions support the following MIDI sound cards:
@example

MIDI_AUTODETECT      - let Allegro pick a MIDI sound driver
MIDI_NONE            - no MIDI sound
MIDI_ALSA            - ALSA RawMIDI driver
MIDI_DIGMID          - sample-based software wavetable player
@end example


@end ftable
See also:@*
@xref{detect_midi_driver}.@*
@xref{install_sound}.@*
@xref{install_sound_input}.@*
@node QNX integration routines, qnx_get_window, MIDI_*/QNX, QNX
@subsection QNX integration routines
@ftable @asis

@end ftable
The following functions provide a platform specific interface to seamlessly 
integrate Allegro into general purpose QNX programs. To use these routines, 
you must include qnxalleg.h after other Allegro headers.

@node qnx_get_window, GFX_*/MacOSX, QNX integration routines, QNX
@subsection qnx_get_window
@ftable @asis
@item @t{PtWidget_t qnx_get_window(void);}
Retrieves a handle to the window used by Allegro. Note that Allegro
uses an underlying window even though you don't set any graphics mode,
unless you have installed the neutral system driver (SYSTEM_NONE).



@end ftable
@node MacOS, Differences, QNX, Platform
@section MacOS X specifics

In terms of file redistribution, the MacOS X platform behaves practically the
same as the DOS platform. Read section chapter "Dos specifics" in the manual
to learn more about this.

Allegro programs under MacOS X are Cocoa applications; in order to hide all
the Cocoa interfacing to the end-user, you need to add the END_OF_MAIN()
macro right after your main() function. This is a necessary step: if you omit
it, your program will not compile.

The END_OF_MAIN() macro simply does some magic to make sure your program
executes another function before your main(); this function is defined into
the liballeg-main.a static library, which is automatically linked if you use
the allegro-config script when linking. Otherwise be sure you link against it
unless you want to get undefined symbol errors.

To behave nicely with the MacOS X user interface, Allegro apps will provide a
standard application menu with the "Quit" menu item in it. The default
behaviour when the user hits Command-Q or selects "Quit" is to do nothing.
To override this behaviour you must call the set_close_button_callback() function; under MacOS
X the supplied callback will be used either if the user clicks the window
close button either on Command-Q or "Quit" selection. In this last case the
application will not shutdown, but you are supposed to set some quit flag
in your callback and check for it on a regular basis in your main program
loop.

If you would like to use InterfaceBuilder to design a more
fully-featured menu, Allegro will automatically load it if you create
a bundle for your application. The use of InterfaceBuilder is beyond
the scope of this document. Briefly, you need to create a Nib, called
MainMenu.nib, containing a main menu and a controller. Then, when you
create the bundle, install MainMenu.nib into the Contents/Resources
subdirectory. Note that the actions attached to the menu items will be
called from a different thread than the one in which your Allegro code
is running. Therefore you should not do any work there (especially,
don't call Allegro functions.) Instead, set a variable, and test it in
your main loop.

@menu
* GFX_*/MacOSX::
* DIGI_*/MacOSX::
* MIDI_*/MacOSX::
@end menu
@node GFX_*/MacOSX, DIGI_*/MacOSX, qnx_get_window, MacOS
@subsection GFX_*/MacOSX
@ftable @asis
@item @t{Drivers GFX_*/MacOSX}
MacOS X Allegro supports the following card parameters for the
set_gfx_mode() function:

@itemize @bullet
@item 
GFX_TEXT@*
This closes any graphics mode previously opened with set_gfx_mode.
@item 
GFX_AUTODETECT@*
Let Allegro pick an appropriate graphics driver.
@item 
GFX_AUTODETECT_FULLSCREEN@*
Autodetects a graphics driver, but will only use fullscreen drivers,
failing if these are not available on current platform.
@item 
GFX_AUTODETECT_WINDOWED@*
Same as above, but uses only windowed drivers.
@item 
GFX_SAFE@*
Special driver for when you want to reliably set a graphics mode and 
don't really care what resolution. See the set_gfx_mode() 
documentation for details.
@item 
GFX_QUARTZ_FULLSCREEN@*
Fullscreen exclusive mode, using the CGDirectDisplay interface. 
Supports only resolutions higher or equal to 640x480, and uses 
hardware acceleration if available.
@item 
GFX_QUARTZ_WINDOW@*
Windowed mode using QuickDraw in a Cocoa window.
@end itemize

@end ftable
See also:@*
@xref{set_gfx_mode}.@*
@node DIGI_*/MacOSX, MIDI_*/MacOSX, GFX_*/MacOSX, MacOS
@subsection DIGI_*/MacOSX
@ftable @asis
@item @t{Drivers DIGI_*/MacOSX}
The MacOS X sound functions support the following digital sound cards:
@example

DIGI_AUTODETECT      - let Allegro pick a digital sound driver
DIGI_NONE            - no digital sound
DIGI_CORE_AUDIO      - CoreAudio digital output (OS >= X.2 required)
DIGI_SOUND_MANAGER   - Carbon Sound Manager digital output
@end example


@end ftable
See also:@*
@xref{detect_digi_driver}.@*
@xref{install_sound}.@*
@xref{install_sound_input}.@*
@node MIDI_*/MacOSX, ASSERT, DIGI_*/MacOSX, MacOS
@subsection MIDI_*/MacOSX
@ftable @asis
@item @t{Drivers MIDI_*/MacOSX}
The MacOS X sound functions support the following MIDI sound cards:
@example

MIDI_AUTODETECT      - let Allegro pick a MIDI sound driver
MIDI_NONE            - no MIDI sound
MIDI_CORE_AUDIO      - CoreAudio MIDI synthesizer (OS >= X.2 required)
MIDI_QUICKTIME       - QuickTime Music Note Allocator MIDI output
MIDI_DIGMID          - sample-based software wavetable player
@end example



@end ftable
See also:@*
@xref{detect_midi_driver}.@*
@xref{install_sound}.@*
@xref{install_sound_input}.@*
@node Differences, Miscellaneous, MacOS, Platform
@section Differences between platforms

Here's a quick summary of things that may cause problems when moving your 
code from one platform to another (you can find a more detailed version of 
this in the docs section of the Allegro website).

The Windows, Unix and MacOS X versions require you to write END_OF_MAIN() 
after your main() function. This is used to magically turn an ISO C style 
main() into a Windows style WinMain(), or by the Unix code to grab a copy
of your argv[] parameter, or by the MacOS X code to shell the user main() 
inside a Cocoa application.

On many platforms Allegro runs very slowly if you rely on it in order to 
automatically lock bitmaps when drawing onto them. For good performance, 
you need to call acquire_bitmap() and release_bitmap() yourself, and try 
to keep the amount of locking to a minimum.

The Windows version may lose the contents of video memory if the user 
switches away from your program, so you need to deal with that.

None of the currently supported platforms require input polling, but it is 
possible that some future ones might, so if you want to ensure 100% 
portability of your program, you should call poll_mouse() and 
poll_keyboard() in all the relevant places.

On Unix the shared files by Allegro (like `language.dat') may require a
special use due to the nature of distributing the resources in separate paths
instead of putting everything in the same directory. Check the beginning of
your platform's specific chapter to learn more about this.

Allegro defines a number of standard macros that can be used to check 
various attributes of the current platform:

ALLEGRO_PLATFORM_STR@*
Text string containing the name of the current platform.

ALLEGRO_DOS@*
ALLEGRO_DJGPP@*
ALLEGRO_WATCOM@*
ALLEGRO_WINDOWS@*
ALLEGRO_MSVC@*
ALLEGRO_MINGW32@*
ALLEGRO_BCC32@*
ALLEGRO_UNIX@*
ALLEGRO_LINUX@*
ALLEGRO_BEOS@*
ALLEGRO_QNX@*
ALLEGRO_DARWIN@*
ALLEGRO_MACOSX@*
ALLEGRO_GCC@*
Defined if you are building for a relevant system. Often several of these 
will apply, eg. DOS+Watcom, or Windows+GCC+MinGW.

Note that ALLEGRO_LINUX is a misnomer. It will only be defined if
Linux console support is enabled. It is not a reliable way to check
if the program is being built on a Linux system.

ALLEGRO_AMD64@*
ALLEGRO_I386@*
ALLEGRO_BIG_ENDIAN@*
ALLEGRO_LITTLE_ENDIAN@*
Defined if you are building for a processor of the relevant type.

ALLEGRO_MULTITHREADED@*
Defined if the library is internally multi-threaded on this system.

ALLEGRO_USE_CONSTRUCTOR@*
Defined if the compiler supports constructor/destructor functions.

ALLEGRO_VRAM_SINGLE_SURFACE@*
Defined if the screen is a single large surface that is then partitioned 
into multiple video sub-bitmaps (eg. DOS), rather than each video bitmap 
being a totally unique entity (eg. Windows).

ALLEGRO_CONSOLE_OK@*
Defined if when you are not in a graphics mode, there is a text mode 
console that you can printf() to, and from which the user could 
potentially redirect stdout to capture it even while you are in a 
graphics mode. If this define is absent, you are running in an 
environment like Windows that has no stdout at all.

ALLEGRO_MAGIC_MAIN@*
Defined if Allegro uses a magic main, i.e takes over the main() entry 
point and turns it into a secondary entry point suited to its needs.

ALLEGRO_LFN@*
Non-zero if long filenames are supported, or zero if you are limited to 
8.3 format (in the DJGPP version, this is a variable depending on the 
runtime environment).

LONG_LONG@*
Defined to whatever represents a 64-bit "long long" integer for the 
current compiler, or not defined if that isn't supported.

OTHER_PATH_SEPARATOR@*
Defined to a path separator character other than a forward slash for 
platforms that use one (eg. a backslash under DOS and Windows), or 
defined to a forward slash if there is no other separator character.

DEVICE_SEPARATOR@*
Defined to the filename device separator character (a colon for DOS and 
Windows), or to zero if there are no explicit devices in paths (Unix).

Allegro can be customized at compile time to a certain extent with the
following macros:

ALLEGRO_NO_MAGIC_MAIN@*
If you define this prior to including Allegro headers, Allegro won't
touch the main() entry point. This effectively removes the requirement
on a program to be linked against the Allegro library when it includes
the allegro.h header file. Note that the configuration and file routines
are not guaranteed to work on Unix systems when this symbol is defined.
Moreover, on Darwin/MacOS X systems, this symbol simply prevents the
program from being linked against the Allegro library! This highly non
portable feature is primarily intended to be used under Windows.

ALLEGRO_USE_CONSOLE@*
If you define this prior to including Allegro headers, Allegro will be 
set up for building a console application rather than the default GUI 
program on some platforms (especially Windows).

ALLEGRO_NO_STD_HEADER@*
If you define this prior to including Allegro headers, Allegro will not
automatically include some standard headers (eg <stddef.h>) its own
headers depend upon.

ALLEGRO_NO_KEY_DEFINES@*
If you define this prior to including Allegro headers, Allegro will omit
the definition of the KEY_* constants, which may clash with other headers.

ALLEGRO_NO_FIX_ALIASES@*
The fixed point functions used to be named with an "f" prefix instead of
"fix", eg. fixsqrt() used to be fsqrt(), but were renamed due to conflicts
with some libc implementations. So backwards compatibility aliases are
provided as static inline functions which map the old names to the new
names, eg. fsqrt() calls fixsqrt(). If you define this symbol prior to
including Allegro headers, the aliases will be turned off.

ALLEGRO_NO_FIX_CLASS@*
If you define this symbol prior to including Allegro headers in a C++
source file, the 'fix' class will not be made available. This mitigates
problems with the 'fix' class's overloading getting in the way.

ALLEGRO_NO_VHLINE_ALIAS@*
The `curses' API also defines functions called vline() and hline().
To avoid a linker conflict when both libraries are used, we have
internally renamed our functions and added inline function aliases which
remap vline() and hline(). This should not be noticeable to most users.

If you define ALLEGRO_NO_VHLINE_ALIAS prior to including Allegro headers,
Allegro will not define the vline() and hline() aliases, e.g. so you can
include curses.h and allegro.h in the same module.

ALLEGRO_NO_CLEAR_BITMAP_ALIAS@*
If you define this prior to including Allegro headers, Allegro will not
define the clear() backwards compatibility alias to clear_bitmap().

ALLEGRO_NO_COMPATIBILITY@*
If you define this prior to including Allegro headers, Allegro will not
include the backward compatibility layer. It is undefined by default so
old programs can still be compiled with the minimum amount of issues,
but you should define this symbol if you intend to maintain your code
up to date with the latest versions of Allegro. It automatically turns
off all backwards compatibility aliases.

Allegro also defines a number of standard macros that can be used to 
insulate you from some of the differences between systems:

INLINE@*
Use this in place of the regular "inline" function modifier keyword, and 
your code will work correctly on any of the supported compilers.

RET_VOLATILE@*
Use this to declare a function with a volatile return value.

ZERO_SIZE_ARRAY(type, name)@*
Use this to declare zero-sized arrays in terminal position inside 
structures, like in the BITMAP structure. These arrays are effectively 
equivalent to the flexible array members of ISO C99.

AL_CONST@*
Use this in place of the regular "const" object modifier keyword, and 
your code will work correctly on any of the supported compilers.

AL_RAND()@*
On platforms that require it, this macro does a simple shift 
transformation of the libc rand() function, in order to improve the 
perceived randomness of the output series in the lower 16 bits.
Where not required, it directly translates into a rand() call.



@node Miscellaneous, Reducing, Differences, Top
@chapter Miscellaneous
@menu
* Reducing::                Reducing your executable size
* Debugging::               Debugging
* Makefile::                Makefile targets
* Available::               Available Allegro examples
@end menu
@node Reducing, Debugging, Miscellaneous, Miscellaneous
@section Reducing your executable size

Some people complain that Allegro produces very large executables. This is 
certainly true: with the DJGPP version, a simple "hello world" program will 
be about 200k, although the per-executable overhead is much less for 
platforms that support dynamic linking. But don't worry, Allegro takes up a 
relatively fixed amount of space, and won't increase as your program gets 
larger. As George Foot so succinctly put it, anyone who is concerned about 
the ratio between library and program code should just get to work and write 
more program code to catch up :-)

Having said that, there are several things you can do to make your programs 
smaller:

@itemize @bullet
@item 
For all platforms, you can use an executable compressor called UPX, which
is available at http://upx.sourceforge.net/. This usually manages a
compression ratio of about 40%.
@item 
When using DJGPP: for starters, read the DJGPP FAQ section 8.14, and take
note of the -s switch. And don't forget to compile your program with
optimisation enabled!
@item 
If a DOS program is only going to run in a limited number of graphics modes, 
you can specify which graphics drivers you would like to include with the 
code:
@example

BEGIN_GFX_DRIVER_LIST
   driver1
   driver2
   etc...
END_GFX_DRIVER_LIST
@end example

where the driver names are any of the defines:
@example

GFX_DRIVER_VBEAF
GFX_DRIVER_VGA
GFX_DRIVER_MODEX
GFX_DRIVER_VESA3
GFX_DRIVER_VESA2L
GFX_DRIVER_VESA2B
GFX_DRIVER_XTENDED
GFX_DRIVER_VESA1
@end example

This construct must be included in only one of your C source files. The 
ordering of the names is important, because the autodetection routine works 
down from the top of the list until it finds the first driver that is able 
to support the requested mode. I suggest you stick to the default ordering 
given above, and simply delete whatever entries you aren't going to use.
@item 
If your DOS program doesn't need to use all the possible color depths, you 
can specify which pixel formats you want to support with the code:
@example

BEGIN_COLOR_DEPTH_LIST
   depth1
   depth2
   etc...
END_COLOR_DEPTH_LIST
@end example

where the color depth names are any of the defines:
@example

COLOR_DEPTH_8
COLOR_DEPTH_15
COLOR_DEPTH_16
COLOR_DEPTH_24
COLOR_DEPTH_32
@end example

Removing any of the color depths will save quite a bit of space, with the 
exception of the 15 and 16-bit modes: these share a great deal of code, so 
if you are including one of them, there is no reason not to use both. Be 
warned that if you try to use a color depth which isn't in this list, your 
program will crash horribly!
@item 
In the same way as the above, you can specify which DOS sound drivers you 
want to support with the code:
@example

BEGIN_DIGI_DRIVER_LIST
   driver1
   driver2
   etc...
END_DIGI_DRIVER_LIST
@end example

using the digital sound driver defines:
@example

DIGI_DRIVER_SOUNDSCAPE
DIGI_DRIVER_AUDIODRIVE
DIGI_DRIVER_WINSOUNDSYS
DIGI_DRIVER_SB
@end example

and for the MIDI music:
@example

BEGIN_MIDI_DRIVER_LIST
   driver1
   driver2
   etc...
END_MIDI_DRIVER_LIST
@end example

using the MIDI driver defines:
@example

MIDI_DRIVER_AWE32
MIDI_DRIVER_DIGMID
MIDI_DRIVER_ADLIB
MIDI_DRIVER_MPU
MIDI_DRIVER_SB_OUT
@end example

If you are going to use either of these sound driver constructs, you must 
include both.
@item 
Likewise for the DOS joystick drivers, you can declare an inclusion list:
@example

BEGIN_JOYSTICK_DRIVER_LIST
   driver1
   driver2
   etc...
END_JOYSTICK_DRIVER_LIST
@end example

using the joystick driver defines:
@example

JOYSTICK_DRIVER_WINGWARRIOR
JOYSTICK_DRIVER_SIDEWINDER
JOYSTICK_DRIVER_GAMEPAD_PRO
JOYSTICK_DRIVER_GRIP
JOYSTICK_DRIVER_STANDARD
JOYSTICK_DRIVER_SNESPAD
JOYSTICK_DRIVER_PSXPAD
JOYSTICK_DRIVER_N64PAD
JOYSTICK_DRIVER_DB9
JOYSTICK_DRIVER_TURBOGRAFX
JOYSTICK_DRIVER_IFSEGA_ISA
JOYSTICK_DRIVER_IFSEGA_PCI
JOYSTICK_DRIVER_IFSEGA_PCI_FAST
@end example

The standard driver includes support for the dual joysticks, increased 
numbers of buttons, Flightstick Pro, and Wingman Extreme, because these are 
all quite minor variations on the basic code.
@item 
If you are _really_ serious about this size, thing, have a look at the top 
of include/allegro/alconfig.h and you will see the lines:
@example

#define ALLEGRO_COLOR8
#define ALLEGRO_COLOR16
#define ALLEGRO_COLOR24
#define ALLEGRO_COLOR32
@end example

If you comment out any of these definitions and then rebuild the library, 
you will get a version without any support for the absent color depths, 
which will be even smaller than using the DECLARE_COLOR_DEPTH_LIST() macro. 
Removing the ALLEGRO_COLOR16 define will get rid of the support for both 15 
and 16-bit hicolor modes, since these share a lot of the same code.
@end itemize

Note: the aforementioned methods for removing unused hardware drivers only 
apply to statically linked versions of the library, eg. DOS. On Windows and 
Unix platforms, you can build Allegro as a DLL or shared library, which 
prevents these methods from working, but saves so much space that you 
probably won't care about that. Removing unused color depths from alconfig.h 
will work on any platform, though.

If you are distributing a copy of the setup program along with your game, 
you may be able to get a dramatic size reduction by merging the setup code 
into your main program, so that only one copy of the Allegro routines will 
need to be linked. See setup.txt for details. In the DJGPP version, after 
compressing the executable, this will probably save you about 200k compared 
to having two separate programs for the setup and the game itself.



@node Debugging, Makefile, Reducing, Miscellaneous
@section Debugging

There are three versions of the Allegro library: the normal optimised code, 
one with extra debugging support, and a profiling version. See the platform 
specific readme files for information about how to install and link with 
these alternative libs. Although you will obviously want to use the 
optimised library for the final version of your program, it can be very 
useful to link with the debug lib while you are working on it, because this 
will make debugging much easier, and includes assert tests that will help to 
locate errors in your code at an earlier stage. Allegro also contains some 
debugging helper functions:

@menu
* ASSERT::
* TRACE::
* register_assert_handler::
* register_trace_handler::
* al_assert::
* al_trace::
@end menu
@node ASSERT, TRACE, MIDI_*/MacOSX, Debugging
@subsection ASSERT
@ftable @asis
@item @t{void ASSERT(condition);}
Debugging helper macro. Normally compiles away to nothing, but if you 
defined the preprocessor symbol DEBUGMODE before including Allegro headers,
it will check the supplied condition and call al_assert() if it fails,
whose default action is to stop the program and report the assert. You can
use this macro even when Allegro has not been initialised. Example:
@example

#define DEBUGMODE
#include 
...
void my_blitter(BITMAP *source, int flags)
@{
   int some_variables;
   ASSERT(source != NULL);
   ASSERT(flags & GAME_RUNNING);
   ...
@}@end example


@end ftable
See also:@*
@xref{al_assert}.@*
@xref{TRACE}.@*
@xref{register_assert_handler}.@*
@xref{expackf}.@*
@node TRACE, register_assert_handler, ASSERT, Debugging
@subsection TRACE
@ftable @asis
@item @t{void TRACE(char *msg, ...);}
Debugging helper macro. Normally compiles away to nothing, but if you 
defined the preprocessor symbol DEBUGMODE before including Allegro headers,
it passes the supplied message given in ASCII format to al_trace().
Example:
@example

#define DEBUGMODE
#include 
...
void my_blitter(BITMAP *source, int flags)
@{
   static int count_call = 0;
   TRACE("my_blitter() called %d times.\n", count_call++);
   ...
@}@end example


@end ftable
See also:@*
@xref{al_trace}.@*
@xref{ASSERT}.@*
@xref{register_trace_handler}.@*
@node register_assert_handler, register_trace_handler, TRACE, Debugging
@subsection register_assert_handler
@ftable @asis
@item @t{void register_assert_handler(int (*handler)(const char *msg));}
Supplies a custom handler function for dealing with assert failures. Your 
callback will be passed a formatted error message in ASCII, and should 
return non-zero if it has processed the error, or zero to continue with 
the default actions. You could use this to ignore assert failures, or to 
display the error messages on a graphics mode screen without aborting the 
program. You can call this function even when Allegro has not been
initialised. Example:
@example

int show_but_continue(const char *text)
@{
    alert("Uh oh...", "Fasten your seat belts.", text,
          "&Go on!", NULL, 'g', 0);
    return 1;
@}
...
   register_assert(show_but_continue);
   ASSERT(0); /* This won't crash the program now. */@end example


@end ftable
See also:@*
@xref{al_assert}.@*
@xref{ASSERT}.@*
@xref{register_trace_handler}.@*
@node register_trace_handler, al_assert, register_assert_handler, Debugging
@subsection register_trace_handler
@ftable @asis
@item @t{void register_trace_handler(int (*handler)(const char *msg));}
Supplies a custom handler function for dealing with trace output. Your 
callback will be passed a formatted error message in ASCII, and should 
return non-zero if it has processed the message, or zero to continue with 
the default actions. You could use this to ignore trace output, or to 
display the messages on a second monochrome monitor, etc. You can call
this function even when Allegro has not been initialised. Example:
@example

int network_broadcaster(const char *text)
@{
   int f;

   for (int f = 0; f 
      send_msg_to_client(client[f], text);
      
   return 0; /* Let normal tracing occur. */
@}
...
   register_trace_handler(network_broadcaster);
   TRACE("Networked tracing activated\n");@end example


@end ftable
See also:@*
@xref{al_trace}.@*
@xref{TRACE}.@*
@xref{register_assert_handler}.@*
@node al_assert, al_trace, register_trace_handler, Debugging
@subsection al_assert
@ftable @asis
@item @t{void al_assert(const char *file, int line);}
Raises an assert for an error at the specified file and line number. The 
file parameter is always given in ASCII format. By default, this will call
the system driver's assert handler. If there is none, the error will be
sent to stderr and the program will abort. However, if the environment
variable ALLEGRO_ASSERT is set, this function writes a message into the
file specified by the environment variable and program execution will
continue. If none of this behaviours is wanted, you can override them with
a custom assert handler.

You will usually want to use the ASSERT() macro instead of calling this
function directly.

@end ftable
See also:@*
@xref{ASSERT}.@*
@xref{al_trace}.@*
@xref{register_assert_handler}.@*
@node al_trace, exhello, al_assert, Debugging
@subsection al_trace
@ftable @asis
@item @t{void al_trace(const char *msg, ...);}
Outputs a debugging trace message, using a printf() format string given 
in ASCII. If you have installed a custom trace handler it uses that, or 
if the environment variable ALLEGRO_TRACE is set it writes into the file 
specified by the environment, otherwise it writes the message to 
"allegro.log" in the current directory. You will usually want to use the 
TRACE() macro instead of calling this function directly.



@end ftable
See also:@*
@xref{TRACE}.@*
@xref{al_assert}.@*
@xref{register_trace_handler}.@*
@node Makefile, Available, Debugging, Miscellaneous
@section Makefile targets

There are a number of options that you can use to control exactly how 
Allegro will be compiled. On Unix platforms, you do this by passing arguments 
to the configure script (run "configure --help" for a list), but on other 
platforms you can set the following environment variables:

@itemize @bullet
@item 
DEBUGMODE=1@*
Selects a debug build, rather than the normal optimised version.
@item 
DEBUGMODE=2@*
Selects a build intended to debug Allegro itself, rather than the
normal optimised version.
@item 
PROFILEMODE=1@*
Selects a profiling build, rather than the normal optimised version.
@item 
WARNMODE=1@*
Selects strict compiler warnings. If you are planning to work on Allegro 
yourself, rather than just using it in your programs, you should be sure 
to have this mode enabled.
@item 
STATICLINK=1 (MinGW, MSVC, BeOS, MacOS X only)@*
Link as a static library, rather than the default dynamic library.
@item 
STATICRUNTIME=1 (MSVC only)@*
Link against static runtime libraries, rather than the default dynamic
runtime libraries.
@item 
TARGET_ARCH_COMPAT=[cpu] (GCC-based platforms only)@*
This option will optimize for the given processor while maintaining
compatibility with older processors.
Example: set TARGET_ARCH_COMPAT=i586
@item 
TARGET_ARCH_EXCL=[cpu] (GCC-based platforms only)@*
This option will optimize for the given processor. Please note that
using it will cause the code to *NOT* run on older processors.
Example: set TARGET_ARCH_EXCL=i586
@item 
TARGET_OPTS=[opts] (GCC-based platforms only)@*
This option allows you to customize general compiler optimisations.
@item 
TARGET_ARCH_EXCL=[opts] (MSVC only)@*
This option allows you to optimize exclusively for a given architecture.
Pass B to optimize for a PentiumPro or 7 to optimize for Pentium 4. Note
that the options you can pass may be different between MSVC 6 and 7.
Example: set TARGET_ARCH_EXCL=7
@item 
CROSSCOMPILE=1 (DJGPP, MinGW only)@*
Allows you to build the library under Linux by using a cross-compiler.
@item 
ALLEGRO_USE_C=1 (GCC-based platforms only)@*
Allows you to build the library using C drawing code instead of the usual
asm routines. This is only really useful for testing, since the asm
version is faster.
@item 
UNIX_TOOLS=1@*
Instructs the build process to use Unix-like tools instead of DOS tools.
Note that you usually don't need to set it because the build process will
try to autodetect this configuration.
@item 
COMPILER_MSVC7=1 (MSVC only)@*
Enables special optimizations for MSVC 7 (the default is MSVC 6). You don't
normally need to set this flag since fix.bat msvc7 should do the same
thing and is the preferred way of doing this.
@item 
COMPILER_ICL=1 (MSVC only)@*
Instructs the build process to use the Intel command line compiler icl rather
than Microsoft's command line compiler cl. You don't normally need to pass 
this flag since fix.bat icl should do the same thing and is the 
preferred way of doing this. Do not try COMPILER_MSVC7=1 and COMPILER_ICL=1
at the same time.
@end itemize

If you only want to recompile a specific test program or utility, you can 
specify it as an argument to make, eg. "make demo" or "make grabber". The 
makefiles also provide some special pseudo-targets:

@itemize @bullet
@item 
'info' (Unix only)@*
Tells you which options this particular build of Allegro will use.
Especially useful to verify that the required libraries were detected
and you won't get a 'half-featured' Allegro.
@item 
'default'@*
The normal build process. Compiles the current library version (one of 
optimised, debugging, or profiling, selected by the above environment 
variables), builds the test and example programs, and converts the 
documentation files.
@item 
'all' (non-Unix only)@*
Compiles all three library versions (optimised, debugging, and 
profiling), builds the test and example programs, and converts the 
documentation files.
@item 
'lib'@*
Compiles the current library version (one of optimised, debugging, or 
profiling, selected by the above environment variables).
@item 
'modules' (Unix only)@*
This will compile all the modules currently configured. The 'lib' and
'modules' targets together are needed to build a working copy of the
library, without documentation or programs.
@item 
'install'@*
Copies the current library version (one of optimised, debugging, or 
profiling, selected by the above environment variables), into your 
compiler lib directory, recompiling it as required, and installs the 
Allegro headers.
@item 
'install-lib' (Unix only)@*
You can use this to install the library and the modules only, without
documentation or programs.  Use the 'install' target to install
everything.
@item 
'installall' (non-Unix only)@*
Copies all three library versions (optimised, debugging, and profiling), 
into your compiler lib directory, recompiling them as required, and 
installs the Allegro headers.
@item 
'uninstall'@*
Removes the Allegro library and headers from your compiler directories. 
@item 
'docs'@*
Converts the documentation files from the ._tx sources.
@item 
'chm-docs' (Windows only)@*
Creates a compiled HTML file from the previously generated html output.
This is not a default target, since you need Microsoft's HTML compiler
(http://go.microsoft.com/fwlink/?LinkId=14188),
and it has to be installed somewhere in your PATH. Also, this only works
if you use '@@multiplefiles' (see the top of docs/src/allegro._tx).
@item 
'docs-dvi' (Unix only)@*
Creates the allegro.dvi device independent documentation file. This is
not a default target, since you need the texi2dvi tool to create it. The
generated file is especially prepared to be printed on paper.
@item 
'docs-ps' or 'docs-gzipped-ps' or 'docs-bzipped-ps' (Unix only)@*
Creates a PostScript file from the previously generated DVI file. This is
not a default target, since you need the texi2dvi and dvips tools to
create it. The second and third targets compress the generated Postscript
file. The generated file is especially prepared to be printed on paper.
@item 
'docs-pdf' (Unix only)@*
Creates a PDF file. This is not a default target, since you need the
texi2pdf tool to create it. The generated file is especially prepared to
be printed on paper, and it also has hyperlinks.
@item 
'docs-devhelp' (Unix only)@*
Creates normal HTML documentation with an additional xml index file which
can be used by tools like Devhelp (http://www.devhelp.net/) to
show context sensitive help within any editor using Devhelp, like for
example http://anjuta.sourceforge.net/. The Allegro 'book' will be
created in `docs/devhelp/allegro.devhelp', you have to install it
manually.
@item 
'install-man' (Unix and Mac OS X only)@*
Generates Unix man pages for each Allegro function or variable and
installs them.
@item 
'install-gzipped-man' or 'install-bzipped-man' (Unix only)@*
Like install-man, but also compresses the manual pages after installing
them (run only one of these).
@item 
'uninstall-man' (Unix)@*
Uninstalls any man pages previously installed with 'install-man',
'install-gzipped-man', or 'install-bzipped-man'.
@item 
'install-info' or 'install-gzipped-info' or 'install-bzipped-info'
(Unix only)@*
Converts the documentation to Info format and installs it. The second
and third targets compress the info file after installing it (run only
one of them).
@item 
'uninstall-info' (Unix only)@*
Uninstalls any man pages previously installed with 'install-info',
'install-gzipped-info', or 'install-bzipped-info'.
@item 
'clean'@*
Removes generated object and library files, either to recover disk space 
or to force a complete rebuild the next time you run make. This target is 
designed so that if you run a "make install" followed by "make clean", 
you will still have a functional version of Allegro.
@item 
'distclean'@*
Like "make clean", but more so. This removes all the executable files and 
the documentation, leaving you with only the same files that are included
when you unzip a new Allegro distribution.
@item 
'veryclean'@*
Use with extreme caution! This target deletes absolutely all generated 
files, including some that may be non-trivial to recreate. After you run 
"make veryclean", a simple rebuild will not work: at the very least you 
will have to run "make depend", and perhaps also fixdll.bat if you are 
using the Windows library. These targets make use of non-standard tools 
like SED, so unless you know what you are doing and have all this stuff 
installed, you should not use them.
@item 
'compress' (DJGPP, MinGW and MSVC only)@*
Uses the DJP or UPX executable compressors (whichever you have installed) 
to compress the example executables and utility programs, which can 
recover a significant amount of disk space.
@item 
'depend'@*
Regenerates the dependency files (obj/*/makefile.dep). You need to run 
this after "make veryclean", or whenever you add new headers to the 
Allegro sources.
@end itemize




@node Available, Tools, Makefile, Miscellaneous
@section Available Allegro examples

With Allegro comes quite a bunch of examples, which go from the simple
introductory `Hello world' to more complicated programs featuring truecolor
blending effects. This chapter describes these examples which you can find
in the allegro/examples folder. You don't have to go through them in the same
order as this documentation, but doing so you will learn the basic functions
and avoid missing any important bit of information.

@menu
* exhello::
* exmem::
* expal::
* expat::
* exflame::
* exdbuf::
* exflip::
* exfixed::
* exfont::
* exmouse::
* extimer::
* exkeys::
* exjoy::
* exsample::
* exmidi::
* exgui::
* excustom::
* exunicod::
* exbitmap::
* exscale::
* exconfig::
* exdata::
* exsprite::
* exexedat::
* extrans::
* extruec::
* excolmap::
* exrgbhsv::
* exshade::
* exblend::
* exxfade::
* exalpha::
* exlights::
* ex3d::
* excamera::
* exquat::
* exstars::
* exscn3d::
* exzbuf::
* exscroll::
* ex3buf::
* ex12bit::
* exaccel::
* exspline::
* exsyscur::
* exupdate::
* exswitch::
* exstream::
* expackf::
@end menu
@node exhello, exmem, al_trace, Available
@subsection exhello
@ftable @asis
@item @t{Example exhello}
This is a very simple program showing how to get into graphics
mode and draw text onto the screen.

@end ftable
See also:@*
@xref{END_OF_MAIN}.@*
@xref{SCREEN_W, SCREEN_H}.@*
@xref{SCREEN_W}.@*
@xref{acquire_screen}.@*
@xref{allegro_error}.@*
@xref{allegro_init}.@*
@xref{allegro_message}.@*
@xref{clear_to_color}.@*
@xref{desktop_palette}.@*
@xref{font}.@*
@xref{install_keyboard}.@*
@xref{key}.@*
@xref{makecol}.@*
@xref{readkey}.@*
@xref{release_screen}.@*
@xref{screen}.@*
@xref{set_gfx_mode}.@*
@xref{set_palette}.@*
@xref{textout_centre_ex}.@*
@node exmem, expal, exhello, Available
@subsection exmem
@ftable @asis
@item @t{Example exmem}
This program demonstrates the use of memory bitmaps. It creates
a small temporary bitmap in memory, draws some circles onto it,
and then blits lots of copies of it onto the screen.

@end ftable
See also:@*
@xref{BITMAP}.@*
@xref{END_OF_MAIN}.@*
@xref{SCREEN_W, SCREEN_H}.@*
@xref{SCREEN_W}.@*
@xref{acquire_screen}.@*
@xref{allegro_error}.@*
@xref{allegro_init}.@*
@xref{allegro_message}.@*
@xref{blit}.@*
@xref{circle}.@*
@xref{clear_bitmap}.@*
@xref{create_bitmap}.@*
@xref{desktop_palette}.@*
@xref{destroy_bitmap}.@*
@xref{install_keyboard}.@*
@xref{palette_color}.@*
@xref{readkey}.@*
@xref{release_screen}.@*
@xref{screen}.@*
@xref{set_gfx_mode}.@*
@xref{set_palette}.@*
@node expal, expat, exmem, Available
@subsection expal
@ftable @asis
@item @t{Example expal}
This program demonstrates how to manipulate the palette. It draws
a set of concentric circles onto the screen and animates them by
cycling the palette.

@end ftable
See also:@*
@xref{END_OF_MAIN}.@*
@xref{PALETTE}.@*
@xref{RGB}.@*
@xref{SCREEN_W, SCREEN_H}.@*
@xref{SCREEN_W}.@*
@xref{acquire_screen}.@*
@xref{allegro_error}.@*
@xref{allegro_init}.@*
@xref{allegro_message}.@*
@xref{black_palette}.@*
@xref{circlefill}.@*
@xref{install_keyboard}.@*
@xref{install_mouse}.@*
@xref{keypressed}.@*
@xref{release_screen}.@*
@xref{screen}.@*
@xref{set_gfx_mode}.@*
@xref{set_palette}.@*
@xref{show_mouse}.@*
@node expat, exflame, expal, Available
@subsection expat
@ftable @asis
@item @t{Example expat}
This program demonstrates the use of patterned drawing and sub-bitmaps.

@end ftable
See also:@*
@xref{BITMAP}.@*
@xref{END_OF_MAIN}.@*
@xref{acquire_bitmap}.@*
@xref{allegro_error}.@*
@xref{allegro_init}.@*
@xref{allegro_message}.@*
@xref{bitmap_mask_color}.@*
@xref{blit}.@*
@xref{clear_to_color}.@*
@xref{create_bitmap}.@*
@xref{create_sub_bitmap}.@*
@xref{desktop_palette}.@*
@xref{destroy_bitmap}.@*
@xref{drawing_mode}.@*
@xref{font}.@*
@xref{install_keyboard}.@*
@xref{makecol}.@*
@xref{masked_blit}.@*
@xref{palette_color}.@*
@xref{readkey}.@*
@xref{rectfill}.@*
@xref{release_bitmap}.@*
@xref{screen}.@*
@xref{set_gfx_mode}.@*
@xref{set_palette}.@*
@xref{solid_mode}.@*
@xref{text_height}.@*
@xref{text_length}.@*
@xref{textout_ex}.@*
@node exflame, exdbuf, expat, Available
@subsection exflame
@ftable @asis
@item @t{Example exflame}
This program demonstrates how to write directly to video memory.
It implements a simple fire effect, first by calling getpixel() and
putpixel(), then by accessing video memory directly a byte at a
time, and finally using block memory copy operations.

@end ftable
See also:@*
@xref{END_OF_MAIN}.@*
@xref{PALETTE}.@*
@xref{SCREEN_W, SCREEN_H}.@*
@xref{SCREEN_W}.@*
@xref{acquire_screen}.@*
@xref{allegro_error}.@*
@xref{allegro_init}.@*
@xref{allegro_message}.@*
@xref{bmp_read_line}.@*
@xref{bmp_unwrite_line}.@*
@xref{bmp_write_line}.@*
@xref{clear_keybuf}.@*
@xref{font}.@*
@xref{getpixel}.@*
@xref{install_keyboard}.@*
@xref{keypressed}.@*
@xref{line}.@*
@xref{makecol}.@*
@xref{putpixel}.@*
@xref{release_screen}.@*
@xref{screen}.@*
@xref{set_gfx_mode}.@*
@xref{set_palette}.@*
@xref{textout_ex}.@*
@node exdbuf, exflip, exflame, Available
@subsection exdbuf
@ftable @asis
@item @t{Example exdbuf}
This program demonstrates the use of double buffering.
It moves a circle across the screen, first just erasing and
redrawing directly to the screen, then with a double buffer.

@end ftable
See also:@*
@xref{BITMAP}.@*
@xref{END_OF_MAIN}.@*
@xref{SCREEN_W, SCREEN_H}.@*
@xref{SCREEN_W}.@*
@xref{acquire_screen}.@*
@xref{allegro_error}.@*
@xref{allegro_init}.@*
@xref{allegro_message}.@*
@xref{blit}.@*
@xref{circlefill}.@*
@xref{clear_keybuf}.@*
@xref{clear_to_color}.@*
@xref{create_bitmap}.@*
@xref{desktop_palette}.@*
@xref{destroy_bitmap}.@*
@xref{font}.@*
@xref{install_keyboard}.@*
@xref{install_timer}.@*
@xref{keypressed}.@*
@xref{makecol}.@*
@xref{release_screen}.@*
@xref{retrace_count}.@*
@xref{screen}.@*
@xref{set_gfx_mode}.@*
@xref{set_palette}.@*
@xref{textprintf_ex}.@*
@node exflip, exfixed, exdbuf, Available
@subsection exflip
@ftable @asis
@item @t{Example exflip}
This program moves a circle across the screen, first with a
double buffer and then using page flips.

@end ftable
See also:@*
@xref{BITMAP}.@*
@xref{END_OF_MAIN}.@*
@xref{SCREEN_W, SCREEN_H}.@*
@xref{SCREEN_W}.@*
@xref{allegro_error}.@*
@xref{allegro_init}.@*
@xref{allegro_message}.@*
@xref{blit}.@*
@xref{circlefill}.@*
@xref{clear_keybuf}.@*
@xref{clear_to_color}.@*
@xref{create_bitmap}.@*
@xref{create_video_bitmap}.@*
@xref{desktop_palette}.@*
@xref{destroy_bitmap}.@*
@xref{font}.@*
@xref{install_keyboard}.@*
@xref{install_timer}.@*
@xref{keypressed}.@*
@xref{makecol}.@*
@xref{retrace_count}.@*
@xref{screen}.@*
@xref{set_gfx_mode}.@*
@xref{set_palette}.@*
@xref{show_video_bitmap}.@*
@xref{textprintf_ex}.@*
@node exfixed, exfont, exflip, Available
@subsection exfixed
@ftable @asis
@item @t{Example exfixed}
This program demonstrates how to use fixed point numbers, which
are signed 32-bit integers storing the integer part in the
upper 16 bits and the decimal part in the 16 lower bits. This
example also uses the unusual approach of communicating with
the user exclusively via the allegro_message() function.

@end ftable
See also:@*
@xref{END_OF_MAIN}.@*
@xref{allegro_init}.@*
@xref{allegro_message}.@*
@xref{fixdiv}.@*
@xref{fixed}.@*
@xref{fixmul}.@*
@xref{fixsqrt}.@*
@xref{fixtof}.@*
@xref{ftofix}.@*
@xref{itofix}.@*
@node exfont, exmouse, exfixed, Available
@subsection exfont
@ftable @asis
@item @t{Example exfont}
This is a very simple program showing how to load and manipulate fonts.

@end ftable
See also:@*
@xref{END_OF_MAIN}.@*
@xref{FONT}.@*
@xref{SCREEN_W, SCREEN_H}.@*
@xref{SCREEN_W}.@*
@xref{acquire_screen}.@*
@xref{allegro_error}.@*
@xref{allegro_init}.@*
@xref{allegro_message}.@*
@xref{clear_to_color}.@*
@xref{desktop_palette}.@*
@xref{destroy_font}.@*
@xref{extract_font_range}.@*
@xref{font}.@*
@xref{install_keyboard}.@*
@xref{key}.@*
@xref{load_font}.@*
@xref{makecol}.@*
@xref{merge_fonts}.@*
@xref{readkey}.@*
@xref{release_screen}.@*
@xref{screen}.@*
@xref{set_gfx_mode}.@*
@xref{set_palette}.@*
@xref{textout_centre_ex}.@*
@node exmouse, extimer, exfont, Available
@subsection exmouse
@ftable @asis
@item @t{Example exmouse}
This program demonstrates how to get mouse input. The
first part of the test retrieves the raw mouse input data
and displays it on the screen without using any mouse
cursor. When you press a key the standard arrow-like mouse
cursor appears.  You are not restricted to this shape,
and a second key press modifies the cursor to be several
concentric colored circles. They are not joined together,
so you can still see bits of what's behind when you move the
cursor over the printed text message.

@end ftable
See also:@*
@xref{BITMAP}.@*
@xref{END_OF_MAIN}.@*
@xref{SCREEN_W, SCREEN_H}.@*
@xref{SCREEN_W}.@*
@xref{acquire_screen}.@*
@xref{allegro_error}.@*
@xref{allegro_init}.@*
@xref{allegro_message}.@*
@xref{bitmap_mask_color}.@*
@xref{circle}.@*
@xref{clear_keybuf}.@*
@xref{clear_to_color}.@*
@xref{create_bitmap}.@*
@xref{desktop_palette}.@*
@xref{destroy_bitmap}.@*
@xref{font}.@*
@xref{get_mouse_mickeys}.@*
@xref{install_keyboard}.@*
@xref{install_mouse}.@*
@xref{install_timer}.@*
@xref{key}.@*
@xref{keypressed}.@*
@xref{makecol}.@*
@xref{mouse_x, mouse_b}.@*
@xref{mouse_x, mouse_w}.@*
@xref{mouse_x}.@*
@xref{mouse_x, mouse_y}.@*
@xref{mouse_x, mouse_z}.@*
@xref{palette_color}.@*
@xref{poll_mouse}.@*
@xref{readkey}.@*
@xref{release_screen}.@*
@xref{screen}.@*
@xref{set_gfx_mode}.@*
@xref{set_mouse_sprite}.@*
@xref{set_mouse_sprite_focus}.@*
@xref{set_palette}.@*
@xref{show_mouse}.@*
@xref{textout_centre_ex}.@*
@xref{textout_ex}.@*
@xref{textprintf_centre_ex}.@*
@xref{textprintf_ex}.@*
@xref{textprintf_right_ex}.@*
@xref{vsync}.@*
@node extimer, exkeys, exmouse, Available
@subsection extimer
@ftable @asis
@item @t{Example extimer}
This program demonstrates how to use the timer routines.
These can be a bit of a pain, because you have to be sure
you lock all the memory that is used inside your interrupt
handlers.  The first part of the example shows a basic use of
timing using the blocking function rest(). The second part
shows how to use three timers with different frequencies in
a non blocking way.

@end ftable
See also:@*
@xref{END_OF_FUNCTION}.@*
@xref{END_OF_MAIN}.@*
@xref{LOCK_FUNCTION}.@*
@xref{LOCK_VARIABLE}.@*
@xref{SCREEN_W}.@*
@xref{allegro_error}.@*
@xref{allegro_init}.@*
@xref{allegro_message}.@*
@xref{clear_to_color}.@*
@xref{desktop_palette}.@*
@xref{font}.@*
@xref{install_int}.@*
@xref{install_int_ex}.@*
@xref{install_keyboard}.@*
@xref{install_timer}.@*
@xref{key}.@*
@xref{keypressed}.@*
@xref{makecol}.@*
@xref{readkey}.@*
@xref{rest}.@*
@xref{screen}.@*
@xref{set_gfx_mode}.@*
@xref{set_palette}.@*
@xref{textprintf_centre_ex}.@*
@node exkeys, exjoy, extimer, Available
@subsection exkeys
@ftable @asis
@item @t{Example exkeys}
This program demonstrates how to access the keyboard. The
first part shows the basic use of readkey(). The second part
shows how to extract the ASCII value. Next come the scan codes.
The fourth test detects modifier keys like alt or shift. The
fifth test requires some focus to be passed. The final step
shows how to use the global key array to read simultaneous
key presses.
The last method to detect key presses are keyboard callbacks.
This is demonstrated by by installing a keyboard callback,
which marks all pressed keys by drawing to a grid.

@end ftable
See also:@*
@xref{END_OF_FUNCTION}.@*
@xref{END_OF_MAIN}.@*
@xref{LOCK_FUNCTION}.@*
@xref{SCREEN_W, SCREEN_H}.@*
@xref{SCREEN_W}.@*
@xref{acquire_screen}.@*
@xref{allegro_error}.@*
@xref{allegro_init}.@*
@xref{allegro_message}.@*
@xref{blit}.@*
@xref{clear_keybuf}.@*
@xref{clear_to_color}.@*
@xref{desktop_palette}.@*
@xref{font}.@*
@xref{install_keyboard}.@*
@xref{install_timer}.@*
@xref{key}.@*
@xref{key_shifts}.@*
@xref{keyboard_lowlevel_callback}.@*
@xref{keypressed}.@*
@xref{makecol}.@*
@xref{readkey}.@*
@xref{rectfill}.@*
@xref{release_screen}.@*
@xref{rest}.@*
@xref{scancode_to_name}.@*
@xref{screen}.@*
@xref{set_gfx_mode}.@*
@xref{set_palette}.@*
@xref{textprintf_centre_ex}.@*
@xref{textprintf_ex}.@*
@xref{ureadkey}.@*
@xref{usprintf}.@*
@xref{ustrzncpy}.@*
@node exjoy, exsample, exkeys, Available
@subsection exjoy
@ftable @asis
@item @t{Example exjoy}
This program uses the Allegro library to detect and read the value
of a joystick. The output of the program is a small target sight
on the screen which you can move. At the same time the program will
tell you what you are doing with the joystick (moving or firing).

@end ftable
See also:@*
@xref{BITMAP}.@*
@xref{END_OF_MAIN}.@*
@xref{SCREEN_W, SCREEN_H}.@*
@xref{SCREEN_W}.@*
@xref{allegro_error}.@*
@xref{allegro_init}.@*
@xref{allegro_message}.@*
@xref{blit}.@*
@xref{calibrate_joystick}.@*
@xref{calibrate_joystick_name}.@*
@xref{circle}.@*
@xref{clear_bitmap}.@*
@xref{clear_keybuf}.@*
@xref{create_bitmap}.@*
@xref{default_palette}.@*
@xref{destroy_bitmap}.@*
@xref{drawing_mode}.@*
@xref{font}.@*
@xref{install_joystick}.@*
@xref{install_keyboard}.@*
@xref{joy}.@*
@xref{key}.@*
@xref{keypressed}.@*
@xref{num_joysticks}.@*
@xref{palette_color}.@*
@xref{poll_joystick}.@*
@xref{putpixel}.@*
@xref{readkey}.@*
@xref{screen}.@*
@xref{set_gfx_mode}.@*
@xref{set_palette}.@*
@xref{textout_centre_ex}.@*
@xref{textprintf_centre_ex}.@*
@xref{textprintf_ex}.@*
@node exsample, exmidi, exjoy, Available
@subsection exsample
@ftable @asis
@item @t{Example exsample}
This program demonstrates how to play samples. You have to
use this example from the command line to specify as first
parameter a WAV or VOC sound file to play. If the file is
loaded successfully, the sound will be played in an infinite
loop. While it is being played, you can use the left and right
arrow keys to modify the panning of the sound. You can also
use the up and down arrow keys to modify the pitch.

@end ftable
See also:@*
@xref{END_OF_MAIN}.@*
@xref{SAMPLE}.@*
@xref{SCREEN_W, SCREEN_H}.@*
@xref{SCREEN_W}.@*
@xref{adjust_sample}.@*
@xref{allegro_error}.@*
@xref{allegro_init}.@*
@xref{allegro_message}.@*
@xref{clear_to_color}.@*
@xref{desktop_palette}.@*
@xref{destroy_sample}.@*
@xref{font}.@*
@xref{install_keyboard}.@*
@xref{install_sound}.@*
@xref{install_timer}.@*
@xref{key}.@*
@xref{load_sample}.@*
@xref{makecol}.@*
@xref{play_sample}.@*
@xref{poll_keyboard}.@*
@xref{rest}.@*
@xref{screen}.@*
@xref{set_gfx_mode}.@*
@xref{set_palette}.@*
@xref{textprintf_centre_ex}.@*
@node exmidi, exgui, exsample, Available
@subsection exmidi
@ftable @asis
@item @t{Example exmidi}
This program demonstrates how to play MIDI files.

@end ftable
See also:@*
@xref{END_OF_MAIN}.@*
@xref{MIDI}.@*
@xref{SCREEN_W, SCREEN_H}.@*
@xref{SCREEN_W}.@*
@xref{allegro_error}.@*
@xref{allegro_init}.@*
@xref{allegro_message}.@*
@xref{clear_to_color}.@*
@xref{desktop_palette}.@*
@xref{destroy_midi}.@*
@xref{font}.@*
@xref{get_filename}.@*
@xref{get_midi_length}.@*
@xref{install_keyboard}.@*
@xref{install_sound}.@*
@xref{install_timer}.@*
@xref{key}.@*
@xref{keypressed}.@*
@xref{load_midi}.@*
@xref{makecol}.@*
@xref{midi_pause}.@*
@xref{midi_pos}.@*
@xref{midi_resume}.@*
@xref{midi_time}.@*
@xref{play_midi}.@*
@xref{readkey}.@*
@xref{rectfill}.@*
@xref{rest}.@*
@xref{screen}.@*
@xref{set_display_switch_mode}.@*
@xref{set_gfx_mode}.@*
@xref{set_palette}.@*
@xref{text_height}.@*
@xref{text_length}.@*
@xref{textprintf_centre_ex}.@*
@node exgui, excustom, exmidi, Available
@subsection exgui
@ftable @asis
@item @t{Example exgui}
This program demonstrates how to use the GUI routines. From
the simple dialog controls that display a text or a bitmap to
more complex multiple choice selection lists, Allegro provides
a framework which can be customised to suit your needs.

@end ftable
See also:@*
@xref{DATAFILE}.@*
@xref{DIALOG}.@*
@xref{END_OF_MAIN}.@*
@xref{MENU}.@*
@xref{active_menu}.@*
@xref{alert}.@*
@xref{allegro_error}.@*
@xref{allegro_init}.@*
@xref{allegro_message}.@*
@xref{d_bitmap_proc}.@*
@xref{d_box_proc}.@*
@xref{d_button_proc}.@*
@xref{d_check_proc}.@*
@xref{d_clear_proc}.@*
@xref{d_text_proc, d_ctext_proc}.@*
@xref{d_edit_proc}.@*
@xref{d_icon_proc}.@*
@xref{d_keyboard_proc}.@*
@xref{d_list_proc}.@*
@xref{d_menu_proc}.@*
@xref{d_radio_proc}.@*
@xref{d_text_proc, d_rtext_proc}.@*
@xref{d_box_proc, d_shadow_box_proc}.@*
@xref{d_slider_proc}.@*
@xref{d_text_list_proc}.@*
@xref{d_text_proc}.@*
@xref{d_textbox_proc}.@*
@xref{d_yield_proc}.@*
@xref{do_dialog}.@*
@xref{gui_fg_color, gui_bg_color}.@*
@xref{gui_fg_color}.@*
@xref{gui_mg_color}.@*
@xref{install_keyboard}.@*
@xref{install_mouse}.@*
@xref{install_timer}.@*
@xref{key}.@*
@xref{load_datafile}.@*
@xref{makecol}.@*
@xref{position_dialog}.@*
@xref{replace_filename}.@*
@xref{screen}.@*
@xref{set_dialog_color}.@*
@xref{set_gfx_mode}.@*
@xref{set_palette}.@*
@xref{unload_datafile}.@*
@xref{ustrtok}.@*
@xref{ustrzcat}.@*
@xref{ustrzcpy}.@*
@xref{uszprintf}.@*
@node excustom, exunicod, exgui, Available
@subsection excustom
@ftable @asis
@item @t{Example excustom}
A follow up of the exgui.c example showing how to customise the
default Allegro framework. In this case a dialog procedure
animates a graphical clock without disrupting other GUI
dialogs.  A more simple option shows how to dynamically change
the font used by all GUI elements.

@end ftable
See also:@*
@xref{BITMAP}.@*
@xref{DATAFILE}.@*
@xref{DIALOG}.@*
@xref{END_OF_MAIN}.@*
@xref{FONT}.@*
@xref{allegro_error}.@*
@xref{allegro_init}.@*
@xref{allegro_message}.@*
@xref{blit}.@*
@xref{circle}.@*
@xref{circlefill}.@*
@xref{clear_to_color}.@*
@xref{create_bitmap}.@*
@xref{d_button_proc}.@*
@xref{d_check_proc}.@*
@xref{d_clear_proc}.@*
@xref{d_edit_proc}.@*
@xref{desktop_palette}.@*
@xref{destroy_bitmap}.@*
@xref{do_dialog}.@*
@xref{fixcos}.@*
@xref{fixed}.@*
@xref{fixmul}.@*
@xref{fixsin}.@*
@xref{fixtoi}.@*
@xref{font}.@*
@xref{install_keyboard}.@*
@xref{install_mouse}.@*
@xref{install_timer}.@*
@xref{itofix}.@*
@xref{key}.@*
@xref{line}.@*
@xref{load_datafile}.@*
@xref{makecol}.@*
@xref{object_message}.@*
@xref{replace_filename}.@*
@xref{screen}.@*
@xref{set_gfx_mode}.@*
@xref{set_palette}.@*
@xref{unload_datafile}.@*
@node exunicod, exbitmap, excustom, Available
@subsection exunicod
@ftable @asis
@item @t{Example exunicod}
This program demonstrates the use of the 16-bit Unicode text
encoding format with Allegro. The example displays a message
translated to different languages scrolling on the screen
using an external font containing the required characters to
display those messages.

Note how the Allegro unicode string functions resemble the
functions you can find in the standard C library, only these
handle Unicode on all platforms.

@end ftable
See also:@*
@xref{BITMAP}.@*
@xref{DATAFILE}.@*
@xref{END_OF_MAIN}.@*
@xref{FONT}.@*
@xref{SCREEN_W, SCREEN_H}.@*
@xref{SCREEN_W}.@*
@xref{allegro_error}.@*
@xref{allegro_init}.@*
@xref{allegro_message}.@*
@xref{blit}.@*
@xref{clear_to_color}.@*
@xref{create_bitmap}.@*
@xref{destroy_bitmap}.@*
@xref{font}.@*
@xref{install_int_ex}.@*
@xref{install_keyboard}.@*
@xref{install_timer}.@*
@xref{keypressed}.@*
@xref{load_datafile}.@*
@xref{replace_filename}.@*
@xref{rest}.@*
@xref{screen}.@*
@xref{set_gfx_mode}.@*
@xref{set_uformat}.@*
@xref{set_window_title}.@*
@xref{text_height}.@*
@xref{text_length}.@*
@xref{textout_ex}.@*
@xref{uconvert_ascii}.@*
@xref{unload_datafile}.@*
@xref{ustrcat}.@*
@xref{ustrcpy}.@*
@xref{ustrsize}.@*
@xref{ustrsizez}.@*
@node exbitmap, exscale, exunicod, Available
@subsection exbitmap
@ftable @asis
@item @t{Example exbitmap}
This program demonstrates how to load and display a bitmap
file.  You have to use this example from the command line to
specify as first parameter a graphic file in one of Allegro's
supported formats.  If the file is loaded successfully,
it will be displayed until you press a key.

@end ftable
See also:@*
@xref{BITMAP}.@*
@xref{END_OF_MAIN}.@*
@xref{PALETTE}.@*
@xref{SCREEN_W, SCREEN_H}.@*
@xref{SCREEN_W}.@*
@xref{allegro_error}.@*
@xref{allegro_init}.@*
@xref{allegro_message}.@*
@xref{blit}.@*
@xref{destroy_bitmap}.@*
@xref{install_keyboard}.@*
@xref{load_bitmap}.@*
@xref{readkey}.@*
@xref{screen}.@*
@xref{set_gfx_mode}.@*
@xref{set_palette}.@*
@node exscale, exconfig, exbitmap, Available
@subsection exscale
@ftable @asis
@item @t{Example exscale}
This example demonstrates how to use PCX files, palettes and stretch
blits. It loads a PCX file, sets its palette and does some random
stretch_blits. Don't worry - it's VERY slowed down using vsync().

@end ftable
See also:@*
@xref{BITMAP}.@*
@xref{END_OF_MAIN}.@*
@xref{PALETTE}.@*
@xref{SCREEN_W, SCREEN_H}.@*
@xref{SCREEN_W}.@*
@xref{allegro_error}.@*
@xref{allegro_init}.@*
@xref{allegro_message}.@*
@xref{blit}.@*
@xref{destroy_bitmap}.@*
@xref{install_keyboard}.@*
@xref{keypressed}.@*
@xref{load_pcx}.@*
@xref{replace_filename}.@*
@xref{screen}.@*
@xref{set_gfx_mode}.@*
@xref{set_palette}.@*
@xref{stretch_blit}.@*
@xref{vsync}.@*
@node exconfig, exdata, exscale, Available
@subsection exconfig
@ftable @asis
@item @t{Example exconfig}
This is a very simple program showing how to use the Allegro
configuration (ini file) routines. A first look at the example
shows nothing more than a static graphic and the wait for
a key press. However, the way this graphic is displayed is
configured through a custom exconfig.ini file which is loaded
manually. From this file the example obtains parameters like
fullscreen/windowed mode, a specific graphic resolution to set
up, which graphic to show, how to blit it on the screen, etc.

@end ftable
See also:@*
@xref{BITMAP}.@*
@xref{END_OF_MAIN}.@*
@xref{RGB}.@*
@xref{SCREEN_W, SCREEN_H}.@*
@xref{SCREEN_W}.@*
@xref{allegro_init}.@*
@xref{allegro_message}.@*
@xref{blit}.@*
@xref{clear_bitmap}.@*
@xref{font}.@*
@xref{get_config_argv}.@*
@xref{get_config_int}.@*
@xref{get_config_string}.@*
@xref{install_keyboard}.@*
@xref{line}.@*
@xref{load_bitmap}.@*
@xref{makecol}.@*
@xref{pop_config_state}.@*
@xref{push_config_state}.@*
@xref{readkey}.@*
@xref{screen}.@*
@xref{set_color_depth}.@*
@xref{set_config_file}.@*
@xref{set_gfx_mode}.@*
@xref{set_palette}.@*
@xref{stretch_blit}.@*
@xref{textout_centre_ex}.@*
@xref{textprintf_centre_ex}.@*
@xref{ustrdup}.@*
@xref{ustricmp}.@*
@node exdata, exsprite, exconfig, Available
@subsection exdata
@ftable @asis
@item @t{Example exdata}
This program demonstrates how to access the contents of an
Allegro datafile (created by the grabber utility). The example
loads the file `example.dat', then blits a bitmap and shows
a font, both from this datafile.

@end ftable
See also:@*
@xref{DATAFILE}.@*
@xref{END_OF_MAIN}.@*
@xref{allegro_error}.@*
@xref{allegro_init}.@*
@xref{allegro_message}.@*
@xref{blit}.@*
@xref{font}.@*
@xref{install_keyboard}.@*
@xref{load_datafile}.@*
@xref{makecol}.@*
@xref{readkey}.@*
@xref{replace_filename}.@*
@xref{screen}.@*
@xref{set_color_conversion}.@*
@xref{set_gfx_mode}.@*
@xref{set_palette}.@*
@xref{textout_ex}.@*
@xref{unload_datafile}.@*
@node exsprite, exexedat, exdata, Available
@subsection exsprite
@ftable @asis
@item @t{Example exsprite}
This example demonstrates how to use datafiles, various sprite
drawing routines and flicker-free animation.

Why is the animate() routine coded in that way?  As you
probably know, VIDEO RAM is much slower than "normal"
RAM, so it's advisable to reduce VRAM blits to a minimum.
Drawing sprite on the screen (meaning in VRAM) and then
clearing a background for it is not very fast. This example
uses a different method which is much faster, but require a
bit more memory.

First the buffer is cleared (it's a normal BITMAP), then the
sprite is drawn on it, and when the drawing is finished this
buffer is copied directly to the screen. So the end result is
that there is a single VRAM blit instead of blitting/clearing
the background and drawing a sprite on it.  It's a good method
even when you have to restore the background. And of course,
it completely removes any flickering effect.

When one uses a big (ie. 800x600 background) and draws
something on it, it's wise to use a copy of background
somewhere in memory and restore background using this
"virtual background". When blitting from VRAM in SVGA modes,
it's probably, that drawing routines have to switch banks on
video card. I think, I don't have to remind how slow is it.

Note that on modern systems, the above isn't true anymore, and
you usually get the best performance by caching all your
animations in video ram and doing only VRAM->VRAM blits, so
there is no more RAM->VRAM transfer at all anymore. And usually,
such transfers can run in parallel on the graphics card's
processor as well, costing virtually no main cpu time at all.
See the exaccel example for an example of this.

@end ftable
See also:@*
@xref{BITMAP}.@*
@xref{DATAFILE}.@*
@xref{END_OF_FUNCTION}.@*
@xref{END_OF_MAIN}.@*
@xref{LOCK_FUNCTION}.@*
@xref{LOCK_VARIABLE}.@*
@xref{SCREEN_W, SCREEN_H}.@*
@xref{SCREEN_W}.@*
@xref{allegro_error}.@*
@xref{allegro_init}.@*
@xref{allegro_message}.@*
@xref{blit}.@*
@xref{circle}.@*
@xref{clear_bitmap}.@*
@xref{clear_keybuf}.@*
@xref{create_bitmap}.@*
@xref{destroy_bitmap}.@*
@xref{draw_sprite}.@*
@xref{draw_sprite_v_flip, draw_sprite_h_flip}.@*
@xref{draw_sprite_v_flip}.@*
@xref{draw_sprite_v_flip, draw_sprite_vh_flip}.@*
@xref{fixed}.@*
@xref{font}.@*
@xref{hline}.@*
@xref{install_int_ex}.@*
@xref{install_keyboard}.@*
@xref{install_sound}.@*
@xref{install_timer}.@*
@xref{itofix}.@*
@xref{key}.@*
@xref{keypressed}.@*
@xref{load_datafile}.@*
@xref{makecol}.@*
@xref{palette_color}.@*
@xref{pivot_sprite}.@*
@xref{pivot_sprite_v_flip}.@*
@xref{play_sample}.@*
@xref{rectfill}.@*
@xref{replace_filename}.@*
@xref{rest}.@*
@xref{screen}.@*
@xref{set_gfx_mode}.@*
@xref{set_palette}.@*
@xref{text_height}.@*
@xref{textout_centre_ex}.@*
@xref{unload_datafile}.@*
@xref{vsync}.@*
@node exexedat, extrans, exsprite, Available
@subsection exexedat
@ftable @asis
@item @t{Example exexedat}
This program demonstrates how to access the contents of an Allegro
datafile (created by the grabber utility) linked to the executable by the
exedat tool. It is basically the exdata example with minor
modifications.

You may ask: how do you compile, append and exec your program?

Answer: like this...

1) Compile your program like normal. Use the magic filenames with '#'
to load your data where needed.

2) Once you compressed your program, run "exedat foo.exe data.dat"

3) Finally run your program.

Note that appending data to the end of binaries may not be portable
across all platforms supported by Allegro.

@end ftable
See also:@*
@xref{DATAFILE}.@*
@xref{END_OF_MAIN}.@*
@xref{allegro_error}.@*
@xref{allegro_init}.@*
@xref{allegro_message}.@*
@xref{blit}.@*
@xref{font}.@*
@xref{install_keyboard}.@*
@xref{line}.@*
@xref{load_datafile}.@*
@xref{makecol}.@*
@xref{readkey}.@*
@xref{screen}.@*
@xref{set_color_conversion}.@*
@xref{set_gfx_mode}.@*
@xref{set_palette}.@*
@xref{textout_ex}.@*
@xref{unload_datafile}.@*
@node extrans, extruec, exexedat, Available
@subsection extrans
@ftable @asis
@item @t{Example extrans}
This program demonstrates how to use the lighting and
translucency functions. The first part of the example will
show a dark screen illuminated by a spotlight you can move
with your mouse. After a key press the example shows the full
bitmap and the spotlight changes to be a reduced version of
the background with 50% of translucency.

The translucency effect is easy to do in all color depths.
However, the lighting effect has to be performed in a different
way depending on whether the screen is in 8bit mode or another
color depth. This is because additive drawing mode uses a
different set of routines for truecolor modes.

@end ftable
See also:@*
@xref{BITMAP}.@*
@xref{COLOR_MAP}.@*
@xref{END_OF_MAIN}.@*
@xref{PALETTE}.@*
@xref{RGB}.@*
@xref{RGB_MAP}.@*
@xref{SCREEN_W, SCREEN_H}.@*
@xref{SCREEN_W}.@*
@xref{allegro_error}.@*
@xref{allegro_init}.@*
@xref{allegro_message}.@*
@xref{bitmap_color_depth}.@*
@xref{blit}.@*
@xref{circlefill}.@*
@xref{clear_bitmap}.@*
@xref{clear_keybuf}.@*
@xref{color_map}.@*
@xref{create_bitmap}.@*
@xref{create_bitmap_ex}.@*
@xref{create_light_table}.@*
@xref{create_rgb_table}.@*
@xref{create_trans_table}.@*
@xref{destroy_bitmap}.@*
@xref{draw_trans_sprite}.@*
@xref{drawing_mode}.@*
@xref{install_keyboard}.@*
@xref{install_mouse}.@*
@xref{install_timer}.@*
@xref{keypressed}.@*
@xref{load_bitmap}.@*
@xref{mouse_x}.@*
@xref{mouse_x, mouse_y}.@*
@xref{poll_mouse}.@*
@xref{rectfill}.@*
@xref{replace_filename}.@*
@xref{rest}.@*
@xref{rgb_map}.@*
@xref{screen}.@*
@xref{set_alpha_blender}.@*
@xref{set_gfx_mode}.@*
@xref{set_palette}.@*
@xref{set_trans_blender}.@*
@xref{set_write_alpha_blender}.@*
@xref{stretch_blit}.@*
@node extruec, excolmap, extrans, Available
@subsection extruec
@ftable @asis
@item @t{Example extruec}
This program shows how to specify colors in the various different
truecolor pixel formats. The example shows the same screen (a few
text lines and three coloured gradients) in all the color depth
modes supported by your video card. The more color depth you have,
the less banding you will see in the gradients.

@end ftable
See also:@*
@xref{END_OF_MAIN}.@*
@xref{PALETTE}.@*
@xref{RGB}.@*
@xref{SCREEN_W, SCREEN_H}.@*
@xref{SCREEN_W}.@*
@xref{acquire_screen}.@*
@xref{allegro_init}.@*
@xref{clear_to_color}.@*
@xref{font}.@*
@xref{generate_332_palette}.@*
@xref{install_keyboard}.@*
@xref{key}.@*
@xref{makecol}.@*
@xref{readkey}.@*
@xref{release_screen}.@*
@xref{screen}.@*
@xref{set_color_depth}.@*
@xref{set_gfx_mode}.@*
@xref{set_palette}.@*
@xref{textout_centre_ex}.@*
@xref{textout_ex}.@*
@xref{textprintf_ex}.@*
@xref{vline}.@*
@node excolmap, exrgbhsv, extruec, Available
@subsection excolmap
@ftable @asis
@item @t{Example excolmap}
This program demonstrates how to create custom graphic effects
with the create_color_table function. Allegro drawing routines
are affected by any color table you might have set up. In
the first part of this example, a greyscale color table is
set. The result is that a simple rectfill call, instead of
drawing a rectangle with color zero, uses the already drawn
pixels to determine the pixel to be drawn (read the comment
of return_grey_color() for a precise description of the
algorithm). In the second part of the test, the color table
is changed to be an inverse table, meaning that any pixel
drawn will be shown as its color values had been inverted.

@end ftable
See also:@*
@xref{BITMAP}.@*
@xref{COLOR_MAP}.@*
@xref{END_OF_MAIN}.@*
@xref{PALETTE}.@*
@xref{RGB}.@*
@xref{RGB_MAP}.@*
@xref{SCREEN_W, SCREEN_H}.@*
@xref{SCREEN_W}.@*
@xref{allegro_error}.@*
@xref{allegro_init}.@*
@xref{allegro_message}.@*
@xref{blit}.@*
@xref{circlefill}.@*
@xref{clear_keybuf}.@*
@xref{color_map}.@*
@xref{create_bitmap}.@*
@xref{create_color_table}.@*
@xref{create_rgb_table}.@*
@xref{destroy_bitmap}.@*
@xref{drawing_mode}.@*
@xref{font}.@*
@xref{generate_332_palette}.@*
@xref{install_keyboard}.@*
@xref{keypressed}.@*
@xref{makecol}.@*
@xref{rectfill}.@*
@xref{rgb_map}.@*
@xref{screen}.@*
@xref{set_gfx_mode}.@*
@xref{set_palette}.@*
@xref{textout_centre_ex}.@*
@xref{vsync}.@*
@node exrgbhsv, exshade, excolmap, Available
@subsection exrgbhsv
@ftable @asis
@item @t{Example exrgbhsv}
This program shows how to convert colors between the different
color-space representations. The central area of the screen
will display the current color. On the top left corner of the
screen, three sliders allow you to modify the red, green and
blue value of the color. On the bottom right corner of the
screen, three sliders allow you to modify the hue, saturation
and value of the color. The color bars beneath the sliders
show what the resulting color will look like when the slider
is dragged to that position.

Additionally this example also shows how to "inherit" the
behaviour of a GUI object and extend it, here used to create
the sliders.

@end ftable
See also:@*
@xref{BITMAP}.@*
@xref{DIALOG}.@*
@xref{END_OF_MAIN}.@*
@xref{PALETTE}.@*
@xref{RGB}.@*
@xref{RGB_MAP}.@*
@xref{allegro_error}.@*
@xref{allegro_init}.@*
@xref{allegro_message}.@*
@xref{clear_to_color}.@*
@xref{create_bitmap_ex}.@*
@xref{create_rgb_table}.@*
@xref{d_bitmap_proc}.@*
@xref{d_box_proc}.@*
@xref{d_slider_proc}.@*
@xref{d_text_proc}.@*
@xref{destroy_bitmap}.@*
@xref{do_dialog}.@*
@xref{font}.@*
@xref{generate_332_palette}.@*
@xref{get_color_depth}.@*
@xref{hsv_to_rgb}.@*
@xref{install_keyboard}.@*
@xref{install_mouse}.@*
@xref{install_timer}.@*
@xref{key}.@*
@xref{makecol}.@*
@xref{makecol8, makecol32}.@*
@xref{makecol8}.@*
@xref{object_message}.@*
@xref{rgb_map}.@*
@xref{hsv_to_rgb, rgb_to_hsv}.@*
@xref{screen}.@*
@xref{set_color}.@*
@xref{set_color_depth}.@*
@xref{set_gfx_mode}.@*
@xref{set_palette}.@*
@xref{textout_ex}.@*
@xref{vline}.@*
@xref{vsync}.@*
@node exshade, exblend, exrgbhsv, Available
@subsection exshade
@ftable @asis
@item @t{Example exshade}
This program demonstrates how to draw Gouraud shaded (lit)
sprites.  In an apparently black screen, a planet like sprite
is drawn close to the middle of the screen. In a similar
way to how the first test of extrans works, you move the
cursor on the screen with the mouse. Attached to this mouse
you can imagine a virtual spotlight illuminating the scene
around. Depending on where the mouse is, the Gouraud shaded
sprite will show the direction of the light.

@end ftable
See also:@*
@xref{BITMAP}.@*
@xref{COLOR_MAP}.@*
@xref{END_OF_MAIN}.@*
@xref{PALETTE}.@*
@xref{RGB}.@*
@xref{RGB_MAP}.@*
@xref{SCREEN_W, SCREEN_H}.@*
@xref{SCREEN_W}.@*
@xref{allegro_error}.@*
@xref{allegro_init}.@*
@xref{allegro_message}.@*
@xref{blit}.@*
@xref{clear_bitmap}.@*
@xref{color_map}.@*
@xref{create_bitmap}.@*
@xref{create_light_table}.@*
@xref{create_rgb_table}.@*
@xref{destroy_bitmap}.@*
@xref{draw_gouraud_sprite}.@*
@xref{font}.@*
@xref{install_keyboard}.@*
@xref{install_mouse}.@*
@xref{keypressed}.@*
@xref{line}.@*
@xref{load_bitmap}.@*
@xref{mouse_x}.@*
@xref{mouse_x, mouse_y}.@*
@xref{palette_color}.@*
@xref{poll_mouse}.@*
@xref{replace_filename}.@*
@xref{rgb_map}.@*
@xref{screen}.@*
@xref{set_gfx_mode}.@*
@xref{set_palette}.@*
@xref{set_trans_blender}.@*
@xref{show_mouse}.@*
@xref{textout_ex}.@*
@node exblend, exxfade, exshade, Available
@subsection exblend
@ftable @asis
@item @t{Example exblend}
This program demonstrates how to use the translucency functions
in truecolor video modes. Two image files are loaded from
disk and displayed moving slowly around the screen. One of
the images will be tinted to different colors. The other
image will be faded out with a varying alpha strength, and
drawn on top of the other image.

@end ftable
See also:@*
@xref{BITMAP}.@*
@xref{END_OF_MAIN}.@*
@xref{PALETTE}.@*
@xref{SCREEN_W, SCREEN_H}.@*
@xref{SCREEN_W}.@*
@xref{allegro_error}.@*
@xref{allegro_init}.@*
@xref{allegro_message}.@*
@xref{blit}.@*
@xref{circle}.@*
@xref{clear_bitmap}.@*
@xref{clear_keybuf}.@*
@xref{create_bitmap}.@*
@xref{destroy_bitmap}.@*
@xref{draw_lit_sprite}.@*
@xref{draw_trans_sprite}.@*
@xref{fixcos}.@*
@xref{fixsin}.@*
@xref{fixtoi}.@*
@xref{font}.@*
@xref{install_keyboard}.@*
@xref{install_timer}.@*
@xref{itofix}.@*
@xref{keypressed}.@*
@xref{load_bitmap}.@*
@xref{makecol}.@*
@xref{replace_filename}.@*
@xref{retrace_count}.@*
@xref{screen}.@*
@xref{set_color_conversion}.@*
@xref{set_color_depth}.@*
@xref{set_gfx_mode}.@*
@xref{set_trans_blender}.@*
@xref{textprintf_ex}.@*
@xref{vsync}.@*
@node exxfade, exalpha, exblend, Available
@subsection exxfade
@ftable @asis
@item @t{Example exxfade}
This program demonstrates how to load and display bitmap files
in truecolor video modes, and how to crossfade between them.
You have to use this example from the command line to specify
as parameters a number of graphic files. Use at least two
files to see the graphical effect. The example will crossfade
from one image to another with each key press until you press
the ESC key.

@end ftable
See also:@*
@xref{BITMAP}.@*
@xref{END_OF_MAIN}.@*
@xref{PALETTE}.@*
@xref{SCREEN_W, SCREEN_H}.@*
@xref{SCREEN_W}.@*
@xref{allegro_error}.@*
@xref{allegro_exit}.@*
@xref{allegro_init}.@*
@xref{allegro_message}.@*
@xref{blit}.@*
@xref{create_bitmap}.@*
@xref{destroy_bitmap}.@*
@xref{draw_trans_sprite}.@*
@xref{install_keyboard}.@*
@xref{keypressed}.@*
@xref{line}.@*
@xref{load_bitmap}.@*
@xref{readkey}.@*
@xref{screen}.@*
@xref{set_color_conversion}.@*
@xref{set_color_depth}.@*
@xref{set_gfx_mode}.@*
@xref{set_palette}.@*
@xref{set_trans_blender}.@*
@xref{vsync}.@*
@node exalpha, exlights, exxfade, Available
@subsection exalpha
@ftable @asis
@item @t{Example exalpha}
This program demonstrates how to use the 32 bit RGBA
translucency functions to store an alpha channel along with
a bitmap graphic.  Two images are loaded from disk. One will
be used for the background and the other as a sprite. The
example generates an alpha channel for the sprite image,
composing the 32 bit RGBA bitmap during runtime, and draws
it at the position of the mouse cursor.

@end ftable
See also:@*
@xref{BITMAP}.@*
@xref{END_OF_MAIN}.@*
@xref{SCREEN_W, SCREEN_H}.@*
@xref{SCREEN_W}.@*
@xref{allegro_error}.@*
@xref{allegro_init}.@*
@xref{allegro_message}.@*
@xref{blit}.@*
@xref{clear_keybuf}.@*
@xref{create_bitmap}.@*
@xref{destroy_bitmap}.@*
@xref{draw_trans_sprite}.@*
@xref{drawing_mode}.@*
@xref{font}.@*
@xref{getr, getb}.@*
@xref{getr, getg}.@*
@xref{getpixel}.@*
@xref{getr}.@*
@xref{install_keyboard}.@*
@xref{install_mouse}.@*
@xref{install_timer}.@*
@xref{keypressed}.@*
@xref{load_bitmap}.@*
@xref{makecol}.@*
@xref{mouse_x}.@*
@xref{mouse_x, mouse_y}.@*
@xref{putpixel}.@*
@xref{rectfill}.@*
@xref{replace_filename}.@*
@xref{screen}.@*
@xref{set_alpha_blender}.@*
@xref{set_color_conversion}.@*
@xref{set_color_depth}.@*
@xref{set_gfx_mode}.@*
@xref{set_multiply_blender}.@*
@xref{set_write_alpha_blender}.@*
@xref{solid_mode}.@*
@xref{stretch_blit}.@*
@xref{textprintf_ex}.@*
@node exlights, ex3d, exalpha, Available
@subsection exlights
@ftable @asis
@item @t{Example exlights}
This program shows one way to implement colored lighting effects
in a hicolor video mode. Warning: it is not for the faint of heart!
This is by no means the simplest or easiest to understand method,
I just thought it was a cool concept that would be worth
demonstrating.

The basic approach is to select a 15 or 16 bit screen mode, but
then draw onto 24 bit memory bitmaps. Since we only need the bottom
5 bits of each 8 bit color in order to store 15 bit data within a
24 bit location, we can fit a light level into the top 3 bits.
The tricky bit is that these aren't actually 24 bit images at all:
they are implemented as 8 bit memory bitmaps, and we just store the
red level in one pixel, green in the next, and blue in the next,
making the total image be three times wider than we really wanted.
This allows us to use all the normal 256 color graphics routines
for drawing onto our memory surfaces, most importantly the lookup
table translucency, which can be used to combine the low 5 bits
of color and the top 3 bits of light in a single drawing operation.
Some trickery is needed to load 24 bit data into this fake 8 bit
format, and of course it needs a custom routine to convert the
resulting image while copying it across to the hardware screen.

This program chugs slightly on my p133, but not significantly
worse than any double buffering in what amounts to a 1920x640,
256 color resolution. The light blending doesn't seem to slow
it down too badly, so I think this technique would be quite usable
on faster machines and in lower resolution hicolor modes. The
biggest problem is that although you keep the full 15 bit color
resolution, you only get 3 bits of light, ie. 8 light levels.
You can do some nice colored light patches, but smooth gradients
aren't going to work too well :-)

@end ftable
See also:@*
@xref{BITMAP}.@*
@xref{COLOR_MAP}.@*
@xref{END_OF_MAIN}.@*
@xref{PALETTE}.@*
@xref{SCREEN_W, SCREEN_H}.@*
@xref{SCREEN_W}.@*
@xref{allegro_error}.@*
@xref{allegro_init}.@*
@xref{allegro_message}.@*
@xref{bitmap_color_depth}.@*
@xref{blit}.@*
@xref{bmp_unwrite_line}.@*
@xref{bmp_write_line}.@*
@xref{circlefill}.@*
@xref{clear_bitmap}.@*
@xref{clear_keybuf}.@*
@xref{color_map}.@*
@xref{create_bitmap_ex}.@*
@xref{destroy_bitmap}.@*
@xref{draw_trans_sprite}.@*
@xref{fixatan2}.@*
@xref{fixsqrt}.@*
@xref{fixtoi}.@*
@xref{getr_depth, getb_depth}.@*
@xref{getr_depth, getg_depth}.@*
@xref{getpixel}.@*
@xref{getr_depth}.@*
@xref{hsv_to_rgb}.@*
@xref{install_keyboard}.@*
@xref{install_mouse}.@*
@xref{install_timer}.@*
@xref{itofix}.@*
@xref{key}.@*
@xref{keypressed}.@*
@xref{line}.@*
@xref{load_bitmap}.@*
@xref{makecol}.@*
@xref{mouse_x}.@*
@xref{mouse_x, mouse_y}.@*
@xref{poll_mouse}.@*
@xref{replace_filename}.@*
@xref{retrace_count}.@*
@xref{screen}.@*
@xref{select_palette}.@*
@xref{set_color_conversion}.@*
@xref{set_color_depth}.@*
@xref{set_gfx_mode}.@*
@node ex3d, excamera, exlights, Available
@subsection ex3d
@ftable @asis
@item @t{Example ex3d}
This program demonstrates how to use the 3d matrix functions.
It isn't a very elegant or efficient piece of code, but it
does show the stuff in action. It is left to the reader as
an exercise to design a proper model structure and rendering
pipeline: after all, the best way to do that sort of stuff
varies hugely from one game to another.

The example first shows a screen resolution selection dialog.
Then, a number of bouncing 3d cubes are animated. Pressing
a key modifies the rendering of the cubes, which can be
wireframe, the more complex transparent perspective correct
texture mapped version, and many other.

@end ftable
See also:@*
@xref{BITMAP}.@*
@xref{COLOR_MAP}.@*
@xref{END_OF_MAIN}.@*
@xref{MATRIX}.@*
@xref{PALETTE}.@*
@xref{POLYTYPE_ATEX}.@*
@xref{POLYTYPE_ATEX_LIT}.@*
@xref{POLYTYPE_ATEX_MASK}.@*
@xref{POLYTYPE_ATEX_MASK_LIT}.@*
@xref{POLYTYPE_ATEX_MASK_TRANS}.@*
@xref{POLYTYPE_ATEX_TRANS}.@*
@xref{POLYTYPE_FLAT}.@*
@xref{POLYTYPE_GCOL}.@*
@xref{POLYTYPE_GRGB}.@*
@xref{POLYTYPE_PTEX}.@*
@xref{POLYTYPE_ATEX_LIT, POLYTYPE_PTEX_LIT}.@*
@xref{POLYTYPE_ATEX_MASK, POLYTYPE_PTEX_MASK}.@*
@xref{POLYTYPE_ATEX_MASK_LIT, POLYTYPE_PTEX_MASK_LIT}.@*
@xref{POLYTYPE_ATEX_MASK_TRANS, POLYTYPE_PTEX_MASK_TRANS}.@*
@xref{POLYTYPE_ATEX_TRANS, POLYTYPE_PTEX_TRANS}.@*
@xref{RGB}.@*
@xref{RGB_MAP}.@*
@xref{SCREEN_W, SCREEN_H}.@*
@xref{SCREEN_W}.@*
@xref{V3D}.@*
@xref{allegro_error}.@*
@xref{allegro_exit}.@*
@xref{allegro_init}.@*
@xref{allegro_message}.@*
@xref{apply_matrix}.@*
@xref{bitmap_color_depth}.@*
@xref{bitmap_mask_color}.@*
@xref{blit}.@*
@xref{clear_bitmap}.@*
@xref{clear_to_color}.@*
@xref{color_map}.@*
@xref{create_bitmap}.@*
@xref{create_light_table}.@*
@xref{create_rgb_table}.@*
@xref{create_trans_table}.@*
@xref{desktop_palette}.@*
@xref{destroy_bitmap}.@*
@xref{fixed}.@*
@xref{fixtoi}.@*
@xref{font}.@*
@xref{get_transformation_matrix}.@*
@xref{gfx_mode_select_ex}.@*
@xref{install_keyboard}.@*
@xref{install_mouse}.@*
@xref{install_timer}.@*
@xref{itofix}.@*
@xref{key}.@*
@xref{keypressed}.@*
@xref{line}.@*
@xref{palette_color}.@*
@xref{persp_project}.@*
@xref{polygon_z_normal}.@*
@xref{quad3d}.@*
@xref{readkey}.@*
@xref{rect}.@*
@xref{retrace_count}.@*
@xref{rgb_map}.@*
@xref{screen}.@*
@xref{set_color_depth}.@*
@xref{set_gfx_mode}.@*
@xref{set_palette}.@*
@xref{set_projection_viewport}.@*
@xref{set_trans_blender}.@*
@xref{textout_ex}.@*
@xref{textprintf_ex}.@*
@xref{vsync}.@*
@node excamera, exquat, ex3d, Available
@subsection excamera
@ftable @asis
@item @t{Example excamera}
This program demonstrates how to use the get_camera_matrix()
function to view a 3d world from any position and angle. The
example draws a checkered floor through a viewport region
on the screen. You can use the keyboard to move around the
camera or modify the size of the viewport. The keys that can
be used with this example are displayed between brackets at
the top of the screen.

@end ftable
See also:@*
@xref{BITMAP}.@*
@xref{END_OF_MAIN}.@*
@xref{MATRIX_f}.@*
@xref{POLYTYPE_FLAT}.@*
@xref{SCREEN_W, SCREEN_H}.@*
@xref{SCREEN_W}.@*
@xref{V3D_f}.@*
@xref{allegro_error}.@*
@xref{allegro_init}.@*
@xref{allegro_message}.@*
@xref{apply_matrix, apply_matrix_f}.@*
@xref{blit}.@*
@xref{clear_to_color}.@*
@xref{clip3d_f}.@*
@xref{create_bitmap}.@*
@xref{desktop_palette}.@*
@xref{destroy_bitmap}.@*
@xref{font}.@*
@xref{get_camera_matrix_f}.@*
@xref{get_vector_rotation_matrix, get_vector_rotation_matrix_f}.@*
@xref{install_int_ex}.@*
@xref{install_keyboard}.@*
@xref{install_timer}.@*
@xref{key}.@*
@xref{key_shifts}.@*
@xref{makecol}.@*
@xref{persp_project, persp_project_f}.@*
@xref{poll_keyboard}.@*
@xref{polygon}.@*
@xref{polygon3d, polygon3d_f}.@*
@xref{rect}.@*
@xref{screen}.@*
@xref{set_clip_rect}.@*
@xref{set_gfx_mode}.@*
@xref{set_palette}.@*
@xref{set_projection_viewport}.@*
@xref{textprintf_ex}.@*
@xref{vsync}.@*
@node exquat, exstars, excamera, Available
@subsection exquat
@ftable @asis
@item @t{Example exquat}
Euler angles are convenient for storing and creating 3D orientations.
However, this program demonstrates that they are not good when
interpolating between two different orientations. The problem is
solved by using Allegro's quaternion operations.

In this program, two cubes are rotated between random orientations.
Notice that although they have the same beginning and ending
orientations, they do not follow the same path between orientations.

One cube is being rotated by directly incrementing or decrementing
the Euler angles from the starting point to the ending point.
This is an intuitive notion, but it is incorrect because it does not
cause the object to turn around a single unchanging axis of rotation.
The axis of rotation wobbles resulting in the object spinning in
strange ways. The object will eventually end up in the orientation
that the user intended, but it gets there in a way that is unattractive.
Imagine if this method was used to update the position of a camera in a
game! Sometimes it would swing wildly and disorient the player.

The other cube is animated using quaternions. This results in a much
more pleasing animation because the cube turns around a single axis
of rotation.

@end ftable
See also:@*
@xref{BITMAP}.@*
@xref{END_OF_MAIN}.@*
@xref{MATRIX_f}.@*
@xref{QUAT}.@*
@xref{acquire_bitmap}.@*
@xref{allegro_error}.@*
@xref{allegro_init}.@*
@xref{allegro_message}.@*
@xref{apply_matrix, apply_matrix_f}.@*
@xref{blit}.@*
@xref{circle}.@*
@xref{clear_keybuf}.@*
@xref{clear_to_color}.@*
@xref{create_bitmap}.@*
@xref{desktop_palette}.@*
@xref{destroy_bitmap}.@*
@xref{font}.@*
@xref{get_camera_matrix_f}.@*
@xref{get_rotation_matrix}.@*
@xref{get_rotation_matrix, get_rotation_matrix_f}.@*
@xref{get_rotation_quat}.@*
@xref{install_keyboard}.@*
@xref{keypressed}.@*
@xref{line}.@*
@xref{matrix_mul, matrix_mul_f}.@*
@xref{palette_color}.@*
@xref{persp_project, persp_project_f}.@*
@xref{quat_interpolate}.@*
@xref{quat_to_matrix}.@*
@xref{readkey}.@*
@xref{release_bitmap}.@*
@xref{rest}.@*
@xref{screen}.@*
@xref{set_gfx_mode}.@*
@xref{set_palette}.@*
@xref{set_projection_viewport}.@*
@xref{textout_ex}.@*
@node exstars, exscn3d, exquat, Available
@subsection exstars
@ftable @asis
@item @t{Example exstars}
This program draws a 3D star field (depth-cued) and a polygon
starship (controllable with the keyboard cursor keys), using
the Allegro math functions.

@end ftable
See also:@*
@xref{BITMAP}.@*
@xref{END_OF_MAIN}.@*
@xref{MATRIX}.@*
@xref{PALETTE}.@*
@xref{SCREEN_W, SCREEN_H}.@*
@xref{SCREEN_W}.@*
@xref{allegro_error}.@*
@xref{allegro_init}.@*
@xref{allegro_message}.@*
@xref{apply_matrix}.@*
@xref{blit}.@*
@xref{clear_bitmap}.@*
@xref{create_bitmap}.@*
@xref{cross_product}.@*
@xref{destroy_bitmap}.@*
@xref{dot_product}.@*
@xref{fixed}.@*
@xref{fixmul}.@*
@xref{fixtof}.@*
@xref{fixtoi}.@*
@xref{font}.@*
@xref{get_rotation_matrix}.@*
@xref{get_transformation_matrix}.@*
@xref{get_translation_matrix}.@*
@xref{install_keyboard}.@*
@xref{install_timer}.@*
@xref{itofix}.@*
@xref{key}.@*
@xref{normalize_vector}.@*
@xref{palette_color}.@*
@xref{persp_project}.@*
@xref{poll_keyboard}.@*
@xref{putpixel}.@*
@xref{rectfill}.@*
@xref{screen}.@*
@xref{set_gfx_mode}.@*
@xref{set_palette}.@*
@xref{set_projection_viewport}.@*
@xref{textout_centre_ex}.@*
@xref{textprintf_centre_ex}.@*
@xref{triangle}.@*
@xref{vsync}.@*
@node exscn3d, exzbuf, exstars, Available
@subsection exscn3d
@ftable @asis
@item @t{Example exscn3d}
This program demonstrates how to use scanline sorting algorithm
in Allegro (create_scene, clear_scene, ... functions). It
also provides an example of how to use the 3D clipping
function. The example consists of a flyby through a lot of
rotating 3d cubes.


@end ftable
See also:@*
@xref{BITMAP}.@*
@xref{END_OF_FUNCTION}.@*
@xref{END_OF_MAIN}.@*
@xref{LOCK_FUNCTION}.@*
@xref{LOCK_VARIABLE}.@*
@xref{MATRIX_f}.@*
@xref{PALETTE}.@*
@xref{POLYTYPE_GCOL}.@*
@xref{SCREEN_W, SCREEN_H}.@*
@xref{SCREEN_W}.@*
@xref{V3D_f}.@*
@xref{allegro_error}.@*
@xref{allegro_exit}.@*
@xref{allegro_init}.@*
@xref{allegro_message}.@*
@xref{apply_matrix, apply_matrix_f}.@*
@xref{bitmap_color_depth}.@*
@xref{blit}.@*
@xref{clear_bitmap}.@*
@xref{clear_scene}.@*
@xref{clip3d_f}.@*
@xref{create_bitmap}.@*
@xref{create_scene}.@*
@xref{desktop_palette}.@*
@xref{destroy_bitmap}.@*
@xref{destroy_scene}.@*
@xref{font}.@*
@xref{get_rotation_matrix, get_rotation_matrix_f}.@*
@xref{get_translation_matrix, get_translation_matrix_f}.@*
@xref{gfx_mode_select_ex}.@*
@xref{install_int}.@*
@xref{install_keyboard}.@*
@xref{install_mouse}.@*
@xref{install_timer}.@*
@xref{key}.@*
@xref{matrix_mul, matrix_mul_f}.@*
@xref{palette_color}.@*
@xref{persp_project, persp_project_f}.@*
@xref{polygon_z_normal, polygon_z_normal_f}.@*
@xref{render_scene}.@*
@xref{scene_polygon3d, scene_polygon3d_f}.@*
@xref{screen}.@*
@xref{set_color_depth}.@*
@xref{set_gfx_mode}.@*
@xref{set_palette}.@*
@xref{set_projection_viewport}.@*
@xref{textprintf_ex}.@*
@node exzbuf, exscroll, exscn3d, Available
@subsection exzbuf
@ftable @asis
@item @t{Example exzbuf}
This program demonstrates how to use Z-buffered polygons and
floating point 3D math routines. It also provides a simple
way to compute fps (frames per second) using a timer. After
selecting a screen resolution through the standard GUI dialog,
the example shows two 3D cubes rotating and intersecting each
other. Rather than having full polygons incorrectly overlap
other polygons due to per-polygon sorting, each pixel is drawn
at the correct depth.

@end ftable
See also:@*
@xref{BITMAP}.@*
@xref{END_OF_FUNCTION}.@*
@xref{END_OF_MAIN}.@*
@xref{LOCK_FUNCTION}.@*
@xref{LOCK_VARIABLE}.@*
@xref{MATRIX_f}.@*
@xref{PALETTE}.@*
@xref{POLYTYPE_GCOL}.@*
@xref{SCREEN_W, SCREEN_H}.@*
@xref{SCREEN_W}.@*
@xref{V3D_f}.@*
@xref{ZBUFFER}.@*
@xref{allegro_error}.@*
@xref{allegro_exit}.@*
@xref{allegro_init}.@*
@xref{allegro_message}.@*
@xref{apply_matrix, apply_matrix_f}.@*
@xref{bitmap_color_depth}.@*
@xref{blit}.@*
@xref{clear_bitmap}.@*
@xref{clear_zbuffer}.@*
@xref{create_bitmap}.@*
@xref{create_zbuffer}.@*
@xref{desktop_palette}.@*
@xref{destroy_bitmap}.@*
@xref{destroy_zbuffer}.@*
@xref{font}.@*
@xref{get_transformation_matrix_f}.@*
@xref{gfx_mode_select_ex}.@*
@xref{install_int}.@*
@xref{install_keyboard}.@*
@xref{install_mouse}.@*
@xref{install_timer}.@*
@xref{keypressed}.@*
@xref{palette_color}.@*
@xref{persp_project, persp_project_f}.@*
@xref{polygon_z_normal, polygon_z_normal_f}.@*
@xref{quad3d, quad3d_f}.@*
@xref{readkey}.@*
@xref{screen}.@*
@xref{set_color_depth}.@*
@xref{set_gfx_mode}.@*
@xref{set_palette}.@*
@xref{set_palette_range}.@*
@xref{set_projection_viewport}.@*
@xref{set_zbuffer}.@*
@xref{textprintf_ex}.@*
@xref{vsync}.@*
@node exscroll, ex3buf, exzbuf, Available
@subsection exscroll
@ftable @asis
@item @t{Example exscroll}
This program demonstrates how to use hardware scrolling.
The scrolling should work on anything that supports virtual
screens larger than the physical screen.

@end ftable
See also:@*
@xref{BITMAP}.@*
@xref{END_OF_MAIN}.@*
@xref{RGB}.@*
@xref{SCREEN_W, SCREEN_H}.@*
@xref{SCREEN_W}.@*
@xref{acquire_bitmap}.@*
@xref{allegro_init}.@*
@xref{allegro_message}.@*
@xref{clear_keybuf}.@*
@xref{create_sub_bitmap}.@*
@xref{desktop_palette}.@*
@xref{destroy_bitmap}.@*
@xref{install_keyboard}.@*
@xref{keypressed}.@*
@xref{rectfill}.@*
@xref{release_bitmap}.@*
@xref{screen}.@*
@xref{scroll_screen}.@*
@xref{set_color}.@*
@xref{set_gfx_mode}.@*
@xref{set_palette}.@*
@xref{vline}.@*
@node ex3buf, ex12bit, exscroll, Available
@subsection ex3buf
@ftable @asis
@item @t{Example ex3buf}
This program demonstrates the use of triple buffering. Several
triangles are displayed rotating and bouncing on the screen
until you press a key. Note that on some platforms you
can't get real hardware triple buffering.  The Allegro code
remains the same, but most likely the graphic driver will
emulate it. Unfortunately, in these cases you can't expect
the animation to be completely smooth and flicker free.

@end ftable
See also:@*
@xref{BITMAP}.@*
@xref{END_OF_MAIN}.@*
@xref{SCREEN_W, SCREEN_H}.@*
@xref{SCREEN_W}.@*
@xref{acquire_bitmap}.@*
@xref{allegro_error}.@*
@xref{allegro_init}.@*
@xref{allegro_message}.@*
@xref{clear_bitmap}.@*
@xref{clear_keybuf}.@*
@xref{create_video_bitmap}.@*
@xref{desktop_palette}.@*
@xref{destroy_bitmap}.@*
@xref{enable_triple_buffer}.@*
@xref{fixcos}.@*
@xref{fixed}.@*
@xref{fixmul}.@*
@xref{fixsin}.@*
@xref{fixtoi}.@*
@xref{font}.@*
@xref{gfx_capabilities}.@*
@xref{install_keyboard}.@*
@xref{install_mouse}.@*
@xref{install_timer}.@*
@xref{itofix}.@*
@xref{keypressed}.@*
@xref{poll_scroll}.@*
@xref{release_bitmap}.@*
@xref{request_video_bitmap}.@*
@xref{screen}.@*
@xref{set_gfx_mode}.@*
@xref{set_palette}.@*
@xref{textout_ex}.@*
@xref{triangle}.@*
@xref{ustrzcpy}.@*
@node ex12bit, exaccel, ex3buf, Available
@subsection ex12bit
@ftable @asis
@item @t{Example ex12bit}
This program sets up a 12-bit mode on any 8-bit card, by
setting up a 256-colour palette that will fool the eye into
grouping two 8-bit pixels into one 12-bit pixel. In order
to do this, you make your 256-colour palette with all the
combinations of blue and green, assuming green ranges from 0-15
and blue from 0-14. This takes up 16x15=240 colours. This
leaves 16 colours to use as red (red ranges from 0-15).
Then you put your green/blue in one pixel, and your red in
the pixel next to it. The eye gets fooled into thinking it's
all one pixel.

The example starts setting a normal 256 color mode, and
construct a special palette for it. But then comes the trick:
you need to write to a set of two adjacent pixels to form a
single 12 bit dot. Two eight bit pixels is the same as one 16
bit pixel, so after setting the video mode you need to hack
the screen bitmap about, halving the width and changing it
to use the 16 bit drawing code. Then, once you have packed a
color into the correct format (using the makecol12() function
below), any of the normal Allegro drawing functions can be
used with this 12 bit display!

Things to note:


@itemize @bullet
@item The horizontal width is halved, so you get resolutions
like 320x480, 400x600, and 512x768.

@item Because each dot is spread over two actual pixels, the
display will be darker than in a normal video mode.

@item Any bitmap data will obviously need converting to the
correct 12 bit format: regular 15 or 16 bit images won't
display correctly...

@item Although this works like a truecolor mode, it is
actually using a 256 color palette, so palette fades are
still possible!

@item This code only works in linear screen modes (don't try
Mode-X).@end itemize


@end ftable
See also:@*
@xref{BITMAP}.@*
@xref{END_OF_MAIN}.@*
@xref{MATRIX}.@*
@xref{PALETTE}.@*
@xref{RGB}.@*
@xref{allegro_error}.@*
@xref{allegro_init}.@*
@xref{allegro_message}.@*
@xref{apply_matrix}.@*
@xref{blit}.@*
@xref{circle}.@*
@xref{clear_bitmap}.@*
@xref{clear_keybuf}.@*
@xref{clear_to_color}.@*
@xref{create_bitmap}.@*
@xref{create_bitmap_ex}.@*
@xref{destroy_bitmap}.@*
@xref{ellipsefill}.@*
@xref{fade_out}.@*
@xref{fixcos}.@*
@xref{fixed}.@*
@xref{fixsin}.@*
@xref{fixtoi}.@*
@xref{font}.@*
@xref{get_rotation_matrix}.@*
@xref{getpixel}.@*
@xref{install_keyboard}.@*
@xref{itofix}.@*
@xref{keypressed}.@*
@xref{line}.@*
@xref{makecol}.@*
@xref{masked_blit}.@*
@xref{putpixel}.@*
@xref{screen}.@*
@xref{set_clip_rect}.@*
@xref{set_color}.@*
@xref{set_gfx_mode}.@*
@xref{set_palette}.@*
@xref{text_height}.@*
@xref{text_length}.@*
@xref{textout_ex}.@*
@xref{textprintf_ex}.@*
@node exaccel, exspline, ex12bit, Available
@subsection exaccel
@ftable @asis
@item @t{Example exaccel}
This program demonstrates how to use an offscreen part of
the video memory to store source graphics for a hardware
accelerated graphics driver. The example loads the `mysha.pcx'
file and then blits it several times on the screen. Depending
on whether you have enough video memory and Allegro supports
the hardware acceleration features of your card, your success
running this example may be none at all, sluggish performance
due to software emulation, or flicker free smooth hardware
accelerated animation.

@end ftable
See also:@*
@xref{BITMAP}.@*
@xref{END_OF_MAIN}.@*
@xref{PALETTE}.@*
@xref{SCREEN_W, SCREEN_H}.@*
@xref{SCREEN_W}.@*
@xref{acquire_bitmap}.@*
@xref{allegro_error}.@*
@xref{allegro_init}.@*
@xref{allegro_message}.@*
@xref{blit}.@*
@xref{clear_bitmap}.@*
@xref{create_video_bitmap}.@*
@xref{destroy_bitmap}.@*
@xref{font}.@*
@xref{gfx_capabilities}.@*
@xref{install_keyboard}.@*
@xref{install_timer}.@*
@xref{keypressed}.@*
@xref{load_bitmap}.@*
@xref{readkey}.@*
@xref{release_bitmap}.@*
@xref{replace_filename}.@*
@xref{screen}.@*
@xref{set_gfx_mode}.@*
@xref{set_palette}.@*
@xref{show_video_bitmap}.@*
@xref{textout_ex}.@*
@xref{textprintf_ex}.@*
@node exspline, exsyscur, exaccel, Available
@subsection exspline
@ftable @asis
@item @t{Example exspline}
This program demonstrates the use of spline curves to create smooth
paths connecting a number of node points. This can be useful for
constructing realistic motion and animations.

The technique is to connect the series of guide points p1..p(n) with
spline curves from p1-p2, p2-p3, etc. Each spline must pass though
both of its guide points, so they must be used as the first and fourth
of the spline control points. The fun bit is coming up with sensible
values for the second and third spline control points, such that the
spline segments will have equal gradients where they meet. I came
up with the following solution:

For each guide point p(n), calculate the desired tangent to the curve
at that point. I took this to be the vector p(n-1) -> p(n+1), which
can easily be calculated with the inverse tangent function, and gives
decent looking results. One implication of this is that two dummy
guide points are needed at each end of the curve, which are used in
the tangent calculations but not connected to the set of splines.

Having got these tangents, it becomes fairly easy to calculate the
spline control points. For a spline between guide points p(a) and
p(b), the second control point should lie along the positive tangent
from p(a), and the third control point should lie along the negative
tangent from p(b). How far they are placed along these tangents
controls the shape of the curve: I found that applying a 'curviness'
scaling factor to the distance between p(a) and p(b) works well.

One thing to note about splines is that the generated points are
not all equidistant. Instead they tend to bunch up nearer to the
ends of the spline, which means you will need to apply some fudges
to get an object to move at a constant speed. On the other hand,
in situations where the curve has a noticeable change of direction
at each guide point, the effect can be quite nice because it makes
the object slow down for the curve.

@end ftable
See also:@*
@xref{END_OF_MAIN}.@*
@xref{SCREEN_W}.@*
@xref{acquire_screen}.@*
@xref{alert}.@*
@xref{allegro_error}.@*
@xref{allegro_init}.@*
@xref{allegro_message}.@*
@xref{calc_spline}.@*
@xref{circlefill}.@*
@xref{clear_keybuf}.@*
@xref{clear_to_color}.@*
@xref{desktop_palette}.@*
@xref{fixatan2}.@*
@xref{fixcos}.@*
@xref{fixed}.@*
@xref{fixmul}.@*
@xref{fixsin}.@*
@xref{fixsqrt}.@*
@xref{fixtof}.@*
@xref{fixtoi}.@*
@xref{font}.@*
@xref{ftofix}.@*
@xref{install_keyboard}.@*
@xref{install_mouse}.@*
@xref{install_timer}.@*
@xref{itofix}.@*
@xref{key}.@*
@xref{keypressed}.@*
@xref{line}.@*
@xref{makecol}.@*
@xref{mouse_x, mouse_b}.@*
@xref{mouse_x}.@*
@xref{mouse_x, mouse_y}.@*
@xref{palette_color}.@*
@xref{poll_mouse}.@*
@xref{readkey}.@*
@xref{release_screen}.@*
@xref{screen}.@*
@xref{set_gfx_mode}.@*
@xref{set_palette}.@*
@xref{show_mouse}.@*
@xref{spline}.@*
@xref{textout_centre_ex}.@*
@xref{textprintf_centre_ex}.@*
@xref{textprintf_ex}.@*
@xref{vsync}.@*
@xref{xor_mode}.@*
@node exsyscur, exupdate, exspline, Available
@subsection exsyscur
@ftable @asis
@item @t{Example exsyscur}
This program demonstrates the use of hardware accelerated mouse cursors.

@end ftable
See also:@*
@xref{END_OF_MAIN}.@*
@xref{SCREEN_W, SCREEN_H}.@*
@xref{SCREEN_W}.@*
@xref{allegro_error}.@*
@xref{allegro_init}.@*
@xref{allegro_message}.@*
@xref{clear_to_color}.@*
@xref{enable_hardware_cursor}.@*
@xref{font}.@*
@xref{gfx_capabilities}.@*
@xref{install_keyboard}.@*
@xref{install_mouse}.@*
@xref{install_timer}.@*
@xref{makecol}.@*
@xref{readkey}.@*
@xref{screen}.@*
@xref{select_mouse_cursor}.@*
@xref{set_gfx_mode}.@*
@xref{show_mouse}.@*
@xref{text_height}.@*
@xref{textprintf_centre_ex}.@*
@node exupdate, exswitch, exsyscur, Available
@subsection exupdate
@ftable @asis
@item @t{Example exupdate}
This program demonstrates how to support double buffering,
page flipping, and triple buffering as options within a single
program, and how to make things run at a constant rate no
matter what the speed of your computer. You have to use this
example from the command line to specify as first parameter a
number which represents the type of video update you want: 1
for double buffering with memory bitmaps, 2 for page flipping,
3 for triple buffering and 4 for double buffering with system
bitmaps. After this, a dialog allows you to select a screen
resolution and finally you will see a kaleidoscopic animation,
along with a frames per second counter on the top left of
the screen.

@end ftable
See also:@*
@xref{BITMAP}.@*
@xref{END_OF_FUNCTION}.@*
@xref{END_OF_MAIN}.@*
@xref{LOCK_FUNCTION}.@*
@xref{LOCK_VARIABLE}.@*
@xref{PALETTE}.@*
@xref{SCREEN_W, SCREEN_H}.@*
@xref{SCREEN_W}.@*
@xref{acquire_bitmap}.@*
@xref{allegro_error}.@*
@xref{allegro_init}.@*
@xref{allegro_message}.@*
@xref{bitmap_color_depth}.@*
@xref{blit}.@*
@xref{clear_bitmap}.@*
@xref{create_bitmap}.@*
@xref{create_system_bitmap}.@*
@xref{create_video_bitmap}.@*
@xref{desktop_palette}.@*
@xref{destroy_bitmap}.@*
@xref{enable_triple_buffer}.@*
@xref{fixcos}.@*
@xref{fixed}.@*
@xref{fixmul}.@*
@xref{fixsin}.@*
@xref{fixtoi}.@*
@xref{font}.@*
@xref{ftofix}.@*
@xref{generate_332_palette}.@*
@xref{gfx_capabilities}.@*
@xref{gfx_mode_select_ex}.@*
@xref{install_int_ex}.@*
@xref{install_keyboard}.@*
@xref{install_mouse}.@*
@xref{install_timer}.@*
@xref{keypressed}.@*
@xref{line}.@*
@xref{makecol}.@*
@xref{poll_scroll}.@*
@xref{release_bitmap}.@*
@xref{request_video_bitmap}.@*
@xref{screen}.@*
@xref{set_color_depth}.@*
@xref{set_gfx_mode}.@*
@xref{set_palette}.@*
@xref{show_video_bitmap}.@*
@xref{textout_ex}.@*
@xref{textprintf_ex}.@*
@xref{triangle}.@*
@xref{vsync}.@*
@xref{xor_mode}.@*
@node exswitch, exstream, exupdate, Available
@subsection exswitch
@ftable @asis
@item @t{Example exswitch}
This program shows how to control the console switching mode, and
let your program run in the background. These functions don't apply
to every platform and driver, for example you can't control the
switching mode from a DOS program.

Yes, I know the fractal drawing is very slow: that's the point!
This is so you can easily check whether it goes on working in the
background after you switch away from the app.

Depending on the type of selected switching mode, you will see
whether the contents of the screen are preserved or not.

@end ftable
See also:@*
@xref{BITMAP}.@*
@xref{END_OF_FUNCTION}.@*
@xref{END_OF_MAIN}.@*
@xref{LOCK_FUNCTION}.@*
@xref{LOCK_VARIABLE}.@*
@xref{PALETTE}.@*
@xref{SCREEN_W, SCREEN_H}.@*
@xref{SCREEN_W}.@*
@xref{acquire_bitmap}.@*
@xref{acquire_screen}.@*
@xref{allegro_error}.@*
@xref{allegro_exit}.@*
@xref{allegro_init}.@*
@xref{allegro_message}.@*
@xref{bitmap_color_depth}.@*
@xref{blit}.@*
@xref{clear_to_color}.@*
@xref{create_sub_bitmap}.@*
@xref{desktop_palette}.@*
@xref{destroy_bitmap}.@*
@xref{font}.@*
@xref{get_display_switch_mode}.@*
@xref{gfx_mode_select_ex}.@*
@xref{install_int}.@*
@xref{install_keyboard}.@*
@xref{install_mouse}.@*
@xref{install_timer}.@*
@xref{keypressed}.@*
@xref{makecol}.@*
@xref{palette_color}.@*
@xref{putpixel}.@*
@xref{readkey}.@*
@xref{rectfill}.@*
@xref{release_bitmap}.@*
@xref{release_screen}.@*
@xref{screen}.@*
@xref{set_color_depth}.@*
@xref{set_display_switch_callback}.@*
@xref{set_display_switch_mode}.@*
@xref{set_gfx_mode}.@*
@xref{set_palette}.@*
@xref{textout_centre_ex}.@*
@xref{textprintf_centre_ex}.@*
@node exstream, expackf, exswitch, Available
@subsection exstream
@ftable @asis
@item @t{Example exstream}
This program shows how to use the audio stream functions to
transfer large blocks of sample data to the sound card. In
this case, the sample data is generated during runtime,
and the resulting sound reminds of a car engine when you
are accelerating.

@end ftable
See also:@*
@xref{AUDIOSTREAM}.@*
@xref{END_OF_MAIN}.@*
@xref{SCREEN_W, SCREEN_H}.@*
@xref{SCREEN_W}.@*
@xref{allegro_error}.@*
@xref{allegro_init}.@*
@xref{allegro_message}.@*
@xref{clear_to_color}.@*
@xref{desktop_palette}.@*
@xref{font}.@*
@xref{free_audio_stream_buffer}.@*
@xref{get_audio_stream_buffer}.@*
@xref{install_keyboard}.@*
@xref{install_sound}.@*
@xref{install_timer}.@*
@xref{keypressed}.@*
@xref{makecol}.@*
@xref{play_audio_stream}.@*
@xref{readkey}.@*
@xref{screen}.@*
@xref{set_gfx_mode}.@*
@xref{set_palette}.@*
@xref{stop_audio_stream}.@*
@xref{textprintf_centre_ex}.@*
@xref{voice_start}.@*
@xref{voice_stop}.@*
@node expackf, , exstream, Available
@subsection expackf
@ftable @asis
@item @t{Example expackf}
This program demonstrates the use of the packfile functions, with some
simple tests.

The first test uses the standard packfile functions to transfer a
bitmap file into a block of memory, then reads the bitmap out of the
block of memory, using a custom packfile vtable.

The second test reads in a bitmap with another custom packfile
vtable, which uses libc's file stream functions.

The third test demonstrates seeking with a custom vtable.

The fourth test reads two bitmaps, and dumps them back into a
single file, using a custom vtable again.



@end ftable
See also:@*
@xref{ASSERT}.@*
@xref{BITMAP}.@*
@xref{END_OF_MAIN}.@*
@xref{PACKFILE}.@*
@xref{PACKFILE_VTABLE}.@*
@xref{SCREEN_W, SCREEN_H}.@*
@xref{SCREEN_W}.@*
@xref{alert}.@*
@xref{allegro_error}.@*
@xref{allegro_init}.@*
@xref{allegro_message}.@*
@xref{blit}.@*
@xref{clear_bitmap}.@*
@xref{destroy_bitmap}.@*
@xref{file_size_ex}.@*
@xref{font}.@*
@xref{install_keyboard}.@*
@xref{key}.@*
@xref{load_bmp_pf}.@*
@xref{load_pcx}.@*
@xref{load_pcx_pf}.@*
@xref{load_tga_pf}.@*
@xref{pack_fclose}.@*
@xref{pack_fopen}.@*
@xref{pack_fopen_vtable}.@*
@xref{pack_fread}.@*
@xref{pack_fseek}.@*
@xref{readkey}.@*
@xref{save_bmp_pf}.@*
@xref{save_tga_pf}.@*
@xref{screen}.@*
@xref{set_color_depth}.@*
@xref{set_gfx_mode}.@*
@xref{text_height}.@*
@xref{textprintf_centre_ex}.@*
@xref{textprintf_ex}.@*
@node Tools, Additional, Available, Top
@chapter Tools
@menu
* Additional::              Additional programs included with Allegro
@end menu
@node Additional, Community, Tools, Tools
@section Additional programs included with Allegro

Allegro comes with several useful utility programs. They are currently
documented separately. Refer to the HTML documentation (including CHM
and devhelp) of Allegro which includes all the documents, or the single
plain text versions of these documents (makedoc.txt, grabber.txt, dat.txt,
dat2s.txt, dat2c.txt).



@node Community, Conclusion, Additional, Top
@chapter Community

Allegro was originally created by Shawn Hargreaves. Published sometime between
1994 and 1995, it was just a simple lib for himself. At that time, many people
were switching from Borland C to DJGPP and looking for a decent graphics
library. Allegro was the first reasonably complete one to show up, so it
attracted enough interest to keep growing, and a little contribution here, and
some more encouragement there made it all light up like fire.

Some time after the latest 3.x stable release, though, Shawn was flooded with
Allegro tasks and Real Life (TM) work, and chose the latter to focus his
energies on. While this somehow stalled Allegro's development, it also
attracted a lot of people who wanted Allegro to live longer. Also, by that
time other people had started to work on Windows and Unix ports of Allegro,
which suggested that Allegro had the potential to survive its only decaying
main platform (DOS).

The current situation is that Shawn still keeps watching Allegro's progress
from time to time, but is not involved with development any more. The
community that grew over the years when Shawn was in charge of everything has
stepped forward to continue improving Allegro. Transformed into a meritocratic
community, users keep sending bug reports to the mailing lists, developers
around the world keep sending patches to fix them, and a few carefully chosen
have write access to the SVN repository, from which releases are built every
now and then.

But, who decides when a build is stable enough? Who decides when somebody is
granted write access to the SVN? Who chooses the lesser of two evils patching
some obscure bug? And more importantly, who decides what's Allegro's mascot?
For all these reasons, the community decided to replace Shawn's position with
the Allegro Dictator.

In republican Rome, political power was with the Senate and the Consuls.
However, if it was necessary that decisions were made very quickly then the
senate could appoint a Dictator. The Dictator was appointed for a specified
duration or charged with a specific task, after which he was expected to
surrender his authority back to the Senate. Nowadays, the Allegro Dictator is
a benevolent figure and rarely has to use his overwhelming fist of iron to put
order into chaos.

The truth is that the Allegro Dictator is usually the person in charge of
doing releases and all that unsexy work inside the community, like pestering
users to test some obscure bugfix or rejecting incomplete patches.

Past Allegro dictators have been: Shawn Hargreaves, George Foot, Peter Wang
and Eric Botcazou. At the moment of writing this, Evert Glebbeek is the
active Allegro Dictator. Should you want to change Allegro in some illogical
way, he's the guy you have to send your bribes too :-)



@node Conclusion, Index, Community, Top
@chapter Conclusion

All good things must come to an end. Writing documentation is not a good 
thing, though, and that means it goes on for ever. There is always something 
we've forgotten to explain, or some essential detail we've left out, but for
now you will have to make do with this. Feel free to ask if you can't figure 
something out.

Enjoy. We hope you find some of this stuff useful.


By Shawn Hargreaves and the Allegro development team.

http://alleg.sourceforge.net/



@ifinfo
@node Index, , Conclusion, Top
@chapter Index

@menu
* 256-color transparency::
* _getpixel::
* _putpixel::
* _set_color::
* _ustrdup::
* acquire_bitmap::
* acquire_screen::
* active_dialog::
* active_menu::
* add_clip_rect::
* adjust_sample::
* al_assert::
* al_ffblk::
* al_ffblk_get_size::
* al_findclose::
* al_findfirst::
* al_findnext::
* AL_ID::
* al_trace::
* alert::
* alert3::
* allegro_404_char::
* ALLEGRO_DATE::
* ALLEGRO_DATE_STR::
* allegro_error::
* allegro_exit::
* allegro_icon::
* allegro_id::
* allegro_init::
* allegro_message::
* ALLEGRO_SUB_VERSION::
* ALLEGRO_VERSION::
* ALLEGRO_VERSION_STR::
* ALLEGRO_WIP_VERSION::
* allocate_voice::
* append_filename::
* apply_matrix::
* apply_quat::
* arc::
* ASSERT::
* AUDIOSTREAM::
* bestfit_color::
* BITMAP::
* bitmap_color_depth::
* bitmap_mask_color::
* black_palette::
* blit::
* blit_from_hdc::
* blit_to_hdc::
* bmp_read_line::
* bmp_unwrite_line::
* bmp_write_line::
* broadcast_dialog_message::
* calc_spline::
* calibrate_joystick::
* calibrate_joystick_name::
* canonicalize_filename::
* centre_dialog::
* check_cpu::
* circle::
* circlefill::
* clear_bitmap::
* clear_keybuf::
* clear_scene::
* clear_to_color::
* clear_zbuffer::
* clip3d::
* clip3d_f::
* close_fli::
* COLOR_MAP::
* color_map::
* COMPILED_SPRITE::
* config_is_hooked::
* convert_bitmap_to_hbitmap::
* convert_hbitmap_to_bitmap::
* convert_hpalette_to_palette::
* convert_palette_to_hpalette::
* cpu_capabilities::
* cpu_family::
* cpu_model::
* cpu_vendor::
* create_bitmap::
* create_bitmap_ex::
* create_blender_table::
* create_color_table::
* create_datafile_index::
* create_light_table::
* create_lzss_pack_data::
* create_lzss_unpack_data::
* create_rgb_table::
* create_sample::
* create_scene::
* create_sub_bitmap::
* create_sub_zbuffer::
* create_system_bitmap::
* create_trans_table::
* create_video_bitmap::
* create_zbuffer::
* cross_product::
* Custom datafile objects::
* d_bitmap_proc::
* d_box_proc::
* d_button_proc::
* d_check_proc::
* d_clear_proc::
* d_edit_proc::
* d_icon_proc::
* d_keyboard_proc::
* d_list_proc::
* d_menu_proc::
* d_radio_proc::
* d_slider_proc::
* d_text_list_proc::
* d_text_proc::
* d_textbox_proc::
* d_yield_proc::
* DAT_ID::
* DATAFILE::
* deallocate_voice::
* default_palette::
* delete_file::
* desktop_color_depth::
* desktop_palette::
* destroy_bitmap::
* destroy_compiled_sprite::
* destroy_datafile_index::
* destroy_font::
* destroy_gfx_mode_list::
* destroy_midi::
* destroy_rle_sprite::
* destroy_sample::
* destroy_scene::
* destroy_zbuffer::
* detect_digi_driver::
* detect_midi_driver::
* DIALOG::
* dialog_message::
* DIALOG_PLAYER::
* DIGI_*/BeOS::
* DIGI_*/DOS::
* DIGI_*/MacOSX::
* DIGI_*/QNX::
* DIGI_*/Unix::
* DIGI_*/Windows::
* digi_recorder::
* disable_hardware_cursor::
* do_arc::
* do_circle::
* do_dialog::
* do_ellipse::
* do_line::
* do_menu::
* do_uconvert::
* DOS integration routines::
* dot_product::
* draw_character_ex::
* draw_compiled_sprite::
* draw_gouraud_sprite::
* draw_lit_rle_sprite::
* draw_lit_sprite::
* draw_rle_sprite::
* draw_sprite::
* draw_sprite_v_flip::
* draw_to_hdc::
* draw_trans_rle_sprite::
* draw_trans_sprite::
* drawing_mode::
* ellipse::
* ellipsefill::
* empty_string::
* enable_hardware_cursor::
* enable_triple_buffer::
* END_OF_FUNCTION::
* END_OF_MAIN::
* ex12bit::
* ex3buf::
* ex3d::
* exaccel::
* exalpha::
* exbitmap::
* exblend::
* excamera::
* excolmap::
* exconfig::
* excustom::
* exdata::
* exdbuf::
* exexedat::
* exfixed::
* exflame::
* exflip::
* exfont::
* exgui::
* exhello::
* exists::
* exjoy::
* exkeys::
* exlights::
* exmem::
* exmidi::
* exmouse::
* expackf::
* expal::
* expat::
* exquat::
* exrgbhsv::
* exsample::
* exscale::
* exscn3d::
* exscroll::
* exshade::
* exspline::
* exsprite::
* exstars::
* exstream::
* exswitch::
* exsyscur::
* extimer::
* extract_font_range::
* extrans::
* extruec::
* exunicod::
* exupdate::
* exxfade::
* exzbuf::
* fade_from::
* fade_from_range::
* fade_in::
* fade_in_range::
* fade_interpolate::
* fade_out::
* fade_out_range::
* fastline::
* file_exists::
* file_select_ex::
* file_size_ex::
* file_time::
* find_allegro_resource::
* find_datafile_object::
* find_dialog_focus::
* Fix class::
* fix_filename_case::
* fix_filename_slashes::
* fixacos::
* fixadd::
* fixasin::
* fixatan::
* fixatan2::
* fixceil::
* fixcos::
* fixdiv::
* fixed::
* Fixed point trig::
* fixfloor::
* fixhypot::
* fixmul::
* fixsin::
* fixsqrt::
* fixsub::
* fixtan::
* fixtof::
* fixtoi::
* fixtorad_r::
* fixup_datafile::
* fli_bitmap::
* fli_bmp_dirty_from::
* fli_frame::
* fli_pal_dirty_from::
* fli_palette::
* fli_timer::
* floodfill::
* flush_config_file::
* FONT::
* font::
* font_has_alpha::
* for_each_file_ex::
* free_audio_stream_buffer::
* free_config_entries::
* free_lzss_pack_data::
* free_lzss_unpack_data::
* freeze_mouse_flag::
* ftofix::
* GDI routines::
* generate_332_palette::
* generate_optimized_palette::
* get_align_matrix::
* get_align_matrix_f::
* get_audio_stream_buffer::
* get_camera_matrix::
* get_camera_matrix_f::
* get_clip_rect::
* get_clip_state::
* get_color::
* get_color_conversion::
* get_color_depth::
* get_compiled_sprite::
* get_config_argv::
* get_config_float::
* get_config_hex::
* get_config_id::
* get_config_int::
* get_config_string::
* get_config_text::
* get_datafile_property::
* get_desktop_resolution::
* get_display_switch_mode::
* get_executable_name::
* get_extension::
* get_filename::
* get_font_range_begin::
* get_font_range_end::
* get_font_ranges::
* get_gfx_mode_list::
* get_hardware_volume::
* get_midi_length::
* get_mixer_bits::
* get_mixer_buffer_length::
* get_mixer_channels::
* get_mixer_frequency::
* get_mixer_quality::
* get_mixer_voices::
* get_mouse_mickeys::
* get_palette::
* get_palette_range::
* get_refresh_rate::
* get_rle_sprite::
* get_rotation_matrix::
* get_rotation_quat::
* get_scaling_matrix::
* get_sound_input_cap_bits::
* get_sound_input_cap_parm::
* get_sound_input_cap_rate::
* get_sound_input_cap_stereo::
* get_transformation_matrix::
* get_transformation_matrix_f::
* get_translation_matrix::
* get_uformat::
* get_vector_rotation_matrix::
* get_vector_rotation_quat::
* get_volume::
* get_x_rotate_matrix::
* get_x_rotate_quat::
* get_y_rotate_matrix::
* get_z_rotate_matrix::
* geta32::
* getpixel::
* getr::
* getr8::
* getr_depth::
* GFX_*/BeOS::
* GFX_*/DOS::
* GFX_*/Linux::
* GFX_*/MacOSX::
* GFX_*/QNX::
* GFX_*/Windows::
* GFX_*/X::
* gfx_capabilities::
* GFX_MODE::
* GFX_MODE_LIST::
* gfx_mode_select::
* gfx_mode_select_ex::
* gfx_mode_select_filter::
* grab_font_from_bitmap::
* GUI font::
* GUI menus::
* GUI variables::
* gui_fg_color::
* gui_font_baseline::
* gui_get_screen::
* gui_menu_draw_menu::
* gui_mg_color::
* gui_mouse_focus::
* gui_mouse_x::
* gui_set_screen::
* gui_shadow_box_proc::
* gui_strlen::
* gui_textout_ex::
* hline::
* hook_config_section::
* hsv_to_rgb::
* i_love_bill::
* identity_matrix::
* identity_quat::
* init_dialog::
* init_menu::
* initialise_joystick::
* install_allegro::
* install_int::
* install_int_ex::
* install_joystick::
* install_keyboard::
* install_keyboard_hooks::
* install_mouse::
* install_param_int::
* install_param_int_ex::
* install_sound::
* install_sound_input::
* install_timer::
* is_color_font::
* is_compatible_font::
* is_inside_bitmap::
* is_linear_bitmap::
* is_memory_bitmap::
* is_mono_font::
* is_planar_bitmap::
* is_relative_filename::
* is_same_bitmap::
* is_screen_bitmap::
* is_sub_bitmap::
* is_system_bitmap::
* is_trans_font::
* is_video_bitmap::
* is_windowed_mode::
* itofix::
* joy::
* JOY_TYPE_*/DOS::
* JOY_TYPE_*/Linux::
* JOY_TYPE_*/Windows::
* JOYSTICK_AXIS_INFO::
* JOYSTICK_BUTTON_INFO::
* JOYSTICK_INFO::
* JOYSTICK_STICK_INFO::
* key::
* key_led_flag::
* key_shifts::
* keyboard_callback::
* keyboard_lowlevel_callback::
* keyboard_needs_poll::
* keyboard_ucallback::
* keypressed::
* line::
* list_config_entries::
* list_config_sections::
* load_bios_font::
* load_bitmap::
* load_bitmap_font::
* load_bmp::
* load_bmp_pf::
* load_dat_font::
* load_datafile::
* load_datafile_callback::
* load_datafile_object::
* load_datafile_object_indexed::
* load_font::
* load_grx_font::
* load_grx_or_bios_font::
* load_ibk::
* load_joystick_data::
* load_lbm::
* load_midi::
* load_midi_patches::
* load_pcx::
* load_pcx_pf::
* load_sample::
* load_tga::
* load_tga_pf::
* load_txt_font::
* load_voc::
* load_voc_pf::
* load_wav::
* load_wav_pf::
* lock_bitmap::
* LOCK_FUNCTION::
* lock_midi::
* lock_sample::
* LOCK_VARIABLE::
* LZSS_PACK_DATA::
* lzss_read::
* LZSS_UNPACK_DATA::
* lzss_write::
* make_absolute_filename::
* make_relative_filename::
* make_trans_font::
* MAKE_VERSION::
* makeacol::
* makeacol32::
* makecol::
* makecol15_dither::
* makecol8::
* makecol_depth::
* MASK_COLOR_8::
* masked_blit::
* masked_stretch_blit::
* MATRIX::
* MATRIX_f::
* matrix_mul::
* matrix_to_quat::
* MENU::
* MENU_PLAYER::
* merge_fonts::
* MIDI::
* MIDI_*/BeOS::
* MIDI_*/DOS::
* MIDI_*/MacOSX::
* MIDI_*/QNX::
* MIDI_*/Unix::
* MIDI_*/Windows::
* midi_loop_start::
* midi_msg_callback::
* midi_out::
* midi_pause::
* midi_pos::
* midi_recorder::
* midi_resume::
* midi_seek::
* midi_time::
* More on banked direct memory access::
* mouse_callback::
* mouse_needs_poll::
* mouse_sprite::
* mouse_x::
* need_uconvert::
* next_fli_frame::
* normalize_vector::
* num_joysticks::
* object_message::
* offer_focus::
* open_fli::
* os_multitasking::
* os_type::
* os_version::
* override_config_data::
* override_config_file::
* pack_fclose::
* pack_fclose_chunk::
* pack_feof::
* pack_ferror::
* pack_fgets::
* pack_fopen::
* pack_fopen_chunk::
* pack_fopen_vtable::
* pack_fputs::
* pack_fread::
* pack_fseek::
* pack_fwrite::
* pack_getc::
* pack_igetl::
* pack_igetw::
* pack_iputl::
* pack_iputw::
* pack_mgetl::
* pack_mgetw::
* pack_mputl::
* pack_mputw::
* pack_putc::
* pack_ungetc::
* PACKFILE::
* packfile_password::
* PACKFILE_VTABLE::
* PAL_SIZE::
* PALETTE::
* palette_color::
* persp_project::
* pivot_scaled_sprite::
* pivot_scaled_sprite_v_flip::
* pivot_sprite::
* pivot_sprite_v_flip::
* play_audio_stream::
* play_fli::
* play_looped_midi::
* play_memory_fli::
* play_midi::
* play_sample::
* poll_joystick::
* poll_keyboard::
* poll_mouse::
* poll_scroll::
* polygon::
* polygon3d::
* polygon_z_normal::
* POLYTYPE_ATEX::
* POLYTYPE_ATEX_LIT::
* POLYTYPE_ATEX_MASK::
* POLYTYPE_ATEX_MASK_LIT::
* POLYTYPE_ATEX_MASK_TRANS::
* POLYTYPE_ATEX_TRANS::
* POLYTYPE_FLAT::
* POLYTYPE_GCOL::
* POLYTYPE_GRGB::
* POLYTYPE_PTEX::
* pop_config_state::
* popup_dialog::
* position_dialog::
* position_mouse::
* position_mouse_w::
* position_mouse_z::
* push_config_state::
* put_backslash::
* putpixel::
* QNX integration routines::
* qnx_get_window::
* qscale_matrix::
* qtranslate_matrix::
* quad3d::
* QUAT::
* quat_interpolate::
* quat_mul::
* quat_slerp::
* quat_to_matrix::
* radtofix_r::
* read_sound_input::
* readkey::
* reallocate_voice::
* rect::
* rectfill::
* register_assert_handler::
* register_bitmap_file_type::
* register_datafile_object::
* register_font_file_type::
* register_sample_file_type::
* register_trace_handler::
* register_uformat::
* release_bitmap::
* release_screen::
* release_voice::
* reload_config_texts::
* remove_display_switch_callback::
* remove_int::
* remove_joystick::
* remove_keyboard::
* remove_mouse::
* remove_param_int::
* remove_sound::
* remove_sound_input::
* remove_timer::
* render_scene::
* replace_extension::
* replace_filename::
* request_refresh_rate::
* request_scroll::
* request_video_bitmap::
* reserve_voices::
* reset_fli_variables::
* rest::
* rest_callback::
* retrace_count::
* RGB::
* rgb_map::
* RGB_MAP::
* RLE_SPRITE::
* rotate_scaled_sprite::
* rotate_scaled_sprite_v_flip::
* rotate_sprite::
* rotate_sprite_v_flip::
* SAMPLE::
* save_bitmap::
* save_bmp::
* save_bmp_pf::
* save_joystick_data::
* save_pcx::
* save_pcx_pf::
* save_sample::
* save_tga::
* save_tga_pf::
* scancode_to_ascii::
* scancode_to_name::
* scare_mouse::
* scare_mouse_area::
* Scene rendering::
* scene_gap::
* scene_polygon3d::
* screen::
* SCREEN_W::
* scroll_screen::
* select_mouse_cursor::
* select_palette::
* set_add_blender::
* set_allegro_resource_path::
* set_alpha_blender::
* set_blender_mode::
* set_blender_mode_ex::
* set_burn_blender::
* set_clip_rect::
* set_clip_state::
* set_close_button_callback::
* set_color::
* set_color_blender::
* set_color_conversion::
* set_color_depth::
* set_config_data::
* set_config_file::
* set_config_float::
* set_config_hex::
* set_config_id::
* set_config_int::
* set_config_string::
* set_dialog_color::
* set_difference_blender::
* set_display_switch_callback::
* set_display_switch_mode::
* set_dissolve_blender::
* set_dodge_blender::
* set_gdi_color_format::
* set_gfx_mode::
* set_hardware_volume::
* set_hue_blender::
* set_invert_blender::
* set_keyboard_rate::
* set_leds::
* set_luminance_blender::
* set_mixer_quality::
* set_mouse_cursor_bitmap::
* set_mouse_range::
* set_mouse_speed::
* set_mouse_sprite::
* set_mouse_sprite_focus::
* set_multiply_blender::
* set_palette::
* set_palette_range::
* set_palette_to_hdc::
* set_projection_viewport::
* set_saturation_blender::
* set_screen_blender::
* set_sound_input_source::
* set_trans_blender::
* set_ucodepage::
* set_uformat::
* set_volume::
* set_volume_per_voice::
* set_window_title::
* set_write_alpha_blender::
* set_zbuffer::
* show_mouse::
* show_os_cursor::
* show_video_bitmap::
* shutdown_dialog::
* shutdown_menu::
* simulate_keypress::
* simulate_ukeypress::
* solid_mode::
* spline::
* Standard config variables::
* start_sound_input::
* stop_audio_stream::
* stop_midi::
* stop_sample::
* stop_sound_input::
* stretch_blit::
* stretch_blit_from_hdc::
* stretch_blit_to_hdc::
* stretch_sprite::
* text_height::
* text_length::
* textout_centre_ex::
* textout_ex::
* textout_justify_ex::
* textout_right_ex::
* textprintf_centre_ex::
* textprintf_ex::
* textprintf_justify_ex::
* textprintf_right_ex::
* three_finger_flag::
* TRACE::
* transpose_font::
* triangle::
* triangle3d::
* Truecolor transparency::
* uatof::
* uconvert::
* uconvert_ascii::
* uconvert_size::
* uconvert_toascii::
* ucwidth::
* ugetat::
* ugetc::
* ugetx::
* uinsert::
* uisdigit::
* uisok::
* uisspace::
* Unix integration routines::
* unload_datafile::
* unload_datafile_object::
* unscare_mouse::
* unselect_palette::
* uoffset::
* update_dialog::
* update_menu::
* ureadkey::
* uremove::
* usetat::
* usetc::
* Using datafiles::
* usprintf::
* ustrcat::
* ustrchr::
* ustrcmp::
* ustrcpy::
* ustrdup::
* ustrerror::
* ustricmp::
* ustrlen::
* ustrlwr::
* ustrncat::
* ustrncmp::
* ustrncpy::
* ustrnicmp::
* ustrpbrk::
* ustrrchr::
* ustrsize::
* ustrsizez::
* ustrstr::
* ustrtod::
* ustrtok::
* ustrtok_r::
* ustrtol::
* ustrupr::
* ustrzcat::
* ustrzcpy::
* ustrzncat::
* ustrzncpy::
* uszprintf::
* utolower::
* utoupper::
* uvsprintf::
* uvszprintf::
* uwidth::
* uwidth_max::
* V3D::
* V3D_f::
* vector_length::
* VIRTUAL_W::
* vline::
* Voice control::
* voice_check::
* voice_get_frequency::
* voice_get_pan::
* voice_get_position::
* voice_get_volume::
* voice_ramp_volume::
* voice_set_echo::
* voice_set_frequency::
* voice_set_pan::
* voice_set_playmode::
* voice_set_position::
* voice_set_priority::
* voice_set_tremolo::
* voice_set_vibrato::
* voice_set_volume::
* voice_start::
* voice_stop::
* voice_stop_frequency_sweep::
* voice_stop_pan_sweep::
* voice_stop_volumeramp::
* voice_sweep_frequency::
* voice_sweep_pan::
* vsync::
* win_get_dc::
* win_get_window::
* win_release_dc::
* win_set_window::
* win_set_wnd_create_proc::
* Windows integration routines::
* xor_mode::
* xwin_set_window_name::
* ZBUFFER::
* Zbuffered rendering::
@end menu
@end ifinfo

@contents
@bye


