<?xml version="1.0" encoding="ISO-8859-1"?>
<doc><titlepage><text><![CDATA[<pre>     ______   ___    ___
    /\  _  \ /\_ \  /\_ \
    \ \ \L\ \\//\ \ \//\ \      __     __   _ __   ___
     \ \  __ \ \ \ \  \ \ \   /'__`\ /'_ `\/\`'__\/ __`\
      \ \ \/\ \ \_\ \_ \_\ \_/\  __//\ \L\ \ \ \//\ \L\ \
       \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
	\/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
				       /\____/
				       \_/__/     Version 4.2.1


		A game programming library.

	     By Shawn Hargreaves, Nov 26, 2006.

		See the AUTHORS file for a
	       complete list of contributors.
</pre>]]></text><text><![CDATA[


#include &lt;std_disclaimer.h&gt;
<blockquote class="text"><i>
   "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."
</i></blockquote>
]]></text></titlepage><section title="Contents"><contents/></section><section title="A general introduction to Allegro"><section title="Introduction"><text><![CDATA[
   Allegro is a cross-platform library intended for use in computer games
   and other types of multimedia programming. It was initially conceived on
   the Atari ST, but that platform sadly died during childbirth. After a
   brief stay with Borland C, it was adopted by the fantastic djgpp
   compiler, where it grew to maturity. In the fullness of time it gave
   birth to children of its own, who went to live in such exotic locations
   as DirectX and the X Server, but the entire family is now back together
   again, living in harmony as a single portable entity. How about that for
   a mixture of metaphors? :-)

   A wide range of extension packages and add-on modules are also available,
   which can be found in the "Library Extensions" section of the Allegro.cc
   website, <a href="http://www.allegro.cc/">http://www.allegro.cc/</a>.

   According to the Oxford Companion to Music, Allegro is the Italian for
   "quick, lively, bright". It is also a recursive acronym which stands for
   "Allegro Low Level Game Routines".



]]></text></section><section title="Supported platforms"><text><![CDATA[
   For instructions on how to install Allegro, how to link your programs
   with it, and any additional information specific to each of the supported
   platforms, see one of the files included in the distribution package:
<pre class="text">
   DOS/djgpp         - see docs/build/djgpp.txt
   DOS/Watcom        - see docs/build/watcom.txt
   Windows/MSVC      - see docs/build/msvc.txt
   Windows/MinGW     - see docs/build/mingw32.txt
   Windows/Cygwin    - see docs/build/mingw32.txt
   Windows/Borland   - see docs/build/bcc32.txt
   Linux (console)   - see docs/build/linux.txt
   Unix (X11)        - see docs/build/unix.txt
   Darwin (X11)      - see docs/build/darwin.txt
   BeOS              - see docs/build/beos.txt
   QNX               - see docs/build/qnx.txt
   MacOS X           - see docs/build/macosx.txt
</pre>
   General API information can be found in the main manual, usually referred
   to as docs/txt/allegro.txt, allegro.txt or simply "The Allegro manual"
   throughout this document. The Allegro manual source is available as a set
   of files in the docs/src directory. During the build process of the
   library, these source files will be converted to HTML, TexInfo, and RTF
   formats (among others) and placed in their respective doc/FORMAT
   directory.

   Information about changes in the API and deprecated features can be found
   in docs/txt/api.txt (also available in HTML, TexInfo, and RTF format as
   part of the Allegro manual).



]]></text></section><section title="Features"><text><![CDATA[<ul><li>
   Cross-platform support for DOS, Windows, Unix, BeOS, QNX and MacOS X
   systems.
<li>
   Drawing functions including putpixel, getpixel, lines, rectangles, flat
   shaded, gouraud shaded, texture mapped, and z-buffered polygons, circles,
   floodfill, bezier splines, patterned fills, masked, run length encoded,
   and compiled sprites, blitting, bitmap scaling and rotation,
   translucency/lighting, and text output with proportional fonts. Supports
   clipping, and can draw directly to the screen or to memory bitmaps of any
   size.
<li>
   DOS graphics drivers for VGA mode 13h, mode-X (twenty three tweaked VGA
   resolutions plus unchained 640x400 Xtended mode), and SVGA modes with 8,
   15, 16, 24, and 32 bit color depths, taking full advantage of VBE 2.0
   linear framebuffers and the VBE/AF hardware accelerator API if they are
   available. Additional video hardware support is available from the
   FreeBE/AF project (<a href="http://www.talula.demon.co.uk/freebe/">http://www.talula.demon.co.uk/freebe/</a>).
<li>
   Windows graphics drivers using DirectX in fullscreen and windowed modes,
   plus routines for drawing onto GDI device contexts.
<li>
   Unix graphics drivers for X, DGA2, fbcon, SVGAlib, VBE/AF, mode-X, and
   standard VGA.
<li>
   BeOS graphics drivers using BWindowScreen in fullscreen and BDirectWindow
   in windowed modes.
<li>
   MacOS X native graphics drivers using CGDirectDisplay API for direct
   fullscreen gfx access and QuickDraw in a Cocoa window in windowed mode.
<li>
   Hardware scrolling and triple buffering (where available), mode-X split
   screens, and palette manipulation.
<li>
   FLI/FLC animation player.
<li>
   Plays background MIDI music and up to 64 simultaneous sound effects, and
   can record sample waveforms and MIDI input. Samples can be looped
   (forwards, backwards, or bidirectionally), and the volume, pan, pitch,
   etc, can be adjusted while they are playing. The MIDI player responds to
   note on, note off, main volume, pan, pitch bend, and program change
   messages, using the General MIDI patch set and drum mappings. DOS version
   currently supports Adlib, SB, SB Pro, SB16, AWE32, MPU-401, ESS
   AudioDrive, Ensoniq Soundscape, and Windows Sound System. Windows version
   supports WaveOut and DirectSound interfaces and the system MIDI drivers.
   Unix version supports OSS, ESD, and ALSA sound drivers. BeOS version
   supports BSoundPlayer and BMidiSynth interfaces. MacOS X native version
   supports CoreAudio, Carbon Sound Manager and QuickTime Note Allocator
   interfaces. All versions provide software wavetable MIDI playback.
<li>
   Easy access to the mouse, keyboard, joystick, and high resolution timer
   interrupts, including a vertical retrace interrupt simulator in the DOS
   version.
<li>
   Routines for reading and writing LZSS compressed files.
<li>
   Multi-object data files and a grabber utility.
<li>
   Math functions including fixed point arithmetic, lookup table trig, and
   3d vector/matrix/quaternion manipulation.
<li>
   GUI dialog manager and file selector.
<li>
   Built-in support for 16-bit and UTF-8 format Unicode characters.
</ul>


]]></text></section><section title="Copyright"><text><![CDATA[
   Allegro is gift-ware. It was created by a number of people working in
   cooperation, and is given to you freely as a gift. You may use, modify,
   redistribute, and generally hack it about in any way you like, and you do
   not have to give us anything in return. However, if you like this product
   you are encouraged to thank us by making a return gift to the Allegro
   community. This could be by writing an add-on package, providing a useful
   bug report, making an improvement to the library, or perhaps just
   releasing the sources of your program so that other people can learn from
   them. If you redistribute parts of this code or make a game using it, it
   would be nice if you mentioned Allegro somewhere in the credits, but you
   are not required to do this. We trust you not to abuse our generosity.

   Disclaimer:

   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
   SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
   FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
   DEALINGS IN THE SOFTWARE.

]]></text></section><section title="Configuration"><text><![CDATA[
   Allegro reads information about your hardware from a file called
   allegro.cfg. If this file doesn't exist it will autodetect (ie. guess :-)
   You can write your config file by hand with a text editor, or you can use
   the setup utility program (located in the setup directory).

   Normally the setup program and allegro.cfg will go in the same directory
   as the Allegro program they are controlling. This is fine for the end
   user, but it can be a pain for a programmer using Allegro because you may
   have several programs in different directories and want to use a single
   allegro.cfg for all of them. If this is the case you can set the
   environment variable ALLEGRO to the directory containing your
   allegro.cfg, and Allegro will look there if there is no allegro.cfg in
   the current directory.

   The mapping tables used to store different keyboard layouts are stored in
   a file called keyboard.dat. This must either be located in the same
   directory as your Allegro program, or in the directory pointed to by the
   ALLEGRO environment variable. If you want to support different
   international keyboard layouts, you must distribute a copy of
   keyboard.dat along with your program.

   Various translations of things like the system error messages are stored
   in a file called language.dat. This must either be located in the same
   directory as your Allegro program, or in the directory pointed to by the
   ALLEGRO environment variable. If you want to support non-English versions
   of these strings, you must distribute a copy of language.dat along with
   your program.

   Under Unix, BeOS and MacOS X, the config file routines also check for
   ~/allegro.cfg, ~/.allegrorc, /etc/allegro.cfg, and /etc/allegrorc, in
   that order, and the keyboard and language files can be stored in your
   home directory or in /etc/. If under MacOS X, the application bundle
   Contents/Resources directory, if any, is also scanned first.

   See docs/txt/allegro.txt for details of the config file format.



]]></text></section><section title="Notes about sound"><text><![CDATA[
   The DIGMID wavetable driver uses standard GUS format .pat files, and you
   will need a collection of such instruments before you can use it. This
   can either be in the standard GUS format (a set of .pat files and a
   default.cfg index), or a patches.dat file as produced by the pat2dat
   utility. You can also use pat2dat to convert AWE32 SoundFont banks into
   the patches.dat format, and if you list some MIDI files on the command
   line it will filter the sample set to only include the instruments that
   are actually used by those tunes, so it can be useful for getting rid of
   unused instruments when you are preparing to distribute a game. See the
   Allegro website for some links to suitable sample sets.

   The DIGMID driver normally only loads the patches needed for each song
   when the tune is first played. This reduces the memory usage, but can
   result in a longish delay the first time you play each MIDI file. If you
   prefer to load the entire patch set in one go, call the
   load_midi_patches() function.

   The CPU sample mixing code can support between 1 and 64 voices, going up
   in powers of two (ie. either 1, 2, 4, 8, 16, 32, or 64 channels). By
   default it provides 8 digital voices, or 8 digital plus 24 MIDI voices (a
   total of 32) if the DIGMID driver is in use. But the more voices, the
   lower the output volume and quality, so you may wish to change this by
   calling the reserve_voices() function or setting the digi_voices and
   midi_voices parameters in allegro.cfg.



]]></text></section><section title="Contact info"><text><![CDATA[
   The latest version of Allegro can always be found on the Allegro
   homepage, <a href="http://alleg.sourceforge.net/">http://alleg.sourceforge.net/</a>.

   There are three mailing lists for Allegro-related discussion, each with a
   slightly different purpose.
<ul><li>
   [AL] - Allegro main -
   <a href="http://lists.sourceforge.net/lists/listinfo/alleg-main/">http://lists.sourceforge.net/lists/listinfo/alleg-main/</a>.<p>

      This list is for any kind of discussion about Allegro, questions about
      Allegro, reports of problems with Allegro, suggestions for new
      features, announcements of programs written using Allegro, etc.
      General rule: if it has to do with Allegro, you can post it here. If
      not, go somewhere else (for example comp.os.msdos.djgpp, comp.lang.c,
      or the online forums at <a href="http://www.allegro.cc/">http://www.allegro.cc/</a>).
<p><li>
   [AD] - Allegro developers -
   <a href="http://lists.sourceforge.net/lists/listinfo/alleg-developers/">http://lists.sourceforge.net/lists/listinfo/alleg-developers/</a>.<p>

      This list is for the people currently working on Allegro, who use it to
      coordinate their efforts. You can use this address if you need to
      contact the developers directly, for example to submit some new code
      that you have written or to report a bug.
<p>
      Unlike the other lists, we will be really rude to people who post
      inappropriate material here, so please don't do that! Do not send
      tech-support questions to this list. Don't post bug reports here unless
      you are 100% certain they aren't your fault (if you are in any doubt,
      use the main Allegro list instead, which is read by most of the same
      people who are subscribed here).
<p>
      The Allegro development is a completely open process, and everyone is
      welcome to drop by, have a listen, and start contributing code patches.
      This list is for working rather than talking, though, so please don't
      do anything that might get in our way.
<p><li>
   [Alleg5] - Allegro 5 -
   <a href="http://lists.sourceforge.net/mailman/listinfo/alleg-bigfive">http://lists.sourceforge.net/mailman/listinfo/alleg-bigfive</a>.<p>

      This list was once available for discussing the next major version of
      Allegro, when it was too noisy to do so on [AD]. This is no longer the
      case so the list has been shut down. However, its archives are still
      valuable.
</ul>
   To subscribe to one of the three lists, simply go to it's web page and use
   the online forms to subscribe yourself. You can remove yourself from a
   list going to the same page above, which can be used to remind you of your
   password too, in case you have forgotten it.

   To send a message to one of the lists, write to
   alleg-main AT lists.sourceforge DOT net or
   alleg-developers AT lists.sourceforge DOT net. You don't need to be subscribed to
   these mailing lists before you can post there, but it is a good idea to
   subscribe in order to see the replies.

   Before posting tech-support questions to the Allegro list, please take a
   moment to read the guidelines in docs/txt/help.txt. See docs/txt/ahack.txt
   for information about the style of code we use, and how to create your
   patches.

   If you want to search through the archives of any of those mailing lists,
   you will have to check the available options at
   <a href="http://alleg.sourceforge.net/maillist.html">http://alleg.sourceforge.net/maillist.html</a>.

   Please don't send messages in HTML format. The increased size places an
   unnecessary load on the server, and many subscribers have a hard time
   reading these posts.

   Please do not crosspost between these lists. Choose the most appropriate
   one for your message, and then send it only to that list.

   Please don't send large binary attachments to any of the lists, they will
   be rejected by the size limit filter, which is set to 100KB for the
   developers mailing list, and 40KB for the others. Upload your files to a
   website and then post the URL, or if you can't do that, post an
   announcement asking people to write to you privately, and then send the
   file by individual email to whoever responded.

   Please use English in your messages. You could eventually post messages in
   whatever language you prefer, but that would terribly limit the chances of
   getting a useful answer.

   Remember that the RFC 1855: netiquette guidelines
   (<a href="http://www.rfc-editor.org/rfc/rfc1855.txt">http://www.rfc-editor.org/rfc/rfc1855.txt</a>) describes other general
   guidelines you should follow as a correct internet user (in mailing lists
   and other places as well), and provides more verbose descriptions and
   explanations about why you should follow the above guidelines.

   One of the important guidelines you should be aware of is how to quote
   correctly the message you are replying to. The previous RFC doesn't really
   explain how to do it, so you might want to read the document "How do I
   quote correctly in Usenet?" at
   <a href="http://www.netmeister.org/news/learn2quote.html">http://www.netmeister.org/news/learn2quote.html</a>. Quoting correctly is
   easier to say than to do, especially for users of Microsoft Outlook. If
   you are such a user, you can help yourself using the Outlook-QuoteFix
   extension written by Dominik Jain, which you can find at
   <a href="http://home.in.tum.de/~jain/software/outlook-quotefix/">http://home.in.tum.de/~jain/software/outlook-quotefix/</a>.
]]></text></section></section><section title="API"><section title="Using Allegro"><text><![CDATA[
See readme.txt for a general introduction, copyright details, and
information about how to install Allegro and link your program with it.

]]></text><reflist><ref name="install_allegro" syntax="int install_allegro(int system_id, int *errno_ptr, int (*atexit_ptr)());"><xreflist><xref>allegro_init</xref><xref>allegro_exit</xref><xref>set_uformat</xref><xref>set_config_file</xref></xreflist><shortdesc>Initialise the Allegro library.</shortdesc><text><![CDATA[   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:
<pre class="code">
      install_allegro(SYSTEM_AUTODETECT, &amp;errno, atexit);</pre>
]]></text><retval><text><![CDATA[   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.

]]></text></retval></ref><ref name="allegro_init" syntax="int allegro_init();"><xreflist><xref>install_allegro</xref><xref>allegro_exit</xref></xreflist><ereflist><eref>Available Allegro examples</eref></ereflist><shortdesc>Macro to initialise the Allegro library.</shortdesc><text><![CDATA[   Macro which initialises the Allegro library. This is the same thing as
   calling install_allegro(SYSTEM_AUTODETECT, &amp;errno, atexit).

]]></text></ref><ref name="allegro_exit" syntax="void allegro_exit();"><xreflist><xref>install_allegro</xref><xref>allegro_init</xref><xref>destroy_bitmap</xref></xreflist><ereflist><eref>ex3d</eref><eref>exscn3d</eref><eref>exswitch</eref><eref>exxfade</eref><eref>exzbuf</eref></ereflist><shortdesc>Closes down the Allegro system.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="END_OF_MAIN" syntax="Macro END_OF_MAIN()"><xreflist><xref>Windows specifics</xref><xref>Unix specifics</xref><xref>MacOS X specifics</xref><xref>Differences between platforms</xref></xreflist><ereflist><eref>Available Allegro examples</eref></ereflist><shortdesc>Macro to put after your main() function.</shortdesc><text><![CDATA[   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:
<pre class="code">
      int main(void)
      {
	 allegro_init();
	 /* more stuff goes here */
	 ...
	 return 0;
      }
      END_OF_MAIN()</pre>

]]></text></ref><ref name="allegro_id" syntax="extern char allegro_id[];"><shortdesc>String containing date and version number of Allegro.</shortdesc><text><![CDATA[   Text string containing a date and version number for the library, in case
   you want to display these somewhere.

]]></text></ref><ref name="allegro_error" syntax="extern char allegro_error[ALLEGRO_ERROR_SIZE];"><xreflist><xref>set_gfx_mode</xref><xref>install_sound</xref></xreflist><ereflist><eref>Available Allegro examples</eref></ereflist><shortdesc>Stores the last Allegro error message.</shortdesc><text><![CDATA[   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:
<pre class="code">
      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!");</pre>
]]></text></ref><ref name="ALLEGRO_VERSION" syntax="#define ALLEGRO_VERSION"><shortdesc>Defined to the major version of Allegro.</shortdesc><text><![CDATA[   Defined to the major version of Allegro. From a version number like
   4.1.16, this would be defined to the integer 4.

]]></text></ref><ref name="ALLEGRO_SUB_VERSION" syntax="#define ALLEGRO_SUB_VERSION"><shortdesc>Defined to the middle version of Allegro.</shortdesc><text><![CDATA[   Defined to the middle version of Allegro. From a version number like
   4.1.16, this would be defined to the integer 1.

]]></text></ref><ref name="ALLEGRO_WIP_VERSION" syntax="#define ALLEGRO_WIP_VERSION"><shortdesc>Defined to the minor version of Allegro.</shortdesc><text><![CDATA[   Defined to the minor version of Allegro. From a version number like
   4.1.16, this would be defined to the integer 16.

]]></text></ref><ref name="ALLEGRO_VERSION_STR" syntax="#define ALLEGRO_VERSION_STR"><shortdesc>Defined to a string with the full Allegro version number.</shortdesc><text><![CDATA[   Defined to a text string containing all version numbers and maybe some
   additional text. This could be `4.1.16 (CVS)' for an Allegro version
   obtained straight from the CVS repository.

]]></text></ref><ref name="ALLEGRO_DATE_STR" syntax="#define ALLEGRO_DATE_STR"><shortdesc>Defined to a string with the year Allegro was released.</shortdesc><text><![CDATA[   Defined to a text string containing the year this version of Allegro was
   released, like `2004'.

]]></text></ref><ref name="ALLEGRO_DATE" syntax="#define ALLEGRO_DATE"><shortdesc>Defined to a number with the release date of Allegro.</shortdesc><text><![CDATA[   Defined to an integer containing the release date of Allegro in the packed
   format `yyyymmdd'. Example:
<pre class="code">
      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);</pre>

]]></text></ref><ref name="AL_ID" syntax="Macro AL_ID(a,b,c,d)"><shortdesc>Converts four 8 bit values to a packed 32 bit integer ID.</shortdesc><xreflist><xref>DAT_ID</xref></xreflist><text><![CDATA[   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:
<pre class="code">
      #define OSTYPE_LINUX       AL_ID('T','U','X',' ')</pre>

]]></text></ref><ref name="MAKE_VERSION" syntax="Macro MAKE_VERSION(a, b, c)"><shortdesc>Create a 32 bit integer from the Allegro version</shortdesc><xreflist><xref>ALLEGRO_VERSION</xref><xref>ALLEGRO_SUB_VERSION</xref><xref>ALLEGRO_WIP_VERSION</xref></xreflist><text><![CDATA[   This macro can be used to check if some Allegro version is (binary)
   compatible with the current version. It is safe to use &gt; and &lt; 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:
<pre class="code">
      /* Check if the current version is compatible with Allegro 4.2.0 */
      #if (MAKE_VERSION(4, 2, 0) &lt;= MAKE_VERSION(ALLEGRO_VERSION, \
			 ALLEGRO_SUB_VERSION, ALLEGRO_WIP_VERSION))
	 /* Allegro 4.2.0 compatibility */
      #else
	 /* Work-around */
      #endif</pre>

]]></text></ref><ref name="os_type" syntax="extern int os_type;"><xreflist><xref>allegro_init</xref><xref>os_version</xref><xref>os_multitasking</xref></xreflist><shortdesc>Stores the detected type of the OS.</shortdesc><text><![CDATA[   Set by allegro_init() to one of the values:
<pre class="text">
      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</pre>

]]></text></ref><ref name="os_version" syntax="extern int os_version;"/><ref name="os_revision" syntax="extern int os_revision;"><xreflist><xref>os_type</xref><xref>os_multitasking</xref></xreflist><shortdesc>Version of the OS currently running.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="os_multitasking" syntax="extern int os_multitasking;"><xreflist><xref>os_type</xref><xref>os_version</xref></xreflist><shortdesc>Indicates if the OS is multitasking.</shortdesc><text><![CDATA[   Set by allegro_init() to either TRUE or FALSE depending on whether your
   Operating System is multitasking or not.

]]></text></ref><ref name="allegro_message" syntax="void allegro_message(const char *text_format, ...);"><xreflist><xref>allegro_init</xref><xref>install_allegro</xref><xref>set_uformat</xref></xreflist><ereflist><eref>Available Allegro examples</eref></ereflist><shortdesc>Used mainly to show error messages to users.</shortdesc><text><![CDATA[   Outputs a message, using a printf() format string. Usually you want to
   use this to report messages to the user in an OS independant 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:
<pre class="code">
      if (allegro_init() != 0)
	 exit(1);

      if (init_my_data() != 0) {
	 allegro_message("Sorry, missing game data!\n");
	 exit(2);
      }</pre>

]]></text></ref><ref name="set_window_title" syntax="void set_window_title(const char *name);"><xreflist><xref>set_close_button_callback</xref><xref>set_uformat</xref></xreflist><ereflist><eref>exunicod</eref></ereflist><shortdesc>Sets the window title of the Allegro program.</shortdesc><text><![CDATA[   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:
<pre class="code">
      set_window_title("Allegro rules!");</pre>

]]></text></ref><ref name="set_close_button_callback" syntax="int set_close_button_callback(void (*proc)(void));"><xreflist><xref>set_window_title</xref></xreflist><shortdesc>Handles the user clicking on the close button of the window.</shortdesc><text><![CDATA[   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:
<pre class="code">
      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();</pre>
]]></text><retval><text><![CDATA[   Returns zero on success and non-zero on failure (e.g. the feature is not
   supported by the platform).

]]></text></retval></ref><ref name="desktop_color_depth" syntax="int desktop_color_depth();"><xreflist><xref>get_desktop_resolution</xref><xref>set_color_depth</xref><xref>set_gfx_mode</xref></xreflist><shortdesc>Finds out the desktop color depth.</shortdesc><text><![CDATA[   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:
<pre class="code">
      allegro_init();
      ...
      if ((depth = desktop_color_depth()) != 0) {
	 set_color_depth(depth);
      }</pre>
]]></text><retval><text><![CDATA[   Returns the color depth or zero on platforms where this information is not
   available or does not apply.

]]></text></retval></ref><ref name="get_desktop_resolution" syntax="int get_desktop_resolution(int *width, int *height);"><xreflist><xref>desktop_color_depth</xref><xref>set_gfx_mode</xref></xreflist><shortdesc>Finds out the desktop resolution.</shortdesc><text><![CDATA[   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:
<pre class="code">
      int width, height;

      allegro_init();
      ...
      if (get_desktop_resolution(&amp;width, &amp;height) == 0) {
	 /* Got the resolution correctly */
      }</pre>
]]></text><retval><text><![CDATA[   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.

]]></text></retval></ref><ref name="check_cpu" syntax="void check_cpu();"><xreflist><xref>cpu_vendor</xref><xref>cpu_family</xref><xref>cpu_model</xref><xref>cpu_capabilities</xref><xref>allegro_init</xref></xreflist><shortdesc>Detects the CPU type.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="cpu_vendor" syntax="extern char cpu_vendor[];"><xreflist><xref>check_cpu</xref><xref>cpu_family</xref><xref>cpu_model</xref><xref>cpu_capabilities</xref><xref>allegro_init</xref></xreflist><shortdesc>Contains the CPU vendor name.</shortdesc><text><![CDATA[   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()).

]]></text></ref><ref name="cpu_family" syntax="extern int cpu_family;"><xreflist><xref>check_cpu</xref><xref>cpu_vendor</xref><xref>cpu_model</xref><xref>cpu_capabilities</xref><xref>allegro_init</xref></xreflist><shortdesc>Contains the CPU type.</shortdesc><text><![CDATA[   Contains the Intel type, where applicable. Allegro defines the following
   CPU family types:
<pre class="text">
      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
</pre>
   You can read this variable after you have called check_cpu()
   (which is automatically called by allegro_init()).

]]></text></ref><ref name="cpu_model" syntax="extern int cpu_model;"><xreflist><xref>check_cpu</xref><xref>cpu_vendor</xref><xref>cpu_family</xref><xref>cpu_capabilities</xref><xref>allegro_init</xref></xreflist><shortdesc>Contains the Intel CPU submodel.</shortdesc><text><![CDATA[   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):
<pre class="text">
      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
</pre>
   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.

]]></text></ref><ref name="cpu_capabilities" syntax="extern int cpu_capabilities;"><xreflist><xref>check_cpu</xref><xref>cpu_vendor</xref><xref>cpu_family</xref><xref>cpu_model</xref><xref>cpu_capabilities</xref><xref>allegro_init</xref></xreflist><shortdesc>Contains the capability flags of the CPU.</shortdesc><text><![CDATA[   Contains CPU flags indicating what features are available on the current
   CPU. The flags can be any combination of these:
<pre class="text">
      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.
</pre>
   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:
<pre class="code">
      if ((cpu_capabilities &amp; (CPU_FPU | CPU_MMX)) ==
	  (CPU_FPU | CPU_MMX)) {
	 printf("CPU has both an FPU and MMX instructions!\n");
      }
</pre>
   You can read this variable after you have called check_cpu() (which is
   automatically called by allegro_init()).



]]></text></ref></reflist></section><section title="Structures and types defined by Allegro"><text><![CDATA[
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
appropiate 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.

]]></text><reflist><ref name="fixed" syntax="typedef long fixed"><xreflist><xref>Fixed point math routines</xref></xreflist><ereflist><eref>ex12bit</eref><eref>ex3buf</eref><eref>ex3d</eref><eref>excustom</eref><eref>exfixed</eref><eref>exspline</eref><eref>exsprite</eref><eref>exstars</eref><eref>exupdate</eref></ereflist><shortdesc>Fixed point integer to replace floats.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="BITMAP" syntax="typedef struct BITMAP"><xreflist><xref>create_bitmap</xref><xref>set_clip_rect</xref><xref>bitmap_color_depth</xref><xref>RLE_SPRITE</xref><xref>COMPILED_SPRITE</xref><xref>Direct access to video memory</xref></xreflist><ereflist><eref>Available Allegro examples</eref></ereflist><shortdesc>Stores the contents of a bitmap.</shortdesc><text><![CDATA[<pre class="code">
   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
</pre>
   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:
<pre class="code">
      bmp = load_bitmap("file.bmp", pal);
      allegro_message("Bitmap size: (%dx%d)\n", bmp->w, bmp->h);
</pre>
   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.

]]></text></ref><ref name="RLE_SPRITE" syntax="typedef struct RLE_SPRITE"><xreflist><xref>get_rle_sprite</xref><xref>BITMAP</xref><xref>COMPILED_SPRITE</xref><xref>RLE sprites</xref></xreflist><shortdesc>Stores the contents of an RLE sprite.</shortdesc><text><![CDATA[<pre class="code">
   int w, h;           - width and height in pixels
   int color_depth;    - color depth of the image
</pre>
   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.

]]></text></ref><ref name="COMPILED_SPRITE" syntax="typedef struct COMPILED_SPRITE"><xreflist><xref>get_compiled_sprite</xref><xref>BITMAP</xref><xref>RLE_SPRITE</xref><xref>Compiled sprites</xref></xreflist><shortdesc>Stores the contents of a compiled sprite.</shortdesc><text><![CDATA[<pre class="code">
   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
</pre>
   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.

]]></text></ref><ref name="JOYSTICK_INFO" syntax="typedef struct JOYSTICK_INFO"><xreflist><xref>joy</xref><xref>Joystick routines</xref></xreflist><shortdesc>Stores information about joysticks.</shortdesc><text><![CDATA[<pre class="code">
   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
</pre>
   Read chapter "Joystick routines" for a description on how to obtain/use
   this structure.

]]></text></ref><ref name="JOYSTICK_BUTTON_INFO" syntax="typedef struct JOYSTICK_BUTTON_INFO"><xreflist><xref>joy</xref><xref>Joystick routines</xref></xreflist><shortdesc>Stores joystick button information.</shortdesc><text><![CDATA[<pre class="code">
   int b;                           - boolean on/off flag
   char *name;                      - description of this
				      button
</pre>
   Read chapter "Joystick routines" for a description on how to obtain/use
   this structure.

]]></text></ref><ref name="JOYSTICK_STICK_INFO" syntax="typedef struct JOYSTICK_STICK_INFO"><xreflist><xref>joy</xref><xref>Joystick routines</xref></xreflist><shortdesc>Stores joystick stick information.</shortdesc><text><![CDATA[<pre class="code">
   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
</pre>
   Read chapter "Joystick routines" for a description on how to obtain/use
   this structure.

]]></text></ref><ref name="JOYSTICK_AXIS_INFO" syntax="typedef struct JOYSTICK_AXIS_INFO"><xreflist><xref>joy</xref><xref>Joystick routines</xref></xreflist><shortdesc>Stores joystick axis information.</shortdesc><text><![CDATA[<pre class="code">
   int pos;                         - analogue axis position
   int d1, d2;                      - digital axis position
   char *name;                      - description of this axis
</pre>
   Read chapter "Joystick routines" for a description on how to obtain/use
   this structure.

]]></text></ref><ref name="GFX_MODE_LIST" syntax="typedef struct GFX_MODE_LIST"><xreflist><xref>GFX_MODE</xref><xref>get_gfx_mode_list</xref></xreflist><shortdesc>Stores an array of GFX_MODE structures.</shortdesc><text><![CDATA[<pre class="code">
   int num_modes;
   GFX_MODE *mode;
</pre>
   Structure returned by get_gfx_mode_list, which contains an array of
   GFX_MODE structures.

]]></text></ref><ref name="GFX_MODE" syntax="typedef struct GFX_MODE"><xreflist><xref>GFX_MODE_LIST</xref><xref>get_gfx_mode_list</xref></xreflist><shortdesc>Stores video mode information.</shortdesc><text><![CDATA[<pre class="code">
   int width, height, bpp;
</pre>
   Structure contained in GFX_MODE_LIST.

]]></text></ref><ref name="PAL_SIZE" syntax="#define PAL_SIZE"><xreflist><xref>RGB</xref><xref>PALETTE</xref><xref>COLOR_MAP</xref></xreflist><shortdesc>Number of entries in a palette.</shortdesc><text><![CDATA[   Preprocessor constant equal to 256.

]]></text></ref><ref name="PALETTE" syntax="typedef PALETTE RGB[PAL_SIZE]"><xreflist><xref>RGB</xref><xref>Palette routines</xref></xreflist><ereflist><eref>Available Allegro examples</eref></ereflist><shortdesc>Stores palette information.</shortdesc><text><![CDATA[   Allegro palettes are arrays of PAL_SIZE RGB entries.

]]></text></ref><ref name="RGB" syntax="typedef struct RGB"><xreflist><xref>Palette routines</xref><xref>PALETTE</xref></xreflist><ereflist><eref>ex12bit</eref><eref>ex3d</eref><eref>excolmap</eref><eref>exconfig</eref><eref>expal</eref><eref>exrgbhsv</eref><eref>exscroll</eref><eref>exshade</eref><eref>extrans</eref><eref>extruec</eref></ereflist><shortdesc>Single palette entry.</shortdesc><text><![CDATA[<pre class="code">
   unsigned char r, g, b;
</pre>
   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.

]]></text></ref><ref name="V3D" syntax="typedef struct V3D"><xreflist><xref>V3D_f</xref><xref>polygon3d</xref><xref>Fixed point trig</xref></xreflist><ereflist><eref>ex3d</eref></ereflist><shortdesc>Fixed point vertex structure used by 3d functions.</shortdesc><text><![CDATA[<pre class="code">
   fixed x, y, z;       - position
   fixed u, v;          - texture map coordinates
   int c;               - color
</pre>
   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.

]]></text></ref><ref name="V3D_f" syntax="typedef struct V3D_f"><xreflist><xref>V3D</xref><xref>polygon3d_f</xref><xref>Fixed point trig</xref></xreflist><ereflist><eref>excamera</eref><eref>exscn3d</eref><eref>exzbuf</eref></ereflist><shortdesc>Floating point vertex structure used by 3d functions.</shortdesc><text><![CDATA[<pre class="code">
   float x, y, z;       - position
   float u, v;          - texture map coordinates
   int c;               - color
</pre>
   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.

]]></text></ref><ref name="COLOR_MAP" syntax="typedef struct COLOR_MAP"><xreflist><xref>256-color transparency</xref><xref>color_map</xref></xreflist><ereflist><eref>ex3d</eref><eref>excolmap</eref><eref>exlights</eref><eref>exshade</eref><eref>extrans</eref></ereflist><shortdesc>Stores a color map to accelerate drawing.</shortdesc><text><![CDATA[<pre class="code">
   unsigned char data[PAL_SIZE][PAL_SIZE];
</pre>
   Read chapter "Transparency and patterned drawing", section "256-color
   transparency" for a description on how to obtain/use this structure.

]]></text></ref><ref name="RGB_MAP" syntax="typedef struct RGB_MAP"><xreflist><xref>Converting between color formats</xref><xref>create_rgb_table</xref></xreflist><ereflist><eref>ex3d</eref><eref>excolmap</eref><eref>exrgbhsv</eref><eref>exshade</eref><eref>extrans</eref></ereflist><shortdesc>Stores an rgb map to accelerate conversions.</shortdesc><text><![CDATA[<pre class="code">
   unsigned char data[32][32][32];
</pre>
   Read chapter "Converting between color formats" for a description on how
   to obtain/use this structure.

]]></text></ref><ref name="al_ffblk" syntax="struct al_ffblk"><xreflist><xref>al_findfirst</xref><xref>al_ffblk_get_size</xref></xreflist><shortdesc>Cross platform structure storing file information.</shortdesc><text><![CDATA[<pre class="code">
   int attrib;       - actual attributes of the file found
   time_t time;      - modification time of file
   char name[512];   - name of file
</pre>
   Read the description of al_findfirst for a description on how to
   obtain/use this structure.

]]></text></ref><ref name="DATAFILE" syntax="typedef struct DATAFILE"><xreflist><xref>load_datafile</xref><xref>Using datafiles</xref></xreflist><ereflist><eref>excustom</eref><eref>exdata</eref><eref>exexedat</eref><eref>exgui</eref><eref>exsprite</eref><eref>exunicod</eref></ereflist><shortdesc>Stores an Allegro datafile in memory.</shortdesc><text><![CDATA[<pre class="code">
   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
</pre>
   Read chapter "Datafile routines", section "Using datafiles" for a
   description on how to obtain/use this structure.

]]></text></ref><ref name="MATRIX" syntax="typedef struct MATRIX"><xreflist><xref>MATRIX_f</xref><xref>3D math routines</xref></xreflist><ereflist><eref>ex12bit</eref><eref>ex3d</eref><eref>exstars</eref></ereflist><shortdesc>Fixed point matrix structure.</shortdesc><text><![CDATA[<pre class="code">
   fixed v[3][3];           - 3x3 scaling and rotation component
   fixed t[3];              - x/y/z translation component
</pre>
   Fixed point matrix structure. Read chapter "3D math routines" for a
   description on how to obtain/use this structure.

]]></text></ref><ref name="MATRIX_f" syntax="typedef struct MATRIX_f"><xreflist><xref>MATRIX</xref><xref>3D math routines</xref></xreflist><ereflist><eref>excamera</eref><eref>exquat</eref><eref>exscn3d</eref><eref>exzbuf</eref></ereflist><shortdesc>Floating point matrix structure.</shortdesc><text><![CDATA[<pre class="code">
   float v[3][3];           - 3x3 scaling and rotation component
   float t[3];              - x/y/z translation component
</pre>
   Floating point matrix structure. Read chapter "3D math routines" for a
   description on how to obtain/use this structure.

]]></text></ref><ref name="QUAT" syntax="typedef struct QUAT"><xreflist><xref>Quaternion math routines</xref></xreflist><ereflist><eref>exquat</eref></ereflist><shortdesc>Stores quaternion information.</shortdesc><text><![CDATA[<pre class="code">
   float w, x, y, z;
</pre>
   Read chapter "Quaternion math routines" for a description on how to
   obtain/use this structure.

]]></text></ref><ref name="DIALOG" syntax="typedef struct DIALOG"><xreflist><xref>do_dialog</xref><xref>GUI routines</xref></xreflist><ereflist><eref>excustom</eref><eref>exgui</eref><eref>exrgbhsv</eref></ereflist><shortdesc>Stores a GUI description.</shortdesc><text><![CDATA[<pre class="code">
   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
</pre>
   This is the structure which contains a GUI object. Read chapter "GUI
   routines" for a description on how to obtain/use this structure.

]]></text></ref><ref name="MENU" syntax="typedef struct MENU"><xreflist><xref>do_menu</xref><xref>GUI menus</xref></xreflist><ereflist><eref>exgui</eref></ereflist><shortdesc>Stores the entries of a menu.</shortdesc><text><![CDATA[<pre class="code">
   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
</pre>
   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.

]]></text></ref><ref name="DIALOG_PLAYER" syntax="typedef struct DIALOG_PLAYER"><xreflist><xref>init_dialog</xref><xref>update_dialog</xref><xref>shutdown_dialog</xref><xref>GUI routines</xref></xreflist><shortdesc>Stores GUI data internally used by Allegro.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="MENU_PLAYER" syntax="typedef struct MENU_PLAYER"><xreflist><xref>init_menu</xref><xref>update_menu</xref><xref>shutdown_menu</xref><xref>GUI menus</xref></xreflist><shortdesc>Stores GUI data internally used by Allegro.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="FONT" syntax="typedef struct FONT"><xreflist><xref>font</xref></xreflist><ereflist><eref>excustom</eref><eref>exfont</eref><eref>exunicod</eref></ereflist><shortdesc>Stores an Allegro font.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="ZBUFFER" syntax="typedef struct BITMAP ZBUFFER"><xreflist><xref>Zbuffered rendering</xref><xref>BITMAP</xref></xreflist><ereflist><eref>exzbuf</eref></ereflist><shortdesc>Stores 3d zbuffer information.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="SAMPLE" syntax="typedef struct SAMPLE"><xreflist><xref>load_sample</xref><xref>Digital sample routines</xref><xref>Voice control</xref></xreflist><ereflist><eref>exsample</eref></ereflist><shortdesc>Stores sound data.</shortdesc><text><![CDATA[<pre class="code">
   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
</pre>
   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.

]]></text></ref><ref name="MIDI" syntax="typedef struct MIDI"><xreflist><xref>load_midi</xref><xref>Music routines (MIDI)</xref></xreflist><ereflist><eref>exmidi</eref></ereflist><shortdesc>Stores MIDI data.</shortdesc><text><![CDATA[   A structure holding MIDI data. Read chapter "Music routines (MIDI)" for a
   description on how to obtain/use this structure.

]]></text></ref><ref name="AUDIOSTREAM" syntax="typedef struct AUDIOSTREAM"><xreflist><xref>play_audio_stream</xref><xref>Audio stream routines</xref><xref>Voice control</xref></xreflist><ereflist><eref>exstream</eref></ereflist><shortdesc>Stores an audiostream.</shortdesc><text><![CDATA[<pre class="code">
   int voice;  - the hardware voice used for the sample
</pre>
   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.

]]></text></ref><ref name="PACKFILE" syntax="typedef struct PACKFILE"><xreflist><xref>File and compression routines</xref><xref>pack_fopen</xref><xref>pack_fopen_chunk</xref><xref>pack_fopen_vtable</xref></xreflist><ereflist><eref>expackf</eref></ereflist><shortdesc>Packfile structure, similar to the libc FILE structure.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="PACKFILE_VTABLE" syntax="typedef struct PACKFILE_VTABLE"><xreflist><xref>File and compression routines</xref><xref>pack_fopen_vtable</xref></xreflist><ereflist><eref>expackf</eref></ereflist><shortdesc>Packfile vtable structure, for custom packfiles.</shortdesc><text><![CDATA[<pre class="code">
   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);
</pre>
   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.

]]></text></ref><ref name="LZSS_PACK_DATA" syntax="typedef struct LZSS_PACK_DATA"><xreflist><xref>File and compression routines</xref><xref>create_lzss_pack_data</xref></xreflist><shortdesc>Opaque structure for handling LZSS comression.</shortdesc><text><![CDATA[   Opaque structure for handling LZSS compression. Read chapter "File and
   compression routines for a description on how to obtain/use this
   structure.

]]></text></ref><ref name="LZSS_UNPACK_DATA" syntax="typedef struct LZSS_UNPACK_DATA"><xreflist><xref>File and compression routines</xref><xref>create_lzss_unpack_data</xref></xreflist><shortdesc>Opaque structure for handling LZSS decomression.</shortdesc><text><![CDATA[   Opaque structure for handling LZSS decompression. Read chapter "File and
   compression routines for a description on how to obtain/use this
   structure.



]]></text></ref></reflist></section><section title="Unicode routines"><text><![CDATA[
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.

]]></text><reflist><ref name="set_uformat" syntax="void set_uformat(int type);"><xreflist><xref>get_uformat</xref><xref>register_uformat</xref><xref>set_ucodepage</xref><xref>set_uformat</xref><xref>uconvert</xref><xref>ustrsize</xref><xref>ugetc</xref><xref>ugetx</xref><xref>usetc</xref><xref>uwidth</xref><xref>ucwidth</xref><xref>uisok</xref><xref>uoffset</xref><xref>ugetat</xref><xref>usetat</xref><xref>uinsert</xref><xref>uremove</xref><xref>allegro_init</xref></xreflist><ereflist><eref>exunicod</eref></ereflist><shortdesc>Set the global current text encoding format.</shortdesc><text><![CDATA[   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:
<pre class="text">
      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
</pre>
   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.

]]></text></ref><ref name="get_uformat" syntax="int get_uformat(void);"><xreflist><xref>set_uformat</xref></xreflist><shortdesc>Finds out what text encoding format is currently selected.</shortdesc><text><![CDATA[   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:
<pre class="code">
      switch(get_uformat()) {
	 case U_ASCII:
	    do_something();
	    break;
	 case U_UTF8:
	    do_something_else();
	    break;
	 ...
      }</pre>
]]></text><retval><text><![CDATA[   Returns the currently selected text encoding format. See the documentation
   of set_uformat() for a list of encoding formats.

]]></text></retval></ref><ref name="register_uformat" syntax="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));"><xreflist><xref>set_uformat</xref><xref>uconvert</xref><xref>ugetc</xref><xref>ugetx</xref><xref>usetc</xref><xref>uwidth</xref><xref>ucwidth</xref><xref>uisok</xref></xreflist><shortdesc>Installs handler functions for a new text encoding format.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="set_ucodepage" syntax="void set_ucodepage(const unsigned short *table, const unsigned short *extras);"><xreflist><xref>set_uformat</xref></xreflist><shortdesc>Sets 8-bit to Unicode conversion tables.</shortdesc><text><![CDATA[   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-&gt;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).

]]></text></ref><ref name="need_uconvert" syntax="int need_uconvert(const char *s, int type, int newtype);"><xreflist><xref>set_uformat</xref><xref>get_uformat</xref><xref>do_uconvert</xref><xref>uconvert</xref></xreflist><shortdesc>Tells if a string requires encoding conversion.</shortdesc><text><![CDATA[   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:
<pre class="code">
      if (need_uconvert(text, U_UTF8, U_CURRENT)) {
	 /* conversion is required */
      }</pre>
]]></text><retval><text><![CDATA[   Returns non-zero if any conversion is required or zero otherwise.

]]></text></retval></ref><ref name="uconvert_size" syntax="int uconvert_size(const char *s, int type, int newtype);"><xreflist><xref>need_uconvert</xref><xref>do_uconvert</xref></xreflist><shortdesc>Number of bytes needed to store a string after conversion.</shortdesc><text><![CDATA[   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:
<pre class="code">
      length = uconvert_size(old_string, U_CURRENT, U_UNICODE);
      new_string = malloc(length);
      ustrcpy(new_string, old_string);</pre>
]]></text><retval><text><![CDATA[   Returns the number of bytes required to store the string after conversion.

]]></text></retval></ref><ref name="do_uconvert" syntax="void do_uconvert(const char *s, int type, char *buf, int newtype, int size);"><xreflist><xref>uconvert</xref></xreflist><shortdesc>Converts a string to another encoding format.</shortdesc><text><![CDATA[   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:
<pre class="code">
      char temp_string[256];
      do_uconvert(input_string, U_CURRENT, temp_string, U_ASCII, 256);
</pre>
   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.

]]></text></ref><ref name="uconvert" syntax="char *uconvert(const char *s, int type, char *buf, int newtype, int size);"><xreflist><xref>set_uformat</xref><xref>need_uconvert</xref><xref>uconvert</xref><xref>uconvert_ascii</xref><xref>uconvert_toascii</xref><xref>do_uconvert</xref></xreflist><shortdesc>Hih level string encoding conversion wrapper.</shortdesc><text><![CDATA[   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:
<pre class="code">
      char *p = uconvert(input_string, U_CURRENT, buffer, U_ASCII, 256);</pre>
]]></text><retval><text><![CDATA[   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'.

]]></text></retval></ref><ref name="uconvert_ascii" syntax="char *uconvert_ascii(const char *s, char buf[]);"><xreflist><xref>uconvert</xref></xreflist><ereflist><eref>exunicod</eref></ereflist><shortdesc>Converts string from ASCII into the current format.</shortdesc><text><![CDATA[   Helper macro for converting strings from ASCII into the current encoding
   format. Expands to uconvert(s, U_ASCII, buf, U_CURRENT, sizeof(buf)).

]]></text></ref><ref name="uconvert_toascii" syntax="char *uconvert_toascii(const char *s, char buf[]);"><xreflist><xref>uconvert</xref></xreflist><shortdesc>Converts strings from the current format into ASCII.</shortdesc><text><![CDATA[   Helper macro for converting strings from the current encoding format into
   ASCII. Expands to uconvert(s, U_CURRENT, buf, U_ASCII, sizeof(buf)).

]]></text></ref><ref name="empty_string" syntax="extern char empty_string[];"><shortdesc>Universal string NULL terminator.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="ugetc" syntax="int ugetc(const char *s);"><xreflist><xref>ugetx</xref><xref>usetc</xref><xref>uwidth</xref><xref>ucwidth</xref><xref>uisok</xref></xreflist><shortdesc>Low level helper function for reading Unicode text data.</shortdesc><text><![CDATA[   Low level helper function for reading Unicode text data. Example:
<pre class="code">
      int first_unicode_letter = ugetc(text_string);</pre>
]]></text><retval><text><![CDATA[   Returns the character pointed to by `s' in the current encoding format.

]]></text></retval></ref><ref name="ugetx" syntax="int ugetx(char **s);"/><ref name="ugetxc" syntax="int ugetxc(const char **s);"><xreflist><xref>ugetc</xref><xref>usetc</xref><xref>uwidth</xref><xref>ucwidth</xref><xref>uisok</xref></xreflist><shortdesc>Low level helper function for reading Unicode text data.</shortdesc><text><![CDATA[   Low level helper function for reading Unicode text data. ugetxc is provided
   for working with pointer-to-pointer-to-const char data. Example:
<pre class="code">
      char *p = string;
      int first_letter, second_letter, third_letter;
      first_letter = ugetx(&amp;p);
      second_letter = ugetx(&amp;p);
      third_letter = ugetx(&amp;p);</pre>
]]></text><retval><text><![CDATA[   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.

]]></text></retval></ref><ref name="usetc" syntax="int usetc(char *s, int c);"><xreflist><xref>ugetc</xref><xref>ugetx</xref><xref>uwidth</xref><xref>ucwidth</xref><xref>uisok</xref></xreflist><shortdesc>Low level helper function for writing Unicode text data.</shortdesc><text><![CDATA[   Low level helper function for writing Unicode text data. Writes the
   character `c' to the address pointed to by `s'.
]]></text><retval><text><![CDATA[   Returns the number of bytes written, which is equal to the width of the
   character in the current encoding format.

]]></text></retval></ref><ref name="uwidth" syntax="int uwidth(const char *s);"><xreflist><xref>uwidth_max</xref><xref>ugetc</xref><xref>ugetx</xref><xref>usetc</xref><xref>ucwidth</xref><xref>uisok</xref></xreflist><shortdesc>Low level helper function for testing Unicode text data.</shortdesc><text><![CDATA[   Low level helper function for testing Unicode text data.
]]></text><retval><text><![CDATA[   Returns the number of bytes occupied by the first character of the
   specified string, in the current encoding format.

]]></text></retval></ref><ref name="ucwidth" syntax="int ucwidth(int c);"><xreflist><xref>uwidth_max</xref><xref>ugetc</xref><xref>ugetx</xref><xref>usetc</xref><xref>uwidth</xref><xref>uisok</xref></xreflist><shortdesc>Low level helper function for testing Unicode text data.</shortdesc><text><![CDATA[   Low level helper function for testing Unicode text data.
]]></text><retval><text><![CDATA[   Returns the number of bytes that would be occupied by the specified
   character value, when encoded in the current format.

]]></text></retval></ref><ref name="uisok" syntax="int uisok(int c);"><xreflist><xref>ugetc</xref><xref>ugetx</xref><xref>usetc</xref><xref>uwidth</xref><xref>ucwidth</xref></xreflist><shortdesc>Low level helper function for testing Unicode text data.</shortdesc><text><![CDATA[   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.
]]></text><retval><text><![CDATA[   Returns non-zero if the value can be correctly encoded, zero otherwise.

]]></text></retval></ref><ref name="uoffset" syntax="int uoffset(const char *s, int index);"><xreflist><xref>ugetat</xref><xref>usetat</xref><xref>uinsert</xref><xref>uremove</xref></xreflist><shortdesc>Finds the offset of a character in a string.</shortdesc><text><![CDATA[   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:
<pre class="code">
      int from_third_letter = uoffset(text_string, 2);</pre>
]]></text><retval><text><![CDATA[   Returns the offset in bytes to the specified character.

]]></text></retval></ref><ref name="ugetat" syntax="int ugetat(const char *s, int index);"><xreflist><xref>uoffset</xref><xref>usetat</xref><xref>uinsert</xref><xref>uremove</xref></xreflist><shortdesc>Finds out the value of a character in a string.</shortdesc><text><![CDATA[   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:
<pre class="code">
      int third_letter = ugetat(text_string, 2);</pre>
]]></text><retval><text><![CDATA[   Returns the character value at the specified index in the string.

]]></text></retval></ref><ref name="usetat" syntax="int usetat(char *s, int index, int c);"><xreflist><xref>uoffset</xref><xref>ugetat</xref><xref>uinsert</xref><xref>uremove</xref></xreflist><shortdesc>Replaces a character in a string.</shortdesc><text><![CDATA[   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:
<pre class="code">
      usetat(text_string, 2, letter_a);</pre>
]]></text><retval><text><![CDATA[   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.

]]></text></retval></ref><ref name="uinsert" syntax="int uinsert(char *s, int index, int c);"><xreflist><xref>uoffset</xref><xref>ugetat</xref><xref>usetat</xref><xref>uremove</xref></xreflist><shortdesc>Inserts a character in a string.</shortdesc><text><![CDATA[   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:
<pre class="code">
      uinsert(text_string, 0, prefix_letter);</pre>
]]></text><retval><text><![CDATA[   Returns the number of bytes by which the trailing part of the string was
   moved.

]]></text></retval></ref><ref name="uremove" syntax="int uremove(char *s, int index);"><xreflist><xref>uoffset</xref><xref>ugetat</xref><xref>usetat</xref><xref>uinsert</xref></xreflist><shortdesc>Removes a character from a string.</shortdesc><text><![CDATA[   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:
<pre class="code">
      int length_in_bytes = ustrsizez(text_string);
      ...
      length_in_bytes -= uremove(text_string, -1);</pre>
]]></text><retval><text><![CDATA[   Returns the number of bytes by which the trailing part of the string was
   moved.

]]></text></retval></ref><ref name="ustrsize" syntax="int ustrsize(const char *s);"><xreflist><xref>ustrsizez</xref><xref>empty_string</xref></xreflist><ereflist><eref>exunicod</eref></ereflist><shortdesc>Size of the string in bytes without null terminator.</shortdesc><text><![CDATA[   Returns the size of the specified string in bytes, not including the
   trailing null character.

]]></text></ref><ref name="ustrsizez" syntax="int ustrsizez(const char *s);"><xreflist><xref>ustrsize</xref><xref>empty_string</xref></xreflist><ereflist><eref>exunicod</eref></ereflist><shortdesc>Size of the string in bytes including null terminator.</shortdesc><text><![CDATA[   Returns the size of the specified string in bytes, including the trailing
   null character.

]]></text></ref><ref name="uwidth_max" syntax="int uwidth_max(int type);"><xreflist><xref>uwidth</xref><xref>ucwidth</xref></xreflist><shortdesc>Number of bytes a character can occupy.</shortdesc><text><![CDATA[   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:
<pre class="code">
      char *temp_buffer = malloc(256 * uwidth_max(U_UTF8));</pre>

]]></text></ref><ref name="utolower" syntax="int utolower(int c);"><xreflist><xref>utoupper</xref><xref>ugetc</xref><xref>ugetx</xref><xref>usetc</xref><xref>uwidth</xref><xref>ucwidth</xref><xref>uisok</xref></xreflist><shortdesc>Converts a letter to lower case.</shortdesc><text><![CDATA[   This function returns `c', converting it to lower case if it is upper case.

]]></text></ref><ref name="utoupper" syntax="int utoupper(int c);"><xreflist><xref>utolower</xref><xref>ugetc</xref><xref>ugetx</xref><xref>usetc</xref><xref>uwidth</xref><xref>ucwidth</xref><xref>uisok</xref></xreflist><shortdesc>Converts a letter to upper case.</shortdesc><text><![CDATA[   This function returns `c', converting it to upper case if it is lower case.

]]></text></ref><ref name="uisspace" syntax="int uisspace(int c);"><xreflist><xref>uisdigit</xref><xref>ugetc</xref><xref>usetc</xref><xref>uwidth</xref><xref>ucwidth</xref><xref>uisok</xref></xreflist><shortdesc>Tells if a character is whitespace.</shortdesc><text><![CDATA[   Returns nonzero if `c' is whitespace, that is, carriage return, newline,
   form feed, tab, vertical tab, or space. Example:
<pre class="code">
      for (counter = 0; counter &lt; ustrlen(text_string); counter++) {
	 if (uisspace(ugetat(text_string, counter)))
	    usetat(text_string, counter, '_');
      }</pre>

]]></text></ref><ref name="uisdigit" syntax="int uisdigit(int c);"><xreflist><xref>uisspace</xref><xref>ugetc</xref><xref>usetc</xref><xref>uwidth</xref><xref>ucwidth</xref><xref>uisok</xref></xreflist><shortdesc>Tells if a character is a digit.</shortdesc><text><![CDATA[   Returns nonzero if `c' is a digit.
<pre class="code">
      for (counter = 0; counter &lt; ustrlen(text_string); counter++) {
	 if (uisdigit(ugetat(text_string, counter)))
	    usetat(text_string, counter, '*');
      }</pre>

]]></text></ref><ref name="ustrdup" syntax="char *ustrdup(const char *src)"><xreflist><xref>_ustrdup</xref><xref>uconvert</xref><xref>ustrsize</xref><xref>ustrsizez</xref></xreflist><ereflist><eref>exconfig</eref></ereflist><shortdesc>Duplicates a string.</shortdesc><text><![CDATA[   This functions copies the null-terminated string `src' into a newly
   allocated area of memory, effectively duplicating it. Example:
<pre class="code">
      void manipulate_string(const char *input_string)
      {
	 char *temp_buffer = ustrdup(input_string);
	 /* Now we can modify temp_buffer */
	 ...</pre>
]]></text><retval><text><![CDATA[   Returns the newly allocated string. This memory must be freed by the
   caller. Returns NULL if it cannot allocate space for the duplicated string.

]]></text></retval></ref><ref name="_ustrdup" syntax="char *_ustrdup(const char *src, void* (*malloc_func)(size_t))"><xreflist><xref>ustrdup</xref><xref>uconvert</xref><xref>ustrsize</xref><xref>ustrsizez</xref></xreflist><shortdesc>Duplicates a string with a custom memory allocator.</shortdesc><text><![CDATA[   Does the same as ustrdup(), but allows the user to specify a custom memory
   allocator function.

]]></text></ref><ref name="ustrcpy" syntax="char *ustrcpy(char *dest, const char *src);"><xreflist><xref>uconvert</xref><xref>ustrzcpy</xref><xref>ustrncpy</xref></xreflist><ereflist><eref>exunicod</eref></ereflist><shortdesc>Copies a string into another one.</shortdesc><text><![CDATA[   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.
]]></text><retval><text><![CDATA[   Returns the value of dest.

]]></text></retval></ref><ref name="ustrzcpy" syntax="char *ustrzcpy(char *dest, int size, const char *src);"><xreflist><xref>uconvert</xref><xref>ustrcpy</xref><xref>ustrzncpy</xref></xreflist><ereflist><eref>ex3buf</eref><eref>exgui</eref></ereflist><shortdesc>Copies a string into another one, specifying size.</shortdesc><text><![CDATA[   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.
]]></text><retval><text><![CDATA[   Returns the value of `dest'.

]]></text></retval></ref><ref name="ustrcat" syntax="char *ustrcat(char *dest, const char *src);"><xreflist><xref>uconvert</xref><xref>ustrzcat</xref><xref>ustrncat</xref></xreflist><ereflist><eref>exunicod</eref></ereflist><shortdesc>Concatenates a string to another one.</shortdesc><text><![CDATA[   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.
]]></text><retval><text><![CDATA[   Returns the value of `dest'.

]]></text></retval></ref><ref name="ustrzcat" syntax="char *ustrzcat(char *dest, int size, const char *src);"><xreflist><xref>uconvert</xref><xref>ustrcat</xref><xref>ustrzncat</xref></xreflist><ereflist><eref>exgui</eref></ereflist><shortdesc>Concatenates a string to another one, specifying size.</shortdesc><text><![CDATA[   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.
]]></text><retval><text><![CDATA[   Returns the value of `dest'.

]]></text></retval></ref><ref name="ustrlen" syntax="int ustrlen(const char *s);"><xreflist><xref>uconvert</xref><xref>ustrsize</xref><xref>ustrsizez</xref></xreflist><shortdesc>Tells the number of characters in a string.</shortdesc><text><![CDATA[   This function returns the number of characters in `s'. Note that this
   doesn't have to equal the string's size in bytes.

]]></text></ref><ref name="ustrcmp" syntax="int ustrcmp(const char *s1, const char *s2);"><xreflist><xref>uconvert</xref><xref>ustrsize</xref><xref>ustrsizez</xref><xref>ustrncmp</xref><xref>ustricmp</xref><xref>ustrnicmp</xref></xreflist><shortdesc>Compares two strings.</shortdesc><text><![CDATA[   This function compares `s1' and `s2'.
]]></text><retval><text><![CDATA[   Returns zero if the strings are equal, a positive number if `s1' comes
   after `s2' in the ASCII collating sequence, else a negative number.

]]></text></retval></ref><ref name="ustrncpy" syntax="char *ustrncpy(char *dest, const char *src, int n);"><xreflist><xref>uconvert</xref><xref>ustrcpy</xref><xref>ustrzncpy</xref></xreflist><shortdesc>Copies a string into another one, specifying size.</shortdesc><text><![CDATA[   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.
]]></text><retval><text><![CDATA[   The return value is the value of `dest'.

]]></text></retval></ref><ref name="ustrzncpy" syntax="char *ustrzncpy(char *dest, int size, const char *src, int n);"><xreflist><xref>uconvert</xref><xref>ustrzcpy</xref><xref>ustrncpy</xref></xreflist><ereflist><eref>exkeys</eref></ereflist><shortdesc>Copies a string into another one, specifying size.</shortdesc><text><![CDATA[   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.
]]></text><retval><text><![CDATA[   The return value is the value of `dest'.

]]></text></retval></ref><ref name="ustrncat" syntax="char *ustrncat(char *dest, const char *src, int n);"><xreflist><xref>uconvert</xref><xref>ustrcat</xref><xref>ustrzncat</xref></xreflist><shortdesc>Concatenates a string to another one, specifying size.</shortdesc><text><![CDATA[   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.
]]></text><retval><text><![CDATA[   The return value is the value of `dest'.

]]></text></retval></ref><ref name="ustrzncat" syntax="char *ustrzncat(char *dest, int size, const char *src, int n);"><xreflist><xref>uconvert</xref><xref>ustrzcat</xref><xref>ustrncat</xref></xreflist><shortdesc>Concatenates a string to another one, specifying size.</shortdesc><text><![CDATA[   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.
]]></text><retval><text><![CDATA[   The return value is the value of `dest'.

]]></text></retval></ref><ref name="ustrncmp" syntax="int ustrncmp(const char *s1, const char *s2, int n);"><xreflist><xref>uconvert</xref><xref>ustrsize</xref><xref>ustrsizez</xref><xref>ustrcmp</xref><xref>ustricmp</xref><xref>ustrnicmp</xref></xreflist><shortdesc>Compares up to n letters of two strings.</shortdesc><text><![CDATA[   This function compares up to `n' characters of `s1' and `s2'. Example:
<pre class="code">
      if (ustrncmp(prefix, long_string, ustrlen(prefix)) == 0) {
	 /* long_string starts with prefix */
      }</pre>
]]></text><retval><text><![CDATA[   Returns zero if the substrings are equal, a positive number if `s1' comes
   after `s2' in the ASCII collating sequence, else a negative number.

]]></text></retval></ref><ref name="ustricmp" syntax="int ustricmp(const char *s1, const char *s2);"><xreflist><xref>uconvert</xref><xref>ustrsize</xref><xref>ustrsizez</xref><xref>ustrnicmp</xref><xref>ustrcmp</xref><xref>ustrncmp</xref></xreflist><ereflist><eref>exconfig</eref></ereflist><shortdesc>Compares two strings ignoring case.</shortdesc><text><![CDATA[   This function compares `s1' and `s2', ignoring case. Example:
<pre class="code">
      if (ustricmp(string, user_input) == 0) {
	 /* string and user_input are equal (ignoring case) */
      }</pre>
]]></text><retval><text><![CDATA[   Returns zero if the strings are equal, a positive number if `s1' comes
   after `s2' in the ASCII collating sequence, else a negative number.

]]></text></retval></ref><ref name="ustrnicmp" syntax="int ustrnicmp(const char *s1, const char *s2, int n);"><xreflist><xref>uconvert</xref><xref>ustrsize</xref><xref>ustrsizez</xref><xref>ustricmp</xref><xref>ustrcmp</xref><xref>ustrncmp</xref></xreflist><shortdesc>Compares up to n letters of two strings ignoring case.</shortdesc><text><![CDATA[   This function compares up to `n' characters of `s1' and `s2', ignoring
   case. Example:
<pre class="code">
      if (ustrnicmp(prefix, long_string, ustrlen(prefix)) == 0) {
	 /* long_string starts with prefix (ignoring case) */
      }</pre>
]]></text><retval><text><![CDATA[   Returns zero if the strings are equal, a positive number if `s1' comes
   after `s2' in the ASCII collating sequence, else a negative number.

]]></text></retval></ref><ref name="ustrlwr" syntax="char *ustrlwr(char *s);"><xreflist><xref>uconvert</xref><xref>utolower</xref><xref>ustrupr</xref></xreflist><shortdesc>Replaces all letters with lower case.</shortdesc><text><![CDATA[   This function replaces all upper case letters in `s' with lower case
   letters. Example:
<pre class="code">
      char buffer[] = "UPPER CASE STRING";
      allegro_message(ustrlwr(buffer));</pre>
]]></text><retval><text><![CDATA[   The return value is the value of `s'.

]]></text></retval></ref><ref name="ustrupr" syntax="char *ustrupr(char *s);"><xreflist><xref>uconvert</xref><xref>utolower</xref><xref>ustrlwr</xref></xreflist><shortdesc>Replaces all letters with upper case.</shortdesc><text><![CDATA[   This function replaces all lower case letters in `s' with upper case
   letters. Example:
<pre class="code">
      char buffer[] = "lower case string";
      allegro_message(ustrupr(buffer));</pre>
]]></text><retval><text><![CDATA[   The return value is the value of `s'.

]]></text></retval></ref><ref name="ustrchr" syntax="char *ustrchr(const char *s, int c);"><xreflist><xref>uconvert</xref><xref>ustrrchr</xref><xref>ustrstr</xref><xref>ustrpbrk</xref><xref>ustrtok</xref></xreflist><shortdesc>Finds the first occurrence of a character in a string.</shortdesc><text><![CDATA[   Finds the first occurrence of the character `c' in the string `s'. Example:
<pre class="code">
      char *p = ustrchr("one,two,three,four", ',');</pre>
]]></text><retval><text><![CDATA[   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.

]]></text></retval></ref><ref name="ustrrchr" syntax="char *ustrrchr(const char *s, int c);"><xreflist><xref>uconvert</xref><xref>ustrchr</xref><xref>ustrstr</xref><xref>ustrpbrk</xref><xref>ustrtok</xref></xreflist><shortdesc>Finds the last occurence of a character in a string.</shortdesc><text><![CDATA[   Finds the last occurrence of the character `c' in the string `s'. Example:
<pre class="code">
      char *p = ustrrchr("one,two,three,four", ',');</pre>
]]></text><retval><text><![CDATA[   Returns a pointer fo the last occurrence of `c' in `s', or NULL if no
   match was found.

]]></text></retval></ref><ref name="ustrstr" syntax="char *ustrstr(const char *s1, const char *s2);"><xreflist><xref>uconvert</xref><xref>ustrchr</xref><xref>ustrrchr</xref><xref>ustrpbrk</xref><xref>ustrtok</xref></xreflist><shortdesc>Finds the first occurence of a string in another one.</shortdesc><text><![CDATA[   This function finds the first occurence of string `s2' in string `s1'.
   Example:
<pre class="code">
      char *p = ustrstr("hello world", "world");</pre>
]]></text><retval><text><![CDATA[   Returns a pointer within `s1', or NULL if `s2' wasn't found.

]]></text></retval></ref><ref name="ustrpbrk" syntax="char *ustrpbrk(const char *s, const char *set);"><xreflist><xref>uconvert</xref><xref>ustrchr</xref><xref>ustrrchr</xref><xref>ustrstr</xref><xref>ustrtok</xref></xreflist><shortdesc>Finds the first character that matches any in a set.</shortdesc><text><![CDATA[   This function finds the first character in `s' that matches any character
   in `set'. Example:
<pre class="code">
      char *p = ustrpbrk("one,two-three.four", "-. ");</pre>
]]></text><retval><text><![CDATA[   Returns a pointer to the first match, or NULL if none are found.

]]></text></retval></ref><ref name="ustrtok" syntax="char *ustrtok(char *s, const char *set);"><xreflist><xref>uconvert</xref><xref>ustrchr</xref><xref>ustrrchr</xref><xref>ustrstr</xref><xref>ustrpbrk</xref><xref>ustrtok_r</xref><xref>allegro_message</xref><xref>ustrncpy</xref></xreflist><ereflist><eref>exgui</eref></ereflist><shortdesc>Retrieves tokens from a string.</shortdesc><text><![CDATA[   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 reentrant (ie. you
   cannot parse two strings at the same time). Example:
<pre class="code">
      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);</pre>
]]></text><retval><text><![CDATA[   Returns a pointer to the token, or NULL if no more are found.

]]></text></retval></ref><ref name="ustrtok_r" syntax="char *ustrtok_r(char *s, const char *set, char **last);"><xreflist><xref>ustrtok</xref></xreflist><shortdesc>Reentrant function to retrieve tokens from a string.</shortdesc><text><![CDATA[   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:
<pre class="code">
      char *word, *last;
      char string[]="some-words with dashes";
      char *temp = ustrdup(string);
      word = ustrtok_r(string, " -", &amp;last);
      while (word) {
	 allegro_message("Found `%s'\n", word);
	 word = ustrtok_r(NULL, " -", &amp;last);
      }
      free(temp);</pre>
]]></text><retval><text><![CDATA[   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.

]]></text></retval></ref><ref name="uatof" syntax="double uatof(const char *s);"><xreflist><xref>uconvert</xref><xref>ustrtol</xref><xref>ustrtod</xref></xreflist><shortdesc>Converts a string into a double.</shortdesc><text><![CDATA[   Convert as much of the string as possible to an equivalent double
   precision real number. This function is almost like `ustrtod(s, NULL)'.
]]></text><retval><text><![CDATA[   Returns the equivalent value, or zero if the string does not represent a
   number.

]]></text></retval></ref><ref name="ustrtol" syntax="long ustrtol(const char *s, char **endp, int base);"><xreflist><xref>uconvert</xref><xref>ustrtod</xref><xref>uatof</xref></xreflist><shortdesc>Converts a string into an integer.</shortdesc><text><![CDATA[   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:
<pre class="code">
      char *endp, *string = "456.203 askdfg";
      int number = ustrtol(string, &amp;endp, 10);</pre>
]]></text><retval><text><![CDATA[   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'.

]]></text></retval></ref><ref name="ustrtod" syntax="double ustrtod(const char *s, char **endp);"><xreflist><xref>uconvert</xref><xref>ustrtol</xref><xref>uatof</xref></xreflist><shortdesc>Converts a string into a floating point number.</shortdesc><text><![CDATA[   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:
<pre class="code">
      char *endp, *string = "456.203 askdfg";
      double number = ustrtod(string, &amp;endp);</pre>
]]></text><retval><text><![CDATA[   Returns the string converted as a value of type `double'. If nothing was
   converted, returns zero with *endp pointing to the beginning of s.

]]></text></retval></ref><ref name="ustrerror" syntax="const char *ustrerror(int err);"><xreflist><xref>uconvert</xref><xref>allegro_error</xref></xreflist><shortdesc>Returns a string describing errno.</shortdesc><text><![CDATA[   This function returns a string that describes the error code `err', which
   normally comes from the variable `errno'. Example:
<pre class="code">
      PACKFILE *input_file = pack_fopen("badname", "r");
      if (input_file == NULL)
	 allegro_message("%s\nSorry!\n", ustrerror(errno));</pre>
]]></text><retval><text><![CDATA[   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.

]]></text></retval></ref><ref name="usprintf" syntax="int usprintf(char *buf, const char *format, ...);"><xreflist><xref>uconvert</xref><xref>uszprintf</xref><xref>uvsprintf</xref></xreflist><ereflist><eref>exkeys</eref></ereflist><shortdesc>Writes formatted data into a buffer.</shortdesc><text><![CDATA[   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.
]]></text><retval><text><![CDATA[   Returns the number of characters written, not including the terminating
   null character.

]]></text></retval></ref><ref name="uszprintf" syntax="int uszprintf(char *buf, int size, const char *format, ...);"><xreflist><xref>uconvert</xref><xref>usprintf</xref><xref>uvszprintf</xref></xreflist><ereflist><eref>exgui</eref></ereflist><shortdesc>Writes formatted data into a buffer, specifying size.</shortdesc><text><![CDATA[   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:
<pre class="code">
      char buffer[10];
      int player_score;
      ...
      uszprintf(buffer, sizeof(buffer), "Your score is: %d", player_score);</pre>
]]></text><retval><text><![CDATA[   Returns the number of characters that would have been written without
   eventual truncation (like with usprintf), not including the terminating
   null character.

]]></text></retval></ref><ref name="uvsprintf" syntax="int uvsprintf(char *buf, const char *format, va_list args);"><xreflist><xref>uconvert</xref><xref>usprintf</xref><xref>uvszprintf</xref></xreflist><shortdesc>Writes formatted data into a buffer, using variable arguments.</shortdesc><text><![CDATA[   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.
]]></text><retval><text><![CDATA[   Returns the number of characters written, not including the terminating
   null character.

]]></text></retval></ref><ref name="uvszprintf" syntax="int uvszprintf(char *buf, int size, const char *format, va_list args);"><xreflist><xref>uconvert</xref><xref>uszprintf</xref><xref>uvsprintf</xref></xreflist><shortdesc>Writes formatted data into a buffer, using size and variable arguments.</shortdesc><text><![CDATA[   This is like uszprintf(), but you pass the variable argument list
   directly, instead of the arguments themselves. Example:
<pre class="code">
      #include &lt;stdarg.h&gt;

      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);
      }</pre>
]]></text><retval><text><![CDATA[   Returns the number of characters that would have been written without
   eventual truncation (like with uvsprintf), not including the terminating
   null character.



]]></text></retval></ref></reflist></section><section title="Configuration routines"><text><![CDATA[
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.

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 soundcard testing. You are welcome to include the setup
program with your game, either as is or with modified graphics to fit better
your game.

]]></text><reflist><ref name="set_config_file" syntax="void set_config_file(const char *filename);"><xreflist><xref>set_config_data</xref><xref>override_config_file</xref><xref>push_config_state</xref><xref>set_uformat</xref><xref>Standard config variables</xref><xref>set_config_string</xref><xref>get_config_string</xref></xreflist><ereflist><eref>exconfig</eref></ereflist><shortdesc>Sets the configuration file.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="set_config_data" syntax="void set_config_data(const char *data, int length);"><xreflist><xref>set_config_file</xref><xref>override_config_data</xref><xref>push_config_state</xref><xref>Standard config variables</xref><xref>set_config_string</xref><xref>get_config_string</xref></xreflist><shortdesc>Sets a block of configuration data.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="override_config_file" syntax="void override_config_file(const char *filename);"><xreflist><xref>override_config_data</xref><xref>set_config_file</xref></xreflist><shortdesc>Specifies a file containing config overrides.</shortdesc><text><![CDATA[   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:
<pre class="code">
      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);</pre>

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

]]></text></ref><ref name="override_config_data" syntax="void override_config_data(const char *data, int length);"><xreflist><xref>override_config_file</xref><xref>set_config_data</xref></xreflist><shortdesc>Specifies a block of data containing config overrides.</shortdesc><text><![CDATA[   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:
<pre class="code">
      /* 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));</pre>

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

]]></text></ref><ref name="push_config_state" syntax="void push_config_state();"><xreflist><xref>pop_config_state</xref><xref>set_config_file</xref><xref>save_joystick_data</xref></xreflist><ereflist><eref>exconfig</eref></ereflist><shortdesc>Pushes the current configuration state.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="pop_config_state" syntax="void pop_config_state();"><xreflist><xref>push_config_state</xref></xreflist><ereflist><eref>exconfig</eref></ereflist><shortdesc>Pops a previously pushed configuration state.</shortdesc><text><![CDATA[   Pops a configuration state previously stored by push_config_state(),
   replacing the current config source with it.

]]></text></ref><ref name="flush_config_file" syntax="void flush_config_file();"><xreflist><xref>set_config_file</xref><xref>override_config_file</xref><xref>push_config_state</xref></xreflist><shortdesc>Flushes the current config file to disk.</shortdesc><text><![CDATA[   Writes the current config file to disk if the contents have changed
   since it was loaded or since the latest call to the function.

]]></text></ref><ref name="reload_config_texts" syntax="void reload_config_texts(const char *new_language);"><xreflist><xref>get_config_text</xref><xref>get_config_string</xref><xref>Standard config variables</xref></xreflist><shortdesc>Reloads translated strings returned by get_config_text().</shortdesc><text><![CDATA[   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:
<pre class="code">
      ...
      /* The user selects French from a language choice menu. */
      reload_config_texts("FR");</pre>

]]></text></ref><ref name="hook_config_section" syntax="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));"><xreflist><xref>config_is_hooked</xref></xreflist><shortdesc>Hooks a configuration file section with custom handlers.</shortdesc><text><![CDATA[   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:
<pre class="code">
      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()</pre>

]]></text></ref><ref name="config_is_hooked" syntax="int config_is_hooked(const char *section);"><xreflist><xref>hook_config_section</xref></xreflist><shortdesc>Tells if a config section has custom hooks.</shortdesc><text><![CDATA[   Returns TRUE if the specified config section has been hooked. Example:
<pre class="code">
      if (config_is_hooked("high_scores")) {
	 hook_config_section("high_scores, NULL, NULL, NULL);
      }</pre>

]]></text></ref><ref name="get_config_string" syntax="const char *get_config_string(const char *section, const char *name, const char *def);"><xreflist><xref>set_config_file</xref><xref>set_config_string</xref><xref>get_config_argv</xref><xref>get_config_float</xref><xref>get_config_hex</xref><xref>get_config_int</xref><xref>get_config_id</xref><xref>get_config_text</xref></xreflist><ereflist><eref>exconfig</eref></ereflist><shortdesc>Retrieves a string from the configuration file.</shortdesc><text><![CDATA[   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:
<pre class="code">
      const char *lang = get_config_string("system", "language", "EN");
</pre>
]]></text><retval><text><![CDATA[   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.

]]></text></retval></ref><ref name="get_config_int" syntax="int get_config_int(const char *section, const char *name, int def);"><xreflist><xref>set_config_file</xref><xref>set_config_int</xref><xref>get_config_string</xref><xref>get_config_argv</xref><xref>get_config_float</xref><xref>get_config_hex</xref><xref>get_config_id</xref></xreflist><ereflist><eref>exconfig</eref></ereflist><shortdesc>Retrieves an integer from the configuration file.</shortdesc><text><![CDATA[   Reads an integer variable from the current config file. See the comments
   about get_config_string().

]]></text></ref><ref name="get_config_hex" syntax="int get_config_hex(const char *section, const char *name, int def);"><xreflist><xref>set_config_file</xref><xref>set_config_hex</xref><xref>get_config_string</xref><xref>get_config_argv</xref><xref>get_config_float</xref><xref>get_config_int</xref><xref>get_config_id</xref></xreflist><shortdesc>Retrieves a hexadecimal value from the configuration file.</shortdesc><text><![CDATA[   Reads an integer variable from the current config file, in hexadecimal
   format. See the comments about get_config_string().

]]></text></ref><ref name="get_config_float" syntax="float get_config_float(const char *section, const char *name, float def);"><xreflist><xref>set_config_file</xref><xref>set_config_float</xref><xref>get_config_string</xref><xref>get_config_argv</xref><xref>get_config_hex</xref><xref>get_config_int</xref><xref>get_config_id</xref></xreflist><shortdesc>Retrieves a float from the configuration file.</shortdesc><text><![CDATA[   Reads a floating point variable from the current config file. See the
   comments about get_config_string().

]]></text></ref><ref name="get_config_id" syntax="int get_config_id(const char *section, const char *name, int def);"><xreflist><xref>set_config_file</xref><xref>set_config_id</xref><xref>get_config_string</xref><xref>get_config_argv</xref><xref>get_config_float</xref><xref>get_config_hex</xref><xref>get_config_int</xref></xreflist><shortdesc>Retrieves a driver ID from a configuration file.</shortdesc><text><![CDATA[   Reads a 4-letter driver ID variable from the current config file. See the
   comments about get_config_string().

]]></text></ref><ref name="get_config_argv" syntax="char **get_config_argv(const char *section, const char *name, int *argc);"><xreflist><xref>set_config_file</xref><xref>get_config_string</xref><xref>get_config_float</xref><xref>get_config_hex</xref><xref>get_config_int</xref><xref>get_config_id</xref></xreflist><ereflist><eref>exconfig</eref></ereflist><shortdesc>Reads a token list from the configuration file.</shortdesc><text><![CDATA[   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.
]]></text><retval><text><![CDATA[   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.

]]></text></retval></ref><ref name="get_config_text" syntax="const char *get_config_text(const char *msg);"><xreflist><xref>get_config_string</xref><xref>reload_config_texts</xref><xref>Standard config variables</xref></xreflist><shortdesc>Returns a string translated to the current language.</shortdesc><text><![CDATA[   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.
]]></text><retval><text><![CDATA[   Returns a suitable translation if one can be found or a copy of the
   parameter if nothing else is available.

]]></text></retval></ref><ref name="set_config_string" syntax="void set_config_string(const char *section, const char *name, const char *val);"><xreflist><xref>set_config_file</xref><xref>get_config_string</xref><xref>set_config_float</xref><xref>set_config_hex</xref><xref>set_config_int</xref><xref>set_config_id</xref></xreflist><shortdesc>Writes a string in the configuration file.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="set_config_int" syntax="void set_config_int(const char *section, const char *name, int val);"><xreflist><xref>set_config_file</xref><xref>get_config_int</xref><xref>set_config_string</xref><xref>set_config_float</xref><xref>set_config_hex</xref><xref>set_config_id</xref></xreflist><shortdesc>Writes an integer in the configuration file.</shortdesc><text><![CDATA[   Writes an integer variable to the current config file. See the comments
   about set_config_string().

]]></text></ref><ref name="set_config_hex" syntax="void set_config_hex(const char *section, const char *name, int val);"><xreflist><xref>set_config_file</xref><xref>get_config_hex</xref><xref>set_config_string</xref><xref>set_config_float</xref><xref>set_config_int</xref><xref>set_config_id</xref></xreflist><shortdesc>Writes a hexadecimal integer in the configuration file.</shortdesc><text><![CDATA[   Writes an integer variable to the current config file, in hexadecimal
   format. See the comments about set_config_string().

]]></text></ref><ref name="set_config_float" syntax="void set_config_float(const char *section, const char *name, float val);"><xreflist><xref>set_config_file</xref><xref>get_config_float</xref><xref>set_config_string</xref><xref>set_config_hex</xref><xref>set_config_int</xref><xref>set_config_id</xref></xreflist><shortdesc>Writes a float in the configuration file.</shortdesc><text><![CDATA[   Writes a floating point variable to the current config file. See the
   comments about set_config_string().

]]></text></ref><ref name="set_config_id" syntax="void set_config_id(const char *section, const char *name, int val);"><xreflist><xref>set_config_file</xref><xref>get_config_id</xref><xref>set_config_string</xref><xref>set_config_float</xref><xref>set_config_hex</xref><xref>set_config_int</xref></xreflist><shortdesc>Writes a driver ID in the configuration file.</shortdesc><text><![CDATA[   Writes a 4-letter driver ID variable to the current config file. See the
   comments about set_config_string().

]]></text></ref><ref name="list_config_entries" syntax="int list_config_entries(const char *section, const char ***names);"><xreflist><xref>set_config_file</xref><xref>get_config_string</xref><xref>list_config_sections</xref><xref>free_config_entries</xref></xreflist><shortdesc>Lists the names of all entries in a config section</shortdesc><text><![CDATA[   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:
<pre class="code">
   int i, n;
   char const **sections = NULL;
   char const **entries = NULL;

   n = list_config_sections(&amp;sections);
   /* loop through all section names */
   for (i = 0; i < n; i++)
   {
      int j, m;
      printf("%s\n", sections[i]);
      m = list_config_entries(sections[i], &amp;entries);
      /* loop through all entries in the section */
      for (j = 0; j < m; j++)
      {
          printf(" %s=\"%s\"\n", entries[j], get_config_string(
             sections[i], entries[j], "-"));
      }
   }
   free_config_entries(&amp;sections);
   free_config_entries(&amp;entries);</pre>
]]></text><retval><text><![CDATA[   Returns the number of valid strings in the names array.

]]></text></retval></ref><ref name="list_config_sections" syntax="int list_config_sections(const char ***names);"><xreflist><xref>list_config_entries</xref><xref>set_config_file</xref><xref>get_config_string</xref><xref>free_config_entries</xref></xreflist><shortdesc>Lists the names of all sections available in the current configuration.</shortdesc><text><![CDATA[   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.
]]></text><retval><text><![CDATA[   Returns the number of valid strings in the names array.

]]></text></retval></ref><ref name="free_config_entries" syntax="int free_config_entries(const char ***names);"><xreflist><xref>list_config_entries</xref><xref>list_config_sections</xref></xreflist><shortdesc>Frees memory allocated for config entry lists.</shortdesc><text><![CDATA[
   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.

]]></text></ref></reflist><section title="Standard config variables"><xreflist><xref>set_config_file</xref><xref>set_config_string</xref><xref>get_config_string</xref></xreflist><text><![CDATA[Allegro uses these standard variables from the configuration file:
]]></text><text><![CDATA[<ul><li>
[system]<br>
   Section containing general purpose variables:
<ul><li>
system = x<br>
   Specifies which system driver to use. This is currently only useful on
   Linux, for choosing between the XWindows ("XWIN") or console ("LNXC")
   modes.
<li>
keyboard = x<br>
   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 basename 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.
<li>
language = x<br>
   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 basename 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.
<li>
disable_screensaver = x<br>
   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.
<li>
menu_opening_delay = x<br>
   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.
<li>
XInitThreads = x<br>
   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.
</ul><li>
[graphics]<br>
   Section containing graphics configuration information, using the
   variables:
<ul><li>
gfx_card = x<br>
   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.
<li>
gfx_cardw = x<br>
   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.
<li>
disable_vsync = x<br>
   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.
<li>
vbeaf_driver = x<br>
   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).
<li>
framebuffer = x<br>
   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'.
<li>
force_centering = x<br>
   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.
<li>
disable_direct_updating = x<br>
   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.
</ul><li>
[mouse]<br>
   Section containing mouse configuration information, using the variables:
<ul><li>
mouse = x<br>
   Mouse driver type. Available DOS drivers are:
<pre class="text">
      MICK - mickey mode driver (normally the best)
      I33  - int 0x33 callback driver
      POLL - timer polling (for use under NT)
</pre>
   Linux console mouse drivers are:
<pre class="text">
      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)</pre>
<li>
num_buttons = x<br>
   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.
<li>
emulate_three = x<br>
   Sets whether to emulate a third mouse button by detecting chords of the
   left and right buttons (yes or no). Defaults to no.
<li>
mouse_device = x<br>
   Linux only: specifies the name of the mouse device file (eg.
   `/dev/mouse').
<li>
ev_absolute = x<br>
   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 additionnal tools
   work in absolute mode.
<li>
ev_min_x = x<br>
ev_max_x = x<br>
ev_min_y = x<br>
ev_max_y = x<br>
ev_min_z = x<br>
ev_max_z = x<br>
   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.
<li>
ev_abs_to_rel_x = x<br>
ev_abs_to_rel_y = x<br>
ev_abs_to_rel_z = x<br>
   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).
<li>
mouse_accel_factor = x<br>
   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.
</ul><li>
[sound]<br>
   Section containing sound configuration information, using the variables:
<ul><li>
digi_card = x<br>
   Sets the driver to use for playing digital samples.
<li>
midi_card = x<br>
   Sets the driver to use for MIDI music.
<li>
digi_input_card = x<br>
   Sets the driver to use for digital sample input.
<li>
midi_input_card = x<br>
   Sets the driver to use for MIDI data input.
<li>
digi_voices = x<br>
   Specifies the minimum number of voices to reserve for use by the digital
   sound driver. How many are possible depends on the driver.
<li>
midi_voices = x<br>
   Specifies the minimum number of voices to reserve for use by the MIDI
   sound driver. How many are possible depends on the driver.
<li>
digi_volume = x<br>
   Sets the volume for digital sample playback, from 0 to 255.
<li>
midi_volume = x<br>
   Sets the volume for midi music playback, from 0 to 255.
<li>
quality = x<br>
   Controls the sound quality vs. performance tradeoff for the sample mixing
   code. This can be set to any of the values:<pre class="text">
      0 - fast mixing of 8-bit data into 16-bit buffers
      1 - true 16-bit mixing (requires a 16-bit stereo soundcard)
      2 - interpolated 16-bit mixing</pre>
<li>
flip_pan = x<br>
   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.
<li>
sound_freq = x<br>
   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.
<li>
sound_bits = x<br>
   Unix and BeOS: sets the preferred number of bits (8 or 16).
<li>
sound_stereo = x<br>
   Unix and BeOS: selects mono or stereo output (0 or 1).
<li>
sound_port = x<br>
   DOS only: sets the soundcard port address (this is usually 220).
<li>
sound_dma = x<br>
   DOS only: sets the soundcard DMA channel (this is usually 1).
<li>
sound_irq = x<br>
   DOS only: sets the soundcard IRQ number (this is usually 7).
<li>
fm_port = x<br>
   DOS only: sets the port address of the OPL synth (this is usually 388).
<li>
mpu_port = x<br>
   DOS only: sets the port address of the MPU-401 MIDI interface (this is
   usually 330).
<li>
mpu_irq = x<br>
   DOS only: sets the IRQ for the MPU-401 (this is usually the same as
   sound_irq).
<li>
ibk_file = x<br>
   DOS only: specifies the name of a .IBK file which will be used to replace
   the standard Adlib patch set.
<li>
ibk_drum_file = x<br>
   DOS only: specifies the name of a .IBK file which will be used to replace
   the standard set of Adlib percussion patches.
<li>
oss_driver = x<br>
   Unix only: sets the OSS device driver name. Usually `/dev/dsp' or
   `/dev/audio', but could be a particular device (e.g. `/dev/dsp2').
<li>
oss_numfrags = x<br>
oss_fragsize = x<br>
   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.
<li>
oss_midi_driver = x<br>
   Unix only: sets the OSS MIDI device name. Usually `/dev/sequencer'.
<li>
oss_mixer_driver = x<br>
   Unix only: sets the OSS mixer device name. Usually `/dev/mixer'.
<li>
esd_server = x<br>
   Unix only: where to find the ESD (Enlightened Sound Daemon) server.
<li>
alsa_card = x<br>
alsa_pcmdevice = x<br>
   Unix only: card number and PCM device for the ALSA 0.5 sound driver.
<li>
alsa_device = x<br>
   Unix only: device name for the ALSA 0.9 sound driver. The format is
   &lt;driver&gt;[:&lt;card&gt;,&lt;device&gt;], for example: `hw:0,1'.
<li>
alsa_mixer_device = x<br>
   Unix only: mixer device name for the ALSA 0.9 sound driver. The
   default is "default".
<li>
alsa_mixer_elem = x<br>
   Unix only: mixer element name for the ALSA 0.9 driver. The default
   is PCM.
<li>
alsa_numfrags = x<br>
   Unix only: number of ALSA driver fragments (buffers).
<li>
alsa_fragsize = x<br>
   Unix only: size of each ALSA fragment, in samples.
<li>
alsa_rawmidi_card = x<br>
   Unix only: card number and device for the ALSA 0.5 midi driver.
<li>
alsa_rawmidi_device = x<br>
   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).
<li>
jack_client_name = x<br>
   Sets the name with which Allegro should identify itself to the Jack
   audio server.
<li>
jack_buffer_size = x<br>
   Forces a buffer size for the transfer buffer from Allegro's mixer
   to Jack.
<li>
be_midi_quality = x<br>
   BeOS only: system MIDI synthesizer instruments quality. 0 uses low
   quality 8-bit 11 kHz samples, 1 uses 16-bit 22 kHz samples.
<li>
be_midi_freq = x<br>
   BeOS only: MIDI sample mixing frequency in Hz. Can be 11025, 22050 or
   44100.
<li>
be_midi_interpolation = x<br>
   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.
<li>
be_midi_reverb = x<br>
   BeOS only: reverberation intensity, from 0 to 5. 0 disables it, 5 is the
   strongest one.
<li>
ca_midi_quality = x<br>
   MacOS X only: CoreAudio MIDI synthesizer rendering quality, from 0 to 127.
   Higher qualities sound better but increase the CPU work load.
<li>
ca_midi_reverb = x<br>
   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).
<li>
patches = x<br>
   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.
</ul><li>
[midimap]<br>
   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:
<ul><li>
p&lt;n&gt; = bank0 bank1 prog pitch<br>
   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:
<pre class="text">
      p36 = 0 34 9 12
</pre>
   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.
</ul><li>
[joystick]<br>
   Section containing joystick configuration information, using the
   variables:
<ul><li>
joytype = x<br>
   Specifies which joystick driver to use when the program requests
   JOY_TYPE_AUTODETECT.
<li>
joystick_device = x<br>
   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.
<li>
throttle_axis = x<br>
   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.
</ul></ul>


]]></text></section></section><section title="Mouse routines"><text><![CDATA[
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:
<ul><li>
Standard Allegro cursor<br>
   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.
<li>
Custom operating system cursor (hardware cursor)<br>
   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 upto 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.
<li>
Default operating system cursor<br>
   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.
</ul>
Not all drivers will support all functionality. See the platform specific
information for more details.

]]></text><reflist><ref name="install_mouse" syntax="int install_mouse();"><xreflist><xref>remove_mouse</xref><xref>poll_mouse</xref><xref>mouse_x</xref><xref>show_mouse</xref><xref>get_mouse_mickeys</xref><xref>position_mouse</xref><xref>set_mouse_range</xref><xref>set_mouse_speed</xref><xref>Standard config variables</xref></xreflist><ereflist><eref>Available Allegro examples</eref></ereflist><shortdesc>Installs the Allegro mouse handler.</shortdesc><text><![CDATA[   Installs the Allegro mouse handler. You must do this before using any
   other mouse functions.
]]></text><retval><text><![CDATA[   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
   overriden by the user, the global mouse variables will still report
   whatever the hardware is sending.

]]></text></retval></ref><ref name="remove_mouse" syntax="void remove_mouse();"><xreflist><xref>install_mouse</xref><xref>allegro_exit</xref></xreflist><shortdesc>Removes the mouse handler.</shortdesc><text><![CDATA[   Removes the mouse handler. You don't normally need to bother calling
   this, because allegro_exit() will do it for you.

]]></text></ref><ref name="poll_mouse" syntax="int poll_mouse();"><xreflist><xref>mouse_needs_poll</xref><xref>install_mouse</xref><xref>mouse_x</xref></xreflist><ereflist><eref>exlights</eref><eref>exmouse</eref><eref>exshade</eref><eref>exspline</eref><eref>extrans</eref></ereflist><shortdesc>Polls the mouse.</shortdesc><text><![CDATA[   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.
]]></text><retval><text><![CDATA[   Returns zero on success, or a negative number on failure (ie. no mouse
   driver installed).

]]></text></retval></ref><ref name="mouse_needs_poll" syntax="int mouse_needs_poll();"><xreflist><xref>poll_mouse</xref><xref>install_mouse</xref><xref>mouse_x</xref></xreflist><shortdesc>Tells if the mouse driver requires polling.</shortdesc><text><![CDATA[   Returns TRUE if the current mouse driver is operating in polling mode.

]]></text></ref><ref name="enable_hardware_cursor" syntax="void enable_hardware_cursor(void);"><xreflist><xref>install_mouse</xref><xref>show_mouse</xref><xref>set_mouse_sprite</xref><xref>get_mouse_mickeys</xref><xref>gfx_capabilities</xref><xref>disable_hardware_cursor</xref><xref>show_os_cursor</xref></xreflist><ereflist><eref>exsyscur</eref></ereflist><shortdesc>Enables the OS hardware cursor.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="disable_hardware_cursor" syntax="void disable_hardware_cursor(void);"><xreflist><xref>install_mouse</xref><xref>show_mouse</xref><xref>set_mouse_sprite</xref><xref>get_mouse_mickeys</xref><xref>gfx_capabilities</xref><xref>enable_hardware_cursor</xref></xreflist><shortdesc>Disables the OS hardware cursor.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="select_mouse_cursor" syntax="void select_mouse_cursor(int cursor);"><xreflist><xref>install_mouse</xref><xref>show_mouse</xref><xref>set_mouse_sprite</xref><xref>gfx_capabilities</xref><xref>enable_hardware_cursor</xref><xref>set_mouse_cursor_bitmap</xref><xref>show_os_cursor</xref></xreflist><ereflist><eref>exsyscur</eref></ereflist><shortdesc>Tells Allegro to select software or hardware cursor drawing.</shortdesc><text><![CDATA[   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:

   <b>MOUSE_CURSOR_NONE</b><br>
   Selects an invisible mouse cursor. In that sense, it is similar to calling
   show_mouse(NULL);

   <b>MOUSE_CURSOR_ALLEGRO</b><br>
   Selects the custom Allegro cursor, i.e. the one that you set with
   set_mouse_sprite().

   <b>MOUSE_CURSOR_ARROW</b><br>
   The operating system default arrow cursor.

   <b>MOUSE_CURSOR_BUSY</b><br>
   The operating system default `busy' cursor (hourglass).

   <b>MOUSE_CURSOR_QUESTION</b><br>
   The operating system default `question' cursor (arrow with question mark).

   <b>MOUSE_CURSOR_EDIT</b><br>
   The operating system default `edit' cursor (vertical bar).

   Example:
<pre class="code">
   /* 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);
</pre>

]]></text></ref><ref name="set_mouse_cursor_bitmap" syntax="void set_mouse_cursor_bitmap(int cursor, BITMAP *bmp);"><xreflist><xref>install_mouse</xref><xref>show_mouse</xref><xref>set_mouse_sprite</xref><xref>gfx_capabilities</xref><xref>enable_hardware_cursor</xref><xref>show_os_cursor</xref></xreflist><shortdesc>Changes the image Allegro uses for mouse cursors.</shortdesc><text><![CDATA[   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:<br>
   <b>MOUSE_CURSOR_ALLEGRO</b><br>
   <b>MOUSE_CURSOR_ARROW</b><br>
   <b>MOUSE_CURSOR_BUSY</b><br>
   <b>MOUSE_CURSOR_QUESTION</b><br>
   <b>MOUSE_CURSOR_EDIT</b><br>

   but <i>not</i> 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 substition (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.

]]></text></ref><ref name="mouse_x" syntax="extern volatile int mouse_x;"/><ref name="mouse_y" syntax="extern volatile int mouse_y;"/><ref name="mouse_z" syntax="extern volatile int mouse_z;"/><ref name="mouse_b" syntax="extern volatile int mouse_b;"/><ref name="mouse_pos" syntax="extern volatile int mouse_pos;"><xreflist><xref>install_mouse</xref><xref>poll_mouse</xref><xref>mouse_needs_poll</xref></xreflist><ereflist><eref>exalpha</eref><eref>exlights</eref><eref>exmouse</eref><eref>exshade</eref><eref>exspline</eref><eref>extrans</eref></ereflist><shortdesc>Global variable with the mouse position/button state.</shortdesc><text><![CDATA[   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' variable holds the current 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:
<pre class="code">
      if (mouse_b &amp; 1)
	 printf("Left button is pressed\n");

      if (!(mouse_b &amp; 2))
	 printf("Right button is not pressed\n");
</pre>
   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:
<pre class="code">
   int pos, x, y;

   pos = mouse_pos;
   x = pos >> 16;
   y = pos &amp; 0x0000ffff;
</pre>


]]></text></ref><ref name="mouse_sprite" syntax="extern BITMAP *mouse_sprite;"/><ref name="mouse_x_focus" syntax="extern int mouse_x_focus;"/><ref name="mouse_y_focus" syntax="extern int mouse_y_focus;"><xreflist><xref>set_mouse_sprite</xref><xref>set_mouse_sprite_focus</xref></xreflist><shortdesc>Global variable with the mouse sprite and focus point.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="show_mouse" syntax="void show_mouse(BITMAP *bmp);"><xreflist><xref>install_mouse</xref><xref>install_timer</xref><xref>set_mouse_sprite</xref><xref>scare_mouse</xref><xref>freeze_mouse_flag</xref><xref>show_os_cursor</xref></xreflist><ereflist><eref>exmouse</eref><eref>expal</eref><eref>exshade</eref><eref>exspline</eref><eref>exsyscur</eref></ereflist><shortdesc>Tells Allegro to display a mouse pointer on the screen.</shortdesc><text><![CDATA[   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().

]]></text></ref><ref name="scare_mouse" syntax="void scare_mouse();"><xreflist><xref>unscare_mouse</xref><xref>scare_mouse_area</xref><xref>show_mouse</xref></xreflist><shortdesc>Helper for hiding the mouse pointer before drawing.</shortdesc><text><![CDATA[   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().

]]></text></ref><ref name="scare_mouse_area" syntax="void scare_mouse_area(int x, int y, int w, int h);"><xreflist><xref>unscare_mouse</xref><xref>scare_mouse</xref><xref>show_mouse</xref></xreflist><shortdesc>Helper for hiding the mouse cursor before drawing in an area.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="unscare_mouse" syntax="void unscare_mouse();"><xreflist><xref>scare_mouse</xref><xref>scare_mouse_area</xref></xreflist><shortdesc>Undoes the effect of scare_mouse() or scare_mouse_area().</shortdesc><text><![CDATA[   Undoes the effect of a previous call to scare_mouse() or
   scare_mouse_area(), restoring the original pointer state.

]]></text></ref><ref name="show_os_cursor" syntax="int show_os_cursor(int cursor);"><xreflist><xref>show_mouse</xref><xref>set_mouse_cursor_bitmap</xref><xref>select_mouse_cursor</xref></xreflist><shortdesc>Low level function to display the operating system cursor.</shortdesc><text><![CDATA[   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
   suceeded 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.
]]></text><retval><text><![CDATA[   Returns 0 if a system cursor is being displayed after the function
   returns, or -1 otherwise.

]]></text></retval></ref><ref name="freeze_mouse_flag" syntax="extern volatile int freeze_mouse_flag;"><xreflist><xref>show_mouse</xref></xreflist><shortdesc>Flag to avoid redrawing the mouse pointer.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="position_mouse" syntax="void position_mouse(int x, int y);"><xreflist><xref>install_mouse</xref><xref>position_mouse_z</xref><xref>set_mouse_range</xref><xref>set_mouse_speed</xref></xreflist><shortdesc>Moves the mouse to the specified screen position.</shortdesc><text><![CDATA[   Moves the mouse to the specified screen position. It is safe to call even
   when a mouse pointer is being displayed.

]]></text></ref><ref name="position_mouse_z" syntax="void position_mouse_z(int z);"><xreflist><xref>install_mouse</xref><xref>position_mouse</xref></xreflist><shortdesc>Sets the mouse wheel position global variable.</shortdesc><text><![CDATA[   Sets the mouse wheel position variable to the specified value.

]]></text></ref><ref name="set_mouse_range" syntax="void set_mouse_range(int x1, int y1, int x2, int y2);"><xreflist><xref>install_mouse</xref><xref>set_mouse_speed</xref><xref>position_mouse</xref></xreflist><shortdesc>Sets the area of the screen restricting mouse movement.</shortdesc><text><![CDATA[   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).

]]></text></ref><ref name="set_mouse_speed" syntax="void set_mouse_speed(int xspeed, int yspeed);"><xreflist><xref>install_mouse</xref><xref>set_mouse_range</xref><xref>position_mouse</xref></xreflist><shortdesc>Sets the mouse speed.</shortdesc><text><![CDATA[   Sets the mouse speed. Larger values of xspeed and yspeed represent slower
   mouse movement: the default for both is 2.

]]></text></ref><ref name="set_mouse_sprite" syntax="void set_mouse_sprite(BITMAP *sprite);"><xreflist><xref>install_mouse</xref><xref>show_mouse</xref><xref>set_mouse_sprite_focus</xref></xreflist><ereflist><eref>exmouse</eref></ereflist><shortdesc>Sets the mouse sprite.</shortdesc><text><![CDATA[   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).

]]></text></ref><ref name="set_mouse_sprite_focus" syntax="void set_mouse_sprite_focus(int x, int y);"><xreflist><xref>set_mouse_sprite</xref></xreflist><ereflist><eref>exmouse</eref></ereflist><shortdesc>Sets the mouse sprite focus.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="get_mouse_mickeys" syntax="void get_mouse_mickeys(int *mickeyx, int *mickeyy);"><xreflist><xref>install_mouse</xref></xreflist><ereflist><eref>exmouse</eref></ereflist><shortdesc>How far the mouse has moved since the last call to this function.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="mouse_callback" syntax="extern void (*mouse_callback)(int flags);"><xreflist><xref>install_mouse</xref></xreflist><shortdesc>User specified mouse callback.</shortdesc><text><![CDATA[   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.



]]></text></ref></reflist></section><section title="Timer routines"><text><![CDATA[
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.)

]]></text><reflist><ref name="install_timer" syntax="int install_timer();"><xreflist><xref>remove_timer</xref><xref>install_int</xref></xreflist><ereflist><eref>Available Allegro examples</eref></ereflist><shortdesc>Installs the Allegro timer interrupt handler.</shortdesc><text><![CDATA[   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.
]]></text><retval><text><![CDATA[   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).

]]></text></retval></ref><ref name="remove_timer" syntax="void remove_timer();"><xreflist><xref>install_timer</xref><xref>allegro_exit</xref></xreflist><shortdesc>Removes the Allegro time handler.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="install_int" syntax="int install_int(void (*proc)(), int speed);"><xreflist><xref>install_timer</xref><xref>remove_int</xref><xref>install_int_ex</xref><xref>install_param_int</xref></xreflist><ereflist><eref>exscn3d</eref><eref>exswitch</eref><eref>extimer</eref><eref>exzbuf</eref></ereflist><shortdesc>Installs a user timer handler.</shortdesc><text><![CDATA[   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.
]]></text><retval><text><![CDATA[   Returns zero on success, or a negative number if there is no room to add
   a new user timer.

]]></text></retval></ref><ref name="install_int_ex" syntax="int install_int_ex(void (*proc)(), int speed);"><xreflist><xref>install_timer</xref><xref>remove_int</xref><xref>install_int</xref><xref>install_param_int_ex</xref></xreflist><ereflist><eref>excamera</eref><eref>exsprite</eref><eref>extimer</eref><eref>exunicod</eref><eref>exupdate</eref></ereflist><shortdesc>Adds or modifies a timer.</shortdesc><text><![CDATA[   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 occured 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:
<pre class="text">
      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
</pre>
   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:
<pre class="code">
      volatile int counter;

      void my_timer_handler()
      {
	 counter++;
      }

      END_OF_FUNCTION(my_timer_handler)
</pre>
   and in your initialisation code you should lock the memory:
<pre class="code">
      LOCK_VARIABLE(counter);
      LOCK_FUNCTION(my_timer_handler);
</pre>
   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.
]]></text><retval><text><![CDATA[   Returns zero on success, or a negative number if there is no room to add
   a new user timer.

]]></text></retval></ref><ref name="LOCK_VARIABLE" syntax="Macro LOCK_VARIABLE(variable_name);"><xreflist><xref>install_int</xref><xref>install_int_ex</xref></xreflist><ereflist><eref>exscn3d</eref><eref>exsprite</eref><eref>exswitch</eref><eref>extimer</eref><eref>exupdate</eref><eref>exzbuf</eref></ereflist><shortdesc>Locks the memory of a variable used by a timer.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="LOCK_FUNCTION" syntax="Macro LOCK_FUNCTION(function_name);"><xreflist><xref>install_int</xref><xref>install_int_ex</xref></xreflist><ereflist><eref>exkeys</eref><eref>exscn3d</eref><eref>exsprite</eref><eref>exswitch</eref><eref>extimer</eref><eref>exupdate</eref><eref>exzbuf</eref></ereflist><shortdesc>Locks the memory of a function used by a timer.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="END_OF_FUNCTION" syntax="Macro END_OF_FUNCTION(function_name);"><xreflist><xref>install_int</xref><xref>install_int_ex</xref></xreflist><ereflist><eref>exkeys</eref><eref>exscn3d</eref><eref>exsprite</eref><eref>exswitch</eref><eref>extimer</eref><eref>exupdate</eref><eref>exzbuf</eref></ereflist><shortdesc>Locks the code used by a timer.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="remove_int" syntax="void remove_int(void (*proc)());"><xreflist><xref>install_int</xref><xref>install_int_ex</xref><xref>remove_param_int</xref></xreflist><shortdesc>Removes a timers.</shortdesc><text><![CDATA[   Removes a function from the list of user interrupt routines. At program
   termination, allegro_exit() does this automatically.

]]></text></ref><ref name="install_param_int" syntax="int install_param_int(void (*proc)(void *), void *param, int speed);"><xreflist><xref>install_timer</xref><xref>remove_param_int</xref><xref>install_param_int_ex</xref><xref>install_int</xref></xreflist><shortdesc>Installs a timer routine with a customizable parameter.</shortdesc><text><![CDATA[   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().

]]></text></ref><ref name="install_param_int_ex" syntax="int install_param_int_ex(void (*proc)(void *), void *param, int speed);"><xreflist><xref>install_timer</xref><xref>remove_param_int</xref><xref>install_param_int</xref><xref>install_int_ex</xref></xreflist><shortdesc>Adds or modifies a timer with a customizable parameter.</shortdesc><text><![CDATA[   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().

]]></text></ref><ref name="remove_param_int" syntax="void remove_param_int(void (*proc)(void *), void *param);"><xreflist><xref>install_param_int</xref><xref>install_param_int_ex</xref><xref>remove_int</xref></xreflist><shortdesc>Removes a timer with a customizable parameter.</shortdesc><text><![CDATA[   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).

]]></text></ref><ref name="retrace_count" syntax="extern volatile int retrace_count;"><ereflist><eref>ex3d</eref><eref>exblend</eref><eref>exdbuf</eref><eref>exflip</eref><eref>exlights</eref></ereflist><shortdesc>Retrace count simulator.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="rest" syntax="void rest(unsigned int time);"><xreflist><xref>install_timer</xref><xref>rest_callback</xref><xref>vsync</xref><xref>d_yield_proc</xref></xreflist><ereflist><eref>exkeys</eref><eref>exmidi</eref><eref>exquat</eref><eref>exsample</eref><eref>exsprite</eref><eref>extimer</eref><eref>extrans</eref><eref>exunicod</eref></ereflist><shortdesc>Waits a specified number of milliseconds or yields CPU.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="rest_callback" syntax="void rest_callback(long time, void (*callback)())"><xreflist><xref>install_timer</xref><xref>rest</xref></xreflist><shortdesc>Like rest(), but calls the callback during the wait.</shortdesc><text><![CDATA[   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().



]]></text></ref></reflist></section><section title="Keyboard routines"><text><![CDATA[
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 acomplished through the keyboard variable
of the system section in a standard `allegro.cfg' configuration file. Read
chapter "Configuration routines" for more information about this.

]]></text><reflist><ref name="install_keyboard" syntax="int install_keyboard();"><xreflist><xref>remove_keyboard</xref><xref>poll_keyboard</xref><xref>key</xref><xref>keypressed</xref><xref>readkey</xref><xref>ureadkey</xref><xref>keyboard_callback</xref><xref>keyboard_ucallback</xref><xref>keyboard_lowlevel_callback</xref><xref>three_finger_flag</xref><xref>key_led_flag</xref><xref>set_leds</xref><xref>set_keyboard_rate</xref><xref>set_gfx_mode</xref><xref>Standard config variables</xref></xreflist><ereflist><eref>Available Allegro examples</eref></ereflist><shortdesc>Installs the Allegro keyboard interrupt handler.</shortdesc><text><![CDATA[   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_call). Example:
<pre class="code">
      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();</pre>
]]></text><retval><text><![CDATA[   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).

]]></text></retval></ref><ref name="remove_keyboard" syntax="void remove_keyboard();"><xreflist><xref>install_keyboard</xref><xref>allegro_exit</xref><xref>set_config_string</xref></xreflist><shortdesc>Removes the Allegro keyboard handler.</shortdesc><text><![CDATA[   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:
<pre class="code">
      remove_keyboard();
      /* Switch to Spanish keyboard mapping. */
      set_config_string("system", "keyboard", "es");
      install_keyboard();</pre>

]]></text></ref><ref name="install_keyboard_hooks" syntax="void install_keyboard_hooks(int (*keypressed)(), int (*readkey)());"><xreflist><xref>install_keyboard</xref><xref>keypressed</xref><xref>readkey</xref></xreflist><shortdesc>Installs custom keyboard hooks.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="poll_keyboard" syntax="int poll_keyboard();"><xreflist><xref>keyboard_needs_poll</xref><xref>install_keyboard</xref><xref>key</xref><xref>key_shifts</xref></xreflist><ereflist><eref>excamera</eref><eref>exsample</eref><eref>exstars</eref></ereflist><shortdesc>Polls the keyboard.</shortdesc><text><![CDATA[   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.
]]></text><retval><text><![CDATA[   Returns zero on success, or a negative number on failure (ie. no keyboard
   driver installed).

]]></text></retval></ref><ref name="keyboard_needs_poll" syntax="int keyboard_needs_poll();"><xreflist><xref>poll_keyboard</xref><xref>install_keyboard</xref><xref>key</xref></xreflist><shortdesc>Tells if the keyboard needs polling.</shortdesc><text><![CDATA[   Returns TRUE if the current keyboard driver is operating in polling mode.

]]></text></ref><ref name="key" syntax="extern volatile char key[KEY_MAX];"><xreflist><xref>install_keyboard</xref><xref>poll_keyboard</xref><xref>key_shifts</xref></xreflist><ereflist><eref>Available Allegro examples</eref></ereflist><shortdesc>Array of flags indicating key state.</shortdesc><text><![CDATA[   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:
<pre class="code">
      if (key[KEY_SPACE])
	 printf("Space is pressed\n");</pre>

   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:
<pre class="text">
      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</pre>

   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.

]]></text></ref><ref name="key_shifts" syntax="extern volatile int key_shifts;"><xreflist><xref>install_keyboard</xref><xref>poll_keyboard</xref><xref>key</xref></xreflist><ereflist><eref>excamera</eref><eref>exkeys</eref></ereflist><shortdesc>Bitmask containing the current state of modifier keys.</shortdesc><text><![CDATA[   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:
<pre class="text">
      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</pre>

   Example:
<pre class="code">
      if (key[KEY_W]) {
	 if (key_shifts &amp; KB_SHIFT_FLAG) {
	    /* User is pressing shift + W. */
	 } else {
	    /* Hmmm... lower case W then. */
	 }
      }</pre>

]]></text></ref><ref name="keypressed" syntax="int keypressed();"><xreflist><xref>install_keyboard</xref><xref>readkey</xref><xref>ureadkey</xref><xref>clear_keybuf</xref><xref>simulate_keypress</xref><xref>simulate_ukeypress</xref></xreflist><ereflist><eref>Available Allegro examples</eref></ereflist><shortdesc>Tells if there are keypresses waiting in the input buffer.</shortdesc><text><![CDATA[   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:
<pre class="code">
      while (!keypressed()) {
         /* Show cool animated logo. */
      }
      /* So he skipped our title screen. */</pre>

]]></text></ref><ref name="readkey" syntax="int readkey();"><xreflist><xref>install_keyboard</xref><xref>ureadkey</xref><xref>keypressed</xref><xref>clear_keybuf</xref><xref>simulate_keypress</xref></xreflist><ereflist><eref>Available Allegro examples</eref></ereflist><shortdesc>Returns the next character from the keyboard buffer.</shortdesc><text><![CDATA[   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:
<pre class="code">
      int val;
      ...
      val = readkey();
      if ((val &amp; 0xff) == 'd')     /* by ASCII code */
	 allegro_message("You pressed 'd'\n");

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

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

      if (val == (KEY_X &lt;&lt; 8))     /* alt+letter */
	 allegro_message("You pressed Alt+X\n");
</pre>
   This function cannot return character values greater than 255. If you
   need to read Unicode input, use ureadkey() instead.

]]></text></ref><ref name="ureadkey" syntax="int ureadkey(int *scancode);"><xreflist><xref>install_keyboard</xref><xref>readkey</xref><xref>keypressed</xref><xref>clear_keybuf</xref><xref>simulate_ukeypress</xref></xreflist><ereflist><eref>exkeys</eref></ereflist><shortdesc>Returns the next unicode character from the keyboard buffer.</shortdesc><text><![CDATA[   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:
<pre class="code">
      int val, scancode;
      ...
      val = ureadkey(&amp;scancode);
      if (val == 0x00F1)
	 allegro_message("You pressed n with tilde\n");

      if (val == 0x00DF)
	 allegro_message("You pressed sharp s\n");
</pre>
   You should be able to find Unicode character maps at
   <a href="http://www.unicode.org/">http://www.unicode.org/</a>. 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.

]]></text></ref><ref name="scancode_to_ascii" syntax="int scancode_to_ascii(int scancode);"><xreflist><xref>scancode_to_name</xref></xreflist><shortdesc>Converts a scancode to an ASCII character.</shortdesc><text><![CDATA[   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:
<pre class="code">
      int ascii;
      ...
      ascii = scancode_to_ascii(scancode);
      allegro_message("You pressed '%c'\n", ascii);</pre>

]]></text></ref><ref name="scancode_to_name" syntax="const char *scancode_to_name(int scancode);"><xreflist><xref>scancode_to_ascii</xref></xreflist><ereflist><eref>exkeys</eref></ereflist><shortdesc>Converts a scancode to a key name.</shortdesc><text><![CDATA[   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:
<pre class="code">
      char const *keyname = scancode_to_name(scancode);
      allegro_message("You pressed the %s key.", keyname);</pre>

]]></text></ref><ref name="simulate_keypress" syntax="void simulate_keypress(int key);"><xreflist><xref>install_keyboard</xref><xref>simulate_ukeypress</xref><xref>keypressed</xref><xref>readkey</xref></xreflist><shortdesc>Stuffs a key into the keyboard buffer.</shortdesc><text><![CDATA[   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:
<pre class="code">
      simulate_keypress(KEY_SPACE &lt;&lt; 8);
      if (readkey() == (KEY_SPACE &lt;&lt; 8))
	 allegro_message("You simulated Alt+Space\n");</pre>

]]></text></ref><ref name="simulate_ukeypress" syntax="void simulate_ukeypress(int key, int scancode);"><xreflist><xref>install_keyboard</xref><xref>simulate_keypress</xref><xref>keypressed</xref><xref>ureadkey</xref></xreflist><shortdesc>Stuffs an unicode key into the keyboard buffer.</shortdesc><text><![CDATA[   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:
<pre class="code">
      /* We ignore the scancode simulation. */
      simulate_ukeypress(0x00DF, 0);
      if (ureadkey(&amp;scancode) == 0x00DF)
	 allegro_message("You simulated sharp s\n");</pre>

]]></text></ref><ref name="keyboard_callback" syntax="extern int (*keyboard_callback)(int key);"><xreflist><xref>install_keyboard</xref><xref>readkey</xref><xref>ureadkey</xref><xref>keyboard_ucallback</xref><xref>keyboard_lowlevel_callback</xref></xreflist><shortdesc>User specified keyboard callback handler.</shortdesc><text><![CDATA[   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:
<pre class="code">
      int enigma_scrambler(int key)
      {
	 /* Add one to both the scancode and ascii values. */
	 return (((key >> 8) + 1) << 8) | ((key &amp; 0xff) + 1);
      }
      END_OF_FUNCTION(enigma_scrambler)

      ...

	 install_timer();
	 LOCK_FUNCTION(enigma_scrambler);
	 install_keyboard();
	 keyboard_callback = enigma_scrambler;</pre>

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

]]></text></ref><ref name="keyboard_ucallback" syntax="extern int (*keyboard_ucallback)(int key, int *scancode);"><xreflist><xref>install_keyboard</xref><xref>readkey</xref><xref>ureadkey</xref><xref>keyboard_callback</xref><xref>keyboard_lowlevel_callback</xref></xreflist><shortdesc>User specified unicode keyboard callback handler.</shortdesc><text><![CDATA[   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:
<pre class="code">
      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;</pre>

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

]]></text></ref><ref name="keyboard_lowlevel_callback" syntax="extern void (*keyboard_lowlevel_callback)(int scancode);"><xreflist><xref>install_keyboard</xref><xref>keyboard_callback</xref><xref>keyboard_ucallback</xref></xreflist><ereflist><eref>exkeys</eref></ereflist><shortdesc>User specified low level keyboard event handler.</shortdesc><text><![CDATA[   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:
<pre class="code">
      volatile int key_down, key_up;

      void keypress_watcher(int scancode)
      {
	 if (scancode &amp; 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. */
	    }
	 }</pre>

]]></text></ref><ref name="set_leds" syntax="void set_leds(int leds);"><xreflist><xref>install_keyboard</xref><xref>key_led_flag</xref></xreflist><shortdesc>Sets the state of the keyboard LED indicators.</shortdesc><text><![CDATA[   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:
<pre class="code">
      /* 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);
</pre>
   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.

]]></text></ref><ref name="set_keyboard_rate" syntax="void set_keyboard_rate(int delay, int repeat);"><xreflist><xref>install_keyboard</xref><xref>readkey</xref><xref>ureadkey</xref></xreflist><shortdesc>Sets the keyboard repeat rate.</shortdesc><text><![CDATA[   Sets the keyboard repeat rate. Times are given in milliseconds. Passing
   zero times will disable the key repeat.

]]></text></ref><ref name="clear_keybuf" syntax="void clear_keybuf();"><xreflist><xref>install_keyboard</xref><xref>keypressed</xref><xref>readkey</xref><xref>ureadkey</xref></xreflist><ereflist><eref>Available Allegro examples</eref></ereflist><shortdesc>Clears the keyboard buffer.</shortdesc><text><![CDATA[   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().

]]></text></ref><ref name="three_finger_flag" syntax="extern int three_finger_flag;"><xreflist><xref>install_keyboard</xref></xreflist><shortdesc>Flag to desactivate the emergency exit key combination.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="key_led_flag" syntax="extern int key_led_flag;"><xreflist><xref>install_keyboard</xref><xref>set_leds</xref></xreflist><shortdesc>Flag to prevent the keyboard LEDs from being updated.</shortdesc><text><![CDATA[   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.



]]></text></ref></reflist></section><section title="Joystick routines"><text><![CDATA[
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.

]]></text><reflist><ref name="install_joystick" syntax="int install_joystick(int type);"><xreflist><xref>remove_joystick</xref><xref>num_joysticks</xref><xref>load_joystick_data</xref><xref>calibrate_joystick</xref><xref>calibrate_joystick_name</xref><xref>poll_joystick</xref><xref>Standard config variables</xref><xref>JOY_TYPE_*/DOS</xref><xref>JOY_TYPE_*/Windows</xref><xref>JOY_TYPE_*/Linux</xref></xreflist><ereflist><eref>exjoy</eref></ereflist><shortdesc>Initialises the joystick.</shortdesc><text><![CDATA[   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:
<pre class="code">
      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!");</pre>
]]></text><retval><text><![CDATA[   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.

]]></text></retval></ref><ref name="remove_joystick" syntax="void remove_joystick();"><xreflist><xref>install_joystick</xref><xref>allegro_exit</xref></xreflist><shortdesc>Removes the joystick handler.</shortdesc><text><![CDATA[   Removes the joystick handler. You don't normally need to bother calling
   this, because allegro_exit() will do it for you.

]]></text></ref><ref name="poll_joystick" syntax="int poll_joystick();"><xreflist><xref>install_joystick</xref><xref>joy</xref><xref>num_joysticks</xref></xreflist><ereflist><eref>exjoy</eref></ereflist><shortdesc>Polls the joystick.</shortdesc><text><![CDATA[   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:
<pre class="code">
   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);</pre>
]]></text><retval><text><![CDATA[   Returns zero on success or a negative number on failure (usually because
   no joystick driver was installed).

]]></text></retval></ref><ref name="num_joysticks" syntax="extern int num_joysticks;"><xreflist><xref>install_joystick</xref><xref>joy</xref></xreflist><ereflist><eref>exjoy</eref></ereflist><shortdesc>Global variable saying how many joysticks there are.</shortdesc><text><![CDATA[   Global variable containing the number of active joystick devices. The
   current drivers support a maximum of eight controllers.

]]></text></ref><ref name="joy" syntax="extern JOYSTICK_INFO joy[n];"><xreflist><xref>install_joystick</xref><xref>poll_joystick</xref><xref>num_joysticks</xref><xref>calibrate_joystick</xref><xref>calibrate_joystick_name</xref></xreflist><ereflist><eref>exjoy</eref></ereflist><shortdesc>Global array of joystick state information.</shortdesc><text><![CDATA[   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:
<pre class="code">
      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;
</pre>
   The button status is stored in the structure:
<pre class="code">
      typedef struct JOYSTICK_BUTTON_INFO
      {
	 int b;                           - boolean on/off flag
	 char *name;                      - description of this
					    button
      } JOYSTICK_BUTTON_INFO;
</pre>
   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:
<pre class="code">
      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;
</pre>
   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:
<pre class="code">
      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;
</pre>
   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:

   <b>JOYFLAG_DIGITAL</b><br>
      This control is currently providing digital input.

   <b>JOYFLAG_ANALOGUE</b><br>
      This control is currently providing analogue input.

   <b>JOYFLAG_CALIB_DIGITAL</b><br>
      This control will be capable of providing digital input once it has
      been calibrated, but is not doing this at the moment.

   <b>JOYFLAG_CALIB_ANALOGUE</b><br>
      This control will be capable of providing analogue input once it has
      been calibrated, but is not doing this at the moment.

   <b>JOYFLAG_CALIBRATE</b><br>
      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.

   <b>JOYFLAG_SIGNED</b><br>
      Indicates that the analogue axis position is in signed format, ranging
      from -128 to 128. This is the case for all 2d directional controls.

   <b>JOYFLAG_UNSIGNED</b><br>
      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.

]]></text></ref><ref name="calibrate_joystick_name" syntax="const char *calibrate_joystick_name(int n);"><xreflist><xref>install_joystick</xref><xref>calibrate_joystick</xref><xref>joy</xref><xref>num_joysticks</xref></xreflist><ereflist><eref>exjoy</eref></ereflist><shortdesc>Returns the next calibration text string.</shortdesc><text><![CDATA[   Pass the number of the joystick you want to calibrate as the parameter.
]]></text><retval><text><![CDATA[   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.

]]></text></retval></ref><ref name="calibrate_joystick" syntax="int calibrate_joystick(int n);"><xreflist><xref>install_joystick</xref><xref>calibrate_joystick_name</xref><xref>joy</xref><xref>num_joysticks</xref></xreflist><ereflist><eref>exjoy</eref></ereflist><shortdesc>Calibrates the specified joystick.</shortdesc><text><![CDATA[   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:
<pre class="code">
      int i;

      for (i=0; i&lt;;num_joysticks; i++) {
	 while (joy[i].flags &amp; 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);
	    }
	 }
      }</pre>
]]></text><retval><text><![CDATA[   Returns zero on success, non-zero if the calibration could not be
   performed successfully.

]]></text></retval></ref><ref name="save_joystick_data" syntax="int save_joystick_data(const char *filename);"><xreflist><xref>load_joystick_data</xref><xref>set_config_file</xref></xreflist><shortdesc>Saves joystick calibration data.</shortdesc><text><![CDATA[   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.
]]></text><retval><text><![CDATA[   Returns zero on success, non-zero if the data could not be saved.

]]></text></retval></ref><ref name="load_joystick_data" syntax="int load_joystick_data(const char *filename);"><xreflist><xref>install_joystick</xref><xref>save_joystick_data</xref><xref>set_config_file</xref></xreflist><shortdesc>Loads joystick calibration data.</shortdesc><text><![CDATA[   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.
]]></text><retval><text><![CDATA[   Returns zero on success: if it fails the joystick state is undefined and
   you must reinitialise it from scratch.

]]></text></retval></ref><ref name="initialise_joystick" syntax="int initialise_joystick();"><xreflist><xref>install_joystick</xref></xreflist><shortdesc>Deprecated version of install_joystick().</shortdesc><text><![CDATA[   Deprecated. Use install_joystick() instead.



]]></text></ref></reflist></section><section title="Graphics modes"><text><![CDATA[
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:
<pre class="text">
      (0,0)------------(640,0)----(1024,0)
	|                  |           |
	|  visible screen  |           |
	|                  |           |
      (0,480)----------(640,480)       |
	|                              |
	|   the rest of video memory   |
	|                              |
      (0,1024)--------------------(1024,1024)
</pre>
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 wich 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:
<ul><li>
GFX_AUTODETECT:<br>
   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.
<li>
GFX_AUTODETECT_FULLSCREEN:<br>
   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.
<li>
GFX_AUTODETECT_WINDOWED:<br>
   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.
<li>
GFX_SAFE:<br>
   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.
<li>
   GFX_TEXT:<br>
   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.
</ul>

]]></text><reflist><ref name="set_color_depth" syntax="void set_color_depth(int depth);"><xreflist><xref>get_color_depth</xref><xref>set_gfx_mode</xref><xref>set_color_conversion</xref><xref>makecol</xref><xref>getr</xref><xref>desktop_color_depth</xref></xreflist><ereflist><eref>Available Allegro examples</eref></ereflist><shortdesc>Sets the global pixel color depth.</shortdesc><text><![CDATA[   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:
<pre class="code">
      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");
      }
</pre>
   Note that the screen color depth won't change until the next successful
   call to set_gfx_mode().

]]></text></ref><ref name="get_color_depth" syntax="int get_color_depth(void);"><xreflist><xref>set_color_depth</xref><xref>bitmap_color_depth</xref></xreflist><ereflist><eref>exrgbhsv</eref></ereflist><shortdesc>Returns the current pixel color depth.</shortdesc><text><![CDATA[   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().

]]></text></ref><ref name="request_refresh_rate" syntax="void request_refresh_rate(int rate);"><xreflist><xref>set_gfx_mode</xref><xref>get_refresh_rate</xref></xreflist><shortdesc>Requests a specific refresh rate during graphic mode switch.</shortdesc><text><![CDATA[   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:
<pre class="code">
      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!");</pre>

]]></text></ref><ref name="get_refresh_rate" syntax="int get_refresh_rate(void);"><xreflist><xref>request_refresh_rate</xref></xreflist><shortdesc>Returns the current refresh rate.</shortdesc><text><![CDATA[   Returns the current refresh rate, if known (not all drivers are able to
   report this information). Returns zero if the actual rate is unknown.

]]></text></ref><ref name="get_gfx_mode_list" syntax="GFX_MODE_LIST *get_gfx_mode_list(int card);"><xreflist><xref>destroy_gfx_mode_list</xref><xref>set_gfx_mode</xref><xref>set_color_depth</xref></xreflist><shortdesc>Obtains a list of available video modes.</shortdesc><text><![CDATA[   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:
<pre class="code">
      typedef struct GFX_MODE_LIST
      {
	 int num_modes;
	 GFX_MODE *mode;
      } GFX_MODE_LIST;
</pre>
   The mode entry  points to the actual list of video modes.
<pre class="code">
      typedef struct GFX_MODE
      {
	 int width, height, bpp;
      } GFX_MODE;
</pre>
   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.
]]></text><retval><text><![CDATA[   Returns a pointer to a list structure of the type GFX_MODE_LIST or NULL
   if the request could not be satisfied.

]]></text></retval></ref><ref name="destroy_gfx_mode_list" syntax="void destroy_gfx_mode_list(GFX_MODE_LIST *mode_list);"><xreflist><xref>get_gfx_mode_list</xref><xref>set_gfx_mode</xref><xref>set_color_depth</xref></xreflist><shortdesc>Frees the list created by get_gfx_mode_list().</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="set_gfx_mode" syntax="int set_gfx_mode(int card, int w, int h, int v_w, int v_h);"><xreflist><xref>set_color_depth</xref><xref>request_refresh_rate</xref><xref>screen</xref><xref>gfx_capabilities</xref><xref>allegro_error</xref><xref>Standard config variables</xref><xref>GFX_*/DOS</xref><xref>GFX_*/Windows</xref><xref>GFX_*/X</xref><xref>GFX_*/Linux</xref><xref>GFX_*/BeOS</xref><xref>GFX_*/MacOSX</xref><xref>create_video_bitmap</xref><xref>get_desktop_resolution</xref><xref>SCREEN_W</xref><xref>SCREEN_H</xref><xref>VIRTUAL_W</xref><xref>VIRTUAL_H</xref></xreflist><ereflist><eref>Available Allegro examples</eref></ereflist><shortdesc>Sets a graphic video mode.</shortdesc><text><![CDATA[   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.
]]></text><retval><text><![CDATA[   Returns zero on success. On failure returns a negative number and stores a
   description of the problem in allegro_error.

]]></text></retval></ref><ref name="set_display_switch_mode" syntax="int set_display_switch_mode(int mode);"><xreflist><xref>set_display_switch_callback</xref><xref>get_display_switch_mode</xref></xreflist><ereflist><eref>exmidi</eref><eref>exswitch</eref></ereflist><shortdesc>Tells Allegro how the program handles background switching.</shortdesc><text><![CDATA[   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:
<ul><li>
   SWITCH_NONE<br>
      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!
<li>
   SWITCH_PAUSE<br>
      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.
<li>
   SWITCH_AMNESIA<br>
      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.
<li>
   SWITCH_BACKGROUND<br>
      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).
<li>
   SWITCH_BACKAMNESIA<br>
      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.
</ul>
   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.
]]></text><retval><text><![CDATA[   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.

]]></text></retval></ref><ref name="set_display_switch_callback" syntax="int set_display_switch_callback(int dir, void (*cb)());"><xreflist><xref>remove_display_switch_callback</xref><xref>set_display_switch_mode</xref></xreflist><ereflist><eref>exswitch</eref></ereflist><shortdesc>Installs a switching notification callback.</shortdesc><text><![CDATA[   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.
]]></text><retval><text><![CDATA[   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.

]]></text></retval></ref><ref name="remove_display_switch_callback" syntax="void remove_display_switch_callback(void (*cb)());"><xreflist><xref>set_display_switch_callback</xref></xreflist><shortdesc>Removes a switching notification callback.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="get_display_switch_mode" syntax="int get_display_switch_mode();"><xreflist><xref>set_display_switch_mode</xref></xreflist><ereflist><eref>exswitch</eref></ereflist><shortdesc>Returns the current display switching mode.</shortdesc><text><![CDATA[   Returns the current display switching mode, in the same format passed to
   set_display_switch_mode().

]]></text></ref><ref name="is_windowed_mode" syntax="int is_windowed_mode(void);"><xreflist><xref>set_gfx_mode</xref></xreflist><shortdesc>Tells if you are running in windowed mode.</shortdesc><text><![CDATA[   This function can be used to detect wether or not set_gfx_mode() selected
   a windowed mode. Example:
<pre class="code">
      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. */
      }</pre>
]]></text><retval><text><![CDATA[   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.

]]></text></retval></ref><ref name="gfx_capabilities" syntax="extern int gfx_capabilities;"><xreflist><xref>screen</xref><xref>create_video_bitmap</xref><xref>scroll_screen</xref><xref>request_scroll</xref><xref>show_mouse</xref><xref>enable_triple_buffer</xref></xreflist><ereflist><eref>ex3buf</eref><eref>exaccel</eref><eref>exsyscur</eref><eref>exupdate</eref></ereflist><shortdesc>Bitfield describing video hardware capabilities.</shortdesc><text><![CDATA[   Bitfield describing the capabilities of the current graphics driver and
   video hardware. This may contain combination any of the flags:

   <b>GFX_CAN_SCROLL:</b><br>
      Indicates that the scroll_screen() function may be used with this
      driver.

   <b>GFX_CAN_TRIPLE_BUFFER:</b><br>
      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.

   <b>GFX_HW_CURSOR:</b><br>
      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.

   <b>GFX_SYSTEM_CURSOR</b><br>
      Indicates that the mouse cursor is the default system cursor, not
      Allegro's custom cursor.

   <b>GFX_HW_HLINE:</b><br>
      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().

   <b>GFX_HW_HLINE_XOR:</b><br>
      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.

   <b>GFX_HW_HLINE_SOLID_PATTERN:</b><br>
      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).

   <b>GFX_HW_HLINE_COPY_PATTERN:</b><br>
      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).

   <b>GFX_HW_FILL:</b><br>
      Indicates that the opaque version of the rectfill() function, the
      clear_bitmap() routine, and clear_to_color(), are implemented using a
      hardware accelerator.

   <b>GFX_HW_FILL_XOR:</b><br>
      Indicates that the XOR version of the rectfill() function is
      implemented using a hardware accelerator.

   <b>GFX_HW_FILL_SOLID_PATTERN:</b><br>
      Indicates that the solid and masked pattern modes of the rectfill()
      function are implemented using a hardware accelerator (see note below).

   <b>GFX_HW_FILL_COPY_PATTERN:</b><br>
      Indicates that the copy pattern mode of the rectfill() function is
      implemented using a hardware accelerator (see note below).

   <b>GFX_HW_LINE:</b><br>
      Indicates that the opaque mode line() and vline() functions are
      implemented using a hardware accelerator.

   <b>GFX_HW_LINE_XOR:</b><br>
      Indicates that the XOR version of the line() and vline() functions are
      implemented using a hardware accelerator.

   <b>GFX_HW_TRIANGLE:</b><br>
      Indicates that the opaque mode triangle() function is implemented
      using a hardware accelerator.

   <b>GFX_HW_TRIANGLE_XOR:</b><br>
      Indicates that the XOR version of the triangle() function is
      implemented using a hardware accelerator.

   <b>GFX_HW_GLYPH:</b><br>
      Indicates that monochrome character expansion (for text drawing) is
      implemented using a hardware accelerator.

   <b>GFX_HW_VRAM_BLIT:</b><br>
      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.

   <b>GFX_HW_VRAM_BLIT_MASKED:</b><br>
      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.

   <b>GFX_HW_MEM_BLIT:</b><br>
      Indicates that blitting from a memory bitmap onto the screen is being
      accelerated in hardware.

   <b>GFX_HW_MEM_BLIT_MASKED:</b><br>
      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.

   <b>GFX_HW_SYS_TO_VRAM_BLIT:</b><br>
      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.

   <b>GFX_HW_SYS_TO_VRAM_BLIT_MASKED:</b><br>
      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.

   <b>GFX_HW_VRAM_STRETCH_BLIT:</b><br>
      Indicates that stretched blitting of video bitmaps onto the screen is
      implemented using hardware acceleration.

   <b>GFX_HW_SYS_STRETCH_BLIT:</b><br>
      Indicates that stretched blitting of system bitmaps onto the screen is
      implemented using hardware acceleration.

   <b>GFX_HW_VRAM_STRETCH_BLIT_MASKED:</b><br>
      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 artefacts when this function is used.
      If the image does not look correct try updating your video drivers.

   <b>GFX_HW_SYS_STRETCH_BLIT_MASKED:</b><br>
      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 artefacts 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.

]]></text></ref><ref name="enable_triple_buffer" syntax="int enable_triple_buffer();"><xreflist><xref>gfx_capabilities</xref><xref>request_scroll</xref><xref>request_video_bitmap</xref></xreflist><ereflist><eref>ex3buf</eref><eref>exupdate</eref></ereflist><shortdesc>Enables triple buffering.</shortdesc><text><![CDATA[   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.
]]></text><retval><text><![CDATA[   Returns zero if triple buffering is enabled, -1 otherwise.

]]></text></retval></ref><ref name="scroll_screen" syntax="int scroll_screen(int x, int y);"><xreflist><xref>set_gfx_mode</xref><xref>show_video_bitmap</xref><xref>request_scroll</xref><xref>request_video_bitmap</xref></xreflist><ereflist><eref>exscroll</eref></ereflist><shortdesc>Requests a hardware scroll request.</shortdesc><text><![CDATA[   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().
]]></text><retval><text><![CDATA[   Returns zero on success. Returns non-zero if the graphics driver can't
   handle hardware scrolling or the virtual screen is not large enough.

]]></text></retval></ref><ref name="request_scroll" syntax="int request_scroll(int x, int y);"><xreflist><xref>poll_scroll</xref><xref>request_video_bitmap</xref><xref>gfx_capabilities</xref><xref>scroll_screen</xref></xreflist><shortdesc>Queues a hardware scroll request with triple buffering.</shortdesc><text><![CDATA[   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.
]]></text><retval><text><![CDATA[   This function returns zero on success, non-zero otherwise.

]]></text></retval></ref><ref name="poll_scroll" syntax="int poll_scroll();"><xreflist><xref>request_scroll</xref><xref>request_video_bitmap</xref></xreflist><ereflist><eref>ex3buf</eref><eref>exupdate</eref></ereflist><shortdesc>Checks the status of a scroll request with triple buffering.</shortdesc><text><![CDATA[   This function is used for triple buffering. It checks the status of a
   hardware scroll previously initiated by the request_scroll() routine.
]]></text><retval><text><![CDATA[   Returns non-zero if it is still waiting to take place, and zero if the
   requested scroll has already happened.

]]></text></retval></ref><ref name="show_video_bitmap" syntax="int show_video_bitmap(BITMAP *bitmap);"><xreflist><xref>scroll_screen</xref><xref>create_video_bitmap</xref><xref>Standard config variables</xref></xreflist><ereflist><eref>exaccel</eref><eref>exflip</eref><eref>exupdate</eref></ereflist><shortdesc>Flips the hardware screen to use the specified page.</shortdesc><text><![CDATA[   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:
<pre class="code">
      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;
      ...</pre>
]]></text><retval><text><![CDATA[   Returns zero on success and non-zero on failure.

]]></text></retval></ref><ref name="request_video_bitmap" syntax="int request_video_bitmap(BITMAP *bitmap);"><xreflist><xref>poll_scroll</xref><xref>request_scroll</xref><xref>gfx_capabilities</xref><xref>create_video_bitmap</xref><xref>scroll_screen</xref></xreflist><ereflist><eref>ex3buf</eref><eref>exupdate</eref></ereflist><shortdesc>Triple buffering page flip request.</shortdesc><text><![CDATA[   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:
<pre class="code">
      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;
      ...</pre>
]]></text><retval><text><![CDATA[   Returns zero on success and non-zero on failure.

]]></text></retval></ref><ref name="vsync" syntax="void vsync();"><xreflist><xref>set_palette</xref><xref>scroll_screen</xref></xreflist><ereflist><eref>Available Allegro examples</eref></ereflist><shortdesc>Waits for a vertical retrace to begin.</shortdesc><text><![CDATA[   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.



]]></text></ref></reflist></section><section title="Bitmap objects"><text><![CDATA[
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:
<ul><li>
   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.
<li>
   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.
<li>
   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.
<li>
   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().
<li>
   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().
</ul>

]]></text><reflist><ref name="screen" syntax="extern BITMAP *screen;"><xreflist><xref>set_gfx_mode</xref><xref>is_screen_bitmap</xref><xref>create_video_bitmap</xref><xref>scroll_screen</xref></xreflist><ereflist><eref>Available Allegro examples</eref></ereflist><shortdesc>Global pointer to the screen hardware video memory.</shortdesc><text><![CDATA[   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:
<pre class="code">
      putpixel(screen, x, y, color);
</pre>
   Or to implement a double-buffered system:
<pre class="code">
      /* 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);</pre>

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

]]></text></ref><ref name="SCREEN_W" syntax="#define SCREEN_W;"/><ref name="SCREEN_H" syntax="#define SCREEN_H;"><xreflist><xref>screen</xref><xref>set_gfx_mode</xref><xref>VIRTUAL_W</xref><xref>VIRTUAL_H</xref></xreflist><ereflist><eref>Available Allegro examples</eref></ereflist><shortdesc>Global define to obtain the size of the screen.</shortdesc><text><![CDATA[   Global defines that return the width and height of the screen, or zero if
   the screen has not been initialised yet. Example:
<pre class="code">
      char buf[100];
      ...
      uszprintf(buf, sizeof(buf),
		"The screen size is %d x %d pixels",
		SCREEN_W, SCREEN_H);</pre>

]]></text></ref><ref name="VIRTUAL_W" syntax="#define VIRTUAL_W;"/><ref name="VIRTUAL_H" syntax="#define VIRTUAL_H;"><xreflist><xref>screen</xref><xref>set_gfx_mode</xref><xref>SCREEN_W</xref><xref>SCREEN_H</xref></xreflist><shortdesc>Global define to obtain the virtual size of the screen.</shortdesc><text><![CDATA[   Global defines that return the width and height of the virtual screen, or
   zero if the screen has not been initialised yet. Example:
<pre class="code">
      char buf[100];
      ...
      uszprintf(buf, sizeof(buf),
		"The virtual screen size is %d x %d pixels",
		SCREEN_W, SCREEN_H);</pre>

]]></text></ref><ref name="create_bitmap" syntax="BITMAP *create_bitmap(int width, int height);"><xreflist><xref>create_bitmap_ex</xref><xref>create_sub_bitmap</xref><xref>create_video_bitmap</xref><xref>create_system_bitmap</xref><xref>destroy_bitmap</xref><xref>set_color_depth</xref><xref>is_memory_bitmap</xref><xref>clear_bitmap</xref><xref>clear_to_color</xref></xreflist><ereflist><eref>Available Allegro examples</eref></ereflist><shortdesc>Creates a memory bitmap.</shortdesc><text><![CDATA[   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:
<pre class="code">
      /* 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);</pre>
]]></text><retval><text><![CDATA[   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.

]]></text></retval></ref><ref name="create_bitmap_ex" syntax="BITMAP *create_bitmap_ex(int color_depth, int width, int height);"><xreflist><xref>create_bitmap</xref><xref>create_sub_bitmap</xref><xref>create_video_bitmap</xref><xref>create_system_bitmap</xref><xref>destroy_bitmap</xref><xref>is_memory_bitmap</xref><xref>clear_bitmap</xref><xref>clear_to_color</xref></xreflist><ereflist><eref>ex12bit</eref><eref>exlights</eref><eref>exrgbhsv</eref><eref>extrans</eref></ereflist><shortdesc>Creates a memory bitmap specifying color depth.</shortdesc><text><![CDATA[   Creates a bitmap in a specific color depth (8, 15, 16, 24 or 32 bits per
   pixel). Example:
<pre class="code">
      /* 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);</pre>
]]></text><retval><text><![CDATA[   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.


]]></text></retval></ref><ref name="create_sub_bitmap" syntax="BITMAP *create_sub_bitmap(BITMAP *parent, int x, y, width, height);"><xreflist><xref>create_bitmap</xref><xref>create_bitmap_ex</xref><xref>destroy_bitmap</xref><xref>is_sub_bitmap</xref><xref>clear_bitmap</xref><xref>clear_to_color</xref></xreflist><ereflist><eref>expat</eref><eref>exscroll</eref><eref>exswitch</eref></ereflist><shortdesc>Creates a memory sub bitmap.</shortdesc><text><![CDATA[   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.
]]></text><retval><text><![CDATA[   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.

]]></text></retval></ref><ref name="create_video_bitmap" syntax="BITMAP *create_video_bitmap(int width, int height);"><xreflist><xref>create_bitmap</xref><xref>create_bitmap_ex</xref><xref>create_system_bitmap</xref><xref>create_sub_bitmap</xref><xref>destroy_bitmap</xref><xref>screen</xref><xref>show_video_bitmap</xref><xref>gfx_capabilities</xref><xref>is_video_bitmap</xref><xref>clear_bitmap</xref><xref>clear_to_color</xref></xreflist><ereflist><eref>ex3buf</eref><eref>exaccel</eref><eref>exflip</eref><eref>exupdate</eref></ereflist><shortdesc>Creates a video memory bitmap.</shortdesc><text><![CDATA[   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.
]]></text><retval><text><![CDATA[   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().

]]></text></retval></ref><ref name="create_system_bitmap" syntax="BITMAP *create_system_bitmap(int width, int height);"><xreflist><xref>create_bitmap</xref><xref>create_bitmap_ex</xref><xref>create_video_bitmap</xref><xref>create_sub_bitmap</xref><xref>destroy_bitmap</xref><xref>is_system_bitmap</xref><xref>clear_bitmap</xref><xref>clear_to_color</xref></xreflist><ereflist><eref>exupdate</eref></ereflist><shortdesc>Creates a system memory bitmap.</shortdesc><text><![CDATA[   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.
]]></text><retval><text><![CDATA[   Returns a pointer to the bitmap on success, NULL otherwise. Remember to
   destroy this bitmap before any subsequent call to set_gfx_mode().

]]></text></retval></ref><ref name="destroy_bitmap" syntax="void destroy_bitmap(BITMAP *bitmap);"><xreflist><xref>create_bitmap</xref><xref>load_bitmap</xref><xref>show_mouse</xref></xreflist><ereflist><eref>Available Allegro examples</eref></ereflist><shortdesc>Destroys any type of created bitmap.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="lock_bitmap" syntax="void lock_bitmap(BITMAP *bitmap);"><shortdesc>Locks the memory used by a bitmap.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="bitmap_color_depth" syntax="int bitmap_color_depth(BITMAP *bmp);"><xreflist><xref>set_color_depth</xref><xref>bitmap_mask_color</xref></xreflist><ereflist><eref>ex3d</eref><eref>exlights</eref><eref>exscn3d</eref><eref>exswitch</eref><eref>extrans</eref><eref>exupdate</eref><eref>exzbuf</eref></ereflist><shortdesc>Returns the color depth of the specified bitmap.</shortdesc><text><![CDATA[   Returns the color depth of the specified bitmap (8, 15, 16, 24, or 32).
   Example:
<pre class="code">
      switch (bitmap_color_depth(screen)) {
	 case 8:
	    /* Access screen using optimized 8-bit code. */
	    break;
	 default:
	    /* Use generic slow functions. */
	    break;
      }</pre>

]]></text></ref><ref name="bitmap_mask_color" syntax="int bitmap_mask_color(BITMAP *bmp);"><xreflist><xref>MASK_COLOR_8</xref><xref>set_color_depth</xref><xref>bitmap_color_depth</xref></xreflist><ereflist><eref>ex3d</eref><eref>exmouse</eref><eref>expat</eref></ereflist><shortdesc>Returns the mask color of the specified bitmap.</shortdesc><text><![CDATA[   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:
<pre class="code">
      /* Replace mask color with another color. */
      for (y = 0; y < bmp->h; y++)
	 for (x = 0; x < bmp->w; x++)
	    if (getpixel(bmp, x, y) == bitmap_mask_color(bmp))
	       putpixel(bmp, x, y, another_color);</pre>

]]></text></ref><ref name="is_same_bitmap" syntax="int is_same_bitmap(BITMAP *bmp1, BITMAP *bmp2);"><xreflist><xref>create_sub_bitmap</xref></xreflist><shortdesc>Tells if two bitmaps describe the same drawing surface.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="is_planar_bitmap" syntax="int is_planar_bitmap(BITMAP *bmp);"><xreflist><xref>is_linear_bitmap</xref><xref>is_memory_bitmap</xref></xreflist><shortdesc>Tells if a bitmap is a planar screen bitmap.</shortdesc><text><![CDATA[   Returns TRUE if bmp is a planar (mode-X or Xtended mode) screen bitmap.

]]></text></ref><ref name="is_linear_bitmap" syntax="int is_linear_bitmap(BITMAP *bmp);"><xreflist><xref>is_planar_bitmap</xref><xref>is_memory_bitmap</xref></xreflist><shortdesc>Tells if a bitmap is linear.</shortdesc><text><![CDATA[   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().

]]></text></ref><ref name="is_memory_bitmap" syntax="int is_memory_bitmap(BITMAP *bmp);"><xreflist><xref>is_linear_bitmap</xref><xref>is_planar_bitmap</xref></xreflist><shortdesc>Tells if a bitmap is a memory bitmap.</shortdesc><text><![CDATA[   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-&gt;line[y][x] = color.

]]></text></ref><ref name="is_screen_bitmap" syntax="int is_screen_bitmap(BITMAP *bmp);"><xreflist><xref>screen</xref><xref>create_sub_bitmap</xref></xreflist><shortdesc>Tells if a bitmap is the screen bitmap or sub bitmap.</shortdesc><text><![CDATA[   Returns TRUE if bmp is the screen bitmap, or a sub-bitmap of the screen.

]]></text></ref><ref name="is_video_bitmap" syntax="int is_video_bitmap(BITMAP *bmp);"><xreflist><xref>screen</xref><xref>create_video_bitmap</xref><xref>create_sub_bitmap</xref></xreflist><shortdesc>Tells if a bitmap is a screen bitmap, video memory or sub bitmap.</shortdesc><text><![CDATA[   Returns TRUE if bmp is the screen bitmap, a video memory bitmap, or a
   sub-bitmap of either.

]]></text></ref><ref name="is_system_bitmap" syntax="int is_system_bitmap(BITMAP *bmp);"><xreflist><xref>create_system_bitmap</xref><xref>create_sub_bitmap</xref></xreflist><shortdesc>Tells if a bitmap is a system bitmap or sub bitmap.</shortdesc><text><![CDATA[   Returns TRUE if bmp is a system bitmap object, or a sub-bitmap of one.

]]></text></ref><ref name="is_sub_bitmap" syntax="int is_sub_bitmap(BITMAP *bmp);"><xreflist><xref>create_sub_bitmap</xref></xreflist><shortdesc>Tells if a bitmap is a sub bitmap.</shortdesc><text><![CDATA[   Returns TRUE if bmp is a sub-bitmap.

]]></text></ref><ref name="acquire_bitmap" syntax="void acquire_bitmap(BITMAP *bmp);"><xreflist><xref>release_bitmap</xref><xref>acquire_screen</xref><xref>release_screen</xref></xreflist><ereflist><eref>ex3buf</eref><eref>exaccel</eref><eref>expat</eref><eref>exquat</eref><eref>exscroll</eref><eref>exswitch</eref><eref>exupdate</eref></ereflist><shortdesc>Locks the bitmap before drawing onto it.</shortdesc><text><![CDATA[   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-&gt;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.

]]></text></ref><ref name="release_bitmap" syntax="void release_bitmap(BITMAP *bmp);"><xreflist><xref>acquire_bitmap</xref><xref>acquire_screen</xref><xref>release_screen</xref></xreflist><ereflist><eref>ex3buf</eref><eref>exaccel</eref><eref>expat</eref><eref>exquat</eref><eref>exscroll</eref><eref>exswitch</eref><eref>exupdate</eref></ereflist><shortdesc>Releases a previously locked bitmap.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="acquire_screen" syntax="void acquire_screen();"><xreflist><xref>acquire_bitmap</xref><xref>release_bitmap</xref><xref>release_screen</xref></xreflist><ereflist><eref>Available Allegro examples</eref></ereflist><shortdesc>Shortcut of acquire_bitmap(screen);</shortdesc><text><![CDATA[   Shortcut version of acquire_bitmap(screen);

]]></text></ref><ref name="release_screen" syntax="void release_screen();"><xreflist><xref>acquire_bitmap</xref><xref>release_bitmap</xref><xref>acquire_screen</xref></xreflist><ereflist><eref>Available Allegro examples</eref></ereflist><shortdesc>Shortcut of release_bitmap(screen);</shortdesc><text><![CDATA[   Shortcut version of release_bitmap(screen);

]]></text></ref><ref name="set_clip_rect" syntax="void set_clip_rect(BITMAP *bitmap, int x1, int y1, int x2, int y2);"><xreflist><xref>get_clip_rect</xref><xref>add_clip_rect</xref><xref>set_clip_state</xref><xref>get_clip_state</xref></xreflist><ereflist><eref>ex12bit</eref><eref>excamera</eref></ereflist><shortdesc>Sets the clipping rectangle of a bitmap.</shortdesc><text><![CDATA[   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.
<pre class="code">
      set_clip_rect(bmp, 0, 0, -1, -1); /* disable drawing on bmp */</pre>

   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.

]]></text></ref><ref name="get_clip_rect" syntax="void get_clip_rect(BITMAP *bitmap, int *x1, int *y1, int *x2, int *y2);"><xreflist><xref>set_clip_rect</xref><xref>add_clip_rect</xref><xref>set_clip_state</xref><xref>get_clip_state</xref></xreflist><shortdesc>Returns the clipping rectangle of a bitmap.</shortdesc><text><![CDATA[   Returns the clipping rectangle for the specified bitmap.

]]></text></ref><ref name="add_clip_rect" syntax="void add_clip_rect(BITMAP *bitmap, int x1, int y1, int x2, int y2);"><xreflist><xref>set_clip_rect</xref><xref>get_clip_rect</xref><xref>set_clip_state</xref><xref>get_clip_state</xref></xreflist><shortdesc>Intersects a bitmap's clipping rectangle with the given area.</shortdesc><text><![CDATA[   Sets the clipping rectangle of the specified bitmap as the intersection of
   its current clipping rectangle and the rectangle described by the four
   coordinates.

]]></text></ref><ref name="set_clip_state" syntax="void set_clip_state(BITMAP *bitmap, int state)"><xreflist><xref>set_clip_rect</xref><xref>get_clip_rect</xref><xref>add_clip_rect</xref><xref>get_clip_state</xref></xreflist><shortdesc>Turns on or off the clipping of a bitmap.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="get_clip_state" syntax="int get_clip_state(BITMAP *bitmap)"><xreflist><xref>set_clip_rect</xref><xref>get_clip_rect</xref><xref>add_clip_rect</xref><xref>set_clip_state</xref></xreflist><shortdesc>Tells if clipping is on for a bitmap.</shortdesc><text><![CDATA[   Returns non-zero if clipping is turned on for the specified bitmap and
   zero otherwise.

]]></text></ref><ref name="is_inside_bitmap" syntax="int is_inside_bitmap(BITMAP *bmp, int x, int y, int clip);"><xreflist><xref>set_clip_rect</xref><xref>set_clip_state</xref><xref>getpixel</xref></xreflist><shortdesc>Tells if a point is inside a bitmap.</shortdesc><text><![CDATA[   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.



]]></text></ref></reflist></section><section title="Loading image files"><text><![CDATA[
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.

]]></text><reflist><ref name="load_bitmap" syntax="BITMAP *load_bitmap(const char *filename, RGB *pal);"><xreflist><xref>load_bmp</xref><xref>load_lbm</xref><xref>load_pcx</xref><xref>load_tga</xref><xref>destroy_bitmap</xref><xref>save_bitmap</xref><xref>register_bitmap_file_type</xref><xref>set_color_depth</xref><xref>set_color_conversion</xref><xref>generate_optimized_palette</xref><xref>generate_332_palette</xref></xreflist><ereflist><eref>exaccel</eref><eref>exalpha</eref><eref>exbitmap</eref><eref>exblend</eref><eref>exconfig</eref><eref>exlights</eref><eref>exshade</eref><eref>extrans</eref><eref>exxfade</eref></ereflist><shortdesc>Loads any supported bitmap from a file.</shortdesc><text><![CDATA[   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:
<pre class="code">
      BITMAP *bmp;
      PALETTE palette;
      ...
      bmp = load_bitmap("image.pcx", palette);
      if (!bmp)
	 abort_on_error("Couldn't load image.pcx!");
      ...
      destroy_bitmap(bmp);</pre>
]]></text><retval><text><![CDATA[   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.

]]></text></retval></ref><ref name="load_bmp" syntax="BITMAP *load_bmp(const char *filename, RGB *pal);"><xreflist><xref>load_bitmap</xref><xref>load_bmp_pf</xref></xreflist><shortdesc>Loads a BMP bitmap from a file.</shortdesc><text><![CDATA[   Loads an 8-bit, 16-bit, 24-bit or 32-bit Windows or OS/2 BMP file.
]]></text><retval><text><![CDATA[   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.

]]></text></retval></ref><ref name="load_bmp_pf" syntax="BITMAP *load_bmp_pf(PACKFILE *f, RGB *pal);"><xreflist><xref>load_bmp</xref></xreflist><ereflist><eref>expackf</eref></ereflist><shortdesc>Packfile version of load_bmp.</shortdesc><text><![CDATA[   A version of load_bmp() which reads from a packfile. Example:
<pre class="code">
      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");</pre>
]]></text><retval><text><![CDATA[   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.

]]></text></retval></ref><ref name="load_lbm" syntax="BITMAP *load_lbm(const char *filename, RGB *pal);"><xreflist><xref>load_bitmap</xref></xreflist><shortdesc>Loads an LBM bitmap from a file.</shortdesc><text><![CDATA[   Loads a 256-color IFF ILBM/PBM file.
]]></text><retval><text><![CDATA[   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.

]]></text></retval></ref><ref name="load_pcx" syntax="BITMAP *load_pcx(const char *filename, RGB *pal);"><xreflist><xref>load_bitmap</xref></xreflist><ereflist><eref>expackf</eref><eref>exscale</eref></ereflist><shortdesc>Loads a PCX bitmap from a file.</shortdesc><text><![CDATA[   Loads a 256-color or 24-bit truecolor PCX file.
]]></text><retval><text><![CDATA[   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.

]]></text></retval></ref><ref name="load_pcx_pf" syntax="BITMAP *load_pcx_pf(PACKFILE *f, RGB *pal);"><xreflist><xref>load_pcx</xref></xreflist><ereflist><eref>expackf</eref></ereflist><shortdesc>Packfile version of load_pcx.</shortdesc><text><![CDATA[   A version of load_pcx() which reads from a packfile. Example:
<pre class="code">
      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");</pre>
]]></text><retval><text><![CDATA[   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.

]]></text></retval></ref><ref name="load_tga" syntax="BITMAP *load_tga(const char *filename, RGB *pal);"><xreflist><xref>load_bitmap</xref></xreflist><shortdesc>Loads a TGA bitmap from a file.</shortdesc><text><![CDATA[   Loads a 256-color, 15-bit hicolor, 24-bit truecolor, or 32-bit
   truecolor+alpha TGA file.
]]></text><retval><text><![CDATA[   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.

]]></text></retval></ref><ref name="load_tga_pf" syntax="BITMAP *load_tga_pf(PACKFILE *f, RGB *pal);"><xreflist><xref>load_tga</xref></xreflist><ereflist><eref>expackf</eref></ereflist><shortdesc>Packfile version of load_tga.</shortdesc><text><![CDATA[   A version of load_tga() which reads from a packfile. Example:
<pre class="code">
      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");</pre>
]]></text><retval><text><![CDATA[   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.

]]></text></retval></ref><ref name="save_bitmap" syntax="int save_bitmap(const char *filename, BITMAP *bmp, const RGB *pal);"><xreflist><xref>save_bmp</xref><xref>save_pcx</xref><xref>save_tga</xref><xref>load_bitmap</xref><xref>register_bitmap_file_type</xref></xreflist><shortdesc>Saves a bitmap into any supported file format.</shortdesc><text><![CDATA[   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:
<pre class="code">
      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);</pre>
]]></text><retval><text><![CDATA[   Returns non-zero on error.

]]></text></retval></ref><ref name="save_bmp" syntax="int save_bmp(const char *filename, BITMAP *bmp, const RGB *pal);"><xreflist><xref>save_bitmap</xref></xreflist><shortdesc>Saves a bitmap into a BMP file.</shortdesc><text><![CDATA[   Writes a bitmap into a 256-color or 24-bit truecolor BMP file.
]]></text><retval><text><![CDATA[   Returns non-zero on error.

]]></text></retval></ref><ref name="save_bmp_pf" syntax="int save_bmp_pf(PACKFILE *f, BITMAP *bmp, RGB *pal);"><xreflist><xref>save_bmp</xref></xreflist><ereflist><eref>expackf</eref></ereflist><shortdesc>Packfile version of save_bmp.</shortdesc><text><![CDATA[   A version of save_bmp which writes to a packfile.

]]></text></ref><ref name="save_pcx" syntax="int save_pcx(const char *filename, BITMAP *bmp, const RGB *pal);"><xreflist><xref>save_bitmap</xref></xreflist><shortdesc>Saves a bitmap into a PCX file.</shortdesc><text><![CDATA[   Writes a bitmap into a 256-color or 24-bit truecolor PCX file.
]]></text><retval><text><![CDATA[   Returns non-zero on error.

]]></text></retval></ref><ref name="save_pcx_pf" syntax="int save_pcx_pf(PACKFILE *f, BITMAP *bmp, RGB *pal);"><xreflist><xref>save_pcx</xref></xreflist><shortdesc>Packfile version of save_pcx.</shortdesc><text><![CDATA[   A version of save_pcx which writes to a packfile.

]]></text></ref><ref name="save_tga" syntax="int save_tga(const char *filename, BITMAP *bmp, const RGB *pal);"><xreflist><xref>save_bitmap</xref></xreflist><shortdesc>Saves a bitmap into a TGA file.</shortdesc><text><![CDATA[   Writes a bitmap into a 256-color, 15-bit hicolor, 24-bit truecolor, or
   32-bit truecolor+alpha TGA file.
]]></text><retval><text><![CDATA[   Returns non-zero on error.

]]></text></retval></ref><ref name="save_tga_pf" syntax="int save_tga_pf(PACKFILE *f, BITMAP *bmp, RGB *pal);"><xreflist><xref>save_tga</xref></xreflist><ereflist><eref>expackf</eref></ereflist><shortdesc>Packfile version of save_tga.</shortdesc><text><![CDATA[   A version of save_tga which writes to a packfile.

]]></text></ref><ref name="register_bitmap_file_type" syntax="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));"><xreflist><xref>load_bitmap</xref><xref>save_bitmap</xref></xreflist><shortdesc>Registers custom bitmap loading/saving functions.</shortdesc><text><![CDATA[   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:
<pre class="code">
      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);</pre>

]]></text></ref><ref name="set_color_conversion" syntax="void set_color_conversion(int mode);"><xreflist><xref>set_color_depth</xref><xref>load_bitmap</xref><xref>load_datafile</xref><xref>fixup_datafile</xref><xref>makecol15_dither</xref><xref>get_color_conversion</xref></xreflist><ereflist><eref>exalpha</eref><eref>exblend</eref><eref>exdata</eref><eref>exexedat</eref><eref>exlights</eref><eref>exxfade</eref></ereflist><shortdesc>Tells Allegro how to convert images during loading time.</shortdesc><text><![CDATA[   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:
<pre class="text">
      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
</pre>
   For convenience, the following macros can be used to select common
   combinations of these flags:
<pre class="text">
      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 &lt;-&gt; 16-bit and
				    // 24 &lt;-&gt; 32-bit
      COLORCONV_MOST                // all but hi/truecolor &lt;-&gt; 256
      COLORCONV_DITHER              // dither during all color reductions
      COLORCONV_KEEP_ALPHA          // convert everything to current format
                                    // unless it would lose alpha information
</pre>
   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.

]]></text></ref><ref name="get_color_conversion" syntax="int get_color_conversion();"><xreflist><xref>set_color_conversion</xref></xreflist><shortdesc>Returns the current color conversion mode.</shortdesc><text><![CDATA[   Returns the current color conversion mode.



]]></text></ref></reflist></section><section title="Palette routines"><text><![CDATA[
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:
<pre class="code">
   typedef struct RGB
   {
      unsigned char r, g, b;
   } RGB;
</pre>
It contains an additional field for the purpose of padding but you should
not usually care about it. For example:
<pre class="code">
   RGB black = { 0,  0,  0  };
   RGB white = { 63, 63, 63 };
   RGB green = { 0,  63, 0  };
   RGB grey  = { 32, 32, 32 };
</pre>
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).

]]></text><reflist><ref name="set_color" syntax="void set_color(int index, const RGB *p);"><xreflist><xref>set_palette</xref><xref>get_color</xref><xref>_set_color</xref></xreflist><ereflist><eref>ex12bit</eref><eref>exrgbhsv</eref><eref>exscroll</eref></ereflist><shortdesc>Sets the specified palette entry to the specified RGB triplet.</shortdesc><text><![CDATA[   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:
<pre class="code">
      RGB rgb;
      ...
      vsync();
      set_color(192, &amp;rgb);</pre>

]]></text></ref><ref name="_set_color" syntax="void _set_color(int index, const RGB *p);"><xreflist><xref>set_color</xref><xref>set_gfx_mode</xref></xreflist><ereflist><eref>ex3buf</eref></ereflist><shortdesc>Inline version of set_color().</shortdesc><text><![CDATA[   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).

]]></text></ref><ref name="set_palette" syntax="void set_palette(const PALETTE p);"><xreflist><xref>set_gfx_mode</xref><xref>set_palette_range</xref><xref>set_color</xref><xref>get_palette</xref><xref>select_palette</xref><xref>palette_color</xref></xreflist><ereflist><eref>Available Allegro examples</eref></ereflist><shortdesc>Sets the entire palette of 256 colors.</shortdesc><text><![CDATA[   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:
<pre class="code">
      BITMAP *bmp;
      PALETTE palette;
      ...
      bmp = load_bitmap(filename, palette);
      if (!bmp)
	 abort_on_error("Couldn't load bitmap!");
      set_palette(palette);</pre>

]]></text></ref><ref name="set_palette_range" syntax="void set_palette_range(const PALETTE p, int from, int to, int vsync);"><xreflist><xref>set_palette</xref><xref>get_palette_range</xref></xreflist><shortdesc>Sets a specific range of the palette.</shortdesc><text><![CDATA[   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:
<pre class="code">
      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);</pre>

]]></text></ref><ref name="get_color" syntax="void get_color(int index, RGB *p);"><xreflist><xref>get_palette</xref><xref>set_color</xref></xreflist><shortdesc>Retrieves the specified palette entry.</shortdesc><text><![CDATA[   Retrieves the specified palette entry. Example:
<pre class="code">
      RGB color;
      ...
      get_color(11, &amp;color);</pre>

]]></text></ref><ref name="get_palette" syntax="void get_palette(PALETTE p);"><xreflist><xref>get_palette_range</xref><xref>get_color</xref><xref>set_palette</xref></xreflist><shortdesc>Retrieves the entire palette of 256 colors.</shortdesc><text><![CDATA[   Retrieves the entire palette of 256 colors. You should provide an array
   of 256 RGB structures to store it in. Example:
<pre class="code">
      PALETTE pal;
      ...
      get_palette(pal);</pre>

]]></text></ref><ref name="get_palette_range" syntax="void get_palette_range(PALETTE p, int from, int to);"><xreflist><xref>get_palette</xref><xref>set_palette_range</xref></xreflist><shortdesc>Retrieves a specific palette range.</shortdesc><text><![CDATA[   Retrieves the palette entries between from and to (inclusive: pass 0 and
   255 to get the entire palette).

]]></text></ref><ref name="fade_interpolate" syntax="void fade_interpolate(const PALETTE source, const PALETTE dest, PALETTE output, int pos, int from, int to);"><xreflist><xref>fade_in</xref><xref>fade_out</xref><xref>fade_from</xref></xreflist><shortdesc>Calculates a new palette interpolated between two others.</shortdesc><text><![CDATA[   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).

]]></text></ref><ref name="fade_from_range" syntax="void fade_from_range(const PALETTE source, const PALETTE dest, int speed, int from, int to);"><xreflist><xref>fade_from</xref></xreflist><shortdesc>Gradually fades a part of the palette between two others.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="fade_in_range" syntax="void fade_in_range(const PALETTE p, int speed, int from, int to);"><xreflist><xref>fade_in</xref></xreflist><shortdesc>Gradually fades a part of the palette from black.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="fade_out_range" syntax="void fade_out_range(int speed, int from, int to);"><xreflist><xref>fade_out</xref></xreflist><shortdesc>Gradually fades a part of the palette to black.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="fade_from" syntax="void fade_from(const PALETTE source, const PALETTE dest, int speed);"><xreflist><xref>fade_in</xref><xref>fade_out</xref><xref>fade_interpolate</xref><xref>fade_from_range</xref></xreflist><shortdesc>Gradually fades the palette between two others.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="fade_in" syntax="void fade_in(const PALETTE p, int speed);"><xreflist><xref>fade_out</xref><xref>fade_from</xref><xref>fade_interpolate</xref><xref>fade_in_range</xref></xreflist><shortdesc>Gradually fades the palette from black.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="fade_out" syntax="void fade_out(int speed);"><xreflist><xref>fade_in</xref><xref>fade_from</xref><xref>fade_interpolate</xref><xref>fade_in_range</xref></xreflist><ereflist><eref>ex12bit</eref></ereflist><shortdesc>Gradually fades the palette to black.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="select_palette" syntax="void select_palette(const PALETTE p);"><xreflist><xref>set_palette</xref><xref>unselect_palette</xref></xreflist><ereflist><eref>exlights</eref></ereflist><shortdesc>Sets the internal palette for color conversion.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="unselect_palette" syntax="void unselect_palette();"><xreflist><xref>select_palette</xref></xreflist><shortdesc>Restores the palette before last call to select_palette().</shortdesc><text><![CDATA[   Restores the palette tables that were in use before the last call to
   select_palette().

]]></text></ref><ref name="generate_332_palette" syntax="void generate_332_palette(PALETTE pal);"><xreflist><xref>generate_optimized_palette</xref><xref>set_color_depth</xref></xreflist><ereflist><eref>excolmap</eref><eref>exrgbhsv</eref><eref>extruec</eref><eref>exupdate</eref></ereflist><shortdesc>Constructs a fake truecolor palette.</shortdesc><text><![CDATA[   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).

]]></text></ref><ref name="generate_optimized_palette" syntax="int generate_optimized_palette(BITMAP *bmp, PALETTE pal, const char rsvd[PAL_SIZE]);"><xreflist><xref>generate_332_palette</xref><xref>set_color_depth</xref></xreflist><shortdesc>Generates an optimized palette for a bitmap.</shortdesc><text><![CDATA[   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.
]]></text><retval><text><![CDATA[   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.

]]></text></retval></ref><ref name="default_palette" syntax="extern PALETTE default_palette;"><xreflist><xref>black_palette</xref><xref>desktop_palette</xref></xreflist><ereflist><eref>exjoy</eref></ereflist><shortdesc>The default IBM BIOS palette.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="black_palette" syntax="extern PALETTE black_palette;"><xreflist><xref>default_palette</xref><xref>desktop_palette</xref></xreflist><ereflist><eref>expal</eref></ereflist><shortdesc>A palette containing solid black colors.</shortdesc><text><![CDATA[   A palette containing solid black colors, used by the fade routines.

]]></text></ref><ref name="desktop_palette" syntax="extern PALETTE desktop_palette;"><xreflist><xref>default_palette</xref><xref>black_palette</xref></xreflist><ereflist><eref>Available Allegro examples</eref></ereflist><shortdesc>The palette used by the Atari ST low resolution desktop.</shortdesc><text><![CDATA[   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.
<pre class="text">
       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</pre>



]]></text></ref></reflist></section><section title="Truecolor pixel formats"><text><![CDATA[
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!

]]></text><reflist><ref name="makecol8" syntax="int makecol8(int r, int g, int b);"/><ref name="makecol15" syntax="int makecol15(int r, int g, int b);"/><ref name="makecol16" syntax="int makecol16(int r, int g, int b);"/><ref name="makecol24" syntax="int makecol24(int r, int g, int b);"/><ref name="makecol32" syntax="int makecol32(int r, int g, int b);"><xreflist><xref>makeacol32</xref><xref>makecol</xref><xref>makecol_depth</xref><xref>makecol15_dither</xref><xref>rgb_map</xref><xref>bestfit_color</xref><xref>set_color_depth</xref></xreflist><ereflist><eref>exrgbhsv</eref></ereflist><shortdesc>Converts an RGB value into a display dependent pixel format.</shortdesc><text><![CDATA[   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:
<pre class="code">
      /* 16 bit color version of green. */
      int green_color = makecol16(0, 255, 0);</pre>
]]></text><retval><text><![CDATA[   Returns the requested RGB triplet in the specified color depth.

]]></text></retval></ref><ref name="makeacol32" syntax="int makeacol32(int r, int g, int b, int a);"><xreflist><xref>makeacol</xref><xref>set_alpha_blender</xref><xref>set_write_alpha_blender</xref></xreflist><shortdesc>Converts an RGBA color into a 32-bit display pixel format.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="makecol" syntax="int makecol(int r, int g, int b);"><xreflist><xref>makeacol</xref><xref>makecol8</xref><xref>makecol_depth</xref><xref>makecol15_dither</xref><xref>rgb_map</xref><xref>set_color_depth</xref></xreflist><ereflist><eref>Available Allegro examples</eref></ereflist><shortdesc>Converts an RGB value into the current pixel format.</shortdesc><text><![CDATA[   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:
<pre class="code">
      /* Regardless of color depth, this will look green. */
      int green_color = makecol(0, 255, 0);</pre>
]]></text><retval><text><![CDATA[   Returns the requested RGB triplet in the current color depth.

]]></text></retval></ref><ref name="makecol_depth" syntax="int makecol_depth(int color_depth, int r, int g, int b);"><xreflist><xref>makeacol</xref><xref>makecol</xref><xref>makecol8</xref><xref>makecol15_dither</xref><xref>rgb_map</xref><xref>set_color_depth</xref></xreflist><shortdesc>Converts an RGB value into the specified pixel format.</shortdesc><text><![CDATA[   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:
<pre class="code">
      /* Compose the green color for 15 bit color depth. */
      int green_15bit = makecol_depth(15, 0, 255, 0);</pre>
]]></text><retval><text><![CDATA[   Returns the requested RGB triplet in the specified color depth.

]]></text></retval></ref><ref name="makeacol" syntax="int makeacol(int r, int g, int b, int a);"/><ref name="makeacol_depth" syntax="int makeacol_depth(int color_depth, int r, int g, int b, int a);"><xreflist><xref>makecol</xref><xref>makecol_depth</xref><xref>set_alpha_blender</xref><xref>set_write_alpha_blender</xref></xreflist><shortdesc>Converts RGBA colors into display dependent pixel formats.</shortdesc><text><![CDATA[   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.
]]></text><retval><text><![CDATA[   Returns the requested RGBA quadruplet.

]]></text></retval></ref><ref name="makecol15_dither" syntax="int makecol15_dither(int r, int g, int b, int x, int y);"/><ref name="makecol16_dither" syntax="int makecol16_dither(int r, int g, int b, int x, int y);"><xreflist><xref>makecol</xref><xref>makecol8</xref><xref>set_color_conversion</xref></xreflist><shortdesc>Calculates a dithered 15 or 16-bit RGB value.</shortdesc><text><![CDATA[   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:
<pre class="code">
      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);</pre>
]]></text><retval><text><![CDATA[   Returns the RGB value dithered for the specified coordinate.

]]></text></retval></ref><ref name="getr8" syntax="int getr8(int c);"/><ref name="getg8" syntax="int getg8(int c);"/><ref name="getb8" syntax="int getb8(int c);"/><ref name="getr15" syntax="int getr15(int c);"/><ref name="getg15" syntax="int getg15(int c);"/><ref name="getb15" syntax="int getb15(int c);"/><ref name="getr16" syntax="int getr16(int c);"/><ref name="getg16" syntax="int getg16(int c);"/><ref name="getb16" syntax="int getb16(int c);"/><ref name="getr24" syntax="int getr24(int c);"/><ref name="getg24" syntax="int getg24(int c);"/><ref name="getb24" syntax="int getb24(int c);"/><ref name="getr32" syntax="int getr32(int c);"/><ref name="getg32" syntax="int getg32(int c);"/><ref name="getb32" syntax="int getb32(int c);"><xreflist><xref>geta32</xref><xref>getr</xref><xref>getr_depth</xref><xref>makecol</xref><xref>set_color_depth</xref></xreflist><shortdesc>Extract a color component from the specified pixel format.</shortdesc><text><![CDATA[   Given a color in a display dependent format, these functions extract one
   of the red, green, or blue components (ranging 0-255). Example:
<pre class="code">
      int r, g, b, color_value;

      color_value = _getpixel15(screen, 100, 100);
      r = getr15(color_value);
      g = getg15(color_value);
      b = getb15(color_value);</pre>

]]></text></ref><ref name="geta32" syntax="int geta32(int c);"><xreflist><xref>getr8</xref></xreflist><shortdesc>Extract the alpha component form a 32-bit pixel format color.</shortdesc><text><![CDATA[   Given a color in a 32-bit pixel format, this function extracts the alpha
   component (ranging 0-255).

]]></text></ref><ref name="getr" syntax="int getr(int c);"/><ref name="getg" syntax="int getg(int c);"/><ref name="getb" syntax="int getb(int c);"/><ref name="geta" syntax="int geta(int c);"><xreflist><xref>getr8</xref><xref>getr_depth</xref><xref>makecol</xref><xref>set_color_depth</xref></xreflist><ereflist><eref>exalpha</eref></ereflist><shortdesc>Extract a color component from the current pixel format.</shortdesc><text><![CDATA[   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:
<pre class="code">
      int r, g, b, color_value;

      color_value = getpixel(screen, 100, 100);
      r = getr(color_value);
      g = getg(color_value);
      b = getb(color_value);</pre>

]]></text></ref><ref name="getr_depth" syntax="int getr_depth(int color_depth, int c);"/><ref name="getg_depth" syntax="int getg_depth(int color_depth, int c);"/><ref name="getb_depth" syntax="int getb_depth(int color_depth, int c);"/><ref name="geta_depth" syntax="int geta_depth(int color_depth, int c);"><xreflist><xref>getr</xref><xref>getr8</xref><xref>geta32</xref><xref>makecol</xref><xref>set_color_depth</xref></xreflist><ereflist><eref>exlights</eref></ereflist><shortdesc>Extract a color component from a color in a specified pixel format.</shortdesc><text><![CDATA[   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:
<pre class="code">
      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);</pre>

]]></text></ref><ref name="palette_color" syntax="extern int palette_color[256];"><xreflist><xref>set_palette</xref><xref>makecol</xref><xref>set_color_depth</xref></xreflist><ereflist><eref>Available Allegro examples</eref></ereflist><shortdesc>Maps palette indexes into the current pixel format colors.</shortdesc><text><![CDATA[   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:
<pre class="code">
      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]);</pre>

]]></text></ref><ref name="MASK_COLOR_8" syntax="#define MASK_COLOR_8 0"/><ref name="MASK_COLOR_15" syntax="#define MASK_COLOR_15 (5.5.5 pink)"/><ref name="MASK_COLOR_16" syntax="#define MASK_COLOR_16 (5.6.5 pink)"/><ref name="MASK_COLOR_24" syntax="#define MASK_COLOR_24 (8.8.8 pink)"/><ref name="MASK_COLOR_32" syntax="#define MASK_COLOR_32 (8.8.8 pink)"><xreflist><xref>bitmap_mask_color</xref><xref>makecol</xref><xref>draw_sprite</xref><xref>masked_blit</xref></xreflist><shortdesc>Constant representing the mask value in sprites.</shortdesc><text><![CDATA[   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).



]]></text></ref></reflist></section><section title="Drawing primitives"><text><![CDATA[
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.

]]></text><reflist><ref name="clear_bitmap" syntax="void clear_bitmap(BITMAP *bitmap);"><xreflist><xref>clear_to_color</xref></xreflist><ereflist><eref>Available Allegro examples</eref></ereflist><shortdesc>Clears the bitmap to color 0.</shortdesc><text><![CDATA[   Clears the bitmap to color 0.

]]></text></ref><ref name="clear_to_color" syntax="void clear_to_color(BITMAP *bitmap, int color);"><xreflist><xref>clear_bitmap</xref><xref>makecol</xref></xreflist><ereflist><eref>Available Allegro examples</eref></ereflist><shortdesc>Clears the bitmap to the specified color.</shortdesc><text><![CDATA[   Clears the bitmap to the specified color. Example:
<pre class="code">
      /* Clear the screen to red. */
      clear_to_color(bmp, makecol(255, 0, 0));</pre>

]]></text></ref><ref name="putpixel" syntax="void putpixel(BITMAP *bmp, int x, int y, int color);"><xreflist><xref>getpixel</xref><xref>_putpixel</xref><xref>drawing_mode</xref><xref>makecol</xref></xreflist><ereflist><eref>ex12bit</eref><eref>exalpha</eref><eref>exflame</eref><eref>exjoy</eref><eref>exstars</eref><eref>exswitch</eref></ereflist><shortdesc>Writes a pixel into a bitmap.</shortdesc><text><![CDATA[   Writes a pixel to the specified position in the bitmap, using the current
   drawing mode and the bitmap's clipping rectangle. Example:
<pre class="code">
      putpixel(screen, 10, 30, some_color);</pre>

]]></text></ref><ref name="_putpixel" syntax="void _putpixel(BITMAP *bmp, int x, int y, int color);"/><ref name="_putpixel15" syntax="void _putpixel15(BITMAP *bmp, int x, int y, int color);"/><ref name="_putpixel16" syntax="void _putpixel16(BITMAP *bmp, int x, int y, int color);"/><ref name="_putpixel24" syntax="void _putpixel24(BITMAP *bmp, int x, int y, int color);"/><ref name="_putpixel32" syntax="void _putpixel32(BITMAP *bmp, int x, int y, int color);"><xreflist><xref>putpixel</xref><xref>makecol</xref></xreflist><shortdesc>Faster specific version of putpixel().</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="getpixel" syntax="int getpixel(BITMAP *bmp, int x, int y);"><xreflist><xref>putpixel</xref><xref>_getpixel</xref><xref>is_inside_bitmap</xref><xref>getr</xref><xref>getg</xref><xref>getb</xref><xref>geta</xref><xref>Truecolor pixel formats</xref><xref>Palette routines</xref></xreflist><ereflist><eref>ex12bit</eref><eref>exalpha</eref><eref>exflame</eref><eref>exlights</eref></ereflist><shortdesc>Reads a pixel from a bitmap.</shortdesc><text><![CDATA[   Reads a pixel from point (x, y) in the bitmap.
]]></text><retval><text><![CDATA[   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.

]]></text></retval></ref><ref name="_getpixel" syntax="int _getpixel(BITMAP *bmp, int x, int y);"/><ref name="_getpixel15" syntax="int _getpixel15(BITMAP *bmp, int x, int y);"/><ref name="_getpixel16" syntax="int _getpixel16(BITMAP *bmp, int x, int y);"/><ref name="_getpixel24" syntax="int _getpixel24(BITMAP *bmp, int x, int y);"/><ref name="_getpixel32" syntax="int _getpixel32(BITMAP *bmp, int x, int y);"><xreflist><xref>getpixel</xref></xreflist><shortdesc>Faster specific version of getpixel().</shortdesc><text><![CDATA[   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.
]]></text><retval><text><![CDATA[   Returns the value of the pixel in the color format you specified.

]]></text></retval></ref><ref name="vline" syntax="void vline(BITMAP *bmp, int x, int y1, int y2, int color);"><xreflist><xref>hline</xref><xref>line</xref><xref>drawing_mode</xref><xref>makecol</xref><xref>Differences between platforms</xref></xreflist><ereflist><eref>exrgbhsv</eref><eref>exscroll</eref><eref>extruec</eref></ereflist><shortdesc>Draws a vertical line onto the bitmap.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="hline" syntax="void hline(BITMAP *bmp, int x1, int y, int x2, int color);"><xreflist><xref>vline</xref><xref>line</xref><xref>drawing_mode</xref><xref>makecol</xref><xref>Differences between platforms</xref></xreflist><ereflist><eref>exsprite</eref></ereflist><shortdesc>Draws a horizontal line onto the bitmap.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="do_line" syntax="void do_line(BITMAP *bmp, int x1, y1, x2, y2, int d, void (*proc)(BITMAP *bmp, int x, int y, int d));"><xreflist><xref>do_circle</xref><xref>do_ellipse</xref><xref>do_arc</xref><xref>line</xref></xreflist><shortdesc>Calculates all the points along a line.</shortdesc><text><![CDATA[   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:
<pre class="code">
      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);</pre>

]]></text></ref><ref name="line" syntax="void line(BITMAP *bmp, int x1, int y1, int x2, int y2, int color);"><xreflist><xref>fastline</xref><xref>hline</xref><xref>vline</xref><xref>do_line</xref><xref>drawing_mode</xref><xref>makecol</xref></xreflist><ereflist><eref>Available Allegro examples</eref></ereflist><shortdesc>Draws a line onto the bitmap.</shortdesc><text><![CDATA[   Draws a line onto the bitmap, from point (x1, y1) to (x2, y2).

]]></text></ref><ref name="fastline" syntax="void fastline(BITMAP *bmp, int x1, int y1, int x2, int y2, int color);"><xreflist><xref>line</xref><xref>hline</xref><xref>vline</xref><xref>do_line</xref><xref>drawing_mode</xref><xref>makecol</xref></xreflist><ereflist><eref>Available Allegro examples</eref></ereflist><shortdesc>Faster version of line().</shortdesc><text><![CDATA[   Faster version of the previous function. Note that pixel correctness is
   not guaranteed for this function.

]]></text></ref><ref name="triangle" syntax="void triangle(BITMAP *bmp, int x1, y1, x2, y2, x3, y3, int color);"><xreflist><xref>polygon</xref><xref>triangle3d</xref><xref>drawing_mode</xref><xref>makecol</xref></xreflist><ereflist><eref>ex3buf</eref><eref>exstars</eref><eref>exupdate</eref></ereflist><shortdesc>Draws a filled triangle.</shortdesc><text><![CDATA[   Draws a filled triangle between the three points.

]]></text></ref><ref name="polygon" syntax="void polygon(BITMAP *bmp, int vertices, const int *points, int color);"><xreflist><xref>triangle</xref><xref>polygon3d</xref><xref>drawing_mode</xref><xref>makecol</xref></xreflist><ereflist><eref>excamera</eref></ereflist><shortdesc>Draws a filled polygon.</shortdesc><text><![CDATA[   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:
<pre class="code">
      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));</pre>

]]></text></ref><ref name="rect" syntax="void rect(BITMAP *bmp, int x1, int y1, int x2, int y2, int color);"><xreflist><xref>rectfill</xref><xref>drawing_mode</xref><xref>makecol</xref></xreflist><ereflist><eref>ex3d</eref><eref>excamera</eref></ereflist><shortdesc>Draws an outline rectangle.</shortdesc><text><![CDATA[   Draws an outline rectangle with the two points as its opposite corners.

]]></text></ref><ref name="rectfill" syntax="void rectfill(BITMAP *bmp, int x1, int y1, int x2, int y2, int color);"><xreflist><xref>rect</xref><xref>clear_bitmap</xref><xref>drawing_mode</xref><xref>makecol</xref></xreflist><ereflist><eref>exalpha</eref><eref>excolmap</eref><eref>exkeys</eref><eref>exmidi</eref><eref>expat</eref><eref>exscroll</eref><eref>exsprite</eref><eref>exstars</eref><eref>exswitch</eref><eref>extrans</eref></ereflist><shortdesc>Draws a solid filled rectangle.</shortdesc><text><![CDATA[   Draws a solid, filled rectangle with the two points as its opposite
   corners.

]]></text></ref><ref name="do_circle" syntax="void do_circle(BITMAP *bmp, int x, int y, int radius, int d, void (*proc)(BITMAP *bmp, int x, int y, int d));"><xreflist><xref>do_ellipse</xref><xref>do_arc</xref><xref>do_line</xref><xref>circle</xref><xref>circlefill</xref></xreflist><shortdesc>Calculates all the points in a circle.</shortdesc><text><![CDATA[   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:
<pre class="code">
      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);</pre>

]]></text></ref><ref name="circle" syntax="void circle(BITMAP *bmp, int x, int y, int radius, int color);"><xreflist><xref>ellipse</xref><xref>arc</xref><xref>circlefill</xref><xref>do_circle</xref><xref>drawing_mode</xref><xref>makecol</xref></xreflist><ereflist><eref>ex12bit</eref><eref>exblend</eref><eref>excustom</eref><eref>exjoy</eref><eref>exmem</eref><eref>exmouse</eref><eref>exquat</eref><eref>exsprite</eref></ereflist><shortdesc>Draws a circle.</shortdesc><text><![CDATA[   Draws a circle with the specified centre and radius.

]]></text></ref><ref name="circlefill" syntax="void circlefill(BITMAP *bmp, int x, int y, int radius, int color);"><xreflist><xref>ellipsefill</xref><xref>circle</xref><xref>do_circle</xref><xref>drawing_mode</xref><xref>makecol</xref></xreflist><ereflist><eref>excolmap</eref><eref>excustom</eref><eref>exdbuf</eref><eref>exflip</eref><eref>exlights</eref><eref>expal</eref><eref>exspline</eref><eref>extrans</eref></ereflist><shortdesc>Draws a filled circle.</shortdesc><text><![CDATA[   Draws a filled circle with the specified centre and radius.

]]></text></ref><ref name="do_ellipse" syntax="void do_ellipse(BITMAP *bmp, int x, int y, int rx, ry, int d, void (*proc)(BITMAP *bmp, int x, int y, int d));"><xreflist><xref>do_circle</xref><xref>do_arc</xref><xref>do_line</xref><xref>ellipse</xref><xref>ellipsefill</xref></xreflist><shortdesc>Calculates all the points in an ellipse.</shortdesc><text><![CDATA[   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:
<pre class="code">
      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);</pre>

]]></text></ref><ref name="ellipse" syntax="void ellipse(BITMAP *bmp, int x, int y, int rx, int ry, int color);"><xreflist><xref>circle</xref><xref>arc</xref><xref>ellipsefill</xref><xref>do_ellipse</xref><xref>drawing_mode</xref><xref>makecol</xref></xreflist><shortdesc>Draws an ellipse.</shortdesc><text><![CDATA[   Draws an ellipse with the specified centre and radius.

]]></text></ref><ref name="ellipsefill" syntax="void ellipsefill(BITMAP *bmp, int x, int y, int rx, int ry, int color);"><xreflist><xref>circlefill</xref><xref>ellipse</xref><xref>do_ellipse</xref><xref>drawing_mode</xref><xref>makecol</xref></xreflist><ereflist><eref>ex12bit</eref></ereflist><shortdesc>Draws a filled ellipse.</shortdesc><text><![CDATA[   Draws a filled ellipse with the specified centre and radius.

]]></text></ref><ref name="do_arc" syntax="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));"><xreflist><xref>do_circle</xref><xref>do_ellipse</xref><xref>do_line</xref><xref>arc</xref></xreflist><shortdesc>Calculates all the points in a circular arc.</shortdesc><text><![CDATA[   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:
<pre class="code">
      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);</pre>

]]></text></ref><ref name="arc" syntax="void arc(BITMAP *bmp, int x, y, fixed ang1, ang2, int r, int color);"><xreflist><xref>circle</xref><xref>ellipse</xref><xref>drawing_mode</xref><xref>makecol</xref></xreflist><shortdesc>Draws a circular arc.</shortdesc><text><![CDATA[   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:
<pre class="code">
      /* 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));</pre>

]]></text></ref><ref name="calc_spline" syntax="void calc_spline(const int points[8], int npts, int *x, int *y);"><xreflist><xref>spline</xref></xreflist><ereflist><eref>exspline</eref></ereflist><shortdesc>Calculates a series of values along a bezier spline.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="spline" syntax="void spline(BITMAP *bmp, const int points[8], int color);"><xreflist><xref>calc_spline</xref><xref>drawing_mode</xref><xref>makecol</xref></xreflist><ereflist><eref>exspline</eref></ereflist><shortdesc>Draws a bezier spline using four control points.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="floodfill" syntax="void floodfill(BITMAP *bmp, int x, int y, int color);"><xreflist><xref>drawing_mode</xref><xref>makecol</xref></xreflist><shortdesc>Floodfills an enclosed area.</shortdesc><text><![CDATA[   Floodfills an enclosed area, starting at point (x, y), with the specified
   color.



]]></text></ref></reflist></section><section title="Blitting and sprites"><text><![CDATA[
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.

Thusly, 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.

]]></text><reflist><ref name="blit" syntax="void blit(BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height);"><xreflist><xref>masked_blit</xref><xref>stretch_blit</xref><xref>draw_sprite</xref><xref>gfx_capabilities</xref><xref>set_color_conversion</xref></xreflist><ereflist><eref>Available Allegro examples</eref></ereflist><shortdesc>Copies a rectangular area from one bitmap to another.</shortdesc><text><![CDATA[   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:
<pre class="code">
      BITMAP *bmp;
      ...
      /* Blit src on the screen. */
      blit(bmp, screen, 0, 0, 0, 0, bmp-&gt;w, bmp-&gt;h);

      /* Now copy a chunk to a corner, slightly outside. /*
      blit(screen, screen, 100, 100, -10, -10, 25, 30);
</pre>
   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.

]]></text></ref><ref name="stretch_blit" syntax="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);"><xreflist><xref>blit</xref><xref>masked_stretch_blit</xref><xref>stretch_sprite</xref></xreflist><ereflist><eref>exalpha</eref><eref>exconfig</eref><eref>exscale</eref><eref>extrans</eref></ereflist><shortdesc>Scales a rectangular area from one bitmap to another.</shortdesc><text><![CDATA[   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:
<pre class="code">
      BITMAP *bmp;
      ...
      /* Stretch bmp to fill the screen. */
      stretch_blit(bmp, screen, 0, 0, bmp-&gt;w, bmp-&gt;h,
		   0, 0, SCREEN_W, SCREEN_H);</pre>

]]></text></ref><ref name="masked_blit" syntax="void masked_blit(BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height);"><xreflist><xref>blit</xref><xref>masked_stretch_blit</xref><xref>draw_sprite</xref><xref>bitmap_mask_color</xref></xreflist><ereflist><eref>ex12bit</eref><eref>expat</eref></ereflist><shortdesc>Copies a rectangle skipping pixels with the mask color.</shortdesc><text><![CDATA[   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:
<pre class="code">
      BITMAP *hud_overlay;
      ...
      /* Paint hud overlay on the screen. */
      masked_blit(hud_overlay, screen, 0, 0, 0, 0,
		  hud_overlay-&gt;w, hud_overlay-&gt;h);</pre>

   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.

]]></text></ref><ref name="masked_stretch_blit" syntax="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);"><xreflist><xref>blit</xref><xref>masked_blit</xref><xref>stretch_blit</xref><xref>stretch_sprite</xref></xreflist><shortdesc>Scales a rectangular area skipping pixels with the mask color.</shortdesc><text><![CDATA[   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:
<pre class="code">
      BITMAP *hud_overlay;
      ...
      /* Stretch hud overlay over the screen. */
      masked_stretch_blit(hud_overlay, screen, 0, 0,
			  hud_overlay-&gt;w, hud_overlay-&gt;h,
			  0, 0, SCREEN_W, SCREEN_H);</pre>

]]></text></ref><ref name="draw_sprite" syntax="void draw_sprite(BITMAP *bmp, BITMAP *sprite, int x, int y);"><xreflist><xref>draw_sprite_v_flip</xref><xref>draw_trans_sprite</xref><xref>draw_lit_sprite</xref><xref>draw_gouraud_sprite</xref><xref>stretch_sprite</xref><xref>rotate_sprite</xref><xref>draw_character_ex</xref><xref>draw_rle_sprite</xref><xref>draw_compiled_sprite</xref><xref>masked_blit</xref><xref>blit</xref><xref>bitmap_mask_color</xref></xreflist><ereflist><eref>exsprite</eref></ereflist><shortdesc>Draws a copy of the sprite onto the destination bitmap.</shortdesc><text><![CDATA[   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-&gt;w, sprite-&gt;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:
<pre class="code">
      BITMAP *spaceship;
      ...
      draw_sprite(screen, spaceship, x, y);</pre>

   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.

]]></text></ref><ref name="stretch_sprite" syntax="void stretch_sprite(BITMAP *bmp, BITMAP *sprite, int x, int y, int w, int h);"><xreflist><xref>draw_sprite</xref><xref>stretch_blit</xref><xref>bitmap_mask_color</xref></xreflist><shortdesc>Stretches a sprite to the destination bitmap.</shortdesc><text><![CDATA[   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:
<pre class="code">
      /* Create tunnel like effect. */
      for (step = 1; step < 16; 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);
      }</pre>

]]></text></ref><ref name="draw_sprite_v_flip" syntax="void draw_sprite_v_flip(BITMAP *bmp, BITMAP *sprite, int x, int y);"/><ref name="draw_sprite_h_flip" syntax="void draw_sprite_h_flip(BITMAP *bmp, BITMAP *sprite, int x, int y);"/><ref name="draw_sprite_vh_flip" syntax="void draw_sprite_vh_flip(BITMAP *bmp, BITMAP *sprite, int x, int y);"><xreflist><xref>draw_sprite</xref><xref>bitmap_mask_color</xref></xreflist><ereflist><eref>exsprite</eref></ereflist><shortdesc>Draws the sprite transformed to the destination bitmap.</shortdesc><text><![CDATA[   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:
<pre class="code">
      if (key[KEY_RIGHT])
	 draw_sprite(screen, hero_right, pos_x, pos_y);
      else if (key[KEY_LEFT])
	 draw_h_sprite(screen, hero_right, pos_x, pos_y);
      else
	 draw_sprite(screen, hero_idle, pos_x, pos_y);</pre>

]]></text></ref><ref name="draw_trans_sprite" syntax="void draw_trans_sprite(BITMAP *bmp, BITMAP *sprite, int x, int y);"><xreflist><xref>draw_sprite</xref><xref>draw_lit_sprite</xref><xref>draw_trans_rle_sprite</xref><xref>color_map</xref><xref>set_trans_blender</xref><xref>set_alpha_blender</xref><xref>set_write_alpha_blender</xref><xref>bitmap_mask_color</xref></xreflist><ereflist><eref>exalpha</eref><eref>exblend</eref><eref>exlights</eref><eref>extrans</eref><eref>exxfade</eref></ereflist><shortdesc>Draws a sprite blending it with the destination.</shortdesc><text><![CDATA[   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:
<pre class="code">
      /* Some one time initialisation code. */
      COLOR_MAP global_trans_table;
      create_trans_table(&amp;global_trans_table, my_palette,
			 128, 128, 128, NULL);
      ...
      if (get_color_depth() == 8)
	 color_map = &amp;global_trans_table;
      else
	 set_trans_blender(128, 128, 128, 128);

      draw_trans_sprite(buffer, ghost_sprite, x, y);</pre>

   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.

]]></text></ref><ref name="draw_lit_sprite" syntax="void draw_lit_sprite(BITMAP *bmp, BITMAP *sprite, int x, int y, int color);"><xreflist><xref>draw_sprite</xref><xref>draw_trans_sprite</xref><xref>draw_gouraud_sprite</xref><xref>draw_lit_rle_sprite</xref><xref>color_map</xref><xref>set_trans_blender</xref><xref>bitmap_mask_color</xref></xreflist><ereflist><eref>exblend</eref></ereflist><shortdesc>Draws a sprite tinted with a specific color.</shortdesc><text><![CDATA[   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:
<pre class="code">
      /* Some one time initialisation code. */
      COLOR_MAP global_light_table;
      create_light_table(&amp;global_trans_table, my_palette,
			 10, 10, 60, NULL);
      ...
      if (get_color_depth() == 8)
	 color_map = &amp;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);</pre>

]]></text></ref><ref name="draw_gouraud_sprite" syntax="void draw_gouraud_sprite(BITMAP *bmp, BITMAP *sprite, int x, int y, int c1, int c2, int c3, int c4);"><xreflist><xref>draw_sprite</xref><xref>draw_lit_sprite</xref><xref>color_map</xref><xref>set_trans_blender</xref><xref>bitmap_mask_color</xref></xreflist><ereflist><eref>exshade</eref></ereflist><shortdesc>Draws a sprite with gouraud shading.</shortdesc><text><![CDATA[   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:
<pre class="code">
      /* Some one time initialisation code. */
      COLOR_MAP global_light_table;
      create_light_table(&amp;global_trans_table, my_palette,
			 0, 0, 0, NULL);
      ...
      if (get_color_depth() == 8)
	 color_map = &amp;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);</pre>

]]></text></ref><ref name="draw_character_ex" syntax="void draw_character_ex(BITMAP *bmp, BITMAP *sprite, int x, int y, color, bg);"><xreflist><xref>draw_sprite</xref><xref>bitmap_mask_color</xref></xreflist><shortdesc>Draws non transparent pixels of the sprite with a color.</shortdesc><text><![CDATA[   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:
<pre class="code">
      BITMAP *logo;
      ...
      /* Draw the logo silhouette in red. */
      draw_character_ex(screen, logo, SCREEN_W / 2, SCREEN_H / 2,
			makecol(255, 0, 0), -1);</pre>

]]></text></ref><ref name="rotate_sprite" syntax="void rotate_sprite(BITMAP *bmp, BITMAP *sprite, int x, int y, fixed angle);"><xreflist><xref>draw_sprite</xref><xref>rotate_scaled_sprite</xref><xref>rotate_sprite_v_flip</xref><xref>rotate_scaled_sprite_v_flip</xref><xref>pivot_sprite</xref><xref>pivot_sprite_v_flip</xref><xref>pivot_scaled_sprite</xref><xref>pivot_scaled_sprite_v_flip</xref><xref>itofix</xref><xref>Fixed point trig</xref></xreflist><ereflist><eref>exsprite</eref></ereflist><shortdesc>Rotates a sprite.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="rotate_sprite_v_flip" syntax="void rotate_sprite_v_flip(BITMAP *bmp, BITMAP *sprite, int x, int y, fixed angle);"><xreflist><xref>rotate_sprite</xref><xref>rotate_scaled_sprite_v_flip</xref><xref>pivot_sprite_v_flip</xref><xref>pivot_scaled_sprite_v_flip</xref></xreflist><ereflist><eref>exsprite</eref></ereflist><shortdesc>Rotates and flips a sprite.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="rotate_scaled_sprite" syntax="void rotate_scaled_sprite(BITMAP *bmp, BITMAP *sprite, int x, int y, fixed angle, fixed scale);"><xreflist><xref>rotate_sprite</xref><xref>rotate_scaled_sprite_v_flip</xref><xref>pivot_scaled_sprite</xref><xref>pivot_scaled_sprite_v_flip</xref></xreflist><shortdesc>Rotates and stretches a sprite.</shortdesc><text><![CDATA[   Like rotate_sprite(), but stretches or shrinks the image at the same time
   as rotating it.

]]></text></ref><ref name="rotate_scaled_sprite_v_flip" syntax="void rotate_scaled_sprite_v_flip(BITMAP *bmp, BITMAP *sprite, int x, int y, fixed angle, fixed scale);"><xreflist><xref>rotate_sprite</xref><xref>rotate_scaled_sprite</xref><xref>rotate_sprite_v_flip</xref></xreflist><shortdesc>Rotates, stretches and flips a sprite.</shortdesc><text><![CDATA[   Draws the sprite, similar to rotate_scaled_sprite() except that it flips
   the sprite vertically first.

]]></text></ref><ref name="pivot_sprite" syntax="void pivot_sprite(BITMAP *bmp, BITMAP *sprite, int x, int y, int cx, int cy, fixed angle);"><xreflist><xref>rotate_sprite</xref><xref>pivot_scaled_sprite</xref><xref>pivot_sprite_v_flip</xref></xreflist><ereflist><eref>exsprite</eref></ereflist><shortdesc>Rotates a sprite around a specified point.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="pivot_sprite_v_flip" syntax="void pivot_sprite_v_flip(BITMAP *bmp, BITMAP *sprite, int x, int y, int cx, int cy, fixed angle);"><xreflist><xref>rotate_sprite</xref><xref>rotate_sprite_v_flip</xref><xref>pivot_sprite</xref></xreflist><ereflist><eref>exsprite</eref></ereflist><shortdesc>Rotates and flips a sprite around a specified point.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="pivot_scaled_sprite" syntax="void pivot_scaled_sprite(BITMAP *bmp, BITMAP *sprite, int x, int y, int cx, int cy, fixed angle, fixed scale);"><xreflist><xref>rotate_sprite</xref><xref>rotate_scaled_sprite</xref><xref>pivot_sprite</xref><xref>pivot_scaled_sprite_v_flip</xref></xreflist><shortdesc>Rotates and stretches a sprite around a specified point.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="pivot_scaled_sprite_v_flip" syntax="void pivot_scaled_sprite_v_flip(BITMAP *bmp, BITMAP *sprite, int x, int y, int cx, int cy, fixed angle, fixed scale);"><xreflist><xref>rotate_sprite</xref><xref>rotate_scaled_sprite_v_flip</xref><xref>rotate_sprite_v_flip</xref><xref>pivot_sprite</xref><xref>pivot_scaled_sprite</xref></xreflist><shortdesc>Rotates, stretches and flips a sprite around a specified point.</shortdesc><text><![CDATA[   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.



]]></text></ref></reflist></section><section title="RLE sprites"><text><![CDATA[
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'.

]]></text><reflist><ref name="get_rle_sprite" syntax="RLE_SPRITE *get_rle_sprite(BITMAP *bitmap);"><xreflist><xref>draw_rle_sprite</xref><xref>destroy_rle_sprite</xref></xreflist><shortdesc>Creates an RLE sprite using a bitmap as source.</shortdesc><text><![CDATA[   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:
<pre class="code">
      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);</pre>
]]></text><retval><text><![CDATA[   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.

]]></text></retval></ref><ref name="destroy_rle_sprite" syntax="void destroy_rle_sprite(RLE_SPRITE *sprite);"><xreflist><xref>get_rle_sprite</xref></xreflist><shortdesc>Destroys an RLE sprite.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="draw_rle_sprite" syntax="void draw_rle_sprite(BITMAP *bmp, const RLE_SPRITE *sprite, int x, int y);"><xreflist><xref>get_rle_sprite</xref><xref>draw_sprite</xref><xref>draw_compiled_sprite</xref><xref>draw_trans_rle_sprite</xref><xref>draw_lit_rle_sprite</xref><xref>bitmap_mask_color</xref></xreflist><shortdesc>Draws an RLE sprite.</shortdesc><text><![CDATA[   Draws an RLE sprite onto a bitmap at the specified position. Example:
<pre class="code">
      RLE_SPRITE *rle_sprite;
      ...
      draw_rle_sprite(screen, rle_sprite, 100, 100);</pre>

]]></text></ref><ref name="draw_trans_rle_sprite" syntax="void draw_trans_rle_sprite(BITMAP *bmp, const RLE_SPRITE *sprite, int x, int y);"><xreflist><xref>draw_rle_sprite</xref><xref>draw_lit_rle_sprite</xref><xref>draw_trans_sprite</xref><xref>color_map</xref><xref>set_trans_blender</xref><xref>set_alpha_blender</xref><xref>bitmap_mask_color</xref></xreflist><shortdesc>Draws a translucent RLE sprite.</shortdesc><text><![CDATA[   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:
<pre class="code">
      /* Some one time initialisation code. */
      COLOR_MAP global_trans_table;
      create_trans_table(&amp;global_trans_table, my_palette,
			 128, 128, 128, NULL);
      ...
      if (get_color_depth() == 8)
	 color_map = &amp;global_trans_table;
      else
	 set_trans_blender(128, 128, 128, 128);

      draw_trans_rle_sprite(buffer, rle_ghost_sprite, x, y);</pre>

]]></text></ref><ref name="draw_lit_rle_sprite" syntax="void draw_lit_rle_sprite(BITMAP *bmp, const RLE_SPRITE *sprite, int x, y, color);"><xreflist><xref>draw_rle_sprite</xref><xref>draw_trans_rle_sprite</xref><xref>draw_lit_sprite</xref><xref>color_map</xref><xref>set_trans_blender</xref><xref>bitmap_mask_color</xref></xreflist><shortdesc>Draws a tinted RLE sprite.</shortdesc><text><![CDATA[   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:
<pre class="code">
      /* Some one time initialisation code. */
      COLOR_MAP global_light_table;
      create_light_table(&amp;global_trans_table, my_palette,
			 10, 10, 60, NULL);
      ...
      if (get_color_depth() == 8)
	 color_map = &amp;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);</pre>



]]></text></ref></reflist></section><section title="Compiled sprites"><text><![CDATA[
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'.

]]></text><reflist><ref name="get_compiled_sprite" syntax="COMPILED_SPRITE *get_compiled_sprite(BITMAP *bitmap, int planar);"><xreflist><xref>draw_compiled_sprite</xref><xref>destroy_compiled_sprite</xref></xreflist><shortdesc>Creates a compiled sprite using a bitmap as source.</shortdesc><text><![CDATA[   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:
<pre class="code">
      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);
</pre>
   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.

]]></text></ref><ref name="destroy_compiled_sprite" syntax="void destroy_compiled_sprite(COMPILED_SPRITE *sprite);"><xreflist><xref>get_compiled_sprite</xref></xreflist><shortdesc>Destroys a compiled sprite.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="draw_compiled_sprite" syntax="void draw_compiled_sprite(BITMAP *bmp, const COMPILED_SPRITE *sprite, int x, int y);"><xreflist><xref>get_compiled_sprite</xref><xref>draw_sprite</xref><xref>draw_rle_sprite</xref><xref>bitmap_mask_color</xref></xreflist><shortdesc>Draws a compiled sprite.</shortdesc><text><![CDATA[   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...



]]></text></ref></reflist></section><section title="Fonts"><text><![CDATA[
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 <a href="http://www.allegro.cc/">http://www.allegro.cc/</a>) and render them directly, or generate a
bitmapped version of a TrueType font with tools like TTF2PCX
(<a href="http://www.talula.demon.co.uk/ttf2pcx/index.html">http://www.talula.demon.co.uk/ttf2pcx/index.html</a>).

]]></text><reflist><ref name="register_font_file_type" syntax="void register_font_file_type(const char *ext, FONT *(*load)(const char *filename, RGB *pal, void *param));"><xreflist><xref>load_font</xref></xreflist><shortdesc>Register a new font loading function.</shortdesc><text><![CDATA[   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:
<pre class="code">
      FONT *load_my_font(const char *filename, RGB *pal, void *param)
      {
	 ...
      }
</pre>
   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.

]]></text></ref><ref name="load_font" syntax="FONT *load_font(const char *filename, RGB *pal, void *param);"><xreflist><xref>register_font_file_type</xref><xref>load_bitmap</xref><xref>load_dat_font</xref><xref>load_bios_font</xref><xref>load_grx_font</xref><xref>load_grx_or_bios_font</xref><xref>load_bitmap_font</xref><xref>load_txt_font</xref><xref>destroy_font</xref></xreflist><ereflist><eref>exfont</eref></ereflist><shortdesc>Loads a font from a file.</shortdesc><text><![CDATA[   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:
<pre class="code">
      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(bmp);</pre>
]]></text><retval><text><![CDATA[   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.

]]></text></retval></ref><ref name="destroy_font" syntax="void destroy_font(FONT *f);"><xreflist><xref>load_datafile_object</xref><xref>load_font</xref></xreflist><ereflist><eref>exfont</eref></ereflist><shortdesc>Frees the memory being used by a font structure.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="make_trans_font" syntax="void make_trans_font(FONT *f);"><xreflist><xref>set_alpha_blender</xref><xref>load_font</xref><xref>draw_trans_sprite</xref></xreflist><shortdesc>Makes a font use transparency.</shortdesc><text><![CDATA[   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:

   <pre class="code">
   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!");</pre>

]]></text></ref><ref name="is_color_font" syntax="int is_color_font(FONT *f)"><xreflist><xref>is_mono_font</xref></xreflist><shortdesc>Returns TRUE if a font is a color font.</shortdesc><text><![CDATA[   This function checks if the given font is a color font, as opposed to a
   monochrome font.
]]></text><retval><text><![CDATA[   Returns TRUE if the font is a color font, FALSE if it is not.

]]></text></retval></ref><ref name="is_mono_font" syntax="int is_mono_font(FONT *f)"><xreflist><xref>is_color_font</xref></xreflist><shortdesc>Returns TRUE if a font is a monochrome font.</shortdesc><text><![CDATA[   This function checks if the given font is a mono font, as opposed to a
   color font.
]]></text><retval><text><![CDATA[   Returns TRUE if the font is a monochrome font, FALSE if it is not.

]]></text></retval></ref><ref name="is_compatible_font" syntax="FONT *is_compatible_font(FONT *f1, FONT *f2)"><xreflist><xref>merge_fonts</xref><xref>is_color_font</xref><xref>is_mono_font</xref></xreflist><shortdesc>Check if two fonts are of the same type.</shortdesc><text><![CDATA[   This function compares the two fonts, which you can use to find out if
   Allegro is capable of merging them.
]]></text><retval><text><![CDATA[   Returns TRUE if the two fonts are of the same general type (both are color
   fonts or both are monochrome fonts, for instance).

]]></text></retval></ref><ref name="get_font_ranges" syntax="int get_font_ranges(FONT *f)"><xreflist><xref>get_font_range_begin</xref><xref>get_font_range_end</xref><xref>transpose_font</xref></xreflist><shortdesc>Returns the number of character ranges in a font.</shortdesc><text><![CDATA[   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:
<pre class="code">
      FONT *f;
      int range;
      int n;
      ...

      range = get_font_ranges(f);
      printf("The font has %d character ranges:\n", range);
      for (n = 0; n &lt; range; n++)
	 printf("Range %d from 0x%03x - 0x%03x\n",
		get_font_range_begin(f, n),
		get_font_range_end(f, n));</pre>
]]></text><retval><text><![CDATA[   Returns the number of continuous character ranges in a font, or -1 if that
   information is not available.

]]></text></retval></ref><ref name="get_font_range_begin" syntax="int get_font_range_begin(FONT *f, int range)"><xreflist><xref>get_font_ranges</xref><xref>get_font_range_end</xref><xref>transpose_font</xref></xreflist><shortdesc>Returns the start of a character range in a font.</shortdesc><text><![CDATA[   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:
<pre class="code">
      printf("The font has a character range of %d - %d\n",
	     get_font_range_begin(font, -1),
	     get_font_range_end(font, -1));</pre>
]]></text><retval><text><![CDATA[   Returns the first character in the font range, or -1 if that information
   is not available.

]]></text></retval></ref><ref name="get_font_range_end" syntax="int get_font_range_end(FONT *f, int range)"><xreflist><xref>get_font_ranges</xref><xref>get_font_range_begin</xref><xref>transpose_font</xref></xreflist><shortdesc>Returns the last character of a character range in a font.</shortdesc><text><![CDATA[   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:
<pre class="code">
      printf("The font has a character range of %d - %d\n",
	     get_font_range_begin(font, -1),
	     get_font_range_end(font, -1));</pre>
]]></text><retval><text><![CDATA[   Returns the last character in the font range, or -1 if that information is
   not available.

]]></text></retval></ref><ref name="extract_font_range" syntax="FONT *extract_font_range(FONT *f, int begin, int end)"><xreflist><xref>get_font_range_begin</xref><xref>get_font_range_end</xref><xref>merge_fonts</xref><xref>transpose_font</xref></xreflist><ereflist><eref>exfont</eref></ereflist><shortdesc>Extracts a range of characters from a font.</shortdesc><text><![CDATA[   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:
<pre class="code">
      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);</pre>
]]></text><retval><text><![CDATA[   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.

]]></text></retval></ref><ref name="transpose_font" syntax="int transpose_font(FONT *f, int drange)"><xreflist><xref>get_font_range_begin</xref><xref>get_font_range_end</xref><xref>merge_fonts</xref><xref>extract_font_range</xref></xreflist><shortdesc>Transposes all characters in a font.</shortdesc><text><![CDATA[   This function transposes all characters in a font, effectively remapping the
   font. Example:
<pre class="code">
      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);</pre>
]]></text><retval><text><![CDATA[   Returns 0 on success, -1 on failure.

]]></text></retval></ref><ref name="merge_fonts" syntax="FONT *merge_fonts(FONT *f1, FONT *f2)"><xreflist><xref>extract_font_range</xref><xref>is_color_font</xref><xref>is_mono_font</xref></xreflist><ereflist><eref>exfont</eref></ereflist><shortdesc>Merges two fonts into one font.</shortdesc><text><![CDATA[   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:
<pre class="code">
      FONT *myfont;
      FONT *myfancy_font;
      FONT *lower_range;
      FONT *upper_range;
      FONT *capitals;
      FONT *combined_font;
      FONT *tempfont;
      ...
      /* Create a font that contains the capatials 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);</pre>
]]></text><retval><text><![CDATA[   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.

]]></text></retval></ref><ref name="load_dat_font" syntax="FONT *load_dat_font(const char *filename, RGB *pal, void *param)"><xreflist><xref>register_font_file_type</xref><xref>load_font</xref></xreflist><shortdesc>Loads a FONT from an Allegro datafile.</shortdesc><text><![CDATA[   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:
<pre class="text">
      FONT  FONT_1_DATA
      FONT  FONT_2_DATA
      FONT  FONT_3_DATA
      PAL   FONT_1_PALETTE
      PAL   FONT_2_PALETTE
</pre>
   Then the following code will load FONT_1_DATA as a FONT and return
   FONT_1_PALETTE as the palette:
<pre class="code">
      FONT *f;
      PALETTE pal;
      char *names[] = { "FONT_1_DATA", "FONT_1_PALETTE" }

      f = load_dat_font("fonts.dat", pal, names);
</pre>
   If instead you want to load the second font, FONT_2, from the datafile,
   you would use:
<pre class="code">
      FONT *f;
      PALETTE pal;
      char *names[] = { "FONT_2_DATA", "FONT_2_PALETTE" }

      f = load_dat_font("fonts.dat", pal, names);
</pre>
   If you want to load the third font, but not bother with a palette, use:
<pre class="code">
      FONT *f;
      char *names[] = { "FONT_3_DATA", NULL }

      f = load_dat_font("fonts.dat", NULL, names);</pre>
]]></text><retval><text><![CDATA[   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.

]]></text></retval></ref><ref name="load_bios_font" syntax="FONT *load_bios_font(const char *filename, RGB *pal, void *param)"><xreflist><xref>register_font_file_type</xref><xref>load_font</xref></xreflist><shortdesc>Loads a 8x8 or 8x16 BIOS format font.</shortdesc><text><![CDATA[   Loads a 8x8 or 8x16 BIOS format font. You shouldn't normally call this
   routine directly.
]]></text><retval><text><![CDATA[   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.

]]></text></retval></ref><ref name="load_grx_font" syntax="FONT *load_grx_font(const char *filename, RGB *pal, void *param)"><xreflist><xref>register_font_file_type</xref><xref>load_font</xref></xreflist><shortdesc>Loads a GRX format font.</shortdesc><text><![CDATA[   Loads a GRX format font. You shouldn't normally call this routine
   directly.
]]></text><retval><text><![CDATA[   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.

]]></text></retval></ref><ref name="load_grx_or_bios_font" syntax="FONT *load_grx_or_bios_font(const char *filename, RGB *pal, void *param)"><xreflist><xref>register_font_file_type</xref><xref>load_font</xref></xreflist><shortdesc>Loads either a BIOS or GRX format font.</shortdesc><text><![CDATA[   Loads either a BIOS or GRX format font. You shouldn't normally call this
   routine directly.
]]></text><retval><text><![CDATA[   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.

]]></text></retval></ref><ref name="load_bitmap_font" syntax="FONT *load_bitmap_font(const char *filename, RGB *pal, void *param)"><xreflist><xref>register_font_file_type</xref><xref>load_font</xref><xref>load_bitmap</xref><xref>set_color_depth</xref><xref>grab_font_from_bitmap</xref></xreflist><shortdesc>Grabs a font from a bitmap file.</shortdesc><text><![CDATA[   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 colordepth of the image file:
<ul><li>
   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.
<li>
   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).
</ul>

   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 colordepth 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 colordepth to the colordepth you want to use before loading any
   fonts.
]]></text><retval><text><![CDATA[   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.

]]></text></retval></ref><ref name="grab_font_from_bitmap" syntax="FONT *grab_font_from_bitmap(BITMAP *bmp)"><xreflist><xref>load_bitmap_font</xref></xreflist><shortdesc>Grabs a font from a bitmap</shortdesc><text><![CDATA[   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.
]]></text><retval><text><![CDATA[   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.

]]></text></retval></ref><ref name="load_txt_font" syntax="FONT *load_txt_font(const char *filename, RGB *pal, void *param)"><xreflist><xref>register_font_file_type</xref><xref>load_font</xref></xreflist><shortdesc>Loads a font script.</shortdesc><text><![CDATA[   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:
   <pre class="text">
      ascii.fnt 0x20 0x7F
      - 0xA0 0xFF
      dingbats.fnt 0x1000
   </pre>
   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.
]]></text><retval><text><![CDATA[   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.



]]></text></retval></ref></reflist></section><section title="Text output"><text><![CDATA[
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.

]]></text><reflist><ref name="font" syntax="extern FONT *font;"><xreflist><xref>textout_ex</xref><xref>textprintf_ex</xref></xreflist><ereflist><eref>Available Allegro examples</eref></ereflist><shortdesc>A simple 8x8 fixed size font.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="allegro_404_char" syntax="extern int allegro_404_char;"><xreflist><xref>font</xref></xreflist><shortdesc>Character used when Allegro cannot find a glyph.</shortdesc><text><![CDATA[   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:
<pre class="code">
      /* Show unknown glyphs with an asterisk. */
      allegro_404_char = '*';</pre>

]]></text></ref><ref name="text_length" syntax="int text_length(const FONT *f, const char *str);"><xreflist><xref>text_height</xref></xreflist><ereflist><eref>ex12bit</eref><eref>exmidi</eref><eref>expat</eref><eref>exunicod</eref></ereflist><shortdesc>Returns the length of a string in pixels.</shortdesc><text><![CDATA[   Returns the length (in pixels) of a string in the specified font. Example:
<pre class="code">
      int width = text_length(font, "I love spam");
      ...
      bmp = create_bitmap(width, height);</pre>

]]></text></ref><ref name="text_height" syntax="int text_height(const FONT *f)"><xreflist><xref>text_length</xref></xreflist><ereflist><eref>ex12bit</eref><eref>exmidi</eref><eref>expackf</eref><eref>expat</eref><eref>exsprite</eref><eref>exsyscur</eref><eref>exunicod</eref></ereflist><shortdesc>Returns the height of a font in pixels.</shortdesc><text><![CDATA[   Returns the height (in pixels) of the specified font. Example:
<pre class="code">
      int height = text_height(font);
      ...
      bmp = create_bitmap(width, height);</pre>

]]></text></ref><ref name="textout_ex" syntax="void textout_ex(BITMAP *bmp, const FONT *f, const char *s, int x, int y, int color, int bg);"><xreflist><xref>font</xref><xref>textout_centre_ex</xref><xref>textout_right_ex</xref><xref>textout_justify_ex</xref><xref>textprintf_ex</xref><xref>text_height</xref><xref>text_length</xref></xreflist><ereflist><eref>Available Allegro examples</eref></ereflist><shortdesc>Writes a string on a bitmap.</shortdesc><text><![CDATA[   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:
<pre class="code">
      /* Show the program's version in blue letters. */
      textout_ex(screen, font, "v4.2.0-beta2", 10, 10,
		 makecol(0, 0, 255), -1);</pre>

]]></text></ref><ref name="textout_centre_ex" syntax="void textout_centre_ex(BITMAP *bmp, const FONT *f, const char *s, int x, y, int color, int bg);"><xreflist><xref>textout_ex</xref><xref>textprintf_centre_ex</xref></xreflist><ereflist><eref>Available Allegro examples</eref></ereflist><shortdesc>Writes a centered string on a bitmap.</shortdesc><text><![CDATA[   Like textout_ex(), but interprets the x coordinate as the centre rather
   than the left edge of the string. Example:
<pre class="code">
      /* 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));</pre>

]]></text></ref><ref name="textout_right_ex" syntax="void textout_right_ex(BITMAP *bmp, const FONT *f, const char *s, int x, int y, int color, int bg);"><xreflist><xref>textout_ex</xref><xref>textprintf_right_ex</xref></xreflist><shortdesc>Writes a right aligned string on a bitmap.</shortdesc><text><![CDATA[   Like textout_ex(), but interprets the x coordinate as the right rather
   than the left edge of the string. Example:
<pre class="code">
      textout_right_ex(screen, font, "Look at this color!",
		       SCREEN_W - 10, 10, my_yellow, -1);</pre>

]]></text></ref><ref name="textout_justify_ex" syntax="void textout_justify_ex(BITMAP *bmp, const FONT *f, const char *s, int x1, int x2, int y, int diff, int color, int bg);"><xreflist><xref>textout_ex</xref><xref>textprintf_justify_ex</xref></xreflist><shortdesc>Draws justified text within a region.</shortdesc><text><![CDATA[   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:
<pre class="code">
      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));</pre>

]]></text></ref><ref name="textprintf_ex" syntax="void textprintf_ex(BITMAP *bmp, const FONT *f, int x, int y, int color, int bg, const char *fmt, ...);"><xreflist><xref>font</xref><xref>textout_ex</xref><xref>textprintf_centre_ex</xref><xref>textprintf_right_ex</xref><xref>textprintf_justify_ex</xref><xref>text_height</xref><xref>text_length</xref><xref>uszprintf</xref></xreflist><ereflist><eref>Available Allegro examples</eref></ereflist><shortdesc>Formatted output of a string.</shortdesc><text><![CDATA[   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:
<pre class="code">
      int player_score;
      ...
      textprintf_ex(screen, font, 10, 10, makecol(255, 100, 200),
		    -1, "Score: %d", player_score);</pre>

]]></text></ref><ref name="textprintf_centre_ex" syntax="void textprintf_centre_ex(BITMAP *bmp, const FONT *f, int x, int y, int color, int bg, const char *fmt, ...);"><xreflist><xref>textprintf_ex</xref><xref>textout_centre_ex</xref></xreflist><ereflist><eref>Available Allegro examples</eref></ereflist><shortdesc>Formatted centered output of a string.</shortdesc><text><![CDATA[   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:
<pre class="code">
      textprintf_centre_ex(screen, font, SCREEN_W / 2, 120,
			   makecol(0, 100, 243), -1,
			   "Your best score so far was %d!",
			   total_max_points);</pre>

]]></text></ref><ref name="textprintf_right_ex" syntax="void textprintf_right_ex(BITMAP *bmp, const FONT *f, int x, y, color, bg, const char *fmt, ...);"><xreflist><xref>textprintf_ex</xref><xref>textout_right_ex</xref></xreflist><shortdesc>Formatted right aligned output of a string.</shortdesc><text><![CDATA[   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:
<pre class="code">
      textprintf_right_ex(screen, font, SCREEN_W - 10, 10,
			  makecol(200, 200, 20), -1,
			  "%d bullets left", player_ammo);</pre>

]]></text></ref><ref name="textprintf_justify_ex" syntax="void textprintf_justify_ex(BITMAP *bmp, const FONT *f, int x1, x2, y, diff, color, bg, const char *fmt, ...);"><xreflist><xref>textprintf_ex</xref><xref>textout_justify_ex</xref></xreflist><shortdesc>Formatted justified output of a string.</shortdesc><text><![CDATA[   Like textout_justify_ex(), but using a printf() style format string. This
   function shares the text length limitation of textprintf_ex(). Example:
<pre class="code">
      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);</pre>



]]></text></ref></reflist></section><section title="Polygon rendering"><text><![CDATA[
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.

]]></text><reflist><ref name="POLYTYPE_FLAT" syntax="#define POLYTYPE_FLAT"><xreflist><xref>Polygon rendering</xref><xref>polygon3d</xref><xref>drawing_mode</xref></xreflist><ereflist><eref>ex3d</eref><eref>excamera</eref></ereflist><shortdesc>Polygon rendering mode type</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="POLYTYPE_GCOL" syntax="#define POLYTYPE_GCOL"><xreflist><xref>Polygon rendering</xref><xref>polygon3d</xref><xref>makecol</xref></xreflist><ereflist><eref>ex3d</eref><eref>exscn3d</eref><eref>exzbuf</eref></ereflist><shortdesc>Polygon rendering mode type</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="POLYTYPE_GRGB" syntax="#define POLYTYPE_GRGB"><xreflist><xref>Polygon rendering</xref><xref>polygon3d</xref><xref>rgb_map</xref></xreflist><ereflist><eref>ex3d</eref></ereflist><shortdesc>Polygon rendering mode type</shortdesc><text><![CDATA[   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).

]]></text></ref><ref name="POLYTYPE_ATEX" syntax="#define POLYTYPE_ATEX"><xreflist><xref>Polygon rendering</xref><xref>polygon3d</xref></xreflist><ereflist><eref>ex3d</eref></ereflist><shortdesc>Polygon rendering mode type</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="POLYTYPE_PTEX" syntax="#define POLYTYPE_PTEX"><xreflist><xref>Polygon rendering</xref><xref>polygon3d</xref><xref>POLYTYPE_ATEX</xref></xreflist><ereflist><eref>ex3d</eref></ereflist><shortdesc>Polygon rendering mode type</shortdesc><text><![CDATA[   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).

]]></text></ref><ref name="POLYTYPE_ATEX_MASK" syntax="#define POLYTYPE_ATEX_MASK"/><ref name="POLYTYPE_PTEX_MASK" syntax="#define POLYTYPE_PTEX_MASK"><xreflist><xref>Polygon rendering</xref><xref>polygon3d</xref><xref>POLYTYPE_ATEX</xref><xref>POLYTYPE_PTEX</xref></xreflist><ereflist><eref>ex3d</eref></ereflist><shortdesc>Polygon rendering mode type</shortdesc><text><![CDATA[   Like POLYTYPE_ATEX and POLYTYPE_PTEX, but zero texture map pixels are
   skipped, allowing parts of the texture map to be transparent.

]]></text></ref><ref name="POLYTYPE_ATEX_LIT" syntax="#define POLYTYPE_ATEX_LIT"/><ref name="POLYTYPE_PTEX_LIT" syntax="#define POLYTYPE_PTEX_LIT"><xreflist><xref>Polygon rendering</xref><xref>polygon3d</xref><xref>POLYTYPE_ATEX</xref><xref>POLYTYPE_PTEX</xref><xref>color_map</xref><xref>Truecolor transparency</xref></xreflist><ereflist><eref>ex3d</eref></ereflist><shortdesc>Polygon rendering mode type</shortdesc><text><![CDATA[   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!

]]></text></ref><ref name="POLYTYPE_ATEX_MASK_LIT" syntax="#define POLYTYPE_ATEX_MASK_LIT"/><ref name="POLYTYPE_PTEX_MASK_LIT" syntax="#define POLYTYPE_PTEX_MASK_LIT"><xreflist><xref>Polygon rendering</xref><xref>polygon3d</xref><xref>POLYTYPE_ATEX_LIT</xref><xref>POLYTYPE_PTEX_LIT</xref></xreflist><ereflist><eref>ex3d</eref></ereflist><shortdesc>Polygon rendering mode type</shortdesc><text><![CDATA[   Like POLYTYPE_ATEX_LIT and POLYTYPE_PTEX_LIT, but zero texture map pixels
   are skipped, allowing parts of the texture map to be transparent.

]]></text></ref><ref name="POLYTYPE_ATEX_TRANS" syntax="#define POLYTYPE_ATEX_TRANS"/><ref name="POLYTYPE_PTEX_TRANS" syntax="#define POLYTYPE_PTEX_TRANS"><xreflist><xref>Polygon rendering</xref><xref>polygon3d</xref></xreflist><ereflist><eref>ex3d</eref></ereflist><shortdesc>Polygon rendering mode type</shortdesc><text><![CDATA[   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).

]]></text></ref><ref name="POLYTYPE_ATEX_MASK_TRANS" syntax="#define POLYTYPE_ATEX_MASK_TRANS"/><ref name="POLYTYPE_PTEX_MASK_TRANS" syntax="#define POLYTYPE_PTEX_MASK_TRANS"><xreflist><xref>Polygon rendering</xref><xref>polygon3d</xref></xreflist><ereflist><eref>ex3d</eref></ereflist><shortdesc>Polygon rendering mode type</shortdesc><text><![CDATA[   Like POLYTYPE_ATEX_TRANS and POLYTYPE_PTEX_TRANS, but zero texture map
   pixels are skipped.

]]></text></ref><ref name="polygon3d" syntax="void polygon3d(BITMAP *bmp, int type, BITMAP *texture, int vc, V3D *vtx[]);"/><ref name="polygon3d_f" syntax="void polygon3d_f(BITMAP *bmp, int type, BITMAP *texture, int vc, V3D_f *vtx[]);"><xreflist><xref>triangle3d</xref><xref>quad3d</xref><xref>polygon</xref><xref>clip3d</xref><xref>cpu_capabilities</xref></xreflist><ereflist><eref>excamera</eref></ereflist><shortdesc>Draws a 3d polygon onto the specified bitmap.</shortdesc><text><![CDATA[   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:
<pre class="code">
      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;
</pre>
   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.

]]></text></ref><ref name="triangle3d" syntax="void triangle3d(BITMAP *bmp, int type, BITMAP *tex, V3D *v1, *v2, *v3);"/><ref name="triangle3d_f" syntax="void triangle3d_f(BITMAP *bmp, int type, BITMAP *tex, V3D_f *v1, *v2, *v3);"><xreflist><xref>polygon3d</xref><xref>quad3d</xref><xref>triangle</xref><xref>Polygon rendering</xref></xreflist><shortdesc>Draws a 3d triangle onto the specified bitmap.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="quad3d" syntax="void quad3d(BITMAP *bmp, int type, BITMAP *tex, V3D *v1, *v2, *v3, *v4);"/><ref name="quad3d_f" syntax="void quad3d_f(BITMAP *bmp, int type, BITMAP *tex, V3D_f *v1, *v2, *v3, *v4);"><xreflist><xref>polygon3d</xref><xref>triangle3d</xref><xref>Polygon rendering</xref></xreflist><ereflist><eref>ex3d</eref></ereflist><shortdesc>Draws a 3d quad onto the specified bitmap.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="clip3d_f" syntax="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[]);"><xreflist><xref>polygon3d</xref><xref>clip3d</xref></xreflist><ereflist><eref>excamera</eref><eref>exscn3d</eref></ereflist><shortdesc>Clips the polygon given in vtx using floating point math,</shortdesc><text><![CDATA[   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&lt;x&lt;z, -z&lt;y&lt;z,
   0&lt;min_z&lt;z&lt;max_z. If  max_z&lt;=min_z, the z&lt;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.
]]></text><retval><text><![CDATA[   Returns the number of vertices after clipping is done.

]]></text></retval></ref><ref name="clip3d" syntax="int clip3d(int type, fixed min_z, fixed max_z, int vc, const V3D *vtx[], V3D *vout[], V3D *vtmp[], int out[]);"><xreflist><xref>polygon3d</xref><xref>clip3d_f</xref></xreflist><shortdesc>Clips the polygon given in vtx using fixed point math.</shortdesc><text><![CDATA[   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.
]]></text><retval><text><![CDATA[   Returns the number of vertices after clipping is done.

]]></text></retval></ref></reflist><section title="Zbuffered rendering"><text><![CDATA[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:
<pre class="code">
   polygon3d(bmp, POLYTYPE_ATEX | POLYTYPE_ZBUF, tex, vc, vtx);</pre>

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:
<ul><li>
Unlike the normal POLYTYPE_FLAT renderers, the Z-buffered ones don't use
the hline() routine. Therefore DRAW_MODE has no effect.
<li>
The *LIT* routines work the traditional way - through the set of
blender routines.
<li>
All the Z-buffered routines are much slower than their normal counterparts
(they all use the FPU to interpolate and test 1/z values).
</ul>
]]></text><reflist><ref name="create_zbuffer" syntax="ZBUFFER *create_zbuffer(BITMAP *bmp);"><xreflist><xref>create_sub_zbuffer</xref><xref>set_zbuffer</xref><xref>clear_zbuffer</xref><xref>destroy_zbuffer</xref></xreflist><ereflist><eref>exzbuf</eref></ereflist><shortdesc>Creates a Z-buffer for a bitmap.</shortdesc><text><![CDATA[   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.
]]></text><retval><text><![CDATA[   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.

]]></text></retval></ref><ref name="create_sub_zbuffer" syntax="ZBUFFER *create_sub_zbuffer(ZBUFFER *parent, int x, int y, int width, int height);"><xreflist><xref>create_zbuffer</xref><xref>create_sub_bitmap</xref><xref>destroy_zbuffer</xref></xreflist><shortdesc>Creates a sub-z-buffer.</shortdesc><text><![CDATA[   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.
]]></text><retval><text><![CDATA[   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.

]]></text></retval></ref><ref name="set_zbuffer" syntax="void set_zbuffer(ZBUFFER *zbuf);"><xreflist><xref>create_zbuffer</xref><xref>clear_zbuffer</xref><xref>destroy_zbuffer</xref></xreflist><ereflist><eref>exzbuf</eref></ereflist><shortdesc>Makes the given Z-buffer the active one.</shortdesc><text><![CDATA[   Makes the given Z-buffer be the active one. This should have been
   previously created with create_zbuffer().

]]></text></ref><ref name="clear_zbuffer" syntax="void clear_zbuffer(ZBUFFER *zbuf, float z);"><xreflist><xref>create_zbuffer</xref><xref>set_zbuffer</xref><xref>destroy_zbuffer</xref></xreflist><ereflist><eref>exzbuf</eref></ereflist><shortdesc>Writes a depth value into the given Z-buffer.</shortdesc><text><![CDATA[   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).

]]></text></ref><ref name="destroy_zbuffer" syntax="void destroy_zbuffer(ZBUFFER *zbuf);"><xreflist><xref>create_zbuffer</xref><xref>set_zbuffer</xref><xref>clear_zbuffer</xref></xreflist><ereflist><eref>exzbuf</eref></ereflist><shortdesc>Destroys a Z-buffer.</shortdesc><text><![CDATA[   Destroys the Z-buffer when you are finished with it. Use this to avoid
   memory leaks in your program.

]]></text></ref></reflist></section><section title="Scene rendering"><text><![CDATA[Allegro provides two simple approaches to remove hidden surfaces:
<ul><li>
   Z-buffering - (see above)
<li>
   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.
</ul>

The scene rendering has approximately the following steps:
<ul><li>
   Initialize the scene (set the clip area, clear the bitmap, blit a
   background, etc.)
<li>
   Call clear_scene().
<li>
   Transform all your points to camera space.
<li>
   Clip polygons.
<li>
   Project with persp_project() or persp_project_f().
<li>
   "Draw" polygons with scene_polygon3d() and/or scene_polygon3d_f().
   This doesn't do any actual drawing, only initializes tables.
<li>
   Render all the polygons defined previously to the bitmap with
   render_scene().
<li>
   Overlay some non-3D graphics.
<li>
   Show the bitmap (blit it to screen, flip the page, etc).
</ul>

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:
<ul><li>
   Unlike polygon3d(), scene_polygon3d() requires valid z coordinates
   for all vertices, regardless of rendering style (unlike
   polygon3d(), which only uses z coordinate for *PTEX*).
<li>
   All polygons passed to scene_polygon3d() have to be
   persp_project()'ed.
<li>
   After render_scene() the mode is reset to SOLID.
</ul>
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 algo.
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:
<pre class="code">
   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();</pre>

]]></text><reflist><ref name="create_scene" syntax="int create_scene(int nedge, int npoly);"><xreflist><xref>scene_polygon3d</xref><xref>render_scene</xref><xref>clear_scene</xref><xref>destroy_scene</xref><xref>scene_gap</xref><xref>create_zbuffer</xref></xreflist><ereflist><eref>exscn3d</eref></ereflist><shortdesc>Allocates memory for a 3d scene.</shortdesc><text><![CDATA[   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 succesive calls, the
   space will be reused (no new malloc()).

   The memory allocated is a little less than 150 * (nedge + npoly) bytes.
]]></text><retval><text><![CDATA[   Returns zero on success, or a negative number if allocations fail.

]]></text></retval></ref><ref name="clear_scene" syntax="void clear_scene(BITMAP *bmp);"><xreflist><xref>create_scene</xref><xref>scene_polygon3d</xref><xref>render_scene</xref><xref>destroy_scene</xref><xref>scene_gap</xref></xreflist><ereflist><eref>exscn3d</eref></ereflist><shortdesc>Initializes a scene.</shortdesc><text><![CDATA[   Initializes a scene. The bitmap is the bitmap you will eventually render
   on.

]]></text></ref><ref name="destroy_scene" syntax="void destroy_scene();"><xreflist><xref>create_scene</xref><xref>scene_polygon3d</xref><xref>clear_scene</xref><xref>render_scene</xref><xref>scene_gap</xref></xreflist><ereflist><eref>exscn3d</eref></ereflist><shortdesc>Deallocates the memory used by a scene.</shortdesc><text><![CDATA[   Deallocate memory previously allocated by create_scene. Use this to avoid
   memory leaks in your program.

]]></text></ref><ref name="scene_polygon3d" syntax="int scene_polygon3d(int type, BITMAP *texture, int vc, V3D *vtx[]);"/><ref name="scene_polygon3d_f" syntax="int scene_polygon3d_f(int type, BITMAP *texture, int vc, V3D_f *vtx[]);"><xreflist><xref>create_scene</xref><xref>clear_scene</xref><xref>render_scene</xref><xref>destroy_scene</xref><xref>polygon3d</xref><xref>cpu_capabilities</xref></xreflist><ereflist><eref>exscn3d</eref></ereflist><shortdesc>Puts a polygon in the scene rendering list.</shortdesc><text><![CDATA[   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() funtion,
   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.
]]></text><retval><text><![CDATA[   Returns zero on success, or a negative number if it won't be rendered for
   lack of a rendering routine.

]]></text></retval></ref><ref name="render_scene" syntax="void render_scene();"><xreflist><xref>create_scene</xref><xref>clear_scene</xref><xref>destroy_scene</xref><xref>scene_gap</xref><xref>scene_polygon3d</xref></xreflist><ereflist><eref>exscn3d</eref></ereflist><shortdesc>Renders all the queued scene polygons.</shortdesc><text><![CDATA[   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().

]]></text></ref><ref name="scene_gap" syntax="extern float scene_gap;"><xreflist><xref>create_scene</xref><xref>clear_scene</xref><xref>destroy_scene</xref><xref>render_scene</xref><xref>scene_polygon3d</xref></xreflist><shortdesc>Number controlling the scene z-sorting algorithm behaviour.</shortdesc><text><![CDATA[   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.



]]></text></ref></reflist></section></section><section title="Transparency and patterned drawing"><reflist><ref name="drawing_mode" syntax="void drawing_mode(int mode, BITMAP *pattern, int x_anchor, int y_anchor);"><xreflist><xref>xor_mode</xref><xref>solid_mode</xref><xref>color_map</xref><xref>set_trans_blender</xref></xreflist><ereflist><eref>exalpha</eref><eref>excolmap</eref><eref>exjoy</eref><eref>expat</eref><eref>extrans</eref></ereflist><shortdesc>Sets the graphics drawing mode.</shortdesc><text><![CDATA[   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:
<pre class="text">
      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
</pre>
   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.

]]></text></ref><ref name="xor_mode" syntax="void xor_mode(int on);"><xreflist><xref>drawing_mode</xref></xreflist><ereflist><eref>exspline</eref><eref>exupdate</eref></ereflist><shortdesc>Shortcut for toggling xor drawing mode on and off.</shortdesc><text><![CDATA[   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).

]]></text></ref><ref name="solid_mode" syntax="void solid_mode();"><xreflist><xref>drawing_mode</xref></xreflist><ereflist><eref>exalpha</eref><eref>expat</eref></ereflist><shortdesc>Shortcut for selecting solid drawing mode.</shortdesc><text><![CDATA[   This is a shortcut for selecting solid drawing mode. It is equivalent to
   calling drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0).

]]></text></ref></reflist><section title="256-color transparency"><text><![CDATA[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.

]]></text><reflist><ref name="color_map" syntax="extern COLOR_MAP *color_map;"><xreflist><xref>create_color_table</xref><xref>create_light_table</xref><xref>create_trans_table</xref><xref>create_blender_table</xref><xref>set_trans_blender</xref><xref>draw_trans_sprite</xref><xref>draw_lit_sprite</xref><xref>draw_gouraud_sprite</xref><xref>drawing_mode</xref></xreflist><ereflist><eref>ex3d</eref><eref>excolmap</eref><eref>exlights</eref><eref>exshade</eref><eref>extrans</eref></ereflist><shortdesc>Global pointer to the color mapping table.</shortdesc><text><![CDATA[   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:
<pre class="code">
      color_map = malloc(sizeof(COLOR_MAP));
      if (!color_map)
	 abort_on_error("Not enough memory for color map!");</pre>

]]></text></ref><ref name="create_trans_table" syntax="void create_trans_table(COLOR_MAP *table, const PALETTE pal, int r, g, b, void (*callback)(int pos));"><xreflist><xref>color_map</xref><xref>create_light_table</xref><xref>create_color_table</xref><xref>create_blender_table</xref><xref>draw_trans_sprite</xref><xref>draw_lit_sprite</xref><xref>draw_gouraud_sprite</xref><xref>rgb_map</xref></xreflist><ereflist><eref>ex3d</eref><eref>extrans</eref></ereflist><shortdesc>Fills a color mapping table for translucency effects.</shortdesc><text><![CDATA[   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:
<pre class="code">
      COLOR_MAP trans_table;
      ...
      /* Build a color lookup table for translucent drawing. */
      create_trans_table(&amp;trans_table, pal, 128, 128, 128, NULL);</pre>

]]></text></ref><ref name="create_light_table" syntax="void create_light_table(COLOR_MAP *table, const PALETTE pal, int r, g, b, void (*callback)(int pos));"><xreflist><xref>color_map</xref><xref>create_trans_table</xref><xref>create_color_table</xref><xref>create_blender_table</xref><xref>draw_trans_sprite</xref><xref>draw_lit_sprite</xref><xref>draw_gouraud_sprite</xref><xref>rgb_map</xref></xreflist><ereflist><eref>ex3d</eref><eref>exshade</eref><eref>extrans</eref></ereflist><shortdesc>Fills a color mapping table for lighting effects.</shortdesc><text><![CDATA[   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:
<pre class="code">
      COLOR_MAP light_table;
      ...
      /* Build a color lookup table for lighting effects. */
      create_light_table(&amp;light_table, pal, 0, 0, 0, NULL);</pre>

]]></text></ref><ref name="create_color_table" syntax="void create_color_table(COLOR_MAP *table, const PALETTE pal, void (*blend)(PALETTE pal, int x, int y, RGB *rgb), void (*callback)(int pos));"><xreflist><xref>color_map</xref><xref>create_light_table</xref><xref>create_trans_table</xref><xref>create_blender_table</xref><xref>draw_trans_sprite</xref><xref>draw_lit_sprite</xref><xref>draw_gouraud_sprite</xref><xref>rgb_map</xref></xreflist><ereflist><eref>excolmap</eref></ereflist><shortdesc>Fills a color mapping table for customised effects.</shortdesc><text><![CDATA[   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:
<pre class="code">
      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(&amp;greyscale_table, pal,
			    return_grey_color, NULL);</pre>

]]></text></ref><ref name="create_blender_table" syntax="void create_blender_table(COLOR_MAP *table, const PALETTE pal, void (*callback)(int pos));"><xreflist><xref>color_map</xref><xref>create_light_table</xref><xref>create_trans_table</xref><xref>create_color_table</xref><xref>draw_trans_sprite</xref><xref>draw_lit_sprite</xref><xref>draw_gouraud_sprite</xref><xref>set_trans_blender</xref><xref>set_blender_mode</xref></xreflist><shortdesc>Emulates truecolor blender effects in palettised modes.</shortdesc><text><![CDATA[   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.

]]></text></ref></reflist></section><section title="Truecolor transparency"><text><![CDATA[In truecolor video modes, translucency and lighting are implemented by a
blender function of the form:
<pre class="code">
   unsigned long (*BLENDER_FUNC)(unsigned long x, y, n);</pre>

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

]]></text><reflist><ref name="set_trans_blender" syntax="void set_trans_blender(int r, int g, int b, int a);"><xreflist><xref>set_blender_mode</xref><xref>set_alpha_blender</xref><xref>set_write_alpha_blender</xref><xref>color_map</xref><xref>draw_trans_sprite</xref><xref>draw_lit_sprite</xref><xref>drawing_mode</xref><xref>set_add_blender</xref><xref>set_burn_blender</xref><xref>set_color_blender</xref><xref>set_difference_blender</xref><xref>set_dissolve_blender</xref><xref>set_dodge_blender</xref><xref>set_hue_blender</xref><xref>set_invert_blender</xref><xref>set_luminance_blender</xref><xref>set_multiply_blender</xref><xref>set_saturation_blender</xref><xref>set_screen_blender</xref></xreflist><ereflist><eref>ex3d</eref><eref>exblend</eref><eref>exshade</eref><eref>extrans</eref><eref>exxfade</eref></ereflist><shortdesc>Enables a truecolor blender.</shortdesc><text><![CDATA[   Enables a linear interpolator blender mode for combining translucent
   or lit truecolor pixels.

]]></text></ref><ref name="set_alpha_blender" syntax="void set_alpha_blender();"><xreflist><xref>set_trans_blender</xref><xref>draw_trans_sprite</xref><xref>draw_trans_rle_sprite</xref><xref>set_write_alpha_blender</xref></xreflist><ereflist><eref>exalpha</eref><eref>extrans</eref></ereflist><shortdesc>Enables a special alpha-channel blending mode.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="set_write_alpha_blender" syntax="void set_write_alpha_blender();"><xreflist><xref>set_alpha_blender</xref><xref>draw_trans_sprite</xref><xref>drawing_mode</xref></xreflist><ereflist><eref>exalpha</eref><eref>extrans</eref></ereflist><shortdesc>Enables the special alpha-channel editing mode.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="set_add_blender" syntax="void set_add_blender(int r, int g, int b, int a);"><xreflist><xref>set_trans_blender</xref><xref>drawing_mode</xref></xreflist><shortdesc>Enables an additive blender mode.</shortdesc><text><![CDATA[   Enables an additive blender mode for combining translucent or lit
   truecolor pixels.

]]></text></ref><ref name="set_burn_blender" syntax="void set_burn_blender(int r, int g, int b, int a);"><xreflist><xref>set_trans_blender</xref><xref>drawing_mode</xref></xreflist><shortdesc>Enables a burn blender mode.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="set_color_blender" syntax="void set_color_blender(int r, int g, int b, int a);"><xreflist><xref>set_trans_blender</xref><xref>drawing_mode</xref></xreflist><shortdesc>Enables a color blender mode.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="set_difference_blender" syntax="void set_difference_blender(int r, int g, int b, int a);"><xreflist><xref>set_trans_blender</xref><xref>drawing_mode</xref></xreflist><shortdesc>Enables a difference blender mode.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="set_dissolve_blender" syntax="void set_dissolve_blender(int r, int g, int b, int a);"><xreflist><xref>set_trans_blender</xref><xref>drawing_mode</xref></xreflist><shortdesc>Enables a dissolve blender mode.</shortdesc><text><![CDATA[   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 :).

]]></text></ref><ref name="set_dodge_blender" syntax="void set_dodge_blender(int r, int g, int b, int a);"><xreflist><xref>set_trans_blender</xref><xref>drawing_mode</xref></xreflist><shortdesc>Enables a dodge blender mode.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="set_hue_blender" syntax="void set_hue_blender(int r, int g, int b, int a);"><xreflist><xref>set_trans_blender</xref><xref>drawing_mode</xref></xreflist><shortdesc>Enables a hue blender mode.</shortdesc><text><![CDATA[   Enables a hue blender mode for combining translucent or lit truecolor
   pixels. This applies the hue of the source to the destination.

]]></text></ref><ref name="set_invert_blender" syntax="void set_invert_blender(int r, int g, int b, int a);"><xreflist><xref>set_trans_blender</xref><xref>drawing_mode</xref></xreflist><shortdesc>Enables an invert blender mode.</shortdesc><text><![CDATA[   Enables an invert blender mode for combining translucent or lit truecolor
   pixels. Blends the inverse (or negative) colour of the source with the
   destination.

]]></text></ref><ref name="set_luminance_blender" syntax="void set_luminance_blender(int r, int g, int b, int a);"><xreflist><xref>set_trans_blender</xref><xref>drawing_mode</xref></xreflist><shortdesc>Enables a luminance blender mode.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="set_multiply_blender" syntax="void set_multiply_blender(int r, int g, int b, int a);"><xreflist><xref>set_trans_blender</xref><xref>drawing_mode</xref></xreflist><ereflist><eref>exalpha</eref></ereflist><shortdesc>Enables a multiply blender mode.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="set_saturation_blender" syntax="void set_saturation_blender(int r, int g, int b, int a);"><xreflist><xref>set_trans_blender</xref><xref>drawing_mode</xref></xreflist><shortdesc>Enables a saturation blender mode.</shortdesc><text><![CDATA[   Enables a saturation blender mode for combining translucent or lit
   truecolor pixels. Applies the saturation of the source to the destination
   image.

]]></text></ref><ref name="set_screen_blender" syntax="void set_screen_blender(int r, int g, int b, int a);"><xreflist><xref>set_trans_blender</xref><xref>drawing_mode</xref></xreflist><shortdesc>Enables a screen blender mode.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="set_blender_mode" syntax="void set_blender_mode(BLENDER_FUNC b15, b16, b24, int r, g, b, a);"><xreflist><xref>set_blender_mode_ex</xref><xref>set_trans_blender</xref><xref>color_map</xref><xref>draw_trans_sprite</xref><xref>draw_lit_sprite</xref><xref>drawing_mode</xref></xreflist><shortdesc>Specifies a custom set of truecolor blender routines.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="set_blender_mode_ex" syntax="void set_blender_mode_ex(BLENDER_FUNC b15, b16, b24, b32, b15x, b16x, b24x, int r, g, b, a);"><xreflist><xref>set_blender_mode</xref><xref>set_alpha_blender</xref></xreflist><shortdesc>An even more complex version of set_blender_mode().</shortdesc><text><![CDATA[   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.



]]></text></ref></reflist></section></section><section title="Converting between color formats"><text><![CDATA[
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:
<ul><li>
   blit() and the rotation routines can copy between bitmaps of any format,
   converting the data as required.
<li>
   draw_sprite() can draw 256-color source images onto destinations of any
   format.
<li>
   draw_character_ex() _always_ uses a 256-color source bitmap, whatever the
   format of the destination.
<li>
   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.
<li>
   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.
</ul>
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).

]]></text><reflist><ref name="bestfit_color" syntax="int bestfit_color(const PALETTE pal, int r, int g, int b);"><xreflist><xref>makecol8</xref></xreflist><shortdesc>Finds a palette color fitting the requested RGB values.</shortdesc><text><![CDATA[   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.
]]></text><retval><text><![CDATA[   Returns the index of the palette for the closest match to the requested
   color.

]]></text></retval></ref><ref name="rgb_map" syntax="extern RGB_MAP *rgb_map;"><xreflist><xref>create_rgb_table</xref><xref>makecol8</xref><xref>create_trans_table</xref><xref>create_light_table</xref><xref>create_color_table</xref></xreflist><ereflist><eref>ex3d</eref><eref>excolmap</eref><eref>exrgbhsv</eref><eref>exshade</eref><eref>extrans</eref></ereflist><shortdesc>Look up table to speed up reducing RGB values to palette colors.</shortdesc><text><![CDATA[   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().

]]></text></ref><ref name="create_rgb_table" syntax="void create_rgb_table(RGB_MAP *table, const PALETTE pal, void (*callback)(int pos));"><xreflist><xref>rgb_map</xref></xreflist><ereflist><eref>ex3d</eref><eref>excolmap</eref><eref>exrgbhsv</eref><eref>exshade</eref><eref>extrans</eref></ereflist><shortdesc>Generates an RGB mapping table with lookup data for a palette.</shortdesc><text><![CDATA[   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:
<pre class="code">
      RGB_MAP rgb_table;

      create_rgb_table(&amp;rgb_table, palette, NULL);
      rgb_map = &amp;rgb_table;</pre>

]]></text></ref><ref name="hsv_to_rgb" syntax="void hsv_to_rgb(float h, float s, float v, int *r, int *g, int *b);"/><ref name="rgb_to_hsv" syntax="void rgb_to_hsv(int r, int g, int b, float *h, float *s, float *v);"><ereflist><eref>exlights</eref><eref>exrgbhsv</eref></ereflist><shortdesc>Converts color values between the HSV and RGB colorspaces.</shortdesc><text><![CDATA[   Convert color values between the HSV and RGB colorspaces. The RGB values
   range from 0 to 255, hue is from 0 to 360, and saturation and value are
   from 0 to 1. Example:
<pre class="code">
      int r, g, b;
      float hue, saturation, value;
      ...
      /* Convert a reddish color to HSV format. */
      rgb_to_hsv(255, 0, 128, &amp;hue, &amp;saturation, &amp;value);

      /* Now put our tin foil hat, and verify that. */
      hsv_to_rgb(hue, saturation, value, &amp;r, &amp;g, &amp;b);
      ASSERT(r == 255);
      ASSERT(g == 0);
      ASSERT(b == 128);</pre>



]]></text></ref></reflist></section><section title="Direct access to video memory"><text><![CDATA[
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:
<pre class="code">
   void memory_putpixel(BITMAP *bmp, int x, int y, int color)
   {
      bmp-&gt;line[y][x] = color;
   }
</pre>
For truecolor modes you need to cast the line pointer to the appropriate
type, for example:
<pre class="code">
   void memory_putpixel_15_or_16_bpp(BITMAP *bmp, int x, int y, int color)
   {
      ((short *)bmp-&gt;line[y])[x] = color;
   }

   void memory_putpixel_32(BITMAP *bmp, int x, int y, int color)
   {
      ((long *)bmp-&gt;line[y])[x] = color;
   }
</pre>
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:
<pre class="code">
   void linear_screen_putpixel(BITMAP *bmp, int x, int y, int color)
   {
      bmp_select(bmp);
      bmp_write8((unsigned long)bmp-&gt;line[y]+x, color);
   }
</pre>
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-&gt;line[line].

]]></text><reflist><ref name="bmp_write_line" syntax="unsigned long bmp_write_line(BITMAP *bmp, int line);"><ereflist><eref>exflame</eref><eref>exlights</eref></ereflist><shortdesc>Direct access bank switching line selection for writing.</shortdesc><text><![CDATA[   Selects the line of a bitmap that you are going to draw onto.
]]></text><retval><text><![CDATA[   Returns the address of the selected line for writing.

]]></text></retval></ref><ref name="bmp_read_line" syntax="unsigned long bmp_read_line(BITMAP *bmp, int line);"><ereflist><eref>exflame</eref></ereflist><shortdesc>Direct access bank switching line selection for reading.</shortdesc><text><![CDATA[   Selects the line of a bitmap that you are going to read from.
]]></text><retval><text><![CDATA[   Returns the address of the selected line for reading.

]]></text></retval></ref><ref name="bmp_unwrite_line" syntax="void bmp_unwrite_line(BITMAP *bmp);"><ereflist><eref>exflame</eref><eref>exlights</eref></ereflist><shortdesc>Direct access bank switching line release.</shortdesc><text><![CDATA[   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.

]]></text></ref></reflist><section title="More on banked direct memory access"><text><![CDATA[
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:
<pre class="code">
   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);
   }
</pre>
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:
<pre class="code">
   void modex_putpixel(BITMAP *b, int x, int y, int color)
   {
      outportw(0x3C4, (0x100&lt;&lt;(x&amp;3))|2);
      bmp_select(bmp);
      bmp_write8((unsigned long)bmp-&gt;line[y]+(x&gt;&gt;2), color);
   }</pre>

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:
<pre class="code">
   #include &lt;sys/nearptr.h&gt;

   unsigned char *screenmemory;
   unsigned long screen_base_addr;

   __djgpp_nearptr_enable();

   __dpmi_get_segment_base_address(screen-&gt;seg, &amp;screen_base_addr);

   screenmemory = (unsigned char *)(screen_base_addr +
				    screen-&gt;line[0] -
				    __djgpp_base_address);
</pre>
Then:
<pre class="code">
   void nearptr_putpixel(int x, int y, int color)
   {
      screenmemory[x + y*VIRTUAL_W] = color;
   }
</pre>


]]></text></section></section><section title="FLIC routines"><text><![CDATA[
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.

]]></text><reflist><ref name="play_fli" syntax="int play_fli(const char *filename, BITMAP *bmp, int loop, int (*callback)());"><xreflist><xref>play_memory_fli</xref><xref>install_timer</xref><xref>fli_frame</xref></xreflist><shortdesc>Plays a FLI or FLC animation from disk.</shortdesc><text><![CDATA[   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:
<pre class="code">
      /* 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!");</pre>
]]></text><retval><text><![CDATA[   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.

]]></text></retval></ref><ref name="play_memory_fli" syntax="int play_memory_fli(const void *fli_data, BITMAP *bmp, int loop, int (*callback)());"><xreflist><xref>play_fli</xref><xref>install_timer</xref><xref>fli_frame</xref></xreflist><shortdesc>Plays a FLI or FLC animation from memory.</shortdesc><text><![CDATA[   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 mallocing 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 cueing 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:
<pre class="code">
      int ret = play_memory_fli(anim_data, screen, 0, NULL);
      if (ret == FLI_ERROR)
	 abort_on_error("Corrupted animation data?");</pre>
]]></text><retval><text><![CDATA[   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.

]]></text></retval></ref><ref name="open_fli" syntax="int open_fli(const char *filename);"/><ref name="open_memory_fli" syntax="int open_memory_fli(const void *fli_data);"><xreflist><xref>close_fli</xref><xref>next_fli_frame</xref><xref>fli_bitmap</xref><xref>fli_palette</xref></xreflist><shortdesc>Makes a FLI file open and ready for playing.</shortdesc><text><![CDATA[   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:
<pre class="code">
      if (open_fli("intro.fli") == FLI_ERROR)
	 abort_on_error("Error playing intro");</pre>
]]></text><retval><text><![CDATA[   Returns FLI_OK on success, FLI_ERROR if something went wrong, like trying
   to open another FLI file without closing the previous one.

]]></text></retval></ref><ref name="close_fli" syntax="void close_fli();"><xreflist><xref>open_fli</xref></xreflist><shortdesc>Closes a FLI file previously opened.</shortdesc><text><![CDATA[   Closes an FLI file when you have finished reading from it. Remember to do
   this to avoid having memory leaks in your program.

]]></text></ref><ref name="next_fli_frame" syntax="int next_fli_frame(int loop);"><xreflist><xref>open_fli</xref><xref>fli_bitmap</xref><xref>fli_palette</xref><xref>fli_timer</xref><xref>fli_frame</xref></xreflist><shortdesc>Reads the next frame of the current animation file.</shortdesc><text><![CDATA[   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:
<pre class="code">
      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... */
      }</pre>
]]></text><retval><text><![CDATA[   Returns FLI_OK on success, FLI_ERROR or FLI_NOT_OPEN on error, and FLI_EOF
   on reaching the end of the file.

]]></text></retval></ref><ref name="fli_bitmap" syntax="extern BITMAP *fli_bitmap;"><xreflist><xref>next_fli_frame</xref><xref>fli_bmp_dirty_from</xref><xref>fli_palette</xref></xreflist><shortdesc>Contains the current frame of the animation.</shortdesc><text><![CDATA[   Contains the current frame of the FLI/FLC animation. If there is no open
   animation, its value will be NULL.

]]></text></ref><ref name="fli_palette" syntax="extern PALETTE fli_palette;"><xreflist><xref>next_fli_frame</xref><xref>fli_pal_dirty_from</xref><xref>fli_bitmap</xref></xreflist><shortdesc>Contains the current palette of the animation.</shortdesc><text><![CDATA[   Contains the current FLI palette.

]]></text></ref><ref name="fli_bmp_dirty_from" syntax="extern int fli_bmp_dirty_from;"/><ref name="fli_bmp_dirty_to" syntax="extern int fli_bmp_dirty_to;"><xreflist><xref>fli_bitmap</xref><xref>reset_fli_variables</xref></xreflist><shortdesc>Indicate which parts of the image have changed.</shortdesc><text><![CDATA[   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:
<pre class="code">
      if (fli_bmp_dirty_from &lt;= 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);</pre>

]]></text></ref><ref name="fli_pal_dirty_from" syntax="extern int fli_pal_dirty_from;"/><ref name="fli_pal_dirty_to" syntax="extern int fli_pal_dirty_to;"><xreflist><xref>fli_palette</xref><xref>reset_fli_variables</xref></xreflist><shortdesc>Indicate which parts of the palette have changed.</shortdesc><text><![CDATA[   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:
<pre class="code">
      if (fli_pal_dirty_from &lt;= fli_pal_dirty_to)
	 set_palette_range(fli_palette, fli_pal_dirty_from,
			   fli_pal_dirty_to, 1);</pre>

]]></text></ref><ref name="reset_fli_variables" syntax="void reset_fli_variables();"><xreflist><xref>fli_bmp_dirty_from</xref><xref>fli_pal_dirty_from</xref></xreflist><shortdesc>Resets the bitmap and palette dirty global variables.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="fli_frame" syntax="extern int fli_frame;"><xreflist><xref>play_fli</xref><xref>play_memory_fli</xref><xref>next_fli_frame</xref></xreflist><shortdesc>Stores the current frame number of the animation.</shortdesc><text><![CDATA[   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:
<pre class="code">
      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... */
      }</pre>

]]></text></ref><ref name="fli_timer" syntax="extern volatile int fli_timer;"><xreflist><xref>install_timer</xref><xref>next_fli_frame</xref></xreflist><shortdesc>Global variable for timing FLI playback.</shortdesc><text><![CDATA[   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:
<pre class="code">
      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 &lt;= 0)
	    rest(0);
      }</pre>



]]></text></ref></reflist></section><section title="Sound init routines"><text><![CDATA[
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
scenary) 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.

]]></text><reflist><ref name="detect_digi_driver" syntax="int detect_digi_driver(int driver_id);"><xreflist><xref>install_sound</xref><xref>reserve_voices</xref><xref>DIGI_*/DOS</xref><xref>DIGI_*/Windows</xref><xref>DIGI_*/Unix</xref><xref>DIGI_*/BeOS</xref><xref>DIGI_*/QNX</xref><xref>DIGI_*/MacOSX</xref></xreflist><shortdesc>Detects whether the specified digital sound device is available.</shortdesc><text><![CDATA[   Detects whether the specified digital sound device is available. This
   function must be called _before_ install_sound().
]]></text><retval><text><![CDATA[   Returns the maximum number of voices that the driver can provide, or zero
   if the hardware is not present.

]]></text></retval></ref><ref name="detect_midi_driver" syntax="int detect_midi_driver(int driver_id);"><xreflist><xref>install_sound</xref><xref>reserve_voices</xref><xref>MIDI_*/DOS</xref><xref>MIDI_*/Windows</xref><xref>MIDI_*/Unix</xref><xref>MIDI_*/BeOS</xref><xref>MIDI_*/QNX</xref><xref>MIDI_*/MacOSX</xref></xreflist><shortdesc>Detects whether the specified MIDI sound device is available.</shortdesc><text><![CDATA[   Detects whether the specified MIDI sound device is available. This function
   must be called _before_ install_sound().
]]></text><retval><text><![CDATA[   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.

]]></text></retval></ref><ref name="reserve_voices" syntax="void reserve_voices(int digi_voices, int midi_voices);"><xreflist><xref>set_volume_per_voice</xref><xref>install_sound</xref><xref>detect_digi_driver</xref><xref>detect_midi_driver</xref><xref>get_mixer_voices</xref></xreflist><shortdesc>Reserve a number of voices for the digital and MIDI drivers.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="set_volume_per_voice" syntax="void set_volume_per_voice(int scale);"><xreflist><xref>reserve_voices</xref><xref>set_volume</xref><xref>install_sound</xref><xref>detect_digi_driver</xref><xref>detect_midi_driver</xref></xreflist><shortdesc>Sets the volume of a voice.</shortdesc><text><![CDATA[   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:
<pre class="text">
     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)
</pre>
   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.

]]></text></ref><ref name="install_sound" syntax="int install_sound(int digi, int midi, const char *cfg_path);"><xreflist><xref>remove_sound</xref><xref>reserve_voices</xref><xref>detect_digi_driver</xref><xref>detect_midi_driver</xref><xref>set_volume</xref><xref>play_sample</xref><xref>Voice control</xref><xref>play_midi</xref><xref>play_audio_stream</xref><xref>install_sound_input</xref><xref>allegro_error</xref><xref>Standard config variables</xref><xref>set_mixer_quality</xref><xref>DIGI_*/DOS</xref><xref>DIGI_*/Windows</xref><xref>DIGI_*/Unix</xref><xref>DIGI_*/BeOS</xref><xref>DIGI_*/QNX</xref><xref>DIGI_*/MacOSX</xref><xref>MIDI_*/DOS</xref><xref>MIDI_*/Windows</xref><xref>MIDI_*/Unix</xref><xref>MIDI_*/BeOS</xref><xref>MIDI_*/QNX</xref><xref>MIDI_*/MacOSX</xref></xreflist><ereflist><eref>exmidi</eref><eref>exsample</eref><eref>exsprite</eref><eref>exstream</eref></ereflist><shortdesc>Initialises the sound module.</shortdesc><text><![CDATA[   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.
]]></text><retval><text><![CDATA[   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.

]]></text></retval></ref><ref name="remove_sound" syntax="void remove_sound();"><xreflist><xref>install_sound</xref><xref>allegro_exit</xref></xreflist><shortdesc>Cleans up after you are finished with the sound routines.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="set_volume" syntax="void set_volume(int digi_volume, int midi_volume);"><xreflist><xref>install_sound</xref><xref>set_hardware_volume</xref></xreflist><shortdesc>Alters the global sound output volume.</shortdesc><text><![CDATA[   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).

]]></text></ref><ref name="set_hardware_volume" syntax="void set_hardware_volume(int digi_volume, int midi_volume);"><xreflist><xref>install_sound</xref><xref>set_volume</xref></xreflist><shortdesc>Alters the hardware sound output volume.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="get_volume" syntax="void get_volume(int *digi_volume, int *midi_volume);"><xreflist><xref>set_volume</xref><xref>get_hardware_volume</xref></xreflist><shortdesc>Retrieves the global sound output volume.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="get_hardware_volume" syntax="void get_hardware_volume(int *digi_volume, int *midi_volume);"><xreflist><xref>set_hardware_volume</xref><xref>get_volume</xref></xreflist><shortdesc>Retrieves the hardware sound output volume.</shortdesc><text><![CDATA[   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.

]]></text></ref></reflist></section><section title="Mixer routines"><reflist><ref name="set_mixer_quality" syntax="void set_mixer_quality(int quality);"><xreflist><xref>get_mixer_quality</xref><xref>Standard config variables</xref></xreflist><shortdesc>Sets the resampling quality of the mixer.</shortdesc><text><![CDATA[   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().

]]></text></ref><ref name="get_mixer_quality" syntax="int get_mixer_quality(void);"><xreflist><xref>set_mixer_quality</xref><xref>Standard config variables</xref></xreflist><shortdesc>Returns the current mixing quality.</shortdesc><text><![CDATA[   Returns the current mixing quality, as specified by the `quality' config
   variable, or a previous call to set_mixer_quality().

]]></text></ref><ref name="get_mixer_frequency" syntax="int get_mixer_frequency(void);"><xreflist><xref>Standard config variables</xref></xreflist><shortdesc>Returns the mixer frequency, in Hz.</shortdesc><text><![CDATA[   Returns the mixer frequency, in Hz.

]]></text></ref><ref name="get_mixer_bits" syntax="int get_mixer_bits(void);"><xreflist><xref>Standard config variables</xref></xreflist><shortdesc>Returns the mixer bitdepth (8 or 16).</shortdesc><text><![CDATA[   Returns the mixer bitdepth (8 or 16).

]]></text></ref><ref name="get_mixer_channels" syntax="int get_mixer_channels(void);"><xreflist><xref>Standard config variables</xref></xreflist><shortdesc>Returns the number of output channels.</shortdesc><text><![CDATA[   Returns the number of output channels. 2 for stereo, 1 for mono, 0 if
   the mixer isn't active.

]]></text></ref><ref name="get_mixer_voices" syntax="int get_mixer_voices(void);"><xreflist><xref>reserve_voices</xref></xreflist><shortdesc>Returns the number of voices allocated to the mixer.</shortdesc><text><![CDATA[   Returns the number of voices allocated to the mixer.

]]></text></ref><ref name="get_mixer_buffer_length" syntax="int get_mixer_buffer_length(void);"><xreflist><xref>Standard config variables</xref></xreflist><shortdesc>Returns the number of samples per channel in the mixer buffer.</shortdesc><text><![CDATA[   Returns the number of samples per channel in the mixer buffer.



]]></text></ref></reflist></section><section title="Digital sample routines"><reflist><ref name="load_sample" syntax="SAMPLE *load_sample(const char *filename);"><xreflist><xref>destroy_sample</xref><xref>load_voc</xref><xref>load_wav</xref><xref>play_sample</xref><xref>save_sample</xref><xref>register_sample_file_type</xref><xref>Voice control</xref></xreflist><ereflist><eref>exsample</eref></ereflist><shortdesc>Loads a sample from a file.</shortdesc><text><![CDATA[   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:
<pre class="code">
      SAMPLE *sample = load_sample(user_input);
      if (!sample)
	 abort_on_error("Couldn't load sample!");</pre>
]]></text><retval><text><![CDATA[   Returns a pointer to the SAMPLE or NULL on error. Remember to free this
   sample later to avoid memory leaks.

]]></text></retval></ref><ref name="load_wav" syntax="SAMPLE *load_wav(const char *filename);"><xreflist><xref>load_sample</xref><xref>register_sample_file_type</xref></xreflist><shortdesc>Loads a sample from a RIFF WAV file.</shortdesc><text><![CDATA[   Loads a sample from a RIFF WAV file. Example:
<pre class="code">
      SAMPLE *sample = load_wav("scream.wav");
      if (!sample)
	 abort_on_error("Couldn't scare user!");</pre>
]]></text><retval><text><![CDATA[   Returns a pointer to the SAMPLE or NULL on error. Remember to free this
   sample later to avoid memory leaks.

]]></text></retval></ref><ref name="load_wav_pf" syntax="SAMPLE *load_wav_pf(PACKFILE *f);"><xreflist><xref>load_wav</xref></xreflist><shortdesc>Packfile version of load_wav.</shortdesc><text><![CDATA[   A version of load_wav() which reads from a packfile. Example:
<pre class="code">
      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");</pre>
]]></text><retval><text><![CDATA[   Returns a pointer to the SAMPLE or NULL on error. Remember to free this
   sample later to avoid memory leaks.

]]></text></retval></ref><ref name="load_voc" syntax="SAMPLE *load_voc(const char *filename);"><xreflist><xref>load_sample</xref><xref>register_sample_file_type</xref></xreflist><shortdesc>Loads a sample from a Creative Labs VOC file.</shortdesc><text><![CDATA[   Loads a sample from a Creative Labs VOC file. Example:
<pre class="code">
      SAMPLE *sample = load_wav("alarm.wav");
      if (!sample)
	 abort_on_error("Couldn't alert user!");</pre>
]]></text><retval><text><![CDATA[   Returns a pointer to the SAMPLE or NULL on error. Remember to free this
   sample later to avoid memory leaks.

]]></text></retval></ref><ref name="load_voc_pf" syntax="SAMPLE *load_voc_pf(PACKFILE *f);"><xreflist><xref>load_voc</xref></xreflist><shortdesc>Packfile version of load_voc.</shortdesc><text><![CDATA[   A version of load_voc() which reads from a packfile. Example:
<pre class="code">
      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");</pre>
]]></text><retval><text><![CDATA[   Returns a pointer to the SAMPLE or NULL on error. Remember to free this
   sample later to avoid memory leaks.

]]></text></retval></ref><ref name="save_sample" syntax="int save_sample(const char *filename, SAMPLE *spl);"><xreflist><xref>load_sample</xref><xref>register_sample_file_type</xref></xreflist><shortdesc>Writes a sample into a file.</shortdesc><text><![CDATA[   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:
<pre class="code">
      if (save_sample("sound.wav", sample) != 0)
	 abort_on_error("Couldn't save sample!");</pre>
]]></text><retval><text><![CDATA[   Returns zero on success, non-zero otherwise.

]]></text></retval></ref><ref name="create_sample" syntax="SAMPLE *create_sample(int bits, int stereo, int freq, int len);"><xreflist><xref>load_sample</xref><xref>destroy_sample</xref><xref>Structures and types defined by Allegro</xref></xreflist><shortdesc>Constructs a new sample structure of the specified type.</shortdesc><text><![CDATA[   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.
]]></text><retval><text><![CDATA[   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.

]]></text></retval></ref><ref name="destroy_sample" syntax="void destroy_sample(SAMPLE *spl);"><xreflist><xref>load_sample</xref></xreflist><ereflist><eref>exsample</eref></ereflist><shortdesc>Destroys a sample structure when you are done with it.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="lock_sample" syntax="void lock_sample(SAMPLE *spl);"><xreflist><xref>load_sample</xref><xref>create_sample</xref></xreflist><shortdesc>Locks all the memory used by a sample.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="register_sample_file_type" syntax="void register_sample_file_type(const char *ext, SAMPLE *(*load)(const char *filename), int (*save)(const char *filename, SAMPLE *spl));"><xreflist><xref>load_sample</xref><xref>save_sample</xref></xreflist><shortdesc>Registers custom loading/saving sample routines.</shortdesc><text><![CDATA[   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:
<pre class="code">
      SAMPLE *load_mp3(const char *filename)
      {
	 ...
      }

	 register_sample_file_type("mp3", load_mp3, NULL);</pre>

]]></text></ref><ref name="play_sample" syntax="int play_sample(const SAMPLE *spl, int vol, int pan, int freq, int loop);"><xreflist><xref>install_sound</xref><xref>load_sample</xref><xref>adjust_sample</xref><xref>stop_sample</xref><xref>Voice control</xref></xreflist><ereflist><eref>exsample</eref><eref>exsprite</eref></ereflist><shortdesc>Plays a sample.</shortdesc><text><![CDATA[   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:
<pre class="code">
      /* Scream from the left speaker, twice the freq. */
      int sound = play_sample(scream, 255, 0, 2000, 0);</pre>
]]></text><retval><text><![CDATA[   Returns the voice number that was allocated for the sample or negative if
   no voices were available.

]]></text></retval></ref><ref name="adjust_sample" syntax="void adjust_sample(const SAMPLE *spl, int vol, int pan, int freq, int loop);"><xreflist><xref>play_sample</xref></xreflist><ereflist><eref>exsample</eref></ereflist><shortdesc>Alters the parameters of a sample while it is playing.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="stop_sample" syntax="void stop_sample(const SAMPLE *spl);"><xreflist><xref>play_sample</xref></xreflist><shortdesc>Kills off a sample.</shortdesc><text><![CDATA[   Kills off a sample, 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.

]]></text></ref></reflist><section title="Voice control"><xreflist><xref>install_sound</xref><xref>allocate_voice</xref><xref>deallocate_voice</xref><xref>reallocate_voice</xref><xref>release_voice</xref><xref>voice_start</xref><xref>voice_set_priority</xref><xref>voice_check</xref><xref>voice_set_position</xref><xref>voice_set_playmode</xref><xref>voice_set_volume</xref><xref>voice_set_frequency</xref><xref>voice_set_pan</xref><xref>SAMPLE</xref></xreflist><text><![CDATA[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.

]]></text><reflist><ref name="allocate_voice" syntax="int allocate_voice(const SAMPLE *spl);"><xreflist><xref>Voice control</xref><xref>deallocate_voice</xref><xref>reallocate_voice</xref><xref>release_voice</xref><xref>load_sample</xref></xreflist><shortdesc>Allocates a soundcard voice for a sample.</shortdesc><text><![CDATA[   Allocates a soundcard 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.
]]></text><retval><text><![CDATA[   Returns the voice number, or -1 if no voices are available.

]]></text></retval></ref><ref name="deallocate_voice" syntax="void deallocate_voice(int voice);"><xreflist><xref>allocate_voice</xref><xref>voice_stop</xref></xreflist><shortdesc>Frees a soundcard voice.</shortdesc><text><![CDATA[   Frees a soundcard voice, stopping it from playing and releasing whatever
   resources it is using.

]]></text></ref><ref name="reallocate_voice" syntax="void reallocate_voice(int voice, const SAMPLE *spl);"><xreflist><xref>allocate_voice</xref><xref>deallocate_voice</xref><xref>load_sample</xref></xreflist><shortdesc>Switches the sample of an already-allocated voice.</shortdesc><text><![CDATA[   Switches an already-allocated voice to use a different sample. Calling
   reallocate_voice(voice, sample) is equivalent to:
<pre class="code">
      deallocate_voice(voice);
      voice = allocate_voice(sample);</pre>

]]></text></ref><ref name="release_voice" syntax="void release_voice(int voice);"><xreflist><xref>allocate_voice</xref><xref>deallocate_voice</xref></xreflist><shortdesc>Releases a soundcard voice.</shortdesc><text><![CDATA[   Releases a soundcard 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.

]]></text></ref><ref name="voice_start" syntax="void voice_start(int voice);"><xreflist><xref>Voice control</xref><xref>allocate_voice</xref><xref>voice_stop</xref><xref>release_voice</xref></xreflist><ereflist><eref>exstream</eref></ereflist><shortdesc>Activates a voice.</shortdesc><text><![CDATA[   Activates a voice, using whatever parameters have been set for it.

]]></text></ref><ref name="voice_stop" syntax="void voice_stop(int voice);"><xreflist><xref>voice_start</xref><xref>deallocate_voice</xref><xref>release_voice</xref></xreflist><ereflist><eref>exstream</eref></ereflist><shortdesc>Stops a voice.</shortdesc><text><![CDATA[   Stops a voice, storing the current position and state so that it may
   later be resumed by calling voice_start().

]]></text></ref><ref name="voice_set_priority" syntax="void voice_set_priority(int voice, int priority);"><xreflist><xref>Voice control</xref></xreflist><shortdesc>Sets the priority of a voice.</shortdesc><text><![CDATA[   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
   soundcard driver can handle.

]]></text></ref><ref name="voice_check" syntax="SAMPLE *voice_check(int voice);"><xreflist><xref>allocate_voice</xref><xref>voice_start</xref><xref>voice_get_position</xref></xreflist><shortdesc>Checks whether a voice is currently allocated.</shortdesc><text><![CDATA[   Checks whether a voice is currently allocated.
]]></text><retval><text><![CDATA[   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).

]]></text></retval></ref><ref name="voice_get_position" syntax="int voice_get_position(int voice);"><xreflist><xref>Voice control</xref><xref>voice_set_position</xref></xreflist><shortdesc>Returns the current position of a voice.</shortdesc><text><![CDATA[   Returns the current position of a voice, in sample units, or -1 if it has
   finished playing.

]]></text></ref><ref name="voice_set_position" syntax="void voice_set_position(int voice, int position);"><xreflist><xref>Voice control</xref><xref>voice_get_position</xref><xref>voice_set_playmode</xref></xreflist><shortdesc>Sets the position of a voice.</shortdesc><text><![CDATA[   Sets the position of a voice, in sample units.

]]></text></ref><ref name="voice_set_playmode" syntax="void voice_set_playmode(int voice, int playmode);"><xreflist><xref>Voice control</xref></xreflist><shortdesc>Adjusts the loop status of the specified voice.</shortdesc><text><![CDATA[   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:
   <ul><li>
   PLAYMODE_PLAY<br>
      Plays the sample a single time. This is the default if you don't set
      the loop flag.
   <li>
   PLAYMODE_LOOP<br>
      Loops repeatedly through the sample, jumping back to the loop start
      position upon reaching the loop end.
   <li>
   PLAYMODE_FORWARD<br>
      Plays the sample from beginning to end. This is the default if you
      don't set the backward flag.
   <li>
   PLAYMODE_BACKWARD<br>
      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).
   <li>
   PLAYMODE_BIDIR<br>
      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.
   </ul>
]]></text></ref><ref name="voice_get_volume" syntax="int voice_get_volume(int voice);"><xreflist><xref>Voice control</xref><xref>voice_set_volume</xref></xreflist><shortdesc>Returns the current volume of the voice.</shortdesc><text><![CDATA[   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).

]]></text></ref><ref name="voice_set_volume" syntax="void voice_set_volume(int voice, int volume);"><xreflist><xref>Voice control</xref><xref>voice_get_volume</xref><xref>voice_ramp_volume</xref></xreflist><shortdesc>Sets the volume of the voice.</shortdesc><text><![CDATA[   Sets the volume of the voice, range 0-255.

]]></text></ref><ref name="voice_ramp_volume" syntax="void voice_ramp_volume(int voice, int time, int endvol);"><xreflist><xref>Voice control</xref><xref>voice_set_volume</xref></xreflist><shortdesc>Starts a volume ramp for a voice.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="voice_stop_volumeramp" syntax="void voice_stop_volumeramp(int voice);"><xreflist><xref>voice_ramp_volume</xref></xreflist><shortdesc>Interrupts a volume ramp operation.</shortdesc><text><![CDATA[   Interrupts a volume ramp operation.

]]></text></ref><ref name="voice_get_frequency" syntax="int voice_get_frequency(int voice);"><xreflist><xref>Voice control</xref><xref>voice_set_frequency</xref></xreflist><shortdesc>Returns the current pitch of the voice.</shortdesc><text><![CDATA[   Returns the current pitch of the voice, in Hz.

]]></text></ref><ref name="voice_set_frequency" syntax="void voice_set_frequency(int voice, int frequency);"><xreflist><xref>Voice control</xref><xref>voice_get_frequency</xref><xref>voice_sweep_frequency</xref></xreflist><shortdesc>Sets the pitch of the voice.</shortdesc><text><![CDATA[   Sets the pitch of the voice, in Hz.

]]></text></ref><ref name="voice_sweep_frequency" syntax="void voice_sweep_frequency(int voice, int time, int endfreq);"><xreflist><xref>Voice control</xref><xref>voice_set_frequency</xref></xreflist><shortdesc>Starts a frequency sweep for a voice.</shortdesc><text><![CDATA[   Starts a frequency sweep (glissando) from the current pitch to the
   specified ending pitch, lasting for time milliseconds.

]]></text></ref><ref name="voice_stop_frequency_sweep" syntax="void voice_stop_frequency_sweep(int voice);"><xreflist><xref>voice_sweep_frequency</xref></xreflist><shortdesc>Interrupts a frequency sweep operation.</shortdesc><text><![CDATA[   Interrupts a frequency sweep operation.

]]></text></ref><ref name="voice_get_pan" syntax="int voice_get_pan(int voice);"><xreflist><xref>Voice control</xref><xref>voice_set_pan</xref></xreflist><shortdesc>Returns the current pan position.</shortdesc><text><![CDATA[   Returns the current pan position, from 0 (left) to 255 (right).

]]></text></ref><ref name="voice_set_pan" syntax="void voice_set_pan(int voice, int pan);"><xreflist><xref>Voice control</xref><xref>voice_get_pan</xref><xref>voice_sweep_pan</xref></xreflist><shortdesc>Sets the pan position.</shortdesc><text><![CDATA[   Sets the pan position, ranging from 0 (left) to 255 (right).

]]></text></ref><ref name="voice_sweep_pan" syntax="void voice_sweep_pan(int voice, int time, int endpan);"><xreflist><xref>Voice control</xref><xref>voice_set_pan</xref></xreflist><shortdesc>Starts a pan sweep for a voice.</shortdesc><text><![CDATA[   Starts a pan sweep (left &lt;-&gt; right movement) from the current position to
   the specified ending position, lasting for time milliseconds.

]]></text></ref><ref name="voice_stop_pan_sweep" syntax="void voice_stop_pan_sweep(int voice);"><xreflist><xref>voice_sweep_pan</xref></xreflist><shortdesc>Interrupts a pan sweep operation.</shortdesc><text><![CDATA[   Interrupts a pan sweep operation.

]]></text></ref><ref name="voice_set_echo" syntax="void voice_set_echo(int voice, int strength, int delay);"><xreflist><xref>Voice control</xref></xreflist><shortdesc>Sets the echo parameters for a voice.</shortdesc><text><![CDATA[   Sets the echo parameters for a voice (not currently implemented).

]]></text></ref><ref name="voice_set_tremolo" syntax="void voice_set_tremolo(int voice, int rate, int depth);"><xreflist><xref>Voice control</xref></xreflist><shortdesc>Sets the tremolo parameters for a voice.</shortdesc><text><![CDATA[   Sets the tremolo parameters for a voice (not currently implemented).

]]></text></ref><ref name="voice_set_vibrato" syntax="void voice_set_vibrato(int voice, int rate, int depth);"><xreflist><xref>Voice control</xref></xreflist><shortdesc>Sets the vibrato parameters for a voice.</shortdesc><text><![CDATA[   Sets the vibrato parameters for a voice (not currently implemented).



]]></text></ref></reflist></section></section><section title="Music routines (MIDI)"><text><![CDATA[
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 soundcard of the end user to play the
notes, and soundcards 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. Soundcards 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 soundcard, which
might be more critical for the end user experience than the background music.
At the Allegro homepage (<a href="http://alleg.sourceforge.net/">http://alleg.sourceforge.net/</a>) you can find more
information about DIGMID and where to download digital samples for your MIDI
files.

]]></text><reflist><ref name="load_midi" syntax="MIDI *load_midi(const char *filename);"><xreflist><xref>destroy_midi</xref><xref>play_midi</xref><xref>get_midi_length</xref></xreflist><ereflist><eref>exmidi</eref></ereflist><shortdesc>Loads a MIDI file.</shortdesc><text><![CDATA[   Loads a MIDI file (handles both format 0 and format 1). Example:
<pre class="code">
      MIDI *music;
      music = load_midi("backmus.mid");
      if (!music)
	 abort_on_error("Couldn't load background music!");</pre>
]]></text><retval><text><![CDATA[   Returns a pointer to a MIDI structure, or NULL on error. Remember to free
   this MIDI file later to avoid memory leaks.

]]></text></retval></ref><ref name="destroy_midi" syntax="void destroy_midi(MIDI *midi);"><xreflist><xref>load_midi</xref></xreflist><ereflist><eref>exmidi</eref></ereflist><shortdesc>Destroys a MIDI structure when you are done with it.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="lock_midi" syntax="void lock_midi(MIDI *midi);"><xreflist><xref>load_midi</xref></xreflist><shortdesc>Locks all the memory used by a MIDI file.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="play_midi" syntax="int play_midi(MIDI *midi, int loop);"><xreflist><xref>install_sound</xref><xref>load_midi</xref><xref>play_looped_midi</xref><xref>stop_midi</xref><xref>midi_pause</xref><xref>midi_seek</xref><xref>midi_pos</xref><xref>midi_time</xref><xref>midi_msg_callback</xref></xreflist><ereflist><eref>exmidi</eref></ereflist><shortdesc>Starts playing the specified MIDI file.</shortdesc><text><![CDATA[   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.
]]></text><retval><text><![CDATA[   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 :-)

]]></text></retval></ref><ref name="play_looped_midi" syntax="int play_looped_midi(MIDI *midi, int loop_start, int loop_end);"><xreflist><xref>play_midi</xref><xref>midi_pos</xref><xref>midi_loop_start</xref></xreflist><shortdesc>Starts playing a MIDI file with a user-defined loop position.</shortdesc><text><![CDATA[   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.
]]></text><retval><text><![CDATA[   The return value has the same meaning as that of play_midi(): non-zero if
   an error occurs, zero otherwise.

]]></text></retval></ref><ref name="stop_midi" syntax="void stop_midi();"><xreflist><xref>play_midi</xref><xref>midi_pause</xref></xreflist><shortdesc>Stops whatever music is currently playing.</shortdesc><text><![CDATA[   Stops whatever music is currently playing. This is the same thing as
   calling play_midi(NULL, FALSE).

]]></text></ref><ref name="midi_pause" syntax="void midi_pause();"><xreflist><xref>play_midi</xref><xref>stop_midi</xref><xref>midi_resume</xref><xref>midi_seek</xref></xreflist><ereflist><eref>exmidi</eref></ereflist><shortdesc>Pauses the MIDI player.</shortdesc><text><![CDATA[   Pauses the MIDI player.

]]></text></ref><ref name="midi_resume" syntax="void midi_resume();"><xreflist><xref>midi_pause</xref></xreflist><ereflist><eref>exmidi</eref></ereflist><shortdesc>Resumes playback of a paused MIDI file.</shortdesc><text><![CDATA[   Resumes playback of a paused MIDI file.

]]></text></ref><ref name="midi_seek" syntax="int midi_seek(int target);"><xreflist><xref>play_midi</xref><xref>midi_pos</xref></xreflist><shortdesc>Seeks to the given midi_pos in the current MIDI file.</shortdesc><text><![CDATA[   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.
]]></text><retval><text><![CDATA[   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.

]]></text></retval></ref><ref name="get_midi_length" syntax="int get_midi_length(MIDI *midi);"><xreflist><xref>load_midi</xref><xref>midi_time</xref><xref>midi_pos</xref></xreflist><ereflist><eref>exmidi</eref></ereflist><shortdesc>Determines the total playing time of a midi, in seconds.</shortdesc><text><![CDATA[   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:
<pre class="code">
      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 &lt;= length);</pre>
]]></text><retval><text><![CDATA[   Returns the value of midi_time, the length of the midi.

]]></text></retval></ref><ref name="midi_out" syntax="void midi_out(unsigned char *data, int length);"><xreflist><xref>install_sound</xref><xref>load_midi_patches</xref><xref>midi_recorder</xref></xreflist><shortdesc>Streams a block of MIDI commands into the player.</shortdesc><text><![CDATA[   Streams a block of MIDI commands into the player in realtime, allowing
   you to trigger notes, jingles, etc, over the top of whatever MIDI file is
   currently playing.

]]></text></ref><ref name="load_midi_patches" syntax="int load_midi_patches();"><xreflist><xref>install_sound</xref><xref>midi_out</xref></xreflist><shortdesc>Forces the MIDI driver to load a set of patches.</shortdesc><text><![CDATA[   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.
]]></text><retval><text><![CDATA[   Returns non-zero if an error occurred.

]]></text></retval></ref><ref name="midi_pos" syntax="extern volatile long midi_pos;"><xreflist><xref>play_midi</xref><xref>midi_msg_callback</xref></xreflist><ereflist><eref>exmidi</eref></ereflist><shortdesc>Stores the current position in the MIDI file.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="midi_time" syntax="extern volatile long midi_time;"><xreflist><xref>play_midi</xref><xref>midi_pos</xref><xref>get_midi_length</xref></xreflist><ereflist><eref>exmidi</eref></ereflist><shortdesc>The current position in the MIDI file, in seconds.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="midi_loop_start" syntax="extern long midi_loop_start;"/><ref name="midi_loop_end" syntax="extern long midi_loop_end;"><xreflist><xref>play_looped_midi</xref></xreflist><shortdesc>Loop start and end points, set by play_looped_midi().</shortdesc><text><![CDATA[   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 &lt; 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.

]]></text></ref><ref name="midi_msg_callback" syntax="extern void (*midi_msg_callback)(int msg, int byte1, int byte2);"/><ref name="midi_meta_callback" syntax="extern void (*midi_meta_callback)(int type, const unsigned char *data, int length);"/><ref name="midi_sysex_callback" syntax="extern void (*midi_sysex_callback)(const unsigned char *data, int length);"><xreflist><xref>play_midi</xref></xreflist><shortdesc>Hook functions allowing you to intercept MIDI player events.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="load_ibk" syntax="int load_ibk(char *filename, int drums);"><xreflist><xref>install_sound</xref></xreflist><shortdesc>Reads in a .IBK patch definition file for the Adlib driver.</shortdesc><text><![CDATA[   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!
]]></text><retval><text><![CDATA[   Returns non-zero on error.



]]></text></retval></ref></reflist></section><section title="Audio stream routines"><text><![CDATA[
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.

]]></text><reflist><ref name="play_audio_stream" syntax="AUDIOSTREAM *play_audio_stream(int len, int bits, int stereo, int freq, int vol, int pan);"><xreflist><xref>install_sound</xref><xref>get_audio_stream_buffer</xref><xref>stop_audio_stream</xref><xref>AUDIOSTREAM</xref><xref>Voice control</xref></xreflist><ereflist><eref>exstream</eref></ereflist><shortdesc>Creates a new audio stream and starts playing it.</shortdesc><text><![CDATA[   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-&gt;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:
<pre class="code">
      bytes = length * (bits / 8) * (stereo ? 2 : 1)</pre>
   Example:
<pre class="code">
      /* 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");</pre>
]]></text><retval><text><![CDATA[   This function returns a pointer to the audio stream or NULL if it could
   not be created.

]]></text></retval></ref><ref name="stop_audio_stream" syntax="void stop_audio_stream(AUDIOSTREAM *stream);"><xreflist><xref>play_audio_stream</xref></xreflist><ereflist><eref>exstream</eref></ereflist><shortdesc>Destroys an audio stream when it is no longer required.</shortdesc><text><![CDATA[   Destroys an audio stream when it is no longer required.

]]></text></ref><ref name="get_audio_stream_buffer" syntax="void *get_audio_stream_buffer(AUDIOSTREAM *stream);"><xreflist><xref>play_audio_stream</xref><xref>free_audio_stream_buffer</xref></xreflist><ereflist><eref>exstream</eref></ereflist><shortdesc>Tells you if you need to fill the audiostream or not.</shortdesc><text><![CDATA[   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:
<pre class="code">
      void *mem_chunk;
      ...
      while (TRUE) {
	 ...
         mem_chunk = get_audio_stream_buffer(buffer);
	 if (mem_chunk != NULL) {
	    /* Refill the stream buffer. */
	 }
      }</pre>
]]></text><retval><text><![CDATA[   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.

]]></text></retval></ref><ref name="free_audio_stream_buffer" syntax="void free_audio_stream_buffer(AUDIOSTREAM *stream);"><xreflist><xref>get_audio_stream_buffer</xref></xreflist><ereflist><eref>exstream</eref></ereflist><shortdesc>Tells the audio stream player new data can be played.</shortdesc><text><![CDATA[   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:
<pre class="code">
      mem_chunk = get_audio_stream_buffer(buffer);
      if (mem_chunk != NULL) {
	 /* Refill the stream buffer. */
	 ...
	 free_audio_stream_buffer(buffer);
      }</pre>



]]></text></ref></reflist></section><section title="Recording routines"><text><![CDATA[
Allegro provides routines to capture sound from the soundcard, 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 soundcard 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.

]]></text><reflist><ref name="install_sound_input" syntax="int install_sound_input(int digi, int midi);"><xreflist><xref>install_sound</xref><xref>start_sound_input</xref><xref>midi_recorder</xref><xref>Standard config variables</xref><xref>DIGI_*/DOS</xref><xref>DIGI_*/Windows</xref><xref>DIGI_*/Unix</xref><xref>DIGI_*/BeOS</xref><xref>DIGI_*/QNX</xref><xref>DIGI_*/MacOSX</xref><xref>MIDI_*/DOS</xref><xref>MIDI_*/Windows</xref><xref>MIDI_*/Unix</xref><xref>MIDI_*/BeOS</xref><xref>MIDI_*/QNX</xref><xref>MIDI_*/MacOSX</xref></xreflist><shortdesc>Initialises the sound recorder module.</shortdesc><text><![CDATA[   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.
]]></text><retval><text><![CDATA[   This function returns zero on success, and any other value if the machine
   or driver doesn't support sound recording.

]]></text></retval></ref><ref name="remove_sound_input" syntax="void remove_sound_input();"><xreflist><xref>install_sound_input</xref><xref>remove_sound</xref><xref>allegro_exit</xref></xreflist><shortdesc>Cleans up after you are finished with the sound input routines.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="get_sound_input_cap_bits" syntax="int get_sound_input_cap_bits();"><xreflist><xref>start_sound_input</xref><xref>get_sound_input_cap_parm</xref><xref>get_sound_input_cap_rate</xref><xref>get_sound_input_cap_stereo</xref></xreflist><shortdesc>Checks which audio input sample formats are supported.</shortdesc><text><![CDATA[   Checks which sample formats are supported by the current audio input
   driver, returning one of the bitfield values:
<pre class="text">
      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</pre>
   Example:
<pre class="code">
      cap = get_sound_input_cap_bits();
      if (cap == 0) {
	 /* Ugh, no audio input supported? */
      } else {
	 if (cap &amp; 8) {
	    /* We have eight bit audio input. */
	 }
	 if (cap &amp; 16) {
	    /* We have sixteen bit audio input. */
	 }
      }</pre>

]]></text></ref><ref name="get_sound_input_cap_stereo" syntax="int get_sound_input_cap_stereo();"><xreflist><xref>start_sound_input</xref><xref>get_sound_input_cap_parm</xref><xref>get_sound_input_cap_bits</xref><xref>get_sound_input_cap_rate</xref></xreflist><shortdesc>Tells if the input driver is capable of stereo recording.</shortdesc><text><![CDATA[   Checks whether the current audio input driver is capable of stereo
   recording.
]]></text><retval><text><![CDATA[   Returns non-zero if the driver is capable of stereo recording.

]]></text></retval></ref><ref name="get_sound_input_cap_rate" syntax="int get_sound_input_cap_rate(int bits, int stereo);"><xreflist><xref>start_sound_input</xref><xref>get_sound_input_cap_parm</xref><xref>get_sound_input_cap_bits</xref><xref>get_sound_input_cap_stereo</xref></xreflist><shortdesc>Returns the maximum sample frequency for recording.</shortdesc><text><![CDATA[   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:
<pre class="code">
      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. */
      }</pre>

]]></text></ref><ref name="get_sound_input_cap_parm" syntax="int get_sound_input_cap_parm(int rate, int bits, int stereo);"><xreflist><xref>start_sound_input</xref><xref>get_sound_input_cap_bits</xref><xref>get_sound_input_cap_rate</xref><xref>get_sound_input_cap_stereo</xref></xreflist><shortdesc>Detects if the specified recording parameters are supported.</shortdesc><text><![CDATA[   Checks whether the specified recording frequency, number of bits, and
   mono/stereo mode are supported (and how) by the current audio driver.
]]></text><retval><text><![CDATA[   The function returns one of the following possible values:
<pre class="text">
      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 soundcard).
      -n = Sampling rate not supported, but rate 'n'
	   would work instead.</pre>

]]></text></retval></ref><ref name="set_sound_input_source" syntax="int set_sound_input_source(int source);"><xreflist><xref>start_sound_input</xref></xreflist><shortdesc>Selects the audio input source.</shortdesc><text><![CDATA[   Selects the audio input source. The parameter should be one of the values:
<pre class="text">
      SOUND_INPUT_MIC
      SOUND_INPUT_LINE
      SOUND_INPUT_CD</pre>
]]></text><retval><text><![CDATA[   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).

]]></text></retval></ref><ref name="start_sound_input" syntax="int start_sound_input(int rate, int bits, int stereo);"><xreflist><xref>install_sound_input</xref><xref>read_sound_input</xref><xref>stop_sound_input</xref><xref>digi_recorder</xref><xref>set_sound_input_source</xref><xref>get_sound_input_cap_parm</xref><xref>get_sound_input_cap_bits</xref><xref>get_sound_input_cap_rate</xref><xref>get_sound_input_cap_stereo</xref></xreflist><shortdesc>Starts recording in the specified format.</shortdesc><text><![CDATA[   Starts recording in the specified format, suspending audio playback as
   necessary if the card is not full duplex.
]]></text><retval><text><![CDATA[   Returns the buffer size in bytes if successful, or zero on error.

]]></text></retval></ref><ref name="stop_sound_input" syntax="void stop_sound_input();"><xreflist><xref>start_sound_input</xref></xreflist><shortdesc>Stops audio recording.</shortdesc><text><![CDATA[   Stops audio recording, switching the card back into the normal playback
   mode.

]]></text></ref><ref name="read_sound_input" syntax="int read_sound_input(void *buffer);"><xreflist><xref>start_sound_input</xref></xreflist><shortdesc>Retrieves the last recorded audio buffer.</shortdesc><text><![CDATA[   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.
]]></text><retval><text><![CDATA[   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).

]]></text></retval></ref><ref name="digi_recorder" syntax="extern void (*digi_recorder)();"><xreflist><xref>install_sound_input</xref><xref>start_sound_input</xref></xreflist><shortdesc>Hook notifying you when a new sample buffer becomes available.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="midi_recorder" syntax="extern void (*midi_recorder)(unsigned char data);"><xreflist><xref>install_sound_input</xref><xref>midi_out</xref></xreflist><shortdesc>Hook notifying you when new MIDI data becomes available.</shortdesc><text><![CDATA[   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.



]]></text></ref></reflist></section><section title="File and compression routines"><text><![CDATA[
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:
<pre class="text">
      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</pre>
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 explictly <i>exclude</i> the flags that you
do <i>not</i> 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).

]]></text><reflist><ref name="get_executable_name" syntax="void get_executable_name(char *buf, int size);"><shortdesc>Obtains the full path to the current executable.</shortdesc><text><![CDATA[   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:
<pre class="code">
      char name[200];
      ...
      get_executable_name(name, sizeof(name));
      allegro_message("Running `%s'\n", name);</pre>

]]></text></ref><ref name="fix_filename_case" syntax="char *fix_filename_case(char *path);"><xreflist><xref>fix_filename_slashes</xref><xref>canonicalize_filename</xref></xreflist><shortdesc>Converts a filename to a standardised case.</shortdesc><text><![CDATA[   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:
<pre class="code">
      get_executable_name(name, sizeof(name));
      fix_filename_case(name);
      allegro_message("Running `%s'\n", name);</pre>
]]></text><retval><text><![CDATA[   Returns a copy of the `path' parameter.

]]></text></retval></ref><ref name="fix_filename_slashes" syntax="char *fix_filename_slashes(char *path);"><xreflist><xref>fix_filename_case</xref><xref>canonicalize_filename</xref></xreflist><shortdesc>Converts all the directory separators to a standard character.</shortdesc><text><![CDATA[   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:
<pre class="code">
      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. */</pre>
]]></text><retval><text><![CDATA[   Returns a copy of the `path' parameter.

]]></text></retval></ref><ref name="canonicalize_filename" syntax="char *canonicalize_filename(char *dest, const char *filename, int size);"><xreflist><xref>fix_filename_case</xref><xref>fix_filename_slashes</xref></xreflist><shortdesc>Converts any filename into its canonical form.</shortdesc><text><![CDATA[   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:
<pre class="code">
      char buf[256];
      ...
      canonicalize_filename(buf, "~/../s22/..\\t3st///hi.c",
			    sizeof(buf));
      /* Running this under Unix would
	 return: /home/t3st/hi.c */
</pre>
   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").
]]></text><retval><text><![CDATA[   Returns a copy of the `dest' parameter.

]]></text></retval></ref><ref name="make_absolute_filename" syntax="char *make_absolute_filename(char *dest, const char *path, const char *filename, int size);"><xreflist><xref>make_relative_filename</xref><xref>is_relative_filename</xref><xref>replace_filename</xref><xref>canonicalize_filename</xref></xreflist><shortdesc>Makes an absolute filename from a path and relative filename.</shortdesc><text><![CDATA[   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:
<pre class="code">
      char buf[256];
      ...
      make_absolute_filename(buf, "/usr/games/",
			     "../temp.txt", sizeof(buf));
      /* This would create /usr/temp.txt */</pre>
]]></text><retval><text><![CDATA[   Returns a copy of the `dest' parameter.

]]></text></retval></ref><ref name="make_relative_filename" syntax="char *make_relative_filename(char *dest, const char *path, const char *filename, int size);"><xreflist><xref>make_absolute_filename</xref><xref>is_relative_filename</xref><xref>canonicalize_filename</xref></xreflist><shortdesc>Tries to make a relative filename from absolute path and filename.</shortdesc><text><![CDATA[   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:
<pre class="code">
      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 */</pre>
]]></text><retval><text><![CDATA[   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:\").

]]></text></retval></ref><ref name="is_relative_filename" syntax="int is_relative_filename(const char *filename);"><xreflist><xref>make_absolute_filename</xref><xref>make_relative_filename</xref></xreflist><shortdesc>Returns TRUE if the filename is relative.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="replace_filename" syntax="char *replace_filename(char *dest, const char *path, const char *filename, int size);"><xreflist><xref>get_filename</xref><xref>replace_extension</xref><xref>append_filename</xref></xreflist><ereflist><eref>Available Allegro examples</eref></ereflist><shortdesc>Replaces path+filename with a new filename tail.</shortdesc><text><![CDATA[   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:
<pre class="code">
      char name[200];
      ...
      get_executable_name(name, sizeof(name));
      replace_filename(name, name, "sound.dat", sizeof(name));</pre>
]]></text><retval><text><![CDATA[   Returns a copy of the `dest' parameter.

]]></text></retval></ref><ref name="replace_extension" syntax="char *replace_extension(char *dest, const char *filename, const char *ext, int size);"><xreflist><xref>get_extension</xref><xref>replace_filename</xref></xreflist><shortdesc>Replaces filename+extension with a new extension tail.</shortdesc><text><![CDATA[   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:
<pre class="code">
      replace_extension(buf, "C:\\game\\prog.exe",
			"dat", sizeof(buf));</pre>
]]></text><retval><text><![CDATA[   Returns a copy of the `dest' parameter.

]]></text></retval></ref><ref name="append_filename" syntax="char *append_filename(char *dest, const char *path, const char *filename, int size);"><xreflist><xref>replace_filename</xref></xreflist><shortdesc>Concatenates a filename to a path.</shortdesc><text><![CDATA[   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:
<pre class="code">
      append_filename(buf, "/home/user",
		      "prog.bin", sizeof(buf));</pre>
]]></text><retval><text><![CDATA[   Returns a copy of the `dest' parameter.

]]></text></retval></ref><ref name="get_filename" syntax="char *get_filename(const char *path);"><xreflist><xref>get_extension</xref><xref>put_backslash</xref><xref>replace_filename</xref></xreflist><ereflist><eref>exmidi</eref></ereflist><shortdesc>Returns a pointer to the filename portion of a path.</shortdesc><text><![CDATA[   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:
<pre class="code">
      get_executable_name(name, sizeof(name));
      allegro_message("Running `%s'\n", get_filename(name));
</pre>
   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.
]]></text><retval><text><![CDATA[   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).

]]></text></retval></ref><ref name="get_extension" syntax="char *get_extension(const char *filename);"><xreflist><xref>get_filename</xref><xref>put_backslash</xref><xref>replace_extension</xref></xreflist><shortdesc>Returns a pointer to the extension of a filename.</shortdesc><text><![CDATA[   Finds out the extension of the filename (with or without path
   information). Example:
<pre class="code">
      get_executable_name(name, sizeof(name));
      allegro_message("The binary has the extension `%s'\n",
		      get_extension(name));</pre>
]]></text><retval><text><![CDATA[   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.

]]></text></retval></ref><ref name="put_backslash" syntax="void put_backslash(char *filename);"><xreflist><xref>get_extension</xref><xref>get_filename</xref></xreflist><shortdesc>Puts a path separator at the end of a path if needed.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="file_exists" syntax="int file_exists(const char *filename, int attrib, int *aret);"><xreflist><xref>exists</xref><xref>file_size_ex</xref><xref>file_time</xref></xreflist><shortdesc>Tells if a file exists.</shortdesc><text><![CDATA[   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:
<pre class="code">
      /* Check for a normal file. */
      if (file_exists("franken.dat", 0, NULL))
	 allegro_message("It is alive!\n");</pre>
]]></text><retval><text><![CDATA[   Returns non-zero if the file exists, or zero if it doesn't or the
   specified attributes mask it out.

]]></text></retval></ref><ref name="exists" syntax="int exists(const char *filename);"><xreflist><xref>file_exists</xref><xref>file_size_ex</xref><xref>file_time</xref></xreflist><shortdesc>Shortcut version of file_exists() for normal files.</shortdesc><text><![CDATA[   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.
]]></text><retval><text><![CDATA[   Returns non-zero if the file exists, or zero if it doesn't.

]]></text></retval></ref><ref name="file_size_ex" syntax="uint64_t file_size_ex(const char *filename);"><xreflist><xref>file_exists</xref><xref>file_time</xref></xreflist><ereflist><eref>expackf</eref></ereflist><shortdesc>Returns the size of a file in bytes.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="file_time" syntax="time_t file_time(const char *filename);"><xreflist><xref>file_exists</xref><xref>file_size_ex</xref></xreflist><shortdesc>Returns the modification time of a file.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="delete_file" syntax="int delete_file(const char *filename);"><shortdesc>Removes a file from the disk.</shortdesc><text><![CDATA[   Removes a file from the disk. You can't delete directories, though.
]]></text><retval><text><![CDATA[   Returns zero on success, non-zero on failure.

]]></text></retval></ref><ref name="for_each_file_ex" syntax="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);"><xreflist><xref>al_findfirst</xref><xref>al_findnext</xref><xref>al_findclose</xref></xreflist><shortdesc>Executes callback() for each file matching a wildcard.</shortdesc><text><![CDATA[   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:
<pre class="code">
      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);</pre>
]]></text><retval><text><![CDATA[   Returns the number of successful calls made to callback(), that is, the
   number of times callback() was called and returned 0.

]]></text></retval></ref><ref name="al_findfirst" syntax="int al_findfirst(const char *pattern, struct al_ffblk *info, int attrib);"><xreflist><xref>al_findnext</xref><xref>al_findclose</xref><xref>al_ffblk_get_size</xref></xreflist><shortdesc>Low-level function for searching files.</shortdesc><text><![CDATA[   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:
<pre class="code">
      struct al_ffblk
      {
	 int attrib;       - actual attributes of the file found
	 time_t time;      - modification time of file
	 char name[512];   - name of file
      };
</pre>
   There is some other stuff in the structure as well, but it is there for
   internal use only. Example:
<pre class="code">
      struct al_ffblk info;

      if (al_findfirst("*.pcx", &amp;info, FA_ALL) != 0) {
	 /* Tell user there are no PCX files. */
	 return;
      }</pre>
]]></text><retval><text><![CDATA[   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.

]]></text></retval></ref><ref name="al_findnext" syntax="int al_findnext(struct al_ffblk *info);"><xreflist><xref>al_findfirst</xref><xref>al_findclose</xref></xreflist><shortdesc>Finds the next file in a search started by al_findfirst().</shortdesc><text><![CDATA[   This finds the next file in a search started by al_findfirst(). Example:
<pre class="code">
      if (al_findfirst("*.pcx", &amp;info, 0) != 0)
	 return;

      do {
	 /* Do something useful here with info.name. */
      } while (al_findnext(&amp;info) == 0);

      al_findclose(&amp;info);</pre>
]]></text><retval><text><![CDATA[   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.

]]></text></retval></ref><ref name="al_findclose" syntax="void al_findclose(struct al_ffblk *info);"><xreflist><xref>al_findfirst</xref><xref>al_findnext</xref></xreflist><shortdesc>Closes a previously opened search with al_findfirst().</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="al_ffblk_get_size" syntax="uint64_t al_ffblk_get_size(struct al_ffblk *info);"><xreflist><xref>al_findfirst</xref><xref>al_findnext</xref><xref>al_ffblk</xref></xreflist><shortdesc>Get size of file returned by al_findfirst/al_findnext.</shortdesc><text><![CDATA[   This returns the size of the file returned by al_findfirst or al_findnext.

]]></text></ref><ref name="find_allegro_resource" syntax="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);"><xreflist><xref>set_allegro_resource_path</xref></xreflist><shortdesc>Searches for a support file in many places.</shortdesc><text><![CDATA[   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:
<pre class="code">
      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. */
      }</pre>
]]></text><retval><text><![CDATA[   Returns zero on success, and stores a full path to the file (at most size
   bytes) into the dest buffer.

]]></text></retval></ref><ref name="set_allegro_resource_path" syntax="int set_allegro_resource_path(int priority, const char *path);"><xreflist><xref>find_allegro_resource</xref></xreflist><shortdesc>Sets a specific resource search path.</shortdesc><text><![CDATA[   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:
<pre class="code">
      set_allegro_resource_path(10, "my_game/configs");
      set_allegro_resource_path(0, "users/configs/");
      set_allegro_resource_path(-45, "temp");
</pre>
   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.
]]></text><retval><text><![CDATA[   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.

]]></text></retval></ref><ref name="packfile_password" syntax="void packfile_password(const char *password);"><xreflist><xref>pack_fopen</xref><xref>load_datafile</xref><xref>pack_fopen_vtable</xref></xreflist><shortdesc>Sets the global I/O encryption password.</shortdesc><text><![CDATA[   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().

]]></text></ref><ref name="pack_fopen" syntax="PACKFILE *pack_fopen(const char *filename, const char *mode);"><xreflist><xref>pack_fclose</xref><xref>pack_fopen_chunk</xref><xref>packfile_password</xref><xref>pack_fread</xref><xref>pack_getc</xref><xref>file_select_ex</xref><xref>pack_fopen_vtable</xref></xreflist><ereflist><eref>expackf</eref></ereflist><shortdesc>Opens a file according to mode.</shortdesc><text><![CDATA[   Opens a file according to mode, which may contain any of the flags:
<ul><li>
      `r' - open file for reading.
<li>
      `w' - open file for writing, overwriting any existing data.
<li>
      `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.
<li>
      `!' - 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.
</ul>
   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:
<ul><li>
      `#' - read data that has been appended to your executable file with
      the exedat utility, as if it was a regular independent disk file.
<li>
      `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'.
<li>
      `#object_name' - combination of the above, reading an object from a
      datafile that has been appended onto your executable.
</ul>
   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:
<pre class="code">
      PACKFILE *input_file;

      input_file = pack_fopen("scores.dat", "rp");
      if (!input_file)
	 abort_on_error("Couldn't read `scores.dat'!");</pre>
]]></text><retval><text><![CDATA[   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.

]]></text></retval></ref><ref name="pack_fopen_vtable" syntax="PACKFILE *pack_fopen_vtable(const PACKFILE_VTABLE *vtable, void *userdata);"><xreflist><xref>pack_fopen</xref><xref>pack_fopen_chunk</xref><xref>packfile_password</xref></xreflist><ereflist><eref>expackf</eref></ereflist><text><![CDATA[   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().
]]></text><retval><text><![CDATA[   On success, it returns a pointer to a PACKFILE structure, and on error it
   returns NULL and stores an error code in `errno'.

]]></text></retval></ref><ref name="pack_fclose" syntax="int pack_fclose(PACKFILE *f);"><xreflist><xref>pack_fopen</xref><xref>pack_fopen_vtable</xref><xref>packfile_password</xref></xreflist><ereflist><eref>expackf</eref></ereflist><shortdesc>Closes a stream previously opened.</shortdesc><text><![CDATA[   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.
]]></text><retval><text><![CDATA[   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.

]]></text></retval></ref><ref name="pack_fseek" syntax="int pack_fseek(PACKFILE *f, int offset);"><xreflist><xref>pack_fopen</xref><xref>pack_fopen_chunk</xref></xreflist><ereflist><eref>expackf</eref></ereflist><shortdesc>Seeks inside a stream.</shortdesc><text><![CDATA[   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:
<pre class="code">
      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);</pre>
]]></text><retval><text><![CDATA[   Returns zero on success or a negative number on error, storing the error
   code in `errno'.

]]></text></retval></ref><ref name="pack_feof" syntax="int pack_feof(PACKFILE *f);"><xreflist><xref>pack_fopen</xref><xref>pack_fopen_chunk</xref><xref>pack_ferror</xref></xreflist><shortdesc>Returns nonzero as soon as you reach the end of the file.</shortdesc><text><![CDATA[   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).
]]></text><retval><text><![CDATA[   Returns non-zero if you are at the end of the file, zero otherwise.

]]></text></retval></ref><ref name="pack_ferror" syntax="int pack_ferror(PACKFILE *f);"><xreflist><xref>pack_fopen</xref><xref>pack_fopen_chunk</xref></xreflist><shortdesc>Tells if an error occurred during an operation on the stream.</shortdesc><text><![CDATA[   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.
]]></text><retval><text><![CDATA[   Returns nonzero if the error indicator for the stream is set, meaning
   that an error has occurred during a previous operation on the stream.

]]></text></retval></ref><ref name="pack_getc" syntax="int pack_getc(PACKFILE *f);"><xreflist><xref>pack_fopen</xref><xref>pack_fopen_chunk</xref></xreflist><shortdesc>Returns the next character from a stream.</shortdesc><text><![CDATA[   Returns the next character from the stream `f', or EOF if the end of the
   file has been reached.

]]></text></ref><ref name="pack_putc" syntax="int pack_putc(int c, PACKFILE *f);"><xreflist><xref>pack_fopen</xref><xref>pack_fopen_chunk</xref></xreflist><shortdesc>Puts a character in the stream.</shortdesc><text><![CDATA[   Puts a character in the stream f.
]]></text><retval><text><![CDATA[   Returns the character written on success, or EOF on error.

]]></text></retval></ref><ref name="pack_igetw" syntax="int pack_igetw(PACKFILE *f);"><xreflist><xref>pack_getc</xref></xreflist><shortdesc>Like pack_getc(), but using 16-bit Intel byte ordering words.</shortdesc><text><![CDATA[   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).

]]></text></ref><ref name="pack_iputw" syntax="int pack_iputw(int c, PACKFILE *f);"><xreflist><xref>pack_putc</xref></xreflist><shortdesc>Like pack_putc(), but using 16-bit Intel byte ordering words.</shortdesc><text><![CDATA[   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).

]]></text></ref><ref name="pack_igetl" syntax="long pack_igetl(PACKFILE *f);"><xreflist><xref>pack_getc</xref></xreflist><shortdesc>Like pack_getc(), but using 32-bit Intel byte ordering words.</shortdesc><text><![CDATA[   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).

]]></text></ref><ref name="pack_iputl" syntax="long pack_iputl(long c, PACKFILE *f);"><xreflist><xref>pack_putc</xref></xreflist><shortdesc>Like pack_putc(), but using 32-bit Intel byte ordering words.</shortdesc><text><![CDATA[   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).

]]></text></ref><ref name="pack_mgetw" syntax="int pack_mgetw(PACKFILE *f);"><xreflist><xref>pack_getc</xref></xreflist><shortdesc>Like pack_getc(), but using 16-bit Motorola byte ordering words.</shortdesc><text><![CDATA[   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).

]]></text></ref><ref name="pack_mputw" syntax="int pack_mputw(int c, PACKFILE *f);"><xreflist><xref>pack_putc</xref></xreflist><shortdesc>Like pack_putc(), but using 16-bit Motorola byte ordering words.</shortdesc><text><![CDATA[   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).

]]></text></ref><ref name="pack_mgetl" syntax="long pack_mgetl(PACKFILE *f);"><xreflist><xref>pack_getc</xref></xreflist><shortdesc>Like pack_getc(), but using 32-bit Motorola byte ordering words.</shortdesc><text><![CDATA[   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).

]]></text></ref><ref name="pack_mputl" syntax="long pack_mputl(long c, PACKFILE *f);"><xreflist><xref>pack_putc</xref></xreflist><shortdesc>Like pack_putc(), but using 32-bit Motorola byte ordering words.</shortdesc><text><![CDATA[   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).

]]></text></ref><ref name="pack_fread" syntax="long pack_fread(void *p, long n, PACKFILE *f);"><xreflist><xref>pack_fopen</xref><xref>pack_fopen_chunk</xref><xref>pack_feof</xref></xreflist><ereflist><eref>expackf</eref></ereflist><shortdesc>Reads n bytes from the stream.</shortdesc><text><![CDATA[   Reads `n' bytes from the stream `f', storing them at the memory location
   pointed to by `p'. Example:
<pre class="code">
      unsigned char buf[256];
      ...
      if (pack_fread(buf, 256, input_file) != 256)
	 abort_on_error("Truncated input file!");</pre>
]]></text><retval><text><![CDATA[   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.

]]></text></retval></ref><ref name="pack_fwrite" syntax="long pack_fwrite(const void *p, long n, PACKFILE *f);"><xreflist><xref>pack_fopen</xref><xref>pack_fopen_chunk</xref><xref>pack_feof</xref></xreflist><shortdesc>Writes n bytes to the stream.</shortdesc><text><![CDATA[   Writes `n' bytes to the stream `f' from memory location pointed to by `p'.
]]></text><retval><text><![CDATA[   Returns the number of bytes written, which will be less than n if an
   error occurs. Error codes are stored in errno.

]]></text></retval></ref><ref name="pack_fgets" syntax="char *pack_fgets(char *p, int max, PACKFILE *f);"><xreflist><xref>pack_fopen</xref><xref>pack_fopen_chunk</xref><xref>pack_fread</xref><xref>pack_getc</xref></xreflist><shortdesc>Reads a line from the stream.</shortdesc><text><![CDATA[   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. Example:
<pre class="code">
      char buf[256];
      ...
      while (pack_fgets(buf, sizeof(buf), input_file)) {
	 /* Process input line. */
      }
      fclose(input_file);</pre>
]]></text><retval><text><![CDATA[   Returns the pointer `p' on success, or NULL on error.

]]></text></retval></ref><ref name="pack_fputs" syntax="int pack_fputs(const char *p, PACKFILE *f);"><xreflist><xref>pack_fopen</xref><xref>pack_fopen_chunk</xref><xref>pack_fwrite</xref><xref>pack_putc</xref></xreflist><shortdesc>Writes a string to the stream.</shortdesc><text><![CDATA[   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.
]]></text><retval><text><![CDATA[   Returns zero on success or a negative number on error.

]]></text></retval></ref><ref name="pack_fopen_chunk" syntax="PACKFILE *pack_fopen_chunk(PACKFILE *f, int pack);"><xreflist><xref>pack_fclose_chunk</xref><xref>pack_fopen</xref></xreflist><shortdesc>Opens a sub-chunk of a file.</shortdesc><text><![CDATA[   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:
<pre class="code">
      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);
</pre>
   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:
<pre class="code">
      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);
</pre>
   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.
]]></text><retval><text><![CDATA[   Returns a pointer to the sub-chunked PACKFILE, or NULL if there was some
   error (eg. you are using a custom PACKFILE vtable).

]]></text></retval></ref><ref name="pack_fclose_chunk" syntax="PACKFILE *pack_fclose_chunk(PACKFILE *f);"><xreflist><xref>pack_fopen_chunk</xref></xreflist><shortdesc>Closes a previously opened sub-chunk.</shortdesc><text><![CDATA[   Closes a sub-chunk of a file, previously obtained by calling
   pack_fopen_chunk().
]]></text><retval><text><![CDATA[   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).

]]></text></retval></ref><ref name="create_lzss_pack_data" syntax="LZSS_PACK_DATA *create_lzss_pack_data(void);"><xreflist><xref>free_lzss_pack_data</xref></xreflist><shortdesc>Creates an LZSS structure for compression.</shortdesc><text><![CDATA[   Creates an LZSS_PACK_DATA structure, which can be used for LZSS
   compression with PACKFILEs.
]]></text><retval><text><![CDATA[   Returns a pointer to the structure, or NULL if there was an error.

]]></text></retval></ref><ref name="free_lzss_pack_data" syntax="void free_lzss_pack_data(LZSS_PACK_DATA *dat);"><xreflist><xref>create_lzss_pack_data</xref></xreflist><shortdesc>Frees an LZSS structure.</shortdesc><text><![CDATA[   Frees an LZSS_PACK_DATA structure created with create_lzss_pack_data().

]]></text></ref><ref name="lzss_write" syntax="int lzss_write(PACKFILE *file, LZSS_PACK_DATA *dat, int size, unsigned char *buf, int last);"><xreflist><xref>create_lzss_pack_data</xref><xref>free_lzss_pack_data</xref></xreflist><shortdesc>Compresses data using LZSS.</shortdesc><text><![CDATA[   Packs `size' bytes from `buf', using the pack information contained in
   `dat'. The compressed bytes will be stored in `file'.
]]></text><retval><text><![CDATA[   Returns 0 on success, or EOF if there was an error.

]]></text></retval></ref><ref name="create_lzss_unpack_data" syntax="LZSS_UNPACK_DATA *create_lzss_unpack_data(void);"><xreflist><xref>free_lzss_unpack_data</xref></xreflist><shortdesc>Creates an LZSS structure for decompression.</shortdesc><text><![CDATA[   Creates an LZSS_UNPACK_DATA structure, which can be used for LZSS
   decompression reading PACKFILEs.
]]></text><retval><text><![CDATA[   Returns a pointer to the structure, or NULL if there was an error.

]]></text></retval></ref><ref name="free_lzss_unpack_data" syntax="void free_lzss_unpack_data(LZSS_UNPACK_DATA *dat);"><xreflist><xref>create_lzss_unpack_data</xref></xreflist><shortdesc>Frees an LZSS structure.</shortdesc><text><![CDATA[   Frees an LZSS_UNPACK_DATA structure created with create_lzss_pack_data.

]]></text></ref><ref name="lzss_read" syntax="int lzss_read(PACKFILE *file, LZSS_UNPACK_DATA *dat, int s, unsigned char *buf);"><xreflist><xref>free_lzss_unpack_data</xref></xreflist><shortdesc>Decompresses data using LZSS.</shortdesc><text><![CDATA[   Unpacks from `dat' into `buf', until either EOF is reached or `s' bytes
   have been extracted from `file'.
]]></text><retval><text><![CDATA[   Returns the number of bytes added to the buffer `buf'.



]]></text></retval></ref></reflist></section><section title="Datafile routines"><text><![CDATA[
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:
<ul><li>
   On some platforms loading a single big datafile at once is faster than
   loading individual resources one by one.
<li>
   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.
<li>
   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!
<li>
   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.
<li>
   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!
<li>
   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.
</ul>
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.

]]></text><reflist><ref name="load_datafile" syntax="DATAFILE *load_datafile(const char *filename);"><xreflist><xref>load_datafile_callback</xref><xref>unload_datafile</xref><xref>load_datafile_object</xref><xref>set_color_conversion</xref><xref>fixup_datafile</xref><xref>packfile_password</xref><xref>find_datafile_object</xref><xref>register_datafile_object</xref><xref>Using datafiles</xref></xreflist><ereflist><eref>excustom</eref><eref>exdata</eref><eref>exexedat</eref><eref>exgui</eref><eref>exsprite</eref><eref>exunicod</eref></ereflist><shortdesc>Loads a datafile into memory.</shortdesc><text><![CDATA[   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:
<pre class="code">
      /* 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);</pre>
]]></text><retval><text><![CDATA[   Returns a pointer to the DATAFILE, or NULL on error. Remember to free this
   DATAFILE later to avoid memory leaks.

]]></text></retval></ref><ref name="load_datafile_callback" syntax="DATAFILE *load_datafile_callback(const char *filename, void (*callback)(DATAFILE *d));"><xreflist><xref>load_datafile</xref><xref>unload_datafile</xref><xref>load_datafile_object</xref><xref>set_color_conversion</xref><xref>fixup_datafile</xref><xref>packfile_password</xref><xref>find_datafile_object</xref><xref>register_datafile_object</xref></xreflist><shortdesc>Loads a datafile into memory, calling a hook per object.</shortdesc><text><![CDATA[   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:
<pre class="code">
      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);</pre>
]]></text><retval><text><![CDATA[   Returns a pointer to the DATAFILE or NULL on error. Remember to free this
   DATAFILE later to avoid memory leaks.

]]></text></retval></ref><ref name="unload_datafile" syntax="void unload_datafile(DATAFILE *dat);"><xreflist><xref>load_datafile</xref></xreflist><ereflist><eref>excustom</eref><eref>exdata</eref><eref>exexedat</eref><eref>exgui</eref><eref>exsprite</eref><eref>exunicod</eref></ereflist><shortdesc>Frees all the objects in a datafile.</shortdesc><text><![CDATA[   Frees all the objects in a datafile. Use this to avoid memory leaks in
   your program.

]]></text></ref><ref name="load_datafile_object" syntax="DATAFILE *load_datafile_object(const char *filename, const char *objectname);"><xreflist><xref>unload_datafile_object</xref><xref>load_datafile</xref><xref>set_color_conversion</xref><xref>find_datafile_object</xref><xref>register_datafile_object</xref><xref>Using datafiles</xref></xreflist><shortdesc>Loads a specific object from a datafile.</shortdesc><text><![CDATA[   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:
<pre class="code">
      /* 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-&gt;dat);
      ...
      /* Destroy unneeded music. */
      unload_datafile_object(music_object);</pre>
]]></text><retval><text><![CDATA[   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!

]]></text></retval></ref><ref name="unload_datafile_object" syntax="void unload_datafile_object(DATAFILE *dat);"><xreflist><xref>load_datafile_object</xref></xreflist><shortdesc>Frees an object previously loaded by load_datafile_object().</shortdesc><text><![CDATA[   Frees an object previously loaded by load_datafile_object(). Use this to
   avoid memory leaks in your program.

]]></text></ref><ref name="find_datafile_object" syntax="DATAFILE *find_datafile_object(const DATAFILE *dat, const char *objectname);"><xreflist><xref>load_datafile</xref><xref>load_datafile_object</xref></xreflist><shortdesc>Searches a datafile for an object with a name.</shortdesc><text><![CDATA[   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:
<pre class="code">
      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!");</pre>
]]></text><retval><text><![CDATA[   Returns a pointer to a single DATAFILE element whose `dat' member points to
   the object, or NULL if the object could not be found.

]]></text></retval></ref><ref name="create_datafile_index" syntax="DATAFILE_INDEX *create_datafile_index(const char *filename);"><xreflist><xref>destroy_datafile_index</xref><xref>load_datafile_object_indexed</xref><xref>Using datafiles</xref></xreflist><shortdesc>Creates an index for a datafile.</shortdesc><text><![CDATA[   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:
<pre class="code">
   DATAFILE_INDEX *index = create_datafile_index("huge.dat");
   DATAFILE *object = load_datafile_object_indexed(index, 1234);
   ...
   unload_datafile_object(object);
   destroy_datafile_index(index);</pre>
]]></text><retval><text><![CDATA[   A pointer value which you can pass to load_datafile_object_indexed.

]]></text></retval></ref><ref name="load_datafile_object_indexed" syntax="DATAFILE *load_datafile_object_indexed(const DATAFILE_INDEX *index, int item)"><xreflist><xref>create_datafile_index</xref><xref>load_datafile_object</xref><xref>unload_datafile_object</xref></xreflist><shortdesc>Loads a single object from a datafile index.</shortdesc><text><![CDATA[   This loads a single object, using the index created previously with
   create_datafile_index. See create_datafile_index for an example.
]]></text><retval><text><![CDATA[   Returns a pointer to a single DATAFILE element whose "dat" member points to
   the object, or NULL if the object could not be loaded.

]]></text></retval></ref><ref name="destroy_datafile_index" syntax="void destroy_datafile_index(DATAFILE_INDEX *index)"><xreflist><xref>create_datafile_index</xref></xreflist><shortdesc>Destroys a datafile index.</shortdesc><text><![CDATA[   This function frees the memory used by a datafile index created with
   create_datafile_index earlier.

]]></text></ref><ref name="get_datafile_property" syntax="const char *get_datafile_property(const DATAFILE *dat, int type);"><xreflist><xref>Using datafiles</xref><xref>DAT_ID</xref><xref>empty_string</xref></xreflist><shortdesc>Returns the property string for the object.</shortdesc><text><![CDATA[   Finds the property type of a DATAFILE object. The type parameter must be a
   value created with the DAT_ID() macro. Example:
<pre class="code">
      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!");</pre>
]]></text><retval><text><![CDATA[   Returns a pointer to the text string for the object, or a pointer to the
   variable empty_string if the property isn't present.

]]></text></retval></ref><ref name="register_datafile_object" syntax="void register_datafile_object(int id, void *(*load)(PACKFILE *f, long size), void (*destroy)(void *data));"><xreflist><xref>load_datafile</xref><xref>load_datafile_object</xref><xref>DAT_ID</xref><xref>Custom datafile objects</xref></xreflist><shortdesc>Registers load/destroy functions for custom object types.</shortdesc><text><![CDATA[   Used to add custom object types, specifying functions to load and destroy
   objects of this type.

]]></text></ref><ref name="fixup_datafile" syntax="void fixup_datafile(DATAFILE *data);"><xreflist><xref>set_gfx_mode</xref><xref>set_color_conversion</xref><xref>Differences between platforms</xref></xreflist><shortdesc>Fixes truecolor images in compiled datafiles.</shortdesc><text><![CDATA[   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&lt;-&gt;16-bit
   hicolor for both bitmaps and RLE sprites, and 24&lt;-&gt;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.

]]></text></ref><ref name="DAT_ID" syntax="Macro DAT_ID(a, b, c, d);"><xreflist><xref>register_datafile_object</xref><xref>get_datafile_property</xref><xref>Custom datafile objects</xref><xref>Using datafiles</xref></xreflist><shortdesc>Makes an ID value from four letters.</shortdesc><text><![CDATA[   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:
<pre class="code">
      get_datafile_property(datob, DAT_ID('N','A','M','E'));
</pre>


]]></text></ref></reflist><section title="Using datafiles"><text><![CDATA[
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:
<pre class="code">
   #define SOME_DATA                        0        /* DATA */
   #define SOME_MORE_DATA                   1        /* DATA */
</pre>
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:
<pre class="code">
   DATAFILE *load_datafile(char *filename);
</pre>
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:
<pre class="code">
   void unload_datafile(DATAFILE *dat);
</pre>
When you load a datafile, you will obtain a pointer to an array of DATAFILE
structures:
<pre class="code">
   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;</pre>

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:
<pre class="code">
   #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-&gt;w, bmp-&gt;h);
      unload_datafile(dat);
   }</pre>

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:
<pre class="text">
   "FILE" - NESTED_FILE
	    |- "BMP" - A_BITMAP
	    |- "FONT" - A_FONT
   "DATA" - SOME_DATA
   "DATA" - SOME_MORE_DATA
</pre>
Will produce the header:
<pre class="code">
   #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 */
</pre>
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:
<pre class="code">
   DATAFILE *dat = load_datafile("whatever.dat");
   DATAFILE *nested = (DATAFILE *)dat[NESTED_FILE].dat;
   FONT *thefont = (FONT *)nested[NESTED_FILE_A_FONT].dat;
</pre>
If you need to access object property strings from within your program, you
can use the function:
<pre class="code">
   char *get_datafile_property(DATAFILE *dat, int type);
</pre>
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:
<pre class="code">
   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... */
</pre>
If you prefer to access objects by name rather than index number, you can
use the function:
<pre class="code">
   DATAFILE *find_datafile_object(DATAFILE *dat, char *objectname);
</pre>
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:
<pre class="code">
   DATAFILE *load_datafile_object(char *filename, char *objectname);
</pre>
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:
<pre class="code">
   void unload_datafile_object(DATAFILE *dat);
</pre>
Example:
<pre class="code">
   music_object = load_datafile_object("datafile.dat", "MUSIC");
   play_midi(music_object-&gt;dat);
   ...
   unload_datafile_object(music_object);
</pre>
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().



]]></text></section><section title="Custom datafile objects"><text><![CDATA[
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:
<pre class="code">
   #define DAT_MAPDATA  DAT_ID('M','A','P','D')
</pre>
You then need to write functions for loading and destroying objects of this
type, in the form:
<pre class="code">
   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&lt;;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);
   }
</pre>
Finally, before you load your datafile you must tell Allegro about the
custom format, by calling:
<pre class="code">
   register_datafile_object(DAT_MAPDATA, load_mapdata, destroy_mapdata);
</pre>
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.



]]></text></section></section><section title="Fixed point math routines"><text><![CDATA[
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.

]]></text><reflist><ref name="itofix" syntax="fixed itofix(int x);"><xreflist><xref>fixtoi</xref><xref>ftofix</xref><xref>fixtof</xref></xreflist><ereflist><eref>ex12bit</eref><eref>ex3buf</eref><eref>ex3d</eref><eref>exblend</eref><eref>excustom</eref><eref>exfixed</eref><eref>exlights</eref><eref>exspline</eref><eref>exsprite</eref><eref>exstars</eref></ereflist><shortdesc>Converts an integer to fixed point.</shortdesc><text><![CDATA[   Converts an integer to fixed point. This is the same thing as x&lt;&lt;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:
<pre class="code">
      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);</pre>
]]></text><retval><text><![CDATA[   Returns the value of the integer converted to fixed point ignoring
   overflows.

]]></text></retval></ref><ref name="fixtoi" syntax="int fixtoi(fixed x);"><xreflist><xref>itofix</xref><xref>ftofix</xref><xref>fixtof</xref><xref>fixfloor</xref><xref>fixceil</xref></xreflist><ereflist><eref>ex12bit</eref><eref>ex3buf</eref><eref>ex3d</eref><eref>exblend</eref><eref>excustom</eref><eref>exlights</eref><eref>exspline</eref><eref>exstars</eref><eref>exupdate</eref></ereflist><shortdesc>Converts a fixed point to integer with rounding.</shortdesc><text><![CDATA[   Converts fixed point to integer, rounding as required to the nearest
   integer. Example:
<pre class="code">
      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);</pre>

]]></text></ref><ref name="fixfloor" syntax="int fixfloor(fixed x);"><xreflist><xref>fixtoi</xref><xref>fixceil</xref></xreflist><shortdesc>Returns the greatest integer not greater than x.</shortdesc><text><![CDATA[   Returns the greatest integer not greater than x. That is, it rounds
   towards negative infinity. Example:
<pre class="code">
      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);</pre>

]]></text></ref><ref name="fixceil" syntax="int fixceil(fixed x);"><xreflist><xref>fixtoi</xref><xref>fixfloor</xref></xreflist><shortdesc>Returns the smallest integer not less than x.</shortdesc><text><![CDATA[   Returns the smallest integer not less than x. That is, it rounds towards
   positive infinity. Example:
<pre class="code">
      int result;
      /* This will put 34 into `result'. */
      result = fixceil(itofix(100) / 3);
      /* This will round up to 17. */
      result = fixceil(itofix(100) / 6);</pre>

]]></text></ref><ref name="ftofix" syntax="fixed ftofix(double x);"><xreflist><xref>fixtof</xref><xref>itofix</xref><xref>fixtoi</xref></xreflist><ereflist><eref>exfixed</eref><eref>exspline</eref><eref>exupdate</eref></ereflist><shortdesc>Converts a floating point value to fixed point.</shortdesc><text><![CDATA[   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:
<pre class="code">
      fixed number;
      number = itofix(-40000);
      ASSERT(fixfloor(number) == -32768);
      number = itofix(64000);
      ASSERT(fixfloor(number) == 32767);
      ASSERT(!errno); /* This will fail. */</pre>
]]></text><retval><text><![CDATA[   Returns the value of the floating point value converted to fixed point
   clamping overflows (and setting `errno').

]]></text></retval></ref><ref name="fixtof" syntax="double fixtof(fixed x);"><xreflist><xref>ftofix</xref><xref>itofix</xref><xref>fixtoi</xref></xreflist><ereflist><eref>exfixed</eref><eref>exspline</eref><eref>exstars</eref></ereflist><shortdesc>Converts a fixed point to floating point.</shortdesc><text><![CDATA[   Converts fixed point to floating point. Example:
<pre class="code">
      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);</pre>

]]></text></ref><ref name="fixmul" syntax="fixed fixmul(fixed x, fixed y);"><xreflist><xref>fixadd</xref><xref>fixsub</xref><xref>fixdiv</xref></xreflist><ereflist><eref>ex3buf</eref><eref>excustom</eref><eref>exfixed</eref><eref>exspline</eref><eref>exstars</eref><eref>exupdate</eref></ereflist><shortdesc>Multiplies two fixed point values together.</shortdesc><text><![CDATA[   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:
<pre class="code">
      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);</pre>
]]></text><retval><text><![CDATA[   Returns the clamped result of multiplying `x' by `y', setting `errno' to
   ERANGE if there was an overflow.

]]></text></retval></ref><ref name="fixdiv" syntax="fixed fixdiv(fixed x, fixed y);"><xreflist><xref>fixadd</xref><xref>fixsub</xref><xref>fixmul</xref></xreflist><ereflist><eref>exfixed</eref></ereflist><shortdesc>Fixed point division.</shortdesc><text><![CDATA[   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:
<pre class="code">
      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. */</pre>
]]></text><retval><text><![CDATA[   Returns the result of dividing `x' by `y'. If `y' is zero, returns the
   maximum possible fixed point value and sets `errno' to ERANGE.

]]></text></retval></ref><ref name="fixadd" syntax="fixed fixadd(fixed x, fixed y);"><xreflist><xref>fixsub</xref><xref>fixmul</xref><xref>fixdiv</xref></xreflist><shortdesc>Safe function to add fixed point numbers clamping overflow.</shortdesc><text><![CDATA[   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:
<pre class="code">
      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. */</pre>
]]></text><retval><text><![CDATA[   Returns the clamped result of adding `x' to `y', setting `errno' to ERANGE
   if there was an overflow.

]]></text></retval></ref><ref name="fixsub" syntax="fixed fixsub(fixed x, fixed y);"><xreflist><xref>fixadd</xref><xref>fixmul</xref><xref>fixdiv</xref></xreflist><shortdesc>Safe function to subtract fixed point numbers clamping underflow.</shortdesc><text><![CDATA[   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:
<pre class="code">
      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. */</pre>
]]></text><retval><text><![CDATA[   Returns the clamped result of subtracting `y' from `x', setting `errno' to
   ERANGE if there was an overflow.

]]></text></retval></ref></reflist><section title="Fixed point trig"><text><![CDATA[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 cicles 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 &gt;= 360)' checks.

]]></text><reflist><ref name="fixtorad_r" syntax="extern const fixed fixtorad_r;"><xreflist><xref>fixmul</xref><xref>radtofix_r</xref></xreflist><shortdesc>Constant to convert angles in fixed point format to radians.</shortdesc><text><![CDATA[   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:
<pre class="code">
      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);</pre>

]]></text></ref><ref name="radtofix_r" syntax="extern const fixed radtofix_r;"><xreflist><xref>fixmul</xref><xref>fixtorad_r</xref></xreflist><shortdesc>Constant to convert radians to fixed point angles.</shortdesc><text><![CDATA[   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:
<pre class="code">
      fixed rad_angle, binary_angle;
      ...
      binary_angle = fixmul(rad_angle, radtofix_r);</pre>

]]></text></ref><ref name="fixsin" syntax="fixed fixsin(fixed x);"><xreflist><xref>Fixed point trig</xref></xreflist><ereflist><eref>ex12bit</eref><eref>ex3buf</eref><eref>exblend</eref><eref>excustom</eref><eref>exspline</eref><eref>exupdate</eref></ereflist><shortdesc>Fixed point sine of binary angles.</shortdesc><text><![CDATA[   This function finds the sine of a value using a lookup table. The input
   value must be a fixed point binary angle. Example:
<pre class="code">
      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);</pre>
]]></text><retval><text><![CDATA[   Returns the sine of a fixed point binary format angle. The return value
   will be in radians.

]]></text></retval></ref><ref name="fixcos" syntax="fixed fixcos(fixed x);"><xreflist><xref>Fixed point trig</xref></xreflist><ereflist><eref>ex12bit</eref><eref>ex3buf</eref><eref>exblend</eref><eref>excustom</eref><eref>exspline</eref><eref>exupdate</eref></ereflist><shortdesc>Fixed point cosine of binary angles.</shortdesc><text><![CDATA[   This function finds the cosine of a value using a lookup table. The input
   value must be a fixed point binary angle. Example:
<pre class="code">
      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 &gt; 0.7 &amp;&amp; result &lt; 0.71);</pre>
]]></text><retval><text><![CDATA[   Returns the cosine of a fixed point binary format angle. The return value
   will be in radians.

]]></text></retval></ref><ref name="fixtan" syntax="fixed fixtan(fixed x);"><xreflist><xref>Fixed point trig</xref></xreflist><shortdesc>Fixed point tangent of binary angles.</shortdesc><text><![CDATA[   This function finds the tangent of a value using a lookup table. The input
   value must be a fixed point binary angle. Example:
<pre class="code">
      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);</pre>
]]></text><retval><text><![CDATA[   Returns the tangent of a fixed point binary format angle. The return value
   will be in radians.

]]></text></retval></ref><ref name="fixasin" syntax="fixed fixasin(fixed x);"><xreflist><xref>Fixed point trig</xref></xreflist><shortdesc>Fixed point inverse sine lookup table.</shortdesc><text><![CDATA[   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:
<pre class="code">
      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);</pre>
]]></text><retval><text><![CDATA[   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'.

]]></text></retval></ref><ref name="fixacos" syntax="fixed fixacos(fixed x);"><xreflist><xref>Fixed point trig</xref></xreflist><shortdesc>Fixed point inverse cosine lookup table.</shortdesc><text><![CDATA[   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:
<pre class="code">
      fixed result;

      /* Sets `result' to binary angle 128. */
      result = fixacos(itofix(-1));</pre>
]]></text><retval><text><![CDATA[   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'.

]]></text></retval></ref><ref name="fixatan" syntax="fixed fixatan(fixed x);"><xreflist><xref>Fixed point trig</xref></xreflist><shortdesc>Fixed point inverse tangent lookup table.</shortdesc><text><![CDATA[   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:
<pre class="code">
      fixed result;

      /* Sets `result' to binary angle 13. */
      result = fixatan(ftofix(0.326));</pre>
]]></text><retval><text><![CDATA[   Returns the inverse tangent of a fixed point value, measured as a fixed
   point binary format angle.

]]></text></retval></ref><ref name="fixatan2" syntax="fixed fixatan2(fixed y, fixed x);"><xreflist><xref>Fixed point trig</xref></xreflist><ereflist><eref>exlights</eref><eref>exspline</eref></ereflist><shortdesc>Fixed point version of the libc atan2() routine.</shortdesc><text><![CDATA[   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:
<pre class="code">
      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);</pre>
]]></text><retval><text><![CDATA[   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.

]]></text></retval></ref><ref name="fixsqrt" syntax="fixed fixsqrt(fixed x);"><xreflist><xref>Fixed point trig</xref></xreflist><ereflist><eref>exfixed</eref><eref>exlights</eref><eref>exspline</eref></ereflist><shortdesc>Fixed point square root.</shortdesc><text><![CDATA[   This finds out the non negative square root of `x'. If `x' is negative,
   `errno' is set to EDOM and the function returns zero.

]]></text></ref><ref name="fixhypot" syntax="fixed fixhypot(fixed x, fixed y);"><xreflist><xref>Fixed point trig</xref></xreflist><shortdesc>Fixed point hypotenuse.</shortdesc><text><![CDATA[   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.

]]></text></ref></reflist></section><section title="Fix class"><text><![CDATA[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.



]]></text></section></section><section title="3D math routines"><text><![CDATA[
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.

<pre class="code">
   /* 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 (&amp;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 (&amp;m, 100, 200, -300, &amp;x, &amp;y, &amp;z);

   /* Finally, the point is projected from
    * camera space to the screen.
    */
   persp_project_f (cx, cy, cz, &amp;sx, &amp;sy);</pre>

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:
<pre class="text">
   ( a, b, c, d )
   ( e, f, g, h )
   ( i, j, k, l )
   ( m, n, o, p )
</pre>
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 &amp; 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.

]]></text><reflist><ref name="identity_matrix" syntax="extern MATRIX identity_matrix;"/><ref name="identity_matrix_f" syntax="extern MATRIX_f identity_matrix_f;"><shortdesc>Global containing the identity matrix.</shortdesc><text><![CDATA[   Global variables containing the 'do nothing' identity matrix. Multiplying
   by the identity matrix has no effect.

]]></text></ref><ref name="get_translation_matrix" syntax="void get_translation_matrix(MATRIX *m, fixed x, fixed y, fixed z);"/><ref name="get_translation_matrix_f" syntax="void get_translation_matrix_f(MATRIX_f *m, float x, float y, float z);"><xreflist><xref>apply_matrix</xref><xref>get_transformation_matrix</xref><xref>qtranslate_matrix</xref></xreflist><ereflist><eref>exstars</eref></ereflist><shortdesc>Constructs a translation matrix.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="get_scaling_matrix" syntax="void get_scaling_matrix(MATRIX *m, fixed x, fixed y, fixed z);"/><ref name="get_scaling_matrix_f" syntax="void get_scaling_matrix_f(MATRIX_f *m, float x, float y, float z);"><xreflist><xref>apply_matrix</xref><xref>get_transformation_matrix</xref><xref>qscale_matrix</xref></xreflist><shortdesc>Constructs a scaling matrix.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="get_x_rotate_matrix" syntax="void get_x_rotate_matrix(MATRIX *m, fixed r);"/><ref name="get_x_rotate_matrix_f" syntax="void get_x_rotate_matrix_f(MATRIX_f *m, float r);"><xreflist><xref>apply_matrix</xref><xref>get_rotation_matrix</xref><xref>get_y_rotate_matrix</xref><xref>get_z_rotate_matrix</xref></xreflist><shortdesc>Construct X axis rotation matrices.</shortdesc><text><![CDATA[   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).

]]></text></ref><ref name="get_y_rotate_matrix" syntax="void get_y_rotate_matrix(MATRIX *m, fixed r);"/><ref name="get_y_rotate_matrix_f" syntax="void get_y_rotate_matrix_f(MATRIX_f *m, float r);"><xreflist><xref>apply_matrix</xref><xref>get_rotation_matrix</xref><xref>get_x_rotate_matrix</xref><xref>get_z_rotate_matrix</xref></xreflist><shortdesc>Construct Y axis rotation matrices.</shortdesc><text><![CDATA[   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).

]]></text></ref><ref name="get_z_rotate_matrix" syntax="void get_z_rotate_matrix(MATRIX *m, fixed r);"/><ref name="get_z_rotate_matrix_f" syntax="void get_z_rotate_matrix_f(MATRIX_f *m, float r);"><xreflist><xref>apply_matrix</xref><xref>get_rotation_matrix</xref><xref>get_x_rotate_matrix</xref><xref>get_y_rotate_matrix</xref></xreflist><shortdesc>Construct Z axis rotation matrices.</shortdesc><text><![CDATA[   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).

]]></text></ref><ref name="get_rotation_matrix" syntax="void get_rotation_matrix(MATRIX *m, fixed x, fixed y, fixed z);"/><ref name="get_rotation_matrix_f" syntax="void get_rotation_matrix_f(MATRIX_f *m, float x, float y, float z);"><xreflist><xref>apply_matrix</xref><xref>get_transformation_matrix</xref><xref>get_vector_rotation_matrix</xref><xref>get_x_rotate_matrix</xref><xref>get_y_rotate_matrix</xref><xref>get_z_rotate_matrix</xref><xref>get_align_matrix</xref></xreflist><ereflist><eref>ex12bit</eref><eref>exquat</eref><eref>exstars</eref></ereflist><shortdesc>Constructs X, Y, Z rotation matrices.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="get_align_matrix" syntax="void get_align_matrix(MATRIX *m, fixed xfront, yfront, zfront, fixed xup, fixed yup, fixed zup);"><xreflist><xref>apply_matrix</xref><xref>get_camera_matrix</xref></xreflist><shortdesc>Rotates a matrix to align it along specified coordinate vectors.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="get_align_matrix_f" syntax="void get_align_matrix_f(MATRIX *m, float xfront, yfront, zfront, float xup, yup, zup);"><xreflist><xref>get_align_matrix</xref></xreflist><shortdesc>Floating point version of get_align_matrix().</shortdesc><text><![CDATA[   Floating point version of get_align_matrix().

]]></text></ref><ref name="get_vector_rotation_matrix" syntax="void get_vector_rotation_matrix(MATRIX *m, fixed x, y, z, fixed a);"/><ref name="get_vector_rotation_matrix_f" syntax="void get_vector_rotation_matrix_f(MATRIX_f *m, float x, y, z, float a);"><xreflist><xref>apply_matrix</xref><xref>get_rotation_matrix</xref><xref>get_align_matrix</xref></xreflist><ereflist><eref>excamera</eref></ereflist><shortdesc>Constructs X, Y, Z rotation matrices with an angle.</shortdesc><text><![CDATA[   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).

]]></text></ref><ref name="get_transformation_matrix" syntax="void get_transformation_matrix(MATRIX *m, fixed scale, fixed xrot, yrot, zrot, x, y, z);"><xreflist><xref>apply_matrix</xref><xref>get_rotation_matrix</xref><xref>get_scaling_matrix</xref><xref>get_translation_matrix</xref></xreflist><ereflist><eref>ex3d</eref><eref>exstars</eref></ereflist><shortdesc>Constructs X, Y, Z rotation matrices with an angle and scaling.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="get_transformation_matrix_f" syntax="void get_transformation_matrix_f(MATRIX_f *m, float scale, float xrot, yrot, zrot, x, y, z);"><xreflist><xref>get_transformation_matrix</xref></xreflist><ereflist><eref>exzbuf</eref></ereflist><shortdesc>Floating point version of get_transformation_matrix().</shortdesc><text><![CDATA[   Floating point version of get_transformation_matrix().

]]></text></ref><ref name="get_camera_matrix" syntax="void get_camera_matrix(MATRIX *m, fixed x, y, z, xfront, yfront, zfront, fixed xup, yup, zup, fov, aspect);"><xreflist><xref>apply_matrix</xref><xref>get_align_matrix</xref><xref>set_projection_viewport</xref><xref>persp_project</xref></xreflist><shortdesc>Constructs a camera matrix for perspective projection.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="get_camera_matrix_f" syntax="void get_camera_matrix_f(MATRIX_f *m, float x, y, z, xfront, yfront, zfront, float xup, yup, zup, fov, aspect);"><xreflist><xref>get_camera_matrix</xref></xreflist><ereflist><eref>excamera</eref><eref>exquat</eref></ereflist><shortdesc>Floating point version of get_camera_matrix().</shortdesc><text><![CDATA[   Floating point version of get_camera_matrix().

]]></text></ref><ref name="qtranslate_matrix" syntax="void qtranslate_matrix(MATRIX *m, fixed x, fixed y, fixed z);"/><ref name="qtranslate_matrix_f" syntax="void qtranslate_matrix_f(MATRIX_f *m, float x, float y, float z);"><xreflist><xref>get_translation_matrix</xref></xreflist><shortdesc>Optimised routine for translating an already generated matrix.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="qscale_matrix" syntax="void qscale_matrix(MATRIX *m, fixed scale);"/><ref name="qscale_matrix_f" syntax="void qscale_matrix_f(MATRIX_f *m, float scale);"><xreflist><xref>get_scaling_matrix</xref></xreflist><shortdesc>Optimised routine for scaling an already generated matrix.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="matrix_mul" syntax="void matrix_mul(const MATRIX *m1, const MATRIX *m2, MATRIX *out);"/><ref name="matrix_mul_f" syntax="void matrix_mul_f(const MATRIX_f *m1, const MATRIX_f *m2, MATRIX_f *out);"><xreflist><xref>apply_matrix</xref></xreflist><ereflist><eref>exquat</eref><eref>exscn3d</eref></ereflist><shortdesc>Multiplies two matrices.</shortdesc><text><![CDATA[   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).

]]></text></ref><ref name="vector_length" syntax="fixed vector_length(fixed x, fixed y, fixed z);"/><ref name="vector_length_f" syntax="float vector_length_f(float x, float y, float z);"><xreflist><xref>normalize_vector</xref></xreflist><shortdesc>Calculates the length of a vector.</shortdesc><text><![CDATA[   Calculates the length of the vector (x, y, z), using that good 'ole
   Pythagoras theorem.

]]></text></ref><ref name="normalize_vector" syntax="void normalize_vector(fixed *x, fixed *y, fixed *z);"/><ref name="normalize_vector_f" syntax="void normalize_vector_f(float *x, float *y, float *z);"><xreflist><xref>vector_length</xref><xref>dot_product</xref><xref>cross_product</xref></xreflist><ereflist><eref>exstars</eref></ereflist><shortdesc>Converts the vector to a unit vector.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="dot_product" syntax="fixed dot_product(fixed x1, y1, z1, x2, y2, z2);"/><ref name="dot_product_f" syntax="float dot_product_f(float x1, y1, z1, x2, y2, z2);"><xreflist><xref>cross_product</xref><xref>normalize_vector</xref></xreflist><ereflist><eref>exstars</eref></ereflist><shortdesc>Calculates the dot product.</shortdesc><text><![CDATA[   Calculates the dot product (x1, y1, z1) . (x2, y2, z2), returning the
   result.

]]></text></ref><ref name="cross_product" syntax="void cross_product(fixed x1, y1, z1, x2, y2, z2, *xout, *yout, *zout);"/><ref name="cross_product_f" syntax="void cross_product_f(float x1, y1, z1, x2, y2, z2, *xout, *yout, *zout);"><xreflist><xref>dot_product</xref><xref>polygon_z_normal</xref><xref>normalize_vector</xref></xreflist><ereflist><eref>exstars</eref></ereflist><shortdesc>Calculates the cross product.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="polygon_z_normal" syntax="fixed polygon_z_normal(const V3D *v1, const V3D *v2, const V3D *v3);"/><ref name="polygon_z_normal_f" syntax="float polygon_z_normal_f(const V3D_f *v1, const V3D_f *v2, const V3D_f *v3);"><xreflist><xref>cross_product</xref></xreflist><ereflist><eref>ex3d</eref></ereflist><shortdesc>Finds the Z component of the normal vector to three vertices.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="apply_matrix" syntax="void apply_matrix(const MATRIX *m, fixed x, y, z, *xout, *yout, *zout);"/><ref name="apply_matrix_f" syntax="void apply_matrix_f(const MATRIX_f *m, float x, y, z, *xout, *yout, *zout);"><xreflist><xref>matrix_mul</xref></xreflist><ereflist><eref>ex12bit</eref><eref>ex3d</eref><eref>exstars</eref></ereflist><shortdesc>Multiplies a point by a transformation matrix.</shortdesc><text><![CDATA[   Multiplies the point (x, y, z) by the transformation matrix m, storing
   the result in (*xout, *yout, *zout).

]]></text></ref><ref name="set_projection_viewport" syntax="void set_projection_viewport(int x, int y, int w, int h);"><xreflist><xref>persp_project</xref><xref>get_camera_matrix</xref></xreflist><ereflist><eref>ex3d</eref><eref>excamera</eref><eref>exquat</eref><eref>exscn3d</eref><eref>exstars</eref><eref>exzbuf</eref></ereflist><shortdesc>Sets the viewport used to scale the output of persp_project().</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="persp_project" syntax="void persp_project(fixed x, fixed y, fixed z, fixed *xout, fixed *yout);"/><ref name="persp_project_f" syntax="void persp_project_f(float x, float y, float z, float *xout, float *yout);"><xreflist><xref>set_projection_viewport</xref><xref>get_camera_matrix</xref></xreflist><ereflist><eref>ex3d</eref><eref>exstars</eref></ereflist><shortdesc>Projects a 3d point into 2d screen space.</shortdesc><text><![CDATA[   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.



]]></text></ref></reflist></section><section title="Quaternion math routines"><text><![CDATA[
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:
<pre class="code">
   typedef struct QUAT
   {
      float w, x, y, z;
   }
</pre>
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.

]]></text><reflist><ref name="identity_quat" syntax="extern QUAT identity_quat;"><shortdesc>Global variable containing the identity quaternion.</shortdesc><text><![CDATA[   Global variable containing the 'do nothing' identity quaternion.
   Multiplying by the identity quaternion has no effect.

]]></text></ref><ref name="get_x_rotate_quat" syntax="void get_x_rotate_quat(QUAT *q, float r);"/><ref name="get_y_rotate_quat" syntax="void get_y_rotate_quat(QUAT *q, float r);"/><ref name="get_z_rotate_quat" syntax="void get_z_rotate_quat(QUAT *q, float r);"><shortdesc>Construct axis rotation quaternions.</shortdesc><text><![CDATA[   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).

]]></text></ref><ref name="get_rotation_quat" syntax="void get_rotation_quat(QUAT *q, float x, float y, float z);"><ereflist><eref>exquat</eref></ereflist><shortdesc>Constructs a quaternion to rotate points around all three axes.</shortdesc><text><![CDATA[   Constructs a quaternion that will rotate points around all three axes by
   the specified amounts (given in binary, 256 degrees to a circle format).

]]></text></ref><ref name="get_vector_rotation_quat" syntax="void get_vector_rotation_quat(QUAT *q, float x, y, z, float a);"><shortdesc>Constructs a quaternion to rotate points around a vector.</shortdesc><text><![CDATA[   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).

]]></text></ref><ref name="quat_to_matrix" syntax="void quat_to_matrix(const QUAT *q, MATRIX_f *m);"><ereflist><eref>exquat</eref></ereflist><shortdesc>Constructs a rotation matrix from a quaternion.</shortdesc><text><![CDATA[   Constructs a rotation matrix from a quaternion.

]]></text></ref><ref name="matrix_to_quat" syntax="void matrix_to_quat(const MATRIX_f *m, QUAT *q);"><shortdesc>Constructs a quaternion from a rotation matrix.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="quat_mul" syntax="void quat_mul(const QUAT *p, const QUAT *q, QUAT *out);"><shortdesc>Multiplies two quaternions.</shortdesc><text><![CDATA[   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).

]]></text></ref><ref name="apply_quat" syntax="void apply_quat(const QUAT *q, float x, y, z, *xout, *yout, *zout);"><shortdesc>Multiplies a point by a quaternion.</shortdesc><text><![CDATA[   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().

]]></text></ref><ref name="quat_interpolate" syntax="void quat_interpolate(const QUAT *from, const QUAT *to, float t, QUAT *out);"><ereflist><eref>exquat</eref></ereflist><shortdesc>Constructs a quaternion representing a rotation between from and to.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="quat_slerp" syntax="void quat_slerp(const QUAT *from, const QUAT *to, float t, QUAT *out, int how);"><shortdesc>Version of quat_interpolate() allowing control over the rotation.</shortdesc><text><![CDATA[   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:
<pre class="text">
      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
</pre>


]]></text></ref></reflist></section><section title="GUI routines"><text><![CDATA[
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:
<pre class="text">
   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
</pre>
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:
<pre class="code">
   int foo(int msg, DIALOG *d, int c);
</pre>
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:
<pre class="text">
   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
</pre>
Dialog procedures may be called with any of the messages:

<b>MSG_START:</b><br>
   Tells the object to initialise itself. The dialog manager sends this to
   all the objects in a dialog just before it displays the dialog.

<b>MSG_END:</b><br>
   Sent to all objects when closing a dialog, allowing them to perform
   whatever cleanup operations they require.

<b>MSG_DRAW:</b><br>
   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.

<b>MSG_CLICK:</b><br>
   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.

<b>MSG_DCLICK:</b><br>
   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.

<b>MSG_KEY:</b><br>
   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.

<b>MSG_CHAR:</b><br>
   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.

<b>MSG_UCHAR:</b><br>
   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.

<b>MSG_XCHAR:</b><br>
   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.

<b>MSG_WANTFOCUS:</b><br>
   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.

<b>MSG_GOTFOCUS:</b><br>
<b>MSG_LOSTFOCUS:</b><br>
   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).

<b>MSG_GOTMOUSE:</b><br>
<b>MSG_LOSTMOUSE:</b><br>
   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.

<b>MSG_IDLE:</b><br>
   Sent whenever the dialog manager has nothing better to do.

<b>MSG_RADIO:</b><br>
   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.

<b>MSG_WHEEL:</b><br>
   Sent to the focused object whenever the mouse wheel moves. The c message
   parameter contains the number of clicks.

<b>MSG_LPRESS, MSG_MPRESS, MSG_RPRESS:</b><br>
   Sent when the corresponding mouse button is pressed.

<b>MSG_LRELEASE, MSG_MRELEASE, MSG_RRELEASE:</b><br>
   Sent when the corresponding mouse button is released.

<b>MSG_USER:</b><br>
   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:
<ul><li>
   Shadows under d_shadow_box_proc and d_button_proc are always black.
<li>
   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-&gt;w+1 and d-&gt;h+1 pixels (and not d-&gt;w and d-&gt;h, as it
   should be). This change affects the following objects :
<pre class="text">
      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.
</pre>
   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.
<li>
   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.
</ul><br>

Menus had been forgotten during the changes for 3.9.33 (CVS), so they were
still drawn too large until version 4.1.0.

]]></text><reflist><ref name="d_clear_proc" syntax="int d_clear_proc(int msg, DIALOG *d, int c);"><ereflist><eref>excustom</eref><eref>exgui</eref></ereflist><shortdesc>Dialog procedure to clear the screen.</shortdesc><text><![CDATA[   This just clears the screen when it is drawn. Useful as the first object
   in a dialog.

]]></text></ref><ref name="d_box_proc" syntax="int d_box_proc(int msg, DIALOG *d, int c);"/><ref name="d_shadow_box_proc" syntax="int d_shadow_box_proc(int msg, DIALOG *d, int c);"><ereflist><eref>exgui</eref><eref>exrgbhsv</eref></ereflist><shortdesc>Dialog procedure drawing boxes onto the screen.</shortdesc><text><![CDATA[   These draw boxes onto the screen, with or without a shadow.

]]></text></ref><ref name="d_bitmap_proc" syntax="int d_bitmap_proc(int msg, DIALOG *d, int c);"><ereflist><eref>exgui</eref><eref>exrgbhsv</eref></ereflist><shortdesc>Dialog procedure drawing a bitmap.</shortdesc><text><![CDATA[   This draws a bitmap onto the screen, which should be pointed to by the
   dp field.

]]></text></ref><ref name="d_text_proc" syntax="int d_text_proc(int msg, DIALOG *d, int c);"/><ref name="d_ctext_proc" syntax="int d_ctext_proc(int msg, DIALOG *d, int c);"/><ref name="d_rtext_proc" syntax="int d_rtext_proc(int msg, DIALOG *d, int c);"><ereflist><eref>exgui</eref><eref>exrgbhsv</eref></ereflist><shortdesc>Dialogs procedure drawing text onto the screen.</shortdesc><text><![CDATA[   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 '&amp;' 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
   "&amp;&amp;". To draw the text in something other than the default font, set the
   dp2 field to point to your custom font data.

]]></text></ref><ref name="d_button_proc" syntax="int d_button_proc(int msg, DIALOG *d, int c);"><ereflist><eref>excustom</eref><eref>exgui</eref></ereflist><shortdesc>Dialog procedure implementing a button object.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="d_check_proc" syntax="int d_check_proc(int msg, DIALOG *d, int c);"><ereflist><eref>excustom</eref><eref>exgui</eref></ereflist><shortdesc>Dialog procedure implementing a check box object.</shortdesc><text><![CDATA[   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).

]]></text></ref><ref name="d_radio_proc" syntax="int d_radio_proc(int msg, DIALOG *d, int c);"><ereflist><eref>exgui</eref></ereflist><shortdesc>Dialog procedure implementing a radio button object.</shortdesc><text><![CDATA[   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).

]]></text></ref><ref name="d_icon_proc" syntax="int d_icon_proc(int msg, DIALOG *d, int c);"><ereflist><eref>exgui</eref></ereflist><shortdesc>Dialog procedure implementing a bitmap button.</shortdesc><text><![CDATA[   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).

]]></text></ref><ref name="d_keyboard_proc" syntax="int d_keyboard_proc(int msg, DIALOG *d, int c);"><ereflist><eref>exgui</eref></ereflist><shortdesc>Invisible dialog procedure for implementing keyboard shortcuts.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="d_edit_proc" syntax="int d_edit_proc(int msg, DIALOG *d, int c);"><ereflist><eref>excustom</eref><eref>exgui</eref></ereflist><shortdesc>Dialog procedure implementing an editable text object.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="d_list_proc" syntax="int d_list_proc(int msg, DIALOG *d, int c);"><ereflist><eref>exgui</eref></ereflist><shortdesc>Dialog procedure implementing a list box object.</shortdesc><text><![CDATA[   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:
<pre class="code">
      char *foobar(int index, int *list_size);
</pre>
   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!

]]></text></ref><ref name="d_text_list_proc" syntax="int d_text_list_proc(int msg, DIALOG *d, int c);"><ereflist><eref>exgui</eref></ereflist><shortdesc>Dialog procedure implementing a list box object with type ahead.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="d_textbox_proc" syntax="int d_textbox_proc(int msg, DIALOG *d, int c);"><ereflist><eref>exgui</eref></ereflist><shortdesc>Dialog procedure implementing a text box object.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="d_slider_proc" syntax="int d_slider_proc(int msg, DIALOG *d, int c);"><ereflist><eref>exgui</eref><eref>exrgbhsv</eref></ereflist><shortdesc>Dialog procedure implementing a slider control object.</shortdesc><text><![CDATA[   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:
<pre class="code">
      int function(void *dp3, int d2);
</pre>
   The d_slider_proc object will return the value of the callback function.

]]></text></ref><ref name="d_menu_proc" syntax="int d_menu_proc(int msg, DIALOG *d, int c);"><xreflist><xref>GUI menus</xref><xref>active_menu</xref><xref>gui_menu_draw_menu</xref></xreflist><ereflist><eref>exgui</eref></ereflist><shortdesc>Dialog procedure implementing a menu bar object.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="d_yield_proc" syntax="int d_yield_proc(int msg, DIALOG *d, int c);"><xreflist><xref>rest</xref></xreflist><ereflist><eref>exgui</eref></ereflist><shortdesc>Invisible dialog procedure that yields CPU timeslices.</shortdesc><text><![CDATA[   An invisible helper object that yields timeslices 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.

]]></text></ref></reflist><section title="GUI variables"><text><![CDATA[The behaviour of the dialog manager can be controlled by the following
global variables.

]]></text><reflist><ref name="gui_mouse_focus" syntax="extern int gui_mouse_focus;"><shortdesc>Tells if the input focus follows the mouse pointer.</shortdesc><text><![CDATA[   If set, the input focus follows the mouse pointer around the dialog,
   otherwise a click is required to move it.

]]></text></ref><ref name="gui_fg_color" syntax="extern int gui_fg_color;"/><ref name="gui_bg_color" syntax="extern int gui_bg_color;"><xreflist><xref>gui_mg_color</xref><xref>set_dialog_color</xref></xreflist><ereflist><eref>exgui</eref></ereflist><shortdesc>The foreground and background colors for the standard dialogs.</shortdesc><text><![CDATA[   The foreground and background colors for the standard dialogs (alerts,
   menus, and the file selector). They default to 255 and 0.

]]></text></ref><ref name="gui_mg_color" syntax="extern int gui_mg_color;"><xreflist><xref>gui_fg_color</xref><xref>set_dialog_color</xref></xreflist><ereflist><eref>exgui</eref></ereflist><shortdesc>The color used for displaying greyed-out dialog objects.</shortdesc><text><![CDATA[   The color used for displaying greyed-out dialog objects (with the
   D_DISABLED flag set). Defaults to 8.

]]></text></ref><ref name="gui_font_baseline" syntax="extern int gui_font_baseline;"><shortdesc>Adjusts the keyboard shortcut underscores height.</shortdesc><text><![CDATA[   If set to a non-zero value, adjusts the keyboard shortcut underscores to
   account for the height of the descenders in your font.

]]></text></ref><ref name="gui_mouse_x" syntax="extern int (*gui_mouse_x)();"/><ref name="gui_mouse_y" syntax="extern int (*gui_mouse_y)();"/><ref name="gui_mouse_z" syntax="extern int (*gui_mouse_z)();"/><ref name="gui_mouse_b" syntax="extern int (*gui_mouse_b)();"><shortdesc>Hook functions used by the GUI routines to access the mouse state.</shortdesc><text><![CDATA[   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.

]]></text></ref></reflist></section><section title="GUI font"><text><![CDATA[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.

]]></text><reflist><ref name="gui_textout_ex" syntax="int gui_textout_ex(BITMAP *bmp, const char *s, int x, y, color, bg, centre);"><xreflist><xref>gui_strlen</xref></xreflist><shortdesc>Draws a text string onto the screen with keyboard shortcut underbars.</shortdesc><text><![CDATA[   Helper function for use by the GUI routines. Draws a text string onto the
   screen, interpreting the '&amp;' character as an underbar for displaying
   keyboard shortcuts. Returns the width of the output string in pixels.

]]></text></ref><ref name="gui_strlen" syntax="int gui_strlen(const char *s);"><xreflist><xref>gui_textout_ex</xref></xreflist><shortdesc>Returns the length of a string in pixels.</shortdesc><text><![CDATA[   Helper function for use by the GUI routines. Returns the length of a
   string in pixels, ignoring '&amp;' characters.

]]></text></ref><ref name="gui_set_screen" syntax="void gui_set_screen(BITMAP *bmp);"><xreflist><xref>gui_get_screen</xref></xreflist><shortdesc>Changes the bitmap surface GUI routines draw to.</shortdesc><text><![CDATA[   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:
<pre class="code">
      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]);
</pre>

]]></text></ref><ref name="gui_get_screen" syntax="BITMAP *gui_get_screen(void);"><xreflist><xref>gui_set_screen</xref></xreflist><shortdesc>Returns the bitmap surface GUI routines draw to.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="position_dialog" syntax="void position_dialog(DIALOG *dialog, int x, int y);"><xreflist><xref>centre_dialog</xref></xreflist><ereflist><eref>exgui</eref></ereflist><shortdesc>Moves an array of dialog objects to the specified position.</shortdesc><text><![CDATA[   Moves an array of dialog objects to the specified screen position
   (specified as the top left corner of the dialog).

]]></text></ref><ref name="centre_dialog" syntax="void centre_dialog(DIALOG *dialog);"><xreflist><xref>position_dialog</xref><xref>set_dialog_color</xref></xreflist><shortdesc>Centers an array of dialog objects.</shortdesc><text><![CDATA[   Moves an array of dialog objects so that it is centered in the screen.

]]></text></ref><ref name="set_dialog_color" syntax="void set_dialog_color(DIALOG *dialog, int fg, int bg);"><xreflist><xref>gui_fg_color</xref><xref>gui_mg_color</xref><xref>centre_dialog</xref></xreflist><ereflist><eref>exgui</eref></ereflist><shortdesc>Sets the colors of an array of dialog objects.</shortdesc><text><![CDATA[   Sets the foreground and background colors of an array of dialog objects.

]]></text></ref><ref name="find_dialog_focus" syntax="int find_dialog_focus(DIALOG *dialog);"><xreflist><xref>do_dialog</xref><xref>init_dialog</xref><xref>offer_focus</xref></xreflist><shortdesc>Searches the dialog for the object which has the input focus.</shortdesc><text><![CDATA[   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));

]]></text></ref><ref name="offer_focus" syntax="int offer_focus(DIALOG *dialog, int obj, int *focus_obj, int force);"><xreflist><xref>find_dialog_focus</xref></xreflist><shortdesc>Offers the input focus to a particular object.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="object_message" syntax="int object_message(DIALOG *dialog, int msg, int c);"><xreflist><xref>dialog_message</xref><xref>scare_mouse</xref><xref>scare_mouse_area</xref><xref>unscare_mouse</xref></xreflist><ereflist><eref>excustom</eref><eref>exrgbhsv</eref></ereflist><shortdesc>Sends a message to an object and returns the answer.</shortdesc><text><![CDATA[   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:
<pre class="code">
      object_message(&amp;dialog[1], MSG_DRAW, 0);
</pre>
   The function will take care of scaring and unscaring the mouse if the
   message is MSG_DRAW.

]]></text></ref><ref name="dialog_message" syntax="int dialog_message(DIALOG *dialog, int msg, int c, int *obj);"><xreflist><xref>object_message</xref><xref>broadcast_dialog_message</xref></xreflist><shortdesc>Sends a message to all the objects in an array.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="broadcast_dialog_message" syntax="int broadcast_dialog_message(int msg, int c);"><xreflist><xref>dialog_message</xref><xref>active_dialog</xref></xreflist><shortdesc>Broadcasts a message to all the objects in the active dialog.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="do_dialog" syntax="int do_dialog(DIALOG *dialog, int focus_obj);"><xreflist><xref>popup_dialog</xref><xref>init_dialog</xref><xref>centre_dialog</xref><xref>set_dialog_color</xref><xref>find_dialog_focus</xref></xreflist><ereflist><eref>excustom</eref><eref>exgui</eref><eref>exrgbhsv</eref></ereflist><shortdesc>Basic dialog manager function.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="popup_dialog" syntax="int popup_dialog(DIALOG *dialog, int focus_obj);"><xreflist><xref>do_dialog</xref></xreflist><shortdesc>do_dialog() used for popup dialogs.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="init_dialog" syntax="DIALOG_PLAYER *init_dialog(DIALOG *dialog, int focus_obj);"><xreflist><xref>update_dialog</xref><xref>shutdown_dialog</xref><xref>do_dialog</xref></xreflist><shortdesc>Low level initialisation of a dialog.</shortdesc><text><![CDATA[   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:
<pre class="code">
      DIALOG_PLAYER *player = init_dialog(dialog, focus_obj);

      while (update_dialog(player))
	 ;

      return shutdown_dialog(player);</pre>

   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.

]]></text></ref><ref name="update_dialog" syntax="int update_dialog(DIALOG_PLAYER *player);"><xreflist><xref>init_dialog</xref></xreflist><shortdesc>Low level function to update a dialog player.</shortdesc><text><![CDATA[   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-&gt;obj field.

]]></text></ref><ref name="shutdown_dialog" syntax="int shutdown_dialog(DIALOG_PLAYER *player);"><xreflist><xref>init_dialog</xref></xreflist><shortdesc>Destroys a dialog player returned by init_dialog().</shortdesc><text><![CDATA[   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()).

]]></text></ref><ref name="active_dialog" syntax="extern DIALOG *active_dialog;"><xreflist><xref>do_dialog</xref><xref>init_dialog</xref><xref>broadcast_dialog_message</xref></xreflist><shortdesc>Global pointer to the most recent activated dialog.</shortdesc><text><![CDATA[   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.

]]></text></ref></reflist></section><section title="GUI menus"><xreflist><xref>do_menu</xref><xref>d_menu_proc</xref><xref>gui_menu_draw_menu</xref></xreflist><text><![CDATA[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 '&amp;' 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.

]]></text><reflist><ref name="do_menu" syntax="int do_menu(MENU *menu, int x, int y);"><xreflist><xref>GUI menus</xref><xref>d_menu_proc</xref><xref>active_menu</xref><xref>gui_menu_draw_menu</xref><xref>update_menu</xref></xreflist><shortdesc>Displays an animates a popup menu.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="init_menu" syntax="MENU_PLAYER *init_menu(MENU *menu, int x, int y);"><xreflist><xref>update_menu</xref><xref>shutdown_menu</xref><xref>do_menu</xref></xreflist><shortdesc>Low level initialisation of a menu.</shortdesc><text><![CDATA[   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:
<pre class="code">
      MENU_PLAYER *player = init_menu(menu, x, y);

      while (update_menu(player))
	 ;

      return shutdown_menu(player);</pre>

]]></text></ref><ref name="update_menu" syntax="int update_menu(MENU_PLAYER *player);"><xreflist><xref>init_menu</xref><xref>shutdown_menu</xref><xref>do_menu</xref></xreflist><shortdesc>Low level function to update a menu player.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="shutdown_menu" syntax="int shutdown_menu(MENU_PLAYER *player);"><xreflist><xref>init_menu</xref><xref>update_menu</xref></xreflist><shortdesc>Destroys a menu player object returned by init_menu().</shortdesc><text><![CDATA[   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()).

]]></text></ref><ref name="active_menu" syntax="extern MENU *active_menu;"><xreflist><xref>GUI menus</xref></xreflist><ereflist><eref>exgui</eref></ereflist><shortdesc>Global pointer to the most recent activated menu.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="gui_menu_draw_menu" syntax="extern void (*gui_menu_draw_menu)(int x, int y, int w, int h);"/><ref name="gui_menu_draw_menu_item" syntax="extern void (*gui_menu_draw_menu_item)(MENU *m, int x, int y, int w, int h, int bar, int sel);"><xreflist><xref>GUI menus</xref></xreflist><shortdesc>Hooks to modify the appearance of menus.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="alert" syntax="int alert(const char *s1, *s2, *s3, const char *b1, *b2, int c1, c2);"><xreflist><xref>alert3</xref><xref>gui_fg_color</xref></xreflist><ereflist><eref>exgui</eref><eref>expackf</eref><eref>exspline</eref></ereflist><shortdesc>Displays a popup alert box.</shortdesc><text><![CDATA[   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:
<pre class="code">
      if (!exists(CONFIG_FILE))
	 alert(CONFIG_FILE, "not found.", "Using defaults.",
	       "&amp;Continue", NULL, 'c', 0);</pre>
]]></text><retval><text><![CDATA[   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).

]]></text></retval></ref><ref name="alert3" syntax="int alert3(const char *s1, *s2, *s3, const char *b1, *b2, *b3, int c1, c2, c3);"><xreflist><xref>alert</xref><xref>gui_fg_color</xref></xreflist><shortdesc>Like alert(), but with three buttons.</shortdesc><text><![CDATA[   Like alert(), but with three buttons. Returns 1, 2, or 3.

]]></text></ref><ref name="file_select_ex" syntax="int file_select_ex(const char *message, char *path, const char *ext, int size, int w, int h);"><xreflist><xref>gui_fg_color</xref></xreflist><shortdesc>Displays the Allegro file selector with a caption.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="gfx_mode_select" syntax="int gfx_mode_select(int *card, int *w, int *h);"><xreflist><xref>gfx_mode_select_ex</xref><xref>gfx_mode_select_filter</xref><xref>set_gfx_mode</xref><xref>gui_fg_color</xref></xreflist><shortdesc>Displays the Allegro graphics mode selection dialog.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="gfx_mode_select_ex" syntax="int gfx_mode_select_ex(int *card, int *w, int *h, int *color_depth);"><xreflist><xref>gfx_mode_select</xref><xref>gfx_mode_select_filter</xref><xref>set_color_depth</xref><xref>set_gfx_mode</xref><xref>gui_fg_color</xref></xreflist><ereflist><eref>ex3d</eref><eref>exscn3d</eref><eref>exswitch</eref><eref>exupdate</eref><eref>exzbuf</eref></ereflist><shortdesc>Extended version of the graphics mode selection dialog.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="gfx_mode_select_filter" syntax="int gfx_mode_select_filter(int *card, int *w, int *h, int *color_depth, int (*filter)(int, int, int, int));"><xreflist><xref>gfx_mode_select</xref><xref>gfx_mode_select_ex</xref><xref>set_color_depth</xref><xref>set_gfx_mode</xref><xref>gui_fg_color</xref></xreflist><shortdesc>Even more extended version of the graphics mode selection dialog.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="gui_shadow_box_proc" syntax="extern int (*gui_shadow_box_proc)(int msg, struct DIALOG *d, int c);"/><ref name="gui_ctext_proc" syntax="extern int (*gui_ctext_proc)(int msg, struct DIALOG *d, int c);"/><ref name="gui_button_proc" syntax="extern int (*gui_button_proc)(int msg, struct DIALOG *d, int c);"/><ref name="gui_edit_proc" syntax="extern int (*gui_edit_proc)(int msg, struct DIALOG *d, int c);"/><ref name="gui_list_proc" syntax="extern int (*gui_list_proc)(int msg, struct DIALOG *d, int c);"/><ref name="gui_text_list_proc" syntax="extern int (*gui_text_list_proc)(int msg, struct DIALOG *d, int c);"><xreflist><xref>alert</xref><xref>alert3</xref><xref>file_select_ex</xref><xref>gfx_mode_select</xref><xref>gui_fg_color</xref></xreflist><shortdesc>Hooks to customise the look and feel of Allegro dialogs.</shortdesc><text><![CDATA[   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.


]]></text></ref></reflist></section></section></section><section title="Platform specifics"><section title="DOS specifics"><text><![CDATA[
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.

]]></text><reflist><ref name="JOY_TYPE_" syntax="Drivers JOY_TYPE_*/DOS"><xreflist><xref>install_joystick</xref></xreflist><shortdesc>Supported DOS joystick drivers.</shortdesc><text><![CDATA[   The DOS library supports the following type parameters for the
   install_joystick() function:
<ul><li>
   JOY_TYPE_AUTODETECT<br>
      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.
<li>
   JOY_TYPE_NONE<br>
      Dummy driver for machines without any joystick.
<li>
   JOY_TYPE_STANDARD<br>
      A normal two button stick.
<li>
   JOY_TYPE_2PADS<br>
      Dual joystick mode (two sticks, each with two buttons).
<li>
   JOY_TYPE_4BUTTON<br>
      Enable the extra buttons on a 4-button joystick.
<li>
   JOY_TYPE_6BUTTON<br>
      Enable the extra buttons on a 6-button joystick.
<li>
   JOY_TYPE_8BUTTON<br>
      Enable the extra buttons on an 8-button joystick.
<li>
   JOY_TYPE_FSPRO<br>
      CH Flightstick Pro or compatible stick, which provides four buttons,
      an analogue throttle control, and a 4-direction coolie hat.
<li>
   JOY_TYPE_WINGEX<br>
      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).
<li>
   JOY_TYPE_SIDEWINDER<br>
      The Microsoft Sidewinder digital pad (supports up to four controllers,
      each with ten buttons and a digital direction control).
<li>
   JOY_TYPE_SIDEWINDER_AG<br>
      An alternative driver to JOY_TYPE_SIDEWINDER.
      Try this if your Sidewinder isn't recognized with JOY_TYPE_SIDEWINDER.
<li>
   JOY_TYPE_SIDEWINDER_PP<br>
      The Microsoft Sidewinder 3D/Precision/Force Feedback Pro joysticks.
<li>
   JOY_TYPE_GAMEPAD_PRO<br>
      The Gravis GamePad Pro (supports up to two controllers, each with ten
      buttons and a digital direction control).
<li>
   JOY_TYPE_GRIP<br>
      Gravis GrIP driver, using the grip.gll driver file.
<li>
   JOY_TYPE_GRIP4<br>
      Version of the Gravis GrIP driver that is constrained to only move
      along the four main axes.
<li>
   JOY_TYPE_SNESPAD_LPT1<br>
   JOY_TYPE_SNESPAD_LPT2<br>
   JOY_TYPE_SNESPAD_LPT3<br>
      SNES joypads connected to LPT1, LPT2, and LPT3 respectively.
<li>
   JOY_TYPE_PSXPAD_LPT1<br>
   JOY_TYPE_PSXPAD_LPT2<br>
   JOY_TYPE_PSXPAD_LPT3<br>
      PSX joypads connected to LPT1, LPT2, and LPT3 respectively. See
      <a href="http://www.ziplabel.com/dpadpro/index.html">http://www.ziplabel.com/dpadpro/index.html</a> 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.
<li>
   JOY_TYPE_N64PAD_LPT1<br>
   JOY_TYPE_N64PAD_LPT2<br>
   JOY_TYPE_N64PAD_LPT3<br>
      N64 joypads connected to LPT1, LPT2, and LPT3 respectively. See
      <a href="http://www.st-hans.de/N64.htm">http://www.st-hans.de/N64.htm</a> for information about the
      necessary hardware adaptor. 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 noticable 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%.
<li>
   JOY_TYPE_DB9_LPT1<br>
   JOY_TYPE_DB9_LPT2<br>
   JOY_TYPE_DB9_LPT3<br>
      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.
<li>
   JOY_TYPE_TURBOGRAFIX_LPT1<br>
   JOY_TYPE_TURBOGRAFIX_LPT2<br>
   JOY_TYPE_TURBOGRAFIX_LPT3<br>
      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
      <a href="http://www.burg-halle.de/~schwenke/parport.html">http://www.burg-halle.de/~schwenke/parport.html</a> for details
      on how to build this.
<li>
   JOY_TYPE_WINGWARRIOR<br>
      A Wingman Warrior joystick.
<li>
   JOY_TYPE_IFSEGA_ISA<br>
   JOY_TYPE_IFSEGA_PCI<br>
   JOY_TYPE_IFSEGA_PCI_FAST<br>
      Drivers for the IF-SEGA joystick interface cards by the IO-DATA
      company (these come in PCI, PCI2, and ISA variants).
</ul>
]]></text></ref><ref name="GFX_" syntax="Drivers GFX_*/DOS"><xreflist><xref>set_gfx_mode</xref></xreflist><shortdesc>Supported DOS graphic drivers.</shortdesc><text><![CDATA[   The DOS library supports the following card parameters for the
   set_gfx_mode() function:
<ul><li>
   GFX_TEXT<br>
      Return to text mode.
<li>
   GFX_AUTODETECT<br>
      Let Allegro pick an appropriate graphics driver.
<li>
   GFX_AUTODETECT_FULLSCREEN<br>
      Autodetects a graphics driver, but will only use fullscreen drivers,
      failing if these are not available on current platform.
<li>
   GFX_AUTODETECT_WINDOWED<br>
      Same as above, but uses only windowed drivers. This will always fail
      under DOS.
<li>
   GFX_SAFE<br>
      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.
<li>
   GFX_VGA<br>
      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).
<li>
   GFX_MODEX<br>
      Mode-X will work on any VGA card, and provides a range of different
      256-color tweaked resolutions.
<ul><li>
      Stable mode-X resolutions:
<ul><li>
	 Square aspect ratio: 320x240
<li>
	 Skewed aspect ratio: 256x224, 256x240, 320x200, 320x400,
			      320x480, 320x600, 360x200, 360x240,
			      360x360, 360x400, 360x480
</ul>
	 These have worked on every card/monitor that I've tested.
<li>
      Unstable mode-X resolutions:
<ul><li>
	 Square aspect ratio: 360x270, 376x282, 400x300
<li>
	 Skewed aspect ratio: 256x200, 256x256, 320x350, 360x600,
			      376x308, 376x564, 400x150, 400x600
</ul>
	 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."
</ul>
      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.
<li>
   GFX_VESA1<br>
      Use the VESA 1.x driver.
<li>
   GFX_VESA2B<br>
      Use the VBE 2.0 banked mode driver.
<li>
   GFX_VESA2L<br>
      Use the VBE 2.0 linear framebuffer driver.
<li>
   GFX_VESA3<br>
      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.
<li>
   GFX_VBEAF<br>
      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.
<li>
   GFX_XTENDED<br>
      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().
</ul>
   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.
]]></text></ref><ref name="DIGI_" syntax="Drivers DIGI_*/DOS"><xreflist><xref>detect_digi_driver</xref><xref>install_sound</xref><xref>install_sound_input</xref></xreflist><shortdesc>Supported DOS digital sound drivers.</shortdesc><text><![CDATA[   The DOS sound functions support the following digital soundcards:
<pre class="text">
      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</pre>

]]></text></ref><ref name="MIDI_" syntax="Drivers MIDI_*/DOS"><xreflist><xref>detect_midi_driver</xref><xref>install_sound</xref><xref>install_sound_input</xref></xreflist><shortdesc>Supported DOS MIDI sound drivers.</shortdesc><text><![CDATA[   The DOS sound functions support the following MIDI soundcards:
<pre class="text">
      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)</pre>

]]></text></ref></reflist><section title="DOS integration routines"><reflist><ref name="i_love_bill" syntax="extern int i_love_bill;"><xreflist><xref>install_timer</xref><xref>allegro_init</xref><xref>os_type</xref></xreflist><shortdesc>Tells if Allegro has to used fixed rate timers.</shortdesc><text><![CDATA[   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.



]]></text></ref></reflist></section></section><section title="Windows specifics"><text><![CDATA[
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.

]]></text><reflist><ref name="JOY_TYPE_" syntax="Drivers JOY_TYPE_*/Windows"><xreflist><xref>install_joystick</xref></xreflist><shortdesc>Supported Windows joystick drivers.</shortdesc><text><![CDATA[   The Windows library supports the following type parameters for the
   install_joystick() function:
<ul><li>
   JOY_TYPE_AUTODETECT<br>
      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.
<li>
   JOY_TYPE_NONE<br>
      Dummy driver for machines without any joystick.
<li>
   JOY_TYPE_DIRECTX<br>
      Use DirectInput to access the joystick.
<li>
   JOY_TYPE_WIN32<br>
      Use the regular Win32 interface rather than DirectInput to access the
      joystick.
</ul>

]]></text></ref><ref name="GFX_" syntax="Drivers GFX_*/Windows"><xreflist><xref>set_gfx_mode</xref></xreflist><shortdesc>Supported Windows graphic drivers.</shortdesc><text><![CDATA[   The Windows library supports the following card parameters for the
   set_gfx_mode() function:
<ul><li>
   GFX_TEXT<br>
      This closes any graphics mode previously opened with set_gfx_mode.
<li>
   GFX_AUTODETECT<br>
      Let Allegro pick an appropriate graphics driver.
<li>
   GFX_AUTODETECT_FULLSCREEN<br>
      Autodetects a graphics driver, but will only use fullscreen drivers,
      failing if these are not available on current platform.
<li>
   GFX_AUTODETECT_WINDOWED<br>
      Same as above, but uses only windowed drivers.
<li>
   GFX_SAFE<br>
      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.
<li>
   GFX_DIRECTX<br>
      Alias for GFX_DIRECTX_ACCEL.
<li>
   GFX_DIRECTX_ACCEL<br>
      The regular fullscreen DirectX driver, running with hardware
      acceleration enabled.
<li>
   GFX_DIRECTX_SOFT<br>
      DirectX fullscreen driver that only uses software drawing, rather than
      any hardware accelerated features.
<li>
   GFX_DIRECTX_SAFE<br>
      Simplified fullscreen DirectX driver that doesn't support any hardware
      acceleration, video or system bitmaps, etc.
<li>
   GFX_DIRECTX_WIN<br>
      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:
<pre class="code">
	 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 */
	 }
</pre>
      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.
<li>
   GFX_DIRECTX_OVL<br>
      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:
<pre class="code">
	 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 */
	 }</pre>
<li>
   GFX_GDI<br>
      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).
</ul>
]]></text></ref><ref name="DIGI_" syntax="Drivers DIGI_*/Windows"><xreflist><xref>detect_digi_driver</xref><xref>install_sound</xref><xref>install_sound_input</xref></xreflist><shortdesc>Supported Windows digital sound drivers.</shortdesc><text><![CDATA[   The Windows sound functions support the following digital soundcards:
<pre class="text">
      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</pre>

]]></text></ref><ref name="MIDI_" syntax="Drivers MIDI_*/Windows"><xreflist><xref>detect_midi_driver</xref><xref>install_sound</xref><xref>install_sound_input</xref></xreflist><shortdesc>Supported Windows MIDI sound drivers.</shortdesc><text><![CDATA[   The Windows sound functions support the following MIDI soundcards:
<pre class="text">
      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</pre>

]]></text></ref></reflist><section title="Windows integration routines"><text><![CDATA[
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.

]]></text><reflist><ref name="win_get_window" syntax="HWND win_get_window(void);"><shortdesc>Retrieves a handle to the window used by Allegro.</shortdesc><text><![CDATA[   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).

]]></text></ref><ref name="win_set_window" syntax="void win_set_window(HWND wnd);"><shortdesc>Registers an user-created window to be used by Allegro.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="win_set_wnd_create_proc" syntax="void win_set_wnd_create_proc(HWND (*proc)(WNDPROC));"><shortdesc>Registers a custom procedure to be used by Allegro for creating its window.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="win_get_dc" syntax="HDC win_get_dc(BITMAP *bmp);"><shortdesc>Retrieves a handle to the device context.</shortdesc><text><![CDATA[   Retrieves a handle to the device context of a DirectX video or system
   bitmap.

]]></text></ref><ref name="win_release_dc" syntax="void win_release_dc(BITMAP *bmp, HDC dc);"><shortdesc>Releases a handle to the device context.</shortdesc><text><![CDATA[   Releases a handle to the device context of the bitmap that was
   previously retrieved with win_get_dc().

]]></text></ref></reflist></section><section title="GDI routines"><text><![CDATA[
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.

]]></text><reflist><ref name="set_gdi_color_format" syntax="void set_gdi_color_format(void);"><shortdesc>Tells Allegro to use the GDI color layout for truecolor images.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="set_palette_to_hdc" syntax="void set_palette_to_hdc(HDC dc, PALETTE pal);"><shortdesc>Selects and realizes a palette on the specified device context.</shortdesc><text><![CDATA[   Selects and realizes an Allegro palette on the specified device context.

]]></text></ref><ref name="convert_palette_to_hpalette" syntax="HPALETTE convert_palette_to_hpalette(PALETTE pal);"><xreflist><xref>convert_hpalette_to_palette</xref></xreflist><shortdesc>Converts an Allegro palette to a Windows palette.</shortdesc><text><![CDATA[   Converts an Allegro palette to a Windows palette and returns a handle to
   it. You should call DeleteObject() when you no longer need it.

]]></text></ref><ref name="convert_hpalette_to_palette" syntax="void convert_hpalette_to_palette(HPALETTE hpal, PALETTE pal);"><xreflist><xref>convert_palette_to_hpalette</xref></xreflist><shortdesc>Converts a Windows palette to an Allegro palette.</shortdesc><text><![CDATA[   Converts a Windows palette to an Allegro palette.

]]></text></ref><ref name="convert_bitmap_to_hbitmap" syntax="HBITMAP convert_bitmap_to_hbitmap(BITMAP *bitmap);"><xreflist><xref>convert_hbitmap_to_bitmap</xref></xreflist><shortdesc>Converts an Allegro memory bitmap to a Windows DDB.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="convert_hbitmap_to_bitmap" syntax="BITMAP *convert_hbitmap_to_bitmap(HBITMAP bitmap);"><xreflist><xref>convert_bitmap_to_hbitmap</xref></xreflist><shortdesc>Creates an Allegro memory bitmap from a Windows DDB.</shortdesc><text><![CDATA[   Creates an Allegro memory bitmap from a Windows DDB.

]]></text></ref><ref name="draw_to_hdc" syntax="void draw_to_hdc(HDC dc, BITMAP *bitmap, int x, int y);"><xreflist><xref>blit_to_hdc</xref><xref>stretch_blit_to_hdc</xref><xref>draw_sprite</xref></xreflist><shortdesc>Draws an Allegro bitmap to a Windows device context.</shortdesc><text><![CDATA[   Draws an entire Allegro bitmap to a Windows device context, using the
   same parameters as the draw_sprite() function.

]]></text></ref><ref name="blit_to_hdc" syntax="void blit_to_hdc(BITMAP *bitmap, HDC dc, int sx, sy, dx, dy, w, h);"><xreflist><xref>draw_to_hdc</xref><xref>stretch_blit_to_hdc</xref><xref>blit_from_hdc</xref><xref>blit</xref></xreflist><shortdesc>Blits an Allegro memory bitmap to a Windows device context.</shortdesc><text><![CDATA[   Blits an Allegro memory bitmap to a Windows device context, using the
   same parameters as the blit() function.

]]></text></ref><ref name="stretch_blit_to_hdc" syntax="void stretch_blit_to_hdc(BITMAP *bitmap, HDC dc, int sx, sy, sw, sh, int dx, dy, dw, dh);"><xreflist><xref>draw_to_hdc</xref><xref>blit_to_hdc</xref><xref>stretch_blit_from_hdc</xref><xref>stretch_blit</xref></xreflist><shortdesc>Blits an Allegro memory bitmap to a Windows device context.</shortdesc><text><![CDATA[   Blits an Allegro memory bitmap to a Windows device context, using the
   same parameters as the stretch_blit() function.

]]></text></ref><ref name="blit_from_hdc" syntax="void blit_from_hdc(HDC hdc, BITMAP *bitmap, int sx, sy, dx, dy, w, h);"><xreflist><xref>stretch_blit_from_hdc</xref><xref>blit_to_hdc</xref><xref>blit</xref></xreflist><shortdesc>Blits from a Windows device context to an Allegro memory bitmap.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="stretch_blit_from_hdc" syntax="void stretch_blit_from_hdc(HDC hcd, BITMAP *bitmap, int sx, sy, sw, sh, int dx, dy, dw, dh);"><xreflist><xref>blit_from_hdc</xref><xref>stretch_blit_to_hdc</xref><xref>stretch_blit</xref></xreflist><shortdesc>Blits from a Windows device context to an Allegro memory bitmap.</shortdesc><text><![CDATA[   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.

]]></text></ref></reflist></section></section><section title="Unix specifics"><text><![CDATA[
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:
<pre class="text">
   ./allegro.cfg
   $ALLEGRO/allegro.cfg
   ~/allegro.cfg
   ~/.allegrorc
   /etc/allegro.cfg
   /etc/allegrorc
</pre>
Binary resources like the language translation files packfile (language.dat)
are looked for in:
<pre class="text">
   ./language.dat
   $ALLEGRO/language.dat
   ~/language.dat
   /etc/language.dat
   /usr/share/allegro/language.dat
   /usr/local/share/allegro/language.dat
</pre>
Note that if you have installed Allegro from the source distribution with
the typical `<tt>make install</tt>', 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:
<pre class="text">
   strace program 2>&amp;1|egrep "(open|stat)"
</pre>
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 `<tt>2>&amp;1</tt>'.
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'.

]]></text><reflist><ref name="JOY_TYPE_" syntax="Drivers JOY_TYPE_*/Linux"><xreflist><xref>install_joystick</xref></xreflist><shortdesc>Supported Linux joystick drivers.</shortdesc><text><![CDATA[   The Linux library supports the following type parameters for the
   install_joystick() function:
<ul><li>
   JOY_TYPE_AUTODETECT<br>
      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.
<li>
   JOY_TYPE_NONE<br>
      Dummy driver for machines without any joystick.
<li>
   JOY_TYPE_LINUX_ANALOGUE<br>
      Regular joystick interface. Joystick support needs to be enabled in your
      kernel.
</ul>

]]></text></ref><ref name="GFX_" syntax="Drivers GFX_*/Linux"><xreflist><xref>set_gfx_mode</xref><xref>GFX_*/X</xref></xreflist><shortdesc>Supported Linux console graphic drivers.</shortdesc><text><![CDATA[   When running in Linux console mode, Allegro supports the following card
   parameters for the set_gfx_mode() function:
<ul><li>
   GFX_TEXT<br>
      Return to text mode.
<li>
   GFX_AUTODETECT<br>
      Let Allegro pick an appropriate graphics driver.
<li>
   GFX_AUTODETECT_FULLSCREEN<br>
      Autodetects a graphics driver, but will only use fullscreen drivers,
      failing if these are not available on current platform.
<li>
   GFX_AUTODETECT_WINDOWED<br>
      Same as above, but uses only windowed drivers. This will always fail
      under Linux console mode.
<li>
   GFX_SAFE<br>
      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.
<li>
   GFX_FBCON<br>
      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.
<li>
   GFX_VBEAF<br>
      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.
<li>
   GFX_SVGALIB<br>
      Use the SVGAlib library for graphics output. This requires root
      permissions if your version of SVGAlib requires them.
<li>
   GFX_VGA<br>
   GFX_MODEX<br>
      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.
</ul>
]]></text></ref><ref name="GFX_" syntax="Drivers GFX_*/X"><xreflist><xref>set_gfx_mode</xref><xref>GFX_*/Linux</xref></xreflist><shortdesc>Supported X graphic drivers.</shortdesc><text><![CDATA[   When running in X mode, Allegro supports the following card parameters
   for the set_gfx_mode() function:
<ul><li>
   GFX_TEXT<br>
      This closes any graphics mode previously opened with set_gfx_mode.
<li>
   GFX_AUTODETECT<br>
      Let Allegro pick an appropriate graphics driver.
<li>
   GFX_AUTODETECT_FULLSCREEN<br>
      Autodetects a graphics driver, but will only use fullscreen drivers,
      failing if these are not available on current platform.
<li>
   GFX_AUTODETECT_WINDOWED<br>
      Same as above, but uses only windowed drivers.
<li>
   GFX_SAFE<br>
      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.
<li>
   GFX_XWINDOWS<br>
      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() becaue it cannot be used reliably alongside
      get_mouse_mickeys().
<li>
   GFX_XWINDOWS_FULLSCREEN<br>
      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() becaue it cannot be used reliably alongside
      get_mouse_mickeys().
<li>
   GFX_XDGA2<br>
      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.
<li>
   GFX_XDGA2_SOFT<br>
      The same as GFX_XDGA2, but turns off hardware acceleration support.
      This driver requires root permissions.
</ul>
]]></text></ref><ref name="DIGI_" syntax="Drivers DIGI_*/Unix"><xreflist><xref>detect_digi_driver</xref><xref>install_sound</xref><xref>install_sound_input</xref></xreflist><shortdesc>Supported Unix digital sound drivers.</shortdesc><text><![CDATA[   The Unix sound functions support the following digital soundcards:
<pre class="text">
      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</pre>

]]></text></ref><ref name="MIDI_" syntax="Drivers MIDI_*/Unix"><xreflist><xref>detect_midi_driver</xref><xref>install_sound</xref><xref>install_sound_input</xref></xreflist><shortdesc>Supported Unix MIDI sound drivers.</shortdesc><text><![CDATA[   The Unix sound functions support the following MIDI soundcards:
<pre class="text">
      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</pre>

]]></text></ref></reflist><section title="Unix integration routines"><reflist><ref name="xwin_set_window_name" syntax="void xwin_set_window_name(const char *name, const char *group);"><xreflist><xref>set_window_title</xref></xreflist><shortdesc>Specify the window name and group (or class).</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="allegro_icon" syntax="extern void *allegro_icon;"><shortdesc>Pointer to the Allegro X11 icon.</shortdesc><text><![CDATA[   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.



]]></text></ref></reflist></section></section><section title="BeOS specifics"><text><![CDATA[
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.

]]></text><reflist><ref name="GFX_" syntax="Drivers GFX_*/BeOS"><xreflist><xref>set_gfx_mode</xref></xreflist><shortdesc>Supported BeOS graphic drivers.</shortdesc><text><![CDATA[   BeOS Allegro supports the following card parameters for the
   set_gfx_mode() function:
<ul><li>
   GFX_TEXT<br>
      This closes any graphics mode previously opened with set_gfx_mode.
<li>
   GFX_AUTODETECT<br>
      Let Allegro pick an appropriate graphics driver.
<li>
   GFX_AUTODETECT_FULLSCREEN<br>
      Autodetects a graphics driver, but will only use fullscreen drivers,
      failing if these are not available on current platform.
<li>
   GFX_AUTODETECT_WINDOWED<br>
      Same as above, but uses only windowed drivers.
<li>
   GFX_SAFE<br>
      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.
<li>
   GFX_BWINDOWSCREEN_ACCEL<br>
      Fullscreen exclusive mode. Supports only resolutions higher or equal
      to 640x480, and uses hardware acceleration if available.
<li>
   GFX_BWINDOWSCREEN<br>
      Works the same as GFX_BWINDOWSCREEN_ACCEL, but disables acceleration.
<li>
   GFX_BDIRECTWINDOW<br>
      Fast windowed mode using the BDirectWindow class. Not all graphics
      cards support this.
<li>
   GFX_BWINDOW<br>
      Normal windowed mode using the BWindow class. Slow but always works.
<li>
   GFX_BWINDOW_OVERLAY<br>
      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.
</ul>
]]></text></ref><ref name="DIGI_" syntax="Drivers DIGI_*/BeOS"><xreflist><xref>detect_digi_driver</xref><xref>install_sound</xref><xref>install_sound_input</xref></xreflist><shortdesc>Supported BeOS digital sound drivers.</shortdesc><text><![CDATA[   The BeOS sound functions support the following digital soundcards:
<pre class="text">
      DIGI_AUTODETECT      - let Allegro pick a digital sound driver
      DIGI_NONE            - no digital sound
      DIGI_BEOS            - BeOS digital output</pre>

]]></text></ref><ref name="MIDI_" syntax="Drivers MIDI_*/BeOS"><xreflist><xref>detect_midi_driver</xref><xref>install_sound</xref><xref>install_sound_input</xref></xreflist><shortdesc>Supported BeOS MIDI sound drivers.</shortdesc><text><![CDATA[   The BeOS sound functions support the following MIDI soundcards:
<pre class="text">
      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
</pre>


]]></text></ref></reflist></section><section title="QNX specifics"><text><![CDATA[
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.

]]></text><reflist><ref name="GFX_" syntax="Drivers GFX_*/QNX"><xreflist><xref>set_gfx_mode</xref></xreflist><shortdesc>Supported QNX graphic drivers.</shortdesc><text><![CDATA[   QNX Allegro supports the following card parameters for the
   set_gfx_mode() function:
<ul><li>
   GFX_TEXT<br>
      This closes any graphics mode previously opened with set_gfx_mode.
<li>
   GFX_AUTODETECT<br>
      Let Allegro pick an appropriate graphics driver.
<li>
   GFX_AUTODETECT_FULLSCREEN<br>
      Autodetects a graphics driver, but will only use fullscreen drivers,
      failing if these are not available on current platform.
<li>
   GFX_AUTODETECT_WINDOWED<br>
      Same as above, but uses only windowed drivers.
<li>
   GFX_SAFE<br>
      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.
<li>
   GFX_PHOTON<br>
      Alias for GFX_PHOTON_ACCEL.
<li>
   GFX_PHOTON_ACCEL<br>
      Fullscreen exclusive mode through Photon, running with hardware
      acceleration enabled.
<li>
   GFX_PHOTON_SOFT<br>
      Fullscreen exclusive mode that only uses software drawing, rather than
      any hardware accelerated features.
<li>
   GFX_PHOTON_SAFE<br>
      Simplified fullscreen exclusive driver that doesn't support any
      hardware acceleration, video or system bitmaps, etc.
<li>
   GFX_PHOTON_WIN<br>
      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.
</ul>
]]></text></ref><ref name="DIGI_" syntax="Drivers DIGI_*/QNX"><xreflist><xref>detect_digi_driver</xref><xref>install_sound</xref><xref>install_sound_input</xref></xreflist><shortdesc>Supported QNX digital sound drivers.</shortdesc><text><![CDATA[   The QNX sound functions support the following digital soundcards:
<pre class="text">
      DIGI_AUTODETECT      - let Allegro pick a digital sound driver
      DIGI_NONE            - no digital sound
      DIGI_ALSA            - ALSA sound driver</pre>

]]></text></ref><ref name="MIDI_" syntax="Drivers MIDI_*/QNX"><xreflist><xref>detect_midi_driver</xref><xref>install_sound</xref><xref>install_sound_input</xref></xreflist><shortdesc>Supported QNX MIDI sound drivers.</shortdesc><text><![CDATA[   The QNX sound functions support the following MIDI soundcards:
<pre class="text">
      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
</pre>

]]></text></ref></reflist><section title="QNX integration routines"><text><![CDATA[
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.

]]></text><reflist><ref name="qnx_get_window" syntax="PtWidget_t qnx_get_window(void);"><shortdesc>Retrieves a handle to the window used by Allegro.</shortdesc><text><![CDATA[   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).



]]></text></ref></reflist></section></section><section title="MacOS X specifics"><text><![CDATA[
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 enduser, 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.

]]></text><reflist><ref name="GFX_" syntax="Drivers GFX_*/MacOSX"><xreflist><xref>set_gfx_mode</xref></xreflist><shortdesc>Supported MacOSX graphic drivers.</shortdesc><text><![CDATA[   MacOS X Allegro supports the following card parameters for the
   set_gfx_mode() function:
<ul><li>
   GFX_TEXT<br>
      This closes any graphics mode previously opened with set_gfx_mode.
<li>
   GFX_AUTODETECT<br>
      Let Allegro pick an appropriate graphics driver.
<li>
   GFX_AUTODETECT_FULLSCREEN<br>
      Autodetects a graphics driver, but will only use fullscreen drivers,
      failing if these are not available on current platform.
<li>
   GFX_AUTODETECT_WINDOWED<br>
      Same as above, but uses only windowed drivers.
<li>
   GFX_SAFE<br>
      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.
<li>
   GFX_QUARTZ_FULLSCREEN<br>
      Fullscreen exclusive mode, using the CGDirectDisplay interface.
      Supports only resolutions higher or equal to 640x480, and uses
      hardware acceleration if available.
<li>
   GFX_QUARTZ_WINDOW<br>
      Windowed mode using QuickDraw in a Cocoa window.
</ul>
]]></text></ref><ref name="DIGI_" syntax="Drivers DIGI_*/MacOSX"><xreflist><xref>detect_digi_driver</xref><xref>install_sound</xref><xref>install_sound_input</xref></xreflist><shortdesc>Supported MacOSX digital sound drivers.</shortdesc><text><![CDATA[   The MacOS X sound functions support the following digital soundcards:
<pre class="text">
      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
</pre>

]]></text></ref><ref name="MIDI_" syntax="Drivers MIDI_*/MacOSX"><xreflist><xref>detect_midi_driver</xref><xref>install_sound</xref><xref>install_sound_input</xref></xreflist><shortdesc>Supported MacOSX MIDI sound drivers.</shortdesc><text><![CDATA[   The MacOS X sound functions support the following MIDI soundcards:
<pre class="text">
      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
</pre>


]]></text></ref></reflist></section><section title="Differences between platforms"><text><![CDATA[
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:

<b>ALLEGRO_PLATFORM_STR</b><br>
   Text string containing the name of the current platform.

<b>ALLEGRO_DOS</b><br>
<b>ALLEGRO_DJGPP</b><br>
<b>ALLEGRO_WATCOM</b><br>
<b>ALLEGRO_WINDOWS</b><br>
<b>ALLEGRO_MSVC</b><br>
<b>ALLEGRO_MINGW32</b><br>
<b>ALLEGRO_BCC32</b><br>
<b>ALLEGRO_UNIX</b><br>
<b>ALLEGRO_LINUX</b><br>
<b>ALLEGRO_BEOS</b><br>
<b>ALLEGRO_QNX</b><br>
<b>ALLEGRO_DARWIN</b><br>
<b>ALLEGRO_MACOSX</b><br>
<b>ALLEGRO_GCC</b><br>
   Defined if you are building for a relevant system. Often several of these
   will apply, eg. DOS+Watcom, or Windows+GCC+MinGW.

<b>ALLEGRO_AMD64</b><br>
<b>ALLEGRO_I386</b><br>
<b>ALLEGRO_BIG_ENDIAN</b><br>
<b>ALLEGRO_LITTLE_ENDIAN</b><br>
   Defined if you are building for a processor of the relevant type.

<b>ALLEGRO_MULTITHREADED</b><br>
   Defined if the library is internally multi-threaded on this system.

<b>ALLEGRO_USE_CONSTRUCTOR</b><br>
   Defined if the compiler supports constructor/destructor functions.

<b>ALLEGRO_VRAM_SINGLE_SURFACE</b><br>
   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).

<b>ALLEGRO_CONSOLE_OK</b><br>
   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.

<b>ALLEGRO_MAGIC_MAIN</b><br>
   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.

<b>ALLEGRO_LFN</b><br>
   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).

<b>LONG_LONG</b><br>
   Defined to whatever represents a 64-bit "long long" integer for the
   current compiler, or not defined if that isn't supported.

<b>OTHER_PATH_SEPARATOR</b><br>
   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.

<b>DEVICE_SEPARATOR</b><br>
   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:

<b>ALLEGRO_NO_MAGIC_MAIN</b><br>
   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.

<b>ALLEGRO_USE_CONSOLE</b><br>
   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).

<b>ALLEGRO_NO_STD_HEADER</b><br>
   If you define this prior to including Allegro headers, Allegro will not
   automatically include some standard headers (eg &lt;stddef.h&gt;) its own
   headers depend upon.

<b>ALLEGRO_NO_KEY_DEFINES</b><br>
   If you define this prior to including Allegro headers, Allegro will omit
   the definition of the KEY_* constants, which may clash with other headers.

<b>ALLEGRO_NO_FIX_ALIASES</b><br>
   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.

<b>ALLEGRO_NO_FIX_CLASS</b><br>
   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.

<b>ALLEGRO_NO_VHLINE_ALIAS</b><br>
   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 noticable 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.

<b>ALLEGRO_NO_CLEAR_BITMAP_ALIAS</b><br>
   If you define this prior to including Allegro headers, Allegro will not
   define the clear() backwards compatibility alias to clear_bitmap().

<b>ALLEGRO_NO_COMPATIBILITY</b><br>
   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:

<b>INLINE</b><br>
   Use this in place of the regular "inline" function modifier keyword, and
   your code will work correctly on any of the supported compilers.

<b>RET_VOLATILE</b><br>
   Use this to declare a function with a volatile return value.

<b>ZERO_SIZE_ARRAY(type, name)</b><br>
   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.

<b>AL_CONST</b><br>
   Use this in place of the regular "const" object modifier keyword, and
   your code will work correctly on any of the supported compilers.

<b>AL_RAND()</b><br>
   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.



]]></text></section></section><section title="Miscellaneous"><section title="Reducing your executable size"><text><![CDATA[
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:
<ul><li>
For all platforms, you can use an executable compressor called UPX, which
is available at <a href="http://upx.sourceforge.net/">http://upx.sourceforge.net/</a>. This usually manages a
compression ratio of about 40%.
<li>
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!
<li>
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:
<pre class="code">
   BEGIN_GFX_DRIVER_LIST
      driver1
      driver2
      etc...
   END_GFX_DRIVER_LIST
</pre>
where the driver names are any of the defines:
<pre class="text">
   GFX_DRIVER_VBEAF
   GFX_DRIVER_VGA
   GFX_DRIVER_MODEX
   GFX_DRIVER_VESA3
   GFX_DRIVER_VESA2L
   GFX_DRIVER_VESA2B
   GFX_DRIVER_XTENDED
   GFX_DRIVER_VESA1
</pre>
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.
<li>
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:
<pre class="code">
   BEGIN_COLOR_DEPTH_LIST
      depth1
      depth2
      etc...
   END_COLOR_DEPTH_LIST
</pre>
where the color depth names are any of the defines:
<pre class="text">
   COLOR_DEPTH_8
   COLOR_DEPTH_15
   COLOR_DEPTH_16
   COLOR_DEPTH_24
   COLOR_DEPTH_32
</pre>
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!
<li>
In the same way as the above, you can specify which DOS sound drivers you
want to support with the code:
<pre class="code">
   BEGIN_DIGI_DRIVER_LIST
      driver1
      driver2
      etc...
   END_DIGI_DRIVER_LIST
</pre>
using the digital sound driver defines:
<pre class="text">
   DIGI_DRIVER_SOUNDSCAPE
   DIGI_DRIVER_AUDIODRIVE
   DIGI_DRIVER_WINSOUNDSYS
   DIGI_DRIVER_SB
</pre>
and for the MIDI music:
<pre class="code">
   BEGIN_MIDI_DRIVER_LIST
      driver1
      driver2
      etc...
   END_MIDI_DRIVER_LIST
</pre>
using the MIDI driver defines:
<pre class="text">
   MIDI_DRIVER_AWE32
   MIDI_DRIVER_DIGMID
   MIDI_DRIVER_ADLIB
   MIDI_DRIVER_MPU
   MIDI_DRIVER_SB_OUT
</pre>
If you are going to use either of these sound driver constructs, you must
include both.
<li>
Likewise for the DOS joystick drivers, you can declare an inclusion list:
<pre class="code">
   BEGIN_JOYSTICK_DRIVER_LIST
      driver1
      driver2
      etc...
   END_JOYSTICK_DRIVER_LIST
</pre>
using the joystick driver defines:
<pre class="text">
   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
</pre>
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.
<li>
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:
<pre class="code">
   #define ALLEGRO_COLOR8
   #define ALLEGRO_COLOR16
   #define ALLEGRO_COLOR24
   #define ALLEGRO_COLOR32
</pre>
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.
</ul>
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.



]]></text></section><section title="Debugging"><text><![CDATA[
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:

]]></text><reflist><ref name="ASSERT" syntax="void ASSERT(condition);"><xreflist><xref>al_assert</xref><xref>TRACE</xref><xref>register_assert_handler</xref></xreflist><ereflist><eref>expackf</eref></ereflist><shortdesc>Debugging helper macro to assert.</shortdesc><text><![CDATA[   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:
<pre class="code">
      #define DEBUGMODE
      #include <allegro.h>
      ...
      void my_blitter(BITMAP *source, int flags)
      {
	 int some_variables;
	 ASSERT(source != NULL);
	 ASSERT(flags &amp; GAME_RUNNING);
         ...
      }</pre>

]]></text></ref><ref name="TRACE" syntax="void TRACE(char *msg, ...);"><xreflist><xref>al_trace</xref><xref>ASSERT</xref><xref>register_trace_handler</xref></xreflist><shortdesc>Debugging helper macro to trace messages.</shortdesc><text><![CDATA[   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:
<pre class="code">
      #define DEBUGMODE
      #include <allegro.h>
      ...
      void my_blitter(BITMAP *source, int flags)
      {
	 static int count_call = 0;
	 TRACE("my_blitter() called %d times.\n", count_call++);
         ...
      }</pre>

]]></text></ref><ref name="register_assert_handler" syntax="void register_assert_handler(int (*handler)(const char *msg));"><xreflist><xref>al_assert</xref><xref>ASSERT</xref><xref>register_trace_handler</xref></xreflist><shortdesc>Registers a custom handler for assert failures.</shortdesc><text><![CDATA[   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. Example:
<pre class="code">
   int show_but_continue(const char *text)
   {
       alert("Uh oh...", "Fasten your seat belts.", text,
	     "&amp;Go on!", NULL, 'g', 0);
       return 1;
   }
   ...
      register_assert(show_but_continue);
      ASSERT(0); /* This won't crash the program now. */</pre>

]]></text></ref><ref name="register_trace_handler" syntax="void register_trace_handler(int (*handler)(const char *msg));"><xreflist><xref>al_trace</xref><xref>TRACE</xref><xref>register_assert_handler</xref></xreflist><shortdesc>Registers a custom handler for trace output.</shortdesc><text><![CDATA[   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. Example:
<pre class="code">
   int network_broadcaster(const char *text)
   {
      int f;

      for (int f = 0; f < connected_clients; f++)
	 send_msg_to_client(client[f], text);

      return 0; /* Let normal tracing occur. */
   }
   ...
      register_trace_handler(network_broadcaster);
      TRACE("Networked tracing activated\n");</pre>

]]></text></ref><ref name="al_assert" syntax="void al_assert(const char *file, int line);"><xreflist><xref>ASSERT</xref><xref>al_trace</xref><xref>register_assert_handler</xref></xreflist><shortdesc>Asserts at the specified file and line number.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="al_trace" syntax="void al_trace(const char *msg, ...);"><xreflist><xref>TRACE</xref><xref>al_assert</xref><xref>register_trace_handler</xref></xreflist><shortdesc>Outputs a debugging trace message.</shortdesc><text><![CDATA[   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.



]]></text></ref></reflist></section><section title="Makefile targets"><text><![CDATA[
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:
<ul><li>
   DEBUGMODE=1<br>
   Selects a debug build, rather than the normal optimised version.
<li>
   DEBUGMODE=2<br>
   Selects a build intended to debug Allegro itself, rather than the
   normal optimised version.
<li>
   PROFILEMODE=1<br>
   Selects a profiling build, rather than the normal optimised version.
<li>
   WARNMODE=1<br>
   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.
<li>
   STATICLINK=1 (MinGW, MSVC, BeOS, MacOS X only)<br>
   Link as a static library, rather than the default dynamic library.
<li>
   STATICRUNTIME=1 (MSVC only)<br>
   Link against static runtime libraries, rather than the default dynamic
   runtime libraries.
<li>
   TARGET_ARCH_COMPAT=[cpu] (GCC-based platforms only)<br>
   This option will optimize for the given processor while maintaining
   compatibility with older processors.
   Example: set TARGET_ARCH_COMPAT=i586
<li>
   TARGET_ARCH_EXCL=[cpu] (GCC-based platforms only)<br>
   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
<li>
   TARGET_OPTS=[opts] (GCC-based platforms only)<br>
   This option allows you to customize general compiler optimisations.
<li>
   TARGET_ARCH_EXCL=[opts] (MSVC only)<br>
   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
<li>
   CROSSCOMPILE=1 (DJGPP, MinGW only)<br>
   Allows you to build the library under Linux by using a cross-compiler.
<li>
   ALLEGRO_USE_C=1 (GCC-based platforms only)<br>
   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.
<li>
   UNIX_TOOLS=1<br>
   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 proces will
   try to autodetect this configuration.
<li>
   COMPILER_MSVC7=1 (MSVC only)<br>
   Enables special optimizations for MSVC 7 (the default is MSVC 6). You don't
   normally need to set this flag since <i>fix.bat msvc7</i> should do the same
   thing and is the prefered way of doing this.
<li>
   COMPILER_ICL=1 (MSVC only)<br>
   Instructs the build process to use the Intel commandline compiler icl rather
   than Microsoft's commandline compiler cl. You don't normally need to pass
   this flag since <i>fix.bat icl</i> should do the same thing and is the
   prefered way of doing this. Do not try COMPILER_MSVC7=1 and COMPILER_ICL=1
   at the same time.
</ul>
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:
<ul><li>
   'info' (Unix only)<br>
   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.
<li>
   'default'<br>
   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.
<li>
   'all' (non-Unix only)<br>
   Compiles all three library versions (optimised, debugging, and
   profiling), builds the test and example programs, and converts the
   documentation files.
<li>
   'lib'<br>
   Compiles the current library version (one of optimised, debugging, or
   profiling, selected by the above environment variables).
<li>
   'modules' (Unix only)<br>
    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.
<li>
   'install'<br>
   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.
<li>
   'install-lib' (Unix only)<br>
   You can use this to install the library and the modules only, without
   documentation or programs.  Use the 'install' target to install
   everything.
<li>
   'installall' (non-Unix only)<br>
   Copies all three library versions (optimised, debugging, and profiling),
   into your compiler lib directory, recompiling them as required, and
   installs the Allegro headers.
<li>
   'uninstall'<br>
   Removes the Allegro library and headers from your compiler directories.
<li>
   'docs'<br>
   Converts the documentation files from the ._tx sources.
<li>
   'chm-docs' (Windows only)<br>
   Creates a compiled HTML file from the previously generated html output.
   This is not a default target, since you need Microsoft's HTML compiler
   (<a href="http://go.microsoft.com/fwlink/?LinkId=14188">http://go.microsoft.com/fwlink/?LinkId=14188</a>),
   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).
<li>
   'docs-dvi' (Unix only)<br>
   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.
<li>
   'docs-ps' or 'docs-gzipped-ps' or 'docs-bzipped-ps' (Unix only)<br>
   Creates a Postcript 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.
<li>
   'docs-pdf' (Unix only)<br>
   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.
<li>
   'docs-devhelp' (Unix only)<br>
   Creates normal HTML documentation with an additional xml index file which
   can be used by tools like Devhelp (<a href="http://www.devhelp.net/">http://www.devhelp.net/</a>) to
   show context sensitive help within any editor using Devhelp, like for
   example <a href="http://anjuta.sourceforge.net/">http://anjuta.sourceforge.net/</a>. The Allegro 'book' will be
   created in `docs/devhelp/allegro.devhelp', you have to install it
   manually.
<li>
   'install-man' (Unix and Mac OS X only)<br>
   Generates Unix man pages for each Allegro function or variable and
   installs them.
<li>
   'install-gzipped-man' or 'install-bzipped-man' (Unix only)<br>
   Like install-man, but also compresses the manual pages after installing
   them (run only one of these).
<li>
   'uninstall-man' (Unix)<br>
   Uninstalls any man pages previously installed with 'install-man',
   'install-gzipped-man', or 'install-bzipped-man'.
<li>
   'install-info' or 'install-gzipped-info' or 'install-bzipped-info'
   (Unix only)<br>
   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).
<li>
   'uninstall-info' (Unix only)<br>
   Uninstalls any man pages previously installed with 'install-info',
   'install-gzipped-info', or 'install-bzipped-info'.
<li>
   'clean'<br>
   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.
<li>
   'distclean'<br>
   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.
<li>
   'veryclean'<br>
   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.
<li>
   'compress' (DJGPP, MinGW and MSVC only)<br>
   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.
<li>
   'depend'<br>
   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.
</ul>



]]></text></section><section title="Available Allegro examples"><text><![CDATA[
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.

]]></text><reflist><ref name="exhello" syntax="Example exhello"><xreflist><xref>END_OF_MAIN</xref><xref>SCREEN_H</xref><xref>SCREEN_W</xref><xref>acquire_screen</xref><xref>allegro_error</xref><xref>allegro_init</xref><xref>allegro_message</xref><xref>clear_to_color</xref><xref>desktop_palette</xref><xref>font</xref><xref>install_keyboard</xref><xref>makecol</xref><xref>readkey</xref><xref>release_screen</xref><xref>screen</xref><xref>set_gfx_mode</xref><xref>set_palette</xref><xref>textout_centre_ex</xref></xreflist><shortdesc>Simple graphical "hello world" program.</shortdesc><text><![CDATA[   This is a very simple program showing how to get into graphics
   mode and draw text onto the screen.

]]></text></ref><ref name="exmem" syntax="Example exmem"><xreflist><xref>BITMAP</xref><xref>END_OF_MAIN</xref><xref>SCREEN_H</xref><xref>SCREEN_W</xref><xref>acquire_screen</xref><xref>allegro_error</xref><xref>allegro_init</xref><xref>allegro_message</xref><xref>blit</xref><xref>circle</xref><xref>clear_bitmap</xref><xref>create_bitmap</xref><xref>desktop_palette</xref><xref>destroy_bitmap</xref><xref>install_keyboard</xref><xref>palette_color</xref><xref>readkey</xref><xref>release_screen</xref><xref>screen</xref><xref>set_gfx_mode</xref><xref>set_palette</xref></xreflist><shortdesc>Drawing onto memory bitmaps and then blitting them to the screen.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="expal" syntax="Example expal"><xreflist><xref>END_OF_MAIN</xref><xref>PALETTE</xref><xref>RGB</xref><xref>SCREEN_H</xref><xref>SCREEN_W</xref><xref>acquire_screen</xref><xref>allegro_error</xref><xref>allegro_init</xref><xref>allegro_message</xref><xref>black_palette</xref><xref>circlefill</xref><xref>install_keyboard</xref><xref>install_mouse</xref><xref>keypressed</xref><xref>release_screen</xref><xref>screen</xref><xref>set_gfx_mode</xref><xref>set_palette</xref><xref>show_mouse</xref></xreflist><shortdesc>Palette effects and color cycling.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="expat" syntax="Example expat"><xreflist><xref>BITMAP</xref><xref>END_OF_MAIN</xref><xref>acquire_bitmap</xref><xref>allegro_error</xref><xref>allegro_init</xref><xref>allegro_message</xref><xref>bitmap_mask_color</xref><xref>blit</xref><xref>clear_to_color</xref><xref>create_bitmap</xref><xref>create_sub_bitmap</xref><xref>desktop_palette</xref><xref>destroy_bitmap</xref><xref>drawing_mode</xref><xref>font</xref><xref>install_keyboard</xref><xref>makecol</xref><xref>masked_blit</xref><xref>palette_color</xref><xref>readkey</xref><xref>rectfill</xref><xref>release_bitmap</xref><xref>screen</xref><xref>set_gfx_mode</xref><xref>set_palette</xref><xref>solid_mode</xref><xref>text_height</xref><xref>text_length</xref><xref>textout_ex</xref></xreflist><shortdesc>Using patterned drawing modes and sub-bitmaps.</shortdesc><text><![CDATA[   This program demonstrates the use of patterned drawing and sub-bitmaps.

]]></text></ref><ref name="exflame" syntax="Example exflame"><xreflist><xref>END_OF_MAIN</xref><xref>PALETTE</xref><xref>SCREEN_H</xref><xref>SCREEN_W</xref><xref>acquire_screen</xref><xref>allegro_error</xref><xref>allegro_init</xref><xref>allegro_message</xref><xref>bmp_read_line</xref><xref>bmp_unwrite_line</xref><xref>bmp_write_line</xref><xref>clear_keybuf</xref><xref>font</xref><xref>getpixel</xref><xref>install_keyboard</xref><xref>keypressed</xref><xref>line</xref><xref>makecol</xref><xref>putpixel</xref><xref>release_screen</xref><xref>screen</xref><xref>set_gfx_mode</xref><xref>set_palette</xref><xref>textout_ex</xref></xreflist><shortdesc>How to write directly to video memory improving performance.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="exdbuf" syntax="Example exdbuf"><xreflist><xref>BITMAP</xref><xref>END_OF_MAIN</xref><xref>SCREEN_H</xref><xref>SCREEN_W</xref><xref>acquire_screen</xref><xref>allegro_error</xref><xref>allegro_init</xref><xref>allegro_message</xref><xref>blit</xref><xref>circlefill</xref><xref>clear_keybuf</xref><xref>clear_to_color</xref><xref>create_bitmap</xref><xref>desktop_palette</xref><xref>destroy_bitmap</xref><xref>font</xref><xref>install_keyboard</xref><xref>install_timer</xref><xref>keypressed</xref><xref>makecol</xref><xref>release_screen</xref><xref>retrace_count</xref><xref>screen</xref><xref>set_gfx_mode</xref><xref>set_palette</xref><xref>textprintf_ex</xref></xreflist><shortdesc>How to use double buffering to avoid flicker.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="exflip" syntax="Example exflip"><xreflist><xref>BITMAP</xref><xref>END_OF_MAIN</xref><xref>SCREEN_H</xref><xref>SCREEN_W</xref><xref>allegro_error</xref><xref>allegro_init</xref><xref>allegro_message</xref><xref>blit</xref><xref>circlefill</xref><xref>clear_keybuf</xref><xref>clear_to_color</xref><xref>create_bitmap</xref><xref>create_video_bitmap</xref><xref>desktop_palette</xref><xref>destroy_bitmap</xref><xref>font</xref><xref>install_keyboard</xref><xref>install_timer</xref><xref>keypressed</xref><xref>makecol</xref><xref>retrace_count</xref><xref>screen</xref><xref>set_gfx_mode</xref><xref>set_palette</xref><xref>show_video_bitmap</xref><xref>textprintf_ex</xref></xreflist><shortdesc>Comparison of double buffering and page flipping.</shortdesc><text><![CDATA[   This program moves a circle across the screen, first with a
   double buffer and then using page flips.

]]></text></ref><ref name="exfixed" syntax="Example exfixed"><xreflist><xref>END_OF_MAIN</xref><xref>allegro_init</xref><xref>allegro_message</xref><xref>fixdiv</xref><xref>fixed</xref><xref>fixmul</xref><xref>fixsqrt</xref><xref>fixtof</xref><xref>ftofix</xref><xref>itofix</xref></xreflist><shortdesc>Using fixed point maths.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="exfont" syntax="Example exfont"><xreflist><xref>END_OF_MAIN</xref><xref>FONT</xref><xref>SCREEN_H</xref><xref>SCREEN_W</xref><xref>acquire_screen</xref><xref>allegro_error</xref><xref>allegro_init</xref><xref>allegro_message</xref><xref>clear_to_color</xref><xref>desktop_palette</xref><xref>destroy_font</xref><xref>extract_font_range</xref><xref>font</xref><xref>install_keyboard</xref><xref>load_font</xref><xref>makecol</xref><xref>merge_fonts</xref><xref>readkey</xref><xref>release_screen</xref><xref>screen</xref><xref>set_gfx_mode</xref><xref>set_palette</xref><xref>textout_centre_ex</xref></xreflist><text><![CDATA[   This is a very simple program showing how to load and manipulate fonts.

]]></text></ref><ref name="exmouse" syntax="Example exmouse"><xreflist><xref>BITMAP</xref><xref>END_OF_MAIN</xref><xref>SCREEN_H</xref><xref>SCREEN_W</xref><xref>acquire_screen</xref><xref>allegro_error</xref><xref>allegro_init</xref><xref>allegro_message</xref><xref>bitmap_mask_color</xref><xref>circle</xref><xref>clear_keybuf</xref><xref>clear_to_color</xref><xref>create_bitmap</xref><xref>desktop_palette</xref><xref>destroy_bitmap</xref><xref>font</xref><xref>get_mouse_mickeys</xref><xref>install_keyboard</xref><xref>install_mouse</xref><xref>install_timer</xref><xref>key</xref><xref>keypressed</xref><xref>makecol</xref><xref>mouse_b</xref><xref>mouse_x</xref><xref>mouse_y</xref><xref>mouse_z</xref><xref>palette_color</xref><xref>poll_mouse</xref><xref>readkey</xref><xref>release_screen</xref><xref>screen</xref><xref>set_gfx_mode</xref><xref>set_mouse_sprite</xref><xref>set_mouse_sprite_focus</xref><xref>set_palette</xref><xref>show_mouse</xref><xref>textout_centre_ex</xref><xref>textout_ex</xref><xref>textprintf_centre_ex</xref><xref>textprintf_ex</xref><xref>vsync</xref></xreflist><shortdesc>Getting input from the mouse.</shortdesc><text><![CDATA[   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 keypress 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.

]]></text></ref><ref name="extimer" syntax="Example extimer"><xreflist><xref>END_OF_FUNCTION</xref><xref>END_OF_MAIN</xref><xref>LOCK_FUNCTION</xref><xref>LOCK_VARIABLE</xref><xref>SCREEN_W</xref><xref>allegro_error</xref><xref>allegro_init</xref><xref>allegro_message</xref><xref>clear_to_color</xref><xref>desktop_palette</xref><xref>font</xref><xref>install_int</xref><xref>install_int_ex</xref><xref>install_keyboard</xref><xref>install_timer</xref><xref>key</xref><xref>keypressed</xref><xref>makecol</xref><xref>readkey</xref><xref>rest</xref><xref>screen</xref><xref>set_gfx_mode</xref><xref>set_palette</xref><xref>textprintf_centre_ex</xref></xreflist><shortdesc>Using the timer (delays and interrupts).</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="exkeys" syntax="Example exkeys"><xreflist><xref>END_OF_FUNCTION</xref><xref>END_OF_MAIN</xref><xref>LOCK_FUNCTION</xref><xref>SCREEN_H</xref><xref>SCREEN_W</xref><xref>acquire_screen</xref><xref>allegro_error</xref><xref>allegro_init</xref><xref>allegro_message</xref><xref>blit</xref><xref>clear_keybuf</xref><xref>clear_to_color</xref><xref>desktop_palette</xref><xref>font</xref><xref>install_keyboard</xref><xref>install_timer</xref><xref>key</xref><xref>key_shifts</xref><xref>keyboard_lowlevel_callback</xref><xref>keypressed</xref><xref>makecol</xref><xref>readkey</xref><xref>rectfill</xref><xref>release_screen</xref><xref>rest</xref><xref>scancode_to_name</xref><xref>screen</xref><xref>set_gfx_mode</xref><xref>set_palette</xref><xref>textprintf_centre_ex</xref><xref>textprintf_ex</xref><xref>ureadkey</xref><xref>usprintf</xref><xref>ustrzncpy</xref></xreflist><shortdesc>How to get input from the keyboard in different ways.</shortdesc><text><![CDATA[   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 scancodes.
   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
   keypresses.
   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.

]]></text></ref><ref name="exjoy" syntax="Example exjoy"><xreflist><xref>BITMAP</xref><xref>END_OF_MAIN</xref><xref>SCREEN_H</xref><xref>SCREEN_W</xref><xref>allegro_error</xref><xref>allegro_init</xref><xref>allegro_message</xref><xref>blit</xref><xref>calibrate_joystick</xref><xref>calibrate_joystick_name</xref><xref>circle</xref><xref>clear_bitmap</xref><xref>clear_keybuf</xref><xref>create_bitmap</xref><xref>default_palette</xref><xref>destroy_bitmap</xref><xref>drawing_mode</xref><xref>font</xref><xref>install_joystick</xref><xref>install_keyboard</xref><xref>joy</xref><xref>key</xref><xref>keypressed</xref><xref>num_joysticks</xref><xref>palette_color</xref><xref>poll_joystick</xref><xref>putpixel</xref><xref>readkey</xref><xref>screen</xref><xref>set_gfx_mode</xref><xref>set_palette</xref><xref>textout_centre_ex</xref><xref>textprintf_centre_ex</xref><xref>textprintf_ex</xref></xreflist><shortdesc>Detecting, calibrating and using joystick input.</shortdesc><text><![CDATA[   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).

]]></text></ref><ref name="exsample" syntax="Example exsample"><xreflist><xref>END_OF_MAIN</xref><xref>SAMPLE</xref><xref>SCREEN_H</xref><xref>SCREEN_W</xref><xref>adjust_sample</xref><xref>allegro_error</xref><xref>allegro_init</xref><xref>allegro_message</xref><xref>clear_to_color</xref><xref>desktop_palette</xref><xref>destroy_sample</xref><xref>font</xref><xref>install_keyboard</xref><xref>install_sound</xref><xref>install_timer</xref><xref>key</xref><xref>load_sample</xref><xref>makecol</xref><xref>play_sample</xref><xref>poll_keyboard</xref><xref>rest</xref><xref>screen</xref><xref>set_gfx_mode</xref><xref>set_palette</xref><xref>textprintf_centre_ex</xref></xreflist><shortdesc>Playing digital samples.</shortdesc><text><![CDATA[   This program demonstrates how to play samples. You have to
   use this example from the commandline 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.

]]></text></ref><ref name="exmidi" syntax="Example exmidi"><xreflist><xref>END_OF_MAIN</xref><xref>MIDI</xref><xref>SCREEN_H</xref><xref>SCREEN_W</xref><xref>allegro_error</xref><xref>allegro_init</xref><xref>allegro_message</xref><xref>clear_to_color</xref><xref>desktop_palette</xref><xref>destroy_midi</xref><xref>font</xref><xref>get_filename</xref><xref>get_midi_length</xref><xref>install_keyboard</xref><xref>install_sound</xref><xref>install_timer</xref><xref>key</xref><xref>keypressed</xref><xref>load_midi</xref><xref>makecol</xref><xref>midi_pause</xref><xref>midi_pos</xref><xref>midi_resume</xref><xref>midi_time</xref><xref>play_midi</xref><xref>readkey</xref><xref>rectfill</xref><xref>rest</xref><xref>screen</xref><xref>set_display_switch_mode</xref><xref>set_gfx_mode</xref><xref>set_palette</xref><xref>text_height</xref><xref>text_length</xref><xref>textprintf_centre_ex</xref></xreflist><shortdesc>Playing MIDI music.</shortdesc><text><![CDATA[   This program demonstrates how to play MIDI files.

]]></text></ref><ref name="exgui" syntax="Example exgui"><xreflist><xref>DATAFILE</xref><xref>DIALOG</xref><xref>END_OF_MAIN</xref><xref>MENU</xref><xref>active_menu</xref><xref>alert</xref><xref>allegro_error</xref><xref>allegro_init</xref><xref>allegro_message</xref><xref>d_bitmap_proc</xref><xref>d_box_proc</xref><xref>d_button_proc</xref><xref>d_check_proc</xref><xref>d_clear_proc</xref><xref>d_ctext_proc</xref><xref>d_edit_proc</xref><xref>d_icon_proc</xref><xref>d_keyboard_proc</xref><xref>d_list_proc</xref><xref>d_menu_proc</xref><xref>d_radio_proc</xref><xref>d_rtext_proc</xref><xref>d_shadow_box_proc</xref><xref>d_slider_proc</xref><xref>d_text_list_proc</xref><xref>d_text_proc</xref><xref>d_textbox_proc</xref><xref>d_yield_proc</xref><xref>do_dialog</xref><xref>gui_bg_color</xref><xref>gui_fg_color</xref><xref>gui_mg_color</xref><xref>install_keyboard</xref><xref>install_mouse</xref><xref>install_timer</xref><xref>key</xref><xref>load_datafile</xref><xref>makecol</xref><xref>position_dialog</xref><xref>replace_filename</xref><xref>screen</xref><xref>set_dialog_color</xref><xref>set_gfx_mode</xref><xref>set_palette</xref><xref>unload_datafile</xref><xref>ustrtok</xref><xref>ustrzcat</xref><xref>ustrzcpy</xref><xref>uszprintf</xref></xreflist><shortdesc>Using the GUI routines.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="excustom" syntax="Example excustom"><xreflist><xref>BITMAP</xref><xref>DATAFILE</xref><xref>DIALOG</xref><xref>END_OF_MAIN</xref><xref>FONT</xref><xref>allegro_error</xref><xref>allegro_init</xref><xref>allegro_message</xref><xref>blit</xref><xref>circle</xref><xref>circlefill</xref><xref>clear_to_color</xref><xref>create_bitmap</xref><xref>d_button_proc</xref><xref>d_check_proc</xref><xref>d_clear_proc</xref><xref>d_edit_proc</xref><xref>desktop_palette</xref><xref>destroy_bitmap</xref><xref>do_dialog</xref><xref>fixcos</xref><xref>fixed</xref><xref>fixmul</xref><xref>fixsin</xref><xref>fixtoi</xref><xref>font</xref><xref>install_keyboard</xref><xref>install_mouse</xref><xref>install_timer</xref><xref>itofix</xref><xref>key</xref><xref>line</xref><xref>load_datafile</xref><xref>makecol</xref><xref>object_message</xref><xref>replace_filename</xref><xref>screen</xref><xref>set_gfx_mode</xref><xref>set_palette</xref><xref>unload_datafile</xref></xreflist><shortdesc>Creating custom GUI objects.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="exunicod" syntax="Example exunicod"><xreflist><xref>BITMAP</xref><xref>DATAFILE</xref><xref>END_OF_MAIN</xref><xref>FONT</xref><xref>SCREEN_H</xref><xref>SCREEN_W</xref><xref>allegro_error</xref><xref>allegro_init</xref><xref>allegro_message</xref><xref>blit</xref><xref>clear_to_color</xref><xref>create_bitmap</xref><xref>font</xref><xref>install_int_ex</xref><xref>install_keyboard</xref><xref>install_timer</xref><xref>keypressed</xref><xref>load_datafile</xref><xref>replace_filename</xref><xref>rest</xref><xref>screen</xref><xref>set_gfx_mode</xref><xref>set_uformat</xref><xref>set_window_title</xref><xref>text_height</xref><xref>text_length</xref><xref>textout_ex</xref><xref>uconvert_ascii</xref><xref>unload_datafile</xref><xref>ustrcat</xref><xref>ustrcpy</xref><xref>ustrsize</xref><xref>ustrsizez</xref></xreflist><shortdesc>Using Unicode string functions.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="exbitmap" syntax="Example exbitmap"><xreflist><xref>BITMAP</xref><xref>END_OF_MAIN</xref><xref>PALETTE</xref><xref>SCREEN_H</xref><xref>SCREEN_W</xref><xref>allegro_error</xref><xref>allegro_init</xref><xref>allegro_message</xref><xref>blit</xref><xref>destroy_bitmap</xref><xref>install_keyboard</xref><xref>load_bitmap</xref><xref>readkey</xref><xref>screen</xref><xref>set_gfx_mode</xref><xref>set_palette</xref></xreflist><shortdesc>Loading and displaying PCX and BMP files.</shortdesc><text><![CDATA[   This program demonstrates how to load and display a bitmap
   file.  You have to use this example from the commandline 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.

]]></text></ref><ref name="exscale" syntax="Example exscale"><xreflist><xref>BITMAP</xref><xref>END_OF_MAIN</xref><xref>PALETTE</xref><xref>SCREEN_H</xref><xref>SCREEN_W</xref><xref>allegro_error</xref><xref>allegro_init</xref><xref>allegro_message</xref><xref>blit</xref><xref>destroy_bitmap</xref><xref>install_keyboard</xref><xref>keypressed</xref><xref>load_pcx</xref><xref>replace_filename</xref><xref>screen</xref><xref>set_gfx_mode</xref><xref>set_palette</xref><xref>stretch_blit</xref><xref>vsync</xref></xreflist><shortdesc>Loading PCX files and bitmap stretching.</shortdesc><text><![CDATA[   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().

]]></text></ref><ref name="exconfig" syntax="Example exconfig"><xreflist><xref>BITMAP</xref><xref>END_OF_MAIN</xref><xref>RGB</xref><xref>SCREEN_H</xref><xref>SCREEN_W</xref><xref>allegro_init</xref><xref>allegro_message</xref><xref>blit</xref><xref>clear_bitmap</xref><xref>font</xref><xref>get_config_argv</xref><xref>get_config_int</xref><xref>get_config_string</xref><xref>install_keyboard</xref><xref>line</xref><xref>load_bitmap</xref><xref>makecol</xref><xref>pop_config_state</xref><xref>push_config_state</xref><xref>readkey</xref><xref>screen</xref><xref>set_color_depth</xref><xref>set_config_file</xref><xref>set_gfx_mode</xref><xref>set_palette</xref><xref>stretch_blit</xref><xref>textout_centre_ex</xref><xref>textprintf_centre_ex</xref><xref>ustrdup</xref><xref>ustricmp</xref></xreflist><shortdesc>Using the configuration routines.</shortdesc><text><![CDATA[   This is a very simple program showing how to use the allegro
   config (ini file) routines. A first look at the example
   shows nothing more than a static graphic and the wait for
   a keypress. 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.

]]></text></ref><ref name="exdata" syntax="Example exdata"><xreflist><xref>DATAFILE</xref><xref>END_OF_MAIN</xref><xref>allegro_error</xref><xref>allegro_init</xref><xref>allegro_message</xref><xref>blit</xref><xref>font</xref><xref>install_keyboard</xref><xref>load_datafile</xref><xref>makecol</xref><xref>readkey</xref><xref>replace_filename</xref><xref>screen</xref><xref>set_color_conversion</xref><xref>set_gfx_mode</xref><xref>set_palette</xref><xref>textout_ex</xref><xref>unload_datafile</xref></xreflist><shortdesc>Accessing the contents of datafiles.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="exsprite" syntax="Example exsprite"><xreflist><xref>BITMAP</xref><xref>DATAFILE</xref><xref>END_OF_FUNCTION</xref><xref>END_OF_MAIN</xref><xref>LOCK_FUNCTION</xref><xref>LOCK_VARIABLE</xref><xref>SCREEN_H</xref><xref>SCREEN_W</xref><xref>allegro_error</xref><xref>allegro_init</xref><xref>allegro_message</xref><xref>blit</xref><xref>circle</xref><xref>clear_bitmap</xref><xref>clear_keybuf</xref><xref>create_bitmap</xref><xref>destroy_bitmap</xref><xref>draw_sprite</xref><xref>draw_sprite_h_flip</xref><xref>draw_sprite_v_flip</xref><xref>draw_sprite_vh_flip</xref><xref>fixed</xref><xref>font</xref><xref>hline</xref><xref>install_int_ex</xref><xref>install_keyboard</xref><xref>install_sound</xref><xref>install_timer</xref><xref>itofix</xref><xref>key</xref><xref>keypressed</xref><xref>load_datafile</xref><xref>makecol</xref><xref>palette_color</xref><xref>pivot_sprite</xref><xref>pivot_sprite_v_flip</xref><xref>play_sample</xref><xref>rectfill</xref><xref>replace_filename</xref><xref>rest</xref><xref>screen</xref><xref>set_gfx_mode</xref><xref>set_palette</xref><xref>text_height</xref><xref>textout_centre_ex</xref><xref>unload_datafile</xref><xref>vsync</xref></xreflist><shortdesc>Datafiles access and sprite animation.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="exexedat" syntax="Example exexedat"><xreflist><xref>DATAFILE</xref><xref>END_OF_MAIN</xref><xref>allegro_error</xref><xref>allegro_init</xref><xref>allegro_message</xref><xref>blit</xref><xref>font</xref><xref>install_keyboard</xref><xref>line</xref><xref>load_datafile</xref><xref>makecol</xref><xref>readkey</xref><xref>screen</xref><xref>set_color_conversion</xref><xref>set_gfx_mode</xref><xref>set_palette</xref><xref>textout_ex</xref><xref>unload_datafile</xref></xreflist><shortdesc>Appending datafiles onto your executable.</shortdesc><text><![CDATA[   This program demonstrates how to access the contents of an Allegro
   datafile (created by the grabber utility) linked to the exe 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
   accross all platforms supported by Allegro.

]]></text></ref><ref name="extrans" syntax="Example extrans"><xreflist><xref>BITMAP</xref><xref>COLOR_MAP</xref><xref>END_OF_MAIN</xref><xref>PALETTE</xref><xref>RGB</xref><xref>RGB_MAP</xref><xref>SCREEN_H</xref><xref>SCREEN_W</xref><xref>allegro_error</xref><xref>allegro_init</xref><xref>allegro_message</xref><xref>bitmap_color_depth</xref><xref>blit</xref><xref>circlefill</xref><xref>clear_bitmap</xref><xref>clear_keybuf</xref><xref>color_map</xref><xref>create_bitmap</xref><xref>create_bitmap_ex</xref><xref>create_light_table</xref><xref>create_rgb_table</xref><xref>create_trans_table</xref><xref>destroy_bitmap</xref><xref>draw_trans_sprite</xref><xref>drawing_mode</xref><xref>install_keyboard</xref><xref>install_mouse</xref><xref>install_timer</xref><xref>keypressed</xref><xref>load_bitmap</xref><xref>mouse_x</xref><xref>mouse_y</xref><xref>poll_mouse</xref><xref>rectfill</xref><xref>replace_filename</xref><xref>rest</xref><xref>rgb_map</xref><xref>screen</xref><xref>set_alpha_blender</xref><xref>set_gfx_mode</xref><xref>set_palette</xref><xref>set_trans_blender</xref><xref>set_write_alpha_blender</xref><xref>stretch_blit</xref></xreflist><shortdesc>Lighting and translucency effects.</shortdesc><text><![CDATA[   This program demonstrates how to use the lighting and
   translucency functions. The first part of the example will
   show a dark screen iluminated by a spotlight you can move
   with your mouse. After a keypress 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.

]]></text></ref><ref name="extruec" syntax="Example extruec"><xreflist><xref>END_OF_MAIN</xref><xref>PALETTE</xref><xref>RGB</xref><xref>SCREEN_H</xref><xref>SCREEN_W</xref><xref>acquire_screen</xref><xref>allegro_init</xref><xref>clear_to_color</xref><xref>font</xref><xref>generate_332_palette</xref><xref>install_keyboard</xref><xref>key</xref><xref>makecol</xref><xref>readkey</xref><xref>release_screen</xref><xref>screen</xref><xref>set_color_depth</xref><xref>set_gfx_mode</xref><xref>set_palette</xref><xref>textout_centre_ex</xref><xref>textout_ex</xref><xref>textprintf_ex</xref><xref>vline</xref></xreflist><shortdesc>Truecolor pixel format conversions.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="excolmap" syntax="Example excolmap"><xreflist><xref>BITMAP</xref><xref>COLOR_MAP</xref><xref>END_OF_MAIN</xref><xref>PALETTE</xref><xref>RGB</xref><xref>RGB_MAP</xref><xref>SCREEN_H</xref><xref>SCREEN_W</xref><xref>allegro_error</xref><xref>allegro_init</xref><xref>allegro_message</xref><xref>blit</xref><xref>circlefill</xref><xref>clear_keybuf</xref><xref>color_map</xref><xref>create_bitmap</xref><xref>create_color_table</xref><xref>create_rgb_table</xref><xref>destroy_bitmap</xref><xref>drawing_mode</xref><xref>font</xref><xref>generate_332_palette</xref><xref>install_keyboard</xref><xref>keypressed</xref><xref>makecol</xref><xref>rectfill</xref><xref>rgb_map</xref><xref>screen</xref><xref>set_gfx_mode</xref><xref>set_palette</xref><xref>textout_centre_ex</xref><xref>vsync</xref></xreflist><shortdesc>Creating graphical effects with color mapping tables.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="exrgbhsv" syntax="Example exrgbhsv"><xreflist><xref>BITMAP</xref><xref>DIALOG</xref><xref>END_OF_MAIN</xref><xref>PALETTE</xref><xref>RGB</xref><xref>RGB_MAP</xref><xref>allegro_error</xref><xref>allegro_init</xref><xref>allegro_message</xref><xref>clear_to_color</xref><xref>create_bitmap_ex</xref><xref>create_rgb_table</xref><xref>d_bitmap_proc</xref><xref>d_box_proc</xref><xref>d_slider_proc</xref><xref>d_text_proc</xref><xref>destroy_bitmap</xref><xref>do_dialog</xref><xref>font</xref><xref>generate_332_palette</xref><xref>get_color_depth</xref><xref>hsv_to_rgb</xref><xref>install_keyboard</xref><xref>install_mouse</xref><xref>install_timer</xref><xref>key</xref><xref>makecol</xref><xref>makecol32</xref><xref>makecol8</xref><xref>object_message</xref><xref>rgb_map</xref><xref>rgb_to_hsv</xref><xref>screen</xref><xref>set_color</xref><xref>set_color_depth</xref><xref>set_gfx_mode</xref><xref>set_palette</xref><xref>textout_ex</xref><xref>vline</xref><xref>vsync</xref></xreflist><shortdesc>RGB &lt;-&gt; HSV colorspace conversions.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="exshade" syntax="Example exshade"><xreflist><xref>BITMAP</xref><xref>COLOR_MAP</xref><xref>END_OF_MAIN</xref><xref>PALETTE</xref><xref>RGB</xref><xref>RGB_MAP</xref><xref>SCREEN_H</xref><xref>SCREEN_W</xref><xref>allegro_error</xref><xref>allegro_init</xref><xref>allegro_message</xref><xref>blit</xref><xref>clear_bitmap</xref><xref>color_map</xref><xref>create_bitmap</xref><xref>create_light_table</xref><xref>create_rgb_table</xref><xref>destroy_bitmap</xref><xref>draw_gouraud_sprite</xref><xref>font</xref><xref>install_keyboard</xref><xref>install_mouse</xref><xref>keypressed</xref><xref>line</xref><xref>load_bitmap</xref><xref>mouse_x</xref><xref>mouse_y</xref><xref>palette_color</xref><xref>poll_mouse</xref><xref>replace_filename</xref><xref>rgb_map</xref><xref>screen</xref><xref>set_gfx_mode</xref><xref>set_palette</xref><xref>set_trans_blender</xref><xref>show_mouse</xref><xref>textout_ex</xref></xreflist><shortdesc>Gouraud shaded sprites.</shortdesc><text><![CDATA[   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 goraud shaded
   sprite will show the direction of the light.

]]></text></ref><ref name="exblend" syntax="Example exblend"><xreflist><xref>BITMAP</xref><xref>END_OF_MAIN</xref><xref>PALETTE</xref><xref>SCREEN_H</xref><xref>SCREEN_W</xref><xref>allegro_error</xref><xref>allegro_init</xref><xref>allegro_message</xref><xref>blit</xref><xref>circle</xref><xref>clear_bitmap</xref><xref>clear_keybuf</xref><xref>create_bitmap</xref><xref>destroy_bitmap</xref><xref>draw_lit_sprite</xref><xref>draw_trans_sprite</xref><xref>fixcos</xref><xref>fixsin</xref><xref>fixtoi</xref><xref>font</xref><xref>install_keyboard</xref><xref>install_timer</xref><xref>itofix</xref><xref>keypressed</xref><xref>load_bitmap</xref><xref>makecol</xref><xref>replace_filename</xref><xref>retrace_count</xref><xref>screen</xref><xref>set_color_conversion</xref><xref>set_color_depth</xref><xref>set_gfx_mode</xref><xref>set_trans_blender</xref><xref>textprintf_ex</xref><xref>vsync</xref></xreflist><shortdesc>Using translucency in truecolor modes.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="exxfade" syntax="Example exxfade"><xreflist><xref>BITMAP</xref><xref>END_OF_MAIN</xref><xref>PALETTE</xref><xref>SCREEN_H</xref><xref>SCREEN_W</xref><xref>allegro_error</xref><xref>allegro_exit</xref><xref>allegro_init</xref><xref>allegro_message</xref><xref>blit</xref><xref>create_bitmap</xref><xref>destroy_bitmap</xref><xref>draw_trans_sprite</xref><xref>install_keyboard</xref><xref>keypressed</xref><xref>line</xref><xref>load_bitmap</xref><xref>readkey</xref><xref>screen</xref><xref>set_color_conversion</xref><xref>set_color_depth</xref><xref>set_gfx_mode</xref><xref>set_palette</xref><xref>set_trans_blender</xref><xref>vsync</xref></xreflist><shortdesc>Truecolor image loading and fades.</shortdesc><text><![CDATA[   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 commandline 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 keypress until you press
   the ESC key.

]]></text></ref><ref name="exalpha" syntax="Example exalpha"><xreflist><xref>BITMAP</xref><xref>END_OF_MAIN</xref><xref>SCREEN_H</xref><xref>SCREEN_W</xref><xref>allegro_error</xref><xref>allegro_init</xref><xref>allegro_message</xref><xref>blit</xref><xref>clear_keybuf</xref><xref>create_bitmap</xref><xref>destroy_bitmap</xref><xref>draw_trans_sprite</xref><xref>drawing_mode</xref><xref>font</xref><xref>getb</xref><xref>getg</xref><xref>getpixel</xref><xref>getr</xref><xref>install_keyboard</xref><xref>install_mouse</xref><xref>install_timer</xref><xref>keypressed</xref><xref>load_bitmap</xref><xref>makecol</xref><xref>mouse_x</xref><xref>mouse_y</xref><xref>putpixel</xref><xref>rectfill</xref><xref>replace_filename</xref><xref>screen</xref><xref>set_alpha_blender</xref><xref>set_color_conversion</xref><xref>set_color_depth</xref><xref>set_gfx_mode</xref><xref>set_multiply_blender</xref><xref>set_write_alpha_blender</xref><xref>solid_mode</xref><xref>stretch_blit</xref><xref>textprintf_ex</xref></xreflist><shortdesc>Creating and using 32 bit RGBA sprites.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="exlights" syntax="Example exlights"><xreflist><xref>BITMAP</xref><xref>COLOR_MAP</xref><xref>END_OF_MAIN</xref><xref>PALETTE</xref><xref>SCREEN_H</xref><xref>SCREEN_W</xref><xref>allegro_error</xref><xref>allegro_init</xref><xref>allegro_message</xref><xref>bitmap_color_depth</xref><xref>blit</xref><xref>bmp_unwrite_line</xref><xref>bmp_write_line</xref><xref>circlefill</xref><xref>clear_bitmap</xref><xref>clear_keybuf</xref><xref>color_map</xref><xref>create_bitmap_ex</xref><xref>destroy_bitmap</xref><xref>draw_trans_sprite</xref><xref>fixatan2</xref><xref>fixsqrt</xref><xref>fixtoi</xref><xref>getb_depth</xref><xref>getg_depth</xref><xref>getpixel</xref><xref>getr_depth</xref><xref>hsv_to_rgb</xref><xref>install_keyboard</xref><xref>install_mouse</xref><xref>install_timer</xref><xref>itofix</xref><xref>key</xref><xref>keypressed</xref><xref>line</xref><xref>load_bitmap</xref><xref>makecol</xref><xref>mouse_x</xref><xref>mouse_y</xref><xref>poll_mouse</xref><xref>replace_filename</xref><xref>retrace_count</xref><xref>screen</xref><xref>select_palette</xref><xref>set_color_conversion</xref><xref>set_color_depth</xref><xref>set_gfx_mode</xref></xreflist><shortdesc>One way to do colored lighting effects in a hicolor video mode.</shortdesc><text><![CDATA[   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 :-)

]]></text></ref><ref name="ex3d" syntax="Example ex3d"><xreflist><xref>BITMAP</xref><xref>COLOR_MAP</xref><xref>END_OF_MAIN</xref><xref>MATRIX</xref><xref>PALETTE</xref><xref>POLYTYPE_ATEX</xref><xref>POLYTYPE_ATEX_LIT</xref><xref>POLYTYPE_ATEX_MASK</xref><xref>POLYTYPE_ATEX_MASK_LIT</xref><xref>POLYTYPE_ATEX_MASK_TRANS</xref><xref>POLYTYPE_ATEX_TRANS</xref><xref>POLYTYPE_FLAT</xref><xref>POLYTYPE_GCOL</xref><xref>POLYTYPE_GRGB</xref><xref>POLYTYPE_PTEX</xref><xref>POLYTYPE_PTEX_LIT</xref><xref>POLYTYPE_PTEX_MASK</xref><xref>POLYTYPE_PTEX_MASK_LIT</xref><xref>POLYTYPE_PTEX_MASK_TRANS</xref><xref>POLYTYPE_PTEX_TRANS</xref><xref>RGB</xref><xref>RGB_MAP</xref><xref>SCREEN_H</xref><xref>SCREEN_W</xref><xref>V3D</xref><xref>allegro_error</xref><xref>allegro_exit</xref><xref>allegro_init</xref><xref>allegro_message</xref><xref>apply_matrix</xref><xref>bitmap_color_depth</xref><xref>bitmap_mask_color</xref><xref>blit</xref><xref>clear_bitmap</xref><xref>clear_to_color</xref><xref>color_map</xref><xref>create_bitmap</xref><xref>create_light_table</xref><xref>create_rgb_table</xref><xref>create_trans_table</xref><xref>desktop_palette</xref><xref>destroy_bitmap</xref><xref>fixed</xref><xref>fixtoi</xref><xref>font</xref><xref>get_transformation_matrix</xref><xref>gfx_mode_select_ex</xref><xref>install_keyboard</xref><xref>install_mouse</xref><xref>install_timer</xref><xref>itofix</xref><xref>key</xref><xref>keypressed</xref><xref>line</xref><xref>palette_color</xref><xref>persp_project</xref><xref>polygon_z_normal</xref><xref>quad3d</xref><xref>readkey</xref><xref>rect</xref><xref>retrace_count</xref><xref>rgb_map</xref><xref>screen</xref><xref>set_color_depth</xref><xref>set_gfx_mode</xref><xref>set_palette</xref><xref>set_projection_viewport</xref><xref>set_trans_blender</xref><xref>textout_ex</xref><xref>textprintf_ex</xref><xref>vsync</xref></xreflist><shortdesc>3d 'bouncy cubes' demo.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="excamera" syntax="Example excamera"><xreflist><xref>BITMAP</xref><xref>END_OF_MAIN</xref><xref>MATRIX_f</xref><xref>POLYTYPE_FLAT</xref><xref>SCREEN_H</xref><xref>SCREEN_W</xref><xref>V3D_f</xref><xref>allegro_error</xref><xref>allegro_init</xref><xref>allegro_message</xref><xref>apply_matrix_f</xref><xref>blit</xref><xref>clear_to_color</xref><xref>clip3d_f</xref><xref>create_bitmap</xref><xref>desktop_palette</xref><xref>destroy_bitmap</xref><xref>font</xref><xref>get_camera_matrix_f</xref><xref>get_vector_rotation_matrix_f</xref><xref>install_int_ex</xref><xref>install_keyboard</xref><xref>install_timer</xref><xref>key</xref><xref>key_shifts</xref><xref>makecol</xref><xref>persp_project_f</xref><xref>poll_keyboard</xref><xref>polygon</xref><xref>polygon3d_f</xref><xref>rect</xref><xref>screen</xref><xref>set_clip_rect</xref><xref>set_gfx_mode</xref><xref>set_palette</xref><xref>set_projection_viewport</xref><xref>textprintf_ex</xref><xref>vsync</xref></xreflist><shortdesc>Viewing a 3d world from an arbitrary camera position.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="exquat" syntax="Example exquat"><xreflist><xref>BITMAP</xref><xref>END_OF_MAIN</xref><xref>MATRIX_f</xref><xref>QUAT</xref><xref>acquire_bitmap</xref><xref>allegro_error</xref><xref>allegro_init</xref><xref>allegro_message</xref><xref>apply_matrix_f</xref><xref>blit</xref><xref>circle</xref><xref>clear_keybuf</xref><xref>clear_to_color</xref><xref>create_bitmap</xref><xref>desktop_palette</xref><xref>destroy_bitmap</xref><xref>font</xref><xref>get_camera_matrix_f</xref><xref>get_rotation_matrix</xref><xref>get_rotation_matrix_f</xref><xref>get_rotation_quat</xref><xref>install_keyboard</xref><xref>keypressed</xref><xref>line</xref><xref>matrix_mul_f</xref><xref>palette_color</xref><xref>persp_project_f</xref><xref>quat_interpolate</xref><xref>quat_to_matrix</xref><xref>readkey</xref><xref>release_bitmap</xref><xref>rest</xref><xref>screen</xref><xref>set_gfx_mode</xref><xref>set_palette</xref><xref>set_projection_viewport</xref><xref>textout_ex</xref></xreflist><shortdesc>A comparison between euler angles and quaternions.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="exstars" syntax="Example exstars"><xreflist><xref>BITMAP</xref><xref>END_OF_MAIN</xref><xref>MATRIX</xref><xref>PALETTE</xref><xref>SCREEN_H</xref><xref>SCREEN_W</xref><xref>allegro_error</xref><xref>allegro_init</xref><xref>allegro_message</xref><xref>apply_matrix</xref><xref>blit</xref><xref>clear_bitmap</xref><xref>create_bitmap</xref><xref>cross_product</xref><xref>destroy_bitmap</xref><xref>dot_product</xref><xref>fixed</xref><xref>fixmul</xref><xref>fixtof</xref><xref>fixtoi</xref><xref>font</xref><xref>get_rotation_matrix</xref><xref>get_transformation_matrix</xref><xref>get_translation_matrix</xref><xref>install_keyboard</xref><xref>install_timer</xref><xref>itofix</xref><xref>key</xref><xref>normalize_vector</xref><xref>palette_color</xref><xref>persp_project</xref><xref>poll_keyboard</xref><xref>putpixel</xref><xref>rectfill</xref><xref>screen</xref><xref>set_gfx_mode</xref><xref>set_palette</xref><xref>set_projection_viewport</xref><xref>textout_centre_ex</xref><xref>textprintf_centre_ex</xref><xref>triangle</xref><xref>vsync</xref></xreflist><shortdesc>3d starfield and lightsourced spaceship.</shortdesc><text><![CDATA[   This program draws a 3D starfield (depth-cued) and a polygon
   starship (controllable with the keyboard cursor keys), using
   the Allegro math functions.

]]></text></ref><ref name="exscn3d" syntax="Example exscn3d"><xreflist><xref>BITMAP</xref><xref>END_OF_FUNCTION</xref><xref>END_OF_MAIN</xref><xref>LOCK_FUNCTION</xref><xref>LOCK_VARIABLE</xref><xref>MATRIX_f</xref><xref>PALETTE</xref><xref>POLYTYPE_GCOL</xref><xref>SCREEN_H</xref><xref>SCREEN_W</xref><xref>V3D_f</xref><xref>allegro_error</xref><xref>allegro_exit</xref><xref>allegro_init</xref><xref>allegro_message</xref><xref>apply_matrix_f</xref><xref>bitmap_color_depth</xref><xref>blit</xref><xref>clear_bitmap</xref><xref>clear_scene</xref><xref>clip3d_f</xref><xref>create_bitmap</xref><xref>create_scene</xref><xref>desktop_palette</xref><xref>destroy_bitmap</xref><xref>destroy_scene</xref><xref>font</xref><xref>get_rotation_matrix_f</xref><xref>get_translation_matrix_f</xref><xref>gfx_mode_select_ex</xref><xref>install_int</xref><xref>install_keyboard</xref><xref>install_mouse</xref><xref>install_timer</xref><xref>key</xref><xref>matrix_mul_f</xref><xref>palette_color</xref><xref>persp_project_f</xref><xref>polygon_z_normal_f</xref><xref>render_scene</xref><xref>scene_polygon3d_f</xref><xref>screen</xref><xref>set_color_depth</xref><xref>set_gfx_mode</xref><xref>set_palette</xref><xref>set_projection_viewport</xref><xref>textprintf_ex</xref></xreflist><shortdesc>Using the 3d scene functions.</shortdesc><text><![CDATA[   This program demonstrates how to use scanline sorting algo
   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.


]]></text></ref><ref name="exzbuf" syntax="Example exzbuf"><xreflist><xref>BITMAP</xref><xref>END_OF_FUNCTION</xref><xref>END_OF_MAIN</xref><xref>LOCK_FUNCTION</xref><xref>LOCK_VARIABLE</xref><xref>MATRIX_f</xref><xref>PALETTE</xref><xref>POLYTYPE_GCOL</xref><xref>SCREEN_H</xref><xref>SCREEN_W</xref><xref>V3D_f</xref><xref>ZBUFFER</xref><xref>allegro_error</xref><xref>allegro_exit</xref><xref>allegro_init</xref><xref>allegro_message</xref><xref>apply_matrix_f</xref><xref>bitmap_color_depth</xref><xref>blit</xref><xref>clear_bitmap</xref><xref>clear_zbuffer</xref><xref>create_bitmap</xref><xref>create_zbuffer</xref><xref>desktop_palette</xref><xref>destroy_bitmap</xref><xref>destroy_zbuffer</xref><xref>font</xref><xref>get_transformation_matrix_f</xref><xref>gfx_mode_select_ex</xref><xref>install_int</xref><xref>install_keyboard</xref><xref>install_mouse</xref><xref>install_timer</xref><xref>keypressed</xref><xref>palette_color</xref><xref>persp_project_f</xref><xref>polygon_z_normal_f</xref><xref>quad3d_f</xref><xref>readkey</xref><xref>screen</xref><xref>set_color_depth</xref><xref>set_gfx_mode</xref><xref>set_palette</xref><xref>set_projection_viewport</xref><xref>set_zbuffer</xref><xref>textprintf_ex</xref><xref>vsync</xref></xreflist><shortdesc>Z-buffered polygons demo.</shortdesc><text><![CDATA[   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 polgons due to per-polygon sorting, each pixel is drawn
   at the correct depth.

]]></text></ref><ref name="exscroll" syntax="Example exscroll"><xreflist><xref>BITMAP</xref><xref>END_OF_MAIN</xref><xref>RGB</xref><xref>SCREEN_H</xref><xref>SCREEN_W</xref><xref>acquire_bitmap</xref><xref>allegro_init</xref><xref>allegro_message</xref><xref>clear_keybuf</xref><xref>create_sub_bitmap</xref><xref>desktop_palette</xref><xref>destroy_bitmap</xref><xref>install_keyboard</xref><xref>keypressed</xref><xref>rectfill</xref><xref>release_bitmap</xref><xref>screen</xref><xref>scroll_screen</xref><xref>set_color</xref><xref>set_gfx_mode</xref><xref>set_palette</xref><xref>vline</xref></xreflist><shortdesc>Mode-X hardware scrolling and split screens.</shortdesc><text><![CDATA[   This program demonstrates how to use hardware scrolling.
   The scrolling should work on anything that supports virtual
   screens larger than the physical screen.

]]></text></ref><ref name="ex3buf" syntax="Example ex3buf"><xreflist><xref>BITMAP</xref><xref>END_OF_MAIN</xref><xref>SCREEN_H</xref><xref>SCREEN_W</xref><xref>acquire_bitmap</xref><xref>allegro_error</xref><xref>allegro_init</xref><xref>allegro_message</xref><xref>clear_bitmap</xref><xref>clear_keybuf</xref><xref>create_video_bitmap</xref><xref>desktop_palette</xref><xref>destroy_bitmap</xref><xref>enable_triple_buffer</xref><xref>fixcos</xref><xref>fixed</xref><xref>fixmul</xref><xref>fixsin</xref><xref>fixtoi</xref><xref>font</xref><xref>gfx_capabilities</xref><xref>install_keyboard</xref><xref>install_mouse</xref><xref>install_timer</xref><xref>itofix</xref><xref>keypressed</xref><xref>poll_scroll</xref><xref>release_bitmap</xref><xref>request_video_bitmap</xref><xref>screen</xref><xref>set_gfx_mode</xref><xref>set_palette</xref><xref>textout_ex</xref><xref>triangle</xref><xref>ustrzcpy</xref></xreflist><shortdesc>Mode-X triple buffering and retrace interrupt simulation.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="ex12bit" syntax="Example ex12bit"><xreflist><xref>BITMAP</xref><xref>END_OF_MAIN</xref><xref>MATRIX</xref><xref>PALETTE</xref><xref>RGB</xref><xref>allegro_error</xref><xref>allegro_init</xref><xref>allegro_message</xref><xref>apply_matrix</xref><xref>blit</xref><xref>circle</xref><xref>clear_bitmap</xref><xref>clear_keybuf</xref><xref>clear_to_color</xref><xref>create_bitmap</xref><xref>create_bitmap_ex</xref><xref>destroy_bitmap</xref><xref>ellipsefill</xref><xref>fade_out</xref><xref>fixcos</xref><xref>fixed</xref><xref>fixsin</xref><xref>fixtoi</xref><xref>font</xref><xref>get_rotation_matrix</xref><xref>getpixel</xref><xref>install_keyboard</xref><xref>itofix</xref><xref>keypressed</xref><xref>line</xref><xref>makecol</xref><xref>masked_blit</xref><xref>putpixel</xref><xref>screen</xref><xref>set_clip_rect</xref><xref>set_color</xref><xref>set_gfx_mode</xref><xref>set_palette</xref><xref>text_height</xref><xref>text_length</xref><xref>textout_ex</xref><xref>textprintf_ex</xref></xreflist><shortdesc>How to fake a 12-bit truecolor mode on an 8-bit card.</shortdesc><text><![CDATA[   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:

   <ul><li>The horizontal width is halved, so you get resolutions
   like 320x480, 400x600, and 512x768.

   <li>Because each dot is spread over two actual pixels, the
   display will be darker than in a normal video mode.

   <li>Any bitmap data will obviously need converting to the
   correct 12 bit format: regular 15 or 16 bit images won't
   display correctly...

   <li>Although this works like a truecolor mode, it is
   actually using a 256 color palette, so palette fades are
   still possible!

   <li>This code only works in linear screen modes (don't try
   Mode-X).</ul>

]]></text></ref><ref name="exaccel" syntax="Example exaccel"><xreflist><xref>BITMAP</xref><xref>END_OF_MAIN</xref><xref>PALETTE</xref><xref>SCREEN_H</xref><xref>SCREEN_W</xref><xref>acquire_bitmap</xref><xref>allegro_error</xref><xref>allegro_init</xref><xref>allegro_message</xref><xref>blit</xref><xref>clear_bitmap</xref><xref>create_video_bitmap</xref><xref>destroy_bitmap</xref><xref>font</xref><xref>gfx_capabilities</xref><xref>install_keyboard</xref><xref>install_timer</xref><xref>keypressed</xref><xref>load_bitmap</xref><xref>readkey</xref><xref>release_bitmap</xref><xref>replace_filename</xref><xref>screen</xref><xref>set_gfx_mode</xref><xref>set_palette</xref><xref>show_video_bitmap</xref><xref>textout_ex</xref><xref>textprintf_ex</xref></xreflist><shortdesc>Using offscreen video memory to store source graphics for VBE/AF.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="exspline" syntax="Example exspline"><xreflist><xref>END_OF_MAIN</xref><xref>SCREEN_W</xref><xref>acquire_screen</xref><xref>alert</xref><xref>allegro_error</xref><xref>allegro_init</xref><xref>allegro_message</xref><xref>calc_spline</xref><xref>circlefill</xref><xref>clear_keybuf</xref><xref>clear_to_color</xref><xref>desktop_palette</xref><xref>fixatan2</xref><xref>fixcos</xref><xref>fixed</xref><xref>fixmul</xref><xref>fixsin</xref><xref>fixsqrt</xref><xref>fixtof</xref><xref>fixtoi</xref><xref>font</xref><xref>ftofix</xref><xref>install_keyboard</xref><xref>install_mouse</xref><xref>install_timer</xref><xref>itofix</xref><xref>key</xref><xref>keypressed</xref><xref>line</xref><xref>makecol</xref><xref>mouse_b</xref><xref>mouse_x</xref><xref>mouse_y</xref><xref>palette_color</xref><xref>poll_mouse</xref><xref>readkey</xref><xref>release_screen</xref><xref>screen</xref><xref>set_gfx_mode</xref><xref>set_palette</xref><xref>show_mouse</xref><xref>spline</xref><xref>textout_centre_ex</xref><xref>textprintf_centre_ex</xref><xref>textprintf_ex</xref><xref>vsync</xref><xref>xor_mode</xref></xreflist><shortdesc>Constructing smooth movement paths from spline curves.</shortdesc><text><![CDATA[   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 noticable change of direction
   at each guide point, the effect can be quite nice because it makes
   the object slow down for the curve.

]]></text></ref><ref name="exsyscur" syntax="Example exsyscur"><xreflist><xref>END_OF_MAIN</xref><xref>SCREEN_H</xref><xref>SCREEN_W</xref><xref>allegro_error</xref><xref>allegro_init</xref><xref>allegro_message</xref><xref>clear_to_color</xref><xref>enable_hardware_cursor</xref><xref>font</xref><xref>gfx_capabilities</xref><xref>install_keyboard</xref><xref>install_mouse</xref><xref>install_timer</xref><xref>makecol</xref><xref>readkey</xref><xref>screen</xref><xref>select_mouse_cursor</xref><xref>set_gfx_mode</xref><xref>show_mouse</xref><xref>text_height</xref><xref>textprintf_centre_ex</xref></xreflist><text><![CDATA[   This program demonstrates the use of hardware accelerated mouse cursors.

]]></text></ref><ref name="exupdate" syntax="Example exupdate"><xreflist><xref>BITMAP</xref><xref>END_OF_FUNCTION</xref><xref>END_OF_MAIN</xref><xref>LOCK_FUNCTION</xref><xref>LOCK_VARIABLE</xref><xref>PALETTE</xref><xref>SCREEN_H</xref><xref>SCREEN_W</xref><xref>acquire_bitmap</xref><xref>allegro_error</xref><xref>allegro_init</xref><xref>allegro_message</xref><xref>bitmap_color_depth</xref><xref>blit</xref><xref>clear_bitmap</xref><xref>create_bitmap</xref><xref>create_system_bitmap</xref><xref>create_video_bitmap</xref><xref>desktop_palette</xref><xref>destroy_bitmap</xref><xref>enable_triple_buffer</xref><xref>fixcos</xref><xref>fixed</xref><xref>fixmul</xref><xref>fixsin</xref><xref>fixtoi</xref><xref>font</xref><xref>ftofix</xref><xref>generate_332_palette</xref><xref>gfx_capabilities</xref><xref>gfx_mode_select_ex</xref><xref>install_int_ex</xref><xref>install_keyboard</xref><xref>install_mouse</xref><xref>install_timer</xref><xref>keypressed</xref><xref>line</xref><xref>makecol</xref><xref>poll_scroll</xref><xref>release_bitmap</xref><xref>request_video_bitmap</xref><xref>screen</xref><xref>set_color_depth</xref><xref>set_gfx_mode</xref><xref>set_palette</xref><xref>show_video_bitmap</xref><xref>textout_ex</xref><xref>textprintf_ex</xref><xref>triangle</xref><xref>vsync</xref><xref>xor_mode</xref></xreflist><shortdesc>Supporting different screen update methods in a single program.</shortdesc><text><![CDATA[   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 commandline 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.

]]></text></ref><ref name="exswitch" syntax="Example exswitch"><xreflist><xref>BITMAP</xref><xref>END_OF_FUNCTION</xref><xref>END_OF_MAIN</xref><xref>LOCK_FUNCTION</xref><xref>LOCK_VARIABLE</xref><xref>PALETTE</xref><xref>SCREEN_H</xref><xref>SCREEN_W</xref><xref>acquire_bitmap</xref><xref>acquire_screen</xref><xref>allegro_error</xref><xref>allegro_exit</xref><xref>allegro_init</xref><xref>allegro_message</xref><xref>bitmap_color_depth</xref><xref>blit</xref><xref>clear_to_color</xref><xref>create_sub_bitmap</xref><xref>desktop_palette</xref><xref>destroy_bitmap</xref><xref>font</xref><xref>get_display_switch_mode</xref><xref>gfx_mode_select_ex</xref><xref>install_int</xref><xref>install_keyboard</xref><xref>install_mouse</xref><xref>install_timer</xref><xref>keypressed</xref><xref>makecol</xref><xref>palette_color</xref><xref>putpixel</xref><xref>readkey</xref><xref>rectfill</xref><xref>release_bitmap</xref><xref>release_screen</xref><xref>screen</xref><xref>set_color_depth</xref><xref>set_display_switch_callback</xref><xref>set_display_switch_mode</xref><xref>set_gfx_mode</xref><xref>set_palette</xref><xref>textout_centre_ex</xref><xref>textprintf_centre_ex</xref></xreflist><shortdesc>Controlling the console switch mode for background running.</shortdesc><text><![CDATA[   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.

]]></text></ref><ref name="exstream" syntax="Example exstream"><xreflist><xref>AUDIOSTREAM</xref><xref>END_OF_MAIN</xref><xref>SCREEN_H</xref><xref>SCREEN_W</xref><xref>allegro_error</xref><xref>allegro_init</xref><xref>allegro_message</xref><xref>clear_to_color</xref><xref>desktop_palette</xref><xref>font</xref><xref>free_audio_stream_buffer</xref><xref>get_audio_stream_buffer</xref><xref>install_keyboard</xref><xref>install_sound</xref><xref>install_timer</xref><xref>keypressed</xref><xref>makecol</xref><xref>play_audio_stream</xref><xref>readkey</xref><xref>screen</xref><xref>set_gfx_mode</xref><xref>set_palette</xref><xref>stop_audio_stream</xref><xref>textprintf_centre_ex</xref><xref>voice_start</xref><xref>voice_stop</xref></xreflist><shortdesc>Playing audio streams.</shortdesc><text><![CDATA[   This program shows how to use the audio stream functions to
   transfer large blocks of sample data to the soundcard. In
   this case, the sample data is generated during runtime,
   and the resulting sound reminds of a car engine when you
   are accelerating.

]]></text></ref><ref name="expackf" syntax="Example expackf"><xreflist><xref>ASSERT</xref><xref>BITMAP</xref><xref>END_OF_MAIN</xref><xref>PACKFILE</xref><xref>PACKFILE_VTABLE</xref><xref>SCREEN_H</xref><xref>SCREEN_W</xref><xref>alert</xref><xref>allegro_error</xref><xref>allegro_init</xref><xref>allegro_message</xref><xref>blit</xref><xref>clear_bitmap</xref><xref>destroy_bitmap</xref><xref>file_size_ex</xref><xref>font</xref><xref>install_keyboard</xref><xref>key</xref><xref>load_bmp_pf</xref><xref>load_pcx</xref><xref>load_pcx_pf</xref><xref>load_tga_pf</xref><xref>pack_fclose</xref><xref>pack_fopen</xref><xref>pack_fopen_vtable</xref><xref>pack_fread</xref><xref>pack_fseek</xref><xref>readkey</xref><xref>save_bmp_pf</xref><xref>save_tga_pf</xref><xref>screen</xref><xref>set_color_depth</xref><xref>set_gfx_mode</xref><xref>text_height</xref><xref>textprintf_centre_ex</xref><xref>textprintf_ex</xref></xreflist><shortdesc>Using custom PACKFILE vtables.</shortdesc><text><![CDATA[   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 filestream 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.

]]></text></ref></reflist></section><section title="Changes since previous versions"><section title="Changes from 4.2.1 RC1 to 4.2.1 (November 2006)"><text><![CDATA[<ul><li>
   Peter Wang made the Unix ports query the memory page size with sysconf()
   when necessary, instead of using the PAGE_SIZE constant, which seems to be
   Linux-specific.
<li>
   Matthew Leverton gave the STATICRUNTIME builds of MSVC new names by
   appending _crt (c run time) to the libraries. He also fixed the problem of
   incorrectly setting the EMBED_MANIFEST variable when using the
   STATICRUNTIME.
<li>
   Andrei Ellman fixed an inverted test in pack_fopen_chunk on Windows.
<li>
   Peter Hull made 32-bit icon generation by fixbundle endian-independent
   (colours were incorrect on Intel Macs).
<li>
   Peter Wang fixed a long standing bug where some compressed packfiles would not
   be read back properly (premature EOF).  Reported by jman2050.
<li>
   Andrei Ellman spotted a free() of an internal buffer returned by tmpnam().
<li>
   Peter Hull fixed a problem with mouse-related deadlock on MacOS X as
   reported by Mike Farrell.
<li>
   Peter Hull implemented simulation of video bitmaps on MacOS X, so that
   page flipping will work.
<li>
   Peter Hull fixed an endian problem in the digital sound driver on MacOS X.
<li>
   Elias Pschernig and Chris Robinson fixed problems with UTF-8 filenames
   under Unix, as reported by Grzegorz.  Non-ASCII non-UTF-8 filenames remain
   broken.
<li>
   Chris Robinson fixed some problems with non-ASCII filenames under Windows.
<li>
   Elias Pschernig made the X11 driver call XInitThreads, to make Mesa-OpenGL
   work together with Allegro.  It can be disabled at runtime through a config
   variable.
<li>
   Andrei Ellman fixed a bug in datedit.c that could crash the grabber.
<li>
   Elias Pschernig added file_size_ex(), which returns a 64 bit integer
   to handle large files.
<li>
   Ron Novy made improvements to the test program.
<li>
   Peter Hull fixed problems with set_mouse_sprite() on Intel Macs.
<li>
   Peter Hull added universal binary support to the MacOS X port.
<li>
   Peter Wang and Evert Glebbeek independently fixed a problem with dependency
   generation for MacOS X on non-Mac systems.
<li>
   Many smaller fixes and updates by Peter Hull, Elias Pschernig, Peter Wang
   and Milan Mimica.
</ul>

]]></text></section><section title="Changes from 4.2.0 to 4.2.1 RC1 (May 2006)"><text><![CDATA[<ul><li>
   Michal Molhanec made msvchelp.exe work on Cygwin, where there was a
   problem with the case-insensitivity of environment variables. Reported by
   Milan Mimica.
<li>
   Peter Hull fixed a bug where Allegro detected keypresses on
   KEY_MINUS_PAD as KEY_PLUS_PAD.
<li>
   Peter Hull made OSX work correctly with Logitech sticks, as discussed
   with Ultio.
<li>
   Milan Mimica fixed some spin loops in the test program.
<li>
   Chris Robinson added UTF8/Unicode support for filenames in Windows.
<li>
   Milan Mimica made the Linux console driver more robust:
   set_gfx_mode used to get stuck in a infinite loop when there wasn't a
   console available.
<li>
   Evert Glebbeek made the C blitter use memmove for normal blits, with a bugfix
   by Milan Mimica. This can be disabled by removing a #define USE_MEMMOVE at
   the top of cblit.h so that it can easliy be tested against the older versions
   of the code.
<li>
   Christer Sandberg worked around a problem where one-line high bitmaps would
   crash with  Electric Fence.
<li>
   Chris Robinson fixed a crash that occurred if the sound mixer quality
   level was set to 0 after the mixer was already initialised.
<li>
   Evert Glebbeek fixed the window title under X11, which was broken by a
   previous change.
<li>
   Peter Hull updated the endian detection under OSX as recommended by Apple.
<li>
   Miguel A. Gavidia and Jay Bernardo made qtmidi.m work on both PPC and Intel.
<li>
   Milan Mimica fixed a crash when vsync() on certain drivers.
<li>
   Elias Pschernig replaced the ALLEGRO_USE_C define with ALLEGRO_NO_ASM.
<li>
   Peter Wang restored the JACK driver to compiling state.
<li>
   Milan Mimica made the new transparent fonts be recognized as color fonts
   with is_color_font.
<li>
   Elias Pschernig made the modules path WIP version specific, for enhanced
   binary compatibility.
<li>
   Stijn Wolters clarified the documentation of init_dialog.
<li>
   Hans de Goede fixed a problem with dynamically generated stretcher code not
   being properly marked as executable on Linux (esp. SELinux).
<li>
   Hans de Goede fixed a busy wait in the X11 vsync simulation.
<li>
   Elias Pschernig makde it so modules under Unix are now searched in libdir
   as passed by the build machinery. Closes bug #1401840 from SF, reported by
   Paul Eipper.
<li>
   Milan Mimica added a get_volume and a get_hardware_volume function, to
   work as pendants to set_volume and set_hardware_volume.
<li>
   Milan Mimica corrected a case where a wrong structure on the stack was
   being cleared in the DirectSound input driver.
<li>
   Hans de Goede added a fullscreen driver for X11 which does not need
   XVidMode extension, and instead simply centers the window on the desktop
   and draws a black border around.
<li>
   Hans de Goede fixed a problem where switching to fullscreen mode under X11.
<li>
   Serge Semashko added Enter as a fire key in the demo game.
<li>
   Serge Semashko added fixed problems with Allegro working on Nokia 770.
<li>
   Peter Wang fixed some problems with binary compatibility checking in the
   4.2 branch.
<li>
   Catatonic Porpoise added OpenBSD detection (in addition to FreeBSD and
   NetBSD) and fixed an issue with executable rights not set on the memory
   for the i386 stretcher on UNIX systems.
<li>
   Hans de Goede fixed a bug preventing the ALSA driver to work on big endian
   systems.
<li>
   Elias Pschernig and Chris Robinson fixed binary compatibility checking in
   allegro_init and install_allegro.
<li>
   Catatonic Porpoise fixed the example in the documentation of
   stretch_sprite.
<li>
   Hans de Goede made DIGMID work with absolute paths in the patches.cfg file.
<li>
   Peter Hull added code to make Allegro work better with user-supplied Nibs
   under OSX, as discussed with Thomas Harte.
<li>
   Matthew Leverton added embedding of manifests to the MSVC 8 build process.
<li>
   Neil Walker and Thomas Harte implemented a hardware accelerated
   stretch_blit() for the Windows DX port.
<li>
   Evert Glebbeek corrected a bug when destroying sub-bitmaps under Windows.
<li>
   Evert Glebbeek fixed a bug in pack_fopen_chunk() where a temporary file
   would be created in a non-writable location.
<li>
   Peter Wang changed a "/lib" option to MSVC's link utility to "-lib" as
   reported to be problematic by Karthik Kumar.
<li>
   Peter Wang fixed a crash in dat and grabber due to the return value of
   pack_fopen_chunk() not being checked.
<li>
   Elias Pschernig added support for anti-aliased bitmap fonts.
<li>
   Dennis Busch fixed the short description of add_clip_rect.
<li>
   Thomas Harte and Neil Walker fixed a problem with draw_sprite() and
   sub-bitmaps.
<li>
   Peter Wang fixed scancode_to_name(KEY_NUMLOCK) returning "PAUSE" in Windows.
<li>
   Peter Wang fixed page flipping and triple buffering in the demo game.
<li>
   Elias Pschernig added list_config_sections and list_config_entries
   functions.
<li>
   Hrvoje Ban added create_datafile_index and load_datafile_object_indexed
   functions.
<li>
   Peter Hull allowed use of "mingw" instead of  "mingw32" in fix.bat and
   fix.sh.
<li>
   Peter Wang fixed a bug with SWITCH_BACKAMNESIA mode with the fbcon graphics
   driver.
<li>
   Peter Wang made the svgalib driver save and restore the palette on VT
   switches.
<li>
   Peter Wang fixed a problem with the fbcon driver and VT switching.
<li>
   Milan Mimica delayed Linux console initialisation until it is required.
   This way the user can write command-line programs using timers  without
   needing a real console.
<li>
   Chris Jones fixed behavior of numeric keys when NumLock is on.
<li>
   Vincent Penecherc'h worked around a problem with 24-bit bitmaps in
   the assembler code.
<li>
   Tobias Dammers fixed a problem with the DirectSound input driver.
<li>
   Matthew Leverton fixed Ctrl-Alt-Del mistakenly being captured by Allegro
   under Windows
<li>
   Vincent Penecherc'h improved the implementation of set_ramp_cmap in the
   fbcon driver.
<li>
   Vincent Penecherc'h implemented get_refresh_rate for the fbcon driver.
<li>
   Vincent Penecherc'h fixed problems with the fbcon driver not restoring the
   original video mode when the driver exits.
<li>
   Victor Williams Stafusa da Silva made OS type detection handle Windows 2003
   and Windows Vista.
<li>
   Chris Jones and Vincent Penecherc'h fixed load_wav to handle degenerate
   stereo wave files with an odd length.
<li>
   Annie Testes fixed all sorts of problems with the linux evdev mouse driver
   when using a tablet as the mouse.
<li>
   Annie Testes made the linux evdev mouse driver use the correct device files.
<li>
   Vincent Penecherc'h made the linux fbcon driver set a ramp colourmap for
   directcolor modes, otherwise colours in those modes were all wrong.
<li>
   Vincent Penecherc'h fixed a problem with the linux fbcon driver, where it
   would keep using the old pitch after changing resolutions.
<li>
   Serge Semashko fixed a typo causing crashs in
   _linear_draw_trans_rgba_rle_sprite24.
<li>
   Annie Testes fixed cursor speed and incorrect mickey computation bugs in
   the Linux evdev mouse driver.
<li>
   Vincent Penecherc'h made the Linux PS/2 mouse driver try /dev/input/mice
   by default, in addition to /dev/mouse.
<li>
   Warnings, code formatting and minor changes to code and build system
   by Milan Mimica, Evert Glebbeek, Elias Pschernig, Peter Wang, Peter
   Hull, Thomas Harte, Vincent Penecherc'h and Chris Robinson.
<li>
   Documentation updates by Tore Halse, Elias Pschernig, Milan Mimica,
   Peter Wang, Physics Dave, Ryan Patterson, Grzegorz Adam Hankiewicz,
   Andrei Ellman and Evert Glebbeek.
</ul>

]]></text></section><section title="Changes from 4.2.0 RC2 to 4.2.0 (November 2005)"><text><![CDATA[<ul><li>
   Peter Wang made fixmul() detect overflows as it used to do in the 4.0.x
   branch.
<li>
   Peter Hull fixed a bug in the fixbundle utility.
<li>
   Dennis Busch found a bug where d_clear_proc would not work properly if the
   GUI target bitmap is	different from screen.
<li>
   Grzegorz Adam Hankiewicz made Allegro log all TRACE output with a prefix
   in the format "al-system level: ". This makes it easier to grep debug logs.
<li>
   Grzegorz Adam Hankiewicz made dialogs with MSG_CHAR/MSG_UCHAR handlers
   honor a D_CLOSE return flag without a D_USED_CHAR.
<li>
   Peter Hull fixed problems with the mouse position as reported by Allegro and
   the mouse position as known to OS X.
<li>
   Peter Hull made Command-Q not close the application if no exit-button
   callback is registered.
<li>
   Peter Hull fixed problems with joysticks under MacOS X as reported by
   Thomas Harte.
<li>
   Peter Hull fixed a bug preventing more than one Allegro application from
   being run at a time on Mac OS X. Reported by Thomas Harte.
<li>
   Peter Hull did a lot of other things for the MacOS X port too.
<li>
   Jiri Gabriel fixed loading of multiple ranges in a single bitmap with txt
   fonts.
<li>
   Milan Mimica and Jiri Gabriel fixed several bugs in extract_font_range.
<li>
   Dennis Busch fixed a Unicode bug in the mode selector.
<li>
   Evert Glebbeek added FA_ALL and FA_NONE file attribute flags.
<li>
   Peter Hull fixed a deadlock in OS X when calling vsync() while the screen
   was acquired.
<li>
   Robert Alfonso fixed a grabber crash when importing a new font range into an
   existing font. Reported by Milan Mimica.
<li>
   Chris Robinson fixed the fileselector in UNIXnot properly recognising
   filenames containing UTF-8 characters.
<li>
   Hrvoje Ban and Peter Wang wrote a documentation section that explains
   several common mistakes.
<li>
   Elias Pschernig disabled DGA auto-detection under X11
<li>
   i_am_drv added support for .rmi midis to the midi reader
<li>
   Elias Pschernig fixed a fix-point overflow in pivot_sprite.
<li>
   Michal Molhanec fixed several problems with the Watcom compiler.
<li>
   Peter Hull fixed an error with 'make uninstall' on MacOS X.
<li>
   Matthew Leverton added a programs: makefile target.
<li>
   Many small fixes and improvements by Michal Molhanec, Peter Hull, Chris
   Robinson, Peter Wang and Elias Pschernig.
<li>
   Documentation improvements by Grzegorz Adam Hankiewicz, Tore Halse and
   Peter Hull.
</ul>

]]></text></section><section title="Changes from 4.2.0 RC1 to 4.2.0 RC2 (August 2005)"><text><![CDATA[<ul><li>
   Grady Martin made the grabber consider deleting object properties as a
   change to the datafile.
<li>
   Milan Mimica fixed numerous bugs in extract_font_range().
<li>
   Peter Hull moved the 'magic chdir' in the MacOS X port to earlier in the
   startup process, so that the config file will be looked for in the
   resource directory if is present.
<li>
   Chris Robinson made create_bitmap(0,0) not return a bitmap that would
   later crash destroy_bitmap().  Zero-sized bitmaps are still not allowed so
   the assertions for debug mode have not changed.
<li>
   Elias Pschernig patched the Windows keyboard driver to get key_shifts
   working again with KB_SHIFT_FLAG, KB_CTRL_FLAG, KB_ALT_FLAG on Win98.
<li>
   Peter Wang changed hline and vline into aliases for internal symbols to
   avoid a conflict with the curses API. This change should be transparent
   for users.
<li>
   Matthew Leverton and Michal Molhanec updated the build system for MSVC 8.
<li>
   Grzegorz Adam Hankiewicz prevented make_relative_filename() from crashing
   with malformed parameters.
<li>
   Hrvoje Ban made ASSERT() actually abort in Windows.
<li>
   Chris Robinson made GUI menus work with gui_screen.
<li>
   Evert Glebbeek fixed reading of 32 bit Windows .bmp files, which was not
   supported.  These files seem to be not very standard though, so it's
   unclear if it will always do the right thing.  Alpha channels also seem
   not to be standard in 32 bit BMP files, so it's possible they're not read
   in correctly.
<li>
   Peter Wang and Peter Hull updated the ABI compatibility document.  This
   documents our policy for the 4.2.x series.
<li>
   Extensive documentation updates from Grzegorz Adam Hankiewicz and minor
   updates due to Michael Faerber, Robert Ohannessian and Milan Mimica.
</ul>

]]></text></section><section title="Changes from 4.2.0 beta 4 to 4.2.0 RC1 (August 2005)"><text><![CDATA[<ul><li>
   Peter Hull fixed the MacOS X port to avoid an issue with the dead bootstrap
   context and cleaned up the dock notification. This means command line
   apps (with SYSTEM_NONE) run without the dock being notified.
<li>
   Peter Wang Added a COLORCONV_KEEP_ALPHA flag, as suggested by Gideon Weems.
<li>
   Peter Wang fixed issues with OSS in OpenBSD and made the configure script
   print a warning if Allegro is compiled without X11 support.
<li>
   Peter Hull set the compatibility version to 4.2.0 for MacOS X and added a
   MacOS X help file.
<li>
   Peter Wang made the Mode-X and VBE/AF drivers fail if Allegro is compiled
   as a C-only library in Linux and made the Unix port install liballeg*.so
   and the alleg-*.so modules with the execute permission enabled.
<li>
   Grady Martin standardised some of the grabber dialog boxes and added a `move'
   command to the grabber.
<li>
   Evert Glebbeek fixed a bug when loading some old datafiles containing
   monochrome fonts.
<li>
   Evert Glebbeek fixed a bug that prevented system cursors from working
   correctly in Windows.
<li>
   Olivier Blin fixed compilation problems for the ModeX driver with newer
   binutils.
<li>
   Shawn Walker fixed a bug in get_executable_name under some UNIX systems.
<li>
   Shawn Walker worked around a problem with some versions of GNU AS and fixed
   some errors in the configure script when not using GCC.
<li>
   Elias Pschernig made create_sample not unnecessarily clear the sample to 0.
<li>
   Bobby Ferris fixed the makedoc SciTE API output.
<li>
   Elias Pschernig fixed a too strict assert that prevented set_volume from
   working in debug mode.
<li>
   Paavo Ahola helped fix a problem with BCC and the C implementations of
   fixmul.
<li>
   Elias Pschernig fixed a cosmetic bug where the listbox was drawing a too big
   selection rectangle, reported by dthompson.
<li>
   Documentation and example updates by Grzegorz Adam Hankiewicz, Peter
   Wang, Elias Pschernig Michal Molhanec and Evert Glebbeek.
</ul>

]]></text></section><section title="Changes from 4.2.0 beta 3 to 4.2.0 beta 4 (June 2005)"><text><![CDATA[<ul><li>
   Matthew Leverton changed the default behavior of the grabber: default color
   depth is now the desktop, default mode is windowed and if fullscreen is
   specified, then desktop resolution is used by default.
<li>
   Peter Wang fixed compilation problems related to get_modex_screen() on
   UNIX and deprecated it.
<li>
   Robert Ohannessian fixed compilation problems for the assembler code with
   newer binutils.
<li>
   Peter Wang, Thomas Harte and Evert Glebbeek optimised fixmul() for different
   platforms.
<li>
   Robert Alfonso fixed a couple of warnings that with DJGPP.
<li>
   Grzegorz Adam Hankiewicz made the FLIC player yield.
<li>
   Miran Amon fixed an arbitrary limit in get_config_argv(). Evert Glebbeek
   fixed a memory leak in same.
<li>
   Thomas Klausner fixed a problem in allegro.m4 and automake 1.8+.
<li>
   Charles Wardlaw fixed some warnings with gcc 4 on MacOS X.
<li>
   Elias Pschernig removed the `256 items' limit from the dat utility.
<li>
   Julien Cugniere fixed a crash in the GUI if a new dialog was opened while
   a menu was still open.
<li>
   Shawn Walker fixed crashes with the keyboard driver under Solaris.
<li>
   Elias Pschernig split the demo game into multiple files and made the
   makefile handle a multi-file demo game.
<li>
   Evert Glebbeek fixed a bug where the hardware mouse wasn't displayed in
   Windows until the mouse was moved.
<li>
   J.P. Morris fixed rest_callback() under UNIX.
<li>
   Shawn Walker and Evert Glebbeek fixed get_executable_name() under
   Solaris and OpenBSD.
<li>
   Peter Hull fixed compilation problems with setAppleMenu under Tiger.
<li>
   Peter Hull fixed a deadlock on MacOS X related to mouse updating.
<li>
   Peter Wang fixed a problem with compiling the VBE/AF driver using newer
   binutils.
<li>
   Evert Glebbeek fixed a bug with colour conversions when loading a font from
   a datafile.
<li>
   Many code, example and documentation updates by Grzegorz Adam Hankiewicz,
   Elias Pschernig, Peter Wang, Evert Glebbeek, Andrei Ellman,
   Victor Williams Stafusa da Silva, Matthew Leverton, AJ, Michal Molhanec
   and Hrvoje Ban.
</ul>

]]></text></section><section title="Changes from 4.2.0 beta 2 to 4.2.0 beta 3 (May 2005)"><text><![CDATA[<ul><li>
   Grzegorz Adam Hankiewicz did several documentation updates.
<li>
   Evert Glebbeek cleaned up some of the global namespace pollution in the
   Windows port.
<li>
   Chris Robinson made improvements to the Windows sound driver.
<li>
   Chris Robinson made the GUI multi-selection box behave a bit nicer.
<li>
   Grzegorz Adam Hankiewicz added a bunch of ASSERTs to the code to check for
   out-of-range arguments.
<li>
   Jakub Wasilewski fixed a bug when loading greyscale TGA images.
<li>
   Evert Glebbeek fixed a bug where the bottom and right line of pixels was
   not updated on show_video_bitmap, as pointed out by Thomas Harte.
<li>
   Evert Glebbeek documented JOY_TYPE_* defines for Windows and Linux.
<li>
   Dark Nation restored the ability to read old-style encrypted packfiles,
   i.e. those produced before Allegro 3.9.30.  This was silently removed
   from 4.1.18 when custom packfile support / decoupled compression routines
   were added.
<li>
   Evert Glebbeek made the grabber and dat utilities now use Allegro's builtin
   load_font() function and made datafiles properly store truecolour fonts and
   added a datedit_select() callback to datedit.
<li>
   Evert Glebbeek fixed some unsafe assumptions on the size of integer
   data types.
<li>
   Arthur Huillet fixed a typo in the docs.
<li>
   Elias Pschernig restored Alt+key = ASCII code 0 behavior for the Windows
   keyboard driver
<li>
   Evert Glebbeek fixed a bug that caused a crash when loading Allegro 1.x
   datafiles containing 4 bit bitmaps.
<li>
   Peter Wang clarified the mode select documentation and made the mode
   selector clear the input variables before passing them on to the filter.
<li>
   Peter Wang fixed a bug in the mode selector where disabled drivers were
   still shown with empty resolution lists. Pointed out by Hrvoje Ban.
<li>
   Elias Pschernig fixed Allegro's internal multithreading in Windows. This
   fixes a deadlock on exit.
<li>
   Robert Alfonso made the MSVC makefile call `link /lib' rather than `lib',
   which doesn't work for the free toolkit.
<li>
   Peter Hull fixed a problem with hardware cursors not working properly in
   MacOS X.
<li>
   Peter Hull added a missing enable_hardware_cursor vtable entry and added OS
   native cursors for the MacOS X port.
<li>
   Grzegorz Adam Hankiewicz documented the online Allegro patch generator.
<li>
   Evert Glebbeek renamed datafiles._tx -> datafile._tx
<li>
   StApostol updated the FAQ to use rest(0) instead of the deprecated yield_timeslice().
<li>
   Evert Glebbeek silenced some GCC4 warnings in MacOS X.
<li>
   Peter Wang fixed warnings and errors with gcc 4.0.0 on the Unix port;
   reported by Milan Mimica.
<li>
   Peter Wang added the preprocessor symbol ALLEGRO_NO_FIX_CLASS that the user
   can define to not pull in the `fix' class in C++ programs.
<li>
   Peter Wang removed the exdodgy example.
<li>
   Elias Pschernig fixed another X11 async reply bug.
<li>
   Elias Pschernig made the seek in expackf test work with CR/LF line endings.
<li>
   Evert Glebbeek fixed a small bug that prevented the Allegro template for
   Project Builder from installing correctly on MacOSX.
<li>
   Elias Pschernig enabled warnings about unused variables with
   --enable-strictwarn in unix.
<li>
   Peter Wang fixed a warning with Watcom 1.3.
</ul>

]]></text></section><section title="Changes from 4.2.0 beta 1 to 4.2.0 beta 2 (April 2005)"><text><![CDATA[<ul><li>
   Daniel Schlyder fixed a problem with the makefile in Windows.
<li>
   Evert Glebbeek fixed a bug that prevented true colour fonts from working.
<li>
   Peter Wang fixed a possible deadlock in dialog_message.
<li>
   Elias Pschernig fixed a bug where the DJGPP version would choke on a missing
   variable.
<li>
   Peter Hull made makedoc return an error code if it failed to build the
   SciTE documentation.
<li>
   Evert Glebbeek fixed a problem with incorrect dependencies being generated
   for MacOS X.
<li>
   Tobi Vollebregt fixed a problem in X11 if the XRGBACursor extension was
   missing.
<li>
   Evert Glebbeek made configure use k8 rather than athlon64 as a compiler
   switch on AMD64.
<li>
   Peter Wang and Elias Pschernig added a packfile example.
<li>
   Michal Molhanec fixed a problem in the MSVC makefile.
<li>
   Evert Glebbeek removed void*-arithmetic from the colour converter.
<li>
   Evert Glebbeek fixed a bug where hardware cursors would stop working.
<li>
   Elias Pschernig, Andrew Chew fixed and Tobi Vollebregt fixed several
   problems with the Windows keyboard driver.
<li>
   Elias Pschernig fixed bug in unix dependency generation.
<li>
   Elias Pschernig made the GUI not mess up the hardware cursor.
<li>
   Elias Pschernig removed pckeys.c and keyconf from the windows port, since
   the dinput driver no longer needs pckeys.c nor uses keyboard.dat.
<li>
   Daniel Schlyder fixed a problem with the -mtune switch on older gcc based
   compilers.
<li>
   Matthew Leverton figured out which versions of Watcom have inttypes.h and
   stdint.h.
<li>
   V Karthik Kumar added a password to the Windows screensaver example.
<li>
   Cosmetic fixes, example bugfixes and spelling corrections by Jon Rafkind,
   Evert Glebbeek, Peter Wang, StApostol and Elias Pschernig.
</ul>

]]></text></section><section title="Changes from 4.1.18 to 4.2.0 beta (March 2005)"><text><![CDATA[<ul><li>
   Peter Wang fixed many problems on AMD64 in Linux - it should now work fine.
<li>
   Peter Hull added CPU detection to the MacOS X port.
<li>
   Peter Hull fixed some problems related to /usr/local/bin not existing in
   recent versions of MacOS X.
<li>
   Elias Pschernig and Peter Wang rewrote the Windows keyboard driver so it
   no longer needs keyboard.dat.
<li>
   Elias Pschernig added a show_os_cursor function as an alternative to
   show_mouse() for system cursors.
<li>
   Evert Glebbeek and Peter Wang added an example programme for system cursors.
<li>
   Elias Pschernig fixed a deadlocks in X11 related to scare_mouse() and
   keyboard repeats and fixed async replies.
<li>
   Daniel Schlyder fixed the gcc -mcpu is deprecated warnings.
<li>
   Peter Wang added an astdint.h, which provides C99 typedefs for pre-C99
   compilers.
<li>
   AJ added detection for DirectX 8 and 9 to the Windows port.
<li>
   Evert Glebbeek added detection for AMD64 to the UNIX port and test
   programme.
<li>
   Elias Pschernig added a get_midi_length function and a midi_time variable.
<li>
   Elias Pschernig fixed a problem where Allegro would ignore a user-specified
   configuration file if set_config_file() was called before allegro_init().
<li>
   Evert Glebbeek added a transpose_font function.
<li>
   Evert Glebbeek added support for true colour fonts and a font example.
<li>
   Elias Pschernig fixed a problem in shutdown_dialog() reported by Tobi
   Vollebregt.
<li>
   Marcio Fialho fixed some issues with displaying author names in the demo
   game.
<li>
   Andrei Ellman fixed a problem in the MSVC makefile when building Allegro
   with Cygwin.
<li>
   Daniel Schlyder fixed (again) problems with creating directories in
   different setups in Windows.
<li>
   Elias Pschernig added documentation for the custom packfile functions.
<li>
   Jeff Mitchell fixed the location of grabber.txt in the spec file.
<li>
   Harshavardhana Reddy added a Kannada greeting to exunicod.
<li>
   Elias Pschernig cleaned up the example programmes.
<li>
   Peter Wang made it possible to disable the hardware cursor in X by passing
   an option to the configure script.
<li>
   AJ and Michal Molhanec added an MSVC 7 configure option and added an msvc7
   switch to fix.bat. Karthik Kumar did the same for the Intel compiler icl.
<li>
   Mr_Bones fixed compilation of setup.c when --disable-ossdigi is used
<li>
   AJ fixed a beep being generated in Windows when alt+character was pressed
   in Windowed mode.
<li>
   Peter Wang fixed many oversights and problems in the library and examples and
   allowed the code to be build with stricter warnings.
<li>
   Peter Wang fixed problems compiling the Windows port with WARNMODE=1
<li>
   Tore Halse fixed compilation problems in Windows related to TITLEBARINFO.
<li>
   Daniel Schlyder made the Windows port use TITLEBARINFO if it is available.
<li>
   Grzegorz Adam Hankiewicz made many improvements to the documentation.
</ul>

]]></text></section><section title="Changes from 4.1.17 to 4.1.18 (January 2005)"><text><![CDATA[<ul><li>
   Peter Hull fixed a bug that caused rest() to wait too long on MacOS X.
<li>
   Tore Halse made the Allegro window always appear centred in Windows.
<li>
   Peter Wang fixed a lot of warnings in the code and did a lot of cosmetic
   fixes as well.
<li>
   Grzegorz Adam Hankiewicz added short description support to the MAN and
   HTML documentation.
<li>
   Milan Mimica fixed a bug in the keyconf utility.
<li>
   Peter Hull fixed some issues compiling Allegro for MacOS X.
<li>
   Marcio Fialho fixed a warning when compiling Allegro with DJGPP.
<li>
   Evert Glebbeek fixed a bug that prevented system cursors from working in
   Windows, as pointed out by Peter Johansson.
<li>
   Evert Glebbeek added a font loading routine and various other font
   functions to the library.
<li>
   Peter Wang added custom packfile functions and packfile vtables.
<li>
   Peter Wang decoupled the packfile compression code from the packfile
   routines.
<li>
   Daniel Schlyder fixed some problems with the font loading code.
<li>
   AJ added IA64, SSE3 and AMD64 detection code.
<li>
   Daniel Schlyder fixed some warnings with MinGW gcc 3.4.2
<li>
   Peter Hull made the file selector work properly with directories that have
   more than 2048 entries.
<li>
   Marcio Afonso Arimura Fialho fixed some problems with the DJGPP version and
   the VBE/AF driver.
<li>
   Phil Shenk clarified the MSVC build docs.
<li>
   Michal Molhanec fixed a problem with long filenames in the MSVC build
   process and added a --msvcpaths flag to the fix.bat script.
<li>
   Grzegorz Adam Hankiewicz made a lot of improvements to the documentation.
<li>
   Peter Wang made some modifications to allegro_message() in X11.
<li>
   Evert Glebbeek added blender mode defines and activated the gfx_vtable
   set_blender_mode() function in the source.
<li>
   Evert Glebbeek added gui_set_screen and gui_get_screen functions and a
   set_mouse_cursor_bitmap function.
<li>
   Peter Wang made scancode_to_name never return NULL.
<li>
   Peter Wang fixed some problems in the Linux joystick driver.
<li>
   Grzegorz Adam Hankiewicz added a lot of ASSERTions to the code.
<li>
   Elias Pschernig added special Ctrl-Alt-End and Pause key handlers to the
   X11 keyboard driver.
<li>
   Elias Pschernig fixed a problem with the mouse acceleration in Windows.
</ul>

]]></text></section><section title="Changes from 4.1.16 to 4.1.17 (December 2004)"><text><![CDATA[<ul><li>
   Sven Sandberg fixed a few problems with the sprite rotation code.
<li>
   Sven Sandberg optimized blitting between different colour depths.
<li>
   Evert Glebbeek added support for the use of native window manager cursors.
<li>
   Chris Robinson made install_allegro() check if the library version matches
   the version of the header files installed.
<li>
   Peter Wang fixed some problems with rest() on UNIX systems.
<li>
   Evert Glebbeek added an is_windowed_mode() function.
<li>
   Elias Pschernig added the scancode_to_name function.
<li>
   Elias Pschernig made rest use usleep() on MacOSX.
<li>
   Chris Robinson fixed the incorrect use of -export-dynamic on UNIX
<li>
   Elias Pschernig, Chris Robinson and Peter Wang fixed XOR mode leaving
   droppings in X11.
<li>
   Elias Pschernig fixed several dependency issues.
<li>
   James Lohr fixed a problem with mouse acceleration in fullscreen modes under
   Windows.
<li>
   Peter Wang fixed a problem in the TGA loader.
<li>
   Lennart Steinke contributed keyboard layout detection code for Windows.
<li>
   Peter Wang fixed a bug that caused Allegro to crash if it failed to
   initialize.
<li>
   Peter Wang fixed a deadlock related to X vsync emulation.
<li>
   Daniel Schlyder fixed make uninstall with mingw make.
<li>
   Elias Pschernig fixed QNX issue of not including utimer.c
<li>
   Angelo Mottola fixed compilation problems on BeOS and fixed the detection
   of VRAM.
<li>
   Evert Glebbeek fixed compilation problems on *BSD.
<li>
   Elias Pschernig made the X11 window hidden in GFX_TEXT mode.
<li>
   Peter Wang removed remapping of numpad keys when NumLock was off in Linux
<li>
   David A. Capello made override_config_file also be used for writing to the
   config file.
<li>
   Julien Cugniere added an X11 message box for allegro_message under X11.
<li>
   Vitaliy Chetverikov a small bug in the GUI where the return value of
   MSG_IDLE was ignored.
<li>
   Peter Wang made several improvements to the examples.
<li>
   Grzegorz Adam Hankiewicz made a lot of improvements to the documentation.
<li>
   Elias Pschernig made make-install not build examples.
<li>
   Peter Wang fixed several instances of symbols not declared static that should
   have been.
<li>
   Elias Pschernig replaced the X11 keyboard driver with a new XIM driver.
<li>
   Peter Wang fixed a problem with Linux headers and Allegro headers both
   declaring KEY_ constants, as pointed out by David A. Capello.
<li>
   Elias Pschernig fixed X11 async reply in DGA2 mode detection due to missing
   XLOCK/XUNLOCK
<li>
   Peter Wang fixed problems in ex3buf, which was trying to lock symbols which
   had been removed.
<li>
   Elias Pschernig cleaned up grabber/dat documentation.
<li>
   Daniel Schlyder added ALLEGRO_LIB_BUILD flag for gcc variants not using
   configure.
<li>
   Elias Pschernig fixed bugs in matrix_to_quat and get_align_matrix.
<li>
   Evert Glebbeek fixed a problem with the X11 port when
   ALLEGRO_MULTITHREADED was not defined.
<li>
   Matthew Leverton added support for a fourth mouse button to the Windows port.
<li>
   Michal Molhanec added a FAQ section about the giftware license.
<li>
   Elias Pschernig added the license disclaimer to the docs.
<li>
   Evert Glebbeek added missing vtable entries for AllegroGL, as requested by
   Robert Ohannessian.
<li>
   Dustin Dettmer spotted a typo in save_bitmap.
<li>
   Sam Hocevar removed deprecated use of init_read_test, test_byte_read, etc.
<li>
   Peter Wang fixed a bug in the Windows keyboard driver.
</ul>

]]></text></section><section title="Changes from 4.1.15 to 4.1.16 (October 2004)"><text><![CDATA[<ul><li>
   Peter Wang fixed two problems with the keyboard driver on Windows.
<li>
   Chris Robinson fixed a problem causing some components to wrongly
   initialized in Windows when the window is set.
<li>
   Elias Pschernig added chapters to the documentation.
<li>
   Chris Robinson fixed a bug where the X11 fullscreen driver would fail if
   no virtual screen was reported.
<li>
   Daniel Schlyder added a set_allegro_resource_path() function .
<li>
   Elias Pschernig fixed an issue with xf2pcx.
<li>
   David A. Capello made makedoc write sub-section headings for .txt output.
<li>
   Evert Glebbeek added hardware cursor support to the X11 and DirectX window
   drivers.
<li>
   Peter Wang made the Linux joystick driver read more than one joystick
   event at a time, as pointed out by Greg Lee.
<li>
   Evert Glebbeek removed the need for magic main under UNIX and added a
   --enable-magicmain option to the configure script.
<li>
   Evert Glebbeek fixed a crash when initializing, deinitializing and
   reinitializing Allegro on Windows.
<li>
   Evert Glebbeek fixed a possible memory protection problem in stretch_blit
   on Windows XP SP2, as suggested by Chris Robinson.
<li>
   Chris Robinson fixed set_palette() not waiting for vsync in X11.
<li>
   Peter Wang deprecated the retrace simulator.
<li>
   Daniel Verkamp contributed a MIDI input driver for the Windows port.
<li>
   Chris Robinson improved the speed of drawing primitives on X11 and
   implemented locking/unlocking for video bitmaps.
<li>
   Evert Glebbeek fixed a problem with the build process on non-intel UNIX
   systems.
<li>
   Peter Wang fixed a problem with programs aborting on exit under X11.
<li>
   Peter Wang disabled VBE/AF by default on Linux.
<li>
   Sam Hocevar fixed a bug where makedoc would crash for missing @erefs.
<li>
   Peter Wang made the mouse movement appear smoother.
<li>
   Chris Robinson made the file routines work with files containing a # in the
   filename.
<li>
   Peter Wang fixed a bug in remove_int().
<li>
   Bobby Ferris added SciTE .api file generation to makedoc.
<li>
   Sam Hocevar made is possible to put functions defined in assembler
   source files in a shared library in UNIX.
<li>
   Evert Glebbeek removed the weak declaration of allegro_icon and changed
   xfixicon.sh accordingly.
<li>
   Evert Glebbeek made get_executable_name() use procfs on UNIX.
<li>
   Grzegorz Adam Hankiewicz made many improvements to the documentation and
   to the makedoc tool.
<li>
   Many fixes to source, examples and documentation.
</ul>

]]></text></section><section title="Changes from 4.1.14 to 4.1.15 (July 2004)"><text><![CDATA[<ul><li>
   Chris Robinson tweaked tests/play.c slightly.
<li>
   Elias Pschernig deprecated yield_timeslice in favour of rest(0) and adjusted
   yield_timeslice on BeOS, QNX and MacOS X to behave the same as on other
   platforms.
<li>
   Eric Botcazou fixed a problem with the asm colour converter.
<li>
   Elias Pschernig fixed some gcc warnings.
<li>
   Vincent Penquerc'h added the ability to pass extra CFLAGS and LDFLAGS on the
   make command line.
<li>
   Elias Pschernig made ex3buf work outside of DOS.
<li>
   Chris Robinson made the alleg mixer default instead of the DirectX one in
   windows.
<li>
   Angelo Mottola fixed a bug where vsync() was blocking on a mutex if called
   when the screen was already acquired in windowed mode.
<li>
   Evert Glebbeek made triple buffering work in the demo if VRAM is a single
   surface.
<li>
   Jon Rafkind provided an m4 macro for Allegro.
<li>
   Eric Botcazou and Henrik Stokseth made some improvements to the build
   process.
<li>
   Grzegorz Adam Hankiewicz added various fixes to the documentation and
   to the documentation generation system.
<li>
   V Karthik Kumar added a Tamil language greeting to exunicode.
<li>
   Chris Robinson and Elias Pschernig reduced lag under X11 when X11
   locks are held for too long.
<li>
   Vincent Penquerc'h fixed a problem with dependency generation under
   bash.
<li>
   Evert Glebbeek added an icon to the X11 port and contributed the xfixicon
   script.
<li>
   Angelo Mottola fixed an endianess issue when loading/saving 24 bit
   images from datafiles.
<li>
   Angelo Mottola made datafile plugins return FALSE on error.
<li>
   Angelo Mottola fixed the docs for pack_putc.
<li>
   Vincent Penquerc'h made the grabber choose better default menu
   shortcuts.
<li>
   Henrik Stokseth enabled the asm color converters for the X11 port.
<li>
   Henrik Stokseth improved buffer security in various parts of the
   library.
<li>
   Evert Glebbeek made strncpy use sizeof() for fixed length strings.
<li>
   Eric Botcazou made KEY_PAUSE work properly in windows.
<li>
   Chris Robinson improved the threaded UNIX timer code.
<li>
   Elias Pschernig fixed some problems with the ALSA driver.
<li>
   Angelo Mottola made  Command-Q and Quit trigger the
   close_button_callback in OSX.
<li>
   Grady Martin fixed a bug in the handling of %n in the printf style
   text functions.
<li>
   Chris Robinson rewrote parts of Allegro's mixer.
<li>
   Chris Robinson increased the default volume, which was set very quiet
   previously.
<li>
   Grzegorz Adam Hankiewicz clarified the behavior of install_mouse.
<li>
   Elias Pschernig improved the pause key behavior.
<li>
   Vincent Penquerc'h added MSG_WANTMOUSE to the GUI.
<li>
   Vincent Penquerc'h sped up get_filename.
<li>
   Chris Robinson implemented the digmid_set_pan function
<li>
   Chris Robinson improved the performance of the DIGMID driver.
</ul>

]]></text></section><section title="Changes from 4.1.13 to 4.1.14 (April 2004)"><text><![CDATA[<ul><li>
   Elias Pschernig added a missing install dependency on Linux.
<li>
   Elias Pschernig fixed a couple of problems in dat2c.
<li>
   Angelo Mottola polished the MacOS X package builder script.
<li>
   Elias Pschernig added a Jack sound driver to the Unix port.
<li>
   Henrik Stokseth added support for debugging with DMalloc under Unix.
<li>
   Eric Botcazou fixed detection of the ALSA 1.0 MIDI driver.
<li>
   Eric Botcazou fixed compilation with --enable-color8=no under Unix.
<li>
   Angelo Mottola made it possible to link against the Allegro framework
   with the allegro-config script under MacOS X.
<li>
   Angelo Mottola changed the dynamic lib install name to major.minor to
   preserve binary compatibility under MacOS X.
<li>
   Angelo Mottola fixed a bug in fixbundle with 32bpp icons and alpha channel
   under MacOS X.
<li>
   Eric Botcazou improved the cross-compilation support on Linux.
<li>
   Eric Botcazou restored the compensation code for end-of-frame in the FLI
   player.
<li>
   Daniel Schlyder fixed potentially unsafe constructs in the Windows code.
</ul>

]]></text></section><section title="Changes from 4.1.12 to 4.1.13 (March 2004)"><text><![CDATA[<ul><li>
   Minor changes and clarifications in the docs by Sven Sandberg, Andy Goth,
   Jon Rafkind, Nathan Smith and Daniel Schlyder.
<li>
   Elias Pschernig extensively modified the ALSA 0.9/1.0 sound driver to make
   it work more nicely.
<li>
   Julien Cugniere and Eric Botcazou fixed the crash on exit with the aRts
   sound driver.
<li>
   Nathan Smith implemented the recursive handling of directories for the
   dat utility.
<li>
   Eric Botcazou renamed the new '-r' option of the dat utility into '-f'.
<li>
   Omar Cornut improved the handling of KEY_COLON2 on Japanese keyboards.
<li>
   Omar Cornut fixed the Windows joystick driver to handle a weird peculiarity
   of the DirectInput API.
<li>
   Elias Pschernig corrected the value of the alpha-channel depth field in the
   header when saving TGA image files.
<li>
   Eric Botcazou fixed again the formula giving the stride value in the Linux
   framebuffer console.
<li>
   Eric Botcazou restored the pixel-correct version of line() and added
   fastline() after Doug Eleveld had reported the problem.
<li>
   Andy Goth and Eric Botcazou fixed the constructor support in dat2s on Unix.
<li>
   Angelo Mottola revamped the MacOS X package creation process to make it
   work under 10.3 and create an enduser package that holds just the shared
   framework.
<li>
   Angelo Mottola changed the MacOS X shared library building process to have
   a prebound shared library separated from a small static libray holding just
   the magic main stuff.
<li>
   Angelo Mottola removed window shadow flickering when moving the program
   window around on MacOS X.
<li>
   Elias Pschernig changed the behavior of yield_timeslice() to sleeping
   instead of just yielding.
<li>
   Angelo Mottola made the MacOS X port reuse the screen on the first video
   bitmap creation and made the screen fade on mode switches faster.
<li>
   Elias Pschernig made d_menu_proc() automatically yield when the dialog
   is driven by do_dialog().
<li>
   Elias Pschernig added missing d_yield_proc()s to the grabber.
<li>
   Eric Botcazou fixed a bug which caused too many sliders to be reported
   in the presence of a POV device on Windows.
<li>
   Chris Jones added support for the bitfield compressed BMP image format.
<li>
   Eric Botcazou removed all uses of GCC's cast-expression-as-lvalue
   extension in preparation for GCC 3.4.
<li>
   Michal Molhanec replaced all occurences of MingW32 by MinGW in the docs.
<li>
   Omar Cornut bumped the maximum number of buttons per joystick to 32.
<li>
   Eric Botcazou implemented automatic screensaver disabling (only on
   Windows for the time being).
<li>
   Elias Pschernig added mode 1280x960 to the gfx mode selector.
<li>
   Elias Pschernig fixed the video mode error display in the test program.
<li>
   Eric Botcazou fixed the final animation of the demo game.
<li>
   Elias Pschernig made the X11 gfx driver ignore repeated key-events.
<li>
   Eric Botcazou added set_hardware_volume().
<li>
   Francisco Pires added an FPS counter and an option to disable vsync to
   the excamera example.
<li>
   Eric Botcazou and Sven Sandberg documented the limitations of getpixel()
   and added is_inside_bitmap().
<li>
   Eric Botcazou added i386 sincos optimization to GCC-based ports.
<li>
   David Capello fixed a bug with FLI frames containing odd-sized chunks.
<li>
   Elias Pschernig and Sven Sandberg improved the GUI focus algorithm.
<li>
   Eric Botcazou modified the dat/grabber plugins interface to expose
   datafile properties to plugins.
<li>
   Eric Botcazou added a new clipping API and deprecated the old one.
<li>
   Grzegorz Adam Hankiewicz updated the MSVC build instructions.
</ul>

]]></text></section><section title="Changes from 4.1.11 to 4.1.12 (Nov 2003)"><text><![CDATA[<ul><li>
   Many minor changes and clarifications in the docs, some of them based on
   suggestions by Neil Roy, Jon Rafkind, aj, Andrei Ellman and Michal
   Molhanec.
<li>
   Angelo Mottola made little fixes all over the place in the MacOS X port.
<li>
   Angelo Mottola removed MacOS X 10.1.x source compatibility.
<li>
   Eric Botcazou disabled keyconf on platforms that don't need it.
<li>
   Elias Pschernig shifted key name display so that all keys are visible
   in the keyconf utility.
<li>
   Stephan Brauss added new keysyms to the X11-to-BIOS conversion table in
   order to catch missing keycodes for the keypad when NumLock is on.
<li>
   Stephan Brauss corrected a few nits in the Swiss keyboard configuration
   file.
<li>
   Eric Botcazou disabled the close button support when a user window is
   registered under Windows.
<li>
   Eric Botcazou changed the default switch mode to SWITCH_BACKGROUND for
   the Windows port to cure the problems on exit under WinXP.
<li>
   Sven Sandberg improved the previous fix to _parallelogram_map().
<li>
   Sven Sandberg fixed an overflow in floodfill().
<li>
   Sven Sandberg fixed the dither blit mode for the Mode-X driver.
<li>
   Angelo Mottola added quality and reverberation settings support to the
   CoreAudio MIDI driver under MacOS X.
<li>
   Angelo Mottola added high performance CoreAudio digi/midi drivers (default
   on autodetect) and made little fixes to the old QT Note Allocator and
   Carbon Sound Manager drivers under MacOS X.
<li>
   KronomanX added a FAQ entry about the conflict between Allegro headers and
   the C++ 'using' directive.
<li>
   Vincent Penquerc'h let dialog_message() pass user messages to hidden
   objects.
<li>
   Michal Molhanec simplified the build instructions for Dev-C++.
<li>
   Annie Testes fixed a redrawing problem in the grabber.
<li>
   Vincent Penquerc'h added support for the joystick_device* config variables
   under Linux.
<li>
   Vincent Penquerc'h added gfx_mode_select_filter().
<li>
   Peter Wang removed the old Linux async I/O stuff, which had been out of
   service for a long, long time. Also simplified the Linux standard drivers
   stuff.
<li>
   Thomas Fjellstrom added (experimental) support for ALSA 0.9.x.
<li>
   John Utz corrected a wrong assumption about the VRAM layout in the Linux
   framebuffer console driver.
<li>
   Grzegorz Adam Hankiewicz tt-ized text quotes in the HTML version of the
   docs.
<li>
   Eric Botcazou made the Linux port compile on non-x86 platforms.
<li>
   Stephan Brauss made a few fixes to let the Linux port compile again on
   Linux 2.2.x systems.
<li>
   Kalle Toivonen fixed a bug in _parallelogram_map().
<li>
   Eric Botcazou cleaned up the ALSA config variables under Unix.
<li>
   David Cullen added multiple bullets and extra lives to the demo game.
<li>
   Sam Hocevar fixed a race condition in the mixer under Unix w/ threads,
   Windows, BeOS and MacOS X.
<li>
   Andrei Ellman improved the Windows screensaver.
<li>
   Jon Rafkind implemented the Cohen-Sutherland clipping algorithm for the
   line() function.
<li>
   Angelo Mottola added an application menu with a Quit item acting like the
   three fingers salute, in order to better integrate Allegro apps with the
   Aqua UI guidelines under MacOS X.
<li>
   Jon Rafkind and Vincent Penquerc'h added more ASSERTs to the code.
<li>
   Eric Botcazou added an option to disable vsync when page-flipping.
<li>
   Eric Botcazou added the detection of spaces to the MSVCDir variable for
   the MSVC port.
<li>
   Grzegorz Adam Hankiewicz integrated the build instructions in the HTML
   version of the documentation.
<li>
   Angelo Mottola fixed some nits in fixbundle for alpha channel on 32-bit
   icons under MacOS X.
<li>
   Lisa Parratt improved the performances of the SGI audio driver.
<li>
   Grzegorz Adam Hankiewicz updated and improved the documentation in many
   places.
<li>
   Grzegorz Adam Hankiewicz added HTML text substitution to the doc processor.
<li>
   Tobi Vollebregt spotted a bug in ustrerror(), which was not returning a
   pointer to a static buffer.
<li>
   Grzegorz Adam Hankiewicz added more documentation about return values
   of functions.
<li>
   Grzegorz Adam Hankiewicz added a new section about documentation to
   ahack._tx.
<li>
   Grzegorz Adam Hankiewicz fixed rare buffer overflows in do_uconvert with
   very tiny buffer sizes.
<li>
   Serge Semashko fixed a bug with the letter P in the Russian keyboard
   configuration file.
<li>
   Angelo Mottola let application bundles accept files dragged onto the
   application icon under MacOS X.
<li>
   Peter Wang fixed save_bmp for better conformance (a couple of header
   fields were wrong, and dots-per-metre fields were being filled with zero).
<li>
   Julien Cugniere fixed a bug related to the retrieval of the inital volume
   when no primary buffer was present under Windows.
<li>
   Henrik Stokseth simplified the asm detection test, removed many GNUish
   preprocessor constructs in the asm files and, as a consequence, let the
   Watcom port use its own preprocessor on assembly files.
<li>
   Peter Wang prevented non-mmapped memory from being munmapped under Linux.
<li>
   Annie Testes prevented __al_linux_shutdown_vga_helpers from being called
   unless the corresponding init function was first called under Linux.
<li>
   Sven Sandberg improved the misc/findtext.sh script.
<li>
   Sven Sandberg added support to produce a PDF version of the manual under
   Unix and to compress the various formats with bzip2.
<li>
   Sven Sandberg made some correction to the Swedish translation file.
<li>
   Eric Botcazou pluginized the new 'Change filename' menu option in the
   grabber.
<li>
   Eric Botcazou fixed the X11 mouse scrolling bug.
<li>
   Vincent Penquerc'h made it so that modifications to the type or color
   depth of an image are detected as such by the grabber.
<li>
   Henrik Stokseth added a C++ test, Eric Botcazou integrated it in the build
   process.
<li>
   Angelo Mottola made several fixes to let Allegro play nice with AllegroGL
   under MacOS X.
<li>
   Angelo Mottola added proper embeddable framework support to the MacOS X
   port, modified fixbundle and updated the docs accordingly.
<li>
   Angelo Mottola made external plugins scripts work under MacOS X.
</ul>

]]></text></section><section title="Changes from 4.1.10 to 4.1.11 (Jun 2003)"><text><![CDATA[<ul><li>
   Eric Botcazou temporarily reverted the fix for the mouse bug when
   scrolling with the X11 driver under Unix.
<li>
   Eric Botcazou fixed the invocation of non-GNU make in the configure script,
   a few compilation warnings in tools/dat2c.c and made it possible to pass
   libraries to the misc/deplexe.sh script, so as to let Allegro build again
   under Solaris.
<li>
   Grzegorz Adam Hankiewicz removed all direct references to Canvaslink and
   credited SourceForge for current services.
<li>
   Eric Botcazou reworked the configure check for sched_yield() under Unix.
<li>
   Sam Hocevar fixed a Bashism in fix.sh that makes Solaris' sh choke.
<li>
   Angelo Mottola made sure mouse buttons are initialized to 0 at startup
   under MacOS X.
<li>
   Eric Botcazou added a blurb about the new behaviour of d_ctext_proc().
<li>
   Eric Botcazou corrected several inadequacies in the documentation of
   makefile targets.
<li>
   Grzegorz Adam Hankiewicz did some housekeeping work in the docs.
<li>
   Angelo Mottola added a missing item to the list of installed files
   under MacOS X.
<li>
   Angelo Mottola added a script to automate the enduser MacOS X package
   creation.
<li>
   Angelo Mottola made it possible to compile apps if just the Allegro
   framework is installed under MacOS X.
<li>
   Vincent Penquerc'h corrected an inefficiency in select_palette() and
   unselect_palette().
<li>
   Eric Botcazou fixed the build failure with MSVC.
<li>
   Andrei Ellman added a few missing items to the list of uninstalled files
   for the MinGW and MSVC ports.
<li>
   Vincent Penquerc'h fixed a bug in _fill_3d_edge_structure().
</ul>

]]></text></section><section title="Changes from 4.1.9 to 4.1.10 (Jun 2003)"><text><![CDATA[<ul><li>
   Many minor changes and clarifications in the docs.
<li>
   Hein Zelle reworked the paragraph on the location of shared libraries
   under Unix in the docs and added a FAQ entry on the same subject.
<li>
   Martijn Van Lersel fixed an overflow in create_light_table().
<li>
   Chris Jones and Eric Botcazou made the MIDI player handle the 'All Sound Off'
   controller message.
<li>
   Angelo Mottola made the MacOS X port play nice with 10.1.x.
<li>
   Eric Botcazou made the menus not block on exit when mouse buttons are
   still being held down.
<li>
   Grzegorz Adam Hankiewicz improved the description of set_gfx_mode about
   virtual screen sizes and hardware scrolling by suggestion of Lothar May.
<li>
   Chris Jones let the MIDI player pass controller events to the raw player
   by default.
<li>
   Angelo Mottola added the platform-dependent AL_RAND() macro.
<li>
   Angelo Mottola added a HID joystick driver to the MacOS X port.
<li>
   Henrik Stokseth spotted non-standard constructs in the Windows port.
<li>
   Henrik Stokseth spotted unused variables throughout the library.
<li>
   Jim Grainger spotted a broken link in the docs and updated it.
<li>
   Javier Gonzalez fixed some problems in the DirectSound streaming.
<li>
   Andrei Ellman improved the exrgbhsv example.
<li>
   Andrei Ellman corrected a rounding issue in hsv_to_rgb().
<li>
   Angelo Mottola added _al_rand() and replaced rand() with it throughout
   the library.
<li>
   Elias Pschernig moved the big font example from exgui to excustom and
   fixed d_edit_box string length.
<li>
   Angelo Mottola added the 'fixbundle' utility to the MacOS X port.
<li>
   Eric Botcazou added the possibility to fold/unfold nested datafiles in
   the grabber.
<li>
   Angelo Mottola fixed a couple of color conversion bugs.
<li>
   Elias Pschernig replaced exgui with a more thorough version.
<li>
   Vincent Penquerc'h added support for debugging with Fortify under Unix.
<li>
   Vincent Penquerc'h added the 'Replace' option to the grabber.
<li>
   Vincent Penquerc'h added the 'Force Update Selection' command to the
   grabber and refactored a fair amount of duplicated code.
<li>
   Eric Botcazou made exunicod endian-safe.
<li>
   Eric Botcazou fixed the behaviour of the C version of draw_trans_sprite()
   with 32-bit RGBA sprites.
<li>
   Angelo Mottola fixed the behaviour of the C version of draw_trans_sprite()
   in 8bpp mode.
<li>
   Angelo Mottola added system bitmaps support to the MacOS X port.
<li>
   Eric Botcazou enabled full support of relative filenames in the dat/grabber
   utilities.
<li>
   Angelo Mottola made exlights endian-safe.
<li>
   Christer Sandberg fixed a bug in the 24-bit graphics code of fixup_datafile().
<li>
   Angelo Mottola added hw-accelerated VRAM->VRAM blit support under MacOS X.
<li>
   Angelo Mottola added an install-template makefile target to install an
   Allegro application Project Builder template under MacOS X.
<li>
   Angelo Mottola added a digital sound driver to the MacOS X port.
<li>
   John Holden fixed a bug in load_wav().
<li>
   Angelo Mottola added a MIDI driver to the MacOS X port.
<li>
   Angelo Mottola added proper mouse buttons detection via HID Manager and
   buttons emulation if needed under MacOS X.
<li>
   Eric Botcazou added canonicalize_filename() and deprecated fix_filename_path().
<li>
   Evert Glebbeek added the support for relative filenames to the grabber.
<li>
   Eric Botcazou made it possible to pass CC on the command line to make
   on non-Unix systems.
<li>
   Angelo Mottola added support for bundled applications under MacOS X.
<li>
   Javier Gonzalez devised a simpler fix for the WinXP black screen bug.
<li>
   Javier Gonzalez prevented some artifacts from being left on the screen
   when moving fast the window under Windows.
<li>
   Angelo Mottola contributed the MacOS X port.
<li>
   Angelo Mottola fixed various things in preparation for the MacOS X port.
<li>
   Eric Botcazou uncoupled link options for libraries and programs.
<li>
   Evert Glebbeek added the support for relative filenames by means of three
   new API functions.
<li>
   Elias Pschernig made the allegro.devhelp work with devhelp 0.6.0.
<li>
   Eric Botcazou made file_select_ex() honor the '(+)d' attribute character
   in the extension string.
<li>
   Eric Botcazou removed the remaining occurences of ustrcpy() from the
   library code.
<li>
   Christer Sandberg fixed a problem with the include guard generated
   by dat2c.
<li>
   Eric Botcazou removed the remaining calls to deprecated functions from
   the distribution.
<li>
   Eric Botcazou optimized the handling of the extension string in the
   file selector.
<li>
   Eric Botcazou implemented the AL_*_DEPRECATED macros and enabled them
   for GCC 3.1 or later.
<li>
   Sven Sandberg improved the performance of the rgb_to_hsv() function.
<li>
   Christer Sandberg and Eric Botcazou made dat2c correctly detect the
   native line ending.
<li>
   Christer Sandberg and Eric Botcazou made dat2c work better with ISO C90
   compilers.
<li>
   Henrik Stokseth updated the installation and configuration instructions
   of both MinGW and Dev-C++ and documented the support of MSYS.
<li>
   Andrei Ellman improved the performance of the hsv_to_rgb() function.
<li>
   Peter Wang made the makefile not pass the -s switch to ld on Unix for
   non-optimized builds.
<li>
   Evert Glebbeek added the 'New' command to the grabber.
<li>
   Eric Botcazou made the grabber save previous modified data when loading
   new data.
<li>
   Eric Botcazou unified and fixed the support for ALLEGRO_USE_C on all
   GCC-based ports.
<li>
   Eric Botcazou unified the autodetection and handling of Unix-like tools
   on non-Unix systems.
<li>
   Andrei Ellman got Allegro for MSVC to build with Cygwin.
<li>
   Elias Pschernig made the programs be linked with -pg in profile mode
   under Unix.
<li>
   Andrei Ellman updated the Cygwin section in docs/build/mingw32.txt.
<li>
   Magnus Henoch fixed a problem when compiling without 8bpp support.
<li>
   James Ponder and Hein Zelle clarified a requirement when cross-compiling
   from Linux.
<li>
   James Ponder suggested to remove the DJGPP makefile from the Unix tar
   archive.
<li>
   Grzegorz Adam Hankiewicz improved the docs on allegro_exit().
<li>
   Grzegorz Adam Hankiewicz documented the bunch of packfile functions.
<li>
   Eric Botcazou fixed the profile build on BeOS.
<li>
   Eric Botcazou updated the FAQ about DJGPP's va_list problem (thanks
   to aj for spotting this).
<li>
   Andrei Ellman suggested some additions to the docs.
<li>
   Grzegorz Adam Hankiewicz added a chapter on available examples to the
   docs, the ability to cross-reference them and display the references
   with a specific layout in the HTML docs, and a Python script to automate
   the updating process when new examples are added.
<li>
   Eric Botcazou fixed an asm locking bug under Windows spotted by
   Omar Cornut.
<li>
   EvilTypeGuy cleaned up and fixed the RPM spec file for RedHat 9.
<li>
   Ville Skyttä fixed a problem with make install libdir= and modules on
   Unix systems.
<li>
   Peter Wang added a hack to not unload the SVGAlib module if SVGAlib
   installs an atexit() handler.
<li>
   Elias Pschernig updated xf2pcx and integrated it in the build process
   under Unix/X11.
<li>
   Grzegorz Adam Hankiewicz added support for dumping the configure settings
   under Unix.
<li>
   Javier Gonzalez added get_color_depth() to the API.
<li>
   Julien Cugniere and Eric Botcazou improved the support for non-blocking
   menus.
<li>
   Grzegorz Adam Hankiewicz corrected several nits in the documentation.
<li>
   Grzegorz Adam Hankiewicz documented the END_OF_MAIN macro.
<li>
   Javier Gonzalez added get_color_conversion() to the API.
<li>
   Lennart Steinke added the exconfig example.
<li>
   Eric Botcazou added big-endian support to the BMP, PCX and TGA loaders
   as well as to the X11 driver.
<li>
   Eric Botcazou fixed the 'uninstall' target and a problem with
   Mingw32's make for the Watcom port.
<li>
   Charles Bilyue suggested to not force yielding timeslice with non-blocking
   menus.
<li>
   Annie Testes fixed a bug with asynchronous I/O mode restoring under Linux.
<li>
   Annie Testes made the screen be cleared before setting the default
   palette when calling set_gfx_mode().
<li>
   Annie Testes fixed a bug with patterned drawing in the C version.
<li>
   Vincent Penquerc'h spotted an off-by-one problem when building the list
   of color depths in the gfx mode selector.
<li>
   Peter Wang made the Intellimouse PS/2 driver work for USB mice in Linux.
<li>
   Elias Pschernig integrated xkeymap in the build process under Unix/X11.
<li>
   Oscar Giner fixed a conflict between the magic main and the MFC.
<li>
   Matthew Leverton fixed a bug with pack_fgets().
<li>
   Eric Botcazou fixed broken and missing dependencies for make -j2 builds.
<li>
   Hein Zelle revamped the cross-compilation section of docs/build/mingw32.txt.
<li>
   Marcel Smit and Eric Botcazou made the show_video_bitmap() method of the
   Windows windowed driver wait for a vsync.
<li>
   Eric Botcazou made the test program really time the fixed math functions.
<li>
   Eric Botcazou clarified the limitations of Allegro's interrupts regarding
   the FPU state under DOS.
<li>
   Peter Wang fixed a bug in stretch_blit() where the first column or row can
   get an extra pixel, reported by David Gowers and AJ.
<li>
   Eric Botcazou made the linux mouse detection code really empty the buffer
   before proceeding in the setup program.
<li>
   Eric Botcazou made the Watcom port compile in warnmode with Open Watcom.
<li>
   Elias Pschernig fixed the build with the Unix->MinGW cross-compiler.
<li>
   Magnus Henoch made the gfx mode selector keep the current selection as
   much as possible.
<li>
   Eric Botcazou fixed the mouse not being scared over alert boxes.
<li>
   Eric Botcazou added -Wstrict-prototypes to the build warnmode under DOS,
   Windows and BeOS.
<li>
   Annie Testes updated the mouse autodetection code under Linux to take
   into account her EVDEV driver.
<li>
   Philipp Thomas added multi-arch support, DESTDIR support and the German
   translation to the RPM spec file.
<li>
   Philipp Thomas converted the configure machinery to autoconf 2.53 or later.
<li>
   Philipp Thomas fixed all function prototypes, thus allowing to build with
   -Wstrict-prototypes on Unix systems.
<li>
   Philipp Thomas fixed the compilation on x86-64.
<li>
   Philipp Thomas fixed all comparisons between signed and unsigned types,
   thus allowing to build with -W -Wno-unused on Unix systems.
<li>
   Eric Botcazou reworked the truecolor subsection of the 'Transparency and
   patterned drawing' section.
<li>
   Eric Botcazou clarified the return value on failure of file_time(),
   following AJ's suggestion.
<li>
   Eric Botcazou fixed the build in strictwarn mode on Unix systems.
<li>
   Eric Botcazou fixed a mouse bug when the screen is scrolled with the X11
   fullscreen driver.
<li>
   Eric Botcazou fixed a bug with resolution and color depth not being taken
   into account by gfx_mode_select_ex().
<li>
   Vincent Penquerc'h fixed the compilation breakage on Linux kernels 2.2.x.
<li>
   Eric Botcazou defined ALLEGRO_LIB_BUILD for debug and profile releases as
   well on Unix systems.
<li>
   Eric Botcazou forced the exstream example to abort if no real sound driver
   is found.
<li>
   Eric Botcazou clarified the limitations of the stretching functions.
<li>
   Acho A. Tang added a Sidewinder Precision Pro joystick driver to the
   DOS port.
<li>
   Eric Botcazou re-enabled the autodetection of joysticks in the setup
   program.
</ul>


]]></text></section><section title="Changes from 4.1.8 to 4.1.9 (Jan 2003)"><text><![CDATA[<ul><li>
   Many minor changes and clarifications in the docs.
<li>
   Annie Testes fixed some device name strings in the setup program.
<li>
   Annie Testes added a mouse driver based on the event interface (EVDEV)
   to the Linux port.
<li>
   Eric Botcazou added for_each_file_ex() and deprecated for_each_file().
<li>
   Eric Botcazou disabled hackish centering code in fullscreen mode
   under X11 which caused some artifacts to appear on KDE desktops.
<li>
   Elias Pschernig fixed a pasto in the sample reading code.
<li>
   Eric Botcazou fixed a bug with Alt+TAB under X11.
<li>
   Eric Botcazou added a configure check for the include prefix problem
   with gcc 3.1 or later on Unix systems.
<li>
   Eric Botcazou reverted the latest patch applied to the joystick code.
<li>
   Matt Witherspoon and Eric Botcazou fixed a bug in the scroll() method of
   the Linux SVGAlib driver so as to make it wait for the vertical retrace.
<li>
   Eric Botcazou added a stop/resume option to the exstream.c example.
<li>
   Ben Davis documented the non-standard behaviour of pack_feof().
<li>
   Eric Botcazou worked around a weird problem with some X11 window managers
   that prevented the fullscreen driver from setting up.
<li>
   Eric Botcazou disabled the new timer synchronization code.
<li>
   Grzegorz Adam Hankiewicz added a warning about DJGPP stability under some
   Windows versions.
<li>
   Eric Botcazou made it so that the window is centered at startup under
   Windows.
<li>
   Chris Jones and Eric Botcazou worked around a problem with DOS file
   attributes under Win2k.
<li>
   Eric Botcazou made the filetest work better with the keyboard.
<li>
   Eric Botcazou fixed shifted help sections in the grabber.
<li>
   Eric Botcazou fixed the mishandling of TAB characters in menu bar entries.
<li>
   Eric Botcazou added a new DEBUGMODE level so that debuggers will not be
   flooded by internal debug messages any more under Windows.
<li>
   Eric Botcazou fixed a weird compilation bug under MacOS X.
</ul>


]]></text></section><section title="Changes from 4.1.7 to 4.1.8 (Dec 2002)"><text><![CDATA[<ul><li>
   Eric Botcazou fixed a bug with nested datafiles in the dat/grabber code
   spotted by Thomas Klausner.
<li>
   Eric Botcazou clarified the wording about ABI/API compatibility.
<li>
   Thomas Klausner added NetBSD detection.
<li>
   Ben Davis constified the parameter of set_window_title.
<li>
   Lisa Parratt added IRIX detection.
<li>
   Robert J. Ohannessian clarified the docs for play_audio_stream.
<li>
   Sven Sandberg fixed the makedoc linking problem with Watcom spotted by
   Glenn Jarvis.
<li>
   Ben Davis fixed a compilation warning for set_window_close_button.
<li>
   Eric Botcazou fixed a buffer overflow in the Windows debug version
   spotted by aj.
</ul>


]]></text></section><section title="Changes from 4.1.6 to 4.1.7 (Dec 2002)"><text><![CDATA[<ul><li>
   Eric Botcazou made the joystick initialization routine correctly handle
   zero as the joytype.
<li>
   Eric Botcazou fixed the compile-time check for the MMX asm support.
<li>
   Eric Botcazou fixed the non-MMX asm color copy routine.
<li>
   Eric Botcazou implemented the synchronization routines for the BeOS port.
<li>
   Eric Botcazou turned the set_window_close_* macros into inline functions.
<li>
   Eric Botcazou fixed an oversight that caused the SGI AL audio driver not
   to be built as a module on Unix.
<li>
   Stepan Roh fixed a glitch with autoconf 2.53 on Unix.
<li>
   Eric Botcazou fixed the compilation bug with MinGW.
</ul>


]]></text></section><section title="Changes from 4.1.5 to 4.1.6 (Nov 2002)"><text><![CDATA[<ul><li>
   Grzegorz Adam Hankiewicz added informations on the FLI format provided
   by Kronoman X to the FAQ.
<li>
   Eric Botcazou revived the two former set_window_close_* functions as
   deprecated functions.
<li>
   Elias Pschernig contributed an improved xkeymap utility, based on the
   original code by Michael Bukin.
<li>
   Eric Botcazou added synchronization to the timer code on multi-threaded
   platforms (except BeOS for the time being).
<li>
   Eric Botcazou made the new 'save' method of plugins use the same return
   value convention as the 'export' method (see tools/plugins/plugins.txt).
<li>
   Eric Botcazou added the support for plugin scripts to the MinGW port.
<li>
   Peter Wang changed the default sound mixing quality to 2 (highest).
<li>
   Matthew Leverton added the detection of left-hand mouse configuration
   under Windows.
<li>
   Oscar Giner fixed a bug with binary data exporting in the grabber,
   introduced in the 4.1.4 release.
<li>
   Eric Botcazou fixed a crash when Alt+Tabbing under WinXP.
<li>
   Eric Botcazou reverted his patch changing the behaviour at startup
   under Windows.
<li>
   Grzegorz Adam Hankiewicz added infrastructure for properly documenting
   the return value of the API calls.
</ul>


]]></text></section><section title="Changes from 4.1.4 to 4.1.5 (Nov 2002)"><text><![CDATA[<ul><li>
   Grzegorz Adam Hankiewicz updated the docs about mailing lists/contacts.
<li>
   Grzegorz Adam Hankiewicz added instructions on how to create and submit
   patches to the Allegro developers.
<li>
   Eric Botcazou implemented the support for non-blocking menus.
<li>
   Lisa Parratt spotted a BSDism that IRIX doesn't like at all.
<li>
   Daniel Schlyder fixed a problem with set_window_title() under BeOS.
<li>
   Lisa Parratt contributed the SGI Audio Library sound driver.
<li>
   Eric Botcazou completely revamped the close button support.
<li>
   Eric Botcazou simplified fullscreen mode initialization under Windows.
<li>
   Elias Pschernig and Eric Botcazou made the GUI code scare the mouse, when
   drawing, only if it is necessary to do so, thus reducing cursor flicker.
<li>
   Eric Botcazou fixed a bug in scare_mouse_area().
<li>
   Elias Pschernig optimized the load_bitmap() function family when no
   palette is specified and documented the feature.
<li>
   Grzegorz Adam Hankiewicz aliased the stylesheet to the default CSS style,
   allowing The Big Lizard(tm) and other web browsers to disable CSS.
<li>
   Eric Botcazou fixed an ill-behaviour at startup under Windows.
<li>
   Elias Pschernig added the Euro character to the default font and to the
   German and French keyboard configuration files.
<li>
   Eric Botcazou made _ustrdup() set *allegro_errno to ENOMEM on failures.
<li>
   Annie Testes lifted several hardcoded length limitations in the
   configuration routines.
<li>
   Eric Botcazou prevented set_gfx_mode() from resetting the layout of all
   color depths.
<li>
   Eric Botcazou moved #include directives out of the range of extern "C"
   directives (fixing the C++ compilation bug with Borland C++).
<li>
   Vincent Penquerc'h added the ALLEGRO_NO_COMPATIBILITY symbol and moved
   all the deprecated stuff from allegro._tx to api._tx .
<li>
   Grzegorz Adam Hankiewicz reformatted monospaced text blocks to fit page
   in Postscript output.
<li>
   Oscar Giner added the Catalan translation.
<li>
   Oscar Giner corrected the Spanish translation.
<li>
   Grzegorz Adam Hankiewicz added a new command to the doc processor for
   email mangling: me@serv.com -> me at serv dot com. It is applied to all
   documentation output formats.
<li>
   Grzegorz Adam Hankiewicz made all source files use the external CSS.
<li>
   Chris Jones fixed a bug with 16-bit samples loading introduced in the
   previous release.
</ul>


]]></text></section><section title="Changes from 4.1.3 to 4.1.4 (Oct 2002)"><text><![CDATA[<ul><li>
   Eric Botcazou prevented the linker from choking on Solaris because of a
   static library with no symbols.
<li>
   Eric Botcazou removed joystick control from main part of the setup program.
<li>
   Eric Botcazou documented the workaround needed for C++ programs compiled
   with Borland C++ (in docs/build/bcc32.txt).
<li>
   Eric Botcazou unified the magic main for the 3 Windows compilers and fixed
   the WinMain() linkage for Borland C++.
<li>
   Henrik Schmidt made gcc pass '-h' instead of '-soname' to the linker and
   replaced '-L' by '-h' in shell comparisons so as not to break on Solaris.
<li>
   Eric Botcazou fixed the bogus check for GNU ar on Unix systems.
<li>
   Elias Pschernig made load_datafile_object() load the properties attached
   to the object.
<li>
   Javier Gonzalez and Eric Botcazou fixed the infamous blank screen problem
   under Win2k/WinXP.
<li>
   Eric Botcazou cleaned up the use of errno/allegro_errno throughout the
   library and removed all occurences of errno in the grabber/plugins code.
<li>
   Grzegorz Adam Hankiewicz embedded readme.txt into the Allegro manual.
<li>
   Eric Botcazou made the Windows port set the NULL mouse cursor in
   fullscreen mode instead of hiding it.
<li>
   Vincent Penquerc'h ASSERTed a bunch of C drawing routines.
<li>
   Robert J. Ohannessian did some cosmetic improvements to the HTML output
   and separated the CSS file.
<li>
   Evert Glebbeek added configure options for x86 processor optimizations
   on Unix systems.
<li>
   Benny Colyn added a Dutch translation.
<li>
   Evert Glebbeek added the detection of SunOS/Solaris.
<li>
   Javier Gonzalez fixed a graphics bug with always-on-top applications.
<li>
   Igor Gnip added the detection of MSYS via the SHELL variable to the
   MingW32 port.
<li>
   Eric Botcazou made the mouse use the exclusive foreground cooperative
   level in fullscreen mode under Windows.
<li>
   Eric Botcazou fixed a bug than had prevented ALT+F4 from being properly
   handled under Windows and cleaned up the low-level scancode handler.
<li>
   Eric Botcazou updated the description of the layout of header files in
   the aHack file.
<li>
   Grzegorz Adam Hankiewicz corrected the docs about 'ulimit' in the Help
   file.
<li>
   Laurence Withers converted the core library and the whole distribution
   to use the new text API.
<li>
   Laurence Withers added a new text API and deprecated the old one.
<li>
   Eric Botcazou made the Windows port stop triggering SWITCH_IN events
   when restoring the DirectDraw surfaces.
<li>
   Eric Botcazou re-enabled screensavers and powerdowns under Windows.
<li>
   Eric Botcazou made the deprecated file_select() an inline function.
<li>
   Eric Botcazou cleaned up set_gfx_mode() and made it so that GFX_SAFE
   selects a windowed mode in windowed environments.
<li>
   Vincent Penquerc'h added a container header file graphics.h for all the
   graphics stuff.
<li>
   Vincent Penquerc'h added an indexing option to the grabber.
<li>
   Evert Glebbeek added an option menu to the grabber.
<li>
   Evert Glebbeek and Eric Botcazou cleaned up the grabber/plugins code;
   in particular, the 'save' method of plugins got a new prototype.
<li>
   Peter Wang made fix.sh and zipup.sh not destroy timestamps when just
   changing EOL markers.
<li>
   Peter Wang fixed a misuse of the -I option with gcc 3.0 and later.
<li>
   Robert J. Ohannessian added more caveats to docs/build/mingw32.txt.
</ul>


]]></text></section><section title="Changes from 4.1.2 to 4.1.3 (Sep 2002)"><text><![CDATA[<ul><li>
   Grzegorz Adam Hankiewicz fixed a bug in the HTML rendering code.
<li>
   Eric Botcazou modified the querying of DirectSound devices under Windows.
<li>
   Evert Glebbeek added a '-fullscreen' switch to the grabber, Laurence
   Withers a '-windowed' switch.
<li>
   Eric Botcazou temporarily disabled screensavers and power downs under
   Windows.
<li>
   Daniel Schlydler fixed problems with get_executable_name() under Windows.
<li>
   Eric Botcazou added a FAQ entry on the C++ headers problem with gcc 3.x
   and Mingw32, summarizing findings by Robert J. Ohannessian.
<li>
   Robert J. Ohannessian fixed the compilation problem with MSVC.
</ul>


]]></text></section><section title="Changes from 4.1.1 to 4.1.2 (Sep 2002)"><text><![CDATA[<ul><li>
   Many minor changes in the code and the docs.
<li>
   Grzegorz Adam Hankiewicz fixed a crash in the exmouse example when no
   mouse is present.
<li>
   Angelo Mottola made the exunicod example welcome Italian programmers too.
<li>
   Grzegorz Adam Hankiewicz documented new structures.
<li>
   Eric Botcazou added a native DirectX window test.
<li>
   Eric Botcazou re-enabled the 1 ms accuracy limitation for timers under
   Windows.
<li>
   Elias Pschernig added support for the Devhelp documentation format.
<li>
   Marcel Smit corrected an error in the packfile format write-up.
<li>
   Eric Botcazou fixed a conflict between Allegro headers and standard C++
   headers of gcc 3.x under Mingw32.
<li>
   Matthew Leverton made the DOS/Windows makefiles use 'copy /B' instead
   of 'copy' for file concatenation.
<li>
   Eric Botcazou wrote another new page flipping/triple buffering code for
   the Windows port.
<li>
   Eric Botcazou made it so that win_set_window() restores the state of the
   joystick module as well.
<li>
   Grzegorz Adam Hankiewicz ASSERTed a bunch of public functions.
<li>
   Eric Botcazou made it so that restoring the DirectDraw surfaces always
   triggers a SWITCH_IN event under Windows.
<li>
   Peter Wang fixed a problem linking with the debug version under linux,
   due to missing "inline" functions.
<li>
   Robert J. Ohannessian fixed the docs for pivot_scaled_sprite_v_flip().
<li>
   Eric Botcazou fixed a race condition when registering input events at
   startup under Windows.
<li>
   Roberto Alfonso added an srand() call in the demo game.
<li>
   Elias Pschernig removed (seemingly) arbitrary window size checks in the
   Unix X11 driver.
<li>
   Roberto Alfonso fixed a couple of memory problems in the dat2c utility.
<li>
   Matthew Leverton pointed out a C99 idiom in the dat2c utility that
   Borland C++ doesn't like.
<li>
   Angelo Mottola changed the BeOS gfx driver IDs/constants to more
   pertinent ones.
<li>
   Angelo Mottola added a safe BWindow-based windowed driver and a
   fullscreen overlay driver to the BeOS port.
<li>
   Angelo Mottola reorganized and commented all the BeOS gfx subsystem.
<li>
   Sven Sandberg fixed a bug in create_trans_table().
<li>
   Javier Gonzaled fixed a bug with volume and pan not properly set in
   loop mode by the DirectSound driver.
<li>
   Laurence Withers added two fixed point ratios for converting to and
   from radians.
<li>
   Eric Botcazou fixed the documented prototype of fixtof() and ftofix().
<li>
   Laurence Withers fixed the 'inline' compilation bug in the dat2c utility.
<li>
   Eric Botcazou fixed a bug that causes timers to restart permanently when
   Allegro is switched out under Windows.
<li>
   Eric Botcazou fixed a bug with switch mode setting under Windows he had
   introduced in the 4.1.1 release.
<li>
   Grzegorz Adam Hankiewicz improved the legibility of the HTML code
   generated by the doc processor and reduced its size in the process.
</ul>


]]></text></section><section title="Changes from 4.1.0 to 4.1.1 (Aug 2002)"><text><![CDATA[<ul><li>
   Many minor changes and clarifications in the docs and the FAQ.
<li>
   Eric Botcazou fixed a bug with graphics mode switching using a
   ALT+key combination under Windows.
<li>
   Laurence Withers contributed the dat2c utility.
<li>
   Grzegorz Adam Hankiewicz made it so that chapters can be referenced
   in the documentation and added a new one on the types and
   structures defined by the library.
<li>
   Eric Botcazou improved win_set_window() so that it can be called
   after the library has been initialized.
<li>
   Elias Pschernig fixed a bug in midi_seek().
<li>
   Eric Botcazou wrote a new page flipping/triple buffering code for the
   Windows port.
<li>
   Grzegorz Adam Hankiewicz added a linux specific debug help section.
<li>
   Eric Botcazou made the constructors of the fix class from integer and
   floating point values explicit.
<li>
   Eric Botcazou fixed a dat2s bug with dynamically linked programs
   under Windows.
<li>
   Jan Bruun Andersen fixed a compilation problem with Cygwin.
<li>
   Jeremiah Blanchard updated the build instructions for Darwin.
<li>
   Vincent Penquerc'h added sample loader/saver registration and a
   save_sample() function. Peter Wang documented it.
<li>
   George Foot added (preliminary) non-FM support to the OSS MIDI driver.
<li>
   Ben Davis and Robert J. Ohannessian put in (void *) casts for the
   LOCK_* macros on DJGPP and Mac.
<li>
   Nicholas Davies made the fix class not trigger warnings with gcc -Weffc++.
<li>
   Angelo Mottola fixed a keyboard focus problem under BeOS.
<li>
   Peter Wang fixed the detection of ESD and aRts on Unix systems.
<li>
   Peter Wang made files be opened with as permissive as possible
   permissions on Unix systems.
<li>
   Stepan Roh added support for a automake-style DESTDIR variable in the
   Unix makefile.
<li>
   Grzegorz Adam Hankiewicz made the doc processor output valid HMTL 4.0 in
   some corner cases for which it previously didn't.
<li>
   Grzegorz Adam Hankiewicz fixed a crash of the doc processor with very
   long lines.
<li>
   Peter Wang did some housekeeping work throughout the code and the
   documentation.
</ul>


]]></text></section><section title="Changes from 4.0.2 to 4.1.0 (Jul 2002)"><text><![CDATA[<ul><li>
   Charles Bilyue optimized the i386 blitters.
<li>
   Peter Wang fixed the mis-treatment of empty files by the library and
   the 'pack' utility.
<li>
   Eric Botcazou simplified pack_f{read,write} and cleaned up several
   uses of pack_feof().
<li>
   Eric Botcazou split USE_CONSOLE into ALLEGRO_USE_CONSOLE and
   ALLEGRO_NO_MAGIC_MAIN.
<li>
   Eric Botcazou simplified and cleaned up the asm bank switchers.
<li>
   Peter Wang added support for the environment variable ALLEGRO_MODULES
   under Unix.
<li>
   Peter Wang made 'configure --disable-vga' remove more stuff out of the
   core under Unix.
<li>
   Eric Botcazou made the DirectDraw code try to restore its surfaces as
   soon as it detects they have been lost.
<li>
   Peter Wang added a description of the packfile format.
<li>
   Peter Wang added an aRts sound driver to the Unix port.
<li>
   Sven Sandberg optimized create_video_bitmap() for systems with a single
   video memory surface.
<li>
   Grzegorz Adam Hankiewicz reindented the documentation sources, improving
   the text/info/html output in the process.
<li>
   Grzegorz Adam Hankiewicz improved chm output for the documentation.
<li>
   Sven Sandberg optimized and reduced numeric errors in create_trans_table().
<li>
   Lorenzo Petrone added a xwin_set_window_name() function to the X11 port.
<li>
   Peter Wang made install_allegro()/allegro_init() not abort the program
   on failure.
<li>
   Sven Sandberg and Grzegorz Adam Hankiewicz added backward compatibility
   to the new doc processor.
<li>
   Sven Sandberg fixed various problem in the makefiles.
<li>
   Elias Pschernig made it so that the COLORCONV_KEEP_TRANS flag is checked
   when converting bitmaps out of datafiles.
<li>
   Eric Botcazou added preliminary support for hardware acceleration and
   video bitmaps to the QNX port.
<li>
   Elias Pschernig added a window position saving feature to the Windows port.
<li>
   Vincent Penquerc'h added a -s-PROP option to the dat utility in order
   to preserve properties when stripping.
<li>
   Henrik Stokseth made the zipwin.sh script for packaging the Windows
   binary distribution work with Cygwin.
<li>
   Peter Wang and Eric Botcazou made it so that Allegro C programs can
   compile with gcc -ansi -pedantic.
<li>
   Vincent Penquerc'h added a 'sort' option to the grabber and the dat
   utility.
<li>
   Eric Botcazou added preliminary support for native windows under Windows.
<li>
   Vincent Penquerc'h made gcc use pipes on Unix when building the library.
<li>
   Lorenzo Petrone added support for switch callbacks under X11 and
   refactored the display switching code.
<li>
   Javier Gonzalez changed the default value of emulate_three to no in all
   cases.
<li>
   Eric Botcazou modified the behaviour of the retrace_* objects to take
   into account the refresh rate if known.
<li>
   Eric Botcazou fixed the 'configure --disable-constructor' problem.
<li>
   Elias Pschernig fixed menu dimensions in the GUI engine.
<li>
   Eric Botcazou added documentation on API compatibility.
<li>
   Elias Pschernig and Eric Botcazou fixed the get_camera_matrix*() functions.
<li>
   Igor Gnip removed the requirements for fileutils on DOS/Windows platforms.
<li>
   Jeremiah Blanchard contributed modifications in order for Allegro to
   compile on Darwin/MacOS X.
<li>
   Henrik Stokseth merged standard and extended mode-selectors.
<li>
   Elias Pschernig added chm ouput support for the documentation.
<li>
   Eric Botcazou merged the three input threads into a single one under Windows.
<li>
   Mike Pichagin contributed the ustrnicmp() function.
<li>
   Grzegorz Adam Hankiewicz contributed a new documentation format for better
   html output.
<li>
   Eric Botcazou added a DirectInput joystick driver to the Windows port.
</ul>


]]></text></section><section title="Changes from 4.0.1 to 4.0.2 (Jun 2002)"><text><![CDATA[<ul><li>
   Many clarifications in the docs.
<li>
   Sven Sandberg improved accuracy and fixed bugs in do_arc().
<li>
   Matthew Leverton added missing header files to be installed by the
   Windows binary distribution.
<li>
   Grzegorz Adam Hankiewicz fixed a problem with the TOC of the FAQ.
<li>
   Eric Botcazou fixed a bug with stretch_blit() under Windows XP.
<li>
   Peter Wang fixed various configure machinery problems under Unix.
<li>
   Sven Sandberg updated the Swedish translation file.
<li>
   Sven Sandberg fixed a crash in the exswitch example when compiled
   by Watcom C/C++ and also made if faster.
<li>
   Maxime Carey added a Canada (French) keyboard mapping file.
<li>
   Henrik Stokseth updated instructions and fixed installation for Cygwin.
<li>
   Eric Botcazou added an option to disable direct updating in color
   conversion mode under Windows.
<li>
   Eric Botcazou (presumably) fixed the bug in the emergency exit mechanism
   under Windows when called from the DLL.
<li>
   Angelo Mottola made it so that the sound doesn't block the main thread
   anymore under BeOS.
<li>
   Deepak T and Eric Botcazou fixed clipping in three C sprite drawing
   routines.
<li>
   Peter Wang fixed a deadlock that occurred under Unix when Allegro
   received an X11 close event.
<li>
   Eric Botcazou added a --cppflags option to allegro-config and fixed
   C++ compilation under QNX.
<li>
   Vincent Penquerc'h added a --version= option to allegro-config.
<li>
   Robert J. Ohannessian made the 32->24 color convertors more robust and
   improved the MMX one in the process.
<li>
   Robert J. Ohannessian, Eric Botcazou and Sven Sandberg fixed a bug in
   the hue blender and the hsv_to_rgb() routine.
<li>
   Matthew Leverton fixed another problem with al_find*() and NTFS
   partitions under Windows.
<li>
   Peter Wang fixed a bug in ALSA device detection.
<li>
   Peter Wang fixed a bug in al_find* under Unix when running as root.
<li>
   Matthew Leverton and Eric Botcazou fixed a bug with mouse mickeys in
   windowed mode under Windows.
</ul>


]]></text></section><section title="Changes from 4.0.0 to 4.0.1 (Mar 2002)"><text><![CDATA[<ul><li>
   Many minor changes, many clarifications in the docs.
<li>
   Peter Wang fixed the installation of shared libs under FreeBSD.
<li>
   Peter Wang and Eric Botcazou fixed autodetection glitches for VGA and
   SVGAlib.
<li>
   Eric Botcazou fixed a problem under X11 when the MIT X-SHM extension is
   used.
<li>
   Eric Botcazou fixed a deadlock on exit when an user window is used in
   conjunction with timers under Windows.
<li>
   Eric Botcazou disabled useless backbuffers for the DirectX safe driver.
<li>
   Peter Wang made the Alsa sound driver use non-blocking mode when
   detecting if ALSA PCM available.
<li>
   Sven Sandberg added support for long long integers to usprintf() and al.
<li>
   Robert J. Ohannessian fixed the difference blender.
<li>
   Peter Wang fixed a race condition when closing the X display.
<li>
   Elias Pschernig made all active dialogs redraw themselves after a switch.
<li>
   Peter Wang made fbcon a priority driver, so that it can appear above VGA.
<li>
   Javier Gonzalez fixed a glitch in the DirectSound input code.
<li>
   Eric Botcazou fixed the SIGSEGV on exit with the three-finger salute
   under QNX.
<li>
   Eric Botcazou fixed the C-to-asm calling problem for Borland C++ compiled
   programs.
<li>
   Eric Botcazou cleaned up the messy (and somewhat incorrect) DirectDraw
   bitmap management code.
<li>
   Sven Sandberg improved the video bitmap subdivision algorithm.
<li>
   Sven Sandberg fixed problems in the Windows makefiles (especially
   Borland) when building Allegro under Win98.
<li>
   Peter Wang removed the hack which switched off fix aliases under IRIX.
<li>
   Vincent Penquerc'h fixed a problem with the SIGALRM timer and
   SWITCH_PAUSE.
<li>
   Javier Gonzalez fixed a latency problem with audiostreams.
<li>
   Laurence Withers made the font exporter use the current palette for the
   output.
<li>
   Elias Pschernig made some changes to grabber: added a close hook; keeps
   track if anything has been modified; when you exit the grabber and the
   file was modified, the popup now has a 3rd option for save+exit; window
   title displays the current filename, and if the file has been modified;
   fixed multicolour font exports.
<li>
   Sven Sandberg optimized again the create_light_table() function.
<li>
   Attila Szilagyi fixed SVGAlib horizontal scrolling.
<li>
   Eric Botcazou fixed synchronization problems under QNX.
<li>
   Grzegorz Adam Hankiewicz made the TOC at the top of sections
   alphabetically sorted.
<li>
   Eric Botcazou fixed the screen not restored after a wake-up in the
   Windows windowed and overlay drivers.
<li>
   Richard Reeve fixed a silly mistake with gcc 3.0.x detection.
<li>
   Angelo Mottola fixed static keyconf compilation problem on BeOS due to
   pckeys keyboard driver.
<li>
   Eric Botcazou fixed the not-returning-focus-on-exit bug under Windows.
<li>
   Michael Bukin fixed a bug with C-version textprintf on 24-bpp bitmaps,
   reported by Bertrand Coconnier.
<li>
   Eric Botcazou fixed a bug in the 32->15 MMX color conversion routine.
<li>
   Eric Botcazou fixed the DLL linking problem with Borland C++ Builder 4.
<li>
   Sven Sandberg made exaccel more responsive.
<li>
   Sven Sandberg fixed a glitch with short filenames under DOS.
</ul>


]]></text></section><section title="Changes from 3.9.40 to 4.0.0 (Dec 2001)"><text><![CDATA[<ul><li>
   Many minor changes.
<li>
   Eric Botcazou modularised the VGA/Mode-X drivers under Linux.
<li>
   Peter Wang fixed the segfault bug in Mode-X under Linux with threads.
<li>
   Peter Wang made the X11 port use SIGTERM signal instead of exit() when
   invoking the three finger salute. This solves a problem where programs
   with sound hang when they are killed.
<li>
   Eric Botcazou added os_version and os_revision support to the QNX port and
   added a QNX specific section to the docs.
<li>
   Peter Wang added a deadzone for digital readings of joystick axes under
   Linux, as suggested by George Foot and made the driver look for
   /dev/input/js# before /dev/js#.
<li>
   Peter Wang renamed fixed point functions to be prefixed with "fix" instead
   of "f", to avoid clashes with some libcs. Backwards compatibility is
   provided using static inline functions.
<li>
   Peter Wang fixed two problems with emergency exits under Linux/Unix.
<li>
   Eric Botcazou changed the updating logic of the QNX Photon graphics
   driver.
<li>
   Eric Botcazou added a doc for the wfixicon utility, with the help of
   Laurence Withers.
<li>
   Angelo Mottola unicodified allegro_message on BeOS and wrote a new BeOS
   keyboard driver (using the shared pckeys system).
<li>
   Eric Botcazou fixed a problem with David Capello's d_menu_proc
   steal/return mouse focus patch.
<li>
   Peter Wang made passing NULL to install_allegro() as the atexit_ptr
   parameter mean allegro_exit() won't be installed as an atexit()
   callback, as suggested by Javier Gonzalez.
<li>
   Lorenzo Petrone added a gfxinfo utility.
<li>
   Eric Botcazou added fetch_mode_list() to the QNX Photon Direct driver.
<li>
   Peter Wang made X desktop_color_depth() able to return 15 bpp.
<li>
   Grzegorz Adam Hankiewicz updated Spanish translation strings.
<li>
   Peter Wang fixed a problem with X shutdown sequence.
<li>
   Eric Botcazou repaired the QNX build process, revamped the layout of the
   QNX port sources and made some fixes.
<li>
   Peter Wang disabled the SVGAlib mode fetching code as it was causing
   problems with other drivers.
<li>
   Angelo Mottola added BeOS notes to the ABI compatibility doc.
<li>
   Eric Botcazou fixed a bug in the Windows locking code that caused the
   grabber to crash on switch out.
<li>
   Eric Botcazou fixed a bug in the handling of recursive sub-bitmaps under
   Windows.
<li>
   Eric Botcazou fixed a bug preventing old style password-protected
   packfiles from loading in the grabber.
<li>
   Lorenzo Petrone added two FAQ entries on DGA2 problems.
<li>
   Grzegorz Adam Hankiewicz revamped the structure of the docs directory.
<li>
   Stepan Roh updated the Czech translation.
<li>
   Javier Gonzalez fixed a bug in the DirectSound driver related to the loop
   playing modes.
<li>
   David Capello fixed a problem with submenus which overlapped their
   parents, where focus would pop back to the parent instead of the child.
</ul>


]]></text></section><section title="Changes from 3.11 to 3.9.40 (Nov 2001)"><text><![CDATA[<ul><li>
   3.9.40: Eric Botcazou enabled SSE support under Linux. Also reduced the
   delay in the DOS Sidewinder init code. Made the definition of _AL_DLL
   for MinGW32 consistent with other Windows ports.
<li>
   3.9.40: Henrik Stokseth improved make install to install only the needed
   headers from the include/allegro/platform directory.
<li>
   3.9.40: Vincent Penquerc'h updated 7 makefiles after his header splitting
   patch.
<li>
   3.9.40: Robert J. Ohannessian added two new entries to the GFX_VTABLE
   structure.
<li>
   3.9.40: Eric Botcazou replaced sprintf() by snprintf() in the Linux/Unix
   code. Increased the delay in the Windows switch handling code.
   Unicodified the GFX mode selector and fixed some glitches. Added a new
   test dubbed filetest. Fixed more unicode string problems. Unified the
   handling of system directory variables in the Windows makefiles. Made
   two strings translatable in the GFX mode selector.
<li>
   3.9.40: Ben Davis added support for timers with parameters under Windows.
<li>
   3.9.40: Eric Botcazou fixed the bug in the asm sprite functions when
   used with sub-bitmaps. Fixed a problem of the new header layout for
   platforms not supporting asm.
<li>
   3.9.40: George Foot and Eric Botcazou fixed the C fceil() function and
   added the ffloor() function.
<li>
   3.9.40: Chris Graham suggested to add a new flag for Windows NTFS
   compressed files.
<li>
   3.9.40: Henrik Schmidt and Eric Botcazou found a workaround for the
   switching problem under Windows.
<li>
   3.9.40: Eric Botcazou revamped the Borland C++ build process. Now it
   targets BC++ 5.5. Made pack_fdopen() an exported internal function.
   Reverted to the 3.9.38 code for 16-bit audio streaming with DirectSound.
<li>
   3.9.40: Vincent Penquerc'h contributed a rather large split-up/
   reorganization of the Allegro header files. Henrik and Eric did some
   related clean-up and fixing.
<li>
   3.9.40: Peter Wang updated put_backslash() docs.
<li>
   3.9.40: Eric Botcazou modified the way DirectDraw surfaces are
   enumerated. Fixed compilation errors/warnings with BC++. Made
   generate_optimized_palette_ex() a static function. Worked around the
   DOS limitations for al_findfirst() and for_each_file(). Moved
   platform-dependent stuff out of src/fsel.c.
<li>
   3.9.40: Peter Wang updated timer docs for non-DOS. Added ABI
   compatibility readme.
<li>
   3.9.40: Javier Gonzalez removed all references to the RSXNT build.
<li>
   3.9.40: Vincent Penquerc'h made it so that users can provide their own
   ustrdup().
<li>
   3.9.40: Robin Burrows fixed two glitches in the DirectDraw code.
<li>
   3.9.40: Peter Wang fixed a problem where XUnlockDisplay was called after
   XCloseDisplay.
<li>
   3.9.40: Eric Botcazou removed old Sidewinder asm driver. Cleaned up
   buffer usage in DIGMID. Fixed unicode support in the DIGMID driver.
   Replaced all occurrences of SEND_MESSAGE() by object_message().
<li>
   3.9.40: Annie Testes caught a misordering in the X system shutdown.
<li>
   3.9.40: Eric Botcazou increased the size of filename buffers to 1024
   bytes.
<li>
   3.9.40: Sven Sandberg improved fix.bat script.
<li>
   3.9.40: David Capello fixed a problem with lost GUI mouse clicks.
<li>
   3.9.40: Vincent Penquerc'h removed two hard-coded list sizes in grabber.
<li>
   3.9.40: Peter Wang added a little clarification regarding
   mouse_accel_factor.
<li>
   3.9.40: Eric Botcazou made debugging functions revert to ASCII strings.
   Added some defines for backwards compatibility with former cpu_* flags.
   Fixed a compilation problem under DJGPP.
<li>
   3.9.40: Henrik Stokseth added VBE/AF fetch_mode_list().
<li>
   3.9.40: Robert J. Ohannessian revamped the retrieval mechanism of CPU
   capabilities and added some new flags.
<li>
   3.9.40: Eric Botcazou fixed various mouse cursor problems under Windows.
   Updated docs about the DIGI_DIRECTX drivers.
<li>
   3.9.40: Javier Gonzalez fixed audio streams in Windows.
<li>
   3.9.40: Peter Wang improved the XDGA2 driver by removing unneccessary
   scrolling, which also resulted in speed-ups due to less
   locking/unlocking. The original fix was by Michael Bukin.
<li>
   3.9.40: Eric Botcazou and Javier Gonzalez added some documentation on
   static linking with MSVC/MinGW32.
<li>
   3.9.40: Peter Wang fixed sonames for debug and profile libs. Also added
   a 'configure' check that ld supports -export-modules before enabling
   modules.
<li>
   3.9.40: Annie Testes found ASCII strings that needed to be converted.
   Also added a pack_fdopen() function.
<li>
   3.9.40: Robert J. Ohannessian clarified some Dev-C++ instructions.
   Fixed fix.bat script under MinGW32/Win2k.
<li>
   3.9.40: Marcel Smit corrected a bug that caused errors when drawing
   perspective-correct polygons facing the screen. (dz=0)
<li>
   3.9.40: Peter Wang made install_timer_int static. Also moved
   allegro_404_char into public API.
<li>
   3.9.40: Laurence Withers added docs for allegro_404_char.
<li>
   3.9.40: Eric Botcazou fixed a little glitch with menu auto-opening. Also
   fixed a color glitch in the Windows windowed driver on 8-bit desktops.
<li>
   3.9.40: Salvador Eduardos Tropea fixed inline friend declarations with
   bodies. (gcc 3.0.x problem)
<li>
   3.9.40: Peter Wang improved behaviour between mouse auto-opening menus
   and navigating with keyboard. Also unspartanised the ustrtok_r() docs.
<li>
   3.9.40: Henrik Stokseth replaced the mmxtest with a more advanced
   assembler capabilities testing.
<li>
   3.9.40: Eric Botcazou re-enabled full pairing on Pentium for five color
   conversion routines. Applied xor vs. mov instruction-length optimization
   to the  non-MMX code. Applied %ecx vs. %edx instruction-length
   optimization to the non-MMX code. Updated the mouse_accel_factor docs.
<li>
   3.9.40: Peter Wang eliminated use of static buffers by uconvert() in
   several places.
<li>
   3.9.40: David A. Capello made d_menu_proc steal/return focus when
   activated/deactivated.
<li>
   3.9.40: Henrik Stokseth added Out of Environment space detection on the
   fix.bat script.
<li>
   3.9.40: Eric Botcazou fixed a non ANSI C compliant behaviour in
   usprintf().
<li>
   3.9.40: Seunghwan Ji made makedoc output correct html and rtf files for
   Korean.
<li>
   3.9.39: Robert J. Ohannessian added -? and --help options to dat.
<li>
   3.9.39: Sven Sandberg and Grzegorz Adam Hankiewicz fixed some errors in
   the documentation.
<li>
   3.9.39: Annie Testes fixed several glitches related to unicode support.
<li>
   3.9.39: Henrik Stokseth added an internal _al_sane_realloc() function
   with guaranteed behaviour. Used this to fix a memory leak and updated
   the FAQ.
<li>
   3.9.39: Eric Botcazou and Peter Wang updated the documentation on:
   file attribute flags, request_scroll and request_video_bitmap.
<li>
   3.9.39: Eric Botcazou unified the use of internal timers in Windows
   drivers. Also let digitest use max volume of Allegro mixer.
<li>
   3.9.39: Paul Hampson improved again the DOS SNESpad joystick driver.
<li>
   3.9.39: Eric Botcazou revamped the locking mechanism of the DGA2 driver.
   Also fixed some memory leaks.
<li>
   3.9.39: Peter Wang added mode fetching for X11 fullscreen and DGA
   fullscreen drivers.
<li>
   3.9.39: Robert J. Ohannessian fixed 16bit masked blit SSE code and
   removed unused instruction in the other blitters.
<li>
   3.9.39: Salvador Eduardos Tropea added some GCC 3.x fixes.
<li>
   3.9.39: Peter Wang added a check if a module listed in modules.lst exist
   before trying to load it.
<li>
   3.9.39: Charles Wardlaw made alert/alert3 use transparent background for
   text label.
<li>
   3.9.39: Eric Botcazou added a flush_config_file() API function. Also added
   a hfill() method to the GFX_VTABLE structure.
<li>
   3.9.39: Peter Wang fixed some memory leaks.
<li>
   3.9.39: Eric Botcazou fixed two compilation warnings with gcc &gt; 2.95.
<li>
   3.9.39: Johan Peitz contributed 'Alex the Allegator' icon.
<li>
   3.9.39: Angelo Mottola fixed safe fullscreen bug and fetch_mode_list()
   for BeOS.
<li>
   3.9.39: Peter Wang updated XDGA2 and SVGAlib driver's fetch_mode_list()
   function.
<li>
   3.9.39: Henrik Stokseth rewrote the mode-list API, updated the code and
   updated the documentation.
<li>
   3.9.39: Grzegorz Adam Hankiewicz updated all URLs in the Allegro sources
   and documentation.
<li>
   3.9.39: Eric Botcazou fixed cmplog script for perl 5.6.1.
<li>
   3.9.39: Peter Wang added a FAQ entry.
<li>
   3.9.39: Peter Wang fixed up the sound subsystem which he accidentally
   broke when he introduced the dynamic modules.
<li>
   3.9.39: Eric Botcazou fixed a compilation warning. Also added support
   for 8-bit desktops to the windows windowed driver. Fixed color shifts in
   the color convertors from 8-bit. Fixed a bug in the 8-&gt;8 color conversion
   routine.
<li>
   3.9.39: Javier Gonzalez contributed bidirectional looping support for the
   directsound driver.
<li>
   3.9.39: Robert J. Ohannessian and Henrik Stokseth did a large update on
   the installation instructions for Mingw32.
<li>
   3.9.39: Eric Botcazou cleaned up windows dll version info sheet and let
   the windows makefiles use implicit rules on some file targets. Fixed a
   compilation glitch with MSVC.
<li>
   3.9.39: Henrik Stokseth added support for building RPMs with SuSE Linux.
<li>
   3.9.39: Peter Wang fixed some off-by-one errors. Fixed unix makefile.
   Fixed disabling of dynamic modules.
<li>
   3.9.39: Eric Botcazou and Grzegorz Adam Hankiewicz finished translation
   of the allegro.spec file.
<li>
   3.9.39: Eric Botcazou re-added a faq entry on DirectX version problem.
<li>
   3.9.39: Grzegorz made fbcon a module.
<li>
   3.9.39: Peter Wang removed allegro-enduser.spec as it is no longer needed.
   Also contributed a rewrite of the allegro.spec file, and updated the
   scripts to make the rpm. The new allegro.spec file was based on one
   contributed by Osvaldo Santana Neto. Peter also allowed configure to give
   linker flags to allegro-config (for modules). Also let _unix_find_resource
   search in /usr/[local/]share/allegro for .dat files.
<li>
   3.9.39: Javier Gonzalez contributed backward playing support for the
   directsound driver.
<li>
   3.9.39: Eric Botcazou fixed a glitch with backward playing in the digitest
   test.
<li>
   3.9.39: Salvador Eduardos Tropea made a small update on the cygwin section
   of readme.mgw.
<li>
   3.9.39: Peter Wang fixed a problem with BSD make and Mac directory
   separators ':'. Documented gfx_cardw variable.
<li>
   3.9.39: Sven Sandberg fixed a nasty side-effect of clear() inlining on
   Watcom.
<li>
   3.9.39: Laurence Withers fixed a crash bug in the mode-selector.
<li>
   3.9.39: Peter Wang removed SIGIO asynch stuff since it's not needed when
   we have pthreads. Updated documentation to mention dynamic modules.
   Added configure option to disable threads.
<li>
   3.9.39: Burton Radons fixed a bug in his dissolve blender.
<li>
   3.9.39: Eric Botcazou fixed a bug in the menus caused by auto-opening.
<li>
   3.9.39: Henrik Stokseth updated the makefiles to use -mcpu=pentium instead
   of the depreciated -mpentium gcc option. Also let the packaging scripts
   run autoconf and remove hidden or leftover files.
<li>
   3.9.39: Eric Botcazou cleaned up the windows sound code. Also clarified
   the code in the core menu function. Corrected a unicode glitch.
   Removed remaining references to ALLEGRO_NO_FINDFIRST. Added a unified
   al_find*() interface. Made the Portuguese translation file of the former
   Portuguese (Br) file. Fixed a few keyboard configuration files. Changed
   pl.cfg EOLN delimiter to \r\n.
<li>
   3.9.39: Grzegorz Godlewski contributed a Polish localization patch.
   Also added support for lower and upper altgr tables.
<li>
   3.9.39: Eric Botcazou fixed a bug in the keyconf utility caused by the
   sectionification.
<li>
   3.9.38: Robert J. Ohannessian added the following to the color convertor:
   color copy routines needed by the BeOS port, support for cross-conversion
   between 15-bit and 16-bit colors, support for conversion to 8-bit color,
   support for rectangles of any width and added two new MMX routines.
<li>
   3.9.38: Henrik Stokseth rewrote get_gfx_mode_list() likewise rewrote the
   mode-selector to use get_gfx_mode_list(). Also added fetch_mode_list()
   functions on the DirectX, VGA, Mode-X and Xtended GFX drivers.
<li>
   3.9.38: Angelo Mottola fixed problems with SMP on the BeOS port.
<li>
   3.9.38: Eric Botcazou fixed some problems with the non-MMX code in the
   color convertor.
<li>
   3.9.38: Sven Sandberg improved spline() for DRAW_MODE_TRANS
<li>
   3.9.38: Peter Wang renamed clear() to clear_bitmap(). clear() is still
   provided for backwards compatibility.
<li>
   3.9.38: Stepan Roh made fractal generator work under non-Intel
   processors.
<li>
   3.9.38: Eric Botcazou made a valid display switch mode of SWITCH_NONE
   under DOS.
<li>
   3.9.38: Angelo Mottola made the BeOS port use the new unified color
   conversion routines.
<li>
   3.9.38: Peter Wang added check to see if display is local under X11.
<li>
   3.9.38: Eric Botcazou and Sven Sandberg fixed compilation under
   Watcom 10.6.
<li>
   3.9.38: Elias Pschernig contributed an icon resource fixer for the
   Windows port and added support for shared library under BeOS.
<li>
   3.9.38: Angelo Mottola added a bfixicon utility.
<li>
   3.9.38: Stepan Roh made the native Allegro time format of ANSI time_t.
<li>
   3.9.38: Peter Wang added an ustrtok_r() function.
<li>
   3.9.38: Robert J. Ohannessian optimized some masked_blits with SSE
   instructions.
<li>
   3.9.38: Angelo Mottola did a sound fix for audiostream output and SMP
   machines and added triple buffering support on the BeOS port.
<li>
   3.9.38: Angelo Mottola added fetch_mode_list() support to the BeOS
   fullscreen driver.
<li>
   3.9.38: Eric Botcazou changed the acceleration scheme for the mouse under
   Windows.
<li>
   3.9.38: Peter Wang added fetch_mode_list() support to the svgalib driver.
<li>
   3.9.38: Peter Wang added pthread timer and removed dependancy to SIGALRM.
<li>
   3.9.38: Henrik Stokseth added Windows XP detection.
<li>
   3.9.38: Andreas Kluge fixed a bug with volume setting in the DOS
   Soundscape driver.
<li>
   3.9.38: Angelo Mottola rewrote the BeOS sound driver to use the
   BSoundPlayer class.
<li>
   3.9.38: Robert J. Ohannessian added SSE and SSE2 detection.
<li>
   3.9.38: Connelly Barnes fixed a bug with the DirectSound pan.
<li>
   3.9.38: Eric Botcazou added support of switch modes to the test program.
<li>
   3.9.38: Eric Botcazou modified the Windows switch mechanism.
<li>
   3.9.38: Angelo Mottola added fullscreen display switching support and did
   many fixes and cleanups on the BeOS port.
<li>
   3.9.38: Henrik Stokseth added code to get more os info under unix.
<li>
   3.9.38: Nimrod Abing fixed a bug in the config routines related to the
   NULL section.
<li>
   3.9.38: Eric Botcazou fixed a crash in the Windows windowed driver on fast
   machines.
<li>
   3.9.38: Ronaldo Hideki Yamada did a large update on the PowerMac port and
   added a midi driver.
<li>
   3.9.38: Henrik Stokseth generalised the support for processor specific
   optimisations in some makefiles.
<li>
   3.9.38: Evert Glebbeek put set_gfx_mode on a diet and added config entry
   for specifying the card to use for GFX_AUTODETECT_WINDOWED.
<li>
   3.9.38: Robert J. Ohannessian made blit not convert between colordepths
   for video bitmaps. (for AllegroGL)
<li>
   3.9.38: Peter Wang made fix_filename_slashes() handle both types of
   slashes.
<li>
   3.9.38: Grzegorz Adam Hankiewicz implemented a switch in makedoc to check
   for long (&gt;77) doc lines.
<li>
   3.9.38: Owen Rudge contributed a DLL version resource script.
<li>
   3.9.38: Sven Sandberg made the rotation functions faster, more accurate
   and working with any type of bitmap. Also removed
   rotate_scaled_sprite_flip().
<li>
   3.9.38: Angelo Mottola added fetch_mode_list() support to DGA2.
<li>
   3.9.38: David A. Capello made test program use transparent polygon types.
<li>
   3.9.38: Owen Rudge contributed a mkdata.bat script.
<li>
   3.9.38: Grzegorz Adam Hankiewicz added reload_config_texts().
<li>
   3.9.38: Eric Botcazou added an enhanced building mechanism for DLL
   export definition files.
<li>
   3.9.38: Eric Botcazou added a new unicode example program and did a ton of
   small fixes.
<li>
   3.9.37: Johan Peitz fixed and enhanced the Win32 joystick driver.
<li>
   3.9.37: Sven Sandberg added Ctrl + arrow keys to d_edit_proc().
<li>
   3.9.37: Eric Botcazou changed the color key for the Windows overlay
   driver to bright pink.
<li>
   3.9.37: Eric Botcazou reverted some changes he made to the timer core
   last release which were causing problems with the MIDI player, and
   removed the Windows multithreaded timer driver.
<li>
   3.9.37: Henrik Stokseth made some updates to the OS detection code, and
   added a os_multitasking variable.
<li>
   3.9.37: Eric Botcazou fixed a problem in the config routines, where
   entries in the NULL section were hiding duplicate entries in other
   sections.
<li>
   3.9.37: Eric Botcazou made the setup program use Unicode functions.
<li>
   3.9.37: Henrik Stokseth unified the fix* scripts, and gave them new
   options.
<li>
   3.9.37: Peter Wang added support for dynamically loaded modules under
   Unix. The SVGAlib, ALSA digital, ALSA MIDI, ESD and DGA2 drivers will
   be built as modules when possible. This removes external dependencies
   on the main library and improves binary transportability under Linux.
<li>
   3.9.37: Eric Botcazou made many changes and bug fixes to the Unicode
   string functions, and their use in the library.  The old functions now
   behave exactly like the libc equivalents, while the new functions (the
   'z' functions) behave more sanely. This change affects most code which
   uses the Unicode functions.
<li>
   3.9.37: Bertrand Coconnier changed the recently merged scene rendering
   API, fixed a bug, and provided a new example program. The API change
   will affect all code which uses the scene functions.
<li>
   3.9.37: Laurence Withers wrapped registration of the bitmap file types
   in a constructor. Where constructors are supported, this should reduce
   the executable size when statically linking (unless you use the bitmap
   loaders, of course).
<li>
   3.9.37: Ben Davis modified the set_volume_per_voice scale. Please see
   the docs for this function if you have used it in the past.
<li>
   3.9.37: Eric Botcazou worked around a DOS mouse bug under Win2k.
<li>
   3.9.37: Eric Botcazou added VGA Mode 13h support under DirectX 5 or
   greater.
<li>
   3.9.37: Henrik Stokseth added a get_gfx_mode_list() function, and the
   implementation of it for the VESA driver.
<li>
   3.9.37: Eric Botcazou and Annie Testes toiled hard to avoid buffer
   overflows (particularly with regards to the Unicode functions).
<li>
   3.9.37: Eric Botcazou fixed a mouse mickeys bug and cleaned up the
   input subsystem under Windows.
<li>
   3.9.37: Eric Botcazou made two minor changes in the handling of index 0
   in paletted modes.
<li>
   3.9.37: Eric Botcazou added a transparency preserving feature to the
   grabber and dat utility.
<li>
   3.9.37: Eric Botcazou fixed a crash when alt-tabbing in page flipping
   under Windows.
<li>
   3.9.37: Peter Wang added gui_menu_draw_menu and gui_menu_draw_menu_item
   to allow customising the look of the GUI menus (to a certain extent).
<li>
   3.9.37: Angelo Mottola added support for the new
   GFX_AUTODETECT_FULLSCREEN and GFX_AUTODETECT_WINDOWED constants, which
   we _all_ wholeheartedly agreed upon :-)
<li>
   3.9.37: Eduard Bloch made config vars which exist but are empty return
   defaults.
<li>
   3.9.37: Elias Pschernig added a COLORCONV_KEEP_TRANS mode.
<li>
   3.9.37: Henrik Stokseth added support for compiling with Cygwin. It
   works in Mingw compatibility mode.
<li>
   3.9.37: Angelo Mottola made GUI submenus automatically open when the
   mouse hovers for long enough. (This was an old patch that finally got
   merged.) Eric made some related modifications to it later.
<li>
   3.9.37: Eric Botcazou made clear_keybuf() not clear the key[] array.
<li>
   3.9.37: Sven Sandberg added a --quick option to fix scripts.
<li>
   3.9.37: Angelo Mottola did _loads_ of work on the QNX port (much too
   much to document here).
<li>
   3.9.37: Eric Botcazou made the Win32 asm color conversion code for
   windowed drivers available for other ports, and added a few other
   converters. Isaac Cruz added one too.
<li>
   3.9.37: Eric Botcazou restructured the config file format.  Some
   previously unsectioned variables are now in sections.
<li>
   3.9.37: George Foot added a threading system to handle asynchronous
   events, instead of using SIGALRM (under Unix).
<li>
   3.9.37: George Foot fixed some problems with pack_fgets().
<li>
   3.9.36: Eric Botcazou made it so that set_keyboard_rate(0, 0) will
   disable keyboard repeat, as in the documentation.
<li>
   3.9.36: Annie Testes added font_height, render_char, char_length hooks
   to FONT_VTABLE.
<li>
   3.9.36: Eric Botcazou made some minor changes related to AllegroGL in
   the window management code, and fixed two little mouse bugs Javier
   Gonzalez had found (both under Windows).
<li>
   3.9.36: Eric Botcazou added a get_desktop_resolution() function for
   Windows and X. Joshua Haberman added a BeOS version.
<li>
   3.9.36: Angelo Mottola comprehensively started a QNX port.
<li>
   3.9.36: Robert Ohannessian corrected src/dest ordering in additive
   blenders.
<li>
   3.9.36: Eric Botcazou improved support of external windows in Windows.
<li>
   3.9.36: Peter Wang updated the SVGAlib driver for version 2.
<li>
   3.9.36: Peter Wang added a fullscreen version of the X-Windows graphics
   driver. The original was by Benjamin Joel Stover.
<li>
   3.9.36: Peter Wang made grabber use file_select_ex(). This is just here
   so you don't get a shock :-)
<li>
   3.9.36: Eric Botcazou fixed some small bugs in the DirectSound input code.
<li>
   3.9.36: Eric Botcazou fixed the NumLock state in X not matching
   keyboard LEDs.
<li>
   3.9.36: Eric Botcazou reenabled the multi-threaded timer under Windows.
<li>
   3.9.36: Eric Botcazou and Javier Gonzalez made the keyboard repeat
   system more efficient.
<li>
   3.9.36: Eric Botcazou fixed some asm blitters, and also a bug with
   changing timer speeds.
<li>
   3.9.36: Peter Wang made the keypad return / * - + ASCII values even if
   NumLock is off, under Linux console.
<li>
   3.9.36: Ronaldo Hideki Yamada made a big update of the Mac port,
   including some new PPC files.
<li>
   3.9.36: The GGI driver was removed, due to its inability to actually
   work. It is no longer supported, unless someone rewrites it.
<li>
   3.9.36: Eric Botcazou fixed a problem with the GDI driver when compiled
   with MSVC.
<li>
   3.9.36: Some MIDI fixes by Javier Gonzalez and Eric Botcazou.
<li>
   3.9.36: Grzegorz Adam Hankiewicz improved the fb.modes line parsing
   function in the fbcon driver.
<li>
   3.9.36: Grzegorz Adam Hankiewicz changed the behaviour of GFX_SAFE.
   This means that "set_gfx_mode(GFX_SAFE, ...)" now returns an error if
   it is unable to set a video mode, just like any other video driver.
<li>
   3.9.36: Eric Botcazou fixed volume setting in Windows.
<li>
   3.9.36: Eric Botcazou added DirectX 3 compatibility.
<li>
   3.9.36: Nick Kochakian added input routines to the DirectSound driver.
   It was also modified by Javier Gonzalez.
<li>
   3.9.35: Eric Botcazou made Windows restore the original sound volume
   after an Allegro program quits.
<li>
   3.9.35: Eric Botcazou fixed sample looping in DirectSound driver.
<li>
   3.9.35: Grzegorz Adam Hankiewicz solved some color problems in the
   demo game.
<li>
   3.9.35: Angelo Mottola implemented a close button hook for X11.
<li>
   3.9.35: Eric Botcazou fixed _the_ Windows 2000 keyboard bug.
<li>
   3.9.35: Eric Botcazou made some changes to the locking/unlocking
   mechanism in the Windows port.
<li>
   3.9.35: Laurence Withers made some modules avoid linking
   dependencies.
<li>
   3.9.35: Javier Gonzalez added close button support for Windows.
<li>
   3.9.35: Eric Botcazou improved mouse handling in the GFX_GDI driver
   and fixed some other mouse glitches.
<li>
   3.9.35: Peter Wang made set_mouse_sprite(NULL) regenerate the
   default arrow bitmap (using the current palette).
<li>
   3.9.35: Eric Botcazou made hardware accelerated primitives stop
   when the user switches out in Windows.
<li>
   3.9.35: Tom St Denis fixed clipping of transparent objects.
<li>
   3.9.35: Eric Botcazou and Javier Gonzalez improved switching in
   Windows and other things.
<li>
   3.9.35: Peter Wang made the Linux joystick driver use standard
   constants.
<li>
   3.9.35: Sven Sandberg changed the Z-buffer API.
<li>
   3.9.35: Peter Wang made the default mouse sprite independent of the
   palette in 8 bpp modes.
<li>
   3.9.35: Bertrand Coconnier added documentation for the P3D merge.
<li>
   3.9.35: Angelo Mottola fixed desktop_color_depth() and added window
   close button support for the BeOS port.
<li>
   3.9.35: Ben Davis added the set_window_close_button() and
   set_window_close_hook() framework.
<li>
   3.9.35: Peter Wang exposed the mouse_sprite, mouse_x_focus and
   mouse_y_focus variables.
<li>
   3.9.35: Robert Ohannessian and Javier Gonzalez fixed bad clearing
   of subbitmaps.
<li>
   3.9.35: Peter Wang renamed GFX_XDFS to GFX_XDGA_FULLSCREEN.
<li>
   3.9.35: Henrik Stokseth updated the cross-compilation system.
<li>
   3.9.35: Tomohiko Sugiura added some keys and renamed some JP keys.
<li>
   3.9.35: Eric Botcazou added a DirectDraw2 interface, with support
   for refresh rates.
<li>
   3.9.35: Bertrand Coconnier merged in Calin Andrian's P3D library.
<li>
   3.9.35: Javier Gonzalez made allegro_message() use the title from
   set_window_title() in Windows.
<li>
   3.9.35: Andreas Kluge fixed division bugs in the fix class.
<li>
   3.9.35: Stepan Roh documented the FA_* flags.
<li>
   3.9.35: Peter Wang added hooks to allow overriding the look of
   standard dialogs.
<li>
   3.9.35: Peter Wang changed X window placement and mapping behaviour.
<li>
   3.9.35: David A. Capello made dotted_rect() avoid bank switches.
<li>
   3.9.35: Eric Botcazou fixed a freezing problem under Window with
   locking/unlocking bitmaps under heavy load. He received help
   tracking down the bug from Javier Gonzalez.
<li>
   3.9.35: Stepan Roh fixed a bug with FA_RDONLY constant under Unix.
<li>
   3.9.35: Eric Botcazou cleaned up the Windows graphics subsystem.
<li>
   3.9.35: "Sask Allegro" added support for more than two joysticks in
   the Windows port.
<li>
   3.9.34: Ben Davis made close button in Windows windowed modes not
   simulate Escape key, in preparation for new behaviour (in next WIP).
<li>
   3.9.34: Laurence Withers fixed a problem with accents in keyconf.
<li>
   3.9.34: Javier Gonzalez added DIGMID to the Windows MIDI drivers list.
<li>
   3.9.34: Eric Botcazou cleaned up the DirectDraw subsystem.
<li>
   3.9.34: Eric Botcazou made the DirectDraw overlay driver comply with
   page flipping and triple buffering code, amongst other things.
<li>
   3.9.34: Bertrand Coconnier improved subtexel accuracy for texture
   mapping.
<li>
   3.9.34: Javier Gonzalez corrected mouse movement speed in Windows.
<li>
   3.9.34: Ben Davis adapted polygon functions to handle two coincident
   vertices, and changed and clarified texture coordinate alignment in
   code and documentation.
<li>
   3.9.34: Grzegorz Adam Hankiewicz fleshed out the docs for Unicode
   functions, adapting from djgpp and gcc docs.
<li>
   3.9.34: Eric Botcazou fixed a triple buffering problem in the
   DirectDraw accelerated driver.
<li>
   3.9.34: Henrik Stokseth added support for cross-compilation in the
   mingw32 build.
<li>
   3.9.34: Grzegorz Adam Hankiewicz updated more examples for GFX_SAFE.
<li>
   3.9.34: Ben Davis added set_volume_per_voice(), made silent voices
   continue playing and fixed other minor bugs.
<li>
   3.9.34: Ben Davis fixed a bug in create_rgb_table().
<li>
   3.9.34: Angelo Mottola added display switching routines for BeOS and
   fixed some bugs.
<li>
   3.9.34: Laurence Withers updated documentation about `const'.
<li>
   3.9.34: Ronaldo Hideki Yamada contributed a macintosh port of Allegro.
<li>
   3.9.34: Grzegorz Adam Hankiewicz changed and documented new GFX_SAFE
   behaviour (that color depth is undefined), updated the fbcon driver to
   take advantage of this and updated example programs.
<li>
   3.9.34: Peter Pavlovic fixed a bug caused by file selector stretching.
<li>
   3.9.34: Bertrand Coconnier fixed bugs related to poly3d(); removed
   never-called C versions of scanline functions for POLYTYPE_FLAT and
   non-8bpp POLYTYPE_GCOL; and made clip3d() and clip3d_f() functions
   compliant with Z-buffered polygons.
<li>
   3.9.34: Stepan Roh added C version of masked_stretch_blit().
<li>
   3.9.34: Angelo Mottola did more work on BeOS: hardware acceleration
   (rect, hline, vline, clear_to_color, blit); mouse fix in windowed mode;
   desktop_color_depth(); yield_timeslice();
<li>
   3.9.34: Peter Wang retroactively updated CHANGES and AUTHORS from
   late 3.9.33 to present using CVS logs and email archives, and
   possibly messed up.
<li>
   3.9.34: Angelo Mottola added a BeOS windowed driver (originally by
   Peter Wang), a BeOS MIDI driver, mouse wheel support under BeOS and
   made many bug fixes and changes to other BeOS code and documentation.
<li>
   3.9.34: Laurence Withers fixed dat2s output of fonts for new font
   subsystem.
<li>
   3.9.34: Peter Wang made the SVGAlib driver more robust.
<li>
   3.9.34: Peter Wang changed the way Intellimouse protocols are selected
   under Linux console.
<li>
   3.9.34: Eric Botcazou added file_select_ex and reverted file_select to
   old behaviour.
<li>
   3.9.34: Laurence Withers added ugetcx() function.
<li>
   3.9.34: Laurence Withers designed and implemented a new FONT structure,
   which should provide many advantages over the old one.
<li>
   3.9.34: Eric Botcazou made more fixes to Windows code.
<li>
   3.9.34: Bertrand Coconnier added a z-buffer rendering mode for 3D
   polygons (derived from Calin Andrian's P3D library) and an example
   program for it.
<li>
   3.9.34: Michael Bukin added customization for keycode to scancode
   mapping in X.
<li>
   3.9.34: Peter Wang added mouse wheel support to d_textbox_proc and
   d_slider_proc, and made file selector dialog stretch.
<li>
   3.9.34: Tom Fjellstrom added an ALSA MIDI driver.
<li>
   3.9.34: Eric Botcazou made some changes to the Windows windowed driver.
<li>
   3.9.34: Grzegorz Adam Hankiewicz updated the documentation and the
   makedoc program to produce better .texi output. The new version works
   very well with the texi2dvi program, which produces fine ready to print
   device independent output. Also documented the new unix makefile targets.
<li>
   3.9.34: George Foot added --env option to allegro-config script.
<li>
   3.9.34: Benjamin Stover made some vararg fixes in unicode.c and added a
   workaround for missing defines in fbcon.c.
<li>
   3.9.34: Robin Burrows added a Windows waveOut sound driver.
<li>
   3.9.34: Eric Botcazou changed desktop_color_depth() for Windows.
<li>
   3.9.34: Angelo Mottola added line switching and refresh rate support to
   DGA2 driver.
<li>
   3.9.34: Bertrand Coconnier added scanline subdivisions and fixed 3D
   polygon drawing.
<li>
   3.9.34: Angelo Mottola added BeOS joystick driver.
<li>
   3.9.34: Angelo Mottola added DGA2 driver.
<li>
   3.9.34: Robin Burrows added Windows sound driver using Allegro mixer.
<li>
   3.9.34: Stepan Roh added workaround for fceil defined in Irix headers.
<li>
   3.9.34: Michael Bukin changed DGA screen clearing.
<li>
   3.9.34: Tomohiko Sugiura added a more aggressive Sidewinder driver.
<li>
   3.9.34: Tomohiko Sugiura added three Japanese keys.
<li>
   3.9.34: Stepan Roh made C functions const-correct.
<li>
   3.9.34: Bertrand Coconnier fixed blending in atex_lit scanline
   functions.
<li>
   3.9.34: Michael Bukin modified text_mode to return previous mode.
<li>
   3.9.34: Peter Pavlovic fixed scrollbar display in grabber and improved
   scrolling in GUI objects.
<li>
   3.9.34: anarko made GUI objects restore textmode.
<li>
   3.9.34: Laurence Withers added font destroy hook.
<li>
   3.9.34: Vincent Penquerc'h modified the mouse button press/release events
   so they have higher priority than double-click events.
<li>
   3.9.34: Eric Botcazou improved colormap handling in XDGA.
<li>
   3.9.34: Robin Burrows provided a new page flipping code for the DirectDraw
   subsytem, which now works on every graphic card.
<li>
   3.9.33: Henrik Stokseth updated the mingw32 makefile, the documentation
   and sent in some other related fixes and updates. You will never again
   need MSVC to compile the Allegro DLLs. ;o)
<li>
   3.9.33: Peter Puck contributed some updates to Allegro's win32 code
   which got the native mingw32 build fully working.
<li>
   3.9.33: Michael Bukin changed the auto-repeat handling in X,
   sched_yield handling for Unix, fixed _add_exit_func, and added list of
   active dialogs to the GUI.
<li>
   3.9.33: Vincent Penquerc'h sped up the C versions of the RLE sprite
   drawing routines by quite a bit.
<li>
   3.9.33: Peter Wang improved TGA palette loading.
<li>
   3.9.33: Laurence Withers made more functions const-correct.
<li>
   3.9.33: Isaac Cruz moved Windows bitmap locking to a separate .S file,
   changed the update logic for the windowed driver, and added an accelerated
   vline implementation.
<li>
   3.9.33: Stephen Kittelson fixed a bug in pckeys.c, and changed the ASCII
   values returned for a few weird key combinations.
<li>
   3.9.33: Peter Wang made various functions const-correct.
<li>
   3.9.33: Peter Pavlovic made aesthetic modifications to the GUI menu
   system.
<li>
   3.9.33: Javier Gonzalez suggested that the file and mode selector dialogs
   should use popup_dialog.
<li>
   3.9.33: Vincent Penquerc'h added the install-gzipped-man makefile target,
   patched some of the EINTR handling, and made the OSS driver detect whether
   the device is 16 bit or not.
<li>
   3.9.33: Peter Pavlovic modified the Slovak keyboard mapping and made the
   file selector detect available drives in Windows.
<li>
   3.9.33: Peter Wang added a sound (output only) driver for BeOS.
<li>
   3.9.33: Sven Sandberg fixed a typo in the definition of ustrdup, added
   the uwidth_max function, provided the d_yield_proc function, and made
   various dialogs use it.
<li>
   3.9.33: Michael Bukin made the DGA driver clear video memory and centre
   the screen, if it's not fullscreen.
<li>
   3.9.33: Eduard Bloch suggested better ways to find the executable in
   Unix.
<li>
   3.9.33: Andrew Geers added flipped rotated sprites.
<li>
   3.9.33: George Foot made the Unix makefile work for non-root users.
<li>
   3.9.33: Grzegorz Adam Hankiewicz made language config files be forced
   to lower case.
<li>
   3.9.33: Grzegorz Adam Hankiewicz added documentation for findfirst(),
   findnext(), and findclose(), and corrected the documentation for
   get_executable_name().
<li>
   3.9.33: Stepan Roh made patches to allow compilation on IRIX.
<li>
   3.9.33: John Harger made a change to improve the stability of AllegroGL
   in Windows.
<li>
   3.9.33: Sven Sandberg fixed a bug in the plain C 16bpp stretched blitter.
<li>
   3.9.33: George Foot fixed a bug in the i386 8bpp masked blit routines,
   reported by Damian Yerrick.
<li>
   3.9.33: Eduard Bloch fixed a freeze caused by the ESD detection code.
<li>
   3.9.33: Vincent Penquerc'h added mouse button press/release events to
   the GUI system.
<li>
   3.9.33: Peter Wang solved a conflict with SVGAlib.
<li>
   3.9.33: Vincent Penquerc'h added the XCRP and YCRP properties to bitmap
   objects in datafiles.
<li>
   3.9.33: Vincent Penquerc'h made the GUI system not send MSG_DRAW to
   hidden objects.
<li>
   3.9.33: Chris La Mantia pointed out that his code for textprintf_right
   had mutated somehow.
<li>
   3.9.33: Peter Wang added a workaround for a mouse motion reporting bug
   in some X servers.
<li>
   3.9.33: Eric Botcazou altered the DGA code to work better in 32bpp modes.
<li>
   3.9.33: Daniel Nilsson tweaked exstars and exlights
<li>
   3.9.33: Isaac Cruz fixed a nasty bug with subbitmap locking, and added
   desktop_color_depth and yield_timeslice support to the Windows version.
<li>
   3.9.33: Peter Cech made uisspace() recognise non-ASCII space characters.
<li>
   3.9.32: S.Sakamaki added a function for controlling the refresh rate when
   using the DOS VESA 3.0 driver (this could also be supported by some other
   drivers if anyone wants to implement that).
<li>
   3.9.32: S.Suzuki added DOS drivers for the IF-SEGA /PCI, /PCI2, and /ISA
   joystick interface cards.
<li>
   3.9.32: Fabrizio Gennari added DOS drivers for multisystem joysticks with
   9-pin connectors (Atari, Commodore 64, MSX).
<li>
   3.9.32: Peter Pavlovic improved the support for accented character maps
   in the keyboard driver.
<li>
   3.9.32: Sven Sandberg optimised the GUI listbox scrolling to skip redraws
   if it can't keep up with the update speed.
<li>
   3.9.32: Olly Betts did some work to make cross-compiling the djgpp
   version work on Linux.
<li>
   3.9.32: Isaac Cruz improved the windowed mode ddraw driver, adding
   support for many different color depth conversions.
<li>
   3.9.32: Vincent Penquerc'h added an update selection function to the
   grabber.
<li>
   3.9.32: many bugfixes from various people.
<li>
   3.9.32: zipup.sh now generates dependencies entirely using standard Unix
   tools and gcc, so it can setup all the supported platforms without
   needing those compilers to be available (ie. I can create Watcom, BeOS,
   and Mingw32 dependencies all from my Linux machine). This does require a
   bit of cooperation from the different targets, though: they have to set
   up their "make depend" target to override the standard gcc defines, and
   wrap any non-standard header includes with "#ifndef SCAN_DEPEND".
<li>
   3.9.32: fixed (I hope :-) bug with non-GMT timezones in the datafile
   update code.
<li>
   3.9.32: rewrote the Unicode usprintf() to piggyback on libc when
   converting floating point data (too hard to get this right ourselves :-)
<li>
   3.9.31: Henrik Stokseth did some work on a native Mingw32 build. This is
   currently incomplete, and unlikely to work right now since there have
   been other changes in the Windows code since the version he started from.
   At the moment this version is statically linked, using makefile.mgs, and
   makefile.mgw still exists for the MSVC-piggyback version. The ultimate
   goal is to get this native version building as a DLL in addition to
   statically linked, at which point we can merge both makefiles into
   makefile.mgw and remove makefile.mgs. Oh yeah, and there are currently no
   docs for the native version.
<li>
   3.9.31: Greg Hackmann contributed a Borland C++ Builder port. Like the
   RSXNT and Mingw32 versions, this is a client for the MSVC DLL, and not
   able to compile Allegro directly itself, but allows you to build Allegro
   programs using the Borland compiler.
<li>
   3.9.31: Robert Ohannessian added MMX optimisation for the 8 and 16 bit
   clear() functions, and Jose Antonio Luque optimised the 16 bit blit() and
   masked_blit() routines.
<li>
   3.9.31: Vincent Penquerc'h added a yield_timeslice() function (currently
   implemented in DOS and Unix).
<li>
   3.9.31: added a desktop_color_depth() function (currently only
   implemented in X: a Windows version will follow).
<li>
   3.9.31: Isaac Cruz added support for windowed modes in color depths other
   than the current Windows desktop, and hardware accelerated system bitmaps.
<li>
   3.9.31: Jose Antonio Luque improved the Windows joystick driver.
<li>
   3.9.31: James Hyman added support for dithering truecolor down to
   paletted images.
<li>
   3.9.31: Chris La Mantia added textout_right(), textprintf_right(), and
   textprintf_justify() functions.
<li>
   3.9.31: Sven Sandberg added a ustrrchr() function, and improved the
   usprintf() handling of large floating point values.
<li>
   3.9.31: Peter Pavlovic added a Slovak keyboard mapping and message
   translation.
<li>
   3.9.31: Manni Heumann fixed some problems with the German keyboard
   mapping.
<li>
   3.9.31: Michael Bukin improved the X keyboard and mouse handling, and
   fixed some problems with building on non-GNU Unix systems.
<li>
   3.9.31: many bugfixes and tweaks from various people (sorry, my typing
   patience has run out so you don't get a full list :-)
<li>
   3.9.31: Peter Wang added input support to the Linux OSS sound driver.
<li>
   3.9.31: David Kuhling optimised the i386/gcc fsqrt() code, and added an
   fhypot() routine.
<li>
   3.9.30: fixed the double XOR that was making datafile passwords so easy
   to reverse. The new code can still read old-style encrypted files, but
   data written by this version can't be accessed by older copies of Allegro.
<li>
   3.9.30: made load_datafile(), load_datafile_object(), and the
   file.dat#object syntax work correctly in all possible combinations.
<li>
   3.9.30: Vincent Penquerc'h added a scare_mouse_area() function.
<li>
   3.9.30: changed the DirectX surface locking mechanism, to improve the
   performance of hardware accelerated drawing.
<li>
   3.9.30: George Foot improved the Linux LED code, and made the internal X
   driver state visible via xalleg.h.
<li>
   3.9.30: added EINTR retry handling to read/write calls. I hope I got this
   right: if anyone who properly groks this stuff could check over file.c,
   that would be cool.
<li>
   3.9.30: made the Windows mouse driver work correctly in windowed mode.
<li>
   3.9.30: fixed various problems with Windows foreground/background
   switching (keys were getting stuck down, timers weren't being paused, and
   not all the right switching modes were being reported to the caller).
<li>
   3.9.30: made the X keyboard handler release all keys when it loses the
   input focus, to avoid stuck buttons when you alt+tab between windows.
<li>
   3.9.30: made the allegro-lib script arguments compatible with the
   standard used by GTK, ESD, etc, and renamed it to allegro-config. This
   changes the syntax for linking Allegro programs on Unix: see readme.uni
   for details of the new method.
<li>
   3.9.30: George Foot improved the Unix shared library system.
<li>
   3.9.30: Joerg Rueppel added a find_datafile_object() function.
<li>
   3.9.30: Peter Wang improved the SVGAlib driver.
<li>
   3.9.30: Peter Wang improved the Linux joystick driver.
<li>
   3.9.29: made the Windows code agree with other platforms about how video
   bitmaps are supposed to behave.
<li>
   3.9.29: fixed some problems with the Windows mouse wheel support.
<li>
   3.9.29: added set_write_alpha_blender(), set_add_blender() and
   create_blender_table() functions, and made the 32 bit version of
   draw_trans_sprite() able to use 8 bit source images in conjunction with
   set_write_alpha_blender(). In addition to being generally useful, using
   these routines makes the sources for my SpeedHack entry much smaller :-)
<li>
   3.9.29: added uninstall targets to the Linux makefile.
<li>
   3.9.29: made the X windowed mouse driver hide the Allegro cursor when the
   mouse moves out of our window.
<li>
   3.9.29: added a simple timer delay emulation of vsync() to the X code, so
   that eg. the demo worms game runs sensibly.
<li>
   3.9.29: Isaac Cruz added a GFX_DIRECTX_WIN driver.
<li>
   3.9.29: Keith Gerdes made some more improvements to the DirectX overlay
   driver.
<li>
   3.9.29: Andrew Geers added scrolling support to the grabber image viewer.
<li>
   3.9.29: Peter Wang added an alternative X DGA driver, that includes mode
   switching support to run in fullscreen mode.
<li>
   3.9.29: Peter Wang added a MSG_WHEEL event to the GUI, and made
   d_list_proc() use it.
<li>
   3.9.29: Lucas Vignoli Reis added a Portuguese (Brazil) message
   translation and keyboard mapping.
<li>
   3.9.29: Peter Wang added a Linux OSS MIDI driver for FM synth devices,
   and mixer support for the OSS digital driver.
<li>
   3.9.29: George Foot added scripts for building various Linux distribution
   formats.
<li>
   3.9.29: Michael Bukin fixed the portability problems in quantize.c.
<li>
   3.9.29: added a zipwin.sh script for making Windows binary distributions,
   including a batch file that can compile the MSVC support programs without
   having any GNU tools installed.
<li>
   3.9.29: fixed bug with color font rendering in the Windows version.
<li>
   3.9.29: added hardware accelerated rectfill() and hline() to the Windows
   version, and fixed a couple of accel related bugs (clears were being
   clipped wrongly, and it was claiming to support XOR drawing even though
   that isn't supported).
<li>
   3.9.29: Michael Bukin fixed bug with X drawing onto screen sub-bitmaps.
<li>
   3.9.28: various documentation updates.
<li>
   3.9.28: added parameter autodetection to the Unix OSS sound driver.
<li>
   3.9.28: made it possible to nest calls to the Unix for_each_file()
   routine.
<li>
   3.9.28: added a load_datafile_callback() function.
<li>
   3.9.28: rationalised the sound config variables, so they can be shared
   between drivers more easily. For instance sb_freq has been renamed to
   sound_freq.
<li>
   3.9.28: Antti Koskipaa added a DOS driver for WSS (Windows Sound System)
   cards.
<li>
   3.9.28: the audiosteam code is now able to merge multiple buffers into a
   single larger one, so it will still work correctly even if the user
   supplies a buffer smaller than the current soundcard transfer size. You
   can even play streams with single byte buffers now, as long as you refill
   them often enough!
<li>
   3.9.28: made the Windows timer code more robust, so it will no longer
   lock up when you install extremely high frequency callbacks.
<li>
   3.9.28: Teijo Hakala added wheel support to the Windows mouse driver.
<li>
   3.9.28: Peter Wang added wheel support to the X mouse driver.
<li>
   3.9.28: Andrew Geers added -ppassword and -nosound options to the grabber.
<li>
   3.9.28: Keith Gerdes fixed the DirectDraw overlay mode driver.
<li>
   3.9.28: Isaac Cruz fixed the bug with accelerated drawing onto sub
   bitmaps of DirectDraw surfaces.
<li>
   3.9.28: Peter Wang added banked mode support to the SVGAlib driver.
<li>
   3.9.28: Peter Wang fixed some problems with the ESD sound driver, and
   added an ALSA driver.
<li>
   3.9.28: palette fading speed is now timer regulated, to avoid problems
   with some systems (eg. DGA with non-matching color depth) where it can be
   excessively slow.
<li>
   3.9.28: fixed a couple of different overflow bugs that were causing
   timers to run slow on heavily loaded Unix systems.
<li>
   3.9.28: added a display of author credits to the demo game.
<li>
   3.9.28: changed the info page installation system. It now creates a dir
   file in the same directory as the info page, rather than messing around
   with symlinks, and autoconf is used to locate the install-info program.
<li>
   3.9.28: added an allegro-lib script to the Unix installation, which can
   be run by makefiles to find the right linker commandline for building
   Allegro programs.
<li>
   3.9.28: added a manpage output format to the makedoc utility. It doesn't
   work terribly well with apropos due to the lack of a one-line summary for
   each function, but the basic formatting seems to be ok: please let me
   know if you see any problems.
<li>
   3.9.28: patches from George Foot for Linux console handing, keyboard, and
   filename manipulations.
<li>
   3.9.28: many improvements by Michael Bukin, in particular enhanced
   performance in X, better X mouse behaviour, and DGA graphics support.
<li>
   3.9.27: Robert J. Ragno made some improvements to the Wingman, PSX, and
   throttle joystick input code.
<li>
   3.9.27: Peter Wang added wheel input support to the Linux mouse code
   (this shows up as a new mouse_z state variable).
<li>
   3.9.27: Patrick Hogan made Windows audiostreams work properly.
<li>
   3.9.27: Sven Sandberg optimised the spline routines.
<li>
   3.9.27: Tomohiko Sugiura added KEY_YEN and KEY_YEN2 Japanese keys to the
   input handler.
<li>
   3.9.27: Chris Robinson wrote a fixed point version of clip3d_f(), called
   (surprise!) clip3d().
<li>
   3.9.27: Sven Sandberg improved the file selector sorting algorithm.
<li>
   3.9.27: Henrik Stokseth improved the OS detection in the Windows lib.
<li>
   3.9.27: Sven Sandberg made more accurately rounded lookup tables for the
   fixed point trig routines.
<li>
   3.9.27: George Foot made the fbcon driver reset the palette on exit.
<li>
   3.9.27: much new X code from Michael Bukin: this stuff is working
   brilliantly now!
<li>
   3.9.27: added the X library path to the Linux liballeg.a wrapper. I think
   I prefer Michael's idea of having a script to return this info, though,
   so perhaps we should change across to doing it that way.
<li>
   3.9.27: fixed various bugs in both the C and i386 RLE sprite code (mostly
   relating to lit modes and hicolor formats).
<li>
   3.9.27: front-ported various fixes from the 3.12 release, to make
   WARNMODE=1 compile cleanly with gcc 2.95.
<li>
   3.9.27: Knut Pape improved the Mingw32 readme file.
<li>
   3.9.26: rewrote the DOS Sidewinder driver, after powerjaw sent me a pad
   to test it with. It still doesn't work for me in DOS mode, but it is ok
   under Windows, which is better than before, and as good as any of the
   other Sidewinder code that I've been able to locate. If anyone has or
   knows of code that works better than this, please let me know!
<li>
   3.9.26: more flexible mode flags for set_color_conversion().
<li>
   3.9.26: Robert J. Ragno added a driver for Gravis GrIP devices.
<li>
   3.9.26: Gorka Olaizola added a Redhat RPM .spec file.
<li>
   3.9.26: Stepan Roh updated the Czech translation and added multiple
   codepage support to the textconv utility, and a Unicode-aware ustrtod()
   function.
<li>
   3.9.26: added ustrdup() to the Unicode support functions.
<li>
   3.9.26: Sven Sandberg optimised the gcc fixed point math routines to
   collapse constant expressions at compile time.
<li>
   3.9.26: Stefan T. Boettner added a proper Linux SVGAlib driver.
<li>
   3.9.26: several tweaks from Vincent Penquerc'h (added a datafile merge
   function to the grabber, GUI bugfixes, optimised spline calculation, fix
   for 24 bit version of the C drawing code).
<li>
   3.9.26: Linux patches from Michael Bukin improve the OSS sound driver,
   SIGALRM handling, and X keyboard driver.
<li>
   3.9.26: many Linux patches from George Foot (fixes to the mouse driver,
   shared library and configure script, and assorted other stuff).
<li>
   3.9.25: fixed pckeys.c to leave sensible data in the key[] array when
   doing numeral vs. arrow key numlock fakery.
<li>
   3.9.25: fixed a bunch of problems with the SWITCH_BACKGROUND mode (I'd
   stupidly forgotten to disable a lot of graphics driver functions that
   could do bad things if called when the Allegro console isn't active).
<li>
   3.9.25: added pivot_sprite() and pivot_scaled_sprite() functions (thanks
   to Matt Jallo for the suggestion).
<li>
   3.9.25: added ustrerror() to the standard Unicode support functions.
<li>
   3.9.25: fixed the d_edit_proc() GUI object to handle shift+tab focus
   movement properly.
<li>
   3.9.25: lots of Linux patches from George Foot (proper fbcon mode
   setting, different mouse types and setup program support for configuring
   them, fixes to the shared library support, exedat no longer destroys the
   file permissions, and probably some other stuff that I forgot about).
<li>
   3.9.24: assorted bugfixes to the Linux fbcon and sound code (this is
   mostly an emergency release because these were broken in 3.9.23).
<li>
   3.9.24: James Arthur wrote some docs for the Photoshop-style truecolor
   blender routines.
<li>
   3.9.23: Michael Bukin added an OSS sound driver to the Linux code, and
   the beginnings of an ESD driver.
<li>
   3.9.23: many Linux patches from George Foot, including shared library
   support.
<li>
   3.9.23: Ole Laursen made the Unicode utolower() and utoupper() functions
   understand the entire 16 bit character set.
<li>
   3.9.23: Pavlos Touboulidis made file_select() able to include or exclude
   files based on their attributes.
<li>
   3.9.23: the d_check_proc() GUI object can now print the text to the right
   of the check, selected by having a non-zero d1 field.
<li>
   3.9.23: changed my mind about how GFX_SAFE should work, and removed the
   color depth emulation bodges. Now, the GFX_SAFE driver may simply change
   the color depth if it doesn't like what you are requesting, and it is up
   to the caller to deal with this.
<li>
   3.9.23: fixed problems with MMX polygon rendering code in the MSVC
   version.
<li>
   3.9.23: added a strictwarn option to the configure script, and fixed
   everything that it moaned about. The warnings still aren't all that
   strict: at some point I want to sit down and make it build cleanly with
   -W, as well as -Wall -Werror.
<li>
   3.9.22: fixed some potential race conditions introduced by my previous
   fixes to the Windows timer code.
<li>
   3.9.22: made set_display_switch_callback() able to install multiple hook
   functions, added a remove_display_switch_callback() routine, and wrote an
   exswitch example program.
<li>
   3.9.22: adjusted MSVC inline asm syntax in an attempt to work around
   compiler version conflicts.
<li>
   3.9.22: more flexible GFX_SAFE system. As well as defining fixed safe
   values for each platform, you can now leave out those definitions to get
   zeros passed through to the actual hardware drivers, and if your driver
   sets a color depth other than the requested one, graphics.c will hook up
   some emulation routines so that everything still works in a sensible way.
<li>
   3.9.22: George Foot added a scancode to ASCII conversion function to the
   keyboard driver (implemented for DOS, Windows, Linux, and X). This is
   needed to handle alt+key input sensibly when using unusual mappings like
   the Dvorak layout.
<li>
   3.9.22: Linux patches from George add better console switching, shared
   library support, and various other nice things.
<li>
   3.9.22: Windows patch from Stefan adds much cool new stuff, including
   windowed mode support.
<li>
   3.9.22: Peter Wang made the Linux GGI driver work properly.
<li>
   3.9.22: Johan Venter made some more improvements to the RSXNT and Mingw32
   makefiles.
<li>
   3.9.22: updated the Watcom makefile to allow manual override of the 10.6
   vs. 11.0 version detection, in case it guesses wrong.
<li>
   3.9.21: Windows patch from Stefan adds support for the new screen mode
   switching system.
<li>
   3.9.21: more BeOS patches from Jason Wilkins.
<li>
   3.9.21: Johan Venter fixed some problems with the RSXNT and Mingw32
   makefiles.
<li>
   3.9.21: ran "configure --enable-asm=no", and fixed all the reasons why
   this didn't work. In particular there was a bug in patterned drawing
   modes, RLE sprites were broken, and I'd forgotten to add C versions of
   the RGBA sprite functions. Those of you who are interested in such things
   will be interested to know that the test program thinks the C drawing
   code is 20% slower at hline(), 10% slower at rectfill(), 50% slower at
   blitting, and 40% slower at draw_sprite(), which is not at all bad going.
   It's actually a bit faster at drawing translucent and lit sprites, so we
   need to have a look at that!
<li>
   3.9.21: many new Linux patches from George Foot.
<li>
   3.9.21: added VBE/AF support to the Linux code.
<li>
   3.9.21: finished the Linux fbcon driver.
<li>
   3.9.21: made Linux console switching work in a more complete manner, with
   a set of helper functions in dispsw.c. The background mode should work
   now, but is untested.
<li>
   3.9.21: added Linux GGI driver by Carsten Schmidt (this is somewhat out
   of date, and doesn't work yet, but a good start if anyone wants to hack
   on it).
<li>
   3.9.21: improved the Unix configure and build system. Moved more things
   into makefile.lst, so there are no file lists anywhere else now. Made it
   understand how to build the datafile tools, and convert the documentation
   (this may cause problems for systems without makeinfo: it would be good
   if someone who groks autoconf could try to do this better). Made the
   Linux VGA drivers (vga and modex) configurable.
<li>
   3.9.21: added ctrl+alt+end abort sequence to the Linux keyboard driver.
<li>
   3.9.21: directory structure changes: moved ufile.c into the misc
   directory, so BeOS can share it. Moved various helper scripts into the
   misc directory, including a cmplog.pl that compares two test.exe profile
   logs.
<li>
   3.9.21: made the Linux PS2 mouse driver understand the middle button.
   Added a scaling factor to make it go at a more sensible speed in SVGA
   modes.
<li>
   3.9.20: started working on a driver for the Linux fbcon device. It works,
   but can't change video mode yet.
<li>
   3.9.20: Windows patch from Stefan adds joystick input, and the beginnings
   of a windowed mode driver.
<li>
   3.9.20: moved all filename lists (even the platform specific ones) into
   makefile.lst, to avoid any duplication and give us a nice centralised
   place that mentions every single source file we use.
<li>
   3.9.20: removed the install_lost_bitmap_callback() function, in favour of
   the more generic set_display_switch_mode(). Updated the Windows code to
   use these new routines.
<li>
   3.9.20: merged X patch from Michael Bukin (adds mouse support).
<li>
   3.9.20: Vincent Penquerc'h optimised the 256 to truecolor graphics
   blitting code to avoid repeated conversions of the palette table.
<li>
   3.9.20: James Hyman added quoting support to get_config_argv().
<li>
   3.9.20: Peter Cech optimised the alpha sprite blending routines. Shawn
   optimised them a bit more by expanding out specialised versions for
   common pixel formats.
<li>
   3.9.20: Richard Davies made some improvements to the PSX joypad driver.
<li>
   3.9.20: added a system driver parameter to allegro.cfg, and hooks to make
   the Unix version look for config data in /etc/ and ~/.
<li>
   3.9.20: moved the Posix findfirst() emulation into libc.c, removing it
   from the autoconf and BeOS specific builds.
<li>
   3.9.20: more BeOS patches from Jason Wilkins. The graphics stuff be
   working there now!
<li>
   3.9.20: improved the VBE/AF driver to know that vertical lines can be
   implemented as a rectfill. This enables hardware acceleration for
   patterned vertical lines, and with drivers that don't have hardware
   support for the VBE/AF line draw routine.
<li>
   3.9.20: George Foot did some major work on the Linux console version,
   getting it up and running in a fairly convincing way.
<li>
   3.9.20: the Windows sound driver lists are now dynamically generated
   based on the available devices, so you can select which ones to use.
<li>
   3.9.19: wrote the first part of an Allegro Hacker's Guide, which is my
   (probably futile :-) attempt to document at least a few of the more gory
   parts of the Allegro code.
<li>
   3.9.19: finally got around to documenting the Unicode functions.
<li>
   3.9.19: more BeOS patches from Jason Wilkins.
<li>
   3.9.19: Michael Bukin made some more patches to the X code (timers are
   implemented now), and added a complete (?) C implementation of all the
   drawing code. Non-Intel machines, here we come! If you define
   ALLEGRO_USE_C before building the djgpp library, you can actually test
   out a pure C version of test.exe, the demo game, etc.
<li>
   3.9.19: added a findtext.sh script, which scans the source code and
   creates a list of all the strings that are available for translation. It
   can also compare this list against an existing translation file, to see
   if any new messages need to be added.
<li>
   3.9.19: Stepan Roh updated the Czech keyboard mapping for Unicode
   support, added support for keyconf to use a non-standard font, and added
   the Latin Extended-A characters (U+0100 to U+017F) to the default font.
<li>
   3.9.19: Grzegorz Adam Hankiewicz updated the Spanish translation with
   UTF-8 format (ie. properly accented) strings. Converted the setup program
   font into Latin-1 ordering so that this will display correctly. Fixed bug
   with dat2s not correctly converting the resulting multiple-range font.
<li>
   3.9.19: Chris La Mantia made some cosmetic fixes to the d_slider_proc()
   GUI object.
<li>
   3.9.19: Richard Davies added support for N64 joypads.
<li>
   3.9.19: added keyboard_ucallback() (I missed this one when I first added
   the Unicode support).
<li>
   3.9.19: made some changes to setup.c so that it can easily be embedded
   into other programs (thanks to Grzegorz Adam Hankiewicz for the
   suggestion).
<li>
   3.9.18: added support for 32 bit RGBA images. You can now read TGA files
   with an alpha channel into the grabber, or you can import a normal image
   and then overlay alpha data from any greyscale bitmap. You can save these
   alpha channels as part of a datafile, call the makeacol(r, g, b, a)
   function, and most importantly, call set_alpha_blender() and then
   draw_trans_sprite() to display them. Check out exalpha.c. There is much
   room to optimise the 15, 16, and 24 bit versions of _blender_alpha*(), if
   anyone wants to have a go at this. I think it would be profitable to
   write specific versions for common pixel orderings, and only keep the
   current generic implementation around as an emergency fallback.
<li>
   3.9.18: more Unix patches from Michael Bukin. It builds flawlessly now,
   even if it doesn't do anything very interesting yet.
<li>
   3.9.18: Jason Wilkins contributed the beginnings of a BeOS port (not yet
   functional, but it does compile).
<li>
   3.9.18: Revin Guillen added a position_dialog() function.
<li>
   3.9.18: portability improvements: changed makefile to be a generated
   stub, which normally just includes makefile.all, but can be completely
   replaced when using autoconf, and moved the emulation for missing libc
   functions into the shared sources.
<li>
   3.9.18: numerous bugfixes.
<li>
   3.9.17: Burton Radons changed the truecolor pixel blending functions to
   use a single callback function rather than the previous table. This may
   break some old code, but should remain largely backward compatible, and
   the new way is much more flexible. He also added a more complete set of
   blender functions, including Photoshop modes like burn, difference,
   lumincance, etc.
<li>
   3.9.17: Richard Davies added support for PSX joypads.
<li>
   3.9.17: fixed bug in dat2s handling of truecolor images.
<li>
   3.9.17: Jason Wilkins improved the quaternion math routines, and added
   some documentation for them.
<li>
   3.9.17: Neil Townsend added callback parameters to the timer handlers.
<li>
   3.9.17: Gunter Ladwig added three-button mouse emulation, which can be
   enabled using the config file (it defaults to on if you have a two button
   mouse).
<li>
   3.9.16: applied some patches from Michael Bukin, which add the basics of
   a Unix build system. It doesn't actually work yet, though :-)
<li>
   3.9.16: merged new code from Stefan. Lots more cool things are working in
   the Windows version now, eg. hardware acceleration, triple buffering,
   sound...
<li>
   3.9.16: added an example of how to write a Windows screensaver using
   Allegro. If anyone knows how to get a proper name to show up in the
   Windows selection dialog, please let me know! (I've made the stringtable
   entry that MSDN says you need, but it doesn't work).
<li>
   3.9.16: Andy Goth added a d_text_list_proc() dialog object, that lets you
   alter the selection by typing the first few characters of a list entry.
<li>
   3.9.16: Ole Laursen updated the Danish message translation.
<li>
   3.9.16: Calvin French added a -w (always update) switch to dat.exe.
<li>
   3.9.16: Joerg Rueppel added more flexible wildcard matching for object
   names in dat.exe.
<li>
   3.9.16: added GFX_HW_SYS_TO_VRAM_BLIT and GFX_HW_SYS_TO_VRAM_BLIT_MASKED
   capabilities flags, and more flexible blitting functions in the vtable.
<li>
   3.9.16: added lock_voice() and unlock_voice() methods to the digital
   sound driver, for implementing audiostreams under Windows.
<li>
   3.9.16: _handle_timer_tick() now returns the desired gap until the next
   interrupt.
<li>
   3.9.15: Michael Rickmann added a Mingw32 port. This currently works the
   same way as the RSXNT version, using MSVC to build the DLL, but will
   become a full gcc port after the core Windows code stabilises a bit.
<li>
   3.9.15: Vincent Penquerc'h added a D_DIRTY flag for GUI objects, and I
   extended this with a new D_REDRAWME return code for the handlers.
<li>
   3.9.15: changed the syntax of the create_color_table() callback. This
   breaks the API, but is the only way to make it work reliably with
   different compiler calling conventions.
<li>
   3.9.15: added a sub bitmap creation hooks to the vtable structure (so the
   parent bitmap can be told when it is being cloned).
<li>
   3.9.15: "make install" is now a separate target, not run automatically.
   This means that you now have to run "make" and "make install" as two
   separate operations, or if you want all three versions of the library,
   "make all" and then "make installall".
<li>
   3.9.15: added an END_OF_MAIN() macro, which makes the WinMain() magic
   work correctly in any combination of C and C++ code.
<li>
   3.9.15: Olly Betts modified the djgpp makefile to support cross-compiling
   on a Linux machine.
<li>
   3.9.15: Andy Goth added a 256x256 tweaked VGA mode.
<li>
   3.9.15: major documentation update (from now on I'll be adding a version
   number to each changelog comment).
<li>
   Merged new code from Stefan. Windows version is getting much closer to
   completion, including mouse support and video bitmaps, although the mouse
   code isn't working quite right for me at the moment.
<li>
   Rewrote fix_filename_path() to avoid calling _fixpath(). The new version
   is much more portable, although things like reading the current directory
   across multiple drives need some tweaking to work with different
   compilers.
<li>
   Fixed oodles of things that were stopping the Watcom version from
   working. It now runs everything without any trouble at all, including
   such gems as exdodgy and the grabber shell edit! According to test.exe,
   gcc 2.8.1 is about 10% faster than Watcom 10.6 for most things, although
   for some reason textout() is about twice as fast in the Watcom version.
<li>
   Fixed a bunch of stuff to make the RSXNT version work. All the tests and
   examples now build with RSXNT, and work identically to the MSVC originals.
<li>
   Added quaternion math routines by Jason Wilkins.
<li>
   Added more flexible gfx_card config support by Andy Goth.
<li>
   Added a masked_stretch_blit() function (trivial change, the code could do
   it, but the API entry point was missing).
<li>
   Added Windows GDI routines by Marian Dvorsky.
<li>
   Added a DMA poll to the Soundscape driver, to make sure it can never get
   out of sync with the transfer.
<li>
   Merged various bits and pieces that have been sitting around my hard
   drive for ages (Swedish and Norwegian translations, various patches from
   Michael Bukin, new palette generation code by Michal Mertl, Soundscape
   driver fixes by Andreas Kluge).
<li>
   Grabber now knows about and can manipulate Unicode fonts.
<li>
   Now passing atexit() as a parameter to install_allegro(), to avoid
   problems with DLL shutdown.
<li>
   Made FLIC player set the dirty variables when clearing the bitmap at the
   start/loop point (this was sometimes causing the screen not to be cleared
   from previous contents).
<li>
   Fixed several bugs in the grabber.
<li>
   Changed the datafile utilities to link the datedit and plugin routines as
   a proper library. This will make life easier for third parties that want
   to use those routines (duplicating the plugin linkage isn't much fun).
<li>
   Replaced errno references with allegro_errno pointer, to avoid problems
   with multiple runtimes when linking as a DLL. The MSVC version of dat now
   works perfectly!
<li>
   Added a system_none driver for commandline utilities and other platform
   neutral situations.
<li>
   Made new demo intro animation. My first ever Max rendering!
<li>
   Merged Windows patches from Stefan. Whoah! This thing is cool. It works
   (sort of :-) on two platforms. Now I can die happy....
<li>
   The file selector now adjusts for platforms without any directory list
   (eg. Unix).
<li>
   Added a global default_palette (the normal IBM BIOS one), and made
   set_gfx_mode() select it.
<li>
   Modified DIGMID driver to avoid using 64 bit ints or floating point in
   the interrupt handler.
<li>
   Added ASSERT() and TRACE() debugging routines, and lots of asserts
   throughout the library code.
<li>
   The default truecolor pixel format before setting a video mode is now BGR
   rather than RGB. This should help to shake out bugs in BGR support, and
   catch any errors where people load graphics before setting a video mode.
<li>
   Fixed fmul() overflow detection bug.
<li>
   Rewrote gpro.c and sw.c to avoid using inline asm. The SW code is
   currently very ugly (literal translation of the asm routine), but I'm
   keen to improve it given some testing feedback. If you have a Gamepad Pro
   or Sidewinder, and were able to use it with the Allegro 3.11 driver, I
   would _really_ like to hear whether this current code works for you or
   not...
<li>
   Numerous changes to make the support programs more portable.
<li>
   Added a get_executable_name() function.
<li>
   The sound.cfg file is no longer supported. Use allegro.cfg instead.
<li>
   Added versions of the inline _putpixel() and _getpixel() for all color
   depths.
<li>
   The check_cpu() function is now called automatically by allegro_init().
<li>
   Added system bitmap objects, which exist in system memory but are
   accessed in a similar way to video memory surfaces (this can enable
   better hardware acceleration on some platforms).
<li>
   Added enable_triple_buffer(), timer_can_simulate_retrace(), and
   timer_is_using_retrace() functions. This enables programs to correctly
   handle the interrelationship between mode-X triple buffering, the retrace
   sync mode, and the current OS, without having to include any DOS specific
   code.
<li>
   GUI routines now call the input polling functions and acquire/release the
   screen as appropriate.
<li>
   Fixed a real show-stopping error that was causing VBE/AF crashes on some
   machines (calling driver functions with non-flat memory selector in %es).
<li>
   Added an allegro_message() function.
<li>
   Added dummy bank switch routines that can emulate linear access to a
   mode-X screen, albeit rather slowly. The only practical result from this
   is that polygon routines work in mode-X now, but it helps to make things
   more robust in general (if a routine doesn't know about mode-X, now it
   will just run more slowly than usual, rather than not working at all).
<li>
   The SB, Adlib, and standard joystick drivers now properly have a separate
   instance for each variant of the hardware, rather than a single driver
   pretending to exist under multiple different ID codes.
<li>
   Rewrote joystick polling to avoid inline asm.
<li>
   Converted translation files into UTF-8 format. These can now use any
   Unicode characters they like, so accented vowels etc. can safely be used.
<li>
   Keyboard scancodes have changed from the hardware format to an abstract,
   Allegro-specific encoding. This simplifies the code a great deal, and
   avoids hassles with two different keys generating the same scancode.
<li>
   Added generic find_allegro_resource() function, which removes a lot of
   duplicated code from config.c, digmid.c, and pckeys.c.
<li>
   Timer module now autoinstalls whenever someone tries to use it.
<li>
   Keyboard functions can now alter the repeat rate.
<li>
   Watcom port.
<li>
   Added a special GFX_SAFE driver ID.
<li>
   Now using VDS to detect win95 even when in stealth mode.
<li>
   Added fixver.sh for patching version numbers and dates when releasing a
   new version (requires bash, fileutils, shutils, etc, to run on DOS).
<li>
   Added zipup.sh for building a distribution zip and diffs, which
   automatically cleans up the tree ready for this (eg. pregenerating the
   dependency files for all supported compilers).
<li>
   Added input polling functions.
<li>
   Major code restucturing, added system drivers, new framework for input
   handling, timers, keyboard scancode conversion, file access, etc.
<li>
   Added full support for Unicode text, including string manipulation
   functions, a new font format, the textconv utility, a new GUI MSG_UCHAR,
   and a ureadkey() function.
<li>
   Added variable sized monochrome fonts, replacing the the old 8x8 fixed
   size format. As a result, the GFX_HW_TEXTOUT_FIXED capabilities flag has
   been renamed to GFX_HW_GLYPH.
<li>
   New system for accessing video memory, using bmp_select(), bmp_write*(),
   and bmp_unwrite_line(). This is equivalent to the djgpp farptr functions,
   but portable to different platforms.
<li>
   Drastic reorganisation of directory structure, makefile system, etc.
<li>
   Enhanced the makedoc utility to simplify adding links and email addresses
   to the docs.
<li>
   Added a bodge to make the VESA code work with broken S3 Trio64 drivers.
<li>
   Removed the 386DX vs. 386SX processor detection code (it was sometimes
   crashing).
</ul>


]]></text></section><section title="Changes from 3.11 to 3.12 (Aug 1999)"><text><![CDATA[<ul><li>
   Fixed a few incompatibilities with gcc 2.95. This release is otherwise
   identical to 3.11.
</ul>


]]></text></section><section title="Changes from 3.1 to 3.11 (Feb 1999)"><text><![CDATA[<ul><li>
   Cleaned up a few places where memory wasn't getting freed during the
   system shutdown. A cosmetic detail since the OS will free it for us, but
   it is nice to get these things right.
<li>
   Alessandro Monopoli added an Italian translation of the system messages.
<li>
   Henrik Stokseth added code to distinguish between win95 and win98.
<li>
   Creative Labs have been removed from the THANKS file, because of their
   refusal to release any specs on the SB Live soundcard.
<li>
   Changed the name of the library. After years of thinking that Allegro was
   a word with no particular meaning, I realised that it is in fact a
   recursive acronym for "Allegro Low Level Game Routines".
<li>
   Established a new mailing list for use by the people currently working on
   Allegro. Please send code contributions to this list rather than directly
   to me (Shawn Hargreaves), because this will allow Allegro development to
   continue even if I'm not around or am busy with something else at the
   moment.
<li>
   Andreas Kluge wrote a driver for Ensoniq Soundscape cards.
<li>
   More localisation: Swedish message translation by Sven Sandberg, Anton
   Ragnarsson, and Erik Sandberg, Finnish message translation by Antti
   Haapala, and Russian message translation and keyboard mapping by Dmitriy
   Kazimirow.
<li>
   The midi_out() function now correctly updates the pan/volume/bend
   controller status.
<li>
   Kester Maddock added a Wingman Warrior joystick driver.
<li>
   Fixed some problems with the Sidewinder, Gamepad Pro, and SNES joypad
   drivers.
<li>
   Changed the SB16 driver to use signed 16 bit output mode, rather than the
   previous unsigned format. Hopefully this will improve compatibility with
   crappy clone hardware.
<li>
   Added a new WARNMODE environment switch to the makefile. Allegro
   developers should all set this to get strict warnings, but it will be
   left off by default so that the distributed version will be more
   forgiving about different compiler/libc versions.
<li>
   Fixed problem with reading the top and left positions on digital joystick
   devices.
<li>
   Fixed (I think, still waiting accurate confirmation on this one :-)
   problem with timers running too fast on some motherboards.
<li>
   Fixed stupid bug where get_align_matrix() wasn't bothering to zero the
   translation vector.
<li>
   Fixed stupid bug where rotated sprites were coming out upside down in
   mode-X and hi/truecolor modes.
<li>
   Fixed bug where dat utility was truncating long filenames to 8.3 format.
<li>
   Renamed the ChangeLog file to CHANGES, to avoid problems on 8.3 systems.
<li>
   Various other minor bugfixes.
</ul>


]]></text></section><section title="Changes from 3.0 to 3.1 (Jan 1999)"><text><![CDATA[<ul><li>
   Changes between the 3.1 beta and final releases: assorted bugfixes,
   Antoine Mathys added a Swiss keyboard mapping, Thomas Wolf added a German
   translation of the system messages.
<li>
   Changes between the 3.1 alpha and beta releases: assorted bugfixes, FLIC
   routines can now read from datafiles, included rotation optimisations by
   Ivan Baldo.
<li>
   Peter Cech added support for hot-swapping between a custom keyboard
   layout and the standard US mapping.
<li>
   Neil Townsend improved the accuracy of the timer routines.
<li>
   Added exlights.c example program, showing one way to do colored lighting
   effects in a hicolor mode (and also because it makes the total number of
   examples a nice round number :-)
<li>
   Added an afinfo test program, which does the same thing as vesainfo but
   for VBE/AF drivers.
<li>
   Michael Bukin made a lot more portability patches and some bug fixes,
   including some improvements to the FLIC player and a much more rational
   filename handling system.
<li>
   Removed the chipset-specific SVGA hardware drivers from the main library
   distribution. Instead, these will now be available both as an optional
   addon package, and reformatted as part of the FreeBE/AF project.
<li>
   Added FreeBE/AF extensions support to the Allegro VBE/AF driver (farptr
   access to video memory, and the libc and pmode exports needed for future
   compatibility with the SciTech Nucleus drivers).
<li>
   Fixed a bug with the patterned and translucent vline() function in 15 bit
   color depths.
<li>
   Fixed a NULL pointer dereference bug in the config routines.
<li>
   Fixed an order of processing bug that was causing data to be lost when
   calling set_config_file() with the same filename as the current config.
<li>
   Stepan Roh added a Czech translation of the system messages.
<li>
   Ole Laursen added a Danish translation of the system messages.
<li>
   Grzegorz Ludorowski made a new demo game intro animation.
<li>
   Calin Andrian added 3d polygon timing routines to test.exe.
<li>
   Peter Cech added grabber support for the 8x8 BIOS font format.
<li>
   Stepan Roh added a Czech keyboard mapping.
<li>
   Renamed the Spanish language translation file from SP to ES.
<li>
   Calin Andrian added a complete set of truecolor polygon rendering
   routines, with support for MMX and 3DNow! optimisations and a new masked
   lit drawing mode, along with a new polygon clipping function. One minor
   change is that POLYTYPE_FLAT mode is now implemented by calling hline(),
   so it will respond to the current drawing_mode() settings.
<li>
   Changed the graphics/sound/joystick driver ID numbers from a zero based
   list to a descriptive 4-character string, to make them more readable and
   flexible. Added config functions to read/write data in this format. The
   sound config data is backwardly compatible, but you will need to manually
   update any graphics or joystick driver numbers that are stored in your
   config files.
<li>
   Michael Bukin contributed a _lot_ of patches to improve the portability
   and robustness of pretty much the entire library. The only externally
   visible change is that the macros used for declaring hardware driver
   lists have been redesigned to use a more portable syntax, although the
   old syntax is still available as a compatibility macro.
<li>
   Burton Radons did some more optimisation of the truecolor pixel blending
   functions.
<li>
   Martijn Versteegh added a hook mechanism for extending the config file
   system, which can be used to provide extended system status information
   or customisation routines for addon packages.
<li>
   Redesigned the grabber and dat utilities to support source-code "plugin"
   modules, which can be used to extend the system with additional object
   types, import/export routines, and menu commands.
<li>
   Ivan Baldo added a dithering option to the 15/16 bit color conversion
   routines.
<li>
   Kerry High added a SNES joypad driver.
<li>
   Added a font override to the d_text_proc() and d_ctext_proc() GUI
   objects, using the dp2 field to specify a custom font.
<li>
   Michael Tanczos fixed some bugs in the FLIC player.
<li>
   Cloud Wu optimised the truecolor pixel blending functions.
<li>
   Paul Pinault added a French translation of the system error messages.
<li>
   Grzegorz Adam Hankiewicz added a Spanish translation of the system error
   messages, and added a new (but undocumented :-) command line option to
   the demo game.
<li>
   Fixed clicks in the interpolated sample mixing.
<li>
   Fixed a bug with position_mouse() not updating the mouse_pos variable.
<li>
   Fixed a bug in mode-X horizontal scrolling while the timer retrace
   simulator is active.
<li>
   Added a language.dat file, which can be used to provide translated
   versions of system strings (eg. error messages), in a similar way to the
   existing keyboard.dat. If you want to use this mechanism from your own
   code, replace all your constant strings with calls to
   get_config_text("string"). This allows them to be translated by including
   a line of the form "string=foreignstring" in the relevant section of
   language.dat.
<li>
   Added an ASCII name field to the keyboard mapping files, in order to make
   the setup program a bit more friendly.
<li>
   Increased the maximum number of sound channels from 32 to 64.
<li>
   Modified the DIGMID patch loader to support 16 bit samples, rather than
   just reducing everything to 8 bit.
<li>
   Added an interpolation option to the sample mixer (quality=2).
<li>
   Salvador Eduardo Tropea added support for proper 16 bit sample mixing
   (quality=1).
<li>
   Lee Killough added a lower level hook routine to the keyboard handler.
<li>
   Removed floating point code from the DIGMID driver, to avoid potential
   FPU stack overflows.
<li>
   Jim Flynn removed floating point calculations from the AWE32 MIDI driver
   (these could sometimes cause stack overflows).
<li>
   Salvador Eduardo Tropea improved the datafile system to avoid linking of
   unused code.
<li>
   Romano Signorelli contributed a Bresenham arc plotting function.
<li>
   Thomas Wolf corrected some errors in the German keyboard mapping file.
<li>
   Grzegorz Adam Hankiewicz improved the excolmap example program.
<li>
   Sven Sandberg optimised the fixed point trig routines.
<li>
   Fixed some silly crash bugs in the joystick code.
<li>
   Added a "compress" target to the makefile, based on a suggestion
   by Grzegorz Adam Hankiewicz.
<li>
   Added dummy bitmap acquire/release functions to allegro.h, for
   compatibility with the Windows version.
<li>
   Added a cross-reference facility to the Info format documentation.
<li>
   Martin Fuller fixed an obscure bug in the reading of compressed .bmp
   files.
<li>
   The emergency exit signal handler now correctly restores the previous
   handler, rather than resetting to the default action.
<li>
   Sven Sandberg optimised the create_light_table() function.
<li>
   George Foot fixed a bug when the get_mouse_mickeys() routine was called
   with both parameters pointing to the same value.
<li>
   Changed the licensing terms from "swapware" to "giftware". See the
   Allegro website for an explanation of the reasons for this change.
<li>
   Added yet more overloaded operators (this time for long and double types)
   to the fix class.
<li>
   Marius Fodor added support for the Sidewinder and Gravis GamePad Pro.
   Many apologies for my taking so long to merge in this code!
<li>
   Stefan Schimanski optimised the reverse blitting routine (for overlapping
   images).
<li>
   Added a shift+tab reverse focus movement key to the GUI routines.
<li>
   Grzegorz Adam Hankiewicz added a new example showing how to create and
   use a custom color mapping table.
<li>
   Totally revamped the joystick system (better API and new driver
   structure).
<li>
   Modified the fix class to work properly with gcc 2.8.0.
<li>
   Added a help.txt "how to get tech support" file.
<li>
   The midi_pos variable is now negated, rather than cleared to -1, at the
   end of a MIDI file. This can be used for measuring the length of a file.
<li>
   Added a rendering hook to the font structure, for use by text addon
   packages.
<li>
   Improved the VBE/AF text output routine.
<li>
   Corrected an error in the way the VBE/AF driver interprets hardware
   cursor colors.
<li>
   Pedro Cardoso contributed a tweaked 80x80 VGA mode.
<li>
   The VBE/AF driver now supports dumb framebuffer drivers as well as
   accelerated ones.
<li>
   Added more accelerator support to the VBE/AF driver (hardware cursors,
   lines, vertical lines, triangles, fixed width text output, and
   opaque/masked blitting from system memory to the screen).
<li>
   Added a scare_mouse() function, based on ideas by Martijn Versteegh.
<li>
   The grabber now stores the "grab from grid" dialog state in allegro.cfg.
<li>
   Sven Sandberg fixed a problem with save_bitmap() widths being rounded
   upwards.
<li>
   Made the _timer_installed flag globally visible.
<li>
   Ove Kaaven added linear framebuffer support to the native mach64 driver.
<li>
   Erik Sandberg optimised the 8 bit draw_sprite() and draw_trans_sprite()
   functions.
<li>
   Michal Mertl fixed a memory leak in the generate_optimized_palette()
   function.
<li>
   Added an ALLEGRO_DATE version define to allegro.h.
<li>
   Michael Bukin optimised the line drawing routine and fixed problem with
   the inline asm constraints for fadd()/fsub().
<li>
   Fixed potential problems caused by a lag between the mouse state
   variables changing and the pointer being redrawn.
<li>
   Michal Mertl optimised the clipping code for lines, rectangles, and
   circles.
<li>
   Maiolino Carmelo contributed an Italian keyboard mapping.
<li>
   Fixed lockup problems caused by the keyboard LED functions on some
   platforms/hardware.
<li>
   Added new create_video_bitmap() and show_video_bitmap() functions.
<li>
   Added a profile option to the test program.
<li>
   The keyboard handler now correctly updates the BIOS state for the right
   control and alt keys when it shuts down.
<li>
   Fixed a problem that was preventing the DIGMID driver from reading patch
   sets stored in executable appended datafiles.
<li>
   Changed the default sample priority from 255 to 128.
<li>
   Fixed some problems with virtual screen sizes in the VBE/AF driver.
<li>
   Added two new example programs.
<li>
   The VBE/AF driver now has full support for hardware accelerated drawing.
<li>
   Added VBE 3.0 support, including new triple buffering routines.
<li>
   Wrote a routine to select the sound input source (microphone, line input
   or CD audio).
<li>
   Added proper support for stereo samples. This requires an extra parameter
   to the play_audio_stream() function, so you will need to change any
   programs that use this. I'm very sorry for breaking your old code!
<li>
   Fixed bugs with the SB16 autodetection and 16 bit sample recording.
<li>
   Added input support to the raw SB MIDI interface driver.
<li>
   Wrote a new test program to demonstrate the audio input features.
<li>
   Ove Kaaven added support for MIDI and audio (sampled sound) input.
<li>
   The pack_fopen() function now understands nested datafiles as directory
   structures, using filenames like "graphics.dat#level1/sprites/zdurgle".
<li>
   Charles Mac Donald showed me how to set a 160x120 VGA mode, and more
   reliable 400x* mode-X resolutions.
<li>
   Guilherme Silveira and Theuzifan Sumachingun both independently modified
   the file selector to only list valid drive letters.
<li>
   Carsten Sorensen added a driver for the ESS AudioDrive soundcard.
<li>
   Przemek Podsiadly added hicolor versions of the 3d polygon routines.
<li>
   Ove Kaaven added truecolor support to the native ATI mach64 driver.
<li>
   Patrick Hogan added a draw_gouraud_sprite() function.
<li>
   Ben Chauveau added a driver for Tseng ET6000 cards.
<li>
   Marco Campinoti added truecolor support to the native Tseng ET4000 driver.
<li>
   Marco Marmulla added 16 bit support to the load_voc() routine.
<li>
   Added Danish, Swedish, and Norwegian keyboard mappings.
<li>
   Added GUI hook functions for scaling or offsetting the mouse position.
<li>
   Fixed bug which was causing a lockup when calling set_leds(-1).
<li>
   Michael Bevin optimised the create_trans_table() function.
<li>
   It is now possible to display a mouse pointer without the mouse handler
   needing to be installed.
<li>
   Added a create_sample() function.
<li>
   Made the _blender_map pixel blending functions and the _mouse_installed,
   _keyboard_installed, and _sound_installed flags globally visible.
<li>
   Added an 8-button joystick mode.
<li>
   Chris La Mantia fixed a minor visual problem with the d_icon_proc().
<li>
   Added a Rich Text Format (.rtf) version of the documentation.
<li>
   Added postfix increment and decrement operators to the C++ fix class, and
   the unary negation operator is now const-correct.
</ul>


]]></text></section><section title="Changes from 3.0 beta to release (Dec 1997)"><text><![CDATA[<ul><li>
   The pat2dat utility can now import instruments from AWE32 SoundFont files.
<li>
   Optimised the DIGMID patch loader and fixed a couple of bugs.
<li>
   Ove Kaaven fixed the ATI mach64 driver.
<li>
   The config file can now mention several possible video drivers, using
   lines in the form gfx_driver=x, gfx_driver2=x, etc.
<li>
   Improved the native SVGA driver helper functions, making it easier to add
   truecolor support to the register level drivers.
<li>
   Double-clicking on a font object in the grabber now allows you to view
   the extended characters as well as normal ASCII.
<li>
   Markus Oberhumer corrected a potential problem with the Video-7
   initialisation code.
<li>
   Markus Oberhumer, Bitland, and Sormuras all sent me mapping tables for
   the German keyboard layout. Coordination of effort: who needs it? :-)
<li>
   Mathieu Lafon improved the French keyboard mapping.
<li>
   Fixed some bugs in the MIDI voice allocation system.
<li>
   Added a -k (keep names) option to the dat utility.
<li>
   The setup program now uses the ALLEGRO environment variable to locate the
   keyboard.dat file.
<li>
   Fixed a problem with &lt; and &gt; characters in the HTML documentation.
</ul>


]]></text></section><section title="Changes from 2.2 to 3.0 beta (Nov 1997)"><text><![CDATA[<ul><li>
   Merged in George's improved instrument parameters for the AWE32 driver.
<li>
   The pat2dat utility can now reduce sample data from 16 to 8 bits (saves
   space, and the DIGMID driver only uses 8 bits in any case).
<li>
   Added yet another version of the mouse handler, this time in an attempt
   to make it work more reliably under Windows NT.
<li>
   Frodo Baggins added a mapping table for Portuguese keyboards.
<li>
   Added an external tool "shell" function to the grabber.
<li>
   Added a "box grab" function to the grabber, which uses a color #255
   bounding box to determine the extent of the sprite to grab.
<li>
   Santeri Saarimaa added a Finnish keyboard mapping.
<li>
   Finished writing the pat2dat utility, and the DIGMID driver is working a
   lot better now.
<li>
   Mathieu Lafon added support for the Pause and PrtScr keys, and changed
   the key[] array to a bitfield indicating whether either or both of the
   normal and extended versions of the key are pressed. This remains
   compatible with the "if (key[KEY_*])" syntax, but also allows you to
   distinguish between, for example, the Enter key on the numeric pad and
   the one next to the right shift key.
<li>
   Fixed a bug in the handling of config variables that don't belong to any
   section.
<li>
   The makefile now tries to detect and warn people about some of the more
   common installation errors.
<li>
   The HTML version of the documentation now uses a short .htm file
   extension if it is built on a system with LFN disabled.
<li>
   Keyboard mapping files now only bother saving the entries that differ
   from the default US mapping. This makes the maps a great deal smaller!
<li>
   Changed the default font and keyboard mapping tables from DOS codepage
   437 to the standard ISO charset (first part of Unicode). If you have made
   a keyboard config using the old codepage it will need to be updated, but
   don't worry, I have a script that can do this very easily.
<li>
   Fixed a bug in the detection of font formats (fixed or proportional) when
   grabbing from a bitmap font.
<li>
   Added an editable loop point to the MIDI player (thanks to George for
   sorting out how to do this...)
<li>
   Rewrote the mouse handler to track the position itself, using only the
   mickey counters from the int 0x33 driver. Hopefully this will fix the
   problem with buggy Logitech drivers...
<li>
   Added a mouse_pos variable containing both the X and Y values in one 32
   bit location, to allow a single instruction read during tight polling
   loops.
<li>
   The grabber now supports multiple selection, and has a new "ungrab"
   command that copies from a bitmap object into the scratch buffer (you can
   use this to generate palettes from truecolor images, or to re-grab a
   smaller area from the image).
<li>
   Added multiple selection abilities to the GUI listbox object.
<li>
   Theuzifan improved the cpu detection for Cyrix chips.
<li>
   Mathieu Lafon added a French keyboard mapping.
<li>
   Richard Mitton wrote an example program demonstrating how to fake a 12
   bit truecolor display on an 8 bit card.
<li>
   Michal Mertl added a routine for generating optimised palettes for a
   specific truecolor image.
<li>
   Optimised the getr/g/b() functions. Converting between different color
   depths should be much faster now...
<li>
   Scott Harrison added code to detect OpenDOS, and use the i_love_bill mode
   if their version of EMM386 is in use.
<li>
   Added some new example programs.
<li>
   The makedoc utility now converts between the DOS and Windows extended
   character sets when producing HTML output files.
<li>
   Ettore Perazzoli made a spectacular optimisation to the linear -&gt;
   mode-X blitting function.
<li>
   Added a grid option to the dat utility, to specify which region of a
   bitmap you want to grab.
<li>
   Fixed a bug in blitting truecolor bitmaps onto mode-X destinations.
<li>
   Fixed a bug that was preventing the Adlib volume from being changed when
   only MIDI sound drivers were installed.
<li>
   The grabber can now be run in video modes other than 640x480 (it doesn't
   look very nice in lower resolutions, though :-)
<li>
   Added a new fake scancode for the extended / key (the one on the numeric
   keypad) so that the two keys can be distinguished from each other.
<li>
   Joaquin Hierro Diaz made a mapping table for Spanish keyboards.
<li>
   The setup utility can now be used to select a keyboard layout and to
   calibrate the joystick, as well as for the sound hardware.
<li>
   Moved some of the documentation to different locations, so hopefully
   people will now be less likely to miss the faq.txt, and to bring it
   closer in line with the standard GNU distribution format.
<li>
   Better keyboard configuration system. There is now a proper utility for
   setting up the mapping tables, the tables can be read from external
   files, and it properly supports the alt-gr and accent escape keys.
<li>
   Menu items can now be disabled, have check marks next to them, and
   support right aligned text eg. for displaying keyboard shortcuts, there
   is a new "void *dp" field in the menu structure, and the click callback
   routines can now use the global pointer "active_menu" to determine which
   option they were called by, if a single routine is shared by several menu
   items.
<li>
   Peter Palotas added an input callback to the keyboard routines, and event
   flags to the mouse callback.
<li>
   Added a -pal option to the dat utility.
<li>
   Grzegorz Ludorowski made some new graphics for the demo game.
<li>
   Moved some code to new files and added a bunch of macros so you can
   remove unused graphics and sound drivers at link time.
<li>
   Fabian Nunez added support for the Logitech Wingman Extreme joystick.
<li>
   Chris La Mantia contributed a d_slider_proc() dialog object.
<li>
   Sean Gugler added a routine for changing the keyboard LED state.
<li>
   George Foot added pause and seek functions to the MIDI player.
<li>
   Added the ability to append datafiles (in fact any files at all) onto the
   end of your program executable.
<li>
   Merged in the AWE32 driver. Long live George!
<li>
   Can now read RLE compressed TGA files.
<li>
   Added a mouse movement callback function (useful for detecting double
   click events).
<li>
   Stefan Eilert added support for dual joysticks.
<li>
   Seymour Shlien contributed a routine for drawing justified text.
<li>
   Krzysztof Krzyzaniak contributed a loader for .VOC sample files.
<li>
   Added a rotate_scaled_sprite() function.
<li>
   Now supports the Dvorak keyboard layout.
<li>
   Salvador Eduardo Tropea added a 320x100 VGA mode.
<li>
   Implemented translucent and lit sprite and RLE sprite drawing functions
   for the truecolor modes.
<li>
   Updated the sound setup utility.
<li>
   The dat utility can now output makefile dependencies for automatically
   rebuilding the file when any of the source data changes.
<li>
   Fixed some problems with the RGB &lt;-&gt; HSV conversion functions.
<li>
   Truecolor image loading and grabber support.
<li>
   Phil Frisbie provided some code to detect the CPU type.
<li>
   Michal Mertl added 24 bit graphics modes. Hurrah!
<li>
   Added functions for playing streams of digital audio data.
<li>
   Chris La Mantia contributed a bitmap icon GUI object.
<li>
   Doug Eleveld added a text box GUI object, plus an improved help system
   for the grabber.
<li>
   Added support for UK and AZERTY keyboard layouts. More can easily be
   added if you send me the appropriate scancode -&gt; ASCII mapping tables...
<li>
   Added get_align_matrix(), qtranslate_matrix(), and qscale_matrix()
   functions.
<li>
   Added a draw_character() function for using sprites as monochrome pixel
   masks.
<li>
   It is now safe to pass the same matrix as both input and output to the
   matrix_mul() function.
<li>
   Paul Bartrum contributed some ellipse drawing functions.
<li>
   Added some callbacks to the MIDI driver, allowing you to hook your own
   code into MIDI notes or marker events.
<li>
   Added a function to measure mouse movement in terms of mickeys
   (difference since the last call) as well as in absolute screen
   coordinates.
<li>
   VolkerOth made the d_edit_proc objects able to scroll, if the string is
   larger than the available space.
<li>
   Added the ability to distinguish between the left and right Control and
   Alt keys.
<li>
   Fabian Nunez added support for the extra keys on a Microsoft keyboard.
<li>
   Added void *dp2 and void *dp3 fields to the dialog structure. This
   ought not to break any existing code, but will let you store a lot more
   data when creating custom objects.
<li>
   The packfile functions can now directly open and read from datafile
   member objects, using fake filenames in the form "filename.dat#obj_name".
   This means that all the Allegro file access routines (eg. load_pcx() and
   set_config_file()) can now read from datafile objects as well as separate
   files.
<li>
   Added miditest and digitest programs to allow more rigorous testing of
   the sound routines and patch sets, and a vesainfo program to check which
   video modes are available on any given card.
<li>
   Jan Hubicka wrote a faster version of create_rgb_table().
<li>
   The grabber now scales the bitmap preview if the image is too large to
   fit onto the screen.
<li>
   Jorrit Rouwe provided a new and much cooler set of FM instrument
   definitions for the Adlib MIDI driver.
<li>
   Added a function to load .IBK patch sets for use by the Adlib driver.
<li>
   Added a wrapper allegro/ directory around the contents of the zip file,
   so it can now be safely unzipped into the main djgpp directory.
<li>
   Richard Mitton added support for 6-button joysticks.
<li>
   Truecolor (15, 16, and 32 bit) graphics modes.
<li>
   Vastly improved sound routines (more flexible API, now supports up to 32
   simultaneous voices on the SB, sample-based MIDI playback driver, can
   reverse samples, volume/pan/pitch sweep effects, MIDI commands can be
   output on the fly as well as played from MIDI files, and lots of other
   goodies).
<li>
   It is now possible to update the status of GUI dialogs incrementally from
   your own control loops, with an update_dialog() function, rather than
   completely transferring control to do_dialog().
<li>
   Compressed files (including grabber datafiles) can now be encypted with a
   password.
<li>
   Added a masked_blit() function, that skips zero pixels.
<li>
   Added code to detect being run under Linux DOSEMU, and use the less
   demanding version of the timer code if this is the case.
<li>
   Added a standardised configuration mechanism. The format for saved
   joystick calibration information has changed, so existing joystick files
   are no longer valid.
<li>
   Added a textprintf() routine, which uses a printf() style format string.
<li>
   Added a TexInfo version of the documentation (thanks for the help,
   Francois!)
<li>
   Jonas Petersen added a save_bmp() function, and support for the OS/2 BMP
   format.
</ul>


]]></text></section><section title="Changes from 2.11 to 2.2 (Feb 1997)"><text><![CDATA[<ul><li>
   TBD/FeR added tweaked 320x600 and 360x600 resolutions to the mode-X
   driver.
<li>
   Matthew Bowie added support for 4-button joysticks.
<li>
   Dave Thomson added RGB &lt;-&gt; HSV conversion functions.
<li>
   Added a 'freeze_mouse_flag' variable, that can be used to lock the
   pointer to a specific position.
<li>
   Added a 'key_led_flag' variable, that can be used to prevent the keyboard
   LED's updating in response to the capslock, numlock, and scroll-lock keys.
<li>
   The midi player now resets midi_pos to -1 when the music finishes playing.
<li>
   Adrian Oboroc wrote an LBM loader.
<li>
   Fonts can now contain characters above ASCII 127.
<li>
   Chris Wigman made a better intro animation for the demo game.
<li>
   Added translucency, color blending, and lighting routines (based on code
   by Owen Embury and ideas by Nathan Albury).
<li>
   Added 3d math and matrix manipulation functions.
<li>
   Added texture mapped and gouraud shaded polygon drawers.
<li>
   Tim Gunn contributed code for reading and writing TGA files.
<li>
   Fixed clamping problems with rotating non-circular sprites.
<li>
   Added scrollbars to the GUI listbox object.
<li>
   Seymour Shlien wrote a bezier spline drawing function.
<li>
   Added fixed point fadd() and fsub() functions, which check for overflow.
<li>
   Added pack_fseek() and chunk manipulation functions to the file routines.
<li>
   Improved datafile structure and grabber program.
<li>
   Wrote a utility to convert grabber datafiles into linkable asm code.
<li>
   Salvador Eduardo Tropea improved the keyboard routines (better handling
   of extended scancodes, keyboard LED support, capslock and numlock, and
   alt+numpad input).
<li>
   Fixed the packfile functions and file selector to work with long
   filenames under win95.
<li>
   Seymour Shlien contributed a BMP reader.
<li>
   Added a hook function to the keyboard code, allowing you to use the GUI
   code without installing the keyboard handler.
<li>
   Fixed a lockup caused by trying to access non-existent floppy drives.
<li>
   Francois Charton wrote a driver for Paradise graphics cards.
<li>
   Chris La Mantia contributed a radio button GUI dialog object and added a
   D_DISABLED object flag.
<li>
   Markus F.X.J. Oberhumer fixed the Video-7 scrolling function.
<li>
   Converted the docs into HTML format.
<li>
   Added code to detect Windows NT.
<li>
   Mark Habersack added support for newer Trident chipsets.
<li>
   Did some more work on the VBE/AF driver (it now works, but still doesn't
   support accelerated hardware features).
<li>
   Fixed bugs in the WAV sample reader and FLIC player.
<li>
   Added special 'windows friendly' mode to the timer code. You can now even
   run demo.exe under Windows 3.1!
<li>
   Reorganised directory structure, to allow for a Linux version. The output
   liballeg.a is now found in lib/djgpp.
<li>
   Added support for 8x16 BIOS format fonts.
<li>
   Fixed a problem with overflow when rotating large sprites.
<li>
   Fixed a problem with restoring the text mode screen height after running
   Allegro programs.
</ul>


]]></text></section><section title="Changes from 2.1 to 2.11 (Nov 1996)"><text><![CDATA[<ul><li>
   Fixed bug in bank.S.
<li>
   install_mouse() now sets the range to (0,0,SCREEN_W,SCREEN_H).
<li>
   install_sound() does not automatically set the volume to maximum.
<li>
   Added ++ and -- operators to class fix.
<li>
   Makefile now copies liballeg.a to lib, and allegro.h to include.
<li>
   Made a few changes to work under LFN=y (if you use unzip or winzip
   instead of pkunzip).
<li>
   Added manifest.
<li>
   Clarified installation instructions.
</ul>


]]></text></section><section title="Changes from 2.0 to 2.1 (June 1996)"><text><![CDATA[<ul><li>
   Mode-X support (thanks to Jonathan Tarbox and Dominique Biesmans for
   suggesting and then helping to implement this).
<li>
   Compiled sprites.
<li>
   Jonathan Tarbox contributed an FLI/FLC player.
<li>
   Added patterned drawing modes.
<li>
   Added a vertical retrace interrupt simulator.
<li>
   polygon() can now handle concave and self-intersecting shapes. I also
   changed the parameters a bit. Sorry if this breaks your old code, but
   it's more efficient the new way...
<li>
   Added stretch_sprite().
<li>
   Wrote a floodfill() routine.
<li>
   More flexible palette fade routines.
<li>
   Added set_volume() to the sound code.
<li>
   David Calvin wrote a sound setup utility.
<li>
   Improved the GUI. Added popup/dropdown menus, joystick input, three
   button alert boxes, better handling of arrow key focus movement, a new
   keyboard shortcut object (d_keyboard_proc()), and '&amp;' markers in strings
   to display keyboard shortcuts. The GUI can also now be used with fonts
   other than the standard 8x8 default, by altering the global 'font'
   pointer.
<li>
   Fabian Nunez added support for the CH Flightstick Pro joystick (looks
   cool: I want one :-) and 3-button mice.
<li>
   The keyboard handler now responds to the state of the ctrl and alt keys,
   and there is a new simulate_keypress() function.
<li>
   Mark Wodrich added sub-bitmaps, which share their memory with a parent
   bitmap but can be positioned anywhere within it, and have their own
   clipping rectangles.
<li>
   Mark also modified the mouse driver to double-buffer the pointer (so it
   doesn't flicker any more), and added a set_mouse_sprite_focus() function.
<li>
   Added set_mouse_range() and set_mouse_speed() functions.
<li>
   Thanks (again) to Mark Wodrich, the grabber can now import GRX .FNT files.
<li>
   The grabber can now make backups when saving datafiles, and it only
   writes the datafile headers if their contents have changed, to prevent
   unnecessary recompilation.
<li>
   Added a text_height() function.
<li>
   The fixed point inverse sin and inverse cos functions now use lookup
   tables, which makes them a lot faster.
<li>
   Reorganised the directory structure, added some example programs, and
   improved the documentation.
</ul>


]]></text></section><section title="Changes from 2.0 beta to release (March 1996)"><text><![CDATA[<ul><li>
   Marcel de Kogel fixed some problems with the MPU-401 driver. It now
   actually works :-)
<li>
   Marcel also provided some better drum sounds for the Adlib driver.
<li>
   Inlined the fmul() and fdiv() functions.
<li>
   Much faster fsqrt(), taken from Arne Steinarson's fix-float library.
<li>
   Added inline bmp_write_line(), bmp_read_line(), and _putpixel() functions.
<li>
   The keyboard routines now support the emergency abort sequence
   ctrl+alt+del, and there are signal handlers to make sure Allegro will
   shut down cleanly if your program crashes.
<li>
   Wrote new irq wrappers that can deal with reentrant interrupts.
<li>
   Added joystick routines (based on code provided by Jonathan Tarbox and
   Marcel de Kogel).
<li>
   Moved some functions to different files and juggled things about so the
   linker can do a better job. If you don't use the sound stuff, or don't
   use any graphics functions, now they won't be linked into your executable.
<li>
   Marcel de Kogel manged to locate my (embarrassingly stupid :-) mistake
   which was preventing the VESA 2.0 linear framebuffer driver from working.
<li>
   Various other performance enhancements and bug fixes.
</ul>


]]></text></section><section title="Changes from 1.x to 2.0 beta (Jan/Feb 1996)"><text><![CDATA[<ul><li>
   Dropped all the Borland code. A couple of months ago I ran out of disk
   space, and it was with great satisfaction the I executed the command
   'deltree /y c:\bc4'. It was a horrible compiler, and I'm glad it's dead.
<li>
   Added SVGA support. As a result it no longer makes sense for
   allegro_init() to put the system into mode 13h, so you will be in text
   mode until you call set_gfx_mode().
<li>
   Added sound code (background MIDI music and sample mixing).
<li>
   Added support for proportional fonts (of any size) as well as the old 8x8
   fixed size ones.
<li>
   XOR drawing mode.
<li>
   There is no longer such a thing as a SPRITE structure. The sprite drawing
   code now draws bitmaps onto other bitmaps, which is a much more flexible
   way of doing things. The datafile reader will convert all your old
   sprites to bitmaps as it loads them in, so the only practical difference
   this is likely to make is that the sprite drawing routines can't draw
   opaque sprites any more (but you can use a blit instead).
<li>
   show() and get_sprite() no longer exist: use blit() instead.
<li>
   Added flipped and rotated sprite draw routines.
<li>
   Added bitmap scaling.
<li>
   Added RLE sprites.
<li>
   drawsprite() has been renamed to draw_sprite().
<li>
   textmode() has been renamed to text_mode(), to avoid conflicts with
   definitions in conio.h.
<li>
   All the file access functions have been renamed from the stdio syntax to
   pack_fopen(), pack_getc(), etc, so they can now be mixed with stdio code.
<li>
   Added pack_fgets() and pack_fputs().
<li>
   The port_callback pointer no longer exists.
<li>
   Removed polyline() (who ever used it?), and added a polygon(), which
   draws a filled convex polygon with an arbitrary number of vertices.
<li>
   Added do_line() and do_circle() functions, which call a user-supplied
   function for each pixel that needs to be drawn.
<li>
   Added a default keyboard interface to the GUI routines, allowing the
   selection of objects with the arrow keys and &lt;enter&gt;.
<li>
   Added several new GUI messages and flags. In particular there are now
   messages for tracking mouse cursor movement, an idle message, a special
   return value for the MSG_CHAR message which allows an object to override
   the default keyboard handling, and a flag which hides the object.
<li>
   There are new GUI routines to centre a dialog on the screen and to alter
   the colors used by the standard alert and file selector dialogs.
<li>
   The file selector now takes a third parameter specifying which file
   extensions to display.
<li>
   The timer routines now have better than millisecond accuracy, and it is
   possible to alter the speed of a user timer callback in realtime (by
   reinstalling it with a different speed value).
<li>
   Removed the _RGB struct and paltorgb() functions. RGB's are now stored
   directly in the hardware format, with each value in the range 0-63.
<li>
   Added functions to get and set single palette entries as well as entire
   palettes.
<li>
   Added DPMI memory locking code.
<li>
   Wrote a C++ 'fix' class which overloads a lot of operators, providing an
   easy way to use the fixed point routines.
<li>
   There are probably lots of other things that I have forgotten about.
</ul>

]]></text></section></section><section title="Contributors: The Hall of Fame"><section title="Contributors"><text><![CDATA[
   Acho A. Tang (acho AT telus DOT net).<br>
   Added a Sidewinder Precision Pro joystick driver to the DOS port.

   Adrian Oboroc (doba AT corefx DOT com).<br>
   Wrote the LBM loader.

   aj.<br>
   Reported many problems, suggested a lot of improvements to the
   documentation, added AMD64/IA64/SSE3 detection code, added DirectX 8 and 9
   detection to the Windows port, added MSVC7 specific options to the makefile,
   cleaned up a C99-ism in makedoc, fixed a beep when alt+character was pressed
   in windowed mode in Windows and made TARGET_ARCH_EXCL also work with MSVC.

   Alex Demko (alex_demko AT mbnet.mb DOT ca).<br>
   Suggested lots of improvements to the datafile system and provided code
   for handling the 8x16 BIOS font format.

   Alessandro Monopoli (almonopo AT tin DOT it).<br>
   Added the Italian translation of the system messages.

   Andreas Kluge (bitland AT aol DOT com).<br>
   Wrote the Ensoniq Soundscape driver and fixed division bugs in the fix
   class.

   Andrei Ellman (ae-a-alleg2 AT wacko.wackonet DOT net).<br>
   Contributed the polygon_z_normal() function, suggested some additions to
   the docs, updated the Cygwin section in docs/build/mingw32.txt, got
   Allegro for MSVC to build with Cygwin, improved the performance of the
   hsv_to_rgb() function, corrected a rounding issue in hsv_to_rgb(),
   improved the exrgbhsv example and the Windows screensaver, fixed problems
   in the MSVC makefile when using Cygwin and did plenty of other things too.

   Andrew Cottrell (andrewc AT dbworld.net DOT au).<br>
   Changed the grabber to use a more robust (locale-independent) date format.

   Andrew Ellem (krand AT ican DOT net).<br>
   Wrote the original version of the digital audio streaming code.

   Andrew Geers (andy AT geerswj.clara DOT net).<br>
   Added the -ppassword and -nosound options to the grabber, scrolling
   support in the image viewer and the flipped rotated sprite routines.

   Andy Goth (unununium AT openverse DOT com).<br>
   Made the gfx_card config variable more flexible, added the 256x256 tweaked
   VGA mode, wrote the d_text_list_proc() dialog object and fixed the
   constructor support in dat2s on Unix.

   Angelo Mottola (a.mottola AT libero DOT it).<br>
   Added the BeOS joystick, MIDI and windowed graphics drivers, added mouse
   wheel, display switching and close button support for BeOS, wrote the
   DGA2 driver and close button support for X, contributed the bfixicon
   utility, added triple buffering support, a BWindow-based windowed driver
   and a fullscreen overlay driver to the BeOS port and reorganized its gfx
   subsystem. And, oh, contributed the QNX and MacOS X ports too.

   Annie Testes (annie AT kezako DOT net).<br>
   Added font_height, render_char, char_length hooks to FONT_VTABLE, fixed
   several glitches in the unicode support, added a pack_fdopen() function,
   caught a misordering in the X system shutdown, fixed some device name
   strings, lifted several hardcoded length limitations in the configuration
   routines, added a mouse driver based on the event interface (EVDEV) to the
   Linux port, fixed numerous bugs and did plenty of other things too.

   Antoine Mathys (mmathys AT bluewin DOT ch).<br>
   Added the Swiss keyboard mapping.

   Anton Ragnarsson (anton.ragnarsson AT swipnet DOT se).<br>
   Contributed the Swedish keyboard mapping table.

   Antti Haapala (ztane AT lyseo.edu.ouka DOT fi).<br>
   Fixed the setup program to display the right frequency list for each
   type of soundcard and contributed the Finnish translation of the system
   messages.

   Antti Koskipaa (antti.koskipaa AT nic DOT fi).<br>
   Wrote the DOS driver for WSS (Windows Sound System) cards.

   Arne Steinarson (arst AT ludd.luth DOT se).<br>
   The fixed point square root routine came from his fix-float library.

   Arthur Huillet (email unknown).<br>
   Fixed a typo in the docs.

   Attila Szilagyi (attilabox AT hotmail DOT com).<br>
   Fixed SVGAlib horizontal scrolling.

   Ben Chauveau (bendomc AT worldnet DOT fr).<br>
   Added support for Tseng ET6000 cards (now available as part of the
   FreeBE/AF project).

   Ben Darnell (bdarnell AT vnet DOT net).<br>
   Put together the 2.11 release of Allegro while I was away from the net
   and wrote the original version of the Allegro FAQ.

   Ben Davis (entheh AT users.sf DOT net).<br>
   Added set_volume_per_voice(), made silent voices continue playing,
   fixed other minor bugs in the mixer, fixed a bug in create_rgb_table(),
   adapted polygon functions to handle two coincident vertices, added the
   set_window_close_button() and set_window_close_hook() framework, added
   support for timers with parameters under Windows, corrected several
   compilation warnings and documented the behaviour of pack_feof().

   Benjamin Joel Stover (stovertech AT intellisys DOT net).<br>
   Wrote the initial version of the fullscreen X-Windows graphics driver.

   Benny Colyn (email unknown).<br>
   Added a Dutch translation.

   Bertrand Coconnier (bcoconni AT club-internet DOT fr).<br>
   Modified 3D polygones routines for subpixel and subtexel accuracy, made
   speed enhancements in these routines, fixed blending in C version of
   atex_lit scanline functions, added scanline subdivisions in C scanline
   functions and Z-buffer polygon functions and merged in Calin Andrian's
   P3D library.

   Bobby Ferris (baf AT bafsoft DOT com).<br>
   Added the SciTE API output format to makedoc and temporarily hosted
   Allegro's SVN repository while SourceForge's SVN was in beta.

   Burton Radons (loth AT gec DOT net).<br>
   Optimised the truecolor pixel blending function, converted the blenders
   to the new single-handler format, and added the range of
   Photoshop-compatible blender functions.

   Calin Andrian (calin AT ibd.dbio DOT ro).<br>
   Wrote the truecolor, MMX, 3DNow!, masked lit mode, translucent and
   Z-buffered polygon rendering routines, the clip3d_f() function and also
   the scanline sorting functions for 3D scene rendering, and his P3D
   addon library was merged in.

   Calvin French (frenchc AT home DOT com).<br>
   Added the -w (always update) switch to dat.exe.

   Carsten Schmidt (email unknown).<br>
   Wrote the the initial version of the Linux GGI driver.

   Carsten Sorensen (csorensen AT ea DOT com).<br>
   Wrote the the ESS AudioDrive soundcard driver.

   Catatonic Porpoise (<graue AT oceanbase DOT org>).<br>
   Added OpenBSD detection, fixed an issue with executable rights not set
   on the memory for the i386 stretcher on UNIX systems, and fixed the
   documentation for stretch_sprite.

   Cloud Wu (cloudwu AT 263 DOT net).<br>
   Optimised the truecolor pixel blending functions.

   Charles Bilyue (Esaelon AT aol DOT com).<br>
   Optimized the i386 blitters and suggested to not force yielding timeslice
   with non-blocking menus.

   Charles Wardlaw (kattkieru AT yahoo DOT com).<br>
   Fixed warnings with gcc 4 on MacOS X and helped resolve a problem with
   setAppleMenu under Tiger.

   Chris Graham (chris_graham AT postmark DOT net).<br>
   Suggested to add a new flag for Windows NTFS compressed files.

   Chris Jones (cj AT jibblers.plus DOT com).<br>
   Fixed a bug with 16-bit samples loading, worked around a problem with DOS
   file attributes under Win2k, let the MIDI player pass controller events to
   the raw player by default, made the MIDI player handle the 'All Sound Off'
   controller message, added support for the bitfield compressed BMP image
   format, fixed the behavior of numeric keys when NumLock is on, and fixed
   loading of certain .wav files.

   Chris La Mantia (celamantia AT home DOT com).<br>
   Wrote the d_radio_proc(), d_icon_proc(), and d_slider_proc() dialog
   objects, added the D_DISABLED flag, improved the GUI handling of
   different font heights, and added the right aligned text functions.

   Chris Robinson (crobin_99 AT yahoo DOT com).<br>
   Wrote the fixed point clip3d() function, improved the performance of the
   DIGMID driver, implemented the digmid_set_pan function, rewrote part of
   the Allegro mixer, made the Allegro mixer the default one in Windows,
   improved the threaded UNIX timer code, helped improve responsiveness under
   X11, tweaked tests/play.c, added drawing primitives and video bitmap locking
   to the X11 port and did plenty of other things too.

   Christer Sandberg (christer.sandberg AT mdh DOT se).<br>
   Made dat2c work better with ISO C90 compilers, made dat2c correctly detect
   the native line ending, fixed a problem with the include guard generated
   by dat2c, fixed a bug in the 24-bit graphics code of fixup_datafile(),
   fixed a problem with Electric Fence.

   Christian Schueler (cschueler AT gmx DOT de).<br>
   Changed the optimisation settings for better performance.

   Daniel Nilsson (daniel7 AT algonet DOT se).<br>
   Enlarged the starfield in exstars, and fixed an incorrect range in
   exlights.

   Daniel Schlyder (daniel AT bitblaze DOT com).<br>
   Fixed problems with get_executable_name() under Windows, another one with
   set_window_title() under BeOS, potentially unsafe constructs in the
   Windows code, the installall makefile target under Windows, added
   set_allegro_resource_path(), fixed make uninstall with mingw make,
   added ALLEGRO_LIB_BUILD flag for gcc variants not using configure,
   fixed a bunch of warnings in MinGW and did plenty of other things too.

   Daniel Verkamp (i_am_drv AT users.sourceforge DOT net).<br>
   Added a MIDI input driver to the Windows port anda dded support for .rmi
   MIDI files to the MIDI loader.

   Dark Nation (email unknown).<br>
   Restored support for old-style encrypted packfiles, which had been removed
   in 4.1.18.

   David A. Capello (dacap AT users.sourceforge DOT net).<br>
   Made dotted_rect() avoid bank switches, fixed a problem with lost GUI
   mouse clicks, made d_menu_proc() steal/return focus when activated then
   deactivated, fixed a problem with submenus, fixed a bug with FLI frames
   containing odd-sized chunks, made makedoc write sub-section headings
   for .txt output, made override_config_file also be used for writing to
   the config file and did plenty of other things too.

   David Kuhling (dkuelhin AT hell1og.be.schule DOT de).<br>
   Optimised the fsqrt() routine, and added fhypot().

   Dave Physics.<br>
   Some documentation fixes.

   Dave Thomson (gameskitchen AT geocities DOT com).<br>
   Added the RGB &lt;-&gt; HSV conversion routines, the autocrop function to
   the grabber and wrote the 3d starfield example program (exstars.exe).

   David Calvin (calvid AT rpi DOT edu).<br>
   Wrote the original version of the sound setup utility.

   David Cullen (dcullen7 AT bellsouth DOT net).<br>
   Added multiple bullets and extra lives to the demo game.

   Deepak T (coolbool AT gmx DOT net).<br>
   Fixed clipping in three C sprite drawing routines.

   Dennis Busch (email unknown).<br>
   Fixed a bug in d_clear_proc, fixed a Unicode bug in the mode selector,
   and fixed the short description of add_clip_rect.

   Dmitriy Kazimirow (mariann AT mail DOT ru).<br>
   Provided the Russian keyboard mapping and message translation files.

   Dominique Biesmans (Dominique.Biesmans AT ping DOT be).<br>
   Wrote the mode-X version of draw_sprite() and the mode-X &lt;-&gt; linear
   blitting functions.

   Doug Eleveld (D.J.Eleveld AT anest.azg DOT nl).<br>
   Wrote the d_textbox_proc() dialog object and the new grabber help system.

   Dustin Dettmer (dustin AT mize DOT org).<br>
   Spotted a typo in save_bitmap.

   Eduard Bloch (edi AT gmx DOT de).<br>
   Fixed a freeze caused by the ESD detection code, fixed a bad behaviour
   of the config routines and suggested better ways to find the path to
   the executable on Unix.

   Edward Boone (Lucien.Boone AT ping DOT be).<br>
   Provided scancode mapping tables for the AZERTY keyboard layout.

   Elias Pschernig (elias AT users.sf DOT net).<br>
   Added a COLORCONV_KEEP_TRANS mode, contributed the wfixicon utility,
   contributed several enhancements to the grabber, fixed menu dimensions in
   the GUI engine, fixed the get_camera_matrix*() functions, added support
   for the CHM and Devhelp documentation formats, fixed a bug in midi_seek(),
   made load_datafile_object() load the object properties, made the GUI code
   scare the mouse more intelligently and did plenty of other things too.

   Eric Botcazou (ebotcazou AT libertysurf DOT fr).<br>
   Made the DGA driver work better in 8bpp and 32bpp modes, improved the
   DirectX windowed driver and Windows graphics subsystem, partially
   revamped the Unicode API and added uszprintf(), added file_select_ex(),
   the unified al_find*() interface, an Unicode example, a new filetest,
   rewrote the fixdll script, revamped the Borland C++ build process, fixed
   lots of bugs and did plenty of other things too.

   Erik Sandberg (eriksandberg AT geocities DOT com).<br>
   Optimised the 8 bit draw_sprite() and draw_trans_sprite() functions and
   helped with the Swedish message translation.

   Ettore Perazzoli (ettore AT comm2000 DOT it).<br>
   Optimised the linear -&gt; mode-X blitting function.

   Evert Glebbeek (eglebbk AT dds DOT nl).<br>
   Put set_gfx_mode on a diet, added a config entry for specifying the card
   to be used for GFX_AUTODETECT_WINDOWED, added a '-fullscreen' switch to
   the grabber, cleaned up the grabber/plugins code, added various commands
   to the grabber, added the detection of SunOS/Solaris, added configure
   options for x86 processor optimisations on Unix systems, added the support
   for relative filenames and did plenty of other things too.

   EvilTypeGuy (eviltypeguy AT icculus DOT org).<br>
   Cleaned up and fixed the RPM spec file for RedHat 9.

   Fabian Nunez (faybs AT iafrica DOT com).<br>
   Added support for the CH Flightstick Pro and Logitech Wingman Extreme
   joysticks, 3-button mice, and the extended keys on a Microsoft keyboard.

   Fabrizio Gennari (faybs AT iafrica DOT com).<br>
   Contributed the DB9 and TurboGraFXoystick drivers.

   Francisco Pires (fmlvp AT hotmail DOT com).<br>
   Added an FPS counter and an option to disable vsync to the excamera
   example.

   Francois Charton (deef AT pobox.oleane DOT com).<br>
   Wrote the Paradise graphics driver (now available as part of the
   FreeBE/AF project), improved the VGA palette setting code and helped
   with the TexInfo conversion of the docs.

   Frodo Baggins (l41273 AT alfa.ist.utl DOT pt).<br>
   Made the Portuguese keyboard mapping.

   Garret Thomson (g AT sirsonic DOT com).<br>
   Wrote the music used in the demo game.

   George Foot (gfoot AT users.sourceforge DOT net).<br>
   Did a great deal of work on the Linux console version, wrote the AWE32
   driver, added the MIDI pause/seek functions, provided the basis of the
   SoundFont reader used in the pat2dat utility, fixed the C fceil()
   function, added the ffloor() function and added non-FM support to the
   OSS MIDI driver.

   Gorka Olaizola (olsago AT jet DOT es).<br>
   Added the Redhat RPM .spec file.

   Grady Martin (shadygrady AT budweiser DOT com).<br>
   Fixed a bug in the handling of %n in the printf style text functions, added
   a move command to the grabber and standardised some of the grabber dialog
   boxes.

   Greg Hackmann (hacker AT ididitmyway DOT com).<br>
   Contributed the Borland C++ Builder port.

   Greg Lee (greg AT ling.lll.hawaii DOT edu).<br>
   Pointed out that Linux joystick driver should read all events.

   Grzegorz Adam Hankiewicz (gradha AT users.sourceforge DOT net).<br>
   Wrote several of the example programs, suggested the "compress" makefile
   target, translated the docs and system error messages into Spanish,
   suggested the idea of embedding the setup utility into other programs,
   wrote some documentation and corrected the .texi generation to improve
   texi2dvi output, improved the makedoc utility and contributed a new doc
   format, added reload_config_texts() and did plenty of other things too.

   Grzegorz Godlewski (email unknown).<br>
   Contributed a Polish localization patch, and added support for lower and
   upper altgr tables.

   Grzegorz Ludorowski (pajonk AT ajax.umcs.lublin DOT pl).<br>
   Wrote several of the example programs, and made the intro animation and
   graphics for the demo game.

   Guilherme Silveira (thedarkage AT geocities DOT com).<br>
   Modified the file selector to only list valid drive letters.

   Gunter Ladwig (gladwig AT iname DOT com).<br>
   Wrote the OS/2 detection routines and added the three-button mouse
   emulation.

   Hans de Goede.<be>
   Fixed a problem with dynamically generated stretcher code not being
   properly marked as executable on Linux, fixed a busy wait in the X11 vsync
   simulation, added a fullscreen driver for X11 which does not need XVidMode
   extension, fixed a problem where switching to fullscreen mode under X11,
   made digmid work with absolute pathes in patches.cfg, and fixed a problem
   with the Alsa driver on big endian systems.

   Harshavardhana Reddy N (nharsha AT gmail DOT com).<br>
   Added a Kannada greeting to exunicod.

   Haruhiko Okumura (email unknown).<br>
   Wrote the original version of the LZSS compression code.
   12-2-404 Green Heights, 580 Nagasawa, Yokosuka 239, JP.

   Hein Zelle (hein AT icce.rug DOT nl).<br>
   Revamped the cross-compilation section of docs/build/mingw32.txt,
   clarified a requirement when cross-compiling from Linux, reworked the
   paragraph on the location of shared libraries under Unix in the docs and
   added a FAQ entry on the same subject.

   Henrik Schmidt (hbs AT ks.informatik.uni-kiel DOT de).<br>
   Found a workaround for the switching problem under Windows, made gcc pass
   '-h' instead of '-soname' to the linker and replaced '-L' by '-h' in shell
   comparisons so as not to break on Solaris.

   Henrik Stokseth (hensto AT online DOT no).<br>
   Contributed a native Mingw32 port which can also be built with a
   cross-compiler and the Cygwin compiler, much improved OS detection, added
   get_gfx_mode_list() and methods for querying the VGA, Mode-X, Xtended,
   VESA, VBE/AF and DirectX drivers for a list of possible GFX modes,
   rewrote the mode-selector to use get_gfx_mode_list(), reworked the build
   system many times and did plenty of other things too.

   Hrvoje Ban (spoofer255 AT gmail DOT com).<br>
   Pointed out a bug in the mode selector, fixed several double ;'s, fixed
   ASSERT() in Windows, helped write a documentation section about common
   pitfalls, and added the create_datafile_index function.

   Igor Gnip (gnipi AT mindnever DOT org).<br>
   Removed the requirements for fileutils on DOS/Windows platforms and added
   the detection of MSYS to the MingW32 port.

   Isaac Cruz (icruzbal AT teleline DOT es).<br>
   Fixed a bug with accelerated drawing onto sub bitmaps of DirectDraw
   surfaces, added the GFX_DIRECTX_WIN driver, fixed a Windows sub bitmap
   locking bug, added Windows desktop_color_depth and yield_timeslice
   routines, and made extensive modifications to other aspects of the
   Windows code.

   Ivan Baldo (lubaldo AT adinet.com DOT uy).<br>
   Wrote the 15/16 bit dithering code and optimised the sprite rotation
   routines.

   Jaime Moreno (daviangel AT hotmail DOT com).<br>
   Helped track down a problem with dependency generation in MacOS X.

   Jakub Wasilewski (krajzega AT meditech DOT pl).<br>
   Fixed a bug when loading greyscale TGA images.

   James Arthur (jaa AT arfa.clara DOT net).<br>
   Documented the Photoshop-style truecolor blender routines.

   James Hyman (frooge AT mindless DOT com).<br>
   Added support for quoted strings in the get_config_argv() function and
   the dithering code for paletted images.

   James Lohr (email unknown).<br>
   Fixed a problem with mouse acceleration in fullscreen modes under Windows.

   James Ponder (james AT squish DOT net).<br>
   Suggested to remove the DJGPP makefile from the Unix tar archive and
   clarified a requirement when cross-compiling from Linux.

   Jan Bruun Andersen (jba-dk AT users.sourceforge DOT net).<br>
   Fixed a compilation problem with Cygwin.

   Jan Hubicka (hubicka AT horac.ta.jcu DOT cz).<br>
   Vastly improved the speed of the create_rgb_table() function.

   Jason Wilkins (fenix AT io DOT com).<br>
   Wrote the quaternion math routines and contributed the BeOS port.

   Javier Gonzalez (xaviergonz AT hotmail DOT com).<br>
   Corrected mouse movement speed, made allegro_message() use title from
   set_window_title(), added close button hook support and improved
   switching in Windows, fixed bad clearing of subbitmaps, made bug
   reports and suggestions for improvement, contributed bidirectional
   looping support, backward playing support and bugfixes for the
   DirectSound driver and did plenty of other things too.

   Jeff Mitchell (email unknown).<br>
   Fixed the location of grabber.txt in the spec file.

   Jeremiah Blanchard (squirminworm AT yahoo DOT com).<br>
   Contributed modifications in order for Allegro to build on Darwin/MacOS X
   and updated the build instructions for this new port afterwards.

   Jim Flynn (jflynn AT pacbell DOT net).<br>
   Removed floating point calculations from the AWE32 MIDI driver.

   Jim Grainger (Grainger_Jim/world_europe_samuro_WYN-CTV AT samsung.co DOT kr).<br>
   Spotted a broken link in the docs and updated it.

   Jiri Gabriel (email unknown).<br>
   fixed loading of multiple ranges in a single bitmap with txt fonts and helped
   fix an off-by-one mistake for the last glyph in extract_font_range.

   Joaquin Hierro Diaz (Joaquin.Hierro.Diaz AT fresno.csic DOT es).<br>
   Made the mapping table for Spanish keyboards.

   Joerg Rueppel (sharky-x AT gmx DOT net).<br>
   Added more flexible wildcard matching for object names in dat.exe and
   the find_datafile_object() function.

   Johan Peitz (d98peitz AT dtek.chalmers DOT se).<br>
   Fixed and enhanced the Win32 joystick driver, and contributed the 'Alex
   the Allegator' icon.

   Johan Venter (leonjventer AT bigpond DOT com).<br>
   Fixed some problems with the RSXNT and Mingw32 makefiles.

   John Holden (johnh AT psych.usyd.edu DOT au).<br>
   Fixed a bug in load_wav().

   John Utz (Johnut01 AT noa.nintendo DOT com).<br>
   Corrected a wrong assumption about the VRAM layout in the Linux
   framebuffer console driver.

   Jon Rafkind (workmin AT ccs.neu DOT edu).<br>
   Added more ASSERTs to the code, implemented the Cohen-Sutherland clipping
   algorithm for the line() function and supplied an m4 macro for allegro.

   Jonas Petersen (joXonoX AT berlin.snafu DOT de).<br>
   Added the save_bmp() function and support for the OS/2 BMP format.

   Jonathan Tarbox (jonattar AT rocketmail DOT com).<br>
   Wrote the mode-X setup code, the FLI/FLC player and contributed parts of
   the joystick handler.

   Jorrit Rouwe (j.rouwe AT cpedu.rug DOT nl).<br>
   Provided a new and much cooler set of FM instrument definitions for the
   Adlib MIDI driver.

   Jose Antonio Luque (skylord AT LatinMail DOT com).<br>
   Improved the Windows joystick driver, and optimised the 16-bit blit() and
   masked_blit() functions.

   Joshua Heyer (joshua_heyer AT yahoo DOT com).<br>
   Wrote the original version of the OSS sound driver.

   J. P. Morris (email unknown).<br>
   Fixed a bug rest_callback under unix.

   Julien Cugnière (jcugniere AT free DOT fr).<br>
   Improved the support for non-blocking menus, fixed a bug related to the
   retrieval of the inital volume when no primary buffer was present under
   Windows, fixed the crash on exit with the aRts sound driver, added an
   X11 message box for allegro_message under X11 and fixed a crash in the GUI
   when a dialog was opened while a menu was still open.

   Kalle Toivonen (allegro AT korpiq.iki DOT fi).<br>
   Fixed a bug in _parallelogram_map().

   Keith Gerdes (kwg AT softhome DOT net).<br>
   Fixed the DirectDraw overlay mode driver.

   Kerry High (khigh01 AT umr DOT edu).<br>
   Contributed the SNES joypad driver.

   Kester Maddock (dmaddock AT xtra.co DOT nz).<br>
   Wrote the Wingman Warrior joystick driver.

   Knut Pape (Knut_Pape AT t-online DOT de).<br>
   Improved the Mingw32 readme file.

   Kronoman X (kronoman_x AT hotmail DOT com).<br>
   Added a FAQ entry about the conflict between Allegro headers and the C++
   'using' directive.

   Krzysztof Krzyzaniak (eloy AT arrakis.cs.put.poznan DOT pl).<br>
   Wrote the load_voc() function.

   Laurence Withers (lwithers AT users.sf DOT net).<br>
   Added destroy hook to font structure, worked on const-correctness
   throughout the library, implemented the new FONT structure, made
   some modules avoid linking dependencies, contributed the dat2c
   utility, added two fixed point ratios for converting to and from
   radians, added a '-windowed' switch to the grabber, added a new text
   API and did plenty of other things too.

   Lee Killough (email unknown).<br>
   Added the low-level hook routine to the keyboard handler and fixed a
   couple of bugs.

   Lennart Rolland (chimeni AT hotmail DOT com).<br>
   Contributed the Norwegian message translation.

   Lennart Steinke (lst AT steinke DOT net).<br>
   Added the exconfig example, contributed keyboard layout detection code
   for Windows and suggested the true colour font rendering.

   Lisa Parratt (lisa AT thecommune.org DOT uk).<br>
   Contributed the SGI Audio Library sound driver, spotted a BSDism that
   IRIX doesn't like at all, added IRIX detection and improved the
   performances of the SGI audio driver

   Lorenzo Petrone (_lano_ AT libero DOT it).<br>
   Contributed the gfxinfo utility, added two FAQ entries, added a
   xwin_set_window_name() function to the X11 port, added support for
   switch callbacks under X11 and refactored the display switching code.

   Lucas Vignoli Reis (lucasvr AT bestway.com DOT br).<br>
   Added the Portuguese (Brazil) message translation and keyboard mapping.

   Magnus Henoch (mange AT freemail DOT hu).<br>
   Made the gfx mode selector keep the current selection as much as possible
   and fixed a problem when compiling without 8bpp support.

   Maiolino Carmelo (cmaiolino AT ctonline DOT it).<br>
   Added the Italian keyboard mapping table.

   Manni Heumann (manfred.heumann AT uni-bielefeld DOT de).<br>
   Fixed some problems with the German keyboard mapping table.

   Marcel de Kogel (m.dekogel AT student.utwente DOT nl).<br>
   Not content with fixing my broken MPU-401 driver, Marcel went on to
   provide a set of vastly improved drum sounds for the OPL driver, to help
   me sort out some problems with reentrant interrupts, to supply the half
   of the joystick code that didn't come from Jonathan and to locate a
   stupid mistake in my VESA linear framebuffer code.

   Marcel Smit (marcel.athlon AT hccnet DOT nl).<br>
   Corrected a bug that caused errors when drawing persp. correct polygons
   facing the screen, corrected an error in the packfile format write-up and
   made the show_video_bitmap() method of the Windows windowed driver wait
   for a vsync.

   Márcio Fialho (maaf1980 AT yahoo.com DOT br).<br>
   Fixed several issues with the DJGPP port and the VBE/AF driver and fixed
   some bugs related to author credits.

   Marco Campinoti (marco AT etruscan.li DOT it).<br>
   Added 15 and 24 bit support to the native Tseng ET4000 driver (now
   available as part of the FreeBE/AF project).

   Marco Marmulla (Viper005 AT usa DOT net).<br>
   Added 16 bit support to the load_voc() routine.

   Marian Dvorsky (marian AT step DOT sk).<br>
   Wrote the Windows GDI interface routines.

   Marius Fodor (iceman AT teleport DOT com).<br>
   Added support for the Sidewinder and Gravis GamePad Pro.

   Marek Habersack (grendel AT ananke.amu.edu DOT pl).<br>
   Did the original Linux console port (brave man: this was the first ever
   work done on porting Allegro away from DOS), which is the basis of the
   code we are still using today and added support for the more recent
   Trident chipsets (now available as part of the FreeBE/AF project).

   Mark Wodrich (mwodric AT eleceng.uct.ac DOT za).<br>
   The brain behind sub-bitmaps, flicker-free mouse pointers, and the
   ability to import GRX .FNT files into the grabber.

   Markus F.X.J. Oberhumer (markus.oberhumer AT jk.uni-linz.ac DOT at).<br>
   Fixed the Video-7 scrolling function (now available as part of the
   FreeBE/AF project), optimised the color mapping routines, and made many
   useful suggestions like the addition of a vid_phys_base field to the
   graphics driver structure.

   Martijn Van Lersel (amarillion AT yahoo DOT com).<br>
   Fixed an overflow in create_light_table().

   Martijn Versteegh (m.versteegh AT hccnet DOT nl).<br>
   Added the config hook extension mechanism.

   Mathieu Lafon (mlafon AT ifhamy.insa-lyon DOT fr).<br>
   Added the French keyboard mapping, support for the Pause/PrtScr keys and
   changed the key[] table to a normal/extended bitfield.

   Matt Witherspoon (spoon AT vt DOT edu).<br>
   Fixed a bug in the scroll() method of the Linux SVGAlib driver.

   Matthew Bowie (catcat AT nmt DOT edu).<br>
   Added support for 4-button joysticks.

   Matthew Leverton (matthew AT allegro DOT cc).<br>
   Fixed a bug with mouse mickeys in windowed mode under Windows, fixed a
   problem with al_find*() and NTFS partitions under Windows, added missing
   header files to be installed by the Windows binary distribution, made the
   DOS/Windows makefiles use 'copy /B' instead of 'copy', added the detection
   of left-hand mouse configuration under Windows, fixed a bug with
   pack_fgets(), made an online diff generator and did lots of other things too.

   Maxime Carey (werfu AT users.sourceforge DOT net).<br>
   Contributed the Canada (French) keyboard mapping file.

   Michael Bevin (michael.bevin AT stonebow.otago.ac DOT nz).<br>
   Optimised the create_trans_table() function.

   Michael Bukin (M.A.Bukin AT inp.nsk DOT su).<br>
   Ported the whole thing to Unix/X, and contributed a _lot_ of patches to
   improve the portability, robustness, and performance of pretty much the
   entire library.

   Michael Faerber.<br>
   Pointed out a mistake in the documentation for text_height().

   Michael Rickmann (mrickma AT gwdg DOT de).<br>
   Ported the Windows code to Mingw32.

   Michael Tanczos (webmaster AT logic-gate DOT com).<br>
   Fixed some bugs in the FLIC player.

   Michal Mertl (mime AT eunet DOT cz).<br>
   Wrote all the 24 bit graphics code, the optimised palette generation
   function and a fair amount of the other truecolor stuff too (bitmap
   scaling, image loading, etc).

   Michal Molhanec (molhanec AT seznam DOT cz).<br>
   Simplified the build instructions for Dev-C++, replaced all occurences
   of MingW32 by MinGW in the docs, added an faq section about the giftware
   license, fixed problems with long filenames when building for MSVC,
   corrected a problem with the Watcom port, added MSVC7 options to the
   makefile, fixed a linker problem with the MSVC port, fixed some const
   warnings in the grabber code and did plenty of other things too.

   Michail Pishchagin (mblsha AT users.sourceforge DOT net).<br>
   Contributed the ustrnicmp() function.

   Milan Mimica (milan.mimica1 AT pu.htnet DOT hr).<br>
   Fixed bugs in the keyconf utility, the alsa 9 volume settings and
   extract_font_range(), helped fix an off-by-one mistake for the last glyph
   in extract_font_range, fixed a bug where a font would be converted to 8
   bit, a bug with is_color_font, made the Linux console driver more robust,
   fixed some spin loops in the test program, and added the get_volume and
   get_hardware_volume functions, and did plenty of other things too.

   Miran Amon (miran.amon AT gmail DOT com).<br>
   Fixed an undocumented arbitrary limit in get_config_argv()

   Nathan Albury, aka Rubicant (gt4558a AT prism.gatech DOT edu).<br>
   Improved the fire routine in examples/exflame.c (my original version
   didn't really look very much like flames :-) and gave me some extremely
   useful ideas about how to implement translucency.

   Nathan Smith (white_door AT dread DOT nl).<br>
   Implemented the recursive handling of directories for the dat utility.

   Neil Townsend (neil AT robots.ox.ac DOT uk).<br>
   Improved the accuracy of the timer routines and added the callback
   parameters.

   Neil Roy (neilroy AT cogeco DOT ca).<br>
   Suggested many improvements to the documentation.

   Neil Walker.<br>
   Implemented a hardware accelerated stretch_blit() for the Windows DX port,
   and fixed a bug with draw_sprite and sub-bitmaps.

   Nicholas Davies (master_goodbytes AT hotmail DOT com).<br>
   Made the fix class not trigger warnings with gcc -Weffc++.

   Nick Kochakian (nickk AT worldnet.att DOT net).<br>
   Wrote the DirectSound input driver.

   Ole Laursen (98zOLaw AT aalborghus DOT dk).<br>
   Contributed the Danish keyboard mapping table and system message
   translation, and made the Unicode utolower() and utoupper() functions
   understand the entire 16 bit character set.

   Olivier Blin (oblin AT mandriva DOT com).<br>
   Fixed compilation problems for the ModeX driver.

   Olly Betts (olly AT muscat.co DOT uk).<br>
   Modified the djgpp makefile to support cross-compiling on a Linux machine.

   Omar Cornut (cornut AT noos DOT fr).<br>
   Spotted an asm locking bug under Windows, bumped the maximum number of
   buttons per joystick to 32, fixed the Windows joystick driver to handle a
   weird peculiarity of the DirectInput API and improved the handling of
   KEY_COLON2 on Japanese keyboards.

   Oscar Giner (O_giner AT hotmail DOT com).<br>
   Added the Catalan translation, corrected the Spanish translation, fixed a
   bug with binary data exporting in the grabber and fixed a conflict between
   the magic main and the MFC.

   Owen Embury (owen AT gememail.demon.co DOT uk).<br>
   Wrote part of the translucency/lighting code.

   Owen Rudge (alleg AT orudge.freeuk DOT com).<br>
   Contributed a DLL version resource script and the mkdata.bat script.

   Ove Kaaven (ovek AT arcticnet DOT no).<br>
   Fixed a bug in the ATI mach64 driver (now available as part of the
   FreeBE/AF project), added native truecolor and linear framebuffer support
   to the ATI driver, contributed the Norwegian keyboard mapping, and added
   MIDI and sample input features to the MPU and SB drivers respectively.

   Paavo Ahola (email unknown).<br>
   Helped fix a problem with BCC and the C implementations of fixmul.

   Patrick Hogan (patter AT iname DOT com).<br>
   Wrote the draw_gouraud_sprite() function, and made Windows audiostreams
   work properly.

   Paul Bartrum (bartrum AT xtra.co DOT nz).<br>
   Contributed the ellipse drawing functions.

   Paul Eipper.<br>
   Reported a bug where libdir from autotools was not used for the modules path.

   Paul Furber (paul AT sprintlink.co DOT za).<br>
   Provided the floating point apply_matrix_f() function.

   Paul Hampson (Paul.Hampson AT Pobox DOT Com).<br>
   Improved and fixed some problems in the SNES gamepad driver.

   Paul Pinault (diskaleg AT infonie DOT fr).<br>
   Translated the system error messages into French.

   Pavlos Touboulidis (gtoub AT otenet DOT gr).<br>
   Made file_select() able to include or exclude files based on their
   attributes.

   Pedro Cardoso (pcardoso AT viriato.ipv DOT pt).<br>
   Contributed the tweaked 80x80 VGA mode.

   Peter Cech (7cech AT nw.fmph.uniba DOT sk).<br>
   Added grabber support for the 8x8 BIOS font format, support for
   hot-swapping between a custom keyboard layout and the standard US
   mapping, optimised the alpha sprite blending routines and added non-ASCII
   space recognition to uisspace().

   Peter Hull (peterhull90 AT users.sourceforge DOT net).<br>
   Made the file selector work with directories that have more than 2048
   files, solved some compiling issues on MacOS X, fixed a bug in rest()
   that caused it to wait too long on that platform, fixed several problems
   with the hardware mouse cursor, fixed a deadlock in the software mouse
   updating code, fixed compilation problems under MacOS X tiger, added a
   MacOS X helpfile and did plenty of other things too.

   Peter Johansson (email unknown).<br>
   Reported a problem with system cursors not working in Windows.

   Peter Monks (pmonks AT iname DOT com).<br>
   Wrote the Video-7 graphics driver (now available as part of the FreeBE/AF
   project) and showed me how to set up the unchained 640x400 mode.

   Peter Palotas (blizzar AT hem1.passagen DOT se).<br>
   Added the keyboard callback routine.

   Peter Pavlovic (Peter.Pavlovic AT st.fmph.uniba DOT sk).<br>
   Added the Slovak keyboard mapping and message translation, stopped the
   DOS file selector from listing virtual drives, did the same for the
   Windows file selector, improved the support for accented character maps in
   the keyboard driver and made aesthetic modifications to the GUI menu
   system.

   Peter Puck (zaqhaq AT netscape DOT net).<br>
   Helped with the Mingw32 native build.

   Peter Wang (tjaden AT users.sourceforge DOT net).<br>
   Added the mouse_z wheel input support to the Linux code, fixed problems
   with the ESD sound driver, wrote the ALSA sound driver, wrote the BeOS
   sound driver, added OSS MIDI and sample input support, added banked mode
   support to the SVGAlib driver, wrote the X DGA mode switching code,
   improved the Linux joystick driver, X11 fullscreen, DGA2 and DGA driver,
   added pthread timers under Linux/Unix and did loads of other things too.

   Phil Frisbie, Jr. (pfrisbie AT geocities DOT com).<br>
   Wrote the CPU type detection code.

   Phil Shenk (email unknown).<br>
   Improved the MSVC build instructions.

   Philipp Thomas (pthomas AT suse DOT de).<br>
   Fixed all comparisons between signed and unsigned types, fixed compilation
   on x86-64, fixed all function prototypes, converted the configure
   machinery to autoconf 2.53 or later and added multi-arch support, DESTDIR
   support and the German translation to the RPM spec file.

   Przemek Podsiadly (ppodsiad AT elka.pw.edu DOT pl).<br>
   Added hicolor versions of the 3d polygon code.

   Revin Guillen (revin AT phylo DOT com).<br>
   Added the position_dialog() function.

   Richard Davies (richard AT debaser.force9.co DOT uk).<br>
   Added support for PSX and N64 joypads.

   Richard Mitton (100740.1271 AT compuserve DOT com).<br>
   Added support for 6-button joysticks, and wrote the 12-bit color example
   program (ex12bit.c).

   Richard Reeve (r.e.reeve AT stir.ac DOT uk).<br>
   Fixed a silly mistake with gcc 3.0.x detection.

   Robert J. Ragno (rjr AT mit DOT edu).<br>
   Wrote the Gravis GrIP driver, made some improvements to the Wingman, PSX
   and throttle input code.

   Robert J. Ohannessian (voidstar AT ifrance DOT com).<br>
   Added MMX optimisation for the 8 and 16-bit clear() functions, fixed bad
   clearing of subbitmaps, added SSE detection and optimised some masked
   blits with SSE instructions, added some routines to the unified color
   convertor and made some of them more robust, fixed the docs for
   pivot_scaled_sprite_v_flip(), revamped the retrieval mechanism of CPU
   capabilities, separated the CSS file and did plenty of other things too.

   Roberto Alfonso (rpgrca AT labint.frba.utn.edu DOT ar).<br>
   Fixed a couple of memory problems in the dat2c utility, added an
   srand() call in the demo game, made the MSVC port call `link /lib'
   rather than `lib', fixed several warnings with GCC 4 under DJGPP and
   fixed a grabber crash when importing a font range in an existing font.

   Robin Burrows (rburrows AT bigfoot DOT com).<br>
   Provided a new page flipping code for the DirectDraw subsytem, added a
   Windows sound driver using the Allegro mixer and another using waveOut,
   fixed two glitches in the DirectDraw code.

   Romano Signorelli (romanos AT bigfoot DOT com).<br>
   Added an arc plotting routine.

   Ron Novy<br>
   Made several improvements to the test program.

   Ronaldo Hideki Yamada (r.yamada AT uol.com DOT br).<br>
   Contributed the MacOS 9 port of Allegro.

   Ryan Patterson.<br>
   Some documentation fixes.

   S.Sakamaki (emt AT geocities.co DOT jp).<br>
   Added the VESA 3.0 refresh rate control code.

   S.Suzuki (s-suz AT sunfield.ne DOT jp).<br>
   Wrote the IF-SEGA /PCI, /PCI2, and /ISA joystick interface drivers.

   Salvador Eduardo Tropea (salvador AT inti.edu DOT ar).<br>
   Improved the keyboard routines (better handling of extended scancodes,
   keyboard LED support, capslock and numlock, and alt+numpad input),
   contributed the 320x100 VGA graphics mode, added support for proper 16
   bit sample mixing, fixed compilation on gcc 3.x and made numerous other
   useful suggestions, contributions and bugfixes.

   Sam Hocevar (sam AT zoy DOT org).<br>
   Fixed a Bashism in fix.sh that makes Solaris' sh choke, a race
   condition in the mixer under Unix w/ threads, Windows, BeOS and MacOS X,
   a crash in makedoc, made it possible to put functions from .s sources
   in a shared library under Unix and removed deprecated use of several
   functions.

   Santeri Saarimaa (gridle AT mbnet DOT fi).<br>
   Made the Finnish keyboard mapping.

   Sask Allegro (sask_allegro AT iespana DOT es).<br>
   Added support for more than two joysticks in the Windows port.

   Scott Harrison (scotth AT calderauk DOT com).<br>
   Added the OpenDOS detection code.

   Sean Gugler (sean AT epal DOT com).<br>
   Added the set_leds() function.

   Seunghwan Ji (email unknown).<br>
   Made makedoc output correct html and rtf files for Korean.

   Serge Semashko (serge AT lxnt DOT info).<br>
   Fixed a bug with the letter P in the Russian keyboard configuration
   file, added Enter as a fire key to the demo game, fixed some
   problems with Allegro working on Nokia 770, and fixed a crash in
   _linear_draw_trans_rgba_rle_sprite24.

   Seymour Shlien (seymour AT dgbt.doc DOT ca).<br>
   Contributed the Windows BMP file reader, bezier spline drawer, and
   justified text plotting function.

   Shawn Hargreaves (shawn AT talula.demon.co DOT uk).<br>
   Progenitor. Wrote everything that wasn't written by somebody else.

   Shawn Walker (binarycrusader AT gmail DOT com).<br>
   Several fixes to the .spec file, made get_executable_name use getexecname()
   under Solaris, fixed a bug in the keyboard driver that caused crashes on
   the same system, worked around errors with some versions of GNU AS and fixed
   errors in the configure script when not using GCC

   StApostol (stapostol AT gmail DOT com).<br>
   Fixed a bug in the exflame example and updated the FAQ to use rest(0) instead
   of yield_timeslice().

   Stefan Eilert (seilert AT rz.Uni-Osnabrueck DOT DE).<br>
   Added support for a second joystick.

   Stefan Schimanski (1Stein AT gmx DOT de).<br>
   Wrote the original Windows version pretty much single-handedly.

   Stefan T. Boettner (virtual.man AT t-online DOT de).<br>
   Wrote the Linux SVGAlib driver.

   Stepan Roh (src AT srnet DOT cz).<br>
   Added a Czech keyboard mapping and system message translation, the Latin
   Extended-A characters in the default font, the codepage support in the
   textconv utility, fixed some problems with the ESD sound driver, helped
   make Allegro build better on some Unix platforms, fixed const related
   problems in C versions of routines and added support for a automake-style
   DESTDIR variable in the Unix makefile.

   Stephan Brauss (sbrauss AT optronic DOT ch).<br>
   Made a few fixes to let the Linux port compile again on Linux 2.2.x,
   corrected a few nits in the Swiss keyboard configuration file and added
   new keysyms to the X11-to-BIOS conversion table in order to catch missing
   keycodes for the keypad when NumLock is on.

   Stephen Kittelson (stickman2000 AT juno DOT com).<br>
   Made bugfixes and tweaks to the keyboard system.

   Stijn Wolters.<br>
   Clarified the documentation of init_dialog.

   Sveinung Kvilhaugsvik(email unknown).<br>
   Pointed out that Allegro should respect DESTDIR under MacOS X.

   Sven Sandberg (svens AT it.uu DOT se).<br>
   Fixed a problem with save_bitmap() rounding the image widths, optimised
   the create_light_table() function, optimised the fixed point trigonometric
   routines, provided the Swedish message translations, improved the file
   selector sorting algorithm, optimised the spline routines, added
   ustrrchr(), improved the usprintf() handling of floats, changed the
   Z-buffer API, and did plenty of other things too.

   TBD/FeR (tbd AT usa DOT net).<br>
   Added the 320x600 and 360x600 resolutions to the mode-X driver.

   Teijo Hakala (teijo.hakala AT imnetti DOT fi).<br>
   Added wheel support to the Windows mouse driver.

   Tero Parvinen (Tero.Parvinen AT hut DOT fi).<br>
   Designed most of the new sound API.

   Theuzifan Sumachingun (uzi AT simauria.upv DOT es).<br>
   Improved the cpu detection for Cyrix chips and made the file selector
   only list valid drive letters.

   Thomas Fjellstrom (tfjellstrom AT home DOT com).<br>
   Wrote the ALSA 0.5.x MIDI driver and added support for ALSA 0.9.x.

   Thomas Harte (email unknown).<br>
   Helped fix a bug in show_video_bitmap() on MacOS X, helped optimise
   fixmul(), helped find many bugs in the MacOS X port, like better support
   for user-supplied Nibs, implemented a hardware accelerated stretch_blit
   under DirectX, and fixed a bug with draw_sprite and sub-bitmaps.

   Thomas Klausner (wiz AT danbala.ifoer.tuwien.ac DOT at).<br>
   Added NetBSD detection and fixed a problem with the allegro.m4 macro and
   automake 1.8+.

   Thomas Wolf (two AT chello DOT at).<br>
   Corrected some errors in the German keyboard mapping and added the
   German translation of the system messages.

   Tim Bird (tbird AT caldera DOT com).<br>
   Worked on the Linux console port.

   Tim Gunn (timgunn AT eastwind.com DOT au).<br>
   Wrote the TGA reading/writing routines.

   Timothy Terriberry (sundance AT sprintmail DOT com).<br>
   Fixed several bugs in the RGB &lt;-&gt; HSV conversion routines.

   Tobi Vollebregt (email unknown).<br>
   Spotted a bug in ustrerror(), which was not returning a pointer to
   a static buffer, reported a problem with shutdown_dialog() when a
   menu was open, helped port the Windows keyboard driver to Windows 98
   and fixed a bug with hardware cursor detection in X11.

   Tobias Dammers.<br>
   Fixed a problem with the DirectSound input driver.

   Tom Breton (tob AT world.std DOT com).<br>
   Added the functionality selection #ifndefs to allegro.h.

   Tom Novelli (tnovelli AT cyber3.servtech DOT com).<br>
   Wrote the original version of the digital MIDI driver.

   Tom St Denis (tomstdenis AT yahoo DOT com).<br>
   Fixed clipping of transparent objects.

   Tomohiko Sugiura (tmsugi AT d4.dion.ne DOT jp).<br>
   Added the KEY_ABNT_C1, KEY_YEN, KEY_KANA, KEY_CONVERT, KEY_NOCONVERT
   and other keys to the input handler, organised getting the IF-SEGA
   joystick drivers by S.Suzuki merged into my codebase and added a more
   aggressive Sidewinder joystick driver.

   Tore Halse (gnolam AT gmail DOT com).<br>
   Made Allegro windows always popup centred in Windows and made fixes to the
   documentation.

   V Karthik Kumar (karthikkumar AT gmail DOT com).<br>
   Added a Tamil language greeting to exunicode, added switches to use
   the Intel compiler in Windows and added a password option to the Windows
   screensaver example.

   Victor Williams Stafusa da Silva (vwss1984 AT yahoo.com DOT br).<br>
   Changed a few occurences of "256" to PAL_SIZE and made OS type detection
   handle Windows 2003 and Windows Vista.

   Ville Skyttä (scop AT users.sourceforge DOT net).<br>
   Fixed a problem with make install libdir= and modules on Unix systems.

   Vincent Penquerc'h (lyrian AT kezako DOT net).<br>
   Added the D_DIRTY flag and mouse button press/release events to the GUI
   system, optimised the 256 to truecolor blitting code to avoid repeated
   conversions of the palette table, added scare_mouse_area(), added the
   yield_timeslice() function, added the update selection function to the
   grabber, added the XCRP and YCRP properties to datafiles in general,
   implemented the big header split and did plenty of other things too.

   Vitaliy Chetverikov (email unknown).<br>
   Fixed a bug in the GUI where the return value of MSG_IDLE was ignored.

   VolkerOth (VolkerOth AT aol DOT com).<br>
   Integrated the concepts of scrolling and edit_proc objects.

]]></text></section><section title="Thanks!"><text><![CDATA[
   First, a big thank you to all the people who help me test and debug this
   code. It sometimes gets frustrating to receive hundreds of messages
   saying "it doesn't work!", but they are useful all the same...

   Andre Baresel (baresel AT informatik.hu-berlin DOT de),
   and Craig Jackson (Craig.Jackson AT launchpad.unc DOT edu),
   provided a tremendous amount of information about SB hardware.

   Benji York (Benji AT cookeville DOT com).<br>
   Provided hardware information for the Gravis GamePad Pro.

   Charles Mac Donald (cgfm2 AT hooked DOT net).<br>
   Showed me how to set some cool tweaked VGA and mode-X resolutions.

   Charles Sandmann (sandmann AT clio.rice DOT edu),
   DJ Delorie (dj AT delorie DOT com),
   Eli Zaretskii (eliz AT is.elta.co DOT il),
   and everyone else who has contributed to djgpp. I love it.

   C. Schwerdtfeger (schwerdt AT physics.ubc DOT ca),
   for his help (and enourmous patience!) in getting the SB Pro-I MIDI
   driver to work.

   Finn Thoegersen, Nordbanevej 3 C, DK-7800 Skive, Denmark.<br>
   Most of my SVGA hardware information came from his VGADOC package.

   Eric Jorgensen (smeagol AT rt66 DOT com).<br>
   Varmint's Audio Tools (VAT) gave me many useful ideas about how to play
   MIDI files.

   Jamie O'Connell (JamieOConnell AT msn DOT com).<br>
   Several of the new Adlib drum patches, and the specifications for the
   .IBK file format, came from his SBTimbre package.

   Jean-Paul Mikkers (mikmak AT stack.urc.tue DOT nl).<br>
   MikMod was the source of a lot of information about programming the SB,
   and also gave me the idea of dynamically reprogramming the PIT to get a
   really high resolution timer.

   Joel H. Hunter (jhunter AT kendaco.telebyte DOT com).<br>
   His SB library for djgpp is excellent, and helped me a lot.

   John Pollard (74723.1626 AT compuserve DOT com).<br>
   The FM instrument definitions are based on his MID-KIT library.

   Kendall Bennett and all the other cool people at SciTech Software.<br>
   These guys gave the world UniVBE, the VBE/AF API, and a lot of free
   information and example code. Plus they very kindly sent me a copy of the
   VBE/AF spec when I wanted one.

   Kris Heidenstrom (kheidens AT actrix.gen DOT nz).<br>
   His PC timing FAQ was a big help.

   Mark Feldman.<br>
   It goes without saying that the PCGPE was an invaluable resource.

   Michael Abrash.<br>
   You just gotta love that man...

   Paul Fenwick (bg914 AT freenet.carleton DOT ca).<br>
   Various bits of the mode-X code (notably the split screen stuff) came
   from his XLIBDJ library.

   powerjaw (powerjaw AT dnai DOT com).<br>
   Sent me a Sidewinder gamepad so I could fix some problems with the driver
   for it. What a cool thing to do...

   Robert Grubbs (rwgrubbs AT vt DOT edu).<br>
   Provided hardware information for the Sidewinder joypad.

   Robert Schmidt (robert AT stud.unit DOT no).<br>
   The register values for the 400x* mode-X resolutions came from his TWEAK
   program.

   Sourceforge.net (<a href="http://sourceforge.net/">http://sourceforge.net/</a>).<br>
   The Allegro community has been using their services (web, mailing lists,
   cvs, etc) since 3.9.x WIP versions.

   Tom Grandgent (tgrand AT canvaslink DOT com).<br>
   Organised and hosted the original Allegro mailing lists for many years.
   Hurrah!

   Vladimir Arnost (xarnos00 AT dcse.fee.vutbr DOT cz).<br>
   Provided hardware specs for the OPL3 chip.

   Frank Zappa, Mike Keneally, Pink Floyd, the Doors, Tori Amos, and all the
   other great musicians who provide me with things to listen to while I am
   programming.

   My parents, John and Nancy.<br>
   I would never have made it through all those late night coding sessions
   without the cafetiere they gave me last Christmas :-)


   By Shawn Hargreaves, Allegro creator.

]]></text></section></section><section title="Frequently asked questions (FAQ)"><section title="Contents"/><section title="Trivial problems"><text><![CDATA[
<div class="faq-shift-to-right">
]]></text><reflist><ref name="What is Allegro?" syntax="What is Allegro?"><text><![CDATA[      See <tt>readme.txt</tt>.


]]></text></ref><ref name="Where can I get it?" syntax="Where can I get it?"><text><![CDATA[      From any SimTel mirror (<a href="http://alleg.sourceforge.net/mirrors.html">http://alleg.sourceforge.net/mirrors.html</a>), in
      the directory <tt>gnu/djgpp/v2tk/</tt>, or from the Allegro homepage,
      <a href="http://alleg.sourceforge.net/">http://alleg.sourceforge.net/</a>.


]]></text></ref><ref name="How do I use it?" syntax="How do I use it?"><text><![CDATA[      See <tt>allegro.txt</tt>.
</div>



]]></text></ref></reflist></section><section title="The giftware licence"><text><![CDATA[
   The Allegro licence is absolutely clear unless you are a lawyer.
   However, it's written quite informally so this mini-FAQ tries to clarify
   some things.

<div class="faq-shift-to-right">
]]></text><reflist><ref name="Does the licence mean that Allegro is public domain?" syntax="Does the licence mean that Allegro is public domain?"><text><![CDATA[      No. Every Allegro contributor holds the copyright for the code he or
      she wrote. This means he or she grants you the right to use it for
      any purpose you want. But the fact that the contributor holds the
      copyright means that you e.g. cannot claim that you wrote the code.

]]></text></ref><ref name="Can I use Allegro for commercial purposes?" syntax="Can I use Allegro for commercial purposes?"><text><![CDATA[      Yes.

]]></text></ref><ref name="Is Allegro compatible with licence XXX (e.g. GPL)?" syntax="Is Allegro compatible with licence XXX (e.g. GPL)?"><text><![CDATA[      Because the Allegro licence has no restrictions on use you can combine
      it with any licence you want.

]]></text></ref><ref name="Is Allegro open source (OSI) compatible?" syntax="Is Allegro open source (OSI) compatible?"><text><![CDATA[      See the previous question. Since Allegro is compatible with about any
      license, it also is OSI compatible. It clearly is compatible with all the
      points in the OSD (open source definition). You can search the OSI
      mailing list for "Allegro" to see that OSI shares this view. (OSI
      officials still were reluctant to consider it for approval though and
      suggested to use an existing license like MIT instead.)

]]></text></ref><ref name="How are modifications of the library licensed?" syntax="How are modifications of the library licensed?"><text><![CDATA[      You can modify Allegro and distribute the modified Allegro under
      any licence you want, but the original unmodified parts will still
      be licenced under the Allegro licence. If you offer your
      modifications to be included in the official Allegro distribution
      (e.g. by sending them to the Allegro developers mailing list) you
      automatically agree with licencing the modification under the
      Allegro licence.

]]></text></ref><ref name="I took your code. Will you sue me? Your library destroyed my PC. Who do I sue?" syntax="I took your code. Will you sue me? Your library destroyed my PC. Who do I sue?"><text><![CDATA[      We are programmers not lawyers. This FAQ represents our current
      understanding of copyright law (or copyright laws in different
      countries). But given the license, which allows everything, and
      the disclaimer, which says we take no responsibility for anything,
      we really don't see how there could be any problems.
</div>



]]></text></ref></reflist></section><section title="DJGPP problems"><text><![CDATA[
<div class="faq-shift-to-right">
]]></text><reflist><ref name="What is this make program that I'm supposed to run?" syntax="What is this make program that I'm supposed to run?"><text><![CDATA[      Make is part of the standard djgpp distribution, in the file
      <tt>v2gnu/mak*b.zip</tt> (whatever the latest version number is).
      You can get this from <a href="http://www.delorie.com/djgpp/">http://www.delorie.com/djgpp/</a>.


]]></text></ref><ref name="Make doesn't work properly." syntax="Make doesn't work properly."><text><![CDATA[      Are you sure that you have installed djgpp correctly? Check the
      instructions in the djgpp <tt>readme.1st</tt> file, and in particular confirm
      that you have set the DJGPP environment variable and added the
      <tt>djgpp\bin</tt> directory to your path.


]]></text></ref><ref name="My djgpp installation is fine, but make still doesn't work properly." syntax="My djgpp installation is fine, but make still doesn't work properly."><text><![CDATA[      Are you sure that you are using the GNU make program, and not some
      other version like the Borland one? If in doubt, run <tt>make -v</tt> and
      check that the GNU copyright message is displayed.


]]></text></ref><ref name="When I run make, it asks me for some parameters. What do I type?" syntax="When I run make, it asks me for some parameters. What do I type?"><text><![CDATA[      You shouldn't be running make from the Win95 explorer! Bring up a DOS
      box, change to your Allegro directory, and type <tt>make</tt> at the command
      prompt.


]]></text></ref><ref name="When I run make, it says &quot;makefile has modification time in the future&quot;." syntax="When I run make, it says &quot;makefile has modification time in the future&quot;."><text><![CDATA[      Are you sure that your system time and date are set correctly?
      Alternatively you may have downloaded a fresh file made by someone in a
      more eastern timezone. In the latter case you can either wait a few
      hours, temporarily set your clock forward, or use a utility such as
      <tt>touch</tt> to change the timestamp of the files.


]]></text></ref><ref name="When I run make, it says &quot;virtual memory exhausted&quot;." syntax="When I run make, it says &quot;virtual memory exhausted&quot;."><text><![CDATA[
      As the error message suggests, you need to provide more memory for the
      compiler to use. The <tt>go32-v2</tt> program will tell you how much is
      currently available. If you are running under DOS, try to free up more
      disk space for use as a swapfile. When using win95, increase the DPMI
      memory limit in the properties for your DOS session to 65535 (you'll
      have to type this in by hand, because the pulldown list doesn't go
      above 16384).


]]></text></ref><ref name="When I run make, it says &quot;conflicting types for va_list&quot;." syntax="When I run make, it says &quot;conflicting types for va_list&quot;."><text><![CDATA[
      As the error message suggests, there is a conflict between newer
      versions of gcc and older versions of the libc. You must upgrade your
      djdevxxx.zip package to the latest update (timestamp 11 August 2002)
      of DJGPP-2.03 or above.


]]></text></ref><ref name="When I try to compile a program using Allegro, I get lots of errors like:" syntax="When I try to compile a program using Allegro, I get lots of errors like:"><text><![CDATA[   C:\TEMP\ccdaaaaa(.text+0x9):x.c: undefined reference to `allegro_init'<br>
   C:\TEMP\ccdaaaaa(.text+0xe):x.c: undefined reference to `install_keyboard'<br>

      You haven't read the docs, have you? :-) You need to link your program
      with the library file, <tt>liballeg.a</tt>. First, make sure you have installed
      everything properly (running <tt>make install</tt> should do this for you).
      Second, if you are compiling from the command prompt or with a makefile,
      add <tt>-lalleg</tt> to the end of your gcc command line, or if you are using Rhide,
      go to the Options/Libraries menu, type <tt>alleg</tt> into the first empty field,
      and make sure the box next to it is checked.


]]></text></ref><ref name="I give up: I can't compile this! Can you send me a precompiled version?" syntax="I give up: I can't compile this! Can you send me a precompiled version?"><text><![CDATA[
      No, sorry. For starters, <tt>liballeg.a</tt> is about 450k, but you'd probably
      also want various utilities like the grabber, sound setup, etc. And
      what about all the example programs? If we included compiled versions
      of everything, a binary distribution would be over 7 megs: way too big
      to be practical! More seriously though, there just isn't any reason
      why you can't build it yourself. A compiler is a deterministic
      process: given a particular input file and command line, it will always
      produce the same output. If this isn't working, you either have the
      wrong input files (ie. your copy of Allegro is broken in some way), or
      the wrong command line (it is hard to see how that could happen, since
      all you have to do is type <tt>make</tt>...) or your compiler is broken, ie. you
      didn't install djgpp properly. You need to find and fix the problem,
      not just sweep it under the carpet by getting someone else to compile
      Allegro for you...


]]></text></ref><ref name="Compile errors scroll off the screen too quickly for me to read them!" syntax="Compile errors scroll off the screen too quickly for me to read them!"><text><![CDATA[
      GNU tools write their error messages to the error stream, <tt>stderr</tt>.
      Unfortunately <tt>command.com</tt> is too stupid to know how to redirect this,
      but fortunately DJ was smart enough to work around that, so you can
      use his redir program to capture the output messages, for example
      <pre>
         redir -eo make > logfile.txt
      </pre>
</div>


]]></text></ref></reflist></section><section title="DOS problems"><text><![CDATA[
<div class="faq-shift-to-right">
]]></text><reflist><ref name="Does the DOS version of Allegro work under Windows NT?" syntax="Does the DOS version of Allegro work under Windows NT?"><text><![CDATA[
      Your mileage may vary. Some people have reported problems, while
      others say that it works fine. Use the Windows version of Allegro
      if you want to make Windows programs. If you want to run DOS
      programs, use DOS!


]]></text></ref><ref name="Does Allegro work under OpenDOS?" syntax="Does Allegro work under OpenDOS?"><text><![CDATA[
      Yes, but with some caveats. If you are using the OpenDOS version of
      EMM386, you must disable their DPMI implementation (specify <tt>DPMI=OFF</tt>
      on the <tt>EMM386.EXE</tt> device line in your config.sys). You should also
      make sure the <tt>PIC=OFF</tt> flag is set, but this is the default so it won't
      be a problem unless you have specifically enabled it.


]]></text></ref><ref name="How can I extend the 256k limit on Mode-X video memory? I have two megs in my card." syntax="How can I extend the 256k limit on Mode-X video memory? I have two megs in my card."><text><![CDATA[
      You can't. The limit is imposed by the VGA hardware, not by Allegro.
      To access more than 256k of video memory you need to use an SVGA mode,
      which means either switching to a higher resolution or getting a copy
      of the SciTech Display Doctor, which provides several low resolution
      SVGA modes.


]]></text></ref><ref name="Does DOS Allegro work with the SB-Live soundcard?" syntax="Does DOS Allegro work with the SB-Live soundcard?"><text><![CDATA[
      It does for some people, but not for others. The problem is that
      Creative Labs refuse to release any specs, so we don't know how to
      write a driver for it. Complain to them, or buy a different card from
      a more reasonable manufacturer.


]]></text></ref><ref name="Why does DOS Allegro play sounds so much quieter than in Windows?" syntax="Why does DOS Allegro play sounds so much quieter than in Windows?"><text><![CDATA[
      This might be because you have the volume set very low: try changing
      this in the setup program. Also, Allegro is mixing several sounds into
      a single output buffer, unlike the Windows sound player that only
      plays one sample at a time, so each individual sound can only get a
      smaller percentage of the total output volume. This is just the price
      you pay for multiple output channels. If you don't like it, use the
      setup program to tweak the number of channels: this can be any power
      of two less than or equal to 64, and the smaller you make it, the
      louder the sound will be. Alternatively, use <code>set_volume_per_voice()</code>,
      described in the docs. This will enable you to adjust the overall
      volume of Allegro's digital sound output.


]]></text></ref><ref name="Why doesn't it work with my video card?" syntax="Why doesn't it work with my video card?"><text><![CDATA[
      Try using a FreeBE/AF driver (<a href="http://www.talula.demon.co.uk/freebe/">http://www.talula.demon.co.uk/freebe/</a>),
      or the commercial SciTech Display Doctor (<a href="http://www.scitechsoft.com">http://www.scitechsoft.com</a>).
      If it still doesn't work, post a description of your problem to the
      Allegro mailing list, along with a copy of the output from running the
      afinfo and vesainfo programs.


]]></text></ref><ref name="Why not use some sort of dynamic linking system?" syntax="Why not use some sort of dynamic linking system?"><text><![CDATA[
      The VBE/AF interface already provides this for the video drivers: see
      the FreeBE/AF project on <a href="http://www.talula.demon.co.uk/freebe/">http://www.talula.demon.co.uk/freebe/</a>.
      For more general things like the sound, VESA, and mode-X routines,
      this would be very difficult to do because the drivers depend on a lot
      of helper functions from the core lib. The djgpp DXE format is nowhere
      near flexible enough to support this, and we don't want to make Allegro
      dependent on any other dynamic linking packages.


]]></text></ref><ref name="I get an &quot;out of environment space&quot; error when I run fix.bat or vcvars32.bat!" syntax="I get an &quot;out of environment space&quot; error when I run fix.bat or vcvars32.bat!"><text><![CDATA[
      Well duh, you need to increase the size of your environment then :-)
      You can do this by changing the settings for your DOS box (click the
      system menu and select "properties"), or at startup in your config.sys
      file (eg. <tt>shell=c:\command.com /e:8192 /p</tt>).
</div>


]]></text></ref></reflist></section><section title="Windows problems"><text><![CDATA[
<div class="faq-shift-to-right">
]]></text><reflist><ref name="I get an &quot;out of environment space&quot; error when I run fix.bat or vcvars32.bat!" syntax="I get an &quot;out of environment space&quot; error when I run fix.bat or vcvars32.bat!"><text><![CDATA[
      Well duh, you need to increase the size of your environment then :-)
      You can do this by changing the settings for your DOS box (click the
      system menu and select "properties"), or at startup in your config.sys
      file (eg. <tt>shell=c:\command.com /e:8192 /p</tt>).


]]></text></ref><ref name="When I run make, it says &quot;missing separator&quot;." syntax="When I run make, it says &quot;missing separator&quot;."><text><![CDATA[
      Make sure that you don't have a semi-colon appended to your MSVCDIR
      variable if you are using MSVC, to your MINGDIR variable if you are
      using MinGW or to your BCC32DIR variable if you are using BCC.
      Also run <tt>make -v</tt> from the command line and make sure you are using
      GNU make and not Borland make or Microsoft make.


]]></text></ref><ref name="I get lots of compile errors about things like &quot;LPDIRECTDRAWSURFACE2&quot;!" syntax="I get lots of compile errors about things like &quot;LPDIRECTDRAWSURFACE2&quot;!"><text><![CDATA[
      You need to tell your compiler how to find the DirectX include files
      and libraries: put the DirectX SDK <tt>/include</tt> and <tt>/lib</tt> directories in the
      compiler/linker path. Alternatively, if you don't want to modify any
      configuration stuff, you can simply copy the files from the DirectX SDK
      <tt>/include</tt> and <tt>/lib</tt> directories to the corresponding ones for your
      compiler.


]]></text></ref><ref name="I get lots of compile errors about things like &quot;DDEDM_STANDARDVGAMODES&quot;!" syntax="I get lots of compile errors about things like &quot;DDEDM_STANDARDVGAMODES&quot;!"><text><![CDATA[
      You need to upgrade to a more recent version of the DirectX SDK, at
      least version 5, which you can get from the Microsoft Developer site.


]]></text></ref><ref name="When I run make, it says &quot;windres: no resources&quot;." syntax="When I run make, it says &quot;windres: no resources&quot;."><text><![CDATA[
      If an anti-virus software (Norton or McAfee for example) is running in
      the background on your computer, try to disable it temporarily.


]]></text></ref><ref name="I get an error about a missing WinMain() or main() function!" syntax="I get an error about a missing WinMain() or main() function!"><text><![CDATA[
      You need to write <code>END_OF_MAIN()</code> just after your <code>main()</code> function.
      Allegro uses this, along with some preprocessor magic, to turn a normal
      <code>main()</code> function into a Windows-style <code>WinMain()</code> entry point.


]]></text></ref><ref name="I get an error about an &quot;unresolved external symbol _main&quot;!" syntax="I get an error about an &quot;unresolved external symbol _main&quot;!"><text><![CDATA[
      Make sure you're building a Windows GUI Application, and not a Windows
      Console Application. This is a setting when you create the project in
      MSVC, Dev-C++ or Borland C++ Builder. Alternatively, this is specified
      on the command line by the <tt>-subsystem:windows</tt> option for the MSVC
      linker, by the <tt>-Wl,--subsystem,windows</tt> option for the MinGW compiler
      or the <tt>-tW</tt> option for the Borland C++ compiler. Either that, or define
      the preprocessor symbol <tt>ALLEGRO_USE_CONSOLE</tt> prior to including Allegro
      headers if you really need the console for your program.


]]></text></ref><ref name="I get lots of compile errors about conflicting types for &quot;struct BITMAP&quot;!" syntax="I get lots of compile errors about conflicting types for &quot;struct BITMAP&quot;!"><text><![CDATA[
      If your program directly includes Win32 API header files, see the
      "Windows specifics" section of the documentation.
      <p>
      If your program only includes header files of the C++ standard library,
      you're very likely trying to compile it with gcc 3.x for MinGW; if so,
      define the symbol <tt>__GTHREAD_HIDE_WIN32API</tt> on the compiler command line:
      <pre>
         g++ -D__GTHREAD_HIDE_WIN32API program.cpp -lalleg
      </pre>


]]></text></ref><ref name="In windowed mode artifacts are left on the desktop when the window is moved or when another window is placed on top of it." syntax="In windowed mode artifacts are left on the desktop when the window is moved or when another window is placed on top of it."><text><![CDATA[
      Disable direct updating for the DirectX windowed driver by using the
      dedicated configuration variable. See the 'Configuration routines'
      section in the docs and the <tt>allegro.cfg</tt> template file for more
      detailed informations.


]]></text></ref><ref name="In windowed mode the screen stays black unless the window is placed under another window on the desktop." syntax="In windowed mode the screen stays black unless the window is placed under another window on the desktop."><text><![CDATA[
      Disable direct updating for the DirectX windowed driver by using the
      dedicated configuration variable. See the 'Configuration routines'
      section in the docs and the <tt>allegro.cfg</tt> template file for more
      detailed informations.
</div>


]]></text></ref></reflist></section><section title="Unix problems"><text><![CDATA[
<div class="faq-shift-to-right">
]]></text><reflist><ref name="I get an error about &quot;_mangled_main_address&quot; being undefined!" syntax="I get an error about &quot;_mangled_main_address&quot; being undefined!"><text><![CDATA[
      You need to write <code>END_OF_MAIN()</code> just after your <code>main()</code> function.
      Allegro uses this, along with some preprocessor magic, to get a copy
      of your <code>argv[]</code> parameters (it needs those for various internal things).


]]></text></ref><ref name="I get an error about a duplicate definition of the &quot;_main&quot; symbol!" syntax="I get an error about a duplicate definition of the &quot;_main&quot; symbol!"><text><![CDATA[
      You are probably on a Darwin/MacOS X system. If so, make sure the symbol
      <code>USE_CONSOLE</code> is not defined in your program: it is a deprecated symbol
      that must be replaced by <code>ALLEGRO_USE_CONSOLE</code>. Also note that the magic
      main can't be disabled on such a system: you simply can't define the
      symbol <code>ALLEGRO_NO_MAGIC_MAIN</code> in a program linked against Allegro.


]]></text></ref><ref name="Compile errors scroll off the screen way too quickly for me to read them!" syntax="Compile errors scroll off the screen way too quickly for me to read them!"><text><![CDATA[
      You need to redirect stderr into a file, so you can view them later.
      The method for doing this depends on your shell: if you are using a
      Bourne-style shell like bash, try <tt>make 2> logfile.txt</tt>


]]></text></ref><ref name="When I try to run Allegro programs, I get &quot;error while loading shared libraries: liballeg.so.4.1: cannot open shared object file: No such file or directory&quot;." syntax="When I try to run Allegro programs, I get &quot;error while loading shared libraries: liballeg.so.4.1: cannot open shared object file: No such file or directory&quot;."><text><![CDATA[
      You need to teach the dynamic linker where to find the Allegro shared library.
      See <tt>docs/build/unix.txt</tt>, near the end of the 'Installing Allegro' section.


]]></text></ref><ref name="When I try to use DGA2, I get &quot;resolution not supported&quot;, but the X server does actually support that resolution !" syntax="When I try to use DGA2, I get &quot;resolution not supported&quot;, but the X server does actually support that resolution !"><text><![CDATA[
      There are two possible reasons:
      1) DGA2 may support different resolutions/color depths than X,
         run the gfxinfo program to know what combinations you can use,
      2) You may have a buggy DGA2 implementation, see next question.


]]></text></ref><ref name="When I try to use DGA2, the screen goes black and the PC completely halts!" syntax="When I try to use DGA2, the screen goes black and the PC completely halts!"><text><![CDATA[
      You are probably using a XFree86 server with a very buggy DGA2
      implementation, such as 4.0.3 (shipped with Red Hat 7.1 for example).
      Upgrading to 4.1.0 will probably solve your problem. You can obtain
      it from <a href="ftp://ftp.xfree86.org/pub/XFree86/4.1.0/binaries/">ftp://ftp.xfree86.org/pub/XFree86/4.1.0/binaries/</a> selecting
      the directory suited to your platform and following the instructions
      you find in the Install file.
</div>


]]></text></ref></reflist></section><section title="General problems"><text><![CDATA[
<div class="faq-shift-to-right">
]]></text><reflist><ref name="I'm trying to compile the grabber, but it doesn't work!" syntax="I'm trying to compile the grabber, but it doesn't work!"><text><![CDATA[
      The grabber needs to be linked with the code in <code>datedit.c</code>. But you
      shouldn't have to worry about doing this by hand: just run <code>make</code> and
      that will build everything for you.


]]></text></ref><ref name="When I compile Allegro, make fails with something like `Error: operands given don't match any known 386 instruction' or `Error: no such instruction `maskmovq %mm3, %mm1''." syntax="When I compile Allegro, make fails with something like `Error: operands given don't match any known 386 instruction' or `Error: no such instruction `maskmovq %mm3, %mm1''."><text><![CDATA[
      You need to update your version of GNU binutils. See <tt>readme.txt</tt> to
      find out what the minimum required version you need is.


]]></text></ref><ref name="Can I use Allegro with my &amp;ltfoobar&amp;gt compiler?" syntax="Can I use Allegro with my &amp;ltfoobar&amp;gt compiler?"><text><![CDATA[
      Not unless &lt;foobar&gt; is mentioned in <tt>readme.txt</tt> as one of the
      supported platforms. You could port it, but that is usually a lot of
      work. If &lt;foobar&gt; is a 16 bit DOS compiler like Borland C, you
      might as well just forget the idea :-)


]]></text></ref><ref name="What is this &quot;Allegro WIP&quot; that I see people talking about?" syntax="What is this &quot;Allegro WIP&quot; that I see people talking about?"><text><![CDATA[
      WIP stands for "work in progress", and refers to any changes that are
      more recent than the last official release. WIP versions of the
      library can be obtained as patches from the Allegro website
      (<a href="http://alleg.sourceforge.net/">http://alleg.sourceforge.net/</a>), and are usually
      quite stable, although obviously not so well tested as a final release
      version.


]]></text></ref><ref name="I got the WIP patch, but I can't apply it." syntax="I got the WIP patch, but I can't apply it."><text><![CDATA[
      Do you have a copy of <tt>patch.exe</tt>? If not, go and get it from the same
      place that you downloaded the rest of djgpp: this tool is a standard
      part of the compiler distribution. Similarly, you can get the Mingw
      compiled version from <a href="http://sourceforge.net/projects/gnuwin32/">http://sourceforge.net/projects/gnuwin32/</a>.
      <p>
      If you do have the patch program but it isn't working properly, make
      sure that you are installing the patch over the top of an unmodified
      copy of whatever Allegro version it is intended to update (this will
      usually be the most recent official release from before the WIP was
      made, but check the text file that comes with the WIP to be sure).


]]></text></ref><ref name="When I run the demo game, it says it can't find demo.dat." syntax="When I run the demo game, it says it can't find demo.dat."><text><![CDATA[
      That file is distributed separately in the WIP versions. It is here:
      <a href="http://alleg.sourceforge.net/wip.html">http://alleg.sourceforge.net/wip.html</a>. (<tt>alldata.zip</tt>)


]]></text></ref><ref name="How can I display several different images at the same time? When I show the second one it messes up the palette for the first." syntax="How can I display several different images at the same time? When I show the second one it messes up the palette for the first."><text><![CDATA[
      This is just the way that the video hardware works: there can only be
      one palette in use at any given moment. Either convert your images so
      they all use the same palette, or switch to a truecolor graphics mode.


]]></text></ref><ref name="How can I convert my graphics to all use the same 256 color palette?" syntax="How can I convert my graphics to all use the same 256 color palette?"><text><![CDATA[
      See the Allegro.cc homepage (<a href="http://www.allegro.cc/">http://www.allegro.cc/</a>)
      for some utilities, for example FixPal and Smacker.


]]></text></ref><ref name="My colors always come out wrong. And how can I make a greyscale palette with 256 different shades?" syntax="My colors always come out wrong. And how can I make a greyscale palette with 256 different shades?"><text><![CDATA[
      The VGA hardware only uses 6 bits for each color component, which
      means the red, green, and blue values in the palette structure range
      from 0 to 63, not all the way up to 255. That gives you a potential
      2^18 = 262144 different colors, or 64 shades of grey. If you need more
      than this you could try using VESA function <tt>0x4F08</tt> to select an 8 bit
      wide DAC, but Allegro doesn't support this directly and I don't know
      how reliable it will be across different hardware.


]]></text></ref><ref name="Why do I have a funny color border at the edges of my monitor?" syntax="Why do I have a funny color border at the edges of my monitor?"><text><![CDATA[
      When you are in a 256 color mode, the VGA card displays color #0
      around the border of the display area (in truecolor modes it displays
      black). Your funny color will go away if you change the palette so
      that color #0 is black.


]]></text></ref><ref name="How can I fade the screen in a truecolor graphics mode?" syntax="How can I fade the screen in a truecolor graphics mode?"><text><![CDATA[
      With great difficulty :-) There is no such easy trick as just altering
      the palette, so you will have to repeatedly redraw the image in a
      lighter or darker form. You could draw black translucent rectangles
      over the screen to darken it down, or use <code>draw_lit_sprite()</code> to tint a
      bitmap while copying it to the screen, but be warned that these
      operations are expensive and will require a fast PC!
      <p>
      Also, have a look at <a href="http://www.allegro.cc/">http://www.allegro.cc/</a> for add-on packages
      (notably FBlend v0.5) that attempt to make this operation as fast as
      possible.


]]></text></ref><ref name="I tried using fade_in() and fade_out() with truecolor modes but nothing happened. What am I doing wrong?" syntax="I tried using fade_in() and fade_out() with truecolor modes but nothing happened. What am I doing wrong?"><text><![CDATA[
      <code>fade_in()</code> and <code>fade_out()</code> only work in 8-bit paletted modes.
      See the previous question for details.


]]></text></ref><ref name="How can I generate FLI or FLC format animations?" syntax="How can I generate FLI or FLC format animations?"><text><![CDATA[
      See the Allegro.cc homepage (<a href="http://www.allegro.cc/">http://www.allegro.cc/</a>)
      for some utilities, for example DTA and Smacker. Also, you can use ASE
      (Allegro Sprite Editor, <a href="http://ase.sourceforge.net/">http://ase.sourceforge.net/</a>), which allows
      drawing/editing each frame of the animation and save it as a FLI. Or
      you can use The GIMP (<a href="http://www.gimp.org/">http://www.gimp.org/</a>) along with it's GFli
      plugin, using layers as frames, and saving your work as <tt>file.fli</tt>.
      The GIMP allows you to edit existent FLI files too.


]]></text></ref><ref name="How can I make parts of my sprite transparent in truecolor modes? I don't understand what the docs mean by &quot;bright pink&quot;..." syntax="How can I make parts of my sprite transparent in truecolor modes? I don't understand what the docs mean by &quot;bright pink&quot;..."><text><![CDATA[
      In your favourite paint program, get hold of the RGB sliders and drag
      the red and blue ones up as far as they go (usually to 255, but this
      will depend on what units your software uses), and the green one right
      down to zero. The result is a special shade of Magic Pink, or as some
      people prefer to call it, magenta.


]]></text></ref><ref name="I can't get the 3D polygon functions to work!" syntax="I can't get the 3D polygon functions to work!"><text><![CDATA[
      Remember that the vertex positions are stored in fixed point format,
      so you must use the <code>itofix()</code> macro or shift your coordinates 16 bits
      to the left.


]]></text></ref><ref name="I can't get the rotate_sprite() function to work!" syntax="I can't get the rotate_sprite() function to work!"><text><![CDATA[
      Remember that the angle of rotation is stored in fixed point format,
      so you must use the <code>itofix()</code> macro or shift your coordinates 16 bits
      to the left. For example, <code>rotate_sprite(bmp, spr, x, y, itofix(32))</code>
      will rotate the graphic by 45 degrees.


]]></text></ref><ref name="I can't get the d_bitmap_proc() or d_icon_proc() GUI object to work!" syntax="I can't get the d_bitmap_proc() or d_icon_proc() GUI object to work!"><text><![CDATA[
      You are probably trying to initialise the dialog structure with a
      pointer to your bitmap, right? That won't work because the dialog is
      created at compile time, but the bitmap is only loaded at runtime, so
      the compiler doesn't yet know where it will be located. You need to
      fill in the dialog structure with a <code>NULL</code> pointer, and then copy the
      real bitmap pointer into the <code>dp</code> field as part of your program init
      code, after you've loaded the bitmap into memory.


]]></text></ref><ref name="Should I use regular bitmaps, RLE sprites, or compiled sprites?" syntax="Should I use regular bitmaps, RLE sprites, or compiled sprites?"><text><![CDATA[
      It depends on exactly what you are doing. If your images are totally
      opaque, there is no advantage to using an RLE sprite, and it will
      probably be faster to use a regular bitmap with the <code>blit()</code> function.
      If your graphics contain masked areas, an RLE sprite may be both smaller
      and faster than the <code>draw_sprite()</code> function, depending on your CPU
      and your bitmaps.
      Compiled sprites are in general quite a bit faster than both the
      others for masked images, and slightly faster for opaque graphics, but
      this is far more variable. They are at their best with small sprites,
      on older machines and in mode-X, and may actually be slower than
      <code>blit()</code> when using SVGA modes on a pentium (the large size of a
      compiled sprite is very bad for the cache performance).


]]></text></ref><ref name="How can I make my game run at the same speed on any computer?" syntax="How can I make my game run at the same speed on any computer?"><text><![CDATA[
      You need to make sure the game logic gets updated at a regular rate,
      but skip the screen refresh every now and then if the computer is too
      slow to keep up. This can be done by installing a timer handler that
      will increment a global variable at your game logic speed, eg:
<pre class="code">
      volatile int speed_counter = 0;

      void increment_speed_counter()
      {
	 speed_counter++;
      }

      END_OF_FUNCTION(increment_speed_counter)

      void play_the_game()
      {
	 LOCK_VARIABLE(speed_counter);
	 LOCK_FUNCTION(increment_speed_counter);

	 install_int_ex(increment_speed_counter, BPS_TO_TIMER(60));

	 while (!game_over) {
	    while (speed_counter &gt; 0) {
	       update_game_logic();
	       speed_counter--;
	    }

	    update_display();
	 }
      }</pre>


]]></text></ref><ref name="How can I take a screenshot of my Allegro program?" syntax="How can I take a screenshot of my Allegro program?"><text><![CDATA[
      Add a call to <code>save_bitmap()</code> somewhere in your code. See the
      <code>save_bitmap()</code> documentation for a discussion of one common pitfall
      when doing this, and some example code.


]]></text></ref><ref name="How can I generate a random number?" syntax="How can I generate a random number?"><text><![CDATA[
      Call <code>srand(time(NULL))</code> at the beginning of your program, and then use
      <code>rand()%limit</code> to obtain a pseudo-random number between <code>0</code> and <code>limit-1</code>.


]]></text></ref><ref name="Why not make a &quot;lite&quot; version of Allegro? I don't need any of the sound, maths, or GUI routines..." syntax="Why not make a &quot;lite&quot; version of Allegro? I don't need any of the sound, maths, or GUI routines..."><text><![CDATA[
      There is no need. The linker will only include the parts of the
      library that you actually use, so if you don't call any of, say, the
      texture mapping or FLIC playing functions, they will be left out of
      your executable. This doesn't work perfectly because a lot of the
      Allegro code uses tables of function pointers that cause some
      unnecessary routines to be linked in, so the majority of the graphics
      functions will be included in every executable, but I have tried to
      keep this to a minimum. See <tt>allegro.txt</tt> for information about more
      precise ways to remove some of the graphics and sound drivers.


]]></text></ref><ref name="Will you ever add support for 3D accelerator hardware?" syntax="Will you ever add support for 3D accelerator hardware?"><text><![CDATA[
      No. This sort of hardware support would be most useful as part of a
      proper 3D API, which Allegro is not, and will never be. If you want
      to do some work on this, the MESA library (a free implementation
      of OpenGL) is IMHO the place to start.
      <p>
      However, if you are interested in using OpenGL for graphics and Allegro
      for everything else, you can try the various add-ons libraries linked
      from <a href="http://www.allegro.cc/">http://www.allegro.cc/</a> such as AllegroGL.


]]></text></ref><ref name="Why not add a MOD playing function?" syntax="Why not add a MOD playing function?"><text><![CDATA[
      Several very good ones already exist, for instance the JGMOD or DUMB
      packages. See the audio library extensions section on the Allegro.cc
      website (<a href="http://www.allegro.cc/">http://www.allegro.cc/</a>). You are not allowed to suggest
      that one of these libraries be merged into Allegro, because this topic
      has already been done to death on the mailing list and we are tired of it.


]]></text></ref><ref name="Why not add networking support?" syntax="Why not add networking support?"><text><![CDATA[
      There are several networking packages currently in development or
      floating around on the net, though, and in our opinion this sort of
      code is more useful as an external library than it would be as part of
      Allegro.


]]></text></ref><ref name="Why can't Allegro read GIF files?" syntax="Why can't Allegro read GIF files?"><text><![CDATA[
      Unisys has a patent on the LZW compression algorithm that is used by
      the GIF format. We want everything in Allegro to be freely usable
      without any restrictions whatsoever, which means we can't include any
      code that is subject to licensing or the payment of royalties.


]]></text></ref><ref name="My program crashes all the time. Could this be a bug in Allegro?" syntax="My program crashes all the time. Could this be a bug in Allegro?"><text><![CDATA[
      Perhaps. Try to isolate the smallest fragment of code that is able to
      reproduce the problem, and we'll have a look at it. If you can send us
      a 10 line program, we will fix it. 100 lines, and we can probably fix
      it. 1000 lines, and we don't have a chance :-)


]]></text></ref><ref name="Can I use Allegro in my &amp;ltwhatever&amp;gt commercial application?" syntax="Can I use Allegro in my &amp;ltwhatever&amp;gt commercial application?"><text><![CDATA[
      Sure. See the giftware terms in <tt>readme.txt</tt>. We don't mind what you do
      with it, and there are no problems with commercial usage.


]]></text></ref><ref name="When will &amp;ltfoobar&amp;gt be finished? I can't wait..." syntax="When will &amp;ltfoobar&amp;gt be finished? I can't wait..."><text><![CDATA[
      Whenever it is done! A little encouragement is always welcome, but we
      don't have any completion deadlines and we're not going to make one up
      for you :-) As soon as it is finished, it will be released.


]]></text></ref><ref name="Where can I get some fonts to use with Allegro?" syntax="Where can I get some fonts to use with Allegro?"><text><![CDATA[
      The grabber can import directly from GRX or BIOS format .fnt files, or
      you can draw them onto a .pcx image using any paint program. See
      <a href="http://www.talula.demon.co.uk/ttf2pcx/">http://www.talula.demon.co.uk/ttf2pcx/</a> for a utility that
      will convert Windows TrueType fonts into this .pcx format.


]]></text></ref><ref name="Where can I find a set of instrument samples for the DIGMID driver?" syntax="Where can I find a set of instrument samples for the DIGMID driver?"><text><![CDATA[
      See the Allegro homepage (<a href="http://alleg.sourceforge.net/">http://alleg.sourceforge.net/</a>)
      for some links. You can use Gravis patches (.pat format), or SoundFont
      2.0 (.sf2) files, but the latter must be converted into a patches.dat
      file with the pat2dat utility.


]]></text></ref><ref name="How can I convert the documentation into Windows Help format?" syntax="How can I convert the documentation into Windows Help format?"><text><![CDATA[
      You need to download the makertf conversion utility
      (<a href="ftp://ftp.coast.net/Coast/win3/winhelp/mkrtf104.zip">ftp://ftp.coast.net/Coast/win3/winhelp/mkrtf104.zip</a>), and the Windows
      Help compiler (<a href="ftp://ftp.microsoft.com/Softlib/MSLFILES/HC505.EXE">ftp://ftp.microsoft.com/Softlib/MSLFILES/HC505.EXE</a>).
      Make a temporary directory, copy the <code>allegro.txi</code> file from the
      <code>allegro/docs</code> dir, and run the commands <tt>makertf --no-warn allegro.txi
      -o allegro.rtf -J allegro.hpj</tt> followed by <tt>hcp allegro.hpj</tt>. The
      second command will give a lot of warnings, but they can safely be
      ignored.


]]></text></ref><ref name="How can I print out the documentation?" syntax="How can I print out the documentation?"><text><![CDATA[
      The <tt>allegro.rtf</tt> file can be read directly into Microsoft Word and
      printed from there, but you should right-click and update the table of
      contents and index fields to fill them with the correct data first.
      Alternatively you can install the TeX package and use the tex and
      dvips programs to convert <tt>allegro.txi</tt> into Postscript format.


]]></text></ref><ref name="Where can I find example source code, add-on packages, and tutorials?" syntax="Where can I find example source code, add-on packages, and tutorials?"><text><![CDATA[
      Check the Allegro.cc homepage, <a href="http://www.allegro.cc/">http://www.allegro.cc/</a>.
      If you have anything to add to this, please post the URL!


]]></text></ref><ref name="Why is it considered good coding practice to define PI as a constant, rather than just using the value 3.141592 in my code?" syntax="Why is it considered good coding practice to define PI as a constant, rather than just using the value 3.141592 in my code?"><text><![CDATA[
      It simplifies the maintenance of your program, in case the value of PI
      ever needs to be changed. Also it will make your program more portable
      to other compilers that use different values of PI.


]]></text></ref><ref name="Why doesn't vsync() seem to work?" syntax="Why doesn't vsync() seem to work?"><text><![CDATA[
      A number of graphics cards have buggy or incomplete VESA
      implementations, and often the <code>vsync()</code> function is not implemented. For
      examples on flicker-free drawing, look at the code for the demo game,
      which uses a variety of methods to draw itself.


]]></text></ref><ref name="Why doesn't busy waiting on the key array work? For example, &quot;while (!key[KEY_ENTER]);&quot; doesn't work." syntax="Why doesn't busy waiting on the key array work? For example, &quot;while (!key[KEY_ENTER]);&quot; doesn't work."><text><![CDATA[
      If the code works without optimisations, then it could be the
      compiler's fault. You can try beating the compiler into submission,
      for example:
<pre class="code">
      while (!key[KEY_ENTER])
         rest(0);</pre>

      For this case, however, it would be better to use <code>readkey()</code> instead.
      Or consider upgrading or downgrading your compiler.


]]></text></ref><ref name="I get lots of errors when I try to compile my C++ Allegro program." syntax="I get lots of errors when I try to compile my C++ Allegro program."><text><![CDATA[
      You are probably declaring the use of a namespace before including
      Allegro headers. For example:
<pre class="code">
      #include &lt;iostream&gt;
      using namespace std;

      #include &lt;allegro.h&gt;</pre>

      Move the `using' declaration after the `include' directives referring
      to Allegro headers:
<pre class="code">
      #include &lt;iostream&gt;
      #include &lt;allegro.h&gt;

      using namespace std;</pre>


]]></text></ref><ref name="I'm still confused. Where can I get help?" syntax="I'm still confused. Where can I get help?"><text><![CDATA[
      See <a href="http://alleg.sourceforge.net/maillist.html">http://alleg.sourceforge.net/maillist.html</a>.
</div>

]]></text></ref></reflist></section></section><section title="Common mistakes"><section title="Contents"><reflist><ref name="Ignoring this manual." syntax="Ignoring this manual."><text><![CDATA[      Most problems are addressed in this manual. If you aren't sure about
      some parts of Allegro check particular section of manual. The FAQ
      section can also be very useful.

]]></text></ref><ref name="main() not returning int." syntax="main() not returning int."><text><![CDATA[      On platforms that need it, Allegro uses <code>END_OF_MAIN</code> to
      mangle your main() function and supply its own that is required by the
      platform. Allegro assumes that main() returns an integer, as required
      by various C standards. If you change the return type of your main() to
      something else Allegro's main() will get confused and return some
      nonsense value which some system can recognize as an error and crash
      your program.

]]></text></ref><ref name="Semicolon at END_OF_MAIN." syntax="Semicolon at END_OF_MAIN."><text><![CDATA[<pre class="code">
         int main(void)
         {
            allegro_init();
            /* more stuff goes here */
            ...
            return 0;
         }
         END_OF_MAIN(); /* wrong */ </pre>

      The semicolon is not only unnecessary after END_OF_MAIN(), but it can
      also cause some compilers to issue a warning.

]]></text></ref><ref name="Getting bitmap's size." syntax="Getting bitmap's size."><text><![CDATA[      Many people don't know how to get the dimensions of a bitmap. This can
      be done by accessing the `w' and `h' fields of the BITMAP structure:
<pre class="code">
         BITMAP *image;
         ...
         allegro_message("Bitmap size: %d x %d\n",
                         image-&gt;w, image-&gt;h);</pre>

]]></text></ref><ref name="Creating bitmaps before loading." syntax="Creating bitmaps before loading."><text><![CDATA[<pre class="code">
         BITMAP *image = create_bitmap(width, height);
         image = load_bitmap("image.bmp", pal);</pre>

      When loading a bitmap, Allegro will automatically create a bitmap big
      enough to store it. In the above code the address returned by
      create_bitmap() is overwritten by the second assignment statement, to
      the return value of the call to load_bitmap().  Since the address of
      the first (unnecessary) bitmap has been lost, there is no way to
      destroy it so there is a memory leak.

]]></text></ref><ref name="Loading a bitmap/font/sound inside a global object constructor." syntax="Loading a bitmap/font/sound inside a global object constructor."><text><![CDATA[      Almost all Allegro functions require Allegro to be initialized first,
      before they can be used. Since global object constructors are called
      before main() (from where <code>allegro_init()</code> would be called) this
      condition is violated.  You need to postpone calls to Allegro functions
      to after initializing Allegro.

]]></text></ref><ref name="Calling set_color_depth without resetting graphic mode." syntax="Calling set_color_depth without resetting graphic mode."><text><![CDATA[      <code>set_color_depth()</code> tells Allegro which color depth to use the <em>next</em> time a
      graphic mode is set or bitmap is created or loaded. It doesn't change
      the color depth of the current graphic mode or existing bitmaps.  You
      need to be sure that all your bitmaps and/or graphic mode are in the
      same color depth or Allegro will be forced to do slow color conversions
      between them.

]]></text></ref><ref name="Destroying global objects like `screen'." syntax="Destroying global objects like `screen'."><text><![CDATA[      Unlike other bitmaps `screen' is created by calling <code>set_gfx_mode()</code> and
      must not be destroyed by calling <code>destroy_bitmap()</code>. The proper way to
      destroy `screen' is calling <code>set_gfx_mode(GFX_TEXT, 0, 0, 0, 0)</code>.

]]></text></ref></reflist></section></section><section title="Help: what to do when your Allegro program doesn't work"><section title="Contents"/><section title="Introduction"><text><![CDATA[
   When things go wrong, it often seems like a good idea to ask other people
   for help. Fortunately for people in this situation, there are many people
   (both Allegro developers and users) who are happy to spend their time
   answering support questions of this type, but there are various things
   you can do to make this process work more efficiently. This document
   describes some steps to take whenever you have a problem with an Allegro
   program, suggesting ways that you can try to solve it yourself, and also
   giving some tips about when/how to ask for help. Following these
   guidelines will make life easier both for the helper (because all the
   relevant information will be presented to them in a concise and useful
   way), and for the helpee (because they are more likely to get a prompt
   and accurate reply).



]]></text></section><section title="Part 1 - who is the culprit?"><text><![CDATA[
   Is the problem a bug in Allegro, or in your code? To find out, try
   running the Allegro test programs, in particular the test.exe (for
   graphics related problems), the play.exe (for soundcard troubles), and
   the entire contents of the examples directory (for anything that is going
   wrong). If you can't reproduce the problem with any of these, it is
   probably your fault, in which case you should skip to part 3 below.

   If the problem is related to DOS graphics modes, you should start by
   getting a copy of Display Doctor from <a href="http://www.scitechsoft.com/">http://www.scitechsoft.com/</a>.
   If this fixes the trouble, it almost certainly means that your original
   VESA driver was broken in some way. I'm not interested in hearing reports
   about problems of this type: there is nothing I can do to fix them, so
   I'm afraid your only option is to get a better VESA driver, for instance
   by downloading Display Doctor. This is now free for download from SciTech's
   website, but there is no longer support for it. Alternatively, you can see
   if there is a FreeBE/AF driver for your card (see
   <a href="http://www.talula.demon.co.uk/freebe/">http://www.talula.demon.co.uk/freebe/</a>).

   For Windows graphics modes, you should probably check if DirectX is
   installed properly on your system and if new drivers have been released for
   your card.



]]></text></section><section title="Part 2 - when Allegro is at fault"><text><![CDATA[
   If you still think the problem lies with Allegro, post a system report
   containing a description of the problem, what platform and library
   version you are using, your hardware specs, and a list of exactly which
   programs you were able to reproduce the problem with (it is important to
   know not only what programs had trouble, but also which ones worked
   correctly, if any).

   Try running the test.exe program with various display drivers (any native
   drivers that you think might work with your card), and in various video
   modes, and report exactly what modes and color depths cause problems. If
   you are able to use any high resolutions at all, run test.exe with the
   Autodetect option and report the entire text that it displays in the
   middle of the screen.

   If the problem is related to DOS graphics modes, you should also post the
   output from running the afinfo and vesainfo programs (the short version
   is enough unless you are explicitly asked to add the -v switch: all that
   extra data isn't usually needed).

   If the problem is related to the sound system, try using the setup
   program to manually configure your card. You may need to manually enter
   the hardware parameters, and if it is an SB clone card, try selecting
   some earlier breed of SB card than whatever it is autodetecting (SB Pro,
   SB 2.0, or SB 1.0). If you are still unable to get anything working, your
   post should include the name and descriptions of whatever digital and
   MIDI sound drivers are being autodetected (this information is displayed
   by the play.exe program).



]]></text></section><section title="Part 3 - when your program crashes"><section title="crashes under DOS"><text><![CDATA[   When a djgpp program crashes, you will usually get a stack traceback
   looking something like:
<pre class="text">
      Exiting due to signal SIGSEGV
      General Protection Fault at eip=00001eca
      [snip]

      Call frame traceback EIPs:
	0x00001eca
	0x00001590
	0x00001aea
</pre>
   This information tells you exactly where the crash occurred. To make
   sense of it, you should compile your program with debugging information
   (using the -g switch), and then run "symify program.exe" while this
   traceback is displayed onscreen. That will change the traceback to
   something along the lines of:
<pre class="text">
      Call frame traceback EIPs:
	0x00001eca   _strcpy+14
	0x00001590   _main+56, line 7 of t.c
	0x00001aea   ___crt1_startup+138
</pre>
   In this case, you can see that the crash occurred in the strcpy()
   function, which was called at line 7 of the main() function in the t.c
   source file. Now you just have to go to that line, have a look at
   whatever you are doing there, and change it to be correct :-)

   Note: if the crash happens deep inside an Allegro function, this
   traceback may not be so useful. When this happens you can recompile
   Allegro with debugging information (see the readme file), and then
   link your program with the debugging library version.

   Note 2: even when this crash traceback points to one of the Allegro
   functions, that does not necessarily mean the Allegro routine is at
   fault. Anything will crash if you pass it invalid parameters, so unless
   you can duplicate the problem in one of the Allegro example programs, you
   should start out by assuming that it is a case of operator error and
   double-check exactly what you are passing to the Allegro function.

]]></text></section><section title="crashes under Linux/Unix"><text><![CDATA[   When your Allegro compiled Linux/Unix program crashes, you will usually
   get a not very meaningful message along with a core dump:
<pre class="text">
      Shutting down Allegro due to signal #11
      Segment violation (core dumped)
</pre>
   Look at your filesystem: there should be a file named core or something
   similar with information telling you exactly where the crash occurred.
   If there is no core, check your environment settings, under bash this is
   done with the 'ulimit -a' command. Usually 'ulimit -c unlimited'
   somewhere in your login scripts should work fine.

   Just like with djgpp, to make sense of the core, you should compile your
   program with debugging information (using the -g switch), and then run
   the GNU debugger on it "gdb binary core". That will load the debugger,
   print some information about linked libraries and leave you at a prompt.
   Now you can get the full backtrace:
<pre class="text">
      (gdb) backtrace
      #0  0x08065237 in utf8_getx (s=0xbffffc5c) at ./src/unicode.c:347
      #1  0x0806953f in ustrzcpy (dest=0x0, size=2147483646, src=0x0) at ./src/unicode.c:1770
      #2  0x08057575 in _mangled_main () at t.c:9
      #3  0x0806c9bf in main (argc=1, argv=0xbffffd14) at ./src/unix/umain.c:39
      #4  0x4015414f in __libc_start_main () from /lib/libc.so.6
</pre>
   In this case, you can see that the crash occurred in the ustrzcpy()
   function, which was called at line 9 of the main() function in the t.c
   source file. Now you just have to go to that line, have a look at
   whatever you are doing there, and change it to be correct :-)

   Note that the crash happened deep inside an Allegro function, which is
   also revealed by the traceback. However, the binary was linked against a
   static debug version of Allegro, we wouldn't have had so much luck with
   a non debug or dynamically linked version.

   Since gdb is an interactive debugger, you could also select a frame and
   check out the values of the variables, to see better who is the culprit:
<pre class="text">
      (gdb) frame 2
      #2  0x08057575 in _mangled_main () at t.c:9
      9          ustrcpy(p1, p2);
      (gdb) list
      4
      5       int main(void)
      6       {
      7          char *p1 = 0, *p2 = 0;
      8          allegro_init();
      9          ustrcpy(p1, p2);
      10         return 0;
      11      }
      12      END_OF_MAIN()
      (gdb) print p1
      $1 = 0x0
      (gdb) print p2
      $2 = 0x0
</pre>
   Yuck! Playing with NULL values doesn't really pay off. Ok, while this was
   a slightly out-of-the-can example, you surely get the point. Remember to
   check out GDB's manual to learn about more useful commands and/or how to
   debug your program while it's running and many other things. You might also
   want to check out Peter Wang's "Debugging with GDB" article, featured in
   the ninth number of the Pixelate online magazine
   (<a href="http://pixwiki.bafsoft.com/">http://pixwiki.bafsoft.com/</a>).



]]></text></section></section><section title="Part 4 - things people don't do (but should)"><text><![CDATA[
   One of the most common errors made by programmers is to neglect to check
   the return value from a function that may fail. Such an error will often
   lead to unexpected and downright unusual errors, making for a debugging
   nightmare. There are many functions in and out of Allegro that may or may
   not work depending on varying circumstances. They are, however, nice
   enough to let you know whether or not they were successful through
   documented return values.

   Whenever you call a function that might fail (most importantly
   set_gfx_mode(), install_sound(), and anything that loads data from the
   disk), it is _essential_ that you check the return code from this, and
   respond accordingly.

   Another commonly forgotten but important tool is to use whatever option
   enables strict warnings for your compiler (gcc uses -Wall), when
   compiling your code. Any warnings reported by this option will almost
   certainly represent errors in your program, and should be fixed before
   doing anything else. When using gcc, a useful trick is to compile with
   the -O setting as well, because this causes gcc to examine the program's
   actions in more detail, enabling more useful warnings. You should
   normally disable optimisation while debugging, though. Although it gives
   better compile time warnings, it is likely to upset any debugging tools
   that you later try to use.



]]></text></section><section title="Part 5 - asking for help"><text><![CDATA[
   Ok, so you've tried everything described above, and your program still
   doesn't work. You have no idea what to do next, so it is time to cast
   yourself unto the mercies of the net, in hopes of finding some kind of
   wise man, seer, or oracle that holds an answer for your question...

   The best places to ask are the Allegro mailing list (see readme.txt for
   details) and the Allegro.cc forums. Please remember that the mailing list
   is an Allegro-specific list. Problems relating to the C language or djgpp
   compiler belong in other forums (comp.lang.c and comp.os.msdos.djgpp
   respectively). The Allegro.cc forums can be found at
   <a href="http://www.allegro.cc/">http://www.allegro.cc/</a>. You can usually ask any question related
   to Allegro here.

   Both the Allegro and djgpp mailing lists are archived, and can be
   searched via their respective homepages. It is very likely that you will
   be able to find a solution to your problem by looking through the answers
   to past questions, which will save you needing to post a query at all.

   In accordance with proper netiquette, it is assumed that when you post to
   any forum on the Internet you have at least consulted the relevant
   documentation first, if not read it in its entirety. If the problem you
   are having is worth asking hundreds of people the answer for, then it is
   certainly worth taking a few minutes to try to solve the problem
   yourself. Allegro is extensively and painstakingly documented and it is
   considered a prerequisite to posting that you have not only read the
   text, but examined the example programs as well.



]]></text></section><section title="Part 6 - learn from my mistakes"><text><![CDATA[
   What not to do, Part One:
<pre class="text">
      "My program crashes. Please tell me why."
</pre>
   Yes, people really do sometimes send me questions like this :-) Despite
   years of practice I am still totally unable to read minds, so this is a
   very pointless thing to ask. In order to get help with a problem you must
   describe it in enough detail that other people will be able to understand
   and reproduce it: this usually means posting some of your source code.


   What not to do, Part Two:
<pre class="text">
      "I've got a problem with my program. I'm attaching a 500k zip file
      containing ten thousand lines of source code and all the graphics and
      sound data: can you please debug it and tell me what the trouble is?"
</pre>
   After wasting the time and phone bills to download such a huge file, it
   is unlikely that anyone will even _want_ to help you, let alone invest
   the amount of time it would take to read and understand such a huge mess
   of information. You must try to isolate a smaller chunk of code that
   demonstrates the trouble: the smaller you can make it, the more chance
   that someone will be able to help you with it. Remember that you are
   asking other people to do you a favour, so it is your responsibility to
   make this process as easy for them as you possibly can.



]]></text></section><section title="Part 7 - wording your plea"><text><![CDATA[
   The most important thing is to include code that can be compiled and
   tested by the person reading your message. Don't just post your entire
   program: try to extract a small section that includes the specific lines
   causing your problem, or reproduces the trouble in a simpler way (you
   will often find that you can locate the error yourself in the process of
   making this simpler version, so it is a good exercise in itself). This
   code should be a small but complete program that can actually be compiled
   and run, because it is very hard to debug incomplete code fragments.

   It is best to include the code directly in the text of your email
   message, because it is easier for people to read this than if they have
   to extract it from an attachment.

   Ideally your example should avoid using any external graphics and data
   files. It is ok to include a small (max 2k) zip containing such
   information, or failing that a description of what other files it needs
   (eg. "put a 32x32 .pcx file called 'tile.pcx' into the same directory as
   the program). If there is no way that you can simplify things this far,
   you should upload the program and data to a website and then just post
   that URL in your message.

   You should say what compiler options you used to build the program. These
   should include extra warnings. If you use gcc, post the list of compiler
   switches you used.

   Describe what you intended this program to do (it may not be instantly
   obvious to other people), and also what it really does when you run it.
   There is usually no need to post the actual crash traceback (other people
   can duplicate this for themselves as long as they are able to compile and
   run your code), but you should say whether you do get such a traceback,
   or a lockup, or just incorrect results (and if so, in exactly what way
   they differ from what you were expecting). It is useful to mark your
   source with a comment to show what line the crash traceback points to.

   Any other information that you can include may also be useful. Most
   importantly a brief machine description, information about any relevant
   drivers, and your Allegro version (please don't just say "WIP", but give
   the exact date if you are using anything other than an official numbered
   release).



]]></text></section><section title="Part 8 - a model of perfection"><text><![CDATA[
   For reference, here is an example of what I would consider to be an ideal
   problem report:

<pre class="text">
   I'm having some trouble using the hicolor video modes in my program,
   although they work fine with the Allegro tests. I'm using Allegro 4.0
   with MinGW 3.1.0 (gcc version 3.3.1) on a Pentium 1.2GHz, running under
   Windows 2000 and an ATi Radeon 7000 videocard.

   This program is supposed to select a 640x480 16 bit resolution, draw a
   blue rectangle near the top left corner of the screen, and then wait for
   a keypress before quitting, but I just get a General Protection Fault
   when I run it.

   I compile it using "gcc -Wall t.c -o t.exe -lalleg", and don't get any
   warnings.


   --- cut here, t.c ---

   #include &lt;stdio.h&gt;
   #include &lt;allegro.h&gt;

   void main()
   {
      BITMAP *bmp = screen;

      install_keyboard();

      if (set_gfx_mode(GFX_AUTODETECT, 640, 480, 0, 0) != 0) {
	 printf("Error setting video mode\n");
	 return;
      }

      set_color_depth(16);

      /* crashes during this rectangle call! */
      rectfill(bmp, 32, 32, 64, 64, 0x001F);

      readkey();
   }
</pre>

]]></text></section></section><section title="API compatibility information"><section title="Introduction"><text><![CDATA[
   Once Allegro 4.0 is released, we plan to maintain backward compatibility
   at the Application Programming Interface level for the subsequent stable
   releases of the 4.x series, that is for the releases with an even minor
   version number. For example, that means you will be able to compile your
   program written for version 4.0.0 with version 4.0.23 or version 4.2.1 of
   the library. However, in order to fix some minor inconsistencies of the
   original 4.0 API, we may make exceptions to the rule and break strict
   backward compatibility in a few cases. But this is guaranteed to never
   happen in a stable series for which major and minor version numbers are
   fixed; in other words, two stable versions that differ from each other
   only by the revision (3rd) number will be strictly backward compatible.

]]></text></section><section title="Changes between 4.0.x and 4.2.x series"><text><![CDATA[<ul><li>
   The 'aspect' parameter of get_camera_matrix() and get_camera_matrix_f()
   strictly conforms to the documentation; in particular, setting it to 1
   instructs the functions to do no scaling. This was not the case before,
   because the functions multiplied this aspect ratio by 4/3.
<li>
   Menus created from a DIALOG array (by using d_menu_proc for the proc pointer)
   now correctly use the w and h fields as a minimum for their inclusive
   dimensions (in the same way as all other GUI elements). Before, they would
   draw the border outside of this dimension (1 pixel overdraw with other GUI
   elements), and also add an additional 'shadow' to the right and the bottom
   (2 pixels overdraw with other GUI elements).
<li>
   The 'retrace_count' variable and the 'retrace_proc' callback function
   take into account the refresh rate (if it is known) when the retrace
   simulator is not installed. This was not the case before, except under
   Windows.
<li>
   The default value for the mouse configuration variable 'emulate_three'
   has been changed to 'no' in all cases (even if you have a 2-button mouse).
<li>
   The COLORCONV_KEEP_TRANS flag strictly conforms to the documentation now.
   This was not the case before, because it was ignored when loading bitmaps
   from datafiles. fixup_datafile() was modified to preserve transparency
   when this flag is set, which was not guaranteed before in rare cases.
<li>
   create_sub_bitmap() is now less tolerant about receiving bad arguments.
   For example, it used to compensate for negative values for the origin
   and return NULL if the parent bitmap was NULL. These cases are now
   ASSERTed in the debug version, but unchecked in the release version.
<li>
   install_allegro() and allegro_init() now return an error code if unable to
   initialise a system driver. Previously they would have aborted the program
   in such cases. Consequently you should check their return values.
<li>
   The preprocessor symbol USE_CONSOLE is deprecated. Define instead the
   symbol ALLEGRO_USE_CONSOLE prior to including Allegro headers in order
   to set up Allegro for building a console application.
<li>
   The constructors of the fix class from integer and floating point values
   are now explicit.
<li>
   All BeOS gfx driver IDs and constants have been replaced by more meaningful
   ones. You may have to modify your allegro.cfg to reflect the change, or
   update and recompile your programs if you used BeOS specific gfx drivers.
<li>
   The behaviour of the GFX_SAFE driver has changed: it doesn't try to first
   set up GFX_AUTODETECTed drivers anymore and is now guaranteed to be a
   windowed driver when the platform has got a windowing system.
<li>
   A datafile object returned by load_datafile_object() used not to contain
   the properties attached to the object. This has been fixed.
<li>
   object_message() now takes care of scaring and unscaring the mouse if the
   message to be sent is MSG_DRAW.
<li>
   file_select_ex() now treats '(+)d' as it does for any other attributes in
   the extension string which is passed to it: only directories are included
   and, among them, only those with the correct set of attributes.
<li>
   d_ctext_proc() now behaves like d_text_proc() and d_rtext_proc(), that is
   it takes into account the bounding box to calculate the position which the
   string is centered around. It previously used only the x field. And, as a
   consequence, gui_ctext_proc is now expected to behave the same.
<li>
   dialog_message() now passes user messages to hidden objects.
<li>
   set_volume() doesn't use the hardware mixer anymore to alter the global
   volume. Use set_hardware_volume() instead to get the old behaviour.
<li>
   The default sound volume of Allegro was raised, since there no longer is
   the risk of wrapping with the new mixer. To restore the volume level to
   that of previous versions, look at the set_volume_per_voice function.
   Programs already using set_volume_per_voice are not affected.
<li>
   The semantics of rest are clarified so rest(0) does yielding when
   possible.
<li>
   The get_align_matrix[_f] functions would return mirrored matrices in some
   cases, this was fixed.
<li>
   In many places 'unsigned long' variables were used to hold memory
   addresses. These have been changed to use the 'uintptr_t' type instead.
<li>
   15-bit and 16-bit bitmaps used to be arrays of unsigned shorts, and 32-bit
   bitmaps used to be arrays of unsigned longs. They have been changed to be
   arrays of 16-bit and 32-bit integers respectively. This makes a difference
   on platforms where an unsigned long is not 32-bits wide (e.g. some 64-bit
   platforms).
</ul>

]]></text></section><section title="Deprecated materials"><text><![CDATA[
   The following items have been deprecated and the main documentation was
   purged of any references to them. If you are still using any of those, now
   might be a good time to get rid of them (within parentheses is the symbol
   most likely to be a replacement for the obsolete one, if any). However
   they are still supported for the sake of backwards compatibility, unless
   you define the symbol ALLEGRO_NO_COMPATIBILITY prior to including Allegro
   headers.

<ul><li>
   clear (clear_bitmap).
<li>
   cpu_fpu (cpu_capabilities, in combination with CPU_FPU).
<li>
   cpu_mmx (cpu_capabilities, in combination with CPU_MMX).
<li>
   cpu_3dnow (cpu_capabilities, in combination with CPU_3DNOW).
<li>
   cpu_cpuid (cpu_capabilities, in combination with CPU_ID).
<li>
   draw_character (draw_character_ex, passing the mode you would have passed
   to text_mode() as the 'bg' parameter).
<li>
   fadd (fixadd).
<li>
   fsub (fixsub).
<li>
   fmul (fixmul).
<li>
   fdiv (fixdiv).
<li>
   fceil (fixceil).
<li>
   ffloor (fixfloor).
<li>
   fcos (fixcos).
<li>
   fsin (fixsin).
<li>
   ftan (fixtan).
<li>
   facos (fixacos).
<li>
   fasin (fixasin).
<li>
   fatan (fixatan).
<li>
   fatan2 (fixatan2).
<li>
   fsqrt (fixsqrt).
<li>
   fhypot (fixhypot).
<li>
   file_size (file_size_ex)
<li>
   file_select (file_select_ex, passing the two constants OLD_FILESEL_WIDTH
   and OLD_FILESEL_HEIGHT if you want the file selector to be displayed with
   the dimensions of the old file selector).
<li>
   fix_filename_path (canonicalize_filename).
<li>
   for_each_file (for_each_file_ex).
<li>
   gui_textout (gui_textout_ex, passing the mode you would have passed to
   text_mode() as the 'bg' parameter).
<li>
   initialise_joystick (install_joystick).
<li>
   joy_x (joy).
<li>
   joy_y (joy).
<li>
   joy_left (joy).
<li>
   joy_right (joy).
<li>
   joy_up (joy).
<li>
   joy_down (joy).
<li>
   joy_b1 (joy).
<li>
   joy_b2 (joy).
<li>
   joy_b3 (joy).
<li>
   joy_b4 (joy).
<li>
   joy_b5 (joy).
<li>
   joy_b6 (joy).
<li>
   joy_b7 (joy).
<li>
   joy_b8 (joy).
<li>
   joy2_x (joy).
<li>
   joy2_y (joy).
<li>
   joy2_left (joy).
<li>
   joy2_right (joy).
<li>
   joy2_up (joy).
<li>
   joy2_down (joy).
<li>
   joy2_b1 (joy).
<li>
   joy2_b2 (joy).
<li>
   joy_throttle (joy).
<li>
   joy_hat (joy).
<li>
   JOY_HAT_CENTER.
<li>
   JOY_HAT_CENTRE.
<li>
   JOY_HAT_LEFT.
<li>
   JOY_HAT_RIGHT.
<li>
   JOY_HAT_DOWN.
<li>
   JOY_HAT_UP.
<li>
   KB_EXTENDED.
<li>
   KB_NORMAL.
<li>
   SEND_MESSAGE (object_message).
<li>
   set_window_close_button.
<li>
   set_window_close_hook (set_close_button_callback).
<li>
   text_mode.
<li>
   textout (textout_ex, passing the mode you would have passed to text_mode()
   as the 'bg' parameter).
<li>
   textout_centre (textout_centre_ex, passing the mode you would have passed
   to text_mode() as the 'bg' parameter).
<li>
   textout_right (textout_right_ex, passing the mode you would have passed to
   text_mode() as the 'bg' parameter).
<li>
   textout_justify (textout_justify_ex, passing the mode you would have
   passed to text_mode() as the 'bg' parameter).
<li>
   textprintf (textprintf_ex, passing the mode you would have passed to
   text_mode() as the 'bg' parameter).
<li>
   textprintf_centre (textprintf_centre_ex, passing the mode you would have
   passed to text_mode() as the 'bg' parameter).
<li>
   textprintf_right (textprintf_right_ex, passing the mode you would have
   passed to text_mode() as the 'bg' parameter).
<li>
   textprintf_justify (textprintf_justify_ex, passing the mode you would have
   passed to text_mode() as the 'bg' parameter).
<li>
   PALLETE (PALETTE).
<li>
   DAT_PALLETE (DAT_PALETTE).
<li>
   black_pallete (black_palette).
<li>
   desktop_pallete (desktop_palette)
<li>
   get_pallete (get_palette).
<li>
   set_pallete (set_palette).
<li>
   get_pallete_range (get_palette_range)
<li>
   set_pallete_range (set_palette_range).
<li>
   fli_pallete (fli_palette).
<li>
   pallete_color (palette_color).
<li>
   select_pallete (select_palette).
<li>
   set_clip (set_clip_rect).
<li>
   unselect_pallete (unselect_palette).
<li>
   generate_332_pallete (generate_332_palette).
<li>
   generate_optimized_pallete (generate_optimized_palette).
<li>
   yield_timeslice (rest, passing 0 as parameter)
<li>
   retrace_proc (retrace_count or install_int).
<li>
   timer_can_simulate_retrace.
<li>
   timer_is_using_retrace.
<li>
   timer_simulate_retrace (when enable_triple_buffer is called, the mode-X
   driver still enables retrace simulation automatically where possible).
<li>
   split_modex_screen.
</ul>
]]></text></section></section><section title="ABI compatibility information"><section title="Introduction"><text><![CDATA[
   Once Allegro 4.2 is released, we plan to maintain backward compatibility
   at the Application Binary Interface level for the subsequent releases of
   the 4.2.x series. For example, that means you will be able to use an
   executable compiled using version 4.2.0 with version 4.2.5 or 4.2.41 of
   the dynamically linked library.

   However, there are some guidelines (rules) you should (must) follow,
   otherwise things will not work, and you will get angry emails from
   users and from us.

   Note: ABI compatibility will only be _actively_ maintained for:
<ul>
<li>Windows on x86
<li>Linux on x86
<li>Linux on x86-64
<li>MacOS X on PowerPC
</ul>

   We will not be maintaining "forwards compatibility", meaning that
   programs compiled with a newer release of Allegro may not necessarily
   run on a target system which has an older release of Allegro installed.
   You would have to upgrade the Allegro DLL on the target system.  While
   we will try to minimise these kinds of forced upgrades, it should give
   us more flexibility within the stable series.



]]></text></section><section title="Windows notes"><text><![CDATA[
   If you don't need a modified version of Allegro then just link your
   program against an officially blessed non-WIP, non-CVS, non-dodgy
   version. Don't disable any features (eg. colour depths, drivers) in
   the DLL.

   If you require a modified version of Allegro, then please either
   statically link, or pick a non-standard name for the Allegro DLL.
   For example, don't distribute a modified version of Allegro under a
   name such as all42.dll or alleg42.dll. Instead, call it something
   like alcustom.dll. Even better, statically link.

   For the people who use vanilla Allegro, we will provide a set of
   "reference" DLLs. If your binary works with those then everything is
   fine. If you want to distribute Allegro DLLs with your program
   (usually a good idea), we recommend you distribute our DLLs instead
   of ones you compiled yourself.



]]></text></section><section title="Linux on x86 notes"><text><![CDATA[
   To make sure an Allegro binary compiled on your machine will work on
   another machine, do not disable any "features" with `configure'. Your
   copy of Allegro must have assembly routines, threads, modules, all
   colour depths and X11 support enabled, amongst other things. If in
   doubt, leave it at the default setting.

   When you are ready to distribute your binary, run "ldd &lt;mybinary&gt;".
   It should say something like:

      liballeg.so.4.2 =&gt; /usr/local/lib/liballeg.so.4.2 (0xdeadbeaf)

   It should NOT say:

      liballeg.so.4.2.0 =&gt; /usr/local/lib/liballeg.so.4.2.0 (0xdeadbeaf)

   If you see the latter, that would mean users with later versions of
   Allegro would not be able to run your binary.

   See also the Windows section if you need to use a modified version of
   Allegro.

   For people packaging Allegro for redistribution: Drivers that are
   built as dynamically loaded modules may be disabled or left out, but
   all others should be left in. Examples of drivers that are _not_
   dynamically loaded include: OSS digital sound and OSS MIDI. In
   short, if a program built against a copy of default-options Allegro
   will work with your final library it should be fine.



]]></text></section><section title="Linux on x86-64 notes"><text><![CDATA[
   The situation is basically the same as for Linux on x86, however
   your copy of Allegro must NOT have assembly routines enabled (it
   wouldn't work anyhow).



]]></text></section><section title="MacOS X notes"><text><![CDATA[
   On OSX there are two 'styles' of linking - Unix style and Mac style.
   For the Unix style linking, you would use `allegro-config --libs`
   on the link line. For versioning, follow the advice given in the
   'Linux on x86' section above, using the command otool -L instead
   of ldd.

   For example, otool -L &lt;mybinary&gt; should give

      liballeg-4.2.dylib (compatibility version 4.2.0, current version 4.2.0)

   For the Mac style, use `allegro-config --frameworks` on the link
   line, or add Allegro.framework to your project if you are using
   XCode. In this case, the versioning is done inside the framework
   itself.

   Apple recommends that an application should be entirely self-
   contained. To achieve this in Allegro, static-link the executable
   and use fixbundle to bind all its resources together. In this
   way, you will not need to worry about incompatible versions of
   the library. This is useful if you are distributing an application.

   There is a known compatibility problem when using gcc 4 on MacOS X 10.4
   that prevents binaries from working on older versions of MacOS X. While it
   is anticipated that a future update from Apple will fix this problem, you
   can use gcc 3 to work around it.



]]></text></section><section title="Final notes"><text><![CDATA[
   Providing source is still better than not providing source. Binaries
   are good, however, if your code sucks and only you (with the help of
   witchcraft) can compile it.

   If you provided binaries in the past using WIP versions of Allegro,
   we politely request that you recompile your program using a stable
   version of Allegro.

]]></text></section></section><section title="The Allegro hacker's guide"><section title="Contents"/><section title="Coding Style"><text><![CDATA[
I'm not going to be a fascist about this, but it does make life easier if
all the code uses a consistent layout. If you are going to write and
maintain more than one complete source file of your own, I think you are
entitled to do that however you like, but for smaller contributions, I will
probably reformat your code to fit in with my existing style. It will
obviously save me time if you write it this way in the first place, hence
this description:

Basic Allegro style: K&amp;R, with 3 space indentation. On disk, though, tab stops
are 8 spaces, so if for example a line was indented by 12 spaces, this would be
saved out as either 12 space characters or 1 tab and 4 spaces, not as 4 tabs.
Because this format always will lead to code display looking broken in place or
another, new patches should now always use spaces only and no longer contain
tabs. The indent.pro file included with the Allegro distribution comes close to
getting this layout right, but doesn't quite manage it, so some things still
need to be cleaned up by hand.

Preprocessor defines and structure names are UPPER_CASE. Function and
variable names are lower_case. MixedCaseNames are evil and should not be
used. That silly m_pHungarian notation is _really_ evil and should not even
be thought about.

All symbols should be declared as static unless that is absolutely not
possible, in which case they should be prefixed with an underscore.

Functions look like this:
<pre class="code">
/* foobar:
 *  Description of what it does.
 */
void foobar(int foo, int bar)
{
   /* do some stuff */
}
</pre>
Three blank lines between functions.

Conditionals look like:
<pre class="code">
   if (foo) {
      /* stuff */
   }
   else {
      /* stuff */
   }
</pre>
The only time when something comes on the same line after a closing brace is
at the end of a do/while loop, eg:
<pre class="code">
   do {
      /* stuff */
   } while (foo);
</pre>
Case statements look like this:
<pre class="code">
   switch (foo) {

      case bar:
	 /* stuff */
	 break;

      default:
	 /* stuff */
	 break;
   }
</pre>
Examples of where to put spaces:
<pre class="code">
   char *p;
   if (condition) { }
   for (x=0; x&lt;10; x++) { }
   function(foo, bar);
   (BITMAP *)data[id].dat;
</pre>
All sources should begin with the standard header:
<pre class="code">
/*         ______   ___    ___
 *        /\  _  \ /\_ \  /\_ \
 *        \ \ \L\ \\//\ \ \//\ \      __     __   _ __   ___
 *         \ \  __ \ \ \ \  \ \ \   /'__`\ /'_ `\/\`'__\/ __`\
 *          \ \ \/\ \ \_\ \_ \_\ \_/\  __//\ \L\ \ \ \//\ \L\ \
 *           \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
 *            \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
 *                                           /\____/
 *                                           \_/__/
 *
 *      Brief description of what this file does.
 *
 *      By Author.
 *
 *      Cool stuff added by Someone Else.
 *
 *      Stupid bug fixed by a Third Person.
 *
 *      See readme.txt for copyright information.
 */
</pre>
Author credits should be added in chronological order, and email addresses
should not be included: those can be found in the main credits file, and if
they only exist in one place, it is easier to update them when people change
address.

People only need to be listed in the source file header if they've made a
significant contribution to it (one-line fixes don't count), but no matter
how small their addition, they must be added to the docs/thanks._tx file.
This is sorted alphabetically by name. If they are already in it, update the
text to describe the new addition, otherwise make a new entry for the new
contributor. Also, anything more than very tiny modifications should be
added to the docs/changes._tx file, which grows from the top in reverse
chronological order. This file should briefly describe both the nature of
the modification and who did it.



]]></text></section><section title="Build Process"><text><![CDATA[
This is very different depending on whether you are using autoconf or a
fixed makefile. For most platforms, though, the fixup script (eg.
fixdjgpp.bat), will create a small makefile, which defines MAKEFILE_INC to
the make of another file (eg. makefile.dj), and then includes makefile.all.
This contains a lot of generic rules, and includes the file named in
MAKEFILE_INC to provide additional platform-specific information. The actual
source files are listed in makefile.lst.

There are three library targets: alleg (release), alld (debugging), and allp
(profiling). Objects go in obj/compiler/version/, where version is one of
alleg, alld, or allp. Libraries go in lib/compiler/. A few generated things
(asmdefs.inc, mmxtest.s, etc), go in the root of obj/compiler/. Dependencies
are generated by "make depend", and go in obj/compiler/version/makefile.dep,
which is included by makefile.all.

When you run "make clean", this only deletes harmless generated files like
the objects. "make distclean" strips you right back to the original
distribution, including getting rid of the test executables and the library
itself. For the ultimate in personal hygene, run "make veryclean", which
will wipe absolutely all generated files. After doing this, you will have to
run "make depend" before you can build the library, and also "fixdll.bat" if
you are working on a Windows platform.

To pass long commandlines to the MSVC and Watcom linkers, the program
runner.exe is compiled using gcc, so make can pass it a decent number of
arguments. This just saves the parameters into a temporary file, and then
invokes the real command using that as an argument file.

All the makefiles currently use gcc for dependency generation, because this
is easier than trying to get MSVC or Watcom to output the right info.

The symbol LIBRARY_VERSION, defined at the top of the makefile.ver, is used
for including a version number in things like the DLL filename.



]]></text></section><section title="Header Files"><text><![CDATA[
allegro.h lives in the include/ directory. It is only a placeholder which
includes other headers which live in the include/allegro/ tree. The reason
for this slightly odd approach is that allegro.h can include things like
"allegro/keyboard.h", which will work both in-situ within the build
directory, and if we copy allegro.h to the system include directory and the
other headers into system_include/allegro/. This avoids cluttering the
system directories with lots of our headers, while still allowing programs
to just #include &lt;allegro.h&gt;, and also makes it possible for people to
access keyboard stuff with #include &lt;allegro/keyboard.h&gt;.

base.h includes alconfig.h, which checks the current platform and includes
a helper header for this compiler (aldjgpp.h, almsvc.h, alwatcom.h,  etc).
That helper header defines a bunch of macros describing the system, emulates
whatever things are needed to make the code compile properly, and optionally
defines ALLEGRO_EXTRA_HEADER and ALLEGRO_INTERNAL_HEADER if it is going to
need any other platform-specific includes.

After including the platform header, the rest of alconfig.h defines a lot of
generic helper macros to their default values, but only if the platform
header hasn't already overridden these to something specific.

Every module-specific header contains structure definitions and function
prototypes. At the end of the file, it may include a header from the
include/allegro/inline/ directory which defines related inline routines.
If inline asm is supported, this can include in turn asm.inl which imports
routines from one of the compiler-specific files al386gcc.h, al386vc.h and
al386wat.h; otherwise C versions are used instead. The header alinline.h
is a placeholder which includes all the headers defining inline functions.

If ALLEGRO_EXTRA_HEADER is defined, allegro.h includes this at the very end.
This is used to include one of the files aldos.h, alwin.h, etc, which define
platform-specific things like ID values for the hardware drivers. Unlike the
platform files included from the top of allegro.h, these are specific per-OS
rather than per-compiler, so the same alwin.h can be used by both MSVC and
MinGW. They describe library functions that relate to this platform, while
the earlier header described the basic language syntax.

aintern.h is like the internal.h in earlier Allegro versions, defining
routines that are shared between multiple sources, but that we don't
generally want user programs to see.

On platforms which have specific, non-portable API routines of their own,
these should go in a special header in the root of the include directory,
eg. winalleg.h. This can be included by user programs that want to access
these routines, while making it very clear to them that by including this
header, they are writing non-portable code.



]]></text></section><section title="Definitions"><text><![CDATA[
All header function prototypes should use the macro AL_FUNC(). Inline
routines use the macro AL_INLINE(). Global variables use AL_VAR() or
AL_ARRAY(). Global pointers to functions use AL_FUNCPTR(). Pointers to
functions which are passed as parameters to other routines or stored in a
structure typedef use AL_METHOD(). This may seem like something of an
overkill, but it gives us a lot of flexibility to add DLL import/export
specifiers, calling convention markers like __cdecl, and even to mangle
symbol names on some compilers. If you forget to use these macros, your code
won't work on some platforms.

This only applies to header files, though: you can write normal code in the
C sources.

The symbol ALLEGRO_SRC is defined while compiling library source files. If
you want to inline a function in one of your sources, use the INLINE macro.
To declare a zero-sized array in terminal position inside a structure, use
the ZERO_SIZE_ARRAY(type, name) macro. To use 64 bit integers, declare a
LONG_LONG variable (this won't be defined on all platforms). To do things
with filenames, check the macros ALLEGRO_LFN, OTHER_PATH_SEPARATOR, and
DEVICE_SEPARATOR. See the headers for details.



]]></text></section><section title="Unicode Support"><text><![CDATA[
Do not assume that strings are ASCII. They aren't. If you assume they are,
your code might work for a while as long as people are only using it with
UTF-8 data, but it will die horribly as soon as someone tries to run it with
16 bit Unicode strings, or Chinese GB-code, or some strange MIME format,
etc. Whenever you see a char * being passed around, you must be aware that
this will actually contain text in whatever format is currently selected, so
you have to be damn careful when manipulating strings. Don't ever forget and
call a regular libc routine on them!

Use the Unicode functions for all your text manipulation: see the docs for
details. When allocating a scratch string on the stack, assume that each
character will occupy at most four bytes: this will give you more than
enough space for any of the current encoding schemes.

If you want to specify a constant string, use the function
uconvert_ascii("my string", buf) to obtain a copy of "my string" in the
current encoding format. If buf is NULL, this will use an internal static
buffer, but the converted string will be overwritten by the next call to any
format conversion routines, so you shouldn't pass it down into other library
functions. Normally you should provide the conversion space yourself,
allocating buf as a temporary object on the stack.

To convert the other way (eg. before passing an Allegro string to an OS
routine that expects ASCII data), call uconvert_toascii(mystring, buf).

For any messages that may be seen by the user, you can call
get_config_text("my ascii string") instead of uconvert_ascii(). This will
return a pointer to persistent memory (so it is ok to keep the string around
indefinitely), after converting into the current text encoding format. This
function is cool because it saves you having to bother allocating space for
the converted data, and because it allows the string to be replaced by the
translations in language.dat. You should be sure to always pass a constant
string to get_config_text(), rather than any generated text or data from
other string variables: this is so that the findtext.sh script can easily
locate all the strings that need to be translated.

Hardware drivers should initialise their name and desc fields to the global
empty_string, and store an ASCII driver name in their ascii_name field. The
framework code will automatically translate and convert this value, storing
the result in both the name and desc fields. For most drivers this will be
enough, but if you want to provide a more detailed description, it is up to
your driver to set this up from their init routine, and take care of all the
required conversions.



]]></text></section><section title="Asm Routines"><text><![CDATA[
Structure offsets are defined in asmdef.inc, which is generated by asmdef.c.
This allows the asm code to use human readable names for the structure
members, and to automatically adjust whenever new fields are added, so it
will always exactly match the layout of the C structures.

Asm code should use the macro FUNC(name) to declare the start of a routine,
and GLOBL(name) whenever it wants to refer to an external symbol (eg. a C
variable or function). This is to handle name mangling in a portable way
(COFF requires an underscore prefix, ELF does not).

You can modify %ds and %es from asm, as long as you put them back. If USE_FS
and FSEG are defined, you can also change %fs, otherwise this is not
required and you can safely use nearptr access for everything.

Don't assume that the MMX opcodes will be supported: not every assembler
version knows about these. Check the ALLEGRO_MMX macro, and be sure to give
up gracefully if these instructions are not available.



]]></text></section><section title="Documentation"><text><![CDATA[
One of the nicest features of Allegro is its excellent manual, that you can
read in several formats, ranging from plain text to compiled HTML. All API
functions of the library have to be documented in docs/src/allegro._tx in the
appropriate section. Note that, whatever you write in the file, you shouldn't
exceed a line width of 78 characters, except for lines which contain tags.
This rule is needed in order to produce correct plain text documentation that
doesn't extend beyond the standard 80 column screen/terminal. All the other
formats are less strict about line width and will probably reformat the text
anyway.

If the function you are documenting returns a value, use the @retval command
to start the chunk of text that describes the return value or how it is used.
If the function takes parameters, document if they are required to follow a
specific format (e.g. string encoding), what they are for, and their range of
values (if any). The latter is particularly important for boolean parameters,
because there's no way to tell the user that an integer must be either `true'
or `false' in the C programming language. Parameters are always referred to
between single quotes, left and right. These are tt-ized in the HTML version,
but only if there are no space characters between the left and right quote.

If it is possible to include a little fragment of code which demonstrates the
usage of the function, do it just before the @retval command if there is one,
or at the end of the block. This is very welcome for functions that don't have
example references (@eref). You don't need to include the declaration of the
variables unless you really think it can help newbies.

Usually a single line will be enough, but don't hesitate to add whatever
comments you might think of as useful for newbies. Also, if you are writing
such a one liner, try to use verbose variable names to indicate where they
come from or what they should contain. Compare the following lines, where the
second is more likely to be found in `<tt>real life</tt>' code, but should be avoided
in these little code fragments taken out of context:
<pre class="text">
   blit(source_bitmap, destination_bitmap, source_x, source_y,
      destination_x, destination_y, bitmap_width, bitmap_height);
      ...
   blit(spr[3]->bmp, screen, x, y, s_x, s_y, spr[3]->bmp->w, spr[3]->bmp->h);
</pre>
Whatever coding style applies to Allegro's code also applies to these examples
(e.g. 8 characters tab, 3 spaces indentation). If you are having trouble
documenting a particular function because you don't know how to approach the
task (this tends to happen when you have used the function so much that you
have learnt it by heart), here is a checklist you can follow:
<ul><li>
   What is the purpose of the function? Why would the user want to call it?
<li>
   Can you call it at any time or is any other function required to have
   been called before (excluding install_allegro/allegro_init)?
<li>
   What do the parameters mean? Do they have a precisely defined type?
   Do they have a range (like boolean integers)?
<li>
   If the function returns a value, what is it? What can it be used for? Is
   it likely to be the input of another Allegro function? Does the return
   value have a range (e.g. positive numbers mean success, negative ones
   failure)?
<li>
   Is this function supported across all platforms that Allegro runs on?
   What does it do if it is not supported? Does it require a more thorough
   explanation in the platform-specific section of the documentation?
<li>
   Should the description say whether the function is reentrant or not?
   Do you think users would like to use it concurrently in multithreaded
   environments?
</ul>
Don't bother about existing example references (@eref). These are generated
automatically by a script. The person in charge of releasing Allegro will
most surely do this for you. If you know how to run it, you are very welcome
to update these tags though, to avoid piling extra work on the maintainer's
shoulders. Of course, all said about documenting functions applies to macros
and variables too.



]]></text></section><section title="Debugging helpers"><text><![CDATA[
As a developer you are encouraged to spill as many ASSERT and TRACE macros as
you consider necessary. ASSERT macros are a very good way of enforcing
documented limitations in input parameters which should never happen during a
perfect (ie. bugless) version of your game. They are good for things like
verifying some Allegro subsystem was initialised at the entry point of a
function which depends on it, or passing NULL pointers where the documentation
explicitly says the user is not allowed to do so.

The TRACE macro is very good for things which are not very repetitive, mainly
initialisation functions. The problem with C code is that usually error
reporting to the user programmer layer is done through a simple integer or
NULL pointer, and the error description (if any) stored in allegro_error. This
is clearly insufficient for functions like set_gfx_mode() which test many
graphic drivers before bailing out.

What should be the error code in such case? How could you preserve a coherent
error message to the user in driver A when driver B later overwrites it with
some other error which may not interest the user trying to run driver A?
Developers have made plans to include better logging facilities in future
Allegro releases. In the meantime, it is good if opaque systems like drivers
use TRACE both to indicate success and failure.

For this reason there is a TRACE convention for Allegro code using this macro.
At the top of the source file you want to use TRACE define three macros:
PREFIX_I, PREFIX_W, PREFIX_E. Each of this should be a string in the format
"al-SYSTEM LEVEL: " where SYSTEM is usually the filename creating the TRACE
(but doesn't have to) and LEVEL is either INFO, WARNING or ERROR respectively.
Later you can use them like this:
<pre class="code">
   if (some_error_in_a_deep_obscure_function) {
      TRACE(PREFIX_E "Couldn't init obscure driver because %s", something);
      return -1;
   }
   TRACE(PREFIX_I "Obscure system initialised with option %s", switch);
</pre>
Thanks to this prefix convention a user can use the TRACE macro too and grep
Allegro's messages if there is no interest in them.



]]></text></section><section title="Other Stuff"><text><![CDATA[
Any portable routines that run inside a timer handler or input callback must
be sure to lock all the code and data that they touch. This is done by
placing an END_OF_FUNCTION(x) or END_OF_STATIC_FUNCTION(x) after each
function definition (this is not required if you declare the function as
INLINE, though), and then calling LOCK_FUNCTION() somewhere in your init
code. Use LOCK_VARIABLE() to lock global variables, and LOCK_DATA() to lock
allocated memory.

Any modules that have cleanup code should register their exit function by
calling _add_exit_func(). This will ensure that they are closed down
gracefully no matter whether the user calls allegro_exit(), falls off the
bottom of main(), or the program dies suddenly due to a runtime error. You
must call _remove_exit_func() from inside your shutdown routine, or you will
find yourself stuck in an endless loop.



]]></text></section><section title="How to contribute patches"><text><![CDATA[
Once you are willing to contribute that beautiful hack which does what
everybody has been waiting for, the fix for that hideous bug which has been
driving you mad for several nights, the nice improved documentation you would
have liked to read in the manual for the first time, etc, you have already
done the hardest part. Now you only need a way to let the Allegro developers
merge your changes in the main distribution.

You could probably send your patch to one of the people working on Allegro,
but this is not very safe, it depends on the person you chose being available
and willing to do the work for you. The best you can do is to send your patch
to the Allegro Developers mailing list. Read the readme.txt file for
information on how to subscribe to this list.  Alternatively, updated
subscription instructions should always be available at
<a href="http://alleg.sourceforge.net/maillist.html">http://alleg.sourceforge.net/maillist.html</a>.

Sending your patches to the mailing list instead of a single person is good,
because all the subscribed developers can take a look at your modifications,
suggest improvements, or find problems, which you can discuss on the same
mailing list, letting other developers join the conversation when they
consider appropriate. If the modifications are good, they will probably be
accepted and merged in the WIP version for the next release. If you aren't
lucky, or your patch still needs some work, you will be told why it's not
accepted, or what you have to do to improve it. If you aren't subscribed to
the list, remember to say this in your message as, by default, replies are
irected to the list.

You can also use SourceForge's issue web trackers, which you can find at
<a href="http://sourceforge.net/tracker/?group_id=5665">http://sourceforge.net/tracker/?group_id=5665</a>. This doesn't require you to
subscribe to any mailing list and you can verify every now and then the
status of your contribution.



]]></text><section title="Building your patch against an existent release"><text><![CDATA[
If you have obtained Allegro from an existent release, stable or unstable,
you will have all the source code contained in some archive format. You will
need it, because to create a patch you need two versions of each modified
file, the original version, and your modified version.  You will also need
the diff tool, which is used to create the patches. This tool is usually
packaged as a standalone package in most GNU/Linux distributions with the
same name. For DOS, you can get a port from <a href="http://www.delorie.com/djgpp/">http://www.delorie.com/djgpp/</a>.
Just choose a mirror from <a href="http://www.delorie.com/djgpp/getting.html">http://www.delorie.com/djgpp/getting.html</a>,
enter the v2gnu directory and download the difxxb.zip package. While you are
at it, you can also get a tool named patch (patxxb.zip), which is used to
apply patches generated by diff, in case you have to apply the patches
somebody else sends to you. Install the binaries in some directory of your
path, so that you can use them from anywhere.

If you are planing to modify only one file, you will usually copy this file
to the same name in the same directory with the appended extension '.old'
before starting to work on it. After you have made your modifications to the
file, and verified that they please you, go to the directory containing the
modified and original files and type at the prompt:
<pre class="text">
   diff -u file.c.old file.c > patch
</pre>
This command will generate a text file which contains the differences
between both files in unified output format. Open it with your prefered
editor and verify that it contains the modifications you wanted to do: lines
you have added will be marked with a plus sign '+', lines you have removed
will be marked with a minus sign '-'. If the file is bigger than a few
kilobytes, compress it before sending to the developers mailing list, and of
course remember to add an explanation of what the patch is meant to do, why
it's needed, and any other information you consider relevant.

If the modifications you want to do are scattered through several files
and/or directories, this form of patch generation is very tiresome for both
ends (you, and the developers). So unpack a fresh copy of the Allegro source
somewhere and move it to the parent directory where your current version is,
after giving it another name of course, so as to obtain two complete sources
trees side by side. Modify the files you wish in your working
directory. Once you are finished, go back to the parent directory housing the
two source trees and type:
<pre class="text">
   diff -ur fresh_original_directory working_directory > patch
</pre>
The '-r' switch makes diff compare directories recursively. Again, do the
previous steps of verifying your patch, compressing and sending with correct
instructions.  If your patch adds or removes files, you will have to add the
'-N' switch, because by default diff will ignore files which are only in one
of the trees. Of course, you might want to run a 'make clean' in your working
directory before running this command, or you will include lots of generated
files which have nothing to do with your patch.  Or you could edit the
resulting patch, but that can be error prone.



]]></text></section><section title="Building your patch against a CVS version"><text><![CDATA[
If you are working with the cvs version of Allegro which you can get from
Sourceforge (<a href="http://sourceforge.net/projects/alleg/">http://sourceforge.net/projects/alleg/</a>), you won't need
to copy any files at all. Just modify the files you want, go to the root
directory of the cvs copy and type:
<pre class="text">
   cvs diff -u > patch
</pre>
Unlike the standalone diff, the cvs diff command will work recursively
through the Allegro source tree, comparing each file against the Sourceforge
repository. The patch will have slightly different headers, but that's ok,
once you have it follow the previous process to send it to the developers
mailing list. Of course, check cvs' manual for more information and options.



]]></text></section><section title="Online patch creation"><text><![CDATA[
Sometimes you don't have the diff tool around, or don't have the cvs tool to
check out the bleeding edge version of Allegro, or you are too lazy to care
how to actually make the patch yourself. For any of those cases, you can use
the online Allegro patcher at <a href="http://www.allegro.cc/dev/make-diff.php">http://www.allegro.cc/dev/make-diff.php</a>.

To use it, first you have to get one of the source files of Allegro and make
your changes to it. Then, go to that URL and supply the local path on your
computer to the modified file. Then, you write the path of this file relative
to Allegro's <em>root</em>. If everything goes well, you will end up with a
patch you can send to the Allegro developers mailing list or post on
SourceForge's patch submission page.
]]></text></section></section></section><section title="Allegro `const'-correctness"><section title="Contents"/><section title="Library changes"><text><![CDATA[
There are very few actual changes to the library code itself; only some
symbol declarations and definitions have been altered to include
AL_CONST. See below for a description of the AL_CONST preprocessor
define. In a few places, some string was changed that should not have
been - in these cases, the string is simply duplicated and then the
duplicate is erased on exiting the function.

In all, there were very few changes to the library code.



]]></text></section><section title="The AL_CONST preprocessor define"><text><![CDATA[
In order to support compilers which don't know about the `const'
keyword, or perhaps use a different keyword, the preprocessor symbol
AL_CONST is used wherever `const' would normally be used. Note that in
the documentation, I have used `const' for readability.



]]></text></section><section title="Allegro API changes"><text><![CDATA[
These are, generally speaking, totally transparent to the user. I did
not change the behaviour of any function; only its parameter types.
Basically, if you can pass it as <code>type* ptr</code>, then you can
pass it as <code>const type* ptr</code> without any problem whatsoever.
Note also that certain changes may remove warnings in your program as
static strings, etc, are now treated as `const' by Allegro functions.

There are a few places, described below, where there will be an effect
on existing code.

`const'-correctness is deemed important for two reasons. Firstly, it can
increase code readability and comprehension of Allegro functions (for
instance, you can see which parameters are altered and which are not).
Secondly, it ensures that the Allegro code is not changing data which it
should not be, and that client callback functions are not breaking
Allegro by changing data they should not be.



]]></text></section><section title="Callback functions and Pointers to Pointers"><text><![CDATA[
Certain callback functions now have a different type - they take `const'
pointers as opposed to non-`const' pointers. As far as I know, a
compiler will issue a warning about incompatible pointer types. You
should update your callback function to the new format (which will be
listed in the main Allegro documentation).

Also, when passing a pointer to a pointer to an Allegro function which
is declared as taking an <code>AL_CONST type** ptr</code>, you will need
to cast your pointer to be `const' if it is not already. For instance:
<pre class="code">
   int some_allegro_function(AL_CONST char** p);

   void my_func(char** x)
   {
       some_allegro_function((AL_CONST char**) x);
   }
</pre>
I realise that this is a change to the Allegro API, and that we are
supposed to avoid those at all costs, but this is essentially fixing a
bug in Allegro and changing behaviour. It also ensures that
client-supplied callback functions are functioning correctly, and not
altering data that they should not. Callback functions which do not
treat relevant parameters as `const' are, in a small (but potentially
signficant) way, broken.

Please note that for the Unicode function ugetx(), I have provided an
alternative version ugetxc(), which takes a `const char**' parameter as
opposed to a `char**' parameter. This is because it is valid to pass
either a `char**' or a `const char**', but unfortunately there is no way
to tell the compiler exactly what we mean.



]]></text></section><section title="BITMAP objects"><text><![CDATA[
Allegro represents both a screen bitmap and a memory bitmap by a single
object; a BITMAP. Unfortunately, these two things can be very different.
For instance, reading a pixel from a bitmap would not seem to change it,
but if it is a screen bitmap we are reading from, then it is possible
that some parameter of the video card is changed to select the correct
line, etc.

Therefore, a const BITMAP parameter does not make sense, and is not used
throughout the library. This is unfortunate, but I cannot see any way
around it.



]]></text></section><section title="Finally..."><text><![CDATA[
Allegro `const'-correctness has been tested for quite enough time to say
that it is working OK. However, if you still find problems with a compiler,
please contact the Allegro mailing list; see `Contact info' in the Allegro
documentation (readme.txt).

Email: lwithers AT lwithers.demon.co DOT uk.

Thanks for listening :-)

]]></text></section></section><section title="Packfile format information"><section title="Contents"/><section title="Introduction and scope"><text><![CDATA[
   This document describes the format of Allegro's packfiles from a
   decompression point of view. It does not describe how to do the
   compression (read the source, or ask Google about LZSS).

   file.c says "This compression algorithm is based on the ideas of Lempel
   and Ziv, with the modifications suggested by Storer and Szymanski.", if
   that means anything to you.


]]></text></section><section title="Packfile signature"><text><![CDATA[
   All compressed packfiles begin with a four byte signature "slh!" (ASCII),
   which in hexadecimal is 0x73, 0x6C, 0x68, 0x21 (in that order).

   Another form of packfiles are uncompressed packfiles, which begin with the
   four byte signature "slh." (ASCII), in hexadecimal 0x73, 0x6C, 0x68, 0x2B.
   The rest of the file is then completely raw. Uncompressed packfiles will
   not be discussed further.


]]></text></section><section title="Format and decompression algorithm"><text><![CDATA[
   Decompression requires a ring buffer of 4096 bytes and a ring index (which
   indexes into the ring buffer). The ring index starts at 4078, assuming
   0-based indices. New bytes may be stored into in the position in the ring
   buffer that the index points to. When a byte is stored, the index is
   incremented by one, wrapping around to zero as necessary.

   Packfiles must be decompressed sequentially. The first byte following the
   signature in the packfile is the "flags" byte, which determines how the
   following "tokens" in the file are to be interpreted.

   Bit 1 (the least significant bit) corresponds to the first token following
   the flags byte. Bit 2 corresponds to the second token, etc. After every
   eight tokens, there is another flag byte and another eight tokens, and so
   on, until the end of file.

   If the bit I of the flags byte is set, then token I is a single byte to be
   sent to the output. In addition, it must put onto the ring buffer and the
   ring index incremented.

   Otherwise, if bit I of the flags byte is not set, then token I is a two
   byte sequence containing an index and a length. The index is the first
   byte OR'd together with the higher 4 bits of the second byte as the higher
   order bits, thus making a 12-bit unsigned number (0-4095). The length is
   the lower 4 bits of the second byte, plus 3.
   In less hand-wavy C syntax:
<pre class="code">
      index  = byte1 | ((byte2 &amp; 0xF0) &lt;&lt; 4);
      length = (byte2 &amp; 0x0F) + 3;
</pre>
   Then, "length" number of bytes from the ring buffer, starting at "index",
   are to be sent to the output. In addition, all these bytes must be put
   onto the ring buffer, and the ring buffer incremented accordingly.

   Decompression ends at the end of the file. There is no end-of-file
   marker. If the number of tokens is not a multiple of eight, the unused
   bits in the latest flags byte are always zero.


]]></text></section><section title="Summary"><text><![CDATA[
   In brief, compressed packfiles take the form:
<pre class="text">
      signature -- 4 bytes

      flags     -- 1 byte
      token 1   -- each token 1 or 2 bytes
      token 2
       ...
      token 8
      flags
       ...
      (repeat flags and tokens 1-8 until EOF)
</pre>
]]></text></section></section><section title="Datafile format information"><section title="Contents"/><section title="Introduction"><text><![CDATA[
An Allegro datafile is a bit like a zip file in that it consists of lots of
different pieces of data stuck together one after another, and optionally
compressed. This means that your game doesn't have to clutter up the disk
with hundreds of tiny files, and it makes programming easier because you can
load everything with a single function call at program startup. Another
benefit is that the LZSS file compression algorithm works much better with
one large file than with many small ones.

Datafiles have the extension .dat, and can be created and edited with the
graphical grabber program or the command line dat utility. They can be
stored as separate files and loaded into memory by the load_datafile()
function, or you can use dat2s to convert them into asm code which can then
be linked directly into your executable.

]]></text></section><section title="Objects"><text><![CDATA[
Each datafile contains a number of objects, of varying types. Object types
are represented by 32 bit integer ID's, which are interpreted as four
character ASCII strings. These ID's can be constructed with the DAT_ID()
macro, for example a DATA object is represented by DAT_ID('D','A','T','A'),
or you can use the predefined DAT_* constants for the standard data types:

<ul><li>
DAT_FILE - "FILE"<br>
   A datafile, which contains a list of other objects. Datafile objects
   can be nested inside other datafiles, allowing you to create
   hierarchical structures of any depth.

<li>DAT_DATA - "DATA"<br>
   A block of binary data. Allegro treats all unknown types as binary
   data objects, so you don't need to use this ID: you can create custom
   object formats using whatever ID's you like.

<li>DAT_FONT - "FONT"<br>
   A font.

<li>DAT_SAMPLE - "SAMP"<br>
   A digital sound sample.

<li>DAT_MIDI - "MIDI"<br>
   A MIDI file.

<li>DAT_PATCH - "PAT "<br>
   A Gravis patch (MIDI instrument).

<li>DAT_FLI - "FLIC"<br>
   An FLI or FLC animation.

<li>DAT_BITMAP - "BMP "<br>
   A bitmap.

<li>DAT_RLE_SPRITE - "RLE "<br>
   A run length encoded sprite.

<li>DAT_C_SPRITE - "CMP "<br>
   A compiled sprite.

<li>DAT_XC_SPRITE - "XCMP"<br>
   A mode-X compiled sprite.

<li>DAT_PALETTE - "PAL "<br>
   A 256 color palette.

<li>DAT_PROPERTY - "prop"<br>
   An object property (see below). You will never directly encounter this
   object type, but you should be aware that it is treated specially by
   the datafile code.

<li>DAT_INFO - "info"<br>
   The grabber utility uses this object to store information about the
   datafile. Like property objects, you ought never to encounter it, but
   you should avoid using the ID for any custom object formats you create.

<li>DAT_END - -1<br>
   Special marker used to indicate the end of a datafile.
</ul>

]]></text></section><section title="Properties"><text><![CDATA[
Each object can have any number of properties attached to it. These are
ASCII strings describing attributes of the object, such as its name and
where it came from. Like the objects themselves, properties are identified
by 32 bit integer ID's which are constructed from four character strings by
the DAT_ID() macro. Allegro defines the standard properties:

<ul><li>
"NAME"<br>
   The name of the object.
<li>
"ORIG"<br>
   The object's origin, ie. the name of the file from which it was
   grabbed.
<li>
"DATE"<br>
   A timestamp, used by the update command in the grabber and dat
   utilities. This is the modification time of the file from which the
   object was grabbed, in "m-dd-yyyy, hh:mm" format.
<li>
"XPOS"<br>
   For bitmap objects which were grabbed from part of a larger image, the
   x position of the origin within the parent bitmap.
<li>
"YPOS"<br>
   For bitmap objects which were grabbed from part of a larger image, the
   y position of the origin within the parent bitmap.
<li>
"XSIZ"<br>
   For bitmap objects which were grabbed from part of a larger image, the
   width of the selected region.
<li>
"YSIZ"<br>
   For bitmap objects which were grabbed from part of a larger image, the
   height of the selected region.
<li>
"XCRP"<br>
   For autocropped bitmap objects, the amount of cropping on the left of
   the image.
<li>
"YCRP"<br>
   For autocropped bitmap objects, the amount of cropping at the top of
   the image.
</ul>

You can use whatever other ID's you like to store custom information about
your objects (the grabber internally use some other properties stored in a
hidden DAT_INFO object, so they won't conflict with yours).



]]></text></section><section title="File format specification"><text><![CDATA[
In case anyone wants to do some serious hackery, and for my own future
reference, here are some details of the innards of the datafile format.

Note that this is different to the datafile format used by Allegro versions
2.1 and earlier. Allegro can still load files from the old format, but it
was much less flexible and didn't support nice things like object
properties, so you should load any old files into the grabber and save them
out again to convert to the new format.

Nb. if all you want to do is write a utility that manipulates datafiles in
some way, the easiest approach is probably to use the helper functions in
datedit.c, which are currently shared by the dat, dat2s, and grabber
programs. These functions handle loading, saving, inserting and deleting
objects, and modifying the contents of datafiles in various ways, but life
is too short for me to bother documenting them all here. Look at the
source...

Anyway. All numbers are stored in big-endian (Motorola) format. All text is
stored in UTF-8 encoding. A datafile begins with one of the 32 bit values
F_PACK_MAGIC or F_NOPACK_MAGIC, which are defined in allegro.h. If it starts
with F_PACK_MAGIC the rest of the file is compressed with the LZSS
algorithm, otherwise it is uncompressed. This magic number and optional
decompression can be handled automatically by using the packfile functions
and opening the file in F_READ_PACKED mode. After this comes the 32 bit
value DAT_MAGIC, followed by the number of objects in the root datafile (not
including objects nested inside child datafiles), followed by each of those
objects in turn.

Each object is in the format:

<pre class="text">
   OBJECT =
      var    - &lt;property list&gt;      - any properties relating to the object
      32 bit - &lt;type ID&gt;            - object type ID
      32 bit - &lt;compressed size&gt;    - size of the raw data in the file
      32 bit - &lt;uncompressed size&gt;  - see below
      var    - &lt;data&gt;               - the contents of the object
</pre>

The property list can contain zero or more object properties, in the form:

<pre class="text">
   PROPERTY =
      32 bit - &lt;magic&gt;              - "prop"
      32 bit - &lt;type ID&gt;            - property type ID
      32 bit - &lt;size&gt;               - size of the property string, in bytes
      var    - &lt;data&gt;               - property string, _not_ null-terminated
</pre>

If the uncompressed size field in an object is positive, the contents of the
object are not compressed (ie. the raw and compressed sizes should be the
same). If the uncompressed size is negative, the object is LZSS compressed,
and will expand into -&lt;uncompressed size&gt; bytes of data. The easiest way to
handle this is to use the pack_fopen_chunk() function to read both the raw
and compressed sizes and the contents of the object.

The contents of an object vary depending on the type. Allegro defines the
standard types:

<pre class="text">
   DAT_FILE =
      32 bit - &lt;object count&gt;       - number of objects in the sub-file
      var    - &lt;object list&gt;        - objects in the same format as above

   DAT_FONT =
      16 bit - &lt;font size&gt;          - 8, 16, -1, or 0

      if font size == 8 {           - obsolete as of version 3.9.x!
	 unsigned char[95][8]       - 8x8 bit-packed font data
      }

      if font size == 16 {          - obsolete as of version 3.9.x!
	 unsigned char[95][16]      - 8x16 bit-packed font data
      }

      if font size == -1 {          - obsolete as of version 3.9.x!
	 95x {
	    16 bit - &lt;width&gt;        - character width
	    16 bit - &lt;height&gt;       - character height
	    var    - &lt;data&gt;         - character data (8 bit pixels)
	 }
      }

      if font size == 0 {           - new format introduced in version 3.9.x
	 16 bit - &lt;ranges&gt;          - number of character ranges
	 for each range {
	    8 bit  - &lt;mono&gt;         - 1 or 8 bit format flag
	    32 bit - &lt;start&gt;        - first character in range
	    32 bit - &lt;end&gt;          - last character in range (inclusive)
	    for each character {
	       16 bit - &lt;width&gt;     - character width
	       16 bit - &lt;height&gt;    - character height
	       var    - &lt;data&gt;      - character data
	    }
	 }
      }

   DAT_SAMP =
      16 bit - &lt;bits&gt;               - sample bits (negative for stereo)
      16 bit - &lt;freq&gt;               - sample frequency
      32 bit - &lt;length&gt;             - sample length
      var    - &lt;data&gt;               - sample data

   DAT_MIDI =
      16 bit - &lt;divisions&gt;          - MIDI beat divisions
      32x {
	 32 bit - &lt;length&gt;          - track length, in bytes
	 var    - &lt;data&gt;            - MIDI track data
      }

   DAT_FLI =
      var - &lt;data&gt;                  - FLI or FLC animation, standard format

   DAT_BITMAP =
   DAT_C_SPRITE =
   DAT_XC_SPRITE =
      16 bit - &lt;bits&gt;               - bitmap color depth
      16 bit - &lt;width&gt;              - bitmap width
      16 bit - &lt;height&gt;             - bitmap height
      var    - &lt;data&gt;               - bitmap data

      Valid color depths are 8, 15, 16, 24, 32, and -32. Both 15 and 16 bit
      images are stored in 5.6.5 RGB format, and 24 and 32 bit images as
      8.8.8 RGB. The special -32 flag indicates that the data is in true 32
      bit RGBA format.

   DAT_RLE_SPRITE =
      16 bit - &lt;bits&gt;               - sprite color depth
      16 bit - &lt;width&gt;              - sprite width
      16 bit - &lt;height&gt;             - sprite height
      32 bit - &lt;size&gt;               - data size, in bytes
      var    - &lt;data&gt;               - RLE compressed sprite data

      Valid color depths are 8, 15, 16, 24, 32. and -32. Both 15 and 16 bit
      images are stored in 5.6.5 RGB format with 16 bit skip counts and EOL
      markers, and 24 and 32 bit images as 8.8.8 RGB. with 32 bit skip
      counts and markers. The special -32 flag indicates that the data is in
      true 32 bit RGBA format.

   DAT_PALETTE =
      256 x {
	 8 bit - &lt;red&gt;              - red component, 0-63
	 8 bit - &lt;green&gt;            - green component, 0-63
	 8 bit - &lt;blue&gt;             - blue component, 0-63
	 8 bit - &lt;pad&gt;              - alignment padding
      }
</pre>

I think that covers everything.
]]></text></section></section><section title="License and Disclaimer"><section title="The giftware license"><text><![CDATA[
   Allegro is gift-ware. It was created by a number of people working in
   cooperation, and is given to you freely as a gift. You may use, modify,
   redistribute, and generally hack it about in any way you like, and you do
   not have to give us anything in return.

   However, if you like this product you are encouraged to thank us by making
   a return gift to the Allegro community. This could be by writing an add-on
   package, providing a useful bug report, making an improvement to the
   library, or perhaps just releasing the sources of your program so that
   other people can learn from them. If you redistribute parts of this code or
   make a game using it, it would be nice if you mentioned Allegro somewhere
   in the credits, but you are not required to do this. We trust you not to
   abuse our generosity.

   Disclaimer:

   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
   SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
   FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
   DEALINGS IN THE SOFTWARE.
]]></text></section></section></section><section title="Tools"><section title="makedoc - Generate documentation in various formats"><section title="Using makedoc"><text><![CDATA[
Not only the library is built from source code but the actual documentation
too. Allegro is bundled with makedoc, a convulsed C program which started
small and has grown to support many different output formats. The
documentation source and documentation generator can be found both under the
`docs/src' directory. Running `make' in Allegro's top directory will generate
the documentation along with the library, but there are more specific make
targets which you can use to selectively build only the documentation or
specific versions of the documentation which by default won't be generated.
You can find more about these in the "Makefile targets" chapter.

]]></text><section title="Output formats"><text><![CDATA[Makedoc output will be placed in the `docs/format' directory or directly in
the `docs' directory. Usually if an output format requires an external tool
which doesn't come bundled with Allegro you will have to generate it manually
with the correct makefile target.
<ul><li>
   `.txt'<br>
   Plain text version of the documentation. It is basically a dump of the
   `._tx' source file stripping the custom tags. This output is generated by
   default and available on all supported platforms.
<li>
   `.rtf'<br>
   Rich text format version of the documentation. This is a slightly improved
   version of the text output. Makedoc will generate a few nice things like
   a table of contents and will use different fonts in the output, which
   are nicer to read or print than the text version. This output is generated
   by default and available on all supported platforms.
<li>
   `.html'<br>
   Html version of the documentation. Depending on some tags in the `._tx'
   source file it can be built as multiple files or a single big page (see
   below). The documentation is generated in two steps: first the normal
   output is generated. This output doesn't contain hyperlinks between
   chapters since the makedoc tool doesn't know in advance in which file will
   be found a specific symbol. The second pass will go through all the links
   and make them point to the correct files. Thanks to cascade style sheets
   you can customize the outlook of the documentation without having to
   modify the makedoc tool. This output is generated by default and available
   on all supported platforms.
<li>
   `.3'<br>
   Unix man pages for the section "Library calls (functions within program
   libraries)". As usual these man pages will contain a synopsis,
   description and see also sections. Certain parts of the documentation
   like chapter introductions won't have man pages. This output is generated
   by default on Unix platforms. Note that you have to install the man pages
   manually with a specific makefile target.
<li>
   `.texi'<br>
   Intermediate format for GNU tools. This format is not readable alone and
   requires processing to be transformed into something else. This output can
   be generated on all platforms because it doesn't require external
   programs, but all by itself is not very useful.
<li>
   `.info'<br>
   GNU online info format. Generated from the `.texi' output this format can
   be used with the GNU `info' tool. The produced output looks similar to the
   plain text version but features hyperlinked navigation. This output is
   generated by default on platforms supporting the GNU tools like Unix or
   DJGPP (DOS). You need the `makeinfo' tool to generate the output and the
   `info' tool to view it. You have to install this manually on your system
   with a specific makefile target.
<li>
   `.chm'<br>
   Compiled HTML. Similar to the HTML output but instead of having lots of
   separate files you end up with a single file. You need Microsoft's HTML
   compiler to build this version of the documentation. Windows users can
   view `.chm' files by default. Non Windows users can go to
   <a href="http://freshmeat.net/">http://freshmeat.net/</a> and search for "chm viewer". Read more in the
   "Makefile targets" chapter.
<li>
   `.dvi'<br>
   Device independent documentation file. While this format is usable, it is
   also used as intermediate step to other formats. In fact, this one is
   build from the texi output. By default not build, as it relies on the
   external tool texi2dvi.
<li>
   `.ps'<br>
   Postscript version of the documentation, ideal for printing. This is not
   generated by default because it needs to generate the DVI output and
   then use the external tool `dvips'.
<li>
   `.pdf'<br>
   Portable document format. Similar in output quality to the postscript
   output, this has the advantage of having hyperlinks. Generated from the
   texi output with the external tool `texi2pdf'.
<li>
   `.devhelp'<br>
   Devhelp HTML + XML index format. Similar to the HTML output, this also
   carries a separate index which can be used by external programs (usually
   programming editors) to look up context sensitive help. Basically it is
   like the info output but using the more flexible HTML format as base.
   This format doesn't require external tools to be built, but it is not
   built by default. You have to create and install it manually.
<li>
   `.api'<br>
   SciTE api format. This is an index of all Allegro functions of the
   library for the SciTE editor (<a href="http://www.scintilla.org/SciTE.html">http://www.scintilla.org/SciTE.html</a>).
   This output is generated by default and available on all supported
   platforms.</ul>

]]></text></section><section title="Customizing the output"><text><![CDATA[Some of the output formats can be customized even further by modifying some
of the generated files or directly the original source file. The
documentation source file format is described with more detail in
`docs/src/makedoc/format.txt'. Usually the interesting bits to users are:
<ul><li>
   The HTML output generates by default individual HTML files for each
   chapter. By uncommenting the `multiplefiles' command you can create a
   single file with the whole manual. Note that external documentation files
   like the FAQ or hacking guide will still be linked, but not included.
<li>
   The HTML output also uses cascade style sheets to specify the outlook of
   the generated pages. You can disable CSS with the `ignore_css' command or
   specify a different CSS file with external-css=. The default CSS file
   generated by makedoc also has something to tweak.
<li>
   When using the multiple file output, makedoc places a "Back to contents"
   link at the bottom of each chapter. If you follow a hyperlink you can end
   up pointing at one of the last descriptions of the page but your browser
   might not scroll to the correct height because the page ends up before.
   To avoid this effect, you can uncomment one of the last lines in the CSS
   related to a bottom margin. Making the bottom margin higher puts more
   space between the "Back to contents" link and the physical end of the
   page.
</ul>
Note that all the above which applies to HTML output also applies to
documentation formats which are HTML based, like Devhelp or CHM.
]]></text></section></section></section><section title="grabber - Create datafiles"><section title="Contents"/><section title="Commandline options"><text><![CDATA[
The grabber accepts a few different commandline options:

   '-bpp'
      Sets the color depth, eg. -8, -16, -32.

   '-WxH'
      Sets the screen resolution, eg. -320x200, -1024x768

   '-windowed'
      Forces the grabber to start up in a window.

   '-fullscreen'
      Forces the grabber to start up in fullscreen mode.

   '-nosound'
      Disables audio output.

   '-pkey'
      Use 'key' as the datafile password.

   'filename.dat'
      Loads the named datafile.

]]></text></section><section title="Using the grabber"><text><![CDATA[
Various options can be set using the buttons and text fields at the top of
the screen. You can edit the name of the datafile, the name of the header
file for exporting object indexes (leave this blank if you don't want to
output a header), and the prefix string for the header file definitions. You
can change the grid settings for grabbing bitmaps, and alter the compression
mode (see below). You can enable or disable backups: if this box is checked,
the old version will be renamed to a .bak extension when datafiles are saved.
You can also turn dithering on (this can improve the image quality when you
reduce graphics from 15, 16, 24 or 32-bit color to 8-bit color and from 24 or
32-bit color to 15 or 16-bit color) and enable transparency preserving (this
will ensure that the masked areas in bitmaps stay exactly the same through
color conversion).

The contents of the datafile are listed in the box at the bottom left of the
screen, and can be selected with the mouse or arrow keys. Multiple objects
can be selected by holding down the shift or control keys while you click
on the list or move the cursor. The selected object can be edited with
commands from the Object menu, or using the shortcut menu produced by
pressing Esc or right-clicking on an object. Double-clicking on an object
performs a function which varies depending on the type of the object.
Bitmaps are displayed full-screen (use the plus and minus keys to zoom in
and out), samples and MIDI files are played, palettes are selected (meaning
that they will be used when displaying and exporting bitmaps), and fonts can
be edited by adding and removing specific character ranges.



]]></text></section><section title="Modifying objects"><text><![CDATA[
New objects can be created using the menus or by pressing Insert while the
item list has the input focus. To make nested datafiles, create a FILE
object (New/Datafile), and select it before inserting other objects.

To insert information into a datafile you must first create an object of the
appropriate type, and then select the grab command (keyboard shortcut
ctrl+G). For most objects this will bring up a file selector for you to
select the file to read, but for graphic objects (bitmaps, RLE sprites,
compiled sprites, and palettes) it will grab from the current contents of
the image buffer, so you must previously have read a picture into this
buffer with the File/Read Bitmap command (keyboard shortcut ctrl+G). You can
use the mouse or arrow keys to select which portion of the image to grab.
With the mouse, select the top left corner, click and hold the left mouse
button, and move to the bottom right corner before releasing the button.
Press the right mouse button to cancel. With the keyboard, use the arrow
keys to select the top left corner, press Space or Enter, adjust the size
with the arrow keys, and press Space or Enter again. By default the position
will snap to a 16x16 grid, which can be adjusted by changing the values in
the X-grid and Y-grid fields. Alternatively you can use the Box Grab
command, in which case you should draw a bounding box in color #255 around
your sprites, and can then just click once inside a box to grab the contents.

Note that palette data is not stored along with bitmap and sprite objects.
To store the entire contents of a PCX or BMP file, you will need to create
both bitmap and palette objects, and grab data into both of them. When you
reload the datafile the bitmap will probably be displayed with the wrong
palette. This can be corrected by double-clicking on the palette object,
which will select its contents as the current palette, meaning that it will
be used when displaying and exporting bitmaps.

The properties of the selected object are listed in the box to the right of
the item list. These can be edited by double-clicking on one of the
properties, and deleted by selecting one and pressing Del. You can insert
new properties by pressing Insert while the property list has the input
focus, or using the Object/Set Property command. Object names are stored as
NAME properties, so the rename command is simply a shortcut for editing this
property.



]]></text></section><section title="Bitmap grabbing"><text><![CDATA[
To simplify the process of grabbing several related images from a single
bitmap (for example a set of frames which form an animation), you can use
the File/Grab from Grid command. Like the normal bitmap grab command, this
uses data from the image buffer, so you must read in a bitmap before you use
it. You will then be able to adjust the grabbing parameters, enter a name
for the new objects, and choose the type of object to create (bitmap, RLE
sprite, or compiled sprite). Because several objects may be created, their
names will be formed by adding a number to the end of the name you supply,
for example if you enter "a_picture", the grabber will create the objects
"a_picture000", "a_picture001", etc. There are two grabbing modes: using
cutouts of color 255, and using a regular grid. The regular grid option
simply divides the bitmap up into a set of equally sized tiles, using the
specified grid size, and grabs each of these as a separate object. If you
set the Skip Empties flag, the grabber will ignore tiles that don't contain
any data (ie. those that are a single solid color). The color 255 option is
more flexible. It expects the bitmap to contain information describing the
position and size of each tile, in the form of a bounding box drawn in color
255. The most reliable way to do this is to fill all the image except the
parts you want with color 255, but the grabber should be able to understand
more complicated layouts, even if you simply draw color 255 lines along the
top and left edges of the area you want to be grabbed. For truecolor images
where color 255 is not particularly meaningful, use a cyan bounding box
(maximum blue and green, zero red), with a single yellow (maximum red and
green, zero blue) pixel in the top left corner of the box.



]]></text></section><section title="Configuration"><text><![CDATA[
By default, the grabber will run in a 640x480 resolution, using the highest
color depth possible on your graphics card. If you want to override this,
you can specify an alternative color depth or resolution on the commandline,
eg. "grabber -8" for a 256 color mode, "grabber -16" for 16 bit hicolor
graphics, "grabber -320x200" to use VGA mode 13h, or "grabber 1024x768".
Warning: editing datafiles that contain truecolor graphics is very slow in
256 color video modes, and the grabber is not really usable in resolutions
lower than 640x400.

You can configure the grabber to use external tools for editing data, by
setting some variables in the [grabber] section of the allegro.cfg file.
These are in the form "type=command", where the type is a four letter object
ID, and the command is whatever program you want to be invoked to edit this
kind of data. For these variables to be seen, the allegro.cfg file must
either be in the same directory as the grabber executable, or in the
directory pointed to by your ALLEGRO environment variable. To invoke this
feature, select the Shell Edit command or press ctrl+Z. The grabber will try
to invoke the tool on the original version of the file if it knows where you
grabbed the data from in the first place, or otherwise it will write the
object out into a temporary file prior to editing.



]]></text></section><section title="Saving datafiles"><text><![CDATA[
Datafiles can be saved using any of three compression types, selected from
the list at the top right of the grabber screen, or with the '-c0', '-c1',
and '-c2' options to dat. With type 0, the data is not compressed at all.
Type 1 compresses each object individually, while type 2 uses global
compression over the entire file. As a rule, global compression will give
better results than per-object compression, but it should not be used if you
intend to dynamically load specific objects with the load_datafile_object()
function or "filename.dat#objectname" packfile syntax.

There are also three strip modes for saving datafiles, selected with the
File/Save Stripped command in the grabber, or using the '-s0', '-s1', and
'-s2' options to dat. With zero stripping, all object properties are written
to the datafile, which is normally what you will want. With strip mode 1,
properties specific to the grabber (the ones describing the origins and
dates of each object) are removed, which will marginally reduce the file
size, but will prevent the update command from working. For the smallest
possible file sizes, strip mode 2 removes all properties, including object
names and any custom properties you have added. This level of stripping
should obviously be used with extreme caution, although in some cases it may
be possible to recover the object names even after they have been stripped
out of the datafile. If the grabber and dat utilities cannot find any name
properties in a datafile, they will look for a header (.h) file with the
same name, and attempt to parse this to recover the names. This is far from
foolproof, and will not work for nested datafiles, but in some situations
it allows the names to be read back from the index definition header. In
addition to those three strip modes, you can define properties to be kept,
whatever the strip mode. For example, if you want to strip all properties
but the NAME, this command will do the job:

<pre class="text">
   dat -s2 -s-NAME file.dat
</pre>

The objects of the datafile can be sorted alphabetically by name. This is
selected by the Sort checkbox in the grabber, or by using the '-n0' and
'-n1' options to dat. With zero sorting, objects are listed in the order
they were added to the datafile. With sort level 1, they are listed in
alphabetical order according to their NAME property, including inside
nested datafiles.



]]></text></section><section title="Updating datafiles"><text><![CDATA[
Both the grabber and the dat utility have an update command, which scans
through the datafile checking if any objects have changed, and replacing
those which are out of date. This depends on the origin and date properties
which were set when the data was grabbed in the first place, so it won't
work if these properties have been stripped out of the file. This command
can be very useful if you build a datafile containing hundreds of objects
grabbed from external bitmaps, and later go back and change some of these
bitmaps. Rather than having to figure out which objects are out of date and
then manually re-grab all the affected data, the update command will
automatically refresh the modified objects.



]]></text></section><section title="Fonts"><text><![CDATA[
Fonts can be read from GRX format .fnt files, 8x8 or 8x16 BIOS format .fnt
files, and from bitmap images, 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. 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:

<pre class="text">
   ascii.fnt 0x20 0x7F
   - 0xA0 0xFF
   dingbats.fnt 0x1000
</pre>

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.

When reading a font from a bitmap file, 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),
unless you are using the script mechanism described above, in which case the
range(s) should match the one(s) specified in the .txt file. The spaces
between each letter should be filled with color 255. If each character is
sized exactly 8x8 or 8x16 the grabber will create a fixed size font,
otherwise it will make a proportional font. 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...



]]></text></section><section title="Alpha channel"><text><![CDATA[
Bitmap and RLE sprites can store an alpha channel along with the color
information, as long as they are in a 32 bit format. Alpha data can be read
directly from 32 bit TGA files, or you can use the alpha channel commands
(in the Object menu, or the right mouse button popup menu) to import a
greyscale alpha image over the top of an existing object. This menu also
contains options for viewing the alpha channel of the selected object,
exporting the alpha data to a greyscale image file, and deleting the alpha
data to leave only pure color information. You can also use the File menu to
import an alpha channel over the top of a bitmap that you have loaded with
the Read Bitmap command, after which the alpha information will be included
when you next perform a Grab or Grab From Grid operation.



]]></text></section><section title="Datafile passwords"><text><![CDATA[
Datafiles can be encrypted with a password, by typing it into the
"Password:" field in the grabber, or using the '-007 password' option to the
dat utility. Passwords may be up to 256 characters in length, and are case
sensitive. Encrypted files _cannot_ be read without the password, so please
don't forget it and then come crying to me for help :-) To read an encrypted
file into your program, call the packfile_password() function before
load_datafile(). It is also a good idea to call packfile_password(NULL)
afterwards, to set everything back to normal.



]]></text></section></section><section title="dat - Manipulate datafiles from the commandline"><section title="Commandline options"><text><![CDATA[
As an alternative to the graphical grabber program, you can use the command
line dat utility. This accepts the following options:

   '-a &lt;files&gt;'

      Adds the named files to the datafile, for example:

<pre class="text">
	 dat myfile.dat -a title.pcx scream.wav
</pre>

      If the objects are already present in the datafile, their current
      contents will be replaced. Names for the new objects will be generated
      from the input filenames, and the object type will be detected from
      the file extensions. In some cases this is ambiguous, for example a
      PCX file can be read as a bitmap, RLE sprite, compiled sprite, or font
      object, so you may need to explicitly specify the object type with the
      '-t' flag. For example, to insert alien.pcx as an RLE sprite, use the
      command:

<pre class="text">
	 dat myfile.dat -a alien.pcx -t RLE
</pre>

   '-bpp colordepth'
      Specifies which color format bitmap data should be grabbed in (valid
      depths are 8, 15, 16, 24, and 32 bits per pixel).

   '-c0' - no compression

   '-c1' - compress objects individually

   '-c2' - global compression on the entire datafile

      Sets the compression mode (see below). These can be used on their own
      to convert a datafile from one format to another, or in combination
      with any other options.

   '-d &lt;objects&gt;'

      Deletes the named objects from the datafile.

   '-dither'

      Dithers graphics when reducing color depths.

   '-e &lt;objects&gt;'

      Extracts the named objects from the datafile. To extract everything,
      use the wildcard * as the object name. To set the output filename or
      directory, use the '-o filename' option. For example, to extract an
      object called TITLE_SCREEN to the file title.pcx, use the command:

<pre class="text">
	 dat myfile.dat -e title_screen -o title.pcx
</pre>

      To extract the entire contents of the datafile to the directory
      c:\output, use:

<pre class="text">
	 dat myfile.dat -e * -o c:\output\
</pre>

   '-f'

      Stores the references to original files as relative filenames instead of
      absolute filenames. This greatly increases the portability of complete
      source trees containing the source data.

   '-g x y w h'

      Grabs bitmap data from a specific grid location.

   '-h outputfile.h'

      Sets the output header file, for exporting object index definitions.
      This may be used on its own to produce a header file from an existing
      datafile, or in combination with any other commands. You can also use
      the '-p prefixstring' option to set a prefix string for the object
      definitions.

   '-k'

      Keep original names while grabbing objects. Without this switch, a
      file called image.pcx will be imported as an object called IMAGE_PCX,
      to ensure that all the object names are valid symbols for the output
      header defines.

   '-l'

      Lists the contents of the datafile. This can be combined with the '-v'
      option to list object properties along with the names, and you can
      specify particular objects to produce a partial listing.

   '-m dependencyfile'

      Writes a set of makefile dependencies into the specified file, which
      can be used to automatically update the file whenever any of the
      source data changes.

   '-n0' - no sort: list the objects in the order they were added

   '-n1' - sort the objects of the datafile alphabetically by name

      Sets the sort mode (see below). These can be used on their own to
      sort the objects of the datafile, or in combination with any other
      options.

   '-o output'

      Sets the output file or directory when extracting data.

   '-p prefixstring'

      Sets the prefix for the output header file.

   '-pal objectname'

      Specifies which palette to use.

   '-r'

      Recursively adds directories as nested datafiles. This makes it possible
      to maintain the data hierarchy within the datafile.

   '-s0' - no strip: save everything

   '-s1' - strip grabber specific information from the file

   '-s2' - strip all object properties and names from the file

   '-s-PROP' do not strip object property PROP from the file

      Sets the strip mode (see below). These can be used on their own to
      strip properties from the datafile, or in combination with any other
      options.

   '-t type'

      Sets the object type when adding files.

   '-transparency'

      Preserves transparency when converting between color depths.

   '-u'

      Updates the contents of the datafile. See below.

   '-v'

      Selects verbose mode. This can be used in combination with any other
      options to produce more detailed output.

   '-w'

      Always updates the entire contents of the datafile.

   '-x &lt;objects&gt;'

      Alias for '-e &lt;objects&gt;'.

   '-007 password'

      Sets the file encryption key.

   '&lt;objects&gt; PROP=value'

      Sets properties for the specified objects. This works like environment
      variables, in that setting a property to an empty string removes it.
      Because object names are stored as NAME properties, you can use this
      command to rename objects. For example, to rename MY_OBJECT to
      WHAT_A_SILLY_NAME, use the command:

<pre class="text">
	 dat myfile.dat my_object NAME=what_a_silly_name
</pre>

      You can use the wildcard * to apply the property to everything in the
      file, so to remove the ORIG property from the entire datafile, you
      could execute:

<pre class="text">
	 dat myfile.dat * ORIG=
</pre>

You can create hierarchical nested datafiles by inserting one datafile into
another with the '-a' command. Objects in the nested datafile can then be
referred to by as "parentname/objectname". For example if the datafile
myfile.dat contains a nested datafile called nestedfile, which contains a
bitmap called thepicture, you could export the bitmap with the command:

<pre class="text">
	 dat myfile.dat -e nestedfile/thepicture -o output.pcx
</pre>



]]></text></section></section><section title="dat2s - Compile datafiles into assembler code"><section title="Compiling Datafiles to Assembler"><text><![CDATA[

The utility dat2s can be used to convert a datafile into an asm (.s) source
file, which can then be assembled and linked into your program. This avoids
the need for a separate datafile to accompany your program, and means the
data will automatically be loaded into memory at startup. You should be
aware, though, that large datafiles can take a long time to compile, and
that it is not possible to compress data which is compiled in this way.

The simplest way to invoke dat2s is with the command:

   dat2s filename.dat -o output.s

The resulting asm file can then be assembled with the command:

   gcc -c output.s

This will produce an object module called output.o, which can be linked into
your program, for example:

   gcc myprog.c -o myprog.exe output.o -lalleg

Your program can then access the contents of the datafile as simple global
variables. Definitions for these variables can be obtained by telling dat2s
to output a header file as well as the asm file, with the '-h' option. You
can also use '-p' to set a prefix string for all the object names. For
example, when applied to the datafile:

   "BMP"  - A_BITMAP
   "BMP"  - ANOTHER_BITMAP
   "SAMP" - EXPLODE
   "PAL"  - SOME_COLORS
   "FONT" - THE_FONT

the command:

   dat2s filename.dat -o output.s -h output.h -p item

produces the header:

   extern BITMAP item_a_bitmap;
   extern BITMAP item_another_bitmap;
   extern SAMPLE item_explode;
   extern PALETTE item_some_colors;
   extern FONT item_the_font;
   extern DATAFILE item_data[];

You can refer to these objects directly, for example:

   blit(&amp;item_a_bitmap, screen, 0, 0, 0, 0, SCREEN_W, SCREEN_H);

Alternatively, you can use the datafile array for compatibility with code
that was originally written for separately loaded datafiles, with the
standard syntax item_data[index].dat.

If your datafile contains truecolor images, be sure to call fixup_datafile()
after you have set the graphics mode. You must also call fixup_datafile()
if your platform does not support constructors (currently any non GCC-based
platform).

Note that compiled sprites are not supported and will cause dat2s to
abort whenever it encounters one of them. However you can use the '-S'
option to instruct dat2s to convert them to regular BITMAP objects.

Note that datafiles compiled by dat2s must not be appended to shared objects,
only to standalone executables. Use dat2c for this purpose.



]]></text></section></section><section title="dat2c - Compile datafiles into C code"><section title="Contents"/><section title="Introduction"><text><![CDATA[

The utility dat2c can be used in much the same way as dat2s, above, except
that it writes C code rather than assembler. This has the advantage that it
is portable - you can compile it anywhere you can use Allegro.



]]></text></section><section title="Commandline Options"><text><![CDATA[

Each option may appear only once. To specify which datafile to convert,
give the filename without a preceding option.

--cfile, -o
    Arguments: filename

    Gives the name of the C source file to output. Won't add a .c
    extension, even if you don't specify one. By default, dat2c will
    write to stdout.

--hfile, -h
    Arguments: filename

    Gives the name of the C header file to output. Won't add a .h
    extension, even if you don't specify one.

--prefix, -p
    Arguments: prefix (must be a valid macro name)

    If you specify a prefix, then this will be used when constructing a
    macro name for each object in the datafile. This is the same as the
    grabber; if you don't specify a prefix, the macro name is simply
    &lt;obj_name&gt;, but if you do, then the macro name becomes
    &lt;prefix&gt;_&lt;obj_name&gt; .

--crlf, -C
    Arguments: none

    Forces the file to be output in CRLF (DOS) format. This is the
    default on DOS/Windows platforms.

--unix, -U
    Arguments: none

    Sets the output to be in Unix (LF only) text format. This is the
    default on non-DOS non-Mac platforms.

--mac, -M
    Arguments: none

    Sets the output to be in Macintosh (CR only) text format. This is
    the default on Mac platforms.

--global, -g
    Arguments: none

    Specifies that the objects should be globally visible (default is
    for objects to be local to the compilation unit). If they are
    globally visible, then you can refer to them in your code.

--convert-compiled-sprites, -S
    Arguments: none

    (See note below for more info on compiled sprites). Tells dat2c to
    convert any compiled sprite objects it finds into bitmap objects.
    More a convenience feature for lazy people :-)

--datafile-name, -n
    Arguments: C identifier

    By default, the datafile is exported as:
        PREFIX_data
    or  data
    But with this option, you can change 'data' to be something else.



]]></text></section><section title="Notes"><text><![CDATA[
 - If your datafile contains truecolor images, be sure to call
   fixup_datafile() after you have set the graphics mode. You must
   also call fixup_datafile() if your platform does not support
   constructors (currently any non GCC-based platform).

 - Compiled sprites are *not* supported (but see the commandline option
   --convert-compiled-sprites , above). This is because Allegro silently
   switches to an RLE_SPRITE implementation on platforms which don't
   support compiled sprites, and to get dat2c to implement that behaviour
   would be more effort than it is worth (especially since you can just
   call get_compiled_sprite() anyway!).
]]></text></section></section></section><section title="Community"><text><![CDATA[
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 CVS 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 CVS? 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 nescessary 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 :-)



]]></text></section><section title="Conclusion"><text><![CDATA[
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.

<a href="http://alleg.sourceforge.net/">http://alleg.sourceforge.net/</a>



]]></text></section><section title="Index"><index/></section></doc>
