@# @# This is the source for the Allegro docs, in a weird custom format. @# Read makedoc.c for a description of what is going on... @# @# If you want to put everything in one big HTML file rather than splitting @# it into sections, remove this 'multiplefiles' statement: @# @multiplefiles @# @# Uncomment the following statement to output css clean html files. @# @#ignore_css @# @html_text_substitution=readme.txt|readme.txt @html_text_substitution=grabber.txt|grabber.txt @html_text_substitution=AUTHORS|AUTHORS @external-css=allegro.css @document_title=Allegro Manual @html_footer=Back to contents @rtfh=Allegro - a game programming library @manh="version 4.2.0" "Allegro" "Allegro manual" @mans=#include @man_shortdesc_force1=allegro @man_shortdesc_force2=Allegro game programming library. @$\input texinfo @$@setfilename allegro.inf @$@settitle Allegro Manual @$@setchapternewpage odd @$@paragraphindent 0 @$@setchapternewpage off @# This should remain commented at the moment (dvi output) @$@finalout @$ @$@ifinfo @$@dircategory Libraries @$@direntry @$* Allegro: (allegro). The Allegro game programming library. @$@end direntry @$This is the Info version of the Allegro manual @$ @$By Shawn Hargreaves @$@end ifinfo @$ @$@node Top, , (dir), (dir) @titlepage @
@!indent
     ______   ___    ___
    /\  _  \ /\_ \  /\_ \
    \ \ \L\ \\//\ \ \//\ \      __     __   _ __   ___ 
     \ \  __ \ \ \ \  \ \ \   /'__`\ /'_ `\/\`'__\/ __`\
      \ \ \/\ \ \_\ \_ \_\ \_/\  __//\ \L\ \ \ \//\ \L\ \
       \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
	\/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
				       /\____/
				       \_/__/     Version 4.2.0


		A game programming library.

	     By Shawn Hargreaves, Nov 05, 2005.

		See the AUTHORS file for a
	       complete list of contributors.
@indent
@
#include <std_disclaimer.h>
"I do not accept responsibility for any effects, adverse or otherwise, that this code may have on you, your computer, your sanity, your dog, and anything else that you can think of. Use it at your own risk."
@!titlepage @!text @heading Contents @contents @text @externalfile readme A general introduction to Allegro @chapter API @heading Using Allegro See readme.txt for a general introduction, copyright details, and information about how to install Allegro and link your program with it. @@int @install_allegro(int system_id, int *errno_ptr, int (*atexit_ptr)()); @xref allegro_init, allegro_exit, set_uformat, set_config_file @shortdesc Initialise the Allegro library. 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: install_allegro(SYSTEM_AUTODETECT, &errno, atexit); @retval 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. @@int @allegro_init(); @xref install_allegro, allegro_exit @eref Available Allegro examples @shortdesc Macro to initialise the Allegro library. Macro which initialises the Allegro library. This is the same thing as calling install_allegro(SYSTEM_AUTODETECT, &errno, atexit). @@void @allegro_exit(); @xref install_allegro, allegro_init, destroy_bitmap @eref ex3d, exscn3d, exswitch, exxfade, exzbuf @shortdesc Closes down the Allegro system. 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. @@Macro @END_OF_MAIN() @xref Windows specifics, Unix specifics, MacOS X specifics @xref Differences between platforms @eref Available Allegro examples @shortdesc Macro to put after your main() function. 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: int main(void) { allegro_init(); /* more stuff goes here */ ... return 0; } END_OF_MAIN() @@extern char @allegro_id[]; @shortdesc String containing date and version number of Allegro. Text string containing a date and version number for the library, in case you want to display these somewhere. @@extern char @allegro_error[ALLEGRO_ERROR_SIZE]; @xref set_gfx_mode, install_sound @eref Available Allegro examples @shortdesc Stores the last Allegro error message. 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: 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!"); @@#define @ALLEGRO_VERSION @shortdesc Defined to the major version of Allegro. Defined to the major version of Allegro. From a version number like 4.1.16, this would be defined to the integer 4. @@#define @ALLEGRO_SUB_VERSION @shortdesc Defined to the middle version of Allegro. Defined to the middle version of Allegro. From a version number like 4.1.16, this would be defined to the integer 1. @@#define @ALLEGRO_WIP_VERSION @shortdesc Defined to the minor version of Allegro. Defined to the minor version of Allegro. From a version number like 4.1.16, this would be defined to the integer 16. @@#define @ALLEGRO_VERSION_STR @shortdesc Defined to a string with the full Allegro version number. 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. @@#define @ALLEGRO_DATE_STR @shortdesc Defined to a string with the year Allegro was released. Defined to a text string containing the year this version of Allegro was released, like `2004'. @@#define @ALLEGRO_DATE @shortdesc Defined to a number with the release date of Allegro. Defined to an integer containing the release date of Allegro in the packed format `yyyymmdd'. Example: const int year = ALLEGRO_DATE / 10000; const int month = (ALLEGRO_DATE / 100) % 100; const int day = ALLEGRO_DATE % 100; allegro_message("Year %d, month %d, day %d\n", year, month, day); @@Macro @AL_ID(a,b,c,d) @shortdesc Converts four 8 bit values to a packed 32 bit integer ID. @xref DAT_ID 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: #define OSTYPE_LINUX AL_ID('T','U','X',' ') @@Macro @MAKE_VERSION(a, b, c) @shortdesc Create a 32 bit integer from the Allegro version @xref ALLEGRO_VERSION, ALLEGRO_SUB_VERSION, ALLEGRO_WIP_VERSION This macro can be used to check if some Allegro version is (binary) compatible with the current version. It is safe to use > and < to check if one version is more recent than another. The third number is ignored if the second number is even, so MAKE_VERSION(4, 2, 0) is equivalent to MAKE_VERSION(4, 2, 1). This is because of our version numbering policy since 4.0.0: the second number is even for stable releases, which must be ABI-compatible with earlier versions of the same series. This macro is mainly useful for addon packages and libraries. See the `ABI compatibility information' section of the manual for more detailed information. Example: /* Check if the current version is compatible with Allegro 4.2.0 */ #if (MAKE_VERSION(4, 2, 0) <= MAKE_VERSION(ALLEGRO_VERSION, \ ALLEGRO_SUB_VERSION, ALLEGRO_WIP_VERSION)) /* Allegro 4.2.0 compatibility */ #else /* Work-around */ #endif @@extern int @os_type; @xref allegro_init, os_version, os_multitasking @shortdesc Stores the detected type of the OS. Set by allegro_init() to one of the values: 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_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 @@extern int @os_version; @@extern int @os_revision; @xref os_type, os_multitasking @shortdesc Version of the OS currently running. 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. @@extern int @os_multitasking; @xref os_type, os_version @shortdesc Indicates if the OS is multitasking. Set by allegro_init() to either TRUE or FALSE depending on whether your Operating System is multitasking or not. @@void @allegro_message(const char *text_format, ...); @xref allegro_init, install_allegro, set_uformat @eref Available Allegro examples @shortdesc Used mainly to show error messages to users. 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: if (allegro_init() != 0) exit(1); if (init_my_data() != 0) { allegro_message("Sorry, missing game data!\n"); exit(2); } @@void @set_window_title(const char *name); @xref set_close_button_callback, set_uformat @eref exunicod @shortdesc Sets the window title of the Allegro program. 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: set_window_title("Allegro rules!"); @@int @set_close_button_callback(void (*proc)(void)); @xref set_window_title @shortdesc Handles the user clicking on the close button of the window. 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: 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(); @retval Returns zero on success and non-zero on failure (e.g. the feature is not supported by the platform). @@int @desktop_color_depth(); @xref get_desktop_resolution, set_color_depth, set_gfx_mode @shortdesc Finds out the desktop color depth. Finds out the currently selected desktop color depth. You can use this information to make your program use the same color depth as the desktop, which will likely make it run faster because the graphic driver won't be doing unnecessary color conversions behind your back. Under some OSes, switching to a full screen graphics mode may automatically change the desktop color depth. You have, therefore, to call this function before setting any graphics mode in order to retrieve the real desktop color depth. Example: allegro_init(); ... if ((depth = desktop_color_depth()) != 0) { set_color_depth(depth); } @retval Returns the color depth or zero on platforms where this information is not available or does not apply. @@int @get_desktop_resolution(int *width, int *height); @xref desktop_color_depth, set_gfx_mode @shortdesc Finds out the desktop resolution. 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: int width, height; allegro_init(); ... if (get_desktop_resolution(&width, &height) == 0) { /* Got the resolution correctly */ } @retval 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. @@void @check_cpu(); @xref cpu_vendor, cpu_family, cpu_model, cpu_capabilities, allegro_init @shortdesc Detects the CPU type. 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. @@extern char @cpu_vendor[]; @xref check_cpu, cpu_family, cpu_model, cpu_capabilities, allegro_init @shortdesc Contains the CPU vendor name. 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()). @@extern int @cpu_family; @xref check_cpu, cpu_vendor, cpu_model, cpu_capabilities, allegro_init @shortdesc Contains the CPU type. Contains the Intel type, where applicable. Allegro defines the following CPU family types: 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 You can read this variable after you have called check_cpu() (which is automatically called by allegro_init()). @@extern int @cpu_model; @xref check_cpu, cpu_vendor, cpu_family, cpu_capabilities, allegro_init @shortdesc Contains the Intel CPU submodel. 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): 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 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. @@extern int @cpu_capabilities; @xref check_cpu, cpu_vendor, cpu_family, cpu_model, cpu_capabilities, @xref allegro_init @shortdesc Contains the capability flags of the CPU. Contains CPU flags indicating what features are available on the current CPU. The flags can be any combination of these: 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. 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: if ((cpu_capabilities & (CPU_FPU | CPU_MMX)) == (CPU_FPU | CPU_MMX)) { printf("CPU has both an FPU and MMX instructions!\n"); } You can read this variable after you have called check_cpu() (which is automatically called by allegro_init()). @heading Structures and types defined by Allegro There are several structures and types defined by Allegro which are used in many functions (like the BITMAP structure). This section of the manual describes their useful content from a user point of view when they don't fit very well any of the existing manual sections, and redirects you to the 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. @@typedef long @fixed @xref Fixed point math routines @eref ex12bit, ex3buf, ex3d, excustom, exfixed, exspline, exsprite @eref exstars, exupdate @shortdesc Fixed point integer to replace floats. 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. @@typedef struct @BITMAP @xref create_bitmap, set_clip_rect, bitmap_color_depth, RLE_SPRITE @xref COMPILED_SPRITE, Direct access to video memory @eref Available Allegro examples @shortdesc Stores the contents of a bitmap. 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 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: bmp = load_bitmap("file.bmp", pal); allegro_message("Bitmap size: (%dx%d)\n", bmp->w, bmp->h); 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. @@typedef struct @RLE_SPRITE @xref get_rle_sprite, BITMAP, COMPILED_SPRITE, RLE sprites @shortdesc Stores the contents of an RLE sprite. int w, h; - width and height in pixels int color_depth; - color depth of the image 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. @@typedef struct @COMPILED_SPRITE @xref get_compiled_sprite, BITMAP, RLE_SPRITE, Compiled sprites @shortdesc Stores the contents of a compiled sprite. 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 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. @@typedef struct @JOYSTICK_INFO @xref joy, Joystick routines @shortdesc Stores information about joysticks. 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 Read chapter "Joystick routines" for a description on how to obtain/use this structure. @@typedef struct @JOYSTICK_BUTTON_INFO @xref joy, Joystick routines @shortdesc Stores joystick button information. int b; - boolean on/off flag char *name; - description of this button Read chapter "Joystick routines" for a description on how to obtain/use this structure. @@typedef struct @JOYSTICK_STICK_INFO @xref joy, Joystick routines @shortdesc Stores joystick stick information. 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 Read chapter "Joystick routines" for a description on how to obtain/use this structure. @@typedef struct @JOYSTICK_AXIS_INFO @xref joy, Joystick routines @shortdesc Stores joystick axis information. int pos; - analogue axis position int d1, d2; - digital axis position char *name; - description of this axis Read chapter "Joystick routines" for a description on how to obtain/use this structure. @@typedef struct @GFX_MODE_LIST @xref GFX_MODE, get_gfx_mode_list @shortdesc Stores an array of GFX_MODE structures. int num_modes; GFX_MODE *mode; Structure returned by get_gfx_mode_list, which contains an array of GFX_MODE structures. @@typedef struct @GFX_MODE @xref GFX_MODE_LIST, get_gfx_mode_list @shortdesc Stores video mode information. int width, height, bpp; Structure contained in GFX_MODE_LIST. @@#define @PAL_SIZE @xref RGB, PALETTE, COLOR_MAP @shortdesc Number of entries in a palette. Preprocessor constant equal to 256. @@typedef @PALETTE RGB[PAL_SIZE] @xref RGB, Palette routines @eref Available Allegro examples @shortdesc Stores palette information. Allegro palettes are arrays of PAL_SIZE RGB entries. @@typedef struct @RGB @xref Palette routines, PALETTE @eref ex12bit, ex3d, excolmap, exconfig, expal, exrgbhsv, exscroll @eref exshade, extrans, extruec @shortdesc Single palette entry. unsigned char r, g, b; 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. @@typedef struct @V3D @xref V3D_f, polygon3d, Fixed point trig @eref ex3d @shortdesc Fixed point vertex structure used by 3d functions. fixed x, y, z; - position fixed u, v; - texture map coordinates int c; - color 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. @@typedef struct @V3D_f @xref V3D, polygon3d_f, Fixed point trig @eref excamera, exscn3d, exzbuf @shortdesc Floating point vertex structure used by 3d functions. float x, y, z; - position float u, v; - texture map coordinates int c; - color 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. @@typedef struct @COLOR_MAP @xref 256-color transparency, color_map @eref ex3d, excolmap, exlights, exshade, extrans @shortdesc Stores a color map to accelerate drawing. unsigned char data[PAL_SIZE][PAL_SIZE]; Read chapter "Transparency and patterned drawing", section "256-color transparency" for a description on how to obtain/use this structure. @@typedef struct @RGB_MAP @xref Converting between color formats, create_rgb_table @eref ex3d, excolmap, exrgbhsv, exshade, extrans @shortdesc Stores an rgb map to accelerate conversions. unsigned char data[32][32][32]; Read chapter "Converting between color formats" for a description on how to obtain/use this structure. @@struct @al_ffblk @xref al_findfirst @shortdesc Cross platform structure storing file information. int attrib; - actual attributes of the file found time_t time; - modification time of file long size; - size of file char name[512]; - name of file Read the description of al_findfirst for a description on how to obtain/use this structure. @@typedef struct @DATAFILE @xref load_datafile, Using datafiles @eref excustom, exdata, exexedat, exgui, exsprite, exunicod @shortdesc Stores an Allegro datafile in memory. 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 Read chapter "Datafile routines", section "Using datafiles" for a description on how to obtain/use this structure. @@typedef struct @MATRIX @xref MATRIX_f, 3D math routines @eref ex12bit, ex3d, exstars @shortdesc Fixed point matrix structure. fixed v[3][3]; - 3x3 scaling and rotation component fixed t[3]; - x/y/z translation component Fixed point matrix structure. Read chapter "3D math routines" for a description on how to obtain/use this structure. @@typedef struct @MATRIX_f @xref MATRIX, 3D math routines @eref excamera, exquat, exscn3d, exzbuf @shortdesc Floating point matrix structure. float v[3][3]; - 3x3 scaling and rotation component float t[3]; - x/y/z translation component Floating point matrix structure. Read chapter "3D math routines" for a description on how to obtain/use this structure. @@typedef struct @QUAT @xref Quaternion math routines @eref exquat @shortdesc Stores quaternion information. float w, x, y, z; Read chapter "Quaternion math routines" for a description on how to obtain/use this structure. @@typedef struct @DIALOG @xref do_dialog, GUI routines @eref excustom, exgui, exrgbhsv @shortdesc Stores a GUI description. 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 This is the structure which contains a GUI object. Read chapter "GUI routines" for a description on how to obtain/use this structure. @@typedef struct @MENU @xref do_menu, GUI menus @eref exgui @shortdesc Stores the entries of a menu. 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 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. @@typedef struct @DIALOG_PLAYER @xref init_dialog, update_dialog, shutdown_dialog, GUI routines @shortdesc Stores GUI data internally used by Allegro. 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. @@typedef struct @MENU_PLAYER @xref init_menu, update_menu, shutdown_menu, GUI menus @shortdesc Stores GUI data internally used by Allegro. 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. @@typedef struct @FONT @xref font @eref excustom, exfont, exunicod @shortdesc Stores an Allegro font. A structure holding an Allegro font, usually created beforehand with the grabber tool or Allegro's default font. Read chapter "Fonts" for a description on how to load/destroy fonts, and chapter "Text output" for a description on how to show text. @@typedef struct BITMAP @ZBUFFER @xref Zbuffered rendering, BITMAP @eref exzbuf @shortdesc Stores 3d zbuffer information. 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. @@typedef struct @SAMPLE @xref load_sample, Digital sample routines, Voice control @eref exsample @shortdesc Stores sound data. 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 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. @@typedef struct @MIDI @xref load_midi, Music routines (MIDI) @eref exmidi @shortdesc Stores MIDI data. A structure holding MIDI data. Read chapter "Music routines (MIDI)" for a description on how to obtain/use this structure. @@typedef struct @AUDIOSTREAM @xref play_audio_stream, Audio stream routines, Voice control @eref exstream @shortdesc Stores an audiostream. int voice; - the hardware voice used for the sample 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. @@typedef struct @PACKFILE @xref File and compression routines, pack_fopen, pack_fopen_chunk @xref pack_fopen_vtable @eref expackf @shortdesc Packfile structure, similar to the libc FILE structure. 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. @@typedef struct @PACKFILE_VTABLE @xref File and compression routines, pack_fopen_vtable @eref expackf @shortdesc Packfile vtable structure, for custom packfiles. 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); 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. @@typedef struct @LZSS_PACK_DATA @xref File and compression routines, create_lzss_pack_data @shortdesc Opaque structure for handling LZSS comression. Opaque structure for handling LZSS compression. Read chapter "File and compression routines for a description on how to obtain/use this structure. @@typedef struct @LZSS_UNPACK_DATA @xref File and compression routines, create_lzss_unpack_data @shortdesc Opaque structure for handling LZSS decomression. Opaque structure for handling LZSS decompression. Read chapter "File and compression routines for a description on how to obtain/use this structure. @heading Unicode routines Allegro can manipulate and display text using any character values from 0 right up to 2^32-1 (although the current implementation of the grabber can only create fonts using characters up to 2^16-1). You can choose between a number of different text encoding formats, which controls how strings are stored and how Allegro interprets strings that you pass to it. This setting affects all aspects of the system: whenever you see a function that returns a char * type, or that takes a char * as an argument, that text will be in whatever format you have told Allegro to use. By default, Allegro uses UTF-8 encoded text (U_UTF8). This is a variable-width format, where characters can occupy anywhere from one to four bytes. The nice thing about it is that characters ranging from 0-127 are encoded directly as themselves, so UTF-8 is upwardly compatible with 7-bit ASCII ("Hello, World!" means the same thing regardless of whether you interpret it as ASCII or UTF-8 data). Any character values above 128, such as accented vowels, the UK currency symbol, and Arabic or Chinese characters, will be encoded as a sequence of two or more bytes, each in the range 128-255. This means you will never get what looks like a 7-bit ASCII character as part of the encoding of a different character value, which makes it very easy to manipulate UTF-8 strings. There are a few editing programs that understand UTF-8 format text files. Alternatively, you can write your strings in plain ASCII or 16-bit Unicode formats, and then use the Allegro textconv program to convert them into UTF-8. If you prefer to use some other text format, you can set Allegro to work with normal 8-bit ASCII (U_ASCII), or 16-bit Unicode (U_UNICODE) instead, or you can provide some handler functions to make it support whatever other text encoding you like (for example it would be easy to add support for 32 bit UCS-4 characters, or the Chinese GB-code format). There is some limited support for alternative 8-bit codepages, via the U_ASCII_CP mode. This is very slow, so you shouldn't use it for serious work, but it can be handy as an easy way to convert text between different codepages. By default the U_ASCII_CP mode is set up to reduce text to a clean 7-bit ASCII format, trying to replace any accented vowels with their simpler equivalents (this is used by the allegro_message() function when it needs to print an error report onto a text mode DOS screen). If you want to work with other codepages, you can do this by passing a character mapping table to the set_ucodepage() function. Note that you can use the Unicode routines before you call install_allegro() or allegro_init(). If you want to work in a text mode other than UTF-8, it is best to set it with set_uformat() just before you call these. @@void @set_uformat(int type); @xref get_uformat, register_uformat, set_ucodepage, set_uformat, uconvert @xref ustrsize, ugetc, ugetx, usetc, uwidth, ucwidth, uisok, uoffset @xref ugetat, usetat, uinsert, uremove, allegro_init @eref exunicod @shortdesc Set the global current text encoding format. 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: 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 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. @@int @get_uformat(void); @xref set_uformat @shortdesc Finds out what text encoding format is currently selected. 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: switch(get_uformat()) { case U_ASCII: do_something(); break; case U_UTF8: do_something_else(); break; ... } @retval Returns the currently selected text encoding format. See the documentation of set_uformat() for a list of encoding formats. @\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)); @xref set_uformat, uconvert, ugetc, ugetx, usetc, uwidth, ucwidth, uisok @shortdesc Installs handler functions for a new text encoding format. 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. @\void @set_ucodepage(const unsigned short *table, @@ const unsigned short *extras); @xref set_uformat @shortdesc Sets 8-bit to Unicode conversion tables. When you select the U_ASCII_CP encoding mode, a set of tables are used to convert between 8-bit characters and their Unicode equivalents. You can use this function to specify a custom set of mapping tables, which allows you to support different 8-bit codepages. The `table' parameter points to an array of 256 shorts, which contain the Unicode value for each character in your codepage. The `extras' parameter, if not NULL, points to a list of mapping pairs, which will be used when reducing Unicode data to your codepage. Each pair consists of a Unicode value, followed by the way it should be represented in your codepage. The list is terminated by a zero Unicode value. This allows you to create a many->one mapping, where many different Unicode characters can be represented by a single codepage value (eg. for reducing accented vowels to 7-bit ASCII). Allegro will use the `table' parameter when it needs to convert an ASCII string to an Unicode string. But when Allegro converts an Unicode string to ASCII, it will use both parameters. First, it will loop through the `table' parameter looking for an index position pointing at the unicode value it is trying to convert (ie. the `table' parameter is also used for reverse matching). If that fails, the `extras' list is used. If that fails too, Allegro will put the character `^', giving up the conversion. Note that Allegro comes with a default `table' and `extras' parameters set internally. The default `table' will convert 8-bit characters to `^'. The default `extras' list reduces Latin-1 and Extended-A characters to 7 bits in a sensible way (eg. an accented vowel will be reduced to the same vowel without the accent). @@int @need_uconvert(const char *s, int type, int newtype); @xref set_uformat, get_uformat, do_uconvert, uconvert @shortdesc Tells if a string requires encoding conversion. 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: if (need_uconvert(text, U_UTF8, U_CURRENT)) { /* conversion is required */ } @retval Returns non-zero if any conversion is required or zero otherwise. @@int @uconvert_size(const char *s, int type, int newtype); @xref need_uconvert, do_uconvert @shortdesc Number of bytes needed to store a string after conversion. 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: length = uconvert_size(old_string, U_CURRENT, U_UNICODE); new_string = malloc(length); ustrcpy(new_string, old_string); @retval Returns the number of bytes required to store the string after conversion. @\void @do_uconvert(const char *s, int type, @@ char *buf, int newtype, int size); @xref uconvert @shortdesc Converts a string to another encoding format. 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: char temp_string[256]; do_uconvert(input_string, U_CURRENT, temp_string, U_ASCII, 256); 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. @\char *@uconvert(const char *s, int type, @@ char *buf, int newtype, int size); @xref set_uformat, need_uconvert, uconvert, uconvert_ascii, uconvert_toascii @xref do_uconvert @shortdesc Hih level string encoding conversion wrapper. 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: char *p = uconvert(input_string, U_CURRENT, buffer, U_ASCII, 256); @retval 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'. @@char *@uconvert_ascii(const char *s, char buf[]); @xref uconvert @eref exunicod @shortdesc Converts string from ASCII into the current format. Helper macro for converting strings from ASCII into the current encoding format. Expands to uconvert(s, U_ASCII, buf, U_CURRENT, sizeof(buf)). @@char *@uconvert_toascii(const char *s, char buf[]); @xref uconvert @shortdesc Converts strings from the current format into ASCII. Helper macro for converting strings from the current encoding format into ASCII. Expands to uconvert(s, U_CURRENT, buf, U_ASCII, sizeof(buf)). @@extern char @empty_string[]; @shortdesc Universal string NULL terminator. 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. @@int @ugetc(const char *s); @xref ugetx, usetc, uwidth, ucwidth, uisok @shortdesc Low level helper function for reading Unicode text data. Low level helper function for reading Unicode text data. Example: int first_unicode_letter = ugetc(text_string); @retval Returns the character pointed to by `s' in the current encoding format. @@int @ugetx(char **s); @@int @ugetxc(const char **s); @xref ugetc, usetc, uwidth, ucwidth, uisok @shortdesc Low level helper function for reading Unicode text data. Low level helper function for reading Unicode text data. ugetxc is provided for working with pointer-to-pointer-to-const char data. Example: char *p = string; int first_letter, second_letter, third_letter; first_letter = ugetx(&p); second_letter = ugetx(&p); third_letter = ugetx(&p); @retval 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. @@int @usetc(char *s, int c); @xref ugetc, ugetx, uwidth, ucwidth, uisok @shortdesc Low level helper function for writing Unicode text data. Low level helper function for writing Unicode text data. Writes the character `c' to the address pointed to by `s'. @retval Returns the number of bytes written, which is equal to the width of the character in the current encoding format. @@int @uwidth(const char *s); @xref uwidth_max, ugetc, ugetx, usetc, ucwidth, uisok @shortdesc Low level helper function for testing Unicode text data. Low level helper function for testing Unicode text data. @retval Returns the number of bytes occupied by the first character of the specified string, in the current encoding format. @@int @ucwidth(int c); @xref uwidth_max, ugetc, ugetx, usetc, uwidth, uisok @shortdesc Low level helper function for testing Unicode text data. Low level helper function for testing Unicode text data. @retval Returns the number of bytes that would be occupied by the specified character value, when encoded in the current format. @@int @uisok(int c); @xref ugetc, ugetx, usetc, uwidth, ucwidth @shortdesc Low level helper function for testing Unicode text data. 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. @retval Returns non-zero if the value can be correctly encoded, zero otherwise. @@int @uoffset(const char *s, int index); @xref ugetat, usetat, uinsert, uremove @shortdesc Finds the offset of a character in a string. 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: int from_third_letter = uoffset(text_string, 2); @retval Returns the offset in bytes to the specified character. @@int @ugetat(const char *s, int index); @xref uoffset, usetat, uinsert, uremove @shortdesc Finds out the value of a character in a string. 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: int third_letter = ugetat(text_string, 2); @retval Returns the character value at the specified index in the string. @@int @usetat(char *s, int index, int c); @xref uoffset, ugetat, uinsert, uremove @shortdesc Replaces a character in a string. 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: usetat(text_string, 2, letter_a); @retval 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. @@int @uinsert(char *s, int index, int c); @xref uoffset, ugetat, usetat, uremove @shortdesc Inserts a character in a string. 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: uinsert(text_string, 0, prefix_letter); @retval Returns the number of bytes by which the trailing part of the string was moved. @@int @uremove(char *s, int index); @xref uoffset, ugetat, usetat, uinsert @shortdesc Removes a character from a string. 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: int length_in_bytes = ustrsizez(text_string); ... length_in_bytes -= uremove(text_string, -1); @retval Returns the number of bytes by which the trailing part of the string was moved. @@int @ustrsize(const char *s); @xref ustrsizez, empty_string @eref exunicod @shortdesc Size of the string in bytes without null terminator. Returns the size of the specified string in bytes, not including the trailing null character. @@int @ustrsizez(const char *s); @xref ustrsize, empty_string @eref exunicod @shortdesc Size of the string in bytes including null terminator. Returns the size of the specified string in bytes, including the trailing null character. @@int @uwidth_max(int type); @xref uwidth, ucwidth @shortdesc Number of bytes a character can occupy. 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: char *temp_buffer = malloc(256 * uwidth_max(U_UTF8)); @@int @utolower(int c); @xref utoupper, ugetc, ugetx, usetc, uwidth, ucwidth, uisok @shortdesc Converts a letter to lower case. This function returns `c', converting it to lower case if it is upper case. @@int @utoupper(int c); @xref utolower, ugetc, ugetx, usetc, uwidth, ucwidth, uisok @shortdesc Converts a letter to upper case. This function returns `c', converting it to upper case if it is lower case. @@int @uisspace(int c); @xref uisdigit, ugetc, usetc, uwidth, ucwidth, uisok @shortdesc Tells if a character is whitespace. Returns nonzero if `c' is whitespace, that is, carriage return, newline, form feed, tab, vertical tab, or space. Example: for (counter = 0; counter < ustrlen(text_string); counter++) { if (uisspace(ugetat(text_string, counter))) usetat(text_string, counter, '_'); } @@int @uisdigit(int c); @xref uisspace, ugetc, usetc, uwidth, ucwidth, uisok @shortdesc Tells if a character is a digit. Returns nonzero if `c' is a digit. for (counter = 0; counter < ustrlen(text_string); counter++) { if (uisdigit(ugetat(text_string, counter))) usetat(text_string, counter, '*'); } @@char *@ustrdup(const char *src) @xref _ustrdup, uconvert, ustrsize, ustrsizez @eref exconfig @shortdesc Duplicates a string. This functions copies the null-terminated string `src' into a newly allocated area of memory, effectively duplicating it. Example: void manipulate_string(const char *input_string) { char *temp_buffer = ustrdup(input_string); /* Now we can modify temp_buffer */ ... @retval Returns the newly allocated string. This memory must be freed by the caller. Returns NULL if it cannot allocate space for the duplicated string. @@char *@_ustrdup(const char *src, void* (*malloc_func)(size_t)) @xref ustrdup, uconvert, ustrsize, ustrsizez @shortdesc Duplicates a string with a custom memory allocator. Does the same as ustrdup(), but allows the user to specify a custom memory allocator function. @@char *@ustrcpy(char *dest, const char *src); @xref uconvert, ustrzcpy, ustrncpy @eref exunicod @shortdesc Copies a string into another one. 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. @retval Returns the value of dest. @@char *@ustrzcpy(char *dest, int size, const char *src); @xref uconvert, ustrcpy, ustrzncpy @eref ex3buf, exgui @shortdesc Copies a string into another one, specifying size. 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. @retval Returns the value of `dest'. @@char *@ustrcat(char *dest, const char *src); @xref uconvert, ustrzcat, ustrncat @eref exunicod @shortdesc Concatenates a string to another one. 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. @retval Returns the value of `dest'. @@char *@ustrzcat(char *dest, int size, const char *src); @xref uconvert, ustrcat, ustrzncat @eref exgui @shortdesc Concatenates a string to another one, specifying size. 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. @retval Returns the value of `dest'. @@int @ustrlen(const char *s); @xref uconvert, ustrsize, ustrsizez @shortdesc Tells the number of characters in a string. This function returns the number of characters in `s'. Note that this doesn't have to equal the string's size in bytes. @@int @ustrcmp(const char *s1, const char *s2); @xref uconvert, ustrsize, ustrsizez, ustrncmp, ustricmp, ustrnicmp @shortdesc Compares two strings. This function compares `s1' and `s2'. @retval Returns zero if the strings are equal, a positive number if `s1' comes after `s2' in the ASCII collating sequence, else a negative number. @@char *@ustrncpy(char *dest, const char *src, int n); @xref uconvert, ustrcpy, ustrzncpy @shortdesc Copies a string into another one, specifying size. 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. @retval The return value is the value of `dest'. @@char *@ustrzncpy(char *dest, int size, const char *src, int n); @xref uconvert, ustrzcpy, ustrncpy @eref exkeys @shortdesc Copies a string into another one, specifying size. 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. @retval The return value is the value of `dest'. @@char *@ustrncat(char *dest, const char *src, int n); @xref uconvert, ustrcat, ustrzncat @shortdesc Concatenates a string to another one, specifying size. 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. @retval The return value is the value of `dest'. @@char *@ustrzncat(char *dest, int size, const char *src, int n); @xref uconvert, ustrzcat, ustrncat @shortdesc Concatenates a string to another one, specifying size. 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. @retval The return value is the value of `dest'. @@int @ustrncmp(const char *s1, const char *s2, int n); @xref uconvert, ustrsize, ustrsizez, ustrcmp, ustricmp, ustrnicmp @shortdesc Compares up to n letters of two strings. This function compares up to `n' characters of `s1' and `s2'. Example: if (ustrncmp(prefix, long_string, ustrlen(prefix)) == 0) { /* long_string starts with prefix */ } @retval Returns zero if the substrings are equal, a positive number if `s1' comes after `s2' in the ASCII collating sequence, else a negative number. @@int @ustricmp(const char *s1, const char *s2); @xref uconvert, ustrsize, ustrsizez, ustrnicmp, ustrcmp, ustrncmp @eref exconfig @shortdesc Compares two strings ignoring case. This function compares `s1' and `s2', ignoring case. Example: if (ustricmp(string, user_input) == 0) { /* string and user_input are equal (ignoring case) */ } @retval Returns zero if the strings are equal, a positive number if `s1' comes after `s2' in the ASCII collating sequence, else a negative number. @@int @ustrnicmp(const char *s1, const char *s2, int n); @xref uconvert, ustrsize, ustrsizez, ustricmp, ustrcmp, ustrncmp @shortdesc Compares up to n letters of two strings ignoring case. This function compares up to `n' characters of `s1' and `s2', ignoring case. Example: if (ustrnicmp(prefix, long_string, ustrlen(prefix)) == 0) { /* long_string starts with prefix (ignoring case) */ } @retval Returns zero if the strings are equal, a positive number if `s1' comes after `s2' in the ASCII collating sequence, else a negative number. @@char *@ustrlwr(char *s); @xref uconvert, utolower, ustrupr @shortdesc Replaces all letters with lower case. This function replaces all upper case letters in `s' with lower case letters. Example: char buffer[] = "UPPER CASE STRING"; allegro_message(ustrlwr(buffer)); @retval The return value is the value of `s'. @@char *@ustrupr(char *s); @xref uconvert, utolower, ustrlwr @shortdesc Replaces all letters with upper case. This function replaces all lower case letters in `s' with upper case letters. Example: char buffer[] = "lower case string"; allegro_message(ustrupr(buffer)); @retval The return value is the value of `s'. @@char *@ustrchr(const char *s, int c); @xref uconvert, ustrrchr, ustrstr, ustrpbrk, ustrtok @shortdesc Finds the first occurrence of a character in a string. Finds the first occurrence of the character `c' in the string `s'. Example: char *p = ustrchr("one,two,three,four", ','); @retval 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. @@char *@ustrrchr(const char *s, int c); @xref uconvert, ustrchr, ustrstr, ustrpbrk, ustrtok @shortdesc Finds the last occurence of a character in a string. Finds the last occurrence of the character `c' in the string `s'. Example: char *p = ustrrchr("one,two,three,four", ','); @retval Returns a pointer fo the last occurrence of `c' in `s', or NULL if no match was found. @@char *@ustrstr(const char *s1, const char *s2); @xref uconvert, ustrchr, ustrrchr, ustrpbrk, ustrtok @shortdesc Finds the first occurence of a string in another one. This function finds the first occurence of string `s2' in string `s1'. Example: char *p = ustrstr("hello world", "world"); @retval Returns a pointer within `s1', or NULL if `s2' wasn't found. @@char *@ustrpbrk(const char *s, const char *set); @xref uconvert, ustrchr, ustrrchr, ustrstr, ustrtok @shortdesc Finds the first character that matches any in a set. This function finds the first character in `s' that matches any character in `set'. Example: char *p = ustrpbrk("one,two-three.four", "-. "); @retval Returns a pointer to the first match, or NULL if none are found. @@char *@ustrtok(char *s, const char *set); @xref uconvert, ustrchr, ustrrchr, ustrstr, ustrpbrk, ustrtok_r @xref allegro_message, ustrncpy @eref exgui @shortdesc Retrieves tokens from a string. 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: 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); @retval Returns a pointer to the token, or NULL if no more are found. @@char *@ustrtok_r(char *s, const char *set, char **last); @xref ustrtok @shortdesc Reentrant function to retrieve tokens from a string. 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: char *word, *last; char string[]="some-words with dashes"; char *temp = ustrdup(string); word = ustrtok_r(string, " -", &last); while (word) { allegro_message("Found `%s'\n", word); word = ustrtok_r(NULL, " -", &last); } free(temp); @retval 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. @@double @uatof(const char *s); @xref uconvert, ustrtol, ustrtod @shortdesc Converts a string into a double. Convert as much of the string as possible to an equivalent double precision real number. This function is almost like `ustrtod(s, NULL)'. @retval Returns the equivalent value, or zero if the string does not represent a number. @@long @ustrtol(const char *s, char **endp, int base); @xref uconvert, ustrtod, uatof @shortdesc Converts a string into an integer. 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: char *endp, *string = "456.203 askdfg"; int number = ustrtol(string, &endp, 10); @retval 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'. @@double @ustrtod(const char *s, char **endp); @xref uconvert, ustrtol, uatof @shortdesc Converts a string into a floating point number. 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: char *endp, *string = "456.203 askdfg"; double number = ustrtod(string, &endp); @retval Returns the string converted as a value of type `double'. If nothing was converted, returns zero with *endp pointing to the beginning of s. @@const char *@ustrerror(int err); @xref uconvert, allegro_error @shortdesc Returns a string describing errno. This function returns a string that describes the error code `err', which normally comes from the variable `errno'. Example: PACKFILE *input_file = pack_fopen("badname", "r"); if (input_file == NULL) allegro_message("%s\nSorry!\n", ustrerror(errno)); @retval 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. @@int @usprintf(char *buf, const char *format, ...); @xref uconvert, uszprintf, uvsprintf @eref exkeys @shortdesc Writes formatted data into a buffer. 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. @retval Returns the number of characters written, not including the terminating null character. @@int @uszprintf(char *buf, int size, const char *format, ...); @xref uconvert, usprintf, uvszprintf @eref exgui @shortdesc Writes formatted data into a buffer, specifying size. 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: char buffer[10]; int player_score; ... uszprintf(buffer, sizeof(buffer), "Your score is: %d", player_score); @retval Returns the number of characters that would have been written without eventual truncation (like with usprintf), not including the terminating null character. @@int @uvsprintf(char *buf, const char *format, va_list args); @xref uconvert, usprintf, uvszprintf @shortdesc Writes formatted data into a buffer, using variable arguments. 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. @retval Returns the number of characters written, not including the terminating null character. @@int @uvszprintf(char *buf, int size, const char *format, va_list args); @xref uconvert, uszprintf, uvsprintf @shortdesc Writes formatted data into a buffer, using size and variable arguments. This is like uszprintf(), but you pass the variable argument list directly, instead of the arguments themselves. Example: #include <stdarg.h> void log_message(const char *format, ...) { char buffer[100]; va_list parameters; va_start(parameters, format); uvszprintf(buffer, sizeof(buffer), format, parameters); va_end(parameters); append_buffer_to_logfile(log_name, buffer); send_buffer_to_other_networked_players(multicast_ip, buffer); and_also_print_it_on_the_screen(cool_font, buffer); } void some_other_function(void) { log_message("Hello %s, are you %d years old?\n", "Dave", 25); } @retval Returns the number of characters that would have been written without eventual truncation (like with uvsprintf), not including the terminating null character. @heading Configuration routines Various parts of Allegro, such as the sound routines and the load_joystick_data() function, require some configuration information. This data is stored in text files as a collection of `variable=value' lines, along with comments that begin with a `#' character and continue to the end of the line. The configuration file may optionally be divided into sections, which begin with a `[sectionname]' line. Each section has a unique namespace, to prevent variable name conflicts, but any variables that aren't in a section are considered to belong to all the sections simultaneously. 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. @@void @set_config_file(const char *filename); @xref set_config_data, override_config_file, push_config_state, set_uformat @xref Standard config variables, set_config_string, get_config_string @eref exconfig @shortdesc Sets the configuration file. 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. @@void @set_config_data(const char *data, int length); @xref set_config_file, override_config_data, push_config_state @xref Standard config variables, set_config_string, get_config_string @shortdesc Sets a block of configuration data. 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. @@void @override_config_file(const char *filename); @xref override_config_data, set_config_file @shortdesc Specifies a file containing config overrides. 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: 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); Note that this function and override_config_data() are mutually exclusive, i.e. calling one will cancel the effects of the other. @@void @override_config_data(const char *data, int length); @xref override_config_file, set_config_data @shortdesc Specifies a block of data containing config overrides. 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: /* 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)); Note that this function and override_config_file() are mutually exclusive, i.e. calling one will cancel the effects of the other. @@void @push_config_state(); @xref pop_config_state, set_config_file, save_joystick_data @eref exconfig @shortdesc Pushes the current configuration state. Pushes the current configuration state (filename, variable values, etc). onto an internal stack, allowing you to select some other config source and later restore the current settings by calling pop_config_state(). This function is mostly intended for internal use by other library functions, for example when you specify a config filename to the save_joystick_data() function, it pushes the config state before switching to the file you specified. @@void @pop_config_state(); @xref push_config_state @eref exconfig @shortdesc Pops a previously pushed configuration state. Pops a configuration state previously stored by push_config_state(), replacing the current config source with it. @@void @flush_config_file(); @xref set_config_file, override_config_file, push_config_state @shortdesc Flushes the current config file to disk. Writes the current config file to disk if the contents have changed since it was loaded or since the latest call to the function. @@void @reload_config_texts(const char *new_language); @xref get_config_text, get_config_string, Standard config variables @shortdesc Reloads translated strings returned by get_config_text(). 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: ... /* The user selects French from a language choice menu. */ reload_config_texts("FR"); @\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)); @xref config_is_hooked @shortdesc Hooks a configuration file section with custom handlers. 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: 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() @@int @config_is_hooked(const char *section); @xref hook_config_section @shortdesc Tells if a config section has custom hooks. Returns TRUE if the specified config section has been hooked. Example: if (config_is_hooked("high_scores")) { hook_config_section("high_scores, NULL, NULL, NULL); } @\const char *@get_config_string(const char *section, @@ const char *name, const char *def); @xref set_config_file, set_config_string, get_config_argv, get_config_float @xref get_config_hex, get_config_int, get_config_id, get_config_text @eref exconfig @shortdesc Retrieves a string from the configuration file. 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: const char *lang = get_config_string("system", "language", "EN"); @retval 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. @@int @get_config_int(const char *section, const char *name, int def); @xref set_config_file, set_config_int, get_config_string, get_config_argv @xref get_config_float, get_config_hex, get_config_id @eref exconfig @shortdesc Retrieves an integer from the configuration file. Reads an integer variable from the current config file. See the comments about get_config_string(). @@int @get_config_hex(const char *section, const char *name, int def); @xref set_config_file, set_config_hex, get_config_string, get_config_argv @xref get_config_float, get_config_int, get_config_id @shortdesc Retrieves a hexadecimal value from the configuration file. Reads an integer variable from the current config file, in hexadecimal format. See the comments about get_config_string(). @@float @get_config_float(const char *section, const char *name, float def); @xref set_config_file, set_config_float, get_config_string, get_config_argv @xref get_config_hex, get_config_int, get_config_id @shortdesc Retrieves a float from the configuration file. Reads a floating point variable from the current config file. See the comments about get_config_string(). @@int @get_config_id(const char *section, const char *name, int def); @xref set_config_file, set_config_id, get_config_string, get_config_argv @xref get_config_float, get_config_hex, get_config_int @shortdesc Retrieves a driver ID from a configuration file. Reads a 4-letter driver ID variable from the current config file. See the comments about get_config_string(). @@char **@get_config_argv(const char *section, const char *name, int *argc); @xref set_config_file, get_config_string, get_config_float, get_config_hex @xref get_config_int, get_config_id @eref exconfig @shortdesc Reads a token list from the configuration file. 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. @retval 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. @@const char *@get_config_text(const char *msg); @xref get_config_string, reload_config_texts, Standard config variables @shortdesc Returns a string translated to the current language. 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. @retval Returns a suitable translation if one can be found or a copy of the parameter if nothing else is available. @\void @set_config_string(const char *section, const char *name, @@ const char *val); @xref set_config_file, get_config_string, set_config_float, set_config_hex @xref set_config_int, set_config_id @shortdesc Writes a string in the configuration file. 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. @@void @set_config_int(const char *section, const char *name, int val); @xref set_config_file, get_config_int, set_config_string, set_config_float @xref set_config_hex, set_config_id @shortdesc Writes an integer in the configuration file. Writes an integer variable to the current config file. See the comments about set_config_string(). @@void @set_config_hex(const char *section, const char *name, int val); @xref set_config_file, get_config_hex, set_config_string, set_config_float @xref set_config_int, set_config_id @shortdesc Writes a hexadecimal integer in the configuration file. Writes an integer variable to the current config file, in hexadecimal format. See the comments about set_config_string(). @@void @set_config_float(const char *section, const char *name, float val); @xref set_config_file, get_config_float, set_config_string, set_config_hex @xref set_config_int, set_config_id @shortdesc Writes a float in the configuration file. Writes a floating point variable to the current config file. See the comments about set_config_string(). @@void @set_config_id(const char *section, const char *name, int val); @xref set_config_file, get_config_id, set_config_string, set_config_float @xref set_config_hex, set_config_int @shortdesc Writes a driver ID in the configuration file. Writes a 4-letter driver ID variable to the current config file. See the comments about set_config_string(). @hnode Standard config variables @xref set_config_file, set_config_string, get_config_string Allegro uses these standard variables from the configuration file: @tallbullets
  • [system]
    Section containing general purpose variables:
    • system = x
      Specifies which system driver to use. This is currently only useful on Linux, for choosing between the XWindows ("XWIN") or console ("LNXC") modes.
    • keyboard = x
      Specifies which keyboard layout to use. The parameter is the name of a keyboard mapping file produced by the keyconf utility, and can either be a fully qualified file path or a 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.
    • language = x
      Specifies which language file to use for error messages and other bits of system text. The parameter is the name of a translation file, and can either be a fully qualified file path or a 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.
    • disable_screensaver = x
      Specifies whether to disable the screensaver: 0 to never disable it, 1 to disable it in fullscreen mode only and 2 to always disable it. Default is 1.
    • menu_opening_delay = x
      Sets how long the menus take to auto-open. The time is given in milliseconds (default is `300'). Specifying `-1' will disable the auto-opening feature.
  • [graphics]
    Section containing graphics configuration information, using the variables:
    • gfx_card = x
      Specifies which graphics driver to use when the program requests GFX_AUTODETECT. Multiple possible drivers can be suggested with extra lines in the form `gfx_card1 = x', `gfx_card2 = x', etc, or you can specify different drivers for each mode and color depth with variables in the form `gfx_card_24bpp = x', `gfx_card_640x480x16 = x', etc.
    • gfx_cardw = x
      Specifies which graphics driver to use when the program requests GFX_AUTODETECT_WINDOWED. This variable functions exactly like gfx_card in all other respects. If it is not set, Allegro will look for the gfx_card variable.
    • disable_vsync = x
      Specifies whether to disable synchronization with the vertical blank when page-flipping (yes or no). Disabling synchronization may increase the frame rate on slow systems, at the expense of introducing flicker on fast systems.
    • vbeaf_driver = x
      DOS and Linux only: specifies where to look for the VBE/AF driver (vbeaf.drv). If this variable is not set, Allegro will look in the same directory as the program, and then fall back on the standard locations (`c:\' for DOS, `/usr/local/lib', `/usr/lib', `/lib', and `/' for Linux, or the directory specified with the VBEAF_PATH environment variable).
    • framebuffer = x
      Linux only: specifies what device file to use for the fbcon driver. If this variable is not set, Allegro checks the FRAMEBUFFER environment variable, and then defaults to `/dev/fb0'.
    • force_centering = x
      Unix/X11 only: specifies whether to force window centering in fullscreen mode when the XWFS driver is used (yes or no). Enabling this setting may cause some artifacts to appear on KDE desktops.
    • disable_direct_updating = x
      Windows only: specifies whether to disable direct updating when the GFX_DIRECTX_WIN driver is used in color conversion mode (yes or no). Direct updating can cause artifacts to be left on the desktop when the window is moved or minimized; disabling it results in a significant performance loss.
  • [mouse]
    Section containing mouse configuration information, using the variables:
    • mouse = x
      Mouse driver type. Available DOS drivers are: MICK - mickey mode driver (normally the best) I33 - int 0x33 callback driver POLL - timer polling (for use under NT) Linux console mouse drivers are: 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)
    • num_buttons = x
      Sets the number of mouse buttons viewed by Allegro. You don't normally need to set this variable because Allegro will autodetect it. You can only use it to restrict the set of actual mouse buttons to zero or positive values, negative values will be ignored.
    • emulate_three = x
      Sets whether to emulate a third mouse button by detecting chords of the left and right buttons (yes or no). Defaults to no.
    • mouse_device = x
      Linux only: specifies the name of the mouse device file (eg. `/dev/mouse').
    • ev_absolute = x
      Linux only: specifies the mode for the default EV input: 0 - relative mode: pointer position changes if the input moves, 1 - absolute mode: pointer position is the input position. If unspecified, the mode is relative. If the device supports several tools (such as a graphic tablet), the default input is the mouse. If the device has only one tool (e.g. a normal mouse) the default input is this tool. All additionnal tools work in absolute mode.
    • ev_min_x = x
      ev_max_x = x
      ev_min_y = x
      ev_max_y = x
      ev_min_z = x
      ev_max_z = x
      Linux only: for absolute EV inputs, minimum and maximum value. By default this information is autodetected.
    • mouse_accel_factor = x
      Windows only: specifies the mouse acceleration factor. Defaults to 1. Set it to 0 in order to disable mouse acceleration. 2 accelerates twice as much as 1.
  • [sound]
    Section containing sound configuration information, using the variables:
    • digi_card = x
      Sets the driver to use for playing digital samples.
    • midi_card = x
      Sets the driver to use for MIDI music.
    • digi_input_card = x
      Sets the driver to use for digital sample input.
    • midi_input_card = x
      Sets the driver to use for MIDI data input.
    • digi_voices = x
      Specifies the minimum number of voices to reserve for use by the digital sound driver. How many are possible depends on the driver.
    • midi_voices = x
      Specifies the minimum number of voices to reserve for use by the MIDI sound driver. How many are possible depends on the driver.
    • digi_volume = x
      Sets the volume for digital sample playback, from 0 to 255.
    • midi_volume = x
      Sets the volume for midi music playback, from 0 to 255.
    • quality = x
      Controls the sound quality vs. performance tradeoff for the sample mixing code. This can be set to any of the values: 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
    • flip_pan = x
      Toggling this between 0 and 1 reverses the left/right panning of samples, which might be needed because some SB cards get the stereo image the wrong way round.
    • sound_freq = x
      DOS, Unix and BeOS: sets the sample frequency. With the SB driver, possible rates are 11906 (any), 16129 (any), 22727 (SB 2.0 and above), and 45454 (only on SB 2.0 or SB16, not the stereo SB Pro driver). On the ESS Audiodrive, possible rates are 11363, 17046, 22729, or 44194. On the Ensoniq Soundscape, possible rates are 11025, 16000, 22050, or 48000. On the Windows Sound System, possible rates are 11025, 22050, 44100, or 48000. Don't worry if you set some other number by mistake: Allegro will automatically round it to the closest supported frequency.
    • sound_bits = x
      Unix and BeOS: sets the preferred number of bits (8 or 16).
    • sound_stereo = x
      Unix and BeOS: selects mono or stereo output (0 or 1).
    • sound_port = x
      DOS only: sets the soundcard port address (this is usually 220).
    • sound_dma = x
      DOS only: sets the soundcard DMA channel (this is usually 1).
    • sound_irq = x
      DOS only: sets the soundcard IRQ number (this is usually 7).
    • fm_port = x
      DOS only: sets the port address of the OPL synth (this is usually 388).
    • mpu_port = x
      DOS only: sets the port address of the MPU-401 MIDI interface (this is usually 330).
    • mpu_irq = x
      DOS only: sets the IRQ for the MPU-401 (this is usually the same as sound_irq).
    • ibk_file = x
      DOS only: specifies the name of a .IBK file which will be used to replace the standard Adlib patch set.
    • ibk_drum_file = x
      DOS only: specifies the name of a .IBK file which will be used to replace the standard set of Adlib percussion patches.
    • oss_driver = x
      Unix only: sets the OSS device driver name. Usually `/dev/dsp' or `/dev/audio', but could be a particular device (e.g. `/dev/dsp2').
    • oss_numfrags = x
      oss_fragsize = x
      Unix only: sets number of OSS driver fragments (buffers) and size of each buffer in samples. Buffers are filled with data in the interrupts where interval between subsequent interrupts is not less than 10 ms. If hardware can play all information from buffers faster than 10 ms, then there will be clicks, when hardware have played all data and library has not prepared new data yet. On the other hand, if it takes too long for device driver to play data from all buffers, then there will be delays between action which triggers sound and sound itself.
    • oss_midi_driver = x
      Unix only: sets the OSS MIDI device name. Usually `/dev/sequencer'.
    • oss_mixer_driver = x
      Unix only: sets the OSS mixer device name. Usually `/dev/mixer'.
    • esd_server = x
      Unix only: where to find the ESD (Enlightened Sound Daemon) server.
    • alsa_card = x
      alsa_pcmdevice = x
      Unix only: card number and PCM device for the ALSA 0.5 sound driver.
    • alsa_device = x
      Unix only: device name for the ALSA 0.9 sound driver. The format is <driver>[:<card>,<device>], for example: `hw:0,1'.
    • alsa_mixer_device = x
      Unix only: mixer device name for the ALSA 0.9 sound driver. The default is "default".
    • alsa_mixer_elem = x
      Unix only: mixer element name for the ALSA 0.9 driver. The default is PCM.
    • alsa_numfrags = x
      Unix only: number of ALSA driver fragments (buffers).
    • alsa_fragsize = x
      Unix only: size of each ALSA fragment, in samples.
    • alsa_rawmidi_card = x
      Unix only: card number and device for the ALSA 0.5 midi driver.
    • alsa_rawmidi_device = x
      Unix only: device for the ALSA 0.5 midi driver or device name for the ALSA 0.9 midi driver (see alsa_device for the format).
    • jack_client_name = x
      Sets the name with which Allegro should identify itself to the Jack audio server.
    • jack_buffer_size = x
      Forces a buffer size for the transfer buffer from Allegro's mixer to Jack.
    • be_midi_quality = x
      BeOS only: system MIDI synthesizer instruments quality. 0 uses low quality 8-bit 11 kHz samples, 1 uses 16-bit 22 kHz samples.
    • be_midi_freq = x
      BeOS only: MIDI sample mixing frequency in Hz. Can be 11025, 22050 or 44100.
    • be_midi_interpolation = x
      BeOS only: specifies the MIDI samples interpolation method. 0 doesn't interpolate, it's fast but has the worst quality; 1 does a fast interpolation with better performances, but it's a bit slower than the previous method; 2 does a linear interpolation between samples, it is the slowest method but gives the best performances.
    • be_midi_reverb = x
      BeOS only: reverberation intensity, from 0 to 5. 0 disables it, 5 is the strongest one.
    • ca_midi_quality = x
      MacOS X only: CoreAudio MIDI synthesizer rendering quality, from 0 to 127. Higher qualities sound better but increase the CPU work load.
    • ca_midi_reverb = x
      MacOS X only: CoreAudio MIDI synthesizer reverberation intensity, from 0 to 5. 0 equals to a small room (low reverb), 5 to a plate (high reverb).
    • patches = x
      Specifies where to find the sample set for the DIGMID driver. This can either be a Gravis style directory containing a collection of .pat files and a `default.cfg' index, or an Allegro datafile produced by the pat2dat utility. If this variable is not set, Allegro will look either for a `default.cfg' or `patches.dat' file in the same directory as the program, the directory pointed to by the ALLEGRO environment variable, and the standard GUS directory pointed to by the ULTRASND environment variable.
  • [midimap]
    If you are using the SB MIDI output or MPU-401 drivers with an external synthesiser that is not General MIDI compatible, you can use the midimap section of the config file to specify a patch mapping table for converting GM patch numbers into whatever bank and program change messages will select the appropriate sound on your synth. This is a real piece of self-indulgence. I have a Yamaha TG500, which has some great sounds but no GM patch set, and I just had to make it work somehow... This section consists of a set of lines in the form:
    • p<n> = bank0 bank1 prog pitch
      With this statement, n is the GM program change number (1-128), bank0 and bank1 are the two bank change messages to send to your synth (on controllers #0 and #32), prog is the program change message to send to your synth, and pitch is the number of semitones to shift everything that is played with that sound. Setting the bank change numbers to -1 will prevent them from being sent. For example, the line: p36 = 0 34 9 12 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.
  • [joystick]
    Section containing joystick configuration information, using the variables:
    • joytype = x
      Specifies which joystick driver to use when the program requests JOY_TYPE_AUTODETECT.
    • joystick_device = x
      BeOS and Linux only: specifies the name of the joystick device to be used (as reported in the system joystick preferences under BeOS). The first device found is used by default. If you want to specify the device for each joystick, use variables of the form joystick_device_n, where n is the joystick number.
    • throttle_axis = x
      Linux only: sets the axis number the throttle is located at. This variable will be used for every detected joystick. If you want to specify the axis number for each joystick individually, use variables of the form throttle_axis_n, where n is the joystick number.
@heading Mouse routines Allegro provides functions for reading the mouse state and displaying a mouse cursor on-screen. You can read the absolute position of the mouse and the state of the mouse buttons from global variables. Additionally, you can read the mouse position difference as mouse mickeys, which is the number of pixels the cursor moved since the last time this information was read. Allegro offers three ways to display the mouse cursor:
  • Standard Allegro cursor
    Allegro is responsible for drawing the mouse cursor from a timer. Use set_mouse_sprite() and show_mouse() to define your own cursor and display it on the screen. You need to call scare_mouse()/unscare_mouse() to hide the mouse cursor whenever you draw to the screen.
  • Custom operating system cursor (hardware cursor)
    Allegro will let the operating system draw the mouse cursor. Use set_mouse_sprite() and show_mouse() (or show_os_cursor) to define your own cursor and display it on the screen. Not all graphics drivers are capable of this and some may only be able to display cursors 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.
  • Default operating system cursor
    Allegro will not draw its own cursor, but use the operating system default cursor. You can use the select_mouse_cursor() function to select the cursor shape to display. As with custom operating system cursors, you need to call enable_hardware_cursor() before you can use this. Or you can use the low level show_os_cursor() function.
Not all drivers will support all functionality. See the platform specific information for more details. @@int @install_mouse(); @xref remove_mouse, poll_mouse, mouse_x, show_mouse, get_mouse_mickeys @xref position_mouse, set_mouse_range, set_mouse_speed @xref Standard config variables @eref Available Allegro examples @shortdesc Installs the Allegro mouse handler. Installs the Allegro mouse handler. You must do this before using any other mouse functions. @retval 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. @@void @remove_mouse(); @xref install_mouse, allegro_exit @shortdesc Removes the mouse handler. Removes the mouse handler. You don't normally need to bother calling this, because allegro_exit() will do it for you. @@int @poll_mouse(); @xref mouse_needs_poll, install_mouse, mouse_x @eref exlights, exmouse, exshade, exspline, extrans @shortdesc Polls the mouse. Wherever possible, Allegro will read the mouse input asynchronously (ie. from inside an interrupt handler), but on some platforms that may not be possible, in which case you must call this routine at regular intervals to update the mouse state variables. To help you test your mouse polling code even if you are programming on a platform that doesn't require it, after the first time that you call this function Allegro will switch into polling mode, so from that point onwards you will have to call this routine in order to get any mouse input at all, regardless of whether the current driver actually needs to be polled or not. @retval Returns zero on success, or a negative number on failure (ie. no mouse driver installed). @@int @mouse_needs_poll(); @xref poll_mouse, install_mouse, mouse_x @shortdesc Tells if the mouse driver requires polling. Returns TRUE if the current mouse driver is operating in polling mode. @@void @enable_hardware_cursor(void); @xref install_mouse, show_mouse, set_mouse_sprite, get_mouse_mickeys @xref gfx_capabilities, disable_hardware_cursor, show_os_cursor @eref exsyscur @shortdesc Enables the OS hardware cursor. 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. @@void @disable_hardware_cursor(void); @xref install_mouse, show_mouse, set_mouse_sprite, get_mouse_mickeys @xref gfx_capabilities, enable_hardware_cursor @shortdesc Disables the OS hardware cursor. 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. @@void @select_mouse_cursor(int cursor); @xref install_mouse, show_mouse, set_mouse_sprite, gfx_capabilities @xref enable_hardware_cursor, set_mouse_cursor_bitmap, show_os_cursor @eref exsyscur @shortdesc Tells Allegro to select software or hardware cursor drawing. This function allows you to use the operating system's native mouse cursors rather than some custom cursor. You will need to enable this functionality by calling enable_hardware_cursor() beforehand. If the operating system does not support this functionality, or if it has not been enabled, then Allegro will substitute its own cursor images. You can change these substitute images using set_mouse_cursor_bitmap(). Note that the effects of this function are not apparent until show_mouse() is called. To know whether the operating system's native cursor is being used, or if Allegro has made a substitution, you can check the GFX_SYSTEM_CURSOR flag in gfx_capabilities after calling show_mouse(). The cursor argument selects the type of cursor to be displayed: MOUSE_CURSOR_NONE
Selects an invisible mouse cursor. In that sense, it is similar to calling show_mouse(NULL); MOUSE_CURSOR_ALLEGRO
Selects the custom Allegro cursor, i.e. the one that you set with set_mouse_sprite(). MOUSE_CURSOR_ARROW
The operating system default arrow cursor. MOUSE_CURSOR_BUSY
The operating system default `busy' cursor (hourglass). MOUSE_CURSOR_QUESTION
The operating system default `question' cursor (arrow with question mark). MOUSE_CURSOR_EDIT
The operating system default `edit' cursor (vertical bar). Example: /* 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); @@void @set_mouse_cursor_bitmap(int cursor, BITMAP *bmp); @xref install_mouse, show_mouse, set_mouse_sprite, gfx_capabilities @xref enable_hardware_cursor, show_os_cursor @shortdesc Changes the image Allegro uses for mouse cursors. This function changes the cursor image Allegro uses if select_mouse_cursor() is called but no native operating system cursor can be used, e.g. because you did not call enable_hardware_cursor(). The cursor argument can be one of:
MOUSE_CURSOR_ALLEGRO
MOUSE_CURSOR_ARROW
MOUSE_CURSOR_BUSY
MOUSE_CURSOR_QUESTION
MOUSE_CURSOR_EDIT
but not MOUSE_CURSOR_NONE. The bmp argument can either point to a valid bitmap or it can be NULL. Passing a bitmap makes Allegro use that image in place of its own default 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. @@extern volatile int @mouse_x; @@extern volatile int @mouse_y; @@extern volatile int @mouse_z; @@extern volatile int @mouse_b; @@extern volatile int @mouse_pos; @xref install_mouse, poll_mouse, mouse_needs_poll @eref exalpha, exlights, exmouse, exshade, exspline, extrans @shortdesc Global variable with the mouse position/button state. 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: if (mouse_b & 1) printf("Left button is pressed\n"); if (!(mouse_b & 2)) printf("Right button is not pressed\n"); 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: int pos, x, y; pos = mouse_pos; x = pos >> 16; y = pos & 0x0000ffff; @@extern BITMAP *@mouse_sprite; @@extern int @mouse_x_focus; @@extern int @mouse_y_focus; @xref set_mouse_sprite, set_mouse_sprite_focus @shortdesc Global variable with the mouse sprite and focus point. 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. @@void @show_mouse(BITMAP *bmp); @xref install_mouse, install_timer, set_mouse_sprite, scare_mouse @xref freeze_mouse_flag, show_os_cursor @eref exmouse, expal, exshade, exspline, exsyscur @shortdesc Tells Allegro to display a mouse pointer on the screen. 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. @@void @scare_mouse(); @xref unscare_mouse, scare_mouse_area, show_mouse @shortdesc Helper for hiding the mouse pointer before drawing. 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(). @@void @scare_mouse_area(int x, int y, int w, int h); @xref unscare_mouse, scare_mouse, show_mouse @shortdesc Helper for hiding the mouse cursor before drawing in an area. 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. @@void @unscare_mouse(); @xref scare_mouse, scare_mouse_area @shortdesc Undoes the effect of scare_mouse() or scare_mouse_area(). Undoes the effect of a previous call to scare_mouse() or scare_mouse_area(), restoring the original pointer state. @@int @show_os_cursor(int cursor); @xref show_mouse, set_mouse_cursor_bitmap, select_mouse_cursor @shortdesc Low level function to display the operating system cursor. In case you do not need Allegro's mouse cursor API, which automatically emulates a cursor in software if no other cursor is available, you can use this low level function to try to display or hide the system cursor directly. The cursor parameter takes the same values as select_mouse_cursor. This function is very similar to calling enable_hardware_cursor, select_mouse_cursor and show_mouse, but will not try to do anything if no system cursor is available. The most common use for this function is to just call it once at the beginning of the program to tell it to display the system cursor inside the Allegro window. The return value can be used to see if this 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. @retval Returns 0 if a system cursor is being displayed after the function returns, or -1 otherwise. @@extern volatile int @freeze_mouse_flag; @xref show_mouse @shortdesc Flag to avoid redrawing the mouse pointer. 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. @@void @position_mouse(int x, int y); @xref install_mouse, position_mouse_z, set_mouse_range, set_mouse_speed @shortdesc Moves the mouse to the specified screen position. Moves the mouse to the specified screen position. It is safe to call even when a mouse pointer is being displayed. @@void @position_mouse_z(int z); @xref install_mouse, position_mouse @shortdesc Sets the mouse wheel position global variable. Sets the mouse wheel position variable to the specified value. @@void @set_mouse_range(int x1, int y1, int x2, int y2); @xref install_mouse, set_mouse_speed, position_mouse @shortdesc Sets the area of the screen restricting mouse movement. 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). @@void @set_mouse_speed(int xspeed, int yspeed); @xref install_mouse, set_mouse_range, position_mouse @shortdesc Sets the mouse speed. Sets the mouse speed. Larger values of xspeed and yspeed represent slower mouse movement: the default for both is 2. @@void @set_mouse_sprite(BITMAP *sprite); @xref install_mouse, show_mouse, set_mouse_sprite_focus @eref exmouse @shortdesc Sets the mouse sprite. You don't like Allegro's mouse pointer? No problem. Use this function to supply an alternative of your own. If you change the pointer and then want to get Allegro's lovely arrow back again, call set_mouse_sprite(NULL). As a bonus, set_mouse_sprite(NULL) uses the current palette in choosing colors for the arrow. So if your arrow mouse sprite looks ugly after changing the palette, call set_mouse_sprite(NULL). @@void @set_mouse_sprite_focus(int x, int y); @xref set_mouse_sprite @eref exmouse @shortdesc Sets the mouse sprite focus. 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. @@void @get_mouse_mickeys(int *mickeyx, int *mickeyy); @xref install_mouse @eref exmouse @shortdesc How far the mouse has moved since the last call to this function. 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. @@extern void (*@mouse_callback)(int flags); @xref install_mouse @shortdesc User specified mouse callback. 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. @heading Timer routines Allegro can set up several virtual timer functions, all going at different speeds. Under DOS it will constantly reprogram the clock to make sure they are all called at the correct times. Because they alter the low level timer chip settings, these routines should not be used together with other DOS timer functions like the DJGPP uclock() routine. Moreover, the FPU state is not preserved across Allegro interrupts so you ought not to use floating point or MMX code inside timer interrupt handlers. Under other platforms, they are usually implemented using threads, which run parallel to the main thread. Therefore timer callbacks on such platforms will not block the main thread when called, so you may need to use appropriate synchronisation devices (eg. mutexes, semaphores, etc.) when accessing data that is shared by a callback and the main thread. (Currently Allegro does not provide such devices.) @@int @install_timer(); @xref remove_timer, install_int @eref Available Allegro examples @shortdesc Installs the Allegro timer interrupt handler. 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. @retval 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). @@void @remove_timer(); @xref install_timer, allegro_exit @shortdesc Removes the Allegro time handler. 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. @@int @install_int(void (*proc)(), int speed); @xref install_timer, remove_int, install_int_ex, install_param_int @eref exscn3d, exswitch, extimer, exzbuf @shortdesc Installs a user timer handler. 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. @retval Returns zero on success, or a negative number if there is no room to add a new user timer. @@int @install_int_ex(void (*proc)(), int speed); @xref install_timer, remove_int, install_int, install_param_int_ex @eref excamera, exsprite, extimer, exunicod, exupdate @shortdesc Adds or modifies a timer. 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: 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 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: volatile int counter; void my_timer_handler() { counter++; } END_OF_FUNCTION(my_timer_handler) and in your initialisation code you should lock the memory: LOCK_VARIABLE(counter); LOCK_FUNCTION(my_timer_handler); 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. @retval Returns zero on success, or a negative number if there is no room to add a new user timer. @@Macro @LOCK_VARIABLE(variable_name); @xref install_int, install_int_ex @eref exscn3d, exsprite, exswitch, extimer, exupdate, exzbuf @shortdesc Locks the memory of a variable used by a timer. 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. @@Macro @LOCK_FUNCTION(function_name); @xref install_int, install_int_ex @eref exkeys, exscn3d, exsprite, exswitch, extimer, exupdate, exzbuf @shortdesc Locks the memory of a function used by a timer. 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. @@Macro @END_OF_FUNCTION(function_name); @xref install_int, install_int_ex @eref exkeys, exscn3d, exsprite, exswitch, extimer, exupdate, exzbuf @shortdesc Locks the code used by a timer. 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. @@void @remove_int(void (*proc)()); @xref install_int, install_int_ex, remove_param_int @shortdesc Removes a timers. Removes a function from the list of user interrupt routines. At program termination, allegro_exit() does this automatically. @@int @install_param_int(void (*proc)(void *), void *param, int speed); @xref install_timer, remove_param_int, install_param_int_ex, install_int @shortdesc Installs a timer routine with a customizable parameter. 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(). @@int @install_param_int_ex(void (*proc)(void *), void *param, int speed); @xref install_timer, remove_param_int, install_param_int, install_int_ex @shortdesc Adds or modifies a timer with a customizable parameter. 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(). @@void @remove_param_int(void (*proc)(void *), void *param); @xref install_param_int, install_param_int_ex, remove_int @shortdesc Removes a timer with a customizable parameter. 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). @@extern volatile int @retrace_count; @eref ex3d, exblend, exdbuf, exflip, exlights @shortdesc Retrace count simulator. 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. @@void @rest(unsigned int time); @xref install_timer, rest_callback @xref vsync, d_yield_proc @eref exkeys, exmidi, exquat, exsample, exsprite, extimer, exunicod @shortdesc Waits a specified number of milliseconds or yields CPU. 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. @@void @rest_callback(long time, void (*callback)()) @xref install_timer, rest @shortdesc Like rest(), but calls the callback during the wait. 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(). @heading Keyboard routines The Allegro keyboard handler provides both buffered input and a set of flags storing the current state of each key. Note that it is not possible to correctly detect every combination of keys, due to the design of the PC keyboard. Up to two or three keys at a time will work fine, but if you press more than that the extras are likely to be ignored (exactly which combinations are possible seems to vary from one keyboard to another). On DOS, Allegro requires the user to specify the language of the keyboard mapping because it is impossible to obtain this information from the OS, otherwise the default US keyboard mapping will be used. Allegro comes with a prepackaged `keyboard.dat' file which you can put along with your binary. If this file is present, Allegro will be able to extract the keyboard mapping information stored there. However, the end user still needs to select which keyboard mapping to use. This can be 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. @@int @install_keyboard(); @xref remove_keyboard, poll_keyboard, key, keypressed, readkey, ureadkey @xref keyboard_callback, keyboard_ucallback, keyboard_lowlevel_callback @xref three_finger_flag, key_led_flag, set_leds, set_keyboard_rate @xref set_gfx_mode, Standard config variables @eref Available Allegro examples @shortdesc Installs the Allegro keyboard interrupt handler. 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: 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(); @retval 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). @@void @remove_keyboard(); @xref install_keyboard, allegro_exit, set_config_string @shortdesc Removes the Allegro keyboard handler. 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: remove_keyboard(); /* Switch to Spanish keyboard mapping. */ set_config_string("system", "keyboard", "es"); install_keyboard(); @@void @install_keyboard_hooks(int (*keypressed)(), int (*readkey)()); @xref install_keyboard, keypressed, readkey @shortdesc Installs custom keyboard hooks. 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. @@int @poll_keyboard(); @xref keyboard_needs_poll, install_keyboard, key, key_shifts @eref excamera, exsample, exstars @shortdesc Polls the keyboard. Wherever possible, Allegro will read the keyboard input asynchronously (ie. from inside an interrupt handler), but on some platforms that may not be possible, in which case you must call this routine at regular intervals to update the keyboard state variables. To help you test your keyboard polling code even if you are programming on a platform that doesn't require it, after the first time that you call this function Allegro will switch into polling mode, so from that point onwards you will have to call this routine in order to get any keyboard input at all, regardless of whether the current driver actually needs to be polled or not. The keypressed(), readkey(), and ureadkey() functions call poll_keyboard() automatically, so you only need to use this function when accessing the key[] array and key_shifts variable. @retval Returns zero on success, or a negative number on failure (ie. no keyboard driver installed). @@int @keyboard_needs_poll(); @xref poll_keyboard, install_keyboard, key @shortdesc Tells if the keyboard needs polling. Returns TRUE if the current keyboard driver is operating in polling mode. @@extern volatile char @key[KEY_MAX]; @xref install_keyboard, poll_keyboard, key_shifts @eref Available Allegro examples @shortdesc Array of flags indicating key state. 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: if (key[KEY_SPACE]) printf("Space is pressed\n"); 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: 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 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. @@extern volatile int @key_shifts; @xref install_keyboard, poll_keyboard, key @eref excamera, exkeys @shortdesc Bitmask containing the current state of modifier keys. 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: 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 Example: if (key[KEY_W]) { if (key_shifts & KB_SHIFT_FLAG) { /* User is pressing shift + W. */ } else { /* Hmmm... lower case W then. */ } } @@int @keypressed(); @xref install_keyboard, readkey, ureadkey, clear_keybuf @xref simulate_keypress, simulate_ukeypress @eref Available Allegro examples @shortdesc Tells if there are keypresses waiting in the input buffer. 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: while (!keypressed()) { /* Show cool animated logo. */ } /* So he skipped our title screen. */ @@int @readkey(); @xref install_keyboard, ureadkey, keypressed, clear_keybuf, simulate_keypress @eref Available Allegro examples @shortdesc Returns the next character from the keyboard buffer. 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: int val; ... val = readkey(); if ((val & 0xff) == 'd') /* by ASCII code */ allegro_message("You pressed 'd'\n"); if ((val >> 8) == KEY_SPACE) /* by scancode */ allegro_message("You pressed Space\n"); if ((val & 0xff) == 3) /* ctrl+letter */ allegro_message("You pressed Control+C\n"); if (val == (KEY_X << 8)) /* alt+letter */ allegro_message("You pressed Alt+X\n"); This function cannot return character values greater than 255. If you need to read Unicode input, use ureadkey() instead. @@int @ureadkey(int *scancode); @xref install_keyboard, readkey, keypressed, clear_keybuf, simulate_ukeypress @eref exkeys @shortdesc Returns the next unicode character from the keyboard buffer. 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: int val, scancode; ... val = ureadkey(&scancode); if (val == 0x00F1) allegro_message("You pressed n with tilde\n"); if (val == 0x00DF) allegro_message("You pressed sharp s\n"); You should be able to find Unicode character maps at http://www.unicode.org/. Remember that on DOS you must specify a custom keyboard map (like those found in `keyboard.dat') usually with the help of a configuration file specifying the language mapping (keyboard variable in system section of `allegro.cfg'), or you will get the default US keyboard mapping. @@int @scancode_to_ascii(int scancode); @xref scancode_to_name @shortdesc Converts a scancode to an ASCII character. 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: int ascii; ... ascii = scancode_to_ascii(scancode); allegro_message("You pressed '%c'\n", ascii); @@const char *@scancode_to_name(int scancode); @xref scancode_to_ascii @eref exkeys @shortdesc Converts a scancode to a key name. 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: char const *keyname = scancode_to_name(scancode); allegro_message("You pressed the %s key.", keyname); @@void @simulate_keypress(int key); @xref install_keyboard, simulate_ukeypress, keypressed, readkey @shortdesc Stuffs a key into the keyboard buffer. 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: simulate_keypress(KEY_SPACE << 8); if (readkey() == (KEY_SPACE << 8)) allegro_message("You simulated Alt+Space\n"); @@void @simulate_ukeypress(int key, int scancode); @xref install_keyboard, simulate_keypress, keypressed, ureadkey @shortdesc Stuffs an unicode key into the keyboard buffer. 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: /* We ignore the scancode simulation. */ simulate_ukeypress(0x00DF, 0); if (ureadkey(&scancode) == 0x00DF) allegro_message("You simulated sharp s\n"); @@extern int (*@keyboard_callback)(int key); @xref install_keyboard, readkey, ureadkey, keyboard_ucallback @xref keyboard_lowlevel_callback @shortdesc User specified keyboard callback handler. 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: int enigma_scrambler(int key) { /* Add one to both the scancode and ascii values. */ return (((key >> 8) + 1) << 8) | ((key & 0xff) + 1); } END_OF_FUNCTION(enigma_scrambler) ... install_timer(); LOCK_FUNCTION(enigma_scrambler); install_keyboard(); keyboard_callback = enigma_scrambler; Note that this callback will be ignored if you also set the unicode keyboard callback. @@extern int (*@keyboard_ucallback)(int key, int *scancode); @xref install_keyboard, readkey, ureadkey, keyboard_callback @xref keyboard_lowlevel_callback @shortdesc User specified unicode keyboard callback handler. 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: 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; Note that this keyboard callback has priority over the non unicode callback. If you set both, only the unicode one will work. @@extern void (*@keyboard_lowlevel_callback)(int scancode); @xref install_keyboard, keyboard_callback, keyboard_ucallback @eref exkeys @shortdesc User specified low level keyboard event handler. 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: volatile int key_down, key_up; void keypress_watcher(int scancode) { if (scancode & 0x80) { key_up = 1; } else { key_down = 1; } } END_OF_FUNCTION(keypress_watcher) ... install_timer(); LOCK_FUNCTION(silence_g_key); LOCK_VARIABLE(key_down); LOCK_VARIABLE(key_up); install_keyboard(); keyboard_lowlevel_callback = keypress_watcher; /* Disable keyboard repeat to get typewriter effect. */ set_keyboard_rate(0, 0); ... while (game_loop) { if (key_down) { key_down = 0; /* Play sample of typewriter key press. */ } if (key_up) { key_up = 0; /* Play sample of typewriter key release. */ } } @@void @set_leds(int leds); @xref install_keyboard, key_led_flag @shortdesc Sets the state of the keyboard LED indicators. 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: /* 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); 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. @@void @set_keyboard_rate(int delay, int repeat); @xref install_keyboard, readkey, ureadkey @shortdesc Sets the keyboard repeat rate. Sets the keyboard repeat rate. Times are given in milliseconds. Passing zero times will disable the key repeat. @@void @clear_keybuf(); @xref install_keyboard, keypressed, readkey, ureadkey @eref Available Allegro examples @shortdesc Clears the keyboard buffer. 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(). @@extern int @three_finger_flag; @xref install_keyboard @shortdesc Flag to desactivate the emergency exit key combination. 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. @@extern int @key_led_flag; @xref install_keyboard, set_leds @shortdesc Flag to prevent the keyboard LEDs from being updated. 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. @heading Joystick routines Unlike keyboard or mouse input, which are usually read through hardware interrupts by Allegro, joystick input functions have to be polled because there are no hardware interrupts for them on most platforms. This doesn't mean that you have to poll the joysticks on each line of code you want to read their values, but you should make sure to poll them at least once per frame in your game loop. Otherwise you face the possibility of reading stale incorrect data. @@int @install_joystick(int type); @xref remove_joystick, num_joysticks, load_joystick_data, calibrate_joystick @xref calibrate_joystick_name, poll_joystick, Standard config variables @xref JOY_TYPE_*/DOS, JOY_TYPE_*/Windows, JOY_TYPE_*/Linux @eref exjoy @shortdesc Initialises the joystick. Initialises the joystick, and calibrates the centre position value. 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 the joystick is in the middle position at the time. Example: textout_centre_ex(screen, font, "Center the joystick and press a key", SCREEN_W/2, SCREEN_H/2, red_color, -1); readkey(); if (install_joystick(JOY_TYPE_AUTODETECT) != 0) abort_on_error("Error initialising joystick!"); @retval 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. @@void @remove_joystick(); @xref install_joystick, allegro_exit @shortdesc Removes the joystick handler. Removes the joystick handler. You don't normally need to bother calling this, because allegro_exit() will do it for you. @@int @poll_joystick(); @xref install_joystick, joy, num_joysticks @eref exjoy @shortdesc Polls the joystick. The joystick is not interrupt driven, so you need to call this function every now and again to update the global position values. Example: do { /* Get joystick input */ poll_joystick(); /* Process input for the first joystick */ if (joy[0].button[0].b) first_button_pressed(); if (joy[0].button[1].b) second_button_pressed(); ... } while(!done); @retval Returns zero on success or a negative number on failure (usually because no joystick driver was installed). @@extern int @num_joysticks; @xref install_joystick, joy @eref exjoy @shortdesc Global variable saying how many joysticks there are. Global variable containing the number of active joystick devices. The current drivers support a maximum of four controllers. @@extern JOYSTICK_INFO @joy[n]; @xref install_joystick, poll_joystick, num_joysticks, calibrate_joystick @xref calibrate_joystick_name @eref exjoy @shortdesc Global array of joystick state information. 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: 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; The button status is stored in the structure: typedef struct JOYSTICK_BUTTON_INFO { int b; - boolean on/off flag char *name; - description of this button } JOYSTICK_BUTTON_INFO; 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: 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; 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: 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; This provides both analogue input in the pos field (ranging from -128 to 128 or from 0 to 255, depending on the type of the control), and digital values in the d1 and d2 fields. For example, when describing the X-axis position, the pos field will hold the horizontal position of the joystick, d1 will be set if it is moved left, and d2 will be set if it is moved right. Allegro will fill in all these values regardless of whether it is using a digital or analogue joystick, emulating the pos field for digital inputs by snapping it to the min, middle, and maximum positions, and emulating the d1 and d2 values for an analogue stick by comparing the current position with the centre point. The joystick flags field may contain any combination of the bit flags: JOYFLAG_DIGITAL
This control is currently providing digital input. JOYFLAG_ANALOGUE
This control is currently providing analogue input. JOYFLAG_CALIB_DIGITAL
This control will be capable of providing digital input once it has been calibrated, but is not doing this at the moment. JOYFLAG_CALIB_ANALOGUE
This control will be capable of providing analogue input once it has been calibrated, but is not doing this at the moment. JOYFLAG_CALIBRATE
Indicates that this control needs to be calibrated. Many devices require multiple calibration steps, so you should call the calibrate_joystick() function from a loop until this flag is cleared. JOYFLAG_SIGNED
Indicates that the analogue axis position is in signed format, ranging from -128 to 128. This is the case for all 2d directional controls. JOYFLAG_UNSIGNED
Indicates that the analogue axis position is in unsigned format, ranging from 0 to 255. This is the case for all 1d throttle controls. Note for people who spell funny: in case you don't like having to type "analogue", there are some #define aliases in allegro/joystick.h that will allow you to write "analog" instead. @@const char *@calibrate_joystick_name(int n); @xref install_joystick, calibrate_joystick, joy, num_joysticks @eref exjoy @shortdesc Returns the next calibration text string. As parameter pass the number of joystick you want to calibrate. @retval 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. @@int @calibrate_joystick(int n); @xref install_joystick, calibrate_joystick_name, joy, num_joysticks @eref exjoy @shortdesc Calibrates the specified joystick. 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: int i; for (i=0; i<num_joysticks; i++) { while (joy[i].flags & JOYFLAG_CALIBRATE) { char *msg = calibrate_joystick_name(i); textprintf_ex(..., "%s, and press a key\n", msg); readkey(); if (calibrate_joystick(i) != 0) { textprintf_ex(..., "oops!\n"); readkey(); exit(1); } } } @retval Returns zero on success, non-zero if the calibration could not be performed successfully. @@int @save_joystick_data(const char *filename); @xref load_joystick_data, set_config_file @shortdesc Saves joystick calibration data. 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. @retval Returns zero on success, non-zero if the data could not be saved. @@int @load_joystick_data(const char *filename); @xref install_joystick, save_joystick_data, set_config_file @shortdesc Loads joystick calibration data. 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. @retval Returns zero on success: if it fails the joystick state is undefined and you must reinitialise it from scratch. @@int @initialise_joystick(); @xref install_joystick @shortdesc Deprecated version of install_joystick(). Deprecated. Use install_joystick() instead. @heading @html @texinfo Graphics modes Graphics modes are the common denominator for most Allegro programs. While it is possible to write platform specific programs using Allegro which don't set a graphic mode through the routines provided in this chapter, these are not very common. The first thing to note is that due to the wide range of supported platforms, a graphic mode is the only way to safely communicate with the user. When Allegro was a DOS only library (versions 3.x and previous), it was frequent for programmers to use functions from the C standard library to communicate with the user, like calling printf() before setting a graphic mode or maybe scanf() to read the user's input. However, what would happen for such a game running under Windows where there is no default console output or it may be hidden from the user? Even if the game compiled successfully, it would be unplayable, especially if there was vital information for the user in those text only messages. Allegro provides the allegro_message() function to deal with this problem, but this is not a very user friendly method of communicating with the user and its main purpose is displaying small error like messages when no graphic mode is available. Therefore, the first thing your Allegro program should do is set a graphic mode, and from there on, use Allegro's text output routines to display messages to the user, just like `allegro/examples/exhello.c' does. Setting a graphic mode involves deciding how to allocate the memory of the video card for your program. On some platforms this means creating a virtual screen bigger than the physical resolution to do hardware scrolling or page flipping. Virtual screens can cause a lot of confusion, but they are really quite simple. Warning: patronising explanation coming up, so you may wish to skip the rest of this paragraph. Think of video memory as a rectangular piece of paper which is being viewed through a small hole (your monitor) in a bit of cardboard. Since the paper is bigger than the hole you can only see part of it at any one time, but by sliding the cardboard around you can alter which portion of the image is visible. You could just leave the hole in one position and ignore the parts of video memory that aren't visible, but you can get all sorts of useful effects by sliding the screen window around, or by drawing images in a hidden part of video memory and then flipping across to display them. For example, you could select a 640x480 mode in which the monitor acts as a window onto a 1024x1024 virtual screen, and then move the visible screen around in this larger area (hardware scrolling). Initially, with the visible screen positioned at the top left corner of video memory, this setup would look like: (0,0)------------(640,0)----(1024,0) | | | | visible screen | | | | | (0,480)----------(640,480) | | | | the rest of video memory | | | (0,1024)--------------------(1024,1024) 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:
  • GFX_AUTODETECT:
    Allegro will try to set the specified resolution with the current color depth in fullscreen mode. Failing that, it will try to repeat the same operation in windowed mode. If the call to set_gfx_mode() succeeds, you are guaranteed to have set the specified resolution in the current color depth, but you don't know if the program is running fullscreen or windowed.
  • GFX_AUTODETECT_FULLSCREEN:
    Allegro will try to set the specified resolution with the current color depth in fullscreen mode. If that is not possible, set_gfx_mode() will fail.
  • GFX_AUTODETECT_WINDOWED:
    Allegro will try to set the specified resolution with the current color depth in a windowed mode. If that is not possible, set_gfx_mode() will fail. When it comes to windowed modes, the `specified resolution' actually means the graphic area your program can draw on, without including window decorations (if any). Note that in windowed modes running with a color depth other than the desktop may result in non optimal performance due to internal color conversions in the graphic driver. Use desktop_color_depth() to your advantage in these situations.
  • GFX_SAFE:
    Using this driver Allegro guarantees that a graphic mode will always be set correctly. It will try to select the resolution that you request, and if that fails, it will fall back upon whatever mode is known to be reliable on the current platform (this is 320x200 VGA mode under DOS, a 640x480 resolution under Windows, the actual framebuffer's resolution under Linux if it's supported, etc). If it absolutely cannot set any graphics mode at all, it will return negative as usual, meaning that there's no possible video output on the machine, and that you should abort your program immediately, possibly after notifying this to the user with allegro_message. This fake driver is useful for situations where you just want to get into some kind of workable display mode, and can't be bothered with trying multiple different resolutions and doing all the error checking yourself. Note however, that after a successful call to set_gfx_mode with this driver, you cannot make any assumptions about the width, height or color depth of the screen: your code will have to deal with this little detail.
  • GFX_TEXT:
    Closes any previously opened graphics mode, making you unable to use the global variable `screen', and in those environments that have text modes, sets one previously used or the closest match to that (usually 80x25). With this driver the size parameters of set_gfx_mode don't mean anything, so you can leave them all to zero or any other number you prefer.
@@void @set_color_depth(int depth); @xref get_color_depth, set_gfx_mode, set_color_conversion, makecol, getr @xref desktop_color_depth @eref Available Allegro examples @shortdesc Sets the global pixel color depth. Sets the pixel format to be used by subsequent calls to set_gfx_mode() and create_bitmap(). Valid depths are 8 (the default), 15, 16, 24, and 32 bits. Example: 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"); } Note that the screen color depth won't change until the next successful call to set_gfx_mode(). @@int @get_color_depth(void); @xref set_color_depth, bitmap_color_depth @eref exrgbhsv @shortdesc Returns the current pixel color depth. 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(). @@void @request_refresh_rate(int rate); @xref set_gfx_mode, get_refresh_rate @shortdesc Requests a specific refresh rate during graphic mode switch. 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: 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!"); @@int @get_refresh_rate(void); @xref request_refresh_rate @shortdesc Returns the current refresh rate. Returns the current refresh rate, if known (not all drivers are able to report this information). Returns zero if the actual rate is unknown. @@GFX_MODE_LIST *@get_gfx_mode_list(int card); @xref destroy_gfx_mode_list, set_gfx_mode, set_color_depth @shortdesc Obtains a list of available video modes. 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: typedef struct GFX_MODE_LIST { int num_modes; GFX_MODE *mode; } GFX_MODE_LIST; The mode entry points to the actual list of video modes. typedef struct GFX_MODE { int width, height, bpp; } GFX_MODE; 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. @retval Returns a pointer to a list structure of the type GFX_MODE_LIST or NULL if the request could not be satisfied. @@void @destroy_gfx_mode_list(GFX_MODE_LIST *mode_list); @xref get_gfx_mode_list, set_gfx_mode, set_color_depth @shortdesc Frees the list created by get_gfx_mode_list(). Removes the mode list created by get_gfx_mode_list() from memory. Use this once you are done with the generated mode list to avoid memory leaks in your program. @@int @set_gfx_mode(int card, int w, int h, int v_w, int v_h); @xref set_color_depth, request_refresh_rate, screen, gfx_capabilities @xref allegro_error, Standard config variables, GFX_*/DOS, GFX_*/Windows @xref GFX_*/X, GFX_*/Linux, GFX_*/BeOS, GFX_*/MacOSX, create_video_bitmap @xref get_desktop_resolution, SCREEN_W, SCREEN_H, VIRTUAL_W, VIRTUAL_H @eref Available Allegro examples @shortdesc Sets a graphic video mode. 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. @retval Returns zero on success. On failure returns a negative number and stores a description of the problem in allegro_error. @@int @set_display_switch_mode(int mode); @xref set_display_switch_callback, get_display_switch_mode @eref exmidi, exswitch @shortdesc Tells Allegro how the program handles background switching. 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:
  • SWITCH_NONE
    Disables switching. This is the default in single-tasking systems like DOS. It may be supported on other platforms, but you should use it with caution, because your users won't be impressed if they want to switch away from your program, but you don't let them!
  • SWITCH_PAUSE
    Pauses the program whenever it is in the background. Execution will be resumed as soon as the user switches back to it. This is the default in most fullscreen multitasking environments, for example the Linux console, but not under Windows.
  • SWITCH_AMNESIA
    Like SWITCH_PAUSE, but this mode doesn't bother to remember the contents of video memory, so the screen, and any video bitmaps that you have created, will be erased after the user switches away and then back to your program. This is not a terribly useful mode to have, but it is the default for the fullscreen drivers under Windows because DirectDraw is too dumb to implement anything better.
  • SWITCH_BACKGROUND
    The program will carry on running in the background, with the screen bitmap temporarily being pointed at a memory buffer for the fullscreen drivers. You must take special care when using this mode, because bad things will happen if the screen bitmap gets changed around when your program isn't expecting it (see below).
  • SWITCH_BACKAMNESIA
    Like SWITCH_BACKGROUND, but this mode doesn't bother to remember the contents of video memory (see SWITCH_AMNESIA). It is again the only mode supported by the fullscreen drivers under Windows that lets the program keep running in the background.
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. @retval 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. @@int @set_display_switch_callback(int dir, void (*cb)()); @xref remove_display_switch_callback, set_display_switch_mode @eref exswitch @shortdesc Installs a switching notification callback. 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. @retval 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. @@void @remove_display_switch_callback(void (*cb)()); @xref set_display_switch_callback @shortdesc Removes a switching notification callback. 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. @@int @get_display_switch_mode(); @xref set_display_switch_mode @eref exswitch @shortdesc Returns the current display switching mode. Returns the current display switching mode, in the same format passed to set_display_switch_mode(). @@int @is_windowed_mode(void); @xref set_gfx_mode @shortdesc Tells if you are running in windowed mode. This function can be used to detect wether or not set_gfx_mode() selected a windowed mode. Example: if (set_gfx_mode(GFX_AUTODETECT, 640, 480, 0, 0) != 0) abort_on_error("Couldn't set graphic mode!"); if (is_windowed_mode()) { /* Windowed mode stuff. */ } else { /* Fullscreen mode stuff. */ } @retval 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. @@extern int @gfx_capabilities; @xref screen, create_video_bitmap, scroll_screen, request_scroll, show_mouse @xref enable_triple_buffer @eref ex3buf, exaccel, exsyscur, exupdate @shortdesc Bitfield describing video hardware capabilities. Bitfield describing the capabilities of the current graphics driver and video hardware. This may contain combination any of the flags: GFX_CAN_SCROLL:
Indicates that the scroll_screen() function may be used with this driver. GFX_CAN_TRIPLE_BUFFER:
Indicates that the request_scroll() and poll_scroll() functions may be used with this driver. If this flag is not set, it is possible that the enable_triple_buffer() function may be able to activate it. GFX_HW_CURSOR:
Indicates that a hardware mouse cursor is in use. When this flag is set, it is safe to draw onto the screen without hiding the mouse pointer first. Note that not every cursor graphic can be implemented in hardware: in particular VBE/AF only supports 2-color images up to 32x32 in size, where the second color is an exact inverse of the first. This means that Allegro may need to switch between hardware and software cursors at any point during the execution of your program, so you should not assume that this flag will remain constant for long periods of time. It only tells you whether a hardware cursor is in use at the current time, and may change whenever you hide/redisplay the pointer. GFX_SYSTEM_CURSOR
Indicates that the mouse cursor is the default system cursor, not Allegro's custom cursor. GFX_HW_HLINE:
Indicates that the normal opaque version of the hline() function is implemented using a hardware accelerator. This will improve the performance not only of hline() itself, but also of many other functions that use it as a workhorse, for example circlefill(), triangle(), and floodfill(). GFX_HW_HLINE_XOR:
Indicates that the XOR version of the hline() function, and any other functions that use it as a workhorse, are implemented using a hardware accelerator. GFX_HW_HLINE_SOLID_PATTERN:
Indicates that the solid and masked pattern modes of the hline() function, and any other functions that use it as a workhorse, are implemented using a hardware accelerator (see note below). GFX_HW_HLINE_COPY_PATTERN:
Indicates that the copy pattern mode of the hline() function, and any other functions that use it as a workhorse, are implemented using a hardware accelerator (see note below). GFX_HW_FILL:
Indicates that the opaque version of the rectfill() function, the clear_bitmap() routine, and clear_to_color(), are implemented using a hardware accelerator. GFX_HW_FILL_XOR:
Indicates that the XOR version of the rectfill() function is implemented using a hardware accelerator. GFX_HW_FILL_SOLID_PATTERN:
Indicates that the solid and masked pattern modes of the rectfill() function are implemented using a hardware accelerator (see note below). GFX_HW_FILL_COPY_PATTERN:
Indicates that the copy pattern mode of the rectfill() function is implemented using a hardware accelerator (see note below). GFX_HW_LINE:
Indicates that the opaque mode line() and vline() functions are implemented using a hardware accelerator. GFX_HW_LINE_XOR:
Indicates that the XOR version of the line() and vline() functions are implemented using a hardware accelerator. GFX_HW_TRIANGLE:
Indicates that the opaque mode triangle() function is implemented using a hardware accelerator. GFX_HW_TRIANGLE_XOR:
Indicates that the XOR version of the triangle() function is implemented using a hardware accelerator. GFX_HW_GLYPH:
Indicates that monochrome character expansion (for text drawing) is implemented using a hardware accelerator. GFX_HW_VRAM_BLIT:
Indicates that blitting from one part of the screen to another is implemented using a hardware accelerator. If this flag is set, blitting within the video memory will almost certainly be the fastest possible way to display an image, so it may be worth storing some of your more frequently used graphics in an offscreen portion of the video memory. GFX_HW_VRAM_BLIT_MASKED:
Indicates that the masked_blit() routine is capable of a hardware accelerated copy from one part of video memory to another, and that draw_sprite() will use a hardware copy when given a sub-bitmap of the screen or a video memory bitmap as the source image. If this flag is set, copying within the video memory will almost certainly be the fastest possible way to display an image, so it may be worth storing some of your more frequently used sprites in an offscreen portion of the video memory. Warning: if this flag is not set, masked_blit() and draw_sprite() will not work correctly when used with a video memory source image! You must only try to use these functions to copy within the video memory if they are supported in hardware. GFX_HW_MEM_BLIT:
Indicates that blitting from a memory bitmap onto the screen is being accelerated in hardware. GFX_HW_MEM_BLIT_MASKED:
Indicates that the masked_blit() and draw_sprite() functions are being accelerated in hardware when the source image is a memory bitmap and the destination is the physical screen. GFX_HW_SYS_TO_VRAM_BLIT:
Indicates that blitting from a system bitmap onto the screen is being accelerated in hardware. Note that some acceleration may be present even if this flag is not set, because system bitmaps can benefit from normal memory to screen blitting as well. This flag will only be set if system bitmaps have further acceleration above and beyond what is provided by GFX_HW_MEM_BLIT. GFX_HW_SYS_TO_VRAM_BLIT_MASKED:
Indicates that the masked_blit() and draw_sprite() functions are being accelerated in hardware when the source image is a system bitmap and the destination is the physical screen. Note that some acceleration may be present even if this flag is not set, because system bitmaps can benefit from normal memory to screen blitting as well. This flag will only be set if system bitmaps have further acceleration above and beyond what is provided by GFX_HW_MEM_BLIT_MASKED. 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. @@int @enable_triple_buffer(); @xref gfx_capabilities, request_scroll, request_video_bitmap @eref ex3buf, exupdate @shortdesc Enables triple buffering. 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. @retval Returns zero if triple buffering is enabled, -1 otherwise. @@int @scroll_screen(int x, int y); @xref set_gfx_mode, show_video_bitmap, request_scroll, request_video_bitmap @eref exscroll @shortdesc Requests a hardware scroll request. 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(). @retval Returns zero on success. Returns non-zero if the graphics driver can't handle hardware scrolling or the virtual screen is not large enough. @@int @request_scroll(int x, int y); @xref poll_scroll, request_video_bitmap, gfx_capabilities @xref scroll_screen @shortdesc Queues a hardware scroll request with triple buffering. 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. @retval This function returns zero on success, non-zero otherwise. @@int @poll_scroll(); @xref request_scroll, request_video_bitmap @eref ex3buf, exupdate @shortdesc Checks the status of a scroll request with triple buffering. This function is used for triple buffering. It checks the status of a hardware scroll previously initiated by the request_scroll() routine. @retval Returns non-zero if it is still waiting to take place, and zero if the requested scroll has already happened. @@int @show_video_bitmap(BITMAP *bitmap); @xref scroll_screen, create_video_bitmap, Standard config variables @eref exaccel, exflip, exupdate @shortdesc Flips the hardware screen to use the specified page. 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: 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; ... @retval Returns zero on success and non-zero on failure. @@int @request_video_bitmap(BITMAP *bitmap); @xref poll_scroll, request_scroll, gfx_capabilities @xref create_video_bitmap, scroll_screen @eref ex3buf, exupdate @shortdesc Triple buffering page flip request. 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: 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; ... @retval Returns zero on success and non-zero on failure. @@void @vsync(); @xref set_palette, scroll_screen @eref Available Allegro examples @shortdesc Waits for a vertical retrace to begin. 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. @heading Bitmap objects Once you have selected a graphics mode, you can draw things onto the display via the `screen' bitmap. All the Allegro graphics routines draw onto BITMAP structures, which are areas of memory containing rectangular images, stored as packed byte arrays (in 8-bit modes one byte per pixel, in 15- and 16-bit modes two bytes per pixel, in 24-bit modes 3 bytes per pixel and in 32-bit modes 4 bytes per pixel). You can create and manipulate bitmaps in system RAM, or you can write to the special `screen' bitmap which represents the video memory in your graphics card. Read chapter "Direct access to video memory" for information on how to get direct access to the image memory in a bitmap. Allegro supports several different types of bitmaps:
  • 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.
  • 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.
  • 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.
  • 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().
  • 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().
@@extern BITMAP *@screen; @xref set_gfx_mode, is_screen_bitmap, create_video_bitmap, scroll_screen @eref Available Allegro examples @shortdesc Global pointer to the screen hardware video memory. 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: putpixel(screen, x, y, color); Or to implement a double-buffered system: /* 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); 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(). @@#define @SCREEN_W; @@#define @SCREEN_H; @xref screen, set_gfx_mode, VIRTUAL_W, VIRTUAL_H @eref Available Allegro examples @shortdesc Global define to obtain the size of the screen. Global defines that return the width and height of the screen, or zero if the screen has not been initialised yet. Example: char buf[100]; ... uszprintf(buf, sizeof(buf), "The screen size is %d x %d pixels", SCREEN_W, SCREEN_H); @@#define @VIRTUAL_W; @@#define @VIRTUAL_H; @xref screen, set_gfx_mode, SCREEN_W, SCREEN_H @shortdesc Global define to obtain the virtual size of the screen. Global defines that return the width and height of the virtual screen, or zero if the screen has not been initialised yet. Example: char buf[100]; ... uszprintf(buf, sizeof(buf), "The virtual screen size is %d x %d pixels", SCREEN_W, SCREEN_H); @@BITMAP *@create_bitmap(int width, int height); @xref create_bitmap_ex, create_sub_bitmap, create_video_bitmap @xref create_system_bitmap, destroy_bitmap, set_color_depth, is_memory_bitmap @xref clear_bitmap, clear_to_color @eref Available Allegro examples @shortdesc Creates a memory bitmap. 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: /* 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); @retval 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. @@BITMAP *@create_bitmap_ex(int color_depth, int width, int height); @xref create_bitmap, create_sub_bitmap, create_video_bitmap @xref create_system_bitmap, destroy_bitmap, is_memory_bitmap @xref clear_bitmap, clear_to_color @eref ex12bit, exlights, exrgbhsv, extrans @shortdesc Creates a memory bitmap specifying color depth. Creates a bitmap in a specific color depth (8, 15, 16, 24 or 32 bits per pixel). Example: /* Create screen sized bitmap in 32 bits per pixel. /* BITMAP *bmp = create_bitmap_ex(32, SCREEN_W, SCREEN_H); if (!bmp) abort_on_error("Couldn't create bitmap!"); /* Use the bitmap. */ ... /* Destroy it when we don't need it any more. */ destroy_bitmap(bmp); @retval 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. @@BITMAP *@create_sub_bitmap(BITMAP *parent, int x, y, width, height); @xref create_bitmap, create_bitmap_ex, destroy_bitmap, is_sub_bitmap @xref clear_bitmap, clear_to_color @eref expat, exscroll, exswitch @shortdesc Creates a memory sub bitmap. 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. @retval 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. @@BITMAP *@create_video_bitmap(int width, int height); @xref create_bitmap, create_bitmap_ex, create_system_bitmap @xref create_sub_bitmap, destroy_bitmap, screen, show_video_bitmap @xref gfx_capabilities, is_video_bitmap, clear_bitmap, clear_to_color @eref ex3buf, exaccel, exflip, exupdate @shortdesc Creates a video memory bitmap. 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. @retval 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(). @@BITMAP *@create_system_bitmap(int width, int height); @xref create_bitmap, create_bitmap_ex, create_video_bitmap @xref create_sub_bitmap, destroy_bitmap, is_system_bitmap @xref clear_bitmap, clear_to_color @eref exupdate @shortdesc Creates a system memory bitmap. 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. @retval Returns a pointer to the bitmap on success, NULL otherwise. Remember to destroy this bitmap before any subsequent call to set_gfx_mode(). @@void @destroy_bitmap(BITMAP *bitmap); @xref create_bitmap, load_bitmap @eref Available Allegro examples @shortdesc Destroys any type of created bitmap. Destroys a memory bitmap, sub-bitmap, video memory bitmap, or system bitmap when you are finished with it. If you pass a NULL pointer this function won't do anything. See above for the restrictions as to when you are allowed to destroy the various types of bitmaps. @@void @lock_bitmap(BITMAP *bitmap); @shortdesc Locks the memory used by a bitmap. Under DOS, locks all the memory used by a bitmap. You don't normally need to call this function unless you are doing very weird things in your program. @@int @bitmap_color_depth(BITMAP *bmp); @xref set_color_depth, bitmap_mask_color @eref ex3d, exlights, exscn3d, exswitch, extrans, exupdate, exzbuf @shortdesc Returns the color depth of the specified bitmap. Returns the color depth of the specified bitmap (8, 15, 16, 24, or 32). Example: switch (bitmap_color_depth(screen)) { case 8: /* Access screen using optimized 8-bit code. */ break; default: /* Use generic slow functions. */ break; } @@int @bitmap_mask_color(BITMAP *bmp); @xref MASK_COLOR_8, set_color_depth, bitmap_color_depth @eref ex3d, exmouse, expat @shortdesc Returns the mask color of the specified bitmap. 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: /* 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); @@int @is_same_bitmap(BITMAP *bmp1, BITMAP *bmp2); @xref create_sub_bitmap @shortdesc Tells if two bitmaps describe the same drawing surface. 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. @@int @is_planar_bitmap(BITMAP *bmp); @xref is_linear_bitmap, is_memory_bitmap @shortdesc Tells if a bitmap is a planar screen bitmap. Returns TRUE if bmp is a planar (mode-X or Xtended mode) screen bitmap. @@int @is_linear_bitmap(BITMAP *bmp); @xref is_planar_bitmap, is_memory_bitmap @shortdesc Tells if a bitmap is linear. 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(). @@int @is_memory_bitmap(BITMAP *bmp); @xref is_linear_bitmap, is_planar_bitmap @shortdesc Tells if a bitmap is a memory bitmap. Returns TRUE if bmp is a memory bitmap, ie. it was created by calling create_bitmap() or loaded from a grabber datafile or image file. Memory bitmaps can be accessed directly via the line pointers in the bitmap structure, eg. bmp->line[y][x] = color. @@int @is_screen_bitmap(BITMAP *bmp); @xref screen, create_sub_bitmap @shortdesc Tells if a bitmap is the screen bitmap or sub bitmap. Returns TRUE if bmp is the screen bitmap, or a sub-bitmap of the screen. @@int @is_video_bitmap(BITMAP *bmp); @xref screen, create_video_bitmap, create_sub_bitmap @shortdesc Tells if a bitmap is a screen bitmap, video memory or sub bitmap. Returns TRUE if bmp is the screen bitmap, a video memory bitmap, or a sub-bitmap of either. @@int @is_system_bitmap(BITMAP *bmp); @xref create_system_bitmap, create_sub_bitmap @shortdesc Tells if a bitmap is a system bitmap or sub bitmap. Returns TRUE if bmp is a system bitmap object, or a sub-bitmap of one. @@int @is_sub_bitmap(BITMAP *bmp); @xref create_sub_bitmap @shortdesc Tells if a bitmap is a sub bitmap. Returns TRUE if bmp is a sub-bitmap. @@void @acquire_bitmap(BITMAP *bmp); @xref release_bitmap, acquire_screen, release_screen @eref ex3buf, exaccel, expat, exquat, exscroll, exswitch, exupdate @shortdesc Locks the bitmap before drawing onto it. Locks the specified video memory bitmap prior to drawing onto it. This does not apply to memory bitmaps, and only affects some platforms (Windows needs it, DOS does not). These calls are not strictly required, because the drawing routines will automatically acquire the bitmap before accessing it, but locking a DirectDraw surface 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, and only release it when the drawing is completely finished. Multiple acquire calls may be nested, and the bitmap will only be truly released when the lock count returns to zero. Be warned that DirectX programs activate a mutex lock whenever a surface is locked, which prevents them from getting any input messages, so you must be sure to release all your bitmaps before using any timer, keyboard, or other non-graphics routines! Note that if you are using hardware accelerated VRAM->VRAM blits, you should not call acquire_bitmap(). @@void @release_bitmap(BITMAP *bmp); @xref acquire_bitmap, acquire_screen, release_screen @eref ex3buf, exaccel, expat, exquat, exscroll, exswitch, exupdate @shortdesc Releases a previously locked bitmap. 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. @@void @acquire_screen(); @xref acquire_bitmap, release_bitmap, release_screen @eref Available Allegro examples @shortdesc Shortcut of acquire_bitmap(screen); Shortcut version of acquire_bitmap(screen); @@void @release_screen(); @xref acquire_bitmap, release_bitmap, acquire_screen @eref Available Allegro examples @shortdesc Shortcut of release_bitmap(screen); Shortcut version of release_bitmap(screen); @@void @set_clip_rect(BITMAP *bitmap, int x1, int y1, int x2, int y2); @xref get_clip_rect, add_clip_rect, set_clip_state, get_clip_state @eref ex12bit, excamera @shortdesc Sets the clipping rectangle of a bitmap. 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. set_clip_rect(bmp, 0, 0, -1, -1); /* disable drawing on bmp */ 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. @@void @get_clip_rect(BITMAP *bitmap, int *x1, int *y1, int *x2, int *y2); @xref set_clip_rect, add_clip_rect, set_clip_state, get_clip_state @shortdesc Returns the clipping rectangle of a bitmap. Returns the clipping rectangle for the specified bitmap. @@void @add_clip_rect(BITMAP *bitmap, int x1, int y1, int x2, int y2); @xref set_clip_rect, get_clip_rect, set_clip_state, get_clip_state @shortdesc Expands a bitmap's clipping rectangle with a new area. Sets the clipping rectangle of the specified bitmap as the intersection of its current clipping rectangle and the rectangle described by the four coordinates. @@void @set_clip_state(BITMAP *bitmap, int state) @xref set_clip_rect, get_clip_rect, add_clip_rect, get_clip_state @shortdesc Turns on or off the clipping of a bitmap. 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. @@int @get_clip_state(BITMAP *bitmap) @xref set_clip_rect, get_clip_rect, add_clip_rect, set_clip_state @shortdesc Tells if clipping is on for a bitmap. Returns non-zero if clipping is turned on for the specified bitmap and zero otherwise. @@int @is_inside_bitmap(BITMAP *bmp, int x, int y, int clip); @xref set_clip_rect, set_clip_state, getpixel @shortdesc Tells if a point is inside a bitmap. 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. @heading Loading image files Warning: when using truecolor images, you should always set the graphics mode before loading any bitmap data! Otherwise the pixel format (RGB or BGR) will not be known, so the file may be converted wrongly. @@BITMAP *@load_bitmap(const char *filename, RGB *pal); @xref load_bmp, load_lbm, load_pcx, load_tga, destroy_bitmap, save_bitmap @xref register_bitmap_file_type, set_color_depth, set_color_conversion @xref generate_optimized_palette, generate_332_palette @eref exaccel, exalpha, exbitmap, exblend, exconfig, exlights, exshade @eref extrans, exxfade @shortdesc Loads any supported bitmap from a file. 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: BITMAP *bmp; PALETTE palette; ... bmp = load_bitmap("image.pcx", palette); if (!bmp) abort_on_error("Couldn't load image.pcx!"); ... destroy_bitmap(bmp); @retval 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. @@BITMAP *@load_bmp(const char *filename, RGB *pal); @xref load_bitmap, load_bmp_pf @shortdesc Loads a BMP bitmap from a file. Loads an 8-bit, 16-bit, 24-bit or 32-bit Windows or OS/2 BMP file. @retval 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. @@BITMAP *@load_bmp_pf(PACKFILE *f, RGB *pal); @xref load_bmp @eref expackf @shortdesc Packfile version of load_bmp. A version of load_bmp() which reads from a packfile. Example: PACKFILE *packfile; BITMAP *bmp; packfile = pack_fopen("mybitmap.bmp", F_READ); if (!packfile) abort_on_error("Couldn't open mybitmap.bmp"); bmp = load_bmp_pf(packfile, pal); if (!bmp) abort_on_error("Error loading mybitmap.bmp"); @retval 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. @@BITMAP *@load_lbm(const char *filename, RGB *pal); @xref load_bitmap @shortdesc Loads an LBM bitmap from a file. Loads a 256-color IFF ILBM/PBM file. @retval 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. @@BITMAP *@load_pcx(const char *filename, RGB *pal); @xref load_bitmap @eref expackf, exscale @shortdesc Loads a PCX bitmap from a file. Loads a 256-color or 24-bit truecolor PCX file. @retval 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. @@BITMAP *@load_pcx_pf(PACKFILE *f, RGB *pal); @xref load_pcx @eref expackf @shortdesc Packfile version of load_pcx. A version of load_pcx() which reads from a packfile. Example: PACKFILE *packfile; BITMAP *bmp; packfile = pack_fopen("mybitmap.pcx", F_READ); if (!packfile) abort_on_error("Couldn't open mybitmap.pcx"); bmp = load_bmp_pf(packfile, pal); if (!bmp) abort_on_error("Error loading mybitmap.pcx"); @retval 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. @@BITMAP *@load_tga(const char *filename, RGB *pal); @xref load_bitmap @shortdesc Loads a TGA bitmap from a file. Loads a 256-color, 15-bit hicolor, 24-bit truecolor, or 32-bit truecolor+alpha TGA file. @retval 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. @@BITMAP *@load_tga_pf(PACKFILE *f, RGB *pal); @xref load_tga @eref expackf @shortdesc Packfile version of load_tga. A version of load_tga() which reads from a packfile. Example: PACKFILE *packfile; BITMAP *bmp; packfile = pack_fopen("mybitmap.tga", F_READ); if (!packfile) abort_on_error("Couldn't open mybitmap.tga"); bmp = load_bmp_pf(packfile, pal); if (!bmp) abort_on_error("Error loading mybitmap.tga"); @retval 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. @@int @save_bitmap(const char *filename, BITMAP *bmp, const RGB *pal); @xref save_bmp, save_pcx, save_tga, load_bitmap, register_bitmap_file_type @shortdesc Saves a bitmap into any supported file format. 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: 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); @retval Returns non-zero on error. @@int @save_bmp(const char *filename, BITMAP *bmp, const RGB *pal); @xref save_bitmap @shortdesc Saves a bitmap into a BMP file. Writes a bitmap into a 256-color or 24-bit truecolor BMP file. @retval Returns non-zero on error. @@int @save_bmp_pf(PACKFILE *f, RGB *pal); @xref save_bmp @eref expackf @shortdesc Packfile version of save_bmp. A version of save_bmp which writes to a packfile. @@int @save_pcx(const char *filename, BITMAP *bmp, const RGB *pal); @xref save_bitmap @shortdesc Saves a bitmap into a PCX file. Writes a bitmap into a 256-color or 24-bit truecolor PCX file. @retval Returns non-zero on error. @@int @save_pcx_pf(PACKFILE *f, RGB *pal); @xref save_pcx @shortdesc Packfile version of save_pcx. A version of save_pcx which writes to a packfile. @@int @save_tga(const char *filename, BITMAP *bmp, const RGB *pal); @xref save_bitmap @shortdesc Saves a bitmap into a TGA file. Writes a bitmap into a 256-color, 15-bit hicolor, 24-bit truecolor, or 32-bit truecolor+alpha TGA file. @retval Returns non-zero on error. @@int @save_tga_pf(PACKFILE *f, RGB *pal); @xref save_tga @eref expackf @shortdesc Packfile version of save_tga. A version of save_tga which writes to a packfile. @\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)); @xref load_bitmap, save_bitmap @shortdesc Registers custom bitmap loading/saving functions. 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: 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); @@void @set_color_conversion(int mode); @xref set_color_depth, load_bitmap, load_datafile, fixup_datafile @xref makecol15_dither, get_color_conversion @eref exalpha, exblend, exdata, exexedat, exlights, exxfade @shortdesc Tells Allegro how to convert images during loading time. 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: 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 For convenience, the following macros can be used to select common combinations of these flags: COLORCONV_EXPAND_256 // expand 256-color to hi/truecolor COLORCONV_REDUCE_TO_256 // reduce hi/truecolor to 256-color COLORCONV_EXPAND_15_TO_16 // expand 15-bit hicolor to 16-bit COLORCONV_REDUCE_16_TO_15 // reduce 16-bit hicolor to 15-bit COLORCONV_EXPAND_HI_TO_TRUE // expand 15/16-bit to 24/32-bit COLORCONV_REDUCE_TRUE_TO_HI // reduce 24/32-bit to 15/16-bit COLORCONV_24_EQUALS_32 // convert between 24- and 32-bit COLORCONV_TOTAL // everything to current format COLORCONV_PARTIAL // convert 15 <-> 16-bit and // 24 <-> 32-bit COLORCONV_MOST // all but hi/truecolor <-> 256 COLORCONV_DITHER // dither during all color reductions COLORCONV_KEEP_ALPHA // convert everything to current format // unless it would lose alpha information 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. @@int @get_color_conversion(); @xref set_color_conversion @shortdesc Returns the current color conversion mode. Returns the current color conversion mode. @heading Palette routines All the Allegro drawing functions use integer parameters to represent colors. In truecolor resolutions these numbers encode the color directly as a collection of red, green, and blue bits, but in a regular 256-color mode the values are treated as indexes into the current palette, which is a table listing the red, green and blue intensities for each of the 256 possible colors. Palette entries are stored in an RGB structure, which contains red, green and blue intensities in the VGA hardware format, ranging from 0-63, and is defined as: typedef struct RGB { unsigned char r, g, b; } RGB; It contains an additional field for the purpose of padding but you should not usually care about it. For example: RGB black = { 0, 0, 0 }; RGB white = { 63, 63, 63 }; RGB green = { 0, 63, 0 }; RGB grey = { 32, 32, 32 }; 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). @@void @set_color(int index, const RGB *p); @xref set_palette, get_color, _set_color @eref ex12bit, exrgbhsv, exscroll @shortdesc Sets the specified palette entry to the specified RGB triplet. 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: RGB rgb; ... vsync(); set_color(192, &rgb); @@void @_set_color(int index, const RGB *p); @xref set_color, set_gfx_mode @eref ex3buf @shortdesc Inline version of set_color(). 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). @@void @set_palette(const PALETTE p); @xref set_gfx_mode, set_palette_range, set_color, get_palette @xref select_palette, palette_color @eref Available Allegro examples @shortdesc Sets the entire palette of 256 colors. 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: BITMAP *bmp; PALETTE palette; ... bmp = load_bitmap(filename, palette); if (!bmp) abort_on_error("Couldn't load bitmap!"); set_palette(palette); @@void @set_palette_range(const PALETTE p, int from, int to, int vsync); @xref set_palette, get_palette_range @shortdesc Sets a specific range of the palette. 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: 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); @@void @get_color(int index, RGB *p); @xref get_palette, set_color @shortdesc Retrieves the specified palette entry. Retrieves the specified palette entry. Example: RGB color; ... get_color(11, &color); @@void @get_palette(PALETTE p); @xref get_palette_range, get_color, set_palette @shortdesc Retrieves the entire palette of 256 colors. Retrieves the entire palette of 256 colors. You should provide an array of 256 RGB structures to store it in. Example: PALETTE pal; ... get_palette(pal); @@void @get_palette_range(PALETTE p, int from, int to); @xref get_palette, set_palette_range @shortdesc Retrieves a specific palette range. Retrieves the palette entries between from and to (inclusive: pass 0 and 255 to get the entire palette). @\void @fade_interpolate(const PALETTE source, const PALETTE dest, @@ PALETTE output, int pos, int from, int to); @xref fade_in, fade_out, fade_from @shortdesc Calculates a new palette interpolated between two others. 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). @\void @fade_from_range(const PALETTE source, const PALETTE dest, @@ int speed, int from, int to); @xref fade_from @shortdesc Gradually fades a part of the palette between two others. 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. @@void @fade_in_range(const PALETTE p, int speed, int from, int to); @xref fade_in @shortdesc Gradually fades a part of the palette from black. 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. @@void @fade_out_range(int speed, int from, int to); @xref fade_out @shortdesc Gradually fades a part of the palette to black. 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. @@void @fade_from(const PALETTE source, const PALETTE dest, int speed); @xref fade_in, fade_out, fade_interpolate, fade_from_range @shortdesc Gradually fades the palette between two others. 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. @@void @fade_in(const PALETTE p, int speed); @xref fade_out, fade_from, fade_interpolate, fade_in_range @shortdesc Gradually fades the palette from black. 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. @@void @fade_out(int speed); @xref fade_in, fade_from, fade_interpolate, fade_in_range @eref ex12bit @shortdesc Gradually fades the palette to black. 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. @@void @select_palette(const PALETTE p); @xref set_palette, unselect_palette @eref exlights @shortdesc Sets the internal palette for color conversion. 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. @@void @unselect_palette(); @xref select_palette @shortdesc Restores the palette before last call to select_palette(). Restores the palette tables that were in use before the last call to select_palette(). @@void @generate_332_palette(PALETTE pal); @xref generate_optimized_palette, set_color_depth @eref excolmap, exrgbhsv, extruec, exupdate @shortdesc Constructs a fake truecolor palette. 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). @\int @generate_optimized_palette(BITMAP *bmp, PALETTE pal, @@ const char rsvd[PAL_SIZE]); @xref generate_332_palette, set_color_depth @shortdesc Generates an optimized palette for a bitmap. 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. @retval 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. @@extern PALETTE @default_palette; @xref black_palette, desktop_palette @eref exjoy @shortdesc The default IBM BIOS palette. The default IBM BIOS palette. This will be automatically selected whenever you set a new graphics mode. The palette contains 16 basic colors plus many gradients between them. If you want to see the values, you can write a small Allegro program which saves a screenshot with this palette, or open the grabber tool provided with Allegro and create a new palette object, which will use this palette by default. @@extern PALETTE @black_palette; @xref default_palette, desktop_palette @eref expal @shortdesc A palette containing solid black colors. A palette containing solid black colors, used by the fade routines. @@extern PALETTE @desktop_palette; @xref default_palette, black_palette @eref Available Allegro examples @shortdesc The palette used by the Atari ST low resolution desktop. 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. 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 @heading Truecolor pixel formats In a truecolor video mode the red, green, and blue components for each pixel are packed directly into the color value, rather than using a palette lookup table. In a 15-bit mode there are 5 bits for each color, in 16-bit modes there are 5 bits each of red and blue and six bits of green, and both 24 and 32-bit modes use 8 bits for each color (the 32-bit pixels simply have an extra padding byte to align the data nicely). The layout of these components can vary depending on your hardware, but will generally either be RGB or BGR. Since the layout is not known until you select the video mode you will be using, you must call set_gfx_mode() before using any of the following routines! @@int @makecol8(int r, int g, int b); @@int @makecol15(int r, int g, int b); @@int @makecol16(int r, int g, int b); @@int @makecol24(int r, int g, int b); @@int @makecol32(int r, int g, int b); @xref makeacol32, makecol, makecol_depth, makecol15_dither, rgb_map @xref bestfit_color, set_color_depth @eref exrgbhsv @shortdesc Converts an RGB value into a display dependent pixel format. 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: /* 16 bit color version of green. */ int green_color = makecol16(0, 255, 0); @retval Returns the requested RGB triplet in the specified color depth. @@int @makeacol32(int r, int g, int b, int a); @xref makeacol, set_alpha_blender, set_write_alpha_blender @shortdesc Converts an RGBA color into a 32-bit display pixel format. 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. @@int @makecol(int r, int g, int b); @xref makeacol, makecol8, makecol_depth, makecol15_dither, rgb_map @xref set_color_depth @eref Available Allegro examples @shortdesc Converts an RGB value into the current pixel format. 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: /* Regardless of color depth, this will look green. */ int green_color = makecol(0, 255, 0); @retval Returns the requested RGB triplet in the current color depth. @@int @makecol_depth(int color_depth, int r, int g, int b); @xref makeacol, makecol, makecol8, makecol15_dither, rgb_map @xref set_color_depth @shortdesc Converts an RGB value into the specified pixel format. 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: /* Compose the green color for 15 bit color depth. */ int green_15bit = makecol_depth(15, 0, 255, 0); @retval Returns the requested RGB triplet in the specified color depth. @@int @makeacol(int r, int g, int b, int a); @@int @makeacol_depth(int color_depth, int r, int g, int b, int a); @xref makecol, makecol_depth, set_alpha_blender, set_write_alpha_blender @shortdesc Converts RGBA colors into display dependent pixel formats. 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. @retval Returns the requested RGBA quadruplet. @@int @makecol15_dither(int r, int g, int b, int x, int y); @@int @makecol16_dither(int r, int g, int b, int x, int y); @xref makecol, makecol8, set_color_conversion @shortdesc Calculates a dithered 15 or 16-bit RGB value. 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: 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); @retval Returns the RGB value dithered for the specified coordinate. @@int @getr8(int c); @@int @getg8(int c); @@int @getb8(int c); @@int @getr15(int c); @@int @getg15(int c); @@int @getb15(int c); @@int @getr16(int c); @@int @getg16(int c); @@int @getb16(int c); @@int @getr24(int c); @@int @getg24(int c); @@int @getb24(int c); @@int @getr32(int c); @@int @getg32(int c); @@int @getb32(int c); @xref geta32, getr, getr_depth, makecol, set_color_depth @shortdesc Extract a color component from the specified pixel format. Given a color in a display dependent format, these functions extract one of the red, green, or blue components (ranging 0-255). Example: int r, g, b, color_value; color_value = _getpixel15(screen, 100, 100); r = getr15(color_value); g = getg15(color_value); b = getb15(color_value); @@int @geta32(int c); @xref getr8 @shortdesc Extract the alpha component form a 32-bit pixel format color. Given a color in a 32-bit pixel format, this function extracts the alpha component (ranging 0-255). @@int @getr(int c); @@int @getg(int c); @@int @getb(int c); @@int @geta(int c); @xref getr8, getr_depth, makecol, set_color_depth @eref exalpha @shortdesc Extract a color component from the current pixel format. 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: int r, g, b, color_value; color_value = getpixel(screen, 100, 100); r = getr(color_value); g = getg(color_value); b = getb(color_value); @@int @getr_depth(int color_depth, int c); @@int @getg_depth(int color_depth, int c); @@int @getb_depth(int color_depth, int c); @@int @geta_depth(int color_depth, int c); @xref getr, getr8, geta32, makecol, set_color_depth @eref exlights @shortdesc Extract a color component from a color in a specified pixel format. 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: 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); @@extern int @palette_color[256]; @xref set_palette, makecol, set_color_depth @eref Available Allegro examples @shortdesc Maps palette indexes into the current pixel format colors. 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: 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]); @@#define @MASK_COLOR_8 0 @@#define @MASK_COLOR_15 (5.5.5 pink) @@#define @MASK_COLOR_16 (5.6.5 pink) @@#define @MASK_COLOR_24 (8.8.8 pink) @@#define @MASK_COLOR_32 (8.8.8 pink) @xref bitmap_mask_color, makecol, draw_sprite, masked_blit @shortdesc Constant representing the mask value in sprites. 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). @heading Drawing primitives Except for _putpixel(), all these routines are affected by the current drawing mode and the clipping rectangle of the destination bitmap. Unless specified otherwise, all coordinates for drawing operations are inclusive, and they, as well as lengths, are specified in pixel units. @@void @clear_bitmap(BITMAP *bitmap); @xref clear_to_color @eref Available Allegro examples @shortdesc Clears the bitmap to color 0. Clears the bitmap to color 0. @@void @clear_to_color(BITMAP *bitmap, int color); @xref clear_bitmap, makecol @eref Available Allegro examples @shortdesc Clears the bitmap to the specified color. Clears the bitmap to the specified color. Example: /* Clear the screen to red. */ clear_to_color(bmp, makecol(255, 0, 0)); @@void @putpixel(BITMAP *bmp, int x, int y, int color); @xref getpixel, _putpixel, drawing_mode, makecol @eref ex12bit, exalpha, exflame, exjoy, exstars, exswitch @shortdesc Writes a pixel into a bitmap. Writes a pixel to the specified position in the bitmap, using the current drawing mode and the bitmap's clipping rectangle. Example: putpixel(screen, 10, 30, some_color); @@void @_putpixel(BITMAP *bmp, int x, int y, int color); @@void @_putpixel15(BITMAP *bmp, int x, int y, int color); @@void @_putpixel16(BITMAP *bmp, int x, int y, int color); @@void @_putpixel24(BITMAP *bmp, int x, int y, int color); @@void @_putpixel32(BITMAP *bmp, int x, int y, int color); @xref putpixel, makecol @shortdesc Faster specific version of putpixel(). 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. @@int @getpixel(BITMAP *bmp, int x, int y); @xref putpixel, _getpixel, is_inside_bitmap @eref ex12bit, exalpha, exflame, exlights @shortdesc Reads a pixel from a bitmap. Reads a pixel from point (x, y) in the bitmap. @retval 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(). @@int @_getpixel(BITMAP *bmp, int x, int y); @@int @_getpixel15(BITMAP *bmp, int x, int y); @@int @_getpixel16(BITMAP *bmp, int x, int y); @@int @_getpixel24(BITMAP *bmp, int x, int y); @@int @_getpixel32(BITMAP *bmp, int x, int y); @xref getpixel @shortdesc Faster specific version of getpixel(). 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. @retval Returns the value of the pixel in the color format you specified. @@void @vline(BITMAP *bmp, int x, int y1, int y2, int color); @xref hline, line, drawing_mode, makecol @xref Differences between platforms @eref exrgbhsv, exscroll, extruec @shortdesc Draws a vertical line onto the bitmap. 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. @@void @hline(BITMAP *bmp, int x1, int y, int x2, int color); @xref vline, line, drawing_mode, makecol @xref Differences between platforms @eref exsprite @shortdesc Draws a horizontal line onto the bitmap. 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. @\void @do_line(BITMAP *bmp, int x1, y1, x2, y2, int d, @@ void (*proc)(BITMAP *bmp, int x, int y, int d)); @xref do_circle, do_ellipse, do_arc, line @shortdesc Calculates all the points along a line. 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: 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); @@void @line(BITMAP *bmp, int x1, int y1, int x2, int y2, int color); @xref fastline, hline, vline, do_line, drawing_mode, makecol @eref Available Allegro examples @shortdesc Draws a line onto the bitmap. Draws a line onto the bitmap, from point (x1, y1) to (x2, y2). @@void @fastline(BITMAP *bmp, int x1, int y1, int x2, int y2, int color); @xref line, hline, vline, do_line, drawing_mode, makecol @eref Available Allegro examples @shortdesc Faster version of line(). Faster version of the previous function. Note that pixel correctness is not guaranteed for this function. @@void @triangle(BITMAP *bmp, int x1, y1, x2, y2, x3, y3, int color); @xref polygon, triangle3d, drawing_mode, makecol @eref ex3buf, exstars, exupdate @shortdesc Draws a filled triangle. Draws a filled triangle between the three points. @@void @polygon(BITMAP *bmp, int vertices, const int *points, int color); @xref triangle, polygon3d, drawing_mode, makecol @eref excamera @shortdesc Draws a filled polygon. 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: 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)); @@void @rect(BITMAP *bmp, int x1, int y1, int x2, int y2, int color); @xref rectfill, drawing_mode, makecol @eref ex3d, excamera @shortdesc Draws an outline rectangle. Draws an outline rectangle with the two points as its opposite corners. @@void @rectfill(BITMAP *bmp, int x1, int y1, int x2, int y2, int color); @xref rect, clear_bitmap, drawing_mode, makecol @eref exalpha, excolmap, exkeys, exmidi, expat, exscroll, exsprite @eref exstars, exswitch, extrans @shortdesc Draws a solid filled rectangle. Draws a solid, filled rectangle with the two points as its opposite corners. @\void @do_circle(BITMAP *bmp, int x, int y, int radius, int d, @@ void (*proc)(BITMAP *bmp, int x, int y, int d)); @xref do_ellipse, do_arc, do_line, circle, circlefill @shortdesc Calculates all the points in a circle. 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: 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); @@void @circle(BITMAP *bmp, int x, int y, int radius, int color); @xref ellipse, arc, circlefill, do_circle, drawing_mode, makecol @eref ex12bit, exblend, excustom, exjoy, exmem, exmouse, exquat, exsprite @shortdesc Draws a circle. Draws a circle with the specified centre and radius. @@void @circlefill(BITMAP *bmp, int x, int y, int radius, int color); @xref ellipsefill, circle, do_circle, drawing_mode, makecol @eref excolmap, excustom, exdbuf, exflip, exlights, expal, exspline @eref extrans @shortdesc Draws a filled circle. Draws a filled circle with the specified centre and radius. @\void @do_ellipse(BITMAP *bmp, int x, int y, int rx, ry, int d, @@ void (*proc)(BITMAP *bmp, int x, int y, int d)); @xref do_circle, do_arc, do_line, ellipse, ellipsefill @shortdesc Calculates all the points in an ellipse. 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: 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); @@void @ellipse(BITMAP *bmp, int x, int y, int rx, int ry, int color); @xref circle, arc, ellipsefill, do_ellipse, drawing_mode, makecol @shortdesc Draws an ellipse. Draws an ellipse with the specified centre and radius. @@void @ellipsefill(BITMAP *bmp, int x, int y, int rx, int ry, int color); @xref circlefill, ellipse, do_ellipse, drawing_mode, makecol @eref ex12bit @shortdesc Draws a filled ellipse. Draws a filled ellipse with the specified centre and radius. @\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)); @xref do_circle, do_ellipse, do_line, arc @shortdesc Calculates all the points in a circular arc. 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: void draw_explosion_ring(BITMAP *bmp, int x, int y, int d) { ... } arc(screen, SCREEN_W/2, SCREEN_H/2, itofix(-21), itofix(43), 50, flame_color, draw_explosion_ring); @@void @arc(BITMAP *bmp, int x, y, fixed ang1, ang2, int r, int color); @xref circle, ellipse, drawing_mode, makecol @shortdesc Draws a circular arc. 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: /* 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)); @@void @calc_spline(const int points[8], int npts, int *x, int *y); @xref spline @eref exspline @shortdesc Calculates a series of values along a bezier spline. 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. @@void @spline(BITMAP *bmp, const int points[8], int color); @xref calc_spline, drawing_mode, makecol @eref exspline @shortdesc Draws a bezier spline using four control points. 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. @@void @floodfill(BITMAP *bmp, int x, int y, int color); @xref drawing_mode, makecol @shortdesc Floodfills an enclosed area. Floodfills an enclosed area, starting at point (x, y), with the specified color. @heading Blitting and sprites As far as Allegro is concerned, a bitmap and a sprite are the same thing, but to many people the two words imply slightly different things. The function draw_sprite() is called so rather than draw_bitmap() partly because it indicates that it uses a masked drawing mode (if it existed, you could expect draw_bitmap() to be a simple block copy), and partly for historical reasons. In Allegro 1.0 there were actually different structures for sprites and bitmaps, each with their own set of abilities. Allegro 2.0 merged these into a single more flexible structure, but retained some names like draw_sprite(). In wider (non-Allegro) terms, the two words can mean quite different things. Generally you can say that sprites are a subset of bitmaps, but even that isn't true in 100% of cases. BITMAP: a widely accepted term that will be understood by anyone even remotely connected with computer graphics. It simply means an image built up from a grid of pixels, ie. just about any picture that you are likely to come across on a computer (vector graphics formats are the exception, but those must be rendered into a bitmap format before they can be displayed by most hardware). A more accurate term but slightly rarer term with the same meaning is "pixmap" (pixel-map). SPRITE: a particular usage of bitmapped images, restricted to video games (other types of programmer probably won't be familiar with this term). Originally on machines like the C64, sprites were a hardware feature that allowed a number of small bitmap images to be loaded into special registers, and they could then be superimposed over the main graphics display and moved around just by modifying the position register. They were used for the moving objects (player and enemy characters), and enabled the C64 to do much more impressive things than would have been possible if all the drawing had to be done directly by the puny CPU. Later on, a lot of old C64 programmers upgraded to machines like the Atari ST, which didn't have any special sprite hardware, but they carried on referring to their main moving objects as sprites (the routine to draw such a thing would obviously be called draw_sprite()). A sprite is really just a bitmap graphic which is drawn onto the screen, but when you call it a sprite rather than a bitmap, this suggests it is a gameplay element that can move freely around the world rather than being a static part of the environment, and that it will be drawn in a masked overlay mode rather than as a solid rectangle (there is also a strong implication that a sprite will be animated by cycling through a number of frames, but that isn't always the case). In recent years some people have started using "sprite" to refer to any character graphics, even if they are not in fact drawn as 2d bitmaps, eg. "this game uses 3d polygonal player sprites". This is a confusing misuse of the word (Doom uses sprites, Quake does not), but it does happen. The origin of the term "blit" is also rather interesting. This was originally BitBlt, an abbreviation of BITmap BLock Transfer, which was a function designed (possibly) by the people at Xerox who did so much of the pioneering work on graphics display systems, and subsequently copied by virtually everybody doing computer graphics (the Microsoft Windows GDI still provides a BitBlt function with identical functionality to the original). This routine was a workhorse for all sorts of drawing operations, basically copying bitmap graphics from one place to another, but including a number of different ROP modes (Raster OPerations) for doing things like XOR, inverting pixels, etc. A whole family of related words grew up around the BitBlt function, but "blt" is impossible to speak (try saying "bltter" or "bltting" :-) so people added the vowel to make it easier to pronounce. 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. @\void @blit(BITMAP *source, BITMAP *dest, int source_x, int source_y, @@ int dest_x, int dest_y, int width, int height); @xref masked_blit, stretch_blit, draw_sprite, gfx_capabilities, @xref set_color_conversion @eref Available Allegro examples @shortdesc Copies a rectangular area from one bitmap to another. 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: BITMAP *bmp; ... /* Blit src on the screen. */ blit(bmp, screen, 0, 0, 0, 0, bmp->w, bmp->h); /* Now copy a chunk to a corner, slightly outside. /* blit(screen, screen, 100, 100, -10, -10, 25, 30); 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. @\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); @xref blit, masked_stretch_blit, stretch_sprite @eref exalpha, exconfig, exscale, extrans @shortdesc Scales a rectangular area from one bitmap to another. 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: BITMAP *bmp; ... /* Stretch bmp to fill the screen. */ stretch_blit(bmp, screen, 0, 0, bmp->w, bmp->h, 0, 0, SCREEN_W, SCREEN_H); @\void @masked_blit(BITMAP *source, BITMAP *dest, int source_x, int source_y, @@ int dest_x, int dest_y, int width, int height); @xref blit, masked_stretch_blit, draw_sprite, bitmap_mask_color @eref ex12bit, expat @shortdesc Copies a rectangle skipping pixels with the mask color. 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: BITMAP *hud_overlay; ... /* Paint hud overlay on the screen. */ masked_blit(hud_overlay, screen, 0, 0, 0, 0, hud_overlay->w, hud_overlay->h); 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. @\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); @xref blit, masked_blit, stretch_blit, stretch_sprite @shortdesc Scales a rectangular area skipping pixels with the mask color. 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: BITMAP *hud_overlay; ... /* Stretch hud overlay over the screen. */ masked_stretch_blit(hud_overlay, screen, 0, 0, hud_overlay->w, hud_overlay->h, 0, 0, SCREEN_W, SCREEN_H); @@void @draw_sprite(BITMAP *bmp, BITMAP *sprite, int x, int y); @xref draw_sprite_v_flip, draw_trans_sprite, draw_lit_sprite @xref draw_gouraud_sprite, stretch_sprite, rotate_sprite, draw_character_ex @xref draw_rle_sprite, draw_compiled_sprite, masked_blit, blit @xref bitmap_mask_color @eref exsprite @shortdesc Draws a copy of the sprite onto the destination bitmap. Draws a copy of the sprite bitmap onto the destination bitmap at the specified position. This is almost the same as blit(sprite, bmp, 0, 0, x, y, sprite->w, sprite->h), but it uses a masked drawing mode where transparent pixels are skipped, so the background image will show through the masked parts of the sprite. Transparent pixels are marked by a zero in 256-color modes or bright pink for truecolor data (maximum red and blue, zero green). Example: BITMAP *spaceship; ... draw_sprite(screen, spaceship, x, y); 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. @@void @stretch_sprite(BITMAP *bmp, BITMAP *sprite, int x, int y, int w, int h); @xref draw_sprite, stretch_blit, bitmap_mask_color @shortdesc Stretches a sprite to the destination bitmap. 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: /* Create tunnel like effect. */ for (step = 1; step < 16; step++) { int width = SCREEN_W / f; int height = SCREEN_H / f; stretch_sprite(screen, image, SCREEN_W / 2 - width / 2, SCREEN_H / 2 - height / 2, width, height); } @@void @draw_sprite_v_flip(BITMAP *bmp, BITMAP *sprite, int x, int y); @@void @draw_sprite_h_flip(BITMAP *bmp, BITMAP *sprite, int x, int y); @@void @draw_sprite_vh_flip(BITMAP *bmp, BITMAP *sprite, int x, int y); @xref draw_sprite, bitmap_mask_color @eref exsprite @shortdesc Draws the sprite transformed to the destination bitmap. 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: 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); @@void @draw_trans_sprite(BITMAP *bmp, BITMAP *sprite, int x, int y); @xref draw_sprite, draw_lit_sprite, draw_trans_rle_sprite, color_map @xref set_trans_blender, set_alpha_blender, set_write_alpha_blender @xref bitmap_mask_color @eref exalpha, exblend, exlights, extrans, exxfade @shortdesc Draws a sprite blending it with the destination. 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: /* Some one time initialisation code. */ COLOR_MAP global_trans_table; create_trans_table(&global_trans_table, my_palette, 128, 128, 128, NULL); ... if (get_color_depth() == 8) color_map = &global_trans_table; else set_trans_blender(128, 128, 128, 128); draw_trans_sprite(buffer, ghost_sprite, x, y); 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. @@void @draw_lit_sprite(BITMAP *bmp, BITMAP *sprite, int x, int y, int color); @xref draw_sprite, draw_trans_sprite, draw_gouraud_sprite @xref draw_lit_rle_sprite, color_map, set_trans_blender, bitmap_mask_color @eref exblend @shortdesc Draws a sprite tinted with a specific color. In 256-color modes, uses the global color_map table to tint the sprite image to the specified color or to light it to the level specified by 'color', depending on the function which was used to build the table (create_trans_table or create_light_table), and draws the resulting image to the destination bitmap. In truecolor modes, uses the blender functions to light the sprite image using the alpha level specified by 'color' (the alpha level which was passed to the blender functions is ignored) and draws the resulting image to the destination bitmap. The 'color' parameter must be in the range [0-255] whatever its actual meaning is. This must only be used after you have set up the color mapping table (for 256-color modes) or blender functions (for truecolor modes). Example: /* Some one time initialisation code. */ COLOR_MAP global_light_table; create_light_table(&global_trans_table, my_palette, 10, 10, 60, NULL); ... if (get_color_depth() == 8) color_map = &global_light_table; else set_trans_blender(40, 40, 255, 255); /* Lit the cape with a blueish light. */ draw_lit_sprite(buffer, colored_cape, x, y); @\void @draw_gouraud_sprite(BITMAP *bmp, BITMAP *sprite, int x, int y, @@ int c1, int c2, int c3, int c4); @xref draw_sprite, draw_lit_sprite, color_map, set_trans_blender @xref bitmap_mask_color @eref exshade @shortdesc Draws a sprite with gouraud shading. 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: /* Some one time initialisation code. */ COLOR_MAP global_light_table; create_light_table(&global_trans_table, my_palette, 0, 0, 0, NULL); ... if (get_color_depth() == 8) color_map = &global_light_table; else set_trans_blender(0, 0, 0, 128); /* Enemies are in shadow unless lit by torch. */ draw_gouraud_sprite(buffer, menacing_spy, x, y, light_strength_on_corner_1, light_strength_on_corner_2, light_strength_on_corner_3, light_strength_on_corner_4); @\void @draw_character_ex(BITMAP *bmp, BITMAP *sprite, int x, int y, @@ color, bg); @xref draw_sprite, bitmap_mask_color @shortdesc Draws non transparent pixels of the sprite with a color. 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: BITMAP *logo; ... /* Draw the logo silhouette in red. */ draw_character_ex(screen, logo, SCREEN_W / 2, SCREEN_H / 2, makecol(255, 0, 0), -1); @@void @rotate_sprite(BITMAP *bmp, BITMAP *sprite, int x, int y, fixed angle); @xref draw_sprite, rotate_scaled_sprite, rotate_sprite_v_flip @xref rotate_scaled_sprite_v_flip @xref pivot_sprite, pivot_sprite_v_flip, @xref pivot_scaled_sprite, pivot_scaled_sprite_v_flip, @xref itofix, Fixed point trig @eref exsprite @shortdesc Rotates a sprite. 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. @@void @rotate_sprite_v_flip(BITMAP *bmp, BITMAP *sprite, int x, int y, fixed angle); @xref rotate_sprite, rotate_scaled_sprite_v_flip @xref pivot_sprite_v_flip, pivot_scaled_sprite_v_flip @eref exsprite @shortdesc Rotates and flips a sprite. 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. @\void @rotate_scaled_sprite(BITMAP *bmp, BITMAP *sprite, int x, int y, @@ fixed angle, fixed scale); @xref rotate_sprite, rotate_scaled_sprite_v_flip @xref pivot_scaled_sprite, pivot_scaled_sprite_v_flip @shortdesc Rotates and stretches a sprite. Like rotate_sprite(), but stretches or shrinks the image at the same time as rotating it. @\void @rotate_scaled_sprite_v_flip(BITMAP *bmp, BITMAP *sprite, int x, int y, @@ fixed angle, fixed scale); @xref rotate_sprite, rotate_scaled_sprite, rotate_sprite_v_flip @shortdesc Rotates, stretches and flips a sprite. Draws the sprite, similar to rotate_scaled_sprite() except that it flips the sprite vertically first. @\void @pivot_sprite(BITMAP *bmp, BITMAP *sprite, int x, int y, @@ int cx, int cy, fixed angle); @xref rotate_sprite, pivot_scaled_sprite, pivot_sprite_v_flip @eref exsprite @shortdesc Rotates a sprite around a specified point. 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. @\void @pivot_sprite_v_flip(BITMAP *bmp, BITMAP *sprite, int x, int y, @@ int cx, int cy, fixed angle); @xref rotate_sprite, rotate_sprite_v_flip, pivot_sprite @eref exsprite @shortdesc Rotates and flips a sprite around a specified point. 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. @\void @pivot_scaled_sprite(BITMAP *bmp, BITMAP *sprite, int x, int y, @@ int cx, int cy, fixed angle, fixed scale); @xref rotate_sprite, rotate_scaled_sprite @xref pivot_sprite, pivot_scaled_sprite_v_flip @shortdesc Rotates and stretches a sprite around a specified point. 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. @\void @pivot_scaled_sprite_v_flip(BITMAP *bmp, BITMAP *sprite, int x, int y, @@ int cx, int cy, fixed angle, fixed scale); @xref rotate_sprite, rotate_scaled_sprite_v_flip, rotate_sprite_v_flip @xref pivot_sprite, pivot_scaled_sprite @shortdesc Rotates, stretches and flips a sprite around a specified point. 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. @heading RLE sprites Because bitmaps can be used in so many different ways, the bitmap structure is quite complicated, and it contains a lot of data. In many situations, though, you will find yourself storing images that are only ever copied to the screen, rather than being drawn onto or used as filling patterns, etc. If this is the case you may be better off storing your images in RLE_SPRITE (read chapter "Structures and types defined by Allegro" for an internal description of the RLE_SPRITE structure) or COMPILED_SPRITE (see next chapter) structures rather than regular bitmaps. RLE sprites store the image in a simple run-length encoded format, where repeated zero pixels are replaced by a single length count, and strings of non-zero pixels are preceded by a counter giving the length of the solid run. RLE sprites are usually much smaller than normal bitmaps, both because of the run length compression, and because they avoid most of the overhead of the bitmap structure. They are often also faster than normal bitmaps, because rather than having to compare every single pixel with zero to determine whether it should be drawn, it is possible to skip over a whole run of zeros with a single add, or to copy a long run of non-zero pixels with fast string instructions. Every silver lining has a cloud, though, and in the case of RLE sprites it is a lack of flexibility. You can't draw onto them, and you can't flip them, rotate them, or stretch them. In fact the only thing you can do with them is to blast them onto a bitmap with the draw_rle_sprite() function, which is equivalent to using draw_sprite() with a regular bitmap. You can convert bitmaps into RLE sprites at runtime, or you can create RLE sprite structures in grabber datafiles by making a new object of type 'RLE sprite'. @@RLE_SPRITE *@get_rle_sprite(BITMAP *bitmap); @xref draw_rle_sprite, destroy_rle_sprite @shortdesc Creates an RLE sprite using a bitmap as source. 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: 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); @retval 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. @@void @destroy_rle_sprite(RLE_SPRITE *sprite); @xref get_rle_sprite @shortdesc Destroys an RLE sprite. Destroys an RLE sprite structure previously returned by get_rle_sprite(). If you pass a NULL pointer this function won't do anything. Use this once you are done with an RLE sprite to avoid memory leaks in your program. @\void @draw_rle_sprite(BITMAP *bmp, const RLE_SPRITE *sprite, @@ int x, int y); @xref get_rle_sprite, draw_sprite, draw_compiled_sprite @xref draw_trans_rle_sprite, draw_lit_rle_sprite, bitmap_mask_color @shortdesc Draws an RLE sprite. Draws an RLE sprite onto a bitmap at the specified position. Example: RLE_SPRITE *rle_sprite; ... draw_rle_sprite(screen, rle_sprite, 100, 100); @\void @draw_trans_rle_sprite(BITMAP *bmp, const RLE_SPRITE *sprite, @@ int x, int y); @xref draw_rle_sprite, draw_lit_rle_sprite, draw_trans_sprite, color_map @xref set_trans_blender, set_alpha_blender, bitmap_mask_color @shortdesc Draws a translucent RLE sprite. 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: /* Some one time initialisation code. */ COLOR_MAP global_trans_table; create_trans_table(&global_trans_table, my_palette, 128, 128, 128, NULL); ... if (get_color_depth() == 8) color_map = &global_trans_table; else set_trans_blender(128, 128, 128, 128); draw_trans_rle_sprite(buffer, rle_ghost_sprite, x, y); @\void @draw_lit_rle_sprite(BITMAP *bmp, const RLE_SPRITE *sprite, @@ int x, y, color); @xref draw_rle_sprite, draw_trans_rle_sprite, draw_lit_sprite, color_map @xref set_trans_blender, bitmap_mask_color @shortdesc Draws a tinted RLE sprite. 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: /* Some one time initialisation code. */ COLOR_MAP global_light_table; create_light_table(&global_trans_table, my_palette, 10, 10, 60, NULL); ... if (get_color_depth() == 8) color_map = &global_light_table; else set_trans_blender(40, 40, 255, 255); /* Lit the cape with a blueish light. */ draw_lit_rle_sprite(buffer, rle_colored_cape, x, y); @heading Compiled sprites Compiled sprites are stored as actual machine code instructions that draw a specific image onto a bitmap, using mov instructions with immediate data values. This is the fastest way to draw a masked image: on slow machines, up to and including a 486, drawing compiled sprites can be about to five times as fast as using draw_sprite() with a regular bitmap. On newer machines the difference is usually negligible. Compiled sprites are big, so if memory is tight you should use RLE sprites instead, and what you can do with them is even more restricted than with RLE sprites, because they don't support clipping. If you try to draw one off the edge of a bitmap, you will corrupt memory and probably crash the system. You can convert bitmaps into compiled sprites at runtime, or you can create compiled sprite structures in grabber datafiles by making a new object of type 'Compiled sprite' or 'Compiled x-sprite'. @@COMPILED_SPRITE *@get_compiled_sprite(BITMAP *bitmap, int planar); @xref draw_compiled_sprite, destroy_compiled_sprite @shortdesc Creates a compiled sprite using a bitmap as source. 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: 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); 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. @@void @destroy_compiled_sprite(COMPILED_SPRITE *sprite); @xref get_compiled_sprite @shortdesc Destroys a compiled sprite. Destroys a compiled sprite structure previously returned by get_compiled_sprite(). If you pass a NULL pointer this function won't do anything. Use this once you are done with a compiled sprite to avoid memory leaks in your program. @\void @draw_compiled_sprite(BITMAP *bmp, const COMPILED_SPRITE *sprite, @@ int x, int y); @xref get_compiled_sprite, draw_sprite, draw_rle_sprite, bitmap_mask_color @shortdesc Draws a compiled sprite. 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... @heading Fonts Allegro provides routines for loading fonts directly from GRX format .fnt files, 8x8 or 8x16 BIOS format .fnt files, from bitmap images, from datafiles or you can import a multiple-range Unicode font by writing a .txt script that specifies a number of different source files for each range of characters. By default, Allegro can only use bitmapped (non-scalable) fonts. If you want to use TrueType fonts, you will need to use an add-on library which allows you to load them on the fly (like AllegTTF or Glyph Keeper, listed among others at http://www.allegro.cc/) and render them directly, or generate a bitmapped version of a TrueType font with tools like TTF2PCX (http://www.talula.demon.co.uk/ttf2pcx/index.html). @\void @register_font_file_type(const char *ext, @@ FONT *(*load)(const char *filename, RGB *pal, void *param)); @xref load_font @shortdesc Register a new font loading function. 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: FONT *load_my_font(const char *filename, RGB *pal, void *param) { ... } 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. @@FONT *@load_font(const char *filename, RGB *pal, void *param); @xref register_font_file_type, load_bitmap, load_dat_font, load_bios_font @xref load_grx_font, load_grx_or_bios_font, load_bitmap_font, load_txt_font @xref destroy_font @eref exfont @shortdesc Loads a font from a file. 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: 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); @retval 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. @@void @destroy_font(FONT *f); @xref load_datafile_object, load_font @eref exfont @shortdesc Frees the memory being used by a font structure. 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. @@int @is_color_font(FONT *f) @xref is_mono_font @shortdesc Returns TRUE if a font is a color font. This function checks if the given font is a color font, as opposed to a monochrome font. @retval Returns TRUE if the font is a color font, FALSE if it is not. @@int @is_mono_font(FONT *f) @xref is_color_font @shortdesc Returns TRUE if a font is a monochrome font. This function checks if the given font is a mono font, as opposed to a color font. @retval Returns TRUE if the font is a monochrome font, FALSE if it is not. @@FONT *@is_compatible_font(FONT *f1, FONT *f2) @xref merge_fonts, is_color_font, is_mono_font @shortdesc Check if two fonts are of the same type. This function compares the two fonts, which you can use to find out if Allegro is capable of merging them. @retval Returns TRUE if the two fonts are of the same general type (both are color fonts or both are monochrome fonts, for instance). @@int @get_font_ranges(FONT *f) @xref get_font_range_begin, get_font_range_end, transpose_font @shortdesc Returns the number of character ranges in a font. 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: FONT *f; int range; int n; ... range = get_font_ranges(f); printf("The font has %d character ranges:\n", range); for (n = 0; n < range; n++) printf("Range %d from 0x%03x - 0x%03x\n", get_font_range_begin(f, n), get_font_range_end(f, n)); @retval Returns the number of continuous character ranges in a font, or -1 if that information is not available. @@int @get_font_range_begin(FONT *f, int range) @xref get_font_ranges, get_font_range_end, transpose_font @shortdesc Returns the start of a character range in a font. 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: printf("The font has a character range of %d - %d\n", get_font_range_begin(font, -1), get_font_range_end(font, -1)); @retval Returns the first character in the font range, or -1 if that information is not available. @@int @get_font_range_end(FONT *f, int range) @xref get_font_ranges, get_font_range_begin, transpose_font @shortdesc Returns the last character of a character range in a font. 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: printf("The font has a character range of %d - %d\n", get_font_range_begin(font, -1), get_font_range_end(font, -1)); @retval Returns the last character in the font range, or -1 if that information is not available. @@FONT *@extract_font_range(FONT *f, int begin, int end) @xref get_font_range_begin, get_font_range_end, merge_fonts, transpose_font @eref exfont @shortdesc Extracts a range of characters from a font. 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: 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); @retval 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. @@int @transpose_font(FONT *f, int drange) @xref get_font_range_begin, get_font_range_end, merge_fonts, extract_font_range @shortdesc Transposes all characters in a font. This function transposes all characters in a font, effectively remapping the font. Example: FONT *myfont; FONT *capitals; ... /* Create a font of only capital letters */ capitals = extract_font_range(myfont, 'A', 'Z'); /* Now transpose the characters in the font so that they will be used */ /* for the lower case letters a-z */ transpose_font(capitals, 'a'-'A'); textout_ex(screen, capitals, "allcaps", 100, 100, makecol(255,255,255), 0); @retval Returns 0 on success, -1 on failure. @@FONT *@merge_fonts(FONT *f1, FONT *f2) @xref extract_font_range, is_color_font, is_mono_font @eref exfont @shortdesc Merges two fonts into one font. 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: 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(combined_font); @retval 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. @@FONT *@load_dat_font(const char *filename, RGB *pal, void *param) @xref register_font_file_type, load_font @shortdesc Loads a FONT from an Allegro datafile. 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: FONT FONT_1_DATA FONT FONT_2_DATA FONT FONT_3_DATA PAL FONT_1_PALETTE PAL FONT_2_PALETTE Then the following code will load FONT_1_DATA as a FONT and return FONT_1_PALETTE as the palette: FONT *f; PALETTE pal; char *names[] = { "FONT_1_DATA", "FONT_1_PALETTE" } f = load_dat_font("fonts.dat", pal, names); If instead you want to load the second font, FONT_2, from the datafile, you would use: FONT *f; PALETTE pal; char *names[] = { "FONT_2_DATA", "FONT_2_PALETTE" } f = load_dat_font("fonts.dat", pal, names); If you want to load the third font, but not bother with a palette, use: FONT *f; char *names[] = { "FONT_3_DATA", NULL } f = load_dat_font("fonts.dat", NULL, names); @retval 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. @@FONT *@load_bios_font(const char *filename, RGB *pal, void *param) @xref register_font_file_type, load_font @shortdesc Loads a 8x8 or 8x16 BIOS format font. Loads a 8x8 or 8x16 BIOS format font. You shouldn't normally call this routine directly. @retval 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. @@FONT *@load_grx_font(const char *filename, RGB *pal, void *param) @xref register_font_file_type, load_font @shortdesc Loads a GRX format font. Loads a GRX format font. You shouldn't normally call this routine directly. @retval 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. @@FONT *@load_grx_or_bios_font(const char *filename, RGB *pal, void *param) @xref register_font_file_type, load_font @shortdesc Loads either a BIOS or GRX format font. Loads either a BIOS or GRX format font. You shouldn't normally call this routine directly. @retval 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. @@FONT *@load_bitmap_font(const char *filename, RGB *pal, void *param) @xref register_font_file_type, load_font, load_bitmap, set_color_depth @xref grab_font_from_bitmap @shortdesc Grabs a font from a bitmap file. 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:
  • 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.
  • 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).
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. @retval 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. @@FONT *@grab_font_from_bitmap(BITMAP *bmp) @xref load_bitmap_font @shortdesc Grabs a font from a bitmap 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. @retval 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. @@FONT *@load_txt_font(const char *filename, RGB *pal, void *param) @xref register_font_file_type, load_font @shortdesc Loads a font script. 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: ascii.fnt 0x20 0x7F - 0xA0 0xFF dingbats.fnt 0x1000 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. @retval 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. @heading Text output Allegro provides text output routines that work with both monochrome and color fonts, which can contain any number of Unicode character ranges. The grabber program can create fonts from sets of characters drawn in a bitmap file (see grabber.txt for more information), and can also import GRX or BIOS format font files. The font structure contains a number of hooks that can be used to extend it with your own custom drawing code: see the definition in allegro/text.h for details. @@extern FONT *@font; @xref textout_ex, textprintf_ex @eref Available Allegro examples @shortdesc A simple 8x8 fixed size font. A simple 8x8 fixed size font (the mode 13h BIOS default). If you want to alter the font used by the GUI routines, change this to point to one of your own fonts. This font contains the standard ASCII (U+20 to U+7F), Latin-1 (U+A1 to U+FF), and Latin Extended-A (U+0100 to U+017F) character ranges. @@extern int @allegro_404_char; @xref font @shortdesc Character used when Allegro cannot find a glyph. 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: /* Show unknown glyphs with an asterisk. */ allegro_404_char = '*'; @@int @text_length(const FONT *f, const char *str); @xref text_height @eref ex12bit, exmidi, expat, exunicod @shortdesc Returns the length of a string in pixels. Returns the length (in pixels) of a string in the specified font. Example: int width = text_length(font, "I love spam"); ... bmp = create_bitmap(width, height); @@int @text_height(const FONT *f) @xref text_length @eref ex12bit, exmidi, expackf, expat, exsprite, exsyscur, exunicod @shortdesc Returns the height of a font in pixels. Returns the height (in pixels) of the specified font. Example: int height = text_height(font); ... bmp = create_bitmap(width, height); @\void @textout_ex(BITMAP *bmp, const FONT *f, const char *s, @@ int x, int y, int color, int bg); @xref font, textout_centre_ex, textout_right_ex, textout_justify_ex @xref textprintf_ex, text_height, text_length @eref Available Allegro examples @shortdesc Writes a string on a bitmap. 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: /* Show the program's version in blue letters. */ textout_ex(screen, font, "v4.2.0-beta2", 10, 10, makecol(0, 0, 255), -1); @\void @textout_centre_ex(BITMAP *bmp, const FONT *f, const char *s, @@ int x, y, int color, int bg); @xref textout_ex, textprintf_centre_ex @eref Available Allegro examples @shortdesc Writes a centered string on a bitmap. Like textout_ex(), but interprets the x coordinate as the centre rather than the left edge of the string. Example: /* Important texts go in the middle. */ width = text_length("GAME OVER"); textout_centre_ex(screen, font, "GAME OVER", SCREEN_W / 2, SCREEN_H / 2, makecol(255, 0, 0), makecol(0, 0, 0)); @\void @textout_right_ex(BITMAP *bmp, const FONT *f, const char *s, @@ int x, int y, int color, int bg); @xref textout_ex, textprintf_right_ex @shortdesc Writes a right aligned string on a bitmap. Like textout_ex(), but interprets the x coordinate as the right rather than the left edge of the string. Example: textout_right_ex(screen, font, "Look at this color!", SCREEN_W - 10, 10, my_yellow, -1); @\void @textout_justify_ex(BITMAP *bmp, const FONT *f, const char *s, @\ int x1, int x2, int y, int diff, int color, @@ int bg); @xref textout_ex, textprintf_justify_ex @shortdesc Draws justified text within a region. 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: 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)); @\void @textprintf_ex(BITMAP *bmp, const FONT *f, int x, int y, @@ int color, int bg, const char *fmt, ...); @xref font, textout_ex, textprintf_centre_ex, textprintf_right_ex @xref textprintf_justify_ex, text_height, text_length, uszprintf @eref Available Allegro examples @shortdesc Formatted output of a string. 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: int player_score; ... textprintf_ex(screen, font, 10, 10, makecol(255, 100, 200), -1, "Score: %d", player_score); @\void @textprintf_centre_ex(BITMAP *bmp, const FONT *f, int x, int y, @@ int color, int bg, const char *fmt, ...); @xref textprintf_ex, textout_centre_ex @eref Available Allegro examples @shortdesc Formatted centered output of a string. 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: textprintf_centre_ex(screen, font, SCREEN_W / 2, 120, makecol(0, 100, 243), -1, "Your best score so far was %d!", total_max_points); @\void @textprintf_right_ex(BITMAP *bmp, const FONT *f, int x, y, color, bg, @@ const char *fmt, ...); @xref textprintf_ex, textout_right_ex @shortdesc Formatted right aligned output of a string. 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: textprintf_right_ex(screen, font, SCREEN_W - 10, 10, makecol(200, 200, 20), -1, "%d bullets left", player_ammo); @\void @textprintf_justify_ex(BITMAP *bmp, const FONT *f, int x1, x2, y, @@ diff, color, bg, const char *fmt, ...); @xref textprintf_ex, textout_justify_ex @shortdesc Formatted justified output of a string. Like textout_justify_ex(), but using a printf() style format string. This function shares the text length limitation of textprintf_ex(). Example: char *lines[] = {"Line %02d: Draws justified text", "Line %02d: within the specified", "Line %02d: x2-x1 area. But not", "Line %02d: T H I S !", NULL}; /* Show the justification marker. */ vline(screen, 300, 0, SCREEN_H-1, makecol(0, 0, 0)); /* Draw all the lines until we reach a NULL entry. */ for (num = 0, y = 0; lines[num]; num++, y += text_height(font)) textprintf_justify_ex(screen, font, 0, 300, y, 180, makecol(0, 0, 0), makecol(255, 255, 255), lines[num], num); @heading Polygon rendering All the 3d functions that accept a `type' parameter are asking for a polygon rendering mode, which can be any of the following POLYTYPE_* values. If the CPU_MMX flag of the cpu_capabilities global variable is set, the GRGB and truecolor *LIT routines will be optimised using MMX instructions. If the CPU_3DNOW flag is set, the truecolor PTEX*LIT routines will take advantage of the 3DNow! CPU extensions. Using MMX for *LIT routines has a side effect: normally (without MMX), these routines use the blender functions used also for other lighting functions, set with set_trans_blender() or set_blender_mode(). The MMX versions only use the RGB value passed to set_trans_blender() and do the linear interpolation themselves. Therefore a new set of blender functions passed to set_blender_mode() is ignored. @@#define @POLYTYPE_FLAT @xref Polygon rendering, polygon3d, drawing_mode @eref ex3d, excamera @shortdesc Polygon rendering mode type 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. @@#define @POLYTYPE_GCOL @xref Polygon rendering, polygon3d, makecol @eref ex3d, exscn3d, exzbuf @shortdesc Polygon rendering mode type 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. @@#define @POLYTYPE_GRGB @xref Polygon rendering, polygon3d, rgb_map @eref ex3d @shortdesc Polygon rendering mode type 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). @@#define @POLYTYPE_ATEX @xref Polygon rendering, polygon3d @eref ex3d @shortdesc Polygon rendering mode type 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. @@#define @POLYTYPE_PTEX @xref Polygon rendering, polygon3d, POLYTYPE_ATEX @eref ex3d @shortdesc Polygon rendering mode type 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). @@#define @POLYTYPE_ATEX_MASK @@#define @POLYTYPE_PTEX_MASK @xref Polygon rendering, polygon3d, POLYTYPE_ATEX, POLYTYPE_PTEX @eref ex3d @shortdesc Polygon rendering mode type Like POLYTYPE_ATEX and POLYTYPE_PTEX, but zero texture map pixels are skipped, allowing parts of the texture map to be transparent. @@#define @POLYTYPE_ATEX_LIT @@#define @POLYTYPE_PTEX_LIT @xref Polygon rendering, polygon3d, POLYTYPE_ATEX, POLYTYPE_PTEX @xref color_map, Truecolor transparency @eref ex3d @shortdesc Polygon rendering mode type 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! @@#define @POLYTYPE_ATEX_MASK_LIT @@#define @POLYTYPE_PTEX_MASK_LIT @xref Polygon rendering, polygon3d, POLYTYPE_ATEX_LIT, POLYTYPE_PTEX_LIT @eref ex3d @shortdesc Polygon rendering mode type Like POLYTYPE_ATEX_LIT and POLYTYPE_PTEX_LIT, but zero texture map pixels are skipped, allowing parts of the texture map to be transparent. @@#define @POLYTYPE_ATEX_TRANS @@#define @POLYTYPE_PTEX_TRANS @xref Polygon rendering, polygon3d @eref ex3d @shortdesc Polygon rendering mode type 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). @@#define @POLYTYPE_ATEX_MASK_TRANS @@#define @POLYTYPE_PTEX_MASK_TRANS @xref Polygon rendering, polygon3d @eref ex3d @shortdesc Polygon rendering mode type Like POLYTYPE_ATEX_TRANS and POLYTYPE_PTEX_TRANS, but zero texture map pixels are skipped. @@void @polygon3d(BITMAP *bmp, int type, BITMAP *texture, int vc, V3D *vtx[]); @@void @polygon3d_f(BITMAP *bmp, int type, BITMAP *texture, int vc, V3D_f *vtx[]); @xref triangle3d, quad3d, polygon, clip3d, cpu_capabilities @eref excamera @shortdesc Draws a 3d polygon onto the specified bitmap. 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: 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; 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. @@void @triangle3d(BITMAP *bmp, int type, BITMAP *tex, V3D *v1, *v2, *v3); @@void @triangle3d_f(BITMAP *bmp, int type, BITMAP *tex, V3D_f *v1, *v2, *v3); @xref polygon3d, quad3d, triangle, Polygon rendering @shortdesc Draws a 3d triangle onto the specified bitmap. 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. @@void @quad3d(BITMAP *bmp, int type, BITMAP *tex, V3D *v1, *v2, *v3, *v4); @@void @quad3d_f(BITMAP *bmp, int type, BITMAP *tex, V3D_f *v1, *v2, *v3, *v4); @xref polygon3d, triangle3d, Polygon rendering @eref ex3d @shortdesc Draws a 3d quad onto the specified bitmap. 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. @\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[]); @xref polygon3d, clip3d @eref excamera, exscn3d @shortdesc Clips the polygon given in vtx using floating point math, Clips the polygon given in `vtx'. The number of vertices is `vc', the result goes in `vout', and `vtmp' and `out' are needed for internal purposes. The pointers in `vtx', `vout' and `vtmp' must point to valid V3D_f structures. As additional vertices may appear in the process of clipping, so the size of `vout', `vtmp' and `out' should be at least vc * (1.5 ^ n), where `n' is the number of clipping planes (5 or 6), and `^' denotes "to the power of". The frustum (viewing volume) is defined by -z<x<z, -z<y<z, 0<min_z<z<max_z. If max_z<=min_z, the z<max_z clipping is not done. As you can see, clipping is done in the camera space, with perspective in mind, so this routine should be called after you apply the camera matrix, but before the perspective projection. The routine will correctly interpolate u, v, and c in the vertex structure. However, no provision is made for high/truecolor GCOL. @retval Returns the number of vertices after clipping is done. @\int @clip3d(int type, fixed min_z, fixed max_z, int vc, @@ const V3D *vtx[], V3D *vout[], V3D *vtmp[], int out[]); @xref polygon3d, clip3d_f @shortdesc Clips the polygon given in vtx using fixed point math. 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. @retval Returns the number of vertices after clipping is done. @hnode Zbuffered rendering 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: polygon3d(bmp, POLYTYPE_ATEX | POLYTYPE_ZBUF, tex, vc, vtx); 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:
  • Unlike the normal POLYTYPE_FLAT renderers, the Z-buffered ones don't use the hline() routine. Therefore DRAW_MODE has no effect.
  • The *LIT* routines work the traditional way - through the set of blender routines.
  • All the Z-buffered routines are much slower than their normal counterparts (they all use the FPU to interpolate and test 1/z values).
@@ZBUFFER *@create_zbuffer(BITMAP *bmp); @xref create_sub_zbuffer, set_zbuffer, clear_zbuffer, destroy_zbuffer @eref exzbuf @shortdesc Creates a Z-buffer for a bitmap. 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. @retval 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. @@ZBUFFER *@create_sub_zbuffer(ZBUFFER *parent, int x, int y, int width, int height); @xref create_zbuffer, create_sub_bitmap, destroy_zbuffer @shortdesc Creates a sub-z-buffer. 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. @retval 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. @@void @set_zbuffer(ZBUFFER *zbuf); @xref create_zbuffer, clear_zbuffer, destroy_zbuffer @eref exzbuf @shortdesc Makes the given Z-buffer the active one. Makes the given Z-buffer be the active one. This should have been previously created with create_zbuffer(). @@void @clear_zbuffer(ZBUFFER *zbuf, float z); @xref create_zbuffer, set_zbuffer, destroy_zbuffer @eref exzbuf @shortdesc Writes a depth value into the given Z-buffer. 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). @@void @destroy_zbuffer(ZBUFFER *zbuf); @xref create_zbuffer, set_zbuffer, clear_zbuffer @eref exzbuf @shortdesc Destroys a Z-buffer. Destroys the Z-buffer when you are finished with it. Use this to avoid memory leaks in your program. @hnode Scene rendering Allegro provides two simple approaches to remove hidden surfaces:
  • Z-buffering - (see above)
  • 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.
The scene rendering has approximately the following steps:
  • Initialize the scene (set the clip area, clear the bitmap, blit a background, etc.)
  • Call clear_scene().
  • Transform all your points to camera space.
  • Clip polygons.
  • Project with persp_project() or persp_project_f().
  • "Draw" polygons with scene_polygon3d() and/or scene_polygon3d_f(). This doesn't do any actual drawing, only initializes tables.
  • Render all the polygons defined previously to the bitmap with render_scene().
  • Overlay some non-3D graphics.
  • Show the bitmap (blit it to screen, flip the page, etc).
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:
  • Unlike polygon3d(), scene_polygon3d() requires valid z coordinates for all vertices, regardless of rendering style (unlike polygon3d(), which only uses z coordinate for *PTEX*).
  • All polygons passed to scene_polygon3d() have to be persp_project()'ed.
  • After render_scene() the mode is reset to SOLID.
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: 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(); @@int @create_scene(int nedge, int npoly); @xref scene_polygon3d, render_scene, clear_scene, destroy_scene, scene_gap @xref create_zbuffer @eref exscn3d @shortdesc Allocates memory for a 3d scene. 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. @retval Returns zero on success, or a negative number if allocations fail. @@void @clear_scene(BITMAP *bmp); @xref create_scene, scene_polygon3d, render_scene, destroy_scene, scene_gap @eref exscn3d @shortdesc Initializes a scene. Initializes a scene. The bitmap is the bitmap you will eventually render on. @@void @destroy_scene(); @xref create_scene, scene_polygon3d, clear_scene, render_scene, scene_gap @eref exscn3d @shortdesc Deallocates the memory used by a scene. Deallocate memory previously allocated by create_scene. Use this to avoid memory leaks in your program. @@int @scene_polygon3d(int type, BITMAP *texture, int vc, V3D *vtx[]); @@int @scene_polygon3d_f(int type, BITMAP *texture, int vc, V3D_f *vtx[]); @xref create_scene, clear_scene, render_scene, destroy_scene, polygon3d @xref cpu_capabilities @eref exscn3d @shortdesc Puts a polygon in the scene rendering list. 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. @retval Returns zero on success, or a negative number if it won't be rendered for lack of a rendering routine. @@void @render_scene(); @xref create_scene, clear_scene, destroy_scene, scene_gap, scene_polygon3d @eref exscn3d @shortdesc Renders all the queued scene polygons. 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(). @@extern float @scene_gap; @xref create_scene, clear_scene, destroy_scene, render_scene, scene_polygon3d @shortdesc Number controlling the scene z-sorting algorithm behaviour. 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. @heading Transparency and patterned drawing @@void @drawing_mode(int mode, BITMAP *pattern, int x_anchor, int y_anchor); @xref xor_mode, solid_mode, color_map, set_trans_blender @eref exalpha, excolmap, exjoy, expat, extrans @shortdesc Sets the graphics drawing mode. 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: 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 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. @@void @xor_mode(int on); @xref drawing_mode @eref exspline, exupdate @shortdesc Shortcut for toggling xor drawing mode on and off. 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). @@void @solid_mode(); @xref drawing_mode @eref exalpha, expat @shortdesc Shortcut for selecting solid drawing mode. This is a shortcut for selecting solid drawing mode. It is equivalent to calling drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0). @hnode 256-color transparency 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. @@extern COLOR_MAP *@color_map; @xref create_color_table, create_light_table, create_trans_table @xref create_blender_table, set_trans_blender, draw_trans_sprite @xref draw_lit_sprite, draw_gouraud_sprite, drawing_mode @eref ex3d, excolmap, exlights, exshade, extrans @shortdesc Global pointer to the color mapping table. 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: color_map = malloc(sizeof(COLOR_MAP)); if (!color_map) abort_on_error("Not enough memory for color map!"); @\void @create_trans_table(COLOR_MAP *table, const PALETTE pal, @@ int r, g, b, void (*callback)(int pos)); @xref color_map, create_light_table, create_color_table @xref create_blender_table, draw_trans_sprite, draw_lit_sprite @xref draw_gouraud_sprite, rgb_map @eref ex3d, extrans @shortdesc Fills a color mapping table for translucency effects. 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: COLOR_MAP trans_table; ... /* Build a color lookup table for translucent drawing. */ create_trans_table(&trans_table, pal, 128, 128, 128, NULL); @\void @create_light_table(COLOR_MAP *table, const PALETTE pal, @@ int r, g, b, void (*callback)(int pos)); @xref color_map, create_trans_table, create_color_table @xref create_blender_table, draw_trans_sprite, draw_lit_sprite @xref draw_gouraud_sprite, rgb_map @eref ex3d, exshade, extrans @shortdesc Fills a color mapping table for lighting effects. 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: COLOR_MAP light_table; ... /* Build a color lookup table for lighting effects. */ create_light_table(&light_table, pal, 0, 0, 0, NULL); @\void @create_color_table(COLOR_MAP *table, const PALETTE pal, @\ void (*blend)(PALETTE pal, int x, int y, RGB *rgb), @@ void (*callback)(int pos)); @xref color_map, create_light_table, create_trans_table, create_blender_table @xref draw_trans_sprite, draw_lit_sprite, draw_gouraud_sprite, rgb_map @eref excolmap @shortdesc Fills a color mapping table for customised effects. 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: COLOR_MAP greyscale_table; ... void return_grey_color(const PALETTE pal, int x, int y, RGB *rgb) { ... } ... /* Build a color lookup table for greyscale effect. */ create_color_table(&greyscale_table, pal, return_grey_color, NULL); @\void @create_blender_table(COLOR_MAP *table, const PALETTE pal, @@ void (*callback)(int pos)); @xref color_map, create_light_table, create_trans_table, create_color_table @xref draw_trans_sprite, draw_lit_sprite, draw_gouraud_sprite @xref set_trans_blender, set_blender_mode @shortdesc Emulates truecolor blender effects in palettised modes. 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. @hnode Truecolor transparency In truecolor video modes, translucency and lighting are implemented by a blender function of the form: unsigned long (*BLENDER_FUNC)(unsigned long x, y, n); 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). @@void @set_trans_blender(int r, int g, int b, int a); @xref set_blender_mode, set_alpha_blender, set_write_alpha_blender @xref color_map, draw_trans_sprite, draw_lit_sprite, drawing_mode @xref set_add_blender, set_burn_blender, set_color_blender @xref set_difference_blender, set_dissolve_blender, set_dodge_blender @xref set_hue_blender, set_invert_blender, set_luminance_blender @xref set_multiply_blender, set_saturation_blender, set_screen_blender @eref ex3d, exblend, exshade, extrans, exxfade @shortdesc Enables a truecolor blender. Enables a linear interpolator blender mode for combining translucent or lit truecolor pixels. @@void @set_alpha_blender(); @xref set_trans_blender, draw_trans_sprite, draw_trans_rle_sprite, @xref set_write_alpha_blender @eref exalpha, extrans @shortdesc Enables a special alpha-channel blending mode. 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. @@void @set_write_alpha_blender(); @xref set_alpha_blender, draw_trans_sprite, drawing_mode @eref exalpha, extrans @shortdesc Enables the special alpha-channel editing mode. 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. @@void @set_add_blender(int r, int g, int b, int a); @xref set_trans_blender, drawing_mode @shortdesc Enables an additive blender mode. Enables an additive blender mode for combining translucent or lit truecolor pixels. @@void @set_burn_blender(int r, int g, int b, int a); @xref set_trans_blender, drawing_mode @shortdesc Enables a burn blender mode. 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. @@void @set_color_blender(int r, int g, int b, int a); @xref set_trans_blender, drawing_mode @shortdesc Enables a color blender mode. 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. @@void @set_difference_blender(int r, int g, int b, int a); @xref set_trans_blender, drawing_mode @shortdesc Enables a difference blender mode. 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. @@void @set_dissolve_blender(int r, int g, int b, int a); @xref set_trans_blender, drawing_mode @shortdesc Enables a dissolve blender mode. 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 :). @@void @set_dodge_blender(int r, int g, int b, int a); @xref set_trans_blender, drawing_mode @shortdesc Enables a dodge blender mode. 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. @@void @set_hue_blender(int r, int g, int b, int a); @xref set_trans_blender, drawing_mode @shortdesc Enables a hue blender mode. Enables a hue blender mode for combining translucent or lit truecolor pixels. This applies the hue of the source to the destination. @@void @set_invert_blender(int r, int g, int b, int a); @xref set_trans_blender, drawing_mode @shortdesc Enables an invert blender mode. Enables an invert blender mode for combining translucent or lit truecolor pixels. Blends the inverse (or negative) colour of the source with the destination. @@void @set_luminance_blender(int r, int g, int b, int a); @xref set_trans_blender, drawing_mode @shortdesc Enables a luminance blender mode. 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. @@void @set_multiply_blender(int r, int g, int b, int a); @xref set_trans_blender, drawing_mode @eref exalpha @shortdesc Enables a multiply blender mode. 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. @@void @set_saturation_blender(int r, int g, int b, int a); @xref set_trans_blender, drawing_mode @shortdesc Enables a saturation blender mode. Enables a saturation blender mode for combining translucent or lit truecolor pixels. Applies the saturation of the source to the destination image. @@void @set_screen_blender(int r, int g, int b, int a); @xref set_trans_blender, drawing_mode @shortdesc Enables a screen blender mode. 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. @@void @set_blender_mode(BLENDER_FUNC b15, b16, b24, int r, g, b, a); @xref set_blender_mode_ex, set_trans_blender, color_map, draw_trans_sprite @xref draw_lit_sprite, drawing_mode @shortdesc Specifies a custom set of truecolor blender routines. 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. @\void @set_blender_mode_ex(BLENDER_FUNC b15, b16, b24, b32, b15x, b16x, b24x, @@ int r, g, b, a); @xref set_blender_mode, set_alpha_blender @shortdesc An even more complex version of set_blender_mode(). 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. @heading Converting between color formats In general, Allegro is designed to be used in only one color depth at a time, so you will call set_color_depth() once and then store all your bitmaps in the same format. If you want to mix several different pixel formats, you can use create_bitmap_ex() in place of create_bitmap(), and call bitmap_color_depth() to query the format of a specific image. Most of the graphics routines require all their input parameters to be in the same format (eg. you cannot stretch a 15-bit source bitmap onto a 24-bit destination), but there are some exceptions:
  • blit() and the rotation routines can copy between bitmaps of any format, converting the data as required.
  • draw_sprite() can draw 256-color source images onto destinations of any format.
  • draw_character_ex() _always_ uses a 256-color source bitmap, whatever the format of the destination.
  • 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.
  • 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.
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). @@int @bestfit_color(const PALETTE pal, int r, int g, int b); @xref makecol8 @shortdesc Finds a palette color fitting the requested RGB values. 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. @retval Returns the index of the palette for the closest match to the requested color. @@extern RGB_MAP *@rgb_map; @xref create_rgb_table, makecol8, create_trans_table @xref create_light_table, create_color_table @eref ex3d, excolmap, exrgbhsv, exshade, extrans @shortdesc Look up table to speed up reducing RGB values to palette colors. 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(). @\void @create_rgb_table(RGB_MAP *table, const PALETTE pal, @@ void (*callback)(int pos)); @xref rgb_map @eref ex3d, excolmap, exrgbhsv, exshade, extrans @shortdesc Generates an RGB mapping table with lookup data for a palette. 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: RGB_MAP rgb_table; create_rgb_table(&rgb_table, palette, NULL); rgb_map = &rgb_table; @@void @hsv_to_rgb(float h, float s, float v, int *r, int *g, int *b); @@void @rgb_to_hsv(int r, int g, int b, float *h, float *s, float *v); @eref exlights, exrgbhsv @shortdesc Converts color values between the HSV and RGB colorspaces. 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: int r, g, b; float hue, saturation, value; ... /* Convert a reddish color to HSV format. */ rgb_to_hsv(255, 0, 128, &hue, &saturation, &value); /* Now put our tin foil hat, and verify that. */ hsv_to_rgb(hue, saturation, value, &r, &g, &b); ASSERT(r == 255); ASSERT(g == 0); ASSERT(b == 128); @heading Direct access to video memory Read chapter "Structures and types defined by Allegro" for an internal description of the BITMAP structure. There are several ways to get direct access to the image memory of a bitmap, varying in complexity depending on what sort of bitmap you are using. The simplest approach will only work with memory bitmaps (obtained from create_bitmap(), grabber datafiles, and image files) and sub-bitmaps of memory bitmaps. This uses a table of char pointers, called `line', which is a part of the bitmap structure and contains pointers to the start of each line of the image. For example, a simple memory bitmap putpixel function is: void memory_putpixel(BITMAP *bmp, int x, int y, int color) { bmp->line[y][x] = color; } For truecolor modes you need to cast the line pointer to the appropriate type, for example: void memory_putpixel_15_or_16_bpp(BITMAP *bmp, int x, int y, int color) { ((short *)bmp->line[y])[x] = color; } void memory_putpixel_32(BITMAP *bmp, int x, int y, int color) { ((long *)bmp->line[y])[x] = color; } 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: void linear_screen_putpixel(BITMAP *bmp, int x, int y, int color) { bmp_select(bmp); bmp_write8((unsigned long)bmp->line[y]+x, color); } For truecolor modes you should replace the bmp_write8() with bmp_write16(), bmp_write24(), or bmp_write32(), and multiply the x offset by the number of bytes per pixel. There are of course similar functions to read a pixel value from a bitmap, namely bmp_read8(), bmp_read16(), bmp_read24() and bmp_read32(). This still won't work in banked SVGA modes, however, or on platforms like Windows that do special processing inside the bank switching functions. For more flexible access to bitmap memory, you need to call the following routines. They are implemented as inline assembler routines, so they are not as inefficient as they might seem. If the bitmap doesn't require bank switching (ie. it is a memory bitmap, mode 13h screen, etc), these functions just return bmp->line[line]. @@unsigned long @bmp_write_line(BITMAP *bmp, int line); @eref exflame, exlights @shortdesc Direct access bank switching line selection for writing. Selects the line of a bitmap that you are going to draw onto. @retval Returns the address of the selected line for writing. @@unsigned long @bmp_read_line(BITMAP *bmp, int line); @eref exflame @shortdesc Direct access bank switching line selection for reading. Selects the line of a bitmap that you are going to read from. @retval Returns the address of the selected line for reading. @@void @bmp_unwrite_line(BITMAP *bmp); @eref exflame, exlights @shortdesc Direct access bank switching line release. 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. @hnode More on banked direct memory access 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: 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); } 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: void modex_putpixel(BITMAP *b, int x, int y, int color) { outportw(0x3C4, (0x100<<(x&3))|2); bmp_select(bmp); bmp_write8((unsigned long)bmp->line[y]+(x>>2), color); } 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: #include <sys/nearptr.h> unsigned char *screenmemory; unsigned long screen_base_addr; __djgpp_nearptr_enable(); __dpmi_get_segment_base_address(screen->seg, &screen_base_addr); screenmemory = (unsigned char *)(screen_base_addr + screen->line[0] - __djgpp_base_address); Then: void nearptr_putpixel(int x, int y, int color) { screenmemory[x + y*VIRTUAL_W] = color; } @heading FLIC routines There are two high level functions for playing FLI/FLC animations: play_fli(), which reads the data directly from disk, and play_memory_fli(), which uses data that has already been loaded into RAM. Apart from the different sources of the data, these two functions behave identically. They draw the animation onto the specified bitmap, which should normally be the screen. Frames will be aligned with the top left corner of the bitmap: if you want to position them somewhere else you will need to create a sub-bitmap for the FLI player to draw onto. If the callback function is not NULL it will be called once for each frame, allowing you to perform background tasks of your own. This callback should normally return zero: if it returns non-zero the player will terminate (this is the only way to stop an animation that is playing in looped mode). The FLI player returns FLI_OK if it reached the end of the file, FLI_ERROR if something went wrong, and the value returned by the callback function if that was what stopped it. If you need to distinguish between different return values, your callback should return positive integers, since FLI_OK is zero and FLI_ERROR is negative. Note that the FLI player will only work when the timer module is installed, and that it will alter the palette according to whatever palette data is present in the animation file. Occasionally you may need more detailed control over how an FLI is played, for example if you want to superimpose a text scroller on top of the animation, or to play it back at a different speed. You could do both of these with the lower level functions described below. @@int @play_fli(const char *filename, BITMAP *bmp, int loop, int (*callback)()); @xref play_memory_fli, install_timer, fli_frame @shortdesc Plays a FLI or FLC animation from disk. 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: /* 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!"); @retval 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. @\int @play_memory_fli(const void *fli_data, BITMAP *bmp, int loop, @@ int (*callback)()); @xref play_fli, install_timer, fli_frame @shortdesc Plays a FLI or FLC animation from memory. 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: int ret = play_memory_fli(anim_data, screen, 0, NULL); if (ret == FLI_ERROR) abort_on_error("Corrupted animation data?"); @retval 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. @@int @open_fli(const char *filename); @@int @open_memory_fli(const void *fli_data); @xref close_fli, next_fli_frame, fli_bitmap, fli_palette @shortdesc Makes a FLI file open and ready for playing. 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: if (open_fli("intro.fli") == FLI_ERROR) abort_on_error("Error playing intro"); @retval Returns FLI_OK on success, FLI_ERROR if something went wrong, like trying to open another FLI file without closing the previous one. @@void @close_fli(); @xref open_fli @shortdesc Closes a FLI file previously opened. Closes an FLI file when you have finished reading from it. Remember to do this to avoid having memory leaks in your program. @@int @next_fli_frame(int loop); @xref open_fli, fli_bitmap, fli_palette, fli_timer, fli_frame @shortdesc Reads the next frame of the current animation file. 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: 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... */ } @retval Returns FLI_OK on success, FLI_ERROR or FLI_NOT_OPEN on error, and FLI_EOF on reaching the end of the file. @@extern BITMAP *@fli_bitmap; @xref next_fli_frame, fli_bmp_dirty_from, fli_palette @shortdesc Contains the current frame of the animation. Contains the current frame of the FLI/FLC animation. If there is no open animation, its value will be NULL. @@extern PALETTE @fli_palette; @xref next_fli_frame, fli_pal_dirty_from, fli_bitmap @shortdesc Contains the current palette of the animation. Contains the current FLI palette. @@extern int @fli_bmp_dirty_from; @@extern int @fli_bmp_dirty_to; @xref fli_bitmap, reset_fli_variables @shortdesc Indicate which parts of the image have changed. 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: if (fli_bmp_dirty_from <= fli_bmp_dirty_to) blit(fli_bitmap, screen, 0, fli_bmp_dirty_from, 0, fli_bmp_dirty_from, fli_bitmap->w, fli_bmp_dirty_to - fli_bmp_dirty_from + 1); @@extern int @fli_pal_dirty_from; @@extern int @fli_pal_dirty_to; @xref fli_palette, reset_fli_variables @shortdesc Indicate which parts of the palette have changed. 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: if (fli_pal_dirty_from <= fli_pal_dirty_to) set_palette_range(fli_palette, fli_pal_dirty_from, fli_pal_dirty_to, 1); @@void @reset_fli_variables(); @xref fli_bmp_dirty_from, fli_pal_dirty_from @shortdesc Resets the bitmap and palette dirty global variables. Once you have done whatever you are going to do with the fli_bitmap and fli_palette, call this function to reset the fli_bmp_dirty_* and fli_pal_dirty_* variables. @@extern int @fli_frame; @xref play_fli, play_memory_fli, next_fli_frame @shortdesc Stores the current frame number of the animation. 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: 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... */ } @@extern volatile int @fli_timer; @xref install_timer, next_fli_frame @shortdesc Global variable for timing FLI playback. 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: while (next_fli_frame(0) == FLI_OK) { /* Do stuff, like play audio stream or check keys to skip animation. */ /* Rest some time until next frame... */ while (fli_timer <= 0) rest(0); } @heading Sound init routines Allegro allows you to use the sound hardware in two ways: automatic, or manual. Usually you should try the automatic version first. This means calling install_sound() with the autodetection parameters and using the rest of the sound functions to play samples or music. In this situation, Allegro will handle the sound devices and mix the samples and/or music the best way it can. However, sound hardware has a limitation on the number of samples it may play all at the same time (from now on, called hardware voices). When you exceed this limit, Allegro will cut off one of the samples being played and reproduce the new one. Depending on the type of sounds you are playing, how many of them you need at the same time and their nature (e.g: vital audio feedback to the user or useless "ping" when some shrapnel hits a rock in the 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. @@int @detect_digi_driver(int driver_id); @xref install_sound, reserve_voices @xref DIGI_*/DOS, DIGI_*/Windows, DIGI_*/Unix, DIGI_*/BeOS, DIGI_*/QNX @xref DIGI_*/MacOSX @shortdesc Detects whether the specified digital sound device is available. Detects whether the specified digital sound device is available. This function must be called _before_ install_sound(). @retval Returns the maximum number of voices that the driver can provide, or zero if the hardware is not present. @@int @detect_midi_driver(int driver_id); @xref install_sound, reserve_voices @xref MIDI_*/DOS, MIDI_*/Windows, MIDI_*/Unix, MIDI_*/BeOS, MIDI_*/QNX @xref MIDI_*/MacOSX @shortdesc Detects whether the specified MIDI sound device is available. Detects whether the specified MIDI sound device is available. This function must be called _before_ install_sound(). @retval 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. @@void @reserve_voices(int digi_voices, int midi_voices); @xref set_volume_per_voice, install_sound, detect_digi_driver @xref detect_midi_driver, get_mixer_voices @shortdesc Reserve a number of voices for the digital and MIDI drivers. 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. @@void @set_volume_per_voice(int scale); @xref reserve_voices, set_volume, install_sound, detect_digi_driver @xref detect_midi_driver @shortdesc Sets the volume of a voice. 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: 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) 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. @@int @install_sound(int digi, int midi, const char *cfg_path); @xref remove_sound, reserve_voices, detect_digi_driver, detect_midi_driver @xref set_volume, play_sample, Voice control, play_midi, play_audio_stream @xref install_sound_input, allegro_error, Standard config variables @xref set_mixer_quality @xref DIGI_*/DOS, DIGI_*/Windows, DIGI_*/Unix, DIGI_*/BeOS, DIGI_*/QNX @xref DIGI_*/MacOSX @xref MIDI_*/DOS, MIDI_*/Windows, MIDI_*/Unix, MIDI_*/BeOS, MIDI_*/QNX @xref MIDI_*/MacOSX @eref exmidi, exsample, exsprite, exstream @shortdesc Initialises the sound module. 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. @retval 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. @@void @remove_sound(); @xref install_sound, allegro_exit @shortdesc Cleans up after you are finished with the sound routines. 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. @@void @set_volume(int digi_volume, int midi_volume); @xref install_sound, set_hardware_volume @shortdesc Alters the global sound output volume. Alters the global sound output volume. Specify volumes for both digital samples and MIDI playback, as integers from 0 to 255, or pass a negative value to leave one of the settings unchanged. Values bigger than 255 will be reduced to 255. This routine will not alter the volume of the hardware mixer if it exists (i.e. only your application will be affected). @@void @set_hardware_volume(int digi_volume, int midi_volume); @xref install_sound, set_volume @shortdesc Alters the hardware sound output volume. Alters the hardware sound output volume. Specify volumes for both digital samples and MIDI playback, as integers from 0 to 255, or pass a negative value to leave one of the settings unchanged. Values bigger than 255 will be reduced to 255. This routine will use the hardware mixer to control the volume if it exists (i.e. the volume of all the applications on your machine will be affected), otherwise do nothing. @heading Mixer routines @@void @set_mixer_quality(int quality); @xref get_mixer_quality @xref Standard config variables @shortdesc Sets the resampling quality of the mixer. 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(). @@int @get_mixer_quality(void); @xref set_mixer_quality @xref Standard config variables @shortdesc Returns the current mixing quality. Returns the current mixing quality, as specified by the `quality' config variable, or a previous call to set_mixer_quality(). @@int @get_mixer_frequency(void); @xref Standard config variables @shortdesc Returns the mixer frequency, in Hz. Returns the mixer frequency, in Hz. @@int @get_mixer_bits(void); @xref Standard config variables @shortdesc Returns the mixer bitdepth (8 or 16). Returns the mixer bitdepth (8 or 16). @@int @get_mixer_channels(void); @xref Standard config variables @shortdesc Returns the number of output channels. Returns the number of output channels. 2 for stereo, 1 for mono, 0 if the mixer isn't active. @@int @get_mixer_voices(void); @xref reserve_voices @shortdesc Returns the number of voices allocated to the mixer. Returns the number of voices allocated to the mixer. @@int @get_mixer_buffer_length(void); @xref Standard config variables @shortdesc Returns the number of samples per channel in the mixer buffer. Returns the number of samples per channel in the mixer buffer. @heading Digital sample routines @@SAMPLE *@load_sample(const char *filename); @xref destroy_sample, load_voc, load_wav, play_sample, save_sample @xref register_sample_file_type, Voice control @eref exsample @shortdesc Loads a sample from a file. 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: SAMPLE *sample = load_sample(user_input); if (!sample) abort_on_error("Couldn't load sample!"); @retval Returns a pointer to the SAMPLE or NULL on error. Remember to free this sample later to avoid memory leaks. @@SAMPLE *@load_wav(const char *filename); @xref load_sample, register_sample_file_type @shortdesc Loads a sample from a RIFF WAV file. Loads a sample from a RIFF WAV file. Example: SAMPLE *sample = load_wav("scream.wav"); if (!sample) abort_on_error("Couldn't scare user!"); @retval Returns a pointer to the SAMPLE or NULL on error. Remember to free this sample later to avoid memory leaks. @@SAMPLE *@load_wav_pf(PACKFILE *f); @xref load_wav @shortdesc Packfile version of load_wav. A version of load_wav() which reads from a packfile. Example: PACKFILE *packfile; SAMPLE *sample; packfile = pack_fopen("sound.wav", F_READ); if (!packfile) abort_on_error("Couldn't open sound.wav"); sample = load_wav_pf(packfile); if (!sample) abort_on_error("Error loading sound.wav"); @retval Returns a pointer to the SAMPLE or NULL on error. Remember to free this sample later to avoid memory leaks. @@SAMPLE *@load_voc(const char *filename); @xref load_sample, register_sample_file_type @shortdesc Loads a sample from a Creative Labs VOC file. Loads a sample from a Creative Labs VOC file. Example: SAMPLE *sample = load_wav("alarm.wav"); if (!sample) abort_on_error("Couldn't alert user!"); @retval Returns a pointer to the SAMPLE or NULL on error. Remember to free this sample later to avoid memory leaks. @@SAMPLE *@load_voc_pf(PACKFILE *f); @xref load_voc @shortdesc Packfile version of load_voc. A version of load_voc() which reads from a packfile. Example: PACKFILE *packfile; SAMPLE *sample; packfile = pack_fopen("sound.wav", F_READ); if (!packfile) abort_on_error("Couldn't open sound.wav"); sample = load_wav_pf(packfile); if (!sample) abort_on_error("Error loading sound.wav"); @retval Returns a pointer to the SAMPLE or NULL on error. Remember to free this sample later to avoid memory leaks. @@int @save_sample(const char *filename, SAMPLE *spl); @xref load_sample, register_sample_file_type @shortdesc Writes a sample into a file. 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: if (save_sample("sound.wav", sample) != 0) abort_on_error("Couldn't save sample!"); @retval Returns zero on success, non-zero otherwise. @@SAMPLE *@create_sample(int bits, int stereo, int freq, int len); @xref load_sample, destroy_sample, Structures and types defined by Allegro @shortdesc Constructs a new sample structure of the specified type. 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. @retval 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. @@void @destroy_sample(SAMPLE *spl); @xref load_sample @eref exsample @shortdesc Destroys a sample structure when you are done with it. 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. @@void @lock_sample(SAMPLE *spl); @xref load_sample, create_sample @shortdesc Locks all the memory used by a sample. 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. @\void @register_sample_file_type(const char *ext, @\ SAMPLE *(*load)(const char *filename), @@ int (*save)(const char *filename, SAMPLE *spl)); @xref load_sample, save_sample @shortdesc Registers custom loading/saving sample routines. 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: SAMPLE *load_mp3(const char *filename) { ... } register_sample_file_type("mp3", load_mp3, NULL); @@int @play_sample(const SAMPLE *spl, int vol, int pan, int freq, int loop); @xref install_sound, load_sample, adjust_sample, stop_sample, Voice control @eref exsample, exsprite @shortdesc Plays a sample. 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: /* Scream from the left speaker, twice the freq. */ int sound = play_sample(scream, 255, 0, 2000, 0); @retval Returns the voice number that was allocated for the sample or negative if no voices were available. @@void @adjust_sample(const SAMPLE *spl, int vol, int pan, int freq, int loop); @xref play_sample @eref exsample @shortdesc Alters the parameters of a sample while it is playing. 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. @@void @stop_sample(const SAMPLE *spl); @xref play_sample @shortdesc Kills off a sample. 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. @hnode Voice control @xref install_sound, allocate_voice, deallocate_voice, reallocate_voice @xref release_voice, voice_start, voice_set_priority, voice_check @xref voice_set_position, voice_set_playmode, voice_set_volume @xref voice_set_frequency, voice_set_pan, SAMPLE 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. @@int @allocate_voice(const SAMPLE *spl); @xref Voice control, deallocate_voice, reallocate_voice, release_voice @xref load_sample @shortdesc Allocates a soundcard voice for a sample. 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. @retval Returns the voice number, or -1 if no voices are available. @@void @deallocate_voice(int voice); @xref allocate_voice, voice_stop @shortdesc Frees a soundcard voice. Frees a soundcard voice, stopping it from playing and releasing whatever resources it is using. @@void @reallocate_voice(int voice, const SAMPLE *spl); @xref allocate_voice, deallocate_voice, load_sample @shortdesc Switches the sample of an already-allocated voice. Switches an already-allocated voice to use a different sample. Calling reallocate_voice(voice, sample) is equivalent to: deallocate_voice(voice); voice = allocate_voice(sample); @@void @release_voice(int voice); @xref allocate_voice, deallocate_voice @shortdesc Releases a soundcard voice. 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. @@void @voice_start(int voice); @xref Voice control, allocate_voice, voice_stop, release_voice @eref exstream @shortdesc Activates a voice. Activates a voice, using whatever parameters have been set for it. @@void @voice_stop(int voice); @xref voice_start, deallocate_voice, release_voice @eref exstream @shortdesc Stops a voice. Stops a voice, storing the current position and state so that it may later be resumed by calling voice_start(). @@void @voice_set_priority(int voice, int priority); @xref Voice control @shortdesc Sets the priority of a voice. 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. @@SAMPLE *@voice_check(int voice); @xref allocate_voice, voice_start, voice_get_position @shortdesc Checks whether a voice is currently allocated. Checks whether a voice is currently allocated. @retval 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). @@int @voice_get_position(int voice); @xref Voice control, voice_set_position @shortdesc Returns the current position of a voice. Returns the current position of a voice, in sample units, or -1 if it has finished playing. @@void @voice_set_position(int voice, int position); @xref Voice control, voice_get_position, voice_set_playmode @shortdesc Sets the position of a voice. Sets the position of a voice, in sample units. @@void @voice_set_playmode(int voice, int playmode); @xref Voice control @shortdesc Adjusts the loop status of the specified voice. 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:
  • PLAYMODE_PLAY
    Plays the sample a single time. This is the default if you don't set the loop flag.
  • PLAYMODE_LOOP
    Loops repeatedly through the sample, jumping back to the loop start position upon reaching the loop end.
  • PLAYMODE_FORWARD
    Plays the sample from beginning to end. This is the default if you don't set the backward flag.
  • PLAYMODE_BACKWARD
    Reverses the direction of the sample. If you combine this with the loop flag, the sample jumps to the loop end position upon reaching the loop start (ie. you do not need to reverse the loop start and end values when you play the sample in reverse).
  • PLAYMODE_BIDIR
    When used in combination with the loop flag, causes the sample to change direction each time it reaches one of the loop points, so it alternates between playing forwards and in reverse.
@@int @voice_get_volume(int voice); @xref Voice control, voice_set_volume @shortdesc Returns the current volume of the voice. Returns the current volume of the voice, range 0-255. Otherwise it returns -1 if that cannot be determined (because it has finished or been preempted by a different sound). @@void @voice_set_volume(int voice, int volume); @xref Voice control, voice_get_volume, voice_ramp_volume @shortdesc Sets the volume of the voice. Sets the volume of the voice, range 0-255. @@void @voice_ramp_volume(int voice, int time, int endvol); @xref Voice control, voice_set_volume @shortdesc Starts a volume ramp for a voice. 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. @@void @voice_stop_volumeramp(int voice); @xref voice_ramp_volume @shortdesc Interrupts a volume ramp operation. Interrupts a volume ramp operation. @@int @voice_get_frequency(int voice); @xref Voice control, voice_set_frequency @shortdesc Returns the current pitch of the voice. Returns the current pitch of the voice, in Hz. @@void @voice_set_frequency(int voice, int frequency); @xref Voice control, voice_get_frequency, voice_sweep_frequency @shortdesc Sets the pitch of the voice. Sets the pitch of the voice, in Hz. @@void @voice_sweep_frequency(int voice, int time, int endfreq); @xref Voice control, voice_set_frequency @shortdesc Starts a frequency sweep for a voice. Starts a frequency sweep (glissando) from the current pitch to the specified ending pitch, lasting for time milliseconds. @@void @voice_stop_frequency_sweep(int voice); @xref voice_sweep_frequency @shortdesc Interrupts a frequency sweep operation. Interrupts a frequency sweep operation. @@int @voice_get_pan(int voice); @xref Voice control, voice_set_pan @shortdesc Returns the current pan position. Returns the current pan position, from 0 (left) to 255 (right). @@void @voice_set_pan(int voice, int pan); @xref Voice control, voice_get_pan, voice_sweep_pan @shortdesc Sets the pan position. Sets the pan position, ranging from 0 (left) to 255 (right). @@void @voice_sweep_pan(int voice, int time, int endpan); @xref Voice control, voice_set_pan @shortdesc Starts a pan sweep for a voice. Starts a pan sweep (left <-> right movement) from the current position to the specified ending position, lasting for time milliseconds. @@void @voice_stop_pan_sweep(int voice); @xref voice_sweep_pan @shortdesc Interrupts a pan sweep operation. Interrupts a pan sweep operation. @@void @voice_set_echo(int voice, int strength, int delay); @xref Voice control @shortdesc Sets the echo parameters for a voice. Sets the echo parameters for a voice (not currently implemented). @@void @voice_set_tremolo(int voice, int rate, int depth); @xref Voice control @shortdesc Sets the tremolo parameters for a voice. Sets the tremolo parameters for a voice (not currently implemented). @@void @voice_set_vibrato(int voice, int rate, int depth); @xref Voice control @shortdesc Sets the vibrato parameters for a voice. Sets the vibrato parameters for a voice (not currently implemented). @heading Music routines (MIDI) Allegro allows you to play MIDI files. MIDI files basically contain notes and the type of instrument that is meant to play them, so they are usually very small in size. However, it's up to the 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 (http://alleg.sourceforge.net/) you can find more information about DIGMID and where to download digital samples for your MIDI files. @@MIDI *@load_midi(const char *filename); @xref destroy_midi, play_midi, get_midi_length @eref exmidi @shortdesc Loads a MIDI file. Loads a MIDI file (handles both format 0 and format 1). Example: MIDI *music; music = load_midi("backmus.mid"); if (!music) abort_on_error("Couldn't load background music!"); @retval Returns a pointer to a MIDI structure, or NULL on error. Remember to free this MIDI file later to avoid memory leaks. @@void @destroy_midi(MIDI *midi); @xref load_midi @eref exmidi @shortdesc Destroys a MIDI structure when you are done with it. 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. @@void @lock_midi(MIDI *midi); @xref load_midi @shortdesc Locks all the memory used by a MIDI file. 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. @@int @play_midi(MIDI *midi, int loop); @xref install_sound, load_midi, play_looped_midi, stop_midi, midi_pause @xref midi_seek, midi_pos, midi_time, midi_msg_callback @eref exmidi @shortdesc Starts playing the specified MIDI file. 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. @retval 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 :-) @@int @play_looped_midi(MIDI *midi, int loop_start, int loop_end); @xref play_midi, midi_pos, midi_loop_start @shortdesc Starts playing a MIDI file with a user-defined loop position. 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. @retval The return value has the same meaning as that of play_midi(): non-zero if an error occurs, zero otherwise. @@void @stop_midi(); @xref play_midi, midi_pause @shortdesc Stops whatever music is currently playing. Stops whatever music is currently playing. This is the same thing as calling play_midi(NULL, FALSE). @@void @midi_pause(); @xref play_midi, stop_midi, midi_resume, midi_seek @eref exmidi @shortdesc Pauses the MIDI player. Pauses the MIDI player. @@void @midi_resume(); @xref midi_pause @eref exmidi @shortdesc Resumes playback of a paused MIDI file. Resumes playback of a paused MIDI file. @@int @midi_seek(int target); @xref play_midi, midi_pos @shortdesc Seeks to the given midi_pos in the current MIDI file. 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. @retval 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. @@int @get_midi_length(MIDI *midi); @xref load_midi, midi_time, midi_pos @eref exmidi @shortdesc Determines the total playing time of a midi, in seconds. 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: length = get_midi_length(my_midi); play_midi(my_midi); do { pos = midi_time; textprintf_ex(screen, font, 0, 0, c, -1, "%d:%02d / %d:%02d\n", pos / 60, pos % 60, length / 60, length % 60); rest(100); } while(pos <= length); @retval Returns the value of midi_time, the length of the midi. @@void @midi_out(unsigned char *data, int length); @xref install_sound, load_midi_patches, midi_recorder @shortdesc Streams a block of MIDI commands into the player. 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. @@int @load_midi_patches(); @xref install_sound, midi_out @shortdesc Forces the MIDI driver to load a set of patches. Forces the MIDI driver to load the entire set of patches ready for use. You will not normally need to call this, because Allegro automatically loads whatever data is required for the current MIDI file, but you must call it before sending any program change messages via the midi_out() command. @retval Returns non-zero if an error occurred. @@extern volatile long @midi_pos; @xref play_midi, midi_msg_callback @eref exmidi @shortdesc Stores the current position in the MIDI file. 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. @@extern volatile long @midi_time; @xref play_midi, midi_pos, get_midi_length @eref exmidi @shortdesc The current position in the MIDI file, in seconds. 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. @@extern long @midi_loop_start; @@extern long @midi_loop_end; @xref play_looped_midi @shortdesc Loop start and end points, set by play_looped_midi(). The loop start and end points, set by the play_looped_midi() function. These may safely be altered while the music is playing, but you should be sure they are always set to sensible values (start < end). If you are changing them both at the same time, make sure to alter them in the right order in case a MIDI interrupt happens to occur in between your two writes! Setting these values to -1 represents the start and end of the file respectively. @@extern void (*@midi_msg_callback)(int msg, int byte1, int byte2); @@extern void (*@midi_meta_callback)(int type, const unsigned char *data, int length); @@extern void (*@midi_sysex_callback)(const unsigned char *data, int length); @xref play_midi @shortdesc Hook functions allowing you to intercept MIDI player events. 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. @@int @load_ibk(char *filename, int drums); @xref install_sound @shortdesc Reads in a .IBK patch definition file for the Adlib driver. 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! @retval Returns non-zero on error. @heading Audio stream routines The audio stream functions are for playing digital sounds that are too big to fit in a regular SAMPLE structure, either because they are huge files that you want to load in pieces as the data is required, or because you are doing something clever like generating the waveform on the fly. You can think of an AUDIOSTREAM structure as a wrapper around two audio buffers. The first thing you do is fill both buffers with sound data and let Allegro play them. Once the first buffer has been played, the second starts, and Allegro lets you know you have to fill the other one (i.e. graphics double buffering applied to sounds too big to fit into memory). The implementation of the sound buffers uses normal SAMPLE structures, so you can use all the voice_*() functions to modify the audio streams. Read chapter "Digital sample routines", section "Voice control" for a list of additional functions you can use. Read chapter "Structures and types defined by Allegro" for the internals of the AUDIOSTREAM structure. @\AUDIOSTREAM *@play_audio_stream(int len, int bits, int stereo, @@ int freq, int vol, int pan); @xref install_sound, get_audio_stream_buffer, stop_audio_stream @xref AUDIOSTREAM, Voice control @eref exstream @shortdesc Creates a new audio stream and starts playing it. This function creates a new audio stream and starts playing it. The length is the size of each transfer buffer in sample frames (not bytes), where a sample frame is a single sample value for mono data or a pair of interleaved sample values (left first) for stereo data. The length should normally be (but doesn't have to be) a power of 2 somewhere around 1k in size. Larger buffers are more efficient and require fewer updates, but result in more latency between you providing the data and it actually being played. The `bits' parameter must be 8 or 16. `freq' is the sample rate of the data in Hertz. The `vol' and `pan' values use the same 0-255 ranges as the regular sample playing functions. The `stereo' parameter should be set to 1 for stereo streams, or 0 otherwise. If you want to adjust the pitch, volume, or panning of a stream once it is playing, you can use the regular voice_*() functions with stream->voice as a parameter. The format of the sample data is described in the SAMPLE entry of the "Structures and types defined by Allegro" chapter. The formula to get the size of the buffers in bytes could be: bytes = length * (bits / 8) * (stereo ? 2 : 1) Example: /* Create a 22KHz 8bit mono audio stream. */ stream = play_audio_stream(1024, 8, FALSE, 22050, 255, 128); if (!stream) abort_on_error("Error creating audio stream!\n"); @retval This function returns a pointer to the audio stream or NULL if it could not be created. @@void @stop_audio_stream(AUDIOSTREAM *stream); @xref play_audio_stream @eref exstream @shortdesc Destroys an audio stream when it is no longer required. Destroys an audio stream when it is no longer required. @@void *@get_audio_stream_buffer(AUDIOSTREAM *stream); @xref play_audio_stream, free_audio_stream_buffer @eref exstream @shortdesc Tells you if you need to fill the audiostream or not. 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: void *mem_chunk; ... while (TRUE) { ... mem_chunk = get_audio_stream_buffer(buffer); if (mem_chunk != NULL) { /* Refill the stream buffer. */ } } @retval 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. @@void @free_audio_stream_buffer(AUDIOSTREAM *stream); @xref get_audio_stream_buffer @eref exstream @shortdesc Tells the audio stream player new data can be played. 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: mem_chunk = get_audio_stream_buffer(buffer); if (mem_chunk != NULL) { /* Refill the stream buffer. */ ... free_audio_stream_buffer(buffer); } @heading Recording routines 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. @@int @install_sound_input(int digi, int midi); @xref install_sound, start_sound_input, midi_recorder @xref Standard config variables @xref DIGI_*/DOS, DIGI_*/Windows, DIGI_*/Unix, DIGI_*/BeOS, DIGI_*/QNX @xref DIGI_*/MacOSX @xref MIDI_*/DOS, MIDI_*/Windows, MIDI_*/Unix, MIDI_*/BeOS, MIDI_*/QNX @xref MIDI_*/MacOSX @shortdesc Initialises the sound recorder module. 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. @retval This function returns zero on success, and any other value if the machine or driver doesn't support sound recording. @@void @remove_sound_input(); @xref install_sound_input, remove_sound, allegro_exit @shortdesc Cleans up after you are finished with the sound input routines. 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. @@int @get_sound_input_cap_bits(); @xref start_sound_input, get_sound_input_cap_parm, get_sound_input_cap_rate @xref get_sound_input_cap_stereo @shortdesc Checks which audio input sample formats are supported. Checks which sample formats are supported by the current audio input driver, returning one of the bitfield values: 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 Example: cap = get_sound_input_cap_bits(); if (cap == 0) { /* Ugh, no audio input supported? */ } else { if (cap & 8) { /* We have eight bit audio input. */ } if (cap & 16) { /* We have sixteen bit audio input. */ } } @@int @get_sound_input_cap_stereo(); @xref start_sound_input, get_sound_input_cap_parm, get_sound_input_cap_bits @xref get_sound_input_cap_rate @shortdesc Tells if the input driver is capable of stereo recording. Checks whether the current audio input driver is capable of stereo recording. @retval Returns non-zero if the driver is capable of stereo recording. @@int @get_sound_input_cap_rate(int bits, int stereo); @xref start_sound_input, get_sound_input_cap_parm, get_sound_input_cap_bits @xref get_sound_input_cap_stereo @shortdesc Returns the maximum sample frequency for recording. 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: 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. */ } @@int @get_sound_input_cap_parm(int rate, int bits, int stereo); @xref start_sound_input, get_sound_input_cap_bits, get_sound_input_cap_rate @xref get_sound_input_cap_stereo @shortdesc Detects if the specified recording parameters are supported. Checks whether the specified recording frequency, number of bits, and mono/stereo mode are supported (and how) by the current audio driver. @retval The function returns one of the following possible values: 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. @@int @set_sound_input_source(int source); @xref start_sound_input @shortdesc Selects the audio input source. Selects the audio input source. The parameter should be one of the values: SOUND_INPUT_MIC SOUND_INPUT_LINE SOUND_INPUT_CD @retval 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). @@int @start_sound_input(int rate, int bits, int stereo); @xref install_sound_input, read_sound_input, stop_sound_input @xref digi_recorder, set_sound_input_source, get_sound_input_cap_parm @xref get_sound_input_cap_bits, get_sound_input_cap_rate @xref get_sound_input_cap_stereo @shortdesc Starts recording in the specified format. Starts recording in the specified format, suspending audio playback as necessary if the card is not full duplex. @retval Returns the buffer size in bytes if successful, or zero on error. @@void @stop_sound_input(); @xref start_sound_input @shortdesc Stops audio recording. Stops audio recording, switching the card back into the normal playback mode. @@int @read_sound_input(void *buffer); @xref start_sound_input @shortdesc Retrieves the last recorded audio buffer. Retrieves the most recently recorded audio buffer into the specified location. The buffer size can be obtained by checking the return value from start_sound_input(). You must be sure to call this function at regular intervals during the recording (typically around 100 times a second), or some data will be lost. If you are unable to do this often enough from the mainline code, use the digi_recorder() callback to store the waveform into a larger buffer of your own. Note: many cards produce a click or popping sound when switching between record and playback modes, so it is often a good idea to discard the first buffer after you start a recording. The waveform is always stored in unsigned format, with stereo data consisting of alternate left/right samples. @retval 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). @@extern void (*@digi_recorder)(); @xref install_sound_input, start_sound_input @shortdesc Hook notifying you when a new sample buffer becomes available. 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. @@extern void (*@midi_recorder)(unsigned char data); @xref install_sound_input, midi_out @shortdesc Hook notifying you when new MIDI data becomes available. 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. @heading File and compression routines The following routines implement a fast buffered file I/O system, which supports the reading and writing of compressed files using a ring buffer algorithm based on the LZSS compressor by Haruhiko Okumura. This does not achieve quite such good compression as programs like zip and lha, but unpacking is very fast and it does not require much memory. Packed files always begin with the 32-bit value F_PACK_MAGIC, and autodetect files with the value F_NOPACK_MAGIC. The following FA_* flags are guaranteed to work: FA_RDONLY, FA_HIDDEN, FA_SYSTEM, FA_LABEL, FA_DIREC, FA_ARCH. Do not use any other flags from DOS/Windows or your code will not compile on another platform. Flags FA_SYSTEM, FA_LABEL and FA_ARCH are valuable only on DOS/Windows (entries with system flag, volume labels and archive flag). FA_RDONLY is for directory entries with read-only flag on DOS-like systems or unwritable by current user on Unix-like systems. FA_HIDDEN is for entries with hidden flag on DOS-like systems or starting with '.' on Unix (dotted files - excluding '.' and '..'). FA_DIREC represents directories. 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. 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. 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). @@void @get_executable_name(char *buf, int size); @shortdesc Obtains the full path to the current executable. 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: char name[200]; ... get_executable_name(name, sizeof(name)); allegro_message("Running `%s'\n", name); @@char *@fix_filename_case(char *path); @xref fix_filename_slashes, canonicalize_filename @shortdesc Converts a filename to a standardised case. 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: get_executable_name(name, sizeof(name)); fix_filename_case(name); allegro_message("Running `%s'\n", name); @retval Returns a copy of the `path' parameter. @@char *@fix_filename_slashes(char *path); @xref fix_filename_case, canonicalize_filename @shortdesc Converts all the directory separators to a standard character. 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: 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. */ @retval Returns a copy of the `path' parameter. @@char *@canonicalize_filename(char *dest, const char *filename, int size); @xref fix_filename_case, fix_filename_slashes @shortdesc Converts any filename into its canonical form. 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: char buf[256]; ... canonicalize_filename(buf, "~/../s22/..\\t3st///hi.c", sizeof(buf)); /* Running this under Unix would return: /home/t3st/hi.c */ 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"). @retval Returns a copy of the `dest' parameter. @@char *@make_absolute_filename(char *dest, const char *path, const char *filename, int size); @xref make_relative_filename, is_relative_filename, replace_filename @xref canonicalize_filename @shortdesc Makes an absolute filename from a path and relative filename. 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: char buf[256]; ... make_absolute_filename(buf, "/usr/games/", "../temp.txt", sizeof(buf)); /* This would create /usr/temp.txt */ @retval Returns a copy of the `dest' parameter. @@char *@make_relative_filename(char *dest, const char *path, const char *filename, int size); @xref make_absolute_filename, is_relative_filename, canonicalize_filename @shortdesc Tries to make a relative filename from absolute path and filename. 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: 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 */ @retval 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:\"). @@int @is_relative_filename(const char *filename); @xref make_absolute_filename, make_relative_filename @shortdesc Returns TRUE if the filename is relative. 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. @\char *@replace_filename(char *dest, const char *path, @@ const char *filename, int size); @xref get_filename, replace_extension, append_filename @eref Available Allegro examples @shortdesc Replaces path+filename with a new filename tail. 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: char name[200]; ... get_executable_name(name, sizeof(name)); replace_filename(name, name, "sound.dat", sizeof(name)); @retval Returns a copy of the `dest' parameter. @\char *@replace_extension(char *dest, const char *filename, @@ const char *ext, int size); @xref get_extension, replace_filename @shortdesc Replaces filename+extension with a new extension tail. 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: replace_extension(buf, "C:\\game\\prog.exe", "dat", sizeof(buf)); @retval Returns a copy of the `dest' parameter. @\char *@append_filename(char *dest, const char *path, @@ const char *filename, int size); @xref replace_filename @shortdesc Concatenates a filename to a path. 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: append_filename(buf, "/home/user", "prog.bin", sizeof(buf)); @retval Returns a copy of the `dest' parameter. @@char *@get_filename(const char *path); @xref get_extension, put_backslash, replace_filename @eref exmidi @shortdesc Returns a pointer to the filename portion of a path. Finds out the filename portion of a completely specified file path. Both `\' and `/' are recognized as directory separators under DOS and Windows. However, only `/' is recognized as directory separator under other platforms. Example: get_executable_name(name, sizeof(name)); allegro_message("Running `%s'\n", get_filename(name)); 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. @retval 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). @@char *@get_extension(const char *filename); @xref get_filename, put_backslash, replace_extension @shortdesc Returns a pointer to the extension of a filename. Finds out the extension of the filename (with or without path information). Example: get_executable_name(name, sizeof(name)); allegro_message("The binary has the extension `%s'\n", get_extension(name)); @retval 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. @@void @put_backslash(char *filename); @xref get_extension, get_filename @shortdesc Puts a path separator at the end of a path if needed. 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. @@int @file_exists(const char *filename, int attrib, int *aret); @xref exists, file_size, file_time @shortdesc Tells if a file exists. 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: /* Check for a normal file. */ if (file_exists("franken.dat", 0, NULL)) allegro_message("It is alive!\n"); @retval Returns non-zero if the file exists, or zero if it doesn't or the specified attributes mask it out. @@int @exists(const char *filename); @xref file_exists, file_size, file_time @shortdesc Shortcut version of file_exists() for normal files. 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. @retval Returns non-zero if the file exists, or zero if it doesn't. @@long @file_size(const char *filename); @xref file_exists, file_time @eref expackf @shortdesc Returns the size of a file in bytes. 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. @@time_t @file_time(const char *filename); @xref file_exists, file_size @shortdesc Returns the modification time of a file. 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. @@int @delete_file(const char *filename); @shortdesc Removes a file from the disk. Removes a file from the disk. You can't delete directories, though. @retval Returns zero on success, non-zero on failure. @\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); @xref al_findfirst, al_findnext, al_findclose @shortdesc Executes callback() for each file matching a wildcard. 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: 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); @retval Returns the number of successful calls made to callback(), that is, the number of times callback() was called and returned 0. @@int @al_findfirst(const char *pattern, struct al_ffblk *info, int attrib); @xref al_findnext, al_findclose @shortdesc Low-level function for searching files. 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: struct al_ffblk { int attrib; - actual attributes of the file found time_t time; - modification time of file long size; - size of file char name[512]; - name of file }; There is some other stuff in the structure as well, but it is there for internal use only. Example: struct al_ffblk info; if (al_findfirst("*.pcx", &info, 0) != 0) { /* Tell user there are no PCX files. */ return; } @retval 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. @@int @al_findnext(struct al_ffblk *info); @xref al_findfirst, al_findclose @shortdesc Finds the next file in a search started by al_findfirst(). This finds the next file in a search started by al_findfirst(). Example: if (al_findfirst("*.pcx", &info, 0) != 0) return; do { /* Do something useful here with info.name. */ } while (al_findnext(&info) == 0); al_findclose(&info); @retval 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. @@void @al_findclose(struct al_ffblk *info); @xref al_findfirst, al_findnext @shortdesc Closes a previously opened search with al_findfirst(). 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. @\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); @xref set_allegro_resource_path @shortdesc Searches for a support file in many places. 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: 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. */ } @retval Returns zero on success, and stores a full path to the file (at most size bytes) into the dest buffer. @@int @set_allegro_resource_path(int priority, const char *path); @xref find_allegro_resource @shortdesc Sets a specific resource search path. Sometimes Allegro doesn't look in enough places to find a resource. For those special cases, you can call this function before loading your resource with additional paths to search for. You set up the priorities, higher numbers are searched for first. To modify an already setup path, call this function with the same priority and the new path. To remove an already setup path, call this function with the priority of the path and NULL as the path parameter. Example: set_allegro_resource_path(10, "my_game/configs"); set_allegro_resource_path(0, "users/configs/"); set_allegro_resource_path(-45, "temp"); 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. @retval 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. @@void @packfile_password(const char *password); @xref pack_fopen, load_datafile, pack_fopen_vtable @shortdesc Sets the global I/O encryption password. Sets the encryption password to be used for all read/write operations on files opened in future using Allegro's packfile functions (whether they are compressed or not), including all the save, load and config routines. Files written with an encryption password cannot be read unless the same password is selected, so be careful: if you forget the key, nobody can make your data come back again! Pass NULL or an empty string to return to the normal, non-encrypted mode. If you are using this function to prevent people getting access to your datafiles, be careful not to store an obvious copy of the password in your executable: if there are any strings like "I'm the password for the datafile", it would be fairly easy to get access to your data :-) Note #1: when writing a packfile, you can change the password to whatever you want after opening the file, without affecting the write operation. On the contrary, when writing a sub-chunk of a packfile, you must make sure that the password that was active at the time the sub-chunk was opened is still active before closing the sub-chunk. This is guaranteed to be true if you didn't call the packfile_password() routine in the meantime. Read operations, either on packfiles or sub-chunks, have no such restriction. Note #2: as explained above, the password is used for all read/write operations on files, including for several functions of the library that operate on files without explicitly using packfiles (e.g. load_bitmap()). The unencrypted mode is mandatory in order for those functions to work. Therefore remember to call packfile_password(NULL) before using them if you previously changed the password. As a rule of thumb, always call packfile_password(NULL) when you are done with operations on packfiles. The only exception to this is custom packfiles created with pack_fopen_vtable(). @@PACKFILE *@pack_fopen(const char *filename, const char *mode); @xref pack_fclose, pack_fopen_chunk, packfile_password, pack_fread, pack_getc @xref file_select_ex, pack_fopen_vtable @eref expackf @shortdesc Opens a file according to mode. Opens a file according to mode, which may contain any of the flags:
  • `r' - open file for reading.
  • `w' - open file for writing, overwriting any existing data.
  • `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.
  • `!' - 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.
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:
  • `#' - read data that has been appended to your executable file with the exedat utility, as if it was a regular independent disk file.
  • `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'.
  • `#object_name' - combination of the above, reading an object from a datafile that has been appended onto your executable.
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: PACKFILE *input_file; input_file = pack_fopen("scores.dat", "rp"); if (!input_file) abort_on_error("Couldn't read `scores.dat'!"); @retval 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. @@PACKFILE *@pack_fopen_vtable(const PACKFILE_VTABLE *vtable, void *userdata); @xref pack_fopen, pack_fopen_chunk, packfile_password @eref expackf 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(). @retval On success, it returns a pointer to a PACKFILE structure, and on error it returns NULL and stores an error code in `errno'. @@int @pack_fclose(PACKFILE *f); @xref pack_fopen, pack_fopen_vtable, packfile_password @eref expackf @shortdesc Closes a stream previously opened. 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. @retval 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. @@int @pack_fseek(PACKFILE *f, int offset); @xref pack_fopen, pack_fopen_chunk @eref expackf @shortdesc Seeks inside a stream. 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: 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); @retval Returns zero on success or a negative number on error, storing the error code in `errno'. @@int @pack_feof(PACKFILE *f); @xref pack_fopen, pack_fopen_chunk, pack_ferror @shortdesc Returns nonzero as soon as you reach the end of the file. 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). @retval Returns non-zero if you are at the end of the file, zero otherwise. @@int @pack_ferror(PACKFILE *f); @xref pack_fopen, pack_fopen_chunk @shortdesc Tells if an error occurred during an operation on the stream. 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. @retval Returns nonzero if the error indicator for the stream is set, meaning that an error has occurred during a previous operation on the stream. @@int @pack_getc(PACKFILE *f); @xref pack_fopen, pack_fopen_chunk @shortdesc Returns the next character from a stream. Returns the next character from the stream `f', or EOF if the end of the file has been reached. @@int @pack_putc(int c, PACKFILE *f); @xref pack_fopen, pack_fopen_chunk @shortdesc Puts a character in the stream. Puts a character in the stream f. @retval Returns the character written on success, or EOF on error. @@int @pack_igetw(PACKFILE *f); @xref pack_getc @shortdesc Like pack_getc(), but using 16-bit Intel byte ordering words. 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). @@int @pack_iputw(int c, PACKFILE *f); @xref pack_putc @shortdesc Like pack_putc(), but using 16-bit Intel byte ordering words. 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). @@long @pack_igetl(PACKFILE *f); @xref pack_getc @shortdesc Like pack_getc(), but using 32-bit Intel byte ordering words. 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). @@long @pack_iputl(long c, PACKFILE *f); @xref pack_putc @shortdesc Like pack_putc(), but using 32-bit Intel byte ordering words. 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). @@int @pack_mgetw(PACKFILE *f); @xref pack_getc @shortdesc Like pack_getc(), but using 16-bit Motorola byte ordering words. 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). @@int @pack_mputw(int c, PACKFILE *f); @xref pack_putc @shortdesc Like pack_putc(), but using 16-bit Motorola byte ordering words. 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). @@long @pack_mgetl(PACKFILE *f); @xref pack_getc @shortdesc Like pack_getc(), but using 32-bit Motorola byte ordering words. 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). @@long @pack_mputl(long c, PACKFILE *f); @xref pack_putc @shortdesc Like pack_putc(), but using 32-bit Motorola byte ordering words. 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). @@long @pack_fread(void *p, long n, PACKFILE *f); @xref pack_fopen, pack_fopen_chunk, pack_feof @eref expackf @shortdesc Reads n bytes from the stream. Reads `n' bytes from the stream `f', storing them at the memory location pointed to by `p'. Example: unsigned char buf[256]; ... if (pack_fread(buf, 256, input_file) != 256) abort_on_error("Truncated input file!"); @retval 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. @@long @pack_fwrite(const void *p, long n, PACKFILE *f); @xref pack_fopen, pack_fopen_chunk, pack_feof @shortdesc Writes n bytes to the stream. Writes `n' bytes to the stream `f' from memory location pointed to by `p'. @retval Returns the number of bytes written, which will be less than n if an error occurs. Error codes are stored in errno. @@char *@pack_fgets(char *p, int max, PACKFILE *f); @xref pack_fopen, pack_fopen_chunk, pack_fread, pack_getc @shortdesc Reads a line from the stream. 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: char buf[256]; ... while (pack_fgets(buf, sizeof(buf), input_file)) { /* Process input line. */ } fclose(input_file); @retval Returns the pointer `p' on success, or NULL on error. @@int @pack_fputs(const char *p, PACKFILE *f); @xref pack_fopen, pack_fopen_chunk, pack_fwrite, pack_putc @shortdesc Writes a string to the stream. 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. @retval Returns zero on success or a negative number on error. @@PACKFILE *@pack_fopen_chunk(PACKFILE *f, int pack); @xref pack_fclose_chunk, pack_fopen @shortdesc Opens a sub-chunk of a file. 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: 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); 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: 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); 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. @retval Returns a pointer to the sub-chunked PACKFILE, or NULL if there was some error (eg. you are using a custom PACKFILE vtable). @@PACKFILE *@pack_fclose_chunk(PACKFILE *f); @xref pack_fopen_chunk @shortdesc Closes a previously opened sub-chunk. Closes a sub-chunk of a file, previously obtained by calling pack_fopen_chunk(). @retval 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). @@LZSS_PACK_DATA *@create_lzss_pack_data(void); @xref free_lzss_pack_data @shortdesc Creates an LZSS structure for compression. Creates an LZSS_PACK_DATA structure, which can be used for LZSS compression with PACKFILEs. @retval Returns a pointer to the structure, or NULL if there was an error. @@void @free_lzss_pack_data(LZSS_PACK_DATA *dat); @xref create_lzss_pack_data @shortdesc Frees an LZSS structure. Frees an LZSS_PACK_DATA structure created with create_lzss_pack_data(). @\int @lzss_write(PACKFILE *file, LZSS_PACK_DATA *dat, int size, @@ unsigned char *buf, int last); @xref create_lzss_pack_data, free_lzss_pack_data @shortdesc Compresses data using LZSS. Packs `size' bytes from `buf', using the pack information contained in `dat'. The compressed bytes will be stored in `file'. @retval Returns 0 on success, or EOF if there was an error. @@LZSS_UNPACK_DATA *@create_lzss_unpack_data(void); @xref free_lzss_unpack_data @shortdesc Creates an LZSS structure for decompression. Creates an LZSS_UNPACK_DATA structure, which can be used for LZSS decompression reading PACKFILEs. @retval Returns a pointer to the structure, or NULL if there was an error. @@void @free_lzss_unpack_data(LZSS_UNPACK_DATA *dat); @xref create_lzss_unpack_data @shortdesc Frees an LZSS structure. Frees an LZSS_UNPACK_DATA structure created with create_lzss_pack_data. @\int @lzss_read(PACKFILE *file, LZSS_UNPACK_DATA *dat, int s, @@ unsigned char *buf); @xref free_lzss_unpack_data @shortdesc Decompresses data using LZSS. Unpacks from `dat' into `buf', until either EOF is reached or `s' bytes have been extracted from `file'. @retval Returns the number of bytes added to the buffer `buf'. @heading Datafile routines Datafiles are created by the grabber utility (see grabber.txt for more information), and have a `.dat' extension. They can contain bitmaps, palettes, fonts, samples, MIDI music, FLI/FLC animations, and any other binary data that you import. You could distribute your bitmaps and samples in a myriad of separate files, but packing them in a few `.dat' binaries has a few advantages:
  • On some platforms loading a single big datafile at once is faster than loading individual resources one by one.
  • 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.
  • 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!
  • 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.
  • 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!
  • 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.
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. @@DATAFILE *@load_datafile(const char *filename); @xref load_datafile_callback, unload_datafile, load_datafile_object @xref set_color_conversion, fixup_datafile, packfile_password @xref find_datafile_object, register_datafile_object @xref Using datafiles @eref excustom, exdata, exexedat, exgui, exsprite, exunicod @shortdesc Loads a datafile into memory. 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: /* 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); @retval Returns a pointer to the DATAFILE, or NULL on error. Remember to free this DATAFILE later to avoid memory leaks. @\DATAFILE *@load_datafile_callback(const char *filename, @@ void (*callback)(DATAFILE *d)); @xref load_datafile, unload_datafile, load_datafile_object @xref set_color_conversion, fixup_datafile, packfile_password @xref find_datafile_object, register_datafile_object @shortdesc Loads a datafile into memory, calling a hook per object. 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: 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); @retval Returns a pointer to the DATAFILE or NULL on error. Remember to free this DATAFILE later to avoid memory leaks. @@void @unload_datafile(DATAFILE *dat); @xref load_datafile @eref excustom, exdata, exexedat, exgui, exsprite, exunicod @shortdesc Frees all the objects in a datafile. Frees all the objects in a datafile. Use this to avoid memory leaks in your program. @\DATAFILE *@load_datafile_object(const char *filename, @@ const char *objectname); @xref unload_datafile_object, load_datafile, set_color_conversion @xref find_datafile_object, register_datafile_object @xref Using datafiles @shortdesc Loads a specific object from a datafile. 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: /* Load only the music from the datafile. */ music_object = load_datafile_object("datafile.dat", "MUSIC"); /* Play it and wait a moment for it. */ play_midi(music_object->dat); ... /* Destroy unneeded music. */ unload_datafile_object(music_object); @retval 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! @@void @unload_datafile_object(DATAFILE *dat); @xref load_datafile_object @shortdesc Frees an object previously loaded by load_datafile_object(). Frees an object previously loaded by load_datafile_object(). Use this to avoid memory leaks in your program. @@DATAFILE *@find_datafile_object(const DATAFILE *dat, const char *objectname); @xref load_datafile, load_datafile_object @shortdesc Searches a datafile for an object with a name. 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: 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!"); @retval Returns a pointer to a single DATAFILE element whose `dat' member points to the object, or NULL if the object could not be found. @@const char *@get_datafile_property(const DATAFILE *dat, int type); @xref Using datafiles, DAT_ID, empty_string @shortdesc Returns the property string for the object. Finds the property type of a DATAFILE object. The type parameter must be a value created with the DAT_ID() macro. Example: const char *name; ... name = get_datafile_property(game_data, DAT_ID('N','A','M','E')); if (name == empty_string) abort_on_error("Object doesn't have a name!"); @retval Returns a pointer to the text string for the object, or a pointer to the variable empty_string if the property isn't present. @\void @register_datafile_object(int id, void *(*load)(PACKFILE *f, long size), @@ void (*destroy)(void *data)); @xref load_datafile, load_datafile_object, DAT_ID @xref Custom datafile objects @shortdesc Registers load/destroy functions for custom object types. Used to add custom object types, specifying functions to load and destroy objects of this type. @@void @fixup_datafile(DATAFILE *data); @xref set_gfx_mode, set_color_conversion, Differences between platforms @shortdesc Fixes truecolor images in compiled datafiles. If you are using compiled datafiles (produced by the dat2s and dat2c utilities) on a platform that doesn't support constructors (currently any non GCC-based platform), or if the datafiles contain truecolor images, you must call this function once after your set the video mode that you will be using. This will ensure the datafiles are properly initialised in the first case and convert the color values into the appropriate format in the second case. It handles flipping between RGB and BGR formats, and converting between different color depths whenever that can be done without changing the size of the image (ie. changing 15<->16-bit hicolor for both bitmaps and RLE sprites, and 24<->32-bit truecolor for RLE sprites). Note that you can only call this once and expect it to work correctly, because after the call the DATAFILE you fixed up is permanently converted to whatever is the current component ordering for your screen mode. If you call fixup_datafile again, the function assumes you have a freshly loaded datafile. It cannot "undo" the previous conversion. If your program supports changing resolution and/or color depth during runtime, you have two choices: either call fixup_datafile() just once and hope that the component ordering and bit depth doesn't change when the screen mode changes (unlikely). Or, you can reload your datafiles when the screen mode changes. @@Macro @DAT_ID(a, b, c, d); @xref register_datafile_object, get_datafile_property @xref Custom datafile objects, Using datafiles @shortdesc Makes an ID value from four letters. 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: get_datafile_property(datob, DAT_ID('N','A','M','E')); @hnode Using datafiles 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: #define SOME_DATA 0 /* DATA */ #define SOME_MORE_DATA 1 /* DATA */ 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: DATAFILE *load_datafile(char *filename); 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: void unload_datafile(DATAFILE *dat); When you load a datafile, you will obtain a pointer to an array of DATAFILE structures: 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; 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: #include "myfile.h" void show_the_bitmap() { DATAFILE *dat; BITMAP *bmp; dat = load_datafile("myfile.dat"); if (!dat) { /* report an error! */ return; } bmp = (BITMAP *)dat[COOL_PICTURE].dat; blit(bmp, screen, 0, 0, 0, 0, bmp->w, bmp->h); unload_datafile(dat); } 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: "FILE" - NESTED_FILE |- "BMP" - A_BITMAP |- "FONT" - A_FONT "DATA" - SOME_DATA "DATA" - SOME_MORE_DATA Will produce the header: #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 */ 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: DATAFILE *dat = load_datafile("whatever.dat"); DATAFILE *nested = (DATAFILE *)dat[NESTED_FILE].dat; FONT *thefont = (FONT *)nested[NESTED_FILE_A_FONT].dat; If you need to access object property strings from within your program, you can use the function: char *get_datafile_property(DATAFILE *dat, int type); 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: 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... */ If you prefer to access objects by name rather than index number, you can use the function: DATAFILE *find_datafile_object(DATAFILE *dat, char *objectname); 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: DATAFILE *load_datafile_object(char *filename, char *objectname); 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: void unload_datafile_object(DATAFILE *dat); Example: music_object = load_datafile_object("datafile.dat", "MUSIC"); play_midi(music_object->dat); ... unload_datafile_object(music_object); 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(). @hnode Custom datafile objects 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: #define DAT_MAPDATA DAT_ID('M','A','P','D') You then need to write functions for loading and destroying objects of this type, in the form: void *load_mapdata(PACKFILE *f, long size) { /* Allegro will call this function whenever an object of your custom * type needs to be loaded from a datafile. It will be passed a * pointer to the file from which the data is to be read, and the size * of the object in bytes. It should return a pointer to the loaded * data, which will be stored in the dat field of the datafile object * structure, or NULL if an error occurs. The file will have been * opened as a sub-chunk of the main datafile, so it is safe to read * past the end of the object (if you attempt this, Allegro will * return EOF), and it is also safe to return before reading all the * data in the chunk (if you do this, Allegro will skip any unused * bytes before starting to read the next object). You should _not_ * close the file when you are done: this will be handled by the * calling function. To clarify how all this works, here's an example * implementation of a null-terminated string object: */ #define MAX_LEN 256 char buf[MAX_LEN]; char *p; int i, c; for (i=0; i<MAX_LEN-1; i++) { if ((c = pack_getc(f)) == EOF) break; buf[i] = c; } buf[i] = 0; p = malloc(i+1); strcpy(p, buf); return p; } void destroy_mapdata(void *data) { /* Allegro will call this function whenever an object of your custom * type needs to be destroyed. It will be passed a pointer to the * object (as returned by the load function), and should free whatever * memory the object is using. For example, the simple string object * returned by the above loader could be destroyed with the code: */ if (data) free(data); } Finally, before you load your datafile you must tell Allegro about the custom format, by calling: register_datafile_object(DAT_MAPDATA, load_mapdata, destroy_mapdata); 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. @heading Fixed point math routines Allegro provides some routines for working with fixed point numbers, and defines the type `fixed' to be a signed 32-bit integer. The high word is used for the integer part and the low word for the fraction, giving a range of -32768 to 32767 and an accuracy of about four or five decimal places. Fixed point numbers can be assigned, compared, added, subtracted, negated and shifted (for multiplying or dividing by powers of two) using the normal integer operators, but you should take care to use the appropriate conversion routines when mixing fixed point with integer or floating point values. Writing `fixed_point_1 + fixed_point_2' is OK, but `fixed_point + integer' is not. Unfortunately the only advantage of fixed point math routines is that you don't require a floating point coprocessor to use them. This was great in the time period of i386 and i486 machines, but stopped being so useful with the coming of the Pentium class of processors. From Pentium onwards, CPUs have increased their strength in floating point operations, equaling or even surpassing integer math performance. Depending on the type of operations your program may need, using floating point types may be faster than fixed types if you are targeting a specific machine class. Allegro comes with a test program in the `allegro/tests' directory. Its `Misc' menu contains a basic profile test which can give you an idea of the speed difference between fixed and float types for a few basic operations on your machine. However, don't forget to profile your program in real life conditions, tight loop benchmarks are after all artificial. Fixed point math is considered "add-on" material and is kept only for backwards compatibility. Whenever a future release of Allegro breaks backwards compatibility, fixed point math will likely be moved to a separate add-on package for the very few users who still find it convenient and useful, and Allegro functions using fixed point math will use other types. @@fixed @itofix(int x); @xref fixtoi, ftofix, fixtof @eref ex12bit, ex3buf, ex3d, exblend, excustom, exfixed, exlights @eref exspline, exsprite, exstars @shortdesc Converts an integer to fixed point. Converts an integer to fixed point. This is the same thing as x<<16. Remember that overflows (trying to convert an integer greater than 32767) and underflows (trying to convert an integer lesser than -32768) are not detected even in debug builds! The values simply "wrap around". Example: 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); @retval Returns the value of the integer converted to fixed point ignoring overflows. @@int @fixtoi(fixed x); @xref itofix, ftofix, fixtof, fixfloor, fixceil @eref ex12bit, ex3buf, ex3d, exblend, excustom, exlights, exspline @eref exstars, exupdate @shortdesc Converts a fixed point to integer with rounding. Converts fixed point to integer, rounding as required to the nearest integer. Example: int result; /* This will put 33 into `result'. */ result = fixtoi(itofix(100) / 3); /* But this will round up to 17. */ result = fixtoi(itofix(100) / 6); @@int @fixfloor(fixed x); @xref fixtoi, fixceil @shortdesc Returns the greatest integer not greater than x. Returns the greatest integer not greater than x. That is, it rounds towards negative infinity. Example: int result; /* This will put 33 into `result'. */ result = fixfloor(itofix(100) / 3); /* And this will round down to 16. */ result = fixfloor(itofix(100) / 6); @@int @fixceil(fixed x); @xref fixtoi, fixfloor @shortdesc Returns the smallest integer not less than x. Returns the smallest integer not less than x. That is, it rounds towards positive infinity. Example: int result; /* This will put 34 into `result'. */ result = fixceil(itofix(100) / 3); /* This will round up to 17. */ result = fixceil(itofix(100) / 6); @@fixed @ftofix(double x); @xref fixtof, itofix, fixtoi @eref exfixed, exspline, exupdate @shortdesc Converts a floating point value to fixed point. 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: fixed number; number = itofix(-40000); ASSERT(fixfloor(number) == -32768); number = itofix(64000); ASSERT(fixfloor(number) == 32767); ASSERT(!errno); /* This will fail. */ @retval Returns the value of the floating point value converted to fixed point clamping overflows (and setting `errno'). @@double @fixtof(fixed x); @xref ftofix, itofix, fixtoi @eref exfixed, exspline, exstars @shortdesc Converts a fixed point to floating point. Converts fixed point to floating point. Example: float result; /* This will put 33.33333 into `result'. */ result = fixtof(itofix(100) / 3); /* This will put 16.66666 into `result'. */ result = fixtof(itofix(100) / 6); @@fixed @fixmul(fixed x, fixed y); @xref fixadd, fixsub, fixdiv @eref ex3buf, excustom, exfixed, exspline, exstars, exupdate @shortdesc Multiplies two fixed point values together. 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: 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); @retval Returns the clamped result of multiplying `x' by `y', setting `errno' to ERANGE if there was an overflow. @@fixed @fixdiv(fixed x, fixed y); @xref fixadd, fixsub, fixmul @eref exfixed @shortdesc Fixed point division. 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: 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. */ @retval Returns the result of dividing `x' by `y'. If `y' is zero, returns the maximum possible fixed point value and sets `errno' to ERANGE. @@fixed @fixadd(fixed x, fixed y); @xref fixsub, fixmul, fixdiv @shortdesc Safe function to add fixed point numbers clamping overflow. 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: 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. */ @retval Returns the clamped result of adding `x' to `y', setting `errno' to ERANGE if there was an overflow. @@fixed @fixsub(fixed x, fixed y); @xref fixadd, fixmul, fixdiv @shortdesc Safe function to subtract fixed point numbers clamping underflow. 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: 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. */ @retval Returns the clamped result of subtracting `y' from `x', setting `errno' to ERANGE if there was an overflow. @hnode Fixed point trig 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 >= 360)' checks. @@extern const fixed @fixtorad_r; @xref fixmul, radtofix_r @shortdesc Constant to convert angles in fixed point format to radians. 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: 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); @@extern const fixed @radtofix_r; @xref fixmul, fixtorad_r @shortdesc Constant to convert radians to fixed point angles. 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: fixed rad_angle, binary_angle; ... binary_angle = fixmul(rad_angle, radtofix_r); @@fixed @fixsin(fixed x); @xref Fixed point trig @eref ex12bit, ex3buf, exblend, excustom, exspline, exupdate @shortdesc Fixed point sine of binary angles. This function finds the sine of a value using a lookup table. The input value must be a fixed point binary angle. Example: fixed angle; int result; /* Set the binary angle to 90 degrees. */ angle = itofix(64); /* The sine of 90 degrees is one. */ result = fixtoi(fixsin(angle)); ASSERT(result == 1); @retval Returns the sine of a fixed point binary format angle. The return value will be in radians. @@fixed @fixcos(fixed x); @xref Fixed point trig @eref ex12bit, ex3buf, exblend, excustom, exspline, exupdate @shortdesc Fixed point cosine of binary angles. This function finds the cosine of a value using a lookup table. The input value must be a fixed point binary angle. Example: fixed angle; float result; /* Set the binary angle to 45 degrees. */ angle = itofix(32); /* The cosine of 45 degrees is about 0.7071. */ result = fixtof(fixcos(angle)); ASSERT(result > 0.7 && result < 0.71); @retval Returns the cosine of a fixed point binary format angle. The return value will be in radians. @@fixed @fixtan(fixed x); @xref Fixed point trig @shortdesc Fixed point tangent of binary angles. This function finds the tangent of a value using a lookup table. The input value must be a fixed point binary angle. Example: fixed angle, res_a, res_b; float dif; angle = itofix(37); /* Prove that tan(angle) == sin(angle) / cos(angle). */ res_a = fixdiv(fixsin(angle), fixcos(angle)); res_b = fixtan(angle); dif = fixtof(fixsub(res_a, res_b)); allegro_message("Precision error: %f\n", dif); @retval Returns the tangent of a fixed point binary format angle. The return value will be in radians. @@fixed @fixasin(fixed x); @xref Fixed point trig @shortdesc Fixed point inverse sine lookup table. 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: 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); @retval 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'. @@fixed @fixacos(fixed x); @xref Fixed point trig @shortdesc Fixed point inverse cosine lookup table. 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: fixed result; /* Sets `result' to binary angle 128. */ result = fixacos(itofix(-1)); @retval 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'. @@fixed @fixatan(fixed x); @xref Fixed point trig @shortdesc Fixed point inverse tangent lookup table. 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: fixed result; /* Sets `result' to binary angle 13. */ result = fixatan(ftofix(0.326)); @retval Returns the inverse tangent of a fixed point value, measured as a fixed point binary format angle. @@fixed @fixatan2(fixed y, fixed x); @xref Fixed point trig @eref exlights, exspline @shortdesc Fixed point version of the libc atan2() routine. 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: 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); @retval 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. @@fixed @fixsqrt(fixed x); @xref Fixed point trig @eref exfixed, exlights, exspline @shortdesc Fixed point square root. This finds out the non negative square root of `x'. If `x' is negative, `errno' is set to EDOM and the function returns zero. @@fixed @fixhypot(fixed x, fixed y); @xref Fixed point trig @shortdesc Fixed point hypotenuse. 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. @hnode Fix class 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. @heading 3D math routines Allegro contains some 3d helper functions for manipulating vectors, constructing and using transformation matrices, and doing perspective projections from 3d space onto the screen. It is not, and never will be, a fully fledged 3d library (the goal is to supply generic support routines, not shrink-wrapped graphics code :-) but these functions may be useful for developing your own 3d code. Allegro uses a right-handed coordinate system, i.e. if you point the thumb of your right hand along the x axis, and the index finger along the y axis, your middle finger points in the direction of the z axis. Allegro's world coordinate system typically has the positive x axis right, the positive y axis up, and the positive z axis out of the screen. What all this means is this: Assume, the viewer is located at the origin (0/0/0) in world space, looks along the negative z axis (0/0/-1), and is oriented so up is along the positive y axis (0/1/0). Then something located at (100/200/-300) will be 100 to the right, 200 above, and 300 in front of the viewer. Just like in OpenGL. (Of course, both OpenGL and Allegro allow to use a different system.) Here's a short piece of code demonstrating the transformation pipeline of a point from world space to the screen. /* First, set up the projection viewport. */ set_projection_viewport (0, 0, SCREEN_W, SCREEN_H); /* Next, get a camera matrix, depending on the * current viewer position and orientation. */ get_camera_matrix_f (&m, 0, 0, 0, /* Viewer position, in this case, 0/0/0. */ 0, 0, -1, /* Viewer direction, in this case along negative z. */ 0, 1, 0, /* Up vector, in this case positive y. */ 32, /* The FOV, here 45°. */ (float)SCREEN_W / (float)SCREEN_H)); /* Aspect ratio. */ /* Applying the matrix transforms the point 100/200/-300 * from world space into camera space. The transformation * moves and rotates the point so it is relative to the * camera, scales it according to the FOV and aspect * parameters, and also flips up and front direction - * ready to project the point to the viewport. */ apply_matrix_f (&m, 100, 200, -300, &x, &y, &z); /* Finally, the point is projected from * camera space to the screen. */ persp_project_f (cx, cy, cz, &sx, &sy); 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: ( a, b, c, d ) ( e, f, g, h ) ( i, j, k, l ) ( m, n, o, p ) a pattern can be observed in which parts of it do what. The top left 3x3 grid implements rotation and scaling. The three values in the top right column (d, h, and l) implement translation, and as long as the matrix is only used for affine transformations, m, n and o will always be zero and p will always be 1. If you don't know what affine means, read Foley & Van Damme: basically it covers scaling, translation, and rotation, but not projection. Since Allegro uses a separate function for projection, the matrix functions only need to support affine transformations, which means that there is no need to store the bottom row of the matrix. Allegro implicitly assumes that it contains (0,0,0,1), and optimises the matrix manipulation functions accordingly. Read chapter "Structures and types defined by Allegro" for an internal view of the MATRIX/_f structures. @@extern MATRIX @identity_matrix; @@extern MATRIX_f @identity_matrix_f; @shortdesc Global containing the identity matrix. Global variables containing the 'do nothing' identity matrix. Multiplying by the identity matrix has no effect. @@void @get_translation_matrix(MATRIX *m, fixed x, fixed y, fixed z); @@void @get_translation_matrix_f(MATRIX_f *m, float x, float y, float z); @xref apply_matrix, get_transformation_matrix, qtranslate_matrix @eref exstars @shortdesc Constructs a translation matrix. 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. @@void @get_scaling_matrix(MATRIX *m, fixed x, fixed y, fixed z); @@void @get_scaling_matrix_f(MATRIX_f *m, float x, float y, float z); @xref apply_matrix, get_transformation_matrix, qscale_matrix @shortdesc Constructs a scaling matrix. 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. @@void @get_x_rotate_matrix(MATRIX *m, fixed r); @@void @get_x_rotate_matrix_f(MATRIX_f *m, float r); @xref apply_matrix, get_rotation_matrix, get_y_rotate_matrix @xref get_z_rotate_matrix @shortdesc Construct X axis rotation matrices. 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). @@void @get_y_rotate_matrix(MATRIX *m, fixed r); @@void @get_y_rotate_matrix_f(MATRIX_f *m, float r); @xref apply_matrix, get_rotation_matrix, get_x_rotate_matrix @xref get_z_rotate_matrix @shortdesc Construct Y axis rotation matrices. 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). @@void @get_z_rotate_matrix(MATRIX *m, fixed r); @@void @get_z_rotate_matrix_f(MATRIX_f *m, float r); @xref apply_matrix, get_rotation_matrix, get_x_rotate_matrix @xref get_y_rotate_matrix @shortdesc Construct Z axis rotation matrices. 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). @@void @get_rotation_matrix(MATRIX *m, fixed x, fixed y, fixed z); @@void @get_rotation_matrix_f(MATRIX_f *m, float x, float y, float z); @xref apply_matrix, get_transformation_matrix, get_vector_rotation_matrix @xref get_x_rotate_matrix, get_y_rotate_matrix, get_z_rotate_matrix @xref get_align_matrix @eref ex12bit, exquat, exstars @shortdesc Constructs X, Y, Z rotation matrices. 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. @\void @get_align_matrix(MATRIX *m, fixed xfront, yfront, zfront, @@ fixed xup, fixed yup, fixed zup); @xref apply_matrix, get_camera_matrix @shortdesc Rotates a matrix to align it along specified coordinate vectors. 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. @\void @get_align_matrix_f(MATRIX *m, float xfront, yfront, zfront, @@ float xup, yup, zup); @xref get_align_matrix @shortdesc Floating point version of get_align_matrix(). Floating point version of get_align_matrix(). @@void @get_vector_rotation_matrix(MATRIX *m, fixed x, y, z, fixed a); @@void @get_vector_rotation_matrix_f(MATRIX_f *m, float x, y, z, float a); @xref apply_matrix, get_rotation_matrix, get_align_matrix @eref excamera @shortdesc Constructs X, Y, Z rotation matrices with an angle. 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). @\void @get_transformation_matrix(MATRIX *m, fixed scale, @@ fixed xrot, yrot, zrot, x, y, z); @xref apply_matrix, get_rotation_matrix, get_scaling_matrix @xref get_translation_matrix @eref ex3d, exstars @shortdesc Constructs X, Y, Z rotation matrices with an angle and scaling. 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. @\void @get_transformation_matrix_f(MATRIX_f *m, float scale, @@ float xrot, yrot, zrot, x, y, z); @xref get_transformation_matrix @eref exzbuf @shortdesc Floating point version of get_transformation_matrix(). Floating point version of get_transformation_matrix(). @\void @get_camera_matrix(MATRIX *m, fixed x, y, z, xfront, yfront, zfront, @@ fixed xup, yup, zup, fov, aspect); @xref apply_matrix, get_align_matrix, set_projection_viewport, persp_project @shortdesc Constructs a camera matrix for perspective projection. 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. @\void @get_camera_matrix_f(MATRIX_f *m, float x, y, z, xfront, yfront, zfront, @@ float xup, yup, zup, fov, aspect); @xref get_camera_matrix @eref excamera, exquat @shortdesc Floating point version of get_camera_matrix(). Floating point version of get_camera_matrix(). @@void @qtranslate_matrix(MATRIX *m, fixed x, fixed y, fixed z); @@void @qtranslate_matrix_f(MATRIX_f *m, float x, float y, float z); @xref get_translation_matrix @shortdesc Optimised routine for translating an already generated matrix. 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. @@void @qscale_matrix(MATRIX *m, fixed scale); @@void @qscale_matrix_f(MATRIX_f *m, float scale); @xref get_scaling_matrix @shortdesc Optimised routine for scaling an already generated matrix. 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. @@void @matrix_mul(const MATRIX *m1, const MATRIX *m2, MATRIX *out); @@void @matrix_mul_f(const MATRIX_f *m1, const MATRIX_f *m2, MATRIX_f *out); @xref apply_matrix @eref exquat, exscn3d @shortdesc Multiplies two matrices. 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). @@fixed @vector_length(fixed x, fixed y, fixed z); @@float @vector_length_f(float x, float y, float z); @xref normalize_vector @shortdesc Calculates the length of a vector. Calculates the length of the vector (x, y, z), using that good 'ole Pythagoras theorem. @@void @normalize_vector(fixed *x, fixed *y, fixed *z); @@void @normalize_vector_f(float *x, float *y, float *z); @xref vector_length, dot_product, cross_product @eref exstars @shortdesc Converts the vector to a unit vector. 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. @@fixed @dot_product(fixed x1, y1, z1, x2, y2, z2); @@float @dot_product_f(float x1, y1, z1, x2, y2, z2); @xref cross_product, normalize_vector @eref exstars @shortdesc Calculates the dot product. Calculates the dot product (x1, y1, z1) . (x2, y2, z2), returning the result. @@void @cross_product(fixed x1, y1, z1, x2, y2, z2, *xout, *yout, *zout); @@void @cross_product_f(float x1, y1, z1, x2, y2, z2, *xout, *yout, *zout); @xref dot_product, polygon_z_normal, normalize_vector @eref exstars @shortdesc Calculates the cross product. 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. @@fixed @polygon_z_normal(const V3D *v1, const V3D *v2, const V3D *v3); @@float @polygon_z_normal_f(const V3D_f *v1, const V3D_f *v2, const V3D_f *v3); @xref cross_product @eref ex3d @shortdesc Finds the Z component of the normal vector to three vertices. 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. @@void @apply_matrix(const MATRIX *m, fixed x, y, z, *xout, *yout, *zout); @@void @apply_matrix_f(const MATRIX_f *m, float x, y, z, *xout, *yout, *zout); @xref matrix_mul @eref ex12bit, ex3d, exstars @shortdesc Multiplies a point by a transformation matrix. Multiplies the point (x, y, z) by the transformation matrix m, storing the result in (*xout, *yout, *zout). @@void @set_projection_viewport(int x, int y, int w, int h); @xref persp_project, get_camera_matrix @eref ex3d, excamera, exquat, exscn3d, exstars, exzbuf @shortdesc Sets the viewport used to scale the output of persp_project(). 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. @@void @persp_project(fixed x, fixed y, fixed z, fixed *xout, fixed *yout); @@void @persp_project_f(float x, float y, float z, float *xout, float *yout); @xref set_projection_viewport, get_camera_matrix @eref ex3d, exstars @shortdesc Projects a 3d point into 2d screen space. 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. @heading Quaternion math routines Quaternions are an alternate way to represent the rotation part of a transformation, and can be easier to manipulate than matrices. As with a matrix, you can encode a geometric transformations in one, concatenate several of them to merge multiple transformations, and apply them to a vector, but they can only store pure rotations. The big advantage is that you can accurately interpolate between two quaternions to get a part-way rotation, avoiding the gimbal problems of the more conventional euler angle interpolation. Quaternions only have floating point versions, without any _f suffix. Other than that, most of the quaternion functions correspond with a matrix function that performs a similar operation. Quaternion means 'of four parts', and that's exactly what it is. Here is the structure: typedef struct QUAT { float w, x, y, z; } 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. @@extern QUAT @identity_quat; @shortdesc Global variable containing the identity quaternion. Global variable containing the 'do nothing' identity quaternion. Multiplying by the identity quaternion has no effect. @@void @get_x_rotate_quat(QUAT *q, float r); @@void @get_y_rotate_quat(QUAT *q, float r); @@void @get_z_rotate_quat(QUAT *q, float r); @shortdesc Construct axis rotation quaternions. 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). @@void @get_rotation_quat(QUAT *q, float x, float y, float z); @eref exquat @shortdesc Constructs a quaternion to rotate points around all three axes. Constructs a quaternion that will rotate points around all three axes by the specified amounts (given in binary, 256 degrees to a circle format). @@void @get_vector_rotation_quat(QUAT *q, float x, y, z, float a); @shortdesc Constructs a quaternion to rotate points around a vector. 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). @@void @quat_to_matrix(const QUAT *q, MATRIX_f *m); @eref exquat @shortdesc Constructs a rotation matrix from a quaternion. Constructs a rotation matrix from a quaternion. @@void @matrix_to_quat(const MATRIX_f *m, QUAT *q); @shortdesc Constructs a quaternion from a rotation matrix. 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. @@void @quat_mul(const QUAT *p, const QUAT *q, QUAT *out); @shortdesc Multiplies two quaternions. 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). @@void @apply_quat(const QUAT *q, float x, y, z, *xout, *yout, *zout); @shortdesc Multiplies a point by a quaternion. 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(). @@void @quat_interpolate(const QUAT *from, const QUAT *to, float t, QUAT *out); @eref exquat @shortdesc Constructs a quaternion representing a rotation between from and to. 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. @@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. 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: 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 @heading GUI routines Allegro contains an object-oriented dialog manager, which was originally based on the Atari GEM system (form_do(), objc_draw(), etc: old ST programmers will know what we are talking about :-) You can use the GUI as-is to knock out simple interfaces for things like the test program and grabber utility, or you can use it as a basis for more complicated systems of your own. Allegro lets you define your own object types by writing new dialog procedures, so you can take complete control over the visual aspects of the interface while still using Allegro to handle input from the mouse, keyboard, joystick, etc. A GUI dialog is stored as an array of DIALOG objects, read chapter "Structures and types defined by Allegro" for an internal description of the DIALOG structure. The array should end with an object which has the proc pointer set to NULL. Each object has a flags field which may contain any combination of the bit flags: 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 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: int foo(int msg, DIALOG *d, int c); 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: 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 Dialog procedures may be called with any of the messages: MSG_START:
Tells the object to initialise itself. The dialog manager sends this to all the objects in a dialog just before it displays the dialog. MSG_END:
Sent to all objects when closing a dialog, allowing them to perform whatever cleanup operations they require. MSG_DRAW:
Tells the object to draw itself onto the screen. The mouse pointer will be turned off when this message is sent, so the drawing code does not need to worry about it. MSG_CLICK:
Informs the object that a mouse button has been clicked while the mouse was on top of the object. Typically an object will perform its own mouse tracking as long as the button is held down, and only return from this message handler when it is released. If you process this message, use the functions gui_mouse_*() to read the state of the mouse. MSG_DCLICK:
Sent when the user double-clicks on an object. A MSG_CLICK will be sent when the button is first pressed, then MSG_DCLICK if it is released and pressed again within a short space of time. If you process this message, use the functions gui_mouse_*() to read the state of the mouse. MSG_KEY:
Sent when the keyboard shortcut for the object is pressed, or if enter, space, or a joystick button is pressed while it has the input focus. MSG_CHAR:
When a key is pressed, this message is sent to the object that has the input focus, with a readkey() format character code (ASCII value in the low byte, scancode in the high byte) as the c parameter. If the object deals with the keypress it should return D_USED_CHAR, otherwise it should return D_O_K to allow the default keyboard interface to operate. If you need to access Unicode character input, you should use MSG_UCHAR instead of MSG_CHAR. MSG_UCHAR:
If an object ignores the MSG_CHAR input, this message will be sent immediately after it, passed the full Unicode key value as the c parameter. This enables you to read character codes greater than 255, but cannot tell you anything about the scancode: if you need to know that, use MSG_CHAR instead. This handler should return D_USED_CHAR if it processed the input, or D_O_K otherwise. MSG_XCHAR:
When a key is pressed, Allegro will send a MSG_CHAR and MSG_UCHAR to the object with the input focus. If this object doesn't process the key (ie. it returns D_O_K rather than D_USED_CHAR), the dialog manager will look for an object with a matching keyboard shortcut in the key field, and send it a MSG_KEY. If this fails, it broadcasts a MSG_XCHAR to all objects in the dialog, allowing them to respond to special keypresses even when they don't have the input focus. Normally you should ignore this message (return D_O_K rather than D_USED_CHAR), in which case Allegro will perform default actions such as moving the focus in response to the arrow keys and closing the dialog if ESC is pressed. MSG_WANTFOCUS:
Queries whether an object is willing to accept the input focus. It should return D_WANTFOCUS if it does, or D_O_K if it isn't interested in getting user input. MSG_GOTFOCUS:
MSG_LOSTFOCUS:
Sent whenever an object gains or loses the input focus. These messages will always be followed by a MSG_DRAW, to let objects display themselves differently when they have the input focus. If you return D_WANTFOCUS in response to a MSG_LOSTFOCUS event, this will prevent your object from losing the focus when the mouse moves off it onto the screen background or some inert object, so it will only lose the input focus when some other object is ready to take over the focus (this trick is used by the d_edit_proc() object). MSG_GOTMOUSE:
MSG_LOSTMOUSE:
Sent when the mouse moves on top of or away from an object. Unlike the focus messages, these are not followed by a MSG_DRAW, so if the object is displayed differently when the mouse is on top of it, it is responsible for redrawing itself in response to these messages. MSG_IDLE:
Sent whenever the dialog manager has nothing better to do. MSG_RADIO:
Sent by radio button objects to deselect other buttons in the same group when they are clicked. The group number is passed in the c message parameter. MSG_WHEEL:
Sent to the focused object whenever the mouse wheel moves. The c message parameter contains the number of clicks. MSG_LPRESS, MSG_MPRESS, MSG_RPRESS:
Sent when the corresponding mouse button is pressed. MSG_LRELEASE, MSG_MRELEASE, MSG_RRELEASE:
Sent when the corresponding mouse button is released. MSG_USER:
The first free message value. Any numbers from here on (MSG_USER, MSG_USER+1, MSG_USER+2, ... MSG_USER+n) are free to use for whatever you like. Allegro provides several standard dialog procedures. You can use these as they are to provide simple user interface objects, or you can call them from within your own dialog procedures, resulting in a kind of OOP inheritance. For instance, you could make an object which calls d_button_proc to draw itself, but handles the click message in a different way, or an object which calls d_button_proc for everything except drawing itself, so it would behave like a normal button but could look completely different. Since the release of Allegro version 3.9.33 (CVS), some GUI objects and menus are being drawn differently unlike in previous Allegro versions. The changes are the following:
  • Shadows under d_shadow_box_proc and d_button_proc are always black.
  • The most important (and immediately visible) change is, that some objects are being drawn smaller. The difference is exactly one pixel in both height and width, when comparing to previous versions. The reason is, that in previous versions these objects were too large on the screen - their size was d->w+1 and d->h+1 pixels (and not d->w and d->h, as it should be). This change affects the following objects : 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. 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.
  • 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.

Menus had been forgotten during the changes for 3.9.33 (CVS), so they were still drawn too large until version 4.1.0. @@int @d_clear_proc(int msg, DIALOG *d, int c); @eref excustom, exgui @shortdesc Dialog procedure to clear the screen. This just clears the screen when it is drawn. Useful as the first object in a dialog. @@int @d_box_proc(int msg, DIALOG *d, int c); @@int @d_shadow_box_proc(int msg, DIALOG *d, int c); @eref exgui, exrgbhsv @shortdesc Dialog procedure drawing boxes onto the screen. These draw boxes onto the screen, with or without a shadow. @@int @d_bitmap_proc(int msg, DIALOG *d, int c); @eref exgui, exrgbhsv @shortdesc Dialog procedure drawing a bitmap. This draws a bitmap onto the screen, which should be pointed to by the dp field. @@int @d_text_proc(int msg, DIALOG *d, int c); @@int @d_ctext_proc(int msg, DIALOG *d, int c); @@int @d_rtext_proc(int msg, DIALOG *d, int c); @eref exgui, exrgbhsv @shortdesc Dialogs procedure drawing text onto the screen. These draw text onto the screen. The dp field should point to the string to display. d_ctext_proc() centers the string horizontally, and d_rtext_proc() right aligns it. Any '&' characters in the string will be replaced with lines underneath the following character, for displaying keyboard shortcuts (as in MS Windows). To display a single ampersand, put "&&". To draw the text in something other than the default font, set the dp2 field to point to your custom font data. @@int @d_button_proc(int msg, DIALOG *d, int c); @eref excustom, exgui @shortdesc Dialog procedure implementing a button object. 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. @@int @d_check_proc(int msg, DIALOG *d, int c); @eref excustom, exgui @shortdesc Dialog procedure implementing a check box object. 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). @@int @d_radio_proc(int msg, DIALOG *d, int c); @eref exgui @shortdesc Dialog procedure implementing a radio button object. 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). @@int @d_icon_proc(int msg, DIALOG *d, int c); @eref exgui @shortdesc Dialog procedure implementing a bitmap button. 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). @@int @d_keyboard_proc(int msg, DIALOG *d, int c); @eref exgui @shortdesc Invisible dialog procedure for implementing keyboard shortcuts. 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. @@int @d_edit_proc(int msg, DIALOG *d, int c); @eref excustom, exgui @shortdesc Dialog procedure implementing an editable text object. 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. @@int @d_list_proc(int msg, DIALOG *d, int c); @eref exgui @shortdesc Dialog procedure implementing a list box object. 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: char *foobar(int index, int *list_size); 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! @@int @d_text_list_proc(int msg, DIALOG *d, int c); @eref exgui @shortdesc Dialog procedure implementing a list box object with type ahead. 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. @@int @d_textbox_proc(int msg, DIALOG *d, int c); @eref exgui @shortdesc Dialog procedure implementing a text box object. 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. @@int @d_slider_proc(int msg, DIALOG *d, int c); @eref exgui, exrgbhsv @shortdesc Dialog procedure implementing a slider control object. 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: int function(void *dp3, int d2); The d_slider_proc object will return the value of the callback function. @@int @d_menu_proc(int msg, DIALOG *d, int c); @xref GUI menus, active_menu, gui_menu_draw_menu @eref exgui @shortdesc Dialog procedure implementing a menu bar object. 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. @@int @d_yield_proc(int msg, DIALOG *d, int c); @xref rest @eref exgui @shortdesc Invisible dialog procedure that yields CPU timeslices. 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. @hnode GUI variables The behaviour of the dialog manager can be controlled by the following global variables. @@extern int @gui_mouse_focus; @shortdesc Tells if the input focus follows the mouse pointer. If set, the input focus follows the mouse pointer around the dialog, otherwise a click is required to move it. @@extern int @gui_fg_color; @@extern int @gui_bg_color; @xref gui_mg_color, set_dialog_color @eref exgui @shortdesc The foreground and background colors for the standard dialogs. The foreground and background colors for the standard dialogs (alerts, menus, and the file selector). They default to 255 and 0. @@extern int @gui_mg_color; @xref gui_fg_color, set_dialog_color @eref exgui @shortdesc The color used for displaying greyed-out dialog objects. The color used for displaying greyed-out dialog objects (with the D_DISABLED flag set). Defaults to 8. @@extern int @gui_font_baseline; @shortdesc Adjusts the keyboard shortcut underscores height. If set to a non-zero value, adjusts the keyboard shortcut underscores to account for the height of the descenders in your font. @@extern int (*@gui_mouse_x)(); @@extern int (*@gui_mouse_y)(); @@extern int (*@gui_mouse_z)(); @@extern int (*@gui_mouse_b)(); @shortdesc Hook functions used by the GUI routines to access the mouse state. 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. @hnode GUI font 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. @@int @gui_textout_ex(BITMAP *bmp, const char *s, int x, y, color, bg, centre); @xref gui_strlen @shortdesc Draws a text string onto the screen with keyboard shortcut underbars. Helper function for use by the GUI routines. Draws a text string onto the screen, interpreting the '&' character as an underbar for displaying keyboard shortcuts. Returns the width of the output string in pixels. @@int @gui_strlen(const char *s); @xref gui_textout_ex @shortdesc Returns the length of a string in pixels. Helper function for use by the GUI routines. Returns the length of a string in pixels, ignoring '&' characters. @@void @gui_set_screen(BITMAP *bmp); @xref gui_get_screen @shortdesc Changes the bitmap surface GUI routines draw to. 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: 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]); @@BITMAP *@gui_get_screen(void); @xref gui_set_screen @shortdesc Returns the bitmap surface GUI routines draw to. 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. @@void @position_dialog(DIALOG *dialog, int x, int y); @xref centre_dialog @eref exgui @shortdesc Moves an array of dialog objects to the specified position. Moves an array of dialog objects to the specified screen position (specified as the top left corner of the dialog). @@void @centre_dialog(DIALOG *dialog); @xref position_dialog, set_dialog_color @shortdesc Centers an array of dialog objects. Moves an array of dialog objects so that it is centered in the screen. @@void @set_dialog_color(DIALOG *dialog, int fg, int bg); @xref gui_fg_color, gui_mg_color, centre_dialog @eref exgui @shortdesc Sets the colors of an array of dialog objects. Sets the foreground and background colors of an array of dialog objects. @@int @find_dialog_focus(DIALOG *dialog); @xref do_dialog, init_dialog, offer_focus @shortdesc Searches the dialog for the object which has the input focus. 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)); @@int @offer_focus(DIALOG *dialog, int obj, int *focus_obj, int force); @xref find_dialog_focus @shortdesc Offers the input focus to a particular object. 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. @@int @object_message(DIALOG *dialog, int msg, int c); @xref dialog_message, scare_mouse, scare_mouse_area, unscare_mouse @eref excustom, exrgbhsv @shortdesc Sends a message to an object and returns the answer. 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: object_message(&dialog[1], MSG_DRAW, 0); The function will take care of scaring and unscaring the mouse if the message is MSG_DRAW. @@int @dialog_message(DIALOG *dialog, int msg, int c, int *obj); @xref object_message, broadcast_dialog_message @shortdesc Sends a message to all the objects in an array. 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. @@int @broadcast_dialog_message(int msg, int c); @xref dialog_message, active_dialog @shortdesc Broadcasts a message to all the objects in the active dialog. 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. @@int @do_dialog(DIALOG *dialog, int focus_obj); @xref popup_dialog, init_dialog, centre_dialog, set_dialog_color @xref find_dialog_focus @eref excustom, exgui, exrgbhsv @shortdesc Basic dialog manager function. 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. @@int @popup_dialog(DIALOG *dialog, int focus_obj); @xref do_dialog @shortdesc do_dialog() used for popup dialogs. 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. @@DIALOG_PLAYER *@init_dialog(DIALOG *dialog, int focus_obj); @xref update_dialog, shutdown_dialog, do_dialog @shortdesc Low level initialisation of a dialog. 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: DIALOG_PLAYER *player = init_dialog(dialog, focus_obj); while (update_dialog(player)) ; return shutdown_dialog(player); @@int @update_dialog(DIALOG_PLAYER *player); @xref init_dialog @shortdesc Low level function to update a dialog player. Updates the status of a dialog object returned by init_dialog(). Returns TRUE if the dialog is still active, or FALSE if it has terminated. Upon a return value of FALSE, it is up to you whether to call shutdown_dialog() or to continue execution. The object that requested the exit can be determined from the player->obj field. @@int @shutdown_dialog(DIALOG_PLAYER *player); @xref init_dialog @shortdesc Destroys a dialog player returned by init_dialog(). 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()). @@extern DIALOG *@active_dialog; @xref do_dialog, init_dialog, broadcast_dialog_message @shortdesc Global pointer to the most recent activated dialog. Global pointer to the most recent activated dialog. This may be useful if an object needs to iterate through a list of all its siblings. @hnode GUI menus @xref do_menu, d_menu_proc, gui_menu_draw_menu Popup or pulldown menus are created as an array of MENU structures. Read chapter "Structures and types defined by Allegro" for an internal description of the MENU structure. Each menu item contains a text string. This can use the '&' character to indicate keyboard shortcuts, or can be an zero-length string to display the item as a non-selectable splitter bar. If the string contains a "\t" tab character, any text after this will be right-justified, eg. for displaying keyboard shortcut information. The proc pointer is a function which will be called when the menu item is selected, and child points to another menu, allowing you to create nested menus. Both proc and child may be NULL. The proc function returns an integer which is ignored if the menu was brought up by calling do_menu(), but which is passed back to the dialog manager if it was created by a d_menu_proc() object. The array of menu items is terminated by an entry with a NULL text pointer. Menu items can be disabled (greyed-out) by setting the D_DISABLED bit in the flags field, and a check mark can be displayed next to them by setting the D_SELECTED bit. With the default alignment and font this will usually overlap the menu text, so if you are going to use checked menu items it would be a good idea to prefix all your options with a space or two, to ensure there is room for the check. @@int @do_menu(MENU *menu, int x, int y); @xref GUI menus, d_menu_proc, active_menu, gui_menu_draw_menu, update_menu @shortdesc Displays an animates a popup menu. 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. @@MENU_PLAYER *@init_menu(MENU *menu, int x, int y); @xref update_menu, shutdown_menu, do_menu @shortdesc Low level initialisation of a menu. 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: MENU_PLAYER *player = init_menu(menu, x, y); while (update_menu(player)) ; return shutdown_menu(player); @@int @update_menu(MENU_PLAYER *player); @xref init_menu, shutdown_menu, do_menu @shortdesc Low level function to update a menu player. Updates the status of a menu object returned by init_menu(). Returns TRUE if the menu is still active, or FALSE if it has terminated. Upon a return value of FALSE, it is up to you to call shutdown_menu() or to continue execution. @@int @shutdown_menu(MENU_PLAYER *player); @xref init_menu, update_menu @shortdesc Destroys a menu player object returned by init_menu(). 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()). @@extern MENU *@active_menu; @xref GUI menus @eref exgui @shortdesc Global pointer to the most recent activated menu. When a menu callback procedure is triggered, this will be set to the menu item that was selected, so your routine can determine where it was called from. @@extern void (*@gui_menu_draw_menu)(int x, int y, int w, int h); @\extern void (*@gui_menu_draw_menu_item)(MENU *m, int x, int y, int w, @@ int h, int bar, int sel); @xref GUI menus @shortdesc Hooks to modify the appearance of menus. 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. @@int @alert(const char *s1, *s2, *s3, const char *b1, *b2, int c1, c2); @xref alert3, gui_fg_color @eref exgui, expackf, exspline @shortdesc Displays a popup alert box. 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: if (!exists(CONFIG_FILE)) alert(CONFIG_FILE, "not found.", "Using defaults.", "&Continue", NULL, 'c', 0); @retval 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). @@int @alert3(const char *s1, *s2, *s3, const char *b1, *b2, *b3, int c1, c2, c3); @xref alert, gui_fg_color @shortdesc Like alert(), but with three buttons. Like alert(), but with three buttons. Returns 1, 2, or 3. @\int @file_select_ex(const char *message, char *path, const char *ext, @@ int size, int w, int h); @xref gui_fg_color @shortdesc Displays the Allegro file selector with a caption. 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. @@int @gfx_mode_select(int *card, int *w, int *h); @xref gfx_mode_select_ex, gfx_mode_select_filter, set_gfx_mode, gui_fg_color @shortdesc Displays the Allegro graphics mode selection dialog. 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. @@int @gfx_mode_select_ex(int *card, int *w, int *h, int *color_depth); @xref gfx_mode_select, gfx_mode_select_filter, set_color_depth, set_gfx_mode @xref gui_fg_color @eref ex3d, exscn3d, exswitch, exupdate, exzbuf @shortdesc Extended version of the graphics mode selection dialog. 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. @\int @gfx_mode_select_filter(int *card, int *w, int *h, int *color_depth, @@ int (*filter)(int, int, int, int)); @xref gfx_mode_select, gfx_mode_select_ex, set_color_depth, set_gfx_mode, gui_fg_color @shortdesc Even more extended version of the graphics mode selection dialog. 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. @@extern int (*@gui_shadow_box_proc)(int msg, struct DIALOG *d, int c); @@extern int (*@gui_ctext_proc)(int msg, struct DIALOG *d, int c); @@extern int (*@gui_button_proc)(int msg, struct DIALOG *d, int c); @@extern int (*@gui_edit_proc)(int msg, struct DIALOG *d, int c); @@extern int (*@gui_list_proc)(int msg, struct DIALOG *d, int c); @@extern int (*@gui_text_list_proc)(int msg, struct DIALOG *d, int c); @xref alert, alert3, file_select_ex, gfx_mode_select, gui_fg_color @shortdesc Hooks to customise the look and feel of Allegro dialogs. 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. @!man @chapter Platform specifics @heading DOS specifics There are four Allegro files which you should redistribute along your program. These are the files `keyboard.dat', `language.dat', `allegro.cfg' and `setup.exe'. The first two contain internationalisation information for keyboard mappings and system messages to show up localised on the user's computer. The `setup.exe' program, which comes in Allegro's `setup' directory, is a standalone tool which you can graphically customise and even embed into your main binary. The user can generate a configuration file with this tool, to store special settings or avoid Allegro's autodetection failing on specific hardware. Even if you distribute `setup.exe', you are recommended to copy too the empty `allegro.cfg' file, in case the setup program itself is unable to run and the user has to edit manually the configuration with a text editor. If you are using get_config_text() in your program to localise text strings, merge your xxtext.cfg files with the ones provided by Allegro in the `resource' directory before creating `language.dat', and redistribute this with your program. This file will contain then both Allegro's system messages and the strings of your program. @@Drivers @JOY_TYPE_*/DOS @xref install_joystick @shortdesc Supported DOS joystick drivers. The DOS library supports the following type parameters for the install_joystick() function:
  • JOY_TYPE_AUTODETECT
    Attempts to autodetect your joystick hardware. It isn't possible to reliably distinguish between all the possible input setups, so this routine can only ever choose the standard joystick, Sidewider, GamePad Pro, or GrIP drivers, but it will use information from the configuration file if one is available (this can be created using the setup utility or by calling the save_joystick_data() function), so you can always use JOY_TYPE_AUTODETECT in your code and then select the exact hardware type from the setup program.
  • JOY_TYPE_NONE
    Dummy driver for machines without any joystick.
  • JOY_TYPE_STANDARD
    A normal two button stick.
  • JOY_TYPE_2PADS
    Dual joystick mode (two sticks, each with two buttons).
  • JOY_TYPE_4BUTTON
    Enable the extra buttons on a 4-button joystick.
  • JOY_TYPE_6BUTTON
    Enable the extra buttons on a 6-button joystick.
  • JOY_TYPE_8BUTTON
    Enable the extra buttons on an 8-button joystick.
  • JOY_TYPE_FSPRO
    CH Flightstick Pro or compatible stick, which provides four buttons, an analogue throttle control, and a 4-direction coolie hat.
  • JOY_TYPE_WINGEX
    A Logitech Wingman Extreme, which should also work with any Thrustmaster Mk.I compatible joystick. It provides support for four buttons and a coolie hat. This also works with the Wingman Warrior, if you plug in the 15 pin plug (remember to unplug the 9-pin plug!) and set the tiny switch in front to the "H" position (you will not be able to use the throttle or the spinner though).
  • JOY_TYPE_SIDEWINDER
    The Microsoft Sidewinder digital pad (supports up to four controllers, each with ten buttons and a digital direction control).
  • JOY_TYPE_SIDEWINDER_AG
    An alternative driver to JOY_TYPE_SIDEWINDER. Try this if your Sidewinder isn't recognized with JOY_TYPE_SIDEWINDER.
  • JOY_TYPE_SIDEWINDER_PP
    The Microsoft Sidewinder 3D/Precision/Force Feedback Pro joysticks.
  • JOY_TYPE_GAMEPAD_PRO
    The Gravis GamePad Pro (supports up to two controllers, each with ten buttons and a digital direction control).
  • JOY_TYPE_GRIP
    Gravis GrIP driver, using the grip.gll driver file.
  • JOY_TYPE_GRIP4
    Version of the Gravis GrIP driver that is constrained to only move along the four main axes.
  • JOY_TYPE_SNESPAD_LPT1
    JOY_TYPE_SNESPAD_LPT2
    JOY_TYPE_SNESPAD_LPT3
    SNES joypads connected to LPT1, LPT2, and LPT3 respectively.
  • JOY_TYPE_PSXPAD_LPT1
    JOY_TYPE_PSXPAD_LPT2
    JOY_TYPE_PSXPAD_LPT3
    PSX joypads connected to LPT1, LPT2, and LPT3 respectively. See http://www.ziplabel.com/dpadpro/index.html for information about the parallel cable required. The driver automagically detects which types of PSX pads are connected out of digital, analog (red or green mode), NegCon, multi taps, Namco light guns, Jogcons (force feedback steering wheel) and the mouse. If the controller isn't recognised it is treated as an analog controller, meaning the driver should work with just about anything. You can connect controllers in any way you see fit, but only the first 8 will be used. The Sony Dual Shock or Namco Jogcon will reset themselves (to digital mode) after not being polled for 5 seconds. This is normal, the same thing happens on a Playstation, it's designed to stop any vibration in case the host machine crashes. Other mode switching controllers may have similar quirks. However, if this happens to a Jogcon controller the mode button is disabled. To reenable the mode button on the Jogcon you need to hold down the Start and Select buttons at the same time. The G-con45 needs to be connected to (and pointed at) a TV type monitor connected to your computer. The composite video out on my video card works fine for this (a Hercules Stingray 128/3D 8Mb). The TV video modes in Mame should work too.
  • JOY_TYPE_N64PAD_LPT1
    JOY_TYPE_N64PAD_LPT2
    JOY_TYPE_N64PAD_LPT3
    N64 joypads connected to LPT1, LPT2, and LPT3 respectively. See http://www.st-hans.de/N64.htm for information about the necessary hardware 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%.
  • JOY_TYPE_DB9_LPT1
    JOY_TYPE_DB9_LPT2
    JOY_TYPE_DB9_LPT3
    A pair of two-button joysticks connected to LPT1, LPT2, and LPT3 respectively. Port 1 is compatible with Linux joy-db9 driver (multisystem 2-button), and port 2 is compatible with Atari interface for DirectPad Pro. See the source file (src/dos/multijoy.c) for pinout information.
  • JOY_TYPE_TURBOGRAFIX_LPT1
    JOY_TYPE_TURBOGRAFIX_LPT2
    JOY_TYPE_TURBOGRAFIX_LPT3
    These drivers support up to 7 joysticks, each one with up to 5 buttons, connected to LPT1, LPT2, and LPT3 respectively. They use the TurboGraFX interface by Steffen Schwenke: see http://www.burg-halle.de/~schwenke/parport.html for details on how to build this.
  • JOY_TYPE_WINGWARRIOR
    A Wingman Warrior joystick.
  • JOY_TYPE_IFSEGA_ISA
    JOY_TYPE_IFSEGA_PCI
    JOY_TYPE_IFSEGA_PCI_FAST
    Drivers for the IF-SEGA joystick interface cards by the IO-DATA company (these come in PCI, PCI2, and ISA variants).
@@Drivers @GFX_*/DOS @xref set_gfx_mode @shortdesc Supported DOS graphic drivers. The DOS library supports the following card parameters for the set_gfx_mode() function:
  • GFX_TEXT
    Return to text mode.
  • GFX_AUTODETECT
    Let Allegro pick an appropriate graphics driver.
  • GFX_AUTODETECT_FULLSCREEN
    Autodetects a graphics driver, but will only use fullscreen drivers, failing if these are not available on current platform.
  • GFX_AUTODETECT_WINDOWED
    Same as above, but uses only windowed drivers. This will always fail under DOS.
  • GFX_SAFE
    Special driver for when you want to reliably set a graphics mode and don't really care what resolution or color depth you get. See the set_gfx_mode() documentation for details.
  • GFX_VGA
    The standard 256-color VGA mode 13h, using the GFX_VGA driver. This is normally sized 320x200, which will work on any VGA but doesn't support large virtual screens and hardware scrolling. Allegro also provides some tweaked variants of the mode which are able to scroll, sized 320x100 (with a 200 pixel high virtual screen), 160x120 (with a 409 pixel high virtual screen), 256x256 (no scrolling), and 80x80 (with a 819 pixel high virtual screen).
  • GFX_MODEX
    Mode-X will work on any VGA card, and provides a range of different 256-color tweaked resolutions.
    • Stable mode-X resolutions:
      • Square aspect ratio: 320x240
      • Skewed aspect ratio: 256x224, 256x240, 320x200, 320x400, 320x480, 320x600, 360x200, 360x240, 360x360, 360x400, 360x480
      These have worked on every card/monitor that I've tested.
    • Unstable mode-X resolutions:
      • Square aspect ratio: 360x270, 376x282, 400x300
      • Skewed aspect ratio: 256x200, 256x256, 320x350, 360x600, 376x308, 376x564, 400x150, 400x600
      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."
    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.
  • GFX_VESA1
    Use the VESA 1.x driver.
  • GFX_VESA2B
    Use the VBE 2.0 banked mode driver.
  • GFX_VESA2L
    Use the VBE 2.0 linear framebuffer driver.
  • GFX_VESA3
    Use the VBE 3.0 driver. This is the only VESA driver that supports the request_refresh_rate() function. The standard VESA modes are 640x480, 800x600, and 1024x768. These ought to work with any SVGA card: if they don't, get a copy of the SciTech Display Doctor and see if that fixes it. What color depths are available will depend on your hardware. Most cards support both 15 and 16-bit resolutions, but if at all possible I would advise you to support both (it's not hard...) in case one is not available. Some cards provide both 24 and 32-bit truecolor, in which case it is a choice between 24 (saves memory) or 32 (faster), but many older cards have no 32-bit mode and some newer ones don't support 24-bit resolutions. Use the vesainfo test program to see what modes your VESA driver provides. Many cards also support 640x400, 1280x1024, and 1600x1200, but these aren't available on everything, for example the S3 chipset has no 640x400 mode. Other weird resolution may be possible, eg. some Tseng boards can do 640x350, and the Avance Logic has a 512x512 mode. The SciTech Display Doctor provides several scrollable low resolution modes in a range of different color depths (320x200, 320x240, 320x400, 320x480, 360x200, 360x240, 360x400, and 360x480 all work on my ET4000 with 8, 15, or 16 bits per pixel). These are lovely, allowing scrolling and page flipping without the complexity of the mode-X planar setup, but unfortunately they aren't standard so you will need Display Doctor in order to use them.
  • GFX_VBEAF
    VBE/AF is a superset of the VBE 2.0 standard, which provides an API for accessing hardware accelerator features. VBE/AF drivers are currently only available from the FreeBE/AF project or as part of the SciTech Display Doctor package, but they can give dramatic speed improvements when used with suitable hardware. For a detailed discussion of hardware acceleration issues, refer to the documentation for the gfx_capabilities flag. You can use the afinfo test program to check whether you have a VBE/AF driver, and to see what resolutions it supports. The SciTech VBE/AF drivers require nearptr access to be enabled, so any stray pointers are likely to crash your machine while their drivers are in use. This means it may be a good idea to use VESA while debugging your program, and only switch to VBE/AF once the code is working correctly. The FreeBE/AF drivers do not have this problem.
  • GFX_XTENDED
    An unchained 640x400 mode, as described by Mark Feldman in the PCGPE. This uses VESA to select an SVGA mode (so it will only work on cards supporting the VESA 640x400 resolution), and then unchains the VGA hardware as for mode-X. This allows the entire screen to be addressed without the need for bank switching, but hardware scrolling and page flipping are not possible. This driver will never be autodetected (the normal VESA 640x400 mode will be chosen instead), so if you want to use it you will have to explicitly pass GFX_XTENDED to set_gfx_mode().
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. @@Drivers @DIGI_*/DOS @xref detect_digi_driver, install_sound, install_sound_input @shortdesc Supported DOS digital sound drivers. The DOS sound functions support the following digital soundcards: 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 @@Drivers @MIDI_*/DOS @xref detect_midi_driver, install_sound, install_sound_input @shortdesc Supported DOS MIDI sound drivers. The DOS sound functions support the following MIDI soundcards: 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) @hnode DOS integration routines @@extern int @i_love_bill; @xref install_timer, allegro_init, os_type @shortdesc Tells if Allegro has to used fixed rate timers. 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. @heading Windows specifics In terms of file redistribution, the Windows platform behaves practically the same as the DOS platform. Read section chapter "Dos specifics" in the manual to learn more about this. A Windows program that uses the Allegro library is only required to include one or more header files from the include/allegro tree, or allegro.h; however, if it also needs to directly call non portable Win32 API functions, it must include the Windows-specific header file winalleg.h after the Allegro headers, and before any Win32 API header file. By default winalleg.h includes the main Win32 C API header file windows.h. If instead you want to use the C++ interface to the Win32 API (a.k.a. the Microsoft Foundation Classes), define the preprocessor symbol ALLEGRO_AND_MFC before including any Allegro header so that afxwin.h will be included. Note that, in this latter case, the Allegro debugging macros ASSERT() and TRACE() are renamed AL_ASSERT() and AL_TRACE() respectively. Windows GUI applications start with a WinMain() entry point, rather than the standard main() entry point. Allegro is configured to build GUI applications by default and to do some magic in order to make a regular main() work with them, but you have to help it out a bit by writing END_OF_MAIN() right after your main() function. If you don't want to do that, you can just include winalleg.h and write a WinMain() function. Note that this magic may bring about conflicts with a few programs using direct calls to Win32 API functions; for these programs, the regular WinMain() is required and the magic must be disabled by defining the preprocessor symbol ALLEGRO_NO_MAGIC_MAIN before including Allegro headers. If you want to build a console application using Allegro, you have to define the preprocessor symbol ALLEGRO_USE_CONSOLE before including Allegro headers; it will instruct the library to use console features and also to disable the special processing of the main() function described above. When creating the main window, Allegro searches the executable for an ICON resource named "allegro_icon". If it is present, Allegro automatically loads it and uses it as its application icon; otherwise, Allegro uses the default IDI_APPLICATION icon. See the manual of your compiler for a method to create an ICON resource, or use the wfixicon utility from the tools/win directory. DirectX requires that system and video bitmaps (including the screen) be locked before you can draw onto them. This will be done automatically, but you can usually get much better performance by doing it yourself: see the acquire_bitmap() function for details. Due to a major oversight in the design of DirectX, there is no way to preserve the contents of video memory when the user switches away from your program. You need to be prepared for the fact that your screen contents, and the contents of any video memory bitmaps, may be destroyed at any point. You can use the set_display_switch_callback() function to find out when this happens. On the Windows platform, the only return values for the desktop_color_depth() function are 8, 16, 24 and 32. This means that 15-bit and 16-bit desktops cannot be differentiated and are both reported as 16-bit desktops. See below for the consequences for windowed and overlay DirectX drivers. @@Drivers @JOY_TYPE_*/Windows @xref install_joystick @shortdesc Supported Windows joystick drivers. The Windows library supports the following type parameters for the install_joystick() function:
  • JOY_TYPE_AUTODETECT
    Attempts to autodetect your joystick hardware. It will use information from the configuration file if one is available (this can be created using the setup utility or by calling the save_joystick_data() function), so you can always use JOY_TYPE_AUTODETECT in your code and then select the exact hardware type from the setup program.
  • JOY_TYPE_NONE
    Dummy driver for machines without any joystick.
  • JOY_TYPE_DIRECTX
    Use DirectInput to access the joystick.
  • JOY_TYPE_WIN32
    Use the regular Win32 interface rather than DirectInput to access the joystick.
@@Drivers @GFX_*/Windows @xref set_gfx_mode @shortdesc Supported Windows graphic drivers. The Windows library supports the following card parameters for the set_gfx_mode() function:
  • GFX_TEXT
    This closes any graphics mode previously opened with set_gfx_mode.
  • GFX_AUTODETECT
    Let Allegro pick an appropriate graphics driver.
  • GFX_AUTODETECT_FULLSCREEN
    Autodetects a graphics driver, but will only use fullscreen drivers, failing if these are not available on current platform.
  • GFX_AUTODETECT_WINDOWED
    Same as above, but uses only windowed drivers.
  • GFX_SAFE
    Special driver for when you want to reliably set a graphics mode and don't really care what resolution or color depth you get. See the set_gfx_mode() documentation for details.
  • GFX_DIRECTX
    Alias for GFX_DIRECTX_ACCEL.
  • GFX_DIRECTX_ACCEL
    The regular fullscreen DirectX driver, running with hardware acceleration enabled.
  • GFX_DIRECTX_SOFT
    DirectX fullscreen driver that only uses software drawing, rather than any hardware accelerated features.
  • GFX_DIRECTX_SAFE
    Simplified fullscreen DirectX driver that doesn't support any hardware acceleration, video or system bitmaps, etc.
  • GFX_DIRECTX_WIN
    The regular windowed DirectX driver, running in color conversion mode when the color depth doesn't match that of the Windows desktop. Color conversion is much slower than direct drawing and is not supported between 15-bit and 16-bit color depths. This limitation is needed to work around that of desktop_color_depth() (see above) and allows to select the direct drawing mode in a reliable way on desktops reported as 16-bit: 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 */ } 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.
  • GFX_DIRECTX_OVL
    The DirectX overlay driver. It uses special hardware features to run your program in a windowed mode: it doesn't work on all hardware, but performance is excellent on cards that are capable of it. It requires the color depth to be the same as that of the Windows desktop. In light of the limitation of desktop_color_depth() (see above), the reliable way of setting the overlay driver on desktops reported as 16-bit is: 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 */ }
  • GFX_GDI
    The windowed GDI driver. It is extremely slow, but is guaranteed to work on all hardware, so it can be useful for situations where you want to run in a window and don't care about performance. Note that this driver features a hardware mouse cursor emulation in order to speed up basic mouse operations (like GUI operations).
@@Drivers @DIGI_*/Windows @xref detect_digi_driver, install_sound, install_sound_input @shortdesc Supported Windows digital sound drivers. The Windows sound functions support the following digital soundcards: 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 @@Drivers @MIDI_*/Windows @xref detect_midi_driver, install_sound, install_sound_input @shortdesc Supported Windows MIDI sound drivers. The Windows sound functions support the following MIDI soundcards: 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 @hnode Windows integration routines 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. @@HWND @win_get_window(void); @shortdesc Retrieves a handle to the window used by Allegro. 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). @@void @win_set_window(HWND wnd); @shortdesc Registers an user-created window to be used by Allegro. 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. @@void @win_set_wnd_create_proc(HWND (*proc)(WNDPROC)); @shortdesc Registers a custom procedure to be used by Allegro for creating its window. 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. @@HDC @win_get_dc(BITMAP *bmp); @shortdesc Retrieves a handle to the device context. Retrieves a handle to the device context of a DirectX video or system bitmap. @@void @win_release_dc(BITMAP *bmp, HDC dc); @shortdesc Releases a handle to the device context. Releases a handle to the device context of the bitmap that was previously retrieved with win_get_dc(). @hnode GDI routines 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. @@void @set_gdi_color_format(void); @shortdesc Tells Allegro to use the GDI color layout for truecolor images. 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. @@void @set_palette_to_hdc(HDC dc, PALETTE pal); @shortdesc Selects and realizes a palette on the specified device context. Selects and realizes an Allegro palette on the specified device context. @@HPALETTE @convert_palette_to_hpalette(PALETTE pal); @xref convert_hpalette_to_palette @shortdesc Converts an Allegro palette to a Windows palette. Converts an Allegro palette to a Windows palette and returns a handle to it. You should call DeleteObject() when you no longer need it. @@void @convert_hpalette_to_palette(HPALETTE hpal, PALETTE pal); @xref convert_palette_to_hpalette @shortdesc Converts a Windows palette to an Allegro palette. Converts a Windows palette to an Allegro palette. @@HBITMAP @convert_bitmap_to_hbitmap(BITMAP *bitmap); @xref convert_hbitmap_to_bitmap @shortdesc Converts an Allegro memory bitmap to a Windows DDB. 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. @@BITMAP *@convert_hbitmap_to_bitmap(HBITMAP bitmap); @xref convert_bitmap_to_hbitmap @shortdesc Creates an Allegro memory bitmap from a Windows DDB. Creates an Allegro memory bitmap from a Windows DDB. @@void @draw_to_hdc(HDC dc, BITMAP *bitmap, int x, int y); @xref blit_to_hdc, stretch_blit_to_hdc, draw_sprite @shortdesc Draws an Allegro bitmap to a Windows device context. Draws an entire Allegro bitmap to a Windows device context, using the same parameters as the draw_sprite() function. @@void @blit_to_hdc(BITMAP *bitmap, HDC dc, int sx, sy, dx, dy, w, h); @xref draw_to_hdc, stretch_blit_to_hdc, blit_from_hdc, blit @shortdesc Blits an Allegro memory bitmap to a Windows device context. Blits an Allegro memory bitmap to a Windows device context, using the same parameters as the blit() function. @\void @stretch_blit_to_hdc(BITMAP *bitmap, HDC dc, int sx, sy, sw, sh, @@ int dx, dy, dw, dh); @xref draw_to_hdc, blit_to_hdc, stretch_blit_from_hdc, stretch_blit @shortdesc Blits an Allegro memory bitmap to a Windows device context. Blits an Allegro memory bitmap to a Windows device context, using the same parameters as the stretch_blit() function. @@void @blit_from_hdc(HDC hdc, BITMAP *bitmap, int sx, sy, dx, dy, w, h); @xref stretch_blit_from_hdc, blit_to_hdc, blit @shortdesc Blits from a Windows device context to an Allegro memory bitmap. 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. @\void @stretch_blit_from_hdc(HDC hcd, BITMAP *bitmap, int sx, sy, sw, sh, @@ int dx, dy, dw, dh); @xref blit_from_hdc, stretch_blit_to_hdc, stretch_blit @shortdesc Blits from a Windows device context to an Allegro memory bitmap. 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. @man @heading Unix specifics Under Unix you usually have two ways of redistributing your binaries. You either pack everything in a single directory, even providing Allegro in binary or source form for the user to compile. Or your program is being packaged separately from Allegro and stored in different paths. For the first case of redistribution, read section "Files shared by Allegro" from the "Dos specifics" chapter to learn more about this. For the second type, you can ignore redistributing the setup, keyboard mappings and language datafiles, because they will be already installed in the system. This, however, is problematic if you are using get_config_text() to localise your program's text strings. The problem is that on other platforms you usually mix your program's text strings with those of Allegro (found in the `resources' directory) to create a special language.dat. And it is likely that the Allegro library installed on the user's system already contains a datafile.dat. You can go ahead and still provide your own language.dat file, but this will mean that if Allegro is updated, your language.dat file may not contain all the text strings used by the new version. Given the slow paced release cycle of Allegro, this might not be a concern. However, if you want to make it easy on system administrators, instead of providing your own `language.dat', you should provide the separate `xxtext.cfg' files it in a separate directory. Then, before showing the strings to the user you can detect the language setting and use override_config_file() with the appropriate localisation file and call reload_config_texts(). In order to locate things like the config and translation files, Allegro needs to know the path to your executable. Since there is no standard way to find that, it needs to capture a copy of your argv[] parameter, and it does this with some preprocessor macro trickery. Unfortunately it can't quite pull this off without a little bit of your help, so you will have to write END_OF_MAIN() right after your main() function. Pretty easy, really, and if you forget, you'll get a nice linker error about a missing _mangled_main function to remind you :-) Under Unix resources are searched for in many different paths (see above). When a configuration resource is looked for, it is usually tried with the variations `name.cfg' or `.namerc' in multiple paths: the current directory, the directory pointed to by the ALLEGRO environment variable, the user's home directory, one or more global system directories which usually only the root user has access to and any custom paths set up with set_allegro_resource_path(). Text files, like the main allegro config file or a language text translation files are looked for in the following places: ./allegro.cfg $ALLEGRO/allegro.cfg ~/allegro.cfg ~/.allegrorc /etc/allegro.cfg /etc/allegrorc Binary resources like the language translation files packfile (language.dat) are looked for in: ./language.dat $ALLEGRO/language.dat ~/language.dat /etc/language.dat /usr/share/allegro/language.dat /usr/local/share/allegro/language.dat Note that if you have installed Allegro from the source distribution with the typical `make install', global files like `language.dat' and `allegro.cfg' will not have been installed. As a system administrator you are required to install them manually wherever you prefer to have them. If you suspect that an Allegro program is somehow not finding the correct configuration file, you could try using the following command: strace program 2>&1|egrep "(open|stat)" The strace program traces system calls and signals. By default it outputs the information to stderr, so that's why we redirect it to stdin with `2>&1'. Since we are interested only in files being (un)successfully opened, we restrict the output of the log to stat or open calls with the extended grep command. You could add another grep to filter only lines with text like `language' or `allegro'. @@Drivers @JOY_TYPE_*/Linux @xref install_joystick @shortdesc Supported Linux joystick drivers. The Linux library supports the following type parameters for the install_joystick() function:
  • JOY_TYPE_AUTODETECT
    Attempts to autodetect your joystick hardware. It will use information from the configuration file if one is available (this can be created using the setup utility or by calling the save_joystick_data() function), so you can always use JOY_TYPE_AUTODETECT in your code and then select the exact hardware type from the setup program.
  • JOY_TYPE_NONE
    Dummy driver for machines without any joystick.
  • JOY_TYPE_LINUX_ANALOGUE
    Regular joystick interface. Joystick support needs to be enabled in your kernel.
@@Drivers @GFX_*/Linux @xref set_gfx_mode, GFX_*/X @shortdesc Supported Linux console graphic drivers. When running in Linux console mode, Allegro supports the following card parameters for the set_gfx_mode() function:
  • GFX_TEXT
    Return to text mode.
  • GFX_AUTODETECT
    Let Allegro pick an appropriate graphics driver.
  • GFX_AUTODETECT_FULLSCREEN
    Autodetects a graphics driver, but will only use fullscreen drivers, failing if these are not available on current platform.
  • GFX_AUTODETECT_WINDOWED
    Same as above, but uses only windowed drivers. This will always fail under Linux console mode.
  • GFX_SAFE
    Special driver for when you want to reliably set a graphics mode and don't really care what resolution or color depth you get. See the set_gfx_mode() documentation for details.
  • GFX_FBCON
    Use the framebuffer device (eg. /dev/fb0). This requires you to have framebuffer support compiled into your kernel, and correctly configured for your hardware. It is currently the only console mode driver that will work without root permissions, unless you are using a development version of SVGAlib.
  • GFX_VBEAF
    Use a VBE/AF driver (vbeaf.drv), assuming that you have installed one which works under Linux (currently only two of the FreeBE/AF project drivers are capable of this: I don't know about the SciTech ones). VBE/AF requires root permissions, but is currently the only Linux driver which supports hardware accelerated graphics.
  • GFX_SVGALIB
    Use the SVGAlib library for graphics output. This requires root permissions if your version of SVGAlib requires them.
  • GFX_VGA
    GFX_MODEX
    Use direct hardware access to set standard VGA or mode-X resolutions, supporting the same modes as in the DOS versions of these drivers. Requires root permissions.
@@Drivers @GFX_*/X @xref set_gfx_mode, GFX_*/Linux @shortdesc Supported X graphic drivers. When running in X mode, Allegro supports the following card parameters for the set_gfx_mode() function:
  • GFX_TEXT
    This closes any graphics mode previously opened with set_gfx_mode.
  • GFX_AUTODETECT
    Let Allegro pick an appropriate graphics driver.
  • GFX_AUTODETECT_FULLSCREEN
    Autodetects a graphics driver, but will only use fullscreen drivers, failing if these are not available on current platform.
  • GFX_AUTODETECT_WINDOWED
    Same as above, but uses only windowed drivers.
  • GFX_SAFE
    Special driver for when you want to reliably set a graphics mode and don't really care what resolution or color depth you get. See the set_gfx_mode() documentation for details.
  • GFX_XWINDOWS
    The standard X graphics driver. This should work on any Unix system, and can operate remotely. It does not require root permissions. If the ARGB cursor extension is available, this driver is capable of displaying a hardware cursor. This needs to be enabled by calling enable_hardware_cursor() becaue it cannot be used reliably alongside get_mouse_mickeys().
  • GFX_XWINDOWS_FULLSCREEN
    The same as above, but while GFX_XWINDOWS runs windowed, this one uses the XF86VidMode extension to make it run in fullscreen mode even without root permissions. You're still using the standard X protocol though, so expect the same low performances as with the windowed driver version. If the ARGB cursor extension is available, this driver is capable of displaying a hardware cursor. This needs to be enabled by calling enable_hardware_cursor() becaue it cannot be used reliably alongside get_mouse_mickeys().
  • GFX_XDGA2
    Use new DGA 2.0 extension provided by XFree86 4.0.x. This will work in fullscreen mode, and it will support hardware acceleration if available. This driver requires root permissions.
  • GFX_XDGA2_SOFT
    The same as GFX_XDGA2, but turns off hardware acceleration support. This driver requires root permissions.
@@Drivers @DIGI_*/Unix @xref detect_digi_driver, install_sound, install_sound_input @shortdesc Supported Unix digital sound drivers. The Unix sound functions support the following digital soundcards: 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 @@Drivers @MIDI_*/Unix @xref detect_midi_driver, install_sound, install_sound_input @shortdesc Supported Unix MIDI sound drivers. The Unix sound functions support the following MIDI soundcards: 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 @hnode Unix integration routines @@void @xwin_set_window_name(const char *name, const char *group); @xref set_window_title @shortdesc Specify the window name and group (or class). 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. @@extern void *@allegro_icon; @shortdesc Pointer to the Allegro X11 icon. This is a pointer to the Allegro X11 icon, which is in the format of standard .xpm bitmap data. You do not normally have to bother with this at all: you can use the xfixicon.sh utility from the tools/x11 directory to convert a true colour bitmap to a C file that you only need to link with your own code to set the icon. @heading BeOS specifics In terms of file redistribution, the BeOS platform behaves practically the same as the DOS platform. Read section chapter "Dos specifics" in the manual to learn more about this. @@Drivers @GFX_*/BeOS @xref set_gfx_mode @shortdesc Supported BeOS graphic drivers. BeOS Allegro supports the following card parameters for the set_gfx_mode() function:
  • GFX_TEXT
    This closes any graphics mode previously opened with set_gfx_mode.
  • GFX_AUTODETECT
    Let Allegro pick an appropriate graphics driver.
  • GFX_AUTODETECT_FULLSCREEN
    Autodetects a graphics driver, but will only use fullscreen drivers, failing if these are not available on current platform.
  • GFX_AUTODETECT_WINDOWED
    Same as above, but uses only windowed drivers.
  • GFX_SAFE
    Special driver for when you want to reliably set a graphics mode and don't really care what resolution. See the set_gfx_mode() documentation for details.
  • GFX_BWINDOWSCREEN_ACCEL
    Fullscreen exclusive mode. Supports only resolutions higher or equal to 640x480, and uses hardware acceleration if available.
  • GFX_BWINDOWSCREEN
    Works the same as GFX_BWINDOWSCREEN_ACCEL, but disables acceleration.
  • GFX_BDIRECTWINDOW
    Fast windowed mode using the BDirectWindow class. Not all graphics cards support this.
  • GFX_BWINDOW
    Normal windowed mode using the BWindow class. Slow but always works.
  • GFX_BWINDOW_OVERLAY
    Fullscreen mode using BWindow with a BBitmap overlay. This mode isn't supported by all graphics cards, only supports 15, 16 and 32-bit color depths, but allows any fullscreen resolution, even low ones that are normally unavailable under BeOS.
@@Drivers @DIGI_*/BeOS @xref detect_digi_driver, install_sound, install_sound_input @shortdesc Supported BeOS digital sound drivers. The BeOS sound functions support the following digital soundcards: DIGI_AUTODETECT - let Allegro pick a digital sound driver DIGI_NONE - no digital sound DIGI_BEOS - BeOS digital output @@Drivers @MIDI_*/BeOS @xref detect_midi_driver, install_sound, install_sound_input @shortdesc Supported BeOS MIDI sound drivers. The BeOS sound functions support the following MIDI soundcards: 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 @heading QNX specifics In terms of file redistribution, the QNX platform behaves practically the same as the DOS platform. Read section chapter "Dos specifics" in the manual to learn more about this. @@Drivers @GFX_*/QNX @xref set_gfx_mode @shortdesc Supported QNX graphic drivers. QNX Allegro supports the following card parameters for the set_gfx_mode() function:
  • GFX_TEXT
    This closes any graphics mode previously opened with set_gfx_mode.
  • GFX_AUTODETECT
    Let Allegro pick an appropriate graphics driver.
  • GFX_AUTODETECT_FULLSCREEN
    Autodetects a graphics driver, but will only use fullscreen drivers, failing if these are not available on current platform.
  • GFX_AUTODETECT_WINDOWED
    Same as above, but uses only windowed drivers.
  • GFX_SAFE
    Special driver for when you want to reliably set a graphics mode and don't really care what resolution. See the set_gfx_mode() documentation for details.
  • GFX_PHOTON
    Alias for GFX_PHOTON_ACCEL.
  • GFX_PHOTON_ACCEL
    Fullscreen exclusive mode through Photon, running with hardware acceleration enabled.
  • GFX_PHOTON_SOFT
    Fullscreen exclusive mode that only uses software drawing, rather than any hardware accelerated features.
  • GFX_PHOTON_SAFE
    Simplified fullscreen exclusive driver that doesn't support any hardware acceleration, video or system bitmaps, etc.
  • GFX_PHOTON_WIN
    The regular windowed Photon driver, running in color conversion mode when the color depth doesn't match that of the Photon desktop. Color conversion is much slower than direct drawing. Note that, mainly for performance reasons, this driver requires the width of the screen to be a multiple of 4.
@@Drivers @DIGI_*/QNX @xref detect_digi_driver, install_sound, install_sound_input @shortdesc Supported QNX digital sound drivers. The QNX sound functions support the following digital soundcards: DIGI_AUTODETECT - let Allegro pick a digital sound driver DIGI_NONE - no digital sound DIGI_ALSA - ALSA sound driver @@Drivers @MIDI_*/QNX @xref detect_midi_driver, install_sound, install_sound_input @shortdesc Supported QNX MIDI sound drivers. The QNX sound functions support the following MIDI soundcards: 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 @hnode QNX integration routines 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. @@PtWidget_t @qnx_get_window(void); @shortdesc Retrieves a handle to the window used by Allegro. 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). @heading MacOS X specifics In terms of file redistribution, the MacOS X platform behaves practically the same as the DOS platform. Read section chapter "Dos specifics" in the manual to learn more about this. Allegro programs under MacOS X are Cocoa applications; in order to hide all the Cocoa interfacing to the 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. @@Drivers @GFX_*/MacOSX @xref set_gfx_mode @shortdesc Supported MacOSX graphic drivers. MacOS X Allegro supports the following card parameters for the set_gfx_mode() function:
  • GFX_TEXT
    This closes any graphics mode previously opened with set_gfx_mode.
  • GFX_AUTODETECT
    Let Allegro pick an appropriate graphics driver.
  • GFX_AUTODETECT_FULLSCREEN
    Autodetects a graphics driver, but will only use fullscreen drivers, failing if these are not available on current platform.
  • GFX_AUTODETECT_WINDOWED
    Same as above, but uses only windowed drivers.
  • GFX_SAFE
    Special driver for when you want to reliably set a graphics mode and don't really care what resolution. See the set_gfx_mode() documentation for details.
  • GFX_QUARTZ_FULLSCREEN
    Fullscreen exclusive mode, using the CGDirectDisplay interface. Supports only resolutions higher or equal to 640x480, and uses hardware acceleration if available.
  • GFX_QUARTZ_WINDOW
    Windowed mode using QuickDraw in a Cocoa window.
@@Drivers @DIGI_*/MacOSX @xref detect_digi_driver, install_sound, install_sound_input @shortdesc Supported MacOSX digital sound drivers. The MacOS X sound functions support the following digital soundcards: 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 @@Drivers @MIDI_*/MacOSX @xref detect_midi_driver, install_sound, install_sound_input @shortdesc Supported MacOSX MIDI sound drivers. The MacOS X sound functions support the following MIDI soundcards: 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 @headingnocontent Differences between platforms Here's a quick summary of things that may cause problems when moving your code from one platform to another (you can find a more detailed version of this in the docs section of the Allegro website). The Windows, Unix and MacOS X versions require you to write END_OF_MAIN() after your main() function. This is used to magically turn an ISO C style main() into a Windows style WinMain(), or by the Unix code to grab a copy of your argv[] parameter, or by the MacOS X code to shell the user main() inside a Cocoa application. On many platforms Allegro runs very slowly if you rely on it in order to automatically lock bitmaps when drawing onto them. For good performance, you need to call acquire_bitmap() and release_bitmap() yourself, and try to keep the amount of locking to a minimum. The Windows version may lose the contents of video memory if the user switches away from your program, so you need to deal with that. None of the currently supported platforms require input polling, but it is possible that some future ones might, so if you want to ensure 100% portability of your program, you should call poll_mouse() and poll_keyboard() in all the relevant places. On Unix the shared files by Allegro (like `language.dat') may require a special use due to the nature of distributing the resources in separate paths instead of putting everything in the same directory. Check the beginning of your platform's specific chapter to learn more about this. Allegro defines a number of standard macros that can be used to check various attributes of the current platform: ALLEGRO_PLATFORM_STR
Text string containing the name of the current platform. ALLEGRO_DOS
ALLEGRO_DJGPP
ALLEGRO_WATCOM
ALLEGRO_WINDOWS
ALLEGRO_MSVC
ALLEGRO_MINGW32
ALLEGRO_BCC32
ALLEGRO_UNIX
ALLEGRO_LINUX
ALLEGRO_BEOS
ALLEGRO_QNX
ALLEGRO_DARWIN
ALLEGRO_MACOSX
ALLEGRO_GCC
Defined if you are building for a relevant system. Often several of these will apply, eg. DOS+Watcom, or Windows+GCC+MinGW. ALLEGRO_AMD64
ALLEGRO_I386
ALLEGRO_BIG_ENDIAN
ALLEGRO_LITTLE_ENDIAN
Defined if you are building for a processor of the relevant type. ALLEGRO_MULTITHREADED
Defined if the library is internally multi-threaded on this system. ALLEGRO_USE_CONSTRUCTOR
Defined if the compiler supports constructor/destructor functions. ALLEGRO_VRAM_SINGLE_SURFACE
Defined if the screen is a single large surface that is then partitioned into multiple video sub-bitmaps (eg. DOS), rather than each video bitmap being a totally unique entity (eg. Windows). ALLEGRO_CONSOLE_OK
Defined if when you are not in a graphics mode, there is a text mode console that you can printf() to, and from which the user could potentially redirect stdout to capture it even while you are in a graphics mode. If this define is absent, you are running in an environment like Windows that has no stdout at all. ALLEGRO_MAGIC_MAIN
Defined if Allegro uses a magic main, i.e takes over the main() entry point and turns it into a secondary entry point suited to its needs. ALLEGRO_LFN
Non-zero if long filenames are supported, or zero if you are limited to 8.3 format (in the DJGPP version, this is a variable depending on the runtime environment). LONG_LONG
Defined to whatever represents a 64-bit "long long" integer for the current compiler, or not defined if that isn't supported. OTHER_PATH_SEPARATOR
Defined to a path separator character other than a forward slash for platforms that use one (eg. a backslash under DOS and Windows), or defined to a forward slash if there is no other separator character. DEVICE_SEPARATOR
Defined to the filename device separator character (a colon for DOS and Windows), or to zero if there are no explicit devices in paths (Unix). Allegro can be customized at compile time to a certain extent with the following macros: ALLEGRO_NO_MAGIC_MAIN
If you define this prior to including Allegro headers, Allegro won't touch the main() entry point. This effectively removes the requirement on a program to be linked against the Allegro library when it includes the allegro.h header file. Note that the configuration and file routines are not guaranteed to work on Unix systems when this symbol is defined. Moreover, on Darwin/MacOS X systems, this symbol simply prevents the program from being linked against the Allegro library! This highly non portable feature is primarily intended to be used under Windows. ALLEGRO_USE_CONSOLE
If you define this prior to including Allegro headers, Allegro will be set up for building a console application rather than the default GUI program on some platforms (especially Windows). ALLEGRO_NO_STD_HEADER
If you define this prior to including Allegro headers, Allegro will not automatically include some standard headers (eg <stddef.h>) its own headers depend upon. ALLEGRO_NO_KEY_DEFINES
If you define this prior to including Allegro headers, Allegro will omit the definition of the KEY_* constants, which may clash with other headers. ALLEGRO_NO_FIX_ALIASES
The fixed point functions used to be named with an "f" prefix instead of "fix", eg. fixsqrt() used to be fsqrt(), but were renamed due to conflicts with some libc implementations. So backwards compatibility aliases are provided as static inline functions which map the old names to the new names, eg. fsqrt() calls fixsqrt(). If you define this symbol prior to including Allegro headers, the aliases will be turned off. ALLEGRO_NO_FIX_CLASS
If you define this symbol prior to including Allegro headers in a C++ source file, the 'fix' class will not be made available. This mitigates problems with the 'fix' class's overloading getting in the way. ALLEGRO_NO_VHLINE_ALIAS
The `curses' API also defines functions called vline() and hline(). To avoid a linker conflict when both libraries are used, we have internally renamed our functions and added inline function aliases which remap vline() and hline(). This should not be 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. ALLEGRO_NO_CLEAR_BITMAP_ALIAS
If you define this prior to including Allegro headers, Allegro will not define the clear() backwards compatibility alias to clear_bitmap(). ALLEGRO_NO_COMPATIBILITY
If you define this prior to including Allegro headers, Allegro will not include the backward compatibility layer. It is undefined by default so old programs can still be compiled with the minimum amount of issues, but you should define this symbol if you intend to maintain your code up to date with the latest versions of Allegro. It automatically turns off all backwards compatibility aliases. Allegro also defines a number of standard macros that can be used to insulate you from some of the differences between systems: INLINE
Use this in place of the regular "inline" function modifier keyword, and your code will work correctly on any of the supported compilers. RET_VOLATILE
Use this to declare a function with a volatile return value. ZERO_SIZE_ARRAY(type, name)
Use this to declare zero-sized arrays in terminal position inside structures, like in the BITMAP structure. These arrays are effectively equivalent to the flexible array members of ISO C99. AL_CONST
Use this in place of the regular "const" object modifier keyword, and your code will work correctly on any of the supported compilers. AL_RAND()
On platforms that require it, this macro does a simple shift transformation of the libc rand() function, in order to improve the perceived randomness of the output series in the lower 16 bits. Where not required, it directly translates into a rand() call. @chapter Miscellaneous @headingnocontent Reducing your executable size Some people complain that Allegro produces very large executables. This is certainly true: with the DJGPP version, a simple "hello world" program will be about 200k, although the per-executable overhead is much less for platforms that support dynamic linking. But don't worry, Allegro takes up a relatively fixed amount of space, and won't increase as your program gets larger. As George Foot so succinctly put it, anyone who is concerned about the ratio between library and program code should just get to work and write more program code to catch up :-) Having said that, there are several things you can do to make your programs smaller:
  • For all platforms, you can use an executable compressor called UPX, which is available at http://upx.sourceforge.net/. This usually manages a compression ratio of about 40%.
  • 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!
  • 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: BEGIN_GFX_DRIVER_LIST driver1 driver2 etc... END_GFX_DRIVER_LIST where the driver names are any of the defines: GFX_DRIVER_VBEAF GFX_DRIVER_VGA GFX_DRIVER_MODEX GFX_DRIVER_VESA3 GFX_DRIVER_VESA2L GFX_DRIVER_VESA2B GFX_DRIVER_XTENDED GFX_DRIVER_VESA1 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.
  • 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: BEGIN_COLOR_DEPTH_LIST depth1 depth2 etc... END_COLOR_DEPTH_LIST where the color depth names are any of the defines: COLOR_DEPTH_8 COLOR_DEPTH_15 COLOR_DEPTH_16 COLOR_DEPTH_24 COLOR_DEPTH_32 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!
  • In the same way as the above, you can specify which DOS sound drivers you want to support with the code: BEGIN_DIGI_DRIVER_LIST driver1 driver2 etc... END_DIGI_DRIVER_LIST using the digital sound driver defines: DIGI_DRIVER_SOUNDSCAPE DIGI_DRIVER_AUDIODRIVE DIGI_DRIVER_WINSOUNDSYS DIGI_DRIVER_SB and for the MIDI music: BEGIN_MIDI_DRIVER_LIST driver1 driver2 etc... END_MIDI_DRIVER_LIST using the MIDI driver defines: MIDI_DRIVER_AWE32 MIDI_DRIVER_DIGMID MIDI_DRIVER_ADLIB MIDI_DRIVER_MPU MIDI_DRIVER_SB_OUT If you are going to use either of these sound driver constructs, you must include both.
  • Likewise for the DOS joystick drivers, you can declare an inclusion list: BEGIN_JOYSTICK_DRIVER_LIST driver1 driver2 etc... END_JOYSTICK_DRIVER_LIST using the joystick driver defines: 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 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.
  • 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: #define ALLEGRO_COLOR8 #define ALLEGRO_COLOR16 #define ALLEGRO_COLOR24 #define ALLEGRO_COLOR32 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.
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. @heading Debugging There are three versions of the Allegro library: the normal optimised code, one with extra debugging support, and a profiling version. See the platform specific readme files for information about how to install and link with these alternative libs. Although you will obviously want to use the optimised library for the final version of your program, it can be very useful to link with the debug lib while you are working on it, because this will make debugging much easier, and includes assert tests that will help to locate errors in your code at an earlier stage. Allegro also contains some debugging helper functions: @@void @ASSERT(condition); @xref al_assert, TRACE, register_assert_handler @eref expackf @shortdesc Debugging helper macro to assert. 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: #define DEBUGMODE #include ... void my_blitter(BITMAP *source, int flags) { int some_variables; ASSERT(source != NULL); ASSERT(flags & GAME_RUNNING); ... } @@void @TRACE(char *msg, ...); @xref al_trace, ASSERT, register_trace_handler @shortdesc Debugging helper macro to trace messages. 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: #define DEBUGMODE #include ... void my_blitter(BITMAP *source, int flags) { static int count_call = 0; TRACE("my_blitter() called %d times.\n", count_call++); ... } @@void @register_assert_handler(int (*handler)(const char *msg)); @xref al_assert, ASSERT, register_trace_handler @shortdesc Registers a custom handler for assert failures. 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: int show_but_continue(const char *text) { alert("Uh oh...", "Fasten your seat belts.", text, "&Go on!", NULL, 'g', 0); return 1; } ... register_assert(show_but_continue); ASSERT(0); /* This won't crash the program now. */ @@void @register_trace_handler(int (*handler)(const char *msg)); @xref al_trace, TRACE, register_assert_handler @shortdesc Registers a custom handler for trace output. 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: 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"); @@void @al_assert(const char *file, int line); @xref ASSERT, al_trace, register_assert_handler @shortdesc Asserts at the specified file and line number. 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. @@void @al_trace(const char *msg, ...); @xref TRACE, al_assert, register_trace_handler @shortdesc Outputs a debugging trace message. 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. @headingnocontent Makefile targets There are a number of options that you can use to control exactly how Allegro will be compiled. On Unix platforms, you do this by passing arguments to the configure script (run "configure --help" for a list), but on other platforms you can set the following environment variables:
  • DEBUGMODE=1
    Selects a debug build, rather than the normal optimised version.
  • DEBUGMODE=2
    Selects a build intended to debug Allegro itself, rather than the normal optimised version.
  • PROFILEMODE=1
    Selects a profiling build, rather than the normal optimised version.
  • WARNMODE=1
    Selects strict compiler warnings. If you are planning to work on Allegro yourself, rather than just using it in your programs, you should be sure to have this mode enabled.
  • STATICLINK=1 (MinGW, MSVC, BeOS, MacOS X only)
    Link as a static library, rather than the default dynamic library.
  • STATICRUNTIME=1 (MSVC only)
    Link against static runtime libraries, rather than the default dynamic runtime libraries.
  • TARGET_ARCH_COMPAT=[cpu] (GCC-based platforms only)
    This option will optimize for the given processor while maintaining compatibility with older processors. Example: set TARGET_ARCH_COMPAT=i586
  • TARGET_ARCH_EXCL=[cpu] (GCC-based platforms only)
    This option will optimize for the given processor. Please note that using it will cause the code to *NOT* run on older processors. Example: set TARGET_ARCH_EXCL=i586
  • TARGET_OPTS=[opts] (GCC-based platforms only)
    This option allows you to customize general compiler optimisations.
  • TARGET_ARCH_EXCL=[opts] (MSVC only)
    This option allows you to optimize exclusively for a given architecture. Pass B to optimize for a PentiumPro or 7 to optimize for Pentium 4. Note that the options you can pass may be different between MSVC 6 and 7. Example: set TARGET_ARCH_EXCL=7
  • CROSSCOMPILE=1 (DJGPP, MinGW only)
    Allows you to build the library under Linux by using a cross-compiler.
  • ALLEGRO_USE_C=1 (GCC-based platforms only)
    Allows you to build the library using C drawing code instead of the usual asm routines. This is only really useful for testing, since the asm version is faster.
  • UNIX_TOOLS=1
    Instructs the build process to use Unix-like tools instead of DOS tools. Note that you usually don't need to set it because the build proces will try to autodetect this configuration.
  • COMPILER_MSVC7=1 (MSVC only)
    Enables special optimizations for MSVC 7 (the default is MSVC 6). You don't normally need to set this flag since fix.bat msvc7 should do the same thing and is the prefered way of doing this.
  • COMPILER_ICL=1 (MSVC only)
    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 fix.bat icl 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.
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:
  • 'info' (Unix only)
    Tells you which options this particular build of Allegro will use. Especially useful to verify that the required libraries were detected and you won't get a 'half-featured' Allegro.
  • 'default'
    The normal build process. Compiles the current library version (one of optimised, debugging, or profiling, selected by the above environment variables), builds the test and example programs, and converts the documentation files.
  • 'all' (non-Unix only)
    Compiles all three library versions (optimised, debugging, and profiling), builds the test and example programs, and converts the documentation files.
  • 'lib'
    Compiles the current library version (one of optimised, debugging, or profiling, selected by the above environment variables).
  • 'modules' (Unix only)
    This will compile all the modules currently configured. The 'lib' and 'modules' targets together are needed to build a working copy of the library, without documentation or programs.
  • 'install'
    Copies the current library version (one of optimised, debugging, or profiling, selected by the above environment variables), into your compiler lib directory, recompiling it as required, and installs the Allegro headers.
  • 'install-lib' (Unix only)
    You can use this to install the library and the modules only, without documentation or programs. Use the 'install' target to install everything.
  • 'installall' (non-Unix only)
    Copies all three library versions (optimised, debugging, and profiling), into your compiler lib directory, recompiling them as required, and installs the Allegro headers.
  • 'uninstall'
    Removes the Allegro library and headers from your compiler directories.
  • 'docs'
    Converts the documentation files from the ._tx sources.
  • 'chm-docs' (Windows only)
    Creates a compiled HTML file from the previously generated html output. This is not a default target, since you need Microsoft's HTML compiler (http://go.microsoft.com/fwlink/?LinkId=14188), and it has to be installed somewhere in your PATH. Also, this only works if you use '@multiplefiles' (see the top of docs/src/allegro._tx).
  • 'docs-dvi' (Unix only)
    Creates the allegro.dvi device independent documentation file. This is not a default target, since you need the texi2dvi tool to create it. The generated file is especially prepared to be printed on paper.
  • 'docs-ps' or 'docs-gzipped-ps' or 'docs-bzipped-ps' (Unix only)
    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.
  • 'docs-pdf' (Unix only)
    Creates a PDF file. This is not a default target, since you need the texi2pdf tool to create it. The generated file is especially prepared to be printed on paper, and it also has hyperlinks.
  • 'docs-devhelp' (Unix only)
    Creates normal HTML documentation with an additional xml index file which can be used by tools like Devhelp (http://www.devhelp.net/) to show context sensitive help within any editor using Devhelp, like for example http://anjuta.sourceforge.net/. The Allegro 'book' will be created in `docs/devhelp/allegro.devhelp', you have to install it manually.
  • 'install-man' (Unix and Mac OS X only)
    Generates Unix man pages for each Allegro function or variable and installs them.
  • 'install-gzipped-man' or 'install-bzipped-man' (Unix only)
    Like install-man, but also compresses the manual pages after installing them (run only one of these).
  • 'uninstall-man' (Unix)
    Uninstalls any man pages previously installed with 'install-man', 'install-gzipped-man', or 'install-bzipped-man'.
  • 'install-info' or 'install-gzipped-info' or 'install-bzipped-info' (Unix only)
    Converts the documentation to Info format and installs it. The second and third targets compress the info file after installing it (run only one of them).
  • 'uninstall-info' (Unix only)
    Uninstalls any man pages previously installed with 'install-info', 'install-gzipped-info', or 'install-bzipped-info'.
  • 'clean'
    Removes generated object and library files, either to recover disk space or to force a complete rebuild the next time you run make. This target is designed so that if you run a "make install" followed by "make clean", you will still have a functional version of Allegro.
  • 'distclean'
    Like "make clean", but more so. This removes all the executable files and the documentation, leaving you with only the same files that are included when you unzip a new Allegro distribution.
  • 'veryclean'
    Use with extreme caution! This target deletes absolutely all generated files, including some that may be non-trivial to recreate. After you run "make veryclean", a simple rebuild will not work: at the very least you will have to run "make depend", and perhaps also fixdll.bat if you are using the Windows library. These targets make use of non-standard tools like SED, so unless you know what you are doing and have all this stuff installed, you should not use them.
  • 'compress' (DJGPP, MinGW and MSVC only)
    Uses the DJP or UPX executable compressors (whichever you have installed) to compress the example executables and utility programs, which can recover a significant amount of disk space.
  • 'depend'
    Regenerates the dependency files (obj/*/makefile.dep). You need to run this after "make veryclean", or whenever you add new headers to the Allegro sources.
@heading Available Allegro examples With Allegro comes quite a bunch of examples, which go from the simple introductory `Hello world' to more complicated programs featuring truecolor blending effects. This chapter describes these examples which you can find in the allegro/examples folder. You don't have to go through them in the same order as this documentation, but doing so you will learn the basic functions and avoid missing any important bit of information. @# The following text is generated with misc/genexamp.py, so read the source @# for the gory details. The basic idea is: don't touch these comment lines! @# start genexamp.py chunk @@Example @exhello @xref END_OF_MAIN, SCREEN_H, SCREEN_W, acquire_screen, allegro_error @xref allegro_init, allegro_message, clear_to_color, desktop_palette @xref font, install_keyboard, makecol, readkey, release_screen, screen @xref set_gfx_mode, set_palette, textout_centre_ex @shortdesc Simple graphical "hello world" program. This is a very simple program showing how to get into graphics mode and draw text onto the screen. @@Example @exmem @xref BITMAP, END_OF_MAIN, SCREEN_H, SCREEN_W, acquire_screen @xref allegro_error, allegro_init, allegro_message, blit, circle @xref clear_bitmap, create_bitmap, desktop_palette, destroy_bitmap @xref install_keyboard, palette_color, readkey, release_screen, screen @xref set_gfx_mode, set_palette @shortdesc Drawing onto memory bitmaps and then blitting them to the screen. 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. @@Example @expal @xref END_OF_MAIN, PALETTE, RGB, SCREEN_H, SCREEN_W, acquire_screen @xref allegro_error, allegro_init, allegro_message, black_palette @xref circlefill, install_keyboard, install_mouse, keypressed @xref release_screen, screen, set_gfx_mode, set_palette, show_mouse @shortdesc Palette effects and color cycling. 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. @@Example @expat @xref BITMAP, END_OF_MAIN, acquire_bitmap, allegro_error, allegro_init @xref allegro_message, bitmap_mask_color, blit, clear_to_color @xref create_bitmap, create_sub_bitmap, desktop_palette, destroy_bitmap @xref drawing_mode, font, install_keyboard, makecol, masked_blit @xref palette_color, readkey, rectfill, release_bitmap, screen @xref set_gfx_mode, set_palette, solid_mode, text_height, text_length @xref textout_ex @shortdesc Using patterned drawing modes and sub-bitmaps. This program demonstrates the use of patterned drawing and sub-bitmaps. @@Example @exflame @xref END_OF_MAIN, PALETTE, SCREEN_H, SCREEN_W, acquire_screen @xref allegro_error, allegro_init, allegro_message, bmp_read_line @xref bmp_unwrite_line, bmp_write_line, clear_keybuf, font, getpixel @xref install_keyboard, keypressed, line, makecol, putpixel @xref release_screen, screen, set_gfx_mode, set_palette, textout_ex @shortdesc How to write directly to video memory improving performance. 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. @@Example @exdbuf @xref BITMAP, END_OF_MAIN, SCREEN_H, SCREEN_W, acquire_screen @xref allegro_error, allegro_init, allegro_message, blit, circlefill @xref clear_to_color, create_bitmap, desktop_palette, destroy_bitmap @xref font, install_timer, makecol, release_screen, retrace_count, screen @xref set_gfx_mode, set_palette, textprintf_ex @shortdesc How to use double buffering to avoid flicker. 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. @@Example @exflip @xref BITMAP, END_OF_MAIN, SCREEN_H, SCREEN_W, allegro_error @xref allegro_init, allegro_message, blit, circlefill, clear_to_color @xref create_bitmap, create_video_bitmap, desktop_palette, destroy_bitmap @xref font, install_timer, makecol, retrace_count, screen, set_gfx_mode @xref set_palette, show_video_bitmap, textprintf_ex @shortdesc Comparison of double buffering and page flipping. This program moves a circle across the screen, first with a double buffer and then using page flips. @@Example @exfixed @xref END_OF_MAIN, allegro_init, allegro_message, fixdiv, fixed, fixmul @xref fixsqrt, fixtof, ftofix, itofix @shortdesc Using fixed point maths. 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. @@Example @exfont @xref END_OF_MAIN, FONT, SCREEN_H, SCREEN_W, acquire_screen @xref allegro_error, allegro_init, allegro_message, clear_to_color @xref desktop_palette, destroy_font, extract_font_range, font @xref install_keyboard, load_font, makecol, merge_fonts, readkey @xref release_screen, screen, set_gfx_mode, set_palette @xref textout_centre_ex This is a very simple program showing how to load and manipulate fonts. @@Example @exmouse @xref BITMAP, END_OF_MAIN, SCREEN_H, SCREEN_W, acquire_screen @xref allegro_error, allegro_init, allegro_message, bitmap_mask_color @xref circle, clear_keybuf, clear_to_color, create_bitmap @xref desktop_palette, destroy_bitmap, font, get_mouse_mickeys @xref install_keyboard, install_mouse, install_timer, key, keypressed @xref makecol, mouse_b, mouse_x, mouse_y, mouse_z, palette_color @xref poll_mouse, readkey, release_screen, screen, set_gfx_mode @xref set_mouse_sprite, set_mouse_sprite_focus, set_palette, show_mouse @xref textout_centre_ex, textout_ex, textprintf_centre_ex, textprintf_ex @xref vsync @shortdesc Getting input from the mouse. 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. @@Example @extimer @xref END_OF_FUNCTION, END_OF_MAIN, LOCK_FUNCTION, LOCK_VARIABLE @xref SCREEN_W, allegro_error, allegro_init, allegro_message @xref clear_to_color, desktop_palette, font, install_int, install_int_ex @xref install_keyboard, install_timer, key, keypressed, makecol, readkey @xref rest, screen, set_gfx_mode, set_palette, textprintf_centre_ex @shortdesc Using the timer (delays and interrupts). 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. @@Example @exkeys @xref END_OF_FUNCTION, END_OF_MAIN, LOCK_FUNCTION, SCREEN_H, SCREEN_W @xref acquire_screen, allegro_error, allegro_init, allegro_message, blit @xref clear_keybuf, clear_to_color, desktop_palette, font @xref install_keyboard, key, key_shifts, keyboard_lowlevel_callback @xref keypressed, makecol, readkey, rectfill, release_screen, rest @xref scancode_to_name, screen, set_gfx_mode, set_palette @xref textprintf_centre_ex, textprintf_ex, ureadkey, usprintf, ustrzncpy @shortdesc How to get input from the keyboard in different ways. 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. @@Example @exjoy @xref BITMAP, END_OF_MAIN, SCREEN_H, SCREEN_W, allegro_error @xref allegro_init, allegro_message, blit, calibrate_joystick @xref calibrate_joystick_name, circle, clear_bitmap, clear_keybuf @xref create_bitmap, default_palette, destroy_bitmap, drawing_mode, font @xref install_joystick, install_keyboard, joy, key, keypressed @xref num_joysticks, palette_color, poll_joystick, putpixel, readkey @xref screen, set_gfx_mode, set_palette, textout_centre_ex @xref textprintf_centre_ex, textprintf_ex @shortdesc Detecting, calibrating and using joystick input. 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). @@Example @exsample @xref END_OF_MAIN, SAMPLE, SCREEN_H, SCREEN_W, adjust_sample @xref allegro_error, allegro_init, allegro_message, clear_to_color @xref desktop_palette, destroy_sample, font, install_keyboard @xref install_sound, install_timer, key, load_sample, makecol @xref play_sample, poll_keyboard, rest, screen, set_gfx_mode, set_palette @xref textprintf_centre_ex @shortdesc Playing digital samples. 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. @@Example @exmidi @xref END_OF_MAIN, MIDI, SCREEN_H, SCREEN_W, allegro_error, allegro_init @xref allegro_message, clear_to_color, desktop_palette, destroy_midi @xref font, get_filename, get_midi_length, install_keyboard @xref install_sound, install_timer, key, keypressed, load_midi, makecol @xref midi_pause, midi_pos, midi_resume, midi_time, play_midi, readkey @xref rectfill, rest, screen, set_display_switch_mode, set_gfx_mode @xref set_palette, text_height, text_length, textprintf_centre_ex @shortdesc Playing MIDI music. This program demonstrates how to play MIDI files. @@Example @exgui @xref DATAFILE, DIALOG, END_OF_MAIN, MENU, active_menu, alert @xref allegro_error, allegro_init, allegro_message, d_bitmap_proc @xref d_box_proc, d_button_proc, d_check_proc, d_clear_proc, d_ctext_proc @xref d_edit_proc, d_icon_proc, d_keyboard_proc, d_list_proc, d_menu_proc @xref d_radio_proc, d_rtext_proc, d_shadow_box_proc, d_slider_proc @xref d_text_list_proc, d_text_proc, d_textbox_proc, d_yield_proc @xref do_dialog, gui_bg_color, gui_fg_color, gui_mg_color @xref install_keyboard, install_mouse, install_timer, key, load_datafile @xref makecol, position_dialog, replace_filename, screen @xref set_dialog_color, set_gfx_mode, set_palette, unload_datafile @xref ustrtok, ustrzcat, ustrzcpy, uszprintf @shortdesc Using the GUI routines. 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. @@Example @excustom @xref BITMAP, DATAFILE, DIALOG, END_OF_MAIN, FONT, allegro_error @xref allegro_init, allegro_message, blit, circle, circlefill @xref clear_to_color, create_bitmap, d_button_proc, d_check_proc @xref d_clear_proc, d_edit_proc, desktop_palette, destroy_bitmap @xref do_dialog, fixcos, fixed, fixmul, fixsin, fixtoi, font @xref install_keyboard, install_mouse, install_timer, itofix, key, line @xref load_datafile, makecol, object_message, replace_filename, screen @xref set_gfx_mode, set_palette, unload_datafile @shortdesc Creating custom GUI objects. 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. @@Example @exunicod @xref BITMAP, DATAFILE, END_OF_MAIN, FONT, SCREEN_H, SCREEN_W @xref allegro_error, allegro_init, allegro_message, blit, clear_to_color @xref create_bitmap, font, install_int_ex, install_keyboard @xref install_timer, keypressed, load_datafile, replace_filename, rest @xref screen, set_gfx_mode, set_uformat, set_window_title, text_height @xref text_length, textout_ex, uconvert_ascii, unload_datafile, ustrcat @xref ustrcpy, ustrsize, ustrsizez @shortdesc Using Unicode string functions. 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. @@Example @exbitmap @xref BITMAP, END_OF_MAIN, PALETTE, SCREEN_H, SCREEN_W, allegro_error @xref allegro_init, allegro_message, blit, destroy_bitmap @xref install_keyboard, load_bitmap, readkey, screen, set_gfx_mode @xref set_palette @shortdesc Loading and displaying PCX and BMP files. 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. @@Example @exscale @xref BITMAP, END_OF_MAIN, PALETTE, SCREEN_H, SCREEN_W, allegro_error @xref allegro_init, allegro_message, blit, destroy_bitmap @xref install_keyboard, keypressed, load_pcx, replace_filename, screen @xref set_gfx_mode, set_palette, stretch_blit, vsync @shortdesc Loading PCX files and bitmap stretching. 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(). @@Example @exconfig @xref BITMAP, END_OF_MAIN, RGB, SCREEN_H, SCREEN_W, allegro_init @xref allegro_message, blit, clear_bitmap, font, get_config_argv @xref get_config_int, get_config_string, install_keyboard, line @xref load_bitmap, makecol, pop_config_state, push_config_state, readkey @xref screen, set_color_depth, set_config_file, set_gfx_mode, set_palette @xref stretch_blit, textout_centre_ex, textprintf_centre_ex, ustrdup @xref ustricmp @shortdesc Using the configuration routines. 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. @@Example @exdata @xref DATAFILE, END_OF_MAIN, allegro_error, allegro_init, allegro_message @xref blit, font, install_keyboard, load_datafile, makecol, readkey @xref replace_filename, screen, set_color_conversion, set_gfx_mode @xref set_palette, textout_ex, unload_datafile @shortdesc Accessing the contents of datafiles. 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. @@Example @exsprite @xref BITMAP, DATAFILE, END_OF_FUNCTION, END_OF_MAIN, LOCK_FUNCTION @xref LOCK_VARIABLE, SCREEN_H, SCREEN_W, allegro_error, allegro_init @xref allegro_message, blit, circle, clear_bitmap, clear_keybuf @xref create_bitmap, destroy_bitmap, draw_sprite, draw_sprite_h_flip @xref draw_sprite_v_flip, draw_sprite_vh_flip, fixed, font, hline @xref install_int_ex, install_keyboard, install_sound, install_timer @xref itofix, key, keypressed, load_datafile, makecol, palette_color @xref pivot_sprite, pivot_sprite_v_flip, play_sample, rectfill @xref replace_filename, rest, screen, set_gfx_mode, set_palette @xref text_height, textout_centre_ex, unload_datafile, vsync @shortdesc Datafiles access and sprite animation. 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. @@Example @exexedat @xref DATAFILE, END_OF_MAIN, allegro_error, allegro_init, allegro_message @xref blit, font, install_keyboard, line, load_datafile, makecol, readkey @xref screen, set_color_conversion, set_gfx_mode, set_palette, textout_ex @xref unload_datafile @shortdesc Appending datafiles onto your executable. 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. @@Example @extrans @xref BITMAP, COLOR_MAP, END_OF_MAIN, PALETTE, RGB, RGB_MAP, SCREEN_H @xref SCREEN_W, allegro_error, allegro_init, allegro_message @xref bitmap_color_depth, blit, circlefill, clear_bitmap, clear_keybuf @xref color_map, create_bitmap, create_bitmap_ex, create_light_table @xref create_rgb_table, create_trans_table, destroy_bitmap @xref draw_trans_sprite, drawing_mode, install_keyboard, install_mouse @xref install_timer, keypressed, load_bitmap, mouse_x, mouse_y @xref poll_mouse, rectfill, replace_filename, rgb_map, screen @xref set_alpha_blender, set_gfx_mode, set_palette, set_trans_blender @xref set_write_alpha_blender, stretch_blit @shortdesc Lighting and translucency effects. 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. @@Example @extruec @xref END_OF_MAIN, PALETTE, RGB, SCREEN_H, SCREEN_W, acquire_screen @xref allegro_init, clear_to_color, font, generate_332_palette @xref install_keyboard, key, makecol, readkey, release_screen, screen @xref set_color_depth, set_gfx_mode, set_palette, textout_centre_ex @xref textout_ex, textprintf_ex, vline @shortdesc Truecolor pixel format conversions. 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. @@Example @excolmap @xref BITMAP, COLOR_MAP, END_OF_MAIN, PALETTE, RGB, RGB_MAP, SCREEN_H @xref SCREEN_W, allegro_error, allegro_init, allegro_message, blit @xref circlefill, clear_keybuf, color_map, create_bitmap @xref create_color_table, create_rgb_table, destroy_bitmap, drawing_mode @xref font, generate_332_palette, install_keyboard, keypressed, makecol @xref rectfill, rgb_map, screen, set_gfx_mode, set_palette @xref textout_centre_ex, vsync @shortdesc Creating graphical effects with color mapping tables. 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. @@Example @exrgbhsv @xref BITMAP, DIALOG, END_OF_MAIN, PALETTE, RGB, RGB_MAP, allegro_error @xref allegro_init, allegro_message, clear_to_color, create_bitmap_ex @xref create_rgb_table, d_bitmap_proc, d_box_proc, d_slider_proc @xref d_text_proc, destroy_bitmap, do_dialog, font, generate_332_palette @xref get_color_depth, hsv_to_rgb, install_keyboard, install_mouse @xref install_timer, key, makecol, makecol32, makecol8, object_message @xref rgb_map, rgb_to_hsv, screen, set_color, set_color_depth @xref set_gfx_mode, set_palette, textout_ex, vline, vsync @shortdesc RGB <-> HSV colorspace conversions. 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. @@Example @exshade @xref BITMAP, COLOR_MAP, END_OF_MAIN, PALETTE, RGB, RGB_MAP, SCREEN_H @xref SCREEN_W, allegro_error, allegro_init, allegro_message, blit @xref clear_bitmap, color_map, create_bitmap, create_light_table @xref create_rgb_table, destroy_bitmap, draw_gouraud_sprite, font @xref install_keyboard, install_mouse, keypressed, line, load_bitmap @xref mouse_x, mouse_y, palette_color, poll_mouse, replace_filename @xref rgb_map, screen, set_gfx_mode, set_palette, set_trans_blender @xref show_mouse, textout_ex @shortdesc Gouraud shaded sprites. 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. @@Example @exblend @xref BITMAP, END_OF_MAIN, PALETTE, SCREEN_H, SCREEN_W, allegro_error @xref allegro_init, allegro_message, blit, circle, clear_bitmap @xref clear_keybuf, create_bitmap, destroy_bitmap, draw_lit_sprite @xref draw_trans_sprite, fixcos, fixsin, fixtoi, font, install_keyboard @xref install_timer, itofix, keypressed, load_bitmap, makecol @xref replace_filename, retrace_count, screen, set_color_conversion @xref set_color_depth, set_gfx_mode, set_trans_blender, textprintf_ex @xref vsync @shortdesc Using translucency in truecolor modes. 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. @@Example @exxfade @xref BITMAP, END_OF_MAIN, PALETTE, SCREEN_H, SCREEN_W, allegro_error @xref allegro_exit, allegro_init, allegro_message, blit, create_bitmap @xref destroy_bitmap, draw_trans_sprite, install_keyboard, keypressed @xref line, load_bitmap, readkey, screen, set_color_conversion @xref set_color_depth, set_gfx_mode, set_palette, set_trans_blender @xref vsync @shortdesc Truecolor image loading and fades. 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. @@Example @exalpha @xref BITMAP, END_OF_MAIN, SCREEN_H, SCREEN_W, allegro_error @xref allegro_init, allegro_message, blit, clear_keybuf, create_bitmap @xref destroy_bitmap, draw_trans_sprite, drawing_mode, font, getb, getg @xref getpixel, getr, install_keyboard, install_mouse, install_timer @xref keypressed, load_bitmap, makecol, mouse_x, mouse_y, putpixel @xref rectfill, replace_filename, screen, set_alpha_blender @xref set_color_conversion, set_color_depth, set_gfx_mode @xref set_multiply_blender, set_write_alpha_blender, solid_mode @xref stretch_blit, textprintf_ex @shortdesc Creating and using 32 bit RGBA sprites. 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. @@Example @exlights @xref BITMAP, COLOR_MAP, END_OF_MAIN, PALETTE, SCREEN_H, SCREEN_W @xref allegro_error, allegro_init, allegro_message, bitmap_color_depth @xref blit, bmp_unwrite_line, bmp_write_line, circlefill, clear_bitmap @xref clear_keybuf, color_map, create_bitmap_ex, destroy_bitmap @xref draw_trans_sprite, fixatan2, fixsqrt, fixtoi, getb_depth @xref getg_depth, getpixel, getr_depth, hsv_to_rgb, install_keyboard @xref install_mouse, install_timer, itofix, key, keypressed, line @xref load_bitmap, makecol, mouse_x, mouse_y, poll_mouse @xref replace_filename, retrace_count, screen, select_palette @xref set_color_conversion, set_color_depth, set_gfx_mode @shortdesc One way to do colored lighting effects in a hicolor video mode. 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 :-) @@Example @ex3d @xref BITMAP, COLOR_MAP, END_OF_MAIN, MATRIX, PALETTE, POLYTYPE_ATEX @xref POLYTYPE_ATEX_LIT, POLYTYPE_ATEX_MASK, POLYTYPE_ATEX_MASK_LIT @xref POLYTYPE_ATEX_MASK_TRANS, POLYTYPE_ATEX_TRANS, POLYTYPE_FLAT @xref POLYTYPE_GCOL, POLYTYPE_GRGB, POLYTYPE_PTEX, POLYTYPE_PTEX_LIT @xref POLYTYPE_PTEX_MASK, POLYTYPE_PTEX_MASK_LIT @xref POLYTYPE_PTEX_MASK_TRANS, POLYTYPE_PTEX_TRANS, RGB, RGB_MAP @xref SCREEN_H, SCREEN_W, V3D, allegro_error, allegro_exit, allegro_init @xref allegro_message, apply_matrix, bitmap_color_depth @xref bitmap_mask_color, blit, clear_bitmap, clear_to_color, color_map @xref create_bitmap, create_light_table, create_rgb_table @xref create_trans_table, desktop_palette, destroy_bitmap, fixed, fixtoi @xref font, get_transformation_matrix, gfx_mode_select_ex @xref install_keyboard, install_mouse, install_timer, itofix, key @xref keypressed, line, palette_color, persp_project, polygon_z_normal @xref quad3d, readkey, rect, retrace_count, rgb_map, screen @xref set_color_depth, set_gfx_mode, set_palette, set_projection_viewport @xref set_trans_blender, textout_ex, textprintf_ex, vsync @shortdesc 3d 'bouncy cubes' demo. 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. @@Example @excamera @xref BITMAP, END_OF_MAIN, MATRIX_f, POLYTYPE_FLAT, SCREEN_H, SCREEN_W @xref V3D_f, allegro_error, allegro_init, allegro_message, apply_matrix_f @xref blit, clear_to_color, clip3d_f, create_bitmap, desktop_palette @xref destroy_bitmap, font, get_camera_matrix_f @xref get_vector_rotation_matrix_f, install_int_ex, install_keyboard @xref install_timer, key, key_shifts, makecol, persp_project_f @xref poll_keyboard, polygon, polygon3d_f, rect, screen, set_clip_rect @xref set_gfx_mode, set_palette, set_projection_viewport, textprintf_ex @xref vsync @shortdesc Viewing a 3d world from an arbitrary camera position. 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. @@Example @exquat @xref BITMAP, END_OF_MAIN, MATRIX_f, QUAT, acquire_bitmap, allegro_error @xref allegro_init, allegro_message, apply_matrix_f, blit, circle @xref clear_keybuf, clear_to_color, create_bitmap, desktop_palette @xref destroy_bitmap, font, get_camera_matrix_f, get_rotation_matrix @xref get_rotation_matrix_f, get_rotation_quat, install_keyboard @xref keypressed, line, matrix_mul_f, palette_color, persp_project_f @xref quat_interpolate, quat_to_matrix, readkey, release_bitmap, rest @xref screen, set_gfx_mode, set_palette, set_projection_viewport @xref textout_ex @shortdesc A comparison between euler angles and quaternions. 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. @@Example @exstars @xref BITMAP, END_OF_MAIN, MATRIX, PALETTE, SCREEN_H, SCREEN_W @xref allegro_error, allegro_init, allegro_message, apply_matrix, blit @xref clear_bitmap, create_bitmap, cross_product, destroy_bitmap @xref dot_product, fixed, fixmul, fixtof, fixtoi, font @xref get_rotation_matrix, get_transformation_matrix @xref get_translation_matrix, install_keyboard, install_timer, itofix @xref key, normalize_vector, palette_color, persp_project, poll_keyboard @xref putpixel, rectfill, screen, set_gfx_mode, set_palette @xref set_projection_viewport, textout_centre_ex, textprintf_centre_ex @xref triangle, vsync @shortdesc 3d starfield and lightsourced spaceship. This program draws a 3D starfield (depth-cued) and a polygon starship (controllable with the keyboard cursor keys), using the Allegro math functions. @@Example @exscn3d @xref BITMAP, END_OF_FUNCTION, END_OF_MAIN, LOCK_FUNCTION, LOCK_VARIABLE @xref MATRIX_f, PALETTE, POLYTYPE_GCOL, SCREEN_H, SCREEN_W, V3D_f @xref allegro_error, allegro_exit, allegro_init, allegro_message @xref apply_matrix_f, bitmap_color_depth, blit, clear_bitmap, clear_scene @xref clip3d_f, create_bitmap, create_scene, desktop_palette @xref destroy_bitmap, destroy_scene, font, get_rotation_matrix_f @xref get_translation_matrix_f, gfx_mode_select_ex, install_int @xref install_keyboard, install_mouse, install_timer, key, matrix_mul_f @xref palette_color, persp_project_f, polygon_z_normal_f, render_scene @xref scene_polygon3d_f, screen, set_color_depth, set_gfx_mode @xref set_palette, set_projection_viewport, textprintf_ex @shortdesc Using the 3d scene functions. 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. @@Example @exzbuf @xref BITMAP, END_OF_FUNCTION, END_OF_MAIN, LOCK_FUNCTION, LOCK_VARIABLE @xref MATRIX_f, PALETTE, POLYTYPE_GCOL, SCREEN_H, SCREEN_W, V3D_f @xref ZBUFFER, allegro_error, allegro_exit, allegro_init, allegro_message @xref apply_matrix_f, bitmap_color_depth, blit, clear_bitmap @xref clear_zbuffer, create_bitmap, create_zbuffer, desktop_palette @xref destroy_bitmap, destroy_zbuffer, font, get_transformation_matrix_f @xref gfx_mode_select_ex, install_int, install_keyboard, install_mouse @xref install_timer, keypressed, palette_color, persp_project_f @xref polygon_z_normal_f, quad3d_f, readkey, screen, set_color_depth @xref set_gfx_mode, set_palette, set_projection_viewport, set_zbuffer @xref textprintf_ex, vsync @shortdesc Z-buffered polygons demo. 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. @@Example @exscroll @xref BITMAP, END_OF_MAIN, RGB, SCREEN_H, SCREEN_W, acquire_bitmap @xref allegro_init, allegro_message, clear_keybuf, create_sub_bitmap @xref desktop_palette, destroy_bitmap, install_keyboard, keypressed @xref rectfill, release_bitmap, screen, scroll_screen, set_color @xref set_gfx_mode, set_palette, vline @shortdesc Mode-X hardware scrolling and split screens. This program demonstrates how to use hardware scrolling. The scrolling should work on anything that supports virtual screens larger than the physical screen. @@Example @ex3buf @xref BITMAP, END_OF_MAIN, SCREEN_H, SCREEN_W, acquire_bitmap @xref allegro_error, allegro_init, allegro_message, clear_bitmap @xref clear_keybuf, create_video_bitmap, desktop_palette, destroy_bitmap @xref enable_triple_buffer, fixcos, fixed, fixmul, fixsin, fixtoi, font @xref gfx_capabilities, install_keyboard, install_mouse, install_timer @xref itofix, keypressed, poll_scroll, release_bitmap @xref request_video_bitmap, screen, set_gfx_mode, set_palette, textout_ex @xref triangle, ustrzcpy @shortdesc Mode-X triple buffering and retrace interrupt simulation. 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. @@Example @ex12bit @xref BITMAP, END_OF_MAIN, MATRIX, PALETTE, RGB, allegro_error @xref allegro_init, allegro_message, apply_matrix, blit, circle @xref clear_bitmap, clear_keybuf, clear_to_color, create_bitmap @xref create_bitmap_ex, destroy_bitmap, ellipsefill, fade_out, fixcos @xref fixed, fixsin, fixtoi, font, get_rotation_matrix, getpixel @xref install_keyboard, itofix, keypressed, line, makecol, masked_blit @xref putpixel, screen, set_clip_rect, set_color, set_gfx_mode @xref set_palette, text_height, text_length, textout_ex, textprintf_ex @shortdesc How to fake a 12-bit truecolor mode on an 8-bit card. 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:
  • The horizontal width is halved, so you get resolutions like 320x480, 400x600, and 512x768.
  • Because each dot is spread over two actual pixels, the display will be darker than in a normal video mode.
  • Any bitmap data will obviously need converting to the correct 12 bit format: regular 15 or 16 bit images won't display correctly...
  • Although this works like a truecolor mode, it is actually using a 256 color palette, so palette fades are still possible!
  • This code only works in linear screen modes (don't try Mode-X).
@@Example @exaccel @xref BITMAP, END_OF_MAIN, PALETTE, SCREEN_H, SCREEN_W, acquire_bitmap @xref allegro_error, allegro_init, allegro_message, blit, clear_bitmap @xref create_video_bitmap, destroy_bitmap, font, gfx_capabilities @xref install_keyboard, install_timer, keypressed, load_bitmap, readkey @xref release_bitmap, replace_filename, screen, set_gfx_mode, set_palette @xref show_video_bitmap, textout_ex, textprintf_ex @shortdesc Using offscreen video memory to store source graphics for VBE/AF. 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. @@Example @exspline @xref END_OF_MAIN, SCREEN_W, acquire_screen, alert, allegro_error @xref allegro_init, allegro_message, calc_spline, circlefill @xref clear_keybuf, clear_to_color, desktop_palette, fixatan2, fixcos @xref fixed, fixmul, fixsin, fixsqrt, fixtof, fixtoi, font, ftofix @xref install_keyboard, install_mouse, install_timer, itofix, key @xref keypressed, line, makecol, mouse_b, mouse_x, mouse_y, palette_color @xref poll_mouse, readkey, release_screen, screen, set_gfx_mode @xref set_palette, show_mouse, spline, textout_centre_ex @xref textprintf_centre_ex, textprintf_ex, vsync, xor_mode @shortdesc Constructing smooth movement paths from spline curves. 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. @@Example @exsyscur @xref END_OF_MAIN, SCREEN_H, SCREEN_W, allegro_error, allegro_init @xref allegro_message, clear_to_color, enable_hardware_cursor, font @xref gfx_capabilities, install_keyboard, install_mouse, install_timer @xref makecol, readkey, screen, select_mouse_cursor, set_gfx_mode @xref show_mouse, text_height, textprintf_centre_ex This program demonstrates the use of hardware accelerated mouse cursors. @@Example @exupdate @xref BITMAP, END_OF_FUNCTION, END_OF_MAIN, LOCK_FUNCTION, LOCK_VARIABLE @xref PALETTE, SCREEN_H, SCREEN_W, acquire_bitmap, allegro_error @xref allegro_init, allegro_message, bitmap_color_depth, blit @xref clear_bitmap, create_bitmap, create_system_bitmap @xref create_video_bitmap, desktop_palette, destroy_bitmap @xref enable_triple_buffer, fixcos, fixed, fixmul, fixsin, fixtoi, font @xref ftofix, generate_332_palette, gfx_capabilities, gfx_mode_select_ex @xref install_int_ex, install_keyboard, install_mouse, install_timer @xref keypressed, line, makecol, poll_scroll, release_bitmap @xref request_video_bitmap, screen, set_color_depth, set_gfx_mode @xref set_palette, show_video_bitmap, textout_ex, textprintf_ex, triangle @xref vsync, xor_mode @shortdesc Supporting different screen update methods in a single program. 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. @@Example @exswitch @xref BITMAP, END_OF_FUNCTION, END_OF_MAIN, LOCK_FUNCTION, LOCK_VARIABLE @xref PALETTE, SCREEN_H, SCREEN_W, acquire_bitmap, acquire_screen @xref allegro_error, allegro_exit, allegro_init, allegro_message @xref bitmap_color_depth, blit, clear_to_color, create_sub_bitmap @xref desktop_palette, destroy_bitmap, font, get_display_switch_mode @xref gfx_mode_select_ex, install_int, install_keyboard, install_mouse @xref install_timer, keypressed, makecol, palette_color, putpixel @xref readkey, rectfill, release_bitmap, release_screen, screen @xref set_color_depth, set_display_switch_callback @xref set_display_switch_mode, set_gfx_mode, set_palette @xref textout_centre_ex, textprintf_centre_ex @shortdesc Controlling the console switch mode for background running. 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. @@Example @exstream @xref AUDIOSTREAM, END_OF_MAIN, SCREEN_H, SCREEN_W, allegro_error @xref allegro_init, allegro_message, clear_to_color, desktop_palette @xref font, free_audio_stream_buffer, get_audio_stream_buffer @xref install_keyboard, install_sound, install_timer, keypressed, makecol @xref play_audio_stream, readkey, screen, set_gfx_mode, set_palette @xref stop_audio_stream, textprintf_centre_ex, voice_start, voice_stop @shortdesc Playing audio streams. 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. @@Example @expackf @xref ASSERT, BITMAP, END_OF_MAIN, PACKFILE, PACKFILE_VTABLE, SCREEN_H @xref SCREEN_W, alert, allegro_error, allegro_init, allegro_message, blit @xref clear_bitmap, destroy_bitmap, file_size, font, install_keyboard @xref key, load_bmp_pf, load_pcx, load_pcx_pf, load_tga_pf, pack_fclose @xref pack_fopen, pack_fopen_vtable, pack_fread, pack_fseek, readkey @xref save_bmp_pf, save_tga_pf, screen, set_color_depth, set_gfx_mode @xref text_height, textprintf_centre_ex, textprintf_ex @shortdesc Using custom PACKFILE vtables. 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. @# end genexamp.py chunk @externalfile changes Changes since previous versions @externalfile thanks Contributors: The Hall of Fame @externalfile faq Frequently asked questions (FAQ) @externalfile mistakes Common mistakes @externalfile help Help: what to do when your Allegro program doesn't work @externalfile api API compatibility information @externalfile abi ABI compatibility information @externalfile ahack The Allegro hacker's guide @externalfile const Allegro `const'-correctness @externalfile packfile Packfile format information @externalfile datafile Datafile format information @externalfile license License and Disclaimer @chapter Tools @!html @headingnocontent Additional programs included with Allegro Allegro comes with several useful utility programs. They are currently documented separately. Refer to the HTML documentation (including CHM and devhelp) of Allegro which includes all the documents, or the single plain text versions of these documents (makedoc.txt, grabber.txt, dat.txt, dat2s.txt, dat2c.txt). @html @externalfile makedoc makedoc - Generate documentation in various formats @externalfile grabber grabber - Create datafiles @externalfile dat dat - Manipulate datafiles from the commandline @externalfile dat2s dat2s - Compile datafiles into assembler code @externalfile dat2c dat2c - Compile datafiles into C code @endchapter @headingnocontent Community Allegro was originally created by Shawn Hargreaves. Published sometime between 1994 and 1995, it was just a simple lib for himself. At that time, many people were switching from Borland C to DJGPP and looking for a decent graphics library. Allegro was the first reasonably complete one to show up, so it attracted enough interest to keep growing, and a little contribution here, and some more encouragement there made it all light up like fire. Some time after the latest 3.x stable release, though, Shawn was flooded with Allegro tasks and Real Life (TM) work, and chose the latter to focus his energies on. While this somehow stalled Allegro's development, it also attracted a lot of people who wanted Allegro to live longer. Also, by that time other people had started to work on Windows and Unix ports of Allegro, which suggested that Allegro had the potential to survive its only decaying main platform (DOS). The current situation is that Shawn still keeps watching Allegro's progress from time to time, but is not involved with development any more. The community that grew over the years when Shawn was in charge of everything has stepped forward to continue improving Allegro. Transformed into a meritocratic community, users keep sending bug reports to the mailing lists, developers around the world keep sending patches to fix them, and a few carefully chosen have write access to the 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 :-) @headingnocontent Conclusion All good things must come to an end. Writing documentation is not a good thing, though, and that means it goes on for ever. There is always something we've forgotten to explain, or some essential detail we've left out, but for now you will have to make do with this. Feel free to ask if you can't figure something out. Enjoy. We hope you find some of this stuff useful. By Shawn Hargreaves and the Allegro development team. http://alleg.sourceforge.net/ @!text @$@ifinfo @headingnocontent Index @index @$@end ifinfo @$@contents @$@bye @text