Allegro.pas

Contents

Introduction

Allegro.pas is a wrapper to allow Pascal compilers (such as Free Pascal or Delphi) to use the Allegro library.

Read section "How to use Allegro.pas" for a description of the main module of the library.

There are a few add-ons that adds some functionality to the original Allegro. They came with their own documentation and makefiles at the addons directory.

There are a wiki at Allegro.pas website (http://allegro-pas.sf.net/) which may include additional documentation and tutorials.

If you want to collaborate please join the main Allegro.pas mailing list or ask at Pascal Game Development forum. Read section "Contact info".

How to use Allegro.pas

The best way to start with Allegro.pas is to study the sources at examples and look for detailed description of procedures and functions at the documentation. That examples are fully commented and should be easy to understand.

Anyway, here you have a brief description of the Allegro library:

Initialization and finalization

You must call either al_install or al_init before doing anything other than using the UNICODE routines.

On the other hand, you can call al_exit before to finish the program to close Allegro. You don't need to do it because it will be called automaticly by the FINALIZATION section of Allegro.pas but some times it's neccessary to call it before.

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, using the al_set_uformat procedure. This setting affects all aspects of the system: whenever you see a function that returns a STRING or AL_STRptr type, or that takes the same as an argument, that text will be in whatever format you have told Allegro to use.

By default, Allegro uses UTF-8 encoded text (AL_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. The textconv program is included with the original Allegro release.

If you prefer to use some other text format, you can set Allegro to work with normal 8-bit ASCII (AL_U_ASCII), or 16-bit Unicode (AL_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 AL_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 AL_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 al_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 al_set_ucodepage function.

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

Note: While UNICODE is almost supported by Free Pascal and Lazarus, you might have bad results using it with Allegro.pas. There will be a new version of Free Pascal (3.0) that will improve the UNICODE support. I hopw I'll be able to update Allegro.pas.

Configuration routines

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

Note that variable and section names cannot contain spaces.

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

If you don't like this approach, you can specify any filename you like with using procedure al_set_config_file, or use a block of binary configuration data with al_set_config_data provided by your program (which could for example be loaded from a datafile).

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

Timer routines

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

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

See also al_install_int

Keyboard routines

The Allegro keyboard handler provides both buffered input (al_readkey) and a set of flags storing the current state of each key (al_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).

Allegro.pas comes with a prepackaged keyboard.dat file at the resources directory which you can put along with your binary. If this file is present, Allegro will be able to extract the keyboard mapping information stored there. However, the end user still needs to select which keyboard mapping to use. This can be accomplished through the keyboard variable of the system section in a standard allegro.cfg configuration file. Read section about configuration for more information about this.

See also al_install_keyboard

Joystick support

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.

See also al_install_joystick

Color

All the Allegro drawing functions use integer parameters to represent colors.

In 256-color mode the color 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 AL_RGB structure, which contains red, green and blue intensities in the VGA hardware format, ranging from 0-63. The full palette is an AL_PALETTE, a list of 256 AL_RGB values. You can set the palette using the al_set_palette procedure.

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 al_set_gfx_mode before using any of the color routines!

See also alvga alblend

Bitmaps

Once you have selected a graphics mode, you can draw things onto the display via the al_screen bitmap. All the Allegro graphics routines draw onto AL_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 al_screen bitmap which represents the video memory in your graphics card.

Allegro supports several different types of bitmaps:

  • The al_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 al_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 al_create_bitmap, al_load_bitmap, 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. 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. Are created by the al_create_sub_bitmap function.

  • Video memory bitmaps. These are created by the al_create_video_bitmap function, and are usually implemented as sub-bitmaps of the screen object. They must be destroyed by al_destroy_bitmap before any subsequent calls to al_set_gfx_mode.

  • System bitmaps. These are created by the al_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 AL_GFX_HW_SYS_TO_VRAM_BLIT and AL_GFX_HW_SYS_TO_VRAM_BLIT_MASKED flags in al_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, al_create_system_bitmap will function identically to al_create_bitmap. They must be destroyed by al_destroy_bitmap before any subsequent calls to al_set_gfx_mode.

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 al_set_mouse_sprite and al_show_mouse to define your own cursor and display it on the screen. You need to call al_scare_mouse/al_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 al_set_mouse_sprite and al_show_mouse (or al_show_os_cursor) to define your own cursor and display it on the screen. Not all graphics drivers are capable of this and some may only be able to display cursors up to a certain size. Allegro will fall back on its own cursor drawing if it cannot let the OS handle this. On some platforms, the hardware cursor is incompatible with al_get_mouse_mickeys and it is therefor disabled by default. In such cases you need to call al_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 al_select_mouse_cursor function to select the cursor shape to display. As with custom operating system cursors, you need to call al_enable_hardware_cursor before you can use this. Or you can use the low level al_show_os_cursor function.

Not all drivers will support all functionality.

Graphics modes initialization

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 unit, 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 runt-time library to communicate with the user, like calling WriteLn before setting a graphic mode or maybe GetLn 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 al_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.pas/examples/exhello.pp 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 al_create_system_bitmap, al_create_video_bitmap, al_show_video_bitmap, etc. These functions divide the memory of the video card in areas and switch between them, a feature supported on all platforms and video cards (given that they have enough memory for the screen resolutions you asked for).

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

The magic drivers you can use are: AL_GFX_AUTODETECT, AL_GFX_AUTODETECT_FULLSCREEN, AL_GFX_AUTODETECT_WINDOWED, AL_GFX_SAFE, AL_GFX_TEXT.

See also al_set_gfx_mode

Drawing primitives

Except for _al_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.

See also al_set_clip_rect al_drawing_mode

Text drawing

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

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, and can also import GRX or BIOS format font files.

See also al_load_font al_textout_ex

Bitting and sprite drawing

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 al_draw_sprite is called so rather than al_draw_bitmap partly because it indicates that it uses a masked drawing mode (if it existed, you could expect al_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 al_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 al_draw_sprite). A sprite is really just a bitmap graphic which is drawn onto the screen, but when you call it a sprite rather than a bitmap, this suggests it is a gameplay element that can move freely around the world rather than being a static part of the environment, and that it will be drawn in a masked overlay mode rather than as a solid rectangle (there is also a strong implication that a sprite will be animated by cycling through a number of frames, but that isn't always the case).

In recent years some people have started using "sprite" to refer to any character graphics, even if they are not in fact drawn as 2d bitmaps, eg. "this game uses 3d polygonal player sprites". This is a confusing misuse of the word (Doom uses sprites, Quake does not), but it does happen.

The origin of the term blit is also rather interesting. This was originally BitBlt, an abbreviation of BITmap BLock Transfer, which was a function designed (possibly) by the people at Xerox who did so much of the pioneering work on graphics display systems, and subsequently copied by virtually everybody doing computer graphics (the Microsoft Windows GDI still provides a BitBlt function with identical functionality to the original). This routine was a workhorse for all sorts of drawing operations, basically copying bitmap graphics from one place to another, but including a number of different ROP modes (Raster OPerations) for doing things like XOR, inverting pixels, etc. A whole family of related words grew up around the BitBlt function, but "blt" is impossible to speak (try saying "bltter" or "bltting" :-) so people added the vowel to make it easier to pronounce.

Therefore, the act of calling the BitBlt function came to be known as "doing a blit". The obvious next step was to rename the function itself to blit, which generally took place at the same time as people decided to simplify the original, removing the different ROP modes on the grounds that they aren't needed for games coding and don't work well with anything higher than monochrome images in any case. This leaves us with a function called blit, which is an abbreviation for "block transfer". A strong case could be made for calling this blot instead, but somehow that just doesn't sound the same!

Anyway, all the routines in this chapter are affected by the clipping rectangle of the destination bitmap.

See also al_blit

Run-length compressed 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 AL_RLE_SPRITE structure 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 al_draw_rle_sprite function, which is equivalent to using al_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'.

Sound and music 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 al_install_sound with the autodetection parameters and using the rest of the sound functions to play samples or music. In this situation, Allegro will handle the sound devices and mix the samples and/or music the best way it can.

However, sound hardware has a limitation on the number of samples it may play all at the same time (from now on, called hardware voices). When you exceed this limit, Allegro will cut off one of the samples being played and reproduce the new one. Depending on the type of sounds you are playing, how many of them you need at the same time and their nature (e.g: vital audio feedback to the user or useless "ping" when some shrapnel hits a rock in the scenery) you will want to specify more carefully how hardware voices are reserved and which samples have priority over others.

The hardware voice reservation phase has to be done before the call to al_install_sound, since it directly affects how Allegro talks to the sound drivers.

Allegro allows you to play MIDI files. MIDI files basically contain notes and the type of instrument that is meant to play them, so they are usually very small in size. However, it's up to the sound card of the end user to play the notes, and sound cards have been historically known to have poor MIDI performance (at least those oriented to the consumer market). Few consumer cards feature decent MIDI playback. Still, as a game creator you can never be sure if the music of your game will be played as you meant it, because it totally depends on the hardware of the user.

For this reason Allegro also provides a AL_MIDI_DIGMID driver. This is a software implementation of the so called Wavetable synthesis. Sound cards featuring this store digital samples of real instruments at different pitches, interpolating those that are not recorded, thus achieving a high sound quality. Implementing this in software makes you sure that the quality you hear on your computer is that which will be heard by end users using the same driver.

The disadvantage of the AL_MIDI_DIGMID driver is that it uses more CPU than simple MIDI playback, and it steals some hardware voices from the sound card, which might be more critical for the end user experience than the background music . At the Allegro.pas wiki (http://allegro-pas.sourceforge.net/) you can find more information about AL_MIDI_DIGMID and where to download and create digital samples for your MIDI files.

Allegro also allows the use of digital samples.

See also al_play_midi al_play_sample

Contact info

If you want to ask, comment or make suggestions about Allegro.pas you can do it by joining the Allegro.pas mailing list (http://sourceforge.net/mailarchive/forum.php?forum_name=allegro-pas-main), or at the Pascal Game Development forums (http://www.pascalgamedevelopment.com/).


Generated by PasDoc 0.13.0 on 2016-07-20 12:01:36