pax_global_header00006660000000000000000000000064117350750570014524gustar00rootroot0000000000000052 comment=4c915139028eca4516e504557723c9cfd15ef6ef allegro4.4-4.4.2/000077500000000000000000000000001173507505700134065ustar00rootroot00000000000000allegro4.4-4.4.2/AUTHORS000066400000000000000000001425261173507505700144700ustar00rootroot00000000000000 We hope to have remembered everyone who ought to be mentioned here. If your name should be included, accept our apologies, and please tell us so we can correct the oversight! ====================================== ============ Contributors ============ ====================================== Acho A. Tang (acho at telus dot net). Added a Sidewinder Precision Pro joystick driver to the DOS port. Adrian Oboroc (doba at corefx dot com). Wrote the LBM loader. aj. Reported many problems, suggested a lot of improvements to the documentation, added AMD64/IA64/SSE3 detection code, added DirectX 8 and 9 detection to the Windows port, added MSVC7 specific options to the makefile, cleaned up a C99-ism in makedoc, fixed a beep when alt+character was pressed in windowed mode in Windows and made TARGET_ARCH_EXCL also work with MSVC. Alex Demko (alex_demko at mbnet dot mb dot ca). Suggested lots of improvements to the datafile system and provided code for handling the 8x16 BIOS font format. Alessandro Monopoli (almonopo at tin dot it). Added the Italian translation of the system messages. Andreas Kluge (bitland at aol dot com). Wrote the Ensoniq Soundscape driver and fixed division bugs in the fix class. Andrei Ellman (ae-a-alleg2 at wacko dot wackonet dot net). Contributed the polygon_z_normal() function, suggested some additions to the docs, updated the Cygwin section in docs/build/mingw32.txt, got Allegro for MSVC to build with Cygwin, improved the performance of the hsv_to_rgb() function, corrected a rounding issue in hsv_to_rgb(), improved the exrgbhsv example and the Windows screensaver, fixed problems in the MSVC makefile when using Cygwin and did plenty of other things too. Andrew Cottrell (andrewc at dbworld dot net dot au). Changed the grabber to use a more robust (locale-independent) date format. Andrew Ellem (krand at ican dot net). Wrote the original version of the digital audio streaming code. Andrew Geers (andy at geerswj dot clara dot net). Added the -ppassword and -nosound options to the grabber, scrolling support in the image viewer and the flipped rotated sprite routines. Andy Goth (unununium at openverse dot com). Made the gfx_card config variable more flexible, added the 256x256 tweaked VGA mode, wrote the d_text_list_proc() dialog object and fixed the constructor support in dat2s on Unix. Angelo Mottola (a dot mottola at libero dot it). Added the BeOS joystick, MIDI and windowed graphics drivers, added mouse wheel, display switching and close button support for BeOS, wrote the DGA2 driver and close button support for X, contributed the bfixicon utility, added triple buffering support, a BWindow-based windowed driver and a fullscreen overlay driver to the BeOS port and reorganized its gfx subsystem. And, oh, contributed the QNX and MacOS X ports too. Annie Testes (annie at kezako dot net). Added font_height, render_char, char_length hooks to FONT_VTABLE, fixed several glitches in the unicode support, added a pack_fdopen() function, caught a misordering in the X system shutdown, fixed some device name strings, lifted several hardcoded length limitations in the configuration routines, added a mouse driver based on the event interface (EVDEV) to the Linux port, fixed numerous bugs and did plenty of other things too. Anthony 'Timorg' Cassidy. Made d_menu_proc fill up its assigned area with the gui_bg_color, updated required cygwin package list. Antoine Mathys (mmathys at bluewin dot ch). Added the Swiss keyboard mapping. Anton Ragnarsson (anton dot ragnarsson at swipnet dot se). Contributed the Swedish keyboard mapping table. Antti Haapala (ztane at lyseo dot edu dot ouka dot fi). Fixed the setup program to display the right frequency list for each type of soundcard and contributed the Finnish translation of the system messages. Antti Koskipaa (antti dot koskipaa at nic dot fi). Wrote the DOS driver for WSS (Windows Sound System) cards. Arne Steinarson (arst at ludd dot luth dot se). The fixed point square root routine came from his fix-float library. Arthur Huillet (email unknown). Fixed a typo in the docs. Attila Szilagyi (attilabox at hotmail dot com). Fixed SVGAlib horizontal scrolling. Ben Chauveau (bendomc at worldnet dot fr). Added support for Tseng ET6000 cards (now available as part of the FreeBE/AF project). Ben Darnell (bdarnell at vnet dot net). Put together the 2.11 release of Allegro while I was away from the net and wrote the original version of the Allegro FAQ. Ben Davis (entheh at users dot sf dot net). Added set_volume_per_voice(), made silent voices continue playing, fixed other minor bugs in the mixer, fixed a bug in create_rgb_table(), adapted polygon functions to handle two coincident vertices, added the set_window_close_button() and set_window_close_hook() framework, added support for timers with parameters under Windows, corrected several compilation warnings and documented the behaviour of pack_feof(). Benjamin Joel Stover (stovertech at intellisys dot net). Wrote the initial version of the fullscreen X-Windows graphics driver. Benny Colyn (email unknown). Added a Dutch translation. Bertrand Coconnier (bcoconni at club-internet dot fr). Modified 3D polygones routines for subpixel and subtexel accuracy, made speed enhancements in these routines, fixed blending in C version of atex_lit scanline functions, added scanline subdivisions in C scanline functions and Z-buffer polygon functions and merged in Calin Andrian's P3D library. 8L45T3R (o8l45t3ro at users dot sf dot net). Fixed a bug in arc() where small arcs would be drawn as circles. Bobby Ferris (baf at bafsoft dot com). Added the SciTE API output format to makedoc and temporarily hosted Allegro's SVN repository while SourceForge's SVN was in beta. Burton Radons (loth at gec dot net). Optimised the truecolor pixel blending function, converted the blenders to the new single-handler format, and added the range of Photoshop-compatible blender functions. Calin Andrian (calin at ibd dot dbio dot ro). Wrote the truecolor, MMX, 3DNow!, masked lit mode, translucent and Z-buffered polygon rendering routines, the clip3d_f() function and also the scanline sorting functions for 3D scene rendering, and his P3D addon library was merged in. Calvin French (frenchc at home dot com). Added the -w (always update) switch to dat.exe. Carsten Schmidt (email unknown). Wrote the the initial version of the Linux GGI driver. Carsten Sorensen (csorensen at ea dot com). Wrote the the ESS AudioDrive soundcard driver. Catatonic Porpoise (). Added OpenBSD detection, fixed an issue with executable rights not set on the memory for the i386 stretcher on UNIX systems, and fixed the documentation for stretch_sprite. Cloud Wu (cloudwu at 263 dot net). Optimised the truecolor pixel blending functions. Charles Bilyue (Esaelon at aol dot com). Optimized the i386 blitters and suggested to not force yielding timeslice with non-blocking menus. Charles Wardlaw (kattkieru at yahoo dot com). Fixed warnings with gcc 4 on MacOS X and helped resolve a problem with setAppleMenu under Tiger. Chris Graham (chris_graham at postmark dot net). Suggested to add a new flag for Windows NTFS compressed files. Chris Jones (cj at jibblers dot plus dot com). Fixed a bug with 16-bit samples loading, worked around a problem with DOS file attributes under Win2k, let the MIDI player pass controller events to the raw player by default, made the MIDI player handle the 'All Sound Off' controller message, added support for the bitfield compressed BMP image format, fixed the behavior of numeric keys when NumLock is on, and fixed loading of certain .wav files. Chris La Mantia (celamantia at home dot com). Wrote the d_radio_proc(), d_icon_proc(), and d_slider_proc() dialog objects, added the D_DISABLED flag, improved the GUI handling of different font heights, and added the right aligned text functions. Chris Roberts. Updated CMake build for BeOS/Haiku. Chris Robinson (crobin_99 at yahoo dot com). Wrote the fixed point clip3d() function, improved the performance of the DIGMID driver, implemented the digmid_set_pan function, rewrote part of the Allegro mixer, made the Allegro mixer the default one in Windows, improved the threaded UNIX timer code, helped improve responsiveness under X11, tweaked tests/play.c, added drawing primitives and video bitmap locking to the X11 port and did plenty of other things too. Christer Sandberg (christer dot sandberg at mdh dot se). Made dat2c work better with ISO C90 compilers, made dat2c correctly detect the native line ending, fixed a problem with the include guard generated by dat2c, fixed a bug in the 24-bit graphics code of fixup_datafile(), fixed a memory leak with datedit_exit, fixed a problem with Electric Fence. Christian Schueler (cschueler at gmx dot de). Changed the optimisation settings for better performance. Daniel Nilsson (daniel7 at algonet dot se). Enlarged the starfield in exstars, and fixed an incorrect range in exlights. Daniel Schlyder (daniel at bitblaze dot com). Fixed problems with get_executable_name() under Windows, another one with set_window_title() under BeOS, potentially unsafe constructs in the Windows code, the installall makefile target under Windows, added set_allegro_resource_path(), fixed make uninstall with mingw make, added ALLEGRO_LIB_BUILD flag for gcc variants not using configure, fixed a bunch of warnings in MinGW and did plenty of other things too. Daniel Verkamp (i_am_drv at users dot sourceforge dot net). Added a MIDI input driver to the Windows port and added support for .rmi MIDI files to the MIDI loader. Dark Nation (email unknown). Restored support for old-style encrypted packfiles, which had been removed in 4.1.18. David A. Capello (dacap at users dot sourceforge dot net). Made dotted_rect() avoid bank switches, fixed a problem with lost GUI mouse clicks, made d_menu_proc() steal/return focus when activated then deactivated, fixed a problem with submenus, fixed a bug with FLI frames containing odd-sized chunks, made makedoc write sub-section headings for .txt output, made override_config_file also be used for writing to the config file and did plenty of other things too. David Kuhling (dkuelhin at hell1og dot be dot schule dot de). Optimised the fsqrt() routine, and added fhypot(). Dave Physics. Some documentation fixes. Dave Thomson (gameskitchen at geocities dot com). Added the RGB <-> HSV conversion routines, the autocrop function to the grabber and wrote the 3d starfield example program (exstars.exe). David Calvin (calvid at rpi dot edu). Wrote the original version of the sound setup utility. David Cullen (dcullen7 at bellsouth dot net). Added multiple bullets and extra lives to the demo game. Deepak T (coolbool at gmx dot net). Fixed clipping in three C sprite drawing routines. Dennis Busch (email unknown). Fixed a bug in d_clear_proc, fixed a Unicode bug in the mode selector, and fixed the short description of add_clip_rect. Dmitriy Kazimirow (mariann at mail dot ru). Provided the Russian keyboard mapping and message translation files. Dominique Biesmans (Dominique dot Biesmans at ping dot be). Wrote the mode-X version of draw_sprite() and the mode-X <-> linear blitting functions. Doug Eleveld (D dot J dot Eleveld at anest dot azg dot nl). Wrote the d_textbox_proc() dialog object and the new grabber help system. Dustin Dettmer (dustin at mize dot org). Spotted a typo in save_bitmap. Edgar Reynaldo. Helped fixing several problems with gfx_mode_select_filter(), pointed out two warnings, fixed two warnings in a loadpng example, provided mouse_on_screen(), get_gfx_mode_type() and get_gfx_mode() functions. Eduard Bloch (edi at gmx dot de). Fixed a freeze caused by the ESD detection code, fixed a bad behaviour of the config routines and suggested better ways to find the path to the executable on Unix. Edward Boone (Lucien dot Boone at ping dot be). Provided scancode mapping tables for the AZERTY keyboard layout. Elias Pschernig (elias at users dot sf dot net). Added a COLORCONV_KEEP_TRANS mode, contributed the wfixicon utility, contributed several enhancements to the grabber, fixed menu dimensions in the GUI engine, fixed the get_camera_matrix*() functions, added support for the CHM and Devhelp documentation formats, fixed a bug in midi_seek(), made load_datafile_object() load the object properties, made the GUI code scare the mouse more intelligently and did plenty of other things too. Eric Botcazou (ebotcazou at libertysurf dot fr). Made the DGA driver work better in 8bpp and 32bpp modes, improved the DirectX windowed driver and Windows graphics subsystem, partially revamped the Unicode API and added uszprintf(), added file_select_ex(), the unified al_find*() interface, an Unicode example, a new filetest, rewrote the fixdll script, revamped the Borland C++ build process, fixed lots of bugs and did plenty of other things too. Erik Sandberg (eriksandberg at geocities dot com). Optimised the 8 bit draw_sprite() and draw_trans_sprite() functions and helped with the Swedish message translation. Erno Schwetter. Fixed some bugs in the Linux console port and fixed a long-standing bug in the polygon() routine. Etienne Vouga. Fixed a bug with the reset_controllers MIDI command. Ettore Perazzoli (ettore at comm2000 dot it). Optimised the linear -> mode-X blitting function. Evert Glebbeek (eglebbk at dds dot nl). Put set_gfx_mode on a diet, added a config entry for specifying the card to be used for GFX_AUTODETECT_WINDOWED, added a '-fullscreen' switch to the grabber, cleaned up the grabber/plugins code, added various commands to the grabber, added the detection of SunOS/Solaris, added configure options for x86 processor optimisations on Unix systems, added the support for relative filenames and did plenty of other things too. EvilTypeGuy (eviltypeguy at icculus dot org). Cleaned up and fixed the RPM spec file for RedHat 9. Fabian Nunez (faybs at iafrica dot com). Added support for the CH Flightstick Pro and Logitech Wingman Extreme joysticks, 3-button mice, and the extended keys on a Microsoft keyboard. Fabrizio Gennari (faybs at iafrica dot com). Contributed the DB9 and TurboGraFXoystick drivers. Francis Devereux. Helped out with build issues on Mac OS X. Francisco Pires (fmlvp at hotmail dot com). Added an FPS counter and an option to disable vsync to the excamera example. Francois Charton (deef at pobox dot oleane dot com). Wrote the Paradise graphics driver (now available as part of the FreeBE/AF project), improved the VGA palette setting code and helped with the TexInfo conversion of the docs. Frodo Baggins (l41273 at alfa dot ist dot utl dot pt). Made the Portuguese keyboard mapping. Garret Thomson (g at sirsonic dot com). Wrote the music used in the demo game. George Foot (gfoot at users dot sourceforge dot net). Did a great deal of work on the Linux console version, wrote the AWE32 driver, added the MIDI pause/seek functions, provided the basis of the SoundFont reader used in the pat2dat utility, fixed the C fceil() function, added the ffloor() function and added non-FM support to the OSS MIDI driver. Gorka Olaizola (olsago at jet dot es). Added the Redhat RPM .spec file. Grady Martin (shadygrady at budweiser dot com). Fixed a bug in the handling of %n in the printf style text functions, added a move command to the grabber and standardised some of the grabber dialog boxes. Greg Hackmann (hacker at ididitmyway dot com). Contributed the Borland C++ Builder port. Greg Lee (greg at ling dot lll dot hawaii dot edu). Pointed out that Linux joystick driver should read all events. Grzegorz Adam Hankiewicz (gradha at users dot sourceforge dot net). Wrote several of the example programs, suggested the "compress" makefile target, translated the docs and system error messages into Spanish, suggested the idea of embedding the setup utility into other programs, wrote some documentation and corrected the .texi generation to improve texi2dvi output, improved the makedoc utility and contributed a new doc format, added reload_config_texts() and did plenty of other things too. Grzegorz Godlewski (email unknown). Contributed a Polish localization patch, and added support for lower and upper altgr tables. Grzegorz Ludorowski (pajonk at ajax dot umcs dot lublin dot pl). Wrote several of the example programs, and made the intro animation and graphics for the demo game. Guilherme Silveira (thedarkage at geocities dot com). Modified the file selector to only list valid drive letters. Gunter Ladwig (gladwig at iname dot com). Wrote the OS/2 detection routines and added the three-button mouse emulation. Hans de Goede. Fixed a problem with dynamically generated stretcher code not being properly marked as executable on Linux, fixed a busy wait in the X11 vsync simulation, added a fullscreen driver for X11 which does not need XVidMode extension, fixed a problem where switching to fullscreen mode under X11, made digmid work with absolute pathes in patches.cfg, and fixed a problem with the Alsa driver on big endian systems. Harshavardhana Reddy N (nharsha at gmail dot com). Added a Kannada greeting to exunicod. Haruhiko Okumura (email unknown). Wrote the original version of the LZSS compression code. 12-2-404 Green Heights, 580 Nagasawa, Yokosuka 239, JP. Hein Zelle (hein at icce dot rug dot nl). Revamped the cross-compilation section of docs/build/mingw32.txt, clarified a requirement when cross-compiling from Linux, reworked the paragraph on the location of shared libraries under Unix in the docs and added a FAQ entry on the same subject. Henrik Schmidt (hbs at ks dot informatik dot uni-kiel dot de). Found a workaround for the switching problem under Windows, made gcc pass '-h' instead of '-soname' to the linker and replaced '-L' by '-h' in shell comparisons so as not to break on Solaris. Henrik Stokseth (hensto at online dot no). Contributed a native Mingw32 port which can also be built with a cross-compiler and the Cygwin compiler, much improved OS detection, added get_gfx_mode_list() and methods for querying the VGA, Mode-X, Xtended, VESA, VBE/AF and DirectX drivers for a list of possible GFX modes, rewrote the mode-selector to use get_gfx_mode_list(), reworked the build system many times and did plenty of other things too. Hrvoje Ban (spoofer255 at gmail dot com). Pointed out a bug in the mode selector, fixed several double ;'s, fixed ASSERT() in Windows, helped write a documentation section about common pitfalls, and added the create_datafile_index function. Igor Gnip (gnipi at mindnever dot org). Removed the requirements for fileutils on DOS/Windows platforms and added the detection of MSYS to the MingW32 port. Isaac Cruz (icruzbal at teleline dot es). Fixed a bug with accelerated drawing onto sub bitmaps of DirectDraw surfaces, added the GFX_DIRECTX_WIN driver, fixed a Windows sub bitmap locking bug, added Windows desktop_color_depth and yield_timeslice routines, and made extensive modifications to other aspects of the Windows code. Ivan Baldo (lubaldo at adinet dot com dot uy). Wrote the 15/16 bit dithering code and optimised the sprite rotation routines. Jaime Moreno (daviangel at hotmail dot com). Helped track down a problem with dependency generation in MacOS X. Jakub Wasilewski (krajzega at meditech dot pl). Fixed a bug when loading greyscale TGA images and contributed to the skater demo. James Arthur (jaa at arfa dot clara dot net). Documented the Photoshop-style truecolor blender routines. James Hyman (frooge at mindless dot com). Added support for quoted strings in the get_config_argv() function and the dithering code for paletted images. James Lohr (email unknown). Fixed a problem with mouse acceleration in fullscreen modes under Windows. James Ponder (james at squish dot net). Suggested to remove the DJGPP makefile from the Unix tar archive and clarified a requirement when cross-compiling from Linux. Jan Bruun Andersen (jba-dk at users dot sourceforge dot net). Fixed a compilation problem with Cygwin. Jan Hubicka (hubicka at horac dot ta dot jcu dot cz). Vastly improved the speed of the create_rgb_table() function. Jason Wilkins (fenix at io dot com). Wrote the quaternion math routines and contributed the BeOS port. Javier Gonzalez (xaviergonz at hotmail dot com). Corrected mouse movement speed, made allegro_message() use title from set_window_title(), added close button hook support and improved switching in Windows, fixed bad clearing of subbitmaps, made bug reports and suggestions for improvement, contributed bidirectional looping support, backward playing support and bugfixes for the DirectSound driver and did plenty of other things too. Jeff Mitchell (email unknown). Fixed the location of grabber.txt in the spec file. Jeremiah Blanchard (squirminworm at yahoo dot com). Contributed modifications in order for Allegro to build on Darwin/MacOS X and updated the build instructions for this new port afterwards. Jim Flynn (jflynn at pacbell dot net). Removed floating point calculations from the AWE32 MIDI driver. Jim Grainger (Grainger_Jim/world_europe_samuro_WYN-CTV at samsung dot co dot kr). Spotted a broken link in the docs and updated it. Jiri Gabriel (email unknown). fixed loading of multiple ranges in a single bitmap with txt fonts and helped fix an off-by-one mistake for the last glyph in extract_font_range. Joaquin Hierro Diaz (Joaquin dot Hierro dot Diaz at fresno dot csic dot es). Made the mapping table for Spanish keyboards. Joerg Rueppel (sharky-x at gmx dot net). Added more flexible wildcard matching for object names in dat.exe and the find_datafile_object() function. Johan Peitz (d98peitz at dtek dot chalmers dot se). Fixed and enhanced the Win32 joystick driver, and contributed the 'Alex the Allegator' icon. Johan Venter (leonjventer at bigpond dot com). Fixed some problems with the RSXNT and Mingw32 makefiles. John Holden (johnh at psych dot usyd dot edu dot au). Fixed a bug in load_wav(). John Utz (Johnut01 at noa dot nintendo dot com). Corrected a wrong assumption about the VRAM layout in the Linux framebuffer console driver. Jon Rafkind (workmin at ccs dot neu dot edu). Added more ASSERTs to the code, implemented the Cohen-Sutherland clipping algorithm for the line() function and supplied an m4 macro for allegro. Also fixed a problem with allegro-config. Implemented draw_sprite_ex() function. Jonas Petersen (joXonoX at berlin dot snafu dot de). Added the save_bmp() function and support for the OS/2 BMP format. Jonathan Tarbox (jonattar at rocketmail dot com). Wrote the mode-X setup code, the FLI/FLC player and contributed parts of the joystick handler. Jorrit Rouwe (j dot rouwe at cpedu dot rug dot nl). Provided a new and much cooler set of FM instrument definitions for the Adlib MIDI driver. Jose Antonio Luque (skylord at LatinMail dot com). Improved the Windows joystick driver, and optimised the 16-bit blit() and masked_blit() functions. Joshua Heyer (joshua_heyer at yahoo dot com). Wrote the original version of the OSS sound driver. J. P. Morris (email unknown). Fixed a bug rest_callback under unix. Julien Cugnière (jcugniere at free dot fr). Improved the support for non-blocking menus, fixed a bug related to the retrieval of the inital volume when no primary buffer was present under Windows, fixed the crash on exit with the aRts sound driver, added an X11 message box for allegro_message under X11 and fixed a crash in the GUI when a dialog was opened while a menu was still open. Kalle Toivonen (allegro at korpiq dot iki dot fi). Fixed a bug in _parallelogram_map(). Keith Gerdes (kwg at softhome dot net). Fixed the DirectDraw overlay mode driver. Kerry High (khigh01 at umr dot edu). Contributed the SNES joypad driver. Kester Maddock (dmaddock at xtra dot co dot nz). Wrote the Wingman Warrior joystick driver. Knut Pape (Knut_Pape at t-online dot de). Improved the Mingw32 readme file. Kronoman X (kronoman_x at hotmail dot com). Added a FAQ entry about the conflict between Allegro headers and the C++ 'using' directive. Krzysztof Krzyzaniak (eloy at arrakis dot cs dot put dot poznan dot pl). Wrote the load_voc() function. Laurence Withers (lwithers at users dot sf dot net). Added destroy hook to font structure, worked on const-correctness throughout the library, implemented the new FONT structure, made some modules avoid linking dependencies, contributed the dat2c utility, added two fixed point ratios for converting to and from radians, added a '-windowed' switch to the grabber, added a new text API and did plenty of other things too. Lee Killough (email unknown). Added the low-level hook routine to the keyboard handler and fixed a couple of bugs. Lennart Rolland (chimeni at hotmail dot com). Contributed the Norwegian message translation. Lennart Steinke (lst at steinke dot net). Added the exconfig example, contributed keyboard layout detection code for Windows and suggested the true colour font rendering. Lisa Parratt (lisa at thecommune dot org dot uk). Contributed the SGI Audio Library sound driver, spotted a BSDism that IRIX doesn't like at all, added IRIX detection and improved the performances of the SGI audio driver Lorenzo Petrone (looris at gmail dot com). Contributed the gfxinfo utility, added two FAQ entries, added a xwin_set_window_name() function to the X11 port, added support for switch callbacks under X11 and refactored the display switching code. Lucas Vignoli Reis (lucasvr at bestway dot com dot br). Added the Portuguese (Brazil) message translation and keyboard mapping. Magnus Henoch (mange at freemail dot hu). Made the gfx mode selector keep the current selection as much as possible and fixed a problem when compiling without 8bpp support. Maiolino Carmelo (cmaiolino at ctonline dot it). Added the Italian keyboard mapping table. Manni Heumann (manfred dot heumann at uni-bielefeld dot de). Fixed some problems with the German keyboard mapping table. Marcel de Kogel (m dot dekogel at student dot utwente dot nl). Not content with fixing my broken MPU-401 driver, Marcel went on to provide a set of vastly improved drum sounds for the OPL driver, to help me sort out some problems with reentrant interrupts, to supply the half of the joystick code that didn't come from Jonathan and to locate a stupid mistake in my VESA linear framebuffer code. Marcel Smit (marcel dot athlon at hccnet dot nl). Corrected a bug that caused errors when drawing persp. correct polygons facing the screen, corrected an error in the packfile format write-up and made the show_video_bitmap() method of the Windows windowed driver wait for a vsync. Márcio Fialho (maaf1980 at yahoo dot com dot br). Fixed several issues with the DJGPP port and the VBE/AF driver and fixed some bugs related to author credits. Marco Campinoti (marco at etruscan dot li dot it). Added 15 and 24 bit support to the native Tseng ET4000 driver (now available as part of the FreeBE/AF project). Marco Marmulla (Viper005 at usa dot net). Added 16 bit support to the load_voc() routine. Marian Dvorsky (marian at step dot sk). Wrote the Windows GDI interface routines. Marius Fodor (iceman at teleport dot com). Added support for the Sidewinder and Gravis GamePad Pro. Marek Habersack (grendel at ananke dot amu dot edu dot pl). Did the original Linux console port (brave man: this was the first ever work done on porting Allegro away from DOS), which is the basis of the code we are still using today and added support for the more recent Trident chipsets (now available as part of the FreeBE/AF project). Mark Keller. Reported two minor mistakes in the manual. Mark Wodrich (mwodric at eleceng dot uct dot ac dot za). The brain behind sub-bitmaps, flicker-free mouse pointers, and the ability to import GRX .FNT files into the grabber. Markus F.X.J. Oberhumer (markus dot oberhumer at jk dot uni-linz dot ac dot at). Fixed the Video-7 scrolling function (now available as part of the FreeBE/AF project), optimised the color mapping routines, and made many useful suggestions like the addition of a vid_phys_base field to the graphics driver structure. Martijn Van Lersel (amarillion at yahoo dot com). Fixed an overflow in create_light_table(). Martijn Versteegh (m dot versteegh at hccnet dot nl). Added the config hook extension mechanism. Mathieu Lafon (mlafon at ifhamy dot insa-lyon dot fr). Added the French keyboard mapping, support for the Pause/PrtScr keys and changed the key[] table to a normal/extended bitfield. Matt Witherspoon (spoon at vt dot edu). Fixed a bug in the scroll() method of the Linux SVGAlib driver. Matthew Bowie (catcat at nmt dot edu). Added support for 4-button joysticks. Matthew Leverton (matthew at allegro dot cc). Fixed a bug with mouse mickeys in windowed mode under Windows, fixed a problem with al_find*() and NTFS partitions under Windows, added missing header files to be installed by the Windows binary distribution, made the DOS/Windows makefiles use 'copy /B' instead of 'copy', added the detection of left-hand mouse configuration under Windows, fixed a bug with pack_fgets(), made an online diff generator and did lots of other things too. Matthew Smith. Fix a bug in C locking code in GDI. Maxime Carey (werfu at users dot sourceforge dot net). Contributed the Canada (French) keyboard mapping file. Michael Bevin (michael dot bevin at stonebow dot otago dot ac dot nz). Optimised the create_trans_table() function. Michael Bukin (M dot A dot Bukin at inp dot nsk dot su). Ported the whole thing to Unix/X, and contributed a _lot_ of patches to improve the portability, robustness, and performance of pretty much the entire library. Michael Faerber. Pointed out a mistake in the documentation for text_height(). Michael Jensen. Fixed a mistake in the documentation for is_compatible_font. Michael Rickmann (mrickma at gwdg dot de). Ported the Windows code to Mingw32. Michael Tanczos (webmaster at logic-gate dot com). Fixed some bugs in the FLIC player. Michal Mertl (mime at eunet dot cz). Wrote all the 24 bit graphics code, the optimised palette generation function and a fair amount of the other truecolor stuff too (bitmap scaling, image loading, etc). Michal Molhanec (molhanec at seznam dot cz). Simplified the build instructions for Dev-C++, replaced all occurences of MingW32 by MinGW in the docs, added an faq section about the giftware license, fixed problems with long filenames when building for MSVC, corrected a problem with the Watcom port, added MSVC7 options to the makefile, fixed a linker problem with the MSVC port, fixed some const warnings in the grabber code and did plenty of other things too. Michail Pishchagin (mblsha at users dot sourceforge dot net). Contributed the ustrnicmp() function. Milan Mimica (milan dot mimica1 at pu dot htnet dot hr). Fixed bugs in the keyconf utility, the alsa 9 volume settings and extract_font_range(), helped fix an off-by-one mistake for the last glyph in extract_font_range, fixed a bug where a font would be converted to 8 bit, a bug with is_color_font, made the Linux console driver more robust, fixed some spin loops in the test program, and added the get_volume and get_hardware_volume functions, and did plenty of other things too. Miran Amon (miran dot amon at gmail dot com). Fixed an undocumented arbitrary limit in get_config_argv() and contributed to the skater demo. Nathan Albury, aka Rubicant (gt4558a at prism dot gatech dot edu). Improved the fire routine in examples/exflame.c (my original version didn't really look very much like flames :-) and gave me some extremely useful ideas about how to implement translucency. Nathan Smith (white_door at dread dot nl). Implemented the recursive handling of directories for the dat utility. Neil Townsend (neil at robots dot ox dot ac dot uk). Improved the accuracy of the timer routines and added the callback parameters. Neil Roy (neilroy at cogeco dot ca). Suggested many improvements to the documentation. Neil Walker. Implemented a hardware accelerated stretch_blit() for the Windows DX port, and fixed a bug with draw_sprite and sub-bitmaps. Nicholas Davies (master_goodbytes at hotmail dot com). Made the fix class not trigger warnings with gcc -Weffc++ and contributed to the skater demo. Nick Kochakian (nickk at worldnet dot att dot net). Wrote the DirectSound input driver. Ole Laursen (98zOLaw at aalborghus dot dk). Contributed the Danish keyboard mapping table and system message translation, and made the Unicode utolower() and utoupper() functions understand the entire 16 bit character set. Olivier Blin (oblin at mandriva dot com). Fixed compilation problems for the ModeX driver. Olly Betts (olly at muscat dot co dot uk). Modified the djgpp makefile to support cross-compiling on a Linux machine. Omar Cornut (cornut at noos dot fr). Spotted an asm locking bug under Windows, bumped the maximum number of buttons per joystick to 32, fixed the Windows joystick driver to handle a weird peculiarity of the DirectInput API and improved the handling of KEY_COLON2 on Japanese keyboards. Oscar Giner (O_giner at hotmail dot com). Added the Catalan translation, corrected the Spanish translation, fixed a bug with binary data exporting in the grabber and fixed a conflict between the magic main and the MFC. Owen Embury (owen at gememail dot demon dot co dot uk). Wrote part of the translucency/lighting code. Owen Rudge (alleg at orudge dot freeuk dot com). Contributed a DLL version resource script and the mkdata.bat script. Ove Kaaven (ovek at arcticnet dot no). Fixed a bug in the ATI mach64 driver (now available as part of the FreeBE/AF project), added native truecolor and linear framebuffer support to the ATI driver, contributed the Norwegian keyboard mapping, and added MIDI and sample input features to the MPU and SB drivers respectively. Paavo Ahola (email unknown). Helped fix a problem with BCC and the C implementations of fixmul. Patrick Hogan (patter at iname dot com). Wrote the draw_gouraud_sprite() function, and made Windows audiostreams work properly. Paul Bartrum (bartrum at xtra dot co dot nz). Contributed the ellipse drawing functions. Paul Eipper. Reported a bug where libdir from autotools was not used for the modules path. Paul Furber (paul at sprintlink dot co dot za). Provided the floating point apply_matrix_f() function. Paul Hampson (Paul dot Hampson at Pobox dot Com). Improved and fixed some problems in the SNES gamepad driver. Paul Pinault (diskaleg at infonie dot fr). Translated the system error messages into French. Pavlos Touboulidis (gtoub at otenet dot gr). Made file_select() able to include or exclude files based on their attributes. Pedro Cardoso (pcardoso at viriato dot ipv dot pt). Contributed the tweaked 80x80 VGA mode. Peter Cech (7cech at nw dot fmph dot uniba dot sk). Added grabber support for the 8x8 BIOS font format, support for hot-swapping between a custom keyboard layout and the standard US mapping, optimised the alpha sprite blending routines and added non-ASCII space recognition to uisspace(). Peter De Wachter. Made the ALSA driver work for hardware which does not support unsigned samples. Peter Hull (peterhull90 at users dot sourceforge dot net). Made the file selector work with directories that have more than 2048 files, solved some compiling issues on MacOS X, fixed a bug in rest() that caused it to wait too long on that platform, fixed several problems with the hardware mouse cursor, fixed a deadlock in the software mouse updating code, fixed compilation problems under MacOS X tiger, added a MacOS X helpfile and did plenty of other things too. Peter Johansson (email unknown). Reported a problem with system cursors not working in Windows. Peter Monks (pmonks at iname dot com). Wrote the Video-7 graphics driver (now available as part of the FreeBE/AF project) and showed me how to set up the unchained 640x400 mode. Peter Palotas (blizzar at hem1 dot passagen dot se). Added the keyboard callback routine. Peter Pavlovic (Peter dot Pavlovic at st dot fmph dot uniba dot sk). Added the Slovak keyboard mapping and message translation, stopped the DOS file selector from listing virtual drives, did the same for the Windows file selector, improved the support for accented character maps in the keyboard driver and made aesthetic modifications to the GUI menu system. Peter Puck (zaqhaq at netscape dot net). Helped with the Mingw32 native build. Peter Wang (tjaden at users dot sourceforge dot net). Added the mouse_z wheel input support to the Linux code, fixed problems with the ESD sound driver, wrote the ALSA sound driver, wrote the BeOS sound driver, added OSS MIDI and sample input support, added banked mode support to the SVGAlib driver, wrote the X DGA mode switching code, improved the Linux joystick driver, X11 fullscreen, DGA2 and DGA driver, added pthread timers under Linux/Unix and did loads of other things too. Phil Frisbie, Jr. (pfrisbie at geocities dot com). Wrote the CPU type detection code. Phil Krylov. Fixed a bug in load_bios_font(). Phil Shenk (email unknown). Improved the MSVC build instructions. Philipp Thomas (pthomas at suse dot de). Fixed all comparisons between signed and unsigned types, fixed compilation on x86-64, fixed all function prototypes, converted the configure machinery to autoconf 2.53 or later and added multi-arch support, DESTDIR support and the German translation to the RPM spec file. Przemek Podsiadly (ppodsiad at elka dot pw dot edu dot pl). Added hicolor versions of the 3d polygon code. Revin Guillen (revin at phylo dot com). Added the position_dialog() function. Richard Davies (richard at debaser dot force9 dot co dot uk). Added support for PSX and N64 joypads. Richard Mitton (100740 dot 1271 at compuserve dot com). Added support for 6-button joysticks, and wrote the 12-bit color example program (ex12bit.c). Richard Reeve (r dot e dot reeve at stir dot ac dot uk). Fixed a silly mistake with gcc 3.0.x detection. Rikard Peterson. Fixed a small problem with the Mac OS X joystick driver. Robert J. Ragno (rjr at mit dot edu). Wrote the Gravis GrIP driver, made some improvements to the Wingman, PSX and throttle input code. Robert J. Ohannessian (voidstar at ifrance dot com). Added MMX optimisation for the 8 and 16-bit clear() functions, fixed bad clearing of subbitmaps, added SSE detection and optimised some masked blits with SSE instructions, added some routines to the unified color convertor and made some of them more robust, fixed the docs for pivot_scaled_sprite_v_flip(), revamped the retrieval mechanism of CPU capabilities, separated the CSS file and did plenty of other things too. Robert Riebisch. Fixed some warnings from gcc 4.x on VESA and VBE/AF drivers. Roberto Alfonso (rpgrca at labint dot frba dot utn dot edu dot ar). Fixed a couple of memory problems in the dat2c utility, added an srand() call in the demo game, made the MSVC port call `link /lib' rather than `lib', fixed several warnings with GCC 4 under DJGPP and fixed a grabber crash when importing a font range in an existing font. Robin Burrows (rburrows at bigfoot dot com). Provided a new page flipping code for the DirectDraw subsytem, added a Windows sound driver using the Allegro mixer and another using waveOut, fixed two glitches in the DirectDraw code. Romano Signorelli (romanos at bigfoot dot com). Added an arc plotting routine. Ron Novy Made several improvements to the test program. Ronaldo Hideki Yamada (r dot yamada at uol dot com dot br). Contributed the MacOS 9 port of Allegro. Ryan Patterson. Made various documentation fixes and fixed a crash in free_config_entries. S.Sakamaki (emt at geocities dot co dot jp). Added the VESA 3.0 refresh rate control code. S.Suzuki (s-suz at sunfield dot ne dot jp). Wrote the IF-SEGA /PCI, /PCI2, and /ISA joystick interface drivers. Salvador Eduardo Tropea (salvador at inti dot edu dot ar). Improved the keyboard routines (better handling of extended scancodes, keyboard LED support, capslock and numlock, and alt+numpad input), contributed the 320x100 VGA graphics mode, added support for proper 16 bit sample mixing, fixed compilation on gcc 3.x and made numerous other useful suggestions, contributions and bugfixes. Sam Hocevar (sam at zoy dot org). Fixed a Bashism in fix.sh that makes Solaris' sh choke, a race condition in the mixer under Unix w/ threads, Windows, BeOS and MacOS X, a crash in makedoc, made it possible to put functions from .s sources in a shared library under Unix and removed deprecated use of several functions. Santeri Saarimaa (gridle at mbnet dot fi). Made the Finnish keyboard mapping. Sask Allegro (sask_allegro at iespana dot es). Added support for more than two joysticks in the Windows port. Scott Harrison (scotth at calderauk dot com). Added the OpenDOS detection code. Sean Gugler (sean at epal dot com). Added the set_leds() function. Seunghwan Ji (email unknown). Made makedoc output correct html and rtf files for Korean. Serge Semashko (serge at lxnt dot info). Fixed a bug with the letter P in the Russian keyboard configuration file, added Enter as a fire key to the demo game, fixed some problems with Allegro working on Nokia 770, and fixed a crash in _linear_draw_trans_rgba_rle_sprite24. Seymour Shlien (seymour at dgbt dot doc dot ca). Contributed the Windows BMP file reader, bezier spline drawer, and justified text plotting function. Shawn Hargreaves (shawn at talula dot demon dot co dot uk). Progenitor. Wrote everything that wasn't written by somebody else. Shawn Walker (binarycrusader at gmail dot com). Several fixes to the .spec file, made get_executable_name use getexecname() under Solaris, fixed a bug in the keyboard driver that caused crashes on the same system, worked around errors with some versions of GNU AS and fixed errors in the configure script when not using GCC StApostol (stapostol at gmail dot com). Fixed a bug in the exflame example and updated the FAQ to use rest(0) instead of yield_timeslice(). Stefan Eilert (seilert at rz dot Uni-Osnabrueck dot DE). Added support for a second joystick. Stefan Schimanski (1Stein at gmx dot de). Wrote the original Windows version pretty much single-handedly. Stefan T. Boettner (virtual dot man at t-online dot de). Wrote the Linux SVGAlib driver. Stepan Roh (src at srnet dot cz). Added a Czech keyboard mapping and system message translation, the Latin Extended-A characters in the default font, the codepage support in the textconv utility, fixed some problems with the ESD sound driver, helped make Allegro build better on some Unix platforms, fixed const related problems in C versions of routines and added support for a automake-style DESTDIR variable in the Unix makefile. Stephan Brauss (sbrauss at optronic dot ch). Made a few fixes to let the Linux port compile again on Linux 2.2.x, corrected a few nits in the Swiss keyboard configuration file and added new keysyms to the X11-to-BIOS conversion table in order to catch missing keycodes for the keypad when NumLock is on. Stephen Kittelson (stickman2000 at juno dot com). Made bugfixes and tweaks to the keyboard system. Stijn Wolters. Clarified the documentation of init_dialog. Sveinung Kvilhaugsvik(email unknown). Pointed out that Allegro should respect DESTDIR under MacOS X. Sven Sandberg (svens at it dot uu dot se). Fixed a problem with save_bitmap() rounding the image widths, optimised the create_light_table() function, optimised the fixed point trigonometric routines, provided the Swedish message translations, improved the file selector sorting algorithm, optimised the spline routines, added ustrrchr(), improved the usprintf() handling of floats, changed the Z-buffer API, and did plenty of other things too. TBD/FeR (tbd at usa dot net). Added the 320x600 and 360x600 resolutions to the mode-X driver. Teijo Hakala (teijo dot hakala at imnetti dot fi). Added wheel support to the Windows mouse driver. Tero Parvinen (Tero dot Parvinen at hut dot fi). Designed most of the new sound API. Theuzifan Sumachingun (uzi at simauria dot upv dot es). Improved the cpu detection for Cyrix chips and made the file selector only list valid drive letters. Thomas Fjellstrom (tfjellstrom at home dot com). Wrote the ALSA 0.5.x MIDI driver and added support for ALSA 0.9.x. Thomas Harte (email unknown). Helped fix a bug in show_video_bitmap() on MacOS X, helped optimise fixmul(), helped find many bugs in the MacOS X port, like better support for user-supplied Nibs, implemented a hardware accelerated stretch_blit under DirectX, fixed a bug with draw_sprite and sub-bitmaps and contributed to the skater demo. Thomas Klausner (wiz at danbala dot ifoer dot tuwien dot ac dot at). Added NetBSD detection and fixed a problem with the allegro.m4 macro and automake 1.8+. Thomas Wolf (two at chello dot at). Corrected some errors in the German keyboard mapping and added the German translation of the system messages. Tim Bird (tbird at caldera dot com). Worked on the Linux console port. Tim Gunn (timgunn at eastwind dot com dot au). Wrote the TGA reading/writing routines. Timothy Terriberry (sundance at sprintmail dot com). Fixed several bugs in the RGB <-> HSV conversion routines. Tobi Vollebregt (email unknown). Spotted a bug in ustrerror(), which was not returning a pointer to a static buffer, reported a problem with shutdown_dialog() when a menu was open, helped port the Windows keyboard driver to Windows 98 and fixed a bug with hardware cursor detection in X11. Tobias Dammers. Fixed a problem with the DirectSound input driver. Tom Breton (tob at world dot std dot com). Added the functionality selection #ifndefs to allegro.h. Tom Novelli (tnovelli at cyber3 dot servtech dot com). Wrote the original version of the digital MIDI driver. Tom St Denis (tomstdenis at yahoo dot com). Fixed clipping of transparent objects. Tomohiko Sugiura (tmsugi at d4 dot dion dot ne dot jp). Added the KEY_ABNT_C1, KEY_YEN, KEY_KANA, KEY_CONVERT, KEY_NOCONVERT and other keys to the input handler, organised getting the IF-SEGA joystick drivers by S.Suzuki merged into my codebase and added a more aggressive Sidewinder joystick driver. Tore Halse (gnolam at gmail dot com). Made Allegro windows always popup centred in Windows and made fixes to the documentation. torhu. Fixed an out-of-bounds error in akaitest. Trent Gamblin. Implemented set_mouse_speed under X11, fixed the C version of stretch_blit and made the fullscreen DirectX driver save and restore the palette on switching away. V Karthik Kumar (karthikkumar at gmail dot com). Added a Tamil language greeting to exunicode, added switches to use the Intel compiler in Windows and added a password option to the Windows screensaver example. Also fixed a problem with allegro-config. Victor Williams Stafusa da Silva (vwss1984 at yahoo dot com dot br). Changed a few occurences of "256" to PAL_SIZE and made OS type detection handle Windows 2003 and Windows Vista. Ville Skyttä (scop at users dot sourceforge dot net). Fixed a problem with make install libdir= and modules on Unix systems. Vincent Penquerc'h (lyrian at kezako dot net). Added the D_DIRTY flag and mouse button press/release events to the GUI system, optimised the 256 to truecolor blitting code to avoid repeated conversions of the palette table, added scare_mouse_area(), added the yield_timeslice() function, added the update selection function to the grabber, added the XCRP and YCRP properties to datafiles in general, implemented the big header split and did plenty of other things too. Vitaliy Chetverikov (email unknown). Fixed a bug in the GUI where the return value of MSG_IDLE was ignored. VolkerOth (VolkerOth at aol dot com). Integrated the concepts of scrolling and edit_proc objects. allegro4.4-4.4.2/CHANGES000066400000000000000000006554361173507505700144240ustar00rootroot00000000000000 ================================================================== ============ Changes from 4.4.1.1 to 4.4.2 (May 2011) ============ ================================================================== Make rest(0) call select() with non-zero timeout on Unix. The old implementation was no longer enough to make input responsive on X11, on programs which try to draw as fast as possible. (Peter Wang) Fix module loading on Unix (Bernhard Rosenkraenzer). Made memory bitmaps returned by create_system_bitmap not marked as system bitmaps (Edgar Reynaldo). Add detection of Windows 7 (Andrei Ellman). Fail instead of crashing if gfx_directx_make_bitmap_from_surface() fails (Andrei Ellman). Fix crash in GDI driver if setting a second mode fails, after having successfully set a mode previously (Andrei Ellman). Add missing frameworks required for static linking on OS X (Peter Johansson). Fixed a problem with keyboard focus being lost on OS X when switching from windowed mode to fullscreen mode (Peter Johansson). alsa_rawmidi_init could return success on failure (Nicolas Kaiser). Updated PSP port from diedel. "The graphics, system, digi, keyboard, mouse, joystick and timer drivers are implemented and are fully functional. It supports 8, 15, 16 and 32 bpp color depths and a max. resolution of 480x272 pixels." Eliminated the need for old DirectX headers for the Windows port (David Capello). Fix problems in Windows when you use Alt-Tab. Sometimes the Alt modifier is kept pressed when you focus the Allegro window. (David Capello) Make the submenu appear to the right of its parent menu if it does not fit in the screen (Paul Suntsov). Made timers on Unix cope with system time being set backwards (Hardi Stengelin). Fix various compilation and build problems (scottmc, Cristian Morales Vega, Tony Ylisirniö, Edgar Reynaldo). Added WANT_OSS, WANT_ALSA, WANT_JACK, WANT_SGIAUDIO options (Samuli Suominen). Also pass -pg when building shared library in PROFILE mode. Let demos find readme.txt and source files correctly even if running from a build directory (Peter Wang). ==================================================================== ============ Changes from 4.4.1 to 4.4.1.1 (March 2010) ============ ==================================================================== Fix a silly build system problem with MinGW on Windows. Update loadpng code to not use a deprecated interface (as of libpng 1.4). ==================================================================== ============ Changes from 4.4.0.1 to 4.4.1 (March 2010) ============ ==================================================================== Allow Linux joystick driver to be used with the X11 port without enabling the Linux console port. Avoid problem compiling joystick driver on some Linux systems. Install DLLs into bin directories on Windows. A few build improvements for MinGW cross-compiler. ======================================================================= ============ Changes from 4.4.0 to 4.4.0.1 (December 2009) ============ ======================================================================= Chris Roberts updated CMake build for BeOS/Haiku. Some AllegroGL header files were not being installed. Fix a build problem with CMake 2.6.2+ on Mac OS X. ========================================================================= ============ Changes from 4.4.0 RC2 to 4.4.0 (December 2009) ============ ========================================================================= Fix an integer overflow problem with polygon3d(). Work around DSCAPS_PRIMARY16BIT capability flag not being set in DirectAudio driver. Avoid a potential divide-by-zero in non-FM synth case in OSS MIDI driver. Name DLL as alleg44.dll not alleg.dll. Various minor changes to build system and example programs. ============================================================================= ============ Changes from 4.4.0 RC1 to 4.4.0 RC2 (November 2009) ============ ============================================================================= Peter Wang replaced the old build system with a new one using CMake. Please see docs/build/cmake.txt. Peter Wang disabled the Linux console port by default. Most people use X11 exclusively now. Peter Wang made the build system install pkg-config .pc files on Unix-like systems. Trent Gamblin added _trans and _lit versions of all rotate_* and pivot_* functions. New example: exrotscl. Francis Devereux made it possible for keyboard events to go to other windows when the Allegro window does not have focus, on Mac OS X. Fixed various compilation issues. ======================================================================= ============ Changes from 4.3.10 to 4.4.0 RC1 (April 2009) ============ ======================================================================= Christer Sandberg fixed a crash when omitting the end of the glyph interval in the text file for load_txt_font(). Peter De Wachter made the ALSA driver work for hardware which does not support unsigned samples. Milan Mimica fixed display switching on linux console driver. Milan Mimica fixed various glitches related to the build system in the core library and addons. Milan Mimica added support for MSVC6/7/8/9 to logg and loadpng. David Capello fixed the BMP loader to handle (valid) .bmp files with negative heights and other uncommon features. Peter Hull added Mac OS X (non-universal) build support for loadpng and logg. Peter Wang made configure and fix.sh scripts more robust. Paul Suntsov made a replacement function for do_ellipse() which produces accurate ellipses and much more rapidly. Milan Mimica added supprot for macosx-universal binary to addons. Elias Zacarias added a function that allows users to intercept window events on Windows. Scott McCreary and Grzegorz Dabrowski made the BeOS port compile on Haiku. diedel started a Playstation Portable port. (Alpha status) Edgar Reynaldo provided mouse_on_screen() function. Edgar Reynaldo added functions that can be used to determine the graphics mode type of arbitrary graphics drivers at runtime. Edgar Reynaldo improved the behavior of the file_select_ex* functions. Various minor improvements and fixes. ===================================================================== ============ Changes from 4.2.2 to 4.3.10 (January 2008) ============ ===================================================================== Milan Mimica integrated the following addons into the Allegro build system: AllegroGL, loadpng, JPGalleg, logg. Not all addons currently build on all platforms, but Unix and MinGW are supported by all. Milan Mimica disabled support for asm mode on all platforms. This was previously the default for non-x86 architectures. Jon Rafkind and Milan Mimica implemented draw_sprite_ex() function and added an extrans2 example. Milan Mimica integrated the "skater" demo game and renamed the classic demo to "shooter". The skater demo was written by Miran Amon, Nick Davies, Elias Pschernig, Thomas Harte & Jakub Wasilewski. AJ added detection for SSE3, SSE4.1 and SSE4.2 Matthew Leverton fixed a problem with filename encoding and the SYSTEM_NONE driver on Windows. 8L45T3R fixed a bug in arc() function, where small arcs would be drawn as circles. David A. Capello fixed a problem on Windows where the NumLock, ScrollLock and CapsLock flags are not registered in the key_shifts flag until at least one key is pressed. Christer Sandberg fixed a memory leak where datedit_exit would not free datafile properties. (bug #1808894) Robert Riebisch fixed warnings from gcc 4.x about unnecessary 'packed' attributes being ignored on some data structures in the VESA and VBE/AF drivers. (bug #1729552) Matthew Leverton renamed MID() to CLAMP() and introduced a new MID() that returns the median of x,y,z for all cases. Various minor improvements. ====================================================================== ============ Changes from 4.2.3 to 4.2.3.1 (October 2009) ============ ====================================================================== Francis Devereux made the OS X port compile on Mac OS X 10.6. ==================================================================== ============ Changes from 4.2.2 to 4.2.3 (October 2009) ============ ==================================================================== Fix fnstsw compile bug with newer binutils. Trent Gamblin made a small change to the Windows mouse driver to add support for touchscreens (at least 1 of them). Peter De Wachter made the ALSA driver work for hardware which does not support unsigned samples. Matthew Leverton fixed a problem with filename encoding and the SYSTEM_NONE driver. Added set_filename_encoding(), get_filename_encoding(). Milan Mimica made the MinGW and MSVC makefiles add the suffix "_c" onto non-asm builds, and clarified that user programs linking against the non-asm libraries must also defined ALLEGRO_USE_C. Mixing calling conventions causes segfaults when functions are inlined. AJ added detection for SSSE3, SSE4.1 and SSE4.2 David A. Capello made key_shifts work properly on Windows for Control, Alt, and Shift. Clarified that set_config_file() does not search for the given config file in other locations, as Allegro does with allegro.cfg at initialization. Fixed buffer overflow in exgui. Fixed problems with newer versions of autoconf. ===================================================================== ============ Changes from 4.2.2 RC1 to 4.2.2 (July 2007) ============ ===================================================================== Matthew Leverton added build instructions for DMC and updated the MSVC project files and instructions. Matthew Leverton added a shell script wrapper around gcc to build universal binaries (i386 + PPC) on Mac OS X and made the Allegro makefile use it. Peter Hull reenabled the Quit menu option on Mac OS X when set_close_button_callback is used. Rikard Peterson fixed the Mac OS X joystick driver so that HID_ELEMENT_STANDALONE_AXIS axes correctly got the flag JOYFLAG_UNSIGNED and not JOYFLAG_DIGITAL. Matthew Leverton fixed a problem with the GDI driver blitting a rectangle smaller than the bitmap's height that touches the bottom left corner of a bitmap. Some minor changes. ===================================================================== ============ Changes from 4.2.1 to 4.2.2 RC1 (July 2007) ============ ===================================================================== Matthew Leverton added project files for MSVC 6/7/8 (see the build directory and Allegro Wiki for instructions). Matthew Leverton added initial support for the Digital Mars C compiler (for the Windows port). It only works with the C-only port and obj\dmc\plugins.h needs to be built by hand. Peter Wang cleaned up most of the autoconf namespace pollution. Matthew Smith made a fix for C locking code in GDI. Trent Gamblin made the fullscreen DirectX driver save and restore the palette when switching away and back in 8-bit video modes. Elias Pschernig added missing documentation for pack_ungetc(). Trent Gamblin fixed the C version of stretch_blit so it now draws correctly. He also made it about 20% faster along the way. orz and Matthew Leverton made the ALLEGRO_USE_C=1 option to work under MinGW and MSVC. Erno Schwetter fixed a long-standing bug in polygon() where the bottom-most pixels would not be drawn. Anthony 'Timorg' Cassidy made d_menu_proc fill up its assigned area with the gui_bg_color. Phil Krylov fixed a bug that prevented load_bios_font() from loading 8x16 fonts. Etienne Vouga fixed a bug with the reset_controllers MIDI command. Milan Mimica fixed a double SWITCH_IN event callback bug when de-minimizing an Allegro program in Windows. Erno Schwetter fixed a bug where __al_linux_console_fd was used in display_switch_lock() without the console being initialized first. Erno Schwetter fixed an unbalanced __al_linux_console_graphics() call. Ryan Patterson fixed a crash in free_config_entries. Elias Pschernig added support for horizontal wheel mice (so far, only the X11 driver reports any horizontal wheel movement though). Also increased the number of supported mouse buttons from 3 to 5 for the X11 driver. Jon Rafkind and Karthik Kumar fixed a problem where allegro-config would respect neither --libdir nor --includedir. Peter Wang fixed some problems with the ALSA MIDI driver in the case of failure. torhu fixed a bug in akaitest where an array was indexed with -1. Trent Gamblin implemented set_mouse_speed under X11. Peter Wang made setting stick only while the cursor is in the Allegro window. Evert Glebbeek added desktop_color_depth and get_desktop_resolution to the Linux fbcon driver. Matthew Leverton fixed building of universal binaries on MacOS X. This currently requires OS X 10.4 on both PPC and Intel. Milan Miminca made the fbcon driver initialization fail if an unsupported color depth was set. Michal Molhanec and Milan Mimica simplified the MSVC build process and updated the documentation. Andrei Ellman made the MSVC makefile compatible with cygwin port of make-3.81 (and newer?). makefile.vc now uses cygpath tool to convert DOS 8.3 paths to unix-style paths. Daniel Schlyder added a functions is_trans_font, font_has_alpha. Daniel Schlyder made load_txt_font() additionally search for files referenced in the font script in the same directory as the script itself. It still searches in the current working directory first (for relative paths). Daniel Schlyder documented that register_assert_handler() and register_trace_handler() can be called before initialising Allegro. Daniel Schlyder prevented the Windows port from registering its default trace handler on initialisation if the user had previously registered a custom trace handler. Andrei Ellman modified the 6-to-8 bit value scaling tables to be more evenly distributed, and changed the implementation of create_blender_table() to create a more evenly distributed distribution of the lower 2 bits. It should be faster as well. Other minor bug fixes and documentation updates. ========================================================================= ============ Changes from 4.2.1 RC1 to 4.2.1 (November 2006) ============ ========================================================================= Peter Wang made the Unix ports query the memory page size with sysconf() when necessary, instead of using the PAGE_SIZE constant, which seems to be Linux-specific. Matthew Leverton gave the STATICRUNTIME builds of MSVC new names by appending _crt (c run time) to the libraries. He also fixed the problem of incorrectly setting the EMBED_MANIFEST variable when using the STATICRUNTIME. Andrei Ellman fixed an inverted test in pack_fopen_chunk on Windows. Peter Hull made 32-bit icon generation by fixbundle endian-independent (colours were incorrect on Intel Macs). Peter Wang fixed a long standing bug where some compressed packfiles would not be read back properly (premature EOF). Reported by jman2050. Andrei Ellman spotted a free() of an internal buffer returned by tmpnam(). Peter Hull fixed a problem with mouse-related deadlock on MacOS X as reported by Mike Farrell. Peter Hull implemented simulation of video bitmaps on MacOS X, so that page flipping will work. Peter Hull fixed an endian problem in the digital sound driver on MacOS X. Elias Pschernig and Chris Robinson fixed problems with UTF-8 filenames under Unix, as reported by Grzegorz. Non-ASCII non-UTF-8 filenames remain broken. Chris Robinson fixed some problems with non-ASCII filenames under Windows. Elias Pschernig made the X11 driver call XInitThreads, to make Mesa-OpenGL work together with Allegro. It can be disabled at runtime through a config variable. Andrei Ellman fixed a bug in datedit.c that could crash the grabber. Elias Pschernig added file_size_ex(), which returns a 64 bit integer to handle large files. Ron Novy made improvements to the test program. Peter Hull fixed problems with set_mouse_sprite() on Intel Macs. Peter Hull added universal binary support to the MacOS X port. Peter Wang and Evert Glebbeek independently fixed a problem with dependency generation for MacOS X on non-Mac systems. Many smaller fixes and updates by Peter Hull, Elias Pschernig, Peter Wang and Milan Mimica. ==================================================================== ============ Changes from 4.2.0 to 4.2.1 RC1 (May 2006) ============ ==================================================================== Michal Molhanec made msvchelp.exe work on Cygwin, where there was a problem with the case-insensitivity of environment variables. Reported by Milan Mimica. Peter Hull fixed a bug where Allegro detected keypresses on KEY_MINUS_PAD as KEY_PLUS_PAD. Peter Hull made OSX work correctly with Logitech sticks, as discussed with Ultio. Milan Mimica fixed some spin loops in the test program. Chris Robinson added UTF8/Unicode support for filenames in Windows. Milan Mimica made the Linux console driver more robust: set_gfx_mode used to get stuck in a infinite loop when there wasn't a console available. Evert Glebbeek made the C blitter use memmove for normal blits, with a bugfix by Milan Mimica. This can be disabled by removing a #define USE_MEMMOVE at the top of cblit.h so that it can easliy be tested against the older versions of the code. Christer Sandberg worked around a problem where one-line high bitmaps would crash with Electric Fence. Chris Robinson fixed a crash that occurred if the sound mixer quality level was set to 0 after the mixer was already initialised. Evert Glebbeek fixed the window title under X11, which was broken by a previous change. Peter Hull updated the endian detection under OSX as recommended by Apple. Miguel A. Gavidia and Jay Bernardo made qtmidi.m work on both PPC and Intel. Milan Mimica fixed a crash when vsync() on certain drivers. Elias Pschernig replaced the ALLEGRO_USE_C define with ALLEGRO_NO_ASM. Peter Wang restored the JACK driver to compiling state. Milan Mimica made the new transparent fonts be recognized as color fonts with is_color_font. Elias Pschernig made the modules path WIP version specific, for enhanced binary compatibility. Stijn Wolters clarified the documentation of init_dialog. Hans de Goede fixed a problem with dynamically generated stretcher code not being properly marked as executable on Linux (esp. SELinux). Hans de Goede fixed a busy wait in the X11 vsync simulation. Elias Pschernig makde it so modules under Unix are now searched in libdir as passed by the build machinery. Closes bug #1401840 from SF, reported by Paul Eipper. Milan Mimica added a get_volume and a get_hardware_volume function, to work as pendants to set_volume and set_hardware_volume. Milan Mimica corrected a case where a wrong structure on the stack was being cleared in the DirectSound input driver. Hans de Goede added a fullscreen driver for X11 which does not need XVidMode extension, and instead simply centers the window on the desktop and draws a black border around. Hans de Goede fixed a problem where switching to fullscreen mode under X11. Serge Semashko added Enter as a fire key in the demo game. Serge Semashko added fixed problems with Allegro working on Nokia 770. Peter Wang fixed some problems with binary compatibility checking in the 4.2 branch. Catatonic Porpoise added OpenBSD detection (in addition to FreeBSD and NetBSD) and fixed an issue with executable rights not set on the memory for the i386 stretcher on UNIX systems. Hans de Goede fixed a bug preventing the ALSA driver to work on big endian systems. Elias Pschernig and Chris Robinson fixed binary compatibility checking in allegro_init and install_allegro. Catatonic Porpoise fixed the example in the documentation of stretch_sprite. Hans de Goede made DIGMID work with absolute paths in the patches.cfg file. Peter Hull added code to make Allegro work better with user-supplied Nibs under OSX, as discussed with Thomas Harte. Matthew Leverton added embedding of manifests to the MSVC 8 build process. Neil Walker and Thomas Harte implemented a hardware accelerated stretch_blit() for the Windows DX port. Evert Glebbeek corrected a bug when destroying sub-bitmaps under Windows. Evert Glebbeek fixed a bug in pack_fopen_chunk() where a temporary file would be created in a non-writable location. Peter Wang changed a "/lib" option to MSVC's link utility to "-lib" as reported to be problematic by Karthik Kumar. Peter Wang fixed a crash in dat and grabber due to the return value of pack_fopen_chunk() not being checked. Elias Pschernig added support for anti-aliased bitmap fonts. Dennis Busch fixed the short description of add_clip_rect. Thomas Harte and Neil Walker fixed a problem with draw_sprite() and sub-bitmaps. Peter Wang fixed scancode_to_name(KEY_NUMLOCK) returning "PAUSE" in Windows. Peter Wang fixed page flipping and triple buffering in the demo game. Elias Pschernig added list_config_sections and list_config_entries functions. Hrvoje Ban added create_datafile_index and load_datafile_object_indexed functions. Peter Hull allowed use of "mingw" instead of "mingw32" in fix.bat and fix.sh. Peter Wang fixed a bug with SWITCH_BACKAMNESIA mode with the fbcon graphics driver. Peter Wang made the svgalib driver save and restore the palette on VT switches. Peter Wang fixed a problem with the fbcon driver and VT switching. Milan Mimica delayed Linux console initialisation until it is required. This way the user can write command-line programs using timers without needing a real console. Chris Jones fixed behavior of numeric keys when NumLock is on. Vincent Penecherc'h worked around a problem with 24-bit bitmaps in the assembler code. Tobias Dammers fixed a problem with the DirectSound input driver. Matthew Leverton fixed Ctrl-Alt-Del mistakenly being captured by Allegro under Windows Vincent Penecherc'h improved the implementation of set_ramp_cmap in the fbcon driver. Vincent Penecherc'h implemented get_refresh_rate for the fbcon driver. Vincent Penecherc'h fixed problems with the fbcon driver not restoring the original video mode when the driver exits. Victor Williams Stafusa da Silva made OS type detection handle Windows 2003 and Windows Vista. Chris Jones and Vincent Penecherc'h fixed load_wav to handle degenerate stereo wave files with an odd length. Annie Testes fixed all sorts of problems with the linux evdev mouse driver when using a tablet as the mouse. Annie Testes made the linux evdev mouse driver use the correct device files. Vincent Penecherc'h made the linux fbcon driver set a ramp colourmap for directcolor modes, otherwise colours in those modes were all wrong. Vincent Penecherc'h fixed a problem with the linux fbcon driver, where it would keep using the old pitch after changing resolutions. Serge Semashko fixed a typo causing crashs in _linear_draw_trans_rgba_rle_sprite24. Annie Testes fixed cursor speed and incorrect mickey computation bugs in the Linux evdev mouse driver. Vincent Penecherc'h made the Linux PS/2 mouse driver try /dev/input/mice by default, in addition to /dev/mouse. Warnings, code formatting and minor changes to code and build system by Milan Mimica, Evert Glebbeek, Elias Pschernig, Peter Wang, Peter Hull, Thomas Harte, Vincent Penecherc'h and Chris Robinson. Documentation updates by Tore Halse, Elias Pschernig, Milan Mimica, Peter Wang, Physics Dave, Ryan Patterson, Grzegorz Adam Hankiewicz, Andrei Ellman and Evert Glebbeek. ========================================================================= ============ Changes from 4.2.0 RC2 to 4.2.0 (November 2005) ============ ========================================================================= Peter Wang made fixmul() detect overflows as it used to do in the 4.0.x branch. Peter Hull fixed a bug in the fixbundle utility. Dennis Busch found a bug where d_clear_proc would not work properly if the GUI target bitmap is different from screen. Grzegorz Adam Hankiewicz made Allegro log all TRACE output with a prefix in the format "al-system level: ". This makes it easier to grep debug logs. Grzegorz Adam Hankiewicz made dialogs with MSG_CHAR/MSG_UCHAR handlers honor a D_CLOSE return flag without a D_USED_CHAR. Peter Hull fixed problems with the mouse position as reported by Allegro and the mouse position as known to OS X. Peter Hull made Command-Q not close the application if no exit-button callback is registered. Peter Hull fixed problems with joysticks under MacOS X as reported by Thomas Harte. Peter Hull fixed a bug preventing more than one Allegro application from being run at a time on Mac OS X. Reported by Thomas Harte. Peter Hull did a lot of other things for the MacOS X port too. Jiri Gabriel fixed loading of multiple ranges in a single bitmap with txt fonts. Milan Mimica and Jiri Gabriel fixed several bugs in extract_font_range. Dennis Busch fixed a Unicode bug in the mode selector. Evert Glebbeek added FA_ALL and FA_NONE file attribute flags. Peter Hull fixed a deadlock in OS X when calling vsync() while the screen was acquired. Robert Alfonso fixed a grabber crash when importing a new font range into an existing font. Reported by Milan Mimica. Chris Robinson fixed the fileselector in UNIXnot properly recognising filenames containing UTF-8 characters. Hrvoje Ban and Peter Wang wrote a documentation section that explains several common mistakes. Elias Pschernig disabled DGA auto-detection under X11 i_am_drv added support for .rmi midis to the midi reader Elias Pschernig fixed a fix-point overflow in pivot_sprite. Michal Molhanec fixed several problems with the Watcom compiler. Peter Hull fixed an error with 'make uninstall' on MacOS X. Matthew Leverton added a programs: makefile target. Many small fixes and improvements by Michal Molhanec, Peter Hull, Chris Robinson, Peter Wang and Elias Pschernig. Documentation improvements by Grzegorz Adam Hankiewicz, Tore Halse and Peter Hull. =========================================================================== ============ Changes from 4.2.0 RC1 to 4.2.0 RC2 (August 2005) ============ =========================================================================== Grady Martin made the grabber consider deleting object properties as a change to the datafile. Milan Mimica fixed numerous bugs in extract_font_range(). Peter Hull moved the 'magic chdir' in the MacOS X port to earlier in the startup process, so that the config file will be looked for in the resource directory if is present. Chris Robinson made create_bitmap(0,0) not return a bitmap that would later crash destroy_bitmap(). Zero-sized bitmaps are still not allowed so the assertions for debug mode have not changed. Elias Pschernig patched the Windows keyboard driver to get key_shifts working again with KB_SHIFT_FLAG, KB_CTRL_FLAG, KB_ALT_FLAG on Win98. Peter Wang changed hline and vline into aliases for internal symbols to avoid a conflict with the curses API. This change should be transparent for users. Matthew Leverton and Michal Molhanec updated the build system for MSVC 8. Grzegorz Adam Hankiewicz prevented make_relative_filename() from crashing with malformed parameters. Hrvoje Ban made ASSERT() actually abort in Windows. Chris Robinson made GUI menus work with gui_screen. Evert Glebbeek fixed reading of 32 bit Windows .bmp files, which was not supported. These files seem to be not very standard though, so it's unclear if it will always do the right thing. Alpha channels also seem not to be standard in 32 bit BMP files, so it's possible they're not read in correctly. Peter Wang and Peter Hull updated the ABI compatibility document. This documents our policy for the 4.2.x series. Extensive documentation updates from Grzegorz Adam Hankiewicz and minor updates due to Michael Faerber, Robert Ohannessian and Milan Mimica. ============================================================================== ============ Changes from 4.2.0 beta 4 to 4.2.0 RC1 (August 2005) ============ ============================================================================== Peter Hull fixed the MacOS X port to avoid an issue with the dead bootstrap context and cleaned up the dock notification. This means command line apps (with SYSTEM_NONE) run without the dock being notified. Peter Wang Added a COLORCONV_KEEP_ALPHA flag, as suggested by Gideon Weems. Peter Wang fixed issues with OSS in OpenBSD and made the configure script print a warning if Allegro is compiled without X11 support. Peter Hull set the compatibility version to 4.2.0 for MacOS X and added a MacOS X help file. Peter Wang made the Mode-X and VBE/AF drivers fail if Allegro is compiled as a C-only library in Linux and made the Unix port install liballeg*.so and the alleg-*.so modules with the execute permission enabled. Grady Martin standardised some of the grabber dialog boxes and added a `move' command to the grabber. Evert Glebbeek fixed a bug when loading some old datafiles containing monochrome fonts. Evert Glebbeek fixed a bug that prevented system cursors from working correctly in Windows. Olivier Blin fixed compilation problems for the ModeX driver with newer binutils. Shawn Walker fixed a bug in get_executable_name under some UNIX systems. Shawn Walker worked around a problem with some versions of GNU AS and fixed some errors in the configure script when not using GCC. Elias Pschernig made create_sample not unnecessarily clear the sample to 0. Bobby Ferris fixed the makedoc SciTE API output. Elias Pschernig fixed a too strict assert that prevented set_volume from working in debug mode. Paavo Ahola helped fix a problem with BCC and the C implementations of fixmul. Elias Pschernig fixed a cosmetic bug where the listbox was drawing a too big selection rectangle, reported by dthompson. Documentation and example updates by Grzegorz Adam Hankiewicz, Peter Wang, Elias Pschernig Michal Molhanec and Evert Glebbeek. =============================================================================== ============ Changes from 4.2.0 beta 3 to 4.2.0 beta 4 (June 2005) ============ =============================================================================== Matthew Leverton changed the default behavior of the grabber: default color depth is now the desktop, default mode is windowed and if fullscreen is specified, then desktop resolution is used by default. Peter Wang fixed compilation problems related to get_modex_screen() on UNIX and deprecated it. Robert Ohannessian fixed compilation problems for the assembler code with newer binutils. Peter Wang, Thomas Harte and Evert Glebbeek optimised fixmul() for different platforms. Robert Alfonso fixed a couple of warnings that with DJGPP. Grzegorz Adam Hankiewicz made the FLIC player yield. Miran Amon fixed an arbitrary limit in get_config_argv(). Evert Glebbeek fixed a memory leak in same. Thomas Klausner fixed a problem in allegro.m4 and automake 1.8+. Charles Wardlaw fixed some warnings with gcc 4 on MacOS X. Elias Pschernig removed the `256 items' limit from the dat utility. Julien Cugniere fixed a crash in the GUI if a new dialog was opened while a menu was still open. Shawn Walker fixed crashes with the keyboard driver under Solaris. Elias Pschernig split the demo game into multiple files and made the makefile handle a multi-file demo game. Evert Glebbeek fixed a bug where the hardware mouse wasn't displayed in Windows until the mouse was moved. J.P. Morris fixed rest_callback() under UNIX. Shawn Walker and Evert Glebbeek fixed get_executable_name() under Solaris and OpenBSD. Peter Hull fixed compilation problems with setAppleMenu under Tiger. Peter Hull fixed a deadlock on MacOS X related to mouse updating. Peter Wang fixed a problem with compiling the VBE/AF driver using newer binutils. Evert Glebbeek fixed a bug with colour conversions when loading a font from a datafile. Many code, example and documentation updates by Grzegorz Adam Hankiewicz, Elias Pschernig, Peter Wang, Evert Glebbeek, Andrei Ellman, Victor Williams Stafusa da Silva, Matthew Leverton, AJ, Michal Molhanec and Hrvoje Ban. ============================================================================== ============ Changes from 4.2.0 beta 2 to 4.2.0 beta 3 (May 2005) ============ ============================================================================== Grzegorz Adam Hankiewicz did several documentation updates. Evert Glebbeek cleaned up some of the global namespace pollution in the Windows port. Chris Robinson made improvements to the Windows sound driver. Chris Robinson made the GUI multi-selection box behave a bit nicer. Grzegorz Adam Hankiewicz added a bunch of ASSERTs to the code to check for out-of-range arguments. Jakub Wasilewski fixed a bug when loading greyscale TGA images. Evert Glebbeek fixed a bug where the bottom and right line of pixels was not updated on show_video_bitmap, as pointed out by Thomas Harte. Evert Glebbeek documented JOY_TYPE_* defines for Windows and Linux. Dark Nation restored the ability to read old-style encrypted packfiles, i.e. those produced before Allegro 3.9.30. This was silently removed from 4.1.18 when custom packfile support / decoupled compression routines were added. Evert Glebbeek made the grabber and dat utilities now use Allegro's builtin load_font() function and made datafiles properly store truecolour fonts and added a datedit_select() callback to datedit. Evert Glebbeek fixed some unsafe assumptions on the size of integer data types. Arthur Huillet fixed a typo in the docs. Elias Pschernig restored Alt+key = ASCII code 0 behavior for the Windows keyboard driver Evert Glebbeek fixed a bug that caused a crash when loading Allegro 1.x datafiles containing 4 bit bitmaps. Peter Wang clarified the mode select documentation and made the mode selector clear the input variables before passing them on to the filter. Peter Wang fixed a bug in the mode selector where disabled drivers were still shown with empty resolution lists. Pointed out by Hrvoje Ban. Elias Pschernig fixed Allegro's internal multithreading in Windows. This fixes a deadlock on exit. Robert Alfonso made the MSVC makefile call `link /lib' rather than `lib', which doesn't work for the free toolkit. Peter Hull fixed a problem with hardware cursors not working properly in MacOS X. Peter Hull added a missing enable_hardware_cursor vtable entry and added OS native cursors for the MacOS X port. Grzegorz Adam Hankiewicz documented the online Allegro patch generator. Evert Glebbeek renamed datafiles._tx -> datafile._tx StApostol updated the FAQ to use rest(0) instead of the deprecated yield_timeslice(). Evert Glebbeek silenced some GCC4 warnings in MacOS X. Peter Wang fixed warnings and errors with gcc 4.0.0 on the Unix port; reported by Milan Mimica. Peter Wang added the preprocessor symbol ALLEGRO_NO_FIX_CLASS that the user can define to not pull in the `fix' class in C++ programs. Peter Wang removed the exdodgy example. Elias Pschernig fixed another X11 async reply bug. Elias Pschernig made the seek in expackf test work with CR/LF line endings. Evert Glebbeek fixed a small bug that prevented the Allegro template for Project Builder from installing correctly on MacOSX. Elias Pschernig enabled warnings about unused variables with --enable-strictwarn in unix. Peter Wang fixed a warning with Watcom 1.3. ================================================================================ ============ Changes from 4.2.0 beta 1 to 4.2.0 beta 2 (April 2005) ============ ================================================================================ Daniel Schlyder fixed a problem with the makefile in Windows. Evert Glebbeek fixed a bug that prevented true colour fonts from working. Peter Wang fixed a possible deadlock in dialog_message. Elias Pschernig fixed a bug where the DJGPP version would choke on a missing variable. Peter Hull made makedoc return an error code if it failed to build the SciTE documentation. Evert Glebbeek fixed a problem with incorrect dependencies being generated for MacOS X. Tobi Vollebregt fixed a problem in X11 if the XRGBACursor extension was missing. Evert Glebbeek made configure use k8 rather than athlon64 as a compiler switch on AMD64. Peter Wang and Elias Pschernig added a packfile example. Michal Molhanec fixed a problem in the MSVC makefile. Evert Glebbeek removed void*-arithmetic from the colour converter. Evert Glebbeek fixed a bug where hardware cursors would stop working. Elias Pschernig, Andrew Chew fixed and Tobi Vollebregt fixed several problems with the Windows keyboard driver. Elias Pschernig fixed bug in unix dependency generation. Elias Pschernig made the GUI not mess up the hardware cursor. Elias Pschernig removed pckeys.c and keyconf from the windows port, since the dinput driver no longer needs pckeys.c nor uses keyboard.dat. Daniel Schlyder fixed a problem with the -mtune switch on older gcc based compilers. Matthew Leverton figured out which versions of Watcom have inttypes.h and stdint.h. V Karthik Kumar added a password to the Windows screensaver example. Cosmetic fixes, example bugfixes and spelling corrections by Jon Rafkind, Evert Glebbeek, Peter Wang, StApostol and Elias Pschernig. ======================================================================== ============ Changes from 4.1.18 to 4.2.0 beta (March 2005) ============ ======================================================================== Peter Wang fixed many problems on AMD64 in Linux - it should now work fine. Peter Hull added CPU detection to the MacOS X port. Peter Hull fixed some problems related to /usr/local/bin not existing in recent versions of MacOS X. Elias Pschernig and Peter Wang rewrote the Windows keyboard driver so it no longer needs keyboard.dat. Elias Pschernig added a show_os_cursor function as an alternative to show_mouse() for system cursors. Evert Glebbeek and Peter Wang added an example programme for system cursors. Elias Pschernig fixed a deadlocks in X11 related to scare_mouse() and keyboard repeats and fixed async replies. Daniel Schlyder fixed the gcc -mcpu is deprecated warnings. Peter Wang added an astdint.h, which provides C99 typedefs for pre-C99 compilers. AJ added detection for DirectX 8 and 9 to the Windows port. Evert Glebbeek added detection for AMD64 to the UNIX port and test programme. Elias Pschernig added a get_midi_length function and a midi_time variable. Elias Pschernig fixed a problem where Allegro would ignore a user-specified configuration file if set_config_file() was called before allegro_init(). Evert Glebbeek added a transpose_font function. Evert Glebbeek added support for true colour fonts and a font example. Elias Pschernig fixed a problem in shutdown_dialog() reported by Tobi Vollebregt. Marcio Fialho fixed some issues with displaying author names in the demo game. Andrei Ellman fixed a problem in the MSVC makefile when building Allegro with Cygwin. Daniel Schlyder fixed (again) problems with creating directories in different setups in Windows. Elias Pschernig added documentation for the custom packfile functions. Jeff Mitchell fixed the location of grabber.txt in the spec file. Harshavardhana Reddy added a Kannada greeting to exunicod. Elias Pschernig cleaned up the example programmes. Peter Wang made it possible to disable the hardware cursor in X by passing an option to the configure script. AJ and Michal Molhanec added an MSVC 7 configure option and added an msvc7 switch to fix.bat. Karthik Kumar did the same for the Intel compiler icl. Mr_Bones fixed compilation of setup.c when --disable-ossdigi is used AJ fixed a beep being generated in Windows when alt+character was pressed in Windowed mode. Peter Wang fixed many oversights and problems in the library and examples and allowed the code to be build with stricter warnings. Peter Wang fixed problems compiling the Windows port with WARNMODE=1 Tore Halse fixed compilation problems in Windows related to TITLEBARINFO. Daniel Schlyder made the Windows port use TITLEBARINFO if it is available. Grzegorz Adam Hankiewicz made many improvements to the documentation. ====================================================================== ============ Changes from 4.1.17 to 4.1.18 (January 2005) ============ ====================================================================== Peter Hull fixed a bug that caused rest() to wait too long on MacOS X. Tore Halse made the Allegro window always appear centred in Windows. Peter Wang fixed a lot of warnings in the code and did a lot of cosmetic fixes as well. Grzegorz Adam Hankiewicz added short description support to the MAN and HTML documentation. Milan Mimica fixed a bug in the keyconf utility. Peter Hull fixed some issues compiling Allegro for MacOS X. Marcio Fialho fixed a warning when compiling Allegro with DJGPP. Evert Glebbeek fixed a bug that prevented system cursors from working in Windows, as pointed out by Peter Johansson. Evert Glebbeek added a font loading routine and various other font functions to the library. Peter Wang added custom packfile functions and packfile vtables. Peter Wang decoupled the packfile compression code from the packfile routines. Daniel Schlyder fixed some problems with the font loading code. AJ added IA64, SSE3 and AMD64 detection code. Daniel Schlyder fixed some warnings with MinGW gcc 3.4.2 Peter Hull made the file selector work properly with directories that have more than 2048 entries. Marcio Afonso Arimura Fialho fixed some problems with the DJGPP version and the VBE/AF driver. Phil Shenk clarified the MSVC build docs. Michal Molhanec fixed a problem with long filenames in the MSVC build process and added a --msvcpaths flag to the fix.bat script. Grzegorz Adam Hankiewicz made a lot of improvements to the documentation. Peter Wang made some modifications to allegro_message() in X11. Evert Glebbeek added blender mode defines and activated the gfx_vtable set_blender_mode() function in the source. Evert Glebbeek added gui_set_screen and gui_get_screen functions and a set_mouse_cursor_bitmap function. Peter Wang made scancode_to_name never return NULL. Peter Wang fixed some problems in the Linux joystick driver. Grzegorz Adam Hankiewicz added a lot of ASSERTions to the code. Elias Pschernig added special Ctrl-Alt-End and Pause key handlers to the X11 keyboard driver. Elias Pschernig fixed a problem with the mouse acceleration in Windows. ======================================================================= ============ Changes from 4.1.16 to 4.1.17 (December 2004) ============ ======================================================================= Sven Sandberg fixed a few problems with the sprite rotation code. Sven Sandberg optimized blitting between different colour depths. Evert Glebbeek added support for the use of native window manager cursors. Chris Robinson made install_allegro() check if the library version matches the version of the header files installed. Peter Wang fixed some problems with rest() on UNIX systems. Evert Glebbeek added an is_windowed_mode() function. Elias Pschernig added the scancode_to_name function. Elias Pschernig made rest use usleep() on MacOSX. Chris Robinson fixed the incorrect use of -export-dynamic on UNIX Elias Pschernig, Chris Robinson and Peter Wang fixed XOR mode leaving droppings in X11. Elias Pschernig fixed several dependency issues. James Lohr fixed a problem with mouse acceleration in fullscreen modes under Windows. Peter Wang fixed a problem in the TGA loader. Lennart Steinke contributed keyboard layout detection code for Windows. Peter Wang fixed a bug that caused Allegro to crash if it failed to initialize. Peter Wang fixed a deadlock related to X vsync emulation. Daniel Schlyder fixed make uninstall with mingw make. Elias Pschernig fixed QNX issue of not including utimer.c Angelo Mottola fixed compilation problems on BeOS and fixed the detection of VRAM. Evert Glebbeek fixed compilation problems on *BSD. Elias Pschernig made the X11 window hidden in GFX_TEXT mode. Peter Wang removed remapping of numpad keys when NumLock was off in Linux David A. Capello made override_config_file also be used for writing to the config file. Julien Cugniere added an X11 message box for allegro_message under X11. Vitaliy Chetverikov a small bug in the GUI where the return value of MSG_IDLE was ignored. Peter Wang made several improvements to the examples. Grzegorz Adam Hankiewicz made a lot of improvements to the documentation. Elias Pschernig made make-install not build examples. Peter Wang fixed several instances of symbols not declared static that should have been. Elias Pschernig replaced the X11 keyboard driver with a new XIM driver. Peter Wang fixed a problem with Linux headers and Allegro headers both declaring KEY_ constants, as pointed out by David A. Capello. Elias Pschernig fixed X11 async reply in DGA2 mode detection due to missing XLOCK/XUNLOCK Peter Wang fixed problems in ex3buf, which was trying to lock symbols which had been removed. Elias Pschernig cleaned up grabber/dat documentation. Daniel Schlyder added ALLEGRO_LIB_BUILD flag for gcc variants not using configure. Elias Pschernig fixed bugs in matrix_to_quat and get_align_matrix. Evert Glebbeek fixed a problem with the X11 port when ALLEGRO_MULTITHREADED was not defined. Matthew Leverton added support for a fourth mouse button to the Windows port. Michal Molhanec added a FAQ section about the giftware license. Elias Pschernig added the license disclaimer to the docs. Evert Glebbeek added missing vtable entries for AllegroGL, as requested by Robert Ohannessian. Dustin Dettmer spotted a typo in save_bitmap. Sam Hocevar removed deprecated use of init_read_test, test_byte_read, etc. Peter Wang fixed a bug in the Windows keyboard driver. ====================================================================== ============ Changes from 4.1.15 to 4.1.16 (October 2004) ============ ====================================================================== Peter Wang fixed two problems with the keyboard driver on Windows. Chris Robinson fixed a problem causing some components to wrongly initialized in Windows when the window is set. Elias Pschernig added chapters to the documentation. Chris Robinson fixed a bug where the X11 fullscreen driver would fail if no virtual screen was reported. Daniel Schlyder added a set_allegro_resource_path() function . Elias Pschernig fixed an issue with xf2pcx. David A. Capello made makedoc write sub-section headings for .txt output. Evert Glebbeek added hardware cursor support to the X11 and DirectX window drivers. Peter Wang made the Linux joystick driver read more than one joystick event at a time, as pointed out by Greg Lee. Evert Glebbeek removed the need for magic main under UNIX and added a --enable-magicmain option to the configure script. Evert Glebbeek fixed a crash when initializing, deinitializing and reinitializing Allegro on Windows. Evert Glebbeek fixed a possible memory protection problem in stretch_blit on Windows XP SP2, as suggested by Chris Robinson. Chris Robinson fixed set_palette() not waiting for vsync in X11. Peter Wang deprecated the retrace simulator. Daniel Verkamp contributed a MIDI input driver for the Windows port. Chris Robinson improved the speed of drawing primitives on X11 and implemented locking/unlocking for video bitmaps. Evert Glebbeek fixed a problem with the build process on non-intel UNIX systems. Peter Wang fixed a problem with programs aborting on exit under X11. Peter Wang disabled VBE/AF by default on Linux. Sam Hocevar fixed a bug where makedoc would crash for missing @erefs. Peter Wang made the mouse movement appear smoother. Chris Robinson made the file routines work with files containing a # in the filename. Peter Wang fixed a bug in remove_int(). Bobby Ferris added SciTE .api file generation to makedoc. Sam Hocevar made is possible to put functions defined in assembler source files in a shared library in UNIX. Evert Glebbeek removed the weak declaration of allegro_icon and changed xfixicon.sh accordingly. Evert Glebbeek made get_executable_name() use procfs on UNIX. Grzegorz Adam Hankiewicz made many improvements to the documentation and to the makedoc tool. Many fixes to source, examples and documentation. =================================================================== ============ Changes from 4.1.14 to 4.1.15 (July 2004) ============ =================================================================== Chris Robinson tweaked tests/play.c slightly. Elias Pschernig deprecated yield_timeslice in favour of rest(0) and adjusted yield_timeslice on BeOS, QNX and MacOS X to behave the same as on other platforms. Eric Botcazou fixed a problem with the asm colour converter. Elias Pschernig fixed some gcc warnings. Vincent Penquerc'h added the ability to pass extra CFLAGS and LDFLAGS on the make command line. Elias Pschernig made ex3buf work outside of DOS. Chris Robinson made the alleg mixer default instead of the DirectX one in windows. Angelo Mottola fixed a bug where vsync() was blocking on a mutex if called when the screen was already acquired in windowed mode. Evert Glebbeek made triple buffering work in the demo if VRAM is a single surface. Jon Rafkind provided an m4 macro for Allegro. Eric Botcazou and Henrik Stokseth made some improvements to the build process. Grzegorz Adam Hankiewicz added various fixes to the documentation and to the documentation generation system. V Karthik Kumar added a Tamil language greeting to exunicode. Chris Robinson and Elias Pschernig reduced lag under X11 when X11 locks are held for too long. Vincent Penquerc'h fixed a problem with dependency generation under bash. Evert Glebbeek added an icon to the X11 port and contributed the xfixicon script. Angelo Mottola fixed an endianess issue when loading/saving 24 bit images from datafiles. Angelo Mottola made datafile plugins return FALSE on error. Angelo Mottola fixed the docs for pack_putc. Vincent Penquerc'h made the grabber choose better default menu shortcuts. Henrik Stokseth enabled the asm color converters for the X11 port. Henrik Stokseth improved buffer security in various parts of the library. Evert Glebbeek made strncpy use sizeof() for fixed length strings. Eric Botcazou made KEY_PAUSE work properly in windows. Chris Robinson improved the threaded UNIX timer code. Elias Pschernig fixed some problems with the ALSA driver. Angelo Mottola made Command-Q and Quit trigger the close_button_callback in OSX. Grady Martin fixed a bug in the handling of %n in the printf style text functions. Chris Robinson rewrote parts of Allegro's mixer. Chris Robinson increased the default volume, which was set very quiet previously. Grzegorz Adam Hankiewicz clarified the behavior of install_mouse. Elias Pschernig improved the pause key behavior. Vincent Penquerc'h added MSG_WANTMOUSE to the GUI. Vincent Penquerc'h sped up get_filename. Chris Robinson implemented the digmid_set_pan function Chris Robinson improved the performance of the DIGMID driver. ==================================================================== ============ Changes from 4.1.13 to 4.1.14 (April 2004) ============ ==================================================================== Elias Pschernig added a missing install dependency on Linux. Elias Pschernig fixed a couple of problems in dat2c. Angelo Mottola polished the MacOS X package builder script. Elias Pschernig added a Jack sound driver to the Unix port. Henrik Stokseth added support for debugging with DMalloc under Unix. Eric Botcazou fixed detection of the ALSA 1.0 MIDI driver. Eric Botcazou fixed compilation with --enable-color8=no under Unix. Angelo Mottola made it possible to link against the Allegro framework with the allegro-config script under MacOS X. Angelo Mottola changed the dynamic lib install name to major.minor to preserve binary compatibility under MacOS X. Angelo Mottola fixed a bug in fixbundle with 32bpp icons and alpha channel under MacOS X. Eric Botcazou improved the cross-compilation support on Linux. Eric Botcazou restored the compensation code for end-of-frame in the FLI player. Daniel Schlyder fixed potentially unsafe constructs in the Windows code. ==================================================================== ============ Changes from 4.1.12 to 4.1.13 (March 2004) ============ ==================================================================== Minor changes and clarifications in the docs by Sven Sandberg, Andy Goth, Jon Rafkind, Nathan Smith and Daniel Schlyder. Elias Pschernig extensively modified the ALSA 0.9/1.0 sound driver to make it work more nicely. Julien Cugniere and Eric Botcazou fixed the crash on exit with the aRts sound driver. Nathan Smith implemented the recursive handling of directories for the dat utility. Eric Botcazou renamed the new '-r' option of the dat utility into '-f'. Omar Cornut improved the handling of KEY_COLON2 on Japanese keyboards. Omar Cornut fixed the Windows joystick driver to handle a weird peculiarity of the DirectInput API. Elias Pschernig corrected the value of the alpha-channel depth field in the header when saving TGA image files. Eric Botcazou fixed again the formula giving the stride value in the Linux framebuffer console. Eric Botcazou restored the pixel-correct version of line() and added fastline() after Doug Eleveld had reported the problem. Andy Goth and Eric Botcazou fixed the constructor support in dat2s on Unix. Angelo Mottola revamped the MacOS X package creation process to make it work under 10.3 and create an enduser package that holds just the shared framework. Angelo Mottola changed the MacOS X shared library building process to have a prebound shared library separated from a small static libray holding just the magic main stuff. Angelo Mottola removed window shadow flickering when moving the program window around on MacOS X. Elias Pschernig changed the behavior of yield_timeslice() to sleeping instead of just yielding. Angelo Mottola made the MacOS X port reuse the screen on the first video bitmap creation and made the screen fade on mode switches faster. Elias Pschernig made d_menu_proc() automatically yield when the dialog is driven by do_dialog(). Elias Pschernig added missing d_yield_proc()s to the grabber. Eric Botcazou fixed a bug which caused too many sliders to be reported in the presence of a POV device on Windows. Chris Jones added support for the bitfield compressed BMP image format. Eric Botcazou removed all uses of GCC's cast-expression-as-lvalue extension in preparation for GCC 3.4. Michal Molhanec replaced all occurences of MingW32 by MinGW in the docs. Omar Cornut bumped the maximum number of buttons per joystick to 32. Eric Botcazou implemented automatic screensaver disabling (only on Windows for the time being). Elias Pschernig added mode 1280x960 to the gfx mode selector. Elias Pschernig fixed the video mode error display in the test program. Eric Botcazou fixed the final animation of the demo game. Elias Pschernig made the X11 gfx driver ignore repeated key-events. Eric Botcazou added set_hardware_volume(). Francisco Pires added an FPS counter and an option to disable vsync to the excamera example. Eric Botcazou and Sven Sandberg documented the limitations of getpixel() and added is_inside_bitmap(). Eric Botcazou added i386 sincos optimization to GCC-based ports. David Capello fixed a bug with FLI frames containing odd-sized chunks. Elias Pschernig and Sven Sandberg improved the GUI focus algorithm. Eric Botcazou modified the dat/grabber plugins interface to expose datafile properties to plugins. Eric Botcazou added a new clipping API and deprecated the old one. Grzegorz Adam Hankiewicz updated the MSVC build instructions. ================================================================== ============ Changes from 4.1.11 to 4.1.12 (Nov 2003) ============ ================================================================== Many minor changes and clarifications in the docs, some of them based on suggestions by Neil Roy, Jon Rafkind, aj, Andrei Ellman and Michal Molhanec. Angelo Mottola made little fixes all over the place in the MacOS X port. Angelo Mottola removed MacOS X 10.1.x source compatibility. Eric Botcazou disabled keyconf on platforms that don't need it. Elias Pschernig shifted key name display so that all keys are visible in the keyconf utility. Stephan Brauss added new keysyms to the X11-to-BIOS conversion table in order to catch missing keycodes for the keypad when NumLock is on. Stephan Brauss corrected a few nits in the Swiss keyboard configuration file. Eric Botcazou disabled the close button support when a user window is registered under Windows. Eric Botcazou changed the default switch mode to SWITCH_BACKGROUND for the Windows port to cure the problems on exit under WinXP. Sven Sandberg improved the previous fix to _parallelogram_map(). Sven Sandberg fixed an overflow in floodfill(). Sven Sandberg fixed the dither blit mode for the Mode-X driver. Angelo Mottola added quality and reverberation settings support to the CoreAudio MIDI driver under MacOS X. Angelo Mottola added high performance CoreAudio digi/midi drivers (default on autodetect) and made little fixes to the old QT Note Allocator and Carbon Sound Manager drivers under MacOS X. KronomanX added a FAQ entry about the conflict between Allegro headers and the C++ 'using' directive. Vincent Penquerc'h let dialog_message() pass user messages to hidden objects. Michal Molhanec simplified the build instructions for Dev-C++. Annie Testes fixed a redrawing problem in the grabber. Vincent Penquerc'h added support for the joystick_device* config variables under Linux. Vincent Penquerc'h added gfx_mode_select_filter(). Peter Wang removed the old Linux async I/O stuff, which had been out of service for a long, long time. Also simplified the Linux standard drivers stuff. Thomas Fjellstrom added (experimental) support for ALSA 0.9.x. John Utz corrected a wrong assumption about the VRAM layout in the Linux framebuffer console driver. Grzegorz Adam Hankiewicz tt-ized text quotes in the HTML version of the docs. Eric Botcazou made the Linux port compile on non-x86 platforms. Stephan Brauss made a few fixes to let the Linux port compile again on Linux 2.2.x systems. Kalle Toivonen fixed a bug in _parallelogram_map(). Eric Botcazou cleaned up the ALSA config variables under Unix. David Cullen added multiple bullets and extra lives to the demo game. Sam Hocevar fixed a race condition in the mixer under Unix w/ threads, Windows, BeOS and MacOS X. Andrei Ellman improved the Windows screensaver. Jon Rafkind implemented the Cohen-Sutherland clipping algorithm for the line() function. Angelo Mottola added an application menu with a Quit item acting like the three fingers salute, in order to better integrate Allegro apps with the Aqua UI guidelines under MacOS X. Jon Rafkind and Vincent Penquerc'h added more ASSERTs to the code. Eric Botcazou added an option to disable vsync when page-flipping. Eric Botcazou added the detection of spaces to the MSVCDir variable for the MSVC port. Grzegorz Adam Hankiewicz integrated the build instructions in the HTML version of the documentation. Angelo Mottola fixed some nits in fixbundle for alpha channel on 32-bit icons under MacOS X. Lisa Parratt improved the performances of the SGI audio driver. Grzegorz Adam Hankiewicz updated and improved the documentation in many places. Grzegorz Adam Hankiewicz added HTML text substitution to the doc processor. Tobi Vollebregt spotted a bug in ustrerror(), which was not returning a pointer to a static buffer. Grzegorz Adam Hankiewicz added more documentation about return values of functions. Grzegorz Adam Hankiewicz added a new section about documentation to ahack._tx. Grzegorz Adam Hankiewicz fixed rare buffer overflows in do_uconvert with very tiny buffer sizes. Serge Semashko fixed a bug with the letter P in the Russian keyboard configuration file. Angelo Mottola let application bundles accept files dragged onto the application icon under MacOS X. Peter Wang fixed save_bmp for better conformance (a couple of header fields were wrong, and dots-per-metre fields were being filled with zero). Julien Cugniere fixed a bug related to the retrieval of the inital volume when no primary buffer was present under Windows. Henrik Stokseth simplified the asm detection test, removed many GNUish preprocessor constructs in the asm files and, as a consequence, let the Watcom port use its own preprocessor on assembly files. Peter Wang prevented non-mmapped memory from being munmapped under Linux. Annie Testes prevented __al_linux_shutdown_vga_helpers from being called unless the corresponding init function was first called under Linux. Sven Sandberg improved the misc/findtext.sh script. Sven Sandberg added support to produce a PDF version of the manual under Unix and to compress the various formats with bzip2. Sven Sandberg made some correction to the Swedish translation file. Eric Botcazou pluginized the new 'Change filename' menu option in the grabber. Eric Botcazou fixed the X11 mouse scrolling bug. Vincent Penquerc'h made it so that modifications to the type or color depth of an image are detected as such by the grabber. Henrik Stokseth added a C++ test, Eric Botcazou integrated it in the build process. Angelo Mottola made several fixes to let Allegro play nice with AllegroGL under MacOS X. Angelo Mottola added proper embeddable framework support to the MacOS X port, modified fixbundle and updated the docs accordingly. Angelo Mottola made external plugins scripts work under MacOS X. ================================================================== ============ Changes from 4.1.10 to 4.1.11 (Jun 2003) ============ ================================================================== Eric Botcazou temporarily reverted the fix for the mouse bug when scrolling with the X11 driver under Unix. Eric Botcazou fixed the invocation of non-GNU make in the configure script, a few compilation warnings in tools/dat2c.c and made it possible to pass libraries to the misc/deplexe.sh script, so as to let Allegro build again under Solaris. Grzegorz Adam Hankiewicz removed all direct references to Canvaslink and credited SourceForge for current services. Eric Botcazou reworked the configure check for sched_yield() under Unix. Sam Hocevar fixed a Bashism in fix.sh that makes Solaris' sh choke. Angelo Mottola made sure mouse buttons are initialized to 0 at startup under MacOS X. Eric Botcazou added a blurb about the new behaviour of d_ctext_proc(). Eric Botcazou corrected several inadequacies in the documentation of makefile targets. Grzegorz Adam Hankiewicz did some housekeeping work in the docs. Angelo Mottola added a missing item to the list of installed files under MacOS X. Angelo Mottola added a script to automate the enduser MacOS X package creation. Angelo Mottola made it possible to compile apps if just the Allegro framework is installed under MacOS X. Vincent Penquerc'h corrected an inefficiency in select_palette() and unselect_palette(). Eric Botcazou fixed the build failure with MSVC. Andrei Ellman added a few missing items to the list of uninstalled files for the MinGW and MSVC ports. Vincent Penquerc'h fixed a bug in _fill_3d_edge_structure(). ================================================================= ============ Changes from 4.1.9 to 4.1.10 (Jun 2003) ============ ================================================================= Many minor changes and clarifications in the docs. Hein Zelle reworked the paragraph on the location of shared libraries under Unix in the docs and added a FAQ entry on the same subject. Martijn Van Lersel fixed an overflow in create_light_table(). Chris Jones and Eric Botcazou made the MIDI player handle the 'All Sound Off' controller message. Angelo Mottola made the MacOS X port play nice with 10.1.x. Eric Botcazou made the menus not block on exit when mouse buttons are still being held down. Grzegorz Adam Hankiewicz improved the description of set_gfx_mode about virtual screen sizes and hardware scrolling by suggestion of Lothar May. Chris Jones let the MIDI player pass controller events to the raw player by default. Angelo Mottola added the platform-dependent AL_RAND() macro. Angelo Mottola added a HID joystick driver to the MacOS X port. Henrik Stokseth spotted non-standard constructs in the Windows port. Henrik Stokseth spotted unused variables throughout the library. Jim Grainger spotted a broken link in the docs and updated it. Javier Gonzalez fixed some problems in the DirectSound streaming. Andrei Ellman improved the exrgbhsv example. Andrei Ellman corrected a rounding issue in hsv_to_rgb(). Angelo Mottola added _al_rand() and replaced rand() with it throughout the library. Elias Pschernig moved the big font example from exgui to excustom and fixed d_edit_box string length. Angelo Mottola added the 'fixbundle' utility to the MacOS X port. Eric Botcazou added the possibility to fold/unfold nested datafiles in the grabber. Angelo Mottola fixed a couple of color conversion bugs. Elias Pschernig replaced exgui with a more thorough version. Vincent Penquerc'h added support for debugging with Fortify under Unix. Vincent Penquerc'h added the 'Replace' option to the grabber. Vincent Penquerc'h added the 'Force Update Selection' command to the grabber and refactored a fair amount of duplicated code. Eric Botcazou made exunicod endian-safe. Eric Botcazou fixed the behaviour of the C version of draw_trans_sprite() with 32-bit RGBA sprites. Angelo Mottola fixed the behaviour of the C version of draw_trans_sprite() in 8bpp mode. Angelo Mottola added system bitmaps support to the MacOS X port. Eric Botcazou enabled full support of relative filenames in the dat/grabber utilities. Angelo Mottola made exlights endian-safe. Christer Sandberg fixed a bug in the 24-bit graphics code of fixup_datafile(). Angelo Mottola added hw-accelerated VRAM->VRAM blit support under MacOS X. Angelo Mottola added an install-template makefile target to install an Allegro application Project Builder template under MacOS X. Angelo Mottola added a digital sound driver to the MacOS X port. John Holden fixed a bug in load_wav(). Angelo Mottola added a MIDI driver to the MacOS X port. Angelo Mottola added proper mouse buttons detection via HID Manager and buttons emulation if needed under MacOS X. Eric Botcazou added canonicalize_filename() and deprecated fix_filename_path(). Evert Glebbeek added the support for relative filenames to the grabber. Eric Botcazou made it possible to pass CC on the command line to make on non-Unix systems. Angelo Mottola added support for bundled applications under MacOS X. Javier Gonzalez devised a simpler fix for the WinXP black screen bug. Javier Gonzalez prevented some artifacts from being left on the screen when moving fast the window under Windows. Angelo Mottola contributed the MacOS X port. Angelo Mottola fixed various things in preparation for the MacOS X port. Eric Botcazou uncoupled link options for libraries and programs. Evert Glebbeek added the support for relative filenames by means of three new API functions. Elias Pschernig made the allegro.devhelp work with devhelp 0.6.0. Eric Botcazou made file_select_ex() honor the '(+)d' attribute character in the extension string. Eric Botcazou removed the remaining occurences of ustrcpy() from the library code. Christer Sandberg fixed a problem with the include guard generated by dat2c. Eric Botcazou removed the remaining calls to deprecated functions from the distribution. Eric Botcazou optimized the handling of the extension string in the file selector. Eric Botcazou implemented the AL_*_DEPRECATED macros and enabled them for GCC 3.1 or later. Sven Sandberg improved the performance of the rgb_to_hsv() function. Christer Sandberg and Eric Botcazou made dat2c correctly detect the native line ending. Christer Sandberg and Eric Botcazou made dat2c work better with ISO C90 compilers. Henrik Stokseth updated the installation and configuration instructions of both MinGW and Dev-C++ and documented the support of MSYS. Andrei Ellman improved the performance of the hsv_to_rgb() function. Peter Wang made the makefile not pass the -s switch to ld on Unix for non-optimized builds. Evert Glebbeek added the 'New' command to the grabber. Eric Botcazou made the grabber save previous modified data when loading new data. Eric Botcazou unified and fixed the support for ALLEGRO_USE_C on all GCC-based ports. Eric Botcazou unified the autodetection and handling of Unix-like tools on non-Unix systems. Andrei Ellman got Allegro for MSVC to build with Cygwin. Elias Pschernig made the programs be linked with -pg in profile mode under Unix. Andrei Ellman updated the Cygwin section in docs/build/mingw32.txt. Magnus Henoch fixed a problem when compiling without 8bpp support. James Ponder and Hein Zelle clarified a requirement when cross-compiling from Linux. James Ponder suggested to remove the DJGPP makefile from the Unix tar archive. Grzegorz Adam Hankiewicz improved the docs on allegro_exit(). Grzegorz Adam Hankiewicz documented the bunch of packfile functions. Eric Botcazou fixed the profile build on BeOS. Eric Botcazou updated the FAQ about DJGPP's va_list problem (thanks to aj for spotting this). Andrei Ellman suggested some additions to the docs. Grzegorz Adam Hankiewicz added a chapter on available examples to the docs, the ability to cross-reference them and display the references with a specific layout in the HTML docs, and a Python script to automate the updating process when new examples are added. Eric Botcazou fixed an asm locking bug under Windows spotted by Omar Cornut. EvilTypeGuy cleaned up and fixed the RPM spec file for RedHat 9. Ville Skyttä fixed a problem with make install libdir= and modules on Unix systems. Peter Wang added a hack to not unload the SVGAlib module if SVGAlib installs an atexit() handler. Elias Pschernig updated xf2pcx and integrated it in the build process under Unix/X11. Grzegorz Adam Hankiewicz added support for dumping the configure settings under Unix. Javier Gonzalez added get_color_depth() to the API. Julien Cugniere and Eric Botcazou improved the support for non-blocking menus. Grzegorz Adam Hankiewicz corrected several nits in the documentation. Grzegorz Adam Hankiewicz documented the END_OF_MAIN macro. Javier Gonzalez added get_color_conversion() to the API. Lennart Steinke added the exconfig example. Eric Botcazou added big-endian support to the BMP, PCX and TGA loaders as well as to the X11 driver. Eric Botcazou fixed the 'uninstall' target and a problem with Mingw32's make for the Watcom port. Charles Bilyue suggested to not force yielding timeslice with non-blocking menus. Annie Testes fixed a bug with asynchronous I/O mode restoring under Linux. Annie Testes made the screen be cleared before setting the default palette when calling set_gfx_mode(). Annie Testes fixed a bug with patterned drawing in the C version. Vincent Penquerc'h spotted an off-by-one problem when building the list of color depths in the gfx mode selector. Peter Wang made the Intellimouse PS/2 driver work for USB mice in Linux. Elias Pschernig integrated xkeymap in the build process under Unix/X11. Oscar Giner fixed a conflict between the magic main and the MFC. Matthew Leverton fixed a bug with pack_fgets(). Eric Botcazou fixed broken and missing dependencies for make -j2 builds. Hein Zelle revamped the cross-compilation section of docs/build/mingw32.txt. Marcel Smit and Eric Botcazou made the show_video_bitmap() method of the Windows windowed driver wait for a vsync. Eric Botcazou made the test program really time the fixed math functions. Eric Botcazou clarified the limitations of Allegro's interrupts regarding the FPU state under DOS. Peter Wang fixed a bug in stretch_blit() where the first column or row can get an extra pixel, reported by David Gowers and AJ. Eric Botcazou made the linux mouse detection code really empty the buffer before proceeding in the setup program. Eric Botcazou made the Watcom port compile in warnmode with Open Watcom. Elias Pschernig fixed the build with the Unix->MinGW cross-compiler. Magnus Henoch made the gfx mode selector keep the current selection as much as possible. Eric Botcazou fixed the mouse not being scared over alert boxes. Eric Botcazou added -Wstrict-prototypes to the build warnmode under DOS, Windows and BeOS. Annie Testes updated the mouse autodetection code under Linux to take into account her EVDEV driver. Philipp Thomas added multi-arch support, DESTDIR support and the German translation to the RPM spec file. Philipp Thomas converted the configure machinery to autoconf 2.53 or later. Philipp Thomas fixed all function prototypes, thus allowing to build with -Wstrict-prototypes on Unix systems. Philipp Thomas fixed the compilation on x86-64. Philipp Thomas fixed all comparisons between signed and unsigned types, thus allowing to build with -W -Wno-unused on Unix systems. Eric Botcazou reworked the truecolor subsection of the 'Transparency and patterned drawing' section. Eric Botcazou clarified the return value on failure of file_time(), following AJ's suggestion. Eric Botcazou fixed the build in strictwarn mode on Unix systems. Eric Botcazou fixed a mouse bug when the screen is scrolled with the X11 fullscreen driver. Eric Botcazou fixed a bug with resolution and color depth not being taken into account by gfx_mode_select_ex(). Vincent Penquerc'h fixed the compilation breakage on Linux kernels 2.2.x. Eric Botcazou defined ALLEGRO_LIB_BUILD for debug and profile releases as well on Unix systems. Eric Botcazou forced the exstream example to abort if no real sound driver is found. Eric Botcazou clarified the limitations of the stretching functions. Acho A. Tang added a Sidewinder Precision Pro joystick driver to the DOS port. Eric Botcazou re-enabled the autodetection of joysticks in the setup program. ================================================================ ============ Changes from 4.1.8 to 4.1.9 (Jan 2003) ============ ================================================================ Many minor changes and clarifications in the docs. Annie Testes fixed some device name strings in the setup program. Annie Testes added a mouse driver based on the event interface (EVDEV) to the Linux port. Eric Botcazou added for_each_file_ex() and deprecated for_each_file(). Eric Botcazou disabled hackish centering code in fullscreen mode under X11 which caused some artifacts to appear on KDE desktops. Elias Pschernig fixed a pasto in the sample reading code. Eric Botcazou fixed a bug with Alt+TAB under X11. Eric Botcazou added a configure check for the include prefix problem with gcc 3.1 or later on Unix systems. Eric Botcazou reverted the latest patch applied to the joystick code. Matt Witherspoon and Eric Botcazou fixed a bug in the scroll() method of the Linux SVGAlib driver so as to make it wait for the vertical retrace. Eric Botcazou added a stop/resume option to the exstream.c example. Ben Davis documented the non-standard behaviour of pack_feof(). Eric Botcazou worked around a weird problem with some X11 window managers that prevented the fullscreen driver from setting up. Eric Botcazou disabled the new timer synchronization code. Grzegorz Adam Hankiewicz added a warning about DJGPP stability under some Windows versions. Eric Botcazou made it so that the window is centered at startup under Windows. Chris Jones and Eric Botcazou worked around a problem with DOS file attributes under Win2k. Eric Botcazou made the filetest work better with the keyboard. Eric Botcazou fixed shifted help sections in the grabber. Eric Botcazou fixed the mishandling of TAB characters in menu bar entries. Eric Botcazou added a new DEBUGMODE level so that debuggers will not be flooded by internal debug messages any more under Windows. Eric Botcazou fixed a weird compilation bug under MacOS X. ================================================================ ============ Changes from 4.1.7 to 4.1.8 (Dec 2002) ============ ================================================================ Eric Botcazou fixed a bug with nested datafiles in the dat/grabber code spotted by Thomas Klausner. Eric Botcazou clarified the wording about ABI/API compatibility. Thomas Klausner added NetBSD detection. Ben Davis constified the parameter of set_window_title. Lisa Parratt added IRIX detection. Robert J. Ohannessian clarified the docs for play_audio_stream. Sven Sandberg fixed the makedoc linking problem with Watcom spotted by Glenn Jarvis. Ben Davis fixed a compilation warning for set_window_close_button. Eric Botcazou fixed a buffer overflow in the Windows debug version spotted by aj. ================================================================ ============ Changes from 4.1.6 to 4.1.7 (Dec 2002) ============ ================================================================ Eric Botcazou made the joystick initialization routine correctly handle zero as the joytype. Eric Botcazou fixed the compile-time check for the MMX asm support. Eric Botcazou fixed the non-MMX asm color copy routine. Eric Botcazou implemented the synchronization routines for the BeOS port. Eric Botcazou turned the set_window_close_* macros into inline functions. Eric Botcazou fixed an oversight that caused the SGI AL audio driver not to be built as a module on Unix. Stepan Roh fixed a glitch with autoconf 2.53 on Unix. Eric Botcazou fixed the compilation bug with MinGW. ================================================================ ============ Changes from 4.1.5 to 4.1.6 (Nov 2002) ============ ================================================================ Grzegorz Adam Hankiewicz added informations on the FLI format provided by Kronoman X to the FAQ. Eric Botcazou revived the two former set_window_close_* functions as deprecated functions. Elias Pschernig contributed an improved xkeymap utility, based on the original code by Michael Bukin. Eric Botcazou added synchronization to the timer code on multi-threaded platforms (except BeOS for the time being). Eric Botcazou made the new 'save' method of plugins use the same return value convention as the 'export' method (see tools/plugins/plugins.txt). Eric Botcazou added the support for plugin scripts to the MinGW port. Peter Wang changed the default sound mixing quality to 2 (highest). Matthew Leverton added the detection of left-hand mouse configuration under Windows. Oscar Giner fixed a bug with binary data exporting in the grabber, introduced in the 4.1.4 release. Eric Botcazou fixed a crash when Alt+Tabbing under WinXP. Eric Botcazou reverted his patch changing the behaviour at startup under Windows. Grzegorz Adam Hankiewicz added infrastructure for properly documenting the return value of the API calls. ================================================================ ============ Changes from 4.1.4 to 4.1.5 (Nov 2002) ============ ================================================================ Grzegorz Adam Hankiewicz updated the docs about mailing lists/contacts. Grzegorz Adam Hankiewicz added instructions on how to create and submit patches to the Allegro developers. Eric Botcazou implemented the support for non-blocking menus. Lisa Parratt spotted a BSDism that IRIX doesn't like at all. Daniel Schlyder fixed a problem with set_window_title() under BeOS. Lisa Parratt contributed the SGI Audio Library sound driver. Eric Botcazou completely revamped the close button support. Eric Botcazou simplified fullscreen mode initialization under Windows. Elias Pschernig and Eric Botcazou made the GUI code scare the mouse, when drawing, only if it is necessary to do so, thus reducing cursor flicker. Eric Botcazou fixed a bug in scare_mouse_area(). Elias Pschernig optimized the load_bitmap() function family when no palette is specified and documented the feature. Grzegorz Adam Hankiewicz aliased the stylesheet to the default CSS style, allowing The Big Lizard(tm) and other web browsers to disable CSS. Eric Botcazou fixed an ill-behaviour at startup under Windows. Elias Pschernig added the Euro character to the default font and to the German and French keyboard configuration files. Eric Botcazou made _ustrdup() set *allegro_errno to ENOMEM on failures. Annie Testes lifted several hardcoded length limitations in the configuration routines. Eric Botcazou prevented set_gfx_mode() from resetting the layout of all color depths. Eric Botcazou moved #include directives out of the range of extern "C" directives (fixing the C++ compilation bug with Borland C++). Vincent Penquerc'h added the ALLEGRO_NO_COMPATIBILITY symbol and moved all the deprecated stuff from allegro._tx to api._tx . Grzegorz Adam Hankiewicz reformatted monospaced text blocks to fit page in Postscript output. Oscar Giner added the Catalan translation. Oscar Giner corrected the Spanish translation. Grzegorz Adam Hankiewicz added a new command to the doc processor for email mangling: me@serv.com -> me at serv dot com. It is applied to all documentation output formats. Grzegorz Adam Hankiewicz made all source files use the external CSS. Chris Jones fixed a bug with 16-bit samples loading introduced in the previous release. ================================================================ ============ Changes from 4.1.3 to 4.1.4 (Oct 2002) ============ ================================================================ Eric Botcazou prevented the linker from choking on Solaris because of a static library with no symbols. Eric Botcazou removed joystick control from main part of the setup program. Eric Botcazou documented the workaround needed for C++ programs compiled with Borland C++ (in docs/build/bcc32.txt). Eric Botcazou unified the magic main for the 3 Windows compilers and fixed the WinMain() linkage for Borland C++. Henrik Schmidt made gcc pass '-h' instead of '-soname' to the linker and replaced '-L' by '-h' in shell comparisons so as not to break on Solaris. Eric Botcazou fixed the bogus check for GNU ar on Unix systems. Elias Pschernig made load_datafile_object() load the properties attached to the object. Javier Gonzalez and Eric Botcazou fixed the infamous blank screen problem under Win2k/WinXP. Eric Botcazou cleaned up the use of errno/allegro_errno throughout the library and removed all occurences of errno in the grabber/plugins code. Grzegorz Adam Hankiewicz embedded readme.txt into the Allegro manual. Eric Botcazou made the Windows port set the NULL mouse cursor in fullscreen mode instead of hiding it. Vincent Penquerc'h ASSERTed a bunch of C drawing routines. Robert J. Ohannessian did some cosmetic improvements to the HTML output and separated the CSS file. Evert Glebbeek added configure options for x86 processor optimizations on Unix systems. Benny Colyn added a Dutch translation. Evert Glebbeek added the detection of SunOS/Solaris. Javier Gonzalez fixed a graphics bug with always-on-top applications. Igor Gnip added the detection of MSYS via the SHELL variable to the MingW32 port. Eric Botcazou made the mouse use the exclusive foreground cooperative level in fullscreen mode under Windows. Eric Botcazou fixed a bug than had prevented ALT+F4 from being properly handled under Windows and cleaned up the low-level scancode handler. Eric Botcazou updated the description of the layout of header files in the aHack file. Grzegorz Adam Hankiewicz corrected the docs about 'ulimit' in the Help file. Laurence Withers converted the core library and the whole distribution to use the new text API. Laurence Withers added a new text API and deprecated the old one. Eric Botcazou made the Windows port stop triggering SWITCH_IN events when restoring the DirectDraw surfaces. Eric Botcazou re-enabled screensavers and powerdowns under Windows. Eric Botcazou made the deprecated file_select() an inline function. Eric Botcazou cleaned up set_gfx_mode() and made it so that GFX_SAFE selects a windowed mode in windowed environments. Vincent Penquerc'h added a container header file graphics.h for all the graphics stuff. Vincent Penquerc'h added an indexing option to the grabber. Evert Glebbeek added an option menu to the grabber. Evert Glebbeek and Eric Botcazou cleaned up the grabber/plugins code; in particular, the 'save' method of plugins got a new prototype. Peter Wang made fix.sh and zipup.sh not destroy timestamps when just changing EOL markers. Peter Wang fixed a misuse of the -I option with gcc 3.0 and later. Robert J. Ohannessian added more caveats to docs/build/mingw32.txt. ================================================================ ============ Changes from 4.1.2 to 4.1.3 (Sep 2002) ============ ================================================================ Grzegorz Adam Hankiewicz fixed a bug in the HTML rendering code. Eric Botcazou modified the querying of DirectSound devices under Windows. Evert Glebbeek added a '-fullscreen' switch to the grabber, Laurence Withers a '-windowed' switch. Eric Botcazou temporarily disabled screensavers and power downs under Windows. Daniel Schlydler fixed problems with get_executable_name() under Windows. Eric Botcazou added a FAQ entry on the C++ headers problem with gcc 3.x and Mingw32, summarizing findings by Robert J. Ohannessian. Robert J. Ohannessian fixed the compilation problem with MSVC. ================================================================ ============ Changes from 4.1.1 to 4.1.2 (Sep 2002) ============ ================================================================ Many minor changes in the code and the docs. Grzegorz Adam Hankiewicz fixed a crash in the exmouse example when no mouse is present. Angelo Mottola made the exunicod example welcome Italian programmers too. Grzegorz Adam Hankiewicz documented new structures. Eric Botcazou added a native DirectX window test. Eric Botcazou re-enabled the 1 ms accuracy limitation for timers under Windows. Elias Pschernig added support for the Devhelp documentation format. Marcel Smit corrected an error in the packfile format write-up. Eric Botcazou fixed a conflict between Allegro headers and standard C++ headers of gcc 3.x under Mingw32. Matthew Leverton made the DOS/Windows makefiles use 'copy /B' instead of 'copy' for file concatenation. Eric Botcazou wrote another new page flipping/triple buffering code for the Windows port. Eric Botcazou made it so that win_set_window() restores the state of the joystick module as well. Grzegorz Adam Hankiewicz ASSERTed a bunch of public functions. Eric Botcazou made it so that restoring the DirectDraw surfaces always triggers a SWITCH_IN event under Windows. Peter Wang fixed a problem linking with the debug version under linux, due to missing "inline" functions. Robert J. Ohannessian fixed the docs for pivot_scaled_sprite_v_flip(). Eric Botcazou fixed a race condition when registering input events at startup under Windows. Roberto Alfonso added an srand() call in the demo game. Elias Pschernig removed (seemingly) arbitrary window size checks in the Unix X11 driver. Roberto Alfonso fixed a couple of memory problems in the dat2c utility. Matthew Leverton pointed out a C99 idiom in the dat2c utility that Borland C++ doesn't like. Angelo Mottola changed the BeOS gfx driver IDs/constants to more pertinent ones. Angelo Mottola added a safe BWindow-based windowed driver and a fullscreen overlay driver to the BeOS port. Angelo Mottola reorganized and commented all the BeOS gfx subsystem. Sven Sandberg fixed a bug in create_trans_table(). Javier Gonzaled fixed a bug with volume and pan not properly set in loop mode by the DirectSound driver. Laurence Withers added two fixed point ratios for converting to and from radians. Eric Botcazou fixed the documented prototype of fixtof() and ftofix(). Laurence Withers fixed the 'inline' compilation bug in the dat2c utility. Eric Botcazou fixed a bug that causes timers to restart permanently when Allegro is switched out under Windows. Eric Botcazou fixed a bug with switch mode setting under Windows he had introduced in the 4.1.1 release. Grzegorz Adam Hankiewicz improved the legibility of the HTML code generated by the doc processor and reduced its size in the process. ================================================================ ============ Changes from 4.1.0 to 4.1.1 (Aug 2002) ============ ================================================================ Many minor changes and clarifications in the docs and the FAQ. Eric Botcazou fixed a bug with graphics mode switching using a ALT+key combination under Windows. Laurence Withers contributed the dat2c utility. Grzegorz Adam Hankiewicz made it so that chapters can be referenced in the documentation and added a new one on the types and structures defined by the library. Eric Botcazou improved win_set_window() so that it can be called after the library has been initialized. Elias Pschernig fixed a bug in midi_seek(). Eric Botcazou wrote a new page flipping/triple buffering code for the Windows port. Grzegorz Adam Hankiewicz added a linux specific debug help section. Eric Botcazou made the constructors of the fix class from integer and floating point values explicit. Eric Botcazou fixed a dat2s bug with dynamically linked programs under Windows. Jan Bruun Andersen fixed a compilation problem with Cygwin. Jeremiah Blanchard updated the build instructions for Darwin. Vincent Penquerc'h added sample loader/saver registration and a save_sample() function. Peter Wang documented it. George Foot added (preliminary) non-FM support to the OSS MIDI driver. Ben Davis and Robert J. Ohannessian put in (void *) casts for the LOCK_* macros on DJGPP and Mac. Nicholas Davies made the fix class not trigger warnings with gcc -Weffc++. Angelo Mottola fixed a keyboard focus problem under BeOS. Peter Wang fixed the detection of ESD and aRts on Unix systems. Peter Wang made files be opened with as permissive as possible permissions on Unix systems. Stepan Roh added support for a automake-style DESTDIR variable in the Unix makefile. Grzegorz Adam Hankiewicz made the doc processor output valid HMTL 4.0 in some corner cases for which it previously didn't. Grzegorz Adam Hankiewicz fixed a crash of the doc processor with very long lines. Peter Wang did some housekeeping work throughout the code and the documentation. ================================================================ ============ Changes from 4.0.2 to 4.1.0 (Jul 2002) ============ ================================================================ Charles Bilyue optimized the i386 blitters. Peter Wang fixed the mis-treatment of empty files by the library and the 'pack' utility. Eric Botcazou simplified pack_f{read,write} and cleaned up several uses of pack_feof(). Eric Botcazou split USE_CONSOLE into ALLEGRO_USE_CONSOLE and ALLEGRO_NO_MAGIC_MAIN. Eric Botcazou simplified and cleaned up the asm bank switchers. Peter Wang added support for the environment variable ALLEGRO_MODULES under Unix. Peter Wang made 'configure --disable-vga' remove more stuff out of the core under Unix. Eric Botcazou made the DirectDraw code try to restore its surfaces as soon as it detects they have been lost. Peter Wang added a description of the packfile format. Peter Wang added an aRts sound driver to the Unix port. Sven Sandberg optimized create_video_bitmap() for systems with a single video memory surface. Grzegorz Adam Hankiewicz reindented the documentation sources, improving the text/info/html output in the process. Grzegorz Adam Hankiewicz improved chm output for the documentation. Sven Sandberg optimized and reduced numeric errors in create_trans_table(). Lorenzo Petrone added a xwin_set_window_name() function to the X11 port. Peter Wang made install_allegro()/allegro_init() not abort the program on failure. Sven Sandberg and Grzegorz Adam Hankiewicz added backward compatibility to the new doc processor. Sven Sandberg fixed various problem in the makefiles. Elias Pschernig made it so that the COLORCONV_KEEP_TRANS flag is checked when converting bitmaps out of datafiles. Eric Botcazou added preliminary support for hardware acceleration and video bitmaps to the QNX port. Elias Pschernig added a window position saving feature to the Windows port. Vincent Penquerc'h added a -s-PROP option to the dat utility in order to preserve properties when stripping. Henrik Stokseth made the zipwin.sh script for packaging the Windows binary distribution work with Cygwin. Peter Wang and Eric Botcazou made it so that Allegro C programs can compile with gcc -ansi -pedantic. Vincent Penquerc'h added a 'sort' option to the grabber and the dat utility. Eric Botcazou added preliminary support for native windows under Windows. Vincent Penquerc'h made gcc use pipes on Unix when building the library. Lorenzo Petrone added support for switch callbacks under X11 and refactored the display switching code. Javier Gonzalez changed the default value of emulate_three to no in all cases. Eric Botcazou modified the behaviour of the retrace_* objects to take into account the refresh rate if known. Eric Botcazou fixed the 'configure --disable-constructor' problem. Elias Pschernig fixed menu dimensions in the GUI engine. Eric Botcazou added documentation on API compatibility. Elias Pschernig and Eric Botcazou fixed the get_camera_matrix*() functions. Igor Gnip removed the requirements for fileutils on DOS/Windows platforms. Jeremiah Blanchard contributed modifications in order for Allegro to compile on Darwin/MacOS X. Henrik Stokseth merged standard and extended mode-selectors. Elias Pschernig added chm ouput support for the documentation. Eric Botcazou merged the three input threads into a single one under Windows. Mike Pichagin contributed the ustrnicmp() function. Grzegorz Adam Hankiewicz contributed a new documentation format for better html output. Eric Botcazou added a DirectInput joystick driver to the Windows port. ================================================================ ============ Changes from 4.0.1 to 4.0.2 (Jun 2002) ============ ================================================================ Many clarifications in the docs. Sven Sandberg improved accuracy and fixed bugs in do_arc(). Matthew Leverton added missing header files to be installed by the Windows binary distribution. Grzegorz Adam Hankiewicz fixed a problem with the TOC of the FAQ. Eric Botcazou fixed a bug with stretch_blit() under Windows XP. Peter Wang fixed various configure machinery problems under Unix. Sven Sandberg updated the Swedish translation file. Sven Sandberg fixed a crash in the exswitch example when compiled by Watcom C/C++ and also made if faster. Maxime Carey added a Canada (French) keyboard mapping file. Henrik Stokseth updated instructions and fixed installation for Cygwin. Eric Botcazou added an option to disable direct updating in color conversion mode under Windows. Eric Botcazou (presumably) fixed the bug in the emergency exit mechanism under Windows when called from the DLL. Angelo Mottola made it so that the sound doesn't block the main thread anymore under BeOS. Deepak T and Eric Botcazou fixed clipping in three C sprite drawing routines. Peter Wang fixed a deadlock that occurred under Unix when Allegro received an X11 close event. Eric Botcazou added a --cppflags option to allegro-config and fixed C++ compilation under QNX. Vincent Penquerc'h added a --version= option to allegro-config. Robert J. Ohannessian made the 32->24 color convertors more robust and improved the MMX one in the process. Robert J. Ohannessian, Eric Botcazou and Sven Sandberg fixed a bug in the hue blender and the hsv_to_rgb() routine. Matthew Leverton fixed another problem with al_find*() and NTFS partitions under Windows. Peter Wang fixed a bug in ALSA device detection. Peter Wang fixed a bug in al_find* under Unix when running as root. Matthew Leverton and Eric Botcazou fixed a bug with mouse mickeys in windowed mode under Windows. ================================================================ ============ Changes from 4.0.0 to 4.0.1 (Mar 2002) ============ ================================================================ Many minor changes, many clarifications in the docs. Peter Wang fixed the installation of shared libs under FreeBSD. Peter Wang and Eric Botcazou fixed autodetection glitches for VGA and SVGAlib. Eric Botcazou fixed a problem under X11 when the MIT X-SHM extension is used. Eric Botcazou fixed a deadlock on exit when an user window is used in conjunction with timers under Windows. Eric Botcazou disabled useless backbuffers for the DirectX safe driver. Peter Wang made the Alsa sound driver use non-blocking mode when detecting if ALSA PCM available. Sven Sandberg added support for long long integers to usprintf() and al. Robert J. Ohannessian fixed the difference blender. Peter Wang fixed a race condition when closing the X display. Elias Pschernig made all active dialogs redraw themselves after a switch. Peter Wang made fbcon a priority driver, so that it can appear above VGA. Javier Gonzalez fixed a glitch in the DirectSound input code. Eric Botcazou fixed the SIGSEGV on exit with the three-finger salute under QNX. Eric Botcazou fixed the C-to-asm calling problem for Borland C++ compiled programs. Eric Botcazou cleaned up the messy (and somewhat incorrect) DirectDraw bitmap management code. Sven Sandberg improved the video bitmap subdivision algorithm. Sven Sandberg fixed problems in the Windows makefiles (especially Borland) when building Allegro under Win98. Peter Wang removed the hack which switched off fix aliases under IRIX. Vincent Penquerc'h fixed a problem with the SIGALRM timer and SWITCH_PAUSE. Javier Gonzalez fixed a latency problem with audiostreams. Laurence Withers made the font exporter use the current palette for the output. Elias Pschernig made some changes to grabber: added a close hook; keeps track if anything has been modified; when you exit the grabber and the file was modified, the popup now has a 3rd option for save+exit; window title displays the current filename, and if the file has been modified; fixed multicolour font exports. Sven Sandberg optimized again the create_light_table() function. Attila Szilagyi fixed SVGAlib horizontal scrolling. Eric Botcazou fixed synchronization problems under QNX. Grzegorz Adam Hankiewicz made the TOC at the top of sections alphabetically sorted. Eric Botcazou fixed the screen not restored after a wake-up in the Windows windowed and overlay drivers. Richard Reeve fixed a silly mistake with gcc 3.0.x detection. Angelo Mottola fixed static keyconf compilation problem on BeOS due to pckeys keyboard driver. Eric Botcazou fixed the not-returning-focus-on-exit bug under Windows. Michael Bukin fixed a bug with C-version textprintf on 24-bpp bitmaps, reported by Bertrand Coconnier. Eric Botcazou fixed a bug in the 32->15 MMX color conversion routine. Eric Botcazou fixed the DLL linking problem with Borland C++ Builder 4. Sven Sandberg made exaccel more responsive. Sven Sandberg fixed a glitch with short filenames under DOS. ================================================================= ============ Changes from 3.9.40 to 4.0.0 (Dec 2001) ============ ================================================================= Many minor changes. Eric Botcazou modularised the VGA/Mode-X drivers under Linux. Peter Wang fixed the segfault bug in Mode-X under Linux with threads. Peter Wang made the X11 port use SIGTERM signal instead of exit() when invoking the three finger salute. This solves a problem where programs with sound hang when they are killed. Eric Botcazou added os_version and os_revision support to the QNX port and added a QNX specific section to the docs. Peter Wang added a deadzone for digital readings of joystick axes under Linux, as suggested by George Foot and made the driver look for /dev/input/js# before /dev/js#. Peter Wang renamed fixed point functions to be prefixed with "fix" instead of "f", to avoid clashes with some libcs. Backwards compatibility is provided using static inline functions. Peter Wang fixed two problems with emergency exits under Linux/Unix. Eric Botcazou changed the updating logic of the QNX Photon graphics driver. Eric Botcazou added a doc for the wfixicon utility, with the help of Laurence Withers. Angelo Mottola unicodified allegro_message on BeOS and wrote a new BeOS keyboard driver (using the shared pckeys system). Eric Botcazou fixed a problem with David Capello's d_menu_proc steal/return mouse focus patch. Peter Wang made passing NULL to install_allegro() as the atexit_ptr parameter mean allegro_exit() won't be installed as an atexit() callback, as suggested by Javier Gonzalez. Lorenzo Petrone added a gfxinfo utility. Eric Botcazou added fetch_mode_list() to the QNX Photon Direct driver. Peter Wang made X desktop_color_depth() able to return 15 bpp. Grzegorz Adam Hankiewicz updated Spanish translation strings. Peter Wang fixed a problem with X shutdown sequence. Eric Botcazou repaired the QNX build process, revamped the layout of the QNX port sources and made some fixes. Peter Wang disabled the SVGAlib mode fetching code as it was causing problems with other drivers. Angelo Mottola added BeOS notes to the ABI compatibility doc. Eric Botcazou fixed a bug in the Windows locking code that caused the grabber to crash on switch out. Eric Botcazou fixed a bug in the handling of recursive sub-bitmaps under Windows. Eric Botcazou fixed a bug preventing old style password-protected packfiles from loading in the grabber. Lorenzo Petrone added two FAQ entries on DGA2 problems. Grzegorz Adam Hankiewicz revamped the structure of the docs directory. Stepan Roh updated the Czech translation. Javier Gonzalez fixed a bug in the DirectSound driver related to the loop playing modes. David Capello fixed a problem with submenus which overlapped their parents, where focus would pop back to the parent instead of the child. ================================================================ ============ Changes from 3.11 to 3.9.40 (Nov 2001) ============ ================================================================ 3.9.40: Eric Botcazou enabled SSE support under Linux. Also reduced the delay in the DOS Sidewinder init code. Made the definition of _AL_DLL for MinGW32 consistent with other Windows ports. 3.9.40: Henrik Stokseth improved make install to install only the needed headers from the include/allegro/platform directory. 3.9.40: Vincent Penquerc'h updated 7 makefiles after his header splitting patch. 3.9.40: Robert J. Ohannessian added two new entries to the GFX_VTABLE structure. 3.9.40: Eric Botcazou replaced sprintf() by snprintf() in the Linux/Unix code. Increased the delay in the Windows switch handling code. Unicodified the GFX mode selector and fixed some glitches. Added a new test dubbed filetest. Fixed more unicode string problems. Unified the handling of system directory variables in the Windows makefiles. Made two strings translatable in the GFX mode selector. 3.9.40: Ben Davis added support for timers with parameters under Windows. 3.9.40: Eric Botcazou fixed the bug in the asm sprite functions when used with sub-bitmaps. Fixed a problem of the new header layout for platforms not supporting asm. 3.9.40: George Foot and Eric Botcazou fixed the C fceil() function and added the ffloor() function. 3.9.40: Chris Graham suggested to add a new flag for Windows NTFS compressed files. 3.9.40: Henrik Schmidt and Eric Botcazou found a workaround for the switching problem under Windows. 3.9.40: Eric Botcazou revamped the Borland C++ build process. Now it targets BC++ 5.5. Made pack_fdopen() an exported internal function. Reverted to the 3.9.38 code for 16-bit audio streaming with DirectSound. 3.9.40: Vincent Penquerc'h contributed a rather large split-up/ reorganization of the Allegro header files. Henrik and Eric did some related clean-up and fixing. 3.9.40: Peter Wang updated put_backslash() docs. 3.9.40: Eric Botcazou modified the way DirectDraw surfaces are enumerated. Fixed compilation errors/warnings with BC++. Made generate_optimized_palette_ex() a static function. Worked around the DOS limitations for al_findfirst() and for_each_file(). Moved platform-dependent stuff out of src/fsel.c. 3.9.40: Peter Wang updated timer docs for non-DOS. Added ABI compatibility readme. 3.9.40: Javier Gonzalez removed all references to the RSXNT build. 3.9.40: Vincent Penquerc'h made it so that users can provide their own ustrdup(). 3.9.40: Robin Burrows fixed two glitches in the DirectDraw code. 3.9.40: Peter Wang fixed a problem where XUnlockDisplay was called after XCloseDisplay. 3.9.40: Eric Botcazou removed old Sidewinder asm driver. Cleaned up buffer usage in DIGMID. Fixed unicode support in the DIGMID driver. Replaced all occurrences of SEND_MESSAGE() by object_message(). 3.9.40: Annie Testes caught a misordering in the X system shutdown. 3.9.40: Eric Botcazou increased the size of filename buffers to 1024 bytes. 3.9.40: Sven Sandberg improved fix.bat script. 3.9.40: David Capello fixed a problem with lost GUI mouse clicks. 3.9.40: Vincent Penquerc'h removed two hard-coded list sizes in grabber. 3.9.40: Peter Wang added a little clarification regarding mouse_accel_factor. 3.9.40: Eric Botcazou made debugging functions revert to ASCII strings. Added some defines for backwards compatibility with former cpu_* flags. Fixed a compilation problem under DJGPP. 3.9.40: Henrik Stokseth added VBE/AF fetch_mode_list(). 3.9.40: Robert J. Ohannessian revamped the retrieval mechanism of CPU capabilities and added some new flags. 3.9.40: Eric Botcazou fixed various mouse cursor problems under Windows. Updated docs about the DIGI_DIRECTX drivers. 3.9.40: Javier Gonzalez fixed audio streams in Windows. 3.9.40: Peter Wang improved the XDGA2 driver by removing unneccessary scrolling, which also resulted in speed-ups due to less locking/unlocking. The original fix was by Michael Bukin. 3.9.40: Eric Botcazou and Javier Gonzalez added some documentation on static linking with MSVC/MinGW32. 3.9.40: Peter Wang fixed sonames for debug and profile libs. Also added a 'configure' check that ld supports -export-modules before enabling modules. 3.9.40: Annie Testes found ASCII strings that needed to be converted. Also added a pack_fdopen() function. 3.9.40: Robert J. Ohannessian clarified some Dev-C++ instructions. Fixed fix.bat script under MinGW32/Win2k. 3.9.40: Marcel Smit corrected a bug that caused errors when drawing perspective-correct polygons facing the screen. (dz=0) 3.9.40: Peter Wang made install_timer_int static. Also moved allegro_404_char into public API. 3.9.40: Laurence Withers added docs for allegro_404_char. 3.9.40: Eric Botcazou fixed a little glitch with menu auto-opening. Also fixed a color glitch in the Windows windowed driver on 8-bit desktops. 3.9.40: Salvador Eduardos Tropea fixed inline friend declarations with bodies. (gcc 3.0.x problem) 3.9.40: Peter Wang improved behaviour between mouse auto-opening menus and navigating with keyboard. Also unspartanised the ustrtok_r() docs. 3.9.40: Henrik Stokseth replaced the mmxtest with a more advanced assembler capabilities testing. 3.9.40: Eric Botcazou re-enabled full pairing on Pentium for five color conversion routines. Applied xor vs. mov instruction-length optimization to the non-MMX code. Applied %ecx vs. %edx instruction-length optimization to the non-MMX code. Updated the mouse_accel_factor docs. 3.9.40: Peter Wang eliminated use of static buffers by uconvert() in several places. 3.9.40: David A. Capello made d_menu_proc steal/return focus when activated/deactivated. 3.9.40: Henrik Stokseth added Out of Environment space detection on the fix.bat script. 3.9.40: Eric Botcazou fixed a non ANSI C compliant behaviour in usprintf(). 3.9.40: Seunghwan Ji made makedoc output correct html and rtf files for Korean. 3.9.39: Robert J. Ohannessian added -? and --help options to dat. 3.9.39: Sven Sandberg and Grzegorz Adam Hankiewicz fixed some errors in the documentation. 3.9.39: Annie Testes fixed several glitches related to unicode support. 3.9.39: Henrik Stokseth added an internal _al_sane_realloc() function with guaranteed behaviour. Used this to fix a memory leak and updated the FAQ. 3.9.39: Eric Botcazou and Peter Wang updated the documentation on: file attribute flags, request_scroll and request_video_bitmap. 3.9.39: Eric Botcazou unified the use of internal timers in Windows drivers. Also let digitest use max volume of Allegro mixer. 3.9.39: Paul Hampson improved again the DOS SNESpad joystick driver. 3.9.39: Eric Botcazou revamped the locking mechanism of the DGA2 driver. Also fixed some memory leaks. 3.9.39: Peter Wang added mode fetching for X11 fullscreen and DGA fullscreen drivers. 3.9.39: Robert J. Ohannessian fixed 16bit masked blit SSE code and removed unused instruction in the other blitters. 3.9.39: Salvador Eduardos Tropea added some GCC 3.x fixes. 3.9.39: Peter Wang added a check if a module listed in modules.lst exist before trying to load it. 3.9.39: Charles Wardlaw made alert/alert3 use transparent background for text label. 3.9.39: Eric Botcazou added a flush_config_file() API function. Also added a hfill() method to the GFX_VTABLE structure. 3.9.39: Peter Wang fixed some memory leaks. 3.9.39: Eric Botcazou fixed two compilation warnings with gcc > 2.95. 3.9.39: Johan Peitz contributed 'Alex the Allegator' icon. 3.9.39: Angelo Mottola fixed safe fullscreen bug and fetch_mode_list() for BeOS. 3.9.39: Peter Wang updated XDGA2 and SVGAlib driver's fetch_mode_list() function. 3.9.39: Henrik Stokseth rewrote the mode-list API, updated the code and updated the documentation. 3.9.39: Grzegorz Adam Hankiewicz updated all URLs in the Allegro sources and documentation. 3.9.39: Eric Botcazou fixed cmplog script for perl 5.6.1. 3.9.39: Peter Wang added a FAQ entry. 3.9.39: Peter Wang fixed up the sound subsystem which he accidentally broke when he introduced the dynamic modules. 3.9.39: Eric Botcazou fixed a compilation warning. Also added support for 8-bit desktops to the windows windowed driver. Fixed color shifts in the color convertors from 8-bit. Fixed a bug in the 8->8 color conversion routine. 3.9.39: Javier Gonzalez contributed bidirectional looping support for the directsound driver. 3.9.39: Robert J. Ohannessian and Henrik Stokseth did a large update on the installation instructions for Mingw32. 3.9.39: Eric Botcazou cleaned up windows dll version info sheet and let the windows makefiles use implicit rules on some file targets. Fixed a compilation glitch with MSVC. 3.9.39: Henrik Stokseth added support for building RPMs with SuSE Linux. 3.9.39: Peter Wang fixed some off-by-one errors. Fixed unix makefile. Fixed disabling of dynamic modules. 3.9.39: Eric Botcazou and Grzegorz Adam Hankiewicz finished translation of the allegro.spec file. 3.9.39: Eric Botcazou re-added a faq entry on DirectX version problem. 3.9.39: Grzegorz made fbcon a module. 3.9.39: Peter Wang removed allegro-enduser.spec as it is no longer needed. Also contributed a rewrite of the allegro.spec file, and updated the scripts to make the rpm. The new allegro.spec file was based on one contributed by Osvaldo Santana Neto. Peter also allowed configure to give linker flags to allegro-config (for modules). Also let _unix_find_resource search in /usr/[local/]share/allegro for .dat files. 3.9.39: Javier Gonzalez contributed backward playing support for the directsound driver. 3.9.39: Eric Botcazou fixed a glitch with backward playing in the digitest test. 3.9.39: Salvador Eduardos Tropea made a small update on the cygwin section of readme.mgw. 3.9.39: Peter Wang fixed a problem with BSD make and Mac directory separators ':'. Documented gfx_cardw variable. 3.9.39: Sven Sandberg fixed a nasty side-effect of clear() inlining on Watcom. 3.9.39: Laurence Withers fixed a crash bug in the mode-selector. 3.9.39: Peter Wang removed SIGIO asynch stuff since it's not needed when we have pthreads. Updated documentation to mention dynamic modules. Added configure option to disable threads. 3.9.39: Burton Radons fixed a bug in his dissolve blender. 3.9.39: Eric Botcazou fixed a bug in the menus caused by auto-opening. 3.9.39: Henrik Stokseth updated the makefiles to use -mcpu=pentium instead of the depreciated -mpentium gcc option. Also let the packaging scripts run autoconf and remove hidden or leftover files. 3.9.39: Eric Botcazou cleaned up the windows sound code. Also clarified the code in the core menu function. Corrected a unicode glitch. Removed remaining references to ALLEGRO_NO_FINDFIRST. Added a unified al_find*() interface. Made the Portuguese translation file of the former Portuguese (Br) file. Fixed a few keyboard configuration files. Changed pl.cfg EOLN delimiter to \r\n. 3.9.39: Grzegorz Godlewski contributed a Polish localization patch. Also added support for lower and upper altgr tables. 3.9.39: Eric Botcazou fixed a bug in the keyconf utility caused by the sectionification. 3.9.38: Robert J. Ohannessian added the following to the color convertor: color copy routines needed by the BeOS port, support for cross-conversion between 15-bit and 16-bit colors, support for conversion to 8-bit color, support for rectangles of any width and added two new MMX routines. 3.9.38: Henrik Stokseth rewrote get_gfx_mode_list() likewise rewrote the mode-selector to use get_gfx_mode_list(). Also added fetch_mode_list() functions on the DirectX, VGA, Mode-X and Xtended GFX drivers. 3.9.38: Angelo Mottola fixed problems with SMP on the BeOS port. 3.9.38: Eric Botcazou fixed some problems with the non-MMX code in the color convertor. 3.9.38: Sven Sandberg improved spline() for DRAW_MODE_TRANS 3.9.38: Peter Wang renamed clear() to clear_bitmap(). clear() is still provided for backwards compatibility. 3.9.38: Stepan Roh made fractal generator work under non-Intel processors. 3.9.38: Eric Botcazou made a valid display switch mode of SWITCH_NONE under DOS. 3.9.38: Angelo Mottola made the BeOS port use the new unified color conversion routines. 3.9.38: Peter Wang added check to see if display is local under X11. 3.9.38: Eric Botcazou and Sven Sandberg fixed compilation under Watcom 10.6. 3.9.38: Elias Pschernig contributed an icon resource fixer for the Windows port and added support for shared library under BeOS. 3.9.38: Angelo Mottola added a bfixicon utility. 3.9.38: Stepan Roh made the native Allegro time format of ANSI time_t. 3.9.38: Peter Wang added an ustrtok_r() function. 3.9.38: Robert J. Ohannessian optimized some masked_blits with SSE instructions. 3.9.38: Angelo Mottola did a sound fix for audiostream output and SMP machines and added triple buffering support on the BeOS port. 3.9.38: Angelo Mottola added fetch_mode_list() support to the BeOS fullscreen driver. 3.9.38: Eric Botcazou changed the acceleration scheme for the mouse under Windows. 3.9.38: Peter Wang added fetch_mode_list() support to the svgalib driver. 3.9.38: Peter Wang added pthread timer and removed dependancy to SIGALRM. 3.9.38: Henrik Stokseth added Windows XP detection. 3.9.38: Andreas Kluge fixed a bug with volume setting in the DOS Soundscape driver. 3.9.38: Angelo Mottola rewrote the BeOS sound driver to use the BSoundPlayer class. 3.9.38: Robert J. Ohannessian added SSE and SSE2 detection. 3.9.38: Connelly Barnes fixed a bug with the DirectSound pan. 3.9.38: Eric Botcazou added support of switch modes to the test program. 3.9.38: Eric Botcazou modified the Windows switch mechanism. 3.9.38: Angelo Mottola added fullscreen display switching support and did many fixes and cleanups on the BeOS port. 3.9.38: Henrik Stokseth added code to get more os info under unix. 3.9.38: Nimrod Abing fixed a bug in the config routines related to the NULL section. 3.9.38: Eric Botcazou fixed a crash in the Windows windowed driver on fast machines. 3.9.38: Ronaldo Hideki Yamada did a large update on the PowerMac port and added a midi driver. 3.9.38: Henrik Stokseth generalised the support for processor specific optimisations in some makefiles. 3.9.38: Evert Glebbeek put set_gfx_mode on a diet and added config entry for specifying the card to use for GFX_AUTODETECT_WINDOWED. 3.9.38: Robert J. Ohannessian made blit not convert between colordepths for video bitmaps. (for AllegroGL) 3.9.38: Peter Wang made fix_filename_slashes() handle both types of slashes. 3.9.38: Grzegorz Adam Hankiewicz implemented a switch in makedoc to check for long (>77) doc lines. 3.9.38: Owen Rudge contributed a DLL version resource script. 3.9.38: Sven Sandberg made the rotation functions faster, more accurate and working with any type of bitmap. Also removed rotate_scaled_sprite_flip(). 3.9.38: Angelo Mottola added fetch_mode_list() support to DGA2. 3.9.38: David A. Capello made test program use transparent polygon types. 3.9.38: Owen Rudge contributed a mkdata.bat script. 3.9.38: Grzegorz Adam Hankiewicz added reload_config_texts(). 3.9.38: Eric Botcazou added an enhanced building mechanism for DLL export definition files. 3.9.38: Eric Botcazou added a new unicode example program and did a ton of small fixes. 3.9.37: Johan Peitz fixed and enhanced the Win32 joystick driver. 3.9.37: Sven Sandberg added Ctrl + arrow keys to d_edit_proc(). 3.9.37: Eric Botcazou changed the color key for the Windows overlay driver to bright pink. 3.9.37: Eric Botcazou reverted some changes he made to the timer core last release which were causing problems with the MIDI player, and removed the Windows multithreaded timer driver. 3.9.37: Henrik Stokseth made some updates to the OS detection code, and added a os_multitasking variable. 3.9.37: Eric Botcazou fixed a problem in the config routines, where entries in the NULL section were hiding duplicate entries in other sections. 3.9.37: Eric Botcazou made the setup program use Unicode functions. 3.9.37: Henrik Stokseth unified the fix* scripts, and gave them new options. 3.9.37: Peter Wang added support for dynamically loaded modules under Unix. The SVGAlib, ALSA digital, ALSA MIDI, ESD and DGA2 drivers will be built as modules when possible. This removes external dependencies on the main library and improves binary transportability under Linux. 3.9.37: Eric Botcazou made many changes and bug fixes to the Unicode string functions, and their use in the library. The old functions now behave exactly like the libc equivalents, while the new functions (the 'z' functions) behave more sanely. This change affects most code which uses the Unicode functions. 3.9.37: Bertrand Coconnier changed the recently merged scene rendering API, fixed a bug, and provided a new example program. The API change will affect all code which uses the scene functions. 3.9.37: Laurence Withers wrapped registration of the bitmap file types in a constructor. Where constructors are supported, this should reduce the executable size when statically linking (unless you use the bitmap loaders, of course). 3.9.37: Ben Davis modified the set_volume_per_voice scale. Please see the docs for this function if you have used it in the past. 3.9.37: Eric Botcazou worked around a DOS mouse bug under Win2k. 3.9.37: Eric Botcazou added VGA Mode 13h support under DirectX 5 or greater. 3.9.37: Henrik Stokseth added a get_gfx_mode_list() function, and the implementation of it for the VESA driver. 3.9.37: Eric Botcazou and Annie Testes toiled hard to avoid buffer overflows (particularly with regards to the Unicode functions). 3.9.37: Eric Botcazou fixed a mouse mickeys bug and cleaned up the input subsystem under Windows. 3.9.37: Eric Botcazou made two minor changes in the handling of index 0 in paletted modes. 3.9.37: Eric Botcazou added a transparency preserving feature to the grabber and dat utility. 3.9.37: Eric Botcazou fixed a crash when alt-tabbing in page flipping under Windows. 3.9.37: Peter Wang added gui_menu_draw_menu and gui_menu_draw_menu_item to allow customising the look of the GUI menus (to a certain extent). 3.9.37: Angelo Mottola added support for the new GFX_AUTODETECT_FULLSCREEN and GFX_AUTODETECT_WINDOWED constants, which we _all_ wholeheartedly agreed upon :-) 3.9.37: Eduard Bloch made config vars which exist but are empty return defaults. 3.9.37: Elias Pschernig added a COLORCONV_KEEP_TRANS mode. 3.9.37: Henrik Stokseth added support for compiling with Cygwin. It works in Mingw compatibility mode. 3.9.37: Angelo Mottola made GUI submenus automatically open when the mouse hovers for long enough. (This was an old patch that finally got merged.) Eric made some related modifications to it later. 3.9.37: Eric Botcazou made clear_keybuf() not clear the key[] array. 3.9.37: Sven Sandberg added a --quick option to fix scripts. 3.9.37: Angelo Mottola did _loads_ of work on the QNX port (much too much to document here). 3.9.37: Eric Botcazou made the Win32 asm color conversion code for windowed drivers available for other ports, and added a few other converters. Isaac Cruz added one too. 3.9.37: Eric Botcazou restructured the config file format. Some previously unsectioned variables are now in sections. 3.9.37: George Foot added a threading system to handle asynchronous events, instead of using SIGALRM (under Unix). 3.9.37: George Foot fixed some problems with pack_fgets(). 3.9.36: Eric Botcazou made it so that set_keyboard_rate(0, 0) will disable keyboard repeat, as in the documentation. 3.9.36: Annie Testes added font_height, render_char, char_length hooks to FONT_VTABLE. 3.9.36: Eric Botcazou made some minor changes related to AllegroGL in the window management code, and fixed two little mouse bugs Javier Gonzalez had found (both under Windows). 3.9.36: Eric Botcazou added a get_desktop_resolution() function for Windows and X. Joshua Haberman added a BeOS version. 3.9.36: Angelo Mottola comprehensively started a QNX port. 3.9.36: Robert Ohannessian corrected src/dest ordering in additive blenders. 3.9.36: Eric Botcazou improved support of external windows in Windows. 3.9.36: Peter Wang updated the SVGAlib driver for version 2. 3.9.36: Peter Wang added a fullscreen version of the X-Windows graphics driver. The original was by Benjamin Joel Stover. 3.9.36: Peter Wang made grabber use file_select_ex(). This is just here so you don't get a shock :-) 3.9.36: Eric Botcazou fixed some small bugs in the DirectSound input code. 3.9.36: Eric Botcazou fixed the NumLock state in X not matching keyboard LEDs. 3.9.36: Eric Botcazou reenabled the multi-threaded timer under Windows. 3.9.36: Eric Botcazou and Javier Gonzalez made the keyboard repeat system more efficient. 3.9.36: Eric Botcazou fixed some asm blitters, and also a bug with changing timer speeds. 3.9.36: Peter Wang made the keypad return / * - + ASCII values even if NumLock is off, under Linux console. 3.9.36: Ronaldo Hideki Yamada made a big update of the Mac port, including some new PPC files. 3.9.36: The GGI driver was removed, due to its inability to actually work. It is no longer supported, unless someone rewrites it. 3.9.36: Eric Botcazou fixed a problem with the GDI driver when compiled with MSVC. 3.9.36: Some MIDI fixes by Javier Gonzalez and Eric Botcazou. 3.9.36: Grzegorz Adam Hankiewicz improved the fb.modes line parsing function in the fbcon driver. 3.9.36: Grzegorz Adam Hankiewicz changed the behaviour of GFX_SAFE. This means that "set_gfx_mode(GFX_SAFE, ...)" now returns an error if it is unable to set a video mode, just like any other video driver. 3.9.36: Eric Botcazou fixed volume setting in Windows. 3.9.36: Eric Botcazou added DirectX 3 compatibility. 3.9.36: Nick Kochakian added input routines to the DirectSound driver. It was also modified by Javier Gonzalez. 3.9.35: Eric Botcazou made Windows restore the original sound volume after an Allegro program quits. 3.9.35: Eric Botcazou fixed sample looping in DirectSound driver. 3.9.35: Grzegorz Adam Hankiewicz solved some color problems in the demo game. 3.9.35: Angelo Mottola implemented a close button hook for X11. 3.9.35: Eric Botcazou fixed _the_ Windows 2000 keyboard bug. 3.9.35: Eric Botcazou made some changes to the locking/unlocking mechanism in the Windows port. 3.9.35: Laurence Withers made some modules avoid linking dependencies. 3.9.35: Javier Gonzalez added close button support for Windows. 3.9.35: Eric Botcazou improved mouse handling in the GFX_GDI driver and fixed some other mouse glitches. 3.9.35: Peter Wang made set_mouse_sprite(NULL) regenerate the default arrow bitmap (using the current palette). 3.9.35: Eric Botcazou made hardware accelerated primitives stop when the user switches out in Windows. 3.9.35: Tom St Denis fixed clipping of transparent objects. 3.9.35: Eric Botcazou and Javier Gonzalez improved switching in Windows and other things. 3.9.35: Peter Wang made the Linux joystick driver use standard constants. 3.9.35: Sven Sandberg changed the Z-buffer API. 3.9.35: Peter Wang made the default mouse sprite independent of the palette in 8 bpp modes. 3.9.35: Bertrand Coconnier added documentation for the P3D merge. 3.9.35: Angelo Mottola fixed desktop_color_depth() and added window close button support for the BeOS port. 3.9.35: Ben Davis added the set_window_close_button() and set_window_close_hook() framework. 3.9.35: Peter Wang exposed the mouse_sprite, mouse_x_focus and mouse_y_focus variables. 3.9.35: Robert Ohannessian and Javier Gonzalez fixed bad clearing of subbitmaps. 3.9.35: Peter Wang renamed GFX_XDFS to GFX_XDGA_FULLSCREEN. 3.9.35: Henrik Stokseth updated the cross-compilation system. 3.9.35: Tomohiko Sugiura added some keys and renamed some JP keys. 3.9.35: Eric Botcazou added a DirectDraw2 interface, with support for refresh rates. 3.9.35: Bertrand Coconnier merged in Calin Andrian's P3D library. 3.9.35: Javier Gonzalez made allegro_message() use the title from set_window_title() in Windows. 3.9.35: Andreas Kluge fixed division bugs in the fix class. 3.9.35: Stepan Roh documented the FA_* flags. 3.9.35: Peter Wang added hooks to allow overriding the look of standard dialogs. 3.9.35: Peter Wang changed X window placement and mapping behaviour. 3.9.35: David A. Capello made dotted_rect() avoid bank switches. 3.9.35: Eric Botcazou fixed a freezing problem under Window with locking/unlocking bitmaps under heavy load. He received help tracking down the bug from Javier Gonzalez. 3.9.35: Stepan Roh fixed a bug with FA_RDONLY constant under Unix. 3.9.35: Eric Botcazou cleaned up the Windows graphics subsystem. 3.9.35: "Sask Allegro" added support for more than two joysticks in the Windows port. 3.9.34: Ben Davis made close button in Windows windowed modes not simulate Escape key, in preparation for new behaviour (in next WIP). 3.9.34: Laurence Withers fixed a problem with accents in keyconf. 3.9.34: Javier Gonzalez added DIGMID to the Windows MIDI drivers list. 3.9.34: Eric Botcazou cleaned up the DirectDraw subsystem. 3.9.34: Eric Botcazou made the DirectDraw overlay driver comply with page flipping and triple buffering code, amongst other things. 3.9.34: Bertrand Coconnier improved subtexel accuracy for texture mapping. 3.9.34: Javier Gonzalez corrected mouse movement speed in Windows. 3.9.34: Ben Davis adapted polygon functions to handle two coincident vertices, and changed and clarified texture coordinate alignment in code and documentation. 3.9.34: Grzegorz Adam Hankiewicz fleshed out the docs for Unicode functions, adapting from djgpp and gcc docs. 3.9.34: Eric Botcazou fixed a triple buffering problem in the DirectDraw accelerated driver. 3.9.34: Henrik Stokseth added support for cross-compilation in the mingw32 build. 3.9.34: Grzegorz Adam Hankiewicz updated more examples for GFX_SAFE. 3.9.34: Ben Davis added set_volume_per_voice(), made silent voices continue playing and fixed other minor bugs. 3.9.34: Ben Davis fixed a bug in create_rgb_table(). 3.9.34: Angelo Mottola added display switching routines for BeOS and fixed some bugs. 3.9.34: Laurence Withers updated documentation about `const'. 3.9.34: Ronaldo Hideki Yamada contributed a macintosh port of Allegro. 3.9.34: Grzegorz Adam Hankiewicz changed and documented new GFX_SAFE behaviour (that color depth is undefined), updated the fbcon driver to take advantage of this and updated example programs. 3.9.34: Peter Pavlovic fixed a bug caused by file selector stretching. 3.9.34: Bertrand Coconnier fixed bugs related to poly3d(); removed never-called C versions of scanline functions for POLYTYPE_FLAT and non-8bpp POLYTYPE_GCOL; and made clip3d() and clip3d_f() functions compliant with Z-buffered polygons. 3.9.34: Stepan Roh added C version of masked_stretch_blit(). 3.9.34: Angelo Mottola did more work on BeOS: hardware acceleration (rect, hline, vline, clear_to_color, blit); mouse fix in windowed mode; desktop_color_depth(); yield_timeslice(); 3.9.34: Peter Wang retroactively updated CHANGES and AUTHORS from late 3.9.33 to present using CVS logs and email archives, and possibly messed up. 3.9.34: Angelo Mottola added a BeOS windowed driver (originally by Peter Wang), a BeOS MIDI driver, mouse wheel support under BeOS and made many bug fixes and changes to other BeOS code and documentation. 3.9.34: Laurence Withers fixed dat2s output of fonts for new font subsystem. 3.9.34: Peter Wang made the SVGAlib driver more robust. 3.9.34: Peter Wang changed the way Intellimouse protocols are selected under Linux console. 3.9.34: Eric Botcazou added file_select_ex and reverted file_select to old behaviour. 3.9.34: Laurence Withers added ugetcx() function. 3.9.34: Laurence Withers designed and implemented a new FONT structure, which should provide many advantages over the old one. 3.9.34: Eric Botcazou made more fixes to Windows code. 3.9.34: Bertrand Coconnier added a z-buffer rendering mode for 3D polygons (derived from Calin Andrian's P3D library) and an example program for it. 3.9.34: Michael Bukin added customization for keycode to scancode mapping in X. 3.9.34: Peter Wang added mouse wheel support to d_textbox_proc and d_slider_proc, and made file selector dialog stretch. 3.9.34: Tom Fjellstrom added an ALSA MIDI driver. 3.9.34: Eric Botcazou made some changes to the Windows windowed driver. 3.9.34: Grzegorz Adam Hankiewicz updated the documentation and the makedoc program to produce better .texi output. The new version works very well with the texi2dvi program, which produces fine ready to print device independent output. Also documented the new unix makefile targets. 3.9.34: George Foot added --env option to allegro-config script. 3.9.34: Benjamin Stover made some vararg fixes in unicode.c and added a workaround for missing defines in fbcon.c. 3.9.34: Robin Burrows added a Windows waveOut sound driver. 3.9.34: Eric Botcazou changed desktop_color_depth() for Windows. 3.9.34: Angelo Mottola added line switching and refresh rate support to DGA2 driver. 3.9.34: Bertrand Coconnier added scanline subdivisions and fixed 3D polygon drawing. 3.9.34: Angelo Mottola added BeOS joystick driver. 3.9.34: Angelo Mottola added DGA2 driver. 3.9.34: Robin Burrows added Windows sound driver using Allegro mixer. 3.9.34: Stepan Roh added workaround for fceil defined in Irix headers. 3.9.34: Michael Bukin changed DGA screen clearing. 3.9.34: Tomohiko Sugiura added a more aggressive Sidewinder driver. 3.9.34: Tomohiko Sugiura added three Japanese keys. 3.9.34: Stepan Roh made C functions const-correct. 3.9.34: Bertrand Coconnier fixed blending in atex_lit scanline functions. 3.9.34: Michael Bukin modified text_mode to return previous mode. 3.9.34: Peter Pavlovic fixed scrollbar display in grabber and improved scrolling in GUI objects. 3.9.34: anarko made GUI objects restore textmode. 3.9.34: Laurence Withers added font destroy hook. 3.9.34: Vincent Penquerc'h modified the mouse button press/release events so they have higher priority than double-click events. 3.9.34: Eric Botcazou improved colormap handling in XDGA. 3.9.34: Robin Burrows provided a new page flipping code for the DirectDraw subsytem, which now works on every graphic card. 3.9.33: Henrik Stokseth updated the mingw32 makefile, the documentation and sent in some other related fixes and updates. You will never again need MSVC to compile the Allegro DLLs. ;o) 3.9.33: Peter Puck contributed some updates to Allegro's win32 code which got the native mingw32 build fully working. 3.9.33: Michael Bukin changed the auto-repeat handling in X, sched_yield handling for Unix, fixed _add_exit_func, and added list of active dialogs to the GUI. 3.9.33: Vincent Penquerc'h sped up the C versions of the RLE sprite drawing routines by quite a bit. 3.9.33: Peter Wang improved TGA palette loading. 3.9.33: Laurence Withers made more functions const-correct. 3.9.33: Isaac Cruz moved Windows bitmap locking to a separate .S file, changed the update logic for the windowed driver, and added an accelerated vline implementation. 3.9.33: Stephen Kittelson fixed a bug in pckeys.c, and changed the ASCII values returned for a few weird key combinations. 3.9.33: Peter Wang made various functions const-correct. 3.9.33: Peter Pavlovic made aesthetic modifications to the GUI menu system. 3.9.33: Javier Gonzalez suggested that the file and mode selector dialogs should use popup_dialog. 3.9.33: Vincent Penquerc'h added the install-gzipped-man makefile target, patched some of the EINTR handling, and made the OSS driver detect whether the device is 16 bit or not. 3.9.33: Peter Pavlovic modified the Slovak keyboard mapping and made the file selector detect available drives in Windows. 3.9.33: Peter Wang added a sound (output only) driver for BeOS. 3.9.33: Sven Sandberg fixed a typo in the definition of ustrdup, added the uwidth_max function, provided the d_yield_proc function, and made various dialogs use it. 3.9.33: Michael Bukin made the DGA driver clear video memory and centre the screen, if it's not fullscreen. 3.9.33: Eduard Bloch suggested better ways to find the executable in Unix. 3.9.33: Andrew Geers added flipped rotated sprites. 3.9.33: George Foot made the Unix makefile work for non-root users. 3.9.33: Grzegorz Adam Hankiewicz made language config files be forced to lower case. 3.9.33: Grzegorz Adam Hankiewicz added documentation for findfirst(), findnext(), and findclose(), and corrected the documentation for get_executable_name(). 3.9.33: Stepan Roh made patches to allow compilation on IRIX. 3.9.33: John Harger made a change to improve the stability of AllegroGL in Windows. 3.9.33: Sven Sandberg fixed a bug in the plain C 16bpp stretched blitter. 3.9.33: George Foot fixed a bug in the i386 8bpp masked blit routines, reported by Damian Yerrick. 3.9.33: Eduard Bloch fixed a freeze caused by the ESD detection code. 3.9.33: Vincent Penquerc'h added mouse button press/release events to the GUI system. 3.9.33: Peter Wang solved a conflict with SVGAlib. 3.9.33: Vincent Penquerc'h added the XCRP and YCRP properties to bitmap objects in datafiles. 3.9.33: Vincent Penquerc'h made the GUI system not send MSG_DRAW to hidden objects. 3.9.33: Chris La Mantia pointed out that his code for textprintf_right had mutated somehow. 3.9.33: Peter Wang added a workaround for a mouse motion reporting bug in some X servers. 3.9.33: Eric Botcazou altered the DGA code to work better in 32bpp modes. 3.9.33: Daniel Nilsson tweaked exstars and exlights 3.9.33: Isaac Cruz fixed a nasty bug with subbitmap locking, and added desktop_color_depth and yield_timeslice support to the Windows version. 3.9.33: Peter Cech made uisspace() recognise non-ASCII space characters. 3.9.32: S.Sakamaki added a function for controlling the refresh rate when using the DOS VESA 3.0 driver (this could also be supported by some other drivers if anyone wants to implement that). 3.9.32: S.Suzuki added DOS drivers for the IF-SEGA /PCI, /PCI2, and /ISA joystick interface cards. 3.9.32: Fabrizio Gennari added DOS drivers for multisystem joysticks with 9-pin connectors (Atari, Commodore 64, MSX). 3.9.32: Peter Pavlovic improved the support for accented character maps in the keyboard driver. 3.9.32: Sven Sandberg optimised the GUI listbox scrolling to skip redraws if it can't keep up with the update speed. 3.9.32: Olly Betts did some work to make cross-compiling the djgpp version work on Linux. 3.9.32: Isaac Cruz improved the windowed mode ddraw driver, adding support for many different color depth conversions. 3.9.32: Vincent Penquerc'h added an update selection function to the grabber. 3.9.32: many bugfixes from various people. 3.9.32: zipup.sh now generates dependencies entirely using standard Unix tools and gcc, so it can setup all the supported platforms without needing those compilers to be available (ie. I can create Watcom, BeOS, and Mingw32 dependencies all from my Linux machine). This does require a bit of cooperation from the different targets, though: they have to set up their "make depend" target to override the standard gcc defines, and wrap any non-standard header includes with "#ifndef SCAN_DEPEND". 3.9.32: fixed (I hope :-) bug with non-GMT timezones in the datafile update code. 3.9.32: rewrote the Unicode usprintf() to piggyback on libc when converting floating point data (too hard to get this right ourselves :-) 3.9.31: Henrik Stokseth did some work on a native Mingw32 build. This is currently incomplete, and unlikely to work right now since there have been other changes in the Windows code since the version he started from. At the moment this version is statically linked, using makefile.mgs, and makefile.mgw still exists for the MSVC-piggyback version. The ultimate goal is to get this native version building as a DLL in addition to statically linked, at which point we can merge both makefiles into makefile.mgw and remove makefile.mgs. Oh yeah, and there are currently no docs for the native version. 3.9.31: Greg Hackmann contributed a Borland C++ Builder port. Like the RSXNT and Mingw32 versions, this is a client for the MSVC DLL, and not able to compile Allegro directly itself, but allows you to build Allegro programs using the Borland compiler. 3.9.31: Robert Ohannessian added MMX optimisation for the 8 and 16 bit clear() functions, and Jose Antonio Luque optimised the 16 bit blit() and masked_blit() routines. 3.9.31: Vincent Penquerc'h added a yield_timeslice() function (currently implemented in DOS and Unix). 3.9.31: added a desktop_color_depth() function (currently only implemented in X: a Windows version will follow). 3.9.31: Isaac Cruz added support for windowed modes in color depths other than the current Windows desktop, and hardware accelerated system bitmaps. 3.9.31: Jose Antonio Luque improved the Windows joystick driver. 3.9.31: James Hyman added support for dithering truecolor down to paletted images. 3.9.31: Chris La Mantia added textout_right(), textprintf_right(), and textprintf_justify() functions. 3.9.31: Sven Sandberg added a ustrrchr() function, and improved the usprintf() handling of large floating point values. 3.9.31: Peter Pavlovic added a Slovak keyboard mapping and message translation. 3.9.31: Manni Heumann fixed some problems with the German keyboard mapping. 3.9.31: Michael Bukin improved the X keyboard and mouse handling, and fixed some problems with building on non-GNU Unix systems. 3.9.31: many bugfixes and tweaks from various people (sorry, my typing patience has run out so you don't get a full list :-) 3.9.31: Peter Wang added input support to the Linux OSS sound driver. 3.9.31: David Kuhling optimised the i386/gcc fsqrt() code, and added an fhypot() routine. 3.9.30: fixed the double XOR that was making datafile passwords so easy to reverse. The new code can still read old-style encrypted files, but data written by this version can't be accessed by older copies of Allegro. 3.9.30: made load_datafile(), load_datafile_object(), and the file.dat#object syntax work correctly in all possible combinations. 3.9.30: Vincent Penquerc'h added a scare_mouse_area() function. 3.9.30: changed the DirectX surface locking mechanism, to improve the performance of hardware accelerated drawing. 3.9.30: George Foot improved the Linux LED code, and made the internal X driver state visible via xalleg.h. 3.9.30: added EINTR retry handling to read/write calls. I hope I got this right: if anyone who properly groks this stuff could check over file.c, that would be cool. 3.9.30: made the Windows mouse driver work correctly in windowed mode. 3.9.30: fixed various problems with Windows foreground/background switching (keys were getting stuck down, timers weren't being paused, and not all the right switching modes were being reported to the caller). 3.9.30: made the X keyboard handler release all keys when it loses the input focus, to avoid stuck buttons when you alt+tab between windows. 3.9.30: made the allegro-lib script arguments compatible with the standard used by GTK, ESD, etc, and renamed it to allegro-config. This changes the syntax for linking Allegro programs on Unix: see readme.uni for details of the new method. 3.9.30: George Foot improved the Unix shared library system. 3.9.30: Joerg Rueppel added a find_datafile_object() function. 3.9.30: Peter Wang improved the SVGAlib driver. 3.9.30: Peter Wang improved the Linux joystick driver. 3.9.29: made the Windows code agree with other platforms about how video bitmaps are supposed to behave. 3.9.29: fixed some problems with the Windows mouse wheel support. 3.9.29: added set_write_alpha_blender(), set_add_blender() and create_blender_table() functions, and made the 32 bit version of draw_trans_sprite() able to use 8 bit source images in conjunction with set_write_alpha_blender(). In addition to being generally useful, using these routines makes the sources for my SpeedHack entry much smaller :-) 3.9.29: added uninstall targets to the Linux makefile. 3.9.29: made the X windowed mouse driver hide the Allegro cursor when the mouse moves out of our window. 3.9.29: added a simple timer delay emulation of vsync() to the X code, so that eg. the demo worms game runs sensibly. 3.9.29: Isaac Cruz added a GFX_DIRECTX_WIN driver. 3.9.29: Keith Gerdes made some more improvements to the DirectX overlay driver. 3.9.29: Andrew Geers added scrolling support to the grabber image viewer. 3.9.29: Peter Wang added an alternative X DGA driver, that includes mode switching support to run in fullscreen mode. 3.9.29: Peter Wang added a MSG_WHEEL event to the GUI, and made d_list_proc() use it. 3.9.29: Lucas Vignoli Reis added a Portuguese (Brazil) message translation and keyboard mapping. 3.9.29: Peter Wang added a Linux OSS MIDI driver for FM synth devices, and mixer support for the OSS digital driver. 3.9.29: George Foot added scripts for building various Linux distribution formats. 3.9.29: Michael Bukin fixed the portability problems in quantize.c. 3.9.29: added a zipwin.sh script for making Windows binary distributions, including a batch file that can compile the MSVC support programs without having any GNU tools installed. 3.9.29: fixed bug with color font rendering in the Windows version. 3.9.29: added hardware accelerated rectfill() and hline() to the Windows version, and fixed a couple of accel related bugs (clears were being clipped wrongly, and it was claiming to support XOR drawing even though that isn't supported). 3.9.29: Michael Bukin fixed bug with X drawing onto screen sub-bitmaps. 3.9.28: various documentation updates. 3.9.28: added parameter autodetection to the Unix OSS sound driver. 3.9.28: made it possible to nest calls to the Unix for_each_file() routine. 3.9.28: added a load_datafile_callback() function. 3.9.28: rationalised the sound config variables, so they can be shared between drivers more easily. For instance sb_freq has been renamed to sound_freq. 3.9.28: Antti Koskipaa added a DOS driver for WSS (Windows Sound System) cards. 3.9.28: the audiosteam code is now able to merge multiple buffers into a single larger one, so it will still work correctly even if the user supplies a buffer smaller than the current soundcard transfer size. You can even play streams with single byte buffers now, as long as you refill them often enough! 3.9.28: made the Windows timer code more robust, so it will no longer lock up when you install extremely high frequency callbacks. 3.9.28: Teijo Hakala added wheel support to the Windows mouse driver. 3.9.28: Peter Wang added wheel support to the X mouse driver. 3.9.28: Andrew Geers added -ppassword and -nosound options to the grabber. 3.9.28: Keith Gerdes fixed the DirectDraw overlay mode driver. 3.9.28: Isaac Cruz fixed the bug with accelerated drawing onto sub bitmaps of DirectDraw surfaces. 3.9.28: Peter Wang added banked mode support to the SVGAlib driver. 3.9.28: Peter Wang fixed some problems with the ESD sound driver, and added an ALSA driver. 3.9.28: palette fading speed is now timer regulated, to avoid problems with some systems (eg. DGA with non-matching color depth) where it can be excessively slow. 3.9.28: fixed a couple of different overflow bugs that were causing timers to run slow on heavily loaded Unix systems. 3.9.28: added a display of author credits to the demo game. 3.9.28: changed the info page installation system. It now creates a dir file in the same directory as the info page, rather than messing around with symlinks, and autoconf is used to locate the install-info program. 3.9.28: added an allegro-lib script to the Unix installation, which can be run by makefiles to find the right linker commandline for building Allegro programs. 3.9.28: added a manpage output format to the makedoc utility. It doesn't work terribly well with apropos due to the lack of a one-line summary for each function, but the basic formatting seems to be ok: please let me know if you see any problems. 3.9.28: patches from George Foot for Linux console handing, keyboard, and filename manipulations. 3.9.28: many improvements by Michael Bukin, in particular enhanced performance in X, better X mouse behaviour, and DGA graphics support. 3.9.27: Robert J. Ragno made some improvements to the Wingman, PSX, and throttle joystick input code. 3.9.27: Peter Wang added wheel input support to the Linux mouse code (this shows up as a new mouse_z state variable). 3.9.27: Patrick Hogan made Windows audiostreams work properly. 3.9.27: Sven Sandberg optimised the spline routines. 3.9.27: Tomohiko Sugiura added KEY_YEN and KEY_YEN2 Japanese keys to the input handler. 3.9.27: Chris Robinson wrote a fixed point version of clip3d_f(), called (surprise!) clip3d(). 3.9.27: Sven Sandberg improved the file selector sorting algorithm. 3.9.27: Henrik Stokseth improved the OS detection in the Windows lib. 3.9.27: Sven Sandberg made more accurately rounded lookup tables for the fixed point trig routines. 3.9.27: George Foot made the fbcon driver reset the palette on exit. 3.9.27: much new X code from Michael Bukin: this stuff is working brilliantly now! 3.9.27: added the X library path to the Linux liballeg.a wrapper. I think I prefer Michael's idea of having a script to return this info, though, so perhaps we should change across to doing it that way. 3.9.27: fixed various bugs in both the C and i386 RLE sprite code (mostly relating to lit modes and hicolor formats). 3.9.27: front-ported various fixes from the 3.12 release, to make WARNMODE=1 compile cleanly with gcc 2.95. 3.9.27: Knut Pape improved the Mingw32 readme file. 3.9.26: rewrote the DOS Sidewinder driver, after powerjaw sent me a pad to test it with. It still doesn't work for me in DOS mode, but it is ok under Windows, which is better than before, and as good as any of the other Sidewinder code that I've been able to locate. If anyone has or knows of code that works better than this, please let me know! 3.9.26: more flexible mode flags for set_color_conversion(). 3.9.26: Robert J. Ragno added a driver for Gravis GrIP devices. 3.9.26: Gorka Olaizola added a Redhat RPM .spec file. 3.9.26: Stepan Roh updated the Czech translation and added multiple codepage support to the textconv utility, and a Unicode-aware ustrtod() function. 3.9.26: added ustrdup() to the Unicode support functions. 3.9.26: Sven Sandberg optimised the gcc fixed point math routines to collapse constant expressions at compile time. 3.9.26: Stefan T. Boettner added a proper Linux SVGAlib driver. 3.9.26: several tweaks from Vincent Penquerc'h (added a datafile merge function to the grabber, GUI bugfixes, optimised spline calculation, fix for 24 bit version of the C drawing code). 3.9.26: Linux patches from Michael Bukin improve the OSS sound driver, SIGALRM handling, and X keyboard driver. 3.9.26: many Linux patches from George Foot (fixes to the mouse driver, shared library and configure script, and assorted other stuff). 3.9.25: fixed pckeys.c to leave sensible data in the key[] array when doing numeral vs. arrow key numlock fakery. 3.9.25: fixed a bunch of problems with the SWITCH_BACKGROUND mode (I'd stupidly forgotten to disable a lot of graphics driver functions that could do bad things if called when the Allegro console isn't active). 3.9.25: added pivot_sprite() and pivot_scaled_sprite() functions (thanks to Matt Jallo for the suggestion). 3.9.25: added ustrerror() to the standard Unicode support functions. 3.9.25: fixed the d_edit_proc() GUI object to handle shift+tab focus movement properly. 3.9.25: lots of Linux patches from George Foot (proper fbcon mode setting, different mouse types and setup program support for configuring them, fixes to the shared library support, exedat no longer destroys the file permissions, and probably some other stuff that I forgot about). 3.9.24: assorted bugfixes to the Linux fbcon and sound code (this is mostly an emergency release because these were broken in 3.9.23). 3.9.24: James Arthur wrote some docs for the Photoshop-style truecolor blender routines. 3.9.23: Michael Bukin added an OSS sound driver to the Linux code, and the beginnings of an ESD driver. 3.9.23: many Linux patches from George Foot, including shared library support. 3.9.23: Ole Laursen made the Unicode utolower() and utoupper() functions understand the entire 16 bit character set. 3.9.23: Pavlos Touboulidis made file_select() able to include or exclude files based on their attributes. 3.9.23: the d_check_proc() GUI object can now print the text to the right of the check, selected by having a non-zero d1 field. 3.9.23: changed my mind about how GFX_SAFE should work, and removed the color depth emulation bodges. Now, the GFX_SAFE driver may simply change the color depth if it doesn't like what you are requesting, and it is up to the caller to deal with this. 3.9.23: fixed problems with MMX polygon rendering code in the MSVC version. 3.9.23: added a strictwarn option to the configure script, and fixed everything that it moaned about. The warnings still aren't all that strict: at some point I want to sit down and make it build cleanly with -W, as well as -Wall -Werror. 3.9.22: fixed some potential race conditions introduced by my previous fixes to the Windows timer code. 3.9.22: made set_display_switch_callback() able to install multiple hook functions, added a remove_display_switch_callback() routine, and wrote an exswitch example program. 3.9.22: adjusted MSVC inline asm syntax in an attempt to work around compiler version conflicts. 3.9.22: more flexible GFX_SAFE system. As well as defining fixed safe values for each platform, you can now leave out those definitions to get zeros passed through to the actual hardware drivers, and if your driver sets a color depth other than the requested one, graphics.c will hook up some emulation routines so that everything still works in a sensible way. 3.9.22: George Foot added a scancode to ASCII conversion function to the keyboard driver (implemented for DOS, Windows, Linux, and X). This is needed to handle alt+key input sensibly when using unusual mappings like the Dvorak layout. 3.9.22: Linux patches from George add better console switching, shared library support, and various other nice things. 3.9.22: Windows patch from Stefan adds much cool new stuff, including windowed mode support. 3.9.22: Peter Wang made the Linux GGI driver work properly. 3.9.22: Johan Venter made some more improvements to the RSXNT and Mingw32 makefiles. 3.9.22: updated the Watcom makefile to allow manual override of the 10.6 vs. 11.0 version detection, in case it guesses wrong. 3.9.21: Windows patch from Stefan adds support for the new screen mode switching system. 3.9.21: more BeOS patches from Jason Wilkins. 3.9.21: Johan Venter fixed some problems with the RSXNT and Mingw32 makefiles. 3.9.21: ran "configure --enable-asm=no", and fixed all the reasons why this didn't work. In particular there was a bug in patterned drawing modes, RLE sprites were broken, and I'd forgotten to add C versions of the RGBA sprite functions. Those of you who are interested in such things will be interested to know that the test program thinks the C drawing code is 20% slower at hline(), 10% slower at rectfill(), 50% slower at blitting, and 40% slower at draw_sprite(), which is not at all bad going. It's actually a bit faster at drawing translucent and lit sprites, so we need to have a look at that! 3.9.21: many new Linux patches from George Foot. 3.9.21: added VBE/AF support to the Linux code. 3.9.21: finished the Linux fbcon driver. 3.9.21: made Linux console switching work in a more complete manner, with a set of helper functions in dispsw.c. The background mode should work now, but is untested. 3.9.21: added Linux GGI driver by Carsten Schmidt (this is somewhat out of date, and doesn't work yet, but a good start if anyone wants to hack on it). 3.9.21: improved the Unix configure and build system. Moved more things into makefile.lst, so there are no file lists anywhere else now. Made it understand how to build the datafile tools, and convert the documentation (this may cause problems for systems without makeinfo: it would be good if someone who groks autoconf could try to do this better). Made the Linux VGA drivers (vga and modex) configurable. 3.9.21: added ctrl+alt+end abort sequence to the Linux keyboard driver. 3.9.21: directory structure changes: moved ufile.c into the misc directory, so BeOS can share it. Moved various helper scripts into the misc directory, including a cmplog.pl that compares two test.exe profile logs. 3.9.21: made the Linux PS2 mouse driver understand the middle button. Added a scaling factor to make it go at a more sensible speed in SVGA modes. 3.9.20: started working on a driver for the Linux fbcon device. It works, but can't change video mode yet. 3.9.20: Windows patch from Stefan adds joystick input, and the beginnings of a windowed mode driver. 3.9.20: moved all filename lists (even the platform specific ones) into makefile.lst, to avoid any duplication and give us a nice centralised place that mentions every single source file we use. 3.9.20: removed the install_lost_bitmap_callback() function, in favour of the more generic set_display_switch_mode(). Updated the Windows code to use these new routines. 3.9.20: merged X patch from Michael Bukin (adds mouse support). 3.9.20: Vincent Penquerc'h optimised the 256 to truecolor graphics blitting code to avoid repeated conversions of the palette table. 3.9.20: James Hyman added quoting support to get_config_argv(). 3.9.20: Peter Cech optimised the alpha sprite blending routines. Shawn optimised them a bit more by expanding out specialised versions for common pixel formats. 3.9.20: Richard Davies made some improvements to the PSX joypad driver. 3.9.20: added a system driver parameter to allegro.cfg, and hooks to make the Unix version look for config data in /etc/ and ~/. 3.9.20: moved the Posix findfirst() emulation into libc.c, removing it from the autoconf and BeOS specific builds. 3.9.20: more BeOS patches from Jason Wilkins. The graphics stuff be working there now! 3.9.20: improved the VBE/AF driver to know that vertical lines can be implemented as a rectfill. This enables hardware acceleration for patterned vertical lines, and with drivers that don't have hardware support for the VBE/AF line draw routine. 3.9.20: George Foot did some major work on the Linux console version, getting it up and running in a fairly convincing way. 3.9.20: the Windows sound driver lists are now dynamically generated based on the available devices, so you can select which ones to use. 3.9.19: wrote the first part of an Allegro Hacker's Guide, which is my (probably futile :-) attempt to document at least a few of the more gory parts of the Allegro code. 3.9.19: finally got around to documenting the Unicode functions. 3.9.19: more BeOS patches from Jason Wilkins. 3.9.19: Michael Bukin made some more patches to the X code (timers are implemented now), and added a complete (?) C implementation of all the drawing code. Non-Intel machines, here we come! If you define ALLEGRO_USE_C before building the djgpp library, you can actually test out a pure C version of test.exe, the demo game, etc. 3.9.19: added a findtext.sh script, which scans the source code and creates a list of all the strings that are available for translation. It can also compare this list against an existing translation file, to see if any new messages need to be added. 3.9.19: Stepan Roh updated the Czech keyboard mapping for Unicode support, added support for keyconf to use a non-standard font, and added the Latin Extended-A characters (U+0100 to U+017F) to the default font. 3.9.19: Grzegorz Adam Hankiewicz updated the Spanish translation with UTF-8 format (ie. properly accented) strings. Converted the setup program font into Latin-1 ordering so that this will display correctly. Fixed bug with dat2s not correctly converting the resulting multiple-range font. 3.9.19: Chris La Mantia made some cosmetic fixes to the d_slider_proc() GUI object. 3.9.19: Richard Davies added support for N64 joypads. 3.9.19: added keyboard_ucallback() (I missed this one when I first added the Unicode support). 3.9.19: made some changes to setup.c so that it can easily be embedded into other programs (thanks to Grzegorz Adam Hankiewicz for the suggestion). 3.9.18: added support for 32 bit RGBA images. You can now read TGA files with an alpha channel into the grabber, or you can import a normal image and then overlay alpha data from any greyscale bitmap. You can save these alpha channels as part of a datafile, call the makeacol(r, g, b, a) function, and most importantly, call set_alpha_blender() and then draw_trans_sprite() to display them. Check out exalpha.c. There is much room to optimise the 15, 16, and 24 bit versions of _blender_alpha*(), if anyone wants to have a go at this. I think it would be profitable to write specific versions for common pixel orderings, and only keep the current generic implementation around as an emergency fallback. 3.9.18: more Unix patches from Michael Bukin. It builds flawlessly now, even if it doesn't do anything very interesting yet. 3.9.18: Jason Wilkins contributed the beginnings of a BeOS port (not yet functional, but it does compile). 3.9.18: Revin Guillen added a position_dialog() function. 3.9.18: portability improvements: changed makefile to be a generated stub, which normally just includes makefile.all, but can be completely replaced when using autoconf, and moved the emulation for missing libc functions into the shared sources. 3.9.18: numerous bugfixes. 3.9.17: Burton Radons changed the truecolor pixel blending functions to use a single callback function rather than the previous table. This may break some old code, but should remain largely backward compatible, and the new way is much more flexible. He also added a more complete set of blender functions, including Photoshop modes like burn, difference, lumincance, etc. 3.9.17: Richard Davies added support for PSX joypads. 3.9.17: fixed bug in dat2s handling of truecolor images. 3.9.17: Jason Wilkins improved the quaternion math routines, and added some documentation for them. 3.9.17: Neil Townsend added callback parameters to the timer handlers. 3.9.17: Gunter Ladwig added three-button mouse emulation, which can be enabled using the config file (it defaults to on if you have a two button mouse). 3.9.16: applied some patches from Michael Bukin, which add the basics of a Unix build system. It doesn't actually work yet, though :-) 3.9.16: merged new code from Stefan. Lots more cool things are working in the Windows version now, eg. hardware acceleration, triple buffering, sound... 3.9.16: added an example of how to write a Windows screensaver using Allegro. If anyone knows how to get a proper name to show up in the Windows selection dialog, please let me know! (I've made the stringtable entry that MSDN says you need, but it doesn't work). 3.9.16: Andy Goth added a d_text_list_proc() dialog object, that lets you alter the selection by typing the first few characters of a list entry. 3.9.16: Ole Laursen updated the Danish message translation. 3.9.16: Calvin French added a -w (always update) switch to dat.exe. 3.9.16: Joerg Rueppel added more flexible wildcard matching for object names in dat.exe. 3.9.16: added GFX_HW_SYS_TO_VRAM_BLIT and GFX_HW_SYS_TO_VRAM_BLIT_MASKED capabilities flags, and more flexible blitting functions in the vtable. 3.9.16: added lock_voice() and unlock_voice() methods to the digital sound driver, for implementing audiostreams under Windows. 3.9.16: _handle_timer_tick() now returns the desired gap until the next interrupt. 3.9.15: Michael Rickmann added a Mingw32 port. This currently works the same way as the RSXNT version, using MSVC to build the DLL, but will become a full gcc port after the core Windows code stabilises a bit. 3.9.15: Vincent Penquerc'h added a D_DIRTY flag for GUI objects, and I extended this with a new D_REDRAWME return code for the handlers. 3.9.15: changed the syntax of the create_color_table() callback. This breaks the API, but is the only way to make it work reliably with different compiler calling conventions. 3.9.15: added a sub bitmap creation hooks to the vtable structure (so the parent bitmap can be told when it is being cloned). 3.9.15: "make install" is now a separate target, not run automatically. This means that you now have to run "make" and "make install" as two separate operations, or if you want all three versions of the library, "make all" and then "make installall". 3.9.15: added an END_OF_MAIN() macro, which makes the WinMain() magic work correctly in any combination of C and C++ code. 3.9.15: Olly Betts modified the djgpp makefile to support cross-compiling on a Linux machine. 3.9.15: Andy Goth added a 256x256 tweaked VGA mode. 3.9.15: major documentation update (from now on I'll be adding a version number to each changelog comment). Merged new code from Stefan. Windows version is getting much closer to completion, including mouse support and video bitmaps, although the mouse code isn't working quite right for me at the moment. Rewrote fix_filename_path() to avoid calling _fixpath(). The new version is much more portable, although things like reading the current directory across multiple drives need some tweaking to work with different compilers. Fixed oodles of things that were stopping the Watcom version from working. It now runs everything without any trouble at all, including such gems as exdodgy and the grabber shell edit! According to test.exe, gcc 2.8.1 is about 10% faster than Watcom 10.6 for most things, although for some reason textout() is about twice as fast in the Watcom version. Fixed a bunch of stuff to make the RSXNT version work. All the tests and examples now build with RSXNT, and work identically to the MSVC originals. Added quaternion math routines by Jason Wilkins. Added more flexible gfx_card config support by Andy Goth. Added a masked_stretch_blit() function (trivial change, the code could do it, but the API entry point was missing). Added Windows GDI routines by Marian Dvorsky. Added a DMA poll to the Soundscape driver, to make sure it can never get out of sync with the transfer. Merged various bits and pieces that have been sitting around my hard drive for ages (Swedish and Norwegian translations, various patches from Michael Bukin, new palette generation code by Michal Mertl, Soundscape driver fixes by Andreas Kluge). Grabber now knows about and can manipulate Unicode fonts. Now passing atexit() as a parameter to install_allegro(), to avoid problems with DLL shutdown. Made FLIC player set the dirty variables when clearing the bitmap at the start/loop point (this was sometimes causing the screen not to be cleared from previous contents). Fixed several bugs in the grabber. Changed the datafile utilities to link the datedit and plugin routines as a proper library. This will make life easier for third parties that want to use those routines (duplicating the plugin linkage isn't much fun). Replaced errno references with allegro_errno pointer, to avoid problems with multiple runtimes when linking as a DLL. The MSVC version of dat now works perfectly! Added a system_none driver for commandline utilities and other platform neutral situations. Made new demo intro animation. My first ever Max rendering! Merged Windows patches from Stefan. Whoah! This thing is cool. It works (sort of :-) on two platforms. Now I can die happy.... The file selector now adjusts for platforms without any directory list (eg. Unix). Added a global default_palette (the normal IBM BIOS one), and made set_gfx_mode() select it. Modified DIGMID driver to avoid using 64 bit ints or floating point in the interrupt handler. Added ASSERT() and TRACE() debugging routines, and lots of asserts throughout the library code. The default truecolor pixel format before setting a video mode is now BGR rather than RGB. This should help to shake out bugs in BGR support, and catch any errors where people load graphics before setting a video mode. Fixed fmul() overflow detection bug. Rewrote gpro.c and sw.c to avoid using inline asm. The SW code is currently very ugly (literal translation of the asm routine), but I'm keen to improve it given some testing feedback. If you have a Gamepad Pro or Sidewinder, and were able to use it with the Allegro 3.11 driver, I would _really_ like to hear whether this current code works for you or not... Numerous changes to make the support programs more portable. Added a get_executable_name() function. The sound.cfg file is no longer supported. Use allegro.cfg instead. Added versions of the inline _putpixel() and _getpixel() for all color depths. The check_cpu() function is now called automatically by allegro_init(). Added system bitmap objects, which exist in system memory but are accessed in a similar way to video memory surfaces (this can enable better hardware acceleration on some platforms). Added enable_triple_buffer(), timer_can_simulate_retrace(), and timer_is_using_retrace() functions. This enables programs to correctly handle the interrelationship between mode-X triple buffering, the retrace sync mode, and the current OS, without having to include any DOS specific code. GUI routines now call the input polling functions and acquire/release the screen as appropriate. Fixed a real show-stopping error that was causing VBE/AF crashes on some machines (calling driver functions with non-flat memory selector in %es). Added an allegro_message() function. Added dummy bank switch routines that can emulate linear access to a mode-X screen, albeit rather slowly. The only practical result from this is that polygon routines work in mode-X now, but it helps to make things more robust in general (if a routine doesn't know about mode-X, now it will just run more slowly than usual, rather than not working at all). The SB, Adlib, and standard joystick drivers now properly have a separate instance for each variant of the hardware, rather than a single driver pretending to exist under multiple different ID codes. Rewrote joystick polling to avoid inline asm. Converted translation files into UTF-8 format. These can now use any Unicode characters they like, so accented vowels etc. can safely be used. Keyboard scancodes have changed from the hardware format to an abstract, Allegro-specific encoding. This simplifies the code a great deal, and avoids hassles with two different keys generating the same scancode. Added generic find_allegro_resource() function, which removes a lot of duplicated code from config.c, digmid.c, and pckeys.c. Timer module now autoinstalls whenever someone tries to use it. Keyboard functions can now alter the repeat rate. Watcom port. Added a special GFX_SAFE driver ID. Now using VDS to detect win95 even when in stealth mode. Added fixver.sh for patching version numbers and dates when releasing a new version (requires bash, fileutils, shutils, etc, to run on DOS). Added zipup.sh for building a distribution zip and diffs, which automatically cleans up the tree ready for this (eg. pregenerating the dependency files for all supported compilers). Added input polling functions. Major code restucturing, added system drivers, new framework for input handling, timers, keyboard scancode conversion, file access, etc. Added full support for Unicode text, including string manipulation functions, a new font format, the textconv utility, a new GUI MSG_UCHAR, and a ureadkey() function. Added variable sized monochrome fonts, replacing the the old 8x8 fixed size format. As a result, the GFX_HW_TEXTOUT_FIXED capabilities flag has been renamed to GFX_HW_GLYPH. New system for accessing video memory, using bmp_select(), bmp_write*(), and bmp_unwrite_line(). This is equivalent to the djgpp farptr functions, but portable to different platforms. Drastic reorganisation of directory structure, makefile system, etc. Enhanced the makedoc utility to simplify adding links and email addresses to the docs. Added a bodge to make the VESA code work with broken S3 Trio64 drivers. Removed the 386DX vs. 386SX processor detection code (it was sometimes crashing). ============================================================== ============ Changes from 3.11 to 3.12 (Aug 1999) ============ ============================================================== Fixed a few incompatibilities with gcc 2.95. This release is otherwise identical to 3.11. ============================================================= ============ Changes from 3.1 to 3.11 (Feb 1999) ============ ============================================================= Cleaned up a few places where memory wasn't getting freed during the system shutdown. A cosmetic detail since the OS will free it for us, but it is nice to get these things right. Alessandro Monopoli added an Italian translation of the system messages. Henrik Stokseth added code to distinguish between win95 and win98. Creative Labs have been removed from the THANKS file, because of their refusal to release any specs on the SB Live soundcard. Changed the name of the library. After years of thinking that Allegro was a word with no particular meaning, I realised that it is in fact a recursive acronym for "Allegro Low Level Game Routines". Established a new mailing list for use by the people currently working on Allegro. Please send code contributions to this list rather than directly to me (Shawn Hargreaves), because this will allow Allegro development to continue even if I'm not around or am busy with something else at the moment. Andreas Kluge wrote a driver for Ensoniq Soundscape cards. More localisation: Swedish message translation by Sven Sandberg, Anton Ragnarsson, and Erik Sandberg, Finnish message translation by Antti Haapala, and Russian message translation and keyboard mapping by Dmitriy Kazimirow. The midi_out() function now correctly updates the pan/volume/bend controller status. Kester Maddock added a Wingman Warrior joystick driver. Fixed some problems with the Sidewinder, Gamepad Pro, and SNES joypad drivers. Changed the SB16 driver to use signed 16 bit output mode, rather than the previous unsigned format. Hopefully this will improve compatibility with crappy clone hardware. Added a new WARNMODE environment switch to the makefile. Allegro developers should all set this to get strict warnings, but it will be left off by default so that the distributed version will be more forgiving about different compiler/libc versions. Fixed problem with reading the top and left positions on digital joystick devices. Fixed (I think, still waiting accurate confirmation on this one :-) problem with timers running too fast on some motherboards. Fixed stupid bug where get_align_matrix() wasn't bothering to zero the translation vector. Fixed stupid bug where rotated sprites were coming out upside down in mode-X and hi/truecolor modes. Fixed bug where dat utility was truncating long filenames to 8.3 format. Renamed the ChangeLog file to CHANGES, to avoid problems on 8.3 systems. Various other minor bugfixes. ============================================================ ============ Changes from 3.0 to 3.1 (Jan 1999) ============ ============================================================ Changes between the 3.1 beta and final releases: assorted bugfixes, Antoine Mathys added a Swiss keyboard mapping, Thomas Wolf added a German translation of the system messages. Changes between the 3.1 alpha and beta releases: assorted bugfixes, FLIC routines can now read from datafiles, included rotation optimisations by Ivan Baldo. Peter Cech added support for hot-swapping between a custom keyboard layout and the standard US mapping. Neil Townsend improved the accuracy of the timer routines. Added exlights.c example program, showing one way to do colored lighting effects in a hicolor mode (and also because it makes the total number of examples a nice round number :-) Added an afinfo test program, which does the same thing as vesainfo but for VBE/AF drivers. Michael Bukin made a lot more portability patches and some bug fixes, including some improvements to the FLIC player and a much more rational filename handling system. Removed the chipset-specific SVGA hardware drivers from the main library distribution. Instead, these will now be available both as an optional addon package, and reformatted as part of the FreeBE/AF project. Added FreeBE/AF extensions support to the Allegro VBE/AF driver (farptr access to video memory, and the libc and pmode exports needed for future compatibility with the SciTech Nucleus drivers). Fixed a bug with the patterned and translucent vline() function in 15 bit color depths. Fixed a NULL pointer dereference bug in the config routines. Fixed an order of processing bug that was causing data to be lost when calling set_config_file() with the same filename as the current config. Stepan Roh added a Czech translation of the system messages. Ole Laursen added a Danish translation of the system messages. Grzegorz Ludorowski made a new demo game intro animation. Calin Andrian added 3d polygon timing routines to test.exe. Peter Cech added grabber support for the 8x8 BIOS font format. Stepan Roh added a Czech keyboard mapping. Renamed the Spanish language translation file from SP to ES. Calin Andrian added a complete set of truecolor polygon rendering routines, with support for MMX and 3DNow! optimisations and a new masked lit drawing mode, along with a new polygon clipping function. One minor change is that POLYTYPE_FLAT mode is now implemented by calling hline(), so it will respond to the current drawing_mode() settings. Changed the graphics/sound/joystick driver ID numbers from a zero based list to a descriptive 4-character string, to make them more readable and flexible. Added config functions to read/write data in this format. The sound config data is backwardly compatible, but you will need to manually update any graphics or joystick driver numbers that are stored in your config files. Michael Bukin contributed a _lot_ of patches to improve the portability and robustness of pretty much the entire library. The only externally visible change is that the macros used for declaring hardware driver lists have been redesigned to use a more portable syntax, although the old syntax is still available as a compatibility macro. Burton Radons did some more optimisation of the truecolor pixel blending functions. Martijn Versteegh added a hook mechanism for extending the config file system, which can be used to provide extended system status information or customisation routines for addon packages. Redesigned the grabber and dat utilities to support source-code "plugin" modules, which can be used to extend the system with additional object types, import/export routines, and menu commands. Ivan Baldo added a dithering option to the 15/16 bit color conversion routines. Kerry High added a SNES joypad driver. Added a font override to the d_text_proc() and d_ctext_proc() GUI objects, using the dp2 field to specify a custom font. Michael Tanczos fixed some bugs in the FLIC player. Cloud Wu optimised the truecolor pixel blending functions. Paul Pinault added a French translation of the system error messages. Grzegorz Adam Hankiewicz added a Spanish translation of the system error messages, and added a new (but undocumented :-) command line option to the demo game. Fixed clicks in the interpolated sample mixing. Fixed a bug with position_mouse() not updating the mouse_pos variable. Fixed a bug in mode-X horizontal scrolling while the timer retrace simulator is active. Added a language.dat file, which can be used to provide translated versions of system strings (eg. error messages), in a similar way to the existing keyboard.dat. If you want to use this mechanism from your own code, replace all your constant strings with calls to get_config_text("string"). This allows them to be translated by including a line of the form "string=foreignstring" in the relevant section of language.dat. Added an ASCII name field to the keyboard mapping files, in order to make the setup program a bit more friendly. Increased the maximum number of sound channels from 32 to 64. Modified the DIGMID patch loader to support 16 bit samples, rather than just reducing everything to 8 bit. Added an interpolation option to the sample mixer (quality=2). Salvador Eduardo Tropea added support for proper 16 bit sample mixing (quality=1). Lee Killough added a lower level hook routine to the keyboard handler. Removed floating point code from the DIGMID driver, to avoid potential FPU stack overflows. Jim Flynn removed floating point calculations from the AWE32 MIDI driver (these could sometimes cause stack overflows). Salvador Eduardo Tropea improved the datafile system to avoid linking of unused code. Romano Signorelli contributed a Bresenham arc plotting function. Thomas Wolf corrected some errors in the German keyboard mapping file. Grzegorz Adam Hankiewicz improved the excolmap example program. Sven Sandberg optimised the fixed point trig routines. Fixed some silly crash bugs in the joystick code. Added a "compress" target to the makefile, based on a suggestion by Grzegorz Adam Hankiewicz. Added dummy bitmap acquire/release functions to allegro.h, for compatibility with the Windows version. Added a cross-reference facility to the Info format documentation. Martin Fuller fixed an obscure bug in the reading of compressed .bmp files. The emergency exit signal handler now correctly restores the previous handler, rather than resetting to the default action. Sven Sandberg optimised the create_light_table() function. George Foot fixed a bug when the get_mouse_mickeys() routine was called with both parameters pointing to the same value. Changed the licensing terms from "swapware" to "giftware". See the Allegro website for an explanation of the reasons for this change. Added yet more overloaded operators (this time for long and double types) to the fix class. Marius Fodor added support for the Sidewinder and Gravis GamePad Pro. Many apologies for my taking so long to merge in this code! Stefan Schimanski optimised the reverse blitting routine (for overlapping images). Added a shift+tab reverse focus movement key to the GUI routines. Grzegorz Adam Hankiewicz added a new example showing how to create and use a custom color mapping table. Totally revamped the joystick system (better API and new driver structure). Modified the fix class to work properly with gcc 2.8.0. Added a help.txt "how to get tech support" file. The midi_pos variable is now negated, rather than cleared to -1, at the end of a MIDI file. This can be used for measuring the length of a file. Added a rendering hook to the font structure, for use by text addon packages. Improved the VBE/AF text output routine. Corrected an error in the way the VBE/AF driver interprets hardware cursor colors. Pedro Cardoso contributed a tweaked 80x80 VGA mode. The VBE/AF driver now supports dumb framebuffer drivers as well as accelerated ones. Added more accelerator support to the VBE/AF driver (hardware cursors, lines, vertical lines, triangles, fixed width text output, and opaque/masked blitting from system memory to the screen). Added a scare_mouse() function, based on ideas by Martijn Versteegh. The grabber now stores the "grab from grid" dialog state in allegro.cfg. Sven Sandberg fixed a problem with save_bitmap() widths being rounded upwards. Made the _timer_installed flag globally visible. Ove Kaaven added linear framebuffer support to the native mach64 driver. Erik Sandberg optimised the 8 bit draw_sprite() and draw_trans_sprite() functions. Michal Mertl fixed a memory leak in the generate_optimized_palette() function. Added an ALLEGRO_DATE version define to allegro.h. Michael Bukin optimised the line drawing routine and fixed problem with the inline asm constraints for fadd()/fsub(). Fixed potential problems caused by a lag between the mouse state variables changing and the pointer being redrawn. Michal Mertl optimised the clipping code for lines, rectangles, and circles. Maiolino Carmelo contributed an Italian keyboard mapping. Fixed lockup problems caused by the keyboard LED functions on some platforms/hardware. Added new create_video_bitmap() and show_video_bitmap() functions. Added a profile option to the test program. The keyboard handler now correctly updates the BIOS state for the right control and alt keys when it shuts down. Fixed a problem that was preventing the DIGMID driver from reading patch sets stored in executable appended datafiles. Changed the default sample priority from 255 to 128. Fixed some problems with virtual screen sizes in the VBE/AF driver. Added two new example programs. The VBE/AF driver now has full support for hardware accelerated drawing. Added VBE 3.0 support, including new triple buffering routines. Wrote a routine to select the sound input source (microphone, line input or CD audio). Added proper support for stereo samples. This requires an extra parameter to the play_audio_stream() function, so you will need to change any programs that use this. I'm very sorry for breaking your old code! Fixed bugs with the SB16 autodetection and 16 bit sample recording. Added input support to the raw SB MIDI interface driver. Wrote a new test program to demonstrate the audio input features. Ove Kaaven added support for MIDI and audio (sampled sound) input. The pack_fopen() function now understands nested datafiles as directory structures, using filenames like "graphics.dat#level1/sprites/zdurgle". Charles Mac Donald showed me how to set a 160x120 VGA mode, and more reliable 400x* mode-X resolutions. Guilherme Silveira and Theuzifan Sumachingun both independently modified the file selector to only list valid drive letters. Carsten Sorensen added a driver for the ESS AudioDrive soundcard. Przemek Podsiadly added hicolor versions of the 3d polygon routines. Ove Kaaven added truecolor support to the native ATI mach64 driver. Patrick Hogan added a draw_gouraud_sprite() function. Ben Chauveau added a driver for Tseng ET6000 cards. Marco Campinoti added truecolor support to the native Tseng ET4000 driver. Marco Marmulla added 16 bit support to the load_voc() routine. Added Danish, Swedish, and Norwegian keyboard mappings. Added GUI hook functions for scaling or offsetting the mouse position. Fixed bug which was causing a lockup when calling set_leds(-1). Michael Bevin optimised the create_trans_table() function. It is now possible to display a mouse pointer without the mouse handler needing to be installed. Added a create_sample() function. Made the _blender_map pixel blending functions and the _mouse_installed, _keyboard_installed, and _sound_installed flags globally visible. Added an 8-button joystick mode. Chris La Mantia fixed a minor visual problem with the d_icon_proc(). Added a Rich Text Format (.rtf) version of the documentation. Added postfix increment and decrement operators to the C++ fix class, and the unary negation operator is now const-correct. ===================================================================== ============ Changes from 3.0 beta to release (Dec 1997) ============ ===================================================================== The pat2dat utility can now import instruments from AWE32 SoundFont files. Optimised the DIGMID patch loader and fixed a couple of bugs. Ove Kaaven fixed the ATI mach64 driver. The config file can now mention several possible video drivers, using lines in the form gfx_driver=x, gfx_driver2=x, etc. Improved the native SVGA driver helper functions, making it easier to add truecolor support to the register level drivers. Double-clicking on a font object in the grabber now allows you to view the extended characters as well as normal ASCII. Markus Oberhumer corrected a potential problem with the Video-7 initialisation code. Markus Oberhumer, Bitland, and Sormuras all sent me mapping tables for the German keyboard layout. Coordination of effort: who needs it? :-) Mathieu Lafon improved the French keyboard mapping. Fixed some bugs in the MIDI voice allocation system. Added a -k (keep names) option to the dat utility. The setup program now uses the ALLEGRO environment variable to locate the keyboard.dat file. Fixed a problem with < and > characters in the HTML documentation. ================================================================= ============ Changes from 2.2 to 3.0 beta (Nov 1997) ============ ================================================================= Merged in George's improved instrument parameters for the AWE32 driver. The pat2dat utility can now reduce sample data from 16 to 8 bits (saves space, and the DIGMID driver only uses 8 bits in any case). Added yet another version of the mouse handler, this time in an attempt to make it work more reliably under Windows NT. Frodo Baggins added a mapping table for Portuguese keyboards. Added an external tool "shell" function to the grabber. Added a "box grab" function to the grabber, which uses a color #255 bounding box to determine the extent of the sprite to grab. Santeri Saarimaa added a Finnish keyboard mapping. Finished writing the pat2dat utility, and the DIGMID driver is working a lot better now. Mathieu Lafon added support for the Pause and PrtScr keys, and changed the key[] array to a bitfield indicating whether either or both of the normal and extended versions of the key are pressed. This remains compatible with the "if (key[KEY_*])" syntax, but also allows you to distinguish between, for example, the Enter key on the numeric pad and the one next to the right shift key. Fixed a bug in the handling of config variables that don't belong to any section. The makefile now tries to detect and warn people about some of the more common installation errors. The HTML version of the documentation now uses a short .htm file extension if it is built on a system with LFN disabled. Keyboard mapping files now only bother saving the entries that differ from the default US mapping. This makes the maps a great deal smaller! Changed the default font and keyboard mapping tables from DOS codepage 437 to the standard ISO charset (first part of Unicode). If you have made a keyboard config using the old codepage it will need to be updated, but don't worry, I have a script that can do this very easily. Fixed a bug in the detection of font formats (fixed or proportional) when grabbing from a bitmap font. Added an editable loop point to the MIDI player (thanks to George for sorting out how to do this...) Rewrote the mouse handler to track the position itself, using only the mickey counters from the int 0x33 driver. Hopefully this will fix the problem with buggy Logitech drivers... Added a mouse_pos variable containing both the X and Y values in one 32 bit location, to allow a single instruction read during tight polling loops. The grabber now supports multiple selection, and has a new "ungrab" command that copies from a bitmap object into the scratch buffer (you can use this to generate palettes from truecolor images, or to re-grab a smaller area from the image). Added multiple selection abilities to the GUI listbox object. Theuzifan improved the cpu detection for Cyrix chips. Mathieu Lafon added a French keyboard mapping. Richard Mitton wrote an example program demonstrating how to fake a 12 bit truecolor display on an 8 bit card. Michal Mertl added a routine for generating optimised palettes for a specific truecolor image. Optimised the getr/g/b() functions. Converting between different color depths should be much faster now... Scott Harrison added code to detect OpenDOS, and use the i_love_bill mode if their version of EMM386 is in use. Added some new example programs. The makedoc utility now converts between the DOS and Windows extended character sets when producing HTML output files. Ettore Perazzoli made a spectacular optimisation to the linear -> mode-X blitting function. Added a grid option to the dat utility, to specify which region of a bitmap you want to grab. Fixed a bug in blitting truecolor bitmaps onto mode-X destinations. Fixed a bug that was preventing the Adlib volume from being changed when only MIDI sound drivers were installed. The grabber can now be run in video modes other than 640x480 (it doesn't look very nice in lower resolutions, though :-) Added a new fake scancode for the extended / key (the one on the numeric keypad) so that the two keys can be distinguished from each other. Joaquin Hierro Diaz made a mapping table for Spanish keyboards. The setup utility can now be used to select a keyboard layout and to calibrate the joystick, as well as for the sound hardware. Moved some of the documentation to different locations, so hopefully people will now be less likely to miss the faq.txt, and to bring it closer in line with the standard GNU distribution format. Better keyboard configuration system. There is now a proper utility for setting up the mapping tables, the tables can be read from external files, and it properly supports the alt-gr and accent escape keys. Menu items can now be disabled, have check marks next to them, and support right aligned text eg. for displaying keyboard shortcuts, there is a new "void *dp" field in the menu structure, and the click callback routines can now use the global pointer "active_menu" to determine which option they were called by, if a single routine is shared by several menu items. Peter Palotas added an input callback to the keyboard routines, and event flags to the mouse callback. Added a -pal option to the dat utility. Grzegorz Ludorowski made some new graphics for the demo game. Moved some code to new files and added a bunch of macros so you can remove unused graphics and sound drivers at link time. Fabian Nunez added support for the Logitech Wingman Extreme joystick. Chris La Mantia contributed a d_slider_proc() dialog object. Sean Gugler added a routine for changing the keyboard LED state. George Foot added pause and seek functions to the MIDI player. Added the ability to append datafiles (in fact any files at all) onto the end of your program executable. Merged in the AWE32 driver. Long live George! Can now read RLE compressed TGA files. Added a mouse movement callback function (useful for detecting double click events). Stefan Eilert added support for dual joysticks. Seymour Shlien contributed a routine for drawing justified text. Krzysztof Krzyzaniak contributed a loader for .VOC sample files. Added a rotate_scaled_sprite() function. Now supports the Dvorak keyboard layout. Salvador Eduardo Tropea added a 320x100 VGA mode. Implemented translucent and lit sprite and RLE sprite drawing functions for the truecolor modes. Updated the sound setup utility. The dat utility can now output makefile dependencies for automatically rebuilding the file when any of the source data changes. Fixed some problems with the RGB <-> HSV conversion functions. Truecolor image loading and grabber support. Phil Frisbie provided some code to detect the CPU type. Michal Mertl added 24 bit graphics modes. Hurrah! Added functions for playing streams of digital audio data. Chris La Mantia contributed a bitmap icon GUI object. Doug Eleveld added a text box GUI object, plus an improved help system for the grabber. Added support for UK and AZERTY keyboard layouts. More can easily be added if you send me the appropriate scancode -> ASCII mapping tables... Added get_align_matrix(), qtranslate_matrix(), and qscale_matrix() functions. Added a draw_character() function for using sprites as monochrome pixel masks. It is now safe to pass the same matrix as both input and output to the matrix_mul() function. Paul Bartrum contributed some ellipse drawing functions. Added some callbacks to the MIDI driver, allowing you to hook your own code into MIDI notes or marker events. Added a function to measure mouse movement in terms of mickeys (difference since the last call) as well as in absolute screen coordinates. VolkerOth made the d_edit_proc objects able to scroll, if the string is larger than the available space. Added the ability to distinguish between the left and right Control and Alt keys. Fabian Nunez added support for the extra keys on a Microsoft keyboard. Added void *dp2 and void *dp3 fields to the dialog structure. This ought not to break any existing code, but will let you store a lot more data when creating custom objects. The packfile functions can now directly open and read from datafile member objects, using fake filenames in the form "filename.dat#obj_name". This means that all the Allegro file access routines (eg. load_pcx() and set_config_file()) can now read from datafile objects as well as separate files. Added miditest and digitest programs to allow more rigorous testing of the sound routines and patch sets, and a vesainfo program to check which video modes are available on any given card. Jan Hubicka wrote a faster version of create_rgb_table(). The grabber now scales the bitmap preview if the image is too large to fit onto the screen. Jorrit Rouwe provided a new and much cooler set of FM instrument definitions for the Adlib MIDI driver. Added a function to load .IBK patch sets for use by the Adlib driver. Added a wrapper allegro/ directory around the contents of the zip file, so it can now be safely unzipped into the main djgpp directory. Richard Mitton added support for 6-button joysticks. Truecolor (15, 16, and 32 bit) graphics modes. Vastly improved sound routines (more flexible API, now supports up to 32 simultaneous voices on the SB, sample-based MIDI playback driver, can reverse samples, volume/pan/pitch sweep effects, MIDI commands can be output on the fly as well as played from MIDI files, and lots of other goodies). It is now possible to update the status of GUI dialogs incrementally from your own control loops, with an update_dialog() function, rather than completely transferring control to do_dialog(). Compressed files (including grabber datafiles) can now be encypted with a password. Added a masked_blit() function, that skips zero pixels. Added code to detect being run under Linux DOSEMU, and use the less demanding version of the timer code if this is the case. Added a standardised configuration mechanism. The format for saved joystick calibration information has changed, so existing joystick files are no longer valid. Added a textprintf() routine, which uses a printf() style format string. Added a TexInfo version of the documentation (thanks for the help, Francois!) Jonas Petersen added a save_bmp() function, and support for the OS/2 BMP format. ============================================================= ============ Changes from 2.11 to 2.2 (Feb 1997) ============ ============================================================= TBD/FeR added tweaked 320x600 and 360x600 resolutions to the mode-X driver. Matthew Bowie added support for 4-button joysticks. Dave Thomson added RGB <-> HSV conversion functions. Added a 'freeze_mouse_flag' variable, that can be used to lock the pointer to a specific position. Added a 'key_led_flag' variable, that can be used to prevent the keyboard LED's updating in response to the capslock, numlock, and scroll-lock keys. The midi player now resets midi_pos to -1 when the music finishes playing. Adrian Oboroc wrote an LBM loader. Fonts can now contain characters above ASCII 127. Chris Wigman made a better intro animation for the demo game. Added translucency, color blending, and lighting routines (based on code by Owen Embury and ideas by Nathan Albury). Added 3d math and matrix manipulation functions. Added texture mapped and gouraud shaded polygon drawers. Tim Gunn contributed code for reading and writing TGA files. Fixed clamping problems with rotating non-circular sprites. Added scrollbars to the GUI listbox object. Seymour Shlien wrote a bezier spline drawing function. Added fixed point fadd() and fsub() functions, which check for overflow. Added pack_fseek() and chunk manipulation functions to the file routines. Improved datafile structure and grabber program. Wrote a utility to convert grabber datafiles into linkable asm code. Salvador Eduardo Tropea improved the keyboard routines (better handling of extended scancodes, keyboard LED support, capslock and numlock, and alt+numpad input). Fixed the packfile functions and file selector to work with long filenames under win95. Seymour Shlien contributed a BMP reader. Added a hook function to the keyboard code, allowing you to use the GUI code without installing the keyboard handler. Fixed a lockup caused by trying to access non-existent floppy drives. Francois Charton wrote a driver for Paradise graphics cards. Chris La Mantia contributed a radio button GUI dialog object and added a D_DISABLED object flag. Markus F.X.J. Oberhumer fixed the Video-7 scrolling function. Converted the docs into HTML format. Added code to detect Windows NT. Mark Habersack added support for newer Trident chipsets. Did some more work on the VBE/AF driver (it now works, but still doesn't support accelerated hardware features). Fixed bugs in the WAV sample reader and FLIC player. Added special 'windows friendly' mode to the timer code. You can now even run demo.exe under Windows 3.1! Reorganised directory structure, to allow for a Linux version. The output liballeg.a is now found in lib/djgpp. Added support for 8x16 BIOS format fonts. Fixed a problem with overflow when rotating large sprites. Fixed a problem with restoring the text mode screen height after running Allegro programs. ============================================================= ============ Changes from 2.1 to 2.11 (Nov 1996) ============ ============================================================= Fixed bug in bank.S. install_mouse() now sets the range to (0,0,SCREEN_W,SCREEN_H). install_sound() does not automatically set the volume to maximum. Added ++ and -- operators to class fix. Makefile now copies liballeg.a to lib, and allegro.h to include. Made a few changes to work under LFN=y (if you use unzip or winzip instead of pkunzip). Added manifest. Clarified installation instructions. ============================================================= ============ Changes from 2.0 to 2.1 (June 1996) ============ ============================================================= Mode-X support (thanks to Jonathan Tarbox and Dominique Biesmans for suggesting and then helping to implement this). Compiled sprites. Jonathan Tarbox contributed an FLI/FLC player. Added patterned drawing modes. Added a vertical retrace interrupt simulator. polygon() can now handle concave and self-intersecting shapes. I also changed the parameters a bit. Sorry if this breaks your old code, but it's more efficient the new way... Added stretch_sprite(). Wrote a floodfill() routine. More flexible palette fade routines. Added set_volume() to the sound code. David Calvin wrote a sound setup utility. Improved the GUI. Added popup/dropdown menus, joystick input, three button alert boxes, better handling of arrow key focus movement, a new keyboard shortcut object (d_keyboard_proc()), and '&' markers in strings to display keyboard shortcuts. The GUI can also now be used with fonts other than the standard 8x8 default, by altering the global 'font' pointer. Fabian Nunez added support for the CH Flightstick Pro joystick (looks cool: I want one :-) and 3-button mice. The keyboard handler now responds to the state of the ctrl and alt keys, and there is a new simulate_keypress() function. Mark Wodrich added sub-bitmaps, which share their memory with a parent bitmap but can be positioned anywhere within it, and have their own clipping rectangles. Mark also modified the mouse driver to double-buffer the pointer (so it doesn't flicker any more), and added a set_mouse_sprite_focus() function. Added set_mouse_range() and set_mouse_speed() functions. Thanks (again) to Mark Wodrich, the grabber can now import GRX .FNT files. The grabber can now make backups when saving datafiles, and it only writes the datafile headers if their contents have changed, to prevent unnecessary recompilation. Added a text_height() function. The fixed point inverse sin and inverse cos functions now use lookup tables, which makes them a lot faster. Reorganised the directory structure, added some example programs, and improved the documentation. ======================================================================= ============ Changes from 2.0 beta to release (March 1996) ============ ======================================================================= Marcel de Kogel fixed some problems with the MPU-401 driver. It now actually works :-) Marcel also provided some better drum sounds for the Adlib driver. Inlined the fmul() and fdiv() functions. Much faster fsqrt(), taken from Arne Steinarson's fix-float library. Added inline bmp_write_line(), bmp_read_line(), and _putpixel() functions. The keyboard routines now support the emergency abort sequence ctrl+alt+del, and there are signal handlers to make sure Allegro will shut down cleanly if your program crashes. Wrote new irq wrappers that can deal with reentrant interrupts. Added joystick routines (based on code provided by Jonathan Tarbox and Marcel de Kogel). Moved some functions to different files and juggled things about so the linker can do a better job. If you don't use the sound stuff, or don't use any graphics functions, now they won't be linked into your executable. Marcel de Kogel manged to locate my (embarrassingly stupid :-) mistake which was preventing the VESA 2.0 linear framebuffer driver from working. Various other performance enhancements and bug fixes. ===================================================================== ============ Changes from 1.x to 2.0 beta (Jan/Feb 1996) ============ ===================================================================== Dropped all the Borland code. A couple of months ago I ran out of disk space, and it was with great satisfaction the I executed the command 'deltree /y c:\bc4'. It was a horrible compiler, and I'm glad it's dead. Added SVGA support. As a result it no longer makes sense for allegro_init() to put the system into mode 13h, so you will be in text mode until you call set_gfx_mode(). Added sound code (background MIDI music and sample mixing). Added support for proportional fonts (of any size) as well as the old 8x8 fixed size ones. XOR drawing mode. There is no longer such a thing as a SPRITE structure. The sprite drawing code now draws bitmaps onto other bitmaps, which is a much more flexible way of doing things. The datafile reader will convert all your old sprites to bitmaps as it loads them in, so the only practical difference this is likely to make is that the sprite drawing routines can't draw opaque sprites any more (but you can use a blit instead). show() and get_sprite() no longer exist: use blit() instead. Added flipped and rotated sprite draw routines. Added bitmap scaling. Added RLE sprites. drawsprite() has been renamed to draw_sprite(). textmode() has been renamed to text_mode(), to avoid conflicts with definitions in conio.h. All the file access functions have been renamed from the stdio syntax to pack_fopen(), pack_getc(), etc, so they can now be mixed with stdio code. Added pack_fgets() and pack_fputs(). The port_callback pointer no longer exists. Removed polyline() (who ever used it?), and added a polygon(), which draws a filled convex polygon with an arbitrary number of vertices. Added do_line() and do_circle() functions, which call a user-supplied function for each pixel that needs to be drawn. Added a default keyboard interface to the GUI routines, allowing the selection of objects with the arrow keys and . Added several new GUI messages and flags. In particular there are now messages for tracking mouse cursor movement, an idle message, a special return value for the MSG_CHAR message which allows an object to override the default keyboard handling, and a flag which hides the object. There are new GUI routines to centre a dialog on the screen and to alter the colors used by the standard alert and file selector dialogs. The file selector now takes a third parameter specifying which file extensions to display. The timer routines now have better than millisecond accuracy, and it is possible to alter the speed of a user timer callback in realtime (by reinstalling it with a different speed value). Removed the _RGB struct and paltorgb() functions. RGB's are now stored directly in the hardware format, with each value in the range 0-63. Added functions to get and set single palette entries as well as entire palettes. Added DPMI memory locking code. Wrote a C++ 'fix' class which overloads a lot of operators, providing an easy way to use the fixed point routines. There are probably lots of other things that I have forgotten about. allegro4.4-4.4.2/CMakeLists.txt000066400000000000000000000732401173507505700161540ustar00rootroot00000000000000# XXX build chm files # XXX build devhelp files # XXX resources (keyboard/language) - pretty useless except on DOS # XXX install grabber.txt? # XXX png plugin for grabber # XXX what is fixbundle? # XXX applehelp bundle? # XXX projectbuilder application template? # XXX allegro.m4? # Ports that used to work which aren't supported yet: # Haiku/BeOS port # djgpp port # QNX port # BCC32 # Watcom # DMC # PSP port? #-----------------------------------------------------------------------------# # # CMake setup # cmake_minimum_required(VERSION 2.6 FATAL_ERROR) if(COMMAND cmake_policy) cmake_policy(SET CMP0003 NEW) endif(COMMAND cmake_policy) if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel Profile." FORCE) endif() # Restrict configuration types to the selected build type. # Note: This needs to be done before the project command set(CMAKE_CONFIGURATION_TYPES "${CMAKE_BUILD_TYPE}" CACHE INTERNAL "internal") #-----------------------------------------------------------------------------# # # Build options # # Set the project name. project(ALLEGRO C CXX) if(WIN32) if(MINGW) # As of CMake 2.6.2, support for building .rc files with mingw seems to # be broken (uses wrong command line syntax) so we have to set this # variable manually. set(CMAKE_RC_COMPILE_OBJECT " -O coff -o -i ") if(NOT CMAKE_RC_COMPILER OR "${CMAKE_RC_COMPILER}" STREQUAL "") string(REGEX REPLACE "gcc(.exe)?$" "windres" GUESS_RC_COMPILER ${CMAKE_C_COMPILER}) find_program(CMAKE_RC_COMPILER ${GUESS_RC_COMPILER}) endif() endif(MINGW) enable_language(RC OPTIONAL) message(STATUS "CMAKE_RC_COMPILER: ${CMAKE_RC_COMPILER}") if(NOT CMAKE_RC_COMPILER) message(FATAL_ERROR "Please set CMAKE_RC_COMPILER manually, e.g. *-windres.") endif() endif(WIN32) set(ALLEGRO_VERSION 4.4.2) string(REGEX MATCH "^[0-9]+[.][0-9]+" ALLEGRO_SOVERSION ${ALLEGRO_VERSION}) # Mac OS X -compatibility_version. # XXX doesn't seem to work set(COMPAT_VERSION 4.4.0) set(ALLEGRO_DLL_SHORTVER 44) # Search in the `cmake' directory for additional CMake modules. list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake) # Search for C header files in these directories. include_directories(${CMAKE_SOURCE_DIR}/include) include_directories(${CMAKE_BINARY_DIR}/include) # Put libraries into `lib'. set(LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR}/lib) # Lists of all the source files. include(FileList) # Our own CMake macros and functions. include(Common) #-----------------------------------------------------------------------------# # # Build options # option(SHARED "Build shared library for main Allegro library" on) set(BUILD_SHARED_LIBS ${SHARED}) # actual CMake variable # On some 64-bit platforms, libraries should be installed into `lib64' # instead of `lib'. Set this to 64 to do that. set(LIB_SUFFIX "" CACHE STRING "Suffix for 'lib' directories, e.g. '64'") option(MAGIC_MAIN "Enable magic main (Unix)" off) option(WANT_FRAMEWORKS "Want frameworks on Mac OS X" off) option(WANT_EMBED "Make frameworks embeddable in application bundles (Mac OS X)" on) set(FRAMEWORK_INSTALL_PREFIX "/Library/Frameworks" CACHE STRING "Directory in which to install Mac OS X frameworks") #-----------------------------------------------------------------------------# # # Unix platform checks # include(CheckIncludeFiles) include(CheckFunctionExists) include(CheckCSourceCompiles) include(CheckCSourceRuns) include(FindPkgConfig) include(TestBigEndian) if(UNIX) test_big_endian(ALLEGRO_BIG_ENDIAN) if(NOT ALLEGRO_BIG_ENDIAN) set(ALLEGRO_LITTLE_ENDIAN 1) endif(NOT ALLEGRO_BIG_ENDIAN) check_include_files(dirent.h ALLEGRO_HAVE_DIRENT_H) check_include_files(inttypes.h ALLEGRO_HAVE_INTTYPES_H) check_include_files(linux/awe_voice.h ALLEGRO_HAVE_LINUX_AWE_VOICE_H) check_include_files(linux/input.h ALLEGRO_HAVE_LINUX_INPUT_H) # On some systems including linux/joystick.h without sys/types.h results # in conflicting definitions of fd_set. check_include_files("sys/types.h;linux/joystick.h" ALLEGRO_HAVE_LINUX_JOYSTICK_H) check_include_files(linux/soundcard.h ALLEGRO_HAVE_LINUX_SOUNDCARD_H) check_include_files(machine/soundcard.h ALLEGRO_HAVE_MACHINE_SOUNDCARD_H) check_include_files(soundcard.h ALLEGRO_HAVE_SOUNDCARD_H) check_include_files(stdint.h ALLEGRO_HAVE_STDINT_H) check_include_files(sys/io.h ALLEGRO_HAVE_SYS_IO_H) check_include_files(sys/stat.h ALLEGRO_HAVE_SYS_STAT_H) check_include_files(sys/time.h ALLEGRO_HAVE_SYS_TIME_H) check_include_files(sys/soundcard.h ALLEGRO_HAVE_SYS_SOUNDCARD_H) check_include_files(sys/utsname.h ALLEGRO_HAVE_SYS_UTSNAME_H) check_function_exists(getexecname ALLEGRO_HAVE_GETEXECNAME) check_function_exists(memcmp ALLEGRO_HAVE_MEMCMP) check_function_exists(mkstemp ALLEGRO_HAVE_MKSTEMP) check_function_exists(mmap ALLEGRO_HAVE_MMAP) check_function_exists(mprotect ALLEGRO_HAVE_MPROTECT) check_function_exists(sched_yield ALLEGRO_HAVE_SCHED_YIELD) check_function_exists(stricmp ALLEGRO_HAVE_STRICMP) check_function_exists(strlwr ALLEGRO_HAVE_STRLWR) check_function_exists(strupr ALLEGRO_HAVE_STRUPR) check_function_exists(sysconf ALLEGRO_HAVE_SYSCONF) check_c_source_compiles(" #include #include int main(void) { struct prpsinfo psinfo; ioctl(0, PIOCPSINFO, &psinfo); return 0; }" ALLEGRO_HAVE_SV_PROCFS_H ) check_c_source_compiles(" #include int main(void) { struct prpsinfo psinfo; psinfo.pr_argc = 0; return 0; }" ALLEGRO_HAVE_PROCFS_ARGCV ) check_c_source_compiles(" #include #include int main(void) { void *x = MAP_FAILED; }" MAP_FAILED_DEFINED) if(NOT MAP_FAILED_DEFINED) set(MAP_FAILED "((void *) -1)") endif() check_c_source_runs(" static int notsupported = 1; void test_ctor (void) __attribute__((constructor)); void test_ctor (void) { notsupported = 0; } int main(void) { return (notsupported); } " ALLEGRO_USE_CONSTRUCTOR) find_library(RT_LIBRARY rt) check_c_source_compiles(" #include int main(void) { struct timespec new_time_ns; clock_gettime(CLOCK_MONOTONIC, &new_time_ns); return 0; }" ALLEGRO_HAVE_POSIX_MONOTONIC_CLOCK ) if(MAGIC_MAIN) set(ALLEGRO_WITH_MAGIC_MAIN 1) endif(MAGIC_MAIN) # XXX const # XXX inline # XXX size_t endif(UNIX) #-----------------------------------------------------------------------------# # # Compiler and platform setup # option(STRICT_WARN "Halt at warnings" off) set(INSTALL_PREFIX "") if(CMAKE_COMPILER_IS_GNUCC) set(COMPILER_GCC 1) set(ALLEGRO_GCC 1) set(WFLAGS "-W -Wall -Wno-unused-parameter") set(WFLAGS_C_ONLY "-Wdeclaration-after-statement") if(STRICT_WARN) set(WFLAGS "${WFLAGS} -Werror -Wpointer-arith") set(WFLAGS_C_ONLY "${WFLAGS_C_ONLY} -Wmissing-declarations") set(WFLAGS_C_ONLY "${WFLAGS_C_ONLY} -Wstrict-prototypes") endif(STRICT_WARN) endif(CMAKE_COMPILER_IS_GNUCC) if(MINGW) set(ALLEGRO_MINGW32 1) # Guess MINGDIR from the value of CMAKE_C_COMPILER if it's not set. if("$ENV{MINGDIR}" STREQUAL "") string(REGEX REPLACE "/bin/[^/]*$" "" MINGDIR "${CMAKE_C_COMPILER}") message(STATUS "Guessed MinGW directory: ${MINGDIR}") else("$ENV{MINGDIR}" STREQUAL "") file(TO_CMAKE_PATH "$ENV{MINGDIR}" MINGDIR) message(STATUS "Using MINGDIR: ${MINGDIR}") endif("$ENV{MINGDIR}" STREQUAL "") # Search in MINGDIR for headers and libraries. set(CMAKE_PREFIX_PATH "${MINGDIR}") # Install to MINGDIR if(INSTALL_PREFIX STREQUAL "") set(CMAKE_INSTALL_PREFIX ${MINGDIR}) else(INSTALL_PREFIX STREQUAL "") set(CMAKE_INSTALL_PREFIX ${INSTALL_PREFIX}) endif(INSTALL_PREFIX STREQUAL "") message(STATUS "CMAKE_INSTALL_PREFIX: ${CMAKE_INSTALL_PREFIX}") endif(MINGW) if(MSVC) set(COMPILER_MSVC 1) set(ALLEGRO_MSVC 1) set(WFLAGS "/W3 -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE") endif(MSVC) if(WIN32) set(ALLEGRO_WINDOWS 1) endif() if(APPLE) set(ALLEGRO_MACOSX 1) set(ALLEGRO_DARWIN 1) # Hack to deal with Mac OS X 10.6. NSQuickDrawView is not defined by # NSQuickDrawView.h when compiling in 64-bit mode, and 64-bit mode is the # default when compiling on Snow Leopard. if(${CMAKE_SYSTEM_PROCESSOR} STREQUAL i386) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -arch i386") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -arch i386") endif() # The Mac port simply uses too many deprecated things. if(COMPILER_GCC) set(WFLAGS "${WFLAGS} -Wno-deprecated-declarations") endif(COMPILER_GCC) endif(APPLE) if(BEOS) if(CMAKE_SYSTEM_NAME STREQUAL Haiku) set(ALLEGRO_HAIKU 1) else(CMAKE_SYSTEM_NAME STREQUAL Haiku) set(ALLEGRO_BEOS 1) endif(CMAKE_SYSTEM_NAME STREQUAL Haiku) set(WFLAGS "-W -Wall -Wno-unused -Wno-multichar") set(WFLAGS_C_ONLY "") set(WFLAGS_CXX_ONLY "-Wno-ctor-dtor-privacy") endif(BEOS) if(UNIX AND NOT APPLE AND NOT BEOS) set(ALLEGRO_UNIX 1) endif() if(PSP) set(ALLEGRO_PSP 1) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -G0") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -G0 -fno-exceptions -fno-rtti") set(CMAKE_INSTALL_PREFIX ${PSP_PREFIX}) endif(PSP) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${WFLAGS} ${WFLAGS_C_ONLY}") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${WFLAGS} ${WFLAGS_CXX_ONLY}") if(NOT BUILD_SHARED_LIBS) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DALLEGRO_STATICLINK") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DALLEGRO_STATICLINK") endif() set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DDEBUGMODE=1") set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUGMODE=1") list(APPEND CMAKE_BUILD_TYPES Profile) mark_as_advanced( CMAKE_C_FLAGS_PROFILE CMAKE_CXX_FLAGS_PROFILE CMAKE_EXE_LINKER_FLAGS_PROFILE ) if(COMPILER_GCC) set(CMAKE_C_FLAGS_PROFILE "-pg" CACHE STRING "profiling flags") set(CMAKE_CXX_FLAGS_PROFILE "${CMAKE_C_FLAGS_PROFILE}" CACHE STRING "profiling flags") set(CMAKE_EXE_LINKER_FLAGS_PROFILE "-pg" CACHE STRING "profiling flags") set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "-pg" CACHE STRING "profiling flags") endif(COMPILER_GCC) if(COMPILER_MSVC) set(CMAKE_C_FLAGS_PROFILE "-Gd -Ox" CACHE STRING "profiling flags") set(CMAKE_CXX_FLAGS_PROFILE "${CMAKE_C_FLAGS_PROFILE}" CACHE STRING "profiling flags") set(CMAKE_EXE_LINKER_FLAGS_PROFILE "-profile" CACHE STRING "profiling flags") endif(COMPILER_MSVC) #-----------------------------------------------------------------------------# # Not sure if we want to support disabling these any more. set(ALLEGRO_COLOR8 1) set(ALLEGRO_COLOR16 1) set(ALLEGRO_COLOR24 1) set(ALLEGRO_COLOR32 1) set(ALLEGRO_NO_ASM 1) # ALLEGRO_MMX left undefined # ALLEGRO_SSE left undefined #-----------------------------------------------------------------------------# # # Unix modules # option(WANT_MODULES "Use modules for drivers (Unix)" on) if(WANT_MODULES AND ALLEGRO_UNIX) set(ALLEGRO_WITH_MODULES 1) set(ALLEGRO_MODULES_PATH ${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}/allegro/${ALLEGRO_VERSION}) install(FILES ${CMAKE_SOURCE_DIR}/modules.lst DESTINATION "${ALLEGRO_MODULES_PATH}" ) endif(WANT_MODULES AND ALLEGRO_UNIX) function(add_our_module nm files) if(ALLEGRO_WITH_MODULES) add_library(${nm} MODULE ${files}) set_target_properties(${nm} PROPERTIES PREFIX "" COMPILE_FLAGS -DALLEGRO_MODULE ) target_link_libraries(${nm} ${ARGN}) install(TARGETS ${nm} DESTINATION "${ALLEGRO_MODULES_PATH}" ) endif(ALLEGRO_WITH_MODULES) endfunction(add_our_module) #-----------------------------------------------------------------------------# # # Platform drivers # set(PLATFORM_SOURCES) set(PLATFORM_LIBS) # always link with these libraries set(PLATFORM_LIBS_NON_MODULES) # only link with these if modules disabled set(PLATFORM_LIBS_MODULES) # only link with these if modules enabled # -- Unix -- option(WANT_OSS "Build OSS support" on) option(WANT_ALSA "Build ALSA support" on) option(WANT_JACK "Build JACK support" on) option(WANT_SGIAUDIO "Build SGI audio support" on) if(ALLEGRO_UNIX) # not MACOSX find_package(Threads) if(NOT CMAKE_USE_PTHREADS_INIT) message(FATAL_ERROR "Unix port requires pthreads support.") endif() set(ALLEGRO_HAVE_LIBPTHREAD 1) list(APPEND PLATFORM_LIBS m ${CMAKE_THREAD_LIBS_INIT}) list(APPEND PLATFORM_SOURCES ${ALLEGRO_SRC_UNIX_FILES}) find_library(DLOPEN_LIBRARY dl) mark_as_advanced(DLOPEN_LIBRARY) if(DLOPEN_LIBRARY) list(APPEND PLATFORM_LIBS_MODULES ${DLOPEN_LIBRARY}) endif() if(ALLEGRO_HAVE_POSIX_MONOTONIC_CLOCK) list(APPEND PLATFORM_LIBS ${RT_LIBRARY}) endif(ALLEGRO_HAVE_POSIX_MONOTONIC_CLOCK) if(WANT_OSS) include(AllegroFindOSS) if(OSS_FOUND) set(ALLEGRO_WITH_OSSDIGI 1) set(ALLEGRO_WITH_OSSMIDI 1) include_directories(SYSTEM ${OSS_INCLUDE_DIR}) endif(OSS_FOUND) endif(WANT_OSS) if(WANT_ALSA) pkg_check_modules(ALSA alsa) if(ALSA_FOUND) # ALSA 0.5 is beyond obsolete. set(ALLEGRO_ALSA_VERSION 9) set(ALLEGRO_WITH_ALSADIGI 1) set(ALLEGRO_WITH_ALSAMIDI 1) include_directories(SYSTEM ${ALSA_INCLUDE_DIRS}) list(APPEND PLATFORM_LIBS_NON_MODULES ${ALSA_LIBRARIES}) add_our_module(alleg-alsadigi src/unix/alsa9.c ${ALSA_LIBRARIES}) add_our_module(alleg-alsamidi src/unix/alsamidi.c ${ALSA_LIBRARIES}) endif(ALSA_FOUND) endif(WANT_ALSA) if(WANT_JACK) pkg_check_modules(JACK jack) if(JACK_FOUND) set(ALLEGRO_WITH_JACKDIGI 1) include_directories(SYSTEM ${JACK_INCLUDE_DIRS}) list(APPEND PLATFORM_LIBS_NON_MODULES ${JACK_LIBRARIES}) add_our_module(alleg-jack src/unix/jack.c ${JACK_LIBRARIES}) endif(JACK_FOUND) endif(WANT_JACK) # This is untested. if(WANT_SGIAUDIO) check_library_exists(audio alOpenPort "" SGIAUDIO_FOUND) if(SGIAUDIO_FOUND) set(ALLEGRO_WITH_SGIALDIGI 1) list(APPEND PLATFORM_LIBS_NON_MODULES audio) add_our_module(alleg-sgialdigi src/unix/sgial.c audio) endif(SGIAUDIO_FOUND) endif(WANT_SGIAUDIO) # aRts is obsolete # esd is obsolete endif(ALLEGRO_UNIX) # -- X11 -- option(WANT_X11 "Want X11 support (Unix)" on) if(ALLEGRO_UNIX AND WANT_X11) find_package(X11) if(X11_FOUND) set(ALLEGRO_WITH_XWINDOWS 1) endif() endif() if(ALLEGRO_WITH_XWINDOWS) include_directories(SYSTEM ${X11_INCLUDE_DIR}) list(APPEND PLATFORM_SOURCES ${ALLEGRO_SRC_X_FILES}) list(APPEND PLATFORM_LIBS ${X11_LIBRARIES}) if(X11_XShm_FOUND) set(ALLEGRO_XWINDOWS_WITH_SHM 1) list(APPEND PLATFORM_LIBS ${X11_Xext_LIB}) endif() if(X11_Xcursor_FOUND) set(ALLEGRO_XWINDOWS_WITH_XCURSOR 1) list(APPEND PLATFORM_LIBS ${X11_Xcursor_LIB}) endif() if(X11_Xcursor_FOUND) set(ALLEGRO_XWINDOWS_WITH_XCURSOR 1) list(APPEND PLATFORM_LIBS ${X11_Xcursor_LIB}) endif() if(X11_Xpm_FOUND) set(ALLEGRO_XWINDOWS_WITH_XPM 1) list(APPEND PLATFORM_LIBS ${X11_Xpm_LIB}) endif() find_library(X11_Xxf86vm_LIB Xxf86vm ${X11_LIB_SEARCH_PATH}) mark_as_advanced(X11_Xxf86vm_LIB) if(X11_xf86vmode_FOUND) set(ALLEGRO_XWINDOWS_WITH_XF86VIDMODE 1) list(APPEND PLATFORM_LIBS ${X11_Xxf86vm_LIB}) endif() check_library_exists(X11 XOpenIM "${X11_LIB_SEARCH_PATH}" XIM_FOUND) if(XIM_FOUND) set(ALLEGRO_XWINDOWS_WITH_XIM 1) endif(XIM_FOUND) check_library_exists(Xxf86dga XDGAQueryExtension "${X11_LIB_SEARCH_PATH}" XDGA_FOUND) if(XDGA_FOUND) set(ALLEGRO_XWINDOWS_WITH_XF86DGA2 1) list(APPEND PLATFORM_LIBS_NON_MODULES Xxf86dga ${X11_LIBRARIES}) add_our_module(alleg-dga2 src/x/xdga2.c Xxf86dga ${X11_LIBRARIES}) endif() endif(ALLEGRO_WITH_XWINDOWS) # -- Linux console -- option(WANT_LINUX_CONSOLE "Want Linux console support (Linux)" off) option(WANT_LINUX_VGA "Want Linux console VGA driver (Linux)" on) option(WANT_LINUX_FBCON "Want Linux console fbcon driver (Linux)" on) option(WANT_LINUX_SVGALIB "Want Linux console SVGAlib driver (Linux)" on) if(WANT_LINUX_CONSOLE AND CMAKE_SYSTEM_NAME STREQUAL Linux) set(ALLEGRO_LINUX 1) list(APPEND PLATFORM_SOURCES ${ALLEGRO_SRC_LINUX_FILES}) if(WANT_LINUX_VGA) set(ALLEGRO_LINUX_VGA 1) add_our_module(alleg-vga src/misc/vga.c) endif() if(WANT_LINUX_FBCON) check_c_source_compiles(" #include int main(void) { int x = FB_SYNC_ON_GREEN; return 0; }" CAN_FBCON) if(CAN_FBCON) set(ALLEGRO_LINUX_FBCON 1) add_our_module(alleg-fbcon src/linux/fbcon.c) endif() endif() if(WANT_LINUX_SVGALIB) find_package(Svgalib) if(SVGALIB_FOUND) set(ALLEGRO_LINUX_SVGALIB 1) include_directories(SYSTEM ${SVGALIB_INCLUDE_DIR}) set(CMAKE_REQUIRED_LIBRARIES ${SVGALIB_LIBRARY}) check_c_source_compiles(" #include int main(void) { int x = vga_version; return 0; }" ALLEGRO_LINUX_SVGALIB_HAVE_VGA_VERSION) list(APPEND PLATFORM_LIBS_NON_MODULES ${SVGALIB_LIBRARY}) add_our_module(alleg-svgalib src/linux/svgalib.c ${SVGALIB_LIBRARY}) endif() endif() endif(WANT_LINUX_CONSOLE AND CMAKE_SYSTEM_NAME STREQUAL Linux) # -- Windows -- if(WIN32) find_package(DDraw) find_package(DInput) find_package(DSound) find_package(DXGuid) if(NOT DDRAW_FOUND OR NOT DINPUT_FOUND OR NOT DSOUND_FOUND OR NOT DXGUID_FOUND) if(MSVC) message(FATAL_ERROR "DirectX required for Windows port. You might need to add DirectX include and lib directories to your INCLUDE and LIB environment variables. ") elseif(MINGW) message(FATAL_ERROR "DirectX required for Windows port. Get it from the Allegro web site (dx80_mgw.zip).") else() message(FATAL_ERROR "DirectX required for Windows port.") endif() endif() include_directories(SYSTEM ${DDRAW_INCLUDE_DIR} ${DINPUT_INCLUDE_DIR} ${DSOUND_INCLUDE_DIR} ${DXGUID_INCLUDE_DIR} ) list(APPEND PLATFORM_SOURCES ${ALLEGRO_SRC_WIN_FILES}) list(APPEND PLATFORM_LIBS kernel32 user32 gdi32 comdlg32 ole32 ${DINPUT_LIBRARIES} ${DDRAW_LIBRARIES} ${DXGUID_LIBRARIES} winmm ${DSOUND_LIBRARIES} ) endif(WIN32) # -- Haiku/BeOS -- if(BEOS) list(APPEND PLATFORM_SOURCES ${ALLEGRO_SRC_BEOS_FILES}) list(APPEND PLATFORM_LIBS game midi device) endif(BEOS) # -- Mac OS X -- if(ALLEGRO_MACOSX) list(APPEND PLATFORM_SOURCES ${ALLEGRO_SRC_MACOSX_FILES}) if(NOT SHARED) list(APPEND PLATFORM_SOURCES src/macosx/main.m) endif(NOT SHARED) find_library(COCOA_LIBRARY Cocoa) find_library(CARBON_LIBRARY Carbon) find_library(IOKIT_LIBRARY IOKit) find_library(COREAUDIO_LIBRARY CoreAudio) find_library(AUDIOUNIT_LIBRARY AudioUnit) find_library(AUDIOTOOLBOX_LIBRARY AudioToolbox) find_package(QuickTime) mark_as_advanced(COCOA_LIBRARY CARBON_LIBRARY IOKIT_LIBRARY) mark_as_advanced(COREAUDIO_LIBRARY AUDIOUNIT_LIBRARY AUDIOTOOLBOX_LIBRARY) mark_as_advanced(QUICKTIME_INCLUDE_DIR QUICKTIME_LIBRARY) list(APPEND PLATFORM_LIBS ${COCOA_LIBRARY} ${CARBON_LIBRARY} ${IOKIT_LIBRARY} ${COREAUDIO_LIBRARY} ${AUDIOUNIT_LIBRARY} ${AUDIOTOOLBOX_LIBRARY} ${QUICKTIME_LIBRARY} ) endif(ALLEGRO_MACOSX) # -- PSP -- if(PSP) include_directories(SYSTEM ${PSPSDK_PATH}/include) link_directories(${PSPSDK_PATH}/lib) list(APPEND PLATFORM_SOURCES ${ALLEGRO_SRC_PSP_FILES}) list(APPEND PLATFORM_LIBS m pspaudio pspgu psprtc pspdebug pspdisplay pspge pspctrl pspsdk c pspnet pspnet_inet pspnet_resolver psputility pspuser pspkernel) endif(PSP) #-----------------------------------------------------------------------------# # # Generate and install headers # set(ALLEGRO_PUBLIC_HEADERS) macro(add_headers location) list(APPEND ALLEGRO_PUBLIC_HEADERS ${ARGN}) # We reuse MACOSX_PACKAGE_LOCATION on non-Mac platforms as well. set_source_files_properties(${ARGN} PROPERTIES MACOSX_PACKAGE_LOCATION Headers/${location} ) endmacro(add_headers) configure_file( ${CMAKE_SOURCE_DIR}/include/allegro/platform/alplatf.h.cmake ${CMAKE_BINARY_DIR}/include/allegro/platform/alplatf.h @ONLY ) add_headers(allegro/platform ${CMAKE_BINARY_DIR}/include/allegro/platform/alplatf.h ) if(UNIX) configure_file( ${CMAKE_SOURCE_DIR}/include/allegro/platform/alunixac.h.cmake ${CMAKE_BINARY_DIR}/include/allegro/platform/alunixac.h ) add_headers(allegro/platform ${CMAKE_BINARY_DIR}/include/allegro/platform/alunixac.h ) endif(UNIX) add_headers("" include/allegro.h) add_headers(allegro ${ALLEGRO_INCLUDE_ALLEGRO_FILES}) add_headers(allegro/inline ${ALLEGRO_INCLUDE_ALLEGRO_INLINE_FILES}) add_headers(allegro/internal ${ALLEGRO_INCLUDE_ALLEGRO_INTERNAL_FILES}) add_headers(allegro/platform ${ALLEGRO_INCLUDE_ALLEGRO_PLATFORM_FILES}) # Platform-specific top-level headers. if(ALLEGRO_LINUX) add_headers("" include/linalleg.h) endif(ALLEGRO_LINUX) if(APPLE) add_headers("" include/osxalleg.h) endif(APPLE) if(WIN32) add_headers("" include/winalleg.h) endif(WIN32) if(ALLEGRO_WITH_XWINDOWS) add_headers("" include/xalleg.h) endif(ALLEGRO_WITH_XWINDOWS) if(BEOS) add_headers("" include/bealleg.h) endif(BEOS) #-----------------------------------------------------------------------------# # # Main library # # On Unix/Mac we don't ever use a -static postfix. if(CMAKE_BUILD_TYPE STREQUAL Debug) set(BUILD_TYPE_SUFFIX -debug) elseif(CMAKE_BUILD_TYPE STREQUAL Profile) set(BUILD_TYPE_SUFFIX -profile) else() set(BUILD_TYPE_SUFFIX "") endif() if(ALLEGRO_MODULES_PATH) set(ALLEGRO_MODULES_PATH_FLAG "-DALLEGRO_MODULES_PATH='\"${ALLEGRO_MODULES_PATH}\"'") endif(ALLEGRO_MODULES_PATH) if(APPLE) # CMake 2.6.2 onwards passes these flags automatically. if(${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} STREQUAL 2.6 AND ${CMAKE_PATCH_VERSION} LESS 2) set(ALLEGRO_LINK_FLAGS "-compatibility_version ${COMPAT_VERSION} -current_version ${ALLEGRO_VERSION}") endif() endif(APPLE) add_our_library(allegro ${ALLEGRO_SRC_FILES} ${ALLEGRO_SRC_C_FILES} ${PLATFORM_SOURCES} ${ALLEGRO_PUBLIC_HEADERS} ) if(WIN32 AND SHARED) set(allegro_OUTPUT_NAME alleg${ALLEGRO_DLL_SHORTVER}) else() set(allegro_OUTPUT_NAME alleg) endif() set_target_properties(allegro PROPERTIES COMPILE_FLAGS "-DALLEGRO_SRC ${ALLEGRO_MODULES_PATH_FLAG}" LINK_FLAGS "${ALLEGRO_LINK_FLAGS}" OUTPUT_NAME ${allegro_OUTPUT_NAME} VERSION ${ALLEGRO_VERSION} SOVERSION ${ALLEGRO_SOVERSION} ) if(WIN32) if(SHARED) # Make mingw not add lib prefix to DLL, to match MSVC. set_target_properties(allegro PROPERTIES PREFIX "" ) else(SHARED) # Add a -static postfix on the main library for Windows. # In earlier versions of Allegro this was "_s". set_target_properties(allegro PROPERTIES POSTFIX "-static" DEBUG_POSTFIX "-debug-static" PROFILE_POSTFIX "-profile-static" ) endif(SHARED) endif(WIN32) set_our_framework_properties(allegro Allegro) set(link_with ${PLATFORM_LIBS}) if(ALLEGRO_WITH_MODULES) list(APPEND link_with ${PLATFORM_LIBS_MODULES}) else() list(APPEND link_with ${PLATFORM_LIBS_NON_MODULES}) endif() target_link_libraries(allegro ${link_with}) sanitize_cmake_link_flags(static_link_with ${link_with}) set_target_properties(allegro PROPERTIES static_link_with "${static_link_with}" ) install_our_library(allegro) if(NOT WANT_FRAMEWORKS) install_our_headers(${ALLEGRO_PUBLIC_HEADERS}) endif(NOT WANT_FRAMEWORKS) if(APPLE AND SHARED OR WANT_FRAMEWORKS) add_our_library(alleg-main STATIC src/macosx/main.m ) set_target_properties(alleg-main PROPERTIES OUTPUT_NAME alleg-main${BUILD_TYPE_SUFFIX} COMPILE_FLAGS -DALLEGRO_SRC ) target_link_libraries(allegro alleg-main) install_our_library(alleg-main) endif(APPLE AND SHARED OR WANT_FRAMEWORKS) if(PSP) add_our_library(alleg-main STATIC src/psp/pmain.c ) set_target_properties(alleg-main PROPERTIES OUTPUT_NAME alleg-main${BUILD_TYPE_SUFFIX} COMPILE_FLAGS -DALLEGRO_SRC ) target_link_libraries(alleg-main pspuser pspkernel) target_link_libraries(allegro alleg-main) install_our_library(alleg-main) endif(PSP) #-----------------------------------------------------------------------------# # # allegro-config script # if(UNIX) # including MACOSX set(prefix "${CMAKE_INSTALL_PREFIX}") set(INCLUDE_PREFIX "${CMAKE_INSTALL_PREFIX}") # not sure what this is if(BUILD_SHARED_LIBS) set(LINK_WITH_STATIC_LIBS no) else() set(LINK_WITH_STATIC_LIBS yes) endif() set(LIB_TO_LINK alleg${BUILD_TYPE_SUFFIX}) if(APPLE) set(LDFLAGS "-framework Cocoa -lalleg-main") else(APPLE) set(LDFLAGS "") endif(APPLE) sanitize_cmake_link_flags(LIBS ${PLATFORM_LIBS} ${PLATFORM_LIBS_NON_MODULES} ${PLATFORM_LIBS_MODULES} ) if(APPLE) # XXX untested set(ACCEPT_FRAMEWORKS yes) if(BUILD_SHARED_LIBS) set(FRAMEWORKS "-framework Cocoa -framework Allegro -lalleg-main${BUILD_TYPE_SUFFIX}") else(BUILD_SHARED_LIBS) set(FRAMEWORKS "-framework Cocoa -framework Allegro -lalleg-main${BUILD_TYPE_SUFFIX} -framework Carbon -framework IOKit -framework System -framework CoreAudio -framework AudioUnit -framework AudioToolbox -framework QuickTime") endif(BUILD_SHARED_LIBS) else() set(ACCEPT_FRAMEWORKS no) set(FRAMEWORKS "") endif() configure_file( ${CMAKE_SOURCE_DIR}/misc/allegro-config.in ${CMAKE_BINARY_DIR}/allegro-config @ONLY ) install(PROGRAMS ${CMAKE_BINARY_DIR}/allegro-config DESTINATION bin ) endif(UNIX) #-----------------------------------------------------------------------------# # # Addons # option(WANT_ALLEGROGL "Enable AllegroGL" on) option(WANT_LOADPNG "Enable loadpng" on) option(WANT_LOGG "Enable logg" on) option(WANT_JPGALLEG "Enable JPGAlleg" on) if(WANT_FRAMEWORKS) set(ADDON_LINKAGE SHARED) else() set(ADDON_LINKAGE STATIC) endif() if(WANT_ALLEGROGL) add_subdirectory(addons/allegrogl) endif() if(WANT_LOADPNG) add_subdirectory(addons/loadpng) endif() if(WANT_LOGG) add_subdirectory(addons/logg) endif() if(WANT_JPGALLEG) add_subdirectory(addons/jpgalleg) endif() #-----------------------------------------------------------------------------# # # pkg-config files - after addons to get properties # set(PKG_CONFIG_FILES allegro allegrogl jpgalleg loadpng logg ) if(UNIX) set(prefix "${CMAKE_INSTALL_PREFIX}") set(INCLUDE_PREFIX "\${prefix}") set(bindir "\${exec_prefix}/bin") set(includedir "\${prefix}/include") set(libdir "\${exec_prefix}/lib${LIB_SUFFIX}") set(lib_type "${BUILD_TYPE_SUFFIX}") # We only use -static suffixes on Windows, for the main library. set(lib_linkage "") foreach(name ${PKG_CONFIG_FILES}) set(target ${name}) # For static linking: get extra libraries to link with. get_target_property(link_with ${target} static_link_with) configure_file( misc/${name}.pc.in ${LIBRARY_OUTPUT_PATH}/pkgconfig/${name}${lib_type}.pc @ONLY ) install(FILES ${LIBRARY_OUTPUT_PATH}/pkgconfig/${name}${lib_type}.pc DESTINATION "lib${LIB_SUFFIX}/pkgconfig" ) endforeach(name) endif(UNIX) #-----------------------------------------------------------------------------# # # Documentation # add_subdirectory(docs) #-----------------------------------------------------------------------------# # # Samples - after addons because skater can use AllegroGL # option(WANT_EXAMPLES "Build example programs" on) if(WANT_EXAMPLES) add_subdirectory(examples) add_subdirectory(demos/shooter) add_subdirectory(demos/skater) endif(WANT_EXAMPLES) #-----------------------------------------------------------------------------# # # Tools - after addons because of grabber plugins # option(WANT_TOOLS "Build tool programs" on) if(WANT_TOOLS) add_subdirectory(tools) # Note to packagers: setup is mostly a historical footnote on modern # operating systems. Do not feel the need to package it. add_subdirectory(setup) endif(WANT_TOOLS) #-----------------------------------------------------------------------------# # # Tests # option(WANT_TESTS "Build test programs" on) if(WANT_TESTS) add_subdirectory(tests) endif(WANT_TESTS) #-----------------------------------------------------------------------------# # vim: set sts=4 sw=4 et: allegro4.4-4.4.2/THANKS000066400000000000000000000075161173507505700143320ustar00rootroot00000000000000 ================================= ============ Thanks! ============ ================================= First, a big thank you to all the people who help me test and debug this code. It sometimes gets frustrating to receive hundreds of messages saying "it doesn't work!", but they are useful all the same... Andre Baresel (baresel at informatik dot hu-berlin dot de), and Craig Jackson (Craig dot Jackson at launchpad dot unc dot edu), provided a tremendous amount of information about SB hardware. Benji York (Benji at cookeville dot com). Provided hardware information for the Gravis GamePad Pro. Charles Mac Donald (cgfm2 at hooked dot net). Showed me how to set some cool tweaked VGA and mode-X resolutions. Charles Sandmann (sandmann at clio dot rice dot edu), DJ Delorie (dj at delorie dot com), Eli Zaretskii (eliz at is dot elta dot co dot il), and everyone else who has contributed to djgpp. I love it. C. Schwerdtfeger (schwerdt at physics dot ubc dot ca), for his help (and enourmous patience!) in getting the SB Pro-I MIDI driver to work. Finn Thoegersen, Nordbanevej 3 C, DK-7800 Skive, Denmark. Most of my SVGA hardware information came from his VGADOC package. Eric Jorgensen (smeagol at rt66 dot com). Varmint's Audio Tools (VAT) gave me many useful ideas about how to play MIDI files. Jamie O'Connell (JamieOConnell at msn dot com). Several of the new Adlib drum patches, and the specifications for the .IBK file format, came from his SBTimbre package. Jean-Paul Mikkers (mikmak at stack dot urc dot tue dot nl). MikMod was the source of a lot of information about programming the SB, and also gave me the idea of dynamically reprogramming the PIT to get a really high resolution timer. Joel H. Hunter (jhunter at kendaco dot telebyte dot com). His SB library for djgpp is excellent, and helped me a lot. John Pollard (74723 dot 1626 at compuserve dot com). The FM instrument definitions are based on his MID-KIT library. Kendall Bennett and all the other cool people at SciTech Software. These guys gave the world UniVBE, the VBE/AF API, and a lot of free information and example code. Plus they very kindly sent me a copy of the VBE/AF spec when I wanted one. Kris Heidenstrom (kheidens at actrix dot gen dot nz). His PC timing FAQ was a big help. Mark Feldman. It goes without saying that the PCGPE was an invaluable resource. Michael Abrash. You just gotta love that man... Paul Fenwick (bg914 at freenet dot carleton dot ca). Various bits of the mode-X code (notably the split screen stuff) came from his XLIBDJ library. powerjaw (powerjaw at dnai dot com). Sent me a Sidewinder gamepad so I could fix some problems with the driver for it. What a cool thing to do... Robert Grubbs (rwgrubbs at vt dot edu). Provided hardware information for the Sidewinder joypad. Robert Schmidt (robert at stud dot unit dot no). The register values for the 400x* mode-X resolutions came from his TWEAK program. Sourceforge.net (http://sourceforge.net/). The Allegro community has been using their services (web, mailing lists, CVS, Subversion, etc) since 3.9.x WIP versions. Tom Grandgent (tgrand at canvaslink dot com). Organised and hosted the original Allegro mailing lists for many years. Hurrah! Vladimir Arnost (xarnos00 at dcse dot fee dot vutbr dot cz). Provided hardware specs for the OPL3 chip. Frank Zappa, Mike Keneally, Pink Floyd, the Doors, Tori Amos, and all the other great musicians who provide me with things to listen to while I am programming. My parents, John and Nancy. I would never have made it through all those late night coding sessions without the cafetiere they gave me last Christmas :-) By Shawn Hargreaves, Allegro creator. allegro4.4-4.4.2/addons/000077500000000000000000000000001173507505700146565ustar00rootroot00000000000000allegro4.4-4.4.2/addons/allegrogl/000077500000000000000000000000001173507505700166265ustar00rootroot00000000000000allegro4.4-4.4.2/addons/allegrogl/CMakeLists.txt000066400000000000000000000131011173507505700213620ustar00rootroot00000000000000#-----------------------------------------------------------------------------# # # AllegroGL # find_package(OpenGL) if(NOT OPENGL_FOUND) return() endif() if(UNIX AND NOT APPLE) find_package(X11) if(NOT X11_FOUND) return() endif() set(GLX 1) endif() if(ALLEGRO_XWINDOWS_WITH_XF86VIDMODE) set(ALLEGROGL_HAVE_XF86VIDMODE 1) endif() find_library(DLOPEN_LIB dl) mark_as_advanced(DLOPEN_LIB) if(DLOPEN_LIB) set(ALLEGROGL_HAVE_DYNAMIC_LINK 1) endif() if(ALLEGRO_WITH_XWINDOWS) set(CMAKE_REQUIRED_LIBRARIES ${OPENGL_gl_LIBRARY}) check_function_exists(glXGetProcAddress GLXGETPROCADDRESS_FOUND) if(NOT GLXGETPROCADDRESS_FOUND) check_function_exists(glXGetProcAddressARB GLXGETPROCADDRESSARB_FOUND) if(GLXGETPROCADDRESSARB_FOUND) set(ALLEGROGL_GLXGETPROCADDRESSARB 1) else() message(FATAL_ERROR "OpenGL does not export symbol glXGetProcAddress[ARB]") endif() endif() set(CMAKE_REQUIRED_LIBRARIES) endif(ALLEGRO_WITH_XWINDOWS) # XXX Mesa generic driver support? configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/include/allegrogl/alleggl_config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/include/allegrogl/alleggl_config.h @ONLY ) include_directories(SYSTEM ${OPENGL_INCLUDE_DIR}) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include) include_directories(${CMAKE_CURRENT_BINARY_DIR}/include) #-----------------------------------------------------------------------------# set(ALLEGROGL_SOURCES src/alleggl.c src/glvtable.c src/scorer.c src/math.c src/aglf.c src/fontconv.c src/texture.c src/glext.c src/gui.c src/videovtb.c ) if(WIN32) list(APPEND ALLEGROGL_SOURCES src/win.c) endif() if(DJGPP) list(APPEND ALLEGROGL_SOURCES src/djgpp.c) endif() if(APPLE) list(APPEND ALLEGROGL_SOURCES src/macosx.m) endif() if(GLX) list(APPEND ALLEGROGL_SOURCES src/x.c) endif() set(ALLEGROGL_HEADERS include/alleggl.h include/allegrogl/gl_ext.h include/allegrogl/gl_header_detect.h ${CMAKE_CURRENT_BINARY_DIR}/include/allegrogl/alleggl_config.h include/allegrogl/GLext/glx_ext_alias.h include/allegrogl/GLext/glx_ext_api.h include/allegrogl/GLext/glx_ext_defs.h include/allegrogl/GLext/glx_ext_list.h include/allegrogl/GLext/gl_ext_alias.h include/allegrogl/GLext/gl_ext_api.h include/allegrogl/GLext/gl_ext_defs.h include/allegrogl/GLext/gl_ext_list.h include/allegrogl/GLext/wgl_ext_alias.h include/allegrogl/GLext/wgl_ext_api.h include/allegrogl/GLext/wgl_ext_defs.h include/allegrogl/GLext/wgl_ext_list.h ) set_source_files_properties( include/alleggl.h PROPERTIES MACOSX_PACKAGE_LOCATION Headers ) set_source_files_properties( include/allegrogl/gl_ext.h include/allegrogl/gl_header_detect.h ${CMAKE_CURRENT_BINARY_DIR}/include/allegrogl/alleggl_config.h PROPERTIES MACOSX_PACKAGE_LOCATION Headers/allegrogl ) set_source_files_properties( include/allegrogl/GLext/glx_ext_alias.h include/allegrogl/GLext/glx_ext_api.h include/allegrogl/GLext/glx_ext_defs.h include/allegrogl/GLext/glx_ext_list.h include/allegrogl/GLext/gl_ext_alias.h include/allegrogl/GLext/gl_ext_api.h include/allegrogl/GLext/gl_ext_defs.h include/allegrogl/GLext/gl_ext_list.h include/allegrogl/GLext/wgl_ext_alias.h include/allegrogl/GLext/wgl_ext_api.h include/allegrogl/GLext/wgl_ext_defs.h include/allegrogl/GLext/wgl_ext_list.h PROPERTIES MACOSX_PACKAGE_LOCATION Headers/allegrogl/GLext ) # XXX Maybe AllegroGL should be optionally dynamic? add_our_library(allegrogl ${ADDON_LINKAGE} ${ALLEGROGL_SOURCES} ${ALLEGROGL_HEADERS} ) set_target_properties(allegrogl PROPERTIES COMPILE_FLAGS -DALLEGRO_GL_SRC_BUILD LINK_FLAGS "${ALLEGRO_LINK_FLAGS}" OUTPUT_NAME alleggl VERSION ${ALLEGRO_VERSION} SOVERSION ${ALLEGRO_SOVERSION} ) set_our_framework_properties(allegrogl AllegroGL) target_link_libraries(allegrogl allegro ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} ) sanitize_cmake_link_flags(static_link_with ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} ) set_target_properties(allegrogl PROPERTIES static_link_with "${static_link_with}" ) install_our_library(allegrogl) if(NOT WANT_FRAMEWORKS) install_our_headers(${ALLEGROGL_HEADERS}) endif(NOT WANT_FRAMEWORKS) set(SUPPORT_ALLEGROGL 1 PARENT_SCOPE) #-----------------------------------------------------------------------------# # # Examples # file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/examp) function(add_our_example nm) add_executable(${nm}_agl WIN32 examp/${nm}.c) set_target_properties(${nm}_agl PROPERTIES OUTPUT_NAME examp/${nm} ) target_link_libraries(${nm}_agl allegrogl) endfunction() if(WANT_EXAMPLES) add_our_example(dialog) add_our_example(dumbtest) add_our_example(exalleg) add_our_example(exalpfnt) add_our_example(exblend) add_our_example(excamera) add_our_example(exext) add_our_example(exgui) add_our_example(exmasked) add_our_example(exmipmaps) add_our_example(extext) add_our_example(extextur) add_our_example(fonttest) add_our_example(test) add_our_example(tex) copy_files(copy_allegrogl_example_data examp/a1.bmp examp/a8.bmp examp/a24.tga examp/a32.tga examp/demofont.dat examp/lucidia.dat examp/mysha.pcx examp/running.dat ) endif(WANT_EXAMPLES) #-----------------------------------------------------------------------------# # vim: set sts=4 sw=4 et: allegro4.4-4.4.2/addons/allegrogl/bugs.txt000066400000000000000000000047371173507505700203420ustar00rootroot00000000000000AllegroGL Know Bug List ----------------------- * Voodoo 5 only seems to support mipmapping for textures that are 32x32 and under. Voodoo 3 supports larger textures with mipmaps. GLU also resizes down to 32x32. Needs investigation * Catalyst 3.10 drivers aren't able to correctly compile the code in exext.c. This looks like a bug in Cat 3.10; with ATI not following the ARB grammar for VP. Works on NV drivers. * "In extextur, the space character is rendered as a small dot when the background is not transparent". This is a bug in the font generation code. We need to make it more solid. Should we remove the cropping code? Should we draw a rectangle before the text? * AGL cannot deal with extensions which name starts with a number (e.g WGL_3DL_stereo_control). It fails at compile-time trying to construct an invalid struct member variable name like allegro_gl_extensions_WGL.3DL_stereo_control. * Functions that do text drawing, rotating and/or flipping to video bitmaps do not work correctly for dest bitmaps that have textures in segments. Bitmap is made segmented if the texture of the size of the bitmap is not supported by the GFX driver (too large or non-power-of-2). The work-around is obvious. * Functions that do text drawing, stretching, rotating and/or flipping to video bitmaps do not work correctly if EXT_framebuffer_object OpenGL extension is not available. * Functions that do stretching, rotating and/or flipping to video bitmaps do not apply rotation and scale to the memory copy. Thus reading from such bitmaps may return unexpected images. * Before any drawing to the video bitmap occurs, when using FBO feature, at least one call to allegro_gl_set_allegro_mode() must be made. This is needed in order for __allegro_gl_pool_texture texture to be created, which is used for FBO drawing. Here's a list of known bugs, that are either unresolved, lack debug information, or the original discoverer dispeared without confirming whether the bug still exists or not. We would appreciate some feedback on those: * The Allegro mouse cursor doesn't work. This is due to GL not being able to operate accross threads and assynchronously. Potential resolve: make agl_flip() draw the mouse cursor. * On Win32 platforms, the mouse cursor (Windows style) is not always hidden in fullscreen mode. Workaround while the bug is not fixed : call 'set_gfx_mode(GFX_TEXT,0,0,0,0)' before the actual 'set_gfx_mode' (workaround suggested by Martin Dusek). allegro4.4-4.4.2/addons/allegrogl/changelog000066400000000000000000001314511173507505700205050ustar00rootroot00000000000000Changes from 0.4.4 to 0.4.x ------------------------------- * Milan Mimica - [X Driver] Fixed minor problems in deinitialisation code. - [X Driver] Added support for some fullscreen modes without XVidMode extension. Changes from 0.4.3 to 0.4.4 ------------------------------- * Milan Mimica - [Allegro driver] Implemented draw_sprite_ex(). - [Build] Merged the build system to Allegro. Changes from 0.4.2 to 0.4.3 ------------------------------- * Milan Mimica - [Allegro driver] Made FBO extension handling more robust. - [Allegro driver] Fixed a clipping problem with large video bitmaps and FBO. - [Allegro driver] Added support for DRAW_MODE_COPY_PATTERN drawing mode. - [Allegro driver] Added support for POLYTYPE_[A|P]TEX and POLYTYPE_[A|P]TEX_TRANS in 3d polygon rendering. - [Allegro driver] Fixed plenty of clipping bugs. - [Glext] Added GL_GREMEDY_frame_terminator extension. * Matthew Leverton & torhu - [Build] Added Digital Mars Compiler support. * Dennis Busch - [Build] Fixed the breakage when building DLL Release configuration in batch build. Changes from 0.4.1 to 0.4.2 ------------------------------- * Milan Mimica - [Allegro driver] Implemented video <-> video and memory -> video blit(), masked_blit(), [pivot_scaled|draw]_sprite[_vh_flip], and draw_trans_sprite(). - [Allegro driver] Accelerated clear_to_color() on video bitmaps by using FBO when available. - [Allegro driver] Made drawing to video bitmaps work again when EXT_packed_pixels is not available. - [Allegro driver] Implemented video -> screen and video <-> video stretch_blit(), masked_stretch_blit() and stretch_sprite(). - [Allegro driver] Implemented drawing of allegro fonts onto video bitmaps. - [Build] Made compatible with allegro 4.2.2 Changes from 0.4.0 to 0.4.1 ------------------------------- * Milan Mimica - [Allegro driver] Fixed wrong coordinate system for getpixel. - [Allegro driver] Made video->screen maked_blit work in color depth 16 or lower. - [Build] Added version suffixes to unix dynamic link libraries and set SONAME appropriately. - [Allegro driver] Introduced the allegro_gl_set_video_bitmap_color_depth() function. - [Allegro driver] Implemented set_blender_mode() and draw_trans_sprite(). - [Examples] Added a new example exblend. - [Allegro driver] Fixed triangle() on video bitmap. - [Allegro driver] Fixed video bitmaps which size is not multiple of 4/bytes-per-pixel. - [Allegro driver] Added support for NPOT video bitmaps even if hardware doesn't support NPOT textures. - [Allegro driver] Implemented rect() and polygon() onto screen bitmap using OpenGL methods. - [Allegro driver] Partialy implemented polygon3d(_f), quad3d(_f) and triangle3d(_f) using OpenGL. Only color shaded polygons are supported. - [Allegro driver] Partialy implemented drawing_mode() when drawing to the screen. Only DRAW_MODE_XOR and DRAW_MODE_TRANS are supported. - [Build] Added MSVC6 and MSVC2005 project files for building AllegroGL. - [Allegro driver] Fixed screen->video blit. - [Allegro driver] Fixed putpixel() on video bitmaps. Changes from 0.2.4 to 0.4.0 ------------------------------- * Robert J Ohannessian - [GLext] Added in the following extensions: - GL_ARB_fragment_program_shadow - GL_ARB_draw_buffers - GL_ARB_texture_rectangle - GL_EXT_pixel_buffer_object - GL_NV_fragment_program_option - GL_NV_fragment_program2 - GL_NV_vertex_program2_option - GL_NV_vertex_program3 - GLX_SGIX_hyperpipe - GLX_MESA_agp_offset - GL_ARB_color_buffer_float - GL_ARB_half_float_pixel - GL_ARB_texture_float - GL_EXT_texture_compression_dxt1 - WGL_ARB_pixel_format_float - GLX_ARB_fbconfig_float - GL_ARB_pixel_buffer_object - GL_EXT_framebuffer_object - GL_GREMEDY_string_marker - GL_EXT_packed_depth_stencil - GL_EXT_bindable_uniform - GL_EXT_draw_buffers2 - GL_EXT_draw_instanced - GL_EXT_framebuffer_sRGB - WGL_EXT_framebuffer_sRGB - GLX_EXT_framebuffer_sRGB - GL_EXT_geometry_shader4 - GL_EXT_gpu_shader4 - GL_EXT_packed_float - WGL_EXT_packed_float - GLX_EXT_packed_float - GL_EXT_texture_array - GL_EXT_texture_buffer_object - GL_EXT_texture_compression_latc - GL_EXT_texture_compression_rgtc - GL_EXT_texture_integer - GL_EXT_texture_shared_exponent - GL_NV_depth_buffer_float - GL_NV_fragment_program4 - GL_NV_framebuffer_multisample_coverage - GL_NV_geometry_program4 - GL_NV_gpu_program4 - GL_NV_parameter_buffer_object - GL_NV_transform_feedback - GL_NV_vertex_program4 - [GLext] Added OpenGL 2.0 support. - [GLext] Added missing GL_SAMPLER_* defines for ARB_shader_objects - [Examples] Removed text from extextur and put it in exalpfnt. - [Examples] Cleaned up exalpfnt code. - [Examples] Added an NV_vp2 path to exext, just because it's simpler. - [AGLF] Default format for monochrome fonts is now GL_INTENSITY4. This should resolve many issues people had with font formats. - [AGLF] Fixed color fonts. - [GLext] Fixed the API alias script to correctly ignore whitespaces. - [AGLF] Added agl_printf_ex() which uses the current GL primary color instead of overwriting it with Allegro's. This should solve issues with alpha blending when the screen is not in 32-bpp. - [Texture] Added support for ARB_texture_non_power_of_two in allegro_gl_make_texture_ex(). Now non-power-of-two textures are automagically used. - [Texture] Resize textures to the maximum supported size if they exceed the max supported size and AGL_TEXTURE_RESCALE is used. - [Windows driver] Fixed uninitialized memory used for pixel format. This greatly speeds up context creation on NV drivers. - [Core] Removed Direct/Indirect screen modes. They have been deprecated for the last 4 years anyway. - [Core] Added support for floating-point color and depth buffers in the core and in Windows. X support is still lacking. - [Windows Driver] Fixed some uninitialized variables as pointed out by Daniel Schlyder. - [Examples] Added a mipmapping w/ aniso example. - [Windows Driver] Fixed a crash that happens on full-screen modes due to not having set-up the HDC correctly in some cases. - [Core] Now suggesting settings that were not explicitly set by the user. This fixes some performance issues, where AGL would pick high-sample multisampling modes when none was needed. - [Texture] NP2 textures now fail to load if RESCALE is not specified and ARB_texture_non_power_of_2 is not supported. - [Texture] Added many more helpful debug messages when uploading textures in the debug log. - [Allegro Driver] Added support for clipping and subbitmaps to the video bitmap vtable. - [Allegro Driver] Use ARB_texture_np2 and ARB/NV_texture_rectangle if available. Removed support for non-power-of-2 bitmaps if neither of these extensions are present. - [AGLF] Fix crash bug detected by MSVC. - [Examples] extext needs to work around an Allegro 4.2.0 bug :( - [Examples] Fixed the mysha.pcx, which seems to have been corrupted. - [Build] Add Allegro's GCC version detect for the -mtune/-mcpu switch crap. - [Build] Fixed cygwin build to match Allegro's. - [Allegro driver] Fixed some depricated API calls into Allegro. - [Texture] Disable support for non-power-of-2 textures on NVIDIA and ATI cards that don't really support them put still report that they do. * Elias Pschernig - [GLext] Fixed build break under Linux. - [Allegro Driver] Added vtable entries for Allegro 4.1.17 WIP. - [Allegro Driver] Added vtable entries for Allegro 4.1.18 (patch was applied with modifications to work with older versions of Allegro). - [X Driver] Fixed random crashes due to a misplaced XUNLOCK() call. Some X functions were still being called after the unlock. - [X Driver] Fixed "X connection to :0.0 broken (explicit kill or server shutdown)" problem. - [GLext & Texture] Fixed some pointer sign-ess issues. - [X Driver] Fix broken hardware cursor hiding under X11 with AllegroGL. - [AGLF] Add proper support for truecolor fonts. - [X Driver] Fixed an async reply introduced by the previous cursor fix. - [AGLF] Fixed get_text_length() for AllegroGL fonts with a non-integer scale. - [Build] removed bogus default makefile from SVN. - [Windows Driver] Added a hack which creates a temporary window to retain focus with the application while switching from windowed to fullscreen mode under Windows XP. - [Docs] Only create HTML (not RTF) per default. - fixed doxygen markup - Added a new example "fonttest.c". - Hacked in a cludge to make AllegroGL work together with changed X11 window handling in Allegro 4.2.1 - Adjusted the log style to match Allegro's, basically, have a prefix for each line, and no more empty lines - Added license information - GL_MODELVIEW_MATRIX was used instead of GL_MODELVIEW * Milan Mimica - [Examples] Fixed the examples so that they compile under MSVC again. - [Windows Driver] Added the ability to query the list of supported display modes through get_gfx_mode_list(). - [AGLF] Fixed a potential return of garbage value from font_height(). - [AGLF] Updated font vtable entries for allegro 4.2.0b. - [Allegro Driver] Fixed a compiler warning. - [AGLF] Fixed detection of recent versions of Allegro. - [Core] Fixed texture generation for 1-high bitmaps. - [AGLF] Added vtable implementation for all of the Allegro font routines. - [AGLF] Fixed extract_font_range() to match the new Allegro behavior. - [X driver] Fix build problem from X icon fix. - [Examples & Allegro Driver] Fixed pointer sign-ness issues. - [Windows Driver] Windows refresh rate fix. - [Build] MSVC build fix. - [Build] Added STATICTUNTIME, MSVC7 and MSVC8 support. - [AGLF] Made new translucent fonts (created with make_trans_font in Allegro) work. - [Docs] Docs update for new MSVC targets and user-frendly messages. - using M4 script to detect installed allegro version - MSVC makefile fixes: fixed linking problem and changed 'delete' to 'del' - adding rest() calls to some examples - fixing compiler errors with nvidia OGL headers installed - set executable permissions to libagl.so on unix - adding directories for static linking on unix - fixed memory leak in agl_merge_fonts and agl_extract_font_range - fixed several Xlib async replies - fixed font splitting - some fixes to the windows msg logging - msvc makefile fix: put obj files in right places - fixed floating point color format detection under windows - fixed a bug that lead to inconsistnecy in scorer on windows - added the ability to use GLXFBConfig instead of XVisualInfo routines on X11 port, if available - fixed blitters for NPOT bitmapts when no NPOT extension is available. - fixed make install with MSVC - made windows select_pixel_format more robust - workaround the problem when system headers do not define GLX_SAMPLES - fixed a issue with some Intel drivers that do not export glSampleCoverageARB but do export the non-ARB version - made LOGLEVEL env variable work on MSVC build - added full support for OpenGL version 2.1. Added 9 new extensions: - GL_EXT_stencil_clear_tag - GL_EXT_texture_sRGB - GL_EXT_framebuffer_blit - GL_EXT_framebuffer_multisample - GL_MESAX_texture_stack - GL_EXT_timer_query - GL_EXT_gpu_program_parameters - GL_APPLE_flush_buffer_renge - GL_EXT_stencil_clear_tag * Milan Mimica & Daniel Schlyder - [Windows Driver] Added support for requesting a refresh rate. * Peter Wang - [X Driver] Fixed the double-free-of-screen problem that's been plaguing the X port. - [GLext] Release the GL driver shared object once we're done querying it. - [Build] Added a --quick parameter to fix.sh. - [X Driver] Fixed an async reply due to glXSwapBuffers. - [Build] Added support for @libdir@ to the unix makefile. * Evert Glebbeek - [X Driver] Fixed icon. A generic icon gets loaded instead of the Allegro one. * Andreas Rönnquist - [X Driver] Reported a bug where availability of XCursor extension at compile time was not checked for. * Peter Hull - [Allegro Driver] Fixed double free when creating a video bitmap fails. - [OSX Driver] Mapping of allegro_gl_set constants to Apple pixel format was faulty (for example, requested Stereo even if the programmer asked for 'not Stereo'). - [OSX Driver] Default setting of Scissor region appears not to be the full screen (see exmipmaps) - now set explicitly. - [OSX Driver] Mouse setup not correct w.r.t hardware cursor (see recent change to Allegro proper). - [OSX Driver] Used an NSOpenGLView instead of plain of NSView - code is a bit neater. - [OSX Driver] Threads now use the _unix_* functions defined by Allegro instead of the bare pthreads. - [Allegro Driver] Workaround for crash in glRasterPos for Mac OSX 10.2.x - [GLext] On Mac OSX 10.2.x, NV_texture_rectangle is called EXT_texture_rectangle - Fixed a problem in screen_masked_blit_standard. - Added different blit modes, such as masked_blit and draw_sprite with power of two and non power of two bitmaps - Removed some unused variables and fixed colour conversion on Intel Mac - Fixed crash if mysha.pcx is not present * Sam Hocevar -fixed an oversight breaking 4.2.0 compatibility * Daniel Schlyder - Fixed an assertion when changing graphics modes under Windows. * Inphernic - made AGL on Windows pick a refresh rate as close as possible to 60Hz, if the requested refresh rate is not available. Changes from 0.2.2 to 0.2.4 --------------------------- * Robert J Ohannessian - [Windows driver] Re-fixed the second-set_gfx_mode()-call-fails problem. This was fixed on CVS at some point, but the fix was undone due to the input focus problem. This has since been corrected. - [Windows driver] Fixed the WGL_p_f problems under NV1x. Basically, we were querying for multisampling when multisampling wasn't supported. - [Windows driver / X driver] Screen video ID is now MAX_ID, not 1000. This should fix issues with programs that create more than 1000 video bitmaps. - [Allegro driver] Using GL_MESA_pack_invert when we can. - [Allegro driver] Added screen->video blits (untested) - [Windows driver] Overhauled error detection. - [Windows driver] Code clean-up. * Bertrand Coconnier - [Allegro Driver] Added support for RLE sprites. - [X driver] Added an error handler for X windows : X errors are now caught by AGL and reported to the log file. - [X driver] Elias Pschernig reported a bug in the DRI drivers for ATI card with R200 chip. A workaround has been added in order not to crash DRI drivers when AGL quits. Changes from 0.2.0 to 0.2.2 --------------------------- Note: AllegroGL 0.2.2 is NOT ABI compatible with AllegroGL 0.2.0 * Bertrand Coconnier - [Core] Added multisampling support. - [GLext] Changed the namespace of extension pointers in order to avoid name clashes between libagl.* and libGL.so under Linux. - [Build] Windows build does not install glX headers anymore *nix build does not install wgl headers anymore. - [X Driver] Made vsync() functional for GL drivers that support GLX_SGI_video_sync. - [Build & GLext] Alias headers are now automagically built - [Build] By default, AGL is now built as a shared library under *nix - [GLext] AGL now tries to use static linking for glXGetProcAddress[ARB] when libdl.so is not available. * Robert J Ohannessian - [Windows Driver] Fixed Multisampling support in the Windows port. - [Windows Driver] Using WGL_ARB_pixel_format for the pixel format selection, if available. - [Build] Fixed MSVC makefile to use -GF (read-only string pooling) instead of -Gf (read/write string pooling), as -Gf is deprecated. - [GLext] Added GL_EXT_blend_equation_separate, GL_MESA_pack_invert and GL_MESA_ycbcr_texture. - [Allegro Driver] Updated for 4.1.13 vtable changes. Bug pointed out by Peter Hull. - [Scorer] Correctly set the color depth if not set by user. - [GUI] Fixed potential memory leak. - [Windows driver] Improved error checking. - [GUI] Fixed mouse cursor being incorrectly displayed. Changes from 0.1.4 to 0.2.0 --------------------------- * Elias Pschernig - [Allegro Driver] Fixed a bug when dealing with blitting memory sub-bitmaps to the screen. - [Allegro Driver] Fixed a bug when blitting from memory to video bitmaps. - [Allegro Driver] Added support for blitting to video subbitmaps. - [Allegro Driver] Fixed drawing method of flipped sprites in order to prevent (some) OpenGL drivers to clip the whole sprite whenever it touches the screen edge. * Robert J Ohannessian - [Examples] Added missing text_mode(-1) call in dumbtest. - [Examples] Fixed exalpfnt to redraw itself continuously. Resolves issue with occluded window under Windows. - [GUI] Fixed GUI viewport DIALOG proc not clearing depth buffer bug - [Allegro Driver] Fixed function prototypes so that text output would work with Allegro WIP 4.1.4 and up. - [Allegro Driver] textout() on monochrome fonts now supports opaque background colors. - [Allegro Driver] Colored fonts text output uses alpha testing instead of blending to draw transparently. - [Allegro Driver] Replaced some get/set pairs with push/pop attribs. - [Allegro Driver] In Allegro mode, depth writes are disabled. - [Build] Batch files removed. They never worked right anyway. - [Windows Driver] We now set up some default values for the modelview and projection matrices and the viewport. This is a workaround for buggy drivers. - [Docs] Updated howto, quickstart and readme. - [Allegro Driver] Default filtering for video bitmaps is now GL_NEAREST. - [Windows Driver] Added a workaround for the input focus problem on app launch. - [Docs] Updated font section, depricating the system fonts functions. - [Windows Driver] Binding to texture 0 on init to go around a bug in some GL drivers. - [Core] Added GL extension library, to automatically load all known GL extensions. Removed need for GLsdk. - [Font] Fixed font splitting code. - [Texture] Updated texturing code. Removed the ever increasing need for more state, using automatic mipmap generation or our own mipmap generator, depending on availability, to avoid dependency issues with GLU. - [Examples] Fixed excamera's text drawing code - [All] Updated AllegroGL to build with Allegro 4.0 and Allegro WIP 4.1.12 and over. - [All] OpenGL Extensions are better detected and used. - [aglf] Textures used by fonts are queryable now - [Docs] Various doc updates - [GLext] Workaround for broken MESA/SGI headers. - [Build] Removed extra space character in fix.sh script - [Texture] Packed pixel formats don't seem to be correctly supported on any Voodoo cards. Disabling them for now. - [Texture] Voodoo cards seem to be limited to 32x32 textures when mipmapping is used. We rescale if possible, or otherwise disable mipmaps. Credit to 'Mutator' for helping in debugging. - [Texture] Workaround for crash on Matrox G200 cards. gluBuidl2DMipmaps doesn't seem to be affected, so we're using that; up-converting bitmaps to 24-bpp if needed. Credit to 'Rash' for helping in debugging. - [Texture] Workaround for Matrox G200 not interpreting the internalformat parameter to glTexImage?D correctly. - [Font] Better spaced out fonts to avoid glitches. - [Font] Fixed a bug that would sometimes cause fonts to allocate twice the texture space it really needs. - [Font] Fixed maximum texture size to 32k * 32k for fonts. - [Allegro Driver] Priliminary fix for problems drawing on an ATI Rage Pro glVertex2i is incorrectly implemented. Using glVertex2f instead. - [GLext] Added OpenGL 1.5 support - [GLext] Exposing the list of available GL extensions. - [Examples] Fixed some issues with the exext example. - [Texture] agl_check_texture() now uses agl_make_texture_ex() to check for texture validity, which makes it much more accurate. Also saves us from having the same code written twice. - [Texture] Added the missing agl_check_texture_ex(). - [AGLF] Logging gross font area as well as net. - [Core] Moved Voodoo 1/2/3 detection code with the others. - [Texture] Using max texture sizes check before trying to upload textures. Should prevent Radeon drivers from crashing. - [Texture] Lots of little doc updates. - [Texture] agl_make/check_texture[_ex]() now restores the texture binding. - [Texture] Texture flip flag was ignored (AGL always flipped). Fixed now. - [Windows Driver] Screen mode reset code simplified and corrected. Hangs on mode reset, and double resets shouldn't happen any more. - [Windows Driver] Input focus bug on full-screen modes should be fixed now for Win2k/XP/98. - [Windows Driver] Some minor code clean-up. - [AGLF] Correctly checking for valid texture before uploading. - [Texture] Correctly round on downsampling when building mipmap stack. - [Core] Setting up Allegro RGBA shift values to be compatible with GL (instead of the other way around). This should solve the discoloration issues some people were having. - [Examples] Simplified some examples, removed dead code. - [Examples] Added more test cases to extextur. - [Texture] Using GL_INTENSITY instead of GL_ALPHA for 8-bpp textures. - [Core] Added Radeon 7000 detection - [Texture] Workaround for SGIS_generate_mipmap bug in Radeon 7000. - [Texture] Fixed mipmap generation code (Allegro path). Thanks to 'Kitty Cat' on allegro.cc for his help. - [Examples] Added new example (exext.c) to show how to use the GL extension mechanism present in AGL. - [X Driver] Fixed a crash bug due to a bug in some DRI implementations. Elias Pschernig provided both the bug report and the initial fix. - [Allegro Driver] Binding to a 1x1 white texture when ATI Rage Pro is detected to work around a a bug in ATI's OpenGL drivers. - [Examples] Fixed some issues with the exext example. * Bertrand Coconnier - [Windows Driver] Fixed the gfx mode setting so that the desktop does not flicker anymore when AGL tests pixel formats on temporary windows. - [X Driver] Sync with Allegro : disabled hackish centering code in fullscreen mode (after Eric Botcazou's fix in Allegro). - [Allegro Driver] For clarity sake, splitted glvtable.c into glvtable.c (for screen vtable) and videovtb.c (for video bitmaps vtable) - [Ext] Fixed a typo in the definition of AGL_DEFINE_PROC_TYPE. - [Examples] exmasked now uses alpha test instead of blending. - [Texture] Fixed a bug that prevented OpenGL 1.1 ICDs to use the packed pixels extension. - [Allegro Driver] Added "standard" masked_blit methods for memory->screen and video->screen blits. - [Allegro Driver] Fixed a bug in the clipping code of blits (destination bitmaps were not correctly clipped). - [X & Win Driver] Constified extensions strings of WGL and glX. - [Texture] Moved the code chunk that converts mask colored pixels into RGBA values. It is now in a separate function so that the masked_blit method can also reference it. - [Allegro Driver] Added an optimized version of masked_blit that uses GL_NV_register_combiners to convert mask colored pixels into RGBA pixels. - [Allegro Driver] Modified masked_blit and draw_sprite_*_flip methods in order to make them fully functionnal (added horizontal & vertical flipping) - [Allegro Driver] Implemented the pivot_scaled_sprite_flip method. - [Headers] Moved internal structs from alleggl.h to allglint.h - [Allegro Driver] Added a new AGL_VIDEO_MEMORY_POLICY option to allegro_gl_get/set. - [Allegro Driver] Added another optimized version of masked_blit which implements the method that Bob has suggested in the mailing list (textures combination). - [Allegro Driver] Modified the drawing routine of the mouse cursor so that it uses alpha testing instead of blending. - [Build] Modified the makefile for Unix platforms in order to use the common makefile "makefile.all" - [X Driver] Fixed some memory leaks. - [X Driver] X window should now be correctly restored when XF86Vidmod fails. - [X Driver] Fullscreen modes can now be fetched by Allegro. - [Build] AllegroGL can now be built as a shared library under *nix. - [Texture] Added a new function allegro_gl_flip_texture() so that textures can optionnaly not be flipped when allegro_gl_make_texture() or allegro_gl_make_masked_texture() are called. - [Allegro Driver] Fixed typo in masked blit code, standard path. - [Allegro Driver] Driver vtable is now built after extensions are loaded to be able to use them properly. - [Allegro Driver] Numerous bug fixes to the blit() code. - [Makefiles] Fixed install/uninstall of GL extension headers. - [Extensions] Fixed compilation error under GCC 3 * Angelo Mottola - [OSX Driver] Added MacOSX port. - [Allegro Driver] Fixed incorrect computation of triangle()'s dirty rectangle for video bitmaps. - [Allegro Driver] Fix for vline/hline missing-a-pixel-at-the-end bug, using work-around by Robert J Ohannessian. - [Docs] Documented installation procedure for Mac OS X Changes from 0.1.2 to 0.1.4: ---------------------------- * Bertrand Coconnier - [X Driver] Fixed the 'motion blur' bug for mouse cursor. - [Generic Driver] Modified AMesa in order to support Mesa 4.0.2 and higher. - [Generic Driver] Added partial support of Allegro 3D primitives for faster rendering. - [X Driver] AGL now checks at run-time if pthread support is enabled. (The current behaviour is to generate a fatal error if pthreads are disabled but this may change in the future). - [Allegro Driver] Fixed a bug in allegro_gl_screen_draw_glyph that made glyphs to be drawn at the wrong location on sub-bitmaps. - [Core] Fixed a bug in allegro_gl_set_projection : glViewport values were not taken into account. - [Build] Fixed a bug in the Unix install process (bug reported by Benny Kramek). - [GUI] Added the GL viewport object : d_algl_viewport_proc - [X Driver] Fixed a bug that prevented SCREEN_W and SCREEN_H to be set to correct values if the dimensions of the fullscreen display did not match those asked by the user (bug reported by Benny Kramek). - [X Driver] Added size and position hints for the Window Manager in order to prevent the window to be resized (issue reported by Benny Kramek). - [Ext] Added AGL_DEFINE_PROC_TYPE in order to hide the need of APIENTRY for Windows platforms (issue reported by Andrew Bainbridge). - [Ext] Cleaned up the code. AllegroGL no longer tries to define GL 1.2 features itself. Use GLsdk instead. This removes some conflicts with GL/glext.h in Windows. - [Docs] Some tiny documentation updates. - [Allegro Driver] Added ability to draw characters and 256 color sprites on the screen bitmap. - [X Driver] Fixed a bug that made AGL crash when trying to switch several times between the Allegro's DGA2 driver and the AGL's OpenGL driver (thanks to Chris Martens for pointing out the fix). - [Texture] Changed the default settings of the texture created by 'allegro_gl_make_texture' with mipmapping disabled : bilinear filtering is now disabled for consistency with the behaviour of the same function when mipmapping is enabled (issue reported by Steve Apostol). - [Core] Fixed a bug where AGL overwrited mask colors of Allegro's vtables and did not set them back to their previous values when switching back to a non-OpenGL mode (bug reported by Chris Martens). - [Core] Added the ability to manipulate AGL's mouse cursor with Allegro's functions : show_mouse, set_mouse_sprite, scare_mouse,... - [Build] Fixed a bug in the DJGPP build process : agl_ext.h was not built (bug reported by Jeff Hurdle) - [Windows Driver] Fixed a bug that prevented WGL extensions to be written in the log file. - [Ext] Fixed GLsdk integration : renamed AGL_EXTENSIONS to AGL_USE_EXTENSIONS (issue reported by Igor Gnip) - [Core] Added a workaround for buggy proxy textures management of GL drivers based on Mesa/DRI (bug reported by Steffen Hein). - [Generic driver] Fixed a bug related to generation of masked textures from a 15 bpp bitmap. * Peter Hull - [AGLF] Fixed a bug in fontconv.c where texture sizes were sorted before they were set up. * Eric Botcazou - [Windows Driver] Fixed a bug that made AGL unable to change the color depth of the window (Allegro 4.1.1 WIP or higher is needed). The bug was reported by Martin Dusek. * Robert J Ohannessian - [Allegro driver] Fixed video bitmap creation code for bitmaps that have a dimension that is a multiple of 256. - [Build] Fixed warning with -mpentium on DJGPP and Mingw. Now using -mcpu=i586. * Chris Graham - [Allegro driver] Switched the y1 and y2 coordinates in agl_screen_rectfill. (Some drivers seem not to like upside-down rectangles). - [Ext] Fixed a bug where AGL claimed in the log file that it both failed and succeeded to load an extension (actually AGL failed). - [Core] Fixed a bug where OpenGL strings returned as NULL caused "allegro_gl_is_extension_supported" to crash (issue reported with Mesa). - [Windows driver] Made the test window size the same as the requested resolution so that fullscreen-only drivers do not crash anymore. - [Core] Made AllegroGL to default the OpenGL version to 1.0 when the drivers do not return any version info. * Igor Gnip - [Build] Fixed the Windows build with Mingw tools so that the build sequence can run even if sh.exe is found in PATH - [Ext] Fixed our copy of GLsdk so that it can be built with Mingw32-2.0.0.3 Changes from 0.1.0 to 0.1.2: ---------------------------- * Robert J Ohannessian - [Texture] Workaround for GL drivers that convert textures to 16-bit even when 32-bit was requested (thanks to Nick Davies for pointing out the fix). - [Docs] Fixed the demo program in quickstart.txt - [Build] Fixed include dir in makefiles - [AGLF] Made scale factor in AGLF conversion be able to flip y-axis. - [Allegro Driver] Added clip support for the screen and sub-bitmaps thereof. - [Build] Fixed various issues with the Windows makefiles. - [Allegro Driver] Added ability to blit from memory bitmaps of arbitrary depth to the screen and video bitmaps. - [Ext] GLsdk integration. AGL should now be able to detect and link to GLsdk if the user puts it in the add-on directory. This allows usage of GL 1.3 and extensions under Windows and Linux. - [Core] Made double buffering, and hardware acceleration default settings. You don't need to specify those any longer unless you want to require them. - [Windows Driver] Bug fix in the Windows full screen color depth detection code. (thanks to George Foot for pointing it out) - [Docs] Various documentation updates - [AGLF] Fixed a bug in the system fonts in AGLF. A float was accidentally type changed to an int. - [Examples] Fixed yaw/pitch/roll in excamera.c. Thanks to George Foot for the correct equations! - [Math] Fixed a bug in excamera.c and maths.c which caused glRotate to rotate around a zero vector. - [Allegro Driver] Text partially off screen renders correctly now. - [Scorer] Added RGBA accumulator depth - [Core] Added extra checks to make sure the user doesn't call GL commands without a valid context. * Hein Zelle - [Build] Changed the schell script of utod and dtou so that they can work on more platforms (Irix comes to mind). * Bertrand Coconnier - [Allegro Driver] Added sub-bitmap support for the screen - [Ext] Added GLsdk integration to the Unix build process. - [X Driver] Fixed a bug that prevented the Packed Pixels extension to be correctly handled. - [X Driver] Added a specific "Expose" event handler to AGL. - [Core] Added 'allegro_gl_error' variable in order to complete usual allegro error messages - [Core] Added 'allegro_gl_set/unset_allegro_mode' functions. These functions should now replace the 'allegro_gl_set/unset_projection' pair (which have been kept for backward compatibility). * George Foot - [GUI] Added GUI manager routines - [Build] Updated the MSVC build batch files to include gui.c and exgui.c - [GUI] Made the mouse cursor hide when the pointer is outside the window * Nick Sumner - [Texture] Fixed internal type for 32 bpp textures Changes from 0.0.24 to 0.1.0: ----------------------------- Note: AllegroGL 0.1.0 is NOT source compatible with AllegroGL 0.0.24 * Bertrand Coconnier: - Changed the DOS port into a generic driver that can either be built on DOS or Unix platforms (thanks to Allegro and Mesa portability !). - Upgraded the DOS (aka generic) driver to Mesa 4.0 (splitted amesa.c into amesa.c and raster.c) - allegro_gl_get_proc_address now works for the DOS (aka generic) driver too. - Added automatic dependencies generation for the Unix build. - Fixed the draw_glyph method of the generic driver. - Fixed the DJGPP makefile (according to Bob's new makefile system). - Fixed the color conversion problem of the generic driver (RGB components were sometimes mixed up) - Fixed a bug in the glClear method of the generic driver : it now takes glClearColor into account. - Fixed a bug that made the generic driver overwrite Allegro's vtables, thus rendering Allegro graphic functions useless. - Fixed a bug in 'remove_allegro_gl' : Allegro's gfx drivers are now correctly restored . - In alleggl.h, the prototypes of the functions that manage OpenGL extensions are now included in 'extern "C"' : they can now be used in a C++ prog. - Added an example (exgui.c) of how to use Allegro GUI routines within AllegroGL - Fixed a tiny bug in (and BTW simplified) the clear_to_color method. * Robert J Ohannessian: - Updated the Mingw compilation instructions. - Updated makefile system to be more consistent with itself and with Allegro's. MSVC and Mingw are done. Unix and DJGPP are pending. - Fixed a bug in allegro_gl_printf() that caused it to not restore the texture binding in some circumstances. - Documented strange behaviour of OpenGL - the default texture is not 0 if you use glGetIntegerv(GL_TEXTURE_2D_BINDING). - Added a new example/tutorial to show how to use a camera with quaternions in OpenGL. - Removed ability to draw AllegroGL fonts using Allegro functions. Use AGL functions for AGL fonts, and AL functions for AL fonts. - Glyphs are now sorted and fitted to textures. This should reduce wasted texture space, and fix some problems on Voodoos (but not all). - AllegroGL now *requires* Allegro 4.0.0. - Fixed most compilation warnings. - Cleaned up conversion code, and split aglf.c to fontconv.c - Reduced memory used by converted font. - Blank space in glyphs is now cropped to save more texture space. The example programs should now work on the Voodoos. - Font conversion code now takes a scaling factor (see docs for details). Use 16.0 so fonts get generated as in 0.0.24-. - Slight tweak in the alpha font converter so that end value range is [0..255] and not [0..254]. - Added ability to save/load current configuration. - Made set_color_depth be respected by AllegroGL, but only if the other AllegroGL functions weren't being used. * George Foot: - Fixed the Unix makefile - Added the capability of having glyphs placed arbitrarily in a texture. * Julien Cugniere: - Fixed a bug in allegro_gl_screen_triangle so that 2D triangles are not drawn twice anymore. * Igor Gnip: - Added the STATICLINK option for Mingw and MSVC compilers Changes from 0.0.22 to 0.0.24: ------------------------------ * Bertrand Coconnier: - Added 24 bpp support to the DOS port - Added an experimental scorer to the DOS port - The Read and Draw buffers are now handled by two different pointers on the DOS port. - Changed every GL_TEXTURE_2D_BINDING to GL_TEXTURE_BINDING_2D (the later is the only one which is compliant with OpenGL specifications). * George Foot - made the fix scripts create target directories Changes from 0.0.20 to 0.0.22: ------------------------------ * Bertrand Coconnier: - Revamped the DOS build process - Fixed a bug in "allegro_gl_check_texture" - Added support for OpenGL extensions mechanism - Fixed GFX_VTABLE and Allegro headers location to compile with WIP 40 - Fixed a bug in "allegro_gl_make_masked_texture" (mask color sometimes needs to be updated). - Fixed the color conversion bug for video bitmaps thanks to Bob's Allegro patch (e.g. blit_between_formats) - Added support for X fonts * Robert J Ohannessian - Fixed MSVC makefile so that "make clean" works again - Made allegro_gl_begin/end nops. * George Foot - Added alpha map fonts - Updated vtable checks to support Allegro 4 Changes from 0.0.18 to 0.0.20: ------------------------------ * Bertrand Coconnier: - Doc updates. - Fixed the GFX_VTABLE 'hfill' entry which must not be NULL. * Robert J Ohannessian - Fixed textout not working on non-square fonts. The bug crept back during an earlier patch, sorry. - Doc updates. - Fixed windowed mode bug in Windows. - Fixed GFX_VTABLE to compile with WIP 39 (added hrect field) - Fixed multi-range TEXTURED fonts. Changes from 0.0.16 to 0.0.18: ------------------------------ * Bertrand Coconnier: - Fixed the allegro_gl_screen and __allegro_gl_memory deallocation bug. - Fixed the reinitialization of keyboard and mouse when set_gfx_mode is called. - Added lots of debug info on the Unix build. - Added a DOS driver for rendering via Mesa. OpenGL programs can now be written for DOS! - Added the ability to hint windowness to the graphics driver. - Fixed a bug in exalleg which caused textures to not show up in 32bpp. - Determined the glvtable bug. - Added alpha channel support for 32 bpp in X. - Fixed the problematic color depth problem. - allegro_gl_printf now behaves accordingly to the value set with allegro_gl_use_alpha_channel. * Robert J Ohannessian - Lots of doc updates. - Bug fixes in the mono glyph drawing routine (incorrect width, and texture binding) - Allegro functions (glvtable) now reset the texture binding to 0 when called to fix problems when lines and points were drawn with a texture; Bertrand found the bug. - Added warning for unsupported platforms. - Fixed blitting to the screen from a < 24bpp bitmap in Windows. - Fixed a crashing bug when AGL wasn't able to properly set up a mode. - Added extra debug info to the Windows driver - Tweaked the scorer a bit to get better modes. Color depth is now better considered, and acceleration gets a bonus. Changes from 0.0.14 to 0.0.16: ------------------------------ * Steffen Hein - Fixed compilation warning * Robert J Ohannessian - Fixed error in texture uploading code. - Added a new example (extextur) which tests texturing and blending. - Added another example that tests the texture-bitmap masking code. - Fixed a bug that made AllegroGL overwrite Allegro's vtables, thus rendering Allegro graphic functions useless. - Added the (incomplete) video bitmap vtable. Only create/destroy/ putpixel/getpixel are supported. - Added an fps counter, and fixed the double buffering bug in dumbtest. - Added some simple Allegro calls in exalleg. - Updated docs, added a buglist. - Added RGBA depths to the scorer system, including depth guessing. - Replaced incorrect blending modes with ones that work. - Added priliminary support for video bitmaps through textures. vline/hline/line/rectfill and video->screen blits are supported. (need latest CVS of Allegro, or 3.9.38). - Fixed the 2D projection matrix to work with exact coordinates (according to the red book anyway) - Fixed a bug that made AllegroGL crash when doing screen->memory blits. * Bertrand Coconnier - Removed the -g switch for the Unix optimized build - Fixed a bug that generates a segmentation fault when the app switches between fullscreen and windowed mode in X. - The X fullscreen functions have been merged with the windowed ones (it allows to share much code between the two drivers) - Mouse should work under fullscreen in X. - X Fullscreen driver should also cleanly quit. - Cosmetic changes in the X code (ustrzcpy, h/w acceleration detection, extra debug info) * George Foot - Updated the screen vtable to fix pixel alignement issues. - Fixed the draw_glyph() problem: textout with regular Allegro fonts works! - Added blit_to_self to the screen vtable. Now screen->screen blits work. - Added a configure script. Now AGL can be compiled in X by running configure/make/make install. Video driver is now detected dynamically. - Debugging those incorrect blending modes (see above) Changes from 0.0.12 to 0.0.14: ------------------------------ * Eric Botcazou - made AGL re-read the desktop depth in select_pixel_format() to go around a bug in Win95. - Fixed the window-can-be-resized bug in the Windows port. * Robert J Ohannessian - Fixed a bad bug in the texture uploading code. AllegroGL should now properly work in alternate color depths (thanks to stoney``, _deserel and networm, from #allegro on EFNet for the bug reports!) - Added the allegro_gl_opengl_version() function. - Bug in 32bpp modes - Allegro loads bitmaps with alpha channel set to 0. This causes textures to not show up (documented) - Updated the docs for the texture routines. - Renamed the LOG macro to AGL_LOG to avoid conflicts. - Added a compile-time version check for Allegro. - Added a compile-time version check for OpenGL 1.1 - Removed the AGL_PPT and AGL_PPF macros - they don't make sense anymore, and replaced them with new functions (allegro_gl_get_texture_format() allegro_gl_bitmap_color_format() and allegro_gl_bitmap_type()) - Fixed the color bug in extext - Merged the texturing code from AGLF and AllegroGL - Added a new option for mipmapping. - Improved the visuals in the extext example. - Split alleggl.c into alleggl.c and texture.c - Fixed character alignment bug in AGLF. - Fixed incorrect character sizes in AGLF. Also made 16 pixels = 1.0 units in the Allegro->Textured code (documented). - Fixed "polygons being always culled" bug in AGLF (thanks to Bertrand & dusekm for the bug reports). - Added a main page to the Doxygen generated documentation. Rearanged the readme and quickstart guides. Added a FAQ. * Bertrand Coconnier - Fixed the warnings when compiling texture.c Changes from 0.0.10 to 0.0.12: ------------------------------ * Eric Botcazou - removed all the Windows specific hooks into Allegro internals. It lets AllegroGL reuse the Allegro window in a way similar to that of the Allegro windowed drivers. AGL now requires WIP 34-35 to compile. - Fixed the mode set/reset bug. * Javier González - Changed the Mingw makefile to use DOS's 'copy' instead of 'cp' - Added the missing agl_begin/end around allegro_gl_make_texture(). - Made allegro_gl_make_texture upload bitmaps upside down, as they should be. * Bertrand Coconnier - added fullscreen support in X * Günter Ladwig - Fixed compilation warnings in glvtable.c * Peter Wang - Fixed warnings about 'memcpy' and 'memset' * Robert J Ohannessian - Merged AGLF into AGL. Now AllegroGL has proper text output support, can convert Allegro fonts, load system fonts... - Fixed the MSVC makefile to work with the Mingw tools, and under Win2k. - Made the Dialog example useful as a screen mode testing program. - Updated the MSVC batch files. - Documented aglf - Updated aglf to work with Allegro's new FONT structure. * Georges Foot - Changed documentation system to work with Doxygen, and documented most of the lib. - Added a new package: alleggl_docs for holding the generated documentation. Changes from alpha-8 to 0.0.10: ------------------------------- * John Harger - added support for Mingw. - made the Allegro window close, and new window open to make up for difficulties with Win95. - fixed the windowed mode border/title bar problem. * Igor Gnip - fixed Ming support (accidently broken by Robert) * Robert J Ohannessian - added the fixmsvc.bat script - fixed a bug in makefile.win where the command line would be too long to be passed to cl. Now using 'echo' to write to a temporary file. - added a todo/bug list file. - modified the 'tex' example to use H/W acceleration and no stencil buffer. - fixed the linking errors with C++ program (thanks to martinik for pointing it out!) - added a font conversion routine. Now textout works in AllegroGL (but breaks it in Allegro *grin*) - fixed up the scorer a bit and beautified its output. - added support for 32bpp. - added a Quat to glRotate conversion function. - added a work-around to get the proper color depth in Win95. - fixed various things in the full-screen mode-setting code for Windows. - made the windowed mode work regardless of suggested color depth. * Günter Ladwig - added the fixunix.sh script - removed the showing of the echo'ed commands in makefile.win - fixed the hardware acceleration bug on Voodoo's. - changed the color depth setting mechanism for full screen modes in Windows. * George Foot - did minor aesthetic changes to fixunix.sh - rearranged the directory structure of AGL - moved the documentation to a seperate tree. - fixed a bug in 'tex' regarding texturing being turned off. - added a logging facility and trace calls in 'glvtable.c' - disabled the mouse cursor in X - added 8bpp support and fixed the X mouse warping. - fixed various things in the full-screen mode-setting code for Windows. allegro4.4-4.4.2/addons/allegrogl/docs/000077500000000000000000000000001173507505700175565ustar00rootroot00000000000000allegro4.4-4.4.2/addons/allegrogl/docs/Doxyfile000066400000000000000000001461131173507505700212720ustar00rootroot00000000000000# Doxyfile 1.5.2 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project # # All text after a hash (#) is considered a comment and will be ignored # The format is: # TAG = value [value, ...] # For lists items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (" ") #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # This tag specifies the encoding used for all characters in the config file that # follow. The default is UTF-8 which is also the encoding used for all text before # the first occurrence of this tag. Doxygen uses libiconv (or the iconv built into # libc) for the transcoding. See http://www.gnu.org/software/libiconv for the list of # possible encodings. DOXYFILE_ENCODING = UTF-8 # The PROJECT_NAME tag is a single word (or a sequence of words surrounded # by quotes) that should identify the project. PROJECT_NAME = AllegroGL # The PROJECT_NUMBER tag can be used to enter a project or revision number. # This could be handy for archiving the generated documentation or # if some version control system is used. PROJECT_NUMBER = 0.4.4 # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # base path where the generated documentation will be put. # If a relative path is entered, it will be relative to the location # where doxygen was started. If left blank the current directory will be used. OUTPUT_DIRECTORY = # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create # 4096 sub-directories (in 2 levels) under the output directory of each output # format and will distribute the generated files over these directories. # Enabling this option can be useful when feeding doxygen a huge amount of # source files, where putting all generated files in the same directory would # otherwise cause performance problems for the file system. CREATE_SUBDIRS = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # The default language is English, other supported languages are: # Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, # Croatian, Czech, Danish, Dutch, Finnish, French, German, Greek, Hungarian, # Italian, Japanese, Japanese-en (Japanese with English messages), Korean, # Korean-en, Lithuanian, Norwegian, Polish, Portuguese, Romanian, Russian, # Serbian, Slovak, Slovene, Spanish, Swedish, and Ukrainian. OUTPUT_LANGUAGE = English # If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will # include brief member descriptions after the members that are listed in # the file and class documentation (similar to JavaDoc). # Set to NO to disable this. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend # the brief description of a member or function before the detailed description. # Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. REPEAT_BRIEF = YES # This tag implements a quasi-intelligent brief description abbreviator # that is used to form the text in various listings. Each string # in this list, if found as the leading text of the brief description, will be # stripped from the text and the result after processing the whole list, is # used as the annotated text. Otherwise, the brief description is used as-is. # If left blank, the following values are used ("$name" is automatically # replaced with the name of the entity): "The $name class" "The $name widget" # "The $name file" "is" "provides" "specifies" "contains" # "represents" "a" "an" "the" ABBREVIATE_BRIEF = # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # Doxygen will generate a detailed section even if there is only a brief # description. ALWAYS_DETAILED_SEC = NO # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all # inherited members of a class in the documentation of that class as if those # members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. INLINE_INHERITED_MEMB = NO # If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full # path before files name in the file list and in the header files. If set # to NO the shortest path that makes the file name unique will be used. FULL_PATH_NAMES = NO # If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag # can be used to strip a user-defined part of the path. Stripping is # only done if one of the specified strings matches the left-hand part of # the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the # path to strip. STRIP_FROM_PATH = # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of # the path mentioned in the documentation of a class, which tells # the reader which header file to include in order to use a class. # If left blank only the name of the header file containing the class # definition is used. Otherwise one should specify the include paths that # are normally passed to the compiler using the -I flag. STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter # (but less readable) file names. This can be useful is your file systems # doesn't support long names like on DOS, Mac, or CD-ROM. SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen # will interpret the first line (until the first dot) of a JavaDoc-style # comment as the brief description. If set to NO, the JavaDoc # comments will behave just like the Qt-style comments (thus requiring an # explicit @brief command for a brief description. JAVADOC_AUTOBRIEF = YES # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen # treat a multi-line C++ special comment block (i.e. a block of //! or /// # comments) as a brief description. This used to be the default behaviour. # The new default is to treat a multi-line C++ comment block as a detailed # description. Set this tag to YES if you prefer the old behaviour instead. MULTILINE_CPP_IS_BRIEF = NO # If the DETAILS_AT_TOP tag is set to YES then Doxygen # will output the detailed description near the top, like JavaDoc. # If set to NO, the detailed description appears after the member # documentation. DETAILS_AT_TOP = NO # If the INHERIT_DOCS tag is set to YES (the default) then an undocumented # member inherits the documentation from any documented member that it # re-implements. INHERIT_DOCS = YES # If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce # a new page for each member. If set to NO, the documentation of a member will # be part of the file/class/namespace that contains it. SEPARATE_MEMBER_PAGES = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. # Doxygen uses this value to replace tabs by spaces in code fragments. TAB_SIZE = 4 # This tag can be used to specify a number of aliases that acts # as commands in the documentation. An alias has the form "name=value". # For example adding "sideeffect=\par Side Effects:\n" will allow you to # put the command \sideeffect (or @sideeffect) in the documentation, which # will result in a user-defined paragraph with heading "Side Effects:". # You can put \n's in the value part of an alias to insert newlines. ALIASES = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C # sources only. Doxygen will then generate output that is more tailored for C. # For instance, some of the names that are used will be different. The list # of all members will be omitted, etc. OPTIMIZE_OUTPUT_FOR_C = YES # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java # sources only. Doxygen will then generate output that is more tailored for Java. # For instance, namespaces will be presented as packages, qualified scopes # will look different, etc. OPTIMIZE_OUTPUT_JAVA = NO # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want to # include (a tag file for) the STL sources as input, then you should # set this tag to YES in order to let doxygen match functions declarations and # definitions whose arguments contain STL classes (e.g. func(std::string); v.s. # func(std::string) {}). This also make the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. BUILTIN_STL_SUPPORT = NO # If you use Microsoft's C++/CLI language, you should set this option to YES to # enable parsing support. CPP_CLI_SUPPORT = NO # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES, then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. DISTRIBUTE_GROUP_DOC = YES # Set the SUBGROUPING tag to YES (the default) to allow class member groups of # the same type (for instance a group of public functions) to be put as a # subgroup of that type (e.g. under the Public Functions section). Set it to # NO to prevent subgrouping. Alternatively, this can be done per class using # the \nosubgrouping command. SUBGROUPING = YES #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in # documentation are documented, even if no documentation was available. # Private class members and static file members will be hidden unless # the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES EXTRACT_ALL = NO # If the EXTRACT_PRIVATE tag is set to YES all private members of a class # will be included in the documentation. EXTRACT_PRIVATE = NO # If the EXTRACT_STATIC tag is set to YES all static members of a file # will be included in the documentation. EXTRACT_STATIC = YES # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) # defined locally in source files will be included in the documentation. # If set to NO only classes defined in header files are included. EXTRACT_LOCAL_CLASSES = YES # This flag is only useful for Objective-C code. When set to YES local # methods, which are defined in the implementation section but not in # the interface are included in the documentation. # If set to NO (the default) only methods in the interface are included. EXTRACT_LOCAL_METHODS = NO # If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all # undocumented members of documented classes, files or namespaces. # If set to NO (the default) these members will be included in the # various overviews, but no documentation section is generated. # This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. # If set to NO (the default) these classes will be included in the various # overviews. This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_CLASSES = YES # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all # friend (class|struct|union) declarations. # If set to NO (the default) these declarations will be included in the # documentation. HIDE_FRIEND_COMPOUNDS = NO # If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any # documentation blocks found inside the body of a function. # If set to NO (the default) these blocks will be appended to the # function's detailed documentation block. HIDE_IN_BODY_DOCS = NO # The INTERNAL_DOCS tag determines if documentation # that is typed after a \internal command is included. If the tag is set # to NO (the default) then the documentation will be excluded. # Set it to YES to include the internal documentation. INTERNAL_DOCS = NO # If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate # file names in lower-case letters. If set to YES upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. CASE_SENSE_NAMES = YES # If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen # will show members with their full class and namespace scopes in the # documentation. If set to YES the scope will be hidden. HIDE_SCOPE_NAMES = NO # If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen # will put a list of the files that are included by a file in the documentation # of that file. SHOW_INCLUDE_FILES = YES # If the INLINE_INFO tag is set to YES (the default) then a tag [inline] # is inserted in the documentation for inline members. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen # will sort the (detailed) documentation of file and class members # alphabetically by member name. If set to NO the members will appear in # declaration order. SORT_MEMBER_DOCS = NO # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the # brief documentation of file, namespace and class members alphabetically # by member name. If set to NO (the default) the members will appear in # declaration order. SORT_BRIEF_DOCS = NO # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be # sorted by fully-qualified names, including namespaces. If set to # NO (the default), the class list will be sorted only by class name, # not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the # alphabetical list. SORT_BY_SCOPE_NAME = NO # The GENERATE_TODOLIST tag can be used to enable (YES) or # disable (NO) the todo list. This list is created by putting \todo # commands in the documentation. GENERATE_TODOLIST = YES # The GENERATE_TESTLIST tag can be used to enable (YES) or # disable (NO) the test list. This list is created by putting \test # commands in the documentation. GENERATE_TESTLIST = YES # The GENERATE_BUGLIST tag can be used to enable (YES) or # disable (NO) the bug list. This list is created by putting \bug # commands in the documentation. GENERATE_BUGLIST = YES # The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or # disable (NO) the deprecated list. This list is created by putting # \deprecated commands in the documentation. GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional # documentation sections, marked by \if sectionname ... \endif. ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines # the initial value of a variable or define consists of for it to appear in # the documentation. If the initializer consists of more lines than specified # here it will be hidden. Use a value of 0 to hide initializers completely. # The appearance of the initializer of individual variables and defines in the # documentation can be controlled using \showinitializer or \hideinitializer # command in the documentation regardless of this setting. MAX_INITIALIZER_LINES = 30 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated # at the bottom of the documentation of classes and structs. If set to YES the # list will mention the files that were used to generate the documentation. SHOW_USED_FILES = YES # If the sources in your project are distributed over multiple directories # then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy # in the documentation. The default is NO. SHOW_DIRECTORIES = NO # The FILE_VERSION_FILTER tag can be used to specify a program or script that # doxygen should invoke to get the current version for each file (typically from the # version control system). Doxygen will invoke the program by executing (via # popen()) the command , where is the value of # the FILE_VERSION_FILTER tag, and is the name of an input file # provided by doxygen. Whatever the program writes to standard output # is used as the file version. See the manual for examples. FILE_VERSION_FILTER = #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated # by doxygen. Possible values are YES and NO. If left blank NO is used. QUIET = NO # The WARNINGS tag can be used to turn on/off the warning messages that are # generated by doxygen. Possible values are YES and NO. If left blank # NO is used. WARNINGS = YES # If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings # for undocumented members. If EXTRACT_ALL is set to YES then this flag will # automatically be disabled. WARN_IF_UNDOCUMENTED = NO # If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some # parameters in a documented function, or documenting parameters that # don't exist or using markup commands wrongly. WARN_IF_DOC_ERROR = YES # This WARN_NO_PARAMDOC option can be abled to get warnings for # functions that are documented, but have no documentation for their parameters # or return value. If set to NO (the default) doxygen will only warn about # wrong or incomplete parameter documentation, but not about the absence of # documentation. WARN_NO_PARAMDOC = NO # The WARN_FORMAT tag determines the format of the warning messages that # doxygen can produce. The string should contain the $file, $line, and $text # tags, which will be replaced by the file and line number from which the # warning originated and the warning text. Optionally the format may contain # $version, which will be replaced by the version of the file (if it could # be obtained via FILE_VERSION_FILTER) WARN_FORMAT = # The WARN_LOGFILE tag can be used to specify a file to which warning # and error messages should be written. If left blank the output is written # to stderr. WARN_LOGFILE = #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag can be used to specify the files and/or directories that contain # documented source files. You may enter file names like "myfile.cpp" or # directories like "/usr/src/myproject". Separate the files or directories # with spaces. INPUT = ../include \ ../src \ . \ .. # This tag can be used to specify the character encoding of the source files that # doxygen parses. Internally doxygen uses the UTF-8 encoding, which is also the default # input encoding. Doxygen uses libiconv (or the iconv built into libc) for the transcoding. # See http://www.gnu.org/software/libiconv for the list of possible encodings. INPUT_ENCODING = UTF-8 # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank the following patterns are tested: # *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx # *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py FILE_PATTERNS = *.c \ *.h \ *.dox \ mainpage.foo # The RECURSIVE tag can be used to turn specify whether or not subdirectories # should be searched for input files as well. Possible values are YES and NO. # If left blank NO is used. RECURSIVE = NO # The EXCLUDE tag can be used to specify files and/or directories that should # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. EXCLUDE = # The EXCLUDE_SYMLINKS tag can be used select whether or not files or # directories that are symbolic links (a Unix filesystem feature) are excluded # from the input. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. Note that the wildcards are matched # against the file with absolute path, so to exclude all test directories # for example use the pattern */test/* EXCLUDE_PATTERNS = # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the output. # The symbol name can be a fully qualified name, a word, or if the wildcard * is used, # a substring. Examples: ANamespace, AClass, AClass::ANamespace, ANamespace::*Test EXCLUDE_SYMBOLS = # The EXAMPLE_PATH tag can be used to specify one or more files or # directories that contain example code fragments that are included (see # the \include command). EXAMPLE_PATH = . \ .. \ ../src \ ../examp # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank all files are included. EXAMPLE_PATTERNS = # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude # commands irrespective of the value of the RECURSIVE tag. # Possible values are YES and NO. If left blank NO is used. EXAMPLE_RECURSIVE = NO # The IMAGE_PATH tag can be used to specify one or more files or # directories that contain image that are included in the documentation (see # the \image command). IMAGE_PATH = # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command , where # is the value of the INPUT_FILTER tag, and is the name of an # input file. Doxygen will then use the output that the filter program writes # to standard output. If FILTER_PATTERNS is specified, this tag will be # ignored. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. Doxygen will compare the file name with each pattern and apply the # filter if there is a match. The filters are a list of the form: # pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further # info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER # is applied to all files. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER) will be used to filter the input files when producing source # files to browse (i.e. when SOURCE_BROWSER is set to YES). FILTER_SOURCE_FILES = NO #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will # be generated. Documented entities will be cross-referenced with these sources. # Note: To get rid of all source code in the generated output, make sure also # VERBATIM_HEADERS is set to NO. SOURCE_BROWSER = YES # Setting the INLINE_SOURCES tag to YES will include the body # of functions and classes directly in the documentation. INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct # doxygen to hide any special comment blocks from generated source code # fragments. Normal C and C++ comments will always remain visible. STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES (the default) # then for each documented function all documented # functions referencing it will be listed. REFERENCED_BY_RELATION = YES # If the REFERENCES_RELATION tag is set to YES (the default) # then for each documented function all documented entities # called/used by that function will be listed. REFERENCES_RELATION = YES # If the REFERENCES_LINK_SOURCE tag is set to YES (the default) # and SOURCE_BROWSER tag is set to YES, then the hyperlinks from # functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will # link to the source code. Otherwise they will link to the documentstion. REFERENCES_LINK_SOURCE = YES # If the USE_HTAGS tag is set to YES then the references to source code # will point to the HTML generated by the htags(1) tool instead of doxygen # built-in source browser. The htags tool is part of GNU's global source # tagging system (see http://www.gnu.org/software/global/global.html). You # will need version 4.8.6 or higher. USE_HTAGS = NO # If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen # will generate a verbatim copy of the header file for each class for # which an include is specified. Set to NO to disable this. VERBATIM_HEADERS = YES #--------------------------------------------------------------------------- # configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index # of all compounds will be generated. Enable this if the project # contains a lot of classes, structs, unions or interfaces. ALPHABETICAL_INDEX = NO # If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then # the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns # in which this list will be split (can be a number in the range [1..20]) COLS_IN_ALPHA_INDEX = 5 # In case all classes in a project start with a common prefix, all # classes will be put under the same header in the alphabetical index. # The IGNORE_PREFIX tag can be used to specify one or more prefixes that # should be ignored while generating the index headers. IGNORE_PREFIX = #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES (the default) Doxygen will # generate HTML output. GENERATE_HTML = YES # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `html' will be used as the default path. HTML_OUTPUT = # The HTML_FILE_EXTENSION tag can be used to specify the file extension for # each generated HTML page (for example: .htm,.php,.asp). If it is left blank # doxygen will generate files with .html extension. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a personal HTML header for # each generated HTML page. If it is left blank doxygen will generate a # standard header. HTML_HEADER = # The HTML_FOOTER tag can be used to specify a personal HTML footer for # each generated HTML page. If it is left blank doxygen will generate a # standard footer. HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user-defined cascading # style sheet that is used by each HTML page. It can be used to # fine-tune the look of the HTML output. If the tag is left blank doxygen # will generate a default style sheet. Note that doxygen will try to copy # the style sheet file to the HTML output directory, so don't put your own # stylesheet in the HTML output directory as well, or it will be erased! HTML_STYLESHEET = alleggl.css # If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, # files or namespaces will be aligned in HTML using tables. If set to # NO a bullet list will be used. HTML_ALIGN_MEMBERS = NO # If the GENERATE_HTMLHELP tag is set to YES, additional index files # will be generated that can be used as input for tools like the # Microsoft HTML help workshop to generate a compressed HTML help file (.chm) # of the generated HTML documentation. GENERATE_HTMLHELP = YES # If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can # be used to specify the file name of the resulting .chm file. You # can add a path in front of the file if the result should not be # written to the html output directory. CHM_FILE = # If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can # be used to specify the location (absolute path including file name) of # the HTML help compiler (hhc.exe). If non-empty doxygen will try to run # the HTML help compiler on the generated index.hhp. HHC_LOCATION = # If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag # controls if a separate .chi index file is generated (YES) or that # it should be included in the master .chm file (NO). GENERATE_CHI = NO # If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag # controls whether a binary table of contents is generated (YES) or a # normal table of contents (NO) in the .chm file. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members # to the contents of the HTML help documentation and to the tree view. TOC_EXPAND = YES # The DISABLE_INDEX tag can be used to turn on/off the condensed index at # top of each HTML page. The value NO (the default) enables the index and # the value YES disables it. DISABLE_INDEX = NO # This tag can be used to set the number of enum values (range [1..20]) # that doxygen will group on one line in the generated HTML documentation. ENUM_VALUES_PER_LINE = 1 # If the GENERATE_TREEVIEW tag is set to YES, a side panel will be # generated containing a tree-like index structure (just like the one that # is generated for HTML Help). For this to work a browser that supports # JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, # Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are # probably better off using the HTML help feature. GENERATE_TREEVIEW = YES # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be # used to set the initial width (in pixels) of the frame in which the tree # is shown. TREEVIEW_WIDTH = 250 #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- # If the GENERATE_LATEX tag is set to YES (the default) Doxygen will # generate Latex output. GENERATE_LATEX = NO # The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `latex' will be used as the default path. LATEX_OUTPUT = # The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be # invoked. If left blank `latex' will be used as the default command name. LATEX_CMD_NAME = latex # The MAKEINDEX_CMD_NAME tag can be used to specify the command name to # generate index for LaTeX. If left blank `makeindex' will be used as the # default command name. MAKEINDEX_CMD_NAME = makeindex # If the COMPACT_LATEX tag is set to YES Doxygen generates more compact # LaTeX documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_LATEX = NO # The PAPER_TYPE tag can be used to set the paper type that is used # by the printer. Possible values are: a4, a4wide, letter, legal and # executive. If left blank a4wide will be used. PAPER_TYPE = a4wide # The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX # packages that should be included in the LaTeX output. EXTRA_PACKAGES = # The LATEX_HEADER tag can be used to specify a personal LaTeX header for # the generated latex document. The header should contain everything until # the first chapter. If it is left blank doxygen will generate a # standard header. Notice: only use this tag if you know what you are doing! LATEX_HEADER = # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated # is prepared for conversion to pdf (using ps2pdf). The pdf file will # contain links (just like the HTML output) instead of page references # This makes the output suitable for online browsing using a pdf viewer. PDF_HYPERLINKS = NO # If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of # plain latex in the generated Makefile. Set this option to YES to get a # higher quality PDF documentation. USE_PDFLATEX = NO # If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. # command to the generated LaTeX files. This will instruct LaTeX to keep # running if errors occur, instead of asking the user for help. # This option is also used when generating formulas in HTML. LATEX_BATCHMODE = NO # If LATEX_HIDE_INDICES is set to YES then doxygen will not # include the index chapters (such as File Index, Compound Index, etc.) # in the output. LATEX_HIDE_INDICES = NO #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- # If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output # The RTF output is optimized for Word 97 and may not look very pretty with # other RTF readers or editors. GENERATE_RTF = NO # The RTF_OUTPUT tag is used to specify where the RTF docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `rtf' will be used as the default path. RTF_OUTPUT = # If the COMPACT_RTF tag is set to YES Doxygen generates more compact # RTF documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_RTF = NO # If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated # will contain hyperlink fields. The RTF file will # contain links (just like the HTML output) instead of page references. # This makes the output suitable for online browsing using WORD or other # programs which support those fields. # Note: wordpad (write) and others do not support links. RTF_HYPERLINKS = NO # Load stylesheet definitions from file. Syntax is similar to doxygen's # config file, i.e. a series of assignments. You only have to provide # replacements, missing definitions are set to their default value. RTF_STYLESHEET_FILE = # Set optional variables used in the generation of an rtf document. # Syntax is similar to doxygen's config file. RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- # If the GENERATE_MAN tag is set to YES (the default) Doxygen will # generate man pages GENERATE_MAN = NO # The MAN_OUTPUT tag is used to specify where the man pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `man' will be used as the default path. MAN_OUTPUT = # The MAN_EXTENSION tag determines the extension that is added to # the generated man pages (default is the subroutine's section .3) MAN_EXTENSION = # If the MAN_LINKS tag is set to YES and Doxygen generates man output, # then it will generate one additional man file for each entity # documented in the real man page(s). These additional files # only source the real man page, but without them the man command # would be unable to find the correct page. The default is NO. MAN_LINKS = NO #--------------------------------------------------------------------------- # configuration options related to the XML output #--------------------------------------------------------------------------- # If the GENERATE_XML tag is set to YES Doxygen will # generate an XML file that captures the structure of # the code including all documentation. GENERATE_XML = NO # The XML_OUTPUT tag is used to specify where the XML pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `xml' will be used as the default path. XML_OUTPUT = xml # The XML_SCHEMA tag can be used to specify an XML schema, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_SCHEMA = # The XML_DTD tag can be used to specify an XML DTD, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_DTD = # If the XML_PROGRAMLISTING tag is set to YES Doxygen will # dump the program listings (including syntax highlighting # and cross-referencing information) to the XML output. Note that # enabling this will significantly increase the size of the XML output. XML_PROGRAMLISTING = YES #--------------------------------------------------------------------------- # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- # If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will # generate an AutoGen Definitions (see autogen.sf.net) file # that captures the structure of the code including all # documentation. Note that this feature is still experimental # and incomplete at the moment. GENERATE_AUTOGEN_DEF = NO #--------------------------------------------------------------------------- # configuration options related to the Perl module output #--------------------------------------------------------------------------- # If the GENERATE_PERLMOD tag is set to YES Doxygen will # generate a Perl module file that captures the structure of # the code including all documentation. Note that this # feature is still experimental and incomplete at the # moment. GENERATE_PERLMOD = NO # If the PERLMOD_LATEX tag is set to YES Doxygen will generate # the necessary Makefile rules, Perl scripts and LaTeX code to be able # to generate PDF and DVI output from the Perl module output. PERLMOD_LATEX = NO # If the PERLMOD_PRETTY tag is set to YES the Perl module output will be # nicely formatted so it can be parsed by a human reader. This is useful # if you want to understand what is going on. On the other hand, if this # tag is set to NO the size of the Perl module output will be much smaller # and Perl will parse it just the same. PERLMOD_PRETTY = YES # The names of the make variables in the generated doxyrules.make file # are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. # This is useful so different doxyrules.make files included by the same # Makefile don't overwrite each other's variables. PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- # If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will # evaluate all C-preprocessor directives found in the sources and include # files. ENABLE_PREPROCESSING = YES # If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro # names in the source code. If set to NO (the default) only conditional # compilation will be performed. Macro expansion can be done in a controlled # way by setting EXPAND_ONLY_PREDEF to YES. MACRO_EXPANSION = YES # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES # then the macro expansion is limited to the macros specified with the # PREDEFINED and EXPAND_AS_DEFINED tags. EXPAND_ONLY_PREDEF = NO # If the SEARCH_INCLUDES tag is set to YES (the default) the includes files # in the INCLUDE_PATH (see below) will be search if a #include is found. SEARCH_INCLUDES = YES # The INCLUDE_PATH tag can be used to specify one or more directories that # contain include files that are not input files but should be processed by # the preprocessor. INCLUDE_PATH = ../include # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard # patterns (like *.h and *.hpp) to filter out the header-files in the # directories. If left blank, the patterns specified with FILE_PATTERNS will # be used. INCLUDE_FILE_PATTERNS = # The PREDEFINED tag can be used to specify one or more macro names that # are defined before the preprocessor is started (similar to the -D option of # gcc). The argument of the tag is a list of macros of the form: name # or name=definition (no spaces). If the definition and the = are # omitted =1 is assumed. To prevent a macro definition from being # undefined via #undef or recursively expanded use the := operator # instead of the = operator. PREDEFINED = DOXYGEN # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then # this tag can be used to specify a list of macro names that should be expanded. # The macro definition that is found in the sources will be used. # Use the PREDEFINED tag if you want to use a different macro definition. EXPAND_AS_DEFINED = # If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then # doxygen's preprocessor will remove all function-like macros that are alone # on a line, have an all uppercase name, and do not end with a semicolon. Such # function macros are typically used for boiler-plate code, and will confuse # the parser if not removed. SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- # Configuration::additions related to external references #--------------------------------------------------------------------------- # The TAGFILES option can be used to specify one or more tagfiles. # Optionally an initial location of the external documentation # can be added for each tagfile. The format of a tag file without # this location is as follows: # TAGFILES = file1 file2 ... # Adding location for the tag files is done as follows: # TAGFILES = file1=loc1 "file2 = loc2" ... # where "loc1" and "loc2" can be relative or absolute paths or # URLs. If a location is present for each tag, the installdox tool # does not have to be run to correct the links. # Note that each tag file must have a unique name # (where the name does NOT include the path) # If a tag file is not located in the directory in which doxygen # is run, you must also specify the path to the tagfile here. TAGFILES = # When a file name is specified after GENERATE_TAGFILE, doxygen will create # a tag file that is based on the input files it reads. GENERATE_TAGFILE = # If the ALLEXTERNALS tag is set to YES all external classes will be listed # in the class index. If set to NO only the inherited external classes # will be listed. ALLEXTERNALS = NO # If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed # in the modules index. If set to NO, only the current project's groups will # be listed. EXTERNAL_GROUPS = YES # The PERL_PATH should be the absolute path and name of the perl script # interpreter (i.e. the result of `which perl'). PERL_PATH = #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- # If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will # generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base # or super classes. Setting the tag to NO turns the diagrams off. Note that # this option is superseded by the HAVE_DOT option below. This is only a # fallback. It is recommended to install and use dot, since it yields more # powerful graphs. CLASS_DIAGRAMS = YES # You can define message sequence charts within doxygen comments using the \msc # command. Doxygen will then run the mscgen tool (see http://www.mcternan.me.uk/mscgen/) to # produce the chart and insert it in the documentation. The MSCGEN_PATH tag allows you to # specify the directory where the mscgen tool resides. If left empty the tool is assumed to # be found in the default search path. MSCGEN_PATH = # If set to YES, the inheritance and collaboration graphs will hide # inheritance and usage relations if the target is undocumented # or is not a class. HIDE_UNDOC_RELATIONS = YES # If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is # available from the path. This tool is part of Graphviz, a graph visualization # toolkit from AT&T and Lucent Bell Labs. The other options in this section # have no effect if this option is set to NO (the default) HAVE_DOT = NO # If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect inheritance relations. Setting this tag to YES will force the # the CLASS_DIAGRAMS tag to NO. CLASS_GRAPH = YES # If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect implementation dependencies (inheritance, containment, and # class references variables) of the class with other documented classes. COLLABORATION_GRAPH = YES # If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen # will generate a graph for groups, showing the direct groups dependencies GROUP_GRAPHS = YES # If the UML_LOOK tag is set to YES doxygen will generate inheritance and # collaboration diagrams in a style similar to the OMG's Unified Modeling # Language. UML_LOOK = NO # If set to YES, the inheritance and collaboration graphs will show the # relations between templates and their instances. TEMPLATE_RELATIONS = YES # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT # tags are set to YES then doxygen will generate a graph for each documented # file showing the direct and indirect include dependencies of the file with # other documented files. INCLUDE_GRAPH = YES # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and # HAVE_DOT tags are set to YES then doxygen will generate a graph for each # documented header file showing the documented files that directly or # indirectly include this file. INCLUDED_BY_GRAPH = YES # If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will # generate a call dependency graph for every global function or class method. # Note that enabling this option will significantly increase the time of a run. # So in most cases it will be better to enable call graphs for selected # functions only using the \callgraph command. CALL_GRAPH = NO # If the CALLER_GRAPH and HAVE_DOT tags are set to YES then doxygen will # generate a caller dependency graph for every global function or class method. # Note that enabling this option will significantly increase the time of a run. # So in most cases it will be better to enable caller graphs for selected # functions only using the \callergraph command. CALLER_GRAPH = NO # If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen # will graphical hierarchy of all classes instead of a textual one. GRAPHICAL_HIERARCHY = YES # If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES # then doxygen will show the dependencies a directory has on other directories # in a graphical way. The dependency relations are determined by the #include # relations between the files in the directories. DIRECTORY_GRAPH = YES # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images # generated by dot. Possible values are png, jpg, or gif # If left blank png will be used. DOT_IMAGE_FORMAT = png # The tag DOT_PATH can be used to specify the path where the dot tool can be # found. If left blank, it is assumed the dot tool can be found in the path. DOT_PATH = # The DOTFILE_DIRS tag can be used to specify one or more directories that # contain dot files that are included in the documentation (see the # \dotfile command). DOTFILE_DIRS = # The MAX_DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of # nodes that will be shown in the graph. If the number of nodes in a graph # becomes larger than this value, doxygen will truncate the graph, which is # visualized by representing a node as a red box. Note that doxygen will always # show the root nodes and its direct children regardless of this setting. DOT_GRAPH_MAX_NODES = 50 # Set the DOT_TRANSPARENT tag to YES to generate images with a transparent # background. This is disabled by default, which results in a white background. # Warning: Depending on the platform used, enabling this option may lead to # badly anti-aliased labels on the edges of a graph (i.e. they become hard to # read). DOT_TRANSPARENT = NO # Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output # files in one run (i.e. multiple -o and -T options on the command line). This # makes dot run faster, but since only newer versions of dot (>1.8.10) # support this, this feature is disabled by default. DOT_MULTI_TARGETS = NO # If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will # generate a legend page explaining the meaning of the various boxes and # arrows in the dot generated graphs. GENERATE_LEGEND = YES # If the DOT_CLEANUP tag is set to YES (the default) Doxygen will # remove the intermediate dot files that are used to generate # the various graphs. DOT_CLEANUP = YES #--------------------------------------------------------------------------- # Configuration::additions related to the search engine #--------------------------------------------------------------------------- # The SEARCHENGINE tag specifies whether or not a search engine should be # used. If set to NO the values of all tags below this one will be ignored. SEARCHENGINE = NO allegro4.4-4.4.2/addons/allegrogl/docs/alleggl.css000066400000000000000000000023071173507505700217010ustar00rootroot00000000000000H1 { text-align: center; } A.qindex {} A.qindexRef {} A.el { text-decoration: none; font-weight: bold } A.elRef { font-weight: bold } A.code { text-decoration: none; font-weight: normal; color: #4444ee } A.codeRef { font-weight: normal; color: #4444ee } A:hover { text-decoration: none; background-color: #f2f2ff } DL.el { margin-left: -1cm } DIV.fragment { width: 100%; border: none; background-color: #eeeeee } DIV.ah { background-color: black; font-weight: bold; color: #ffffff; margin-bottom: 3px; margin-top: 3px } TD.md { background-color: #f2f2ff; font-weight: bold; } TD.mdname1 { background-color: #f2f2ff; font-weight: bold; color: #602020; } TD.mdname { background-color: #f2f2ff; font-weight: bold; color: #602020; width: 600px; } DIV.groupHeader { margin-left: 16px; margin-top: 12px; margin-bottom: 6px; font-weight: bold } DIV.groupText { margin-left: 16px; font-style: italic; font-size: smaller } FONT.keyword { color: #008000 } FONT.keywordtype { color: #604020 } FONT.keywordflow { color: #e08000 } FONT.comment { color: #800000 } FONT.preprocessor { color: #806020 } FONT.stringliteral { color: #002080 } FONT.charliteral { color: #008080 } P { margin-left: 0.5em; } allegro4.4-4.4.2/addons/allegrogl/docs/html/000077500000000000000000000000001173507505700205225ustar00rootroot00000000000000allegro4.4-4.4.2/addons/allegrogl/docs/html/aglf_8c.html000066400000000000000000000160441173507505700227200ustar00rootroot00000000000000 AllegroGL: aglf.c File Reference

aglf.c File Reference

Text output and font support in OpenGL. More...

#include <math.h>
#include <string.h>
#include <stdio.h>
#include "allegro.h"
#include "alleggl.h"
#include "allglint.h"
#include <GL/glu.h>

Go to the source code of this file.

Defines

  • #define PREFIX_E   "agl-font ERROR: "
  • #define BUF_SIZE   1024
  • #define BUF_SIZE   1024

Functions

Variables

  • static int aglf_font_generation_mode = 1

Detailed Description

Text output and font support in OpenGL.

Definition in file aglf.c.

allegro4.4-4.4.2/addons/allegrogl/docs/html/aglf_8c_source.html000066400000000000000000001325121173507505700242770ustar00rootroot00000000000000 AllegroGL: aglf.c Source File

aglf.c

Go to the documentation of this file.
00001 /* This code is (C) AllegroGL contributors, and double licensed under
00002  * the GPL and zlib licenses. See gpl.txt or zlib.txt for details.
00003  */
00008 #include <math.h>
00009 #include <string.h>
00010 #include <stdio.h>
00011 
00012 #include "allegro.h"
00013 
00014 #include "alleggl.h"
00015 #include "allglint.h"
00016 
00017 #ifdef ALLEGRO_MACOSX
00018 #include <OpenGL/glu.h>
00019 #else
00020 #include <GL/glu.h>
00021 #endif
00022 
00023 #if defined ALLEGRO_WITH_XWINDOWS && !defined ALLEGROGL_GENERIC_DRIVER
00024 #include <xalleg.h>
00025 #include <GL/glx.h>
00026 #endif
00027 
00028 #define PREFIX_E "agl-font ERROR: "
00029 
00030 
00031 
00032 static int aglf_font_generation_mode = AGL_FONT_POLYGONS;
00033 
00034 
00035 /* find_range:
00036  *  Searches a font for a specific character.
00037  */
00038 static AL_CONST FONT_AGL_DATA *find_range(AL_CONST FONT_AGL_DATA *f, int c) {
00039 
00040     while (f) {
00041         if ((c >= f->start) && (c < f->end))
00042             return f;
00043 
00044         f = f->next;
00045     }
00046 
00047     return NULL;
00048 }
00049 
00050 
00051 
00052 /* allegro_gl_printf(FONT *f, float x, float y, float z, int color,
00053             char *format, ...) */
00067 int allegro_gl_printf(AL_CONST FONT *f, float x, float y, float z, int color,
00068                       AL_CONST char *format, ...) {
00069 
00070 #define BUF_SIZE 1024
00071     char buf[BUF_SIZE];
00072     va_list ap;
00073     
00074     if (!__allegro_gl_valid_context)
00075         return 0;
00076     
00077     /* Get the string */
00078     va_start(ap, format);
00079         uvszprintf(buf, BUF_SIZE, format, ap);
00080     va_end(ap);
00081 
00082 #undef BUF_SIZE
00083 
00084     /* Set color */
00085     {
00086         GLubyte c[4];
00087         c[0] = (GLubyte)getr(color);
00088         c[1] = (GLubyte)getg(color);
00089         c[2] = (GLubyte)getb(color);
00090         c[3] = (__allegro_gl_use_alpha && bitmap_color_depth(screen) == 32)
00091              ? (GLubyte)geta(color) : 255;
00092 
00093         glColor4ubv(c);
00094     }
00095 
00096     return allegro_gl_printf_ex(f, x, y, z, buf);
00097 }
00098 
00099 
00100 
00101 /* allegro_gl_printf_ex(FONT *f, float x, float y, float z,
00102  *                      char *format, ...)
00103  */
00169 int allegro_gl_printf_ex(AL_CONST FONT *f, float x, float y, float z,
00170                          AL_CONST char *format, ...) {
00171     #define BUF_SIZE 1024
00172     char buf[BUF_SIZE];
00173     va_list ap;
00174     
00175     AL_CONST FONT_AGL_DATA *range = NULL;
00176     int c, pos = 0;
00177     int count = 0;
00178     AL_CONST FONT_AGL_DATA *d;
00179     GLint vert_order, cull_mode;
00180     GLint matrix_mode;
00181 
00182     int restore_rasterpos = 0;
00183     GLuint old_texture_bind = 0;
00184     GLfloat old_raster_pos[4];
00185     
00186 
00187     if (!__allegro_gl_valid_context)
00188         return 0;
00189 
00190     /* Check arguments */
00191     if (!format || !f) {
00192         TRACE(PREFIX_E "agl_printf: Null parameter\n");
00193         return 0;
00194     }
00195         
00196     if (f->vtable != font_vtable_agl) {
00197         TRACE(PREFIX_E "agl_printf: Font parameter isn't of the AGL "
00198               "type.\n");
00199         return 0;
00200     }
00201         
00202     d = (AL_CONST FONT_AGL_DATA*)f->data;
00203 
00204     /* Get the string */
00205     va_start(ap, format);
00206         uvszprintf(buf, BUF_SIZE, format, ap);
00207     va_end(ap);
00208 
00209 #undef BUF_SIZE
00210 
00211     glGetIntegerv(GL_MATRIX_MODE, &matrix_mode);
00212     glGetIntegerv(GL_FRONT_FACE, &vert_order);
00213     glGetIntegerv(GL_CULL_FACE_MODE, &cull_mode);   
00214     
00215     glMatrixMode(GL_MODELVIEW);
00216     glPushMatrix();
00217     
00218     glFrontFace(GL_CW);
00219     glCullFace(GL_BACK);
00220 
00221     {   GLint temp;
00222         glGetIntegerv(GL_TEXTURE_BINDING_2D, &temp);
00223         old_texture_bind = (GLuint)temp;
00224     }
00225 
00226     if (d->type == AGL_FONT_TYPE_BITMAP) {
00227         glTranslatef(0, 0, -1);
00228         glBindTexture(GL_TEXTURE_2D, 0);
00229         
00230         glGetFloatv(GL_CURRENT_RASTER_POSITION, old_raster_pos);
00231         glRasterPos2f(x, y);
00232         restore_rasterpos = 1;
00233     }
00234     else if (d->type == AGL_FONT_TYPE_OUTLINE) {
00235         glTranslatef(x, y, z);
00236         glBindTexture(GL_TEXTURE_2D, 0);
00237     }
00238     else if (d->type == AGL_FONT_TYPE_TEXTURED) {
00239         glTranslatef(x, y, z);
00240     }
00241 
00242 
00243     while ((c = ugetc(buf + pos)) != 0) {
00244 
00245         pos += ucwidth(c);
00246 
00247         if ((!range) || (c < range->start) || (c >= range->end)) {
00248             /* search for a suitable character range */
00249             range = find_range(d, c);
00250 
00251             if (!range) {
00252                 range = find_range(d, (c = '^'));
00253 
00254                 if (!range)
00255                     continue;
00256             }
00257         }
00258         
00259         /* Set up texture */
00260         if (d->type == AGL_FONT_TYPE_TEXTURED) {
00261             glBindTexture(GL_TEXTURE_2D, range->texture);
00262         }
00263         
00264         /* draw the character */
00265         c -= range->start;
00266         c += range->list_base;
00267         
00268         glCallList(c);
00269 
00270         count++;
00271     }
00272     
00273     glPopMatrix();
00274 
00275     glMatrixMode(matrix_mode);
00276     glFrontFace(vert_order);
00277     glCullFace(cull_mode);  
00278 
00279     glBindTexture(GL_TEXTURE_2D, old_texture_bind);
00280 
00281     if (restore_rasterpos) {
00282         glRasterPos4fv(old_raster_pos);
00283     }
00284 
00285     return count;
00286 }
00287 
00288 
00289 
00290 #ifndef ALLEGROGL_GENERIC_DRIVER
00291 #ifdef ALLEGRO_WINDOWS
00292 
00293 static FONT *win_load_system_font(char *name, int type, int style, int w, int h, float depth, int start, int end) {
00294 
00295     HFONT hFont;
00296 
00297     FONT_AGL_DATA *data;
00298     FONT *ret;
00299     
00300     ret = malloc(sizeof(FONT));
00301     if (!ret) {
00302         TRACE(PREFIX_E "win_load_system_font: Ran out of memory "
00303               "while allocating %i bytes\n", sizeof(FONT));
00304         return NULL;
00305     }
00306     data = malloc(sizeof(FONT_AGL_DATA));
00307     if (!data) {
00308         free(ret);
00309         TRACE(PREFIX_E "win_load_system_font: Ran out of memory "
00310               "while allocating %i bytes\n", sizeof(FONT_AGL_DATA));
00311         return NULL;
00312     }
00313     ret->vtable = font_vtable_agl;
00314     ret->data = data;
00315         
00316     data->list_base = glGenLists(end - start);
00317     data->start = start;
00318     data->end = end;
00319     data->next = NULL;
00320     data->is_free_chunk = 0;
00321 
00322     if (type == AGL_FONT_TYPE_BITMAP || type == AGL_FONT_TYPE_DONT_CARE) {
00323 
00324         HDC dc;
00325 
00326         hFont = CreateFont( -h, w,
00327             0, 0,
00328             (style & AGL_FONT_STYLE_BOLD) ? FW_BOLD
00329                      : ((style & AGL_FONT_STYLE_BLACK) ? FW_BLACK : FW_NORMAL),
00330             ((style & AGL_FONT_STYLE_ITALIC) ? TRUE : FALSE),
00331             ((style & AGL_FONT_STYLE_UNDERLINE) ? TRUE : FALSE),
00332             ((style & AGL_FONT_STYLE_STRIKEOUT) ? TRUE : FALSE),
00333             ANSI_CHARSET,
00334             OUT_TT_PRECIS,
00335             CLIP_DEFAULT_PRECIS,
00336             (style & AGL_FONT_STYLE_ANTI_ALIASED) ? ANTIALIASED_QUALITY
00337                      : DEFAULT_QUALITY,
00338             FF_DONTCARE | DEFAULT_PITCH,
00339             name);
00340 
00341         dc = GetDC(win_get_window());
00342 
00343         SelectObject(dc, hFont);
00344 
00345         wglUseFontBitmaps(dc, start, end - start, data->list_base);
00346         data->type = AGL_FONT_TYPE_BITMAP;
00347         data->data = NULL;
00348     }
00349     else if (type == AGL_FONT_TYPE_OUTLINE) {
00350         HDC dc;
00351 
00352         GLYPHMETRICSFLOAT *gmf;
00353         gmf = malloc(sizeof(GLYPHMETRICSFLOAT) * (end - start));
00354         memset(gmf, 0, sizeof(GLYPHMETRICSFLOAT) * (end - start));
00355 
00356         hFont = CreateFont( -h, w,
00357             0, 0,
00358             (style & AGL_FONT_STYLE_BOLD) ? FW_BOLD
00359                       : ((style & AGL_FONT_STYLE_BLACK) ? FW_BLACK : FW_NORMAL),
00360             ((style & AGL_FONT_STYLE_ITALIC) ? TRUE : FALSE),
00361             ((style & AGL_FONT_STYLE_UNDERLINE) ? TRUE : FALSE),
00362             ((style & AGL_FONT_STYLE_STRIKEOUT) ? TRUE : FALSE),
00363             ANSI_CHARSET,
00364             OUT_TT_PRECIS,
00365             CLIP_DEFAULT_PRECIS,
00366             (style & AGL_FONT_STYLE_ANTI_ALIASED) ? ANTIALIASED_QUALITY
00367                       : DEFAULT_QUALITY,
00368             FF_DONTCARE | DEFAULT_PITCH,
00369             name);
00370 
00371         dc = GetDC(win_get_window());
00372 
00373         SelectObject(dc, hFont);
00374         wglUseFontOutlines(dc, start, end - start, data->list_base,
00375             0.0, depth, (aglf_font_generation_mode == AGL_FONT_POLYGONS)
00376             ? WGL_FONT_POLYGONS : WGL_FONT_LINES, gmf);
00377 
00378         data->type = AGL_FONT_TYPE_OUTLINE;
00379         data->data = gmf;
00380     }
00381 
00382     return ret;
00383 }
00384 #endif
00385 
00386 
00387 
00388 #ifdef ALLEGRO_WITH_XWINDOWS
00389 static FONT *x_load_system_font(char *name, int type, int style, int w, int h,
00390                                               float depth, int start, int end) {
00391     FONT_AGL_DATA *data;
00392     FONT *ret;
00393     XFontStruct *xfont;
00394 
00395     ret = malloc(sizeof(FONT));
00396     if (!ret) {
00397         TRACE(PREFIX_E "x_load_system_font: Ran out of memory "
00398               "while allocating %zi bytes\n", sizeof(FONT));
00399         return NULL;
00400     }
00401     data = malloc(sizeof(FONT_AGL_DATA));
00402     if (!data) {
00403         free(ret);
00404         TRACE(PREFIX_E "x_load_system_font: Ran out of memory "
00405               "while allocating %zi bytes\n", sizeof(FONT_AGL_DATA));
00406         return NULL;
00407     }
00408     ret->vtable = font_vtable_agl;
00409     ret->data = data;
00410         
00411     data->list_base = glGenLists(end - start);
00412     data->start = start;
00413     data->end = end;
00414     data->next = NULL;
00415     data->is_free_chunk = 0;
00416 
00417     if (type == AGL_FONT_TYPE_BITMAP || type == AGL_FONT_TYPE_DONT_CARE) {
00418         char buf[256], major_type[256], minor_type[2];
00419         
00420         usprintf(major_type, "medium");
00421         if (style & AGL_FONT_STYLE_BOLD)
00422             usprintf(major_type, "bold");
00423         minor_type[0] = (style & AGL_FONT_STYLE_ITALIC) ? 'i' : 'r';
00424         minor_type[1] = '\0';
00425         
00426         usprintf(buf, "-*-%s-%s-%s-normal-*-%i-*-*-*-*-*-*-*", name,
00427                                                     major_type, minor_type, h);
00428         /* Load the font */
00429         xfont = XLoadQueryFont(_xwin.display, buf);
00430         if (!xfont) {
00431             free(ret);
00432             free(data);
00433             TRACE(PREFIX_E "x_load_system_font: Failed to load "
00434                   "%s\n", buf);
00435             return NULL;
00436         }
00437         glXUseXFont(xfont->fid, start, end - start, data->list_base);
00438         data->type = AGL_FONT_TYPE_BITMAP;
00439         data->data = NULL;
00440         XFreeFont(_xwin.display, xfont);
00441     }
00442     else {
00443         /* Not Yet Implemented */
00444         return NULL;
00445     }
00446     
00447     return ret;
00448 }
00449 #endif
00450 #endif /* ALLEGROGL_GENERIC_DRIVER */
00451 
00452 
00453 
00454 /* void allegro_gl_set_font_generation_mode(int mode) */
00469 void allegro_gl_set_font_generation_mode(int mode) {
00470     aglf_font_generation_mode = mode;
00471     return;
00472 }
00473 
00474 
00475 
00476 /* FONT *allegro_gl_load_system_font(char *name, int style, int w, int h) */
00485 FONT *allegro_gl_load_system_font(char *name, int style, int w, int h) {
00486 
00487     return allegro_gl_load_system_font_ex(name, AGL_FONT_TYPE_OUTLINE,
00488                                           style, w, h, 0.0f, 32, 256);
00489 }
00490 
00491 
00492 
00493 /* FONT *allegro_gl_load_system_font_ex(char *name, int type, int style,
00494             int w, int h, float depth, int start, int end) */
00526 FONT *allegro_gl_load_system_font_ex(char *name, int type, int style,
00527                                 int w, int h, float depth, int start, int end) {
00528 
00529     FONT *ret = NULL;
00530 
00531     if (!__allegro_gl_valid_context)
00532         return NULL;
00533 
00534     if (!name) {
00535         TRACE(PREFIX_E "load_system_font: Nameless font\n");
00536         return NULL;
00537     }
00538 
00539     /* Load a system font */
00540 
00541 #ifndef ALLEGROGL_GENERIC_DRIVER
00542 #ifdef ALLEGRO_WINDOWS
00543     ret = win_load_system_font(name, type, style, w, h, depth, start, end);
00544 #elif defined ALLEGRO_UNIX
00545     XLOCK();
00546     ret = x_load_system_font(name, type, style, w, h, depth, start, end);
00547     XUNLOCK();
00548 #else
00549     /* Other platform */
00550 #endif
00551 #endif
00552 
00553     return ret;
00554 }
00555 
00556 
00557 
00573 void allegro_gl_destroy_font(FONT *f) {
00574 
00575     FONT_AGL_DATA *data;
00576 
00577     if (!f) {
00578         return;
00579     }
00580     if (f->vtable != font_vtable_agl) {
00581         TRACE(PREFIX_E "destroy_font: Font is not of AGL type\n");  
00582         return;
00583     }
00584     
00585     data = f->data;
00586     
00587     if (!data) {
00588         TRACE(PREFIX_E "destroy_font: Font is inconsistent\n"); 
00589         return;
00590     }
00591 
00592     /* Iterate through every segment of the font */
00593     while (data) {  
00594         FONT_AGL_DATA *datanext;
00595         
00596         /* Release all resources taken up by this font */
00597         if (data->type == AGL_FONT_TYPE_BITMAP
00598          || data->type == AGL_FONT_TYPE_OUTLINE
00599          || data->type == AGL_FONT_TYPE_TEXTURED) {
00600 
00601             if (__allegro_gl_valid_context) {
00602                 if (data->list_base)
00603                     glDeleteLists(data->list_base, data->end - data->start);
00604                 if (data->texture)
00605                     glDeleteTextures(1, &data->texture);
00606             }
00607         }
00608         if (data->type == AGL_FONT_TYPE_OUTLINE) {
00609             if (data->data) 
00610                 free(data->data);
00611         }
00612         else if (data->type == AGL_FONT_TYPE_TEXTURED) {
00613             if (data->data)
00614                 destroy_bitmap(data->data);
00615             if (data->glyph_coords)
00616                 free(data->glyph_coords);
00617         }
00618         else if (data->type == AGL_FONT_TYPE_BITMAP) {
00619             if (data->data) {
00620                 int i;
00621                 FONT_GLYPH **gl = data->data;
00622                 for (i = 0; i < data->end - data->start; i++) {
00623                     if (gl[i])
00624                         free(gl[i]);
00625                 }
00626                 free(gl);
00627             }
00628         }
00629         datanext = data->next;
00630 
00631         if (data->is_free_chunk)
00632             free(data);
00633             
00634         data = datanext;
00635     }
00636     free(f->data);
00637 
00638     if (f != font)
00639         free(f);
00640     
00641     return;
00642 }
00643 
00644 
00645 
00646 /* size_t allegro_gl_list_font_textures(FONT *f, GLuint *ids, size_t max_num_id) */
00689 size_t allegro_gl_list_font_textures(FONT *f, GLuint *ids, size_t max_num_id) {
00690 
00691     size_t num_ids = 0;
00692     FONT_AGL_DATA *data;
00693 
00694     if (!f) {
00695         return 0;
00696     }
00697     if (f->vtable != font_vtable_agl) {
00698         TRACE(PREFIX_E "list_font_textures: Font is not of AGL type\n");    
00699         return 0;
00700     }
00701     
00702     data = f->data;
00703     
00704     if (!data) {
00705         TRACE(PREFIX_E "list_font_textures: Font is inconsistent\n");   
00706         return 0;
00707     }
00708 
00709     if (!__allegro_gl_valid_context) {
00710         return 0;
00711     }
00712 
00713     /* Iterate through all font segments */
00714     while (data) {
00715         if (data->texture) {
00716             /* Add the texture ID in the array, if it's not NULL and if there
00717              * is room.
00718              */
00719             if (ids && num_ids < max_num_id) {
00720                 ids[num_ids] = data->texture;
00721             }
00722             num_ids++;
00723         }
00724 
00725         data = data->next;
00726     }
00727     
00728     return num_ids;
00729 }
00730 
allegro4.4-4.4.2/addons/allegrogl/docs/html/alleggl.css000066400000000000000000000023071173507505700226450ustar00rootroot00000000000000H1 { text-align: center; } A.qindex {} A.qindexRef {} A.el { text-decoration: none; font-weight: bold } A.elRef { font-weight: bold } A.code { text-decoration: none; font-weight: normal; color: #4444ee } A.codeRef { font-weight: normal; color: #4444ee } A:hover { text-decoration: none; background-color: #f2f2ff } DL.el { margin-left: -1cm } DIV.fragment { width: 100%; border: none; background-color: #eeeeee } DIV.ah { background-color: black; font-weight: bold; color: #ffffff; margin-bottom: 3px; margin-top: 3px } TD.md { background-color: #f2f2ff; font-weight: bold; } TD.mdname1 { background-color: #f2f2ff; font-weight: bold; color: #602020; } TD.mdname { background-color: #f2f2ff; font-weight: bold; color: #602020; width: 600px; } DIV.groupHeader { margin-left: 16px; margin-top: 12px; margin-bottom: 6px; font-weight: bold } DIV.groupText { margin-left: 16px; font-style: italic; font-size: smaller } FONT.keyword { color: #008000 } FONT.keywordtype { color: #604020 } FONT.keywordflow { color: #e08000 } FONT.comment { color: #800000 } FONT.preprocessor { color: #806020 } FONT.stringliteral { color: #002080 } FONT.charliteral { color: #008080 } P { margin-left: 0.5em; } allegro4.4-4.4.2/addons/allegrogl/docs/html/alleggl_8c.html000066400000000000000000000357061173507505700234240ustar00rootroot00000000000000 AllegroGL: alleggl.c File Reference

alleggl.c File Reference

Allegro-OpenGL interfacing. More...

#include <string.h>
#include <stdlib.h>
#include "alleggl.h"
#include "allglint.h"
#include <allegro/internal/aintern.h>
#include <GL/glu.h>

Go to the source code of this file.

Defines

  • #define PREFIX_I   "agl INFO: "
  • #define PREFIX_E   "agl ERROR: "
  • #define PREFIX_L   "agl LOG: "

Functions

  • static _DRIVER_INFO * our_gfx_drivers (void)
  • static _DRIVER_INFO * list_saved_gfx_drivers (void)
  • static BITMAP * allegro_gl_default_gfx_init (int w, int h, int vw, int vh, int depth)
  • static void build_settings (int opt, char *section, char *name)
  • static void agl_parse_section (int sec, char *section, char *name)
  • int install_allegro_gl (void)
    Installs the AllegroGL addon to Allegro.
  • void remove_allegro_gl (void)
    Removes the AllegroGL addon.
  • void allegro_gl_flip (void)
    Flips the front and back framebuffers.
  • float allegro_gl_opengl_version ()
    Returns the OpenGL version number of the client (the computer the program is running on).
  • void __allegro_gl_set_allegro_image_format (int big_endian)
  • void allegro_gl_set_blender_mode (int mode, int r, int g, int b, int a)
Mode selection functions

Variables

  • struct allegro_gl_driver * __allegro_gl_driver = NULL
  • struct allegro_gl_display_info allegro_gl_display_info
  • int __allegro_gl_required_settings
  • int __allegro_gl_suggested_settings
  • int __allegro_gl_valid_context = 0
  • int __allegro_gl_blit_operation
  • char allegro_gl_error [AGL_ERROR_SIZE] = EMPTY_STRING
  • BLIT_BETWEEN_FORMATS_FUNC __blit_between_formats8
  • BLIT_BETWEEN_FORMATS_FUNC __blit_between_formats15
  • BLIT_BETWEEN_FORMATS_FUNC __blit_between_formats16
  • BLIT_BETWEEN_FORMATS_FUNC __blit_between_formats24
  • BLIT_BETWEEN_FORMATS_FUNC __blit_between_formats32
  • BITMAP * allegro_gl_screen
    Direct-mode GL `screen' bitmap.
  • static _DRIVER_INFO our_driver_list []
  • _DRIVER_INFO *(* saved_gfx_drivers )(void) = NULL
  • GFX_DRIVER gfx_allegro_gl_default

Detailed Description

Allegro-OpenGL interfacing.

This sorts out having Allegro and the OpenGL library sharing a window, and generally cooperating.

Definition in file alleggl.c.


Variable Documentation

Direct-mode GL `screen' bitmap.

If you draw to this bitmap (using supported Allegro functions) your calls will be converted into OpenGL equivalents and appear on the screen (or backbuffer).

Definition at line 62 of file alleggl.c.

_DRIVER_INFO our_driver_list[] [static]
Initial value:
 {






    {GFX_OPENGL, &gfx_allegro_gl_default, FALSE},
    {0, NULL, FALSE}
}

Definition at line 67 of file alleggl.c.

GFX_DRIVER gfx_allegro_gl_default
Initial value:
{
   GFX_OPENGL,
   EMPTY_STRING,
   EMPTY_STRING,
   "AllegroGL Default Driver",
   allegro_gl_default_gfx_init,
   NULL,
   NULL,
   NULL,               
   NULL,
   NULL, NULL, NULL,
   NULL,        
   NULL,
   NULL, NULL,  
   NULL, NULL,
   NULL, NULL, NULL, NULL,
   NULL,
   NULL, NULL,
   NULL,        
   NULL,        
   0, 0,
   0,
   0, 0,
   0,
   0,
   FALSE        
}

Definition at line 102 of file alleggl.c.

allegro4.4-4.4.2/addons/allegrogl/docs/html/alleggl_8c_source.html000066400000000000000000003624351173507505700250060ustar00rootroot00000000000000 AllegroGL: alleggl.c Source File

alleggl.c

Go to the documentation of this file.
00001 /* This code is (C) AllegroGL contributors, and double licensed under
00002  * the GPL and zlib licenses. See gpl.txt or zlib.txt for details.
00003  */
00011 #include <string.h>
00012 #include <stdlib.h>
00013 
00014 #include "alleggl.h"
00015 #include "allglint.h"
00016 
00017 #include <allegro/internal/aintern.h>
00018 #ifdef ALLEGRO_MACOSX
00019 #include <OpenGL/glu.h>
00020 #else
00021 #include <GL/glu.h>
00022 #endif
00023 
00024 #define PREFIX_I                "agl INFO: "
00025 #define PREFIX_E                "agl ERROR: "
00026 #define PREFIX_L                "agl LOG: "
00027 
00028 
00029 /* Structs containing the current driver state */
00030 struct allegro_gl_driver *__allegro_gl_driver = NULL;
00031 struct allegro_gl_display_info allegro_gl_display_info;
00032 
00033 /* Settings required/suggested */
00034 int __allegro_gl_required_settings, __allegro_gl_suggested_settings;
00035 
00036 /* Valid context state */
00037 int __allegro_gl_valid_context = 0;
00038 
00039 
00040 /* Operation to enable while blitting. */
00041 int __allegro_gl_blit_operation;
00042 
00043 
00044 char allegro_gl_error[AGL_ERROR_SIZE] = EMPTY_STRING;
00045 
00046 BLIT_BETWEEN_FORMATS_FUNC __blit_between_formats8;
00047 BLIT_BETWEEN_FORMATS_FUNC __blit_between_formats15;
00048 BLIT_BETWEEN_FORMATS_FUNC __blit_between_formats16;
00049 BLIT_BETWEEN_FORMATS_FUNC __blit_between_formats24;
00050 BLIT_BETWEEN_FORMATS_FUNC __blit_between_formats32;
00051 
00052 
00053 
00062 BITMAP *allegro_gl_screen;
00063 
00064 
00065 
00066 /* Allegro GFX_DRIVER list handling */
00067 static _DRIVER_INFO our_driver_list[] = {
00068 #ifdef GFX_OPENGL_WINDOWED
00069     {GFX_OPENGL_WINDOWED, &gfx_allegro_gl_windowed, FALSE},
00070 #endif
00071 #ifdef GFX_OPENGL_FULLSCREEN
00072     {GFX_OPENGL_FULLSCREEN, &gfx_allegro_gl_fullscreen, FALSE},
00073 #endif
00074     {GFX_OPENGL, &gfx_allegro_gl_default, FALSE},
00075     {0, NULL, FALSE}
00076 };
00077 
00078 
00079 
00080 static _DRIVER_INFO *our_gfx_drivers(void)
00081 {
00082     return our_driver_list;
00083 }
00084 
00085 
00086 
00087 _DRIVER_INFO *(*saved_gfx_drivers) (void) = NULL;
00088 
00089 
00090 
00091 static _DRIVER_INFO *list_saved_gfx_drivers(void)
00092 {
00093     return _gfx_driver_list;
00094 }
00095 
00096 
00097 
00098 static BITMAP *allegro_gl_default_gfx_init(int w, int h, int vw, int vh, int depth);
00099 
00100 
00101 
00102 GFX_DRIVER gfx_allegro_gl_default =
00103 {
00104    GFX_OPENGL,
00105    EMPTY_STRING,
00106    EMPTY_STRING,
00107    "AllegroGL Default Driver",
00108    allegro_gl_default_gfx_init,
00109    NULL,
00110    NULL,
00111    NULL,               //_xwin_vsync,
00112    NULL,
00113    NULL, NULL, NULL,
00114    NULL,        /* create_video_bitmap */
00115    NULL,
00116    NULL, NULL,  /* No show/request video bitmaps */
00117    NULL, NULL,
00118    NULL, NULL, NULL, NULL,
00119    NULL,
00120    NULL, NULL,
00121    NULL,        /* set_blender_mode */
00122    NULL,        /* No fetch_mode_list */
00123    0, 0,
00124    0,
00125    0, 0,
00126    0,
00127    0,
00128    FALSE        /* Windowed mode */
00129 };
00130 
00131 
00132 
00176 /* void allegro_gl_clear_settings(void) */
00193 void allegro_gl_clear_settings(void)
00194 {
00195     memset(&allegro_gl_display_info, 0, sizeof allegro_gl_display_info);
00196 
00197     __allegro_gl_required_settings = __allegro_gl_suggested_settings = 0;
00198     
00199     /* Pick sensible defaults */
00200     allegro_gl_display_info.fullscreen = 1;
00201     allegro_gl_display_info.rmethod = 1;
00202     allegro_gl_display_info.doublebuffered = 1;
00203     allegro_gl_display_info.vidmem_policy = AGL_KEEP;
00204     __allegro_gl_suggested_settings =
00205                            AGL_FULLSCREEN | AGL_RENDERMETHOD | AGL_DOUBLEBUFFER;
00206 }
00207 
00208 
00209 
00210 /* void allegro_gl_set(int option, int value) */
00274 void allegro_gl_set(int option, int value)
00275 {
00276     switch (option) {
00277             /* Options stating importance of other options */
00278         case AGL_REQUIRE:
00279             __allegro_gl_required_settings |= value;
00280             __allegro_gl_suggested_settings &= ~value;
00281             break;
00282         case AGL_SUGGEST:
00283             __allegro_gl_suggested_settings |= value;
00284             __allegro_gl_required_settings &= ~value;
00285             break;
00286         case AGL_DONTCARE:
00287             __allegro_gl_required_settings &= ~value;
00288             __allegro_gl_suggested_settings &= ~value;
00289             break;
00290 
00291             /* Options configuring the mode set */
00292         case AGL_ALLEGRO_FORMAT:
00293             allegro_gl_display_info.allegro_format = value;
00294             break;
00295         case AGL_RED_DEPTH:
00296             allegro_gl_display_info.pixel_size.rgba.r = value;
00297             break;
00298         case AGL_GREEN_DEPTH:
00299             allegro_gl_display_info.pixel_size.rgba.g = value;
00300             break;
00301         case AGL_BLUE_DEPTH:
00302             allegro_gl_display_info.pixel_size.rgba.b = value;
00303             break;
00304         case AGL_ALPHA_DEPTH:
00305             allegro_gl_display_info.pixel_size.rgba.a = value;
00306             break;
00307         case AGL_COLOR_DEPTH:
00308             switch (value) {
00309                 case 8:
00310                     allegro_gl_set(AGL_RED_DEPTH, 3);
00311                     allegro_gl_set(AGL_GREEN_DEPTH, 3);
00312                     allegro_gl_set(AGL_BLUE_DEPTH, 2);
00313                     allegro_gl_set(AGL_ALPHA_DEPTH, 0);
00314                     break;
00315                 case 15:
00316                     allegro_gl_set(AGL_RED_DEPTH, 5);
00317                     allegro_gl_set(AGL_GREEN_DEPTH, 5);
00318                     allegro_gl_set(AGL_BLUE_DEPTH, 5);
00319                     allegro_gl_set(AGL_ALPHA_DEPTH, 1);
00320                     break;
00321                 case 16:
00322                     allegro_gl_set(AGL_RED_DEPTH, 5);
00323                     allegro_gl_set(AGL_GREEN_DEPTH, 6);
00324                     allegro_gl_set(AGL_BLUE_DEPTH, 5);
00325                     allegro_gl_set(AGL_ALPHA_DEPTH, 0);
00326                     break;
00327                 case 24:
00328                 case 32:
00329                     allegro_gl_set(AGL_RED_DEPTH, 8);
00330                     allegro_gl_set(AGL_GREEN_DEPTH, 8);
00331                     allegro_gl_set(AGL_BLUE_DEPTH, 8);
00332                     allegro_gl_set(AGL_ALPHA_DEPTH, value-24);
00333                     break;
00334             }
00335             allegro_gl_display_info.colour_depth = value;
00336             break;
00337         case AGL_ACC_RED_DEPTH:
00338             allegro_gl_display_info.accum_size.rgba.r = value;
00339             break;
00340         case AGL_ACC_GREEN_DEPTH:
00341             allegro_gl_display_info.accum_size.rgba.g = value;
00342             break;
00343         case AGL_ACC_BLUE_DEPTH:
00344             allegro_gl_display_info.accum_size.rgba.b = value;
00345             break;
00346         case AGL_ACC_ALPHA_DEPTH:
00347             allegro_gl_display_info.accum_size.rgba.a = value;
00348             break;
00349 
00350         case AGL_DOUBLEBUFFER:
00351             allegro_gl_display_info.doublebuffered = value;
00352             break;
00353         case AGL_STEREO:
00354             allegro_gl_display_info.stereo = value;
00355             break;
00356         case AGL_AUX_BUFFERS:
00357             allegro_gl_display_info.aux_buffers = value;
00358             break;
00359         case AGL_Z_DEPTH:
00360             allegro_gl_display_info.depth_size = value;
00361             break;
00362         case AGL_STENCIL_DEPTH:
00363             allegro_gl_display_info.stencil_size = value;
00364             break;
00365 
00366         case AGL_WINDOW_X:
00367             allegro_gl_display_info.x = value;
00368             break;
00369         case AGL_WINDOW_Y:
00370             allegro_gl_display_info.y = value;
00371             break;
00372 
00373         case AGL_RENDERMETHOD:
00374             allegro_gl_display_info.rmethod = value;
00375             break;
00376 
00377         case AGL_FULLSCREEN:
00378             allegro_gl_display_info.fullscreen = value;
00379             break;
00380 
00381         case AGL_WINDOWED:
00382             allegro_gl_display_info.fullscreen = !value;
00383             break;
00384         case AGL_VIDEO_MEMORY_POLICY:
00385             if ((value == AGL_KEEP) || (value == AGL_RELEASE))
00386                 allegro_gl_display_info.vidmem_policy = value;
00387             break;
00388         case AGL_SAMPLE_BUFFERS:
00389             allegro_gl_display_info.sample_buffers = value;
00390             break;
00391         case AGL_SAMPLES:
00392             allegro_gl_display_info.samples = value;
00393             break;
00394         case AGL_FLOAT_COLOR:
00395             allegro_gl_display_info.float_color = value;
00396             break;
00397         case AGL_FLOAT_Z:
00398             allegro_gl_display_info.float_depth = value;
00399             break;
00400     }
00401 }
00402 
00403 
00404 
00421 int allegro_gl_get(int option)
00422 {
00423     switch (option) {
00424             /* Options stating importance of other options */
00425         case AGL_REQUIRE:
00426             return __allegro_gl_required_settings;
00427         case AGL_SUGGEST:
00428             return __allegro_gl_suggested_settings;
00429         case AGL_DONTCARE:
00430             return ~0 & ~(__allegro_gl_required_settings |
00431                           __allegro_gl_suggested_settings);
00432 
00433             /* Options configuring the mode set */
00434         case AGL_ALLEGRO_FORMAT:
00435             return allegro_gl_display_info.allegro_format;
00436         case AGL_RED_DEPTH:
00437             return allegro_gl_display_info.pixel_size.rgba.r;
00438         case AGL_GREEN_DEPTH:
00439             return allegro_gl_display_info.pixel_size.rgba.g;
00440         case AGL_BLUE_DEPTH:
00441             return allegro_gl_display_info.pixel_size.rgba.b;
00442         case AGL_ALPHA_DEPTH:
00443             return allegro_gl_display_info.pixel_size.rgba.a;
00444         case AGL_COLOR_DEPTH:
00445             return allegro_gl_display_info.pixel_size.rgba.r
00446                 + allegro_gl_display_info.pixel_size.rgba.g
00447                 + allegro_gl_display_info.pixel_size.rgba.b
00448                 + allegro_gl_display_info.pixel_size.rgba.a;
00449         case AGL_ACC_RED_DEPTH:
00450             return allegro_gl_display_info.accum_size.rgba.r;
00451         case AGL_ACC_GREEN_DEPTH:
00452             return allegro_gl_display_info.accum_size.rgba.g;
00453         case AGL_ACC_BLUE_DEPTH:
00454             return allegro_gl_display_info.accum_size.rgba.b;
00455         case AGL_ACC_ALPHA_DEPTH:
00456             return allegro_gl_display_info.accum_size.rgba.a;
00457         case AGL_DOUBLEBUFFER:
00458             return allegro_gl_display_info.doublebuffered;
00459         case AGL_STEREO:
00460             return allegro_gl_display_info.stereo;
00461         case AGL_AUX_BUFFERS:
00462             return allegro_gl_display_info.aux_buffers;
00463         case AGL_Z_DEPTH:
00464             return allegro_gl_display_info.depth_size;
00465         case AGL_STENCIL_DEPTH:
00466             return allegro_gl_display_info.stencil_size;
00467         case AGL_WINDOW_X:
00468             return allegro_gl_display_info.x;
00469         case AGL_WINDOW_Y:
00470             return allegro_gl_display_info.y;
00471         case AGL_FULLSCREEN:
00472             return allegro_gl_display_info.fullscreen;
00473         case AGL_WINDOWED:
00474             return !allegro_gl_display_info.fullscreen;
00475         case AGL_VIDEO_MEMORY_POLICY:
00476             return allegro_gl_display_info.vidmem_policy;
00477         case AGL_SAMPLE_BUFFERS:
00478             return allegro_gl_display_info.sample_buffers;
00479         case AGL_SAMPLES:
00480             return allegro_gl_display_info.samples;
00481         case AGL_FLOAT_COLOR:
00482             return allegro_gl_display_info.float_color;
00483         case AGL_FLOAT_Z:
00484             return allegro_gl_display_info.float_depth;
00485     }
00486     return -1;
00487 }
00488 
00489 
00490 
00491 /* Builds a string corresponding to the options set in 'opt'
00492  * and writes in the config file
00493  */
00494 static void build_settings(int opt, char *section, char *name) {
00495     char buf[2048];
00496 
00497     usetc(buf, 0);
00498 
00499     if (opt & AGL_ALLEGRO_FORMAT)
00500         ustrcat(buf, "allegro_format ");
00501     if (opt & AGL_RED_DEPTH)
00502         ustrcat(buf, "red_depth ");
00503     if (opt & AGL_GREEN_DEPTH)
00504         ustrcat(buf, "green_depth ");
00505     if (opt & AGL_BLUE_DEPTH)
00506         ustrcat(buf, "blue_depth ");
00507     if (opt & AGL_ALPHA_DEPTH)
00508         ustrcat(buf, "alpha_depth ");
00509     if (opt & AGL_COLOR_DEPTH)
00510         ustrcat(buf, "color_depth ");
00511     if (opt & AGL_ACC_RED_DEPTH)
00512         ustrcat(buf, "accum_red_depth ");
00513     if (opt & AGL_ACC_GREEN_DEPTH)
00514         ustrcat(buf, "accum_green_depth ");
00515     if (opt & AGL_ACC_BLUE_DEPTH)
00516         ustrcat(buf, "accum_blue_depth ");
00517     if (opt & AGL_ACC_ALPHA_DEPTH)
00518         ustrcat(buf, "accum_alpha_depth ");
00519     if (opt & AGL_DOUBLEBUFFER)
00520         ustrcat(buf, "double_buffer ");
00521     if (opt & AGL_STEREO)
00522         ustrcat(buf, "stereo_display ");
00523     if (opt & AGL_AUX_BUFFERS)
00524         ustrcat(buf, "aux_buffers ");
00525     if (opt & AGL_Z_DEPTH)
00526         ustrcat(buf, "z_depth ");
00527     if (opt & AGL_STENCIL_DEPTH)
00528         ustrcat(buf, "stencil_depth ");
00529     if (opt & AGL_WINDOW_X)
00530         ustrcat(buf, "window_x ");
00531     if (opt & AGL_WINDOW_Y)
00532         ustrcat(buf, "window_y ");
00533     if (opt & AGL_FULLSCREEN)
00534         ustrcat(buf, "fullscreen ");
00535     if (opt & AGL_WINDOWED)
00536         ustrcat(buf, "windowed ");
00537     if (opt & AGL_VIDEO_MEMORY_POLICY)
00538         ustrcat(buf, "video_memory_policy ");
00539     if (opt & AGL_SAMPLE_BUFFERS)
00540         ustrcat(buf, "sample_buffers ");
00541     if (opt & AGL_SAMPLES)
00542         ustrcat(buf, "samples ");
00543     if (opt & AGL_FLOAT_COLOR)
00544         ustrcat(buf, "float_color ");
00545     if (opt & AGL_FLOAT_Z)
00546         ustrcat(buf, "float_depth ");
00547         
00548     set_config_string(section, name, buf);
00549 }
00550 
00551 
00552 
00553 /* void allegro_gl_save_settings() */
00560 void allegro_gl_save_settings() {
00561 
00562     char *section = "OpenGL";
00563     int save = allegro_gl_get(AGL_REQUIRE) | allegro_gl_get(AGL_SUGGEST);
00564     
00565     if (save & AGL_ALLEGRO_FORMAT)
00566         set_config_int(section, "allegro_format",
00567             allegro_gl_get(AGL_ALLEGRO_FORMAT));
00568     if (save & AGL_RED_DEPTH)
00569         set_config_int(section, "red_depth",
00570             allegro_gl_get(AGL_RED_DEPTH));
00571     if (save & AGL_GREEN_DEPTH)
00572         set_config_int(section, "green_depth",
00573             allegro_gl_get(AGL_GREEN_DEPTH));
00574     if (save & AGL_BLUE_DEPTH)
00575         set_config_int(section, "blue_depth",
00576             allegro_gl_get(AGL_BLUE_DEPTH));
00577     if (save & AGL_ALPHA_DEPTH)
00578         set_config_int(section, "alpha_depth",
00579             allegro_gl_get(AGL_ALPHA_DEPTH));
00580     if (save & AGL_COLOR_DEPTH)
00581         set_config_int(section, "color_depth",
00582             allegro_gl_get(AGL_COLOR_DEPTH));
00583     if (save & AGL_ACC_RED_DEPTH)
00584         set_config_int(section, "accum_red_depth",
00585             allegro_gl_get(AGL_ACC_RED_DEPTH));
00586     if (save & AGL_ACC_GREEN_DEPTH)
00587         set_config_int(section, "accum_green_depth",
00588             allegro_gl_get(AGL_ACC_GREEN_DEPTH));
00589     if (save & AGL_ACC_BLUE_DEPTH)
00590         set_config_int(section, "accum_blue_depth",
00591             allegro_gl_get(AGL_ACC_BLUE_DEPTH));
00592     if (save & AGL_ACC_ALPHA_DEPTH)
00593         set_config_int(section, "accum_alpha_depth",
00594             allegro_gl_get(AGL_ACC_ALPHA_DEPTH));
00595     if (save & AGL_DOUBLEBUFFER)
00596         set_config_int(section, "double_buffer",
00597             allegro_gl_get(AGL_DOUBLEBUFFER));
00598     if (save & AGL_STEREO)
00599         set_config_int(section, "stereo_display",
00600             allegro_gl_get(AGL_STEREO));
00601     if (save & AGL_AUX_BUFFERS)
00602         set_config_int(section, "aux_buffers",
00603             allegro_gl_get(AGL_AUX_BUFFERS));
00604     if (save & AGL_Z_DEPTH)
00605         set_config_int(section, "z_depth",
00606             allegro_gl_get(AGL_Z_DEPTH));
00607     if (save & AGL_STENCIL_DEPTH)
00608         set_config_int(section, "stencil_depth",
00609             allegro_gl_get(AGL_STENCIL_DEPTH));
00610     if (save & AGL_WINDOW_X)
00611         set_config_int(section, "window_x",
00612             allegro_gl_get(AGL_WINDOW_X));
00613     if (save & AGL_WINDOW_Y)
00614         set_config_int(section, "window_y",
00615             allegro_gl_get(AGL_WINDOW_Y));
00616     if (save & AGL_FULLSCREEN)
00617         set_config_int(section, "fullscreen",
00618             allegro_gl_get(AGL_FULLSCREEN));
00619     if (save & AGL_WINDOWED)
00620         set_config_int(section, "windowed",
00621             allegro_gl_get(AGL_WINDOWED));
00622     if (save & AGL_VIDEO_MEMORY_POLICY)
00623         set_config_int(section, "video_memory_policy",
00624             allegro_gl_get(AGL_VIDEO_MEMORY_POLICY));
00625     if (save & AGL_SAMPLE_BUFFERS)
00626         set_config_int(section, "sample_buffers",
00627                        allegro_gl_get(AGL_SAMPLE_BUFFERS));
00628     if (save & AGL_SAMPLES)
00629         set_config_int(section, "samples",
00630                        allegro_gl_get(AGL_SAMPLES));
00631     if (save & AGL_FLOAT_COLOR)
00632         set_config_int(section, "float_color",
00633                        allegro_gl_get(AGL_FLOAT_COLOR));
00634     if (save & AGL_FLOAT_Z)
00635         set_config_int(section, "float_depth",
00636                        allegro_gl_get(AGL_FLOAT_Z));
00637 
00638     if (save & AGL_REQUIRE)
00639         build_settings(allegro_gl_get(AGL_REQUIRE), section, "require");
00640     if (save & AGL_SUGGEST)
00641         build_settings(allegro_gl_get(AGL_SUGGEST), section, "suggest");
00642 }
00643 
00644 
00645 
00646 /* Parses an input string to read settings */
00647 static void agl_parse_section(int sec, char *section, char *name) {
00648     const char *end;
00649     char *buf;
00650     char *ptr;
00651     int strsize;
00652     int opt = 0;
00653 
00654     end = get_config_string(section, name, "");
00655     strsize = ustrsizez(end);
00656     
00657     buf = (char*)malloc(sizeof(char) * strsize);
00658     
00659     if (!buf) {
00660         TRACE(PREFIX_E "parse_section: Ran out of memory "
00661               "while trying to allocate %i bytes!",
00662               (int)sizeof(char) * strsize);
00663         return;
00664     }
00665 
00666     memcpy(buf, end, strsize);
00667     end = buf + strsize;
00668     ptr = buf;
00669 
00670     while (ptr < end) {
00671         char *s = ustrtok_r(ptr, " ;|+", &ptr);
00672         
00673         if (!ustrcmp(s, "allegro_format"))
00674             opt |= AGL_ALLEGRO_FORMAT;
00675         if (!ustrcmp(s, "red_depth"))
00676             opt |= AGL_RED_DEPTH;
00677         if (!ustrcmp(s, "green_depth"))
00678             opt |= AGL_GREEN_DEPTH;
00679         if (!ustrcmp(s, "blue_depth"))
00680             opt |= AGL_BLUE_DEPTH;
00681         if (!ustrcmp(s, "alpha_depth"))
00682             opt |= AGL_ALPHA_DEPTH;
00683         if (!ustrcmp(s, "color_depth"))
00684             opt |= AGL_COLOR_DEPTH;
00685         if (!ustrcmp(s, "accum_red_depth"))
00686             opt |= AGL_ACC_RED_DEPTH;
00687         if (!ustrcmp(s, "accum_green_depth"))
00688             opt |= AGL_ACC_GREEN_DEPTH;
00689         if (!ustrcmp(s, "accum_blue_depth"))
00690             opt |= AGL_ACC_BLUE_DEPTH;
00691         if (!ustrcmp(s, "accum_alpha_depth"))
00692             opt |= AGL_ACC_ALPHA_DEPTH;
00693         if (!ustrcmp(s, "double_buffer"))
00694             opt |= AGL_DOUBLEBUFFER;
00695         if (!ustrcmp(s, "stereo_display"))
00696             opt |= AGL_STEREO;
00697         if (!ustrcmp(s, "aux_buffers"))
00698             opt |= AGL_AUX_BUFFERS;
00699         if (!ustrcmp(s, "z_depth"))
00700             opt |= AGL_Z_DEPTH;
00701         if (!ustrcmp(s, "stencil_depth"))
00702             opt |= AGL_STENCIL_DEPTH;
00703         if (!ustrcmp(s, "window_x"))
00704             opt |= AGL_WINDOW_X;
00705         if (!ustrcmp(s, "window_y"))
00706             opt |= AGL_WINDOW_Y;
00707         if (!ustrcmp(s, "fullscreen"))
00708             opt |= AGL_FULLSCREEN;
00709         if (!ustrcmp(s, "windowed"))
00710             opt |= AGL_WINDOWED;
00711         if (!ustrcmp(s, "video_memory_policy"))
00712             opt |= AGL_VIDEO_MEMORY_POLICY;
00713         if (!ustrcmp(s, "sample_buffers"))
00714             opt |= AGL_SAMPLE_BUFFERS;
00715         if (!ustrcmp(s, "samples"))
00716             opt |= AGL_SAMPLES;
00717         if (!ustrcmp(s, "float_color"))
00718             opt |= AGL_FLOAT_COLOR;
00719         if (!ustrcmp(s, "float_depth"))
00720             opt |= AGL_FLOAT_Z;
00721     }
00722     
00723     free(buf);
00724     
00725     allegro_gl_set(sec, opt);
00726 }
00727 
00728 
00729 
00730 /* void allegro_gl_load_settings() */
00741 void allegro_gl_load_settings() {
00742 
00743     int set;
00744     char *section = "OpenGL";
00745     
00746     set = get_config_int(section, "allegro_format", -1);
00747     if (set != -1)
00748         allegro_gl_set(AGL_ALLEGRO_FORMAT, set);
00749     set = get_config_int(section, "red_depth", -1);
00750     if (set != -1)
00751         allegro_gl_set(AGL_RED_DEPTH, set);
00752     set = get_config_int(section, "green_depth", -1);
00753     if (set != -1)
00754         allegro_gl_set(AGL_GREEN_DEPTH, set);
00755     set = get_config_int(section, "blue_depth", -1);
00756     if (set != -1)
00757         allegro_gl_set(AGL_BLUE_DEPTH, set);
00758     set = get_config_int(section, "alpha_depth", -1);
00759     if (set != -1)
00760         allegro_gl_set(AGL_ALPHA_DEPTH, set);
00761     set = get_config_int(section, "color_depth", -1);
00762     if (set != -1)
00763         allegro_gl_set(AGL_COLOR_DEPTH, set);
00764     set = get_config_int(section, "accum_red_depth", -1);
00765     if (set != -1)
00766         allegro_gl_set(AGL_ACC_RED_DEPTH, set);
00767     set = get_config_int(section, "accum_green_depth", -1);
00768     if (set != -1)
00769         allegro_gl_set(AGL_ACC_GREEN_DEPTH, set);
00770     set = get_config_int(section, "accum_blue_depth", -1);
00771     if (set != -1)
00772         allegro_gl_set(AGL_ACC_BLUE_DEPTH, set);
00773     set = get_config_int(section, "accum_alpha_depth", -1);
00774     if (set != -1)
00775         allegro_gl_set(AGL_ACC_ALPHA_DEPTH, set);
00776     set = get_config_int(section, "double_buffer", -1);
00777     if (set != -1)
00778         allegro_gl_set(AGL_DOUBLEBUFFER, set);
00779     set = get_config_int(section, "stereo_display", -1);
00780     if (set != -1)
00781         allegro_gl_set(AGL_STEREO, set);
00782     set = get_config_int(section, "aux_buffers", -1);
00783     if (set != -1)
00784         allegro_gl_set(AGL_AUX_BUFFERS, set);
00785     set = get_config_int(section, "z_depth", -1);
00786     if (set != -1)
00787         allegro_gl_set(AGL_Z_DEPTH, set);
00788     set = get_config_int(section, "stencil_depth", -1);
00789     if (set != -1)
00790         allegro_gl_set(AGL_STENCIL_DEPTH, set);
00791     set = get_config_int(section, "window_x", -1);
00792     if (set != -1)
00793         allegro_gl_set(AGL_WINDOW_X, set);
00794     set = get_config_int(section, "window_y", -1);
00795     if (set != -1)
00796         allegro_gl_set(AGL_WINDOW_Y, set);
00797     set = get_config_int(section, "fullscreen", -1);
00798     if (set != -1)
00799         allegro_gl_set(AGL_FULLSCREEN, set);
00800     set = get_config_int(section, "windowed", -1);
00801     if (set != -1)
00802         allegro_gl_set(AGL_WINDOWED, set);
00803     set = get_config_int(section, "video_memory_policy", -1);
00804     if (set != -1)
00805         allegro_gl_set(AGL_VIDEO_MEMORY_POLICY, set);
00806     set = get_config_int(section, "sample_buffers", -1);
00807     if (set != -1)
00808         allegro_gl_set(AGL_SAMPLE_BUFFERS, set);
00809     set = get_config_int(section, "samples", -1);
00810     if (set != -1)
00811         allegro_gl_set(AGL_SAMPLES, set);
00812     set = get_config_int(section, "float_color", -1);
00813     if (set != -1)
00814         allegro_gl_set(AGL_FLOAT_COLOR, set);
00815     set = get_config_int(section, "float_depth", -1);
00816     if (set != -1)
00817         allegro_gl_set(AGL_FLOAT_Z, set);
00818     
00819     agl_parse_section(AGL_REQUIRE, section, "require");
00820     agl_parse_section(AGL_SUGGEST, section, "suggest");
00821 }
00822 
00823 
00824 
00825 /* int install_allegro_gl(void) */
00836 int install_allegro_gl(void)
00837 {
00838     if (!system_driver)
00839         return -1;
00840 
00841     if (atexit(remove_allegro_gl))
00842         return -1;
00843     
00844     if (system_driver->gfx_drivers)
00845         saved_gfx_drivers = system_driver->gfx_drivers;
00846     else
00847         saved_gfx_drivers = list_saved_gfx_drivers;
00848     
00849     system_driver->gfx_drivers = our_gfx_drivers;
00850 
00851     allegro_gl_clear_settings();
00852 
00853     /* Save and replace old blit_between_formats methods */
00854 #ifdef ALLEGRO_COLOR8
00855     __blit_between_formats8 = __linear_vtable8.blit_between_formats;
00856     __linear_vtable8.blit_between_formats =
00857                                          allegro_gl_memory_blit_between_formats;
00858 #endif
00859 #ifdef ALLEGRO_COLOR16
00860     __blit_between_formats15 = __linear_vtable15.blit_between_formats;
00861     __linear_vtable15.blit_between_formats =
00862                                          allegro_gl_memory_blit_between_formats;
00863     __blit_between_formats16 = __linear_vtable16.blit_between_formats;
00864     __linear_vtable16.blit_between_formats
00865                                        = allegro_gl_memory_blit_between_formats;
00866 #endif
00867 #ifdef ALLEGRO_COLOR24
00868     __blit_between_formats24 = __linear_vtable24.blit_between_formats;
00869     __linear_vtable24.blit_between_formats
00870                                        = allegro_gl_memory_blit_between_formats;
00871 #endif
00872 #ifdef ALLEGRO_COLOR32
00873     __blit_between_formats32 = __linear_vtable32.blit_between_formats;
00874     __linear_vtable32.blit_between_formats
00875                                        = allegro_gl_memory_blit_between_formats;
00876 #endif
00877 
00878     usetc(allegro_gl_error, 0);
00879     
00880     return 0;
00881 }
00882 
00883 
00884 
00885 /* void remove_allegro_gl(void) */
00894 void remove_allegro_gl(void)
00895 {
00896     if ((!system_driver) || (!saved_gfx_drivers))
00897         return;
00898 
00899     if (saved_gfx_drivers == &list_saved_gfx_drivers)
00900         system_driver->gfx_drivers = NULL;
00901     else
00902         system_driver->gfx_drivers = saved_gfx_drivers;
00903 
00904     /* This function may be called twice (once by a user explicit call
00905      * and once again at exit since the function is registered with at_exit)
00906      * In order to prevent crashes, 'saved_gfx_drivers' is set to NULL
00907      */
00908     saved_gfx_drivers = NULL;
00909 
00910     /* Restore the blit_between_formats methods */
00911     #ifdef ALLEGRO_COLOR8
00912     __linear_vtable8.blit_between_formats = __blit_between_formats8;
00913     #endif
00914     #ifdef ALLEGRO_COLOR16
00915     __linear_vtable15.blit_between_formats = __blit_between_formats15;
00916     __linear_vtable16.blit_between_formats = __blit_between_formats16;
00917     #endif
00918     #ifdef ALLEGRO_COLOR24
00919     __linear_vtable24.blit_between_formats = __blit_between_formats24;
00920     #endif
00921     #ifdef ALLEGRO_COLOR32
00922     __linear_vtable32.blit_between_formats = __blit_between_formats32;
00923     #endif
00924 }
00925 
00926 
00927 
00928 /* void allegro_gl_flip(void) */
00951 void allegro_gl_flip(void)
00952 {
00953     __allegro_gl_driver->flip();
00954 }
00955 
00956 
00957 
00958 /* float allegro_gl_opengl_version() */
00971 float allegro_gl_opengl_version() {
00972     
00973     const char *str;
00974     
00975     if (!__allegro_gl_valid_context)
00976         return 0.0f;
00977     
00978     str = (const char*)glGetString(GL_VERSION);
00979 
00980     if ((strncmp(str, "1.0 ", 4) == 0) || (strncmp(str, "1.0.0 ", 6) == 0))
00981         return 1.0;
00982     if ((strncmp(str, "1.1 ", 4) == 0) || (strncmp(str, "1.1.0 ", 6) == 0))
00983         return 1.1;
00984     if ((strncmp(str, "1.2 ", 4) == 0) || (strncmp(str, "1.2.0 ", 6) == 0))
00985         return 1.2;
00986     if ((strncmp(str, "1.2.1 ", 6) == 0))
00987         return 1.21;
00988     if ((strncmp(str, "1.2.2 ", 6) == 0))
00989         return 1.22;
00990     if ((strncmp(str, "1.3 ", 4) == 0) || (strncmp(str, "1.3.0 ", 6) == 0))
00991         return 1.3;
00992     if ((strncmp(str, "1.4 ", 4) == 0) || (strncmp(str, "1.4.0 ", 6) == 0))
00993         return 1.4;
00994     if ((strncmp(str, "1.5 ", 4) == 0) || (strncmp(str, "1.5.0 ", 6) == 0))
00995         return 1.5;
00996     if ((strncmp(str, "2.0 ", 4) == 0) || (strncmp(str, "2.0.0 ", 6) == 0))
00997         return 2.0;
00998     if ((strncmp(str, "2.1 ", 4) == 0) || (strncmp(str, "2.1.0 ", 6) == 0))
00999         return 2.1;
01000     if ((strncmp(str, "3.0 ", 4) == 0) || (strncmp(str, "3.0.0 ", 6) == 0))
01001         return 3.0;
01002 
01003     /* The OpenGL driver does not return a version
01004      * number. However it probably supports at least OpenGL 1.0
01005      */ 
01006     if (!str) {
01007         return 1.0;
01008     }
01009     
01010     return atof(str);
01011 }
01012 
01013 
01014 
01015 void __allegro_gl_set_allegro_image_format(int big_endian)
01016 {
01017     /* Sets up Allegro to use OpenGL formats */
01018     _rgb_r_shift_15 = 11;
01019     _rgb_g_shift_15 = 6;
01020     _rgb_b_shift_15 = 1;
01021 
01022     _rgb_r_shift_16 = 11;
01023     _rgb_g_shift_16 = 5;
01024     _rgb_b_shift_16 = 0;
01025 
01026     if (big_endian) {
01027         _rgb_r_shift_24 = 16;
01028         _rgb_g_shift_24 = 8;
01029         _rgb_b_shift_24 = 0;
01030 
01031         _rgb_a_shift_32 = 0;
01032         _rgb_r_shift_32 = 24;
01033         _rgb_g_shift_32 = 16;
01034         _rgb_b_shift_32 = 8;
01035     }
01036     else {
01037         _rgb_r_shift_24 = 0;
01038         _rgb_g_shift_24 = 8;
01039         _rgb_b_shift_24 = 16;
01040 
01041         _rgb_r_shift_32 = 0;
01042         _rgb_g_shift_32 = 8;
01043         _rgb_b_shift_32 = 16;
01044         _rgb_a_shift_32 = 24;
01045     }
01046 
01047     return;
01048 }
01049 
01050 
01051 
01052 /* allegro_gl_default_init:
01053  *  Sets a graphics mode according to the mode (fullscreen or windowed)
01054  *  requested by the user. If it fails to set up the mode then it tries
01055  *  (if available) the other one unless the user has "AGL_REQUIRED" the mode.
01056  */
01057 static BITMAP *allegro_gl_default_gfx_init(int w, int h, int vw, int vh,
01058                                                                      int depth)
01059 {
01060     BITMAP* bmp = NULL;
01061     
01062     if (allegro_gl_display_info.fullscreen) {
01063         TRACE(PREFIX_I "default_gfx_init: Trying to set up fullscreen mode.\n");
01064         
01065 #ifdef GFX_OPENGL_FULLSCREEN
01066         /* Looks for fullscreen mode in our_driver_list */
01067         gfx_driver = &gfx_allegro_gl_fullscreen;
01068 
01069         if (__allegro_gl_required_settings & AGL_FULLSCREEN)
01070             /* Fullscreen mode required and found */
01071             return gfx_allegro_gl_fullscreen.init(w, h, vw, vh, depth);
01072         else
01073             bmp = gfx_allegro_gl_fullscreen.init(w, h, vw, vh, depth);
01074         
01075         if (bmp)
01076             /* Fullscreen mode found but not required (probably suggested) */
01077             return bmp;
01078 
01079 #endif /*GFX_OPENGL_FULLSCREEN*/
01080 
01081         /* Fullscreen mode not available but not required :
01082          * let's try windowed mode :
01083          */
01084         TRACE(PREFIX_I "default_gfx_init: Failed to set up fullscreen mode!\n");
01085 #ifdef GFX_OPENGL_WINDOWED
01086         TRACE(PREFIX_I "default_gfx_init: Trying windowed mode...\n");
01087         allegro_gl_display_info.fullscreen = FALSE;
01088         gfx_driver = &gfx_allegro_gl_windowed;
01089         return gfx_allegro_gl_windowed.init(w, h, vw, vh, depth);
01090 #else
01091         return NULL;
01092 #endif /* GFX_OPENGL_WINDOWED */
01093     }
01094     else {
01095         TRACE(PREFIX_I "default_gfx_init: Trying to set up windowed mode...\n");
01096         
01097 #ifdef GFX_OPENGL_WINDOWED
01098         /* Looks for windowed mode in our_driver_list */
01099         gfx_driver = &gfx_allegro_gl_windowed;
01100 
01101         if (__allegro_gl_required_settings & AGL_WINDOWED)
01102             /* Windowed mode required and found */
01103             return gfx_allegro_gl_windowed.init(w, h, vw, vh, depth);
01104         else
01105             bmp = gfx_allegro_gl_windowed.init(w, h, vw, vh, depth);
01106         
01107         if (bmp)
01108             /* Windowed mode found but not required (probably suggested) */
01109             return bmp;
01110 
01111 #endif /* GFX_OPENGL_WINDOWED */
01112 
01113         /* Windowed mode not available but not required :
01114          * let's try fullscreen mode :
01115          */
01116         TRACE(PREFIX_I "default_gfx_init: Failed to set up windowed mode...\n");
01117 #ifdef GFX_OPENGL_FULLSCREEN
01118         TRACE(PREFIX_I "default_gfx_init: Trying fullscreen mode...\n");
01119         allegro_gl_display_info.fullscreen = TRUE;
01120         gfx_driver = &gfx_allegro_gl_fullscreen;
01121         return gfx_allegro_gl_fullscreen.init(w, h, vw, vh, depth);
01122 #else
01123         return NULL;
01124 #endif /*GFX_OPENGL_FULLSCREEN*/
01125     }
01126 }
01127 
01128 
01129 
01130 /* allegro_gl_set_blender_mode (GFX_DRIVER vtable entry):
01131  * Sets the blending mode. Same implementation to all GFX vtables.
01132  */
01133 void allegro_gl_set_blender_mode(int mode, int r, int g, int b, int a) {
01134     __allegro_gl_blit_operation = AGL_OP_BLEND;
01135     /* These blenders do not need any special extensions. 
01136      * We specify only pixel arithmetic here. Blend equation and blend
01137      * color (if available) are reset to defualt later.*/
01138     switch (mode) {
01139         case blender_mode_none:
01140             glBlendFunc(GL_ONE, GL_ZERO);
01141         break;
01142         case blender_mode_alpha:
01143             glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
01144         break;
01145         case blender_mode_invert:
01146             glLogicOp(GL_COPY_INVERTED);
01147             __allegro_gl_blit_operation = AGL_OP_LOGIC_OP;
01148         break;
01149         case blender_mode_multiply:
01150             glBlendFunc(GL_DST_COLOR, GL_ZERO);
01151         break;
01152     }
01153     
01154     if (allegro_gl_opengl_version() >= 1.4 ||
01155        (allegro_gl_opengl_version() >= 1.2 &&
01156         allegro_gl_is_extension_supported("GL_ARB_imaging"))) {
01157         /* We're running a recent version of OpenGL and everything needed is here. */
01158         
01159         glBlendColor(r / 255.f, g / 255.f, b / 255.f, a / 255.f);
01160 
01161         switch (mode) {
01162             case blender_mode_none:
01163                 glBlendEquation(GL_FUNC_ADD);
01164             break;
01165             case blender_mode_alpha:
01166                 glBlendEquation(GL_FUNC_ADD);
01167             break;
01168             case blender_mode_trans:
01169                 glBlendEquation(GL_FUNC_ADD);
01170                 glBlendFunc(GL_CONSTANT_ALPHA, GL_ONE_MINUS_CONSTANT_ALPHA);
01171             break;
01172             case blender_mode_add:
01173                 glBlendEquation(GL_FUNC_ADD);
01174                 glBlendFunc(GL_CONSTANT_ALPHA, GL_ONE);
01175             break;
01176             case blender_mode_burn:
01177                 glBlendEquation(GL_FUNC_SUBTRACT);
01178                 glBlendFunc(GL_ONE, GL_CONSTANT_ALPHA);
01179             break;
01180             case blender_mode_dodge:
01181                 glBlendEquation(GL_FUNC_ADD);
01182                 glBlendFunc(GL_ONE, GL_CONSTANT_ALPHA);
01183             break;
01184             case blender_mode_multiply:
01185                 glBlendEquation(GL_FUNC_ADD);
01186             break;
01187         }
01188 
01189         return;
01190     }
01191     
01192     /* Check for presence of glBlendColor() and special parameters to
01193      * glBlendFunc(). */
01194     if (allegro_gl_is_extension_supported("GL_EXT_blend_color")) {
01195         glBlendColorEXT(r / 255.f, g / 255.f, b / 255.f, a / 255.f);
01196 
01197         switch (mode) {
01198             case blender_mode_trans:
01199                 glBlendFunc(GL_CONSTANT_ALPHA_EXT, GL_ONE_MINUS_CONSTANT_ALPHA_EXT);
01200             break;
01201             case blender_mode_add:
01202                 glBlendFunc(GL_CONSTANT_ALPHA_EXT, GL_ONE);
01203             break;
01204             case blender_mode_burn:
01205                 glBlendFunc(GL_ONE, GL_CONSTANT_ALPHA_EXT);
01206             break;
01207             case blender_mode_dodge:
01208                 glBlendFunc(GL_ONE, GL_CONSTANT_ALPHA_EXT);
01209             break;
01210         }
01211     }
01212     else if (mode == blender_mode_trans ||
01213              mode == blender_mode_add ||
01214              mode == blender_mode_burn ||
01215              mode == blender_mode_dodge) {
01216         /* glBlendColor() is not available and it is needed by the selected
01217          * bledner. Bail out.*/
01218         return;
01219     }
01220 
01221     /* Check for presence of glBlendEquation(). */
01222     if (allegro_gl_is_extension_supported("GL_EXT_blend_minmax")) {
01223         switch (mode) {
01224             case blender_mode_none:
01225                 glBlendEquationEXT(GL_FUNC_ADD_EXT);
01226             break;
01227             case blender_mode_alpha:
01228                 glBlendEquationEXT(GL_FUNC_ADD_EXT);
01229             break;
01230             case blender_mode_trans:
01231                 glBlendEquationEXT(GL_FUNC_ADD_EXT);
01232             break;
01233             case blender_mode_add:
01234                 glBlendEquationEXT(GL_FUNC_ADD_EXT);
01235             break;
01236             case blender_mode_dodge:
01237                 glBlendEquationEXT(GL_FUNC_ADD_EXT);
01238             break;
01239             case blender_mode_multiply:
01240                 glBlendEquationEXT(GL_FUNC_ADD_EXT);
01241             break;
01242             case blender_mode_burn:
01243                 if (allegro_gl_is_extension_supported("GL_EXT_blend_subtract")) {
01244                     glBlendEquationEXT(GL_FUNC_SUBTRACT_EXT);
01245                 }
01246                 else {
01247                     /* GL_FUNC_SUBTRACT is not supported and it is needed by the
01248                      * selected blender. Bail out. */
01249                     return;
01250                 }
01251             break;
01252         }
01253     }
01254 }
01255 
01256 
01257 #ifdef DEBUGMODE
01258 #ifdef LOGLEVEL
01259 
01260 void __allegro_gl_log(int level, const char *str)
01261 {
01262     if (level <= LOGLEVEL)
01263         TRACE(PREFIX_L "[%d] %s", level, str);
01264 }
01265 
01266 #endif
01267 #endif
01268 
allegro4.4-4.4.2/addons/allegrogl/docs/html/alleggl_8h.html000066400000000000000000001254321173507505700234250ustar00rootroot00000000000000 AllegroGL: alleggl.h File Reference

alleggl.h File Reference

Main header file for AllegroGL. More...

#include <allegro.h>
#include <GL/gl.h>
#include "allegrogl/gl_ext.h"

Go to the source code of this file.

Defines

  • #define _AGL_DLL
  • #define AGL_VAR(type, name)   extern _AGL_DLL type name
  • #define AGL_FUNC(type, name, args)   extern type name args
  • #define __glext_h_
  • #define __glxext_h_
  • #define AGL_ERROR_SIZE   256
  • #define AGL_FLOAT_COLOR   0x00800000
    Floating-point Color buffer.
  • #define AGL_FLOAT_Z   0x01000000
    Floating-point Depth buffer.
  • #define AGL_CONFIG_RESRVED   0xA000000
Version Information
Frame Buffer Settings
  • #define AGL_ALLEGRO_FORMAT   0x00000001
    Use Allegro-compatible framebuffer.
  • #define AGL_RED_DEPTH   0x00000002
    Select the red depth of the frame buffer.
  • #define AGL_GREEN_DEPTH   0x00000004
    Select the green depth of the frame buffer.
  • #define AGL_BLUE_DEPTH   0x00000008
    Select the blue depth of the frame buffer.
  • #define AGL_ALPHA_DEPTH   0x00000010
    Select the alpha depth of the frame buffer.
  • #define AGL_COLOR_DEPTH   0x00000020
    Specify the total color depth of the frame buffer.
  • #define AGL_ACC_RED_DEPTH   0x00000040
    Select the red depth of the accumulator buffer.
  • #define AGL_ACC_GREEN_DEPTH   0x00000080
    Select the green depth of the accumulator buffer.
  • #define AGL_ACC_BLUE_DEPTH   0x00000100
    Select the blue depth of the accumulator buffer.
  • #define AGL_ACC_ALPHA_DEPTH   0x00000200
    Select the alpha depth of the accumulator buffer.
  • #define AGL_DOUBLEBUFFER   0x00000400
    Creates a backbuffer if set.
  • #define AGL_STEREO   0x00000800
    Creates seperate left/right buffers for stereo display.
  • #define AGL_AUX_BUFFERS   0x00001000
    Creates additional auxiliary buffers.
  • #define AGL_Z_DEPTH   0x00002000
    Select the depth of the z-buffer.
  • #define AGL_STENCIL_DEPTH   0x00004000
    Select the depth of the stencil buffer.
  • #define AGL_WINDOW_X   0x00008000
    Requests a placement of the window to a specified pixel location.
  • #define AGL_WINDOW_Y   0x00010000
    Same as AGL_WINDOW_X, but for the y-axis.
  • #define AGL_RENDERMETHOD   0x00020000
    Set it if you'd like AllegroGL to pay special attention on whether hardware acceleration is present or not.
  • #define AGL_FULLSCREEN   0x00040000
    Set if you'd like a full screen mode.
  • #define AGL_WINDOWED   0x00080000
    Set if you'd like a windowed mode.
  • #define AGL_VIDEO_MEMORY_POLICY   0x00100000
    Define AllegroGL's policy relative to video memory usage.
  • #define AGL_SAMPLE_BUFFERS   0x00200000
    Define multisample parameters Some OpenGL ICDs expose an extension called GL_ARB_multisample which provides a mechanism to anti-alias all GL primitives: points, lines, polygons, bitmaps and pixel rectangles.
  • #define AGL_SAMPLES   0x00400000
    Define multisample samples Set this value to the number of samples that can be accepted in the multisample buffers.
Mode selection priority options
  • #define AGL_DONTCARE   0
    Ignore these settings.
  • #define AGL_SUGGEST   -1
    Prefer the assigned values for these settings.
  • #define AGL_REQUIRE   -2
    Reject other values for these settings.
Video memory policy options
  • #define AGL_KEEP   1
    Keep internal texture in video memory.
  • #define AGL_RELEASE   2
    Release video memory occupied by internal texture.
Graphics drivers
OpenGL Extensions Management Functions

Functions

  • int algl_do_dialog (DIALOG *dialog, int focus_obj)
    AllegroGL-friendly version of do_dialog.
  • int algl_popup_dialog (DIALOG *dialog, int focus_obj)
    AllegroGL-friendly version of popup_dialog.
  • void algl_draw_mouse (void)
    Draws a mouse pointer on the screen.
  • void algl_set_mouse_drawer (void(*user_draw_mouse)(void))
    Sets (or clears) a user mouse drawing callback.
  • int algl_alert (AL_CONST char *s1, AL_CONST char *s2, AL_CONST char *s3, AL_CONST char *b1, AL_CONST char *b2, int c1, int c2)
    AllegroGL-friendly version of Allegro's alert.
  • int algl_alert3 (AL_CONST char *s1, AL_CONST char *s2, AL_CONST char *s3, AL_CONST char *b1, AL_CONST char *b2, AL_CONST char *b3, int c1, int c2, int c3)
    AllegroGL-friendly version of Allegro's alert3.
  • int d_algl_viewport_proc (int msg, DIALOG *d, int c)
    Creates a viewport object where OpenGL commands can be performed.
Mode selection functions
Video Bitmap Rountines
Allegro Interfacing routines
Matrix conversion routines
  • void allegro_gl_MATRIX_to_GLfloat (MATRIX *m, GLfloat gl[16])
    Converts an Allegro fixed-point matrix to an array of floats suitable for OpenGL's matrix operations.
  • void allegro_gl_MATRIX_to_GLdouble (MATRIX *m, GLdouble gl[16])
    Converts an Allegro fixed-point matrix to an array of doubles suitable for OpenGL's matrix operations.
  • void allegro_gl_MATRIX_f_to_GLfloat (MATRIX_f *m, GLfloat gl[16])
    Converts an Allegro floating-point matrix to an array of floats suitable for OpenGL's matrix operations.
  • void allegro_gl_MATRIX_f_to_GLdouble (MATRIX_f *m, GLdouble gl[16])
    Converts an Allegro floating-point matrix to an array of doubles suitable for OpenGL's matrix operations.
  • void allegro_gl_GLfloat_to_MATRIX (GLfloat gl[16], MATRIX *m)
    Converts an Allegro fixed-point matrix to an array of floats suitable for OpenGL's matrix operations.
  • void allegro_gl_GLdouble_to_MATRIX (GLdouble gl[16], MATRIX *m)
    Converts an Allegro fixed-point matrix to an array of floats suitable for OpenGL's matrix operations.
  • void allegro_gl_GLfloat_to_MATRIX_f (GLfloat gl[16], MATRIX_f *m)
    Converts an Allegro fixed-point matrix to an array of floats suitable for OpenGL's matrix operations.
  • void allegro_gl_GLdouble_to_MATRIX_f (GLdouble gl[16], MATRIX_f *m)
    Converts an Allegro fixed-point matrix to an array of floats suitable for OpenGL's matrix operations.
Quaternion conversion routines
  • void allegro_gl_apply_quat (QUAT *q)
  • void allegro_gl_quat_to_glrotatef (QUAT *q, float *angle, float *x, float *y, float *z)
  • void allegro_gl_quat_to_glrotated (QUAT *q, double *angle, double *x, double *y, double *z)

Variables

  • char allegro_gl_error [256]
  • GFX_DRIVER gfx_allegro_gl_default
  • GFX_DRIVER gfx_allegro_gl_windowed
  • GFX_DRIVER gfx_allegro_gl_fullscreen

Core Functions

  • #define allegro_gl_begin()   ;
    Backward compatibility #define for programs written prior to AGL 0.0.22.
  • #define allegro_gl_end()   ;
    Backward compatibility #define for programs written prior to AGL 0.0.22.
  • int install_allegro_gl (void)
    Installs the AllegroGL addon to Allegro.
  • void remove_allegro_gl (void)
    Removes the AllegroGL addon.
  • void allegro_gl_flip (void)
    Flips the front and back framebuffers.
  • float allegro_gl_opengl_version (void)
    Returns the OpenGL version number of the client (the computer the program is running on).

Texture routines

Text Drawing and Font conversion


Detailed Description

Main header file for AllegroGL.

Definition in file alleggl.h.

allegro4.4-4.4.2/addons/allegrogl/docs/html/alleggl_8h_source.html000066400000000000000000001574751173507505700250210ustar00rootroot00000000000000 AllegroGL: alleggl.h Source File

alleggl.h

Go to the documentation of this file.
00001 
00005 #ifndef _allegrogl_included_alleggl_h
00006 #define _allegrogl_included_alleggl_h
00007 
00008 #include <allegro.h>
00009 
00010 #ifdef ALLEGRO_WINDOWS
00011 
00012 #ifndef WIN32_LEAN_AND_MEAN
00013 #define WIN32_LEAN_AND_MEAN
00014 #define WIN32_LEAN_AND_MEAN_defined
00015 #endif /* WIN32_LEAN_AND_MEAN */
00016 
00017 #ifdef ALLEGRO_DMC
00018 typedef int32_t INT32;
00019 typedef __int64 INT64;
00020 #endif
00021 
00022 #include <winalleg.h>
00023 
00024 #ifdef WIN32_LEAN_AND_MEAN_defined
00025 #undef WIN32_LEAN_AND_MEAN_defined
00026 #undef WIN32_LEAN_AND_MEAN
00027 #endif /* WIN32_LEAN_AND_MEAN_defined */
00028 
00029 #endif /* ALLEGRO_WINDOWS */
00030 
00031 
00032 #if (defined ALLEGRO_GL_DYNAMIC) && (defined ALLEGRO_WINDOWS)
00033     #ifdef ALLEGRO_GL_SRC_BUILD
00034         #define _AGL_DLL __declspec(dllexport)
00035     #else
00036         #define _AGL_DLL __declspec(dllimport)
00037     #endif /* ALLEGRO_GL_SRC_BUILD */
00038 #else
00039     #define _AGL_DLL
00040 #endif /* (defined ALLEGRO_GL_DYNAMIC) && (defined ALLEGRO_WINDOWS) */
00041 
00042 #define AGL_VAR(type, name) extern _AGL_DLL type name
00043 
00044 #if (defined ALLEGRO_GL_DYNAMIC) && (defined ALLEGRO_WINDOWS)
00045     #define AGL_FUNC(type, name, args) extern _AGL_DLL type __cdecl name args
00046 #else
00047     #define AGL_FUNC(type, name, args) extern type name args
00048 #endif /* (defined ALLEGRO_GL_DYNAMIC) && (defined ALLEGRO_WINDOWS) */
00049 
00050 
00051 #ifdef ALLEGRO_MACOSX
00052 
00053 #include <OpenGL/OpenGL.h>
00054 #include <OpenGL/gl.h>
00055 #include <OpenGL/glext.h>
00056 
00057 #ifndef GL_GLEXT_PROTOTYPES
00058 #define GL_GLEXT_PROTOTYPES
00059 #endif
00060 
00061 #else /* ALLEGRO_MACOSX */
00062 
00063 /* HACK: Prevent both Mesa and SGI's broken headers from screwing us */
00064 #define __glext_h_
00065 #define __glxext_h_
00066 #include <GL/gl.h>
00067 #undef  __glext_h_
00068 #undef  __glxext_h_
00069 
00070 #endif /* ALLEGRO_MACOSX */
00071 
00072 
00073 #include "allegrogl/gl_ext.h"
00074 
00075 #ifdef ALLEGRO_WITH_XWINDOWS
00076 #if (ALLEGRO_SUB_VERSION == 2) && (ALLEGRO_WIP_VERSION < 2)
00077 #   ifndef HAVE_LIBPTHREAD
00078 #      error AllegroGL requires Allegro to have pthread support enabled!
00079 #   endif
00080 #else
00081 #   ifndef ALLEGRO_HAVE_LIBPTHREAD
00082 #      error AllegroGL requires Allegro to have pthread support enabled!
00083 #   endif
00084 #endif
00085 #include "allegrogl/alleggl_config.h"
00086 #endif
00087 
00088 
00093 #define AGL_VERSION     0            ///< Major version number
00094 #define AGL_SUB_VERSION 4            ///< Minor version number
00095 #define AGL_WIP_VERSION 4            ///< Work-In-Progress version number
00096 #define AGL_VERSION_STR "0.4.4"      ///< Version description string
00097 
00100 /* Version Check */
00101 #if (ALLEGRO_VERSION < 4 || (ALLEGRO_VERSION == 4 && ALLEGRO_SUB_VERSION < 2))
00102     #error AllegroGL requires Allegro 4.2.0 or later to compile!
00103 #endif
00104 #ifndef GL_VERSION_1_1
00105     #error AllegroGL requires OpenGL 1.1 libraries or later to compile!
00106 #endif
00107 
00108 
00109 #ifdef __cplusplus
00110 extern "C" {
00111 #endif
00112 
00113 #ifdef ALLEGRO_WINDOWS
00114     
00115 /* Missing #defines from Mingw */
00116 #ifndef PFD_SWAP_LAYER_BUFFERS
00117 #define PFD_SWAP_LAYER_BUFFERS  0x00000800
00118 #endif
00119 
00120 #ifndef PFD_GENERIC_ACCELERATED
00121 #define PFD_GENERIC_ACCELERATED 0x00001000
00122 #endif
00123 
00124 #ifndef PFD_SUPPORT_DIRECTDRAW
00125 #define PFD_SUPPORT_DIRECTDRAW  0x00002000
00126 #endif
00127 
00128 #ifndef CDS_FULLSCREEN
00129 #define CDS_FULLSCREEN      0x00000004
00130 #endif
00131 
00132 #ifndef ENUM_CURRENT_SETTINGS
00133 #define ENUM_CURRENT_SETTINGS       ((DWORD)-1)
00134 #endif
00135 
00136 #endif
00137 
00138 
00139 #define AGL_ERROR_SIZE 256
00140 AGL_VAR(char, allegro_gl_error[AGL_ERROR_SIZE]);
00141 
00142 
00152 AGL_FUNC(int, install_allegro_gl, (void));
00153 AGL_FUNC(void, remove_allegro_gl, (void));
00154 
00155 AGL_FUNC(void, allegro_gl_flip, (void));
00156 AGL_FUNC(float, allegro_gl_opengl_version, (void));
00157 
00166 #define allegro_gl_begin() ;
00167 
00176 #define allegro_gl_end() ;
00177 
00189 #define AGL_ALLEGRO_FORMAT  0x00000001
00190 
00195 #define AGL_RED_DEPTH       0x00000002
00196 
00201 #define AGL_GREEN_DEPTH     0x00000004
00202 
00207 #define AGL_BLUE_DEPTH      0x00000008
00208 
00214 #define AGL_ALPHA_DEPTH     0x00000010
00215 
00219 #define AGL_COLOR_DEPTH     0x00000020
00220 
00221 
00227 #define AGL_ACC_RED_DEPTH   0x00000040
00228 
00234 #define AGL_ACC_GREEN_DEPTH 0x00000080
00235 
00236 
00242 #define AGL_ACC_BLUE_DEPTH  0x00000100
00243 
00244 
00250 #define AGL_ACC_ALPHA_DEPTH 0x00000200
00251 
00256 #define AGL_DOUBLEBUFFER    0x00000400
00257 
00265 #define AGL_STEREO          0x00000800
00266 
00267 
00271 #define AGL_AUX_BUFFERS     0x00001000
00272 
00273 
00278 #define AGL_Z_DEPTH         0x00002000
00279 
00280 
00287 #define AGL_STENCIL_DEPTH   0x00004000
00288 
00292 #define AGL_WINDOW_X        0x00008000
00293 
00296 #define AGL_WINDOW_Y        0x00010000
00297 
00306 #define AGL_RENDERMETHOD    0x00020000
00307 
00311 #define AGL_FULLSCREEN      0x00040000
00312 
00316 #define AGL_WINDOWED        0x00080000
00317 
00333 #define AGL_VIDEO_MEMORY_POLICY     0x00100000
00334 
00357 #define AGL_SAMPLE_BUFFERS  0x00200000
00358 
00365 #define AGL_SAMPLES        0x00400000
00366 
00371 #define AGL_FLOAT_COLOR    0x00800000
00372 
00375 #define AGL_FLOAT_Z        0x01000000
00376 
00377 
00378 
00379 /* XXX <rohannessian> I'm reserving 2 bits here for later expansion. DO NOT USE
00380  * without consulting me first.
00381  */
00382 #define AGL_CONFIG_RESRVED 0xA000000
00383 
00384 
00387 #define AGL_DONTCARE   0 ///< Ignore these settings
00388 #define AGL_SUGGEST   -1 ///< Prefer the assigned values for these settings
00389 #define AGL_REQUIRE   -2 ///< Reject other values for these settings
00390 
00395 #define AGL_KEEP    1 ///< Keep internal texture in video memory
00396 #define AGL_RELEASE 2 ///< Release video memory occupied by internal texture
00397 
00402 AGL_FUNC(void, allegro_gl_clear_settings, (void));
00403 AGL_FUNC(void, allegro_gl_set, (int option, int value));
00404 AGL_FUNC(int,  allegro_gl_get, (int option));
00405 AGL_FUNC(void, allegro_gl_save_settings, (void));
00406 AGL_FUNC(void, allegro_gl_load_settings, (void));
00423 #if defined DOXYGEN  /* Is this a documentation scan? */
00424 
00429 # define GFX_OPENGL_WINDOWED
00430 
00431 # define GFX_OPENGL_FULLSCREEN
00432 
00433   #define GFX_OPENGL
00434 
00437 #else
00438 
00439 #if defined ALLEGROGL_GENERIC_DRIVER
00440   /* Allegro is able to determine at run-time if windowed or fullscreen modes
00441      are available */
00442   #define GFX_OPENGL_WINDOWED               AL_ID('O','G','L','W')
00443   #define GFX_OPENGL_FULLSCREEN             AL_ID('O','G','L','F')
00444 
00445 #else
00446 #if defined _WIN32
00447   /* Windows always supports fullscreen */
00448   #define GFX_OPENGL_WINDOWED               AL_ID('O','G','L','W')
00449   #define GFX_OPENGL_FULLSCREEN             AL_ID('O','G','L','F')
00450 
00451 #elif defined ALLEGRO_WITH_XWINDOWS
00452   /* X always supports fullscreen */
00453   #define GFX_OPENGL_WINDOWED               AL_ID('O','G','L','W')
00454   #define GFX_OPENGL_FULLSCREEN             AL_ID('O','G','L','F')
00455   
00456 #elif defined ALLEGRO_MACOSX
00457   /* MacOS X always supports fullscreen */
00458   #define GFX_OPENGL_WINDOWED               AL_ID('O','G','L','W')
00459   #define GFX_OPENGL_FULLSCREEN             AL_ID('O','G','L','F')
00460 
00461 #else
00462   #warning Unknown or unsupported platform.
00463 #endif
00464 #endif
00465 
00466 #define GFX_OPENGL                  AL_ID('O','G','L','D')
00467 
00468 #endif
00469 
00470 
00471 /* Declare graphics driver objects */
00472 extern GFX_DRIVER gfx_allegro_gl_default;
00473 #ifdef GFX_OPENGL_WINDOWED
00474 extern GFX_DRIVER gfx_allegro_gl_windowed;
00475 #endif
00476 #ifdef GFX_OPENGL_FULLSCREEN
00477 extern GFX_DRIVER gfx_allegro_gl_fullscreen;
00478 #endif
00479 
00480 
00488 AGL_FUNC(GLint, allegro_gl_set_video_bitmap_color_depth, (int bpp));
00500 AGL_FUNC(int, allegro_gl_use_mipmapping, (int enable));
00501 AGL_FUNC(int, allegro_gl_use_alpha_channel, (int enable));
00502 AGL_FUNC(int, allegro_gl_flip_texture, (int enable));
00503 AGL_FUNC(int, allegro_gl_check_texture, (BITMAP *bmp));
00504 AGL_FUNC(int, allegro_gl_check_texture_ex, (int flags, BITMAP *bmp,
00505                                        GLint internal_format));
00506 AGL_FUNC(GLint, allegro_gl_get_texture_format, (BITMAP *bmp));
00507 AGL_FUNC(GLint, allegro_gl_set_texture_format, (GLint format));
00508 AGL_FUNC(GLenum, allegro_gl_get_bitmap_type, (BITMAP *bmp));
00509 AGL_FUNC(GLenum, allegro_gl_get_bitmap_color_format, (BITMAP *bmp));
00510 AGL_FUNC(GLuint, allegro_gl_make_texture, (BITMAP *bmp));
00511 AGL_FUNC(GLuint, allegro_gl_make_masked_texture, (BITMAP *bmp));
00512 AGL_FUNC(GLuint, allegro_gl_make_texture_ex,(int flags, BITMAP *bmp,
00513                                          GLint internal_format));
00514 
00515 
00518 #define AGL_TEXTURE_MIPMAP      0x01
00519 
00523 #define AGL_TEXTURE_HAS_ALPHA   0x02
00524 
00529 #define AGL_TEXTURE_FLIP        0x04
00530 
00534 #define AGL_TEXTURE_MASKED      0x08
00535 
00540 #define AGL_TEXTURE_RESCALE     0x10
00541 
00542 
00545 #define AGL_TEXTURE_ALPHA_ONLY  0x20
00546 
00557 AGL_FUNC(void, allegro_gl_set_allegro_mode, (void));
00558 AGL_FUNC(void, allegro_gl_unset_allegro_mode, (void));
00559 AGL_FUNC(void, allegro_gl_set_projection, (void));
00560 AGL_FUNC(void, allegro_gl_unset_projection, (void));
00574 AGL_FUNC(void, allegro_gl_MATRIX_to_GLfloat, (MATRIX *m, GLfloat gl[16]));
00575 AGL_FUNC(void, allegro_gl_MATRIX_to_GLdouble, (MATRIX *m, GLdouble gl[16]));
00576 AGL_FUNC(void, allegro_gl_MATRIX_f_to_GLfloat, (MATRIX_f *m, GLfloat gl[16]));
00577 AGL_FUNC(void, allegro_gl_MATRIX_f_to_GLdouble, (MATRIX_f *m, GLdouble gl[16]));
00578 
00579 AGL_FUNC(void, allegro_gl_GLfloat_to_MATRIX, (GLfloat gl[16], MATRIX *m));
00580 AGL_FUNC(void, allegro_gl_GLdouble_to_MATRIX, (GLdouble gl[16], MATRIX *m));
00581 AGL_FUNC(void, allegro_gl_GLfloat_to_MATRIX_f, (GLfloat gl[16], MATRIX_f *m));
00582 AGL_FUNC(void, allegro_gl_GLdouble_to_MATRIX_f, (GLdouble gl[16], MATRIX_f *m));
00583 
00588 AGL_FUNC(void, allegro_gl_apply_quat, (QUAT *q));
00589 AGL_FUNC(void, allegro_gl_quat_to_glrotatef, (QUAT *q, float *angle,
00590                                          float *x, float *y, float *z));
00591 AGL_FUNC(void, allegro_gl_quat_to_glrotated, (QUAT *q, double *angle,
00592                                          double *x, double *y, double *z));
00614 /* These define the supported font types */
00618 #define AGL_FONT_TYPE_DONT_CARE     -1
00619 
00629 #define AGL_FONT_TYPE_BITMAP         0
00630 
00641 #define AGL_FONT_TYPE_OUTLINE        1
00642 
00653 #define AGL_FONT_TYPE_TEXTURED       2
00654 
00655 
00656 /* These defines the font styles for system generated fonts */
00661 #define AGL_FONT_STYLE_BOLD          1
00662 
00666 #define AGL_FONT_STYLE_BLACK         2
00667 
00671 #define AGL_FONT_STYLE_ITALIC        4
00672 
00676 #define AGL_FONT_STYLE_UNDERLINE     8
00677 
00681 #define AGL_FONT_STYLE_STRIKEOUT    16
00682 
00688 #define AGL_FONT_STYLE_ANTI_ALIASED 32
00689 
00696 #define AGL_FONT_POLYGONS 1
00697 
00698 
00705 #define AGL_FONT_LINES    2
00706 
00707 
00708 AGL_FUNC(int, allegro_gl_printf, (AL_CONST FONT *f, float x, float y, float z,
00709                              int color, AL_CONST char *format, ...));
00710 AGL_FUNC(int, allegro_gl_printf_ex, (AL_CONST FONT *f, float x, float y, float z,
00711                              AL_CONST char *format, ...));
00712 AGL_FUNC(FONT*, allegro_gl_convert_allegro_font, (FONT *f, int type, float scale));
00713 AGL_FUNC(FONT*, allegro_gl_convert_allegro_font_ex, (FONT *f, int type, float scale,
00714                                                 GLint format));
00715 
00716 AGL_FUNC(void, allegro_gl_set_font_generation_mode, (int mode));
00717 AGL_FUNC(FONT*, allegro_gl_load_system_font, (char *name, int style, int w, int h));
00718 AGL_FUNC(FONT*, allegro_gl_load_system_font_ex, (char *name, int type, int style,
00719                                  int w, int h, float depth, int start, int end));
00720 AGL_FUNC(void, allegro_gl_destroy_font, (FONT *f));
00721 AGL_FUNC(size_t, allegro_gl_list_font_textures, (FONT *f, GLuint *ids, size_t max_num_id));
00743 #if defined DOXYGEN  /* Is this a documentation scan? */
00744 
00751 #define AGL_DEFINE_PROC_TYPE
00752 
00753 #else
00754 
00755 AGL_FUNC(int, allegro_gl_is_extension_supported, (const char *));
00756 AGL_FUNC(void*, allegro_gl_get_proc_address, (const char *));
00757 
00758 #if defined ALLEGRO_WINDOWS
00759     #define AGL_DEFINE_PROC_TYPE(type, name, args) \
00760         typedef type (APIENTRY * name) args;
00761 #else
00762     #define AGL_DEFINE_PROC_TYPE(type, name, args) \
00763         typedef type (*name) args;
00764 #endif
00765 
00766 #endif
00767 
00789 AGL_FUNC(int, algl_do_dialog, (DIALOG *dialog, int focus_obj));
00790 AGL_FUNC(int, algl_popup_dialog, (DIALOG *dialog, int focus_obj));
00791 AGL_FUNC(void, algl_draw_mouse, (void));
00792 AGL_FUNC(void, algl_set_mouse_drawer, (void (*user_draw_mouse)(void)));
00793 AGL_FUNC(int, algl_alert, (AL_CONST char *s1, AL_CONST char *s2, AL_CONST char *s3,
00794                       AL_CONST char *b1, AL_CONST char *b2, int c1, int c2));
00795 AGL_FUNC(int, algl_alert3, (AL_CONST char *s1, AL_CONST char *s2, AL_CONST char *s3,
00796                        AL_CONST char *b1, AL_CONST char *b2, AL_CONST char *b3,
00797                        int c1, int c2, int c3));
00798 AGL_FUNC(int, d_algl_viewport_proc, (int msg, DIALOG *d, int c));
00799 
00804 #ifdef __cplusplus
00805 }
00806 #endif
00807 
00808 
00809 /* Fixes to MS's (or SGI?) broken GL headers */
00810 #ifdef GL_VERSION_1_1
00811 #ifndef GL_TEXTURE_BINDING_2D
00812 
00813 #ifdef GL_TEXTURE_2D_BINDING
00814 #define GL_TEXTURE_BINDING_2D GL_TEXTURE_2D_BINDING
00815 #endif
00816 
00817 #else
00818 
00819 #ifdef GL_TEXTURE_BINDING_2D
00820 #define GL_TEXTURE_2D_BINDING GL_TEXTURE_BINDING_2D
00821 #endif
00822 
00823 #endif
00824 
00825 #ifndef GL_TEXTURE_BINDING_2D
00826 #warning "GL_TEXTURE_BINDING_2D or GL_TEXTURE_2D_BINDING isn't defined by your"
00827 #warning "OpenGL headers. Make sure you have a genuine set of headers for"
00828 #warning "OpenGL 1.1 (or greater)"
00829 #endif
00830 #endif
00831 
00832 #endif
00833 
allegro4.4-4.4.2/addons/allegrogl/docs/html/allglint_8h_source.html000066400000000000000000000525721173507505700252100ustar00rootroot00000000000000 AllegroGL: allglint.h Source File

allglint.h

00001 #ifndef gf_included_allglint_h
00002 #define gf_included_allglint_h
00003 
00004 #include "alleggl.h"
00005 
00006 
00007 struct allegro_gl_info {
00008     float version;          /* OpenGL version */
00009     int num_texture_units;  /* Number of texture units */
00010     int max_texture_size;   /* Maximum texture size */
00011     int is_voodoo3_and_under; /* Special cases for Voodoo 1-3 */
00012     int is_voodoo;          /* Special cases for Voodoo cards */
00013     int is_matrox_g200;     /* Special cases for Matrox G200 boards */
00014     int is_ati_rage_pro;    /* Special cases for ATI Rage Pro boards */
00015     int is_ati_radeon_7000; /* Special cases for ATI Radeon 7000 */
00016     int is_ati_r200_chip;   /* Special cases for ATI card with chip R200 */
00017     int is_mesa_driver;     /* Special cases for MESA */
00018 };
00019 
00020 
00021 
00022 struct allegro_gl_driver {
00023     void (*flip) (void);
00024     void (*gl_on) (void);
00025     void (*gl_off) (void);
00026     void (*screen_masked_blit)(struct BITMAP *source, int source_x,
00027                                int source_y, int dest_x, int dest_y,
00028                                int width, int height, int flip_dir,
00029                                int blit_type);
00030 };
00031 
00032 
00033 
00034 struct allegro_gl_rgba_size {
00035     int r, g, b, a;
00036 };
00037 
00038 
00039 
00040 struct allegro_gl_indexed_size {
00041     int bpp;
00042 };
00043 
00044 
00045 
00046 union allegro_gl_pixel_size {
00047     struct allegro_gl_rgba_size rgba;
00048     struct allegro_gl_indexed_size indexed;
00049 };
00050 
00051 
00052 
00053 struct allegro_gl_display_info {
00054     int allegro_format;
00055     union allegro_gl_pixel_size pixel_size;
00056     int colour_depth;
00057     union allegro_gl_pixel_size accum_size;
00058     int doublebuffered;
00059     int stereo;
00060     int aux_buffers;
00061     int depth_size;
00062     int stencil_size;
00063     int w, h, x, y;
00064     int r_shift, g_shift, b_shift, a_shift;
00065     int packed_pixel_type, packed_pixel_format;
00066     int rmethod; /* type of rendering, 0: software; 1: hardware, 2: unknown (X Win) */
00067     int fullscreen;
00068     int vidmem_policy;
00069     int sample_buffers;
00070     int samples;
00071     int float_color;
00072     int float_depth;
00073 };
00074 
00075 extern struct allegro_gl_display_info allegro_gl_display_info;
00076 extern struct allegro_gl_driver *__allegro_gl_driver;
00077 extern struct allegro_gl_info allegro_gl_info;
00078 extern int __allegro_gl_required_settings, __allegro_gl_suggested_settings;
00079 extern int __allegro_gl_valid_context;
00080 extern int __allegro_gl_use_alpha;
00081 extern GLint __allegro_gl_texture_read_format[5];
00082 extern GLint __allegro_gl_texture_components[5];
00083 
00084 #ifdef ALLEGRO_WINDOWS
00085 extern HDC __allegro_gl_hdc;
00086 #endif
00087 
00088 int __allegro_gl_make_power_of_2(int x);
00089 
00090 void __allegro_gl_reset_scorer (void);
00091 int __allegro_gl_score_config (int refnum, struct allegro_gl_display_info *dinfo);
00092 int __allegro_gl_best_config (void);
00093 
00094 void __allegro_gl_set_allegro_image_format (int big_endian);
00095 
00096 void __allegro_gl_fill_in_info(void);
00097 
00098 void __allegro_gl_manage_extensions(void);
00099 void __allegro_gl_unmanage_extensions(void);
00100 void __allegro_gl_print_extensions(const char * extension);
00101 int __allegro_gl_look_for_an_extension(AL_CONST char *name,
00102                                                   AL_CONST GLubyte * extensions);
00103 
00104 
00105 extern _DRIVER_INFO *(*saved_gfx_drivers) (void);
00106 
00107 typedef void (* BLIT_BETWEEN_FORMATS_FUNC) (struct BITMAP*, struct BITMAP*, int, int, int, int, int, int);
00108 extern BLIT_BETWEEN_FORMATS_FUNC __blit_between_formats8;
00109 extern BLIT_BETWEEN_FORMATS_FUNC __blit_between_formats15;
00110 extern BLIT_BETWEEN_FORMATS_FUNC __blit_between_formats16;
00111 extern BLIT_BETWEEN_FORMATS_FUNC __blit_between_formats24;
00112 extern BLIT_BETWEEN_FORMATS_FUNC __blit_between_formats32;
00113 
00114 void allegro_gl_memory_blit_between_formats(struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height);
00115 
00116 int allegro_gl_set_mouse_sprite(BITMAP *sprite, int xfocus, int yfocus);
00117 int allegro_gl_show_mouse(BITMAP* bmp, int x, int y);
00118 void allegro_gl_hide_mouse(void);
00119 void allegro_gl_move_mouse(int x, int y);
00120 
00121 
00122 extern char const *__allegro_gl_get_format_description(GLint format);
00123 extern int __allegro_gl_get_num_channels(GLenum format);
00124 extern GLenum __allegro_gl_get_bitmap_type(BITMAP *bmp, int flags);
00125 extern GLenum __allegro_gl_get_bitmap_color_format(BITMAP *bmp, int flags);
00126 extern GLint __allegro_gl_get_texture_format_ex(BITMAP *bmp, int flags);
00127 extern BITMAP *__allegro_gl_munge_bitmap(int flags, BITMAP *bmp, int x, int y,
00128                                       int w, int h, GLint *type, GLint *format);
00129 
00130 extern int __allegro_gl_blit_operation;
00131 
00132 
00136 typedef struct AGL_GLYPH {
00137     int glyph_num;
00138     int x, y, w, h;
00139     int offset_x, offset_y, offset_w, offset_h;
00140 } AGL_GLYPH;
00141 
00142 
00143 /*   <ofs_x>
00144      +--------------------+
00145      |                    |
00146      |    +-------+       |
00147      |    | glyph |       |
00148      |    +-------+       |
00149      |                    |
00150      +--------------------+
00151           <   w   ><ofs_w >
00152      <      polygon       >
00153 */
00154 
00155 
00160 typedef struct FONT_AGL_DATA {
00161     int type;
00162     int start, end;
00163     int is_free_chunk;
00164 
00165     float scale;
00166     GLint format;
00167 
00168     void *data;
00169     AGL_GLYPH *glyph_coords;
00170     GLuint list_base;
00171     GLuint texture;
00172 
00173     struct FONT_AGL_DATA *next;
00174 
00175         int has_alpha;
00176 } FONT_AGL_DATA;
00177 
00178 extern struct FONT_VTABLE *font_vtable_agl;
00179 
00180 
00185 #define AGL_TEXTURE_FORCE_ALPHA_INTERNAL 0x80000000
00186 
00190 #define AGL_TEXTURE_CHECK_VALID_INTERNAL 0x40000000
00191 
00192 
00193 #define AGL_OP_LOGIC_OP         0x0
00194 #define AGL_OP_BLEND            0x1
00195 
00196 #define AGL_H_FLIP      1   /* Flag to request horizontal flipping */
00197 #define AGL_V_FLIP      2   /* Flag to request vertical flipping */
00198 #define AGL_REGULAR_BMP 1   /* Must be set for bitmaps that are not sprites.
00199                                Otherwise the clipping routine will not test
00200                                if source_x and source_y are legal values */
00201 #define AGL_NO_ROTATION 2   /* If not set the clipping routine is skipped
00202                                This is needed for pivot_scaled_x() in order
00203                                not to clip rotated bitmaps (in such a case
00204                                OpenGL will take care of it) */
00205 
00206 
00207 #define AGL_LOG(level,str)
00208 
00209 #ifdef DEBUGMODE
00210 #ifdef LOGLEVEL
00211 
00212 void __allegro_gl_log (int level, const char *str);
00213 #undef AGL_LOG
00214 #define AGL_LOG(level,str) __allegro_gl_log (level, str)
00215 
00216 
00217 #endif
00218 #endif
00219 
00220 
00221 #define GET_ALLEGRO_VERSION() MAKE_VER(ALLEGRO_VERSION, ALLEGRO_SUB_VERSION, \
00222                                        ALLEGRO_WIP_VERSION)
00223 #define MAKE_VER(a, b, c) (((a) << 16) | ((b) << 8) | (c))
00224 
00225 
00226 #endif
00227 
allegro4.4-4.4.2/addons/allegrogl/docs/html/bc_s.png000066400000000000000000000012451173507505700221400ustar00rootroot00000000000000‰PNG  IHDR /ð9ÐlIDATxíÝKHTmðÿóžwfÎgæÌ¯å8ŽÓ˜—Š6ñ-BÚ´‘]d–VZMa…D}ßg¸háB¤¶*Ñýbå¥U9Š—3ƒŽFy<£‹ šaæè²í³yøÿÎóžÅóî©ýÁÇåþtðªÚ %”8Vj•LÜlø·ÅCF@mÃÿˆÞ[”ïü À7ªj¿RÀ•ûC0TâU‹Y¸øYÕú’ÿsv~Æî,Ûi)€.w €™ˆæwø\cT i Ðúÿ`¼owgÛö»âH0¤5%À¥ÿ>Äû\.°ÉÒ×*O0¬-c}BàÞûä+msË…VÑÔ5Ö:€Îß}— *l’©Çç–cÁV¸€OÅ^ÅaâìÔXxñ)µÜ0‚ãé²xrKfÚÜxx±Ššo½5Ièk±WaŒÑjºùÆà¶;ÛVá´[¨ñÆ«Í@¥ÃfnöäØ¿°ÍRÕ.‡¨¬®B¥×_C™ˆæK|.¬ý²Ÿ®½0‚3ŠTŸ¥H¡‰½†Ž¶=7‚ ßã´™8k˜œÑ_Ó‘«Ï’Ã2«Èz·:V&fôBv—Ní9iVÎY— Õµ>‰‡.Qx{¾E“³ú»Ê‡˜'‰|dj6ÚØ‡ÚÀãx?åÏsJ‚@uÓ‘hbI„Ò½‡Ö2ì“,¼F¶[bÓ‘h e'«Ïõ@;Û^d•x·‰þ›¶ôg2Fa¿G^ÿ @,é) êlß… §Të’-ãêÜRý†—UÙÜ*È•EΩ64·4lÜÄÙ #èjDßþú Ųo{”N IEND®B`‚allegro4.4-4.4.2/addons/allegrogl/docs/html/closed.png000066400000000000000000000001761173507505700225050ustar00rootroot00000000000000‰PNG  IHDR à‘EIDATxíÝA @! PŠ­iš/`Є.È?,!ƒu zlÞ–Jh1ߘ+výRLé§x@‘Ù (*79HÑ þl)¡ó²‰IEND®B`‚allegro4.4-4.4.2/addons/allegrogl/docs/html/deprecated.html000066400000000000000000000161171173507505700235160ustar00rootroot00000000000000 AllegroGL: Deprecated List

Deprecated List

Global AGL_ALLEGRO_FORMAT
This define is ignored.

Global AGL_FONT_LINES
Non-textured fonts will be dropped from AllegroGL.

Global AGL_FONT_POLYGONS
Non-textured fonts will be dropped from AllegroGL.

Global AGL_FONT_STYLE_ANTI_ALIASED
Non-textured fonts will be dropped from AllegroGL.

Global AGL_FONT_STYLE_BLACK
Non-textured fonts will be dropped from AllegroGL.

Global AGL_FONT_STYLE_BOLD
Non-textured fonts will be dropped from AllegroGL

Global AGL_FONT_STYLE_ITALIC
Non-textured fonts will be dropped from AllegroGL.

Global AGL_FONT_STYLE_STRIKEOUT
Non-textured fonts will be dropped from AllegroGL.

Global AGL_FONT_STYLE_UNDERLINE
Non-textured fonts will be dropped from AllegroGL.

Global AGL_FONT_TYPE_OUTLINE
Non-textured fonts will be dropped from AllegroGL.

Global allegro_gl_check_texture (BITMAP *bmp)

Global allegro_gl_convert_allegro_font (FONT *f, int type, float scale)

Global allegro_gl_flip_texture (int enable)

Global allegro_gl_get_texture_format (BITMAP *bmp)

Global allegro_gl_load_system_font (char *name, int style, int w, int h)

Global allegro_gl_load_system_font_ex (char *name, int type, int style, int w, int h, float depth, int start, int end)

Global allegro_gl_make_masked_texture (BITMAP *bmp)

Global allegro_gl_make_texture (BITMAP *bmp)

Global allegro_gl_set_font_generation_mode (int mode)

Global allegro_gl_set_texture_format (GLint format)

Global allegro_gl_use_alpha_channel (int enable)

Global allegro_gl_use_mipmapping (int enable)
allegro4.4-4.4.2/addons/allegrogl/docs/html/djgpp_8c_source.html000066400000000000000000001453531173507505700245010ustar00rootroot00000000000000 AllegroGL: djgpp.c Source File

djgpp.c

00001 /* This code is (C) AllegroGL contributors, and double licensed under
00002  * the GPL and zlib licenses. See gpl.txt or zlib.txt for details.
00003  */
00004 /*----------------------------------------------------------------
00005  * amesa.c -- Allegro-Mesa interfacing
00006  *----------------------------------------------------------------
00007  *  This is the interface module for use AllegroGL with Mesa using the AMesa driver.
00008  */
00009 #include <string.h>
00010 
00011 #include <GL/gl.h>
00012 #include <GL/amesa.h>
00013 
00014 #include <allegro.h>
00015 #include <allegro/internal/aintern.h>
00016 
00017 #include "alleggl.h"
00018 #include "allglint.h"
00019 #include "glvtable.h"
00020 
00021 
00022 static void allegro_gl_amesa_exit(BITMAP *bmp);
00023 static void __allegro_gl_init_texture_read_format(void);
00024 
00025 #ifdef GFX_OPENGL_FULLSCREEN
00026 static BITMAP *allegro_gl_amesa_fullscreen_init(int w, int h, int vw, int vh, int color_depth);
00027 
00028 GFX_DRIVER gfx_allegro_gl_fullscreen =
00029 {
00030    GFX_OPENGL_FULLSCREEN,
00031    empty_string,
00032    empty_string,
00033    "AllegroGL Fullscreen (AMesa)",
00034    allegro_gl_amesa_fullscreen_init,
00035    allegro_gl_amesa_exit,
00036    NULL,
00037    NULL,               //_xwin_vsync,
00038    NULL,
00039    NULL, NULL, NULL,
00040    allegro_gl_create_video_bitmap,
00041    allegro_gl_destroy_video_bitmap,
00042    NULL, NULL,                  /* No show/request video bitmaps */
00043    NULL, NULL,
00044    allegro_gl_set_mouse_sprite,
00045    allegro_gl_show_mouse,
00046    allegro_gl_hide_mouse,
00047    allegro_gl_move_mouse,
00048    NULL,
00049    NULL, NULL,
00050    NULL,                        /* No fetch_mode_list */
00051    0, 0,
00052    0,
00053    0, 0,
00054    0,
00055    0,
00056    FALSE                        /* Windowed mode */
00057 };
00058 #endif /* GFX_OPENGL_FULLSCREEN */
00059 
00060 
00061 #ifdef GFX_OPENGL_WINDOWED
00062 static BITMAP *allegro_gl_amesa_windowed_init(int w, int h, int vw, int vh, int color_depth);
00063 
00064 GFX_DRIVER gfx_allegro_gl_windowed =
00065 {
00066    GFX_OPENGL_WINDOWED,
00067    empty_string,
00068    empty_string,
00069    "AllegroGL Windowed (AMesa)",
00070    allegro_gl_amesa_windowed_init,
00071    allegro_gl_amesa_exit,
00072    NULL,
00073    NULL,               //_xwin_vsync,
00074    NULL,
00075    NULL, NULL, NULL,
00076    allegro_gl_create_video_bitmap,
00077    allegro_gl_destroy_video_bitmap,
00078    NULL, NULL,                  /* No show/request video bitmaps */
00079    NULL, NULL,
00080    allegro_gl_set_mouse_sprite,
00081    allegro_gl_show_mouse,
00082    allegro_gl_hide_mouse,
00083    allegro_gl_move_mouse,
00084    NULL,
00085    NULL, NULL,
00086    NULL,                        /* No fetch_mode_list */
00087    0, 0,
00088    0,
00089    0, 0,
00090    0,
00091    0,
00092    TRUE                         /* Windowed mode */
00093 };
00094 #endif /* GFX_OPENGL_WINDOWED */
00095 
00096 
00097 
00098 static int allegro_gl_amesa_create_window (int fullscreen);
00099 static BITMAP *allegro_gl_amesa_create_screen_bitmap (GFX_DRIVER *drv, int w, int h, int depth);
00100 
00101 struct AMESA_DATA {
00102     int          fullscreen;
00103     AMesaVisual  visual;
00104     AMesaBuffer  buffer;
00105     AMesaContext context;
00106 } AMESA_DATA;
00107 
00108 static struct AMESA_DATA _amesa;
00109 static struct allegro_gl_driver allegro_gl_amesa;
00110 
00111 static BITMAP* subscreen = NULL;                 /* Sub_bitmap of the virtual screen */
00112 static BITMAP* saved_screen = NULL;              /* Saves screen address */
00113 
00114 GFX_DRIVER *amesa_gfx_driver = NULL;
00115 
00116 static GFX_VTABLE allegro_gl_generic_vtable;
00117 static GFX_VTABLE *old_vtable;
00118 
00119 
00120 
00121 /* allegro_gl_amesa_create_screen:
00122  *  Creates screen bitmap.
00123  */
00124 static BITMAP *allegro_gl_amesa_create_screen(int w, int h, int vw, int vh, int depth, int fullscreen)
00125 {
00126     int _keyboard_was_installed = FALSE;
00127     int _mouse_was_installed = FALSE;
00128     GFX_VTABLE vtable, *pvtable;
00129 
00130     pvtable = &vtable;
00131     
00132     if (keyboard_driver) {
00133         _keyboard_was_installed = TRUE;
00134         remove_keyboard();
00135         TRACE("* Note * amesa_create_screen: Removing Keyboard...\n");
00136     }
00137     
00138     if (mouse_driver) {
00139         _mouse_was_installed = TRUE;
00140         remove_mouse();
00141         TRACE("* Note * amesa_create_screen: Removing Mouse...\n");
00142     }
00143     
00144     if ((w == 0) && (h == 0)) {
00145         w = 640;
00146         h = 480;
00147     }
00148 
00149     if ((vw > w) || (vh > h)) {
00150         ustrzcpy (allegro_error, ALLEGRO_ERROR_SIZE,
00151              get_config_text ("OpenGL drivers do not support virtual screens"));
00152         return NULL;
00153     }
00154 
00155     allegro_gl_display_info.w = w;
00156     allegro_gl_display_info.h = h;
00157 
00158     if (allegro_gl_amesa_create_window(fullscreen)) {
00159         if (fullscreen) {
00160             ustrzcpy (allegro_error, ALLEGRO_ERROR_SIZE,
00161                       get_config_text ("Unable to switch in AMesa fullscreen"));
00162         }
00163         else {
00164             ustrzcpy (allegro_error, ALLEGRO_ERROR_SIZE,
00165                       get_config_text ("Unable to create AMesa window"));
00166         }
00167         return NULL;
00168     }
00169 
00170     /* If pixel format is Allegro compatible, set up Allegro correctly. */
00171 
00172     if (fullscreen) {
00173 #ifdef GFX_OPENGL_FULLSCREEN
00174         allegro_gl_screen = allegro_gl_amesa_create_screen_bitmap (&gfx_allegro_gl_fullscreen, w, h, allegro_gl_display_info.colour_depth);
00175 #endif
00176     }
00177     else {
00178 #ifdef GFX_OPENGL_WINDOWED
00179         allegro_gl_screen = allegro_gl_amesa_create_screen_bitmap (&gfx_allegro_gl_windowed, w, h, allegro_gl_display_info.colour_depth);
00180 #endif
00181     }
00182 
00183     if (!allegro_gl_screen) {
00184         ustrzcpy (allegro_error, ALLEGRO_ERROR_SIZE,
00185                   get_config_text ("Error creating screen bitmap"));
00186         return NULL;
00187     }
00188     
00189     __allegro_gl_valid_context = TRUE;
00190     __allegro_gl_driver = &allegro_gl_amesa;
00191     LOCK_DATA(&_amesa, sizeof(AMESA_DATA));
00192     LOCK_DATA(__allegro_gl_driver, sizeof(struct allegro_gl_driver));
00193 
00194     /* save the old vtable and create a copy */
00195     old_vtable = allegro_gl_screen->vtable;
00196     memcpy(&allegro_gl_generic_vtable, allegro_gl_screen->vtable,
00197            sizeof(GFX_VTABLE));
00198     allegro_gl_screen->vtable = &allegro_gl_generic_vtable;
00199 
00200     /* The generic driver does not use the glvtable (since it already uses
00201      * 'pure' Allegro gfx functions. However it needs the AGL-specific
00202      * draw_glyph method. 
00203      * Hence this hack : we call __allegro_gl__glvtable_update_vtable with
00204      * 'pvtable' as a parameter since we do not want the regular
00205      * allegro_gl_screen->vtable to be crushed.
00206      */
00207     __allegro_gl__glvtable_update_vtable(&pvtable);
00208     allegro_gl_screen->vtable->draw_glyph = pvtable->draw_glyph;
00209     memcpy(&_screen_vtable, allegro_gl_screen->vtable, sizeof(GFX_VTABLE));
00210     allegro_gl_screen->vtable = &_screen_vtable;
00211     __allegro_gl_init_screen_mode();
00212 
00213     /* Print out OpenGL version info */
00214     TRACE("\n\nOpenGL Version: %s\nVendor: %s\nRenderer: %s\n",
00215           (const char*)glGetString(GL_VERSION),
00216           (const char*)glGetString(GL_VENDOR),
00217           (const char*)glGetString(GL_RENDERER));
00218     
00219     /* Prints out OpenGL extensions info and activates needed extensions */
00220     __allegro_gl_manage_extensions();
00221     __allegro_gl_init_texture_read_format();    
00222 
00223     if (_keyboard_was_installed) {
00224         install_keyboard();
00225         TRACE("* Note * amesa_create_screen: Installing Keyboard...\n");
00226     }
00227 
00228     if (_mouse_was_installed) {
00229         install_mouse();
00230         TRACE("* Note * amesa_create_screen: Installing Mouse...\n");
00231     }
00232     
00233     /* XXX <rohannessian> Maybe we should leave this for autodetection? */
00234     gfx_capabilities |= GFX_HW_CURSOR;
00235 
00236     allegro_gl_info.is_mesa_driver = TRUE;
00237     _amesa.fullscreen = fullscreen;
00238     return allegro_gl_screen;
00239 }
00240 
00241 
00242 
00243 #ifdef GFX_OPENGL_WINDOWED
00244 /* allegro_gl_amesa_windowed_init:
00245  *  Creates screen bitmap for windowed driver.
00246  */
00247 static BITMAP *allegro_gl_amesa_windowed_init(int w, int h, int vw, int vh, int depth)
00248 {
00249     return allegro_gl_amesa_create_screen(w, h, vw, vh, depth, FALSE);
00250 }
00251 #endif
00252 
00253 
00254 
00255 #ifdef GFX_OPENGL_FULLSCREEN
00256 /* allegro_gl_amesa_fullscreen_init:
00257  *  Creates screen bitmap for fullscreen driver.
00258  */
00259 static BITMAP *allegro_gl_amesa_fullscreen_init(int w, int h, int vw, int vh, int depth)
00260 {
00261     return allegro_gl_amesa_create_screen(w, h, vw, vh, depth, TRUE);
00262 }
00263 #endif
00264 
00265 
00266 
00267 /* allegro_gl_amesa_exit:
00268  *  Shuts down the driver (shared between windowed and full-screen)
00269  */
00270 static void allegro_gl_amesa_exit(BITMAP *bmp)
00271 {
00272     /* Restore the screen to its intial value */
00273     screen = saved_screen;
00274     if (subscreen)
00275        destroy_bitmap(subscreen);
00276 
00277     amesa_gfx_driver->exit(screen);
00278    
00279     AMesaMakeCurrent(_amesa.context, NULL);
00280     AMesaDestroyVisual(_amesa.visual);
00281     AMesaDestroyBuffer(_amesa.buffer);
00282     AMesaDestroyContext(_amesa.context);
00283     
00284     __allegro_gl_valid_context = FALSE;
00285 }
00286 
00287 
00288 
00289 static void amesa_choose_gfx_mode(_DRIVER_INFO *driver_info, int *w, int *h,
00290                                   int *colour_depth)
00291 {
00292     GFX_MODE_LIST *mode_list;
00293     GFX_MODE *mode;
00294     int i;
00295 
00296     TRACE("* Note * amesa_choose_gfx_mode: GFX driver : %s\n",
00297           ((GFX_DRIVER*)driver_info->driver)->ascii_name);
00298 
00299     /* Try to find a mode which resolution and color depth are higher or
00300      * equal to those requested
00301      */
00302     mode_list = get_gfx_mode_list(driver_info->id);
00303 
00304     if (mode_list) {
00305         TRACE("* Note * amesa_choose_gfx_mode: %i modes\n",
00306               mode_list->num_modes);
00307 
00308         mode = mode_list->mode;
00309 
00310         for (i = 0; i < mode_list->num_modes; i++) {
00311             TRACE("Mode %i : %ix%i %i bpp\n", i, mode->width, mode->height,
00312                    mode->bpp);
00313             if ((mode->width >= *w) && (mode->height >= *h) &&
00314                 (mode->bpp >= *colour_depth)) {
00315                 break;
00316             }
00317             if (mode->width) {
00318                 mode++;
00319             }
00320         }
00321         if ((mode->width) && (mode->height) && (mode->bpp)) {
00322             allegro_gl_display_info.w = *w = mode->width;
00323             allegro_gl_display_info.h = *h = mode->height;
00324             allegro_gl_display_info.colour_depth = *colour_depth = mode->bpp;
00325         }
00326         TRACE("Best Mode : %ix%i %i bpp\n", *w, *h, *colour_depth);
00327         destroy_gfx_mode_list(mode_list);
00328     }
00329     else {
00330         TRACE("** Warning ** amesa_choose_gfx_mode: Can not list modes...\n"
00331               "Trying %ix%i %i bpp anyway\n", *w, *h, *colour_depth);
00332     }
00333 }
00334 
00335 
00336 
00337 /* amesa_set_gfx_mode :
00338  * A light version of set_gfx_mode since when this function is reached we are
00339  * ALREADY in set_gfx_mode. No need to initialize some parameters.
00340  * Moreover we must choose our driver in saved_gfx_drivers and set the real
00341  * gfx driver (i.e. the GFX_OPENGL one) the right way.
00342  */
00343 static int amesa_set_gfx_mode(int fullscreen)
00344 {
00345     extern void blit_end();
00346     _DRIVER_INFO *driver_list;
00347     int tried = FALSE;
00348     char buf[512], tmp[64];
00349     int c, n;
00350     int card = GFX_AUTODETECT;
00351     int w = allegro_gl_display_info.w;
00352     int h = allegro_gl_display_info.h;
00353     int check_mode = TRUE, require_window = FALSE;
00354 
00355     driver_list = saved_gfx_drivers();
00356 
00357     if (!fullscreen)
00358         require_window = TRUE;
00359 
00360     /* try the drivers that are listed in the config file */
00361     for (n=-2; n<255; n++) {
00362         switch (n) {
00363 
00364             case -2:
00365                 /* example: gfx_card_640x480x16 = */
00366                 usprintf(buf, uconvert_ascii("gfx_card_%dx%dx%d", tmp), w, h,
00367                          _color_depth);
00368                 break;
00369 
00370             case -1:
00371                 /* example: gfx_card_24bpp = */
00372                 usprintf(buf, uconvert_ascii("gfx_card_%dbpp", tmp),
00373                          _color_depth);
00374                 break;
00375 
00376             case 0:
00377                 /* example: gfx_card = */
00378                 ustrcpy(buf, uconvert_ascii("gfx_card", tmp));
00379                 break;
00380 
00381             default:
00382                 /* example: gfx_card1 = */
00383                 usprintf(buf, uconvert_ascii("gfx_card%d", tmp), n);
00384             break;
00385         }
00386         card = get_config_id(uconvert_ascii("graphics", tmp), buf,
00387                              GFX_AUTODETECT);
00388 
00389         if (card != GFX_AUTODETECT) {
00390 
00391             for (c=0; driver_list[c].driver; c++) {
00392                 if (driver_list[c].id == card) {
00393                     amesa_gfx_driver = driver_list[c].driver;
00394                     
00395                     if (check_mode) {
00396                         if ( ((require_window) && (!amesa_gfx_driver->windowed))
00397                          || ((!require_window)
00398                           && (amesa_gfx_driver->windowed))) {
00399 
00400                             amesa_gfx_driver = NULL;
00401                             continue;
00402                         }
00403                     }
00404                     break;
00405                 }
00406             }
00407 
00408             if (amesa_gfx_driver) {
00409                 tried = TRUE;
00410                 amesa_gfx_driver->name = amesa_gfx_driver->desc
00411                                 = get_config_text(amesa_gfx_driver->ascii_name);
00412                 
00413                 amesa_choose_gfx_mode(&driver_list[c], &w, &h, &_color_depth);
00414                 
00415                 screen = amesa_gfx_driver->init(w, h, 0, 0, _color_depth);
00416                 if (screen) {
00417                     break;
00418                 }
00419                 else {
00420                     amesa_gfx_driver = NULL;
00421                 }
00422             }
00423         }
00424         else {
00425             if (n > 1) {
00426                 break;
00427             }
00428         }
00429     }
00430 
00431     if (!tried) {
00432         for (c=0; driver_list[c].driver; c++) {
00433 
00434             if (driver_list[c].autodetect) {
00435                 
00436                 amesa_gfx_driver = driver_list[c].driver;
00437                 if (check_mode) {
00438                     if (((require_window) && (!amesa_gfx_driver->windowed)) ||
00439                        ((!require_window) && (amesa_gfx_driver->windowed)))
00440                         continue;
00441                 }
00442 
00443                 amesa_gfx_driver->name = amesa_gfx_driver->desc
00444                                 = get_config_text(amesa_gfx_driver->ascii_name);
00445 
00446                 amesa_choose_gfx_mode(&driver_list[c], &w, &h, &_color_depth);
00447 
00448                 screen = amesa_gfx_driver->init(w, h, 0, 0, _color_depth);
00449 
00450                 if (screen) {
00451                     break;
00452                 }
00453             }
00454         }
00455     }
00456 
00457     if (!screen) {
00458         amesa_gfx_driver = NULL;
00459         return -1;
00460     }
00461 
00462     LOCK_DATA(amesa_gfx_driver, sizeof(GFX_DRIVER));
00463     _register_switch_bitmap(screen, NULL);
00464 
00465     return 0;
00466 }
00467 
00468 
00469 
00470 /* create_window:
00471  *  Based on Bernhard Tschirren AMesa GLUT code.
00472  */
00473 static int allegro_gl_amesa_create_window (int fullscreen)
00474 {
00475     if (!allegro_gl_display_info.colour_depth)
00476         allegro_gl_display_info.colour_depth = _color_depth;
00477 
00478     set_color_depth(allegro_gl_display_info.colour_depth);
00479 
00480     if (amesa_set_gfx_mode(fullscreen)) {
00481         TRACE("** ERROR ** amesa_create_window: Unable to set a gfx mode!\n");
00482         return 1;
00483     }
00484 
00485     _amesa.visual  = AMesaCreateVisual(allegro_gl_display_info.doublebuffered,
00486                     allegro_gl_display_info.colour_depth,
00487                     GL_TRUE,                /* RGBA Mode */
00488                     allegro_gl_display_info.depth_size,
00489                     allegro_gl_display_info.stencil_size,
00490                     allegro_gl_display_info.accum_size.rgba.r,
00491                     allegro_gl_display_info.accum_size.rgba.g,
00492                     allegro_gl_display_info.accum_size.rgba.b,
00493                     allegro_gl_display_info.accum_size.rgba.a
00494                     );
00495     if (!_amesa.visual) {
00496         TRACE("** ERROR ** amesa_create_window: Unable to create AMesa "
00497               "Visual\n");
00498         return 1;
00499     }
00500 
00501     _amesa.context = AMesaCreateContext(_amesa.visual, NULL);
00502     if (!_amesa.context) {
00503         TRACE("** ERROR ** amesa_create_window: Unable to create AMesa "
00504               "Context\n");
00505         AMesaDestroyVisual(_amesa.visual);
00506         return 1;
00507     }
00508 
00509     if ((screen->w != allegro_gl_display_info.w)
00510      || (screen->h != allegro_gl_display_info.h)) {
00511 
00512         subscreen = create_sub_bitmap(screen, 0, 0,
00513                           allegro_gl_display_info.w, allegro_gl_display_info.h);
00514 
00515         _amesa.buffer = AMesaCreateBuffer(_amesa.visual, subscreen);
00516 
00517         TRACE("** Note ** amesa_create_window: Screen : %ix%i %i bpp\n",
00518               ubscreen->w, subscreen->h, bitmap_color_depth(subscreen));
00519     }
00520     else {
00521         _amesa.buffer = AMesaCreateBuffer(_amesa.visual, screen);
00522     }
00523 
00524     if (!_amesa.buffer) {
00525         AMesaDestroyContext(_amesa.context);
00526         AMesaDestroyVisual(_amesa.visual);
00527         TRACE("** ERROR ** amesa_create_window: Unable to create AMesa "
00528               "Buffer\n");
00529         return 1;
00530     }
00531 
00532     if (!AMesaMakeCurrent(_amesa.context, _amesa.buffer)) {
00533         AMesaDestroyContext(_amesa.context);
00534         AMesaDestroyVisual(_amesa.visual);
00535         AMesaDestroyBuffer(_amesa.buffer);
00536         TRACE("** ERROR ** amesa_create_window: Unable to make context "
00537               "current\n");
00538         return 1;
00539     }
00540 
00541     saved_screen = screen;
00542     return 0;
00543 }
00544 
00545 
00546 
00547 static BITMAP *allegro_gl_amesa_create_screen_bitmap (GFX_DRIVER *drv,
00548                                                       int w, int h, int depth)
00549 {
00550     drv->w = w;
00551     drv->h = h;
00552     drv->linear        = amesa_gfx_driver->linear;
00553     drv->bank_size     = amesa_gfx_driver->bank_size;
00554     drv->bank_gran     = amesa_gfx_driver->bank_gran;
00555     drv->vid_mem       = amesa_gfx_driver->vid_mem;
00556     drv->vid_phys_base = amesa_gfx_driver->vid_phys_base;
00557 
00558     return AMesaGetColorBuffer(_amesa.buffer, AMESA_ACTIVE);
00559 }
00560 
00561 
00562 
00563 static void __allegro_gl_init_texture_read_format(void)
00564 {
00565     /* 8 bpp (true color mode) */
00566     __allegro_gl_texture_read_format[0] = GL_UNSIGNED_BYTE_3_3_2;
00567 
00568     /* 15 bpp */
00569     if (_rgb_r_shift_15 > _rgb_b_shift_15) {
00570         __allegro_gl_texture_read_format[1] = GL_UNSIGNED_SHORT_5_5_5_1;
00571         if (_rgb_r_shift_15 == 10) {
00572             __allegro_gl_texture_components[1] = GL_BGRA;
00573         }
00574     }
00575     else {
00576         __allegro_gl_texture_read_format[1] = GL_UNSIGNED_SHORT_1_5_5_5_REV;
00577     }
00578 
00579     /* 16 bpp */
00580     if (_rgb_r_shift_16 > _rgb_b_shift_16) {
00581         __allegro_gl_texture_read_format[2] = GL_UNSIGNED_SHORT_5_6_5;
00582     }
00583     else {
00584         __allegro_gl_texture_read_format[2] = GL_UNSIGNED_SHORT_5_6_5_REV;
00585     }
00586 
00587     /* 24 bpp */
00588     __allegro_gl_texture_read_format[3] = GL_UNSIGNED_BYTE;
00589 
00590     /* 32 bpp */
00591     if (_rgb_r_shift_32 > _rgb_b_shift_32) {
00592         __allegro_gl_texture_read_format[4] = GL_UNSIGNED_INT_8_8_8_8_REV;
00593         if (_rgb_r_shift_32 == 16) {
00594             __allegro_gl_texture_components[4] = GL_BGRA;
00595         }
00596     }
00597     else {
00598         __allegro_gl_texture_read_format[4] = GL_UNSIGNED_BYTE;
00599     }
00600 }
00601 
00602 
00603 
00604 /******************************/
00605 /* AllegroGL driver functions */
00606 /******************************/
00607 
00608 /* flip:
00609  *  Does a page flip / double buffer copy / whatever it really is.
00610  */
00611 static void amesa_flip (void)
00612 {
00613     AMesaSwapBuffers (_amesa.buffer);
00614 }
00615 
00616 
00617 
00618 /* gl_on, gl_off:
00619  *  Switches to/from GL mode.
00620  */
00621 static void amesa_gl_on (void)
00622 {
00623 }
00624 
00625 
00626 
00627 static void amesa_gl_off (void)
00628 {
00629 }
00630 
00631 
00632 
00633 /*****************/
00634 /* Driver struct */
00635 /*****************/
00636 
00637 static struct allegro_gl_driver allegro_gl_amesa = {
00638     amesa_flip,
00639     amesa_gl_on,
00640     amesa_gl_off
00641 };
00642 
allegro4.4-4.4.2/addons/allegrogl/docs/html/doxygen.png000066400000000000000000000075461173507505700227210ustar00rootroot00000000000000‰PNG  IHDRh ;ˆØ-IDATxí]{XŒyÿ¾sZ%Ê”NF:¨´FåЪքbÝè@;~ÓŽÃ"DH‘ÚZ•ð–m_Œéè4ÄÙÚ!ë-‡2«U«Ce[Š"§š_ñÌ3óLSìõ¾ï¾öº|®««y>§ïý¹ïïá_ ™L†öþZ·¼ß¦ajëñ®¹L•oñúþ}«.Íë2Þãû$Zöå);*.d¥~Ûìß³wˆ—·'ˆâ0³Ëâþ@áû!ZZeÊÿÁÞͺwÓøÏÔÚ‰ù?ØO =\Lâ[òg²dxr0Ð —€¤Rrj·Jž€‘*í.WJN5¨äÉqÈMªÔ[mºÞ•’Sb58™Ä¼RB5½¥•’SRus[2<ÙÄ %·˜˜•²V'˜ê+%§$fv˜ØÄºR»«Kó$ ¡¥C 4ã+xº˜£½sQÙ}f¶ðÀ[²vôZ €ç6c}”½!,Lt×ï<ÂÅ«µ°dx†H)/ÎÙfí襧¥C«1¶v£ôº[~– ÏÑåÅ9%DÏDKgžrN}M9úY««3*/Îi謷%ÓU^œ#¶vôr'p²=]ÌÑ_§7®ßy„ìS¸ª½ëkÊaÉð´-/Î!E²vôâà902œíÁÉ–FæŸ*¸Å,ý­– O!1k>QÓÓ³¦°dx¦X:ûð¼=GÃÂD×ï<ÂþÃ'¸fvRªKó‚UZjbóièþ¤`èõýˆtº9cùœ‘xÕÚªV W­­°sžabóièw1ó1x%îæhŒ¹Þ¶¸9׉>oÕ®hkG¯~¥—Nl°sž"^™ÀdŽ2%sw…ø¨•¼W­­‹ìœ§D¸z¯àí W †Æç˜8c>‚í1”ô‡m·Bvêî«ÖÖ8܉ÞAˆZò þT…u—r­½ª´th9kÂÖRêåŸSfÛþ/d§–°‰¾äœ1kçb„A.ܸ@ø“+;:j ÛÚÑË«ôÒ‰|#­Ýp4i®â¨]¼â߯óV~éØÇŒ…xfv$Õ¥y| S[ö;BOK‡V“ÅßÖàÎÌa 4x0¶Ï:ÂßDN54>Çgœõxp÷ªo;Z:´¬œÃÉ”º€ÕÇðë™ïbÛ‡ªöü|Ñ^TŠ7=$4)L!Ü/åuü’#)9/rqÃ%îØÅï¬~a”çŽÅ-à¸poE ‚”®,|gŽ¥m /9/ŠsÃâ˜Ø|šœ±c Ó/åu¨ü Êë€P\…aÁÂ’ó¢‡1,¦¥Ó¢Ã;ueòyªKó\ä…°üÃ"7-K!3>õ2ÊËËamm åÚÈr7M.(~[2ÓÝÉ„Œ]©¨C<¿í»b9Ç[)v[~Ñ,_º@\|î8ËqÜ´{· Ð}QÞ”ugr7àÛÈJ]|Úe¤ïÚ`ƒ–­æçÿ¤à™4s5Ü+µÕÒ¡•©Æ\§áéãû¶Ù•ýxàJ,ûÌudùùs&@yŽõI…eD…Ÿ;ç8nZÁž={ʘfóQU|X ÞØÚ)ض˜"ÞtîVÜ-ÏwÐo¨ãç¢ý‰œöJy>¶6è°¹ ÌFrÊf¥ÑÍú’ KbÏà¼(!@~»ó³) F¹{€í€Ave'3£Hÿ£¦˜î»Íu @³¯Aò±¬$èj÷"s&û…½&ób~¶t”»w¢ÿ¼¼¥þŠ·öQÓ J~Iå âJÚö½˜Ÿ]=ÊÝ;=|S{ºû™Éç‘“nçÊÜ9ôË¿ÈõË„.{ù®‰Ü´`Œb³ßÅÊå ÅâÚž)†j\Þ€ÔΕ›ÞY_ÂE_¸â.gÚ0uõ‹‘Ÿ‰2ݪiDàWËÐÜX'ÖìkÀÌÿº©ü–ñqýòV¶gDO³¯Ý„¦âÁÔôçE 6È ä1cZŒ¦ÄÄ—n£¹±NXxú(¿] ±ãgL_ºM!ÓÐb4Ü+e´´Ê¤âŽdüƒç62[é£]Am­ž,b÷@Jáé£Õ„ÿð‘Ü_Ù,Wºˆr€‘®Îèr_g8ÕÕ&(ÁQAäÛ4·­Ÿò.«ö—¯­ajëAïghS–öÝFJËÛhheg©‹³;Lýcs é/¼RƒÈõËÄ¢ì,‘—¾84†íõ‰9™óõ:n–œ`‰²³Ä,o_ï~†6YIqaÐÑî¥vÊèã¸v>=V”E¹æXÞ¾5™é=uu›^À/ °A”eD䆸ÍX¹j®S¬‘#§Ï^Ëžç3œŒÇì-ÂÙ£[Ã@µövmæÏ ’X ÊÎÊW¤×vú9šÚúѽµõQ_{ͽ3žäW\ø¦æØ:p¤ajëeIÉ)tšâîŽåáܱ8Iû£>xødÆöEóöëd:ÛŒ4µõk¾OŽƒNI¼‰¨½q>m•á1!)[©›Vàb47ýa @æšṉ̃ p…%5Pþ~üä¾Z‚æ¦?| 3³•0DN  á}® Unû¬@ú® » 3¹ÌÁÃ'‹Tç(,©ÁÏ—ïÂÁÊ^.ŠM¤ÄA8a?šUÙ¾äJ<§à2S÷ þ~…@=hjë3-GÍÄ|ŸÈ8Y.¯—¨®]XRƒèËIT9X²A€›¿ž$ÚéÇÛÈõ™hIPvã!ÀvHÿ°}Úo)Ͷ‡8rŠßš ¶=…Ч*^÷˜éiEïŸÂ«8‘"<˜Ìö Ht™¶œ·"Б²æ–͘á¿Êx.üZ‹˜M!b~ƒé Ã!c ’bwÀ·zëqT\È L*a.ˆŒÙÁP7:Û*(FÁñøpáÁô8¶O@â¿5<å9•17>yö“1z¸a‡zs{/Q†9æ‘ ´j}S¹vYD*n]Í!rÐhyakÔj ™Ê„«úgúÍ‘ d¦©­_¾*llé]^&}ˆ˜¨ÍhnúÃÛpȨèí[¨ä.Y»µ7..ÐÔÖOŽÚ²ÆµÉX|Úeœ%¤ÈL%äL¿9e ‰Étå¼ÇO^ (ˆÛp 3U±%ßär ‡ŒJŽ ›§vÎ2éCÊ Äzá2SãfúÍ1êÃ]Ïõ™@ÝÈ™¼€ÄÜn’èÛp%®Ö"nËJR µß2GÛ+Z™Š[¥?’@„½[PèâÙcÐWKþÂÕZìÛó=’â×Q÷ŸšiøÏäôîÓ?yê¬E`3‡ª+Wá‡ý;ñìÉÃŽöîÓ¿fóæHŠÛÒ%¸x2!%#Mì?;p)î°™*à²u;p_zÉ%#M !pˆ‚WÇR†Š«phϦÝi‚Eª8ügFôîÓ?ÔÁíKÈïü²ëp)_+Ç©XÀPÅž‘&ˆ#jðÌí&q=˜n˜0ÚLí¬×n>Dá•\Ê¢á÷J[ts»I¢è5³)¼&~J ¤:Úè´µAB„î@‹PKÆ´×doCú)ñÑaSteLgÓ.㦶襩›Àÿ?MàÙ¿|Ö¸bÙšs+s’¤Ÿ¸†ÑtïÙ›À@€<öòyÓ¶_=ï ‡žok®Ô‡Û¶½ÚžŸ¿x¾Œª¢Ã=ä_C?ÝlÐßB™«WŠp·òœ‰ÙcK3=hh(b%ùÐ7u@}mEû»ÃtØxØØØâRÁ)ÔUÿ¢%“2™ ݺ)©Ø™¢;¸œŸnÝ{†®ÃÆÎ†‰¡î_2Ÿ´úªŠ ý‘ýLKϲַÆöEe÷¡A(ô¤ù%ž?iÀÓÆßÓ¸›`N·zýàëÑ,ñðÞo´w¯ÊNõ{elЧ‡òÉ«}ð·êq¥ì&ªKsñüÉÃän=>º`á°±³Ýÿ*q:½âht§¿Õw_Z”ÞòòÙ^š:cå¾nÝ{âùÓ†‹Ýº÷Ì`N£;‘×›Üj*ÿµ½¥å¥K¯Þ}^4?&ý=zi¡—¦zkõCcýPBht'×ÿÑ|UE‡ä1 ý;ž&5v›øßõëÛµ]@kS}ðÿpŽªª¢ÃâÕ¥y &þ>Ø{fÝ>Pð~ÛÿÞžk˜^œIEND®B`‚allegro4.4-4.4.2/addons/allegrogl/docs/html/files.html000066400000000000000000000125251173507505700225170ustar00rootroot00000000000000 AllegroGL: File List

File List

Here is a list of all documented files with brief descriptions:
aglf.c [code]Text output and font support in OpenGL
alleggl.c [code]Allegro-OpenGL interfacing
alleggl.h [code]Main header file for AllegroGL
allglint.h [code]
djgpp.c [code]
fontconv.c [code]Allegro FONT conversion routines
glext.c [code]OpenGL extension management
glvtable.c [code]Allegro->OpenGL conversion vtable
glvtable.h [code]
gui.c [code]AllegroGL GUI wrappers
mainpage.foo [code]This file only contains the information useful for the main page of the documentation - There is no code here
math.c [code]Converting mathematical structures from Allegro to OpenGL
scorer.c [code]Scoring system for screen mode selection (internal)
texture.c [code]AllegroGL texture management
videovtb.c [code]Video bitmaps (ie
win.c [code]
x.c [code]
allegro4.4-4.4.2/addons/allegrogl/docs/html/fontconv_8c.html000066400000000000000000000366101173507505700236440ustar00rootroot00000000000000 AllegroGL: fontconv.c File Reference

fontconv.c File Reference

Allegro FONT conversion routines. More...

#include <math.h>
#include <string.h>
#include <stdio.h>
#include <allegro.h>
#include <allegro/internal/aintern.h>
#include "alleggl.h"
#include "allglint.h"
#include <GL/glu.h>

Go to the source code of this file.

Defines

  • #define PREFIX_I   "agl-font INFO: "
  • #define PREFIX_W   "agl-font WARNING: "
  • #define PREFIX_E   "agl-font ERROR: "
  • #define FONT_CHARACTER_SPACING   2
  • #define MIN_TEXTURE_SIZE   2
  • #define NUM_TEXTURE_SIZE   13

Typedefs

  • typedef struct texture_size texture_size

Functions

  • static int agl_get_font_height (AL_CONST FONT *f)
  • static int agl_char_length (const FONT *f, int ch)
  • static int agl_text_length (const FONT *f, const char *str)
  • static int agl_get_font_ranges (FONT *f)
  • static int agl_get_font_range_begin (FONT *f, int range)
  • static int agl_get_font_range_end (FONT *f, int range)
  • static FONT * agl_extract_font_range (FONT *f, int start, int end)
  • static FONT * agl_merge_fonts (FONT *f1, FONT *f2)
  • static int agl_transpose_font (FONT *f, int drange)
  • static void aglf_convert_allegro_font_to_bitmap (FONT_AGL_DATA *dest, FONT *f, void *src, int *height)
  • static void aglf_convert_allegro_font_to_texture (FONT_AGL_DATA **dest, FONT *f, void *src, int *height, float scale, GLint format)
  • static GLuint aglf_upload_texture (BITMAP *bmp, GLint format, int has_alpha)
  • static int aglf_check_texture (BITMAP *bmp, GLint format, int has_alpha)
  • static BITMAP * look_for_texture (int beg, int end, AGL_GLYPH *glyphs, int max_w, int max_h, int total_area, GLint format, int has_alpha)
  • static int iroundf (float v)
  • static float agl_char_length_fractional (const FONT *f, int ch)
  • static int create_textured_font_call_lists (AGL_GLYPH *coords, int max, BITMAP *bmp, float scale, int *height)
  • static FONT_AGL_DATA * copy_glyph_range (FONT_AGL_DATA *fad, int start, int end, int *height)
  • FONT * allegro_gl_convert_allegro_font (FONT *f, int type, float scale)
    Equivalent to:
  • FONT * allegro_gl_convert_allegro_font_ex (FONT *f, int type, float scale, GLint format)
    Converts a regular Allegro FONT to the AGL format for 3D display.
  • static int sort_glyphs (const void *c1, const void *c2)
  • static int unsort_glyphs (const void *c1, const void *c2)
  • static int sort_textures (const void *c1, const void *c2)
  • static int aglf_sort_out_glyphs (BITMAP *bmp, AGL_GLYPH *glyphs, const int beg, const int end)
  • static int split_font (FONT *f, void *source, void **dest1, void **dest2)
  • static void destroy_split_font (FONT *f, union mixed_ptr range1, union mixed_ptr range2)
  • static int do_crop_font_range (FONT *f, AGL_GLYPH *glyphs, int beg, int end)
  • static int crop_font_range (FONT *f, void *src, int beg, int end, AGL_GLYPH *glyphs, int *net_area, int *gross_area, int *max_w, int *max_h)
  • static int dummy_render_char (AL_CONST FONT *f, int ch, int fg, int bg, BITMAP *bmp, int x, int y)
  • static int draw_glyphs (BITMAP *bmp, FONT *f, GLint format, int beg, int end, AGL_GLYPH *glyphs)

Variables

  • FONT_VTABLE _agl_font_vtable
  • FONT_VTABLE * font_vtable_agl = &_agl_font_vtable

Detailed Description

Allegro FONT conversion routines.

Notes: - Depends on the Allegro's FONT structure remaining intact. Bugs: - Bitmapped font support is flakey at best.

Definition in file fontconv.c.


Variable Documentation

FONT_VTABLE _agl_font_vtable
Initial value:
 {
    agl_get_font_height,
    agl_char_length,
    agl_text_length,
    NULL, 
    NULL, 
    allegro_gl_destroy_font,
    agl_get_font_ranges,
    agl_get_font_range_begin,
    agl_get_font_range_end,
    agl_extract_font_range,
    agl_merge_fonts,

    agl_transpose_font

}

Definition at line 64 of file fontconv.c.

allegro4.4-4.4.2/addons/allegrogl/docs/html/fontconv_8c_source.html000066400000000000000000004170251173507505700252270ustar00rootroot00000000000000 AllegroGL: fontconv.c Source File

fontconv.c

Go to the documentation of this file.
00001 /* This code is (C) AllegroGL contributors, and double licensed under
00002  * the GPL and zlib licenses. See gpl.txt or zlib.txt for details.
00003  */
00013 #include <math.h>
00014 #include <string.h>
00015 #include <stdio.h>
00016 
00017 #include <allegro.h>
00018 #include <allegro/internal/aintern.h>
00019 
00020 #include "alleggl.h"
00021 #include "allglint.h"
00022 
00023 #ifdef ALLEGRO_MACOSX
00024 #include <OpenGL/glu.h>
00025 #else
00026 #include <GL/glu.h>
00027 #endif
00028 
00029 #if defined ALLEGRO_WITH_XWINDOWS && !defined ALLEGROGL_GENERIC_DRIVER
00030 #include <xalleg.h>
00031 #include <GL/glx.h>
00032 #endif
00033 
00034 #define PREFIX_I                "agl-font INFO: "
00035 #define PREFIX_W                "agl-font WARNING: "
00036 #define PREFIX_E                "agl-font ERROR: "
00037 
00038 
00039 /* Number of pixels between characters in a textured font.
00040  */
00041 #define FONT_CHARACTER_SPACING 2
00042 
00043 /* Uncomment to have the font generator dump screenshots of the textures it
00044  * generates.
00045  */
00046 /* #define SAVE_FONT_SCREENSHOT */
00047 
00048 
00049 static int agl_get_font_height(AL_CONST FONT *f);
00050 static int agl_char_length(const FONT *f, int ch);
00051 static int agl_text_length(const FONT *f, const char *str);
00052 
00053 static int agl_get_font_ranges(FONT *f);
00054 static int agl_get_font_range_begin(FONT *f, int range);
00055 static int agl_get_font_range_end(FONT *f, int range);
00056 static FONT *agl_extract_font_range(FONT *f, int start, int end);
00057 static FONT *agl_merge_fonts(FONT *f1, FONT *f2);
00058 
00059 #if GET_ALLEGRO_VERSION() >= MAKE_VER(4, 2, 0)
00060 static int agl_transpose_font(FONT *f, int drange);
00061 #endif
00062 
00063 
00064 FONT_VTABLE _agl_font_vtable = {
00065     agl_get_font_height,
00066     agl_char_length,
00067     agl_text_length,
00068     NULL, /* render_char */
00069     NULL, /* render */
00070     allegro_gl_destroy_font,
00071     agl_get_font_ranges,
00072     agl_get_font_range_begin,
00073     agl_get_font_range_end,
00074     agl_extract_font_range,
00075     agl_merge_fonts,
00076 #if GET_ALLEGRO_VERSION() >= MAKE_VER(4, 2, 0)
00077     agl_transpose_font
00078 #endif
00079 };
00080 
00081 
00082 FONT_VTABLE *font_vtable_agl = &_agl_font_vtable;
00083 
00084 static void aglf_convert_allegro_font_to_bitmap(FONT_AGL_DATA *dest, FONT *f,
00085                                                 void *src, int *height);
00086 static void aglf_convert_allegro_font_to_texture(FONT_AGL_DATA **dest, FONT *f,
00087                              void *src, int *height, float scale, GLint format);
00088 static GLuint aglf_upload_texture(BITMAP *bmp, GLint format, int has_alpha);
00089 static int aglf_check_texture(BITMAP *bmp, GLint format, int has_alpha);
00090 static BITMAP* look_for_texture(int beg, int end, AGL_GLYPH *glyphs,
00091                                 int max_w, int max_h, int total_area,
00092                                 GLint format, int has_alpha);
00093 
00094 
00095 
00096 union mixed_ptr {
00097     FONT_MONO_DATA* mf;
00098     FONT_COLOR_DATA* cf;
00099     void *ptr;
00100 };
00101 
00102 
00103 /* Stores info about a texture size */
00104 typedef struct texture_size {
00105     int w, h;
00106 } texture_size;
00107 
00108 
00109 
00110 static int agl_get_font_height(AL_CONST FONT *f) {
00111     return f->height;
00112 }
00113 
00114 
00115 /* iroundf:
00116  * Round float to nearest integer, away from zero.
00117  */
00118 static int iroundf(float v) {
00119     float f = floor(v);
00120     float c = ceil(v);
00121 
00122     if (v >= 0) {
00123         /* distance to ceil smaller than distance to floor */
00124         if ((c - v) < (v - f))
00125             return (int)c;
00126         else
00127             return (int)f;
00128     }
00129     else {
00130         /* distance to ceil smaller than distance to floor */
00131         if ((c - v) < (v - f)) 
00132             return (int)f;
00133         else
00134             return (int)c;
00135     }
00136 }
00137 
00138 
00139 
00140 /* agl_char_length_fractional:
00141  * Returns the width, in fractional pixels of the given character.
00142  */
00143 static float agl_char_length_fractional(const FONT *f, int ch) {
00144     FONT_AGL_DATA *fad = f->data;
00145 
00146     if (fad->type == AGL_FONT_TYPE_TEXTURED) {
00147         while (fad) {
00148             if (ch >= fad->start && ch < fad->end) {
00149                 AGL_GLYPH *coords = &(fad->glyph_coords[ch - fad->start]);
00150                 return (coords->offset_x + coords->w + coords->offset_w)
00151                        / fabs(fad->scale);
00152             }
00153 
00154             fad = fad->next;
00155         }
00156     }
00157     else if (fad->type == AGL_FONT_TYPE_BITMAP) {
00158         while (fad) {
00159             if (ch >= fad->start && ch < fad->end) {
00160                 FONT_GLYPH **gl = fad->data;
00161                 return gl[ch - fad->start]->w;
00162             }
00163 
00164             fad = fad->next;
00165         }
00166     }
00167 
00168     /* if we don't find the character, then search for the missing
00169      * glyph, but don't get stuck in a loop. */
00170     if (ch != allegro_404_char)
00171         return agl_char_length_fractional(f, allegro_404_char);
00172 
00173     return 0;
00174 }
00175 
00176 
00177 
00178 /* agl_char_length:
00179  * font vtable entry
00180  * Returns the width, in pixels of the given character.
00181  */
00182 static int agl_char_length(const FONT *f, int ch) {
00183     return iroundf(agl_char_length_fractional(f, ch));
00184 }
00185 
00186 
00187 
00188 /* agl_text_length:
00189  * font vtable entry
00190  * Returns the length, in pixels, of a string as rendered in a font.
00191  */
00192 static int agl_text_length(const FONT *f, const char *str) {
00193     int ch = 0;
00194     float l = 0;
00195     const char *p = str;
00196     ASSERT(f);
00197     ASSERT(str);
00198 
00199     while ( (ch = ugetxc(&p)) ) {
00200         l += agl_char_length_fractional(f, ch);
00201     }
00202 
00203     return iroundf(l);
00204 }
00205 
00206 
00207 
00208 /* agl_get_font_ranges:
00209  * font vtable entry
00210  * Returns the number of character ranges in a font, or -1 if that information
00211  *   is not available.
00212  */
00213 static int agl_get_font_ranges(FONT *f) {
00214     FONT_AGL_DATA *fad;
00215     int ranges = 0;
00216 
00217     if (!f)
00218         return 0;
00219 
00220     fad = (FONT_AGL_DATA*)(f->data);
00221 
00222     while (fad) {
00223         FONT_AGL_DATA *next = fad->next;
00224 
00225         ranges++;
00226         if (!next)
00227             return ranges;
00228         fad = next;
00229     }
00230 
00231     return -1;
00232 }
00233 
00234 
00235 
00236 /* agl_get_font_range_begin:
00237  * font vtable entry
00238  * Get first character for font.
00239  */
00240 static int agl_get_font_range_begin(FONT *f, int range) {
00241     FONT_AGL_DATA *fad;
00242     int n = 0;
00243 
00244     if (!f || !f->data)
00245         return -1;
00246 
00247     if (range < 0)
00248         range = 0;
00249 
00250     fad = (FONT_AGL_DATA*)(f->data);
00251     while (fad && n <= range) {
00252         FONT_AGL_DATA *next = fad->next;
00253 
00254         if (!next || range == n)
00255             return fad->start;
00256         fad = next;
00257         n++;
00258     }
00259 
00260     return -1;
00261 }
00262 
00263 
00264 
00265 /* agl_get_font_range_end:
00266  * font vtable entry
00267  * Get last character for font range.
00268  */
00269 static int agl_get_font_range_end(FONT *f, int range) {
00270     FONT_AGL_DATA* fad = 0;
00271     int n = 0;
00272 
00273     if (!f || !f->data)
00274         return -1;
00275 
00276     fad = (FONT_AGL_DATA*)(f->data);
00277 
00278     while (fad && (n <= range || range == -1)) {
00279         FONT_AGL_DATA *next = fad->next;
00280         if (!next || range == n)
00281             return fad->end - 1;
00282         fad = next;
00283         n++;
00284     }
00285     
00286     return -1;
00287 }
00288 
00289 
00290 
00291 /* Creates a call lists from given glyph coords. Returns list base.*/
00292 static int create_textured_font_call_lists(AGL_GLYPH *coords, int max, BITMAP *bmp,
00293                                                     float scale, int *height) {
00294     GLuint list;
00295     int i;
00296 
00297     int rev = scale < 0 ? 1 : 0;
00298     scale = fabs(scale);
00299 
00300     list = glGenLists(max);
00301         
00302     for (i = 0; i < max; i++) {
00303         /* Coords of glyph in texture (texture coords) */
00304         float tx = (float)coords[i].x / bmp->w;
00305         float ty = 1.0 - (float)coords[i].y / bmp->h;
00306         /* Size of glyph in texture (texture coords) */
00307         float dtx = (float)(coords[i].w) / bmp->w;
00308         float dty = (float)(coords[i].h) / bmp->h;
00309 
00310         /* Offset to apply to glyph (output coords) */
00311         float xoffs = (float)coords[i].offset_x / scale;
00312         float yoffs = (float)coords[i].offset_y / scale;
00313         /* Size of rendered glyph (output coords) */
00314         float woffs = (float)coords[i].w / scale;
00315         float hoffs = (float)coords[i].h / scale;
00316 
00317         /* Size of overall screen character including dead space */
00318         float sizew = (float)(coords[i].offset_x + coords[i].w
00319                     + coords[i].offset_w) / scale;
00320         int sizeh = iroundf((coords[i].offset_y + coords[i].h
00321                     + coords[i].offset_h) / scale);
00322 
00323         if ((*height) < sizeh)
00324             *height = sizeh;
00325 
00326         if (rev) {
00327             hoffs = -hoffs;
00328             yoffs = -yoffs;
00329         }
00330 
00331         glNewList(list + i, GL_COMPILE);
00332             
00333         glBegin(GL_QUADS);
00334             glTexCoord2f(tx, ty);
00335             glVertex2f(xoffs, -yoffs);
00336 
00337             glTexCoord2f(tx + dtx, ty);
00338             glVertex2f(xoffs + woffs, -yoffs);
00339 
00340             glTexCoord2f(tx + dtx, ty - dty);
00341             glVertex2f(xoffs + woffs, -yoffs - hoffs);
00342 
00343             glTexCoord2f(tx, ty - dty);
00344             glVertex2f(xoffs, -yoffs - hoffs);
00345         glEnd();
00346 
00347         glTranslatef(sizew, 0, 0);
00348 
00349         glEndList();
00350     }
00351 
00352     return list;
00353 }
00354 
00355 
00356 
00357 /* copy_glyph_range:
00358  * Copies part of glyph range.
00359  */
00360 static FONT_AGL_DATA* copy_glyph_range(FONT_AGL_DATA *fad, int start, int end,
00361                                                                 int *height) {
00362     int i, count, w = 0, h = 0;
00363     AGL_GLYPH *coords;
00364     BITMAP *bmp, *srcbmp;
00365     FONT_AGL_DATA *newfad = NULL;
00366 
00367     if (fad->type != AGL_FONT_TYPE_TEXTURED)
00368         return NULL;
00369 
00370     count = end - start;
00371 
00372     coords = malloc(count * sizeof (AGL_GLYPH));
00373         
00374     /* for now, just copy glyph coords of the range */
00375     for (i = 0; i < count; i++) {
00376         coords[i] = fad->glyph_coords[start - fad->start + i];
00377         coords[i].glyph_num = i;
00378     }
00379             
00380     /* calculate the width of the glyphs and find the max height */ 
00381     for (i = 0; i < count; i++) {
00382         int hh = coords[i].h + coords[i].offset_y + coords[i].offset_h;
00383         if (h < hh)
00384             h = hh;
00385         w += coords[i].w + coords[i].offset_w + coords[i].offset_x;
00386     }
00387 
00388     srcbmp = (BITMAP*)fad->data;
00389 
00390     /* allocate a new bitmap to hold new glyphs */
00391     w = __allegro_gl_make_power_of_2(w);
00392     h = __allegro_gl_make_power_of_2(h);
00393     bmp = create_bitmap_ex(bitmap_color_depth(srcbmp), w, h);
00394     if (!bmp) {
00395         TRACE(PREFIX_E "copy_glyph_range: Unable to create bitmap of size"
00396                 "%ix%i pixels!\n", w, h);
00397         free(coords);
00398         return NULL;
00399     }
00400 
00401     if (__allegro_gl_get_num_channels(fad->format) == 4) {
00402         clear_to_color(bmp, bitmap_mask_color(bmp));
00403     }
00404     else {
00405         clear_bitmap(bmp);
00406     }
00407 
00408     /* blit every glyph from the range to the new bitmap */
00409     w = 0;
00410     for (i = 0; i < count; i++) {
00411         int ch = start - fad->start + i;
00412         int ww = coords[i].w + coords[i].offset_w + coords[i].offset_x;
00413         blit(srcbmp, bmp, fad->glyph_coords[ch].x, 0, w, 0, ww, bmp->h);
00414         /* fix new glyphs coords while here */
00415         coords[i].x = w;
00416         w += ww;
00417     }
00418 
00419     newfad = malloc(sizeof(struct FONT_AGL_DATA));
00420 
00421     newfad->type = AGL_FONT_TYPE_TEXTURED;
00422     newfad->is_free_chunk = 0;
00423     newfad->scale = fad->scale;
00424     newfad->format = fad->format;
00425     newfad->has_alpha = fad->has_alpha;
00426     newfad->start = start;
00427     newfad->end = end;
00428     newfad->data = bmp;
00429     newfad->glyph_coords = coords;
00430     newfad->next = NULL;
00431     newfad->list_base = create_textured_font_call_lists(coords, count, bmp,
00432                                                     newfad->scale, height);
00433     newfad->texture = aglf_upload_texture(bmp, newfad->format, newfad->has_alpha);
00434 
00435     return newfad;
00436 }
00437 
00438 
00439 
00440 /* agl_extract_font_range:
00441  * font vtable entry
00442  * Extracts a glyph range from a given font and makes a new font of it.
00443  */
00444 static FONT *agl_extract_font_range(FONT *f, int start, int end) {
00445     FONT *retval = NULL;
00446     FONT_AGL_DATA *fad, *next, *newfad = NULL;
00447     int count;
00448 
00449     if (!f)
00450         return NULL;
00451 
00452     /* check if range boundaries make sense */
00453     if (start == -1 && end == -1) {
00454     }
00455     else if (start == -1 && end > agl_get_font_range_begin(f, -1)) {
00456     }
00457     else if (end == -1 && start <= agl_get_font_range_end(f, -1)) {
00458     }
00459     else if (start <= end && start != -1 && end != -1) {
00460     }
00461     else
00462         return NULL;
00463 
00464     fad = (FONT_AGL_DATA*)f->data;
00465 
00466     /* only textured fonts are supported */
00467     if (fad->type != AGL_FONT_TYPE_TEXTURED)
00468         return NULL;
00469 
00470     /* anticipate invalid range values */
00471     start = MAX(start, agl_get_font_range_begin(f, -1));
00472     if (end > -1) {
00473         end = MIN(end, agl_get_font_range_end(f, -1));
00474     }
00475     else {
00476         end = agl_get_font_range_end(f, -1);
00477     }
00478     end++;
00479 
00480     retval = malloc(sizeof (struct FONT));
00481     retval->height = 0;
00482     retval->vtable = font_vtable_agl;
00483 
00484     next = fad;
00485     count = end - start;
00486 
00487     while (next) {
00488         /* find the range that is covered by the requested range
00489          * check if the requested and processed ranges at least overlap
00490          *    or if the requested range wraps processed range.
00491          */
00492         if ((start >= next->start && start < next->end)
00493          || (end   <= next->end   && end   > next->start)
00494          || (start <  next->start && end   > next->end)) {
00495             int local_start, local_end;
00496 
00497             /* extract the overlapping range */
00498             local_start = MAX(next->start, start);
00499             local_end = MIN(next->end, end);
00500 
00501             if (newfad) {
00502                 newfad->next = copy_glyph_range(next, local_start, local_end,
00503                                                             &(retval->height));
00504                 newfad = newfad->next;
00505                 newfad->is_free_chunk = TRUE;
00506             }
00507             else {
00508                 newfad = copy_glyph_range(next, local_start, local_end,
00509                                                             &(retval->height));
00510                 retval->data = newfad;
00511             }
00512         }
00513             
00514         next = next->next;
00515     }
00516 
00517     return retval;
00518 }
00519 
00520 
00521 
00522 /* agl_merge_fonts:
00523  * font vtable entry
00524  * Merges f2 with f1 and returns a new font.
00525  */
00526 static FONT *agl_merge_fonts(FONT *f1, FONT *f2) {
00527     FONT *retval;
00528     FONT_AGL_DATA *fad1, *fad2, *fad = NULL;
00529     int phony = 0;
00530 
00531     if (!f1 || !f2)
00532         return NULL;
00533 
00534     fad1 = (FONT_AGL_DATA*)f1->data;
00535     fad2 = (FONT_AGL_DATA*)f2->data;
00536 
00537     /* fonts must be textured and of the same format */
00538     if (fad1->type != AGL_FONT_TYPE_TEXTURED ||
00539         fad2->type != AGL_FONT_TYPE_TEXTURED)
00540         return NULL;
00541 
00542     if (fad1->format != fad2->format)
00543         return NULL;
00544 
00545     /* alloc output font */
00546     retval = malloc(sizeof(struct FONT));
00547     retval->vtable = font_vtable_agl;
00548     retval->height = MAX(f1->height, f2->height);
00549 
00550     while (fad1 || fad2) {
00551         if (fad1 && (!fad2 || fad1->start < fad2->start)) {
00552             if (fad) {
00553                 fad->next = copy_glyph_range(fad1, fad1->start, fad1->end,
00554                                                                         &phony);
00555                 fad = fad->next;
00556                 fad->is_free_chunk = TRUE;
00557             }
00558             else {
00559                 fad = copy_glyph_range(fad1, fad1->start, fad1->end, &phony);
00560                 retval->data = fad;
00561             }
00562             fad1 = fad1->next;
00563         }
00564         else {
00565             if (fad) {
00566                 fad->next = copy_glyph_range(fad2, fad2->start, fad2->end,
00567                                                                     &phony);
00568                 fad = fad->next;
00569                 fad->is_free_chunk = TRUE;
00570             }
00571             else {
00572                 fad = copy_glyph_range(fad2, fad2->start, fad2->end, &phony);
00573                 retval->data = fad;
00574             }
00575             fad2 = fad2->next;
00576         }
00577     }
00578 
00579     return retval;
00580 }
00581 
00582 
00583 
00584 #if GET_ALLEGRO_VERSION() >= MAKE_VER(4, 2, 0)
00585 /* agl_transpose_font:
00586  * font vtable entry
00587  * Transposes characters in a font.
00588  */
00589 static int agl_transpose_font(FONT *f, int drange) {
00590     FONT_AGL_DATA* fad = 0;
00591 
00592     if (!f)
00593         return -1;
00594 
00595     fad = (FONT_AGL_DATA*)(f->data);
00596 
00597     while(fad) {
00598         FONT_AGL_DATA* next = fad->next;
00599         fad->start += drange;
00600         fad->end += drange;
00601         fad = next;
00602     }
00603 
00604     return 0;
00605 }
00606 #endif
00607 
00608 
00609 
00610 /* allegro_gl_convert_allegro_font_ex(FONT *f, int type, float scale, GLint format) */
00623 FONT *allegro_gl_convert_allegro_font(FONT *f, int type, float scale) {
00624     GLint format = allegro_gl_get_texture_format(NULL);
00625     return allegro_gl_convert_allegro_font_ex(f, type, scale, format);
00626 }
00627 
00628 
00629 
00630 /* allegro_gl_convert_allegro_font_ex(FONT *f, int type, float scale, GLint format) */
00688 FONT *allegro_gl_convert_allegro_font_ex(FONT *f, int type, float scale,
00689                                          GLint format) {
00690     int max = 0, height = 0;
00691     int i;
00692     FONT *dest;
00693     FONT_AGL_DATA *destdata;
00694     int has_alpha = 0;
00695 
00696     union {
00697         FONT_MONO_DATA* mf;
00698         FONT_COLOR_DATA* cf;
00699         void *ptr;
00700     } dat;
00701     
00702     if (!__allegro_gl_valid_context) {
00703         return NULL;
00704     }
00705 
00706     if (!f) {
00707         TRACE(PREFIX_E "convert_allegro_font: Null source\n");
00708         return NULL;
00709     }
00710 
00711     /* Make sure it's an Allegro font - we don't want any surprises */
00712 #if GET_ALLEGRO_VERSION() >= MAKE_VER(4, 2, 1)
00713     if (f->vtable != font_vtable_mono && f->vtable != font_vtable_color && f->vtable != font_vtable_trans) {
00714 #else
00715     if (f->vtable != font_vtable_mono && f->vtable != font_vtable_color) {
00716 #endif
00717         TRACE(PREFIX_I "convert_allegro_font: Source font is not "
00718               "in Allegro format\n");
00719         return NULL;
00720     }
00721 
00722     /* No vector fonts allowed as destination */
00723     if (type == AGL_FONT_TYPE_OUTLINE) {
00724         /* Can't convert bitmap to vector font */
00725         TRACE(PREFIX_I "convert_allegro_font: Unable to convert a "
00726               "pixmap font to a vector font.\n");
00727         return NULL;
00728     }
00729 
00730     /* Make sure the scaling factor is appropreate */
00731     if (fabs(scale) < 0.001) {
00732         TRACE(PREFIX_W "convert_allegro_font: Scaling factor might be "
00733               "too small: %f\n", scale);
00734     }
00735 
00736     /* Count number of ranges */
00737     max = get_font_ranges(f);
00738 
00739     /* There should really be an API for this */
00740     dest = (FONT*)malloc(sizeof(FONT));
00741     if (!dest) {
00742         TRACE(PREFIX_E "convert_allegro_font: Ran out of memory "
00743               "while allocating %i bytes\n", (int)sizeof(FONT));
00744         return NULL;
00745     }
00746     destdata = (FONT_AGL_DATA*)malloc(sizeof(FONT_AGL_DATA) * max);
00747     if (!destdata) {
00748         TRACE(PREFIX_E "convert_allegro_font: Ran out of memory "
00749               "while allocating %i bytes\n", (int)sizeof(FONT_AGL_DATA) * max);
00750         return NULL;
00751     }
00752     memset(destdata, 0, sizeof(FONT_AGL_DATA) * max);
00753     
00754     /* Construct the linked list */
00755     for (i = 0; i < max - 1; i++) {
00756         destdata[i].next = &destdata[i + 1];
00757     }
00758     destdata[max - 1].next = NULL;
00759     
00760     /* Set up the font */
00761     dest->data = destdata;
00762     dest->vtable = font_vtable_agl;
00763     dest->height = 0;
00764 
00765     destdata->type = type;
00766 
00767     if (type == AGL_FONT_TYPE_DONT_CARE) {
00768         destdata->type = AGL_FONT_TYPE_TEXTURED;
00769     }
00770 
00771 #if GET_ALLEGRO_VERSION() >= MAKE_VER(4, 2, 1)
00772     has_alpha = (f->vtable == font_vtable_trans);
00773 #endif
00774 
00775     /* Convert each range */
00776     dat.ptr = f->data;
00777 
00778     while (dat.ptr) {
00779 
00780         destdata->has_alpha = has_alpha;
00781 
00782         if (type == AGL_FONT_TYPE_BITMAP) {
00783             aglf_convert_allegro_font_to_bitmap(destdata, f, dat.ptr, &height);
00784         }
00785         else if (type == AGL_FONT_TYPE_TEXTURED) {
00786             aglf_convert_allegro_font_to_texture(&destdata, f, dat.ptr, &height,
00787                                                  scale, format);
00788         }
00789             
00790         if (height > dest->height) {
00791             dest->height = height;
00792         }
00793             
00794         dat.ptr = (is_mono_font(f) ? (void*)dat.mf->next : (void*)dat.cf->next);
00795         
00796         destdata = destdata->next;
00797     }
00798 
00799     return dest;
00800 }
00801 
00802 
00803 
00804 /* QSort helper for sorting glyphs according to width,
00805  * then height - largest first.
00806  */
00807 static int sort_glyphs(const void *c1, const void *c2) {
00808     AGL_GLYPH *g1 = (AGL_GLYPH*)c1;
00809     AGL_GLYPH *g2 = (AGL_GLYPH*)c2;
00810     
00811     if (g1->w < g2->w) {
00812         return 1;
00813     }
00814     else if (g1->w == g2->w) {
00815         return -g1->h + g2->h;
00816     }
00817     else {
00818         return -1;
00819     }
00820 }
00821 
00822 
00823 
00824 /* QSort helper for unsorting glyphs.
00825  */
00826 static int unsort_glyphs(const void *c1, const void *c2) {
00827     AGL_GLYPH *g1 = (AGL_GLYPH*)c1;
00828     AGL_GLYPH *g2 = (AGL_GLYPH*)c2;
00829     
00830     return g1->glyph_num - g2->glyph_num;
00831 }
00832 
00833 
00834 
00835 /* QSort helper for sorting textures by area.
00836  */
00837 static int sort_textures(const void *c1, const void *c2) {
00838     texture_size *t1 = (texture_size*)c1;
00839     texture_size *t2 = (texture_size*)c2;
00840     
00841     return t1->w * t1->h - t2->w * t2->h;
00842 }
00843 
00844 
00845 
00846 #ifdef SAVE_FONT_SCREENSHOT
00847 static void save_shot(BITMAP *bmp) {
00848 
00849     int i;
00850     char name[128];
00851 
00852     for (i = 0; i < 1000; i++) {
00853         /* TGA, in case it is a truecolor font with alpha */
00854         sprintf(name, "fonttest_%02i.tga", i);
00855         if (!exists(name)) {
00856             save_tga(name, bmp, NULL);
00857             break;
00858         }
00859     }
00860 }
00861 #endif
00862 
00863 
00864 
00865 /* Helper function. This will try to place all the glyphs in the bitmap the
00866  * best way it can
00867  */
00868 static int aglf_sort_out_glyphs(BITMAP *bmp, AGL_GLYPH *glyphs, const int beg,
00869                                 const int end) {
00870 
00871     int i, j;
00872     int last_line = 0;
00873     int last_x = 0;
00874 
00875     /* We now try to make all the glyphs fit on the bitmap */
00876     for (i = 0; i < end - beg; i++) {
00877         int collide = FALSE;
00878     
00879         /* Place glyphs on last_line */
00880         glyphs[i].x = last_x;
00881         glyphs[i].y = last_line;
00882         
00883         /* Check for collision */
00884         
00885         for (j = 0; j < i; j++) {
00886             if ((glyphs[i].x >= glyphs[j].x + glyphs[j].w)
00887                     || (glyphs[i].y >= glyphs[j].y + glyphs[j].h)
00888                     || (glyphs[j].x >= glyphs[i].x + glyphs[i].w)
00889                     || (glyphs[j].y >= glyphs[i].y + glyphs[i].h)) {
00890                 continue;
00891             }
00892             last_x = glyphs[j].x + glyphs[j].w;
00893             glyphs[i].x = last_x;
00894             j = 0;
00895         }
00896         
00897         if ((last_x + glyphs[i].w > bmp->w)
00898          || (last_line + glyphs[i].h > bmp->h)) {
00899             collide = TRUE;
00900         }
00901 
00902         if (collide) {
00903             /* If there was a collision, we need to find the sprite with
00904              * the smallest height that is still grater than last_line.
00905              * We also need to redo this glyph.
00906              */
00907             int min_line = bmp->h + 1;
00908             int min_glyph = -1;
00909 
00910             for (j = 0; j < i; j++) {
00911                 if ( glyphs[j].y + glyphs[j].h < min_line
00912                   && glyphs[j].y + glyphs[j].h
00913                   > last_line - FONT_CHARACTER_SPACING) {
00914 
00915                     min_line = glyphs[j].y + glyphs[j].h
00916                              + FONT_CHARACTER_SPACING;
00917                     min_glyph = j;
00918                 }
00919             }
00920             /* If it can't possibly all fit, failure */
00921             if (min_glyph == -1) {
00922                 TRACE(PREFIX_I "sort_out_glyphs: Unable to fit all glyphs into "
00923                       "the texture.\n");
00924                 return FALSE;
00925             }
00926             /* Otherwise, start over at the top of that glyph */
00927             last_x = glyphs[min_glyph].x;
00928             last_line = min_line;
00929 
00930             /* Redo this glyph */
00931             i--;
00932         }
00933         else {
00934             last_x += glyphs[i].w + FONT_CHARACTER_SPACING;
00935         }
00936     }
00937 
00938     /* All ok */
00939     return TRUE;
00940 }
00941 
00942 
00943 
00944 static int split_font(FONT *f, void *source, void **dest1, void **dest2) {
00945 
00946     union mixed_ptr range1, range2, src;
00947     int colored;
00948     int i;
00949     
00950     (*dest1) = NULL;
00951     (*dest2) = NULL;
00952     src.ptr = source;
00953     
00954     colored = (is_mono_font(f) ? FALSE : TRUE);
00955 
00956     /* Allocate the ranges that we need */
00957     range1.ptr = malloc(colored ? sizeof(FONT_COLOR_DATA)
00958                                 : sizeof(FONT_MONO_DATA));
00959     if (!range1.ptr) {
00960         TRACE(PREFIX_E "split_font() - Ran out of memory while "
00961               "trying ot allocate %i bytes.\n",
00962               colored ? (int)sizeof(FONT_COLOR_DATA)
00963               : (int)sizeof(FONT_MONO_DATA));
00964         return FALSE;
00965     }
00966     
00967     range2.ptr = malloc(colored ? sizeof(FONT_COLOR_DATA)
00968                                 : sizeof(FONT_MONO_DATA));
00969     if (!range2.ptr) {
00970         TRACE(PREFIX_E "split_font() - Ran out of memory while "
00971               "trying to allocate %i bytes.\n",
00972               colored ? (int)sizeof(FONT_COLOR_DATA)
00973                       : (int)sizeof(FONT_MONO_DATA));
00974         free(range1.ptr);
00975         return FALSE;
00976     }
00977     
00978     (*dest1) = range1.ptr;
00979     (*dest2) = range2.ptr;
00980     
00981     /* Now we split up the range */
00982     if (colored) {
00983         /* Half the range */
00984         int mid = src.cf->begin + (src.cf->end - src.cf->begin) / 2;
00985         
00986         range1.cf->begin = src.cf->begin;
00987         range1.cf->end = mid;
00988         range2.cf->begin = mid;
00989         range2.cf->end = src.cf->end;
00990         
00991         range1.cf->next = NULL;
00992         range2.cf->next = NULL;
00993         
00994         /* Split up the bitmaps */
00995         range1.cf->bitmaps = malloc(sizeof(BITMAP*)
00996                                         * (range1.cf->end - range1.cf->begin));
00997         if (!range1.cf->bitmaps) {
00998             TRACE(PREFIX_E "split_font() - Ran out of memory "
00999                   "while trying to allocate %i bytes.\n",
01000                   (int)sizeof(BITMAP*) * (range1.cf->end - range1.cf->begin));
01001             free(range1.ptr);
01002             free(range2.ptr);
01003             return FALSE;
01004         }
01005 
01006         range2.cf->bitmaps = malloc(sizeof(BITMAP*)
01007                                          * (range2.cf->end - range2.cf->begin));
01008         if (!range2.cf->bitmaps) {
01009             TRACE(PREFIX_E "split_font() - Ran out of memory "
01010                   "while trying to allocate %i bytes.\n",
01011                   (int)sizeof(BITMAP*) * (range2.cf->end - range2.cf->begin));
01012             free(range1.cf->bitmaps);
01013             free(range1.ptr);
01014             free(range2.ptr);
01015             return FALSE;
01016         }
01017 
01018         
01019         for (i = 0; i < (range1.cf->end - range1.cf->begin); i++) {
01020             range1.cf->bitmaps[i] = src.cf->bitmaps[i];
01021         }
01022         for (i = 0; i < (range2.cf->end - range2.cf->begin); i++) {
01023             range2.cf->bitmaps[i] =
01024                        src.cf->bitmaps[i + range2.cf->begin - range1.cf->begin];
01025         }
01026     }
01027     else {
01028         /* Half the range */
01029         int mid = src.mf->begin + (src.mf->end - src.mf->begin) / 2;
01030         
01031         range1.mf->begin = src.mf->begin;
01032         range1.mf->end = mid;
01033         range2.mf->begin = mid;
01034         range2.mf->end = src.mf->end;
01035         
01036         range1.mf->next = NULL;
01037         range2.mf->next = NULL;
01038         
01039         /* Split up the bitmaps */
01040         range1.mf->glyphs = malloc(sizeof(FONT_GLYPH*)
01041                                          * (range1.mf->end - range1.mf->begin));
01042         if (!range1.mf->glyphs) {
01043             TRACE(PREFIX_E "split_font() - Ran out of memory "
01044                   "while trying to allocate %i bytes.\n",
01045                 (int)sizeof(FONT_GLYPH*) * (range1.mf->end - range1.mf->begin));
01046             free(range1.ptr);
01047             free(range2.ptr);
01048             return FALSE;
01049         }
01050 
01051         range2.mf->glyphs = malloc(sizeof(FONT_GLYPH*)
01052                                          * (range2.mf->end - range2.mf->begin));
01053         if (!range2.mf->glyphs) {
01054             TRACE(PREFIX_E "split_font() - Ran out of memory "
01055                   "while trying to allocate %i bytes.\n",
01056                 (int)sizeof(FONT_GLYPH*) * (range2.mf->end - range2.mf->begin));
01057             free(range1.mf->glyphs);
01058             free(range1.ptr);
01059             free(range2.ptr);
01060             return FALSE;
01061         }
01062         
01063         for (i = 0; i < (range1.mf->end - range1.mf->begin); i++) {
01064             range1.mf->glyphs[i] = src.mf->glyphs[i];
01065         }
01066         for (i = 0; i < (range2.mf->end - range2.mf->begin); i++) {
01067             range2.mf->glyphs[i] =
01068                         src.mf->glyphs[i + range2.mf->begin - range1.mf->begin];
01069         }
01070     }
01071     
01072     return TRUE;
01073 }
01074 
01075 
01076 
01077 /* Destroys a split font */
01078 static void destroy_split_font(FONT *f, union mixed_ptr range1,
01079                                         union mixed_ptr range2) {
01080     
01081     if (!is_mono_font(f)) {
01082         free(range1.cf->bitmaps);
01083         free(range2.cf->bitmaps);
01084     }
01085     else {
01086         free(range1.mf->glyphs);
01087         free(range2.mf->glyphs);
01088     }
01089     
01090     free(range1.ptr);
01091     free(range2.ptr);
01092     
01093     return;
01094 }
01095 
01096 
01097 
01098 static int do_crop_font_range(FONT *f, AGL_GLYPH *glyphs, int beg, int end) {
01099 
01100     int i, j, k;
01101     int max = end - beg;
01102     char buf[32];
01103 
01104     /* Allocate a temp bitmap to work with */
01105     BITMAP *temp = create_bitmap(32, 32);
01106 
01107     if (!temp) {
01108         TRACE(PREFIX_E "crop_font_range - Unable to create "
01109               "bitmap of size: %ix%i!\n", 32, 32);
01110         goto error;
01111     }
01112     
01113     /* Crop glyphs */
01114     for (i = 0; i < max; i++) {
01115         int used = 0;
01116 
01117         if (glyphs[i].w > temp->w || glyphs[i].h > temp->h) {
01118             int old_w = temp->w, old_h = temp->h;
01119             destroy_bitmap(temp);
01120             temp = create_bitmap(old_w * 2, old_h * 2);
01121             if (!temp) {
01122                 TRACE(PREFIX_E "crop_font_range - Unable to "
01123                       "create bitmap of size: %ix%i!\n", old_w * 2, old_h * 2);
01124                 goto error;
01125             }
01126         }
01127         clear(temp);
01128 
01129         usetc(buf + usetc(buf, glyphs[i].glyph_num + beg), 0);
01130 
01131         textout_ex(temp, f, buf, 0, 0,
01132                     makecol_depth(bitmap_color_depth(temp), 255, 255, 255), 0);
01133 
01134         /* Crop top */
01135         for (j = 0; j < glyphs[i].h; j++) {
01136             used = 0;
01137 
01138             for (k = 0; k < glyphs[i].w; k++) {
01139                 if (getpixel(temp, k, j)) {
01140                     used = 1;
01141                     glyphs[i].offset_y += j;
01142                     glyphs[i].h -= j;
01143                     break;
01144                 }
01145             }
01146             if (used)
01147                 break;
01148         }
01149 
01150         /* If just the top crop killed our glyph, then skip it entirely */
01151         if (!used) {
01152             TRACE(PREFIX_I "crop_font_range: skipping glyph %i\n", i);
01153             glyphs[i].offset_y = 0;
01154             glyphs[i].offset_h = glyphs[i].h - 1;
01155             glyphs[i].offset_w = glyphs[i].w - 2;
01156             glyphs[i].h = 1;
01157             glyphs[i].w = 1;
01158             continue;
01159         }
01160         
01161         /* Crop bottom */
01162         j = glyphs[i].h + glyphs[i].offset_y - 1;
01163         for ( /* above */; j >= glyphs[i].offset_y; j--) {
01164             used = 0;
01165 
01166             for (k = 0; k < glyphs[i].w; k++) {
01167                 if (getpixel(temp, k, j)) {
01168                     used = 1;
01169                     glyphs[i].offset_h +=
01170                                        glyphs[i].h + glyphs[i].offset_y - j - 2;
01171                     glyphs[i].h -= glyphs[i].h + glyphs[i].offset_y - j - 1;
01172                     break;
01173                 }
01174             }
01175             if (used)
01176                 break;
01177         }
01178 
01179         /* Crop Left */
01180         for (j = 0; j < glyphs[i].w; j++) {
01181             used = 0;
01182 
01183             k = MAX(glyphs[i].offset_y - 1, 0);
01184             for (/* above */; k < glyphs[i].offset_y + glyphs[i].h + 1; k++) {
01185                 if (getpixel(temp, j, k)) {
01186                     used = 1;
01187                     glyphs[i].offset_x += j;
01188                     glyphs[i].w -= j;
01189                     break;
01190                 }
01191             }
01192             if (used)
01193                 break;
01194         }
01195 
01196         /* Crop Right */
01197         j = glyphs[i].w + glyphs[i].offset_x - 1;
01198         for (/* above */; j >= glyphs[i].offset_x; j--) {
01199             used = 0;
01200 
01201             k = MAX(glyphs[i].offset_y - 1, 0);
01202             for (/* above */; k < glyphs[i].offset_y + glyphs[i].h + 1; k++) {
01203                 if (getpixel(temp, j, k)) {
01204                     used = 1;
01205                     glyphs[i].offset_w +=
01206                                        glyphs[i].w + glyphs[i].offset_x - 1 - j;
01207                     glyphs[i].w -= glyphs[i].w + glyphs[i].offset_x - j - 1;
01208                     break;
01209                 }
01210             }
01211             if (used)
01212                 break;
01213         }
01214 #ifdef LOGLEVEL
01215         TRACE(PREFIX_I "crop_font_range: Glyph %i (%c) offs: x: %i  y: %i, "
01216               "w: %i  h: %i,  offs: w: %i  h: %i\n", i, i + beg,
01217               glyphs[i].offset_x, glyphs[i].offset_y, glyphs[i].w, glyphs[i].h,
01218               glyphs[i].offset_w, glyphs[i].offset_h);
01219 #endif
01220     }
01221     
01222     destroy_bitmap(temp);
01223 
01224     return TRUE;
01225 
01226 error:
01227     if (temp) {
01228         destroy_bitmap(temp);
01229     }
01230 
01231     return FALSE;   
01232 }
01233 
01234 
01235 
01236 /* Crops a font over a particular range */
01237 static int crop_font_range(FONT *f, void *src, int beg, int end,
01238                            AGL_GLYPH *glyphs,
01239                            int *net_area, int *gross_area,
01240                            int *max_w, int *max_h) {
01241 
01242     int i;
01243     int crop = 1;
01244     int max = end - beg;
01245     int ret = TRUE;
01246 
01247     union mixed_ptr dat;
01248     dat.ptr = src;
01249 
01250     /* Disable cropping for trucolor fonts. */
01251     if (is_color_font(f)) {
01252         FONT_COLOR_DATA *fcd = f->data;
01253         if (bitmap_color_depth(fcd->bitmaps[0]) != 8) {
01254             crop = 0;
01255         }
01256     }
01257 
01258     /* Load default sizes */
01259     for (i = 0; i < max; i++) {
01260         glyphs[i].glyph_num = i;
01261 
01262         if (is_mono_font(f)) {
01263             glyphs[i].w = dat.mf->glyphs[i]->w + 1;
01264             glyphs[i].h = dat.mf->glyphs[i]->h + 1;
01265         } else {
01266             glyphs[i].w = dat.cf->bitmaps[i]->w + 1;
01267             glyphs[i].h = dat.cf->bitmaps[i]->h + 1;
01268         }
01269         glyphs[i].offset_w = -1;
01270         glyphs[i].offset_h = -1;
01271 
01272         /* Not placed yet */
01273         glyphs[i].x = -1;
01274     }
01275     
01276     if (crop) {
01277         ret = do_crop_font_range(f, glyphs, beg, end);
01278     }
01279 
01280     (*gross_area) = 0;
01281     (*net_area) = 0;
01282     (*max_w) = 0;
01283     (*max_h) = 0;
01284 
01285     /* Find max w and h, total area covered by the bitmaps, and number of
01286      * glyphs
01287      */
01288     for (i = 0; i < max; i++) {
01289         if (glyphs[i].w > *max_w) (*max_w) = glyphs[i].w;
01290         if (glyphs[i].h > *max_h) (*max_h) = glyphs[i].h;
01291         (*net_area) += glyphs[i].w * glyphs[i].h;
01292         (*gross_area) += (glyphs[i].w + FONT_CHARACTER_SPACING)
01293                        * (glyphs[i].h + FONT_CHARACTER_SPACING);
01294     }
01295     return ret;
01296 
01297 }
01298 
01299 
01300 
01301 /* Tries to find a texture that will fit the font
01302  */
01303 static BITMAP* look_for_texture(int beg, int end, AGL_GLYPH *glyphs,
01304             int max_w, int max_h, int total_area, GLint format, int has_alpha) {
01305 
01306     BITMAP *bmp = NULL;
01307     int i, j;
01308 
01309     /* Max texture size (1 << n) */
01310     /* XXX <rohannessian> We should use ARB_np2 if we can
01311      *
01312      * Other note: w*h shouldn't exceed 31 bits; otherwise, we get funny
01313      * behavior on 32-bit architectures. Limit texture sizes to 32k*32k
01314      * (30 bits).
01315      */
01316 #define MIN_TEXTURE_SIZE 2
01317 #define NUM_TEXTURE_SIZE 13
01318     texture_size texture_sizes[NUM_TEXTURE_SIZE * NUM_TEXTURE_SIZE];
01319 
01320     /* Set up texture sizes */
01321     for (i = 0; i < NUM_TEXTURE_SIZE; i++) {
01322         for (j = 0; j < NUM_TEXTURE_SIZE; j++) {
01323             texture_sizes[j + i * NUM_TEXTURE_SIZE].w =
01324                                                     1 << (j + MIN_TEXTURE_SIZE);
01325             texture_sizes[j + i * NUM_TEXTURE_SIZE].h =
01326                                                     1 << (i + MIN_TEXTURE_SIZE);
01327         }
01328     }
01329 
01330     /* Sort texture sizes by area */
01331     qsort(texture_sizes, NUM_TEXTURE_SIZE * NUM_TEXTURE_SIZE,
01332                                           sizeof(texture_size), &sort_textures);
01333 
01334     for (i = 0; i < NUM_TEXTURE_SIZE * NUM_TEXTURE_SIZE; i++) {
01335         int num_channels;
01336         
01337         /* Check the area - it must be larger than
01338          * all the glyphs
01339          */
01340         texture_size *t = &texture_sizes[i];
01341         int area = t->w * t->h;
01342         int depth = 24;
01343 
01344         if (area < total_area) {
01345             continue;
01346         }
01347             
01348         /* Check against max values */
01349         if ((t->h < max_h) || (t->w < max_w)) {
01350             continue;
01351         }
01352 
01353         TRACE(PREFIX_I "look_for_texture: candidate size: %ix%i\n", t->w, t->h);
01354 
01355         /* Check that the texture can, in fact, be created */
01356         num_channels = __allegro_gl_get_num_channels(format);
01357         if (num_channels == 1) {
01358             depth = 8;
01359         }
01360         else if (num_channels == 4) {
01361             depth = 32;
01362         }
01363         else {
01364             depth = 24;
01365         }
01366         bmp = create_bitmap_ex(depth, t->w, t->h);
01367 
01368         if (!bmp) {
01369             TRACE(PREFIX_W "look_for_texture: Out of memory while "
01370                   "creating bitmap\n");
01371             continue;
01372         }
01373 
01374         if (!aglf_check_texture(bmp, format, has_alpha)) {
01375             TRACE(PREFIX_I "look_for_texture: Texture rejected by driver\n");
01376             destroy_bitmap(bmp);
01377             bmp = NULL;
01378             continue;
01379         }
01380 
01381         /* Sort out the glyphs */
01382         TRACE(PREFIX_I "look_for_texture: Sorting on bmp: %p, beg: %i, "
01383               "end: %i\n", bmp, beg, end);
01384 
01385         if (aglf_sort_out_glyphs(bmp, glyphs, beg, end) == TRUE) {
01386             /* Success? */
01387             return bmp;
01388         }
01389 
01390         /* Failure? Try something else */
01391         TRACE(PREFIX_I "look_for_texture: Conversion failed\n");
01392         destroy_bitmap(bmp);
01393         bmp = NULL;
01394     }
01395     
01396     return NULL;
01397 }
01398 
01399 
01400 
01401 #if GET_ALLEGRO_VERSION() >= MAKE_VER(4, 2, 1)
01402 /* This is only used to render chars from an Allegro font which has the
01403  * font_vtable_trans vtable. If the target is an 8-bit bitmap, only the alpha
01404  * channel is used. Otherwise, blit is used, to preserve the alpha channel.
01405  */
01406 static int dummy_render_char(AL_CONST FONT* f, int ch, int fg, int bg,
01407     BITMAP* bmp, int x, int y)
01408 {
01409     FONT_COLOR_DATA* cf = (FONT_COLOR_DATA*)(f->data);
01410     BITMAP *glyph = NULL;
01411 
01412     while(cf) {
01413         if(ch >= cf->begin && ch < cf->end) {
01414             glyph = cf->bitmaps[ch - cf->begin];
01415             break;
01416         }
01417         cf = cf->next;
01418     }
01419 
01420     if (glyph)
01421     {
01422         if (bitmap_color_depth(bmp) == 8) {
01423             int gx, gy;
01424             for (gy = 0; gy < bmp->h; gy++) {
01425                 for (gx = 0; gx < bmp->w; gx++) {
01426                     int c = getpixel(glyph, gx, gy);
01427                     int a = geta(c);
01428                     putpixel(bmp, x + gx, y + gy, a);
01429                 }
01430             }
01431         }
01432         else
01433             blit(glyph, bmp, 0, 0, x, y, glyph->w, glyph->h);
01434         return bmp->w;
01435     }
01436     return 0;
01437 }
01438 #endif
01439 
01440 
01441 
01442 /* Function to draw a character in a bitmap for conversion */
01443 static int draw_glyphs(BITMAP *bmp, FONT *f, GLint format, int beg, int end,
01444                        AGL_GLYPH *glyphs) {
01445     char buf[32];
01446     int i, j;
01447 
01448 #if GET_ALLEGRO_VERSION() >= MAKE_VER(4, 2, 1)
01449     if (bitmap_color_depth(bmp) == 8 && f->vtable != font_vtable_trans) {
01450 #else
01451     if (bitmap_color_depth(bmp) == 8) {
01452 #endif
01453         /* Generate an alpha font */
01454         BITMAP *rgbbmp = create_bitmap_ex(24, bmp->w, bmp->h);
01455         
01456         if (!rgbbmp) {
01457             TRACE(PREFIX_E "convert_allegro_font_to_texture: "
01458                   "Ran out of memory while creating %ix%ix%i bitmap!\n",
01459                   bmp->w, bmp->h, 24);
01460             return FALSE;
01461         }
01462 
01463         clear_bitmap(rgbbmp);
01464         
01465         for (i = 0; i < end - beg; i++) {
01466             usetc(buf + usetc(buf, glyphs[i].glyph_num + beg), 0);
01467             
01468             textout_ex(rgbbmp, f, buf, glyphs[i].x - glyphs[i].offset_x,
01469                                       glyphs[i].y - glyphs[i].offset_y, -1, -1);
01470         }
01471 
01472         /* Convert back to 8bpp */
01473         for (j = 0; j < bmp->h; j++) {
01474             for (i = 0; i < bmp->w; i++) {
01475                 int pix = _getpixel24(rgbbmp, i, j);
01476                 int r = getr24(pix);
01477                 int g = getg24(pix);
01478                 int b = getb24(pix);
01479                 int gray = (r * 77 + g * 150 + b * 28 + 255) >> 8;
01480                 _putpixel(bmp, i, j, MID(0, gray, 255));
01481             }
01482         }
01483         destroy_bitmap(rgbbmp);
01484     }
01485     else {
01486 #if GET_ALLEGRO_VERSION() >= MAKE_VER(4, 2, 1)
01487         int (*borrowed_color_vtable)(AL_CONST FONT*, int, int, int, BITMAP*, int, int) = NULL;
01488 
01489         //In order to keep the alpha channel in textout_ex we borrow
01490         //the color font vtable which uses maked_blit() instead of
01491         //draw_trans_sprite() to draw glyphs.
01492         if (f->vtable == font_vtable_trans) {
01493             borrowed_color_vtable = f->vtable->render_char;
01494             f->vtable->render_char = dummy_render_char;
01495         }
01496 #endif
01497 
01498         if (__allegro_gl_get_num_channels(format) == 4) {
01499             clear_to_color(bmp, bitmap_mask_color(bmp));
01500         }
01501         else {
01502             clear_bitmap(bmp);
01503         }
01504 
01505         for (i = 0; i < end - beg; i++) {
01506             usetc(buf + usetc(buf, glyphs[i].glyph_num + beg), 0);
01507             textout_ex(bmp, f, buf, glyphs[i].x - glyphs[i].offset_x,
01508                      glyphs[i].y - glyphs[i].offset_y, -1, -1);
01509         }
01510 
01511 #if GET_ALLEGRO_VERSION() >= MAKE_VER(4, 2, 1)
01512         if (borrowed_color_vtable) {
01513             f->vtable->render_char = borrowed_color_vtable;
01514         }
01515 #endif
01516     }
01517 
01518     return TRUE;
01519 }
01520 
01521 
01522 
01523 /* Converts a single font range to a texture.
01524  * dest - Receives the result.
01525  * f - The original font.
01526  * src - The original font data.
01527  */
01528 static void aglf_convert_allegro_font_to_texture(FONT_AGL_DATA **dest, FONT *f,
01529                             void *src, int *height, float scale, GLint format) {
01530 
01531     int max = 0;
01532     BITMAP *bmp = NULL;
01533     int beg = 0, end = 0;
01534     int max_w, max_h;
01535     int total_area, gross_area;
01536     
01537     AGL_GLYPH *glyph_coords;
01538 
01539     union mixed_ptr dat;
01540     dat.ptr = src;
01541 
01542     if (is_mono_font(f)) {
01543         beg = dat.mf->begin;
01544         end = dat.mf->end;
01545         max = dat.mf->end - dat.mf->begin;
01546         if (format == -1) {
01547             format = GL_INTENSITY4;
01548         }
01549     }
01550     else if (is_color_font(f)) {
01551         beg = dat.cf->begin;
01552         end = dat.cf->end;
01553         max = dat.cf->end - dat.cf->begin;
01554         if (format == -1) {
01555 #if GET_ALLEGRO_VERSION() >= MAKE_VER(4, 2, 1)
01556             format = (f->vtable == font_vtable_trans ? GL_RGBA8 : GL_RGB8);
01557 #else
01558             format = GL_RGB8;
01559 #endif
01560         }
01561     }
01562 
01563     /* Allocate glyph sizes */
01564     glyph_coords = malloc(max * sizeof(AGL_GLYPH));
01565     memset(glyph_coords, 0, max * sizeof(AGL_GLYPH));
01566 
01567     if (crop_font_range(f, dat.ptr, beg, end, glyph_coords,
01568                           &total_area, &gross_area, &max_w, &max_h) == FALSE) {
01569         TRACE(PREFIX_I "convert_allegro_font_to_texture: Unable to crop font "
01570               "range\n");
01571         free(glyph_coords);
01572         return;
01573     }
01574 
01575     TRACE(PREFIX_I "convert_allegro_font_to_texture: Total area of glyphs: "
01576           "%i pixels (%i pixels gross) - max_w: %i, max_h: %i\n",
01577           total_area, gross_area, max_w, max_h);
01578 
01579     /* Sort glyphs by width, then height */
01580     qsort(glyph_coords, end - beg, sizeof(AGL_GLYPH), &sort_glyphs);
01581 
01582 
01583     /* Now, we look for the appropriate texture size */
01584     bmp = look_for_texture(beg, end, glyph_coords, max_w, max_h,
01585                            total_area, format, (*dest)->has_alpha);
01586 
01587     /* No texture sizes were found - we should split the font up */
01588     if (!bmp) {
01589         int height1;
01590         union mixed_ptr f1, f2;
01591         FONT_AGL_DATA *dest1, *dest2;
01592 
01593         free(glyph_coords);
01594 
01595         dest1 = *(dest);
01596         dest2 = malloc(sizeof(FONT_AGL_DATA));
01597 
01598         if (!dest2) {
01599             TRACE(PREFIX_E "convert_allegro_font_to_texture: "
01600                   "Out of memory while trying to allocate %i bytes.\n",
01601                   (int)sizeof(FONT_AGL_DATA));
01602             return;
01603         }
01604 
01605         memset(dest2, 0, sizeof(FONT_AGL_DATA));
01606 
01607         dest2->next = dest1->next;
01608         dest1->next = dest2;
01609         dest2->is_free_chunk = TRUE;
01610         dest2->format = dest1->format;
01611         dest2->has_alpha = dest1->has_alpha;
01612         
01613         if (split_font(f, dat.ptr, &f1.ptr, &f2.ptr) == FALSE) {
01614             TRACE(PREFIX_E "convert_allegro_font_to_texture: Unable "
01615                   "to split font!\n");
01616             dest1->next = dest2->next;
01617             free(dest2);
01618             return;
01619         }
01620         
01621         aglf_convert_allegro_font_to_texture(&dest1, f, f1.ptr, height, scale,
01622                                              format);
01623         height1 = (*height);
01624         aglf_convert_allegro_font_to_texture(&dest2, f, f2.ptr, height, scale,
01625                                              format);
01626         destroy_split_font(f, f1, f2);
01627 
01628         if (height1 > (*height))
01629             (*height) = height1;
01630         (*dest) = dest2;
01631         
01632         return;
01633     }
01634 
01635     TRACE(PREFIX_I "convert_allegro_font_to_texture: Using texture "
01636           "%ix%ix%i for font conversion.\n", bmp->w, bmp->h,
01637           bitmap_color_depth(bmp));
01638 
01639     /* Now that all the glyphs are in place, we draw them into the bitmap */
01640     if (draw_glyphs(bmp, f, format, beg, end, glyph_coords) == FALSE) {
01641         destroy_bitmap(bmp);
01642         free(glyph_coords);
01643         return;
01644     }
01645 
01646     /* Un-Sort glyphs  */
01647     qsort(glyph_coords, end - beg, sizeof(AGL_GLYPH), &unsort_glyphs);
01648 
01649 #if (defined SAVE_FONT_SCREENSHOT)
01650         save_shot(bmp);
01651 #endif
01652 
01653     (*dest)->list_base =
01654              create_textured_font_call_lists(glyph_coords, max, bmp,
01655                                              scale, height);
01656 
01657     (*dest)->texture = aglf_upload_texture(bmp, format, (*dest)->has_alpha);
01658     (*dest)->type = AGL_FONT_TYPE_TEXTURED;
01659     (*dest)->format = format;
01660     (*dest)->scale = scale;
01661     (*dest)->start = beg;
01662     (*dest)->end = end;
01663     (*dest)->data = bmp;
01664     (*dest)->glyph_coords = glyph_coords;
01665 
01666     return;
01667 }
01668 
01669 
01670 
01671 static void aglf_convert_allegro_font_to_bitmap(FONT_AGL_DATA *dest, FONT *f,
01672                                                        void *src, int *height) {
01673 
01674     int max = 0;
01675     int i, j, k;
01676     int beg = 0, end = 0;
01677     int mask;
01678     FONT_GLYPH **glyph;
01679 
01680     union {
01681         FONT_MONO_DATA* mf;
01682         FONT_COLOR_DATA* cf;
01683         void *ptr;
01684     } dat;
01685 
01686     dat.ptr = src;
01687 
01688     if (is_mono_font(f))
01689         max = dat.mf->end - dat.mf->begin;
01690     else if (is_color_font(f))
01691         max = dat.cf->end - dat.cf->begin;
01692     else
01693         return;
01694 
01695     glyph = malloc(sizeof(FONT_GLYPH*) * max);
01696 
01697     if (!glyph) {
01698         TRACE(PREFIX_E "convert_allegro_font_to_bitmap: Ran out of "
01699               "memory while allocating %i bytes\n", (int)sizeof(FONT_GLYPH));
01700         return;
01701     }
01702     
01703     *height = f->height;
01704         
01705     if (is_mono_font(f)) {      
01706     
01707         /* for each glyph */
01708         for (i = 0; i < max; i++) {     
01709             FONT_GLYPH *oldgl = dat.mf->glyphs[i];
01710     
01711             int size = sizeof(FONT_GLYPH) + ((oldgl->w + 31) / 32) * 4
01712                                                                      * oldgl->h;
01713     
01714             /* create new glyph */
01715             FONT_GLYPH *newgl = (FONT_GLYPH*)malloc(size);
01716     
01717             if (!newgl)
01718                 break;
01719     
01720             memset(newgl, 0, size);
01721     
01722             newgl->w = oldgl->w;
01723             newgl->h = oldgl->h;
01724 
01725             /* update the data */
01726             for (j = 0; j < oldgl->h; j++) {
01727                 for (k = 0; k < ((oldgl->w + 7) / 8); k++) {
01728                     int addr = (oldgl->h - j - 1) * ((oldgl->w + 31) / 32) * 4
01729                                + k;
01730                     newgl->dat[addr] = oldgl->dat[j * ((oldgl->w + 7) / 8) + k];
01731                 }
01732             }
01733 
01734             glyph[i] = newgl;
01735         }
01736     }
01737     /* Reduce to 1 bit */
01738     else if (is_color_font(f)) {
01739         /* for each glyph */
01740         for (i = 0; i < max; i++) {
01741 
01742             int size;
01743             BITMAP *oldgl = dat.cf->bitmaps[i];
01744             FONT_GLYPH *newgl;
01745 
01746             mask = bitmap_mask_color(oldgl);
01747 
01748             size = sizeof(FONT_GLYPH) + ((oldgl->w + 31) / 32) * 4 * oldgl->h;
01749 
01750             /* create new glyph */
01751             newgl = (FONT_GLYPH*)malloc(size);
01752 
01753             if (!newgl)
01754                 break;
01755 
01756             memset(newgl, 0, size);
01757 
01758             newgl->w = oldgl->w;
01759             newgl->h = oldgl->h;
01760 
01761             /* update the data */
01762             for (j = 0; j < oldgl->h; j++) {
01763                 for (k = 0; k < oldgl->w; k++) {
01764                     int addr = (oldgl->h - j - 1) * ((oldgl->w + 31) / 32) * 4
01765                              + (k / 8);
01766                     newgl->dat[addr] |= (getpixel(oldgl, k, j) == mask)
01767                                      ? 0 : (1 << (k & 7));
01768                 }
01769             }
01770 
01771             glyph[i] = newgl;
01772         }
01773     }
01774     /* Create call lists */
01775     {
01776         GLuint list = glGenLists(max);
01777 
01778         for (i = 0; i < max; i++) {
01779             glNewList(list + i, GL_COMPILE);
01780 
01781             glBitmap(glyph[i]->w, glyph[i]->h, 0, 0, glyph[i]->w, 0,
01782                      glyph[i]->dat);
01783 
01784             glEndList();
01785         }
01786         dest->list_base = list;
01787     }
01788         
01789     dest->is_free_chunk = 0;
01790     dest->type = AGL_FONT_TYPE_BITMAP;
01791     dest->start = beg;
01792     dest->end = end;
01793     dest->data = glyph;
01794 
01795     return;
01796 }
01797 
01798 
01799 
01800 static int aglf_check_texture(BITMAP *bmp, GLint format, int has_alpha) {
01801 
01802     int flags = AGL_TEXTURE_FLIP | AGL_TEXTURE_MIPMAP;
01803 
01804     if (format == GL_ALPHA4 || format == GL_ALPHA8 || format == GL_ALPHA
01805      || format == GL_INTENSITY4 || format == GL_INTENSITY8
01806      || format == GL_INTENSITY
01807      || format == GL_LUMINANCE4 || format == GL_LUMINANCE8
01808      || format == GL_LUMINANCE
01809      || format == 1) {
01810         flags |= AGL_TEXTURE_ALPHA_ONLY;
01811     }
01812     else if (format == GL_RGBA8) {
01813         if (has_alpha) {
01814             flags |= AGL_TEXTURE_HAS_ALPHA;
01815         }
01816         else {
01817             flags |= AGL_TEXTURE_MASKED;
01818         }
01819     }
01820 
01821     return allegro_gl_check_texture_ex(flags, bmp, format);
01822 }
01823 
01824 
01825 
01826 static GLuint aglf_upload_texture(BITMAP *bmp, GLint format, int has_alpha) {
01827 
01828     int flags = AGL_TEXTURE_FLIP | AGL_TEXTURE_MIPMAP;
01829     GLuint texture;
01830 
01831     if (format == GL_ALPHA4 || format == GL_ALPHA8 || format == GL_ALPHA
01832      || format == GL_INTENSITY4 || format == GL_INTENSITY8
01833      || format == GL_INTENSITY
01834      || format == GL_LUMINANCE4 || format == GL_LUMINANCE8
01835      || format == GL_LUMINANCE
01836      || format == 1) {
01837         flags |= AGL_TEXTURE_ALPHA_ONLY;
01838     }
01839     else if (__allegro_gl_get_num_channels(format) == 4) {
01840         if (has_alpha) {
01841             flags |= AGL_TEXTURE_HAS_ALPHA;
01842         }
01843         else {
01844             flags |= AGL_TEXTURE_MASKED;
01845         }
01846     }
01847 
01848     TRACE(PREFIX_I "Want texture format: %s\n",
01849         __allegro_gl_get_format_description(format));
01850     texture = allegro_gl_make_texture_ex(flags, bmp, format);
01851     TRACE(PREFIX_I "Texture ID is: %u\n", texture);
01852 
01853     return texture;
01854 }
01855 
allegro4.4-4.4.2/addons/allegrogl/docs/html/ftv2blank.png000066400000000000000000000001221173507505700231140ustar00rootroot00000000000000‰PNG  IHDRɪ|IDATxíÝÁ¡ó§žÆEG–ë›ÂºIEND®B`‚allegro4.4-4.4.2/addons/allegrogl/docs/html/ftv2doc.png000066400000000000000000000013721173507505700226020ustar00rootroot00000000000000‰PNG  IHDRÚ}\ˆÁIDATxíOOGÆ3;ûÇÞ]oL²¶± n %HP•´IÀ¢9´QL•¢*UÕSOáTõ–ckýýý¹µj8DT¥@«@ˆk †lÃNEMrÁ›À!=õ•æ2Ò¾¿}Ÿgž™«ÐZó6K¾Õîÿ@õÚüíºîD´Ú‡t"žï¶iì¶ð] ÇV¤\‹|èRÈxâu£Z­žØœ_ú»šíKâ%MÜ„‰c+Ž"a+êÏ÷Iû…ŒÇüb SÉj:åÜ;“D†!²»„X¦—0ñ]‹|èñäÙ.ùÐåË!óK5ÿµ{Rb=0 ù "¥@)‰ë(|×du½@>t¹<–åÑã:õfOHOŽêøïtÔZ£é‚’ò¡Ç?þÊN³C>t \‹g[M²ç“§ó`y­QÍ]p‘RPÛÞÂdÂd»ÑÂOšô‡.Ùó.é”Mʵ¨mdxàÜ /â'0$BÀ£ßëh­¹öq_6hµéK9˜J2Ý!á(VÖLŽç|›‹¥4Q¤iwº™9S’¥ܘäË™®OòÍ­1fÊ%îÍ•ùäR÷  [xÖÙ’ Dw-®l1¿TãÅ^‡ÍÆ>…ŒÇP1`ie‹Í&ß~5cǶ‰ŸÀR†”ú}®Žg™­Œpçö|ñé£ïô1[ữ/!¥À0âo‹xôqØ<\cqe‹¡bÀêzã„“ã¹× ýÆStcjÙÊû|vu §ÊÈã@žE)Zk”’2Þ«‹¯˜õÏ¢ÿ‚ÛT c®žE‘fòó»<]þËî6‰«vë¹w¯ðýݹÓ*å’¨ütÿÿ'óßúªWİa\ÔØIEND®B`‚allegro4.4-4.4.2/addons/allegrogl/docs/html/ftv2folderclosed.png000066400000000000000000000011261173507505700244770ustar00rootroot00000000000000‰PNG  IHDRÚ}\ˆIDATxí]MkQ=÷_‹¡b’f’Öˆ-I“FmÛ*¥Ø­+€;7ú$‚ÿÁ…ÿÁ•¸sãBÑ'¡¥®ºPRq!Jk:óîuñf&3I5lW ûo8çžsî¼Ù’ˆà0/u¨èGApì âó7Ÿdms'U»4Ãj{’þ ÁÚæj•l¼&Þ}ø‚Õöä_+ùñ“uù¸ý3! ll}µžE (-†EPλ¸s«žÚp:Nêŧ/¶:·oVQ.¸(å]x9å‚‹æÅj•,êNc¦’ÅÔÙ ¦Ïe0uÆÞÕóY¼^߯JkâÁP‹¾ýè"uË"ð}Žù†í> Ã8qÜ-`÷g‘ž=¶.àpûˆØç¾oF™Ù‚Qès0 ¢ì’õ‘B¾ÿè•ܘŸ€X "$q? (¥ðòýg<¼»˜ y@³ÄõºìukXbëÒVåHt÷MÜa2 "ëß„¦Æw(ìîù0" X$²‚i²)ENÖÐ}ÃðY AúBWkä(ð(À^7€ Gñwâ(Jyî8Sƒ! ðv£wÐ%¿…hœ¬d>™±“ƒôµJ6·Ò*ëë—=}­éé…FQ/4Šújc\Ï×Çu«VÐízQ/ÎõÒ¬§—šž^¾RÒËse=W-èÌØ©gTPÊ»÷þÿÑŽ”àÔùùÞbiIEND®B`‚allegro4.4-4.4.2/addons/allegrogl/docs/html/ftv2folderopen.png000066400000000000000000000011161173507505700241660ustar00rootroot00000000000000‰PNG  IHDRÚ}\ˆIDATxí]?oÓ@ÿÝ%&uÚÔ¾8N„hJÛ´MÔRD‘˜ø |¦LÌfebç;° ±#&t H•ŠT–"U(Q”¶¹÷]í:µ“2P„%KÏwÖïÏû½³WÁ̸ÌK^*ú?APœ´Ñ=ð^·"ÆÈF†°¶ècc%„`¯ÛG#(£äà­Ñw¾âýî!ƒ! PR <¼¿žK\ˆ¢(—`wÿ[ä%¤`œ¢D¨\þ Bå¯ÌÀ›»‚Ù²ƒÞà7×kOóp2cúâåGî † ÓåxŸ™aˆ!…JÌ b0Ûêsxô`kÌIÆÁ«7ûÑÕ¡rѨ–QS.B墿ŸÝçBUJ<þ|)©? pïNsÌInÃ#ƒ‚+“¿IEND®B`‚allegro4.4-4.4.2/addons/allegrogl/docs/html/ftv2lastnode.png000066400000000000000000000001221173507505700236360ustar00rootroot00000000000000‰PNG  IHDRɪ|IDATxíÝÁ¡ó§žÆEG–ë›ÂºIEND®B`‚allegro4.4-4.4.2/addons/allegrogl/docs/html/ftv2link.png000066400000000000000000000013721173507505700227720ustar00rootroot00000000000000‰PNG  IHDRÚ}\ˆÁIDATxíOOGÆ3;ûÇÞ]oL²¶± n %HP•´IÀ¢9´QL•¢*UÕSOáTõ–ckýýý¹µj8DT¥@«@ˆk †lÃNEMrÁ›À!=õ•æ2Ò¾¿}Ÿgž™«ÐZó6K¾Õîÿ@õÚüíºîD´Ú‡t"žï¶iì¶ð] ÇV¤\‹|èRÈxâu£Z­žØœ_ú»šíKâ%MÜ„‰c+Ž"a+êÏ÷Iû…ŒÇüb SÉj:åÜ;“D†!²»„X¦—0ñ]‹|èñäÙ.ùÐåË!óK5ÿµ{Rb=0 ù "¥@)‰ë(|×du½@>t¹<–åÑã:õfOHOŽêøïtÔZ£é‚’ò¡Ç?þÊN³C>t \‹g[M²ç“§ó`y­QÍ]p‘RPÛÞÂdÂd»ÑÂOšô‡.Ùó.é”Mʵ¨mdxàÜ /â'0$BÀ£ßëh­¹öq_6hµéK9˜J2Ý!á(VÖLŽç|›‹¥4Q¤iwº™9S’¥ܘäË™®OòÍ­1fÊ%îÍ•ùäR÷  [xÖÙ’ Dw-®l1¿TãÅ^‡ÍÆ>…ŒÇP1`ie‹Í&ß~5cǶ‰ŸÀR†”ú}®Žg™­Œpçö|ñé£ïô1[ữ/!¥À0âo‹xôqØ<\cqe‹¡bÀêzã„“ã¹× ýÆStcjÙÊû|vu §ÊÈã@žE)Zk”’2Þ«‹¯˜õÏ¢ÿ‚ÛT c®žE‘fòó»<]þËî6‰«vë¹w¯ðýݹÓ*å’¨ütÿÿ'óßúªWİa\ÔØIEND®B`‚allegro4.4-4.4.2/addons/allegrogl/docs/html/ftv2mlastnode.png000066400000000000000000000003351173507505700240210ustar00rootroot00000000000000‰PNG  IHDRɪ|¤IDATxí1A…?âŽàïÎ0¡Ð(F'‘8V§Pk$ À(´¯«QÈŸX›ý5’º÷2ïíîÌÛ¾B J5+©kƒß´ÞÁ|y(€v¤ÿì¦Nì£/ö£OpÓØ}¯Ü´O™Á¸—¸0N¢›.À¬DOÜT$oÁMSàú‚'7-rÖ8@/+nÚ]7³ƒä¦Mý™þÁà žB"cÃAØIEND®B`‚allegro4.4-4.4.2/addons/allegrogl/docs/html/ftv2mnode.png000066400000000000000000000003351173507505700231350ustar00rootroot00000000000000‰PNG  IHDRɪ|¤IDATxí1A…?âŽàïÎ0¡Ð(F'‘8V§Pk$ À(´¯«QÈŸX›ý5’º÷2ïíîÌÛ¾B J5+©kƒß´ÞÁ|y(€v¤ÿì¦Nì£/ö£OpÓØ}¯Ü´O™Á¸—¸0N¢›.À¬DOÜT$oÁMSàú‚'7-rÖ8@/+nÚ]7³ƒä¦Mý™þÁà žB"cÃAØIEND®B`‚allegro4.4-4.4.2/addons/allegrogl/docs/html/ftv2node.png000066400000000000000000000001221173507505700227520ustar00rootroot00000000000000‰PNG  IHDRɪ|IDATxíÝÁ¡ó§žÆEG–ë›ÂºIEND®B`‚allegro4.4-4.4.2/addons/allegrogl/docs/html/ftv2plastnode.png000066400000000000000000000003271173507505700240250ustar00rootroot00000000000000‰PNG  IHDRɪ|žIDATxí! BQE"¸ ‚u¢Ý"îÀ0M°'˜èfuÚ^µ·azZƒòùï%áß6áî\fz/¥D‰úEîÀàsk`c*ç,À+Ó8°5•º-à­%0w¦rÈ }ð¸Ö¦rÍ-q \‚ÇE.àÌLåØv…ÐØÁ¯0i2Kp/ºSwßø€'RG'TÖáIEND®B`‚allegro4.4-4.4.2/addons/allegrogl/docs/html/ftv2pnode.png000066400000000000000000000003271173507505700231410ustar00rootroot00000000000000‰PNG  IHDRɪ|žIDATxí! BQE"¸ ‚u¢Ý"îÀ0M°'˜èfuÚ^µ·azZƒòùï%áß6áî\fz/¥D‰úEîÀàsk`c*ç,À+Ó8°5•º-à­%0w¦rÈ }ð¸Ö¦rÍ-q \‚ÇE.àÌLåØv…ÐØÁ¯0i2Kp/ºSwßø€'RG'TÖáIEND®B`‚allegro4.4-4.4.2/addons/allegrogl/docs/html/ftv2splitbar.png000066400000000000000000000003711173507505700236530ustar00rootroot00000000000000‰PNG  IHDRM¸¿ÀIDATxíÝ¡NBq†áßÿ°™ §Ÿä,4ÉnG±0†Í›LÞ‡Wp(d6¼›YÓ¡0@¢‹ÍÆéy㳯}7Ð(çÕ´üŽßû/oOÏ£Nï5‹!„B!„B!„B!„B!„ÐÅhù½‹ˆýáøG)¥‡vqWä×Wƒn+•óªÿx3[ln›ùz»?ÿ*‹ˆº®#âëg“Ï•ÓB!„B!„B!„B!„BL¿Vì=ü 0ðÉIEND®B`‚allegro4.4-4.4.2/addons/allegrogl/docs/html/ftv2vertline.png000066400000000000000000000001221173507505700236550ustar00rootroot00000000000000‰PNG  IHDRɪ|IDATxíÝÁ¡ó§žÆEG–ë›ÂºIEND®B`‚allegro4.4-4.4.2/addons/allegrogl/docs/html/glext_8c.html000066400000000000000000000253071173507505700231340ustar00rootroot00000000000000 AllegroGL: glext.c File Reference

glext.c File Reference

OpenGL extension management. More...

#include "alleggl.h"
#include "allglint.h"
#include <string.h>
#include <GL/glu.h>
#include <allegro/internal/aintern.h>
#include "allegrogl/GLext/gl_ext_api.h"
#include "allegrogl/GLext/gl_ext_list.h"

Go to the source code of this file.

Defines

  • #define AGL_API(type, name, args)   AGL_##name##_t name;
  • #define PREFIX_I   "agl-ext INFO: "
  • #define PREFIX_W   "agl-ext WARNING: "
  • #define PREFIX_E   "agl-ext ERROR: "
  • #define aglXGetProcAddress   glXGetProcAddress
  • #define AGL_API(type, name, args)   AGL_##name##_t __agl##name = NULL;
  • #define AGL_API(type, name, args)   __agl##name = ext->name;
  • #define AGL_EXT(name, ver)

Typedefs

  • typedef struct AGL_EXT AGL_EXT

Functions

  • AGL_EXT * __allegro_gl_create_extensions ()
  • void __allegro_gl_load_extensions (AGL_EXT *ext)
  • void __allegro_gl_set_extensions (AGL_EXT *ext)
  • void __allegro_gl_destroy_extensions (AGL_EXT *ext)
  • int __allegro_gl_look_for_an_extension (AL_CONST char *name, AL_CONST GLubyte *extensions)
  • int allegro_gl_is_extension_supported (AL_CONST char *extension)
    This function is an helper to determine whether an OpenGL extension is available or not.
  • void * allegro_gl_get_proc_address (AL_CONST char *name)
    Helper to get the address of an OpenGL symbol.
  • static void __fill_in_info_struct (const GLubyte *rendereru, struct allegro_gl_info *info)
  • void __allegro_gl_manage_extensions (void)
  • void __allegro_gl_print_extensions (AL_CONST char *extension)
  • void __allegro_gl_unmanage_extensions ()

Variables

  • struct allegro_gl_info allegro_gl_info
  • struct AGL_EXTENSION_LIST_GL allegro_gl_extensions_GL
    List of OpenGL extensions supported by AllegroGL.
  • AGL_EXT * agl_extension_table = NULL
    List of GLX extensions supported by AllegroGL.

Detailed Description

OpenGL extension management.

Definition in file glext.c.


Define Documentation

#define AGL_EXT (   name,
  ver 
)
Value:
{                               \
        allegro_gl_extensions_GL.name =                        \
              allegro_gl_is_extension_supported("GL_" #name)   \
          || (allegro_gl_info.version >= ver && ver > 0);      \
    }
allegro4.4-4.4.2/addons/allegrogl/docs/html/glext_8c_source.html000066400000000000000000001575371173507505700245270ustar00rootroot00000000000000 AllegroGL: glext.c Source File

glext.c

Go to the documentation of this file.
00001 /* This code is (C) AllegroGL contributors, and double licensed under
00002  * the GPL and zlib licenses. See gpl.txt or zlib.txt for details.
00003  */
00008 #include "alleggl.h"
00009 #include "allglint.h"
00010 #include <string.h>
00011 #ifdef ALLEGRO_MACOSX
00012 #include <OpenGL/glu.h>
00013 #else
00014 #include <GL/glu.h>
00015 #endif
00016 
00017 #include <allegro/internal/aintern.h>
00018 
00019 
00020 /* GL extension Structure. Holds the extension pointers for a single context */
00021 #define AGL_API(type, name, args) AGL_##name##_t name;
00022 typedef struct AGL_EXT {
00023 #   include "allegrogl/GLext/gl_ext_api.h"
00024 #ifdef ALLEGRO_WINDOWS
00025 #   include "allegrogl/GLext/wgl_ext_api.h"
00026 #elif defined ALLEGRO_UNIX
00027 #   include "allegrogl/GLext/glx_ext_api.h"
00028 #endif
00029 } AGL_EXT;
00030 #undef AGL_API
00031 
00032 #define PREFIX_I                "agl-ext INFO: "
00033 #define PREFIX_W                "agl-ext WARNING: "
00034 #define PREFIX_E                "agl-ext ERROR: "
00035 
00036 
00037 /* Current driver info */
00038 struct allegro_gl_info allegro_gl_info;
00039 
00040 
00041 
00055 struct AGL_EXTENSION_LIST_GL allegro_gl_extensions_GL;
00056 
00057 
00058 
00064 #ifdef ALLEGRO_UNIX
00065 struct AGL_EXTENSION_LIST_GLX allegro_gl_extensions_GLX;
00066 #endif
00067 
00068 
00069 
00075 #ifdef ALLEGRO_WINDOWS
00076 struct AGL_EXTENSION_LIST_WGL allegro_gl_extensions_WGL;
00077 #endif
00078 
00079 
00080 
00081 /* Current context */
00082 AGL_EXT *agl_extension_table = NULL;
00083 
00084 
00085 #ifdef ALLEGROGL_GENERIC_DRIVER
00086 #include "GL/amesa.h"
00087 #endif
00088 
00089 
00090 #ifdef ALLEGROGL_HAVE_DYNAMIC_LINK
00091 #include <dlfcn.h>
00092 
00093 /* Handle for dynamic library libGL.so */
00094 static void* __agl_handle = NULL;
00095 /* Pointer to glXGetProcAddressARB */
00096 typedef void* (*GLXGETPROCADDRESSARBPROC) (const GLubyte*);
00097 static GLXGETPROCADDRESSARBPROC aglXGetProcAddress;
00098 #else
00099 /* Tries static linking */
00100 #ifdef ALLEGROGL_GLXGETPROCADDRESSARB
00101 #define aglXGetProcAddress glXGetProcAddressARB
00102 #else
00103 #define aglXGetProcAddress glXGetProcAddress
00104 #endif
00105 #endif
00106 
00107 
00108 #ifdef ALLEGRO_MACOSX
00109 #undef TRUE
00110 #undef FALSE
00111 #include <Carbon/Carbon.h>
00112 #undef TRUE
00113 #undef FALSE
00114 #define TRUE  -1
00115 #define FALSE 0
00116 
00117 static CFBundleRef opengl_bundle_ref;
00118 #endif
00119 
00120 
00121 
00122 /* Define the GL API pointers */
00123 #define AGL_API(type, name, args) AGL_##name##_t __agl##name = NULL;
00124 #   include "allegrogl/GLext/gl_ext_api.h"
00125 #undef AGL_API
00126 #ifdef ALLEGRO_WINDOWS
00127 #define AGL_API(type, name, args) AGL_##name##_t __awgl##name = NULL;
00128 #   include "allegrogl/GLext/wgl_ext_api.h"
00129 #undef AGL_API
00130 #elif defined ALLEGRO_UNIX
00131 #define AGL_API(type, name, args) AGL_##name##_t __aglX##name = NULL;
00132 #   include "allegrogl/GLext/glx_ext_api.h"
00133 #undef AGL_API
00134 #endif
00135 
00136 
00137 
00138 /* Create the extension table */
00139 AGL_EXT* __allegro_gl_create_extensions() {
00140 
00141     AGL_EXT *ret = malloc(sizeof(AGL_EXT));
00142 
00143     if (!ret) {
00144         return NULL;
00145     }
00146 
00147     memset(ret, 0, sizeof(AGL_EXT));
00148 
00149     return ret;
00150 }
00151 
00152 
00153 
00154 /* Load the extension addresses into the table.
00155  * Should only be done on context creation.
00156  */
00157 void __allegro_gl_load_extensions(AGL_EXT *ext) {
00158 
00159 #ifdef ALLEGRO_MACOSX
00160     CFStringRef function;
00161 #endif
00162 
00163     if (!ext) {
00164         return;
00165     }
00166 #ifdef ALLEGRO_UNIX
00167     if (!aglXGetProcAddress) {
00168         return;
00169     }
00170 #endif
00171 
00172 #   ifdef ALLEGRO_WINDOWS
00173 #   define AGL_API(type, name, args) \
00174         ext->name = (AGL_##name##_t)wglGetProcAddress("gl" #name); \
00175         if (ext->name) { AGL_LOG(2,"gl" #name " successfully loaded\n"); }
00176 #   include "allegrogl/GLext/gl_ext_api.h"
00177 #   undef AGL_API
00178 #   define AGL_API(type, name, args) \
00179         ext->name = (AGL_##name##_t)wglGetProcAddress("wgl" #name); \
00180         if (ext->name) { AGL_LOG(2,"wgl" #name " successfully loaded\n"); }
00181 #   include "allegrogl/GLext/wgl_ext_api.h"
00182 #   undef AGL_API
00183 #   elif defined ALLEGRO_UNIX
00184 #   define AGL_API(type, name, args) \
00185         ext->name = (AGL_##name##_t)aglXGetProcAddress((const GLubyte*)"gl" #name); \
00186         if (ext->name) { AGL_LOG(2,"gl" #name " successfully loaded\n"); }
00187 #   include "allegrogl/GLext/gl_ext_api.h"
00188 #   undef AGL_API
00189 #   define AGL_API(type, name, args) \
00190         ext->name = (AGL_##name##_t)aglXGetProcAddress((const GLubyte*)"glX" #name); \
00191         if (ext->name) { AGL_LOG(2,"glX" #name " successfully loaded\n"); }
00192 #   include "allegrogl/GLext/glx_ext_api.h"
00193 #   undef AGL_API
00194 #   elif defined ALLEGRO_MACOSX
00195 #   define AGL_API(type, name, args)                                          \
00196         function = CFStringCreateWithCString(kCFAllocatorDefault, "gl" #name, \
00197                                                      kCFStringEncodingASCII); \
00198         if (function) {                                                       \
00199             ext->name = (AGL_##name##_t)CFBundleGetFunctionPointerForName(    \
00200                                              opengl_bundle_ref, function);    \
00201             CFRelease(function);                                              \
00202         }                                                                     \
00203         if (ext->name) { AGL_LOG(2,"gl" #name " successfully loaded\n"); }
00204 #   include "allegrogl/GLext/gl_ext_api.h"
00205 #   undef AGL_API
00206 #   endif
00207 }
00208 
00209 
00210 
00211 /* Set the GL API pointers to the current table 
00212  * Should only be called on context switches.
00213  */
00214 void __allegro_gl_set_extensions(AGL_EXT *ext) {
00215 
00216     if (!ext) {
00217         return;
00218     }
00219 
00220 #define AGL_API(type, name, args) __agl##name = ext->name;
00221 #   include "allegrogl/GLext/gl_ext_api.h"
00222 #undef AGL_API
00223 #ifdef ALLEGRO_WINDOWS
00224 #define AGL_API(type, name, args) __awgl##name = ext->name;
00225 #   include "allegrogl/GLext/wgl_ext_api.h"
00226 #undef AGL_API
00227 #elif defined ALLEGRO_UNIX
00228 #define AGL_API(type, name, args) __aglX##name = ext->name;
00229 #   include "allegrogl/GLext/glx_ext_api.h"
00230 #undef AGL_API
00231 #endif
00232 }
00233 
00234 
00235 
00236 /* Destroys the extension table */
00237 void __allegro_gl_destroy_extensions(AGL_EXT *ext) {
00238 
00239     if (ext) {
00240         if (ext == agl_extension_table) {
00241             agl_extension_table = NULL;
00242         }
00243         free(ext);
00244     }
00245 }
00246 
00247 
00248 
00249 /* __allegro_gl_look_for_an_extension:
00250  * This function has been written by Mark J. Kilgard in one of his
00251  * tutorials about OpenGL extensions
00252  */
00253 int __allegro_gl_look_for_an_extension(AL_CONST char *name,
00254                                                   AL_CONST GLubyte * extensions)
00255 {
00256     AL_CONST GLubyte *start;
00257     GLubyte *where, *terminator;
00258 
00259     /* Extension names should not have spaces. */
00260     where = (GLubyte *) strchr(name, ' ');
00261     if (where || *name == '\0')
00262         return FALSE;
00263     /* It takes a bit of care to be fool-proof about parsing the
00264      * OpenGL extensions string. Don't be fooled by sub-strings, etc.
00265      */
00266     start = extensions;
00267     for (;;) {
00268         where = (GLubyte *) strstr((AL_CONST char *) start, name);
00269         if (!where)
00270         break;
00271         terminator = where + strlen(name);
00272         if (where == start || *(where - 1) == ' ')
00273             if (*terminator == ' ' || *terminator == '\0')
00274                 return TRUE;
00275         start = terminator;
00276     }
00277     return FALSE;
00278 }
00279 
00280 
00281 
00282 #ifdef ALLEGRO_WINDOWS
00283 static AGL_GetExtensionsStringARB_t __wglGetExtensionsStringARB = NULL;
00284 static HDC __hdc = NULL;
00285 #elif defined ALLEGRO_UNIX
00286 #include <xalleg.h>
00287 #endif
00288 
00289 
00290 /* int allegro_gl_is_extension_supported(AL_CONST char *extension) */
00306 int allegro_gl_is_extension_supported(AL_CONST char *extension)
00307 {
00308     int ret;
00309     
00310     if (!__allegro_gl_valid_context)
00311         return FALSE;
00312 
00313     if (!glGetString(GL_EXTENSIONS))
00314         return FALSE;
00315 
00316     ret = __allegro_gl_look_for_an_extension(extension,
00317                                                   glGetString(GL_EXTENSIONS));
00318 
00319 #ifdef ALLEGRO_WINDOWS
00320     if (!ret && strncmp(extension, "WGL", 3) == 0) {
00321         if (!__wglGetExtensionsStringARB || __hdc != __allegro_gl_hdc) {
00322             __wglGetExtensionsStringARB = (AGL_GetExtensionsStringARB_t)
00323                                wglGetProcAddress("wglGetExtensionsStringARB");
00324             __hdc = __allegro_gl_hdc;
00325         }
00326         if (__wglGetExtensionsStringARB) {
00327             ret = __allegro_gl_look_for_an_extension(extension,
00328                        (AL_CONST GLubyte*)__wglGetExtensionsStringARB(__allegro_gl_hdc));
00329         }
00330     }
00331 #elif defined ALLEGRO_UNIX
00332     if (!ret && strncmp(extension, "GLX", 3) == 0) {
00333         XLOCK();
00334         ret = __allegro_gl_look_for_an_extension(extension,
00335                 (const GLubyte*)glXQueryExtensionsString(_xwin.display,
00336                                                          _xwin.screen));
00337         XUNLOCK();
00338     }
00339 #endif
00340 
00341     return ret;
00342 }
00343 
00344 
00345 
00346 /* void * allegro_gl_get_proc_address(AL_CONST char *name) */
00372 void *allegro_gl_get_proc_address(AL_CONST char *name)
00373 {
00374     void *symbol = NULL;
00375 #ifdef ALLEGRO_MACOSX
00376     CFStringRef function;
00377 #endif
00378 
00379     if (!__allegro_gl_valid_context)
00380         return NULL;
00381 
00382 #ifdef ALLEGROGL_GENERIC_DRIVER
00383     /* AMesa provides a function to get a proc address. It does
00384      * not emulate dynamic linking of course...
00385      */
00386     symbol = AMesaGetProcAddress(name);
00387 
00388 #elif defined ALLEGRO_WINDOWS
00389     /* For once Windows is the easiest platform to use :)
00390      * It provides a standardized way to get a function address
00391      * But of course there is a drawback : the symbol is only valid
00392      * under the current context :P
00393      */
00394     symbol = wglGetProcAddress(name);
00395 #elif defined ALLEGRO_UNIX
00396     if (aglXGetProcAddress) {
00397         /* This is definitely the *good* way on Unix to get a GL proc
00398          * address. Unfortunately glXGetProcAddress is an extension
00399          * and may not be available on all platforms
00400          */
00401         symbol = aglXGetProcAddress((const GLubyte*)name);
00402     }
00403 #elif defined ALLEGROGL_HAVE_DYNAMIC_LINK
00404     else {
00405         /* Hack if glXGetProcAddress is not available :
00406          * we try to find the symbol into libGL.so
00407          */
00408         if (__agl_handle) {
00409             symbol = dlsym(__agl_handle, name);
00410         }
00411     }
00412 #elif defined ALLEGRO_MACOSX
00413     function = CFStringCreateWithCString(kCFAllocatorDefault, name,
00414                                          kCFStringEncodingASCII);
00415     if (function) {
00416         symbol = CFBundleGetFunctionPointerForName(opengl_bundle_ref, function);
00417         CFRelease(function);
00418     }
00419 #else
00420     /* DOS does not support dynamic linking. If the function is not
00421      * available at build-time then it will not be available at run-time
00422      * Therefore we do not need to look for it...
00423      */
00424 #endif
00425 
00426     if (!symbol) {
00427 
00428 #if defined ALLEGROGL_HAVE_DYNAMIC_LINK
00429         if (!aglXGetProcAddress) {
00430             TRACE(PREFIX_W "get_proc_address: libdl::dlsym: %s\n",
00431                   dlerror());
00432         }
00433 #endif
00434         
00435         TRACE(PREFIX_W "get_proc_address : Unable to load symbol %s\n",
00436               name);
00437     }
00438     else {
00439         TRACE(PREFIX_I "get_proc_address : Symbol %s successfully loaded\n",
00440               name);
00441     }
00442     return symbol;
00443 }
00444 
00445 
00446 
00447 /* Fills in the AllegroGL info struct for blacklisting video cards.
00448  */
00449 static void __fill_in_info_struct(const GLubyte *rendereru,
00450                                   struct allegro_gl_info *info) {
00451     const char *renderer = (const char*)rendereru;
00452     
00453     /* Some cards are "special"... */
00454     if (strstr(renderer, "3Dfx/Voodoo")) {
00455         info->is_voodoo = 1;
00456     }
00457     else if (strstr(renderer, "Matrox G200")) {
00458         info->is_matrox_g200 = 1;
00459     }
00460     else if (strstr(renderer, "RagePRO")) {
00461         info->is_ati_rage_pro = 1;
00462     }
00463     else if (strstr(renderer, "RADEON 7000")) {
00464         info->is_ati_radeon_7000 = 1;
00465     }
00466     else if (strstr(renderer, "Mesa DRI R200")) {
00467         info->is_ati_r200_chip = 1;
00468     }
00469 
00470     if ((strncmp(renderer, "3Dfx/Voodoo3 ", 13) == 0)
00471      || (strncmp(renderer, "3Dfx/Voodoo2 ", 13) == 0) 
00472      || (strncmp(renderer, "3Dfx/Voodoo ", 12) == 0)) {
00473         info->is_voodoo3_and_under = 1;
00474     }
00475 
00476     /* Read OpenGL properties */    
00477     info->version = allegro_gl_opengl_version();
00478 
00479     return;
00480 }
00481 
00482 
00483 
00484 /* __allegro_gl_manage_extensions:
00485  * This functions fills the __allegro_gl_extensions structure and displays
00486  * on the log file which extensions are available
00487  */
00488 void __allegro_gl_manage_extensions(void)
00489 {
00490     AL_CONST GLubyte *buf;
00491     int i;
00492 
00493 #ifdef ALLEGRO_MACOSX
00494     CFURLRef bundle_url;
00495 #endif
00496 
00497     /* Print out OpenGL extensions */
00498 #if LOGLEVEL >= 1
00499     AGL_LOG(1, "OpenGL Extensions:\n");
00500              __allegro_gl_print_extensions((AL_CONST char*)
00501             glGetString(GL_EXTENSIONS));
00502 #endif
00503     
00504     /* Print out GLU version */
00505     buf = gluGetString(GLU_VERSION);
00506     TRACE(PREFIX_I "GLU Version : %s\n", buf);
00507 
00508 #ifdef ALLEGROGL_HAVE_DYNAMIC_LINK
00509     /* Get glXGetProcAddress entry */
00510     __agl_handle = dlopen("libGL.so", RTLD_LAZY);
00511     if (__agl_handle) {
00512         aglXGetProcAddress = (GLXGETPROCADDRESSARBPROC) dlsym(__agl_handle,
00513                                                         "glXGetProcAddressARB");
00514         if (!aglXGetProcAddress) {
00515             aglXGetProcAddress = (GLXGETPROCADDRESSARBPROC) dlsym(__agl_handle,
00516                                                            "glXGetProcAddress");
00517         }
00518     }
00519     else {
00520         TRACE(PREFIX_W "Failed to dlopen libGL.so : %s\n", dlerror());
00521     }
00522     TRACE(PREFIX_I "glXGetProcAddress Extension: %s\n",
00523                            aglXGetProcAddress ? "Supported" : "Unsupported");
00524 #elif defined ALLEGRO_UNIX
00525 #ifdef ALLEGROGL_GLXGETPROCADDRESSARB
00526     TRACE(PREFIX_I "glXGetProcAddressARB Extension: supported\n");
00527 #else
00528     TRACE(PREFIX_I "glXGetProcAddress Extension: supported\n");
00529 #endif
00530 #endif
00531     
00532 #ifdef ALLEGRO_MACOSX
00533     bundle_url = CFURLCreateWithFileSystemPath(kCFAllocatorDefault,
00534                          CFSTR("/System/Library/Frameworks/OpenGL.framework"),
00535                          kCFURLPOSIXPathStyle, true);
00536     opengl_bundle_ref = CFBundleCreate(kCFAllocatorDefault, bundle_url);
00537     CFRelease(bundle_url);
00538 #endif
00539 
00540     __fill_in_info_struct(glGetString(GL_RENDERER), &allegro_gl_info);
00541 
00542     /* Load extensions */
00543     agl_extension_table = __allegro_gl_create_extensions();
00544     __allegro_gl_load_extensions(agl_extension_table);
00545     __allegro_gl_set_extensions(agl_extension_table);
00546     
00547     for (i = 0; i < 5; i++) {
00548         __allegro_gl_texture_read_format[i] = -1;
00549         __allegro_gl_texture_components[i] = GL_RGB;
00550     }
00551     __allegro_gl_texture_read_format[3] = GL_UNSIGNED_BYTE;
00552     __allegro_gl_texture_read_format[4] = GL_UNSIGNED_BYTE;
00553     __allegro_gl_texture_components[4] = GL_RGBA;
00554 
00555     
00556     /* Get extension info for the rest of the lib */
00557 #    define AGL_EXT(name, ver) {                               \
00558         allegro_gl_extensions_GL.name =                        \
00559               allegro_gl_is_extension_supported("GL_" #name)   \
00560           || (allegro_gl_info.version >= ver && ver > 0);      \
00561     }
00562 #   include "allegrogl/GLext/gl_ext_list.h"
00563 #   undef AGL_EXT
00564 
00565 #ifdef ALLEGRO_UNIX
00566 #    define AGL_EXT(name, ver) {                               \
00567         allegro_gl_extensions_GLX.name =                       \
00568               allegro_gl_is_extension_supported("GLX_" #name)  \
00569           || (allegro_gl_info.version >= ver && ver > 0);      \
00570     }
00571 #   include "allegrogl/GLext/glx_ext_list.h"
00572 #   undef AGL_EXT
00573 #elif defined ALLEGRO_WINDOWS
00574 #    define AGL_EXT(name, ver) {                               \
00575         allegro_gl_extensions_WGL.name =                       \
00576               allegro_gl_is_extension_supported("WGL_" #name)  \
00577           || (allegro_gl_info.version >= ver && ver > 0);      \
00578     }
00579 #   include "allegrogl/GLext/wgl_ext_list.h"
00580 #   undef AGL_EXT
00581 #endif
00582     
00583     /* Get number of texture units */
00584     if (allegro_gl_extensions_GL.ARB_multitexture) {
00585         glGetIntegerv(GL_MAX_TEXTURE_UNITS,
00586                       (GLint*)&allegro_gl_info.num_texture_units);
00587     }
00588     else {
00589         allegro_gl_info.num_texture_units = 1;
00590     }
00591 
00592     /* Get max texture size */
00593     glGetIntegerv(GL_MAX_TEXTURE_SIZE,
00594                   (GLint*)&allegro_gl_info.max_texture_size);
00595 
00596     /* Note: Voodoo (even V5) don't seem to correctly support
00597      * packed pixel formats. Disabling them for those cards.
00598      */
00599     allegro_gl_extensions_GL.EXT_packed_pixels &= !allegro_gl_info.is_voodoo;
00600 
00601     
00602     if (allegro_gl_extensions_GL.EXT_packed_pixels) {
00603 
00604         AGL_LOG(1, "Packed Pixels formats available\n");
00605 
00606         /* XXX On NV cards, we want to use BGRA instead of RGBA for speed */
00607         /* Fills the __allegro_gl_texture_format array */
00608         __allegro_gl_texture_read_format[0] = GL_UNSIGNED_BYTE_3_3_2;
00609         __allegro_gl_texture_read_format[1] = GL_UNSIGNED_SHORT_5_5_5_1;
00610         __allegro_gl_texture_read_format[2] = GL_UNSIGNED_SHORT_5_6_5;
00611     }
00612 
00613     /* NVidia and ATI cards expose OpenGL 2.0 but often don't accelerate
00614      * non-power-of-2 textures. This check is how you verify that NP2
00615      * textures are hardware accelerated or not.
00616      * We should clobber the NPOT support if it's not accelerated.
00617      */
00618     {   const char *vendor = (const char*)glGetString(GL_VENDOR);
00619         if (strstr(vendor, "NVIDIA Corporation")) {
00620             if (!allegro_gl_extensions_GL.NV_fragment_program2
00621              || !allegro_gl_extensions_GL.NV_vertex_program3) {
00622                 allegro_gl_extensions_GL.ARB_texture_non_power_of_two = 0;
00623             }
00624         }
00625         else if (strstr(vendor, "ATI Technologies")) {
00626             if (!strstr((const char*)glGetString(GL_EXTENSIONS),
00627                         "GL_ARB_texture_non_power_of_two")
00628              && allegro_gl_info.version >= 2.0f) {
00629                 allegro_gl_extensions_GL.ARB_texture_non_power_of_two = 0;
00630             }
00631         }
00632     }
00633 }
00634 
00635 
00636 
00637 /* __allegro_gl_print_extensions:
00638  * Given a string containing extensions (i.e. a NULL terminated string where
00639  * each extension are separated by a space and which names do not contain any
00640  * space)
00641  */
00642 void __allegro_gl_print_extensions(AL_CONST char * extension)
00643 {
00644         char buf[80];
00645         char* start;
00646 
00647         while (*extension != '\0') {
00648                 start = buf;
00649                 strncpy(buf, extension, 80);
00650                 while ((*start != ' ') && (*start != '\0')) {
00651                         extension++;
00652                         start++;
00653                 }
00654                 *start = '\0';
00655                 extension ++;
00656                 TRACE(PREFIX_I "%s\n", buf);
00657         }
00658 }
00659 
00660 
00661 
00662 void __allegro_gl_unmanage_extensions() {
00663     __allegro_gl_destroy_extensions(agl_extension_table);
00664 #ifdef ALLEGRO_MACOSX
00665     CFRelease(opengl_bundle_ref);
00666 #endif
00667 #ifdef ALLEGROGL_HAVE_DYNAMIC_LINK
00668     if (__agl_handle) {
00669         dlclose(__agl_handle);
00670         __agl_handle = NULL;
00671     }
00672 #endif
00673 }
00674 
allegro4.4-4.4.2/addons/allegrogl/docs/html/globals.html000066400000000000000000000463341173507505700230450ustar00rootroot00000000000000 AllegroGL: Globals
Here is a list of all documented functions, variables, defines, enums, and typedefs with links to the documentation:

- a -

- d -

- g -

- i -

- r -

allegro4.4-4.4.2/addons/allegrogl/docs/html/globals_defs.html000066400000000000000000000231751173507505700240440ustar00rootroot00000000000000 AllegroGL: Globals
 

- a -

- g -

allegro4.4-4.4.2/addons/allegrogl/docs/html/globals_func.html000066400000000000000000000275731173507505700240640ustar00rootroot00000000000000 AllegroGL: Globals
 

- a -

- d -

- i -

- r -

allegro4.4-4.4.2/addons/allegrogl/docs/html/globals_vars.html000066400000000000000000000057141173507505700240750ustar00rootroot00000000000000 AllegroGL: Globals
 
allegro4.4-4.4.2/addons/allegrogl/docs/html/glvtable_8c.html000066400000000000000000000723271173507505700236150ustar00rootroot00000000000000 AllegroGL: glvtable.c File Reference

glvtable.c File Reference

Allegro->OpenGL conversion vtable. More...

#include <string.h>
#include <allegro.h>
#include "alleggl.h"
#include "allglint.h"
#include "glvtable.h"
#include <allegro/internal/aintern.h>
#include <GL/glu.h>

Go to the source code of this file.

Defines

  • #define SET_TEX_COORDS(x, y)
  • #define BITMAP_BLIT_CLIP(source, dest, source_x, source_y, dest_x, dest_y, width, height)
  • #define DRAW_RLE_8888(bits)
  • #define BIN_2_DEG(x)   (-(x) * 180.0 / 128)

Functions

  • int __allegro_gl_make_power_of_2 (int x)
  • void allegro_gl_drawing_mode (void)
  • void split_color (int color, GLubyte *r, GLubyte *g, GLubyte *b, GLubyte *a, int color_depth)
  • void allegro_gl_created_sub_bitmap (BITMAP *bmp, BITMAP *parent)
  • static void allegro_gl_screen_acquire (struct BITMAP *bmp)
    acquire_bitmap(screen) overload.
  • static void allegro_gl_screen_release (struct BITMAP *bmp)
    release_bitmap(screen) overload.
  • static int allegro_gl_screen_getpixel (struct BITMAP *bmp, int x, int y)
  • static void allegro_gl_screen_putpixel (struct BITMAP *bmp, int x, int y, int color)
  • static void allegro_gl_screen_vline (struct BITMAP *bmp, int x, int y1, int y2, int color)
  • static void allegro_gl_screen_hline (struct BITMAP *bmp, int x1, int y, int x2, int color)
  • static void allegro_gl_screen_line (struct BITMAP *bmp, int x1, int y1, int x2, int y2, int color)
  • void allegro_gl_screen_rectfill (struct BITMAP *bmp, int x1, int y1, int x2, int y2, int color)
  • static void allegro_gl_screen_triangle (struct BITMAP *bmp, int x1, int y1, int x2, int y2, int x3, int y3, int color)
  • static void allegro_gl_screen_blit_from_memory (struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)
  • static void allegro_gl_screen_blit_to_memory (struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)
  • void allegro_gl_screen_blit_to_self (struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)
  • void allegro_gl_upload_and_display_texture (struct BITMAP *source, int source_x, int source_y, int dest_x, int dest_y, int width, int height, int flip_dir, GLint format, GLint type)
  • static void do_screen_masked_blit_standard (GLint format, GLint type, struct BITMAP *temp, int source_x, int source_y, int dest_x, int dest_y, int width, int height, int flip_dir, int blit_type)
  • static void screen_masked_blit_standard (struct BITMAP *source, int source_x, int source_y, int dest_x, int dest_y, int width, int height, int flip_dir, int blit_type)
  • static void __allegro_gl_init_nv_register_combiners (BITMAP *bmp)
  • static void screen_masked_blit_nv_register (struct BITMAP *source, int source_x, int source_y, int dest_x, int dest_y, int width, int height, int flip_dir, int blit_type)
  • static void __allegro_gl_init_combine_textures (BITMAP *bmp)
  • static void screen_masked_blit_combine_tex (struct BITMAP *source, int source_x, int source_y, int dest_x, int dest_y, int width, int height, int flip_dir, int blit_type)
  • void do_masked_blit_screen (struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height, int flip_dir, int blit_type)
  • static BITMAP * __allegro_gl_convert_rle_sprite (AL_CONST struct RLE_SPRITE *sprite, int trans)
  • void allegro_gl_screen_draw_rle_sprite (struct BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y)
  • static void allegro_gl_screen_draw_trans_rgba_rle_sprite (struct BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y)
  • static void allegro_gl_screen_masked_blit (struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)
  • static void allegro_gl_screen_draw_sprite (struct BITMAP *bmp, struct BITMAP *sprite, int x, int y)
  • static void allegro_gl_screen_draw_sprite_v_flip (struct BITMAP *bmp, struct BITMAP *sprite, int x, int y)
  • static void allegro_gl_screen_draw_sprite_h_flip (struct BITMAP *bmp, struct BITMAP *sprite, int x, int y)
  • static void allegro_gl_screen_draw_sprite_vh_flip (struct BITMAP *bmp, struct BITMAP *sprite, int x, int y)
  • static void allegro_gl_screen_pivot_scaled_sprite_flip (struct BITMAP *bmp, struct BITMAP *sprite, fixed x, fixed y, fixed cx, fixed cy, fixed angle, fixed scale, int v_flip)
  • static void allegro_gl_screen_draw_trans_rgba_sprite (struct BITMAP *bmp, struct BITMAP *sprite, int x, int y)
  • static void allegro_gl_screen_draw_sprite_ex (struct BITMAP *bmp, struct BITMAP *sprite, int x, int y, int mode, int flip)
  • void allegro_gl_screen_draw_glyph_ex (struct BITMAP *bmp, AL_CONST struct FONT_GLYPH *glyph, int x, int y, int color, int bg, int flip)
  • static void allegro_gl_screen_draw_glyph (struct BITMAP *bmp, AL_CONST struct FONT_GLYPH *glyph, int x, int y, int color, int bg)
  • void allegro_gl_screen_draw_color_glyph_ex (struct BITMAP *bmp, struct BITMAP *sprite, int x, int y, int color, int bg, int flip)
  • static void allegro_gl_screen_draw_color_glyph (struct BITMAP *bmp, struct BITMAP *sprite, int x, int y, int color, int bg)
  • static void allegro_gl_screen_draw_character (struct BITMAP *bmp, struct BITMAP *sprite, int x, int y, int color, int bg)
  • static void allegro_gl_screen_draw_256_sprite (struct BITMAP *bmp, struct BITMAP *sprite, int x, int y)
  • void allegro_gl_screen_clear_to_color (struct BITMAP *bmp, int color)
  • static void allegro_gl_screen_polygon (struct BITMAP *bmp, int vertices, AL_CONST int *points, int color)
  • static void allegro_gl_screen_rect (struct BITMAP *bmp, int x1, int y1, int x2, int y2, int color)
  • void allegro_gl_screen_polygon3d_f (struct BITMAP *bmp, int type, struct BITMAP *texture, int vc, V3D_f *vtx[])
  • static void allegro_gl_screen_polygon3d (struct BITMAP *bmp, int type, struct BITMAP *texture, int vc, V3D *vtx[])
  • static void allegro_gl_screen_quad3d_f (struct BITMAP *bmp, int type, struct BITMAP *texture, V3D_f *v1, V3D_f *v2, V3D_f *v3, V3D_f *v4)
  • static void allegro_gl_screen_quad3d (struct BITMAP *bmp, int type, struct BITMAP *texture, V3D *v1, V3D *v2, V3D *v3, V3D *v4)
  • static void allegro_gl_screen_triangle3d (struct BITMAP *bmp, int type, struct BITMAP *texture, V3D *v1, V3D *v2, V3D *v3)
  • static void allegro_gl_screen_triangle3d_f (struct BITMAP *bmp, int type, struct BITMAP *texture, V3D_f *v1, V3D_f *v2, V3D_f *v3)
  • void __allegro_gl__glvtable_update_vtable (GFX_VTABLE **vtable)
  • void allegro_gl_set_allegro_mode (void)
    Prepares for Allegro drawing to the screen.
  • void allegro_gl_unset_allegro_mode (void)
    Restores previous OpenGL settings.
  • void allegro_gl_set_projection (void)
    Prepares for Allegro drawing to the screen.
  • void allegro_gl_unset_projection (void)
    Restores previously saved projection.
  • void allegro_gl_memory_blit_between_formats (struct BITMAP *src, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)
  • static void dummy_unwrite_bank (void)

Variables

  • static GFX_VTABLE allegro_gl_screen_vtable
  • static GLuint __allegro_gl_pool_texture = 0
  • static GLuint __allegro_gl_dummy_texture = 0
  • static int __agl_owning_drawing_pattern_tex = FALSE
  • GLuint __agl_drawing_pattern_tex = 0
  • BITMAP * __agl_drawing_pattern_bmp = 0
  • static int __agl_drawing_mode = DRAW_MODE_SOLID
  • static double allegro_gl_projection_matrix [16]
  • static double allegro_gl_modelview_matrix [16]

Detailed Description

Allegro->OpenGL conversion vtable.

Definition in file glvtable.c.


Define Documentation

#define DRAW_RLE_8888 (   bits)
Value:
{                               \
        for (y = 0; y < sprite->h; y++) {           \
            signed long c = *s++;               \
            for (x = 0; x < sprite->w;) {           \
                if (c == src_mask)          \
                    break;              \
                if (c > 0) {                \
                    /* Run of solid pixels */   \
                    for (c--; c>=0; c--) {      \
                        unsigned long col = *s++;       \
                        if (bits == 32 && trans)        \
                            _putpixel32(temp, x++, y, makeacol32(getr32(col), getg32(col), getb32(col), geta32(col))); \
                        else            \
                            _putpixel32(temp, x++, y, makeacol32(getr##bits(col), getg##bits(col), getb##bits(col), 255)); \
                    }               \
                }                   \
                else {                  \
                    /* Run of transparent pixels */ \
                    hline(temp, x, y, x-c+1, 0);    \
                    x -= c;             \
                }                   \
                c = *s++;               \
            }                       \
        }                           \
    }
allegro4.4-4.4.2/addons/allegrogl/docs/html/glvtable_8c_source.html000066400000000000000000006036251173507505700251760ustar00rootroot00000000000000 AllegroGL: glvtable.c Source File

glvtable.c

Go to the documentation of this file.
00001 /* This code is (C) AllegroGL contributors, and double licensed under
00002  * the GPL and zlib licenses. See gpl.txt or zlib.txt for details.
00003  */
00008 #include <string.h>
00009 
00010 #include <allegro.h>
00011 
00012 #ifdef ALLEGRO_WINDOWS
00013 #include <winalleg.h>
00014 #endif
00015 
00016 #include "alleggl.h"
00017 #include "allglint.h"
00018 #include "glvtable.h"
00019 #include <allegro/internal/aintern.h>
00020 #ifdef ALLEGRO_MACOSX
00021 #include <OpenGL/glu.h>
00022 #else
00023 #include <GL/glu.h>
00024 #endif
00025 
00026 
00027 static GFX_VTABLE allegro_gl_screen_vtable;
00028 static GLuint __allegro_gl_pool_texture = 0;
00029 
00030 static GLuint __allegro_gl_dummy_texture = 0; /* For ATI Rage Pro */
00031 
00032 static int __agl_owning_drawing_pattern_tex = FALSE;
00033 GLuint __agl_drawing_pattern_tex = 0;
00034 BITMAP *__agl_drawing_pattern_bmp = 0;
00035 static int __agl_drawing_mode = DRAW_MODE_SOLID;
00036 
00037 
00058 /* Computes the next power of two if the number wasn't a power of two to start
00059  * with. Ref: http://bob.allegronetwork.com/prog/tricks.html#roundtonextpowerof2
00060  */
00061 int __allegro_gl_make_power_of_2(int x) {
00062     x--;
00063     x |= (x >> 1);
00064     x |= (x >> 2);
00065     x |= (x >> 4);
00066     x |= (x >> 8);
00067     x |= (x >> 16);
00068     x++;
00069     return x;
00070 }
00071 
00072 
00073 
00074 /* allegro_gl_drawing_mode (GFX_DRIVER vtable entry):
00075  * Sets the drawing mode. Same implementation to all GFX vtables.
00076  */
00077 void allegro_gl_drawing_mode(void) {
00078     if (__agl_drawing_mode == _drawing_mode)
00079         return;
00080 
00081     switch (__agl_drawing_mode) {
00082         case DRAW_MODE_TRANS:
00083             glDisable(GL_BLEND);
00084         break;
00085         case DRAW_MODE_XOR:
00086             glDisable(GL_COLOR_LOGIC_OP);
00087         break;
00088         case DRAW_MODE_COPY_PATTERN:
00089             glDisable(GL_TEXTURE_2D);
00090             glBindTexture(GL_TEXTURE_2D, 0);
00091             if (__agl_owning_drawing_pattern_tex && __agl_drawing_pattern_tex)
00092                 glDeleteTextures(1, &__agl_drawing_pattern_tex);
00093             __agl_drawing_pattern_tex = 0;
00094             __agl_drawing_pattern_bmp = 0;
00095         break;
00096     }
00097 
00098     __agl_drawing_mode = _drawing_mode;
00099 
00100     switch (_drawing_mode) {
00101         case DRAW_MODE_TRANS:
00102             glEnable(GL_BLEND);
00103         break;
00104 
00105         case DRAW_MODE_XOR:
00106             glEnable(GL_COLOR_LOGIC_OP);
00107             glLogicOp(GL_XOR);
00108         break;
00109 
00110         case DRAW_MODE_COPY_PATTERN:
00111             if (is_memory_bitmap(_drawing_pattern)) {
00112                 __agl_drawing_pattern_tex =
00113                                     allegro_gl_make_texture(_drawing_pattern);
00114                 __agl_drawing_pattern_bmp = _drawing_pattern;
00115                 __agl_owning_drawing_pattern_tex = TRUE;
00116             }
00117             else if (is_video_bitmap(_drawing_pattern)) {
00118                 AGL_VIDEO_BITMAP *bmp = _drawing_pattern->extra;
00119                 __agl_drawing_pattern_tex = bmp->tex;
00120                 __agl_drawing_pattern_bmp = bmp->memory_copy;
00121                 __agl_owning_drawing_pattern_tex = FALSE;
00122             }
00123 
00124             glEnable(GL_TEXTURE_2D);
00125             glBindTexture(GL_TEXTURE_2D, __agl_drawing_pattern_tex);
00126 
00127             break;
00128     }
00129 }
00130 
00131 
00132 void split_color(int color, GLubyte *r, GLubyte *g, GLubyte *b, GLubyte *a,
00133                         int color_depth)
00134 {
00135     AGL_LOG(2, "glvtable.c:split_color\n");
00136     *r = getr_depth(color_depth, color);
00137     *g = getg_depth(color_depth, color);
00138     *b = getb_depth(color_depth, color);
00139     if (color_depth == 32)
00140         *a = geta_depth(color_depth, color);
00141     else
00142         *a = 255;
00143 }
00144 
00145 
00146 /* allegro_gl_created_sub_bitmap:
00147  */
00148 void allegro_gl_created_sub_bitmap(BITMAP *bmp, BITMAP *parent)
00149 {
00150    bmp->extra = parent;
00151 }
00152 
00153 
00154 /* static void allegro_gl_screen_acquire(struct BITMAP *bmp) */
00160 static void allegro_gl_screen_acquire(struct BITMAP *bmp) {}
00161 
00162 
00163 
00164 /* static void allegro_gl_screen_release(struct BITMAP *bmp) */
00170 static void allegro_gl_screen_release(struct BITMAP *bmp) {}
00171 
00172 
00173 
00174 static int allegro_gl_screen_getpixel(struct BITMAP *bmp, int x, int y)
00175 {
00176     GLubyte pixel[3];
00177     AGL_LOG(2, "glvtable.c:allegro_gl_screen_getpixel\n");
00178     if (bmp->clip && (x < bmp->cl || x >= bmp->cr
00179                                               || y < bmp->ct || y >= bmp->cb)) {
00180         return -1;
00181     }
00182     if (is_sub_bitmap(bmp)) {
00183         x += bmp->x_ofs;
00184         y += bmp->y_ofs;
00185     }
00186     glReadPixels(x, bmp->h - y - 1, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, pixel);
00187 
00188     return makecol_depth(bitmap_color_depth(screen),
00189                                                   pixel[0], pixel[1], pixel[2]);
00190 }
00191 
00192 
00193 
00194 static void allegro_gl_screen_putpixel(struct BITMAP *bmp, int x, int y,
00195                                                                       int color)
00196 {
00197     GLubyte r, g, b, a;
00198     AGL_LOG(2, "glvtable.c:allegro_gl_screen_putpixel\n");
00199     split_color(color, &r, &g, &b, &a, bitmap_color_depth(bmp));
00200     if (bmp->clip && (x < bmp->cl || x >= bmp->cr
00201                                               || y < bmp->ct || y >= bmp->cb)) {
00202         return;
00203     }
00204 
00205     if (is_sub_bitmap(bmp)) {
00206         x += bmp->x_ofs;
00207         y += bmp->y_ofs;
00208     }
00209 
00210     glColor4ub(r, g, b, a);
00211     glBegin(GL_POINTS);
00212         glVertex2f(x, y);
00213     glEnd();
00214 }
00215 
00216 
00217 
00218 static void allegro_gl_screen_vline(struct BITMAP *bmp, int x, int y1, int y2,
00219                                                                       int color)
00220 {
00221     GLubyte r, g, b, a;
00222     AGL_LOG(2, "glvtable.c:allegro_gl_screen_vline\n");
00223 
00224     if (y1 > y2) {
00225         int temp = y1;
00226         y1 = y2;
00227         y2 = temp;
00228     }
00229 
00230     if (bmp->clip) {
00231         if ((x < bmp->cl) || (x >= bmp->cr)) {
00232             return;
00233         }
00234         if ((y1 >= bmp->cb) || (y2 < bmp->ct)) {
00235             return;
00236         }
00237         if (y1 < bmp->ct) {
00238             y1 = bmp->ct;
00239         }
00240         if (y2 >= bmp->cb) {
00241             y2 = bmp->cb - 1;
00242         }
00243     }
00244     
00245     if (is_sub_bitmap(bmp)) {
00246         x += bmp->x_ofs;
00247         y1 += bmp->y_ofs;
00248         y2 += bmp->y_ofs;
00249     }
00250 
00251     split_color(color, &r, &g, &b, &a, bitmap_color_depth(bmp));
00252 
00253     glColor4ub(r, g, b, a);
00254     glBegin(GL_LINES);
00255         glVertex2f(x, y1);
00256         glVertex2f(x, y2 + 0.325 * 3);
00257     glEnd();
00258 
00259     return;
00260 }
00261 
00262 
00263 
00264 static void allegro_gl_screen_hline(struct BITMAP *bmp, int x1, int y, int x2,
00265                                                                       int color)
00266 {
00267     GLubyte r, g, b, a;
00268     AGL_LOG(2, "glvtable.c:allegro_gl_hline\n");
00269     
00270     if (x1 > x2) {
00271         int temp = x1;
00272         x1 = x2;
00273         x2 = temp;
00274     }
00275     if (bmp->clip) {
00276         if ((y < bmp->ct) || (y >= bmp->cb)) {
00277             return;
00278         }
00279         if ((x1 >= bmp->cr) || (x2 < bmp->cl)) {
00280             return;
00281         }
00282         if (x1 < bmp->cl) {
00283             x1 = bmp->cl;
00284         }
00285         if (x2 >= bmp->cr) {
00286             x2 = bmp->cr - 1;
00287         }
00288     }
00289     if (is_sub_bitmap(bmp)) {
00290         x1 += bmp->x_ofs;
00291         x2 += bmp->x_ofs;
00292         y += bmp->y_ofs;
00293     }
00294     
00295     split_color(color, &r, &g, &b, &a, bitmap_color_depth(bmp));
00296     
00297     glColor4ub(r, g, b, a);
00298     glBegin(GL_LINES);
00299         glVertex2f(x1 - 0.325, y);
00300         glVertex2f(x2 + 0.325 * 2, y);
00301     glEnd();
00302 
00303     return;
00304 }
00305 
00306 
00307 
00308 static void allegro_gl_screen_line(struct BITMAP *bmp, int x1, int y1, int x2,
00309                                                               int y2, int color)
00310 {
00311     GLubyte r, g, b, a;
00312     AGL_LOG(2, "glvtable.c:allegro_gl_screen_line\n");
00313 
00314     if (bmp->clip) {
00315         glPushAttrib(GL_SCISSOR_BIT);
00316         glEnable(GL_SCISSOR_TEST);
00317         glScissor(bmp->x_ofs + bmp->cl, bmp->h + bmp->y_ofs - bmp->cb,
00318                                           bmp->cr - bmp->cl, bmp->cb - bmp->ct);
00319     }
00320     if (is_sub_bitmap(bmp)) {
00321         x1 += bmp->x_ofs;
00322         x2 += bmp->x_ofs;
00323         y1 += bmp->y_ofs;
00324         y2 += bmp->y_ofs;
00325     }
00326     
00327     split_color(color, &r, &g, &b, &a, bitmap_color_depth(bmp));
00328 
00329     glColor4ub(r, g, b, a);
00330     glBegin(GL_LINES);
00331         glVertex2f(x1 + 0.1625, y1 + 0.1625);
00332         glVertex2f(x2 + 0.1625, y2 + 0.1625);
00333     glEnd();
00334 
00335     /* OpenGL skips the endpoint when drawing lines */
00336     glBegin(GL_POINTS);
00337         glVertex2f(x2 + 0.1625, y2 + 0.1625);
00338     glEnd();
00339     
00340     if (bmp->clip) {
00341         glPopAttrib();
00342     }
00343 
00344     return;
00345 }
00346 
00347 
00348 #define SET_TEX_COORDS(x, y)  \
00349     do {                      \
00350         if (__agl_drawing_pattern_tex) {  \
00351             glTexCoord2f (                \
00352                 (x - _drawing_x_anchor) / (float)__agl_drawing_pattern_bmp->w,\
00353                 (y - _drawing_y_anchor) / (float)__agl_drawing_pattern_bmp->h \
00354             );                                                                \
00355         }                                                                     \
00356     } while(0)
00357 
00358 
00359 void allegro_gl_screen_rectfill(struct BITMAP *bmp, int x1, int y1,
00360                                                       int x2, int y2, int color)
00361 {
00362     GLubyte r, g, b, a;
00363     GLfloat old_col[4];
00364     AGL_LOG(2, "glvtable.c:allegro_gl_screen_rectfill\n");
00365     
00366     if (x1 > x2) {
00367         int temp = x1;
00368         x1 = x2;
00369         x2 = temp;
00370     }
00371     
00372     if (y1 > y2) {
00373         int temp = y1;
00374         y1 = y2;
00375         y2 = temp;
00376     }
00377     
00378     if (bmp->clip) {
00379         if ((x1 > bmp->cr) || (x2 < bmp->cl)) {
00380             return;
00381         }
00382         if (x1 < bmp->cl) {
00383             x1 = bmp->cl;
00384         }
00385         if (x2 > bmp->cr) {
00386             x2 = bmp->cr;
00387         }
00388         if ((y1 > bmp->cb) || (y2 < bmp->ct)) {
00389             return;
00390         }
00391         if (y1 < bmp->ct) {
00392             y1 = bmp->ct;
00393         }
00394         if (y2 > bmp->cb) {
00395             y2 = bmp->cb;
00396         }
00397     }
00398     if (is_sub_bitmap(bmp)) {
00399         x1 += bmp->x_ofs;
00400         x2 += bmp->x_ofs;
00401         y1 += bmp->y_ofs;
00402         y2 += bmp->y_ofs;
00403     }
00404     
00405     glGetFloatv(GL_CURRENT_COLOR, old_col);
00406     split_color(color, &r, &g, &b, &a, bitmap_color_depth(bmp));
00407     glColor4ub(r, g, b, a);
00408 
00409     glBegin(GL_QUADS);
00410         SET_TEX_COORDS(x1, y1);
00411         glVertex2f(x1, y1);
00412         SET_TEX_COORDS(x2, y1);
00413         glVertex2f(x2, y1);
00414         SET_TEX_COORDS(x2, y2);
00415         glVertex2f(x2, y2);
00416         SET_TEX_COORDS(x1, y2);
00417         glVertex2f(x1, y2);
00418     glEnd();
00419 
00420     glColor4fv(old_col);
00421 
00422     return;
00423 }
00424 
00425 
00426 
00427 static void allegro_gl_screen_triangle(struct BITMAP *bmp, int x1, int y1,
00428                                       int x2, int y2, int x3, int y3, int color)
00429 {
00430     GLubyte r, g, b, a;
00431     AGL_LOG(2, "glvtable.c:allegro_gl_screen_triangle\n");
00432     
00433     split_color(color, &r, &g, &b, &a, bitmap_color_depth(bmp));
00434     
00435     if (bmp->clip) {
00436         glPushAttrib(GL_SCISSOR_BIT);
00437         glEnable(GL_SCISSOR_TEST);
00438         glScissor(bmp->x_ofs + bmp->cl, bmp->h + bmp->y_ofs - bmp->cb,
00439                                          bmp->cr - bmp->cl, bmp->cb - bmp->ct);
00440     }
00441     if (is_sub_bitmap(bmp)) {
00442         x1 += bmp->x_ofs;
00443         y1 += bmp->y_ofs;
00444         x2 += bmp->x_ofs;
00445         y2 += bmp->y_ofs;
00446         x3 += bmp->x_ofs;
00447         y3 += bmp->y_ofs;
00448     }
00449     
00450     glColor4ub(r, g, b, a);
00451     glBegin(GL_TRIANGLES);
00452         SET_TEX_COORDS(x1, y1);
00453         glVertex2f(x1, y1);
00454         SET_TEX_COORDS(x2, y2);
00455         glVertex2f(x2, y2);
00456         SET_TEX_COORDS(x3, y3);
00457         glVertex2f(x3, y3);
00458     glEnd();
00459 
00460     if (bmp->clip) {
00461         glPopAttrib();
00462     }
00463 }
00464 
00465 
00466 
00467 #define BITMAP_BLIT_CLIP(source, dest, source_x, source_y, dest_x, dest_y, \
00468                                                           width, height) { \
00469     if (dest->clip) {                                                      \
00470         if ((dest_x >= dest->cr) || (dest_y >= dest->cb)                   \
00471          || (dest_x + width < dest->cl) || (dest_y + height < dest->ct)) { \
00472             width = 0;                                                     \
00473         }                                                                  \
00474         if (dest_x < dest->cl) {                                           \
00475             width += dest_x - dest->cl;                                    \
00476             source_x -= dest_x - dest->cl;                                 \
00477             dest_x = dest->cl;                                             \
00478         }                                                                  \
00479         if (dest_y < dest->ct) {                                           \
00480             height += dest_y - dest->ct;                                   \
00481             source_y -= dest_y - dest->ct;                                 \
00482             dest_y = dest->ct;                                             \
00483         }                                                                  \
00484         if (dest_x + width > dest->cr) {                                   \
00485             width = dest->cr - dest_x;                                     \
00486         }                                                                  \
00487         if (dest_y + height > dest->cb) {                                  \
00488             height = dest->cb - dest_y;                                    \
00489         }                                                                  \
00490     }                                                                      \
00491     if (source->clip) {                                                    \
00492         if ((source_x >= source->cr) || (source_y >= source->cb)           \
00493          || (source_x + width < source->cl)                                \
00494          || (source_y + height < source->ct)) {                            \
00495             width = 0;                                                     \
00496         }                                                                  \
00497         if (source_x < source->cl) {                                       \
00498             width += source_x - source->cl;                                \
00499             dest_x -= source_x - source->cl;                               \
00500             source_x = source->cl;                                         \
00501         }                                                                  \
00502         if (source_y < source->ct) {                                       \
00503             height += source_y - source->ct;                               \
00504             dest_y -= source_y - source->ct;                               \
00505             source_y = source->ct;                                         \
00506         }                                                                  \
00507         if (source_x + width > source->cr) {                               \
00508             width = source->cr - source_x;                                 \
00509         }                                                                  \
00510         if (source_y + height > source->cb) {                              \
00511             height = source->cb - source_y;                                \
00512         }                                                                  \
00513     }                                                                      \
00514 }
00515     
00516 
00517 
00518 
00519 static void allegro_gl_screen_blit_from_memory(
00520     struct BITMAP *source, struct BITMAP *dest,
00521     int source_x, int source_y, int dest_x, int dest_y, int width, int height)
00522 {
00523     GLfloat saved_zoom_x, saved_zoom_y;
00524     GLint saved_row_length;
00525     BITMAP *temp = NULL;
00526     void *data;
00527     AGL_LOG(2, "glvtable.c:allegro_gl_screen_blit_from_memory\n");
00528 
00529     BITMAP_BLIT_CLIP(source, dest, source_x, source_y, dest_x, dest_y,
00530                                                                  width, height);
00531 
00532     if (width <= 0 || height <= 0) {
00533         return;
00534     }
00535     
00536 
00537     if (is_sub_bitmap(dest)) {
00538         dest_x += dest->x_ofs;
00539         dest_y += dest->y_ofs;
00540     }
00541 
00542     /* Note: We don't need to offset the source bitmap coordinates
00543      * because we use source->line[] directly, which is already offsetted for
00544      * us.
00545      */
00546     data = source->line[source_y]
00547          + source_x * BYTES_PER_PIXEL(bitmap_color_depth(source));
00548 
00549     /* If packed pixels (or GL 1.2) isn't supported, then we need to convert
00550      * the bitmap into something GL can understand - 24-bpp should do it.
00551      */
00552     if (!allegro_gl_extensions_GL.EXT_packed_pixels
00553                                            && bitmap_color_depth(source) < 24) {
00554         temp = create_bitmap_ex(24, width, height);
00555 
00556         if (temp) {
00557             blit(source, temp, source_x, source_y, 0, 0, width, height);
00558             source_x = 0;
00559             source_y = 0;
00560             data = temp->line[0];
00561         }
00562         else {
00563             /* XXX <rohannessian> Report error? */
00564             return;
00565         }
00566         source = temp;
00567     }
00568         
00569 
00570     /* Save state */
00571     glGetFloatv(GL_ZOOM_X, &saved_zoom_x);
00572     glGetFloatv(GL_ZOOM_Y, &saved_zoom_y);
00573     glGetIntegerv(GL_UNPACK_ROW_LENGTH, &saved_row_length);
00574 
00575     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
00576 
00577     glRasterPos2i(dest_x, dest_y);
00578 
00579     /* XXX <rohannessian> I wonder if it would be faster to use glDrawPixels()
00580      * one line at a time instead of playing with the Zoom factor.
00581      */
00582     glPixelZoom (1.0, -1.0);
00583     glPixelStorei(GL_UNPACK_ROW_LENGTH,
00584                     (source->line[1] - source->line[0])
00585                     / BYTES_PER_PIXEL(source->vtable->color_depth));
00586 
00587     glDrawPixels(width, height, __allegro_gl_get_bitmap_color_format(source, 0),
00588         __allegro_gl_get_bitmap_type(source, 0), data);
00589 
00590     /* Restore state */
00591     glPixelZoom(saved_zoom_x, saved_zoom_y);
00592     glPixelStorei(GL_UNPACK_ROW_LENGTH, saved_row_length);
00593 
00594     if (temp) {
00595         destroy_bitmap(temp);
00596     }
00597     return;
00598 }
00599 
00600 
00601 
00602 static void allegro_gl_screen_blit_to_memory(
00603       struct BITMAP *source, struct BITMAP *dest,
00604       int source_x, int source_y, int dest_x, int dest_y, int width, int height)
00605 {
00606     GLint saved_row_length;
00607     GLint saved_alignment;
00608     GLint saved_pack_invert;
00609 
00610     BITMAP *bmp = NULL;
00611 
00612     AGL_LOG(2, "glvtable.c:allegro_gl_screen_blit_to_memory\n");
00613 
00614     BITMAP_BLIT_CLIP(source, dest, source_x, source_y, dest_x, dest_y,
00615                                                                  width, height);
00616     
00617     if (is_sub_bitmap(source)) {
00618         source_x += source->x_ofs;
00619         source_y += source->y_ofs;
00620     }
00621     if (is_sub_bitmap(dest)) {
00622         dest_x += dest->x_ofs;
00623         dest_y += dest->y_ofs;
00624     }
00625 
00626     if (width <= 0 || height <= 0) {
00627         return;
00628     }
00629     
00630     /* Note that glPixelZoom doesn't affect reads -- so we have to do a flip.
00631      * We can do this by reading into a temporary bitmap then flipping that to
00632      * the destination, -OR- use the GL_MESA_pack_invert extension to do it
00633      * for us.
00634      *
00635      * If GL_EXT_packed_pixels isn't supported, then we can't use
00636      * MESA_pack_invert on 16-bpp bitmaps or less.
00637      */
00638     
00639     if ( !allegro_gl_extensions_GL.MESA_pack_invert
00640      || (!allegro_gl_extensions_GL.EXT_packed_pixels
00641        && bitmap_color_depth(dest) < 24)) {
00642     
00643         /* XXX <rohannessian> Bitmap format should be the same as the source
00644          * dest bitmap!
00645          */
00646         if ((!allegro_gl_extensions_GL.EXT_packed_pixels
00647            && bitmap_color_depth(dest) < 24)) {
00648             bmp = create_bitmap_ex(24, width, height);
00649         }
00650         else {
00651             bmp = create_bitmap_ex(bitmap_color_depth(dest), width, height);
00652         }
00653         if (!bmp)
00654             return;
00655     }
00656 
00657     glGetIntegerv(GL_PACK_ROW_LENGTH, &saved_row_length);
00658     glGetIntegerv(GL_PACK_ALIGNMENT,  &saved_alignment);
00659     glPixelStorei(GL_PACK_ROW_LENGTH, 0);
00660     glPixelStorei(GL_PACK_ALIGNMENT,  1);
00661 
00662     if (!allegro_gl_extensions_GL.MESA_pack_invert) {
00663 
00664         glReadPixels(source_x, source->h - source_y - height, width, height,
00665             __allegro_gl_get_bitmap_color_format(bmp, 0),
00666             __allegro_gl_get_bitmap_type(bmp, 0), bmp->dat);
00667     }
00668     else {
00669         glGetIntegerv(GL_PACK_INVERT_MESA, &saved_pack_invert);
00670         glPixelStorei(GL_PACK_INVERT_MESA, TRUE);
00671         glPixelStorei(GL_PACK_ROW_LENGTH,
00672                       (dest->line[1] - dest->line[0])
00673                        / BYTES_PER_PIXEL(dest->vtable->color_depth));
00674         
00675         glReadPixels(source_x, source->h - source_y - height, width, height,
00676             __allegro_gl_get_bitmap_color_format(dest, 0),
00677             __allegro_gl_get_bitmap_type(dest, 0), dest->line[0]);
00678         
00679         glPixelStorei(GL_PACK_INVERT_MESA, saved_pack_invert);
00680     }
00681 
00682     glPixelStorei(GL_PACK_ROW_LENGTH, saved_row_length);
00683     glPixelStorei(GL_PACK_ALIGNMENT,  saved_alignment);
00684 
00685     /* Flip image if needed (glPixelZoom doesn't affect reads) */
00686     if (bmp) {
00687         
00688         int y, dy;
00689         
00690         for (y = 0, dy = dest_y + height - 1; y < height; y++, dy--) {
00691             blit(bmp, dest, 0, y, dest_x, dy, width, 1);
00692         }
00693 
00694         destroy_bitmap(bmp);
00695     }
00696 
00697     return;
00698 }
00699 
00700 
00701 
00702 
00703 void allegro_gl_screen_blit_to_self (
00704      struct BITMAP *source, struct BITMAP *dest,
00705      int source_x, int source_y, int dest_x, int dest_y, int width, int height)
00706 {
00707     AGL_LOG(2, "glvtable.c:allegro_gl_screen_blit_to_self\n");
00708 
00709     BITMAP_BLIT_CLIP(source, dest, source_x, source_y, dest_x, dest_y,
00710                                                                  width, height);
00711 
00712     if (is_sub_bitmap(source)) {
00713         source_x += source->x_ofs;
00714         source_y += source->y_ofs;
00715     }
00716     if (is_sub_bitmap(dest)) {
00717         dest_x += dest->x_ofs;
00718         dest_y += dest->y_ofs;
00719     }
00720 
00721     if (width <= 0 || height <= 0) {
00722         return;
00723     }
00724 
00725     /* screen -> screen */
00726     if (is_screen_bitmap(source) && is_screen_bitmap(dest)) {
00727         glRasterPos2i(dest_x, dest_y + height - 1);
00728         glCopyPixels(source_x, SCREEN_H - source_y - height, width, height,
00729                                                                       GL_COLOR);
00730     }
00731     /* video -> screen */
00732     else if (is_screen_bitmap(dest) && is_video_bitmap(source)) {
00733         AGL_VIDEO_BITMAP *vid;
00734         BITMAP *source_parent = source;
00735         GLfloat current_color[4];
00736 
00737         while (source_parent->id & BMP_ID_SUB) {
00738             source_parent = (BITMAP *)source_parent->extra;
00739         }
00740         vid = source_parent->extra;
00741 
00742         glGetFloatv(GL_CURRENT_COLOR, current_color);
00743         glColor4ub(255, 255, 255, 255);
00744 
00745         while (vid) {
00746             int sx, sy;           /* source coordinates */
00747             int dx, dy;           /* destination coordinates */
00748             int w, h;
00749 
00750             if (source_x >= vid->x_ofs + vid->memory_copy->w ||
00751                 source_y >= vid->y_ofs + vid->memory_copy->h ||
00752                 vid->x_ofs >= source_x + width ||
00753                 vid->y_ofs >= source_y + height) {
00754                 vid = vid->next;
00755                 continue;
00756             }
00757 
00758             sx = MAX(vid->x_ofs, source_x) - vid->x_ofs;
00759             w = MIN(vid->x_ofs + vid->memory_copy->w, source_x + width)
00760               - vid->x_ofs - sx;
00761             sy = MAX(vid->y_ofs, source_y) - vid->y_ofs;
00762             h = MIN(vid->y_ofs + vid->memory_copy->h, source_y + height)
00763               - vid->y_ofs - sy;
00764     
00765             dx = dest_x + vid->x_ofs + sx - source_x;
00766             dy = dest_y + vid->y_ofs + sy - source_y;
00767 
00768             glEnable(vid->target);
00769             glBindTexture(vid->target, vid->tex);
00770 
00771             if (vid->target == GL_TEXTURE_2D) {
00772                 float tx = sx / (float)vid->memory_copy->w;
00773                 float ty = sy / (float)vid->memory_copy->h;
00774                 float tw = w / (float)vid->memory_copy->w;
00775                 float th = h / (float)vid->memory_copy->h;
00776 
00777                 glBegin(GL_QUADS);
00778                     glTexCoord2f(tx, ty);
00779                     glVertex2f(dx, dy);
00780                     glTexCoord2f(tx, ty + th);
00781                     glVertex2f(dx, dy + h);
00782                     glTexCoord2f(tx + tw, ty + th);
00783                     glVertex2f(dx + w, dy + h);
00784                     glTexCoord2f(tx + tw, ty);
00785                     glVertex2f(dx + w, dy);
00786                 glEnd();
00787             }
00788             else {
00789                 glBegin(GL_QUADS);
00790                     glTexCoord2i(sx, sy);
00791                     glVertex2f(dx, dy);
00792                     glTexCoord2i(sx, sy + h);
00793                     glVertex2f(dx, dy + h);
00794                     glTexCoord2i(sx + w, sy + h);
00795                     glVertex2f(dx + w, dy + h);
00796                     glTexCoord2i(sx + w, sy);
00797                     glVertex2f(dx + w, dy);
00798                 glEnd();
00799             }
00800 
00801             glBindTexture(vid->target, 0);
00802             glDisable(vid->target);
00803 
00804             vid = vid->next;
00805         }
00806         
00807         glColor4fv(current_color);
00808     }
00809     /* screen -> video */
00810     else if (is_screen_bitmap(source) && is_video_bitmap(dest)) {
00811     
00812         AGL_VIDEO_BITMAP *vid;
00813         BITMAP *source_parent = source;
00814 
00815         while (source_parent->id & BMP_ID_SUB) {
00816             source_parent = (BITMAP *)source_parent->extra;
00817         }
00818 
00819         vid = dest->extra;
00820 
00821         while (vid) {
00822             int sx, sy;           /* source coordinates */
00823             int dx, dy;           /* destination coordinates */
00824             int w, h;
00825 
00826             if (dest_x >= vid->x_ofs + vid->memory_copy->w ||
00827                 dest_y >= vid->y_ofs + vid->memory_copy->h ||
00828                 vid->x_ofs >= dest_x + width ||
00829                 vid->y_ofs >= dest_y + height) {
00830                 vid = vid->next;
00831                 continue;
00832             }
00833 
00834             dx = MAX(vid->x_ofs, dest_x) - vid->x_ofs;
00835             w = MIN(vid->x_ofs + vid->memory_copy->w, dest_x + width)
00836               - vid->x_ofs - dx;
00837             dy = MAX(vid->y_ofs, dest_y) - vid->y_ofs;
00838             h = MIN(vid->y_ofs + vid->memory_copy->h, dest_y + height)
00839               - vid->y_ofs - dy;
00840     
00841             sx = source_x + vid->x_ofs + dx - dest_x;
00842             sy = source_y + vid->y_ofs + dy - dest_y;
00843 
00844             /* We cannot use glCopyTexSubImage2D() here because it will flip the image. */
00845             allegro_gl_screen_blit_to_memory(source, vid->memory_copy,
00846                                              sx, sy, dx, dy, w, h);
00847 
00848             allegro_gl_video_blit_from_memory(vid->memory_copy, dest, 0, 0,
00849                 vid->x_ofs, vid->y_ofs, vid->memory_copy->w, vid->memory_copy->h);
00850 
00851             vid = vid->next;
00852         }
00853     }
00854     else if (is_video_bitmap(source) && is_video_bitmap(dest)) {
00855         allegro_gl_video_blit_to_self(source, dest, source_x, source_y,
00856                                       dest_x, dest_y, width, height);
00857     }
00858 }
00859 
00860 
00861 
00862 void allegro_gl_upload_and_display_texture(struct BITMAP *source,
00863      int source_x, int source_y, int dest_x, int dest_y, int width, int height,
00864      int flip_dir, GLint format, GLint type)
00865 {
00866     float tx, ty;
00867     GLint saved_row_length;
00868     int bytes_per_pixel = BYTES_PER_PIXEL(bitmap_color_depth(source));
00869     int i, j;
00870     
00871     glEnable(GL_ALPHA_TEST);
00872     glAlphaFunc(GL_GREATER, 0.0f);
00873 
00874     glEnable(GL_TEXTURE_2D);
00875     glBindTexture(GL_TEXTURE_2D, __allegro_gl_pool_texture);
00876 
00877     glGetIntegerv(GL_UNPACK_ROW_LENGTH, &saved_row_length);
00878     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
00879 
00880     glPixelStorei(GL_UNPACK_ROW_LENGTH,
00881                          (source->line[1] - source->line[0]) / bytes_per_pixel);
00882     
00883     for (i = 0; i <= abs(width) / 256; i++) {
00884         for (j = 0; j <= abs(height) / 256; j++) {
00885 
00886             void *data = source->line[source_y + j * 256]
00887                                        + (source_x + i * 256) * bytes_per_pixel;
00888             int w = abs(width)  - i * 256;
00889             int h = abs(height) - j * 256;
00890             int dx = dest_x + i * 256;
00891             int dy = dest_y + j * 256;
00892 
00893             w = (w & -256) ? 256 : w;
00894             h = (h & -256) ? 256 : h;
00895 
00896             glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, format, type, data);
00897 
00898             tx = (float)w / 256.;
00899             ty = (float)h / 256.;
00900 
00901             if (flip_dir & AGL_H_FLIP) {
00902                 dx = 2*dest_x + width - dx;
00903                 w = -w;
00904             }
00905 
00906             if (flip_dir & AGL_V_FLIP) {
00907                 dy = 2*dest_y + height - dy;
00908                 h = -h;
00909             }
00910 
00911             if (width < 0)  w = -w;
00912             if (height < 0) h = -h;
00913 
00914             glBegin(GL_QUADS);
00915                 glTexCoord2f(0., 0.);
00916                 glVertex2i(dx, dy);
00917                 glTexCoord2f(0., ty);
00918                 glVertex2i(dx, dy + h);
00919                 glTexCoord2f(tx, ty);
00920                 glVertex2i(dx + w, dy + h);
00921                 glTexCoord2f(tx, 0.);
00922                 glVertex2i(dx + w, dy);
00923             glEnd();
00924         }
00925     }
00926 
00927     /* Restore state */
00928     glPixelStorei(GL_UNPACK_ROW_LENGTH, saved_row_length);
00929     glBindTexture(GL_TEXTURE_2D, 0);
00930     glDisable(GL_TEXTURE_2D);
00931     glDisable(GL_ALPHA_TEST);
00932 
00933     return;
00934 }
00935 
00936 
00937 
00938 static void do_screen_masked_blit_standard(GLint format, GLint type, struct BITMAP *temp, int source_x, int source_y, int dest_x, int dest_y, int width, int height, int flip_dir, int blit_type)
00939 {
00940     glPushAttrib(GL_COLOR_BUFFER_BIT | GL_ENABLE_BIT);
00941 
00942     if (blit_type & AGL_NO_ROTATION) {
00943         GLint saved_row_length;
00944         float dx = dest_x, dy = dest_y;
00945         GLfloat zoom_x, zoom_y, old_zoom_x, old_zoom_y;
00946 
00947         glEnable(GL_ALPHA_TEST);
00948         glAlphaFunc(GL_GREATER, 0.0f);
00949 
00950         glGetIntegerv(GL_UNPACK_ROW_LENGTH, &saved_row_length);
00951         glGetFloatv(GL_ZOOM_X, &old_zoom_x);
00952         glGetFloatv(GL_ZOOM_Y, &old_zoom_y);
00953 
00954         if (flip_dir & AGL_H_FLIP) {
00955             zoom_x = -1.0f;   
00956             /* Without the -0.5 below, we get an invalid position,
00957              * and the operation is ignored by OpenGL. */
00958             dx += abs(width) - 0.5;
00959         }
00960         else {
00961             zoom_x = (float) width / abs(width);
00962         }
00963 
00964         if (flip_dir & AGL_V_FLIP) {
00965             zoom_y = 1.0f;
00966             dy += abs(height) - 0.5;
00967         }
00968         else {
00969             zoom_y = -1.0f * width / abs(width);
00970         }
00971 
00972         glRasterPos2f(dx, dy);
00973         glPixelZoom(zoom_x, zoom_y);
00974         glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
00975         glPixelStorei(GL_UNPACK_ROW_LENGTH,
00976                 (temp->line[1] - temp->line[0])
00977                 / BYTES_PER_PIXEL(bitmap_color_depth(temp)));
00978 
00979         glDrawPixels(abs(width), abs(height), format, type, temp->line[0]);
00980         
00981         glPixelStorei(GL_UNPACK_ROW_LENGTH, saved_row_length);
00982         glPixelZoom(old_zoom_x, old_zoom_y);
00983     }
00984     else {
00985         allegro_gl_upload_and_display_texture(temp, 0, 0, dest_x, dest_y, width, height,
00986                                    flip_dir, format, type);
00987     }
00988 
00989     glPopAttrib();
00990 }
00991 
00992 
00993 
00994 static void screen_masked_blit_standard(struct BITMAP *source,
00995     int source_x, int source_y, int dest_x, int dest_y, int width, int height,
00996     int flip_dir, int blit_type)
00997 {
00998     BITMAP *temp = NULL;
00999 
01000     GLint format, type;
01001     
01002     format = __allegro_gl_get_bitmap_color_format(source, AGL_TEXTURE_MASKED);
01003     type   = __allegro_gl_get_bitmap_type(source, AGL_TEXTURE_MASKED);
01004 
01005     temp = __allegro_gl_munge_bitmap(AGL_TEXTURE_MASKED, source,
01006                             source_x, source_y, abs(width), abs(height),
01007                             &type, &format);
01008 
01009     if (temp) {
01010         source = temp;
01011     }
01012 
01013     do_screen_masked_blit_standard(format, type, source, source_x, source_y,
01014         dest_x, dest_y, width, height, flip_dir, blit_type);
01015 
01016     if (temp) {
01017         destroy_bitmap(temp);
01018     }
01019 
01020     return;
01021 }
01022 
01023 
01024 
01025 static void __allegro_gl_init_nv_register_combiners(BITMAP *bmp)
01026 {
01027     GLfloat mask_color[4];
01028     int depth = bitmap_color_depth(bmp);
01029     int color = bitmap_mask_color(bmp);
01030 
01031     mask_color[0] = getr_depth(depth, color) / 255.;
01032     mask_color[1] = getg_depth(depth, color) / 255.;
01033     mask_color[2] = getb_depth(depth, color) / 255.;
01034     mask_color[3] = 0.;
01035 
01036     glCombinerParameterfvNV(GL_CONSTANT_COLOR0_NV, mask_color);
01037     glCombinerParameteriNV(GL_NUM_GENERAL_COMBINERS_NV, 2);
01038     glEnable(GL_REGISTER_COMBINERS_NV);
01039 
01040     glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_A_NV,
01041         GL_TEXTURE0_ARB, GL_SIGNED_IDENTITY_NV, GL_RGB);
01042     glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_B_NV,
01043         GL_ZERO, GL_UNSIGNED_INVERT_NV, GL_RGB);
01044     glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_C_NV,
01045         GL_CONSTANT_COLOR0_NV, GL_SIGNED_IDENTITY_NV, GL_RGB);
01046     glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_D_NV,
01047         GL_ZERO, GL_EXPAND_NORMAL_NV, GL_RGB);
01048     glCombinerOutputNV(GL_COMBINER0_NV, GL_RGB, GL_DISCARD_NV,
01049         GL_DISCARD_NV, GL_SPARE0_NV, GL_NONE, GL_NONE,
01050         GL_FALSE, GL_FALSE, GL_FALSE);
01051 
01052     glCombinerInputNV(GL_COMBINER1_NV, GL_RGB, GL_VARIABLE_A_NV,
01053         GL_SPARE0_NV, GL_SIGNED_IDENTITY_NV, GL_RGB);
01054     glCombinerInputNV(GL_COMBINER1_NV, GL_RGB, GL_VARIABLE_B_NV,
01055         GL_SPARE0_NV, GL_SIGNED_IDENTITY_NV, GL_RGB);
01056     glCombinerOutputNV(GL_COMBINER1_NV, GL_RGB, GL_SPARE1_NV,
01057         GL_DISCARD_NV, GL_DISCARD_NV, GL_NONE, GL_NONE,
01058         GL_TRUE, GL_FALSE, GL_FALSE);
01059 
01060     glFinalCombinerInputNV(GL_VARIABLE_A_NV, GL_TEXTURE0_ARB,
01061         GL_UNSIGNED_IDENTITY_NV, GL_RGB);
01062     glFinalCombinerInputNV(GL_VARIABLE_B_NV, GL_ZERO,
01063         GL_UNSIGNED_INVERT_NV, GL_RGB);
01064     glFinalCombinerInputNV(GL_VARIABLE_C_NV, GL_ZERO,
01065         GL_UNSIGNED_IDENTITY_NV, GL_RGB);
01066     glFinalCombinerInputNV(GL_VARIABLE_D_NV, GL_ZERO,
01067         GL_UNSIGNED_IDENTITY_NV, GL_RGB);
01068     glFinalCombinerInputNV(GL_VARIABLE_G_NV, GL_SPARE1_NV,
01069         GL_UNSIGNED_IDENTITY_NV, GL_BLUE);
01070 
01071     return;
01072 }
01073 
01074 
01075 
01076 static void screen_masked_blit_nv_register(struct BITMAP *source,
01077     int source_x, int source_y, int dest_x, int dest_y, int width, int height,
01078     int flip_dir, int blit_type)
01079 {
01080     BITMAP *temp = NULL;
01081     GLint type   = __allegro_gl_get_bitmap_type(source, 0);
01082     GLint format = __allegro_gl_get_bitmap_color_format(source, 0);
01083 
01084     if (type == -1) {
01085         temp = create_bitmap_ex(24, width, height);
01086         if (!temp) {
01087             return;
01088         }
01089         blit(source, temp, source_x, source_y, 0, 0, width, height);
01090         source = temp;
01091         source_x = 0;
01092         source_y = 0;
01093 
01094         type   = __allegro_gl_get_bitmap_type(source, 0);
01095         format = __allegro_gl_get_bitmap_color_format(source, 0);
01096     }
01097 
01098     glPushAttrib(GL_TEXTURE_BIT | GL_COLOR_BUFFER_BIT | GL_ENABLE_BIT);
01099     __allegro_gl_init_nv_register_combiners(source);
01100 
01101     allegro_gl_upload_and_display_texture(source, source_x, source_y, dest_x, dest_y,
01102                                width, height, flip_dir, format, type);
01103 
01104     glPopAttrib();
01105 
01106     if (temp) {
01107         destroy_bitmap(temp);
01108     }
01109     return;
01110 }
01111 
01112 
01113 
01114 static void __allegro_gl_init_combine_textures(BITMAP *bmp)
01115 {
01116     GLubyte mask_color[4];
01117 
01118     split_color(bitmap_mask_color(bmp), &mask_color[0], &mask_color[1],
01119         &mask_color[2], &mask_color[3], bitmap_color_depth(bmp));
01120     glColor4ubv(mask_color);
01121 
01122     glActiveTexture(GL_TEXTURE0);
01123     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
01124     glEnable(GL_TEXTURE_2D);
01125     glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_ADD_SIGNED_ARB);
01126     glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
01127     glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PRIMARY_COLOR);
01128     glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_ONE_MINUS_SRC_COLOR);
01129 
01130     /* Dot the result of the subtract with itself. Store it in the alpha 
01131      * component. The alpha should then be 0 if the color fragment was equal to 
01132      * the mask color, or >0 otherwise.
01133      */
01134     glActiveTexture(GL_TEXTURE1);
01135     glEnable(GL_TEXTURE_2D);
01136     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
01137     glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_DOT3_RGBA_ARB);
01138     glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS_ARB);
01139     glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB);
01140 
01141     /* Put the original RGB value in its place */
01142 
01143     glActiveTexture(GL_TEXTURE2);
01144     glEnable(GL_TEXTURE_2D);
01145     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
01146     glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE);
01147     glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
01148     glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
01149     glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PREVIOUS_ARB);
01150 
01151     glActiveTexture(GL_TEXTURE0);
01152 
01153     return;
01154 }
01155 
01156 
01157 
01158 static void screen_masked_blit_combine_tex(struct BITMAP *source,
01159     int source_x, int source_y, int dest_x, int dest_y, int width, int height,
01160     int flip_dir, int blit_type)
01161 {
01162     float tx, ty;
01163     BITMAP *temp = NULL;
01164     GLint saved_row_length;
01165     GLint type   = __allegro_gl_get_bitmap_type(source, 0);
01166     GLint format = __allegro_gl_get_bitmap_color_format(source, 0);
01167     int bytes_per_pixel;
01168     int i, j;
01169     GLfloat current_color[4];
01170 
01171     if (type == -1) {
01172         temp = create_bitmap_ex(24, width, height);
01173         if (!temp)
01174             return;
01175         blit(source, temp, source_x, source_y, 0, 0, width, height);
01176         source = temp;
01177         source_x = 0;
01178         source_y = 0;
01179 
01180         type   = __allegro_gl_get_bitmap_type(source, 0);
01181         format = __allegro_gl_get_bitmap_color_format(source, 0);
01182     }
01183 
01184     glEnable(GL_TEXTURE_2D);
01185     glBindTexture(GL_TEXTURE_2D, __allegro_gl_pool_texture);
01186     
01187     glPushAttrib(GL_TEXTURE_BIT | GL_COLOR_BUFFER_BIT | GL_ENABLE_BIT);
01188     glGetFloatv(GL_CURRENT_COLOR, current_color);
01189     __allegro_gl_init_combine_textures(source);
01190     
01191     glActiveTexture(GL_TEXTURE0);
01192     glBindTexture(GL_TEXTURE_2D, __allegro_gl_pool_texture);
01193     glActiveTexture(GL_TEXTURE1);
01194     glBindTexture(GL_TEXTURE_2D, __allegro_gl_pool_texture);
01195     glActiveTexture(GL_TEXTURE2);
01196     glBindTexture(GL_TEXTURE_2D, __allegro_gl_pool_texture);
01197     glActiveTexture(GL_TEXTURE0);
01198     
01199     bytes_per_pixel = BYTES_PER_PIXEL(bitmap_color_depth(source));
01200 
01201     glEnable(GL_ALPHA_TEST);
01202     glAlphaFunc(GL_GREATER, 0.0f);
01203 
01204     glGetIntegerv(GL_UNPACK_ROW_LENGTH, &saved_row_length);
01205     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
01206 
01207     glPixelStorei(GL_UNPACK_ROW_LENGTH,
01208                          (source->line[1] - source->line[0]) / bytes_per_pixel);
01209 
01210     for (i = 0; i <= width / 256; i++) {
01211         for (j = 0; j <= height / 256; j++) {
01212                 
01213             void *data = source->line[source_y + j * 256]
01214                                        + (source_x + i * 256) * bytes_per_pixel;
01215             int w = width - i * 256;
01216             int h = height - j * 256;
01217             int dx = dest_x + i * 256;
01218             int dy = dest_y + j * 256;
01219 
01220             w = (w & -256) ? 256 : w;
01221             h = (h & -256) ? 256 : h;
01222 
01223             glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, format, type, data);
01224 
01225             tx = (float)w / 256.;
01226             ty = (float)h / 256.;
01227 
01228             if (flip_dir & AGL_H_FLIP) {
01229                 dx = 2*dest_x + width - dx;
01230                 w = -w;
01231             }
01232 
01233             if (flip_dir & AGL_V_FLIP) {
01234                 dy = 2*dest_y + height - dy;
01235                 h = -h;
01236             }
01237 
01238             glBegin(GL_QUADS);
01239                 glMultiTexCoord2f(GL_TEXTURE0, 0., 0.);
01240                 glMultiTexCoord2f(GL_TEXTURE1, 0., 0.);
01241                 glMultiTexCoord2f(GL_TEXTURE2, 0., 0.);
01242                 glVertex2f(dx, dy);
01243                 glMultiTexCoord2f(GL_TEXTURE0, 0., ty);
01244                 glMultiTexCoord2f(GL_TEXTURE1, 0., ty);
01245                 glMultiTexCoord2f(GL_TEXTURE2, 0., ty);
01246                 glVertex2f(dx, dy + h);
01247                 glMultiTexCoord2f(GL_TEXTURE0, tx, ty);
01248                 glMultiTexCoord2f(GL_TEXTURE1, tx, ty);
01249                 glMultiTexCoord2f(GL_TEXTURE2, tx, ty);
01250                 glVertex2f(dx + w, dy + h);
01251                 glMultiTexCoord2f(GL_TEXTURE0, tx, 0.);
01252                 glMultiTexCoord2f(GL_TEXTURE1, tx, 0.);
01253                 glMultiTexCoord2f(GL_TEXTURE2, tx, 0.);
01254                 glVertex2f(dx + w, dy);
01255             glEnd();
01256         }
01257     }
01258 
01259     /* Restore state */
01260     glPixelStorei(GL_UNPACK_ROW_LENGTH, saved_row_length);
01261     glBindTexture(GL_TEXTURE_2D, 0);
01262     glDisable(GL_TEXTURE_2D);
01263     glPopAttrib();
01264     glColor4fv(current_color);
01265 
01266     if (temp) {
01267         destroy_bitmap(temp);
01268     }
01269 
01270     return;
01271 }
01272 
01273 
01274 
01275 void do_masked_blit_screen(struct BITMAP *source, struct BITMAP *dest,
01276      int source_x, int source_y, int dest_x, int dest_y, int width, int height,
01277      int flip_dir, int blit_type)
01278 {
01279     
01280     /* XXX <rohannessian> We should merge this clip code with the
01281      * BITMAP_BLIT_CLIP macro
01282      */
01283 
01284     /* Clipping of destination bitmap */
01285     if (dest->clip && (blit_type & AGL_NO_ROTATION)) {
01286         if ((dest_x >= dest->cr) || (dest_y >= dest->cb)
01287          || (dest_x + width < dest->cl) || (dest_y + height < dest->ct)) {
01288             return;
01289         }
01290         if (flip_dir & AGL_H_FLIP) {
01291             if (dest_x < dest->cl) {
01292                 width += dest_x - dest->cl;
01293                 dest_x = dest->cl;
01294             }
01295             if (dest_x + width > dest->cr) {
01296                 source_x += dest_x + width - dest->cr;
01297                 width = dest->cr - dest_x;
01298             }
01299         }
01300         else {
01301             if (dest_x < dest->cl) {
01302                 width += dest_x - dest->cl;
01303                 source_x -= dest_x - dest->cl;
01304                 dest_x = dest->cl;
01305             }
01306             if (dest_x + width > dest->cr) {
01307                 width = dest->cr - dest_x;
01308             }
01309         }
01310         if (flip_dir & AGL_V_FLIP) {
01311             if (dest_y < dest->ct) {
01312                 height += dest_y - dest->ct;
01313                 dest_y = dest->ct;
01314             }
01315             if (dest_y + height > dest->cb) {
01316                 source_y += dest_y + height - dest->cb;
01317                 height = dest->cb - dest_y;
01318             }
01319         }
01320         else {
01321             if (dest_y < dest->ct) {
01322                 height += dest_y - dest->ct;
01323                 source_y -= dest_y - dest->ct;
01324                 dest_y = dest->ct;
01325             }
01326             if (dest_y + height > dest->cb) {
01327                 height = dest->cb - dest_y;
01328             }
01329         }
01330     }
01331 
01332     /* Clipping of source bitmap */
01333     if (source->clip && (blit_type & AGL_REGULAR_BMP)) {
01334         if ((source_x >= source->cr) || (source_y >= source->cb)
01335          || (source_x + width < source->cl)
01336          || (source_y + height < source->ct)) {
01337             return;
01338         }
01339         if (source_x < source->cl) {
01340             width += source_x - source->cl;
01341             dest_x -= source_x - source->cl;
01342             source_x = source->cl;
01343         }
01344         if (source_y < source->ct) {
01345             height += source_y - source->ct;
01346             dest_y -= source_y - source->ct;
01347             source_y = source->ct;
01348         }
01349         if (source_x + width > source->cr) {
01350             width = source->cr - source_x;
01351         }
01352         if (source_y + height > source->cb) {
01353             height = source->cb - source_y;
01354         }
01355     }
01356     if (is_sub_bitmap(dest)) {
01357         dest_x += dest->x_ofs;
01358         dest_y += dest->y_ofs;
01359     }
01360     if (width <= 0 || height <= 0)
01361         return;
01362 
01363     /* memory -> screen */
01364     if (!is_video_bitmap(source) && !is_screen_bitmap(source)) {
01365 
01366         __allegro_gl_driver->screen_masked_blit(source, source_x, source_y,
01367                             dest_x, dest_y, width, height, flip_dir, blit_type);
01368     }
01369     /* video -> screen */
01370     else if (is_video_bitmap(source)) {
01371         AGL_VIDEO_BITMAP *vid;
01372         BITMAP *source_parent = source;
01373 
01374         int use_combiners = 0;
01375 
01376         /* Special combiner paths */
01377         if (allegro_gl_extensions_GL.NV_register_combiners
01378          || allegro_gl_info.num_texture_units >= 3) {
01379 
01380             use_combiners = 1;
01381 
01382             glPushAttrib(GL_ENABLE_BIT | GL_TEXTURE_BIT | GL_COLOR_BUFFER_BIT);
01383 
01384             if (allegro_gl_extensions_GL.NV_register_combiners) {
01385                 __allegro_gl_init_nv_register_combiners(source);
01386             }
01387             else {
01388                 __allegro_gl_init_combine_textures(source);
01389             }
01390 
01391             glEnable(GL_ALPHA_TEST);
01392             glAlphaFunc(GL_GREATER, 0.0f);
01393         }
01394 
01395         while (source_parent->id & BMP_ID_SUB) {
01396             source_parent = (BITMAP *)source_parent->extra;
01397         }
01398         vid = source_parent->extra;
01399 
01400         while (vid) {
01401             int sx, sy;           /* source coordinates */
01402             int dx, dy;           /* destination coordinates */
01403             int w, h;
01404 
01405             if (source_x >= vid->x_ofs + vid->memory_copy->w ||
01406                 source_y >= vid->y_ofs + vid->memory_copy->h ||
01407                 vid->x_ofs >= source_x + width ||
01408                 vid->y_ofs >= source_y + height) {
01409                 vid = vid->next;
01410                 continue;
01411             }
01412 
01413             sx = MAX (vid->x_ofs, source_x) - vid->x_ofs;
01414             w = MIN (vid->x_ofs + vid->memory_copy->w, source_x + width)
01415               - vid->x_ofs - sx;
01416             sy = MAX (vid->y_ofs, source_y) - vid->y_ofs;
01417             h = MIN (vid->y_ofs + vid->memory_copy->h, source_y + height)
01418               - vid->y_ofs - sy;
01419 
01420             dx = dest_x + vid->x_ofs + sx - source_x;
01421             dy = dest_y + vid->y_ofs + sy - source_y;
01422 
01423             if (flip_dir & AGL_H_FLIP) {
01424                 dx = 2*dest_x + width - dx;
01425                 w = -w;
01426             }
01427 
01428             if (flip_dir & AGL_V_FLIP) {
01429                 dy = 2*dest_y + height - dy;
01430                 h = -h;
01431             }
01432 
01433             if (use_combiners) {
01434                 if (allegro_gl_extensions_GL.NV_register_combiners) {
01435                     glEnable(vid->target);
01436                     glBindTexture(vid->target, vid->tex);
01437                     glTexParameteri(vid->target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
01438                     glTexParameteri(vid->target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
01439 
01440                     if (vid->target == GL_TEXTURE_2D) {
01441                         float tx = sx / (float)vid->memory_copy->w;
01442                         float ty = sy / (float)vid->memory_copy->h;
01443                         float tw = abs(w) / (float)vid->memory_copy->w;
01444                         float th = abs(h) / (float)vid->memory_copy->h;
01445 
01446                         glBegin(GL_QUADS);
01447                             glTexCoord2f(tx, ty);
01448                             glVertex2f(dx, dy);
01449                             glTexCoord2f(tx, ty + th);
01450                             glVertex2f(dx, dy + h);
01451                             glTexCoord2f(tx + tw, ty + th);
01452                             glVertex2f(dx + w, dy + h);
01453                             glTexCoord2f(tx + tw, ty);
01454                             glVertex2f(dx + w, dy);
01455                         glEnd();
01456                     }
01457                     else {
01458                         glBegin(GL_QUADS);
01459                             glTexCoord2i(sx, sy);
01460                             glVertex2f(dx, dy);
01461                             glTexCoord2i(sx, sy + h);
01462                             glVertex2f(dx, dy + h);
01463                             glTexCoord2i(sx + w, sy + h);
01464                             glVertex2f(dx + w, dy + h);
01465                             glTexCoord2i(sx + w, sy);
01466                             glVertex2f(dx + w, dy);
01467                         glEnd();
01468                     }
01469 
01470                     glBindTexture(vid->target, 0);
01471                     glDisable(vid->target);
01472                 }
01473                 else {
01474                     glEnable(vid->target);
01475                     glActiveTexture(GL_TEXTURE0);
01476                     glBindTexture(vid->target, vid->tex);
01477                     glActiveTexture(GL_TEXTURE1);
01478                     glBindTexture(vid->target, vid->tex);
01479                     glActiveTexture(GL_TEXTURE2);
01480                     glBindTexture(vid->target, vid->tex);
01481                     glActiveTexture(GL_TEXTURE0);
01482                     glTexParameteri(vid->target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
01483                     glTexParameteri(vid->target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
01484 
01485                     if (vid->target == GL_TEXTURE_2D) {
01486                         float tx, ty, tw, th; /* texture coordinates */
01487                         tx = sx / (float)vid->memory_copy->w;
01488                         ty = sy / (float)vid->memory_copy->h;
01489                         tw = abs(w) / (float)vid->memory_copy->w;
01490                         th = abs(h) / (float)vid->memory_copy->h;
01491 
01492                         glBegin(GL_QUADS);
01493                             glMultiTexCoord2f(GL_TEXTURE0, tx, ty);
01494                             glMultiTexCoord2f(GL_TEXTURE1, tx, ty);
01495                             glMultiTexCoord2f(GL_TEXTURE2, tx, ty);
01496                             glVertex2f(dx, dy);
01497                             glMultiTexCoord2f(GL_TEXTURE0, tx, ty + th);
01498                             glMultiTexCoord2f(GL_TEXTURE1, tx, ty + th);
01499                             glMultiTexCoord2f(GL_TEXTURE2, tx, ty + th);
01500                             glVertex2f(dx, dy + h);
01501                             glMultiTexCoord2f(GL_TEXTURE0, tx + tw, ty + th);
01502                             glMultiTexCoord2f(GL_TEXTURE1, tx + tw, ty + th);
01503                             glMultiTexCoord2f(GL_TEXTURE2, tx + tw, ty + th);
01504                             glVertex2f(dx + w, dy + h);
01505                             glMultiTexCoord2f(GL_TEXTURE0, tx + tw, ty);
01506                             glMultiTexCoord2f(GL_TEXTURE1, tx + tw, ty);
01507                             glMultiTexCoord2f(GL_TEXTURE2, tx + tw, ty);
01508                             glVertex2f(dx + w, dy);
01509                         glEnd();
01510                     }
01511                     else {
01512                         glBegin(GL_QUADS);
01513                             glMultiTexCoord2i(GL_TEXTURE0, dx, dy);
01514                             glMultiTexCoord2i(GL_TEXTURE1, dx, dy);
01515                             glMultiTexCoord2i(GL_TEXTURE2, dx, dy);
01516                             glVertex2f(dx, dy);
01517                             glMultiTexCoord2i(GL_TEXTURE0, dx, dy + h);
01518                             glMultiTexCoord2i(GL_TEXTURE1, dx, dy + h);
01519                             glMultiTexCoord2i(GL_TEXTURE2, dx, dy + h);
01520                             glVertex2f(dx, dy + h);
01521                             glMultiTexCoord2i(GL_TEXTURE0, dx + w, dy + h);
01522                             glMultiTexCoord2i(GL_TEXTURE1, dx + w, dy + h);
01523                             glMultiTexCoord2i(GL_TEXTURE2, dx + w, dy + h);
01524                             glVertex2f(dx + w, dy + h);
01525                             glMultiTexCoord2i(GL_TEXTURE0, dx + w, dy);
01526                             glMultiTexCoord2i(GL_TEXTURE1, dx + w, dy);
01527                             glMultiTexCoord2i(GL_TEXTURE2, dx + w, dy);
01528                             glVertex2f(dx + w, dy);
01529                         glEnd();
01530                     }
01531 
01532                     glBindTexture(vid->target, 0);
01533                     glDisable(vid->target);
01534                 }
01535             }
01536             else {
01537                 screen_masked_blit_standard(vid->memory_copy, sx, sy, dx, dy,
01538                                             w, h, FALSE, blit_type);
01539             }
01540 
01541             vid = vid->next;
01542         }
01543 
01544         if (use_combiners) {
01545             glPopAttrib();
01546         }
01547     }
01548     return;
01549 }
01550 
01551 
01552 
01553 static BITMAP* __allegro_gl_convert_rle_sprite(AL_CONST struct RLE_SPRITE *sprite, int trans)
01554 {
01555     BITMAP *temp = NULL;
01556     int y, x, src_depth;
01557     signed long src_mask;
01558 
01559     #define DRAW_RLE_8888(bits)                 \
01560     {                               \
01561         for (y = 0; y < sprite->h; y++) {           \
01562             signed long c = *s++;               \
01563             for (x = 0; x < sprite->w;) {           \
01564                 if (c == src_mask)          \
01565                     break;              \
01566                 if (c > 0) {                \
01567                     /* Run of solid pixels */   \
01568                     for (c--; c>=0; c--) {      \
01569                         unsigned long col = *s++;       \
01570                         if (bits == 32 && trans)        \
01571                             _putpixel32(temp, x++, y, makeacol32(getr32(col), getg32(col), getb32(col), geta32(col))); \
01572                         else            \
01573                             _putpixel32(temp, x++, y, makeacol32(getr##bits(col), getg##bits(col), getb##bits(col), 255)); \
01574                     }               \
01575                 }                   \
01576                 else {                  \
01577                     /* Run of transparent pixels */ \
01578                     hline(temp, x, y, x-c+1, 0);    \
01579                     x -= c;             \
01580                 }                   \
01581                 c = *s++;               \
01582             }                       \
01583         }                           \
01584     }
01585 
01586     src_depth = sprite->color_depth;
01587     if (src_depth == 8)
01588         src_mask = 0;
01589     else
01590         src_mask = makecol_depth(src_depth, 255, 0, 255);
01591 
01592     temp = create_bitmap_ex(32, sprite->w, sprite->h);
01593     if (!temp) return NULL;
01594 
01595     /* RGBA 8888 */
01596     switch(src_depth) {
01597         case 8:
01598         {
01599             signed char *s = (signed char*)sprite->dat;
01600             DRAW_RLE_8888(8);
01601             break;
01602         }
01603         case 15:
01604         {
01605             int16_t *s = (int16_t*)sprite->dat;
01606             DRAW_RLE_8888(15);
01607             break;
01608         }
01609         case 16:
01610         {
01611             int16_t *s = (int16_t*)sprite->dat;
01612             DRAW_RLE_8888(16);
01613             break;
01614         }
01615         case 24:
01616         {
01617             int32_t *s = (int32_t*)sprite->dat;
01618             DRAW_RLE_8888(24);
01619             break;
01620         }
01621         case 32:
01622         {
01623             int32_t *s = (int32_t*)sprite->dat;
01624             DRAW_RLE_8888(32);
01625             break;
01626         }
01627     }
01628 
01629     return temp;
01630 }
01631 
01632 
01633 
01634 void allegro_gl_screen_draw_rle_sprite(struct BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y)
01635 {
01636     BITMAP *temp = NULL, *temp2 = NULL;
01637     int source_x = 0, source_y = 0;
01638     int width = sprite->w, height = sprite->h;
01639 
01640     temp = __allegro_gl_convert_rle_sprite(sprite, FALSE);
01641     if (!temp)
01642         return;
01643 
01644     BITMAP_BLIT_CLIP(temp, bmp, source_x, source_y, x, y, width, height);
01645     
01646     if (is_sub_bitmap(bmp)) {
01647         x += bmp->x_ofs;
01648         y += bmp->y_ofs;
01649     }
01650 
01651     if (width <= 0 || height <= 0) {
01652         destroy_bitmap(temp);
01653         return;
01654     }
01655 
01656     temp2 = create_sub_bitmap(temp, source_x, source_y, width, height);
01657     if (!temp2) {
01658         destroy_bitmap(temp);
01659         return;
01660     }
01661 
01662     do_screen_masked_blit_standard(GL_RGBA, 
01663         __allegro_gl_get_bitmap_type(temp2, AGL_TEXTURE_MASKED), temp2,
01664         0, 0, x, y, width, height, FALSE, AGL_NO_ROTATION);
01665 
01666     destroy_bitmap(temp2);
01667     destroy_bitmap(temp);
01668 }
01669 
01670 
01671 static void allegro_gl_screen_draw_trans_rgba_rle_sprite(struct BITMAP *bmp,
01672                             AL_CONST struct RLE_SPRITE *sprite, int x, int y) {
01673     BITMAP *temp = NULL, *temp2 = NULL;
01674     int source_x = 0, source_y = 0;
01675     int width = sprite->w, height = sprite->h;
01676 
01677     temp = __allegro_gl_convert_rle_sprite(sprite, TRUE);
01678     if (!temp)
01679         return;
01680 
01681     BITMAP_BLIT_CLIP(temp, bmp, source_x, source_y, x, y, width, height);
01682     
01683     if (is_sub_bitmap(bmp)) {
01684         x += bmp->x_ofs;
01685         y += bmp->y_ofs;
01686     }
01687 
01688     if (width <= 0 || height <= 0) {
01689         destroy_bitmap(temp);
01690         return;
01691     }
01692 
01693     temp2 = create_sub_bitmap(temp, source_x, source_y, width, height);
01694     if (!temp2) {
01695         destroy_bitmap(temp);
01696         return;
01697     }
01698     
01699     if (__allegro_gl_blit_operation == AGL_OP_LOGIC_OP)
01700         glEnable(GL_COLOR_LOGIC_OP);
01701     else
01702         glEnable(GL_BLEND);
01703 
01704     allegro_gl_upload_and_display_texture(temp2, 0, 0, x, y, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE);
01705     
01706     if (__allegro_gl_blit_operation == AGL_OP_LOGIC_OP)
01707         glDisable(GL_COLOR_LOGIC_OP);
01708     else
01709         glDisable(GL_BLEND);
01710 
01711     destroy_bitmap(temp2);
01712     destroy_bitmap(temp);
01713 }
01714 
01715 
01716 
01717 static void allegro_gl_screen_masked_blit(struct BITMAP *source,
01718     struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y,
01719     int width, int height)
01720 {
01721     AGL_LOG(2, "glvtable.c:allegro_gl_screen_masked_blit\n");
01722     do_masked_blit_screen(source, dest, source_x, source_y, dest_x, dest_y,
01723                           width, height, FALSE, AGL_REGULAR_BMP | AGL_NO_ROTATION);
01724 }
01725 
01726 
01727 
01728 static void allegro_gl_screen_draw_sprite(struct BITMAP *bmp,
01729     struct BITMAP *sprite, int x, int y)
01730 {
01731     AGL_LOG(2, "glvtable.c:allegro_gl_screen_draw_sprite\n");
01732     do_masked_blit_screen(sprite, bmp, 0, 0, x, y, sprite->w, sprite->h,
01733                           FALSE, AGL_NO_ROTATION);
01734 }
01735 
01736 
01737 
01738 static void allegro_gl_screen_draw_sprite_v_flip(struct BITMAP *bmp,
01739     struct BITMAP *sprite, int x, int y)
01740 {
01741     AGL_LOG(2, "glvtable.c:allegro_gl_screen_draw_sprite_v_flip\n");
01742     do_masked_blit_screen(sprite, bmp, 0, 0, x, y, sprite->w, sprite->h,
01743                           AGL_V_FLIP, AGL_NO_ROTATION);
01744 }
01745 
01746 
01747 
01748 static void allegro_gl_screen_draw_sprite_h_flip(struct BITMAP *bmp,
01749     struct BITMAP *sprite, int x, int y)
01750 {
01751     AGL_LOG(2, "glvtable.c:allegro_gl_screen_draw_sprite_h_flip\n");
01752     do_masked_blit_screen(sprite, bmp, 0, 0, x, y, sprite->w, sprite->h,
01753                           AGL_H_FLIP, AGL_NO_ROTATION);
01754 }
01755 
01756 
01757 
01758 static void allegro_gl_screen_draw_sprite_vh_flip(struct BITMAP *bmp,
01759     struct BITMAP *sprite, int x, int y)
01760 {
01761     AGL_LOG(2, "glvtable.c:allegro_gl_screen_draw_sprite_vh_flip\n");
01762     do_masked_blit_screen(sprite, bmp, 0, 0, x, y, sprite->w, sprite->h,
01763                           AGL_V_FLIP | AGL_H_FLIP, AGL_NO_ROTATION);
01764 }
01765 
01766 
01767 
01768 static void allegro_gl_screen_pivot_scaled_sprite_flip(struct BITMAP *bmp,
01769     struct BITMAP *sprite, fixed x, fixed y, fixed cx, fixed cy, fixed angle,
01770     fixed scale, int v_flip)
01771 {
01772     double dscale = fixtof(scale);
01773     GLint matrix_mode;
01774     AGL_LOG(2, "glvtable.c:allegro_gl_screen_pivot_scaled_sprite_flip\n");
01775     
01776 #define BIN_2_DEG(x) (-(x) * 180.0 / 128)
01777     
01778     glGetIntegerv(GL_MATRIX_MODE, &matrix_mode);
01779     glMatrixMode(GL_MODELVIEW);
01780     glPushMatrix();
01781     glTranslated(fixtof(x), fixtof(y), 0.);
01782     glRotated(BIN_2_DEG(fixtof(angle)), 0., 0., -1.);
01783     glScaled(dscale, dscale, dscale);
01784     glTranslated(-fixtof(x+cx), -fixtof(y+cy), 0.);
01785     
01786     do_masked_blit_screen(sprite, bmp, 0, 0, fixtoi(x), fixtoi(y),
01787                           sprite->w, sprite->h, v_flip ? AGL_V_FLIP : FALSE, FALSE);
01788     glPopMatrix();
01789     glMatrixMode(matrix_mode);
01790 
01791 #undef BIN_2_DEG
01792 
01793     return;
01794 }
01795 
01796 
01797 
01798 static void allegro_gl_screen_draw_trans_rgba_sprite(struct BITMAP *bmp,
01799     struct BITMAP *sprite, int x, int y) {
01800 
01801     if (__allegro_gl_blit_operation == AGL_OP_LOGIC_OP)
01802         glEnable(GL_COLOR_LOGIC_OP);
01803     else
01804         glEnable(GL_BLEND);
01805 
01806     /* video -> screen */
01807     if (is_video_bitmap(sprite)) {
01808         allegro_gl_screen_blit_to_self(sprite, bmp, 0, 0, x, y, sprite->w, sprite->h);
01809     }
01810     /* memory -> screen */
01811     else if (is_memory_bitmap(sprite)) {
01812         GLint format = __allegro_gl_get_bitmap_color_format(sprite, AGL_TEXTURE_HAS_ALPHA);
01813         GLint type = __allegro_gl_get_bitmap_type(sprite, 0);
01814         allegro_gl_upload_and_display_texture(sprite, 0, 0, x, y, sprite->w, sprite->h, 0, format, type);
01815     }
01816     
01817     if (__allegro_gl_blit_operation == AGL_OP_LOGIC_OP)
01818         glDisable(GL_COLOR_LOGIC_OP);
01819     else
01820         glDisable(GL_BLEND);
01821     
01822     return;
01823 }
01824 
01825 
01826 
01827 static void allegro_gl_screen_draw_sprite_ex(struct BITMAP *bmp,
01828     struct BITMAP *sprite, int x, int y, int mode, int flip)
01829 {
01830     int lflip = 0;
01831     int matrix_mode;
01832     AGL_LOG(2, "glvtable.c:allegro_gl_screen_draw_sprite_ex\n");
01833 
01834     /* convert allegro's flipping flags to AGL's flags */
01835     switch (flip) {
01836         case DRAW_SPRITE_NO_FLIP:
01837             lflip = FALSE;
01838         break;
01839         case DRAW_SPRITE_V_FLIP:
01840             lflip = AGL_V_FLIP;
01841         break;
01842         case DRAW_SPRITE_H_FLIP:
01843             lflip = AGL_H_FLIP;
01844         break;
01845         case DRAW_SPRITE_VH_FLIP:
01846             lflip = AGL_V_FLIP | AGL_H_FLIP;
01847         break;
01848     }
01849 
01850     switch (mode) {
01851         case DRAW_SPRITE_NORMAL:
01852             do_masked_blit_screen(sprite, bmp, 0, 0, x, y, sprite->w, sprite->h,
01853                 lflip, AGL_NO_ROTATION);
01854         break;
01855         case DRAW_SPRITE_TRANS:
01856             if (lflip) {
01857                 glGetIntegerv(GL_MATRIX_MODE, &matrix_mode);
01858                 glMatrixMode(GL_MODELVIEW);
01859                 glPushMatrix();
01860 
01861                 glTranslatef(x, y, 0.f);
01862                 glScalef((lflip&AGL_H_FLIP) ? -1 : 1, (lflip&AGL_V_FLIP)? -1 : 1, 1);
01863                 glTranslatef(-x, -y, 0);
01864                 glTranslatef((lflip&AGL_H_FLIP) ? -sprite->w : 0,
01865                              (lflip&AGL_V_FLIP) ? -sprite->h : 0, 0);
01866             }
01867 
01868             allegro_gl_screen_draw_trans_rgba_sprite(bmp, sprite, x, y);
01869 
01870             if (lflip) {
01871                 glPopMatrix();
01872                 glMatrixMode(matrix_mode);
01873             }
01874         break;
01875         case DRAW_SPRITE_LIT:
01876         /* unsupported */
01877         break;
01878     }
01879 }
01880 
01881 
01882 
01883 void allegro_gl_screen_draw_glyph_ex(struct BITMAP *bmp,
01884                                   AL_CONST struct FONT_GLYPH *glyph, int x, int y,
01885                                   int color, int bg, int flip)
01886 {
01887     GLubyte r, g, b, a;
01888     int x_offs = 0;
01889     int i;
01890 
01891     AGL_LOG(2, "glvtable.c:allegro_gl_screen_draw_glyph_ex\n");
01892     
01893     if (bmp->clip) {
01894         glPushAttrib(GL_SCISSOR_BIT);
01895         glEnable(GL_SCISSOR_TEST);
01896         glScissor(bmp->x_ofs + bmp->cl, bmp->h + bmp->y_ofs - bmp->cb,
01897                   bmp->cr - bmp->cl, bmp->cb - bmp->ct);
01898 
01899         if (x < bmp->cl) {
01900             x_offs -= x - bmp->cl;
01901             x = bmp->cl;
01902         }
01903     }
01904     if (is_sub_bitmap(bmp)) {
01905         x += bmp->x_ofs;
01906         y += bmp->y_ofs;
01907     }
01908     
01909     if (bg != -1) {
01910         split_color(bg, &r, &g, &b, &a, bitmap_color_depth(bmp));
01911         glColor4ub(r, g, b, a);
01912         glRecti(x, y, x + glyph->w, y + glyph->h);              
01913     }
01914 
01915     split_color(color, &r, &g, &b, &a, bitmap_color_depth(bmp));
01916     glColor4ub(r, g, b, a);
01917     glRasterPos2i(x, y);
01918     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
01919     glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
01920 
01921     if (flip) {
01922         for (i = 0; i < glyph->h; i++) {
01923             glBitmap(glyph->w, 1, x_offs, i, 0, 2,
01924                                          glyph->dat + i * ((glyph->w + 7) / 8));
01925         }
01926     }
01927     else {
01928         for (i = 0; i < glyph->h; i++) {
01929             glBitmap(glyph->w, 1, x_offs, i, 0, 0,
01930                                          glyph->dat + i * ((glyph->w + 7) / 8));
01931         }
01932     }
01933     
01934     if (bmp->clip) {
01935         glPopAttrib();
01936     }
01937 
01938     return;
01939 }
01940 
01941 
01942 
01943 static void allegro_gl_screen_draw_glyph(struct BITMAP *bmp,
01944                                   AL_CONST struct FONT_GLYPH *glyph, int x, int y,
01945                                   int color, int bg) {
01946     allegro_gl_screen_draw_glyph_ex(bmp, glyph, x, y, color, bg, 0);
01947 }
01948 
01949 
01950 
01951 void allegro_gl_screen_draw_color_glyph_ex(struct BITMAP *bmp,
01952     struct BITMAP *sprite, int x, int y, int color, int bg, int flip)
01953 {
01954 
01955     /* Implementation note: we should try building textures and see how well
01956      * those work instead of of DrawPixels with a weird I_TO_RGBA mapping.
01957      */
01958     static GLfloat red_map[256];
01959     static GLfloat green_map[256];
01960     static GLfloat blue_map[256];
01961     static GLfloat alpha_map[256];
01962     GLubyte r, g, b, a;
01963     int i;
01964     GLint saved_row_length;
01965     GLint width, height;
01966     int sprite_x = 0, sprite_y = 0;
01967     void *data;
01968     int *table;
01969 
01970     width = sprite->w;
01971     height = sprite->h;
01972 
01973     if (bmp->clip) {
01974         if ((x >= bmp->cr) || (y >= bmp->cb) || (x + width < bmp->cl)
01975          || (y + height < bmp->ct)) {
01976             return;
01977         }
01978         if (x < bmp->cl) {
01979             width += x - bmp->cl;
01980             sprite_x -= (x - bmp->cl);
01981             x = bmp->cl;
01982         }
01983         if (y < bmp->ct) {
01984             height += y - bmp->ct;
01985             sprite_y -= (y - bmp->ct);
01986             y = bmp->ct;
01987         }
01988         if (x + width > bmp->cr) {
01989             width = bmp->cr - x;
01990         }
01991         if (y + height > bmp->cb) {
01992             height = bmp->cb - y;
01993         }
01994     }
01995     if (is_sub_bitmap(bmp)) {
01996         x += bmp->x_ofs;
01997         y += bmp->y_ofs;
01998     }
01999 
02000     data = sprite->line[sprite_y]
02001          + sprite_x * BYTES_PER_PIXEL(bitmap_color_depth(sprite));
02002 
02003     if (bg < 0) {
02004         glAlphaFunc(GL_GREATER, 0.0f);
02005         glEnable(GL_ALPHA_TEST);
02006         alpha_map[0] = 0.;
02007     }
02008     else {
02009         split_color(bg, &r, &g, &b, &a, bitmap_color_depth(bmp));
02010         red_map[0] = r / 255.;
02011         green_map[0] = g / 255.;
02012         blue_map[0] = b / 255.;
02013         alpha_map[0] = 1.;
02014     }
02015 
02016     if (color < 0) {
02017         table = _palette_expansion_table(bitmap_color_depth(bmp));
02018 
02019         for(i = 1; i < 255; i++) {
02020             split_color(table[i], &r, &g, &b, &a, bitmap_color_depth(bmp));
02021             red_map[i] = r / 255.;
02022             green_map[i] = g / 255.;
02023             blue_map[i] = b / 255.;
02024             alpha_map[i] = 1.;
02025         }
02026     }
02027     else {
02028         split_color(color, &r, &g, &b, &a, bitmap_color_depth(bmp));
02029 
02030         for(i = 1; i < 255; i++) {
02031             red_map[i] = r / 255.;
02032             green_map[i] = g / 255.;
02033             blue_map[i] = b / 255.;
02034             alpha_map[i] = 1.;
02035         }
02036     }
02037     
02038     glPixelMapfv(GL_PIXEL_MAP_I_TO_R, 256, red_map);
02039     glPixelMapfv(GL_PIXEL_MAP_I_TO_G, 256, green_map);
02040     glPixelMapfv(GL_PIXEL_MAP_I_TO_B, 256, blue_map);
02041     glPixelMapfv(GL_PIXEL_MAP_I_TO_A, 256, alpha_map);
02042     
02043     glRasterPos2i(x, y);
02044     glPushAttrib(GL_PIXEL_MODE_BIT);
02045     glGetIntegerv(GL_UNPACK_ROW_LENGTH, &saved_row_length);
02046     
02047     glPixelZoom(1.0, flip ? -1.0 : 1.0);
02048     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
02049     glPixelStorei(GL_UNPACK_ROW_LENGTH, sprite->w);
02050     glPixelTransferi(GL_MAP_COLOR, GL_TRUE);
02051 
02052     glDrawPixels(width, height, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, data);
02053     glPixelStorei(GL_UNPACK_ROW_LENGTH, saved_row_length);
02054     glPopAttrib();
02055     if (bg < 0) {
02056         glDisable(GL_ALPHA_TEST);
02057     }
02058 
02059     return;
02060 }
02061 
02062 
02063 
02064 static void allegro_gl_screen_draw_color_glyph(struct BITMAP *bmp,
02065     struct BITMAP *sprite, int x, int y, int color, int bg) {
02066     allegro_gl_screen_draw_color_glyph_ex(bmp, sprite, x, y, color, bg, 1);
02067 }
02068 
02069 
02070 
02071 static void allegro_gl_screen_draw_character(struct BITMAP *bmp,
02072                          struct BITMAP *sprite, int x, int y, int color, int bg)
02073 {
02074     AGL_LOG(2, "glvtable.c:allegro_gl_screen_draw_character\n");
02075     allegro_gl_screen_draw_color_glyph(bmp, sprite, x, y, color, bg);
02076 }
02077 
02078 
02079 
02080 static void allegro_gl_screen_draw_256_sprite(struct BITMAP *bmp,
02081                                             struct BITMAP *sprite, int x, int y)
02082 {
02083     AGL_LOG(2, "glvtable.c:allegro_gl_screen_draw_256_sprite\n");
02084     allegro_gl_screen_draw_color_glyph(bmp, sprite, x, y, -1, -1);
02085 }
02086 
02087 
02088 
02089 void allegro_gl_screen_clear_to_color(struct BITMAP *bmp, int color)
02090 {
02091     if (__agl_drawing_pattern_tex || bmp->clip) {
02092         allegro_gl_screen_rectfill(bmp, 0, 0, bmp->w, bmp->h, color);
02093     }
02094     else {
02095         GLubyte r, g, b, a;
02096         GLfloat old_col[4];
02097     
02098         split_color(color, &r, &g, &b, &a, bitmap_color_depth(bmp));
02099         
02100         glGetFloatv(GL_COLOR_CLEAR_VALUE, old_col);
02101         glClearColor(((float) r / 255), ((float) g / 255), ((float) b / 255),
02102                      ((float) a / 255));
02103 
02104         glClear(GL_COLOR_BUFFER_BIT);
02105         glClearColor(old_col[0], old_col[1], old_col[2], old_col[3]);
02106     }
02107 
02108     return;
02109 }
02110 
02111 
02112 
02113 /* TODO: Handle concave and self-intersecting. */
02114 static void allegro_gl_screen_polygon(struct BITMAP *bmp, int vertices,
02115                                       AL_CONST int *points, int color) {
02116     GLubyte r, g, b, a;
02117     int i;
02118 
02119     split_color(color, &r, &g, &b, &a, bitmap_color_depth(bmp));
02120     glColor4ub(r, g, b, a);
02121     
02122     glPushAttrib(GL_SCISSOR_BIT);
02123 
02124     if (bmp->clip) {
02125         glEnable(GL_SCISSOR_TEST);
02126         glScissor(bmp->x_ofs + bmp->cl, bmp->h + bmp->y_ofs - bmp->cb,
02127                   bmp->cr - bmp->cl, bmp->cb - bmp->ct);
02128     }
02129     else {
02130         glScissor(0, 0, bmp->w, bmp->h);
02131     }
02132 
02133     glBegin(GL_POLYGON);
02134         for (i = 0; i < vertices*2-1; i+=2) {
02135             SET_TEX_COORDS(points[i], points[i+1]);
02136             if (is_sub_bitmap(bmp)) {
02137                 glVertex2f(points[i] + bmp->x_ofs, points[i+1] + bmp->y_ofs);
02138             }
02139             else {
02140                 glVertex2f(points[i], points[i+1]);
02141             }
02142         }
02143     glEnd();
02144 
02145     glPopAttrib();
02146 }
02147 
02148 
02149 
02150 static void allegro_gl_screen_rect(struct BITMAP *bmp,
02151                                    int x1, int y1, int x2, int y2, int color) {
02152     GLubyte r, g, b, a;
02153 
02154     split_color(color, &r, &g, &b, &a, bitmap_color_depth(bmp));
02155     glColor4ub(r, g, b, a);
02156     
02157     glPushAttrib(GL_SCISSOR_BIT);
02158 
02159     if (bmp->clip) {
02160         glEnable(GL_SCISSOR_TEST);
02161         glScissor(bmp->x_ofs + bmp->cl, bmp->h + bmp->y_ofs - bmp->cb,
02162                   bmp->cr - bmp->cl, bmp->cb - bmp->ct);
02163     }
02164     else {
02165         glScissor(0, 0, bmp->w, bmp->h);
02166     }
02167     if (is_sub_bitmap(bmp)) {
02168         x1 += bmp->x_ofs;
02169         x2 += bmp->x_ofs;
02170         y1 += bmp->y_ofs;
02171         y2 += bmp->y_ofs;
02172     }
02173 
02174     glBegin(GL_LINE_STRIP);
02175         glVertex2f(x1, y1);
02176         glVertex2f(x2, y1);
02177         glVertex2f(x2, y2);
02178         glVertex2f(x1, y2);
02179         glVertex2f(x1, y1);
02180     glEnd();
02181 
02182     glPopAttrib();
02183 }
02184 
02185 
02186 
02187 void allegro_gl_screen_polygon3d_f(struct BITMAP *bmp, int type,
02188                                    struct BITMAP *texture, int vc,
02189                                    V3D_f *vtx[]) {
02190     int i;
02191     int use_z = FALSE;
02192 
02193     if (type & POLYTYPE_ZBUF) {
02194         use_z = TRUE;
02195         type &= ~POLYTYPE_ZBUF;
02196     }
02197 
02198     if (type == POLYTYPE_PTEX || type == POLYTYPE_PTEX_TRANS)
02199         use_z = TRUE;
02200 
02201     if (bmp->clip) {
02202         glPushAttrib(GL_SCISSOR_BIT);
02203         glEnable(GL_SCISSOR_TEST);
02204         glScissor(bmp->x_ofs + bmp->cl, bmp->h + bmp->y_ofs - bmp->cb,
02205                   bmp->cr - bmp->cl, bmp->cb - bmp->ct);
02206     }
02207     if (is_sub_bitmap(bmp)) {
02208         for (i = 0; i < vc*2-1; i+=2) {
02209             vtx[i] += bmp->x_ofs;
02210             vtx[i+1] += bmp->y_ofs;
02211         }
02212     }
02213 
02214     if (use_z) {
02215         glEnable(GL_DEPTH_TEST);
02216         glDepthFunc(GL_LESS);
02217         glDepthMask(GL_TRUE);
02218     }
02219 
02220     glColor4ub(255, 255, 255, 255);
02221 
02222     if (type == POLYTYPE_ATEX || type == POLYTYPE_PTEX
02223      || type == POLYTYPE_ATEX_TRANS || type == POLYTYPE_PTEX_TRANS) {
02224         drawing_mode(DRAW_MODE_COPY_PATTERN, texture, 0, 0);
02225     }
02226 
02227     if (type == POLYTYPE_ATEX_TRANS || type == POLYTYPE_PTEX_TRANS) {
02228         glEnable(GL_BLEND);
02229     }
02230 
02231     glBegin(GL_POLYGON);
02232         for (i = 0; i < vc; i++) {
02233             if (type == POLYTYPE_FLAT)
02234                 glColor3ub(getr(vtx[0]->c), getg(vtx[0]->c), getb(vtx[0]->c));
02235             else if (type == POLYTYPE_GRGB)
02236                 glColor3ub(getr24(vtx[i]->c), getg24(vtx[i]->c), getb24(vtx[i]->c));
02237             else if (type == POLYTYPE_GCOL)
02238                 glColor3ub(getr(vtx[i]->c), getg(vtx[i]->c), getb(vtx[i]->c));
02239             else if (type == POLYTYPE_ATEX || type == POLYTYPE_PTEX
02240                   || type == POLYTYPE_ATEX_TRANS || type == POLYTYPE_PTEX_TRANS) {
02241                     SET_TEX_COORDS(vtx[i]->u, vtx[i]->v);
02242             }
02243 
02244             if (use_z)
02245                 glVertex3f(vtx[i]->x, vtx[i]->y, 1.f / vtx[i]->z);
02246             else
02247                 glVertex2f(vtx[i]->x, vtx[i]->y);
02248         }
02249     glEnd();
02250 
02251     if (bmp->clip)
02252         glPopAttrib();
02253 
02254     if (use_z) {
02255         glDisable(GL_DEPTH_TEST);
02256         glDepthMask(GL_FALSE);
02257     }
02258 
02259     if (type == POLYTYPE_ATEX || type == POLYTYPE_PTEX
02260      || type == POLYTYPE_ATEX_TRANS || type == POLYTYPE_PTEX_TRANS) {
02261         solid_mode();
02262     }
02263 
02264     if (type == POLYTYPE_ATEX_TRANS || type == POLYTYPE_PTEX_TRANS)
02265         glDisable(GL_BLEND);
02266 }
02267 
02268 
02269 
02270 static void allegro_gl_screen_polygon3d(struct BITMAP *bmp, int type,
02271                                         struct BITMAP *texture, int vc,
02272                                         V3D *vtx[]) {
02273     int i;
02274     V3D_f **vtx_f = malloc(vc * sizeof(struct V3D_f*));
02275     if (!vtx_f)
02276         return;
02277 
02278     for (i = 0; i < vc; i++) {
02279         vtx_f[i] = malloc(sizeof(struct V3D_f));
02280         if (!vtx_f[i]) {
02281             int k;
02282             for (k = 0; k < i; k++)
02283                 free(vtx_f[k]);
02284             free(vtx_f);
02285             return;
02286         }
02287         vtx_f[i]->c = vtx[i]->c;
02288         vtx_f[i]->u = fixtof(vtx[i]->u);
02289         vtx_f[i]->v = fixtof(vtx[i]->v);
02290         vtx_f[i]->x = fixtof(vtx[i]->x);
02291         vtx_f[i]->y = fixtof(vtx[i]->y);
02292         vtx_f[i]->z = fixtof(vtx[i]->z);
02293     }
02294 
02295     allegro_gl_screen_polygon3d_f(bmp, type, texture, vc, vtx_f);
02296     for (i = 0; i < vc; i++)
02297         free(vtx_f[i]);
02298     free(vtx_f);
02299 }
02300 
02301 
02302 static void allegro_gl_screen_quad3d_f(struct BITMAP *bmp, int type,
02303                                        struct BITMAP *texture,
02304                                        V3D_f *v1, V3D_f *v2, V3D_f *v3, V3D_f *v4) {
02305 
02306     V3D_f *vtx_f[4];
02307     vtx_f[0] = v1;
02308     vtx_f[1] = v2;
02309     vtx_f[2] = v3;
02310     vtx_f[3] = v4;
02311 
02312     allegro_gl_screen_polygon3d_f(bmp, type, texture, 4, vtx_f);
02313 }
02314 
02315 
02316 
02317 static void allegro_gl_screen_quad3d(struct BITMAP *bmp, int type,
02318             struct BITMAP *texture, V3D *v1, V3D *v2, V3D *v3, V3D *v4) {
02319 
02320     V3D *vtx[4];
02321     vtx[0] = v1;
02322     vtx[1] = v2;
02323     vtx[2] = v3;
02324     vtx[3] = v4;
02325 
02326     allegro_gl_screen_polygon3d(bmp, type, texture, 4, vtx);
02327 }
02328 
02329 
02330 
02331 static void allegro_gl_screen_triangle3d(struct BITMAP *bmp, int type,
02332                                          struct BITMAP *texture,
02333                                          V3D *v1, V3D *v2, V3D *v3) {
02334     V3D *vtx[3];
02335     vtx[0] = v1;
02336     vtx[1] = v2;
02337     vtx[2] = v3;
02338 
02339     allegro_gl_screen_polygon3d(bmp, type, texture, 3, vtx);
02340 }
02341 
02342 
02343 
02344 static void allegro_gl_screen_triangle3d_f(struct BITMAP *bmp, int type,
02345                                            struct BITMAP *texture,
02346                                            V3D_f *v1, V3D_f *v2, V3D_f *v3) {
02347     V3D_f *vtx_f[3];
02348     vtx_f[0] = v1;
02349     vtx_f[1] = v2;
02350     vtx_f[2] = v3;
02351 
02352     allegro_gl_screen_polygon3d_f(bmp, type, texture, 3, vtx_f);
02353 }
02354 
02355 
02356 
02357 void __allegro_gl__glvtable_update_vtable(GFX_VTABLE ** vtable)
02358 {
02359     int maskcolor = (*vtable)->mask_color;
02360     int depth = (*vtable)->color_depth;
02361 
02362     AGL_LOG(2, "glvtable.c:__allegro_gl__glvtable_update_vtable\n");
02363     allegro_gl_screen_vtable.color_depth = depth;
02364     /* makecol_depth is used below instead of the MASK_COLOR_x constants
02365      * because we may have changed the RGB shift values in order to
02366      * use the packed pixels extension
02367      */
02368     allegro_gl_screen_vtable.mask_color =
02369         makecol_depth(depth, getr(maskcolor), getg(maskcolor), getb(maskcolor));
02370     
02371     *vtable = &allegro_gl_screen_vtable;
02372 
02373     __allegro_gl_driver->screen_masked_blit = screen_masked_blit_standard;
02374     if (allegro_gl_extensions_GL.NV_register_combiners) {
02375         __allegro_gl_driver->screen_masked_blit
02376                                                = screen_masked_blit_nv_register;
02377     }
02378     else if (allegro_gl_info.num_texture_units >= 3) {
02379         __allegro_gl_driver->screen_masked_blit =
02380                                                  screen_masked_blit_combine_tex;
02381     }
02382 }
02383 
02384 
02385 
02386 /* Saved projection matrix */
02387 static double allegro_gl_projection_matrix[16];
02388 static double allegro_gl_modelview_matrix[16];
02389 
02390 
02391 
02422 void allegro_gl_set_allegro_mode(void)
02423 {
02424     AGL_LOG(2, "glvtable.c:allegro_gl_set_allegro_mode\n");
02425 
02426     /* Save the OpenGL state  then set it up */
02427     glPushAttrib(GL_ENABLE_BIT | GL_TEXTURE_BIT | GL_TRANSFORM_BIT
02428                | GL_POINT_BIT | GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
02429     glDisable(GL_DEPTH_TEST);
02430     glDisable(GL_CULL_FACE);
02431     glDisable(GL_FOG);
02432     glDisable(GL_LIGHTING);
02433     glDisable(GL_BLEND);
02434     glDisable(GL_ALPHA_TEST);
02435     glDepthMask(GL_FALSE);
02436     glEnable(GL_TEXTURE_2D);
02437     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
02438     glPointSize(1.);
02439 
02440     /* Create pool texture */
02441     if (!__allegro_gl_pool_texture) {
02442         glGenTextures(1, &__allegro_gl_pool_texture);
02443     }
02444 
02445     glBindTexture(GL_TEXTURE_2D, __allegro_gl_pool_texture);
02446         /* Create a texture without defining the data */
02447     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0,
02448                  GL_RGBA, GL_UNSIGNED_BYTE, NULL);
02449     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
02450     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
02451 
02452     glBindTexture(GL_TEXTURE_2D, 0);
02453     allegro_gl_set_projection();
02454 
02455     /* For some reason, ATI Rage Pro isn't able to draw correctly without a
02456      * texture bound. So we bind a dummy 1x1 texture to work around the issue.
02457      */
02458     if (allegro_gl_info.is_ati_rage_pro) {
02459         if (!__allegro_gl_dummy_texture) {
02460             GLubyte tex[4] = {255, 255, 255, 255};
02461             glGenTextures(1, &__allegro_gl_dummy_texture);
02462             glBindTexture(GL_TEXTURE_2D, __allegro_gl_dummy_texture);
02463             glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0,
02464                          GL_RGBA, GL_UNSIGNED_BYTE, tex);
02465         }
02466         glBindTexture(GL_TEXTURE_2D, __allegro_gl_dummy_texture);
02467     }
02468 #ifdef ALLEGRO_MACOSX
02469     /* MacOSX 10.2.x has a bug: glRasterPos causes a crash (it is used in
02470      *'blit'). This stops it happening.
02471      */
02472     glBegin(GL_POINTS);
02473     glEnd();
02474 #endif
02475 }
02476 
02477 
02478 
02491 void allegro_gl_unset_allegro_mode(void)
02492 {
02493     AGL_LOG(2, "glvtable.c:allegro_gl_unset_allegro_mode\n");
02494 
02495     switch(allegro_gl_display_info.vidmem_policy) {
02496         case AGL_KEEP:
02497             break;
02498         case AGL_RELEASE:
02499             if (__allegro_gl_pool_texture) {
02500                 glDeleteTextures(1, &__allegro_gl_pool_texture);
02501                 __allegro_gl_pool_texture = 0;
02502             }
02503             break;
02504     }
02505     allegro_gl_unset_projection();
02506     glPopAttrib();
02507 }
02508 
02509 
02510 
02540 void allegro_gl_set_projection(void)
02541 {
02542     GLint v[4];
02543     AGL_LOG(2, "glvtable.c:allegro_gl_set_projection\n");
02544     
02545     /* Setup OpenGL matrices */
02546     glGetIntegerv(GL_VIEWPORT, &v[0]);
02547     glMatrixMode(GL_MODELVIEW);
02548     glGetDoublev(GL_MODELVIEW_MATRIX, allegro_gl_modelview_matrix);
02549     glLoadIdentity();
02550     glMatrixMode(GL_PROJECTION);
02551     glGetDoublev(GL_PROJECTION_MATRIX, allegro_gl_projection_matrix);
02552     glLoadIdentity();
02553     gluOrtho2D(v[0] - 0.325, v[0] + v[2] - 0.325, v[1] + v[3] - 0.325, v[1] - 0.325);
02554 }
02555 
02556 
02557 
02567 void allegro_gl_unset_projection(void)
02568 {
02569     AGL_LOG(2, "glvtable.c:allegro_gl_unset_projection\n");
02570     glMatrixMode(GL_PROJECTION);
02571     glLoadMatrixd(allegro_gl_projection_matrix);
02572     glMatrixMode(GL_MODELVIEW);
02573     glLoadMatrixd(allegro_gl_modelview_matrix);
02574 }
02575 
02576 
02577 
02578 void allegro_gl_memory_blit_between_formats(struct BITMAP *src,
02579     struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y,
02580     int width, int height)
02581 {
02582     AGL_LOG(2, "AGL::blit_between_formats\n");
02583 
02584     /* screen -> memory */
02585     if (is_screen_bitmap(src)) {
02586         allegro_gl_screen_blit_to_memory(src, dest, source_x, source_y,
02587                                          dest_x, dest_y, width, height);
02588         return;
02589     }
02590 
02591     /* video -> memory */
02592     if (is_video_bitmap(src)) {
02593         allegro_gl_video_blit_to_memory(src, dest, source_x, source_y,
02594                                         dest_x, dest_y, width, height);
02595         return;
02596     }
02597     
02598     /* memory -> screen */
02599     if (is_screen_bitmap(dest)) {
02600         allegro_gl_screen_blit_from_memory(src, dest, source_x, source_y,
02601                                            dest_x, dest_y, width, height);
02602         return;
02603     }
02604 
02605     /* memory -> video */
02606     if (is_video_bitmap(dest)) {
02607         allegro_gl_video_blit_from_memory(src, dest, source_x, source_y,
02608                                           dest_x, dest_y, width, height);
02609         return;
02610     }
02611 
02612     switch(bitmap_color_depth(dest)) {
02613         #ifdef ALLEGRO_COLOR8
02614         case 8:
02615             __blit_between_formats8(src, dest, source_x, source_y,
02616                                     dest_x, dest_y, width, height);
02617             return;
02618         #endif
02619         #ifdef ALLEGRO_COLOR16
02620         case 15:
02621             __blit_between_formats15(src, dest, source_x, source_y,
02622                                      dest_x, dest_y, width, height);
02623             return;
02624         case 16:
02625             __blit_between_formats16(src, dest, source_x, source_y,
02626                                      dest_x, dest_y, width, height);
02627             return;
02628         #endif
02629         #ifdef ALLEGRO_COLOR24
02630         case 24:
02631             __blit_between_formats24(src, dest, source_x, source_y,
02632                                      dest_x, dest_y, width, height);
02633             return;
02634         #endif
02635         #ifdef ALLEGRO_COLOR32
02636         case 32:
02637             __blit_between_formats32(src, dest, source_x, source_y,
02638                                      dest_x, dest_y, width, height);
02639             return;
02640         #endif
02641         default:
02642             TRACE("--== ERROR ==-- AGL::blit_between_formats : %i -> %i bpp\n",
02643                   bitmap_color_depth(src), bitmap_color_depth(dest));
02644             return;
02645     }
02646 }
02647 
02648 
02649 
02650 static void dummy_unwrite_bank(void)
02651 {
02652 }
02653 
02654 
02655 
02656 static GFX_VTABLE allegro_gl_screen_vtable = {
02657     0,
02658     0,
02659     dummy_unwrite_bank,         //void *unwrite_bank;
02660     NULL,                       //AL_METHOD(void, set_clip, (struct BITMAP *bmp));
02661     allegro_gl_screen_acquire,
02662     allegro_gl_screen_release,
02663     NULL,                       //AL_METHOD(struct BITMAP *, create_sub_bitmap, (struct BITMAP *parent, int x, int y, int width, int height));
02664     NULL,                       //AL_METHOD(void, created_sub_bitmap, (struct BITMAP *bmp, struct BITMAP *parent));
02665     allegro_gl_screen_getpixel,
02666     allegro_gl_screen_putpixel,
02667     allegro_gl_screen_vline,
02668     allegro_gl_screen_hline,
02669     allegro_gl_screen_hline,
02670     allegro_gl_screen_line,
02671     allegro_gl_screen_line,
02672     allegro_gl_screen_rectfill,
02673     allegro_gl_screen_triangle,
02674     allegro_gl_screen_draw_sprite,
02675     allegro_gl_screen_draw_256_sprite,
02676     allegro_gl_screen_draw_sprite_v_flip,
02677     allegro_gl_screen_draw_sprite_h_flip,
02678     allegro_gl_screen_draw_sprite_vh_flip,
02679     allegro_gl_screen_draw_trans_rgba_sprite,
02680     allegro_gl_screen_draw_trans_rgba_sprite,
02681     NULL,                       //AL_METHOD(void, draw_lit_sprite, (struct BITMAP *bmp, struct BITMAP *sprite, int x, int y, int color));
02682     allegro_gl_screen_draw_rle_sprite,
02683     allegro_gl_screen_draw_trans_rgba_rle_sprite,
02684     allegro_gl_screen_draw_trans_rgba_rle_sprite,
02685     NULL,                       //AL_METHOD(void, draw_lit_rle_sprite, (struct BITMAP *bmp, struct RLE_SPRITE *sprite, int x, int y, int color));
02686     allegro_gl_screen_draw_character,
02687     allegro_gl_screen_draw_glyph,
02688     allegro_gl_screen_blit_from_memory,
02689     allegro_gl_screen_blit_to_memory,
02690     NULL,                       //AL_METHOD(void, blit_from_system, (struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height));
02691     NULL,                       //AL_METHOD(void, blit_to_system, (struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height));
02692     allegro_gl_screen_blit_to_self,
02693     allegro_gl_screen_blit_to_self, /* ..._forward */
02694     allegro_gl_screen_blit_to_self, /* ..._backward */
02695     allegro_gl_memory_blit_between_formats,
02696     allegro_gl_screen_masked_blit,
02697     allegro_gl_screen_clear_to_color,
02698     allegro_gl_screen_pivot_scaled_sprite_flip,
02699     NULL,                       //AL_METHOD(void, do_stretch_blit, (struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int source_width, int source_height, int dest_x, int dest_y, int dest_width, int dest_height, int masked));
02700     NULL,                       //AL_METHOD(void, draw_gouraud_sprite, (struct BITMAP *bmp, struct BITMAP *sprite, int x, int y, int c1, int c2, int c3, int c4));
02701     NULL,                       //AL_METHOD(void, draw_sprite_end, (void));
02702     NULL,                       //AL_METHOD(void, blit_end, (void));
02703     allegro_gl_screen_polygon,
02704     allegro_gl_screen_rect,
02705     _soft_circle,               //AL_METHOD(void, circle, (struct BITMAP *bmp, int x, int y, int radius, int color));
02706     _soft_circlefill,           //AL_METHOD(void, circlefill, (struct BITMAP *bmp, int x, int y, int radius, int color));
02707     _soft_ellipse,              //AL_METHOD(void, ellipse, (struct BITMAP *bmp, int x, int y, int rx, int ry, int color));
02708     _soft_ellipsefill,          //AL_METHOD(void, ellipsefill, (struct BITMAP *bmp, int x, int y, int rx, int ry, int color));
02709     _soft_arc,                  //AL_METHOD(void, arc, (struct BITMAP *bmp, int x, int y, fixed ang1, fixed ang2, int r, int color));
02710     _soft_spline,               //AL_METHOD(void, spline, (struct BITMAP *bmp, AL_CONST int points[8], int color));
02711     _soft_floodfill,            //AL_METHOD(void, floodfill, (struct BITMAP *bmp, int x, int y, int color));
02712     allegro_gl_screen_polygon3d,
02713     allegro_gl_screen_polygon3d_f,
02714     allegro_gl_screen_triangle3d,
02715     allegro_gl_screen_triangle3d_f,
02716     allegro_gl_screen_quad3d,
02717     allegro_gl_screen_quad3d_f,
02718     allegro_gl_screen_draw_sprite_ex
02719 };
02720 
allegro4.4-4.4.2/addons/allegrogl/docs/html/glvtable_8h_source.html000066400000000000000000000257321173507505700252000ustar00rootroot00000000000000 AllegroGL: glvtable.h Source File

glvtable.h

00001 #ifndef ALLEGRO_GL_WINDOWS_VTABLE_H
00002 #define ALLEGRO_GL_WINDOWS_VTABLE_H
00003 
00004 #include <allegro.h>
00005 
00006 
00007 /* Special structure for holding video bitmaps. This piggy-backs
00008  * over the regular BITMAP structure to provide AllegroGL with the
00009  * necessary information for maintaining video bitmap over OpenGL
00010  */
00011 typedef struct AGL_VIDEO_BITMAP {
00012     GLenum target;         /* GL_TEXTURE_2D, GL_TEXTURE_RECTANGLE_NV, etc */
00013     BITMAP *memory_copy;   /* Memory copy for reading -> subbitmap */
00014     GLuint tex;            /* Associated texture number */
00015     GLuint fbo;            /* Associated FBO number. */
00016     int x_ofs, y_ofs;      /* Offsets of this block */
00017     int width, height;     /* Size of the bitmap block */
00018     struct AGL_VIDEO_BITMAP *next; /* Next block, if bitmap is too large to fit in one texture */
00019     GLenum format;         /* Pixel data format of the memory copy bitmap. */
00020     GLenum type;           /* Pixel data type of the memory copy bitmap. */
00021 } AGL_VIDEO_BITMAP;
00022 
00023 
00024 void __allegro_gl__glvtable_update_vtable (GFX_VTABLE **vtable);
00025 BITMAP *allegro_gl_create_video_bitmap(int w, int h);
00026 void allegro_gl_drawing_mode(void);
00027 void allegro_gl_set_blender_mode(int mode, int r, int g, int b, int a);
00028 void allegro_gl_destroy_video_bitmap(BITMAP *bmp);
00029 void allegro_gl_created_sub_bitmap(BITMAP *bmp, BITMAP *parent);
00030 void split_color(int color, GLubyte *r, GLubyte *g, GLubyte *b, GLubyte *a,
00031         int color_depth);
00032 void allegro_gl_screen_blit_to_self (struct BITMAP *source, struct BITMAP *dest,
00033         int source_x, int source_y, int dest_x, int dest_y, int width,
00034         int height);
00035 void allegro_gl_video_blit_from_memory(struct BITMAP *source,
00036         struct BITMAP *dest, int source_x, int source_y, int dest_x,
00037         int dest_y, int width, int height);
00038 void allegro_gl_video_blit_to_memory(struct BITMAP *source, struct BITMAP *dest,
00039         int source_x, int source_y, int dest_x, int dest_y, int width,
00040         int height);
00041 void do_masked_blit_screen(struct BITMAP *source, struct BITMAP *dest,
00042         int source_x, int source_y, int dest_x, int dest_y, int width, int height,
00043         int flip_dir, int blit_type);
00044 void allegro_gl_video_blit_to_self(struct BITMAP *source, struct BITMAP *dest,
00045         int source_x, int source_y, int dest_x, int dest_y, int width, int height);
00046 void allegro_gl_screen_clear_to_color(struct BITMAP *bmp, int color);
00047 void allegro_gl_upload_and_display_texture(struct BITMAP *source,
00048         int source_x, int source_y, int dest_x, int dest_y, int width, int height,
00049         int flip_dir, GLint format, GLint type);
00050 void allegro_gl_screen_draw_glyph_ex(struct BITMAP *bmp,
00051         AL_CONST struct FONT_GLYPH *glyph, int x, int y,
00052         int color, int bg, int flip);
00053 void allegro_gl_screen_draw_color_glyph_ex(struct BITMAP *bmp,
00054         struct BITMAP *sprite, int x, int y, int color, int bg, int flip);
00055 void allegro_gl_screen_polygon3d_f(struct BITMAP *bmp, int type,
00056                                    struct BITMAP *texture, int vc,
00057                                    V3D_f *vtx[]);
00058 #endif
00059 
allegro4.4-4.4.2/addons/allegrogl/docs/html/group__Text.html000066400000000000000000001452101173507505700237120ustar00rootroot00000000000000 AllegroGL: Text drawing and fonts.

Text drawing and fonts.

AllegroGL now provides mechanisms for converting Allegro FONTs to a format which is more usable in OpenGL. More...

Text Drawing and Font conversion


Detailed Description

AllegroGL now provides mechanisms for converting Allegro FONTs to a format which is more usable in OpenGL.

You can also load system fonts (such as Arial and Courrier) and draw using those. Allegro FONTs should still work if you use textout, textprintf, etc on them. However, converted Allegro FONTs will not work with these functions. You will have to use AllegroGL functions to work with AllegroGL FONTs.


Define Documentation

#define AGL_FONT_TYPE_DONT_CARE   -1

Indicates that you don't really care how a font will be converted.

AGL will pick the best format for you.

Definition at line 618 of file alleggl.h.

Referenced by allegro_gl_convert_allegro_font_ex().

#define AGL_FONT_TYPE_BITMAP   0

Indicates that you want fonts to be converted to a bitmap format.

Bitmaps are used to represent characters with one bit per pixel, and are usually very slow to draw, as they stall the 3D pipeline. Note that you can't scale, rotate or place text with a z coordinate if you use this style. A display list will be created.

See also:
allegro_gl_convert_allegro_font(), allegro_gl_printf()

Definition at line 629 of file alleggl.h.

Referenced by allegro_gl_convert_allegro_font_ex(), allegro_gl_destroy_font(), and allegro_gl_printf_ex().

#define AGL_FONT_TYPE_OUTLINE   1

Indicates that you want fonts to be converted to an outline format.

Outlined mode is a vector-style font. Characters are represented by a set of polygons and lines. This style of fonts is fast to draw, and can be scaled, rotated, etc, since they are just vectors. A display list will be created.

Deprecated:
Non-textured fonts will be dropped from AllegroGL.
See also:
allegro_gl_convert_allegro_font(), allegro_gl_printf()

Definition at line 641 of file alleggl.h.

Referenced by allegro_gl_convert_allegro_font_ex(), allegro_gl_destroy_font(), allegro_gl_load_system_font(), and allegro_gl_printf_ex().

#define AGL_FONT_TYPE_TEXTURED   2

Indicates that you want fonts to be converted to a texture format.

Each character is represented by a textured quad. The texture is common for all characters of the same font, and it will automatically be uploaded to the video card when needed. Drawing text with this type of font is the fastest since only two triangles are needed per character. Textured text can also be scaled and rotated. A display list will be created.

See also:
allegro_gl_convert_allegro_font(), allegro_gl_printf()

Definition at line 653 of file alleggl.h.

Referenced by allegro_gl_convert_allegro_font_ex(), allegro_gl_destroy_font(), and allegro_gl_printf_ex().

#define AGL_FONT_STYLE_BOLD   1

Creates a font with bold characters.

System fonts only.

Deprecated:
Non-textured fonts will be dropped from AllegroGL

Definition at line 661 of file alleggl.h.

#define AGL_FONT_STYLE_BLACK   2

Creates a font with black (strong bold) characters.

System fonts only.

Deprecated:
Non-textured fonts will be dropped from AllegroGL.

Definition at line 666 of file alleggl.h.

#define AGL_FONT_STYLE_ITALIC   4

Creates a font with italicized characters.

System fonts only.

Deprecated:
Non-textured fonts will be dropped from AllegroGL.

Definition at line 671 of file alleggl.h.

#define AGL_FONT_STYLE_UNDERLINE   8

Creates a font with underlined characters.

System fonts only.

Deprecated:
Non-textured fonts will be dropped from AllegroGL.

Definition at line 676 of file alleggl.h.

#define AGL_FONT_STYLE_STRIKEOUT   16

Creates a font with striked out characters.

System fonts only.

Deprecated:
Non-textured fonts will be dropped from AllegroGL.

Definition at line 681 of file alleggl.h.

#define AGL_FONT_STYLE_ANTI_ALIASED   32

Creates a font with anti-aliased characters.

System fonts only. Anti-aliasing may not be available, and no error will be reported if such is the case.

Deprecated:
Non-textured fonts will be dropped from AllegroGL.

Definition at line 688 of file alleggl.h.

#define AGL_FONT_POLYGONS   1

Font generation mode.

System fonts only. Indicates that you want outline system fonts to be generated using polygons.

Deprecated:
Non-textured fonts will be dropped from AllegroGL.
See also:
allegro_gl_load_system_font(), allegro_gl_load_system_font_ex()

Definition at line 696 of file alleggl.h.

#define AGL_FONT_LINES   2

Font generation mode.

System fonts only. Indicates that you want outline system fonts to be generated using lines.

Deprecated:
Non-textured fonts will be dropped from AllegroGL.
See also:
allegro_gl_load_system_font(), allegro_gl_load_system_font_ex()

Definition at line 705 of file alleggl.h.


Function Documentation

int allegro_gl_printf ( AL_CONST FONT *  f,
float  x,
float  y,
float  z,
int  color,
AL_CONST char *  format,
  ... 
)

Equivalent to:

   r = getr(color);
   g = getg(color);
   b = getb(color);
   a = geta(color);
   glColor4f(r, g, b, a);
   allegro_gl_printf_ex(f, x, y, z,
                        format, ...);
  

Note that the current primary color is not preserved.

Definition at line 67 of file aglf.c.

References allegro_gl_printf_ex().

int allegro_gl_printf_ex ( AL_CONST FONT *  f,
float  x,
float  y,
float  z,
AL_CONST char *  format,
  ... 
)

Prints a formatted string (printf style) on the screen.

Parameters:
fWhich font to use.
x,y,zCoordinates to print at. They specify the top-left corner of the text position.
formatThe format string (see printf() for details)

For bitmap fonts, the raster position is set to (x,y), 'z' is ignored. The current modelview matrix applies to this code so you may want to use glLoadIdentity() beforehand. On the other hand, you can use the modelview matrix to apply transformations to the text. This will only work with textured or vector (outline) fonts. This function only accepts AllegroGL formated fonts, as converted by allegro_gl_convert_allegro_font(), or loaded by allegro_gl_load_system_font() or allegro_gl_load_system_font_ex().

Texturing must be enabled for this function to work with AGL_FONT_TYPE_TEXTURED fonts.

Remember to use glEnable(GL_TEXTURE_2D) to enable texturing.

The resulting size may not be what you expect. For bitmaped fonts, there is nothing you can do about this appart changing the font itself. Textured and Vector fonts are more flexible, in that you can use glScale to adjust the size of the characters.

If you need to draw the text without the black backround, we suggest you set up a proper blending mode prior to drawing the text, such as:

     glEnable(GL_BLEND);
     glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_COLOR);
   

If you want to emulate the Allegro drawing mode (no blending at all), then you should use the folowing code instead:

     glDisable(GL_DEPTH_TEST);
     glEnable(GL_BLEND);
     glBlendFunc(GL_DST_COLOR, GL_ZERO);
     allegro_gl_printf();
     glBlendFunc(GL_ONE, GL_ONE);
     allegro_gl_printf();    // Same as the one above!
     glEnable(GL_DEPTH_TEST);
   

Have a look at NeHe's Tutorial #20 for details on this technique. http://nehe.gamedev.net/

The most flexible way to use fonts, though, is to use alpha textures based on a greyscale font. Set the texture format to GL_ALPHA4 or GL_ALPHA8 before creating the (textured) font. Then you can set the colour and blend modes like so:

    glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    allegro_gl_printf_ex(my_font, x, y, z, "Hi!")
  
Returns:
The number of characters printed.

Definition at line 169 of file aglf.c.

References AGL_FONT_TYPE_BITMAP, AGL_FONT_TYPE_OUTLINE, and AGL_FONT_TYPE_TEXTURED.

Referenced by allegro_gl_printf().

FONT* allegro_gl_convert_allegro_font ( FONT *  f,
int  type,
float  scale 
)

Equivalent to:

   allegro_gl_convert_allegro_font_ex(f, type, scale, format_state);
 

Where format_state is the last specified format to allegro_gl_set_texture_format(). If allegro_gl_set_texture_format() was not previously called, AllegroGL will try to determine the texture format automatically.

Deprecated:

Definition at line 623 of file fontconv.c.

References allegro_gl_convert_allegro_font_ex(), and allegro_gl_get_texture_format().

FONT* allegro_gl_convert_allegro_font_ex ( FONT *  f,
int  type,
float  scale,
GLint  format 
)

Converts a regular Allegro FONT to the AGL format for 3D display.

Parameters:
fThe Allegro font to convert.
typeThe font type to convert to. (see AGL_FONT_TYPE_DONT_CARE, AGL_FONT_TYPE_BITMAP, AGL_FONT_TYPE_TEXTURED)
scaleThe scaling factor (see below).
formatThe texture internal format to use.

This function will build a texture map and/or a display list that will be automatically uploaded to the video card. You can only convert to bitmap or textured fonts.

You can't convert an Allegro font to a vector font (AGL_FONT_TYPE_OUTLINE) as the logistics of such an operation are quite complex. The original font will NOT be modified.

A valid OpenGL rendering context is required, so you may only call this function after a successful call to set_gfx_mode() with a valid OpenGL mode.

You should destroy the font via allegro_gl_destroy_font() when you are done with it.

Scaling

For AGL_FONT_TYPE_TEXTURED fonts, glyphs in the font need to be mapped to OpenGL coordinates. The scale factor ensures that you get the scaling you need. scale reprents the number of pixels to be mapped to 1.0 OpenGL units. For allegro_gl_convert_font() to behave like AllegroGL 0.0.24 and earlier, you'll need to pass 16.0 as the scale factor.

Alternativaly, you can make all your fonts be 1.0 units high by using:

   allegro_gl_convert_allegro_font(f, AGL_FONT_TYPE_TEXTURED, 1.0/text_height(f));
  

Note that it is allowed for the scaling factor to be negative, in case your fonts appear upside down.

If you are planning to use your fonts on an orthographic projection where one unit maps to one pixel, then you should pass 1.0 as scale.

The scaling factor has no meaning for AGL_FONT_TYPE_BITMAP fonts, so it's ignored if the conversion will lead to a font of that type.

Format

The format specifies what internal format OpenGL should use for the texture, in the case of AGL_FONT_TYPE_TEXTURED fonts. It has the same semantics as the internalformat parameter of glTexImage2D(). If you would like for AllegroGL to pick a texture format for you, you may supply -1 as the texture format. The default format for monochrome fonts is GL_INTENSITY4. The default format for colored fonts is GL_RGB8.

Returns:
The converted font, or NULL on error.

Definition at line 688 of file fontconv.c.

References AGL_FONT_TYPE_BITMAP, AGL_FONT_TYPE_DONT_CARE, AGL_FONT_TYPE_OUTLINE, AGL_FONT_TYPE_TEXTURED, AGL_TEXTURE_ALPHA_ONLY, AGL_TEXTURE_FLIP, AGL_TEXTURE_HAS_ALPHA, AGL_TEXTURE_MASKED, AGL_TEXTURE_MIPMAP, allegro_gl_check_texture_ex(), and allegro_gl_make_texture_ex().

Referenced by allegro_gl_convert_allegro_font().

void allegro_gl_set_font_generation_mode ( int  mode)

Set the font generation mode for system fonts.

Note: This function is deprecated and will be removed in a future version.

Parameters:
modeCan be either AGL_FONT_POLYGONS or AGL_FONT_LINES. for creating polygonal or line characters. Default is AGL_FONT_POLYGONS.

Subsequent calls to allegro_gl_load_system_font() and allegro_gl_load_system_font_ex() may be affected by this function.

Deprecated:

Definition at line 469 of file aglf.c.

FONT* allegro_gl_load_system_font ( char *  name,
int  style,
int  w,
int  h 
)

Short hand for aglf_load_system_font_ex(name, AGL_FONT_TYPE_OUTLINE, style, w, h, 0.0f, 32, 256)

Note: This function is deprecated and will be removed in a future version.

Deprecated:

Definition at line 485 of file aglf.c.

References AGL_FONT_TYPE_OUTLINE, and allegro_gl_load_system_font_ex().

FONT* allegro_gl_load_system_font_ex ( char *  name,
int  type,
int  style,
int  w,
int  h,
float  depth,
int  start,
int  end 
)

Loads a system font.

Note: This function is deprecated and will be removed in a future version.

Parameters:
nameThe name of the system font ("Courrier" or "Arial" for example)
typeThe font type to generate (AGL_FONT_TYPE_DONT_CARE, AGL_FONT_TYPE_BITMAP, AGL_FONT_TYPE_OUTLINE)
styleThe text decorations of the font to create (AGL_FONT_STYLE_ITALIC, etc - can be or'ed together)
w,hThe size of the font characters that will be created.
depthThe z-depth of the font. 0.0f is flat, 1.0f is very thick
start,endThe range of characters to create from 'start' (included) to 'end' (excluded) in UTF-8 format (ANSI only on Windows).
Note:
  • In AGL_FONT_TYPE_OUTLINE type, some system fonts seem to be unresponsive to the size paramaters (w and h). You cannot depend on either a system font being present, or the font being what you expect - it is possible to have two fonts with the same name but with different graphic data.
  • BITMAP fonts have no depth.
  • The width and height parameters are also system dependent, and may or may not work with the selected font.
Returns:
The loaded font, or NULL on error.
Deprecated:

Definition at line 526 of file aglf.c.

Referenced by allegro_gl_load_system_font().

void allegro_gl_destroy_font ( FONT *  f)

void allegro_gl_destroy_font(FONT *usefont)

Destroys the font.

Parameters:
fThe AGL font to be destroyed.

The allocated memory is freed, as well as any display list, or texture objects it uses.

You cannot use that font anymore after calling this function. It's safe to call this function with a NULL pointer; a note will be placed in allegro.log if DEBUGMODE was defined.

If NULL is passed as the font to destroy, then this function returns immediately.

Definition at line 573 of file aglf.c.

References AGL_FONT_TYPE_BITMAP, AGL_FONT_TYPE_OUTLINE, and AGL_FONT_TYPE_TEXTURED.

size_t allegro_gl_list_font_textures ( FONT *  f,
GLuint *  ids,
size_t  max_num_id 
)

List the texture ID of all textures forming the specified font.

The font specified must be an AllegroGL font.

If ids is not NULL, then the ID numbers of all textures used by the font are written to the GLuint array pointed by ids. The size of that array is specified by the max_num_id parameter. This function will never write more than 'max_num_id' values in the ids array.

If f is NULL, then zero is returned and the ids array is never touched.

If the font does not contain any textures (because it is a bitmap or outline font, for example), then zero is returned.

Returns:
Number of texture IDs that make up this font.

Here are two examples of the use of this function:

   int num_ids = allegro_gl_list_font_textures(font, NULL, 0);
   GLuint *id = malloc(sizeof(GLuint) * num_ids);
   if (!id) {
     //handle error
   }
   allegro_gl_list_font_textures(font, id, num_ids);
   for (i = 0; i < num_ids; i++) {
       glBindTexture(GL_TEXTURE_2D, id[i]);
       // Use this texture
   }
   free(id);
 
   GLint id[10];  // Reserve a safe number
   GLint num_ids = allegro_gl_list_font_textures(font, id, 10);
 

Definition at line 689 of file aglf.c.

allegro4.4-4.4.2/addons/allegrogl/docs/html/group__allegro.html000066400000000000000000000347761173507505700244310ustar00rootroot00000000000000 AllegroGL: Allegro Interfacing

Allegro Interfacing

Allegro Interfacing routines


Function Documentation

void allegro_gl_set_allegro_mode ( void  )

Prepares for Allegro drawing to the screen.

Since AllegroGL actually calls OpenGL commands to perform Allegro functions for 2D drawing, some OpenGL capabilities may interfer with those operations In order to obtain the expected results, allegro_gl_set_allegro_mode() must be called to disable the depth test, texturing, fog and lighting and set the view matrices to an appropriate state. Call allegro_gl_unset_allegro_mode() to restore OpenGL in its previous state.

You should encapsulate all Allegro code dealing with the screen in between allegro_gl_set_allegro_mode() and allegro_gl_unset_allegro_mode().

If you need to use regular OpenGL commands in between, you may do so, but you can get unexpected results. This is generally not recommended. You should first call allegro_gl_unset_allegro_mode() to restore the original OpenGL matrices. After that, you may freely call any OpenGL command. Don't forget to call back allegro_gl_set_allegro_mode() to switch back to Allegro commands.

AllegroGL saves the current OpenGL state with glPushAttrib so you should make sure that at least one level is available in the attribute stack otherwise the next call to allegro_gl_unset_allegro_mode() may fail.

Also note that allegro_gl_set_allegro_mode() implicitely calls allegro_gl_set_projection() so you do not need to do it yourself.

See also:
allegro_gl_unset_allegro_mode() allegro_gl_set_projection()
allegro_gl_unset_projection()

Definition at line 2422 of file glvtable.c.

References allegro_gl_set_projection().

Referenced by algl_do_dialog(), algl_popup_dialog(), and d_algl_viewport_proc().

void allegro_gl_unset_allegro_mode ( void  )

Restores previous OpenGL settings.

Restores the OpenGL state that have saved during the last call of allegro_gl_set_allegro_mode().

Note that allegro_gl_unset_allegro_mode implicitely calls allegro_gl_unset_projection() so you do not need to do it yourself.

See also:
allegro_gl_set_allegro_mode() allegro_gl_set_projection()
allegro_gl_unset_projection()

Definition at line 2491 of file glvtable.c.

References AGL_KEEP, AGL_RELEASE, and allegro_gl_unset_projection().

Referenced by algl_do_dialog(), algl_popup_dialog(), and d_algl_viewport_proc().

void allegro_gl_set_projection ( void  )

Prepares for Allegro drawing to the screen.

This function sets the OpenGL projection and modelview matrices so that 2D OpenGL coordinates match the usual Allegro coordinate system.

OpenGL uses a completely different coordinate system than Allegro. So to be able to use Allegro operations on the screen, you first need to properly set up the OpenGL projection and modelview matrices. AllegroGL provides this set of functions to allow proper alignment of OpenGL coordinates with their Allegro counterparts.

Since AllegroGL actually calls OpenGL commands to perform Allegro functions for 2D drawing, some OpenGL capabilities such as texturing or depth testing may interfer with those operations. In order to prevent such inconveniences, you should call allegro_gl_set_allegro_mode() instead of allegro_gl_set_projection()

allegro_gl_set_projection() and allegro_gl_unset_projection() are not nestable, which means that you should not call allegro_gl_set_projection() inside another allegro_gl_set_projection() block. Similarly for allegro_gl_unset_projection().

Have a look at examp/exalleg.c for an example of combining Allegro drawing commands and OpenGL.

See also:
allegro_gl_unset_projection() allegro_gl_set_allegro_mode()
allegro_gl_unset_allegro_mode()

Definition at line 2540 of file glvtable.c.

Referenced by allegro_gl_set_allegro_mode().

void allegro_gl_unset_projection ( void  )

Restores previously saved projection.

This function returns the projection and modelview matrices to their state before the last allegro_gl_set_projection() was called.

See also:
allegro_gl_set_projection() allegro_gl_set_allegro_mode()
allegro_gl_unset_allegro_mode()

Definition at line 2567 of file glvtable.c.

Referenced by allegro_gl_unset_allegro_mode().

allegro4.4-4.4.2/addons/allegrogl/docs/html/group__bitmap.html000066400000000000000000000103651173507505700242440ustar00rootroot00000000000000 AllegroGL: Bitmap Routines

Bitmap Routines

AllegroGL provides a function to set color depth for video bitmaps. More...

Video Bitmap Rountines


Detailed Description

AllegroGL provides a function to set color depth for video bitmaps.


Function Documentation

GLint allegro_gl_set_video_bitmap_color_depth ( int  bpp)

Sets the color depth you'd like AllegroGL to use for video bitmaps.

This function lets you create video bitmaps of any color depth using allegro's create_video_bitmap(). You can create a RGBA8 bitmap and take advantage of hardware accelerated blending, no matter what the current color depth is. This call will affect all subsequent calls to create_video_bitmap().

Default value for the video bitmap color depth if the color depth of the screen bitmap. To revert to the default color depth, pass -1.

Parameters:
bppColor depth in btis per pixel.
Returns:
The previous value of the video bitmap color depth.

Definition at line 423 of file videovtb.c.

allegro4.4-4.4.2/addons/allegrogl/docs/html/group__core.html000066400000000000000000000275751173507505700237330ustar00rootroot00000000000000 AllegroGL: Core routines

Core routines

Basic AllegroGL functions. More...

Functions

Core Functions

  • #define allegro_gl_begin()   ;
    Backward compatibility #define for programs written prior to AGL 0.0.22.
  • #define allegro_gl_end()   ;
    Backward compatibility #define for programs written prior to AGL 0.0.22.

Detailed Description

Basic AllegroGL functions.

These functions allow you to initialize AllegroGL, set up a rendering context via set_gfx_mode(), and allow access to regular OpenGL functions.


Define Documentation

#define allegro_gl_begin ( )    ;

Backward compatibility #define for programs written prior to AGL 0.0.22.

It isn't defined as anything meaningful, so you don't need to put them in your program.

See also:
allegro_gl_end()

Definition at line 166 of file alleggl.h.

#define allegro_gl_end ( )    ;

Backward compatibility #define for programs written prior to AGL 0.0.22.

It isn't defined as anything meaningful, so you don't need to put them in your program.

See also:
allegro_gl_begin()

Definition at line 176 of file alleggl.h.


Function Documentation

int install_allegro_gl ( void  )

Installs the AllegroGL addon to Allegro.

Allegro should already be initialized with allegro_init() or install_allegro().

Returns:
0 on success; -1 on failure.
See also:
remove_allegro_gl()

Definition at line 836 of file alleggl.c.

References allegro_gl_clear_settings(), and remove_allegro_gl().

void remove_allegro_gl ( void  )

Removes the AllegroGL addon.

You should not call any more OpenGL or AllegroGL functions after calling this function. Note that it will be called automatically at program exit, so you don't need to explicitly do it.

See also:
install_allegro_gl()

Definition at line 894 of file alleggl.c.

Referenced by install_allegro_gl().

void allegro_gl_flip ( void  )

Flips the front and back framebuffers.

If you chose, or were given, a double buffered OpenGL mode, you have access to a front buffer, which is visible on the screen, and also a back buffer, which is not visible. This routine flips the buffers, so that the contents of the back buffer is now the contents of the (visible) front buffer. The contents of the backbuffer is undefined after the operation.

Normally in these modes you would do all your drawing to the back buffer, without the user seeing the image while it's partially drawn, and then call this function to flip the buffers, allowing the user to see what you've drawn, now that it's finished, while you proceed to draw the next frame.

When drawing to the screen bitmap, you may not be drawing to what user currently sees on his monitor. It is recommended that you rebuild the screen every frame, then flip, then draw again.

See also:
allegro_gl_set(), AGL_DOUBLEBUFFER

Definition at line 951 of file alleggl.c.

Referenced by algl_popup_dialog(), and d_algl_viewport_proc().

float allegro_gl_opengl_version ( void  )

Returns the OpenGL version number of the client (the computer the program is running on).

"1.0" is returned as 1.0, "1.2.1" is returned as 1.21, and "1.2.2" as 1.22, etc.

A valid OpenGL context must exist for this function to work, which means you may not call it before set_gfx_mode(GFX_OPENGL)

Returns:
The OpenGL ICD/MCD version number.

Definition at line 971 of file alleggl.c.

allegro4.4-4.4.2/addons/allegrogl/docs/html/group__extensions.html000066400000000000000000000271561173507505700251750ustar00rootroot00000000000000 AllegroGL: OpenGL Extensions

OpenGL Extensions

Management of the OpenGL extensions mechanism. More...

Functions

Variables

OpenGL Extensions Management Functions


Detailed Description

Management of the OpenGL extensions mechanism.

AllegroGL provides two ways to access OpenGL extensions: It's native extension library and some versatile portable routines.

If you want to get more control on extensions or if you want to use an extension that is not supported by AllegroGL then you can use the routines : allegro_gl_is_extension_supported() and allegro_gl_get_proc_address(). They provide a way to determine if an extension is available and to get its address. These routines are available on every platforms that AllegroGL supports


Define Documentation

#define AGL_DEFINE_PROC_TYPE

OpenGL extensions handlers helper.

Defines a function pointer type. This macro is almost equivalent to a typedef. It is intended to hide some platform-specific machinery in order to keep code portable.

See also:
allegro_gl_get_proc_address()

Definition at line 751 of file alleggl.h.


Function Documentation

int allegro_gl_is_extension_supported ( AL_CONST char *  extension)

This function is an helper to determine whether an OpenGL extension is available or not.

Example:

       int packedpixels =
                  allegro_gl_is_extension_supported("GL_EXT_packed_pixels");
    

If packedpixels is TRUE then you can safely use the constants related to the packed pixels extension.

Parameters:
extensionThe name of the extension that is needed
Returns:
TRUE if the extension is available FALSE otherwise.

Definition at line 306 of file glext.c.

void* allegro_gl_get_proc_address ( AL_CONST char *  name)

Helper to get the address of an OpenGL symbol.

Example: How to get the function glMultiTexCoord3fARB that comes with ARB's Multitexture extension :

  // define the type of the function
	AGL_DEFINE_PROC_TYPE(void, MULTI_TEX_FUNC,
	                                      (GLenum, GLfloat, GLfloat, GLfloat));
  // declare the function pointer
	MULTI_TEX_FUNC glMultiTexCoord3fARB;
  // get the address of the function
 	glMultiTexCoord3fARB = (MULTI_TEX_FUNC) allegro_gl_get_proc_address(
 	                                                   "glMultiTexCoord3fARB");
    

If glMultiTexCoord3fARB is not NULL then it can be used as if it has been defined in the OpenGL core library. Note that the use of the AGL_DEFINE_PROC_TYPE macro is mandatory if you want your program to be portable.

Parameters:
nameThe name of the symbol you want to link to.
Returns:
A pointer to the symbol if available or NULL otherwise.

Definition at line 372 of file glext.c.


Variable Documentation

struct AGL_EXTENSION_LIST_GL allegro_gl_extensions_GL

List of OpenGL extensions supported by AllegroGL.

Each entry of this structure is an int which is either set to 1, if the corresponding extension is available on the host system, or 0 otherwise.

Extension names use only the base name. For example, GL_ARB_multitexture should be refered to by:

   allegro_gl_extensions_GL.ARB_multitexture
  
See also:
allegro_gl_extensions_GLX allegro_gl_extensions_WGL

Definition at line 55 of file glext.c.

Referenced by allegro_gl_make_texture_ex().

AGL_EXT* agl_extension_table = NULL

List of GLX extensions supported by AllegroGL.

See also:
allegro_gl_extensions_GL allegro_gl_extensions_WGL List of WGL OpenGL Extensions supported by AllegroGL.
allegro_gl_extensions_GL allegro_gl_extensions_GLX

Definition at line 82 of file glext.c.

allegro4.4-4.4.2/addons/allegrogl/docs/html/group__gfxdrv.html000066400000000000000000000054561173507505700242750ustar00rootroot00000000000000 AllegroGL: Graphics drivers

Graphics drivers

Use set_gfx_mode to select an OpenGL mode as normal, but using e.g. More...

Use set_gfx_mode to select an OpenGL mode as normal, but using e.g.

GFX_OPENGL as the driver. The virtual width and height are ignored. To set the colour depth, use allegro_gl_set (AGL_COLOR_DEPTH, xxx). However if the color depth is not set by allegro_gl_set(), AllegroGL will refer to the value set by the last call to set_color_depth().

Allegro modes are still available. Use of GFX_AUTODETECT or GFX_AUTODETECT_WINDOWED will select Allegro modes, and not OpenGL modes.

allegro4.4-4.4.2/addons/allegrogl/docs/html/group__glvtable.html000066400000000000000000000735051173507505700245750ustar00rootroot00000000000000 AllegroGL: Allegro Graphics Driver

Allegro Graphics Driver

These functions are used to implement Allegro function over an OpenGL screen. More...

Defines

  • #define SET_TEX_COORDS(x, y)
  • #define BITMAP_BLIT_CLIP(source, dest, source_x, source_y, dest_x, dest_y, width, height)

Functions

  • int __allegro_gl_make_power_of_2 (int x)
  • void allegro_gl_drawing_mode (void)
  • void split_color (int color, GLubyte *r, GLubyte *g, GLubyte *b, GLubyte *a, int color_depth)
  • void allegro_gl_created_sub_bitmap (BITMAP *bmp, BITMAP *parent)
  • static void allegro_gl_screen_acquire (struct BITMAP *bmp)
    acquire_bitmap(screen) overload.
  • static void allegro_gl_screen_release (struct BITMAP *bmp)
    release_bitmap(screen) overload.
  • static int allegro_gl_screen_getpixel (struct BITMAP *bmp, int x, int y)
  • static void allegro_gl_screen_putpixel (struct BITMAP *bmp, int x, int y, int color)
  • static void allegro_gl_screen_vline (struct BITMAP *bmp, int x, int y1, int y2, int color)
  • static void allegro_gl_screen_hline (struct BITMAP *bmp, int x1, int y, int x2, int color)
  • static void allegro_gl_screen_line (struct BITMAP *bmp, int x1, int y1, int x2, int y2, int color)
  • void allegro_gl_screen_rectfill (struct BITMAP *bmp, int x1, int y1, int x2, int y2, int color)
  • static void allegro_gl_screen_triangle (struct BITMAP *bmp, int x1, int y1, int x2, int y2, int x3, int y3, int color)
  • static void allegro_gl_screen_blit_from_memory (struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)
  • static void allegro_gl_screen_blit_to_memory (struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)
  • void allegro_gl_screen_blit_to_self (struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)
  • void allegro_gl_upload_and_display_texture (struct BITMAP *source, int source_x, int source_y, int dest_x, int dest_y, int width, int height, int flip_dir, GLint format, GLint type)
  • static void do_screen_masked_blit_standard (GLint format, GLint type, struct BITMAP *temp, int source_x, int source_y, int dest_x, int dest_y, int width, int height, int flip_dir, int blit_type)
  • static void screen_masked_blit_standard (struct BITMAP *source, int source_x, int source_y, int dest_x, int dest_y, int width, int height, int flip_dir, int blit_type)
  • static void __allegro_gl_init_nv_register_combiners (BITMAP *bmp)
  • static void screen_masked_blit_nv_register (struct BITMAP *source, int source_x, int source_y, int dest_x, int dest_y, int width, int height, int flip_dir, int blit_type)
  • static void __allegro_gl_init_combine_textures (BITMAP *bmp)
  • static void screen_masked_blit_combine_tex (struct BITMAP *source, int source_x, int source_y, int dest_x, int dest_y, int width, int height, int flip_dir, int blit_type)
  • void do_masked_blit_screen (struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height, int flip_dir, int blit_type)
  • static BITMAP * __allegro_gl_convert_rle_sprite (AL_CONST struct RLE_SPRITE *sprite, int trans)
  • void allegro_gl_screen_draw_rle_sprite (struct BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y)
  • static void allegro_gl_screen_draw_trans_rgba_rle_sprite (struct BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y)
  • static void allegro_gl_screen_masked_blit (struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)
  • static void allegro_gl_screen_draw_sprite (struct BITMAP *bmp, struct BITMAP *sprite, int x, int y)
  • static void allegro_gl_screen_draw_sprite_v_flip (struct BITMAP *bmp, struct BITMAP *sprite, int x, int y)
  • static void allegro_gl_screen_draw_sprite_h_flip (struct BITMAP *bmp, struct BITMAP *sprite, int x, int y)
  • static void allegro_gl_screen_draw_sprite_vh_flip (struct BITMAP *bmp, struct BITMAP *sprite, int x, int y)
  • static void allegro_gl_screen_pivot_scaled_sprite_flip (struct BITMAP *bmp, struct BITMAP *sprite, fixed x, fixed y, fixed cx, fixed cy, fixed angle, fixed scale, int v_flip)
  • static void allegro_gl_screen_draw_trans_rgba_sprite (struct BITMAP *bmp, struct BITMAP *sprite, int x, int y)
  • static void allegro_gl_screen_draw_sprite_ex (struct BITMAP *bmp, struct BITMAP *sprite, int x, int y, int mode, int flip)
  • void allegro_gl_screen_draw_glyph_ex (struct BITMAP *bmp, AL_CONST struct FONT_GLYPH *glyph, int x, int y, int color, int bg, int flip)
  • static void allegro_gl_screen_draw_glyph (struct BITMAP *bmp, AL_CONST struct FONT_GLYPH *glyph, int x, int y, int color, int bg)
  • void allegro_gl_screen_draw_color_glyph_ex (struct BITMAP *bmp, struct BITMAP *sprite, int x, int y, int color, int bg, int flip)
  • static void allegro_gl_screen_draw_color_glyph (struct BITMAP *bmp, struct BITMAP *sprite, int x, int y, int color, int bg)
  • static void allegro_gl_screen_draw_character (struct BITMAP *bmp, struct BITMAP *sprite, int x, int y, int color, int bg)
  • static void allegro_gl_screen_draw_256_sprite (struct BITMAP *bmp, struct BITMAP *sprite, int x, int y)
  • void allegro_gl_screen_clear_to_color (struct BITMAP *bmp, int color)
  • static void allegro_gl_screen_polygon (struct BITMAP *bmp, int vertices, AL_CONST int *points, int color)
  • static void allegro_gl_screen_rect (struct BITMAP *bmp, int x1, int y1, int x2, int y2, int color)
  • void allegro_gl_screen_polygon3d_f (struct BITMAP *bmp, int type, struct BITMAP *texture, int vc, V3D_f *vtx[])
  • static void allegro_gl_screen_polygon3d (struct BITMAP *bmp, int type, struct BITMAP *texture, int vc, V3D *vtx[])
  • static void allegro_gl_screen_quad3d_f (struct BITMAP *bmp, int type, struct BITMAP *texture, V3D_f *v1, V3D_f *v2, V3D_f *v3, V3D_f *v4)
  • static void allegro_gl_screen_quad3d (struct BITMAP *bmp, int type, struct BITMAP *texture, V3D *v1, V3D *v2, V3D *v3, V3D *v4)
  • static void allegro_gl_screen_triangle3d (struct BITMAP *bmp, int type, struct BITMAP *texture, V3D *v1, V3D *v2, V3D *v3)
  • static void allegro_gl_screen_triangle3d_f (struct BITMAP *bmp, int type, struct BITMAP *texture, V3D_f *v1, V3D_f *v2, V3D_f *v3)
  • void __allegro_gl__glvtable_update_vtable (GFX_VTABLE **vtable)
  • void allegro_gl_memory_blit_between_formats (struct BITMAP *src, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)
  • static void dummy_unwrite_bank (void)
  • static void allegro_gl_video_acquire (struct BITMAP *bmp)
    acquire_bitmap(bmp) overload.
  • static void allegro_gl_video_release (struct BITMAP *bmp)
    release_bitmap(bmp) overload.

Variables

  • static double allegro_gl_projection_matrix [16]
  • static double allegro_gl_modelview_matrix [16]
  • static GFX_VTABLE allegro_gl_screen_vtable

Detailed Description

These functions are used to implement Allegro function over an OpenGL screen.

Keep in mind that some restictions mentioned in Allegro docs about video bitmaps and the screen do not apply when using AllegroGL GFX driver. Namely:

  • Reading from video bitmaps is just as fast as reading from memory bitmaps.
  • Doing translucent/transparent drawing on the screen can be very fast if the source is a video bitmap.
  • Drawing from video bitmap to a video bitmap will be pretty fast on modern GFX cards with appropiate drivers installed.
  • There are dozen of places in the Allegro docs where it says that a memory bitmap must be used (drawing_mode(), polygon3d(), stretch_sprite() etc.). This doesn't apply when AllegroGL is used. You can also use video bitmaps and it will be quite fast.

Define Documentation

#define SET_TEX_COORDS (   x,
 
)
Value:
do {                      \
        if (__agl_drawing_pattern_tex) {  \
            glTexCoord2f (                \
                (x - _drawing_x_anchor) / (float)__agl_drawing_pattern_bmp->w,\
                (y - _drawing_y_anchor) / (float)__agl_drawing_pattern_bmp->h \
            );                                                                \
        }                                                                     \
    } while(0)

Definition at line 348 of file glvtable.c.


Function Documentation

static void allegro_gl_screen_acquire ( struct BITMAP *  bmp) [static]

acquire_bitmap(screen) overload.

This doesn't do anything, since OpenGL rendering context doesn't need locking. You don't need to call this function in your program.

Definition at line 160 of file glvtable.c.

static void allegro_gl_screen_release ( struct BITMAP *  bmp) [static]

release_bitmap(screen) overload.

This doesn't do anything, since OpenGL rendering context doesn't need locking. You don't need to call this function in your program.

Definition at line 170 of file glvtable.c.

static void allegro_gl_video_acquire ( struct BITMAP *  bmp) [static]

acquire_bitmap(bmp) overload.

This doesn't do anything, since OpenGL textures doesn't need locking. You don't need to call this function in your program.

Definition at line 437 of file videovtb.c.

static void allegro_gl_video_release ( struct BITMAP *  bmp) [static]

release_bitmap(bmp) overload.

This doesn't do anything, since OpenGL textures doesn't need locking. You don't need to call this function in your program.

Definition at line 448 of file videovtb.c.

allegro4.4-4.4.2/addons/allegrogl/docs/html/group__gui.html000066400000000000000000000566571173507505700235720ustar00rootroot00000000000000 AllegroGL: Allegro-compatible GUI routines

Allegro-compatible GUI routines

AllegroGL GUI wrappers. More...

Functions

  • int algl_do_dialog (DIALOG *dialog, int focus_obj)
    AllegroGL-friendly version of do_dialog.
  • int algl_popup_dialog (DIALOG *dialog, int focus_obj)
    AllegroGL-friendly version of popup_dialog.
  • void algl_draw_mouse (void)
    Draws a mouse pointer on the screen.
  • void algl_set_mouse_drawer (void(*user_draw_mouse)(void))
    Sets (or clears) a user mouse drawing callback.
  • int algl_alert (AL_CONST char *s1, AL_CONST char *s2, AL_CONST char *s3, AL_CONST char *b1, AL_CONST char *b2, int c1, int c2)
    AllegroGL-friendly version of Allegro's alert.
  • int algl_alert3 (AL_CONST char *s1, AL_CONST char *s2, AL_CONST char *s3, AL_CONST char *b1, AL_CONST char *b2, AL_CONST char *b3, int c1, int c2, int c3)
    AllegroGL-friendly version of Allegro's alert3.
  • int d_algl_viewport_proc (int msg, DIALOG *d, int c)
    Creates a viewport object where OpenGL commands can be performed.

Detailed Description

AllegroGL GUI wrappers.

Due to several specificities of OpenGL, some of the Allegro's GUI routines can not be used "as is". Indeed they are not designed to natively support double-buffered graphics mode. Hence AllegroGL provides wrapper routines of do_dialog, alert and so on...

AllegroGL GUI routines internally call allegro_gl_set_allegro_mode() and its counterpart allegro_gl_unset_allegro_mode(). So the default drawing mode in the GUI routines is the "2D Allegro mode" and functions like line() or rect() can safely be called.

Additionnaly AllegroGL provides a new GUI object d_algl_viewport_proc() which allows to have a 3D viewport that can safely coexist with other "classical" 2D GUI objects : no need to call allegro_gl_set_allegro_mode() or to save the current state of OpenGL.


Function Documentation

int algl_do_dialog ( DIALOG *  dialog,
int  focus_obj 
)

AllegroGL-friendly version of do_dialog.

This behaves exactly like do_dialog but forces a screen clear, rerender, and flip, after each iteration of update_dialog.

User gui components can do OpenGL or Allegro rendering to draw themselves. They should take care not to alter any OpenGL state (or be aware that this will affect other components). For the main render, they will be called in order, but this is not guarranteed at other times -- they may be called out of order; however the results will never be visible, so just don't crash.

Before drawing the final (in-order) pass, the color and depth buffers will be cleared -- set your clear color to black or green or whatever you like. You can overdraw it with an object of course.

Further notes: This routine uses allegro_gl_set_allegro_mode(), so your GUI components can use allegro_gl_unset_allegro_mode() to restore the old state while they draw themselves, provided that they use allegro_gl_set_allegro_mode() again afterwards.

Parameters:
dialogan array of dialog objects terminated by one with a NULL dialog procedure.
focus_objindex of the object on which the focus is set (-1 if you don't want anything to have the focus
See also:
algl_draw_mouse

Definition at line 58 of file gui.c.

References allegro_gl_set_allegro_mode(), and allegro_gl_unset_allegro_mode().

int algl_popup_dialog ( DIALOG *  dialog,
int  focus_obj 
)

AllegroGL-friendly version of popup_dialog.

This routine is likely to be very slow. It has to take a copy of the screen on entry, then where algl_do_dialog() would just clear the screen, this routine has to blit that copy back again after clearing. This is the only way to do overlays without knowing what type of flipping is going on.

Also, note that we don't save the depth buffer or anything like that so don't go around thinking that algl_popup_dialog won't affect anything when it's gone.

So, unless you need overlays, it's recommended that you just use algl_do_dialog(), and if you do need overlays, it's recommended that you just use algl_do_dialog() and redraw the thing you're overlaying yourself. If you're lazy or that's impossible, use this routine...

Parameters:
dialogan array of dialog objects terminated by one with a NULL dialog procedure.
focus_objindex of the object on which the focus is set (-1 if you don't want anything to have the focus
See also:
algl_do_dialog, algl_draw_mouse

Definition at line 111 of file gui.c.

References algl_draw_mouse(), allegro_gl_flip(), allegro_gl_set_allegro_mode(), and allegro_gl_unset_allegro_mode().

Referenced by algl_alert3().

void algl_draw_mouse ( void  )

Draws a mouse pointer on the screen.

This function draws a mouse pointer on the screen. By default, it displays Allegro's standard black arrow cursor. However the settings of the cursor can be altered by Allegro's functions for mouse cursor management like show_mouse, set_mouse_sprite, scare_mouse, and so on... As a consequence, it should be stressed that if show_mouse(NULL) is called then algl_draw_mouse() won't draw anything.

Unlike Allegro, AllegroGL does not manage the mouse cursor with an interrupt routine, hence algl_draw_mouse() must be regularly called in order to display the mouse cursor (ideally it should be the last function called before allegro_gl_flip()). However if you use algl_do_dialog() then you do not need to make explicit calls to algl_draw_mouse() since algl_do_dialog() takes care of that for you.

See also:
algl_set_mouse_drawer

Definition at line 187 of file gui.c.

Referenced by algl_popup_dialog(), and d_algl_viewport_proc().

void algl_set_mouse_drawer ( void(*)(void)  user_draw_mouse)

Sets (or clears) a user mouse drawing callback.

This function allows to use a user-defined routine to display the mouse cursor. This allows nice effects like a spinning cube or any fancy thing you can think of to be used as a mouse cursor.

When a user mouse drawing callback is enabled, set_mouse_sprite has no effect. However show_mouse and scare_mouse are still enabled.

Parameters:
user_draw_mouseuser routine that displays the mouse cursor (NULL if you want to get back to the standard behaviour)
See also:
algl_draw_mouse

Definition at line 284 of file gui.c.

int algl_alert ( AL_CONST char *  s1,
AL_CONST char *  s2,
AL_CONST char *  s3,
AL_CONST char *  b1,
AL_CONST char *  b2,
int  c1,
int  c2 
)

AllegroGL-friendly version of Allegro's alert.

Displays a simple 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. Returns 1 or 2 depending on which button was selected.

Definition at line 449 of file gui.c.

References algl_alert3().

int algl_alert3 ( AL_CONST char *  s1,
AL_CONST char *  s2,
AL_CONST char *  s3,
AL_CONST char *  b1,
AL_CONST char *  b2,
AL_CONST char *  b3,
int  c1,
int  c2,
int  c3 
)

AllegroGL-friendly version of Allegro's alert3.

Displays a simple alert box, containing three lines of text (s1-s3), and with either one, two, or three buttons. The text for these buttons is passed in b1, b2, and b3 (NULL for buttons which are not used), and the keyboard shortcuts in c1 and c2. Returns 1, 2, or 3 depending on which button was selected.

Definition at line 329 of file gui.c.

References algl_popup_dialog().

Referenced by algl_alert().

int d_algl_viewport_proc ( int  msg,
DIALOG *  d,
int  c 
)

Creates a viewport object where OpenGL commands can be performed.

The viewport and the scissor are updated so that this GUI object behaves somewhat like a window. The dp field of the DIALOG object points to a callback function : int (*callback)(BITMAP* viewport, int msg, int c) where: viewport is a sub-bitmap of the screen limited to the area of the DIALOG object. msg and c are the values that come from the GUI manager. The callback function must return a sensible value to the GUI manager like D_O_K if everything went right or D_EXIT to close the dialog.

Definition at line 477 of file gui.c.

References algl_draw_mouse(), allegro_gl_flip(), allegro_gl_set_allegro_mode(), and allegro_gl_unset_allegro_mode().

allegro4.4-4.4.2/addons/allegrogl/docs/html/group__math.html000066400000000000000000000711141173507505700237200ustar00rootroot00000000000000 AllegroGL: Math conversion routines

Math conversion routines

Routines to convert between OpenGL and Allegro math types. More...

Matrix conversion routines

  • void allegro_gl_MATRIX_to_GLfloat (MATRIX *m, GLfloat gl[16])
    Converts an Allegro fixed-point matrix to an array of floats suitable for OpenGL's matrix operations.
  • void allegro_gl_MATRIX_to_GLdouble (MATRIX *m, GLdouble gl[16])
    Converts an Allegro fixed-point matrix to an array of doubles suitable for OpenGL's matrix operations.
  • void allegro_gl_MATRIX_f_to_GLfloat (MATRIX_f *m, GLfloat gl[16])
    Converts an Allegro floating-point matrix to an array of floats suitable for OpenGL's matrix operations.
  • void allegro_gl_MATRIX_f_to_GLdouble (MATRIX_f *m, GLdouble gl[16])
    Converts an Allegro floating-point matrix to an array of doubles suitable for OpenGL's matrix operations.
  • void allegro_gl_GLfloat_to_MATRIX (GLfloat gl[16], MATRIX *m)
    Converts an Allegro fixed-point matrix to an array of floats suitable for OpenGL's matrix operations.
  • void allegro_gl_GLdouble_to_MATRIX (GLdouble gl[16], MATRIX *m)
    Converts an Allegro fixed-point matrix to an array of floats suitable for OpenGL's matrix operations.
  • void allegro_gl_GLfloat_to_MATRIX_f (GLfloat gl[16], MATRIX_f *m)
    Converts an Allegro fixed-point matrix to an array of floats suitable for OpenGL's matrix operations.
  • void allegro_gl_GLdouble_to_MATRIX_f (GLdouble gl[16], MATRIX_f *m)
    Converts an Allegro fixed-point matrix to an array of floats suitable for OpenGL's matrix operations.

Quaternion conversion routines

  • void allegro_gl_apply_quat (QUAT *q)
  • void allegro_gl_quat_to_glrotatef (QUAT *q, float *angle, float *x, float *y, float *z)
  • void allegro_gl_quat_to_glrotated (QUAT *q, double *angle, double *x, double *y, double *z)

Detailed Description

Routines to convert between OpenGL and Allegro math types.


Function Documentation

void allegro_gl_MATRIX_to_GLfloat ( MATRIX *  m,
GLfloat  gl[16] 
)

Converts an Allegro fixed-point matrix to an array of floats suitable for OpenGL's matrix operations.

Example:

    MATRIX m = identity_matrix;
    GLfloat gl_m[16];
    get_vector_rotation_matrix(&m, itofix(1), 0, itofix(1), ftofix(43.83));
    allegro_gl_MATRIX_to_GLfloat(&m, &gl_m);
    glLoadMatrixf(&gl_m);
  
See also:
allegro_gl_MATRIX_to_GLdouble()
allegro_gl_MATRIX_f_to_GLfloat()
allegro_gl_MATRIX_f_to_GLdouble()
allegro_gl_GLdouble_to_MATRIX()
allegro_gl_GLfloat_to_MATRIX_f()
allegro_gl_GLdouble_to_MATRIX_f()
allegro_gl_GLfloat_to_MATRIX()

Definition at line 66 of file math.c.

void allegro_gl_MATRIX_to_GLdouble ( MATRIX *  m,
GLdouble  gl[16] 
)
void allegro_gl_MATRIX_f_to_GLfloat ( MATRIX_f *  m,
GLfloat  gl[16] 
)

Converts an Allegro floating-point matrix to an array of floats suitable for OpenGL's matrix operations.

See also:
allegro_gl_MATRIX_to_GLfloat()
allegro_gl_MATRIX_to_GLdouble()
allegro_gl_MATRIX_f_to_GLdouble()
allegro_gl_GLdouble_to_MATRIX()
allegro_gl_GLfloat_to_MATRIX_f()
allegro_gl_GLdouble_to_MATRIX_f()
allegro_gl_GLfloat_to_MATRIX()

Definition at line 98 of file math.c.

void allegro_gl_MATRIX_f_to_GLdouble ( MATRIX_f *  m,
GLdouble  gl[16] 
)

Converts an Allegro floating-point matrix to an array of doubles suitable for OpenGL's matrix operations.

See also:
allegro_gl_MATRIX_to_GLfloat()
allegro_gl_MATRIX_to_GLdouble()
allegro_gl_MATRIX_f_to_GLfloat()
allegro_gl_GLdouble_to_MATRIX()
allegro_gl_GLfloat_to_MATRIX_f()
allegro_gl_GLdouble_to_MATRIX_f()
allegro_gl_GLfloat_to_MATRIX()

Definition at line 110 of file math.c.

void allegro_gl_GLfloat_to_MATRIX ( GLfloat  gl[16],
MATRIX *  m 
)

Converts an Allegro fixed-point matrix to an array of floats suitable for OpenGL's matrix operations.

Example:

    MATRIX m = identity_matrix;
    GLfloat gl_m[16];
    get_vector_rotation_matrix(&m, itofix(1), 0, itofix(1), ftofix(43.83));
    allegro_gl_MATRIX_to_GLfloat(&m, &gl_m);
    glLoadMatrixf(&gl_m);
  
See also:
allegro_gl_MATRIX_to_GLdouble()
allegro_gl_MATRIX_f_to_GLfloat()
allegro_gl_MATRIX_f_to_GLdouble()
allegro_gl_GLdouble_to_MATRIX()
allegro_gl_GLfloat_to_MATRIX_f()
allegro_gl_GLdouble_to_MATRIX_f()
allegro_gl_GLfloat_to_MATRIX()
void allegro_gl_GLdouble_to_MATRIX ( GLdouble  gl[16],
MATRIX *  m 
)

Converts an Allegro fixed-point matrix to an array of floats suitable for OpenGL's matrix operations.

Example:

    MATRIX m = identity_matrix;
    GLfloat gl_m[16];
    get_vector_rotation_matrix(&m, itofix(1), 0, itofix(1), ftofix(43.83));
    allegro_gl_MATRIX_to_GLfloat(&m, &gl_m);
    glLoadMatrixf(&gl_m);
  
See also:
allegro_gl_MATRIX_to_GLdouble()
allegro_gl_MATRIX_f_to_GLfloat()
allegro_gl_MATRIX_f_to_GLdouble()
allegro_gl_GLdouble_to_MATRIX()
allegro_gl_GLfloat_to_MATRIX_f()
allegro_gl_GLdouble_to_MATRIX_f()
allegro_gl_GLfloat_to_MATRIX()
void allegro_gl_GLfloat_to_MATRIX_f ( GLfloat  gl[16],
MATRIX_f *  m 
)

Converts an Allegro fixed-point matrix to an array of floats suitable for OpenGL's matrix operations.

Example:

    MATRIX m = identity_matrix;
    GLfloat gl_m[16];
    get_vector_rotation_matrix(&m, itofix(1), 0, itofix(1), ftofix(43.83));
    allegro_gl_MATRIX_to_GLfloat(&m, &gl_m);
    glLoadMatrixf(&gl_m);
  
See also:
allegro_gl_MATRIX_to_GLdouble()
allegro_gl_MATRIX_f_to_GLfloat()
allegro_gl_MATRIX_f_to_GLdouble()
allegro_gl_GLdouble_to_MATRIX()
allegro_gl_GLfloat_to_MATRIX_f()
allegro_gl_GLdouble_to_MATRIX_f()
allegro_gl_GLfloat_to_MATRIX()
void allegro_gl_GLdouble_to_MATRIX_f ( GLdouble  gl[16],
MATRIX_f *  m 
)

Converts an Allegro fixed-point matrix to an array of floats suitable for OpenGL's matrix operations.

Example:

    MATRIX m = identity_matrix;
    GLfloat gl_m[16];
    get_vector_rotation_matrix(&m, itofix(1), 0, itofix(1), ftofix(43.83));
    allegro_gl_MATRIX_to_GLfloat(&m, &gl_m);
    glLoadMatrixf(&gl_m);
  
See also:
allegro_gl_MATRIX_to_GLdouble()
allegro_gl_MATRIX_f_to_GLfloat()
allegro_gl_MATRIX_f_to_GLdouble()
allegro_gl_GLdouble_to_MATRIX()
allegro_gl_GLfloat_to_MATRIX_f()
allegro_gl_GLdouble_to_MATRIX_f()
allegro_gl_GLfloat_to_MATRIX()
allegro4.4-4.4.2/addons/allegrogl/docs/html/group__settings.html000066400000000000000000001707161173507505700246370ustar00rootroot00000000000000 AllegroGL: Option settings

Option settings

OpenGL has many options controlling the way a video mode is selected. More...

Defines

  • #define AGL_FLOAT_COLOR   0x00800000
    Floating-point Color buffer.
  • #define AGL_FLOAT_Z   0x01000000
    Floating-point Depth buffer.
  • #define AGL_CONFIG_RESRVED   0xA000000

Frame Buffer Settings

  • #define AGL_ALLEGRO_FORMAT   0x00000001
    Use Allegro-compatible framebuffer.
  • #define AGL_RED_DEPTH   0x00000002
    Select the red depth of the frame buffer.
  • #define AGL_GREEN_DEPTH   0x00000004
    Select the green depth of the frame buffer.
  • #define AGL_BLUE_DEPTH   0x00000008
    Select the blue depth of the frame buffer.
  • #define AGL_ALPHA_DEPTH   0x00000010
    Select the alpha depth of the frame buffer.
  • #define AGL_COLOR_DEPTH   0x00000020
    Specify the total color depth of the frame buffer.
  • #define AGL_ACC_RED_DEPTH   0x00000040
    Select the red depth of the accumulator buffer.
  • #define AGL_ACC_GREEN_DEPTH   0x00000080
    Select the green depth of the accumulator buffer.
  • #define AGL_ACC_BLUE_DEPTH   0x00000100
    Select the blue depth of the accumulator buffer.
  • #define AGL_ACC_ALPHA_DEPTH   0x00000200
    Select the alpha depth of the accumulator buffer.
  • #define AGL_DOUBLEBUFFER   0x00000400
    Creates a backbuffer if set.
  • #define AGL_STEREO   0x00000800
    Creates seperate left/right buffers for stereo display.
  • #define AGL_AUX_BUFFERS   0x00001000
    Creates additional auxiliary buffers.
  • #define AGL_Z_DEPTH   0x00002000
    Select the depth of the z-buffer.
  • #define AGL_STENCIL_DEPTH   0x00004000
    Select the depth of the stencil buffer.
  • #define AGL_WINDOW_X   0x00008000
    Requests a placement of the window to a specified pixel location.
  • #define AGL_WINDOW_Y   0x00010000
    Same as AGL_WINDOW_X, but for the y-axis.
  • #define AGL_RENDERMETHOD   0x00020000
    Set it if you'd like AllegroGL to pay special attention on whether hardware acceleration is present or not.
  • #define AGL_FULLSCREEN   0x00040000
    Set if you'd like a full screen mode.
  • #define AGL_WINDOWED   0x00080000
    Set if you'd like a windowed mode.
  • #define AGL_VIDEO_MEMORY_POLICY   0x00100000
    Define AllegroGL's policy relative to video memory usage.
  • #define AGL_SAMPLE_BUFFERS   0x00200000
    Define multisample parameters Some OpenGL ICDs expose an extension called GL_ARB_multisample which provides a mechanism to anti-alias all GL primitives: points, lines, polygons, bitmaps and pixel rectangles.
  • #define AGL_SAMPLES   0x00400000
    Define multisample samples Set this value to the number of samples that can be accepted in the multisample buffers.

Mode selection priority options

  • #define AGL_DONTCARE   0
    Ignore these settings.
  • #define AGL_SUGGEST   -1
    Prefer the assigned values for these settings.
  • #define AGL_REQUIRE   -2
    Reject other values for these settings.

Video memory policy options

  • #define AGL_KEEP   1
    Keep internal texture in video memory.
  • #define AGL_RELEASE   2
    Release video memory occupied by internal texture.

Mode selection functions


Detailed Description

OpenGL has many options controlling the way a video mode is selected.

AllegroGL has functions to set particular options, and to state whether choices are merely preferences or are essential.

Use allegro_gl_set() to set options. All options are integers. The value you set is, by default, ignored; you must tell AllegroGL how important it is. There are three levels of importance:

To specify the importance of a setting, set AGL_REQUIRE, AGL_SUGGEST, or AGL_DONTCARE to contain that setting's flag, e.g.

   allegro_gl_set(AGL_COLOR_DEPTH, 16);
   allegro_gl_set(AGL_REQUIRE, AGL_COLOR_DEPTH);
 

Rather than calling allegro_gl_set once per setting you want to mark as required, you can OR the setting flags together:

   allegro_gl_set(AGL_REQUIRE, AGL_COLOR_DEPTH | AGL_DOUBLEBUFFER);
 

This has the same effect as marking the two settings separately.

After saying that you AGL_REQUIRE a particular setting, you can still go back and AGL_DONTCARE or AGL_SUGGEST it instead -- nothing happens until you try to set a graphics mode. At that stage, a mode is set (or set_gfx_mode() returns failure, if not all required settings could be satisfied), and you can then retrieve the actual settings used by calling allegro_gl_get(). Note that this is largely untested; some settings may not be retrieved properly. Please do let us know if you find any!


Define Documentation

#define AGL_ALLEGRO_FORMAT   0x00000001

Use Allegro-compatible framebuffer.

Deprecated:
This define is ignored.

Definition at line 189 of file alleggl.h.

Referenced by allegro_gl_get(), and allegro_gl_set().

#define AGL_RED_DEPTH   0x00000002

Select the red depth of the frame buffer.

This defines the number of bits for the red component you'd like. The driver may or may not find a suitable mode

Definition at line 195 of file alleggl.h.

Referenced by allegro_gl_get(), and allegro_gl_set().

#define AGL_GREEN_DEPTH   0x00000004

Select the green depth of the frame buffer.

This defines the number of bits for the green component you'd like. The driver may or may not find a suitable mode

Definition at line 201 of file alleggl.h.

Referenced by allegro_gl_get(), and allegro_gl_set().

#define AGL_BLUE_DEPTH   0x00000008

Select the blue depth of the frame buffer.

This defines the number of bits for the blue component you'd like. The driver may or may not find a suitable mode

Definition at line 207 of file alleggl.h.

Referenced by allegro_gl_get(), and allegro_gl_set().

#define AGL_ALPHA_DEPTH   0x00000010

Select the alpha depth of the frame buffer.

This defines the number of bits for the alpha component you'd like. Not many video cards support destination alpha, so be aware that the you may not get an alpha depth at all.

Definition at line 214 of file alleggl.h.

Referenced by allegro_gl_get(), and allegro_gl_set().

#define AGL_COLOR_DEPTH   0x00000020

Specify the total color depth of the frame buffer.

The driver is free to select any combination of red, green, blue and alpha bits.

Definition at line 219 of file alleggl.h.

Referenced by allegro_gl_get(), and allegro_gl_set().

#define AGL_ACC_RED_DEPTH   0x00000040

Select the red depth of the accumulator buffer.

This defines the number of bits to use for the red component. The driver may or may not find a suitable mode. Note that on many video cards, the accumulator buffer is not accelerated.

Definition at line 227 of file alleggl.h.

Referenced by allegro_gl_get(), and allegro_gl_set().

#define AGL_ACC_GREEN_DEPTH   0x00000080

Select the green depth of the accumulator buffer.

This defines the number of bits to use for the green component. The driver may or may not find a suitable mode. Note that on many video cards, the accumulator buffer is not accelerated.

Definition at line 234 of file alleggl.h.

Referenced by allegro_gl_get(), and allegro_gl_set().

#define AGL_ACC_BLUE_DEPTH   0x00000100

Select the blue depth of the accumulator buffer.

This defines the number of bits to use for the blue component. The driver may or may not find a suitable mode. Note that on many video cards, the accumulator buffer is not accelerated.

Definition at line 242 of file alleggl.h.

Referenced by allegro_gl_get(), and allegro_gl_set().

#define AGL_ACC_ALPHA_DEPTH   0x00000200

Select the alpha depth of the accumulator buffer.

This defines the number of bits to use for the alpha component. The driver may or may not find a suitable mode. Note that on many video cards, the accumulator buffer is not accelerated. Not many cards support destination alpha either.

Definition at line 250 of file alleggl.h.

Referenced by allegro_gl_get(), and allegro_gl_set().

#define AGL_DOUBLEBUFFER   0x00000400

Creates a backbuffer if set.

The buffering mode may be double buffering or page flipping, depending on the driver settings. OpenGL programs cannot chose the buffering mode themselves.

Definition at line 256 of file alleggl.h.

Referenced by allegro_gl_clear_settings(), allegro_gl_get(), and allegro_gl_set().

#define AGL_STEREO   0x00000800

Creates seperate left/right buffers for stereo display.

Stereo display is used with special hardware (tipically glasses) for giving the illusion of depth by drawing the left and right buffers with a slight horizontal displacement. This makes the display appear to heavily flicker without the special hardware. Set to TRUE for enabling stereo viewing.

Definition at line 265 of file alleggl.h.

Referenced by allegro_gl_get(), and allegro_gl_set().

#define AGL_AUX_BUFFERS   0x00001000

Creates additional auxiliary buffers.

This allows you to have more than one rendering context. Few video cards support this feature.

Definition at line 271 of file alleggl.h.

Referenced by allegro_gl_get(), and allegro_gl_set().

#define AGL_Z_DEPTH   0x00002000

Select the depth of the z-buffer.

The z-buffer is used to properly display polygons in 3D without recurring to sorting. The higher the depth of the z-buffer, the more precise it is.

Definition at line 278 of file alleggl.h.

Referenced by allegro_gl_get(), and allegro_gl_set().

#define AGL_STENCIL_DEPTH   0x00004000

Select the depth of the stencil buffer.

The stencil buffer is used to to do per-pixel testing (like the z-buffer), but of an arbitrary pattern instead of depth. Please see the OpenGL documentation for details. Newer cards support stenciling in hardware, but older cards (TNT2s, Voodoos, ATI Rage) do not.

Definition at line 287 of file alleggl.h.

Referenced by allegro_gl_get(), and allegro_gl_set().

#define AGL_WINDOW_X   0x00008000

Requests a placement of the window to a specified pixel location.

The driver may or may not honnor the request.

Definition at line 292 of file alleggl.h.

Referenced by allegro_gl_get(), and allegro_gl_set().

#define AGL_RENDERMETHOD   0x00020000

Set it if you'd like AllegroGL to pay special attention on whether hardware acceleration is present or not.

Notice however this isn't a guarentee that the OpenGL operations will be accelerated, but rather a request that the operations go through the video card's drivers instead of Microsoft's software renderer. The video card driver is free to drop back to software mode if it deems it necessary. This setting has no effect in X.

Definition at line 306 of file alleggl.h.

Referenced by allegro_gl_clear_settings(), and allegro_gl_set().

#define AGL_FULLSCREEN   0x00040000

Set if you'd like a full screen mode.

Full screen may or may not be available on the current platform.

Definition at line 311 of file alleggl.h.

Referenced by allegro_gl_clear_settings(), allegro_gl_get(), and allegro_gl_set().

#define AGL_WINDOWED   0x00080000

Set if you'd like a windowed mode.

Windowed modes may or may not be available on the current platform.

Definition at line 316 of file alleggl.h.

Referenced by allegro_gl_get(), and allegro_gl_set().

#define AGL_VIDEO_MEMORY_POLICY   0x00100000

Define AllegroGL's policy relative to video memory usage.

Sometimes AllegroGL needs to create an internal 256x256 texture in order to perform graphics operations like masked_blit, draw_sprite and so on. This parameter defines the policy of AllegroGL relative to the management of this texture. Several options are available :

  • AGL_RELEASE : internal texture is released in order to free video memory.
  • AGL_KEEP : internal texture is kept in video memory. This option generally accelerate graphics operations when allegro_gl_set_allegro_mode() and allegro_gl_unset_allegro_mode() are often called. System with few video memory should use AGL_RELEASE while others should use AGL_KEEP since it allows the internal texture to be created once. Default value is AGL_KEEP.

Definition at line 333 of file alleggl.h.

Referenced by allegro_gl_get(), and allegro_gl_set().

#define AGL_SAMPLE_BUFFERS   0x00200000

Define multisample parameters Some OpenGL ICDs expose an extension called GL_ARB_multisample which provides a mechanism to anti-alias all GL primitives: points, lines, polygons, bitmaps and pixel rectangles.

In order to get an AllegroGL mode which supports multisample, you have to set both AGL_SAMPLE_BUFFERS to 1 and AGL_SAMPLES to the number of desired samples for multisampling.

Notice however that since this feature relies on several extensions (GL_ARB_multisample and GLX_ARB_multisample or WGL_ARB_multisample), it isn't guaranteed that AllegroGL will find a graphics mode that supports multisample : many not-so-old video cards, like the GeForce 2, do not support multisampling

Hence, if you want your app to be able to run on most platforms, you should not require this parameter.

Set this value to 1 to enable multisampling.

See also:
AGL_SAMPLES

Definition at line 357 of file alleggl.h.

Referenced by allegro_gl_get(), and allegro_gl_set().

#define AGL_SAMPLES   0x00400000

Define multisample samples Set this value to the number of samples that can be accepted in the multisample buffers.

See also:
AGL_SAMPLE_BUFFERS

Definition at line 365 of file alleggl.h.

Referenced by allegro_gl_get(), and allegro_gl_set().


Function Documentation

void allegro_gl_clear_settings ( void  )

Clear the option settings All settings are set to their default values, and marked as neither suggested not required.

The mode setting routines will now ignore all of the settings other than those which you explicitly mark with AGL_SUGGEST or AGL_REQUIRE.

Note:
You should not rely on what the default values actually are - don't mark settings unless you've also assigned something to them.
Some settings are turned on by default. AGL_DOUBLEBUFFER, AGL_RENDERMETHOD and AGL_FULLSCREEN are set to AGL_SUGGEST.
See also:
allegro_gl_set(), allegro_gl_get()

Definition at line 193 of file alleggl.c.

References AGL_DOUBLEBUFFER, AGL_FULLSCREEN, AGL_KEEP, and AGL_RENDERMETHOD.

Referenced by install_allegro_gl().

void allegro_gl_set ( int  option,
int  value 
)

Sets a configuration option.

Use this routine to configure the framebuffer, *before* setting a graphics mode. Options are integer constants, and all values are effectively integers.

Three of the options are special. AGL_SUGGEST and AGL_REQUIRE are used to mark which of the other options are merely suggestions and which are absolute requirements. If the OpenGL implementation can't provide a feature which you mark with AGL_REQUIRE, the call to set_gfx_mode will fail. If you don't mark an option as either suggested or required, that option will be ignored (AGL_DONTCARE). You can OR (|) together the other constants when using one of these three options to indicate your preferences for several settings at one time. Selecting an option as one of the suggestion modes will remove it from the others. For example, if you first set the color depth to be required, but then decide that you want it to be suggested instead, then the option will be removed from the required settings. Setting any option to AGL_DONTCARE will remove any previous setting attributed to it, and default values will be used if necessary.

The remaining options are:

		AGL_ALLEGRO_FORMAT,
		AGL_RED_DEPTH,
		AGL_GREEN_DEPTH,
		AGL_BLUE_DEPTH,
		AGL_ALPHA_DEPTH,
		AGL_COLOR_DEPTH,
		AGL_ACC_RED_DEPTH,
		AGL_ACC_GREEN_DEPTH,
		AGL_ACC_BLUE_DEPTH,
		AGL_ACC_ALPHA_DEPTH,
		AGL_DOUBLEBUFFER,
		AGL_STEREO,
		AGL_AUX_BUFFERS,
		AGL_Z_DEPTH,
		AGL_STENCIL_DEPTH,
		AGL_WINDOW_X,
		AGL_WINDOW_Y,
		AGL_RENDERMETHOD
		AGL_FULLSCREEN
		AGL_WINDOWED
		AGL_VIDEO_MEMORY_POLICY
		AGL_SAMPLE_BUFFERS
		AGL_SAMPLES
		AGL_FLOAT_COLOR
		AGL_FLOAT_Z
   
Parameters:
optionSelects which option to change.
valueThe new option value.

Example:

    allegro_gl_set(AGL_COLOR_DEPTH, 32);
    allegro_gl_set(AGL_RENDERMETHOD, 1);
    allegro_gl_set(AGL_REQUIRE, AGL_COLOR_DEPTH | AGL_RENDERMETHOD);
  
See also:
allegro_gl_get(), allegro_gl_clear_settings()

Definition at line 274 of file alleggl.c.

References AGL_ACC_ALPHA_DEPTH, AGL_ACC_BLUE_DEPTH, AGL_ACC_GREEN_DEPTH, AGL_ACC_RED_DEPTH, AGL_ALLEGRO_FORMAT, AGL_ALPHA_DEPTH, AGL_AUX_BUFFERS, AGL_BLUE_DEPTH, AGL_COLOR_DEPTH, AGL_DONTCARE, AGL_DOUBLEBUFFER, AGL_FLOAT_COLOR, AGL_FLOAT_Z, AGL_FULLSCREEN, AGL_GREEN_DEPTH, AGL_KEEP, AGL_RED_DEPTH, AGL_RELEASE, AGL_RENDERMETHOD, AGL_REQUIRE, AGL_SAMPLE_BUFFERS, AGL_SAMPLES, AGL_STENCIL_DEPTH, AGL_STEREO, AGL_SUGGEST, AGL_VIDEO_MEMORY_POLICY, AGL_WINDOW_X, AGL_WINDOW_Y, AGL_WINDOWED, and AGL_Z_DEPTH.

Referenced by allegro_gl_load_settings().

int allegro_gl_get ( int  option)

Reads the setting of a configuration option.

This routine can be used to read back the configuration of the framebuffer. You can do this either before setting a graphics mode to check what configuration you are requesting, or afterwards to find out what settings were actually used. For a list of option constants, see documentation for allegro_gl_set().

Parameters:
optionThe option to have its value returned.
Returns:
The value of the option selected by the parameter, or -1 if the option is invalid.
See also:
allegro_gl_set(), allegro_gl_clear_settings()

Definition at line 421 of file alleggl.c.

References AGL_ACC_ALPHA_DEPTH, AGL_ACC_BLUE_DEPTH, AGL_ACC_GREEN_DEPTH, AGL_ACC_RED_DEPTH, AGL_ALLEGRO_FORMAT, AGL_ALPHA_DEPTH, AGL_AUX_BUFFERS, AGL_BLUE_DEPTH, AGL_COLOR_DEPTH, AGL_DONTCARE, AGL_DOUBLEBUFFER, AGL_FLOAT_COLOR, AGL_FLOAT_Z, AGL_FULLSCREEN, AGL_GREEN_DEPTH, AGL_RED_DEPTH, AGL_REQUIRE, AGL_SAMPLE_BUFFERS, AGL_SAMPLES, AGL_STENCIL_DEPTH, AGL_STEREO, AGL_SUGGEST, AGL_VIDEO_MEMORY_POLICY, AGL_WINDOW_X, AGL_WINDOW_Y, AGL_WINDOWED, and AGL_Z_DEPTH.

Referenced by allegro_gl_save_settings().

void allegro_gl_save_settings ( )

Saves the current settings (as specified by allegro_gl_set()) to the current config file, in the section [OpenGL].

See also:
allegro_gl_load_settings()

Definition at line 560 of file alleggl.c.

References AGL_FLOAT_Z, AGL_REQUIRE, AGL_SUGGEST, and allegro_gl_get().

void allegro_gl_load_settings ( )

Loads the settings from the current config file, in the section [OpenGL].

Note that this function will not clear any settings currently set, but will add them up, as if each of the setting were set manually.

See also:
allegro_gl_save_settings()

Definition at line 741 of file alleggl.c.

References AGL_FLOAT_Z, AGL_REQUIRE, AGL_SUGGEST, and allegro_gl_set().

allegro4.4-4.4.2/addons/allegrogl/docs/html/group__texture.html000066400000000000000000001015201173507505700244620ustar00rootroot00000000000000 AllegroGL: Texture Routines

Texture Routines

AllegroGL provides functions to allow using Allegro BITMAP objects to be used as OpenGL textures. More...

Texture routines


Detailed Description

AllegroGL provides functions to allow using Allegro BITMAP objects to be used as OpenGL textures.


Define Documentation

#define AGL_TEXTURE_FLIP   0x04

Flip the texture on the x-axis.

OpenGL uses the bottom-left corner of the texture as (0,0), so if you need your texture to be flipped to make (0,0) the top-left corner, you need to use this flag.

Definition at line 529 of file alleggl.h.

Referenced by allegro_gl_convert_allegro_font_ex().

#define AGL_TEXTURE_MASKED   0x08

Generate an alpha channel for this texture, based on the Allegro mask color.

Make sure the target format supports an alpha channel.

Definition at line 534 of file alleggl.h.

Referenced by allegro_gl_convert_allegro_font_ex().

#define AGL_TEXTURE_RESCALE   0x10

Tell AllegroGL to allow rescaling of the bitmap.

By default, AllegroGL will not rescale the bitmap to fit into a texture. You can override this behavior by using this flag.

Definition at line 540 of file alleggl.h.


Function Documentation

int allegro_gl_use_mipmapping ( int  enable)

Tell AllegroGL to use Mipmapping or not when generating textures via its functions.

This will not affect outside OpenGL states. Default is FALSE (off).

See also:
allegro_gl_check_texture(), allegro_gl_make_texture() allegro_gl_make_masked_texture()
Parameters:
enableSet to TRUE to enable mipmapping, FALSE otherwise.
Returns:
The previous mode (either TRUE or FALSE).
Deprecated:

Definition at line 415 of file texture.c.

int allegro_gl_use_alpha_channel ( int  enable)

Tell AllegroGL to use Alpha channel or not when generating textures via its functions.

This will not affect outside OpenGL states. Default is FALSE (off).

See also:
allegro_gl_check_texture(), allegro_gl_make_texture(), allegro_gl_make_masked_texture()
Parameters:
enableSet to TRUE to enable textures with alpha channel, FALSE otherwise.
Returns:
The previous mode (either TRUE or FALSE).
Deprecated:

Definition at line 439 of file texture.c.

int allegro_gl_flip_texture ( int  enable)

Tell AllegroGL to flip the texture vertically or not when generating textures via its functions, to conform to the usual OpenGL texture coordinate system (increasing upwards).

Default is TRUE (on).

See also:
allegro_gl_check_texture(), allegro_gl_make_texture(), allegro_gl_make_masked_texture()
Parameters:
enableSet to TRUE to enable textures with alpha channel, FALSE otherwise.
Returns:
The previous mode (either TRUE or FALSE).
Deprecated:

Definition at line 464 of file texture.c.

int allegro_gl_check_texture ( BITMAP *  bmp)

Checks whether the specified bitmap is of the proper size for texturing.

This checks for the card's limit on texture sizes.

Important note: allegro_gl_check_texture does not depend on the current state of the texture memory of the driver. This function may return TRUE although there is not enough memory to currently make the texture resident. You may check if the texture is actually resident with glAreTexturesResident().

See also:
allegro_gl_check_texture_ex(), allegro_gl_make_texture_ex()
Parameters:
bmpThe bitmap to be converted to a texture.
Returns:
TRUE if the bitmap can be made a texture of, FALSE otherwise.
Deprecated:

Definition at line 557 of file texture.c.

References allegro_gl_check_texture_ex().

int allegro_gl_check_texture_ex ( int  flags,
BITMAP *  bmp,
GLint  internal_format 
)

Checks whether the specified bitmap is of the proper size for texturing.

This checks for the card's limit on texture sizes.

The parameters to this function are identical to those of allegro_gl_make_texture_ex().

Important note: allegro_gl_check_texture does not depend on the current state of the texture memory of the driver. This function may return TRUE although there is not enough memory to currently make the texture resident. You may check if the texture is actually resident with glAreTexturesResident().

See also:
allegro_gl_make_texture_ex()
Parameters:
flagsThe bitmap conversion flags.
bmpThe bitmap to be converted to a texture.
internal_formatThe internal format to convert to.
Returns:
TRUE if the bitmap can be made a texture of, FALSE otherwise.

Definition at line 495 of file texture.c.

References allegro_gl_make_texture_ex().

Referenced by allegro_gl_check_texture(), and allegro_gl_convert_allegro_font_ex().

GLint allegro_gl_get_texture_format ( BITMAP *  bmp)

Returns the OpenGL internal texture format for this bitmap.

If left to default, it returns the number of color components in the bitmap. Otherwise, it simply returns the user defined value. If the bitmap parameter is NULL, then it returns the currently set format, or -1 if none were previously set. 8 bpp bitmaps are assumed to be alpha channels only (GL_ALPHA8) by default.

See also:
allegro_gl_set_texture_format(), allegro_gl_make_texture()
Parameters:
bmpThe bitmap to get the information of.
Returns:
The OpenGL internal texture format.
Deprecated:

Definition at line 248 of file texture.c.

Referenced by allegro_gl_convert_allegro_font().

GLint allegro_gl_set_texture_format ( GLint  format)

Sets the color format you'd like OpenGL to use for its textures.

You can pass any of the available GL_* constants that describe the internal format (GL_ALPHA4...GL_RGBA16). It is recommended that you check for the availability of the format from the client, using allegro_gl_opengl_version(). No checking will be done as to the validity of the format. The format is a recommendation to the driver, so there is no guarentee that the actual format used will be the one you chose - this is implementation dependant. This call will affect all subsequent calls to allegro_gl_make_texture() and allegro_gl_make_masked_texture().

To revert to the default AllegroGL format, pass -1 as the format.

See also:
allegro_gl_get_texture_format()
Parameters:
formatThe OpenGL internal texture format.
Returns:
The previous value of the texture format.
Deprecated:

Definition at line 282 of file texture.c.

GLuint allegro_gl_make_texture ( BITMAP *  bmp)

Uploads an Allegro BITMAP to the GL driver as a texture.

Deprecated:
See also:
allegro_gl_make_texture_ex()

Definition at line 1383 of file texture.c.

References allegro_gl_make_texture_ex().

GLuint allegro_gl_make_masked_texture ( BITMAP *  bmp)

Uploads an Allegro BITMAP to the GL driver as a texture.

Deprecated:
See also:
allegro_gl_make_texture_ex()

Definition at line 1402 of file texture.c.

References allegro_gl_make_texture_ex().

GLuint allegro_gl_make_texture_ex ( int  flags,
BITMAP *  bmp,
GLint  internal_format 
)

Uploads an Allegro BITMAP to the GL driver as a texture.

The bitmap must be a memory bitmap (note that it can be a subbitmap).

Each bitmap will be converted to a single texture object, with all its size limitations imposed by the video driver and hardware.

The bitmap should conform to the size limitations imposed by the video driver. That is, if ARB_texture_non_power_of_two is not supported, then the BITMAP must be power-of-two sized. Otherwise, AllegroGL will pick the best format for the bitmap.

The original bitmap will NOT be modified.

The flags parameter controls how the texture is generated. It can be a logical OR (|) of any of the following:

AGL_TEXTURE_MIPMAP AGL_TEXTURE_HAS_ALPHA AGL_TEXTURE_FLIP AGL_TEXTURE_MASKED AGL_TEXTURE_RESCALE

AllegroGL will create a texture with the specified texel format. The texel format should be any of the valid formats that can be specified to glTexImage2D(). No validity checks will be performed by AllegroGL. If you want AllegroGL to automatically determine the format to use based on the BITMAP, use -1 as the format specifier.

A valid GL Rendering Context must have been established, which means you cannot use this function before having called set_gfx_mode() with a valid OpenGL mode.

Important note: on 32 bit bitmap in RGBA mode, the alpha channel created by Allegro is set to all 0 by default. This will cause the texture to not show up in 32bpp modes if alpha is set. You will need to fill in the alpha channel manually if you need an alpha channel.

Parameters:
bmpThe bitmap to be converted to a texture.
flagsThe conversion flags.
internal_formatThe texture format to convert to.
Returns:
GLuint The texture handle, or 0 on failure

Definition at line 1165 of file texture.c.

References allegro_gl_extensions_GL.

Referenced by allegro_gl_check_texture_ex(), allegro_gl_convert_allegro_font_ex(), allegro_gl_make_masked_texture(), and allegro_gl_make_texture().

allegro4.4-4.4.2/addons/allegrogl/docs/html/group__version.html000066400000000000000000000071361173507505700244570ustar00rootroot00000000000000 AllegroGL: Version information

Version information

Version Information

allegro4.4-4.4.2/addons/allegrogl/docs/html/gui_8c.html000066400000000000000000000272211173507505700225720ustar00rootroot00000000000000 AllegroGL: gui.c File Reference

gui.c File Reference

AllegroGL GUI wrappers. More...

#include "alleggl.h"
#include "allglint.h"
#include <allegro/internal/aintern.h>

Go to the source code of this file.

Defines

  • #define A_S1   1
  • #define A_S2   2
  • #define A_S3   3
  • #define A_B1   4
  • #define A_B2   5
  • #define A_B3   6
  • #define SORT_OUT_BUTTON(x)

Functions

  • int algl_do_dialog (DIALOG *dialog, int focus_obj)
    AllegroGL-friendly version of do_dialog.
  • int algl_popup_dialog (DIALOG *dialog, int focus_obj)
    AllegroGL-friendly version of popup_dialog.
  • void algl_draw_mouse (void)
    Draws a mouse pointer on the screen.
  • void algl_set_mouse_drawer (void(*user_draw_mouse)(void))
    Sets (or clears) a user mouse drawing callback.
  • int algl_alert3 (AL_CONST char *s1, AL_CONST char *s2, AL_CONST char *s3, AL_CONST char *b1, AL_CONST char *b2, AL_CONST char *b3, int c1, int c2, int c3)
    AllegroGL-friendly version of Allegro's alert3.
  • int algl_alert (AL_CONST char *s1, AL_CONST char *s2, AL_CONST char *s3, AL_CONST char *b1, AL_CONST char *b2, int c1, int c2)
    AllegroGL-friendly version of Allegro's alert.
  • int d_algl_viewport_proc (int msg, DIALOG *d, int c)
    Creates a viewport object where OpenGL commands can be performed.
  • int allegro_gl_set_mouse_sprite (BITMAP *sprite, int xfocus, int yfocus)
  • int allegro_gl_show_mouse (BITMAP *bmp, int x, int y)
  • void allegro_gl_hide_mouse (void)
  • void allegro_gl_move_mouse (int x, int y)

Variables

  • struct {
    •    GLuint    texture
    •    int    hidden
    •    int    xfocus
    •    int    yfocus
    •    int    width
    •    int    height
  • } allegro_gl_mouse
  • static void(* __algl_user_draw_mouse )(void) = NULL
  • static DIALOG alert_dialog []

Detailed Description

AllegroGL GUI wrappers.

These are replacements for Allegro's do_dialog routine and standard dialogs (to use our version of the routine).

Definition in file gui.c.


Define Documentation

#define SORT_OUT_BUTTON (   x)
Value:
{                                            \
      if (b##x) {                                                          \
     alert_dialog[A_B##x].flags &= ~D_HIDDEN;                          \
     alert_dialog[A_B##x].key = c##x;                                  \
     alert_dialog[A_B##x].dp = (char *)b##x;                           \
     len##x = gui_strlen(b##x);                                        \
     b[buttons++] = A_B##x;                                            \
      }                                                                    \
      else {                                                               \
     alert_dialog[A_B##x].flags |= D_HIDDEN;                           \
     len##x = 0;                                                       \
      }                                                                    \
   }

Variable Documentation

DIALOG alert_dialog[] [static]
Initial value:
{
   
   { _gui_shadow_box_proc, 0,    0,    0,    0,    0,    0,    0,    0,       0,    0,    NULL, NULL, NULL  },
   { _gui_ctext_proc,      0,    0,    0,    0,    0,    0,    0,    0,       0,    0,    NULL, NULL, NULL  },
   { _gui_ctext_proc,      0,    0,    0,    0,    0,    0,    0,    0,       0,    0,    NULL, NULL, NULL  },
   { _gui_ctext_proc,      0,    0,    0,    0,    0,    0,    0,    0,       0,    0,    NULL, NULL, NULL  },
   { _gui_button_proc,     0,    0,    0,    0,    0,    0,    0,    D_EXIT,  0,    0,    NULL, NULL, NULL  },
   { _gui_button_proc,     0,    0,    0,    0,    0,    0,    0,    D_EXIT,  0,    0,    NULL, NULL, NULL  },
   { _gui_button_proc,     0,    0,    0,    0,    0,    0,    0,    D_EXIT,  0,    0,    NULL, NULL, NULL  },
   { d_yield_proc,         0,    0,    0,    0,    0,    0,    0,    0,       0,    0,    NULL, NULL, NULL  },
   { NULL,                 0,    0,    0,    0,    0,    0,    0,    0,       0,    0,    NULL, NULL, NULL  }
}

Definition at line 295 of file gui.c.

allegro4.4-4.4.2/addons/allegrogl/docs/html/gui_8c_source.html000066400000000000000000001202341173507505700241500ustar00rootroot00000000000000 AllegroGL: gui.c Source File

gui.c

Go to the documentation of this file.
00001 /* This code is (C) AllegroGL contributors, and double licensed under
00002  * the GPL and zlib licenses. See gpl.txt or zlib.txt for details.
00003  */
00012 #include "alleggl.h"
00013 #include "allglint.h"
00014 
00015 #include <allegro/internal/aintern.h>
00016 
00017 
00018 static struct {
00019     GLuint texture;
00020     int hidden;
00021     int xfocus;
00022     int yfocus;
00023     int width;
00024     int height;
00025 } allegro_gl_mouse = { 0, TRUE, 0, 0, 0, 0};
00026 
00027 
00058 int algl_do_dialog (DIALOG *dialog, int focus_obj)
00059 {
00060     DIALOG_PLAYER *player;
00061 
00062     AGL_LOG(2, "allegro_gl_do_dialog\n");
00063 
00064     /* Allegro GUI routines generally use the 2D gfx functions therefore
00065        we set default behaviour to allegro_gl_set_allegro_mode so that we
00066        can use the GUI functions "as is" */
00067     allegro_gl_set_allegro_mode();
00068 
00069     player = init_dialog (dialog, focus_obj);
00070     show_mouse(screen);
00071 
00072     /* Nothing to do here.
00073      * Redrawing is done from d_algl_viewport_proc() callback. */
00074     while (update_dialog (player)) {}
00075 
00076     show_mouse(NULL);
00077     /* restore previous projection matrices */
00078     allegro_gl_unset_allegro_mode();
00079 
00080     return shutdown_dialog (player);
00081 }
00082 
00083 
00084 
00111 int algl_popup_dialog (DIALOG *dialog, int focus_obj)
00112 {
00113     void *backdrop;
00114     DIALOG_PLAYER *player;
00115     GLint read_buffer;
00116 
00117     AGL_LOG(2, "allegro_gl_popup_dialog\n");
00118 
00119     /* Allegro GUI routines generally use the 2D gfx functions therefore
00120        we set default behaviour to allegro_gl_set_allegro_mode so that we
00121        can use the GUI functions "as is" */
00122     allegro_gl_set_allegro_mode();
00123 
00124     glGetIntegerv(GL_READ_BUFFER, &read_buffer);
00125     glReadBuffer (GL_FRONT); /* TODO: don't clobber */
00126     glDisable(GL_DEPTH_TEST);
00127     backdrop = malloc (SCREEN_W * SCREEN_H * 3 * 4);
00128     glReadPixels (0, 0, SCREEN_W, SCREEN_H, GL_RGB, GL_UNSIGNED_BYTE, backdrop);
00129     glReadBuffer(read_buffer);
00130 
00131     player = init_dialog (dialog, focus_obj);
00132     show_mouse(screen);
00133 
00134     while (update_dialog (player)) {
00135 
00136         /* Redraw the GUI every frame */
00137         glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
00138         glRasterPos2f (0., SCREEN_H-.5); /* TODO: don't clobber */
00139         glDrawPixels (SCREEN_W, SCREEN_H, GL_RGB, GL_UNSIGNED_BYTE, backdrop);
00140         broadcast_dialog_message (MSG_DRAW, 0);
00141 
00142         /* Draw the mouse cursor */
00143         algl_draw_mouse();
00144 
00145         /* Flip buffers */
00146         allegro_gl_flip();
00147     }
00148 
00149     glRasterPos2f (0., SCREEN_H-.5); /* TODO: don't clobber */
00150     glDrawPixels (SCREEN_W, SCREEN_H, GL_RGB, GL_UNSIGNED_BYTE, backdrop);
00151     glEnable(GL_DEPTH_TEST);
00152     free (backdrop);
00153 
00154     show_mouse(NULL);
00155     /* restore previous projection matrices */
00156     allegro_gl_unset_allegro_mode();
00157 
00158     return shutdown_dialog (player);
00159 }
00160 
00161 
00162 
00163 /* User mouse drawing callback */
00164 static void (*__algl_user_draw_mouse)(void) = NULL;
00165 
00166 
00187 void algl_draw_mouse (void)
00188 {
00189     AGL_LOG(2, "allegro_gl_draw_mouse\n");
00190 
00191     /* don't draw the mouse if it's not in our window */
00192     if (!_mouse_on || allegro_gl_mouse.hidden) return;
00193 
00194     if (__algl_user_draw_mouse) {
00195 
00196         __algl_user_draw_mouse();
00197 
00198     } else {
00199 
00200 #if 0
00201         float x = mouse_x;
00202         float y = mouse_y;
00203 
00204         int depth_enabled = glIsEnabled (GL_DEPTH_TEST);
00205         int cull_enabled = glIsEnabled (GL_CULL_FACE);
00206         if (depth_enabled) glDisable (GL_DEPTH_TEST);
00207         if (cull_enabled) glDisable (GL_CULL_FACE);
00208 
00209         glBegin (GL_TRIANGLES);
00210 
00211             #define draw(dx,dy) \
00212                 glVertex2f (x + dx, y + dy); \
00213                 glVertex2f (x + dx, y + dy + 10); \
00214                 glVertex2f (x + dx + 7, y + dy + 7); \
00215                 glVertex2f (x + dx + 1.5, y + dy + 6); \
00216                 glVertex2f (x + dx + 5.5, y + dy + 14); \
00217                 glVertex2f (x + dx + 7.5, y + dy + 14); \
00218                 glVertex2f (x + dx + 3.5, y + dy + 6); \
00219                 glVertex2f (x + dx + 1.5, y + dy + 6); \
00220                 glVertex2f (x + dx + 7.5, y + dy + 14);
00221 
00222             glColor3f (0, 0, 0);
00223             draw(-1,0)
00224             draw(1,0)
00225             draw(0,-1)
00226             draw(0,1)
00227 
00228             glColor3f (1, 1, 1);
00229             draw(0,0)
00230 
00231             #undef draw
00232 
00233         glEnd();
00234 
00235         if (depth_enabled) glEnable (GL_DEPTH_TEST);
00236         if (cull_enabled) glEnable (GL_CULL_FACE);
00237 #endif
00238 
00239         int x = mouse_x - allegro_gl_mouse.xfocus;
00240         int y = mouse_y - allegro_gl_mouse.yfocus;
00241     
00242         glPushAttrib(GL_COLOR_BUFFER_BIT);
00243         glAlphaFunc(GL_GREATER, 0.5);
00244         glEnable(GL_TEXTURE_2D);
00245         glEnable(GL_ALPHA_TEST);
00246 
00247         glBindTexture(GL_TEXTURE_2D, allegro_gl_mouse.texture);
00248         glColor4f(1., 1., 1., 1.);
00249         glTranslatef(-0.375, -0.375, 0);
00250         glBegin(GL_QUADS);
00251             glTexCoord2f(0., 1.);
00252             glVertex2f(x, y);
00253             glTexCoord2f(0., 0.);
00254             glVertex2f(x, y + allegro_gl_mouse.height);
00255             glTexCoord2f(1., 0.);
00256             glVertex2f(x + allegro_gl_mouse.width, y + allegro_gl_mouse.height);
00257             glTexCoord2f(1., 1.);
00258             glVertex2f(x + allegro_gl_mouse.width, y);
00259         glEnd();
00260         glTranslatef(0.375, 0.375, 0);
00261         glPopAttrib();
00262         glBindTexture(GL_TEXTURE_2D, 0);
00263         glDisable(GL_TEXTURE_2D);
00264     }
00265 }
00266 
00267 
00284 void algl_set_mouse_drawer (void (*user_draw_mouse)(void))
00285 {
00286     AGL_LOG(2, "allegro_gl_set_mouse_drawer\n");
00287 
00288     __algl_user_draw_mouse = user_draw_mouse;
00289 }
00290 
00291 
00292 
00293 
00294 
00295 static DIALOG alert_dialog[] =
00296 {
00297    /* (dialog proc)        (x)   (y)   (w)   (h)   (fg)  (bg)  (key) (flags)  (d1)  (d2)  (dp)  (dp2) (dp3) */
00298    { _gui_shadow_box_proc, 0,    0,    0,    0,    0,    0,    0,    0,       0,    0,    NULL, NULL, NULL  },
00299    { _gui_ctext_proc,      0,    0,    0,    0,    0,    0,    0,    0,       0,    0,    NULL, NULL, NULL  },
00300    { _gui_ctext_proc,      0,    0,    0,    0,    0,    0,    0,    0,       0,    0,    NULL, NULL, NULL  },
00301    { _gui_ctext_proc,      0,    0,    0,    0,    0,    0,    0,    0,       0,    0,    NULL, NULL, NULL  },
00302    { _gui_button_proc,     0,    0,    0,    0,    0,    0,    0,    D_EXIT,  0,    0,    NULL, NULL, NULL  },
00303    { _gui_button_proc,     0,    0,    0,    0,    0,    0,    0,    D_EXIT,  0,    0,    NULL, NULL, NULL  },
00304    { _gui_button_proc,     0,    0,    0,    0,    0,    0,    0,    D_EXIT,  0,    0,    NULL, NULL, NULL  },
00305    { d_yield_proc,         0,    0,    0,    0,    0,    0,    0,    0,       0,    0,    NULL, NULL, NULL  },
00306    { NULL,                 0,    0,    0,    0,    0,    0,    0,    0,       0,    0,    NULL, NULL, NULL  }
00307 };
00308 
00309 
00310 #define A_S1  1
00311 #define A_S2  2
00312 #define A_S3  3
00313 #define A_B1  4
00314 #define A_B2  5
00315 #define A_B3  6
00316 
00317 
00318 
00329 int algl_alert3(AL_CONST char *s1, AL_CONST char *s2, AL_CONST char *s3, AL_CONST char *b1, AL_CONST char *b2, AL_CONST char *b3, int c1, int c2, int c3)
00330 {
00331    char tmp[16];
00332    int avg_w, avg_h;
00333    int len1, len2, len3;
00334    int maxlen = 0;
00335    int buttons = 0;
00336    int b[3];
00337    int c;
00338 
00339    AGL_LOG(2, "allegro_gl_alert3\n");
00340 
00341    #define SORT_OUT_BUTTON(x) {                                            \
00342       if (b##x) {                                                          \
00343      alert_dialog[A_B##x].flags &= ~D_HIDDEN;                          \
00344      alert_dialog[A_B##x].key = c##x;                                  \
00345      alert_dialog[A_B##x].dp = (char *)b##x;                           \
00346      len##x = gui_strlen(b##x);                                        \
00347      b[buttons++] = A_B##x;                                            \
00348       }                                                                    \
00349       else {                                                               \
00350      alert_dialog[A_B##x].flags |= D_HIDDEN;                           \
00351      len##x = 0;                                                       \
00352       }                                                                    \
00353    }
00354 
00355    usetc(tmp+usetc(tmp, ' '), 0);
00356 
00357    avg_w = text_length(font, tmp);
00358    avg_h = text_height(font);
00359 
00360    alert_dialog[A_S1].dp = alert_dialog[A_S2].dp = alert_dialog[A_S3].dp = 
00361    alert_dialog[A_B1].dp = alert_dialog[A_B2].dp = empty_string;
00362 
00363    if (s1) {
00364       alert_dialog[A_S1].dp = (char *)s1;
00365       maxlen = text_length(font, s1);
00366    }
00367 
00368    if (s2) {
00369       alert_dialog[A_S2].dp = (char *)s2;
00370       len1 = text_length(font, s2);
00371       if (len1 > maxlen)
00372      maxlen = len1;
00373    }
00374 
00375    if (s3) {
00376       alert_dialog[A_S3].dp = (char *)s3;
00377       len1 = text_length(font, s3);
00378       if (len1 > maxlen)
00379      maxlen = len1;
00380    }
00381 
00382    SORT_OUT_BUTTON(1);
00383    SORT_OUT_BUTTON(2);
00384    SORT_OUT_BUTTON(3);
00385 
00386    len1 = MAX(len1, MAX(len2, len3)) + avg_w*3;
00387    if (len1*buttons > maxlen)
00388       maxlen = len1*buttons;
00389 
00390    maxlen += avg_w*4;
00391    alert_dialog[0].w = maxlen;
00392    alert_dialog[A_S1].x = alert_dialog[A_S2].x = alert_dialog[A_S3].x = 
00393                         alert_dialog[0].x + maxlen/2;
00394 
00395    alert_dialog[A_B1].w = alert_dialog[A_B2].w = alert_dialog[A_B3].w = len1;
00396 
00397    alert_dialog[A_B1].x = alert_dialog[A_B2].x = alert_dialog[A_B3].x = 
00398                        alert_dialog[0].x + maxlen/2 - len1/2;
00399 
00400    if (buttons == 3) {
00401       alert_dialog[b[0]].x = alert_dialog[0].x + maxlen/2 - len1*3/2 - avg_w;
00402       alert_dialog[b[2]].x = alert_dialog[0].x + maxlen/2 + len1/2 + avg_w;
00403    }
00404    else if (buttons == 2) {
00405       alert_dialog[b[0]].x = alert_dialog[0].x + maxlen/2 - len1 - avg_w;
00406       alert_dialog[b[1]].x = alert_dialog[0].x + maxlen/2 + avg_w;
00407    }
00408 
00409    alert_dialog[0].h = avg_h*8;
00410    alert_dialog[A_S1].y = alert_dialog[0].y + avg_h;
00411    alert_dialog[A_S2].y = alert_dialog[0].y + avg_h*2;
00412    alert_dialog[A_S3].y = alert_dialog[0].y + avg_h*3;
00413    alert_dialog[A_S1].h = alert_dialog[A_S2].h = alert_dialog[A_S3].h = avg_h;
00414    alert_dialog[A_B1].y = alert_dialog[A_B2].y = alert_dialog[A_B3].y = alert_dialog[0].y + avg_h*5;
00415    alert_dialog[A_B1].h = alert_dialog[A_B2].h = alert_dialog[A_B3].h = avg_h*2;
00416 
00417    centre_dialog(alert_dialog);
00418    set_dialog_color(alert_dialog, gui_fg_color, gui_bg_color);
00419    for (c = 0; alert_dialog[c].proc; c++)
00420       if (alert_dialog[c].proc == _gui_ctext_proc)
00421      alert_dialog[c].bg = -1;
00422 
00423    clear_keybuf();
00424 
00425    do {
00426    } while (gui_mouse_b());
00427 
00428    c = algl_popup_dialog(alert_dialog, A_B1);
00429 
00430    if (c == A_B1)
00431       return 1;
00432    else if (c == A_B2)
00433       return 2;
00434    else
00435       return 3;
00436 }
00437 
00438 
00439 
00449 int algl_alert(AL_CONST char *s1, AL_CONST char *s2, AL_CONST char *s3, AL_CONST char *b1, AL_CONST char *b2, int c1, int c2)
00450 {
00451    int ret;
00452 
00453    AGL_LOG(2, "allegro_gl_alert\n");
00454 
00455    ret = algl_alert3(s1, s2, s3, b1, b2, NULL, c1, c2, 0);
00456 
00457    if (ret > 2)
00458       ret = 2;
00459 
00460    return ret;
00461 }
00462 
00463 
00464 
00477 int d_algl_viewport_proc(int msg, DIALOG *d, int c)
00478 {
00479     int ret = D_O_K;
00480     typedef int (*_callback)(BITMAP*, int, int);
00481     _callback callback = (_callback) d->dp;
00482     BITMAP *viewport = create_sub_bitmap(screen, d->x, d->y, d->w, d->h);
00483 
00484     AGL_LOG(3, "d_algl_viewport_proc\n");
00485 
00486     if (msg == MSG_DRAW) {
00487         /* Draws the background */
00488         clear_to_color(viewport, d->bg);
00489     }
00490 
00491     /* First we get back into a 3D mode */
00492     allegro_gl_unset_allegro_mode();
00493 
00494     /* Save the Viewport and Scissor states */
00495     glPushAttrib(GL_SCISSOR_BIT | GL_VIEWPORT_BIT);
00496 
00497     /* Adapt the viewport to the object size */
00498     glViewport(d->x, SCREEN_H - d->y - d->h, d->w, d->h);
00499     glScissor(d->x, SCREEN_H - d->y - d->h, d->w, d->h);
00500     glEnable(GL_SCISSOR_TEST);
00501     
00502     /* Clear the depth buffer for this scissor region */
00503     if (msg == MSG_DRAW) {
00504         glClear(GL_DEPTH_BUFFER_BIT);
00505     }
00506 
00507     /* Call the callback function */
00508     if (callback)
00509         ret = callback(viewport, msg, c);
00510 
00511     /* Restore the previous state */
00512     glPopAttrib();
00513     allegro_gl_set_allegro_mode();
00514     destroy_bitmap(viewport);
00515 
00516     /* Redraw the GUI every frame */
00517     if (msg == MSG_IDLE) {
00518         glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
00519         broadcast_dialog_message (MSG_DRAW, 0);
00520 
00521         /* Draw the mouse cursor */
00522         algl_draw_mouse();
00523 
00524         /* Flip buffers */
00525         allegro_gl_flip();
00526     }
00527 
00528 
00529     return ret;
00530 }
00531 
00532 
00533 
00534 /*****************/
00535 /* Mouse manager */
00536 /*****************/
00537 
00538 int allegro_gl_set_mouse_sprite(BITMAP *sprite, int xfocus, int yfocus)
00539 {
00540     BITMAP *bmp = NULL;
00541     GLint old_texture;
00542     
00543     AGL_LOG(2, "allegro_gl_set_mouse_sprite\n");
00544 
00545     glGetIntegerv(GL_TEXTURE_2D_BINDING, &old_texture);
00546 
00547     bmp = create_bitmap_ex(bitmap_color_depth(sprite),
00548              __allegro_gl_make_power_of_2(sprite->w),
00549              __allegro_gl_make_power_of_2(sprite->h));
00550 
00551     if (allegro_gl_mouse.texture) {
00552         glDeleteTextures(1, &allegro_gl_mouse.texture);
00553         allegro_gl_mouse.texture = 0;
00554     }
00555     
00556     clear_to_color(bmp, bitmap_mask_color(sprite));
00557     blit(sprite, bmp, 0, 0, 0, 0, sprite->w, sprite->h);
00558 #ifdef DEBUGMODE
00559     save_bmp("mcursor.bmp",bmp,NULL);
00560 #endif
00561 
00562     allegro_gl_mouse.texture = allegro_gl_make_texture_ex(AGL_TEXTURE_RESCALE
00563                             | AGL_TEXTURE_MASKED | AGL_TEXTURE_FLIP, bmp, -1);
00564     if (!allegro_gl_mouse.texture) {
00565         destroy_bitmap(bmp);
00566         return -1;
00567     }
00568 
00569     glBindTexture(GL_TEXTURE_2D, allegro_gl_mouse.texture);
00570     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
00571     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
00572     
00573     if (allegro_gl_extensions_GL.SGIS_texture_edge_clamp) {
00574         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
00575         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
00576     }
00577     else {
00578         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
00579         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
00580     }
00581 
00582     glBindTexture(GL_TEXTURE_2D, old_texture);
00583 
00584     allegro_gl_mouse.width  = bmp->w;
00585     allegro_gl_mouse.height = bmp->h;
00586     allegro_gl_mouse.xfocus = xfocus;
00587     allegro_gl_mouse.yfocus = yfocus;
00588 
00589     destroy_bitmap(bmp);
00590     return 0;
00591 }
00592 
00593 
00594 
00595 int allegro_gl_show_mouse(BITMAP* bmp, int x, int y)
00596 {
00597     AGL_LOG(3, "allegro_gl_show_mouse\n");
00598     allegro_gl_mouse.hidden = FALSE;
00599     return 0;
00600 }
00601 
00602 
00603 
00604 void allegro_gl_hide_mouse(void)
00605 {
00606     AGL_LOG(3, "allegro_gl_hide_mouse\n");
00607     allegro_gl_mouse.hidden = TRUE;
00608 }
00609 
00610 
00611 
00612 void allegro_gl_move_mouse(int x, int y)
00613 {
00614     AGL_LOG(3, "allegro_gl_move_mouse\n");
00615     /* This function is not called from the main thread, so
00616      * we must not call any OpenGL command there !!!
00617      */
00618 }
00619 
allegro4.4-4.4.2/addons/allegrogl/docs/html/index.hhc000066400000000000000000000730471173507505700223300ustar00rootroot00000000000000
allegro4.4-4.4.2/addons/allegrogl/docs/html/index.hhk000066400000000000000000007340021173507505700223330ustar00rootroot00000000000000
allegro4.4-4.4.2/addons/allegrogl/docs/html/index.hhp000066400000000000000000000024341173507505700223350ustar00rootroot00000000000000[OPTIONS] Compatibility=1.1 Full-text search=Yes Contents file=index.hhc Default Window=main Default topic=index.html Index file=index.hhk Language=0x409 English (United States) Title=AllegroGL [WINDOWS] main="AllegroGL","index.hhc","index.hhk","index.html","index.html",,,,,0x23520,,0x10387e,,,,,,,,0 [FILES] index.html pages.html aglf_8c_source.html alleggl_8c_source.html alleggl_8h_source.html allglint_8h_source.html djgpp_8c_source.html fontconv_8c_source.html glext_8c_source.html glvtable_8c_source.html glvtable_8h_source.html gui_8c_source.html mainpage_8foo_source.html math_8c_source.html scorer_8c_source.html texture_8c_source.html videovtb_8c_source.html win_8c_source.html x_8c_source.html aglf_8c.html alleggl_8c.html alleggl_8h.html fontconv_8c.html glext_8c.html glvtable_8c.html gui_8c.html mainpage_8foo.html math_8c.html scorer_8c.html texture_8c.html videovtb_8c.html deprecated.html group__version.html group__core.html group__gfxdrv.html group__bitmap.html group__texture.html group__math.html group__Text.html group__extensions.html group__gui.html group__glvtable.html group__settings.html group__allegro.html modules.html files.html globals.html globals_func.html globals_vars.html globals_defs.html tabs.css tab_a.png tab_b.png tab_h.png tab_s.png nav_h.png nav_f.png bc_s.png allegro4.4-4.4.2/addons/allegrogl/docs/html/index.html000066400000000000000000000404161173507505700225240ustar00rootroot00000000000000 AllegroGL: AllegroGL

AllegroGL

Table Of Contents:

About AllegroGL

The library mostly provides functions to allow you to use OpenGL alongside Allegro -- you use OpenGL for your rendering to the screen, and Allegro for miscellaneous tasks like gathering input, doing timers, getting cross-platform portability, loading data, and drawing your textures. So this library fills the same hole that things like glut do.

AllegroGL also automatically exposes most, if not all, OpenGL extensions available to user programs. This means you no longer have to manually load them; extension management is already done for you.

License

The code is (C) AllegroGL contributors, and double licensed under the GPL and zlib licenses. See gpl.txt or zlib.txt for details. (You can pick whichever one you prefer.)

About this document

This document contains installation instructions, description of the API, reference manual, and pointers to other resources such as the FAQ, web page and the mailing list.

General build instructions

From version 0.4.4 onwards, AllegroGL is an addon library for Allegro and the usual way to build it is by following the allegro compilation procedure. It will configure, build and install AllegroGL using default options (a shared release library).

However, you if you need a custom compiled library, e.g. with debug symbols or a statically linked one, you can build AllegroGL manually, passing custom build options.

Requirements

General requirement: If you are building AllegroGL separatelly (outside Allegro compilation procedure) it will depend on Allegro being successfully built two directories above.

Unix: You need an X server which provides the OpenGL/GLX functionality. If you have successfully installed 3D drivers (NVidia, DRI drivers, ...) then OpenGL/GLX libraries are already installed. Otherwise XFree86 4.x has OpenGL/GLX built in. We have also successfully used an earlier version, with development snapshots of Mesa3D 3.2 and GLX extensions.

You also need to get the GLU library, preferably the SGI's one (see the Mesa sourceforge webpage - http://Mesa3D.sf.net/ ).

If you want to build the generic driver you need Mesa 4.0 or higher (only the "MesaLib" archive is mandatory, the "MesaDemos" one is optionnal).

Links to the relevant sites can be found on the AllegroGL web site.

Windows/MSVC: MSVC6 or MSVC2005 IDE or GNU make is required for MSVC.

Windows/Mingw: If you use Mingw, you'll need the OpenGL header files and libraries. These are normally included with Mingw.

In case your copy of Mingw does not have the OpenGL headers, you can grab them here: ftp://ftp.microsoft.com/softlib/mslfiles/opengl95.exe This is a self-extracting archive.

You'll also need GNU make (mingw32-make) to compile AllegroGL.

DOS: You need DJGPP and Mesa 4.0 http://Mesa3D.sf.net/ for OpenGL rendering (only the "MesaLib" archive is mandatory, the "MesaDemos" one is optionnal).

Mac OS X: System version 10.1.x or newer is required to build AllegroGL. Allegro WIP 4.1.11 or newer is also required, as older versions did not support OS X.

Installation

Unix instructions

For an optimised build, run `./configure' and `make' from the directory containing this file. This will build the library (in 'lib/unix/') and the examples (in 'examp/'). Use `make install' to install the library and header file. For that part you need write access to /usr/local.

If you want to build the generic driver, run `./configure --enable-generic' and `make MESADIR=xxx' where xxx is the path to the Mesa 4.0 directory. This will build both Mesa (GL and GLU) and AllegroGL

For a debug build, add `DEBUGMODE=1' on each of the command lines.

If you get errors about missing header files or libraries, either for X or GL, see the instructions at the top of `makefile'. Note that you need to have the X development package installed, if you are using Red Hat Linux or Debian GNU/Linux.

Mingw/32 instructions

Mingw 2.0 and higher already come with the OpenGL header files and libraries, so you can skip the next step.

If you don't have the OpenGL header files (GL\gl.h) and libraries, you will first need to acquire thrm. These can be obtained from the Microsoft site, or from MSVC.

If you obtained the self-extracting archive from the Microsoft site, then run it. Move the produced header files (*.h) into C:\Mingw32\include\GL\ (replace C:\Mingw32 by wherever you happen to have installed Mingw). Ignore the other files, as they are only useful for MSVC.

You need to set up your environment if you haven't done that already. Environment variable "PATH" should point to the "bin" directory of Mingw. You can check that by typing "gcc" in the console. It must display something like: "gcc: no input files". If it complains about a unknown command then type "set PATH=%PATH%;C:\Mingw32\bin" (replace C:\Mingw32 by wherever you happen to have installed Mingw). Also, you need to set MINGDIR env. variable. It must point to Mingw instalation directory: "set MINGDIR=C:\Mingw32". You can check that with: "echo %MINGDIR%".

You will need to run 'fix mingw32' in the AllegroGL directory to update makefile for Mingw32. Since both Allegro and AllegroGL have native Mingw support I am happy to say that you can build Allegro/AllegroGL programs entirely using free software.

For an optimised build, run `make' from the directory containing this file. Use `make install' to install the library and header file. Some versions of Mingw come with `mingw32-make' instead of `make', so you may need to run that instead.

For a debug build, do the same but write `DEBUGMODE=1' on each of the command lines; for example, 'make DEBUGMODE=1' and 'make install DEBUGMODE=1'.

Add 'STATICLINK=1' to the last two commands to build AllegroGL that can be linked to statically linked allegro.

MSVC6/7/8 instructions

There are two completely different ways of compiling AllegroGL using MSVC. You can use the old-fashion way decribed bellow (similar to building allegro, using a GNU makefile and a command line), or you can locate the project file for your MSVC version in "projects" directory and compile AllegroGL lib and examples with a few mouse clicks. You'll have to manually copy libs and headers to appropiate locations. You can choose between several build configuration, depending against which Allegro library you want AllegroGL to be linked to. These configurations are:

 
   _____________________________________________________________
  | Configuration name  |    AGL lib name    | Allegro lib name |
  |-------------------------------------------------------------|
  | Release             | agl.lib            | alleg.lib        |
  | DLL Release         | agl.lib & agl.dll  | alleg.lib        |
  | Static Release      | agl_s.lib          | alleg_s.lib      |
  | Static Release CRT  | agl_s_crt.lib      | alleg_s_crt.lib  |
  | Debug               | agld.lib           | alld.lib         |
  | Static Debug        | agld_s.lib         | alld_s.lib       |
   -------------------------------------------------------------

All configuration except "DLL Release" produce AllegroGL library that is statically linked to the executable.

Instructione for compiling AllegroGL using command line follow.

You must have a working copy of GNU Make (useful for building Allegro, anyway). This can be either DJGPP's or Mingw's (recommended).

Step 1:

The first thing you need to do is find `vcvars32.bat', somewhere in your Visual Studio directories (most probably, it's in 'vc98/bin'). Running this batch file will enable the command line compiler for the current DOS session. If you will use it often, or find that typing 'c:\progra~1\micros~2\vc98\bin\vcvars32.bat' gets annoying after a while, then (under Windows 9X) simply add that command to your autoexec.bat**

Note: If at any stage, you get an "Out of Environment space" message, then please see the Allegro FAQ for how to fix this.

The procedure is different for Windows ME and later. If you're running Windows ME, you'll need to select "Run" off the start menu, then type in "msconfig". Select the environment tab. Add the lines inside vcvars32.bat in there by copy/pasting them. Reboot your computer for the changes to take effect.

If you're running Windows 2000/XP (NT?), then open Control Pannel, then the "System" applet, then the "Advanced" tab, and finally the "Environment" button. Add the environment variables as they are in vcvars32.bat. This has to be done manually (yes it's long and painful, please redirect all flames to billg@microsoft.com) You will need to log off and log back in for the changes to take effect.

Step 2:

Much like making Allegro, to configure AllegroGL for your compiler please run in the command prompt:

fix.bat msvc6 - for MSVC 6 and older fix.bat msvc7 - for MSVC 7 (.NET) and 7.1 (.NET 2003) fix.bat msvc8 - for MSVC 8 (.NET 2005)

Then type `make' to build the library in optimized mode, then `make install' to install the library and header files in your MSVC directory.

For a debugging version, add `DEBUGMODE=1', to the last two command lines.

To link against a static runtime libraries, rather than the default dynamic runtime libraries, add STATICRUNTIME=1, to the last two command lines.

To link aginst a static version of allegro, add STATICLINK=1, to the last two command lines.

If you are using Mingw for GNU make, then you may need to run `mingw32-make' instead of `make'.

Dos instructions

Please note that DOS support is currently in experimental stages.

Unzip the archive files MesaLib-4.0.zip wherever you want. Unzip AllegroGL

Create the environment variable MESADIR which defines the Mesa sources path : set MESADIR=xxx where 'xxx' is the path to the Mesa root directory

Go to the root directory of AllegroGL type 'fix djgpp' (without quotes) followed by 'make'. The GL, GLU and AllegroGL libraries are built. Finally type 'make install' to install the library

You're done! You can now use AllegroGL on DOS. Try the example demos...

For a debug build, do the same but write `DEBUGMODE=1' on each of the command lines.

Note that you can also build :

  • The GLUT library (based on AMesa, Allegro and Mesa). Type 'make glut' to build it then 'make install-glut' to install it.
  • The Mesa samples to test both Mesa and GLUT (note that you need to download the MesaDemos archive file to compile mesa samples). Type 'make mesa-samples' (Please note that not all the sample programs will be built. Now, as of Mesa 3.4.2, most demos are for GLUT which has not yet been completely ported to AMesa/Allegro).

Mac OS X instructions

First you will need to run `./fix.sh macosx' in order to prepare the makefile for Mac OS X. Then `make' will build the library (in `lib/macosx') and the examples (in `examp/'). Use `sudo make install' to install the library and the header files; this step will require your system root password and will install into /usr/local.

For a debug build, add `DEBUGMODE=1' on `make' and `make install' calls, for example, `make DEBUGMODE=1' and `sudo make install DEBUGMODE=1'.

Using AllegroGL

A reference to the functions and macros available to user programs can be found by clicking on the links on top of this document, or online at the web site, and is also downloadable from there in various formats.

The quick start guide and the FAQ are included in the distribution in the root directory.

More information

web site: http://allegrogl.sourceforge.net/

The web site has introductory information, system requirements, downloads, and Allegro patches, along with an online version of the reference manual.

mailing list: allegrogl-general@lists.sourceforge.net

All the developers are on this mailing list, and most of the discussion here is about future development and bug fixing. General questions about using the library make a welcome change from the hard work of development, so newcomers are very welcome! If you're not subscribed to the list, make this clear when you post, so that people can Cc: their replies to you.

Closing Words

Good luck...

-- The AllegroGL team

allegro4.4-4.4.2/addons/allegrogl/docs/html/jquery.js000066400000000000000000002456221173507505700224120ustar00rootroot00000000000000/* * jQuery JavaScript Library v1.3.2 * http://jquery.com/ * * Copyright (c) 2009 John Resig * Dual licensed under the MIT and GPL licenses. * http://docs.jquery.com/License * * Date: 2009-02-19 17:34:21 -0500 (Thu, 19 Feb 2009) * Revision: 6246 */ (function(){var l=this,g,y=l.jQuery,p=l.$,o=l.jQuery=l.$=function(E,F){return new o.fn.init(E,F)},D=/^[^<]*(<(.|\s)+>)[^>]*$|^#([\w-]+)$/,f=/^.[^:#\[\.,]*$/;o.fn=o.prototype={init:function(E,H){E=E||document;if(E.nodeType){this[0]=E;this.length=1;this.context=E;return this}if(typeof E==="string"){var G=D.exec(E);if(G&&(G[1]||!H)){if(G[1]){E=o.clean([G[1]],H)}else{var I=document.getElementById(G[3]);if(I&&I.id!=G[3]){return o().find(E)}var F=o(I||[]);F.context=document;F.selector=E;return F}}else{return o(H).find(E)}}else{if(o.isFunction(E)){return o(document).ready(E)}}if(E.selector&&E.context){this.selector=E.selector;this.context=E.context}return this.setArray(o.isArray(E)?E:o.makeArray(E))},selector:"",jquery:"1.3.2",size:function(){return this.length},get:function(E){return E===g?Array.prototype.slice.call(this):this[E]},pushStack:function(F,H,E){var G=o(F);G.prevObject=this;G.context=this.context;if(H==="find"){G.selector=this.selector+(this.selector?" ":"")+E}else{if(H){G.selector=this.selector+"."+H+"("+E+")"}}return G},setArray:function(E){this.length=0;Array.prototype.push.apply(this,E);return this},each:function(F,E){return o.each(this,F,E)},index:function(E){return o.inArray(E&&E.jquery?E[0]:E,this)},attr:function(F,H,G){var E=F;if(typeof F==="string"){if(H===g){return this[0]&&o[G||"attr"](this[0],F)}else{E={};E[F]=H}}return this.each(function(I){for(F in E){o.attr(G?this.style:this,F,o.prop(this,E[F],G,I,F))}})},css:function(E,F){if((E=="width"||E=="height")&&parseFloat(F)<0){F=g}return this.attr(E,F,"curCSS")},text:function(F){if(typeof F!=="object"&&F!=null){return this.empty().append((this[0]&&this[0].ownerDocument||document).createTextNode(F))}var E="";o.each(F||this,function(){o.each(this.childNodes,function(){if(this.nodeType!=8){E+=this.nodeType!=1?this.nodeValue:o.fn.text([this])}})});return E},wrapAll:function(E){if(this[0]){var F=o(E,this[0].ownerDocument).clone();if(this[0].parentNode){F.insertBefore(this[0])}F.map(function(){var G=this;while(G.firstChild){G=G.firstChild}return G}).append(this)}return this},wrapInner:function(E){return this.each(function(){o(this).contents().wrapAll(E)})},wrap:function(E){return this.each(function(){o(this).wrapAll(E)})},append:function(){return this.domManip(arguments,true,function(E){if(this.nodeType==1){this.appendChild(E)}})},prepend:function(){return this.domManip(arguments,true,function(E){if(this.nodeType==1){this.insertBefore(E,this.firstChild)}})},before:function(){return this.domManip(arguments,false,function(E){this.parentNode.insertBefore(E,this)})},after:function(){return this.domManip(arguments,false,function(E){this.parentNode.insertBefore(E,this.nextSibling)})},end:function(){return this.prevObject||o([])},push:[].push,sort:[].sort,splice:[].splice,find:function(E){if(this.length===1){var F=this.pushStack([],"find",E);F.length=0;o.find(E,this[0],F);return F}else{return this.pushStack(o.unique(o.map(this,function(G){return o.find(E,G)})),"find",E)}},clone:function(G){var E=this.map(function(){if(!o.support.noCloneEvent&&!o.isXMLDoc(this)){var I=this.outerHTML;if(!I){var J=this.ownerDocument.createElement("div");J.appendChild(this.cloneNode(true));I=J.innerHTML}return o.clean([I.replace(/ jQuery\d+="(?:\d+|null)"/g,"").replace(/^\s*/,"")])[0]}else{return this.cloneNode(true)}});if(G===true){var H=this.find("*").andSelf(),F=0;E.find("*").andSelf().each(function(){if(this.nodeName!==H[F].nodeName){return}var I=o.data(H[F],"events");for(var K in I){for(var J in I[K]){o.event.add(this,K,I[K][J],I[K][J].data)}}F++})}return E},filter:function(E){return this.pushStack(o.isFunction(E)&&o.grep(this,function(G,F){return E.call(G,F)})||o.multiFilter(E,o.grep(this,function(F){return F.nodeType===1})),"filter",E)},closest:function(E){var G=o.expr.match.POS.test(E)?o(E):null,F=0;return this.map(function(){var H=this;while(H&&H.ownerDocument){if(G?G.index(H)>-1:o(H).is(E)){o.data(H,"closest",F);return H}H=H.parentNode;F++}})},not:function(E){if(typeof E==="string"){if(f.test(E)){return this.pushStack(o.multiFilter(E,this,true),"not",E)}else{E=o.multiFilter(E,this)}}var F=E.length&&E[E.length-1]!==g&&!E.nodeType;return this.filter(function(){return F?o.inArray(this,E)<0:this!=E})},add:function(E){return this.pushStack(o.unique(o.merge(this.get(),typeof E==="string"?o(E):o.makeArray(E))))},is:function(E){return !!E&&o.multiFilter(E,this).length>0},hasClass:function(E){return !!E&&this.is("."+E)},val:function(K){if(K===g){var E=this[0];if(E){if(o.nodeName(E,"option")){return(E.attributes.value||{}).specified?E.value:E.text}if(o.nodeName(E,"select")){var I=E.selectedIndex,L=[],M=E.options,H=E.type=="select-one";if(I<0){return null}for(var F=H?I:0,J=H?I+1:M.length;F=0||o.inArray(this.name,K)>=0)}else{if(o.nodeName(this,"select")){var N=o.makeArray(K);o("option",this).each(function(){this.selected=(o.inArray(this.value,N)>=0||o.inArray(this.text,N)>=0)});if(!N.length){this.selectedIndex=-1}}else{this.value=K}}})},html:function(E){return E===g?(this[0]?this[0].innerHTML.replace(/ jQuery\d+="(?:\d+|null)"/g,""):null):this.empty().append(E)},replaceWith:function(E){return this.after(E).remove()},eq:function(E){return this.slice(E,+E+1)},slice:function(){return this.pushStack(Array.prototype.slice.apply(this,arguments),"slice",Array.prototype.slice.call(arguments).join(","))},map:function(E){return this.pushStack(o.map(this,function(G,F){return E.call(G,F,G)}))},andSelf:function(){return this.add(this.prevObject)},domManip:function(J,M,L){if(this[0]){var I=(this[0].ownerDocument||this[0]).createDocumentFragment(),F=o.clean(J,(this[0].ownerDocument||this[0]),I),H=I.firstChild;if(H){for(var G=0,E=this.length;G1||G>0?I.cloneNode(true):I)}}if(F){o.each(F,z)}}return this;function K(N,O){return M&&o.nodeName(N,"table")&&o.nodeName(O,"tr")?(N.getElementsByTagName("tbody")[0]||N.appendChild(N.ownerDocument.createElement("tbody"))):N}}};o.fn.init.prototype=o.fn;function z(E,F){if(F.src){o.ajax({url:F.src,async:false,dataType:"script"})}else{o.globalEval(F.text||F.textContent||F.innerHTML||"")}if(F.parentNode){F.parentNode.removeChild(F)}}function e(){return +new Date}o.extend=o.fn.extend=function(){var J=arguments[0]||{},H=1,I=arguments.length,E=false,G;if(typeof J==="boolean"){E=J;J=arguments[1]||{};H=2}if(typeof J!=="object"&&!o.isFunction(J)){J={}}if(I==H){J=this;--H}for(;H-1}},swap:function(H,G,I){var E={};for(var F in G){E[F]=H.style[F];H.style[F]=G[F]}I.call(H);for(var F in G){H.style[F]=E[F]}},css:function(H,F,J,E){if(F=="width"||F=="height"){var L,G={position:"absolute",visibility:"hidden",display:"block"},K=F=="width"?["Left","Right"]:["Top","Bottom"];function I(){L=F=="width"?H.offsetWidth:H.offsetHeight;if(E==="border"){return}o.each(K,function(){if(!E){L-=parseFloat(o.curCSS(H,"padding"+this,true))||0}if(E==="margin"){L+=parseFloat(o.curCSS(H,"margin"+this,true))||0}else{L-=parseFloat(o.curCSS(H,"border"+this+"Width",true))||0}})}if(H.offsetWidth!==0){I()}else{o.swap(H,G,I)}return Math.max(0,Math.round(L))}return o.curCSS(H,F,J)},curCSS:function(I,F,G){var L,E=I.style;if(F=="opacity"&&!o.support.opacity){L=o.attr(E,"opacity");return L==""?"1":L}if(F.match(/float/i)){F=w}if(!G&&E&&E[F]){L=E[F]}else{if(q.getComputedStyle){if(F.match(/float/i)){F="float"}F=F.replace(/([A-Z])/g,"-$1").toLowerCase();var M=q.getComputedStyle(I,null);if(M){L=M.getPropertyValue(F)}if(F=="opacity"&&L==""){L="1"}}else{if(I.currentStyle){var J=F.replace(/\-(\w)/g,function(N,O){return O.toUpperCase()});L=I.currentStyle[F]||I.currentStyle[J];if(!/^\d+(px)?$/i.test(L)&&/^\d/.test(L)){var H=E.left,K=I.runtimeStyle.left;I.runtimeStyle.left=I.currentStyle.left;E.left=L||0;L=E.pixelLeft+"px";E.left=H;I.runtimeStyle.left=K}}}}return L},clean:function(F,K,I){K=K||document;if(typeof K.createElement==="undefined"){K=K.ownerDocument||K[0]&&K[0].ownerDocument||document}if(!I&&F.length===1&&typeof F[0]==="string"){var H=/^<(\w+)\s*\/?>$/.exec(F[0]);if(H){return[K.createElement(H[1])]}}var G=[],E=[],L=K.createElement("div");o.each(F,function(P,S){if(typeof S==="number"){S+=""}if(!S){return}if(typeof S==="string"){S=S.replace(/(<(\w+)[^>]*?)\/>/g,function(U,V,T){return T.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i)?U:V+">"});var O=S.replace(/^\s+/,"").substring(0,10).toLowerCase();var Q=!O.indexOf("",""]||!O.indexOf("",""]||O.match(/^<(thead|tbody|tfoot|colg|cap)/)&&[1,"","
"]||!O.indexOf("",""]||(!O.indexOf("",""]||!O.indexOf("",""]||!o.support.htmlSerialize&&[1,"div
","
"]||[0,"",""];L.innerHTML=Q[1]+S+Q[2];while(Q[0]--){L=L.lastChild}if(!o.support.tbody){var R=/"&&!R?L.childNodes:[];for(var M=N.length-1;M>=0;--M){if(o.nodeName(N[M],"tbody")&&!N[M].childNodes.length){N[M].parentNode.removeChild(N[M])}}}if(!o.support.leadingWhitespace&&/^\s/.test(S)){L.insertBefore(K.createTextNode(S.match(/^\s*/)[0]),L.firstChild)}S=o.makeArray(L.childNodes)}if(S.nodeType){G.push(S)}else{G=o.merge(G,S)}});if(I){for(var J=0;G[J];J++){if(o.nodeName(G[J],"script")&&(!G[J].type||G[J].type.toLowerCase()==="text/javascript")){E.push(G[J].parentNode?G[J].parentNode.removeChild(G[J]):G[J])}else{if(G[J].nodeType===1){G.splice.apply(G,[J+1,0].concat(o.makeArray(G[J].getElementsByTagName("script"))))}I.appendChild(G[J])}}return E}return G},attr:function(J,G,K){if(!J||J.nodeType==3||J.nodeType==8){return g}var H=!o.isXMLDoc(J),L=K!==g;G=H&&o.props[G]||G;if(J.tagName){var F=/href|src|style/.test(G);if(G=="selected"&&J.parentNode){J.parentNode.selectedIndex}if(G in J&&H&&!F){if(L){if(G=="type"&&o.nodeName(J,"input")&&J.parentNode){throw"type property can't be changed"}J[G]=K}if(o.nodeName(J,"form")&&J.getAttributeNode(G)){return J.getAttributeNode(G).nodeValue}if(G=="tabIndex"){var I=J.getAttributeNode("tabIndex");return I&&I.specified?I.value:J.nodeName.match(/(button|input|object|select|textarea)/i)?0:J.nodeName.match(/^(a|area)$/i)&&J.href?0:g}return J[G]}if(!o.support.style&&H&&G=="style"){return o.attr(J.style,"cssText",K)}if(L){J.setAttribute(G,""+K)}var E=!o.support.hrefNormalized&&H&&F?J.getAttribute(G,2):J.getAttribute(G);return E===null?g:E}if(!o.support.opacity&&G=="opacity"){if(L){J.zoom=1;J.filter=(J.filter||"").replace(/alpha\([^)]*\)/,"")+(parseInt(K)+""=="NaN"?"":"alpha(opacity="+K*100+")")}return J.filter&&J.filter.indexOf("opacity=")>=0?(parseFloat(J.filter.match(/opacity=([^)]*)/)[1])/100)+"":""}G=G.replace(/-([a-z])/ig,function(M,N){return N.toUpperCase()});if(L){J[G]=K}return J[G]},trim:function(E){return(E||"").replace(/^\s+|\s+$/g,"")},makeArray:function(G){var E=[];if(G!=null){var F=G.length;if(F==null||typeof G==="string"||o.isFunction(G)||G.setInterval){E[0]=G}else{while(F){E[--F]=G[F]}}}return E},inArray:function(G,H){for(var E=0,F=H.length;E0?this.clone(true):this).get();o.fn[F].apply(o(L[K]),I);J=J.concat(I)}return this.pushStack(J,E,G)}});o.each({removeAttr:function(E){o.attr(this,E,"");if(this.nodeType==1){this.removeAttribute(E)}},addClass:function(E){o.className.add(this,E)},removeClass:function(E){o.className.remove(this,E)},toggleClass:function(F,E){if(typeof E!=="boolean"){E=!o.className.has(this,F)}o.className[E?"add":"remove"](this,F)},remove:function(E){if(!E||o.filter(E,[this]).length){o("*",this).add([this]).each(function(){o.event.remove(this);o.removeData(this)});if(this.parentNode){this.parentNode.removeChild(this)}}},empty:function(){o(this).children().remove();while(this.firstChild){this.removeChild(this.firstChild)}}},function(E,F){o.fn[E]=function(){return this.each(F,arguments)}});function j(E,F){return E[0]&&parseInt(o.curCSS(E[0],F,true),10)||0}var h="jQuery"+e(),v=0,A={};o.extend({cache:{},data:function(F,E,G){F=F==l?A:F;var H=F[h];if(!H){H=F[h]=++v}if(E&&!o.cache[H]){o.cache[H]={}}if(G!==g){o.cache[H][E]=G}return E?o.cache[H][E]:H},removeData:function(F,E){F=F==l?A:F;var H=F[h];if(E){if(o.cache[H]){delete o.cache[H][E];E="";for(E in o.cache[H]){break}if(!E){o.removeData(F)}}}else{try{delete F[h]}catch(G){if(F.removeAttribute){F.removeAttribute(h)}}delete o.cache[H]}},queue:function(F,E,H){if(F){E=(E||"fx")+"queue";var G=o.data(F,E);if(!G||o.isArray(H)){G=o.data(F,E,o.makeArray(H))}else{if(H){G.push(H)}}}return G},dequeue:function(H,G){var E=o.queue(H,G),F=E.shift();if(!G||G==="fx"){F=E[0]}if(F!==g){F.call(H)}}});o.fn.extend({data:function(E,G){var H=E.split(".");H[1]=H[1]?"."+H[1]:"";if(G===g){var F=this.triggerHandler("getData"+H[1]+"!",[H[0]]);if(F===g&&this.length){F=o.data(this[0],E)}return F===g&&H[1]?this.data(H[0]):F}else{return this.trigger("setData"+H[1]+"!",[H[0],G]).each(function(){o.data(this,E,G)})}},removeData:function(E){return this.each(function(){o.removeData(this,E)})},queue:function(E,F){if(typeof E!=="string"){F=E;E="fx"}if(F===g){return o.queue(this[0],E)}return this.each(function(){var G=o.queue(this,E,F);if(E=="fx"&&G.length==1){G[0].call(this)}})},dequeue:function(E){return this.each(function(){o.dequeue(this,E)})}}); /* * Sizzle CSS Selector Engine - v0.9.3 * Copyright 2009, The Dojo Foundation * Released under the MIT, BSD, and GPL Licenses. * More information: http://sizzlejs.com/ */ (function(){var R=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?/g,L=0,H=Object.prototype.toString;var F=function(Y,U,ab,ac){ab=ab||[];U=U||document;if(U.nodeType!==1&&U.nodeType!==9){return[]}if(!Y||typeof Y!=="string"){return ab}var Z=[],W,af,ai,T,ad,V,X=true;R.lastIndex=0;while((W=R.exec(Y))!==null){Z.push(W[1]);if(W[2]){V=RegExp.rightContext;break}}if(Z.length>1&&M.exec(Y)){if(Z.length===2&&I.relative[Z[0]]){af=J(Z[0]+Z[1],U)}else{af=I.relative[Z[0]]?[U]:F(Z.shift(),U);while(Z.length){Y=Z.shift();if(I.relative[Y]){Y+=Z.shift()}af=J(Y,af)}}}else{var ae=ac?{expr:Z.pop(),set:E(ac)}:F.find(Z.pop(),Z.length===1&&U.parentNode?U.parentNode:U,Q(U));af=F.filter(ae.expr,ae.set);if(Z.length>0){ai=E(af)}else{X=false}while(Z.length){var ah=Z.pop(),ag=ah;if(!I.relative[ah]){ah=""}else{ag=Z.pop()}if(ag==null){ag=U}I.relative[ah](ai,ag,Q(U))}}if(!ai){ai=af}if(!ai){throw"Syntax error, unrecognized expression: "+(ah||Y)}if(H.call(ai)==="[object Array]"){if(!X){ab.push.apply(ab,ai)}else{if(U.nodeType===1){for(var aa=0;ai[aa]!=null;aa++){if(ai[aa]&&(ai[aa]===true||ai[aa].nodeType===1&&K(U,ai[aa]))){ab.push(af[aa])}}}else{for(var aa=0;ai[aa]!=null;aa++){if(ai[aa]&&ai[aa].nodeType===1){ab.push(af[aa])}}}}}else{E(ai,ab)}if(V){F(V,U,ab,ac);if(G){hasDuplicate=false;ab.sort(G);if(hasDuplicate){for(var aa=1;aa":function(Z,U,aa){var X=typeof U==="string";if(X&&!/\W/.test(U)){U=aa?U:U.toUpperCase();for(var V=0,T=Z.length;V=0)){if(!V){T.push(Y)}}else{if(V){U[X]=false}}}}return false},ID:function(T){return T[1].replace(/\\/g,"")},TAG:function(U,T){for(var V=0;T[V]===false;V++){}return T[V]&&Q(T[V])?U[1]:U[1].toUpperCase()},CHILD:function(T){if(T[1]=="nth"){var U=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(T[2]=="even"&&"2n"||T[2]=="odd"&&"2n+1"||!/\D/.test(T[2])&&"0n+"+T[2]||T[2]);T[2]=(U[1]+(U[2]||1))-0;T[3]=U[3]-0}T[0]=L++;return T},ATTR:function(X,U,V,T,Y,Z){var W=X[1].replace(/\\/g,"");if(!Z&&I.attrMap[W]){X[1]=I.attrMap[W]}if(X[2]==="~="){X[4]=" "+X[4]+" "}return X},PSEUDO:function(X,U,V,T,Y){if(X[1]==="not"){if(X[3].match(R).length>1||/^\w/.test(X[3])){X[3]=F(X[3],null,null,U)}else{var W=F.filter(X[3],U,V,true^Y);if(!V){T.push.apply(T,W)}return false}}else{if(I.match.POS.test(X[0])||I.match.CHILD.test(X[0])){return true}}return X},POS:function(T){T.unshift(true);return T}},filters:{enabled:function(T){return T.disabled===false&&T.type!=="hidden"},disabled:function(T){return T.disabled===true},checked:function(T){return T.checked===true},selected:function(T){T.parentNode.selectedIndex;return T.selected===true},parent:function(T){return !!T.firstChild},empty:function(T){return !T.firstChild},has:function(V,U,T){return !!F(T[3],V).length},header:function(T){return/h\d/i.test(T.nodeName)},text:function(T){return"text"===T.type},radio:function(T){return"radio"===T.type},checkbox:function(T){return"checkbox"===T.type},file:function(T){return"file"===T.type},password:function(T){return"password"===T.type},submit:function(T){return"submit"===T.type},image:function(T){return"image"===T.type},reset:function(T){return"reset"===T.type},button:function(T){return"button"===T.type||T.nodeName.toUpperCase()==="BUTTON"},input:function(T){return/input|select|textarea|button/i.test(T.nodeName)}},setFilters:{first:function(U,T){return T===0},last:function(V,U,T,W){return U===W.length-1},even:function(U,T){return T%2===0},odd:function(U,T){return T%2===1},lt:function(V,U,T){return UT[3]-0},nth:function(V,U,T){return T[3]-0==U},eq:function(V,U,T){return T[3]-0==U}},filter:{PSEUDO:function(Z,V,W,aa){var U=V[1],X=I.filters[U];if(X){return X(Z,W,V,aa)}else{if(U==="contains"){return(Z.textContent||Z.innerText||"").indexOf(V[3])>=0}else{if(U==="not"){var Y=V[3];for(var W=0,T=Y.length;W=0)}}},ID:function(U,T){return U.nodeType===1&&U.getAttribute("id")===T},TAG:function(U,T){return(T==="*"&&U.nodeType===1)||U.nodeName===T},CLASS:function(U,T){return(" "+(U.className||U.getAttribute("class"))+" ").indexOf(T)>-1},ATTR:function(Y,W){var V=W[1],T=I.attrHandle[V]?I.attrHandle[V](Y):Y[V]!=null?Y[V]:Y.getAttribute(V),Z=T+"",X=W[2],U=W[4];return T==null?X==="!=":X==="="?Z===U:X==="*="?Z.indexOf(U)>=0:X==="~="?(" "+Z+" ").indexOf(U)>=0:!U?Z&&T!==false:X==="!="?Z!=U:X==="^="?Z.indexOf(U)===0:X==="$="?Z.substr(Z.length-U.length)===U:X==="|="?Z===U||Z.substr(0,U.length+1)===U+"-":false},POS:function(X,U,V,Y){var T=U[2],W=I.setFilters[T];if(W){return W(X,V,U,Y)}}}};var M=I.match.POS;for(var O in I.match){I.match[O]=RegExp(I.match[O].source+/(?![^\[]*\])(?![^\(]*\))/.source)}var E=function(U,T){U=Array.prototype.slice.call(U);if(T){T.push.apply(T,U);return T}return U};try{Array.prototype.slice.call(document.documentElement.childNodes)}catch(N){E=function(X,W){var U=W||[];if(H.call(X)==="[object Array]"){Array.prototype.push.apply(U,X)}else{if(typeof X.length==="number"){for(var V=0,T=X.length;V";var T=document.documentElement;T.insertBefore(U,T.firstChild);if(!!document.getElementById(V)){I.find.ID=function(X,Y,Z){if(typeof Y.getElementById!=="undefined"&&!Z){var W=Y.getElementById(X[1]);return W?W.id===X[1]||typeof W.getAttributeNode!=="undefined"&&W.getAttributeNode("id").nodeValue===X[1]?[W]:g:[]}};I.filter.ID=function(Y,W){var X=typeof Y.getAttributeNode!=="undefined"&&Y.getAttributeNode("id");return Y.nodeType===1&&X&&X.nodeValue===W}}T.removeChild(U)})();(function(){var T=document.createElement("div");T.appendChild(document.createComment(""));if(T.getElementsByTagName("*").length>0){I.find.TAG=function(U,Y){var X=Y.getElementsByTagName(U[1]);if(U[1]==="*"){var W=[];for(var V=0;X[V];V++){if(X[V].nodeType===1){W.push(X[V])}}X=W}return X}}T.innerHTML="";if(T.firstChild&&typeof T.firstChild.getAttribute!=="undefined"&&T.firstChild.getAttribute("href")!=="#"){I.attrHandle.href=function(U){return U.getAttribute("href",2)}}})();if(document.querySelectorAll){(function(){var T=F,U=document.createElement("div");U.innerHTML="

";if(U.querySelectorAll&&U.querySelectorAll(".TEST").length===0){return}F=function(Y,X,V,W){X=X||document;if(!W&&X.nodeType===9&&!Q(X)){try{return E(X.querySelectorAll(Y),V)}catch(Z){}}return T(Y,X,V,W)};F.find=T.find;F.filter=T.filter;F.selectors=T.selectors;F.matches=T.matches})()}if(document.getElementsByClassName&&document.documentElement.getElementsByClassName){(function(){var T=document.createElement("div");T.innerHTML="
";if(T.getElementsByClassName("e").length===0){return}T.lastChild.className="e";if(T.getElementsByClassName("e").length===1){return}I.order.splice(1,0,"CLASS");I.find.CLASS=function(U,V,W){if(typeof V.getElementsByClassName!=="undefined"&&!W){return V.getElementsByClassName(U[1])}}})()}function P(U,Z,Y,ad,aa,ac){var ab=U=="previousSibling"&&!ac;for(var W=0,V=ad.length;W0){X=T;break}}}T=T[U]}ad[W]=X}}}var K=document.compareDocumentPosition?function(U,T){return U.compareDocumentPosition(T)&16}:function(U,T){return U!==T&&(U.contains?U.contains(T):true)};var Q=function(T){return T.nodeType===9&&T.documentElement.nodeName!=="HTML"||!!T.ownerDocument&&Q(T.ownerDocument)};var J=function(T,aa){var W=[],X="",Y,V=aa.nodeType?[aa]:aa;while((Y=I.match.PSEUDO.exec(T))){X+=Y[0];T=T.replace(I.match.PSEUDO,"")}T=I.relative[T]?T+"*":T;for(var Z=0,U=V.length;Z0||T.offsetHeight>0};F.selectors.filters.animated=function(T){return o.grep(o.timers,function(U){return T===U.elem}).length};o.multiFilter=function(V,T,U){if(U){V=":not("+V+")"}return F.matches(V,T)};o.dir=function(V,U){var T=[],W=V[U];while(W&&W!=document){if(W.nodeType==1){T.push(W)}W=W[U]}return T};o.nth=function(X,T,V,W){T=T||1;var U=0;for(;X;X=X[V]){if(X.nodeType==1&&++U==T){break}}return X};o.sibling=function(V,U){var T=[];for(;V;V=V.nextSibling){if(V.nodeType==1&&V!=U){T.push(V)}}return T};return;l.Sizzle=F})();o.event={add:function(I,F,H,K){if(I.nodeType==3||I.nodeType==8){return}if(I.setInterval&&I!=l){I=l}if(!H.guid){H.guid=this.guid++}if(K!==g){var G=H;H=this.proxy(G);H.data=K}var E=o.data(I,"events")||o.data(I,"events",{}),J=o.data(I,"handle")||o.data(I,"handle",function(){return typeof o!=="undefined"&&!o.event.triggered?o.event.handle.apply(arguments.callee.elem,arguments):g});J.elem=I;o.each(F.split(/\s+/),function(M,N){var O=N.split(".");N=O.shift();H.type=O.slice().sort().join(".");var L=E[N];if(o.event.specialAll[N]){o.event.specialAll[N].setup.call(I,K,O)}if(!L){L=E[N]={};if(!o.event.special[N]||o.event.special[N].setup.call(I,K,O)===false){if(I.addEventListener){I.addEventListener(N,J,false)}else{if(I.attachEvent){I.attachEvent("on"+N,J)}}}}L[H.guid]=H;o.event.global[N]=true});I=null},guid:1,global:{},remove:function(K,H,J){if(K.nodeType==3||K.nodeType==8){return}var G=o.data(K,"events"),F,E;if(G){if(H===g||(typeof H==="string"&&H.charAt(0)==".")){for(var I in G){this.remove(K,I+(H||""))}}else{if(H.type){J=H.handler;H=H.type}o.each(H.split(/\s+/),function(M,O){var Q=O.split(".");O=Q.shift();var N=RegExp("(^|\\.)"+Q.slice().sort().join(".*\\.")+"(\\.|$)");if(G[O]){if(J){delete G[O][J.guid]}else{for(var P in G[O]){if(N.test(G[O][P].type)){delete G[O][P]}}}if(o.event.specialAll[O]){o.event.specialAll[O].teardown.call(K,Q)}for(F in G[O]){break}if(!F){if(!o.event.special[O]||o.event.special[O].teardown.call(K,Q)===false){if(K.removeEventListener){K.removeEventListener(O,o.data(K,"handle"),false)}else{if(K.detachEvent){K.detachEvent("on"+O,o.data(K,"handle"))}}}F=null;delete G[O]}}})}for(F in G){break}if(!F){var L=o.data(K,"handle");if(L){L.elem=null}o.removeData(K,"events");o.removeData(K,"handle")}}},trigger:function(I,K,H,E){var G=I.type||I;if(!E){I=typeof I==="object"?I[h]?I:o.extend(o.Event(G),I):o.Event(G);if(G.indexOf("!")>=0) {I.type=G=G.slice(0,-1);I.exclusive=true}if(!H){I.stopPropagation();if(this.global[G]){o.each(o.cache,function(){if(this.events&&this.events[G]){o.event.trigger(I,K,this.handle.elem)}})}}if(!H||H.nodeType==3||H.nodeType==8){return g}I.result=g;I.target=H;K=o.makeArray(K);K.unshift(I)}I.currentTarget=H;var J=o.data(H,"handle");if(J){J.apply(H,K)}if((!H[G]||(o.nodeName(H,"a")&&G=="click"))&&H["on"+G]&&H["on"+G].apply(H,K)===false){I.result=false}if(!E&&H[G]&&!I.isDefaultPrevented()&&!(o.nodeName(H,"a")&&G=="click")){this.triggered=true;try{H[G]()}catch(L){}}this.triggered=false;if(!I.isPropagationStopped()){var F=H.parentNode||H.ownerDocument;if(F){o.event.trigger(I,K,F,true)}}},handle:function(K){var J,E;K=arguments[0]=o.event.fix(K||l.event);K.currentTarget=this;var L=K.type.split(".");K.type=L.shift();J=!L.length&&!K.exclusive;var I=RegExp("(^|\\.)"+L.slice().sort().join(".*\\.")+"(\\.|$)");E=(o.data(this,"events")||{})[K.type];for(var G in E){var H=E[G];if(J||I.test(H.type)){K.handler=H;K.data=H.data;var F=H.apply(this,arguments);if(F!==g){K.result=F;if(F===false){K.preventDefault();K.stopPropagation()}}if(K.isImmediatePropagationStopped()){break}}}},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode metaKey newValue originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),fix:function(H){if(H[h]){return H}var F=H;H=o.Event(F);for(var G=this.props.length,J;G;){J=this.props[--G];H[J]=F[J]}if(!H.target){H.target=H.srcElement||document}if(H.target.nodeType==3){H.target=H.target.parentNode}if(!H.relatedTarget&&H.fromElement){H.relatedTarget=H.fromElement==H.target?H.toElement:H.fromElement}if(H.pageX==null&&H.clientX!=null){var I=document.documentElement,E=document.body;H.pageX=H.clientX+(I&&I.scrollLeft||E&&E.scrollLeft||0)-(I.clientLeft||0);H.pageY=H.clientY+(I&&I.scrollTop||E&&E.scrollTop||0)-(I.clientTop||0)}if(!H.which&&((H.charCode||H.charCode===0)?H.charCode:H.keyCode)){H.which=H.charCode||H.keyCode}if(!H.metaKey&&H.ctrlKey){H.metaKey=H.ctrlKey}if(!H.which&&H.button){H.which=(H.button&1?1:(H.button&2?3:(H.button&4?2:0)))}return H},proxy:function(F,E){E=E||function(){return F.apply(this,arguments)};E.guid=F.guid=F.guid||E.guid||this.guid++;return E},special:{ready:{setup:B,teardown:function(){}}},specialAll:{live:{setup:function(E,F){o.event.add(this,F[0],c)},teardown:function(G){if(G.length){var E=0,F=RegExp("(^|\\.)"+G[0]+"(\\.|$)");o.each((o.data(this,"events").live||{}),function(){if(F.test(this.type)){E++}});if(E<1){o.event.remove(this,G[0],c)}}}}}};o.Event=function(E){if(!this.preventDefault){return new o.Event(E)}if(E&&E.type){this.originalEvent=E;this.type=E.type}else{this.type=E}this.timeStamp=e();this[h]=true};function k(){return false}function u(){return true}o.Event.prototype={preventDefault:function(){this.isDefaultPrevented=u;var E=this.originalEvent;if(!E){return}if(E.preventDefault){E.preventDefault()}E.returnValue=false},stopPropagation:function(){this.isPropagationStopped=u;var E=this.originalEvent;if(!E){return}if(E.stopPropagation){E.stopPropagation()}E.cancelBubble=true},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=u;this.stopPropagation()},isDefaultPrevented:k,isPropagationStopped:k,isImmediatePropagationStopped:k};var a=function(F){var E=F.relatedTarget;while(E&&E!=this){try{E=E.parentNode}catch(G){E=this}}if(E!=this){F.type=F.data;o.event.handle.apply(this,arguments)}};o.each({mouseover:"mouseenter",mouseout:"mouseleave"},function(F,E){o.event.special[E]={setup:function(){o.event.add(this,F,a,E)},teardown:function(){o.event.remove(this,F,a)}}});o.fn.extend({bind:function(F,G,E){return F=="unload"?this.one(F,G,E):this.each(function(){o.event.add(this,F,E||G,E&&G)})},one:function(G,H,F){var E=o.event.proxy(F||H,function(I){o(this).unbind(I,E);return(F||H).apply(this,arguments)});return this.each(function(){o.event.add(this,G,E,F&&H)})},unbind:function(F,E){return this.each(function(){o.event.remove(this,F,E)})},trigger:function(E,F){return this.each(function(){o.event.trigger(E,F,this)})},triggerHandler:function(E,G){if(this[0]){var F=o.Event(E);F.preventDefault();F.stopPropagation();o.event.trigger(F,G,this[0]);return F.result}},toggle:function(G){var E=arguments,F=1;while(F=0){var E=G.slice(I,G.length);G=G.slice(0,I)}var H="GET";if(J){if(o.isFunction(J)){K=J;J=null}else{if(typeof J==="object"){J=o.param(J);H="POST"}}}var F=this;o.ajax({url:G,type:H,dataType:"html",data:J,complete:function(M,L){if(L=="success"||L=="notmodified"){F.html(E?o("
").append(M.responseText.replace(//g,"")).find(E):M.responseText)}if(K){F.each(K,[M.responseText,L,M])}}});return this},serialize:function(){return o.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?o.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||/select|textarea/i.test(this.nodeName)||/text|hidden|password|search/i.test(this.type))}).map(function(E,F){var G=o(this).val();return G==null?null:o.isArray(G)?o.map(G,function(I,H){return{name:F.name,value:I}}):{name:F.name,value:G}}).get()}});o.each("ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","),function(E,F){o.fn[F]=function(G){return this.bind(F,G)}});var r=e();o.extend({get:function(E,G,H,F){if(o.isFunction(G)){H=G;G=null}return o.ajax({type:"GET",url:E,data:G,success:H,dataType:F})},getScript:function(E,F){return o.get(E,null,F,"script")},getJSON:function(E,F,G){return o.get(E,F,G,"json")},post:function(E,G,H,F){if(o.isFunction(G)){H=G;G={}}return o.ajax({type:"POST",url:E,data:G,success:H,dataType:F})},ajaxSetup:function(E){o.extend(o.ajaxSettings,E)},ajaxSettings:{url:location.href,global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:function(){return l.ActiveXObject?new ActiveXObject("Microsoft.XMLHTTP"):new XMLHttpRequest()},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},ajax:function(M){M=o.extend(true,M,o.extend(true,{},o.ajaxSettings,M));var W,F=/=\?(&|$)/g,R,V,G=M.type.toUpperCase();if(M.data&&M.processData&&typeof M.data!=="string"){M.data=o.param(M.data)}if(M.dataType=="jsonp"){if(G=="GET"){if(!M.url.match(F)){M.url+=(M.url.match(/\?/)?"&":"?")+(M.jsonp||"callback")+"=?"}}else{if(!M.data||!M.data.match(F)){M.data=(M.data?M.data+"&":"")+(M.jsonp||"callback")+"=?"}}M.dataType="json"}if(M.dataType=="json"&&(M.data&&M.data.match(F)||M.url.match(F))){W="jsonp"+r++;if(M.data){M.data=(M.data+"").replace(F,"="+W+"$1")}M.url=M.url.replace(F,"="+W+"$1");M.dataType="script";l[W]=function(X){V=X;I();L();l[W]=g;try{delete l[W]}catch(Y){}if(H){H.removeChild(T)}}}if(M.dataType=="script"&&M.cache==null){M.cache=false}if(M.cache===false&&G=="GET"){var E=e();var U=M.url.replace(/(\?|&)_=.*?(&|$)/,"$1_="+E+"$2");M.url=U+((U==M.url)?(M.url.match(/\?/)?"&":"?")+"_="+E:"")}if(M.data&&G=="GET"){M.url+=(M.url.match(/\?/)?"&":"?")+M.data;M.data=null}if(M.global&&!o.active++){o.event.trigger("ajaxStart")}var Q=/^(\w+:)?\/\/([^\/?#]+)/.exec(M.url);if(M.dataType=="script"&&G=="GET"&&Q&&(Q[1]&&Q[1]!=location.protocol||Q[2]!=location.host)){var H=document.getElementsByTagName("head")[0];var T=document.createElement("script");T.src=M.url;if(M.scriptCharset){T.charset=M.scriptCharset}if(!W){var O=false;T.onload=T.onreadystatechange=function(){if(!O&&(!this.readyState||this.readyState=="loaded"||this.readyState=="complete")){O=true;I();L();T.onload=T.onreadystatechange=null;H.removeChild(T)}}}H.appendChild(T);return g}var K=false;var J=M.xhr();if(M.username){J.open(G,M.url,M.async,M.username,M.password)}else{J.open(G,M.url,M.async)}try{if(M.data){J.setRequestHeader("Content-Type",M.contentType)}if(M.ifModified){J.setRequestHeader("If-Modified-Since",o.lastModified[M.url]||"Thu, 01 Jan 1970 00:00:00 GMT")}J.setRequestHeader("X-Requested-With","XMLHttpRequest");J.setRequestHeader("Accept",M.dataType&&M.accepts[M.dataType]?M.accepts[M.dataType]+", */*":M.accepts._default)}catch(S){}if(M.beforeSend&&M.beforeSend(J,M)===false){if(M.global&&!--o.active){o.event.trigger("ajaxStop")}J.abort();return false}if(M.global){o.event.trigger("ajaxSend",[J,M])}var N=function(X){if(J.readyState==0){if(P){clearInterval(P);P=null;if(M.global&&!--o.active){o.event.trigger("ajaxStop")}}}else{if(!K&&J&&(J.readyState==4||X=="timeout")){K=true;if(P){clearInterval(P);P=null}R=X=="timeout"?"timeout":!o.httpSuccess(J)?"error":M.ifModified&&o.httpNotModified(J,M.url)?"notmodified":"success";if(R=="success"){try{V=o.httpData(J,M.dataType,M)}catch(Z){R="parsererror"}}if(R=="success"){var Y;try{Y=J.getResponseHeader("Last-Modified")}catch(Z){}if(M.ifModified&&Y){o.lastModified[M.url]=Y}if(!W){I()}}else{o.handleError(M,J,R)}L();if(X){J.abort()}if(M.async){J=null}}}};if(M.async){var P=setInterval(N,13);if(M.timeout>0){setTimeout(function(){if(J&&!K){N("timeout")}},M.timeout)}}try{J.send(M.data)}catch(S){o.handleError(M,J,null,S)}if(!M.async){N()}function I(){if(M.success){M.success(V,R)}if(M.global){o.event.trigger("ajaxSuccess",[J,M])}}function L(){if(M.complete){M.complete(J,R)}if(M.global){o.event.trigger("ajaxComplete",[J,M])}if(M.global&&!--o.active){o.event.trigger("ajaxStop")}}return J},handleError:function(F,H,E,G){if(F.error){F.error(H,E,G)}if(F.global){o.event.trigger("ajaxError",[H,F,G])}},active:0,httpSuccess:function(F){try{return !F.status&&location.protocol=="file:"||(F.status>=200&&F.status<300)||F.status==304||F.status==1223}catch(E){}return false},httpNotModified:function(G,E){try{var H=G.getResponseHeader("Last-Modified");return G.status==304||H==o.lastModified[E]}catch(F){}return false},httpData:function(J,H,G){var F=J.getResponseHeader("content-type"),E=H=="xml"||!H&&F&&F.indexOf("xml")>=0,I=E?J.responseXML:J.responseText;if(E&&I.documentElement.tagName=="parsererror"){throw"parsererror"}if(G&&G.dataFilter){I=G.dataFilter(I,H)}if(typeof I==="string"){if(H=="script"){o.globalEval(I)}if(H=="json"){I=l["eval"]("("+I+")")}}return I},param:function(E){var G=[];function H(I,J){G[G.length]=encodeURIComponent(I)+"="+encodeURIComponent(J)}if(o.isArray(E)||E.jquery){o.each(E,function(){H(this.name,this.value)})}else{for(var F in E){if(o.isArray(E[F])){o.each(E[F],function(){H(F,this)})}else{H(F,o.isFunction(E[F])?E[F]():E[F])}}}return G.join("&").replace(/%20/g,"+")}});var m={},n,d=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];function t(F,E){var G={};o.each(d.concat.apply([],d.slice(0,E)),function() {G[this]=F});return G}o.fn.extend({show:function(J,L){if(J){return this.animate(t("show",3),J,L)}else{for(var H=0,F=this.length;H").appendTo("body");K=I.css("display");if(K==="none"){K="block"}I.remove();m[G]=K}o.data(this[H],"olddisplay",K)}}for(var H=0,F=this.length;H=0;H--){if(G[H].elem==this){if(E){G[H](true)}G.splice(H,1)}}});if(!E){this.dequeue()}return this}});o.each({slideDown:t("show",1),slideUp:t("hide",1),slideToggle:t("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(E,F){o.fn[E]=function(G,H){return this.animate(F,G,H)}});o.extend({speed:function(G,H,F){var E=typeof G==="object"?G:{complete:F||!F&&H||o.isFunction(G)&&G,duration:G,easing:F&&H||H&&!o.isFunction(H)&&H};E.duration=o.fx.off?0:typeof E.duration==="number"?E.duration:o.fx.speeds[E.duration]||o.fx.speeds._default;E.old=E.complete;E.complete=function(){if(E.queue!==false){o(this).dequeue()}if(o.isFunction(E.old)){E.old.call(this)}};return E},easing:{linear:function(G,H,E,F){return E+F*G},swing:function(G,H,E,F){return((-Math.cos(G*Math.PI)/2)+0.5)*F+E}},timers:[],fx:function(F,E,G){this.options=E;this.elem=F;this.prop=G;if(!E.orig){E.orig={}}}});o.fx.prototype={update:function(){if(this.options.step){this.options.step.call(this.elem,this.now,this)}(o.fx.step[this.prop]||o.fx.step._default)(this);if((this.prop=="height"||this.prop=="width")&&this.elem.style){this.elem.style.display="block"}},cur:function(F){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null)){return this.elem[this.prop]}var E=parseFloat(o.css(this.elem,this.prop,F));return E&&E>-10000?E:parseFloat(o.curCSS(this.elem,this.prop))||0},custom:function(I,H,G){this.startTime=e();this.start=I;this.end=H;this.unit=G||this.unit||"px";this.now=this.start;this.pos=this.state=0;var E=this;function F(J){return E.step(J)}F.elem=this.elem;if(F()&&o.timers.push(F)&&!n){n=setInterval(function(){var K=o.timers;for(var J=0;J=this.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;var E=true;for(var F in this.options.curAnim){if(this.options.curAnim[F]!==true){E=false}}if(E){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;this.elem.style.display=this.options.display;if(o.css(this.elem,"display")=="none"){this.elem.style.display="block"}}if(this.options.hide){o(this.elem).hide()}if(this.options.hide||this.options.show){for(var I in this.options.curAnim){o.attr(this.elem.style,I,this.options.orig[I])}}this.options.complete.call(this.elem)}return false}else{var J=G-this.startTime;this.state=J/this.options.duration;this.pos=o.easing[this.options.easing||(o.easing.swing?"swing":"linear")](this.state,J,0,1,this.options.duration);this.now=this.start+((this.end-this.start)*this.pos);this.update()}return true}};o.extend(o.fx,{speeds:{slow:600,fast:200,_default:400},step:{opacity:function(E){o.attr(E.elem.style,"opacity",E.now)},_default:function(E){if(E.elem.style&&E.elem.style[E.prop]!=null){E.elem.style[E.prop]=E.now+E.unit}else{E.elem[E.prop]=E.now}}}});if(document.documentElement.getBoundingClientRect){o.fn.offset=function(){if(!this[0]){return{top:0,left:0}}if(this[0]===this[0].ownerDocument.body){return o.offset.bodyOffset(this[0])}var G=this[0].getBoundingClientRect(),J=this[0].ownerDocument,F=J.body,E=J.documentElement,L=E.clientTop||F.clientTop||0,K=E.clientLeft||F.clientLeft||0,I=G.top+(self.pageYOffset||o.boxModel&&E.scrollTop||F.scrollTop)-L,H=G.left+(self.pageXOffset||o.boxModel&&E.scrollLeft||F.scrollLeft)-K;return{top:I,left:H}}}else{o.fn.offset=function(){if(!this[0]){return{top:0,left:0}}if(this[0]===this[0].ownerDocument.body){return o.offset.bodyOffset(this[0])}o.offset.initialized||o.offset.initialize();var J=this[0],G=J.offsetParent,F=J,O=J.ownerDocument,M,H=O.documentElement,K=O.body,L=O.defaultView,E=L.getComputedStyle(J,null),N=J.offsetTop,I=J.offsetLeft;while((J=J.parentNode)&&J!==K&&J!==H){M=L.getComputedStyle(J,null);N-=J.scrollTop,I-=J.scrollLeft;if(J===G){N+=J.offsetTop,I+=J.offsetLeft;if(o.offset.doesNotAddBorder&&!(o.offset.doesAddBorderForTableAndCells&&/^t(able|d|h)$/i.test(J.tagName))){N+=parseInt(M.borderTopWidth,10)||0,I+=parseInt(M.borderLeftWidth,10)||0}F=G,G=J.offsetParent}if(o.offset.subtractsBorderForOverflowNotVisible&&M.overflow!=="visible"){N+=parseInt(M.borderTopWidth,10)||0,I+=parseInt(M.borderLeftWidth,10)||0}E=M}if(E.position==="relative"||E.position==="static"){N+=K.offsetTop,I+=K.offsetLeft}if(E.position==="fixed"){N+=Math.max(H.scrollTop,K.scrollTop),I+=Math.max(H.scrollLeft,K.scrollLeft)}return{top:N,left:I}}}o.offset={initialize:function(){if(this.initialized){return}var L=document.body,F=document.createElement("div"),H,G,N,I,M,E,J=L.style.marginTop,K='
';M={position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"};for(E in M){F.style[E]=M[E]}F.innerHTML=K;L.insertBefore(F,L.firstChild);H=F.firstChild,G=H.firstChild,I=H.nextSibling.firstChild.firstChild;this.doesNotAddBorder=(G.offsetTop!==5);this.doesAddBorderForTableAndCells=(I.offsetTop===5);H.style.overflow="hidden",H.style.position="relative";this.subtractsBorderForOverflowNotVisible=(G.offsetTop===-5);L.style.marginTop="1px";this.doesNotIncludeMarginInBodyOffset=(L.offsetTop===0);L.style.marginTop=J;L.removeChild(F);this.initialized=true},bodyOffset:function(E){o.offset.initialized||o.offset.initialize();var G=E.offsetTop,F=E.offsetLeft;if(o.offset.doesNotIncludeMarginInBodyOffset){G+=parseInt(o.curCSS(E,"marginTop",true),10)||0,F+=parseInt(o.curCSS(E,"marginLeft",true),10)||0}return{top:G,left:F}}};o.fn.extend({position:function(){var I=0,H=0,F;if(this[0]){var G=this.offsetParent(),J=this.offset(),E=/^body|html$/i.test(G[0].tagName)?{top:0,left:0}:G.offset();J.top-=j(this,"marginTop");J.left-=j(this,"marginLeft");E.top+=j(G,"borderTopWidth");E.left+=j(G,"borderLeftWidth");F={top:J.top-E.top,left:J.left-E.left}}return F},offsetParent:function(){var E=this[0].offsetParent||document.body;while(E&&(!/^body|html$/i.test(E.tagName)&&o.css(E,"position")=="static")){E=E.offsetParent}return o(E)}});o.each(["Left","Top"],function(F,E){var G="scroll"+E;o.fn[G]=function(H){if(!this[0]){return null}return H!==g?this.each(function(){this==l||this==document?l.scrollTo(!F?H:o(l).scrollLeft(),F?H:o(l).scrollTop()):this[G]=H}):this[0]==l||this[0]==document?self[F?"pageYOffset":"pageXOffset"]||o.boxModel&&document.documentElement[G]||document.body[G]:this[0][G]}});o.each(["Height","Width"],function(I,G){var E=I?"Left":"Top",H=I?"Right":"Bottom",F=G.toLowerCase();o.fn["inner"+G]=function(){return this[0]?o.css(this[0],F,false,"padding"):null};o.fn["outer"+G]=function(K){return this[0]?o.css(this[0],F,false,K?"margin":"border"):null};var J=G.toLowerCase();o.fn[J]=function(K){return this[0]==l?document.compatMode=="CSS1Compat"&&document.documentElement["client"+G]||document.body["client"+G]:this[0]==document?Math.max(document.documentElement["client"+G],document.body["scroll"+G],document.documentElement["scroll"+G],document.body["offset"+G],document.documentElement["offset"+G]):K===g?(this.length?o.css(this[0],J):null):this.css(J,typeof K==="string"?K:K+"px")}})})(); /* * jQuery UI 1.7.2 * * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about) * Dual licensed under the MIT (MIT-LICENSE.txt) * and GPL (GPL-LICENSE.txt) licenses. * * http://docs.jquery.com/UI */ jQuery.ui||(function(c){var i=c.fn.remove,d=c.browser.mozilla&&(parseFloat(c.browser.version)<1.9);c.ui={version:"1.7.2",plugin:{add:function(k,l,n){var m=c.ui[k].prototype;for(var j in n){m.plugins[j]=m.plugins[j]||[];m.plugins[j].push([l,n[j]])}},call:function(j,l,k){var n=j.plugins[l];if(!n||!j.element[0].parentNode){return}for(var m=0;m0){return true}m[j]=1;l=(m[j]>0);m[j]=0;return l},isOverAxis:function(k,j,l){return(k>j)&&(k<(j+l))},isOver:function(o,k,n,m,j,l){return c.ui.isOverAxis(o,n,j)&&c.ui.isOverAxis(k,m,l)},keyCode:{BACKSPACE:8,CAPS_LOCK:20,COMMA:188,CONTROL:17,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,INSERT:45,LEFT:37,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SHIFT:16,SPACE:32,TAB:9,UP:38}};if(d){var f=c.attr,e=c.fn.removeAttr,h="http://www.w3.org/2005/07/aaa",a=/^aria-/,b=/^wairole:/;c.attr=function(k,j,l){var m=l!==undefined;return(j=="role"?(m?f.call(this,k,j,"wairole:"+l):(f.apply(this,arguments)||"").replace(b,"")):(a.test(j)?(m?k.setAttributeNS(h,j.replace(a,"aaa:"),l):f.call(this,k,j.replace(a,"aaa:"))):f.apply(this,arguments)))};c.fn.removeAttr=function(j){return(a.test(j)?this.each(function(){this.removeAttributeNS(h,j.replace(a,""))}):e.call(this,j))}}c.fn.extend({remove:function(){c("*",this).add(this).each(function(){c(this).triggerHandler("remove")});return i.apply(this,arguments)},enableSelection:function(){return this.attr("unselectable","off").css("MozUserSelect","").unbind("selectstart.ui")},disableSelection:function(){return this.attr("unselectable","on").css("MozUserSelect","none").bind("selectstart.ui",function(){return false})},scrollParent:function(){var j;if((c.browser.msie&&(/(static|relative)/).test(this.css("position")))||(/absolute/).test(this.css("position"))){j=this.parents().filter(function(){return(/(relative|absolute|fixed)/).test(c.curCSS(this,"position",1))&&(/(auto|scroll)/).test(c.curCSS(this,"overflow",1)+c.curCSS(this,"overflow-y",1)+c.curCSS(this,"overflow-x",1))}).eq(0)}else{j=this.parents().filter(function(){return(/(auto|scroll)/).test(c.curCSS(this,"overflow",1)+c.curCSS(this,"overflow-y",1)+c.curCSS(this,"overflow-x",1))}).eq(0)}return(/fixed/).test(this.css("position"))||!j.length?c(document):j}});c.extend(c.expr[":"],{data:function(l,k,j){return !!c.data(l,j[3])},focusable:function(k){var l=k.nodeName.toLowerCase(),j=c.attr(k,"tabindex");return(/input|select|textarea|button|object/.test(l)?!k.disabled:"a"==l||"area"==l?k.href||!isNaN(j):!isNaN(j))&&!c(k)["area"==l?"parents":"closest"](":hidden").length},tabbable:function(k){var j=c.attr(k,"tabindex");return(isNaN(j)||j>=0)&&c(k).is(":focusable")}});function g(m,n,o,l){function k(q){var p=c[m][n][q]||[];return(typeof p=="string"?p.split(/,?\s+/):p)}var j=k("getter");if(l.length==1&&typeof l[0]=="string"){j=j.concat(k("getterSetter"))}return(c.inArray(o,j)!=-1)}c.widget=function(k,j){var l=k.split(".")[0];k=k.split(".")[1];c.fn[k]=function(p){var n=(typeof p=="string"),o=Array.prototype.slice.call(arguments,1);if(n&&p.substring(0,1)=="_"){return this}if(n&&g(l,k,p,o)){var m=c.data(this[0],k);return(m?m[p].apply(m,o):undefined)}return this.each(function(){var q=c.data(this,k);(!q&&!n&&c.data(this,k,new c[l][k](this,p))._init());(q&&n&&c.isFunction(q[p])&&q[p].apply(q,o))})};c[l]=c[l]||{};c[l][k]=function(o,n){var m=this;this.namespace=l;this.widgetName=k;this.widgetEventPrefix=c[l][k].eventPrefix||k;this.widgetBaseClass=l+"-"+k;this.options=c.extend({},c.widget.defaults,c[l][k].defaults,c.metadata&&c.metadata.get(o)[k],n);this.element=c(o).bind("setData."+k,function(q,p,r){if(q.target==o){return m._setData(p,r)}}).bind("getData."+k,function(q,p){if(q.target==o){return m._getData(p)}}).bind("remove",function(){return m.destroy()})};c[l][k].prototype=c.extend({},c.widget.prototype,j);c[l][k].getterSetter="option"};c.widget.prototype={_init:function(){},destroy:function(){this.element.removeData(this.widgetName).removeClass(this.widgetBaseClass+"-disabled "+this.namespace+"-state-disabled").removeAttr("aria-disabled")},option:function(l,m){var k=l,j=this;if(typeof l=="string"){if(m===undefined){return this._getData(l)}k={};k[l]=m}c.each(k,function(n,o){j._setData(n,o)})},_getData:function(j){return this.options[j]},_setData:function(j,k){this.options[j]=k;if(j=="disabled"){this.element[k?"addClass":"removeClass"](this.widgetBaseClass+"-disabled "+this.namespace+"-state-disabled").attr("aria-disabled",k)}},enable:function(){this._setData("disabled",false)},disable:function(){this._setData("disabled",true)},_trigger:function(l,m,n){var p=this.options[l],j=(l==this.widgetEventPrefix?l:this.widgetEventPrefix+l);m=c.Event(m);m.type=j;if(m.originalEvent){for(var k=c.event.props.length,o;k;){o=c.event.props[--k];m[o]=m.originalEvent[o]}}this.element.trigger(m,n);return !(c.isFunction(p)&&p.call(this.element[0],m,n)===false||m.isDefaultPrevented())}};c.widget.defaults={disabled:false};c.ui.mouse={_mouseInit:function(){var j=this;this.element.bind("mousedown."+this.widgetName,function(k){return j._mouseDown(k)}).bind("click."+this.widgetName,function(k){if(j._preventClickEvent){j._preventClickEvent=false;k.stopImmediatePropagation();return false}});if(c.browser.msie){this._mouseUnselectable=this.element.attr("unselectable");this.element.attr("unselectable","on")}this.started=false},_mouseDestroy:function(){this.element.unbind("."+this.widgetName);(c.browser.msie&&this.element.attr("unselectable",this._mouseUnselectable))},_mouseDown:function(l){l.originalEvent=l.originalEvent||{};if(l.originalEvent.mouseHandled){return}(this._mouseStarted&&this._mouseUp(l));this._mouseDownEvent=l;var k=this,m=(l.which==1),j=(typeof this.options.cancel=="string"?c(l.target).parents().add(l.target).filter(this.options.cancel).length:false);if(!m||j||!this._mouseCapture(l)){return true}this.mouseDelayMet=!this.options.delay;if(!this.mouseDelayMet){this._mouseDelayTimer=setTimeout(function(){k.mouseDelayMet=true},this.options.delay)}if(this._mouseDistanceMet(l)&&this._mouseDelayMet(l)){this._mouseStarted=(this._mouseStart(l)!==false);if(!this._mouseStarted){l.preventDefault();return true}}this._mouseMoveDelegate=function(n){return k._mouseMove(n)};this._mouseUpDelegate=function(n){return k._mouseUp(n)};c(document).bind("mousemove."+this.widgetName,this._mouseMoveDelegate).bind("mouseup."+this.widgetName,this._mouseUpDelegate);(c.browser.safari||l.preventDefault());l.originalEvent.mouseHandled=true;return true},_mouseMove:function(j){if(c.browser.msie&&!j.button){return this._mouseUp(j)}if(this._mouseStarted){this._mouseDrag(j);return j.preventDefault()}if(this._mouseDistanceMet(j)&&this._mouseDelayMet(j)){this._mouseStarted=(this._mouseStart(this._mouseDownEvent,j)!==false);(this._mouseStarted?this._mouseDrag(j):this._mouseUp(j))}return !this._mouseStarted},_mouseUp:function(j){c(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate);if(this._mouseStarted){this._mouseStarted=false;this._preventClickEvent=(j.target==this._mouseDownEvent.target);this._mouseStop(j)}return false},_mouseDistanceMet:function(j){return(Math.max(Math.abs(this._mouseDownEvent.pageX-j.pageX),Math.abs(this._mouseDownEvent.pageY-j.pageY))>=this.options.distance)},_mouseDelayMet:function(j){return this.mouseDelayMet},_mouseStart:function(j){},_mouseDrag:function(j){},_mouseStop:function(j){},_mouseCapture:function(j){return true}};c.ui.mouse.defaults={cancel:null,distance:1,delay:0}})(jQuery);;/* * jQuery UI Resizable 1.7.2 * * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about) * Dual licensed under the MIT (MIT-LICENSE.txt) * and GPL (GPL-LICENSE.txt) licenses. * * http://docs.jquery.com/UI/Resizables * * Depends: * ui.core.js */ (function(c){c.widget("ui.resizable",c.extend({},c.ui.mouse,{_init:function(){var e=this,j=this.options;this.element.addClass("ui-resizable");c.extend(this,{_aspectRatio:!!(j.aspectRatio),aspectRatio:j.aspectRatio,originalElement:this.element,_proportionallyResizeElements:[],_helper:j.helper||j.ghost||j.animate?j.helper||"ui-resizable-helper":null});if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)){if(/relative/.test(this.element.css("position"))&&c.browser.opera){this.element.css({position:"relative",top:"auto",left:"auto"})}this.element.wrap(c('
').css({position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(),top:this.element.css("top"),left:this.element.css("left")}));this.element=this.element.parent().data("resizable",this.element.data("resizable"));this.elementIsWrapper=true;this.element.css({marginLeft:this.originalElement.css("marginLeft"),marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom")});this.originalElement.css({marginLeft:0,marginTop:0,marginRight:0,marginBottom:0});this.originalResizeStyle=this.originalElement.css("resize");this.originalElement.css("resize","none");this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"}));this.originalElement.css({margin:this.originalElement.css("margin")});this._proportionallyResize()}this.handles=j.handles||(!c(".ui-resizable-handle",this.element).length?"e,s,se":{n:".ui-resizable-n",e:".ui-resizable-e",s:".ui-resizable-s",w:".ui-resizable-w",se:".ui-resizable-se",sw:".ui-resizable-sw",ne:".ui-resizable-ne",nw:".ui-resizable-nw"});if(this.handles.constructor==String){if(this.handles=="all"){this.handles="n,e,s,w,se,sw,ne,nw"}var k=this.handles.split(",");this.handles={};for(var f=0;f
');if(/sw|se|ne|nw/.test(h)){g.css({zIndex:++j.zIndex})}if("se"==h){g.addClass("ui-icon ui-icon-gripsmall-diagonal-se")}this.handles[h]=".ui-resizable-"+h;this.element.append(g)}}this._renderAxis=function(p){p=p||this.element;for(var m in this.handles){if(this.handles[m].constructor==String){this.handles[m]=c(this.handles[m],this.element).show()}if(this.elementIsWrapper&&this.originalElement[0].nodeName.match(/textarea|input|select|button/i)){var n=c(this.handles[m],this.element),o=0;o=/sw|ne|nw|se|n|s/.test(m)?n.outerHeight():n.outerWidth();var l=["padding",/ne|nw|n/.test(m)?"Top":/se|sw|s/.test(m)?"Bottom":/^e$/.test(m)?"Right":"Left"].join("");p.css(l,o);this._proportionallyResize()}if(!c(this.handles[m]).length){continue}}};this._renderAxis(this.element);this._handles=c(".ui-resizable-handle",this.element).disableSelection();this._handles.mouseover(function(){if(!e.resizing){if(this.className){var i=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i)}e.axis=i&&i[1]?i[1]:"se"}});if(j.autoHide){this._handles.hide();c(this.element).addClass("ui-resizable-autohide").hover(function(){c(this).removeClass("ui-resizable-autohide");e._handles.show()},function(){if(!e.resizing){c(this).addClass("ui-resizable-autohide");e._handles.hide()}})}this._mouseInit()},destroy:function(){this._mouseDestroy();var d=function(f){c(f).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing").removeData("resizable").unbind(".resizable").find(".ui-resizable-handle").remove()};if(this.elementIsWrapper){d(this.element);var e=this.element;e.parent().append(this.originalElement.css({position:e.css("position"),width:e.outerWidth(),height:e.outerHeight(),top:e.css("top"),left:e.css("left")})).end().remove()}this.originalElement.css("resize",this.originalResizeStyle);d(this.originalElement)},_mouseCapture:function(e){var f=false;for(var d in this.handles){if(c(this.handles[d])[0]==e.target){f=true}}return this.options.disabled||!!f},_mouseStart:function(f){var i=this.options,e=this.element.position(),d=this.element;this.resizing=true;this.documentScroll={top:c(document).scrollTop(),left:c(document).scrollLeft()};if(d.is(".ui-draggable")||(/absolute/).test(d.css("position"))){d.css({position:"absolute",top:e.top,left:e.left})}if(c.browser.opera&&(/relative/).test(d.css("position"))){d.css({position:"relative",top:"auto",left:"auto"})}this._renderProxy();var j=b(this.helper.css("left")),g=b(this.helper.css("top"));if(i.containment){j+=c(i.containment).scrollLeft()||0;g+=c(i.containment).scrollTop()||0}this.offset=this.helper.offset();this.position={left:j,top:g};this.size=this._helper?{width:d.outerWidth(),height:d.outerHeight()}:{width:d.width(),height:d.height()};this.originalSize=this._helper?{width:d.outerWidth(),height:d.outerHeight()}:{width:d.width(),height:d.height()};this.originalPosition={left:j,top:g};this.sizeDiff={width:d.outerWidth()-d.width(),height:d.outerHeight()-d.height()};this.originalMousePosition={left:f.pageX,top:f.pageY};this.aspectRatio=(typeof i.aspectRatio=="number")?i.aspectRatio:((this.originalSize.width/this.originalSize.height)||1);var h=c(".ui-resizable-"+this.axis).css("cursor");c("body").css("cursor",h=="auto"?this.axis+"-resize":h);d.addClass("ui-resizable-resizing");this._propagate("start",f);return true},_mouseDrag:function(d){var g=this.helper,f=this.options,l={},p=this,i=this.originalMousePosition,m=this.axis;var q=(d.pageX-i.left)||0,n=(d.pageY-i.top)||0;var h=this._change[m];if(!h){return false}var k=h.apply(this,[d,q,n]),j=c.browser.msie&&c.browser.version<7,e=this.sizeDiff;if(this._aspectRatio||d.shiftKey){k=this._updateRatio(k,d)}k=this._respectSize(k,d);this._propagate("resize",d);g.css({top:this.position.top+"px",left:this.position.left+"px",width:this.size.width+"px",height:this.size.height+"px"});if(!this._helper&&this._proportionallyResizeElements.length){this._proportionallyResize()}this._updateCache(k);this._trigger("resize",d,this.ui());return false},_mouseStop:function(g){this.resizing=false;var h=this.options,l=this;if(this._helper){var f=this._proportionallyResizeElements,d=f.length&&(/textarea/i).test(f[0].nodeName),e=d&&c.ui.hasScroll(f[0],"left")?0:l.sizeDiff.height,j=d?0:l.sizeDiff.width;var m={width:(l.size.width-j),height:(l.size.height-e)},i=(parseInt(l.element.css("left"),10)+(l.position.left-l.originalPosition.left))||null,k=(parseInt(l.element.css("top"),10)+(l.position.top-l.originalPosition.top))||null;if(!h.animate){this.element.css(c.extend(m,{top:k,left:i}))}l.helper.height(l.size.height);l.helper.width(l.size.width);if(this._helper&&!h.animate){this._proportionallyResize()}}c("body").css("cursor","auto");this.element.removeClass("ui-resizable-resizing");this._propagate("stop",g);if(this._helper){this.helper.remove()}return false},_updateCache:function(d){var e=this.options;this.offset=this.helper.offset();if(a(d.left)){this.position.left=d.left}if(a(d.top)){this.position.top=d.top}if(a(d.height)){this.size.height=d.height}if(a(d.width)){this.size.width=d.width}},_updateRatio:function(g,f){var h=this.options,i=this.position,e=this.size,d=this.axis;if(g.height){g.width=(e.height*this.aspectRatio)}else{if(g.width){g.height=(e.width/this.aspectRatio)}}if(d=="sw"){g.left=i.left+(e.width-g.width);g.top=null}if(d=="nw"){g.top=i.top+(e.height-g.height);g.left=i.left+(e.width-g.width)}return g},_respectSize:function(k,f){var i=this.helper,h=this.options,q=this._aspectRatio||f.shiftKey,p=this.axis,s=a(k.width)&&h.maxWidth&&(h.maxWidthk.width),r=a(k.height)&&h.minHeight&&(h.minHeight>k.height);if(g){k.width=h.minWidth}if(r){k.height=h.minHeight}if(s){k.width=h.maxWidth}if(l){k.height=h.maxHeight}var e=this.originalPosition.left+this.originalSize.width,n=this.position.top+this.size.height;var j=/sw|nw|w/.test(p),d=/nw|ne|n/.test(p);if(g&&j){k.left=e-h.minWidth}if(s&&j){k.left=e-h.maxWidth}if(r&&d){k.top=n-h.minHeight}if(l&&d){k.top=n-h.maxHeight}var m=!k.width&&!k.height;if(m&&!k.left&&k.top){k.top=null}else{if(m&&!k.top&&k.left){k.left=null}}return k},_proportionallyResize:function(){var j=this.options;if(!this._proportionallyResizeElements.length){return}var f=this.helper||this.element;for(var e=0;e');var d=c.browser.msie&&c.browser.version<7,f=(d?1:0),g=(d?2:-1);this.helper.addClass(this._helper).css({width:this.element.outerWidth()+g,height:this.element.outerHeight()+g,position:"absolute",left:this.elementOffset.left-f+"px",top:this.elementOffset.top-f+"px",zIndex:++h.zIndex});this.helper.appendTo("body").disableSelection()}else{this.helper=this.element}},_change:{e:function(f,e,d){return{width:this.originalSize.width+e}},w:function(g,e,d){var i=this.options,f=this.originalSize,h=this.originalPosition;return{left:h.left+e,width:f.width-e}},n:function(g,e,d){var i=this.options,f=this.originalSize,h=this.originalPosition;return{top:h.top+d,height:f.height-d}},s:function(f,e,d){return{height:this.originalSize.height+d}},se:function(f,e,d){return c.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[f,e,d]))},sw:function(f,e,d){return c.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[f,e,d]))},ne:function(f,e,d){return c.extend(this._change.n.apply(this,arguments),this._change.e.apply(this,[f,e,d]))},nw:function(f,e,d){return c.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[f,e,d]))}},_propagate:function(e,d){c.ui.plugin.call(this,e,[d,this.ui()]);(e!="resize"&&this._trigger(e,d,this.ui()))},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}}));c.extend(c.ui.resizable,{version:"1.7.2",eventPrefix:"resize",defaults:{alsoResize:false,animate:false,animateDuration:"slow",animateEasing:"swing",aspectRatio:false,autoHide:false,cancel:":input,option",containment:false,delay:0,distance:1,ghost:false,grid:false,handles:"e,s,se",helper:false,maxHeight:null,maxWidth:null,minHeight:10,minWidth:10,zIndex:1000}});c.ui.plugin.add("resizable","alsoResize",{start:function(e,f){var d=c(this).data("resizable"),g=d.options;_store=function(h){c(h).each(function(){c(this).data("resizable-alsoresize",{width:parseInt(c(this).width(),10),height:parseInt(c(this).height(),10),left:parseInt(c(this).css("left"),10),top:parseInt(c(this).css("top"),10)})})};if(typeof(g.alsoResize)=="object"&&!g.alsoResize.parentNode){if(g.alsoResize.length){g.alsoResize=g.alsoResize[0];_store(g.alsoResize)}else{c.each(g.alsoResize,function(h,i){_store(h)})}}else{_store(g.alsoResize)}},resize:function(f,h){var e=c(this).data("resizable"),i=e.options,g=e.originalSize,k=e.originalPosition;var j={height:(e.size.height-g.height)||0,width:(e.size.width-g.width)||0,top:(e.position.top-k.top)||0,left:(e.position.left-k.left)||0},d=function(l,m){c(l).each(function(){var p=c(this),q=c(this).data("resizable-alsoresize"),o={},n=m&&m.length?m:["width","height","top","left"];c.each(n||["width","height","top","left"],function(r,t){var s=(q[t]||0)+(j[t]||0);if(s&&s>=0){o[t]=s||null}});if(/relative/.test(p.css("position"))&&c.browser.opera){e._revertToRelativePosition=true;p.css({position:"absolute",top:"auto",left:"auto"})}p.css(o)})};if(typeof(i.alsoResize)=="object"&&!i.alsoResize.nodeType){c.each(i.alsoResize,function(l,m){d(l,m)})}else{d(i.alsoResize)}},stop:function(e,f){var d=c(this).data("resizable");if(d._revertToRelativePosition&&c.browser.opera){d._revertToRelativePosition=false;el.css({position:"relative"})}c(this).removeData("resizable-alsoresize-start")}});c.ui.plugin.add("resizable","animate",{stop:function(h,m){var n=c(this).data("resizable"),i=n.options;var g=n._proportionallyResizeElements,d=g.length&&(/textarea/i).test(g[0].nodeName),e=d&&c.ui.hasScroll(g[0],"left")?0:n.sizeDiff.height,k=d?0:n.sizeDiff.width;var f={width:(n.size.width-k),height:(n.size.height-e)},j=(parseInt(n.element.css("left"),10)+(n.position.left-n.originalPosition.left))||null,l=(parseInt(n.element.css("top"),10)+(n.position.top-n.originalPosition.top))||null;n.element.animate(c.extend(f,l&&j?{top:l,left:j}:{}),{duration:i.animateDuration,easing:i.animateEasing,step:function(){var o={width:parseInt(n.element.css("width"),10),height:parseInt(n.element.css("height"),10),top:parseInt(n.element.css("top"),10),left:parseInt(n.element.css("left"),10)};if(g&&g.length){c(g[0]).css({width:o.width,height:o.height})}n._updateCache(o);n._propagate("resize",h)}})}});c.ui.plugin.add("resizable","containment",{start:function(e,q){var s=c(this).data("resizable"),i=s.options,k=s.element;var f=i.containment,j=(f instanceof c)?f.get(0):(/parent/.test(f))?k.parent().get(0):f;if(!j){return}s.containerElement=c(j);if(/document/.test(f)||f==document){s.containerOffset={left:0,top:0};s.containerPosition={left:0,top:0};s.parentData={element:c(document),left:0,top:0,width:c(document).width(),height:c(document).height()||document.body.parentNode.scrollHeight}}else{var m=c(j),h=[];c(["Top","Right","Left","Bottom"]).each(function(p,o){h[p]=b(m.css("padding"+o))});s.containerOffset=m.offset();s.containerPosition=m.position();s.containerSize={height:(m.innerHeight()-h[3]),width:(m.innerWidth()-h[1])};var n=s.containerOffset,d=s.containerSize.height,l=s.containerSize.width,g=(c.ui.hasScroll(j,"left")?j.scrollWidth:l),r=(c.ui.hasScroll(j)?j.scrollHeight:d);s.parentData={element:j,left:n.left,top:n.top,width:g,height:r}}},resize:function(f,p){var s=c(this).data("resizable"),h=s.options,e=s.containerSize,n=s.containerOffset,l=s.size,m=s.position,q=s._aspectRatio||f.shiftKey,d={top:0,left:0},g=s.containerElement;if(g[0]!=document&&(/static/).test(g.css("position"))){d=n}if(m.left<(s._helper?n.left:0)){s.size.width=s.size.width+(s._helper?(s.position.left-n.left):(s.position.left-d.left));if(q){s.size.height=s.size.width/h.aspectRatio}s.position.left=h.helper?n.left:0}if(m.top<(s._helper?n.top:0)) {s.size.height=s.size.height+(s._helper?(s.position.top-n.top):s.position.top);if(q){s.size.width=s.size.height*h.aspectRatio}s.position.top=s._helper?n.top:0}s.offset.left=s.parentData.left+s.position.left;s.offset.top=s.parentData.top+s.position.top;var k=Math.abs((s._helper?s.offset.left-d.left:(s.offset.left-d.left))+s.sizeDiff.width),r=Math.abs((s._helper?s.offset.top-d.top:(s.offset.top-n.top))+s.sizeDiff.height);var j=s.containerElement.get(0)==s.element.parent().get(0),i=/relative|absolute/.test(s.containerElement.css("position"));if(j&&i){k-=s.parentData.left}if(k+s.size.width>=s.parentData.width){s.size.width=s.parentData.width-k;if(q){s.size.height=s.size.width/s.aspectRatio}}if(r+s.size.height>=s.parentData.height){s.size.height=s.parentData.height-r;if(q){s.size.width=s.size.height*s.aspectRatio}}},stop:function(e,m){var p=c(this).data("resizable"),f=p.options,k=p.position,l=p.containerOffset,d=p.containerPosition,g=p.containerElement;var i=c(p.helper),q=i.offset(),n=i.outerWidth()-p.sizeDiff.width,j=i.outerHeight()-p.sizeDiff.height;if(p._helper&&!f.animate&&(/relative/).test(g.css("position"))){c(this).css({left:q.left-d.left-l.left,width:n,height:j})}if(p._helper&&!f.animate&&(/static/).test(g.css("position"))){c(this).css({left:q.left-d.left-l.left,width:n,height:j})}}});c.ui.plugin.add("resizable","ghost",{start:function(f,g){var d=c(this).data("resizable"),h=d.options,e=d.size;d.ghost=d.originalElement.clone();d.ghost.css({opacity:0.25,display:"block",position:"relative",height:e.height,width:e.width,margin:0,left:0,top:0}).addClass("ui-resizable-ghost").addClass(typeof h.ghost=="string"?h.ghost:"");d.ghost.appendTo(d.helper)},resize:function(e,f){var d=c(this).data("resizable"),g=d.options;if(d.ghost){d.ghost.css({position:"relative",height:d.size.height,width:d.size.width})}},stop:function(e,f){var d=c(this).data("resizable"),g=d.options;if(d.ghost&&d.helper){d.helper.get(0).removeChild(d.ghost.get(0))}}});c.ui.plugin.add("resizable","grid",{resize:function(d,l){var n=c(this).data("resizable"),g=n.options,j=n.size,h=n.originalSize,i=n.originalPosition,m=n.axis,k=g._aspectRatio||d.shiftKey;g.grid=typeof g.grid=="number"?[g.grid,g.grid]:g.grid;var f=Math.round((j.width-h.width)/(g.grid[0]||1))*(g.grid[0]||1),e=Math.round((j.height-h.height)/(g.grid[1]||1))*(g.grid[1]||1);if(/^(se|s|e)$/.test(m)){n.size.width=h.width+f;n.size.height=h.height+e}else{if(/^(ne)$/.test(m)){n.size.width=h.width+f;n.size.height=h.height+e;n.position.top=i.top-e}else{if(/^(sw)$/.test(m)){n.size.width=h.width+f;n.size.height=h.height+e;n.position.left=i.left-f}else{n.size.width=h.width+f;n.size.height=h.height+e;n.position.top=i.top-e;n.position.left=i.left-f}}}}});var b=function(d){return parseInt(d,10)||0};var a=function(d){return !isNaN(parseInt(d,10))}})(jQuery);; /** * jQuery.ScrollTo - Easy element scrolling using jQuery. * Copyright (c) 2008 Ariel Flesler - aflesler(at)gmail(dot)com * Licensed under GPL license (http://www.opensource.org/licenses/gpl-license.php). * Date: 2/8/2008 * @author Ariel Flesler * @version 1.3.2 */ ;(function($){var o=$.scrollTo=function(a,b,c){o.window().scrollTo(a,b,c)};o.defaults={axis:'y',duration:1};o.window=function(){return $($.browser.safari?'body':'html')};$.fn.scrollTo=function(l,m,n){if(typeof m=='object'){n=m;m=0}n=$.extend({},o.defaults,n);m=m||n.speed||n.duration;n.queue=n.queue&&n.axis.length>1;if(n.queue)m/=2;n.offset=j(n.offset);n.over=j(n.over);return this.each(function(){var a=this,b=$(a),t=l,c,d={},w=b.is('html,body');switch(typeof t){case'number':case'string':if(/^([+-]=)?\d+(px)?$/.test(t)){t=j(t);break}t=$(t,this);case'object':if(t.is||t.style)c=(t=$(t)).offset()}$.each(n.axis.split(''),function(i,f){var P=f=='x'?'Left':'Top',p=P.toLowerCase(),k='scroll'+P,e=a[k],D=f=='x'?'Width':'Height';if(c){d[k]=c[p]+(w?0:e-b.offset()[p]);if(n.margin){d[k]-=parseInt(t.css('margin'+P))||0;d[k]-=parseInt(t.css('border'+P+'Width'))||0}d[k]+=n.offset[p]||0;if(n.over[p])d[k]+=t[D.toLowerCase()]()*n.over[p]}else d[k]=t[p];if(/^\d+$/.test(d[k]))d[k]=d[k]<=0?0:Math.min(d[k],h(D));if(!i&&n.queue){if(e!=d[k])g(n.onAfterFirst);delete d[k]}});g(n.onAfter);function g(a){b.animate(d,m,n.easing,a&&function(){a.call(this,l)})};function h(D){var b=w?$.browser.opera?document.body:document.documentElement:a;return b['scroll'+D]-b['client'+D]}})};function j(a){return typeof a=='object'?a:{top:a,left:a}}})(jQuery); allegro4.4-4.4.2/addons/allegrogl/docs/html/mainpage_8foo.html000066400000000000000000000057071173507505700241350ustar00rootroot00000000000000 AllegroGL: mainpage.foo File Reference

mainpage.foo File Reference

This file only contains the information useful for the main page of the documentation - There is no code here. More...

Go to the source code of this file.


Detailed Description

This file only contains the information useful for the main page of the documentation - There is no code here.

Definition in file mainpage.foo.

allegro4.4-4.4.2/addons/allegrogl/docs/html/mainpage_8foo_source.html000066400000000000000000000050701173507505700255060ustar00rootroot00000000000000 AllegroGL: mainpage.foo Source File
allegro4.4-4.4.2/addons/allegrogl/docs/html/math_8c.html000066400000000000000000000167231173507505700227440ustar00rootroot00000000000000 AllegroGL: math.c File Reference

math.c File Reference

Converting mathematical structures from Allegro to OpenGL. More...

#include <math.h>
#include <allegro.h>
#include "alleggl.h"
#include "allglint.h"

Go to the source code of this file.

Defines

  • #define M_PI   3.14159265358979323846
  • #define ALGL_NOCONV(x)   x
  • #define TRANSLATE_AL_TO_GL(al_type, gl_type, convertor)
  • #define RAD_2_DEG(a)   ((a) * 180 / M_PI)

Functions

Matrix conversion routines
  • void allegro_gl_MATRIX_to_GLfloat (MATRIX *m, GLfloat gl[16])
    Converts an Allegro fixed-point matrix to an array of floats suitable for OpenGL's matrix operations.
  • void allegro_gl_MATRIX_to_GLdouble (MATRIX *m, GLdouble gl[16])
    Converts an Allegro fixed-point matrix to an array of doubles suitable for OpenGL's matrix operations.
  • void allegro_gl_MATRIX_f_to_GLfloat (MATRIX_f *m, GLfloat gl[16])
    Converts an Allegro floating-point matrix to an array of floats suitable for OpenGL's matrix operations.
  • void allegro_gl_MATRIX_f_to_GLdouble (MATRIX_f *m, GLdouble gl[16])
    Converts an Allegro floating-point matrix to an array of doubles suitable for OpenGL's matrix operations.

Detailed Description

Converting mathematical structures from Allegro to OpenGL.

This file provides routines to make Allegro matrices from GL-style matrices, and vice versa. This also provides a QUAT to glRotate converter.

Note that Allegro matrices can only store affine transformations.

Definition in file math.c.


Define Documentation

#define TRANSLATE_AL_TO_GL (   al_type,
  gl_type,
  convertor 
)
Value:
void allegro_gl_##al_type##_to_##gl_type (al_type *m, gl_type gl[16]) \
    { \
        int col, row; \
        for (col = 0; col < 3; col++) \
            for (row = 0; row < 3; row++) \
                gl[col*4+row] = convertor (m->v[col][row]); \
        for (row = 0; row < 3; row++) \
            gl[12+row] = convertor (m->t[row]); \
        for (col = 0; col < 3; col++) \
            gl[4*col + 3] = 0; \
        gl[15] = 1; \
    }

Definition at line 28 of file math.c.

allegro4.4-4.4.2/addons/allegrogl/docs/html/math_8c_source.html000066400000000000000000000266401173507505700243230ustar00rootroot00000000000000 AllegroGL: math.c Source File

math.c

Go to the documentation of this file.
00001 /* This code is (C) AllegroGL contributors, and double licensed under
00002  * the GPL and zlib licenses. See gpl.txt or zlib.txt for details.
00003  */
00015 #include <math.h>
00016 #include <allegro.h>
00017 #include "alleggl.h"
00018 #include "allglint.h"
00019 
00020 
00021 #ifndef M_PI
00022    #define M_PI   3.14159265358979323846
00023 #endif
00024 
00025 
00026 #define ALGL_NOCONV(x) x
00027 
00028 #define TRANSLATE_AL_TO_GL(al_type, gl_type, convertor) \
00029     void allegro_gl_##al_type##_to_##gl_type (al_type *m, gl_type gl[16]) \
00030     { \
00031         int col, row; \
00032         for (col = 0; col < 3; col++) \
00033             for (row = 0; row < 3; row++) \
00034                 gl[col*4+row] = convertor (m->v[col][row]); \
00035         for (row = 0; row < 3; row++) \
00036             gl[12+row] = convertor (m->t[row]); \
00037         for (col = 0; col < 3; col++) \
00038             gl[4*col + 3] = 0; \
00039         gl[15] = 1; \
00040     }
00041 
00042 
00043 
00066 TRANSLATE_AL_TO_GL(MATRIX, GLfloat, fixtof)
00067 
00068 
00069     
00070 
00082 TRANSLATE_AL_TO_GL(MATRIX, GLdouble, fixtof)
00083 
00084     
00085 
00098 TRANSLATE_AL_TO_GL(MATRIX_f, GLfloat, ALGL_NOCONV)
00099 
00100 
00101 
00114 TRANSLATE_AL_TO_GL(MATRIX_f, GLdouble, ALGL_NOCONV)
00115 
00116 
00117     
00118 #define TRANSLATE_GL_TO_AL(gl_type, al_type, convertor) \
00119     void allegro_gl_##gl_type##_to_##al_type (gl_type gl[16], al_type *m) \
00120     { \
00121         int col, row; \
00122         for (col = 0; col < 3; col++) \
00123             for (row = 0; row < 3; row++) \
00124                 m->v[col][row] = convertor (gl[col*4+row]); \
00125         for (row = 0; row < 3; row++) \
00126             m->t[row] = convertor (gl[12+row]); \
00127     }
00128 
00129 
00130 
00143 TRANSLATE_GL_TO_AL(GLfloat, MATRIX, ftofix)
00144 
00145 
00146 
00147 
00159 TRANSLATE_GL_TO_AL(GLdouble, MATRIX, ftofix)
00160 
00161 
00162 
00175 TRANSLATE_GL_TO_AL(GLfloat, MATRIX_f, ALGL_NOCONV)
00176 
00177     
00178 
00192 TRANSLATE_GL_TO_AL(GLdouble, MATRIX_f, ALGL_NOCONV)
00193 
00194 
00195 #undef ALGL_NOCONV
00196 
00197 
00198 #ifndef RAD_2_DEG
00199     #define RAD_2_DEG(a) ((a) * 180 / M_PI)
00200 #endif
00201 
00202     
00203 
00204 /* void allegro_gl_apply_quat(QUAT *q) */
00222 void allegro_gl_apply_quat(QUAT *q) {
00223 
00224     float theta;
00225     ASSERT(q);
00226     ASSERT(__allegro_gl_valid_context);
00227 
00228     theta = RAD_2_DEG(2 * acos(q->w));
00229     if (q->w < 1.0f && q->w > -1.0f) 
00230         glRotatef(theta, q->x, q->y, q->z); 
00231 
00232     return;
00233 }
00234 
00235 
00236 
00237 /* void allegro_gl_quat_to_glrotatef(QUAT *q, float *angle, float *x, float *y, float *z) */
00258 void allegro_gl_quat_to_glrotatef(QUAT *q, float *angle, float *x, float *y, float *z) {
00259 
00260     ASSERT(q);
00261     ASSERT(angle);
00262     ASSERT(x);
00263     ASSERT(y);
00264     ASSERT(z);
00265 
00266     *angle = RAD_2_DEG(2 * acos(q->w));
00267     *x = q->x;
00268     *y = q->y;
00269     *z = q->z;
00270 
00271     return;
00272 }
00273 
00274 
00275 
00276 /* void allegro_gl_quat_to_glrotated(QUAT *q, double *angle, double *x, double *y, double *z) */
00290 void allegro_gl_quat_to_glrotated(QUAT *q, double *angle, double *x, double *y, double *z) {
00291 
00292     ASSERT(q);
00293     ASSERT(angle);
00294     ASSERT(x);
00295     ASSERT(y);
00296     ASSERT(z);
00297 
00298     *angle = RAD_2_DEG(2 * acos(q->w));
00299     *x = q->x;
00300     *y = q->y;
00301     *z = q->z;
00302 
00303     return;
00304 }
00305 
allegro4.4-4.4.2/addons/allegrogl/docs/html/modules.html000066400000000000000000000060111173507505700230560ustar00rootroot00000000000000 AllegroGL: Modules
allegro4.4-4.4.2/addons/allegrogl/docs/html/nav_f.png000066400000000000000000000002371173507505700223230ustar00rootroot00000000000000‰PNG  IHDR8³»fIDATxíÝIB1 Q;uÛ¿@ÑÏh;áÚ ±aË !ŽÐ‹V½CÈíþ âŠÅÆ|c±˜¾™¶¶3èsÑFÐFP»S{PšSšsVãlN®F.F.“ã2’ˆüµ¤ï_U¿Œ¾˜Ïþ«‰ÈH Ým”°•IEND®B`‚allegro4.4-4.4.2/addons/allegrogl/docs/html/nav_h.png000066400000000000000000000001411173507505700223170ustar00rootroot00000000000000‰PNG  IHDR ,é@(IDATxíݱ 0 A½2°ÁU¶— !kÜJrª¯ƒžZýÿÆo‡üèIEND®B`‚allegro4.4-4.4.2/addons/allegrogl/docs/html/navtree.css000066400000000000000000000031471173507505700227050ustar00rootroot00000000000000#nav-tree .children_ul { margin:0; padding:4px; } #nav-tree ul { list-style:none outside none; margin:0px; padding:0px; } #nav-tree li { white-space:nowrap; margin:0px; padding:0px; } #nav-tree .plus { margin:0px; } #nav-tree .selected { background-image: url('tab_a.png'); background-repeat:repeat-x; color: #fff; text-shadow: 0px 1px 1px rgba(0, 0, 0, 1.0); } #nav-tree img { margin:0px; padding:0px; border:0px; vertical-align: middle; } #nav-tree a { text-decoration:none; padding:0px; margin:0px; outline:none; } #nav-tree .label { margin:0px; padding:0px; } #nav-tree .label a { padding:2px; } #nav-tree .selected a { text-decoration:none; padding:2px; margin:0px; color:#fff; } #nav-tree .children_ul { margin:0px; padding:0px; } #nav-tree .item { margin:0px; padding:0px; } #nav-tree { padding: 0px 0px; background-color: #FAFAFF; font-size:14px; overflow:auto; } #doc-content { overflow:auto; display:block; padding:0px; margin:0px; } #side-nav { padding:0 6px 0 0; margin: 0px; display:block; position: absolute; left: 0px; width: 300px; } .ui-resizable .ui-resizable-handle { display:block; } .ui-resizable-e { background:url("ftv2splitbar.png") repeat scroll right center transparent; cursor:e-resize; height:100%; right:0; top:0; width:6px; } .ui-resizable-handle { display:none; font-size:0.1px; position:absolute; z-index:1; } #nav-tree-contents { margin: 6px 0px 0px 0px; } #nav-tree { background-image:url('nav_h.png'); background-repeat:repeat-x; background-color: #F9FAFC; } allegro4.4-4.4.2/addons/allegrogl/docs/html/navtree.js000066400000000000000000000434571173507505700225410ustar00rootroot00000000000000var NAVTREE = [ [ "AllegroGL", "index.html", [ [ "AllegroGL", "index.html", null ], [ "Related Pages", "pages.html", [ [ "Deprecated List", "deprecated.html", null ] ] ], [ "Modules", "modules.html", [ [ "Version information", "group__version.html", null ], [ "Core routines", "group__core.html", [ [ "Defines", "group__core.html", [ [ "allegro_gl_begin", "group__core.html#ga59b02f9584f81789449a7fcc2018bfc5", null ], [ "allegro_gl_end", "group__core.html#gac1303e0363f3adfc33c8812e9b8e30b0", null ] ] ], [ "Functions", "group__core.html", [ [ "install_allegro_gl", "group__core.html#gaa0cbb82fa1e2bae6788eb7bd06673bd3", null ], [ "remove_allegro_gl", "group__core.html#gaeff6abbb1d1071a01f4cd694ef504298", null ], [ "allegro_gl_flip", "group__core.html#gaf5aad043e99b766393fa4a7ec034a0f1", null ], [ "allegro_gl_opengl_version", "group__core.html#ga444d507eaeb5ba800787f6a81827615d", null ] ] ] ] ], [ "Graphics drivers", "group__gfxdrv.html", null ], [ "Bitmap Routines", "group__bitmap.html", [ [ "Functions", "group__bitmap.html", [ [ "allegro_gl_set_video_bitmap_color_depth", "group__bitmap.html#ga92d58cf7b4bebf34aa27112efba1020e", null ] ] ] ] ], [ "Texture Routines", "group__texture.html", [ [ "Defines", "group__texture.html", [ [ "AGL_TEXTURE_FLIP", "group__texture.html#gadeffe4feb290278035beacedb284a010", null ], [ "AGL_TEXTURE_MASKED", "group__texture.html#gaba184d573c65f33b35d1d57936607d08", null ], [ "AGL_TEXTURE_RESCALE", "group__texture.html#gaa8b7246edc7ec019ec3b434eb0cacdf2", null ] ] ], [ "Functions", "group__texture.html", [ [ "allegro_gl_use_mipmapping", "group__texture.html#gab5393ecc10a2a31da7eb80c889af89ac", null ], [ "allegro_gl_use_alpha_channel", "group__texture.html#ga1d88f4ebc7ed1ecd65640b72ea46a71e", null ], [ "allegro_gl_flip_texture", "group__texture.html#ga3ec0a1c4c6656f13c8398bab7a1293f2", null ], [ "allegro_gl_check_texture", "group__texture.html#ga6996c14538e18b1614f91d34b2d4d691", null ], [ "allegro_gl_check_texture_ex", "group__texture.html#gab0cf4dc0ddcb45f5b067d08aed1c88e6", null ], [ "allegro_gl_get_texture_format", "group__texture.html#ga2392fe7a8dd6db65532160821804aa68", null ], [ "allegro_gl_set_texture_format", "group__texture.html#ga5d535e8af776dd449cc4755b9e3585b1", null ], [ "allegro_gl_make_texture", "group__texture.html#gae071354f76bc28e1bafbd90bdecbc0c9", null ], [ "allegro_gl_make_masked_texture", "group__texture.html#gaeb33dfbbc1725f5132c10ac32ef6800d", null ], [ "allegro_gl_make_texture_ex", "group__texture.html#gaf3a48c555068e7051171255c1011150a", null ] ] ] ] ], [ "Math conversion routines", "group__math.html", [ [ "Functions", "group__math.html", [ [ "allegro_gl_MATRIX_to_GLfloat", "group__math.html#ga4cf4f453cb3f95a1e7e861a7401b4a8d", null ], [ "allegro_gl_MATRIX_to_GLdouble", "group__math.html#gaee6cb48f8e3e70abecc6c282a8ea1edc", null ], [ "allegro_gl_MATRIX_f_to_GLfloat", "group__math.html#gae8e0ee18b9aeca955402be16de6ca79d", null ], [ "allegro_gl_MATRIX_f_to_GLdouble", "group__math.html#gab93f3588ea08b048f418023aa76cb3fc", null ], [ "allegro_gl_GLfloat_to_MATRIX", "group__math.html#ga468e83ca4de52ed839978d48f5dbe111", null ], [ "allegro_gl_GLdouble_to_MATRIX", "group__math.html#ga68e2e0e9dcdba42004070a5f8f547994", null ], [ "allegro_gl_GLfloat_to_MATRIX_f", "group__math.html#ga08692466ae37d7888bbd5f5ee5aa9268", null ], [ "allegro_gl_GLdouble_to_MATRIX_f", "group__math.html#gaa6b729a9e93e249a8a76e078e94a2b44", null ] ] ] ] ], [ "Text drawing and fonts.", "group__Text.html", [ [ "Defines", "group__Text.html", [ [ "AGL_FONT_TYPE_DONT_CARE", "group__Text.html#gad2ebae17d2548a5befb888f8618f2206", null ], [ "AGL_FONT_TYPE_BITMAP", "group__Text.html#ga7ed8fdc1b0065d2fe584b15d69108b1a", null ], [ "AGL_FONT_TYPE_OUTLINE", "group__Text.html#gaba7b8c941356029687ff4b4340e8b841", null ], [ "AGL_FONT_TYPE_TEXTURED", "group__Text.html#ga92bf039bc7b06568273ee17f15cf6671", null ], [ "AGL_FONT_STYLE_BOLD", "group__Text.html#gab77d7d2c6ec6d1786472943f7cd814ca", null ], [ "AGL_FONT_STYLE_BLACK", "group__Text.html#ga27874c1fb7fdc1e00115bd853c973fc3", null ], [ "AGL_FONT_STYLE_ITALIC", "group__Text.html#ga67c48bf08c2b6cd6cc1a08dec2c7c5ef", null ], [ "AGL_FONT_STYLE_UNDERLINE", "group__Text.html#gae9e4682339d264429ee601c632231c9f", null ], [ "AGL_FONT_STYLE_STRIKEOUT", "group__Text.html#ga6ba31b9c7866d28b5494fad2577569db", null ], [ "AGL_FONT_STYLE_ANTI_ALIASED", "group__Text.html#ga91cc859278878dd4bf200bed7eab4359", null ], [ "AGL_FONT_POLYGONS", "group__Text.html#ga4b45ef558e7934ceaaff146f450ab23f", null ], [ "AGL_FONT_LINES", "group__Text.html#ga0b426eb30e7203eb094a7adfbb04cb6d", null ] ] ], [ "Functions", "group__Text.html", [ [ "allegro_gl_printf", "group__Text.html#ga84ecf6d5f5b363d7715e15eca8ebafeb", null ], [ "allegro_gl_printf_ex", "group__Text.html#gab93317445f8a566f8b5632e04fbf8e5b", null ], [ "allegro_gl_convert_allegro_font", "group__Text.html#gad01388c5188ae09628284aa2425acae9", null ], [ "allegro_gl_convert_allegro_font_ex", "group__Text.html#ga4986ec80f1a3362e47f7669461fef414", null ], [ "allegro_gl_set_font_generation_mode", "group__Text.html#ga62e79ccec5062f1cdadbc225319e9b44", null ], [ "allegro_gl_load_system_font", "group__Text.html#ga5bddcc6c1954665140083928117519de", null ], [ "allegro_gl_load_system_font_ex", "group__Text.html#ga4ad68c54b0183c60cdbf2c7a02dc3157", null ], [ "allegro_gl_destroy_font", "group__Text.html#gabcbdd9810f7254cdb105f987ae1e557f", null ], [ "allegro_gl_list_font_textures", "group__Text.html#ga70b78c3a523dc9977c222d466edc6a5a", null ] ] ] ] ], [ "OpenGL Extensions", "group__extensions.html", [ [ "Defines", "group__extensions.html", [ [ "AGL_DEFINE_PROC_TYPE", "group__extensions.html#gac45f9222ac965c8d0d756f513cebf0d1", null ] ] ], [ "Functions", "group__extensions.html", [ [ "allegro_gl_is_extension_supported", "group__extensions.html#ga7351f56ea1c4f4665193fc3bf547ff0a", null ], [ "allegro_gl_get_proc_address", "group__extensions.html#gaa0c2cd7c4b4a94e8801af42a58356cc4", null ] ] ], [ "Variables", "group__extensions.html", [ [ "allegro_gl_extensions_GL", "group__extensions.html#ga7492f6f6acc608789210560ee63e5436", null ], [ "agl_extension_table", "group__extensions.html#ga2d6ebb26eec58470e4242b750656268b", null ] ] ] ] ], [ "Allegro-compatible GUI routines", "group__gui.html", [ [ "Functions", "group__gui.html", [ [ "algl_do_dialog", "group__gui.html#ga30c12b20a701f84f994ebcbea14afc99", null ], [ "algl_popup_dialog", "group__gui.html#ga4c6641a5fe463ca062b90bcc3bb5677d", null ], [ "algl_draw_mouse", "group__gui.html#ga4418d38b8585ab443ba7f41a476765c6", null ], [ "algl_set_mouse_drawer", "group__gui.html#ga428394c0ae4d4a1e96fe2b27fb13f745", null ], [ "algl_alert", "group__gui.html#gad6be783b911635769fcb54d188a77107", null ], [ "algl_alert3", "group__gui.html#gadc8b61d7a682b7be11f0f1cc864b30be", null ], [ "d_algl_viewport_proc", "group__gui.html#gae41d96ae1ebefffdf60391e632915fd3", null ] ] ] ] ], [ "Allegro Graphics Driver", "group__glvtable.html", [ [ "Defines", "group__glvtable.html", [ [ "SET_TEX_COORDS", "group__glvtable.html#ga397c41b7c07794b6edce960693361a83", null ] ] ], [ "Functions", "group__glvtable.html", [ [ "allegro_gl_screen_acquire", "group__glvtable.html#ga702812e50246c61eb9f01fd8aba69325", null ], [ "allegro_gl_screen_release", "group__glvtable.html#ga6c2b0685587a0feafcb194a9a67d6aa9", null ], [ "allegro_gl_video_acquire", "group__glvtable.html#ga7002daa2a3e02adf79bed09039469595", null ], [ "allegro_gl_video_release", "group__glvtable.html#ga6fe7f8e5d64ab6b6e85643adefe8b0d5", null ] ] ] ] ], [ "Option settings", "group__settings.html", [ [ "Defines", "group__settings.html", [ [ "AGL_ALLEGRO_FORMAT", "group__settings.html#gab34e1290cbeb5fe252642f3bd59f0a52", null ], [ "AGL_RED_DEPTH", "group__settings.html#gabe75eb7c907fedeef4763ad6c3ffd8f0", null ], [ "AGL_GREEN_DEPTH", "group__settings.html#gada8f8e9bb4e0ccf1bf7f7353d1e6032d", null ], [ "AGL_BLUE_DEPTH", "group__settings.html#ga8efacc076a3d6523dd989211833c1ca8", null ], [ "AGL_ALPHA_DEPTH", "group__settings.html#gad37b2a655ca53a34bb41bc629c8aa51e", null ], [ "AGL_COLOR_DEPTH", "group__settings.html#ga71846e567336fe02f8f063af1282ddc5", null ], [ "AGL_ACC_RED_DEPTH", "group__settings.html#ga317622005a4a2956a0d1659d3c47822a", null ], [ "AGL_ACC_GREEN_DEPTH", "group__settings.html#ga00f4cfb4cb19b60d677b6941fec903ba", null ], [ "AGL_ACC_BLUE_DEPTH", "group__settings.html#gaf80c6da60114ac3962aabcfd8745b97e", null ], [ "AGL_ACC_ALPHA_DEPTH", "group__settings.html#gab8eba4f52cdb3d333b237c0ab0b3594a", null ], [ "AGL_DOUBLEBUFFER", "group__settings.html#gaa1150ae35d6ff9b33d5771f29f9770dd", null ], [ "AGL_STEREO", "group__settings.html#ga47be892718fa4b2c6166caf51da67489", null ], [ "AGL_AUX_BUFFERS", "group__settings.html#ga6267cbe7841d12c35d59032f66b7b871", null ], [ "AGL_Z_DEPTH", "group__settings.html#gabef24a727709a823e8fc900fdb72892e", null ], [ "AGL_STENCIL_DEPTH", "group__settings.html#ga7b34772508e08edb0436e85d2d696fb9", null ], [ "AGL_WINDOW_X", "group__settings.html#gafea8132efd1fcac7a7f997ef0fe34cfa", null ], [ "AGL_RENDERMETHOD", "group__settings.html#ga3cd047a464c8f8d928f9529226a4cf12", null ], [ "AGL_FULLSCREEN", "group__settings.html#ga1baffefcedaffebf7ca47724a0441e60", null ], [ "AGL_WINDOWED", "group__settings.html#ga6fcfd5d01183e704595b05fa9812b94f", null ], [ "AGL_VIDEO_MEMORY_POLICY", "group__settings.html#gab78a9c8ca24294b008d706a409c4fa37", null ], [ "AGL_SAMPLE_BUFFERS", "group__settings.html#gae1836cab58a366c122ace31160fe0e06", null ], [ "AGL_SAMPLES", "group__settings.html#ga92d9751c38774297013087e89a25749d", null ] ] ], [ "Functions", "group__settings.html", [ [ "allegro_gl_clear_settings", "group__settings.html#gadd1249980001c22cb3eba880561a7e19", null ], [ "allegro_gl_set", "group__settings.html#ga025e79a4394803a0e15aaf07b1a8a656", null ], [ "allegro_gl_get", "group__settings.html#ga2179291ddb3cb528c3c0cf84af5c51a9", null ], [ "allegro_gl_save_settings", "group__settings.html#gaa461b9459f56c9274d2d49accf201ee1", null ], [ "allegro_gl_load_settings", "group__settings.html#ga60a577d2fed019cdae83c648f1ff74ec", null ] ] ] ] ], [ "Allegro Interfacing", "group__allegro.html", [ [ "Functions", "group__allegro.html", [ [ "allegro_gl_set_allegro_mode", "group__allegro.html#ga7ea7ffd9b72d0d0722cbf982b729efdb", null ], [ "allegro_gl_unset_allegro_mode", "group__allegro.html#ga00fbbee541046767114bf9746ceb6f8b", null ], [ "allegro_gl_set_projection", "group__allegro.html#gabaf6024e9d196da357aad02c5dc7589f", null ], [ "allegro_gl_unset_projection", "group__allegro.html#ga603f8f3719d02816acdf3dbdcaa1f447", null ] ] ] ] ] ] ], [ "File List", "files.html", [ [ "aglf.c", "aglf_8c.html", null ], [ "alleggl.c", "alleggl_8c.html", null ], [ "alleggl.h", "alleggl_8h.html", null ], [ "allglint.h", null, null ], [ "djgpp.c", null, null ], [ "fontconv.c", "fontconv_8c.html", null ], [ "glext.c", "glext_8c.html", null ], [ "glvtable.c", "glvtable_8c.html", null ], [ "glvtable.h", null, null ], [ "gui.c", "gui_8c.html", null ], [ "mainpage.foo", "mainpage_8foo.html", null ], [ "math.c", "math_8c.html", null ], [ "scorer.c", "scorer_8c.html", null ], [ "texture.c", "texture_8c.html", null ], [ "videovtb.c", "videovtb_8c.html", null ], [ "win.c", null, null ], [ "x.c", null, null ] ] ], [ "Globals", "globals.html", null ] ] ] ]; function createIndent(o,domNode,node,level) { if (node.parentNode && node.parentNode.parentNode) { createIndent(o,domNode,node.parentNode,level+1); } var imgNode = document.createElement("img"); if (level==0 && node.childrenData) { node.plus_img = imgNode; node.expandToggle = document.createElement("a"); node.expandToggle.href = "javascript:void(0)"; node.expandToggle.onclick = function() { if (node.expanded) { $(node.getChildrenUL()).slideUp("fast"); if (node.isLast) { node.plus_img.src = node.relpath+"ftv2plastnode.png"; } else { node.plus_img.src = node.relpath+"ftv2pnode.png"; } node.expanded = false; } else { expandNode(o, node, false); } } node.expandToggle.appendChild(imgNode); domNode.appendChild(node.expandToggle); } else { domNode.appendChild(imgNode); } if (level==0) { if (node.isLast) { if (node.childrenData) { imgNode.src = node.relpath+"ftv2plastnode.png"; } else { imgNode.src = node.relpath+"ftv2lastnode.png"; domNode.appendChild(imgNode); } } else { if (node.childrenData) { imgNode.src = node.relpath+"ftv2pnode.png"; } else { imgNode.src = node.relpath+"ftv2node.png"; domNode.appendChild(imgNode); } } } else { if (node.isLast) { imgNode.src = node.relpath+"ftv2blank.png"; } else { imgNode.src = node.relpath+"ftv2vertline.png"; } } imgNode.border = "0"; } function newNode(o, po, text, link, childrenData, lastNode) { var node = new Object(); node.children = Array(); node.childrenData = childrenData; node.depth = po.depth + 1; node.relpath = po.relpath; node.isLast = lastNode; node.li = document.createElement("li"); po.getChildrenUL().appendChild(node.li); node.parentNode = po; node.itemDiv = document.createElement("div"); node.itemDiv.className = "item"; node.labelSpan = document.createElement("span"); node.labelSpan.className = "label"; createIndent(o,node.itemDiv,node,0); node.itemDiv.appendChild(node.labelSpan); node.li.appendChild(node.itemDiv); var a = document.createElement("a"); node.labelSpan.appendChild(a); node.label = document.createTextNode(text); a.appendChild(node.label); if (link) { a.href = node.relpath+link; } else { if (childrenData != null) { a.className = "nolink"; a.href = "javascript:void(0)"; a.onclick = node.expandToggle.onclick; node.expanded = false; } } node.childrenUL = null; node.getChildrenUL = function() { if (!node.childrenUL) { node.childrenUL = document.createElement("ul"); node.childrenUL.className = "children_ul"; node.childrenUL.style.display = "none"; node.li.appendChild(node.childrenUL); } return node.childrenUL; }; return node; } function showRoot() { var headerHeight = $("#top").height(); var footerHeight = $("#nav-path").height(); var windowHeight = $(window).height() - headerHeight - footerHeight; navtree.scrollTo('#selected',0,{offset:-windowHeight/2}); } function expandNode(o, node, imm) { if (node.childrenData && !node.expanded) { if (!node.childrenVisited) { getNode(o, node); } if (imm) { $(node.getChildrenUL()).show(); } else { $(node.getChildrenUL()).slideDown("fast",showRoot); } if (node.isLast) { node.plus_img.src = node.relpath+"ftv2mlastnode.png"; } else { node.plus_img.src = node.relpath+"ftv2mnode.png"; } node.expanded = true; } } function getNode(o, po) { po.childrenVisited = true; var l = po.childrenData.length-1; for (var i in po.childrenData) { var nodeData = po.childrenData[i]; po.children[i] = newNode(o, po, nodeData[0], nodeData[1], nodeData[2], i==l); } } function findNavTreePage(url, data) { var nodes = data; var result = null; for (var i in nodes) { var d = nodes[i]; if (d[1] == url) { return new Array(i); } else if (d[2] != null) // array of children { result = findNavTreePage(url, d[2]); if (result != null) { return (new Array(i).concat(result)); } } } return null; } function initNavTree(toroot,relpath) { var o = new Object(); o.toroot = toroot; o.node = new Object(); o.node.li = document.getElementById("nav-tree-contents"); o.node.childrenData = NAVTREE; o.node.children = new Array(); o.node.childrenUL = document.createElement("ul"); o.node.getChildrenUL = function() { return o.node.childrenUL; }; o.node.li.appendChild(o.node.childrenUL); o.node.depth = 0; o.node.relpath = relpath; getNode(o, o.node); o.breadcrumbs = findNavTreePage(toroot, NAVTREE); if (o.breadcrumbs == null) { o.breadcrumbs = findNavTreePage("index.html",NAVTREE); } if (o.breadcrumbs != null && o.breadcrumbs.length>0) { var p = o.node; for (var i in o.breadcrumbs) { var j = o.breadcrumbs[i]; p = p.children[j]; expandNode(o,p,true); } p.itemDiv.className = p.itemDiv.className + " selected"; p.itemDiv.id = "selected"; $(window).load(showRoot); } } allegro4.4-4.4.2/addons/allegrogl/docs/html/open.png000066400000000000000000000001661173507505700221740ustar00rootroot00000000000000‰PNG  IHDR à‘=IDATxí1 “ت¦@@   ]01ÀQXY~Jr?D>„¥¶þ’n¼ áFÍ  }ÈúÂéãÏ\ ÄáÿòIEND®B`‚allegro4.4-4.4.2/addons/allegrogl/docs/html/pages.html000066400000000000000000000043711173507505700225140ustar00rootroot00000000000000 AllegroGL: Related Pages

Related Pages

Here is a list of all related documentation pages:
allegro4.4-4.4.2/addons/allegrogl/docs/html/resize.js000066400000000000000000000045021173507505700223620ustar00rootroot00000000000000var cookie_namespace = 'doxygen'; var sidenav,navtree,content,header; function readCookie(cookie) { var myCookie = cookie_namespace+"_"+cookie+"="; if (document.cookie) { var index = document.cookie.indexOf(myCookie); if (index != -1) { var valStart = index + myCookie.length; var valEnd = document.cookie.indexOf(";", valStart); if (valEnd == -1) { valEnd = document.cookie.length; } var val = document.cookie.substring(valStart, valEnd); return val; } } return 0; } function writeCookie(cookie, val, expiration) { if (val==undefined) return; if (expiration == null) { var date = new Date(); date.setTime(date.getTime()+(10*365*24*60*60*1000)); // default expiration is one week expiration = date.toGMTString(); } document.cookie = cookie_namespace + "_" + cookie + "=" + val + "; expires=" + expiration+"; path=/"; } function resizeWidth() { var windowWidth = $(window).width() + "px"; var sidenavWidth = $(sidenav).width(); content.css({marginLeft:parseInt(sidenavWidth)+6+"px"}); //account for 6px-wide handle-bar writeCookie('width',sidenavWidth, null); } function restoreWidth(navWidth) { var windowWidth = $(window).width() + "px"; content.css({marginLeft:parseInt(navWidth)+6+"px"}); sidenav.css({width:navWidth + "px"}); } function resizeHeight() { var headerHeight = header.height(); var footerHeight = footer.height(); var windowHeight = $(window).height() - headerHeight - footerHeight; content.css({height:windowHeight + "px"}); navtree.css({height:windowHeight + "px"}); sidenav.css({height:windowHeight + "px",top: headerHeight+"px"}); } function initResizable() { header = $("#top"); sidenav = $("#side-nav"); content = $("#doc-content"); navtree = $("#nav-tree"); footer = $("#nav-path"); $(".side-nav-resizable").resizable({resize: function(e, ui) { resizeWidth(); } }); $(window).resize(function() { resizeHeight(); }); var width = readCookie('width'); if (width) { restoreWidth(width); } else { resizeWidth(); } resizeHeight(); var url = location.href; var i=url.indexOf("#"); if (i>=0) window.location.hash=url.substr(i); var _preventDefault = function(evt) { evt.preventDefault(); }; $("#splitbar").bind("dragstart", _preventDefault).bind("selectstart", _preventDefault); } allegro4.4-4.4.2/addons/allegrogl/docs/html/scorer_8c.html000066400000000000000000000133761173507505700233110ustar00rootroot00000000000000 AllegroGL: scorer.c File Reference

scorer.c File Reference

Scoring system for screen mode selection (internal). More...

#include <allegro.h>
#include "alleggl.h"
#include "allglint.h"

Go to the source code of this file.

Defines

  • #define target   allegro_gl_display_info
  • #define req   __allegro_gl_required_settings
  • #define sug   __allegro_gl_suggested_settings
  • #define PREFIX_I   "agl-scorer INFO: "

Functions

  • void __allegro_gl_fill_in_info ()
  • void __allegro_gl_reset_scorer (void)
  • static int get_score (struct allegro_gl_display_info *dinfo)
  • int __allegro_gl_score_config (int refnum, struct allegro_gl_display_info *dinfo)
  • int __allegro_gl_best_config (void)

Variables

  • static int best
  • static int best_score

Detailed Description

Scoring system for screen mode selection (internal).

Definition in file scorer.c.

allegro4.4-4.4.2/addons/allegrogl/docs/html/scorer_8c_source.html000066400000000000000000001327701173507505700246710ustar00rootroot00000000000000 AllegroGL: scorer.c Source File

scorer.c

Go to the documentation of this file.
00001 /* This code is (C) AllegroGL contributors, and double licensed under
00002  * the GPL and zlib licenses. See gpl.txt or zlib.txt for details.
00003  */
00008 #include <allegro.h>
00009 
00010 #include "alleggl.h"
00011 #include "allglint.h"
00012 
00013 
00014 static int best, best_score;
00015 
00016 
00017 #define target allegro_gl_display_info
00018 #define req __allegro_gl_required_settings
00019 #define sug __allegro_gl_suggested_settings
00020 
00021 #define PREFIX_I                "agl-scorer INFO: "
00022 
00023 
00024 /* __allegro_gl_fill_in_info()
00025  * Will fill in missing settings by 'guessing'
00026  * what the user intended.
00027  */
00028 void __allegro_gl_fill_in_info() {
00029     
00030     int all_components = AGL_RED_DEPTH | AGL_GREEN_DEPTH | AGL_BLUE_DEPTH
00031                        | AGL_ALPHA_DEPTH;
00032 
00033     /* If all color components were set, but not the color depth */
00034     if ((((req | sug) & AGL_COLOR_DEPTH) == 0)
00035      && (((req | sug) & all_components) == all_components)) {
00036 
00037         target.colour_depth = target.pixel_size.rgba.r
00038                             + target.pixel_size.rgba.g
00039                             + target.pixel_size.rgba.b
00040                             + target.pixel_size.rgba.a;
00041             
00042         /* Round depth to 8 bits */
00043         target.colour_depth = (target.colour_depth + 7) / 8;
00044     }
00045     /* If only some components were set, guess the others */
00046     else if ((req | sug) & all_components) {
00047         
00048         int avg = ((req | sug) & AGL_RED_DEPTH   ? target.pixel_size.rgba.r: 0)
00049                 + ((req | sug) & AGL_GREEN_DEPTH ? target.pixel_size.rgba.g: 0)
00050                 + ((req | sug) & AGL_BLUE_DEPTH  ? target.pixel_size.rgba.b: 0)
00051                 + ((req | sug) & AGL_ALPHA_DEPTH ? target.pixel_size.rgba.a: 0);
00052             
00053         int num = ((req | sug) & AGL_RED_DEPTH   ? 1 : 0)
00054                 + ((req | sug) & AGL_GREEN_DEPTH ? 1 : 0)
00055                 + ((req | sug) & AGL_BLUE_DEPTH  ? 1 : 0)
00056                 + ((req | sug) & AGL_ALPHA_DEPTH ? 1 : 0);
00057 
00058         avg /= (num ? num : 1);
00059         
00060         if (((req | sug) & AGL_RED_DEPTH )== 0) {
00061             sug |= AGL_RED_DEPTH;
00062             target.pixel_size.rgba.r = avg;
00063         }
00064         if (((req | sug) & AGL_GREEN_DEPTH) == 0) {
00065             sug |= AGL_GREEN_DEPTH;
00066             target.pixel_size.rgba.g = avg;
00067         }
00068         if (((req | sug) & AGL_BLUE_DEPTH) == 0) {
00069             sug |= AGL_BLUE_DEPTH;
00070             target.pixel_size.rgba.b = avg;
00071         }
00072         if (((req | sug) & AGL_ALPHA_DEPTH) == 0) {
00073             sug |= AGL_ALPHA_DEPTH;
00074             target.pixel_size.rgba.a = avg;
00075         }
00076         
00077         /* If color depth wasn't defined, figure it out */
00078         if (((req | sug) & AGL_COLOR_DEPTH) == 0) {
00079             __allegro_gl_fill_in_info();
00080         }
00081     }
00082     
00083     /* If the user forgot to set a color depth in AGL, but used the
00084      * Allegro one instead
00085      */
00086     if ((((req | sug) & AGL_COLOR_DEPTH) == 0) && (target.colour_depth == 0)) {
00087         BITMAP *temp = create_bitmap(1, 1);
00088         if (temp) {
00089             allegro_gl_set(AGL_COLOR_DEPTH, bitmap_color_depth(temp));
00090             allegro_gl_set(AGL_REQUIRE, AGL_COLOR_DEPTH);
00091             destroy_bitmap(temp);
00092         }
00093     }
00094 
00095 
00096     /* Prefer double-buffering */
00097     if (!((req | sug) & AGL_DOUBLEBUFFER)) {
00098         allegro_gl_set(AGL_DOUBLEBUFFER, 1);
00099         allegro_gl_set(AGL_SUGGEST, AGL_DOUBLEBUFFER);
00100     }
00101 
00102     /* Prefer no multisamping */
00103     if (!((req | sug) & (AGL_SAMPLE_BUFFERS | AGL_SAMPLES))) {
00104         allegro_gl_set(AGL_SAMPLE_BUFFERS, 0);
00105         allegro_gl_set(AGL_SAMPLES,        0);
00106         allegro_gl_set(AGL_SUGGEST, AGL_SAMPLE_BUFFERS | AGL_SAMPLES);
00107     }
00108 
00109     /* Prefer monoscopic */
00110     if (!((req | sug) & AGL_STEREO)) {
00111         allegro_gl_set(AGL_STEREO, 0);
00112         allegro_gl_set(AGL_SUGGEST, AGL_STEREO);
00113     }
00114 
00115     /* Prefer unsigned normalized buffers */
00116     if (!((req | sug) & (AGL_FLOAT_COLOR | AGL_FLOAT_Z))) {
00117         allegro_gl_set(AGL_FLOAT_COLOR, 0);
00118         allegro_gl_set(AGL_FLOAT_Z, 0);
00119         allegro_gl_set(AGL_SUGGEST, AGL_FLOAT_COLOR | AGL_FLOAT_Z);
00120     }
00121 }
00122 
00123 
00124 
00125 void __allegro_gl_reset_scorer(void)
00126 {
00127     best = -1;
00128     best_score = -1;
00129 }
00130 
00131 
00132 
00133 static int get_score(struct allegro_gl_display_info *dinfo)
00134 {
00135     int score = 0;
00136 
00137     if (dinfo->colour_depth != target.colour_depth) {
00138         if (req & AGL_COLOR_DEPTH) {
00139             ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE,
00140                       get_config_text("Color depth requirement not met."));
00141             return -1;
00142         }
00143     }
00144     else {
00145         /* If requested color depths agree */
00146         score += 128;
00147     }
00148     
00149 
00150     if (sug & AGL_COLOR_DEPTH) {
00151         if (dinfo->colour_depth < target.colour_depth)
00152             score += (96 * dinfo->colour_depth) / target.colour_depth;
00153         else
00154             score += 96 + 96 / (1 + dinfo->colour_depth - target.colour_depth);
00155     }
00156 
00157     
00158     /* check colour component widths here and Allegro formatness */
00159     if ((req & AGL_RED_DEPTH)
00160      && (dinfo->pixel_size.rgba.r != target.pixel_size.rgba.r)) {
00161 
00162         ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE,
00163                   get_config_text("Red depth requirement not met."));
00164         return -1;
00165     }
00166 
00167     if (sug & AGL_RED_DEPTH) {
00168         if (dinfo->pixel_size.rgba.r < target.pixel_size.rgba.r) {
00169             score += (16 * dinfo->pixel_size.rgba.r) / target.pixel_size.rgba.r;
00170         }
00171         else {
00172             score += 16
00173                + 16 / (1 + dinfo->pixel_size.rgba.r - target.pixel_size.rgba.r);
00174         }
00175     }
00176 
00177     if ((req & AGL_GREEN_DEPTH)
00178      && (dinfo->pixel_size.rgba.g != target.pixel_size.rgba.g)) {
00179 
00180         ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE,
00181                   get_config_text("Green depth requirement not met."));
00182         return -1;
00183     }
00184 
00185     if (sug & AGL_GREEN_DEPTH) {
00186         if (dinfo->pixel_size.rgba.g < target.pixel_size.rgba.g) {
00187             score += (16 * dinfo->pixel_size.rgba.g) / target.pixel_size.rgba.g;
00188         }
00189         else {
00190             score += 16
00191                + 16 / (1 + dinfo->pixel_size.rgba.g - target.pixel_size.rgba.g);
00192         }
00193     }
00194 
00195     if ((req & AGL_BLUE_DEPTH)
00196      && (dinfo->pixel_size.rgba.b != target.pixel_size.rgba.b)) {
00197 
00198         ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE,
00199                   get_config_text("Blue depth requirement not met."));
00200         return -1;
00201     }
00202 
00203     if (sug & AGL_BLUE_DEPTH) {
00204         if (dinfo->pixel_size.rgba.b < target.pixel_size.rgba.b) {
00205             score += (16 * dinfo->pixel_size.rgba.b) / target.pixel_size.rgba.b;
00206         }
00207         else {
00208             score += 16
00209                + 16 / (1 + dinfo->pixel_size.rgba.b - target.pixel_size.rgba.b);
00210         }
00211     }
00212 
00213     if ((req & AGL_ALPHA_DEPTH)
00214      && (dinfo->pixel_size.rgba.a != target.pixel_size.rgba.a)) {
00215 
00216         ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE,
00217                   get_config_text("Alpha depth requirement not met."));
00218         return -1;
00219     }
00220 
00221     if (sug & AGL_ALPHA_DEPTH) {
00222         if (dinfo->pixel_size.rgba.a < target.pixel_size.rgba.a) {
00223             score += (16 * dinfo->pixel_size.rgba.a) / target.pixel_size.rgba.a;
00224         }
00225         else {
00226             score += 16
00227                + 16 / (1 + dinfo->pixel_size.rgba.a - target.pixel_size.rgba.a);
00228         }
00229     }
00230 
00231 
00232     if ((req & AGL_ACC_RED_DEPTH)
00233      && (dinfo->accum_size.rgba.r != target.accum_size.rgba.r)) {
00234 
00235         ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE,
00236                  get_config_text("Accumulator Red depth requirement not met."));
00237         return -1;
00238     }
00239 
00240     if (sug & AGL_ACC_RED_DEPTH) {
00241         if (dinfo->accum_size.rgba.r < target.accum_size.rgba.r) {
00242             score += (16 * dinfo->accum_size.rgba.r) / target.accum_size.rgba.r;
00243         }
00244         else {
00245             score += 16
00246                + 16 / (1 + dinfo->accum_size.rgba.r - target.accum_size.rgba.r);
00247         }
00248     }
00249 
00250     if ((req & AGL_ACC_GREEN_DEPTH)
00251      && (dinfo->accum_size.rgba.g != target.accum_size.rgba.g)) {
00252 
00253         ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE,
00254                get_config_text("Accumulator Green depth requirement not met."));
00255         return -1;
00256     }
00257 
00258     if (sug & AGL_ACC_GREEN_DEPTH) {
00259         if (dinfo->accum_size.rgba.g < target.accum_size.rgba.g) {
00260             score += (16 * dinfo->accum_size.rgba.g) / target.accum_size.rgba.g;
00261         }
00262         else {
00263             score += 16
00264                + 16 / (1 + dinfo->accum_size.rgba.g - target.accum_size.rgba.g);
00265         }
00266     }
00267 
00268     if ((req & AGL_ACC_BLUE_DEPTH)
00269      && (dinfo->accum_size.rgba.b != target.accum_size.rgba.b)) {
00270 
00271         ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE,
00272                 get_config_text("Accumulator Blue depth requirement not met."));
00273         return -1;
00274     }
00275 
00276     if (sug & AGL_ACC_BLUE_DEPTH) {
00277         if (dinfo->accum_size.rgba.b < target.accum_size.rgba.b) {
00278             score += (16 * dinfo->accum_size.rgba.b) / target.accum_size.rgba.b;
00279         }
00280         else {
00281             score += 16
00282                + 16 / (1 + dinfo->accum_size.rgba.b - target.accum_size.rgba.b);
00283         }
00284     }
00285 
00286     if ((req & AGL_ACC_ALPHA_DEPTH)
00287      && (dinfo->accum_size.rgba.a != target.accum_size.rgba.a)) {
00288 
00289         ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE,
00290                get_config_text("Accumulator Alpha depth requirement not met."));
00291         return -1;
00292     }
00293 
00294     if (sug & AGL_ACC_ALPHA_DEPTH) {
00295         if (dinfo->accum_size.rgba.a < target.accum_size.rgba.a) {
00296             score += (16 * dinfo->accum_size.rgba.a) / target.accum_size.rgba.a;
00297         }
00298         else {
00299             score += 16
00300                + 16 / (1 + dinfo->accum_size.rgba.a - target.accum_size.rgba.a);
00301         }
00302     }
00303 
00304 
00305 
00306     if (!dinfo->doublebuffered != !target.doublebuffered) {
00307         if (req & AGL_DOUBLEBUFFER) {
00308             ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE,
00309                          get_config_text("Double Buffer requirement not met."));
00310             return -1;
00311         }
00312     }
00313     else {
00314         score += (sug & AGL_DOUBLEBUFFER) ? 256 : 1;
00315     }
00316 
00317     if (!dinfo->stereo != !target.stereo) {
00318         if (req & AGL_STEREO) {
00319             ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE,
00320                          get_config_text("Stereo Buffer requirement not met."));
00321             return -1;
00322         }
00323     }
00324     else {
00325         if (sug & AGL_STEREO) {
00326             score += 128;
00327         }
00328     }
00329 
00330     if ((req & AGL_AUX_BUFFERS) && (dinfo->aux_buffers < target.aux_buffers)) {
00331         ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE,
00332                   get_config_text("Aux Buffer requirement not met."));
00333         return -1;
00334     }
00335     
00336     if (sug & AGL_AUX_BUFFERS) {
00337         if (dinfo->aux_buffers < target.aux_buffers) {
00338             score += (64 * dinfo->aux_buffers) / target.aux_buffers;
00339         }
00340         else {
00341             score += 64 + 64 / (1 + dinfo->aux_buffers - target.aux_buffers);
00342         }
00343     }
00344 
00345     if ((req & AGL_Z_DEPTH) && (dinfo->depth_size != target.depth_size)) {
00346         ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE,
00347                   get_config_text("Z-Buffer requirement not met."));
00348         return -1;
00349     }
00350     if (sug & AGL_Z_DEPTH) {
00351         if (dinfo->depth_size < target.depth_size) {
00352             score += (64 * dinfo->depth_size) / target.depth_size;
00353         }
00354         else {
00355             score += 64 + 64 / (1 + dinfo->depth_size - target.depth_size);
00356         }
00357     }
00358 
00359     if ((req & AGL_STENCIL_DEPTH)
00360      && (dinfo->stencil_size != target.stencil_size)) {
00361 
00362         ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE,
00363                   get_config_text("Stencil depth requirement not met."));
00364         return -1;
00365     }
00366         
00367     if (sug & AGL_STENCIL_DEPTH) {
00368         if (dinfo->stencil_size < target.stencil_size) {
00369             score += (64 * dinfo->stencil_size) / target.stencil_size;
00370         }
00371         else {
00372             score += 64 + 64 / (1 + dinfo->stencil_size - target.stencil_size);
00373         }
00374     }
00375 
00376     if ((req & AGL_RENDERMETHOD)
00377       && ((dinfo->rmethod != target.rmethod) || (target.rmethod == 2))) {
00378 
00379         ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE,
00380                   get_config_text("Render Method requirement not met"));
00381         return -1;
00382     }
00383 
00384     if ((sug & AGL_RENDERMETHOD) && (dinfo->rmethod == target.rmethod)) {
00385         score += 1024;
00386     }
00387     else if (dinfo->rmethod == 1) {
00388         score++; /* Add 1 for h/w accel */
00389     }
00390 
00391     if ((req & AGL_SAMPLE_BUFFERS)
00392      && (dinfo->sample_buffers != target.sample_buffers)) {
00393             ustrzcpy(allegro_gl_error, AGL_ERROR_SIZE,
00394                     get_config_text("Multisample Buffers requirement not met"));
00395             return -1;
00396     }
00397         
00398     if (sug & AGL_SAMPLE_BUFFERS) {
00399         if (dinfo->sample_buffers < target.sample_buffers) {
00400             score += (64 * dinfo->sample_buffers) / target.sample_buffers;
00401         }
00402         else {
00403             score += 64
00404                    + 64 / (1 + dinfo->sample_buffers - target.sample_buffers);
00405         }
00406     }
00407 
00408     if ((req & AGL_SAMPLES) && (dinfo->samples != target.samples)) {
00409         ustrzcpy(allegro_gl_error, AGL_ERROR_SIZE,
00410                 get_config_text("Multisample Samples requirement not met"));
00411         return -1;
00412     }
00413         
00414     if (sug & AGL_SAMPLES) {
00415         if (dinfo->samples < target.samples) {
00416             score += (64 * dinfo->samples) / target.samples;
00417         }
00418         else {
00419             score += 64 + 64 / (1 + dinfo->samples - target.samples);
00420         }
00421     }
00422 
00423 
00424     if (!dinfo->float_color != !target.float_color) {
00425         if (req & AGL_FLOAT_COLOR) {
00426             ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE,
00427                       get_config_text("Float Color requirement not met."));
00428             return -1;
00429         }
00430     }
00431     else {
00432         if (sug & AGL_FLOAT_COLOR) {
00433             score += 128;
00434         }
00435     }
00436 
00437     if (!dinfo->float_depth != !target.float_depth) {
00438         if (req & AGL_FLOAT_Z) {
00439             ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE,
00440                       get_config_text("Float Depth requirement not met."));
00441             return -1;
00442         }
00443     }
00444     else {
00445         if (sug & AGL_FLOAT_Z) {
00446             score += 128;
00447         }
00448     }
00449     
00450     TRACE(PREFIX_I "Score is : %i\n", score);
00451     return score;
00452 }
00453 
00454 #undef target
00455 #undef req
00456 #undef sug
00457 
00458 
00459 
00460 int __allegro_gl_score_config(int refnum,
00461                               struct allegro_gl_display_info *dinfo)
00462 {
00463     int score = get_score(dinfo);
00464     if (score == -1) {
00465         TRACE(PREFIX_I "score_config: %s\n", allegro_gl_error);
00466         return score;
00467     }
00468     
00469     if (score == best_score) {
00470         /*
00471         TRACE(PREFIX_I "score_config: score == best_score, should we change "
00472               "scoring algorithm?\n");
00473         */
00474     }
00475 
00476     if (score > best_score) {
00477         best_score = score;
00478         best = refnum;
00479     }
00480 
00481     return score;
00482 }
00483 
00484 
00485 
00486 int __allegro_gl_best_config(void)
00487 {
00488     return best;
00489 }
00490 
allegro4.4-4.4.2/addons/allegrogl/docs/html/tab_a.png000066400000000000000000000002141173507505700222730ustar00rootroot00000000000000‰PNG  IHDR$ÇÇ[SIDATxí» €@wçÉ¡œˆ˜*æ‚M˜ØIïÎF†ýL :®‡±nÌëN™ ¶±Á’„ØN&â¼_ ɭɾ}Õ¶8~î¾îOwv-ÿêA4Y)Ñ}IEND®B`‚allegro4.4-4.4.2/addons/allegrogl/docs/html/tab_b.png000066400000000000000000000002621173507505700222770ustar00rootroot00000000000000‰PNG  IHDR$ÇÇ[yIDATxíÝÛ Â €Ñ?|SVÓˆ´bB#P®½8³‰O¾:É™D>ßm{SûIí'¹äz(!•TBÞ‰y#¤WìJDp¾ã|Ã…†ó »ìR˜]áá æ™Ð6q·‰›]ç•qŠŒÓÊÕD.&0èÀ =ƒJD”ˆü=@*é*ç×IEND®B`‚allegro4.4-4.4.2/addons/allegrogl/docs/html/tab_h.png000066400000000000000000000003001173507505700222760ustar00rootroot00000000000000‰PNG  IHDR$ÇÇ[‡IDATxíÝÛ ‚`€áÿ¥ºˆFŠ¢‚hšYÒ ÿÌ26@c´HwÍñì!ïÏ—K1ê^‰©HtO’÷ÄyG˜µD׎ k9¦ç?iðâ7zá„vPaŸž˜þãÏðJŒ}ÉÆ)غwV»‚õ®`ai–Ö¥¥™›Z‰ˆšŒP³éøC"àèP=€IEND®B`‚allegro4.4-4.4.2/addons/allegrogl/docs/html/tab_s.png000066400000000000000000000002751173507505700223240ustar00rootroot00000000000000‰PNG  IHDR$ÇÇ[„IDATxíÝë ‚P@áKg"%(IE|¡%¦I¡7iÚlmÐ" ÓäÛC¼ÞòÛ“\.dåOZ̤ÅBr‰/¿‰(ŸˆÎ#a6⟂ôŽ› 8q÷ØÇëÐaF-û°Et¿Aó4¯fçÖlŠ]±¶äJjJC¢%Š!¿<Å#üÀÄ«IEND®B`‚allegro4.4-4.4.2/addons/allegrogl/docs/html/tabs.css000066400000000000000000000021071173507505700221650ustar00rootroot00000000000000.tabs, .tabs2, .tabs3 { background-image: url('tab_b.png'); width: 100%; z-index: 101; font-size: 13px; } .tabs2 { font-size: 10px; } .tabs3 { font-size: 9px; } .tablist { margin: 0; padding: 0; display: table; } .tablist li { float: left; display: table-cell; background-image: url('tab_b.png'); line-height: 36px; list-style: none; } .tablist a { display: block; padding: 0 20px; font-weight: bold; background-image:url('tab_s.png'); background-repeat:no-repeat; background-position:right; color: #283A5D; text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9); text-decoration: none; outline: none; } .tabs3 .tablist a { padding: 0 10px; } .tablist a:hover { background-image: url('tab_h.png'); background-repeat:repeat-x; color: #fff; text-shadow: 0px 1px 1px rgba(0, 0, 0, 1.0); text-decoration: none; } .tablist li.current a { background-image: url('tab_a.png'); background-repeat:repeat-x; color: #fff; text-shadow: 0px 1px 1px rgba(0, 0, 0, 1.0); } allegro4.4-4.4.2/addons/allegrogl/docs/html/texture_8c.html000066400000000000000000000277561173507505700235230ustar00rootroot00000000000000 AllegroGL: texture.c File Reference

texture.c File Reference

AllegroGL texture management. More...

#include <string.h>
#include "alleggl.h"
#include "allglint.h"
#include <allegro/internal/aintern.h>
#include <GL/glu.h>

Go to the source code of this file.

Defines

  • #define PREFIX_I   "agl-tex INFO: "
  • #define PREFIX_W   "agl-tex WARNING: "
  • #define PREFIX_E   "agl-tex ERROR: "
  • #define F(s)   case s: return #s

Functions

  • char const * __allegro_gl_get_format_description (GLint format)
  • int __allegro_gl_get_num_channels (GLenum format)
  • GLint __allegro_gl_get_texture_format_ex (BITMAP *bmp, int flags)
  • GLenum __allegro_gl_get_bitmap_type (BITMAP *bmp, int flags)
  • GLenum __allegro_gl_get_bitmap_color_format (BITMAP *bmp, int flags)
  • static int __allegro_gl_convert_flags (int flags)
  • static int log2i (int n)
  • BITMAP * __allegro_gl_munge_bitmap (int flags, BITMAP *bmp, int x, int y, int w, int h, GLint *type, GLint *format)
  • static GLuint do_texture_upload (BITMAP *bmp, GLuint tex, GLint internal_format, GLint format, GLint type, int flags)
  • GLenum allegro_gl_get_bitmap_type (BITMAP *bmp)
  • GLenum allegro_gl_get_bitmap_color_format (BITMAP *bmp)
Texture routines
  • GLint allegro_gl_get_texture_format (BITMAP *bmp)
    Returns the OpenGL internal texture format for this bitmap.
  • GLint allegro_gl_set_texture_format (GLint format)
    Sets the color format you'd like OpenGL to use for its textures.
  • int allegro_gl_use_mipmapping (int enable)
    Tell AllegroGL to use Mipmapping or not when generating textures via its functions.
  • int allegro_gl_use_alpha_channel (int enable)
    Tell AllegroGL to use Alpha channel or not when generating textures via its functions.
  • int allegro_gl_flip_texture (int enable)
    Tell AllegroGL to flip the texture vertically or not when generating textures via its functions, to conform to the usual OpenGL texture coordinate system (increasing upwards).
  • int allegro_gl_check_texture_ex (int flags, BITMAP *bmp, GLint internal_format)
    Checks whether the specified bitmap is of the proper size for texturing.
  • int allegro_gl_check_texture (BITMAP *bmp)
    Checks whether the specified bitmap is of the proper size for texturing.
  • GLuint allegro_gl_make_texture_ex (int flags, BITMAP *bmp, GLint internal_format)
    Uploads an Allegro BITMAP to the GL driver as a texture.
  • GLuint allegro_gl_make_texture (BITMAP *bmp)
    Uploads an Allegro BITMAP to the GL driver as a texture.
  • GLuint allegro_gl_make_masked_texture (BITMAP *bmp)
    Uploads an Allegro BITMAP to the GL driver as a texture.

Variables

  • static GLint allegro_gl_opengl_internal_texture_format = -1
  • static int allegro_gl_use_mipmapping_for_textures = 0
  • int __allegro_gl_use_alpha = FALSE
  • int __allegro_gl_flip_texture = TRUE
  • GLint __allegro_gl_texture_read_format [5]
  • GLint __allegro_gl_texture_components [5]

Detailed Description

AllegroGL texture management.

Definition in file texture.c.

allegro4.4-4.4.2/addons/allegrogl/docs/html/texture_8c_source.html000066400000000000000000002755071173507505700251020ustar00rootroot00000000000000 AllegroGL: texture.c Source File

texture.c

Go to the documentation of this file.
00001 /* This code is (C) AllegroGL contributors, and double licensed under
00002  * the GPL and zlib licenses. See gpl.txt or zlib.txt for details.
00003  */
00008 #include <string.h>
00009 
00010 #include "alleggl.h"
00011 #include "allglint.h"
00012 
00013 #include <allegro/internal/aintern.h>
00014 
00015 #ifdef ALLEGRO_MACOSX
00016 #include <OpenGL/glu.h>
00017 #else
00018 #include <GL/glu.h>
00019 #endif
00020 
00021 static GLint allegro_gl_opengl_internal_texture_format = -1;
00022 static int allegro_gl_use_mipmapping_for_textures = 0;
00023 int __allegro_gl_use_alpha = FALSE;
00024 int __allegro_gl_flip_texture = TRUE;
00025 GLint __allegro_gl_texture_read_format[5];
00026 GLint __allegro_gl_texture_components[5];
00027 
00028 #define PREFIX_I                "agl-tex INFO: "
00029 #define PREFIX_W                "agl-tex WARNING: "
00030 #define PREFIX_E                "agl-tex ERROR: "
00031 
00032 
00038 char const *__allegro_gl_get_format_description(GLint format)
00039 {
00040     static char str[256];
00041 #define F(s) case s: return #s
00042     switch (format) {
00043         F(GL_ALPHA);
00044         F(GL_ALPHA4);
00045         F(GL_ALPHA8);
00046         F(GL_ALPHA12);
00047         F(GL_ALPHA16);
00048         F(GL_ALPHA16F_ARB);
00049         F(GL_ALPHA32F_ARB);
00050         F(GL_INTENSITY);
00051         F(GL_INTENSITY4);
00052         F(GL_INTENSITY8);
00053         F(GL_INTENSITY12);
00054         F(GL_INTENSITY16);
00055         F(GL_INTENSITY16F_ARB);
00056         F(GL_INTENSITY32F_ARB);
00057         F(GL_LUMINANCE);
00058         F(GL_LUMINANCE4);
00059         F(GL_LUMINANCE8);
00060         F(GL_LUMINANCE12);
00061         F(GL_LUMINANCE16);
00062         F(GL_LUMINANCE16F_ARB);
00063         F(GL_LUMINANCE32F_ARB);
00064         F(GL_LUMINANCE_ALPHA);
00065         F(GL_LUMINANCE4_ALPHA4);
00066         F(GL_LUMINANCE12_ALPHA4);
00067         F(GL_LUMINANCE8_ALPHA8);
00068         F(GL_LUMINANCE6_ALPHA2);
00069         F(GL_LUMINANCE12_ALPHA12);
00070         F(GL_LUMINANCE16_ALPHA16);
00071         F(GL_LUMINANCE_ALPHA16F_ARB);
00072         F(GL_LUMINANCE_ALPHA32F_ARB);
00073         F(GL_RGB);
00074         F(GL_R3_G3_B2);
00075         F(GL_RGB4);
00076         F(GL_RGB5);
00077         F(GL_RGB8);
00078         F(GL_RGB10);
00079         F(GL_RGB12);
00080         F(GL_RGB16);
00081         F(GL_RGB16F_ARB);
00082         F(GL_RGB32F_ARB);
00083         F(GL_RGBA);
00084         F(GL_RGBA2);
00085         F(GL_RGBA4);
00086         F(GL_RGB5_A1);
00087         F(GL_RGBA8);
00088         F(GL_RGB10_A2);
00089         F(GL_RGBA12);
00090         F(GL_RGBA16);
00091         F(GL_RGBA16F_ARB);
00092         F(GL_RGBA32F_ARB);
00093     }
00094     uszprintf(str, sizeof str, "%x", format);
00095     return str;
00096 #undef F
00097 }
00098 
00099 
00100 
00101 /* int __allegro_gl_get_num_channels(GLenum format) */
00111 int __allegro_gl_get_num_channels(GLenum format) {
00112         
00113     switch (format) {
00114     case 1:
00115     case GL_ALPHA:
00116     case GL_ALPHA4:
00117     case GL_ALPHA8:
00118     case GL_ALPHA12:
00119     case GL_ALPHA16:
00120     case GL_ALPHA16F_ARB:
00121     case GL_ALPHA32F_ARB:
00122     case GL_INTENSITY:
00123     case GL_INTENSITY4:
00124     case GL_INTENSITY8:
00125     case GL_INTENSITY12:
00126     case GL_INTENSITY16:
00127     case GL_INTENSITY16F_ARB:
00128     case GL_INTENSITY32F_ARB:
00129     case GL_LUMINANCE:
00130     case GL_LUMINANCE4:
00131     case GL_LUMINANCE8:
00132     case GL_LUMINANCE12:
00133     case GL_LUMINANCE16:
00134     case GL_LUMINANCE16F_ARB:
00135     case GL_LUMINANCE32F_ARB:
00136         return 1;
00137     case 2:
00138     case GL_LUMINANCE_ALPHA:
00139     case GL_LUMINANCE4_ALPHA4:
00140     case GL_LUMINANCE12_ALPHA4:
00141     case GL_LUMINANCE8_ALPHA8:
00142     case GL_LUMINANCE6_ALPHA2:
00143     case GL_LUMINANCE12_ALPHA12:
00144     case GL_LUMINANCE16_ALPHA16:
00145     case GL_LUMINANCE_ALPHA16F_ARB:
00146     case GL_LUMINANCE_ALPHA32F_ARB:
00147         return 2;
00148     case 3:
00149     case GL_RGB:
00150     case GL_R3_G3_B2:
00151     case GL_RGB4:
00152     case GL_RGB5:
00153     case GL_RGB8:
00154     case GL_RGB10:
00155     case GL_RGB12:
00156     case GL_RGB16:
00157     case GL_RGB16F_ARB:
00158     case GL_RGB32F_ARB:
00159         return 3;
00160     case 4:
00161     case GL_RGBA:
00162     case GL_RGBA2:
00163     case GL_RGBA4:
00164     case GL_RGB5_A1:
00165     case GL_RGBA8:
00166     case GL_RGB10_A2:
00167     case GL_RGBA12:
00168     case GL_RGBA16:
00169     case GL_RGBA16F_ARB:
00170     case GL_RGBA32F_ARB:
00171         return 4;
00172     default:
00173         return 0;
00174     }
00175 }
00176 
00177 
00178 
00179 /* GLint __allegro_gl_get_texture_format_ex(BITMAP *bmp, int flags) */
00190 GLint __allegro_gl_get_texture_format_ex(BITMAP *bmp, int flags) {
00191 
00192     if (!bmp) {
00193         return -1;
00194     }
00195 
00196     switch (bitmap_color_depth(bmp)) {
00197         case 32:
00198             if (flags
00199                  & (AGL_TEXTURE_HAS_ALPHA | AGL_TEXTURE_FORCE_ALPHA_INTERNAL)) {
00200                 return GL_RGBA8;
00201             }
00202             else {
00203                 return GL_RGB8;
00204             }
00205         case 8:
00206             return GL_INTENSITY8;
00207         case 15:
00208             if (flags & AGL_TEXTURE_FORCE_ALPHA_INTERNAL) {
00209                 return GL_RGB5_A1;
00210             }
00211             else {
00212                 return GL_RGB5;
00213             }
00214         case 16:
00215         case 24:
00216             if (flags & AGL_TEXTURE_FORCE_ALPHA_INTERNAL) {
00217                 return GL_RGBA8;
00218             }
00219             else {
00220                 return GL_RGB8;
00221             }
00222         default:
00223             return -1;
00224     }
00225 
00226     return -1;
00227 }
00228 
00229 
00230 
00231 /* GLint allegro_gl_get_texture_format(BITMAP *bmp) */
00248 GLint allegro_gl_get_texture_format(BITMAP *bmp) {
00249 
00250     if (bmp && allegro_gl_opengl_internal_texture_format == -1) {
00251         return __allegro_gl_get_texture_format_ex(bmp,
00252                 __allegro_gl_use_alpha ? AGL_TEXTURE_FORCE_ALPHA_INTERNAL : 0);
00253     }
00254     
00255     return allegro_gl_opengl_internal_texture_format;
00256 }
00257 
00258 
00259 
00260 /* GLint allegro_gl_set_texture_format(GLint format) */
00282 GLint allegro_gl_set_texture_format(GLint format) {
00283 
00284     GLint old = allegro_gl_opengl_internal_texture_format;
00285     allegro_gl_opengl_internal_texture_format = format;
00286     return old;
00287 }
00288 
00289 
00290 
00291 /* GLenum __allegro_gl_get_bitmap_type(BITMAP *bmp, int flags) */
00311 GLenum __allegro_gl_get_bitmap_type(BITMAP *bmp, int flags) {
00312 
00313     int c = bitmap_color_depth(bmp);
00314 
00315     switch (c) {
00316 
00317         case 8:
00318             return __allegro_gl_texture_read_format[0];
00319 
00320         case 15:
00321             return __allegro_gl_texture_read_format[1];
00322 
00323         case 16:
00324             return __allegro_gl_texture_read_format[2];
00325 
00326         case 24:
00327             return __allegro_gl_texture_read_format[3];
00328 
00329         case 32:
00330             return __allegro_gl_texture_read_format[4];
00331     
00332         default:
00333             TRACE(PREFIX_E "get_bitmap_type: unhandled bitmap depth: %d\n",
00334                   c);
00335             return -1;
00336     }
00337 }
00338 
00339 
00340 
00341 /* GLenum __allegro_gl_get_bitmap_color_format(BITMAP *bmp, int flags) */
00355 GLenum __allegro_gl_get_bitmap_color_format(BITMAP *bmp, int flags) {
00356 
00357     int c = bitmap_color_depth(bmp);
00358 
00359     switch (c) {
00360 
00361         case 8:
00362             if (flags & AGL_TEXTURE_ALPHA_ONLY) {
00363                 return GL_ALPHA;
00364             }
00365             else {
00366                 return __allegro_gl_texture_components[0];
00367             }
00368 
00369         case 15:
00370             if (flags & AGL_TEXTURE_FORCE_ALPHA_INTERNAL) {
00371                 return GL_RGBA;
00372             }
00373             else {
00374                 return __allegro_gl_texture_components[1];
00375             }
00376 
00377         case 16:
00378             return __allegro_gl_texture_components[2];
00379 
00380         case 24:
00381             return __allegro_gl_texture_components[3];
00382 
00383         case 32:
00384             if (flags & (AGL_TEXTURE_HAS_ALPHA
00385                        | AGL_TEXTURE_FORCE_ALPHA_INTERNAL)) {
00386                 return GL_RGBA;
00387             }
00388             else {
00389                 return __allegro_gl_texture_components[4];
00390             }
00391     
00392         default:
00393             TRACE(PREFIX_E "get_bitmap_color_format: unhandled bitmap "
00394                   "depth: %d\n", c);
00395             return -1;
00396     }
00397 }
00398 
00399 
00400 
00401 /* int allegro_gl_use_mipmapping(int enable) */
00415 int allegro_gl_use_mipmapping(int enable) {
00416 
00417     int old = allegro_gl_use_mipmapping_for_textures;
00418     allegro_gl_use_mipmapping_for_textures = enable;
00419     return old;
00420 }
00421     
00422 
00423 
00424 /* int allegro_gl_use_alpha_channel(int enable) */
00439 int allegro_gl_use_alpha_channel(int enable) {
00440 
00441     int old = __allegro_gl_use_alpha;
00442     __allegro_gl_use_alpha = enable;
00443     return old;
00444 }
00445     
00446 
00447 
00448 /* int allegro_gl_flip_texture(int enable) */
00464 int allegro_gl_flip_texture(int enable) {
00465 
00466     int old = __allegro_gl_flip_texture;
00467     __allegro_gl_flip_texture = enable;
00468     return old;
00469 }
00470     
00471 
00472 
00473 /* int allegro_gl_check_texture_ex(int flags, BITMAP *bmp, GLuint internal_format) */
00495 int allegro_gl_check_texture_ex(int flags, BITMAP *bmp,
00496                                    GLint internal_format) {
00497 
00498     return (allegro_gl_make_texture_ex(flags | AGL_TEXTURE_CHECK_VALID_INTERNAL,
00499                                        bmp, internal_format) ? TRUE : FALSE);
00500 }
00501 
00502 
00503 
00504 /* Convert flags from pre-0.2.0 to 0.2.0+ */
00505 static int __allegro_gl_convert_flags(int flags) {
00506 
00507     flags |= AGL_TEXTURE_RESCALE;
00508 
00509     if (allegro_gl_use_mipmapping_for_textures) {
00510         flags |= AGL_TEXTURE_MIPMAP;
00511     }
00512     if (__allegro_gl_use_alpha) {
00513         flags |= AGL_TEXTURE_HAS_ALPHA;
00514     }
00515     if (__allegro_gl_flip_texture) {
00516         flags |= AGL_TEXTURE_FLIP;
00517     }
00518 
00519     if (allegro_gl_opengl_internal_texture_format == GL_ALPHA4
00520      || allegro_gl_opengl_internal_texture_format == GL_ALPHA8
00521      || allegro_gl_opengl_internal_texture_format == GL_ALPHA12
00522      || allegro_gl_opengl_internal_texture_format == GL_ALPHA16
00523      || allegro_gl_opengl_internal_texture_format == GL_ALPHA
00524      || allegro_gl_opengl_internal_texture_format == GL_INTENSITY4
00525      || allegro_gl_opengl_internal_texture_format == GL_INTENSITY8
00526      || allegro_gl_opengl_internal_texture_format == GL_INTENSITY12
00527      || allegro_gl_opengl_internal_texture_format == GL_INTENSITY16
00528      || allegro_gl_opengl_internal_texture_format == GL_INTENSITY
00529      || allegro_gl_opengl_internal_texture_format == 1) {
00530         flags |= AGL_TEXTURE_ALPHA_ONLY;
00531     }
00532 
00533     return flags;
00534 }
00535 
00536 
00537 
00538 /* int allegro_gl_check_texture(BITMAP *bmp) */
00557 int allegro_gl_check_texture(BITMAP *bmp) {
00558 
00559     int flags = __allegro_gl_convert_flags(0);
00560     
00561     return allegro_gl_check_texture_ex(flags, bmp,
00562                                      allegro_gl_opengl_internal_texture_format);
00563 }
00564 
00565 
00566 
00567 /* Integer log2 function. Not optimized for speed. */
00568 static int log2i(int n) {
00569     
00570     int k;
00571     
00572     if (n < 1) {
00573         return -1;
00574     }
00575 
00576     k = 0;
00577     while (n >>= 1) {
00578         k++;
00579     }
00580 
00581     return k;
00582 }
00583 
00584 
00585 
00586 /* BITMAP *__allegro_gl_munge_bitmap(int flags, BITMAP *bmp, GLint *type, GLint *format) */
00596 BITMAP *__allegro_gl_munge_bitmap(int flags, BITMAP *bmp, int x, int y,
00597                                   int w, int h, GLint *type, GLint *format) {
00598     
00599     BITMAP *ret = 0, *temp = 0;
00600 
00601     int need_rescale = 0;
00602     int need_alpha   = 0;
00603     int need_flip    = 0;
00604     int depth = bitmap_color_depth(bmp);
00605     int force_copy   = 0;
00606 
00607     const int old_w = w, old_h = h;
00608 
00609     if (flags & AGL_TEXTURE_RESCALE) {
00610         
00611         /* Check if rescaling is needed */
00612 
00613         /* NP2 is not supported, and the texture isn't a power-of-two.
00614          * Resize the next power of 2
00615          */     
00616         if (!allegro_gl_extensions_GL.ARB_texture_non_power_of_two
00617          && ((w & (w - 1)) || (h & (h - 1)))) {
00618             w = __allegro_gl_make_power_of_2(w);
00619             h = __allegro_gl_make_power_of_2(h);
00620             TRACE(PREFIX_I "munge_bitmap: Rescaling bitmap from "
00621                   "%ix%i to %ix%i due to non-power-of-2 source size.\n",
00622                   old_w, old_h, w, h);
00623             need_rescale = 1;
00624         }
00625 
00626         /* Don't go over the max texture size */
00627         if (w > allegro_gl_info.max_texture_size) {
00628             w = allegro_gl_info.max_texture_size;
00629             TRACE(PREFIX_I "munge_bitmap: Rescaling bitmap from "
00630                   "%ix%i to %ix%i due to max supported size exceed.\n",
00631                   old_w, old_h, w, h);
00632             need_rescale = 1;
00633         }
00634         
00635         if (h > allegro_gl_info.max_texture_size) {
00636             h = allegro_gl_info.max_texture_size;
00637             TRACE(PREFIX_I "munge_bitmap: Rescaling bitmap from "
00638                   "%ix%i to %ix%i due to max supported size exceed.\n",
00639                   old_w, old_h, w, h);
00640             need_rescale = 1;
00641         }
00642 
00643         /* Voodoos don't support mipmaps for textures greater than 32x32.
00644          * If we're allowed to rescale, rescale the bitmap to 32x32.
00645          * XXX <rohannessian> Apparently, this is a bug in one version
00646          * of the Voodoo GL driver. Need to figure out a workaround
00647          * for that.
00648          */
00649         if (allegro_gl_info.is_voodoo && (flags & AGL_TEXTURE_MIPMAP)
00650           && (w > 32 || h > 32)) {
00651 
00652             w = MIN(32, w);
00653             h = MIN(32, h);
00654             
00655             TRACE(PREFIX_I "munge_bitmap: Rescaling bitmap from "
00656                   "%ix%i to %ix%i due to Voodoo driver bug.\n",
00657                   old_w, old_h, w, h);
00658             need_rescale = 1;
00659         }
00660     }
00661 
00662     /* Matrox G200 cards have a bug where rectangular textures can't have
00663      * more than 4 levels of mipmaps (max_mip == 3). This doesn't seem
00664      * to affect square textures.
00665      *
00666      * Note: Using GLU to build the mipmaps seems to work. Maybe AGL is
00667      * doing something wrong?
00668      *
00669      * Workaround: Use GLU to build the mipmaps, and force depth to 24 or
00670      * 32.
00671      */
00672     if ( allegro_gl_info.is_matrox_g200 && (flags & AGL_TEXTURE_MIPMAP)) {
00673         int wl = log2i(w);
00674         int hl = log2i(h);
00675 
00676         if (w != h && MAX(wl, hl) > 3 && depth < 24
00677          && !(flags & AGL_TEXTURE_ALPHA_ONLY)) {
00678             TRACE(PREFIX_I "munge_bitmap: G200 path in use.\n");
00679             depth = 24;
00680         }
00681     }
00682     
00683     /* Do we need to flip the texture on the t axis? */
00684     if (flags & AGL_TEXTURE_FLIP) {
00685         need_flip = 1;
00686     }
00687 
00688 
00689     /* If not supported, blit to a 24 bpp bitmap and try again
00690      */
00691     if (*type == -1) {
00692         TRACE(PREFIX_W "munge_bitmap: using temporary 24bpp bitmap\n");
00693         depth = 24;
00694     }
00695 
00696     /* We need a texture that can be used for masked blits.
00697      * Insert an alpha channel if one is not there.
00698      * If it's already there, replace it by 0/1 as needed.
00699      */
00700     if ((flags & AGL_TEXTURE_MASKED) && !(flags & AGL_TEXTURE_ALPHA_ONLY)) {
00701         need_alpha = 1;
00702 
00703         switch (depth) {
00704         case 15:
00705             if (!allegro_gl_extensions_GL.EXT_packed_pixels) {
00706                 depth = 32;
00707             }
00708             break;
00709         case 8:
00710         case 16:
00711         case 24:
00712         case 32:
00713             depth = 32;
00714             break;
00715         }
00716         force_copy = 1;
00717     }
00718 
00719     /* Allegro fills in 0 for the alpha channel. Matrox G200 seems to ignore
00720      * the internal format; so we need to drop down to 24-bpp if no alpha
00721      * will be needed.
00722      */
00723     if (allegro_gl_info.is_matrox_g200 && !(flags & AGL_TEXTURE_MASKED)
00724        && !(flags & AGL_TEXTURE_HAS_ALPHA) && depth == 32) {
00725         TRACE(PREFIX_I "munge_bitmap: G200 path in use.\n");
00726         depth = 24;
00727         force_copy = 1;
00728     }
00729 
00730     
00731     /* Do we need to do a color depth conversion or bitmap copy? */
00732     if (depth != bitmap_color_depth(bmp) || force_copy) {
00733 
00734         TRACE(PREFIX_I "munge_bitmap: Need to perform depth conversion from %i "
00735               "to %i bpp.\n", bitmap_color_depth(bmp), depth);
00736 
00737         temp = create_bitmap_ex(depth, bmp->w, bmp->h);
00738 
00739         if (!temp) {
00740             TRACE(PREFIX_E "munge_bitmap: Unable to create temporary bitmap "
00741                   "%ix%ix%i\n", bmp->w, bmp->h, depth);
00742             return NULL;
00743         }
00744 
00745         /* XXX <rohannessian> Use palette conversion?
00746          */
00747         if (bitmap_color_depth(bmp) == 8 && depth > 8) {
00748             int i, j;
00749             for (j = 0; j < bmp->h; j++) {
00750                 for (i = 0; i < bmp->w; i++) {
00751                     int c = _getpixel(bmp, i, j);
00752                     putpixel(temp, i, j, makecol_depth(depth, c, c, c));
00753                 }
00754             }
00755         }
00756         else {
00757             blit(bmp, temp, 0, 0, 0, 0, bmp->w, bmp->h);
00758         }
00759         bmp = temp;
00760 
00761         *format = __allegro_gl_get_bitmap_color_format(bmp, flags);
00762         *type = __allegro_gl_get_bitmap_type(bmp, flags);
00763     }
00764 
00765 
00766 
00767     /* Nothing to do? */
00768     if (!need_rescale && !need_alpha && !need_flip) {
00769 
00770         TRACE(PREFIX_I "munge_bitmap: No need for munging - returning %p\n",
00771               temp);
00772         
00773         /* Return depth-converte bitmap, if present */
00774         if (temp) {
00775             return temp;
00776         }
00777         return NULL;
00778     }
00779 
00780     ret = create_bitmap_ex(depth, w, h);
00781     
00782     if (!ret) {
00783         TRACE(PREFIX_E "munge_bitmap: Unable to create result bitmap "
00784               "%ix%ix%i\n", w, h, depth);
00785         goto error;
00786     }
00787 
00788 
00789     /* No need to fill in bitmap if we're just making a query */
00790     if (flags & AGL_TEXTURE_CHECK_VALID_INTERNAL) {
00791         if (temp) {
00792             destroy_bitmap(temp);
00793         }
00794         return ret;
00795     }
00796 
00797 
00798     /* Perform flip
00799      * I don't want to have to deal with *yet another* temporary bitmap
00800      * so instead, I fugde the line pointers around.
00801      * This will work because we require Allegro memory bitmaps anyway.
00802      */
00803     if (need_flip) {
00804         int i;
00805         TRACE(PREFIX_I "munge_bitmap: Flipping bitmap.\n");
00806         for (i = 0; i < bmp->h/2; i++) {
00807             unsigned char *l = bmp->line[i];
00808             bmp->line[i] = bmp->line[bmp->h - i - 1];
00809             bmp->line[bmp->h - i - 1] = l;
00810         }
00811     }
00812     
00813     /* Rescale bitmap */
00814     if (need_rescale) {
00815         TRACE(PREFIX_I "munge_bitmap: Rescaling bitmap.\n");
00816         stretch_blit(bmp, ret, x, y, old_w, old_h, 0, 0, ret->w, ret->h);
00817     }
00818     else {
00819         TRACE(PREFIX_I "munge_bitmap: Copying bitmap.\n");
00820         blit(bmp, ret, x, y, 0, 0, w, h);
00821     }
00822 
00823     /* Restore the original bitmap, if needed */
00824     if (need_flip && !temp) {
00825         int i;
00826         TRACE(PREFIX_I "munge_bitmap: Unflipping bitmap.\n");
00827         for (i = 0; i < bmp->h/2; i++) {
00828             unsigned char *l = bmp->line[i];
00829             bmp->line[i] = bmp->line[bmp->h - i - 1];
00830             bmp->line[bmp->h - i - 1] = l;
00831         }
00832     }
00833     
00834     /* Insert alpha channel */
00835     if (need_alpha) {
00836         int i, j;
00837         int mask = bitmap_mask_color(ret);
00838 
00839         /* alpha mask for 5.5.5.1 pixels */
00840         int alpha = (-1) ^ makecol_depth(depth, 255, 255, 255);
00841 
00842         TRACE(PREFIX_I "munge_bitmap: Inserting alpha channel.\n");
00843 
00844         for (j = 0; j < h; j++) {
00845             for (i = 0; i < w; i++) {
00846                 int pix;
00847                 
00848                 switch (depth) {
00849                 case 32:
00850                     pix = _getpixel32(ret, i, j);
00851 
00852                     if (pix == mask) {
00853                         pix = 0;
00854                     }
00855                     else if ((flags & AGL_TEXTURE_HAS_ALPHA) == 0) {
00856                         int r, g, b;
00857                         r = getr32(pix);
00858                         g = getg32(pix);
00859                         b = getb32(pix);
00860                         pix = makeacol32(r, g, b, 255);
00861                     }
00862                     _putpixel32(ret, i, j, pix);
00863                     break;
00864                 case 15: 
00865                     pix = _getpixel16(ret, i, j);
00866 
00867                     if (pix == mask) {
00868                         pix = 0;
00869                     }
00870                     else {
00871                         pix |= alpha;
00872                     }
00873                     
00874                     _putpixel16(temp, i, j, pix);
00875                     break;
00876                 default:
00877                     /* Shouldn't actually come here */
00878                     ASSERT(0);
00879                 }
00880             }
00881         }
00882     }
00883 
00884 
00885 error:
00886     if (temp) {
00887         destroy_bitmap(temp);
00888     }
00889 
00890     return ret;
00891 }
00892 
00893 
00894 
00895 /* Perform the actual texture upload. Helper for agl_make_texture_ex().
00896  */
00897 static GLuint do_texture_upload(BITMAP *bmp, GLuint tex, GLint internal_format,
00898                               GLint format, GLint type, int flags) {
00899 
00900     int bytes_per_pixel = BYTES_PER_PIXEL(bitmap_color_depth(bmp));
00901     GLint saved_row_length;
00902     GLint saved_alignment;
00903     GLenum target = GL_TEXTURE_2D;
00904 
00905     glBindTexture(target, tex);
00906     
00907 
00908     /* Handle proxy texture checks */
00909     if (flags & AGL_TEXTURE_CHECK_VALID_INTERNAL) { 
00910         /* <bcoconni> allegro_gl_check_texture is broken with GL drivers based
00911          *  on Mesa. It seems this is a Mesa bug...
00912          */
00913         if (allegro_gl_info.is_mesa_driver) {
00914             AGL_LOG(1, "* Note * check_texture: Mesa driver detected: "
00915                    "PROXY_TEXTURE_2D tests are skipped\n");
00916             return tex;
00917         }
00918         else {
00919             glTexImage2D(GL_PROXY_TEXTURE_2D, 0, internal_format,
00920                          bmp->w, bmp->h, 0, format, type, NULL);
00921 
00922             glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D, 0,
00923                                      GL_TEXTURE_COMPONENTS, &internal_format);
00924 
00925             return (internal_format ? tex : 0);
00926         }
00927     }
00928     
00929 
00930     /* Set up pixel transfer mode */
00931     glGetIntegerv(GL_UNPACK_ROW_LENGTH, &saved_row_length);
00932     glGetIntegerv(GL_UNPACK_ALIGNMENT,  &saved_alignment);
00933     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
00934 
00935     TRACE(PREFIX_I "do_texture_upload: Making texture: bpp: %i\n",
00936           bitmap_color_depth(bmp));
00937 
00938     /* Generate mipmaps, if needed */
00939     if (flags & AGL_TEXTURE_MIPMAP) {
00940         
00941         if (allegro_gl_extensions_GL.SGIS_generate_mipmap) {
00942             /* Easy way out - let the driver do it ;) 
00943              * We do need to set high-qual mipmap generation though.
00944              */
00945             glHint(GL_GENERATE_MIPMAP_HINT, GL_NICEST);
00946             glTexParameteri(target, GL_GENERATE_MIPMAP, GL_TRUE);
00947             TRACE(PREFIX_I "do_texture_upload: Using SGIS_generate_mipmap for "
00948                   "mipmap generation.\n");
00949         }
00950         else if (allegro_gl_info.is_matrox_g200
00951              && (flags & AGL_TEXTURE_MIPMAP) && (bitmap_color_depth(bmp) >= 24
00952                 || bitmap_color_depth(bmp) == 8)
00953              && (bmp->w != bmp->h)) {
00954                 
00955             /* Matrox G200 has issues with our mipmapping code. Use GLU if we
00956              * can.
00957              */
00958             TRACE(PREFIX_I "do_texture_upload: Using GLU for mipmaps.\n");
00959             glPixelStorei(GL_UNPACK_ROW_LENGTH, bmp->h > 1
00960                         ? (bmp->line[1] - bmp->line[0]) / bytes_per_pixel
00961                         : bmp->w);
00962             glPixelStorei(GL_UNPACK_ROW_LENGTH,
00963                                (bmp->line[1] - bmp->line[0]) / bytes_per_pixel);
00964             gluBuild2DMipmaps(GL_TEXTURE_2D, internal_format, bmp->w, bmp->h,
00965                               format, type, bmp->line[0]);
00966         }
00967         else {
00968             int w = bmp->w;
00969             int h = bmp->h;
00970             int depth = bitmap_color_depth(bmp);
00971             
00972             /* The driver can't generate mipmaps for us. We can't rely on GLU
00973              * since the Win32 version doesn't support any of the new pixel
00974              * formats. Instead, we'll use our own downsampler (which only
00975              * has to work on Allegro BITMAPs)
00976              */
00977             BITMAP *temp = create_bitmap_ex(depth, w / 2, h / 2);
00978 
00979             /* We need to generate mipmaps up to 1x1 - compute the number
00980              * of levels we need.
00981              */
00982             int num_levels = log2i(MAX(bmp->w, bmp->h));
00983             
00984             int i, x, y;
00985 
00986             BITMAP *src, *dest;
00987 
00988             TRACE(PREFIX_I "do_texture_upload: Using Allegro for "
00989                   "mipmap generation.\n");
00990 
00991             if (!temp) {
00992                 TRACE(PREFIX_E "do_texture_upload: Unable to create "
00993                       "temporary bitmap sized %ix%ix%i for mipmap generation!",
00994                       w / 2, h / 2, depth);
00995                 tex = 0;
00996                 goto end;
00997             }
00998 
00999             src = bmp;
01000             dest = temp;
01001             
01002             for (i = 1; i <= num_levels; i++) {
01003 
01004                 for (y = 0; y < h; y += 2) {
01005                     for (x = 0; x < w; x += 2) {
01006 
01007                         int r, g, b, a;
01008                         int pix[4];
01009                         int avg;
01010                         
01011                         pix[0] = getpixel(src, x,     y);
01012                         pix[1] = getpixel(src, x + 1, y);
01013                         pix[2] = getpixel(src, x,     y + 1);
01014                         pix[3] = getpixel(src, x + 1, y + 1);
01015 
01016                         if (w == 1) {
01017                             pix[1] = pix[0];
01018                             pix[3] = pix[2];
01019                         }
01020                         if (h == 1) {
01021                             pix[2] = pix[0];
01022                             pix[3] = pix[1];
01023                         }
01024 
01025                         if (flags & AGL_TEXTURE_ALPHA_ONLY) {
01026                             avg = (pix[0] + pix[1] + pix[2] + pix[3] + 2) / 4;
01027                         }
01028                         else {
01029                             r = (getr_depth(depth, pix[0])
01030                                + getr_depth(depth, pix[1])
01031                                + getr_depth(depth, pix[2])
01032                                + getr_depth(depth, pix[3]) + 2) / 4;
01033                             g = (getg_depth(depth, pix[0])
01034                                + getg_depth(depth, pix[1])
01035                                + getg_depth(depth, pix[2])
01036                                + getg_depth(depth, pix[3]) + 2) / 4;
01037                             b = (getb_depth(depth, pix[0])
01038                                + getb_depth(depth, pix[1])
01039                                + getb_depth(depth, pix[2])
01040                                + getb_depth(depth, pix[3]) + 2) / 4;
01041                             a = (geta_depth(depth, pix[0])
01042                                + geta_depth(depth, pix[1])
01043                                + geta_depth(depth, pix[2])
01044                                + geta_depth(depth, pix[3]) + 2) / 4;
01045 
01046                             avg = makeacol_depth(depth, r, g, b, a);
01047                         }
01048 
01049                         putpixel(dest, x / 2, y / 2, avg);
01050                     }
01051                 }
01052                 src = temp;
01053 
01054                 /* Note - we round down; we're still compatible with
01055                  * ARB_texture_non_power_of_two.
01056                  */
01057                 w = MAX(w / 2, 1);
01058                 h = MAX(h / 2, 1);
01059 
01060                 TRACE(PREFIX_I "do_texture_upload: Unpack row length: %li.\n",
01061                       (temp->h > 1)
01062                      ? (long int)((temp->line[1] - temp->line[0]) / bytes_per_pixel)
01063                      : temp->w);
01064 
01065                 glPixelStorei(GL_UNPACK_ROW_LENGTH, temp->h > 1
01066                              ? (temp->line[1] - temp->line[0]) / bytes_per_pixel
01067                              : temp->w);    
01068 
01069                 glTexImage2D(GL_TEXTURE_2D, i, internal_format,
01070                              w, h, 0, format, type, temp->line[0]);
01071 
01072                 TRACE(PREFIX_I "do_texture_upload: Mipmap level: %i, "
01073                       "size: %i x %i\n", i, w, h);
01074 
01075                 TRACE(PREFIX_I "do_texture_upload: Uploaded texture: level %i, "
01076                       "internalformat: %s, %ix%i, format: 0x%x, type: 0x%x."
01077                       "\n", i, __allegro_gl_get_format_description(internal_format),
01078                       bmp->w, bmp->h, format, type);
01079             }
01080 
01081             destroy_bitmap(temp);
01082         }
01083     }
01084 
01085     glPixelStorei(GL_UNPACK_ROW_LENGTH, (bmp->h > 1)
01086                  ? (bmp->line[1] - bmp->line[0]) / bytes_per_pixel
01087                  : bmp->w);
01088     
01089     TRACE(PREFIX_I "do_texture_upload: Unpack row length: %li.\n",
01090       (bmp->h > 1) ? (long int)((bmp->line[1] - bmp->line[0]) / bytes_per_pixel)
01091                    : bmp->w);
01092 
01093     /* Upload the base texture */
01094     glGetError();
01095     glTexImage2D(GL_TEXTURE_2D, 0, internal_format,
01096                  bmp->w, bmp->h, 0, format, type, bmp->line[0]);
01097 
01098     TRACE(PREFIX_I "do_texture_upload: Uploaded texture: level 0, "
01099           "internalformat: %s, %ix%i, format: 0x%x, type: 0x%x.\n",
01100           __allegro_gl_get_format_description(internal_format),
01101           bmp->w, bmp->h, format, type);
01102     
01103     TRACE(PREFIX_I "do_texture_upload: GL Error code: 0x%x\n", glGetError());
01104 
01105     if (!(flags & AGL_TEXTURE_MIPMAP)) {
01106         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
01107     }
01108     
01109 end:
01110     /* Restore state */
01111     glPixelStorei(GL_UNPACK_ROW_LENGTH, saved_row_length);
01112     glPixelStorei(GL_UNPACK_ALIGNMENT,  saved_alignment);
01113 
01114     return tex;
01115 }   
01116 
01117 
01118 
01119 /* GLuint allegro_gl_make_texture_ex(int flag, BITMAP *bmp, GLint internal_format) */
01165 GLuint allegro_gl_make_texture_ex(int flags, BITMAP *bmp, GLint internal_format)
01166 {
01167     GLuint tex = 0, ret = 0;
01168     BITMAP *temp = NULL;
01169     GLint type;
01170     GLint format;
01171     GLint old_tex;
01172 
01173     /* Print the parameters */
01174 #ifdef DEBUGMODE
01175     char buf[1024] = "";
01176 #   define PFLAG(name) if (flags & name) strcat(buf, #name "|");
01177     PFLAG(AGL_TEXTURE_MIPMAP);
01178     PFLAG(AGL_TEXTURE_HAS_ALPHA);
01179     PFLAG(AGL_TEXTURE_FLIP);
01180     PFLAG(AGL_TEXTURE_MASKED);
01181     PFLAG(AGL_TEXTURE_RESCALE);
01182     PFLAG(AGL_TEXTURE_ALPHA_ONLY);
01183 #   undef PFLAG
01184 
01185     TRACE(PREFIX_I "make_texture_ex: flags: %s, bitmap %ix%i, %i bpp.\n", buf,
01186           bmp ? bmp->w : 0, bmp ? bmp->h : 0,
01187           bmp ? bitmap_color_depth(bmp) : 0);
01188     if (internal_format == -1) {
01189         TRACE(PREFIX_I "internalformat: AUTO\n");
01190     }
01191     else {
01192         TRACE(PREFIX_I "internalformat: %s\n",
01193             __allegro_gl_get_format_description(internal_format));
01194     }
01195 #endif  
01196 
01197     /* Basic parameter checks */
01198     if (!__allegro_gl_valid_context)
01199         return 0;
01200 
01201     if (!bmp) {
01202         return 0;
01203     }
01204 
01205     glGetIntegerv(GL_TEXTURE_2D_BINDING, &old_tex);
01206 
01207     /* Voodoo cards don't seem to support mipmaps for textures over 32x32...
01208      */
01209     if ((bmp->w > 32 || bmp->h > 32) && (allegro_gl_info.is_voodoo)) {
01210         /* Disable mipmapping if the user didn't allow us to rescale */
01211         if (!(flags & AGL_TEXTURE_RESCALE)) {
01212             TRACE(PREFIX_I "make_texture_ex: Voodoo card detected && texture "
01213                   "size > 32 texels && no rescaling. Disabling mipmaps.\n");
01214             flags &= ~AGL_TEXTURE_MIPMAP;
01215         }
01216     }
01217 
01218     /* Check the maximum texture size */
01219     if (bmp->w > allegro_gl_info.max_texture_size
01220      || bmp->h > allegro_gl_info.max_texture_size) {
01221         if ((flags & AGL_TEXTURE_RESCALE) == 0) {
01222             TRACE(PREFIX_I "make_texture_ex: Max texture size exceeded but no "
01223                   "rescaling allowed. Returning 0 (unsupported).\n");
01224             return 0;
01225         }
01226     }
01227 
01228     /* Check power-of-2 */
01229     if (((bmp->w & (bmp->w - 1)) || (bmp->h & (bmp->h - 1)))
01230       && !(flags & AGL_TEXTURE_RESCALE)
01231       && !allegro_gl_extensions_GL.ARB_texture_non_power_of_two) {
01232         TRACE(PREFIX_I "make_texture_ex: Non-power-of-2 sized bitmap provided, "
01233               "no rescaling allowed, and ARB_texture_non_power_of_two "
01234               "unsupported. Returning 0 (unsupported).\n");
01235         return 0;
01236     }
01237     
01238     
01239     /* Get OpenGL format and type for this pixel data */
01240     format = __allegro_gl_get_bitmap_color_format(bmp, flags);
01241     type = __allegro_gl_get_bitmap_type(bmp, flags);
01242     
01243     if (flags & AGL_TEXTURE_ALPHA_ONLY) {
01244         type   = GL_UNSIGNED_BYTE;
01245         if (internal_format == GL_ALPHA || internal_format == GL_ALPHA4
01246          || internal_format == GL_ALPHA8) {
01247             format = GL_ALPHA;
01248         }
01249         else if (internal_format == GL_INTENSITY
01250               || internal_format == GL_INTENSITY4
01251               || internal_format == GL_INTENSITY8) {
01252             format = GL_RED;
01253         }
01254         else if (internal_format == GL_LUMINANCE
01255               || internal_format == GL_LUMINANCE4
01256               || internal_format == GL_LUMINANCE8) {
01257             format = GL_LUMINANCE;
01258         }
01259 
01260         /* Alpha bitmaps must be 8-bpp */
01261         if (bitmap_color_depth(bmp) != 8) {
01262             return 0;
01263         }
01264     }
01265 
01266     if (flags & AGL_TEXTURE_MASKED) {
01267         flags |= AGL_TEXTURE_FORCE_ALPHA_INTERNAL;
01268     }
01269 
01270     TRACE(PREFIX_I "make_texture_ex: Preselected texture format: %s, "
01271           "type: 0x%x\n", __allegro_gl_get_format_description(format), type);
01272     
01273     /* Munge the bitmap if needed (rescaling, alpha channel, etc) */
01274     temp = __allegro_gl_munge_bitmap(flags, bmp, 0, 0, bmp->w, bmp->h,
01275                                      &type, &format);
01276     if (temp) {
01277         bmp = temp;
01278     }
01279     
01280     if (internal_format == -1) {
01281         internal_format = __allegro_gl_get_texture_format_ex(bmp, flags);
01282         TRACE(PREFIX_I "make_texture_ex: Picked internalformat: %s\n",
01283               __allegro_gl_get_format_description(internal_format));
01284     }
01285 
01286     if (internal_format == -1) {
01287         TRACE(PREFIX_E "make_texture_ex: Invalid internal format!: "
01288               "%s\n", __allegro_gl_get_format_description(internal_format));
01289         goto end;
01290     }
01291     
01292     TRACE(PREFIX_I "make_texture_ex: dest format=%s, source format=%s, "
01293           "type=0x%x\n", __allegro_gl_get_format_description(internal_format),
01294               __allegro_gl_get_format_description(format), (int)type);
01295 
01296     
01297     /* ATI Radeon 7000 inverts R and B components when generating mipmaps and
01298      * the internal format is GL_RGB8, but only on mipmaps. Instead, we'll use
01299      * GL_RGBA8. This works for bitmaps of depth <= 24. For 32-bpp bitmaps,
01300      * some additional tricks are needed: We must fill in alpha with 255.
01301      */
01302     if (allegro_gl_info.is_ati_radeon_7000 && (flags & AGL_TEXTURE_MIPMAP)
01303      && internal_format == GL_RGB8
01304      && allegro_gl_extensions_GL.SGIS_generate_mipmap) {
01305 
01306         int i, j;
01307         int depth = bitmap_color_depth(bmp);
01308 
01309         TRACE(PREFIX_I "make_texture_ex: ATI Radeon 7000 detected, mipmapping "
01310               "used, SGIS_generate_mipmap available and selected "
01311               "internalformat is GL_RGB8 but format is GL_RGBA. Working around "
01312               "ATI driver bug by upgrading bitmap to 32-bpp and using GL_RGBA8 "
01313               "instead.\n");
01314 
01315         if (depth == 32) {
01316 
01317             /* Create temp bitmap if not already there */
01318             if (!temp) {
01319                 temp = create_bitmap_ex(depth, bmp->w, bmp->h);
01320                 if (!temp) {
01321                     TRACE(PREFIX_E "make_texture_ex: Unable to allocate "
01322                           "memory for temporary bitmap (Radeon 7000 path)!\n");
01323                     goto end;
01324                 }
01325                 blit(bmp, temp, 0, 0, 0, 0, bmp->w, bmp->h);
01326                 bmp = temp;
01327             }
01328             
01329             /* Slow path, until ATI finally gets around to fixing their
01330              * drivers.
01331              *
01332              * Note: If destination internal format was GL_RGBx, then no masking
01333              * code is needed.
01334              */
01335             for (j = 0; j < bmp->h; j++) {
01336                 for (i = 0; i < bmp->w; i++) {
01337                     int pix = _getpixel32(bmp, i, j);
01338                     _putpixel32(bmp, i, j,
01339                         makeacol32(getr32(pix), getg32(pix), getb32(pix), 255));
01340                 }
01341             }
01342         }
01343         internal_format = GL_RGBA8;
01344     }
01345     
01346 
01347     /* Generate the texture */
01348     glGenTextures(1, &tex);
01349     if (!tex) {
01350         TRACE(PREFIX_E "make_texture_ex: Unable to create GL texture!\n");
01351         goto end;
01352     }
01353 
01354     ret = do_texture_upload(bmp, tex, internal_format, format, type, flags);
01355 
01356 end:
01357     if (temp) {
01358         destroy_bitmap(temp);
01359     }
01360 
01361     if (!ret && tex) {
01362         glDeleteTextures(1, &tex);
01363     }
01364 
01365     glBindTexture(GL_TEXTURE_2D, old_tex);
01366 
01367     return tex;
01368 }
01369 
01370 
01371 
01372 
01373 
01374 /* GLuint allegro_gl_make_texture(BITMAP *bmp) */
01383 GLuint allegro_gl_make_texture(BITMAP *bmp) {
01384         
01385     int flags = __allegro_gl_convert_flags(0);
01386     
01387     return allegro_gl_make_texture_ex(flags, bmp,
01388                                      allegro_gl_opengl_internal_texture_format);
01389 }
01390 
01391 
01392 
01393 /* GLuint allegro_gl_make_masked_texture(BITMAP *bmp) */
01402 GLuint allegro_gl_make_masked_texture(BITMAP *bmp) {
01403         
01404     int flags = __allegro_gl_convert_flags(AGL_TEXTURE_MASKED);
01405 
01406     return allegro_gl_make_texture_ex(flags, bmp,
01407                                      allegro_gl_opengl_internal_texture_format);
01408 }
01409 
01410 
01411 
01412 /* GLenum allegro_gl_get_bitmap_type(BITMAP *bmp) */
01433 GLenum allegro_gl_get_bitmap_type(BITMAP *bmp) {
01434 
01435     int flags = __allegro_gl_convert_flags(0);
01436     return __allegro_gl_get_bitmap_type(bmp, flags);
01437 }
01438 
01439 
01440 
01441 /* GLenum allegro_gl_get_bitmap_color_format(BITMAP *bmp) */
01456 GLenum allegro_gl_get_bitmap_color_format(BITMAP *bmp) {
01457 
01458     int flags = __allegro_gl_convert_flags(0);
01459     return __allegro_gl_get_bitmap_color_format(bmp, flags);
01460 }
01461 
allegro4.4-4.4.2/addons/allegrogl/docs/html/videovtb_8c.html000066400000000000000000000577061173507505700236430ustar00rootroot00000000000000 AllegroGL: videovtb.c File Reference

videovtb.c File Reference

video bitmaps (ie. More...

#include <string.h>
#include <limits.h>
#include <allegro.h>
#include "alleggl.h"
#include "allglint.h"
#include "glvtable.h"
#include <allegro/internal/aintern.h>
#include <GL/glu.h>

Go to the source code of this file.

Defines

  • #define MASKED_BLIT   1
  • #define BLIT   2
  • #define TRANS   3
  • #define FOR_EACH_TEXTURE_FRAGMENT(screen_blit_from_vid,screen_blit_from_mem,mem_copy_blit_from_vid,mem_copy_blit_from_mem,vid_and_mem_copy_blit_from_vid, vid_and_mem_copy_blit_from_mem)
  • #define BIN_2_DEG(x)   (-(x) * 180.0 / 128)

Functions

  • void allegro_gl_destroy_video_bitmap (BITMAP *bmp)
    destroy_video_bitmap() overload.
  • static int allegro_gl_make_video_bitmap_helper1 (int w, int h, int x, int y, GLint target, AGL_VIDEO_BITMAP **pvid)
  • static int allegro_gl_make_video_bitmap_helper0 (int w, int h, int x, int y, AGL_VIDEO_BITMAP **pvid)
  • static BITMAP * allegro_gl_make_video_bitmap (BITMAP *bmp)
  • BITMAP * allegro_gl_create_video_bitmap (int w, int h)
    create_video_bitmap() overload.
  • static void allegro_gl_video_acquire (struct BITMAP *bmp)
    acquire_bitmap(bmp) overload.
  • static void allegro_gl_video_release (struct BITMAP *bmp)
    release_bitmap(bmp) overload.
  • static void set_drawing_pattern (void)
  • static void unset_drawing_pattern (void)
  • static int allegro_gl_video_getpixel (struct BITMAP *bmp, int x, int y)
  • static void update_texture_memory (AGL_VIDEO_BITMAP *vid, int x1, int y1, int x2, int y2)
  • static void allegro_gl_video_putpixel (struct BITMAP *bmp, int x, int y, int color)
  • static void allegro_gl_video_vline (BITMAP *bmp, int x, int y1, int y2, int color)
  • static void allegro_gl_video_hline (BITMAP *bmp, int x1, int y, int x2, int color)
  • static void allegro_gl_video_line (struct BITMAP *bmp, int x1, int y1, int x2, int y2, int color)
  • static void allegro_gl_video_rectfill (struct BITMAP *bmp, int x1, int y1, int x2, int y2, int color)
  • static void allegro_gl_video_triangle (struct BITMAP *bmp, int x1, int y1, int x2, int y2, int x3, int y3, int color)
  • static void allegro_gl_video_blit_from_memory_ex (BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height, int draw_type)
  • void allegro_gl_video_blit_from_memory (BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)
  • void allegro_gl_video_blit_to_memory (struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)
  • static void __video_update_memory_copy (BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height, int draw_type)
  • void allegro_gl_video_blit_to_self (struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)
  • static void do_masked_blit_video (struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height, int flip_dir, int blit_type)
  • static void allegro_gl_video_masked_blit (struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)
  • static void allegro_gl_video_draw_sprite (struct BITMAP *bmp, struct BITMAP *sprite, int x, int y)
  • static void allegro_gl_video_draw_sprite_v_flip (struct BITMAP *bmp, struct BITMAP *sprite, int x, int y)
  • static void allegro_gl_video_draw_sprite_h_flip (struct BITMAP *bmp, struct BITMAP *sprite, int x, int y)
  • static void allegro_gl_video_draw_sprite_vh_flip (struct BITMAP *bmp, struct BITMAP *sprite, int x, int y)
  • static void allegro_gl_video_pivot_scaled_sprite_flip (struct BITMAP *bmp, struct BITMAP *sprite, fixed x, fixed y, fixed cx, fixed cy, fixed angle, fixed scale, int v_flip)
  • static void allegro_gl_video_do_stretch_blit (BITMAP *source, BITMAP *dest, int source_x, int source_y, int source_width, int source_height, int dest_x, int dest_y, int dest_width, int dest_height, int masked)
  • static void allegro_gl_video_draw_trans_rgba_sprite (BITMAP *bmp, BITMAP *sprite, int x, int y)
  • static void allegro_gl_video_draw_sprite_ex (BITMAP *bmp, BITMAP *sprite, int x, int y, int mode, int flip)
  • static void allegro_gl_video_clear_to_color (BITMAP *bmp, int color)
  • static void allegro_gl_video_draw_color_glyph (struct BITMAP *bmp, struct BITMAP *sprite, int x, int y, int color, int bg)
  • static void allegro_gl_video_draw_256_sprite (BITMAP *bmp, BITMAP *sprite, int x, int y)
  • static void allegro_gl_video_draw_character (BITMAP *bmp, BITMAP *sprite, int x, int y, int color, int bg)
  • static void allegro_gl_video_draw_glyph (struct BITMAP *bmp, AL_CONST struct FONT_GLYPH *glyph, int x, int y, int color, int bg)
  • static void allegro_gl_video_polygon3d_f (BITMAP *bmp, int type, BITMAP *texture, int vc, V3D_f *vtx[])
  • static void allegro_gl_video_polygon3d (BITMAP *bmp, int type, BITMAP *texture, int vc, V3D *vtx[])
  • static void allegro_gl_video_triangle3d (BITMAP *bmp, int type, BITMAP *texture, V3D *v1, V3D *v2, V3D *v3)
  • static void allegro_gl_video_triangle3d_f (BITMAP *bmp, int type, BITMAP *texture, V3D_f *v1, V3D_f *v2, V3D_f *v3)
  • static void allegro_gl_video_quad3d (BITMAP *bmp, int type, BITMAP *texture, V3D *v1, V3D *v2, V3D *v3, V3D *v4)
  • static void allegro_gl_video_quad3d_f (BITMAP *bmp, int type, BITMAP *texture, V3D_f *v1, V3D_f *v2, V3D_f *v3, V3D_f *v4)
  • static void dummy_unwrite_bank (void)
Video Bitmap Rountines

Variables

  • static GFX_VTABLE allegro_gl_video_vtable
  • static int video_bitmap_count = 2
  • static int __allegro_gl_video_bitmap_bpp = -1
  • BITMAP * __agl_drawing_pattern_bmp
  • BITMAP * old_pattern = NULL

Detailed Description

video bitmaps (ie.

texture rendering) vtable Some of these don't work correctly or will be very slow.

Definition in file videovtb.c.


Function Documentation

void allegro_gl_destroy_video_bitmap ( BITMAP *  bmp)

destroy_video_bitmap() overload.

Will destroy the video bitmap. You mustn't use the BITMAP pointer after calling this function.

Definition at line 308 of file videovtb.c.

BITMAP* allegro_gl_create_video_bitmap ( int  w,
int  h 
)

create_video_bitmap() overload.

This function will create a video bitmap using texture memory. Video bitmaps do not currently share space with the frame buffer (screen). Video bitmaps are lost when switching screen modes.

Definition at line 344 of file videovtb.c.

allegro4.4-4.4.2/addons/allegrogl/docs/html/videovtb_8c_source.html000066400000000000000000004352261173507505700252200ustar00rootroot00000000000000 AllegroGL: videovtb.c Source File

videovtb.c

Go to the documentation of this file.
00001 /* This code is (C) AllegroGL contributors, and double licensed under
00002  * the GPL and zlib licenses. See gpl.txt or zlib.txt for details.
00003  */
00009 #include <string.h>
00010 #include <limits.h>
00011 
00012 #include <allegro.h>
00013 
00014 #ifdef ALLEGRO_WINDOWS
00015 #include <winalleg.h>
00016 #endif
00017 
00018 #include "alleggl.h"
00019 #include "allglint.h"
00020 #include "glvtable.h"
00021 #include <allegro/internal/aintern.h>
00022 #ifdef ALLEGRO_MACOSX
00023 #include <OpenGL/glu.h>
00024 #else
00025 #include <GL/glu.h>
00026 #endif
00027 
00028 
00029 #define MASKED_BLIT 1
00030 #define BLIT        2
00031 #define TRANS       3
00032 
00033 
00034 static GFX_VTABLE allegro_gl_video_vtable;
00035 
00036 /* Counter for video bitmaps. screen = 1 */
00037 static int video_bitmap_count = 2;
00038 
00039 static int __allegro_gl_video_bitmap_bpp = -1;
00040 
00041 extern BITMAP *__agl_drawing_pattern_bmp;
00042 BITMAP *old_pattern = NULL;
00043 
00044 void allegro_gl_destroy_video_bitmap(BITMAP *bmp);
00045 
00046 
00047 
00048 static int allegro_gl_make_video_bitmap_helper1(int w, int h, int x, int y,
00049                                    GLint target, AGL_VIDEO_BITMAP **pvid) {
00050 
00051     int internal_format;
00052     int bpp;
00053 
00054     if (__allegro_gl_video_bitmap_bpp == -1) {
00055         bpp = bitmap_color_depth(screen);
00056     }
00057     else {
00058         bpp = __allegro_gl_video_bitmap_bpp;
00059     }
00060 
00061     (*pvid) = malloc(sizeof(AGL_VIDEO_BITMAP));
00062 
00063     if (!(*pvid))
00064         return -1;
00065 
00066     memset(*pvid, 0, sizeof(AGL_VIDEO_BITMAP));
00067 
00068     /* Create associated bitmap */
00069     (*pvid)->memory_copy = create_bitmap_ex(bpp, w, h);
00070     if (!(*pvid)->memory_copy)
00071         return -1;
00072     
00073     (*pvid)->format = __allegro_gl_get_bitmap_color_format((*pvid)->memory_copy, AGL_TEXTURE_HAS_ALPHA);
00074     (*pvid)->type = __allegro_gl_get_bitmap_type((*pvid)->memory_copy, 0);
00075     internal_format = __allegro_gl_get_texture_format_ex((*pvid)->memory_copy, AGL_TEXTURE_HAS_ALPHA);
00076 
00077     (*pvid)->target = target;
00078 
00079     /* Fill in some values in the bitmap to make it act as a subbitmap
00080      */
00081     (*pvid)->width  = w;
00082     (*pvid)->height = h;
00083     (*pvid)->x_ofs = x;
00084     (*pvid)->y_ofs = y;
00085 
00086     /* Make a texture out of it */
00087     glGenTextures(1, &((*pvid)->tex));
00088     if (!((*pvid)->tex))
00089         return -1;
00090 
00091     glEnable((*pvid)->target);
00092     glBindTexture((*pvid)->target, ((*pvid)->tex));
00093 
00094     glTexImage2D((*pvid)->target, 0, internal_format, w, h,
00095                  0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
00096 
00097     /* By default, use the Allegro filtering mode - ie: Nearest */
00098     glTexParameteri((*pvid)->target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
00099     glTexParameteri((*pvid)->target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
00100 
00101     /* <mmimica>
00102        Clamping removed because we want video bitmaps that are set for
00103        patterned drawing to be GL_REPEAT (default wrapping mode). Doesn't
00104        seem to break anything.
00105     */
00106 #if 0
00107     /* Clamp to edge */
00108     {
00109         GLenum clamp = GL_CLAMP_TO_EDGE;
00110         if (!allegro_gl_extensions_GL.SGIS_texture_edge_clamp) {
00111             clamp = GL_CLAMP;
00112         }
00113         glTexParameteri((*pvid)->target, GL_TEXTURE_WRAP_S, clamp);
00114         glTexParameteri((*pvid)->target, GL_TEXTURE_WRAP_T, clamp);
00115     }
00116 #endif
00117 
00118     glDisable((*pvid)->target);
00119 
00120     if (allegro_gl_extensions_GL.EXT_framebuffer_object) {
00121         glGenFramebuffersEXT(1, &((*pvid)->fbo));
00122         if (!(*pvid)->fbo) {
00123             glDeleteTextures(1, &((*pvid)->tex));
00124             return -1;
00125         }
00126 
00127         glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, (*pvid)->fbo);
00128         glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, (*pvid)->target, (*pvid)->tex, 0);
00129         if (glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT) {
00130             /* Some FBO implementation limitation was hit, will use normal textures. */
00131             glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
00132             glDeleteFramebuffersEXT(1, &((*pvid)->fbo));
00133             (*pvid)->fbo = 0;
00134             return 0;
00135         }
00136         
00137         glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
00138     }
00139     else {
00140         (*pvid)->fbo = 0;
00141     }
00142 
00143     return 0;
00144 }
00145 
00146 
00147 
00148 static int allegro_gl_make_video_bitmap_helper0(int w, int h, int x, int y,
00149                                                 AGL_VIDEO_BITMAP **pvid) {
00150         
00151     int is_power_of_2 = (!(w & (w - 1)) && !(h & (h - 1)));
00152     int texture_rect_available = allegro_gl_extensions_GL.ARB_texture_rectangle
00153 #ifdef ALLEGRO_MACOSX
00154                              || allegro_gl_extensions_GL.EXT_texture_rectangle
00155 #endif
00156                              || allegro_gl_extensions_GL.NV_texture_rectangle;
00157     GLint max_rect_texture_size = 0;
00158 
00159     if (texture_rect_available) {
00160         glGetIntegerv(GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB, &max_rect_texture_size);
00161     }
00162 
00163     if (w <= allegro_gl_info.max_texture_size &&
00164         h <= allegro_gl_info.max_texture_size) {
00165         if (allegro_gl_extensions_GL.ARB_texture_non_power_of_two ||
00166             is_power_of_2) {
00167             if (allegro_gl_make_video_bitmap_helper1(w, h, x, y,
00168                                             GL_TEXTURE_2D, pvid)) {
00169                 return -1;
00170             }
00171         }
00172         else if (texture_rect_available &&
00173                  w <= max_rect_texture_size &&
00174                  h <= max_rect_texture_size) {
00175             if (allegro_gl_make_video_bitmap_helper1(w, h, x, y,
00176                                             GL_TEXTURE_RECTANGLE_ARB, pvid)) {
00177                 return -1;
00178             }
00179         }
00180         else {
00181             /* NPO2 textures are not suppored by the driver in any way.
00182              * Split the bitmap into smaller POT bitmaps. */
00183             const unsigned int BITS = sizeof(int) * CHAR_BIT;
00184             unsigned int i, j;
00185             unsigned int w1, h1;
00186             unsigned int x1, y1;
00187             unsigned int p1, p2;
00188 
00189             /* Find the POTs using bits. */
00190             y1 = 0;
00191             for (i = 0; i < BITS; i++) {
00192                 p1 = 1 << i;
00193                 if (h & p1)
00194                     h1 = p1;
00195                 else
00196                     continue;
00197 
00198                 x1 = 0;
00199                 for (j = 0; j < BITS; j++) {
00200                     p2 = 1 << j;
00201                     if (w & p2)
00202                         w1 = p2;
00203                     else
00204                         continue;
00205 
00206                     if (allegro_gl_make_video_bitmap_helper0(w1, h1, x + x1,
00207                                                         y + y1, pvid)) {
00208                         return -1;
00209                     }
00210                     do {
00211                         pvid = &((*pvid)->next);
00212                     } while (*pvid);
00213 
00214                     x1 += w1;
00215                 }
00216 
00217                 y1 += h1;
00218             }
00219         }
00220     }
00221     else {
00222         /* Texture is too big to fit. Split it in 4 and try again. */
00223         int w1, w2, h1, h2;
00224 
00225         w2 = w / 2;
00226         w1 = w - w2;
00227 
00228         h2 = h / 2;
00229         h1 = h - h2;
00230 
00231         /* Even a 1x1 texture didn't work? Bail*/
00232         if (!w2 && !h2) {
00233             return -1;
00234         }
00235 
00236         /* Top-left corner */
00237         if (allegro_gl_make_video_bitmap_helper0(w1, h1, x, y, pvid)) {
00238             return -1;
00239         }
00240         do {
00241             pvid = &((*pvid)->next);
00242         } while (*pvid);
00243 
00244         /* Top-right corner */
00245         if (w2) {
00246             if (allegro_gl_make_video_bitmap_helper0(w2, h1, x + w1, y, pvid)) {
00247                 return -1;
00248             }
00249             do {
00250                 pvid = &((*pvid)->next);
00251             } while (*pvid);
00252         }
00253         /* Bottom-left corner */
00254         if (h2) {
00255             if (allegro_gl_make_video_bitmap_helper0(w1, h2, x, y + h1, pvid)) {
00256                 return -1;
00257             }
00258             do {
00259                 pvid = &((*pvid)->next);
00260             } while (*pvid);
00261         }
00262         /* Bottom-right corner */
00263         if (w2 && h2) {
00264             if (allegro_gl_make_video_bitmap_helper0(w2, h2, x + w1, y + h1, pvid)) {
00265                 return -1;
00266             }
00267             do {
00268                 pvid = &((*pvid)->next);
00269             } while (*pvid);
00270         }
00271     }
00272 
00273     return 0;
00274 }
00275 
00276 
00277 
00278 /* Will make a (potentially piece-wise) texture out of the specified bitmap
00279  * Source -must- be a memory bitmap or memory subbitmap (created by Allegro
00280  * only).
00281  *
00282  */
00283 static BITMAP *allegro_gl_make_video_bitmap(BITMAP *bmp) {
00284     
00285     /* Grab a pointer to the bitmap data to patch */
00286     void *ptr = &bmp->extra;
00287     AGL_VIDEO_BITMAP **pvid = (AGL_VIDEO_BITMAP**)ptr;
00288     
00289     /* Convert bitmap to texture */
00290     if (allegro_gl_make_video_bitmap_helper0(bmp->w, bmp->h, 0, 0, pvid)) {
00291         goto agl_error;
00292     }
00293 
00294     return bmp;
00295     
00296 agl_error:
00297     allegro_gl_destroy_video_bitmap(bmp);
00298     return NULL;
00299 }
00300 
00301 
00302 
00303 /* void allegro_gl_destroy_video_bitmap(BITMAP *bmp) */
00308 void allegro_gl_destroy_video_bitmap(BITMAP *bmp) {
00309 
00310     AGL_VIDEO_BITMAP *vid = bmp ? bmp->extra : NULL, *next;
00311     
00312     if (!bmp)
00313         return;
00314     
00315     while (vid) {
00316         if (vid->memory_copy)
00317             destroy_bitmap(vid->memory_copy);
00318     
00319         if (vid->tex)
00320             glDeleteTextures(1, &vid->tex);
00321 
00322         if (vid->fbo)
00323             glDeleteFramebuffersEXT(1, &vid->fbo);
00324                                 
00325         next = vid->next;
00326         free(vid);
00327         vid = next;
00328     }
00329 
00330     free(bmp->vtable);
00331     free(bmp);
00332     
00333     return;
00334 }
00335 
00336 
00337 
00338 /* BITMAP *allegro_gl_create_video_bitmap(int w, int h) */
00344 BITMAP *allegro_gl_create_video_bitmap(int w, int h) {
00345     GFX_VTABLE *vtable;
00346     BITMAP *bitmap;
00347 
00348     bitmap = malloc(sizeof(BITMAP) + sizeof(char *));
00349     
00350     if (!bitmap)
00351         return NULL;
00352 
00353     bitmap->dat = NULL;
00354     bitmap->w = bitmap->cr = w;
00355     bitmap->h = bitmap->cb = h;
00356     bitmap->clip = TRUE;
00357     bitmap->cl = bitmap->ct = 0;
00358     bitmap->write_bank = bitmap->read_bank = NULL;
00359     /* We should keep tracks of allocated bitmaps for the ref counter */
00360     bitmap->id = BMP_ID_VIDEO | video_bitmap_count;
00361     bitmap->extra = NULL;
00362     bitmap->x_ofs = 0;
00363     bitmap->y_ofs = 0;
00364     bitmap->seg = _default_ds();
00365     bitmap->line[0] = NULL;
00366     bitmap->vtable = NULL;
00367 
00368     if (!allegro_gl_make_video_bitmap(bitmap)) {
00369         return NULL;
00370     }
00371     video_bitmap_count++;
00372     
00373     /* XXX <rohannessian> We ought to leave the Allegro values intact
00374      * Avoids bad interaction with correct Allegro programs.
00375      */
00376     vtable = malloc(sizeof(struct GFX_VTABLE));
00377     *vtable = allegro_gl_video_vtable;
00378     if (__allegro_gl_video_bitmap_bpp == -1) {
00379         vtable->color_depth = bitmap_color_depth(screen);
00380     }
00381     else {
00382         vtable->color_depth = __allegro_gl_video_bitmap_bpp;
00383     }
00384     switch (vtable->color_depth) {
00385         case 8:
00386             vtable->mask_color = MASK_COLOR_8;
00387         break;
00388         case 15:
00389             vtable->mask_color = MASK_COLOR_15;
00390         break;
00391         case 16:
00392             vtable->mask_color = MASK_COLOR_16;
00393         break;
00394         case 24:
00395             vtable->mask_color = MASK_COLOR_24;
00396         break;
00397         case 32:
00398             vtable->mask_color = MASK_COLOR_32;
00399         break;
00400     }
00401     bitmap->vtable = vtable;
00402 
00403     return bitmap;
00404 }
00405 
00406 
00407 
00408 /* allegro_gl_set_video_bitmap_color_depth(int bpp) */
00423 GLint allegro_gl_set_video_bitmap_color_depth(int bpp) {
00424     GLint old_val = __allegro_gl_video_bitmap_bpp;
00425     __allegro_gl_video_bitmap_bpp = bpp;
00426     return old_val;
00427 }
00428 
00429 
00430 /* static void allegro_gl_video_acquire(struct BITMAP *bmp) */
00437 static void allegro_gl_video_acquire(struct BITMAP *bmp) {}
00438 
00439 
00440 
00441 /* static void allegro_gl_video_release(struct BITMAP *bmp) */
00448 static void allegro_gl_video_release(struct BITMAP *bmp) {}
00449 
00450 
00451 
00452 static void set_drawing_pattern(void)
00453 {
00454     if (_drawing_pattern && !is_memory_bitmap(_drawing_pattern)) {
00455         old_pattern = _drawing_pattern;
00456         drawing_mode(_drawing_mode, __agl_drawing_pattern_bmp,
00457                      _drawing_x_anchor, _drawing_y_anchor);
00458     }
00459 }
00460 
00461 
00462 
00463 static void unset_drawing_pattern(void)
00464 {
00465     if (old_pattern) {
00466         drawing_mode(_drawing_mode, old_pattern,
00467                      _drawing_x_anchor, _drawing_y_anchor);
00468         old_pattern = NULL;
00469     }
00470 }
00471 
00472 
00473 
00474 static int allegro_gl_video_getpixel(struct BITMAP *bmp, int x, int y)
00475 {
00476     int pix = -1;
00477     AGL_VIDEO_BITMAP *vid;
00478     AGL_LOG(2, "glvtable.c:allegro_gl_screen_getpixel\n");  
00479     
00480     if (is_sub_bitmap(bmp)) {
00481         x += bmp->x_ofs;
00482         y += bmp->y_ofs;
00483     }
00484     if (x < bmp->cl || x >= bmp->cr || y < bmp->ct || y >= bmp->cb) {
00485         return -1;
00486     }
00487 
00488     vid = bmp->extra;
00489     
00490     while (vid) {
00491         if (vid->x_ofs <= x && vid->y_ofs <= y
00492          && vid->x_ofs + vid->memory_copy->w > x
00493          && vid->y_ofs + vid->memory_copy->h > y) {
00494             
00495             pix = getpixel(vid->memory_copy, x - vid->x_ofs, y - vid->y_ofs);
00496             break;
00497         }
00498         vid = vid->next;
00499     }
00500     
00501     if (pix != -1) {
00502         return pix;
00503     }
00504     
00505     return -1;
00506 }
00507 
00508 
00509 
00510 static void update_texture_memory(AGL_VIDEO_BITMAP *vid, int x1, int y1,
00511                                   int x2, int y2) {
00512     GLint saved_row_length;
00513     GLint saved_alignment;
00514     GLint type;
00515     GLint format;
00516     int bpp;
00517     BITMAP *temp = NULL;
00518     BITMAP *vbmp = vid->memory_copy;;
00519 
00520     glGetIntegerv(GL_UNPACK_ROW_LENGTH, &saved_row_length);
00521     glGetIntegerv(GL_UNPACK_ALIGNMENT, &saved_alignment);
00522 
00523     bpp = BYTES_PER_PIXEL(bitmap_color_depth(vid->memory_copy));
00524     format = vid->format;
00525     type = vid->type;
00526 
00527     glColor4ub(255, 255, 255, 255);
00528 
00529     /* If packed pixels (or GL 1.2) isn't supported, then we need to convert
00530      * the bitmap into something GL can understand - 24-bpp should do it.
00531      */
00532     if (!allegro_gl_extensions_GL.EXT_packed_pixels
00533                                           && bitmap_color_depth(vbmp) < 24) {
00534         temp = create_bitmap_ex(24, vbmp->w, vbmp->h);
00535         if (!temp)
00536             return;
00537 
00538         blit(vbmp, temp, 0, 0, 0, 0, temp->w, temp->h);
00539         vbmp = temp;
00540         bpp = BYTES_PER_PIXEL(bitmap_color_depth(vbmp));
00541         format = __allegro_gl_get_bitmap_color_format(vbmp, 0);
00542         type = __allegro_gl_get_bitmap_type(vbmp, 0);
00543     }
00544 
00545     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
00546     glPixelStorei(GL_UNPACK_ROW_LENGTH,
00547                   vbmp->h > 1
00548                  ? (vbmp->line[1] - vbmp->line[0]) / bpp
00549                  : vbmp->w);
00550 
00551     glEnable(vid->target);
00552     glBindTexture(vid->target, vid->tex);
00553     glTexSubImage2D(vid->target, 0,
00554         x1, y1, x2 - x1 + 1, y2 - y1 + 1, format,
00555         type, vbmp->line[y1] + x1 * bpp);
00556     glBindTexture(vid->target, 0);
00557     glDisable(vid->target);
00558 
00559     if (temp)
00560         destroy_bitmap(temp);
00561 
00562     glPixelStorei(GL_UNPACK_ROW_LENGTH, saved_row_length);
00563     glPixelStorei(GL_UNPACK_ALIGNMENT, saved_alignment);
00564 }
00565 
00566 
00567 
00568 static void allegro_gl_video_putpixel(struct BITMAP *bmp, int x, int y,
00569                                       int color) {
00570     AGL_VIDEO_BITMAP *vid;
00571 
00572     if (is_sub_bitmap(bmp)) {
00573         x += bmp->x_ofs;
00574         y += bmp->y_ofs;
00575     }
00576     if (x < bmp->cl || x >= bmp->cr || y < bmp->ct || y >= bmp->cb) {
00577         return;
00578     }
00579 
00580     vid = bmp->extra;
00581 
00582     while (vid) {
00583         if (vid->x_ofs <= x && vid->y_ofs <= y
00584          && vid->x_ofs + vid->memory_copy->w > x
00585          && vid->y_ofs + vid->memory_copy->h > y) {
00586 
00587             set_drawing_pattern();
00588             putpixel(vid->memory_copy, x - vid->x_ofs, y - vid->y_ofs, color);
00589             unset_drawing_pattern();
00590             update_texture_memory(vid, x - vid->x_ofs, y - vid->y_ofs, x - vid->x_ofs, y - vid->y_ofs);
00591             break;
00592         }
00593         vid = vid->next;
00594     }
00595     
00596     return;
00597 }
00598 
00599 
00600 
00601 static void allegro_gl_video_vline(BITMAP *bmp, int x, int y1, int y2,
00602                                    int color) {
00603 
00604     AGL_VIDEO_BITMAP *vid;
00605     
00606     AGL_LOG(2, "glvtable.c:allegro_gl_video_vline\n");
00607     vid = bmp->extra;
00608     
00609     if (is_sub_bitmap(bmp)) {
00610         x  += bmp->x_ofs;
00611         y1 += bmp->y_ofs;
00612         y2 += bmp->y_ofs;
00613     }
00614     if (x < bmp->cl || x >= bmp->cr) {
00615         return;
00616     }
00617     
00618     if (y1 > y2) {
00619         int temp = y1;
00620         y1 = y2;
00621         y2 = temp;
00622     }
00623 
00624     if (y1 < bmp->ct) {
00625         y1 = bmp->ct;
00626     }
00627     if (y2 >= bmp->cb) {
00628         y2 = bmp->cb - 1;
00629     }
00630 
00631     while (vid) {
00632         BITMAP *vbmp = vid->memory_copy;
00633         
00634         int _y1, _y2, _x;
00635         if (vid->x_ofs > x || vid->y_ofs > y2
00636          || vid->x_ofs + vbmp->w <= x
00637          || vid->y_ofs + vbmp->h <= y1) {
00638             
00639             vid = vid->next;
00640             continue;
00641         }
00642         
00643         _y1 = MAX(y1, vid->y_ofs) - vid->y_ofs;
00644         _y2 = MIN(y2, vid->y_ofs + vbmp->h - 1) - vid->y_ofs;
00645         _x = x - vid->x_ofs;
00646 
00647         set_drawing_pattern();
00648         vline(vbmp, _x, _y1, _y2, color);
00649         unset_drawing_pattern();
00650         update_texture_memory(vid, _x, _y1, _x, _y2);
00651 
00652         vid = vid->next;
00653     }
00654     
00655     return;
00656 }
00657 
00658 
00659 
00660 static void allegro_gl_video_hline(BITMAP *bmp, int x1, int y, int x2,
00661                                    int color) {
00662 
00663     AGL_VIDEO_BITMAP *vid;
00664     
00665     AGL_LOG(2, "glvtable.c:allegro_gl_video_hline\n");
00666     vid = bmp->extra;
00667 
00668     if (is_sub_bitmap(bmp)) {
00669         x1 += bmp->x_ofs;
00670         x2 += bmp->x_ofs;
00671         y  += bmp->y_ofs;
00672     }
00673 
00674     if (y < bmp->ct || y >= bmp->cb) {
00675         return;
00676     }
00677     
00678     if (x1 > x2) {
00679         int temp = x1;
00680         x1 = x2;
00681         x2 = temp;
00682     }
00683 
00684     if (x1 < bmp->cl) {
00685         x1 = bmp->cl;
00686     }
00687     if (x2 >= bmp->cr) {
00688         x2 = bmp->cr - 1;
00689     }
00690 
00691     while (vid) {
00692         BITMAP *vbmp = vid->memory_copy;
00693         
00694         int _x1, _x2, _y;
00695         if (vid->y_ofs > y || vid->x_ofs > x2
00696          || vid->x_ofs + vbmp->w <= x1
00697          || vid->y_ofs + vbmp->h <= y) {
00698             
00699             vid = vid->next;
00700             continue;
00701         }
00702         
00703         _x1 = MAX(x1, vid->x_ofs) - vid->x_ofs;
00704         _x2 = MIN(x2, vid->x_ofs + vbmp->w - 1) - vid->x_ofs;
00705         _y = y - vid->y_ofs;
00706 
00707         set_drawing_pattern();
00708         hline(vbmp, _x1, _y, _x2, color);   
00709         unset_drawing_pattern();
00710         update_texture_memory(vid, _x1, _y, _x2, _y);
00711 
00712         vid = vid->next;
00713     }
00714     
00715     return;
00716 }
00717 
00718 
00719 
00720 static void allegro_gl_video_line(struct BITMAP *bmp, int x1, int y1, int x2,
00721                                   int y2, int color) {
00722     
00723     /* Note: very very slow */                      
00724     do_line(bmp, x1, y1, x2, y2, color, allegro_gl_video_putpixel);
00725     
00726     return;
00727 }
00728     
00729 
00730 
00731 static void allegro_gl_video_rectfill(struct BITMAP *bmp, int x1, int y1,
00732                                       int x2, int y2, int color) {
00733 
00734     AGL_VIDEO_BITMAP *vid;
00735 
00736     AGL_LOG(2, "glvtable.c:allegro_gl_video_rectfill\n");
00737     vid = bmp->extra;
00738 
00739     if (is_sub_bitmap(bmp)) {
00740         x1 += bmp->x_ofs;
00741         x2 += bmp->x_ofs;
00742         y1 += bmp->y_ofs;
00743         y2 += bmp->y_ofs;
00744     }
00745     
00746     if (y1 > y2) {
00747         int temp = y1;
00748         y1 = y2;
00749         y2 = temp;
00750     }
00751 
00752     if (x1 > x2) {
00753         int temp = x1;
00754         x1 = x2;
00755         x2 = temp;
00756     }
00757 
00758     if (x1 < bmp->cl) {
00759         x1 = bmp->cl;
00760     }
00761     if (x2 > bmp->cr) {
00762         x2 = bmp->cr;
00763     }
00764     if (y1 < bmp->ct) {
00765         y1 = bmp->ct;
00766     }
00767     if (y1 > bmp->cb) {
00768         y1 = bmp->cb;
00769     }
00770 
00771     while (vid) {
00772         BITMAP *vbmp = vid->memory_copy;
00773         
00774         int _y1, _y2, _x1, _x2;
00775         if (vid->x_ofs > x2 || vid->y_ofs > y2
00776          || vid->x_ofs + vbmp->w <= x1
00777          || vid->y_ofs + vbmp->h <= y1) {
00778             
00779             vid = vid->next;
00780             continue;
00781         }
00782         
00783         _y1 = MAX(y1, vid->y_ofs) - vid->y_ofs;
00784         _y2 = MIN(y2, vid->y_ofs + vbmp->h - 1) - vid->y_ofs;
00785         _x1 = MAX(x1, vid->x_ofs) - vid->x_ofs;
00786         _x2 = MIN(x2, vid->x_ofs + vbmp->w - 1) - vid->x_ofs;
00787 
00788         set_drawing_pattern();
00789         rectfill(vbmp, _x1, _y1, _x2, _y2, color);
00790         unset_drawing_pattern();
00791 
00792         update_texture_memory(vid, _x1, _y1, _x2, _y2);
00793 
00794         vid = vid->next;
00795     }
00796 
00797     return;
00798 }
00799 
00800 
00801 static void allegro_gl_video_triangle(struct BITMAP *bmp, int x1, int y1,
00802                                       int x2, int y2, int x3, int y3, int color)
00803 {   
00804     AGL_VIDEO_BITMAP *vid;
00805     int min_y, max_y, min_x, max_x;
00806 
00807     AGL_LOG(2, "glvtable.c:allegro_gl_video_triangle\n");
00808     vid = bmp->extra;
00809 
00810     if (is_sub_bitmap(bmp)) {
00811         x1 += bmp->x_ofs;
00812         x2 += bmp->x_ofs;
00813         x3 += bmp->x_ofs;
00814         y1 += bmp->y_ofs;
00815         y2 += bmp->y_ofs;
00816         y3 += bmp->y_ofs;
00817     }
00818 
00819     min_y = MIN(y1, MIN(y2, y3));
00820     min_x = MIN(x1, MIN(x2, x3));
00821     max_y = MAX(y1, MAX(y2, y3));
00822     max_x = MAX(x1, MAX(x2, x3));
00823 
00824     while (vid) {
00825         BITMAP *vbmp = vid->memory_copy;
00826         
00827         int _y1, _y2, _x1, _x2, _x3, _y3;
00828         if (vid->x_ofs > max_x || vid->y_ofs > max_y
00829          || vid->x_ofs + vbmp->w <= min_x
00830          || vid->y_ofs + vbmp->h <= min_y) {
00831             
00832             vid = vid->next;
00833             continue;
00834         }
00835         
00836         _y1 = y1 - vid->y_ofs;
00837         _y2 = y2 - vid->y_ofs;
00838         _y3 = y3 - vid->y_ofs;
00839         _x1 = x1 - vid->x_ofs;
00840         _x2 = x2 - vid->x_ofs;
00841         _x3 = x3 - vid->x_ofs;
00842 
00843         set_clip_rect(vbmp, bmp->cl - vid->x_ofs, bmp->ct - vid->y_ofs,
00844                             bmp->cr - vid->x_ofs - 1, bmp->cb - vid->y_ofs - 1);
00845 
00846         set_drawing_pattern();
00847 
00848         triangle(vbmp, _x1, _y1, _x2, _y2, _x3, _y3, color);
00849 
00850         unset_drawing_pattern();
00851 
00852         set_clip_rect(vbmp, 0, 0, vbmp->w - 1, vbmp->h - 1);
00853 
00854         /* Not quite the minimal rectangle occupied by the triangle, but
00855         * pretty close */
00856         _y1 = MAX(0, min_y - vid->y_ofs);
00857         _y2 = MIN(vbmp->h - 1, max_y - vid->y_ofs);
00858         _x1 = MAX(0, min_x - vid->x_ofs);
00859         _x2 = MIN(vbmp->w - 1, max_x - vid->x_ofs);
00860 
00861         update_texture_memory(vid, _x1, _y1, _x2, _y2);
00862 
00863         vid = vid->next;
00864     }
00865 }
00866 
00867 
00868 
00869 static void allegro_gl_video_blit_from_memory_ex(BITMAP *source, BITMAP *dest,
00870                     int source_x, int source_y, int dest_x, int dest_y,
00871                     int width, int height, int draw_type) {
00872 
00873     AGL_VIDEO_BITMAP *vid;
00874     BITMAP *dest_parent = dest;
00875     
00876     if (is_sub_bitmap (dest)) {
00877        dest_x += dest->x_ofs;
00878        dest_y += dest->y_ofs;
00879        while (dest_parent->id & BMP_ID_SUB)
00880           dest_parent = (BITMAP *)dest_parent->extra;
00881     }
00882 
00883     if (dest_x < dest->cl) {
00884         dest_x = dest->cl;
00885     }
00886     if (dest_y < dest->ct) {
00887         dest_y = dest->ct;
00888     }
00889     if (dest_x + width >= dest->cr) {
00890         width = dest->cr - dest_x;
00891     }
00892     if (dest_y + height >= dest->cb) {
00893         height = dest->cb - dest_y;
00894     }
00895     if (width < 1 || height < 1) {
00896         return;
00897     }
00898     
00899     vid = dest_parent->extra;
00900 
00901     while (vid) {
00902         BITMAP *vbmp = vid->memory_copy;
00903 
00904         int _x, _y, _w, _h, _sx, _sy;
00905         if (vid->x_ofs >= dest_x + width || vid->y_ofs >= dest_y + height
00906          || vid->x_ofs + vbmp->w <= dest_x
00907          || vid->y_ofs + vbmp->h <= dest_y) {
00908             
00909             vid = vid->next;
00910             continue;
00911         }
00912 
00913         _x = MAX (vid->x_ofs, dest_x) - vid->x_ofs;
00914         _w = MIN (vid->x_ofs + vbmp->w, dest_x + width)
00915            - vid->x_ofs - _x;
00916         _y = MAX (vid->y_ofs, dest_y) - vid->y_ofs;
00917         _h = MIN (vid->y_ofs + vbmp->h, dest_y + height)
00918            - vid->y_ofs - _y;
00919 
00920         _sx = source_x + vid->x_ofs + _x - dest_x;
00921         _sy = source_y + vid->y_ofs + _y - dest_y;
00922 
00923         if (draw_type == BLIT) {
00924             blit(source, vbmp, _sx, _sy, _x, _y, _w, _h);
00925         }
00926         else if (draw_type == MASKED_BLIT) {
00927             masked_blit(source, vbmp, _sx, _sy, _x, _y, _w, _h);
00928         }
00929         else if (draw_type == TRANS) {
00930             BITMAP *clip = create_sub_bitmap(source, _sx, _sy, _w, _h);
00931             if (!clip)
00932                 return;
00933             draw_trans_sprite(vbmp, clip, _x, _y);
00934             destroy_bitmap(clip);
00935         }
00936 
00937         update_texture_memory(vid, _x, _y, _x + _w - 1, _y + _h - 1);
00938 
00939         vid = vid->next;
00940     }
00941 
00942     return; 
00943 }
00944 
00945 
00946 void allegro_gl_video_blit_from_memory(BITMAP *source, BITMAP *dest,
00947                     int source_x, int source_y, int dest_x, int dest_y,
00948                     int width, int height) {
00949 
00950     allegro_gl_video_blit_from_memory_ex(source, dest, source_x, source_y,
00951                                          dest_x, dest_y, width, height, BLIT);
00952     return;
00953 }
00954 
00955 
00956 
00957 void allegro_gl_video_blit_to_memory(struct BITMAP *source, struct BITMAP *dest,
00958                          int source_x, int source_y, int dest_x, int dest_y,
00959                          int width, int height) {
00960 
00961     AGL_VIDEO_BITMAP *vid;
00962     BITMAP *source_parent = source;
00963     
00964     AGL_LOG(2, "glvtable.c:allegro_gl_video_blit_to_memory\n");
00965     
00966     if (is_sub_bitmap(source)) {
00967        source_x += source->x_ofs;
00968        source_y += source->y_ofs;
00969        while (source_parent->id & BMP_ID_SUB)
00970           source_parent = (BITMAP *)source_parent->extra;
00971     }
00972 
00973     vid = source_parent->extra;
00974     
00975     while (vid) {
00976         BITMAP *vbmp = vid->memory_copy;
00977         int x, y, dx, dy, w, h;
00978 
00979         x = MAX(source_x, vid->x_ofs) - vid->x_ofs;
00980         y = MAX(source_y, vid->y_ofs) - vid->y_ofs;
00981         w = MIN(vid->x_ofs + vbmp->w, source_x + width) - vid->x_ofs;
00982         h = MIN(vid->y_ofs + vbmp->h, source_y + height) - vid->y_ofs;
00983         dx = MAX(0, vid->x_ofs - source_x) + dest_x;
00984         dy = MAX(0, vid->y_ofs - source_y) + dest_y;
00985 
00986         blit(vbmp, dest, x, y, dx, dy, w, h);
00987     
00988         vid = vid->next;
00989     }
00990 
00991     return; 
00992 }
00993 
00994 
00995 
00996 /* Just like allegro_gl_video_blit_from_memory(), except that draws only to the
00997  * memory copy.
00998  */
00999 static void __video_update_memory_copy(BITMAP *source, BITMAP *dest,
01000                             int source_x, int source_y, int dest_x, int dest_y,
01001                             int width, int height, int draw_type) {
01002     AGL_VIDEO_BITMAP *vid;
01003     BITMAP *dest_parent = dest;
01004     
01005     if (is_sub_bitmap (dest)) {
01006        dest_x += dest->x_ofs;
01007        dest_y += dest->y_ofs;
01008        while (dest_parent->id & BMP_ID_SUB)
01009           dest_parent = (BITMAP *)dest_parent->extra;
01010     }
01011 
01012     if (dest_x < dest->cl) {
01013         dest_x = dest->cl;
01014     }
01015     if (dest_y < dest->ct) {
01016         dest_y = dest->ct;
01017     }
01018     if (dest_x + width >= dest->cr) {
01019         width = dest->cr - dest_x;
01020     }
01021     if (dest_y + height >= dest->cb) {
01022         height = dest->cb - dest_y;
01023     }
01024     if (width < 1 || height < 1) {
01025         return;
01026     }
01027     
01028     vid = dest_parent->extra;
01029 
01030     while (vid) {
01031         int sx, sy;
01032         BITMAP *vbmp = vid->memory_copy;
01033 
01034         int dx, dy, w, h;
01035         if (vid->x_ofs >= dest_x + width || vid->y_ofs >= dest_y + height
01036          || vid->x_ofs + vbmp->w <= dest_x
01037          || vid->y_ofs + vbmp->h <= dest_y) {
01038             
01039             vid = vid->next;
01040             continue;
01041         }
01042 
01043         dx = MAX (vid->x_ofs, dest_x) - vid->x_ofs;
01044         w = MIN (vid->x_ofs + vbmp->w, dest_x + width)
01045            - vid->x_ofs - dx;
01046         dy = MAX (vid->y_ofs, dest_y) - vid->y_ofs;
01047         h = MIN (vid->y_ofs + vbmp->h, dest_y + height)
01048            - vid->y_ofs - dy;
01049 
01050         sx = source_x + vid->x_ofs + dx - dest_x;
01051         sy = source_y + vid->y_ofs + dy - dest_y;
01052 
01053         if (draw_type == MASKED_BLIT) {
01054             masked_blit(source, vbmp, sx, sy, dx, dy, w, h);
01055         }
01056         else if (draw_type == BLIT) {
01057             blit(source, vbmp, sx, sy, dx, dy, w, h);
01058         }
01059         else if (draw_type == TRANS) {
01060             BITMAP *clip = create_sub_bitmap(source, sx, sy, w, h);
01061             if (!clip)
01062                 return;
01063             draw_trans_sprite(vbmp, clip, dx, dy);
01064             destroy_bitmap(clip);
01065         }
01066 
01067         vid = vid->next;
01068     }
01069     
01070     return;
01071 }
01072 
01073 
01074 #define FOR_EACH_TEXTURE_FRAGMENT(  \
01075     screen_blit_from_vid,           /* used when dest is FBO to blit to texture 
01076                                        memory from video bitmap */                \
01077     screen_blit_from_mem,           /* used when dest is FBO to blit to texture
01078                                        memory from memory bitmap */               \
01079     mem_copy_blit_from_vid,         /* used to update the memory copy of the
01080                                        dest from the source video bitmap */       \
01081     mem_copy_blit_from_mem,         /* used to update the memory copy of the
01082                                        dest from the source memory bitmap */      \
01083     vid_and_mem_copy_blit_from_vid, /* used when dest is not FBO, draws to both
01084                                        memory copy and texute memory of the dest,
01085                                        from video bitmap source*/                 \
01086     vid_and_mem_copy_blit_from_mem) /* used when dest is not FBO, draws to both
01087                                        memory copy and texute memory of the dest,
01088                                        from memory bitmap source */               \
01089 {                                                          \
01090     int used_fbo = FALSE;                                  \
01091     AGL_VIDEO_BITMAP *vid;                                 \
01092                                                            \
01093     vid = dest->extra;                                     \
01094     if (vid->fbo) {                                        \
01095         int sx, sy;                                        \
01096         int dx, dy;                                        \
01097         int w, h;                                          \
01098                                                            \
01099         static GLint v[4];                                 \
01100         static double allegro_gl_projection_matrix[16];    \
01101         static double allegro_gl_modelview_matrix[16];     \
01102                                                            \
01103         glGetIntegerv(GL_VIEWPORT, &v[0]);                 \
01104         glMatrixMode(GL_MODELVIEW);                        \
01105         glGetDoublev(GL_MODELVIEW_MATRIX, allegro_gl_modelview_matrix);   \
01106         glMatrixMode(GL_PROJECTION);                                      \
01107         glGetDoublev(GL_PROJECTION_MATRIX, allegro_gl_projection_matrix); \
01108                                                                           \
01109         while (vid) {                                                     \
01110             if (dest_x >= vid->x_ofs + vid->memory_copy->w ||             \
01111                 dest_y >= vid->y_ofs + vid->memory_copy->h ||             \
01112                 vid->x_ofs >= dest_x + width ||          \
01113                 vid->y_ofs >= dest_y + height) {         \
01114                 vid = vid->next;                         \
01115                 continue;                                \
01116             }                                            \
01117                                                          \
01118             dx = MAX(vid->x_ofs, dest_x) - vid->x_ofs;                  \
01119             w = MIN(vid->x_ofs + vid->memory_copy->w, dest_x + width)   \
01120               - vid->x_ofs - dx;                                        \
01121             dy = MAX(vid->y_ofs, dest_y) - vid->y_ofs;                  \
01122             h = MIN(vid->y_ofs + vid->memory_copy->h, dest_y + height)  \
01123               - vid->y_ofs - dy;                                        \
01124                                                                         \
01125             sx = source_x + vid->x_ofs + dx - dest_x;                   \
01126             sy = source_y + vid->y_ofs + dy - dest_y;                   \
01127                                                                         \
01128             glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, vid->fbo);         \
01129                                                                         \
01130             glViewport(0, 0, vid->memory_copy->w, vid->memory_copy->h); \
01131             glMatrixMode(GL_PROJECTION);                                \
01132             glLoadIdentity();                                           \
01133             gluOrtho2D(0, vid->memory_copy->w, 0, vid->memory_copy->h); \
01134             glMatrixMode(GL_MODELVIEW);                                 \
01135                                              \
01136             if (is_memory_bitmap(source)) {  \
01137                 screen_blit_from_mem;        \
01138             }                                \
01139             else {                           \
01140                 screen_blit_from_vid;        \
01141             }                                \
01142                                 \
01143             vid = vid->next;    \
01144         }                       \
01145                                 \
01146         glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); \
01147                                                      \
01148         glViewport(v[0], v[1], v[2], v[3]);          \
01149         glMatrixMode(GL_PROJECTION);                 \
01150         glLoadMatrixd(allegro_gl_projection_matrix); \
01151         glMatrixMode(GL_MODELVIEW);                  \
01152         glLoadMatrixd(allegro_gl_modelview_matrix);  \
01153                                           \
01154         used_fbo = TRUE;                  \
01155     }                                     \
01156                                           \
01157     if (is_video_bitmap(source)) {        \
01158         int sx, sy;      \
01159         int dx, dy;      \
01160         int w, h;        \
01161                          \
01162         vid = source->extra;   \
01163                                \
01164         while (vid) {          \
01165             if (source_x >= vid->x_ofs + vid->memory_copy->w ||  \
01166                 source_y >= vid->y_ofs + vid->memory_copy->h ||  \
01167                 vid->x_ofs >= source_x + width ||                \
01168                 vid->y_ofs >= source_y + height) {               \
01169                 vid = vid->next;                                 \
01170                 continue;                                        \
01171             }                                                    \
01172                                                                  \
01173             sx = MAX(vid->x_ofs, source_x) - vid->x_ofs;         \
01174             w = MIN(vid->x_ofs + vid->memory_copy->w, source_x + width)  \
01175               - vid->x_ofs - sx;                                         \
01176             sy = MAX(vid->y_ofs, source_y) - vid->y_ofs;                 \
01177             h = MIN(vid->y_ofs + vid->memory_copy->h, source_y + height) \
01178               - vid->y_ofs - sy;                                         \
01179                                                                          \
01180             dx = dest_x + vid->x_ofs + sx - source_x;  \
01181             dy = dest_y + vid->y_ofs + sy - source_y;  \
01182                                                        \
01183             if (used_fbo) {                            \
01184                 mem_copy_blit_from_vid;                \
01185             }                                          \
01186             else {                                     \
01187                 vid_and_mem_copy_blit_from_vid;        \
01188             }                                  \
01189                                                \
01190             vid = vid->next;                   \
01191         }                                      \
01192     }                                          \
01193     else if (is_memory_bitmap(source)) {       \
01194         if (used_fbo) {                        \
01195             mem_copy_blit_from_mem;            \
01196         }                                      \
01197         else {                                 \
01198             vid_and_mem_copy_blit_from_mem;    \
01199         }                                      \
01200     }                                          \
01201 }
01202 
01203 
01204 /* allegro_gl_video_blit_to_self:
01205  * blit() overload for video -> video blits
01206  */
01207 void allegro_gl_video_blit_to_self(struct BITMAP *source, struct BITMAP *dest,
01208     int source_x, int source_y, int dest_x, int dest_y, int width, int height) {
01209 
01210     FOR_EACH_TEXTURE_FRAGMENT (
01211         allegro_gl_screen_blit_to_self(source, screen, sx, sy, dx, dy, w, h),
01212         allegro_gl_screen_blit_to_self(source, screen, sx, sy, dx, dy, w, h),
01213         __video_update_memory_copy(vid->memory_copy, dest, sx, sy, dx, dy, w, h, BLIT),
01214         __video_update_memory_copy(source, dest, source_x, source_y, dest_x, dest_y, width, height, BLIT),
01215         allegro_gl_video_blit_from_memory(vid->memory_copy, dest, sx, sy, dx, dy, w, h),
01216         allegro_gl_video_blit_from_memory(source, dest, source_x, source_y, dest_x, dest_y, width, height)
01217     )
01218 }
01219 
01220 
01221 static void do_masked_blit_video(struct BITMAP *source, struct BITMAP *dest,
01222             int source_x, int source_y, int dest_x, int dest_y,
01223             int width, int height, int flip_dir, int blit_type) {
01224 
01225     FOR_EACH_TEXTURE_FRAGMENT (
01226         do_masked_blit_screen(source, screen, sx, sy, dx, dy, w, h, flip_dir, blit_type),
01227         do_masked_blit_screen(source, screen, sx, sy, dx, dy, w, h, flip_dir, blit_type),
01228         __video_update_memory_copy(vid->memory_copy, dest, sx, sy, dx, dy, w, h, MASKED_BLIT),
01229         __video_update_memory_copy(source, dest, source_x, source_y, dest_x, dest_y, width, height, MASKED_BLIT),
01230         allegro_gl_video_blit_from_memory_ex(vid->memory_copy, dest, sx, sy, dx, dy, w, h, MASKED_BLIT),
01231         allegro_gl_video_blit_from_memory_ex(source, dest, source_x, source_y, dest_x, dest_y, width, height, MASKED_BLIT)
01232     )
01233 }
01234 
01235 
01236 /* allegro_gl_video_masked_blit:
01237  * masked_blit() overload for video -> video masked blits
01238  */
01239 static void allegro_gl_video_masked_blit(struct BITMAP *source,
01240                 struct BITMAP *dest, int source_x, int source_y,
01241                 int dest_x, int dest_y, int width, int height) {
01242     do_masked_blit_video(source, dest, source_x, source_y, dest_x, dest_y,
01243                          width, height, FALSE, AGL_REGULAR_BMP | AGL_NO_ROTATION);
01244 
01245     return;
01246 }
01247 
01248 
01249 /* allegro_gl_video_draw_sprite:
01250  * draw_sprite() overload for video -> video sprite drawing
01251  */
01252 static void allegro_gl_video_draw_sprite(struct BITMAP *bmp,
01253                         struct BITMAP *sprite, int x, int y) {
01254 
01255     do_masked_blit_video(sprite, bmp, 0, 0, x, y, sprite->w, sprite->h,
01256                          FALSE, AGL_NO_ROTATION);
01257 
01258     return;
01259 }
01260 
01261 
01262 /* allegro_gl_video_draw_sprite_v_flip:
01263  * draw_sprite_v_flip() overload for video -> video blits
01264  * FIXME: Broken if the bitmap was split into multiple textures.
01265  * FIXME: Doesn't apply rotation and scale to the memory copy
01266  */
01267 static void allegro_gl_video_draw_sprite_v_flip(struct BITMAP *bmp,
01268                         struct BITMAP *sprite, int x, int y) {
01269 
01270     do_masked_blit_video(sprite, bmp, 0, 0, x, y, sprite->w, sprite->h,
01271                          AGL_V_FLIP, AGL_NO_ROTATION);
01272 
01273     return;
01274 }
01275 
01276 
01277 /* allegro_gl_video_draw_sprite_h_flip:
01278  * draw_sprite_v_flip() overload for video -> video blits
01279  * FIXME: Broken if the bitmap was split into multiple textures.
01280  * FIXME: Doesn't apply rotation and scale to the memory copy
01281  */
01282 static void allegro_gl_video_draw_sprite_h_flip(struct BITMAP *bmp,
01283                         struct BITMAP *sprite, int x, int y) {
01284 
01285     do_masked_blit_video(sprite, bmp, 0, 0, x, y, sprite->w, sprite->h,
01286                          AGL_H_FLIP, AGL_NO_ROTATION);
01287 
01288     return;
01289 }
01290 
01291 
01292 /* allegro_gl_video_draw_sprite_vh_flip:
01293  * draw_sprite_vh_flip() overload for video -> video blits
01294  * FIXME: Broken if the bitmap was split into multiple textures.
01295  * FIXME: Doesn't apply rotation and scale to the memory copy
01296  */
01297 static void allegro_gl_video_draw_sprite_vh_flip(struct BITMAP *bmp,
01298                         struct BITMAP *sprite, int x, int y) {
01299 
01300     do_masked_blit_video(sprite, bmp, 0, 0, x, y, sprite->w, sprite->h,
01301                          AGL_V_FLIP | AGL_H_FLIP, AGL_NO_ROTATION);
01302 
01303     return;
01304 }
01305 
01306 
01307 /* allegro_gl_video_pivot_scaled_sprite_flip:
01308  * FIXME: Broken if the bitmap was split into multiple textures.
01309  * FIXME: Doesn't apply rotation and scale to the memory copy
01310  * FIXME: Doesn't work for when FBO is not available.
01311  */
01312 static void allegro_gl_video_pivot_scaled_sprite_flip(struct BITMAP *bmp,
01313             struct BITMAP *sprite, fixed x, fixed y, fixed cx, fixed cy,
01314             fixed angle, fixed scale, int v_flip) {
01315     double dscale = fixtof(scale);
01316     GLint matrix_mode;
01317     
01318 #define BIN_2_DEG(x) (-(x) * 180.0 / 128)
01319     
01320     glGetIntegerv(GL_MATRIX_MODE, &matrix_mode);
01321     glMatrixMode(GL_MODELVIEW);
01322     glPushMatrix();
01323     glTranslated(fixtof(x), fixtof(y), 0.);
01324     glRotated(BIN_2_DEG(fixtof(angle)), 0., 0., -1.);
01325     glScaled(dscale, dscale, dscale);
01326     glTranslated(-fixtof(x+cx), -fixtof(y+cy), 0.);
01327     
01328     do_masked_blit_video(sprite, bmp, 0, 0, fixtoi(x), fixtoi(y),
01329                           sprite->w, sprite->h, v_flip ? AGL_V_FLIP : FALSE, FALSE);
01330     glPopMatrix();
01331     glMatrixMode(matrix_mode);
01332 
01333 #undef BIN_2_DEG
01334 
01335     return;
01336 }
01337 
01338 
01339 /* allegro_gl_video_do_stretch_blit:
01340  * overload for all kind of video -> video and video -> screen stretchers
01341  * FIXME: Doesn't apply scale to the memory copy
01342  * FIXME: Doesn't work for video->video when FBO is not available.
01343  */
01344 static void allegro_gl_video_do_stretch_blit(BITMAP *source, BITMAP *dest,
01345                int source_x, int source_y, int source_width, int source_height,
01346                int dest_x, int dest_y, int dest_width, int dest_height,
01347                int masked) {
01348     /* note: src is a video bitmap, dest is not a memory bitmap */
01349 
01350     double scalew = ((double)dest_width) / source_width;
01351     double scaleh = ((double)dest_height) / source_height;
01352     
01353     GLint matrix_mode;
01354 
01355     /* BITMAP_BLIT_CLIP macro from glvtable.c is no good for scaled images. */
01356     if (dest->clip) {
01357         if ((dest_x >= dest->cr) || (dest_y >= dest->cb)
01358          || (dest_x + dest_width < dest->cl) || (dest_y + dest_height < dest->ct)) {
01359             return;
01360         }
01361         if (dest_x < dest->cl) {
01362             source_x -= (dest_x - dest->cl) / scalew;
01363             dest_x = dest->cl;
01364         }
01365         if (dest_y < dest->ct) {
01366             source_y -= (dest_y - dest->ct) / scaleh;
01367             dest_y = dest->ct;
01368         }
01369         if (dest_x + dest_width > dest->cr) {
01370             source_width -= (dest_x + dest_width - dest->cr) / scalew;
01371             dest_width = dest->cr - dest_x;
01372         }
01373         if (dest_y + dest_height > dest->cb) {
01374             source_height -= (dest_y + dest_height - dest->cb) / scaleh;
01375             dest_height = dest->cb - dest_y;
01376         }
01377     }
01378 
01379     glGetIntegerv(GL_MATRIX_MODE, &matrix_mode);
01380     glMatrixMode(GL_MODELVIEW);
01381     glPushMatrix();
01382     glTranslated(dest_x, dest_y, 0.);
01383     glScaled(scalew, scaleh, 1.);
01384     glTranslated(-dest_x, -dest_y, 0.);
01385 
01386     if (masked) {
01387         if (is_screen_bitmap(dest)) {
01388             do_masked_blit_screen(source, dest, source_x, source_y,
01389                                   dest_x, dest_y, source_width, source_height,
01390                                   FALSE, AGL_REGULAR_BMP);
01391         }
01392         else {
01393             do_masked_blit_video(source, dest, source_x, source_y,
01394                                  dest_x, dest_y, source_width, source_height,
01395                                  FALSE, AGL_REGULAR_BMP);
01396         }
01397     }
01398     else {
01399         allegro_gl_screen_blit_to_self(source, dest, source_x, source_y,
01400                            dest_x, dest_y, source_width, source_height);
01401     }
01402 
01403     glPopMatrix();
01404     glMatrixMode(matrix_mode);
01405 
01406     return;
01407 }
01408 
01409 
01410 
01411 /* allegro_gl_video_draw_trans_rgba_sprite:
01412  * draw_trans_sprite() overload for video -> video drawing
01413  */
01414 static void allegro_gl_video_draw_trans_rgba_sprite(BITMAP *bmp,
01415                                 BITMAP *sprite, int x, int y) {
01416     /* Adapt variables for FOR_EACH_TEXTURE_FRAGMENT macro. */
01417     BITMAP *source = sprite;
01418     BITMAP *dest = bmp;
01419     int dest_x = x;
01420     int dest_y = y;
01421     int source_x = 0;
01422     int source_y = 0;
01423     int width = sprite->w;
01424     int height = sprite->h;
01425     GLint format = __allegro_gl_get_bitmap_color_format(sprite, AGL_TEXTURE_HAS_ALPHA);
01426     GLint type = __allegro_gl_get_bitmap_type(sprite, 0);
01427 
01428     if (__allegro_gl_blit_operation == AGL_OP_LOGIC_OP)
01429         glEnable(GL_COLOR_LOGIC_OP);
01430     else
01431         glEnable(GL_BLEND);
01432 
01433     FOR_EACH_TEXTURE_FRAGMENT (
01434         allegro_gl_screen_blit_to_self(source, screen, sx, sy, dx, dy, w, h),
01435         allegro_gl_upload_and_display_texture(sprite, sx, sy, dx, dy, w, h, 0, format, type),
01436         __video_update_memory_copy(vid->memory_copy, dest, sx, sy, dx, dy, w, h, TRANS),
01437         __video_update_memory_copy(source, dest, 0, 0, x, y, sprite->w, sprite->h, TRANS),
01438         allegro_gl_video_blit_from_memory_ex(vid->memory_copy, dest, sx, sy, dx, dy, w, h, TRANS),
01439         allegro_gl_video_blit_from_memory_ex(source, dest, 0, 0, x, y, sprite->w, sprite->h, TRANS)
01440     )
01441 
01442     if (__allegro_gl_blit_operation == AGL_OP_LOGIC_OP)
01443         glDisable(GL_COLOR_LOGIC_OP);
01444     else
01445         glDisable(GL_BLEND);
01446 
01447     return;
01448 }
01449 
01450 
01451 
01452 /* allegro_gl_video_draw_sprite_ex:
01453  * draw_sprite_ex() overload for video -> video and memory -> video drawing
01454  *
01455  * When mode is DRAW_SPRITE_TRANS:
01456  * FIXME: Broken if the bitmap was split into multiple textures.
01457  * FIXME: Doesn't apply flipping to the memory copy
01458  */
01459 static void allegro_gl_video_draw_sprite_ex(BITMAP *bmp, BITMAP *sprite,
01460                                             int x, int y, int mode, int flip) {
01461     int matrix_mode;
01462     int lflip = 0;
01463 
01464     /* convert allegro's flipping flags to AGL's flags */
01465     switch (flip) {
01466         case DRAW_SPRITE_NO_FLIP:
01467             lflip = FALSE;
01468         break;
01469         case DRAW_SPRITE_V_FLIP:
01470             lflip = AGL_V_FLIP;
01471         break;
01472         case DRAW_SPRITE_H_FLIP:
01473             lflip = AGL_H_FLIP;
01474         break;
01475         case DRAW_SPRITE_VH_FLIP:
01476             lflip = AGL_V_FLIP | AGL_H_FLIP;
01477         break;
01478     }
01479 
01480     switch (mode) {
01481         case DRAW_SPRITE_NORMAL:
01482             do_masked_blit_video(sprite, bmp, 0, 0, x, y,
01483                                  sprite->w, sprite->h, lflip, FALSE);
01484         break;
01485         case DRAW_SPRITE_TRANS:
01486             if (lflip) {
01487                 glGetIntegerv(GL_MATRIX_MODE, &matrix_mode);
01488                 glMatrixMode(GL_MODELVIEW);
01489                 glPushMatrix();
01490         
01491                 glTranslatef(x, y, 0.f);
01492                 glScalef((lflip&AGL_H_FLIP) ? -1 : 1, (lflip&AGL_V_FLIP)? -1 : 1, 1);
01493                 glTranslatef(-x, -y, 0);
01494                 glTranslatef((lflip&AGL_H_FLIP) ? -sprite->w : 0,
01495                              (lflip&AGL_V_FLIP) ? -sprite->h : 0, 0);
01496             }
01497 
01498             allegro_gl_video_draw_trans_rgba_sprite(bmp, sprite, x, y);
01499 
01500             if (lflip) {
01501                 glPopMatrix();
01502                 glMatrixMode(matrix_mode);
01503             }
01504         break;
01505         case DRAW_SPRITE_LIT:
01506             /* not implemented */
01507         break;
01508     }
01509 }
01510 
01511 
01512 
01513 static void allegro_gl_video_clear_to_color(BITMAP *bmp, int color) {
01514     AGL_VIDEO_BITMAP *vid = bmp->extra;
01515 
01516     if (vid->fbo) {
01517         static GLint v[4];
01518         static double allegro_gl_projection_matrix[16];
01519         static double allegro_gl_modelview_matrix[16];
01520 
01521         glGetIntegerv(GL_VIEWPORT, &v[0]);
01522         glMatrixMode(GL_MODELVIEW);
01523         glGetDoublev(GL_MODELVIEW_MATRIX, allegro_gl_modelview_matrix);
01524         glMatrixMode(GL_PROJECTION);
01525         glGetDoublev(GL_PROJECTION_MATRIX, allegro_gl_projection_matrix);
01526 
01527         while (vid) {
01528             glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, vid->fbo);
01529 
01530             glViewport(0, 0, vid->memory_copy->w, vid->memory_copy->h);
01531             glMatrixMode(GL_PROJECTION);
01532             glLoadIdentity();
01533             gluOrtho2D(0, vid->memory_copy->w, 0, vid->memory_copy->h);
01534             glMatrixMode(GL_MODELVIEW);
01535 
01536             allegro_gl_screen_clear_to_color(bmp, color);
01537             clear_to_color(vid->memory_copy, color);
01538             vid = vid->next;
01539         }
01540 
01541         glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
01542     
01543         glViewport(v[0], v[1], v[2], v[3]);
01544         glMatrixMode(GL_PROJECTION);
01545         glLoadMatrixd(allegro_gl_projection_matrix);
01546         glMatrixMode(GL_MODELVIEW);
01547         glLoadMatrixd(allegro_gl_modelview_matrix);
01548     }
01549     else {
01550         allegro_gl_video_rectfill(bmp, 0, 0, bmp->w, bmp->h, color);
01551     }
01552 }
01553 
01554 
01555 
01556 /* FIXME: Doesn't work when FBO is not available.
01557  * FIXME: Doesn't care for segmented video bitmaps.
01558  */
01559 static void allegro_gl_video_draw_color_glyph(struct BITMAP *bmp,
01560     struct BITMAP *sprite, int x, int y, int color, int bg)
01561 {
01562     AGL_VIDEO_BITMAP *vid = bmp->extra;
01563 
01564     static GLint v[4];
01565     static double allegro_gl_projection_matrix[16];
01566     static double allegro_gl_modelview_matrix[16];
01567 
01568     if (!vid->fbo)
01569         return;
01570 
01571     glGetIntegerv(GL_VIEWPORT, &v[0]);
01572     glMatrixMode(GL_MODELVIEW);
01573     glGetDoublev(GL_MODELVIEW_MATRIX, allegro_gl_modelview_matrix);
01574     glMatrixMode(GL_PROJECTION);
01575     glGetDoublev(GL_PROJECTION_MATRIX, allegro_gl_projection_matrix);
01576 
01577     glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, vid->fbo);
01578 
01579     glViewport(0, 0, vid->memory_copy->w, vid->memory_copy->h);
01580     glMatrixMode(GL_PROJECTION);
01581     glLoadIdentity();
01582     gluOrtho2D(0, vid->memory_copy->w, 0, vid->memory_copy->h);
01583     glMatrixMode(GL_MODELVIEW);
01584 
01585     allegro_gl_screen_draw_color_glyph_ex(bmp, sprite, x, y, color, bg, 0);
01586 
01587     glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
01588 
01589     glViewport(v[0], v[1], v[2], v[3]);
01590     glMatrixMode(GL_PROJECTION);
01591     glLoadMatrixd(allegro_gl_projection_matrix);
01592     glMatrixMode(GL_MODELVIEW);
01593     glLoadMatrixd(allegro_gl_modelview_matrix);
01594 
01595     vid->memory_copy->vtable->draw_character(vid->memory_copy, sprite, x, y, color, bg);
01596 }
01597 
01598 
01599 
01600 static void allegro_gl_video_draw_256_sprite(BITMAP *bmp, BITMAP *sprite,
01601                                       int x, int y) {
01602     allegro_gl_video_draw_color_glyph(bmp, sprite, x, y, -1, _textmode);
01603 }
01604 
01605 
01606 
01607 static void allegro_gl_video_draw_character(BITMAP *bmp, BITMAP *sprite,
01608                                             int x, int y, int color, int bg) {
01609     allegro_gl_video_draw_color_glyph(bmp, sprite, x, y, color, bg);
01610 }
01611 
01612 
01613 
01614 /* FIXME: Doesn't work when FBO is not available.
01615  * FIXME: Doesn't care for segmented video bitmaps.
01616  */
01617 static void allegro_gl_video_draw_glyph(struct BITMAP *bmp,
01618                                AL_CONST struct FONT_GLYPH *glyph, int x, int y,
01619                                int color, int bg) {
01620     AGL_VIDEO_BITMAP *vid = bmp->extra;
01621 
01622     static GLint v[4];
01623     static double allegro_gl_projection_matrix[16];
01624     static double allegro_gl_modelview_matrix[16];
01625 
01626     if (!vid->fbo)
01627         return;
01628 
01629     glGetIntegerv(GL_VIEWPORT, &v[0]);
01630     glMatrixMode(GL_MODELVIEW);
01631     glGetDoublev(GL_MODELVIEW_MATRIX, allegro_gl_modelview_matrix);
01632     glMatrixMode(GL_PROJECTION);
01633     glGetDoublev(GL_PROJECTION_MATRIX, allegro_gl_projection_matrix);
01634 
01635     glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, vid->fbo);
01636 
01637     glViewport(0, 0, vid->memory_copy->w, vid->memory_copy->h);
01638     glMatrixMode(GL_PROJECTION);
01639     glLoadIdentity();
01640     gluOrtho2D(0, vid->memory_copy->w, 0, vid->memory_copy->h);
01641     glMatrixMode(GL_MODELVIEW);
01642 
01643     allegro_gl_screen_draw_glyph_ex(bmp, glyph, x, y, color, bg, 1);
01644 
01645     glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
01646 
01647     glViewport(v[0], v[1], v[2], v[3]);
01648     glMatrixMode(GL_PROJECTION);
01649     glLoadMatrixd(allegro_gl_projection_matrix);
01650     glMatrixMode(GL_MODELVIEW);
01651     glLoadMatrixd(allegro_gl_modelview_matrix);
01652 
01653     vid->memory_copy->vtable->draw_glyph(vid->memory_copy, glyph, x, y, color, bg);
01654 }
01655 
01656 
01657 
01658 static void allegro_gl_video_polygon3d_f(BITMAP *bmp, int type, BITMAP *texture,
01659                                   int vc, V3D_f *vtx[])
01660 {
01661     AGL_VIDEO_BITMAP *vid = bmp->extra;
01662 
01663     /* Switch to software mode is using polygon type that isn't supported by
01664        allegro_gl_screen_polygon3d_f. */
01665     int use_fbo = (type == POLYTYPE_FLAT) ||
01666                   (type == POLYTYPE_GRGB) ||
01667                   (type == POLYTYPE_GCOL) ||
01668                   (type == POLYTYPE_ATEX) ||
01669                   (type == POLYTYPE_PTEX) ||
01670                   (type == POLYTYPE_ATEX_TRANS) ||
01671                   (type == POLYTYPE_PTEX_TRANS);
01672 
01673     if (vid->fbo && use_fbo) {
01674         static GLint v[4];
01675         static double allegro_gl_projection_matrix[16];
01676         static double allegro_gl_modelview_matrix[16];
01677 
01678         glGetIntegerv(GL_VIEWPORT, &v[0]);
01679         glMatrixMode(GL_MODELVIEW);
01680         glGetDoublev(GL_MODELVIEW_MATRIX, allegro_gl_modelview_matrix);
01681         glMatrixMode(GL_PROJECTION);
01682         glGetDoublev(GL_PROJECTION_MATRIX, allegro_gl_projection_matrix);
01683 
01684         while (vid) {
01685             BITMAP *mem_texture;
01686 
01687             glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, vid->fbo);
01688 
01689             glViewport(0, 0, vid->memory_copy->w, vid->memory_copy->h);
01690             glMatrixMode(GL_PROJECTION);
01691             glLoadIdentity();
01692             gluOrtho2D(0, vid->memory_copy->w, 0, vid->memory_copy->h);
01693             glMatrixMode(GL_MODELVIEW);
01694 
01695             allegro_gl_screen_polygon3d_f(bmp, type, texture, vc, vtx);
01696 
01697             if (is_video_bitmap(texture)) {
01698                 AGL_VIDEO_BITMAP *vbmp = texture->extra;
01699                 mem_texture = vbmp->memory_copy;
01700             }
01701             else {
01702                 mem_texture = texture;
01703             }
01704             polygon3d_f(vid->memory_copy, type, mem_texture, vc, vtx);
01705 
01706             vid = vid->next;
01707         }
01708 
01709         glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
01710     
01711         glViewport(v[0], v[1], v[2], v[3]);
01712         glMatrixMode(GL_PROJECTION);
01713         glLoadMatrixd(allegro_gl_projection_matrix);
01714         glMatrixMode(GL_MODELVIEW);
01715         glLoadMatrixd(allegro_gl_modelview_matrix);
01716     }
01717     else {
01718         int i;
01719         AGL_VIDEO_BITMAP *vid;
01720     
01721         vid = bmp->extra;
01722     
01723         if (is_sub_bitmap(bmp)) {
01724             for (i = 0; i < vc; ++i) {
01725                 vtx[i]->x += bmp->x_ofs;
01726                 vtx[i]->y += bmp->y_ofs;
01727             }
01728         }
01729 
01730         while (vid) {
01731             BITMAP *mem_texture;
01732             int _y1, _y2, _x1, _x2;
01733             BITMAP *vbmp = vid->memory_copy;
01734 
01735             _x1 = 9999;
01736             for (i = 0; i < vc; ++i)
01737                 if (vtx[i]->x < _x1) _x1 = vtx[i]->x;
01738 
01739             _x2 = -9999;
01740             for (i = 0; i < vc; ++i)
01741                 if (vtx[i]->x > _x2) _x2 = vtx[i]->x;
01742 
01743             _y1 = 9999;
01744             for (i = 0; i < vc; ++i)
01745                 if (vtx[i]->y < _y1) _y1 = vtx[i]->y;
01746 
01747             _y2 = -9999;
01748             for (i = 0; i < vc; ++i)
01749                 if (vtx[i]->y > _y2) _y2 = vtx[i]->y;
01750 
01751             if (vid->x_ofs > _x2 || vid->y_ofs > _y2
01752              || vid->x_ofs + vbmp->w <= _x1
01753              || vid->y_ofs + vbmp->h <= _y1) {
01754                 
01755                 vid = vid->next;
01756                 continue;
01757             }
01758             
01759             _x1 = MAX(0, _x1 - vid->x_ofs);
01760             _x2 = (_x2 - (vid->x_ofs + vbmp->w) > 0) ? vbmp->w - 1: _x2 - vid->x_ofs;
01761             _y1 = MAX(0, _y1 - vid->y_ofs);
01762             _y2 = (_x2 - (vid->y_ofs + vbmp->h) > 0) ? vbmp->h - 1: _y2 - vid->y_ofs;
01763 
01764             if (is_video_bitmap(texture)) {
01765                 AGL_VIDEO_BITMAP *tex = texture->extra;
01766                 mem_texture = tex->memory_copy;
01767             }
01768             else {
01769                 mem_texture = texture;
01770             }
01771             polygon3d_f(vid->memory_copy, type, mem_texture, vc, vtx);
01772     
01773             update_texture_memory(vid, _x1, _y1, _x2, _y2);
01774     
01775             vid = vid->next;
01776         }
01777     }
01778 
01779     return;
01780 }
01781 
01782 
01783 
01784 static void allegro_gl_video_polygon3d(BITMAP *bmp, int type, BITMAP *texture,
01785                                 int vc, V3D *vtx[])
01786 {
01787     int i;
01788     V3D_f **vtx_f = malloc(vc * sizeof(struct V3D_f*));
01789     if (!vtx_f)
01790         return;
01791 
01792     for (i = 0; i < vc; i++) {
01793         vtx_f[i] = malloc(sizeof(struct V3D_f));
01794         if (!vtx_f[i]) {
01795             int k;
01796             for (k = 0; k < i; k++)
01797                 free(vtx_f[k]);
01798             free(vtx_f);
01799             return;
01800         }
01801         vtx_f[i]->c = vtx[i]->c;
01802         vtx_f[i]->u = fixtof(vtx[i]->u);
01803         vtx_f[i]->v = fixtof(vtx[i]->v);
01804         vtx_f[i]->x = fixtof(vtx[i]->x);
01805         vtx_f[i]->y = fixtof(vtx[i]->y);
01806         vtx_f[i]->z = fixtof(vtx[i]->z);
01807     }
01808 
01809     allegro_gl_video_polygon3d_f(bmp, type, texture, vc, vtx_f);
01810 
01811     for (i = 0; i < vc; i++)
01812         free(vtx_f[i]);
01813     free(vtx_f);
01814 }
01815 
01816 
01817 
01818 static void allegro_gl_video_triangle3d(BITMAP *bmp, int type, BITMAP *texture,
01819                                         V3D *v1, V3D *v2, V3D *v3)
01820 {
01821     V3D *vtx[3];
01822     vtx[0] = v1;
01823     vtx[1] = v2;
01824     vtx[2] = v3;
01825     
01826     allegro_gl_video_polygon3d(bmp, type, texture, 3, vtx);
01827 }
01828 
01829 
01830 
01831 static void allegro_gl_video_triangle3d_f(BITMAP *bmp, int type, BITMAP *texture,
01832                                           V3D_f *v1, V3D_f *v2, V3D_f *v3)
01833 {
01834     V3D_f *vtx_f[3];
01835     vtx_f[0] = v1;
01836     vtx_f[1] = v2;
01837     vtx_f[2] = v3;
01838 
01839     allegro_gl_video_polygon3d_f(bmp, type, texture, 3, vtx_f);
01840 }
01841 
01842 
01843 
01844 static void allegro_gl_video_quad3d(BITMAP *bmp, int type, BITMAP *texture,
01845                                     V3D *v1, V3D *v2, V3D *v3, V3D *v4)
01846 {
01847     V3D *vtx[4];
01848     vtx[0] = v1;
01849     vtx[1] = v2;
01850     vtx[2] = v3;
01851     vtx[3] = v4;
01852 
01853     allegro_gl_video_polygon3d(bmp, type, texture, 4, vtx);
01854 }
01855 
01856 
01857 
01858 static void allegro_gl_video_quad3d_f(BITMAP *bmp, int type, BITMAP *texture,
01859                                V3D_f *v1, V3D_f *v2, V3D_f *v3, V3D_f *v4)
01860 {
01861     V3D_f *vtx_f[4];
01862     vtx_f[0] = v1;
01863     vtx_f[1] = v2;
01864     vtx_f[2] = v3;
01865     vtx_f[3] = v4;
01866 
01867     allegro_gl_video_polygon3d_f(bmp, type, texture, 4, vtx_f);
01868 }
01869 
01870 
01871 
01872 static void dummy_unwrite_bank(void)
01873 {
01874 }
01875 
01876 
01877 
01878 static GFX_VTABLE allegro_gl_video_vtable = {
01879     0,
01880     0,
01881     dummy_unwrite_bank,         //void *unwrite_bank;  /* C function on some machines, asm on i386 */
01882     NULL,                       //AL_METHOD(void, set_clip, (struct BITMAP *bmp));
01883     allegro_gl_video_acquire,
01884     allegro_gl_video_release,
01885     NULL,                       //AL_METHOD(struct BITMAP *, create_sub_bitmap, (struct BITMAP *parent, int x, int y, int width, int height));
01886     allegro_gl_created_sub_bitmap,
01887     allegro_gl_video_getpixel,
01888     allegro_gl_video_putpixel,
01889     allegro_gl_video_vline,
01890     allegro_gl_video_hline,
01891     allegro_gl_video_hline,
01892     allegro_gl_video_line,
01893     allegro_gl_video_line,
01894     allegro_gl_video_rectfill,
01895     allegro_gl_video_triangle,
01896     allegro_gl_video_draw_sprite,
01897     allegro_gl_video_draw_256_sprite,
01898     allegro_gl_video_draw_sprite_v_flip,
01899     allegro_gl_video_draw_sprite_h_flip,
01900     allegro_gl_video_draw_sprite_vh_flip,
01901     allegro_gl_video_draw_trans_rgba_sprite,
01902     allegro_gl_video_draw_trans_rgba_sprite,
01903     NULL,                       //AL_METHOD(void, draw_lit_sprite, (struct BITMAP *bmp, struct BITMAP *sprite, int x, int y, int color));
01904     NULL,                       //AL_METHOD(void, allegro_gl_video_draw_rle_sprite, (struct BITMAP *bmp, struct RLE_SPRITE *sprite, int x, int y));
01905     NULL,                       //AL_METHOD(void, draw_trans_rle_sprite, (struct BITMAP *bmp, struct RLE_SPRITE *sprite, int x, int y));
01906     NULL,                       //AL_METHOD(void, draw_trans_rgba_rle_sprite, (struct BITMAP *bmp, struct RLE_SPRITE *sprite, int x, int y));
01907     NULL,                       //AL_METHOD(void, draw_lit_rle_sprite, (struct BITMAP *bmp, struct RLE_SPRITE *sprite, int x, int y, int color));
01908     allegro_gl_video_draw_character,
01909     allegro_gl_video_draw_glyph,
01910     allegro_gl_video_blit_from_memory,
01911     allegro_gl_video_blit_to_memory,
01912     NULL,                       //AL_METHOD(void, blit_from_system, (struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height));
01913     NULL,                       //AL_METHOD(void, blit_to_system, (struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height));
01914     allegro_gl_screen_blit_to_self, /* Video bitmaps use same method as screen */
01915     allegro_gl_screen_blit_to_self, /* ..._forward */
01916     allegro_gl_screen_blit_to_self, /* ..._backward */
01917     allegro_gl_memory_blit_between_formats,
01918     allegro_gl_video_masked_blit,
01919     allegro_gl_video_clear_to_color,
01920     allegro_gl_video_pivot_scaled_sprite_flip,
01921     allegro_gl_video_do_stretch_blit,
01922     NULL,                       //AL_METHOD(void, draw_gouraud_sprite, (struct BITMAP *bmp, struct BITMAP *sprite, int x, int y, int c1, int c2, int c3, int c4));
01923     NULL,                       //AL_METHOD(void, draw_sprite_end, (void));
01924     NULL,                       //AL_METHOD(void, blit_end, (void));
01925     _soft_polygon,              //AL_METHOD(void, polygon, (struct BITMAP *bmp, int vertices, AL_CONST int *points, int color));
01926     _soft_rect,                 //AL_METHOD(void, rect, (struct BITMAP *bmp, int x1, int y1, int x2, int y2, int color));
01927     _soft_circle,               //AL_METHOD(void, circle, (struct BITMAP *bmp, int x, int y, int radius, int color));
01928     _soft_circlefill,           //AL_METHOD(void, circlefill, (struct BITMAP *bmp, int x, int y, int radius, int color));
01929     _soft_ellipse,              //AL_METHOD(void, ellipse, (struct BITMAP *bmp, int x, int y, int rx, int ry, int color));
01930     _soft_ellipsefill,          //AL_METHOD(void, ellipsefill, (struct BITMAP *bmp, int x, int y, int rx, int ry, int color));
01931     _soft_arc,                  //AL_METHOD(void, arc, (struct BITMAP *bmp, int x, int y, fixed ang1, fixed ang2, int r, int color));
01932     _soft_spline,               //AL_METHOD(void, spline, (struct BITMAP *bmp, AL_CONST int points[8], int color));
01933     _soft_floodfill,            //AL_METHOD(void, floodfill, (struct BITMAP *bmp, int x, int y, int color));
01934     allegro_gl_video_polygon3d,
01935     allegro_gl_video_polygon3d_f,
01936     allegro_gl_video_triangle3d,
01937     allegro_gl_video_triangle3d_f,
01938     allegro_gl_video_quad3d,
01939     allegro_gl_video_quad3d_f,
01940     allegro_gl_video_draw_sprite_ex
01941 };
01942 
allegro4.4-4.4.2/addons/allegrogl/docs/html/win_8c_source.html000066400000000000000000004412671173507505700241750ustar00rootroot00000000000000 AllegroGL: win.c Source File

win.c

00001 /* This code is (C) AllegroGL contributors, and double licensed under
00002  * the GPL and zlib licenses. See gpl.txt or zlib.txt for details.
00003  */
00004 #include <string.h>
00005 #include <allegro.h>
00006 #include <allegro/internal/aintern.h>
00007 
00008 
00009 #include "alleggl.h"
00010 #include "glvtable.h"
00011 #include "allglint.h"
00012 
00013 
00014 static BITMAP *allegro_gl_win_init_windowed(int w, int h, int v_w, int v_h,
00015                                             int color_depth);
00016 static BITMAP *allegro_gl_win_init_fullscreen(int w, int h, int v_w, int v_h,
00017                                               int color_depth);
00018 static void allegro_gl_win_exit(struct BITMAP *b);
00019 static GFX_MODE_LIST* allegro_gl_win_fetch_mode_list(void);
00020 
00021 static struct allegro_gl_driver allegro_gl_win;
00022 
00023 #define PREFIX_I                "agl-win INFO: "
00024 #define PREFIX_W                "agl-win WARNING: "
00025 #define PREFIX_E                "agl-win ERROR: "
00026 
00027 
00028 static BITMAP *allegro_gl_screen = NULL;
00029 
00030 
00031 /* Windowed mode driver */
00032 GFX_DRIVER gfx_allegro_gl_windowed = {
00033     GFX_OPENGL_WINDOWED,
00034     EMPTY_STRING,
00035     EMPTY_STRING,
00036     "AllegroGL Windowed (Win32)",
00037     allegro_gl_win_init_windowed,
00038     allegro_gl_win_exit,
00039     NULL,                       /* scrolling not implemented */
00040     NULL,                       /* vsync, may use for flip? */
00041     NULL,                       /* No h/w pallete, not using indexed mode */
00042     NULL, NULL,                 /* Still no scrolling */
00043     NULL,                       /* No triple buffering */
00044     allegro_gl_create_video_bitmap,
00045     allegro_gl_destroy_video_bitmap,
00046     NULL, NULL,                 /* No show/request video bitmaps */
00047     NULL, NULL,                 /* No system bitmaps */
00048     allegro_gl_set_mouse_sprite,
00049     allegro_gl_show_mouse,
00050     allegro_gl_hide_mouse,
00051     allegro_gl_move_mouse,
00052     allegro_gl_drawing_mode,
00053     NULL, NULL,           /* No video state stuff */
00054     allegro_gl_set_blender_mode,
00055     NULL,                       /* No fetch_mode_list */
00056     0,0,                        /* physical (not virtual!) screen size */
00057     0,                          /* true if video memory is linear */
00058     0,                          /* bank size, in bytes */
00059     0,                          /* bank granularity, in bytes */
00060     0,                          /* video memory size, in bytes */
00061     0,                          /* physical address of video memory */
00062     TRUE                        /* Windowed mode */
00063 };
00064 
00065 
00066 /* Fullscreen driver */
00067 GFX_DRIVER gfx_allegro_gl_fullscreen = {
00068     GFX_OPENGL_FULLSCREEN,
00069     EMPTY_STRING,
00070     EMPTY_STRING,
00071     "AllegroGL Fullscreen (Win32)",
00072     allegro_gl_win_init_fullscreen,
00073     allegro_gl_win_exit,
00074     NULL,                       /* scrolling not implemented */
00075     NULL,                       /* vsync, may use for flip? */
00076     NULL,                       /* No h/w pallete, not using indexed mode */
00077     NULL, NULL,                 /* Still no scrolling */
00078     NULL,                       /* No triple buffering */
00079     allegro_gl_create_video_bitmap,
00080     allegro_gl_destroy_video_bitmap,
00081     NULL, NULL,                 /* No show/request video bitmaps */
00082     NULL, NULL,                 /* No system bitmaps */
00083     allegro_gl_set_mouse_sprite,
00084     allegro_gl_show_mouse,
00085     allegro_gl_hide_mouse,
00086     allegro_gl_move_mouse,
00087     allegro_gl_drawing_mode,
00088     NULL, NULL,           /* No video state stuff */
00089     allegro_gl_set_blender_mode,
00090     allegro_gl_win_fetch_mode_list, /* fetch_mode_list */
00091     0,0,                        /* physical (not virtual!) screen size */
00092     0,                          /* true if video memory is linear */
00093     0,                          /* bank size, in bytes */
00094     0,                          /* bank granularity, in bytes */
00095     0,                          /* video memory size, in bytes */
00096     0,                          /* physical address of video memory */
00097     FALSE                       /* Windowed mode */
00098 };
00099 
00100 
00101 /* XXX <rohannessian> We should move those variable definitions into a struct,
00102  * for when multiple windows end up being supported.
00103  */
00104 
00105 /* Device Context used for the Allegro window. Note that only one window
00106  * is supported, so only onyl HDC is needed. This is shared by the AGL
00107  * extension code.
00108  */
00109 HDC __allegro_gl_hdc = NULL;
00110 
00111 /* Render Context used by AllegroGL, once screen mode was set. Note that only
00112  * a single window is supported.
00113  */
00114 static HGLRC allegro_glrc = NULL;
00115 
00116 /* Full-screen flag, for the current context. */
00117 static int fullscreen = 0;
00118 
00119 /* Current window handle */
00120 static HWND wnd = NULL;
00121 
00122 /* If AGL was initialized */
00123 static int initialized = 0;
00124 
00125 /* XXX <rohannessian> Put those globals as function parameters */
00126 /* Note - these globals should really end up as parameters to functions.
00127  */
00128 static DWORD style_saved, exstyle_saved;
00129 static DEVMODE dm_saved;
00130 static int test_windows_created = 0;
00131 static int new_w = 0, new_h = 0;
00132 
00133 static PIXELFORMATDESCRIPTOR pfd = {
00134     sizeof(PIXELFORMATDESCRIPTOR),  /* size of this pfd */
00135     1,                          /* version number */
00136     PFD_DRAW_TO_WINDOW          /* support window */
00137         | PFD_SUPPORT_OPENGL    /* support OpenGL */
00138         | PFD_DOUBLEBUFFER,     /* double buffered */
00139     PFD_TYPE_RGBA,              /* RGBA type */
00140     24,                         /* 24-bit color depth */
00141     0, 0, 0, 0, 0, 0,           /* color bits ignored */
00142     0,                          /* no alpha buffer */
00143     0,                          /* shift bit ignored */
00144     0,                          /* no accumulation buffer */
00145     0, 0, 0, 0,                 /* accum bits ignored */
00146     0,                          /* z-buffer */
00147     0,                          /* no stencil buffer */
00148     0,                          /* no auxiliary buffer */
00149     PFD_MAIN_PLANE,             /* main layer */
00150     0,                          /* reserved */
00151     0, 0, 0                     /* layer masks ignored */
00152 };
00153 
00154 
00155 
00156 /* Logs a Win32 error/warning message in the log file.
00157  */
00158 static void log_win32_msg(const char *prefix, const char *func,
00159                           const char *error_msg, DWORD err) {
00160 
00161     char *err_msg = NULL;
00162     BOOL free_msg = TRUE;
00163 
00164     /* Get the formatting error string from Windows. Note that only the
00165      * bottom 14 bits matter - the rest are reserved for various library
00166      * IDs and type of error.
00167      */
00168     if (!FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER
00169                      | FORMAT_MESSAGE_FROM_SYSTEM
00170                      | FORMAT_MESSAGE_IGNORE_INSERTS,
00171                      NULL, err & 0x3FFF,
00172                      MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
00173                      (LPTSTR) &err_msg, 0, NULL)) {
00174         err_msg = "(Unable to decode error code)  ";
00175         free_msg = FALSE;
00176     }
00177 
00178     /* Remove two trailing characters */
00179     if (err_msg && strlen(err_msg) > 1)
00180         *(err_msg + strlen(err_msg) - 2) = '\0';
00181 
00182     TRACE("%s%s(): %s %s (0x%08lx)\n", prefix, func,
00183           error_msg ? error_msg : "",
00184           err_msg ? err_msg : "(null)",
00185           (unsigned long)err);
00186 
00187     if (free_msg) {
00188         LocalFree(err_msg);
00189     }
00190 
00191     return;
00192 }
00193 
00194 
00195 
00196 /* Logs an error */
00197 static void log_win32_error(const char *func, const char *error_msg,
00198                             DWORD err) {
00199     log_win32_msg(PREFIX_E, func, error_msg, err);
00200 }
00201 
00202 
00203 
00204 /* Logs a warning */
00205 static void log_win32_warning(const char *func, const char *error_msg,
00206                               DWORD err) {
00207     log_win32_msg(PREFIX_W, func, error_msg, err);
00208 }
00209 
00210 
00211 
00212 /* Logs a note */
00213 static void log_win32_note(const char *func, const char *error_msg, DWORD err) {
00214     log_win32_msg(PREFIX_I, func, error_msg, err);
00215 }
00216 
00217 
00218 
00219 /* Define the AllegroGL Test window class */
00220 #define ALLEGROGL_TEST_WINDOW_CLASS "AllegroGLTestWindow"
00221 
00222 
00223 /* Registers the test window
00224  * Returns 0 on success, non-zero on failure.
00225  */
00226 static int register_test_window()
00227 {
00228     WNDCLASS wc;
00229 
00230     memset(&wc, 0, sizeof(wc));
00231     wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
00232     wc.lpfnWndProc = DefWindowProc;
00233     wc.hInstance = GetModuleHandle(NULL);
00234     wc.hIcon = LoadIcon(GetModuleHandle(NULL), IDI_APPLICATION);
00235     wc.hCursor = LoadCursor(NULL, IDC_ARROW);
00236     wc.lpszClassName = ALLEGROGL_TEST_WINDOW_CLASS;
00237 
00238     if (!RegisterClass(&wc)) {
00239         DWORD err = GetLastError();
00240 
00241         if (err != ERROR_CLASS_ALREADY_EXISTS) {
00242             log_win32_error("register_test_window",
00243                             "Unable to register the window class!", err);
00244             return -1;
00245         }
00246     }
00247 
00248     return 0;
00249 }
00250 
00251 
00252 
00253 
00254 /* Creates the test window.
00255  * The window class must have already been registered.
00256  * Returns the window handle, or NULL on failure.
00257  */
00258 static HWND create_test_window()
00259 {
00260     HWND wnd = CreateWindow(ALLEGROGL_TEST_WINDOW_CLASS,
00261                             "AllegroGL Test Window",
00262                             WS_POPUP | WS_CLIPCHILDREN,
00263                             0, 0, new_w, new_h,
00264                             NULL, NULL,
00265                             GetModuleHandle(NULL),
00266                             NULL);
00267 
00268     if (!wnd) {
00269         log_win32_error("create_test_window",
00270                         "Unable to create a test window!", GetLastError());
00271         return NULL;
00272     }       
00273 
00274     test_windows_created++;
00275     return wnd;
00276 }
00277 
00278 
00279 
00280 /* Print the pixel format info */
00281 static void print_pixel_format(struct allegro_gl_display_info *dinfo) {
00282 
00283     if (!dinfo) {
00284         return;
00285     }
00286     
00287     TRACE(PREFIX_I "Acceleration: %s\n", ((dinfo->rmethod == 0) ? "No"
00288                              : ((dinfo->rmethod == 1) ? "Yes" : "Unknown")));
00289     TRACE(PREFIX_I "RGBA: %i.%i.%i.%i\n", dinfo->pixel_size.rgba.r,
00290           dinfo->pixel_size.rgba.g, dinfo->pixel_size.rgba.b,
00291           dinfo->pixel_size.rgba.a);
00292     
00293     TRACE(PREFIX_I "Accum: %i.%i.%i.%i\n", dinfo->accum_size.rgba.r,
00294           dinfo->accum_size.rgba.g, dinfo->accum_size.rgba.b,
00295           dinfo->accum_size.rgba.a);
00296     
00297     TRACE(PREFIX_I "DblBuf: %i Zbuf: %i Stereo: %i Aux: %i Stencil: %i\n",
00298           dinfo->doublebuffered, dinfo->depth_size, dinfo->stereo,
00299           dinfo->aux_buffers, dinfo->stencil_size);
00300     
00301     TRACE(PREFIX_I "Shift: %i.%i.%i.%i\n", dinfo->r_shift, dinfo->g_shift,
00302           dinfo->b_shift, dinfo->a_shift);
00303 
00304     TRACE(PREFIX_I "Sample Buffers: %i Samples: %i\n",
00305           dinfo->sample_buffers, dinfo->samples);
00306     
00307     TRACE(PREFIX_I "Decoded bpp: %i\n", dinfo->colour_depth);   
00308 }
00309 
00310 
00311 
00312 /* Decodes the pixel format into an agl_display_info struct and logs the pixel
00313  * format in the trace file.
00314  */
00315 static int decode_pixel_format(PIXELFORMATDESCRIPTOR * pfd, HDC hdc, int format,
00316                                struct allegro_gl_display_info *dinfo,
00317                                int desktop_depth)
00318 {
00319     TRACE(PREFIX_I "Decoding: \n");
00320     /* Not interested if it doesn't support OpenGL and RGBA */
00321     if (!(pfd->dwFlags & PFD_SUPPORT_OPENGL)) {
00322         TRACE(PREFIX_I "OpenGL Unsupported\n");
00323         return -1;
00324     }
00325     if (pfd->iPixelType != PFD_TYPE_RGBA) {
00326         TRACE(PREFIX_I "Not RGBA mode\n");
00327         return -1;
00328     }
00329 
00330     if ((pfd->cColorBits != desktop_depth)
00331      && (pfd->cColorBits != 32 || desktop_depth < 24)) {
00332         TRACE(PREFIX_I "Current color depth != "
00333               "pixel format color depth\n");
00334         //return -1;  /* XXX <rohannessian> Why is this a bad thing? */
00335     }
00336     
00337 
00338     /* hardware acceleration */
00339     if (((pfd->dwFlags & PFD_GENERIC_ACCELERATED)
00340          && (pfd->dwFlags & PFD_GENERIC_FORMAT))
00341         || (!(pfd->dwFlags & PFD_GENERIC_ACCELERATED)
00342             && !(pfd->dwFlags & PFD_GENERIC_FORMAT)))
00343         dinfo->rmethod = 1;
00344     else
00345         dinfo->rmethod = 0;
00346 
00347 
00348     /* Depths of colour buffers */
00349     dinfo->pixel_size.rgba.r = pfd->cRedBits;
00350     dinfo->pixel_size.rgba.g = pfd->cGreenBits;
00351     dinfo->pixel_size.rgba.b = pfd->cBlueBits;
00352     dinfo->pixel_size.rgba.a = pfd->cAlphaBits;
00353 
00354     /* Depths of accumulation buffer */
00355     dinfo->accum_size.rgba.r = pfd->cAccumRedBits;
00356     dinfo->accum_size.rgba.g = pfd->cAccumGreenBits;
00357     dinfo->accum_size.rgba.b = pfd->cAccumBlueBits;
00358     dinfo->accum_size.rgba.a = pfd->cAccumAlphaBits;
00359 
00360     /* Miscellaneous settings */
00361     dinfo->doublebuffered = pfd->dwFlags & PFD_DOUBLEBUFFER;
00362     dinfo->stereo = pfd->dwFlags & PFD_STEREO;
00363     dinfo->aux_buffers = pfd->cAuxBuffers;
00364     dinfo->depth_size = pfd->cDepthBits;
00365     dinfo->stencil_size = pfd->cStencilBits;
00366 
00367     /* These are the component shifts, like Allegro's _rgb_*_shift_*. */
00368     dinfo->r_shift = pfd->cRedShift;
00369     dinfo->g_shift = pfd->cGreenShift;
00370     dinfo->b_shift = pfd->cBlueShift;
00371     dinfo->a_shift = pfd->cAlphaShift;
00372 
00373     /* Multisampling isn't supported under Windows if we don't also use
00374      * WGL_ARB_pixel_format or WGL_EXT_pixel_format.
00375      */
00376     dinfo->sample_buffers = 0;
00377     dinfo->samples = 0;
00378 
00379     /* Float depth/color isn't supported under Windows if we don't also use
00380      * AGL_ARB_pixel_format or WGL_EXT_pixel_format.
00381      */
00382     dinfo->float_color = 0;
00383     dinfo->float_depth = 0;
00384 
00385     /* This bit is the same as the X code, setting some things based on
00386      * what we've read out of the PFD. */
00387     dinfo->colour_depth = 0;
00388     if (dinfo->pixel_size.rgba.r == 5 && dinfo->pixel_size.rgba.b == 5) {
00389         if (dinfo->pixel_size.rgba.g == 5)
00390             dinfo->colour_depth = 15;
00391         if (dinfo->pixel_size.rgba.g == 6)
00392             dinfo->colour_depth = 16;
00393     }
00394     if (dinfo->pixel_size.rgba.r == 8
00395         && dinfo->pixel_size.rgba.g == 8 && dinfo->pixel_size.rgba.b == 8) {
00396         if (dinfo->pixel_size.rgba.a == 8)
00397             dinfo->colour_depth = 32;
00398         else
00399             dinfo->colour_depth = 24;
00400     }
00401 
00402 
00403     dinfo->allegro_format = (dinfo->colour_depth != 0)
00404         && (dinfo->g_shift == dinfo->pixel_size.rgba.b)
00405         && (dinfo->r_shift * dinfo->b_shift == 0)
00406         && (dinfo->r_shift + dinfo->b_shift ==
00407             dinfo->pixel_size.rgba.b + dinfo->pixel_size.rgba.g);
00408 
00409     return 0;
00410 }
00411 
00412 
00413 
00414 /* Decodes the pixel format into an agl_display_info struct and logs the pixel
00415  * format in the trace file.
00416  */
00417 static int decode_pixel_format_attrib(struct allegro_gl_display_info *dinfo,
00418                           int num_attribs, const int *attrib, const int *value,
00419                           int desktop_depth) {
00420     int i;
00421     
00422     TRACE(PREFIX_I "Decoding: \n");
00423 
00424     dinfo->samples = 0;
00425     dinfo->sample_buffers = 0;
00426     dinfo->float_depth = 0;
00427     dinfo->float_color = 0;
00428 
00429     for (i = 0; i < num_attribs; i++) {
00430 
00431         /* Not interested if it doesn't support OpenGL or window drawing or
00432          * RGBA.
00433          */
00434         if (attrib[i] == WGL_SUPPORT_OPENGL_ARB && value[i] == 0) { 
00435             TRACE(PREFIX_I "OpenGL Unsupported\n");
00436             return -1;
00437         }
00438         else if (attrib[i] == WGL_DRAW_TO_WINDOW_ARB && value[i] == 0) {    
00439             TRACE(PREFIX_I "Can't draw to window\n");
00440             return -1;
00441         }
00442         else if (attrib[i] == WGL_PIXEL_TYPE_ARB &&
00443                 (value[i] != WGL_TYPE_RGBA_ARB
00444                  && value[i] != WGL_TYPE_RGBA_FLOAT_ARB)) { 
00445             TRACE(PREFIX_I "Not RGBA mode\n");
00446             return -1;
00447         }
00448         /* Check for color depth matching */
00449         else if (attrib[i] == WGL_COLOR_BITS_ARB) {
00450             if ((value[i] != desktop_depth)
00451              && (value[i] != 32 || desktop_depth < 24)) {
00452                 TRACE(PREFIX_I "Current color depth != "
00453                       "pixel format color depth\n");
00454                 //return -1; /* XXX <rohannessian> Why is this a bad thing? */
00455             }
00456         }
00457         /* hardware acceleration */
00458         else if (attrib[i] == WGL_ACCELERATION_ARB) {
00459             dinfo->rmethod = (value[i] == WGL_NO_ACCELERATION_ARB) ? 0 : 1;
00460         }
00461         /* Depths of colour buffers */
00462         else if (attrib[i] == WGL_RED_BITS_ARB) {
00463             dinfo->pixel_size.rgba.r = value[i];
00464         }
00465         else if (attrib[i] == WGL_GREEN_BITS_ARB) {
00466             dinfo->pixel_size.rgba.g = value[i];
00467         }
00468         else if (attrib[i] == WGL_BLUE_BITS_ARB) {
00469             dinfo->pixel_size.rgba.b = value[i];
00470         }
00471         else if (attrib[i] == WGL_ALPHA_BITS_ARB) {
00472             dinfo->pixel_size.rgba.a = value[i];
00473         }
00474         /* Shift of color components */
00475         else if (attrib[i] == WGL_RED_SHIFT_ARB) {
00476             dinfo->r_shift = value[i];
00477         }
00478         else if (attrib[i] == WGL_GREEN_SHIFT_ARB) {
00479             dinfo->g_shift = value[i];
00480         }
00481         else if (attrib[i] == WGL_BLUE_SHIFT_ARB) {
00482             dinfo->b_shift = value[i];
00483         }
00484         else if (attrib[i] == WGL_ALPHA_SHIFT_ARB) {
00485             dinfo->a_shift = value[i];
00486         }
00487 
00488         /* Depths of accumulation buffer */
00489         else if (attrib[i] == WGL_ACCUM_RED_BITS_ARB) {
00490             dinfo->accum_size.rgba.r = value[i];
00491         }
00492         else if (attrib[i] == WGL_ACCUM_GREEN_BITS_ARB) {
00493             dinfo->accum_size.rgba.g = value[i];
00494         }
00495         else if (attrib[i] == WGL_ACCUM_BLUE_BITS_ARB) {
00496             dinfo->accum_size.rgba.b = value[i];
00497         }
00498         else if (attrib[i] == WGL_ACCUM_ALPHA_BITS_ARB) {
00499             dinfo->accum_size.rgba.a = value[i];
00500         }   
00501         /* Miscellaneous settings */
00502         else if (attrib[i] == WGL_DOUBLE_BUFFER_ARB) {
00503             dinfo->doublebuffered = value[i];
00504         }
00505         else if (attrib[i] == WGL_STEREO_ARB) {
00506             dinfo->stereo = value[i];
00507         }
00508         else if (attrib[i] == WGL_AUX_BUFFERS_ARB) {
00509             dinfo->aux_buffers = value[i];
00510         }
00511         else if (attrib[i] == WGL_DEPTH_BITS_ARB) {
00512             dinfo->depth_size = value[i];
00513         }
00514         else if (attrib[i] == WGL_STENCIL_BITS_ARB) {
00515             dinfo->stencil_size = value[i];
00516         }
00517         /* Multisampling bits */
00518         else if (attrib[i] == WGL_SAMPLE_BUFFERS_ARB) {
00519             dinfo->sample_buffers = value[i];
00520         }
00521         else if (attrib[i] == WGL_SAMPLES_ARB) {
00522             dinfo->samples = value[i];
00523         }
00524         /* Float color */
00525         if (attrib[i] == WGL_PIXEL_TYPE_ARB
00526           && value[i] == WGL_TYPE_RGBA_FLOAT_ARB) {
00527             dinfo->float_color = TRUE;
00528         }
00529         /* Float depth */
00530         else if (attrib[i] == WGL_DEPTH_FLOAT_EXT) {
00531             dinfo->float_depth = value[i];
00532         }
00533     }
00534 
00535     /* This bit is the same as the X code, setting some things based on
00536      * what we've read out of the PFD. */
00537     dinfo->colour_depth = 0;
00538     if (dinfo->pixel_size.rgba.r == 5 && dinfo->pixel_size.rgba.b == 5) {
00539         if (dinfo->pixel_size.rgba.g == 5)
00540             dinfo->colour_depth = 15;
00541         if (dinfo->pixel_size.rgba.g == 6)
00542             dinfo->colour_depth = 16;
00543     }
00544     if (dinfo->pixel_size.rgba.r == 8
00545         && dinfo->pixel_size.rgba.g == 8 && dinfo->pixel_size.rgba.b == 8) {
00546         if (dinfo->pixel_size.rgba.a == 8)
00547             dinfo->colour_depth = 32;
00548         else
00549             dinfo->colour_depth = 24;
00550     }
00551 
00552     dinfo->allegro_format = (dinfo->colour_depth != 0)
00553         && (dinfo->g_shift == dinfo->pixel_size.rgba.b)
00554         && (dinfo->r_shift * dinfo->b_shift == 0)
00555         && (dinfo->r_shift + dinfo->b_shift ==
00556             dinfo->pixel_size.rgba.b + dinfo->pixel_size.rgba.g);
00557 
00558     return 0;
00559 }
00560 
00561 
00562 
00563 typedef struct format_t {
00564     int score;
00565     int format;
00566 } format_t;
00567 
00568 
00569 
00570 /* Helper function for sorting pixel formats by score */
00571 static int select_pixel_format_sorter(const void *p0, const void *p1) {
00572     format_t *f0 = (format_t*)p0;
00573     format_t *f1 = (format_t*)p1;
00574 
00575     if (f0->score == f1->score) {
00576         return 0;
00577     }
00578     else if (f0->score > f1->score) {
00579         return -1;
00580     }
00581     else {
00582         return 1;
00583     }
00584 }
00585 
00586 
00587 
00588 /* Describes the pixel format and assigns it a score */
00589 int describe_pixel_format_old(HDC dc, int fmt, int desktop_depth,
00590                                format_t *formats, int *num_formats,
00591                                struct allegro_gl_display_info *pdinfo) {
00592 
00593     struct allegro_gl_display_info dinfo;
00594     PIXELFORMATDESCRIPTOR pfd;
00595     int score = -1;
00596     
00597     int result = DescribePixelFormat(dc, fmt, sizeof(pfd), &pfd);
00598 
00599     /* Remember old settings */
00600     if (pdinfo) {
00601         dinfo = *pdinfo;
00602     }
00603 
00604     if (!result) {
00605         log_win32_warning("describe_pixel_format_old",
00606                           "DescribePixelFormat() failed!", GetLastError());
00607         return -1;
00608     }
00609     
00610     result = !decode_pixel_format(&pfd, dc, fmt, &dinfo, desktop_depth);
00611     
00612     if (result) {
00613         print_pixel_format(&dinfo);
00614         score = __allegro_gl_score_config(fmt, &dinfo);
00615     }
00616             
00617     if (score < 0) {
00618         return -1; /* Reject non-compliant pixel formats */
00619     }
00620 
00621     if (formats && num_formats) {
00622         formats[*num_formats].score  = score;
00623         formats[*num_formats].format = fmt;
00624         (*num_formats)++;
00625     }
00626 
00627     if (pdinfo) {
00628         *pdinfo = dinfo;
00629     }
00630 
00631     return 0;
00632 }
00633 
00634 
00635 
00636 static AGL_GetPixelFormatAttribivARB_t __wglGetPixelFormatAttribivARB = NULL;
00637 static AGL_GetPixelFormatAttribivEXT_t __wglGetPixelFormatAttribivEXT = NULL;
00638 
00639 
00640 
00641 /* Describes the pixel format and assigns it a score */
00642 int describe_pixel_format_new(HDC dc, int fmt, int desktop_depth,
00643                               format_t *formats, int *num_formats,
00644                               struct allegro_gl_display_info *pdinfo) {
00645 
00646     struct allegro_gl_display_info dinfo;
00647     int score = -1;
00648 
00649     /* Note: Even though we use te ARB suffix, all those enums are compatible
00650      * with EXT_pixel_format.
00651      */
00652     int attrib[] = {
00653         WGL_SUPPORT_OPENGL_ARB,
00654         WGL_DRAW_TO_WINDOW_ARB,
00655         WGL_PIXEL_TYPE_ARB,
00656         WGL_ACCELERATION_ARB,
00657         WGL_DOUBLE_BUFFER_ARB,
00658         WGL_DEPTH_BITS_ARB,
00659         WGL_COLOR_BITS_ARB,
00660         WGL_RED_BITS_ARB,
00661         WGL_GREEN_BITS_ARB,
00662         WGL_BLUE_BITS_ARB,
00663         WGL_ALPHA_BITS_ARB,
00664         WGL_RED_SHIFT_ARB,
00665         WGL_GREEN_SHIFT_ARB,
00666         WGL_BLUE_SHIFT_ARB,
00667         WGL_ALPHA_SHIFT_ARB,
00668         WGL_STENCIL_BITS_ARB,
00669         WGL_STEREO_ARB,
00670         WGL_ACCUM_BITS_ARB,
00671         WGL_ACCUM_RED_BITS_ARB,
00672         WGL_ACCUM_GREEN_BITS_ARB,
00673         WGL_ACCUM_BLUE_BITS_ARB,
00674         WGL_ACCUM_ALPHA_BITS_ARB,
00675         WGL_AUX_BUFFERS_ARB,
00676 
00677         /* The following are used by extensions that add to WGL_pixel_format.
00678          * If WGL_p_f isn't supported though, we can't use the (then invalid)
00679          * enums. We can't use any magic number either, so we settle for 
00680          * replicating one. The pixel format decoder
00681          * (decode_pixel_format_attrib()) doesn't care about duplicates.
00682          */
00683         WGL_AUX_BUFFERS_ARB, /* placeholder for WGL_SAMPLE_BUFFERS_ARB */
00684         WGL_AUX_BUFFERS_ARB, /* placeholder for WGL_SAMPLES_ARB        */
00685         WGL_AUX_BUFFERS_ARB, /* placeholder for WGL_DEPTH_FLOAT_EXT    */
00686     };
00687 
00688     const int num_attribs = sizeof(attrib) / sizeof(attrib[0]);
00689     int *value = (int*)malloc(sizeof(int) * num_attribs);
00690     int result;
00691     BOOL ret;
00692     int old_valid = __allegro_gl_valid_context;
00693 
00694     /* Can't allocate mem? */
00695     if (!value) {
00696         TRACE(PREFIX_E "describe_pixel_format_new(): Unable to allocate "
00697               "memory for pixel format descriptor!\n");
00698         return -1;
00699     }
00700 
00701     /* Remember old settings */
00702     if (pdinfo) {
00703         dinfo = *pdinfo;
00704     }
00705     
00706 
00707     /* If multisampling is supported, query for it. Note - we need to tell
00708      * allegro_gl_is_extension_supported() that we have a valid context,
00709      * even though AGL is not initialized yet.
00710      */
00711     __allegro_gl_valid_context = 1;
00712     if (allegro_gl_is_extension_supported("WGL_ARB_multisample")) {
00713         attrib[num_attribs - 3] = WGL_SAMPLE_BUFFERS_ARB;
00714         attrib[num_attribs - 2] = WGL_SAMPLES_ARB;
00715     }
00716     if (allegro_gl_is_extension_supported("WGL_EXT_depth_float")) {
00717         attrib[num_attribs - 1] = WGL_DEPTH_FLOAT_EXT;
00718     }
00719     __allegro_gl_valid_context = old_valid;
00720 
00721     
00722     /* Get the pf attributes */
00723     if (__wglGetPixelFormatAttribivARB) {
00724         ret = __wglGetPixelFormatAttribivARB(dc, fmt, 0, num_attribs,
00725                                              attrib, value);
00726     }
00727     else if (__wglGetPixelFormatAttribivEXT) {
00728         ret = __wglGetPixelFormatAttribivEXT(dc, fmt, 0, num_attribs,
00729                                              attrib, value);
00730     }
00731     else {
00732         ret = 0;
00733     }   
00734 
00735     /* wglGetPixelFormatAttrib() failed? Abort and revert to old path */
00736     if (!ret) {
00737         log_win32_error("describe_pixel_format_new",
00738                         "wglGetPixelFormatAttrib failed!", GetLastError());
00739         free(value);
00740         return -1;
00741     }
00742 
00743     /* Convert to AllegroGL format for scoring */
00744     result = !decode_pixel_format_attrib(&dinfo, num_attribs, attrib, value,
00745                                          desktop_depth);
00746     free(value);
00747 
00748     if (result) {
00749         print_pixel_format(&dinfo); 
00750         score = __allegro_gl_score_config(fmt, &dinfo);
00751     }
00752 
00753     if (score < 0) {
00754         return 0; /* Reject non-compliant pixel formats */
00755     }
00756 
00757     if (formats && num_formats) {
00758         formats[*num_formats].score  = score;
00759         formats[*num_formats].format = fmt;
00760         (*num_formats)++;
00761     }
00762 
00763     if (pdinfo) {
00764         *pdinfo = dinfo;
00765     }
00766 
00767     return 0;
00768 }
00769 
00770 
00771 
00772 /* Returns the number of pixel formats we should investigate */
00773 int get_num_pixel_formats(HDC dc, int *new_pf_code) {
00774     
00775     /* DescribePixelFormat() returns maximum pixel format index in the old
00776      * code. wglGetPixelFormatAttribivARB() does it in the new code.
00777      */
00778     if (new_pf_code && *new_pf_code) {
00779         int attrib[1];
00780         int value[1];
00781         
00782         TRACE(PREFIX_I "get_num_pixel_formats(): Attempting to use WGL_pf.\n");
00783         attrib[0] = WGL_NUMBER_PIXEL_FORMATS_ARB;
00784         if ((__wglGetPixelFormatAttribivARB
00785           && __wglGetPixelFormatAttribivARB(dc, 0, 0, 1, attrib, value)
00786                                                                  == GL_FALSE)
00787          || (__wglGetPixelFormatAttribivEXT
00788           && __wglGetPixelFormatAttribivEXT(dc, 0, 0, 1, attrib, value)
00789                                                                  == GL_FALSE)) {
00790             log_win32_note("get_num_pixel_formats",
00791                         "WGL_ARB/EXT_pixel_format use failed!", GetLastError());
00792             *new_pf_code = 0;
00793         }
00794         else {
00795             return value[0];
00796         }
00797     }
00798 
00799     if (!new_pf_code || !*new_pf_code) {
00800         PIXELFORMATDESCRIPTOR pfd;
00801         int ret;
00802         
00803         TRACE(PREFIX_I "get_num_pixel_formats(): Using DescribePixelFormat.\n");
00804         ret = DescribePixelFormat(dc, 1, sizeof(pfd), &pfd);
00805 
00806         if (!ret) {
00807             log_win32_error("get_num_pixel_formats",
00808                         "DescribePixelFormat failed!", GetLastError());
00809         }
00810         
00811         return ret;
00812     }
00813 
00814     return 0;
00815 }
00816 
00817 
00818 
00819 /* Pick the best matching pixel format */
00820 static int select_pixel_format(PIXELFORMATDESCRIPTOR * pfd)
00821 {
00822     int i;
00823     int result, maxindex;
00824     int desktop_depth;
00825 
00826     HWND testwnd = NULL;
00827     HDC testdc   = NULL;
00828     HGLRC testrc = NULL;
00829     
00830     format_t *format = NULL;
00831     int num_formats = 0;
00832     int new_pf_code = 0;
00833 
00834     
00835     __allegro_gl_reset_scorer();
00836 
00837     /* Read again the desktop depth */
00838     desktop_depth = desktop_color_depth();
00839  
00840     if (register_test_window() < 0) {
00841         return 0;
00842     }
00843 
00844     testwnd = create_test_window();
00845 
00846     if (!testwnd) {
00847         return 0;
00848     }
00849 
00850     testdc = GetDC(testwnd);
00851 
00852     /* Check if we can support new pixel format code */
00853     TRACE(PREFIX_I "select_pixel_format(): Trying to set up temporary RC\n");
00854     {
00855         HDC old_dc = __allegro_gl_hdc;
00856         int old_valid = __allegro_gl_valid_context;
00857         PIXELFORMATDESCRIPTOR pfd;
00858         int pf;
00859         
00860         new_pf_code = 0;
00861         
00862         /* We need to create a dummy window with a pixel format to get the
00863          * list of valid PFDs
00864          */
00865         memset(&pfd, 0, sizeof(pfd));
00866         pfd.nSize = sizeof(pfd);
00867         pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL
00868                     | PFD_DOUBLEBUFFER_DONTCARE | PFD_STEREO_DONTCARE;
00869         pfd.iPixelType = PFD_TYPE_RGBA;
00870         pfd.iLayerType = PFD_MAIN_PLANE;
00871         pfd.cColorBits = 32;
00872 
00873         TRACE(PREFIX_I "select_pixel_format(): ChoosePixelFormat()\n");
00874         pf = ChoosePixelFormat(testdc, &pfd);
00875 
00876         if (!pf) {
00877             log_win32_warning("select_pixel_format",
00878                         "Unable to chose a temporary pixel format!",
00879                         GetLastError());
00880             goto fail_pf;
00881         }
00882 
00883         /* Set up a GL context there */
00884         TRACE(PREFIX_I "select_pixel_format(): SetPixelFormat()\n");
00885         memset(&pfd, 0, sizeof(pfd));
00886         if (!SetPixelFormat(testdc, pf, &pfd)) {
00887             log_win32_warning("select_pixel_format",
00888                         "Unable to set a temporary pixel format!",
00889                         GetLastError());
00890             goto fail_pf;
00891         }
00892 
00893         TRACE(PREFIX_I "select_pixel_format(): CreateContext()\n");
00894         testrc = wglCreateContext(testdc);
00895 
00896         if (!testrc) {
00897             log_win32_warning("select_pixel_format",
00898                         "Unable to create a render context!",
00899                         GetLastError());
00900             goto fail_pf;
00901         }
00902         
00903         TRACE(PREFIX_I "select_pixel_format(): MakeCurrent()\n");
00904         if (!wglMakeCurrent(testdc, testrc)) {
00905             log_win32_warning("select_pixel_format",
00906                         "Unable to set the render context as current!",
00907                         GetLastError());
00908             goto fail_pf;
00909         }
00910 
00911         __allegro_gl_hdc = testdc;
00912         __allegro_gl_valid_context = TRUE;
00913 
00914 
00915         /* This is a workaround for a bug in old NVidia drivers. We need to
00916          * call wglGetExtensionsStringARB() for it to properly initialize.
00917          */
00918         TRACE(PREFIX_I "select_pixel_format(): GetExtensionsStringARB()\n");
00919         if (strstr((AL_CONST char*)glGetString(GL_VENDOR), "NVIDIA")) {
00920             AGL_GetExtensionsStringARB_t __wglGetExtensionsStringARB = NULL;
00921             
00922             __wglGetExtensionsStringARB = (AGL_GetExtensionsStringARB_t)
00923                            wglGetProcAddress("wglGetExtensionsStringARB");
00924 
00925             TRACE(PREFIX_I "select_pixel_format(): Querying for "
00926                   "WGL_ARB_extension_string\n");
00927             
00928             if (__wglGetExtensionsStringARB) {
00929                 TRACE(PREFIX_I "select_pixel_format(): Calling "
00930                       "__wglGetExtensionsStringARB\n");
00931                 __wglGetExtensionsStringARB(testdc);
00932             }
00933         }
00934 
00935         
00936         /* Check that we support ARB/EXT_pixel_format */
00937         if (!allegro_gl_is_extension_supported("WGL_ARB_pixel_format")
00938          && !allegro_gl_is_extension_supported("WGL_EXT_pixel_format")) {
00939             TRACE(PREFIX_I "select_pixel_format(): WGL_ARB/EXT_pf unsupported.\n");
00940             goto fail_pf;
00941         }
00942         
00943         /* Load the ARB_p_f symbol - Note, we shouldn't use the AGL extension
00944          * mechanism here, because AGL hasn't been initialized yet!
00945          */
00946         TRACE(PREFIX_I "select_pixel_format(): GetProcAddress()\n");        
00947         __wglGetPixelFormatAttribivARB = (AGL_GetPixelFormatAttribivARB_t)
00948                        wglGetProcAddress("wglGetPixelFormatAttribivARB");
00949         __wglGetPixelFormatAttribivEXT = (AGL_GetPixelFormatAttribivEXT_t)
00950                        wglGetProcAddress("wglGetPixelFormatAttribivEXT");
00951 
00952         if (!__wglGetPixelFormatAttribivARB
00953          && !__wglGetPixelFormatAttribivEXT) {
00954             TRACE(PREFIX_E "select_pixel_format(): WGL_ARB/EXT_pf not "
00955                   "correctly supported!\n");
00956             goto fail_pf;
00957         }
00958 
00959         new_pf_code = 1;
00960         goto exit_pf;
00961 
00962 fail_pf:
00963         wglMakeCurrent(NULL, NULL);
00964         if (testrc) {
00965             wglDeleteContext(testrc);
00966         }
00967         testrc = NULL;
00968 
00969         __wglGetPixelFormatAttribivARB = NULL;
00970         __wglGetPixelFormatAttribivEXT = NULL;
00971 exit_pf:
00972         __allegro_gl_hdc = old_dc;
00973         __allegro_gl_valid_context = old_valid;
00974     }
00975 
00976     maxindex = get_num_pixel_formats(testdc, &new_pf_code);
00977 
00978     /* Check if using the new pf code failed. Likely due to driver bug.
00979      * maxindex is still valid though, so we can continue.
00980      */
00981     if (!new_pf_code && testrc) {
00982         TRACE(PREFIX_W "select_pixel_format(): WGL_ARB_pf call failed - "
00983               "reverted to plain old WGL.\n");
00984         wglMakeCurrent(NULL, NULL);
00985         wglDeleteContext(testrc);
00986         testrc  = NULL;
00987         __wglGetPixelFormatAttribivARB = NULL;
00988         __wglGetPixelFormatAttribivEXT = NULL;
00989     }
00990 
00991     TRACE(PREFIX_I "select_pixel_format(): %i formats.\n", maxindex);
00992 
00993     if (maxindex < 1) {
00994         TRACE(PREFIX_E "select_pixel_format(): Didn't find any pixel "
00995               "formats at all!\n");
00996         goto bail;
00997     }
00998     
00999     format = malloc((maxindex + 1) * sizeof(format_t));
01000     
01001     if (!format) {
01002         TRACE(PREFIX_E "select_pixel_format(): Unable to allocate memory for "
01003               "pixel format scores!\n");
01004         goto bail;
01005     }
01006 
01007     /* First, pixel formats are sorted by decreasing order */
01008     TRACE(PREFIX_I "select_pixel_format(): Testing pixel formats:\n");
01009     for (i = 1; i <= maxindex; i++) {
01010 
01011         int use_old = !new_pf_code;
01012         
01013         TRACE(PREFIX_I "Format %i:\n", i);
01014         
01015         if (new_pf_code) {
01016             if (describe_pixel_format_new(testdc, i, desktop_depth,
01017                                           format, &num_formats, NULL) < 0) {
01018                 TRACE(PREFIX_W "select_pixel_format(): Wasn't able to use "
01019                       "WGL_PixelFormat - reverting to old WGL code.\n");
01020                 use_old = 1;
01021             }
01022         }
01023 
01024         if (use_old) {
01025             if (describe_pixel_format_old(testdc, i, desktop_depth,
01026                                       format, &num_formats, NULL) < 0) {
01027                 TRACE(PREFIX_W "select_pixel_format(): Unable to rely on "
01028                       "unextended WGL to describe this pixelformat.\n");
01029             }
01030         }
01031     }
01032 
01033     if (new_pf_code) {
01034         wglMakeCurrent(NULL, NULL);
01035         wglDeleteContext(testrc);
01036         testrc = NULL;
01037     }
01038     if (testwnd) {
01039         ReleaseDC(testwnd, testdc);
01040         testdc = NULL;
01041         DestroyWindow(testwnd);
01042         testwnd = NULL;
01043     }
01044 
01045     if (num_formats < 1) {
01046         TRACE(PREFIX_E "select_pixel_format(): Didn't find any available "
01047               "pixel formats!\n");
01048         goto bail;
01049     }
01050 
01051     qsort(format, num_formats, sizeof(format_t), select_pixel_format_sorter);
01052 
01053 
01054     /* Sorted pixel formats are tested until one of them succeeds to
01055      * make a GL context current */
01056     for (i = 0; i < num_formats ; i++) {
01057         HGLRC rc;
01058 
01059         /* Recreate our test windows */
01060         testwnd = create_test_window();
01061         testdc = GetDC(testwnd);
01062         
01063         if (SetPixelFormat(testdc, format[i].format, pfd)) {
01064             rc = wglCreateContext(testdc);
01065             if (!rc) {
01066                 TRACE(PREFIX_I "select_pixel_format(): Unable to create RC!\n");
01067             }
01068             else {
01069                 if (wglMakeCurrent(testdc, rc)) {
01070                     wglMakeCurrent(NULL, NULL);
01071                     wglDeleteContext(rc);
01072                     rc = NULL;
01073 
01074                     TRACE(PREFIX_I "select_pixel_format(): Best config is: %i"
01075                           "\n", format[i].format);
01076 
01077                     /* XXX <rohannessian> DescribePixelFormat may fail on 
01078                      * extended pixel format (WGL_ARB_p_f)
01079                      */
01080                     if (!DescribePixelFormat(testdc, format[i].format,
01081                                         sizeof *pfd, pfd)) {
01082                         TRACE(PREFIX_E "Cannot describe this pixel format\n");
01083                         ReleaseDC(testwnd, testdc);
01084                         DestroyWindow(testwnd);
01085                         testdc = NULL;
01086                         testwnd = NULL;
01087                         continue;
01088                     }
01089 
01090                     ReleaseDC(testwnd, testdc);
01091                     DestroyWindow(testwnd);
01092 
01093                     result = format[i].format;
01094                     
01095                     free(format);
01096                     return result;
01097                 }
01098                 else {
01099                     wglMakeCurrent(NULL, NULL);
01100                     wglDeleteContext(rc);
01101                     rc = NULL;
01102                     log_win32_warning("select_pixel_format",
01103                             "Couldn't make the temporary render context "
01104                             "current for the this pixel format.",
01105                             GetLastError());
01106                 }
01107             }
01108         }
01109         else {
01110             log_win32_note("select_pixel_format",
01111                         "Unable to set pixel format!", GetLastError());
01112         }
01113         
01114         ReleaseDC(testwnd, testdc);
01115         DestroyWindow(testwnd);
01116         testdc = NULL;
01117         testwnd = NULL;
01118     }
01119 
01120     TRACE(PREFIX_E "select_pixel_format(): All modes have failed...\n");
01121 bail:
01122     if (format) {
01123         free(format);
01124     }
01125     if (new_pf_code) {
01126         wglMakeCurrent(NULL, NULL);
01127         if (testrc) {
01128             wglDeleteContext(testrc);
01129         }
01130     }
01131     if (testwnd) {
01132         ReleaseDC(testwnd, testdc);
01133         DestroyWindow(testwnd);
01134     }
01135     
01136     return 0;
01137 }
01138 
01139 
01140 
01141 static void allegrogl_init_window(int w, int h, DWORD style, DWORD exstyle)
01142 {
01143     RECT rect;
01144 
01145 #define req __allegro_gl_required_settings
01146 #define sug __allegro_gl_suggested_settings
01147 
01148     int x = 32, y = 32;
01149     
01150     if (req & AGL_WINDOW_X || sug & AGL_WINDOW_X)
01151         x = allegro_gl_display_info.x;
01152     if (req & AGL_WINDOW_Y || sug & AGL_WINDOW_Y)
01153         y = allegro_gl_display_info.y;
01154 
01155 #undef req
01156 #undef sug
01157     
01158     if (!fullscreen) {
01159         rect.left = x;
01160         rect.right = x + w;
01161         rect.top = y;
01162         rect.bottom = y + h;
01163     }
01164     else {
01165         rect.left = 0;
01166         rect.right = w;
01167         rect.top  = 0;
01168         rect.bottom = h;
01169     }
01170 
01171     /* save original Allegro styles */
01172     style_saved = GetWindowLong(wnd, GWL_STYLE);
01173     exstyle_saved = GetWindowLong(wnd, GWL_EXSTYLE);
01174 
01175     /* set custom AllegroGL style */
01176     SetWindowLong(wnd, GWL_STYLE, style);
01177     SetWindowLong(wnd, GWL_EXSTYLE, exstyle);
01178 
01179     if (!fullscreen) {
01180         AdjustWindowRectEx(&rect, style, FALSE, exstyle);
01181     }
01182 
01183     /* make the changes visible */
01184     SetWindowPos(wnd, 0, rect.left, rect.top,
01185         rect.right - rect.left, rect.bottom - rect.top,
01186         SWP_NOZORDER | SWP_FRAMECHANGED);
01187     
01188     return;
01189 }
01190 
01191 
01192 
01193 static BITMAP *allegro_gl_create_screen (GFX_DRIVER *drv, int w, int h,
01194                                          int depth)
01195 {
01196     BITMAP *bmp;
01197     int is_linear = drv->linear;
01198 
01199     drv->linear = 1;
01200     bmp = _make_bitmap (w, h, 0, drv, depth, 0);
01201     
01202     if (!bmp) {
01203         return NULL;
01204     }
01205 
01206     bmp->id = BMP_ID_VIDEO | 1000;
01207     drv->linear = is_linear;
01208 
01209     drv->w = w;
01210     drv->h = h;
01211 
01212     return bmp;
01213 }
01214 
01215 
01216 static LRESULT CALLBACK dummy_wnd_proc(HWND wnd, UINT message, WPARAM wparam, LPARAM lparam)
01217 {
01218     return DefWindowProc(wnd, message, wparam, lparam);
01219 }
01220 
01221 static HWND dummy_wnd;
01222 
01223 static void dummy_window(void)
01224 {
01225     WNDCLASS wnd_class;
01226 
01227     wnd_class.style = CS_HREDRAW | CS_VREDRAW;
01228     wnd_class.lpfnWndProc = dummy_wnd_proc;
01229     wnd_class.cbClsExtra = 0;
01230     wnd_class.cbWndExtra = 0;
01231     wnd_class.hInstance = GetModuleHandle(NULL);
01232     wnd_class.hIcon = LoadIcon(NULL, IDI_APPLICATION);
01233     wnd_class.hCursor = LoadCursor(NULL, IDC_ARROW);
01234     wnd_class.hbrBackground = NULL;
01235     wnd_class.lpszMenuName = NULL;
01236     wnd_class.lpszClassName = "allegro focus";
01237 
01238     RegisterClass(&wnd_class);
01239 
01240     dummy_wnd = CreateWindow("allegro focus", "Allegro", WS_POPUP | WS_VISIBLE,
01241             0, 0, 200, 200,
01242             NULL, NULL, GetModuleHandle(NULL), NULL);
01243 
01244     ShowWindow(dummy_wnd, SW_SHOWNORMAL);
01245     SetForegroundWindow(dummy_wnd);
01246 }
01247 
01248 static void remove_dummy_window(void)
01249 {
01250     DestroyWindow(dummy_wnd);
01251     UnregisterClass("allegro focus", GetModuleHandle(NULL));
01252 }
01253 
01254 
01255 static BITMAP *allegro_gl_win_init(int w, int h, int v_w, int v_h)
01256 {
01257     static int first_time = 1;
01258     
01259     DWORD style=0, exstyle=0;
01260     int refresh_rate = _refresh_rate_request;
01261     int desktop_depth;
01262     int pf=0;
01263 
01264     new_w = w;
01265     new_h = h;
01266 
01267     /* virtual screen are not supported */
01268     if ((v_w != 0 && v_w != w) || (v_h != 0 && v_h != h)) {
01269         TRACE(PREFIX_E "win_init(): Virtual screens are not supported in "
01270               "AllegroGL!\n");
01271         return NULL;
01272     }
01273         
01274     /* Fill in missing color depth info */
01275     __allegro_gl_fill_in_info();
01276 
01277     /* Be sure the current desktop color depth is at least 15bpp */
01278     /* We may want to change this, so try to set a better depth, or
01279        to at least report an error somehow */
01280     desktop_depth = desktop_color_depth();
01281 
01282     if (desktop_depth < 15)
01283         return NULL;
01284 
01285     TRACE(PREFIX_I "win_init(): Requested color depth: %i  "
01286           "Desktop color depth: %i\n", allegro_gl_display_info.colour_depth,
01287           desktop_depth);
01288 
01289         /* In the moment the main window is destroyed, Allegro loses focus, and
01290          * focus can only be returned by actual user input under Windows XP. So
01291          * we need to create a dummy window which retains focus for us, until
01292          * the new window is up.
01293          */
01294         if (fullscreen) dummy_window();
01295 
01296     /* Need to set the w and h driver members at this point to avoid assertion
01297      * failure in set_mouse_range() when win_set_window() is called.
01298      */
01299     if (fullscreen) {
01300         gfx_allegro_gl_fullscreen.w = w;
01301         gfx_allegro_gl_fullscreen.h = h;
01302     }
01303     else {
01304         gfx_allegro_gl_windowed.w = w;
01305         gfx_allegro_gl_windowed.h = h;
01306     }
01307 
01308     /* request a fresh new window from Allegro... */
01309     /* Set a NULL window to get Allegro to generate a new HWND. This is needed
01310      * because we can only set the pixel format once per window. Thus, calling
01311      * set_gfx_mode() multiple times will fail without this code.
01312      */
01313     if (!first_time) {
01314         win_set_window(NULL);
01315     }
01316     first_time = 0;
01317 
01318     /* ...and retrieve its handle */
01319     wnd = win_get_window();
01320     if (!wnd)
01321         return NULL;
01322 
01323     /* set up the AllegroGL window */
01324     if (fullscreen) {
01325         style = WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
01326         exstyle = WS_EX_APPWINDOW | WS_EX_TOPMOST;
01327     }
01328     else {
01329         style = WS_SYSMENU | WS_CAPTION | WS_MINIMIZEBOX | WS_CLIPCHILDREN
01330               | WS_CLIPSIBLINGS;
01331         exstyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
01332     }
01333 
01334     TRACE(PREFIX_I "win_init(): Setting up window.\n");
01335     allegrogl_init_window(w, h, style, exstyle);
01336 
01337     __allegro_gl_hdc = GetDC(wnd); /* get the device context of our window */
01338     if (!__allegro_gl_hdc) {
01339         goto Error;
01340     }
01341 
01342     TRACE(PREFIX_I "win_init(): Driver selected fullscreen: %s\n",
01343           fullscreen ? "Yes" : "No");
01344 
01345     if (fullscreen)
01346     {
01347         DEVMODE dm;
01348         DEVMODE fallback_dm;
01349         int fallback_dm_valid = 0;
01350 
01351         int bpp_to_check[] = {16, 32, 24, 15, 0};
01352         int bpp_checked[] = {0, 0, 0, 0, 0};
01353         int bpp_index = 0;
01354         int i, j, result, modeswitch, done = 0;
01355 
01356         for (j = 0; j < 4; j++)
01357         {
01358             if (bpp_to_check[j] == allegro_gl_get(AGL_COLOR_DEPTH))
01359             {
01360                 bpp_index = j;
01361                 break;
01362             }
01363         }
01364 
01365         dm.dmSize = sizeof(DEVMODE);
01366         dm_saved.dmSize = sizeof(DEVMODE);
01367         
01368         /* Save old mode */
01369         EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dm_saved);
01370         dm.dmBitsPerPel = desktop_depth; /* Go around Win95's bug */
01371 
01372         do
01373         {
01374             if (!bpp_to_check[bpp_index])
01375             {
01376                 TRACE(PREFIX_E "win_init(): No more color depths to test.\n"
01377                       "\tUnable to find appropriate full screen mode and pixel "
01378                       "format.\n");
01379                 goto Error;
01380             }
01381 
01382             TRACE(PREFIX_I "win_init(): Testing color depth: %i\n",
01383                   bpp_to_check[bpp_index]);
01384             
01385             memset(&dm, 0, sizeof(DEVMODE));
01386             dm.dmSize = sizeof(DEVMODE);
01387             
01388             i = 0;
01389             do 
01390             {
01391                 modeswitch = EnumDisplaySettings(NULL, i, &dm);
01392                 if (!modeswitch)
01393                     break;
01394 
01395                 if ((dm.dmPelsWidth  == (unsigned) w)
01396                  && (dm.dmPelsHeight == (unsigned) h)
01397                  && (dm.dmBitsPerPel == (unsigned) bpp_to_check[bpp_index])
01398                  && (dm.dmDisplayFrequency != (unsigned) refresh_rate)) {
01399                     /* Keep it as fallback if refresh rate request could not
01400                      * be satisfied. Try to get as close to 60Hz as possible though,
01401                      * it's a bit better for a fallback than just blindly picking
01402                      * something like 47Hz or 200Hz.
01403                      */
01404                     if (!fallback_dm_valid) {
01405                         fallback_dm = dm;
01406                         fallback_dm_valid = 1;
01407                     }
01408                     else if (dm.dmDisplayFrequency >= 60) {
01409                         if (dm.dmDisplayFrequency < fallback_dm.dmDisplayFrequency) {
01410                             fallback_dm = dm;
01411                         }
01412                     }
01413                 }
01414         
01415                 i++;
01416             }
01417             while ((dm.dmPelsWidth  != (unsigned) w)
01418                 || (dm.dmPelsHeight != (unsigned) h)
01419                 || (dm.dmBitsPerPel != (unsigned) bpp_to_check[bpp_index])
01420                 || (dm.dmDisplayFrequency != (unsigned) refresh_rate));
01421 
01422             if (!modeswitch && !fallback_dm_valid) {
01423                 TRACE(PREFIX_I "win_init(): Unable to set mode, continuing "
01424                       "with next color depth\n");
01425             }
01426             else {
01427                 if (!modeswitch && fallback_dm_valid)
01428                     dm = fallback_dm;
01429 
01430                 TRACE(PREFIX_I "win_init(): bpp_to_check[bpp_index] = %i\n",
01431                       bpp_to_check[bpp_index]);
01432                 TRACE(PREFIX_I "win_init(): dm.dmBitsPerPel = %i\n",
01433                       (int)dm.dmBitsPerPel);
01434 
01435                 dm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL
01436                             | DM_DISPLAYFREQUENCY;
01437 
01438                 result = ChangeDisplaySettings(&dm, CDS_FULLSCREEN);
01439 
01440                 if (result == DISP_CHANGE_SUCCESSFUL) 
01441                 {
01442                     TRACE(PREFIX_I "win_init(): Setting pixel format.\n");
01443                     pf = select_pixel_format(&pfd);
01444                     if (pf) {
01445                         TRACE(PREFIX_I "mode found\n");
01446                         _set_current_refresh_rate(dm.dmDisplayFrequency);
01447                         done = 1;
01448                     }
01449                     else {
01450                         TRACE(PREFIX_I "win_init(): Couldn't find compatible "
01451                               "GL context. Trying another screen mode.\n");
01452                     }
01453                 }
01454             }
01455 
01456             fallback_dm_valid = 0;
01457             bpp_checked[bpp_index] = 1;
01458 
01459             bpp_index = 0;
01460             while (bpp_checked[bpp_index]) {
01461                 bpp_index++;
01462             }
01463         } while (!done);
01464     }
01465     else {
01466         DEVMODE dm;
01467 
01468         memset(&dm, 0, sizeof(DEVMODE));
01469         dm.dmSize = sizeof(DEVMODE);
01470         if (EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dm) != 0) {
01471             _set_current_refresh_rate(dm.dmDisplayFrequency);
01472         }
01473     }
01474 
01475     if (!fullscreen) {
01476         TRACE(PREFIX_I "win_init(): Setting pixel format.\n");
01477         pf = select_pixel_format(&pfd);
01478         if (pf == 0)
01479             goto Error;
01480     }
01481 
01482     /* set the pixel format */
01483     if (!SetPixelFormat(__allegro_gl_hdc, pf, &pfd)) { 
01484         log_win32_error("win_init",
01485                     "Unable to set pixel format.",
01486                     GetLastError());
01487         goto Error;
01488     }
01489 
01490     /* create an OpenGL context */
01491     allegro_glrc = wglCreateContext(__allegro_gl_hdc);
01492     
01493     if (!allegro_glrc) { /* make the context the current one */
01494         log_win32_error("win_init",
01495                     "Unable to create a render context!",
01496                     GetLastError());
01497         goto Error;
01498     }
01499     if (!wglMakeCurrent(__allegro_gl_hdc, allegro_glrc)) {
01500         log_win32_error("win_init",
01501                     "Unable to make the context current!",
01502                     GetLastError());
01503         goto Error;
01504     }
01505 
01506 
01507     if (__wglGetPixelFormatAttribivARB || __wglGetPixelFormatAttribivEXT) {
01508         describe_pixel_format_new(__allegro_gl_hdc, pf, desktop_depth,
01509                                   NULL, NULL, &allegro_gl_display_info);
01510     }
01511     else {
01512         describe_pixel_format_old(__allegro_gl_hdc, pf, desktop_depth,
01513                                   NULL, NULL, &allegro_gl_display_info);
01514     }
01515     
01516     
01517     __allegro_gl_set_allegro_image_format(FALSE);
01518     set_color_depth(allegro_gl_display_info.colour_depth);
01519     allegro_gl_display_info.w = w;
01520     allegro_gl_display_info.h = h;
01521 
01522     
01523     /* <rohannessian> Win98/2k/XP's window forground rules don't let us
01524      * make our window the topmost window on launch. This causes issues on 
01525      * full-screen apps, as DInput loses input focus on them.
01526      * We use this trick to force the window to be topmost, when switching
01527      * to full-screen only. Note that this only works for Win98 and greater.
01528      * Win95 will ignore our SystemParametersInfo() calls.
01529      * 
01530      * See http://support.microsoft.com:80/support/kb/articles/Q97/9/25.asp
01531      * for details.
01532      */
01533     {
01534         DWORD lock_time;
01535 
01536 #define SPI_GETFOREGROUNDLOCKTIMEOUT 0x2000
01537 #define SPI_SETFOREGROUNDLOCKTIMEOUT 0x2001
01538         if (fullscreen) {
01539             SystemParametersInfo(SPI_GETFOREGROUNDLOCKTIMEOUT,
01540                                  0, (LPVOID)&lock_time, 0);
01541             SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT,
01542                                  0, (LPVOID)0,
01543                                  SPIF_SENDWININICHANGE | SPIF_UPDATEINIFILE);
01544         }
01545 
01546         ShowWindow(wnd, SW_SHOWNORMAL);
01547         SetForegroundWindow(wnd);
01548         /* In some rare cases, it doesn't seem to work without the loop. And we
01549          * absolutely need this to succeed, else we trap the user in a
01550          * fullscreen window without input.
01551          */
01552         while (GetForegroundWindow() != wnd) {
01553             rest(100);
01554             SetForegroundWindow(wnd);
01555         }
01556         UpdateWindow(wnd);
01557 
01558         if (fullscreen) {
01559             SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT,
01560                                  0, (LPVOID)lock_time,
01561                                  SPIF_SENDWININICHANGE | SPIF_UPDATEINIFILE);
01562         }
01563 #undef SPI_GETFOREGROUNDLOCKTIMEOUT
01564 #undef SPI_SETFOREGROUNDLOCKTIMEOUT
01565     }
01566         
01567     win_grab_input();
01568     
01569     if (fullscreen) {
01570         allegro_gl_screen= allegro_gl_create_screen(&gfx_allegro_gl_fullscreen,
01571                                         w, h, allegro_gl_get(AGL_COLOR_DEPTH));
01572     }
01573     else {
01574         allegro_gl_screen= allegro_gl_create_screen(&gfx_allegro_gl_windowed,
01575                                         w, h, allegro_gl_get(AGL_COLOR_DEPTH));
01576     }
01577 
01578     if (!allegro_gl_screen) {
01579         ChangeDisplaySettings(NULL, 0);
01580         goto Error;
01581     }
01582     
01583 
01584     TRACE(PREFIX_I "win_init(): GLScreen: %ix%ix%i\n",
01585           w, h, allegro_gl_get(AGL_COLOR_DEPTH));
01586 
01587     allegro_gl_screen->id |= BMP_ID_VIDEO | BMP_ID_MASK;
01588 
01589     __allegro_gl_valid_context = TRUE;
01590     __allegro_gl_driver = &allegro_gl_win;
01591     initialized = 1;
01592 
01593     /* Print out OpenGL version info */
01594     TRACE(PREFIX_I "OpenGL Version: %s\n", (AL_CONST char*)glGetString(GL_VERSION));
01595     TRACE(PREFIX_I "Vendor: %s\n", (AL_CONST char*)glGetString(GL_VENDOR));
01596     TRACE(PREFIX_I "Renderer: %s\n\n", (AL_CONST char*)glGetString(GL_RENDERER));
01597 
01598     /* Detect if the GL driver is based on Mesa */
01599     allegro_gl_info.is_mesa_driver = FALSE;
01600     if (strstr((AL_CONST char*)glGetString(GL_VERSION),"Mesa")) {
01601         AGL_LOG(1, "OpenGL driver based on Mesa\n");
01602         allegro_gl_info.is_mesa_driver = TRUE;
01603     }
01604 
01605     /* init the GL extensions */
01606     __allegro_gl_manage_extensions();
01607     
01608     /* Update screen vtable in order to use AGL's */
01609     __allegro_gl__glvtable_update_vtable(&allegro_gl_screen->vtable);
01610     memcpy(&_screen_vtable, allegro_gl_screen->vtable, sizeof(GFX_VTABLE));
01611     allegro_gl_screen->vtable = &_screen_vtable;
01612 
01613     /* Print out WGL extension info */
01614     if (wglGetExtensionsStringARB) {
01615         AGL_LOG(1, "WGL Extensions :\n");
01616 #if LOGLEVEL >= 1
01617         __allegro_gl_print_extensions((AL_CONST char*)wglGetExtensionsStringARB(wglGetCurrentDC()));
01618 #endif
01619     }
01620     else {
01621         TRACE(PREFIX_I "win_init(): No WGL Extensions available\n");
01622     }
01623 
01624     gfx_capabilities |= GFX_HW_CURSOR;
01625 
01626     /* Initialize a reasonable viewport. Those should be OpenGL defaults,
01627      * but some drivers don't implement this correctly.
01628      */ 
01629     glViewport(0, 0, SCREEN_W, SCREEN_H);
01630     glMatrixMode(GL_PROJECTION);
01631     glLoadIdentity();
01632     glMatrixMode(GL_MODELVIEW);
01633     glLoadIdentity();
01634 
01635     if (allegro_gl_extensions_GL.ARB_multisample) {
01636         /* Workaround some "special" drivers that do not export the extension
01637          * once it was promoted to core.*/
01638         if (allegro_gl_opengl_version() >= 1.3)
01639             glSampleCoverage(1.0, GL_FALSE);
01640         else
01641             glSampleCoverageARB(1.0, GL_FALSE);
01642     }
01643     
01644     /* Set up some variables that some GL drivers omit */
01645     glBindTexture(GL_TEXTURE_2D, 0);
01646     
01647     screen = allegro_gl_screen;
01648 
01649     if (fullscreen)
01650         remove_dummy_window();
01651 
01652     return allegro_gl_screen;
01653     
01654 Error:
01655     if (allegro_glrc) {
01656         wglDeleteContext(allegro_glrc);
01657     }
01658     if (__allegro_gl_hdc) {
01659         ReleaseDC(wnd, __allegro_gl_hdc);
01660     }
01661     __allegro_gl_hdc = NULL;
01662     ChangeDisplaySettings(NULL, 0);
01663     allegro_gl_win_exit(NULL);
01664 
01665     return NULL;
01666 }
01667 
01668 
01669 
01670 static BITMAP *allegro_gl_win_init_windowed(int w, int h, int v_w, int v_h,
01671                                             int color_depth)
01672 {
01673     fullscreen = 0;
01674     return allegro_gl_win_init(w, h, v_w, v_h);
01675 }
01676 
01677 
01678 
01679 static BITMAP *allegro_gl_win_init_fullscreen(int w, int h, int v_w, int v_h,
01680                                               int color_depth)
01681 {
01682     fullscreen = 1;
01683     return allegro_gl_win_init(w, h, v_w, v_h);
01684 }
01685 
01686 
01687 
01688 static void allegro_gl_win_exit(struct BITMAP *b)
01689 {
01690     /* XXX <rohannessian> For some reason, uncommenting this line will blank
01691      * out the log file.
01692      */
01693     //TRACE(PREFIX_I "allegro_gl_win_exit: Shutting down.\n");
01694     __allegro_gl_unmanage_extensions();
01695     
01696     if (allegro_glrc) {
01697         wglDeleteContext(allegro_glrc);
01698         allegro_glrc = NULL;
01699     }
01700         
01701     if (__allegro_gl_hdc) {
01702         ReleaseDC(wnd, __allegro_gl_hdc);
01703         __allegro_gl_hdc = NULL;
01704     }
01705 
01706     if (fullscreen && initialized) {
01707         /* Restore screen */
01708         ChangeDisplaySettings(NULL, 0);
01709         _set_current_refresh_rate(0);
01710     }
01711     initialized = 0;
01712 
01713     /* Note: Allegro will destroy screen (== allegro_gl_screen),
01714      * so don't destroy it here.
01715      */
01716     //destroy_bitmap(allegro_gl_screen);
01717     allegro_gl_screen = NULL;
01718     
01719     /* hide the window */
01720     system_driver->restore_console_state();
01721 
01722     /* restore original Allegro styles */
01723     SetWindowLong(wnd, GWL_STYLE, style_saved);
01724     SetWindowLong(wnd, GWL_EXSTYLE, exstyle_saved);
01725     SetWindowPos(wnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER
01726                                    | SWP_FRAMECHANGED);
01727 
01728     __allegro_gl_valid_context = FALSE;
01729     
01730     return;
01731 }
01732 
01733 
01734 /* 
01735    Returns TRUE is dm doesn't match any mode in mode_list, FALSE otherwise.
01736 */
01737 static int is_mode_entry_unique(GFX_MODE_LIST *mode_list, DEVMODE *dm) {
01738     int i;
01739     
01740     for (i = 0; i < mode_list->num_modes; ++i) {
01741         if (mode_list->mode[i].width == (int)dm->dmPelsWidth
01742             && mode_list->mode[i].height == (int)dm->dmPelsHeight
01743             && mode_list->mode[i].bpp == (int)dm->dmBitsPerPel)
01744             return FALSE;
01745     }
01746     
01747     return TRUE;
01748 }
01749 
01750 
01751 
01752 /* Returns a list of valid video modes */
01753 static GFX_MODE_LIST* allegro_gl_win_fetch_mode_list(void)
01754 {
01755     int c, modes_count;
01756     GFX_MODE_LIST *mode_list;
01757     DEVMODE dm;
01758 
01759     dm.dmSize = sizeof(DEVMODE);
01760 
01761     /* Allocate space for mode list. */
01762     mode_list = malloc(sizeof(GFX_MODE_LIST));
01763     if (!mode_list) {
01764         return NULL;
01765     }
01766 
01767     /* Allocate and fill the first mode in case EnumDisplaySettings fails at
01768      * first call.
01769      */
01770     mode_list->mode = malloc(sizeof(GFX_MODE));
01771     if (!mode_list->mode) {
01772         free(mode_list);
01773         return NULL;
01774     }
01775     mode_list->mode[0].width = 0;
01776     mode_list->mode[0].height = 0;
01777     mode_list->mode[0].bpp = 0;
01778     mode_list->num_modes = 0;
01779 
01780     modes_count = 0;
01781     c = 0;
01782     while (EnumDisplaySettings(NULL, c, &dm)) {
01783         mode_list->mode = realloc(mode_list->mode,
01784                                 sizeof(GFX_MODE) * (modes_count + 2));
01785         if (!mode_list->mode) {
01786             free(mode_list);
01787             return NULL;
01788         }
01789 
01790         /* Filter modes with bpp lower than 9, and those which are already
01791          * in there.
01792          */
01793         if (dm.dmBitsPerPel > 8 && is_mode_entry_unique(mode_list, &dm)) {
01794             mode_list->mode[modes_count].width = dm.dmPelsWidth;
01795             mode_list->mode[modes_count].height = dm.dmPelsHeight;
01796             mode_list->mode[modes_count].bpp = dm.dmBitsPerPel;
01797             ++modes_count;
01798             mode_list->mode[modes_count].width = 0;
01799             mode_list->mode[modes_count].height = 0;
01800             mode_list->mode[modes_count].bpp = 0;
01801             mode_list->num_modes = modes_count;
01802         }
01803         ++c;
01804     };
01805 
01806     return mode_list;
01807 }
01808 
01809 
01810 
01811 
01812 /* AllegroGL driver routines */
01813 
01814 static void flip(void)
01815 {
01816     SwapBuffers(__allegro_gl_hdc);
01817 }
01818 
01819 
01820 
01821 static void gl_on(void)
01822 {
01823     return;
01824 }
01825 
01826 
01827 
01828 static void gl_off(void)
01829 {
01830     return;
01831 }
01832 
01833 
01834 
01835 /* AllegroGL driver */
01836 
01837 static struct allegro_gl_driver allegro_gl_win = {
01838     flip, gl_on, gl_off, NULL
01839 };
01840 
allegro4.4-4.4.2/addons/allegrogl/docs/html/x_8c_source.html000066400000000000000000003740031173507505700236400ustar00rootroot00000000000000 AllegroGL: x.c Source File

x.c

00001 /* This code is (C) AllegroGL contributors, and double licensed under
00002  * the GPL and zlib licenses. See gpl.txt or zlib.txt for details.
00003  */
00004 /*----------------------------------------------------------------
00005  * x.c -- Allegro-GLX interfacing
00006  *----------------------------------------------------------------
00007  *  This is the interface module for use under X.
00008  */
00009 #include <string.h>
00010 #include <stdio.h>
00011 
00012 #include <allegro.h>
00013 #include <xalleg.h>
00014 
00015 #include <allegro/platform/aintunix.h>
00016 
00017 #include "alleggl.h"
00018 #include "allglint.h"
00019 #include "glvtable.h"
00020 
00021 
00022 #ifndef XLOCK
00023     #define OLD_ALLEGRO
00024     #define XLOCK() DISABLE()
00025     #undef XUNLOCK
00026     #define XUNLOCK() ENABLE()
00027 #endif
00028 
00029 #define PREFIX_I                "agl-x INFO: "
00030 #define PREFIX_E                "agl-x ERROR: "
00031 
00032 
00033 #ifdef ALLEGRO_XWINDOWS_WITH_XPM
00034 #include <X11/xpm.h>
00035 extern void *allegro_icon;
00036 #endif
00037 
00038 
00039 static BITMAP *allegro_gl_x_windowed_init(int w, int h, int vw, int vh,
00040                                           int color_depth);
00041 static void allegro_gl_x_exit(BITMAP *bmp);
00042 #ifdef ALLEGROGL_HAVE_XF86VIDMODE
00043 static GFX_MODE_LIST* allegro_gl_x_fetch_mode_list(void);
00044 #endif
00045 static void allegro_gl_x_vsync(void);
00046 static void allegro_gl_x_hide_mouse(void);
00047 
00048 static BITMAP *allegro_gl_screen = NULL;
00049 
00050 /* TODO: Revamp the whole window handling under X11 in Allegro and
00051  * AllegroGL. We really shouldn't have to duplicate code or hack on
00052  * Allegro internals in AllegroGL - the *only* difference for the AllegroGL
00053  * window should be the GLX visual (e.g. cursor, icon, VidModeExtension and
00054  * so on should never have been touched in this file).
00055  */
00056 #if GET_ALLEGRO_VERSION() >= MAKE_VER(4, 2, 1)
00057 static Window backup_allegro_window = None;
00058 static Colormap backup_allegro_colormap = None;
00059 #endif
00060 
00061 
00062 static BITMAP *allegro_gl_x_fullscreen_init(int w, int h, int vw, int vh,
00063                                             int color_depth);
00064 
00065 GFX_DRIVER gfx_allegro_gl_fullscreen =
00066 {
00067    GFX_OPENGL_FULLSCREEN,
00068    empty_string,
00069    empty_string,
00070    "AllegroGL Fullscreen (X)",
00071    allegro_gl_x_fullscreen_init,
00072    allegro_gl_x_exit,
00073    NULL,
00074    allegro_gl_x_vsync,
00075    NULL,
00076    NULL, NULL, NULL,
00077    allegro_gl_create_video_bitmap,
00078    allegro_gl_destroy_video_bitmap,
00079    NULL, NULL,                  /* No show/request video bitmaps */
00080    NULL, NULL,
00081    allegro_gl_set_mouse_sprite,
00082    allegro_gl_show_mouse,
00083    allegro_gl_x_hide_mouse,
00084    allegro_gl_move_mouse,
00085    allegro_gl_drawing_mode,
00086    NULL, NULL,
00087    allegro_gl_set_blender_mode,
00088 #ifdef ALLEGROGL_HAVE_XF86VIDMODE
00089    allegro_gl_x_fetch_mode_list,
00090 #else
00091    NULL,
00092 #endif
00093    0, 0,
00094    0,
00095    0, 0,
00096    0,
00097    0,
00098    FALSE                        /* Windowed mode */
00099 };
00100 
00101 
00102 
00103 GFX_DRIVER gfx_allegro_gl_windowed =
00104 {
00105    GFX_OPENGL_WINDOWED,
00106    empty_string,
00107    empty_string,
00108    "AllegroGL Windowed (X)",
00109    allegro_gl_x_windowed_init,
00110    allegro_gl_x_exit,
00111    NULL,
00112    allegro_gl_x_vsync,
00113    NULL,
00114    NULL, NULL, NULL,
00115    allegro_gl_create_video_bitmap,
00116    allegro_gl_destroy_video_bitmap,
00117    NULL, NULL,                  /* No show/request video bitmaps */
00118    NULL, NULL,
00119    allegro_gl_set_mouse_sprite,
00120    allegro_gl_show_mouse,
00121    allegro_gl_x_hide_mouse,
00122    allegro_gl_move_mouse,
00123    allegro_gl_drawing_mode,
00124    NULL, NULL,
00125    allegro_gl_set_blender_mode,
00126    NULL,                        /* No fetch_mode_list */
00127    0, 0,
00128    0,
00129    0, 0,
00130    0,
00131    0,
00132    TRUE                         /* Windowed mode */
00133 };
00134 
00135 
00136 
00137 static struct allegro_gl_driver allegro_gl_x;
00138 
00139 static XVisualInfo *allegro_gl_x_windowed_choose_visual (void);
00140 static int allegro_gl_x_create_window (int fullscreen);
00141 static BITMAP *allegro_gl_x_windowed_create_screen (GFX_DRIVER *drv, int w, int h, int depth);
00142 
00143 static int decode_visual (XVisualInfo *v, struct allegro_gl_display_info *i);
00144 struct {
00145     int fullscreen;
00146     GLXContext ctx;
00147     int major, minor;   /* Major and minor GLX version */
00148     int error_base, event_base;
00149     int use_glx_window;
00150     GLXWindow window;
00151 } _glxwin;
00152 
00153 static void (*old_window_redrawer)(int, int, int, int);
00154 extern void (*_xwin_window_redrawer)(int, int, int, int);
00155 static int (*old_x_error_handler)(Display*, XErrorEvent*);
00156 
00157 
00158 
00159 /* allegro_gl_redraw_window :
00160  *  Redraws the window when an Expose event is processed
00161  *  Important note : no GL commands should be processed in this function
00162  *  since it may be called by a thread which is different from the main thread.
00163  *  In order to be able to process GL commands, we should create another context
00164  *  and make it current to the other thread. IMHO it would be overkill.
00165  */
00166 static void allegro_gl_redraw_window(int x, int y, int w, int h)
00167 {
00168     /* Does nothing */
00169     return;
00170 }
00171 
00172 
00173 
00174 #ifdef ALLEGRO_XWINDOWS_WITH_XCURSOR
00175 /* _xwin_hide_x_mouse:
00176  * Create invisible X cursor
00177  */
00178 static void _xwin_hide_x_mouse(void)
00179 {
00180     unsigned long gcmask;
00181     XGCValues gcvalues;
00182     Pixmap pixmap;
00183 
00184     XUndefineCursor(_xwin.display, _xwin.window);
00185 
00186     if (_xwin.cursor != None) {
00187         XFreeCursor(_xwin.display, _xwin.cursor);
00188         _xwin.cursor = None;
00189     }
00190 
00191     if (_xwin.xcursor_image != None) {
00192         XcursorImageDestroy(_xwin.xcursor_image);
00193         _xwin.xcursor_image = None;
00194     }
00195 
00196     pixmap = XCreatePixmap(_xwin.display, _xwin.window, 1, 1, 1);
00197     if (pixmap != None) {
00198         GC temp_gc;
00199         XColor color;
00200 
00201         gcmask = GCFunction | GCForeground | GCBackground;
00202         gcvalues.function = GXcopy;
00203         gcvalues.foreground = 0;
00204         gcvalues.background = 0;
00205         temp_gc = XCreateGC(_xwin.display, pixmap, gcmask, &gcvalues);
00206         XDrawPoint(_xwin.display, pixmap, temp_gc, 0, 0);
00207         XFreeGC(_xwin.display, temp_gc);
00208         color.pixel = 0;
00209         color.red = color.green = color.blue = 0;
00210         color.flags = DoRed | DoGreen | DoBlue;
00211         _xwin.cursor = XCreatePixmapCursor(_xwin.display, pixmap, pixmap, &color, &color, 0, 0);
00212         XDefineCursor(_xwin.display, _xwin.window, _xwin.cursor);
00213         XFreePixmap(_xwin.display, pixmap);
00214     }
00215     else {
00216         _xwin.cursor = XCreateFontCursor(_xwin.display, _xwin.cursor_shape);
00217         XDefineCursor(_xwin.display, _xwin.window, _xwin.cursor);
00218     }
00219 }
00220 #endif
00221 
00222 
00223 
00224 /* hide_mouse:
00225  *  Hide the custom X cursor (if supported)
00226  */
00227 static void hide_mouse(void)
00228 {
00229    #ifdef ALLEGRO_XWINDOWS_WITH_XCURSOR
00230    if (_xwin.support_argb_cursor) {
00231       XLOCK();
00232       _xwin_hide_x_mouse();
00233       XUNLOCK();
00234    }
00235    #endif
00236    return;
00237 }
00238 
00239 
00240 
00241 /* If Allegro's X11 mouse driver enabled hw cursors, we shouldn't use
00242  * allegro_gl_hide_mouse();
00243  */
00244 static void allegro_gl_x_hide_mouse(void)
00245 {
00246     if (_xwin.hw_cursor_ok) {
00247         hide_mouse();
00248     }
00249     else {
00250         allegro_gl_hide_mouse();
00251     }
00252 }
00253 
00254 
00255 
00256 /* allegro_gl_x_windowed_init:
00257  *  Creates screen bitmap.
00258  */
00259 static BITMAP *allegro_gl_x_create_screen(int w, int h, int vw, int vh,
00260                                           int depth, int fullscreen)
00261 {
00262     int _keyboard_was_installed = FALSE;
00263     int _mouse_was_installed = FALSE;
00264     int create_window_ret;
00265 
00266     /* test if Allegro have pthread support enabled */
00267     if (!_unix_bg_man->multi_threaded) {
00268         ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE,
00269                get_config_text("Fatal Error : pthread support is not enabled"));
00270         return NULL;
00271     }
00272     
00273     if (keyboard_driver) {
00274         _keyboard_was_installed = TRUE;
00275         remove_keyboard();
00276         TRACE(PREFIX_I "x_create_screen: Removing Keyboard...\n");
00277     }
00278     
00279     if (mouse_driver) {
00280         _mouse_was_installed = TRUE;
00281         remove_mouse();
00282         TRACE(PREFIX_I "x_create_screen: Removing Mouse...\n");
00283     }
00284     
00285     XLOCK();
00286 
00287     if (!glXQueryExtension(_xwin.display, &_glxwin.error_base,
00288                           &_glxwin.event_base)) {
00289 
00290         ustrzcpy (allegro_error, ALLEGRO_ERROR_SIZE,
00291                      get_config_text("GLX Extension not supported by display"));
00292         XUNLOCK();
00293         goto failure;
00294     }
00295 
00296     sscanf(glXQueryServerString(_xwin.display, _xwin.screen, GLX_VERSION),
00297             "%i.%i", &_glxwin.major, &_glxwin.minor);
00298 
00299     if ((w == 0) && (h == 0)) {
00300         w = 640;
00301         h = 480;
00302     }
00303 
00304     if ((vw > w) || (vh > h)) {
00305         ustrzcpy (allegro_error, ALLEGRO_ERROR_SIZE,
00306              get_config_text ("OpenGL drivers do not support virtual screens"));
00307         XUNLOCK();
00308         goto failure;
00309     }
00310 
00311     allegro_gl_display_info.w = w;
00312     allegro_gl_display_info.h = h;
00313 
00314     old_window_redrawer = _xwin_window_redrawer;
00315     _xwin_window_redrawer = allegro_gl_redraw_window;
00316     _glxwin.fullscreen = FALSE;
00317     _glxwin.use_glx_window = FALSE;
00318 
00319     create_window_ret = allegro_gl_x_create_window(fullscreen);
00320     if (create_window_ret) {
00321         if (fullscreen && create_window_ret == -2) {
00322             ustrzcpy (allegro_error, ALLEGRO_ERROR_SIZE,
00323                       get_config_text ("Unable to switch in GLX fullscreen"));
00324         }
00325         else if (create_window_ret == -2) {
00326             ustrzcpy (allegro_error, ALLEGRO_ERROR_SIZE,
00327                       get_config_text ("Unable to create GLX window"));
00328         }
00329         XUNLOCK();
00330         allegro_gl_x_exit(NULL);
00331         goto failure;
00332     }
00333 
00334     /* If pixel format is Allegro compatible, set up Allegro correctly. */
00335     set_color_depth(allegro_gl_display_info.colour_depth);
00336 
00337     /* XXX <rohannessian> X can run on Big-Endian systems. We need to 
00338      * make a check for that and pass TRUE to
00339      * __allegro_gl_set_allegro_image_format() in that case.
00340      */
00341     __allegro_gl_set_allegro_image_format(FALSE);
00342 
00343     if (fullscreen) {
00344         allegro_gl_screen =
00345                allegro_gl_x_windowed_create_screen (&gfx_allegro_gl_fullscreen,
00346                        allegro_gl_display_info.w, allegro_gl_display_info.h,
00347                        _color_depth);
00348     }
00349     else {
00350         allegro_gl_screen =
00351                 allegro_gl_x_windowed_create_screen (&gfx_allegro_gl_windowed,
00352                         allegro_gl_display_info.w, allegro_gl_display_info.h,
00353                         _color_depth);
00354     }
00355 
00356     if (!allegro_gl_screen) {
00357         ustrzcpy (allegro_error, ALLEGRO_ERROR_SIZE,
00358                   get_config_text ("Error creating screen bitmap"));
00359         XUNLOCK();
00360         allegro_gl_x_exit(NULL);
00361         goto failure;
00362     }
00363     
00364     __allegro_gl_valid_context = TRUE;
00365     __allegro_gl_driver = &allegro_gl_x;
00366 
00367     /* Print out OpenGL version info */
00368     TRACE(PREFIX_I "OpenGL Version: %s\n", (AL_CONST char*)glGetString(GL_VERSION));
00369     TRACE(PREFIX_I "OpenGL Vendor: %s\n", (AL_CONST char*)glGetString(GL_VENDOR));
00370     TRACE(PREFIX_I "OpenGL Renderer: %s\n", (AL_CONST char*)glGetString(GL_RENDERER));
00371     
00372     /* Detect if the GL driver is based on Mesa */
00373     allegro_gl_info.is_mesa_driver = FALSE;
00374     if (strstr((AL_CONST char*)glGetString(GL_VERSION),"Mesa")) {
00375         AGL_LOG(1, "OpenGL driver based on Mesa\n");
00376         allegro_gl_info.is_mesa_driver = TRUE;
00377     }
00378 
00379     /* Print out GLX version info */
00380     TRACE(PREFIX_I "GLX Version: %d.%d\n", _glxwin.major, _glxwin.minor);
00381 
00382 #ifdef LOGLEVEL
00383     if (glXIsDirect(_xwin.display, _glxwin.ctx)) {
00384         AGL_LOG(1, "GLX Direct Rendering is enabled\n");
00385     }
00386     else {
00387         AGL_LOG(1, "GLX Direct Rendering is disabled\n");
00388     }
00389 #endif
00390 
00391     /* Prints out GLX extensions info */
00392     AGL_LOG(1, "glX Extensions:\n");
00393 #ifdef LOGLEVEL
00394     __allegro_gl_print_extensions(
00395         (AL_CONST char*)glXQueryExtensionsString(_xwin.display, _xwin.screen));
00396 #endif
00397     /* Prints out OpenGL extensions info and activates needed extensions */
00398     __allegro_gl_manage_extensions();
00399     
00400     /* Update screen vtable in order to use AGL's */
00401     __allegro_gl__glvtable_update_vtable (&allegro_gl_screen->vtable);
00402     memcpy(&_screen_vtable, allegro_gl_screen->vtable, sizeof(GFX_VTABLE));
00403     allegro_gl_screen->vtable = &_screen_vtable;
00404 
00405     XUNLOCK();
00406 
00407     if (_keyboard_was_installed) {
00408         TRACE(PREFIX_I "x_create_screen: Installing Keyboard...\n");
00409         install_keyboard();
00410     }
00411 
00412     if (_mouse_was_installed) {
00413         TRACE(PREFIX_I "x_create_screen: Installing Mouse...\n");
00414         install_mouse();
00415     }
00416     gfx_capabilities |= GFX_HW_CURSOR;
00417 
00418     return allegro_gl_screen;
00419 
00420 failure:
00421     if (_keyboard_was_installed) {
00422         install_keyboard();
00423     }
00424 
00425     if (_mouse_was_installed) {
00426         install_mouse();
00427     }
00428 
00429     return NULL;
00430 }
00431 
00432 
00433 
00434 /* allegro_gl_x_windowed_init:
00435  *  Creates screen bitmap for windowed driver.
00436  */
00437 static BITMAP *allegro_gl_x_windowed_init(int w, int h, int vw, int vh,
00438                                           int depth)
00439 {
00440     return allegro_gl_x_create_screen(w, h, vw, vh, depth, FALSE);
00441 }
00442 
00443 
00444 
00445 /* allegro_gl_x_fullscreen_init:
00446  *  Creates screen bitmap for fullscreen driver.
00447  */
00448 static BITMAP *allegro_gl_x_fullscreen_init(int w, int h, int vw, int vh,
00449                                             int depth)
00450 {
00451     return allegro_gl_x_create_screen(w, h, vw, vh, depth, TRUE);
00452 }
00453 
00454 
00455 
00456 #ifdef ALLEGROGL_HAVE_XF86VIDMODE
00457 /* free_modelines:
00458  *  Free mode lines.
00459  */
00460 static void free_modelines(XF86VidModeModeInfo **modesinfo, int num_modes)
00461 {
00462    int i;
00463 
00464    for (i = 0; i < num_modes; i++)
00465       if (modesinfo[i]->privsize > 0)
00466      XFree(modesinfo[i]->private);
00467    XFree(modesinfo);
00468 }
00469 #endif
00470 
00471 
00472 
00473 /* allegro_gl_x_exit:
00474  *  Shuts down the driver (shared between windowed and full-screen)
00475  */
00476 static void allegro_gl_x_exit(BITMAP *bmp)
00477 {
00478 #ifdef ALLEGROGL_HAVE_XF86VIDMODE
00479     XSetWindowAttributes setattr;
00480 #endif
00481 
00482     XLOCK();
00483     /* We politely wait for OpenGL to finish its current operations before
00484        shutting down the driver */
00485     glXWaitGL();
00486 
00487     __allegro_gl_unmanage_extensions(); 
00488 
00489     if (_glxwin.ctx) {
00490         if (!allegro_gl_info.is_ati_r200_chip) {
00491             /* The DRI drivers for ATI cards with R200 chip
00492              * seem to be broken since they crash at this point.
00493              * As a workaround AGL does not release the GLX context
00494              * here. This should not hurt since the GLX specs don't
00495              * require the context to be released before the program
00496              * ends or before another context is made current to the
00497              * thread.
00498              */
00499             if (!glXMakeCurrent(_xwin.display, None, NULL)) {
00500                 ustrzcpy (allegro_error, ALLEGRO_ERROR_SIZE,
00501                           get_config_text ("Could not release drawing context.\n"));
00502             }
00503         }
00504 
00505         glXDestroyContext(_xwin.display, _glxwin.ctx);
00506         _glxwin.ctx = NULL;
00507     }
00508 
00509     if (_xwin.mouse_grabbed) {
00510         XUngrabPointer(_xwin.display, CurrentTime);
00511         _xwin.mouse_grabbed = 0;
00512     }
00513 
00514     if (_xwin.keyboard_grabbed) {
00515         XUngrabKeyboard(_xwin.display, CurrentTime);
00516         _xwin.keyboard_grabbed = 0;
00517     }
00518 
00519 #ifdef ALLEGROGL_HAVE_XF86VIDMODE
00520     if (_glxwin.fullscreen) {
00521         if (_xwin.mode_switched) {
00522             XF86VidModeLockModeSwitch(_xwin.display, _xwin.screen, False);
00523             XF86VidModeSwitchToMode(_xwin.display, _xwin.screen,
00524                                     _xwin.modesinfo[0]);
00525             XF86VidModeSetViewPort(_xwin.display, _xwin.screen, 0, 0);
00526             _xwin.mode_switched = 0;
00527         }
00528         if (_xwin.override_redirected) {
00529             setattr.override_redirect = False;
00530             XChangeWindowAttributes(_xwin.display, _xwin.window,
00531                                     CWOverrideRedirect, &setattr);
00532             _xwin.override_redirected = 0;
00533         }
00534 
00535         /* Free modelines.  */
00536         free_modelines(_xwin.modesinfo, _xwin.num_modes);
00537         _xwin.num_modes = 0;
00538         _xwin.modesinfo = NULL;
00539     }
00540 #endif
00541 
00542     /* Note: Allegro will destroy screen (== allegro_gl_screen),
00543      * so don't destroy it here.
00544      */
00545     //destroy_bitmap(allegro_gl_screen);
00546     ASSERT(allegro_gl_screen == screen);
00547     allegro_gl_screen = NULL;
00548 
00549     /* Unmap the window in order not to see the cursor when quitting.
00550        The window *must not* be destroyed and _xwin.visual must be left
00551        to its current value otherwise the program will crash when exiting */
00552     if (_xwin.window != None)
00553         XUnmapWindow(_xwin.display, _xwin.window);
00554 
00555     if (_glxwin.use_glx_window) {
00556         glXDestroyWindow(_xwin.display, _glxwin.window);
00557         _glxwin.window = 0;
00558         _glxwin.use_glx_window = FALSE;
00559     }
00560 
00561     __allegro_gl_valid_context = FALSE;
00562 
00563     _xwin_window_redrawer = old_window_redrawer;
00564     XSetErrorHandler(old_x_error_handler);
00565 
00566 
00567 #if GET_ALLEGRO_VERSION() >= MAKE_VER(4, 2, 1)
00568     /* Hack: Allegro 4.2.1 uses a persistent window, we need to restore it. */
00569     if (backup_allegro_window != None) {
00570         if (_xwin.colormap != None) {
00571             XUninstallColormap(_xwin.display, _xwin.colormap);
00572             XFreeColormap(_xwin.display, _xwin.colormap);
00573         }
00574         _xwin.colormap = backup_allegro_colormap;
00575 
00576         if (_xwin.window != None)
00577             XDestroyWindow(_xwin.display, _xwin.window);
00578         _xwin.window = backup_allegro_window;
00579         backup_allegro_window = None;
00580         XMapWindow(_xwin.display, _xwin.window);
00581     }
00582 #endif
00583 
00584     XUNLOCK();
00585 }
00586 
00587 
00588 
00589 /* get_shift:
00590  *  Returns the shift value for a given mask.
00591  */
00592 static int get_shift (int mask)
00593 {
00594     int i = 0, j = 1;
00595     if (!mask) return -1;
00596     while (!(j & mask)) {
00597         i++;
00598         j <<= 1;
00599     }
00600     return i;
00601 }
00602 
00603 
00604 
00605 static int decode_fbconfig (GLXFBConfig fbc, struct allegro_gl_display_info *i) {
00606     int render_type, visual_type, buffer_size, sbuffers, samples;
00607     int drawable_type, renderable;
00608     XVisualInfo *v;
00609 
00610     TRACE(PREFIX_I "decode_fbconfig: Decoding:\n");
00611     i->rmethod = 2;
00612 
00613     if (glXGetFBConfigAttrib (_xwin.display, fbc, GLX_RENDER_TYPE,
00614                             &render_type)
00615      || glXGetFBConfigAttrib (_xwin.display, fbc, GLX_X_RENDERABLE,
00616                             &renderable)
00617      || glXGetFBConfigAttrib (_xwin.display, fbc, GLX_DRAWABLE_TYPE,
00618                             &drawable_type)
00619      || glXGetFBConfigAttrib (_xwin.display, fbc, GLX_X_VISUAL_TYPE,
00620                             &visual_type)
00621      || glXGetFBConfigAttrib (_xwin.display, fbc, GLX_BUFFER_SIZE,
00622                             &buffer_size)
00623      || glXGetFBConfigAttrib (_xwin.display, fbc, GLX_DEPTH_SIZE,
00624                             &i->depth_size)
00625      || glXGetFBConfigAttrib (_xwin.display, fbc, GLX_STEREO,
00626                             &i->stereo)
00627      || glXGetFBConfigAttrib (_xwin.display, fbc, GLX_RED_SIZE,
00628                             &i->pixel_size.rgba.r)
00629      || glXGetFBConfigAttrib (_xwin.display, fbc, GLX_GREEN_SIZE,
00630                             &i->pixel_size.rgba.g)
00631      || glXGetFBConfigAttrib (_xwin.display, fbc, GLX_BLUE_SIZE,
00632                             &i->pixel_size.rgba.b)
00633      || glXGetFBConfigAttrib (_xwin.display, fbc, GLX_ALPHA_SIZE,
00634                             &i->pixel_size.rgba.a)
00635      || glXGetFBConfigAttrib (_xwin.display, fbc, GLX_DOUBLEBUFFER,
00636                             &i->doublebuffered)
00637      || glXGetFBConfigAttrib (_xwin.display, fbc, GLX_AUX_BUFFERS,
00638                             &i->aux_buffers)
00639      || glXGetFBConfigAttrib (_xwin.display, fbc, GLX_STENCIL_SIZE,
00640                             &i->stencil_size)
00641      || glXGetFBConfigAttrib (_xwin.display, fbc, GLX_ACCUM_RED_SIZE,
00642                             &i->accum_size.rgba.r)
00643      || glXGetFBConfigAttrib (_xwin.display, fbc, GLX_ACCUM_GREEN_SIZE,
00644                             &i->accum_size.rgba.g)
00645      || glXGetFBConfigAttrib (_xwin.display, fbc, GLX_ACCUM_BLUE_SIZE,
00646                             &i->accum_size.rgba.b)
00647      || glXGetFBConfigAttrib (_xwin.display, fbc, GLX_ACCUM_ALPHA_SIZE,
00648                       &i->accum_size.rgba.a)) {
00649         TRACE(PREFIX_I "decode_fbconfig: Incomplete glX mode ...\n");
00650         return -1;
00651     }
00652 
00653     if (!(render_type & GLX_RGBA_BIT) && !(render_type & GLX_RGBA_FLOAT_BIT)) {
00654         TRACE(PREFIX_I "decode_fbconfig: Not RGBA mode\n");
00655         return -1;
00656     }
00657 
00658     if (!(drawable_type & GLX_WINDOW_BIT)) {
00659         TRACE(PREFIX_I "decode_fbconfig: Cannot render to a window.\n");
00660         return -1;
00661     }
00662     
00663     if (renderable == False) {
00664         TRACE(PREFIX_I "decode_fbconfig: GLX windows not supported.\n");
00665         return -1;
00666     }
00667 
00668     if (visual_type != GLX_TRUE_COLOR && visual_type != GLX_DIRECT_COLOR) {
00669         TRACE(PREFIX_I "decode_fbconfig: visual type other than TrueColor and "
00670                         "DirectColor.\n");
00671         return -1;
00672     }
00673 
00674     /* Floating-point depth is not supported as glx extension (yet). */
00675     i->float_depth = 0;
00676 
00677     i->float_color = (render_type & GLX_RGBA_FLOAT_BIT);
00678 
00679     v = glXGetVisualFromFBConfig(_xwin.display, fbc);
00680     if (!v) {
00681         TRACE(PREFIX_I "decode_fbconfig: Cannot get associated visual for the "
00682                         "FBConfig.\n");
00683         return -1;
00684     }
00685     i->r_shift = get_shift (v->red_mask);
00686     i->g_shift = get_shift (v->green_mask);
00687     i->b_shift = get_shift (v->blue_mask);
00688     i->a_shift = 0;
00689 
00690     /* If we are going to need to setup a palette we need bit shifts */
00691     if ((visual_type == GLX_DIRECT_COLOR)
00692         && ((i->r_shift == -1) || (i->g_shift == -1) || (i->b_shift == -1))
00693         && (i->pixel_size.rgba.r + i->pixel_size.rgba.g + i->pixel_size.rgba.b
00694            <= 12)) {
00695         /* XXX <rohannessian> Report something here? */
00696         XFree(v);
00697         return -1;
00698     }
00699 
00700     i->colour_depth = 0;
00701 
00702     if (i->pixel_size.rgba.r == 3
00703      && i->pixel_size.rgba.g == 3
00704      && i->pixel_size.rgba.b == 2) {
00705         i->colour_depth = 8;
00706     }
00707 
00708     if (i->pixel_size.rgba.r == 5
00709      && i->pixel_size.rgba.b == 5) {
00710         if (i->pixel_size.rgba.g == 5) {
00711             i->colour_depth = 15;
00712         }
00713         if (i->pixel_size.rgba.g == 6) {
00714             i->colour_depth = 16;
00715         }
00716     }
00717 
00718     if (i->pixel_size.rgba.r == 8
00719      && i->pixel_size.rgba.g == 8
00720      && i->pixel_size.rgba.b == 8) {
00721         if (i->pixel_size.rgba.a == 0) {
00722             i->colour_depth = 24;
00723         }
00724         if (i->pixel_size.rgba.a == 8) {
00725             i->colour_depth = 32;
00726             /* small hack that tries to guess alpha shifting */
00727             i->a_shift = 48 - i->r_shift - i->g_shift - i->b_shift;
00728         }
00729     }
00730 
00731     i->allegro_format = (i->colour_depth != 0)
00732                      && (i->g_shift == i->pixel_size.rgba.b)
00733                      && (i->r_shift * i->b_shift == 0)
00734                      && (i->r_shift + i->b_shift
00735                                 == i->pixel_size.rgba.b + i->pixel_size.rgba.g);
00736 
00737     if (glXGetConfig(_xwin.display, v, GLX_SAMPLE_BUFFERS, &sbuffers)) {
00738         /* Multisample extension is not supported */
00739         i->sample_buffers = 0;
00740     }
00741     else {
00742         i->sample_buffers = sbuffers;
00743     }
00744     if (glXGetConfig(_xwin.display, v, GLX_SAMPLES, &samples)) {
00745         /* Multisample extension is not supported */
00746         i->samples = 0;
00747     }
00748     else {
00749         i->samples = samples;
00750     }
00751 
00752     XFree(v);
00753 
00754     TRACE(PREFIX_I "Color Depth: %i\n", buffer_size);
00755     TRACE(PREFIX_I "RGBA Type: %s point\n", i->float_color ? "floating" : "fixed");
00756     TRACE(PREFIX_I "RGBA: %i.%i.%i.%i\n", i->pixel_size.rgba.r, i->pixel_size.rgba.g,
00757           i->pixel_size.rgba.b, i->pixel_size.rgba.a);
00758     TRACE(PREFIX_I "Accum: %i.%i.%i.%i\n", i->accum_size.rgba.r, i->accum_size.rgba.g,
00759           i->accum_size.rgba.b, i->accum_size.rgba.a);
00760     TRACE(PREFIX_I "DblBuf: %i Zbuf: %i Stereo: %i Aux: %i Stencil: %i\n",
00761           i->doublebuffered, i->depth_size, i->stereo,
00762           i->aux_buffers, i->stencil_size);
00763     TRACE(PREFIX_I "Shift: %i.%i.%i.%i\n", i->r_shift, i->g_shift, i->b_shift,
00764           i->a_shift);
00765     TRACE(PREFIX_I "Sample Buffers: %i Samples: %i\n", i->sample_buffers, i->samples);
00766     TRACE(PREFIX_I "Decoded bpp: %i\n", i->colour_depth);
00767 
00768     return 0;
00769 }
00770 
00771 
00772 
00773 int allegro_gl_x_windowed_choose_fbconfig (GLXFBConfig *ret_fbconfig) {
00774     int num_fbconfigs, i;
00775     GLXFBConfig *fbconfig;
00776     struct allegro_gl_display_info dinfo;
00777 
00778     fbconfig = glXGetFBConfigs (_xwin.display, _xwin.screen, &num_fbconfigs);
00779     if (!fbconfig || !num_fbconfigs)
00780         return FALSE;
00781 
00782     TRACE(PREFIX_I "x_windowed_choose_fbconfig: %i formats.\n", num_fbconfigs);
00783     __allegro_gl_reset_scorer();
00784 
00785     for (i = 0; i < num_fbconfigs; i++) {
00786         TRACE(PREFIX_I "x_windowed_choose_fbconfig: Mode %i\n", i);
00787         if (decode_fbconfig (*(fbconfig + i), &dinfo) != -1) {
00788             __allegro_gl_score_config (i, &dinfo);
00789         }
00790     }
00791 
00792     i = __allegro_gl_best_config();
00793     TRACE(PREFIX_I "x_windowed_choose_fbconfig: Best FBConfig is: %i\n", i);
00794 
00795     if (i < 0) {
00796         XFree(fbconfig);
00797         return FALSE;
00798     }
00799 
00800     *ret_fbconfig = *(fbconfig + i);
00801     XFree(fbconfig);
00802 
00803     return TRUE;
00804 }
00805 
00806 
00807 
00808 /* windowed_choose_visual:
00809  *  Chooses a visual to use.
00810  */
00811 static XVisualInfo *allegro_gl_x_windowed_choose_visual (void)
00812 {
00813     int num_visuals, i;
00814     XVisualInfo *vinfo;
00815     struct allegro_gl_display_info dinfo;
00816     static XVisualInfo ret_vinfo;
00817 
00818     vinfo = XGetVisualInfo (_xwin.display, 0, NULL, &num_visuals);
00819     if (!vinfo) return NULL;
00820     
00821     TRACE(PREFIX_I "x_windowed_choose_visual: %i formats.\n", num_visuals);
00822     __allegro_gl_reset_scorer();
00823 
00824     for (i = 0; i < num_visuals; i++) {
00825         TRACE(PREFIX_I "x_windowed_choose_visual: Mode %i\n", i);
00826         if (decode_visual (vinfo + i, &dinfo) != -1) {
00827             __allegro_gl_score_config (i, &dinfo);
00828         }
00829     }
00830 
00831     i = __allegro_gl_best_config();
00832     TRACE(PREFIX_I "x_windowed_choose_visual: Best config is: %i\n", i);
00833 
00834     if (i < 0) return NULL;
00835 
00836     memcpy (&ret_vinfo, vinfo+i, sizeof ret_vinfo);
00837     XFree (vinfo);
00838 
00839     return &ret_vinfo;
00840 }
00841 
00842 
00843 
00844 #ifdef ALLEGROGL_HAVE_XF86VIDMODE
00845 /* get_xf86_modes:
00846  *  Test if the XF86VidMode extension is available and get the gfx modes
00847  *  that can be queried.
00848  */
00849 static int get_xf86_modes(XF86VidModeModeInfo ***modesinfo, int *num_modes)
00850 {
00851     int vid_event_base, vid_error_base;
00852     int vid_major_version, vid_minor_version;
00853 
00854     /* Test for presence of VidMode extension.  */
00855     if (!XF86VidModeQueryExtension(_xwin.display, &vid_event_base,
00856                                    &vid_error_base)
00857      || !XF86VidModeQueryVersion(_xwin.display, &vid_major_version,
00858                                  &vid_minor_version)) {
00859 
00860         ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE,
00861                   get_config_text("VidMode extension is not supported"));
00862         return -1;
00863     }
00864 
00865     if (!XF86VidModeGetAllModeLines(_xwin.display, _xwin.screen, num_modes,
00866                                     modesinfo)) {
00867         ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE,
00868                   get_config_text("Can not Get ModeLines"));
00869         return -1;
00870     }
00871 
00872     return 0;
00873 }
00874 #endif
00875 
00876 
00877 static int allegro_gl_x_error_handler(Display *display, XErrorEvent *err_event)
00878 {
00879     char buffer[256];
00880 
00881     XGetErrorText(display, err_event->error_code, buffer, 256);
00882     TRACE(PREFIX_E "%s\n", buffer);
00883     return 0;
00884 }
00885 
00886 
00887 /* create_window:
00888  *  Based on Michael's `_xwin[_private]_create_window' and the xdemos
00889  *  from the Mesa distribution (I don't remember which one).
00890  */
00891 static int allegro_gl_x_create_window (int fullscreen)
00892 {
00893     Window root;
00894     XVisualInfo *visinfo;
00895     XSetWindowAttributes setattr;
00896     unsigned long valuemask = CWBackPixel | CWBorderPixel | CWColormap
00897                             | CWEventMask;
00898     XSizeHints *hints;
00899     GLXFBConfig fbconfig;
00900     int use_fbconfig;
00901 
00902     if (_xwin.display == 0) {
00903         return -2;
00904     }
00905 
00906     old_x_error_handler = XSetErrorHandler(allegro_gl_x_error_handler);
00907 
00908     /* Fill in missing color depth info */
00909     __allegro_gl_fill_in_info();
00910 
00911     use_fbconfig = (_glxwin.major > 1 || (_glxwin.major == 1 && _glxwin.minor >= 3));
00912 
00913     if (use_fbconfig) {
00914         TRACE(PREFIX_I "x_create_window: using FBConfig routines\n");
00915 
00916         if (!allegro_gl_x_windowed_choose_fbconfig(&fbconfig)) {
00917             TRACE(PREFIX_I "x_create_window: Failed using FBConfig, switching "
00918                             "back to VisualInfo routines\n");
00919             use_fbconfig = FALSE;
00920             goto old_choose_visual;
00921         }
00922 
00923         /* Query back FBConfig components */
00924         if (decode_fbconfig(fbconfig, &allegro_gl_display_info)) {
00925             TRACE(PREFIX_E "x_create_window: Cannot decode FBConfig, switching "
00926                             "back to VisualInfo routines\n");
00927             use_fbconfig = FALSE;
00928             goto old_choose_visual;
00929         }
00930 
00931         visinfo = glXGetVisualFromFBConfig(_xwin.display, fbconfig);
00932         if (!visinfo) {
00933             TRACE(PREFIX_I "x_create_window: Failed to convert FBConfig to "
00934                         "visual, switching back to VisualInfo routines\n");
00935             use_fbconfig = FALSE;
00936             goto old_choose_visual;
00937         }
00938     }
00939     else {
00940 old_choose_visual:
00941         TRACE(PREFIX_I "x_create_window: using VisualInfo routines\n");
00942 
00943         /* Find best visual */
00944         visinfo = allegro_gl_x_windowed_choose_visual();
00945         if (!visinfo) {
00946             TRACE(PREFIX_E "x_create_window: Can not get visual.\n");
00947             XSetErrorHandler(old_x_error_handler);
00948             return -2;
00949         }
00950 
00951         /* Query back visual components */
00952         if (decode_visual (visinfo, &allegro_gl_display_info)) {
00953             TRACE(PREFIX_E "x_create_window: Can not decode visual.\n");
00954             XSetErrorHandler(old_x_error_handler);
00955             return -2;
00956         }
00957     }
00958 
00959     /* Log some information about it */
00960     switch (visinfo->class) {
00961         case TrueColor:
00962             AGL_LOG (1, "x.c: visual class: TrueColor\n");
00963             break;
00964         case DirectColor:
00965             AGL_LOG (1, "x.c: visual class: DirectColor\n");
00966             break;
00967         default:
00968             AGL_LOG (1, "x.c: visual class: invalid(!)\n");
00969     }
00970 
00971 
00972     /* Begin window creation. */
00973 
00974 #if GET_ALLEGRO_VERSION() >= MAKE_VER(4, 2, 1)
00975     /* Hack: For Allegro 4.2.1, we need to keep the existing window. */
00976     if (backup_allegro_window == None) {
00977         backup_allegro_window = _xwin.window;
00978         backup_allegro_colormap = _xwin.colormap;
00979         _xwin.colormap = None;
00980         XUnmapWindow(_xwin.display, _xwin.window);
00981     }
00982     else
00983 #endif
00984         XDestroyWindow (_xwin.display, _xwin.window);
00985 
00986     _xwin.window = None;
00987 
00988     root = RootWindow (_xwin.display, _xwin.screen);
00989 
00990     /* Recreate window. */
00991     setattr.background_pixel = XBlackPixel (_xwin.display, _xwin.screen);
00992     setattr.border_pixel = XBlackPixel (_xwin.display, _xwin.screen);
00993     setattr.colormap = XCreateColormap (_xwin.display, root, visinfo->visual, AllocNone);
00994     setattr.event_mask =
00995         ( KeyPressMask | KeyReleaseMask
00996         | EnterWindowMask | LeaveWindowMask
00997         | FocusChangeMask | ExposureMask
00998         | ButtonPressMask | ButtonReleaseMask | PointerMotionMask
00999         /*| MappingNotifyMask (SubstructureRedirectMask?)*/
01000     );
01001 
01002 #ifdef ALLEGROGL_HAVE_XF86VIDMODE
01003     if (fullscreen) {
01004         int i;
01005         int bestmode = 0;
01006         _xwin.num_modes = 0;
01007         _xwin.modesinfo = NULL;
01008         _glxwin.fullscreen = TRUE;
01009 
01010         if (get_xf86_modes(&_xwin.modesinfo, &_xwin.num_modes)) {
01011             ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE,
01012                       get_config_text("x_create_window: Can't get"
01013                                       "XF86VidMode info.\n"));
01014             XSetErrorHandler(old_x_error_handler);
01015             return -2;
01016         }
01017 
01018         /* look for mode with requested resolution */
01019         for (i = 0; i < _xwin.num_modes; i++)
01020         {
01021             if ((_xwin.modesinfo[i]->hdisplay == allegro_gl_display_info.w)
01022              && (_xwin.modesinfo[i]->vdisplay == allegro_gl_display_info.h))
01023                 bestmode = i;
01024         }
01025 
01026         setattr.override_redirect = True;
01027         if (!XF86VidModeSwitchToMode(_xwin.display, _xwin.screen,
01028                                      _xwin.modesinfo[bestmode])) {
01029 
01030             ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE,
01031                       get_config_text("Can not set XF86VidMode mode"));
01032             XSetErrorHandler(old_x_error_handler);
01033             return -1;
01034         }
01035 
01036         XF86VidModeSetViewPort(_xwin.display, _xwin.screen, 0, 0);
01037 
01038         /* Lock Mode switching */
01039         XF86VidModeLockModeSwitch(_xwin.display, _xwin.screen, True);
01040         _xwin.mode_switched = 1;
01041 
01042         allegro_gl_display_info.x = 0;
01043         allegro_gl_display_info.y = 0;
01044         allegro_gl_display_info.w = _xwin.modesinfo[bestmode]->hdisplay;
01045         allegro_gl_display_info.h = _xwin.modesinfo[bestmode]->vdisplay;
01046 
01047         valuemask |= CWOverrideRedirect;
01048         _xwin.override_redirected = 1;
01049     }
01050 
01051     _xwin.window = XCreateWindow (
01052         _xwin.display, root,
01053         allegro_gl_display_info.x, allegro_gl_display_info.y,
01054         allegro_gl_display_info.w, allegro_gl_display_info.h, 0,
01055         visinfo->depth,
01056         InputOutput,
01057         visinfo->visual,
01058         valuemask, &setattr
01059     );
01060 
01061 #else //ALLEGROGL_HAVE_XF86VIDMODE
01062     if (fullscreen) {
01063         /* Without Xf86VidMode extension we support only fullscreen modes which
01064          * match current resolution. */
01065         int fs_width  = DisplayWidth(_xwin.display, _xwin.screen);
01066         int fs_height = DisplayHeight(_xwin.display, _xwin.screen);
01067 
01068         if (fs_width  != allegro_gl_display_info.w
01069          || fs_height != allegro_gl_display_info.h) {
01070             TRACE(PREFIX_E "Only desktop resolution fullscreen available.");
01071             ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE,
01072                 get_config_text("Compiled without Xf86VidMode extension support.\n"
01073                                 "Only desktop resolution fullscreen available."));
01074             XSetErrorHandler(old_x_error_handler);
01075             return -1;
01076         }
01077 
01078         _glxwin.fullscreen = TRUE;
01079 
01080         /* Create the fullscreen window.  */
01081         _xwin.window = XCreateWindow(_xwin.display, root,
01082                                     allegro_gl_display_info.x, allegro_gl_display_info.y,
01083                                     fs_width, fs_height, 0,
01084                                     visinfo->depth,
01085                                     InputOutput,
01086                                     visinfo->visual,
01087                                     valuemask, &setattr);
01088 
01089         /* Map the fullscreen window.  */
01090         XMapRaised(_xwin.display, _xwin.window);
01091 
01092         /* Make sure we got to the top of the window stack.  */
01093         XRaiseWindow(_xwin.display, _xwin.fs_window);
01094     }
01095     else {
01096         _xwin.window = XCreateWindow (
01097             _xwin.display, root,
01098             allegro_gl_display_info.x, allegro_gl_display_info.y,
01099             allegro_gl_display_info.w, allegro_gl_display_info.h, 0,
01100             visinfo->depth,
01101             InputOutput,
01102             visinfo->visual,
01103             valuemask, &setattr
01104         );
01105     }
01106 #endif //ALLEGROGL_HAVE_XF86VIDMODE
01107 
01108     /* Set size and position hints for Window Manager :
01109      * prevents the window to be resized
01110      */
01111     hints = XAllocSizeHints();
01112     if (hints) {
01113         /* This code chunk comes from Allegro's src/x/xwin.c */
01114         hints->flags = PMinSize | PMaxSize | PBaseSize;
01115         hints->min_width  = hints->max_width  = hints->base_width
01116                           = allegro_gl_display_info.w;
01117         hints->min_height = hints->max_height = hints->base_height
01118                           = allegro_gl_display_info.h;
01119 
01120         XSetWMNormalHints(_xwin.display, _xwin.window, hints);
01121         XFree(hints);
01122     }
01123     
01124 
01125     /* Set WM_DELETE_WINDOW atom in WM_PROTOCOLS property
01126      * (to get window_delete requests).
01127      */
01128     {
01129         Atom wm_delete_window = XInternAtom(_xwin.display, "WM_DELETE_WINDOW", False);
01130         XSetWMProtocols(_xwin.display, _xwin.window, &wm_delete_window, 1);
01131     }
01132 
01133     /* Finish off the GLX setup */
01134     if (use_fbconfig)
01135         _glxwin.ctx = glXCreateNewContext (_xwin.display, fbconfig, GLX_RGBA_TYPE, NULL, True);
01136     else
01137         _glxwin.ctx = glXCreateContext (_xwin.display, visinfo, NULL, True);
01138 
01139     if (use_fbconfig) {
01140         _glxwin.window = glXCreateWindow(_xwin.display, fbconfig, _xwin.window, 0); 
01141         if (!_glxwin.window) {
01142             ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE,
01143                       get_config_text("Cannot create GLX window."));
01144             XSetErrorHandler(old_x_error_handler);
01145             return -1;
01146         }
01147         _glxwin.use_glx_window = TRUE;
01148     }
01149 
01150     if (!_glxwin.ctx) {
01151         ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE,
01152                   get_config_text("Can not create GLX context."));
01153         XSetErrorHandler(old_x_error_handler);
01154         return -1;
01155     }
01156     else {
01157         Bool ret;
01158 
01159         if (use_fbconfig)
01160             ret = glXMakeContextCurrent(_xwin.display, _glxwin.window, _glxwin.window, _glxwin.ctx);
01161         else
01162             ret = glXMakeCurrent (_xwin.display, _xwin.window, _glxwin.ctx);
01163 
01164         if (!ret) {
01165             ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE,
01166                       get_config_text("Cannot make GLX context current."));
01167             XSetErrorHandler(old_x_error_handler);
01168             return -1;
01169         }
01170     }
01171 
01172     /* Finish off the Allegro setup */
01173 
01174     /* Get associated visual and window depth (bits per pixel), and
01175      * store window size  */
01176     {
01177         XWindowAttributes getattr;
01178         XGetWindowAttributes(_xwin.display, _xwin.window, &getattr);
01179         _xwin.visual = getattr.visual;
01180         _xwin.window_depth = getattr.depth;
01181         _xwin.window_width = allegro_gl_display_info.w;
01182         _xwin.window_height = allegro_gl_display_info.h;
01183         _xwin.screen_depth = getattr.depth;
01184         _xwin.screen_width = allegro_gl_display_info.w;
01185         _xwin.screen_height = allegro_gl_display_info.h;
01186     }
01187 
01188     /* Destroy the current colormap (if any) */
01189     if (_xwin.colormap != None) {
01190         XUninstallColormap(_xwin.display, _xwin.colormap);
01191         XFreeColormap(_xwin.display, _xwin.colormap);
01192     }
01193 
01194     /* Create and install colormap.  */
01195     if (_xwin.visual->class == DirectColor) {
01196         _xwin.colormap = XCreateColormap(_xwin.display, _xwin.window,
01197                                          _xwin.visual, AllocAll);
01198     }
01199     else { /* must be TrueColor */
01200         _xwin.colormap = XCreateColormap(_xwin.display, _xwin.window,
01201                                          _xwin.visual, AllocNone);
01202     }
01203     XSetWindowColormap(_xwin.display, _xwin.window, _xwin.colormap);
01204     XInstallColormap(_xwin.display, _xwin.colormap);
01205 
01206     /* Setup a palette if needed */
01207     if (_xwin.visual->class == DirectColor) {
01208         XColor color;
01209         int rsize, gsize, bsize;
01210         int rmax, gmax, bmax;
01211         int rshift, gshift, bshift;
01212         int r, g, b;
01213 
01214         AGL_LOG (1, "x.c: Using DirectColor visual, setting palette...\n");
01215 
01216         rsize = 1 << allegro_gl_display_info.pixel_size.rgba.r;
01217         gsize = 1 << allegro_gl_display_info.pixel_size.rgba.g;
01218         bsize = 1 << allegro_gl_display_info.pixel_size.rgba.b;
01219 
01220         rshift = allegro_gl_display_info.r_shift;
01221         bshift = allegro_gl_display_info.b_shift;
01222         gshift = allegro_gl_display_info.g_shift;
01223 
01224         rmax = rsize - 1;
01225         gmax = gsize - 1;
01226         bmax = bsize - 1;
01227 
01228         color.flags = DoRed | DoGreen | DoBlue;
01229         for (r = 0; r < rsize; r++) {
01230             for (g = 0; g < gsize; g++) {
01231                 for (b = 0; b < bsize; b++) {
01232                     color.pixel = (r << rshift) | (g << gshift) | (b << bshift);
01233                     color.red = ((rmax <= 0) ? 0 : ((r * 65535L) / rmax));
01234                     color.green = ((gmax <= 0) ? 0 : ((g * 65535L) / gmax));
01235                     color.blue = ((bmax <= 0) ? 0 : ((b * 65535L) / bmax));
01236                     XStoreColor(_xwin.display, _xwin.colormap, &color);
01237                 }
01238             }
01239         }
01240     }
01241 
01242     /* Configure the window a bit */
01243     {
01244         XClassHint hint;
01245         XWMHints wm_hints;
01246 
01247         /* Set title.  */
01248         XStoreName(_xwin.display, _xwin.window, _xwin.window_title);
01249 
01250         /* Set hints.  */
01251         hint.res_name = _xwin.application_name;
01252         hint.res_class = _xwin.application_class;
01253         XSetClassHint(_xwin.display, _xwin.window, &hint);
01254 
01255         wm_hints.flags = InputHint | StateHint;
01256         wm_hints.input = True;
01257         wm_hints.initial_state = NormalState;
01258 
01259 #ifdef ALLEGRO_XWINDOWS_WITH_XPM
01260         if (allegro_icon) {
01261             wm_hints.flags |= IconPixmapHint | IconMaskHint  | WindowGroupHint;
01262             XpmCreatePixmapFromData(_xwin.display, _xwin.window, allegro_icon,&wm_hints.icon_pixmap, &wm_hints.icon_mask, NULL);
01263         }
01264 #endif
01265 
01266         XSetWMHints(_xwin.display, _xwin.window, &wm_hints);
01267     }
01268 
01269     /* Map window.  */
01270     XMapWindow(_xwin.display, _xwin.window);
01271 
01272 
01273     if (fullscreen) {
01274         AL_CONST char *fc = NULL;
01275         char tmp1[64], tmp2[128];
01276         int c = 0;
01277         int h = allegro_gl_display_info.h;
01278         int w = allegro_gl_display_info.w;
01279         
01280         /* This chunk is disabled by default because of problems on KDE
01281            desktops.  */
01282         fc = get_config_string(uconvert_ascii("graphics", tmp1),
01283             uconvert_ascii("force_centering", tmp2), NULL);
01284         if ((fc) && ((c = ugetc(fc)) != 0) && ((c == 'y') || (c == 'Y')
01285             || (c == '1'))) {
01286             /* Hack: make the window fully visible and center cursor.  */
01287             XWarpPointer(_xwin.display, None, _xwin.window, 0, 0, 0, 0, 0, 0);
01288             XWarpPointer(_xwin.display, None, _xwin.window, 0, 0, 0, 0,
01289                          w - 1, 0);
01290             XWarpPointer(_xwin.display, None, _xwin.window, 0, 0, 0, 0,
01291                          0, h - 1);
01292             XWarpPointer(_xwin.display, None, _xwin.window, 0, 0, 0, 0,
01293                          w - 1, h - 1);
01294         }
01295         XWarpPointer(_xwin.display, None, _xwin.window, 0, 0, 0, 0,
01296                      w / 2, h / 2);
01297         XSync(_xwin.display, False);
01298         
01299         /* Grab keyboard and mouse.  */
01300         if (XGrabKeyboard(_xwin.display, _xwin.window, False, GrabModeAsync,
01301             GrabModeAsync, CurrentTime) != GrabSuccess) {
01302             ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE,
01303                       get_config_text("Can not grab keyboard"));
01304             XSetErrorHandler(old_x_error_handler);
01305             return -1;
01306         }
01307         _xwin.keyboard_grabbed = 1;
01308         
01309         if (XGrabPointer(_xwin.display, _xwin.window, False, 
01310             PointerMotionMask | ButtonPressMask | ButtonReleaseMask,
01311             GrabModeAsync, GrabModeAsync, _xwin.window, None, CurrentTime)
01312          != GrabSuccess) {
01313 
01314             ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE,
01315                       get_config_text("Can not grab mouse"));
01316             XSetErrorHandler(old_x_error_handler);
01317             return -1;
01318         }
01319         _xwin.mouse_grabbed = 1;
01320     }
01321 
01322 
01323     /* Destroy current cursor (if any) */
01324     if (_xwin.cursor != None) {
01325         XUndefineCursor(_xwin.display, _xwin.window);
01326         XFreeCursor(_xwin.display, _xwin.cursor);
01327     }
01328 
01329     {
01330         /* Create invisible X cursor.  */
01331         Pixmap pixmap = XCreatePixmap(_xwin.display, _xwin.window, 1, 1, 1);
01332         if (pixmap != None) {
01333             GC temp_gc;
01334             XColor color;
01335             XGCValues gcvalues;
01336 
01337             int gcmask = GCFunction | GCForeground | GCBackground;
01338             gcvalues.function = GXcopy;
01339             gcvalues.foreground = 0;
01340             gcvalues.background = 0;
01341             temp_gc = XCreateGC(_xwin.display, pixmap, gcmask, &gcvalues);
01342             XDrawPoint(_xwin.display, pixmap, temp_gc, 0, 0);
01343             XFreeGC(_xwin.display, temp_gc);
01344             color.pixel = 0;
01345             color.red = color.green = color.blue = 0;
01346             color.flags = DoRed | DoGreen | DoBlue;
01347             _xwin.cursor = XCreatePixmapCursor(_xwin.display, pixmap, pixmap,
01348                                                &color, &color, 0, 0);
01349             XDefineCursor(_xwin.display, _xwin.window, _xwin.cursor);
01350             XFreePixmap(_xwin.display, pixmap);
01351         }
01352         else {
01353             _xwin.cursor = XCreateFontCursor(_xwin.display, _xwin.cursor_shape);
01354             XDefineCursor(_xwin.display, _xwin.window, _xwin.cursor);
01355         }
01356     }
01357 
01358     /* Wait for the first exposure event. See comment in Allegro's
01359      * xwin.c about why no blocking X11 function is used.
01360      */
01361     while (1) {
01362        XEvent e;
01363        if (XCheckTypedEvent(_xwin.display, Expose, &e)) {
01364           if (e.xexpose.count == 0) break;
01365        }
01366        rest(1);
01367    }
01368 
01369     return 0;
01370 }
01371 
01372 
01373 
01374 static BITMAP *allegro_gl_x_windowed_create_screen (GFX_DRIVER *drv, int w, int h, int depth)
01375 {
01376     BITMAP *bmp;
01377     int is_linear = drv->linear;
01378 
01379     drv->linear = 1;
01380     bmp = _make_bitmap (w, h, 0, drv, depth, 0);
01381     bmp->id = BMP_ID_VIDEO | BMP_ID_MASK;
01382     drv->linear = is_linear;
01383 
01384     if (bmp == 0) {
01385         ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE,
01386                   get_config_text("Not enough memory"));
01387         return NULL;
01388     }
01389     
01390     drv->w = w;
01391     drv->h = h;
01392 
01393     return bmp;
01394 }
01395 
01396 
01397 
01398 /* decode_visual:
01399  *  Used to read back the information in the visual.  0 = ok.
01400  */
01401 static int decode_visual (XVisualInfo *v, struct allegro_gl_display_info *i)
01402 {
01403     int rgba, buffer_size, use_gl, sbuffers, samples;
01404 
01405     TRACE(PREFIX_I "decode_visual: Decoding:\n");
01406     i->rmethod = 2;
01407 
01408     /* We can only support TrueColor and DirectColor visuals --
01409      * we only support RGBA mode */
01410     if (v->class != TrueColor && v->class != DirectColor)
01411         return -1;
01412 
01413     if (glXGetConfig (_xwin.display, v, GLX_RGBA, &rgba)
01414      || glXGetConfig (_xwin.display, v, GLX_USE_GL,       &use_gl)
01415      || glXGetConfig (_xwin.display, v, GLX_BUFFER_SIZE,  &buffer_size)
01416      || glXGetConfig (_xwin.display, v, GLX_RED_SIZE,     &i->pixel_size.rgba.r)
01417      || glXGetConfig (_xwin.display, v, GLX_GREEN_SIZE,   &i->pixel_size.rgba.g)
01418      || glXGetConfig (_xwin.display, v, GLX_BLUE_SIZE,    &i->pixel_size.rgba.b)
01419      || glXGetConfig (_xwin.display, v, GLX_ALPHA_SIZE,   &i->pixel_size.rgba.a)
01420      || glXGetConfig (_xwin.display, v, GLX_DOUBLEBUFFER, &i->doublebuffered)
01421      || glXGetConfig (_xwin.display, v, GLX_STEREO,       &i->stereo)
01422      || glXGetConfig (_xwin.display, v, GLX_AUX_BUFFERS,  &i->aux_buffers)
01423      || glXGetConfig (_xwin.display, v, GLX_DEPTH_SIZE,   &i->depth_size)
01424      || glXGetConfig (_xwin.display, v, GLX_STENCIL_SIZE, &i->stencil_size)
01425      || glXGetConfig (_xwin.display, v, GLX_ACCUM_RED_SIZE,
01426                       &i->accum_size.rgba.r)
01427      || glXGetConfig (_xwin.display, v, GLX_ACCUM_GREEN_SIZE,
01428                       &i->accum_size.rgba.g)
01429      || glXGetConfig (_xwin.display, v, GLX_ACCUM_BLUE_SIZE,
01430                       &i->accum_size.rgba.b)
01431      || glXGetConfig (_xwin.display, v, GLX_ACCUM_ALPHA_SIZE,
01432                       &i->accum_size.rgba.a)) {
01433         TRACE(PREFIX_I "x_create_window: Incomplete glX mode ...\n");
01434         return -1;
01435     }
01436 
01437     if (!rgba) {
01438         TRACE(PREFIX_I "x_create_window: Not RGBA mode\n");
01439         return -1;
01440     }
01441     
01442     if (!use_gl) {
01443         ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE,
01444                   get_config_text("OpenGL Unsupported"));
01445         return -1;
01446     }
01447     
01448     i->r_shift = get_shift (v->red_mask);
01449     i->g_shift = get_shift (v->green_mask);
01450     i->b_shift = get_shift (v->blue_mask);
01451     i->a_shift = 0;
01452     
01453     /* If we are going to need to setup a palette we need bit shifts */
01454     if ((v->class == DirectColor)
01455         && ((i->r_shift == -1) || (i->g_shift == -1) || (i->b_shift == -1))
01456         && (i->pixel_size.rgba.r + i->pixel_size.rgba.g + i->pixel_size.rgba.b
01457            <= 12)) {
01458         /* XXX <rohannessian> Report something here? */
01459         return -1;
01460     }
01461 
01462     i->float_color = 0;
01463     i->float_depth = 0;
01464 
01465     i->colour_depth = 0;
01466 
01467     if (i->pixel_size.rgba.r == 3
01468      && i->pixel_size.rgba.g == 3
01469      && i->pixel_size.rgba.b == 2) {
01470         i->colour_depth = 8;
01471     }
01472 
01473     if (i->pixel_size.rgba.r == 5
01474      && i->pixel_size.rgba.b == 5) {
01475         if (i->pixel_size.rgba.g == 5) {
01476             i->colour_depth = 15;
01477         }
01478         if (i->pixel_size.rgba.g == 6) {
01479             i->colour_depth = 16;
01480         }
01481     }
01482 
01483     if (i->pixel_size.rgba.r == 8
01484      && i->pixel_size.rgba.g == 8
01485      && i->pixel_size.rgba.b == 8) {
01486         if (i->pixel_size.rgba.a == 0) {
01487             i->colour_depth = 24;
01488         }
01489         if (i->pixel_size.rgba.a == 8) {
01490             i->colour_depth = 32;
01491             /* small hack that tries to guess alpha shifting */
01492             i->a_shift = 48 - i->r_shift - i->g_shift - i->b_shift;
01493         }
01494     }
01495 
01496     i->allegro_format = (i->colour_depth != 0)
01497                      && (i->g_shift == i->pixel_size.rgba.b)
01498                      && (i->r_shift * i->b_shift == 0)
01499                      && (i->r_shift + i->b_shift
01500                                 == i->pixel_size.rgba.b + i->pixel_size.rgba.g);
01501     
01502     if (glXGetConfig(_xwin.display, v, GLX_SAMPLE_BUFFERS, &sbuffers)
01503                                                          == GLX_BAD_ATTRIBUTE) {
01504         /* Multisample extension is not supported */
01505         i->sample_buffers = 0;
01506     }
01507     else {
01508         i->sample_buffers = sbuffers;
01509     }
01510     if (glXGetConfig(_xwin.display, v, GLX_SAMPLES, &samples)
01511                                                          == GLX_BAD_ATTRIBUTE) {
01512         /* Multisample extension is not supported */
01513         i->samples = 0;
01514     }
01515     else {
01516         i->samples = samples;
01517     }
01518 
01519     
01520     TRACE(PREFIX_I "Color Depth: %i\n", buffer_size);
01521     TRACE(PREFIX_I "RGBA: %i.%i.%i.%i\n", i->pixel_size.rgba.r, i->pixel_size.rgba.g,
01522           i->pixel_size.rgba.b, i->pixel_size.rgba.a);
01523     TRACE(PREFIX_I "Accum: %i.%i.%i.%i\n", i->accum_size.rgba.r, i->accum_size.rgba.g,
01524           i->accum_size.rgba.b, i->accum_size.rgba.a);
01525     TRACE(PREFIX_I "DblBuf: %i Zbuf: %i Stereo: %i Aux: %i Stencil: %i\n",
01526           i->doublebuffered, i->depth_size, i->stereo,
01527           i->aux_buffers, i->stencil_size);
01528     TRACE(PREFIX_I "Shift: %i.%i.%i.%i\n", i->r_shift, i->g_shift, i->b_shift,
01529           i->a_shift);
01530     TRACE(PREFIX_I "Sample Buffers: %i Samples: %i\n", i->sample_buffers, i->samples);
01531     TRACE(PREFIX_I "Decoded bpp: %i\n", i->colour_depth);
01532     
01533     return 0;
01534 }
01535 
01536 
01537 
01538 #ifdef ALLEGROGL_HAVE_XF86VIDMODE
01539 /* allegro_gl_x_fetch_mode_list:
01540  *  Generates a list of valid video modes (made after 
01541  *  _xvidmode_private_fetch_mode_list of Allegro)
01542  */
01543 static GFX_MODE_LIST* allegro_gl_x_fetch_mode_list(void)
01544 {
01545     int num_modes = 0;
01546     XF86VidModeModeInfo **modesinfo = NULL;
01547     GFX_MODE_LIST *mode_list;
01548     int i;
01549 
01550     XLOCK();
01551 
01552     if (get_xf86_modes(&modesinfo, &num_modes)) {
01553         XUNLOCK();
01554         return NULL;
01555     }
01556 
01557     /* Allocate space for mode list.  */
01558     mode_list = malloc(sizeof(GFX_MODE_LIST));
01559     if (!mode_list) {
01560         free_modelines(modesinfo, num_modes);
01561         XUNLOCK();
01562         return NULL;
01563     }
01564 
01565     mode_list->mode = malloc(sizeof(GFX_MODE) * (num_modes + 1));
01566     if (!mode_list->mode) {
01567         free(mode_list);
01568         free_modelines(modesinfo, num_modes);
01569         XUNLOCK();
01570         return NULL;
01571     }
01572 
01573     /* Fill in mode list.  */
01574     for (i = 0; i < num_modes; i++) {
01575         mode_list->mode[i].width = modesinfo[i]->hdisplay;
01576         mode_list->mode[i].height = modesinfo[i]->vdisplay;
01577         /* Since XF86VidMode can not change the color depth of
01578          * the screen, there is no need to define modes for other
01579          * color depth than the desktop's.
01580          */
01581         mode_list->mode[i].bpp = desktop_color_depth();
01582     }
01583 
01584     mode_list->mode[num_modes].width = 0;
01585     mode_list->mode[num_modes].height = 0;
01586     mode_list->mode[num_modes].bpp = 0;
01587     mode_list->num_modes = num_modes;
01588 
01589     free_modelines(modesinfo, num_modes);
01590 
01591     XUNLOCK();
01592     return mode_list;
01593 }
01594 #endif
01595 
01596 
01597 
01598 /* allegro_gl_x_vsync:
01599  *  Wait for a vertical retrace. GLX_SGI_video_sync is needed.
01600  */
01601 static void allegro_gl_x_vsync(void)
01602 {
01603     XLOCK();
01604     if (allegro_gl_extensions_GLX.SGI_video_sync) {
01605         unsigned int count;
01606 
01607         glXGetVideoSyncSGI(&count);
01608         glXWaitVideoSyncSGI(2, (count+1) & 1, &count);
01609     }
01610     XUNLOCK();
01611 }
01612 
01613 
01614 
01615 /******************************/
01616 /* AllegroGL driver functions */
01617 /******************************/
01618 
01619 /* flip:
01620  *  Does a page flip / double buffer copy / whatever it really is.
01621  */
01622 static void flip (void)
01623 {
01624     XLOCK();
01625     if (_glxwin.use_glx_window)
01626         glXSwapBuffers (_xwin.display, _glxwin.window);
01627     else
01628         glXSwapBuffers (_xwin.display, _xwin.window);
01629     XUNLOCK();
01630 }
01631 
01632 
01633 
01634 /* gl_on, gl_off:
01635  *  Switches to/from GL mode.
01636  */
01637 static void gl_on (void)
01638 {
01639 #ifdef OLD_ALLEGRO
01640     DISABLE();
01641 #endif
01642 }
01643 
01644 
01645 
01646 static void gl_off (void)
01647 {
01648 #ifdef OLD_ALLEGRO
01649     ENABLE();
01650     _xwin_handle_input();
01651 #endif
01652 }
01653 
01654 
01655 
01656 /*****************/
01657 /* Driver struct */
01658 /*****************/
01659 
01660 static struct allegro_gl_driver allegro_gl_x = {
01661     flip,
01662     gl_on,
01663     gl_off,
01664     NULL
01665 };
01666 
allegro4.4-4.4.2/addons/allegrogl/docs/mainpage.foo000066400000000000000000000315061173507505700220510ustar00rootroot00000000000000/** \file mainpage.foo * This file only contains the information useful for the main page of the * documentation - There is no code here. */ /** \mainpage AllegroGL \section contents Table Of Contents:
  • \ref aboutlib
  • \ref license
  • \ref aboutdoc
  • \ref genbuild
  • \ref require
  • \ref install
    • \ref unixinst
    • \ref minginst
    • \ref msvcinst
    • \ref dosinst
    • \ref macinst
  • \ref usagedocs
  • \ref moreinfo
  • \ref end
\section aboutlib About AllegroGL The library mostly provides functions to allow you to use OpenGL alongside Allegro -- you use OpenGL for your rendering to the screen, and Allegro for miscellaneous tasks like gathering input, doing timers, getting cross-platform portability, loading data, and drawing your textures. So this library fills the same hole that things like glut do. AllegroGL also automatically exposes most, if not all, OpenGL extensions available to user programs. This means you no longer have to manually load them; extension management is already done for you. \section license License The code is (C) AllegroGL contributors, and double licensed under the GPL and zlib licenses. See gpl.txt or zlib.txt for details. (You can pick whichever one you prefer.) \section aboutdoc About this document This document contains installation instructions, description of the API, reference manual, and pointers to other resources such as the FAQ, web page and the mailing list. \section genbuild General build instructions From version 0.4.4 onwards, AllegroGL is an addon library for Allegro and the usual way to build it is by following the allegro compilation procedure. It will configure, build and install AllegroGL using default options (a shared release library). However, you if you need a custom compiled library, e.g. with debug symbols or a statically linked one, you can build AllegroGL manually, passing custom build options. \section require Requirements General requirement: If you are building AllegroGL separatelly (outside Allegro compilation procedure) it will depend on Allegro being successfully built two directories above. \b Unix: You need an X server which provides the OpenGL/GLX functionality. If you have successfully installed 3D drivers (NVidia, DRI drivers, ...) then OpenGL/GLX libraries are already installed. Otherwise XFree86 4.x has OpenGL/GLX built in. We have also successfully used an earlier version, with development snapshots of Mesa3D 3.2 and GLX extensions. You also need to get the GLU library, preferably the SGI's one (see the Mesa sourceforge webpage - http://Mesa3D.sf.net/ ). If you want to build the generic driver you need Mesa 4.0 or higher (only the "MesaLib" archive is mandatory, the "MesaDemos" one is optionnal). Links to the relevant sites can be found on the AllegroGL web site. \b Windows/MSVC: MSVC6 or MSVC2005 IDE or GNU make is required for MSVC. \b Windows/Mingw: If you use Mingw, you'll need the OpenGL header files and libraries. These are normally included with Mingw. In case your copy of Mingw does not have the OpenGL headers, you can grab them here: ftp://ftp.microsoft.com/softlib/mslfiles/opengl95.exe This is a self-extracting archive. You'll also need GNU make (mingw32-make) to compile AllegroGL. \b DOS: You need DJGPP and Mesa 4.0 http://Mesa3D.sf.net/ for OpenGL rendering (only the "MesaLib" archive is mandatory, the "MesaDemos" one is optionnal). \b Mac OS X: System version 10.1.x or newer is required to build AllegroGL. Allegro WIP 4.1.11 or newer is also required, as older versions did not support OS X. \section install Installation \subsection unixinst Unix instructions For an optimised build, run `./configure' and `make' from the directory containing this file. This will build the library (in 'lib/unix/') and the examples (in 'examp/'). Use `make install' to install the library and header file. For that part you need write access to /usr/local. If you want to build the generic driver, run `./configure --enable-generic' and `make MESADIR=xxx' where xxx is the path to the Mesa 4.0 directory. This will build both Mesa (GL and GLU) and AllegroGL For a debug build, add `DEBUGMODE=1' on each of the command lines. If you get errors about missing header files or libraries, either for X or GL, see the instructions at the top of `makefile'. Note that you need to have the X development package installed, if you are using Red Hat Linux or Debian GNU/Linux. \subsection minginst Mingw/32 instructions Mingw 2.0 and higher already come with the OpenGL header files and libraries, so you can skip the next step. If you don't have the OpenGL header files (GL\\gl.h) and libraries, you will first need to acquire thrm. These can be obtained from the Microsoft site, or from MSVC. If you obtained the self-extracting archive from the Microsoft site, then run it. Move the produced header files (*.h) into C:\\Mingw32\\include\\GL\\ (replace C:\\Mingw32 by wherever you happen to have installed Mingw). Ignore the other files, as they are only useful for MSVC. You need to set up your environment if you haven't done that already. Environment variable "PATH" should point to the "bin" directory of Mingw. You can check that by typing "gcc" in the console. It must display something like: "gcc: no input files". If it complains about a unknown command then type "set PATH=%PATH%;C:\Mingw32\bin" (replace C:\\Mingw32 by wherever you happen to have installed Mingw). Also, you need to set MINGDIR env. variable. It must point to Mingw instalation directory: "set MINGDIR=C:\Mingw32". You can check that with: "echo %MINGDIR%". You will need to run 'fix mingw32' in the AllegroGL directory to update makefile for Mingw32. Since both Allegro and AllegroGL have native Mingw support I am happy to say that you can build Allegro/AllegroGL programs entirely using free software. For an optimised build, run `make' from the directory containing this file. Use `make install' to install the library and header file. Some versions of Mingw come with `mingw32-make' instead of `make', so you may need to run that instead. For a debug build, do the same but write `DEBUGMODE=1' on each of the command lines; for example, 'make DEBUGMODE=1' and 'make install DEBUGMODE=1'. Add 'STATICLINK=1' to the last two commands to build AllegroGL that can be linked to statically linked allegro. \subsection msvcinst MSVC6/7/8 instructions There are two completely different ways of compiling AllegroGL using MSVC. You can use the old-fashion way decribed bellow (similar to building allegro, using a GNU makefile and a command line), or you can locate the project file for your MSVC version in "projects" directory and compile AllegroGL lib and examples with a few mouse clicks. You'll have to manually copy libs and headers to appropiate locations. You can choose between several build configuration, depending against which Allegro library you want AllegroGL to be linked to. These configurations are:
 
   _____________________________________________________________
  | Configuration name  |    AGL lib name    | Allegro lib name |
  |-------------------------------------------------------------|
  | Release             | agl.lib            | alleg.lib        |
  | DLL Release         | agl.lib & agl.dll  | alleg.lib        |
  | Static Release      | agl_s.lib          | alleg_s.lib      |
  | Static Release CRT  | agl_s_crt.lib      | alleg_s_crt.lib  |
  | Debug               | agld.lib           | alld.lib         |
  | Static Debug        | agld_s.lib         | alld_s.lib       |
   -------------------------------------------------------------
All configuration except "DLL Release" produce AllegroGL library that is statically linked to the executable. Instructione for compiling AllegroGL using command line follow. You must have a working copy of GNU Make (useful for building Allegro, anyway). This can be either DJGPP's or Mingw's (recommended). \b Step \b 1: The first thing you need to do is find `vcvars32.bat', somewhere in your Visual Studio directories (most probably, it's in 'vc98/bin'). Running this batch file will enable the command line compiler for the current DOS session. If you will use it often, or find that typing 'c:\\progra~1\\micros~2\\vc98\\bin\\vcvars32.bat' gets annoying after a while, then (under Windows 9X) simply add that command to your autoexec.bat** Note: If at any stage, you get an "Out of Environment space" message, then please see the Allegro FAQ for how to fix this. ** The procedure is different for Windows ME and later. If you're running Windows ME, you'll need to select "Run" off the start menu, then type in "msconfig". Select the environment tab. Add the lines inside vcvars32.bat in there by copy/pasting them. Reboot your computer for the changes to take effect. If you're running Windows 2000/XP (NT?), then open Control Pannel, then the "System" applet, then the "Advanced" tab, and finally the "Environment" button. Add the environment variables as they are in vcvars32.bat. This has to be done manually (yes it's long and painful, please redirect all flames to billg@microsoft.com) You will need to log off and log back in for the changes to take effect. \b Step \b 2: Much like making Allegro, to configure AllegroGL for your compiler please run in the command prompt: fix.bat msvc6 - for MSVC 6 and older fix.bat msvc7 - for MSVC 7 (.NET) and 7.1 (.NET 2003) fix.bat msvc8 - for MSVC 8 (.NET 2005) Then type `make' to build the library in optimized mode, then `make install' to install the library and header files in your MSVC directory. For a debugging version, add `DEBUGMODE=1', to the last two command lines. To link against a static runtime libraries, rather than the default dynamic runtime libraries, add STATICRUNTIME=1, to the last two command lines. To link aginst a static version of allegro, add STATICLINK=1, to the last two command lines. If you are using Mingw for GNU make, then you may need to run `mingw32-make' instead of `make'. \subsection dosinst Dos instructions Please note that DOS support is currently in experimental stages. Unzip the archive files MesaLib-4.0.zip wherever you want. Unzip AllegroGL Create the environment variable MESADIR which defines the Mesa sources path : set MESADIR=xxx where 'xxx' is the path to the Mesa root directory Go to the root directory of AllegroGL type 'fix djgpp' (without quotes) followed by 'make'. The GL, GLU and AllegroGL libraries are built. Finally type 'make install' to install the library You're done! You can now use AllegroGL on DOS. Try the example demos... For a debug build, do the same but write `DEBUGMODE=1' on each of the command lines. Note that you can also build : - The GLUT library (based on AMesa, Allegro and Mesa). Type 'make glut' to build it then 'make install-glut' to install it. - The Mesa samples to test both Mesa and GLUT (note that you need to download the MesaDemos archive file to compile mesa samples). Type 'make mesa-samples' (Please note that not all the sample programs will be built. Now, as of Mesa 3.4.2, most demos are for GLUT which has not yet been completely ported to AMesa/Allegro). \subsection macinst Mac OS X instructions First you will need to run `./fix.sh macosx' in order to prepare the makefile for Mac OS X. Then `make' will build the library (in `lib/macosx') and the examples (in `examp/'). Use `sudo make install' to install the library and the header files; this step will require your system root password and will install into /usr/local. For a debug build, add `DEBUGMODE=1' on `make' and `make install' calls, for example, `make DEBUGMODE=1' and `sudo make install DEBUGMODE=1'. \section usagedocs Using AllegroGL A reference to the functions and macros available to user programs can be found by clicking on the links on top of this document, or online at the web site, and is also downloadable from there in various formats. The quick start guide and the FAQ are included in the distribution in the root directory. \section moreinfo More information web site: http://allegrogl.sourceforge.net/ The web site has introductory information, system requirements, downloads, and Allegro patches, along with an online version of the reference manual. mailing list: allegrogl-general@lists.sourceforge.net All the developers are on this mailing list, and most of the discussion here is about future development and bug fixing. General questions about using the library make a welcome change from the hard work of development, so newcomers are very welcome! If you're not subscribed to the list, make this clear when you post, so that people can Cc: their replies to you. \section end Closing Words Good luck... -- The AllegroGL team */ allegro4.4-4.4.2/addons/allegrogl/examp/000077500000000000000000000000001173507505700177405ustar00rootroot00000000000000allegro4.4-4.4.2/addons/allegrogl/examp/a1.bmp000066400000000000000000000055101173507505700207420ustar00rootroot00000000000000BMH 6(@@  ÿÿÿÿÿÿ@ÿÿ>ÿÿ4 ÿÿ-ÿÿ.ÿÿ&ÿÿ'ÿÿ'ÿÿ'ÿÿ)ÿÿ%ÿÿ(ÿÿ&ÿÿ(ÿÿ$ÿÿÿÿ ÿÿ ÿÿÿÿ  ÿÿ ÿÿÿÿ"ÿÿ  ÿÿÿÿ ÿÿÿÿÿÿ ÿÿÿÿ!ÿÿÿÿÿÿ ÿÿÿÿÿÿ ÿÿ ÿÿ  ÿÿ  ÿÿ  ÿÿ ÿÿ  ÿÿ  ÿÿ ÿÿ  ÿÿ   ÿÿÿÿ  ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿ ÿÿÿÿÿÿ ÿÿ ÿÿ>ÿÿ>ÿÿ>ÿÿ>ÿ@ÿallegro4.4-4.4.2/addons/allegrogl/examp/a24.tga000066400000000000000000000166131173507505700210320ustar00rootroot00000000000000 @@ ¿ÿÿÿÿ½ÿÿÿÿÿÿ½ÿÿÿÿÿÿ½ÿÿÿÿÿÿ›ÿÿ‚˜ÿÿÿÿÿÿ˜ÿÿ   •ÿÿÿÿÿÿ–ÿÿ   &/67652- ' #   ’ÿÿÿÿÿÿ•ÿÿ  !3AO# `($k*%o*#m)!i(e'`#V NC5 & ÿÿÿÿÿÿ“ÿÿ 1G""`+*x3/‹:5ž@8©B8­B6«B4¨B2¤?.=,–:(Œ4#|+f"O= ) ÿÿÿÿÿÿ‘ÿÿ ,B "]*,{67š@=²GCÄMGÒTIÞUHßUEÚVCÙWAÙV>ÓT;ÍT8ÈO3ºF,¤<%Š0m$R8" ÿÿÿÿÿÿÿÿ !8 S&+s16’=A²GIÌPMßUOèWPì]Qö_Oö^KïaIòcIõaEïcCíeBðb>æ[9ÔU2ÁH+¥œ÷o>ùl:ïe5Þ^0ËO'©<€(T /  Šÿÿÿÿÿÿÿÿ$ 0"Q%3|4E©@QÍHYâM[ìR\÷U]üTYôSTîROæNJÙLDÍK@ÅK>ÂN=ÆR=ÌV<Ñ\<Ûb=åg=ën=õp>ùp;õq8òn5ëd/ÔQ'­;}&O * Šÿÿÿÿÿÿÿÿ%0#R%54H­@VÒI^ìNa÷O_õR\õR\öOVêJN×DEÃ>=®95œ5.Ž5,Š8+;,”A.žH/¬R3¿\5Ñe8ãl:íp8óu9úu8ùp4ëc.ÐP$¨7s C ‰ÿÿÿÿÿÿŒÿÿ& &!L#5{2H«?XÓF`éMd÷PeþN`öLZêITßDLË;A°24‘))u#!b UP Q#W(b/q;$ˆG)¢U/¾a2Ôl5èt7öv6øu3óp0çb*ÉI—.^ 0 ‰ÿÿÿÿÿÿŒÿÿ& $D 3s/H¦#Q/l?"‹P)®a/Ïn2æu3òy4øy1ön-àW$²;y! C‰ÿÿÿÿÿÿ‹ÿÿ 8-d*C˜7WÇBdçHiøKkþIfõF]å?SÍ5Dª+5†!&dE1      %=)[;€Q&«d,Ïs/êz0÷t-éc&ÆH‘,W*ˆÿÿÿÿÿÿŠÿÿ  /'U$>ˆ2U¼>dáCiñHj÷Hi÷Ebér÷@q÷@mò;eá2T½%>Š'X1 Œÿÿ  62bPœj$Îz'ê(ò€&ñw#ád¼F„* O' †ÿÿÿÿÿÿ‡ÿÿ *)RB…+Z¸5iÜ;ró?wþ>sø;kç4]È(F™-d7 ÿÿ #% HB_¶u$Ý‚&ó†&û$ñqÓX¤:k ; †ÿÿÿÿÿÿ†ÿÿ !A:r&T¨0hÕ7sì:uôA qc«~Ùò‘ø‰ëuÉU‘0S' ƒÿÿÿÿÿÿ„ÿÿ -5_U™$rÎ+‚ï.ˆü.…÷+{å$gÀJ‰+P(–ÿÿ 29 c\{Ñ‹ë‘óì|Ð\›7 ], ƒÿÿÿÿÿÿƒÿÿ #=Asc°%yÚ+„ñ,ˆø,„ò'uØZ§                   "%5!Q<~\²vÛ ïƒ ó ënÎQœ1b 3‚ÿÿÿÿ<ÿÿÿÿ %%IFƒ"e»)yá+„õ/„ù-~ñ,iÒ&M£!.qK 9,02427 9 < A"F!H!J!JFDCBABABCC E"F$G'I *L ,O.Z1o04J6¹a9Þl;òo=ùl=ôb8ßL2µ2&~G # ÿÿÿÿ<ÿÿ =.k)J¡2dÓ8qïpöAeë@RÐ=8§< „;l;_<_>c>f= g= j:i;m<t=z>€?…= †;"…7#3&~1'|.)|,,|*-z'/z&2{#5{"8} <€>€A€E„KˆNŠQ‘Už'X±7ZËE]æM`÷NdýLdúH`í=WÑ.D -d 3 ÿÿÿÿ?ÿÿ 2$]53”CHÃLWæR]ùW\þXVù\Iî^7×^$½`¨b Ÿdšfžf£g §d§a§^¨^¬\°\"¶]&½]+ÂZ.ÄW1ÂQ2¼M5ºI9ºF=¹B?¸?C¹áhCómBûq?ýu8ûy.ò|!æÛ цщÓ‰Ô‰ ؈ ܃ÙØ}ÜyÛu#Ýu(ãs-æo1æn6ìj9êb;â_@â\EæXIäSLâPRåLUãGYàC_äAdæ=gä9læ5qæ0uä-|ê*ƒî&„ê#Ší ó ‘ó!”ø›ü þ¡þ¦ý£÷Šßa§8b- ÿÿÿÿ?ÿÿ  32mR)¯k1àx3õ{3û~1ý„+þ†'ü‹ù‘õ•ò• ìšðŸôœðœ ò› ÷–óñŒõ‡ò$ð)ö}.÷x2ôv7ùq<ùj>ñfDôdKú_Nô[QóXXùT[õM_ñJeöGjøCmô?s÷:w÷4zñ1‚ø-‰ü)Šö%ø!˜þ—ù™ú¤þ¨ÿ©ÿ °ÿ ³ýšìn¸?n2 ÿÿÿÿ?ÿÿ  =<_+Æz.ò„,ýƒ-þ†*ÿ#ÿŽ ýû˜üû› ô ø¥þ¢÷Ÿ øŸ þ˜÷“öü‹÷‚#ñ*÷~.÷x1ót6õo:óh>ífEódKú_Nô[QóXXùT[õM_ñJeöGjøCmô?s÷:w÷5yð0ò,†õ(ˆñ$ó ”ø–ö—ø¡ý¤þ¥þ«þ«ü“êh¸röAsýCpüFfòERÖ:8¡%a- ÿÿÿÿ?ÿÿ0$#e<8£QFÖ_KñfKüiGýlBúk:ðj/ÝiÅg±e £d›b˜`–]”Z ’V RŽN‹J‡Eƒ@}<z8u3o/l/o.#s.&v-)y++{*-z'/z&2{#5{"7| :~;z;vj?u"@Š5BªLEÎ]GìcIøhEùi>î_0ÐJ ™.\ , ÿÿÿÿ?ÿÿ %%R&?Ž6WÆ@fêHiùLgüL`öJSàH=¿C&—A{?h<]:Y8X5T3T1R.P, N) L& H# D A >;99<??ABABCBB!C ? ; 8 746 C \: „W%µq&Ý~'ñ‚%õ!íuÑYœ6 _- ÿÿÿÿ&ÿÿ  'GHh»'}â,ƒô.‚õ/zë+iÐ'K¡%,r!M5-+''&%""!                      :8h]  |ÒŽð•ú’ôƒ×d ¢?c1 ÿÿÿÿÿÿ+B N{u¸ã™öš÷èxÅR/U -        ‚*6W\’~É” î› ùš õŠ ÜlªDj#6ÿÿÿÿÿÿ-@Sy ~· œå§ù¦ù›æ ¼ U/FŸÿÿ $3PXŠ}Å’ èš ô™ ó ßq²Hr%;ÿÿÿÿÿÿ-@Vy· žá ªó Ÿâ‚¹X|/C ÿÿ-HT…x À ç›øš÷Ž ãr µKx(?ÿÿÿÿÿÿ.AX{‚·¡ã®õ¡ãƒ¸Y|.A ÿÿ+EPt »å—öŒär ¸Kx(@ÿÿÿÿÿÿ0BXyƒ¶£ä²ú£äƒ·Xy0B ÿÿ)BL|q ¸‰à“ñ‰àq ·Kz)Bÿÿÿÿÿÿ.?Vv² Þ¯ò Þ²Vv.? ÿÿ'@Ixo·‰ã”õ‰ãp¹K |)Cÿÿÿÿÿÿ+;Rp~¬žØ¬ìžØ~¬Rp+; ÿÿ&?G vmµ‰ä•ø•ùŠæp»L ~*Fÿÿÿÿÿÿ(6Niz¥ŸØ²ñŸØz¥Ni(6 ÿÿ#;D qi¯„Ýòó†ãp¼L €*F ÿÿÿÿÿÿ#/E]q—™Í±í™Íq—E]#/ ÿÿ  5> hb¦×ðõ‡æo¼K (D ÿÿÿÿÿÿ $6H[z©–È©[z6H$  ÿÿ -6 [[™zÐó•ýˆèl·G x&@ÿÿÿÿÿÿ #.=RXviŒXv=R#.  ÿÿ$,JK €l·ƒ߉é|Ò^Ÿ< f5 ÿÿÿÿÿÿÿÿ #.2B jB p: c*H+  ÿÿÿÿÿÿÿÿ    £ÿÿ  *5!81$ ÿÿÿÿÿÿƒÿÿ¦ÿÿ     ‚ÿÿÿÿ¿ÿÿTRUEVISION-XFILE.allegro4.4-4.4.2/addons/allegrogl/examp/a32.tga000066400000000000000000000234001173507505700210210ustar00rootroot00000000000000 @@ (¿ÿüÿÿüÿ½ÿüÿÿüÿ½ÿüÿÿüÿ½ÿüÿÿüÿ›`Vÿ‚`VÿaTÿcSÿfPÿfPÿ˜ÿüÿÿüÿ˜Z\ÿ[Zÿ]Yÿ^Wÿ ^Wÿ_Uÿ`UÿbSÿcRÿdQÿgMÿhLÿiJÿ jIÿkIÿ•ÿüÿÿüÿ–Z\ÿZ\ÿZ[ÿ [Zÿ\Yÿ]Xÿ&^Vÿ/_Uÿ6`Tÿ7aSÿ6cQÿ5eOÿ2gMÿ-hLÿ'iJÿ#jIÿkGÿlGÿ mFÿ qCÿ’ÿüÿÿüÿ•W_ÿW_ÿ X^ÿX\ÿ!ZZÿ3[YÿA]WÿO^Vÿ``UÿkaTÿobRÿmcPÿieOÿegLÿ`hKÿViJÿNkHÿClGÿ5mFÿ&nEÿoDÿqCÿqCÿÿüÿÿüÿ“ReÿScÿUaÿV_ÿW]ÿ1Y\ÿGZ[ÿ`[Yÿx]Wÿ‹^Vÿž`Tÿ©aSÿ­bQÿ«dOÿ¨fMÿ¤gKÿhJÿ–jIÿŒkHÿ|lFÿfmDÿOnDÿ=pBÿ)rAÿs@ÿt?ÿÿüÿÿüÿ‘OiÿQfÿQfÿRdÿTbÿ,U`ÿBW]ÿ]X\ÿ{Y[ÿš[Xÿ²]WÿÄ^VÿÒ`TÿÞaRÿßcQÿÚeOÿÙfLÿÙhKÿÓiIÿÍkHÿÈlFÿºmEÿ¤nDÿŠpBÿmqBÿRr@ÿ8t?ÿ"t?ÿw=ÿw=ÿÿüÿÿüÿOiÿOiÿOhÿQfÿ!Rdÿ8SbÿSU`ÿsV^ÿ’W]ÿ²Y[ÿÌ[Xÿß]Wÿè^Vÿì`TÿöbRÿödPÿïfMÿògLÿõhJÿïkHÿíkFÿðmEÿænDÿÔpBÿÁpBÿ¥r?ÿ‡s?ÿet>ÿCu=ÿ*w<ÿx;ÿ w=ÿŒÿüÿÿüÿ NiÿMiÿNhÿ,PfÿEQdÿfRcÿ‡Taÿ¨V^ÿÅW]ÿÚZZÿé[Yÿö\Wÿ÷_Vÿô`TÿøbRÿ÷dPÿñfMÿ÷gLÿüiJÿökGÿ÷lEÿþnDÿ÷pCÿîq@ÿçr?ÿÕs>ÿ»t>ÿšu=ÿtv<ÿQw;ÿ2x:ÿy:ÿ |7ÿ‹ÿüÿÿüÿŽ#JoÿJnÿLkÿMjÿ.NhÿNOhÿuPeÿœRcÿ¼TaÿÔV^ÿèW]ÿòY\ÿóZYÿø\Xÿ÷^Vÿï`TÿëbRÿècPÿåfMÿêgLÿïjIÿíkFÿòmEÿùoCÿöq@ÿ÷r?ÿùs>ÿït=ÿÞv<ÿËw;ÿ©w;ÿ€x:ÿTy:ÿ/y9ÿz9ÿ |7ÿŠÿüÿÿüÿ$JoÿJoÿJnÿKlÿ0LjÿQMiÿ|Nhÿ©PeÿÍQdÿâSbÿìU_ÿ÷V^ÿüX]ÿôYZÿî[Xÿæ\WÿÙ^UÿÍaSÿÅcQÿÂeNÿÆgLÿÌiIÿÑkFÿÛmDÿåpBÿër@ÿõs?ÿùu=ÿõw;ÿòw:ÿëx9ÿÔx9ÿ­y8ÿ}z8ÿOz7ÿ*z8ÿ|7ÿŠÿüÿÿüÿ%FrÿHpÿInÿ0InÿRKkÿLjÿ­NhÿÒOfÿìQdÿ÷RcÿõU`ÿõU_ÿöV^ÿêX\ÿ×YZÿÃ[Yÿ®]Vÿœ`SÿŽbRÿŠeNÿfLÿ”iJÿžkFÿ¬mDÿ¿pAÿÑr?ÿãt>ÿív;ÿów:ÿúx9ÿùy8ÿëy8ÿÐz7ÿ¨z7ÿs{6ÿC{6ÿ|6ÿ |7ÿ‰ÿüÿÿüÿŒ&EsÿGrÿGqÿ&HpÿLInÿ{Jlÿ«LjÿÓMiÿéOgÿ÷PeÿþQdÿöSbÿêT`ÿßU_ÿËV^ÿ°X[ÿ‘ZYÿu\Wÿb_UÿUaRÿPdNÿQfMÿWiJÿbkGÿqnDÿˆpAÿ¢r?ÿ¾u<ÿÔw:ÿèx9ÿöy8ÿø{6ÿó|5ÿç|5ÿÉ|5ÿ—|5ÿ^}4ÿ0}4ÿ}5ÿ‰ÿüÿÿüÿŒ&Esÿ Dsÿ$EsÿDFpÿsHoÿ¦ImÿÒKkÿíLjÿ÷NhÿöOfÿõPeÿêQdÿÔRcÿ¹T`ÿšU_ÿxV^ÿ\Y[ÿC[Xÿ4^Vÿ(aRÿ$dOÿ$gLÿ)jIÿ1kGÿ>nDÿQpAÿlt>ÿ‹u<ÿ®w:ÿÏz7ÿæ{6ÿò|5ÿø}3ÿö}3ÿà}3ÿ²}3ÿy}3ÿC~3ÿ3ÿ‰ÿüÿÿüÿ‹@xÿAvÿCtÿ8DsÿdFqÿ˜GpÿÇInÿçJlÿøKkÿþLjÿõNhÿåNgÿÍOfÿªQdÿ†SbÿdTaÿEV_ÿ1X\ÿZ\ÿ]Wÿ bTÿ dPÿ hLÿ iJÿlFÿoCÿ%q@ÿ=t=ÿ[v:ÿ€y8ÿ«{6ÿÏ}3ÿê~2ÿ÷1ÿé1ÿÆ1ÿ‘€0ÿW€1ÿ*0ÿ‚0ÿˆÿüÿÿüÿŠ>{ÿ?yÿ@wÿ/BuÿUCtÿˆDsÿ¼FqÿáGoÿñJmÿ÷Jlÿ÷KkÿéKkÿÌMiÿ§Nhÿ|OfÿUQdÿ8Tbÿ!V`ÿW_ÿ X^ÿƒnFÿnEÿqBÿ t>ÿv;ÿ5x9ÿX{6ÿ…|4ÿµ~2ÿÚ1ÿî€0ÿô/ÿî/ÿÖ/ÿ§‚/ÿl‚.ÿ<‚.ÿ„-ÿˆÿüÿÿüÿ‰9‚ÿ<}ÿ={ÿ(>xÿK@wÿ|Bvÿ®CtÿØEqÿòFpÿûGpÿöInÿéImÿÐJlÿ¦JlÿyLjÿQOhÿ.PgÿRdÿ UbÿUbÿ†t@ÿu>ÿ x9ÿz7ÿ9|5ÿb~2ÿ™1ÿÉ/ÿé‚.ÿ÷ƒ-ÿ÷ƒ,ÿäƒ,ÿ½„,ÿ‡ƒ,ÿP„+ÿ'†,ÿ ˆÿüÿÿüÿˆ9‚ÿ;ÿ;~ÿ={ÿ@=zÿm?xÿ¡@vÿÎBuÿéDsÿöErÿûEqÿòFpÿ×Gpÿ¯Hoÿ~ImÿPJlÿ-LkÿPgÿUbÿ‰w=ÿ}5ÿ }4ÿ#~2ÿG€1ÿ~/ÿ¶‚-ÿáƒ,ÿö„+ÿ÷…+ÿë…+ÿφ*ÿ¡†*ÿh‡)ÿ8‡)ÿŠ'ÿ‡ÿüÿÿüÿˆ9‚ÿ9€ÿ:ÿ5;}ÿa<{ÿ”=yÿÄ?wÿè@vÿ÷Buÿ÷CsÿòCsÿáDrÿ½DrÿŠEqÿXGoÿ1HoÿJoÿŒ€1ÿ2ÿ€0ÿ6/ÿbƒ-ÿœƒ,ÿÎ…+ÿê†*ÿò‡(ÿñ‡(ÿá‡)ÿ¼ˆ(ÿ„ˆ(ÿO‰'ÿ'Š'ÿ$ÿ†ÿüÿÿüÿ‡7ƒÿ7ƒÿ8ÿ*9€ÿR:~ÿ…;}ÿ¸=zÿÜ>xÿó?wÿþ@vÿøAvÿçBvÿÈBtÿ™CtÿdDsÿ7ErÿGqÿ‚0ÿ0ÿ ‚/ÿ#ƒ.ÿH„,ÿ…+ÿ¶‡)ÿ݈(ÿóˆ'ÿû‰&ÿñ‰&ÿÓ‰&ÿ¤Š%ÿkŠ%ÿ;‹&ÿ$ÿ†ÿüÿÿüÿ†3ˆÿ6…ÿ 6„ÿ7‚ÿA8ÿr9€ÿ¨:}ÿÕ;|ÿì=zÿô>yÿö?xÿî?wÿÓ@wÿ§@vÿtBuÿFBuÿ#Bvÿ ‚0ÿ„-ÿ„,ÿ4…+ÿd‡)ÿ‡'ÿЉ&ÿðŠ%ÿûŠ%ÿõ‹$ÿã‹$ÿ¿Œ$ÿ‰Œ#ÿRŒ#ÿ)Ž"ÿ$ÿ…ÿüÿÿüÿ†3ˆÿ5†ÿ5…ÿ15ƒÿ_6‚ÿ“8ÿÅ9~ÿé:}ÿø;|ÿö<{ÿë=zÿ×=zÿ°?yÿ~?yÿN@xÿ'AxÿBvÿ‚0ÿ…,ÿ…+ÿ$‡)ÿK‡(ÿ‚‰&ÿ»Š%ÿâ‹$ÿò#ÿö"ÿð"ÿÖ"ÿ¦Ž"ÿkŽ"ÿyÿAwÿ‘†+ÿ‡)ÿˆ(ÿ6‰&ÿfŠ%ÿ Œ$ÿÐ"ÿìŽ!ÿùŽ ÿùŽ ÿå ÿ½ ÿ†ÿL ÿ$‘ ÿ …ÿüÿÿüÿ…0‹ÿ0Šÿ0‰ÿ72‡ÿf3‡ÿ4„ÿÌ5ƒÿç7‚ÿð8€ÿð8€ÿä9~ÿÄ9ÿ•:~ÿc;}ÿ:={ÿ<|ÿ >{ÿ’‰(ÿ ‰&ÿ%Š%ÿM‹$ÿƒŒ"ÿºŽ ÿá ÿôÿ÷ÿëÿÏÿ‘ÿ`‘ÿ0‘ÿ“ÿ„ÿüÿÿüÿ…/Œÿ /‹ÿ#/‰ÿN0‰ÿ…2‡ÿº3†ÿâ4„ÿö5„ÿ÷6ƒÿé6ƒÿÐ7‚ÿ§7ÿp8€ÿB9€ÿ!;~ÿ ;~ÿ“Š&ÿŠ%ÿŒ$ÿ7"ÿeŽ!ÿŸÿΑÿé’ÿó“ÿò“ÿà’ÿ²’ÿv’ÿ@’ÿ“ÿ„ÿüÿÿüÿ„-Žÿ,ÿ.Œÿ5.‹ÿf/‰ÿ¢0‰ÿÑ2ˆÿí3†ÿø4†ÿö4„ÿä4„ÿ¼5„ÿ‰5ƒÿU7‚ÿ,7‚ÿ9‚ÿ”$ÿŒ#ÿ "ÿ%Ž!ÿPÿ†‘ÿ¼’ÿâ”ÿö”ÿü”ÿë”ÿ”ÿ†”ÿI”ÿ!”ÿ „ÿüÿÿüÿ„*ÿ +ÿ",ÿI-ÿ€.Šÿº/‰ÿä0‰ÿõ1ˆÿö2‡ÿí2‡ÿÓ2‡ÿ¥3‡ÿj3†ÿ<4…ÿ6…ÿ9‚ÿ•!ÿ‘ÿÿ>’ÿq“ÿ«”ÿÙ•ÿò•ÿø•ÿë•ÿÉ•ÿ‘•ÿS•ÿ'•ÿ ™ÿƒÿüÿÿüÿ„*‘ÿ*ÿ-*ÿ_,ÿ™,ÿÎ.‹ÿï/Šÿü/‰ÿ÷0‰ÿå0‰ÿÀ1‰ÿ‰1ˆÿP2‡ÿ(2‡ÿ5†ÿ–!ÿ“ÿ“ÿ2”ÿc•ÿ–ÿÑ—ÿë˜ÿó˜ÿì˜ÿЗÿ›—ÿ]—ÿ,–ÿ™ÿƒÿüÿÿüÿƒ(”ÿ'“ÿ(’ÿ=)ÿs*ÿ°+ŽÿÚ-Œÿñ-Œÿø.‹ÿò.ŠÿØ.Šÿ§/Šÿn/Šÿ<0‰ÿ1Šÿ˜ –ÿ •ÿ(—ÿY—ÿ•˜ÿÌ™ÿî™ÿú™ÿô™ÿؘÿ¤˜ÿe˜ÿ3™ÿ™ÿƒÿüÿÿüÿƒ%–ÿ'”ÿ&'“ÿO'’ÿ‰)ÿÄ*ÿé*ÿö,Žÿô,ÿå,ÿÃ,ÿ-ÿT-Œÿ+/‹ÿ0‹ÿ˜ ™ÿ ˜ÿ%˜ÿQ™ÿšÿÈšÿî›ÿù›ÿõ›ÿÞšÿ­šÿmšÿ8›ÿ›ÿƒÿüÿÿüÿƒ $—ÿ%–ÿ/%•ÿc'“ÿ '’ÿÕ(‘ÿô)ÿý)ÿõ*ÿÜ*ÿ®+ÿs+Žÿ=,Žÿ/‹ÿ™ ›ÿ šÿ!šÿM›ÿ‡›ÿÜÿçœÿõÿóÿßœÿ´œÿwœÿ?œÿœÿƒÿüÿÿüÿ‚"›ÿ"™ÿ"™ÿ?$–ÿx%•ÿ´&”ÿß(’ÿô(‘ÿù(‘ÿï(‘ÿÎ(‘ÿ—(‘ÿ](‘ÿ.*‘ÿ-Žÿ™›ÿ›ÿ›ÿDœÿ~ÿ½žÿæžÿ÷žÿåžÿ¹žÿ~žÿDžÿžÿƒÿüÿÿüÿ‚ ÿ!›ÿ'!šÿP"˜ÿŒ#—ÿÆ$–ÿë%•ÿ÷&”ÿó&”ÿã'“ÿ¼&”ÿ'”ÿG'“ÿ"4…ÿ œÿ&—ÿ’ÿ$ÿ†,ÿ0ÿ4ÿy:ÿv=ÿ t?ÿ qCÿlHÿ iLÿcSÿ]Yÿ[[ÿUbÿPgÿNjÿInÿBwÿ@zÿ=|ÿ6…ÿ0‹ÿ -ÿ Tbÿ oBÿ#‰%ÿE•ÿz–ÿ¶—ÿâ›ÿö™ÿ÷—ÿé—ÿ×ÿ‰“ÿN’ÿ# ÿƒÿüÿÿüÿ‚7,Žÿ'’ÿ2$–ÿe%”ÿ£$“ÿ×$”ÿô&’ÿý(ÿõ(ÿÛ)ÿ«2…ÿs?wÿ>Peÿ œÿŸÿ™ÿ–ÿ’ÿ‹%ÿ‡)ÿƒ.ÿ|5ÿy9ÿw<ÿs@ÿ pCÿkHÿgLÿcQÿ^VÿZ[ÿUaÿRdÿMjÿHoÿDtÿ?yÿ9€ÿ5„ÿ1ˆÿ+ÿ"3…ÿ%Odÿ5hIÿQy6ÿ~„)ÿ²‰#ÿÛŠ"ÿï‰"ÿóŠ#ÿëˆ%ÿÎ…*ÿœ€/ÿb{6ÿ3iKÿ6ƒÿ‚ÿüÿ<ÿüÿˆ*ÿMjÿ ?xÿ%6€ÿI/ˆÿƒ.Šÿ».‰ÿá-‰ÿõ0‡ÿù0…ÿñ6€ÿÒÿòr>ÿùq@ÿôp@ÿßkFÿµfMÿ~_TÿGTaÿ# ›ÿ Àÿÿüÿ<ÿüÿˆ*ÿˆ*ÿ aTÿPeÿ=HnÿkAuÿ¡vÿø@tÿöFnÿëOeÿÐ]Uÿ§t=ÿ„‹$ÿlžÿ_¢ ÿ_Ÿÿcœÿf˜ÿg“ÿjŽ!ÿi‰&ÿm„,ÿt2ÿz|5ÿ€x9ÿ…t=ÿ†qBÿ…mEÿhLÿ~dPÿ|_Uÿ|ZZÿ|W^ÿzRcÿzNhÿ{Inÿ{Erÿ}@wÿ€<|ÿ€8ÿ€2†ÿ„-Œÿˆ*ÿŠ*ÿ‘.‰ÿž8ÿ±EqÿËMgÿæPcÿ÷OeÿýNfÿúNgÿíKjÿÑIlÿ Dsÿd:ÿ3«ÿÀÿÿüÿ?ÿüÿˆ*ÿˆ*ÿhKÿ2dPÿ]\Xÿ”W^ÿÃT`ÿæT_ÿùW\ÿþZXÿùcNÿîoAÿ×1ÿ½‘ÿ¨ÿŸ¥ÿš¤ ÿž  ÿ£ÿ§™ÿ§”ÿ§ ÿ¨‹%ÿ¬†*ÿ°/ÿ¶~3ÿ½z8ÿÂu<ÿÄr@ÿÂnDÿ¼iIÿºdNÿº`Tÿ¹\Xÿ¸W]ÿ¹Tbÿ·Ogÿ·Jlÿ¹Fqÿ¼Buÿ¼=zÿ½9ÿ½4…ÿ¿/‰ÿÃ+ŽÿÆ)‘ÿÈ'’ÿÏ(ÿØ,Œÿâ0ˆÿð/‰ÿù.‹ÿü+ÿü*ÿ÷+Žÿè.ŠÿÅ0‰ÿ‰-ŒÿL#˜ÿ!Àÿ Àÿÿüÿ?ÿüÿˆ*ÿ~4ÿ#pBÿPoDÿˆmEÿ½mFÿámFÿóoCÿûr?ÿýw9ÿû0ÿò‰%ÿæ–ÿÛžÿÑ£ ÿÑ¥ÿÓ¥ÿÔ¢ ÿØžÿÜšÿÙ–ÿØ‘ÿÜ#ÿÛ‡(ÿ݃-ÿã2ÿæ{6ÿæw:ÿìs>ÿêoCÿâkHÿâfMÿæbRÿä^VÿâY[ÿåU`ÿãQeÿàKjÿäHoÿæDsÿä?xÿæ;}ÿæ6ƒÿä1‡ÿê-Œÿî)ÿê&”ÿí"—ÿó"˜ÿó"˜ÿøÿü¡ÿþ¢ÿþ§ÿý¨ÿ÷žÿß%”ÿ§(’ÿb!šÿ-ÀÿÀÿÿüÿ?ÿüÿˆ*ÿz8ÿ3u=ÿmw<ÿ¯z8ÿà}5ÿõ}4ÿû1ÿý…+ÿþˆ'ÿüŽ ÿù—ÿõÿò¡ ÿì¤ÿð¦ÿô¦ÿð¤ ÿò  ÿ÷ÿó—ÿñ’ÿõŽ!ÿò‰&ÿð„+ÿö/ÿ÷}4ÿôy8ÿùt=ÿùpBÿñkGÿôfLÿúcQÿô_UÿóZZÿùW_ÿõRdÿñMiÿöImÿøFrÿôAwÿ÷<{ÿ÷7ÿñ2†ÿø.‹ÿü*ÿö&”ÿø!™ÿþ›ÿùœÿú¥ÿþ¨ÿÿ©ÿÿ °ÿÿ ´ÿý¦ÿì!˜ÿ¸'“ÿn"šÿ2ÀÿÀÿÿüÿ?ÿüÿˆ*ÿz8ÿ=x;ÿz8ÿÆ0ÿò…,ÿý„-ÿþ†*ÿÿ#ÿÿ ÿý’ÿûšÿüŸÿû¢ ÿô¥ÿø¦ÿþ§ÿ÷¤ ÿø  ÿþÿ÷˜ÿö’ÿü ÿ÷Š%ÿñ…+ÿ÷‚/ÿ÷~3ÿóy8ÿõt=ÿópCÿíkHÿófMÿúcQÿô_UÿóZZÿùW_ÿõRdÿñMiÿöImÿøFrÿôAwÿ÷<{ÿ÷8ÿð3†ÿò.‹ÿõ*ÿñ&”ÿó!˜ÿø ›ÿö›ÿø¢ÿý¥ÿþ¦ÿþ¬ÿþ­ÿü ÿê)ÿ¸1ˆÿp2‡ÿ6¡ÿÀÿÿüÿ?ÿüÿƒ/ÿu=ÿ@t>ÿƒx:ÿÊ€1ÿó…,ÿþƒ.ÿþ†+ÿÿŒ#ÿÿ!ÿý‘ÿú™ÿøžÿö¢ ÿî¥ÿñ¦ÿó¦ÿî¤ ÿí  ÿñœÿì—ÿê’ÿíŽ!ÿê‰&ÿä„,ÿå0ÿä}4ÿßx9ÿÞs>ÿÚnDÿÙjIÿÞeNÿäbRÿã^VÿâY[ÿåU`ÿãQeÿàKjÿäHoÿåDsÿã?xÿå;}ÿâ7‚ÿÜ1‡ÿÛ-ŒÿÜ(‘ÿÙ%”ÿÛ"—ÿà$–ÿã&“ÿì%”ÿö$–ÿü#–ÿý!˜ÿý&”ÿ÷1ˆÿà={ÿ­DrÿkHoÿ4/‹ÿÀÿÿüÿ?ÿüÿ}5ÿlHÿ;kHÿxoDÿ¼v<ÿè{7ÿù|6ÿý2ÿþ„,ÿý‡)ÿú‹$ÿñ“ÿèœÿß  ÿÖ¥ÿÒ¥ÿÒ¥ÿ΢ ÿÍžÿÍ›ÿÊ–ÿÇ‘ÿÇ#ÿÈ(ÿ¾ƒ,ÿ¼1ÿ¸{6ÿ³w;ÿ®q@ÿªmFÿ«hKÿ°cPÿ¶`Tÿ·[Yÿ·W]ÿ¸Tbÿ·Ogÿ·Jlÿ¸FqÿºBtÿº=zÿ¹:~ÿ´5„ÿ°0ˆÿ«+Žÿ©'“ÿ§$•ÿ©&’ÿ°,Œÿ»6€ÿÑ=yÿç@vÿöBtÿýDqÿüJlÿòRbÿÖ\Xÿ¡bQÿa^Wÿ-Nhÿ Àÿÿüÿ?ÿüÿy:ÿ`Uÿ0[Yÿe^Wÿ£aSÿÖdOÿñgLÿüjHÿýnCÿúr>ÿðz6ÿ݈(ÿÅ•ÿ±žÿ£¤ÿ›¥ÿ˜¤ ÿ–¡ ÿ”žÿ’™ÿ”ÿŽ ÿ‹Œ$ÿ‡‡)ÿƒ‚/ÿ}~2ÿzz7ÿuu<ÿopBÿlkHÿofMÿscRÿv^VÿyZZÿ{W^ÿzRcÿzNhÿ{Inÿ{Erÿ|@vÿ~={ÿz9€ÿv4…ÿs.Šÿl*ÿi&”ÿi$•ÿj0‰ÿu?wÿŠOcÿª^UÿÎdMÿìfKÿøkGÿùpBÿîu;ÿÐ{5ÿ™0ÿ\~3ÿ,‚0ÿ §ÿÿüÿ?ÿüÿgNÿ Ljÿ%DsÿRDrÿŽFpÿÆFoÿêJlÿùMhÿüOdÿöT^ÿà`Rÿ¿q@ÿ—†)ÿ{šÿh¤ÿ]¥ÿY£ ÿX  ÿTœÿT˜ÿR“ÿP ÿN‹$ÿL†)ÿH‚/ÿD~3ÿAz7ÿ>t=ÿ;pCÿ9kHÿ9eNÿÿ„{4ÿµ‚,ÿÝ…)ÿñ‡'ÿõ‰$ÿíÿÑ‘ÿœ’ÿ_˜ÿ-œÿ§ÿÿüÿ?ÿüÿ6„ÿ 1‡ÿ,ÿG)ÿ*Žÿ»,ÿâ.‰ÿô0‡ÿõ3„ÿë5ÿÐ>wÿ¡RbÿrmDÿM‹%ÿ5¤ÿ-¥ÿ+¤ ÿ'  ÿ'œÿ&˜ÿ%“ÿ"Ž!ÿ"‹$ÿ!†+ÿ‚.ÿ3ÿy8ÿt>ÿoDÿiJÿeOÿ`Tÿ]WÿY\ÿUaÿRdÿLkÿHpÿDtÿ@xÿ=|ÿ8ÿ4…ÿ.‹ÿ+ÿ%–ÿ&”ÿ[Yÿx6ÿ:Š$ÿh•ÿ –ÿÒ—ÿð˜ÿú™ÿô›ÿ×ÿ¢¢ ÿc¡ ÿ1¥ÿ§ÿÿüÿ?ÿüÿ ²ÿ£ÿ¥ÿB¢ÿ{¢ÿ¸¡ÿãŸÿöŸÿ÷žÿè›ÿÅ#•ÿ+ŒÿU@uÿ-{6ÿ§ÿ¨ÿ ¤ ÿ¢ ÿ œÿ–ÿ “ÿ $ÿ‰'ÿ ‡*ÿ 1ÿ|6ÿz9ÿx;ÿqCÿgMÿePÿcSÿ]Xÿ\ZÿUbÿQfÿNjÿIoÿCvÿ@zÿ=}ÿ9‚ÿ6…ÿ1‰ÿ*‘ÿ%–ÿ ›ÿ’ÿ›ÿ*Ÿ ÿW¡ ÿ’  ÿÉŸ ÿîŸ ÿù  ÿõ  ÿÜ¢ ÿª£ ÿj£ ÿ6¤ ÿ¤ ÿÿüÿÿüÿ ´ÿ ´ÿ ³ÿ@®ÿy¯ÿ· ®ÿå«ÿùªÿù¬ÿæ¬ÿ¼©ÿ«ÿF§ÿ>{ÿ¤ ÿŸ¤ ÿ ¤ ÿ$¤ ÿP£ ÿŠ¢ ÿÅ¡ ÿè¡ ÿô¡ ÿó¡ ÿߢ ÿ²¢ ÿr¢ ÿ;¢ ÿ£ ÿÿüÿÿüÿ¶ÿµÿµÿ@µÿy ´ÿ· ³ÿá ²ÿó ³ÿâ ³ÿ¹ ´ÿ| ´ÿCµÿ¶ÿ £ ÿ¢ ÿ¡ ÿH¡ ÿ…  ÿÀŸÿçŸÿøŸÿ÷Ÿÿã  ÿµ  ÿx  ÿ?¡ ÿ¢ ÿÿüÿÿüÿ·ÿ·ÿ¶ÿA¶ÿ{µÿ·µÿãµÿõµÿãµÿ¸¶ÿ|¶ÿA·ÿ·ÿ  ÿ  ÿ ÿE ÿžÿ»ÿåÿöÿäžÿ¸Ÿÿx ÿ@Ÿÿ ÿÿüÿÿüÿºÿ¹ÿ¹ÿB¹ÿy·ÿ¶¶ÿä¶ÿú¶ÿä·ÿ·¹ÿy¹ÿB¹ÿºÿ žÿžÿžÿBÿ|ÿ¸œÿàœÿñœÿàÿ·ÿzÿBžÿžÿÿüÿÿüÿ¼ÿ»ÿºÿ?¹ÿv¹ÿ²¸ÿÞ¸ÿò¸ÿÞ¹ÿ²¹ÿvºÿ?»ÿ¼ÿ ÿœÿœÿ@œÿx›ÿ·šÿãšÿõšÿã›ÿ¹›ÿ|›ÿC›ÿÿÿüÿÿüÿ½ÿ½ÿ¼ÿ;»ÿp»ÿ¬»ÿغÿì»ÿØ»ÿ¬»ÿp¼ÿ;½ÿ½ÿ œÿ›ÿ›ÿ?šÿvšÿµ™ÿä™ÿø™ÿù™ÿæ™ÿ»™ÿ~šÿFšÿœÿÿüÿÿüÿÀÿ¾ÿ¾ÿ6½ÿi¼ÿ¥¼ÿؼÿñ¼ÿؼÿ¥½ÿi¾ÿ6¾ÿÀÿ šÿ™ÿ™ÿ;™ÿq™ÿ¯˜ÿÝ—ÿò—ÿó—ÿã˜ÿ¼˜ÿ€™ÿF™ÿ˜ÿ ÿüÿÿüÿÀÿ¿ÿ¾ÿ/¾ÿ]¾ÿ—¾ÿ;ÿí¾ÿ;ÿ—¾ÿ]¾ÿ/¿ÿÀÿ ™ÿ˜ÿ˜ÿ5˜ÿh—ÿ¦—ÿ×–ÿð–ÿõ–ÿæ—ÿ¼—ÿ—ÿD˜ÿ—ÿ ÿüÿÿüÿÀÿÀÿ¿ÿ$¿ÿH¿ÿz¿ÿ©¿ÿÈ¿ÿ©¿ÿz¿ÿH¿ÿ$ÀÿÀÿ –ÿ—ÿ—ÿ-—ÿ[—ÿ™–ÿЖÿó–ÿý–ÿè–ÿ·—ÿx—ÿ@—ÿ–ÿÿüÿÿüÿÀÿÀÿ ÀÿÀÿ.¿ÿR¿ÿv¿ÿŒ¿ÿv¿ÿRÀÿ.ÀÿÀÿ Àÿ –ÿ–ÿ—ÿ$—ÿJ–ÿ€–ÿ·–ÿß–ÿé–ÿÒ–ÿŸ–ÿf–ÿ5–ÿ–ÿÿüÿÿüÿÀÿÀÿÀÿÀÿ.ÀÿBÀÿPÀÿBÀÿ.ÀÿÀÿÀÿ¡–ÿ–ÿ –ÿ–ÿ4–ÿ\–ÿ‰–ÿª–ÿ³–ÿŸ–ÿw–ÿI–ÿ%–ÿ–ÿÿüÿÿüÿÀÿÀÿÀÿÀÿÀÿ!Àÿ'Àÿ!ÀÿÀÿÀÿÀÿ¢ –ÿ–ÿ–ÿ–ÿ6–ÿT–ÿj–ÿp–ÿc–ÿH–ÿ+–ÿ–ÿ ÿüÿÿüÿÀÿÀÿÀÿ ÀÿÀÿÀÿÀÿ ÀÿÀÿ£ –ÿ–ÿ–ÿ–ÿ–ÿ*–ÿ5–ÿ8–ÿ1–ÿ$–ÿ–ÿ –ÿÿüÿÿüÿƒÀÿÀÿÀÿÀÿÀÿ¦ –ÿ–ÿ–ÿ –ÿ–ÿ–ÿ–ÿ–ÿ–ÿ –ÿ‚ÿüÿ¿ÿüÿTRUEVISION-XFILE.allegro4.4-4.4.2/addons/allegrogl/examp/a8.bmp000066400000000000000000000077221173507505700207600ustar00rootroot00000000000000BMÒ6(@@œ   ÿÿÿ     & $  , $1# .$$<7 *!>+84(+H > 1=2* M#I5X$2B :>cCLE*X!R<g $C7d-?; l!R2eB qIx)K'P1DP‚ ^(c" `M† .Q0p-\'#jZ‘=|H‚K‰D„ 6Z0cdŸ?UW–/$z7e; …,+y$/v4p/)€a§i ª)/}=mM˜X :ru¹!6{T¤]©=vp º0.‹C&˜:>+–Ni:,˜?€‰Ò Gwm¾K&¥05”i¿‡Ú|ËF…_ ¸W!¹R&²H-¨wÏ%AJ…S{ Qè:7¡WxtÒjÌ…ÝA7­›ñšü¡ú4A£ K——ÿR‘ƒãS1¾M4»— õ5B¬/F¨E:¸Žî_-É<@²'L£xã哸Y1ËŠñg+ØK;Ãt'ß?F¼8J¸þa2Úˆö€"ð XªT:Ò3Mº\8×FEÆm‘… ú|'òo/è)X´0T»KEÏbªy.õ„'ÿCMÑe;èl7îZBàv3ø>SÑ$c¾:XÌr7üWHæLNßl<÷mº{¥fBòkÁj@ý u·/cϪEXÞTOëcGöIUå&jË6aØ`JøvÆ·YR÷+mØ@eæRYøM^ñCcí%t× wÓWYÿ{ÚJcø%vá|¾ÖâÞÞΟhJ4.*#())$ &,//1-'-1CUx ¯®¦ƒR*ªÿÿ!H³ÑÍÇÇž„Z[PIIRDLLMJF SSYV\\Wbbii`e]e|’³ÍÍŸ–h:ªÿÿ S¹»»µ¶®¦Ž…tnuppsswwyyqz””——¡¢©²²±±§§´ÆÕáçêäÙËBÿÿ$U–µ¶£4›‘‡‡‰‡‡‘€•𙝠žž¤«ººÀÌÁÎËÙÖÖàáÕÕÚÛÝååðõôøøõߘX% ÿÿ$U–µ¶£Œˆ‡‰ˆ‘›£¥¦¯¯µ»¹¸ÅÑÑÔÔרÞâàçèèíïðôø ùùüüýîÆe- ÿÿ Fyžµ'¶®¥›‘‘‡‰‡‡ˆ‘•¥¦¯µµ»¿¸ÅÑÑÔÔרÞâàçèëïñðõø ùüüýþöÃ]'ÿÿ3U¸ÅÇ¿¿µ™…tn.tt…{Žš  °°¹¹¸ººÀÌÁÎËÙÖÖàáããïæðôôøøúùüùî´TÿÿBg¡Î×ÜÔÀ«wZP[[Zddwwx––œŸ”——¡¢©²²±½½ÆÛÛæïïññðæÆ}=ÿÿ ,X˜ÉáççÙ¼U8.488JUSSYV\\Wbbimmv}±¾ËÞ ¼“O% ÿ ÿ>v½ßïÕ˜W0$)$0&&,//11>5==EGXrŸ¸ ¸S,ÿÿ ']´ÝôõðÝ´e- !3Jw™¦®¦„^: ÿÿ NÒðôôåÆ}=ªªªªªªªªªªªª (%ª(LpŽ££pD# ÿÿ=v½ãííãÕ§`56_ƒŽŽZ; ÿÿ -T§ÏãèèãÉ‹O-ª(Ksš¥¥ŽƒR*ÿÿ5e§ÕèëèÕ±|G%ªª6_ƒš¥¥šsL(ÿÿª %G‹½èáɱi>ªª(Mw™¥ƒd8ÿÿ5`§ÉáèááИX1ª:c„¦®®šsL( ÿÿª%>m±Ðáççà²|O%ª)Jw ¦®¦ c8ÿÿ %G‹Éàççàв|9%ª $:^„¯¯¦™wM( ªÿÿ -X˜ÐààääЩb9ª ª)Jw ¯„c:ÿÿ >i²Ðä Ö¾“W9ªªª$:^–¯™wM2 ÿÿ ª%>|²ÐÙââÙ¾“W9!ª ªª 2Jxžµ„c:$ ÿÿ %O|¾ÖââÞ˼’\A,!  $2Uyž°µ„^2ª ÿÿ 1b“¾ÙÞØË¡r\A,! 3FUq–°»»µ°xJ)ª ÿÿ ª1b“¼ÙÞÞØÎη—rVC3033BFUq¤¹»°–^: ª ÿÿª%9b“¼Ø×ÎÁ¬—lglljzœ¹ ¿¿°žqF)ª ÿÿ ª%9WмÎÎ×ÌÌÁ³Ÿ¨º¸¸Â¹¹°žyJ)ª ÿÿ ª9WŠ¢·Î×Ô ÌÌÀÀºÍÅÅÇ ¹¤–qU2 ª ÿÿ /A\’¡ÁÌÔÑÀÑÍÍÅÇǸ¸¤yhF2 ª ÿÿª!9Wr—¬ÁÌÌÔÑÀÍ ÅŸ«zUF$ ª ÿÿªª,C\†¬³ÀÀº ¨¨zUF3 ªªÿÿ ª!,CVg† lljjSB3  ªÿÿª!,0CH BB330  ªªÿÿªª ! ªÿÿªªªªÿÿ ªÿÿ>ÿÿ>ÿÿ>ÿ@ÿallegro4.4-4.4.2/addons/allegrogl/examp/demofont.dat000066400000000000000000000311271173507505700222510ustar00rootroot00000000000000slh.ALL.propNAMEFONTFONT/"ÿÿ9pêíðíñ íðÿ Üÿ"4FXj|Ž ²ÄÖè0ú 0ýÿëóý‡íðüì§¡ÿþþƯþþµjj£jjøjÿæ©þÔ·ŸþÂ_þ³íðØÝ£êô‹Ø·’þþwŸä£›Ú«KâãûEáíð£ÿŸ“øÎ­þ«ÿ‹þ³þî{³•wÔð_À›å*/@(@õa0a‚Øñ0 ‚‚@uürŸ)@€Pô'3§þäìòÄ1Y«ô}åù¯(2Þü¡Öíñ—þkCÖƒ£þº2Sò–cÎþèíñµþþ"@¸bA`bAf¦]±þ !0þ÷"ìî‘RŸþîÒàþ±níð­þâÒðò„¢âüvHŸî§YÜýúšü·ÊΗµ‰ìþêâürÿ¡ê؛߽þ±îÞ ‘Ö‡ÆtUd¤Ÿ¶ŸÈŸÚŸìŸþŸ†?"¯4¯F¯4n&¡Ì2T<’QíñÔ'3Î}î¸`öîî­ïaè!¯ƒ£¥‚;‚ƒð«R`QŸÕ¯ç¯ù¯ ¿>/¿PA¿S¿e¿ëó±¥€™‰aÄî!ì2P"Pe(1„§¥åù%¿Á¿Ó¿íñÊwÞÞ›¡ÄÂÎA€ø¿ Ï­¿.Ï@ÏRÏ ÷‘úgQþȇðaà/m˜Ïãû­PBÛ¥þe’ÊülBîâºíñ“wS·þ›5RöÒƒúx`1‘>@bB+ìêíñ‘–cµ‘7PúUaƒøÜc„R$@63RêòìòöʧÏèö! ÏbßtßÍ»ÝÂôßòþþèÀuÂÚþßüÔøþè20þöwP±þ‘Òþü‰›‰ð1ƒø‘±À€ðŒPþÀ’þh`V‚«`Ôj(1â;@©îÓôþiàñ ºaôóû»þº¡½þú“|```QÒþøúþ~¤¯æþ• 7ïIï[ï€Ï¨kï‘ï¨ÏÂBÀá1cŸü½âÆ`¾á•νâ =€Ó뎑¡èâÞîïõaèâ¯ú#‚h¨!ÿ¯EÿðWÿiÿVdô»öþõÐ21‹ÞÐþþàðþþÞ¥*áv«`Æ×ЫøÙÑÎv³Ú!üodö`º¤¸k†ÑÁøþúbB…£êþùr° “í±î?úüâ‡)àè!~Ð »ÞÞÔÆ¹ßr€'9:ÿ]oX¯ñò»§ò«QøÐÔ1þÆ ‡ö໡ÒþyȱfxRêþ]S)¡£ÐW…ç!ØÒ àúè âðƒØÌ¿ÂAîN„Q‚NcUb¡¸`¶0§ÞðþàU`›vÓ0öÀ22›¯›2?€;MNßqƒ•ßò§ ž–&à ¢¢—c‡ê0¾ïÊþÜîð×üþS—òŸ£þ Ò§Ñ`}‡ùÒìþ⟼Ðs»‹oPè$ê‡äð<"@€àçq+„ž•íÐk¥¥ìƒ¬Rð‚.ÒƒARb/t/H˜/ت/¼/.Ò‰ÉÁ‘àÖ£Ðþì"@KAþþ½™nQøÎĵÝÁÜðç0.ÒàšÔÊþþúÑÖ¢%@™ æë Ÿ‡¡¹æ­`*ÈðšÓ… ú0ë S@ÞÐà"©¸`¤¨àû`Ø1ƒï`ÔYC‰­Ä¯y?‹?Œ/¯?Á?•…qʱ¤@kR…îçã(ŽaÝó¶Ñ½¥eüõ³í±—þðÂðÌä`ðò}‘ø€ö“¿þð þþ4Ð‘Þ ààà«ìž¢·öÙЇšð«ñ€ô³œp…yØ"ò§ÒÞÀÉÂwO‰O›Oœ?¿OÑOÅ.ôBÌö‚™¢Þƒìà™£›ÿ‰ŸŸŸ‘ÞþôŽñò‹ú–dáu¤î ?ƒ·‚9‚ÀÔßòúÀõ¼Ð.±TÔþö*ôˆ±.ÒùÓrbñ‰_›_­_®OÑ_<ã_Ù¾«âîÒ BÏ€|¨û€‰úþà‹Y@ƒáщ•áøÐ‰ü‰ß€‡öþÖ¥üˆwa ™ ô^!E€îó°Èð™ ‰°2`ê—ÞÐ¥†2Pì‹ÓÀÓðâ0@ÜSæ=a2`»øàÈðÕî«Ü!ä—Ÿ(%§o¹oº_Ýoïo.ÒŸ¿·ËóJ@ää0‡Ò½üz`êà à›ÈD@úpùÄÝ€¥þþÑÚ àÂÀ6@Þìà⡱ Ò‰˜¤ç0…¿¿èèöþüü™½üƒæþærÓÂE¾ðÞS»þê^$…A³ÅÏØo\û߸¿Ð…݀¹€ç¹Àç3–s¡÷øþ«B`ʇðäð±ábt³Öó‹‘<`n`È·½ÔSCƒA`Ò𵉯üö‡­ÐÀȇ€»¥ÏoÒäöŸsE‘ÎÒ—Ö0r*›·…2’ì³*ùæé­ñòíÐÆh3ƒ·ògþüÎX‘þÖu£d’4Ôƒ¯ìð4·À¹˜ŸªŸ¼Ÿ½àŸòŸ¯¯4(¯>&¿D¢½‰h`™£ïŸ¥¯X¢«™‹PPüEúÐÀÎv¢Ê^/ޝ ¯²¯Ä¯€Ö¯×Ÿú¯ ¿¿§—†Ÿ³ì¯—„·Ðð·*™Ü4’*—ÎüX¶‘Èú4T©êÄâ|g’Òd–•Ìi“Ÿ\•  o¶¿È¿Ú¿ì¿ î¯Ï\¯äh3‰Æø–b¥å"wÞµöÁÀGØÊ•áÂÂðø3" âÐÒ‡òFcX@ðÃŒ€„ÏÂîÀü;2@`D†“­ÊèþS$öG%¯!ÖËÏÝÏC Ïßøß,ß Š‘±¿»¡þSÔþðÞæü앱“òæûÑÚ ¶€ÿîà…“ÔÂø¿ÿ‰øÀÄøƒ÷îüÜæðÖÚöíÈ`»ÀJpÎÞ›þ£ðèøƒÚþ‡ÿÚÒ­þ“þÐ÷‡úîËе¯þï«þ³ÌÉнø‹ÿŸþ¥þðêøÿàµü±…øÒ©Æ‡Èþò·áÝÂÚ‡±ËðØÿþص¯»ÒøîþŒq±âúþôܵ* ïï/ïAïè¯eïwï…ÚÜÂ…Ãà5S"aúÃõ3aMRøï¡ðD 0?QÊŠps“î1ô_A¾n`»ÚþôbÊåÔ‰°‰ìñ SøþöäÚârÀöðRÀ(`ïÄ»þú3!ðþؽÖï3Äþêìϋʷ©Î¥¿AÿSÿ]øwÿ‰ÿ‡£ÄØêî#à¿}¡R1l òºÀ0©Ÿ£Ô4Q€šÁ*QrÎÎ1Ep¹$2F‚°ÔK0áÐl£ö\QÔÌ»á î £½%ð2AîrOÀ`Ý|`Î×ö…ª @ôå!üRÀÞl¡ú}Ô AµÞĵ®€Xj|bÿ ²%¿ÖkøÆysƒA0þò}¢„ 0l »•`A0‚qæGþü“% ‚pÛñ$&ð`ÀkCHpañ‡ÈÚð‹—ˆ%7\NŽÔöÄî…äÕâö" xQ“À‰î"²Vיૠ}£Ê[4ÎåáÕóÿ\#5ˆ½Èòàî“@µÐ³0Ú°ðîÂCÀþüG¯y°¾Et@†_ª¼-·Á£I‘¯™øÞ‡µðPáQXBìðñîbÀ­E~Ήôþü›ÓâÔÐ}ª0K°PM¢ S:Â0ól¢“i S v ÅñŸÔ—øþü•±ú§üþêðÝò¥àó`Òó-Â>!Êøt«…ÄŸ€¡Ÿ³Ÿ÷¿×ŸéŸ2 UÞƒ5B#©à¥)¯;¯¬Â¤ú¹BÐpEµñÈà²ôãüàv@Ò¹•á•P¢¯= ϟׯé¯=;àÚ‹ ÌÞÆæ21A©?Èàâðt@Ò„¢âx—ÀÚØâDDùò|@ Ðµ¯Ðþ#ò‡“@l°³u”ÃÐM½u“üïÑÊQ­ˆ ˜æÐ þêîp}£Ð¤‚ãèâ2 ðN–¿ÔÀ2s±“sÐPn@¶sàáQÈôÊÑ‹äêÅ?…—ÿ¿»Í=›ÔÚÒCdùÐà¡‹^Pˆ sº`»°`ü¥‡™ èpê OÈøöƒ ÊЃA@I‘®3›1Y T^P8ÌQ¢!ˆ Ÿ­F`°Oàîø.l°ü “Ê•p8°Ü}£•PõÆúà⑿ιÀ‘¯¥/·/¸Û/í/“ÿ¡¯¹¿ÎÊ‹Úô;±}¡»´4þú‰­¯Øþö¡“â!¿Q6*? !@5ÎI?[?2m:È5?8‰½nE«?à½?¾/á?ó?3Ï©§ƒH ,°[€Öo3wPÖÝÐDÝPwPÎŒ`zP5Bì;F„3DôÞa5Bb¢]G™D^FPÈÔP,°Ø`¹|à{äÝÐþ£ÀA `€øƒ‰TP} ék‡¹i°Ü”#™Òâ@»OÍOÎ?ñO_ô˜—åßþÊ‹½9’Ôþû蹋A‡úþÊ'£þþ\«ÒЕPÊ­ð‡C@à†Q“ÐÐþ#ü…l°xÐ`°¡pðöq@¹ÔšAúþaÒµ`£€°N"Âþ;°@¿Á~¦A} ,°xá•À¦°òÑQû#³xÐÊ_Ü_‚îžïOo$o6oô˜·Ïä™»OÁü"ôþ=·+@…­Äð°`{—…–Qæþüƒ=0-øt‘Ÿƒ— „P7öþ«q@þ§Ðú‚˳³} ·Êððâþ›¿È} È·aPAÂíâh°ØÐõrÎþÎÿöþÊþèæþʼE2† ŸþøüØâ»h°ò~P½SÖðU€ÊÀ`oBl`€“ÑÐ-ÔÀlsþñîø@—È9“*<N`ãO„–ð.ŸÊ¯›¹îq±Ð§÷±þê{PìþüÓ‰üù€s°Ö-±òƒØT°ñзü8Rƒö€”QYb`€Ýpxá[€“tÁ»³“a" xà·àûóa`üôC’¦ÐÒÃаð† G›‡öO@[€" ­ 4APŽQ“\£Æ”/qàr•§ø&·FÄþÆ}±Yb‹úþÆÜ´R¾˜@•¯þøïq⇅øÇð¡`ƒZè‚ÑÉñ·àÒa±P°ð›SƒC@„¬ñô,Ÿ>™ %t›î ú$@ÆrŸÀ„Ÿ…¨ŸºŸ_怹Ôÿâîîîþô›‰~ 5Ÿ½ÞÞÞµÀÁñábB”ƒÀÓóD€(¯8RÀÓ§Dø¢ò ƒ|@¤;°ðîîâÀ !Þ}£¡³úð÷ÚÎaÌ¿T|¯Ž¯ ¯£ŸüƯ¼—‘ƒôþøîÞµ*Aò+@€Ã²q@òo`½@o`@¿.º¿qnaxâH·ôxâù«?4〱¿Ôµ?‰ØêÖ¯·O赯¢¿ŸñÑ2PZ³³“óËp rƒ0C²]¥õs…üÐxâÞZ³U½“™Ì´ôÔ³ÒB³¥¯õsÇðxáêZ³Ä“£Ì³ƒöx@<ÏŽ¿ì`Ï›5™•]øðüOþ·ƒ™„Ñ:ÂÎÒ¬ð¤2Ö̳ޟϱϤ2åê̳îÐÏÛÙ£ÿúþ½¡ìÞÞÔÎ@}ß'ß9ß⥓îîàÐü"æòpâã¯ßþè±þììê? æR¯EA£þôχƒð³ÒºÁ­î:™îs³ßÅß×ßéßûß ïï6ÿCïUïgïyï‹ïï¯ïÁïÓïåï÷ï ÿÄÿà¿>÷2¯€V÷,ÿrÿ²¯–ÿ¨ÿäp¿îóîøÃƒ…ÈðC²h `êÿüÿ 2ÀDEÏhzŒá“Úµ±R…7ô—÷òÿÚþ¿…öþ§¿çþ¿©…ÐÅ‘ê“å——Á£1AúÐä¿þ¿¿þ¹“žÀ™|úÔÚÔ³ôµœ° €ÿ.â‡ØøÔ?4Wì법"¤ŸþwÞÜøŸþâ«@=»±üŸþê±tAz±›‰…þú‘rvè*A_ ̃£@wøþ™‚0Âðú%”€ÒäZ//,/Ò™™í¹˜Q‹örÂþîÖfaîþGP+@‡à§ü‰©K€i»Øq³û…¿w@³þ¹³þÿÔ‡òþ­‹ðüÿîþä‡ÂøAàjŸ¥/÷É/MÚiÒX_ò/\£ÚX ëýö'@ÞþÔ¡þî¾+@™Ÿþì« P£_þÞ½þØö°Þz Ý! ³þè‹PÞ…zQPÖ…ÑŸÔ#¤€\?n?À/’?¤?¶?B¾uÒÞþúÊg°äÿäþ©èþŸ³ÿþÄ“þö™ÌþùÎòa¿þôÄ­ÿŸ‡¿þÀÎÿ±þ̃ÒþÒÿ‹òüöþòÖüâûÏ'OÕ–|ƒ?DnúÜŸõê< ä0ÚþÀúæŠ`­³­w`‘Ó°¿¯îþòPþ/î¡‘ò²îœO¨HÒCQÃOÕO?ùO __ö뱡α•üþüûܯ_Pòèþâƒøþ­ÎþЙyPçÚþĄѺÀ¿þÊëðâ¿ ¿¯þ}òăàþøë0ß§‘¯Fƒ½±…Ðúð¹àÑ`±:úî`“ÌÚ9”4±_Ô—X”þàK´b³¼Ý_ï^­üÖ‘°òRŠìŽ ‹o`Ò0±Šo`£o`…)aS€ôR¯»þð°àµ0ùüÊ2€——ô‘Ò¼_eoЛ«_Õ–Îg»—ú`H±‰ö]Ð;‰ï ð“œ¼d¥úôR0_‰I±Ÿ0@£àoƒo­zØÖÿ¡a׉öL€™Wîü‹êÀ)~ü*°1±Bx6T‰ò”»v¨éO¬wá Ø©³üD¸Ÿè:`òWõR£)0æ›{üèèþ·É»Ýp“öhаþîyÑrÿpŸþäðý0ž§þü“÷€Ò?ðÔ…ÎÛo ¬îoЛ»Ä(q¿êÀµ‹øhÐþÞ0ò‘ò‡tb#d!ƒ·•þöôRõQ›0…蔂=ï@¦¸ÊÜÎRûƒÁ@þħêkÈ…”@¸`Ôø¶óþÒk€ð ü±þþiæa ï¡Üð Â¯I±7þþ·ð ©µ¬›¡ð ¿1ò^¿HT!­@e!¿50¬A‹I°ýΊÁÈú“›§“ЫŸ¦Ÿ¸ŸÊŸ`d¯^Ô…ê Ÿ·Ìþú¥ð fÐØð qÐÞ𠱄Ðð {P=Þ°½þÜH±;0îY¨»þΈ …À«o!x¯Š¯ÜŸ®¯À¯Ò¯xI±É°øôÒ£ŽÁþ“…úþ¹Þþ{¡A°Äþ൴ºb¿}PÆþìz!ØÿþÚ¯þÚòþÿ½üúÄþüE0æÂ•#p<¿N¿`ª_r¿„¿–¿ë±§8ógüò‰£ÒþÜ“PôþÖ¹þôƒ:­¿›¿Í³Ÿ¿ê¯‹AqÄpþþ“9öý0›Ôþúw Oñ ½º²êÎì¡Bq¹³ËêþÎSƒ›’¯@ÏRÏðdϼ?, wÐàþôÜí¡@`ìâ™æþ©OÎþÊ‹OPÓ§"°¿Îþ»¹þÆ…¯þÅàþ¯·þÄ>¯¯‘øöôÂÀ‘QÖÎqèÂí"âhÓÞhÓÊÞ0ÊX@O ßߟ —ÿ…Úµþöl6¡c"âüHÑ©¹¶ £Ð·L`›ršs›r‡ø•rÁO¯ÿ϶ßÈßüÚߦ‹ÚþâkƒìOðÔ8`öÆ0ï¿þÖ·´©þü?«›æ8`û‰ÜÉÁ™«ÚþÿôÈþâìþäg‹Ö> :±›ì¢DBïž ¥ßwïÌP™Ï0ñÎÁÓ•â‡ÔþÎýüÑÞÆüþâ¹(äïïãĻчÏ1×ïÀžßûï ÿÿÃY°عñpÀ›†‡.0†_yÚ¡à´ÞþÎ¥VRõÎUQä^¡ä—üþ¿ÐìüôüN0“ìö­ìV4Ñô’ÿäïð¶ÿÈÿÚÿ…È‹ÄÛʃ00½ÒL€Èþû³À±Àêþ“«þ½Úµa—þ𯙃\uðÑÁèþø&ÁÐmA®d@þþÈËQîíÄ—>ï\` ²ÿ„–¨üºÌÄ­ÌþŒòÆþĽþ¯‹ÿêµìþ«¯þó»·÷Ð`§þÄÚWþö«ÊbÐR Ò™\µ`7¢¯ð0èKÑ˳–@`Üþ+ð‘˜@`Ømðá •AПÔï_q±ÿp•§¹‡ó‹¥ `ÿÎþÈÐþÖ‘ü þ—à°Þt!E0ÀAJñÚpÓSa3þ‰ÿúþÚþè·þ¿æ…ðþ§ÚC—Ú¥¯öNŠÁ%/wðI/[/m//ƒÈ™¡ÛÒ‘00è¯3°¿þûÒ¡}PÞþµ—þÿèƒúþ“‡þü¡k€ö1çrPþ·70ì‡,a°®aöþ»dÓ`­þúÏ1‹ðp!¸²à>/?"?4?}|“½ÎçâöÞ ð1£•Ì»©¿ÜqêC½¾0à‘úþ.ÁÚ“þÐ1QgQ¡+àð1?—øîæÚÎæ!ž?D°?a ?Ù?/™ Á߯æîîê®°™þ¡îÎS O!K³D—wìþ¹<ÒüþÖì¢$’QaÒ'!OiObü±b½þô³ÄÚ>^ÑàêÖ­Nû/(ÄOÖOVDî.ÂÞT€óO__)_;_M_ïDl_Ç?4_}}Ÿ‘îù¡Ðƒ‰‡×ÄãÁîÃPULq’Ú\ìþõ XCÚw£÷‘ìþ#£öþä""äþÌÚ_e:´:qzbò&Áƒ£Î °ž…0èØÎ¿Œÿ~{ €€_ˆošo¬o¾oÐo s»›Î·w¡µXð8 Òý± ­þȱÔüî¥á‘µñÁµÎ·K"4FXj|Ž_¿²ÄÖèú 0BTfŠœ®ÀÒäöŸŸ,Ÿ>ŸubŸtŸ†Ÿ˜ŸªŸ¼ŸÎŸàŸòŸ¯¯MŸ:¯L¯^¯p¯‚¯”¯¦¯¸¯Ê¯Ü¯î¯¿7¯$¿6¿H¿Z¿l¿~¿¿¢¿´¿Æ¿Ø¿¿ü¿Ï Ï2ÏDÏVÏhÏzόϞϰÏç¿ÔÏæÏøÏ ßß.ß@ßRßdßv߈߿Ϭ߾ßÐßâßôßïï*ï<ïNï`ï—ߩߖï¨ïºïÌïÞïðïÿÿ&ÿ8ÿJÿïnÿ€ÿ’ÿ¤ÿ¶ÿÈÿÚÿìÿþÿ"YÿFXj|Ž ²ÄÖèú10BTfxŠœ®ÀÒ ö//,/>/P/b/t/†/˜/ª/¼/óà/ò/??(?:?L?^?p?‚?”?Ë/¸?Ê?Ü?î?OO$O6OHOZOlO£?O¢O´OÆOØOêOüO_ _2_D_{Oh_z_Œ_ž_°_Â_Ô_æ_ø_ ooS_e_Rodovoˆošo¬o¾oÐoâoôo=o*<N`r„–¨ºÌÞ&8J\n€’¤¶íÚìþŸ"Ÿ4ŸFŸXŸjŸ|ŸŽŸÅ²ŸÄŸÖŸèŸúŸ ¯¯0¯B¯T¯f¯x¯¯Ÿœ¯®¯À¯Ò¯ä¯ö¯¿¿,¿>¿P¿‡¯t¿†¿˜¿ª¿¼¿Î¿à¿ò¿ÏÏ(Ï_¿LÏ^ÏpςϔϦϸÏÊÏÜÏîÏß7Ï$ß6ßHßZßlß~ßߢߴ߯ߨßß!ßï ï2ïDïVïhïzïŒïžï°ïÂïùßæïøï ÿÿ.ÿ@ÿRÿdÿvÿˆÿšÿÑï¾ÿÐÿâÿôÿ*<N`r©ÿ–¨ºÌÞð&8Jn€’¤¶ÈÚìþ/"/4/kX/j/|/Ž/ /²/Ä/Ö/è/ú/ ?C/0?B?T?f?x?Š?œ?®?À?Ò?ä??OO,O>OPObOtO†O˜OªO¼Oó?àOòO__(_:_L_^_p_‚_”_ËOÝOÊ_Ü_î_oo$o6oHoZolo~oµ_¢o´oÆoØoêoüo 2DVozŒž°ÂÔæø .eRdvˆš¬¾ÐâôŸ=*Ÿ<ŸNŸ`ŸrŸ„Ÿ–Ÿ¨ŸºŸÌŸÞŸðŸ'Ÿ¯&¯8¯J¯\¯n¯€¯’¯¤¯¶¯È¯ÿŸì¯þ¯¿"¿4¿F¿X¿j¿|¿Ž¿ ¿×¯Ä¿Ö¿è¿ú¿ ÏÏ0ÏBÏTÏfÏxϯ¿œÏ®ÏÀÏÒÏäÏöÏßß,ß>ßP߇ϙφߘߪ߼ßÎßàßòßïï(ï:ïqß^ïpï‚ï”ï¦ï¸ïÊïÜïîïÿÿIï6ÿHÿZÿlÿ~ÿÿ¢ÿ´ÿÆÿØÿêÿ!ÿ 2DVhzŒž°Âùÿæø .@Rdvˆš¬ãÐâô//*/oPoboto†o˜oªo¼oÎooòo(:L^p‚”¦ÝoÊÜî$6HZl~µ¢´ÆØêüŸ Ÿ2ŸDŸVŸhŸŸŒŸžŸ°ŸÂŸÔŸæŸøŸ ¯¯.¯@¯wŸd¯v¯ˆ¯š¯¬¯¾¯Ð¯â¯ô¯¿¿O¯<¿N¿`¿r¿„¿–¿¨¿º¿Ì¿Þ¿ð¿'¿Ï&Ï8ÏJÏ\ÏnπϒϤ϶ÏÈÏÿ¿ÏþÏß"ß4ßFßXßjß|ߎߠ߲ßéÏÖßèßúß ïï0ïBïTïfïxïŠïÁß®ïÀïÒïäïöïÿÿ,ÿ>ÿPÿbÿ™ï†ÿ˜ÿªÿ¼ÿÎÿàÿòÿ(:qÿ^p‚”¦¸ÊÜî$[HZl~¢´ÆØêü3 /2/D/V/h/z/Œ/ž/°/Â/Ô/ /ø/ ??.?@?R?d?v?ˆ?š?¬?ã/Ð?â?ô?OO*OPbt†˜ª¼ÎàŸŸ(Ÿ:ŸLŸ^ŸpŸ‚Ÿ”Ÿ¦Ÿ¸Ÿïܟ¯$¯6¯H¯Z¯l¯~¯¯ÇŸ´¯Æ¯Ø¯ê¯ü¯¿ ¿2¿D¿V¿h¿Ÿ¯Œ¿ž¿°¿Â¿Ô¿æ¿ø¿ ÏÏ.Ï@Ïw¿‰¿vψϚϬϾÏÐÏâÏôÏßß*ßaÏNß`ßr߄ߖߨߺßÌßÞßðßï9ß&ï8ïJï\ïnï€ï’ï¤ï¶ïÈïÚïïþïÿ"ÿ4ÿFÿXÿjÿ|ÿŽÿ ÿ²ÿéïÖÿèÿúÿ 0BTfxŠœÓÿÀÒäö,>Pbt«˜ª¼Îàò//(/:/L/ƒp/‚/”/¦/¸/Ê/Ü/î/??$?[/H?Z?l?~??¢?´?Æ?Ø?ê?ü?3?E?2ODOVOhOzOŒOžO°OÂOÔOæOO __._@_R_d_v_ˆ_š_¬_¾_õOâ_ô_oo*o¯P¯b¯t¯†¯˜¯ª¯¼¯Î¯à¯¯¿¿(¿:¿L¿^¿p¿‚¿”¿¦¿¸¿ï¯¿î¿ÏÏ$Ï6ÏHÏZÏlÏ~ÏÏ¢ÏÙ¿ÆÏØÏêÏüÏß ß2ßDßVßhßz߱Ϟ߰ßÂßÔßæßøß ïï.ï@ïRï‰ßvïˆïšï¬ï¾ïÐïâïôïÿÿ*ÿaïNÿ`ÿrÿ„ÿ–ÿ¨ÿºÿÌÿÞÿðÿKÿ8J\n€’¤¶ÈÚì#"4FXj|Ž ²Äûèú //0/B/T/f/x/Š/œ/ÓÀ/Ò/ä/ö/??,?>?P?b?t?«/½/ª?¼?Î?à?ò?OO(O:OLO^O•?‚O”O¦O¸OÊOÜOîO__$_6_mOZ_l_~__¢_´_Æ_Ø_ê_ü_oE_2oDoVohozoŒožo°oÂoÔoæoo .@Rdvˆš¬¾Ðô*ÏPÏbÏtφϘϪϼÏÎÏàÏòÏ)Ïß(ß:ßLß^ßp߂ߔߦ߸ßÊßßîßïï$ï6ïHïZïlï~ïï¢ïÙ߯ïØïêïüïÿ ÿ2ÿDÿVÿhÿzÿŒÿÃï°ÿÂÿÔÿæÿøÿ .@Rd›ÿˆš¬¾Ðâô*<s`r„–¨ºÌÞð//K8/J/\/n/€/’/¤/¶/È/Ú/ì/#/5/"?4?F?X?j?|?Ž? ?²?Ä?Ö? ?ú? OO0OBOTOfOxOŠOœO®Oå?ÒOäOöO__,_>_P_b_t_†_½Oª_¼_Î_à_ò_oo(o:oLo^opjpropNAMEPALPAL Jÿÿüþíñ ÿ(ÿ##2//<¯???íòª'/ª7?G íð ªS [ c kªs{ƒ‹ªí𗟧ª¯·¿ÇªÏíðÛãªëó û!"ª #$íð%&ª''/(7)?*ªG+O,W-íð.ªc/k0s1{2ªƒ3‹4“5›6ªíð7§8¯9·:ª¿;Ç<Ï=×>¸ß ìóõ»ý"» ""»"%"»-" 5" » =" E" » M" U"»]"e"»m"u"»}"…"»"•"»"¥"»­"µ"»½"Å"»Í"Õ"»Ý"å" » í"!!!õ""»""ý"###2$»$$ 2%%%2&»&&2'''%2(»((-2)))52*»**=2+++E2,»,,M2---U2.»..]2///e20»00m2111u22»22}2333…24»442555•26»662777¥28»88­2999µ2:»::½2;;;Å2<»<<Í2===Õ2>>>Ý2  propBACKnpropDITHnpropHNAMfont.hpropHPREFONTpropNAME GrabberInfopropPACK1propXGRD16propYGRD16info For internal use by the grabberallegro4.4-4.4.2/addons/allegrogl/examp/dialog.c000066400000000000000000000222561173507505700213520ustar00rootroot00000000000000/*---------------------------------------------------------------- * test.c -- Allegro-GL test program *---------------------------------------------------------------- * Based on firstogl.c. */ #include /* Note: Under Windows, if you include any Windows headers (e.g. GL/gl.h), * you must include first. To save you working out when this * occurs, `alleggl.h' handles this for you, and includes . If * you need other GL headers, include them afterwards. * * Also note that user programs, outside of this library distribution, * should use <...> notation for `alleggl.h'. */ #include "alleggl.h" static void display (void); struct camera { double xangle, yangle, zangle; double dist; }; static struct camera camera = { 0.0, 0.0, 0.0, 20.0 }; static double angle_speed = 5.0; static double dist_speed = 1.0; static int frames = 0; static volatile int secs; static void secs_timer(void) { secs++; } END_OF_STATIC_FUNCTION(secs_timer); static void set_camera_position (void) { /* Note: Normally, you won't build the camera using the Projection * matrix. See excamera.c on how to build a real camera. * This code is there just to simplify this test program a bit. */ glMatrixMode (GL_PROJECTION); glLoadIdentity (); glFrustum (-1.0, 1.0, -1.0, 1.0, 1.0, 40.0); glTranslatef (0, 0, -camera.dist); glRotatef (camera.xangle, 1, 0, 0); glRotatef (camera.yangle, 0, 1, 0); glRotatef (camera.zangle, 0, 0, 1); glMatrixMode (GL_MODELVIEW); } static void keyboard (void) { if (key[KEY_LEFT]) camera.yangle += angle_speed; if (key[KEY_RIGHT]) camera.yangle -= angle_speed; if (key[KEY_UP]) camera.xangle += angle_speed; if (key[KEY_DOWN]) camera.xangle -= angle_speed; if (key[KEY_PGUP]) camera.dist -= dist_speed; if (key[KEY_PGDN]) camera.dist += dist_speed; if (key[KEY_D]) alert ("You pressed D", NULL, NULL, "OK", NULL, 0, 0); set_camera_position(); display(); } static void display (void) { // Clear the RGB buffer and the depth buffer glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Set the modelview matrix to be the identity matrix glLoadIdentity(); // Translate and rotate the object glTranslatef(-2.5, 0.0, 0.0); glRotatef(-30, 1.0, 0.0, 0.0); glRotatef(30, 0.0, 1.0, 0.0); glRotatef(30, 0.0, 0.0, 1.0); glColor3f(1.0, 0.0, 1.0); // Draw the sides of the three-sided pyramid glBegin(GL_TRIANGLE_FAN); glVertex3d(0, 4, 0); glVertex3d(0, -4, -4); glVertex3d(-4, -4, 4); glVertex3d(4, -4, 4); glVertex3d(0, -4, -4); glEnd(); glColor3f(0.0, 1.0, 1.0); // Draw the base of the pyramid glBegin(GL_TRIANGLES); glVertex3d(0, -4, -4); glVertex3d(4, -4, 4); glVertex3d(-4, -4, 4); glEnd(); glLoadIdentity(); glTranslatef(2.5, 0.0, 0.0); glRotatef(45, 1.0, 0.0, 0.0); glRotatef(45, 0.0, 1.0, 0.0); glRotatef(45, 0.0, 0.0, 1.0); glColor3f(0.0, 1.0, 0.0); // Draw the sides of the cube glBegin(GL_QUAD_STRIP); glVertex3d(3, 3, -3); glVertex3d(3, -3, -3); glVertex3d(-3, 3, -3); glVertex3d(-3, -3, -3); glVertex3d(-3, 3, 3); glVertex3d(-3, -3, 3); glVertex3d(3, 3, 3); glVertex3d(3, -3, 3); glVertex3d(3, 3, -3); glVertex3d(3, -3, -3); glEnd(); glColor3f(0.0, 0.0, 1.0); // Draw the top and bottom of the cube glBegin(GL_QUADS); glVertex3d(-3, -3, -3); glVertex3d(3, -3, -3); glVertex3d(3, -3, 3); glVertex3d(-3, -3, 3); glVertex3d(-3, 3, -3); glVertex3d(-3, 3, 3); glVertex3d(3, 3, 3); glVertex3d(3, 3, -3); glEnd(); glFlush(); allegro_gl_flip(); frames++; } static int mode = AGL_FULLSCREEN, width, height; struct resolution_entry { int w,h; char *s; } resolutions[] = { { 320, 240, " 320x240 " }, { 640, 480, " 640x480 " }, { 800, 600, " 800x600 " }, { 1024, 768, "1024x768 " }, { 1280, 1024, "1280x1024" }, { 1600, 1200, "1600x1200" } }; static char *resolution_lister (int i, int *size) { if (i < 0) { *size = sizeof resolutions / sizeof *resolutions; return NULL; } return resolutions[i].s; } struct colour_depth_entry { int depth; char *s; } colour_depths[] = { { 8, " 8 bpp" }, { 15, "15 bpp" }, { 16, "16 bpp" }, { 24, "24 bpp" }, { 32, "32 bpp" } }; static char *colour_depth_lister (int i, int *size) { if (i < 0) { *size = sizeof colour_depths / sizeof *colour_depths; return NULL; } return colour_depths[i].s; } struct zbuffer_depth_entry { int depth; char *s; } zbuffer_depths[] = { { 8, " 8 bits" }, { 16, "16 bits" }, { 24, "24 bits" }, { 32, "32 bits" } }; static char *zbuffer_depth_lister (int i, int *size) { if (i < 0) { *size = sizeof zbuffer_depths / sizeof *zbuffer_depths; return NULL; } return zbuffer_depths[i].s; } static int setup (void) { #define RESOLUTION_LIST 4 #define COLOUR_LIST 6 #define ZBUFFER_LIST 8 #define WINDOWED_BOX 9 #define DOUBLEBUFFER_BOX 10 #define BUTTON_OK 11 DIALOG dlg[] = { /* proc x y w h fg bg key flags d1 d2 dp */ { d_shadow_box_proc, 0, 0, 320, 200, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, { d_ctext_proc, 160, 10, 0, 0, 0, 0, 0, 0, 0, 0, "____________", NULL, NULL }, { d_ctext_proc, 160, 8, 0, 0, 0, 0, 0, 0, 0, 0, "OpenGL Setup", NULL, NULL }, { d_text_proc, 10, 30, 0, 0, 0, 0, 0, 0, 0, 0, "Resolution", NULL, NULL }, { d_list_proc, 10, 40, 96, 52, 0, 0, 0, 0, 0, 0, resolution_lister, NULL, NULL }, { d_text_proc, 120, 30, 0, 0, 0, 0, 0, 0, 0, 0, "Colour depth", NULL, NULL }, { d_list_proc, 120, 40, 96, 48, 0, 0, 0, 0, 0, 0, colour_depth_lister, NULL, NULL }, { d_text_proc, 10, 104, 96, 48, 0, 0, 0, 0, 0, 0, "Z buffer", NULL, NULL }, { d_list_proc, 10, 114, 96, 48, 0, 0, 0, 0, 0, 0, zbuffer_depth_lister, NULL, NULL }, { d_check_proc, 10, 170, 96, 8, 0, 0, 0, 0, 1, 0, "Windowed", NULL, NULL }, { d_check_proc, 10, 180, 128, 8, 0, 0, 0,D_SELECTED, 1, 0, "Double Buffered", NULL, NULL }, { d_button_proc, 220, 150, 96, 18, 0, 0, 0, D_EXIT, 0, 0, "Ok", NULL, NULL }, { d_button_proc, 220, 174, 96, 18, 0, 0, 0, D_EXIT, 0, 0, "Exit", NULL, NULL }, { d_yield_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } }; int x; if (mode == AGL_WINDOWED) dlg[WINDOWED_BOX].flags |= D_SELECTED; centre_dialog (dlg); set_dialog_color (dlg, makecol(0, 0, 0), makecol(255, 255, 255)); if (secs) { textprintf_centre_ex(screen, font, SCREEN_W / 2, SCREEN_H / 2 + 110, makecol(255, 255, 255), 0, "Frames: %i, Seconds: %i, FPS: %f", frames, secs, (float)frames / (float)secs); } x = do_dialog (dlg, 4); allegro_gl_clear_settings(); allegro_gl_set(AGL_COLOR_DEPTH, colour_depths[dlg[COLOUR_LIST].d1].depth); allegro_gl_set(AGL_Z_DEPTH, zbuffer_depths[dlg[ZBUFFER_LIST].d1].depth); allegro_gl_set(AGL_DOUBLEBUFFER, (dlg[DOUBLEBUFFER_BOX].flags & D_SELECTED) ? 1 : 0); allegro_gl_set(AGL_RENDERMETHOD, 1); mode = ((dlg[WINDOWED_BOX].flags & D_SELECTED) ? AGL_WINDOWED : AGL_FULLSCREEN); allegro_gl_set(mode, TRUE); allegro_gl_set(AGL_SUGGEST, AGL_COLOR_DEPTH | AGL_Z_DEPTH | AGL_DOUBLEBUFFER | AGL_RENDERMETHOD | mode); width = resolutions[dlg[RESOLUTION_LIST].d1].w; height = resolutions[dlg[RESOLUTION_LIST].d1].h; return (x == BUTTON_OK); } static void run_demo (void) { set_color_depth (16); if (set_gfx_mode(GFX_OPENGL, width, height, 0, 0) < 0) { allegro_message ("Error setting OpenGL graphics mode:\n%s\nAllegro GL error : %s\n", allegro_error, allegro_gl_error); return; } install_keyboard(); LOCK_FUNCTION(secs_timer); LOCK_VARIABLE(secs); glClearColor (0, 0, 0, 0); glShadeModel (GL_FLAT); glPolygonMode (GL_FRONT_AND_BACK, GL_FILL); glPolygonMode (GL_BACK, GL_POINTS); glEnable (GL_DEPTH_TEST); glCullFace (GL_BACK); glEnable (GL_CULL_FACE); install_int (secs_timer, 1000); do { keyboard(); rest(2); } while (!key[KEY_ESC]); remove_int (secs_timer); remove_keyboard(); } int main() { int ok; allegro_init(); install_timer(); do { set_color_depth(8); if (set_gfx_mode (GFX_AUTODETECT, 640, 480, 0, 0) < 0) { allegro_message ("Error setting plain graphics mode:\n%s\n", allegro_error); return -1; } install_allegro_gl(); install_keyboard(); install_mouse(); ok = setup(); remove_keyboard(); remove_mouse(); if (ok) run_demo(); remove_allegro_gl(); } while (ok); return 0; } END_OF_MAIN() allegro4.4-4.4.2/addons/allegrogl/examp/dumbtest.c000066400000000000000000000263521173507505700217430ustar00rootroot00000000000000#include #include "alleggl.h" volatile int chrono = 0; void the_timer(void) { chrono++; } END_OF_FUNCTION(the_timer); int poly_coords[12] = {150, 400, 200, 400, 225, 425, 200, 450, 175, 450, 175, 425}; /* Some common colours */ #define CYAN makecol(0,255,255) #define BLACK makecol(0,0,0) int main() { float rotate = 0; BITMAP *save_bmp; BITMAP *sub_screen, *sub_screen2, *vid_bitmap, *mem_bitmap, *vid_bitmap2, *trans_mem_bitmap, *trans_vid_bitmap, *trans_vid_bitmap2, *large_vid_bitmap, *proxy_vid_bitmap, *vid_pattern; RLE_SPRITE *rle_sprite, *trans_rle_sprite; int keypress; int frame_count = 0, frame_count_time = 0; int x, y; float fps_rate = 0.0; allegro_init(); install_allegro_gl(); install_timer(); allegro_gl_set(AGL_DOUBLEBUFFER, 1); allegro_gl_set(AGL_WINDOWED, TRUE); allegro_gl_set(AGL_COLOR_DEPTH, 32); allegro_gl_set(AGL_SUGGEST, AGL_DOUBLEBUFFER | AGL_WINDOWED | AGL_COLOR_DEPTH); if(set_gfx_mode(GFX_OPENGL, 640, 480, 0, 0)<0) { allegro_message ("Error setting OpenGL graphics mode:\n%s\n" "Allegro GL error : %s\n", allegro_error, allegro_gl_error); exit(0); } /* Needed because of a bug. */ allegro_gl_set_allegro_mode(); allegro_gl_unset_allegro_mode(); save_bmp = create_bitmap (640, 480); ASSERT (save_bmp); sub_screen = create_sub_bitmap(screen, 320, 0, 128, 96); sub_screen2 = create_sub_bitmap(screen, 448, 0, 128, 96); ASSERT(sub_screen); ASSERT(sub_screen2); vid_bitmap = create_video_bitmap(50, 50); clear_to_color(vid_bitmap, makecol(255,0,255)); rect(vid_bitmap, 10, 10, 39, 39, makecol(255, 255, 255)); rectfill(vid_bitmap, 12, 12, 37, 37, makecol(255, 0, 0)); triangle(vid_bitmap, 9, 9, 46, 3, 0, 16, makecol(0, 255, 0)); mem_bitmap = create_bitmap(50, 50); clear(mem_bitmap); blit(vid_bitmap, mem_bitmap, 25, 25, 10, 10, 50, 50); vid_pattern = create_video_bitmap(32, 32); clear_bitmap(vid_pattern); blit(vid_bitmap, vid_pattern, 0, 0, 0, 0, 32, 32); TRACE("Starting main loop\n"); save_bitmap("dumbtest.bmp", mem_bitmap, NULL); rle_sprite = get_rle_sprite(mem_bitmap); vid_bitmap2 = create_video_bitmap(64, 64); clear_to_color(vid_bitmap2, makecol(255,0,255)); blit(mem_bitmap, vid_bitmap2, 0, 0, 10, 10, 50, 50); trans_mem_bitmap = create_bitmap_ex(32, mem_bitmap->w, mem_bitmap->h); for (y = 0; y < mem_bitmap->h; ++y) { for (x = 0; x < mem_bitmap->w; ++x) { int col = getpixel(mem_bitmap, x, y); putpixel(trans_mem_bitmap, x, y, makeacol32(getr(col), getg(col), getb(col), y*4)); } } allegro_gl_set_video_bitmap_color_depth(32); trans_vid_bitmap2 = create_video_bitmap(64, 64); clear_bitmap(trans_vid_bitmap2); blit(trans_mem_bitmap, trans_vid_bitmap2, 0, 0, 10, 10, 50, 50); trans_vid_bitmap = create_video_bitmap(50, 50); clear_to_color(trans_mem_bitmap, makeacol32(255, 0, 255, 127)); rect(trans_mem_bitmap, 10, 10, 39, 39, makeacol32(255, 255, 255, 127)); rectfill(trans_mem_bitmap, 12, 12, 37, 37, makeacol32(255, 0, 0, 192)); triangle(trans_mem_bitmap, 9, 9, 46, 3, 0, 16, makeacol32(0, 255, 0, 192)); blit(trans_mem_bitmap, trans_vid_bitmap, 0, 0, 0, 0, 50, 50); trans_rle_sprite = get_rle_sprite(trans_mem_bitmap); allegro_gl_set_video_bitmap_color_depth(-1); large_vid_bitmap = create_video_bitmap(120, 120); clear_to_color(large_vid_bitmap, BLACK); rect(large_vid_bitmap, 0, 0, large_vid_bitmap->w-1, large_vid_bitmap->h-1, makecol(255, 255, 0)); line(large_vid_bitmap, 0, 0, large_vid_bitmap->w, 30, makecol(255, 0, 0)); line(large_vid_bitmap, large_vid_bitmap->w, 0, 0, large_vid_bitmap->h, makecol(255, 0, 0)); proxy_vid_bitmap = create_video_bitmap(100, 100); clear_to_color(proxy_vid_bitmap, CYAN); line(proxy_vid_bitmap, 0, 0, proxy_vid_bitmap->w, proxy_vid_bitmap->h, makecol(255, 0, 0)); /* memory -> video */ blit(mem_bitmap, proxy_vid_bitmap, 0, 0, 5, 5, mem_bitmap->w, mem_bitmap->h); set_alpha_blender(); /* memory -> video trans */ draw_trans_sprite(proxy_vid_bitmap, trans_mem_bitmap, mem_bitmap->w, 5); /* video -> video trans */ draw_trans_sprite(proxy_vid_bitmap, trans_vid_bitmap, 5, mem_bitmap->h); { /* textured 3d polygon -> video bitmap */ V3D_f v1, v2, v3, v4; v1.x = 50; v1.y = 50; v1.u = 0; v1.v = 0; v2.x = 98; v2.y = 50; v2.u = 70; v2.v = 0; v3.x = 98; v3.y = 98; v3.u = 70; v3.v = 70; v4.x = 50; v4.y = 98; v4.u = 0; v4.v = 70; quad3d_f(proxy_vid_bitmap, POLYTYPE_ATEX, vid_pattern, &v1, &v2, &v3, &v4); } /* video -> video */ draw_sprite(large_vid_bitmap, proxy_vid_bitmap, 5, 5); textout_ex(large_vid_bitmap, font, "some text", 15, 35, -1, -1); install_keyboard(); LOCK_VARIABLE(chrono); LOCK_FUNCTION(the_timer); install_int(the_timer, 5); /* Setup OpenGL like we want */ glEnable(GL_TEXTURE_2D); do { if (keypressed()) keypress = readkey(); else keypress = 0; rotate+=1.0; if(rotate>360.0) rotate=0; glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); glPushMatrix(); glRotatef(45, 1, 0, 0); glRotatef(rotate, 0.0, 1.0, 0.0); glBegin(GL_QUADS); glColor3f(1.0, 0.0, 1.0); glVertex3f(0.1, 0.1, 0.1); glVertex3f(0.1, -0.1, 0.1); glVertex3f(-0.1, -0.1, 0.1); glVertex3f(-0.1, 0.1, 0.1); glColor3f(1.0, 0.0, 0.0); glVertex3f(0.1, 0.1, -0.1); glVertex3f(0.1, -0.1, -0.1); glVertex3f(-0.1, -0.1, -0.1); glVertex3f(-0.1, 0.1, -0.1); glColor3f(0.0, 1.0, 0.0); glVertex3f(0.1, 0.1, 0.1); glVertex3f(0.1, -0.1, 0.1); glVertex3f(0.1, -0.1, -0.1); glVertex3f(0.1, 0.1, -0.1); glEnd(); glPopMatrix(); frame_count++; if (frame_count >= 20) { if (chrono - frame_count_time) fps_rate = frame_count * 200.0 / (chrono - frame_count_time); else fps_rate = frame_count * 200.0; frame_count_time = chrono; frame_count = 0; } allegro_gl_set_allegro_mode(); line(screen, 0, 0, 640, 480, makecol(0xff, 0, 0xff)); triangle(screen, 115, 21, 150, 350, 5, 90, makecol(0xff, 0, 0)); triangle(screen, 145, 21, 190, 350, 45, 90, makecol(0, 0, 0xff)); triangle(screen, 205, 21, 240, 350, 95, 90, makecol(0, 0xff, 0xff)); triangle(screen, 245, 21, 290, 350, 145, 90, makecol(0xff, 0xff, 0)); rect(screen, 0, 0, 639, 479, makecol(0xff, 0xbf, 0x00)); putpixel(screen, 0, 0, makecol(0xff, 0xff, 0xff)); putpixel(screen, 639, 0, makecol(0xff, 0xff, 0xff)); putpixel(screen, 0, 479, makecol(0xff, 0xff, 0xff)); putpixel(screen, 639, 479, makecol(0xff, 0xff, 0xff)); putpixel(screen, 0, 478, makecol(0xff, 0xff, 0xff)); putpixel(screen, 639, 478, makecol(0xff, 0xff, 0xff)); rectfill(screen, 16, 350, 256, 440, makecol(0xff, 0xff, 0xff)); textout_ex(screen, font, "Partially cut off text", -3, 450, makecol(255,255,255), -1); textout_ex(screen, font, "Hello World!", 40, 380, BLACK, -1); textprintf_ex(screen, font, 40, 400, makecol(0, 0, 0), -1, "FPS: %.2f", fps_rate); /* Now here's the interesting part. This section of code tests * the various blit combinations supported by AllegroGL. That is: * screen -> sub-bitmap of screen * sub-bitmap of screen -> sub-bitmap of screen * screen -> screen * video bitmap -> screen * screen -> memory bitmap * memory bitmap -> screen * rle sprite -> screen * * Other combinations are tested either at the init. */ blit (screen, sub_screen, 256, 192, 0, 0, 128, 96); blit (sub_screen, sub_screen2, 0, 0, 0, 0, 128, 96); blit (screen, screen, 0, 0, 400, 150, 90, 90); blit (vid_bitmap, screen, 0, 0, 0, 0, 50, 50); blit (vid_bitmap2, screen, 0, 0, 50, 0, 50, 50); blit (screen, mem_bitmap, 0, 0, 0, 0, 50, 50); blit (mem_bitmap, screen, 0, 0, 100, 0, 50, 50); masked_blit (vid_bitmap, screen, 0, 0, 0, 50, 50, 50); masked_blit (vid_bitmap2, screen, 0, 0, 50, 50, 50, 50); masked_blit (mem_bitmap, screen, 0, 0, 100, 50, 50, 50); draw_sprite(screen, vid_bitmap, 0, 100); draw_sprite(screen, vid_bitmap2, 50, 100); draw_sprite(screen, mem_bitmap, 100, 100); draw_rle_sprite(screen, rle_sprite, 150, 100); set_alpha_blender(); draw_trans_sprite(screen, trans_vid_bitmap, 0, 150); draw_trans_sprite(screen, trans_vid_bitmap2, 50, 150); draw_trans_sprite(screen, trans_mem_bitmap, 100, 150); draw_trans_rle_sprite(screen, trans_rle_sprite, 150, 150); pivot_scaled_sprite(screen, vid_bitmap, 0, 200, 0, 0, itofix(6), ftofix(1.1)); pivot_scaled_sprite(screen, vid_bitmap2, 50, 200, 0, 0, itofix(6), ftofix(1.1)); pivot_scaled_sprite(screen, mem_bitmap, 100, 200, 0, 0, itofix(6), ftofix(1.1)); draw_sprite_ex(screen, trans_vid_bitmap, 0, 250, DRAW_SPRITE_TRANS, DRAW_SPRITE_VH_FLIP); draw_sprite_ex(screen, trans_vid_bitmap2, 50, 250, DRAW_SPRITE_TRANS, DRAW_SPRITE_VH_FLIP); draw_sprite_ex(screen, trans_mem_bitmap, 100, 250, DRAW_SPRITE_TRANS, DRAW_SPRITE_VH_FLIP); /* Write the captions for each image */ textout_ex(screen, font, "blit", 200, 25, CYAN, BLACK); textout_ex(screen, font, "masked_blit", 200, 75, CYAN, BLACK); textout_ex(screen, font, "draw_sprite", 200, 125, CYAN, BLACK); textout_ex(screen, font, "draw_trans_sprite", 200, 175, CYAN, BLACK); textout_ex(screen, font, "pivot_scaled_sprite", 200, 225, CYAN, BLACK); textout_ex(screen, font, "draw_sprite_ex", 200, 275, CYAN, BLACK); textout_centre_ex(screen, font, "vid", 25, 325, CYAN, BLACK); textout_centre_ex(screen, font, "NPOT", 25, 335, CYAN, BLACK); textout_centre_ex(screen, font, "vid", 75, 325, CYAN, BLACK); textout_centre_ex(screen, font, "POT", 75, 325, CYAN, BLACK); textout_centre_ex(screen, font, "mem",125, 325, CYAN, BLACK); textout_centre_ex(screen, font, "rle",175, 325, CYAN, BLACK); drawing_mode(DRAW_MODE_SOLID, 0, 0, 0); rectfill(screen, 250, 400, 300, 450, CYAN); drawing_mode(DRAW_MODE_XOR, NULL, 0, 0); rect(screen, 270, 420, 280, 430, CYAN); solid_mode(); polygon(screen, 6, poly_coords, CYAN); drawing_mode(DRAW_MODE_TRANS, 0, 0, 0); set_trans_blender(305, 255, 305, 128); rectfill(screen, 170, 400, 200, 450, BLACK); drawing_mode(DRAW_MODE_COPY_PATTERN, vid_pattern, 50, 50); triangle(screen, 320, 350, 430, 350, 320, 480, 0); rectfill(screen, 400, 400, 450, 450, 0); solid_mode(); /* video -> screen stertching */ stretch_blit(large_vid_bitmap, screen, 0, 0, large_vid_bitmap->w, large_vid_bitmap->h, 460, 350, large_vid_bitmap->w+50, large_vid_bitmap->h); allegro_gl_unset_allegro_mode(); if ((keypress & 0xdf) == 'S') blit (screen, save_bmp, 0, 0, 0, 0, 640, 480); glFlush(); allegro_gl_flip(); if ((keypress & 0xdf) == 'S') { save_bitmap ("screen.bmp", save_bmp, desktop_palette); } rest(2); }while(!key[KEY_ESC]); allegro_gl_set_allegro_mode(); glDrawBuffer(GL_FRONT); glReadBuffer(GL_FRONT); textout_ex(screen, font, "Press any key to exit...", 0, 470, makecol(255, 255, 255), -1); /* check the dialog saved the background OK */ readkey(); destroy_bitmap(save_bmp); destroy_bitmap(sub_screen); destroy_bitmap(sub_screen2); destroy_bitmap(mem_bitmap); destroy_bitmap(vid_bitmap); destroy_bitmap(vid_bitmap2); destroy_bitmap(trans_mem_bitmap); destroy_bitmap(trans_vid_bitmap); destroy_bitmap(trans_vid_bitmap2); destroy_bitmap(proxy_vid_bitmap); destroy_bitmap(large_vid_bitmap); destroy_bitmap(vid_pattern); destroy_rle_sprite(rle_sprite); destroy_rle_sprite(trans_rle_sprite); return 0; } END_OF_MAIN() allegro4.4-4.4.2/addons/allegrogl/examp/exalleg.c000066400000000000000000000146351173507505700215360ustar00rootroot00000000000000/* Allegro-AllegroGL interface example */ #include #include #include "allegro.h" #include "alleggl.h" #include "running.h" #ifndef M_PI #define M_PI 3.1415926535897932384626433832795 #endif volatile int chrono = 0; void the_timer(void) { chrono++; } END_OF_FUNCTION(the_timer); int main() { BITMAP *texture; GLuint tex[6]; int i = 0; int frame_count = 0, frame_count_time = 0; float fps_rate = 0.0; FONT *f; int old_depth; /* Init Allegro */ allegro_init(); install_allegro_gl(); install_keyboard(); install_mouse(); /* Set up an OpenGL screen mode */ allegro_gl_clear_settings(); allegro_gl_set(AGL_COLOR_DEPTH, 32); allegro_gl_set(AGL_Z_DEPTH, 24); allegro_gl_set(AGL_WINDOWED, TRUE); allegro_gl_set(AGL_DOUBLEBUFFER, 1); allegro_gl_set(AGL_RENDERMETHOD, 1); allegro_gl_set(AGL_SUGGEST, AGL_COLOR_DEPTH | AGL_DOUBLEBUFFER | AGL_RENDERMETHOD | AGL_Z_DEPTH | AGL_WINDOWED); if (set_gfx_mode(GFX_OPENGL, 640, 480, 0, 0)) { allegro_message("Error setting OpenGL graphics mode:\n%s\n" "Allegro GL error : %s\n", allegro_error, allegro_gl_error); return -1; } /* Set up a timer that ticks every 5 ms */ LOCK_FUNCTION(the_timer); LOCK_VARIABLE(chrono); install_int(the_timer, 5); /* Let's load the mysha image in various color depths. */ old_depth = bitmap_color_depth(screen); for (i = 0; i < 3; i++) { char name[256]; /* Load mysha */ set_color_depth((i + 2) * 8); texture = load_bitmap("mysha.pcx", NULL); if (!texture) { set_gfx_mode(GFX_TEXT, 0, 0, 0, 0); allegro_message("Unable to load mysha.pcx - did you copy Allegro's here?\n"); return -3; } tex[i * 2] = allegro_gl_make_masked_texture(texture); tex[i * 2 + 1] = allegro_gl_make_texture(texture); /* Just to verify that the load was successful, save the images to disk * so they can be checked manually. */ uszprintf(name, sizeof(name), "mysha%i.bmp", i); save_bitmap(name, texture, NULL); destroy_bitmap(texture); } set_color_depth(old_depth); /* Convert the Allegro font */ f = allegro_gl_convert_allegro_font(font, AGL_FONT_TYPE_TEXTURED, 16.0); /* Now display everything */ /* Setup OpenGL the way we want */ glEnable(GL_TEXTURE_2D); glEnable(GL_BLEND); glViewport(0, 0, SCREEN_W, SCREEN_H); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glFrustum(-1.0, 1.0, -1.0, 1.0, 1, 60.0); /* Set culling mode - not that we have anything to cull */ glEnable(GL_CULL_FACE); glFrontFace(GL_CCW); glMatrixMode(GL_MODELVIEW); /* Flush keyboard buffer */ while (keypressed()) readkey(); /* Main rendering loop */ do { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity(); /* Draw all quads */ for (i = 0; i < 6; i++) { glLoadIdentity(); glTranslatef(-10.0 + 4 * (i & 1), -4.0 * (i / 2 - 1), -10.0); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBindTexture(GL_TEXTURE_2D, tex[i]); glBegin(GL_QUADS); glTexCoord2f(0, 0); glVertex2f(0, 0); glTexCoord2f(1, 0); glVertex2f(4, 0); glTexCoord2f(1, 1); glVertex2f(4, 4); glTexCoord2f(0, 1); glVertex2f(0, 4); glEnd(); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); allegro_gl_printf(f, 0, 3.9, 0.1, makecol(255, 255, 255), "%i bpp", (i/2+2) * 8); glBlendFunc(GL_ONE, GL_ZERO); } /* Draw some lines and triangles using Allegro */ allegro_gl_set_allegro_mode(); /* Vertices of triangles should be entered carefully : OpenGL culls * back faces... * Therefore, according to glFrontFace(GL_CCW), vertices are given * in counterclockwise order. */ triangle(screen, 470 + (int)(sin(-chrono / 100.0) * 150), 250 - (int)(cos(-chrono / 100.0) * 150), 470 + (int)(sin(-chrono / 100.0 + M_PI * 4 / 3) * 150), 250 - (int)(cos(-chrono / 100.0 + M_PI * 4 / 3) * 150), 470 + (int)(sin(-chrono / 100.0 + M_PI * 2 / 3) * 150), 250 - (int)(cos(-chrono / 100.0 + M_PI * 2 / 3) * 150), makecol(0, 0, 255)); triangle(screen, 470 + (int)(sin(chrono / 100.0) * 150), 250 - (int)(cos(chrono / 100.0) * 150), 470 + (int)(sin(chrono / 100.0 + M_PI * 4 / 3) * 150), 250 - (int)(cos(chrono / 100.0 + M_PI * 4 / 3) * 150), 470 + (int)(sin(chrono / 100.0 + M_PI * 2 / 3) * 150), 250 - (int)(cos(chrono / 100.0 + M_PI * 2 / 3) * 150), makecol(0, 255, 0)); for (i = 0; i < 6; i++) { hline(screen, 320, 100 + (chrono % 50) + 50 * i, 620, makecol(255, 0, 0)); } for (i = 0; i < 6; i++) { vline(screen, 320 + (chrono % 50) + 50 * i, 100, 400, makecol(255, 0, 0)); } for (i = 0; i < 6; i++) { line(screen, 620 - (chrono % 50) - 50 * i, 400, 620, 400 - (chrono % 50) - 50 * i, makecol(255, 0, 0)); line(screen, 320, 400 - (chrono % 50) - 50 * i, 620 - (chrono % 50) - 50 * i, 100, makecol(255, 0, 0)); } rect(screen, 320, 100, 620, 400, makecol(255, 255, 0)); /* draw mouse */ triangle(screen, mouse_x + 20 + (int)(sin(chrono / 100.0) * 15), mouse_y - (int)(cos(chrono / 100.0) * 15) + 7, mouse_x + 20 + (int)(sin(chrono / 100.0 + M_PI * 4 / 3) * 15), mouse_y - (int)(cos(chrono / 100.0 + M_PI * 4 / 3) * 15) + 7, mouse_x + 20 + (int)(sin(chrono / 100.0 + M_PI * 2 / 3) * 15), mouse_y - (int)(cos(chrono / 100.0 + M_PI * 2 / 3) * 15) + 7, makecol(255, 255, 0)); triangle(screen, mouse_x, mouse_y, mouse_x + 25, mouse_y + 15, mouse_x + 35, mouse_y, makecol(255, 0, 0)); allegro_gl_unset_allegro_mode(); /* Compute and display the framerate */ frame_count++; if (frame_count >= 20) { if (chrono > frame_count_time) { fps_rate = frame_count * 200.0 / (chrono - frame_count_time); } else { fps_rate = 200; } frame_count -= 20; frame_count_time = chrono; } glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); allegro_gl_printf(f, 0, 0, 0, makecol(255, 255, 255), "FPS: %.2f", fps_rate); glBlendFunc(GL_ONE, GL_ZERO); /* Resets the current color to its initial value * That must be done in order to reset alpha to 255 */ glColor4ub(255, 255, 255, 255); allegro_gl_flip(); rest(2); } while (!keypressed()); destroy_font(f); return 0; } END_OF_MAIN() allegro4.4-4.4.2/addons/allegrogl/examp/exalpfnt.c000066400000000000000000000054461173507505700217360ustar00rootroot00000000000000/* font test -- based on extext */ /* Specifically, this tests alpha fonts blending into backgrounds compared * to solid text with transparent background. */ #include #include #include #include "allegro.h" #include "alleggl.h" int main() { FONT *demofont; DATAFILE *dat; allegro_init(); install_allegro_gl(); allegro_gl_clear_settings(); allegro_gl_set(AGL_COLOR_DEPTH, 32); allegro_gl_set(AGL_WINDOWED, TRUE); allegro_gl_set(AGL_DOUBLEBUFFER, 1); allegro_gl_set(AGL_SUGGEST, AGL_DOUBLEBUFFER | AGL_COLOR_DEPTH | AGL_WINDOWED); if (set_gfx_mode(GFX_OPENGL, 640, 480, 0, 0)) { allegro_message("Error initializing OpenGL!\n"); return -1; } install_keyboard(); install_timer(); /* Load font palette first, then font itself */ dat = load_datafile_object ("demofont.dat", "PAL"); if (!dat) { set_gfx_mode(GFX_TEXT, 0, 0, 0, 0); allegro_message("Error loading demofont.dat#PAL\n"); return -1; } set_palette ((RGB *)dat->dat); unload_datafile_object (dat); dat = load_datafile_object ("demofont.dat", "FONT"); if (!dat) { set_gfx_mode(GFX_TEXT, 0, 0, 0, 0); allegro_message("Error loading demofont.dat#FONT\n"); return -1; } demofont = allegro_gl_convert_allegro_font_ex((FONT*)dat->dat, AGL_FONT_TYPE_TEXTURED, 16.0, GL_ALPHA8); unload_datafile_object(dat); if (!demofont) { set_gfx_mode(GFX_TEXT, 0, 0, 0, 0); allegro_message("Unable to convert font!\n"); return -1; } /* Setup OpenGL the way we want */ glEnable(GL_TEXTURE_2D); glViewport(0, 0, SCREEN_W, SCREEN_H); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0, 1, 0, 1, -1, 1); glMatrixMode(GL_MODELVIEW); do { int x, y; glLoadIdentity(); /* Draw the background */ for (y = 0; y < 4; y++) { for (x = 0; x < 4; x++) { glColor3f ((y&1), (x&1), ((y&2)^(x&2))/2); glBegin (GL_QUADS); glVertex2f (x*0.25, y*0.25); glVertex2f (x*0.25, (y+1)*0.25); glVertex2f ((x+1)*0.25, (y+1)*0.25); glVertex2f ((x+1)*0.25, y*0.25); glEnd(); } } /* Draw the text on top */ glScalef (0.1, 0.1, 0.1); /* First, draw the text alpha blended */ glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); allegro_gl_printf(demofont, 1, 8, 0, makeacol(255,255,255,255), "Hello World!"); glBlendFunc(GL_ONE, GL_ZERO); glDisable(GL_BLEND); /* Now just draw it solid with transparent background */ glEnable(GL_ALPHA_TEST); glAlphaFunc(GL_GREATER, 0.5f); allegro_gl_printf(demofont, 1, 5, 0, makeacol(255,255,255,255), "Hello World!"); glDisable(GL_ALPHA_TEST); allegro_gl_flip(); rest(2); } while (!keypressed()); /* Clean up and exit */ allegro_gl_destroy_font(demofont); TRACE("Font Destroyed"); return 0; } END_OF_MAIN() allegro4.4-4.4.2/addons/allegrogl/examp/exblend.c000066400000000000000000000153301173507505700215270ustar00rootroot00000000000000#include #include #define MAX_IMAGES 256 /* structure to hold the current position and velocity of an image */ typedef struct IMAGE { float x, y; float dx, dy; } IMAGE; int blender = 0; char *blender_name = "alpha"; /* initialises an image structure to a random position and velocity */ void init_image(IMAGE *image) { image->x = (float)(AL_RAND() % 704); image->y = (float)(AL_RAND() % 568); image->dx = (float)((AL_RAND() % 255) - 127) / 32.0; image->dy = (float)((AL_RAND() % 255) - 127) / 32.0; } volatile int chrono = 0; void the_timer(void) { chrono++; } END_OF_FUNCTION(the_timer); /* called once per frame to bounce an image around the screen */ void update_image(IMAGE *image) { image->x += image->dx; image->y += image->dy; if (((image->x < 0) && (image->dx < 0)) || ((image->x > SCREEN_W-300) && (image->dx > 0))) image->dx *= -1; if (((image->y < 0) && (image->dy < 0)) || ((image->y > SCREEN_H-200) && (image->dy > 0))) image->dy *= -1; } int main(int argc, char *argv[]) { BITMAP *tmp, *image; BITMAP *vimage; PALETTE pal; FONT *agl_font; IMAGE images[MAX_IMAGES]; int num_images = 4; int done = FALSE; int i, x, y; int frame_count = 0, frame_count_time = 0; float fps_rate = 0.0; if (allegro_init() != 0) return 1; if (install_allegro_gl() != 0) return 1; install_keyboard(); install_timer(); LOCK_FUNCTION(the_timer); LOCK_VARIABLE(chrono); install_int(the_timer, 5); allegro_gl_set(AGL_DOUBLEBUFFER, 1); allegro_gl_set(AGL_WINDOWED, TRUE); allegro_gl_set(AGL_COLOR_DEPTH, 32); allegro_gl_set(AGL_SUGGEST, AGL_DOUBLEBUFFER | AGL_WINDOWED | AGL_COLOR_DEPTH); if(set_gfx_mode(GFX_OPENGL, 800, 600, 0, 0)) { allegro_message ("Error setting OpenGL graphics mode:\n%s\n" "Allegro GL error : %s\n", allegro_error, allegro_gl_error); exit(0); } /* Convert Allegro font */ agl_font = allegro_gl_convert_allegro_font_ex(font, AGL_FONT_TYPE_TEXTURED, -1.0, GL_INTENSITY8); /* read in the source graphic */ set_color_conversion(COLORCONV_NONE); tmp = load_bitmap("mysha.pcx", pal); set_palette(pal); image = create_bitmap_ex(32, tmp->w, tmp->h); blit(tmp, image, 0, 0, 0, 0, tmp->w, tmp->h); /* Generate alpha channel from greyscale of the image. */ for (y = 0; y < image->h; ++y) { for (x = 0; x < image->w; ++x){ int col = _getpixel32(image, x, y); int a = getr32(col) + getg32(col) + getb32(col); a = MID(0, a/2-128, 255); _putpixel32(image, x, y, makeacol32(getr32(col), getg32(col), getb32(col), a)); } } /* initialise the images to random positions */ for (i=0; iw, image->h); blit(image, vimage, 0, 0, 0, 0, image->w, image->h); set_alpha_blender(); allegro_gl_set_projection(); glMatrixMode(GL_MODELVIEW); while (!done) { glClear(GL_COLOR_BUFFER_BIT); glLoadIdentity(); /* Draw background pattern. */ for (y = 0; y < SCREEN_H; y += 50) { for (x = 0; x < SCREEN_W; x += 50) { int sx = (x / 50) & 1; int sy = (y / 50) & 1; float c = sx ^ sy; glColor3f(c, c, c); glBegin(GL_QUADS); glVertex2d(x, y); glVertex2d(x + 50, y); glVertex2d(x + 50, y + 50); glVertex2d(x, y + 50); glEnd(); } } /* draw onto screen */ for (i=0; i>8) { case KEY_UP: case KEY_RIGHT: if (num_images < MAX_IMAGES) num_images++; break; case KEY_DOWN: case KEY_LEFT: if (num_images > 0) num_images--; break; case KEY_SPACE: if (blender < 6) blender++; else blender = 0; switch (blender) { case 0: set_alpha_blender(); blender_name = "alpha"; break; case 1: set_trans_blender(128, 128, 128, 128); blender_name = "trans"; break; case 2: set_add_blender(128, 128, 128, 128); blender_name = "add"; break; case 3: set_burn_blender(128, 128, 128, 128); blender_name = "burn"; break; case 4: set_dodge_blender(128, 128, 128, 128); blender_name = "dodge"; break; case 5: set_invert_blender(128, 128, 128, 128); blender_name = "invert"; break; case 6: set_multiply_blender(128, 128, 128, 128); blender_name = "multiply"; break; } break; case KEY_ESC: done = TRUE; break; } } /* bounce the images around the screen */ for (i=0; i= 20) { if (chrono > frame_count_time) fps_rate = frame_count * 200.0 / (chrono - frame_count_time); else fps_rate = frame_count * 200.0; frame_count_time = chrono; frame_count = 0; } glBegin(GL_QUADS); glColor3ub(0, 0, 0); glVertex2f(0, 0); glVertex2f(0, 50); glVertex2f(300, 50); glVertex2f(300, 0); glEnd(); glEnable(GL_TEXTURE_2D); allegro_gl_printf(agl_font, 0, 0, 0, makecol(255, 255, 255), "FPS: %.2f", fps_rate); allegro_gl_printf(agl_font, 0, 10, 0, makecol(255, 255, 255), "image count: %i (arrow keys to change)", num_images); allegro_gl_printf(agl_font, 0, 20, 0, makecol(255, 255, 255), "using %s blender (space key to change)", blender_name); glDisable(GL_TEXTURE_2D); allegro_gl_flip(); } destroy_bitmap(tmp); destroy_bitmap(image); destroy_bitmap(vimage); destroy_font(agl_font); return 0; } END_OF_MAIN() allegro4.4-4.4.2/addons/allegrogl/examp/excamera.c000066400000000000000000000260221173507505700216730ustar00rootroot00000000000000/* * Example program for the Allegro library, by Shawn Hargreaves * converted to OpenGL/AllegroGL. * * This program demonstrates how to easily manipulate a camera * in OpenGL to view a 3d world from any position and angle. * Quaternions are used, because they're so easy to work with! */ #include #include #include #include #ifdef ALLEGRO_MACOSX #include #else #include #endif /* Define M_PI in case the compiler doesn't */ #ifndef M_PI #define M_PI 3.1415926535897932384626433832795 #endif /* Define a 3D vector type */ typedef struct VECTOR { float x, y, z; } VECTOR; /* display a nice 12x12 chessboard grid */ #define GRID_SIZE 12 /* Parameters controlling the camera and projection state */ int viewport_w = 320; /* Viewport Width (pixels) */ int viewport_h = 240; /* Viewport Height (pixels) */ int fov = 48; /* Field of view (degrees) */ float aspect = 1; /* Aspect ratio */ /* Define the camera * We need: One position vector, and one orientation QUAT */ struct CAMERA { VECTOR position; QUAT orientation; } camera; /* A simple font to display some info on screen */ FONT *agl_font; /* Sets up the viewport to designated values */ void set_viewport() { glViewport((SCREEN_W - viewport_w) / 2, (SCREEN_H - viewport_h) / 2, viewport_w, viewport_h); } /* Sets up the camera for displaying the world */ void set_camera() { float theta; /* First, we set up the projection matrix. * Note that SCREEN_W / SCREEN_H = 1.333333, so we need to multiply the * aspect ratio by that value so that the display doesn't get distorted. */ glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective((float)fov, aspect * 1.333333, 1.0, 120.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); /* Macro to convert radians to degrees */ #define RAD_2_DEG(x) ((x) * 180 / M_PI) /* Convert the QUAT to something OpenGL can understand * We can use allegro_gl_apply_quat() here, but I'd just like * to show how it can be done with regular GL code. * * Since we're working with the camera, we have to rotate first, * and then translate. Objects are done the other way around. */ theta = RAD_2_DEG(2 * acos(camera.orientation.w)); if (camera.orientation.w < 1.0f && camera.orientation.w > -1.0f) { glRotatef(theta, camera.orientation.x, camera.orientation.y, camera.orientation.z); } glTranslatef(-camera.position.x, -camera.position.y, -camera.position.z); #undef RAD_2_DEG } /* Draw the (simple) world * Notice how the camera doesn't affect the positioning. */ void draw_field() { int i, j; for (j = 0; j < GRID_SIZE; j++) { for (i = 0; i < GRID_SIZE; i++) { glPushMatrix(); glTranslatef(i * 2 - GRID_SIZE + 1, -2, j * 2 - GRID_SIZE + 1); if ((i + j) & 1) { glColor3ub(255, 255, 0); } else { glColor3ub(0, 255, 0); } glBegin(GL_QUADS); glVertex3f(-1, 0, -1); glVertex3f(-1, 0, 1); glVertex3f( 1, 0, 1); glVertex3f( 1, 0, -1); glEnd(); glPopMatrix(); } } } /* For display, we'd like to convert the QUAT back to heading, pitch and roll * These don't serve any purpose but to make it look human readable. * Note: Produces incorrect results. */ void convert_quat(QUAT *q, float *heading, float *pitch, float *roll) { MATRIX_f matrix; quat_to_matrix(q, &matrix); *heading = atan2(matrix.v[0][2], matrix.v[0][0]); *pitch = asin(matrix.v[0][1]); *roll = atan2(matrix.v[2][1], matrix.v[2][0]); } /* Draws the overlay over the field. The position of the overlay is * independent of the camera. */ void draw_overlay() { float heading, pitch, roll; int color; VECTOR v; /* Set up the viewport so that it takes up the whole screen */ glViewport(0, 0, SCREEN_W, SCREEN_H); /* Draw a line around the viewport */ allegro_gl_set_projection(); glColor3ub(255, 0, 0); glDisable(GL_DEPTH_TEST); glBegin(GL_LINE_LOOP); glVertex2i((SCREEN_W - viewport_w) / 2, (SCREEN_H - viewport_h) / 2); glVertex2i((SCREEN_W + viewport_w) / 2 - 1, (SCREEN_H - viewport_h) / 2); glVertex2i((SCREEN_W + viewport_w) / 2 - 1, (SCREEN_H + viewport_h) / 2 - 1); glVertex2i((SCREEN_W - viewport_w) / 2, (SCREEN_H + viewport_h) / 2 - 1); glEnd(); /* Overlay some text describing the current situation */ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); color = 0; glTranslatef(-0.375, -0.375, 0); allegro_gl_printf(agl_font, 0, 0, 0, color, "Viewport width: %03d pix (w/W changes)", viewport_w); allegro_gl_printf(agl_font, 0, 8, 0, color, "Viewport height: %03d pix (h/H changes)", viewport_h); allegro_gl_printf(agl_font, 0, 16, 0, color, "Field Of View: %02d deg (f/F changes)", fov); allegro_gl_printf(agl_font, 0, 24, 0, color, "Aspect Ratio: %.2f (a/A changes)", aspect); allegro_gl_printf(agl_font, 0, 32, 0, color, "X position: %+.2f (x/X changes)", camera.position.x); allegro_gl_printf(agl_font, 0, 40, 0, color, "Y position: %+.2f (y/Y changes)", camera.position.y); allegro_gl_printf(agl_font, 0, 48, 0, color, "Z position: %+.2f (z/Z changes)", camera.position.z); /* Convert the orientation QUAT into heading, pitch and roll to display */ convert_quat(&camera.orientation, &heading, &pitch, &roll); allegro_gl_printf(agl_font, 0, 56, 0, color, "Heading: %+.2f deg (left/right changes)", heading * 180 / M_PI); allegro_gl_printf(agl_font, 0, 64, 0, color, "Pitch: %+.2f deg (pgup/pgdn changes)", pitch * 180 / M_PI); allegro_gl_printf(agl_font, 0, 72, 0, color, "Roll: %+.2f deg (r/R changes)", roll * 180 / M_PI); apply_quat(&camera.orientation, 0, 0, -1, &v.x, &v.y, &v.z); allegro_gl_printf(agl_font, 0, 80, 0, color, "Front Vector: %.2f, %.2f, %.2f", v.x, v.y, v.z); apply_quat(&camera.orientation, 0, 1, 0, &v.x, &v.y, &v.z); allegro_gl_printf(agl_font, 0, 88, 0, color, "Up Vector: %.2f, %.2f, %.2f", v.x, v.y, v.z); allegro_gl_printf(agl_font, 0, 96, 0, color, "QUAT: %f, %f, %f, %f ", camera.orientation.w, camera.orientation.x, camera.orientation.y, camera.orientation.z); allegro_gl_unset_projection(); glBlendFunc(GL_ONE, GL_ZERO); glEnable(GL_DEPTH_TEST); } /* draw everything */ void render() { set_viewport(); glClearColor(1.0f, 1.0f, 1.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); set_camera(); draw_field(); draw_overlay(); glFlush(); allegro_gl_flip(); } /* deal with user input */ void process_input(void) { QUAT q; poll_keyboard(); if (key[KEY_W]) { if (key_shifts & KB_SHIFT_FLAG) { if (viewport_w < SCREEN_W) viewport_w += 8; } else { if (viewport_w > 16) viewport_w -= 8; } } if (key[KEY_H]) { if (key_shifts & KB_SHIFT_FLAG) { if (viewport_h < SCREEN_H) viewport_h += 8; } else { if (viewport_h > 16) viewport_h -= 8; } } if (key[KEY_X]) { if (key_shifts & KB_SHIFT_FLAG) camera.position.x += 0.05; else camera.position.x -= 0.05; } if (key[KEY_Y]) { if (key_shifts & KB_SHIFT_FLAG) camera.position.y += 0.05; else camera.position.y -= 0.05; } if (key[KEY_Z]) { if (key_shifts & KB_SHIFT_FLAG) camera.position.z += 0.05; else camera.position.z -= 0.05; } if (key[KEY_UP]) { VECTOR front; /* Note: We use -1 here because Allegro's coordinate system * is slightly different than OpenGL's. */ apply_quat(&camera.orientation, 0, 0, -1, &front.x, &front.y, &front.z); camera.position.x += front.x / 10; camera.position.y += front.y / 10; camera.position.z += front.z / 10; } if (key[KEY_DOWN]) { VECTOR front; apply_quat(&camera.orientation, 0, 0, -1, &front.x, &front.y, &front.z); camera.position.x -= front.x / 10; camera.position.y -= front.y / 10; camera.position.z -= front.z / 10; } /* When turning right or left, we only want to change the heading. * That is, we only want to rotate around the absolute Y axis */ if (key[KEY_LEFT]) { get_y_rotate_quat(&q, -1); quat_mul(&camera.orientation, &q, &camera.orientation); } if (key[KEY_RIGHT]) { get_y_rotate_quat(&q, 1); quat_mul(&camera.orientation, &q, &camera.orientation); } /* However, when rolling or changing pitch, we do a rotation relative to * the current orientation of the camera. This is why we extract the * 'right' and 'front' vectors of the camera and apply a rotation on * those. */ if (key[KEY_PGUP]) { VECTOR right; apply_quat(&camera.orientation, 1, 0, 0, &right.x, &right.y, &right.z); get_vector_rotation_quat(&q, right.x, right.y, right.z, -1); quat_mul(&camera.orientation, &q, &camera.orientation); } if (key[KEY_PGDN]) { VECTOR right; apply_quat(&camera.orientation, 1, 0, 0, &right.x, &right.y, &right.z); get_vector_rotation_quat(&q, right.x, right.y, right.z, 1); quat_mul(&camera.orientation, &q, &camera.orientation); } if (key[KEY_R]) { VECTOR front; apply_quat(&camera.orientation, 0, 0, 1, &front.x, &front.y, &front.z); if (key_shifts & KB_SHIFT_FLAG) get_vector_rotation_quat(&q, front.x, front.y, front.z, -1); else get_vector_rotation_quat(&q, front.x, front.y, front.z, 1); quat_mul(&camera.orientation, &q, &camera.orientation); } if (key[KEY_F]) { if (key_shifts & KB_SHIFT_FLAG) { if (fov < 96) fov++; } else { if (fov > 16) fov--; } } if (key[KEY_A]) { if (key_shifts & KB_SHIFT_FLAG) { aspect += 0.05; if (aspect > 2) aspect = 2; } else { aspect -= 0.05; if (aspect < .1) aspect = .1; } } } int main(void) { allegro_init(); install_allegro_gl(); install_keyboard(); install_timer(); /* Initialise the camera */ camera.orientation = identity_quat; camera.position.x = 0; camera.position.y = 0; camera.position.z = 4; /* Set up AllegroGL */ allegro_gl_clear_settings(); allegro_gl_set (AGL_COLOR_DEPTH, 16); allegro_gl_set (AGL_Z_DEPTH, 16); allegro_gl_set (AGL_DOUBLEBUFFER, 1); allegro_gl_set (AGL_RENDERMETHOD, 1); allegro_gl_set (AGL_WINDOWED, TRUE); allegro_gl_set (AGL_SUGGEST, AGL_Z_DEPTH | AGL_DOUBLEBUFFER | AGL_RENDERMETHOD | AGL_WINDOWED | AGL_COLOR_DEPTH); if (set_gfx_mode(GFX_OPENGL, 640, 480, 0, 0) != 0) { set_gfx_mode(GFX_TEXT, 0, 0, 0, 0); allegro_message ("Error setting OpenGL graphics mode:\n%s\n" "Allegro GL error : %s\n", allegro_error, allegro_gl_error); return 1; } /* Set up OpenGL */ glEnable(GL_DEPTH_TEST); glCullFace(GL_BACK); glEnable(GL_CULL_FACE); glEnable(GL_TEXTURE_2D); glEnable(GL_BLEND); glShadeModel(GL_SMOOTH); /* Build the font we'll use to display info */ agl_font = allegro_gl_convert_allegro_font_ex(font, AGL_FONT_TYPE_TEXTURED, -1.0, GL_ALPHA8); glBindTexture(GL_TEXTURE_2D, 0); /* Run the example program */ while (!key[KEY_ESC]) { render(); process_input(); rest(2); } allegro_gl_destroy_font(agl_font); return 0; } END_OF_MAIN() allegro4.4-4.4.2/addons/allegrogl/examp/exext.c000066400000000000000000000200661173507505700212450ustar00rootroot00000000000000/* This examples demonstrates how to use the AllegroGL extension mechanism. */ #include #include #include #include "alleggl.h" #ifdef ALLEGRO_MACOSX #include #else #include #endif #ifndef M_PI #define M_PI 3.1415926535897932384626433832795 #endif #define WINDOW_W 640 #define WINDOW_H 480 #define MESH_SIZE 64 GLfloat mesh[MESH_SIZE][MESH_SIZE][3]; GLfloat wave_movement = 0.0f; /* Define our vertex program. * It basically does: * pos = vertex.position; * pos.y = (sin(wave.x + pos.x / 5) + sin(wave.x + pos.z / 4)) * 2.5; * result.position = modelview * projection * pos; */ /* Plain ARBvp doesn't have a SIN opcode, so we provide one, built on a taylor * expansion, with some fugding. * * First, we convert the operand to the [-pi..+pi] period by: * - Dividing by 2pi, adding 1/2 * - Taking the fraction of the result * - Multiplying by 2pi, then subtracting pi. * x' = frac((x / 2pi) + 0.5) * 2pi - pi * * Then, we compute the sine using a 7th order Taylor series centered at 0: * x' = x - x^3/3! + x^5/5! - x^7/7! * * Note that we begin by multiplying x by 0.98 as a fugding factor to * compensate for the fact that our Taylor series is just an approximation. * The error is then reduced to < 0.5% from the ideal sine function. */ #define SIN(d, s, t) \ /* Convert to [-pi..+pi] period */ \ "MAD "d", "s", one_over_pi, 0.5;\n" \ "FRC "d","d";\n" \ "MAD "d","d", two_pi, -pi;\n" \ "MUL "d","d", 0.98;\n" /* Scale input to compensate for prec error */\ /* Compute SIN(d), using a Taylor series */ \ "MUL "t".x, "d", "d";\n" /* x^2 */ \ "MUL "t".y, "t".x, "d";\n" /* x^3 */ \ "MUL "t".z, "t".y, "t".x;\n" /* x^5 */ \ "MUL "t".w, "t".z, "t".x;\n" /* x^7 */ \ "MAD "d", "t".y,-inv_3_fact, "d";\n" /* x - x^3/3! */ \ "MAD "d", "t".z, inv_5_fact, "d";\n" /* x - x^3/3! + x^5/5! */ \ "MAD "d", "t".w,-inv_7_fact, "d";\n" /* x - x^3/3! + x^5/5! - x^7/7!*/ /* This is the actual vertex program. * It computes sin(wave.x + pos.x / 5) and sin(wave.x + pos.z), adds them up, * scales the result by 2.5 and stores that as the vertex's y component. * * Then, it does the modelview-projection transform on the vertex. * * XXX Broken ATI drivers need a \n after each "line" */ const char *program = "!!ARBvp1.0\n" "ATTRIB pos = vertex.position;\n" "ATTRIB wave = vertex.attrib[1];\n" "PARAM modelview[4] = { state.matrix.mvp };\n" "PARAM one_over_pi = 0.1591549;\n" "PARAM pi = 3.1415926;\n" "PARAM two_pi = 6.2831853;\n" "PARAM inv_3_fact = 0.1666666;\n" "PARAM inv_5_fact = 0.00833333333;\n" "PARAM inv_7_fact = 0.00019841269841269;\n" "TEMP temp, temp2;\n" /* temp.y = sin(wave.x + pos.x / 5) */ "MAD temp.y, pos.x, 0.2, wave.x;\n" SIN("temp.y", "temp.y", "temp2") /* temp.y += sin(wave.x + pos.z / 4) */ "MAD temp.x, pos.z, 0.25, wave.x;\n" SIN("temp.x", "temp.x", "temp2") "ADD temp.y, temp.x, temp.y;\n" /* pos.y = temp.y * 2.5 */ "MOV temp2, pos;\n" "MUL temp2.y, temp.y, 2.5;\n" /* Transform the position by the modelview matrix */ "DP4 result.position.w, temp2, modelview[3];\n" "DP4 result.position.x, temp2, modelview[0];\n" "DP4 result.position.y, temp2, modelview[1];\n" "DP4 result.position.z, temp2, modelview[2];\n" "MOV result.color, vertex.color;\n" "END"; /* NVIDIA drivers do a better job; let's use a simpler program if we can. */ const char *program_nv = "!!ARBvp1.0" "OPTION NV_vertex_program2;" "ATTRIB wave = vertex.attrib[1];" "PARAM modelview[4] = { state.matrix.mvp };" "TEMP temp;" "TEMP pos;" "MOV pos, vertex.position;" /* temp.x = sin(wave.x + pos.x / 5) */ /* temp.z = sin(wave.x + pos.z / 4) */ "MAD temp.xz, pos, {0.2, 1.0, 0.25, 1.0}, wave.x;" "SIN temp.x, temp.x;" "SIN temp.z, temp.z;" /* temp.y = temp.x + temp.z */ "ADD temp.y, temp.x, temp.z;" /* pos.y = temp.y * 2.5 */ "MUL pos.y, temp.y, 2.5;" /* Transform the position by the modelview matrix */ "DP4 result.position.w, pos, modelview[3];" "DP4 result.position.x, pos, modelview[0];" "DP4 result.position.y, pos, modelview[1];" "DP4 result.position.z, pos, modelview[2];" "MOV result.color, vertex.color;" "END"; void create_mesh() { int x, z; /* Create our mesh */ for (x = 0; x < MESH_SIZE; x++) { for (z = 0; z < MESH_SIZE; z++) { mesh[x][z][0] = (float) (MESH_SIZE / 2) - x; mesh[x][z][1] = 0.0f; mesh[x][z][2] = (float) (MESH_SIZE / 2) - z; } } } void draw_mesh() { int x, z; glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glColor4f(0.5f, 1.0f, 0.5f, 1.0f); for (x = 0; x < MESH_SIZE - 1; x++) { glBegin(GL_TRIANGLE_STRIP); for (z = 0; z < MESH_SIZE - 1; z++) { glVertexAttrib1fARB(1, wave_movement); glVertex3fv(&mesh[x][z][0]); glVertex3fv(&mesh[x+1][z][0]); wave_movement += 0.00001f; if (wave_movement > 2 * M_PI) { wave_movement = 0.0f; } } glEnd(); } glFlush(); } int main() { GLuint pid; allegro_init(); install_allegro_gl(); install_keyboard(); allegro_gl_clear_settings(); allegro_gl_set(AGL_COLOR_DEPTH, 32); allegro_gl_set(AGL_DOUBLEBUFFER, 1); allegro_gl_set(AGL_Z_DEPTH, 32); allegro_gl_set(AGL_WINDOWED, TRUE); allegro_gl_set(AGL_RENDERMETHOD, 1); allegro_gl_set(AGL_SAMPLES, 4); allegro_gl_set(AGL_SAMPLE_BUFFERS, 1); allegro_gl_set(AGL_SUGGEST, AGL_COLOR_DEPTH | AGL_DOUBLEBUFFER | AGL_RENDERMETHOD | AGL_Z_DEPTH | AGL_WINDOWED | AGL_SAMPLES | AGL_SAMPLE_BUFFERS); if (set_gfx_mode(GFX_OPENGL, WINDOW_W, WINDOW_H, 0, 0)) { allegro_message("Error setting OpenGL graphics mode:\n%s\n" "Allegro GL error : %s\n", allegro_error, allegro_gl_error); return -1; } if (allegro_gl_extensions_GL.ARB_multisample) { glEnable(GL_MULTISAMPLE_ARB); } if (!allegro_gl_extensions_GL.ARB_vertex_program) { allegro_message("This example requires a video card that supports " " the ARB_vertex_program extension.\n"); return -1; } glEnable(GL_DEPTH_TEST); glShadeModel(GL_SMOOTH); glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); glDisable(GL_CULL_FACE); /* Setup projection and modelview matrices */ glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(45.0, WINDOW_W/(float)WINDOW_H, 0.1, 100.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); /* Position the camera to look at our mesh from a distance */ gluLookAt(0.0f, 20.0f, -45.0f, 0.0f, 0.0f, 0.0f, 0, 1, 0); create_mesh(); /* Define the vertex program */ glEnable(GL_VERTEX_PROGRAM_ARB); glGenProgramsARB(1, &pid); glBindProgramARB(GL_VERTEX_PROGRAM_ARB, pid); glGetError(); if (allegro_gl_extensions_GL.NV_vertex_program2_option) { glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, strlen(program_nv), program_nv); } else { glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, strlen(program), program); } /* Check for errors */ if (glGetError()) { const char *pgm = allegro_gl_extensions_GL.NV_vertex_program2_option ? program_nv : program; GLint error_pos; const GLubyte *error_str = glGetString(GL_PROGRAM_ERROR_STRING_ARB); glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &error_pos); allegro_message("Error compiling the vertex program:\n%s\n\nat " "character: %i\n%s\n", error_str, (int)error_pos, pgm + error_pos); TRACE("Error compiling the vertex program:\n%s\n\nat " "character: %i\n%s\n", error_str, (int)error_pos, pgm + error_pos); return -1; } while (!key[KEY_ESC]) { draw_mesh(); allegro_gl_flip(); } glDeleteProgramsARB(1, &pid); return 0; } END_OF_MAIN() allegro4.4-4.4.2/addons/allegrogl/examp/exgui.c000066400000000000000000000174131173507505700212330ustar00rootroot00000000000000/* This is an example of how to use the Allegro GUI routines along with AllegroGL It demonstrates how to proceed to : - Use the OpenGL double buffer along with the GUI - Use the regular Allegro GUI routines "as is" - Create a GUI viewport which draws some GL stuff (see 'glviewport_proc()') */ #include #ifdef ALLEGRO_MACOSX #include #else #include #endif #include #include #define VIEW_ASPECT 1. void display(void); int my_radio_proc(int msg, DIALOG *d, int c); /* information needed to display the mesh */ struct { int polygon_mode; /* rendering mode of polygons */ float theta, phi; /* orientation of object */ GLuint tex; /* texture */ } display_info; /* No need of a 'd_clear_proc' since algl_do_dialog will clear the screen * and Z buffer for us. However note that things like centre_dialog will * benefit from having a clear proc at the start, and for non-fullscreen * dialogs perhaps you'd want the auto-clear to clear to black, then draw * your small dialog in white with a d_clear_proc. It's up to you. */ DIALOG my_dialog[] = { /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) (dp2) (dp3) */ { d_algl_viewport_proc, 10, 10, 460, 460, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, { my_radio_proc, 500, 10, 120, 20, 0, 0, 0, 0, 1, 0, "Points", NULL, NULL }, { my_radio_proc, 500, 40, 120, 20, 0, 0, 0, 0, 1, 0, "Lines", NULL, NULL }, { my_radio_proc, 500, 70, 120, 20, 0, 0, 0, D_SELECTED, 1, 0, "Polygons", NULL, NULL }, { d_button_proc, 500, 450, 120, 20, 0, 0, 0, D_EXIT, 0, 0, "Exit", NULL, NULL }, { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } }; /* This callback function demonstrates how to use the d_algl_viewport_proc * object. */ int glviewport_callback(BITMAP* viewport, int msg, int c) { static int focus = TRUE; static float prevx = 0, prevy = 0; /* position of mouse */ static float zoom = 30; /* field of view in degrees */ int ret = 0; /* Determine if the mouse is on the object */ if (msg == MSG_GOTMOUSE) { focus = TRUE; } if (msg == MSG_LOSTMOUSE) { focus = FALSE; } if (msg == MSG_IDLE) { rest(2); ret = D_O_K; } if (msg == MSG_DRAW) { glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(zoom, VIEW_ASPECT, 1,100); glMatrixMode(GL_MODELVIEW); glTranslatef(0,0,-30); /* Apply the rotations */ glRotatef(display_info.phi, 1., 0., 0.); glRotatef(display_info.theta, 0., 1., 0.); /* Display the 3D object */ glPolygonMode(GL_FRONT_AND_BACK, display_info.polygon_mode); display(); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); /* Display of 2D objects is also possible */ allegro_gl_set_allegro_mode(); rect(viewport, 5, 5, viewport->w - 5, viewport->h - 5, focus ? makecol(255,0,0) : makecol(255, 255, 255)); textprintf_ex(viewport, font, 10, 445, makecol(255, 255, 255), -1, "Click & drag"); allegro_gl_unset_allegro_mode(); ret = D_O_K; } /* drag in progress, simulate trackball */ if ((mouse_b & 1) && focus) { float x,y; x = mouse_x; y = mouse_y; display_info.theta += x - prevx; display_info.phi += y - prevy; ret = D_O_K; } /* zooming drag */ if ((mouse_b & 2) && focus) { zoom += ((mouse_y - prevy) / viewport->h) * 40; if (zoom < 5) zoom = 5; if (zoom > 120) zoom = 120; ret = D_O_K; } prevx = mouse_x; prevy = mouse_y; return ret; } /* This function is an ordinary GUI proc (no GL calls) It manages the 3 radio buttons and determine which rendering type has been selected */ int my_radio_proc(int msg, DIALOG *d, int c) { int ret, i; ret = d_radio_proc(msg, d, c); /* Determine which one is selected... */ for (i = 1; i < 3; i++) { if (my_dialog[i].flags & D_SELECTED) { break; } } /* ...and change the mode accordingly */ switch(i) { case 1: display_info.polygon_mode = GL_POINT; break; case 2: display_info.polygon_mode = GL_LINE; break; case 3: default: display_info.polygon_mode = GL_FILL; } return ret; } /* Displays the 3D object */ void display (void) { /* Translate and rotate the object */ glTranslatef(-2.5, 0.0, 0.0); glRotatef(-30, 1.0, 0.0, 0.0); glRotatef(30, 0.0, 1.0, 0.0); glRotatef(30, 0.0, 0.0, 1.0); glColor3f(1.0, 0.0, 1.0); /* Draw the sides of the three-sided pyramid */ glBindTexture (GL_TEXTURE_2D, display_info.tex); glBegin(GL_TRIANGLE_FAN); glTexCoord2f (0, 0); glVertex3d(0, 4, 0); glTexCoord2f (1, 0); glVertex3d(0, -4, -4); glTexCoord2f (1, 1); glVertex3d(-4, -4, 4); glTexCoord2f (0, 1); glVertex3d(4, -4, 4); glTexCoord2f (1, 0); glVertex3d(0, -4, -4); glEnd(); glColor3f(0.0, 1.0, 1.0); /* Draw the base of the pyramid */ glBegin(GL_TRIANGLES); glTexCoord2f (1, 0); glVertex3d(0, -4, -4); glTexCoord2f (0, 1); glVertex3d(4, -4, 4); glTexCoord2f (1, 1); glVertex3d(-4, -4, 4); glEnd(); glTranslatef(2.5, 0.0, 0.0); glRotatef(45, 1.0, 0.0, 0.0); glRotatef(45, 0.0, 1.0, 0.0); glRotatef(45, 0.0, 0.0, 1.0); glColor3f(0.0, 1.0, 0.0); glBindTexture (GL_TEXTURE_2D, 0); /* Draw the sides of the cube */ glBegin(GL_QUAD_STRIP); glVertex3d(3, 3, -3); glVertex3d(3, -3, -3); glVertex3d(-3, 3, -3); glVertex3d(-3, -3, -3); glVertex3d(-3, 3, 3); glVertex3d(-3, -3, 3); glVertex3d(3, 3, 3); glVertex3d(3, -3, 3); glVertex3d(3, 3, -3); glVertex3d(3, -3, -3); glEnd(); glColor3f(0.0, 0.0, 1.0); /* Draw the top of the cube */ glBegin(GL_QUADS); glVertex3d(-3, -3, -3); glVertex3d(3, -3, -3); glVertex3d(3, -3, 3); glVertex3d(-3, -3, 3); glEnd(); /* Bottom is texture-mapped */ glBindTexture (GL_TEXTURE_2D, display_info.tex); glBegin (GL_QUADS); glTexCoord2f (0, 0); glVertex3d(-3, 3, -3); glTexCoord2f (1, 0); glVertex3d(-3, 3, 3); glTexCoord2f (1, 1); glVertex3d(3, 3, 3); glTexCoord2f (0, 1); glVertex3d(3, 3, -3); glEnd(); glBindTexture(GL_TEXTURE_2D, 0); } /* Load the texture */ void setup_texture (void) { PALETTE pal; BITMAP *bmp, *bmp2; int w = 128, h = 128; bmp = load_bitmap ("mysha.pcx", pal); if (!bmp) { allegro_message ("Error loading `mysha.pcx'"); exit (1); } bmp2 = create_bitmap (w, h); stretch_blit (bmp, bmp2, 0, 0, bmp->w, bmp->h, 0, 0, w, h); destroy_bitmap (bmp); glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); display_info.tex = allegro_gl_make_texture (bmp2); destroy_bitmap (bmp2); } int main (void) { allegro_init(); install_allegro_gl(); allegro_gl_clear_settings(); allegro_gl_set (AGL_Z_DEPTH, 16); allegro_gl_set (AGL_COLOR_DEPTH, 16); allegro_gl_set (AGL_DOUBLEBUFFER, 1); allegro_gl_set (AGL_WINDOWED, TRUE); allegro_gl_set (AGL_SUGGEST, AGL_COLOR_DEPTH | AGL_Z_DEPTH | AGL_DOUBLEBUFFER | AGL_WINDOWED); if (set_gfx_mode(GFX_OPENGL, 640, 480, 0, 0) < 0) { allegro_message ("Error setting OpenGL graphics mode:\n%s\n" "Allegro GL error : %s\n", allegro_error, allegro_gl_error); return -1; } install_keyboard(); install_mouse(); /* Set up OpenGL */ /* remove back faces */ glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); /* speedups */ glShadeModel(GL_FLAT); glPointSize(2.); glEnable(GL_TEXTURE_2D); setup_texture(); /* Set colours of dialog components */ set_dialog_color (my_dialog, makecol(0, 0, 0), makecol(255, 255, 255)); /* Set up the callback function for d_algl_viewport_proc */ my_dialog[0].dp = glviewport_callback; my_dialog[0].bg = makecol(77, 102, 153); /* Set colour for automatic dialog clearing */ glClearColor(1.,1.,1.,1.); /* Same as Allegro's do_dialog, but works with OpenGL -- the only * caveat is that the whole screen is cleared and the dialog redrawn * once per update (i.e. pretty much all the time). */ algl_do_dialog (my_dialog, -1); return 0; } END_OF_MAIN() allegro4.4-4.4.2/addons/allegrogl/examp/exmasked.c000066400000000000000000000070561173507505700217150ustar00rootroot00000000000000/* Example of AllegroGL's masked texture routines */ #include "allegro.h" #include "alleggl.h" #include "running.h" volatile int chrono = 0; void the_timer(void) { chrono++; } END_OF_FUNCTION(the_timer); int render_time; int main() { BITMAP *texture; DATAFILE *dat; GLuint tex[11]; int i = 0, j; allegro_init(); install_allegro_gl(); install_keyboard(); install_mouse(); allegro_gl_clear_settings(); allegro_gl_set(AGL_COLOR_DEPTH, 32); allegro_gl_set(AGL_DOUBLEBUFFER, 1); allegro_gl_set(AGL_Z_DEPTH, 24); allegro_gl_set(AGL_WINDOWED, TRUE); allegro_gl_set(AGL_RENDERMETHOD, 1); allegro_gl_set(AGL_SUGGEST, AGL_COLOR_DEPTH | AGL_DOUBLEBUFFER | AGL_RENDERMETHOD | AGL_Z_DEPTH | AGL_WINDOWED); if (set_gfx_mode(GFX_OPENGL, 640, 480, 0, 0)) { allegro_message ("Error setting OpenGL graphics mode:\n%s\n" "Allegro GL error : %s\n", allegro_error, allegro_gl_error); return -1; } install_timer(); LOCK_FUNCTION(the_timer); LOCK_VARIABLE(chrono); install_int(the_timer, 10); dat = load_datafile("running.dat"); if (!dat) { set_gfx_mode(GFX_TEXT, 0, 0, 0, 0); allegro_message("Unable to load running.dat!\n"); return -2; } allegro_gl_use_mipmapping(TRUE); /* Convert running ball thingie */ for (j = 0; j < 10; j++) { BITMAP *bmp = dat[FRAME_00_BMP + j].dat; tex[j] = allegro_gl_make_masked_texture(bmp); } /* Convert Mysha */ texture = load_bitmap("mysha.pcx", NULL); if (!texture) { unload_datafile(dat); set_gfx_mode(GFX_TEXT, 0, 0, 0, 0); allegro_message("Unable to load mysha.pcx - did you copy Allegro's " "here?\n"); return -3; } tex[10] = allegro_gl_make_texture(texture); /* Now display everything */ /* Setup OpenGL like we want */ glEnable(GL_TEXTURE_2D); /* Skip pixels which alpha channel is lower than 0.5*/ glAlphaFunc(GL_GREATER, 0.5); glShadeModel(GL_FLAT); glPolygonMode(GL_FRONT, GL_FILL); glViewport(0, 0, SCREEN_W, SCREEN_H); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glFrustum(-1.0, 1.0, -1.0, 1.0, 1, 60.0); /* Set culling mode - not that we have anything to cull */ glEnable(GL_CULL_FACE); glFrontFace(GL_CCW); glMatrixMode(GL_MODELVIEW); while (keypressed()) readkey(); render_time = chrono; do { int screen_w = SCREEN_W; int screen_h = SCREEN_H; glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity(); glTranslatef(-10.0, -10.0, -10.0); /* Draw BG */ glBindTexture(GL_TEXTURE_2D, tex[10]); glBegin(GL_QUADS); glTexCoord2f(0, 0); glVertex2f(0, 0); glTexCoord2f(1, 0); glVertex2f(20, 0); glTexCoord2f(1, 1); glVertex2f(20, 20); glTexCoord2f(0, 1); glVertex2f(0, 20); glEnd(); i = (chrono / 10) % 10; /* Draw running ball thingie */ /* Enable removing of thingie's transparent pixels */ glEnable(GL_ALPHA_TEST); glLoadIdentity(); if (screen_w != 0 && screen_h != 0) { glTranslatef(mouse_x * 20.0 / screen_w - 10.0, mouse_y * -20.0 / screen_h + 10.0, -9.99); } glRotatef(chrono, 0, 0, 1.0); glBindTexture(GL_TEXTURE_2D, tex[i]); glBegin(GL_QUADS); glTexCoord2f(0, 0); glVertex2f(-1.0, -1.0); glTexCoord2f(1, 0); glVertex2f(1.0, -1.0); glTexCoord2f(1, 1); glVertex2f(1.0, 1.0); glTexCoord2f(0, 1); glVertex2f(-1.0, 1.0); glEnd(); glDisable(GL_ALPHA_TEST); /* Disable removing of transparent pixels */ allegro_gl_flip(); render_time++; while (!keypressed() && render_time > chrono) { rest(2); } } while (!keypressed()); return 0; } END_OF_MAIN() allegro4.4-4.4.2/addons/allegrogl/examp/exmipmaps.c000066400000000000000000000125571173507505700221210ustar00rootroot00000000000000/* exmipmaps.c * * This example shows how to build and use a mipmap stack in AllegroGL * for trilinear filtering. If your GPU also supports setting the maximum * degree of anisotropy for filtering, then that is also used. */ #include "allegro.h" #include "alleggl.h" /* Define a struct to hold our texture information */ typedef struct { BITMAP *bitmap; GLuint id; } texture_t; static void run(texture_t *texture, FONT *agl_font); int main() { int flags; texture_t texture; FONT *agl_font; allegro_init(); install_allegro_gl(); install_keyboard(); install_timer(); allegro_gl_clear_settings(); allegro_gl_set(AGL_COLOR_DEPTH, 32); allegro_gl_set(AGL_DOUBLEBUFFER, 1); allegro_gl_set(AGL_Z_DEPTH, 24); allegro_gl_set(AGL_WINDOWED, TRUE); allegro_gl_set(AGL_RENDERMETHOD, 1); allegro_gl_set(AGL_SUGGEST, AGL_COLOR_DEPTH | AGL_DOUBLEBUFFER | AGL_RENDERMETHOD | AGL_Z_DEPTH | AGL_WINDOWED); if (set_gfx_mode(GFX_OPENGL, 800, 600, 0, 0)) { allegro_message("Error setting OpenGL graphics mode:\n%s\n" "Allegro GL error : %s\n", allegro_error, allegro_gl_error); return -1; } /* Create a checkered bitmap */ { int i, j; int col[2]; col[0] = makecol(0, 0, 0); col[1] = makecol(255, 255, 255); #define TW 64 #define TH 64 texture.bitmap = create_bitmap(TW, TH); #define PW 8 #define PH 8 for (j = 0; j < PH; j++) { for (i = 0; i < PW; i++) { rectfill(texture.bitmap, i * TW / PW, j * TH / PH, (i + 1) * TW / PW, (j + 1) * TH / PH, col[(i ^ j) & 1]); } } #undef TW #undef TH #undef PW #undef PH } /* Create a texture from the bitmap and generate mipmaps */ flags = AGL_TEXTURE_MIPMAP | AGL_TEXTURE_RESCALE; texture.id = allegro_gl_make_texture_ex(flags, texture.bitmap, GL_RGBA8); /* Get an AGL font by converting Allegro's */ agl_font = allegro_gl_convert_allegro_font_ex(font, AGL_FONT_TYPE_TEXTURED, -1.0, GL_INTENSITY8); run(&texture, agl_font); return 0; } END_OF_MAIN() static volatile int the_time = 0; #define TIME_SCALE 500 void the_timer(void) { the_time++; if (the_time > TIME_SCALE) { the_time -= TIME_SCALE; } } END_OF_FUNCTION(the_timer); void run(texture_t *texture, FONT *agl_font) { static const char *text[] = { "Trilinear w/ Aniso", "Trilinear", "Bilinear w/ Aniso", "Bilinear"}; static const GLenum min_filter[] = { GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR }; static const GLfloat max_aniso[] = { 16, 1 }; int i, j; int has_aniso = allegro_gl_extensions_GL.EXT_texture_filter_anisotropic; /* Draw an oblique GL_QUAD in 4 modes: * Bilinear + Aniso | Bilinear * ----------------------------------------- * Trilinear + Aniso | Trilinear */ glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, texture->id); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glEnable(GL_SCISSOR_TEST); glMatrixMode(GL_PROJECTION); glFrustum(-1, 1, -1, 1, 1, 10); glMatrixMode(GL_MODELVIEW); install_int(the_timer, 20); do { float t = the_time / (float)TIME_SCALE; glClear(GL_COLOR_BUFFER_BIT); if (!has_aniso) { static const char *text = "EXT_texture_filter_anisotropic not " "supported!"; int len = text_length(font, text); glViewport(0, 0, SCREEN_W, SCREEN_H); allegro_gl_set_projection(); glTranslatef(-0.375, -0.375, 0); glTranslatef(5, 5, 0); for (j = 0; j < 2; j++) { rectfill(screen, 0, j * SCREEN_H/2, len, j * SCREEN_H/2 + 8, makecol(0,0,0)); allegro_gl_printf(agl_font, 0, j * SCREEN_H/2, 0, makecol(255, 255, 255), "%s", text); } glTranslatef(+0.375, +0.375, 0); allegro_gl_unset_projection(); } for (j = 0; j < 2; j++) { for (i = has_aniso ? 0 : 1; i < 2; i++) { int len = text_length(font, text[i + j * 2]); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter[j]); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, max_aniso[i]); glViewport(i*SCREEN_W/2, j*SCREEN_H/2, SCREEN_W/2, SCREEN_H/2); glBegin(GL_TRIANGLES); glTexCoord2f(t, t); glVertex3f(-1, 1, -1); glTexCoord2f(10+t, t); glVertex3f( 0, 0, -10); glTexCoord2f(t, 1+t); glVertex3f(-1, -1, -1); glTexCoord2f(-t, -t); glVertex3f(-1, 1, -1); glTexCoord2f(10-t, -t); glVertex3f( 0, 0, -10); glTexCoord2f(-t, 1-t); glVertex3f( 1, 1, -1); glTexCoord2f(-t, -t); glVertex3f( 1, 1, -1); glTexCoord2f(10-t, -t); glVertex3f( 0, 0, -10); glTexCoord2f(-t, 1-t); glVertex3f( 1, -1, -1); glTexCoord2f(-t, -t); glVertex3f( 1, -1, -1); glTexCoord2f(10-t, -t); glVertex3f( 0, 0, -10); glTexCoord2f(-t, 1-t); glVertex3f(-1, -1, -1); glEnd(); allegro_gl_set_projection(); glTranslatef(-0.375, -0.375, 0); glTranslatef(5, 5, 0); rectfill(screen, i * SCREEN_W/2, j * SCREEN_H/2, i * SCREEN_W/2 + len, j * SCREEN_H/2 + 8, makecol(0,0,0)); allegro_gl_printf(agl_font, i * SCREEN_W/2, j * SCREEN_H/2, 0, makecol(255, 255, 255), "%s", text[i + j * 2]); glTranslatef(+0.375, +0.375, 0); allegro_gl_unset_projection(); } } allegro_gl_flip(); rest(2); } while (!keypressed()); } allegro4.4-4.4.2/addons/allegrogl/examp/extext.c000066400000000000000000000117651173507505700214370ustar00rootroot00000000000000 #include #include #include #include "allegro.h" #include "alleggl.h" #ifndef M_PI #define M_PI 3.1415 #endif #define NUM_STRINGS 3 #define STRING "Hello World!" #define STRING0 ("AllegroGL v" AGL_VERSION_STR) #define STRING1 "Text Drawing" #define STRING2 "And Font Loading" #define STRING3 "Example Program" #define STRING4 "See Our Webpage At:" #define URL "http://allegrogl.sourceforge.net/" volatile int chrono = 0; volatile double angle = 0.0; void the_timer(void) { chrono++; angle += 1.0 / 400.0; if (angle > M_PI) angle -= 2 * M_PI; } END_OF_FUNCTION(the_timer); int main() { FONT *lucidia_fnt; FONT *allegro_fnt; DATAFILE *dat; struct { float x, y, z; int c; } coord[NUM_STRINGS]; char *string = STRING; int i; allegro_init(); install_allegro_gl(); install_timer(); LOCK_FUNCTION(the_timer); LOCK_VARIABLE(chrono); install_int(the_timer, 2); allegro_gl_clear_settings(); allegro_gl_set(AGL_COLOR_DEPTH, 32); allegro_gl_set(AGL_Z_DEPTH, 24); allegro_gl_set(AGL_WINDOWED, TRUE); allegro_gl_set(AGL_DOUBLEBUFFER, 1); allegro_gl_set(AGL_RENDERMETHOD, 1); allegro_gl_set(AGL_SUGGEST, AGL_COLOR_DEPTH | AGL_DOUBLEBUFFER | AGL_RENDERMETHOD | AGL_Z_DEPTH | AGL_WINDOWED); if (set_gfx_mode(GFX_OPENGL, 640, 480, 0, 0)) { allegro_message("Error initializing OpenGL!\n"); return -1; } install_keyboard(); /* Load 2 copies of the datafile */ dat = load_datafile("lucidia.dat"); if (!dat) { set_gfx_mode(GFX_TEXT, 0, 0, 0, 0); allegro_message("Unable to load lucidia.dat\n"); return -2; } lucidia_fnt = allegro_gl_convert_allegro_font((FONT*)dat[0].dat, AGL_FONT_TYPE_TEXTURED, 16.0); if (!lucidia_fnt) { unload_datafile(dat); set_gfx_mode(GFX_TEXT, 0, 0, 0, 0); allegro_message("Unable to convert font!\n"); return -3; } allegro_fnt = allegro_gl_convert_allegro_font(font, AGL_FONT_TYPE_TEXTURED, 16.0); if (!allegro_fnt) { allegro_gl_destroy_font(lucidia_fnt); unload_datafile(dat); set_gfx_mode(GFX_TEXT, 0, 0, 0, 0); allegro_message("Unable to convert font!\n"); return -4; } srand(time(NULL)); for (i = 0; i < NUM_STRINGS; i++) { coord[i].z = 0; coord[i].c = 0; } i = 0; /* Start nice text demo */ /* Setup OpenGL like we want */ glEnable(GL_TEXTURE_2D); glEnable(GL_BLEND); glViewport(0, 0, SCREEN_W, SCREEN_H); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glFrustum(-1.0, 1.0, -1.0, 1.0, 1, 60.0); /* Set culling mode - not that we have anything to cull */ glEnable(GL_CULL_FACE); glFrontFace(GL_CCW); glMatrixMode(GL_MODELVIEW); do { int c; /* Update rotation angle of text */ glLoadIdentity(); glTranslatef(0, 0, -30); glRotatef(-45, 1, 0, 0); glRotatef(-30, 0, 1, 0); /* Clear the screen and set a nice blender mode */ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_COLOR); /* Print the text wheel */ for (i = 0; i < NUM_STRINGS; i++) { allegro_gl_printf(lucidia_fnt, coord[i].x, coord[i].y, coord[i].z, coord[i].c, string); } /* Update the text wheel's position */ for (i = 0; i < NUM_STRINGS; i++) { int r, g, b; float angle2 = angle + i * M_PI * 2 / NUM_STRINGS; coord[i].x = 10 * cos(angle2) - 10; coord[i].y = 10 * sin(angle2); angle2 = angle2 * 180.0 / M_PI; #if ((((ALLEGRO_VERSION) << 16) | ((ALLEGRO_SUB_VERSION) << 8) | (ALLEGRO_WIP_VERSION)) == 0x40200) /* Work around an Allegro bug that's only in 4.2.0 */ while (angle2 > 360.0f) angle2 -= 360.0f; while (angle2 < 0) angle2 += 360.0f; #endif hsv_to_rgb(angle2, 1, 1, &r, &g, &b); coord[i].c = makeacol(r, g, b, 255); } /* Draw "AllegroGL" */ glLoadIdentity(); c = MID(0, (int)(255 - chrono / 100), 255); allegro_gl_printf(allegro_fnt, -(strlen(STRING0) * 1 / 2.0f) / 2, -3.0f, -chrono / 200.0 + 0, makecol(c, c, c), STRING0); c = MID(0, (int)(255 - chrono / 100) + 24, 255); allegro_gl_printf(allegro_fnt, -(strlen(STRING1) * 1 / 2.0f) / 2, -3.0f, -chrono / 200.0 + 12, makecol(c, c, c), STRING1); c = MID(0, (int)(255 - chrono / 100) + 48, 255); allegro_gl_printf(allegro_fnt, -(strlen(STRING2) * 1 / 2.0f) / 2, -3.0f, -chrono / 200.0 + 24, makecol(c, c, c), STRING2); c = MID(0, (int)(255 - chrono / 100) + 72, 255); allegro_gl_printf(allegro_fnt, -(strlen(STRING3) * 1 / 2.0f) / 2, -3.0f, -chrono / 200.0 + 36, makecol(c, c, c), STRING3); c = MID(0, (int)(255 - chrono / 100) + 96, 255); allegro_gl_printf(allegro_fnt, -(strlen(STRING4) * 1 / 2.0f) / 2, -3.0f, -chrono / 200.0 + 48, makecol(c, c, c), STRING4); c = MID(0, (int)(255 - chrono / 100) + 120, 255); allegro_gl_printf(allegro_fnt, -(strlen(URL) * 1 / 2.0f) / 2, -3.0f, -chrono / 200.0 + 60, makecol(c, c, c), URL); allegro_gl_flip(); rest(2); } while (!key[KEY_ESC]); return 0; } END_OF_MAIN() allegro4.4-4.4.2/addons/allegrogl/examp/extextur.c000066400000000000000000000106121173507505700217740ustar00rootroot00000000000000/* Example of AllegroGL's texture routines */ #include "allegro.h" #include "alleggl.h" int main() { BITMAP *mysha, *texture; GLuint tex[18]; FONT *agl_font; int i, j; allegro_init(); install_allegro_gl(); install_keyboard(); install_timer(); allegro_gl_clear_settings(); allegro_gl_set(AGL_COLOR_DEPTH, 32); allegro_gl_set(AGL_DOUBLEBUFFER, 1); allegro_gl_set(AGL_Z_DEPTH, 24); allegro_gl_set(AGL_WINDOWED, TRUE); allegro_gl_set(AGL_RENDERMETHOD, 1); allegro_gl_set(AGL_SUGGEST, AGL_COLOR_DEPTH | AGL_DOUBLEBUFFER | AGL_RENDERMETHOD | AGL_Z_DEPTH | AGL_WINDOWED); TRACE("Swicthing screen modes...\n"); if (set_gfx_mode(GFX_OPENGL, 800, 600, 0, 0)) { allegro_message("Error setting OpenGL graphics mode:\n%s\n" "Allegro GL error : %s\n", allegro_error, allegro_gl_error); return -1; } TRACE("Loading texture\n"); /* Load mysha.pcx */ for (j = 0; j < 3; j++) { int flag; set_color_depth(8 * (j+2)); mysha = load_bitmap("mysha.pcx", NULL); if (!mysha) { set_gfx_mode(GFX_TEXT, 0, 0, 0, 0); allegro_message("Unable to load mysha.pcx - please copy Allegro's " "in this directory.\n"); return -2; } texture = create_sub_bitmap(mysha, 64, 64, 64, 64); TRACE("Converting textures\n"); /* Convert to texture using different modes */ flag = AGL_TEXTURE_FLIP; tex[j*6 + 0] = allegro_gl_make_texture_ex(flag, texture, -1); tex[j*6 + 1] = allegro_gl_make_texture_ex(flag, texture, GL_RGB8); tex[j*6 + 2] = allegro_gl_make_texture_ex(flag, texture, GL_RGBA8); flag |= AGL_TEXTURE_MIPMAP; tex[j*6 + 3] = allegro_gl_make_texture_ex(flag, texture, -1); tex[j*6 + 4] = allegro_gl_make_texture_ex(flag, texture, GL_RGB8); tex[j*6 + 5] = allegro_gl_make_texture_ex(flag, texture, GL_RGBA8); destroy_bitmap(texture); destroy_bitmap(mysha); } TRACE("Converted all textures\n"); /* Convert Allegro font */ agl_font = allegro_gl_convert_allegro_font_ex(font, AGL_FONT_TYPE_TEXTURED, -1.0, GL_INTENSITY8); TRACE("Converted font\n"); /* Now display everything */ /* Setup OpenGL like we want */ glEnable(GL_TEXTURE_2D); glEnable(GL_BLEND); TRACE("Setup OpenGL\n"); do { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); /* Draw all quads */ for (j = 0; j < 3; j++) { allegro_gl_set_projection(); for (i = 0; i < 6; i++) { float x, y, w, h; glBindTexture(GL_TEXTURE_2D, tex[j * 6 + i]); glBegin(GL_QUADS); x = i * SCREEN_W / 6.0; y = j * SCREEN_H / 6.0; w = SCREEN_W / 6.0; h = w; glTexCoord2f(0, 1); glVertex2f(x, y); glTexCoord2f(1, 1); glVertex2f(x + w - 1, y); glTexCoord2f(1, 0); glVertex2f(x + w - 1, y + h - 1); glTexCoord2f(0, 0); glVertex2f(x, y + h - 1); x = i * SCREEN_W / 6.0; y = j * SCREEN_H / 6.0; w = SCREEN_W / 6.0 / 2; h = w; glTexCoord2f(0, 1); glVertex2f(x, y); glTexCoord2f(1, 1); glVertex2f(x + w - 1, y); glTexCoord2f(1, 0); glVertex2f(x + w - 1, y + h - 1); glTexCoord2f(0, 0); glVertex2f(x, y + h - 1); glEnd(); } glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glTranslatef(-0.375, -0.375, 0); for (i = 0; i < 6; i++) { const char *text = (i % 3 == 0 ? "default" : i % 3 == 1 ? "RGB8" : "RGBA8"); allegro_gl_printf(agl_font, i * SCREEN_W/6, j * SCREEN_H/6, 0, makecol(255, 255, 255), "%ibpp %s", (j+2) * 8, text); allegro_gl_printf(agl_font, i * SCREEN_W/6, j * SCREEN_H/6 + 8, 0, makecol(255, 255, 255), "%s", i < 3 ? "" : "mipmaped"); } allegro_gl_unset_projection(); glBlendFunc(GL_ONE, GL_ZERO); } glViewport(0, 0, SCREEN_W, SCREEN_H); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glFrustum(-1.0, 1.0, -1.0, 1.0, 1, 1000.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); /* Draw a large mysha */ glBindTexture(GL_TEXTURE_2D, tex[0]); glTranslatef(-10.0, -10.0, -10.0); glBegin(GL_QUADS); glTexCoord2f(0, 0); glVertex2f(0, 0); glTexCoord2f(1, 0); glVertex2f(20, 0); glTexCoord2f(1, 1); glVertex2f(20, 8); glTexCoord2f(0, 1); glVertex2f(0, 8); glEnd(); allegro_gl_flip(); rest(2); } while (!keypressed()); return 0; } END_OF_MAIN() allegro4.4-4.4.2/addons/allegrogl/examp/fonttest.c000066400000000000000000000103451173507505700217550ustar00rootroot00000000000000#include #include /* Make it compile with Allegro 4.2.0, which is missing make_trans_font. */ #if ALLEGRO_VERSION == 4 && ALLEGRO_SUB_VERSION == 2 && ALLEGRO_WIP_VERSION == 0 static void make_trans_font(FONT *f) {(void)f;} #endif #define OPENGL_FORMATS 6 #define FONTS_COUNT 4 int main(void) { /* The fonts. */ FONT *allegro_font[OPENGL_FORMATS]; PALETTE pal[FONTS_COUNT]; FONT *allegrogl_font[FONTS_COUNT * OPENGL_FORMATS]; char const *font_file[] = {"a32.tga", "a24.tga", "a8.bmp", "a1.bmp"}; char const *font_name[] = {"32 bit", "24 bit", "8 bit", "1 bit"}; /* OpenGL texture formats to test. */ int opengl_format[] = { GL_RGBA, GL_RGB, GL_ALPHA, GL_LUMINANCE, GL_INTENSITY, GL_LUMINANCE_ALPHA}; char const *opengl_format_name[][2] = { {"RGBA", ""}, {"RGB", ""}, {"ALPHA", ""}, {"LUMINANCE", ""}, {"INTENSITY", ""}, {"LUMINANCE", "_ALPHA"} }; /* Make our window have just the right size. */ int w = 80 + OPENGL_FORMATS * 96; int h = 32 + FONTS_COUNT * 80; int x, y, i; allegro_init(); install_timer(); install_allegro_gl(); allegro_gl_set(AGL_COLOR_DEPTH, 32); allegro_gl_set(AGL_SUGGEST, AGL_COLOR_DEPTH); set_gfx_mode(GFX_OPENGL_WINDOWED, w, h, 0, 0); install_keyboard(); allegro_gl_set_allegro_mode(); /* Load the fonts. */ for (i = 0; i < FONTS_COUNT; i++) { allegro_font[i] = load_font(font_file[i], pal[i], NULL); if (!allegro_font[i]) { set_gfx_mode(GFX_TEXT, 0, 0, 0, 0); allegro_message("Unable to load \"%s\".\n", font_file[i]); return -1; } transpose_font(allegro_font[i], 'a' - ' '); } make_trans_font(allegro_font[0]); set_trans_blender(0, 0, 0, 0); /* Convert the fonts to all the format combination we want to test. */ for (i = 0; i < FONTS_COUNT * OPENGL_FORMATS; i++) { select_palette(pal[i % FONTS_COUNT]); allegrogl_font[i] = allegro_gl_convert_allegro_font_ex( allegro_font[i % FONTS_COUNT], AGL_FONT_TYPE_TEXTURED, 1, opengl_format[i / FONTS_COUNT]); } while (!key[KEY_ESC]) { int s = 16; glClearColor(1, 1, 1, 1); glClear(GL_COLOR_BUFFER_BIT); /* Draw background pattern. */ for (y = 32; y < h; y += s) { for (x = 80; x < w; x += s) { int sx = (x / s) & 1; int sy = (y / s) & 1; float c = sx ^ sy; glColor3f(0.2 + c * 0.6, 0.2 + c * 0.6, c); glBegin(GL_QUADS); glVertex2d(x, y); glVertex2d(x + s, y); glVertex2d(x + s, y + s); glVertex2d(x, y + s); glEnd(); } } glEnable(GL_TEXTURE_2D); glEnable(GL_BLEND); /* Draw left info text. */ for (y = 0; y < FONTS_COUNT; y++) { glBlendFunc(GL_ONE, GL_ZERO); textprintf_ex(screen, font, 4, 32 + y * 80, makecol(0, 0, 0), -1, "%s", font_name[y]); } /* Columns are texture formats, rows are font formats. */ i = 0; for (x = 0; x < OPENGL_FORMATS; x++) { int j; /* Draw top info text. */ glBlendFunc(GL_ONE, GL_ZERO); for (j = 0; j < 2; j++) textprintf_ex(screen, font, 80 + x * 96, 4 + 16 * j, makecol(0, 0, 0), -1, "%s", opengl_format_name[x][j]); /* Draw the example glyph for the current cell. */ for (y = 0; y < FONTS_COUNT; y++) { glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glTranslatef(80 + x * 96, 32 + y * 80, 0); glScalef(1, -1, 1); glColor4f(1, 1, 1, 1); allegro_gl_printf_ex(allegrogl_font[i++], 0, 0, 0, "a"); glPopMatrix(); } } glDisable(GL_TEXTURE_2D); glDisable(GL_BLEND); allegro_gl_flip(); /* Update about 60 times / second. */ rest(1000 / 60); } return 0; } END_OF_MAIN() allegro4.4-4.4.2/addons/allegrogl/examp/lucidia.dat000066400000000000000000000077571173507505700220640ustar00rootroot00000000000000slh!ïALL.ëðpr¿opDATEëðÿ1-01-2001, 6:42öñ÷NAMýñLucïidiaöñORIýGëð g:\LUÿCID.PCXFONT.‰@×ëð ëð~(Üÿj|ŽåöW<³ÅËæõÖ ºæõWÁð€à˜6HZáúmW 88†ppŒ»àà˜ÿþ¡{ÁÀªÀƒ²wÿü¹ÂÊÖÜçôõW û?€ÿÿðÿðìpïÌŒ(Ì¿ìü$ ~ü ÿðÀà ÷ð 7 ø xþ>& ð ðÿàÿÀÿûú_/W ?ÿÀqàpNŠ àp8 —pšþš!qÀpã€-y¦ ?Çÿðëð²!úÛ8ëðpðsþ$ çǿΎÃú×#Ú 8ÿž8üp‡ð$c/áú* þW ÿ€ÇÀWƒ3<Ç/0Ï+0™Þ+0$ øÿðà ÿð<øxý|c0<ð>·ðo0žt0œ¿ðüøU0xÿð|ø?<~0¡þ?T2œ?Ÿ|¿8ˆË4Õ?ç?ù?ôô½!øT1àm€€ >²x+B à 3Bà:OIJ2F,DÜ'@$@!@@U1V0Ô5WÛ$@30H@à ªV0|(B§B­E€v@¹OÅH¯F©CÜ£@ø›A@–@$@ÛE¯VÿpøÃøÃÀêñ;BV ç€*P9QÀü?U_g_rà‹_åöÛ§_­R?ÿþÁS¯_ÓWå_èóVo!oÔR6g¨@Ëx!`ùWoio«=ÿO ayo¥o·oú_Ûoío0or_ Ðc² ÔS¾ ¾ p7rõ H@ÀCq/0v@´"@*sÜ6H+~çôÏiý~(0€ÿÀÃ÷à^0ðx¼s8ÌÈÔvÅp¼vk0¶p³p°p­p{_÷%Aþ-€Þ©C9K]!1¡çôÏh# ûÿŠ`€ÀqpHN¯€¯€ÖCåC0B²Åˆ¯@“Aÿ ò„ôÿO+±pÿàšC,˜²ƒU"C‘—FcF$V™9@ð'!’€,€wŸàš~Ç1 Ÿ’–@?Àÿ;ÀsÀóÀóã¯;RƒÀÿÀÀÀÿÀ<À?ÿü@ГÄݟñŸø •”ÿúp¢wr"­@þ,20 (‘xWL3F9Bàq‘Á4P$ p¯›}–@ðæ!ðpǃÖM€ÿÀÿðÁðÿ€øx|<É¢_0Ñ¢ÿ8€x€ø…á àH‘- ì¯\ÿø¶cwÛ†yqNr¯@² ©@\v-@ep6KéŸv¯¶Ðh€ã ÿÉ€b1™´€¡°àñóýr4P®pßà‡÷ðb0ø|àòʤȠ¢±ÿà¢T l¿y¿«tà³q€Â¸q½uɵǠf0|ÿ€üÁüÿ¼ÿ<üS_˜8Be¯¿odÏÏ‘ÏmπϯÏÙÏ=o÷½*ßçô†¸"|Š0C- Øð/!-#ZÐ&!-!vBŠ0¢AãPDЂßߦ߸ß Ñ–ÂßÔÛößßïáúP¾  oAqÓg×dÕZÖüïE€`&A¾ Pyïü¯ÿ0ÿÀÿððøÃq_™Â‚!C*N€2AâùÒïûï= H‘­á>€p©pµ 8þä øø8£x†ˆ’ pFñ`ª‹àOñxTôø\óáþcñ¸xs¸8 ˆ>?Öwð³$PpÀqpT á¿ÿï ÿãøÜîÁÖõïßó6PÌ ëó*Q¾>þñ²€k0¢°Ì|&@x€¨@)Àÿï´ÿ‡c€NP"ð˜¸ðsR!¥‚Ã^0˜³Ð¦j0f0³àR ðºu*ðÿþÿþðÀ!CâF©CrDtpøðíê5Ìu*Œ-€¢áàóÁ´Ê£ä~„ɵ¾pøðð‚€/€°O~lµ@­HñQ!"òþü$#8ÐGÀÚÿþ^$ÅOn#ÿø$n/•+¨/?/˜Ýïþþ$…ï€å ø,‚ïÄ/ÞѼv\?¼sw3e?s0)ðkàžé@ø|áB :à ÍAÁ±üíϱ?|mD_€V_h_ø¶’_Åר>«|ÂP?ÆQüËP;ï€Ü;ÓQ9Áœû9ÃÜQ8ã8ç^åRv8~îR<ôUÁýZ°_'_I<èp8úB`€FbÀ8à8½Q`ð8øXb|ÿ8<8>8/8j`¸5ðqaøyb«çŠo­O¢ÖÙÿà#‘¶pÁ±xÔs)ÒoÛcÔst1™öp¡A’¤_b蘰,ÀÈ  ©ñpø•´Àþu_'€«ÿ¤¸b¼a] 1ò@Ð)ÝëwÍqÉqÅqÁqÿaH‘@¡uÒrÞñЀÙ¢oÐh—`€‹+€ƒÃà_`„,À>›€D­l ÀÚ°€•°qî$¢5 F‘àƒ?hàwÐMàzÐDày0§­°Á’?Ÿ¸aÿÿT–ÑòbŸtŸ†Ÿ˜Ÿ¦™¹Ÿ¬ÝŸ:±Ê¤øŸ ¯©Ts“°Ø€Þ¿)ŸZ¯ÚÕ €(%!ƒ¡ëu ’€hàþõÁ¾àöñãR‹ðãïðêñ÷ð÷$ˆÖõ¶Ÿç¯V¯ÀÚÿð³T/ñ%²<+´>À~7±£ïPpð?°çG³<|N²3ðǸÃ[¸ƒÆqÆpÅq_€¿ê¯ü¯×Øõ@‚¢D`,ò¢ª¡ᯡ»¤'…zП‚;¡ºpSïïñ€@Ãÿðƒ*gàÊv|Ð>0-ÏPœ¿®¾§ ÔÈà2ð€x‡@ð€tÐ&ð ñðûñð;¡Pà.‚šÏ¬Ï/ÅÏÌŸéÏÐ1üþÃxÒwÐ»å— é&Éãøfá×pàâßoèÂøhÔpq߃ߕߧ߹ßh×8‰½Ðsàsà}ð }ððð…ð…ðóðïð‹ðð€€½ÓsàÉàðßhïãßó“áþ_á€0ðfïxïŠïâ_äâΠ¹âçÓ ê°ê°îÎâç~ððÀƒÝàïÀÀà-ëápñá8K° o ÿ8Ï1ÿCÿUÿgÿyÿ‹ÿPFŸX—¹ÿXãðÀQæßÿñÿÿ'9Í…MAŠÀr+ÐÀ ÑeBÐÿs°zÀ™¡‚ ö+Ї €ÿþ!€ÂÏQß#Þ‰ÕîÜAÀmáðÁ€Å`qŽ?š3qðÏðêï€ð oJ¸W?àÿø€ à8ˆ@Ð! `Øò !!пpð8l€if¥<ˆ`ÆÏüoxÿx ƒ>qà˜3×p÷×p QøýŠPxþxøàˆo:C/^tÀÿà1¡€a€pTpq>Œ‘ol €ž/ !¨à}€?Ðì°è³ !Ò,0å%Ñ/ÿ/?#?8?+/H?²]ãû(LJx(Ï{°ð €{€¨àæÃoè:þx€ð?øpÿxà|À<€G|OJwm?Séí°XE@õÇ`ãgÁtO„K²][3u®HHËBÑÔOæOøOÞS^àü˜<…è?4Z u€€ôŠ€„€TP>aÀ € €aÀ\PYP‡ŠFd€üÉ¢‡_¾Q#S~ƒºp4_½_Ï_á_uoüæÏ+o8ðp9øøÿ;ùü?œ>7<La8Rodoja,oo oO…û? OÜo1O‡oª½pÁpÅpÉp¢5|xcrÞpl ðಡßÁàÃÀ» ã?€ç€÷ô²ö°€æ°æ°øoú¯ ¿ Ñ> ³<p>ðà.°ûx~3´f 8gÚùàçC³<ÃK±˜÷øT³¸ø`°À+Ð Át¿èoŸ„¿ïÌ>dqp€Ö´£À ÷˰èï Ô£„Pÿø±Ï€ÇÀÀçàIP«0Ápù¿p¯Ï[Å<&r_p8cro ð€±¢¹£ãÀĠħӳԣà`êÐ60ÌÐÒ› ?€^ ”¿ÏüÏ+Ð[s:Ó ½Ï°ÊòÏõ™K“ð€_ApÃÖ`@~ÑÂ>[Ó“à/ßßHÐK‘ÅC‹ß߯ßÁß­Â#SsJÖeÙÍàrŒÍàtÑ[àáÑÃÿßíÞ€aQ{ Ï_ïqï¿IÌÀàÿ?ð8üp??püp>’ø§ï¹ï­ÂpropB·ACK·°nÑáD÷ITHÙæNAMEþ·° Grabbe_rInfoÑáPÖä½2ÑáXGRD·°+16ÑáYöiÿà·°ý /ñFor inÿternal uÿse by the gøãallegro4.4-4.4.2/addons/allegrogl/examp/mysha.pcx000066400000000000000000001702151173507505700216030ustar00rootroot00000000000000 ?Ç,,ªªªªªªªªUªªªUUUUUÿUÿUUÿÿÿUUÿUÿÿÿUÿÿÿ@Ä77pÁ77ÂppÂ771p7Åpp7eÄppÂ77Á11Âpp7Ápp7eÁppÁ77pÁ77eÉppÁ……Á77Âpp7p‹Âpp7ÁppeÑpp7ÂppÁ77ÁppeÐppÁeeÃppÁ77ÁppÁ77eÇppÁ77Épp7ÆppeÂppeÁppÁ77Èpp1‹ÁppÁ88eÁppepÁ77Ápp1Ápp1pÁffpŒÂpp7Ápp7p7‹Á77pÁ11Äpp‹p87pfmŒmÂ77p7ÁffmÁ117Áff7m17ÂffÁ77mÂ771mÁffÅ77fÂmmÃffmÃffÃmmfÏmmfÂmmÁ33m3m3ÂmmÂ22pÃ77Áppe7pepeÁppÁ77pÁ77ÂppÁeep‹ÁeeÁ77ÁppÁ77eÂppep78pfÄppe…ÁppeÁppe7ÁppÁeeÃppÂeeÃppÁeeÆppÂeeÁppeÁppeÇppeÃppepÂeeÃppÁeeÍppeÇppeÄppeÔppeÅppÁeeÑppeÁ77Ãpp…ÂppeÄpp…ÁeepÁ77Ápp7ÃppÁ77ÂppfÂppÁ11ÂppÁffÁ77p7fp7ÁffÁpp…p‹Âpp7mÄff7Ãff7Áff7ÄffÁmmÁffÁmmÁffmÁffÄmmfÂmmfmfÉmm3fÃmm2ÁmmÁ11pÁ77Âpp7Ápp7ÄppŒm7Êpp‹pÁ77ÂppÁ77pf8eÅppÁ77pÁeeÃpp7Ápp87ÉppeÁpp7p6ÃppepÁeeÈppeÈppÁ77ÈppÁeeÌpp7ÂppÂeeÂpp78Épp7Æpp7ep7Ôpp‹1‹Ápp7…Ãpp7ÂppÂ77Ápp7epÃ77Á……pÁ77ÂppÁff7pef7Áffp…fÄ77fÁ77ÁppÁff…fmÂff7ÁffmÂffÁ117f71Âmm71ÊffÇmmÁ337ÁffÃmmfÃmm3ÇmmÁ33mÁ33Á227ÁppÁ77ep‹1ÄppeÁ77ÉppeÁppÁ77pÁ77ÁppÁeeÂppeÇppÁ77ÂppÂeeÉppeÁppeÁppÁeeÁppeÁppÁeeÁppÁeeÂppeÁ77eÁpp6ÁeeÄppÁeeÇppeÈppÁ77ÇppeÅppeÂppÁee7ÁeeÃppÁeeÄppepeÁppeÄppÁ77ÆppÁeeÒppÁ77ÍppÁ……Â77pÁ77p7pÁffÈpp7Â……fÁ……Ãff7ÁffpÁ……7pÁmm…mf7f…ÁffÁmmÂff…Åff…Åff7ÁmmÂffÁmmfmÁffÆmmÁffÆmmÂ33ÄppÃ77ep7Âpp…Á77Ãpp78eÅppeÁpp7ÁppÁ77Æpp7pÁ77ÆppeÅppÁeep‹ÂppeÎppeÃpp4ÃppeÁpp7ÂeeÉppe4ÅppeÃppeÈppeÂppÁ77ÆppeÏppeÆppeÈppÁeeÃppÁ77Ãppep7Êpp7ÃppfÂppÂ77peÁ……Áff7eÁ77Áff7Á11ÁppÁ77Áppf7ÁffÁ117mÇffÁmmÂ11Âff7Áff7fm7ÁmmÁ77f7f…17fmÂffÁmm7ÂmmfmÂffÅmmÂ33Âmm32m2mÁ33pÁ77ÆppeÂppÁ77ÃppeÁppeÁpp7ÁeeÅppeÁpp7eÈppeÁppÁeeÂppeÂppeÁppÁeeÄppÁeep7pÁeeÃppÁeeÄppÁeeÂpp4ÁppeÅppeÂppeÈppeÄpp8Çpp7ÎppÁeepÁeepeÃppeÎppÂ77ÅppÁeeÈpp7ep‹ÁppÂ77ÁppÁ77ÂppeÄppÁffp‹pÁ……p7Áff1ÁffpÂ77ÁppÁffÁ77Áff7pÂ77f7Áppf71Áff7ÂffÁ77‹Åffm7Æffmf7mÂffÁmmÆffÁmmÂffmÁff7fÅmmÁffÄmm3Âpp7p‹ÂppeÄppÁeeÂ77Âpp7eÎppepeÔppeÅppeËppÁeeÈppepeÁpp7ÁeeÁppeÁppeÇppeÃppeÃppeÁppÂeepeÄppÁ77ÐppeÁ……Âppe7Épp17eÁppeÁppeÆppÁ77epeÃpp‹p7Á‹‹pmÅppÁ77Âpp8ÁffÂ7717Ãpp…fp71Â77fp17fÁ77p7pÁffÁ77ÅffÁmmfÁmmÃ77Á11mÁffm7ÃffmÁffm7ÁmmÂffÁmmfÉmmÁffÂmmÁffÂmm2Â33Ánn3ÄppeÅppefÅppfÁeepÁeeÆpp7ÇppeÁppepÁeeÈppeÁppÁeepeÄppeÃpp6ÂppeÂpp‹peÁ44ÁppÁeepepeÎppeÂppÂeepÁeeÃppÁeeÂppeÂppeÁppÁeeÇppÃeeÃppeÃppeÓppÁeeÁppÁ77ÁppÁeeÁppÁeeÁppeÐpp7f…ÁppeÁffÂpp7eÁpp7fpÁ……efm‹7p‹ÁffpÁ77Ápp7p7‹7Ápp17Ãff7Áff7Âff7fm7f7Ämmf7Áff7Ámm7Áff1mÆffÄmmfÃmmfÃmm3f3ÂmmpÄ77Ápp7pÁ77Áee8eÁpp78eÃppeÁ77Ãpp4ÁppeÅppeÂppeÂppeÁppÁee7peÅppeÉppeÂppeÁppeÅpp6eÁppÁee×ppÁeepeÃpp6ÁppeÃppe6eÃppeÅppÁee7ÇppeÍppeÊppeËpp7ÃppÁ77ÇppeÁppÂ77Äpp1ÁppÂ77Âpp7fp7f7ÁffÁ77Á11pÄ77…fpÄ77f…ÁmmÂ771Å77Ámmf7fm7fmÁffÃmm1mÂffÁmm7Á11ÁmmÃffÍmmÁ77ÁppÁeeÅppÁeeÉpp8pÂeeÄppeÂppeÅppeÂppÁeeÁppÁeeÃppeÆppÂeeÃppÁeeÂppÁeeÁ77ÂppÁeeÁ66ÁeeÁ77eÁppÃeeÂppe6peÃppepe7ÁeepeÁppeÃppeÂppÁeepeÁppÁeeÅppÁeepÁeeÁppÂeeÄppeÍppeÁppÁeeÁppeÄppÁ77ÉppÁ77ÂppeÍppÁ……Á77epÂ77ÁppÁ77ÂppÁ77ÆppefÁ……p8Ápp7Ápp1fmpÃff7p…ÁmmÄffpfÁ77ÁffmÁffÁmmf…pÁmmÊffÃmmÁffÁmmfÃmmÁffÁmmÁ33ÂppÁ77Åpp78Ìpp4ÄppÂeeÂppÁeepÁ77ÊppeÃppeÍpp4ÁeeÁppeÁpp4ÁeeÂppÁeeÃpp4pÁ77ÁppÁee6ÐppeÁpp6pep4ÁppeÅppepeÁppÂeeÃppepÄeeÆppÁeeÃpp7ÎppÁ77Èpp…eÂppÁ77‹p7Ápp7ÂppeÂppfÁpp7pÁ……7ÂppÁ77pÁ77p…Åpp7pep‹1…7f71Ápp7p…ÁffÁ……ÅffmÁ7717mf7…Áff7m‹fÂmmp7ÁffÃmm7Á11mÁffm7ÁffÁmmfÅmmfÁmm3ÁmmÁ22mÂppÁ77peÂ77ÄppÁ77eÃppe7epÁ77ÃppeÄppÂeepep7ÄppeÁ88ÁeeÁ77pÁeeÃppeÁppeÃppeÁppÂeeÅppeÍppeÁppepepÂeeÂppÂee6peÄppepÁeeÐpp‹Åpp7ÃppeÆppeÁppÁeeÑppe…peÅppÁeepÁ77ÅppÁeeÇppÁ77Èpp‹Á77p‹ÁppÃffp1ÂppÁff8Ápp8f7p…p…pÁffÁ77fmfÂppÁff…mÁ77fÁmmfÁmmf7fmÁffmÁffmfÅmmpÃmmÃffÁmmÄffm7ÁffmÁ33ÂppÁ77ÃppeÁppeÁppeÁ88Á77Äpp7ÂeeÅppeÄpp8ep7ÄeeÃppeÁppe4peÅppeÃppepÂeeÁppeÁpp6ÄeeÁpp4ÁppÁeeÁpp4peÃppe6ÃppÂeeÆppeÅppÂ44ÃppeÁppÁeeÈppÁeeÁppeÁppÁeeÁppeÆppÁeeÅppeÂppeÁppeÅppeÂpp7ÂppÁeeÁpp7Çpp‹pÁ771ÇppÁ11ÂppÁffÁ77epmpÁ11Â77pÁ77Âpp1mpÁ77‹7p7mÁffmÁ11ÂppmfÁ‹‹7Âff7pÁmmf7Áffm1fmÁffÂmmÁ11fÁmmfÂmmÁffÂmmfÈmmfÄmmpepÁ77ÂeepÁeeÅppeËppÁeeÁppÄeeÄppe4pÄppeÃppÁeeÆppÃeeÂppÅeeÆpp4pÂee4ÂppÁeeÅppÁeeÄppÄeeÃppep7ÁeeÁppÇeeÁppeÁppÁeeÂppeÂppÁeep‹ÆppeÅppeÁppÂeeÄppÂeepeÉpp…pÂeeÇppÁ‹‹ÂppÁeeÁppÁeep‹peÁffpep…pÁ……8ÁppÁ77Ápp…fÂppefp…ÇppÁ77Âppfpfp…fpÃ77pf7Âff7ÁppÁ77fpmfpÁmm1fÁmmÅffÁmmÁffÂmmfÁmmÂffÁmmfmÁffÂmmÁppeÃppÁ77ÁeeÆppÁ77eÂppeÍppeÂppeÅppeÇppepeÆppeÁpp4peÆppeÁppÁ44Ápp4eÅppeÂppÂee4ÁppÁeeÂppeÁppeÂppÁeepÂeeÄppe4ÄppepeÄppeÂppÁeeÅppeÅppeÁppÁeepÁeeÄppepeÉppep‹peÁppeÆppeÂppeÃpp7ÂppÁ77Åpp7ÂppÁ77ÂppÃ77ÅppÁ77Áff7Á117ÂppmÁ771fmÁff7pÃ77…ÂffmÁff…ÃffÁ77fÃ77ÇffÂmmÁffÁmm7ÁmmfÃmmfmÁffÁmmÁ33eÁ……ÁeeÂpp7eÁppÁ88ÁppeÄppepeÁppeÁppeÂppeÂppeÂppeÁppÁeeÁpp6ÂppÁeeÄppeÅppÂeeÂppÆeeÁppeÁppÆeep6ÁppÃeeÂppeÃppÁeeÂppepÁeepÁeeÃppÂeeÃppÁppÄeeÆppÂeeÁppeÃppeÃppÃeeÁppepÄeeÃppÁeepeÁppÁeeÄppÁeeÂppÁeeÂppŒ…peÄppÁ……ep78Éppe…ŒÃppefÄppŒ‹Ãpp…mÁ77Âff8…mÁpp1Áff71mÂffŒfpf7Áffm1pf71ÁmmfÂmmÂffŒmÆff8ÁffmÁffÃmmÂffÂmmÁffÂmmÁeeÄppe7pepÁeeÆppÁeeÁppeÃppeÂppeÂppeÅppÁ66Åppe4pÁeepÁeeÂppeÄppeÃppÁeeÁppeÂppÁ44eÃpp4pÁeeÄppeÃppe6pÁ44ÂppÂeeÁppÁpÁeeÄppepeÁppÁee„ÁppeÆppeÁppÁeeÌppepepeÊppeÅppeÅpp7ÂppeÂppeÂpp7‹Åpp71Âppf7eÂpp‹Âpp…pÁ……ÅppÁffÃpp7Ámm…Œ‹ÁppeÅ77pÁ11Âpp7Ápp7fpfÁ117Áff7m1Â771f…ÁffÃmmÁ11fÃmmÂffmÃffÃmm3ÇmmÄppeÈpp4ÇppeÁpp4ÁeeÃppÁeeÇppÂeeÉppeÁppeÂppe4ÂppÂeeÂppeÂppeÂppeÁppeop46ÂeepÂ66ÁppopepÁeeÂppÂeeÁpp6p6Áee„epÁeeÅppeÆppÁee„ÃeeÂppÂppeÁppeÃppeÁppÁeeÁppÁeeÂppeÃppÂeeÁppeÁppeÆppepeÁppepÁeeÅppÄeeÁppÁ77pÁ‹‹Ãppep‹ÇppÁffÁppfpf8f…pÂ……ÁppÁ77peÁffeÁpp8Áff…p7p…fepÂ77pÁffpmpÁ77fmf…p7ÁffÁmmÅffmf…ÃffÄmmÂffÅmmfpeÂpp7ÏppÃeeÃppeÁppÁeeÃppeÄppÁeeÁppe6Ãpp4ÁeeÃppep4Âppe6pÄeeÃppeÄppÁeeÁppeÂppeÂpp4ÁppeÂppeÅppeÁppeÂppeÃppe4peÁpp6Ãppep6ÂppeÇppeÁppepÁeeÂppeÁppe„pÄeeÊppÁeepeÄppÁ77Åpp‹ÂppÁffÂppÁeeÃpp‹ÂppÁ77eÁ77ÁppeÄpp8eÁpp7Ápp7eÁppep…f7Ãpp7Áffp‹Á……fÄ77pfŒpfp…f7Âff7Âff7ÁffÁ11ÃmmfÃmmfÁ771ÃffÄmmfÃmmfÁmmfÂmmfÁppeÅppeÄppeÇppÁeeÂppÂeeÁppÁeeÂppÁeeÂppeÃppeÂppÄeep„ÂeeÄppe6Áee„ÂeeÂppeÁppÂeeÃppoÃppeÁppeÁpp4ŽÁppÇee4Žep4Ápp„ÄeeÂppÁeeÂppÄee6peÅppÁeeÁppeÁppÁeeÂppÁeeoÁeeÄppeÃppÁeeÁppepÁeeÃpp‹ÅppeÁppeÊppeÄppÁ88Éppe…p7fŒ‹ÇppÁ77‹Ãpp…7Âff7Ãpp…Á77…f7eÂppfp1Áff7Äffp8Éff7Ãff…ÆffmÃffÁmmÁffmÁffÁmmfepeÈppÁeepÁeeÅppÁeepÁeepÄeeÇppÁeepeÅppeÁppepep4ÂppÁee4pÂeeÂppeÁppeÁpp„6Âpp64Áeep464pÁeeÁpp4Ápp6Ápp4Áeep4e„Áee„ÁppÂeepÃeepÃeeÁppÁeeÁppeÁppÁeeÉppeÄppÁeeÁppeÁppeÃppÁeeÁppeÌpp7ÂppepÁeeÂppÁeeÁppÂeep7ÃppÁ‹‹Âpp7Á……ÂppÁ77Ãpp7Ápp1ÇppÁffÁppe…‹p7Á11pÃ77…ÁppÂffÁ77fm1pÃff…mÆffpfpŒmÁ77mÁffp7ÁmmfÂmm…Áff7ÁffÃmmfÁmm2ÁmmÁffÂmmfmÁeeÂppeÄppÁeepÁeeÌppeÁppeÁppeÂppeÁppeÁppÃeeÂpp6ÁeepeÂppÈeeÁ66ÂeepeÂppÄeeÆppÅeeÃppep6ÁeeÁppe4p„eÄpp„ep6eÅppeÂppÄeeÅppeÂppeÁppeÁppÇeepeÍpp„ÄppÁeeÈppÁeeÁppepeÖpp7eÁppÁee…Äpp8eÃppfefÁpp7ÁppÁ77ÂppÂ77ÁppÁ……7pÁ77mÁpp7ÁffpÁ77ÂppÃff…Áff7ÆffpÁffmf7ÂmmfÁ11ÅffmfÃmmfeÃppeÁppe4ÁppepÃeeÃppeÂpp46ÁppÁeeÅpp6ÁppÁeeÁppeÂppeÁppe6ÁeeÂppe6ÂppeÄppÂeep4oÃ44ÁppÂee64ÁppÃeeÃppp46ÂppÂeeÄpp6ÁeeÁppep6pÁee„ÁppeÁpp„ÂppeÁppÁ66ÂeeÂppeÆppe4Áee4ÁppeÃppep6ÔppÁeeÈppÁeeÆpp‹ÐppÂ77Çppfp‹7epÁ77Á……Á77Œf1mfpÂ77pÁ77pÄ77pÃ77Áff7fÁpp7Ámm7Âff7‹p7Ámm8Áff1mÂff7m1mfÁmmÅffmÁffÁmmÁffÁeeÃppÈeeÁppÃeeÂppÁeeÂppeÁppÂeeÂppÁeepÁeeÁppÄeeÂppÅee6ÁeeÁppe„ÁeeÁpp4e„ÁppepÁeep4Áeep4Âpp„eÁpp4Áee„ÄeeÂppeÂeepe6ÂeeÁooÁ„„ÁppeÁppÂee„eoÁppeÁ„„ÂeeÄppeÁppÂeeÁpp„ÅeeÇppeÁppÁeeÁppÃeeÂppÁeeÃppÃppeÂppeÄppÂeeÅppÁeeÅppeÎppeÁ77…ÂppeÂppÃ……7Âffp8f7Á‹‹Ä77p17Â……m7Áffp‹pmfÂ……mf7mÁff…Âff…7fÂmmf7mÅffÁmmÄffÁmmÁffmÂppÁ44eÁppeÁppeÁppeËppÁeepeÅppÁee6pÁeeÁppÁeeÁppeÂppeÁppÃee6p6eÄppÃeepŽÁeeÁ664ÁppÂeeÁ44ÁppÆ664Âpp6Áee4pŽÁeeÃppÃeeÁppÁeeÃ66peÅpp4peÁpp„Ápp4ÄppÂeeÁppÁeepÁeeÈppÁeeÃppÂeepÁeeÁpp‹ÂppeÃppeÉppeÂppeÓpp‹ÆppÁ77pÁ……Ápp7Ápp‹ÁppÃ77pÁ……p8ÁppÁff7p‹pÂffmf7…7‹Á77mÂffÁ771Ámmfm7‹Ápp‹1Ámm7mÂffmÂffmf7Áff7ÃmmfÁmmÁffÂmmÄppÂeeÁpp4ÂeepÂeeÄppÁeepÂeepÄeepÁ66ÁeeÂppÁee6eÁppeÁpp46Áeep„pÂeeÁppe„ÁeeÁppÁee6e6Ãeep„e6Ápp6ÁppÃeeÁ„„ÂppeÁppepŽÁeepÁeeÁ„„ÁeeÁ66ÁeeÁ„„eÁ„„ÇeeÁpp„ÄeepÁ„„Áeep6ÂppÂee4Ãpp„ÆeeÆppepÁeeÄppÁeeÅppÂeeÃppeÂppÄeeÃppepeÂppÁeeÂpp‹Âppe…Ëpp7p‹ÃppÁ77ÈppÁ77…fÁ……Çpp…Œ‹71Â771p7fÁ……Åff‹1Á771ÁffpmŒ…Ámmf…Ámm1Ãff8mÅffpÁeepÁeepÂeeÁppeÁppÅeeÁppÁeeÁppeÁpp46p78eÁ44epÁeeÁpp6eÁppeÁppepe4pÁÃee6eÁpp„ÁppeÁpp4Á66Žo„peÁ44ŽÁeeÁ66e6Â44„6eÂ66pÁ„„oÁpp6ep46„Áppe„o„ÂeeÁpŽ4ÁppÁ66ÁeeoÃeepopŽÁppÃeeÁppe„4ÂeeÁppÁeeÄppÁeeÁpp6ÁeeÄppeÂppepÁeeÂppeÃppeÃpp7ÁppÁ‹‹peÇpp‹ÇppÁeeÄppep‹Áppe…ÃppÁ77ÅppfÄpp17pÁ‹‹p7pÄff1Á77f…ÁppÁffÁ77ÁffÁ77mÁffmÁ77pÁmm7Âmmf…Áff‹1mÁffÁmmÅffm7ÁffÁmmf6eÁpp4ÄeeÁppeÁppÁee6ÁppÁeeÁppÂeeÂpp6eÁppÁeeÂppÁ446eÄppÅee6ÂeepÄ66ŽeÁppeÂpp4oÂppe6eÁppoepep6„pÁeeÁ„„Áeep„64Á66„oÁppeoÁeeÁ„„eoÁppÃee6„oeÄ„„pe„pÁeeÁppÁeeÂppeÁppeoÃeepÄee„ÁeepeÄppÁeeÁppÁeeÂpppeÂpp4ÅppÂeeÄppÉppÃeepÁ……peÇpp7Épp…ÁppÂeeËppÁ77pÄ77pÂ77Ápp7…f…ÁmmÁff…ÁffÁpp…Â77fŒmf7Èff7fÂmmÃff…fÁmm7ÃffÂeepÁ44ÂppÁeeÂppeÃppeÆpp6Ãpp6ÁppeÃppÁeeÆppÃeeÁ66pÁ66p4ÁppÃ66ÁppÃee6„e„„„p4Žpe6e6Æee4p„Ápp6Áoo6o6p64pÁeeÁ66e6Âppoe„peÁooep4oÁeepeÁ66„ÂeeÁ66Ápp4p4e6ÂeeÉppÆeeÁppeÂppe„ÁeeÁppeÁppepeÁppÁeeÁppeÎppÂeeÎppeÆpp7p7‹ÅppÁ77pÁ‹‹7ÈppÁ……7p7fpf‹Á77pÁ77pÁ……17Ápp7pfÁpp‹ÁmmfÁmmfÂ77f…Âmmfm1mÁff7fmÁffÁmmÂffÁeeÂppÅee4ÂeeÃpp6eÁppÂeepeÁpp„eÁppÁ66ÈeeopeÁpppÂeepeoÁ66opp6Á44ŽÁ„„peÁoo4„eoÁee„eÂ66pÁpÁ66poÁ„„ÂeeÁppoÃeeÂooeoÁ44„Ápp6Âee6epÁoo„ÁoÁ66Âee6„e„ÂppÁŽŽÄee„pÃee„ÁpppeÄpp„pÄeeÁppÁeeÁppeÁppeÁppÁeeÃppÃeepeÇppÂeeÄppÁeepeÂppÁeeÈppÁeeÁ‹‹Äpp8Ìpp…ep7Á88p87Åpp…pf…Áppf7f…ÁffÂ77pfÁ……f7…Å77Ápp787f1mp7Âff1ÅffÂmmfÁ77ÂeeÃppÃeeÅppeÂppÁeeÁppÁeeÁppeÁpp4eÁppeÁpp64pÂeeÂppÁee6eÁppe6e4„oÁ44ÁeeÁppep6ÁppÁ66ÁeeÁppeÁoo6ÁeeÁoo„eÂoo6ep6ÁeeÂppeo4eop„Áee6e„6eÁŽopoŽÁ66o6eÁ„ep4pÁeeÃppÁ66ÁoŽÁppe4ÃppeÃppŽeÂppe4ÁeeÆpp6ÃeepÁeepÂeeÃppÂeeÓppÁeeÅpp7ÂppeÄppÁ77Èpp7Ápp‹ÂppÁ77Áppf…Á77p7f…fÁppf…fp…fÁ771ÁffÂppÁffÁ771ÃffpÂffÃmmÁff1f7Á117mÃff1ÂmmÅffÃeep6ÁppeÅpp64Äee„ÁeeÁpp6Ãeeop6epÂeeoÃppÂeeÅppoÁeeoŽ4„eÁppÁ„„peÁ66eÁ66oÁee„Áee„e6Á44oÁeepÁ66epÁooÁeeog6„Áee6„e64„o„oÁppoe„ÁeeÁ„„4Á66oÁ„„Áee6ÁppÁoo„Âee„Áeeo6epe„ÁppŽo6epoÁppÁeeÁppŽpÁeeÁ„„ÁppepÄeeÄppeÂppeÃppÂeeÄppÁeeÁppÁeeÂppÁeepeÍppeÃppeÎppÁ77Ãpp…p‹ÁppÂ77eÁpp7fÁpp…ÁffÁ77‹f7Âpp7…pf7ÂffÃ……7fpÁff7mfpÂff…ÁmmÂffÁ……p7ÂffÁmmfÃpp4ep4p6e7ÃppÁeeÁppep4eÃppÁ446pep4ÃppÁ„„Ápp„e64Ápp4Æee6e6Á44ÁÔ4e6Áppe64Áee„ÂeeÁppÂ66eÁpp6e„64„Á44o„epÁ6o„e6o„Áooeo6oÂppÄoogÂooÁ66ŽÁooÂ66oÁ„„o„ŽÁ66oÁ66p4o6o„eoÁppÁeeÁpp4Âeepe4Âeep4ÄeepÁpp…ÁffÁppÇeeÃppÁeeÚpp7Æpp7ÂppeÅppÁffp78Ápp…ÁppÁmmÁppfpÁ77Äpp7p…Ápp7pÃffÆ771mÂffÂmm1Ä77…Âff7mÃffmÁffmÁffÃmmÁee=6Âee6Âeep4ÃppÁee4epÁeeoepÁeepeÂppe6p6ÂeepeÂ44epe6„ÂeeoeÁ„„ÃeeŽpoÁee„6„ep6Á44ÁooÁ44oŽpÁeeo4eo4oepÁeeŽÁooÁ„„Âoo„e6oŽÅoo„Áoo„ÅoogÁÄoo„o„Âoogo„ÃooÁ„„ÂooÄ„„6oÂppeoÁpp„opoepÁeeÂpp…Áff8=Â!!=Áff…eÁppeÁppÅeepÁeeÆppeÂppepeÁppep7ÅppeÅppeÎppÁ77Æpp‹Âpp17Âff7Âpp7fpÂ77Á……fŒ‹f7ÂppÁ……pÁ……Áff‹Ãffp‹1mÂff7Áffpmfm7ÁffÂ77ÃppeÂppÂeepÂeeÁpp6Áee6ÁppÁeeÁ44pepÁeeÆpp46e„e46ÂeeÃppÂeeÁooÂppeÁ446ÂeeÁppoÁ66Áee6pÁ66o4pÂ66ÁooŽÁoo646po„ŽÄoo6ÃooÁŽŽÄoogÅooÁggqÄoo6Æoo4ÃoogÁeeo6Âoo6e„6„p4Že„ÁeeÃppepep1!&LO'ÁOO%A=ÁffpeÂppepÅeeÅpp8p47ÆppeÈpp‹Äpp7ÈppÁ77ÆppeÁ77ÅppÃ77Áppe71pÃ778Â77f…m7fmp78Âff7Åff7ÁmmÁffŒ17Á11ÂffÅmmf6p4Áee6Á44Âee4ÄeeÁppÂeeÁppeÁpp„epÁeeÁppÂee6e6Áee6Áppo„Áee6epoÁ„„e6„e6oÄ„e„oÁ66Áeeo„ÁooÂee„Á66ÁeeŽeoŽ6„ÂooÁee=Á„„oÁggoÁ„„Åoogq<ÃoogogÁqqÁ;;Ágg††ÁooÁgg†Áqq†oÁggÇooŽ6ÂooÁ„„ÁppeÄooÃee6oefe#OQŸŸÁÇÞž%A8feÁppÁeepeÂppÁeeÂppeÁppÁeeÒppeÇppÁ……ÁppÁ77Çppepe…ŒÁeepÂffÁ……eÁ88…7pÂ……‹…7Á……ÁppÁ77Âpp…Á77pÃffmÂ77pÅffÁmmfmŒÂffmpÁffŒmf4peÁpp6ÁppÂeepeÁppeÆppÁeeÁppeÊppÄee6ÁeeÁppe6Áeep4pÁee„Á66ÁppepoÁ44Áee4Á66Ž4o„46oÁee6o4ogÁoo„e64Áoo64ŽÂooqÂgg6ÃooÂ;;FD&%RSTÂVVZÂÁXX\ÁYYÂ\\}XÂÁXXZZW{TQPÁRRÁMMNÁIJF$Ä@@E@AhÁqqo4#Q|yŸÂÇÁÇÁÈÄÃÁÃÁ››šžÃššÁKKžK#gÁ77ÉppÆeeÍppepepeÁpp7Èpp7Æpp1Ápp7Ápp1ÂppÁ77p…ÂppÁffp…f‹1Ápp…fÁppf…Äff7Ãff7f…fp7Ãff…mÂffÁ778f7ÁffpÁffÁee6Á44eÁppÁee6eÂppe6oÂpp4pÅee6ÁeeÂpp6ÁeepÁ44ÁeepeÁ66ÂeeŽ46Á4Á66ÁeeÁooŽÁoo„ÁooeÁoo6e8eÁpp„e6ÂooqÁggÅooÁqqÁ;;9rBA@#&MP'VÁZZXÃ\\Á[[Á]]Ã^^Á]]Æ[[\Y\Y\XÁZWVTÁPPOSMN&IÃJFEtÁhh!$T|£ŸÁÇ ÁÈÁššÁÃÁÃÁœœÁ››ÁššÁÚ ÁššKžž%A8ÁpppÁeeÇpp‹Çpp6ÅppÁeeÃppÁ77p7Äpp7ÉppÁ77e7f7ÁppfÁ77pÁ77Ámm7pfÅpp7mÁ11ÁffÂ77…Áffp1mfÁ11m1ÁmmÁffmÂffp7Ámm7mf717ÁffÁmmf4Ãpp6ÂeepÂeeÅpp6ÇeepÅeeÁpp6Áee„eoÁee6pÁee6oÁ6646Ž46p4ÁooÁ44ÁooÁeeÁ„„Á66!A!8feÄoogÃqqÁggq†ÁÁqq;ts?E#J&PTZX\Á]]Á^^aÄ^^ÁaaÇ^^Ã^Ä[[\ÂYY}ÁÁWWVTÁ''QÁPPSRw&JÁFF$EP{£¥ŸžÁÈÂÃÁÃÁËÁÄœÁÃÁ››šÁÚšxšžx žL!ÁeeÁppÁeeÂppÂeeÄpp‹peÌppeÂpp‹ÉppfÇppÁŒŒp7eÁpp7Æpp7pÁ77Âpp7ÁffÁpp8fp78pŒÁffpÄff87Áff7ÁffŒÂmmÁffÂmmÁffmf…ŒmÁffÂeeÁppeÁppe6pÇeepeÁppÁee4Ãee4ÃeeÃpp4Á66oÃeeÁpp6oÁ44Áoo46eŽepÁ44„Á66oŽp6ÂRAÁffÄooÂqq:Á;;ÅqqA?C&%RTVX]ÂaaaÁaaÁ__aÁ__Áaa®a^Ç^^¯Á^Ä[[ªÂYYÄÂWWUQRMKN&TV|¥¡ž ÁÈÁÈšÁÃÂÄÁÄÃÃÁÃÆššxžšžL=7peÃppeÈppÂee4pepÁ77ÁppeÁpp‹p‹ÉppÂ77ÃppÁ77ÈppÂ77pÁ11pfÁ77…fÁ77fŒÁ77fm7fmŒf7Áffm171ÁffÁmm7Áffmf7mÂffÁmm7Ámmf17mf7fÁmmfÁeeÁppÊeeÁppÂee„Á66Ãee6ÁppÁ664Âee„o6oe6o46eÁooÁpp6Áee„op6opo„ÁppoÁ44oe8#­§}|#8m6ogoÂqq:’AtAÁrrÁAA@EIRPVZXÁ]]ÂaaÁ__bÁ__ÁÂ__bÇ__aÊ^^Á^Â[[\YªÃYYÁXX­§VUÁ||zy{|£¡ÁÇ ÁÈÁÈÂÃÁÃÂÄÁÄÁÃÁÛÁÃÁššxÁššxžšKÁww%eÁppÃppepeËppeÁppŒ…‹ÃppÁeeÃppÁ……ÃppÁeepÁeeÁppepÂ77…pÁ77p‹ÂppÆ77ÂppÂ……f…Á‹‹Á77…Áffpmpfp1mf7pÃffmÆffmÄffmÁffÁ77ÁffÂeeÁpp6Âee6Áppepe6ÂppeÁppeÁ66Ápp6pepÁeeÂppÂee6pe„Á44Áeep6o64pÂooÅ66o„op"R§Á{{WUI!f8ÁggÁ<?F&RPTZY[^_Âbb`Á`Á`ÁbbÆ``ÁbbÅ__ÁÃ__^aÅ^^Â^^Á[[¯Ä[[ÁªªÁYYWÁ||U{£¥µÁÈÁȳÁËÁËÁÄÁËÁÄÁ´´›ÁÃÁÃÄšš ÁxxÄžžŸLJg…e„ÁppÁeeÃpp1ÂppeÅppŒ…Âpp7Ápp‹ÅppÁ77Äpp‹7ÂppÁ77ÂppÁ77p78Âpp7pÁffÂ77fp…Áff7pÂ77Áff7…Á77…ÂffÂmmÁffÁ77pÁffm7ÃffmÄff7ÁffmÁffÂmmfoeÂppep46eÁppÂee6ÃeeoÁeeÁpp„e=ÃeepÁeeÁ„„epŽ46„e6oÁ„„op6„Ãoo„„eÂ66oÁee'Á~Á{{Á§§©Qy¢¤v;gh@EJI%OTZX\)+aÁ__b`ÁÁ``cÅ``‚Ç``bË__Á__®_^®_®ÁÁ[[¯[^Ã[[ªY~Ã{{¨yÁǶÁÌÁËÄ´´™ ÂÃÁÃÁÈÁÈšÁÈšÁžžÁKKžÂŸŸMhÂeeŽpÁeeÅppeÆppeÁppepeÂppeÂpp78Äpp8Épp7ÁeeÁpp7p‹ÁppÂ……p7ÂffÁppÃ77ÂppÁ77…Âff…7Âff…Áff…ÃffmfÁ77Âff7Áff…ÂffÁ77Âffmf7fÃeeÂppeÂppÁeeÁppÁeeÁppÂeeÂ44Â66pe6Âee6Ãeeo4eŽÁ„„oep4oÁ66ÂooÁ66Á„„Â66ÁooÁ66=XÃ~~Á{{¦©£¤Á¢¢xAEIMOTVX\]abbÁcÁ``cÅ``cÁ``cÇ``‚Æ__`_bÅ__Á®®Â__Á^^Á[[¯[^ª¯€}WÄ{{|¥¶ÁÌÂÃÁÃÁËÁÄ ´ÁÂÁ´ÁÄÁÃÁÃÂÁÞÁ  ÂžžÁww¡ÁžžLE6p64Ápp4ÅppeÆppeÄppÁeeÈppeÅppfeÂpp7pÁ77Âpp7pÁ‹‹ÂppÁ77pÁff7pÁ117pÁ77Ãff7ÁppÁ77pÂ77fÁmmÁff7‹ÁmmÁffp7ÂffÁmmÃffÁmmfmÁffÁmmfe4pÄeeÁ66ÁppÁee6ÅeeÁppeÁoo„epe4p„Á66ŽpÂeep6oÃeeÁ66o6ÁooeoÁ66oÁ„„Åoo6!RÁ}}Ä~~Á{{Á©©Ã¤¤LJRT\^Â__Á``c`Âccdc`Ácc`ÁccÁ``cÉ``‚bÁ__Á‚‚Â``Å__^Â__^Á[[į¯ª­~W|Â{{¨|¡ ÁµµÁÈÃÃÁÃÁÄ™´ÁËÁÄÁÄÁÃÁÁÚž¡ÆžžwÁžžŸg„o6Âeep4ÁppeÃppeÅppÂeeÌppÁ……ÊppÁffÂpp7…fÁ77ÃffpÁ……ÁppÂff…Ã77Áffpfmf7pfÁ77f…Ä77Âff…7ÂffpÃff…ÁffpÃffpf7pÁeepeÁppeÁppepÁ44Â66ep4ÁppeÁ66pÄeeÂpp6ÁppeÁ44Á66oepoÃ66„Á66pŽÁ66Á„„ogÃoo46Y}­Á­~Á§§Á©©¢¥Á¤¤QzPVXÁaaÁ__bÁÂcc cd ÂddÁccÁddÃ``ÁddcÈ``Ä__Â``É__Á^^Ã[[¯[­~§Á||~§{¢£ÁÇ ¶ÁÈÃÃÁÃÁÄ´ÁÄÁܚšÁÈ wÞžÁÈÁÈÁžžwÁžžL!Ãee6Âpp‹Äpp7ÈppeÁppeÈppeÆppeÃpp8fÂpp7fÁpp‹Á77pÁ‹‹Á11ÁffpÁffÁpp17f…Ã77ÁffÁ77f7p17fÁmm17Á11Á771ÅmmÁff7Âffmf7ÃmmÂeeÁppeÂppeÁ66e„6e6Ápp6„6ÂeeoÁ„„ÁeeÁ66ŽpeÁpp46Âee„„Á66ÂooÃ66„oeÆoogo"%\Â}}­Á~~§{¨|Á¤¤£¤ŸO~_bÁÂcc dÁ Âdd ÁddÁ dÂccÁ``dƒÁccÆ``Á__`Ã__Á``_®È__®¯Â[[Áªª­§~¨©Â~~{£¥µÁÈÁËÁÃÁÈÁÈÁÃÁËÁ´´ÂÃÁÃÁÈÁššÁÈ ÁÇ  žÁššÂžžwÁ  wI;Â66Äpp46pÂeeÃppÁ‹‹ÂppÁeeÕpp‹7Åpp1‹ÃppÁ……Å77…ÁppÄff…ÁffÂ77fÁppmÆffÂ77p7ÂmmÂffp7f…7fÂ77Âff7ÁffÁee6pe6ÃeeÁppeÁ44ÁeeÁ446Ápp6Á44ÂppÁeeÅ66Áoo6„p4Ä66ÂppoÂ66ÁoopŽ„Åoo6VY€}­Ã}}~§¦{©¢Å¤¤_c`Ácc ÂccÁdd Áccd Á,,ÃddÁ ÁccdƒÅ``‚`_Á‚‚Â__®_Á``_®_®Â__`Á®®Â^^¯[Yª}Á~~}Â{{~Á§§{£ŸµÁÌÁ˳µÁÃÁÆÁÅ´ÁËÂÃÁÃÃÈÁÈ  žwžÁÈ ž ÁÈšÁžžw¡I;eÃooeÍppeÁ88Ápp7Âpp‹ÂppÁ77Èpp7p‹pÃ771Á77Âpp7pÁ11ÄppÁ77p7mfÁpp7Á11ÁffÂ77f717Áff…Äff7Âmmf7pÁ77Âff7ÁffmÅffÁmmfe6eÁppÉeeoe6Ãee4Áee6p6„Ápp„e6„Áee6„Ž6Áoo„ÁppÁoo6Ãoo„o6ÁoogÄoo6#XÁ€€Ä}}Á~~­§Á¦¦¨Á¥¥¤ÁŸŸÁzz©^cdÁ Ádd cÁdd `dÁ,,Ädd` dcÅ``ÁbbÁ__`‚_^Ã__^^®Á__`¯Ã^^Á[[Á­­Á~~X~{Áii¦~{|£¡Á¶¶ÁÃÁÌÁÌ´ÂÅÁÅÁ´´ÁËÁÃÁöÂÈÁÈ ÁÇÁÇޞ  wÁžžwŸvAÄggoÁŽŽpŽÂeepepÁ‹‹ÂppeÁppÁ77Ðpp7Åpp7fpeÁppeÂppÃ77Åpp…pÁ77ÁŒŒ…f7p…pÁ77…f7Áffp…Ámm7fÂ77pÃffpÂ771m1mÂffÁmm7ÁmmeÁ66ÄppeoeÂ446ÁppÁee6„Áppe6ÁeeÁ66ÁooÁ44pe6Á44Á664Å66Á446o6ÃooŽÁooŽÁooÂ==ASÂ\\€Æ}}§¦Á{{y¤£ŸÁ¥¥ÁŸŸW^`ÁccÁ`ÂddÁccd`cÂdd,ÁddƒcÁddcÂ``Á__Á``‚Ä__Á^^®¯^Á®®Á¯¯®Á__[ﯪÂ}}ÁXXY~¦Â{{~{£¥¡µÁÇÁǶÁËÁË´ÄËÁËÁÃÁÃÁÈÁÈÁàžÁ¡¡wÁ¡¡žÂ  xÁžžÁwwx@!rÁ;;q564eËppeÄppÁ77ÎppÁ77ÈppË‹Ã77eÁ77p71pÂ77ÁppÁ‹‹p7fm7Á11ÂffÁ77Áff7…ÂffÂ77ÄffÁ77pm‹mfÁmm7Â6646eÁ44e6„Âeep6ÁooÁee6e6Áoo„eÁoo6ÂooÁ66o„Áoo„e6ÁooÂooŽogoÂ55o<ÁggÁqq;'€ÂYY\[Á€€«€Á}}Ájj«Ã¬¬Ã££¸£¦£¦Áɦ¦}€€Y­}[ÁªªÂ¯¯®€¯Á®®^¯®Æ__‚Â__`Á__`bÃ__®Á^^®_‚Ácc,b]X€Á~~¨¦©Á¥¥·Áµµ¶ÁÌÁÌÁÆÁÅÁËÁÆÁÅÁËÁÃÁÆÁÆÁÌÁÌÁÃÁ³³ÁÈÁÇÁÇÁŸŸÁzz¤Ÿ¡ ¡ÁzzŸžšŸÁßÁLLNIDE@9rÁqqgp6p4ÁppÁpÁeeÄppeÂppÃeeÌppÁeeÂppÁ77‹pÁ77ÃppÁ‹‹Á……pÁ‹‹Ápp7‹p17pfmÁ77Ápp1Á77…f7fpÁ77p7pfÂ77fÁmmÁ77fmf7m7Äff646p6e6ÁppepoÁeeÂ66ÂeeÁ66eÁoo6„eÂ66oÁ66Áee6Âoo6o6Äoo5ÁooÁ<;?FIOYªÁ€€ª€Á}}€«}Á««­Á¬¬¹£¨¦¨£¢Á¨¨Á¢¢¨¦¬­}]^Á[Yª[^Á¯¯Á^^Á®®Ã__Á‚‚_Á``_`Á‚‚Á__Ä``Áƒƒ`bÄ``ƒÁ``d‚`dc_ba\Á]]XÁ~~yÁ¥¥¡ÁÈÁÈÁÃÄËÁËÁÅÁÅÁËÁÅÁÅÁÆÁÆÁ̶ÁöÁÈÁ  ÁÇÁ¡¡ÁŸŸz¥ÁŸŸz¤ŸÁžžŸ¤OÁŸŸÁÞÁÞKGJE@;q@EMPUYÅ€€«}­Á¬¬Â§§~¦¹¨¦¢Ã¨¨Á©©¨¬Â}}^^[¯Â®®Æ__Â``Á‚‚`‚È``dÁccÉ``ƒÁccƒÁbbaÁ]]\Á~~|Â¥¥µÁ̶ÁÆÁËÁËÁÃÁÆÁ±±³ÁÆ´ÁÆÁËÂÌÁÌÄÈÁȵá¡¥¤ÁyyÁŸŸzÁžžŸ¤OÁߟÁLLžš›Du@A;Á<<ÁooŽ4eÂppe6ÈppÁeeÇpp‹ÁppeÁppeÂ77ÁppfÇppÁ77Ápp7fŒÁ77ÁppÅ77ÁffÁpp‹Âpp7Á11Á……7…fÁ77p7Á11Ã77Á‹‹f787f8Áffm7Á66oÁeeÂ664oeÂ66oÁ66ŽÁppÂ66Áee64Á66oÁ66Á446Âoo6ÁooÁ66Áoo6oÁggÂqq:rt?F&RPVZÁÁYY€[€€Á}}­¦Á¹¹¦§¬Á~~Á¦¦Á¨¨{Á¦¦§¬¨­j€X‚Á^^Â_®Ä__Á``Á__Å``‚É``_‚Ã``Ácc`ƒ`‚dc`cÁbba]€}X{£y¥¡ÁÈÁÈÁÌÁËÁËÁ´´ÁÂÁÅÁÃÃËÁË´ÁËÁÌÁ̶ÁÈÁÈÁ  Â¡¡ÂzzŸ¡ÁŸŸzŸÁÈŸ¤ÁßÁߟŸÁÞÁÞÁKKvHC$A;q5ÁooÁ44p‹ÁppeÁppeËppÁ77e7‹Åpp‹‹ÁppÁ11Âpp7Á11Æpp7ÂppÁ77pÂ77Âpp1Ã7717Á11‹pf7Áff7Âmm1f1mÅffÁmmf7Á117oÃeeÂ6646„Á66oÁ66Ž6Ž6Ápp6opeo6Á„„oÁ66Âoo=ÂoogÁooÂggÁ<<:9$NPVZ\[}Y}ÁªªÂ€€Áªª¬§¹Á¨¨§Â¬¬Á¦¦¨£¨¦Á¬¬\~}ª€]Ã_`Á‚‚`‚`‚`d`‚dÁ``cÁ``Á‚‚Æ``c`Á‚‚Ã``ƒ‚dÁ``c,Áccb_ÁbbÁaa\X~¨Á££yÁǵÁÈ´ÂÅÁÅÁËÁËÁÃÁËÁËÁËÁÄÃÃÁÃÁÌÁÈÁÈ µ¡ÂŸŸÂzzÁyy¤zžšŸÁßÁߟŸÁÞžžKG›Dus9r<Áoo6eÃppeÂppÆeeÅppeÍpp7ÂppÁ77Æpp7ÄppÁ77pmÁ77Ápp7871p71Ã77ÂffÁ77…Áff1m…ÁmmÄ77ÁffÁ77Âff764Â66Á44peÁooe6ÁeeÁ664p4ÁeeoÁ66o„op4o6ŽÁ44oÂ66gÂ55<Ãgg<Áqq;@#&PY[a^ª~}ªÂYY€«Á¬¬Â¦¦Áɨ¹¦¬Á§§~¦¨ÁÉ~­€Á}}~\ª€aÁ^^Áb_‚Æ``dÁ``cÃ``cÈ``c`‚`_Á``cÂ``Á‚‚`d`‚Á__bÂaa\}~V|zÁ¡¡ ´ÁÂÁÂÁÅ´ÁöÁËÁÈÁÃÁËÁÃÁÁÃÁÃÁ̶ÁÃÁÈÁ  ¥Ÿ¡Ázz¤zŸŸxž¤OÁßÁŸŸLÞžÁKKšHDC@9q;q<ÂooÁ66ÁeeÁppÁeeÄppeÄppeÉppÁ77ÊppeÁ77p7Ápp7p7epÁ77ÁffÂ7717p‹Á77Âpp‹Â77fÁppÁ77ÁppÂ77ÁffÁ11Â77‹pÄ77Á66oŽÂ66ŽÁ44oÄee6Á44p6ÁppeÁooÁ66ÁooÁ66Á44oÁ66og<5g;q:ÁrrÁ99>EF&R'Z(a_`_Y~Á}}€€Á}}­Á}}§§¦Á¹¹£¨¦¬}¬§¦Á~~}Y}\aÁaÁ__bÁƒƒ,ƒ`Ácc`dÁ``ƒbÃ``ƒÁ``_‚Ã``cd`‚ƒÁbbÁ__ ‚`Ä__b^_‚_aÁ]]€~UÁ||£¡Á  ÁÄ ÁÃÁÈž ÁÈÁÈÁÃÁÃÁËÄÄÁijÁàÁÇ¡Ÿ¡ŸÁ¤¤£Á¤¤ÁŸŸÁÞߟÂÞÁÞÄžžÁKKšGHFE9ÁqqrqoÁeeÁ66ÁeeÅppÁ‹‹ÁppÁ11Åpp7ÃppeÅppÂ77eÁppÁ77ÁppÁ77pÁ7787pÂ77f7fÁppÁ77ep7Á11fÁ11pÁffÃ77ÁffÁmm7ÁmmÁffm1f…71ÃffŒÁ66oÃ66oeÁoogÁ66ÂooÁee6ÂooÁ„„64Ãoo64ogoŽÁooCIRV^Âcc _­YÅ}}Á¬¬§Á¦¦ÁÉÁ©©Áɬ¦¹Áɦ}\€Á]]Á€€]_Ább_`ÁddÃ,,d,Á``,ƒd`cƒÁccÁ‚‚_‚ƒÁbbÂ``b‚Á__bÁ®®bÁ__ÁÁ¯[]€ÁYY€Y~X{|zžŸžšÁÁÈÁÄ´Á±Á™´ÁÃÁÃÁÄÁ ÁÄÁÚ ÁÇŸŸÁ¤¤z¥ÁŸŸžÄŸŸÃÞÁÞÁžžÁÝÁÝÁKKžKÁÝÁÝGHDCs9;9:gÁoo4ËppeÌpp‹Åpp87Áppf7Ãpp7Á11ÁppÃ77pÈ77Ãppf7Ápp7ÁffÂ77Áff7fÁ77fmÃ77f1pÁ77ÁeeÂoo6ÁooÁ66Á44Â66ÁoogÁeeÂ66Áoo6ogÅooÂqqr9t>sF&RVX]a`Ácc Ácc Ácc_­~À€YÁ}}Á~~§Á¹¹ÁÉÁ¦¦~Á­­}jÂ}}j\Á]]bÁ__Á``ÁbbÂcc,d c dc`dÁcc‚cÄ``‚‚b‚cÁ__‚Á__Á^^Á]]Á[[ª}Á}Á§§{Á©©ÁUU|ÁUUÁ||UQzÁPPLxšH ›ÁÄ™Á™ÁÀÂÁÁÁÁÀ±™ ˜œÁÃÁÈžÁÇÁÇŸÁÇÁÈžÁÞÅŸŸÁÞžžÂÞÁÞžžÁššÁGGÁ››ÁGG›GÁ››ÁÛC>9;qIRTXÁaaÁ``cÁ ÂccÁ , Y~ÁYY€€ª­Á¬¬§¦Á¨¨¹¦~§~X}\jÁ}}\]+aÁbb‚`cbÁcc`Â,,dÁccÂ``Ácc‚`‚bÁ‚‚cÁbbÁ__`b_aÁ^^Á[[Áªª€Y~Á§§W{©U|UÁ||Á¢¢ÁQQ|UÁŸŸÁ¤¤xKxH›–Á—ÁÂÁÀÁÁÁÁÁÀ ÁÂÁ ÁÄÁÃÁÃÁÈÁžžÁÇÂÈÁÈÞžÁÞÈŸŸÁÞÁžžKÁššÁGGšÃ››ÃÜÁÜDus9q†Áoo6eÇppeÄppeÁppeÊppÁ‹‹Ãpp7ÉppÄ77p7Á117ÁppÃ77fÁ77‹Â771p7mfÄ77fÅ77Áff1m7Âooe„oÃ66ÂooÁeeÁ44ÅooÁ66Áoo<Á55Á<<Á55<Áooq:;>&'ZÁÁÁcc Äcc Â,,_XÂYYªÁ}}­Á¬¬§Ä¦¦ÁÉÁ¦¦Á~~Á}}\€\+abÅcc,cÂ,,dÁ‚‚Âcc`c‚Â``c`cÄbbÁ__a^[€€}§©{©ÁUU©U|V¢|ÂyyÁQQ¤LOzwMxv–—ÂÂÁ ±ÁÂÁ•ÁÀ±Á ÁÃÁÃÁÈžÁÈÁššÁÈÁȞğŸÁßߟLÁžžÁÝÁÝKښÛ›ÁÜÁÜHÁ––—?>rqoÂeepeÂppeÂppÁeepÂeeÅppeÃpp‹ÃppÁeeÅpp7ÅppÁ77pÅ77p…ep7eÁffÂ77pfÁpp7pfÂ778fÂ77…f…f78Á77ÁffÁ66Â44o6Áoo6Ž46oŽg6ŽÁ44Žo6oÁ66ÁggoÁ<<ÂqqÂ::;A@F%T]+Ábbc Ácc Ãcc ,c[Á}}€€Ã}}­Á~~¬¬§Â¦¦Â~~€\€]aÁbbÃcc‚cdc Áddc`Âcc`cÁ``cbcÁ``ÅbbÁ__Â^^][ÁYY­§ÁUU{U©©Q|Uyz¤QUÁyyzLŸÁzzxšœ—D Á—ÁÂÁÂÁ ÂÀÁÀ±  ÁÄÁÃÁÃÁššÁÃÁššÁÝÁÝžžÁÞޞߟLÁÞÁžžÁÝÁGGÁ›››ÁÃÜÁÜ–—”>;@E&P(ÁbbÌ _Á}ªÂ€€ª}­}­¬Á~~¬­Ã~~X}\)ÁaacÂcc cbÂcc ,Ãcc`bÇ``bÁ‚‚ÁbbÂ__Á^^]Á[[Y­§{ÄUU¢Q|UyÁßÁßÁQQyQzOzŸwxšÁÛ–˜ÅÂÁ Á¿¿Â Á ÁËÁËÁ››ÃššÃžžÁÇžÁÞÁÞŸÁÞŸÁžžÁšš›ÁÜÁ››ÁÜ–ÁÄ–ÁÜ–Á —”•rq5ÁooÁ66Ápp6Áee4ÂppeÍppeÃpp7ÅppÁ77ÅppeÅpp8Â778pÁ77ÃppÁ77‹Ápp7ef7fmÃ77ÁppÁ11p…1Ä77o6oÅ66oÁ66Áoo4Á66oÁ66Âoo6ÅoogÁqq:9A>ÁÙuJNPV()ÁÄccÄ cà ,­~}€€Áªª}­­Â~~§§­X~}\]aÁbb c`Ácc,`Ácc`c,c`Ácc,Á``Ábbc`cÁ``cÄbbÁ__Á^^[\ª­~©Á¢¢©ÁQQ£yQ|yÁOOyQ¤QÁzzywLvÂHH›” ——– Á ÁÂÁ ÁÂÁ Å ÁÄÅššÁÈžÁÇÞžÂÝÁÝÁžžšÃ››–– ÁÛÁÛ ÁÛÁÛ—”strqoÂ66ÃppÁeeÂppe‹Æpp‹Épp‹pÁ77Äpp7Ápp7pÃ77Ápp7pÏ77fm1Â77f7Á11Â771Ãff7fÁmm7oÁ66ÁooeÂ66oÁ66o=4ÂooÁ66Âoo6ÂooÂggÃqq;A@&P(]abÁc ÊccÁ , ­}ªÂ€€ª}Á­­Â¬¬Á§§Ã~~}\]bÁ,,Ábbc cÁ``c,cÂ``c`cbÁ``c`c`_`Â___Á^^€ªYÁWW{Q¤U{¢ÁyyQ¢Qyz¤¢OzLOy ÁššÁ››G›™”DÁ——Á™™Á ”•¿ÁÀÁÂÁ –– –Á›ÃššÁžžËššÁ››ÁÜÁÜ–Á ÄÛÁÛ—ÁÚ?trÁ<<ÁooŽÄppeÌppeÒppeÄppÁ11pÃ77p7Áppfp7pÆ77pÁ77ÁppÄ77pÇ77Âff8oÂ66oÁ66ÁooŽ6eoÁ66ÂooÁ66Âoo4ÅooÁ<<;:’t>L'W\]aÁbbÁc ÁcccÂcc d`[}Áªª€«­Á}}ì¬Á¦¦§Ã~~\]Á**bÃccÁbb Âccbc, `cÅ``Ác`Áb‚Â__aÂYÁ{U|¤¢U¢y|Á¤¤yQÃzzwŸOz GxvGxH™”—–D–uÁ””Á ÁÀ ÂÂÁ Á כššÁÃÁ›ÆššÁÝšGÁ››Á––—Á—— —C”>rq<ÁooÁ66eÒppÃ77ÁppÁ77ÁppÁ77Ápp7ÄppÁ‹‹7pÁ77pÁ77pÁ88Æ77pÁ77ÁffÂ771Å77‹1Á77pÃ771Á77ÂffÃooÄ66o6Ãoo=6ÂooeÅoogÁooÁq:;9@D%'Z]aÁbÂcc ÂccÃÃccÁ c]~}€ªÁ}}­­Á¬¬Â¦¦Á~~X\]+a*ÁccbÁccÁbbcÂbb`ÁccÁcÁ``c`‚`Ácc`cÁbb`Ább_^Á]][Á~U|¢¤¢|yÁQQÁŸŸOzwŸwxwLwÁššKwKv›–—ÁÛ–Hœ—”Á Ô”sà  Á——Á—— ›ÁÁ››Ä››Â›Âšš›–ÁÛÁÛÅ——ÁÛÁ——”>tqÁggÂooÃeeÃppepeÍpp7eÃppÁ77Ãpp8eÃppep7ÁffpÁffpf8p7ÃppÁ77ÄppÁ77Á……pf…Áff7f…7feÁffÄ77ÂooÁ66Âoo6Áoo46ÁooÁ66o6o6ÉoogÁ<<:A$OVaÁÂaa*b ÁccÃÂbbÁ`ÄccaX~Y«}Y­¬Â~~¦ÁÉÁɦ~X]ababÁÁccÂbb_`cb_bcÁbbÂcc`‚ Â``c‚b`_ba[Y}§UQÁyyÁ¢¢yUQÁŸŸzÁLLžÁxxŸžxvKLwv–ÁHH—DÁ––Á——×—ÁÂÁ ÁÂÁ Á–– Á––ÁÜà ÁÜÂÁÃÂÁ››Á Á››ÁGGÁ››–ÁÛÁÛÁ——ÃÁÚC—ÁÚÁÚÁ>>;q<Âoo6o64Ãppepe6eÃppÁ77ÂppÁ77ÁppÁeepÂ77pe7Ápp7e87Âpp7ÁppÁ77eÄ77fÃ77ÁffÃ77ÁppÁ77pÁ77p7fÁ77…17ÁffÁ77Áff1fÃ66=Â66Åoo6ÇoogÄoogÂqq;A?%']ÁÂbÁ__bÂÂÄbbÁccÁ ,^~­}ª}­¬Á~~§§Á¦¦{~\]aÁbbcÁbbÂbb_bcÂbbc`bÇccbÁ``Âbb_ba^ÂYYX{UQÁŸŸ¤¢UTzšwOLÂKKwžvKRLšH–H–Á——ÁDD–ÂDD—u”Á ”Á— ÁÄÁÃÛ›š›Á–ÁÜÁÜÁ›ÁÁ––ÁÄÁÁÛÁÁ ––Á —Á” ”ÁÚÁÚÁÚ?•‘;q<Äoo64peÁppÁeeÂppeÊppeÁppÃ77ÅppepeÁppefÃpp7Ápp7pÃ77ÄppÃ77pÁ……ÁffpÁ77pÃ778ÁffpÁff7pÄ66oÁ66Âoo6Áoo6o6Åoo6ÂooÂ559;qÃoop6Á778Éppe7ÅppÁ77Épp7p‹ÂppÁ77pÁ77ÁppÁffÁppÂ77p‹1Â77pÂ77pÁffÁ77pÁff7ÁppÄ77Âffm7gÁooÁ66oÁŽŽÂ66ÃooÁ66ÂoogÁ66oOX]*ÁcÁ``cbÁ_bÄÁbbÂÂccb€Â§§¬Â§§ÁÉÁÉÁ¦¦{~\]kÄbbÁaaÃbbab_ÁaabÄcc`ÅccbbÁaa^]YÁ}}~{QyžLQUQ šžŸwÁKKwššÁxxÂGGvšÄHHÁÜÁHHDu ••Á — –ÂÄÁÄÁÜÁÄÁÄà –ÁÜ–Á – —ÁÚ——ÁÛÁÛ ÁÛÁ——ÁڗÔ”ÁÚ—Á””•9;q5ÁooÁppeÄppeÁppeÄppeÁpp4ÁeeÉppepeÂpp7eÁ77ÅppÁ77p7p…f7ÁppÁ77Á11f7p7pe7Áff7f78Áff7pÁ77pÁ11Â7746oÁ44ÆooÁŽŽ6Ãoo5Áoo5Áqq;ÁrrÁ99Átt>?R]abÁcÁÃcca_bÅccÁÁbbÂba\¦Á{{ÁÉÁÉ©©~\Y\]+*Âbb*ÁaaÁbbÆaab`Á c` Ácc‚`cÂ__Âaa[Á}}W{|yžŸQyxžOŸÁwwxÁššxvÁ››vxÁKKšH–ÁHHv›ÁHHDu• ‘ÁÙ• Ä””Á™™Ä—— – —à ÁÛÄÂÚÁÚÅ— ÁÁÛÁÁڔà ”ÁÚ ÁÙ>9:$F&'(]+Á**bÁÃcc ÃccÁbbÁaabÅcc`bÂ__ÂbbaY~§§©¦X\]kaÁ**ÁbbÇaaÁ]]Áaab , Á``c`ÂbbcaÁ^^a^][}~©|Q¤ŸÁwwœœÂ˜˜Â››v›ÁššxšGvÁHH›šKv›vÁHHCs•”Á••ÁÚ”?”Á ”—”ÁÂÄ—— —ÁÁ””ÄÁ———Ĕ”Á ” ÂÙÁÙÁ Á””ÁÙ>9:5goŽ6ÆeeÃppeÃppeÂppÁeepÁeeÂppÁeeÅpp7p7ÂppÂ77Ãpp‹Å77p7Áffp78Â77pÁ77Á88pÃ77peÂ77pÁffpf7Âoo6o6oÁ66ÁooÁ664ÂooÁŽŽÃoo6Âoo5trqgÁooÃ66ÂeeÂpp7ÄppeÄpp4ÌppeÁ77ÂppÁ77Âpp71‹Ápp‹1Á77p1ÁffÁ77fÁ7717pÂ77pÂ77fp1Ã778Ã77g6Áoo6oÂ66Áoo6oÁ66ÈoogogÁoo5qÁ;;#%'Z\]+ÂaaÁcÅccÆccÁ^^abcbaÁ]]Á^^[Y~ÁXX\)+ÂaaÃ]]€}{¡ÁÅ´{\+*aÄbb_ÁaaÁ^^ab^[Ã]]\}~WQÁOOxKx˜tÁ¾¾ †½Á¾¾¼ÁʾÁÀÁ—Á™™—–HGÁšš›–ÂDD?••Á””tÁ‘‘Ç••Á””?Á””Á—ÁÚÁ ÁÚÁÂà ”Á ÁØÁØÂ • ÁÙ Á”” ÁÚ” •>ÁØÁØ • ÁÙ•>r:<Âoo6pÂeeÂppe4ËppeÍppÁ77pÁ77…Ápp7Âppepf87Ápp‹Á77pfep7Ápp7ÁppÂ77Áeep7ÁppÄ77‹pÂ66Á44Âoo6ÁooÂ66ÁooÃ66Ãoog6<Áqq;’rA&PÃabÂÁccÁËcc_Á]]aÂbb^Á]]^[€ÂXX\)]+aÃ]]€}¨³²±´¢\+baÅbba+ÂaÁ[[Á]][Y~ZW|¤zÁxxš—°ˆÅ¾¿• —–ÂGGÁvv–DHDuÁÚÁCC—”ÁØ“‘ÁØÁØ•ÁØÁØÁ •ÁØ•Á Õ•Á  ” ”ÁÚ” ÁÙ ÁØÁØ ÃÙÁÙ •à ” ÁÙÂØÁØÁ‘‘ ÁÙÁÙÁØ‘r:tÁØ‘ÁØ‘ Æ‘‘ÁÀ•ÁØ Â••ÁÙ Ä””Å •Á‘‘ÁØÁØÃ•• ÁÙÁÙÁ Á••‘‘ÁØÁ ÁØ‘’qÂooÁppeÆppÃeeÅppeÁpp7eÁppeÃppeÑppep7Äpp87pÁ77p7Ápp7p7ÁppÄ77Áppf7pŒ7ÁffÁ66Åoo6ÂoogÈoog<Áqq;q:;9A&L]+ÁaaÁÂ**Á , ÄcccÂcbaÂ]]Áaa^^[\Y~j]+Á]]\Á]]a¨Á;Áͱ²±Z\]aÁ]]abÁaaÁbbaÁ^^kÂ]]Á[[Á]]}ÂZZ~{Qžš›™“¼ÁÀwu»Ä¿”DÂHHvHD—–ÁHHD—ÁÛÁ——”?•Ä‘‘Â’’‘‘ÁØÁØ‘ÁØÁØ ÁØ Á ”ÁÚ””Á Á‘‘ ÁØÁØ ÁØÁ‘‘ÁØ ÁØ Â••Á ÁØÁØÁ×Á×Á‘‘Á ‘9’qoŽ6ÁeeÃppeÄppÁ88pÁ77Åpp78ÄppÁ77ÃppeÂpp7ÂppÁ‹‹pÁeeÄppÂ77pÄ77Áff7Ápp1ÂppÆ77pÄ77ÁffÄoogÂoo„ÁoogoŽÁoo5Áoo5ÁooÁ‘‘ÁØÁØ ÁØÄ Á••ÂØÁØÁ‘‘ÁØÁØ >‘’gÃooeÁppÁeepeÂppÂeeÈppeÁppeÉppeÁppeÁppÂ77ÁppÂ77pÁff7pÁ77pÁ77p7p7ÁppÂ……eÂpp7pÂ77p7p…ÂppÁooÁŽŽÁooÃ66o6e6oÁggÁooÁ55Ä‘‘ÁØÂ‘‘Á’’‘ÁבÁØ •ÁÙ Á•• ÃÙÁÙÁ ••ÁØÁØÂ‘‘Á×Ä‘‘Á Õ•Ä‘‘ >ÁØrqÁooŽpÂeeÃ66Áoo64o6Á446Á44o64Áppe4pÁeeÌpp‹1Ä77pÃ77Áppe7p7fpÂ77pÁ77ÁppÆ771fÃ77pÁff76ÁooÁ66Áoog6oŽÂooŽÃoo5gÂqq:’rÁ99ts?CHLTZ(ÁaÁ**bÁÂÄcc ÆccÁÁbbÂÃbb_^]Á\\[\}ÂXX\](\][]+}Á;ÁͰÁͱZ\[Á]]ÁaabÄaaÁ]][]€YÁ}}XÁ{{W{|yÁžž›–s½ÁÊÇ»¿ÁÁÁÀ”ÁDD”—ÂHH—ÁCC—ÁÛC””ÁØÃ‘‘Â99‘9r’Á×Á••‘‘Á Á••ÂÙÁÙÁ ÂÙÁÙ•Á””•ÁØ‘’Á Á×Á‘‘à •ÃØÁØÃ••>Á99r:Á55<5‘rÁ’’‘‘ÁØÁؕƑ‘ÁØÁØÂÙÁÙ”ÁÚÁ””ÁÚÁÚ” ••Á‘‘Á Á’’ Á×Á‘‘ •ÁÙ ÂÙÁÙÕ•ÁÙÁÙ?•>Árr;ÁØ‘t‘‘ÁØ‘Á×ÁבÁ••ÁÙ ””ÁÙ?Á ”?ÁÙÁÙ>ÂÙÁÙÁ>>Á99‘‘>Õ•> ÁØÁØÃ••‘Á×’q<ÂooÁppeÁppÂeeÃpp6eÄppÁeeÆppeÇpp7ÁppepÁ77Ápp78ÁppÁ77fÁ77p7ÁppÁ77ÁffÉppÁffpÆ77o6o6ÁooÂ66ÂooÁ66oÁ66ÇooÁ55‘‘ÁØÁ‘‘Á99Ñ‘ÁבÁØÂÙÁÙÁ ÁÚ—ÁÛÁÛ—”ÁÙ ”?ÁÙÁ••>ÁØÂ‘‘’ ’Á Á×ÁבÁ×Á×’Á×Á×Á‘‘ÂØÁØ‘’<Áoo64o4ÃppÁeeÆppeËpp17Åpp7Ápp7Ápp4Ápp7Ápp7p…17pÂ7787pÃ778Ãpp7pÁff7fÁ77Áff7eÂ77fÄoo<ÂoogoŽÃooÁ66Âoo6=goÁ<<Ágg;A&OU\ÁaÁ**bÁ**ÂÂÃÁccÂÂÄbb_Äbba]Â[[YZXÂ\\]Á++*b¬ÁÆÁÍÁÁÁÃWX€Á\\Á^^Áaa^Âaa^]^Á\\ÂYY~§©¢Á||O ÁššžG˜” ÁHHÁÜ—“ÁÀÁÚ— œÁ––Á››Ávv–Á——”Á??ÁÚ” ÁÙÁ””?>9Á’’Á‘‘Á’’ÁבÁØÁØ>Á••ÁÙÆ””Áss• Ä””?•ÁØÁ×Á ÁÖÁ Á’’Á Ã×Á×Á‘‘Ã’’‘‘r:qÃooÂppe„ÆppeÃppe7epÂee7ÁppeÁ77ÃppepÁeeÅpp7Âpp7p7pÄ77Âee8Âpp7Á……Â77epeÂ77ÁppÂ77f7ÁffoÁ66Á44oÁ66Áoo6Âoo=Â66Äoo•Á‘‘>•ÁÚ—ÁDDÁÛÁÚ”•Á‘‘Á×Á’’ ÁÖÁÂ’’Á×Á×Á‘‘ÁבÁ×Â’’Á‘‘ÁØ9:qÁooÁeeÁppepeÆppeÉppeÄppeÁppeÅpp7ÄppÁ771Â77Á117ÂppÃ77ÂppÂ77pÁ77pÁ771Á77Áff17ÁppÂ77ogÁoo6ÃoogÄoo„Áooqr’:;Á::r;Árr‘Á>>L'X\)Áaa*ÂÁ**ÃcÂÂÁÁbbÁ**Äbb_aÂ]][YXÁZZXÁ\\ÁXX\]€]€X£|YÂ\\Á€€]Á]]Ãaa]Á\\][ÁYY}X~{©{|ywÁžžŸxKššžwžÁxxšxÁKKxšKžwxšHDÁ——ÁDD—”Á••”?Á••Â>>ÁÙÁÙÃ??Á••‘Ã’’Áב ÁÙ”ÁÛÁ––ÁÛÁ——C”•t‘Á99ÂØÁØÁ‘‘Á×Â’’ Â’’Á×Á‘‘Â’’Á×Á‘‘ÁØ‘9:5oÁ66„Áppe6ÁppÂeeÈppeÁppÁeepeÃppÁeeÁppÁeepÁ77Ápp787pÂeepeÄppÁ……eÁppeÁpp7ÁppÃ77p78ÁffpÂ77fÁ77pf8ÆooÁ66go4Äoog5Åqq;rh9>?E%PVÁ\\Á))Á]]+ÁÁaab*ÁÁccÁbbÁÃbbÁ__ÁbbÁbÁ__bÃaa]€\ÁZZ(\ÂXXÁ\\Â}}YÁ\\Á[[Â\\[Á]]Áaa^ÁaaÁ]]Á\\[YÁ}}ÁWW~UVUyzŸÁzzÁxxšvšxžwÁžžKÂxxÂKKwxšÁGGÁHHD”?•‘‘>”?”ÁÚÁ””Á??•t‘’Á×Á’’ ÁבÁבÁØÁØÁ‘‘•Ô”C”Á??Ô”?•>Á× ÁÁÖ ’ Á’’ Á×’ ÁÖ:Á’’Á‘‘r:5o„ÁppÁeeÃppÁeeËppeÉpp17ÌppÁ77p7ep8Á77pfpÆ77p7Âpp7f7pÆ77pÂ77Çoo6Ãoo6ÃooŽÃooÁqqsD%P\É]]ÅaaÁ**ÂbbÃbbÂ**b*bÁÃbba^[ÂZZÃ\\ÁXXÂ}}Y\Á]]Ã\\)Ã]]a]+Â]]Â\\}Â~~Á{{WÁ{{|y¤OŸžKš›GxšvÄššxšÁvvÁxxN›˜uÔ”Á??ÁÚ—DÁÜDH?•stÁ’’9Ç’’Á×’Á’‘ ÁÙ”ÁÚCÁ——ÁÛÁÛ×—C”?•Á‘‘9’Ä’Á ÁÖÁ ‘9’:5oÁ44Ãppe„pÁeeÁpp6eÉppÁeepÁeeÁppÁeepeÁppepÁ……eÆppepÁeeÁ77ÁppÁ77ÁppÁ77Áee1Ápp7Çpp…f7Ápp…7pÁ77ÂooÁ66o4Â66ÆooÁŽŽogÁ<<Áqq:Árr‘Á>>&RTX([Á))]ÄaaÁ**ÁbbÁaa^Â]]^Á]]^a*bÁ**bÂaaÁb_a+[Á\\ZVZÁ(()a\Á~~XÁYY]]\(Â\\][Á]]Á^^Ã]]ÁYY\}§¦~§WÁ{{U¢QP¤wÁxxKwšGœ–ÁHH–›vGÁššGvÁ››vH–ÁDDH–ÁÜHÁÜ–JD—”Áss>r’‘’:Á’’Á× ÁÖÃ’’ ’‘•?ÁÚC—ÁÛÁDDÁÛ——ÁÚÔ”ÁÙÁØÁ×’ÁÂŽŽÂÆÁÖ Á×9’qoÁŽŽ6Â446eÁppÁeeÄpp4ÂppÁeeÌppÂeepeÊpp7ÁppeÃ77p7p7pÁ77Ápp7p7pÂ77Á11Á77pÁ778ÂppfÂooÁ66goÁ66Êoo<5<ÂqqÂ;;9A>ELTVX(Â\\)Â]]ÁÁaaÁ**Âa*aa+Å]]a]Åaa^Á]]YÁÃZZÁ((\+]\Á~~XÁ\\Á]]Á\\]Á\\Ã]]aÁ]]Á€€Ã}}ZÁWWÂ{{Á||y¤OžšÃxxvHœGv›ÂHHÁ››Ávv›ÁHHÁ——ÁHH›ÁHH——””ÁCC‘‘>9Á’’ÁÖ Á’’Á×Á99Á’’Áב>”Á??×—uÁ??sÁ••ÁÙ ‘Á’’:ÁÖÁÖ5ÂŽÁÁ ’ÁÖÃÁ 9Á’’qÃoo6Âpp4epeÁppepeÃppeÆppÅee7ÁppeÈpp7p7pfÁpp7Ápp7peÇpp…7ÂppÂ77ÄppÁ7787p7pÂooÁ66Âoo6ÇooÂ55qÁ<<ÃqqÁ::rhA&RVZX\ÁÁ]]+aÁÁ**Ább*ÂaaÂ^^Á]]ÁaaÁÁ]][\€Á\\]+Áa[\XZÁ{{ÁZZ~(Á\\)\}ÁXX\]kÁ\\Á]])Ã]]kÂ]]ÁYY}Â~~§{W{©{|yŸz¤ v›KLN—DH›ÁÜÁ››ÁGGÁ››HÁ––ÄHHDÁ——DÁ——”ÁÙ?C?‘‘>Á‘‘Á’’Á×Á99ÁؑÒ’‘>•?”CÁ??ÂÙÁÙÂ??•>tÁ‘‘9Á’’ÁÖÁÖÁ55ÃŽŽÁÁÖÁÖÁ ÁÁÖ Ä’’:qÁooŽÁ446epÃeeÅppe8ÁeeÄppÁ88ÁffÁeeÂppfp7ÁppepÁ77ÃppeÅppÉ77pÃ77fÁ77pÁ7717pÁ77e7178Á66Èoo6oŽÁooÅgg<5Á•• Á‘‘Á×Á×Á99Á×Á×9Á‘‘Á×Á‘‘ÁØ•ÁÙ••s?”Á??”?”?ÁÙ•Ã>>Á×’ÁÖŽÁÂŽŽ5ÁÖ’ ÁÖÁÖ: ’9r:Áqq5ÂooÁee6eÁppeÈppÂeeÁppÂeeÃppÁeeÃppeÅppeÁppeÁ77pep‹ÁeeÁpp78Ápp7pe7pepÁ77pÂeepÂ77e7pÁ77Ápp7o6ÎooŽÊoo<;9?LTVX(Á\\)Á]]Á++aÁ++ÁaaÄb*Éaa^Å]])Á\\ÂXX~{ÁVVÂXX(Ã\\)\ÁXXÁ\\}YÁ\\]Á€€Â]][€Á}}~Á¦¦ÁWW{©iÁ||¤yŸ¡zšžK KLOK›JÁHHÁ––ÁHHGIH–—D——u”Õ•‘‘Â>>‘Á99Â’’Á×r’ Á×Ñ‘ÂØÁØ•Â??sÁ>>•?ÁÙÁ??””?ÁÙÁ••ÁØÁ×ÂÖÁÖ5ÁŽÁ55ÁÖ’Á::ÁÖÁÖÁ’’Á::Á55ÂooÁpp6eÂppeÃppÁeeÄppÁeepÂeeËppÄ77ÁppÁeeÁppÂ77pÁeeÂ77ÃppÁ77pÃ77Â11mfeÁpp7p71Á77p7pogÉooÁgg6Èoo<5Á<?D&PTZXÂ\\Á]]Á++ÁÂ**Åbb*aÄaaÃÁ[]Á€€Á\\€YXZÁVVÁZZXÁ\\XÃ\\Â}}ÁXX}\€][Á]]€\jÂ~~Á{{©Á{{|Áyy|¥zÁ  œžÂzzÁyyŸšIÃHHGvHDÁCC”Á??••‘¿‘Á>>Å‘‘9Å’’9’Á×Á‘‘ÁØ>ÁØÁ>>•?”ÁÚ”C”?Á””Â??•ÁØ‘ÁØÁ‘‘Á×’ÁÃ55ÁÖ:ÁÖÁÖ’9Á’’ÁÖ’ Â’’:gÁooÁ44Á„„e6ÂppeÁppeÅppÁeeËppÁ77pep7ÁeeÅppeÂppÁeeÄppÂ77pÁffpÁ77ÃppÁeeÁ77Ápp7ÁffpÁ77ÁppÁ77ÂooÁŽŽÁoogÃoo<ÃoogÄoogÂ<C&R'ZÂXX(Á\\Á]]Â++Ã**ÂÁbb_aÅaaÄaaÁ]]ÁÁYYXZWÁVVÂZZÊXX~ÁZZX\À€j}¦{ZÁ{{Á¢¢|¢Áyy¤¡wÂÈÁÈž¤yw ÁwwvÃHHGH–——ÁDDÁÛCÁ——ÁÚÁÙÁÙÕ•ÁØÁØ‘ÁØ‘Â×Á×9‘Ã’’Á×9‘9‘‘>•ÁÙ?s•Á>>•ÁÙÁÙÄ??••> ÁØ9 ÁÆÁÁÖÁÖ:Á ÁÖqÁÖ ’:<ÁooeÄpp6ÁppeÂppeÇppÁeeÁppÁeepepÁeeÇppe7Ápp‹pÁ77‹7p7‹Äpp87peÂpp7pÍ77pÃ77ÁooÁ66Æoo6ÁoogÁoogoÁ55oÁ<•ÁÙÁÙÃ??Á””Á??•Á??”ÁÙÁÙ••>Á‘‘:ÁÖŽoÁÃŽŽ5ÁÁÁ5ÁÂ’’5ÁooÁ44„ÁeeÁpp4ÄppÁeeÃppÂeeÂppepÂeeÁppeÁpp7ÆppeÁppÁeeÁppÁeeÄppÃ77Âpp…fÄppeÄppÁ……p7p7‹ÂppÇoo6Áoo6ÁggÇooÂ<%PVZX(Á\\Á))Â]]+ÂaaÁ++aÆaa+Ç]]Ä\\Y(XZVÁ||VÁZZÄXXÁ~~Z{¨|{Á~~}€}X~§Á¨¨Á||Á¢¢£y¥Á¡¡ ³Áyy¥¡ H˜Á––H–ÁHH–—ÂCCÁÚÁÚCu?••ÁØ>Á••>‘Ä99’ÂÖÁÖÄ’’9ÂØÁØtÑ‘ÁØÄ>>ÁÙÁ>>••ÁÙ•ÁÙ•ÁØ‘9’ÁÖÁÔ4ŽÁÔÁÔÁ5ÂÁ55ÁÖÁÖÃooep46epÂeepeÃppeÂppeÁppÁ77ÆppÂ77ÂppÁ77ÁppÁeeÆpp7Äpp7f…ŒÁppÂ77p7ÁppÅ77p…Ápp7Âpp78ÂooÁ66go56Êoo5ÂoogÃooÁ<ÁØ>Â99Á×9‘9Á×Á×:qÁÆŽŽÁÁŽ5ŽÁ5ÄooÁ„„e„ÆppeÄppÁeeÄppÅeeÃppe78eÅppeÃppÁ……ÂeeÁ77eÃppep7p‹p7peÁ88Â77Ápp‹78Â77pÂooÃ66ÅooÁŽŽÆoogÃooÁgg<;q;A&OTZX\)Á]]Æ++ÃaaÁ++]Á[[Ê]]ÂÁÁ\\YZVÃTTVZXZÁWWÁZZÁ~~¦|i~{~~§¦{¨¢Ä££¥¡Á  ¡¢¥¡x³Á  œÁ ›ÂššÁxxGD”?Ä••>Á‘‘ÁØ >Á••ÁØ ÃÙÁÙ”ÁÚÁÚÂCCÂCCDÁÛÁÛÁCCÁÚÂCCÁÚÁ??ÂÙÁÙÂ>>Õ•?Á>>‘Á×:Á55ÂÁŽŽÁ44Ž‹ŽÃÔÁÔŽ5oŽ4ÂŽŽÁ55oŽ46oÁ44Åpp46pep6ÃppeÅppeÆppÁeeÉppÂ77ep787eÁ77pÁ77pÁ77ÁppÃ77pÁ77pÁ77pÅ77ÁffpÈoogÂoogÈooÁggÂoo<ÂqqÁ;;$IRTVX(\Ã]]Â++ÂaaÁ++Ã]]Á))Â]]\Ã]]Á))Á]]Á]Á\\YXZVQyUi|VZXÂZZ§ZÁ~~i¨{¦Â~~Â{{¨£Á¸¸Â££¥Á¡¡ÁÇÁÇ¡ ÁÈÁ³³v™Á›šÁxxKÂvvHuÁ‘‘Á““Á‘‘•ÁÚÁÚDÁHHÁ&&ÂHHDFCuÂEE?”ÁEEÂ??uÁ””ÃCCFDFÂDDÁÛÁDDÂCCÁÚ?Á>>ÁØÁØÁ>>Ñ‘Á×5ÂŽŽ4ÂŽŽoÁŽŽ4ŽÁŽ4ÁÔÁŽŽo5ÁooŽo6oÂee6Ápp6p7ÁppeÁppÄeeÁppeÁppeÃppeÁ77peÂppepeÃppÂeeÂpp7eÁppeÁ77Åpp7p78Âpp7Ápp7ÁppÁ77Ápp‹Á77p<ÁooÁ66g5ÄoogÅoo5ÃoogÂoog5>• >Á••>Á••?Á••Áss”ÂCC?>ÁØÁØÁ×Á× ÁÖÁÖ5Á54Ž4ÁÔÁÂÂÁŽŽ‹ŽÃooÁ66p4peÃppeÈppÂeeÁppeÁpp87ÂppeÃppepeÁ77Äpp4ÅppÁ77Äppe8ÁppÁ77eÁ77ÂppÈ77ÁffÁ77pogÆoogÁoogÉoog>•Â>>Á‘‘ÂttÁØÁØÁ>>••s•Áss•Á??ÁÙ>AÂ×Á×:ÁÖ5Ž5ÁÖÁŽÁÁÔÁÔÂŽŽÁ66Ápp4Ãee6ÃppÅeeÃpp4peÃppeÂppeÄpp7Ápp7Äpp87ÅppÁffÂppÁ77p7ÄppÁ……ÂppeÁppmfÁppÂ77pÁ……o5ÐoogÃoogÁooÂggÁqqÁ;;>C&PTÁXX(\ÁÁ]])\Â((Á\\Á))Ã]][Á))Ã\\(Æ\\}ÃXXÃZZVÂPPQTÁVVÄZZÁ{{ZiÁ||¨¦Á¨¨Ä££¥¸·¶ÁÌÁ³³µ ¶ÁÈÁijÁ™™–xwxœ–—Á””•‘’Áqq’ÁבÁ99r’r’r9Á’’Á::ÁÖÁÖÂ::’:Á99Á×Á‘‘ÁØÁØÁ>>ÁØÁØ‘ÁØÄ>>Á‘‘ÁØÁÁ‘‘ÁØ>••>Á‘‘r’Á99‘9Á×Á×Á’’Â::qÁÖÃ’’:5Ž4ÂÔÁÔ4ÂŽŽ4peÃppep6ÁppepeÃppeÁppÂeeÁppÁeepÁeeÇppeÇppÁ77ÃppÁ77pÃ77ÁppÂ77Ápp78Â77ÁppÁ7717‹Ápp7pÁffÂ77ÂooÁ66ÈooÁ55Ãoo6Âoo5Â<>ÂØÁØ9Á×Á×’rÄ99Ñ‘tÁØÄ‘‘tÄ>>ÁØÁØ>•>•>tÁ>>•ÁØ>‘9’qŽÁppŽ:qÁqÁÖÂ’’5Á44Á‹‹ÁÕÁÔŽ4oÃppÂ66eÇppeÁppÂeeÆppÂeeÅppÁee7epeÄppeÁppepepe7pÁffpfÁppÁeepÁ771pÂff7ÁppÁ77Ápp7fÁppeÁppÁgg>@$Á>>@Â>>Á••ÅÙÁÙÁØÂ>>‘‘9‘‘Â99‘‘>•>ÁØÂ‘‘>t‘Á×’ŽÂ44ÁŽÂ::’Á×:o‹ÃÕÁÕ‹ÂŽŽpÂeeÁppÂeepeÁppÅeeÆppÁeepÁeeÅpp7pepÁeeÁpp8Ápp7ÁppÁ77ÅppÁ77ÂppÁ77ÊppÇ77ÁppÁ77;Árr’:;Á::;<;qÄ;;<ÄooÁgg5oÁggqÁ<<;9>ENOTÁVVZXÁ((Á\\Â])Ä]][ÂÅ\\YÄXXÃÂXXÁ\\XÂVVTzÁRRPTVÅ{{¨Â||£¸¥Â··ÂµµÃ¶¶³ÁÆÁ´´³Â™™ÁÄÁÜÁ˜˜D—˜—Á””—C?•Á‘‘“Â’’“Ä’’r’:ÁqqÃ’’r‘9tÁ‘‘ÁØ>••ÁssÂ??ÁÙÁÙÂ>>ÁØÁ‘‘Â99Ñ‘ÁØÁ>>t9’:Á×Áב’:<ÁÂÁÖÁqqÁ::q54ÁÔ‹ÁÕ‹pÁŽŽeÂppÂee6ÁeeÁppeÅppeÁpp6Áee46ÁeepÁeeÂppeÂppeÄppeÃppÃee7Äpp‹Á77Âppe87fepÁ77eÄppÂ77pe8fÁpp7ÂttÁ99ÂAA9AÁrrÂAA>tA9;qÁggÂoogÂ<ÁÙÄ??ÁÙÁÙ>ÁØ9‘Á×Á99Â×Á×9Á×Á99r’Ñ‘ÁØÁØÂ‘‘Á>>Á••Ã>>ÁÙÁ>>È‘‘t9:ÁÖÁÖÅÁÖ’Ã::54‹ÂÕÁÕÂÔÁÔÂŽŽÊppÁeeÃppÂeeÃppeÂppeÃppÁ77ÉppÄ77ÃppeÁppÁee8Á77pÇ77Ápp71Ã77pÅ77p7Áfft>••>Á••Â>>s?ÁssÂEEÁ@@trÂoo5Âgg<;A>t>$%OTVÁZZÁXX(\)]Á)])[Ã\\YX}XÅXXÁXXÅZZÁÂZZViTPzOyÁTTU|UV{¨|£¥¡µ¡µÁ¶¶³¶³ÁÆÁÅÁÅÁÆÁ´´ÁËÁÃÁÄ ÁÂÁÂÁ™™˜D™Á””C”•Á““rÄ’’;rÁ‘‘Á>>s?uÁ””ÁÚ?••ÁÙÁØÁØ>‘Á×Á’’‘Á99>‘‘t‘ÁØÄ>>Á••ÁÙ•ÁØ‘9ÁØ‘9Á’’Á×Á::ÂÁ55ÁŽŽo5ÁÖÂ’’;qŽ41ÁÕÁÒÁÒ2ÁÕŽÃoo6eÇpp4epeÂppÁeeÁpp7ÁeepeÁppÂeeÁppeÃppeÂppÃeeÁppeÁppÂeeÂpp7Äpp7eÃppepÁ7717Âpp‹7Ápp7pfpÁ77•ÂÙÁÙ Ä??Á””ÁuuCÂDDCus‘’Ãoo<;A9ÃrrA>F&L'TÁZÁXÂ\\)])Á\YÁ\\ÇXXÅ~ÄZZÁZZVi|ÁTTQÂPPÁzzPTÂ||i{|£y¡Âµµ¶Á³³ÁƳÁÆÃÅÁűÁ´ÁÄÁ––œ–˜Â——”u™uÃDDÁÚ?ÁØÁØ‘9Â’’Ã::rÁ×Â’’9‘Á>>•ÁÙÕ•tÁ>>•Á>>ÁØÁØÁ‘‘9‘9Á‘‘ÁØÂ>>ÁØÁØÂ>>Átt‘9r’Á::5Á55Á44ŽÁ55Ã::54p‹Â22ÁÒÁÁÕp‹pÁ44ÃooÁ44ÅeeÅppÂeep4Ápp6epÁeeÁpp6eÁppÂeeÁ77ÌppÂ77pÁ77Æpp7p7Ápp8p7eÁppÂ77‹7pÂ77pÂÙÁÙ ”ÂCCÁÚCÁÚ—ÂDD–ÂHHJDut’q:Árr’qÁ<>•>‘Á99Á’’rÆ’’Ñ‘t>•>Ñ‘Á>>ÁÙ•>Á‘‘Á99‘ÁØÁØÂ>>Á99‘ÁttÁ>>9rÁ’’:Á55ŽÁ55ÂÂ::qo‹ÁÕ2ÁÒÂÁÁÕ‹p4ÁeeÂppÄooÃeeÁppeÁppÁeepÂeeÆppeÁppeÃppeÂppeÄppeÁppeÁppeÁppeÂpp7pe87pÁee7pÈ77p18e…Á77pÁ ÁÙÂÚÁÚCÄÛÁÛÁDDÁÜHÁGGÁvv–—C•r>‘9Á×Â’’ÁבÁ×Áׯ‘‘“9>Á••Á‘‘9Á‘‘t>Á••>ÁØ‘>ÁØÁØÂ>>‘9Á×Á×t‘9Á×’ ÁÖŽÁ55q:ÁÖÁÖÁ::54ÁÕ2ÁÒÁÒÂÁÒÁÁ‹‹4ÂppeÃppepÁ66o=6ÇppÁeeÂppeÂppeÁppeÂppep7ÇppÂ778ÁeeÁpp7eÅ77Ápp18Á77Ápp7Ápp8Ã77fÁeeÃ77pÁØÁ ÁÙÁÚC—ÁÛÁÛÄ––ÁHHGÂNNvH—s‘qÃoogoÁqr9>@FI%R'TÁÁZZXÄ((Ã\\Y\YXÁÁZZÃWVÂTTÁVVWZÁZZWVWÁZZVÃZZVTÁOOÂPPTÂ||y¥µÁ³³ÁÆÂÅÁÅÂÆÁÆÁÅÁÅÁÀÁÍÁÍÁÁÁ±±Å™™”Á•• ÄuuÁÙ•>tÁ‘‘Â>>‘9Á’’Á‘‘ÁØ>Á‘‘Á×r’Ä‘‘Á99rÂ’’rÃ99Â>>Ã99Â>>•>t‘ÁØÁØÂ>>9Á’’9>9:q:ÁÖ5ÁÁ::Á’’:542ÃÓÁÓÁÁÒ21‹ÄppeÅppÂeeÂ664pÁeeÁppÂeepeÂppÁeeÁppeÁ88eÂppÁ88ÃeeÁ77ÂppÁ88ÁppÁeeÂppepeÃppeÂppÁ88pÂ77ÁppÁ77pf7ÃppÁ‘‘ÁÙÁÙÁÚÁ——ÁÛ–ÁDDÂÜÁÜHÁGGÁKKxvHDu•qÃooÂgg?DIMPTÁVVÂZZÂXX(\Á((Â\\ÃXXÂZV|UVÄZZWÃVVUÂVVZÁVVTyÂPPRzQÂTTy¥µ³ÁÆÁÆÁÅÁ±±ºÂÅÁźÁÁÁÍÁÍÁÁÁ±±™˜—™•Átt ””•Á>>•>Á‘‘>ÁØ‘Á99‘tÁ••ÁØ‘Árr‘t>ÁØÁØ‘Â99‘‘9Á×Á×Árr’Á::Â’’9tÁØ>ÁØ‘Â99Á‘‘>ÁÙÁØÁØÂ‘‘Á99’:Árr‘;Á::Âq:’:Ž12ÅÓÁÓ27Ãpp‹ÁppeÁppÁeeÁppÁeeÂppÁ66o6Áee7Îppep7ÁeeÁpp7ÂppeÄppÂ77ÁppÃ77Ápp…fp7…f7ÂppÄ77ÁppÁ77pÂ88Á×>ÁÙ?CÁÛÂDDÂÜÁÜÁHHGN%ÂKKxvHF”9qÁggoÁggÁ<EJNRPTÁVVZÁXXÁÁXXÄÂXXZVTUZXÃZZÂVVÂVVÁUUÁVVÁWWÁVV|ÂTTQzRzÂPPÁyy¥¡¶´ÁÅÁűŲ²ÁÁÂÍÁÍÁÀÁ±±™—Á±Á Átt•”u•Á>>Á••9r9Ä‘‘’r‘tÃ>>Á‘‘’Ñ‘9r‘9“’Á99rÄ’’Á×Â99rÁ‘‘tÁ‘‘Á99‘‘>ÁÙ@‘Á99Á×9ÁrrÁ’’Á×’Ã::’:<412ÄŠŠÁÓÁÓÁÕÁ‹‹ÁppÁeepeÂppÄeepÂeeÂppÁeeÁ66oÃeepÁ77pÄeepe78Áee8ÅppÃeeÃppeÄppepÁ……ÂppÂ88ÁffÂ77ÁppÂ77epÁ77…9ÁØ?ÁÚCÁDDÁHH›ÃGGK%MÂKKGHDCtogÁ<ÁØ9Á׿Á‘‘9‘9rÁ99‘Átt‘ÁØÃ‘‘ÁØ‘“Á99‘Á99Á’’Á::Á’’Á×Ä99’9Á‘‘Á>>tÁ‘‘Á99>•Á>>Á99‘9Á×Á’’Á::Á’’Á×’42ÁÁÓÁÓŠÁÓÁŠŠÁÓÁÓ2‹ÁppÁeeÄppepÁeepeÁppeÆppÂeepÃeeÃpp8Â77eÆppeÁppeÁ88pÄ77ÁeeÁ77p7Âpp7ÄppeÂ77ÂppÁff1787p78>ÁÙ?CDJÁHH&ÃGGÁÝÁKKMÁLLžšG–C•rÁoogqÁggÁooÁ55q;r>?JNMP'VÁZZÂÂXXÁ\\UVÁZZÁZZWÁVVÁVVÃUUÄTTÁPPTÃVVÂTTÁPPRÁMMRPÁzzwxœ™±ÁÀÁÁÅÍÁ;ÁÍÁÁÁÁ“• Á••Átt•sÕ•sÁ••>ÁØ9rÂ>>‘‘tÁ‘‘Á’’rÁ99r’rA>ÁØÁ‘‘>ÁØ‘r’Á99Å’’Áׯ99A‘ÁØÄ>>Á99‘>?Â>>Ã99Á×Ã’’qo1ÁÒÆŠŠÁÓÁÓÁÒÁÒ2‹ÁppeÂppÁeeÂppepÁeeÁppeÃppÄeepÂeepÁeeÅppÂeepep7ÄppeÁppÂeeÂppeÂppÁ77ÁppÂeeÁ……ÃppÁ77Ápp…fpÁ77pfpf…”ÁÚCDÂHH&HGÁÝÁKKÁMMÁLLMwKš–—s‘<Äoog<Á55Áqq;t@CGRPTVÂZZÃXXVÁXÁZÁWWÁZZÂVVÃTTÁUUÁQQTQyÁPPQUÁVV'ÅTTRÁxxMÁwwRwxœ™±ÁÀÁÀ²ÁÁÁ°°ÂÍÁÍÁÁÁÁÁ““ÁÀÁÀtÃÀÁÀÄ‘‘Áב>ÁÙ>‘‘>@>ÁØ‘9‘Á99Ã’’9Á×Â’’9t•>‘‘Á×Á’’rÃ’’Á×Â99Á‘‘9AÄ>>‘Á‘Ã99Â>>t‘Ã99r’:Ž1ÁŠŠÁÐÁÐÊŠÁÓÁÕ‹ÅppeÁpp6ÂeeÃppÂeepeÃppeÁppÁeepÃeeÃpp7pÄeeÃpp7Âppe7pÁeepÂ77eÂpp7pÁ77ÂppÁ77‹Ápp7fp78Ã77pÁ77à ÁÜÂHHI&G%ÁKKÆLLžšH—•’ÁggÂooÂggÂqq;rA>E%R'TZÂZ{VÁZ(XÁZÁWWÁZZÂVVÇTTyOPQÃTTQPÁTTPQÁTTzÁMMLÂNNÃxx›˜ ™± •ÁÀÁ¿¿ÁÁÁÁÁ¿¿ÁÀÁ••Á““tÆ‘‘rÁ’’t@?sÁ>>•>•s•Á‘‘9Á‘‘rÂ’’Á 9Á×’r’¿t>‘Á×:q’9Árr9Á×Â99Á‘‘9>Á‘‘ÁØ>‘ÁØÁØ>‘Á99tA9>9Á‘‘tÁ99r:<1nÊŠÃÐÁЊÁЊÁÓ2Á‹‹peÅppÉeeÂppÆeeÂppeÂppÅeepÁeeÃppeÅppeÁppÁeeÅpp7ÆppÁ……ÅppÁ77pe7Áff7pÃÛ›ÁGGÂKKMÆLLžxH— ’6eÅooÃqq;rt?NMPTUÂZZÁVVÁZÂXÁÂZZÂVV|TQÄTTÃPPTQÁOOÁPP'ÁPP'ÁTTzLP'wÁxxÃvvIÁHH–˜™ÂÂÁÂs •“ÁÀ• tÁÀÁÀ“tÁÀÁÀt‘“ÁrrÑ‘•Ä??••Â>>‘Â99Á×’ÁÖÁÖ: ’rÁ99Á’’Á99ÁØ9Ã’’Á×Á×9Á×Â99t>‘ÃØÁØ>9tÁ>>tÁØ‘tÁ99AÂ99Á‘‘Á99EFNRPÁTTÃVVZÃXXÁÂZZÁVVTV|TPÁ''QÁPPÂQQTQPROPQÁPPÂTTÁRR'TPMLMNGvH–ÁHH–ÁDDÁ™™D™—ÁssÁ s••Átt‘“’¿“Á’’t>sÁ>>•sÃ??s•Ã>>•ÁØÁØÁ99’Ã::Ã’’Árr:9ÁØÁØ9Ã’’Á99‘Â99Átt‘ÁttÁ‘‘Á99Âtt‘Átt‘Ä99‘9Á×:54ÁÒÁÓÁŠŠÁЊÁˆˆÁÐÁÐÁŠŠÁÓÁÁÕ‹peÅppÂeepÂeepÁeeÂppÄeeÁppeÃppeÁpp8ÆppepÁeepÁ77ÉppÁ77ÂppÁ88eÁ77p7Áff7ÂppÄ77pÁeepÁ77eÂÇÁÇÁžžÁÈššÁÝÁžžÈLLK›—•ÁÖ‹216ÁooÂ<>s•Á>>sÂ??ÁÙÁÙ•ÁÙ>ÁØÂ>>t‘9Á’’ ÁÖ’:’Â::’r’r‘Á99Á×Á’’É99Á‘‘Á99tÑ‘t9‘9ÁrrÁ’’r:512ŠÁˆˆÁÐÁŠŠÂÐÁÐÁŠŠÁ‹4ÈppÂeeÁppÁeepepÁeepÃeeÁpp8eÁppÂeeÁ88eÂppeÆppÁ……peÂ77ÁppÂ77ep787Ápp7f…Ã88Ã77ÂppÂ77p7pÃ77É ÁÜÁÜÆGGÁNNH–”ÁØ23pÂoo5?CJ&MOÂPP'ÁVVÁZZÁZZÂÂVVU|TÂQQÄPP'ÂPPÁRRPOzRÂPPTÁPPTQPzPOzÂRRMÁNNH–DÁuuÁ””•s””s••‘‘Á¿¿Â’’‘•?•Â>>s?••Å??Á••Ã>>t9Á×’rÁ::ÁÖÁÖ:’rÃ’’Ì99tAÆ99‘A9Á‘‘Ä99r:5pÁÓŠÁÐÃŠŠ»ÁÊŠÁÁ½Že4ÂppÁeeÂppepÁeepÃeepepÃeepÂeepÁeeÂppeÁppÂeepÁeeÂ88Âppe7ÁppÁeeÁppÁeeÁ77e8eÁ77peÁppeÂppÂ887p78e78pÂ77pÁÔÁÔÄÂÁ::ÆÂ>>ÁØ:2n3mÂppÁ771Á33mÁ11769>$FINMROPÂTTVÁÈVV|ÁQQyÁOOÃPPÁOOÁRRLÂRRÁOOÂPPOP'T'PyPÃRRLMÁNNvID—C?s•s?”u”Á??Á••‘‘ÁØÂ>>•ÁÙÁÙ?Á••>ÁÙ?••?Á••Â??•>•Â>>t‘9Á×Ã::’ÁÖ:r’Á×:’Á::Ä99rÂ×Á×É99Á‘‘Æ99‘Á99ÁÔ2ŠÁÐÁÐÁˆˆŠ»Ã»ŠÂ»»¼ÁŽŽ6ÃppeÂppÁeepÁeepeÃppeÂppeÁppeÄppÁ77eÁppÂeeÂppeÁ77Åpp7ÁppeÂpp7Ápp8Á778p…eÄ77pÅ77pÁ77ÁppÂ77Æ//ÁÑÁ//‰Ç..Â00ÁÓÁЈÁ..0ÁÓÁÓÄ00ÁÐÁÐ.Á00ÁÓ3234"A$JÁ&&%RÁOOÁPP'ÄTTÃVV|TQPÄOOPÁOORÁMMwÈRRÁPPQÁPPQyPÁzzRMKxGÁIIHÁDDÔ”ÁCCuC”Ã??Á@@Á••Á??ÂÙÁÙÁ??sÁ••ÁssÁÙ•s•Á??ÁÙÁÙ•>sÁ••>ÁØ‘Á99Á×’Á::r’9rÁ’’rÃ’’Ä99Á’’Ârr9ÃrrÂ99Ñ‘9t‘>ÁØ‘9;62ÁŠŠ0ÁˆˆÁŠŠ»Ã»ÂˆˆÁ»»ÁÊÁŽŽÁeeÁpp4ÁppÃeepÁeepeÃppÈeeÂppeÁ88ÁppeÁppeÁppÁeeÁppÈeepÃeepÁ77pÁ77ÂppeÃppeÁ88ÄppfpÁeeÂppÂÁÎÁÎÂ--ÃÁÎ-ÁÎÅÃÎÁÎÂ//ÃÎÁÎ/ÁÎÁÎÂ//.Á//.Á0037!EJ&ÁNN%ÁMMROÁPPQTÁQQÁTTQÂOOzÁRRÃOOLMLÆRRÁMMRPTÁSSQPSRSÁRRMKNvIvHJDCÁÚFÁCCuÁCCÁÚ”Â??Å•• ?ÁÙÁÙÁ??ÁssÁ>>ÁÙ•ÁssÁ••>?Á••?••Â>>Á99’Á::9‘9Ä’’rÁ×Á×9rÆ99Á×’:Á55 ’Áב•Ã>>•‘t9:qpȈÁшˆ»ÁÁ»»ˆÁÁˆˆ»¼ŽÈppÁeepeÁppeÂppÁeeÂppÁeeÃppÄeeÃppeÄpp7pÂeeÂpp7Ãpp7ÂppepÁ77epÁeeÁ77ÂeepÂ7787ÂppÂ77Á117ÌÎÁÎÁÎÁÎÁÁÎÁÎÁÏÁÏÁÎÃÎÁÎ-ÃÅÎÁÎÁÎÁ//ÁÑ.017"EÁCC#D&N%ÂLLROÂPPOÂRRPOzRÁwwÁRRÁLLÃRRÁMMRÁPPÁRRPÄRRÂMMxNvINHJDÆCCu”Ã??Æ••?•ÁÙÂ??ÁÙÁ>>sÁ??s•ÁÙs?Á••?sÁ••Á>>Â99’Á×9‘9’ÁrrÁ×9r9Á;;9’:’9Árr9’:Ž‹2m‹Ž’‘tÕ•ÁttÁ99Á×5pnŠÃˆˆˆˆ»ÁÊÁÊÁ»»Ãˆ»ÁʽÁeeÁppÄee6pÁeepeÁpp6ÁppeÁppÁeeÁppÁeeÂppeÂppÃeeÁppeÈpp87e87ÁppeÁppeÁppepÁ77pepÁ77eÁpp87ÁppÂeeÅppÂ..ÁÑÁÑɉ.ÂÑÁщÁΉÁÑÁÎÁÎÁÑÂÎÁÎ/ÁÎÁ//ÆÎÁÎÁ//ÆÎÁÎ/.ÁÐÁÐÁ00ÁÓ4;;!9$JIÁGG%MRMÁKKMRLRÃMMÁLLÃMMÁNNÁLLRÁMMÄRRÄMMNÂGGNHÁDD——C—Âuu”sÁ••?s•Á>>Á••ÁÙ•?•ÁÙÂ??Á>>Á••ÁÙsÁ••>$Á••Å>>‘Ä99‘Á99ÁrrÂ99Â×Á×9rÂ99Á×’:5420ˆŠŽ ‘tsÕ•>‘’ÁÖ1ŠÁщˆ»»ÁˆˆÄˆ»ŒÅppeÂppÄeeÂppÃeepÁee6epÁeeÅppeÁppÁeeÁppeÁppeÂppe…pepe87…feÁ77Â887Áee7pepÂ77pÃ77f7ÂppÄ77É..ÁÑ.ÁˆˆÁ..0ÁÐÁˆˆÃ..ˆÁÐÁ00ˆÂ..Áˆˆ.ÁÑÁÑÃ..ÁˆˆÁ..Á00ÁŠŠÁ00ÁÓ1Â447n27"9A$ÁNNÁIIvxÁMMÁKKMKMÁLLÃMMNMÁLLwÁMMRÁLLMKÁMMRMÁNNxÂNNHÆDDÂCCu?s>Á••sÁ••Á>>•ÁssÁ••sÕ•?•s?Æ••s•Ã>>‘9‘‘Å99Á‘‘tÄ99’:Ž‹ÁÒ.Á‰‰ŠŽ Á‘‘Õ•t‘9’42ÁÓˆ‰ÂÎÁÎÁлЉÆˆ21Â77p7ÁppeÁppepÂeeÁppeÁppÂeepÅeeÁppÃeeÁppÂeepeÂppÁeeÁppeÂppeÃppeÁ77ÂeeÂppepÁ88eÁ88eÄpp8Á77pep…Á88ÁÎÁÎ/ÃÎÁÎÂ//ÃÎÁÎÁ//ÁÑÆ//ÁÑÃ..ÂÑÁÑ/.ÁÑÁÑÃ..ÁÐÁ00.0ÁÓÁÓÁ00ÁÓ23m2ÁÓÁ00Á2237<;9@EÁDDCDHÂIIG%MÁKKÂMMKÁNNÂMMKNRÂMMÁKKÂLLÁKKMxÁNNvHDÁHHÂDDFÁCCFuÁ??•Á>>sÄ••>s•Â>>Õ•>•Ã>>Á••Å>>ÁttÁØtÅ99Á×Á×9‘Á99Árr’:41ÁÓÁ00lÁ//Áш» ÁÀt••tÁ‘‘’ÁÔ1ˆÁÎÁ--ÃÏÁÏÁÑŠˆÁÎÁÏÁÏÁÎÁŠÁÓÃ00ÄÓÁÓÁÓ2Ánn2Á33mÁ223mÁ33mÄffÁ117ÁffÁ77Ápp7Áppep7ÁppeÁpp78e78eÅpp8Á77ÁppepÄ778Ã77p8ÂppÄ77e×ÎÁÎ/ÁÎÂ//ÈÎÁÎÁ//ÁÑÁÑ.ÁÑÁÑÁ..ÁÑÁÑ.ÁÓ0ÁÓ0ÁÓ0Ã..Ã002Á3376:Átt•”—FÁDDJHGNMNÁxxN&NxKMNMRÁMMLÁMMRÅMMxÁNNHDHÁJJÂDDÁCCDuÁ??ÁÙ•Á>>•sÁ••ÁÙÁ??Ã>>••sÄ>>••Â>>•Á>>ÁØÇ99r’<5Á445pmÁÒŠˆÁ‰‰./ÁÎÁм ÁÀÁ‘‘ÁÀ‘‘“’o4ÁÔŠ/-ÅÏÁÏÁÎÁÑÁÑÁÎÅÏÁÏÁΉ/ÉÎÁÎÂ//ÄÑÁÑÆ..0ÁÐÇ00ÁÓÁÓÂ2Änn2nÂ33mÁ332mfmÂffÁmm71Â77p7fÁ……7f8ÁppeÁ‹‹8ep‹pÁ77p7p×ÎÁÎÁ//ÂÎÁÎËÎÁÎ/ÁÎÂ//ÁÎÁÎÁÑÄ..‰/ÁÎÁÎ/.Á//Á00ÁÐÁЊÁÓ2pqt•s>•?EFDHIÁNNÂGGÁNNKÁNNMRÂMMNMLÄMMNÁGGvÄHHÂDDCuÁCCuÁss•>•Ä>>••Â>>•Á>>•È>>Átt>Ä99’ÁÖÁ55Á66422nÁÓÁÓ0ˆÁ../‰‰ÂÎÁΈ»‹¿‘“Ñ‘’q5ŽÁ‹‹2ÁÓ/ÆÏÁÏÁΉÆÏÁÏÁÑ/-ÔÏÁÏ-ÃÏÁÏ-ÁÏÁ--ÁÎÁÎÁÁ--ÂÎÁÎÈ//Á..ÁÑ.ÁÑÁÑÅ..ÁÐÅ00ÂÓÁÓÁÓÁÓÁn3Ãnn2Ã33ÃmmfÄÎÁÎÁÁÎÁÎ/ÞÎÁÎÂ//ÂÎÁÎÁ//ÁÑ.ÁÑÁÑÁ‰‰Ã//ÁÑÁ‰‰.Á‰‰ÁÑ.ÁÑ.ÁÐnprt9ÁqqrtsÁ@@IvIHÁIIÁNNvNMRÊMMÂNNIÄHHÁDDJFCu”u?•?ÁssÄ••Æ>>•È>>Átt‘Á×’:Á55Ápp412ÁÓÂ00Ä00ˆÁ00Á..ÃÑÁшÁÑÁ‰‰ŠŒ“Á‘‘Á““‘¿’Á޽ÁÑÁÎÂ--ÃÎÁÎ/ÁÑ/ÁÎÁÎÃÁÎÁ//ÁÎÂ--ÁÏÁÏ-èÏÁÏ-ÍÏÁÏÁÃÎÁÎÁÄÎÁÎÂ//ÁÎÁÎÁ//.ÁÑÅ..ÊÎÁÎÁ//ÝÎÁÎ/ÂÎÁÎÁ//ÂÎÁÎ/ÇÎÁΉÁ//‰ÁÑÁ//‰Á..5r735:qÁ77!ÁJJHIÁNNIÁNNÃMMxKNÄMMÁNNvHIÃHHÂDDFCu?CuÁ••s•Æ>>ÁØÁØÈ>>‘‘tÁ99:5472ÃÓÁÓ0ÁÐÁ‰‰/ÂÑÁÑ.ÁÑ/ÃÑÁÑÁ//Á..‰ÁÑ.ÁÑÁÑÁˆˆ»½ ’r“¿r‘’Áqq Ž‹2ˆÁÎÁÎÁ--ÁÎÁÎ/‰.ÁÑÁÑ/‰‰ÁÎÁ//Á‰‰ÅÎÁÎ/ÄÎÁÎ/ÄÎÁÎÁÂÎÁÎÃÁ--ÁÁÏÁ--ÁÏÁÏ-öÏÁÏéÎÁÎ/ÁÎÁÎ/ÅÎÁÎ/ÁÎÃ//ÁÎÁÎÁÑÁÎÁ//‰ÁÎÁÎÁ//‰/06qo0ÁÓ4mˆ."A?EFJÂIIÁ&&NÂMMÁKK%MxN%ÂNNÂIIÃHHJÁDDFCu?Cu?s••sÃ>>•ÁØÁØÈ>>‘9:54pmÁÓÃ00Á..ÁÑÁÑ.Á//ÁÎ/‰‰ÁÑ/ÁÎÁÎÁ//ÇÎÁÎÁˆˆ¼½ ’r“¿Á’’q q o޼Š/ÁÎ-ÁÏÁ--ÁÎÁÎÁ//ÁÎÁÎÁÑÂ//‰Æ//Á‰‰ÁÑÁÎÁÎÂ//Á‰‰ÁщÃ//Á‰‰Ã//‰É//ÆÎÁÎ/ÈÎÁÎÃÂÏÁÏ-Á--ÁÅÏÁÏ-ÑÏÁÏèÎÁÎ/ÂÎÁÎ/ÊÎÁÎÂ//ÁÎÁÎÁ//ÂÎÁÎÃ//.15p.04Á‰‰014ÁA$FJÂIIÉNNÁGGNvÃIIÁHHJÁDDÁCC?u”ÁssÁ••Å>>ÁØÉ>>‘9:430ˆ.‰/Á..ˆÁ‰‰ÁÑÁΉÁ//ÁÎÁÎ/‰ÁÎÁ//ÁÑÄÎÁÎ/ÅÎÁÎÁ‰‰Š‹ Á’’“Á’’¿ qÁ ޽¼ˆ‰-ÂÏÁÏÒÎÁÎ/ÁÎÁÎ/ÁÎÁÎ/ÁÎÈ//ÁÎÁÎÆ//ÁÑ/ÁÑÂ//ÁÎÁÎÃ//ÁllÂ//ÁÎÁÎÁÑÁÑÁ//ÁÎÅ//ÁÎÁ//ÂÎÁÎÂ//ÄÎÁÎ/ÇÎÁÎÁÁÏÃ--ÐÎÁÎ/ÇÎÁÎ/ÊÎÁÎÁ//ÁÎÁ//ÁÎÁÎ/ÊÎÁÎ/‰Á//ÁÎÁÎ/ÂÎÁÎ/ÁÎÁÎ/.12.0p‹ŠÁ//02Á7"9@EJHÄIIÁNNGÁIINvÄIIÄHHJÁDDFC?ÁEE?•Æ>>ÁttÑ‘rÁ::’Á::542ÁÓ0.‰Ä//.Ä//ÅÎÁÎÁÎ/lÁ//ÄÎÁÎ/ÄÎÁÎ/Šn Ó“Á’’ÁqqÂo޽‹¼Š/Ã--ÖÎÁÎ/ÆÎÁÎÂ//ÆÎÁÎ/ÁÎÁÎ/ÃÎÁÎ/ÁÎÁÎÈ//ÁÎÁÎÍ//ÂÎÁΉ.ÁÑÅ//.Í//ßÎÁÎ/ËÎÁÎ/ÈÎÁÎÁ//‰ÇÎÁÎÁ//ÁÎ/ÁÑ.ÁÐ0Š.03n.‰ÁÑÁ00ÁÓÂ00ÁÓ1";$FJIHÁII&ÁIIHÂIIHÂIIÂHHÂJJÁDDFCÃ??sÃ>>t‘‘t‘r:o10ÂÓÁÓˆÁÑÂ//ÁÎ/ÁÎÁÎÁ//ÁÎÁ//ÆÎÁÎ/ÃÎÁÎÁ//.ÆÎÁÎÁ//ÃÎÁΉ»½’““¿“’q޽Œ¼¼ˆ‰ÁÎÁßÎÁÎ/æÎÁÎÂ//ÈÎÁÎÁ//ÂÎÁÎ/ÁÎÁÎ/ÃÎÁÎÁ//ÁÎÄ//ËÎÁÎ/ÁÎ/ÎÎÁÎÁ//ÐÎÁÎ/ÄÎÁÎÁ//‰ÁÎ/ÁÎÁÎÂ//ÄÎÁÎ.‰Â..‰.ÁÓ0/‰.Â00Â..0ÁÓ24EÁJJÁHHIÃHHÃIIHIÄJJDÂFFuÃ??•Ä>>‘Á99‘’p2ÁӈɉÁÎÁÎÁÄÎÁÎ/ÃÎÁÎÁ//ÄÎÁÎ/ÁÎÁÎ/ÃÎÁÎÁÑÁÑÄÎÁÎÁ//ÅÎÁÎÁм’¿Á‘‘’¿’qÁŒÁ¼¼½ŒÁÐéÎÁÎ/ëÎÁÎÁ//ÒÎÁÎÉÎÁÎ/ÏÎÁÎÁ//ÂÎÁÎÁ//ÔÎÁÎÁ//ÃÎÁÎ/ÆÎÁΉÁ//Á‰‰/Á‰‰.ÁщÁÑÁÑÃ..Á‰‰.0ˆ.01$ÁDDÂJJHÁIIÄHHÂJJDÂFFCÁuuÂ??s•Á>>ÁØÁØÂ‘‘Á99Ž2ÁÐÁÐÁÑÆÎÁÎÁÎÁÂÎÁÎÁ//ÁÎÁÎÁ//ÅÎÁÎ/ÆÎÁÎ/‰/ÊÎÁΈ ¿“r’q ޼Ánn2‹2.ÁÎÁÎÒÎÁÎ/ÿÎÌÎÁÎ/ÃÎÁÎÁÁÎÇÎÁÎ/ÖÎÁÎÁ//ÎÎÁÎ/ÄÎÁÎ/ÊÎÁÎÆ//ÁÎÂ//‰/Á‰‰.Áщ/‰ÁÑ.ˆ.‰Á..69@CÁDDÁJJÁÁHHÁJJHÂJJÂDDÁCCÁuÃ??Â>>Átt9r9r9qŽ2ŠÁˆˆÁÎÆÁÏÁÏÄÎÁÎÒÎÁÎ/ÇÎÁÎÁ»¼½q¿“Á’’ ÁmÁ00»2Á‹‹2Š/ÔÎÁÎ/ÈÎÁÎ/ÙÎÁÎÁ//ÂÎÁÎ/ÒÎÁÎ/ÁÎÁÎ/ÒÎÁÎ×ÎÁÎ/éÎÁÎÃ//ÂÎÁÎÁ//ÃÎÁÎÁ//‰Â//Á‰‰.ˆÁÑ/ÁÑ.0ÁÓ4!ECÁDDÄJJDÂJJÂFFÂCCuE?Áss?Á>>tÆ99qp»ŠˆÄÎÁÎÃÁ--ÌÎÁÎ/ÊÎÁÎ/ÄÎÁÎÁÏÁψÁ½½Á ÃqqŽÁmŠ.ÁÑŠ‹2Š/ÌÎÁÎ/ëÎÁÎÁ//ÁÎÂ//ÁÎÁÎ/ÕÎÁÎ-ÄÎÁÎÁÈÎÁÎÓÎÁÎ/ÅÎÁÎÂ//ÂÎÁÎÁ//ÈÎÁÎ/ÊÎÁÎÁ//ÈÎÁÎÁ//ÁÑ/ÁÎ/ÁÎ/ÁÎÁÎ/ÁÎÁÎÁ//./‰ÁÎÁ‰‰Á..‰‰lˆÂ..7>Átt‘‘Â99Á׌¼»ÁЈÃÂÎÁÎÁÎÊÎÁÎÃ//ÁÎ/ÆÎÁÎÁ//ÃÎÁλ¼Ä ½‹ŒŠ‰ÁΈÁÁÓÁÑ/ÁÎÁÎÁÄÎÁÎ/ÔÎÁÎÁ//ÂÎÁÎÁ//ËÎÁÎ/ÃÎÁÎÄ//ÈÎÁÎ/âÎÁÎßÎÁÎÃ//ÛÎÁÎ/ÁÎÁÎÁ//‰/ÁÎÂ//ÆÎÁÎÁÑlÁ‰‰Á//ʼn‰.Á‰‰ÁÑ.Á003"9@ÁCCÁFFDÁCCFÁCCFÁCCÁ??EsÃ>>AÂ99‘Â99’qÁ½Á¼¼ŠˆÄÁÎÂÉÎÁÎÂ//ÊÎÁÎ/ÂÎÁÎ-ÁΈ¼oÁ¼¼Á½½ÁÁ‹Œ¼ˆ‰ÂÎÁÎÁˆˆ0./ËÎÁÎ/ÂÎÁÎ/ÐÎÁÎ/ÁÎÁÎ/øÎÁÎ-ÈÎÁÎÐÎÁÎÁ//ÇÎÁÎ/ÁÎ/ÁÎÁÎÂ//ÃÎÁÎ/ËÎÁÎÁ//ÄÎÁÎ/ÁÎÁÎÂ//ÃÎÁΉ/ÂÎÁÎ/ÆÎÁÎʼn‰Â//ÁÎÁ//Á‰‰Á//‰Â..76!A$EFÁFÁÚÁÚCÁuuÂ??sÁ>>t>ÁttÁ99‘Â99“’Á½‹¼Á»»ÁˆˆÁÁÎÁÎÁÏÁÄÎÁÎ/ÆÎÁÎ/ÍÎÁΉˆonÁŠŠn½ÂÁ½Œ¼0ÁÑÃÎÁÎ/.ÁÑÑÎÁÎ/ÍÎÁÎÂ//ÎÎÁÎÂ//ÐÎÁÎÃÎÁÎÁ//ÆÎÁÎ/ÁÎÁ//ÐÎÁÎáÎÁÎÃ//ÈÎÁÎ/ÁÎÁÎÅ//ÃÎÁÎ/ÁÎÁ//ÂÎÁÎÁ//ËÎÁÎÄ//‰/‰ÁÎÁÎÂ//‰Á//‰ÁÑÁ..ÁÓÁÓ0ÁÓ1"9>Á@@EÁ??ÂEE?s?Á@@Ä>>Ä‘‘9‘’ÁÖq½¼»ÃˆˆÁÎÃÏÁÏÁ×ÎÁΈ»n½qŒ0‰ÁÑ‹ÂÁ½ÁŒŒˆÁÎÁÿÎÐÎÁÎ/ÃÎÁÎ/ÅÎÁÎ/ÍÎÁÎ/ÁÎÁÎÁÎ/ÃÎÁÎÃ//ÆÎÁÎ/ÃÎÁÎ/ÈÎÁÎ/ÊÎÁÎÁ//ÆÎÁÎÂ//ÂÎÁÎ/ÆÎÁÎÂ//ÁÎÁÎÂ//ÁÎÁÎÁ//ÁÎÁ//ÂÎÁÎÂ//ÁÎÁΉ/ÄÎÁÎÁ//Áll.0Â..075"<9AÁ>>@Á??@Áss@Ã>>tÁ‘‘tÁØÃ‘‘Á’’qÁ޽Á¼¼Á»»ÁˆˆÁÎÆÏÁÏÕÎÁÎÁш»Œ†ÁqqnlÁÎ/»½ †Ž‹ŒÁ½½‹nŠ/ÁÎÁÎÁÎÃ//ÇÎÁÎ/ÄÎÁÎ/ÂÎÁÎÁ//ÅÎÁÎ/ßÎÁÎ/ÊÎÁÎ/ÊÎÁÎÁ//ÈÎÁÎÂ//ÁÎÁÎ/ÃÎÁÎÆÎÁÎ/ÒÎÁÎ/ÅÎÁÎ/ÈÎÁÎÁ//ÂÎÁÎ/ÐÎÁÎ/ÂÎÁÎÇ//ÁÎÁÎÁ//ÂÎÁÎÄ//ÁÎ/ÄÎÁÎ/‰Á..ÁÐÁ‰‰ÁÑ.0ÁÓ20ÁÓ34Á;;Á99AÅ>>ÁttÁ>>9t>tÁ‘‘ÁrrÁ’’޽¼ÁÁ»»ˆÁÎÇÏÁÏÐÎÁΉŠŒorqon.ÁÎÁÎŽqÁnn¼Á½½¼.ÊÎÁÎ/ÈÎÁÎ/ÿÎÆÎÁÎ/ÅÎÁÎ/ËÎÁÎ/ÅÎÁÎ/ÊÎÁÎÁ//ÏÎÁÎ/ÃÎÁÎ/ËÎÁÎÁ//ÏÎÁÎÆ//ÃÎÁÎ/ÃÎÁÎÁ//ÁÎÁ//ÂÎÁÎÁ//ÁÑ.ÁÑÁÑÁ//Á‰‰.ˆ0Á..ˆ0mÁ331745Â;;9AÁ‘‘>Á‘‘•Á>>‘‘“¿qÁÁ½½Á¼¼Â»ŠˆÁÎÁÇÏÁÏÇÎÁÎ/ÅÎÁΉ1oÂqqe3./ÁÎÁΈnq‹nno½2ŠÁ//ÁÎÁÎÁ//ÉÎÁÎ/ÕÎÁÎ/ËÎÁÎ/ÁÎ/ãÎÁÎÁ//ÒÎÁÎÒÎÁÎ/ÆÎÁÎ/ÃÎÁÎ/ÈÎÁÎÂ//ÁÎ/ËÎÁÎÁ//ÃÎÁÎÂ//ÁÎÁÎÂ//ÁÎ/ÁÎÁÎ/ÇÎÁÎÁ//ÊÎÁÎÁÑ.ÁÑÁÑÄ//.ÁÐÁ//ÁÑ.Š0Á..Á00ÁÓ1Á7765•Átt‘Á““q½½Œ¼ÂÁ»»ˆÁÎÁÎÃÏÁÏÁÏÁÏ-ÁÎÁÎÁ//ÉÎÁΉ‹Áoop30./Áн ’Œ0мދ0lÑÎÁÎÁ//ÇÎÁÎ/ÃÎÁÎ/ÁÎÁÎ/ÖÎÁÎ/ÈÎÁÎ/ËÎÁÎ/ÚÎÁÎ/ÂÎÁÎ/ÂÎÁÎ/ÌÎÁÎ/ÔÎÁÎÈ//ÁÎÁÎ/ÂÎÁÎÁ//ÂÎÁÎ/‰Á//ÁÎÁÎ/ÁÎÁÎÅ//ÁÎ/ÃÎÁÎ/ÉÎÁÎÁ//ÁÎ/‰Â//Á‰‰ÁÎÁÎ/ÁÑÁÎÁÎ/ÁÑÁЈÁÑÁ..Á‰‰ˆÁ0023m3Â115r>ÁttÁ‘‘r’ ŽoÁ½½Ã¼¼nÁÊ»ˆÁÎÁÎÁÁÎÄÃÎÁÎÁ//ÅÎÁÎÁÑÁÓm‹3ÁÓ.Á//ÂÎÁΈr“m0ˆÁpl/ÄÎÁÎ/ÁÎÁÎÁ//ÃÎÁÎ/ÄÎÁÎÁ//ÂÎÁÎ/ÄÎÁÎ/ÎÎÁÎ/ÅÎÁÎ/ÁÎÁÎ/ÃÎÁÎ/ÆÎÁÎ/ÅÎÁÎ/ÁÎÁÎ/ÅÎÁÎÂ//ÐÎÁÎ/ÁÎÁÎÁÎ/ÄÎÁÎ/ÃÎÁÎ/ÐÎÁÎ/ÂÎÁÎ/ÅÎÁÎÁ//ÁÎ/ÉÎÁÎ/ÁÎÁÎ/ÃÎÁÎÄ//ÁÎÁÎ/ÂÎÁÎ/ÁÎÁÎÃ//ÈÎÁÎ/ÃÎÁÎÂ//ÁÎÁ//ÁÎÁÎÁ//ÃÎÁÎÁ//ÁÎ/.ÁÑɉ/ÁÑÁÑ.Â00ÁÐÁÐÁ..ÁÐ4q9Átt“’q ýŒ¼‹Œ2»ŠÁˆˆÃÏÎÁÎ.ŠÁÓÁÓ./ÄÎÁΈ»½qr‘m0.»½om0Á//ÈÎÁÎ/ÍÎÁÎ/ÒÎÁÎ/ÈÎÁÎ/ÂÎÁÎÁ//ÄÎÁÎ/ÃÎÁÎ/ÃÎÁÎ/áÎÁÎÈÎÁÎ/ÆÎÁÎ/ÂÎÁÎÃ//ÁÎÁÎ/ÁÎÁÎÁ//ÅÎÁÎÁ//ÄÎÁÎ/ÂÎÁÎ/ÄÎÁÎ/ÁÎ/ÁÎÁÎ/ÁÎÁÎÁ//ÈÎÁÎ/ÍÎÁÎÁ//ÂÎÁÎÊ//ÁÎÁÎÁ//ÃÎÁÎ/Á..ĉ‰lÁ..ˆˆ.ÁÑÁÑÁ//.35;tÁ‘‘rÁqq ÁÁý½Œ¼ÁÊÁ»»ÃˆˆÊÎÁÎÂ//Á..0.Á//ÂÎÁÎ/ÁΊ2orÁ‘‘onÁll»‹Ž7./ÏÎÁÎ/ÃÎÁÎÁ//ÁÎÁÎ/ÅÎÁÎ/ËÎÁÎ/ÄÎÁÎ/ÃÎÁÎÂ//ÁÎÁÎ/ÁÎ/áÎÁÎ/ÆÎÁÎ/ÃÎÁÎÐÎÁÎÁ//ÆÎÁÎ/ÂÎÁÎ/ÍÎÁÎ/ÎÎÁÎÄ//ÂÎÁÎÁ//ÂÎÁÎ/ÁÎÁÎÁ//ÂÎÁÎÂ//ÃÎÁÎÇ//ÂÎÁÎ/ÄÎÁÎÁ//‰ÁÎÁÎÃ//ÁÑÃ//ÁÎ/Á‰‰Ã..Á//ÁÎÁÎÁ//.359Á‘‘r’Áqq qÁÁÁ½½¼mŒ‹ÂŒŒ»»Šˆl‰ÉÎÁÎÂ//Á‰‰/ÁÎÁÎ/ÃÎÁΉ»poÁrr;7ÁÓÁ//ÁÐÁÒÁÕn0‰ïÎÁÎÁ//ãÎÁÎ/ËÎÁÎ/ÄÎÁÎÁÎ/ÃÎÁÎÇÎÁÎÁ//ÇÎÁÎÁ//ÂÎÁÎ/ÄÎÁÎ/ÊÎÁÎ/ÄÎÁÎ/ÂÎÁÎÁ//ÂÎÁÎÁ//ÁÎÁÎÁ//ÁÎÁÎ/ÃÎÁÎÁ//ÃÎÁÎÁ//ÁÎÁÎ/ÊÎÁÎÂ//ÁÎÃ//ÂÎÁÎ/ÁÎÁ//ÁΉÁÎÁÎ/ÁÎÁÎÁ//l/ÃÎÁÎ/Á‰‰ÄÑÁщÃ//l01’Á‘‘9r¿Á’’qÁ q½nÁÓÁÓ2Œ‹mnÁ»»ŠÁˆˆÁ‰‰Á//ÌÎÁÎÁ//ÃÎÁΉq570.Á//ÁÑÁÓn0.Â//ÓÎÁÎ/ÊÎÁÎ/ÌÎÁÎ/ÄÎÁÎ/ÁÎÁÎ/ÁÎÁÎÂ//ÈÎÁÎÄ//ÒÎÁÎ/ÃÎÁÎÈÎÁÎÃÎÁÎ/ÄÎÁÎ/ÂÎÁÎ/ØÎÁÎ/ÇÎÁÎ/ÈÎÁÎÁ//ÉÎÁÎÁ//ÁÎÁÎÃ//ÅÎÁÎÁ//ÃÎÁÎÂ//ÂÎÁÎ/ÁÎÁÎÅ//ÇÎÁÎÃ//ÁÎ/ÁÎÁ//‰ÁÑÁ//‰Á//ÂÎÁÎÁ//.qrt‘“Å’’Áqq Œ»ÂˆˆÁÐÁÓŠÃÐÁЈ.ÁÑÁ‰‰/ÇÎÁÎ/ÊÎÁÎ/ÁÓ‹oe30./ÁÎÁΉˆŠÁÑÄÎÁÎÂ//ÁÎÁ//ÈÎÁÎ/ÂÎÁÎ/ÆÎÁÎ/ÊÎÁÎ/ÄÎÁÎ/ÚÎÁÎ/ßÎÁÎÁÁÎÄÎÁÎ/ÆÎÁÎÃ//ÈÎÁÎÁ//ÅÎÁÎ/ÃÎÁÎ/ÃÎÁÎ/ÊÎÁÎÁ//ÁÎ/ÆÎÁÎ/ÃÎÁÎÆ//ÅÎÁÎ/ÃÎÁÎ/ÁÎÃ//ÁÎÁÎÂ//ÂÎÁÎ/ÁÎÂ//ÃÎÁÎÁ//‰ÁÎ/ÃÎÁÎÁ//ÁÑÃ//‰ÄÎÁÎ/ÁÓ5‡ÁttÄ““¿“’Áqq¼ÁÊŠlÅÎÁÎ/‰/‰ÁÎÁÎ/ÈÎÁÎ/ÉÎÁΉ02m0./ÂÎÁΉl.ÌÎÁÎÂÎÁÎÁ//ÁÎ/ÆÎÁÎ/ÍÎÁÎ/ÆÎÁÎ/ÍÎÁÎÃ//ÂÎÁÎ/ÁÎÁÎÂ//ÇÎÁÎÇÎÁÎ/ËÎÁÎ/ÃÎÁÎ/ÉÎÁÎ/ÁÎÁÎ/ÁÑ/ÛÎÁÎ/ÑÎÁÎÁ//ÂÎÁÎÁ//ÄÎÁÎ/ÍÎÁÎÂ//ÁÎÁÎÁ//ÁÎÁÎ/ÃÎÁÎÂ//ÁÎÁÎÂ//ÃÎÁÎ/ÁÎ/ÃÎÁÎÂ//ÁÑÆÎÁÎ/05“t“rq:’r“’Á ÁŽŽŒn»‰ÁÎÂÏÁÏ-ÃÎÁÎ/ÔÎÁÎ/ÁÑ0ÁÓÁÓ.Á//ÃÎÁÎÁ//ÄÎÁÎ/ÄÎÁÎ/ÙÎÁÎ/ÆÎÁÎ/ÇÎÁÎ/ÒÎÁÎ/ÃÎÁÎ/ÕÎÁÎ/ÄÎÁÎÁÎÁ//ÂÎÁÎÁ//ËÎÁÎÁ//ÂÎÁÎ/ÁÎÁÎ/ÃÎÁÎÁ//ÁÎ/ÂÎÁÎ/ÄÎÁÎÁ//ÂÎÁÎ/ÁÎÁÎÂ//ÁÎÁÎÁ//ÁÎÁ//ÁÎ/ÃÎÁÎÁ//ÃÎÁÎ/ÂÎÁÎÁ//ÅÎÁÎ/ÁÎÁÎÃ//ÄÎÁÎÃ//ÃÎÁÎ/ÃÎÁÎÁ//ÁÎÄ//ÆÎÁÎÁ//‰Â//ÁÎÁÎÄ//‰ÁÓq‡trqÁ‹‹4qr’ŒÁ22Œ»ˆ‰ÁÏ-ÁÃÎÁÎÅ//ÂÎÁÎÃ//ÇÎÁÎ/‰.Áщ/ÒÎÁÎ/ÂÎÁÎ/ÃÎÁÎ/ÁÎÂ//ÇÎÁÎ/ÅÎÁÎ/ÄÎÁÎÂ//ÃÎÁÎÁ//ÈÎÁÎÁ//ÂÎÁÎ/ÁÎ/ÁÎÃ//ÅÎÁÎ/ÇÎÁÎÁ//ÄÎÁÎÁÁ//ÂÎÁÎ/ÃÎÁÎ/ÃÎÁÎ/ÂÎÁÎ/ÃÎÁÎ/ÄÎÁÎÁ//ÇÎÁÎ/ÏÎÁÎ/ÁÎÁÎ/ÂÎÁÎÁ//ÁÎÂ//ÁÎÁ//ÅÎÁÎ/ÁÎÁÎ/ÅÎÁÎ/ÉÎÁÎ/ÈÎÁÎÁ//ÂÎÁÎ/ÅÎÁÎÁ//ÈÎÁÎÁ//ÂÎÁÎÁ//ÁÎÃ//ÄÎÁÎ.2qt•rn0ÁÓp “nŠ0p„¼»ˆÃÃÎÁÎÁ//ÑÎÁÎ/ÁÎÁÎ/ÆÎÁÎÁ//ÇÎÁÎÁ//ÃÎÁÎÃ//ÅÎÁÎÁ//ÜÎÁÎ/ÂÎÁÎ/ÄÎÁÎ/ÍÎÁÎ/ÃÎÁÎ/ÒÎÁÎÂ//ÈÎÁÎ/Â//ÇÎÁÎ/ÂÎÁÎÁ//ÇÎÁÎÁ//ÂÎÁÎ/ÂÎÁÎ/ÃÎÁÎÁ//ÇÎÁÎ/ÁÎÁÎÂ//ÁÎÁÎ/ÃÎÁÎ/ÁÎÁÎÂ//‰Á//ÅÎÁÎÁ//ÁÎÂ//ÈÎÁÎÁ//ÂÎÁÎ/ÁÎÁÎ/ÁÎÁÎ/ÁÎ/ÁÎ/ÊÎÁÎ/ÁÎÁÎ/ÁÎÃ//ÁÎ/ÂÎÁÎ/‰ˆ3rts‡onÁ..ŽÁrrnŠˆÁÑÁÓ4oŽ2ˆ‰ÁÎÁÁÎÁÎÂ//ÇÎÁÎÁ//ÄÎÁÎ/ÂÎÁÎ/ÁÎÁÎÂ//ÁÎÁÎ/ÁÎÁÎÇ//ÁÎÁÎ/×ÎÁÎ/ÐÎÁÎ/ÅÎÁÎÅ//ÃÎÁÎÁ//ÂÎÁÎÉ//ÂÎÁÎÃ//ÉÎÁÎ/ÁÎÁÎÁ//ËÎÁÎËÎÁÎ/ÁÎ/ÃÎÁÎ/ÆÎÁÎ/ÁÎÁÎÁ//ÈÎÁÎ/ÂÎÁÎÁ//ÁÎÁÎ/ÂÎÁÎ/‰ÆÎÁÎÁ//ÂÎÁÎ/ÅÎÁÎÁ//ÁÎ/ÁÎÁÎÁ//ÆÎÁÎ/ÄÎÁÎ/ÊÎÁÎ/ÃÎÁÎ/ÃÎÁÎ/ÃÎÁÎ/ÁÎ/ÁÎÁÎÄ//ÂÎÁÎÁÐ2rÁttrp0Á//01’“rlÁ‰‰ÁÓ‹‹nЉÁÎÂÎÁÎ/ÄÎÁÎ/ÐÎÁÎ/ÃÎÁÎ/ÁÎÁÎ/ÂÎÁÎ/ÁÎÁÎÂ//ÁÎÁ//ïÎÁÎ/ÆÎÁÎ/ÁÎÁ//ÁÎÁÎÁ//ÅÎÁÎ/ÃÎÁÎÂ//ÑÎÁÎÉÎÁÎÁ//ÅÎÁÎÁ//ÁÎÉ//ÅÎÁÎ/ÆÎÁÎÈ//ÁÎÁÎ/‰/ÁÎ/ÂÎÁÎ/ÁÎÁ//ÁÎÁ//ÃÎÁÎÂ//ÁÎÅ//ÁÎÃ//ÄÎÁÎÁ//ÐÎÁÎ/ÈÎÁÎÄ//ÁÎÁÎ/ÁÎÁÎÅ//ÁÎÁÎÁ//ˆ2Árro2.Á//.ÁÓÁrrŒŠ‰ÁÎÁÑŠmpŽ‹nˆÁÎÁÎÃÎÁÎ/ÁÎÁÎ/ÁÎ/ÊÎÁÎÃ//ÈÎÁÎÁ//ÁÎÁÎ/ÂÎÁÎÄ//ÔÎÁÎ/áÎÁÎÁ//ÂÎÁÎ/ÇÎÁÎÁ//ÇÎÁÎÄ//ÁÎÁÎ/ÉÎÁÎ/ÇÎÁÎÂ//ÃÎÁÎÂ//ÅÎÁÎÁ//ÐÎÁÎÂ//ÂÎÁÎÂ//ÁÎ/ÁÎ/ÇÎÁÎÁ//ÁÎÁÎ/ÁÎ/ÃÎÁÎÃ//ÂÎÁÎ/ÍÎÁÎ/ÃÎÁÎ/ÁÎÁÎ/ÆÎÁÎ/ÃÎÁÎ/ÅÎÁÎÂ//ÁÎÁÎ/ÁÎÁÎÁ//ÂÎÁÎ/ÁÎÁÎÁ//.oqo30/ÂÎÁÎ0‹rtqŽnlÁÎÁÎ/0n1‹2Š/ÒÎÁÎ/ÁÎÁÎÃ//ÑÎÁÎ/ÁÎ/íÎÁÎ/ÆÎÁÎ/ÂÎÁÎ/ÆÎÁÎ/ÈÎÁÎ/ÅÎÁÎ/ÇÎÁÎÁ//ÎÎÁÎÁÎÁÎÃ//ÆÎÁÎÁ//ÆÎÁÎÂ//ÄÎÁÎ/ÂÎÁÎ/ÃÎÁÎÂ//ÂÎÁÎÉ//ÁÎÂ//ÁÎ/ÁÎÃ//ÃÎÁÎ/ÂÎÁÎÁ//ÅÎÁÎ/ÂÎÁÎÄ//ÆÎÁÎÁ//ÁÎ/ÁÎÁÎÂ//ÄÎÁÎÁ//ÂÎÁÎÊ//ÁÎÁÎÄ//ÁÑÁÓ1p2./ÃÎÁÎÁÑÁÒ5Árrq‹»‰ÁÎÁÎ/.0ÁÒ2nˆ‰ËÎÁÎ/ÃÎÁÎ/ÁÎÁÎ/ÃÎÁÎ/ÄÎÁÎ/ÇÎÁÎ/ÁÎÁÎÃ//ÁÎÁÎÂ//ÁÎÁÎÂ//ÃÎÁÎÁ//ÌÎÁÎÁ//ËÎÁÎ/ÇÎÁÎÁ//ÅÎÁÎÁ//ÍÎÁÎ/ÊÎÁÎ/ÂÎÁÎ/ÃÎÁÎ/ÁÎÁÎ/ÆÎÁÎÈÎÁÎ/ÆÎÁÎ/ÉÎÁÎ/ÂÎÁÎÃ//ÂÎÁÎ/ÆÎÁÎÂ//ÃÎÁÎ/ÁÎÁÎ/ÁÎ/ÁÎÃ//ÃÎÁÎÃ//ÃÎÁÎÁ//ÄÎÁÎÁ//ÂÎÁÎÃ//ÁÎ/ÁÎÁÎ/ÁÎÁÎÂ//ÁÎÊ//ÃÎÁÎÄ//ÁÎÁ//ÇÎÁÎÁшÁÓÁÓÁÐ/ÅÎÁÎ.2o’q2ŠÃÎÁÎÁÑ.ÁÐÁЈl/ÅÎÁÎ/ÁÎÁÎ/ÅÎÁÎ/ÊÎÁÎÁ//ÃÎÁÎÁ//ÂÎÁÎÇ//ÁÎ/ÁÎ/ÂÎÁÎ/ÑÎÁÎ/ÁÎÁÎ/ÐÎÁÎ/ÆÎÁÎ/ÅÎÁÎÇ//ÁÎ/ÎÎÁÎ/ÇÎÁÎ/ÁÎÁÎ/ÆÎÁÎÄÎÁÎÈ//ÈÎÁÎÄ//ÃÎÁÎÅ//ÃÎÁÎ/ÁÎÁÎÅ//ÂÎÁÎ/ÁÎÁÎÂ//‰ÁÎÁÎÁ//ÄÎÁÎÂ//ÅÎÁΉÁ//ÁÎÁÎÃ//ÁÎÁÎÃ//ÁÎÁ//ÁÎÁÎ/ÁÎÃ//ÃÎÁÎ/ÁÎ/ÁÎÁÎ/ÂÎÁÎÁ//ÁÎÄ//ÇÎÁÎÁ//‰Â..Á//ÁÎÁÎ/ÁÎÁÎ/.po‹»‰ÂÎÁÎÁ//Á‰‰ÁÑÁ//ÃÎÁÎ/ÃÎÁÎÁ//ÁÎÁÎ/ËÎÁÎÃ//ÂÎÁÎÅ//ÆÎÁÎÄ//ÆÎÁÎ/ØÎÁÎ/ÍÎÁÎ/ÍÎÁÎ/ÕÎÁÎÁ//ÆÎÁÎÁ//ÁÎÂ//ÁÎÁÎÅÎÁÎÁ//ÅÎÁÎ/ÎÎÁÎ/ÂÎÁÎ/ÆÎÁÎ/ÁÎ/ÂÎÁÎÁ//ÁÎÁÎÈ//ÂÎÁÎ/ÃÎÁÎÂ//ÆÎÁÎÁ//ÃÎÁÎÂ//ÁÎÁ//ÁÎÁ//ÂÎÁÎ/ÄÎÁÎÁ//ÇÎÁÎÂ//ÃÎÁÎ/ÁÎÁ//ÌÎÁÎÁÑÁ//ÄÎÁÎ/ÁÎÁÎ/.ÁÓn7‹nˆ/ÅÎÁÎÁ//ÄÎÁÎ/ÃÎÁÎÁ//ÁÎÁÎ/ÄÎÁÎÁ//ÉÎÁÎ/ÁÎÁÎÁ//ÁÎÁÎ/ÁÎÁÎÂ//ÁÎÁÎ/ÁÎÁÎÁ//äÎÁÎÁ//ÄÎÁÎ/ÅÎÁÎ/ÃÎÁÎÁ//ÛÎÁÎ/ÇÎÁÎ/ÁÎÁÎÁ//ÁÎÁ/ÅÎÁÎ/ÃÎÁÎ/ÅÎÁÎ/ÆÎÁÎ/ÅÎÁÎ/ÃÎÁÎ/ÂÎÁÎ/ÁÎÁ//ÁÎÁÎ/ÁÎÁÎÃ//ÁÎ/ÁÎÁÎÅ//ÃÎÁÎÅ//ÂÎÁÎ/ÄÎÁÎÂ//ÁÎÁ//ÁÎÂ//ÁÎÁÎ/ÁÎÁÎ/ÁÎ/ÁÎ/Ë//ÂÎÁÎÂ//ÁÎÁ//ÌÎÁÎÁ//ÅÎÁÎÁ//l.ÂÓÁÓˆ‰ÄÎÁÎ/ÃÎÁÎ/ÁÎÃ//ÂÎÁÎÅ//ÉÎÁÎÃ//ÅÎÁÎÃ//ÁÎÁÎÂ//ÃÎÁÎ/ÁÎÁ//ÇÎÁÎ/ÁÎ/ÕÎÁÎ/ËÎÁÎ/ÅÎÁÎÄ//ÂÎÁÎ/ÃÎÁÎÃ//ÉÎÁÎÁ//ÂÎÁÎ/ÁÎÁÎ/ËÎÁÎÓÎÁÎ/ÁÎÁÎ/ÑÎÁÎ/ÅÎÁÎ/ÃÎÁÎ/ÃÎÁÎ/ÃÎÁÎ/ÃÎÁÎ/ÁÎÄ//ÈÎÁÎÅ//ÁÎÁ//ÁÎÁÎÄ//ÁÎÁÎÂ//ÃÎÁÎ/ÁÎ/ÁÎÂ//ÁÎÁÎ/ÁÎÅ//ÉÎÁÎÁ//ÁÎ/ÈÎÁÎ/ÁÎ/ÁÑÁ..l/ÎÎÁÎÁ//ÁÎÁÎÂ//ÄÎÁÎ/ÊÎÁÎÁ//ÁÎÁ//ÁÎÁÎÁ//ÂÎÁÎ/ÁÎÁ//ÁÎÁÎ/ÂÎÁÎ/ÆÎÁÎÁ//ÁÎÁÎÂ//ÃÎÁÎÁ//ÁÎÁÎ/ÃÎÁÎ/ÐÎÁÎÂ//ÁÎ/ÁÎÁÎ/ÁÎÁÎ/ÖÎÁÎ/ÍÎÁÎ/ÄÎÁÎÉÎÁÎ/ÏÎÁÎ/ÈÎÁÎ/ÂÎÁÎÂ//ÄÎÁÎ/ÆÎÁÎÃ//ÂÎÁÎ/ÁÎÁÎ/ÁÎÁÎ/ÁÎÁÎÁ//ÁÎÁÎÂ//ÁÎÁÎÂ//ÁÎÂ//‰ÅÎÁÎ/ÁÎÁÎÅ//ÁÎÂ//ÁÎ/ÂÎÁÎ/ÃÎÁÎ/ÈÎÁÎ/ÁÎÁÎÁ//ÁÎÁÎ/ÁÎÁÎ/ÂÎÁÎ/ÁÎÁÎÁ//ÁÎÄ//.Ã//ÁÎÁÎ/ÂÎÁÎÁ//ÁÎÁÎÁ//ÁÎÁÎÁ//ÁÎÁÎÆ//ÃÎÁÎÁ//ÂÎÁÎ/ÃÎÁÎ/ÂÎÁÎÅ//ÅÎÁÎ/ÂÎÁÎ/ÂÎÁÎÁ//ÃÎÁÎÅ//ÅÎÁÎÁ//ÂÎÁÎÁ//ÃÎÁÎÁ//ÂÎÁÎÅ//ÄÎÁÎÅ//ÉÎÁÎÁ//ÁÎÁÎ/ÅÎÁÎ/ÑÎÁÎÁ//ÃÎÁÎÃÎÁÎ/ÇÎÁÎ/ÁÎ/ÍÎÁÎ/ÈÎÁÎÁ//ÂÎÁÎ/ÄÎÁÎÃ//ÁÎÁÎÂ//‰/ÁÎÁÎ/ÁÎÁÎÂ//ÁÎÄ//ÄÎÁÎÁ//ÄÎÁÎÅ//ÅÎÁÎÄ//ÁÎÂ//ÁÎ/ÁÎÁÎÃ//ÁÎÁÎ/ÆÎÁÎ/ÁÎÁÎ/ÁÎÁÎÁ//ÁÎÁÎÁ//ÇÎÁÎ/ÃÎÁÎ/ÅÎÁÎÅ//ÅÎÁÎ/ÅÎÁÎ/ÃÎÁÎ/ÁÎ/ÂÎÁÎ/ÆÎÁÎ/ÅÎÁÎÅ//ÁÎÁ//ÃÎÁÎ/ÌÎÁÎ/ÌÎÁÎÂ//ÁÎ/ÂÎÁÎ/ÃÎÁÎ/ÁÎÂ//ÁÎ/ÁÎÁÎÃ//ÃÎÁÎÁ//åÎÁÎ/ÃÎÁÎÂÎÁÎ/ÆÎÁÎ/ÂÎÁÎ/ÆÎÁÎ/ÉÎÁÎ/ÂÎÁÎÂ//ÂÎÁÎÁ//ÁÎÂ//ÁÎÁÎÃ//ÁÎÁÎÁ//ÁÎÁÎÁ//ÅÎÁÎ/ÂÎÁÎÁ//ÂÎÁÎÃ//ÂÎÁÎÁ//ÁÎÁÎ/ÃÎÁÎÊ//‰ÂÎÁÎÁ//ÁÎÁÎÁ//ÁÎÁÎÂ//ÁÎ/ÁÎÁÎÁ//ÁÎÁΉ/ÁÎÁÎÁ//ÁÎÂ//ÁÎÁ//ÁÎÁÎÅ//ÂÎÁÎ/ÆÎÁÎÅ//ÂÎÁÎ/ÂÎÁÎÁ//ÁÎ/ÆÎÁÎ/ÊÎÁÎ/ÅÎÁÎÁ//ÁÎÁÎÄ//ÁÎ/ÁÎÂ//ÂÎÁÎ/ÃÎÁÎÂ//ÊÎÁÎÁ//ÃÎÁÎÃ//ÃÎÁÎ/ÊÎÁÎÊ//ÂÎÁÎÁ//ÁÎ/ÌÎÁÎÁ//ÍÎÁÎ/ÂÎÁÎÁ//ÏÎÁÎÁ//ÃÎÁÎ/ÊÎÁÎ/ÃÎÁÎÁ//ÄÎÁÎÃ//ÁÎÁÎ/ÅÎÁÎÂ//ÁÎÁÎ/ÈÎÁÎÁ//ÁÎÅ//ÅÎÁÎÁ//ÅÎÁÎÅ//ÁÎ/Á..ÁÑ/ÂÎÁÎÂ//ÉÎÁÎÁ//ÁÎÁÎ/ÄÎÁÎÃ//ÅÎÁÎ/ÅÎÁÎÁ//ÂÎÁÎÃ//ÁÎÁÎ/ÂÎÁÎ/ÃÎÁÎÂ//ÆÎÁÎ/ÅÎÁÎ/ÅÎÁÎÁ//ÅÎÁÎÃ//ÁÎ/ÁÎÃ//ÁÎÁÎÂ//ÂÎÁÎÂ//ÑÎÁÎÃ//ÅÎÁÎ/ÈÎÁÎ/ÆÎÁÎÁ//ÊÎÁÎ/ÛÎÁÎ/ÄÎÁÎÁÎ/ÄÎÁÎ/ÃÎÁÎ/ÁÎÁÎÁ//ÁÎÁÎÁ//ÈÎÁÎÄ//ÁÎÁÎÃ//ÁÎÁÎÂ//ÅÎÁÎ/ÅÎÁÎÃ//ÁÎÁÎ/ÌÎÁÎ/ÁÎÁÎÂ//ÃÎÁÎÄ//ÁÎÃ//‰ÁÎÁÎ/ÁÎ/Â..Æ//ÂÎÁÎÁ//ÃÎÁÎÁ//ÉÎÁÎÂ//ÊÎÁÎÃ//ÁÎ/ÁÎÂ//ÃÎÁÎ/ÁÎÁ//ÁÎÁÎÁ//ÁÎÁÎ/ÁÎÂ//ÂÎÁÎ/ÂÎÁÎ/ÉÎÁÎ/ÁÎÁÎÁ//ÁÎÁÎ/ÆÎÁÎ/ÂÎÁÎÃ//ÁÎÁÎÂ//ÁÎ/ÁÎÁÎ/ÁÎÁÎ/ÏÎÁÎ/ÆÎÁÎÃ//ÅÎÁÎ/ÁÎÁÎ/ÁÎÂ//ÁÎ/ËÎÁÎ/ÃÎÁÎÁ//ÃÎÁÎÁ//ÄÎÁÎÂ//ÁÎÁÎ/ÁÎÁÎ/ÃÎÁÎ ( 8008((IAAA88QIIYIIaYYiaayqqqii‚yyAIIiqqÛëóIaq (0QYaaiqiqyqy‚ª²º²ºÃºÃËËÓÛÃËÓÛãëÓÛããëóAIY8AQaiyYaq‚Ššy‚’š¢²ºÃÓÃËÛÓÛëËÓããëû(008((0((888AAAI88I00A00IQQYIIQIIYAAQ88QYYaaaiYYiQQaIIaiiqqqyaaqiiy‚‚Šyy‚yyŠqq‚ŠŠ’’’šŠŠš‚‚’šš¢ššª¢¢ª’’¢’’ª¢¢²ªª²ªªº²²ºººËÃÃ˲²ÃËËÓÃÃÓËËÛÓÓÛÛÛãããëÓÓãÛÛëããóëëó80I0(AA8QQIaª¢ºÃºÓÓËã0(8( 0A8I80AIAQQIYaYiYQaiaq‚yŠ’ŠšŠ‚’¢šªš’¢²ªºª¢²ÃºËº²ÃÓËÛËÃÓÛÓããÛëëãóA0I8(AI8QYIa  8088(8IAIA8AI8IA0AYQYQIQYIYiaiaYayqyqiqyiyqaqЂЂy‚‚q‚ŠyŠ’Š’š’š’‚’šŠšª¢ªªšª¢š¢¢’¢ºªºº²º²¢²²ª²ËÃË˺ËòÃúÃÛÓÛÓËÓY8QqYiqAaŠq‚‚iyš‚’’yŠ¢Ššª’¢º¢²‚Yq( 8(0A08A 0YIQaQYaAQqaiŠy‚‚qy‚aqŠiyšŠ’’‚Šºª²0 Šqy’y‚i8A((( 888000IIIQQQYYYaaaiiiqqqyyyŠŠŠ’’’šššÿ<<<}}ÿ]]]žžÿ†††¾¾ÿ®®®ßßÿ×××ÿÿÿž¾ßÿž¾ßÿž¾ßÿÿÿÿallegro4.4-4.4.2/addons/allegrogl/examp/running.dat000066400000000000000000000646721173507505700221310ustar00rootroot00000000000000slh!ïALL.ëð pr¿opDATEëðï7-2001,¿ 21:07öñN»AMýñ FR_¿00_BMPöñO÷RIGfram½e#.bmp' ï4ŽFRRøTfxŠœ®ÀÒäöö,´>ss>,hzŒž°ÂÆ<õàèJsÀÆ/(/:/L/^/øLâ‚+õ˜!B¨#b/Â/Ô/æ/ø/l/–#9,7*7†)¨#/f?x?Š?0œ?r!ð 56!˜#È1 È5Ú=äT3¨%RY?O%O7O«>2;Ð3jGlCÐ?B7ô?¬O¾OÐOBOšCVK†rM—1[$Uâ?œERKRâOb_t_=v+fI$U SQ—1ÄS ]ŠKFLQ¨Ooo =NÞ9´]ÀÂS^iÊUÎ]ä¨'2€$o°oÂo”[DmrgÄU—1Ø9qsniUÞ[R5LSN_TÆoôO¨YÀWusªw¨uÆU" IBqžoüÌoÞoUuB¦u¼yÄyÈ5ž-êqF¢‰ð2‰ uJ‡9B9Bì‰NuÆ5€ä@ŸL—òSLYfiæ‰ì…ðƒø‡òƒ¸{ÔY€2ŸèŸp#`“0‚{”}æ‹”“šR0§ð‡TÊ}D[Ü‘ߟSœ`—À Y8.©4¥:£à£šR0ö\¯Ši>w2ÞŸTŸ€9¼Yü‹Ø©è¥|·”•¶ÿµ¶µÆƶµþ«Â•Öw¹4¿œ©JW¾«2«†·(Íœ³<ܱ¶µ´›¿$µÎ¿xÁ0LdIÀ¯ËûZÄÁÊÅ 2Çœ±šÖâÅž³¿º»rÁ„¯ ©¯«6¥ÀÅøfßÄܳšÖûÞûÞèËzmšI×ßôS:k𺯠q‚¹hÛuhª©jEËN¢çV÷½s½süõVóÜňÑx÷y¢×¼·0—¬ÿ¦©Þ5^¹òäóæñçþñš lõšÖ ¼{Ò÷×õzu>ßê…óŒôù˜ <ÃĨu|G¢+z©ðÕºùò»þi9Bt0Ì.ð÷š„êèLž³D§p†cà{L ül@‡tÖÖÌ2âèìÎÉ-. ˜C,—NÓŽƒª¢Ç¤ur!t!.~)’'Ÿ”˜%¦²åˆ¹°ŸÔw ´>w©öbávébGþytY)Y)t!2ãð.763òåFõ:¥ JïÓN.ÙÚÝØ…ð¸1¸1x#–Ê9Ú1zC89¼åP?†óÖ€ŒƒÆEˆ5¢¥|wn›VAÖ7Û9þAY)ÔöùÔ7|Gð¢/ú…ÄyˆgŽðÐI”YT¹öEY)]JÛ93¸çYxGÞ;’EÆÁ /VË*—ÊGÒOP½´1üA]JÿZ¤QÔ” vG43ðéB©p8 KðŒ7$c‚{šWÿZ]J`ELùZm”/åâ]ONçÕÎMÊglGà„‡ªÇZ×¶•˜E° ¸‚Õá&ãç‚Ñ+õõ¨Õë¿°ïûëú\áÂߘ­âMHK·º•å0"ã.ã*ç.í°†‡Ê!œfåÑïû]àÑùfï‰àM?fµhµºé`ùAÈ`õÐëBéðëó­Ð³ÿ~ãÊoîÛ(T×çrñlõrõÚéæ{°÷µ®ÿrïp}¸°Çúó¨ &åàãèCØ•VªÿÆß kž7HIê÷‚ÐLNT`ù‚Óìu¼Güšô™6IŒï7 Vîö¸.é\Wx1šƒ @/˜©´‹ØûòC¸°ypŸÚŸìŸþŸ¯€‘& h‚ßÚ×J©²KÀ¯z¯Œ¯ž¯°¯ ©x ˆÒ ˜äiäk¤9b¯À¿ ¿2¿D¿V¿Æ¯  |°°& ˆÏôÏßß*ß<ߪÏÎËÃ5¡3Ãx¼Âåϙ߽߫ßÏßáßQßcßoÓ×ŃԈß>ïPïbïtï†ïöÞ»ÁÃ{³!Å·ãÓ¡ƒÑ-ïáïóïÿÿ)ÿ—ïÏ¡¯å³é×ÃÛýÁh:ÿˆÿšÿ¬ÿ¾ÿÐÿöß¾ÄU÷ÿ÷Éå+ï);M_qßÿ;ÁOóÑ£ù÷£sòÎàòàÿðöII½Àt†˜ª¼*<é™/#/5/G/Y/k/Ÿëóó‘/»µ/Ç/Ù/ë/ý/?{/‡'7;©/]?o??“?¥?·?#?Û?M?ÿ?O#O5OGOYOkO}OO¡Oø³OÅOÅ0propDÿATE7÷-20é@01, ß21:07ÜANAÝMãA FRý@_0ß1_BMPÜAORûIGQframeÞ P.bmp P ÷4Ž,RRRÊOJ_\_n_€_’_¤_¶_È_Ú_ì_þ_oòcðe&e‘oNo`oro„o–ox¨o"eÂo´õ,i’s¬oüo 2D"c *cØiõpqlyruÞoš¬¾Ðâ c*ips pwÖk&cž¿N`r°„(g|u‰6!¬‹6!Æ|}—œ¿öŸŸ&—J¡Ði‹ÈƒV•N›zy„s¶›&Ÿ¢Ÿ´ŸÆŸÜ…BŸÄ…úŸÆ…l™¤…€™ŸF¯àX¯ÌŸš‰R›¥—1—1œ£ž£¢§­†{Œµh¯ð¯¿2Ÿnu‡¬£ £:·:» ©Ä«uš¿¿¢¿·z¯’­ª¥Ø9è³ð¿¦£j™Ê­2£2ª¿>Ï»0Š‘Ä¿˜©~ËØ9Ã쵔ܩƉr½ˆ‘,ÏâÏîÇ`ÏpÏŠË0ßæµ ©²‡ˆ{€³2„¿ˆßúÉ:™Œ« ˜ÉÁ9BÒÑÐÓÌÕ<ÙT½‹ÈÉáß0ïudÏ|Ë2×ÒÛÒÓä×êÛ¶¥zlÙ2ïPϨÛÀ‡bïÜÓ„åûàßV¹ín×ï”Ý¢Ù0Ûä¹2ù„åšR¾û„ﬧÇ~›dõjÿöËèíÛ˜ª÷ûÄñšRj h9B¶µƶµ„î³^¿‚›  ZyλŠÉ0bh n „Æ$€ŒÌ­bõ¼†óè㚉š§”Åô ûZªj° šÖÊ‚œï(eP®[‡øà“˜ýlí²cûZR/€ÊûÞn!Î2z™:ƒ¬/ˆûðé08·¸û¨T)M9º5¾3Š z›ª H;`þ3tÈ/0õÒÑè'6ú%½s¢3½sêA¢3Ær!\I>×:x·ê3H;0PJë*-ÒÓpQ’9àEêCìG5Ê_Çë@ä9¤' Eèç°M:)ý0xtS>GâA½s„Œ[½s"Ƽ3ÔÓØ€<(Wæ= GØÒ-at0ÃàtQi,c„ÐcìGd#„Äñ2õØloØYFWè”o:µÔõ¹`ÖtÄiÒcrwŒYT#rÒÓXkœ `ù¤#ü98yÀ˜©<'\s`qÜEÎg„Ÿ”z{Þg°Ú×þo"_ÖWŠi86!–\q¤2†ruŸ”¼x{¢7y²Y¢çΫÔWpƒ IÞ}ü¨÷ÐÑÖY)Y)Öbu²ˆ{†çžï6?“p‰J_ì¸aÛ9Û9ºaˆY\ŸÚg€T%88ZýŸÆŸÔ+š{R2EÛ9Y)ð“RŸ§ÊÜ‹_%lÙ´Ÿøj¯È5ÐÕ2Y)]JÛ9L•ø—J³ŠW½s©‚¶ÕœŸfàþ9Ü{ ·@“ê‘ÿZ]J`ul°¥¯r<ÙRÕÀbß®Z;Ü ŠËÒµY)¾cø!ø™x¤5p4ý>нø§¤¿‚ ÷0³Ú³–5(c2ß*þˆöN¯ðÇöÅÎÃv­D•d{>ß.‡~Ÿ¤y(Ç¿êÏÚ÷F‘`ãÎA’9.Ù>Kø#p&ök6!#TszÊuv‰€…B ¨æ' iûîÙøÝD‡'Š¿|mª½^ɺQpSaa¦4M¸­fµ¬ZÕTeºS+zÝÔçB_þHíӜӜqŒqŒŽspQúP+Îÿf¹ì::ø ùðÁ f‹„o4 ¶µU­oqŒï{LŽs$Eàä-.‡p äû.­øúëúïûïû/Ãø”Kth3èU­~Hï{,c,c>+€ØùvD'ôonÓ¤Hóü×ýÛþRfTÉØº³èHï{–ªR–‰ä+àóZ%È>’—ê6FïûòóüN® øvº³Žï{ŽsªR>) ¢h+åï>u0¨# îLëú¨/6ïp§FÚ#˜`[–u–sd/€Å>„ÐÁL7:5è1úùL?/`Åz1ð`¦m–7äùæù¸Ç°dIªyò;Fî1¦ ~û ™TYÀ¤mÖEJKöXEdG ¸dIÎöqò=¤–O$ O€,™ðslÇÖGôu”‡Y ¸¬SdK¾å<_Ú_Æ XU€½$ÃÔÖKÔGU¬QAÈAÈJaPc[¶uâ_€oÚïúϹjÉÎm@gNcîePg°[“†o&”oŽõÀ„Tç6•lÇBkîc‚Дqòe°S2eÄB_€ú_„\w^hѦWuÃà”s˜uLg¤{põÒtÊjc0`Y m¼gSŽy44úi WxñbŸ80Â+‚Â… ¸Ð…t™0‰’qœwö‹ŸºŸì_>Ÿ0„µT›äen—é§~•ŒÜ‡–Ÿ°ÄŸ\¯62`ht¡N_Œ©¤‰„±Ä…<0ƒ¡eùé¾§~“€&§šy°Yb¯d¯v ±x°ˆ0Ÿ¯L•ª§¡¾¡eù¼¡¼©ÚJ‡ U¿¾u¡²À°˜Ä°{¯5¼Üª«`±¼¯(©Ü©B¯>Ït®¿Ä² dB `šoŽ«¾áSÐ…dµÅ£,© ˜}2ÏæÏ´¼eÃÀÒÐpÍ*¿”Á&ÃŒ“«z™Ô«@J…Ôψ߲ºÕ ÓжÔp$ß¾ãUŽyÒ‡†›@î|ß.ï¶կѰÖ ÐÐmÁˆÌ»*ß&‡Žu–í~»ïÊïj¬½¹SéÑeAűiæßhñW¨YÞ©ÊÏÖïtÿ²¸¥ÓOé¡óeC  ó°`‹ˆÂÝdKäÿYzÿl¬½¹­ÓiÃkÃE·ñw Ú¬GÂÓ”¦¸‚ÿ”úGSã±óµó_ "4FXÈø—õåµñ·ñ¹ñ½Ïáó/=Ó?µó]/o//“/¥/o¡×…Û)…±M/??'?9?K?¹/#++'Ñ']±÷/«?½?Ï?á?ó?qï#y9‹7‘8š?PObOtO†O˜O`?F3C+K§>OòO__(_:_¨O´¿GiWaUßO“_¥_·_É_Û_í_Ã)³ g7H†_8oJo\ono€o’oÂ*_W·i%oÙoëoýo!3ŸoÅhXzÏo“¥·ÉÛGÿq#5GYk}éÅ×éû ŸŸ1ŸCŸUŸgŸðyŸ‹ŸŸ¯žpropÿDATEï7-20Ï01,¿ 21:10‘N»AMÉ‘ FRã_¿02_BMP‘O÷RIGæ‘fram½eï.bmpó ï4Ž¢RR°Ÿ0¯B¯T¯f¯x¯Š¯œ¯®¯À¯Ò¯ä¯ö¯Ö׳·ø¯4¿F¿X¿j¿|¿Ž¿·ŒÇൂɳ"¿à¿ò¿ÏÏ(Ï ½¤½º±XÃJËʵпŒÏžÏ°ÏÂÏÎǹZÉöÏ\Å®µùÎÏ6ß`HßZßÐÏLÏþÅ6!þÏÛº³tÇ‚ÜßîßïÖÉ |éòÏ6!>ã<çDãÛ½ñ ïˆïšï¬ï~Ý–ÕBãFéäé:å®Ý µÆÕ®ïÀ.ÿ@ÿí³¨Ý>å—1~õˆóñêëúéûÈßÎÿàÿRÿäÍHçŒùŒõŽõ”õ‚ó”ÛµâÁvÄÿzŒÀ^õµ’Ù|õ$6Ø90Ìÿ¦û\ 2$2d$ïÔÖnxÚð ù ÀÒ¢ f/€Öî ýh´Àj/:¨þ /%9B/’õN ÄÙV#v/?×Tɸ ®-9BÊ!^1d7Î/”õ@-ö+^/x/–Ó/Ä'^1šRd?r?€õØåâŰLAº?Â?ã87 `Z9šRAE¤IÆ-â °·ºùLAQO;Ì?€€GlZ5E¤EDU²K¶ÿµÆƶµ¶µÌK˜Õð-òObO`û¼ T;L[ûZTUTWfSelQ ÷¤5JC¢_UD`Þ;®#u¤CÊ#€?–?É,YܯÚ[ ±óÖHŸ”^ÏŒƒTWÜ¿&o©šQp³xBD98[2ÖŒÑðÏÑѼ·pÅvÉÊ!†ÏÎe$‹TÕÏ E~ˆÓY)Y)2j¥ ÙÛnǘc$ÝÄcÚG°¯`øÙv·”/J©,çt·DçHçÄ·×G¾i6GðTÛB‡$Ï"ëtÛ9Û9HÁÞéèçNíÛ€€R—î¿ÉV×Zo^ÿ¢C>‹Ð]J]J2“Ðj£žÛ¨ÙnÏ8¹æÞO¥˜Sàâ‰ÀÉåÚ]Û9ÿZÖ¹Dëf§H |ÉØ9h{õ.ý†ŠèÌ­Â_ÆéwòÿZY)7æšÛbϪý.)ê/€Z³Çà…^ßziV¡tY)]Jj ½¶¹|‡îUKè»*o–ëÌ© ï Kœ³Y)zñ" ¿â Š…òWx;°‡dŸ–ïïîÚËÛ9ŒÑ´'d«€‹ðtçèc‡øµ^¹°ÅÚÞ¯"wŠÓDÁÖwh9jÍòSýáègÎÿÍï¶ï8Ë,ƒà›IZéß®…øùúùèc Ï–à=$㢱ú¡ú¡–cÞyàÖ'ÄMÊÛÔÑâCëúï‡ûóüègȯ0¯õñPsZ¡ÓœqŒ?ï{qŒŽs6{\_0P ¦àAŠQóü2aèo@z™¶ËÂÃ:¥î'T€U­æQŒaìQÎ{"E k0,OÄñ†U2a×ý6oLmØÇtKtk9B†aU­ûÓœèQï{,c,7 òY¤iüvSPèaâA{ø0a×ý×ýèo`”YlO2=øîqÓœäSŽs,cª9$¦mÊMà\puvq|qŒSïûëúŽfC °yø‰±,q{qŒŠcŽsªRÜq0PìX tï´2‡âA$$Ó€zq2‹Žhe^Ø9,w|´´nYýª¶2‰,aäAæAؘÄ?B,U—1.qaŽsú2™$ã¢^ T'ªá2‹ |ŸfOjÓŒ/š)zÛXø}î+|ë¢52À¯tr`|+R…€³îþ¥ÔYv§0U¦‰ ò½Æ¯È¯x°h;{éV¯¶¿ûô›¶°ì¹KhÏx²{°ÁêùÎ7ð©P­š)°™î+ ‰ì³ ¸ŒÁ’Áì·Ïp»ÀÄx4TýN¯Àwðî)d‡‚ÉÅ ¸AÈCAÈ,ՖǪϸÈxfÒˆˆ2Z%²{P•ÛðrÏà@‰Ê4ÑAȂЂÐ4Ó4ÕŠÅHßÄiÔ â#Æ‚)Ð?BË>ïÙÈÙÀÖÑtéÜÓ’Åìß^Úˆ˜²äÉÊŠµ„Û‡DíÖ»ÊÝ‚ÐÃàõ~åØÕ(ŽÅ”í¦î ZðˆØ£WÌ;üùÆUŽûÄõŠÃÒÓóéºñ¸ñ÷(õ6јÏv²ÅÂfÐWõí±_ôÀíØÍÀ*X—´ŠÃõºóeù€¼óÀó~åÒõØÿìÿþòÀì°xx±Ú¯Ž¹4ÇÖX#¨õñ^þºóbÈõ4× åðÕ`Ö áŸÐZð¹àÀ—šB§Ä ¶¨ûü€Äÿ†åÜùÆ?í±KЀ¦]ñ«~%ïp+s(Õ°õ l 0Ó|Pr¸ åçó°\òh°Œ³/¸%еˆÅ®ùù÷ ‚íÐe׳áí³À:4í³[óÉÂðElû"é`PCà)°ótí~ `Úùùí·[ñOùxP³¦-¶ L…´U„5†ãxëØÓÐ÷zŽÁ?Yóÿñë3ë5³áó2pCø5'P;þê„;&àO†ç\O2±å‘CG—GÁy°ªW(E¢w*CNßÖC*×.Õ2Ù_\ßXÉW ãkÑA^ô_op_åžYŠï¬_Ü çogkÑSCë_Ÿo±ooÕoEßÏeÕ…joDVhzŒøo¾É"x?SoC3å÷ -?«{Ïu-v.‚”¦¸ÊÜFŸt$Ÿ6ŸHŸZŸlŸ~ŸŸ¢Ÿ´ŸÆŸØŸêŸüŸ¯ ¯2¯D¯V¯h¯z¯Œ¯ž¯°¯Â¯Ô¯æ¯ø¯ ¿¿.¿@¿R¿d¿v¿ˆ¿š¿¬¿¾¿Ð¿â¿ô¿ÏÏ*Ï<ÏNÏ`ÏrτϖϨϺÏÌÏÞÏðÏßß&ß8ßJß\ßn߀ߒߤ߶ßÈßÚßìßþßï"ï4ïÀFïXïjï|ïŽï–ãprÿopDATE¿7-20µà0ÿ1, 21:07î¨áNAM¯á FRþÉà_03_BMPÞ¨áORIGÌáfr÷ameÕà.bmp¾Ùà 4ŽøâRR–ïÿ(ÿ:ÿLÿ^ÿpÿ‚ÿ”ÿ¦ÿ¸ÿÊÿÜÿfÞÿ,>Pbtîñ'Ž *-ÈAx`ÈÚìþøjˆ-"/°l~¢Œ .JØäd9Ò%´/./@/¶¶%Bæ6!6!æÚn;´AR/Æ/Ø/ê/ ôûr)‚#‚!"3,5„'œ+Gh_j?|?Ž?Â*,;Æ?Ð5,3ÚTZ?O"O–?òõÔž&76!—1&3fC—1tCdGÞ=¤/O¸OÊOœ?ÈÐ?zC_vE€Iž/`Q¨O^_p_BKr+_¬YÃØ9[&Y6]œK2€v_ o|_JE–]¨[¾QØ9ZcXc¼[dGŠM Iö_¬oºiJQò÷.YºW^güibe"[fAâ5’ì_HÀZFE0mäiòeüg9B¢s} ]:94P_úÊgvˆžw¢qHƒFƒüotk è7žK2D^$‹VH…êVĪ'”o<Ÿ` x)¨Y[×`pÉà·H½tŠ•zµ6å½s ë°å á|·À ô=üë´óš«N¿xf·v±,ÖÖ4  >Ÿ”F°ç*Åö‹l¤×Ö•Jœ¦$÷œw<Ü¥ÐY)Ö–ê†%F~¹D¥°ŸŠo4+ÈÓàZŸZ/.¥$±x!Y)à.5îlÕ6¥¨y:ï€8{Zçä#ZV½ËÒÛo9Û92#2½s.749 å¤+¤q¼S»n?8+èÿž; Í2]JÖ"5Ð?˜-+´îëúëð@-©BÝXItÛ9]JY)4>Š'[°'Z_oª›1  À0`éAˆQðOF³5ÉÂÎW4SÞWäUL3N5'oo*fÐ2b9dJK0üoäsÎSAÈzc4W@*sì7P9¤oZ"h`ˆT1a[˜ú!%¬9n Š÷#qŽA s*y–CF3BwJF*1çCçC7b´PIv†GäUÔw”KR;ô¨Œ™5σ÷!5€²¨;ØÎU6qv…tDY)²RŸè,ñ#w•ñ!­À%<‰b9â7ŒCê3¸“~‹¢'ð¯$¯Œ• )¨‘†E¾Ÿ$ŸêŒ¯ž¯°¯Â¯Ô¯¤ÚŸ$æ3F5F[H]‚¯8¿J¿\¿n¿€¿ð£ô©˜gþ¥¦¹èÔ¿æ¿ø¿ ÏÏŠ¿ 'JÏR7ŒxϊϜϮÏÀÏ.Ï>7bËö¥fÏtÏ(ß:ßLß^ßpß’·>5”ßĹnÏÄßÖßèßúß ïzßü¢ß+¸ßlï~ïï¢ï´ï ïØïêï\ïÿ ÿ2ÿDÿVÿhÿÔïŒÿÿ°ÿÂÿÔÿæÿøÿ .@Rdvˆš¬¾Ðâô*<N`r„–¨ºÌÞð//&/8/J/\/n/€/’/¤/¶/È/Ú/ì/þ/?"?à4?F?X?j?pýproÿpDATEß7-20›001, 21:08Ž1wNAM•1 FR¯0_04_BMPŽ1ïORIG²1fra{me»0.bmp¿0ß 4ŽÞ2RR|?ü?O O2ODOVOhOzOŒOžO°OÂO¢W¤y¤qÄO__$_6_H_Z_ÔEZoºS¤Y¢‘^_®_À_Ò_ä_ö_ÔA¤{ŠQe¦”Wðcú_Zolo~ooh]s¶ek"e$m@oÀøo .oo6!ÄofueÞo8¬¾Ð02¥àG¾ifs6!fq…‰Òo —R›Se€wItàA€w… ‡ƒ—1ª‹Îm‚Už—zú ŸÞàCn{°¶…¸Ä‡vYJq<¥Ÿ¢Ÿ´ŸägDŸ¸—1ú—^›dy~Wà‡ŽŸD¯V¯æuàEl}\“ö›Ø9Ø9ú™¯ oæcŠ“2\¯ð¯b¯Ò›ä™˜¥4»œ£ž¯¶«ÜoÚ£6¯”¿p÷Š‘p¯$¿˜§â½2¹X»iÜCÖ§„¿:Ï ¿¼¿Ö¿Ø99B€Ç†Ã†Å`˜¥^•xy€™2£2Þ¯àϰ·r©F™Ú»ŽÃ$Ù&Õ–ÉNµ¾4ܯ„ß²½Ý4µÛÊךRÊ×6×L»Xß.¥ÎÁÎϊݲ³¿*»&ÙÒÕØÓtáØÙèßúÙâmç(ïß`Ïš§ÈÛØÑ|ãüùÊ×¶µ¶µÆ4ñ®­ï&ÃÀï0ït© …tÍõrãûZ¶óºó|åšR2óÖõ2ñÏ2tÑgÿƒ02øÉ¦ß4µÀ$Õÿ¾óftáÒõšÖ@|ÜóN±l4‰ã 7è†ý*·`åxçb f ºñ6óšÖûÞ –0–0âñŠÀ­ÄÇbÿ 2›öï N ™Îň8¯ê¯ü¯¿ ±¼åÐ f7ž§‚ÐJ³ª§Ø&·å4Á¿”¿¦¿¿škd9 ¶¦¡ÃàîµP±£Æ©è€¿0ÏBÏTÏ2Ëä±FµÃàéô³ø³²£¢yŽ›`ÏÔÏæÏøÏ ÝGøÌŠÃH±Ãàeùeù–Ŭ¥ÏÆ_p߂ߔß`¦ßr­¼å.Õ”Áé:ÙžÇÏïï*ï<ïNï¶ß,Ó ¸Ã:Ñ:ÓÜÑö³úµ^ï®ïÀïÒïäïöïý.ÙÜ׌ãôµ–ïNÿ`ÿrÿ„ÿ–ÿ¨ÿñŠÉÚÓ.û:ùDÿüÿ 2DÿÆ÷Êõ”˪§R¤¶ÈÚìùÂùnØû<ÿ@Rdvˆø.טÅL¹æÿèú //0/ž¢¥Ã¶J¹Ô@/–/¨/º/Ì/Þ/H³H·5,^‘‚/8?J?\?n?€?¤¥*Nµø³Ô^•Š?â?ô?OO*O˜;¤§¨¥x)Æ?zOŒOžO°OÂOÔO¶…þ›\G`KrO&_8_J_\_n_F/îO«^—|_Î_à_ò_ooÜOü“Z™°WnOhozoŒožo°oÂo.k^™ëÛxÅ Õ2BÿÖÿHýrÕïzÿ$"àéÐç Ù ÿÿzf‡ñV¥zÙ6ëÀ" Ê0 úí®õù2Äÿ ’ ”·ü£0çÒ9BrÒ ÷D È»ÀóÂÿÄR£ñüý ,vr% '#ˆ÷–ٸ٦²h/–:è\v'šR/vÞë<-ГfÀ n/´÷ë +šRº#Z3Z5v6 N¼÷??*;ìÅ\T9º%Z1Z7~r¶µƶµA.+ôd¦?º;:"ëZðR9šO¦GAÆšÖÆÀC E,Oô-LOf`X!ÞÎ?B?”KûZDQBQ@YA¼A`UÄCÜåL @K2óO_« „õ°#¦IDSè_ûZZUûÞa|€|€nW†;xÇX#ÀðOªWlK_ð9Þ_foÚ¼%Ì€*y½s½svƒÞkx9æ-ô+„{NgvÁH0ãZh‡€ƒz—âuºCbWAÎ)J Àš=˜W:a~)àÉä?šR1#†t…xƒ„đƑ*›^SÄCvÜ+bíØo€›ð¢y¶ T7®‘ttַ“d§Â•àwC¼@»"Öà/Æ×¯òml]D¯Öú¡2™f«z…ìUh7(#æ ì/È…€˜S~•šÞ=¸#Z1X¡Y)Y)t™d­:wJS'â Zçº÷~w˜Qjµà:~·po¬‘ž³Y) d£Ÿ”RÇ¿(µŠ©ôë¼×®ÞcÉTk€¿4Ëo2Û9èÁtLÅPÇʓ̕nÍŽ­XçL)´«à~™Ò¥Lì=DQ2Yÿ)]J]Jt°PË\Ár«rÅŠ¥ùjyà–ͨϞ4«vßûZU Û9ÿZHÅRÍÌ—$¹Š§8 ~_|w¬Ï¢ "_d5*ãŒ×:åd­ ÝxËbs0Ó”90gǬQÜŸtm *åDÃÖb¥¤Õr¥ ×0Î³Š­f}¬©RØQ€HCà‰ìï’a@Áú¡t[ °¿€‡\pw¢Ï2$?~¹¢™"yø¡&Üå×¾½,»ÊÙDµîµŒëÞ÷ôií@W®“hƒÖ •ßÎ->-@ßPÕøÝHøìUjï{qŒï{Ž!ž"·HZXC°0Z·`·Ö胴|O° æŒgqŒ´!!ŽsªR )D vÇø XG$ý¶¯ðÔfßPBQ¶µÓœ6!qŒ¼#ªRÆ-*µ ×Þ·ø”1ò'Îùî×ÀbCB÷²_¤Àw¶AÓœïÓœï{AŽs,ãc,Ç*Ò/¤‹øùúë=@ZK?f¿yÊÏî;V5EjÉ*¹â%öð›øç¢û$ߤ;ž,>´éÎã6áÆjÊ* ÚtÙÎß¶ÈÚì`Ð`» ÈÜãJðùô ¦¯P/b/t/†/öØãhp"/0Ù¦ô/??`*?š-xõƸ#é*DÁ4§L¿Œ?ž?°?Â?Ô?ü`~ñ^3^3~ó”×p1€?*OßåprÿopDATE¿7-20gÐ0ÿ1, 21:08îZÑNAMaÑ FRþ{Ð_06_BMPÞZÑORIG~Ñfr÷ame‡Ð.bmp¾‹Ð 4ŽªÒRRHßÈßÚßìßþßï"ï4ïFïXïjï|ïŽïH¢ïïÌïÞïðïÿÿ&ÿ á<ý–õèH*ÿzÿŒÿžÿ°ÿÂÿ éJõTó<ôõR÷J Æÿ&8J\JÕÚ÷ú÷Šæûæ OÌÞðˆHõòù6!,:–‚Ot†˜ Üý60ÒÔôÿZ÷b/,/>/ÀØØp%€/èX /À/àÒ/ä/Z+&„)—1—119t'–/%°/h?z?L/=, 7"3Æ5$7p)N%X?O Oò/äõÒÄ9Æ3Ø9jAhCZI3Þ;¢)ü5OºOj ü1@Mv'Â7tEjMtCÐ?NT7R2ÊOb_JÕü1…°wTcxK$}FWNQèü{ÞEHM UJe:‡FƒÞ‰N‡ÿ9B¶µ¶µÆþts?ršoü}BýÀ7FgúcN‡îƒÞûZ0Œ•@þƒ¢‘šÖ“f<_0‘2Ÿ¦‡®‡èIÄ76‹`Š•‘“ˆ™ž•šÖH¡bÐbЕ|mT5–eŒo`èI`Kþe«Î¯ûZ‘H¡ûÞûÞN£N¡jA„G„mЗ؟@q"m’w<į(¡s€ËÀ…ò¿°ðÑ”á^Û½s„¬ãhÕ ™“bi2_4{Ñ~¥4±×rïâݵœåªãLõªåjÕ•ÐÀG„¼} -Ü2µ…xpw€}>ƒ2tÜñ ±¤íôùjÕң[¸™HïÆµóÄgÐe´5ÎÜñcÖ‚öÑìýŸ”P÷ÇŽ•®y" x°Õ~¡ ±ð6·Ìß&ùB2ÖY)„¦ç–œœhÙ z±î‰^žß4±édçxVŸj ØñY)Û9&ˆJó>>¦ Z Ø øéò¬…nïªWÀH÷Þœþý² +šßΙ‰ø0mÌ‹ØñÛ9]JÛ9r+ÚšbÓ ŠE€ŒÿijƳÿ°7$ÿîÑÛ9ÿZÛ9t,ÀÞ¬ãÄÇ tG^5õ€ü˜ùÕ>sœô)X¹Ç¶5å– êè?ØåòËBWRç"CÂߢ©ÌVE†^Óôû (£@Zr-¼K‚9>¿ü'b+WåJóé:7†•w2åNÅ »¼IÀ6)"Ýô-¤u"$Y)2Å®WíÎYH?¦»€¤ß2+üSÖOÈÿ"€tNohÓfoì?±˜³¾€ol_ì/TµBÑ6ó’átºËbÕw{6QN;øÖq‚¡/úëÊOþŸ\)€ðÕ ±VÙÄ[|³²„iøùúù‚£€œoöy‚5N™–5ÔiFÓq}ŒÔï{Žs;ŠðvµÒ«X|÷øúúë#(»ªg~§\ü`ŽÏ9BӜӜ;ï{Ú,c,ñŽT…à†IzmØã³|ëúï7ûïû€¯ø¶ÛÞ/?P?b?t?®;¦Yv?²?Ä?Ö?è?ú? O†; [ˆK®SO`OrO„O–O¨Oè®]"WϾE0r­hÍzÏB±šR.ÓæµH³ú— BgÆÏ|ßàƒ®½cõ…î•Ú·šRÂÑx2ÕÂÓÂÛ¶µÆäÓ²¯j» Çtß ¹Â“&Gš‰0R—(ÙÎÛÐÛ¶µäшçìÕößÞ…Š•ïa¯¹¾<ß.ÕšRûZùÐÕ„åšÖ.ñH H ìщ ©Ô§á¾ïHϺ¿T“ÕÀÂÓóóõõäÑšÖûÞûÞ2õ4ñ´…Ìà‡ïÐåLɹNµ¼×† ýk¸å 2$Ê»è¢(÷}ïv„áü·|Y(«ºãdù`Øïbͼז½sL#l Òñãô—€RßfÛ¬ t´ÙÂÑÁ¶÷F%J#J%°¶µh!.óã̤Ç6jÙP0eª…Ø»z1ü †L#„L%ê#²Œç¶µšËžïv»¬!4åöÅ ¿¢õz12{2H)Ž=ô)ˆå4Ù¾=^ÝpÓb÷'È™œØ› ÷t$K„ÖIL+ùXKÄ?fÝdóð`|ÿh;CÖtct$EJ!ÖEŸ”€QàGó”ϜP¬è`0:¹2Á@Y)Y)jQ,I|S~SÞE¢õXI†lIÀW!¬Ò]&—xZŃ<·Ö a cp_ÆeL)îIDo²_jÙÀªJ5zýbËÃaÛ9Û9 aˆ9Âk*gR!^š[àù²ÉËw%T=Ní~ÀAÛ9]J]JjUJ#¾oàEìMâ¹¾?ë”)ð/ßìuÿZY)$A„9z]…‰ñ.Ó¦]à’ 2;Àw&–mØ92òw„;ÔC"cÞO&žË@6(©Ì_”KÖwh72©`ªaÛ9t8'ÎO^‚¦[êùÀÍtgî3ºð[AhQªaâ™è'ü—ˆY€y4ÙÎê ŸT©Ð}h7z3€aØ!8Mˆ_¬õxŸ—Á1êÿ  `»îYqŒÿï{qŒŽs,cA ÷ä'J)ª­Î…˜Ç”u`fó2¯D­R¯xÓœÀ·È±ÐÕü 0gL!Z ^µ Ë6!øÁä[j˜à=jx‰U­bÁÑï?{,cªRªÑØ:-` §Æ‰ÐbE¼Áù¾ÅÀØ7”'ÞÍzÿz!„áӜӜï{ÑÑÙxÃàìG`îGôOj¹øúëàú&ëÔÏä˰'îS¨ÕÀ±²ÓŠÐÙùø¸¯:‰îQùúïÿûóüëúøïáûfýøìÏþÍŽsŽsæ fí~ïr5.!r'rµãóü×ý á¬á¸í(éDÅÎ6!PãıàÎ%bç ù¾×ªõ¯x%¸á·ïûSðÛþVñù^ÿ(é@LÉ-Bw^ç^QæÓæ×,ý6‹Ð©¸ã®á×ýóü¤ á¼Çnûä¥àï‚‹Î#¨÷ûnÇøôg.§¸çóüïûïûXódѰÖ﮹@÷$'n9Òõ¤ÅÔùHià‹Ì3¸éZñPd׸~ÿîYR[H 0Òÿ¢õ=Ô§õvA¸ëïûøÌí/Ú BIV×.«Î5 />?¸á°V3ô5@]Ú^)Ž9?3?‚·D?F?ö=”“PÏ–eâuRY:O ;,£z'N‹ä?ì= ¸œEþ9À+v7:.+ÈLOÔE¬yø„ON7¤A ¸AÈA7È‚ÐBQAȤG´MÀOÐKêKæ÷.§Y†·þ…(_R5BSæQHSLQ¤E´K€È/°7mè÷žwÂ?ÐÉ2``Î_>SæQÃàÃàæY¢EÀ/x9Àx7ºmZGFoò¤‘hxrolÞWÃàé0qŽaŽaòS¤C`« uf[lPBkìoük pxpxlaxnkšCˆcéeù2sŒa–oþ_\.„òo¦xˆR€xV‚`{˜CŠcÔqz2uFSB{ #ö}$‹ð$‹ ;Uüm ˜T†±qmhÞW0qz‡ÚsæWžmd§øÈ[nßô€õ÷Uƒ’neÞSæQ0s ›„‹Duª·î—œ…ô—§Ö ÖÃê£À6 W1—“ŸŸU4*yd¥Üs:sð[rð{0­`7WpÙÐ6¢9£=¡›™©ž†g.q.sr§Ö™¤AJÅ6µG@¿Ú‰Š¹ô€`W1Ù©›‘C¯}hAÈr¥ µ6uæUžI" d7˜wº¯B‡R‚‰³=£!ÇS·–X¥†kr§„‡J[Xe„ÏViàtWʼn³A§5ʬ™@SäU6ufËòU¤C¶%€Ç€ËœÉU¶s’¹Ã½Á/Ã÷¹;È4WLQòÅâUšÙîW¤E`pEÒÝÌ_TØ·Å·Å»Ãýˆº}šE ×ìU ½¾ßrï„ïîߨæsµë%îR9œGHUîWJUdïÿ*ÿ<ÿ¦êYü@ÿØë8çæçÕ¤IpÿÄÿÖÿèÿúÿ vm*Š÷ªÿ\n€’¤¶î?÷Ü P&8J\Æ€ô¤¶ÈÚìþ/"/4/F/X/j/|/Ž/ /²/Ä/Ö/è/ú/ ??0?B?T?f?x?Š?œ?®?À?Ò?ä?ö?OO,O>OPObOtO†O˜OªO¼OÎOàOòO__(_:_L_^_p_‚_”_¦_¸_Ê_Ü_î_oo$o6oHoZolo~oo¢o´oÆoàØoêoüolproÿpDATEß7-203p01, 21:08&qwNAM-q FRGp_08_BMP&qïORIGJqfra{meSp.bmpWpß 4ŽvrRR”¦¸ÊÜî$6HZlŸ˜¥\˜ª¼ÎàòøŒ§¢­¤«â³öFŸXŸjŸ|ŸŽŸl›¢§§©V»’ŸòŸ¯¯(¯f¶“°•Z¯²™B·0Ó2¯À𝬝¾¯4¯ä·L«6!ö¥³b¯r«0ÕЯD¿V¿h¿•䯷ü¡ ³·ü£ü¥™Ö—æßè¿ú¿ Ï~µ0D©œ·¤»µ—1¨¹¿Ð¹Ú¿Ï¢Ïú„»ø§BÏTÁTÃTÍü£Ê™<×€Ï8ßJßz¿.ÏJɌيÓàϺ½(·~ÏÜßîßbß•~ߌӃØ9ŒÛ’ÙXÏÔ›ÊÓ2ô߈ïúßlßˆÕŠÛØ94á4åÖã@ﺷ´•hé2Îß,ÿl$Ѭï íÖåvÿÖëœÙfÍÄÙtïÐÿ`BûLýÀërÿÖá9B2å¦ÝÊ—léÂÿx‘ìõ禹"Ä$̆÷> hÏõhÜÿìý¹Ìë hÊÜø¥®ÿ  0 ëÆéXšR !%t0éðØ‘º÷fœïÚÀÈï #ª'%#Ø9?¶µƶµÎ!äåìй°Æ”@® #ƪ'ûZR7ª%Î!Æ n5Î!Ø-Òbÿ/-Jù˜·L'R3ô3ð5ð5j3šÖCt?þçì-V/æûØ‘Ê9fûÒ %ø3ô5<ô;GûÞšÖ.p.pÒ!|?ÀÝ¢1¤?ñ"Ó<Ú=H9–GOöIYí|ML9æDW9tý ‘2ur‡‘x‡”e2•È: N¥”?ìG0ƒ’üvMÄtÖt‘Êy“º—~‰ö7Â%†€Œ?xw,"9^c¬ÄPY)Y)¦‘ •—Ÿ”b¡`¡ ›Ô$Œü›Â‰îAFc ­ ³Ú9D©¬Ÿ^§f¡Æ•ЙV3ä™öí ÚI‹0…_ª Û9Û9J¡•&u^£¿v©€©0·J ×ñl“º©ð¨YåÒ刳]J]JY)‘äWþ¯ÂŸFSÊ»€fçvy¸©_îLj³ÿZ]JL£€ixƒª·f£x…ìW'tÉ8/º‡‰ú#x¨]F‡ˆ±Ö]JޱN¡ò7—FÉXÏhÅÀ'üy*ßäGZ»v'gªnÓvÕ9B8YŒÝ¾›’eV9tÇàØµ¤ù^Ÿ\»ðkU­ÓœqŒï{ï{D¡tå çBSž·èÅØå(—Ø›úuØ· P¿Éðeo¶µÓœ®åŽs¶ãD3}èQVÇzhÉÀ÷Ô+ÂkâKïHõU­¬çŽs,c¾q&YÜËÎŽÿ¢ÿeš¯˜Ï0‹ÜAüðñ®ãŽsŽsªRª½pà;~k ({Ø™F €ÄÓLC o†í¨ËÌa”ï={š,cªR.!€Àê=ÎåÌygÖ¼Û6!`LGj›PÕx'U­°áqŒþñ,cfkro¼ pêYÖ™ìÆÁø§8ðÈaÒgj>ý´qŒšxG„Gúà]žMÞ—¾Ûû—1F!úëúøóüTIBkÚCp¿ìþFSFYþ7Ð/"×ì#?ïû×ýóüô)LCîIÐe¨[nãÄÅ~Ohù˜Op('†©´gŠ5ùëï ?óü×ýÛþœ?ö+>ýžP‹F72Y Güëä”´õ4Añ •0ׯ|›°òƒ4¡eùeù:©B£¤›Z‡b¥&GÖŸrï"ÿ¬¯|Ÿô:¡Ú¡|³:¯ô© ÄÅ ¿`{ö.õ\¿À­.§|»æ¥ž“R‡þ­²±XÍʹb濘Ï­Чثâ§ö…ú¶uºwÎ5U*»¬¶ÏBßÇ.£”‘æ¥ÒÏö…Nƒ´{Ä»ß~ÍX'HßêßÅþƒ”•è¥ØÏX‹ôÇÆ¿d\å&×F·`|áîß’ïåºÅ€´ïô¯îÍ$7Ò½:»Z'xhôï7ÿ)¤PƒàÅÄíZ0ï@å×\åžû†Ëˆ¼ðxÀò#ô(ÿÀÞÿ¼wPƒP‡üùV¯°ÛNŸ*ö˜\½÷õÍÿƒÆ®{Z‡Z®sÀw *šõœÿÈÛä‚ ü˜þ_ÿ‹x¸—xÿc°Ú Ú¢§Àšqý_Ï9ópi ôàâ‚ÀÐ8"›ý­Ëò¾r/@„/–/RK'¼7â‚hª p?#›¡_±a/ ?'?9?K?]?ø^ Ñ!Ó#×!yI+¿ù?¹?Ë?Ý?ï?Oq3h²M#G#}3ý«ù#Ãó_/]OoOO“O¥OI«ÇK?GHPO__(_:_L_p4³ù!w3oW{Ue ïO£_µ_Ç_Ù_ë_³OÁñ¿ó½÷c §?EoWoio{ooû]Eµg/gŸ<8oìoþo"4 oD5caueukuÝo¡³Å×éUuˆì2DVhzŒž°ÂÔæø ŸŸ.Ÿ@ŸRŸdŸvŸˆŸšŸ¬Ÿ¾ŸÐŸâŸôŸ¯¯*¯<¯N¯`¯r¯„¯–¯¨¯º¯Ì¯Þ¯ð¯¿¿&¿8¿J¿\¿n¿€¿’¿¤¿¶¿È¿Ú¿ì¿þÜpropDATÿE7-2ý0À01, 21w:08 ÁNAMÁ÷ FR-À_09_÷BMP ÁORIG¾0Áframe9À.÷bmp=À 4}Ž\ÂRRú¿zόϞϰÏÂÏÔÏæÏøÏ ßß.ß@ß^å46BßÀ~ßߢߴ߯ߨßøŽùŒû,sÜß,ï>ïPïbïtïRÓôÛðáŠûŠû|xïØïêïüïÿ‚ï˜ížåD÷B÷: ÿ€ÿ’ÿ¤ÿÞß,ÿœã6!Þûâóàó¬å¢ã+¶ÿ*<NNÕ ŠéØû6!„‚Þó„Ö÷ø× ÄÖèºýXÓ0Fùî÷”„—1(œ ²íÀvˆZ r *À6Ô<œ ï2!2˜ /2/$ÿºÂv!Ðx#v'àõ ç^ /Â/Ô/‚îqRµ¦éŽÎ5Ø97$?â ç¸°/h?0z?ì/ &;Ø93º79d-¨ 'X?OœN/¤?1º1^OXC,=Ь ú5f¸Oˆ5Ž3n JIXEZOØ99BSpKà°ïü?X_¢XÑHõ€NMWS®]nE"]æ7¶ H_þ_PÓÔKú%¦; WDo´[¼UzM¦FWõ_ÇO3Jxl+nEª_9BšRôcôaúcUÀ_0]FW:qšo®o–?t% [øeüeuw9B¶µ°unoHóä_Àô_TÜM°;@göcšRcûZ˜u8‡¬sÆR‡¶wâ†m2à†9Ž9l [öe:‡8â…q°qRšÖúƒZƒ¾†o:sŽþw|SäMÑ0¢ÅÊ¥ôÄÀÇÈÅøX…w°Ÿ »bË,¿Z):Ñ2ÖÞÓB×Nß„å¾Í°s^gÐ;NÉÀ½Ô•„×ô™šÁÖY)Û9€áâ×bµøÙç¾Çr±Š—^gš¿¢'€‰ÐfÅÓþsô)s þ~á]J]JÛ9Y )äѼ©´Çç¢ã²éºãuw4˜ß„…dÅðt¡ê™÷|á]JÿZà$ó,ñ.û®Ç㟔Ÿ”¦ëÒ£8ƒÂépù8ïJëþ ûU­U­ÓœïÇ{qŒ¸ù(ñ@Ñüe¨Ïè÷î÷dÙŽ•j÷äÏ`J=`É‚ƒPúŽsñt(ñšÃˆuv r³Šç¬ Ìïnp§x£ÓÞ°qÓœqŒXŽs,cªR:Ñj©«‚” 8…\&8’R ¦¯ϦïHšwàì›t˜ÿ:!qŒœï{F%Z›y|;°é”/ -\Ë ù3Óœš ,cð#¥œSôeb»?bÛÆ¡t—¾[h™”e.)zÁâ#Ž1Èc,ÙÊ…v =ãjE2?ôc0 ÔYÔœù2béÞ·À‹X»´7VÕ‚/87ûZ¸[ð7pÜ KHZŸ”yz.9Ô?D9lecF[¤ÝúåÕL“z_Œ[\¹Æp¹\ùÈ_t÷|§Ð¬Ý¤ù:³<·R)Ê©ökˆ›,_¬‘ø,s|£Ö}Rí`ë:¹âO”]ƥĥžwD‰Z‡ÿ6!øùëú?úëúóü€©„ƒg⟀ÏJ½©}ˆ›yü'R§øúïûïû×ýÚy|¥Ô™û0N“4G(o*°âêƒ0 ¾ Ðs|Ûþ€|©°ð㊫ö/šRê… ¸€“„‘Š‘Œ•êƒy+ó6!|£vëúÛþ×ý2Ÿ–‹Â#ÎOzóf€|—$¯˜—ꃦŸ×|¥øóün¡ØŸצý$Ù6”9Ø9©AÈġʡ€È§4§:§î?ðÅÜ—“ïû|¯†¯˜¯ÞG§Æ¡‚7ЂÐÊ£AÈj·Ö©`š•ŸZ7Ü—ÖqïûÔqúÒq$¿tÏ¢«¼©p³ ËrµÄ£6«”Mð˹À³€dÁ0wÜyºßÌ×¾§ ÃÃà¨Ã¬ÃÅx»ê‡ª+¢E'Ê·ÐqfÏοbç”Ó‚“¢Å¬Á²ÁNÕªÅhµÂ¥6©ÞC'JÇNUÙ.yßE1R‰È\·¨ÃéìÑòÓìÓÍÖ«ÖÅBÏvSJ“žÛ€Pï¾ÝÊI€“Ê¡²ÁòÕeùöÕîÑ²É ïÖň×ê_C\ïüïæ—Zwêp³ìÑeù2õôÕ¢épµ2­ )ŒßÊ×àÿ¤ÿú}à×0ÿPÙÇ2¯lùvÿT[¨ÿHýˆ“èÕx ìÓìûÆÏ I’ÿè°ýh vX×x·œ X5ìÅrU–oØŠøAêƒÇŠãJ׺Ë@ÊïÀÔ(/:/¨þ·¢Ã´ÉÖ„•ì’g<á>åBw@/Ð/â/€•È¥?Ü­0çÛN[þUè/r?„?H+ õü»lÙ4«.é6åÚíŒÿ OO.O´ûþ%ˆ›:«23FW€E°C®Gæï¬O¾OÐO–?ù]~GgJ[R[ÞOR_d_v_àOF9g‚G'ê?˜Eˆ_ð_oo&oš=š]XoL•Ô_„o–o¨oºoÌo4oJoÈ_F“Üo,>ðPbt†}``XL“È P5h¶rx¶p™p†Ôæø Œ|¾»qxˆ˜F€ JD€`L„ V‚Gˆ@‚¿w‰›­¿-¹s|EW°ÀÐô„W…ˆ`‚gŸ/ŸAŸSŸ eŸ‹~æˆóõ‡ÀP[‹ tŸÈŸÚŸìŸþŸ¯€š‹¡“ÿC• Ÿe¯w¯‰¯›¯­¯¯å…U…ÿK[ƒ_¿¿+¿=¿O¿a¿…•Q£I˜¤’¥‘W‡õ¥³’¿¸¿Ê¿Ü¿î¿ÏÜŠÕ¥Gƒ-Çõ£÷¥ý¤¨¿^ÏpςϔϦπœAƒ=×µõ£S¥£´NÏßß&ß8ßJß"®Õ¥ußû£¡¿Ÿß±ßÃßÕßçßU߇“`ŠÔéAÅçÅ“ßGïYïkï}ïïûß å¹s‹×ÉéïÏéïûï ÿÿ1ÿCÿ—ãƒãg×iõÝïÿ¡ÿ³ÿÅÿ×ÿéÿSý }ÿ/ASew‰›ð­¿Ñ‹ZpropÿNAME ÿGrabberI÷nfoòPACKNú2iú ÿFor inteÿrnal useÿ by the gÿallegro4.4-4.4.2/addons/allegrogl/examp/running.h000066400000000000000000000014101173507505700215650ustar00rootroot00000000000000/* Allegro datafile object indexes, produced by dat v3.9.38 (CVS), MSVC */ /* Datafile: running.dat */ /* Date: Fri Jul 20 17:03:17 2001 */ /* Do not hand edit! */ #define FRAME_00_BMP 0 /* BMP */ #define FRAME_01_BMP 1 /* BMP */ #define FRAME_02_BMP 2 /* BMP */ #define FRAME_03_BMP 3 /* BMP */ #define FRAME_04_BMP 4 /* BMP */ #define FRAME_05_BMP 5 /* BMP */ #define FRAME_06_BMP 6 /* BMP */ #define FRAME_07_BMP 7 /* BMP */ #define FRAME_08_BMP 8 /* BMP */ #define FRAME_09_BMP 9 /* BMP */ allegro4.4-4.4.2/addons/allegrogl/examp/test.c000066400000000000000000000104731173507505700210700ustar00rootroot00000000000000/*---------------------------------------------------------------- * test.c -- Allegro-GL test program *---------------------------------------------------------------- * Based on firstogl.c. */ #include /* Note: Under Windows, if you include any Windows headers (e.g. GL/gl.h), * you must include first. To save you working out when this * occurs, `alleggl.h' handles this for you, and includes . If * you need other GL headers, include them afterwards. * * Also note that user programs, outside of this library distribution, * should use <...> notation for `alleggl.h'. */ #include "alleggl.h" void display (void); struct camera { double xangle, yangle, zangle; double dist; }; struct camera camera = { 0.0, 0.0, 0.0, 20.0 }; double angle_speed = 5.0; double dist_speed = 1.0; int frames = 0; volatile int secs; void secs_timer(void) { secs++; } END_OF_FUNCTION(secs_timer); void set_camera_position (void) { glMatrixMode (GL_PROJECTION); glLoadIdentity (); glFrustum (-1.0, 1.0, -1.0, 1.0, 1.0, 40.0); glMatrixMode (GL_MODELVIEW); } void keyboard (void) { if (key[KEY_LEFT]) camera.yangle += angle_speed; if (key[KEY_RIGHT]) camera.yangle -= angle_speed; if (key[KEY_UP]) camera.xangle += angle_speed; if (key[KEY_DOWN]) camera.xangle -= angle_speed; if (key[KEY_PGUP]) camera.dist -= dist_speed; if (key[KEY_PGDN]) camera.dist += dist_speed; set_camera_position(); display(); } void display (void) { // Clear the RGB buffer and the depth buffer glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Set the modelview matrix to be the identity matrix glLoadIdentity(); //Set the camera glTranslatef (0, 0, -camera.dist); glRotatef (camera.xangle, 1, 0, 0); glRotatef (camera.yangle, 0, 1, 0); glRotatef (camera.zangle, 0, 0, 1); // Save the camera matrix glPushMatrix(); // Translate and rotate the object glTranslatef(-2.5, 0.0, 0.0); glRotatef(-30, 1.0, 0.0, 0.0); glRotatef(30, 0.0, 1.0, 0.0); glRotatef(30, 0.0, 0.0, 1.0); glColor3f(1.0, 0.0, 1.0); // Draw the sides of the three-sided pyramid glBegin(GL_TRIANGLE_FAN); glVertex3d(0, 4, 0); glVertex3d(0, -4, -4); glVertex3d(-4, -4, 4); glVertex3d(4, -4, 4); glVertex3d(0, -4, -4); glEnd(); glColor3f(0.0, 1.0, 1.0); // Draw the base of the pyramid glBegin(GL_TRIANGLES); glVertex3d(0, -4, -4); glVertex3d(4, -4, 4); glVertex3d(-4, -4, 4); glEnd(); // Get the camera matrix back glPopMatrix(); // Translate for the cube glTranslatef(2.5, 0.0, 0.0); glRotatef(45, 1.0, 0.0, 0.0); glRotatef(45, 0.0, 1.0, 0.0); glRotatef(45, 0.0, 0.0, 1.0); glColor3f(0.0, 1.0, 0.0); // Draw the sides of the cube glBegin(GL_QUAD_STRIP); glVertex3d(3, 3, -3); glVertex3d(3, -3, -3); glVertex3d(-3, 3, -3); glVertex3d(-3, -3, -3); glVertex3d(-3, 3, 3); glVertex3d(-3, -3, 3); glVertex3d(3, 3, 3); glVertex3d(3, -3, 3); glVertex3d(3, 3, -3); glVertex3d(3, -3, -3); glEnd(); glColor3f(0.0, 0.0, 1.0); // Draw the top and bottom of the cube glBegin(GL_QUADS); glVertex3d(-3, -3, -3); glVertex3d(3, -3, -3); glVertex3d(3, -3, 3); glVertex3d(-3, -3, 3); glVertex3d(-3, 3, -3); glVertex3d(-3, 3, 3); glVertex3d(3, 3, 3); glVertex3d(3, 3, -3); glEnd(); glFlush(); allegro_gl_flip(); frames++; } int main () { allegro_init(); install_allegro_gl(); allegro_gl_clear_settings(); allegro_gl_set (AGL_COLOR_DEPTH, 32); allegro_gl_set (AGL_Z_DEPTH, 24); allegro_gl_set (AGL_FULLSCREEN, TRUE); allegro_gl_set (AGL_DOUBLEBUFFER, 1); allegro_gl_set (AGL_SUGGEST, AGL_COLOR_DEPTH | AGL_Z_DEPTH | AGL_DOUBLEBUFFER | AGL_FULLSCREEN); if (set_gfx_mode(GFX_OPENGL, 640, 480, 0, 0) < 0) { allegro_message ("Error setting OpenGL graphics mode:\n%s\n" "Allegro GL error : %s\n", allegro_error, allegro_gl_error); return -1; } install_keyboard(); install_timer(); LOCK_FUNCTION(secs_timer); LOCK_VARIABLE(secs); glShadeModel (GL_FLAT); glEnable (GL_DEPTH_TEST); glCullFace (GL_BACK); glEnable (GL_CULL_FACE); install_int (secs_timer, 1000); do { keyboard(); } while (!key[KEY_ESC]); set_gfx_mode (GFX_TEXT, 0, 0, 0, 0); allegro_message("Frames: %i, Seconds: %i, FPS: %f\n", frames, secs, (float)frames / (float)secs); return 0; } END_OF_MAIN() allegro4.4-4.4.2/addons/allegrogl/examp/tex.c000066400000000000000000000130451173507505700207070ustar00rootroot00000000000000/*---------------------------------------------------------------- * tex.c -- Allegro-GL test program -- texturing test *---------------------------------------------------------------- * Based on alleggl/examp/test.c. */ #include /* Note: Under Windows, if you include any Windows headers (e.g. GL/gl.h), * you must include first. To save you working out when this * occurs, `alleggl.h' handles this for you, and includes . If * you need other GL headers, include them afterwards. * * Also note that user programs, outside of this library distribution, * should use <...> notation for `alleggl.h'. */ #include "alleggl.h" void display (void); struct camera { double xangle, yangle, zangle; double dist; }; struct camera camera = { 0.0, 0.0, 0.0, 20.0 }; double angle_speed = 5.0; double dist_speed = 1.0; int frames = 0; volatile int secs; GLuint tex; void secs_timer(void) { secs++; } END_OF_FUNCTION(secs_timer); void set_camera_position (void) { glMatrixMode (GL_PROJECTION); glLoadIdentity (); glFrustum (-1.0, 1.0, -1.0, 1.0, 1.0, 40.0); glTranslatef (0, 0, -camera.dist); glRotatef (camera.xangle, 1, 0, 0); glRotatef (camera.yangle, 0, 1, 0); glRotatef (camera.zangle, 0, 0, 1); glMatrixMode (GL_MODELVIEW); } void keyboard (void) { if (key[KEY_LEFT]) camera.yangle += angle_speed; if (key[KEY_RIGHT]) camera.yangle -= angle_speed; if (key[KEY_UP]) camera.xangle += angle_speed; if (key[KEY_DOWN]) camera.xangle -= angle_speed; if (key[KEY_PGUP]) camera.dist -= dist_speed; if (key[KEY_PGDN]) camera.dist += dist_speed; if (key[KEY_A]) { glDisable (GL_CULL_FACE); // TODO: remove me! algl_alert ("Alert!", NULL, NULL, "OK", NULL, 0, 0); glEnable (GL_CULL_FACE); // TODO: remove me! } set_camera_position(); display(); } void display (void) { // Clear the RGB buffer and the depth buffer glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Set the modelview matrix to be the identity matrix glLoadIdentity(); // Translate and rotate the object glTranslatef(-2.5, 0.0, 0.0); glRotatef(-30, 1.0, 0.0, 0.0); glRotatef(30, 0.0, 1.0, 0.0); glRotatef(30, 0.0, 0.0, 1.0); glColor3f(1.0, 0.0, 1.0); // Draw the sides of the three-sided pyramid glEnable (GL_TEXTURE_2D); glBindTexture (GL_TEXTURE_2D, tex); glBegin(GL_TRIANGLE_FAN); glTexCoord2f (0, 0); glVertex3d(0, 4, 0); glTexCoord2f (1, 0); glVertex3d(0, -4, -4); glTexCoord2f (1, 1); glVertex3d(-4, -4, 4); glTexCoord2f (0, 1); glVertex3d(4, -4, 4); glTexCoord2f (1, 0); glVertex3d(0, -4, -4); glEnd(); glColor3f(0.0, 1.0, 1.0); // Draw the base of the pyramid glBegin(GL_TRIANGLES); glTexCoord2f (1, 0); glVertex3d(0, -4, -4); glTexCoord2f (0, 1); glVertex3d(4, -4, 4); glTexCoord2f (1, 1); glVertex3d(-4, -4, 4); glEnd(); glLoadIdentity(); glTranslatef(2.5, 0.0, 0.0); glRotatef(45, 1.0, 0.0, 0.0); glRotatef(45, 0.0, 1.0, 0.0); glRotatef(45, 0.0, 0.0, 1.0); glColor3f(0.0, 1.0, 0.0); glDisable (GL_TEXTURE_2D); // Draw the sides of the cube glBegin(GL_QUAD_STRIP); glVertex3d(3, 3, -3); glVertex3d(3, -3, -3); glVertex3d(-3, 3, -3); glVertex3d(-3, -3, -3); glVertex3d(-3, 3, 3); glVertex3d(-3, -3, 3); glVertex3d(3, 3, 3); glVertex3d(3, -3, 3); glVertex3d(3, 3, -3); glVertex3d(3, -3, -3); glEnd(); glColor3f(0.0, 0.0, 1.0); // Draw the top of the cube glBegin(GL_QUADS); glVertex3d(-3, -3, -3); glVertex3d(3, -3, -3); glVertex3d(3, -3, 3); glVertex3d(-3, -3, 3); glEnd(); /* Bottom is texture-mapped */ glEnable (GL_TEXTURE_2D); glBindTexture (GL_TEXTURE_2D, tex); glBegin (GL_QUADS); glTexCoord2f (0, 0); glVertex3d(-3, 3, -3); glTexCoord2f (1, 0); glVertex3d(-3, 3, 3); glTexCoord2f (1, 1); glVertex3d(3, 3, 3); glTexCoord2f (0, 1); glVertex3d(3, 3, -3); glEnd(); glFlush(); allegro_gl_flip(); frames++; } void setup_textures (void) { PALETTE pal; BITMAP *bmp, *bmp2; int w, h; bmp = load_bitmap ("mysha.pcx", pal); if (!bmp) { allegro_message ("Error loading `mysha.pcx'"); exit (1); } w = 128; h = 128; bmp2 = create_bitmap (w, h); stretch_blit (bmp, bmp2, 0, 0, bmp->w, bmp->h, 0, 0, w, h); destroy_bitmap (bmp); allegro_gl_begin(); glEnable (GL_TEXTURE_2D); glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); tex = allegro_gl_make_texture(bmp2); destroy_bitmap(bmp2); } int main () { allegro_init(); install_allegro_gl(); allegro_gl_clear_settings(); allegro_gl_set(AGL_Z_DEPTH, 16); allegro_gl_set(AGL_DOUBLEBUFFER, 1); allegro_gl_set(AGL_STENCIL_DEPTH, 0); allegro_gl_set(AGL_RENDERMETHOD, 1); allegro_gl_set(AGL_COLOR_DEPTH, 16); allegro_gl_set(AGL_SUGGEST, AGL_Z_DEPTH | AGL_DOUBLEBUFFER | AGL_COLOR_DEPTH | AGL_STENCIL_DEPTH | AGL_RENDERMETHOD | AGL_WINDOWED); if (set_gfx_mode(GFX_OPENGL, 640, 480, 0, 0) < 0) { allegro_message ("Error setting OpenGL graphics mode:\n%s\n" "Allegro GL error : %s\n", allegro_error, allegro_gl_error); return -1; } /* We want 24bpp textures */ allegro_gl_set_texture_format(GL_RGB8); install_keyboard(); install_mouse(); install_timer(); LOCK_FUNCTION(secs_timer); LOCK_VARIABLE(secs); allegro_gl_begin(); glShadeModel (GL_FLAT); glEnable (GL_DEPTH_TEST); glCullFace (GL_BACK); glEnable (GL_CULL_FACE); allegro_gl_end(); setup_textures(); install_int (secs_timer, 1000); do { keyboard(); } while (!key[KEY_ESC]); set_gfx_mode (GFX_TEXT, 0, 0, 0, 0); allegro_message("Frames: %i, Seconds: %i, FPS: %f\n", frames, secs, (float)frames / (float)secs); return 0; } END_OF_MAIN() allegro4.4-4.4.2/addons/allegrogl/extensions.txt000066400000000000000000000204161173507505700215710ustar00rootroot00000000000000AllegroGL will automatically load the following extensions: ARB Extensions: GL_ARB_multitexture GLX_ARB_get_proc_address GL_ARB_transpose_matrix WGL_ARB_buffer_region GL_ARB_multisample GL_ARB_texture_env_add GL_ARB_texture_cube_map WGL_ARB_extensions_string WGL_ARB_pixel_format WGL_ARB_make_current_read WGL_ARB_pbuffer GL_ARB_texture_compression GL_ARB_texture_border_clamp GL_ARB_point_parameters GL_ARB_vertex_blend GL_ARB_matrix_palette GL_ARB_texture_env_combine GL_ARB_texture_env_crossbar GL_ARB_texture_env_dot3 WGL_ARB_render_texture GL_ARB_texture_mirrored_repeat GL_ARB_depth_texture GL_ARB_shadow GL_ARB_shadow_ambient GL_ARB_window_pos GL_ARB_vertex_program GL_ARB_fragment_program GL_ARB_vertex_buffer_object GL_ARB_occlusion_query GL_ARB_shader_objects GL_ARB_vertex_shader GL_ARB_fragment_shader GL_ARB_shading_language_100 GL_ARB_texture_non_power_of_two GL_ARB_point_sprite GL_ARB_fragment_program_shadow GL_ARB_draw_buffers GL_ARB_texture_rectangle GL_ARB_color_buffer_float GL_ARB_half_float_pixel GL_ARB_texture_float GL_ARB_pixel_buffer_object GL_ARB_instanced_arrays GL_ARB_draw_instanced GL_ARB_geometry_shader4 GL_ARB_texture_buffer_object GL_ARB_depth_buffer_float GL_ARB_framebuffer_object GL_ARB_framebuffer_sRGB GL_ARB_half_float_vertex GL_ARB_map_buffer_range GL_ARB_texture_compression_rgtc GL_ARB_texture_rg GL_ARB_vertex_array_object Non-ARB Extensions: GL_EXT_abgr GL_EXT_blend_color GL_EXT_polygon_offset GL_EXT_texture GL_EXT_texture3D GL_SGIS_texture_filter4 GL_EXT_subtexture GL_EXT_copy_texture GL_EXT_histogram GL_EXT_convolution GL_SGI_color_matrix GL_SGI_color_table GL_SGIS_pixel_texture GL_SGIX_pixel_texture GL_SGIS_texture4D GL_SGI_texture_color_table GL_EXT_cmyka GL_EXT_texture_object GL_SGIS_detail_texture GL_SGIS_sharpen_texture GL_EXT_packed_pixels GL_SGIS_texture_lod GL_SGIS_multisample GL_EXT_rescale_normal GLX_EXT_visual_info GL_EXT_vertex_array GL_EXT_misc_attribute GL_SGIS_generate_mipmap GL_SGIX_clipmap GL_SGIX_shadow GL_SGIS_texture_edge_clamp GL_SGIS_texture_border_clamp GL_EXT_blend_minmax GL_EXT_blend_subtract GL_EXT_blend_logic_op GLX_SGI_swap_control GLX_SGI_video_sync GLX_SGI_make_current_read GLX_SGIX_video_source GLX_EXT_visual_rating GL_SGIX_interlace GLX_EXT_import_context GLX_SGIX_fbconfig GLX_SGIX_pbuffer GL_SGIS_texture_select GL_SGIX_sprite GL_SGIX_texture_multi_buffer GL_EXT_point_parameters GL_SGIX_instruments GL_SGIX_texture_scale_bias GL_SGIX_framezoom GL_SGIX_tag_sample_buffer GL_SGIX_reference_plane GL_SGIX_flush_raster GLX_SGI_cushion GL_SGIX_depth_texture GL_SGIS_fog_function GL_SGIX_fog_offset GL_HP_image_transform GL_HP_convolution_border_modes GL_SGIX_texture_add_env GL_EXT_color_subtable GL_PGI_vertex_hints GL_PGI_misc_hints GL_EXT_paletted_texture GL_EXT_clip_volume_hint GL_SGIX_list_priority GL_SGIX_ir_instrument1 GLX_SGIX_video_resize GL_SGIX_texture_lod_bias GLX_SGIX_dm_buffer GL_SGIX_shadow_ambient GLX_SGIX_swap_group GLX_SGIX_swap_barrier GL_EXT_index_texture GL_EXT_index_material GL_EXT_index_func GL_EXT_index_array_formats GL_EXT_compiled_vertex_array GL_EXT_cull_vertex GL_SGIX_ycrcb GL_EXT_fragment_lighting GL_IBM_rasterpos_clip GL_HP_texture_lighting GL_EXT_draw_range_elements GL_WIN_phong_shading GL_WIN_specular_fog GLX_SGIS_color_range GL_EXT_light_texture GL_SGIX_blend_alpha_minmax GL_EXT_scene_marker GL_SGIX_pixel_texture_bits GL_EXT_bgra GL_SGIX_async GL_SGIX_async_pixel GL_SGIX_async_histogram GL_INTEL_texture_scissor GL_INTEL_parallel_arrays GL_HP_occlusion_test GL_EXT_pixel_transform GL_EXT_pixel_transform_color_table GL_EXT_shared_texture_palette GLX_SGIS_blended_overlay GL_EXT_separate_specular_color GL_EXT_secondary_color GL_EXT_texture_env GL_EXT_texture_perturb_normal GL_EXT_multi_draw_arrays GL_EXT_fog_coord GL_REND_screen_coordinates GL_EXT_coordinate_frame GL_EXT_texture_env_combine GL_APPLE_specular_vector GL_APPLE_transform_hint GL_SUNX_constant_data GL_SUN_global_alpha GL_SUN_triangle_list GL_SUN_vertex WGL_EXT_display_color_table WGL_EXT_extensions_string WGL_EXT_make_current_read WGL_EXT_pixel_format WGL_EXT_pbuffer WGL_EXT_swap_control GL_EXT_blend_func_separate GL_INGR_color_clamp GL_INGR_interlace_read GL_EXT_stencil_wrap WGL_EXT_depth_float GL_EXT_422_pixels GL_NV_texgen_reflection GL_SGIX_texture_range GL_SUN_convolution_border_modes GLX_SUN_get_transparent_index GL_EXT_texture_env_add GL_EXT_texture_lod_bias GL_EXT_texture_filter_anisotropic GL_EXT_vertex_weighting GL_NV_light_max_exponent GL_NV_vertex_array_range GL_NV_register_combiners GL_NV_fog_distance GL_NV_texgen_emboss GL_NV_blend_square GL_NV_texture_env_combine4 GL_MESA_resize_buffers GL_MESA_window_pos GL_EXT_texture_compression_s3tc GL_IBM_cull_vertex GL_IBM_multimode_draw_arrays GL_IBM_vertex_array_lists GL_3DFX_texture_compression_FXT1 GL_3DFX_multisample GL_3DFX_tbuffer WGL_EXT_multisample GL_SGIX_vertex_preclip GL_SGIX_resample GL_SGIS_texture_color_mask GLX_MESA_copy_sub_buffer GLX_MESA_pixmap_colormap GLX_MESA_release_buffers GLX_MESA_set_3dfx_mode GL_EXT_texture_env_dot3 GL_ATI_texture_mirror_once GL_NV_fence GL_IBM_static_data GL_IBM_texture_mirrored_repeat GL_NV_evaluators GL_NV_packed_depth_stencil GL_NV_register_combiners2 GL_NV_texture_compression_vtc GL_NV_texture_rectangle GL_NV_texture_shader GL_NV_texture_shader2 GL_NV_vertex_array_range2 GL_NV_vertex_program GLX_SGIX_visual_select_group GL_SGIX_texture_coordinate_clamp GLX_OML_swap_method GLX_OML_sync_control GL_OML_interlace GL_OML_subsample GL_OML_resample WGL_OML_sync_control GL_NV_copy_depth_to_color GL_ATI_envmap_bumpmap GL_ATI_fragment_shader GL_ATI_pn_triangles GL_ATI_vertex_array_object GL_EXT_vertex_shader GL_ATI_vertex_streams WGL_I3D_digital_video_control WGL_I3D_gamma WGL_I3D_genlock WGL_I3D_image_buffer WGL_I3D_swap_frame_lock WGL_I3D_swap_frame_usage GL_ATI_element_array GL_SUN_mesh_array GL_SUN_slice_accum GL_NV_multisample_filter_hint GL_NV_depth_clamp GL_NV_occlusion_query GL_NV_point_sprite WGL_NV_render_depth_texture WGL_NV_render_texture_rectangle GL_NV_texture_shader3 GL_NV_vertex_program1_1 GL_EXT_shadow_funcs GL_EXT_stencil_two_side GL_ATI_text_fragment_shader GL_APPLE_client_storage GL_APPLE_element_array GL_APPLE_fence GL_APPLE_vertex_array_object GL_APPLE_vertex_array_range GL_APPLE_ycbcr_422 GL_S3_s3tc GL_ATI_draw_buffers WGL_ATI_pixel_format_float GL_ATI_texture_env_combine3 GL_ATI_texture_float GL_NV_float_buffer GL_NV_fragment_program GL_NV_half_float GL_NV_pixel_data_range GL_NV_primitive_restart GL_NV_texture_expand_normal GL_NV_vertex_program2 GL_ATI_map_object_buffer GL_ATI_separate_stencil GL_ATI_vertex_attrib_array_object GL_OES_byte_coordinates GL_OES_fixed_point GL_OES_single_precision GL_OES_compressed_paletted_texture GL_OES_read_format GL_OES_query_matrix GL_EXT_depth_bounds_test GL_EXT_texture_mirror_clamp GL_EXT_blend_equation_separate GL_MESA_pack_invert GL_MESA_ycbcr_texture GL_EXT_pixel_buffer_object GL_NV_fragment_program_option GL_NV_fragment_program2 GL_NV_vertex_program2_option GL_NV_vertex_program3 GLX_SGIX_hyperpipe GLX_MESA_agp_offset GL_EXT_texture_compression_dxt1 GL_EXT_framebuffer_object GL_GREMEDY_string_marker GL_EXT_packed_depth_stencil GL_EXT_stencil_clear_tag GL_EXT_texture_sRGB GL_EXT_framebuffer_blit GL_EXT_framebuffer_multisample GL_MESAX_texture_stack GL_EXT_timer_query GL_EXT_gpu_program_parameters GL_APPLE_flush_buffer_range GL_EXT_bindable_uniform GL_EXT_draw_buffers2 GL_EXT_draw_instanced GL_EXT_framebuffer_sRGB WGL_EXT_framebuffer_sRGB GLX_EXT_framebuffer_sRGB GL_EXT_geometry_shader4 GL_EXT_gpu_shader4 GL_EXT_packed_float WGL_EXT_packed_float GLX_EXT_packed_float GL_EXT_texture_array GL_EXT_texture_buffer_object GL_EXT_texture_compression_latc GL_EXT_texture_compression_rgtc GL_EXT_texture_integer GL_EXT_texture_shared_exponent GL_NV_depth_buffer_float GL_NV_fragment_program4 GL_NV_framebuffer_multisample_coverage GL_NV_geometry_program4 GL_NV_gpu_program4 GL_NV_parameter_buffer_object GL_NV_transform_feedback GL_NV_vertex_program4 GL_GREMEDY_frame_terminator WGL_NV_swap_group WIN_swap_hint GLX_EXT_texture_from_pixmap GLX_NV_video_out GLX_NV_swap_group NV_conditional_render NV_present_video EXT_direct_state_access EXT_transform_feedback allegro4.4-4.4.2/addons/allegrogl/faq.txt000066400000000000000000000140401173507505700201350ustar00rootroot00000000000000 AllegroGL FAQ ============= This is the AllegroGL Frequenly Asked Questions document. It contains answers to some of the questions which have been repeatedly asked by users of AllegroGL. The collection of these questions/answers was taken mainly from the nice people in the #allegro channel (EFNet) and the AllegroGL mailing list. Documentation you should read: The Allegro FAQ - http://www.talula.demon.co.uk/allegro/faq.html The various OpenGL FAQs - http://www.opengl.org/developers/faqs/technical.html - http://www.3dgamedev.com/resources/openglfaq.txt - http://www.sgi.com/software/opengl/faq.html - http://www.faqs.org/faqs/graphics/opengl-faq/ Table of Contents: ------------------ - License - Installation and Configuration - AllegroGL and MSVC - AllegroGL and Mingw - AllegroGL and Windows - AllegroGL and Linux/X - Allegro/AllegroGL and OpenGL License ------- Q: What is the license of AllegroGL? A: It is double licensed under GPL and zlib. Q: So is AllegroGL GPL? Can I use it without open sourcing my own code? A: No, it is not GPL. You just can choose to use it with the GPL license, in which case you are bound to open source your own code as well. You can just as well choose to use the zlib license though. See gpl.txt and zlib.txt for details of both licenses. Q: So does this mean, AllegroGL has not the same license as Allegro? Why is that? Will it change? A: Apparently, it seems to not be the same license. We (current developers) do not know why this is either - but it's how the original authors licensed it. We would like to change the license to be the same as Allegro and likely will do so for new versions. Installation and configuration ------------------------------ Q: How do I compile AllegroGL? A: See readme.txt for detailed instructions. Q: I ran the makefile file, but it complains about a missing 'alleg.lib' or 'liballeg.a'. What's going on? A: You need to make sure you built Allegro before being able to build AllegroGL. You'll also need to build Allegro and AllegroGL using the same compiler - mix and matching compilers will not work. AllegroGL and MSVC ------------------ Q: I made my own program/game with AllegroGL and MSVC, and it successfully compiles. However, it crashes when I run it, complaining about "DescribePixelFormat" not being in opengl32.dll. Is it a bug in AllegroGL? - or - I made my own program/game with AllegroGL and MSVC, and when I try to compile it, it gives me some linker error about missing functions. Is it a bug in AllegroGL? A: No, it's not. You just need to properly set up the libraries to link to. You should be using: user32.lib gdi32.lib alleg.lib agl.lib opengl32.lib glu32.lib. Any other library is optional. Q: I can't compile AllegroGL programs. I get tons of errors about _imp_malloc() being redefined. Help! A: Make sure you compiled with Multithreaded DLL runtime (Debug Multithreaded DLL in debug mode). The command line switch is -MD or -MDd (and NOT -ML). AllegroGL and Mingw ------------------- Q: I made my own program/game with AllegroGL and Mingw/Dev-C++, and it successfully compiles. However, it crashes when I run it, complaining about "DescribePixelFormat" not being in opengl32.dll. Is it a bug in AllegroGL? - or - I made my own program/game with AllegroGL and Mingw/Dev-C++, and when I try to compile it, it gives me some linker error about missing functions. Is it a bug in AllegroGL? A: No, it's not. You just need to properly set up the libraries to link to. You should be using: -lagl -lalleg -luser32 -lgdi32 -lopengl32 -lglu32. AllegroGL and Windows --------------------- AllegroGL and Linux/X --------------------- Q: AllegroGL doesn't work if I build it in Linux. I am using GCC 2.96 and RedHat 7.0. A: Either upgrade or downgrade your version of GCC to 3.0.x or 2.95.x. RedHat 7's version was taken directly from CVS and was in an unstable state. Q : My X server crashes whenever I use an AllegroGL application. - or - AllegroGL apps crash when I move the window or maximize it. A : This is likely to be a race condition. Allegro must be compiled with pthreads support enabled. Allegro/AllegroGL and OpenGL ---------------------------- Q: How do I convert a direction vector and up vector into something OpenGL can use? A: First, you'll need to use Allegro's matrix function. See get_camera_matrix[_f]() on how to use it. Then you can convert the Allegro MATRIX[_f] into an OpenGL matrix (GLfloat[16]) using allegro_gl_MATRIX[_f]_to_GLfloat(). After that, it's a simple matter of calling glMultMatrixf with the array of floats to apply the transformation to the current matrix. Q: Can I use Allegro's matrix and quaternion code with OpenGL? A: You can use most of Allegro's matrix and quat code in OpenGL if you need to do your own transformations. However, apply_matrix[_f]() and apply_quat() will NOT work properly due to the difference of coordinate system in between Allegro and OpenGL (see relevant docs). You should use allegro_gl_apply_quat() (or allegro_gl_quat_to_glRotatef()) instead. Sorry, there is no matrix application code yet. Q: Can I use GLUT 3D primitives with AllegroGL? A: You can use safely 3D primitives of the GLUT library since it uses "pure" OpenGL functions and makes no hardware nor platform specific calls. (Successfully tested on Linux/XFree 4.0, AllegroGL 0.0.18 and GLUT from Mesa 3.4.1). Q: How can I force textures built with 'allegro_gl_make_texture' to use bilinear filtering ? A: Use the GL command 'glTexParameteri' to change the way the texture is magnified or minified. For example, if you want to force bilinear filtering after a texture has been created by AllegroGL, you should add the following lines just after the call of 'allegro_gl_make_texture' : glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); You can also read the man pages of 'glTexParameteri' or the red book for more information. allegro4.4-4.4.2/addons/allegrogl/gpl.txt000066400000000000000000000432571173507505700201640ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. allegro4.4-4.4.2/addons/allegrogl/howto.txt000066400000000000000000000277021173507505700205370ustar00rootroot00000000000000AllegroGL HOWTO =============== HOWTO file AllegroGL web site: http://allegrogl.sourceforge.net/ Table of contents: 1.0 Introduction 1.1 About the library 1.2 About OpenGL 1.3 About this document 2.0 The Basic 2.1 Using AllegroGL for your Window 2.2 States and screen update 2.3 Coordinate Systems 2.4 Text and fonts 2.5 The Mouse 3.0 I just want OpenGL! Help! 4.0 Contact information 1.1 About the library ~~~~~~~~~~~~~~~~~~~~~ The library mostly provides functions to allow you to use OpenGL alongside Allegro -- you use OpenGL for your rendering to the screen, and Allegro for miscellaneous tasks like gathering input, doing timers, getting cross-platform portability, loading data, playing samples and drawing your textures. So this library fills the same hole that things like GLUT do. AllegroGL works with X Window, Microsoft Windows, DOS (via Mesa) and Mac OS X. 1.2 About OpenGL ~~~~~~~~~~~~~~~~ OpenGL is a long-standing Graphics API originally developed by SGI, but now controlled by the people at http://www.opengl.org. It is just an API and not an actual library; there are various libraries that implement the OpenGL standard from the likes of Microsoft (supplied with Windows). There is also a free implementation of the OpenGL standard called Mesa, but this is unofficial and shouldn't really be called OpenGL. You can get it at http://www.mesa3d.org. Mesa3D is a cross-platform library and even works in DOS. The OpenGL specification has reached version 1.4. As of October 2002 not all OpenGL drivers are compliant with 1.4 but many of them are compliant with 1.3. However Microsoft Windows OpenGL implementation is still only version 1.1. However, it is possible to access the OpenGL 1.3 functionality within Windows as long as the drivers supports it. You'll need to get the modified GLsdk (created by SGI and Intel). AllegroGL will automatically detect its presence and link to it. 1.3 About this document ~~~~~~~~~~~~~~~~~~~~~~~ This document serves as a guide to using AllegroGL from the perspective of an Allegro user, but it should be useful for anyone getting to know AllegroGL. It is intended to be read from start to end, as I've used explanations of how features work to explain other features. To install AllegroGL please read the readme file. See the included FAQ before asking any questions to the developpers. There is also a reference built from comments within the AllegroGL code, available as a download from the AllegroGL site. This details many commands and options that I haven't talked about here. 2.0 The Basics -------------- AllegroGL replaces much of Allegro's rendering code on initialisation with code that interfaces with OpenGL. Your old commands such as blit() and line() will still work and this is called AllegroGL Direct Mode. Unfortunately Direct Mode is incomplete and not very fast, so it is probably a better idea for you to use your own calls to OpenGL. It is important to remember that AllegroGL Direct Mode is emulated and the functions you are calling all end up as OpenGL modes. You should note that the above only applies to drawing stuff on the screen or on video bitmaps. Memory operations are still done using regular Allegro, so they work properly. If you don't already know OpenGL here are some suggested resources: - The "OpenGL Programming Guide" aka "The Red Book". This is a lengthy book which can be downloaded from http://www.opengl.org/ in pdf format. - If you need the OpenGL syntax reference, check out the OpenGL.org reference: http://www.opengl.org/developers/documentation/specs.html - Various specific tutorials are available from http://www.gamedev.net/ . This is also another place to try and download the Red Book. - NeHe's tutorials are available from http://nehe.gamedev.net/ - The AllegroGL sourcecode and examples! - There's a page full of links at http://members.net-tech.com.au/alaneb/assemble.htm - There is a set of teaching notes that I don't know the URL of entitled "CPEN 461/661, Spring 1997 OpenGL Tutorial" 2.1 Using AllegroGL for your Window ----------------------------------- - AllegroGL needs to be initialized like nearly all Allegro addons. You use the install_allegro_gl() command. I suggest you do it just after allegro_init(). - When you set your graphics mode, via set_gfx_mode(), you have to use one of the following devices: - GFX_OPENGL - Either a fullscreen or window, depending on platform and configuration. - GFX_OPENGL_FULLSCREEN - Fullscreen driver. Only supports "normal" resolutions, like 640x480. - GFX_OPENGL_WINDOWED - Supports any resolution, such as 543x365 Virtual screens are not supported. Regular Allegro screen modes are still available though, so using GFX_AUTODETECT will behave as if AllegroGL wasn't present. Allegro alone does not support an OpenGL rendering context, so OpenGL calls will *fail* when in an Allegro mode, and can even crash the computer. Only run OpenGL commands when in an OpenGL mode. If you want your program to be more portable, you should use GFX_OPENGL exclusively and let the driver decide whether to use fullscreen or a window. You can still give the driver a hint as to which one you'd like by using allegro_gl_set(AGL_WINDOWED, TRUE) or the likes. See the docs for details. IMPORTANT NOTE: If you switch out of an OpenGL mode, you will lose the current context. This means that all your converted fonts, display lists, textures, video bitmaps, and so on, will be LOST. Remember to destroy AllegroGL fonts before switching out of OpenGL to avoid problems when switching back in. 2.2 States and screen update ---------------------------- Now this is where I'm going to stress how OpenGL and therefore AllegroGL is/are a state machine. Basically this means you apply various states to OpenGL/AllegroGL which affect the behaviour of future functions. This is opposed to how Allegro normally does things as Allegro normally just uses lots of function arguments instead. - OpenGL/AllegroGL have their own page flipping code. You do it differently to Allegro. First, before you set the graphics mode, you need to set an AllegroGL state - allegro_gl_set(AGL_DOUBLEBUFFER, 1); - allegro_gl_set(AGL_REQUIRE, AGL_DOUBLEBUFFER); This shows how to do AllegroGL states. You set a state, then you tell AllegroGL if it is AGL_REQUIRE (required) or AGL_SUGGEST (suggested) or AGL_DONTCARE (irrelevant). - allegro_gl_flip() will do the page flipping. You don't need to bother juggling multiple screens. IMPORTANT NOTE: The page flip may be implemented as a double buffer. That's driver-dependant, and there's no way to control it from your program unless you interface directly with the drivers. The other important bit is that the 'screen' BITMAP may not be what you see on the screen. If you've flipped page, then 'screen' will contain the *previous* frame, and not the current one. In fact, the OpenGL defines the content of the 'screen' as *undefined* after a flip, so you are not guaranteed to have anything meaningful in there. It is recommended that you either clear the screen, or redraw the screen completely at every frame. Now how do you select the colour depth? Here's how to suggest an 8-bit colour depth: - allegro_gl_set (AGL_COLOR_DEPTH, 8); - allegro_gl_set (AGL_SUGGEST, AGL_COLOR_DEPTH); set_color_depth() will also work, but like Allegro, it becomes a required depth, which means that your application may not work on some machines if you don't support multiple depths. This is where AllegroGL comes in. If no color depth was specified by either calls to allegro_gl_set() or set_color_depth(), then AllegroGL will use the Allegro default depth - 8 bpp. One last graphics mode option: AGL_RENDERMETHOD can be set to 1 for hardware acceleration and 0 for software mode. Of course, all these graphics options must be set before you switch graphics modes. Graphic options will have no effect until set_gfx_mode() is called. OpenGL states are done with the glEnable and glDisable commands. 2.3 Coordinate Systems ---------------------- Allegro and OpenGL/AllegroGL use different co-ordinate systems. The AllegroGL Direct Mode commands should work the same as Allegros'. If you are using Allegro commands, and you are inside an allegro_gl_set_allegro_mode()/unset_allegro_mode() block, then the commands will behave like their Allegro counterparts. Otherwise, the behaviour is undefined. In Allegro, the Top-left corner of the screen is the origin. The X-axis goes to the right and the Y-axis goes down. The Screen is the same width and height as the resolution (eg. 640 x 480). In OpenGL, the centre of the screen is the origin. The X-axis goes to the right and the Y-axis goes *up* (not down). The Z-axis starts from the screen and goes out to you. This isn't important for using Allegro functions, but it is for OpenGL related functions. Screen coordinates are evaluated as 'units', where 1.0 unit may be different on each axis depending on the current modelview or projection matrix. We recommend you have a look at the Red Book for further details. 2.4 Text and fonts ------------------ AllegroGL handles fonts and text differently than Allegro does. Allegro fonts need to be converted to AllegroGL fonts using the - FONT * allegro_gl_convert_allegro_font(FONT * f, int type, float scale) function. where type is one of: - AGL_FONT_TYPE_DONT_CARE - font is either of the following... - AGL_FONT_TYPE_BITMAP - font as a bitmap - AGL_FONT_TYPE_TEXTURED - font as a textured quad Look up the accompanying documentation for details. - Fonts should be destroyed by using: void allegro_gl_destroy_font() To use textured fonts you must: - glEnable(GL_TEXTURE_2D); You can use the allegro_gl_printf function to draw AllegroGL fonts OpenGL style. You can NOT use Allegro's textout and textprintf on AllegroGL converted FONTs. Only regular Allegro FONTs work with the Allegro function. System fonts can also be loaded into AllegroGL. This method is depricated and will eventually be removed. 2.5 The Mouse Cursor -------------------- Allegro's functions for mouse management (show_mouse, set_mouse_cursor,...) can be used while an OpenGL mode is set. However two cases should be considered : 1. You are using Allegro's GUI : the cursor is automatically drawn by the GUI routines. You can manage your mouse cursor the same way you do with Allegro. 2. You are not using Allegro's GUI : you have to use algl_draw_mouse() to decide when the mouse cursor have to be drawn. In most cases, the best place to call algl_draw_mouse() is just before allegro_gl_flip(). 3.0 I just want OpenGL! Help! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1. Make sure you installed AllegroGL correctly. Refer to the readme.txt file for detailed installation instructions 2. Add this code at the top of your file: #include #include 3. Initialize AllegroGL by calling install_allegrogl() after allegro_init() but before set_gfx_mode() or other AllegroGL or OpenGL commands. 4. Use set_color_depth() then set_gfx_mode(GFX_OPENGL, ...) to set up a screen mode. If you need more control (like z-buffer depth), see the documentation on the allegro_gl_set() function. 5. Use various OpenGL, Allegro or AllegroGL commands. 6. Link with AllegroGL and OpenGL libraries. Note that the link ORDER MATTERS. Those are: For Mingw: -lagl -lalleg -luser32 -lgdi32 -lopengl32 -lglu32 For MSVC: agl.lib alleg.lib user32.lib gdi32.lib opengl32.lib glu32.lib For Unix and Linux: -lagl `allegro-config --libs` -lGL -lGLU For DOS (Mesa): -lagl -lalleg -lmesagl -lmesaglu For Mac OS X: -lagl `allegro-config --libs` -framework Carbon -framework OpenGL 7. Compile your program. 8. Rejoice! Contact information ~~~~~~~~~~~~~~~~~~~ Web page: http://allegrogl.sourceforge.net/ Mailing list: allegrogl-general@lists.sourceforge.net allegro4.4-4.4.2/addons/allegrogl/include/000077500000000000000000000000001173507505700202515ustar00rootroot00000000000000allegro4.4-4.4.2/addons/allegrogl/include/GL/000077500000000000000000000000001173507505700205535ustar00rootroot00000000000000allegro4.4-4.4.2/addons/allegrogl/include/GL/amesa.h000066400000000000000000000056651173507505700220260ustar00rootroot00000000000000/* $Id: amesa.h 8619 2001-12-27 00:57:05Z bcoconni $ */ /* * Mesa 3-D graphics library * Version: 3.4.2 * * Copyright (C) 1999-2001 Brian Paul All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /* Allegro driver by Bernhard Tschirren (bernie-t@geocities.com) * Updated to Mesa 3.4.2 by Bertrand Coconnier (bcoconni@club-internet.fr) */ #ifndef AMESA_H #define AMESA_H #include /* Names collision : We don't need them to build AMesa so let's undefine... */ #undef ASSERT /* Used by Mesa */ #undef INLINE /* Also used by Mesa */ #include #ifdef __cplusplus extern "C" { #endif #define AMESA_MAJOR_VERSION 3 #define AMESA_MINOR_VERSION 3 #define AMESA_FRONT 0x1 #define AMESA_BACK 0x2 #define AMESA_ACTIVE 0x3 typedef struct amesa_visual* AMesaVisual; typedef struct amesa_buffer* AMesaBuffer; typedef struct amesa_context* AMesaContext; AMesaVisual AMesaCreateVisual(GLboolean dbFlag, GLint depth, GLint rgba, GLint depthSize, GLint stencilSize, GLint accumSizeRed, GLint accumSizeGreen, GLint accumSizeBlue, GLint accumSizeAlpha); void AMesaDestroyVisual(AMesaVisual visual); AMesaBuffer AMesaCreateBuffer(AMesaVisual visual, BITMAP* bmp); void AMesaDestroyBuffer(AMesaBuffer buffer); AMesaContext AMesaCreateContext(AMesaVisual visual, AMesaContext sharelist); void AMesaDestroyContext(AMesaContext context); GLboolean AMesaMakeCurrent(AMesaContext context, AMesaBuffer buffer); void AMesaSwapBuffers(AMesaBuffer buffer); AMesaContext AMesaGetCurrentContext(void); BITMAP* AMesaGetColorBuffer(AMesaBuffer buffer, GLenum mode); void* AMesaGetProcAddress(AL_CONST char *name); #ifdef __cplusplus } #endif #endif /* AMESA_H */ allegro4.4-4.4.2/addons/allegrogl/include/GL/glut.h000066400000000000000000000725411173507505700217100ustar00rootroot00000000000000#ifndef __glut_h__ #define __glut_h__ /* Copyright (c) Mark J. Kilgard, 1994, 1995, 1996, 1998. */ /* This program is freely distributable without licensing fees and is provided without guarantee or warrantee expressed or implied. This program is -not- in the public domain. */ #include #include #include #ifdef __cplusplus extern "C" { #endif #if defined(_WIN32) /* GLUT 3.7 now tries to avoid including to avoid name space pollution, but Win32's needs APIENTRY and WINGDIAPI defined properly. tjump@spgs.com contributes: If users are building glut code on MS Windows, then they should make sure they include windows.h early, let's not get into a header definitions war since MS has proven it's capability to change header dependencies w/o publishing they have done so. So, let's not include windows.h here, as it's not really required and MS own gl/gl.h *should* include it if the dependency is there. */ /* To disable automatic library usage for GLUT, define GLUT_NO_LIB_PRAGMA in your compile preprocessor options. */ # if !defined(GLUT_BUILDING_LIB) && !defined(GLUT_NO_LIB_PRAGMA) # pragma comment (lib, "winmm.lib") /* link with Windows MultiMedia lib */ /* To enable automatic SGI OpenGL for Windows library usage for GLUT, define GLUT_USE_SGI_OPENGL in your compile preprocessor options. */ # ifdef GLUT_USE_SGI_OPENGL # pragma comment (lib, "opengl.lib") /* link with SGI OpenGL for Windows lib */ # pragma comment (lib, "glu.lib") /* link with SGI OpenGL Utility lib */ # pragma comment (lib, "glut.lib") /* link with Win32 GLUT for SGI OpenGL lib */ # else # pragma comment (lib, "opengl32.lib") /* link with Microsoft OpenGL lib */ # pragma comment (lib, "glu32.lib") /* link with Microsoft OpenGL Utility lib */ # pragma comment (lib, "glut32.lib") /* link with Win32 GLUT lib */ # endif # endif /* To disable supression of annoying warnings about floats being promoted to doubles, define GLUT_NO_WARNING_DISABLE in your compile preprocessor options. */ # ifndef GLUT_NO_WARNING_DISABLE # pragma warning (disable:4244) /* Disable bogus VC++ 4.2 conversion warnings. */ # pragma warning (disable:4305) /* VC++ 5.0 version of above warning. */ # endif /* Win32 has an annoying issue where there are multiple C run-time libraries (CRTs). If the executable is linked with a different CRT from the GLUT DLL, the GLUT DLL will not share the same CRT static data seen by the executable. In particular, atexit callbacks registered in the executable will not be called if GLUT calls its (different) exit routine). GLUT is typically built with the "/MD" option (the CRT with multithreading DLL support), but the Visual C++ linker default is "/ML" (the single threaded CRT). One workaround to this issue is requiring users to always link with the same CRT as GLUT is compiled with. That requires users supply a non-standard option. GLUT 3.7 has its own built-in workaround where the executable's "exit" function pointer is covertly passed to GLUT. GLUT then calls the executable's exit function pointer to ensure that any "atexit" calls registered by the application are called if GLUT needs to exit. Note that the __glut*WithExit routines should NEVER be called directly. To avoid the atexit workaround, #define GLUT_DISABLE_ATEXIT_HACK. */ /* XXX This is from Win32's */ # if !defined(_MSC_VER) && !defined(__cdecl) /* Define __cdecl for non-Microsoft compilers. */ # define __cdecl # define GLUT_DEFINED___CDECL # endif # ifndef _CRTIMP # ifdef _NTSDK /* Definition compatible with NT SDK */ # define _CRTIMP # else /* Current definition */ # ifdef _DLL # define _CRTIMP __declspec(dllimport) # else # define _CRTIMP # endif # endif # define GLUT_DEFINED__CRTIMP # endif # ifndef GLUT_BUILDING_LIB extern _CRTIMP void __cdecl exit(int); # endif /* GLUT callback calling convention for Win32. */ # define GLUTCALLBACK __cdecl /* for callback/function pointer defs */ # define GLUTAPIENTRYV __cdecl /* glut-win32 specific macros, defined to prevent collision with and redifinition of Windows system defs, also removes requirement of pretty much any standard windows header from this file */ #if (_MSC_VER >= 800) || defined(_STDCALL_SUPPORTED) || defined(__CYGWIN32__) # define GLUTAPIENTRY __stdcall #else # define GLUTAPIENTRY #endif /* GLUT API entry point declarations for Win32. */ #if defined(GLUT_BUILDING_LIB) && defined(_DLL) # define GLUTAPI __declspec(dllexport) #elif defined(_DLL) # define GLUTAPI __declspec(dllimport) #else # define GLUTAPI extern #endif #if defined(_WIN32) && !defined(_WINDEF_) && !defined(MESA) # if !defined(MESA_MINWARN) # pragma message( "note: WINDOWS.H not included, providing Mesa definition of CALLBACK macro" ) # pragma message( "----: and PROC typedef. If you receive compiler warnings about either ") # pragma message( "----: being multiply defined you should include WINDOWS.H priot to gl/glut.h" ) # endif # define CALLBACK __stdcall typedef int (GLUTAPIENTRY *PROC)(); typedef void *HGLRC; typedef void *HDC; typedef unsigned long COLORREF; #endif #if defined(_WIN32) && !defined(_WINGDI_) && !defined(MESA) # if !defined(MESA_MINWARN) # pragma message( "note: WINDOWS.H not included, providing Mesa definition of wgl functions" ) # pragma message( "----: and macros. If you receive compiler warnings about any being multiply ") # pragma message( "----: defined you should include WINDOWS.H priot to gl/glut.h" ) # endif # define WGL_FONT_LINES 0 # define WGL_FONT_POLYGONS 1 # ifdef UNICODE # define wglUseFontBitmaps wglUseFontBitmapsW # define wglUseFontOutlines wglUseFontOutlinesW # else # define wglUseFontBitmaps wglUseFontBitmapsA # define wglUseFontOutlines wglUseFontOutlinesA # endif /* !UNICODE */ typedef struct tagLAYERPLANEDESCRIPTOR LAYERPLANEDESCRIPTOR, *PLAYERPLANEDESCRIPTOR, *LPLAYERPLANEDESCRIPTOR; typedef struct _GLYPHMETRICSFLOAT GLYPHMETRICSFLOAT, *PGLYPHMETRICSFLOAT, *LPGLYPHMETRICSFLOAT; # pragma warning( push ) # pragma warning( disable : 4273 ) /* 'function' : inconsistent DLL linkage. dllexport assumed. */ # define WGLAPI __declspec(dllimport) WGLAPI int GLAPIENTRY wglDeleteContext(HGLRC); WGLAPI int GLAPIENTRY wglMakeCurrent(HDC,HGLRC); WGLAPI int GLAPIENTRY wglSetPixelFormat(HDC, int, const PIXELFORMATDESCRIPTOR *); WGLAPI int GLAPIENTRY wglSwapBuffers(HDC hdc); WGLAPI HDC GLAPIENTRY wglGetCurrentDC(void); WGLAPI HGLRC GLAPIENTRY wglCreateContext(HDC); WGLAPI HGLRC GLAPIENTRY wglCreateLayerContext(HDC,int); WGLAPI HGLRC GLAPIENTRY wglGetCurrentContext(void); WGLAPI PROC GLAPIENTRY wglGetProcAddress(const char*); WGLAPI int GLAPIENTRY wglChoosePixelFormat(HDC, const PIXELFORMATDESCRIPTOR *); WGLAPI int GLAPIENTRY wglCopyContext(HGLRC, HGLRC, unsigned int); WGLAPI int GLAPIENTRY wglDeleteContext(HGLRC); WGLAPI int GLAPIENTRY wglDescribeLayerPlane(HDC, int, int, unsigned int,LPLAYERPLANEDESCRIPTOR); WGLAPI int GLAPIENTRY wglDescribePixelFormat(HDC,int, unsigned int, LPPIXELFORMATDESCRIPTOR); WGLAPI int GLAPIENTRY wglGetLayerPaletteEntries(HDC, int, int, int,COLORREF *); WGLAPI int GLAPIENTRY wglGetPixelFormat(HDC hdc); WGLAPI int GLAPIENTRY wglMakeCurrent(HDC, HGLRC); WGLAPI int GLAPIENTRY wglRealizeLayerPalette(HDC, int, int); WGLAPI int GLAPIENTRY wglSetLayerPaletteEntries(HDC, int, int, int,const COLORREF *); WGLAPI int GLAPIENTRY wglShareLists(HGLRC, HGLRC); WGLAPI int GLAPIENTRY wglSwapLayerBuffers(HDC, unsigned int); WGLAPI int GLAPIENTRY wglUseFontBitmapsA(HDC, unsigned long, unsigned long, unsigned long); WGLAPI int GLAPIENTRY wglUseFontBitmapsW(HDC, unsigned long, unsigned long, unsigned long); WGLAPI int GLAPIENTRY wglUseFontOutlinesA(HDC, unsigned long, unsigned long, unsigned long, float,float, int, LPGLYPHMETRICSFLOAT); WGLAPI int GLAPIENTRY wglUseFontOutlinesW(HDC, unsigned long, unsigned long, unsigned long, float,float, int, LPGLYPHMETRICSFLOAT); WGLAPI int GLAPIENTRY SwapBuffers(HDC); WGLAPI int GLAPIENTRY ChoosePixelFormat(HDC,const PIXELFORMATDESCRIPTOR *); WGLAPI int GLAPIENTRY DescribePixelFormat(HDC,int,unsigned int,LPPIXELFORMATDESCRIPTOR); WGLAPI int GLAPIENTRY GetPixelFormat(HDC); WGLAPI int GLAPIENTRY SetPixelFormat(HDC,int,const PIXELFORMATDESCRIPTOR *); # undef WGLAPI # pragma warning( pop ) #endif #else /* _WIN32 not defined */ /* Define GLUTAPIENTRY and GLUTCALLBACK to nothing if we aren't on Win32. */ # define GLUTAPIENTRY # define GLUTAPIENTRYV # define GLUT_APIENTRY_DEFINED # define GLUTCALLBACK # define GLUTAPI extern /* Prototype exit for the non-Win32 case (see above). */ /*extern void exit(int); this screws up gcc -ansi -pedantic! */ #endif /** GLUT API revision history: GLUT_API_VERSION is updated to reflect incompatible GLUT API changes (interface changes, semantic changes, deletions, or additions). GLUT_API_VERSION=1 First public release of GLUT. 11/29/94 GLUT_API_VERSION=2 Added support for OpenGL/GLX multisampling, extension. Supports new input devices like tablet, dial and button box, and Spaceball. Easy to query OpenGL extensions. GLUT_API_VERSION=3 glutMenuStatus added. GLUT_API_VERSION=4 glutInitDisplayString, glutWarpPointer, glutBitmapLength, glutStrokeLength, glutWindowStatusFunc, dynamic video resize subAPI, glutPostWindowRedisplay, glutKeyboardUpFunc, glutSpecialUpFunc, glutIgnoreKeyRepeat, glutSetKeyRepeat, glutJoystickFunc, glutForceJoystickFunc (NOT FINALIZED!). **/ #ifndef GLUT_API_VERSION /* allow this to be overriden */ #define GLUT_API_VERSION 3 #endif /** GLUT implementation revision history: GLUT_XLIB_IMPLEMENTATION is updated to reflect both GLUT API revisions and implementation revisions (ie, bug fixes). GLUT_XLIB_IMPLEMENTATION=1 mjk's first public release of GLUT Xlib-based implementation. 11/29/94 GLUT_XLIB_IMPLEMENTATION=2 mjk's second public release of GLUT Xlib-based implementation providing GLUT version 2 interfaces. GLUT_XLIB_IMPLEMENTATION=3 mjk's GLUT 2.2 images. 4/17/95 GLUT_XLIB_IMPLEMENTATION=4 mjk's GLUT 2.3 images. 6/?/95 GLUT_XLIB_IMPLEMENTATION=5 mjk's GLUT 3.0 images. 10/?/95 GLUT_XLIB_IMPLEMENTATION=7 mjk's GLUT 3.1+ with glutWarpPoitner. 7/24/96 GLUT_XLIB_IMPLEMENTATION=8 mjk's GLUT 3.1+ with glutWarpPoitner and video resize. 1/3/97 GLUT_XLIB_IMPLEMENTATION=9 mjk's GLUT 3.4 release with early GLUT 4 routines. GLUT_XLIB_IMPLEMENTATION=11 Mesa 2.5's GLUT 3.6 release. GLUT_XLIB_IMPLEMENTATION=12 mjk's GLUT 3.6 release with early GLUT 4 routines + signal handling. GLUT_XLIB_IMPLEMENTATION=13 mjk's GLUT 3.7 beta with GameGLUT support. GLUT_XLIB_IMPLEMENTATION=14 mjk's GLUT 3.7 beta with f90gl friend interface. GLUT_XLIB_IMPLEMENTATION=15 mjk's GLUT 3.7 beta sync'ed with Mesa **/ #ifndef GLUT_XLIB_IMPLEMENTATION /* Allow this to be overriden. */ #define GLUT_XLIB_IMPLEMENTATION 15 #endif /* Display mode bit masks. */ #define GLUT_RGB 0 #define GLUT_RGBA GLUT_RGB #define GLUT_INDEX 1 #define GLUT_SINGLE 0 #define GLUT_DOUBLE 2 #define GLUT_ACCUM 4 #define GLUT_ALPHA 8 #define GLUT_DEPTH 16 #define GLUT_STENCIL 32 #if (GLUT_API_VERSION >= 2) #define GLUT_MULTISAMPLE 128 #define GLUT_STEREO 256 #endif #if (GLUT_API_VERSION >= 3) #define GLUT_LUMINANCE 512 #endif /* Mouse buttons. */ #define GLUT_LEFT_BUTTON 0 #define GLUT_MIDDLE_BUTTON 1 #define GLUT_RIGHT_BUTTON 2 /* Mouse button state. */ #define GLUT_DOWN 0 #define GLUT_UP 1 #if (GLUT_API_VERSION >= 2) /* function keys */ #define GLUT_KEY_F1 1 #define GLUT_KEY_F2 2 #define GLUT_KEY_F3 3 #define GLUT_KEY_F4 4 #define GLUT_KEY_F5 5 #define GLUT_KEY_F6 6 #define GLUT_KEY_F7 7 #define GLUT_KEY_F8 8 #define GLUT_KEY_F9 9 #define GLUT_KEY_F10 10 #define GLUT_KEY_F11 11 #define GLUT_KEY_F12 12 /* directional keys */ #define GLUT_KEY_LEFT 100 #define GLUT_KEY_UP 101 #define GLUT_KEY_RIGHT 102 #define GLUT_KEY_DOWN 103 #define GLUT_KEY_PAGE_UP 104 #define GLUT_KEY_PAGE_DOWN 105 #define GLUT_KEY_HOME 106 #define GLUT_KEY_END 107 #define GLUT_KEY_INSERT 108 #endif /* Entry/exit state. */ #define GLUT_LEFT 0 #define GLUT_ENTERED 1 /* Menu usage state. */ #define GLUT_MENU_NOT_IN_USE 0 #define GLUT_MENU_IN_USE 1 /* Visibility state. */ #define GLUT_NOT_VISIBLE 0 #define GLUT_VISIBLE 1 /* Window status state. */ #define GLUT_HIDDEN 0 #define GLUT_FULLY_RETAINED 1 #define GLUT_PARTIALLY_RETAINED 2 #define GLUT_FULLY_COVERED 3 /* Color index component selection values. */ #define GLUT_RED 0 #define GLUT_GREEN 1 #define GLUT_BLUE 2 /* Layers for use. */ #define GLUT_NORMAL 0 #define GLUT_OVERLAY 1 #if defined(_WIN32) /* Stroke font constants (use these in GLUT program). */ #define GLUT_STROKE_ROMAN ((void*)0) #define GLUT_STROKE_MONO_ROMAN ((void*)1) /* Bitmap font constants (use these in GLUT program). */ #define GLUT_BITMAP_9_BY_15 ((void*)2) #define GLUT_BITMAP_8_BY_13 ((void*)3) #define GLUT_BITMAP_TIMES_ROMAN_10 ((void*)4) #define GLUT_BITMAP_TIMES_ROMAN_24 ((void*)5) #if (GLUT_API_VERSION >= 3) #define GLUT_BITMAP_HELVETICA_10 ((void*)6) #define GLUT_BITMAP_HELVETICA_12 ((void*)7) #define GLUT_BITMAP_HELVETICA_18 ((void*)8) #endif #else /* Stroke font opaque addresses (use constants instead in source code). */ GLUTAPI void *glutStrokeRoman; GLUTAPI void *glutStrokeMonoRoman; /* Stroke font constants (use these in GLUT program). */ #define GLUT_STROKE_ROMAN (&glutStrokeRoman) #define GLUT_STROKE_MONO_ROMAN (&glutStrokeMonoRoman) /* Bitmap font opaque addresses (use constants instead in source code). */ GLUTAPI void *glutBitmap9By15; GLUTAPI void *glutBitmap8By13; GLUTAPI void *glutBitmapTimesRoman10; GLUTAPI void *glutBitmapTimesRoman24; GLUTAPI void *glutBitmapHelvetica10; GLUTAPI void *glutBitmapHelvetica12; GLUTAPI void *glutBitmapHelvetica18; /* Bitmap font constants (use these in GLUT program). */ #define GLUT_BITMAP_9_BY_15 (&glutBitmap9By15) #define GLUT_BITMAP_8_BY_13 (&glutBitmap8By13) #define GLUT_BITMAP_TIMES_ROMAN_10 (&glutBitmapTimesRoman10) #define GLUT_BITMAP_TIMES_ROMAN_24 (&glutBitmapTimesRoman24) #if (GLUT_API_VERSION >= 3) #define GLUT_BITMAP_HELVETICA_10 (&glutBitmapHelvetica10) #define GLUT_BITMAP_HELVETICA_12 (&glutBitmapHelvetica12) #define GLUT_BITMAP_HELVETICA_18 (&glutBitmapHelvetica18) #endif #endif /* glutGet parameters. */ #define GLUT_WINDOW_X 100 #define GLUT_WINDOW_Y 101 #define GLUT_WINDOW_WIDTH 102 #define GLUT_WINDOW_HEIGHT 103 #define GLUT_WINDOW_BUFFER_SIZE 104 #define GLUT_WINDOW_STENCIL_SIZE 105 #define GLUT_WINDOW_DEPTH_SIZE 106 #define GLUT_WINDOW_RED_SIZE 107 #define GLUT_WINDOW_GREEN_SIZE 108 #define GLUT_WINDOW_BLUE_SIZE 109 #define GLUT_WINDOW_ALPHA_SIZE 110 #define GLUT_WINDOW_ACCUM_RED_SIZE 111 #define GLUT_WINDOW_ACCUM_GREEN_SIZE 112 #define GLUT_WINDOW_ACCUM_BLUE_SIZE 113 #define GLUT_WINDOW_ACCUM_ALPHA_SIZE 114 #define GLUT_WINDOW_DOUBLEBUFFER 115 #define GLUT_WINDOW_RGBA 116 #define GLUT_WINDOW_PARENT 117 #define GLUT_WINDOW_NUM_CHILDREN 118 #define GLUT_WINDOW_COLORMAP_SIZE 119 #if (GLUT_API_VERSION >= 2) #define GLUT_WINDOW_NUM_SAMPLES 120 #define GLUT_WINDOW_STEREO 121 #endif #if (GLUT_API_VERSION >= 3) #define GLUT_WINDOW_CURSOR 122 #endif #define GLUT_SCREEN_WIDTH 200 #define GLUT_SCREEN_HEIGHT 201 #define GLUT_SCREEN_WIDTH_MM 202 #define GLUT_SCREEN_HEIGHT_MM 203 #define GLUT_MENU_NUM_ITEMS 300 #define GLUT_DISPLAY_MODE_POSSIBLE 400 #define GLUT_INIT_WINDOW_X 500 #define GLUT_INIT_WINDOW_Y 501 #define GLUT_INIT_WINDOW_WIDTH 502 #define GLUT_INIT_WINDOW_HEIGHT 503 #define GLUT_INIT_DISPLAY_MODE 504 #if (GLUT_API_VERSION >= 2) #define GLUT_ELAPSED_TIME 700 #endif #if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 13) #define GLUT_WINDOW_FORMAT_ID 123 #endif #if (GLUT_API_VERSION >= 2) /* glutDeviceGet parameters. */ #define GLUT_HAS_KEYBOARD 600 #define GLUT_HAS_MOUSE 601 #define GLUT_HAS_SPACEBALL 602 #define GLUT_HAS_DIAL_AND_BUTTON_BOX 603 #define GLUT_HAS_TABLET 604 #define GLUT_NUM_MOUSE_BUTTONS 605 #define GLUT_NUM_SPACEBALL_BUTTONS 606 #define GLUT_NUM_BUTTON_BOX_BUTTONS 607 #define GLUT_NUM_DIALS 608 #define GLUT_NUM_TABLET_BUTTONS 609 #endif #if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 13) #define GLUT_DEVICE_IGNORE_KEY_REPEAT 610 #define GLUT_DEVICE_KEY_REPEAT 611 #define GLUT_HAS_JOYSTICK 612 #define GLUT_OWNS_JOYSTICK 613 #define GLUT_JOYSTICK_BUTTONS 614 #define GLUT_JOYSTICK_AXES 615 #define GLUT_JOYSTICK_POLL_RATE 616 #endif #if (GLUT_API_VERSION >= 3) /* glutLayerGet parameters. */ #define GLUT_OVERLAY_POSSIBLE 800 #define GLUT_LAYER_IN_USE 801 #define GLUT_HAS_OVERLAY 802 #define GLUT_TRANSPARENT_INDEX 803 #define GLUT_NORMAL_DAMAGED 804 #define GLUT_OVERLAY_DAMAGED 805 #if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9) /* glutVideoResizeGet parameters. */ #define GLUT_VIDEO_RESIZE_POSSIBLE 900 #define GLUT_VIDEO_RESIZE_IN_USE 901 #define GLUT_VIDEO_RESIZE_X_DELTA 902 #define GLUT_VIDEO_RESIZE_Y_DELTA 903 #define GLUT_VIDEO_RESIZE_WIDTH_DELTA 904 #define GLUT_VIDEO_RESIZE_HEIGHT_DELTA 905 #define GLUT_VIDEO_RESIZE_X 906 #define GLUT_VIDEO_RESIZE_Y 907 #define GLUT_VIDEO_RESIZE_WIDTH 908 #define GLUT_VIDEO_RESIZE_HEIGHT 909 #endif /* glutUseLayer parameters. */ #define GLUT_NORMAL 0 #define GLUT_OVERLAY 1 /* glutGetModifiers return mask. */ #define GLUT_ACTIVE_SHIFT 1 #define GLUT_ACTIVE_CTRL 2 #define GLUT_ACTIVE_ALT 4 /* glutSetCursor parameters. */ /* Basic arrows. */ #define GLUT_CURSOR_RIGHT_ARROW 0 #define GLUT_CURSOR_LEFT_ARROW 1 /* Symbolic cursor shapes. */ #define GLUT_CURSOR_INFO 2 #define GLUT_CURSOR_DESTROY 3 #define GLUT_CURSOR_HELP 4 #define GLUT_CURSOR_CYCLE 5 #define GLUT_CURSOR_SPRAY 6 #define GLUT_CURSOR_WAIT 7 #define GLUT_CURSOR_TEXT 8 #define GLUT_CURSOR_CROSSHAIR 9 /* Directional cursors. */ #define GLUT_CURSOR_UP_DOWN 10 #define GLUT_CURSOR_LEFT_RIGHT 11 /* Sizing cursors. */ #define GLUT_CURSOR_TOP_SIDE 12 #define GLUT_CURSOR_BOTTOM_SIDE 13 #define GLUT_CURSOR_LEFT_SIDE 14 #define GLUT_CURSOR_RIGHT_SIDE 15 #define GLUT_CURSOR_TOP_LEFT_CORNER 16 #define GLUT_CURSOR_TOP_RIGHT_CORNER 17 #define GLUT_CURSOR_BOTTOM_RIGHT_CORNER 18 #define GLUT_CURSOR_BOTTOM_LEFT_CORNER 19 /* Inherit from parent window. */ #define GLUT_CURSOR_INHERIT 100 /* Blank cursor. */ #define GLUT_CURSOR_NONE 101 /* Fullscreen crosshair (if available). */ #define GLUT_CURSOR_FULL_CROSSHAIR 102 #endif /* GLUT initialization sub-API. */ GLUTAPI void GLUTAPIENTRY glutInit(int *argcp, char **argv); #if defined(_WIN32) && !defined(GLUT_DISABLE_ATEXIT_HACK) GLUTAPI void GLUTAPIENTRY __glutInitWithExit(int *argcp, char **argv, void (__cdecl *exitfunc)(int)); #ifndef GLUT_BUILDING_LIB static void GLUTAPIENTRY glutInit_ATEXIT_HACK(int *argcp, char **argv) { __glutInitWithExit(argcp, argv, exit); } #define glutInit glutInit_ATEXIT_HACK #endif #endif GLUTAPI void GLUTAPIENTRY glutInitDisplayMode(unsigned int mode); #if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9) GLUTAPI void GLUTAPIENTRY glutInitDisplayString(const char *string); #endif GLUTAPI void GLUTAPIENTRY glutInitWindowPosition(int x, int y); GLUTAPI void GLUTAPIENTRY glutInitWindowSize(int width, int height); GLUTAPI void GLUTAPIENTRY glutMainLoop(void); /* GLUT window sub-API. */ GLUTAPI int GLUTAPIENTRY glutCreateWindow(const char *title); #if defined(_WIN32) && !defined(GLUT_DISABLE_ATEXIT_HACK) GLUTAPI int GLUTAPIENTRY __glutCreateWindowWithExit(const char *title, void (__cdecl *exitfunc)(int)); #ifndef GLUT_BUILDING_LIB static int GLUTAPIENTRY glutCreateWindow_ATEXIT_HACK(const char *title) { return __glutCreateWindowWithExit(title, exit); } #define glutCreateWindow glutCreateWindow_ATEXIT_HACK #endif #endif GLUTAPI int GLUTAPIENTRY glutCreateSubWindow(int win, int x, int y, int width, int height); GLUTAPI void GLUTAPIENTRY glutDestroyWindow(int win); GLUTAPI void GLUTAPIENTRY glutPostRedisplay(void); #if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 11) GLUTAPI void GLUTAPIENTRY glutPostWindowRedisplay(int win); #endif GLUTAPI void GLUTAPIENTRY glutSwapBuffers(void); GLUTAPI int GLUTAPIENTRY glutGetWindow(void); GLUTAPI void GLUTAPIENTRY glutSetWindow(int win); GLUTAPI void GLUTAPIENTRY glutSetWindowTitle(const char *title); GLUTAPI void GLUTAPIENTRY glutSetIconTitle(const char *title); GLUTAPI void GLUTAPIENTRY glutPositionWindow(int x, int y); GLUTAPI void GLUTAPIENTRY glutReshapeWindow(int width, int height); GLUTAPI void GLUTAPIENTRY glutPopWindow(void); GLUTAPI void GLUTAPIENTRY glutPushWindow(void); GLUTAPI void GLUTAPIENTRY glutIconifyWindow(void); GLUTAPI void GLUTAPIENTRY glutShowWindow(void); GLUTAPI void GLUTAPIENTRY glutHideWindow(void); #if (GLUT_API_VERSION >= 3) GLUTAPI void GLUTAPIENTRY glutFullScreen(void); GLUTAPI void GLUTAPIENTRY glutSetCursor(int cursor); #if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9) GLUTAPI void GLUTAPIENTRY glutWarpPointer(int x, int y); #endif /* GLUT overlay sub-API. */ GLUTAPI void GLUTAPIENTRY glutEstablishOverlay(void); GLUTAPI void GLUTAPIENTRY glutRemoveOverlay(void); GLUTAPI void GLUTAPIENTRY glutUseLayer(GLenum layer); GLUTAPI void GLUTAPIENTRY glutPostOverlayRedisplay(void); #if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 11) GLUTAPI void GLUTAPIENTRY glutPostWindowOverlayRedisplay(int win); #endif GLUTAPI void GLUTAPIENTRY glutShowOverlay(void); GLUTAPI void GLUTAPIENTRY glutHideOverlay(void); #endif /* GLUT menu sub-API. */ GLUTAPI int GLUTAPIENTRY glutCreateMenu(void (GLUTCALLBACK *func)(int)); #if defined(_WIN32) && !defined(GLUT_DISABLE_ATEXIT_HACK) GLUTAPI int GLUTAPIENTRY __glutCreateMenuWithExit(void (GLUTCALLBACK *func)(int), void (__cdecl *exitfunc)(int)); #ifndef GLUT_BUILDING_LIB static int GLUTAPIENTRY glutCreateMenu_ATEXIT_HACK(void (GLUTCALLBACK *func)(int)) { return __glutCreateMenuWithExit(func, exit); } #define glutCreateMenu glutCreateMenu_ATEXIT_HACK #endif #endif GLUTAPI void GLUTAPIENTRY glutDestroyMenu(int menu); GLUTAPI int GLUTAPIENTRY glutGetMenu(void); GLUTAPI void GLUTAPIENTRY glutSetMenu(int menu); GLUTAPI void GLUTAPIENTRY glutAddMenuEntry(const char *label, int value); GLUTAPI void GLUTAPIENTRY glutAddSubMenu(const char *label, int submenu); GLUTAPI void GLUTAPIENTRY glutChangeToMenuEntry(int item, const char *label, int value); GLUTAPI void GLUTAPIENTRY glutChangeToSubMenu(int item, const char *label, int submenu); GLUTAPI void GLUTAPIENTRY glutRemoveMenuItem(int item); GLUTAPI void GLUTAPIENTRY glutAttachMenu(int button); GLUTAPI void GLUTAPIENTRY glutDetachMenu(int button); /* GLUT window callback sub-API. */ GLUTAPI void GLUTAPIENTRY glutDisplayFunc(void (GLUTCALLBACK *func)(void)); GLUTAPI void GLUTAPIENTRY glutReshapeFunc(void (GLUTCALLBACK *func)(int width, int height)); GLUTAPI void GLUTAPIENTRY glutKeyboardFunc(void (GLUTCALLBACK *func)(unsigned char key, int x, int y)); GLUTAPI void GLUTAPIENTRY glutMouseFunc(void (GLUTCALLBACK *func)(int button, int state, int x, int y)); GLUTAPI void GLUTAPIENTRY glutMotionFunc(void (GLUTCALLBACK *func)(int x, int y)); GLUTAPI void GLUTAPIENTRY glutPassiveMotionFunc(void (GLUTCALLBACK *func)(int x, int y)); GLUTAPI void GLUTAPIENTRY glutEntryFunc(void (GLUTCALLBACK *func)(int state)); GLUTAPI void GLUTAPIENTRY glutVisibilityFunc(void (GLUTCALLBACK *func)(int state)); GLUTAPI void GLUTAPIENTRY glutIdleFunc(void (GLUTCALLBACK *func)(void)); GLUTAPI void GLUTAPIENTRY glutTimerFunc(unsigned int millis, void (GLUTCALLBACK *func)(int value), int value); GLUTAPI void GLUTAPIENTRY glutMenuStateFunc(void (GLUTCALLBACK *func)(int state)); #if (GLUT_API_VERSION >= 2) GLUTAPI void GLUTAPIENTRY glutSpecialFunc(void (GLUTCALLBACK *func)(int key, int x, int y)); GLUTAPI void GLUTAPIENTRY glutSpaceballMotionFunc(void (GLUTCALLBACK *func)(int x, int y, int z)); GLUTAPI void GLUTAPIENTRY glutSpaceballRotateFunc(void (GLUTCALLBACK *func)(int x, int y, int z)); GLUTAPI void GLUTAPIENTRY glutSpaceballButtonFunc(void (GLUTCALLBACK *func)(int button, int state)); GLUTAPI void GLUTAPIENTRY glutButtonBoxFunc(void (GLUTCALLBACK *func)(int button, int state)); GLUTAPI void GLUTAPIENTRY glutDialsFunc(void (GLUTCALLBACK *func)(int dial, int value)); GLUTAPI void GLUTAPIENTRY glutTabletMotionFunc(void (GLUTCALLBACK *func)(int x, int y)); GLUTAPI void GLUTAPIENTRY glutTabletButtonFunc(void (GLUTCALLBACK *func)(int button, int state, int x, int y)); #if (GLUT_API_VERSION >= 3) GLUTAPI void GLUTAPIENTRY glutMenuStatusFunc(void (GLUTCALLBACK *func)(int status, int x, int y)); GLUTAPI void GLUTAPIENTRY glutOverlayDisplayFunc(void (GLUTCALLBACK *func)(void)); #if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9) GLUTAPI void GLUTAPIENTRY glutWindowStatusFunc(void (GLUTCALLBACK *func)(int state)); #endif #if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 13) GLUTAPI void GLUTAPIENTRY glutKeyboardUpFunc(void (GLUTCALLBACK *func)(unsigned char key, int x, int y)); GLUTAPI void GLUTAPIENTRY glutSpecialUpFunc(void (GLUTCALLBACK *func)(int key, int x, int y)); GLUTAPI void GLUTAPIENTRY glutJoystickFunc(void (GLUTCALLBACK *func)(unsigned int buttonMask, int x, int y, int z), int pollInterval); #endif #endif #endif /* GLUT color index sub-API. */ GLUTAPI void GLUTAPIENTRY glutSetColor(int, GLfloat red, GLfloat green, GLfloat blue); GLUTAPI GLfloat GLUTAPIENTRY glutGetColor(int ndx, int component); GLUTAPI void GLUTAPIENTRY glutCopyColormap(int win); /* GLUT state retrieval sub-API. */ GLUTAPI int GLUTAPIENTRY glutGet(GLenum type); GLUTAPI int GLUTAPIENTRY glutDeviceGet(GLenum type); #if (GLUT_API_VERSION >= 2) /* GLUT extension support sub-API */ GLUTAPI int GLUTAPIENTRY glutExtensionSupported(const char *name); #endif #if (GLUT_API_VERSION >= 3) GLUTAPI int GLUTAPIENTRY glutGetModifiers(void); GLUTAPI int GLUTAPIENTRY glutLayerGet(GLenum type); #endif /* GLUT font sub-API */ GLUTAPI void GLUTAPIENTRY glutBitmapCharacter(void *font, int character); GLUTAPI int GLUTAPIENTRY glutBitmapWidth(void *font, int character); GLUTAPI void GLUTAPIENTRY glutStrokeCharacter(void *font, int character); GLUTAPI int GLUTAPIENTRY glutStrokeWidth(void *font, int character); #if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9) GLUTAPI int GLUTAPIENTRY glutBitmapLength(void *font, const unsigned char *string); GLUTAPI int GLUTAPIENTRY glutStrokeLength(void *font, const unsigned char *string); #endif /* GLUT pre-built models sub-API */ GLUTAPI void GLUTAPIENTRY glutWireSphere(GLdouble radius, GLint slices, GLint stacks); GLUTAPI void GLUTAPIENTRY glutSolidSphere(GLdouble radius, GLint slices, GLint stacks); GLUTAPI void GLUTAPIENTRY glutWireCone(GLdouble base, GLdouble height, GLint slices, GLint stacks); GLUTAPI void GLUTAPIENTRY glutSolidCone(GLdouble base, GLdouble height, GLint slices, GLint stacks); GLUTAPI void GLUTAPIENTRY glutWireCube(GLdouble size); GLUTAPI void GLUTAPIENTRY glutSolidCube(GLdouble size); GLUTAPI void GLUTAPIENTRY glutWireTorus(GLdouble innerRadius, GLdouble outerRadius, GLint sides, GLint rings); GLUTAPI void GLUTAPIENTRY glutSolidTorus(GLdouble innerRadius, GLdouble outerRadius, GLint sides, GLint rings); GLUTAPI void GLUTAPIENTRY glutWireDodecahedron(void); GLUTAPI void GLUTAPIENTRY glutSolidDodecahedron(void); GLUTAPI void GLUTAPIENTRY glutWireTeapot(GLdouble size); GLUTAPI void GLUTAPIENTRY glutSolidTeapot(GLdouble size); GLUTAPI void GLUTAPIENTRY glutWireOctahedron(void); GLUTAPI void GLUTAPIENTRY glutSolidOctahedron(void); GLUTAPI void GLUTAPIENTRY glutWireTetrahedron(void); GLUTAPI void GLUTAPIENTRY glutSolidTetrahedron(void); GLUTAPI void GLUTAPIENTRY glutWireIcosahedron(void); GLUTAPI void GLUTAPIENTRY glutSolidIcosahedron(void); #if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9) /* GLUT video resize sub-API. */ GLUTAPI int GLUTAPIENTRY glutVideoResizeGet(GLenum param); GLUTAPI void GLUTAPIENTRY glutSetupVideoResizing(void); GLUTAPI void GLUTAPIENTRY glutStopVideoResizing(void); GLUTAPI void GLUTAPIENTRY glutVideoResize(int x, int y, int width, int height); GLUTAPI void GLUTAPIENTRY glutVideoPan(int x, int y, int width, int height); /* GLUT debugging sub-API. */ GLUTAPI void GLUTAPIENTRY glutReportErrors(void); #endif #if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 13) /* GLUT device control sub-API. */ /* glutSetKeyRepeat modes. */ #define GLUT_KEY_REPEAT_OFF 0 #define GLUT_KEY_REPEAT_ON 1 #define GLUT_KEY_REPEAT_DEFAULT 2 /* Joystick button masks. */ #define GLUT_JOYSTICK_BUTTON_A 1 #define GLUT_JOYSTICK_BUTTON_B 2 #define GLUT_JOYSTICK_BUTTON_C 4 #define GLUT_JOYSTICK_BUTTON_D 8 GLUTAPI void GLUTAPIENTRY glutIgnoreKeyRepeat(int ignore); GLUTAPI void GLUTAPIENTRY glutSetKeyRepeat(int repeatMode); GLUTAPI void GLUTAPIENTRY glutForceJoystickFunc(void); /* GLUT game mode sub-API. */ /* glutGameModeGet. */ #define GLUT_GAME_MODE_ACTIVE 0 #define GLUT_GAME_MODE_POSSIBLE 1 #define GLUT_GAME_MODE_WIDTH 2 #define GLUT_GAME_MODE_HEIGHT 3 #define GLUT_GAME_MODE_PIXEL_DEPTH 4 #define GLUT_GAME_MODE_REFRESH_RATE 5 #define GLUT_GAME_MODE_DISPLAY_CHANGED 6 GLUTAPI void GLUTAPIENTRY glutGameModeString(const char *string); GLUTAPI int GLUTAPIENTRY glutEnterGameMode(void); GLUTAPI void GLUTAPIENTRY glutLeaveGameMode(void); GLUTAPI int GLUTAPIENTRY glutGameModeGet(GLenum mode); #endif #ifdef __cplusplus } #endif #if 0 #ifdef GLUT_APIENTRY_DEFINED # undef GLUT_APIENTRY_DEFINED # undef APIENTRY #endif #ifdef GLUT_WINGDIAPI_DEFINED # undef GLUT_WINGDIAPI_DEFINED # undef WINGDIAPI #endif #ifdef GLUT_DEFINED___CDECL # undef GLUT_DEFINED___CDECL # undef __cdecl #endif #ifdef GLUT_DEFINED__CRTIMP # undef GLUT_DEFINED__CRTIMP # undef _CRTIMP #endif #endif #endif /* __glut_h__ */ allegro4.4-4.4.2/addons/allegrogl/include/alleggl.h000066400000000000000000000652151173507505700220420ustar00rootroot00000000000000/** \file alleggl.h * \brief Main header file for AllegroGL */ #ifndef _allegrogl_included_alleggl_h #define _allegrogl_included_alleggl_h #include #ifdef ALLEGRO_WINDOWS #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN_defined #endif /* WIN32_LEAN_AND_MEAN */ #ifdef ALLEGRO_DMC typedef int32_t INT32; typedef __int64 INT64; #endif #include #ifdef WIN32_LEAN_AND_MEAN_defined #undef WIN32_LEAN_AND_MEAN_defined #undef WIN32_LEAN_AND_MEAN #endif /* WIN32_LEAN_AND_MEAN_defined */ #endif /* ALLEGRO_WINDOWS */ #if (defined ALLEGRO_GL_DYNAMIC) && (defined ALLEGRO_WINDOWS) #ifdef ALLEGRO_GL_SRC_BUILD #define _AGL_DLL __declspec(dllexport) #else #define _AGL_DLL __declspec(dllimport) #endif /* ALLEGRO_GL_SRC_BUILD */ #else #define _AGL_DLL #endif /* (defined ALLEGRO_GL_DYNAMIC) && (defined ALLEGRO_WINDOWS) */ #define AGL_VAR(type, name) extern _AGL_DLL type name #if (defined ALLEGRO_GL_DYNAMIC) && (defined ALLEGRO_WINDOWS) #define AGL_FUNC(type, name, args) extern _AGL_DLL type __cdecl name args #else #define AGL_FUNC(type, name, args) extern type name args #endif /* (defined ALLEGRO_GL_DYNAMIC) && (defined ALLEGRO_WINDOWS) */ #ifdef ALLEGRO_MACOSX #include #include #include #ifndef GL_GLEXT_PROTOTYPES #define GL_GLEXT_PROTOTYPES #endif #else /* ALLEGRO_MACOSX */ /* HACK: Prevent both Mesa and SGI's broken headers from screwing us */ #define __glext_h_ #define __glxext_h_ #include #undef __glext_h_ #undef __glxext_h_ #endif /* ALLEGRO_MACOSX */ #include "allegrogl/gl_ext.h" #ifdef ALLEGRO_WITH_XWINDOWS #if (ALLEGRO_SUB_VERSION == 2) && (ALLEGRO_WIP_VERSION < 2) # ifndef HAVE_LIBPTHREAD # error AllegroGL requires Allegro to have pthread support enabled! # endif #else # ifndef ALLEGRO_HAVE_LIBPTHREAD # error AllegroGL requires Allegro to have pthread support enabled! # endif #endif #include "allegrogl/alleggl_config.h" #endif /** \defgroup version Version information * \{ */ /** \name Version Information * \{ */ #define AGL_VERSION 0 ///< Major version number #define AGL_SUB_VERSION 4 ///< Minor version number #define AGL_WIP_VERSION 4 ///< Work-In-Progress version number #define AGL_VERSION_STR "0.4.4" ///< Version description string /** \} */ /** \} */ /* Version Check */ #if (ALLEGRO_VERSION < 4 || (ALLEGRO_VERSION == 4 && ALLEGRO_SUB_VERSION < 2)) #error AllegroGL requires Allegro 4.2.0 or later to compile! #endif #ifndef GL_VERSION_1_1 #error AllegroGL requires OpenGL 1.1 libraries or later to compile! #endif #ifdef __cplusplus extern "C" { #endif #ifdef ALLEGRO_WINDOWS /* Missing #defines from Mingw */ #ifndef PFD_SWAP_LAYER_BUFFERS #define PFD_SWAP_LAYER_BUFFERS 0x00000800 #endif #ifndef PFD_GENERIC_ACCELERATED #define PFD_GENERIC_ACCELERATED 0x00001000 #endif #ifndef PFD_SUPPORT_DIRECTDRAW #define PFD_SUPPORT_DIRECTDRAW 0x00002000 #endif #ifndef CDS_FULLSCREEN #define CDS_FULLSCREEN 0x00000004 #endif #ifndef ENUM_CURRENT_SETTINGS #define ENUM_CURRENT_SETTINGS ((DWORD)-1) #endif #endif #define AGL_ERROR_SIZE 256 AGL_VAR(char, allegro_gl_error[AGL_ERROR_SIZE]); /** \defgroup core Core routines * Basic AllegroGL functions. These functions allow you to initialize * AllegroGL, set up a rendering context via set_gfx_mode(), and allow * access to regular OpenGL functions. * */ /** \name Core Functions * \{ */ AGL_FUNC(int, install_allegro_gl, (void)); AGL_FUNC(void, remove_allegro_gl, (void)); AGL_FUNC(void, allegro_gl_flip, (void)); AGL_FUNC(float, allegro_gl_opengl_version, (void)); /** \ingroup core * Backward compatibility \#define for programs written * prior to AGL 0.0.22. * It isn't defined as anything meaningful, so you don't * need to put them in your program. * * \see allegro_gl_end() */ #define allegro_gl_begin() ; /** \ingroup core * Backward compatibility \#define for programs written * prior to AGL 0.0.22. * It isn't defined as anything meaningful, so you don't * need to put them in your program. * * \see allegro_gl_begin() */ #define allegro_gl_end() ; /** \} */ /** \addtogroup settings * \{ */ /** \name Frame Buffer Settings * \{ */ /** Use Allegro-compatible framebuffer * \deprecated This define is ignored. */ #define AGL_ALLEGRO_FORMAT 0x00000001 /** Select the red depth of the frame buffer. This defines the number of * bits for the red component you'd like. The driver may or may not find * a suitable mode */ #define AGL_RED_DEPTH 0x00000002 /** Select the green depth of the frame buffer. This defines the number of * bits for the green component you'd like. The driver may or may not find * a suitable mode */ #define AGL_GREEN_DEPTH 0x00000004 /** Select the blue depth of the frame buffer. This defines the number of * bits for the blue component you'd like. The driver may or may not find * a suitable mode */ #define AGL_BLUE_DEPTH 0x00000008 /** Select the alpha depth of the frame buffer. This defines the number of * bits for the alpha component you'd like. Not many video cards support * destination alpha, so be aware that the you may not get an alpha depth * at all. */ #define AGL_ALPHA_DEPTH 0x00000010 /** Specify the total color depth of the frame buffer. The driver is free to * select any combination of red, green, blue and alpha bits. */ #define AGL_COLOR_DEPTH 0x00000020 /** Select the red depth of the accumulator buffer. This defines the number * of bits to use for the red component. The driver may or may not find a * suitable mode. Note that on many video cards, the accumulator buffer is * not accelerated. */ #define AGL_ACC_RED_DEPTH 0x00000040 /** Select the green depth of the accumulator buffer. This defines the number * of bits to use for the green component. The driver may or may not find a * suitable mode. Note that on many video cards, the accumulator buffer is * not accelerated. */ #define AGL_ACC_GREEN_DEPTH 0x00000080 /** Select the blue depth of the accumulator buffer. This defines the number * of bits to use for the blue component. The driver may or may not find a * suitable mode. Note that on many video cards, the accumulator buffer is * not accelerated. */ #define AGL_ACC_BLUE_DEPTH 0x00000100 /** Select the alpha depth of the accumulator buffer. This defines the number * of bits to use for the alpha component. The driver may or may not find a * suitable mode. Note that on many video cards, the accumulator buffer is * not accelerated. Not many cards support destination alpha either. */ #define AGL_ACC_ALPHA_DEPTH 0x00000200 /** Creates a backbuffer if set. The buffering mode may be double buffering * or page flipping, depending on the driver settings. OpenGL programs cannot * chose the buffering mode themselves. */ #define AGL_DOUBLEBUFFER 0x00000400 /** Creates seperate left/right buffers for stereo display. Stereo display * is used with special hardware (tipically glasses) for giving the illusion * of depth by drawing the left and right buffers with a slight horizontal * displacement. This makes the display appear to heavily flicker without * the special hardware. * Set to TRUE for enabling stereo viewing. */ #define AGL_STEREO 0x00000800 /** Creates additional auxiliary buffers. This allows you to have more than * one rendering context. Few video cards support this feature. */ #define AGL_AUX_BUFFERS 0x00001000 /** Select the depth of the z-buffer. The z-buffer is used to properly * display polygons in 3D without recurring to sorting. The higher the * depth of the z-buffer, the more precise it is. */ #define AGL_Z_DEPTH 0x00002000 /** Select the depth of the stencil buffer. The stencil buffer is used to * to do per-pixel testing (like the z-buffer), but of an arbitrary * pattern instead of depth. Please see the OpenGL documentation for details. * Newer cards support stenciling in hardware, but older cards (TNT2s, * Voodoos, ATI Rage) do not. */ #define AGL_STENCIL_DEPTH 0x00004000 /** Requests a placement of the window to a specified pixel location. * The driver may or may not honnor the request. */ #define AGL_WINDOW_X 0x00008000 /** Same as AGL_WINDOW_X, but for the y-axis. */ #define AGL_WINDOW_Y 0x00010000 /** Set it if you'd like AllegroGL to pay special attention on whether * hardware acceleration is present or not. Notice however this * isn't a guarentee that the OpenGL operations will be accelerated, but * rather a request that the operations go through the video card's * drivers instead of Microsoft's software renderer. The video card * driver is free to drop back to software mode if it deems it necessary. * This setting has no effect in X. */ #define AGL_RENDERMETHOD 0x00020000 /** Set if you'd like a full screen mode. Full screen may or may not be * available on the current platform. */ #define AGL_FULLSCREEN 0x00040000 /** Set if you'd like a windowed mode. Windowed modes may or may not be * available on the current platform. */ #define AGL_WINDOWED 0x00080000 /** Define AllegroGL's policy relative to video memory usage. * Sometimes AllegroGL needs to create an internal 256x256 texture in order to * perform graphics operations like masked_blit, draw_sprite and so on. * This parameter defines the policy of AllegroGL relative to the management * of this texture. * Several options are available : * - AGL_RELEASE : internal texture is released in order to free video memory. * - AGL_KEEP : internal texture is kept in video memory. This option generally * accelerate graphics operations when allegro_gl_set_allegro_mode() and * allegro_gl_unset_allegro_mode() are often called. * System with few video memory should use AGL_RELEASE while others should use * AGL_KEEP since it allows the internal texture to be created once. * Default value is AGL_KEEP. * */ #define AGL_VIDEO_MEMORY_POLICY 0x00100000 /** Define multisample parameters * Some OpenGL ICDs expose an extension called GL_ARB_multisample which * provides a mechanism to anti-alias all GL primitives: points, lines, * polygons, bitmaps and pixel rectangles. * * In order to get an AllegroGL mode which supports multisample, you have to * set both #AGL_SAMPLE_BUFFERS to 1 and #AGL_SAMPLES to the number of desired * samples for multisampling. * * Notice however that since this feature relies on several extensions * (GL_ARB_multisample and GLX_ARB_multisample or WGL_ARB_multisample), * it isn't guaranteed that AllegroGL will find a graphics mode that supports * multisample : many not-so-old video cards, like the GeForce 2, do not * support multisampling * * Hence, if you want your app to be able to run on most platforms, you * should not require this parameter. * * Set this value to 1 to enable multisampling. * * \see AGL_SAMPLES */ #define AGL_SAMPLE_BUFFERS 0x00200000 /** Define multisample samples * Set this value to the number of samples that can be accepted in the * multisample buffers. * * \see AGL_SAMPLE_BUFFERS */ #define AGL_SAMPLES 0x00400000 /** \} */ /** Floating-point Color buffer. */ #define AGL_FLOAT_COLOR 0x00800000 /** Floating-point Depth buffer. */ #define AGL_FLOAT_Z 0x01000000 /* XXX I'm reserving 2 bits here for later expansion. DO NOT USE * without consulting me first. */ #define AGL_CONFIG_RESRVED 0xA000000 /** \name Mode selection priority options * \{ */ #define AGL_DONTCARE 0 ///< Ignore these settings #define AGL_SUGGEST -1 ///< Prefer the assigned values for these settings #define AGL_REQUIRE -2 ///< Reject other values for these settings /** \} */ /** \name Video memory policy options * \{ */ #define AGL_KEEP 1 ///< Keep internal texture in video memory #define AGL_RELEASE 2 ///< Release video memory occupied by internal texture /** \} */ /** \name Mode selection functions * \{ */ AGL_FUNC(void, allegro_gl_clear_settings, (void)); AGL_FUNC(void, allegro_gl_set, (int option, int value)); AGL_FUNC(int, allegro_gl_get, (int option)); AGL_FUNC(void, allegro_gl_save_settings, (void)); AGL_FUNC(void, allegro_gl_load_settings, (void)); /** \} */ /** \} */ /** \defgroup gfxdrv Graphics drivers * * Use set_gfx_mode to select an OpenGL mode as normal, but using e.g. * GFX_OPENGL as the driver. The virtual width and height are ignored. * To set the colour depth, use allegro_gl_set (AGL_COLOR_DEPTH, xxx). * However if the color depth is not set by allegro_gl_set(), AllegroGL * will refer to the value set by the last call to set_color_depth(). * * Allegro modes are still available. Use of GFX_AUTODETECT or * GFX_AUTODETECT_WINDOWED will select Allegro modes, and not OpenGL modes. */ #if defined DOXYGEN /* Is this a documentation scan? */ /** \ingroup gfxdrv * \name Graphics drivers * \{ */ /** Windowed OpenGL graphics driver for Allegro */ # define GFX_OPENGL_WINDOWED /** Fullscreen OpenGL graphics driver for Allegro */ # define GFX_OPENGL_FULLSCREEN /** Non-specific OpenGL graphics driver for Allegro */ #define GFX_OPENGL /** \} */ #else #if defined ALLEGROGL_GENERIC_DRIVER /* Allegro is able to determine at run-time if windowed or fullscreen modes are available */ #define GFX_OPENGL_WINDOWED AL_ID('O','G','L','W') #define GFX_OPENGL_FULLSCREEN AL_ID('O','G','L','F') #else #if defined _WIN32 /* Windows always supports fullscreen */ #define GFX_OPENGL_WINDOWED AL_ID('O','G','L','W') #define GFX_OPENGL_FULLSCREEN AL_ID('O','G','L','F') #elif defined ALLEGRO_WITH_XWINDOWS /* X always supports fullscreen */ #define GFX_OPENGL_WINDOWED AL_ID('O','G','L','W') #define GFX_OPENGL_FULLSCREEN AL_ID('O','G','L','F') #elif defined ALLEGRO_MACOSX /* MacOS X always supports fullscreen */ #define GFX_OPENGL_WINDOWED AL_ID('O','G','L','W') #define GFX_OPENGL_FULLSCREEN AL_ID('O','G','L','F') #else #warning Unknown or unsupported platform. #endif #endif #define GFX_OPENGL AL_ID('O','G','L','D') #endif /* Declare graphics driver objects */ extern GFX_DRIVER gfx_allegro_gl_default; #ifdef GFX_OPENGL_WINDOWED extern GFX_DRIVER gfx_allegro_gl_windowed; #endif #ifdef GFX_OPENGL_FULLSCREEN extern GFX_DRIVER gfx_allegro_gl_fullscreen; #endif /** \defgroup bitmap Bitmap Routines * AllegroGL provides a function to set color depth for video * bitmaps. */ /** \{ */ /** \name Video Bitmap Rountines * \{ */ AGL_FUNC(GLint, allegro_gl_set_video_bitmap_color_depth, (int bpp)); /** \} */ /** \} */ /** \defgroup texture Texture Routines * AllegroGL provides functions to allow using Allegro BITMAP objects to * be used as OpenGL textures. */ /** \{ */ /** \name Texture routines * \{ */ AGL_FUNC(int, allegro_gl_use_mipmapping, (int enable)); AGL_FUNC(int, allegro_gl_use_alpha_channel, (int enable)); AGL_FUNC(int, allegro_gl_flip_texture, (int enable)); AGL_FUNC(int, allegro_gl_check_texture, (BITMAP *bmp)); AGL_FUNC(int, allegro_gl_check_texture_ex, (int flags, BITMAP *bmp, GLint internal_format)); AGL_FUNC(GLint, allegro_gl_get_texture_format, (BITMAP *bmp)); AGL_FUNC(GLint, allegro_gl_set_texture_format, (GLint format)); AGL_FUNC(GLenum, allegro_gl_get_bitmap_type, (BITMAP *bmp)); AGL_FUNC(GLenum, allegro_gl_get_bitmap_color_format, (BITMAP *bmp)); AGL_FUNC(GLuint, allegro_gl_make_texture, (BITMAP *bmp)); AGL_FUNC(GLuint, allegro_gl_make_masked_texture, (BITMAP *bmp)); AGL_FUNC(GLuint, allegro_gl_make_texture_ex,(int flags, BITMAP *bmp, GLint internal_format)); /** AllegroGL will generate mipmaps for this texture. */ #define AGL_TEXTURE_MIPMAP 0x01 /** Tell AllegroGL that the bitmap had an alpha channel, so it should be * preserved when generating the texture. */ #define AGL_TEXTURE_HAS_ALPHA 0x02 /** Flip the texture on the x-axis. OpenGL uses the bottom-left corner of * the texture as (0,0), so if you need your texture to be flipped to make * (0,0) the top-left corner, you need to use this flag. */ #define AGL_TEXTURE_FLIP 0x04 /** Generate an alpha channel for this texture, based on the Allegro mask color. * Make sure the target format supports an alpha channel. */ #define AGL_TEXTURE_MASKED 0x08 /** Tell AllegroGL to allow rescaling of the bitmap. By default, AllegroGL * will not rescale the bitmap to fit into a texture. You can override this * behavior by using this flag. */ #define AGL_TEXTURE_RESCALE 0x10 /** Tell AllegroGL that the specified BITMAP is an 8-bpp alpha-only BITMAP. */ #define AGL_TEXTURE_ALPHA_ONLY 0x20 /** \} */ /** \} */ /** \addtogroup allegro Allegro Interfacing * * \{ */ /** \name Allegro Interfacing routines * \{ */ AGL_FUNC(void, allegro_gl_set_allegro_mode, (void)); AGL_FUNC(void, allegro_gl_unset_allegro_mode, (void)); AGL_FUNC(void, allegro_gl_set_projection, (void)); AGL_FUNC(void, allegro_gl_unset_projection, (void)); /** \} */ /** \} */ /** \defgroup math Math conversion routines * Routines to convert between OpenGL and Allegro math types */ /** \{ */ /** \name Matrix conversion routines * \{ */ AGL_FUNC(void, allegro_gl_MATRIX_to_GLfloat, (MATRIX *m, GLfloat gl[16])); AGL_FUNC(void, allegro_gl_MATRIX_to_GLdouble, (MATRIX *m, GLdouble gl[16])); AGL_FUNC(void, allegro_gl_MATRIX_f_to_GLfloat, (MATRIX_f *m, GLfloat gl[16])); AGL_FUNC(void, allegro_gl_MATRIX_f_to_GLdouble, (MATRIX_f *m, GLdouble gl[16])); AGL_FUNC(void, allegro_gl_GLfloat_to_MATRIX, (GLfloat gl[16], MATRIX *m)); AGL_FUNC(void, allegro_gl_GLdouble_to_MATRIX, (GLdouble gl[16], MATRIX *m)); AGL_FUNC(void, allegro_gl_GLfloat_to_MATRIX_f, (GLfloat gl[16], MATRIX_f *m)); AGL_FUNC(void, allegro_gl_GLdouble_to_MATRIX_f, (GLdouble gl[16], MATRIX_f *m)); /** \} */ /** \name Quaternion conversion routines * \{ */ AGL_FUNC(void, allegro_gl_apply_quat, (QUAT *q)); AGL_FUNC(void, allegro_gl_quat_to_glrotatef, (QUAT *q, float *angle, float *x, float *y, float *z)); AGL_FUNC(void, allegro_gl_quat_to_glrotated, (QUAT *q, double *angle, double *x, double *y, double *z)); /** \} */ /** \} */ /** \defgroup Text Text drawing and fonts. * * AllegroGL now provides mechanisms for converting Allegro FONTs to * a format which is more usable in OpenGL. You can also load system * fonts (such as Arial and Courrier) and draw using those. * Allegro FONTs should still work if you use textout, textprintf, etc * on them. However, converted Allegro FONTs will not work with these * functions. You will have to use AllegroGL functions to work with * AllegroGL FONTs. * * \{ */ /** \name Text Drawing and Font conversion * \{ */ /* These define the supported font types */ /** Indicates that you don't really care how a font will be converted. * AGL will pick the best format for you. */ #define AGL_FONT_TYPE_DONT_CARE -1 /** Indicates that you want fonts to be converted to a bitmap format. * Bitmaps are used to represent characters with one bit per pixel, * and are usually very slow to draw, as they stall the 3D pipeline. * Note that you can't scale, rotate or place text with a z coordinate * if you use this style. * A display list will be created. * * \sa allegro_gl_convert_allegro_font(), allegro_gl_printf() */ #define AGL_FONT_TYPE_BITMAP 0 /** Indicates that you want fonts to be converted to an outline format. * Outlined mode is a vector-style font. Characters are represented by a * set of polygons and lines. This style of fonts is fast to draw, and can * be scaled, rotated, etc, since they are just vectors. * A display list will be created. * * \deprecated Non-textured fonts will be dropped from AllegroGL. * * \sa allegro_gl_convert_allegro_font(), allegro_gl_printf() */ #define AGL_FONT_TYPE_OUTLINE 1 /** Indicates that you want fonts to be converted to a texture format. * Each character is represented by a textured quad. The texture is * common for all characters of the same font, and it will automatically be * uploaded to the video card when needed. Drawing text with this * type of font is the fastest since only two triangles are needed per * character. Textured text can also be scaled and rotated. * A display list will be created. * * \sa allegro_gl_convert_allegro_font(), allegro_gl_printf() */ #define AGL_FONT_TYPE_TEXTURED 2 /* These defines the font styles for system generated fonts */ /** Creates a font with bold characters. System fonts only. * * \deprecated Non-textured fonts will be dropped from AllegroGL */ #define AGL_FONT_STYLE_BOLD 1 /** Creates a font with black (strong bold) characters. System fonts only. * \deprecated Non-textured fonts will be dropped from AllegroGL. */ #define AGL_FONT_STYLE_BLACK 2 /** Creates a font with italicized characters. System fonts only. * \deprecated Non-textured fonts will be dropped from AllegroGL. */ #define AGL_FONT_STYLE_ITALIC 4 /** Creates a font with underlined characters. System fonts only. * \deprecated Non-textured fonts will be dropped from AllegroGL. */ #define AGL_FONT_STYLE_UNDERLINE 8 /** Creates a font with striked out characters. System fonts only. * \deprecated Non-textured fonts will be dropped from AllegroGL. */ #define AGL_FONT_STYLE_STRIKEOUT 16 /** Creates a font with anti-aliased characters. System fonts only. * Anti-aliasing may not be available, and no error will be reported * if such is the case. * \deprecated Non-textured fonts will be dropped from AllegroGL. */ #define AGL_FONT_STYLE_ANTI_ALIASED 32 /** Font generation mode. System fonts only. * Indicates that you want outline system fonts to be generated using polygons. * \deprecated Non-textured fonts will be dropped from AllegroGL. * * \sa allegro_gl_load_system_font(), allegro_gl_load_system_font_ex() */ #define AGL_FONT_POLYGONS 1 /** Font generation mode. System fonts only. * Indicates that you want outline system fonts to be generated using lines. * \deprecated Non-textured fonts will be dropped from AllegroGL. * * \sa allegro_gl_load_system_font(), allegro_gl_load_system_font_ex() */ #define AGL_FONT_LINES 2 AGL_FUNC(int, allegro_gl_printf, (AL_CONST FONT *f, float x, float y, float z, int color, AL_CONST char *format, ...)); AGL_FUNC(int, allegro_gl_printf_ex, (AL_CONST FONT *f, float x, float y, float z, AL_CONST char *format, ...)); AGL_FUNC(FONT*, allegro_gl_convert_allegro_font, (FONT *f, int type, float scale)); AGL_FUNC(FONT*, allegro_gl_convert_allegro_font_ex, (FONT *f, int type, float scale, GLint format)); AGL_FUNC(void, allegro_gl_set_font_generation_mode, (int mode)); AGL_FUNC(FONT*, allegro_gl_load_system_font, (char *name, int style, int w, int h)); AGL_FUNC(FONT*, allegro_gl_load_system_font_ex, (char *name, int type, int style, int w, int h, float depth, int start, int end)); AGL_FUNC(void, allegro_gl_destroy_font, (FONT *f)); AGL_FUNC(size_t, allegro_gl_list_font_textures, (FONT *f, GLuint *ids, size_t max_num_id)); /** \} */ /** \} */ /** \defgroup extensions OpenGL Extensions * Management of the OpenGL extensions mechanism. * AllegroGL provides two ways to access OpenGL extensions: It's native * extension library and some versatile portable routines. * * If you want to get more control on extensions or if you want to use an * extension that is not supported by AllegroGL then you can use the * routines : allegro_gl_is_extension_supported() and * allegro_gl_get_proc_address(). They provide a way to determine if an * extension is available and to get its address. These routines are available * on every platforms that AllegroGL supports * */ /** \{ */ /** \name OpenGL Extensions Management Functions * \{ */ #if defined DOXYGEN /* Is this a documentation scan? */ /** OpenGL extensions handlers helper. * Defines a function pointer type. This macro is almost equivalent to a * \b typedef. It is intended to hide some platform-specific machinery in * order to keep code portable. * * \sa allegro_gl_get_proc_address() */ #define AGL_DEFINE_PROC_TYPE #else AGL_FUNC(int, allegro_gl_is_extension_supported, (const char *)); AGL_FUNC(void*, allegro_gl_get_proc_address, (const char *)); #if defined ALLEGRO_WINDOWS #define AGL_DEFINE_PROC_TYPE(type, name, args) \ typedef type (APIENTRY * name) args; #else #define AGL_DEFINE_PROC_TYPE(type, name, args) \ typedef type (*name) args; #endif #endif /** \} */ /** \} */ /** \defgroup gui Allegro-compatible GUI routines * AllegroGL GUI wrappers. * Due to several specificities of OpenGL, some of the Allegro's GUI routines * can not be used "as is". Indeed they are not designed to natively support * double-buffered graphics mode. Hence AllegroGL provides wrapper routines * of do_dialog, alert and so on... * * AllegroGL GUI routines internally call allegro_gl_set_allegro_mode() and its * counterpart allegro_gl_unset_allegro_mode(). So the default drawing mode in * the GUI routines is the "2D Allegro mode" and functions like line() or * rect() can safely be called. * * Additionnaly AllegroGL provides a new GUI object d_algl_viewport_proc() * which allows to have a 3D viewport that can safely coexist with other * "classical" 2D GUI objects : no need to call allegro_gl_set_allegro_mode() * or to save the current state of OpenGL. */ /** \{ */ AGL_FUNC(int, algl_do_dialog, (DIALOG *dialog, int focus_obj)); AGL_FUNC(int, algl_popup_dialog, (DIALOG *dialog, int focus_obj)); AGL_FUNC(void, algl_draw_mouse, (void)); AGL_FUNC(void, algl_set_mouse_drawer, (void (*user_draw_mouse)(void))); AGL_FUNC(int, algl_alert, (AL_CONST char *s1, AL_CONST char *s2, AL_CONST char *s3, AL_CONST char *b1, AL_CONST char *b2, int c1, int c2)); AGL_FUNC(int, algl_alert3, (AL_CONST char *s1, AL_CONST char *s2, AL_CONST char *s3, AL_CONST char *b1, AL_CONST char *b2, AL_CONST char *b3, int c1, int c2, int c3)); AGL_FUNC(int, d_algl_viewport_proc, (int msg, DIALOG *d, int c)); /** \} */ #ifdef __cplusplus } #endif /* Fixes to MS's (or SGI?) broken GL headers */ #ifdef GL_VERSION_1_1 #ifndef GL_TEXTURE_BINDING_2D #ifdef GL_TEXTURE_2D_BINDING #define GL_TEXTURE_BINDING_2D GL_TEXTURE_2D_BINDING #endif #else #ifdef GL_TEXTURE_BINDING_2D #define GL_TEXTURE_2D_BINDING GL_TEXTURE_BINDING_2D #endif #endif #ifndef GL_TEXTURE_BINDING_2D #warning "GL_TEXTURE_BINDING_2D or GL_TEXTURE_2D_BINDING isn't defined by your" #warning "OpenGL headers. Make sure you have a genuine set of headers for" #warning "OpenGL 1.1 (or greater)" #endif #endif #endif allegro4.4-4.4.2/addons/allegrogl/include/allegrogl/000077500000000000000000000000001173507505700222215ustar00rootroot00000000000000allegro4.4-4.4.2/addons/allegrogl/include/allegrogl/GLext/000077500000000000000000000000001173507505700232445ustar00rootroot00000000000000allegro4.4-4.4.2/addons/allegrogl/include/allegrogl/GLext/gl_ext_alias.h000066400000000000000000003004201173507505700260470ustar00rootroot00000000000000/*Automatically generated by mkalias.sh DO NOT EDIT!*/ /**/ #ifdef AGL_VERSION_1_2 #define glBlendColor __aglBlendColor #define glBlendEquation __aglBlendEquation #define glDrawRangeElements __aglDrawRangeElements #define glColorTable __aglColorTable #define glColorTableParameterfv __aglColorTableParameterfv #define glColorTableParameteriv __aglColorTableParameteriv #define glCopyColorTable __aglCopyColorTable #define glGetColorTable __aglGetColorTable #define glGetColorTableParameterfv __aglGetColorTableParameterfv #define glGetColorTableParameteriv __aglGetColorTableParameteriv #define glColorSubTable __aglColorSubTable #define glCopyColorSubTable __aglCopyColorSubTable #define glTexImage3D __aglTexImage3D #define glTexSubImage3D __aglTexSubImage3D #define glCopyTexSubImage3D __aglCopyTexSubImage3D #endif #if defined AGL_ARB_imaging #define glConvolutionFilter1D __aglConvolutionFilter1D #define glConvolutionFilter2D __aglConvolutionFilter2D #define glConvolutionParameterf __aglConvolutionParameterf #define glConvolutionParameterfv __aglConvolutionParameterfv #define glConvolutionParameteri __aglConvolutionParameteri #define glConvolutionParameteriv __aglConvolutionParameteriv #define glCopyConvolutionFilter1D __aglCopyConvolutionFilter1D #define glCopyConvolutionFilter2D __aglCopyConvolutionFilter2D #define glGetConvolutionFilter __aglGetConvolutionFilter #define glGetConvolutionParameterfv __aglGetConvolutionParameterfv #define glGetConvolutionParameteriv __aglGetConvolutionParameteriv #define glGetSeparableFilter __aglGetSeparableFilter #define glSeparableFilter2D __aglSeparableFilter2D #define glGetHistogram __aglGetHistogram #define glGetHistogramParameterfv __aglGetHistogramParameterfv #define glGetHistogramParameteriv __aglGetHistogramParameteriv #define glGetMinmax __aglGetMinmax #define glGetMinmaxParameterfv __aglGetMinmaxParameterfv #define glGetMinmaxParameteriv __aglGetMinmaxParameteriv #define glHistogram __aglHistogram #define glMinmax __aglMinmax #define glResetHistogram __aglResetHistogram #define glResetMinmax __aglResetMinmax #endif #if defined AGL_VERSION_1_3 #define glActiveTexture __aglActiveTexture #define glClientActiveTexture __aglClientActiveTexture #define glMultiTexCoord1d __aglMultiTexCoord1d #define glMultiTexCoord1dv __aglMultiTexCoord1dv #define glMultiTexCoord1f __aglMultiTexCoord1f #define glMultiTexCoord1fv __aglMultiTexCoord1fv #define glMultiTexCoord1i __aglMultiTexCoord1i #define glMultiTexCoord1iv __aglMultiTexCoord1iv #define glMultiTexCoord1s __aglMultiTexCoord1s #define glMultiTexCoord1sv __aglMultiTexCoord1sv #define glMultiTexCoord2d __aglMultiTexCoord2d #define glMultiTexCoord2dv __aglMultiTexCoord2dv #define glMultiTexCoord2f __aglMultiTexCoord2f #define glMultiTexCoord2fv __aglMultiTexCoord2fv #define glMultiTexCoord2i __aglMultiTexCoord2i #define glMultiTexCoord2iv __aglMultiTexCoord2iv #define glMultiTexCoord2s __aglMultiTexCoord2s #define glMultiTexCoord2sv __aglMultiTexCoord2sv #define glMultiTexCoord3d __aglMultiTexCoord3d #define glMultiTexCoord3dv __aglMultiTexCoord3dv #define glMultiTexCoord3f __aglMultiTexCoord3f #define glMultiTexCoord3fv __aglMultiTexCoord3fv #define glMultiTexCoord3i __aglMultiTexCoord3i #define glMultiTexCoord3iv __aglMultiTexCoord3iv #define glMultiTexCoord3s __aglMultiTexCoord3s #define glMultiTexCoord3sv __aglMultiTexCoord3sv #define glMultiTexCoord4d __aglMultiTexCoord4d #define glMultiTexCoord4dv __aglMultiTexCoord4dv #define glMultiTexCoord4f __aglMultiTexCoord4f #define glMultiTexCoord4fv __aglMultiTexCoord4fv #define glMultiTexCoord4i __aglMultiTexCoord4i #define glMultiTexCoord4iv __aglMultiTexCoord4iv #define glMultiTexCoord4s __aglMultiTexCoord4s #define glMultiTexCoord4sv __aglMultiTexCoord4sv #define glLoadTransposeMatrixf __aglLoadTransposeMatrixf #define glLoadTransposeMatrixd __aglLoadTransposeMatrixd #define glMultTransposeMatrixf __aglMultTransposeMatrixf #define glMultTransposeMatrixd __aglMultTransposeMatrixd #define glSampleCoverage __aglSampleCoverage #define glCompressedTexImage3D __aglCompressedTexImage3D #define glCompressedTexImage2D __aglCompressedTexImage2D #define glCompressedTexImage1D __aglCompressedTexImage1D #define glCompressedTexSubImage3D __aglCompressedTexSubImage3D #define glCompressedTexSubImage2D __aglCompressedTexSubImage2D #define glCompressedTexSubImage1D __aglCompressedTexSubImage1D #define glGetCompressedTexImage __aglGetCompressedTexImage #endif #if defined AGL_VERSION_1_4 #define glBlendFuncSeparate __aglBlendFuncSeparate #define glFogCoordf __aglFogCoordf #define glFogCoordfv __aglFogCoordfv #define glFogCoordd __aglFogCoordd #define glFogCoorddv __aglFogCoorddv #define glFogCoordPointer __aglFogCoordPointer #define glMultiDrawArrays __aglMultiDrawArrays #define glMultiDrawElements __aglMultiDrawElements #define glPointParameterf __aglPointParameterf #define glPointParameterfv __aglPointParameterfv #define glPointParameteri __aglPointParameteri #define glPointParameteriv __aglPointParameteriv #define glSecondaryColor3b __aglSecondaryColor3b #define glSecondaryColor3bv __aglSecondaryColor3bv #define glSecondaryColor3d __aglSecondaryColor3d #define glSecondaryColor3dv __aglSecondaryColor3dv #define glSecondaryColor3f __aglSecondaryColor3f #define glSecondaryColor3fv __aglSecondaryColor3fv #define glSecondaryColor3i __aglSecondaryColor3i #define glSecondaryColor3iv __aglSecondaryColor3iv #define glSecondaryColor3s __aglSecondaryColor3s #define glSecondaryColor3sv __aglSecondaryColor3sv #define glSecondaryColor3ub __aglSecondaryColor3ub #define glSecondaryColor3ubv __aglSecondaryColor3ubv #define glSecondaryColor3ui __aglSecondaryColor3ui #define glSecondaryColor3uiv __aglSecondaryColor3uiv #define glSecondaryColor3us __aglSecondaryColor3us #define glSecondaryColor3usv __aglSecondaryColor3usv #define glSecondaryColorPointer __aglSecondaryColorPointer #define glWindowPos2d __aglWindowPos2d #define glWindowPos2dv __aglWindowPos2dv #define glWindowPos2f __aglWindowPos2f #define glWindowPos2fv __aglWindowPos2fv #define glWindowPos2i __aglWindowPos2i #define glWindowPos2iv __aglWindowPos2iv #define glWindowPos2s __aglWindowPos2s #define glWindowPos2sv __aglWindowPos2sv #define glWindowPos3d __aglWindowPos3d #define glWindowPos3dv __aglWindowPos3dv #define glWindowPos3f __aglWindowPos3f #define glWindowPos3fv __aglWindowPos3fv #define glWindowPos3i __aglWindowPos3i #define glWindowPos3iv __aglWindowPos3iv #define glWindowPos3s __aglWindowPos3s #define glWindowPos3sv __aglWindowPos3sv #endif #if defined AGL_VERSION_1_5 #define glBindBuffer __aglBindBuffer #define glDeleteBuffers __aglDeleteBuffers #define glGenBuffers __aglGenBuffers #define glIsBuffer __aglIsBuffer #define glBufferData __aglBufferData #define glBufferSubData __aglBufferSubData #define glGetBufferSubData __aglGetBufferSubData #define glMapBuffer __aglMapBuffer #define glUnmapBuffer __aglUnmapBuffer #define glGetBufferParameteriv __aglGetBufferParameteriv #define glGetBufferPointerv __aglGetBufferPointerv #define glGenQueries __aglGenQueries #define glDeleteQueries __aglDeleteQueries #define glIsQuery __aglIsQuery #define glBeginQuery __aglBeginQuery #define glEndQuery __aglEndQuery #define glGetQueryiv __aglGetQueryiv #define glGetQueryObjectiv __aglGetQueryObjectiv #define glGetQueryObjectuiv __aglGetQueryObjectuiv #endif #if defined AGL_VERSION_2_0 #define glCreateProgram __aglCreateProgram #define glCreateShader __aglCreateShader #define glDeleteProgram __aglDeleteProgram #define glDeleteShader __aglDeleteShader #define glAttachShader __aglAttachShader #define glDetachShader __aglDetachShader #define glShaderSource __aglShaderSource #define glCompileShader __aglCompileShader #define glIsProgram __aglIsProgram #define glIsShader __aglIsShader #define glLinkProgram __aglLinkProgram #define glUseProgram __aglUseProgram #define glValidateProgram __aglValidateProgram #define glUniform1f __aglUniform1f #define glUniform2f __aglUniform2f #define glUniform3f __aglUniform3f #define glUniform4f __aglUniform4f #define glUniform1i __aglUniform1i #define glUniform2i __aglUniform2i #define glUniform3i __aglUniform3i #define glUniform4i __aglUniform4i #define glUniform1fv __aglUniform1fv #define glUniform2fv __aglUniform2fv #define glUniform3fv __aglUniform3fv #define glUniform4fv __aglUniform4fv #define glUniform1iv __aglUniform1iv #define glUniform2iv __aglUniform2iv #define glUniform3iv __aglUniform3iv #define glUniform4iv __aglUniform4iv #define glUniformMatrix2fv __aglUniformMatrix2fv #define glUniformMatrix3fv __aglUniformMatrix3fv #define glUniformMatrix4fv __aglUniformMatrix4fv #define glGetShaderfv __aglGetShaderfv #define glGetShaderiv __aglGetShaderiv #define glGetProgramfv __aglGetProgramfv #define glGetProgramiv __aglGetProgramiv #define glGetShaderInfoLog __aglGetShaderInfoLog #define glGetProgramInfoLog __aglGetProgramInfoLog #define glGetAttachedShaders __aglGetAttachedShaders #define glGetUniformLocation __aglGetUniformLocation #define glGetActiveUniform __aglGetActiveUniform #define glGetUniformfv __aglGetUniformfv #define glGetUniformiv __aglGetUniformiv #define glGetShaderSource __aglGetShaderSource #define glVertexAttrib1f __aglVertexAttrib1f #define glVertexAttrib1s __aglVertexAttrib1s #define glVertexAttrib1d __aglVertexAttrib1d #define glVertexAttrib2f __aglVertexAttrib2f #define glVertexAttrib2s __aglVertexAttrib2s #define glVertexAttrib2d __aglVertexAttrib2d #define glVertexAttrib3f __aglVertexAttrib3f #define glVertexAttrib3s __aglVertexAttrib3s #define glVertexAttrib3d __aglVertexAttrib3d #define glVertexAttrib4f __aglVertexAttrib4f #define glVertexAttrib4s __aglVertexAttrib4s #define glVertexAttrib4d __aglVertexAttrib4d #define glVertexAttrib4Nub __aglVertexAttrib4Nub #define glVertexAttrib1fv __aglVertexAttrib1fv #define glVertexAttrib1sv __aglVertexAttrib1sv #define glVertexAttrib1dv __aglVertexAttrib1dv #define glVertexAttrib2fv __aglVertexAttrib2fv #define glVertexAttrib2sv __aglVertexAttrib2sv #define glVertexAttrib2dv __aglVertexAttrib2dv #define glVertexAttrib3fv __aglVertexAttrib3fv #define glVertexAttrib3sv __aglVertexAttrib3sv #define glVertexAttrib3dv __aglVertexAttrib3dv #define glVertexAttrib4fv __aglVertexAttrib4fv #define glVertexAttrib4sv __aglVertexAttrib4sv #define glVertexAttrib4dv __aglVertexAttrib4dv #define glVertexAttrib4iv __aglVertexAttrib4iv #define glVertexAttrib4bv __aglVertexAttrib4bv #define glVertexAttrib4ubv __aglVertexAttrib4ubv #define glVertexAttrib4usv __aglVertexAttrib4usv #define glVertexAttrib4uiv __aglVertexAttrib4uiv #define glVertexAttrib4Nbv __aglVertexAttrib4Nbv #define glVertexAttrib4Nsv __aglVertexAttrib4Nsv #define glVertexAttrib4Niv __aglVertexAttrib4Niv #define glVertexAttrib4Nubv __aglVertexAttrib4Nubv #define glVertexAttrib4Nusv __aglVertexAttrib4Nusv #define glVertexAttrib4Nuiv __aglVertexAttrib4Nuiv #define glVertexAttribPointer __aglVertexAttribPointer #define glEnableVertexAttribArray __aglEnableVertexAttribArray #define glDisableVertexAttribArray __aglDisableVertexAttribArray #define glBindAttribLocation __aglBindAttribLocation #define glGetActiveAttrib __aglGetActiveAttrib #define glGetAttribLocation __aglGetAttribLocation #define glGetVertexAttribdv __aglGetVertexAttribdv #define glGetVertexAttribfv __aglGetVertexAttribfv #define glGetVertexAttribiv __aglGetVertexAttribiv #define glGetVertexAttribPointerv __aglGetVertexAttribPointerv #define glDrawBuffers __aglDrawBuffers #define glStencilOpSeparate __aglStencilOpSeparate #define glStencilFuncSeparate __aglStencilFuncSeparate #endif #if defined AGL_VERSION_2_1 #define glUniformMatrix2x3fv __aglUniformMatrix2x3fv #define glUniformMatrix3x2fv __aglUniformMatrix3x2fv #define glUniformMatrix2x4fv __aglUniformMatrix2x4fv #define glUniformMatrix4x2fv __aglUniformMatrix4x2fv #define glUniformMatrix3x4fv __aglUniformMatrix3x4fv #define glUniformMatrix4x3fv __aglUniformMatrix4x3fv #endif #if defined AGL_VERSION_3_0 /*OpenGL3.0alsoreusesentrypointsfromtheseextensions:*/ /*ARB_framebuffer_object*/ /*ARB_map_buffer_range*/ /*ARB_vertex_array_object*/ #define glColorMaski __aglColorMaski #define glGetBooleani_v __aglGetBooleani_v #define glGetIntegeri_v __aglGetIntegeri_v #define glEnablei __aglEnablei #define glDisablei __aglDisablei #define glIsEnabledi __aglIsEnabledi #define glBeginTransformFeedback __aglBeginTransformFeedback #define glEndTransformFeedback __aglEndTransformFeedback #define glBindBufferRange __aglBindBufferRange #define glBindBufferBase __aglBindBufferBase #define glTransformFeedbackVaryings __aglTransformFeedbackVaryings #define glGetTransformFeedbackVarying __aglGetTransformFeedbackVarying #define glClampColor __aglClampColor #define glBeginConditionalRender __aglBeginConditionalRender #define glEndConditionalRender __aglEndConditionalRender #define glVertexAttribI1i __aglVertexAttribI1i #define glVertexAttribI2i __aglVertexAttribI2i #define glVertexAttribI3i __aglVertexAttribI3i #define glVertexAttribI4i __aglVertexAttribI4i #define glVertexAttribI1ui __aglVertexAttribI1ui #define glVertexAttribI2ui __aglVertexAttribI2ui #define glVertexAttribI3ui __aglVertexAttribI3ui #define glVertexAttribI4ui __aglVertexAttribI4ui #define glVertexAttribI1iv __aglVertexAttribI1iv #define glVertexAttribI2iv __aglVertexAttribI2iv #define glVertexAttribI3iv __aglVertexAttribI3iv #define glVertexAttribI4iv __aglVertexAttribI4iv #define glVertexAttribI1uiv __aglVertexAttribI1uiv #define glVertexAttribI2uiv __aglVertexAttribI2uiv #define glVertexAttribI3uiv __aglVertexAttribI3uiv #define glVertexAttribI4uiv __aglVertexAttribI4uiv #define glVertexAttribI4bv __aglVertexAttribI4bv #define glVertexAttribI4sv __aglVertexAttribI4sv #define glVertexAttribI4ubv __aglVertexAttribI4ubv #define glVertexAttribI4usv __aglVertexAttribI4usv #define glVertexAttribIPointer __aglVertexAttribIPointer #define glGetVertexAttribIiv __aglGetVertexAttribIiv #define glGetVertexAttribIuiv __aglGetVertexAttribIuiv #define glGetUniformuiv __aglGetUniformuiv #define glBindFragDataLocation __aglBindFragDataLocation #define glGetFragDataLocation __aglGetFragDataLocation #define glUniform1ui __aglUniform1ui #define glUniform2ui __aglUniform2ui #define glUniform3ui __aglUniform3ui #define glUniform4ui __aglUniform4ui #define glUniform1uiv __aglUniform1uiv #define glUniform2uiv __aglUniform2uiv #define glUniform3uiv __aglUniform3uiv #define glUniform4uiv __aglUniform4uiv #define glTexParameterIiv __aglTexParameterIiv #define glTexParameterIuiv __aglTexParameterIuiv #define glGetTexParameterIiv __aglGetTexParameterIiv #define glGetTexParameterIuiv __aglGetTexParameterIuiv #define glClearBufferiv __aglClearBufferiv #define glClearBufferuiv __aglClearBufferuiv #define glClearBufferfv __aglClearBufferfv #define glClearBufferfi __aglClearBufferfi #define glGetStringi __aglGetStringi #endif /**/ /**/ #ifdef AGL_ARB_multitexture #define glActiveTextureARB __aglActiveTextureARB #define glClientActiveTextureARB __aglClientActiveTextureARB #define glMultiTexCoord1dARB __aglMultiTexCoord1dARB #define glMultiTexCoord1dvARB __aglMultiTexCoord1dvARB #define glMultiTexCoord1fARB __aglMultiTexCoord1fARB #define glMultiTexCoord1fvARB __aglMultiTexCoord1fvARB #define glMultiTexCoord1iARB __aglMultiTexCoord1iARB #define glMultiTexCoord1ivARB __aglMultiTexCoord1ivARB #define glMultiTexCoord1sARB __aglMultiTexCoord1sARB #define glMultiTexCoord1svARB __aglMultiTexCoord1svARB #define glMultiTexCoord2dARB __aglMultiTexCoord2dARB #define glMultiTexCoord2dvARB __aglMultiTexCoord2dvARB #define glMultiTexCoord2fARB __aglMultiTexCoord2fARB #define glMultiTexCoord2fvARB __aglMultiTexCoord2fvARB #define glMultiTexCoord2iARB __aglMultiTexCoord2iARB #define glMultiTexCoord2ivARB __aglMultiTexCoord2ivARB #define glMultiTexCoord2sARB __aglMultiTexCoord2sARB #define glMultiTexCoord2svARB __aglMultiTexCoord2svARB #define glMultiTexCoord3dARB __aglMultiTexCoord3dARB #define glMultiTexCoord3dvARB __aglMultiTexCoord3dvARB #define glMultiTexCoord3fARB __aglMultiTexCoord3fARB #define glMultiTexCoord3fvARB __aglMultiTexCoord3fvARB #define glMultiTexCoord3iARB __aglMultiTexCoord3iARB #define glMultiTexCoord3ivARB __aglMultiTexCoord3ivARB #define glMultiTexCoord3sARB __aglMultiTexCoord3sARB #define glMultiTexCoord3svARB __aglMultiTexCoord3svARB #define glMultiTexCoord4dARB __aglMultiTexCoord4dARB #define glMultiTexCoord4dvARB __aglMultiTexCoord4dvARB #define glMultiTexCoord4fARB __aglMultiTexCoord4fARB #define glMultiTexCoord4fvARB __aglMultiTexCoord4fvARB #define glMultiTexCoord4iARB __aglMultiTexCoord4iARB #define glMultiTexCoord4ivARB __aglMultiTexCoord4ivARB #define glMultiTexCoord4sARB __aglMultiTexCoord4sARB #define glMultiTexCoord4svARB __aglMultiTexCoord4svARB #endif #if defined AGL_ARB_transpose_matrix #define glLoadTransposeMatrixfARB __aglLoadTransposeMatrixfARB #define glLoadTransposeMatrixdARB __aglLoadTransposeMatrixdARB #define glMultTransposeMatrixfARB __aglMultTransposeMatrixfARB #define glMultTransposeMatrixdARB __aglMultTransposeMatrixdARB #endif #if defined AGL_ARB_multisample #define glSampleCoverageARB __aglSampleCoverageARB #endif #if defined AGL_ARB_texture_compression #define glCompressedTexImage3DARB __aglCompressedTexImage3DARB #define glCompressedTexImage2DARB __aglCompressedTexImage2DARB #define glCompressedTexImage1DARB __aglCompressedTexImage1DARB #define glCompressedTexSubImage3DARB __aglCompressedTexSubImage3DARB #define glCompressedTexSubImage2DARB __aglCompressedTexSubImage2DARB #define glCompressedTexSubImage1DARB __aglCompressedTexSubImage1DARB #define glGetCompressedTexImageARB __aglGetCompressedTexImageARB #endif #if defined AGL_ARB_point_parameters #define glPointParameterfARB __aglPointParameterfARB #define glPointParameterfvARB __aglPointParameterfvARB #endif #if defined AGL_ARB_vertex_blend #define glWeightbvARB __aglWeightbvARB #define glWeightsvARB __aglWeightsvARB #define glWeightivARB __aglWeightivARB #define glWeightfvARB __aglWeightfvARB #define glWeightdvARB __aglWeightdvARB #define glWeightubvARB __aglWeightubvARB #define glWeightusvARB __aglWeightusvARB #define glWeightuivARB __aglWeightuivARB #define glWeightPointerARB __aglWeightPointerARB #define glVertexBlendARB __aglVertexBlendARB #endif #if defined AGL_ARB_matrix_palette #define glCurrentPaletteMatrixARB __aglCurrentPaletteMatrixARB #define glMatrixIndexubvARB __aglMatrixIndexubvARB #define glMatrixIndexusvARB __aglMatrixIndexusvARB #define glMatrixIndexuivARB __aglMatrixIndexuivARB #define glMatrixIndexPointerARB __aglMatrixIndexPointerARB #endif #if defined AGL_ARB_window_pos #define glWindowPos2dARB __aglWindowPos2dARB #define glWindowPos2dvARB __aglWindowPos2dvARB #define glWindowPos2fARB __aglWindowPos2fARB #define glWindowPos2fvARB __aglWindowPos2fvARB #define glWindowPos2iARB __aglWindowPos2iARB #define glWindowPos2ivARB __aglWindowPos2ivARB #define glWindowPos2sARB __aglWindowPos2sARB #define glWindowPos2svARB __aglWindowPos2svARB #define glWindowPos3dARB __aglWindowPos3dARB #define glWindowPos3dvARB __aglWindowPos3dvARB #define glWindowPos3fARB __aglWindowPos3fARB #define glWindowPos3fvARB __aglWindowPos3fvARB #define glWindowPos3iARB __aglWindowPos3iARB #define glWindowPos3ivARB __aglWindowPos3ivARB #define glWindowPos3sARB __aglWindowPos3sARB #define glWindowPos3svARB __aglWindowPos3svARB #endif #if defined AGL_ARB_vertex_program #define glVertexAttrib1dARB __aglVertexAttrib1dARB #define glVertexAttrib1dvARB __aglVertexAttrib1dvARB #define glVertexAttrib1fARB __aglVertexAttrib1fARB #define glVertexAttrib1fvARB __aglVertexAttrib1fvARB #define glVertexAttrib1sARB __aglVertexAttrib1sARB #define glVertexAttrib1svARB __aglVertexAttrib1svARB #define glVertexAttrib2dARB __aglVertexAttrib2dARB #define glVertexAttrib2dvARB __aglVertexAttrib2dvARB #define glVertexAttrib2fARB __aglVertexAttrib2fARB #define glVertexAttrib2fvARB __aglVertexAttrib2fvARB #define glVertexAttrib2sARB __aglVertexAttrib2sARB #define glVertexAttrib2svARB __aglVertexAttrib2svARB #define glVertexAttrib3dARB __aglVertexAttrib3dARB #define glVertexAttrib3dvARB __aglVertexAttrib3dvARB #define glVertexAttrib3fARB __aglVertexAttrib3fARB #define glVertexAttrib3fvARB __aglVertexAttrib3fvARB #define glVertexAttrib3sARB __aglVertexAttrib3sARB #define glVertexAttrib3svARB __aglVertexAttrib3svARB #define glVertexAttrib4NbvARB __aglVertexAttrib4NbvARB #define glVertexAttrib4NivARB __aglVertexAttrib4NivARB #define glVertexAttrib4NsvARB __aglVertexAttrib4NsvARB #define glVertexAttrib4NubARB __aglVertexAttrib4NubARB #define glVertexAttrib4NubvARB __aglVertexAttrib4NubvARB #define glVertexAttrib4NuivARB __aglVertexAttrib4NuivARB #define glVertexAttrib4NusvARB __aglVertexAttrib4NusvARB #define glVertexAttrib4bvARB __aglVertexAttrib4bvARB #define glVertexAttrib4dARB __aglVertexAttrib4dARB #define glVertexAttrib4dvARB __aglVertexAttrib4dvARB #define glVertexAttrib4fARB __aglVertexAttrib4fARB #define glVertexAttrib4fvARB __aglVertexAttrib4fvARB #define glVertexAttrib4ivARB __aglVertexAttrib4ivARB #define glVertexAttrib4sARB __aglVertexAttrib4sARB #define glVertexAttrib4svARB __aglVertexAttrib4svARB #define glVertexAttrib4ubvARB __aglVertexAttrib4ubvARB #define glVertexAttrib4uivARB __aglVertexAttrib4uivARB #define glVertexAttrib4usvARB __aglVertexAttrib4usvARB #define glVertexAttribPointerARB __aglVertexAttribPointerARB #define glEnableVertexAttribArrayARB __aglEnableVertexAttribArrayARB #define glDisableVertexAttribArrayARB __aglDisableVertexAttribArrayARB #define glProgramStringARB __aglProgramStringARB #define glBindProgramARB __aglBindProgramARB #define glDeleteProgramsARB __aglDeleteProgramsARB #define glGenProgramsARB __aglGenProgramsARB #define glProgramEnvParameter4dARB __aglProgramEnvParameter4dARB #define glProgramEnvParameter4dvARB __aglProgramEnvParameter4dvARB #define glProgramEnvParameter4fARB __aglProgramEnvParameter4fARB #define glProgramEnvParameter4fvARB __aglProgramEnvParameter4fvARB #define glProgramLocalParameter4dARB __aglProgramLocalParameter4dARB #define glProgramLocalParameter4dvARB __aglProgramLocalParameter4dvARB #define glProgramLocalParameter4fARB __aglProgramLocalParameter4fARB #define glProgramLocalParameter4fvARB __aglProgramLocalParameter4fvARB #define glGetProgramEnvParameterdvARB __aglGetProgramEnvParameterdvARB #define glGetProgramEnvParameterfvARB __aglGetProgramEnvParameterfvARB #define glGetProgramLocalParameterdvARB __aglGetProgramLocalParameterdvARB #define glGetProgramLocalParameterfvARB __aglGetProgramLocalParameterfvARB #define glGetProgramivARB __aglGetProgramivARB #define glGetProgramStringARB __aglGetProgramStringARB #define glGetVertexAttribdvARB __aglGetVertexAttribdvARB #define glGetVertexAttribfvARB __aglGetVertexAttribfvARB #define glGetVertexAttribivARB __aglGetVertexAttribivARB #define glGetVertexAttribPointervARB __aglGetVertexAttribPointervARB #define glIsProgramARB __aglIsProgramARB #endif #if defined AGL_ARB_vertex_buffer_object #define glBindBufferARB __aglBindBufferARB #define glDeleteBuffersARB __aglDeleteBuffersARB #define glGenBuffersARB __aglGenBuffersARB #define glIsBufferARB __aglIsBufferARB #define glBufferDataARB __aglBufferDataARB #define glBufferSubDataARB __aglBufferSubDataARB #define glGetBufferSubDataARB __aglGetBufferSubDataARB #define glMapBufferARB __aglMapBufferARB #define glUnmapBufferARB __aglUnmapBufferARB #define glGetBufferParameterivARB __aglGetBufferParameterivARB #define glGetBufferPointervARB __aglGetBufferPointervARB #endif #if defined AGL_ARB_occlusion_query #define glGenQueriesARB __aglGenQueriesARB #define glDeleteQueriesARB __aglDeleteQueriesARB #define glIsQueryARB __aglIsQueryARB #define glBeginQueryARB __aglBeginQueryARB #define glEndQueryARB __aglEndQueryARB #define glGetQueryivARB __aglGetQueryivARB #define glGetQueryObjectivARB __aglGetQueryObjectivARB #define glGetQueryObjectuivARB __aglGetQueryObjectuivARB #endif #if defined AGL_ARB_shader_objects #define glDeleteObjectARB __aglDeleteObjectARB #define glGetHandleARB __aglGetHandleARB #define glDetachObjectARB __aglDetachObjectARB #define glCreateShaderObjectARB __aglCreateShaderObjectARB #define glShaderSourceARB __aglShaderSourceARB #define glCompileShaderARB __aglCompileShaderARB #define glCreateProgramObjectARB __aglCreateProgramObjectARB #define glAttachObjectARB __aglAttachObjectARB #define glLinkProgramARB __aglLinkProgramARB #define glUseProgramObjectARB __aglUseProgramObjectARB #define glValidateProgramARB __aglValidateProgramARB #define glUniform1fARB __aglUniform1fARB #define glUniform2fARB __aglUniform2fARB #define glUniform3fARB __aglUniform3fARB #define glUniform4fARB __aglUniform4fARB #define glUniform1iARB __aglUniform1iARB #define glUniform2iARB __aglUniform2iARB #define glUniform3iARB __aglUniform3iARB #define glUniform4iARB __aglUniform4iARB #define glUniform1fvARB __aglUniform1fvARB #define glUniform2fvARB __aglUniform2fvARB #define glUniform3fvARB __aglUniform3fvARB #define glUniform4fvARB __aglUniform4fvARB #define glUniform1ivARB __aglUniform1ivARB #define glUniform2ivARB __aglUniform2ivARB #define glUniform3ivARB __aglUniform3ivARB #define glUniform4ivARB __aglUniform4ivARB #define glUniformMatrix2fvARB __aglUniformMatrix2fvARB #define glUniformMatrix3fvARB __aglUniformMatrix3fvARB #define glUniformMatrix4fvARB __aglUniformMatrix4fvARB #define glGetObjectParameterfvARB __aglGetObjectParameterfvARB #define glGetObjectParameterivARB __aglGetObjectParameterivARB #define glGetInfoLogARB __aglGetInfoLogARB #define glGetAttachedObjectsARB __aglGetAttachedObjectsARB #define glGetUniformLocationARB __aglGetUniformLocationARB #define glGetActiveUniformARB __aglGetActiveUniformARB #define glGetUniformfvARB __aglGetUniformfvARB #define glGetUniformivARB __aglGetUniformivARB #define glGetShaderSourceARB __aglGetShaderSourceARB #endif #ifdef AGL_ARB_vertex_shader #ifndef GL_ARB_vertex_program #define glVertexAttrib1fARB __aglVertexAttrib1fARB #define glVertexAttrib1sARB __aglVertexAttrib1sARB #define glVertexAttrib1dARB __aglVertexAttrib1dARB #define glVertexAttrib2fARB __aglVertexAttrib2fARB #define glVertexAttrib2sARB __aglVertexAttrib2sARB #define glVertexAttrib2dARB __aglVertexAttrib2dARB #define glVertexAttrib3fARB __aglVertexAttrib3fARB #define glVertexAttrib3sARB __aglVertexAttrib3sARB #define glVertexAttrib3dARB __aglVertexAttrib3dARB #define glVertexAttrib4fARB __aglVertexAttrib4fARB #define glVertexAttrib4sARB __aglVertexAttrib4sARB #define glVertexAttrib4dARB __aglVertexAttrib4dARB #define glVertexAttrib4NubARB __aglVertexAttrib4NubARB #define glVertexAttrib1fvARB __aglVertexAttrib1fvARB #define glVertexAttrib1svARB __aglVertexAttrib1svARB #define glVertexAttrib1dvARB __aglVertexAttrib1dvARB #define glVertexAttrib2fvARB __aglVertexAttrib2fvARB #define glVertexAttrib2svARB __aglVertexAttrib2svARB #define glVertexAttrib2dvARB __aglVertexAttrib2dvARB #define glVertexAttrib3fvARB __aglVertexAttrib3fvARB #define glVertexAttrib3svARB __aglVertexAttrib3svARB #define glVertexAttrib3dvARB __aglVertexAttrib3dvARB #define glVertexAttrib4fvARB __aglVertexAttrib4fvARB #define glVertexAttrib4svARB __aglVertexAttrib4svARB #define glVertexAttrib4dvARB __aglVertexAttrib4dvARB #define glVertexAttrib4ivARB __aglVertexAttrib4ivARB #define glVertexAttrib4bvARB __aglVertexAttrib4bvARB #define glVertexAttrib4ubvARB __aglVertexAttrib4ubvARB #define glVertexAttrib4usvARB __aglVertexAttrib4usvARB #define glVertexAttrib4uivARB __aglVertexAttrib4uivARB #define glVertexAttrib4NbvARB __aglVertexAttrib4NbvARB #define glVertexAttrib4NsvARB __aglVertexAttrib4NsvARB #define glVertexAttrib4NivARB __aglVertexAttrib4NivARB #define glVertexAttrib4NubvARB __aglVertexAttrib4NubvARB #define glVertexAttrib4NusvARB __aglVertexAttrib4NusvARB #define glVertexAttrib4NuivARB __aglVertexAttrib4NuivARB #define glVertexAttribPointerARB __aglVertexAttribPointerARB #define glEnableVertexAttribArrayARB __aglEnableVertexAttribArrayARB #define glDisableVertexAttribArrayARB __aglDisableVertexAttribArrayARB #endif #define glBindAttribLocationARB __aglBindAttribLocationARB #define glGetActiveAttribARB __aglGetActiveAttribARB #define glGetAttribLocationARB __aglGetAttribLocationARB #ifndef GL_ARB_vertex_program #define glGetVertexAttribdvARB __aglGetVertexAttribdvARB #define glGetVertexAttribfvARB __aglGetVertexAttribfvARB #define glGetVertexAttribivARB __aglGetVertexAttribivARB #define glGetVertexAttribPointervARB __aglGetVertexAttribPointervARB #endif #endif #if defined AGL_ARB_draw_buffers #define glDrawBuffersARB __aglDrawBuffersARB #endif #if defined AGL_ARB_color_buffer_float #define glClampColorARB __aglClampColorARB #endif #if defined AGL_ARB_draw_instanced #define glDrawArraysInstancedARB __aglDrawArraysInstancedARB #define glDrawElementsInstancedARB __aglDrawElementsInstancedARB #endif #if defined AGL_ARB_framebuffer_object #define glIsRenderbuffer __aglIsRenderbuffer #define glBindRenderbuffer __aglBindRenderbuffer #define glDeleteRenderbuffers __aglDeleteRenderbuffers #define glGenRenderbuffers __aglGenRenderbuffers #define glRenderbufferStorage __aglRenderbufferStorage #define glGetRenderbufferParameteriv __aglGetRenderbufferParameteriv #define glIsFramebuffer __aglIsFramebuffer #define glBindFramebuffer __aglBindFramebuffer #define glDeleteFramebuffers __aglDeleteFramebuffers #define glGenFramebuffers __aglGenFramebuffers #define glCheckFramebufferStatus __aglCheckFramebufferStatus #define glFramebufferTexture1D __aglFramebufferTexture1D #define glFramebufferTexture2D __aglFramebufferTexture2D #define glFramebufferTexture3D __aglFramebufferTexture3D #define glFramebufferRenderbuffer __aglFramebufferRenderbuffer #define glGetFramebufferAttachmentParameteriv __aglGetFramebufferAttachmentParameteriv #define glGenerateMipmap __aglGenerateMipmap #define glBlitFramebuffer __aglBlitFramebuffer #define glRenderbufferStorageMultisample __aglRenderbufferStorageMultisample #define glFramebufferTextureLayer __aglFramebufferTextureLayer #endif #if defined AGL_ARB_geometry_shader4 #define glProgramParameteriARB __aglProgramParameteriARB #define glFramebufferTextureARB __aglFramebufferTextureARB #define glFramebufferTextureLayerARB __aglFramebufferTextureLayerARB #define glFramebufferTextureFaceARB __aglFramebufferTextureFaceARB #endif #if defined AGL_ARB_instanced_arrays #define glVertexAttribDivisor __aglVertexAttribDivisor #endif #if defined AGL_ARB_map_buffer_range #define glMapBufferRange __aglMapBufferRange #define glFlushMappedBufferRange __aglFlushMappedBufferRange #endif #if defined AGL_ARB_texture_buffer_object #define glTexBufferARB __aglTexBufferARB #endif #if defined AGL_ARB_vertex_array_object #define glBindVertexArray __aglBindVertexArray #define glDeleteVertexArrays __aglDeleteVertexArrays #define glGenVertexArrays __aglGenVertexArrays #define glIsVertexArray __aglIsVertexArray #endif /**/ #if defined AGL_EXT_blend_color #define glBlendColorEXT __aglBlendColorEXT #endif #if defined AGL_EXT_polygon_offset #define glPolygonOffsetEXT __aglPolygonOffsetEXT #endif #if defined AGL_EXT_texture3D #define glTexImage3DEXT __aglTexImage3DEXT #define glTexSubImage3DEXT __aglTexSubImage3DEXT #endif #if defined AGL_SGIS_texture_filter4 #define glGetTexFilterFuncSGIS __aglGetTexFilterFuncSGIS #define glTexFilterFuncSGIS __aglTexFilterFuncSGIS #endif #if defined AGL_EXT_subtexture #define glTexSubImage1DEXT __aglTexSubImage1DEXT #define glTexSubImage2DEXT __aglTexSubImage2DEXT #endif #if defined AGL_EXT_copy_texture #define glCopyTexImage1DEXT __aglCopyTexImage1DEXT #define glCopyTexImage2DEXT __aglCopyTexImage2DEXT #define glCopyTexSubImage1DEXT __aglCopyTexSubImage1DEXT #define glCopyTexSubImage2DEXT __aglCopyTexSubImage2DEXT #define glCopyTexSubImage3DEXT __aglCopyTexSubImage3DEXT #endif #if defined AGL_EXT_histogram #define glGetHistogramEXT __aglGetHistogramEXT #define glGetHistogramParameterfvEXT __aglGetHistogramParameterfvEXT #define glGetHistogramParameterivEXT __aglGetHistogramParameterivEXT #define glGetMinmaxEXT __aglGetMinmaxEXT #define glGetMinmaxParameterfvEXT __aglGetMinmaxParameterfvEXT #define glGetMinmaxParameterivEXT __aglGetMinmaxParameterivEXT #define glHistogramEXT __aglHistogramEXT #define glMinmaxEXT __aglMinmaxEXT #define glResetHistogramEXT __aglResetHistogramEXT #define glResetMinmaxEXT __aglResetMinmaxEXT #endif #if defined AGL_EXT_convolution #define glConvolutionFilter1DEXT __aglConvolutionFilter1DEXT #define glConvolutionFilter2DEXT __aglConvolutionFilter2DEXT #define glConvolutionParameterfEXT __aglConvolutionParameterfEXT #define glConvolutionParameterfvEXT __aglConvolutionParameterfvEXT #define glConvolutionParameteriEXT __aglConvolutionParameteriEXT #define glConvolutionParameterivEXT __aglConvolutionParameterivEXT #define glCopyConvolutionFilter1DEXT __aglCopyConvolutionFilter1DEXT #define glCopyConvolutionFilter2DEXT __aglCopyConvolutionFilter2DEXT #define glGetConvolutionFilterEXT __aglGetConvolutionFilterEXT #define glGetConvolutionParameterfvEXT __aglGetConvolutionParameterfvEXT #define glGetConvolutionParameterivEXT __aglGetConvolutionParameterivEXT #define glGetSeparableFilterEXT __aglGetSeparableFilterEXT #define glSeparableFilter2DEXT __aglSeparableFilter2DEXT #endif #if defined AGL_SGI_color_table #define glColorTableSGI __aglColorTableSGI #define glColorTableParameterfvSGI __aglColorTableParameterfvSGI #define glColorTableParameterivSGI __aglColorTableParameterivSGI #define glCopyColorTableSGI __aglCopyColorTableSGI #define glGetColorTableSGI __aglGetColorTableSGI #define glGetColorTableParameterfvSGI __aglGetColorTableParameterfvSGI #define glGetColorTableParameterivSGI __aglGetColorTableParameterivSGI #endif #if defined AGL_SGIX_pixel_texture #define glPixelTexGenSGIX __aglPixelTexGenSGIX #endif #if defined AGL_SGIS_pixel_texture #define glPixelTexGenParameteriSGIS __aglPixelTexGenParameteriSGIS #define glPixelTexGenParameterivSGIS __aglPixelTexGenParameterivSGIS #define glPixelTexGenParameterfSGIS __aglPixelTexGenParameterfSGIS #define glPixelTexGenParameterfvSGIS __aglPixelTexGenParameterfvSGIS #define glGetPixelTexGenParameterivSGIS __aglGetPixelTexGenParameterivSGIS #define glGetPixelTexGenParameterfvSGIS __aglGetPixelTexGenParameterfvSGIS #endif #if defined AGL_SGIS_texture4D #define glTexImage4DSGIS __aglTexImage4DSGIS #define glTexSubImage4DSGIS __aglTexSubImage4DSGIS #endif #if defined AGL_EXT_texture_object #define glAreTexturesResidentEXT __aglAreTexturesResidentEXT #define glBindTextureEXT __aglBindTextureEXT #define glDeleteTexturesEXT __aglDeleteTexturesEXT #define glGenTexturesEXT __aglGenTexturesEXT #define glIsTextureEXT __aglIsTextureEXT #define glPrioritizeTexturesEXT __aglPrioritizeTexturesEXT #endif #if defined AGL_SGIS_detail_texture #define glDetailTexFuncSGIS __aglDetailTexFuncSGIS #define glGetDetailTexFuncSGIS __aglGetDetailTexFuncSGIS #endif #if defined AGL_SGIS_sharpen_texture #define glSharpenTexFuncSGIS __aglSharpenTexFuncSGIS #define glGetSharpenTexFuncSGIS __aglGetSharpenTexFuncSGIS #endif #if defined AGL_SGIS_multisample #define glSampleMaskSGIS __aglSampleMaskSGIS #define glSamplePatternSGIS __aglSamplePatternSGIS #endif #if defined AGL_EXT_vertex_array #define glArrayElementEXT __aglArrayElementEXT #define glColorPointerEXT __aglColorPointerEXT #define glDrawArraysEXT __aglDrawArraysEXT #define glEdgeFlagPointerEXT __aglEdgeFlagPointerEXT #define glGetPointervEXT __aglGetPointervEXT #define glIndexPointerEXT __aglIndexPointerEXT #define glNormalPointerEXT __aglNormalPointerEXT #define glTexCoordPointerEXT __aglTexCoordPointerEXT #define glVertexPointerEXT __aglVertexPointerEXT #endif #if defined AGL_EXT_blend_minmax #define glBlendEquationEXT __aglBlendEquationEXT #endif #if defined AGL_SGIX_sprite #define glSpriteParameterfSGIX __aglSpriteParameterfSGIX #define glSpriteParameterfvSGIX __aglSpriteParameterfvSGIX #define glSpriteParameteriSGIX __aglSpriteParameteriSGIX #define glSpriteParameterivSGIX __aglSpriteParameterivSGIX #endif #if defined AGL_EXT_point_parameters #define glPointParameterfEXT __aglPointParameterfEXT #define glPointParameterfvEXT __aglPointParameterfvEXT #endif #if defined AGL_SGIS_point_parameters #define glPointParameterfSGIS __aglPointParameterfSGIS #define glPointParameterfvSGIS __aglPointParameterfvSGIS #endif #if defined AGL_SGIX_instruments #define glGetInstrumentsSGIX __aglGetInstrumentsSGIX #define glInstrumentsBufferSGIX __aglInstrumentsBufferSGIX #define glPollInstrumentsSGIX __aglPollInstrumentsSGIX #define glReadInstrumentsSGIX __aglReadInstrumentsSGIX #define glStartInstrumentsSGIX __aglStartInstrumentsSGIX #define glStopInstrumentsSGIX __aglStopInstrumentsSGIX #endif #if defined AGL_SGIX_framezoom #define glFrameZoomSGIX __aglFrameZoomSGIX #endif #if defined AGL_SGIX_tag_sample_buffer #define glTagSampleBufferSGIX __aglTagSampleBufferSGIX #endif #if defined AGL_SGIX_polynomial_ffd #define glDeformationMap3dSGIX __aglDeformationMap3dSGIX #define glDeformationMap3fSGIX __aglDeformationMap3fSGIX #define glDeformSGIX __aglDeformSGIX #define glLoadIdentityDeformationMapSGIX __aglLoadIdentityDeformationMapSGIX #endif #if defined AGL_SGIX_reference_plane #define glReferencePlaneSGIX __aglReferencePlaneSGIX #endif #if defined AGL_SGIX_flush_raster #define glFlushRasterSGIX __aglFlushRasterSGIX #endif #if defined AGL_SGIS_fog_function #define glFogFuncSGIS __aglFogFuncSGIS #define glGetFogFuncSGIS __aglGetFogFuncSGIS #endif #if defined AGL_HP_image_transform #define glImageTransformParameteriHP __aglImageTransformParameteriHP #define glImageTransformParameterfHP __aglImageTransformParameterfHP #define glImageTransformParameterivHP __aglImageTransformParameterivHP #define glImageTransformParameterfvHP __aglImageTransformParameterfvHP #define glGetImageTransformParameterivHP __aglGetImageTransformParameterivHP #define glGetImageTransformParameterfvHP __aglGetImageTransformParameterfvHP #endif #if defined AGL_EXT_color_subtable #ifndef GL_EXT_paletted_texture #define glColorSubTableEXT __aglColorSubTableEXT #endif #define glCopyColorSubTableEXT __aglCopyColorSubTableEXT #endif #if defined AGL_PGI_misc_hints #define glHintPGI __aglHintPGI #endif #if defined AGL_EXT_paletted_texture #define glColorTableEXT __aglColorTableEXT #define glGetColorTableEXT __aglGetColorTableEXT #define glGetColorTableParameterivEXT __aglGetColorTableParameterivEXT #define glGetColorTableParameterfvEXT __aglGetColorTableParameterfvEXT #endif #if defined AGL_SGIX_list_priority #define glGetListParameterfvSGIX __aglGetListParameterfvSGIX #define glGetListParameterivSGIX __aglGetListParameterivSGIX #define glListParameterfSGIX __aglListParameterfSGIX #define glListParameterfvSGIX __aglListParameterfvSGIX #define glListParameteriSGIX __aglListParameteriSGIX #define glListParameterivSGIX __aglListParameterivSGIX #endif #if defined AGL_EXT_index_material #define glIndexMaterialEXT __aglIndexMaterialEXT #endif #if defined AGL_EXT_index_func #define glIndexFuncEXT __aglIndexFuncEXT #endif #if defined AGL_EXT_compiled_vertex_array #define glLockArraysEXT __aglLockArraysEXT #define glUnlockArraysEXT __aglUnlockArraysEXT #endif #if defined AGL_EXT_cull_vertex #define glCullParameterdvEXT __aglCullParameterdvEXT #define glCullParameterfvEXT __aglCullParameterfvEXT #endif #if defined AGL_SGIX_fragment_lighting #define glFragmentColorMaterialSGIX __aglFragmentColorMaterialSGIX #define glFragmentLightfSGIX __aglFragmentLightfSGIX #define glFragmentLightfvSGIX __aglFragmentLightfvSGIX #define glFragmentLightiSGIX __aglFragmentLightiSGIX #define glFragmentLightivSGIX __aglFragmentLightivSGIX #define glFragmentLightModelfSGIX __aglFragmentLightModelfSGIX #define glFragmentLightModelfvSGIX __aglFragmentLightModelfvSGIX #define glFragmentLightModeliSGIX __aglFragmentLightModeliSGIX #define glFragmentLightModelivSGIX __aglFragmentLightModelivSGIX #define glFragmentMaterialfSGIX __aglFragmentMaterialfSGIX #define glFragmentMaterialfvSGIX __aglFragmentMaterialfvSGIX #define glFragmentMaterialiSGIX __aglFragmentMaterialiSGIX #define glFragmentMaterialivSGIX __aglFragmentMaterialivSGIX #define glGetFragmentLightfvSGIX __aglGetFragmentLightfvSGIX #define glGetFragmentLightivSGIX __aglGetFragmentLightivSGIX #define glGetFragmentMaterialfvSGIX __aglGetFragmentMaterialfvSGIX #define glGetFragmentMaterialivSGIX __aglGetFragmentMaterialivSGIX #define glLightEnviSGIX __aglLightEnviSGIX #endif #if defined AGL_EXT_draw_range_elements #define glDrawRangeElementsEXT __aglDrawRangeElementsEXT #endif #if defined AGL_EXT_light_texture #define glApplyTextureEXT __aglApplyTextureEXT #define glTextureLightEXT __aglTextureLightEXT #define glTextureMaterialEXT __aglTextureMaterialEXT #endif #if defined AGL_SGIX_async #define glAsyncMarkerSGIX __aglAsyncMarkerSGIX #define glFinishAsyncSGIX __aglFinishAsyncSGIX #define glPollAsyncSGIX __aglPollAsyncSGIX #define glGenAsyncMarkersSGIX __aglGenAsyncMarkersSGIX #define glDeleteAsyncMarkersSGIX __aglDeleteAsyncMarkersSGIX #define glIsAsyncMarkerSGIX __aglIsAsyncMarkerSGIX #endif #if defined AGL_INTEL_parallel_arrays #define glVertexPointervINTEL __aglVertexPointervINTEL #define glNormalPointervINTEL __aglNormalPointervINTEL #define glColorPointervINTEL __aglColorPointervINTEL #define glTexCoordPointervINTEL __aglTexCoordPointervINTEL #endif #if defined AGL_EXT_pixel_transform #define glPixelTransformParameteriEXT __aglPixelTransformParameteriEXT #define glPixelTransformParameterfEXT __aglPixelTransformParameterfEXT #define glPixelTransformParameterivEXT __aglPixelTransformParameterivEXT #define glPixelTransformParameterfvEXT __aglPixelTransformParameterfvEXT #endif #if defined AGL_EXT_secondary_color #define glSecondaryColor3bEXT __aglSecondaryColor3bEXT #define glSecondaryColor3bvEXT __aglSecondaryColor3bvEXT #define glSecondaryColor3dEXT __aglSecondaryColor3dEXT #define glSecondaryColor3dvEXT __aglSecondaryColor3dvEXT #define glSecondaryColor3fEXT __aglSecondaryColor3fEXT #define glSecondaryColor3fvEXT __aglSecondaryColor3fvEXT #define glSecondaryColor3iEXT __aglSecondaryColor3iEXT #define glSecondaryColor3ivEXT __aglSecondaryColor3ivEXT #define glSecondaryColor3sEXT __aglSecondaryColor3sEXT #define glSecondaryColor3svEXT __aglSecondaryColor3svEXT #define glSecondaryColor3ubEXT __aglSecondaryColor3ubEXT #define glSecondaryColor3ubvEXT __aglSecondaryColor3ubvEXT #define glSecondaryColor3uiEXT __aglSecondaryColor3uiEXT #define glSecondaryColor3uivEXT __aglSecondaryColor3uivEXT #define glSecondaryColor3usEXT __aglSecondaryColor3usEXT #define glSecondaryColor3usvEXT __aglSecondaryColor3usvEXT #define glSecondaryColorPointerEXT __aglSecondaryColorPointerEXT #endif #if defined AGL_EXT_texture_perturb_normal #define glTextureNormalEXT __aglTextureNormalEXT #endif #if defined AGL_EXT_multi_draw_arrays #define glMultiDrawArraysEXT __aglMultiDrawArraysEXT #define glMultiDrawElementsEXT __aglMultiDrawElementsEXT #endif #if defined AGL_EXT_fog_coord #define glFogCoordfEXT __aglFogCoordfEXT #define glFogCoordfvEXT __aglFogCoordfvEXT #define glFogCoorddEXT __aglFogCoorddEXT #define glFogCoorddvEXT __aglFogCoorddvEXT #define glFogCoordPointerEXT __aglFogCoordPointerEXT #endif #if defined AGL_EXT_coordinate_frame #define glTangent3bEXT __aglTangent3bEXT #define glTangent3bvEXT __aglTangent3bvEXT #define glTangent3dEXT __aglTangent3dEXT #define glTangent3dvEXT __aglTangent3dvEXT #define glTangent3fEXT __aglTangent3fEXT #define glTangent3fvEXT __aglTangent3fvEXT #define glTangent3iEXT __aglTangent3iEXT #define glTangent3ivEXT __aglTangent3ivEXT #define glTangent3sEXT __aglTangent3sEXT #define glTangent3svEXT __aglTangent3svEXT #define glBinormal3bEXT __aglBinormal3bEXT #define glBinormal3bvEXT __aglBinormal3bvEXT #define glBinormal3dEXT __aglBinormal3dEXT #define glBinormal3dvEXT __aglBinormal3dvEXT #define glBinormal3fEXT __aglBinormal3fEXT #define glBinormal3fvEXT __aglBinormal3fvEXT #define glBinormal3iEXT __aglBinormal3iEXT #define glBinormal3ivEXT __aglBinormal3ivEXT #define glBinormal3sEXT __aglBinormal3sEXT #define glBinormal3svEXT __aglBinormal3svEXT #define glTangentPointerEXT __aglTangentPointerEXT #define glBinormalPointerEXT __aglBinormalPointerEXT #endif #if defined AGL_SUNX_constant_data #define glFinishTextureSUNX __aglFinishTextureSUNX #endif #if defined AGL_SUN_global_alpha #define glGlobalAlphaFactorbSUN __aglGlobalAlphaFactorbSUN #define glGlobalAlphaFactorsSUN __aglGlobalAlphaFactorsSUN #define glGlobalAlphaFactoriSUN __aglGlobalAlphaFactoriSUN #define glGlobalAlphaFactorfSUN __aglGlobalAlphaFactorfSUN #define glGlobalAlphaFactordSUN __aglGlobalAlphaFactordSUN #define glGlobalAlphaFactorubSUN __aglGlobalAlphaFactorubSUN #define glGlobalAlphaFactorusSUN __aglGlobalAlphaFactorusSUN #define glGlobalAlphaFactoruiSUN __aglGlobalAlphaFactoruiSUN #endif #if defined AGL_SUN_triangle_list #define glReplacementCodeuiSUN __aglReplacementCodeuiSUN #define glReplacementCodeusSUN __aglReplacementCodeusSUN #define glReplacementCodeubSUN __aglReplacementCodeubSUN #define glReplacementCodeuivSUN __aglReplacementCodeuivSUN #define glReplacementCodeusvSUN __aglReplacementCodeusvSUN #define glReplacementCodeubvSUN __aglReplacementCodeubvSUN #define glReplacementCodePointerSUN __aglReplacementCodePointerSUN #endif #if defined AGL_SUN_vertex #define glColor4ubVertex2fSUN __aglColor4ubVertex2fSUN #define glColor4ubVertex2fvSUN __aglColor4ubVertex2fvSUN #define glColor4ubVertex3fSUN __aglColor4ubVertex3fSUN #define glColor4ubVertex3fvSUN __aglColor4ubVertex3fvSUN #define glColor3fVertex3fSUN __aglColor3fVertex3fSUN #define glColor3fVertex3fvSUN __aglColor3fVertex3fvSUN #define glNormal3fVertex3fSUN __aglNormal3fVertex3fSUN #define glNormal3fVertex3fvSUN __aglNormal3fVertex3fvSUN #define glColor4fNormal3fVertex3fSUN __aglColor4fNormal3fVertex3fSUN #define glColor4fNormal3fVertex3fvSUN __aglColor4fNormal3fVertex3fvSUN #define glTexCoord2fVertex3fSUN __aglTexCoord2fVertex3fSUN #define glTexCoord2fVertex3fvSUN __aglTexCoord2fVertex3fvSUN #define glTexCoord4fVertex4fSUN __aglTexCoord4fVertex4fSUN #define glTexCoord4fVertex4fvSUN __aglTexCoord4fVertex4fvSUN #define glTexCoord2fColor4ubVertex3fSUN __aglTexCoord2fColor4ubVertex3fSUN #define glTexCoord2fColor4ubVertex3fvSUN __aglTexCoord2fColor4ubVertex3fvSUN #define glTexCoord2fColor3fVertex3fSUN __aglTexCoord2fColor3fVertex3fSUN #define glTexCoord2fColor3fVertex3fvSUN __aglTexCoord2fColor3fVertex3fvSUN #define glTexCoord2fNormal3fVertex3fSUN __aglTexCoord2fNormal3fVertex3fSUN #define glTexCoord2fNormal3fVertex3fvSUN __aglTexCoord2fNormal3fVertex3fvSUN #define glTexCoord2fColor4fNormal3fVertex3fSUN __aglTexCoord2fColor4fNormal3fVertex3fSUN #define glTexCoord2fColor4fNormal3fVertex3fvSUN __aglTexCoord2fColor4fNormal3fVertex3fvSUN #define glTexCoord4fColor4fNormal3fVertex4fSUN __aglTexCoord4fColor4fNormal3fVertex4fSUN #define glTexCoord4fColor4fNormal3fVertex4fvSUN __aglTexCoord4fColor4fNormal3fVertex4fvSUN #define glReplacementCodeuiVertex3fSUN __aglReplacementCodeuiVertex3fSUN #define glReplacementCodeuiVertex3fvSUN __aglReplacementCodeuiVertex3fvSUN #define glReplacementCodeuiColor4ubVertex3fSUN __aglReplacementCodeuiColor4ubVertex3fSUN #define glReplacementCodeuiColor4ubVertex3fvSUN __aglReplacementCodeuiColor4ubVertex3fvSUN #define glReplacementCodeuiColor3fVertex3fSUN __aglReplacementCodeuiColor3fVertex3fSUN #define glReplacementCodeuiColor3fVertex3fvSUN __aglReplacementCodeuiColor3fVertex3fvSUN #define glReplacementCodeuiNormal3fVertex3fSUN __aglReplacementCodeuiNormal3fVertex3fSUN #define glReplacementCodeuiNormal3fVertex3fvSUN __aglReplacementCodeuiNormal3fVertex3fvSUN #define glReplacementCodeuiColor4fNormal3fVertex3fSUN __aglReplacementCodeuiColor4fNormal3fVertex3fSUN #define glReplacementCodeuiColor4fNormal3fVertex3fvSUN __aglReplacementCodeuiColor4fNormal3fVertex3fvSUN #define glReplacementCodeuiTexCoord2fVertex3fSUN __aglReplacementCodeuiTexCoord2fVertex3fSUN #define glReplacementCodeuiTexCoord2fVertex3fvSUN __aglReplacementCodeuiTexCoord2fVertex3fvSUN #define glReplacementCodeuiTexCoord2fNormal3fVertex3fSUN __aglReplacementCodeuiTexCoord2fNormal3fVertex3fSUN #define glReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN __aglReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN #define glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN __aglReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN #define glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN __aglReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN #endif #if defined AGL_EXT_blend_func_separate #define glBlendFuncSeparateEXT __aglBlendFuncSeparateEXT #endif #if defined AGL_INGR_blend_func_separate #define glBlendFuncSeparateINGR __aglBlendFuncSeparateINGR #endif #if defined AGL_EXT_vertex_weighting #define glVertexWeightfEXT __aglVertexWeightfEXT #define glVertexWeightfvEXT __aglVertexWeightfvEXT #define glVertexWeightPointerEXT __aglVertexWeightPointerEXT #endif #if defined AGL_NV_vertex_array_range #define glFlushVertexArrayRangeNV __aglFlushVertexArrayRangeNV #define glVertexArrayRangeNV __aglVertexArrayRangeNV #endif #if defined AGL_NV_register_combiners #define glCombinerParameterfvNV __aglCombinerParameterfvNV #define glCombinerParameterfNV __aglCombinerParameterfNV #define glCombinerParameterivNV __aglCombinerParameterivNV #define glCombinerParameteriNV __aglCombinerParameteriNV #define glCombinerInputNV __aglCombinerInputNV #define glCombinerOutputNV __aglCombinerOutputNV #define glFinalCombinerInputNV __aglFinalCombinerInputNV #define glGetCombinerInputParameterfvNV __aglGetCombinerInputParameterfvNV #define glGetCombinerInputParameterivNV __aglGetCombinerInputParameterivNV #define glGetCombinerOutputParameterfvNV __aglGetCombinerOutputParameterfvNV #define glGetCombinerOutputParameterivNV __aglGetCombinerOutputParameterivNV #define glGetFinalCombinerInputParameterfvNV __aglGetFinalCombinerInputParameterfvNV #define glGetFinalCombinerInputParameterivNV __aglGetFinalCombinerInputParameterivNV #endif #if defined AGL_MESA_resize_buffers #define glResizeBuffersMESA __aglResizeBuffersMESA #endif #if defined AGL_MESA_window_pos #define glWindowPos2dMESA __aglWindowPos2dMESA #define glWindowPos2dvMESA __aglWindowPos2dvMESA #define glWindowPos2fMESA __aglWindowPos2fMESA #define glWindowPos2fvMESA __aglWindowPos2fvMESA #define glWindowPos2iMESA __aglWindowPos2iMESA #define glWindowPos2ivMESA __aglWindowPos2ivMESA #define glWindowPos2sMESA __aglWindowPos2sMESA #define glWindowPos2svMESA __aglWindowPos2svMESA #define glWindowPos3dMESA __aglWindowPos3dMESA #define glWindowPos3dvMESA __aglWindowPos3dvMESA #define glWindowPos3fMESA __aglWindowPos3fMESA #define glWindowPos3fvMESA __aglWindowPos3fvMESA #define glWindowPos3iMESA __aglWindowPos3iMESA #define glWindowPos3ivMESA __aglWindowPos3ivMESA #define glWindowPos3sMESA __aglWindowPos3sMESA #define glWindowPos3svMESA __aglWindowPos3svMESA #define glWindowPos4dMESA __aglWindowPos4dMESA #define glWindowPos4dvMESA __aglWindowPos4dvMESA #define glWindowPos4fMESA __aglWindowPos4fMESA #define glWindowPos4fvMESA __aglWindowPos4fvMESA #define glWindowPos4iMESA __aglWindowPos4iMESA #define glWindowPos4ivMESA __aglWindowPos4ivMESA #define glWindowPos4sMESA __aglWindowPos4sMESA #define glWindowPos4svMESA __aglWindowPos4svMESA #endif #if defined AGL_IBM_multimode_draw_arrays #define glMultiModeDrawArraysIBM __aglMultiModeDrawArraysIBM #define glMultiModeDrawElementsIBM __aglMultiModeDrawElementsIBM #endif #ifdef AGK_IBM_vertex_array_lists #define glColorPointerListIBM __aglColorPointerListIBM #define glSecondaryColorPointerListIBM __aglSecondaryColorPointerListIBM #define glEdgeFlagPointerListIBM __aglEdgeFlagPointerListIBM #define glFogCoordPointerListIBM __aglFogCoordPointerListIBM #define glIndexPointerListIBM __aglIndexPointerListIBM #define glNormalPointerListIBM __aglNormalPointerListIBM #define glTexCoordPointerListIBM __aglTexCoordPointerListIBM #define glVertexPointerListIBM __aglVertexPointerListIBM #endif #if defined AGL_3DFX_tbuffer #define glTbufferMask3DFX __aglTbufferMask3DFX #endif #if defined AGL_EXT_multisample #define glSampleMaskEXT __aglSampleMaskEXT #define glSamplePatternEXT __aglSamplePatternEXT #endif #if defined AGL_SGIS_texture_color_mask #define glTextureColorMaskSGIS __aglTextureColorMaskSGIS #endif #if defined AGL_SGIX_igloo_interface #define glIglooInterfaceSGIX __aglIglooInterfaceSGIX #endif #if defined AGL_NV_fence #define glDeleteFencesNV __aglDeleteFencesNV #define glGenFencesNV __aglGenFencesNV #define glIsFenceNV __aglIsFenceNV #define glTestFenceNV __aglTestFenceNV #define glGetFenceivNV __aglGetFenceivNV #define glFinishFenceNV __aglFinishFenceNV #define glSetFenceNV __aglSetFenceNV #endif #if defined AGL_NV_evaluators #define glMapControlPointsNV __aglMapControlPointsNV #define glMapParameterivNV __aglMapParameterivNV #define glMapParameterfvNV __aglMapParameterfvNV #define glGetMapControlPointsNV __aglGetMapControlPointsNV #define glGetMapParameterivNV __aglGetMapParameterivNV #define glGetMapParameterfvNV __aglGetMapParameterfvNV #define glGetMapAttribParameterivNV __aglGetMapAttribParameterivNV #define glGetMapAttribParameterfvNV __aglGetMapAttribParameterfvNV #define glEvalMapsNV __aglEvalMapsNV #endif #if defined AGL_NV_register_combiners2 #define glCombinerStageParameterfvNV __aglCombinerStageParameterfvNV #define glGetCombinerStageParameterfvNV __aglGetCombinerStageParameterfvNV #endif #if defined AGL_NV_vertex_program #define glAreProgramsResidentNV __aglAreProgramsResidentNV #define glBindProgramNV __aglBindProgramNV #define glDeleteProgramsNV __aglDeleteProgramsNV #define glExecuteProgramNV __aglExecuteProgramNV #define glGenProgramsNV __aglGenProgramsNV #define glGetProgramParameterdvNV __aglGetProgramParameterdvNV #define glGetProgramParameterfvNV __aglGetProgramParameterfvNV #define glGetProgramivNV __aglGetProgramivNV #define glGetProgramStringNV __aglGetProgramStringNV #define glGetTrackMatrixivNV __aglGetTrackMatrixivNV #define glGetVertexAttribdvNV __aglGetVertexAttribdvNV #define glGetVertexAttribfvNV __aglGetVertexAttribfvNV #define glGetVertexAttribivNV __aglGetVertexAttribivNV #define glGetVertexAttribPointervNV __aglGetVertexAttribPointervNV #define glIsProgramNV __aglIsProgramNV #define glLoadProgramNV __aglLoadProgramNV #define glProgramParameter4dNV __aglProgramParameter4dNV #define glProgramParameter4dvNV __aglProgramParameter4dvNV #define glProgramParameter4fNV __aglProgramParameter4fNV #define glProgramParameter4fvNV __aglProgramParameter4fvNV #define glProgramParameters4dvNV __aglProgramParameters4dvNV #define glProgramParameters4fvNV __aglProgramParameters4fvNV #define glRequestResidentProgramsNV __aglRequestResidentProgramsNV #define glTrackMatrixNV __aglTrackMatrixNV #define glVertexAttribPointerNV __aglVertexAttribPointerNV #define glVertexAttrib1dNV __aglVertexAttrib1dNV #define glVertexAttrib1dvNV __aglVertexAttrib1dvNV #define glVertexAttrib1fNV __aglVertexAttrib1fNV #define glVertexAttrib1fvNV __aglVertexAttrib1fvNV #define glVertexAttrib1sNV __aglVertexAttrib1sNV #define glVertexAttrib1svNV __aglVertexAttrib1svNV #define glVertexAttrib2dNV __aglVertexAttrib2dNV #define glVertexAttrib2dvNV __aglVertexAttrib2dvNV #define glVertexAttrib2fNV __aglVertexAttrib2fNV #define glVertexAttrib2fvNV __aglVertexAttrib2fvNV #define glVertexAttrib2sNV __aglVertexAttrib2sNV #define glVertexAttrib2svNV __aglVertexAttrib2svNV #define glVertexAttrib3dNV __aglVertexAttrib3dNV #define glVertexAttrib3dvNV __aglVertexAttrib3dvNV #define glVertexAttrib3fNV __aglVertexAttrib3fNV #define glVertexAttrib3fvNV __aglVertexAttrib3fvNV #define glVertexAttrib3sNV __aglVertexAttrib3sNV #define glVertexAttrib3svNV __aglVertexAttrib3svNV #define glVertexAttrib4dNV __aglVertexAttrib4dNV #define glVertexAttrib4dvNV __aglVertexAttrib4dvNV #define glVertexAttrib4fNV __aglVertexAttrib4fNV #define glVertexAttrib4fvNV __aglVertexAttrib4fvNV #define glVertexAttrib4sNV __aglVertexAttrib4sNV #define glVertexAttrib4svNV __aglVertexAttrib4svNV #define glVertexAttrib4ubNV __aglVertexAttrib4ubNV #define glVertexAttrib4ubvNV __aglVertexAttrib4ubvNV #define glVertexAttribs1dvNV __aglVertexAttribs1dvNV #define glVertexAttribs1fvNV __aglVertexAttribs1fvNV #define glVertexAttribs1svNV __aglVertexAttribs1svNV #define glVertexAttribs2dvNV __aglVertexAttribs2dvNV #define glVertexAttribs2fvNV __aglVertexAttribs2fvNV #define glVertexAttribs2svNV __aglVertexAttribs2svNV #define glVertexAttribs3dvNV __aglVertexAttribs3dvNV #define glVertexAttribs3fvNV __aglVertexAttribs3fvNV #define glVertexAttribs3svNV __aglVertexAttribs3svNV #define glVertexAttribs4dvNV __aglVertexAttribs4dvNV #define glVertexAttribs4fvNV __aglVertexAttribs4fvNV #define glVertexAttribs4svNV __aglVertexAttribs4svNV #define glVertexAttribs4ubvNV __aglVertexAttribs4ubvNV #endif #if defined AGL_ATI_envmap_bumpmap #define glTexBumpParameterivATI __aglTexBumpParameterivATI #define glTexBumpParameterfvATI __aglTexBumpParameterfvATI #define glGetTexBumpParameterivATI __aglGetTexBumpParameterivATI #define glGetTexBumpParameterfvATI __aglGetTexBumpParameterfvATI #endif #if defined AGL_ATI_fragment_shader #define glGenFragmentShadersATI __aglGenFragmentShadersATI #define glBindFragmentShaderATI __aglBindFragmentShaderATI #define glDeleteFragmentShaderATI __aglDeleteFragmentShaderATI #define glBeginFragmentShaderATI __aglBeginFragmentShaderATI #define glEndFragmentShaderATI __aglEndFragmentShaderATI #define glPassTexCoordATI __aglPassTexCoordATI #define glSampleMapATI __aglSampleMapATI #define glColorFragmentOp1ATI __aglColorFragmentOp1ATI #define glColorFragmentOp2ATI __aglColorFragmentOp2ATI #define glColorFragmentOp3ATI __aglColorFragmentOp3ATI #define glAlphaFragmentOp1ATI __aglAlphaFragmentOp1ATI #define glAlphaFragmentOp2ATI __aglAlphaFragmentOp2ATI #define glAlphaFragmentOp3ATI __aglAlphaFragmentOp3ATI #define glSetFragmentShaderConstantATI __aglSetFragmentShaderConstantATI #endif #if defined AGL_ATI_pn_triangles #define glPNTrianglesiATI __aglPNTrianglesiATI #define glPNTrianglesfATI __aglPNTrianglesfATI #endif #if defined AGL_ATI_vertex_array_object #define glNewObjectBufferATI __aglNewObjectBufferATI #define glIsObjectBufferATI __aglIsObjectBufferATI #define glUpdateObjectBufferATI __aglUpdateObjectBufferATI #define glGetObjectBufferfvATI __aglGetObjectBufferfvATI #define glGetObjectBufferivATI __aglGetObjectBufferivATI #define glFreeObjectBufferATI __aglFreeObjectBufferATI #define glArrayObjectATI __aglArrayObjectATI #define glGetArrayObjectfvATI __aglGetArrayObjectfvATI #define glGetArrayObjectivATI __aglGetArrayObjectivATI #define glVariantArrayObjectATI __aglVariantArrayObjectATI #define glGetVariantArrayObjectfvATI __aglGetVariantArrayObjectfvATI #define glGetVariantArrayObjectivATI __aglGetVariantArrayObjectivATI #endif #if defined AGL_EXT_vertex_shader #define glBeginVertexShaderEXT __aglBeginVertexShaderEXT #define glEndVertexShaderEXT __aglEndVertexShaderEXT #define glBindVertexShaderEXT __aglBindVertexShaderEXT #define glGenVertexShadersEXT __aglGenVertexShadersEXT #define glDeleteVertexShaderEXT __aglDeleteVertexShaderEXT #define glShaderOp1EXT __aglShaderOp1EXT #define glShaderOp2EXT __aglShaderOp2EXT #define glShaderOp3EXT __aglShaderOp3EXT #define glSwizzleEXT __aglSwizzleEXT #define glWriteMaskEXT __aglWriteMaskEXT #define glInsertComponentEXT __aglInsertComponentEXT #define glExtractComponentEXT __aglExtractComponentEXT #define glGenSymbolsEXT __aglGenSymbolsEXT #define glSetInvariantEXT __aglSetInvariantEXT #define glSetLocalConstantEXT __aglSetLocalConstantEXT #define glVariantbvEXT __aglVariantbvEXT #define glVariantsvEXT __aglVariantsvEXT #define glVariantivEXT __aglVariantivEXT #define glVariantfvEXT __aglVariantfvEXT #define glVariantdvEXT __aglVariantdvEXT #define glVariantubvEXT __aglVariantubvEXT #define glVariantusvEXT __aglVariantusvEXT #define glVariantuivEXT __aglVariantuivEXT #define glVariantPointerEXT __aglVariantPointerEXT #define glEnableVariantClientStateEXT __aglEnableVariantClientStateEXT #define glDisableVariantClientStateEXT __aglDisableVariantClientStateEXT #define glBindLightParameterEXT __aglBindLightParameterEXT #define glBindMaterialParameterEXT __aglBindMaterialParameterEXT #define glBindTexGenParameterEXT __aglBindTexGenParameterEXT #define glBindTextureUnitParameterEXT __aglBindTextureUnitParameterEXT #define glBindParameterEXT __aglBindParameterEXT #define glIsVariantEnabledEXT __aglIsVariantEnabledEXT #define glGetVariantBooleanvEXT __aglGetVariantBooleanvEXT #define glGetVariantIntegervEXT __aglGetVariantIntegervEXT #define glGetVariantFloatvEXT __aglGetVariantFloatvEXT #define glGetVariantPointervEXT __aglGetVariantPointervEXT #define glGetInvariantBooleanvEXT __aglGetInvariantBooleanvEXT #define glGetInvariantIntegervEXT __aglGetInvariantIntegervEXT #define glGetInvariantFloatvEXT __aglGetInvariantFloatvEXT #define glGetLocalConstantBooleanvEXT __aglGetLocalConstantBooleanvEXT #define glGetLocalConstantIntegervEXT __aglGetLocalConstantIntegervEXT #define glGetLocalConstantFloatvEXT __aglGetLocalConstantFloatvEXT #endif #if defined AGL_ATI_vertex_streams #define glVertexStream1sATI __aglVertexStream1sATI #define glVertexStream1svATI __aglVertexStream1svATI #define glVertexStream1iATI __aglVertexStream1iATI #define glVertexStream1ivATI __aglVertexStream1ivATI #define glVertexStream1fATI __aglVertexStream1fATI #define glVertexStream1fvATI __aglVertexStream1fvATI #define glVertexStream1dATI __aglVertexStream1dATI #define glVertexStream1dvATI __aglVertexStream1dvATI #define glVertexStream2sATI __aglVertexStream2sATI #define glVertexStream2svATI __aglVertexStream2svATI #define glVertexStream2iATI __aglVertexStream2iATI #define glVertexStream2ivATI __aglVertexStream2ivATI #define glVertexStream2fATI __aglVertexStream2fATI #define glVertexStream2fvATI __aglVertexStream2fvATI #define glVertexStream2dATI __aglVertexStream2dATI #define glVertexStream2dvATI __aglVertexStream2dvATI #define glVertexStream3sATI __aglVertexStream3sATI #define glVertexStream3svATI __aglVertexStream3svATI #define glVertexStream3iATI __aglVertexStream3iATI #define glVertexStream3ivATI __aglVertexStream3ivATI #define glVertexStream3fATI __aglVertexStream3fATI #define glVertexStream3fvATI __aglVertexStream3fvATI #define glVertexStream3dATI __aglVertexStream3dATI #define glVertexStream3dvATI __aglVertexStream3dvATI #define glVertexStream4sATI __aglVertexStream4sATI #define glVertexStream4svATI __aglVertexStream4svATI #define glVertexStream4iATI __aglVertexStream4iATI #define glVertexStream4ivATI __aglVertexStream4ivATI #define glVertexStream4fATI __aglVertexStream4fATI #define glVertexStream4fvATI __aglVertexStream4fvATI #define glVertexStream4dATI __aglVertexStream4dATI #define glVertexStream4dvATI __aglVertexStream4dvATI #define glNormalStream3bATI __aglNormalStream3bATI #define glNormalStream3bvATI __aglNormalStream3bvATI #define glNormalStream3sATI __aglNormalStream3sATI #define glNormalStream3svATI __aglNormalStream3svATI #define glNormalStream3iATI __aglNormalStream3iATI #define glNormalStream3ivATI __aglNormalStream3ivATI #define glNormalStream3fATI __aglNormalStream3fATI #define glNormalStream3fvATI __aglNormalStream3fvATI #define glNormalStream3dATI __aglNormalStream3dATI #define glNormalStream3dvATI __aglNormalStream3dvATI #define glClientActiveVertexStreamATI __aglClientActiveVertexStreamATI #define glVertexBlendEnviATI __aglVertexBlendEnviATI #define glVertexBlendEnvfATI __aglVertexBlendEnvfATI #endif #if defined AGL_ATI_element_array #define glElementPointerATI __aglElementPointerATI #define glDrawElementArrayATI __aglDrawElementArrayATI #define glDrawRangeElementArrayATI __aglDrawRangeElementArrayATI #endif #if defined AGL_SUN_mesh_array #define glDrawMeshArraysSUN __aglDrawMeshArraysSUN #endif #if defined AGL_NV_occlusion_query #define glGenOcclusionQueriesNV __aglGenOcclusionQueriesNV #define glDeleteOcclusionQueriesNV __aglDeleteOcclusionQueriesNV #define glIsOcclusionQueryNV __aglIsOcclusionQueryNV #define glBeginOcclusionQueryNV __aglBeginOcclusionQueryNV #define glEndOcclusionQueryNV __aglEndOcclusionQueryNV #define glGetOcclusionQueryivNV __aglGetOcclusionQueryivNV #define glGetOcclusionQueryuivNV __aglGetOcclusionQueryuivNV #endif #if defined AGL_NV_point_sprite #define glPointParameteriNV __aglPointParameteriNV #define glPointParameterivNV __aglPointParameterivNV #endif #if defined AGL_EXT_stencil_two_side #define glActiveStencilFaceEXT __aglActiveStencilFaceEXT #endif #if defined AGL_APPLE_element_array #define glElementPointerAPPLE __aglElementPointerAPPLE #define glDrawElementArrayAPPLE __aglDrawElementArrayAPPLE #define glDrawRangeElementArrayAPPLE __aglDrawRangeElementArrayAPPLE #define glMultiDrawElementArrayAPPLE __aglMultiDrawElementArrayAPPLE #define glMultiDrawRangeElementArrayAPPLE __aglMultiDrawRangeElementArrayAPPLE #endif #if defined AGL_APPLE_fence #define glGenFencesAPPLE __aglGenFencesAPPLE #define glDeleteFencesAPPLE __aglDeleteFencesAPPLE #define glSetFenceAPPLE __aglSetFenceAPPLE #define glIsFenceAPPLE __aglIsFenceAPPLE #define glTestFenceAPPLE __aglTestFenceAPPLE #define glFinishFenceAPPLE __aglFinishFenceAPPLE #define glTestObjectAPPLE __aglTestObjectAPPLE #define glFinishObjectAPPLE __aglFinishObjectAPPLE #endif #if defined AGL_APPLE_vertex_array_object #define glBindVertexArrayAPPLE __aglBindVertexArrayAPPLE #define glDeleteVertexArraysAPPLE __aglDeleteVertexArraysAPPLE #define glGenVertexArraysAPPLE __aglGenVertexArraysAPPLE #define glIsVertexArrayAPPLE __aglIsVertexArrayAPPLE #endif #if defined AGL_APPLE_vertex_array_range #define glVertexArrayRangeAPPLE __aglVertexArrayRangeAPPLE #define glFlushVertexArrayRangeAPPLE __aglFlushVertexArrayRangeAPPLE #define glVertexArrayParameteriAPPLE __aglVertexArrayParameteriAPPLE #endif #if defined AGL_ATI_draw_buffers #define glDrawBuffersATI __aglDrawBuffersATI #endif #if defined AGL_NV_fragment_program #define glProgramNamedParameter4fNV __aglProgramNamedParameter4fNV #define glProgramNamedParameter4dNV __aglProgramNamedParameter4dNV #define glProgramNamedParameter4fvNV __aglProgramNamedParameter4fvNV #define glProgramNamedParameter4dvNV __aglProgramNamedParameter4dvNV #define glGetProgramNamedParameterfvNV __aglGetProgramNamedParameterfvNV #define glGetProgramNamedParameterdvNV __aglGetProgramNamedParameterdvNV #endif #if defined AGL_NV_half_float #define glVertex2hNV __aglVertex2hNV #define glVertex2hvNV __aglVertex2hvNV #define glVertex3hNV __aglVertex3hNV #define glVertex3hvNV __aglVertex3hvNV #define glVertex4hNV __aglVertex4hNV #define glVertex4hvNV __aglVertex4hvNV #define glNormal3hNV __aglNormal3hNV #define glNormal3hvNV __aglNormal3hvNV #define glColor3hNV __aglColor3hNV #define glColor3hvNV __aglColor3hvNV #define glColor4hNV __aglColor4hNV #define glColor4hvNV __aglColor4hvNV #define glTexCoord1hNV __aglTexCoord1hNV #define glTexCoord1hvNV __aglTexCoord1hvNV #define glTexCoord2hNV __aglTexCoord2hNV #define glTexCoord2hvNV __aglTexCoord2hvNV #define glTexCoord3hNV __aglTexCoord3hNV #define glTexCoord3hvNV __aglTexCoord3hvNV #define glTexCoord4hNV __aglTexCoord4hNV #define glTexCoord4hvNV __aglTexCoord4hvNV #define glMultiTexCoord1hNV __aglMultiTexCoord1hNV #define glMultiTexCoord1hvNV __aglMultiTexCoord1hvNV #define glMultiTexCoord2hNV __aglMultiTexCoord2hNV #define glMultiTexCoord2hvNV __aglMultiTexCoord2hvNV #define glMultiTexCoord3hNV __aglMultiTexCoord3hNV #define glMultiTexCoord3hvNV __aglMultiTexCoord3hvNV #define glMultiTexCoord4hNV __aglMultiTexCoord4hNV #define glMultiTexCoord4hvNV __aglMultiTexCoord4hvNV #define glFogCoordhNV __aglFogCoordhNV #define glFogCoordhvNV __aglFogCoordhvNV #define glSecondaryColor3hNV __aglSecondaryColor3hNV #define glSecondaryColor3hvNV __aglSecondaryColor3hvNV #define glVertexWeighthNV __aglVertexWeighthNV #define glVertexWeighthvNV __aglVertexWeighthvNV #define glVertexAttrib1hNV __aglVertexAttrib1hNV #define glVertexAttrib1hvNV __aglVertexAttrib1hvNV #define glVertexAttrib2hNV __aglVertexAttrib2hNV #define glVertexAttrib2hvNV __aglVertexAttrib2hvNV #define glVertexAttrib3hNV __aglVertexAttrib3hNV #define glVertexAttrib3hvNV __aglVertexAttrib3hvNV #define glVertexAttrib4hNV __aglVertexAttrib4hNV #define glVertexAttrib4hvNV __aglVertexAttrib4hvNV #define glVertexAttribs1hvNV __aglVertexAttribs1hvNV #define glVertexAttribs2hvNV __aglVertexAttribs2hvNV #define glVertexAttribs3hvNV __aglVertexAttribs3hvNV #define glVertexAttribs4hvNV __aglVertexAttribs4hvNV #endif #if defined AGL_NV_pixel_data_range #define glPixelDataRangeNV __aglPixelDataRangeNV #define glFlushPixelDataRangeNV __aglFlushPixelDataRangeNV #endif #if defined AGL_NV_primitive_restart #define glPrimitiveRestartNV __aglPrimitiveRestartNV #define glPrimitiveRestartIndexNV __aglPrimitiveRestartIndexNV #endif #if defined AGL_ATI_map_object_buffer #define glMapObjectBufferATI __aglMapObjectBufferATI #define glUnmapObjectBufferATI __aglUnmapObjectBufferATI #endif #if defined AGL_ATI_separate_stencil #define glStencilOpSeparateATI __aglStencilOpSeparateATI #define glStencilFuncSeparateATI __aglStencilFuncSeparateATI #endif #if defined AGL_ATI_vertex_attrib_array_object #define glVertexAttribArrayObjectATI __aglVertexAttribArrayObjectATI #define glGetVertexAttribArrayObjectfvATI __aglGetVertexAttribArrayObjectfvATI #define glGetVertexAttribArrayObjectivATI __aglGetVertexAttribArrayObjectivATI #endif #if defined AGL_OES_byte_coordinates #define glVertex2bOES __aglVertex2bOES #define glVertex3bOES __aglVertex3bOES #define glVertex4bOES __aglVertex4bOES #define glVertex2bvOES __aglVertex2bvOES #define glVertex3bvOES __aglVertex3bvOES #define glVertex4bvOES __aglVertex4bvOES #define glTexCoord1bOES __aglTexCoord1bOES #define glTexCoord2bOES __aglTexCoord2bOES #define glTexCoord3bOES __aglTexCoord3bOES #define glTexCoord4bOES __aglTexCoord4bOES #define glTexCoord1bvOES __aglTexCoord1bvOES #define glTexCoord2bvOES __aglTexCoord2bvOES #define glTexCoord3bvOES __aglTexCoord3bvOES #define glTexCoord4bvOES __aglTexCoord4bvOES #define glMultiTexCoord1bOES __aglMultiTexCoord1bOES #define glMultiTexCoord2bOES __aglMultiTexCoord2bOES #define glMultiTexCoord3bOES __aglMultiTexCoord3bOES #define glMultiTexCoord4bOES __aglMultiTexCoord4bOES #define glMultiTexCoord1bvOES __aglMultiTexCoord1bvOES #define glMultiTexCoord2bvOES __aglMultiTexCoord2bvOES #define glMultiTexCoord3bvOES __aglMultiTexCoord3bvOES #define glMultiTexCoord4bvOES __aglMultiTexCoord4bvOES #endif #if defined AGL_OES_fixed_point #define glVertex2xOES __aglVertex2xOES #define glVertex3xOES __aglVertex3xOES #define glVertex4xOES __aglVertex4xOES #define glVertex2xvOES __aglVertex2xvOES #define glVertex3xvOES __aglVertex3xvOES #define glVertex4xvOES __aglVertex4xvOES #define glNormal3xOES __aglNormal3xOES #define glNormal3xvOES __aglNormal3xvOES #define glTexCoord1xOES __aglTexCoord1xOES #define glTexCoord2xOES __aglTexCoord2xOES #define glTexCoord3xOES __aglTexCoord3xOES #define glTexCoord4xOES __aglTexCoord4xOES #define glTexCoord1xvOES __aglTexCoord1xvOES #define glTexCoord2xvOES __aglTexCoord2xvOES #define glTexCoord3xvOES __aglTexCoord3xvOES #define glTexCoord4xvOES __aglTexCoord4xvOES #define glMultiTexCoord1xOES __aglMultiTexCoord1xOES #define glMultiTexCoord2xOES __aglMultiTexCoord2xOES #define glMultiTexCoord3xOES __aglMultiTexCoord3xOES #define glMultiTexCoord4xOES __aglMultiTexCoord4xOES #define glMultiTexCoord1xvOES __aglMultiTexCoord1xvOES #define glMultiTexCoord2xvOES __aglMultiTexCoord2xvOES #define glMultiTexCoord3xvOES __aglMultiTexCoord3xvOES #define glMultiTexCoord4xvOES __aglMultiTexCoord4xvOES #define glColor3xOES __aglColor3xOES #define glColor4xOES __aglColor4xOES #define glColor3xvOES __aglColor3xvOES #define glColor4xvOES __aglColor4xvOES #define glIndexxOES __aglIndexxOES #define glIndexxvOES __aglIndexxvOES #define glRectxOES __aglRectxOES #define glRectxvOES __aglRectxvOES #define glDepthRangexOES __aglDepthRangexOES #define glLoadMatrixxOES __aglLoadMatrixxOES #define glMultMatrixxOES __aglMultMatrixxOES #define glLoadTransposeMatrixxOES __aglLoadTransposeMatrixxOES #define glMultTransposeMatrixxOES __aglMultTransposeMatrixxOES #define glRotatexOES __aglRotatexOES #define glScalexOES __aglScalexOES #define glTranslatexOES __aglTranslatexOES #define glFrustumxOES __aglFrustumxOES #define glOrthoxOES __aglOrthoxOES #define glTexGenxOES __aglTexGenxOES #define glTexGenxvOES __aglTexGenxvOES #define glGetTexGenxvOES __aglGetTexGenxvOES #define glClipPlanexOES __aglClipPlanexOES #define glGetClipPlanexOES __aglGetClipPlanexOES #define glRasterPos2xOES __aglRasterPos2xOES #define glRasterPos3xOES __aglRasterPos3xOES #define glRasterPos4xOES __aglRasterPos4xOES #define glRasterPos2xvOES __aglRasterPos2xvOES #define glRasterPos3xvOES __aglRasterPos3xvOES #define glRasterPos4xvOES __aglRasterPos4xvOES #define glMaterialxOES __aglMaterialxOES #define glMaterialxvOES __aglMaterialxvOES #define glGetMaterialxOES __aglGetMaterialxOES #define glLightxOES __aglLightxOES #define glLightxvOES __aglLightxvOES #define glGetLightxOES __aglGetLightxOES #define glLightModelxOES __aglLightModelxOES #define glLightModelxvOES __aglLightModelxvOES #define glPointSizexOES __aglPointSizexOES #define glLineWidthxOES __aglLineWidthxOES #define glPolygonOffsetxOES __aglPolygonOffsetxOES #define glPixelStorex __aglPixelStorex #define glPixelTransferxOES __aglPixelTransferxOES #define glPixelMapx __aglPixelMapx #define glGetPixelMapxv __aglGetPixelMapxv #define glConvolutionParameterxOES __aglConvolutionParameterxOES #define glConvolutionParameterxvOES __aglConvolutionParameterxvOES #define glGetConvolutionParameterxvOES __aglGetConvolutionParameterxvOES #define glGetHistogramParameterxvOES __aglGetHistogramParameterxvOES #define glPixelZoomxOES __aglPixelZoomxOES #define glBitmapxOES __aglBitmapxOES #define glTexParameterxOES __aglTexParameterxOES #define glTexParameterxvOES __aglTexParameterxvOES #define glGetTexParameterxvOES __aglGetTexParameterxvOES #define glGetTexLevelParameterxvOES __aglGetTexLevelParameterxvOES #define glPrioritizeTexturesxOES __aglPrioritizeTexturesxOES #define glTexEnvxOES __aglTexEnvxOES #define glTexEnvxvOES __aglTexEnvxvOES #define glGetTexEnvxvOES __aglGetTexEnvxvOES #define glFogxOES __aglFogxOES #define glFogxvOES __aglFogxvOES #define glSampleCoverageOES __aglSampleCoverageOES #define glAlphaFuncxOES __aglAlphaFuncxOES #define glBlendColorxOES __aglBlendColorxOES #define glClearColorxOES __aglClearColorxOES #define glClearDepthxOES __aglClearDepthxOES #define glClearAccumxOES __aglClearAccumxOES #define glAccumxOES __aglAccumxOES #define glMap1xOES __aglMap1xOES #define glMap2xOES __aglMap2xOES #define glMapGrid1xOES __aglMapGrid1xOES #define glMapGrid2xOES __aglMapGrid2xOES #define glGetMapxvOES __aglGetMapxvOES #define glEvalCoord1xOES __aglEvalCoord1xOES #define glEvalCoord2xOES __aglEvalCoord2xOES #define glEvalCoord1xvOES __aglEvalCoord1xvOES #define glEvalCoord2xvOES __aglEvalCoord2xvOES #define glFeedbackBufferxOES __aglFeedbackBufferxOES #define glPassThroughxOES __aglPassThroughxOES #define glGetFixedvOES __aglGetFixedvOES #endif #if defined AGL_OES_single_precision #define glDepthRangefOES __aglDepthRangefOES #define glFrustumfOES __aglFrustumfOES #define glOrthofOES __aglOrthofOES #define glClipPlanefOES __aglClipPlanefOES #define glGetClipPlanefOES __aglGetClipPlanefOES #define glClearDepthfOES __aglClearDepthfOES #endif #if defined AGL_OES_query_matrix #define glQueryMatrixxOES __aglQueryMatrixxOES #endif #if defined AGL_EXT_depth_bounds_test #define glDepthBoundsEXT __aglDepthBoundsEXT #endif #if defined AGL_EXT_blend_equation_separate #define glBlendEquationSeparateEXT __aglBlendEquationSeparateEXT #endif #if defined AGL_EXT_framebuffer_object #define glIsRenderbufferEXT __aglIsRenderbufferEXT #define glBindRenderbufferEXT __aglBindRenderbufferEXT #define glDeleteRenderbuffersEXT __aglDeleteRenderbuffersEXT #define glGenRenderbuffersEXT __aglGenRenderbuffersEXT #define glRenderbufferStorageEXT __aglRenderbufferStorageEXT #define glGetRenderbufferParameterivEXT __aglGetRenderbufferParameterivEXT #define glIsFramebufferEXT __aglIsFramebufferEXT #define glBindFramebufferEXT __aglBindFramebufferEXT #define glDeleteFramebuffersEXT __aglDeleteFramebuffersEXT #define glGenFramebuffersEXT __aglGenFramebuffersEXT #define glCheckFramebufferStatusEXT __aglCheckFramebufferStatusEXT #define glFramebufferTexture1DEXT __aglFramebufferTexture1DEXT #define glFramebufferTexture2DEXT __aglFramebufferTexture2DEXT #define glFramebufferTexture3DEXT __aglFramebufferTexture3DEXT #define glFramebufferRenderbufferEXT __aglFramebufferRenderbufferEXT #define glGetFramebufferAttachmentParameterivEXT __aglGetFramebufferAttachmentParameterivEXT #define glGenerateMipmapEXT __aglGenerateMipmapEXT #endif #if defined AGL_GREMEDY_string_marker #define glStringMarkerGREMEDY __aglStringMarkerGREMEDY #endif #if defined AGL_EXT_stencil_clear_tag #define glStencilClearTagEXT __aglStencilClearTagEXT #endif #if defined AGL_EXT_framebuffer_blit #define glBlitFramebufferEXT __aglBlitFramebufferEXT #endif #if defined AGL_EXT_framebuffer_multisample #define glRenderbufferStorageMultisampleEXT __aglRenderbufferStorageMultisampleEXT #endif #if defined AGL_EXT_timer_query #define glGetQueryObjecti64vEXT __aglGetQueryObjecti64vEXT #define glGetQueryObjectui64vEXT __aglGetQueryObjectui64vEXT #endif #if defined AGL_EXT_gpu_program_parameters #define glProgramEnvParameters4fvEXT __aglProgramEnvParameters4fvEXT #define glProgramLocalParameters4fvEXT __aglProgramLocalParameters4fvEXT #endif #if defined AGL_APPLE_flush_buffer_range #define glBufferParameteriAPPLE __aglBufferParameteriAPPLE #define glFlushMappedBufferRangeAPPLE __aglFlushMappedBufferRangeAPPLE #endif #if defined AGL_EXT_bindable_uniform #define glUniformBufferEXT __aglUniformBufferEXT #define glGetUniformBufferSizeEXT __aglGetUniformBufferSizeEXT #define glGetUniformOffsetEXT __aglGetUniformOffsetEXT #endif #if defined AGL_EXT_draw_buffers2 #define glColorMaskIndexedEXT __aglColorMaskIndexedEXT #define glGetBooleanIndexedvEXT __aglGetBooleanIndexedvEXT #define glGetIntegerIndexedvEXT __aglGetIntegerIndexedvEXT #define glEnableIndexedEXT __aglEnableIndexedEXT #define glDisableIndexedEXT __aglDisableIndexedEXT #define glIsEnabledIndexedEXT __aglIsEnabledIndexedEXT #endif #if defined AGL_EXT_draw_instanced #define glDrawArraysInstancedEXT __aglDrawArraysInstancedEXT #define glDrawElementsInstancedEXT __aglDrawElementsInstancedEXT #endif #if defined AGL_EXT_geometry_shader4 #define glProgramParameteriEXT __aglProgramParameteriEXT #define glFramebufferTextureEXT __aglFramebufferTextureEXT #if !defined AGL_EXT_texture_array #define glFramebufferTextureLayerEXT __aglFramebufferTextureLayerEXT #endif #define glFramebufferTextureFaceEXT __aglFramebufferTextureFaceEXT #endif #if defined AGL_EXT_gpu_shader4 #define glVertexAttribI1iEXT __aglVertexAttribI1iEXT #define glVertexAttribI2iEXT __aglVertexAttribI2iEXT #define glVertexAttribI3iEXT __aglVertexAttribI3iEXT #define glVertexAttribI4iEXT __aglVertexAttribI4iEXT #define glVertexAttribI1uiEXT __aglVertexAttribI1uiEXT #define glVertexAttribI2uiEXT __aglVertexAttribI2uiEXT #define glVertexAttribI3uiEXT __aglVertexAttribI3uiEXT #define glVertexAttribI4uiEXT __aglVertexAttribI4uiEXT #define glVertexAttribI1ivEXT __aglVertexAttribI1ivEXT #define glVertexAttribI2ivEXT __aglVertexAttribI2ivEXT #define glVertexAttribI3ivEXT __aglVertexAttribI3ivEXT #define glVertexAttribI4ivEXT __aglVertexAttribI4ivEXT #define glVertexAttribI1uivEXT __aglVertexAttribI1uivEXT #define glVertexAttribI2uivEXT __aglVertexAttribI2uivEXT #define glVertexAttribI3uivEXT __aglVertexAttribI3uivEXT #define glVertexAttribI4uivEXT __aglVertexAttribI4uivEXT #define glVertexAttribI4bvEXT __aglVertexAttribI4bvEXT #define glVertexAttribI4svEXT __aglVertexAttribI4svEXT #define glVertexAttribI4ubvEXT __aglVertexAttribI4ubvEXT #define glVertexAttribI4usvEXT __aglVertexAttribI4usvEXT #define glVertexAttribIPointerEXT __aglVertexAttribIPointerEXT #define glGetVertexAttribIivEXT __aglGetVertexAttribIivEXT #define glGetVertexAttribIuivEXT __aglGetVertexAttribIuivEXT #define glUniform1uiEXT __aglUniform1uiEXT #define glUniform2uiEXT __aglUniform2uiEXT #define glUniform3uiEXT __aglUniform3uiEXT #define glUniform4uiEXT __aglUniform4uiEXT #define glUniform1uivEXT __aglUniform1uivEXT #define glUniform2uivEXT __aglUniform2uivEXT #define glUniform3uivEXT __aglUniform3uivEXT #define glUniform4uivEXT __aglUniform4uivEXT #define glGetUniformuivEXT __aglGetUniformuivEXT #define glBindFragDataLocationEXT __aglBindFragDataLocationEXT #define glGetFragDataLocationEXT __aglGetFragDataLocationEXT #endif #if defined AGL_EXT_texture_array #define glFramebufferTextureLayerEXT __aglFramebufferTextureLayerEXT #endif #if defined AGL_EXT_texture_buffer_object #define glTexBufferEXT __aglTexBufferEXT #endif #if defined AGL_texture_integer #define glClearColorIiEXT __aglClearColorIiEXT #define glClearColorIuiEXT __aglClearColorIuiEXT #define glTexParameterIivEXT __aglTexParameterIivEXT #define glTexParameterIuivEXT __aglTexParameterIuivEXT #define glGetTexParameterIivEXT __aglGetTexParameterIivEXT #define glGetTexParameterIiuvEXT __aglGetTexParameterIiuvEXT #endif #if defined AGL_NV_depth_buffer_float #define glDepthRangedNV __aglDepthRangedNV #define glClearDepthdNV __aglClearDepthdNV #define glDepthBoundsdNV __aglDepthBoundsdNV #endif #if defined AGL_NV_framebuffer_multisample_coverage #define glRenderbufferStorageMultsampleCoverageNV __aglRenderbufferStorageMultsampleCoverageNV #endif #if defined AGL_NV_geometry_program4 #define glProgramVertexLimitNV __aglProgramVertexLimitNV #if !defined AGL_EXT_geometry_shader4 #define glFramebufferTextureEXT __aglFramebufferTextureEXT #if !defined AGL_EXT_texture_array #define glFramebufferTextureLayerEXT __aglFramebufferTextureLayerEXT #endif #endif #endif #if defined AGL_NV_gpu_program4 #define glProgramLocalParameterI4iNV __aglProgramLocalParameterI4iNV #define glProgramLocalParameterI4ivNV __aglProgramLocalParameterI4ivNV #define glProgramLocalParametersI4ivNV __aglProgramLocalParametersI4ivNV #define glProgramLocalParameterI4uiNV __aglProgramLocalParameterI4uiNV #define glProgramLocalParameterI4uivNV __aglProgramLocalParameterI4uivNV #define glProgramLocalParametersI4uivNV __aglProgramLocalParametersI4uivNV #define glProgramEnvParameterI4iNV __aglProgramEnvParameterI4iNV #define glProgramEnvParameterI4ivNV __aglProgramEnvParameterI4ivNV #define glProgramEnvParametersI4ivNV __aglProgramEnvParametersI4ivNV #define glProgramEnvParameterI4uiNV __aglProgramEnvParameterI4uiNV #define glProgramEnvParameterI4uivNV __aglProgramEnvParameterI4uivNV #define glProgramEnvParametersI4uivNV __aglProgramEnvParametersI4uivNV #define glGetProgramLocalParameterIivNV __aglGetProgramLocalParameterIivNV #define glGetProgramLocalParameterIuivNV __aglGetProgramLocalParameterIuivNV #define glGetProgramEnvParameterIivNV __aglGetProgramEnvParameterIivNV #define glGetProgramEnvParameterIuivNV __aglGetProgramEnvParameterIuivNV #endif #if defined AGL_NV_parameter_buffer_object #if !defined AGL_NV_transform_feedback #define glBindBufferRangeNV __aglBindBufferRangeNV #define glBindBufferOffsetNV __aglBindBufferOffsetNV #define glBindBufferBaseNV __aglBindBufferBaseNV #endif #define glProgramBufferParametersfvNV __aglProgramBufferParametersfvNV #define glProgramBufferParametersIivNV __aglProgramBufferParametersIivNV #define glProgramBufferParametersIuivNV __aglProgramBufferParametersIuivNV #if !defined AGL_EXT_draw_buffers2 #define glGetIntegerIndexedvEXT __aglGetIntegerIndexedvEXT #endif #endif #if defined AGL_NV_transform_feedback #define glBindBufferRangeNV __aglBindBufferRangeNV #define glBindBufferOffsetNV __aglBindBufferOffsetNV #define glBindBufferBaseNV __aglBindBufferBaseNV #define glTransformFeedbackAttribsNV __aglTransformFeedbackAttribsNV #define glTransformFeedbackVaryingsNV __aglTransformFeedbackVaryingsNV #define glBeginTransformFeedbackNV __aglBeginTransformFeedbackNV #define glEndTransformFeedbackNV __aglEndTransformFeedbackNV #define glGetVaryingLocationNV __aglGetVaryingLocationNV #define glGetActiveVaryingNV __aglGetActiveVaryingNV #define glActiveVaryingNV __aglActiveVaryingNV #define glGetTransformFeedbackVaryingNV __aglGetTransformFeedbackVaryingNV #if !defined AGL_EXT_draw_buffers2 #define glGetBooleanIndexedvEXT __aglGetBooleanIndexedvEXT /*AGL_API(void,GetIntegerIndexedvEXT,(GLenum,GLuint,GLint*))*/ #endif #endif #if defined AGL_NV_vertex_program4 #ifndef AGL_EXT_gpu_shader4 #define glVertexAttribI1iEXT __aglVertexAttribI1iEXT #define glVertexAttribI2iEXT __aglVertexAttribI2iEXT #define glVertexAttribI3iEXT __aglVertexAttribI3iEXT #define glVertexAttribI4iEXT __aglVertexAttribI4iEXT #define glVertexAttribI1uiEXT __aglVertexAttribI1uiEXT #define glVertexAttribI2uiEXT __aglVertexAttribI2uiEXT #define glVertexAttribI3uiEXT __aglVertexAttribI3uiEXT #define glVertexAttribI4uiEXT __aglVertexAttribI4uiEXT #define glVertexAttribI1ivEXT __aglVertexAttribI1ivEXT #define glVertexAttribI2ivEXT __aglVertexAttribI2ivEXT #define glVertexAttribI3ivEXT __aglVertexAttribI3ivEXT #define glVertexAttribI4ivEXT __aglVertexAttribI4ivEXT #define glVertexAttribI1uivEXT __aglVertexAttribI1uivEXT #define glVertexAttribI2uivEXT __aglVertexAttribI2uivEXT #define glVertexAttribI3uivEXT __aglVertexAttribI3uivEXT #define glVertexAttribI4uivEXT __aglVertexAttribI4uivEXT #define glVertexAttribI4bvEXT __aglVertexAttribI4bvEXT #define glVertexAttribI4svEXT __aglVertexAttribI4svEXT #define glVertexAttribI4ubvEXT __aglVertexAttribI4ubvEXT #define glVertexAttribI4usvEXT __aglVertexAttribI4usvEXT #define glVertexAttribIPointerEXT __aglVertexAttribIPointerEXT #define glGetVertexAttribIivEXT __aglGetVertexAttribIivEXT #define glGetVertexAttribIuivEXT __aglGetVertexAttribIuivEXT #endif #endif #if defined AGL_GREMEDY_frame_terminator #define glFrameTerminatorGREMEDY __aglFrameTerminatorGREMEDY #endif #if defined AGL_NV_conditional_render #define glBeginConditionalRenderNV __aglBeginConditionalRenderNV #define glEndConditionalRenderNV __aglEndConditionalRenderNV #endif #if defined AGL_EXT_transform_feedback #define glBeginTransformFeedbackEXT __aglBeginTransformFeedbackEXT #define glEndTransformFeedbackEXT __aglEndTransformFeedbackEXT #define glBindBufferRangeEXT __aglBindBufferRangeEXT #define glBindBufferOffsetEXT __aglBindBufferOffsetEXT #define glBindBufferBaseEXT __aglBindBufferBaseEXT #define glTransformFeedbackVaryingsEXT __aglTransformFeedbackVaryingsEXT #define glGetTransformFeedbackVaryingEXT __aglGetTransformFeedbackVaryingEXT #endif #if defined AGL_EXT_direct_state_access #define glClientAttribDefaultEXT __aglClientAttribDefaultEXT #define glPushClientAttribDefaultEXT __aglPushClientAttribDefaultEXT #define glMatrixLoadfEXT __aglMatrixLoadfEXT #define glMatrixLoaddEXT __aglMatrixLoaddEXT #define glMatrixMultfEXT __aglMatrixMultfEXT #define glMatrixMultdEXT __aglMatrixMultdEXT #define glMatrixLoadIdentityEXT __aglMatrixLoadIdentityEXT #define glMatrixRotatefEXT __aglMatrixRotatefEXT #define glMatrixRotatedEXT __aglMatrixRotatedEXT #define glMatrixScalefEXT __aglMatrixScalefEXT #define glMatrixScaledEXT __aglMatrixScaledEXT #define glMatrixTranslatefEXT __aglMatrixTranslatefEXT #define glMatrixTranslatedEXT __aglMatrixTranslatedEXT #define glMatrixFrustumEXT __aglMatrixFrustumEXT #define glMatrixOrthoEXT __aglMatrixOrthoEXT #define glMatrixPopEXT __aglMatrixPopEXT #define glMatrixPushEXT __aglMatrixPushEXT #define glMatrixLoadTransposefEXT __aglMatrixLoadTransposefEXT #define glMatrixLoadTransposedEXT __aglMatrixLoadTransposedEXT #define glMatrixMultTransposefEXT __aglMatrixMultTransposefEXT #define glMatrixMultTransposedEXT __aglMatrixMultTransposedEXT #define glTextureParameterfEXT __aglTextureParameterfEXT #define glTextureParameterfvEXT __aglTextureParameterfvEXT #define glTextureParameteriEXT __aglTextureParameteriEXT #define glTextureParameterivEXT __aglTextureParameterivEXT #define glTextureImage1DEXT __aglTextureImage1DEXT #define glTextureImage2DEXT __aglTextureImage2DEXT #define glTextureSubImage1DEXT __aglTextureSubImage1DEXT #define glTextureSubImage2DEXT __aglTextureSubImage2DEXT #define glCopyTextureImage1DEXT __aglCopyTextureImage1DEXT #define glCopyTextureImage2DEXT __aglCopyTextureImage2DEXT #define glCopyTextureSubImage1DEXT __aglCopyTextureSubImage1DEXT #define glCopyTextureSubImage2DEXT __aglCopyTextureSubImage2DEXT #define glGetTextureImageEXT __aglGetTextureImageEXT #define glGetTextureParameterfvEXT __aglGetTextureParameterfvEXT #define glGetTextureParameterivEXT __aglGetTextureParameterivEXT #define glGetTextureLevelParameterfvEXT __aglGetTextureLevelParameterfvEXT #define glGetTextureLevelParameterivEXT __aglGetTextureLevelParameterivEXT #define glTextureImage3DEXT __aglTextureImage3DEXT #define glTextureSubImage3DEXT __aglTextureSubImage3DEXT #define glCopyTextureSubImage3DEXT __aglCopyTextureSubImage3DEXT #define glMultiTexParameterfEXT __aglMultiTexParameterfEXT #define glMultiTexParameterfvEXT __aglMultiTexParameterfvEXT #define glMultiTexParameteriEXT __aglMultiTexParameteriEXT #define glMultiTexParameterivEXT __aglMultiTexParameterivEXT #define glMultiTexImage1DEXT __aglMultiTexImage1DEXT #define glMultiTexImage2DEXT __aglMultiTexImage2DEXT #define glMultiTexSubImage1DEXT __aglMultiTexSubImage1DEXT #define glMultiTexSubImage2DEXT __aglMultiTexSubImage2DEXT #define glCopyMultiTexImage1DEXT __aglCopyMultiTexImage1DEXT #define glCopyMultiTexImage2DEXT __aglCopyMultiTexImage2DEXT #define glCopyMultiTexSubImage1DEXT __aglCopyMultiTexSubImage1DEXT #define glCopyMultiTexSubImage2DEXT __aglCopyMultiTexSubImage2DEXT #define glGetMultiTexImageEXT __aglGetMultiTexImageEXT #define glGetMultiTexParameterfvEXT __aglGetMultiTexParameterfvEXT #define glGetMultiTexParameterivEXT __aglGetMultiTexParameterivEXT #define glGetMultiTexLevelParameterfvEXT __aglGetMultiTexLevelParameterfvEXT #define glGetMultiTexLevelParameterivEXT __aglGetMultiTexLevelParameterivEXT #define glMultiTexImage3DEXT __aglMultiTexImage3DEXT #define glMultiTexSubImage3DEXT __aglMultiTexSubImage3DEXT #define glCopyMultiTexSubImage3DEXT __aglCopyMultiTexSubImage3DEXT #define glBindMultiTextureEXT __aglBindMultiTextureEXT #define glEnableClientStateIndexedEXT __aglEnableClientStateIndexedEXT #define glDisableClientStateIndexedEXT __aglDisableClientStateIndexedEXT #define glMultiTexCoordPointerEXT __aglMultiTexCoordPointerEXT #define glMultiTexEnvfEXT __aglMultiTexEnvfEXT #define glMultiTexEnvfvEXT __aglMultiTexEnvfvEXT #define glMultiTexEnviEXT __aglMultiTexEnviEXT #define glMultiTexEnvivEXT __aglMultiTexEnvivEXT #define glMultiTexGendEXT __aglMultiTexGendEXT #define glMultiTexGendvEXT __aglMultiTexGendvEXT #define glMultiTexGenfEXT __aglMultiTexGenfEXT #define glMultiTexGenfvEXT __aglMultiTexGenfvEXT #define glMultiTexGeniEXT __aglMultiTexGeniEXT #define glMultiTexGenivEXT __aglMultiTexGenivEXT #define glGetMultiTexEnvfvEXT __aglGetMultiTexEnvfvEXT #define glGetMultiTexEnvivEXT __aglGetMultiTexEnvivEXT #define glGetMultiTexGendvEXT __aglGetMultiTexGendvEXT #define glGetMultiTexGenfvEXT __aglGetMultiTexGenfvEXT #define glGetMultiTexGenivEXT __aglGetMultiTexGenivEXT #define glGetFloatIndexedvEXT __aglGetFloatIndexedvEXT #define glGetDoubleIndexedvEXT __aglGetDoubleIndexedvEXT #define glGetPointerIndexedvEXT __aglGetPointerIndexedvEXT #define glCompressedTextureImage3DEXT __aglCompressedTextureImage3DEXT #define glCompressedTextureImage2DEXT __aglCompressedTextureImage2DEXT #define glCompressedTextureImage1DEXT __aglCompressedTextureImage1DEXT #define glCompressedTextureSubImage3DEXT __aglCompressedTextureSubImage3DEXT #define glCompressedTextureSubImage2DEXT __aglCompressedTextureSubImage2DEXT #define glCompressedTextureSubImage1DEXT __aglCompressedTextureSubImage1DEXT #define glGetCompressedTextureImageEXT __aglGetCompressedTextureImageEXT #define glCompressedMultiTexImage3DEXT __aglCompressedMultiTexImage3DEXT #define glCompressedMultiTexImage2DEXT __aglCompressedMultiTexImage2DEXT #define glCompressedMultiTexImage1DEXT __aglCompressedMultiTexImage1DEXT #define glCompressedMultiTexSubImage3DEXT __aglCompressedMultiTexSubImage3DEXT #define glCompressedMultiTexSubImage2DEXT __aglCompressedMultiTexSubImage2DEXT #define glCompressedMultiTexSubImage1DEXT __aglCompressedMultiTexSubImage1DEXT #define glGetCompressedMultiTexImageEXT __aglGetCompressedMultiTexImageEXT #define glNamedProgramStringEXT __aglNamedProgramStringEXT #define glNamedProgramLocalParameter4dEXT __aglNamedProgramLocalParameter4dEXT #define glNamedProgramLocalParameter4dvEXT __aglNamedProgramLocalParameter4dvEXT #define glNamedProgramLocalParameter4fEXT __aglNamedProgramLocalParameter4fEXT #define glNamedProgramLocalParameter4fvEXT __aglNamedProgramLocalParameter4fvEXT #define glGetNamedProgramLocalParameterdvEXT __aglGetNamedProgramLocalParameterdvEXT #define glGetNamedProgramLocalParameterfvEXT __aglGetNamedProgramLocalParameterfvEXT #define glGetNamedProgramivEXT __aglGetNamedProgramivEXT #define glGetNamedProgramStringEXT __aglGetNamedProgramStringEXT #define glNamedProgramLocalParameters4fvEXT __aglNamedProgramLocalParameters4fvEXT #define glNamedProgramLocalParameterI4iEXT __aglNamedProgramLocalParameterI4iEXT #define glNamedProgramLocalParameterI4ivEXT __aglNamedProgramLocalParameterI4ivEXT #define glNamedProgramLocalParametersI4ivEXT __aglNamedProgramLocalParametersI4ivEXT #define glNamedProgramLocalParameterI4uiEXT __aglNamedProgramLocalParameterI4uiEXT #define glNamedProgramLocalParameterI4uivEXT __aglNamedProgramLocalParameterI4uivEXT #define glNamedProgramLocalParametersI4uivEXT __aglNamedProgramLocalParametersI4uivEXT #define glGetNamedProgramLocalParameterIivEXT __aglGetNamedProgramLocalParameterIivEXT #define glGetNamedProgramLocalParameterIuivEXT __aglGetNamedProgramLocalParameterIuivEXT #define glTextureParameterIivEXT __aglTextureParameterIivEXT #define glTextureParameterIuivEXT __aglTextureParameterIuivEXT #define glGetTextureParameterIivEXT __aglGetTextureParameterIivEXT #define glGetTextureParameterIuivEXT __aglGetTextureParameterIuivEXT #define glMultiTexParameterIivEXT __aglMultiTexParameterIivEXT #define glMultiTexParameterIuivEXT __aglMultiTexParameterIuivEXT #define glGetMultiTexParameterIivEXT __aglGetMultiTexParameterIivEXT #define glGetMultiTexParameterIuivEXT __aglGetMultiTexParameterIuivEXT #define glProgramUniform1fEXT __aglProgramUniform1fEXT #define glProgramUniform2fEXT __aglProgramUniform2fEXT #define glProgramUniform3fEXT __aglProgramUniform3fEXT #define glProgramUniform4fEXT __aglProgramUniform4fEXT #define glProgramUniform1iEXT __aglProgramUniform1iEXT #define glProgramUniform2iEXT __aglProgramUniform2iEXT #define glProgramUniform3iEXT __aglProgramUniform3iEXT #define glProgramUniform4iEXT __aglProgramUniform4iEXT #define glProgramUniform1fvEXT __aglProgramUniform1fvEXT #define glProgramUniform2fvEXT __aglProgramUniform2fvEXT #define glProgramUniform3fvEXT __aglProgramUniform3fvEXT #define glProgramUniform4fvEXT __aglProgramUniform4fvEXT #define glProgramUniform1ivEXT __aglProgramUniform1ivEXT #define glProgramUniform2ivEXT __aglProgramUniform2ivEXT #define glProgramUniform3ivEXT __aglProgramUniform3ivEXT #define glProgramUniform4ivEXT __aglProgramUniform4ivEXT #define glProgramUniformMatrix2fvEXT __aglProgramUniformMatrix2fvEXT #define glProgramUniformMatrix3fvEXT __aglProgramUniformMatrix3fvEXT #define glProgramUniformMatrix4fvEXT __aglProgramUniformMatrix4fvEXT #define glProgramUniformMatrix2x3fvEXT __aglProgramUniformMatrix2x3fvEXT #define glProgramUniformMatrix3x2fvEXT __aglProgramUniformMatrix3x2fvEXT #define glProgramUniformMatrix2x4fvEXT __aglProgramUniformMatrix2x4fvEXT #define glProgramUniformMatrix4x2fvEXT __aglProgramUniformMatrix4x2fvEXT #define glProgramUniformMatrix3x4fvEXT __aglProgramUniformMatrix3x4fvEXT #define glProgramUniformMatrix4x3fvEXT __aglProgramUniformMatrix4x3fvEXT #define glProgramUniform1uiEXT __aglProgramUniform1uiEXT #define glProgramUniform2uiEXT __aglProgramUniform2uiEXT #define glProgramUniform3uiEXT __aglProgramUniform3uiEXT #define glProgramUniform4uiEXT __aglProgramUniform4uiEXT #define glProgramUniform1uivEXT __aglProgramUniform1uivEXT #define glProgramUniform2uivEXT __aglProgramUniform2uivEXT #define glProgramUniform3uivEXT __aglProgramUniform3uivEXT #define glProgramUniform4uivEXT __aglProgramUniform4uivEXT #define glNamedBufferDataEXT __aglNamedBufferDataEXT #define glNamedBufferSubDataEXT __aglNamedBufferSubDataEXT #define glMapNamedBufferEXT __aglMapNamedBufferEXT #define glUnmapNamedBufferEXT __aglUnmapNamedBufferEXT #define glGetNamedBufferParameterivEXT __aglGetNamedBufferParameterivEXT #define glGetNamedBufferPointervEXT __aglGetNamedBufferPointervEXT #define glGetNamedBufferSubDataEXT __aglGetNamedBufferSubDataEXT #define glTextureBufferEXT __aglTextureBufferEXT #define glMultiTexBufferEXT __aglMultiTexBufferEXT #define glNamedRenderbufferStorageEXT __aglNamedRenderbufferStorageEXT #define glGetNamedRenderbufferParameterivEXT __aglGetNamedRenderbufferParameterivEXT #define glCheckNamedFramebufferStatusEXT __aglCheckNamedFramebufferStatusEXT #define glNamedFramebufferTexture1DEXT __aglNamedFramebufferTexture1DEXT #define glNamedFramebufferTexture2DEXT __aglNamedFramebufferTexture2DEXT #define glNamedFramebufferTexture3DEXT __aglNamedFramebufferTexture3DEXT #define glNamedFramebufferRenderbufferEXT __aglNamedFramebufferRenderbufferEXT #define glGetNamedFramebufferAttachmentParameterivEXT __aglGetNamedFramebufferAttachmentParameterivEXT #define glGenerateTextureMipmapEXT __aglGenerateTextureMipmapEXT #define glGenerateMultiTexMipmapEXT __aglGenerateMultiTexMipmapEXT #define glFramebufferDrawBufferEXT __aglFramebufferDrawBufferEXT #define glFramebufferDrawBuffersEXT __aglFramebufferDrawBuffersEXT #define glFramebufferReadBufferEXT __aglFramebufferReadBufferEXT #define glGetFramebufferParameterivEXT __aglGetFramebufferParameterivEXT #define glNamedRenderbufferStorageMultisampleEXT __aglNamedRenderbufferStorageMultisampleEXT #define glNamedRenderbufferStorageMultisampleCoverageEXT __aglNamedRenderbufferStorageMultisampleCoverageEXT #define glNamedFramebufferTextureEXT __aglNamedFramebufferTextureEXT #define glNamedFramebufferTextureLayerEXT __aglNamedFramebufferTextureLayerEXT #define glNamedFramebufferTextureFaceEXT __aglNamedFramebufferTextureFaceEXT #define glTextureRenderbufferEXT __aglTextureRenderbufferEXT #define glMultiTexRenderbufferEXT __aglMultiTexRenderbufferEXT #endif allegro4.4-4.4.2/addons/allegrogl/include/allegrogl/GLext/gl_ext_api.h000066400000000000000000003534651173507505700255500ustar00rootroot00000000000000/* */ #ifdef AGL_VERSION_1_2 AGL_API(void, BlendColor, (GLclampf, GLclampf, GLclampf, GLclampf)) AGL_API(void, BlendEquation, (GLenum)) AGL_API(void, DrawRangeElements, (GLenum, GLuint, GLuint, GLsizei, GLenum, const GLvoid *)) AGL_API(void, ColorTable, (GLenum, GLenum, GLsizei, GLenum, GLenum, const GLvoid *)) AGL_API(void, ColorTableParameterfv, (GLenum, GLenum, const GLfloat *)) AGL_API(void, ColorTableParameteriv, (GLenum, GLenum, const GLint *)) AGL_API(void, CopyColorTable, (GLenum, GLenum, GLint, GLint, GLsizei)) AGL_API(void, GetColorTable, (GLenum, GLenum, GLenum, GLvoid *)) AGL_API(void, GetColorTableParameterfv, (GLenum, GLenum, GLfloat *)) AGL_API(void, GetColorTableParameteriv, (GLenum, GLenum, GLint *)) AGL_API(void, ColorSubTable, (GLenum, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *)) AGL_API(void, CopyColorSubTable, (GLenum, GLsizei, GLint, GLint, GLsizei)) AGL_API(void, TexImage3D, (GLenum, GLint, GLint, GLsizei, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid *)) AGL_API(void, TexSubImage3D, (GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *)) AGL_API(void, CopyTexSubImage3D, (GLenum, GLint, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei)) #endif #if defined AGL_ARB_imaging AGL_API(void, ConvolutionFilter1D, (GLenum, GLenum, GLsizei, GLenum, GLenum, const GLvoid *)) AGL_API(void, ConvolutionFilter2D, (GLenum, GLenum, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *)) AGL_API(void, ConvolutionParameterf, (GLenum, GLenum, GLfloat)) AGL_API(void, ConvolutionParameterfv, (GLenum, GLenum, const GLfloat *)) AGL_API(void, ConvolutionParameteri, (GLenum, GLenum, GLint)) AGL_API(void, ConvolutionParameteriv, (GLenum, GLenum, const GLint *)) AGL_API(void, CopyConvolutionFilter1D, (GLenum, GLenum, GLint, GLint, GLsizei)) AGL_API(void, CopyConvolutionFilter2D, (GLenum, GLenum, GLint, GLint, GLsizei, GLsizei)) AGL_API(void, GetConvolutionFilter, (GLenum, GLenum, GLenum, GLvoid *)) AGL_API(void, GetConvolutionParameterfv, (GLenum, GLenum, GLfloat *)) AGL_API(void, GetConvolutionParameteriv, (GLenum, GLenum, GLint *)) AGL_API(void, GetSeparableFilter, (GLenum, GLenum, GLenum, GLvoid *, GLvoid *, GLvoid *)) AGL_API(void, SeparableFilter2D, (GLenum, GLenum, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *, const GLvoid *)) AGL_API(void, GetHistogram, (GLenum, GLboolean, GLenum, GLenum, GLvoid *)) AGL_API(void, GetHistogramParameterfv, (GLenum, GLenum, GLfloat *)) AGL_API(void, GetHistogramParameteriv, (GLenum, GLenum, GLint *)) AGL_API(void, GetMinmax, (GLenum, GLboolean, GLenum, GLenum, GLvoid *)) AGL_API(void, GetMinmaxParameterfv, (GLenum, GLenum, GLfloat *)) AGL_API(void, GetMinmaxParameteriv, (GLenum, GLenum, GLint *)) AGL_API(void, Histogram, (GLenum, GLsizei, GLenum, GLboolean)) AGL_API(void, Minmax, (GLenum, GLenum, GLboolean)) AGL_API(void, ResetHistogram, (GLenum)) AGL_API(void, ResetMinmax, (GLenum)) #endif #if defined AGL_VERSION_1_3 AGL_API(void, ActiveTexture, (GLenum)) AGL_API(void, ClientActiveTexture, (GLenum)) AGL_API(void, MultiTexCoord1d, (GLenum, GLdouble)) AGL_API(void, MultiTexCoord1dv, (GLenum, const GLdouble *)) AGL_API(void, MultiTexCoord1f, (GLenum, GLfloat)) AGL_API(void, MultiTexCoord1fv, (GLenum, const GLfloat *)) AGL_API(void, MultiTexCoord1i, (GLenum, GLint)) AGL_API(void, MultiTexCoord1iv, (GLenum, const GLint *)) AGL_API(void, MultiTexCoord1s, (GLenum, GLshort)) AGL_API(void, MultiTexCoord1sv, (GLenum, const GLshort *)) AGL_API(void, MultiTexCoord2d, (GLenum, GLdouble, GLdouble)) AGL_API(void, MultiTexCoord2dv, (GLenum, const GLdouble *)) AGL_API(void, MultiTexCoord2f, (GLenum, GLfloat, GLfloat)) AGL_API(void, MultiTexCoord2fv, (GLenum, const GLfloat *)) AGL_API(void, MultiTexCoord2i, (GLenum, GLint, GLint)) AGL_API(void, MultiTexCoord2iv, (GLenum, const GLint *)) AGL_API(void, MultiTexCoord2s, (GLenum, GLshort, GLshort)) AGL_API(void, MultiTexCoord2sv, (GLenum, const GLshort *)) AGL_API(void, MultiTexCoord3d, (GLenum, GLdouble, GLdouble, GLdouble)) AGL_API(void, MultiTexCoord3dv, (GLenum, const GLdouble *)) AGL_API(void, MultiTexCoord3f, (GLenum, GLfloat, GLfloat, GLfloat)) AGL_API(void, MultiTexCoord3fv, (GLenum, const GLfloat *)) AGL_API(void, MultiTexCoord3i, (GLenum, GLint, GLint, GLint)) AGL_API(void, MultiTexCoord3iv, (GLenum, const GLint *)) AGL_API(void, MultiTexCoord3s, (GLenum, GLshort, GLshort, GLshort)) AGL_API(void, MultiTexCoord3sv, (GLenum, const GLshort *)) AGL_API(void, MultiTexCoord4d, (GLenum, GLdouble, GLdouble, GLdouble, GLdouble)) AGL_API(void, MultiTexCoord4dv, (GLenum, const GLdouble *)) AGL_API(void, MultiTexCoord4f, (GLenum, GLfloat, GLfloat, GLfloat, GLfloat)) AGL_API(void, MultiTexCoord4fv, (GLenum, const GLfloat *)) AGL_API(void, MultiTexCoord4i, (GLenum, GLint, GLint, GLint, GLint)) AGL_API(void, MultiTexCoord4iv, (GLenum, const GLint *)) AGL_API(void, MultiTexCoord4s, (GLenum, GLshort, GLshort, GLshort, GLshort)) AGL_API(void, MultiTexCoord4sv, (GLenum, const GLshort *)) AGL_API(void, LoadTransposeMatrixf, (const GLfloat *)) AGL_API(void, LoadTransposeMatrixd, (const GLdouble *)) AGL_API(void, MultTransposeMatrixf, (const GLfloat *)) AGL_API(void, MultTransposeMatrixd, (const GLdouble *)) AGL_API(void, SampleCoverage, (GLclampf, GLboolean)) AGL_API(void, CompressedTexImage3D, (GLenum, GLint, GLenum, GLsizei, GLsizei, GLsizei, GLint, GLsizei, const GLvoid *)) AGL_API(void, CompressedTexImage2D, (GLenum, GLint, GLenum, GLsizei, GLsizei, GLint, GLsizei, const GLvoid *)) AGL_API(void, CompressedTexImage1D, (GLenum, GLint, GLenum, GLsizei, GLint, GLsizei, const GLvoid *)) AGL_API(void, CompressedTexSubImage3D, (GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLsizei, const GLvoid *)) AGL_API(void, CompressedTexSubImage2D, (GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLsizei, const GLvoid *)) AGL_API(void, CompressedTexSubImage1D, (GLenum, GLint, GLint, GLsizei, GLenum, GLsizei, const GLvoid *)) AGL_API(void, GetCompressedTexImage, (GLenum, GLint, GLvoid *)) #endif #if defined AGL_VERSION_1_4 AGL_API(void, BlendFuncSeparate, (GLenum, GLenum, GLenum, GLenum)) AGL_API(void, FogCoordf, (GLfloat)) AGL_API(void, FogCoordfv, (const GLfloat *)) AGL_API(void, FogCoordd, (GLdouble)) AGL_API(void, FogCoorddv, (const GLdouble *)) AGL_API(void, FogCoordPointer, (GLenum, GLsizei, const GLvoid *)) AGL_API(void, MultiDrawArrays, (GLenum, GLint *, GLsizei *, GLsizei)) AGL_API(void, MultiDrawElements, (GLenum, const GLsizei *, GLenum, const GLvoid* *, GLsizei)) AGL_API(void, PointParameterf, (GLenum, GLfloat)) AGL_API(void, PointParameterfv, (GLenum, const GLfloat *)) AGL_API(void, PointParameteri, (GLenum, GLint)) AGL_API(void, PointParameteriv, (GLenum, const GLint *)) AGL_API(void, SecondaryColor3b, (GLbyte, GLbyte, GLbyte)) AGL_API(void, SecondaryColor3bv, (const GLbyte *)) AGL_API(void, SecondaryColor3d, (GLdouble, GLdouble, GLdouble)) AGL_API(void, SecondaryColor3dv, (const GLdouble *)) AGL_API(void, SecondaryColor3f, (GLfloat, GLfloat, GLfloat)) AGL_API(void, SecondaryColor3fv, (const GLfloat *)) AGL_API(void, SecondaryColor3i, (GLint, GLint, GLint)) AGL_API(void, SecondaryColor3iv, (const GLint *)) AGL_API(void, SecondaryColor3s, (GLshort, GLshort, GLshort)) AGL_API(void, SecondaryColor3sv, (const GLshort *)) AGL_API(void, SecondaryColor3ub, (GLubyte, GLubyte, GLubyte)) AGL_API(void, SecondaryColor3ubv, (const GLubyte *)) AGL_API(void, SecondaryColor3ui, (GLuint, GLuint, GLuint)) AGL_API(void, SecondaryColor3uiv, (const GLuint *)) AGL_API(void, SecondaryColor3us, (GLushort, GLushort, GLushort)) AGL_API(void, SecondaryColor3usv, (const GLushort *)) AGL_API(void, SecondaryColorPointer, (GLint, GLenum, GLsizei, const GLvoid *)) AGL_API(void, WindowPos2d, (GLdouble, GLdouble)) AGL_API(void, WindowPos2dv, (const GLdouble *)) AGL_API(void, WindowPos2f, (GLfloat, GLfloat)) AGL_API(void, WindowPos2fv, (const GLfloat *)) AGL_API(void, WindowPos2i, (GLint, GLint)) AGL_API(void, WindowPos2iv, (const GLint *)) AGL_API(void, WindowPos2s, (GLshort, GLshort)) AGL_API(void, WindowPos2sv, (const GLshort *)) AGL_API(void, WindowPos3d, (GLdouble, GLdouble, GLdouble)) AGL_API(void, WindowPos3dv, (const GLdouble *)) AGL_API(void, WindowPos3f, (GLfloat, GLfloat, GLfloat)) AGL_API(void, WindowPos3fv, (const GLfloat *)) AGL_API(void, WindowPos3i, (GLint, GLint, GLint)) AGL_API(void, WindowPos3iv, (const GLint *)) AGL_API(void, WindowPos3s, (GLshort, GLshort, GLshort)) AGL_API(void, WindowPos3sv, (const GLshort *)) #endif #if defined AGL_VERSION_1_5 AGL_API(void, BindBuffer, (GLenum, GLuint)) AGL_API(void, DeleteBuffers, (GLsizei, const GLuint *)) AGL_API(void, GenBuffers, (GLsizei, GLuint *)) AGL_API(GLboolean, IsBuffer, (GLuint)) AGL_API(void, BufferData, (GLenum, GLsizeiptr, const GLvoid *, GLenum)) AGL_API(void, BufferSubData, (GLenum, GLintptr, GLsizeiptr, const GLvoid *)) AGL_API(void, GetBufferSubData, (GLenum, GLintptr, GLsizeiptr, GLvoid *)) AGL_API(GLvoid*, MapBuffer, (GLenum, GLenum)) AGL_API(GLboolean, UnmapBuffer, (GLenum)) AGL_API(void, GetBufferParameteriv, (GLenum, GLenum, GLint *)) AGL_API(void, GetBufferPointerv, (GLenum, GLenum, GLvoid* *)) AGL_API(void, GenQueries, (GLsizei, GLuint *)) AGL_API(void, DeleteQueries, (GLsizei, const GLuint *)) AGL_API(GLboolean, IsQuery, (GLuint)) AGL_API(void, BeginQuery, (GLenum, GLuint)) AGL_API(void, EndQuery, (GLenum)) AGL_API(void, GetQueryiv, (GLenum, GLenum, GLint *)) AGL_API(void, GetQueryObjectiv, (GLuint, GLenum, GLint *)) AGL_API(void, GetQueryObjectuiv, (GLuint, GLenum, GLuint *)) #endif #if defined AGL_VERSION_2_0 AGL_API(GLuint, CreateProgram, (void)) AGL_API(GLuint, CreateShader, (GLenum)) AGL_API(void, DeleteProgram, (GLuint)) AGL_API(void, DeleteShader, (GLuint)) AGL_API(void, AttachShader, (GLuint, GLuint)) AGL_API(void, DetachShader, (GLuint, GLuint)) AGL_API(void, ShaderSource, (GLuint, GLsizei, const GLchar **, const GLint *)) AGL_API(void, CompileShader, (GLuint)) AGL_API(GLboolean, IsProgram, (GLuint)) AGL_API(GLboolean, IsShader, (GLuint)) AGL_API(void, LinkProgram, (GLuint)) AGL_API(void, UseProgram, (GLuint)) AGL_API(void, ValidateProgram, (GLuint)) AGL_API(void, Uniform1f, (GLint, GLfloat)) AGL_API(void, Uniform2f, (GLint, GLfloat, GLfloat)) AGL_API(void, Uniform3f, (GLint, GLfloat, GLfloat, GLfloat)) AGL_API(void, Uniform4f, (GLint, GLfloat, GLfloat, GLfloat, GLfloat)) AGL_API(void, Uniform1i, (GLint, GLint)) AGL_API(void, Uniform2i, (GLint, GLint, GLint)) AGL_API(void, Uniform3i, (GLint, GLint, GLint, GLint)) AGL_API(void, Uniform4i, (GLint, GLint, GLint, GLint, GLint)) AGL_API(void, Uniform1fv, (GLint, GLsizei, GLfloat *)) AGL_API(void, Uniform2fv, (GLint, GLsizei, GLfloat *)) AGL_API(void, Uniform3fv, (GLint, GLsizei, GLfloat *)) AGL_API(void, Uniform4fv, (GLint, GLsizei, GLfloat *)) AGL_API(void, Uniform1iv, (GLint, GLsizei, GLint *)) AGL_API(void, Uniform2iv, (GLint, GLsizei, GLint *)) AGL_API(void, Uniform3iv, (GLint, GLsizei, GLint *)) AGL_API(void, Uniform4iv, (GLint, GLsizei, GLint *)) AGL_API(void, UniformMatrix2fv, (GLint, GLsizei, GLboolean, GLfloat *)) AGL_API(void, UniformMatrix3fv, (GLint, GLsizei, GLboolean, GLfloat *)) AGL_API(void, UniformMatrix4fv, (GLint, GLsizei, GLboolean, GLfloat *)) AGL_API(void, GetShaderfv, (GLuint, GLenum, GLfloat *)) AGL_API(void, GetShaderiv, (GLuint, GLenum, GLint *)) AGL_API(void, GetProgramfv, (GLuint, GLenum, GLfloat *)) AGL_API(void, GetProgramiv, (GLuint, GLenum, GLint *)) AGL_API(void, GetShaderInfoLog, (GLuint, GLsizei, GLsizei *, GLchar *)) AGL_API(void, GetProgramInfoLog, (GLuint, GLsizei, GLsizei *, GLchar *)) AGL_API(void, GetAttachedShaders, (GLuint, GLsizei, GLsizei *, GLuint *)) AGL_API(GLint, GetUniformLocation, (GLuint, const GLchar *)) AGL_API(void, GetActiveUniform, (GLuint, GLuint, GLsizei, GLsizei *, GLint *, GLenum *, GLchar *)) AGL_API(void, GetUniformfv, (GLuint, GLint, GLfloat *)) AGL_API(void, GetUniformiv, (GLuint, GLint, GLint *)) AGL_API(void, GetShaderSource, (GLuint, GLsizei, GLsizei *, GLchar *)) AGL_API(void, VertexAttrib1f, (GLuint, GLfloat)) AGL_API(void, VertexAttrib1s, (GLuint, GLshort)) AGL_API(void, VertexAttrib1d, (GLuint, GLdouble)) AGL_API(void, VertexAttrib2f, (GLuint, GLfloat, GLfloat)) AGL_API(void, VertexAttrib2s, (GLuint, GLshort, GLshort)) AGL_API(void, VertexAttrib2d, (GLuint, GLdouble, GLdouble)) AGL_API(void, VertexAttrib3f, (GLuint, GLfloat, GLfloat, GLfloat)) AGL_API(void, VertexAttrib3s, (GLuint, GLshort, GLshort, GLshort)) AGL_API(void, VertexAttrib3d, (GLuint, GLdouble, GLdouble, GLdouble)) AGL_API(void, VertexAttrib4f, (GLuint, GLfloat, GLfloat, GLfloat, GLfloat)) AGL_API(void, VertexAttrib4s, (GLuint, GLshort, GLshort, GLshort, GLshort)) AGL_API(void, VertexAttrib4d, (GLuint, GLdouble,GLdouble,GLdouble,GLdouble)) AGL_API(void, VertexAttrib4Nub, (GLuint, GLubyte, GLubyte, GLubyte, GLubyte)) AGL_API(void, VertexAttrib1fv, (GLuint, const GLfloat *)) AGL_API(void, VertexAttrib1sv, (GLuint, const GLshort *)) AGL_API(void, VertexAttrib1dv, (GLuint, const GLdouble *)) AGL_API(void, VertexAttrib2fv, (GLuint, const GLfloat *)) AGL_API(void, VertexAttrib2sv, (GLuint, const GLshort *)) AGL_API(void, VertexAttrib2dv, (GLuint, const GLdouble *)) AGL_API(void, VertexAttrib3fv, (GLuint, const GLfloat *)) AGL_API(void, VertexAttrib3sv, (GLuint, const GLshort *)) AGL_API(void, VertexAttrib3dv, (GLuint, const GLdouble *)) AGL_API(void, VertexAttrib4fv, (GLuint, const GLfloat *)) AGL_API(void, VertexAttrib4sv, (GLuint, const GLshort *)) AGL_API(void, VertexAttrib4dv, (GLuint, const GLdouble *)) AGL_API(void, VertexAttrib4iv, (GLuint, const GLint *)) AGL_API(void, VertexAttrib4bv, (GLuint, const GLbyte *)) AGL_API(void, VertexAttrib4ubv, (GLuint, const GLubyte *)) AGL_API(void, VertexAttrib4usv, (GLuint, const GLushort *)) AGL_API(void, VertexAttrib4uiv, (GLuint, const GLuint *)) AGL_API(void, VertexAttrib4Nbv, (GLuint, const GLbyte *)) AGL_API(void, VertexAttrib4Nsv, (GLuint, const GLshort *)) AGL_API(void, VertexAttrib4Niv, (GLuint, const GLint *)) AGL_API(void, VertexAttrib4Nubv, (GLuint, const GLubyte *)) AGL_API(void, VertexAttrib4Nusv, (GLuint, const GLushort *)) AGL_API(void, VertexAttrib4Nuiv, (GLuint, const GLuint *)) AGL_API(void, VertexAttribPointer,(GLuint, GLint, GLenum, GLboolean, GLsizei, const GLvoid *)) AGL_API(void, EnableVertexAttribArray, (GLuint)) AGL_API(void, DisableVertexAttribArray, (GLuint)) AGL_API(void, BindAttribLocation, (GLuint, GLuint, const GLchar *)) AGL_API(void, GetActiveAttrib, (GLuint, GLuint, GLsizei, GLsizei *, GLint *, GLenum *, GLchar *)) AGL_API(GLint, GetAttribLocation, (GLuint, const GLchar *)) AGL_API(void, GetVertexAttribdv, (GLuint, GLenum, GLdouble *)) AGL_API(void, GetVertexAttribfv, (GLuint, GLenum, GLfloat *)) AGL_API(void, GetVertexAttribiv, (GLuint, GLenum, GLint *)) AGL_API(void, GetVertexAttribPointerv, (GLuint, GLenum, GLvoid **)) AGL_API(void, DrawBuffers, (GLsizei n, const GLenum *)) AGL_API(void, StencilOpSeparate, (GLenum, GLenum, GLenum, GLenum)) AGL_API(void, StencilFuncSeparate, (GLenum, GLenum, GLint, GLuint)) #endif #if defined AGL_VERSION_2_1 AGL_API(void, UniformMatrix2x3fv, (GLint, GLsizei, GLboolean, const GLfloat *)) AGL_API(void, UniformMatrix3x2fv, (GLint, GLsizei, GLboolean, const GLfloat *)) AGL_API(void, UniformMatrix2x4fv, (GLint, GLsizei, GLboolean, const GLfloat *)) AGL_API(void, UniformMatrix4x2fv, (GLint, GLsizei, GLboolean, const GLfloat *)) AGL_API(void, UniformMatrix3x4fv, (GLint, GLsizei, GLboolean, const GLfloat *)) AGL_API(void, UniformMatrix4x3fv, (GLint, GLsizei, GLboolean, const GLfloat *)) #endif #if defined AGL_VERSION_3_0 /* OpenGL 3.0 also reuses entry points from these extensions: */ /* ARB_framebuffer_object */ /* ARB_map_buffer_range */ /* ARB_vertex_array_object */ AGL_API(void, ColorMaski, (GLuint, GLboolean, GLboolean, GLboolean, GLboolean)) AGL_API(void, GetBooleani_v, (GLenum, GLuint, GLboolean *)) AGL_API(void, GetIntegeri_v, (GLenum, GLuint, GLint *)) AGL_API(void, Enablei, (GLenum, GLuint)) AGL_API(void, Disablei, (GLenum, GLuint)) AGL_API(GLboolean, IsEnabledi, (GLenum, GLuint)) AGL_API(void, BeginTransformFeedback, (GLenum)) AGL_API(void, EndTransformFeedback, (void)) AGL_API(void, BindBufferRange, (GLenum, GLuint, GLuint, GLintptr, GLsizeiptr)) AGL_API(void, BindBufferBase, (GLenum, GLuint, GLuint)) AGL_API(void, TransformFeedbackVaryings, (GLuint, GLsizei, const GLint *, GLenum)) AGL_API(void, GetTransformFeedbackVarying, (GLuint, GLuint, GLint *)) AGL_API(void, ClampColor, (GLenum, GLenum)) AGL_API(void, BeginConditionalRender, (GLuint, GLenum)) AGL_API(void, EndConditionalRender, (void)) AGL_API(void, VertexAttribI1i, (GLuint, GLint)) AGL_API(void, VertexAttribI2i, (GLuint, GLint, GLint)) AGL_API(void, VertexAttribI3i, (GLuint, GLint, GLint, GLint)) AGL_API(void, VertexAttribI4i, (GLuint, GLint, GLint, GLint, GLint)) AGL_API(void, VertexAttribI1ui, (GLuint, GLuint)) AGL_API(void, VertexAttribI2ui, (GLuint, GLuint, GLuint)) AGL_API(void, VertexAttribI3ui, (GLuint, GLuint, GLuint, GLuint)) AGL_API(void, VertexAttribI4ui, (GLuint, GLuint, GLuint, GLuint, GLuint)) AGL_API(void, VertexAttribI1iv, (GLuint, const GLint *)) AGL_API(void, VertexAttribI2iv, (GLuint, const GLint *)) AGL_API(void, VertexAttribI3iv, (GLuint, const GLint *)) AGL_API(void, VertexAttribI4iv, (GLuint, const GLint *)) AGL_API(void, VertexAttribI1uiv, (GLuint, const GLuint *)) AGL_API(void, VertexAttribI2uiv, (GLuint, const GLuint *)) AGL_API(void, VertexAttribI3uiv, (GLuint, const GLuint *)) AGL_API(void, VertexAttribI4uiv, (GLuint, const GLuint *)) AGL_API(void, VertexAttribI4bv, (GLuint, const GLbyte *)) AGL_API(void, VertexAttribI4sv, (GLuint, const GLshort *)) AGL_API(void, VertexAttribI4ubv, (GLuint, const GLubyte *)) AGL_API(void, VertexAttribI4usv, (GLuint, const GLushort *)) AGL_API(void, VertexAttribIPointer, (GLuint, GLint, GLenum, GLsizei, const GLvoid *)) AGL_API(void, GetVertexAttribIiv, (GLuint, GLenum, GLint *)) AGL_API(void, GetVertexAttribIuiv, (GLuint, GLenum, GLuint *)) AGL_API(void, GetUniformuiv, (GLuint, GLint, GLuint *)) AGL_API(void, BindFragDataLocation, (GLuint, GLuint, const GLchar *)) AGL_API(GLint, GetFragDataLocation, (GLuint, const GLchar *)) AGL_API(void, Uniform1ui, (GLint, GLuint)) AGL_API(void, Uniform2ui, (GLint, GLuint, GLuint)) AGL_API(void, Uniform3ui, (GLint, GLuint, GLuint, GLuint)) AGL_API(void, Uniform4ui, (GLint, GLuint, GLuint, GLuint, GLuint)) AGL_API(void, Uniform1uiv, (GLint, GLsizei, const GLuint *)) AGL_API(void, Uniform2uiv, (GLint, GLsizei, const GLuint *)) AGL_API(void, Uniform3uiv, (GLint, GLsizei, const GLuint *)) AGL_API(void, Uniform4uiv, (GLint, GLsizei, const GLuint *)) AGL_API(void, TexParameterIiv, (GLenum, GLenum, const GLint *)) AGL_API(void, TexParameterIuiv, (GLenum, GLenum, const GLuint *)) AGL_API(void, GetTexParameterIiv, (GLenum, GLenum, GLint *)) AGL_API(void, GetTexParameterIuiv, (GLenum, GLenum, GLuint *)) AGL_API(void, ClearBufferiv, (GLenum, GLint, const GLint *)) AGL_API(void, ClearBufferuiv, (GLenum, GLint, const GLuint *)) AGL_API(void, ClearBufferfv, (GLenum, GLint, const GLfloat *)) AGL_API(void, ClearBufferfi, (GLenum, GLint, GLfloat, GLint)) AGL_API(const GLubyte *, GetStringi, (GLenum, GLuint)) #endif /* */ /* */ #ifdef AGL_ARB_multitexture AGL_API(void, ActiveTextureARB, (GLenum)) AGL_API(void, ClientActiveTextureARB, (GLenum)) AGL_API(void, MultiTexCoord1dARB, (GLenum, GLdouble)) AGL_API(void, MultiTexCoord1dvARB, (GLenum, const GLdouble *)) AGL_API(void, MultiTexCoord1fARB, (GLenum, GLfloat)) AGL_API(void, MultiTexCoord1fvARB, (GLenum, const GLfloat *)) AGL_API(void, MultiTexCoord1iARB, (GLenum, GLint)) AGL_API(void, MultiTexCoord1ivARB, (GLenum, const GLint *)) AGL_API(void, MultiTexCoord1sARB, (GLenum, GLshort)) AGL_API(void, MultiTexCoord1svARB, (GLenum, const GLshort *)) AGL_API(void, MultiTexCoord2dARB, (GLenum, GLdouble, GLdouble)) AGL_API(void, MultiTexCoord2dvARB, (GLenum, const GLdouble *)) AGL_API(void, MultiTexCoord2fARB, (GLenum, GLfloat, GLfloat)) AGL_API(void, MultiTexCoord2fvARB, (GLenum, const GLfloat *)) AGL_API(void, MultiTexCoord2iARB, (GLenum, GLint, GLint)) AGL_API(void, MultiTexCoord2ivARB, (GLenum, const GLint *)) AGL_API(void, MultiTexCoord2sARB, (GLenum, GLshort, GLshort)) AGL_API(void, MultiTexCoord2svARB, (GLenum, const GLshort *)) AGL_API(void, MultiTexCoord3dARB, (GLenum, GLdouble, GLdouble, GLdouble)) AGL_API(void, MultiTexCoord3dvARB, (GLenum, const GLdouble *)) AGL_API(void, MultiTexCoord3fARB, (GLenum, GLfloat, GLfloat, GLfloat)) AGL_API(void, MultiTexCoord3fvARB, (GLenum, const GLfloat *)) AGL_API(void, MultiTexCoord3iARB, (GLenum, GLint, GLint, GLint)) AGL_API(void, MultiTexCoord3ivARB, (GLenum, const GLint *)) AGL_API(void, MultiTexCoord3sARB, (GLenum, GLshort, GLshort, GLshort)) AGL_API(void, MultiTexCoord3svARB, (GLenum, const GLshort *)) AGL_API(void, MultiTexCoord4dARB, (GLenum, GLdouble, GLdouble, GLdouble, GLdouble)) AGL_API(void, MultiTexCoord4dvARB, (GLenum, const GLdouble *)) AGL_API(void, MultiTexCoord4fARB, (GLenum, GLfloat, GLfloat, GLfloat, GLfloat)) AGL_API(void, MultiTexCoord4fvARB, (GLenum, const GLfloat *)) AGL_API(void, MultiTexCoord4iARB, (GLenum, GLint, GLint, GLint, GLint)) AGL_API(void, MultiTexCoord4ivARB, (GLenum, const GLint *)) AGL_API(void, MultiTexCoord4sARB, (GLenum, GLshort, GLshort, GLshort, GLshort)) AGL_API(void, MultiTexCoord4svARB, (GLenum, const GLshort *)) #endif #if defined AGL_ARB_transpose_matrix AGL_API(void, LoadTransposeMatrixfARB, (const GLfloat *)) AGL_API(void, LoadTransposeMatrixdARB, (const GLdouble *)) AGL_API(void, MultTransposeMatrixfARB, (const GLfloat *)) AGL_API(void, MultTransposeMatrixdARB, (const GLdouble *)) #endif #if defined AGL_ARB_multisample AGL_API(void, SampleCoverageARB, (GLclampf, GLboolean)) #endif #if defined AGL_ARB_texture_compression AGL_API(void, CompressedTexImage3DARB, (GLenum, GLint, GLenum, GLsizei, GLsizei, GLsizei, GLint, GLsizei, const GLvoid *)) AGL_API(void, CompressedTexImage2DARB, (GLenum, GLint, GLenum, GLsizei, GLsizei, GLint, GLsizei, const GLvoid *)) AGL_API(void, CompressedTexImage1DARB, (GLenum, GLint, GLenum, GLsizei, GLint, GLsizei, const GLvoid *)) AGL_API(void, CompressedTexSubImage3DARB, (GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLsizei, const GLvoid *)) AGL_API(void, CompressedTexSubImage2DARB, (GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLsizei, const GLvoid *)) AGL_API(void, CompressedTexSubImage1DARB, (GLenum, GLint, GLint, GLsizei, GLenum, GLsizei, const GLvoid *)) AGL_API(void, GetCompressedTexImageARB, (GLenum, GLint, GLvoid *)) #endif #if defined AGL_ARB_point_parameters AGL_API(void, PointParameterfARB, (GLenum, GLfloat)) AGL_API(void, PointParameterfvARB, (GLenum, const GLfloat *)) #endif #if defined AGL_ARB_vertex_blend AGL_API(void, WeightbvARB, (GLint, const GLbyte *)) AGL_API(void, WeightsvARB, (GLint, const GLshort *)) AGL_API(void, WeightivARB, (GLint, const GLint *)) AGL_API(void, WeightfvARB, (GLint, const GLfloat *)) AGL_API(void, WeightdvARB, (GLint, const GLdouble *)) AGL_API(void, WeightubvARB, (GLint, const GLubyte *)) AGL_API(void, WeightusvARB, (GLint, const GLushort *)) AGL_API(void, WeightuivARB, (GLint, const GLuint *)) AGL_API(void, WeightPointerARB, (GLint, GLenum, GLsizei, const GLvoid *)) AGL_API(void, VertexBlendARB, (GLint)) #endif #if defined AGL_ARB_matrix_palette AGL_API(void, CurrentPaletteMatrixARB, (GLint)) AGL_API(void, MatrixIndexubvARB, (GLint, const GLubyte *)) AGL_API(void, MatrixIndexusvARB, (GLint, const GLushort *)) AGL_API(void, MatrixIndexuivARB, (GLint, const GLuint *)) AGL_API(void, MatrixIndexPointerARB, (GLint, GLenum, GLsizei, const GLvoid *)) #endif #if defined AGL_ARB_window_pos AGL_API(void, WindowPos2dARB, (GLdouble, GLdouble)) AGL_API(void, WindowPos2dvARB, (const GLdouble *)) AGL_API(void, WindowPos2fARB, (GLfloat, GLfloat)) AGL_API(void, WindowPos2fvARB, (const GLfloat *)) AGL_API(void, WindowPos2iARB, (GLint, GLint)) AGL_API(void, WindowPos2ivARB, (const GLint *)) AGL_API(void, WindowPos2sARB, (GLshort, GLshort)) AGL_API(void, WindowPos2svARB, (const GLshort *)) AGL_API(void, WindowPos3dARB, (GLdouble, GLdouble, GLdouble)) AGL_API(void, WindowPos3dvARB, (const GLdouble *)) AGL_API(void, WindowPos3fARB, (GLfloat, GLfloat, GLfloat)) AGL_API(void, WindowPos3fvARB, (const GLfloat *)) AGL_API(void, WindowPos3iARB, (GLint, GLint, GLint)) AGL_API(void, WindowPos3ivARB, (const GLint *)) AGL_API(void, WindowPos3sARB, (GLshort, GLshort, GLshort)) AGL_API(void, WindowPos3svARB, (const GLshort *)) #endif #if defined AGL_ARB_vertex_program AGL_API(void, VertexAttrib1dARB, (GLuint, GLdouble)) AGL_API(void, VertexAttrib1dvARB, (GLuint, const GLdouble *)) AGL_API(void, VertexAttrib1fARB, (GLuint, GLfloat)) AGL_API(void, VertexAttrib1fvARB, (GLuint, const GLfloat *)) AGL_API(void, VertexAttrib1sARB, (GLuint, GLshort)) AGL_API(void, VertexAttrib1svARB, (GLuint, const GLshort *)) AGL_API(void, VertexAttrib2dARB, (GLuint, GLdouble, GLdouble)) AGL_API(void, VertexAttrib2dvARB, (GLuint, const GLdouble *)) AGL_API(void, VertexAttrib2fARB, (GLuint, GLfloat, GLfloat)) AGL_API(void, VertexAttrib2fvARB, (GLuint, const GLfloat *)) AGL_API(void, VertexAttrib2sARB, (GLuint, GLshort, GLshort)) AGL_API(void, VertexAttrib2svARB, (GLuint, const GLshort *)) AGL_API(void, VertexAttrib3dARB, (GLuint, GLdouble, GLdouble, GLdouble)) AGL_API(void, VertexAttrib3dvARB, (GLuint, const GLdouble *)) AGL_API(void, VertexAttrib3fARB, (GLuint, GLfloat, GLfloat, GLfloat)) AGL_API(void, VertexAttrib3fvARB, (GLuint, const GLfloat *)) AGL_API(void, VertexAttrib3sARB, (GLuint, GLshort, GLshort, GLshort)) AGL_API(void, VertexAttrib3svARB, (GLuint, const GLshort *)) AGL_API(void, VertexAttrib4NbvARB, (GLuint, const GLbyte *)) AGL_API(void, VertexAttrib4NivARB, (GLuint, const GLint *)) AGL_API(void, VertexAttrib4NsvARB, (GLuint, const GLshort *)) AGL_API(void, VertexAttrib4NubARB, (GLuint, GLubyte, GLubyte, GLubyte, GLubyte)) AGL_API(void, VertexAttrib4NubvARB, (GLuint, const GLubyte *)) AGL_API(void, VertexAttrib4NuivARB, (GLuint, const GLuint *)) AGL_API(void, VertexAttrib4NusvARB, (GLuint, const GLushort *)) AGL_API(void, VertexAttrib4bvARB, (GLuint, const GLbyte *)) AGL_API(void, VertexAttrib4dARB, (GLuint, GLdouble, GLdouble, GLdouble, GLdouble)) AGL_API(void, VertexAttrib4dvARB, (GLuint, const GLdouble *)) AGL_API(void, VertexAttrib4fARB, (GLuint, GLfloat, GLfloat, GLfloat, GLfloat)) AGL_API(void, VertexAttrib4fvARB, (GLuint, const GLfloat *)) AGL_API(void, VertexAttrib4ivARB, (GLuint, const GLint *)) AGL_API(void, VertexAttrib4sARB, (GLuint, GLshort, GLshort, GLshort, GLshort)) AGL_API(void, VertexAttrib4svARB, (GLuint, const GLshort *)) AGL_API(void, VertexAttrib4ubvARB, (GLuint, const GLubyte *)) AGL_API(void, VertexAttrib4uivARB, (GLuint, const GLuint *)) AGL_API(void, VertexAttrib4usvARB, (GLuint, const GLushort *)) AGL_API(void, VertexAttribPointerARB, (GLuint, GLint, GLenum, GLboolean, GLsizei, const GLvoid *)) AGL_API(void, EnableVertexAttribArrayARB, (GLuint)) AGL_API(void, DisableVertexAttribArrayARB, (GLuint)) AGL_API(void, ProgramStringARB, (GLenum, GLenum, GLsizei, const GLvoid *)) AGL_API(void, BindProgramARB, (GLenum, GLuint)) AGL_API(void, DeleteProgramsARB, (GLsizei, const GLuint *)) AGL_API(void, GenProgramsARB, (GLsizei, GLuint *)) AGL_API(void, ProgramEnvParameter4dARB, (GLenum, GLuint, GLdouble, GLdouble, GLdouble, GLdouble)) AGL_API(void, ProgramEnvParameter4dvARB, (GLenum, GLuint, const GLdouble *)) AGL_API(void, ProgramEnvParameter4fARB, (GLenum, GLuint, GLfloat, GLfloat, GLfloat, GLfloat)) AGL_API(void, ProgramEnvParameter4fvARB, (GLenum, GLuint, const GLfloat *)) AGL_API(void, ProgramLocalParameter4dARB, (GLenum, GLuint, GLdouble, GLdouble, GLdouble, GLdouble)) AGL_API(void, ProgramLocalParameter4dvARB, (GLenum, GLuint, const GLdouble *)) AGL_API(void, ProgramLocalParameter4fARB, (GLenum, GLuint, GLfloat, GLfloat, GLfloat, GLfloat)) AGL_API(void, ProgramLocalParameter4fvARB, (GLenum, GLuint, const GLfloat *)) AGL_API(void, GetProgramEnvParameterdvARB, (GLenum, GLuint, GLdouble *)) AGL_API(void, GetProgramEnvParameterfvARB, (GLenum, GLuint, GLfloat *)) AGL_API(void, GetProgramLocalParameterdvARB, (GLenum, GLuint, GLdouble *)) AGL_API(void, GetProgramLocalParameterfvARB, (GLenum, GLuint, GLfloat *)) AGL_API(void, GetProgramivARB, (GLenum, GLenum, GLint *)) AGL_API(void, GetProgramStringARB, (GLenum, GLenum, GLvoid *)) AGL_API(void, GetVertexAttribdvARB, (GLuint, GLenum, GLdouble *)) AGL_API(void, GetVertexAttribfvARB, (GLuint, GLenum, GLfloat *)) AGL_API(void, GetVertexAttribivARB, (GLuint, GLenum, GLint *)) AGL_API(void, GetVertexAttribPointervARB, (GLuint, GLenum, GLvoid* *)) AGL_API(GLboolean, IsProgramARB, (GLuint)) #endif #if defined AGL_ARB_vertex_buffer_object AGL_API(void, BindBufferARB, (GLenum, GLuint)) AGL_API(void, DeleteBuffersARB, (GLsizei, const GLuint *)) AGL_API(void, GenBuffersARB, (GLsizei, GLuint *)) AGL_API(GLboolean, IsBufferARB, (GLuint)) AGL_API(void, BufferDataARB, (GLenum, GLsizeiptrARB, const GLvoid *, GLenum)) AGL_API(void, BufferSubDataARB, (GLenum, GLintptrARB, GLsizeiptrARB, const GLvoid *)) AGL_API(void, GetBufferSubDataARB, (GLenum, GLintptrARB, GLsizeiptrARB, GLvoid *)) AGL_API(GLvoid*, MapBufferARB, (GLenum, GLenum)) AGL_API(GLboolean, UnmapBufferARB, (GLenum)) AGL_API(void, GetBufferParameterivARB, (GLenum, GLenum, GLint *)) AGL_API(void, GetBufferPointervARB, (GLenum, GLenum, GLvoid* *)) #endif #if defined AGL_ARB_occlusion_query AGL_API(void, GenQueriesARB, (GLsizei, GLuint *)) AGL_API(void, DeleteQueriesARB, (GLsizei, const GLuint *)) AGL_API(GLboolean, IsQueryARB, (GLuint)) AGL_API(void, BeginQueryARB, (GLenum, GLuint)) AGL_API(void, EndQueryARB, (GLenum)) AGL_API(void, GetQueryivARB, (GLenum, GLenum, GLint *)) AGL_API(void, GetQueryObjectivARB, (GLuint, GLenum, GLint *)) AGL_API(void, GetQueryObjectuivARB, (GLuint, GLenum, GLuint *)) #endif #if defined AGL_ARB_shader_objects AGL_API(void, DeleteObjectARB, (GLhandleARB)) AGL_API(GLhandleARB, GetHandleARB, (GLenum)) AGL_API(void, DetachObjectARB, (GLhandleARB, GLhandleARB)) AGL_API(GLhandleARB, CreateShaderObjectARB, (GLenum)) AGL_API(void, ShaderSourceARB, (GLhandleARB, GLsizei, const GLcharARB **, const GLint *)) AGL_API(void, CompileShaderARB, (GLhandleARB)) AGL_API(GLhandleARB, CreateProgramObjectARB, (void)) AGL_API(void, AttachObjectARB, (GLhandleARB, GLhandleARB)) AGL_API(void, LinkProgramARB, (GLhandleARB)) AGL_API(void, UseProgramObjectARB, (GLhandleARB)) AGL_API(void, ValidateProgramARB, (GLhandleARB)) AGL_API(void, Uniform1fARB, (GLint, GLfloat)) AGL_API(void, Uniform2fARB, (GLint, GLfloat, GLfloat)) AGL_API(void, Uniform3fARB, (GLint, GLfloat, GLfloat, GLfloat)) AGL_API(void, Uniform4fARB, (GLint, GLfloat, GLfloat, GLfloat, GLfloat)) AGL_API(void, Uniform1iARB, (GLint, GLint)) AGL_API(void, Uniform2iARB, (GLint, GLint, GLint)) AGL_API(void, Uniform3iARB, (GLint, GLint, GLint, GLint)) AGL_API(void, Uniform4iARB, (GLint, GLint, GLint, GLint, GLint)) AGL_API(void, Uniform1fvARB, (GLint, GLsizei, GLfloat *)) AGL_API(void, Uniform2fvARB, (GLint, GLsizei, GLfloat *)) AGL_API(void, Uniform3fvARB, (GLint, GLsizei, GLfloat *)) AGL_API(void, Uniform4fvARB, (GLint, GLsizei, GLfloat *)) AGL_API(void, Uniform1ivARB, (GLint, GLsizei, GLint *)) AGL_API(void, Uniform2ivARB, (GLint, GLsizei, GLint *)) AGL_API(void, Uniform3ivARB, (GLint, GLsizei, GLint *)) AGL_API(void, Uniform4ivARB, (GLint, GLsizei, GLint *)) AGL_API(void, UniformMatrix2fvARB, (GLint, GLsizei, GLboolean, GLfloat *)) AGL_API(void, UniformMatrix3fvARB, (GLint, GLsizei, GLboolean, GLfloat *)) AGL_API(void, UniformMatrix4fvARB, (GLint, GLsizei, GLboolean, GLfloat *)) AGL_API(void, GetObjectParameterfvARB, (GLhandleARB, GLenum, GLfloat *)) AGL_API(void, GetObjectParameterivARB, (GLhandleARB, GLenum, GLint *)) AGL_API(void, GetInfoLogARB, (GLhandleARB, GLsizei, GLsizei *, GLcharARB *)) AGL_API(void, GetAttachedObjectsARB, (GLhandleARB, GLsizei, GLsizei *, GLhandleARB *)) AGL_API(GLint, GetUniformLocationARB, (GLhandleARB, const GLcharARB *)) AGL_API(void, GetActiveUniformARB, (GLhandleARB, GLuint, GLsizei, GLsizei *, GLint *, GLenum *, GLcharARB *)) AGL_API(void, GetUniformfvARB, (GLhandleARB, GLint, GLfloat *)) AGL_API(void, GetUniformivARB, (GLhandleARB, GLint, GLint *)) AGL_API(void, GetShaderSourceARB, (GLhandleARB, GLsizei, GLsizei *, GLcharARB *)) #endif #ifdef AGL_ARB_vertex_shader #ifndef GL_ARB_vertex_program AGL_API(void, VertexAttrib1fARB, (GLuint, GLfloat)) AGL_API(void, VertexAttrib1sARB, (GLuint, GLshort)) AGL_API(void, VertexAttrib1dARB, (GLuint, GLdouble)) AGL_API(void, VertexAttrib2fARB, (GLuint, GLfloat, GLfloat)) AGL_API(void, VertexAttrib2sARB, (GLuint, GLshort, GLshort)) AGL_API(void, VertexAttrib2dARB, (GLuint, GLdouble, GLdouble)) AGL_API(void, VertexAttrib3fARB, (GLuint, GLfloat, GLfloat, GLfloat)) AGL_API(void, VertexAttrib3sARB, (GLuint, GLshort, GLshort, GLshort)) AGL_API(void, VertexAttrib3dARB, (GLuint, GLdouble, GLdouble, GLdouble)) AGL_API(void, VertexAttrib4fARB, (GLuint, GLfloat, GLfloat, GLfloat, GLfloat)) AGL_API(void, VertexAttrib4sARB, (GLuint, GLshort, GLshort, GLshort, GLshort)) AGL_API(void, VertexAttrib4dARB, (GLuint, GLdouble, GLdouble, GLdouble, GLdouble)) AGL_API(void, VertexAttrib4NubARB, (GLuint, GLubyte, GLubyte, GLubyte, GLubyte)) AGL_API(void, VertexAttrib1fvARB, (GLuint, const GLfloat *)) AGL_API(void, VertexAttrib1svARB, (GLuint, const GLshort *)) AGL_API(void, VertexAttrib1dvARB, (GLuint, const GLdouble *)) AGL_API(void, VertexAttrib2fvARB, (GLuint, const GLfloat *)) AGL_API(void, VertexAttrib2svARB, (GLuint, const GLshort *)) AGL_API(void, VertexAttrib2dvARB, (GLuint, const GLdouble *)) AGL_API(void, VertexAttrib3fvARB, (GLuint, const GLfloat *)) AGL_API(void, VertexAttrib3svARB, (GLuint, const GLshort *)) AGL_API(void, VertexAttrib3dvARB, (GLuint, const GLdouble *)) AGL_API(void, VertexAttrib4fvARB, (GLuint, const GLfloat *)) AGL_API(void, VertexAttrib4svARB, (GLuint, const GLshort *)) AGL_API(void, VertexAttrib4dvARB, (GLuint, const GLdouble *)) AGL_API(void, VertexAttrib4ivARB, (GLuint, const GLint *)) AGL_API(void, VertexAttrib4bvARB, (GLuint, const GLbyte *)) AGL_API(void, VertexAttrib4ubvARB, (GLuint, const GLubyte *)) AGL_API(void, VertexAttrib4usvARB, (GLuint, const GLushort *)) AGL_API(void, VertexAttrib4uivARB, (GLuint, const GLuint *)) AGL_API(void, VertexAttrib4NbvARB, (GLuint, const GLbyte *)) AGL_API(void, VertexAttrib4NsvARB, (GLuint, const GLshort *)) AGL_API(void, VertexAttrib4NivARB, (GLuint, const GLint *)) AGL_API(void, VertexAttrib4NubvARB, (GLuint, const GLubyte *)) AGL_API(void, VertexAttrib4NusvARB, (GLuint, const GLushort *)) AGL_API(void, VertexAttrib4NuivARB, (GLuint, const GLuint *)) AGL_API(void, VertexAttribPointerARB, (GLuint, GLint, GLenum, GLboolean, GLsizei, const GLvoid *)) AGL_API(void, EnableVertexAttribArrayARB, (GLuint)) AGL_API(void, DisableVertexAttribArrayARB, (GLuint)) #endif AGL_API(void, BindAttribLocationARB, (GLhandleARB, GLuint, const GLcharARB *)) AGL_API(void, GetActiveAttribARB, (GLhandleARB, GLuint, GLsizei, GLsizei *, GLint *, GLenum *, GLcharARB *)) AGL_API(GLint, GetAttribLocationARB, (GLhandleARB, const GLcharARB *)) #ifndef GL_ARB_vertex_program AGL_API(void, GetVertexAttribdvARB, (GLuint, GLenum, GLdouble *)) AGL_API(void, GetVertexAttribfvARB, (GLuint, GLenum, GLfloat *)) AGL_API(void, GetVertexAttribivARB, (GLuint, GLenum, GLint *)) AGL_API(void, GetVertexAttribPointervARB, (GLuint, GLenum, GLvoid **)) #endif #endif #if defined AGL_ARB_draw_buffers AGL_API(void, DrawBuffersARB, (GLsizei n, const GLenum *bufs)) #endif #if defined AGL_ARB_color_buffer_float AGL_API(void, ClampColorARB, (GLenum, GLenum clamp)) #endif #if defined AGL_ARB_draw_instanced AGL_API(void, DrawArraysInstancedARB, (GLenum, GLint, GLsizei, GLsizei)) AGL_API(void, DrawElementsInstancedARB, (GLenum, GLsizei, GLenum, const GLvoid *, GLsizei)) #endif #if defined AGL_ARB_framebuffer_object AGL_API(GLboolean, IsRenderbuffer, (GLuint)) AGL_API(void, BindRenderbuffer, (GLenum, GLuint)) AGL_API(void, DeleteRenderbuffers, (GLsizei, const GLuint *)) AGL_API(void, GenRenderbuffers, (GLsizei, GLuint *)) AGL_API(void, RenderbufferStorage, (GLenum, GLenum, GLsizei, GLsizei)) AGL_API(void, GetRenderbufferParameteriv, (GLenum, GLenum, GLint *)) AGL_API(GLboolean, IsFramebuffer, (GLuint)) AGL_API(void, BindFramebuffer, (GLenum, GLuint)) AGL_API(void, DeleteFramebuffers, (GLsizei, const GLuint *)) AGL_API(void, GenFramebuffers, (GLsizei, GLuint *)) AGL_API(GLenum, CheckFramebufferStatus, (GLenum)) AGL_API(void, FramebufferTexture1D, (GLenum, GLenum, GLenum, GLuint, GLint)) AGL_API(void, FramebufferTexture2D, (GLenum, GLenum, GLenum, GLuint, GLint)) AGL_API(void, FramebufferTexture3D, (GLenum, GLenum, GLenum, GLuint, GLint, GLint)) AGL_API(void, FramebufferRenderbuffer, (GLenum, GLenum, GLenum, GLuint)) AGL_API(void, GetFramebufferAttachmentParameteriv, (GLenum, GLenum, GLenum, GLint *)) AGL_API(void, GenerateMipmap, (GLenum)) AGL_API(void, BlitFramebuffer, (GLint, GLint, GLint, GLint, GLint, GLint, GLint, GLint, GLbitfield, GLenum)) AGL_API(void, RenderbufferStorageMultisample, (GLenum, GLsizei, GLenum, GLsizei, GLsizei)) AGL_API(void, FramebufferTextureLayer, (GLenum, GLenum, GLuint, GLint, GLint)) #endif #if defined AGL_ARB_geometry_shader4 AGL_API(void, ProgramParameteriARB, (GLuint, GLenum, GLint)) AGL_API(void, FramebufferTextureARB, (GLenum, GLenum, GLuint, GLint)) AGL_API(void, FramebufferTextureLayerARB, (GLenum, GLenum, GLuint, GLint, GLint)) AGL_API(void, FramebufferTextureFaceARB, (GLenum, GLenum, GLuint, GLint, GLenum)) #endif #if defined AGL_ARB_instanced_arrays AGL_API(void, VertexAttribDivisor, (GLuint, GLuint)) #endif #if defined AGL_ARB_map_buffer_range AGL_API(void, MapBufferRange, (GLenum, GLintptr, GLsizeiptr, GLbitfield)) AGL_API(void, FlushMappedBufferRange, (GLenum, GLintptr, GLsizeiptr)) #endif #if defined AGL_ARB_texture_buffer_object AGL_API(void, TexBufferARB, (GLenum, GLenum, GLuint)) #endif #if defined AGL_ARB_vertex_array_object AGL_API(void, BindVertexArray, (GLuint)) AGL_API(void, DeleteVertexArrays, (GLsizei, const GLuint *)) AGL_API(void, GenVertexArrays, (GLsizei, GLuint *)) AGL_API(GLboolean, IsVertexArray, (GLuint)) #endif /* */ #if defined AGL_EXT_blend_color AGL_API(void, BlendColorEXT, (GLclampf, GLclampf, GLclampf, GLclampf)) #endif #if defined AGL_EXT_polygon_offset AGL_API(void, PolygonOffsetEXT, (GLfloat, GLfloat)) #endif #if defined AGL_EXT_texture3D AGL_API(void, TexImage3DEXT, (GLenum, GLint, GLenum, GLsizei, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid *)) AGL_API(void, TexSubImage3DEXT, (GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *)) #endif #if defined AGL_SGIS_texture_filter4 AGL_API(void, GetTexFilterFuncSGIS, (GLenum, GLenum, GLfloat *)) AGL_API(void, TexFilterFuncSGIS, (GLenum, GLenum, GLsizei, const GLfloat *)) #endif #if defined AGL_EXT_subtexture AGL_API(void, TexSubImage1DEXT, (GLenum, GLint, GLint, GLsizei, GLenum, GLenum, const GLvoid *)) AGL_API(void, TexSubImage2DEXT, (GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *)) #endif #if defined AGL_EXT_copy_texture AGL_API(void, CopyTexImage1DEXT, (GLenum, GLint, GLenum, GLint, GLint, GLsizei, GLint)) AGL_API(void, CopyTexImage2DEXT, (GLenum, GLint, GLenum, GLint, GLint, GLsizei, GLsizei, GLint)) AGL_API(void, CopyTexSubImage1DEXT, (GLenum, GLint, GLint, GLint, GLint, GLsizei)) AGL_API(void, CopyTexSubImage2DEXT, (GLenum, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei)) AGL_API(void, CopyTexSubImage3DEXT, (GLenum, GLint, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei)) #endif #if defined AGL_EXT_histogram AGL_API(void, GetHistogramEXT, (GLenum, GLboolean, GLenum, GLenum, GLvoid *)) AGL_API(void, GetHistogramParameterfvEXT, (GLenum, GLenum, GLfloat *)) AGL_API(void, GetHistogramParameterivEXT, (GLenum, GLenum, GLint *)) AGL_API(void, GetMinmaxEXT, (GLenum, GLboolean, GLenum, GLenum, GLvoid *)) AGL_API(void, GetMinmaxParameterfvEXT, (GLenum, GLenum, GLfloat *)) AGL_API(void, GetMinmaxParameterivEXT, (GLenum, GLenum, GLint *)) AGL_API(void, HistogramEXT, (GLenum, GLsizei, GLenum, GLboolean)) AGL_API(void, MinmaxEXT, (GLenum, GLenum, GLboolean)) AGL_API(void, ResetHistogramEXT, (GLenum)) AGL_API(void, ResetMinmaxEXT, (GLenum)) #endif #if defined AGL_EXT_convolution AGL_API(void, ConvolutionFilter1DEXT, (GLenum, GLenum, GLsizei, GLenum, GLenum, const GLvoid *)) AGL_API(void, ConvolutionFilter2DEXT, (GLenum, GLenum, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *)) AGL_API(void, ConvolutionParameterfEXT, (GLenum, GLenum, GLfloat)) AGL_API(void, ConvolutionParameterfvEXT, (GLenum, GLenum, const GLfloat *)) AGL_API(void, ConvolutionParameteriEXT, (GLenum, GLenum, GLint)) AGL_API(void, ConvolutionParameterivEXT, (GLenum, GLenum, const GLint *)) AGL_API(void, CopyConvolutionFilter1DEXT, (GLenum, GLenum, GLint, GLint, GLsizei)) AGL_API(void, CopyConvolutionFilter2DEXT, (GLenum, GLenum, GLint, GLint, GLsizei, GLsizei)) AGL_API(void, GetConvolutionFilterEXT, (GLenum, GLenum, GLenum, GLvoid *)) AGL_API(void, GetConvolutionParameterfvEXT, (GLenum, GLenum, GLfloat *)) AGL_API(void, GetConvolutionParameterivEXT, (GLenum, GLenum, GLint *)) AGL_API(void, GetSeparableFilterEXT, (GLenum, GLenum, GLenum, GLvoid *, GLvoid *, GLvoid *)) AGL_API(void, SeparableFilter2DEXT, (GLenum, GLenum, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *, const GLvoid *)) #endif #if defined AGL_SGI_color_table AGL_API(void, ColorTableSGI, (GLenum, GLenum, GLsizei, GLenum, GLenum, const GLvoid *)) AGL_API(void, ColorTableParameterfvSGI, (GLenum, GLenum, const GLfloat *)) AGL_API(void, ColorTableParameterivSGI, (GLenum, GLenum, const GLint *)) AGL_API(void, CopyColorTableSGI, (GLenum, GLenum, GLint, GLint, GLsizei)) AGL_API(void, GetColorTableSGI, (GLenum, GLenum, GLenum, GLvoid *)) AGL_API(void, GetColorTableParameterfvSGI, (GLenum, GLenum, GLfloat *)) AGL_API(void, GetColorTableParameterivSGI, (GLenum, GLenum, GLint *)) #endif #if defined AGL_SGIX_pixel_texture AGL_API(void, PixelTexGenSGIX, (GLenum)) #endif #if defined AGL_SGIS_pixel_texture AGL_API(void, PixelTexGenParameteriSGIS, (GLenum, GLint)) AGL_API(void, PixelTexGenParameterivSGIS, (GLenum, const GLint *)) AGL_API(void, PixelTexGenParameterfSGIS, (GLenum, GLfloat)) AGL_API(void, PixelTexGenParameterfvSGIS, (GLenum, const GLfloat *)) AGL_API(void, GetPixelTexGenParameterivSGIS, (GLenum, GLint *)) AGL_API(void, GetPixelTexGenParameterfvSGIS, (GLenum, GLfloat *)) #endif #if defined AGL_SGIS_texture4D AGL_API(void, TexImage4DSGIS, (GLenum, GLint, GLenum, GLsizei, GLsizei, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid *)) AGL_API(void, TexSubImage4DSGIS, (GLenum, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *)) #endif #if defined AGL_EXT_texture_object AGL_API(GLboolean, AreTexturesResidentEXT, (GLsizei, const GLuint *, GLboolean *)) AGL_API(void, BindTextureEXT, (GLenum, GLuint)) AGL_API(void, DeleteTexturesEXT, (GLsizei, const GLuint *)) AGL_API(void, GenTexturesEXT, (GLsizei, GLuint *)) AGL_API(GLboolean, IsTextureEXT, (GLuint)) AGL_API(void, PrioritizeTexturesEXT, (GLsizei, const GLuint *, const GLclampf *)) #endif #if defined AGL_SGIS_detail_texture AGL_API(void, DetailTexFuncSGIS, (GLenum, GLsizei, const GLfloat *)) AGL_API(void, GetDetailTexFuncSGIS, (GLenum, GLfloat *)) #endif #if defined AGL_SGIS_sharpen_texture AGL_API(void, SharpenTexFuncSGIS, (GLenum, GLsizei, const GLfloat *)) AGL_API(void, GetSharpenTexFuncSGIS, (GLenum, GLfloat *)) #endif #if defined AGL_SGIS_multisample AGL_API(void, SampleMaskSGIS, (GLclampf, GLboolean)) AGL_API(void, SamplePatternSGIS, (GLenum)) #endif #if defined AGL_EXT_vertex_array AGL_API(void, ArrayElementEXT, (GLint)) AGL_API(void, ColorPointerEXT, (GLint, GLenum, GLsizei, GLsizei, const GLvoid *)) AGL_API(void, DrawArraysEXT, (GLenum, GLint, GLsizei)) AGL_API(void, EdgeFlagPointerEXT, (GLsizei, GLsizei, const GLboolean *)) AGL_API(void, GetPointervEXT, (GLenum, GLvoid* *)) AGL_API(void, IndexPointerEXT, (GLenum, GLsizei, GLsizei, const GLvoid *)) AGL_API(void, NormalPointerEXT, (GLenum, GLsizei, GLsizei, const GLvoid *)) AGL_API(void, TexCoordPointerEXT, (GLint, GLenum, GLsizei, GLsizei, const GLvoid *)) AGL_API(void, VertexPointerEXT, (GLint, GLenum, GLsizei, GLsizei, const GLvoid *)) #endif #if defined AGL_EXT_blend_minmax AGL_API(void, BlendEquationEXT, (GLenum)) #endif #if defined AGL_SGIX_sprite AGL_API(void, SpriteParameterfSGIX, (GLenum, GLfloat)) AGL_API(void, SpriteParameterfvSGIX, (GLenum, const GLfloat *)) AGL_API(void, SpriteParameteriSGIX, (GLenum, GLint)) AGL_API(void, SpriteParameterivSGIX, (GLenum, const GLint *)) #endif #if defined AGL_EXT_point_parameters AGL_API(void, PointParameterfEXT, (GLenum, GLfloat)) AGL_API(void, PointParameterfvEXT, (GLenum, const GLfloat *)) #endif #if defined AGL_SGIS_point_parameters AGL_API(void, PointParameterfSGIS, (GLenum, GLfloat)) AGL_API(void, PointParameterfvSGIS, (GLenum, const GLfloat *)) #endif #if defined AGL_SGIX_instruments AGL_API(GLint, GetInstrumentsSGIX, (void)) AGL_API(void, InstrumentsBufferSGIX, (GLsizei, GLint *)) AGL_API(GLint, PollInstrumentsSGIX, (GLint *)) AGL_API(void, ReadInstrumentsSGIX, (GLint)) AGL_API(void, StartInstrumentsSGIX, (void)) AGL_API(void, StopInstrumentsSGIX, (GLint)) #endif #if defined AGL_SGIX_framezoom AGL_API(void, FrameZoomSGIX, (GLint)) #endif #if defined AGL_SGIX_tag_sample_buffer AGL_API(void, TagSampleBufferSGIX, (void)) #endif #if defined AGL_SGIX_polynomial_ffd AGL_API(void, DeformationMap3dSGIX, (GLenum, GLdouble, GLdouble, GLint, GLint, GLdouble, GLdouble, GLint, GLint, GLdouble, GLdouble, GLint, GLint, const GLdouble *)) AGL_API(void, DeformationMap3fSGIX, (GLenum, GLfloat, GLfloat, GLint, GLint, GLfloat, GLfloat, GLint, GLint, GLfloat, GLfloat, GLint, GLint, const GLfloat *)) AGL_API(void, DeformSGIX, (GLbitfield)) AGL_API(void, LoadIdentityDeformationMapSGIX, (GLbitfield)) #endif #if defined AGL_SGIX_reference_plane AGL_API(void, ReferencePlaneSGIX, (const GLdouble *)) #endif #if defined AGL_SGIX_flush_raster AGL_API(void, FlushRasterSGIX, (void)) #endif #if defined AGL_SGIS_fog_function AGL_API(void, FogFuncSGIS, (GLsizei, const GLfloat *)) AGL_API(void, GetFogFuncSGIS, (GLfloat *)) #endif #if defined AGL_HP_image_transform AGL_API(void, ImageTransformParameteriHP, (GLenum, GLenum, GLint)) AGL_API(void, ImageTransformParameterfHP, (GLenum, GLenum, GLfloat)) AGL_API(void, ImageTransformParameterivHP, (GLenum, GLenum, const GLint *)) AGL_API(void, ImageTransformParameterfvHP, (GLenum, GLenum, const GLfloat *)) AGL_API(void, GetImageTransformParameterivHP, (GLenum, GLenum, GLint *)) AGL_API(void, GetImageTransformParameterfvHP, (GLenum, GLenum, GLfloat *)) #endif #if defined AGL_EXT_color_subtable #ifndef GL_EXT_paletted_texture AGL_API(void, ColorSubTableEXT, (GLenum, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *)) #endif AGL_API(void, CopyColorSubTableEXT, (GLenum, GLsizei, GLint, GLint, GLsizei)) #endif #if defined AGL_PGI_misc_hints AGL_API(void, HintPGI, (GLenum, GLint)) #endif #if defined AGL_EXT_paletted_texture AGL_API(void, ColorTableEXT, (GLenum, GLenum, GLsizei, GLenum, GLenum, const GLvoid *)) AGL_API(void, GetColorTableEXT, (GLenum, GLenum, GLenum, GLvoid *)) AGL_API(void, GetColorTableParameterivEXT, (GLenum, GLenum, GLint *)) AGL_API(void, GetColorTableParameterfvEXT, (GLenum, GLenum, GLfloat *)) #endif #if defined AGL_SGIX_list_priority AGL_API(void, GetListParameterfvSGIX, (GLuint, GLenum, GLfloat *)) AGL_API(void, GetListParameterivSGIX, (GLuint, GLenum, GLint *)) AGL_API(void, ListParameterfSGIX, (GLuint, GLenum, GLfloat)) AGL_API(void, ListParameterfvSGIX, (GLuint, GLenum, const GLfloat *)) AGL_API(void, ListParameteriSGIX, (GLuint, GLenum, GLint)) AGL_API(void, ListParameterivSGIX, (GLuint, GLenum, const GLint *)) #endif #if defined AGL_EXT_index_material AGL_API(void, IndexMaterialEXT, (GLenum, GLenum)) #endif #if defined AGL_EXT_index_func AGL_API(void, IndexFuncEXT, (GLenum, GLclampf)) #endif #if defined AGL_EXT_compiled_vertex_array AGL_API(void, LockArraysEXT, (GLint, GLsizei)) AGL_API(void, UnlockArraysEXT, (void)) #endif #if defined AGL_EXT_cull_vertex AGL_API(void, CullParameterdvEXT, (GLenum, GLdouble *)) AGL_API(void, CullParameterfvEXT, (GLenum, GLfloat *)) #endif #if defined AGL_SGIX_fragment_lighting AGL_API(void, FragmentColorMaterialSGIX, (GLenum, GLenum)) AGL_API(void, FragmentLightfSGIX, (GLenum, GLenum, GLfloat)) AGL_API(void, FragmentLightfvSGIX, (GLenum, GLenum, const GLfloat *)) AGL_API(void, FragmentLightiSGIX, (GLenum, GLenum, GLint)) AGL_API(void, FragmentLightivSGIX, (GLenum, GLenum, const GLint *)) AGL_API(void, FragmentLightModelfSGIX, (GLenum, GLfloat)) AGL_API(void, FragmentLightModelfvSGIX, (GLenum, const GLfloat *)) AGL_API(void, FragmentLightModeliSGIX, (GLenum, GLint)) AGL_API(void, FragmentLightModelivSGIX, (GLenum, const GLint *)) AGL_API(void, FragmentMaterialfSGIX, (GLenum, GLenum, GLfloat)) AGL_API(void, FragmentMaterialfvSGIX, (GLenum, GLenum, const GLfloat *)) AGL_API(void, FragmentMaterialiSGIX, (GLenum, GLenum, GLint)) AGL_API(void, FragmentMaterialivSGIX, (GLenum, GLenum, const GLint *)) AGL_API(void, GetFragmentLightfvSGIX, (GLenum, GLenum, GLfloat *)) AGL_API(void, GetFragmentLightivSGIX, (GLenum, GLenum, GLint *)) AGL_API(void, GetFragmentMaterialfvSGIX, (GLenum, GLenum, GLfloat *)) AGL_API(void, GetFragmentMaterialivSGIX, (GLenum, GLenum, GLint *)) AGL_API(void, LightEnviSGIX, (GLenum, GLint)) #endif #if defined AGL_EXT_draw_range_elements AGL_API(void, DrawRangeElementsEXT, (GLenum, GLuint, GLuint, GLsizei, GLenum, const GLvoid *)) #endif #if defined AGL_EXT_light_texture AGL_API(void, ApplyTextureEXT, (GLenum)) AGL_API(void, TextureLightEXT, (GLenum)) AGL_API(void, TextureMaterialEXT, (GLenum, GLenum)) #endif #if defined AGL_SGIX_async AGL_API(void, AsyncMarkerSGIX, (GLuint)) AGL_API(GLint, FinishAsyncSGIX, (GLuint *)) AGL_API(GLint, PollAsyncSGIX, (GLuint *)) AGL_API(GLuint, GenAsyncMarkersSGIX, (GLsizei)) AGL_API(void, DeleteAsyncMarkersSGIX, (GLuint, GLsizei)) AGL_API(GLboolean, IsAsyncMarkerSGIX, (GLuint)) #endif #if defined AGL_INTEL_parallel_arrays AGL_API(void, VertexPointervINTEL, (GLint, GLenum, const GLvoid* *)) AGL_API(void, NormalPointervINTEL, (GLenum, const GLvoid* *)) AGL_API(void, ColorPointervINTEL, (GLint, GLenum, const GLvoid* *)) AGL_API(void, TexCoordPointervINTEL, (GLint, GLenum, const GLvoid* *)) #endif #if defined AGL_EXT_pixel_transform AGL_API(void, PixelTransformParameteriEXT, (GLenum, GLenum, GLint)) AGL_API(void, PixelTransformParameterfEXT, (GLenum, GLenum, GLfloat)) AGL_API(void, PixelTransformParameterivEXT, (GLenum, GLenum, const GLint *)) AGL_API(void, PixelTransformParameterfvEXT, (GLenum, GLenum, const GLfloat *)) #endif #if defined AGL_EXT_secondary_color AGL_API(void, SecondaryColor3bEXT, (GLbyte, GLbyte, GLbyte)) AGL_API(void, SecondaryColor3bvEXT, (const GLbyte *)) AGL_API(void, SecondaryColor3dEXT, (GLdouble, GLdouble, GLdouble)) AGL_API(void, SecondaryColor3dvEXT, (const GLdouble *)) AGL_API(void, SecondaryColor3fEXT, (GLfloat, GLfloat, GLfloat)) AGL_API(void, SecondaryColor3fvEXT, (const GLfloat *)) AGL_API(void, SecondaryColor3iEXT, (GLint, GLint, GLint)) AGL_API(void, SecondaryColor3ivEXT, (const GLint *)) AGL_API(void, SecondaryColor3sEXT, (GLshort, GLshort, GLshort)) AGL_API(void, SecondaryColor3svEXT, (const GLshort *)) AGL_API(void, SecondaryColor3ubEXT, (GLubyte, GLubyte, GLubyte)) AGL_API(void, SecondaryColor3ubvEXT, (const GLubyte *)) AGL_API(void, SecondaryColor3uiEXT, (GLuint, GLuint, GLuint)) AGL_API(void, SecondaryColor3uivEXT, (const GLuint *)) AGL_API(void, SecondaryColor3usEXT, (GLushort, GLushort, GLushort)) AGL_API(void, SecondaryColor3usvEXT, (const GLushort *)) AGL_API(void, SecondaryColorPointerEXT, (GLint, GLenum, GLsizei, const GLvoid *)) #endif #if defined AGL_EXT_texture_perturb_normal AGL_API(void, TextureNormalEXT, (GLenum)) #endif #if defined AGL_EXT_multi_draw_arrays AGL_API(void, MultiDrawArraysEXT, (GLenum, GLint *, GLsizei *, GLsizei)) AGL_API(void, MultiDrawElementsEXT, (GLenum, const GLsizei *, GLenum, const GLvoid* *, GLsizei)) #endif #if defined AGL_EXT_fog_coord AGL_API(void, FogCoordfEXT, (GLfloat)) AGL_API(void, FogCoordfvEXT, (const GLfloat *)) AGL_API(void, FogCoorddEXT, (GLdouble)) AGL_API(void, FogCoorddvEXT, (const GLdouble *)) AGL_API(void, FogCoordPointerEXT, (GLenum, GLsizei, const GLvoid *)) #endif #if defined AGL_EXT_coordinate_frame AGL_API(void, Tangent3bEXT, (GLbyte, GLbyte, GLbyte)) AGL_API(void, Tangent3bvEXT, (const GLbyte *)) AGL_API(void, Tangent3dEXT, (GLdouble, GLdouble, GLdouble)) AGL_API(void, Tangent3dvEXT, (const GLdouble *)) AGL_API(void, Tangent3fEXT, (GLfloat, GLfloat, GLfloat)) AGL_API(void, Tangent3fvEXT, (const GLfloat *)) AGL_API(void, Tangent3iEXT, (GLint, GLint, GLint)) AGL_API(void, Tangent3ivEXT, (const GLint *)) AGL_API(void, Tangent3sEXT, (GLshort, GLshort, GLshort)) AGL_API(void, Tangent3svEXT, (const GLshort *)) AGL_API(void, Binormal3bEXT, (GLbyte, GLbyte, GLbyte)) AGL_API(void, Binormal3bvEXT, (const GLbyte *)) AGL_API(void, Binormal3dEXT, (GLdouble, GLdouble, GLdouble)) AGL_API(void, Binormal3dvEXT, (const GLdouble *)) AGL_API(void, Binormal3fEXT, (GLfloat, GLfloat, GLfloat)) AGL_API(void, Binormal3fvEXT, (const GLfloat *)) AGL_API(void, Binormal3iEXT, (GLint, GLint, GLint)) AGL_API(void, Binormal3ivEXT, (const GLint *)) AGL_API(void, Binormal3sEXT, (GLshort, GLshort, GLshort)) AGL_API(void, Binormal3svEXT, (const GLshort *)) AGL_API(void, TangentPointerEXT, (GLenum, GLsizei, const GLvoid *)) AGL_API(void, BinormalPointerEXT, (GLenum, GLsizei, const GLvoid *)) #endif #if defined AGL_SUNX_constant_data AGL_API(void, FinishTextureSUNX, (void)) #endif #if defined AGL_SUN_global_alpha AGL_API(void, GlobalAlphaFactorbSUN, (GLbyte)) AGL_API(void, GlobalAlphaFactorsSUN, (GLshort)) AGL_API(void, GlobalAlphaFactoriSUN, (GLint)) AGL_API(void, GlobalAlphaFactorfSUN, (GLfloat)) AGL_API(void, GlobalAlphaFactordSUN, (GLdouble)) AGL_API(void, GlobalAlphaFactorubSUN, (GLubyte)) AGL_API(void, GlobalAlphaFactorusSUN, (GLushort)) AGL_API(void, GlobalAlphaFactoruiSUN, (GLuint)) #endif #if defined AGL_SUN_triangle_list AGL_API(void, ReplacementCodeuiSUN, (GLuint)) AGL_API(void, ReplacementCodeusSUN, (GLushort)) AGL_API(void, ReplacementCodeubSUN, (GLubyte)) AGL_API(void, ReplacementCodeuivSUN, (const GLuint *)) AGL_API(void, ReplacementCodeusvSUN, (const GLushort *)) AGL_API(void, ReplacementCodeubvSUN, (const GLubyte *)) AGL_API(void, ReplacementCodePointerSUN, (GLenum, GLsizei, const GLvoid* *)) #endif #if defined AGL_SUN_vertex AGL_API(void, Color4ubVertex2fSUN, (GLubyte, GLubyte, GLubyte, GLubyte, GLfloat, GLfloat)) AGL_API(void, Color4ubVertex2fvSUN, (const GLubyte *, const GLfloat *)) AGL_API(void, Color4ubVertex3fSUN, (GLubyte, GLubyte, GLubyte, GLubyte, GLfloat, GLfloat, GLfloat)) AGL_API(void, Color4ubVertex3fvSUN, (const GLubyte *, const GLfloat *)) AGL_API(void, Color3fVertex3fSUN, (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat)) AGL_API(void, Color3fVertex3fvSUN, (const GLfloat *, const GLfloat *)) AGL_API(void, Normal3fVertex3fSUN, (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat)) AGL_API(void, Normal3fVertex3fvSUN, (const GLfloat *, const GLfloat *)) AGL_API(void, Color4fNormal3fVertex3fSUN, (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat)) AGL_API(void, Color4fNormal3fVertex3fvSUN, (const GLfloat *, const GLfloat *, const GLfloat *)) AGL_API(void, TexCoord2fVertex3fSUN, (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat)) AGL_API(void, TexCoord2fVertex3fvSUN, (const GLfloat *, const GLfloat *)) AGL_API(void, TexCoord4fVertex4fSUN, (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat)) AGL_API(void, TexCoord4fVertex4fvSUN, (const GLfloat *, const GLfloat *)) AGL_API(void, TexCoord2fColor4ubVertex3fSUN, (GLfloat, GLfloat, GLubyte, GLubyte, GLubyte, GLubyte, GLfloat, GLfloat, GLfloat)) AGL_API(void, TexCoord2fColor4ubVertex3fvSUN, (const GLfloat *, const GLubyte *, const GLfloat *)) AGL_API(void, TexCoord2fColor3fVertex3fSUN, (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat)) AGL_API(void, TexCoord2fColor3fVertex3fvSUN, (const GLfloat *, const GLfloat *, const GLfloat *)) AGL_API(void, TexCoord2fNormal3fVertex3fSUN, (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat)) AGL_API(void, TexCoord2fNormal3fVertex3fvSUN, (const GLfloat *, const GLfloat *, const GLfloat *)) AGL_API(void, TexCoord2fColor4fNormal3fVertex3fSUN, (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat)) AGL_API(void, TexCoord2fColor4fNormal3fVertex3fvSUN, (const GLfloat *, const GLfloat *, const GLfloat *, const GLfloat *)) AGL_API(void, TexCoord4fColor4fNormal3fVertex4fSUN, (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat)) AGL_API(void, TexCoord4fColor4fNormal3fVertex4fvSUN, (const GLfloat *, const GLfloat *, const GLfloat *, const GLfloat *)) AGL_API(void, ReplacementCodeuiVertex3fSUN, (GLuint, GLfloat, GLfloat, GLfloat)) AGL_API(void, ReplacementCodeuiVertex3fvSUN, (const GLuint *, const GLfloat *)) AGL_API(void, ReplacementCodeuiColor4ubVertex3fSUN, (GLuint, GLubyte, GLubyte, GLubyte, GLubyte, GLfloat, GLfloat, GLfloat)) AGL_API(void, ReplacementCodeuiColor4ubVertex3fvSUN, (const GLuint *, const GLubyte *, const GLfloat *)) AGL_API(void, ReplacementCodeuiColor3fVertex3fSUN, (GLuint, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat)) AGL_API(void, ReplacementCodeuiColor3fVertex3fvSUN, (const GLuint *, const GLfloat *, const GLfloat *)) AGL_API(void, ReplacementCodeuiNormal3fVertex3fSUN, (GLuint, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat)) AGL_API(void, ReplacementCodeuiNormal3fVertex3fvSUN, (const GLuint *, const GLfloat *, const GLfloat *)) AGL_API(void, ReplacementCodeuiColor4fNormal3fVertex3fSUN, (GLuint, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat)) AGL_API(void, ReplacementCodeuiColor4fNormal3fVertex3fvSUN, (const GLuint *, const GLfloat *, const GLfloat *, const GLfloat *)) AGL_API(void, ReplacementCodeuiTexCoord2fVertex3fSUN, (GLuint, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat)) AGL_API(void, ReplacementCodeuiTexCoord2fVertex3fvSUN, (const GLuint *, const GLfloat *, const GLfloat *)) AGL_API(void, ReplacementCodeuiTexCoord2fNormal3fVertex3fSUN, (GLuint, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat)) AGL_API(void, ReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN, (const GLuint *, const GLfloat *, const GLfloat *, const GLfloat *)) AGL_API(void, ReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN, (GLuint, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat)) AGL_API(void, ReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN, (const GLuint *, const GLfloat *, const GLfloat *, const GLfloat *, const GLfloat *)) #endif #if defined AGL_EXT_blend_func_separate AGL_API(void, BlendFuncSeparateEXT, (GLenum, GLenum, GLenum, GLenum)) #endif #if defined AGL_INGR_blend_func_separate AGL_API(void, BlendFuncSeparateINGR, (GLenum, GLenum, GLenum, GLenum)) #endif #if defined AGL_EXT_vertex_weighting AGL_API(void, VertexWeightfEXT, (GLfloat)) AGL_API(void, VertexWeightfvEXT, (const GLfloat *)) AGL_API(void, VertexWeightPointerEXT, (GLsizei, GLenum, GLsizei, const GLvoid *)) #endif #if defined AGL_NV_vertex_array_range AGL_API(void, FlushVertexArrayRangeNV, (void)) AGL_API(void, VertexArrayRangeNV, (GLsizei, const GLvoid *)) #endif #if defined AGL_NV_register_combiners AGL_API(void, CombinerParameterfvNV, (GLenum, const GLfloat *)) AGL_API(void, CombinerParameterfNV, (GLenum, GLfloat)) AGL_API(void, CombinerParameterivNV, (GLenum, const GLint *)) AGL_API(void, CombinerParameteriNV, (GLenum, GLint)) AGL_API(void, CombinerInputNV, (GLenum, GLenum, GLenum, GLenum, GLenum, GLenum)) AGL_API(void, CombinerOutputNV, (GLenum, GLenum, GLenum, GLenum, GLenum, GLenum, GLenum, GLboolean, GLboolean, GLboolean)) AGL_API(void, FinalCombinerInputNV, (GLenum, GLenum, GLenum, GLenum)) AGL_API(void, GetCombinerInputParameterfvNV, (GLenum, GLenum, GLenum, GLenum, GLfloat *)) AGL_API(void, GetCombinerInputParameterivNV, (GLenum, GLenum, GLenum, GLenum, GLint *)) AGL_API(void, GetCombinerOutputParameterfvNV, (GLenum, GLenum, GLenum, GLfloat *)) AGL_API(void, GetCombinerOutputParameterivNV, (GLenum, GLenum, GLenum, GLint *)) AGL_API(void, GetFinalCombinerInputParameterfvNV, (GLenum, GLenum, GLfloat *)) AGL_API(void, GetFinalCombinerInputParameterivNV, (GLenum, GLenum, GLint *)) #endif #if defined AGL_MESA_resize_buffers AGL_API(void, ResizeBuffersMESA, (void)) #endif #if defined AGL_MESA_window_pos AGL_API(void, WindowPos2dMESA, (GLdouble, GLdouble)) AGL_API(void, WindowPos2dvMESA, (const GLdouble *)) AGL_API(void, WindowPos2fMESA, (GLfloat, GLfloat)) AGL_API(void, WindowPos2fvMESA, (const GLfloat *)) AGL_API(void, WindowPos2iMESA, (GLint, GLint)) AGL_API(void, WindowPos2ivMESA, (const GLint *)) AGL_API(void, WindowPos2sMESA, (GLshort, GLshort)) AGL_API(void, WindowPos2svMESA, (const GLshort *)) AGL_API(void, WindowPos3dMESA, (GLdouble, GLdouble, GLdouble)) AGL_API(void, WindowPos3dvMESA, (const GLdouble *)) AGL_API(void, WindowPos3fMESA, (GLfloat, GLfloat, GLfloat)) AGL_API(void, WindowPos3fvMESA, (const GLfloat *)) AGL_API(void, WindowPos3iMESA, (GLint, GLint, GLint)) AGL_API(void, WindowPos3ivMESA, (const GLint *)) AGL_API(void, WindowPos3sMESA, (GLshort, GLshort, GLshort)) AGL_API(void, WindowPos3svMESA, (const GLshort *)) AGL_API(void, WindowPos4dMESA, (GLdouble, GLdouble, GLdouble, GLdouble)) AGL_API(void, WindowPos4dvMESA, (const GLdouble *)) AGL_API(void, WindowPos4fMESA, (GLfloat, GLfloat, GLfloat, GLfloat)) AGL_API(void, WindowPos4fvMESA, (const GLfloat *)) AGL_API(void, WindowPos4iMESA, (GLint, GLint, GLint, GLint)) AGL_API(void, WindowPos4ivMESA, (const GLint *)) AGL_API(void, WindowPos4sMESA, (GLshort, GLshort, GLshort, GLshort)) AGL_API(void, WindowPos4svMESA, (const GLshort *)) #endif #if defined AGL_IBM_multimode_draw_arrays AGL_API(void, MultiModeDrawArraysIBM, (GLenum, const GLint *, const GLsizei *, GLsizei, GLint)) AGL_API(void, MultiModeDrawElementsIBM, (const GLenum *, const GLsizei *, GLenum, const GLvoid* *, GLsizei, GLint)) #endif #ifdef AGK_IBM_vertex_array_lists AGL_API(void, ColorPointerListIBM, (GLint, GLenum, GLint, const GLvoid* *, GLint)) AGL_API(void, SecondaryColorPointerListIBM, (GLint, GLenum, GLint, const GLvoid* *, GLint)) AGL_API(void, EdgeFlagPointerListIBM, (GLint, const GLboolean* *, GLint)) AGL_API(void, FogCoordPointerListIBM, (GLenum, GLint, const GLvoid* *, GLint)) AGL_API(void, IndexPointerListIBM, (GLenum, GLint, const GLvoid* *, GLint)) AGL_API(void, NormalPointerListIBM, (GLenum, GLint, const GLvoid* *, GLint)) AGL_API(void, TexCoordPointerListIBM, (GLint, GLenum, GLint, const GLvoid* *, GLint)) AGL_API(void, VertexPointerListIBM, (GLint, GLenum, GLint, const GLvoid* *, GLint)) #endif #if defined AGL_3DFX_tbuffer AGL_API(void, TbufferMask3DFX, (GLuint)) #endif #if defined AGL_EXT_multisample AGL_API(void, SampleMaskEXT, (GLclampf, GLboolean)) AGL_API(void, SamplePatternEXT, (GLenum)) #endif #if defined AGL_SGIS_texture_color_mask AGL_API(void, TextureColorMaskSGIS, (GLboolean, GLboolean, GLboolean, GLboolean)) #endif #if defined AGL_SGIX_igloo_interface AGL_API(void, IglooInterfaceSGIX, (GLenum, const GLvoid *)) #endif #if defined AGL_NV_fence AGL_API(void, DeleteFencesNV, (GLsizei, const GLuint *)) AGL_API(void, GenFencesNV, (GLsizei, GLuint *)) AGL_API(GLboolean, IsFenceNV, (GLuint)) AGL_API(GLboolean, TestFenceNV, (GLuint)) AGL_API(void, GetFenceivNV, (GLuint, GLenum, GLint *)) AGL_API(void, FinishFenceNV, (GLuint)) AGL_API(void, SetFenceNV, (GLuint, GLenum)) #endif #if defined AGL_NV_evaluators AGL_API(void, MapControlPointsNV, (GLenum, GLuint, GLenum, GLsizei, GLsizei, GLint, GLint, GLboolean, const GLvoid *)) AGL_API(void, MapParameterivNV, (GLenum, GLenum, const GLint *)) AGL_API(void, MapParameterfvNV, (GLenum, GLenum, const GLfloat *)) AGL_API(void, GetMapControlPointsNV, (GLenum, GLuint, GLenum, GLsizei, GLsizei, GLboolean, GLvoid *)) AGL_API(void, GetMapParameterivNV, (GLenum, GLenum, GLint *)) AGL_API(void, GetMapParameterfvNV, (GLenum, GLenum, GLfloat *)) AGL_API(void, GetMapAttribParameterivNV, (GLenum, GLuint, GLenum, GLint *)) AGL_API(void, GetMapAttribParameterfvNV, (GLenum, GLuint, GLenum, GLfloat *)) AGL_API(void, EvalMapsNV, (GLenum, GLenum)) #endif #if defined AGL_NV_register_combiners2 AGL_API(void, CombinerStageParameterfvNV, (GLenum, GLenum, const GLfloat *)) AGL_API(void, GetCombinerStageParameterfvNV, (GLenum, GLenum, GLfloat *)) #endif #if defined AGL_NV_vertex_program AGL_API(GLboolean, AreProgramsResidentNV, (GLsizei, const GLuint *, GLboolean *)) AGL_API(void, BindProgramNV, (GLenum, GLuint)) AGL_API(void, DeleteProgramsNV, (GLsizei, const GLuint *)) AGL_API(void, ExecuteProgramNV, (GLenum, GLuint, const GLfloat *)) AGL_API(void, GenProgramsNV, (GLsizei, GLuint *)) AGL_API(void, GetProgramParameterdvNV, (GLenum, GLuint, GLenum, GLdouble *)) AGL_API(void, GetProgramParameterfvNV, (GLenum, GLuint, GLenum, GLfloat *)) AGL_API(void, GetProgramivNV, (GLuint, GLenum, GLint *)) AGL_API(void, GetProgramStringNV, (GLuint, GLenum, GLubyte *)) AGL_API(void, GetTrackMatrixivNV, (GLenum, GLuint, GLenum, GLint *)) AGL_API(void, GetVertexAttribdvNV, (GLuint, GLenum, GLdouble *)) AGL_API(void, GetVertexAttribfvNV, (GLuint, GLenum, GLfloat *)) AGL_API(void, GetVertexAttribivNV, (GLuint, GLenum, GLint *)) AGL_API(void, GetVertexAttribPointervNV, (GLuint, GLenum, GLvoid* *)) AGL_API(GLboolean, IsProgramNV, (GLuint)) AGL_API(void, LoadProgramNV, (GLenum, GLuint, GLsizei, const GLubyte *)) AGL_API(void, ProgramParameter4dNV, (GLenum, GLuint, GLdouble, GLdouble, GLdouble, GLdouble)) AGL_API(void, ProgramParameter4dvNV, (GLenum, GLuint, const GLdouble *)) AGL_API(void, ProgramParameter4fNV, (GLenum, GLuint, GLfloat, GLfloat, GLfloat, GLfloat)) AGL_API(void, ProgramParameter4fvNV, (GLenum, GLuint, const GLfloat *)) AGL_API(void, ProgramParameters4dvNV, (GLenum, GLuint, GLuint, const GLdouble *)) AGL_API(void, ProgramParameters4fvNV, (GLenum, GLuint, GLuint, const GLfloat *)) AGL_API(void, RequestResidentProgramsNV, (GLsizei, const GLuint *)) AGL_API(void, TrackMatrixNV, (GLenum, GLuint, GLenum, GLenum)) AGL_API(void, VertexAttribPointerNV, (GLuint, GLint, GLenum, GLsizei, const GLvoid *)) AGL_API(void, VertexAttrib1dNV, (GLuint, GLdouble)) AGL_API(void, VertexAttrib1dvNV, (GLuint, const GLdouble *)) AGL_API(void, VertexAttrib1fNV, (GLuint, GLfloat)) AGL_API(void, VertexAttrib1fvNV, (GLuint, const GLfloat *)) AGL_API(void, VertexAttrib1sNV, (GLuint, GLshort)) AGL_API(void, VertexAttrib1svNV, (GLuint, const GLshort *)) AGL_API(void, VertexAttrib2dNV, (GLuint, GLdouble, GLdouble)) AGL_API(void, VertexAttrib2dvNV, (GLuint, const GLdouble *)) AGL_API(void, VertexAttrib2fNV, (GLuint, GLfloat, GLfloat)) AGL_API(void, VertexAttrib2fvNV, (GLuint, const GLfloat *)) AGL_API(void, VertexAttrib2sNV, (GLuint, GLshort, GLshort)) AGL_API(void, VertexAttrib2svNV, (GLuint, const GLshort *)) AGL_API(void, VertexAttrib3dNV, (GLuint, GLdouble, GLdouble, GLdouble)) AGL_API(void, VertexAttrib3dvNV, (GLuint, const GLdouble *)) AGL_API(void, VertexAttrib3fNV, (GLuint, GLfloat, GLfloat, GLfloat)) AGL_API(void, VertexAttrib3fvNV, (GLuint, const GLfloat *)) AGL_API(void, VertexAttrib3sNV, (GLuint, GLshort, GLshort, GLshort)) AGL_API(void, VertexAttrib3svNV, (GLuint, const GLshort *)) AGL_API(void, VertexAttrib4dNV, (GLuint, GLdouble, GLdouble, GLdouble, GLdouble)) AGL_API(void, VertexAttrib4dvNV, (GLuint, const GLdouble *)) AGL_API(void, VertexAttrib4fNV, (GLuint, GLfloat, GLfloat, GLfloat, GLfloat)) AGL_API(void, VertexAttrib4fvNV, (GLuint, const GLfloat *)) AGL_API(void, VertexAttrib4sNV, (GLuint, GLshort, GLshort, GLshort, GLshort)) AGL_API(void, VertexAttrib4svNV, (GLuint, const GLshort *)) AGL_API(void, VertexAttrib4ubNV, (GLuint, GLubyte, GLubyte, GLubyte, GLubyte)) AGL_API(void, VertexAttrib4ubvNV, (GLuint, const GLubyte *)) AGL_API(void, VertexAttribs1dvNV, (GLuint, GLsizei, const GLdouble *)) AGL_API(void, VertexAttribs1fvNV, (GLuint, GLsizei, const GLfloat *)) AGL_API(void, VertexAttribs1svNV, (GLuint, GLsizei, const GLshort *)) AGL_API(void, VertexAttribs2dvNV, (GLuint, GLsizei, const GLdouble *)) AGL_API(void, VertexAttribs2fvNV, (GLuint, GLsizei, const GLfloat *)) AGL_API(void, VertexAttribs2svNV, (GLuint, GLsizei, const GLshort *)) AGL_API(void, VertexAttribs3dvNV, (GLuint, GLsizei, const GLdouble *)) AGL_API(void, VertexAttribs3fvNV, (GLuint, GLsizei, const GLfloat *)) AGL_API(void, VertexAttribs3svNV, (GLuint, GLsizei, const GLshort *)) AGL_API(void, VertexAttribs4dvNV, (GLuint, GLsizei, const GLdouble *)) AGL_API(void, VertexAttribs4fvNV, (GLuint, GLsizei, const GLfloat *)) AGL_API(void, VertexAttribs4svNV, (GLuint, GLsizei, const GLshort *)) AGL_API(void, VertexAttribs4ubvNV, (GLuint, GLsizei, const GLubyte *)) #endif #if defined AGL_ATI_envmap_bumpmap AGL_API(void, TexBumpParameterivATI, (GLenum, const GLint *)) AGL_API(void, TexBumpParameterfvATI, (GLenum, const GLfloat *)) AGL_API(void, GetTexBumpParameterivATI, (GLenum, GLint *)) AGL_API(void, GetTexBumpParameterfvATI, (GLenum, GLfloat *)) #endif #if defined AGL_ATI_fragment_shader AGL_API(GLuint, GenFragmentShadersATI, (GLuint)) AGL_API(void, BindFragmentShaderATI, (GLuint)) AGL_API(void, DeleteFragmentShaderATI, (GLuint)) AGL_API(void, BeginFragmentShaderATI, (void)) AGL_API(void, EndFragmentShaderATI, (void)) AGL_API(void, PassTexCoordATI, (GLuint, GLuint, GLenum)) AGL_API(void, SampleMapATI, (GLuint, GLuint, GLenum)) AGL_API(void, ColorFragmentOp1ATI, (GLenum, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint)) AGL_API(void, ColorFragmentOp2ATI, (GLenum, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint)) AGL_API(void, ColorFragmentOp3ATI, (GLenum, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint)) AGL_API(void, AlphaFragmentOp1ATI, (GLenum, GLuint, GLuint, GLuint, GLuint, GLuint)) AGL_API(void, AlphaFragmentOp2ATI, (GLenum, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint)) AGL_API(void, AlphaFragmentOp3ATI, (GLenum, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint, GLuint)) AGL_API(void, SetFragmentShaderConstantATI, (GLuint, const GLfloat *)) #endif #if defined AGL_ATI_pn_triangles AGL_API(void, PNTrianglesiATI, (GLenum, GLint)) AGL_API(void, PNTrianglesfATI, (GLenum, GLfloat)) #endif #if defined AGL_ATI_vertex_array_object AGL_API(GLuint, NewObjectBufferATI, (GLsizei, const GLvoid *, GLenum)) AGL_API(GLboolean, IsObjectBufferATI, (GLuint)) AGL_API(void, UpdateObjectBufferATI, (GLuint, GLuint, GLsizei, const GLvoid *, GLenum)) AGL_API(void, GetObjectBufferfvATI, (GLuint, GLenum, GLfloat *)) AGL_API(void, GetObjectBufferivATI, (GLuint, GLenum, GLint *)) AGL_API(void, FreeObjectBufferATI, (GLuint)) AGL_API(void, ArrayObjectATI, (GLenum, GLint, GLenum, GLsizei, GLuint, GLuint)) AGL_API(void, GetArrayObjectfvATI, (GLenum, GLenum, GLfloat *)) AGL_API(void, GetArrayObjectivATI, (GLenum, GLenum, GLint *)) AGL_API(void, VariantArrayObjectATI, (GLuint, GLenum, GLsizei, GLuint, GLuint)) AGL_API(void, GetVariantArrayObjectfvATI, (GLuint, GLenum, GLfloat *)) AGL_API(void, GetVariantArrayObjectivATI, (GLuint, GLenum, GLint *)) #endif #if defined AGL_EXT_vertex_shader AGL_API(void, BeginVertexShaderEXT, (void)) AGL_API(void, EndVertexShaderEXT, (void)) AGL_API(void, BindVertexShaderEXT, (GLuint)) AGL_API(GLuint, GenVertexShadersEXT, (GLuint)) AGL_API(void, DeleteVertexShaderEXT, (GLuint)) AGL_API(void, ShaderOp1EXT, (GLenum, GLuint, GLuint)) AGL_API(void, ShaderOp2EXT, (GLenum, GLuint, GLuint, GLuint)) AGL_API(void, ShaderOp3EXT, (GLenum, GLuint, GLuint, GLuint, GLuint)) AGL_API(void, SwizzleEXT, (GLuint, GLuint, GLenum, GLenum, GLenum, GLenum)) AGL_API(void, WriteMaskEXT, (GLuint, GLuint, GLenum, GLenum, GLenum, GLenum)) AGL_API(void, InsertComponentEXT, (GLuint, GLuint, GLuint)) AGL_API(void, ExtractComponentEXT, (GLuint, GLuint, GLuint)) AGL_API(GLuint, GenSymbolsEXT, (GLenum, GLenum, GLenum, GLuint)) AGL_API(void, SetInvariantEXT, (GLuint, GLenum, const GLvoid *)) AGL_API(void, SetLocalConstantEXT, (GLuint, GLenum, const GLvoid *)) AGL_API(void, VariantbvEXT, (GLuint, const GLbyte *)) AGL_API(void, VariantsvEXT, (GLuint, const GLshort *)) AGL_API(void, VariantivEXT, (GLuint, const GLint *)) AGL_API(void, VariantfvEXT, (GLuint, const GLfloat *)) AGL_API(void, VariantdvEXT, (GLuint, const GLdouble *)) AGL_API(void, VariantubvEXT, (GLuint, const GLubyte *)) AGL_API(void, VariantusvEXT, (GLuint, const GLushort *)) AGL_API(void, VariantuivEXT, (GLuint, const GLuint *)) AGL_API(void, VariantPointerEXT, (GLuint, GLenum, GLuint, const GLvoid *)) AGL_API(void, EnableVariantClientStateEXT, (GLuint)) AGL_API(void, DisableVariantClientStateEXT, (GLuint)) AGL_API(GLuint, BindLightParameterEXT, (GLenum, GLenum)) AGL_API(GLuint, BindMaterialParameterEXT, (GLenum, GLenum)) AGL_API(GLuint, BindTexGenParameterEXT, (GLenum, GLenum, GLenum)) AGL_API(GLuint, BindTextureUnitParameterEXT, (GLenum, GLenum)) AGL_API(GLuint, BindParameterEXT, (GLenum)) AGL_API(GLboolean, IsVariantEnabledEXT, (GLuint, GLenum)) AGL_API(void, GetVariantBooleanvEXT, (GLuint, GLenum, GLboolean *)) AGL_API(void, GetVariantIntegervEXT, (GLuint, GLenum, GLint *)) AGL_API(void, GetVariantFloatvEXT, (GLuint, GLenum, GLfloat *)) AGL_API(void, GetVariantPointervEXT, (GLuint, GLenum, GLvoid* *)) AGL_API(void, GetInvariantBooleanvEXT, (GLuint, GLenum, GLboolean *)) AGL_API(void, GetInvariantIntegervEXT, (GLuint, GLenum, GLint *)) AGL_API(void, GetInvariantFloatvEXT, (GLuint, GLenum, GLfloat *)) AGL_API(void, GetLocalConstantBooleanvEXT, (GLuint, GLenum, GLboolean *)) AGL_API(void, GetLocalConstantIntegervEXT, (GLuint, GLenum, GLint *)) AGL_API(void, GetLocalConstantFloatvEXT, (GLuint, GLenum, GLfloat *)) #endif #if defined AGL_ATI_vertex_streams AGL_API(void, VertexStream1sATI, (GLenum, GLshort)) AGL_API(void, VertexStream1svATI, (GLenum, const GLshort *)) AGL_API(void, VertexStream1iATI, (GLenum, GLint)) AGL_API(void, VertexStream1ivATI, (GLenum, const GLint *)) AGL_API(void, VertexStream1fATI, (GLenum, GLfloat)) AGL_API(void, VertexStream1fvATI, (GLenum, const GLfloat *)) AGL_API(void, VertexStream1dATI, (GLenum, GLdouble)) AGL_API(void, VertexStream1dvATI, (GLenum, const GLdouble *)) AGL_API(void, VertexStream2sATI, (GLenum, GLshort, GLshort)) AGL_API(void, VertexStream2svATI, (GLenum, const GLshort *)) AGL_API(void, VertexStream2iATI, (GLenum, GLint, GLint)) AGL_API(void, VertexStream2ivATI, (GLenum, const GLint *)) AGL_API(void, VertexStream2fATI, (GLenum, GLfloat, GLfloat)) AGL_API(void, VertexStream2fvATI, (GLenum, const GLfloat *)) AGL_API(void, VertexStream2dATI, (GLenum, GLdouble, GLdouble)) AGL_API(void, VertexStream2dvATI, (GLenum, const GLdouble *)) AGL_API(void, VertexStream3sATI, (GLenum, GLshort, GLshort, GLshort)) AGL_API(void, VertexStream3svATI, (GLenum, const GLshort *)) AGL_API(void, VertexStream3iATI, (GLenum, GLint, GLint, GLint)) AGL_API(void, VertexStream3ivATI, (GLenum, const GLint *)) AGL_API(void, VertexStream3fATI, (GLenum, GLfloat, GLfloat, GLfloat)) AGL_API(void, VertexStream3fvATI, (GLenum, const GLfloat *)) AGL_API(void, VertexStream3dATI, (GLenum, GLdouble, GLdouble, GLdouble)) AGL_API(void, VertexStream3dvATI, (GLenum, const GLdouble *)) AGL_API(void, VertexStream4sATI, (GLenum, GLshort, GLshort, GLshort, GLshort)) AGL_API(void, VertexStream4svATI, (GLenum, const GLshort *)) AGL_API(void, VertexStream4iATI, (GLenum, GLint, GLint, GLint, GLint)) AGL_API(void, VertexStream4ivATI, (GLenum, const GLint *)) AGL_API(void, VertexStream4fATI, (GLenum, GLfloat, GLfloat, GLfloat, GLfloat)) AGL_API(void, VertexStream4fvATI, (GLenum, const GLfloat *)) AGL_API(void, VertexStream4dATI, (GLenum, GLdouble, GLdouble, GLdouble, GLdouble)) AGL_API(void, VertexStream4dvATI, (GLenum, const GLdouble *)) AGL_API(void, NormalStream3bATI, (GLenum, GLbyte, GLbyte, GLbyte)) AGL_API(void, NormalStream3bvATI, (GLenum, const GLbyte *)) AGL_API(void, NormalStream3sATI, (GLenum, GLshort, GLshort, GLshort)) AGL_API(void, NormalStream3svATI, (GLenum, const GLshort *)) AGL_API(void, NormalStream3iATI, (GLenum, GLint, GLint, GLint)) AGL_API(void, NormalStream3ivATI, (GLenum, const GLint *)) AGL_API(void, NormalStream3fATI, (GLenum, GLfloat, GLfloat, GLfloat)) AGL_API(void, NormalStream3fvATI, (GLenum, const GLfloat *)) AGL_API(void, NormalStream3dATI, (GLenum, GLdouble, GLdouble, GLdouble)) AGL_API(void, NormalStream3dvATI, (GLenum, const GLdouble *)) AGL_API(void, ClientActiveVertexStreamATI, (GLenum)) AGL_API(void, VertexBlendEnviATI, (GLenum, GLint)) AGL_API(void, VertexBlendEnvfATI, (GLenum, GLfloat)) #endif #if defined AGL_ATI_element_array AGL_API(void, ElementPointerATI, (GLenum, const GLvoid *)) AGL_API(void, DrawElementArrayATI, (GLenum, GLsizei)) AGL_API(void, DrawRangeElementArrayATI, (GLenum, GLuint, GLuint, GLsizei)) #endif #if defined AGL_SUN_mesh_array AGL_API(void, DrawMeshArraysSUN, (GLenum, GLint, GLsizei, GLsizei)) #endif #if defined AGL_NV_occlusion_query AGL_API(void, GenOcclusionQueriesNV, (GLsizei, GLuint *)) AGL_API(void, DeleteOcclusionQueriesNV, (GLsizei, const GLuint *)) AGL_API(GLboolean, IsOcclusionQueryNV, (GLuint)) AGL_API(void, BeginOcclusionQueryNV, (GLuint)) AGL_API(void, EndOcclusionQueryNV, (void)) AGL_API(void, GetOcclusionQueryivNV, (GLuint, GLenum, GLint *)) AGL_API(void, GetOcclusionQueryuivNV, (GLuint, GLenum, GLuint *)) #endif #if defined AGL_NV_point_sprite AGL_API(void, PointParameteriNV, (GLenum, GLint)) AGL_API(void, PointParameterivNV, (GLenum, const GLint *)) #endif #if defined AGL_EXT_stencil_two_side AGL_API(void, ActiveStencilFaceEXT, (GLenum)) #endif #if defined AGL_APPLE_element_array AGL_API(void, ElementPointerAPPLE, (GLenum, const GLvoid *)) AGL_API(void, DrawElementArrayAPPLE, (GLenum, GLint, GLsizei)) AGL_API(void, DrawRangeElementArrayAPPLE, (GLenum, GLuint, GLuint, GLint, GLsizei)) AGL_API(void, MultiDrawElementArrayAPPLE, (GLenum, const GLint *, const GLsizei *, GLsizei)) AGL_API(void, MultiDrawRangeElementArrayAPPLE, (GLenum, GLuint, GLuint, const GLint *, const GLsizei *, GLsizei)) #endif #if defined AGL_APPLE_fence AGL_API(void, GenFencesAPPLE, (GLsizei, GLuint *)) AGL_API(void, DeleteFencesAPPLE, (GLsizei, const GLuint *)) AGL_API(void, SetFenceAPPLE, (GLuint)) AGL_API(GLboolean, IsFenceAPPLE, (GLuint)) AGL_API(GLboolean, TestFenceAPPLE, (GLuint)) AGL_API(void, FinishFenceAPPLE, (GLuint)) AGL_API(GLboolean, TestObjectAPPLE, (GLenum, GLuint)) AGL_API(void, FinishObjectAPPLE, (GLenum, GLint)) #endif #if defined AGL_APPLE_vertex_array_object AGL_API(void, BindVertexArrayAPPLE, (GLuint)) AGL_API(void, DeleteVertexArraysAPPLE, (GLsizei, const GLuint *)) AGL_API(void, GenVertexArraysAPPLE, (GLsizei, const GLuint *)) AGL_API(GLboolean, IsVertexArrayAPPLE, (GLuint)) #endif #if defined AGL_APPLE_vertex_array_range AGL_API(void, VertexArrayRangeAPPLE, (GLsizei, GLvoid *)) AGL_API(void, FlushVertexArrayRangeAPPLE, (GLsizei, GLvoid *)) AGL_API(void, VertexArrayParameteriAPPLE, (GLenum, GLint)) #endif #if defined AGL_ATI_draw_buffers AGL_API(void, DrawBuffersATI, (GLsizei, const GLenum *)) #endif #if defined AGL_NV_fragment_program AGL_API(void, ProgramNamedParameter4fNV, (GLuint, GLsizei, const GLubyte *, GLfloat, GLfloat, GLfloat, GLfloat)) AGL_API(void, ProgramNamedParameter4dNV, (GLuint, GLsizei, const GLubyte *, GLdouble, GLdouble, GLdouble, GLdouble)) AGL_API(void, ProgramNamedParameter4fvNV, (GLuint, GLsizei, const GLubyte *, const GLfloat *)) AGL_API(void, ProgramNamedParameter4dvNV, (GLuint, GLsizei, const GLubyte *, const GLdouble *)) AGL_API(void, GetProgramNamedParameterfvNV, (GLuint, GLsizei, const GLubyte *, GLfloat *)) AGL_API(void, GetProgramNamedParameterdvNV, (GLuint, GLsizei, const GLubyte *, GLdouble *)) #endif #if defined AGL_NV_half_float AGL_API(void, Vertex2hNV, (GLhalfNV, GLhalfNV)) AGL_API(void, Vertex2hvNV, (const GLhalfNV *)) AGL_API(void, Vertex3hNV, (GLhalfNV, GLhalfNV, GLhalfNV)) AGL_API(void, Vertex3hvNV, (const GLhalfNV *)) AGL_API(void, Vertex4hNV, (GLhalfNV, GLhalfNV, GLhalfNV, GLhalfNV)) AGL_API(void, Vertex4hvNV, (const GLhalfNV *)) AGL_API(void, Normal3hNV, (GLhalfNV, GLhalfNV, GLhalfNV)) AGL_API(void, Normal3hvNV, (const GLhalfNV *)) AGL_API(void, Color3hNV, (GLhalfNV, GLhalfNV, GLhalfNV)) AGL_API(void, Color3hvNV, (const GLhalfNV *)) AGL_API(void, Color4hNV, (GLhalfNV, GLhalfNV, GLhalfNV, GLhalfNV)) AGL_API(void, Color4hvNV, (const GLhalfNV *)) AGL_API(void, TexCoord1hNV, (GLhalfNV)) AGL_API(void, TexCoord1hvNV, (const GLhalfNV *)) AGL_API(void, TexCoord2hNV, (GLhalfNV, GLhalfNV)) AGL_API(void, TexCoord2hvNV, (const GLhalfNV *)) AGL_API(void, TexCoord3hNV, (GLhalfNV, GLhalfNV, GLhalfNV)) AGL_API(void, TexCoord3hvNV, (const GLhalfNV *)) AGL_API(void, TexCoord4hNV, (GLhalfNV, GLhalfNV, GLhalfNV, GLhalfNV)) AGL_API(void, TexCoord4hvNV, (const GLhalfNV *)) AGL_API(void, MultiTexCoord1hNV, (GLenum, GLhalfNV)) AGL_API(void, MultiTexCoord1hvNV, (GLenum, const GLhalfNV *)) AGL_API(void, MultiTexCoord2hNV, (GLenum, GLhalfNV, GLhalfNV)) AGL_API(void, MultiTexCoord2hvNV, (GLenum, const GLhalfNV *)) AGL_API(void, MultiTexCoord3hNV, (GLenum, GLhalfNV, GLhalfNV, GLhalfNV)) AGL_API(void, MultiTexCoord3hvNV, (GLenum, const GLhalfNV *)) AGL_API(void, MultiTexCoord4hNV, (GLenum, GLhalfNV, GLhalfNV, GLhalfNV, GLhalfNV)) AGL_API(void, MultiTexCoord4hvNV, (GLenum, const GLhalfNV *)) AGL_API(void, FogCoordhNV, (GLhalfNV)) AGL_API(void, FogCoordhvNV, (const GLhalfNV *)) AGL_API(void, SecondaryColor3hNV, (GLhalfNV, GLhalfNV, GLhalfNV)) AGL_API(void, SecondaryColor3hvNV, (const GLhalfNV *)) AGL_API(void, VertexWeighthNV, (GLhalfNV)) AGL_API(void, VertexWeighthvNV, (const GLhalfNV *)) AGL_API(void, VertexAttrib1hNV, (GLuint, GLhalfNV)) AGL_API(void, VertexAttrib1hvNV, (GLuint, const GLhalfNV *)) AGL_API(void, VertexAttrib2hNV, (GLuint, GLhalfNV, GLhalfNV)) AGL_API(void, VertexAttrib2hvNV, (GLuint, const GLhalfNV *)) AGL_API(void, VertexAttrib3hNV, (GLuint, GLhalfNV, GLhalfNV, GLhalfNV)) AGL_API(void, VertexAttrib3hvNV, (GLuint, const GLhalfNV *)) AGL_API(void, VertexAttrib4hNV, (GLuint, GLhalfNV, GLhalfNV, GLhalfNV, GLhalfNV)) AGL_API(void, VertexAttrib4hvNV, (GLuint, const GLhalfNV *)) AGL_API(void, VertexAttribs1hvNV, (GLuint, GLsizei, const GLhalfNV *)) AGL_API(void, VertexAttribs2hvNV, (GLuint, GLsizei, const GLhalfNV *)) AGL_API(void, VertexAttribs3hvNV, (GLuint, GLsizei, const GLhalfNV *)) AGL_API(void, VertexAttribs4hvNV, (GLuint, GLsizei, const GLhalfNV *)) #endif #if defined AGL_NV_pixel_data_range AGL_API(void, PixelDataRangeNV, (GLenum, GLsizei, GLvoid *)) AGL_API(void, FlushPixelDataRangeNV, (GLenum)) #endif #if defined AGL_NV_primitive_restart AGL_API(void, PrimitiveRestartNV, (void)) AGL_API(void, PrimitiveRestartIndexNV, (GLuint)) #endif #if defined AGL_ATI_map_object_buffer AGL_API(GLvoid*, MapObjectBufferATI, (GLuint)) AGL_API(void, UnmapObjectBufferATI, (GLuint)) #endif #if defined AGL_ATI_separate_stencil AGL_API(void, StencilOpSeparateATI, (GLenum, GLenum, GLenum, GLenum)) AGL_API(void, StencilFuncSeparateATI, (GLenum, GLenum, GLint, GLuint)) #endif #if defined AGL_ATI_vertex_attrib_array_object AGL_API(void, VertexAttribArrayObjectATI, (GLuint, GLint, GLenum, GLboolean, GLsizei, GLuint, GLuint)) AGL_API(void, GetVertexAttribArrayObjectfvATI, (GLuint, GLenum, GLfloat *)) AGL_API(void, GetVertexAttribArrayObjectivATI, (GLuint, GLenum, GLint *)) #endif #if defined AGL_OES_byte_coordinates AGL_API(void, Vertex2bOES, ( GLbyte, GLbyte )) AGL_API(void, Vertex3bOES, ( GLbyte, GLbyte, GLbyte )) AGL_API(void, Vertex4bOES, ( GLbyte, GLbyte, GLbyte, GLbyte )) AGL_API(void, Vertex2bvOES, ( const GLbyte * )) AGL_API(void, Vertex3bvOES, ( const GLbyte * )) AGL_API(void, Vertex4bvOES, ( const GLbyte * )) AGL_API(void, TexCoord1bOES, ( GLbyte )) AGL_API(void, TexCoord2bOES, ( GLbyte, GLbyte )) AGL_API(void, TexCoord3bOES, ( GLbyte, GLbyte, GLbyte )) AGL_API(void, TexCoord4bOES, ( GLbyte, GLbyte, GLbyte, GLbyte )) AGL_API(void, TexCoord1bvOES, ( const GLbyte * )) AGL_API(void, TexCoord2bvOES, ( const GLbyte * )) AGL_API(void, TexCoord3bvOES, ( const GLbyte * )) AGL_API(void, TexCoord4bvOES, ( const GLbyte * )) AGL_API(void, MultiTexCoord1bOES, ( GLenum, GLbyte )) AGL_API(void, MultiTexCoord2bOES, ( GLenum, GLbyte, GLbyte )) AGL_API(void, MultiTexCoord3bOES, ( GLenum, GLbyte, GLbyte, GLbyte )) AGL_API(void, MultiTexCoord4bOES, ( GLenum, GLbyte, GLbyte, GLbyte, GLbyte )) AGL_API(void, MultiTexCoord1bvOES, ( GLenum texture, const GLbyte * )) AGL_API(void, MultiTexCoord2bvOES, ( GLenum texture, const GLbyte * )) AGL_API(void, MultiTexCoord3bvOES, ( GLenum texture, const GLbyte * )) AGL_API(void, MultiTexCoord4bvOES, ( GLenum texture, const GLbyte * )) #endif #if defined AGL_OES_fixed_point AGL_API(void, Vertex2xOES, (GLfixed, GLfixed)) AGL_API(void, Vertex3xOES, (GLfixed, GLfixed, GLfixed)) AGL_API(void, Vertex4xOES, (GLfixed, GLfixed, GLfixed, GLfixed)) AGL_API(void, Vertex2xvOES, (const GLfixed *)) AGL_API(void, Vertex3xvOES, (const GLfixed *)) AGL_API(void, Vertex4xvOES, (const GLfixed *)) AGL_API(void, Normal3xOES, (GLfixed, GLfixed, GLfixed)) AGL_API(void, Normal3xvOES, (const GLfixed *)) AGL_API(void, TexCoord1xOES, (GLfixed)) AGL_API(void, TexCoord2xOES, (GLfixed, GLfixed)) AGL_API(void, TexCoord3xOES, (GLfixed, GLfixed, GLfixed)) AGL_API(void, TexCoord4xOES, (GLfixed, GLfixed, GLfixed, GLfixed)) AGL_API(void, TexCoord1xvOES, (const GLfixed *)) AGL_API(void, TexCoord2xvOES, (const GLfixed *)) AGL_API(void, TexCoord3xvOES, (const GLfixed *)) AGL_API(void, TexCoord4xvOES, (const GLfixed *)) AGL_API(void, MultiTexCoord1xOES, (GLenum, GLfixed)) AGL_API(void, MultiTexCoord2xOES, (GLenum, GLfixed, GLfixed)) AGL_API(void, MultiTexCoord3xOES, (GLenum, GLfixed, GLfixed, GLfixed)) AGL_API(void, MultiTexCoord4xOES, (GLenum, GLfixed, GLfixed, GLfixed, GLfixed)) AGL_API(void, MultiTexCoord1xvOES, (GLenum, const GLfixed *)) AGL_API(void, MultiTexCoord2xvOES, (GLenum, const GLfixed *)) AGL_API(void, MultiTexCoord3xvOES, (GLenum, const GLfixed *)) AGL_API(void, MultiTexCoord4xvOES, (GLenum, const GLfixed *)) AGL_API(void, Color3xOES, (GLfixed, GLfixed, GLfixed)) AGL_API(void, Color4xOES, (GLfixed, GLfixed, GLfixed, GLfixed)) AGL_API(void, Color3xvOES, (const GLfixed *)) AGL_API(void, Color4xvOES, (const GLfixed *)) AGL_API(void, IndexxOES, (GLfixed)) AGL_API(void, IndexxvOES, (const GLfixed *)) AGL_API(void, RectxOES, (GLfixed, GLfixed, GLfixed, GLfixed)) AGL_API(void, RectxvOES, (const GLfixed [2], const GLfixed [2])) AGL_API(void, DepthRangexOES, (GLclampx, GLclampx)) AGL_API(void, LoadMatrixxOES, (const GLfixed [16])) AGL_API(void, MultMatrixxOES, (const GLfixed [16])) AGL_API(void, LoadTransposeMatrixxOES, (const GLfixed [16])) AGL_API(void, MultTransposeMatrixxOES, (const GLfixed [16])) AGL_API(void, RotatexOES, (GLfixed, GLfixed, GLfixed, GLfixed)) AGL_API(void, ScalexOES, (GLfixed, GLfixed, GLfixed)) AGL_API(void, TranslatexOES, (GLfixed, GLfixed, GLfixed)) AGL_API(void, FrustumxOES, (GLfixed, GLfixed, GLfixed, GLfixed, GLfixed, GLfixed)) AGL_API(void, OrthoxOES, (GLfixed, GLfixed, GLfixed, GLfixed, GLfixed, GLfixed)) AGL_API(void, TexGenxOES, (GLenum, GLenum, GLfixed)) AGL_API(void, TexGenxvOES, (GLenum, GLenum, const GLfixed *)) AGL_API(void, GetTexGenxvOES, (GLenum, GLenum, GLfixed *)) AGL_API(void, ClipPlanexOES, (GLenum, const GLfixed *)) AGL_API(void, GetClipPlanexOES, (GLenum, GLfixed *)) AGL_API(void, RasterPos2xOES, (GLfixed, GLfixed)) AGL_API(void, RasterPos3xOES, (GLfixed, GLfixed, GLfixed)) AGL_API(void, RasterPos4xOES, (GLfixed, GLfixed, GLfixed, GLfixed)) AGL_API(void, RasterPos2xvOES, (const GLfixed *)) AGL_API(void, RasterPos3xvOES, (const GLfixed *)) AGL_API(void, RasterPos4xvOES, (const GLfixed *)) AGL_API(void, MaterialxOES, (GLenum, GLenum, GLfixed)) AGL_API(void, MaterialxvOES, (GLenum, GLenum, const GLfixed *)) AGL_API(void, GetMaterialxOES, (GLenum, GLenum, GLfixed *)) AGL_API(void, LightxOES, (GLenum, GLenum, GLfixed)) AGL_API(void, LightxvOES, (GLenum, GLenum, const GLfixed *)) AGL_API(void, GetLightxOES, (GLenum, GLenum, const GLfixed *)) AGL_API(void, LightModelxOES, (GLenum, GLfixed)) AGL_API(void, LightModelxvOES, (GLenum, const GLfixed *)) AGL_API(void, PointSizexOES, (GLfixed size)) AGL_API(void, LineWidthxOES, (GLfixed width)) AGL_API(void, PolygonOffsetxOES, (GLfixed factor, GLfixed units)) AGL_API(void, PixelStorex, (GLenum pname, GLfixed param)) AGL_API(void, PixelTransferxOES, (GLenum pname, GLfixed param)) AGL_API(void, PixelMapx, (GLenum, GLint, const GLfixed *)) AGL_API(void, GetPixelMapxv, (GLenum, GLint, GLfixed *)) AGL_API(void, ConvolutionParameterxOES, (GLenum, GLenum, GLfixed)) AGL_API(void, ConvolutionParameterxvOES, (GLenum, GLenum, const GLfixed *)) AGL_API(void, GetConvolutionParameterxvOES, (GLenum, GLenum, GLfixed *)) AGL_API(void, GetHistogramParameterxvOES, (GLenum, GLenum, GLfixed *)) AGL_API(void, PixelZoomxOES, (GLfixed, GLfixed)) AGL_API(void, BitmapxOES, (GLsizei, GLsizei, GLfixed, GLfixed, GLfixed, GLfixed, const GLubyte *)) AGL_API(void, TexParameterxOES, (GLenum, GLenum, GLfixed)) AGL_API(void, TexParameterxvOES, (GLenum, GLenum, const GLfixed *)) AGL_API(void, GetTexParameterxvOES, (GLenum, GLenum, GLfixed *)) AGL_API(void, GetTexLevelParameterxvOES, (GLenum, GLint, GLenum, GLfixed *)) AGL_API(void, PrioritizeTexturesxOES, (GLsizei, GLuint *, GLclampx *)) AGL_API(void, TexEnvxOES, (GLenum, GLenum, GLfixed)) AGL_API(void, TexEnvxvOES, (GLenum, GLenum, const GLfixed *)) AGL_API(void, GetTexEnvxvOES, (GLenum, GLenum, GLfixed *)) AGL_API(void, FogxOES, (GLenum, GLfixed)) AGL_API(void, FogxvOES, (GLenum, const GLfixed *)) AGL_API(void, SampleCoverageOES, (GLclampx, GLboolean)) AGL_API(void, AlphaFuncxOES, (GLenum, GLclampx)) AGL_API(void, BlendColorxOES, (GLclampx, GLclampx, GLclampx, GLclampx)) AGL_API(void, ClearColorxOES, (GLclampx, GLclampx, GLclampx, GLclampx)) AGL_API(void, ClearDepthxOES, (GLclampx)) AGL_API(void, ClearAccumxOES, (GLclampx, GLclampx, GLclampx, GLclampx)) AGL_API(void, AccumxOES, (GLenum, GLfixed)) AGL_API(void, Map1xOES, (GLenum, GLfixed, GLfixed, GLint, GLint, const GLfixed *)) AGL_API(void, Map2xOES, (GLenum, GLfixed, GLfixed, GLint, GLint, GLfixed, GLfixed, GLint, GLint, const GLfixed *)) AGL_API(void, MapGrid1xOES, (GLint, GLfixed, GLfixed)) AGL_API(void, MapGrid2xOES, (GLint, GLfixed, GLfixed, GLfixed, GLfixed)) AGL_API(void, GetMapxvOES, (GLenum, GLenum, GLfixed *)) AGL_API(void, EvalCoord1xOES, (GLfixed)) AGL_API(void, EvalCoord2xOES, (GLfixed, GLfixed)) AGL_API(void, EvalCoord1xvOES, (const GLfixed *)) AGL_API(void, EvalCoord2xvOES, (const GLfixed *)) AGL_API(void, FeedbackBufferxOES, (GLsizei, GLenum, GLfixed *)) AGL_API(void, PassThroughxOES, (GLfixed)) AGL_API(void, GetFixedvOES, (GLenum, GLfixed *)) #endif #if defined AGL_OES_single_precision AGL_API(void, DepthRangefOES, (GLclampf, GLclampf)) AGL_API(void, FrustumfOES, (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat)) AGL_API(void, OrthofOES, (GLfloat, GLfloat, GLfloat, GLfloat, GLfloat, GLfloat)) AGL_API(void, ClipPlanefOES, (GLenum, const GLfloat*)) AGL_API(void, GetClipPlanefOES, (GLenum, GLfloat*)) AGL_API(void, ClearDepthfOES, (GLclampd)) #endif #if defined AGL_OES_query_matrix AGL_API(GLbitfield, QueryMatrixxOES, (GLfixed [16], GLint [16] )) #endif #if defined AGL_EXT_depth_bounds_test AGL_API(void, DepthBoundsEXT, (GLclampd, GLclampd)) #endif #if defined AGL_EXT_blend_equation_separate AGL_API(void, BlendEquationSeparateEXT, (GLenum, GLenum)) #endif #if defined AGL_EXT_framebuffer_object AGL_API(GLboolean, IsRenderbufferEXT, (GLuint)) AGL_API(void, BindRenderbufferEXT, (GLenum, GLuint)) AGL_API(void, DeleteRenderbuffersEXT, (GLsizei, const GLuint *)) AGL_API(void, GenRenderbuffersEXT, (GLsizei, GLuint *)) AGL_API(void, RenderbufferStorageEXT, (GLenum, GLenum, GLsizei, GLsizei)) AGL_API(void, GetRenderbufferParameterivEXT, (GLenum, GLenum, GLint*)) AGL_API(GLboolean, IsFramebufferEXT, (GLuint)) AGL_API(void, BindFramebufferEXT, (GLenum, GLuint)) AGL_API(void, DeleteFramebuffersEXT, (GLsizei, const GLuint *)) AGL_API(void, GenFramebuffersEXT, (GLsizei, GLuint *)) AGL_API(GLenum, CheckFramebufferStatusEXT, (GLenum)) AGL_API(void, FramebufferTexture1DEXT, (GLenum, GLenum, GLenum, GLuint, GLint)) AGL_API(void, FramebufferTexture2DEXT, (GLenum, GLenum, GLenum, GLuint, GLint)) AGL_API(void, FramebufferTexture3DEXT, (GLenum, GLenum, GLenum, GLuint, GLint, GLint)) AGL_API(void, FramebufferRenderbufferEXT, (GLenum, GLenum, GLenum, GLuint)) AGL_API(void, GetFramebufferAttachmentParameterivEXT, (GLenum, GLenum, GLenum, GLint *)) AGL_API(void, GenerateMipmapEXT, (GLenum)) #endif #if defined AGL_GREMEDY_string_marker AGL_API(void, StringMarkerGREMEDY, (GLsizei, const GLvoid *)) #endif #if defined AGL_EXT_stencil_clear_tag AGL_API(void, StencilClearTagEXT, (GLsizei, GLuint)) #endif #if defined AGL_EXT_framebuffer_blit AGL_API(void, BlitFramebufferEXT, (GLint, GLint, GLint, GLint, GLint, GLint, GLint, GLint, GLbitfield, GLenum)) #endif #if defined AGL_EXT_framebuffer_multisample AGL_API(void, RenderbufferStorageMultisampleEXT, (GLenum, GLsizei, GLenum, GLsizei, GLsizei)) #endif #if defined AGL_EXT_timer_query AGL_API(void, GetQueryObjecti64vEXT, (GLuint, GLenum, GLint64EXT *)) AGL_API(void, GetQueryObjectui64vEXT, (GLuint, GLenum, GLuint64EXT *)) #endif #if defined AGL_EXT_gpu_program_parameters AGL_API(void, ProgramEnvParameters4fvEXT, (GLenum, GLuint, GLsizei, const GLfloat *)) AGL_API(void, ProgramLocalParameters4fvEXT, (GLenum, GLuint, GLsizei, const GLfloat *)) #endif #if defined AGL_APPLE_flush_buffer_range AGL_API(void, BufferParameteriAPPLE, (GLenum, GLenum, GLint)) AGL_API(void, FlushMappedBufferRangeAPPLE, (GLenum, GLintptr, GLsizeiptr)) #endif #if defined AGL_EXT_bindable_uniform AGL_API(void, UniformBufferEXT, (GLuint, GLint, GLuint)) AGL_API(GLint, GetUniformBufferSizeEXT, (GLuint, GLint)) AGL_API(GLintptr, GetUniformOffsetEXT, (GLuint program, GLint)) #endif #if defined AGL_EXT_draw_buffers2 AGL_API(void, ColorMaskIndexedEXT, (GLuint, GLboolean, GLboolean, GLboolean, GLboolean)) AGL_API(void, GetBooleanIndexedvEXT, (GLenum, GLuint, GLboolean *)) AGL_API(void, GetIntegerIndexedvEXT, (GLenum, GLuint, GLint *)) AGL_API(void, EnableIndexedEXT, (GLenum, GLuint)) AGL_API(void, DisableIndexedEXT, (GLenum, GLuint)) AGL_API(GLboolean, IsEnabledIndexedEXT, (GLenum, GLuint)) #endif #if defined AGL_EXT_draw_instanced AGL_API(void, DrawArraysInstancedEXT, (GLenum, GLint, GLsizei, GLsizei)) AGL_API(void, DrawElementsInstancedEXT, (GLenum, GLsizei, GLenum, const GLvoid *, GLsizei)) #endif #if defined AGL_EXT_geometry_shader4 AGL_API(void, ProgramParameteriEXT, (GLuint, GLenum, GLint)) AGL_API(void, FramebufferTextureEXT, (GLenum, GLenum, GLuint, GLint)) #if !defined AGL_EXT_texture_array AGL_API(void, FramebufferTextureLayerEXT, (GLenum, GLenum, GLuint, GLint, GLint)) #endif AGL_API(void, FramebufferTextureFaceEXT, (GLenum, GLenum, GLuint, GLint, GLenum)) #endif #if defined AGL_EXT_gpu_shader4 AGL_API(void, VertexAttribI1iEXT, (GLuint, GLint)) AGL_API(void, VertexAttribI2iEXT, (GLuint, GLint, GLint)) AGL_API(void, VertexAttribI3iEXT, (GLuint, GLint, GLint, GLint)) AGL_API(void, VertexAttribI4iEXT, (GLuint, GLint, GLint, GLint, GLint)) AGL_API(void, VertexAttribI1uiEXT, (GLuint, GLuint)) AGL_API(void, VertexAttribI2uiEXT, (GLuint, GLuint, GLuint)) AGL_API(void, VertexAttribI3uiEXT, (GLuint, GLuint, GLuint, GLuint)) AGL_API(void, VertexAttribI4uiEXT, (GLuint, GLuint, GLuint, GLuint, GLuint)) AGL_API(void, VertexAttribI1ivEXT, (GLuint, const GLint *)) AGL_API(void, VertexAttribI2ivEXT, (GLuint, const GLint *)) AGL_API(void, VertexAttribI3ivEXT, (GLuint, const GLint *)) AGL_API(void, VertexAttribI4ivEXT, (GLuint, const GLint *)) AGL_API(void, VertexAttribI1uivEXT, (GLuint, const GLuint *)) AGL_API(void, VertexAttribI2uivEXT, (GLuint, const GLuint *)) AGL_API(void, VertexAttribI3uivEXT, (GLuint, const GLuint *)) AGL_API(void, VertexAttribI4uivEXT, (GLuint, const GLuint *)) AGL_API(void, VertexAttribI4bvEXT, (GLuint, const GLbyte *)) AGL_API(void, VertexAttribI4svEXT, (GLuint, const GLshort *)) AGL_API(void, VertexAttribI4ubvEXT, (GLuint, const GLubyte *)) AGL_API(void, VertexAttribI4usvEXT, (GLuint, const GLushort *)) AGL_API(void, VertexAttribIPointerEXT, (GLuint, GLint, GLenum, GLsizei, const GLvoid *)) AGL_API(void, GetVertexAttribIivEXT, (GLuint, GLenum, GLint *)) AGL_API(void, GetVertexAttribIuivEXT, (GLuint, GLenum, GLint *)) AGL_API(void, Uniform1uiEXT, (GLint, GLuint)) AGL_API(void, Uniform2uiEXT, (GLint, GLuint, GLuint)) AGL_API(void, Uniform3uiEXT, (GLint, GLuint, GLuint, GLuint)) AGL_API(void, Uniform4uiEXT, (GLint, GLuint, GLuint, GLuint, GLuint)) AGL_API(void, Uniform1uivEXT, (GLint, GLsizei, const GLuint *)) AGL_API(void, Uniform2uivEXT, (GLint, GLsizei, const GLuint *)) AGL_API(void, Uniform3uivEXT, (GLint, GLsizei, const GLuint *)) AGL_API(void, Uniform4uivEXT, (GLint, GLsizei, const GLuint *)) AGL_API(void, GetUniformuivEXT, (GLuint, GLint location, GLint *)) AGL_API(void, BindFragDataLocationEXT, (GLuint, GLuint, const GLchar *)) AGL_API(GLint, GetFragDataLocationEXT, (GLuint, const GLchar *)) #endif #if defined AGL_EXT_texture_array AGL_API(void, FramebufferTextureLayerEXT, (GLenum, GLenum, GLuint, GLint, GLint)) #endif #if defined AGL_EXT_texture_buffer_object AGL_API(void, TexBufferEXT, (GLenum, GLenum, GLuint)) #endif #if defined AGL_texture_integer AGL_API(void, ClearColorIiEXT, (GLint, GLint, GLint, GLint)) AGL_API(void, ClearColorIuiEXT, (GLuint, GLuint, GLuint, GLuint)) AGL_API(void, TexParameterIivEXT, (GLenum, GLenum, GLint *)) AGL_API(void, TexParameterIuivEXT, (GLenum, GLenum, GLuint *)) AGL_API(void, GetTexParameterIivEXT, (GLenum, GLenum, GLint *)) AGL_API(void, GetTexParameterIiuvEXT, (GLenum, GLenum, GLuint *)) #endif #if defined AGL_NV_depth_buffer_float AGL_API(void, DepthRangedNV, (GLdouble, GLdouble)) AGL_API(void, ClearDepthdNV, (GLdouble)) AGL_API(void, DepthBoundsdNV, (GLdouble, GLdouble)) #endif #if defined AGL_NV_framebuffer_multisample_coverage AGL_API(void, RenderbufferStorageMultsampleCoverageNV, (GLenum, GLsizei, GLsizei, GLenum, GLsizei, GLsizei)) #endif #if defined AGL_NV_geometry_program4 AGL_API(void, ProgramVertexLimitNV, (GLenum, GLint)) #if !defined AGL_EXT_geometry_shader4 AGL_API(void, FramebufferTextureEXT, (GLenum, GLenum, GLuint, GLint)) #if !defined AGL_EXT_texture_array AGL_API(void, FramebufferTextureLayerEXT, (GLenum, GLenum, GLuint, GLint, GLint)) #endif #endif #endif #if defined AGL_NV_gpu_program4 AGL_API(void, ProgramLocalParameterI4iNV, (GLenum, GLuint, GLint, GLint, GLint, GLint)) AGL_API(void, ProgramLocalParameterI4ivNV, (GLenum, GLuint, const GLint *)) AGL_API(void, ProgramLocalParametersI4ivNV, (GLenum, GLuint, GLsizei, const GLint *)) AGL_API(void, ProgramLocalParameterI4uiNV, (GLenum, GLuint, GLuint, GLuint, GLuint, GLuint)) AGL_API(void, ProgramLocalParameterI4uivNV, (GLenum, GLuint, const GLuint *)) AGL_API(void, ProgramLocalParametersI4uivNV, (GLenum, GLuint, GLsizei, const GLuint *)) AGL_API(void, ProgramEnvParameterI4iNV, (GLenum, GLuint, GLint, GLint, GLint, GLint)) AGL_API(void, ProgramEnvParameterI4ivNV, (GLenum, GLuint, const GLint *)) AGL_API(void, ProgramEnvParametersI4ivNV, (GLenum, GLuint, GLsizei, const GLint *)) AGL_API(void, ProgramEnvParameterI4uiNV, (GLenum, GLuint, GLuint, GLuint, GLuint, GLuint)) AGL_API(void, ProgramEnvParameterI4uivNV, (GLenum, GLuint, const GLuint *)) AGL_API(void, ProgramEnvParametersI4uivNV, (GLenum, GLuint, GLsizei, const GLuint *)) AGL_API(void, GetProgramLocalParameterIivNV, (GLenum, GLuint, GLint *)) AGL_API(void, GetProgramLocalParameterIuivNV,(GLenum, GLuint, GLuint *)) AGL_API(void, GetProgramEnvParameterIivNV, (GLenum, GLuint, GLint *)) AGL_API(void, GetProgramEnvParameterIuivNV, (GLenum, GLuint, GLuint *)) #endif #if defined AGL_NV_parameter_buffer_object #if !defined AGL_NV_transform_feedback AGL_API(void, BindBufferRangeNV, (GLenum, GLuint, GLuint, GLintptr, GLsizeiptr)) AGL_API(void, BindBufferOffsetNV,(GLenum, GLuint, GLuint, GLintptr)) AGL_API(void, BindBufferBaseNV, (GLenum, GLuint, GLuint)) #endif AGL_API(void, ProgramBufferParametersfvNV, (GLenum, GLuint, GLuint, GLsizei, const GLfloat *)) AGL_API(void, ProgramBufferParametersIivNV, (GLenum, GLuint, GLuint, GLsizei, const GLint *)) AGL_API(void, ProgramBufferParametersIuivNV,(GLenum, GLuint, GLuint, GLuint, const GLuint *)) #if !defined AGL_EXT_draw_buffers2 AGL_API(void, GetIntegerIndexedvEXT, (GLenum, GLuint, GLboolean *)) #endif #endif #if defined AGL_NV_transform_feedback AGL_API(void, BindBufferRangeNV, (GLenum, GLuint, GLuint, GLintptr, GLsizeiptr)) AGL_API(void, BindBufferOffsetNV,(GLenum, GLuint, GLuint, GLintptr)) AGL_API(void, BindBufferBaseNV, (GLenum, GLuint, GLuint)) AGL_API(void, TransformFeedbackAttribsNV, (GLsizei, const GLint *, GLenum)) AGL_API(void, TransformFeedbackVaryingsNV,(GLuint, GLsizei, const GLint *, GLenum)) AGL_API(void, BeginTransformFeedbackNV, (GLenum)) AGL_API(void, EndTransformFeedbackNV, (void)) AGL_API(GLint, GetVaryingLocationNV, (GLuint, const GLchar *)) AGL_API(void, GetActiveVaryingNV, (GLuint, GLuint, GLsizei, GLsizei *, GLsizei *, GLenum *, GLchar *)) AGL_API(void, ActiveVaryingNV, (GLuint, const GLchar *)) AGL_API(void, GetTransformFeedbackVaryingNV, (GLuint, GLuint, GLint *)) #if !defined AGL_EXT_draw_buffers2 AGL_API(void, GetBooleanIndexedvEXT, (GLenum, GLuint, GLboolean *)) /* AGL_API(void, GetIntegerIndexedvEXT, (GLenum, GLuint, GLint *)) */ #endif #endif #if defined AGL_NV_vertex_program4 #ifndef AGL_EXT_gpu_shader4 AGL_API(void, VertexAttribI1iEXT, (GLuint, GLint)) AGL_API(void, VertexAttribI2iEXT, (GLuint, GLint, GLint)) AGL_API(void, VertexAttribI3iEXT, (GLuint, GLint, GLint, GLint)) AGL_API(void, VertexAttribI4iEXT, (GLuint, GLint, GLint, GLint, GLint)) AGL_API(void, VertexAttribI1uiEXT, (GLuint, GLuint)) AGL_API(void, VertexAttribI2uiEXT, (GLuint, GLuint, GLuint)) AGL_API(void, VertexAttribI3uiEXT, (GLuint, GLuint, GLuint, GLuint)) AGL_API(void, VertexAttribI4uiEXT, (GLuint, GLuint, GLuint, GLuint, GLuint)) AGL_API(void, VertexAttribI1ivEXT, (GLuint, const GLint *)) AGL_API(void, VertexAttribI2ivEXT, (GLuint, const GLint *)) AGL_API(void, VertexAttribI3ivEXT, (GLuint, const GLint *)) AGL_API(void, VertexAttribI4ivEXT, (GLuint, const GLint *)) AGL_API(void, VertexAttribI1uivEXT, (GLuint, const GLuint *)) AGL_API(void, VertexAttribI2uivEXT, (GLuint, const GLuint *)) AGL_API(void, VertexAttribI3uivEXT, (GLuint, const GLuint *)) AGL_API(void, VertexAttribI4uivEXT, (GLuint, const GLuint *)) AGL_API(void, VertexAttribI4bvEXT, (GLuint, const GLbyte *)) AGL_API(void, VertexAttribI4svEXT, (GLuint, const GLshort *)) AGL_API(void, VertexAttribI4ubvEXT, (GLuint, const GLubyte *)) AGL_API(void, VertexAttribI4usvEXT, (GLuint, const GLushort *)) AGL_API(void, VertexAttribIPointerEXT, (GLuint, GLint, GLenum, GLsizei, const GLvoid *)) AGL_API(void, GetVertexAttribIivEXT, (GLuint, GLenum, GLint *)) AGL_API(void, GetVertexAttribIuivEXT, (GLuint, GLenum, GLint *)) #endif #endif #if defined AGL_GREMEDY_frame_terminator AGL_API(void, FrameTerminatorGREMEDY, (void)) #endif #if defined AGL_NV_conditional_render AGL_API(void, BeginConditionalRenderNV, (GLuint, GLenum)) AGL_API(void, EndConditionalRenderNV, (void)) #endif #if defined AGL_EXT_transform_feedback AGL_API(void, BeginTransformFeedbackEXT, (GLenum)) AGL_API(void, EndTransformFeedbackEXT, (void)) AGL_API(void, BindBufferRangeEXT, (GLenum, GLuint, GLuint, GLintptr, GLsizeiptr)) AGL_API(void, BindBufferOffsetEXT, (GLenum, GLuint, GLuint, GLintptr)) AGL_API(void, BindBufferBaseEXT, (GLenum, GLuint, GLuint)) AGL_API(void, TransformFeedbackVaryingsEXT, (GLuint, GLsizei, const GLint *, GLenum)) AGL_API(void, GetTransformFeedbackVaryingEXT, (GLuint, GLuint, GLint *)) #endif #if defined AGL_EXT_direct_state_access AGL_API(void, ClientAttribDefaultEXT, (GLbitfield)) AGL_API(void, PushClientAttribDefaultEXT, (GLbitfield)) AGL_API(void, MatrixLoadfEXT, (GLenum, const GLfloat *)) AGL_API(void, MatrixLoaddEXT, (GLenum, const GLdouble *)) AGL_API(void, MatrixMultfEXT, (GLenum, const GLfloat *)) AGL_API(void, MatrixMultdEXT, (GLenum, const GLdouble *)) AGL_API(void, MatrixLoadIdentityEXT, (GLenum)) AGL_API(void, MatrixRotatefEXT, (GLenum, GLfloat, GLfloat, GLfloat, GLfloat)) AGL_API(void, MatrixRotatedEXT, (GLenum, GLdouble, GLdouble, GLdouble, GLdouble)) AGL_API(void, MatrixScalefEXT, (GLenum, GLfloat, GLfloat, GLfloat)) AGL_API(void, MatrixScaledEXT, (GLenum, GLdouble, GLdouble, GLdouble)) AGL_API(void, MatrixTranslatefEXT, (GLenum, GLfloat, GLfloat, GLfloat)) AGL_API(void, MatrixTranslatedEXT, (GLenum, GLdouble, GLdouble, GLdouble)) AGL_API(void, MatrixFrustumEXT, (GLenum, GLdouble, GLdouble, GLdouble, GLdouble, GLdouble, GLdouble)) AGL_API(void, MatrixOrthoEXT, (GLenum, GLdouble, GLdouble, GLdouble, GLdouble, GLdouble, GLdouble)) AGL_API(void, MatrixPopEXT, (GLenum)) AGL_API(void, MatrixPushEXT, (GLenum)) AGL_API(void, MatrixLoadTransposefEXT, (GLenum, const GLfloat *)) AGL_API(void, MatrixLoadTransposedEXT, (GLenum, const GLdouble *)) AGL_API(void, MatrixMultTransposefEXT, (GLenum, const GLfloat *)) AGL_API(void, MatrixMultTransposedEXT, (GLenum, const GLdouble *)) AGL_API(void, TextureParameterfEXT, (GLuint, GLenum, GLenum, GLfloat)) AGL_API(void, TextureParameterfvEXT, (GLuint, GLenum, GLenum, const GLfloat *)) AGL_API(void, TextureParameteriEXT, (GLuint, GLenum, GLenum, GLint)) AGL_API(void, TextureParameterivEXT, (GLuint, GLenum, GLenum, const GLint *)) AGL_API(void, TextureImage1DEXT, (GLuint, GLenum, GLint, GLenum, GLsizei, GLint, GLenum, GLenum, const GLvoid *)) AGL_API(void, TextureImage2DEXT, (GLuint, GLenum, GLint, GLenum, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid *)) AGL_API(void, TextureSubImage1DEXT, (GLuint, GLenum, GLint, GLint, GLsizei, GLenum, GLenum, const GLvoid *)) AGL_API(void, TextureSubImage2DEXT, (GLuint, GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *)) AGL_API(void, CopyTextureImage1DEXT, (GLuint, GLenum, GLint, GLenum, GLint, GLint, GLsizei, GLint)) AGL_API(void, CopyTextureImage2DEXT, (GLuint, GLenum, GLint, GLenum, GLint, GLint, GLsizei, GLsizei, GLint)) AGL_API(void, CopyTextureSubImage1DEXT, (GLuint, GLenum, GLint, GLint, GLint, GLint, GLsizei)) AGL_API(void, CopyTextureSubImage2DEXT, (GLuint, GLenum, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei)) AGL_API(void, GetTextureImageEXT, (GLuint, GLenum, GLint, GLenum, GLenum, GLvoid *)) AGL_API(void, GetTextureParameterfvEXT, (GLuint, GLenum, GLenum, GLfloat *)) AGL_API(void, GetTextureParameterivEXT, (GLuint, GLenum, GLenum, GLint *)) AGL_API(void, GetTextureLevelParameterfvEXT, (GLuint, GLenum, GLint, GLenum, GLfloat *)) AGL_API(void, GetTextureLevelParameterivEXT, (GLuint, GLenum, GLint, GLenum, GLint *)) AGL_API(void, TextureImage3DEXT, (GLuint, GLenum, GLint, GLenum, GLsizei, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid *)) AGL_API(void, TextureSubImage3DEXT, (GLuint, GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *)) AGL_API(void, CopyTextureSubImage3DEXT, (GLuint, GLenum, GLint, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei)) AGL_API(void, MultiTexParameterfEXT, (GLenum, GLenum, GLenum, GLfloat)) AGL_API(void, MultiTexParameterfvEXT, (GLenum, GLenum, GLenum, const GLfloat *)) AGL_API(void, MultiTexParameteriEXT, (GLenum, GLenum, GLenum, GLint)) AGL_API(void, MultiTexParameterivEXT, (GLenum, GLenum, GLenum, const GLint *)) AGL_API(void, MultiTexImage1DEXT, (GLenum, GLenum, GLint, GLenum, GLsizei, GLint, GLenum, GLenum, const GLvoid *)) AGL_API(void, MultiTexImage2DEXT, (GLenum, GLenum, GLint, GLenum, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid *)) AGL_API(void, MultiTexSubImage1DEXT, (GLenum, GLenum, GLint, GLint, GLsizei, GLenum, GLenum, const GLvoid *)) AGL_API(void, MultiTexSubImage2DEXT, (GLenum, GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *)) AGL_API(void, CopyMultiTexImage1DEXT, (GLenum, GLenum, GLint, GLenum, GLint, GLint, GLsizei, GLint)) AGL_API(void, CopyMultiTexImage2DEXT, (GLenum, GLenum, GLint, GLenum, GLint, GLint, GLsizei, GLsizei, GLint)) AGL_API(void, CopyMultiTexSubImage1DEXT, (GLenum, GLenum, GLint, GLint, GLint, GLint, GLsizei)) AGL_API(void, CopyMultiTexSubImage2DEXT, (GLenum, GLenum, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei)) AGL_API(void, GetMultiTexImageEXT, (GLenum, GLenum, GLint, GLenum, GLenum, GLvoid *)) AGL_API(void, GetMultiTexParameterfvEXT, (GLenum, GLenum, GLenum, GLfloat *)) AGL_API(void, GetMultiTexParameterivEXT, (GLenum, GLenum, GLenum, GLint *)) AGL_API(void, GetMultiTexLevelParameterfvEXT, (GLenum, GLenum, GLint, GLenum, GLfloat *)) AGL_API(void, GetMultiTexLevelParameterivEXT, (GLenum, GLenum, GLint, GLenum, GLint *)) AGL_API(void, MultiTexImage3DEXT, (GLenum, GLenum, GLint, GLenum, GLsizei, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid *)) AGL_API(void, MultiTexSubImage3DEXT, (GLenum, GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *)) AGL_API(void, CopyMultiTexSubImage3DEXT, (GLenum, GLenum, GLint, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei)) AGL_API(void, BindMultiTextureEXT, (GLenum, GLenum, GLuint)) AGL_API(void, EnableClientStateIndexedEXT, (GLenum, GLuint)) AGL_API(void, DisableClientStateIndexedEXT, (GLenum, GLuint)) AGL_API(void, MultiTexCoordPointerEXT, (GLenum, GLint, GLenum, GLsizei, const GLvoid *)) AGL_API(void, MultiTexEnvfEXT, (GLenum, GLenum, GLenum, GLfloat)) AGL_API(void, MultiTexEnvfvEXT, (GLenum, GLenum, GLenum, const GLfloat *)) AGL_API(void, MultiTexEnviEXT, (GLenum, GLenum, GLenum, GLint)) AGL_API(void, MultiTexEnvivEXT, (GLenum, GLenum, GLenum, const GLint *)) AGL_API(void, MultiTexGendEXT, (GLenum, GLenum, GLenum, GLdouble)) AGL_API(void, MultiTexGendvEXT, (GLenum, GLenum, GLenum, const GLdouble *)) AGL_API(void, MultiTexGenfEXT, (GLenum, GLenum, GLenum, GLfloat)) AGL_API(void, MultiTexGenfvEXT, (GLenum, GLenum, GLenum, const GLfloat *)) AGL_API(void, MultiTexGeniEXT, (GLenum, GLenum, GLenum, GLint)) AGL_API(void, MultiTexGenivEXT, (GLenum, GLenum, GLenum, const GLint *)) AGL_API(void, GetMultiTexEnvfvEXT, (GLenum, GLenum, GLenum, GLfloat *)) AGL_API(void, GetMultiTexEnvivEXT, (GLenum, GLenum, GLenum, GLint *)) AGL_API(void, GetMultiTexGendvEXT, (GLenum, GLenum, GLenum, GLdouble *)) AGL_API(void, GetMultiTexGenfvEXT, (GLenum, GLenum, GLenum, GLfloat *)) AGL_API(void, GetMultiTexGenivEXT, (GLenum, GLenum, GLenum, GLint *)) AGL_API(void, GetFloatIndexedvEXT, (GLenum, GLuint, GLfloat *)) AGL_API(void, GetDoubleIndexedvEXT, (GLenum, GLuint, GLdouble *)) AGL_API(void, GetPointerIndexedvEXT, (GLenum, GLuint, GLvoid* *)) AGL_API(void, CompressedTextureImage3DEXT, (GLuint, GLenum, GLint, GLenum, GLsizei, GLsizei, GLsizei, GLint, GLsizei, const GLvoid *)) AGL_API(void, CompressedTextureImage2DEXT, (GLuint, GLenum, GLint, GLenum, GLsizei, GLsizei, GLint, GLsizei, const GLvoid *)) AGL_API(void, CompressedTextureImage1DEXT, (GLuint, GLenum, GLint, GLenum, GLsizei, GLint, GLsizei, const GLvoid *)) AGL_API(void, CompressedTextureSubImage3DEXT, (GLuint, GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLsizei, const GLvoid *)) AGL_API(void, CompressedTextureSubImage2DEXT, (GLuint, GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLsizei, const GLvoid *)) AGL_API(void, CompressedTextureSubImage1DEXT, (GLuint, GLenum, GLint, GLint, GLsizei, GLenum, GLsizei, const GLvoid *)) AGL_API(void, GetCompressedTextureImageEXT, (GLuint, GLenum, GLint, GLvoid *)) AGL_API(void, CompressedMultiTexImage3DEXT, (GLenum, GLenum, GLint, GLenum, GLsizei, GLsizei, GLsizei, GLint, GLsizei, const GLvoid *)) AGL_API(void, CompressedMultiTexImage2DEXT, (GLenum, GLenum, GLint, GLenum, GLsizei, GLsizei, GLint, GLsizei, const GLvoid *)) AGL_API(void, CompressedMultiTexImage1DEXT, (GLenum, GLenum, GLint, GLenum, GLsizei, GLint, GLsizei, const GLvoid *)) AGL_API(void, CompressedMultiTexSubImage3DEXT, (GLenum, GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLsizei, const GLvoid *)) AGL_API(void, CompressedMultiTexSubImage2DEXT, (GLenum, GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLsizei, const GLvoid *)) AGL_API(void, CompressedMultiTexSubImage1DEXT, (GLenum, GLenum, GLint, GLint, GLsizei, GLenum, GLsizei, const GLvoid *)) AGL_API(void, GetCompressedMultiTexImageEXT, (GLenum, GLenum, GLint, GLvoid *)) AGL_API(void, NamedProgramStringEXT, (GLuint, GLenum, GLenum, GLsizei, const GLvoid *)) AGL_API(void, NamedProgramLocalParameter4dEXT, (GLuint, GLenum, GLuint, GLdouble, GLdouble, GLdouble, GLdouble)) AGL_API(void, NamedProgramLocalParameter4dvEXT, (GLuint, GLenum, GLuint, const GLdouble *)) AGL_API(void, NamedProgramLocalParameter4fEXT, (GLuint, GLenum, GLuint, GLfloat, GLfloat, GLfloat, GLfloat)) AGL_API(void, NamedProgramLocalParameter4fvEXT, (GLuint, GLenum, GLuint, const GLfloat *)) AGL_API(void, GetNamedProgramLocalParameterdvEXT, (GLuint, GLenum, GLuint, GLdouble *)) AGL_API(void, GetNamedProgramLocalParameterfvEXT, (GLuint, GLenum, GLuint, GLfloat *)) AGL_API(void, GetNamedProgramivEXT, (GLuint, GLenum, GLenum, GLint *)) AGL_API(void, GetNamedProgramStringEXT, (GLuint, GLenum, GLenum, GLvoid *)) AGL_API(void, NamedProgramLocalParameters4fvEXT, (GLuint, GLenum, GLuint, GLsizei, const GLfloat *)) AGL_API(void, NamedProgramLocalParameterI4iEXT, (GLuint, GLenum, GLuint, GLint, GLint, GLint, GLint)) AGL_API(void, NamedProgramLocalParameterI4ivEXT, (GLuint, GLenum, GLuint, const GLint *)) AGL_API(void, NamedProgramLocalParametersI4ivEXT, (GLuint, GLenum, GLuint, GLsizei, const GLint *)) AGL_API(void, NamedProgramLocalParameterI4uiEXT, (GLuint, GLenum, GLuint, GLuint, GLuint, GLuint, GLuint)) AGL_API(void, NamedProgramLocalParameterI4uivEXT, (GLuint, GLenum, GLuint, const GLuint *)) AGL_API(void, NamedProgramLocalParametersI4uivEXT, (GLuint, GLenum, GLuint, GLsizei, const GLuint *)) AGL_API(void, GetNamedProgramLocalParameterIivEXT, (GLuint, GLenum, GLuint, GLint *)) AGL_API(void, GetNamedProgramLocalParameterIuivEXT, (GLuint, GLenum, GLuint, GLuint *)) AGL_API(void, TextureParameterIivEXT, (GLuint, GLenum, GLenum, const GLint *)) AGL_API(void, TextureParameterIuivEXT, (GLuint, GLenum, GLenum, const GLuint *)) AGL_API(void, GetTextureParameterIivEXT, (GLuint, GLenum, GLenum, GLint *)) AGL_API(void, GetTextureParameterIuivEXT, (GLuint, GLenum, GLenum, GLuint *)) AGL_API(void, MultiTexParameterIivEXT, (GLenum, GLenum, GLenum, const GLint *)) AGL_API(void, MultiTexParameterIuivEXT, (GLenum, GLenum, GLenum, const GLuint *)) AGL_API(void, GetMultiTexParameterIivEXT, (GLenum, GLenum, GLenum, GLint *)) AGL_API(void, GetMultiTexParameterIuivEXT, (GLenum, GLenum, GLenum, GLuint *)) AGL_API(void, ProgramUniform1fEXT, (GLuint, GLint, GLfloat)) AGL_API(void, ProgramUniform2fEXT, (GLuint, GLint, GLfloat, GLfloat)) AGL_API(void, ProgramUniform3fEXT, (GLuint, GLint, GLfloat, GLfloat, GLfloat)) AGL_API(void, ProgramUniform4fEXT, (GLuint, GLint, GLfloat, GLfloat, GLfloat, GLfloat)) AGL_API(void, ProgramUniform1iEXT, (GLuint, GLint, GLint)) AGL_API(void, ProgramUniform2iEXT, (GLuint, GLint, GLint, GLint)) AGL_API(void, ProgramUniform3iEXT, (GLuint, GLint, GLint, GLint, GLint)) AGL_API(void, ProgramUniform4iEXT, (GLuint, GLint, GLint, GLint, GLint, GLint)) AGL_API(void, ProgramUniform1fvEXT, (GLuint, GLint, GLsizei, const GLfloat *)) AGL_API(void, ProgramUniform2fvEXT, (GLuint, GLint, GLsizei, const GLfloat *)) AGL_API(void, ProgramUniform3fvEXT, (GLuint, GLint, GLsizei, const GLfloat *)) AGL_API(void, ProgramUniform4fvEXT, (GLuint, GLint, GLsizei, const GLfloat *)) AGL_API(void, ProgramUniform1ivEXT, (GLuint, GLint, GLsizei, const GLint *)) AGL_API(void, ProgramUniform2ivEXT, (GLuint, GLint, GLsizei, const GLint *)) AGL_API(void, ProgramUniform3ivEXT, (GLuint, GLint, GLsizei, const GLint *)) AGL_API(void, ProgramUniform4ivEXT, (GLuint, GLint, GLsizei, const GLint *)) AGL_API(void, ProgramUniformMatrix2fvEXT, (GLuint, GLint, GLsizei, GLboolean, const GLfloat *)) AGL_API(void, ProgramUniformMatrix3fvEXT, (GLuint, GLint, GLsizei, GLboolean, const GLfloat *)) AGL_API(void, ProgramUniformMatrix4fvEXT, (GLuint, GLint, GLsizei, GLboolean, const GLfloat *)) AGL_API(void, ProgramUniformMatrix2x3fvEXT, (GLuint, GLint, GLsizei, GLboolean, const GLfloat *)) AGL_API(void, ProgramUniformMatrix3x2fvEXT, (GLuint, GLint, GLsizei, GLboolean, const GLfloat *)) AGL_API(void, ProgramUniformMatrix2x4fvEXT, (GLuint, GLint, GLsizei, GLboolean, const GLfloat *)) AGL_API(void, ProgramUniformMatrix4x2fvEXT, (GLuint, GLint, GLsizei, GLboolean, const GLfloat *)) AGL_API(void, ProgramUniformMatrix3x4fvEXT, (GLuint, GLint, GLsizei, GLboolean, const GLfloat *)) AGL_API(void, ProgramUniformMatrix4x3fvEXT, (GLuint, GLint, GLsizei, GLboolean, const GLfloat *)) AGL_API(void, ProgramUniform1uiEXT, (GLuint, GLint, GLuint)) AGL_API(void, ProgramUniform2uiEXT, (GLuint, GLint, GLuint, GLuint)) AGL_API(void, ProgramUniform3uiEXT, (GLuint, GLint, GLuint, GLuint, GLuint)) AGL_API(void, ProgramUniform4uiEXT, (GLuint, GLint, GLuint, GLuint, GLuint, GLuint)) AGL_API(void, ProgramUniform1uivEXT, (GLuint, GLint, GLsizei, const GLuint *)) AGL_API(void, ProgramUniform2uivEXT, (GLuint, GLint, GLsizei, const GLuint *)) AGL_API(void, ProgramUniform3uivEXT, (GLuint, GLint, GLsizei, const GLuint *)) AGL_API(void, ProgramUniform4uivEXT, (GLuint, GLint, GLsizei, const GLuint *)) AGL_API(void, NamedBufferDataEXT, (GLuint, GLsizeiptr, const GLvoid *, GLenum)) AGL_API(void, NamedBufferSubDataEXT, (GLuint, GLintptr, GLsizeiptr, const GLvoid *)) AGL_API(GLvoid*, MapNamedBufferEXT, (GLuint, GLenum)) AGL_API(GLboolean, UnmapNamedBufferEXT, (GLuint)) AGL_API(void, GetNamedBufferParameterivEXT, (GLuint, GLenum, GLint *)) AGL_API(void, GetNamedBufferPointervEXT, (GLuint, GLenum, GLvoid* *)) AGL_API(void, GetNamedBufferSubDataEXT, (GLuint, GLintptr, GLsizeiptr, GLvoid *)) AGL_API(void, TextureBufferEXT, (GLuint, GLenum, GLenum, GLuint)) AGL_API(void, MultiTexBufferEXT, (GLenum, GLenum, GLenum, GLuint)) AGL_API(void, NamedRenderbufferStorageEXT, (GLuint, GLenum, GLsizei, GLsizei)) AGL_API(void, GetNamedRenderbufferParameterivEXT, (GLuint, GLenum, GLint *)) AGL_API(GLenum, CheckNamedFramebufferStatusEXT, (GLuint, GLenum)) AGL_API(void, NamedFramebufferTexture1DEXT, (GLuint, GLenum, GLenum, GLuint, GLint)) AGL_API(void, NamedFramebufferTexture2DEXT, (GLuint, GLenum, GLenum, GLuint, GLint)) AGL_API(void, NamedFramebufferTexture3DEXT, (GLuint, GLenum, GLenum, GLuint, GLint, GLint)) AGL_API(void, NamedFramebufferRenderbufferEXT, (GLuint, GLenum, GLenum, GLuint)) AGL_API(void, GetNamedFramebufferAttachmentParameterivEXT, (GLuint, GLenum, GLenum, GLint *)) AGL_API(void, GenerateTextureMipmapEXT, (GLuint, GLenum)) AGL_API(void, GenerateMultiTexMipmapEXT, (GLenum, GLenum)) AGL_API(void, FramebufferDrawBufferEXT, (GLuint, GLenum)) AGL_API(void, FramebufferDrawBuffersEXT, (GLuint, GLsizei, const GLenum *)) AGL_API(void, FramebufferReadBufferEXT, (GLuint, GLenum)) AGL_API(void, GetFramebufferParameterivEXT, (GLuint, GLenum, GLint *)) AGL_API(void, NamedRenderbufferStorageMultisampleEXT, (GLuint, GLsizei, GLenum, GLsizei, GLsizei)) AGL_API(void, NamedRenderbufferStorageMultisampleCoverageEXT, (GLuint, GLsizei, GLsizei, GLenum, GLsizei, GLsizei)) AGL_API(void, NamedFramebufferTextureEXT, (GLuint, GLenum, GLuint, GLint)) AGL_API(void, NamedFramebufferTextureLayerEXT, (GLuint, GLenum, GLuint, GLint, GLint)) AGL_API(void, NamedFramebufferTextureFaceEXT, (GLuint, GLenum, GLuint, GLint, GLenum)) AGL_API(void, TextureRenderbufferEXT, (GLuint, GLenum, GLuint)) AGL_API(void, MultiTexRenderbufferEXT, (GLenum, GLenum, GLuint)) #endif allegro4.4-4.4.2/addons/allegrogl/include/allegrogl/GLext/gl_ext_defs.h000066400000000000000000005155151173507505700257140ustar00rootroot00000000000000/* */ #ifndef GL_VERSION_1_2 #define GL_VERSION_1_2 1 #define AGL_VERSION_1_2 #define GL_UNSIGNED_BYTE_3_3_2 0x8032 #define GL_UNSIGNED_SHORT_4_4_4_4 0x8033 #define GL_UNSIGNED_SHORT_5_5_5_1 0x8034 #define GL_UNSIGNED_INT_8_8_8_8 0x8035 #define GL_UNSIGNED_INT_10_10_10_2 0x8036 #define GL_RESCALE_NORMAL 0x803A #define GL_TEXTURE_BINDING_3D 0x806A #define GL_PACK_SKIP_IMAGES 0x806B #define GL_PACK_IMAGE_HEIGHT 0x806C #define GL_UNPACK_SKIP_IMAGES 0x806D #define GL_UNPACK_IMAGE_HEIGHT 0x806E #define GL_TEXTURE_3D 0x806F #define GL_PROXY_TEXTURE_3D 0x8070 #define GL_TEXTURE_DEPTH 0x8071 #define GL_TEXTURE_WRAP_R 0x8072 #define GL_MAX_3D_TEXTURE_SIZE 0x8073 #define GL_UNSIGNED_BYTE_2_3_3_REV 0x8362 #define GL_UNSIGNED_SHORT_5_6_5 0x8363 #define GL_UNSIGNED_SHORT_5_6_5_REV 0x8364 #define GL_UNSIGNED_SHORT_4_4_4_4_REV 0x8365 #define GL_UNSIGNED_SHORT_1_5_5_5_REV 0x8366 #define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367 #define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368 #define GL_BGR 0x80E0 #define GL_BGRA 0x80E1 #define GL_MAX_ELEMENTS_VERTICES 0x80E8 #define GL_MAX_ELEMENTS_INDICES 0x80E9 #define GL_CLAMP_TO_EDGE 0x812F #define GL_TEXTURE_MIN_LOD 0x813A #define GL_TEXTURE_MAX_LOD 0x813B #define GL_TEXTURE_BASE_LEVEL 0x813C #define GL_TEXTURE_MAX_LEVEL 0x813D #define GL_LIGHT_MODEL_COLOR_CONTROL 0x81F8 #define GL_SINGLE_COLOR 0x81F9 #define GL_SEPARATE_SPECULAR_COLOR 0x81FA #define GL_SMOOTH_POINT_SIZE_RANGE 0x0B12 #define GL_SMOOTH_POINT_SIZE_GRANULARITY 0x0B13 #define GL_SMOOTH_LINE_WIDTH_RANGE 0x0B22 #define GL_SMOOTH_LINE_WIDTH_GRANULARITY 0x0B23 #define GL_ALIASED_POINT_SIZE_RANGE 0x846D #define GL_ALIASED_LINE_WIDTH_RANGE 0x846E #endif #ifndef GL_ARB_imaging #define GL_ARB_imaging #define AGL_ARB_imaging #define GL_CONSTANT_COLOR 0x8001 #define GL_ONE_MINUS_CONSTANT_COLOR 0x8002 #define GL_CONSTANT_ALPHA 0x8003 #define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004 #define GL_BLEND_COLOR 0x8005 #define GL_FUNC_ADD 0x8006 #define GL_MIN 0x8007 #define GL_MAX 0x8008 #define GL_BLEND_EQUATION 0x8009 #define GL_FUNC_SUBTRACT 0x800A #define GL_FUNC_REVERSE_SUBTRACT 0x800B #define GL_CONVOLUTION_1D 0x8010 #define GL_CONVOLUTION_2D 0x8011 #define GL_SEPARABLE_2D 0x8012 #define GL_CONVOLUTION_BORDER_MODE 0x8013 #define GL_CONVOLUTION_FILTER_SCALE 0x8014 #define GL_CONVOLUTION_FILTER_BIAS 0x8015 #define GL_REDUCE 0x8016 #define GL_CONVOLUTION_FORMAT 0x8017 #define GL_CONVOLUTION_WIDTH 0x8018 #define GL_CONVOLUTION_HEIGHT 0x8019 #define GL_MAX_CONVOLUTION_WIDTH 0x801A #define GL_MAX_CONVOLUTION_HEIGHT 0x801B #define GL_POST_CONVOLUTION_RED_SCALE 0x801C #define GL_POST_CONVOLUTION_GREEN_SCALE 0x801D #define GL_POST_CONVOLUTION_BLUE_SCALE 0x801E #define GL_POST_CONVOLUTION_ALPHA_SCALE 0x801F #define GL_POST_CONVOLUTION_RED_BIAS 0x8020 #define GL_POST_CONVOLUTION_GREEN_BIAS 0x8021 #define GL_POST_CONVOLUTION_BLUE_BIAS 0x8022 #define GL_POST_CONVOLUTION_ALPHA_BIAS 0x8023 #define GL_HISTOGRAM 0x8024 #define GL_PROXY_HISTOGRAM 0x8025 #define GL_HISTOGRAM_WIDTH 0x8026 #define GL_HISTOGRAM_FORMAT 0x8027 #define GL_HISTOGRAM_RED_SIZE 0x8028 #define GL_HISTOGRAM_GREEN_SIZE 0x8029 #define GL_HISTOGRAM_BLUE_SIZE 0x802A #define GL_HISTOGRAM_ALPHA_SIZE 0x802B #define GL_HISTOGRAM_LUMINANCE_SIZE 0x802C #define GL_HISTOGRAM_SINK 0x802D #define GL_MINMAX 0x802E #define GL_MINMAX_FORMAT 0x802F #define GL_MINMAX_SINK 0x8030 #define GL_TABLE_TOO_LARGE 0x8031 #define GL_COLOR_MATRIX 0x80B1 #define GL_COLOR_MATRIX_STACK_DEPTH 0x80B2 #define GL_MAX_COLOR_MATRIX_STACK_DEPTH 0x80B3 #define GL_POST_COLOR_MATRIX_RED_SCALE 0x80B4 #define GL_POST_COLOR_MATRIX_GREEN_SCALE 0x80B5 #define GL_POST_COLOR_MATRIX_BLUE_SCALE 0x80B6 #define GL_POST_COLOR_MATRIX_ALPHA_SCALE 0x80B7 #define GL_POST_COLOR_MATRIX_RED_BIAS 0x80B8 #define GL_POST_COLOR_MATRIX_GREEN_BIAS 0x80B9 #define GL_POST_COLOR_MATRIX_BLUE_BIAS 0x80BA #define GL_POST_COLOR_MATRIX_ALPHA_BIAS 0x80BB #define GL_COLOR_TABLE 0x80D0 #define GL_POST_CONVOLUTION_COLOR_TABLE 0x80D1 #define GL_POST_COLOR_MATRIX_COLOR_TABLE 0x80D2 #define GL_PROXY_COLOR_TABLE 0x80D3 #define GL_PROXY_POST_CONVOLUTION_COLOR_TABLE 0x80D4 #define GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE 0x80D5 #define GL_COLOR_TABLE_SCALE 0x80D6 #define GL_COLOR_TABLE_BIAS 0x80D7 #define GL_COLOR_TABLE_FORMAT 0x80D8 #define GL_COLOR_TABLE_WIDTH 0x80D9 #define GL_COLOR_TABLE_RED_SIZE 0x80DA #define GL_COLOR_TABLE_GREEN_SIZE 0x80DB #define GL_COLOR_TABLE_BLUE_SIZE 0x80DC #define GL_COLOR_TABLE_ALPHA_SIZE 0x80DD #define GL_COLOR_TABLE_LUMINANCE_SIZE 0x80DE #define GL_COLOR_TABLE_INTENSITY_SIZE 0x80DF #define GL_CONSTANT_BORDER 0x8151 #define GL_REPLICATE_BORDER 0x8153 #define GL_CONVOLUTION_BORDER_COLOR 0x8154 #endif #ifndef GL_VERSION_1_3 #define GL_VERSION_1_3 1 #define AGL_VERSION_1_3 #define GL_TEXTURE0 0x84C0 #define GL_TEXTURE1 0x84C1 #define GL_TEXTURE2 0x84C2 #define GL_TEXTURE3 0x84C3 #define GL_TEXTURE4 0x84C4 #define GL_TEXTURE5 0x84C5 #define GL_TEXTURE6 0x84C6 #define GL_TEXTURE7 0x84C7 #define GL_TEXTURE8 0x84C8 #define GL_TEXTURE9 0x84C9 #define GL_TEXTURE10 0x84CA #define GL_TEXTURE11 0x84CB #define GL_TEXTURE12 0x84CC #define GL_TEXTURE13 0x84CD #define GL_TEXTURE14 0x84CE #define GL_TEXTURE15 0x84CF #define GL_TEXTURE16 0x84D0 #define GL_TEXTURE17 0x84D1 #define GL_TEXTURE18 0x84D2 #define GL_TEXTURE19 0x84D3 #define GL_TEXTURE20 0x84D4 #define GL_TEXTURE21 0x84D5 #define GL_TEXTURE22 0x84D6 #define GL_TEXTURE23 0x84D7 #define GL_TEXTURE24 0x84D8 #define GL_TEXTURE25 0x84D9 #define GL_TEXTURE26 0x84DA #define GL_TEXTURE27 0x84DB #define GL_TEXTURE28 0x84DC #define GL_TEXTURE29 0x84DD #define GL_TEXTURE30 0x84DE #define GL_TEXTURE31 0x84DF #define GL_ACTIVE_TEXTURE 0x84E0 #define GL_CLIENT_ACTIVE_TEXTURE 0x84E1 #define GL_MAX_TEXTURE_UNITS 0x84E2 #define GL_TRANSPOSE_MODELVIEW_MATRIX 0x84E3 #define GL_TRANSPOSE_PROJECTION_MATRIX 0x84E4 #define GL_TRANSPOSE_TEXTURE_MATRIX 0x84E5 #define GL_TRANSPOSE_COLOR_MATRIX 0x84E6 #define GL_MULTISAMPLE 0x809D #define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E #define GL_SAMPLE_ALPHA_TO_ONE 0x809F #define GL_SAMPLE_COVERAGE 0x80A0 #define GL_SAMPLE_BUFFERS 0x80A8 #define GL_SAMPLES 0x80A9 #define GL_SAMPLE_COVERAGE_VALUE 0x80AA #define GL_SAMPLE_COVERAGE_INVERT 0x80AB #define GL_MULTISAMPLE_BIT 0x20000000 #define GL_NORMAL_MAP 0x8511 #define GL_REFLECTION_MAP 0x8512 #define GL_TEXTURE_CUBE_MAP 0x8513 #define GL_TEXTURE_BINDING_CUBE_MAP 0x8514 #define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515 #define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516 #define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517 #define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518 #define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519 #define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A #define GL_PROXY_TEXTURE_CUBE_MAP 0x851B #define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C #define GL_COMPRESSED_ALPHA 0x84E9 #define GL_COMPRESSED_LUMINANCE 0x84EA #define GL_COMPRESSED_LUMINANCE_ALPHA 0x84EB #define GL_COMPRESSED_INTENSITY 0x84EC #define GL_COMPRESSED_RGB 0x84ED #define GL_COMPRESSED_RGBA 0x84EE #define GL_TEXTURE_COMPRESSION_HINT 0x84EF #define GL_TEXTURE_COMPRESSED_IMAGE_SIZE 0x86A0 #define GL_TEXTURE_COMPRESSED 0x86A1 #define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2 #define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3 #define GL_CLAMP_TO_BORDER 0x812D #define GL_CLAMP_TO_BORDER_SGIS 0x812D #define GL_COMBINE 0x8570 #define GL_COMBINE_RGB 0x8571 #define GL_COMBINE_ALPHA 0x8572 #define GL_SOURCE0_RGB 0x8580 #define GL_SOURCE1_RGB 0x8581 #define GL_SOURCE2_RGB 0x8582 #define GL_SOURCE0_ALPHA 0x8588 #define GL_SOURCE1_ALPHA 0x8589 #define GL_SOURCE2_ALPHA 0x858A #define GL_OPERAND0_RGB 0x8590 #define GL_OPERAND1_RGB 0x8591 #define GL_OPERAND2_RGB 0x8592 #define GL_OPERAND0_ALPHA 0x8598 #define GL_OPERAND1_ALPHA 0x8599 #define GL_OPERAND2_ALPHA 0x859A #define GL_RGB_SCALE 0x8573 #define GL_ADD_SIGNED 0x8574 #define GL_INTERPOLATE 0x8575 #define GL_SUBTRACT 0x84E7 #define GL_CONSTANT 0x8576 #define GL_PRIMARY_COLOR 0x8577 #define GL_PREVIOUS 0x8578 #define GL_DOT3_RGB 0x86AE #define GL_DOT3_RGBA 0x86AF #endif #ifndef GL_VERSION_1_4 #define GL_VERSION_1_4 1 #define AGL_VERSION_1_4 #define GL_BLEND_DST_RGB 0x80C8 #define GL_BLEND_SRC_RGB 0x80C9 #define GL_BLEND_DST_ALPHA 0x80CA #define GL_BLEND_SRC_ALPHA 0x80CB #define GL_POINT_SIZE_MIN 0x8126 #define GL_POINT_SIZE_MAX 0x8127 #define GL_POINT_FADE_THRESHOLD_SIZE 0x8128 #define GL_POINT_DISTANCE_ATTENUATION 0x8129 #define GL_GENERATE_MIPMAP 0x8191 #define GL_GENERATE_MIPMAP_HINT 0x8192 #define GL_DEPTH_COMPONENT16 0x81A5 #define GL_DEPTH_COMPONENT24 0x81A6 #define GL_DEPTH_COMPONENT32 0x81A7 #define GL_MIRRORED_REPEAT 0x8370 #define GL_FOG_COORDINATE_SOURCE 0x8450 #define GL_FOG_COORDINATE 0x8451 #define GL_FRAGMENT_DEPTH 0x8452 #define GL_CURRENT_FOG_COORDINATE 0x8453 #define GL_FOG_COORDINATE_ARRAY_TYPE 0x8454 #define GL_FOG_COORDINATE_ARRAY_STRIDE 0x8455 #define GL_FOG_COORDINATE_ARRAY_POINTER 0x8456 #define GL_FOG_COORDINATE_ARRAY 0x8457 #define GL_COLOR_SUM 0x8458 #define GL_CURRENT_SECONDARY_COLOR 0x8459 #define GL_SECONDARY_COLOR_ARRAY_SIZE 0x845A #define GL_SECONDARY_COLOR_ARRAY_TYPE 0x845B #define GL_SECONDARY_COLOR_ARRAY_STRIDE 0x845C #define GL_SECONDARY_COLOR_ARRAY_POINTER 0x845D #define GL_SECONDARY_COLOR_ARRAY 0x845E #define GL_MAX_TEXTURE_LOD_BIAS 0x84FD #define GL_TEXTURE_FILTER_CONTROL 0x8500 #define GL_TEXTURE_LOD_BIAS 0x8501 #define GL_INCR_WRAP 0x8507 #define GL_DECR_WRAP 0x8508 #define GL_TEXTURE_DEPTH_SIZE 0x884A #define GL_DEPTH_TEXTURE_MODE 0x884B #define GL_TEXTURE_COMPARE_MODE 0x884C #define GL_TEXTURE_COMPARE_FUNC 0x884D #define GL_COMPARE_R_TO_TEXTURE 0x884E #endif #ifndef GL_VERSION_1_5 #define GL_VERSION_1_5 1 #define AGL_VERSION_1_5 /* New types */ #include typedef ptrdiff_t GLintptr; typedef ptrdiff_t GLsizeiptr; /* Renamed enumerants */ #define GL_FOG_COORD_SRC GL_FOG_COORDINATE_SOURCE #define GL_FOG_COORD GL_FOG_COORDINATE #define GL_CURRENT_FOG_COORD GL_CURRENT_FOG_COORDINATE #define GL_FOG_COORD_ARRAY_TYPE GL_FOG_COORDINATE_ARRAY_TYPE #define GL_FOG_COORD_ARRAY_STRIDE GL_FOG_COORDINATE_ARRAY_STRIDE #define GL_FOG_COORD_ARRAY_POINTER GL_FOG_COORDINATE_ARRAY_POINTER #define GL_FOG_COORD_ARRAY GL_FOG_COORDINATE_ARRAY #define GL_SRC0_RGB GL_SOURCE0_RGB #define GL_SRC1_RGB GL_SOURCE1_RGB #define GL_SRC2_RGB GL_SOURCE2_RGB #define GL_SRC0_ALPHA GL_SOURCE0_ALPHA #define GL_SRC1_ALPHA GL_SOURCE1_ALPHA #define GL_SRC2_ALPHA GL_SOURCE2_ALPHA /* Promoted exts */ #define GL_BUFFER_SIZE 0x8764 #define GL_BUFFER_USAGE 0x8765 #define GL_ARRAY_BUFFER 0x8892 #define GL_ELEMENT_ARRAY_BUFFER 0x8893 #define GL_ARRAY_BUFFER_BINDING 0x8894 #define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895 #define GL_VERTEX_ARRAY_BUFFER_BINDING 0x8896 #define GL_NORMAL_ARRAY_BUFFER_BINDING 0x8897 #define GL_COLOR_ARRAY_BUFFER_BINDING 0x8898 #define GL_INDEX_ARRAY_BUFFER_BINDING 0x8899 #define GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING 0x889A #define GL_EDGE_FLAG_ARRAY_BUFFER_BINDING 0x889B #define GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING 0x889C #define GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING 0x889D #define GL_WEIGHT_ARRAY_BUFFER_BINDING 0x889E #define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F #define GL_READ_ONLY 0x88B8 #define GL_WRITE_ONLY 0x88B9 #define GL_READ_WRITE 0x88BA #define GL_BUFFER_ACCESS 0x88BB #define GL_BUFFER_MAPPED 0x88BC #define GL_BUFFER_MAP_POINTER 0x88BD #define GL_STREAM_DRAW 0x88E0 #define GL_STREAM_READ 0x88E1 #define GL_STREAM_COPY 0x88E2 #define GL_STATIC_DRAW 0x88E4 #define GL_STATIC_READ 0x88E5 #define GL_STATIC_COPY 0x88E6 #define GL_DYNAMIC_DRAW 0x88E8 #define GL_DYNAMIC_READ 0x88E9 #define GL_DYNAMIC_COPY 0x88EA #define GL_SAMPLES_PASSED 0x8914 #define GL_QUERY_COUNTER_BITS 0x8864 #define GL_CURRENT_QUERY 0x8865 #define GL_QUERY_RESULT 0x8866 #define GL_QUERY_RESULT_AVAILABLE 0x8867 #endif #ifndef GL_VERSION_2_0 #define GL_VERSION_2_0 1 #define AGL_VERSION_2_0 /* New types */ typedef char GLchar; #define GL_BLEND_EQUATION_RGB GL_BLEND_EQUATION #define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622 #define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623 #define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624 #define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625 #define GL_CURRENT_VERTEX_ATTRIB 0x8626 #define GL_VERTEX_PROGRAM_POINT_SIZE 0x8642 #define GL_VERTEX_PROGRAM_TWO_SIDE 0x8643 #define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645 #define GL_STENCIL_BACK_FUNC 0x8800 #define GL_STENCIL_BACK_FAIL 0x8801 #define GL_STENCIL_BACK_PASS_DEPTH_FAIL 0x8802 #define GL_STENCIL_BACK_PASS_DEPTH_PASS 0x8803 #define GL_MAX_DRAW_BUFFERS 0x8824 #define GL_DRAW_BUFFER0 0x8825 #define GL_DRAW_BUFFER1 0x8826 #define GL_DRAW_BUFFER2 0x8827 #define GL_DRAW_BUFFER3 0x8828 #define GL_DRAW_BUFFER4 0x8829 #define GL_DRAW_BUFFER5 0x882A #define GL_DRAW_BUFFER6 0x882B #define GL_DRAW_BUFFER7 0x882C #define GL_DRAW_BUFFER8 0x882D #define GL_DRAW_BUFFER9 0x882E #define GL_DRAW_BUFFER10 0x882F #define GL_DRAW_BUFFER11 0x8830 #define GL_DRAW_BUFFER12 0x8831 #define GL_DRAW_BUFFER13 0x8832 #define GL_DRAW_BUFFER14 0x8833 #define GL_DRAW_BUFFER15 0x8834 #define GL_BLEND_EQUATION_ALPHA 0x883D #define GL_POINT_SPRITE 0x8861 #define GL_COORD_REPLACE 0x8862 #define GL_MAX_VERTEX_ATTRIBS 0x8869 #define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A #define GL_MAX_TEXTURE_COORDS 0x8871 #define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872 #define GL_FRAGMENT_SHADER 0x8B30 #define GL_VERTEX_SHADER 0x8B31 #define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS 0x8B49 #define GL_MAX_VERTEX_UNIFORM_COMPONENTS 0x8B4A #define GL_MAX_VARYING_FLOATS 0x8B4B #define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C #define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D #define GL_SHADER_TYPE 0x8B4F #define GL_FLOAT_VEC2 0x8B50 #define GL_FLOAT_VEC3 0x8B51 #define GL_FLOAT_VEC4 0x8B52 #define GL_INT_VEC2 0x8B53 #define GL_INT_VEC3 0x8B54 #define GL_INT_VEC4 0x8B55 #define GL_BOOL 0x8B56 #define GL_BOOL_VEC2 0x8B57 #define GL_BOOL_VEC3 0x8B58 #define GL_BOOL_VEC4 0x8B59 #define GL_FLOAT_MAT2 0x8B5A #define GL_FLOAT_MAT3 0x8B5B #define GL_FLOAT_MAT4 0x8B5C #define GL_SAMPLER_1D 0x8B5D #define GL_SAMPLER_2D 0x8B5E #define GL_SAMPLER_3D 0x8B5F #define GL_SAMPLER_CUBE 0x8B60 #define GL_SAMPLER_1D_SHADOW 0x8B61 #define GL_SAMPLER_2D_SHADOW 0x8B62 #define GL_DELETE_STATUS 0x8B80 #define GL_COMPILE_STATUS 0x8B81 #define GL_LINK_STATUS 0x8B82 #define GL_VALIDATE_STATUS 0x8B83 #define GL_INFO_LOG_LENGTH 0x8B84 #define GL_ATTACHED_SHADERS 0x8B85 #define GL_ACTIVE_UNIFORMS 0x8B86 #define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87 #define GL_SHADER_SOURCE_LENGTH 0x8B88 #define GL_ACTIVE_ATTRIBUTES 0x8B89 #define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A #define GL_FRAGMENT_SHADER_DERIVATIVE_HINT 0x8B8B #define GL_SHADING_LANGUAGE_VERSION 0x8B8C #define GL_CURRENT_PROGRAM 0x8B8D #define GL_POINT_SPRITE_COORD_ORIGIN 0x8CA0 #define GL_LOWER_LEFT 0x8CA1 #define GL_UPPER_LEFT 0x8CA2 #define GL_STENCIL_BACK_REF 0x8CA3 #define GL_STENCIL_BACK_VALUE_MASK 0x8CA4 #define GL_STENCIL_BACK_WRITEMASK 0x8CA5 #endif #ifndef GL_VERSION_2_1 #define GL_VERSION_2_1 1 #define AGL_VERSION_2_1 #define GL_CURRENT_RASTER_SECONDARY_COLOR 0x845F #define GL_PIXEL_PACK_BUFFER 0x88EB #define GL_PIXEL_UNPACK_BUFFER 0x88EC #define GL_PIXEL_PACK_BUFFER_BINDING 0x88ED #define GL_PIXEL_UNPACK_BUFFER_BINDING 0x88EF #define GL_FLOAT_MAT2x3 0x8B65 #define GL_FLOAT_MAT2x4 0x8B66 #define GL_FLOAT_MAT3x2 0x8B67 #define GL_FLOAT_MAT3x4 0x8B68 #define GL_FLOAT_MAT4x2 0x8B69 #define GL_FLOAT_MAT4x3 0x8B6A #define GL_SRGB 0x8C40 #define GL_SRGB8 0x8C41 #define GL_SRGB_ALPHA 0x8C42 #define GL_SRGB8_ALPHA8 0x8C43 #define GL_SLUMINANCE_ALPHA 0x8C44 #define GL_SLUMINANCE8_ALPHA8 0x8C45 #define GL_SLUMINANCE 0x8C46 #define GL_SLUMINANCE8 0x8C47 #define GL_COMPRESSED_SRGB 0x8C48 #define GL_COMPRESSED_SRGB_ALPHA 0x8C49 #define GL_COMPRESSED_SLUMINANCE 0x8C4A #define GL_COMPRESSED_SLUMINANCE_ALPHA 0x8C4B #endif #ifndef GL_VERSION_3_0 #define GL_VERSION_3_0 #define AGL_VERSION_3_0 #define GL_COMPARE_REF_TO_TEXTURE GL_COMPARE_R_TO_TEXTURE_ARB #define GL_CLIP_DISTANCE0 GL_CLIP_PLANE0 #define GL_CLIP_DISTANCE1 GL_CLIP_PLANE1 #define GL_CLIP_DISTANCE2 GL_CLIP_PLANE2 #define GL_CLIP_DISTANCE3 GL_CLIP_PLANE3 #define GL_CLIP_DISTANCE4 GL_CLIP_PLANE4 #define GL_CLIP_DISTANCE5 GL_CLIP_PLANE5 #define GL_MAX_CLIP_DISTANCES GL_MAX_CLIP_PLANES #define GL_MAJOR_VERSION 0x821B #define GL_MINOR_VERSION 0x821C #define GL_NUM_EXTENSIONS 0x821D #define GL_CONTEXT_FLAGS 0x821E #define GL_DEPTH_BUFFER 0x8223 #define GL_STENCIL_BUFFER 0x8224 #define GL_COMPRESSED_RED 0x8225 #define GL_COMPRESSED_RG 0x8226 #define GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT 0x0001 #define GL_RGBA32F 0x8814 #define GL_RGB32F 0x8815 #define GL_RGBA16F 0x881A #define GL_RGB16F 0x881B #define GL_VERTEX_ATTRIB_ARRAY_INTEGER 0x88FD #define GL_MAX_ARRAY_TEXTURE_LAYERS 0x88FF #define GL_MIN_PROGRAM_TEXEL_OFFSET 0x8904 #define GL_MAX_PROGRAM_TEXEL_OFFSET 0x8905 #define GL_CLAMP_VERTEX_COLOR 0x891A #define GL_CLAMP_FRAGMENT_COLOR 0x891B #define GL_CLAMP_READ_COLOR 0x891C #define GL_FIXED_ONLY 0x891D #define GL_MAX_VARYING_COMPONENTS GL_MAX_VARYING_FLOATS #define GL_TEXTURE_RED_TYPE 0x8C10 #define GL_TEXTURE_GREEN_TYPE 0x8C11 #define GL_TEXTURE_BLUE_TYPE 0x8C12 #define GL_TEXTURE_ALPHA_TYPE 0x8C13 #define GL_TEXTURE_LUMINANCE_TYPE 0x8C14 #define GL_TEXTURE_INTENSITY_TYPE 0x8C15 #define GL_TEXTURE_DEPTH_TYPE 0x8C16 #define GL_UNSIGNED_NORMALIZED 0x8C17 #define GL_TEXTURE_1D_ARRAY 0x8C18 #define GL_PROXY_TEXTURE_1D_ARRAY 0x8C19 #define GL_TEXTURE_2D_ARRAY 0x8C1A #define GL_PROXY_TEXTURE_2D_ARRAY 0x8C1B #define GL_TEXTURE_BINDING_1D_ARRAY 0x8C1C #define GL_TEXTURE_BINDING_2D_ARRAY 0x8C1D #define GL_R11F_G11F_B10F 0x8C3A #define GL_UNSIGNED_INT_10F_11F_11F_REV 0x8C3B #define GL_RGB9_E5 0x8C3D #define GL_UNSIGNED_INT_5_9_9_9_REV 0x8C3E #define GL_TEXTURE_SHARED_SIZE 0x8C3F #define GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH 0x8C76 #define GL_TRANSFORM_FEEDBACK_BUFFER_MODE 0x8C7F #define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS 0x8C80 #define GL_TRANSFORM_FEEDBACK_VARYINGS 0x8C83 #define GL_TRANSFORM_FEEDBACK_BUFFER_START 0x8C84 #define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE 0x8C85 #define GL_PRIMITIVES_GENERATED 0x8C87 #define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN 0x8C88 #define GL_RASTERIZER_DISCARD 0x8C89 #define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS 0x8C8A #define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS 0x8C8B #define GL_INTERLEAVED_ATTRIBS 0x8C8C #define GL_SEPARATE_ATTRIBS 0x8C8D #define GL_TRANSFORM_FEEDBACK_BUFFER 0x8C8E #define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING 0x8C8F #define GL_RGBA32UI 0x8D70 #define GL_RGB32UI 0x8D71 #define GL_RGBA16UI 0x8D76 #define GL_RGB16UI 0x8D77 #define GL_RGBA8UI 0x8D7C #define GL_RGB8UI 0x8D7D #define GL_RGBA32I 0x8D82 #define GL_RGB32I 0x8D83 #define GL_RGBA16I 0x8D88 #define GL_RGB16I 0x8D89 #define GL_RGBA8I 0x8D8E #define GL_RGB8I 0x8D8F #define GL_RED_INTEGER 0x8D94 #define GL_GREEN_INTEGER 0x8D95 #define GL_BLUE_INTEGER 0x8D96 #define GL_ALPHA_INTEGER 0x8D97 #define GL_RGB_INTEGER 0x8D98 #define GL_RGBA_INTEGER 0x8D99 #define GL_BGR_INTEGER 0x8D9A #define GL_BGRA_INTEGER 0x8D9B #define GL_SAMPLER_1D_ARRAY 0x8DC0 #define GL_SAMPLER_2D_ARRAY 0x8DC1 #define GL_SAMPLER_1D_ARRAY_SHADOW 0x8DC3 #define GL_SAMPLER_2D_ARRAY_SHADOW 0x8DC4 #define GL_SAMPLER_CUBE_SHADOW 0x8DC5 #define GL_UNSIGNED_INT_VEC2 0x8DC6 #define GL_UNSIGNED_INT_VEC3 0x8DC7 #define GL_UNSIGNED_INT_VEC4 0x8DC8 #define GL_INT_SAMPLER_1D 0x8DC9 #define GL_INT_SAMPLER_2D 0x8DCA #define GL_INT_SAMPLER_3D 0x8DCB #define GL_INT_SAMPLER_CUBE 0x8DCC #define GL_INT_SAMPLER_1D_ARRAY 0x8DCE #define GL_INT_SAMPLER_2D_ARRAY 0x8DCF #define GL_UNSIGNED_INT_SAMPLER_1D 0x8DD1 #define GL_UNSIGNED_INT_SAMPLER_2D 0x8DD2 #define GL_UNSIGNED_INT_SAMPLER_3D 0x8DD3 #define GL_UNSIGNED_INT_SAMPLER_CUBE 0x8DD4 #define GL_UNSIGNED_INT_SAMPLER_1D_ARRAY 0x8DD6 #define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY 0x8DD7 #define GL_QUERY_WAIT 0x8E13 #define GL_QUERY_NO_WAIT 0x8E14 #define GL_QUERY_BY_REGION_WAIT 0x8E15 #define GL_QUERY_BY_REGION_NO_WAIT 0x8E16 #endif /* */ /* */ #ifndef GL_ARB_multitexture #define GL_ARB_multitexture #define AGL_ARB_multitexture #define GL_TEXTURE0_ARB 0x84C0 #define GL_TEXTURE1_ARB 0x84C1 #define GL_TEXTURE2_ARB 0x84C2 #define GL_TEXTURE3_ARB 0x84C3 #define GL_TEXTURE4_ARB 0x84C4 #define GL_TEXTURE5_ARB 0x84C5 #define GL_TEXTURE6_ARB 0x84C6 #define GL_TEXTURE7_ARB 0x84C7 #define GL_TEXTURE8_ARB 0x84C8 #define GL_TEXTURE9_ARB 0x84C9 #define GL_TEXTURE10_ARB 0x84CA #define GL_TEXTURE11_ARB 0x84CB #define GL_TEXTURE12_ARB 0x84CC #define GL_TEXTURE13_ARB 0x84CD #define GL_TEXTURE14_ARB 0x84CE #define GL_TEXTURE15_ARB 0x84CF #define GL_TEXTURE16_ARB 0x84D0 #define GL_TEXTURE17_ARB 0x84D1 #define GL_TEXTURE18_ARB 0x84D2 #define GL_TEXTURE19_ARB 0x84D3 #define GL_TEXTURE20_ARB 0x84D4 #define GL_TEXTURE21_ARB 0x84D5 #define GL_TEXTURE22_ARB 0x84D6 #define GL_TEXTURE23_ARB 0x84D7 #define GL_TEXTURE24_ARB 0x84D8 #define GL_TEXTURE25_ARB 0x84D9 #define GL_TEXTURE26_ARB 0x84DA #define GL_TEXTURE27_ARB 0x84DB #define GL_TEXTURE28_ARB 0x84DC #define GL_TEXTURE29_ARB 0x84DD #define GL_TEXTURE30_ARB 0x84DE #define GL_TEXTURE31_ARB 0x84DF #define GL_ACTIVE_TEXTURE_ARB 0x84E0 #define GL_CLIENT_ACTIVE_TEXTURE_ARB 0x84E1 #define GL_MAX_TEXTURE_UNITS_ARB 0x84E2 #endif #ifndef GL_ARB_transpose_matrix #define GL_ARB_transpose_matrix #define AGL_ARB_transpose_matrix #define GL_TRANSPOSE_MODELVIEW_MATRIX_ARB 0x84E3 #define GL_TRANSPOSE_PROJECTION_MATRIX_ARB 0x84E4 #define GL_TRANSPOSE_TEXTURE_MATRIX_ARB 0x84E5 #define GL_TRANSPOSE_COLOR_MATRIX_ARB 0x84E6 #endif #ifndef GL_ARB_multisample #define GL_ARB_multisample #define AGL_ARB_multisample #define GL_MULTISAMPLE_ARB 0x809D #define GL_SAMPLE_ALPHA_TO_COVERAGE_ARB 0x809E #define GL_SAMPLE_ALPHA_TO_ONE_ARB 0x809F #define GL_SAMPLE_COVERAGE_ARB 0x80A0 #define GL_SAMPLE_BUFFERS_ARB 0x80A8 #define GL_SAMPLES_ARB 0x80A9 #define GL_SAMPLE_COVERAGE_VALUE_ARB 0x80AA #define GL_SAMPLE_COVERAGE_INVERT_ARB 0x80AB #define GL_MULTISAMPLE_BIT_ARB 0x20000000 #endif #ifndef GL_ARB_texture_cube_map #define GL_ARB_texture_cube_map #define AGL_ARB_texture_cube_map #define GL_NORMAL_MAP_ARB 0x8511 #define GL_REFLECTION_MAP_ARB 0x8512 #define GL_TEXTURE_CUBE_MAP_ARB 0x8513 #define GL_TEXTURE_BINDING_CUBE_MAP_ARB 0x8514 #define GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB 0x8515 #define GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB 0x8516 #define GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB 0x8517 #define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB 0x8518 #define GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB 0x8519 #define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB 0x851A #define GL_PROXY_TEXTURE_CUBE_MAP_ARB 0x851B #define GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB 0x851C #endif #ifndef GL_ARB_texture_compression #define GL_ARB_texture_compression #define AGL_ARB_texture_compression #define GL_COMPRESSED_ALPHA_ARB 0x84E9 #define GL_COMPRESSED_LUMINANCE_ARB 0x84EA #define GL_COMPRESSED_LUMINANCE_ALPHA_ARB 0x84EB #define GL_COMPRESSED_INTENSITY_ARB 0x84EC #define GL_COMPRESSED_RGB_ARB 0x84ED #define GL_COMPRESSED_RGBA_ARB 0x84EE #define GL_TEXTURE_COMPRESSION_HINT_ARB 0x84EF #define GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB 0x86A0 #define GL_TEXTURE_COMPRESSED_ARB 0x86A1 #define GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB 0x86A2 #define GL_COMPRESSED_TEXTURE_FORMATS_ARB 0x86A3 #endif #ifndef GL_ARB_texture_border_clamp #define GL_ARB_texture_border_clamp #define AGL_ARB_texture_border_clamp #define GL_CLAMP_TO_BORDER_ARB 0x812D #endif #ifndef GL_ARB_point_parameters #define GL_ARB_point_parameters #define AGL_ARB_point_parameters #define GL_POINT_SIZE_MIN_ARB 0x8126 #define GL_POINT_SIZE_MAX_ARB 0x8127 #define GL_POINT_FADE_THRESHOLD_SIZE_ARB 0x8128 #define GL_POINT_DISTANCE_ATTENUATION_ARB 0x8129 #endif #ifndef GL_ARB_vertex_blend #define GL_ARB_vertex_blend #define AGL_ARB_vertex_blend #define GL_MAX_VERTEX_UNITS_ARB 0x86A4 #define GL_ACTIVE_VERTEX_UNITS_ARB 0x86A5 #define GL_WEIGHT_SUM_UNITY_ARB 0x86A6 #define GL_VERTEX_BLEND_ARB 0x86A7 #define GL_CURRENT_WEIGHT_ARB 0x86A8 #define GL_WEIGHT_ARRAY_TYPE_ARB 0x86A9 #define GL_WEIGHT_ARRAY_STRIDE_ARB 0x86AA #define GL_WEIGHT_ARRAY_SIZE_ARB 0x86AB #define GL_WEIGHT_ARRAY_POINTER_ARB 0x86AC #define GL_WEIGHT_ARRAY_ARB 0x86AD #define GL_MODELVIEW0_ARB 0x1700 #define GL_MODELVIEW1_ARB 0x850A #define GL_MODELVIEW2_ARB 0x8722 #define GL_MODELVIEW3_ARB 0x8723 #define GL_MODELVIEW4_ARB 0x8724 #define GL_MODELVIEW5_ARB 0x8725 #define GL_MODELVIEW6_ARB 0x8726 #define GL_MODELVIEW7_ARB 0x8727 #define GL_MODELVIEW8_ARB 0x8728 #define GL_MODELVIEW9_ARB 0x8729 #define GL_MODELVIEW10_ARB 0x872A #define GL_MODELVIEW11_ARB 0x872B #define GL_MODELVIEW12_ARB 0x872C #define GL_MODELVIEW13_ARB 0x872D #define GL_MODELVIEW14_ARB 0x872E #define GL_MODELVIEW15_ARB 0x872F #define GL_MODELVIEW16_ARB 0x8730 #define GL_MODELVIEW17_ARB 0x8731 #define GL_MODELVIEW18_ARB 0x8732 #define GL_MODELVIEW19_ARB 0x8733 #define GL_MODELVIEW20_ARB 0x8734 #define GL_MODELVIEW21_ARB 0x8735 #define GL_MODELVIEW22_ARB 0x8736 #define GL_MODELVIEW23_ARB 0x8737 #define GL_MODELVIEW24_ARB 0x8738 #define GL_MODELVIEW25_ARB 0x8739 #define GL_MODELVIEW26_ARB 0x873A #define GL_MODELVIEW27_ARB 0x873B #define GL_MODELVIEW28_ARB 0x873C #define GL_MODELVIEW29_ARB 0x873D #define GL_MODELVIEW30_ARB 0x873E #define GL_MODELVIEW31_ARB 0x873F #endif #ifndef GL_ARB_matrix_palette #define GL_ARB_matrix_palette #define AGL_ARB_matrix_palette #define GL_MATRIX_PALETTE_ARB 0x8840 #define GL_MAX_MATRIX_PALETTE_STACK_DEPTH_ARB 0x8841 #define GL_MAX_PALETTE_MATRICES_ARB 0x8842 #define GL_CURRENT_PALETTE_MATRIX_ARB 0x8843 #define GL_MATRIX_INDEX_ARRAY_ARB 0x8844 #define GL_CURRENT_MATRIX_INDEX_ARB 0x8845 #define GL_MATRIX_INDEX_ARRAY_SIZE_ARB 0x8846 #define GL_MATRIX_INDEX_ARRAY_TYPE_ARB 0x8847 #define GL_MATRIX_INDEX_ARRAY_STRIDE_ARB 0x8848 #define GL_MATRIX_INDEX_ARRAY_POINTER_ARB 0x8849 #endif #ifndef GL_ARB_texture_env_combine #define GL_ARB_texture_env_combine #define AGL_ARB_texture_env_combine #define GL_COMBINE_ARB 0x8570 #define GL_COMBINE_RGB_ARB 0x8571 #define GL_COMBINE_ALPHA_ARB 0x8572 #define GL_SOURCE0_RGB_ARB 0x8580 #define GL_SOURCE1_RGB_ARB 0x8581 #define GL_SOURCE2_RGB_ARB 0x8582 #define GL_SOURCE0_ALPHA_ARB 0x8588 #define GL_SOURCE1_ALPHA_ARB 0x8589 #define GL_SOURCE2_ALPHA_ARB 0x858A #define GL_OPERAND0_RGB_ARB 0x8590 #define GL_OPERAND1_RGB_ARB 0x8591 #define GL_OPERAND2_RGB_ARB 0x8592 #define GL_OPERAND0_ALPHA_ARB 0x8598 #define GL_OPERAND1_ALPHA_ARB 0x8599 #define GL_OPERAND2_ALPHA_ARB 0x859A #define GL_RGB_SCALE_ARB 0x8573 #define GL_ADD_SIGNED_ARB 0x8574 #define GL_INTERPOLATE_ARB 0x8575 #define GL_SUBTRACT_ARB 0x84E7 #define GL_CONSTANT_ARB 0x8576 #define GL_PRIMARY_COLOR_ARB 0x8577 #define GL_PREVIOUS_ARB 0x8578 #endif #ifndef GL_ARB_texture_env_dot3 #define GL_ARB_texture_env_dot3 #define AGL_ARB_texture_env_dot3 #define GL_DOT3_RGB_ARB 0x86AE #define GL_DOT3_RGBA_ARB 0x86AF #endif #ifndef GL_ARB_texture_mirrored_repeat #define GL_ARB_texture_mirrored_repeat #define AGL_ARB_texture_mirrored_repeat #define GL_MIRRORED_REPEAT_ARB 0x8370 #endif #ifndef GL_ARB_depth_texture #define GL_ARB_depth_texture #define AGL_ARB_depth_texture #define GL_DEPTH_COMPONENT16_ARB 0x81A5 #define GL_DEPTH_COMPONENT24_ARB 0x81A6 #define GL_DEPTH_COMPONENT32_ARB 0x81A7 #define GL_TEXTURE_DEPTH_SIZE_ARB 0x884A #define GL_DEPTH_TEXTURE_MODE_ARB 0x884B #endif #ifndef GL_ARB_window_pos #define GL_ARB_window_pos #define AGL_ARB_window_pos #endif #ifndef GL_ARB_shadow #define GL_ARB_shadow #define AGL_ARB_shadow #define GL_TEXTURE_COMPARE_MODE_ARB 0x884C #define GL_TEXTURE_COMPARE_FUNC_ARB 0x884D #define GL_COMPARE_R_TO_TEXTURE_ARB 0x884E #endif #ifndef GL_ARB_shadow_ambient #define GL_ARB_shadow_ambient #define AGL_ARB_shadow_ambient #define GL_TEXTURE_COMPARE_FAIL_VALUE_ARB 0x80BF #endif #ifndef GL_ARB_vertex_program #define GL_ARB_vertex_program #define AGL_ARB_vertex_program #define GL_COLOR_SUM_ARB 0x8458 #define GL_VERTEX_PROGRAM_ARB 0x8620 #define GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB 0x8622 #define GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB 0x8623 #define GL_VERTEX_ATTRIB_ARRAY_STRIDE_ARB 0x8624 #define GL_VERTEX_ATTRIB_ARRAY_TYPE_ARB 0x8625 #define GL_CURRENT_VERTEX_ATTRIB_ARB 0x8626 #define GL_PROGRAM_LENGTH_ARB 0x8627 #define GL_PROGRAM_STRING_ARB 0x8628 #define GL_MAX_PROGRAM_MATRIX_STACK_DEPTH_ARB 0x862E #define GL_MAX_PROGRAM_MATRICES_ARB 0x862F #define GL_CURRENT_MATRIX_STACK_DEPTH_ARB 0x8640 #define GL_CURRENT_MATRIX_ARB 0x8641 #define GL_VERTEX_PROGRAM_POINT_SIZE_ARB 0x8642 #define GL_VERTEX_PROGRAM_TWO_SIDE_ARB 0x8643 #define GL_VERTEX_ATTRIB_ARRAY_POINTER_ARB 0x8645 #define GL_PROGRAM_ERROR_POSITION_ARB 0x864B #define GL_PROGRAM_BINDING_ARB 0x8677 #define GL_MAX_VERTEX_ATTRIBS_ARB 0x8869 #define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB 0x886A #define GL_PROGRAM_ERROR_STRING_ARB 0x8874 #define GL_PROGRAM_FORMAT_ASCII_ARB 0x8875 #define GL_PROGRAM_FORMAT_ARB 0x8876 #define GL_PROGRAM_INSTRUCTIONS_ARB 0x88A0 #define GL_MAX_PROGRAM_INSTRUCTIONS_ARB 0x88A1 #define GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB 0x88A2 #define GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB 0x88A3 #define GL_PROGRAM_TEMPORARIES_ARB 0x88A4 #define GL_MAX_PROGRAM_TEMPORARIES_ARB 0x88A5 #define GL_PROGRAM_NATIVE_TEMPORARIES_ARB 0x88A6 #define GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB 0x88A7 #define GL_PROGRAM_PARAMETERS_ARB 0x88A8 #define GL_MAX_PROGRAM_PARAMETERS_ARB 0x88A9 #define GL_PROGRAM_NATIVE_PARAMETERS_ARB 0x88AA #define GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB 0x88AB #define GL_PROGRAM_ATTRIBS_ARB 0x88AC #define GL_MAX_PROGRAM_ATTRIBS_ARB 0x88AD #define GL_PROGRAM_NATIVE_ATTRIBS_ARB 0x88AE #define GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB 0x88AF #define GL_PROGRAM_ADDRESS_REGISTERS_ARB 0x88B0 #define GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB 0x88B1 #define GL_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB 0x88B2 #define GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB 0x88B3 #define GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB 0x88B4 #define GL_MAX_PROGRAM_ENV_PARAMETERS_ARB 0x88B5 #define GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB 0x88B6 #define GL_TRANSPOSE_CURRENT_MATRIX_ARB 0x88B7 #define GL_MATRIX0_ARB 0x88C0 #define GL_MATRIX1_ARB 0x88C1 #define GL_MATRIX2_ARB 0x88C2 #define GL_MATRIX3_ARB 0x88C3 #define GL_MATRIX4_ARB 0x88C4 #define GL_MATRIX5_ARB 0x88C5 #define GL_MATRIX6_ARB 0x88C6 #define GL_MATRIX7_ARB 0x88C7 #define GL_MATRIX8_ARB 0x88C8 #define GL_MATRIX9_ARB 0x88C9 #define GL_MATRIX10_ARB 0x88CA #define GL_MATRIX11_ARB 0x88CB #define GL_MATRIX12_ARB 0x88CC #define GL_MATRIX13_ARB 0x88CD #define GL_MATRIX14_ARB 0x88CE #define GL_MATRIX15_ARB 0x88CF #define GL_MATRIX16_ARB 0x88D0 #define GL_MATRIX17_ARB 0x88D1 #define GL_MATRIX18_ARB 0x88D2 #define GL_MATRIX19_ARB 0x88D3 #define GL_MATRIX20_ARB 0x88D4 #define GL_MATRIX21_ARB 0x88D5 #define GL_MATRIX22_ARB 0x88D6 #define GL_MATRIX23_ARB 0x88D7 #define GL_MATRIX24_ARB 0x88D8 #define GL_MATRIX25_ARB 0x88D9 #define GL_MATRIX26_ARB 0x88DA #define GL_MATRIX27_ARB 0x88DB #define GL_MATRIX28_ARB 0x88DC #define GL_MATRIX29_ARB 0x88DD #define GL_MATRIX30_ARB 0x88DE #define GL_MATRIX31_ARB 0x88DF #endif #ifndef GL_ARB_fragment_program #define GL_ARB_fragment_program #define AGL_ARB_fragment_program #define GL_FRAGMENT_PROGRAM_ARB 0x8804 #define GL_PROGRAM_ALU_INSTRUCTIONS_ARB 0x8805 #define GL_PROGRAM_TEX_INSTRUCTIONS_ARB 0x8806 #define GL_PROGRAM_TEX_INDIRECTIONS_ARB 0x8807 #define GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB 0x8808 #define GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB 0x8809 #define GL_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB 0x880A #define GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB 0x880B #define GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB 0x880C #define GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB 0x880D #define GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB 0x880E #define GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB 0x880F #define GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB 0x8810 #define GL_MAX_TEXTURE_COORDS_ARB 0x8871 #define GL_MAX_TEXTURE_IMAGE_UNITS_ARB 0x8872 #endif #ifndef GL_ARB_vertex_buffer_object #define GL_ARB_vertex_buffer_object #define AGL_ARB_vertex_buffer_object #include typedef ptrdiff_t GLintptrARB; typedef ptrdiff_t GLsizeiptrARB; #define GL_BUFFER_SIZE_ARB 0x8764 #define GL_BUFFER_USAGE_ARB 0x8765 #define GL_ARRAY_BUFFER_ARB 0x8892 #define GL_ELEMENT_ARRAY_BUFFER_ARB 0x8893 #define GL_ARRAY_BUFFER_BINDING_ARB 0x8894 #define GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB 0x8895 #define GL_VERTEX_ARRAY_BUFFER_BINDING_ARB 0x8896 #define GL_NORMAL_ARRAY_BUFFER_BINDING_ARB 0x8897 #define GL_COLOR_ARRAY_BUFFER_BINDING_ARB 0x8898 #define GL_INDEX_ARRAY_BUFFER_BINDING_ARB 0x8899 #define GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING_ARB 0x889A #define GL_EDGE_FLAG_ARRAY_BUFFER_BINDING_ARB 0x889B #define GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING_ARB 0x889C #define GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING_ARB 0x889D #define GL_WEIGHT_ARRAY_BUFFER_BINDING_ARB 0x889E #define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB 0x889F #define GL_READ_ONLY_ARB 0x88B8 #define GL_WRITE_ONLY_ARB 0x88B9 #define GL_READ_WRITE_ARB 0x88BA #define GL_BUFFER_ACCESS_ARB 0x88BB #define GL_BUFFER_MAPPED_ARB 0x88BC #define GL_BUFFER_MAP_POINTER_ARB 0x88BD #define GL_STREAM_DRAW_ARB 0x88E0 #define GL_STREAM_READ_ARB 0x88E1 #define GL_STREAM_COPY_ARB 0x88E2 #define GL_STATIC_DRAW_ARB 0x88E4 #define GL_STATIC_READ_ARB 0x88E5 #define GL_STATIC_COPY_ARB 0x88E6 #define GL_DYNAMIC_DRAW_ARB 0x88E8 #define GL_DYNAMIC_READ_ARB 0x88E9 #define GL_DYNAMIC_COPY_ARB 0x88EA #endif #ifndef GL_ARB_occlusion_query #define GL_ARB_occlusion_query #define AGL_ARB_occlusion_query #define GL_SAMPLES_PASSED_ARB 0x8914 #define GL_QUERY_COUNTER_BITS_ARB 0x8864 #define GL_CURRENT_QUERY_ARB 0x8865 #define GL_QUERY_RESULT_ARB 0x8866 #define GL_QUERY_RESULT_AVAILABLE_ARB 0x8867 #endif #ifndef GL_ARB_shader_objects #define GL_ARB_shader_objects #define AGL_ARB_shader_objects typedef char GLcharARB; typedef unsigned long GLhandleARB; #define GL_PROGRAM_OBJECT_ARB 0x8B40 #define GL_OBJECT_TYPE_ARB 0x8B4E #define GL_OBJECT_SUBTYPE_ARB 0x8B4F #define GL_OBJECT_DELETE_STATUS_ARB 0x8B80 #define GL_OBJECT_COMPILE_STATUS_ARB 0x8B81 #define GL_OBJECT_LINK_STATUS_ARB 0x8B82 #define GL_OBJECT_VALIDATE_STATUS_ARB 0x8B83 #define GL_OBJECT_INFO_LOG_LENGTH_ARB 0x8B84 #define GL_OBJECT_ATTACHED_OBJECTS_ARB 0x8B85 #define GL_OBJECT_ACTIVE_UNIFORMS_ARB 0x8B86 #define GL_OBJECT_ACTIVE_UNIFORM_MAX_LENGTH_ARB 0x8B87 #define GL_OBJECT_SHADER_SOURCE_LENGTH_ARB 0x8B88 #define GL_SHADER_OBJECT_ARB 0x8B48 /* GL_FLOAT */ #define GL_FLOAT_VEC2_ARB 0x8B50 #define GL_FLOAT_VEC3_ARB 0x8B51 #define GL_FLOAT_VEC4_ARB 0x8B52 /* GL_INT */ #define GL_INT_VEC2_ARB 0x8B53 #define GL_INT_VEC3_ARB 0x8B54 #define GL_INT_VEC4_ARB 0x8B55 #define GL_BOOL_ARB 0x8B56 #define GL_BOOL_VEC2_ARB 0x8B57 #define GL_BOOL_VEC3_ARB 0x8B58 #define GL_BOOL_VEC4_ARB 0x8B59 #define GL_FLOAT_MAT2_ARB 0x8B5A #define GL_FLOAT_MAT3_ARB 0x8B5B #define GL_FLOAT_MAT4_ARB 0x8B5C #define GL_SAMPLER_1D_ARB 0x8B5D #define GL_SAMPLER_2D_ARB 0x8B5E #define GL_SAMPLER_3D_ARB 0x8B5F #define GL_SAMPLER_CUBE_ARB 0x8B60 #define GL_SAMPLER_1D_SHADOW_ARB 0x8B61 #define GL_SAMPLER_2D_SHADOW_ARB 0x8B62 #define GL_SAMPLER_2D_RECT_ARB 0x8B63 #define GL_SAMPLER_2D_RECT_SHADOW_ARB 0x8B64 #endif #ifndef GL_ARB_vertex_shader #define GL_ARB_vertex_shader #define AGL_ARB_vertex_shader #define GL_VERTEX_SHADER_ARB 0x8B31 #define GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB 0x8B4A #define GL_MAX_VARYING_FLOATS_ARB 0x8B4B #define GL_MAX_VERTEX_ATTRIBS_ARB 0x8869 #define GL_MAX_TEXTURE_IMAGE_UNITS_ARB 0x8872 #define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB 0x8B4C #define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB 0x8B4D #define GL_MAX_TEXTURE_COORDS_ARB 0x8871 #define GL_VERTEX_PROGRAM_POINT_SIZE_ARB 0x8642 #define GL_VERTEX_PROGRAM_TWO_SIDE_ARB 0x8643 #if !defined GL_ARB_shader_objects #define GL_OBJECT_TYPE_ARB 0x8B4E #define GL_OBJECT_SUBTYPE_ARB 0x8B4F #endif #define GL_OBJECT_ACTIVE_ATTRIBUTES_ARB 0x8B89 #define GL_OBJECT_ACTIVE_ATTRIBUTE_MAX_LENGTH_ARB 0x8B8A #if !defined GL_ARB_shader_objects #define GL_SHADER_OBJECT_ARB 0x8B48 #endif #define GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB 0x8622 #define GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB 0x8623 #define GL_VERTEX_ATTRIB_ARRAY_STRIDE_ARB 0x8624 #define GL_VERTEX_ATTRIB_ARRAY_TYPE_ARB 0x8625 #define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB 0x886A #define GL_CURRENT_VERTEX_ATTRIB_ARB 0x8626 #define GL_VERTEX_ATTRIB_ARRAY_POINTER_ARB 0x8645 #if !defined GL_ARB_shader_objects /* GL_FLOAT */ #define GL_FLOAT_VEC2_ARB 0x8B50 #define GL_FLOAT_VEC3_ARB 0x8B51 #define GL_FLOAT_VEC4_ARB 0x8B52 #define GL_FLOAT_MAT2_ARB 0x8B5A #define GL_FLOAT_MAT3_ARB 0x8B5B #define GL_FLOAT_MAT4_ARB 0x8B5C #endif #endif #ifndef GL_ARB_fragment_shader #define GL_ARB_fragment_shader #define AGL_ARB_fragment_shader #define GL_FRAGMENT_SHADER_ARB 0x8B30 #define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB 0x8B49 #define GL_MAX_TEXTURE_COORDS_ARB 0x8871 #define GL_MAX_TEXTURE_IMAGE_UNITS_ARB 0x8872 #if !defined GL_ARB_shader_objects && !defined GL_ARB_vertex_shader #define GL_OBJECT_TYPE_ARB 0x8B4E #define GL_OBJECT_SUBTYPE_ARB 0x8B4F #define GL_SHADER_OBJECT_ARB 0x8B48 #endif #endif #ifndef GL_ARB_shading_language_100 #define GL_ARB_shading_language_100 #define AGL_ARB_shading_language_100 #endif #ifndef GL_ARB_texture_non_power_of_two #define GL_ARB_texture_non_power_of_two #define AGL_ARB_texture_non_power_of_two #endif #ifndef GL_ARB_point_sprite #define GL_ARB_point_sprite #define AGL_ARB_point_sprite #define GL_POINT_SPRITE_ARB 0x8861 #define GL_COORD_REPLACE_ARB 0x8862 /* GL_FALSE */ /* GL_TRUE */ #endif #ifndef GL_ARB_draw_buffers #define GL_ARB_draw_buffers #define AGL_ARB_draw_buffers #define GL_MAX_DRAW_BUFFERS_ARB 0x8824 #define GL_DRAW_BUFFER0_ARB 0x8825 #define GL_DRAW_BUFFER1_ARB 0x8826 #define GL_DRAW_BUFFER2_ARB 0x8827 #define GL_DRAW_BUFFER3_ARB 0x8828 #define GL_DRAW_BUFFER4_ARB 0x8829 #define GL_DRAW_BUFFER5_ARB 0x882A #define GL_DRAW_BUFFER6_ARB 0x882B #define GL_DRAW_BUFFER7_ARB 0x882C #define GL_DRAW_BUFFER8_ARB 0x882D #define GL_DRAW_BUFFER9_ARB 0x882E #define GL_DRAW_BUFFER10_ARB 0x882F #define GL_DRAW_BUFFER11_ARB 0x8830 #define GL_DRAW_BUFFER12_ARB 0x8831 #define GL_DRAW_BUFFER13_ARB 0x8832 #define GL_DRAW_BUFFER14_ARB 0x8833 #define GL_DRAW_BUFFER15_ARB 0x8834 #endif #ifndef GL_ARB_texture_rectangle #define GL_ARB_texture_rectangle #define AGL_ARB_texture_rectangle #define GL_TEXTURE_RECTANGLE_ARB 0x84F5 #define GL_TEXTURE_BINDING_RECTANGLE_ARB 0x84F6 #define GL_PROXY_TEXTURE_RECTANGLE_ARB 0x84F7 #define GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB 0x84F8 #endif #ifdef ALLEGRO_MACOSX #ifndef GL_EXT_texture_rectangle #define GL_EXT_texture_rectangle #define AGL_EXT_texture_rectangle #define GL_TEXTURE_RECTANGLE_EXT 0x84F5 #define GL_TEXTURE_BINDING_RECTANGLE_EXT 0x84F6 #define GL_PROXY_TEXTURE_RECTANGLE_EXT 0x84F7 #define GL_MAX_RECTANGLE_TEXTURE_SIZE_EXT 0x84F8 #endif #endif #ifndef GL_ARB_color_buffer_float #define GL_ARB_color_buffer_float #define AGL_ARB_color_buffer_float #define GL_RGBA_FLOAT_MODE_ARB 0x8820 #define GL_CLAMP_VERTEX_COLOR_ARB 0x891A #define GL_CLAMP_FRAGMENT_COLOR_ARB 0x891B #define GL_CLAMP_READ_COLOR_ARB 0x891C #define GL_FIXED_ONLY_ARB 0x891D #endif #ifndef GL_ARB_half_float_pixel #define GL_ARB_half_float_pixel #define AGL_ARB_half_float_pixel #define GL_HALF_FLOAT_ARB 0x140B #endif #ifndef GL_ARB_texture_float #define GL_ARB_texture_float #define AGL_ARB_texture_float #define GL_TEXTURE_RED_TYPE_ARB 0x8C10 #define GL_TEXTURE_GREEN_TYPE_ARB 0x8C11 #define GL_TEXTURE_BLUE_TYPE_ARB 0x8C12 #define GL_TEXTURE_ALPHA_TYPE_ARB 0x8C13 #define GL_TEXTURE_LUMINANCE_TYPE_ARB 0x8C14 #define GL_TEXTURE_INTENSITY_TYPE_ARB 0x8C15 #define GL_TEXTURE_DEPTH_TYPE_ARB 0x8C16 #define GL_UNSIGNED_NORMALIZED_ARB 0x8C17 #define GL_RGBA32F_ARB 0x8814 #define GL_RGB32F_ARB 0x8815 #define GL_ALPHA32F_ARB 0x8816 #define GL_INTENSITY32F_ARB 0x8817 #define GL_LUMINANCE32F_ARB 0x8818 #define GL_LUMINANCE_ALPHA32F_ARB 0x8819 #define GL_RGBA16F_ARB 0x881A #define GL_RGB16F_ARB 0x881B #define GL_ALPHA16F_ARB 0x881C #define GL_INTENSITY16F_ARB 0x881D #define GL_LUMINANCE16F_ARB 0x881E #define GL_LUMINANCE_ALPHA16F_ARB 0x881F #endif #ifndef GL_ARB_pixel_buffer_object #define GL_ARB_pixel_buffer_object #define AGL_ARB_pixel_buffer_object #define GL_PIXEL_PACK_BUFFER_ARB 0x88EB #define GL_PIXEL_UNPACK_BUFFER_ARB 0x88EC #define GL_PIXEL_PACK_BUFFER_BINDING_ARB 0x88ED #define GL_PIXEL_UNPACK_BUFFER_BINDING_ARB 0x88EF #endif #ifndef GL_ARB_depth_buffer_float #define GL_ARB_depth_buffer_float #define AGL_ARB_depth_buffer_float #define GL_DEPTH_COMPONENT32F 0x8CAC #define GL_DEPTH32F_STENCIL8 0x8CAD #define GL_FLOAT_32_UNSIGNED_INT_24_8_REV 0x8DAD #endif #ifndef GL_ARB_draw_instanced #define GL_ARB_draw_instanced #define AGL_ARB_draw_instanced #endif #ifndef GL_ARB_framebuffer_object #define GL_ARB_framebuffer_object #define AGL_ARB_framebuffer_object #define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506 #define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING 0x8210 #define GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE 0x8211 #define GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE 0x8212 #define GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE 0x8213 #define GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE 0x8214 #define GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE 0x8215 #define GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE 0x8216 #define GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE 0x8217 #define GL_FRAMEBUFFER_DEFAULT 0x8218 #define GL_FRAMEBUFFER_UNDEFINED 0x8219 #define GL_DEPTH_STENCIL_ATTACHMENT 0x821A #define GL_INDEX 0x8222 #define GL_MAX_RENDERBUFFER_SIZE 0x84E8 #define GL_DEPTH_STENCIL 0x84F9 #define GL_UNSIGNED_INT_24_8 0x84FA #define GL_DEPTH24_STENCIL8 0x88F0 #define GL_TEXTURE_STENCIL_SIZE 0x88F1 #define GL_FRAMEBUFFER_BINDING 0x8CA6 #define GL_DRAW_FRAMEBUFFER_BINDING GL_FRAMEBUFFER_BINDING #define GL_RENDERBUFFER_BINDING 0x8CA7 #define GL_READ_FRAMEBUFFER 0x8CA8 #define GL_DRAW_FRAMEBUFFER 0x8CA9 #define GL_READ_FRAMEBUFFER_BINDING 0x8CAA #define GL_RENDERBUFFER_SAMPLES 0x8CAB #define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0 #define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1 #define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2 #define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3 #define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER 0x8CD4 #define GL_FRAMEBUFFER_COMPLETE 0x8CD5 #define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6 #define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7 #define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER 0x8CDB #define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER 0x8CDC #define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD #define GL_MAX_COLOR_ATTACHMENTS 0x8CDF #define GL_COLOR_ATTACHMENT0 0x8CE0 #define GL_COLOR_ATTACHMENT1 0x8CE1 #define GL_COLOR_ATTACHMENT2 0x8CE2 #define GL_COLOR_ATTACHMENT3 0x8CE3 #define GL_COLOR_ATTACHMENT4 0x8CE4 #define GL_COLOR_ATTACHMENT5 0x8CE5 #define GL_COLOR_ATTACHMENT6 0x8CE6 #define GL_COLOR_ATTACHMENT7 0x8CE7 #define GL_COLOR_ATTACHMENT8 0x8CE8 #define GL_COLOR_ATTACHMENT9 0x8CE9 #define GL_COLOR_ATTACHMENT10 0x8CEA #define GL_COLOR_ATTACHMENT11 0x8CEB #define GL_COLOR_ATTACHMENT12 0x8CEC #define GL_COLOR_ATTACHMENT13 0x8CED #define GL_COLOR_ATTACHMENT14 0x8CEE #define GL_COLOR_ATTACHMENT15 0x8CEF #define GL_DEPTH_ATTACHMENT 0x8D00 #define GL_STENCIL_ATTACHMENT 0x8D20 #define GL_FRAMEBUFFER 0x8D40 #define GL_RENDERBUFFER 0x8D41 #define GL_RENDERBUFFER_WIDTH 0x8D42 #define GL_RENDERBUFFER_HEIGHT 0x8D43 #define GL_RENDERBUFFER_INTERNAL_FORMAT 0x8D44 #define GL_STENCIL_INDEX1 0x8D46 #define GL_STENCIL_INDEX4 0x8D47 #define GL_STENCIL_INDEX8 0x8D48 #define GL_STENCIL_INDEX16 0x8D49 #define GL_RENDERBUFFER_RED_SIZE 0x8D50 #define GL_RENDERBUFFER_GREEN_SIZE 0x8D51 #define GL_RENDERBUFFER_BLUE_SIZE 0x8D52 #define GL_RENDERBUFFER_ALPHA_SIZE 0x8D53 #define GL_RENDERBUFFER_DEPTH_SIZE 0x8D54 #define GL_RENDERBUFFER_STENCIL_SIZE 0x8D55 #define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE 0x8D56 #define GL_MAX_SAMPLES 0x8D57 #endif #ifndef GL_ARB_framebuffer_sRGB #define GL_ARB_framebuffer_sRGB #define AGL_ARB_framebuffer_sRGB #define GL_FRAMEBUFFER_SRGB 0x8DB9 #endif #ifndef GL_ARB_geometry_shader4 #define GL_ARB_geometry_shader4 #define AGL_ARB_geometry_shader4 #define GL_LINES_ADJACENCY_ARB 0x000A #define GL_LINE_STRIP_ADJACENCY_ARB 0x000B #define GL_TRIANGLES_ADJACENCY_ARB 0x000C #define GL_TRIANGLE_STRIP_ADJACENCY_ARB 0x000D #define GL_PROGRAM_POINT_SIZE_ARB 0x8642 #define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_ARB 0x8C29 #define GL_FRAMEBUFFER_ATTACHMENT_LAYERED_ARB 0x8DA7 #define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_ARB 0x8DA8 #define GL_FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_ARB 0x8DA9 #define GL_GEOMETRY_SHADER_ARB 0x8DD9 #define GL_GEOMETRY_VERTICES_OUT_ARB 0x8DDA #define GL_GEOMETRY_INPUT_TYPE_ARB 0x8DDB #define GL_GEOMETRY_OUTPUT_TYPE_ARB 0x8DDC #define GL_MAX_GEOMETRY_VARYING_COMPONENTS_ARB 0x8DDD #define GL_MAX_VERTEX_VARYING_COMPONENTS_ARB 0x8DDE #define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_ARB 0x8DDF #define GL_MAX_GEOMETRY_OUTPUT_VERTICES_ARB 0x8DE0 #define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_ARB 0x8DE1 /* reuse GL_MAX_VARYING_COMPONENTS */ /* reuse GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER */ #endif #ifndef GL_ARB_half_float_vertex #define GL_ARB_half_float_vertex #define AGL_ARB_half_float_vertex #define GL_HALF_FLOAT 0x140B #endif #ifndef GL_ARB_instanced_arrays #define GL_ARB_instanced_arrays #define AGL_ARB_instanced_arrays #endif #ifndef GL_ARB_map_buffer_range #define GL_ARB_map_buffer_range #define AGL_ARB_map_buffer_range #define GL_MAP_READ_BIT 0x0001 #define GL_MAP_WRITE_BIT 0x0002 #define GL_MAP_INVALIDATE_RANGE_BIT 0x0004 #define GL_MAP_INVALIDATE_BUFFER_BIT 0x0008 #define GL_MAP_FLUSH_EXPLICIT_BIT 0x0010 #define GL_MAP_UNSYNCHRONIZED_BIT 0x0020 #endif #ifndef GL_ARB_texture_buffer_object #define GL_ARB_texture_buffer_object #define AGL_ARB_texture_buffer_object #define GL_TEXTURE_BUFFER_ARB 0x8C2A #define GL_MAX_TEXTURE_BUFFER_SIZE_ARB 0x8C2B #define GL_TEXTURE_BINDING_BUFFER_ARB 0x8C2C #define GL_TEXTURE_BUFFER_DATA_STORE_BINDING_ARB 0x8C2D #define GL_TEXTURE_BUFFER_FORMAT_ARB 0x8C2E #endif #ifndef GL_ARB_texture_compression_rgtc #define GL_ARB_texture_compression_rgtc #define AGL_ARB_texture_compression_rgtc #define GL_COMPRESSED_RED_RGTC1 0x8DBB #define GL_COMPRESSED_SIGNED_RED_RGTC1 0x8DBC #define GL_COMPRESSED_RG_RGTC2 0x8DBD #define GL_COMPRESSED_SIGNED_RG_RGTC2 0x8DBE #endif #ifndef GL_ARB_texture_rg #define GL_ARB_texture_rg #define AGL_ARB_texture_rg #define GL_RG 0x8227 #define GL_RG_INTEGER 0x8228 #define GL_R8 0x8229 #define GL_R16 0x822A #define GL_RG8 0x822B #define GL_RG16 0x822C #define GL_R16F 0x822D #define GL_R32F 0x822E #define GL_RG16F 0x822F #define GL_RG32F 0x8230 #define GL_R8I 0x8231 #define GL_R8UI 0x8232 #define GL_R16I 0x8233 #define GL_R16UI 0x8234 #define GL_R32I 0x8235 #define GL_R32UI 0x8236 #define GL_RG8I 0x8237 #define GL_RG8UI 0x8238 #define GL_RG16I 0x8239 #define GL_RG16UI 0x823A #define GL_RG32I 0x823B #define GL_RG32UI 0x823C #endif #ifndef GL_ARB_vertex_array_object #define GL_ARB_vertex_array_object #define AGL_ARB_vertex_array_object #define GL_VERTEX_ARRAY_BINDING 0x85B5 #endif /* */ #ifndef GL_EXT_abgr #define GL_EXT_abgr #define AGL_EXT_abgr #define GL_ABGR_EXT 0x8000 #endif #ifndef GL_EXT_blend_color #define GL_EXT_blend_color #define AGL_EXT_blend_color #define GL_CONSTANT_COLOR_EXT 0x8001 #define GL_ONE_MINUS_CONSTANT_COLOR_EXT 0x8002 #define GL_CONSTANT_ALPHA_EXT 0x8003 #define GL_ONE_MINUS_CONSTANT_ALPHA_EXT 0x8004 #define GL_BLEND_COLOR_EXT 0x8005 #endif #ifndef GL_EXT_polygon_offset #define GL_EXT_polygon_offset #define AGL_EXT_polygon_offset #define GL_POLYGON_OFFSET_EXT 0x8037 #define GL_POLYGON_OFFSET_FACTOR_EXT 0x8038 #define GL_POLYGON_OFFSET_BIAS_EXT 0x8039 #endif #ifndef GL_EXT_texture #define GL_EXT_texture #define AGL_EXT_texture #define GL_ALPHA4_EXT 0x803B #define GL_ALPHA8_EXT 0x803C #define GL_ALPHA12_EXT 0x803D #define GL_ALPHA16_EXT 0x803E #define GL_LUMINANCE4_EXT 0x803F #define GL_LUMINANCE8_EXT 0x8040 #define GL_LUMINANCE12_EXT 0x8041 #define GL_LUMINANCE16_EXT 0x8042 #define GL_LUMINANCE4_ALPHA4_EXT 0x8043 #define GL_LUMINANCE6_ALPHA2_EXT 0x8044 #define GL_LUMINANCE8_ALPHA8_EXT 0x8045 #define GL_LUMINANCE12_ALPHA4_EXT 0x8046 #define GL_LUMINANCE12_ALPHA12_EXT 0x8047 #define GL_LUMINANCE16_ALPHA16_EXT 0x8048 #define GL_INTENSITY_EXT 0x8049 #define GL_INTENSITY4_EXT 0x804A #define GL_INTENSITY8_EXT 0x804B #define GL_INTENSITY12_EXT 0x804C #define GL_INTENSITY16_EXT 0x804D #define GL_RGB2_EXT 0x804E #define GL_RGB4_EXT 0x804F #define GL_RGB5_EXT 0x8050 #define GL_RGB8_EXT 0x8051 #define GL_RGB10_EXT 0x8052 #define GL_RGB12_EXT 0x8053 #define GL_RGB16_EXT 0x8054 #define GL_RGBA2_EXT 0x8055 #define GL_RGBA4_EXT 0x8056 #define GL_RGB5_A1_EXT 0x8057 #define GL_RGBA8_EXT 0x8058 #define GL_RGB10_A2_EXT 0x8059 #define GL_RGBA12_EXT 0x805A #define GL_RGBA16_EXT 0x805B #define GL_TEXTURE_RED_SIZE_EXT 0x805C #define GL_TEXTURE_GREEN_SIZE_EXT 0x805D #define GL_TEXTURE_BLUE_SIZE_EXT 0x805E #define GL_TEXTURE_ALPHA_SIZE_EXT 0x805F #define GL_TEXTURE_LUMINANCE_SIZE_EXT 0x8060 #define GL_TEXTURE_INTENSITY_SIZE_EXT 0x8061 #define GL_REPLACE_EXT 0x8062 #define GL_PROXY_TEXTURE_1D_EXT 0x8063 #define GL_PROXY_TEXTURE_2D_EXT 0x8064 #define GL_TEXTURE_TOO_LARGE_EXT 0x8065 #endif #ifndef GL_EXT_texture3D #define GL_EXT_texture3D #define AGL_EXT_texture3D #define GL_PACK_SKIP_IMAGES_EXT 0x806B #define GL_PACK_IMAGE_HEIGHT_EXT 0x806C #define GL_UNPACK_SKIP_IMAGES_EXT 0x806D #define GL_UNPACK_IMAGE_HEIGHT_EXT 0x806E #define GL_TEXTURE_3D_EXT 0x806F #define GL_PROXY_TEXTURE_3D_EXT 0x8070 #define GL_TEXTURE_DEPTH_EXT 0x8071 #define GL_TEXTURE_WRAP_R_EXT 0x8072 #define GL_MAX_3D_TEXTURE_SIZE_EXT 0x8073 #endif #ifndef GL_SGIS_texture_filter4 #define GL_SGIS_texture_filter4 #define AGL_SGIS_texture_filter4 #define GL_FILTER4_SGIS 0x8146 #define GL_TEXTURE_FILTER4_SIZE_SGIS 0x8147 #endif #ifndef GL_EXT_histogram #define GL_EXT_histogram #define AGL_EXT_histogram #define GL_HISTOGRAM_EXT 0x8024 #define GL_PROXY_HISTOGRAM_EXT 0x8025 #define GL_HISTOGRAM_WIDTH_EXT 0x8026 #define GL_HISTOGRAM_FORMAT_EXT 0x8027 #define GL_HISTOGRAM_RED_SIZE_EXT 0x8028 #define GL_HISTOGRAM_GREEN_SIZE_EXT 0x8029 #define GL_HISTOGRAM_BLUE_SIZE_EXT 0x802A #define GL_HISTOGRAM_ALPHA_SIZE_EXT 0x802B #define GL_HISTOGRAM_LUMINANCE_SIZE_EXT 0x802C #define GL_HISTOGRAM_SINK_EXT 0x802D #define GL_MINMAX_EXT 0x802E #define GL_MINMAX_FORMAT_EXT 0x802F #define GL_MINMAX_SINK_EXT 0x8030 #define GL_TABLE_TOO_LARGE_EXT 0x8031 #endif #ifndef GL_EXT_subtexture #define GL_EXT_subtexture #define AGL_EXT_subtexture #endif #ifndef GL_EXT_copy_texture #define GL_EXT_copy_texture /* NV's headers don't define EXT_copy_texture yet provide the API */ #ifndef AGL_HEADER_NV #define AGL_EXT_copy_texture #endif #endif #ifndef GL_EXT_histogram #define GL_EXT_histogram #define AGL_EXT_histogram #endif #ifndef GL_EXT_convolution #define GL_EXT_convolution #define AGL_EXT_convolution #define GL_CONVOLUTION_1D_EXT 0x8010 #define GL_CONVOLUTION_2D_EXT 0x8011 #define GL_SEPARABLE_2D_EXT 0x8012 #define GL_CONVOLUTION_BORDER_MODE_EXT 0x8013 #define GL_CONVOLUTION_FILTER_SCALE_EXT 0x8014 #define GL_CONVOLUTION_FILTER_BIAS_EXT 0x8015 #define GL_REDUCE_EXT 0x8016 #define GL_CONVOLUTION_FORMAT_EXT 0x8017 #define GL_CONVOLUTION_WIDTH_EXT 0x8018 #define GL_CONVOLUTION_HEIGHT_EXT 0x8019 #define GL_MAX_CONVOLUTION_WIDTH_EXT 0x801A #define GL_MAX_CONVOLUTION_HEIGHT_EXT 0x801B #define GL_POST_CONVOLUTION_RED_SCALE_EXT 0x801C #define GL_POST_CONVOLUTION_GREEN_SCALE_EXT 0x801D #define GL_POST_CONVOLUTION_BLUE_SCALE_EXT 0x801E #define GL_POST_CONVOLUTION_ALPHA_SCALE_EXT 0x801F #define GL_POST_CONVOLUTION_RED_BIAS_EXT 0x8020 #define GL_POST_CONVOLUTION_GREEN_BIAS_EXT 0x8021 #define GL_POST_CONVOLUTION_BLUE_BIAS_EXT 0x8022 #define GL_POST_CONVOLUTION_ALPHA_BIAS_EXT 0x8023 #endif #ifndef GL_SGI_color_matrix #define GL_SGI_color_matrix #define AGL_SGI_color_matrix #define GL_COLOR_MATRIX_SGI 0x80B1 #define GL_COLOR_MATRIX_STACK_DEPTH_SGI 0x80B2 #define GL_MAX_COLOR_MATRIX_STACK_DEPTH_SGI 0x80B3 #define GL_POST_COLOR_MATRIX_RED_SCALE_SGI 0x80B4 #define GL_POST_COLOR_MATRIX_GREEN_SCALE_SGI 0x80B5 #define GL_POST_COLOR_MATRIX_BLUE_SCALE_SGI 0x80B6 #define GL_POST_COLOR_MATRIX_ALPHA_SCALE_SGI 0x80B7 #define GL_POST_COLOR_MATRIX_RED_BIAS_SGI 0x80B8 #define GL_POST_COLOR_MATRIX_GREEN_BIAS_SGI 0x80B9 #define GL_POST_COLOR_MATRIX_BLUE_BIAS_SGI 0x80BA #define GL_POST_COLOR_MATRIX_ALPHA_BIAS_SGI 0x80BB #endif #ifndef GL_SGI_color_table #define GL_SGI_color_table #define AGL_SGI_color_table #define GL_COLOR_TABLE_SGI 0x80D0 #define GL_POST_CONVOLUTION_COLOR_TABLE_SGI 0x80D1 #define GL_POST_COLOR_MATRIX_COLOR_TABLE_SGI 0x80D2 #define GL_PROXY_COLOR_TABLE_SGI 0x80D3 #define GL_PROXY_POST_CONVOLUTION_COLOR_TABLE_SGI 0x80D4 #define GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE_SGI 0x80D5 #define GL_COLOR_TABLE_SCALE_SGI 0x80D6 #define GL_COLOR_TABLE_BIAS_SGI 0x80D7 #define GL_COLOR_TABLE_FORMAT_SGI 0x80D8 #define GL_COLOR_TABLE_WIDTH_SGI 0x80D9 #define GL_COLOR_TABLE_RED_SIZE_SGI 0x80DA #define GL_COLOR_TABLE_GREEN_SIZE_SGI 0x80DB #define GL_COLOR_TABLE_BLUE_SIZE_SGI 0x80DC #define GL_COLOR_TABLE_ALPHA_SIZE_SGI 0x80DD #define GL_COLOR_TABLE_LUMINANCE_SIZE_SGI 0x80DE #define GL_COLOR_TABLE_INTENSITY_SIZE_SGI 0x80DF #endif #ifndef GL_SGIS_pixel_texture #define GL_SGIS_pixel_texture #define AGL_SGIS_pixel_texture #define GL_PIXEL_TEXTURE_SGIS 0x8353 #define GL_PIXEL_FRAGMENT_RGB_SOURCE_SGIS 0x8354 #define GL_PIXEL_FRAGMENT_ALPHA_SOURCE_SGIS 0x8355 #define GL_PIXEL_GROUP_COLOR_SGIS 0x8356 #endif #ifndef GL_SGIX_pixel_texture #define GL_SGIX_pixel_texture #define AGL_SGIX_pixel_texture #define GL_PIXEL_TEX_GEN_SGIX 0x8139 #define GL_PIXEL_TEX_GEN_MODE_SGIX 0x832B #endif #ifndef GL_SGIS_texture4D #define GL_SGIS_texture4D #define AGL_SGIS_texture4D #define GL_PACK_SKIP_VOLUMES_SGIS 0x8130 #define GL_PACK_IMAGE_DEPTH_SGIS 0x8131 #define GL_UNPACK_SKIP_VOLUMES_SGIS 0x8132 #define GL_UNPACK_IMAGE_DEPTH_SGIS 0x8133 #define GL_TEXTURE_4D_SGIS 0x8134 #define GL_PROXY_TEXTURE_4D_SGIS 0x8135 #define GL_TEXTURE_4DSIZE_SGIS 0x8136 #define GL_TEXTURE_WRAP_Q_SGIS 0x8137 #define GL_MAX_4D_TEXTURE_SIZE_SGIS 0x8138 #define GL_TEXTURE_4D_BINDING_SGIS 0x814F #endif #ifndef GL_SGI_texture_color_table #define GL_SGI_texture_color_table #define AGL_SGI_texture_color_table #define GL_TEXTURE_COLOR_TABLE_SGI 0x80BC #define GL_PROXY_TEXTURE_COLOR_TABLE_SGI 0x80BD #endif #ifndef GL_EXT_cmyka #define GL_EXT_cmyka #define AGL_EXT_cmyka #define GL_CMYK_EXT 0x800C #define GL_CMYKA_EXT 0x800D #define GL_PACK_CMYK_HINT_EXT 0x800E #define GL_UNPACK_CMYK_HINT_EXT 0x800F #endif #ifndef GL_EXT_texture_object #define GL_EXT_texture_object #define AGL_EXT_texture_object #define GL_TEXTURE_PRIORITY_EXT 0x8066 #define GL_TEXTURE_RESIDENT_EXT 0x8067 #define GL_TEXTURE_1D_BINDING_EXT 0x8068 #define GL_TEXTURE_2D_BINDING_EXT 0x8069 #define GL_TEXTURE_3D_BINDING_EXT 0x806A #endif #ifndef GL_SGIS_detail_texture #define GL_SGIS_detail_texture #define AGL_SGIS_detail_texture #define GL_DETAIL_TEXTURE_2D_SGIS 0x8095 #define GL_DETAIL_TEXTURE_2D_BINDING_SGIS 0x8096 #define GL_LINEAR_DETAIL_SGIS 0x8097 #define GL_LINEAR_DETAIL_ALPHA_SGIS 0x8098 #define GL_LINEAR_DETAIL_COLOR_SGIS 0x8099 #define GL_DETAIL_TEXTURE_LEVEL_SGIS 0x809A #define GL_DETAIL_TEXTURE_MODE_SGIS 0x809B #define GL_DETAIL_TEXTURE_FUNC_POINTS_SGIS 0x809C #endif #ifndef GL_SGIS_sharpen_texture #define GL_SGIS_sharpen_texture #define AGL_SGIS_sharpen_texture #define GL_LINEAR_SHARPEN_SGIS 0x80AD #define GL_LINEAR_SHARPEN_ALPHA_SGIS 0x80AE #define GL_LINEAR_SHARPEN_COLOR_SGIS 0x80AF #define GL_SHARPEN_TEXTURE_FUNC_POINTS_SGIS 0x80B0 #endif #ifndef GL_EXT_packed_pixels #define GL_EXT_packed_pixels #define AGL_EXT_packed_pixels #define GL_UNSIGNED_BYTE_3_3_2_EXT 0x8032 #define GL_UNSIGNED_SHORT_4_4_4_4_EXT 0x8033 #define GL_UNSIGNED_SHORT_5_5_5_1_EXT 0x8034 #define GL_UNSIGNED_INT_8_8_8_8_EXT 0x8035 #define GL_UNSIGNED_INT_10_10_10_2_EXT 0x8036 #endif #ifndef GL_SGIS_texture_lod #define GL_SGIS_texture_lod #define AGL_SGIS_texture_lod #define GL_TEXTURE_MIN_LOD_SGIS 0x813A #define GL_TEXTURE_MAX_LOD_SGIS 0x813B #define GL_TEXTURE_BASE_LEVEL_SGIS 0x813C #define GL_TEXTURE_MAX_LEVEL_SGIS 0x813D #endif #ifndef GL_SGIS_multisample #define GL_SGIS_multisample #define AGL_SGIS_multisample #define GL_MULTISAMPLE_SGIS 0x809D #define GL_SAMPLE_ALPHA_TO_MASK_SGIS 0x809E #define GL_SAMPLE_ALPHA_TO_ONE_SGIS 0x809F #define GL_SAMPLE_MASK_SGIS 0x80A0 #define GL_1PASS_SGIS 0x80A1 #define GL_2PASS_0_SGIS 0x80A2 #define GL_2PASS_1_SGIS 0x80A3 #define GL_4PASS_0_SGIS 0x80A4 #define GL_4PASS_1_SGIS 0x80A5 #define GL_4PASS_2_SGIS 0x80A6 #define GL_4PASS_3_SGIS 0x80A7 #define GL_SAMPLE_BUFFERS_SGIS 0x80A8 #define GL_SAMPLES_SGIS 0x80A9 #define GL_SAMPLE_MASK_VALUE_SGIS 0x80AA #define GL_SAMPLE_MASK_INVERT_SGIS 0x80AB #define GL_SAMPLE_PATTERN_SGIS 0x80AC #endif #ifndef GL_EXT_rescale_normal #define GL_EXT_rescale_normal #define AGL_EXT_rescale_normal #define GL_RESCALE_NORMAL_EXT 0x803A #endif #ifndef GL_EXT_vertex_array #define GL_EXT_vertex_array #define AGL_EXT_vertex_array #define GL_VERTEX_ARRAY_EXT 0x8074 #define GL_NORMAL_ARRAY_EXT 0x8075 #define GL_COLOR_ARRAY_EXT 0x8076 #define GL_INDEX_ARRAY_EXT 0x8077 #define GL_TEXTURE_COORD_ARRAY_EXT 0x8078 #define GL_EDGE_FLAG_ARRAY_EXT 0x8079 #define GL_VERTEX_ARRAY_SIZE_EXT 0x807A #define GL_VERTEX_ARRAY_TYPE_EXT 0x807B #define GL_VERTEX_ARRAY_STRIDE_EXT 0x807C #define GL_VERTEX_ARRAY_COUNT_EXT 0x807D #define GL_NORMAL_ARRAY_TYPE_EXT 0x807E #define GL_NORMAL_ARRAY_STRIDE_EXT 0x807F #define GL_NORMAL_ARRAY_COUNT_EXT 0x8080 #define GL_COLOR_ARRAY_SIZE_EXT 0x8081 #define GL_COLOR_ARRAY_TYPE_EXT 0x8082 #define GL_COLOR_ARRAY_STRIDE_EXT 0x8083 #define GL_COLOR_ARRAY_COUNT_EXT 0x8084 #define GL_INDEX_ARRAY_TYPE_EXT 0x8085 #define GL_INDEX_ARRAY_STRIDE_EXT 0x8086 #define GL_INDEX_ARRAY_COUNT_EXT 0x8087 #define GL_TEXTURE_COORD_ARRAY_SIZE_EXT 0x8088 #define GL_TEXTURE_COORD_ARRAY_TYPE_EXT 0x8089 #define GL_TEXTURE_COORD_ARRAY_STRIDE_EXT 0x808A #define GL_TEXTURE_COORD_ARRAY_COUNT_EXT 0x808B #define GL_EDGE_FLAG_ARRAY_STRIDE_EXT 0x808C #define GL_EDGE_FLAG_ARRAY_COUNT_EXT 0x808D #define GL_VERTEX_ARRAY_POINTER_EXT 0x808E #define GL_NORMAL_ARRAY_POINTER_EXT 0x808F #define GL_COLOR_ARRAY_POINTER_EXT 0x8090 #define GL_INDEX_ARRAY_POINTER_EXT 0x8091 #define GL_TEXTURE_COORD_ARRAY_POINTER_EXT 0x8092 #define GL_EDGE_FLAG_ARRAY_POINTER_EXT 0x8093 #endif #ifndef GL_SGIS_generate_mipmap #define GL_SGIS_generate_mipmap #define AGL_SGIS_generate_mipmap #define GL_GENERATE_MIPMAP_SGIS 0x8191 #define GL_GENERATE_MIPMAP_HINT_SGIS 0x8192 #endif #ifndef GL_SGIX_clipmap #define GL_SGIX_clipmap #define AGL_SGIX_clipmap #define GL_LINEAR_CLIPMAP_LINEAR_SGIX 0x8170 #define GL_TEXTURE_CLIPMAP_CENTER_SGIX 0x8171 #define GL_TEXTURE_CLIPMAP_FRAME_SGIX 0x8172 #define GL_TEXTURE_CLIPMAP_OFFSET_SGIX 0x8173 #define GL_TEXTURE_CLIPMAP_VIRTUAL_DEPTH_SGIX 0x8174 #define GL_TEXTURE_CLIPMAP_LOD_OFFSET_SGIX 0x8175 #define GL_TEXTURE_CLIPMAP_DEPTH_SGIX 0x8176 #define GL_MAX_CLIPMAP_DEPTH_SGIX 0x8177 #define GL_MAX_CLIPMAP_VIRTUAL_DEPTH_SGIX 0x8178 #define GL_NEAREST_CLIPMAP_NEAREST_SGIX 0x844D #define GL_NEAREST_CLIPMAP_LINEAR_SGIX 0x844E #define GL_LINEAR_CLIPMAP_NEAREST_SGIX 0x844F #endif #ifndef GL_SGIX_shadow #define GL_SGIX_shadow #define AGL_SGIX_shadow #define GL_TEXTURE_COMPARE_SGIX 0x819A #define GL_TEXTURE_COMPARE_OPERATOR_SGIX 0x819B #define GL_TEXTURE_LEQUAL_R_SGIX 0x819C #define GL_TEXTURE_GEQUAL_R_SGIX 0x819D #endif #ifndef GL_SGIS_texture_edge_clamp #define GL_SGIS_texture_edge_clamp #define AGL_SGIS_texture_edge_clamp #define GL_CLAMP_TO_EDGE_SGIS 0x812F #endif #ifndef GL_EXT_blend_minmax #define GL_EXT_blend_minmax #define AGL_EXT_blend_minmax #define GL_FUNC_ADD_EXT 0x8006 #define GL_MIN_EXT 0x8007 #define GL_MAX_EXT 0x8008 #define GL_BLEND_EQUATION_EXT 0x8009 #endif #ifndef GL_EXT_blend_subtract #define GL_EXT_blend_subtract #define AGL_EXT_blend_subtract #define GL_FUNC_SUBTRACT_EXT 0x800A #define GL_FUNC_REVERSE_SUBTRACT_EXT 0x800B #endif #ifndef GL_SGIX_interlace #define GL_SGIX_interlace #define AGL_SGIX_interlace #define GL_INTERLACE_SGIX 0x8094 #endif #ifndef GL_SGIX_pixel_tiles #define GL_SGIX_pixel_tiles #define AGL_SGIX_pixel_tiles #define GL_PIXEL_TILE_BEST_ALIGNMENT_SGIX 0x813E #define GL_PIXEL_TILE_CACHE_INCREMENT_SGIX 0x813F #define GL_PIXEL_TILE_WIDTH_SGIX 0x8140 #define GL_PIXEL_TILE_HEIGHT_SGIX 0x8141 #define GL_PIXEL_TILE_GRID_WIDTH_SGIX 0x8142 #define GL_PIXEL_TILE_GRID_HEIGHT_SGIX 0x8143 #define GL_PIXEL_TILE_GRID_DEPTH_SGIX 0x8144 #define GL_PIXEL_TILE_CACHE_SIZE_SGIX 0x8145 #endif #ifndef GL_SGIS_texture_select #define GL_SGIS_texture_select #define AGL_SGIS_texture_select #define GL_DUAL_ALPHA4_SGIS 0x8110 #define GL_DUAL_ALPHA8_SGIS 0x8111 #define GL_DUAL_ALPHA12_SGIS 0x8112 #define GL_DUAL_ALPHA16_SGIS 0x8113 #define GL_DUAL_LUMINANCE4_SGIS 0x8114 #define GL_DUAL_LUMINANCE8_SGIS 0x8115 #define GL_DUAL_LUMINANCE12_SGIS 0x8116 #define GL_DUAL_LUMINANCE16_SGIS 0x8117 #define GL_DUAL_INTENSITY4_SGIS 0x8118 #define GL_DUAL_INTENSITY8_SGIS 0x8119 #define GL_DUAL_INTENSITY12_SGIS 0x811A #define GL_DUAL_INTENSITY16_SGIS 0x811B #define GL_DUAL_LUMINANCE_ALPHA4_SGIS 0x811C #define GL_DUAL_LUMINANCE_ALPHA8_SGIS 0x811D #define GL_QUAD_ALPHA4_SGIS 0x811E #define GL_QUAD_ALPHA8_SGIS 0x811F #define GL_QUAD_LUMINANCE4_SGIS 0x8120 #define GL_QUAD_LUMINANCE8_SGIS 0x8121 #define GL_QUAD_INTENSITY4_SGIS 0x8122 #define GL_QUAD_INTENSITY8_SGIS 0x8123 #define GL_DUAL_TEXTURE_SELECT_SGIS 0x8124 #define GL_QUAD_TEXTURE_SELECT_SGIS 0x8125 #endif #ifndef GL_SGIX_sprite #define GL_SGIX_sprite #define AGL_SGIX_sprite #define GL_SPRITE_SGIX 0x8148 #define GL_SPRITE_MODE_SGIX 0x8149 #define GL_SPRITE_AXIS_SGIX 0x814A #define GL_SPRITE_TRANSLATION_SGIX 0x814B #define GL_SPRITE_AXIAL_SGIX 0x814C #define GL_SPRITE_OBJECT_ALIGNED_SGIX 0x814D #define GL_SPRITE_EYE_ALIGNED_SGIX 0x814E #endif #ifndef GL_SGIX_texture_multi_buffer #define GL_SGIX_texture_multi_buffer #define AGL_SGIX_texture_multi_buffer #define GL_TEXTURE_MULTI_BUFFER_HINT_SGIX 0x812E #endif #ifndef GL_EXT_point_parameters #define GL_EXT_point_parameters #define AGL_EXT_point_parameters #define GL_POINT_SIZE_MIN_EXT 0x8126 #define GL_POINT_SIZE_MAX_EXT 0x8127 #define GL_POINT_FADE_THRESHOLD_SIZE_EXT 0x8128 #define GL_DISTANCE_ATTENUATION_EXT 0x8129 #endif #ifndef GL_SGIS_point_parameters #define GL_SGIS_point_parameters #define AGL_SGIS_point_parameters #define GL_POINT_SIZE_MIN_SGIS 0x8126 #define GL_POINT_SIZE_MAX_SGIS 0x8127 #define GL_POINT_FADE_THRESHOLD_SIZE_SGIS 0x8128 #define GL_DISTANCE_ATTENUATION_SGIS 0x8129 #endif #ifndef GL_SGIX_instruments #define GL_SGIX_instruments #define AGL_SGIX_instruments #define GL_INSTRUMENT_BUFFER_POINTER_SGIX 0x8180 #define GL_INSTRUMENT_MEASUREMENTS_SGIX 0x8181 #endif #ifndef GL_SGIX_texture_scale_bias #define GL_SGIX_texture_scale_bias #define AGL_SGIX_texture_scale_bias #define GL_POST_TEXTURE_FILTER_BIAS_SGIX 0x8179 #define GL_POST_TEXTURE_FILTER_SCALE_SGIX 0x817A #define GL_POST_TEXTURE_FILTER_BIAS_RANGE_SGIX 0x817B #define GL_POST_TEXTURE_FILTER_SCALE_RANGE_SGIX 0x817C #endif #ifndef GL_SGIX_framezoom #define GL_SGIX_framezoom #define AGL_SGIX_framezoom #define GL_FRAMEZOOM_SGIX 0x818B #define GL_FRAMEZOOM_FACTOR_SGIX 0x818C #define GL_MAX_FRAMEZOOM_FACTOR_SGIX 0x818D #endif #ifndef GL_FfdMaskSGIX #define GL_FfdMaskSGIX #define AGL_FfdMaskSGIX #define GL_TEXTURE_DEFORMATION_BIT_SGIX 0x00000001 #define GL_GEOMETRY_DEFORMATION_BIT_SGIX 0x00000002 #endif #ifndef GL_SGIX_tag_sample_buffer #define GL_SGIX_tag_sample_buffer #define AGL_SGIX_tag_sample_buffer #endif #ifndef GL_SGIX_polynomial_ffd #define GL_SGIX_polynomial_ffd #define AGL_SGIX_polynomial_ffd #define GL_GEOMETRY_DEFORMATION_SGIX 0x8194 #define GL_TEXTURE_DEFORMATION_SGIX 0x8195 #define GL_DEFORMATIONS_MASK_SGIX 0x8196 #define GL_MAX_DEFORMATION_ORDER_SGIX 0x8197 #endif #ifndef GL_SGIX_reference_plane #define GL_SGIX_reference_plane #define AGL_SGIX_reference_plane #define GL_REFERENCE_PLANE_SGIX 0x817D #define GL_REFERENCE_PLANE_EQUATION_SGIX 0x817E #endif #ifndef GL_SGIX_depth_texture #define GL_SGIX_depth_texture #define AGL_SGIX_depth_texture #define GL_DEPTH_COMPONENT16_SGIX 0x81A5 #define GL_DEPTH_COMPONENT24_SGIX 0x81A6 #define GL_DEPTH_COMPONENT32_SGIX 0x81A7 #endif #ifndef GL_SGIX_flush_raster #define GL_SGIX_flush_raster #define AGL_SGIX_flush_raster #endif #ifndef GL_SGIS_fog_function #define GL_SGIS_fog_function #define AGL_SGIS_fog_function #define GL_FOG_FUNC_SGIS 0x812A #define GL_FOG_FUNC_POINTS_SGIS 0x812B #define GL_MAX_FOG_FUNC_POINTS_SGIS 0x812C #endif #ifndef GL_SGIX_fog_offset #define GL_SGIX_fog_offset #define AGL_SGIX_fog_offset #define GL_FOG_OFFSET_SGIX 0x8198 #define GL_FOG_OFFSET_VALUE_SGIX 0x8199 #endif #ifndef GL_HP_image_transform #define GL_HP_image_transform #define AGL_HP_image_transform #define GL_IMAGE_SCALE_X_HP 0x8155 #define GL_IMAGE_SCALE_Y_HP 0x8156 #define GL_IMAGE_TRANSLATE_X_HP 0x8157 #define GL_IMAGE_TRANSLATE_Y_HP 0x8158 #define GL_IMAGE_ROTATE_ANGLE_HP 0x8159 #define GL_IMAGE_ROTATE_ORIGIN_X_HP 0x815A #define GL_IMAGE_ROTATE_ORIGIN_Y_HP 0x815B #define GL_IMAGE_MAG_FILTER_HP 0x815C #define GL_IMAGE_MIN_FILTER_HP 0x815D #define GL_IMAGE_CUBIC_WEIGHT_HP 0x815E #define GL_CUBIC_HP 0x815F #define GL_AVERAGE_HP 0x8160 #define GL_IMAGE_TRANSFORM_2D_HP 0x8161 #define GL_POST_IMAGE_TRANSFORM_COLOR_TABLE_HP 0x8162 #define GL_PROXY_POST_IMAGE_TRANSFORM_COLOR_TABLE_HP 0x8163 #endif #ifndef GL_HP_convolution_border_modes #define GL_HP_convolution_border_modes #define AGL_HP_convolution_border_modes #define GL_IGNORE_BORDER_HP 0x8150 #define GL_CONSTANT_BORDER_HP 0x8151 #define GL_REPLICATE_BORDER_HP 0x8153 #define GL_CONVOLUTION_BORDER_COLOR_HP 0x8154 #endif #ifndef GL_SGIX_texture_add_env #define GL_SGIX_texture_add_env #define AGL_SGIX_texture_add_env #define GL_TEXTURE_ENV_BIAS_SGIX 0x80BE #endif #ifndef GL_EXT_color_subtable #define GL_EXT_color_subtable #define AGL_EXT_color_subtable #endif #ifndef GL_PGI_vertex_hints #define GL_PGI_vertex_hints #define AGL_PGI_vertex_hints #define GL_VERTEX_DATA_HINT_PGI 0x1A22A #define GL_VERTEX_CONSISTENT_HINT_PGI 0x1A22B #define GL_MATERIAL_SIDE_HINT_PGI 0x1A22C #define GL_MAX_VERTEX_HINT_PGI 0x1A22D #define GL_COLOR3_BIT_PGI 0x00010000 #define GL_COLOR4_BIT_PGI 0x00020000 #define GL_EDGEFLAG_BIT_PGI 0x00040000 #define GL_INDEX_BIT_PGI 0x00080000 #define GL_MAT_AMBIENT_BIT_PGI 0x00100000 #define GL_MAT_AMBIENT_AND_DIFFUSE_BIT_PGI 0x00200000 #define GL_MAT_DIFFUSE_BIT_PGI 0x00400000 #define GL_MAT_EMISSION_BIT_PGI 0x00800000 #define GL_MAT_COLOR_INDEXES_BIT_PGI 0x01000000 #define GL_MAT_SHININESS_BIT_PGI 0x02000000 #define GL_MAT_SPECULAR_BIT_PGI 0x04000000 #define GL_NORMAL_BIT_PGI 0x08000000 #define GL_TEXCOORD1_BIT_PGI 0x10000000 #define GL_TEXCOORD2_BIT_PGI 0x20000000 #define GL_TEXCOORD3_BIT_PGI 0x40000000 #define GL_TEXCOORD4_BIT_PGI 0x80000000 #define GL_VERTEX23_BIT_PGI 0x00000004 #define GL_VERTEX4_BIT_PGI 0x00000008 #endif #ifndef GL_PGI_misc_hints #define GL_PGI_misc_hints #define AGL_PGI_misc_hints #define GL_PREFER_DOUBLEBUFFER_HINT_PGI 0x1A1F8 #define GL_CONSERVE_MEMORY_HINT_PGI 0x1A1FD #define GL_RECLAIM_MEMORY_HINT_PGI 0x1A1FE #define GL_NATIVE_GRAPHICS_HANDLE_PGI 0x1A202 #define GL_NATIVE_GRAPHICS_BEGIN_HINT_PGI 0x1A203 #define GL_NATIVE_GRAPHICS_END_HINT_PGI 0x1A204 #define GL_ALWAYS_FAST_HINT_PGI 0x1A20C #define GL_ALWAYS_SOFT_HINT_PGI 0x1A20D #define GL_ALLOW_DRAW_OBJ_HINT_PGI 0x1A20E #define GL_ALLOW_DRAW_WIN_HINT_PGI 0x1A20F #define GL_ALLOW_DRAW_FRG_HINT_PGI 0x1A210 #define GL_ALLOW_DRAW_MEM_HINT_PGI 0x1A211 #define GL_STRICT_DEPTHFUNC_HINT_PGI 0x1A216 #define GL_STRICT_LIGHTING_HINT_PGI 0x1A217 #define GL_STRICT_SCISSOR_HINT_PGI 0x1A218 #define GL_FULL_STIPPLE_HINT_PGI 0x1A219 #define GL_CLIP_NEAR_HINT_PGI 0x1A220 #define GL_CLIP_FAR_HINT_PGI 0x1A221 #define GL_WIDE_LINE_HINT_PGI 0x1A222 #define GL_BACK_NORMALS_HINT_PGI 0x1A223 #endif #ifndef GL_EXT_paletted_texture #define GL_EXT_paletted_texture #define AGL_EXT_paletted_texture #define GL_COLOR_INDEX1_EXT 0x80E2 #define GL_COLOR_INDEX2_EXT 0x80E3 #define GL_COLOR_INDEX4_EXT 0x80E4 #define GL_COLOR_INDEX8_EXT 0x80E5 #define GL_COLOR_INDEX12_EXT 0x80E6 #define GL_COLOR_INDEX16_EXT 0x80E7 #define GL_TEXTURE_INDEX_SIZE_EXT 0x80ED #endif #ifndef GL_EXT_clip_volume_hint #define GL_EXT_clip_volume_hint #define AGL_EXT_clip_volume_hint #define GL_CLIP_VOLUME_CLIPPING_HINT_EXT 0x80F0 #endif #ifndef GL_SGIX_list_priority #define GL_SGIX_list_priority #define AGL_SGIX_list_priority #define GL_LIST_PRIORITY_SGIX 0x8182 #endif #ifndef GL_SGIX_ir_instrument1 #define GL_SGIX_ir_instrument1 #define AGL_SGIX_ir_instrument1 #define GL_IR_INSTRUMENT1_SGIX 0x817F #endif #ifndef GL_SGIX_calligraphic_fragment #define GL_SGIX_calligraphic_fragment #define AGL_SGIX_calligraphic_fragment #define GL_CALLIGRAPHIC_FRAGMENT_SGIX 0x8183 #endif #ifndef GL_SGIX_texture_lod_bias #define GL_SGIX_texture_lod_bias #define AGL_SGIX_texture_lod_bias #define GL_TEXTURE_LOD_BIAS_S_SGIX 0x818E #define GL_TEXTURE_LOD_BIAS_T_SGIX 0x818F #define GL_TEXTURE_LOD_BIAS_R_SGIX 0x8190 #endif #ifndef GL_SGIX_shadow_ambient #define GL_SGIX_shadow_ambient #define AGL_SGIX_shadow_ambient #define GL_SHADOW_AMBIENT_SGIX 0x80BF #endif #ifndef GL_EXT_index_material #define GL_EXT_index_material #define AGL_EXT_index_material #define GL_INDEX_MATERIAL_EXT 0x81B8 #define GL_INDEX_MATERIAL_PARAMETER_EXT 0x81B9 #define GL_INDEX_MATERIAL_FACE_EXT 0x81BA #endif #ifndef GL_EXT_index_func #define GL_EXT_index_func #define AGL_EXT_index_func #define GL_INDEX_TEST_EXT 0x81B5 #define GL_INDEX_TEST_FUNC_EXT 0x81B6 #define GL_INDEX_TEST_REF_EXT 0x81B7 #endif #ifndef GL_EXT_index_array_formats #define GL_EXT_index_array_formats #define AGL_EXT_index_array_formats #define GL_IUI_V2F_EXT 0x81AD #define GL_IUI_V3F_EXT 0x81AE #define GL_IUI_N3F_V2F_EXT 0x81AF #define GL_IUI_N3F_V3F_EXT 0x81B0 #define GL_T2F_IUI_V2F_EXT 0x81B1 #define GL_T2F_IUI_V3F_EXT 0x81B2 #define GL_T2F_IUI_N3F_V2F_EXT 0x81B3 #define GL_T2F_IUI_N3F_V3F_EXT 0x81B4 #endif #ifndef GL_EXT_compiled_vertex_array #define GL_EXT_compiled_vertex_array #define AGL_EXT_compiled_vertex_array #define GL_ARRAY_ELEMENT_LOCK_FIRST_EXT 0x81A8 #define GL_ARRAY_ELEMENT_LOCK_COUNT_EXT 0x81A9 #endif #ifndef GL_EXT_cull_vertex #define GL_EXT_cull_vertex #define AGL_EXT_cull_vertex #define GL_CULL_VERTEX_EXT 0x81AA #define GL_CULL_VERTEX_EYE_POSITION_EXT 0x81AB #define GL_CULL_VERTEX_OBJECT_POSITION_EXT 0x81AC #endif #ifndef GL_SGIX_ycrcb #define GL_SGIX_ycrcb #define AGL_SGIX_ycrcb #define GL_YCRCB_422_SGIX 0x81BB #define GL_YCRCB_444_SGIX 0x81BC #endif #ifndef GL_SGIX_fragment_lighting #define GL_SGIX_fragment_lighting #define AGL_SGIX_fragment_lighting #define GL_FRAGMENT_LIGHTING_SGIX 0x8400 #define GL_FRAGMENT_COLOR_MATERIAL_SGIX 0x8401 #define GL_FRAGMENT_COLOR_MATERIAL_FACE_SGIX 0x8402 #define GL_FRAGMENT_COLOR_MATERIAL_PARAMETER_SGIX 0x8403 #define GL_MAX_FRAGMENT_LIGHTS_SGIX 0x8404 #define GL_MAX_ACTIVE_LIGHTS_SGIX 0x8405 #define GL_CURRENT_RASTER_NORMAL_SGIX 0x8406 #define GL_LIGHT_ENV_MODE_SGIX 0x8407 #define GL_FRAGMENT_LIGHT_MODEL_LOCAL_VIEWER_SGIX 0x8408 #define GL_FRAGMENT_LIGHT_MODEL_TWO_SIDE_SGIX 0x8409 #define GL_FRAGMENT_LIGHT_MODEL_AMBIENT_SGIX 0x840A #define GL_FRAGMENT_LIGHT_MODEL_NORMAL_INTERPOLATION_SGIX 0x840B #define GL_FRAGMENT_LIGHT0_SGIX 0x840C #define GL_FRAGMENT_LIGHT1_SGIX 0x840D #define GL_FRAGMENT_LIGHT2_SGIX 0x840E #define GL_FRAGMENT_LIGHT3_SGIX 0x840F #define GL_FRAGMENT_LIGHT4_SGIX 0x8410 #define GL_FRAGMENT_LIGHT5_SGIX 0x8411 #define GL_FRAGMENT_LIGHT6_SGIX 0x8412 #define GL_FRAGMENT_LIGHT7_SGIX 0x8413 #endif #ifndef GL_IBM_rasterpos_clip #define GL_IBM_rasterpos_clip #define AGL_IBM_rasterpos_clip #define GL_RASTER_POSITION_UNCLIPPED_IBM 0x19262 #endif #ifndef GL_HP_texture_lighting #define GL_HP_texture_lighting #define AGL_HP_texture_lighting #define GL_TEXTURE_LIGHTING_MODE_HP 0x8167 #define GL_TEXTURE_POST_SPECULAR_HP 0x8168 #define GL_TEXTURE_PRE_SPECULAR_HP 0x8169 #endif #ifndef GL_EXT_draw_range_elements #define GL_EXT_draw_range_elements #define AGL_EXT_draw_range_elements #define GL_MAX_ELEMENTS_VERTICES_EXT 0x80E8 #define GL_MAX_ELEMENTS_INDICES_EXT 0x80E9 #endif #ifndef GL_WIN_phong_shading #define GL_WIN_phong_shading #define AGL_WIN_phong_shading #define GL_PHONG_WIN 0x80EA #define GL_PHONG_HINT_WIN 0x80EB #endif #ifndef GL_WIN_specular_fog #define GL_WIN_specular_fog #define AGL_WIN_specular_fog #define GL_FOG_SPECULAR_TEXTURE_WIN 0x80EC #endif #ifndef GL_EXT_light_texture #define GL_EXT_light_texture #define AGL_EXT_light_texture #define GL_FRAGMENT_MATERIAL_EXT 0x8349 #define GL_FRAGMENT_NORMAL_EXT 0x834A #define GL_FRAGMENT_COLOR_EXT 0x834C #define GL_ATTENUATION_EXT 0x834D #define GL_SHADOW_ATTENUATION_EXT 0x834E #define GL_TEXTURE_APPLICATION_MODE_EXT 0x834F #define GL_TEXTURE_LIGHT_EXT 0x8350 #define GL_TEXTURE_MATERIAL_FACE_EXT 0x8351 #define GL_TEXTURE_MATERIAL_PARAMETER_EXT 0x8352 #ifndef GL_FRAGMENT_DEPTH_EXT #define GL_FRAGMENT_DEPTH_EXT 0x8452 #endif #endif #ifndef GL_SGIX_blend_alpha_minmax #define GL_SGIX_blend_alpha_minmax #define AGL_SGIX_blend_alpha_minmax #define GL_ALPHA_MIN_SGIX 0x8320 #define GL_ALPHA_MAX_SGIX 0x8321 #endif #ifndef GL_SGIX_impact_pixel_texture #define GL_SGIX_impact_pixel_texture #define AGL_SGIX_impact_pixel_texture #define GL_PIXEL_TEX_GEN_Q_CEILING_SGIX 0x8184 #define GL_PIXEL_TEX_GEN_Q_ROUND_SGIX 0x8185 #define GL_PIXEL_TEX_GEN_Q_FLOOR_SGIX 0x8186 #define GL_PIXEL_TEX_GEN_ALPHA_REPLACE_SGIX 0x8187 #define GL_PIXEL_TEX_GEN_ALPHA_NO_REPLACE_SGIX 0x8188 #define GL_PIXEL_TEX_GEN_ALPHA_LS_SGIX 0x8189 #define GL_PIXEL_TEX_GEN_ALPHA_MS_SGIX 0x818A #endif #ifndef GL_EXT_bgra #define GL_EXT_bgra #define AGL_EXT_bgra #define GL_BGR_EXT 0x80E0 #define GL_BGRA_EXT 0x80E1 #endif #ifndef GL_SGIX_async #define GL_SGIX_async #define AGL_SGIX_async #define GL_ASYNC_MARKER_SGIX 0x8329 #endif #ifndef GL_SGIX_async_pixel #define GL_SGIX_async_pixel #define AGL_SGIX_async_pixel #define GL_ASYNC_TEX_IMAGE_SGIX 0x835C #define GL_ASYNC_DRAW_PIXELS_SGIX 0x835D #define GL_ASYNC_READ_PIXELS_SGIX 0x835E #define GL_MAX_ASYNC_TEX_IMAGE_SGIX 0x835F #define GL_MAX_ASYNC_DRAW_PIXELS_SGIX 0x8360 #define GL_MAX_ASYNC_READ_PIXELS_SGIX 0x8361 #endif #ifndef GL_SGIX_async_histogram #define GL_SGIX_async_histogram #define AGL_SGIX_async_histogram #define GL_ASYNC_HISTOGRAM_SGIX 0x832C #define GL_MAX_ASYNC_HISTOGRAM_SGIX 0x832D #endif #ifndef GL_INTEL_parallel_arrays #define GL_INTEL_parallel_arrays #define AGL_INTEL_parallel_arrays #define GL_PARALLEL_ARRAYS_INTEL 0x83F4 #define GL_VERTEX_ARRAY_PARALLEL_POINTERS_INTEL 0x83F5 #define GL_NORMAL_ARRAY_PARALLEL_POINTERS_INTEL 0x83F6 #define GL_COLOR_ARRAY_PARALLEL_POINTERS_INTEL 0x83F7 #define GL_TEXTURE_COORD_ARRAY_PARALLEL_POINTERS_INTEL 0x83F8 #endif #ifndef GL_HP_occlusion_test #define GL_HP_occlusion_test #define AGL_HP_occlusion_test #define GL_OCCLUSION_TEST_HP 0x8165 #define GL_OCCLUSION_TEST_RESULT_HP 0x8166 #endif #ifndef GL_EXT_pixel_transform #define GL_EXT_pixel_transform #define AGL_EXT_pixel_transform #define GL_PIXEL_TRANSFORM_2D_EXT 0x8330 #define GL_PIXEL_MAG_FILTER_EXT 0x8331 #define GL_PIXEL_MIN_FILTER_EXT 0x8332 #define GL_PIXEL_CUBIC_WEIGHT_EXT 0x8333 #define GL_CUBIC_EXT 0x8334 #define GL_AVERAGE_EXT 0x8335 #define GL_PIXEL_TRANSFORM_2D_STACK_DEPTH_EXT 0x8336 #define GL_MAX_PIXEL_TRANSFORM_2D_STACK_DEPTH_EXT 0x8337 #define GL_PIXEL_TRANSFORM_2D_MATRIX_EXT 0x8338 #endif #ifndef GL_EXT_shared_texture_palette #define GL_EXT_shared_texture_palette #define AGL_EXT_shared_texture_palette #define GL_SHARED_TEXTURE_PALETTE_EXT 0x81FB #endif #ifndef GL_EXT_separate_specular_color #define GL_EXT_separate_specular_color #define AGL_EXT_separate_specular_color #define GL_LIGHT_MODEL_COLOR_CONTROL_EXT 0x81F8 #define GL_SINGLE_COLOR_EXT 0x81F9 #define GL_SEPARATE_SPECULAR_COLOR_EXT 0x81FA #endif #ifndef GL_EXT_secondary_color #define GL_EXT_secondary_color #define AGL_EXT_secondary_color #define GL_COLOR_SUM_EXT 0x8458 #define GL_CURRENT_SECONDARY_COLOR_EXT 0x8459 #define GL_SECONDARY_COLOR_ARRAY_SIZE_EXT 0x845A #define GL_SECONDARY_COLOR_ARRAY_TYPE_EXT 0x845B #define GL_SECONDARY_COLOR_ARRAY_STRIDE_EXT 0x845C #define GL_SECONDARY_COLOR_ARRAY_POINTER_EXT 0x845D #define GL_SECONDARY_COLOR_ARRAY_EXT 0x845E #endif #ifndef GL_EXT_texture_perturb_normal #define GL_EXT_texture_perturb_normal #define AGL_EXT_texture_perturb_normal #define GL_PERTURB_EXT 0x85AE #define GL_TEXTURE_NORMAL_EXT 0x85AF #endif #ifndef GL_EXT_multi_draw_arrays #define GL_EXT_multi_draw_arrays #define AGL_EXT_multi_draw_arrays #endif #ifndef GL_EXT_fog_coord #define GL_EXT_fog_coord #define AGL_EXT_fog_coord #define GL_FOG_COORDINATE_SOURCE_EXT 0x8450 #define GL_FOG_COORDINATE_EXT 0x8451 #define GL_FRAGMENT_DEPTH_EXT 0x8452 #define GL_CURRENT_FOG_COORDINATE_EXT 0x8453 #define GL_FOG_COORDINATE_ARRAY_TYPE_EXT 0x8454 #define GL_FOG_COORDINATE_ARRAY_STRIDE_EXT 0x8455 #define GL_FOG_COORDINATE_ARRAY_POINTER_EXT 0x8456 #define GL_FOG_COORDINATE_ARRAY_EXT 0x8457 #endif #ifndef GL_REND_screen_coordinates #define GL_REND_screen_coordinates #define AGL_REND_screen_coordinates #define GL_SCREEN_COORDINATES_REND 0x8490 #define GL_INVERTED_SCREEN_W_REND 0x8491 #endif #ifndef GL_EXT_coordinate_frame #define GL_EXT_coordinate_frame #define AGL_EXT_coordinate_frame #define GL_TANGENT_ARRAY_EXT 0x8439 #define GL_BINORMAL_ARRAY_EXT 0x843A #define GL_CURRENT_TANGENT_EXT 0x843B #define GL_CURRENT_BINORMAL_EXT 0x843C #define GL_TANGENT_ARRAY_TYPE_EXT 0x843E #define GL_TANGENT_ARRAY_STRIDE_EXT 0x843F #define GL_BINORMAL_ARRAY_TYPE_EXT 0x8440 #define GL_BINORMAL_ARRAY_STRIDE_EXT 0x8441 #define GL_TANGENT_ARRAY_POINTER_EXT 0x8442 #define GL_BINORMAL_ARRAY_POINTER_EXT 0x8443 #define GL_MAP1_TANGENT_EXT 0x8444 #define GL_MAP2_TANGENT_EXT 0x8445 #define GL_MAP1_BINORMAL_EXT 0x8446 #define GL_MAP2_BINORMAL_EXT 0x8447 #endif #ifndef GL_EXT_texture_env_combine #define GL_EXT_texture_env_combine #define AGL_EXT_texture_env_combine #define GL_COMBINE_EXT 0x8570 #define GL_COMBINE_RGB_EXT 0x8571 #define GL_COMBINE_ALPHA_EXT 0x8572 #define GL_RGB_SCALE_EXT 0x8573 #define GL_ADD_SIGNED_EXT 0x8574 #define GL_INTERPOLATE_EXT 0x8575 #define GL_CONSTANT_EXT 0x8576 #define GL_PRIMARY_COLOR_EXT 0x8577 #define GL_PREVIOUS_EXT 0x8578 #define GL_SOURCE0_RGB_EXT 0x8580 #define GL_SOURCE1_RGB_EXT 0x8581 #define GL_SOURCE2_RGB_EXT 0x8582 #define GL_SOURCE0_ALPHA_EXT 0x8588 #define GL_SOURCE1_ALPHA_EXT 0x8589 #define GL_SOURCE2_ALPHA_EXT 0x858A #define GL_OPERAND0_RGB_EXT 0x8590 #define GL_OPERAND1_RGB_EXT 0x8591 #define GL_OPERAND2_RGB_EXT 0x8592 #define GL_OPERAND0_ALPHA_EXT 0x8598 #define GL_OPERAND1_ALPHA_EXT 0x8599 #define GL_OPERAND2_ALPHA_EXT 0x859A #endif #ifndef GL_APPLE_specular_vector #define GL_APPLE_specular_vector #define AGL_APPLE_specular_vector #define GL_LIGHT_MODEL_SPECULAR_VECTOR_APPLE 0x85B0 #endif #ifndef GL_APPLE_transform_hint #define GL_APPLE_transform_hint #define AGL_APPLE_transform_hint #define GL_TRANSFORM_HINT_APPLE 0x85B1 #endif #ifndef GL_SGIX_fog_scale #define GL_SGIX_fog_scale #define AGL_SGIX_fog_scale #define GL_FOG_SCALE_SGIX 0x81FC #define GL_FOG_SCALE_VALUE_SGIX 0x81FD #endif #ifndef GL_SUNX_constant_data #define GL_SUNX_constant_data #define AGL_SUNX_constant_data #define GL_UNPACK_CONSTANT_DATA_SUNX 0x81D5 #define GL_TEXTURE_CONSTANT_DATA_SUNX 0x81D6 #endif #ifndef GL_SUN_global_alpha #define GL_SUN_global_alpha #define AGL_SUN_global_alpha #define GL_GLOBAL_ALPHA_SUN 0x81D9 #define GL_GLOBAL_ALPHA_FACTOR_SUN 0x81DA #endif #ifndef GL_SUN_triangle_list #define GL_SUN_triangle_list #define AGL_SUN_triangle_list #define GL_RESTART_SUN 0x0001 #define GL_REPLACE_MIDDLE_SUN 0x0002 #define GL_REPLACE_OLDEST_SUN 0x0003 #define GL_TRIANGLE_LIST_SUN 0x81D7 #define GL_REPLACEMENT_CODE_SUN 0x81D8 #define GL_REPLACEMENT_CODE_ARRAY_SUN 0x85C0 #define GL_REPLACEMENT_CODE_ARRAY_TYPE_SUN 0x85C1 #define GL_REPLACEMENT_CODE_ARRAY_STRIDE_SUN 0x85C2 #define GL_REPLACEMENT_CODE_ARRAY_POINTER_SUN 0x85C3 #define GL_R1UI_V3F_SUN 0x85C4 #define GL_R1UI_C4UB_V3F_SUN 0x85C5 #define GL_R1UI_C3F_V3F_SUN 0x85C6 #define GL_R1UI_N3F_V3F_SUN 0x85C7 #define GL_R1UI_C4F_N3F_V3F_SUN 0x85C8 #define GL_R1UI_T2F_V3F_SUN 0x85C9 #define GL_R1UI_T2F_N3F_V3F_SUN 0x85CA #define GL_R1UI_T2F_C4F_N3F_V3F_SUN 0x85CB #endif #ifndef GL_SUN_vertex #define GL_SUN_vertex #define AGL_SUN_vertex #endif #ifndef GL_EXT_blend_func_separate #define GL_EXT_blend_func_separate #define AGL_EXT_blend_func_separate #define GL_BLEND_DST_RGB_EXT 0x80C8 #define GL_BLEND_SRC_RGB_EXT 0x80C9 #define GL_BLEND_DST_ALPHA_EXT 0x80CA #define GL_BLEND_SRC_ALPHA_EXT 0x80CB #endif #ifndef GL_INGR_color_clamp #define GL_INGR_color_clamp #define AGL_INGR_color_clamp #define GL_RED_MIN_CLAMP_INGR 0x8560 #define GL_GREEN_MIN_CLAMP_INGR 0x8561 #define GL_BLUE_MIN_CLAMP_INGR 0x8562 #define GL_ALPHA_MIN_CLAMP_INGR 0x8563 #define GL_RED_MAX_CLAMP_INGR 0x8564 #define GL_GREEN_MAX_CLAMP_INGR 0x8565 #define GL_BLUE_MAX_CLAMP_INGR 0x8566 #define GL_ALPHA_MAX_CLAMP_INGR 0x8567 #endif #ifndef GL_INGR_blend_func_separate #define GL_INGR_blend_func_separate #define AGL_INGR_blend_func_separate #endif #ifndef GL_INGR_interlace_read #define GL_INGR_interlace_read #define AGL_INGR_interlace_read #define GL_INTERLACE_READ_INGR 0x8568 #endif #ifndef GL_EXT_stencil_wrap #define GL_EXT_stencil_wrap #define AGL_EXT_stencil_wrap #define GL_INCR_WRAP_EXT 0x8507 #define GL_DECR_WRAP_EXT 0x8508 #endif #ifndef GL_EXT_422_pixels #define GL_EXT_422_pixels #define AGL_EXT_422_pixels #define GL_422_EXT 0x80CC #define GL_422_REV_EXT 0x80CD #define GL_422_AVERAGE_EXT 0x80CE #define GL_422_REV_AVERAGE_EXT 0x80CF #endif #ifndef GL_NV_texgen_reflection #define GL_NV_texgen_reflection #define AGL_NV_texgen_reflection #define GL_NORMAL_MAP_NV 0x8511 #define GL_REFLECTION_MAP_NV 0x8512 #endif #ifndef GL_EXT_texture_cube_map #define GL_EXT_texture_cube_map #define AGL_EXT_texture_cube_map #define GL_NORMAL_MAP_EXT 0x8511 #define GL_REFLECTION_MAP_EXT 0x8512 #define GL_TEXTURE_CUBE_MAP_EXT 0x8513 #define GL_TEXTURE_BINDING_CUBE_MAP_EXT 0x8514 #define GL_TEXTURE_CUBE_MAP_POSITIVE_X_EXT 0x8515 #define GL_TEXTURE_CUBE_MAP_NEGATIVE_X_EXT 0x8516 #define GL_TEXTURE_CUBE_MAP_POSITIVE_Y_EXT 0x8517 #define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT 0x8518 #define GL_TEXTURE_CUBE_MAP_POSITIVE_Z_EXT 0x8519 #define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT 0x851A #define GL_PROXY_TEXTURE_CUBE_MAP_EXT 0x851B #define GL_MAX_CUBE_MAP_TEXTURE_SIZE_EXT 0x851C #endif #ifndef GL_SUN_convolution_border_modes #define GL_SUN_convolution_border_modes #define AGL_SUN_convolution_border_modes #define GL_WRAP_BORDER_SUN 0x81D4 #endif #ifndef GL_EXT_texture_lod_bias #define GL_EXT_texture_lod_bias #define AGL_EXT_texture_lod_bias #define GL_MAX_TEXTURE_LOD_BIAS_EXT 0x84FD #define GL_TEXTURE_FILTER_CONTROL_EXT 0x8500 #define GL_TEXTURE_LOD_BIAS_EXT 0x8501 #endif #ifndef GL_EXT_texture_filter_anisotropic #define GL_EXT_texture_filter_anisotropic #define AGL_EXT_texture_filter_anisotropic #define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE #define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF #endif #ifndef GL_EXT_vertex_weighting #define GL_EXT_vertex_weighting #define AGL_EXT_vertex_weighting #define GL_MODELVIEW0_STACK_DEPTH_EXT GL_MODELVIEW_STACK_DEPTH #define GL_MODELVIEW1_STACK_DEPTH_EXT 0x8502 #define GL_MODELVIEW0_MATRIX_EXT GL_MODELVIEW_MATRIX #define GL_MODELVIEW1_MATRIX_EXT 0x8506 #define GL_VERTEX_WEIGHTING_EXT 0x8509 #define GL_MODELVIEW0_EXT GL_MODELVIEW #define GL_MODELVIEW1_EXT 0x850A #define GL_CURRENT_VERTEX_WEIGHT_EXT 0x850B #define GL_VERTEX_WEIGHT_ARRAY_EXT 0x850C #define GL_VERTEX_WEIGHT_ARRAY_SIZE_EXT 0x850D #define GL_VERTEX_WEIGHT_ARRAY_TYPE_EXT 0x850E #define GL_VERTEX_WEIGHT_ARRAY_STRIDE_EXT 0x850F #define GL_VERTEX_WEIGHT_ARRAY_POINTER_EXT 0x8510 #endif #ifndef GL_NV_light_max_exponent #define GL_NV_light_max_exponent #define AGL_NV_light_max_exponent #define GL_MAX_SHININESS_NV 0x8504 #define GL_MAX_SPOT_EXPONENT_NV 0x8505 #endif #ifndef GL_NV_vertex_array_range #define GL_NV_vertex_array_range #define AGL_NV_vertex_array_range #define GL_VERTEX_ARRAY_RANGE_NV 0x851D #define GL_VERTEX_ARRAY_RANGE_LENGTH_NV 0x851E #define GL_VERTEX_ARRAY_RANGE_VALID_NV 0x851F #define GL_MAX_VERTEX_ARRAY_RANGE_ELEMENT_NV 0x8520 #define GL_VERTEX_ARRAY_RANGE_POINTER_NV 0x8521 #endif #ifndef GL_NV_register_combiners #define GL_NV_register_combiners #define AGL_NV_register_combiners #define GL_REGISTER_COMBINERS_NV 0x8522 #define GL_VARIABLE_A_NV 0x8523 #define GL_VARIABLE_B_NV 0x8524 #define GL_VARIABLE_C_NV 0x8525 #define GL_VARIABLE_D_NV 0x8526 #define GL_VARIABLE_E_NV 0x8527 #define GL_VARIABLE_F_NV 0x8528 #define GL_VARIABLE_G_NV 0x8529 #define GL_CONSTANT_COLOR0_NV 0x852A #define GL_CONSTANT_COLOR1_NV 0x852B #define GL_PRIMARY_COLOR_NV 0x852C #define GL_SECONDARY_COLOR_NV 0x852D #define GL_SPARE0_NV 0x852E #define GL_SPARE1_NV 0x852F #define GL_DISCARD_NV 0x8530 #define GL_E_TIMES_F_NV 0x8531 #define GL_SPARE0_PLUS_SECONDARY_COLOR_NV 0x8532 #define GL_UNSIGNED_IDENTITY_NV 0x8536 #define GL_UNSIGNED_INVERT_NV 0x8537 #define GL_EXPAND_NORMAL_NV 0x8538 #define GL_EXPAND_NEGATE_NV 0x8539 #define GL_HALF_BIAS_NORMAL_NV 0x853A #define GL_HALF_BIAS_NEGATE_NV 0x853B #define GL_SIGNED_IDENTITY_NV 0x853C #define GL_SIGNED_NEGATE_NV 0x853D #define GL_SCALE_BY_TWO_NV 0x853E #define GL_SCALE_BY_FOUR_NV 0x853F #define GL_SCALE_BY_ONE_HALF_NV 0x8540 #define GL_BIAS_BY_NEGATIVE_ONE_HALF_NV 0x8541 #define GL_COMBINER_INPUT_NV 0x8542 #define GL_COMBINER_MAPPING_NV 0x8543 #define GL_COMBINER_COMPONENT_USAGE_NV 0x8544 #define GL_COMBINER_AB_DOT_PRODUCT_NV 0x8545 #define GL_COMBINER_CD_DOT_PRODUCT_NV 0x8546 #define GL_COMBINER_MUX_SUM_NV 0x8547 #define GL_COMBINER_SCALE_NV 0x8548 #define GL_COMBINER_BIAS_NV 0x8549 #define GL_COMBINER_AB_OUTPUT_NV 0x854A #define GL_COMBINER_CD_OUTPUT_NV 0x854B #define GL_COMBINER_SUM_OUTPUT_NV 0x854C #define GL_MAX_GENERAL_COMBINERS_NV 0x854D #define GL_NUM_GENERAL_COMBINERS_NV 0x854E #define GL_COLOR_SUM_CLAMP_NV 0x854F #define GL_COMBINER0_NV 0x8550 #define GL_COMBINER1_NV 0x8551 #define GL_COMBINER2_NV 0x8552 #define GL_COMBINER3_NV 0x8553 #define GL_COMBINER4_NV 0x8554 #define GL_COMBINER5_NV 0x8555 #define GL_COMBINER6_NV 0x8556 #define GL_COMBINER7_NV 0x8557 /* GL_TEXTURE0_ARB */ /* GL_TEXTURE1_ARB */ /* GL_ZERO */ /* GL_NONE */ /* GL_FOG */ #endif #ifndef GL_NV_fog_distance #define GL_NV_fog_distance #define AGL_NV_fog_distance #define GL_FOG_DISTANCE_MODE_NV 0x855A #define GL_EYE_RADIAL_NV 0x855B #define GL_EYE_PLANE_ABSOLUTE_NV 0x855C /* GL_EYE_PLANE */ #endif #ifndef GL_NV_texgen_emboss #define GL_NV_texgen_emboss #define AGL_NV_texgen_emboss #define GL_EMBOSS_LIGHT_NV 0x855D #define GL_EMBOSS_CONSTANT_NV 0x855E #define GL_EMBOSS_MAP_NV 0x855F #endif #ifndef GL_NV_texture_env_combine4 #define GL_NV_texture_env_combine4 #define AGL_NV_texture_env_combine4 #define GL_COMBINE4_NV 0x8503 #define GL_SOURCE3_RGB_NV 0x8583 #define GL_SOURCE3_ALPHA_NV 0x858B #define GL_OPERAND3_RGB_NV 0x8593 #define GL_OPERAND3_ALPHA_NV 0x859B #endif #ifndef GL_EXT_texture_compression_s3tc #define GL_EXT_texture_compression_s3tc #define AGL_EXT_texture_compression_s3tc #define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0 #define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1 #define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2 #define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3 #endif #ifndef GL_MESA_resize_buffers #define GL_MESA_resize_buffers #define AGL_MESA_resize_buffers #endif #ifndef GL_MESA_window_pos #define GL_MESA_window_pos #define AGL_MESA_window_pos #endif #ifndef GL_IBM_cull_vertex #define GL_IBM_cull_vertex #define AGL_IBM_cull_vertex #define GL_CULL_VERTEX_IBM 103050 #endif #ifndef GL_IBM_multimode_draw_arrays #define GL_IBM_multimode_draw_arrays #define AGL_IBM_multimode_draw_arrays #endif #ifndef GL_IBM_vertex_array_lists #define GL_IBM_vertex_array_lists #define AGL_IBM_vertex_array_lists #define GL_VERTEX_ARRAY_LIST_IBM 103070 #define GL_NORMAL_ARRAY_LIST_IBM 103071 #define GL_COLOR_ARRAY_LIST_IBM 103072 #define GL_INDEX_ARRAY_LIST_IBM 103073 #define GL_TEXTURE_COORD_ARRAY_LIST_IBM 103074 #define GL_EDGE_FLAG_ARRAY_LIST_IBM 103075 #define GL_FOG_COORDINATE_ARRAY_LIST_IBM 103076 #define GL_SECONDARY_COLOR_ARRAY_LIST_IBM 103077 #define GL_VERTEX_ARRAY_LIST_STRIDE_IBM 103080 #define GL_NORMAL_ARRAY_LIST_STRIDE_IBM 103081 #define GL_COLOR_ARRAY_LIST_STRIDE_IBM 103082 #define GL_INDEX_ARRAY_LIST_STRIDE_IBM 103083 #define GL_TEXTURE_COORD_ARRAY_LIST_STRIDE_IBM 103084 #define GL_EDGE_FLAG_ARRAY_LIST_STRIDE_IBM 103085 #define GL_FOG_COORDINATE_ARRAY_LIST_STRIDE_IBM 103086 #define GL_SECONDARY_COLOR_ARRAY_LIST_STRIDE_IBM 103087 #endif #ifndef GL_SGIX_subsample #define GL_SGIX_subsample #define AGL_SGIX_subsample #define GL_PACK_SUBSAMPLE_RATE_SGIX 0x85A0 #define GL_UNPACK_SUBSAMPLE_RATE_SGIX 0x85A1 #define GL_PIXEL_SUBSAMPLE_4444_SGIX 0x85A2 #define GL_PIXEL_SUBSAMPLE_2424_SGIX 0x85A3 #define GL_PIXEL_SUBSAMPLE_4242_SGIX 0x85A4 #endif #ifndef GL_SGIX_ycrcba #define GL_SGIX_ycrcba #define AGL_SGIX_ycrcba #define GL_YCRCB_SGIX 0x8318 #define GL_YCRCBA_SGIX 0x8319 #endif #ifndef GL_SGI_depth_pass_instrument #define GL_SGI_depth_pass_instrument #define AGL_SGI_depth_pass_instrument #define GL_DEPTH_PASS_INSTRUMENT_SGIX 0x8310 #define GL_DEPTH_PASS_INSTRUMENT_COUNTERS_SGIX 0x8311 #define GL_DEPTH_PASS_INSTRUMENT_MAX_SGIX 0x8312 #endif #ifndef GL_3DFX_texture_compression_FXT1 #define GL_3DFX_texture_compression_FXT1 #define AGL_3DFX_texture_compression_FXT1 #define GL_COMPRESSED_RGB_FXT1_3DFX 0x86B0 #define GL_COMPRESSED_RGBA_FXT1_3DFX 0x86B1 #endif #ifndef GL_3DFX_multisample #define GL_3DFX_multisample #define AGL_3DFX_multisample #define GL_MULTISAMPLE_3DFX 0x86B2 #define GL_SAMPLE_BUFFERS_3DFX 0x86B3 #define GL_SAMPLES_3DFX 0x86B4 #define GL_MULTISAMPLE_BIT_3DFX 0x20000000 #endif #ifndef GL_3DFX_tbuffer #define GL_3DFX_tbuffer #ifndef AGL_HEADER_NV #define AGL_3DFX_tbuffer #endif #endif #ifndef GL_EXT_multisample #define GL_EXT_multisample #define AGL_EXT_multisample #define GL_MULTISAMPLE_EXT 0x809D #define GL_SAMPLE_ALPHA_TO_MASK_EXT 0x809E #define GL_SAMPLE_ALPHA_TO_ONE_EXT 0x809F #define GL_SAMPLE_MASK_EXT 0x80A0 #define GL_1PASS_EXT 0x80A1 #define GL_2PASS_0_EXT 0x80A2 #define GL_2PASS_1_EXT 0x80A3 #define GL_4PASS_0_EXT 0x80A4 #define GL_4PASS_1_EXT 0x80A5 #define GL_4PASS_2_EXT 0x80A6 #define GL_4PASS_3_EXT 0x80A7 #define GL_SAMPLE_BUFFERS_EXT 0x80A8 #define GL_SAMPLES_EXT 0x80A9 #define GL_SAMPLE_MASK_VALUE_EXT 0x80AA #define GL_SAMPLE_MASK_INVERT_EXT 0x80AB #define GL_SAMPLE_PATTERN_EXT 0x80AC #define GL_MULTISAMPLE_BIT_EXT 0x20000000 #endif #ifndef GL_SGIX_vertex_preclip #define GL_SGIX_vertex_preclip #define AGL_SGIX_vertex_preclip #define GL_VERTEX_PRECLIP_SGIX 0x83EE #define GL_VERTEX_PRECLIP_HINT_SGIX 0x83EF #endif #ifndef GL_SGIX_convolution_accuracy #define GL_SGIX_convolution_accuracy #define AGL_SGIX_convolution_accuracy #define GL_CONVOLUTION_HINT_SGIX 0x8316 #endif #ifndef GL_SGIX_resample #define GL_SGIX_resample #define AGL_SGIX_resample #define GL_PACK_RESAMPLE_SGIX 0x842C #define GL_UNPACK_RESAMPLE_SGIX 0x842D #define GL_RESAMPLE_REPLICATE_SGIX 0x842E #define GL_RESAMPLE_ZERO_FILL_SGIX 0x842F #define GL_RESAMPLE_DECIMATE_SGIX 0x8430 #endif #ifndef GL_SGIS_point_line_texgen #define GL_SGIS_point_line_texgen #define AGL_SGIS_point_line_texgen #define GL_EYE_DISTANCE_TO_POINT_SGIS 0x81F0 #define GL_OBJECT_DISTANCE_TO_POINT_SGIS 0x81F1 #define GL_EYE_DISTANCE_TO_LINE_SGIS 0x81F2 #define GL_OBJECT_DISTANCE_TO_LINE_SGIS 0x81F3 #define GL_EYE_POINT_SGIS 0x81F4 #define GL_OBJECT_POINT_SGIS 0x81F5 #define GL_EYE_LINE_SGIS 0x81F6 #define GL_OBJECT_LINE_SGIS 0x81F7 #endif #ifndef GL_SGIS_texture_color_mask #define GL_SGIS_texture_color_mask #ifndef AGL_HEADER_NV #define AGL_SGIS_texture_color_mask #define GL_TEXTURE_COLOR_WRITEMASK_SGIS 0x81EF #endif #endif #ifndef GL_SGIX_igloo_interface #define GL_SGIX_igloo_interface #define AGL_SGIX_igloo_interface #endif #ifndef GL_EXT_texture_env_dot3 #define GL_EXT_texture_env_dot3 #define AGL_EXT_texture_env_dot3 /* GL_DOT3_RGB_EXT */ /* GL_DOT3_RGBA_EXT */ #endif #ifndef GL_ATI_texture_mirror_once #define GL_ATI_texture_mirror_once #define AGL_ATI_texture_mirror_once #define GL_MIRROR_CLAMP_ATI 0x8742 #define GL_MIRROR_CLAMP_TO_EDGE_ATI 0x8743 #endif #ifndef GL_NV_fence #define GL_NV_fence #define AGL_NV_fence #define GL_ALL_COMPLETED_NV 0x84F2 #define GL_FENCE_STATUS_NV 0x84F3 #define GL_FENCE_CONDITION_NV 0x84F4 #endif #ifndef GL_IBM_texture_mirrored_repeat #define GL_IBM_texture_mirrored_repeat #define AGL_IBM_texture_mirrored_repeat #define GL_MIRRORED_REPEAT_IBM 0x8370 #endif #ifndef GL_NV_evaluators #define GL_NV_evaluators #define AGL_NV_evaluators #define GL_EVAL_2D_NV 0x86C0 #define GL_EVAL_TRIANGULAR_2D_NV 0x86C1 #define GL_MAP_TESSELLATION_NV 0x86C2 #define GL_MAP_ATTRIB_U_ORDER_NV 0x86C3 #define GL_MAP_ATTRIB_V_ORDER_NV 0x86C4 #define GL_EVAL_FRACTIONAL_TESSELLATION_NV 0x86C5 #define GL_EVAL_VERTEX_ATTRIB0_NV 0x86C6 #define GL_EVAL_VERTEX_ATTRIB1_NV 0x86C7 #define GL_EVAL_VERTEX_ATTRIB2_NV 0x86C8 #define GL_EVAL_VERTEX_ATTRIB3_NV 0x86C9 #define GL_EVAL_VERTEX_ATTRIB4_NV 0x86CA #define GL_EVAL_VERTEX_ATTRIB5_NV 0x86CB #define GL_EVAL_VERTEX_ATTRIB6_NV 0x86CC #define GL_EVAL_VERTEX_ATTRIB7_NV 0x86CD #define GL_EVAL_VERTEX_ATTRIB8_NV 0x86CE #define GL_EVAL_VERTEX_ATTRIB9_NV 0x86CF #define GL_EVAL_VERTEX_ATTRIB10_NV 0x86D0 #define GL_EVAL_VERTEX_ATTRIB11_NV 0x86D1 #define GL_EVAL_VERTEX_ATTRIB12_NV 0x86D2 #define GL_EVAL_VERTEX_ATTRIB13_NV 0x86D3 #define GL_EVAL_VERTEX_ATTRIB14_NV 0x86D4 #define GL_EVAL_VERTEX_ATTRIB15_NV 0x86D5 #define GL_MAX_MAP_TESSELLATION_NV 0x86D6 #define GL_MAX_RATIONAL_EVAL_ORDER_NV 0x86D7 #endif #ifndef GL_NV_packed_depth_stencil #define GL_NV_packed_depth_stencil #define AGL_NV_packed_depth_stencil #define GL_DEPTH_STENCIL_NV 0x84F9 #define GL_UNSIGNED_INT_24_8_NV 0x84FA #endif #ifndef GL_NV_register_combiners2 #define GL_NV_register_combiners2 #define AGL_NV_register_combiners2 #define GL_PER_STAGE_CONSTANTS_NV 0x8535 #endif #ifndef GL_NV_texture_rectangle #define GL_NV_texture_rectangle #define AGL_NV_texture_rectangle #define GL_TEXTURE_RECTANGLE_NV 0x84F5 #define GL_TEXTURE_BINDING_RECTANGLE_NV 0x84F6 #define GL_PROXY_TEXTURE_RECTANGLE_NV 0x84F7 #define GL_MAX_RECTANGLE_TEXTURE_SIZE_NV 0x84F8 #endif #ifndef GL_NV_texture_shader #define GL_NV_texture_shader #define AGL_NV_texture_shader #define GL_OFFSET_TEXTURE_RECTANGLE_NV 0x864C #define GL_OFFSET_TEXTURE_RECTANGLE_SCALE_NV 0x864D #define GL_DOT_PRODUCT_TEXTURE_RECTANGLE_NV 0x864E #define GL_RGBA_UNSIGNED_DOT_PRODUCT_MAPPING_NV 0x86D9 #define GL_UNSIGNED_INT_S8_S8_8_8_NV 0x86DA #define GL_UNSIGNED_INT_8_8_S8_S8_REV_NV 0x86DB #define GL_DSDT_MAG_INTENSITY_NV 0x86DC #define GL_SHADER_CONSISTENT_NV 0x86DD #define GL_TEXTURE_SHADER_NV 0x86DE #define GL_SHADER_OPERATION_NV 0x86DF #define GL_CULL_MODES_NV 0x86E0 #define GL_OFFSET_TEXTURE_MATRIX_NV 0x86E1 #define GL_OFFSET_TEXTURE_SCALE_NV 0x86E2 #define GL_OFFSET_TEXTURE_BIAS_NV 0x86E3 #define GL_OFFSET_TEXTURE_2D_MATRIX_NV GL_OFFSET_TEXTURE_MATRIX_NV #define GL_OFFSET_TEXTURE_2D_SCALE_NV GL_OFFSET_TEXTURE_SCALE_NV #define GL_OFFSET_TEXTURE_2D_BIAS_NV GL_OFFSET_TEXTURE_BIAS_NV #define GL_PREVIOUS_TEXTURE_INPUT_NV 0x86E4 #define GL_CONST_EYE_NV 0x86E5 #define GL_PASS_THROUGH_NV 0x86E6 #define GL_CULL_FRAGMENT_NV 0x86E7 #define GL_OFFSET_TEXTURE_2D_NV 0x86E8 #define GL_DEPENDENT_AR_TEXTURE_2D_NV 0x86E9 #define GL_DEPENDENT_GB_TEXTURE_2D_NV 0x86EA #define GL_DOT_PRODUCT_NV 0x86EC #define GL_DOT_PRODUCT_DEPTH_REPLACE_NV 0x86ED #define GL_DOT_PRODUCT_TEXTURE_2D_NV 0x86EE #define GL_DOT_PRODUCT_TEXTURE_CUBE_MAP_NV 0x86F0 #define GL_DOT_PRODUCT_DIFFUSE_CUBE_MAP_NV 0x86F1 #define GL_DOT_PRODUCT_REFLECT_CUBE_MAP_NV 0x86F2 #define GL_DOT_PRODUCT_CONST_EYE_REFLECT_CUBE_MAP_NV 0x86F3 #define GL_HILO_NV 0x86F4 #define GL_DSDT_NV 0x86F5 #define GL_DSDT_MAG_NV 0x86F6 #define GL_DSDT_MAG_VIB_NV 0x86F7 #define GL_HILO16_NV 0x86F8 #define GL_SIGNED_HILO_NV 0x86F9 #define GL_SIGNED_HILO16_NV 0x86FA #define GL_SIGNED_RGBA_NV 0x86FB #define GL_SIGNED_RGBA8_NV 0x86FC #define GL_SIGNED_RGB_NV 0x86FE #define GL_SIGNED_RGB8_NV 0x86FF #define GL_SIGNED_LUMINANCE_NV 0x8701 #define GL_SIGNED_LUMINANCE8_NV 0x8702 #define GL_SIGNED_LUMINANCE_ALPHA_NV 0x8703 #define GL_SIGNED_LUMINANCE8_ALPHA8_NV 0x8704 #define GL_SIGNED_ALPHA_NV 0x8705 #define GL_SIGNED_ALPHA8_NV 0x8706 #define GL_SIGNED_INTENSITY_NV 0x8707 #define GL_SIGNED_INTENSITY8_NV 0x8708 #define GL_DSDT8_NV 0x8709 #define GL_DSDT8_MAG8_NV 0x870A #define GL_DSDT8_MAG8_INTENSITY8_NV 0x870B #define GL_SIGNED_RGB_UNSIGNED_ALPHA_NV 0x870C #define GL_SIGNED_RGB8_UNSIGNED_ALPHA8_NV 0x870D #define GL_HI_SCALE_NV 0x870E #define GL_LO_SCALE_NV 0x870F #define GL_DS_SCALE_NV 0x8710 #define GL_DT_SCALE_NV 0x8711 #define GL_MAGNITUDE_SCALE_NV 0x8712 #define GL_VIBRANCE_SCALE_NV 0x8713 #define GL_HI_BIAS_NV 0x8714 #define GL_LO_BIAS_NV 0x8715 #define GL_DS_BIAS_NV 0x8716 #define GL_DT_BIAS_NV 0x8717 #define GL_MAGNITUDE_BIAS_NV 0x8718 #define GL_VIBRANCE_BIAS_NV 0x8719 #define GL_TEXTURE_BORDER_VALUES_NV 0x871A #define GL_TEXTURE_HI_SIZE_NV 0x871B #define GL_TEXTURE_LO_SIZE_NV 0x871C #define GL_TEXTURE_DS_SIZE_NV 0x871D #define GL_TEXTURE_DT_SIZE_NV 0x871E #define GL_TEXTURE_MAG_SIZE_NV 0x871F #endif #ifndef GL_NV_texture_shader2 #define GL_NV_texture_shader2 #define AGL_NV_texture_shader2 #define GL_DOT_PRODUCT_TEXTURE_3D_NV 0x86EF #endif #ifndef GL_NV_vertex_array_range2 #define GL_NV_vertex_array_range2 #define AGL_NV_vertex_array_range2 #define GL_VERTEX_ARRAY_RANGE_WITHOUT_FLUSH_NV 0x8533 #endif #ifndef GL_NV_vertex_program #define GL_NV_vertex_program #define AGL_NV_vertex_program #define GL_VERTEX_PROGRAM_NV 0x8620 #define GL_VERTEX_STATE_PROGRAM_NV 0x8621 #define GL_ATTRIB_ARRAY_SIZE_NV 0x8623 #define GL_ATTRIB_ARRAY_STRIDE_NV 0x8624 #define GL_ATTRIB_ARRAY_TYPE_NV 0x8625 #define GL_CURRENT_ATTRIB_NV 0x8626 #define GL_PROGRAM_LENGTH_NV 0x8627 #define GL_PROGRAM_STRING_NV 0x8628 #define GL_MODELVIEW_PROJECTION_NV 0x8629 #define GL_IDENTITY_NV 0x862A #define GL_INVERSE_NV 0x862B #define GL_TRANSPOSE_NV 0x862C #define GL_INVERSE_TRANSPOSE_NV 0x862D #define GL_MAX_TRACK_MATRIX_STACK_DEPTH_NV 0x862E #define GL_MAX_TRACK_MATRICES_NV 0x862F #define GL_MATRIX0_NV 0x8630 #define GL_MATRIX1_NV 0x8631 #define GL_MATRIX2_NV 0x8632 #define GL_MATRIX3_NV 0x8633 #define GL_MATRIX4_NV 0x8634 #define GL_MATRIX5_NV 0x8635 #define GL_MATRIX6_NV 0x8636 #define GL_MATRIX7_NV 0x8637 #define GL_CURRENT_MATRIX_STACK_DEPTH_NV 0x8640 #define GL_CURRENT_MATRIX_NV 0x8641 #define GL_VERTEX_PROGRAM_POINT_SIZE_NV 0x8642 #define GL_VERTEX_PROGRAM_TWO_SIDE_NV 0x8643 #define GL_PROGRAM_PARAMETER_NV 0x8644 #define GL_ATTRIB_ARRAY_POINTER_NV 0x8645 #define GL_PROGRAM_TARGET_NV 0x8646 #define GL_PROGRAM_RESIDENT_NV 0x8647 #define GL_TRACK_MATRIX_NV 0x8648 #define GL_TRACK_MATRIX_TRANSFORM_NV 0x8649 #define GL_VERTEX_PROGRAM_BINDING_NV 0x864A #define GL_PROGRAM_ERROR_POSITION_NV 0x864B #define GL_VERTEX_ATTRIB_ARRAY0_NV 0x8650 #define GL_VERTEX_ATTRIB_ARRAY1_NV 0x8651 #define GL_VERTEX_ATTRIB_ARRAY2_NV 0x8652 #define GL_VERTEX_ATTRIB_ARRAY3_NV 0x8653 #define GL_VERTEX_ATTRIB_ARRAY4_NV 0x8654 #define GL_VERTEX_ATTRIB_ARRAY5_NV 0x8655 #define GL_VERTEX_ATTRIB_ARRAY6_NV 0x8656 #define GL_VERTEX_ATTRIB_ARRAY7_NV 0x8657 #define GL_VERTEX_ATTRIB_ARRAY8_NV 0x8658 #define GL_VERTEX_ATTRIB_ARRAY9_NV 0x8659 #define GL_VERTEX_ATTRIB_ARRAY10_NV 0x865A #define GL_VERTEX_ATTRIB_ARRAY11_NV 0x865B #define GL_VERTEX_ATTRIB_ARRAY12_NV 0x865C #define GL_VERTEX_ATTRIB_ARRAY13_NV 0x865D #define GL_VERTEX_ATTRIB_ARRAY14_NV 0x865E #define GL_VERTEX_ATTRIB_ARRAY15_NV 0x865F #define GL_MAP1_VERTEX_ATTRIB0_4_NV 0x8660 #define GL_MAP1_VERTEX_ATTRIB1_4_NV 0x8661 #define GL_MAP1_VERTEX_ATTRIB2_4_NV 0x8662 #define GL_MAP1_VERTEX_ATTRIB3_4_NV 0x8663 #define GL_MAP1_VERTEX_ATTRIB4_4_NV 0x8664 #define GL_MAP1_VERTEX_ATTRIB5_4_NV 0x8665 #define GL_MAP1_VERTEX_ATTRIB6_4_NV 0x8666 #define GL_MAP1_VERTEX_ATTRIB7_4_NV 0x8667 #define GL_MAP1_VERTEX_ATTRIB8_4_NV 0x8668 #define GL_MAP1_VERTEX_ATTRIB9_4_NV 0x8669 #define GL_MAP1_VERTEX_ATTRIB10_4_NV 0x866A #define GL_MAP1_VERTEX_ATTRIB11_4_NV 0x866B #define GL_MAP1_VERTEX_ATTRIB12_4_NV 0x866C #define GL_MAP1_VERTEX_ATTRIB13_4_NV 0x866D #define GL_MAP1_VERTEX_ATTRIB14_4_NV 0x866E #define GL_MAP1_VERTEX_ATTRIB15_4_NV 0x866F #define GL_MAP2_VERTEX_ATTRIB0_4_NV 0x8670 #define GL_MAP2_VERTEX_ATTRIB1_4_NV 0x8671 #define GL_MAP2_VERTEX_ATTRIB2_4_NV 0x8672 #define GL_MAP2_VERTEX_ATTRIB3_4_NV 0x8673 #define GL_MAP2_VERTEX_ATTRIB4_4_NV 0x8674 #define GL_MAP2_VERTEX_ATTRIB5_4_NV 0x8675 #define GL_MAP2_VERTEX_ATTRIB6_4_NV 0x8676 #define GL_MAP2_VERTEX_ATTRIB7_4_NV 0x8677 #define GL_MAP2_VERTEX_ATTRIB8_4_NV 0x8678 #define GL_MAP2_VERTEX_ATTRIB9_4_NV 0x8679 #define GL_MAP2_VERTEX_ATTRIB10_4_NV 0x867A #define GL_MAP2_VERTEX_ATTRIB11_4_NV 0x867B #define GL_MAP2_VERTEX_ATTRIB12_4_NV 0x867C #define GL_MAP2_VERTEX_ATTRIB13_4_NV 0x867D #define GL_MAP2_VERTEX_ATTRIB14_4_NV 0x867E #define GL_MAP2_VERTEX_ATTRIB15_4_NV 0x867F #endif #ifndef GL_SGIX_texture_coordinate_clamp #define GL_SGIX_texture_coordinate_clamp #define AGL_SGIX_texture_coordinate_clamp #define GL_TEXTURE_MAX_CLAMP_S_SGIX 0x8369 #define GL_TEXTURE_MAX_CLAMP_T_SGIX 0x836A #define GL_TEXTURE_MAX_CLAMP_R_SGIX 0x836B #endif #ifndef GL_SGIX_scalebias_hint #define GL_SGIX_scalebias_hint #define AGL_SGIX_scalebias_hint #define GL_SCALEBIAS_HINT_SGIX 0x8322 #endif #ifndef GL_OML_interlace #define GL_OML_interlace #define AGL_OML_interlace #define GL_INTERLACE_OML 0x8980 #define GL_INTERLACE_READ_OML 0x8981 #endif #ifndef GL_OML_subsample #define GL_OML_subsample #define AGL_OML_subsample #define GL_FORMAT_SUBSAMPLE_24_24_OML 0x8982 #define GL_FORMAT_SUBSAMPLE_244_244_OML 0x8983 #endif #ifndef GL_OML_resample #define GL_OML_resample #define AGL_OML_resample #define GL_PACK_RESAMPLE_OML 0x8984 #define GL_UNPACK_RESAMPLE_OML 0x8985 #define GL_RESAMPLE_REPLICATE_OML 0x8986 #define GL_RESAMPLE_ZERO_FILL_OML 0x8987 #define GL_RESAMPLE_AVERAGE_OML 0x8988 #define GL_RESAMPLE_DECIMATE_OML 0x8989 #endif #ifndef GL_NV_copy_depth_to_color #define GL_NV_copy_depth_to_color #define AGL_NV_copy_depth_to_color #define GL_DEPTH_STENCIL_TO_RGBA_NV 0x886E #define GL_DEPTH_STENCIL_TO_BGRA_NV 0x886F #endif #ifndef GL_ATI_envmap_bumpmap #define GL_ATI_envmap_bumpmap #define AGL_ATI_envmap_bumpmap #define GL_BUMP_ROT_MATRIX_ATI 0x8775 #define GL_BUMP_ROT_MATRIX_SIZE_ATI 0x8776 #define GL_BUMP_NUM_TEX_UNITS_ATI 0x8777 #define GL_BUMP_TEX_UNITS_ATI 0x8778 #define GL_DUDV_ATI 0x8779 #define GL_DU8DV8_ATI 0x877A #define GL_BUMP_ENVMAP_ATI 0x877B #define GL_BUMP_TARGET_ATI 0x877C #endif #ifndef GL_ATI_fragment_shader #define GL_ATI_fragment_shader #define AGL_ATI_fragment_shader #define GL_FRAGMENT_SHADER_ATI 0x8920 #define GL_REG_0_ATI 0x8921 #define GL_REG_1_ATI 0x8922 #define GL_REG_2_ATI 0x8923 #define GL_REG_3_ATI 0x8924 #define GL_REG_4_ATI 0x8925 #define GL_REG_5_ATI 0x8926 #define GL_REG_6_ATI 0x8927 #define GL_REG_7_ATI 0x8928 #define GL_REG_8_ATI 0x8929 #define GL_REG_9_ATI 0x892A #define GL_REG_10_ATI 0x892B #define GL_REG_11_ATI 0x892C #define GL_REG_12_ATI 0x892D #define GL_REG_13_ATI 0x892E #define GL_REG_14_ATI 0x892F #define GL_REG_15_ATI 0x8930 #define GL_REG_16_ATI 0x8931 #define GL_REG_17_ATI 0x8932 #define GL_REG_18_ATI 0x8933 #define GL_REG_19_ATI 0x8934 #define GL_REG_20_ATI 0x8935 #define GL_REG_21_ATI 0x8936 #define GL_REG_22_ATI 0x8937 #define GL_REG_23_ATI 0x8938 #define GL_REG_24_ATI 0x8939 #define GL_REG_25_ATI 0x893A #define GL_REG_26_ATI 0x893B #define GL_REG_27_ATI 0x893C #define GL_REG_28_ATI 0x893D #define GL_REG_29_ATI 0x893E #define GL_REG_30_ATI 0x893F #define GL_REG_31_ATI 0x8940 #define GL_CON_0_ATI 0x8941 #define GL_CON_1_ATI 0x8942 #define GL_CON_2_ATI 0x8943 #define GL_CON_3_ATI 0x8944 #define GL_CON_4_ATI 0x8945 #define GL_CON_5_ATI 0x8946 #define GL_CON_6_ATI 0x8947 #define GL_CON_7_ATI 0x8948 #define GL_CON_8_ATI 0x8949 #define GL_CON_9_ATI 0x894A #define GL_CON_10_ATI 0x894B #define GL_CON_11_ATI 0x894C #define GL_CON_12_ATI 0x894D #define GL_CON_13_ATI 0x894E #define GL_CON_14_ATI 0x894F #define GL_CON_15_ATI 0x8950 #define GL_CON_16_ATI 0x8951 #define GL_CON_17_ATI 0x8952 #define GL_CON_18_ATI 0x8953 #define GL_CON_19_ATI 0x8954 #define GL_CON_20_ATI 0x8955 #define GL_CON_21_ATI 0x8956 #define GL_CON_22_ATI 0x8957 #define GL_CON_23_ATI 0x8958 #define GL_CON_24_ATI 0x8959 #define GL_CON_25_ATI 0x895A #define GL_CON_26_ATI 0x895B #define GL_CON_27_ATI 0x895C #define GL_CON_28_ATI 0x895D #define GL_CON_29_ATI 0x895E #define GL_CON_30_ATI 0x895F #define GL_CON_31_ATI 0x8960 #define GL_MOV_ATI 0x8961 #define GL_ADD_ATI 0x8963 #define GL_MUL_ATI 0x8964 #define GL_SUB_ATI 0x8965 #define GL_DOT3_ATI 0x8966 #define GL_DOT4_ATI 0x8967 #define GL_MAD_ATI 0x8968 #define GL_LERP_ATI 0x8969 #define GL_CND_ATI 0x896A #define GL_CND0_ATI 0x896B #define GL_DOT2_ADD_ATI 0x896C #define GL_SECONDARY_INTERPOLATOR_ATI 0x896D #define GL_NUM_FRAGMENT_REGISTERS_ATI 0x896E #define GL_NUM_FRAGMENT_CONSTANTS_ATI 0x896F #define GL_NUM_PASSES_ATI 0x8970 #define GL_NUM_INSTRUCTIONS_PER_PASS_ATI 0x8971 #define GL_NUM_INSTRUCTIONS_TOTAL_ATI 0x8972 #define GL_NUM_INPUT_INTERPOLATOR_COMPONENTS_ATI 0x8973 #define GL_NUM_LOOPBACK_COMPONENTS_ATI 0x8974 #define GL_COLOR_ALPHA_PAIRING_ATI 0x8975 #define GL_SWIZZLE_STR_ATI 0x8976 #define GL_SWIZZLE_STQ_ATI 0x8977 #define GL_SWIZZLE_STR_DR_ATI 0x8978 #define GL_SWIZZLE_STQ_DQ_ATI 0x8979 #define GL_SWIZZLE_STRQ_ATI 0x897A #define GL_SWIZZLE_STRQ_DQ_ATI 0x897B #define GL_RED_BIT_ATI 0x00000001 #define GL_GREEN_BIT_ATI 0x00000002 #define GL_BLUE_BIT_ATI 0x00000004 #define GL_2X_BIT_ATI 0x00000001 #define GL_4X_BIT_ATI 0x00000002 #define GL_8X_BIT_ATI 0x00000004 #define GL_HALF_BIT_ATI 0x00000008 #define GL_QUARTER_BIT_ATI 0x00000010 #define GL_EIGHTH_BIT_ATI 0x00000020 #define GL_SATURATE_BIT_ATI 0x00000040 #define GL_COMP_BIT_ATI 0x00000002 #define GL_NEGATE_BIT_ATI 0x00000004 #define GL_BIAS_BIT_ATI 0x00000008 #endif #ifndef GL_ATI_pn_triangles #define GL_ATI_pn_triangles #define AGL_ATI_pn_triangles #define GL_PN_TRIANGLES_ATI 0x87F0 #define GL_MAX_PN_TRIANGLES_TESSELATION_LEVEL_ATI 0x87F1 #define GL_PN_TRIANGLES_POINT_MODE_ATI 0x87F2 #define GL_PN_TRIANGLES_NORMAL_MODE_ATI 0x87F3 #define GL_PN_TRIANGLES_TESSELATION_LEVEL_ATI 0x87F4 #define GL_PN_TRIANGLES_POINT_MODE_LINEAR_ATI 0x87F5 #define GL_PN_TRIANGLES_POINT_MODE_CUBIC_ATI 0x87F6 #define GL_PN_TRIANGLES_NORMAL_MODE_LINEAR_ATI 0x87F7 #define GL_PN_TRIANGLES_NORMAL_MODE_QUADRATIC_ATI 0x87F8 #endif #ifndef GL_ATI_vertex_array_object #define GL_ATI_vertex_array_object #define AGL_ATI_vertex_array_object #define GL_STATIC_ATI 0x8760 #define GL_DYNAMIC_ATI 0x8761 #define GL_PRESERVE_ATI 0x8762 #define GL_DISCARD_ATI 0x8763 #define GL_OBJECT_BUFFER_SIZE_ATI 0x8764 #define GL_OBJECT_BUFFER_USAGE_ATI 0x8765 #define GL_ARRAY_OBJECT_BUFFER_ATI 0x8766 #define GL_ARRAY_OBJECT_OFFSET_ATI 0x8767 #endif #ifndef GL_EXT_vertex_shader #define GL_EXT_vertex_shader #define AGL_EXT_vertex_shader #define GL_VERTEX_SHADER_EXT 0x8780 #define GL_VERTEX_SHADER_BINDING_EXT 0x8781 #define GL_OP_INDEX_EXT 0x8782 #define GL_OP_NEGATE_EXT 0x8783 #define GL_OP_DOT3_EXT 0x8784 #define GL_OP_DOT4_EXT 0x8785 #define GL_OP_MUL_EXT 0x8786 #define GL_OP_ADD_EXT 0x8787 #define GL_OP_MADD_EXT 0x8788 #define GL_OP_FRAC_EXT 0x8789 #define GL_OP_MAX_EXT 0x878A #define GL_OP_MIN_EXT 0x878B #define GL_OP_SET_GE_EXT 0x878C #define GL_OP_SET_LT_EXT 0x878D #define GL_OP_CLAMP_EXT 0x878E #define GL_OP_FLOOR_EXT 0x878F #define GL_OP_ROUND_EXT 0x8790 #define GL_OP_EXP_BASE_2_EXT 0x8791 #define GL_OP_LOG_BASE_2_EXT 0x8792 #define GL_OP_POWER_EXT 0x8793 #define GL_OP_RECIP_EXT 0x8794 #define GL_OP_RECIP_SQRT_EXT 0x8795 #define GL_OP_SUB_EXT 0x8796 #define GL_OP_CROSS_PRODUCT_EXT 0x8797 #define GL_OP_MULTIPLY_MATRIX_EXT 0x8798 #define GL_OP_MOV_EXT 0x8799 #define GL_OUTPUT_VERTEX_EXT 0x879A #define GL_OUTPUT_COLOR0_EXT 0x879B #define GL_OUTPUT_COLOR1_EXT 0x879C #define GL_OUTPUT_TEXTURE_COORD0_EXT 0x879D #define GL_OUTPUT_TEXTURE_COORD1_EXT 0x879E #define GL_OUTPUT_TEXTURE_COORD2_EXT 0x879F #define GL_OUTPUT_TEXTURE_COORD3_EXT 0x87A0 #define GL_OUTPUT_TEXTURE_COORD4_EXT 0x87A1 #define GL_OUTPUT_TEXTURE_COORD5_EXT 0x87A2 #define GL_OUTPUT_TEXTURE_COORD6_EXT 0x87A3 #define GL_OUTPUT_TEXTURE_COORD7_EXT 0x87A4 #define GL_OUTPUT_TEXTURE_COORD8_EXT 0x87A5 #define GL_OUTPUT_TEXTURE_COORD9_EXT 0x87A6 #define GL_OUTPUT_TEXTURE_COORD10_EXT 0x87A7 #define GL_OUTPUT_TEXTURE_COORD11_EXT 0x87A8 #define GL_OUTPUT_TEXTURE_COORD12_EXT 0x87A9 #define GL_OUTPUT_TEXTURE_COORD13_EXT 0x87AA #define GL_OUTPUT_TEXTURE_COORD14_EXT 0x87AB #define GL_OUTPUT_TEXTURE_COORD15_EXT 0x87AC #define GL_OUTPUT_TEXTURE_COORD16_EXT 0x87AD #define GL_OUTPUT_TEXTURE_COORD17_EXT 0x87AE #define GL_OUTPUT_TEXTURE_COORD18_EXT 0x87AF #define GL_OUTPUT_TEXTURE_COORD19_EXT 0x87B0 #define GL_OUTPUT_TEXTURE_COORD20_EXT 0x87B1 #define GL_OUTPUT_TEXTURE_COORD21_EXT 0x87B2 #define GL_OUTPUT_TEXTURE_COORD22_EXT 0x87B3 #define GL_OUTPUT_TEXTURE_COORD23_EXT 0x87B4 #define GL_OUTPUT_TEXTURE_COORD24_EXT 0x87B5 #define GL_OUTPUT_TEXTURE_COORD25_EXT 0x87B6 #define GL_OUTPUT_TEXTURE_COORD26_EXT 0x87B7 #define GL_OUTPUT_TEXTURE_COORD27_EXT 0x87B8 #define GL_OUTPUT_TEXTURE_COORD28_EXT 0x87B9 #define GL_OUTPUT_TEXTURE_COORD29_EXT 0x87BA #define GL_OUTPUT_TEXTURE_COORD30_EXT 0x87BB #define GL_OUTPUT_TEXTURE_COORD31_EXT 0x87BC #define GL_OUTPUT_FOG_EXT 0x87BD #define GL_SCALAR_EXT 0x87BE #define GL_VECTOR_EXT 0x87BF #define GL_MATRIX_EXT 0x87C0 #define GL_VARIANT_EXT 0x87C1 #define GL_INVARIANT_EXT 0x87C2 #define GL_LOCAL_CONSTANT_EXT 0x87C3 #define GL_LOCAL_EXT 0x87C4 #define GL_MAX_VERTEX_SHADER_INSTRUCTIONS_EXT 0x87C5 #define GL_MAX_VERTEX_SHADER_VARIANTS_EXT 0x87C6 #define GL_MAX_VERTEX_SHADER_INVARIANTS_EXT 0x87C7 #define GL_MAX_VERTEX_SHADER_LOCAL_CONSTANTS_EXT 0x87C8 #define GL_MAX_VERTEX_SHADER_LOCALS_EXT 0x87C9 #define GL_MAX_OPTIMIZED_VERTEX_SHADER_INSTRUCTIONS_EXT 0x87CA #define GL_MAX_OPTIMIZED_VERTEX_SHADER_VARIANTS_EXT 0x87CB #define GL_MAX_OPTIMIZED_VERTEX_SHADER_LOCAL_CONSTANTS_EXT 0x87CC #define GL_MAX_OPTIMIZED_VERTEX_SHADER_INVARIANTS_EXT 0x87CD #define GL_MAX_OPTIMIZED_VERTEX_SHADER_LOCALS_EXT 0x87CE #define GL_VERTEX_SHADER_INSTRUCTIONS_EXT 0x87CF #define GL_VERTEX_SHADER_VARIANTS_EXT 0x87D0 #define GL_VERTEX_SHADER_INVARIANTS_EXT 0x87D1 #define GL_VERTEX_SHADER_LOCAL_CONSTANTS_EXT 0x87D2 #define GL_VERTEX_SHADER_LOCALS_EXT 0x87D3 #define GL_VERTEX_SHADER_OPTIMIZED_EXT 0x87D4 #define GL_X_EXT 0x87D5 #define GL_Y_EXT 0x87D6 #define GL_Z_EXT 0x87D7 #define GL_W_EXT 0x87D8 #define GL_NEGATIVE_X_EXT 0x87D9 #define GL_NEGATIVE_Y_EXT 0x87DA #define GL_NEGATIVE_Z_EXT 0x87DB #define GL_NEGATIVE_W_EXT 0x87DC #define GL_ZERO_EXT 0x87DD #define GL_ONE_EXT 0x87DE #define GL_NEGATIVE_ONE_EXT 0x87DF #define GL_NORMALIZED_RANGE_EXT 0x87E0 #define GL_FULL_RANGE_EXT 0x87E1 #define GL_CURRENT_VERTEX_EXT 0x87E2 #define GL_MVP_MATRIX_EXT 0x87E3 #define GL_VARIANT_VALUE_EXT 0x87E4 #define GL_VARIANT_DATATYPE_EXT 0x87E5 #define GL_VARIANT_ARRAY_STRIDE_EXT 0x87E6 #define GL_VARIANT_ARRAY_TYPE_EXT 0x87E7 #define GL_VARIANT_ARRAY_EXT 0x87E8 #define GL_VARIANT_ARRAY_POINTER_EXT 0x87E9 #define GL_INVARIANT_VALUE_EXT 0x87EA #define GL_INVARIANT_DATATYPE_EXT 0x87EB #define GL_LOCAL_CONSTANT_VALUE_EXT 0x87EC #define GL_LOCAL_CONSTANT_DATATYPE_EXT 0x87ED #endif #ifndef GL_ATI_vertex_streams #define GL_ATI_vertex_streams #define AGL_ATI_vertex_streams #define GL_MAX_VERTEX_STREAMS_ATI 0x876B #define GL_VERTEX_STREAM0_ATI 0x876C #define GL_VERTEX_STREAM1_ATI 0x876D #define GL_VERTEX_STREAM2_ATI 0x876E #define GL_VERTEX_STREAM3_ATI 0x876F #define GL_VERTEX_STREAM4_ATI 0x8770 #define GL_VERTEX_STREAM5_ATI 0x8771 #define GL_VERTEX_STREAM6_ATI 0x8772 #define GL_VERTEX_STREAM7_ATI 0x8773 #define GL_VERTEX_SOURCE_ATI 0x8774 #endif #ifndef GL_ATI_element_array #define GL_ATI_element_array #define AGL_ATI_element_array #define GL_ELEMENT_ARRAY_ATI 0x8768 #define GL_ELEMENT_ARRAY_TYPE_ATI 0x8769 #define GL_ELEMENT_ARRAY_POINTER_ATI 0x876A #endif #ifndef GL_SUN_mesh_array #define GL_SUN_mesh_array #define AGL_SUN_mesh_array #define GL_QUAD_MESH_SUN 0x8614 #define GL_TRIANGLE_MESH_SUN 0x8615 #endif #ifndef GL_SUN_slice_accum #define GL_SUN_slice_accum #define AGL_SUN_slice_accum #define GL_SLICE_ACCUM_SUN 0x85CC #endif #ifndef GL_NV_multisample_filter_hint #define GL_NV_multisample_filter_hint #define AGL_NV_multisample_filter_hint #define GL_MULTISAMPLE_FILTER_HINT_NV 0x8534 #endif #ifndef GL_NV_depth_clamp #define GL_NV_depth_clamp #define AGL_NV_depth_clamp #define GL_DEPTH_CLAMP_NV 0x864F #endif #ifndef GL_NV_occlusion_query #define GL_NV_occlusion_query #define AGL_NV_occlusion_query #define GL_PIXEL_COUNTER_BITS_NV 0x8864 #define GL_CURRENT_OCCLUSION_QUERY_ID_NV 0x8865 #define GL_PIXEL_COUNT_NV 0x8866 #define GL_PIXEL_COUNT_AVAILABLE_NV 0x8867 #endif #ifndef GL_NV_point_sprite #define GL_NV_point_sprite #define AGL_NV_point_sprite #define GL_POINT_SPRITE_NV 0x8861 #define GL_COORD_REPLACE_NV 0x8862 #define GL_POINT_SPRITE_R_MODE_NV 0x8863 #endif #ifndef GL_NV_texture_shader3 #define GL_NV_texture_shader3 #define AGL_NV_texture_shader3 #define GL_OFFSET_PROJECTIVE_TEXTURE_2D_NV 0x8850 #define GL_OFFSET_PROJECTIVE_TEXTURE_2D_SCALE_NV 0x8851 #define GL_OFFSET_PROJECTIVE_TEXTURE_RECTANGLE_NV 0x8852 #define GL_OFFSET_PROJECTIVE_TEXTURE_RECTANGLE_SCALE_NV 0x8853 #define GL_OFFSET_HILO_TEXTURE_2D_NV 0x8854 #define GL_OFFSET_HILO_TEXTURE_RECTANGLE_NV 0x8855 #define GL_OFFSET_HILO_PROJECTIVE_TEXTURE_2D_NV 0x8856 #define GL_OFFSET_HILO_PROJECTIVE_TEXTURE_RECTANGLE_NV 0x8857 #define GL_DEPENDENT_HILO_TEXTURE_2D_NV 0x8858 #define GL_DEPENDENT_RGB_TEXTURE_3D_NV 0x8859 #define GL_DEPENDENT_RGB_TEXTURE_CUBE_MAP_NV 0x885A #define GL_DOT_PRODUCT_PASS_THROUGH_NV 0x885B #define GL_DOT_PRODUCT_TEXTURE_1D_NV 0x885C #define GL_DOT_PRODUCT_AFFINE_DEPTH_REPLACE_NV 0x885D #define GL_HILO8_NV 0x885E #define GL_SIGNED_HILO8_NV 0x885F #define GL_FORCE_BLUE_TO_ONE_NV 0x8860 #endif #ifndef GL_EXT_stencil_two_side #define GL_EXT_stencil_two_side #define AGL_EXT_stencil_two_side #define GL_STENCIL_TEST_TWO_SIDE_EXT 0x8910 #define GL_ACTIVE_STENCIL_FACE_EXT 0x8911 #endif #ifndef GL_ATI_text_fragment_shader #define GL_ATI_text_fragment_shader #define AGL_ATI_text_fragment_shader #define GL_TEXT_FRAGMENT_SHADER_ATI 0x8200 #endif #ifndef GL_APPLE_client_storage #define GL_APPLE_client_storage #define AGL_APPLE_client_storage #define GL_UNPACK_CLIENT_STORAGE_APPLE 0x85B2 #endif #ifndef GL_APPLE_element_array #define GL_APPLE_element_array #define AGL_APPLE_element_array #define GL_ELEMENT_ARRAY_APPLE 0x8768 #define GL_ELEMENT_ARRAY_TYPE_APPLE 0x8769 #define GL_ELEMENT_ARRAY_POINTER_APPLE 0x876A #endif #ifndef GL_APPLE_fence #define GL_APPLE_fence #define AGL_APPLE_fence #define GL_DRAW_PIXELS_APPLE 0x8A0A #define GL_FENCE_APPLE 0x8A0B #endif #ifndef GL_APPLE_vertex_array_object #define GL_APPLE_vertex_array_object #define AGL_APPLE_vertex_array_object #define GL_VERTEX_ARRAY_BINDING_APPLE 0x85B5 #endif #ifndef GL_APPLE_vertex_array_range #define GL_APPLE_vertex_array_range #define AGL_APPLE_vertex_array_range #define GL_VERTEX_ARRAY_RANGE_APPLE 0x851D #define GL_VERTEX_ARRAY_RANGE_LENGTH_APPLE 0x851E #define GL_VERTEX_ARRAY_STORAGE_HINT_APPLE 0x851F #define GL_VERTEX_ARRAY_RANGE_POINTER_APPLE 0x8521 #define GL_STORAGE_CACHED_APPLE 0x85BE #define GL_STORAGE_SHARED_APPLE 0x85BF #endif #ifndef GL_APPLE_ycbcr_422 #define GL_APPLE_ycbcr_422 #define AGL_APPLE_ycbcr_422 #define GL_YCBCR_422_APPLE 0x85B9 #define GL_UNSIGNED_SHORT_8_8_APPLE 0x85BA #define GL_UNSIGNED_SHORT_8_8_REV_APPLE 0x85BB #endif #ifndef GL_S3_s3tc #define GL_S3_s3tc #define AGL_S3_s3tc #define GL_RGB_S3TC 0x83A0 #define GL_RGB4_S3TC 0x83A1 #define GL_RGBA_S3TC 0x83A2 #define GL_RGBA4_S3TC 0x83A3 #endif #ifndef GL_ATI_draw_buffers #define GL_ATI_draw_buffers #define AGL_ATI_draw_buffers #define GL_MAX_DRAW_BUFFERS_ATI 0x8824 #define GL_DRAW_BUFFER0_ATI 0x8825 #define GL_DRAW_BUFFER1_ATI 0x8826 #define GL_DRAW_BUFFER2_ATI 0x8827 #define GL_DRAW_BUFFER3_ATI 0x8828 #define GL_DRAW_BUFFER4_ATI 0x8829 #define GL_DRAW_BUFFER5_ATI 0x882A #define GL_DRAW_BUFFER6_ATI 0x882B #define GL_DRAW_BUFFER7_ATI 0x882C #define GL_DRAW_BUFFER8_ATI 0x882D #define GL_DRAW_BUFFER9_ATI 0x882E #define GL_DRAW_BUFFER10_ATI 0x882F #define GL_DRAW_BUFFER11_ATI 0x8830 #define GL_DRAW_BUFFER12_ATI 0x8831 #define GL_DRAW_BUFFER13_ATI 0x8832 #define GL_DRAW_BUFFER14_ATI 0x8833 #define GL_DRAW_BUFFER15_ATI 0x8834 #endif #ifndef GL_ATI_texture_env_combine3 #define GL_ATI_texture_env_combine3 #define AGL_ATI_texture_env_combine3 #define GL_MODULATE_ADD_ATI 0x8744 #define GL_MODULATE_SIGNED_ADD_ATI 0x8745 #define GL_MODULATE_SUBTRACT_ATI 0x8746 #endif #ifndef GL_ATI_texture_float #define GL_ATI_texture_float #define AGL_ATI_texture_float #define GL_RGBA_FLOAT32_ATI 0x8814 #define GL_RGB_FLOAT32_ATI 0x8815 #define GL_ALPHA_FLOAT32_ATI 0x8816 #define GL_INTENSITY_FLOAT32_ATI 0x8817 #define GL_LUMINANCE_FLOAT32_ATI 0x8818 #define GL_LUMINANCE_ALPHA_FLOAT32_ATI 0x8819 #define GL_RGBA_FLOAT16_ATI 0x881A #define GL_RGB_FLOAT16_ATI 0x881B #define GL_ALPHA_FLOAT16_ATI 0x881C #define GL_INTENSITY_FLOAT16_ATI 0x881D #define GL_LUMINANCE_FLOAT16_ATI 0x881E #define GL_LUMINANCE_ALPHA_FLOAT16_ATI 0x881F #endif #ifndef GL_NV_float_buffer #define GL_NV_float_buffer #define AGL_NV_float_buffer #define GL_FLOAT_R_NV 0x8880 #define GL_FLOAT_RG_NV 0x8881 #define GL_FLOAT_RGB_NV 0x8882 #define GL_FLOAT_RGBA_NV 0x8883 #define GL_FLOAT_R16_NV 0x8884 #define GL_FLOAT_R32_NV 0x8885 #define GL_FLOAT_RG16_NV 0x8886 #define GL_FLOAT_RG32_NV 0x8887 #define GL_FLOAT_RGB16_NV 0x8888 #define GL_FLOAT_RGB32_NV 0x8889 #define GL_FLOAT_RGBA16_NV 0x888A #define GL_FLOAT_RGBA32_NV 0x888B #define GL_TEXTURE_FLOAT_COMPONENTS_NV 0x888C #define GL_FLOAT_CLEAR_COLOR_VALUE_NV 0x888D #define GL_FLOAT_RGBA_MODE_NV 0x888E #endif #ifndef GL_NV_fragment_program #define GL_NV_fragment_program #define AGL_NV_fragment_program #define GL_MAX_FRAGMENT_PROGRAM_LOCAL_PARAMETERS_NV 0x8868 #define GL_FRAGMENT_PROGRAM_NV 0x8870 #define GL_MAX_TEXTURE_COORDS_NV 0x8871 #define GL_MAX_TEXTURE_IMAGE_UNITS_NV 0x8872 #define GL_FRAGMENT_PROGRAM_BINDING_NV 0x8873 #define GL_PROGRAM_ERROR_STRING_NV 0x8874 #endif #ifndef GL_NV_half_float #define GL_NV_half_float #define AGL_NV_half_float typedef short GLhalfNV; #define GL_HALF_FLOAT_NV 0x140B #endif #ifndef GL_NV_pixel_data_range #define GL_NV_pixel_data_range #define AGL_NV_pixel_data_range #define GL_WRITE_PIXEL_DATA_RANGE_NV 0x8878 #define GL_READ_PIXEL_DATA_RANGE_NV 0x8879 #define GL_WRITE_PIXEL_DATA_RANGE_LENGTH_NV 0x887A #define GL_READ_PIXEL_DATA_RANGE_LENGTH_NV 0x887B #define GL_WRITE_PIXEL_DATA_RANGE_POINTER_NV 0x887C #define GL_READ_PIXEL_DATA_RANGE_POINTER_NV 0x887D #endif #ifndef GL_NV_primitive_restart #define GL_NV_primitive_restart #define AGL_NV_primitive_restart #define GL_PRIMITIVE_RESTART_NV 0x8558 #define GL_PRIMITIVE_RESTART_INDEX_NV 0x8559 #endif #ifndef GL_NV_texture_expand_normal #define GL_NV_texture_expand_normal #define AGL_NV_texture_expand_normal #define GL_TEXTURE_UNSIGNED_REMAP_MODE_NV 0x888F #endif #ifndef GL_ATI_map_object_buffer #define GL_ATI_map_object_buffer #define AGL_ATI_map_object_buffer #endif #ifndef GL_ATI_separate_stencil #define GL_ATI_separate_stencil #define GL_STENCIL_BACK_FUNC_ATI 0x8800 #define GL_STENCIL_BACK_FAIL_ATI 0x8801 #define GL_STENCIL_BACK_PASS_DEPTH_FAIL_ATI 0x8802 #define GL_STENCIL_BACK_PASS_DEPTH_PASS_ATI 0x8803 #endif #ifndef GL_ATI_vertex_attrib_array_object #define GL_ATI_vertex_attrib_array_object #define AGL_ATI_vertex_attrib_array_object #endif #ifndef GL_OES_byte_coordinates #define GL_OES_byte_coordinates #define AGL_OES_byte_coordinates /* GL_BYTE */ #endif #ifndef GL_OES_fixed_point #define GL_OES_fixed_point #define AGL_OES_fixed_point typedef int GLfixed; typedef int GLclampx; #define GL_FIXED_OES 0x140C #endif #ifndef GL_OES_single_precision #define GL_OES_single_precision #define AGL_OES_single_precision #endif #ifndef GL_OES_compressed_paletted_texture #define GL_OES_compressed_paletted_texture #define AGL_OES_compressed_paletted_texture #define GL_PALETTE4_RGB8_OES 0x8B90 #define GL_PALETTE4_RGBA8_OES 0x8B91 #define GL_PALETTE4_R5_G6_B5_OES 0x8B92 #define GL_PALETTE4_RGBA4_OES 0x8B93 #define GL_PALETTE4_RGB5_A1_OES 0x8B94 #define GL_PALETTE8_RGB8_OES 0x8B95 #define GL_PALETTE8_RGBA8_OES 0x8B96 #define GL_PALETTE8_R5_G6_B5_OES 0x8B97 #define GL_PALETTE8_RGBA4_OES 0x8B98 #define GL_PALETTE8_RGB5_A1_OES 0x8B99 #endif #ifndef GL_OES_read_format #define GL_OES_read_format #define AGL_OES_read_format #define GL_IMPLEMENTATION_COLOR_READ_TYPE_OES 0x8B9A #define GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES 0x8B9B #endif #ifndef GL_OES_query_matrix #define GL_OES_query_matrix #define AGL_OES_query_matrix #endif #ifndef GL_EXT_depth_bounds_test #define GL_EXT_depth_bounds_test #define AGL_EXT_depth_bounds_test #define GL_DEPTH_BOUNDS_TEST_EXT 0x8890 #define GL_DEPTH_BOUNDS_EXT 0x8891 #endif #ifndef GL_EXT_texture_mirror_clamp #define GL_EXT_texture_mirror_clamp #define AGL_EXT_texture_mirror_clamp #define GL_MIRROR_CLAMP_EXT 0x8742 #define GL_MIRROR_CLAMP_TO_EDGE_EXT 0x8743 #define GL_MIRROR_CLAMP_TO_BORDER_EXT 0x8912 #endif #ifndef GL_EXT_blend_equation_separate #define GL_EXT_blend_equation_separate #define AGL_EXT_blend_equation_separate #define GL_BLEND_EQUATION_RGB_EXT 0x8009 /* Same as GL_BLEND_EQUATION */ #define GL_BLEND_EQUATION_ALPHA_EXT 0x883D #endif #ifndef GL_MESA_pack_invert #define GL_MESA_pack_invert #define AGL_MESA_pack_invert #define GL_PACK_INVERT_MESA 0x8758 #endif #ifndef GL_MESA_ycbcr_texture #define GL_MESA_ycbcr_texture #define AGL_MESA_ycbcr_texture #define GL_YCBCR_MESA 0x8757 /* Same as GL_UNSIGNED_SHORT_8_8_APPLE and GL_UNSIGNED_SHORT_8_8_REV_APPLE */ #define GL_UNSIGNED_SHORT_8_8_MESA 0x85BA #define GL_UNSIGNED_SHORT_8_8_REV_MESA 0x85BB #endif #ifndef GL_EXT_pixel_buffer_object #define GL_EXT_pixel_buffer_object #define AGL_EXT_pixel_buffer_object #define GL_PIXEL_PACK_BUFFER_EXT 0x88EB #define GL_PIXEL_UNPACK_BUFFER_EXT 0x88EC #define GL_PIXEL_PACK_BUFFER_BINDING_EXT 0x88ED #define GL_PIXEL_UNPACK_BUFFER_BINDING_EXT 0x88EF #endif #ifndef GL_NV_fragment_program_option #define GL_NV_fragment_program_option #define AGL_NV_fragment_program_option #endif #ifndef GL_NV_fragment_program2 #define GL_NV_fragment_program2 #define AGL_NV_fragment_program2 #define GL_MAX_PROGRAM_EXEC_INSTRUCTIONS_NV 0x88F4 #define GL_MAX_PROGRAM_CALL_DEPTH_NV 0x88F5 #define GL_MAX_PROGRAM_IF_DEPTH_NV 0x88F6 #define GL_MAX_PROGRAM_LOOP_DEPTH_NV 0x88F7 #define GL_MAX_PROGRAM_LOOP_COUNT_NV 0x88F8 #endif #ifndef GL_NV_vertex_program2_option #define GL_NV_vertex_program2_option #define AGL_NV_vertex_program2_option #define GL_MAX_PROGRAM_EXEC_INSTRUCTIONS_NV 0x88F4 #define GL_MAX_PROGRAM_CALL_DEPTH_NV 0x88F5 #endif #ifndef GL_NV_vertex_program3 #define GL_NV_vertex_program3 #define AGL_NV_vertex_program3 #define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB 0x8B4C #endif #ifndef GL_EXT_texture_compression_dxt1 #define GL_EXT_texture_compression_dxt1 #define AGL_EXT_texture_compression_dxt1 #ifndef AGL_EXT_texture_compression_s3tc #define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0 #define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1 #endif #endif #ifndef GL_EXT_framebuffer_object #define GL_EXT_framebuffer_object #define AGL_EXT_framebuffer_object #define GL_FRAMEBUFFER_EXT 0x8D40 #define GL_RENDERBUFFER_EXT 0x8D41 #define GL_STENCIL_INDEX_EXT 0x8D45 #define GL_STENCIL_INDEX1_EXT 0x8D46 #define GL_STENCIL_INDEX4_EXT 0x8D47 #define GL_STENCIL_INDEX8_EXT 0x8D48 #define GL_STENCIL_INDEX16_EXT 0x8D49 #define GL_RENDERBUFFER_WIDTH_EXT 0x8D42 #define GL_RENDERBUFFER_HEIGHT_EXT 0x8D43 #define GL_RENDERBUFFER_INTERNAL_FORMAT_EXT 0x8D44 #define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT 0x8CD0 #define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT 0x8CD1 #define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT 0x8CD2 #define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT 0x8CD3 #define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT 0x8CD4 #define GL_COLOR_ATTACHMENT0_EXT 0x8CE0 #define GL_COLOR_ATTACHMENT1_EXT 0x8CE1 #define GL_COLOR_ATTACHMENT2_EXT 0x8CE2 #define GL_COLOR_ATTACHMENT3_EXT 0x8CE3 #define GL_COLOR_ATTACHMENT4_EXT 0x8CE4 #define GL_COLOR_ATTACHMENT5_EXT 0x8CE5 #define GL_COLOR_ATTACHMENT6_EXT 0x8CE6 #define GL_COLOR_ATTACHMENT7_EXT 0x8CE7 #define GL_COLOR_ATTACHMENT8_EXT 0x8CE8 #define GL_COLOR_ATTACHMENT9_EXT 0x8CE9 #define GL_COLOR_ATTACHMENT10_EXT 0x8CEA #define GL_COLOR_ATTACHMENT11_EXT 0x8CEB #define GL_COLOR_ATTACHMENT12_EXT 0x8CEC #define GL_COLOR_ATTACHMENT13_EXT 0x8CED #define GL_COLOR_ATTACHMENT14_EXT 0x8CEE #define GL_COLOR_ATTACHMENT15_EXT 0x8CEF #define GL_DEPTH_ATTACHMENT_EXT 0x8D00 #define GL_STENCIL_ATTACHMENT_EXT 0x8D20 #define GL_FRAMEBUFFER_COMPLETE_EXT 0x8CD5 #define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT 0x8CD6 #define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT 0x8CD7 #define GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT 0x8CD8 #define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT 0x8CD9 #define GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT 0x8CDA #define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT 0x8CDB #define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT 0x8CDC #define GL_FRAMEBUFFER_UNSUPPORTED_EXT 0x8CDD #define GL_FRAMEBUFFER_STATUS_ERROR_EXT 0x8CDE #define GL_FRAMEBUFFER_BINDING_EXT 0x8CA6 #define GL_RENDERBUFFER_BINDING_EXT 0x8CA7 #define GL_MAX_COLOR_ATTACHMENTS_EXT 0x8CDF #define GL_MAX_RENDERBUFFER_SIZE_EXT 0x84E8 #define GL_INVALID_FRAMEBUFFER_OPERATION_EXT 0x0506 #endif #ifndef GL_GREMEDY_string_marker #define GL_GREMEDY_string_marker #define AGL_GREMEDY_string_marker #endif #ifndef GL_EXT_packed_depth_stencil #define GL_EXT_packed_depth_stencil #define AGL_EXT_packed_depth_stencil #define GL_DEPTH_STENCIL_EXT 0x84F9 #define GL_UNSIGNED_INT_24_8_EXT 0x84FA #define GL_DEPTH24_STENCIL8_EXT 0x88F0 #define GL_TEXTURE_STENCIL_SIZE_EXT 0x88F1 #endif #ifndef GL_EXT_stencil_clear_tag #define GL_EXT_stencil_clear_tag #define AGL_EXT_stencil_clear_tag #define GL_STENCIL_TAG_BITS_EXT 0x88F2 #define GL_STENCIL_CLEAR_TAG_VALUE_EXT 0x88F3 #endif #ifndef GL_EXT_texture_sRGB #define GL_EXT_texture_sRGB #define AGL_EXT_texture_sRGB #define GL_SRGB_EXT 0x8C40 #define GL_SRGB8_EXT 0x8C41 #define GL_SRGB_ALPHA_EXT 0x8C42 #define GL_SRGB8_ALPHA8_EXT 0x8C43 #define GL_SLUMINANCE_ALPHA_EXT 0x8C44 #define GL_SLUMINANCE8_ALPHA8_EXT 0x8C45 #define GL_SLUMINANCE_EXT 0x8C46 #define GL_SLUMINANCE8_EXT 0x8C47 #define GL_COMPRESSED_SRGB_EXT 0x8C48 #define GL_COMPRESSED_SRGB_ALPHA_EXT 0x8C49 #define GL_COMPRESSED_SLUMINANCE_EXT 0x8C4A #define GL_COMPRESSED_SLUMINANCE_ALPHA_EXT 0x8C4B #define GL_COMPRESSED_SRGB_S3TC_DXT1_EXT 0x8C4C #define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT 0x8C4D #define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT 0x8C4E #define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT 0x8C4F #endif #ifndef GL_EXT_framebuffer_blit #define GL_EXT_framebuffer_blit #define AGL_EXT_framebuffer_blit #define GL_READ_FRAMEBUFFER_EXT 0x8CA8 #define GL_DRAW_FRAMEBUFFER_EXT 0x8CA9 #define GL_READ_FRAMEBUFFER_BINDING_EXT GL_FRAMEBUFFER_BINDING_EXT #define GL_DRAW_FRAMEBUFFER_BINDING_EXT 0x8CAA #endif #ifndef GL_EXT_framebuffer_multisample #define GL_EXT_framebuffer_multisample #define AGL_EXT_framebuffer_multisample #define GL_RENDERBUFFER_SAMPLES_EXT 0x8CAB #define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT 0x8D56 #define GL_MAX_SAMPLES_EXT 0x8D57 #endif #ifndef GL_MESAX_texture_stack #define GL_MESAX_texture_stack #define AGL_MESAX_texture_stack #define GL_TEXTURE_1D_STACK_MESAX 0x8759 #define GL_TEXTURE_2D_STACK_MESAX 0x875A #define GL_PROXY_TEXTURE_1D_STACK_MESAX 0x875B #define GL_PROXY_TEXTURE_2D_STACK_MESAX 0x875C #define GL_TEXTURE_1D_STACK_BINDING_MESAX 0x875D #define GL_TEXTURE_2D_STACK_BINDING_MESAX 0x875E #endif #ifndef GL_EXT_timer_query #define GL_EXT_timer_query #define AGL_EXT_timer_query #if (defined _MSC_VER) && (_MSC_VER < 1400) typedef __int64 GLint64EXT; typedef unsigned __int64 GLuint64EXT; #else typedef int64_t GLint64EXT; typedef uint64_t GLuint64EXT; #endif #define GL_TIME_ELAPSED_EXT 0x88BF #endif #ifndef GL_EXT_gpu_program_parameters #define GL_EXT_gpu_program_parameters #define AGL_EXT_gpu_program_parameters #endif #ifndef GL_APPLE_flush_buffer_range #define GL_APPLE_flush_buffer_range #define AGL_APPLE_flush_buffer_range #define GL_BUFFER_SERIALIZED_MODIFY_APPLE 0x8A12 #define GL_BUFFER_FLUSHING_UNMAP_APPLE 0x8A13 #endif #ifndef GL_EXT_bindable_uniform #define GL_EXT_bindable_uniform #define AGL_EXT_bindable_uniform #define GL_MAX_VERTEX_BINDABLE_UNIFORMS_EXT 0x8DE2 #define GL_MAX_FRAGMENT_BINDABLE_UNIFORMS_EXT 0x8DE3 #define GL_MAX_GEOMETRY_BINDABLE_UNIFORMS_EXT 0x8DE4 #define GL_MAX_BINDABLE_UNIFORM_SIZE_EXT 0x8DED #define GL_UNIFORM_BUFFER_BINDING_EXT 0x8DEF #define GL_UNIFORM_BUFFER_EXT 0x8DEE #endif #ifndef GL_EXT_draw_buffers2 #define GL_EXT_draw_buffers2 #define AGL_EXT_draw_buffers2 #endif #ifndef GL_EXT_draw_instanced #define GL_EXT_draw_instanced #define AGL_EXT_draw_instanced #endif #ifndef GL_EXT_framebuffer_sRGB #define GL_EXT_framebuffer_sRGB #define AGL_EXT_framebuffer_sRGB #define GL_FRAMEBUFFER_SRGB_EXT 0x8DB9 #define GL_FRAMEBUFFER_SRGB_CAPABLE_EXT 0x8DBA #endif #ifndef GL_EXT_geometry_shader4 #define GL_EXT_geometry_shader4 #define AGL_EXT_geometry_shader4 #define GL_GEOMETRY_SHADER_EXT 0x8DD9 #define GL_GEOMETRY_VERTICES_OUT_EXT 0x8DDA #define GL_GEOMETRY_INPUT_TYPE_EXT 0x8DDB #define GL_GEOMETRY_OUTPUT_TYPE_EXT 0x8DDC #define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT 0x8C29 #define GL_MAX_GEOMETRY_VARYING_COMPONENTS_EXT 0x8DDD #define GL_MAX_VERTEX_VARYING_COMPONENTS_EXT 0x8DDE #define GL_MAX_VARYING_COMPONENTS_EXT 0x8B4B #define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_EXT 0x8DDF #define GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT 0x8DE0 #define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_EXT 0x8DE1 #define GL_LINES_ADJACENCY_EXT 0xA #define GL_LINE_STRIP_ADJACENCY_EXT 0xB #define GL_TRIANGLES_ADJACENCY_EXT 0xC #define GL_TRIANGLE_STRIP_ADJACENCY_EXT 0xD #define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT 0x8DA8 #define GL_FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_EXT 0x8DA9 #define GL_FRAMEBUFFER_ATTACHMENT_LAYERED_EXT 0x8DA7 #define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER_EXT 0x8CD4 #define GL_PROGRAM_POINT_SIZE_EXT 0x8642 #endif #ifndef GL_EXT_gpu_shader4 #define GL_EXT_gpu_shader4 #define AGL_EXT_gpu_shader4 #define GL_VERTEX_ATTRIB_ARRAY_INTEGER_EXT 0x88FD #define GL_SAMPLER_1D_ARRAY_EXT 0x8DC0 #define GL_SAMPLER_2D_ARRAY_EXT 0x8DC1 #define GL_SAMPLER_BUFFER_EXT 0x8DC2 #define GL_SAMPLER_1D_ARRAY_SHADOW_EXT 0x8DC3 #define GL_SAMPLER_2D_ARRAY_SHADOW_EXT 0x8DC4 #define GL_SAMPLER_CUBE_SHADOW_EXT 0x8DC5 #define GL_UNSIGNED_INT 0x1405 #define GL_UNSIGNED_INT_VEC2_EXT 0x8DC6 #define GL_UNSIGNED_INT_VEC3_EXT 0x8DC7 #define GL_UNSIGNED_INT_VEC4_EXT 0x8DC8 #define GL_INT_SAMPLER_1D_EXT 0x8DC9 #define GL_INT_SAMPLER_2D_EXT 0x8DCA #define GL_INT_SAMPLER_3D_EXT 0x8DCB #define GL_INT_SAMPLER_CUBE_EXT 0x8DCC #define GL_INT_SAMPLER_2D_RECT_EXT 0x8DCD #define GL_INT_SAMPLER_1D_ARRAY_EXT 0x8DCE #define GL_INT_SAMPLER_2D_ARRAY_EXT 0x8DCF #define GL_INT_SAMPLER_BUFFER_EXT 0x8DD0 #define GL_UNSIGNED_INT_SAMPLER_1D_EXT 0x8DD1 #define GL_UNSIGNED_INT_SAMPLER_2D_EXT 0x8DD2 #define GL_UNSIGNED_INT_SAMPLER_3D_EXT 0x8DD3 #define GL_UNSIGNED_INT_SAMPLER_CUBE_EXT 0x8DD4 #define GL_UNSIGNED_INT_SAMPLER_2D_RECT_EXT 0x8DD5 #define GL_UNSIGNED_INT_SAMPLER_1D_ARRAY_EXT 0x8DD6 #define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY_EXT 0x8DD7 #define GL_UNSIGNED_INT_SAMPLER_BUFFER_EXT 0x8DD8 #define GL_MIN_PROGRAM_TEXEL_OFFSET_EXT 0x8904 #define GL_MAX_PROGRAM_TEXEL_OFFSET_EXT 0x8905 #endif #ifndef GL_EXT_packed_float #define GL_EXT_packed_float #define AGL_EXT_packed_float #define GL_R11F_G11F_B10F_EXT 0x8C3A #define GL_UNSIGNED_INT_10F_11F_11F_REV_EXT 0x8C3B #define GL_RGBA_SIGNED_COMPONENTS_EXT 0x8C3C #endif #ifndef GL_EXT_texture_array #define GL_EXT_texture_array #define AGL_EXT_texture_array #define GL_TEXTURE_1D_ARRAY_EXT 0x8C18 #define GL_TEXTURE_2D_ARRAY_EXT 0x8C1A #define GL_PROXY_TEXTURE_2D_ARRAY_EXT 0x8C1B #define GL_PROXY_TEXTURE_1D_ARRAY_EXT 0x8C19 #define GL_TEXTURE_BINDING_1D_ARRAY_EXT 0x8C1C #define GL_TEXTURE_BINDING_2D_ARRAY_EXT 0x8C1D #define GL_MAX_ARRAY_TEXTURE_LAYERS_EXT 0x88FF #define GL_COMPARE_REF_DEPTH_TO_TEXTURE_EXT 0x884E #define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER_EXT 0x8CD4 #define GL_SAMPLER_1D_ARRAY_EXT 0x8DC0 #define GL_SAMPLER_2D_ARRAY_EXT 0x8DC1 #define GL_SAMPLER_1D_ARRAY_SHADOW_EXT 0x8DC3 #define GL_SAMPLER_2D_ARRAY_SHADOW_EXT 0x8DC4 #endif #ifndef GL_EXT_texture_buffer_object #define GL_EXT_texture_buffer_object #define AGL_EXT_texture_buffer_object #define GL_TEXTURE_BUFFER_EXT 0x8C2A #define GL_MAX_TEXTURE_BUFFER_SIZE_EXT 0x8C2B #define GL_TEXTURE_BINDING_BUFFER_EXT 0x8C2C #define GL_TEXTURE_BUFFER_DATA_STORE_BINDING_EXT 0x8C2D #define GL_TEXTURE_BUFFER_FORMAT_EXT 0x8C2E #endif #ifndef GL_EXT_texture_compression_latc #define GL_EXT_texture_compression_latc #define AGL_EXT_texture_compression_latc #define GL_COMPRESSED_LUMINANCE_LATC1_EXT 0x8C70 #define GL_COMPRESSED_SIGNED_LUMINANCE_LATC1_EXT 0x8C71 #define GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT 0x8C72 #define GL_COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2_EXT 0x8C73 #endif #ifndef GL_EXT_texture_compression_rgtc #define GL_EXT_texture_compression_rgtc #define AGL_EXT_texture_compression_rgtc #define GL_COMPRESSED_RED_RGTC1_EXT 0x8DBB #define GL_COMPRESSED_SIGNED_RED_RGTC1_EXT 0x8DBC #define GL_COMPRESSED_RED_GREEN_RGTC2_EXT 0x8DBD #define GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT 0x8DBE #endif #ifndef GL_EXT_texture_integer #define GL_EXT_texture_integer #define AGL_EXT_texture_integer #define GL_RGBA_INTEGER_MODE_EXT 0x8D9E #define GL_RGBA32UI_EXT 0x8D70 #define GL_RGB32UI_EXT 0x8D71 #define GL_ALPHA32UI_EXT 0x8D72 #define GL_INTENSITY32UI_EXT 0x8D73 #define GL_LUMINANCE32UI_EXT 0x8D74 #define GL_LUMINANCE_ALPHA32UI_EXT 0x8D75 #define GL_RGBA16UI_EXT 0x8D76 #define GL_RGB16UI_EXT 0x8D77 #define GL_ALPHA16UI_EXT 0x8D78 #define GL_INTENSITY16UI_EXT 0x8D79 #define GL_LUMINANCE16UI_EXT 0x8D7A #define GL_LUMINANCE_ALPHA16UI_EXT 0x8D7B #define GL_RGBA8UI_EXT 0x8D7C #define GL_RGB8UI_EXT 0x8D7D #define GL_ALPHA8UI_EXT 0x8D7E #define GL_INTENSITY8UI_EXT 0x8D7F #define GL_LUMINANCE8UI_EXT 0x8D80 #define GL_LUMINANCE_ALPHA8UI_EXT 0x8D81 #define GL_RGBA32I_EXT 0x8D82 #define GL_RGB32I_EXT 0x8D83 #define GL_ALPHA32I_EXT 0x8D84 #define GL_INTENSITY32I_EXT 0x8D85 #define GL_LUMINANCE32I_EXT 0x8D86 #define GL_LUMINANCE_ALPHA32I_EXT 0x8D87 #define GL_RGBA16I_EXT 0x8D88 #define GL_RGB16I_EXT 0x8D89 #define GL_ALPHA16I_EXT 0x8D8A #define GL_INTENSITY16I_EXT 0x8D8B #define GL_LUMINANCE16I_EXT 0x8D8C #define GL_LUMINANCE_ALPHA16I_EXT 0x8D8D #define GL_RGBA8I_EXT 0x8D8E #define GL_RGB8I_EXT 0x8D8F #define GL_ALPHA8I_EXT 0x8D90 #define GL_INTENSITY8I_EXT 0x8D91 #define GL_LUMINANCE8I_EXT 0x8D92 #define GL_LUMINANCE_ALPHA8I_EXT 0x8D93 #define GL_RED_INTEGER_EXT 0x8D94 #define GL_GREEN_INTEGER_EXT 0x8D95 #define GL_BLUE_INTEGER_EXT 0x8D96 #define GL_ALPHA_INTEGER_EXT 0x8D97 #define GL_RGB_INTEGER_EXT 0x8D98 #define GL_RGBA_INTEGER_EXT 0x8D99 #define GL_BGR_INTEGER_EXT 0x8D9A #define GL_BGRA_INTEGER_EXT 0x8D9B #define GL_LUMINANCE_INTEGER_EXT 0x8D9C #define GL_LUMINANCE_ALPHA_INTEGER_EXT 0x8D9D #endif #ifndef GL_EXT_texture_shared_exponent #define GL_EXT_texture_shared_exponent #define AGL_EXT_texture_shared_exponent #define GL_RGB9_E5_EXT 0x8C3D #define GL_UNSIGNED_INT_5_9_9_9_REV_EXT 0x8C3E #define GL_TEXTURE_SHARED_SIZE_EXT 0x8C3F #endif #ifndef GL_NV_depth_buffer_float #define GL_NV_depth_buffer_float #define AGL_NV_depth_buffer_float #define GL_DEPTH_COMPONENT32F_NV 0x8DAB #define GL_DEPTH32F_STENCIL8_NV 0x8DAC #define GL_FLOAT_32_UNSIGNED_INT_24_8_REV_NV 0x8DAD #define GL_DEPTH_BUFFER_FLOAT_MODE_NV 0x8DAF #endif #ifndef GL_NV_fragment_program4 #define GL_NV_fragment_program4 #define AGL_NV_fragment_program4 #endif #ifndef GL_NV_framebuffer_multisample_coverage #define GL_NV_framebuffer_multisample_coverage #define AGL_NV_framebuffer_multisample_coverage #define GL_RENDERBUFFER_COVERAGE_SAMPLES_NV 0x8CAB #define GL_RENDERBUFFER_COLOR_SAMPLES_NV 0x8E10 #endif #ifndef GL_NV_geometry_program4 #define GL_NV_geometry_program4 #define AGL_NV_geometry_program4 #define GL_GEOMETRY_PROGRAM_NV 0x8C26 #define GL_MAX_PROGRAM_OUTPUT_VERTICES_NV 0x8C27 #define GL_MAX_PROGRAM_TOTAL_OUTPUT_COMPONENTS_NV 0x8C28 #if !defined GL_EXT_geometry_shader4 #define GL_GEOMETRY_VERTICES_OUT_EXT 0x8DDA #define GL_GEOMETRY_INPUT_TYPE_EXT 0x8DDB #define GL_GEOMETRY_OUTPUT_TYPE_EXT 0x8DDC #define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT 0x8C29 #define GL_LINES_ADJACENCY_EXT 0xA #define GL_LINE_STRIP_ADJACENCY_EXT 0xB #define GL_TRIANGLES_ADJACENCY_EXT 0xC #define GL_TRIANGLE_STRIP_ADJACENCY_EXT 0xD #define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT 0x8DA8 #define GL_FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_EXT 0x8DA9 #define GL_FRAMEBUFFER_ATTACHMENT_LAYERED_EXT 0x8DA7 #define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER_EXT 0x8CD4 #define GL_PROGRAM_POINT_SIZE_EXT 0x8642 #endif #endif #ifndef GL_NV_gpu_program4 #define GL_NV_gpu_program4 #define AGL_NV_gpu_program4 #define GL_MIN_PROGRAM_TEXEL_OFFSET_EXT 0x8904 #define GL_MAX_PROGRAM_TEXEL_OFFSET_EXT 0x8905 #define GL_PROGRAM_ATTRIB_COMPONENTS_NV 0x8906 #define GL_PROGRAM_RESULT_COMPONENTS_NV 0x8907 #define GL_MAX_PROGRAM_ATTRIB_COMPONENTS_NV 0x8908 #define GL_MAX_PROGRAM_RESULT_COMPONENTS_NV 0x8909 #define GL_MAX_PROGRAM_GENERIC_ATTRIBS_NV 0x8DA5 #define GL_MAX_PROGRAM_GENERIC_RESULTS_NV 0x8DA6 #endif #ifndef GL_NV_parameter_buffer_object #define GL_NV_parameter_buffer_object #define AGL_NV_parameter_buffer_object #define GL_MAX_PROGRAM_PARAMETER_BUFFER_BINDINGS_NV 0x8DA0 #define GL_MAX_PROGRAM_PARAMETER_BUFFER_SIZE_NV 0x8DA1 #define GL_VERTEX_PROGRAM_PARAMETER_BUFFER_NV 0x8DA2 #define GL_GEOMETRY_PROGRAM_PARAMETER_BUFFER_NV 0x8DA3 #define GL_FRAGMENT_PROGRAM_PARAMETER_BUFFER_NV 0x8DA4 #endif #ifndef GL_NV_transform_feedback #define GL_NV_transform_feedback #define AGL_NV_transform_feedback #define GL_TRANSFORM_FEEDBACK_BUFFER_NV 0x8C8E #define GL_TRANSFORM_FEEDBACK_BUFFER_START_NV 0x8C84 #define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE_NV 0x8C85 #define GL_TRANSFORM_FEEDBACK_RECORD_NV 0x8C86 #define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING_NV 0x8C8F #define GL_INTERLEAVED_ATTRIBS_NV 0x8C8C #define GL_SEPARATE_ATTRIBS_NV 0x8C8D #define GL_PRIMITIVES_GENERATED_NV 0x8C87 #define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN_NV 0x8C88 #define GL_RASTERIZER_DISCARD_NV 0x8C89 #define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS_NV 0x8C8A #define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS_NV 0x8C8B #define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS_NV 0x8C80 #define GL_TRANSFORM_FEEDBACK_ATTRIBS_NV 0x8C7E #define GL_ACTIVE_VARYINGS_NV 0x8C81 #define GL_ACTIVE_VARYING_MAX_LENGTH_NV 0x8C82 #define GL_TRANSFORM_FEEDBACK_VARYINGS_NV 0x8C83 #define GL_TRANSFORM_FEEDBACK_BUFFER_MODE_NV 0x8C7F #define GL_BACK_PRIMARY_COLOR_NV 0x8C77 #define GL_BACK_SECONDARY_COLOR_NV 0x8C78 #define GL_TEXTURE_COORD_NV 0x8C79 #define GL_CLIP_DISTANCE_NV 0x8C7A #define GL_VERTEX_ID_NV 0x8C7B #define GL_PRIMITIVE_ID_NV 0x8C7C #define GL_GENERIC_ATTRIB_NV 0x8C7D #if !defined GL_NV_register_combiners #define GL_SECONDARY_COLOR_NV 0x852D #endif #if !defined GL_EXT_gpu_shader4 #define GL_UNSIGNED_INT_VEC2_EXT 0x8DC6 #define GL_UNSIGNED_INT_VEC3_EXT 0x8DC7 #define GL_UNSIGNED_INT_VEC4_EXT 0x8DC8 #endif #endif #ifndef GL_NV_vertex_program4 #define GL_NV_vertex_program4 #define AGL_NV_vertex_program4 #if !defined GL_EXT_vertex_shader4 #define GL_VERTEX_ATTRIB_ARRAY_INTEGER_EXT 0x88FD #endif #endif #ifndef GL_GREMEDY_frame_terminator #define GL_GREMEDY_frame_terminator #define AGL_GREMEDY_frame_terminator #endif #ifndef GL_NV_conditional_render #define GL_NV_conditional_render #define AGL_NV_conditional_render #define GL_QUERY_WAIT_NV 0x8E13 #define GL_QUERY_NO_WAIT_NV 0x8E14 #define GL_QUERY_BY_REGION_WAIT_NV 0x8E15 #define GL_QUERY_BY_REGION_NO_WAIT_NV 0x8E16 #endif #ifndef GL_NV_present_video #define GL_NV_present_video #define AGL_NV_present_video #define GL_FRAME_NV 0x8E26 #define GL_FIELDS_NV 0x8E27 #define GL_CURRENT_TIME_NV 0x8E28 #define GL_NUM_FILL_STREAMS_NV 0x8E29 #define GL_PRESENT_TIME_NV 0x8E2A #define GL_PRESENT_DURATION_NV 0x8E2B #endif #ifndef GL_EXT_transform_feedback #define GL_EXT_transform_feedback #define AGL_EXT_transform_feedback #define GL_TRANSFORM_FEEDBACK_BUFFER_EXT 0x8C8E #define GL_TRANSFORM_FEEDBACK_BUFFER_START_EXT 0x8C84 #define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE_EXT 0x8C85 #define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING_EXT 0x8C8F #define GL_INTERLEAVED_ATTRIBS_EXT 0x8C8C #define GL_SEPARATE_ATTRIBS_EXT 0x8C8D #define GL_PRIMITIVES_GENERATED_EXT 0x8C87 #define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN_EXT 0x8C88 #define GL_RASTERIZER_DISCARD_EXT 0x8C89 #define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS_EXT 0x8C8A #define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS_EXT 0x8C8B #define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS_EXT 0x8C80 #define GL_TRANSFORM_FEEDBACK_VARYINGS_EXT 0x8C83 #define GL_TRANSFORM_FEEDBACK_BUFFER_MODE_EXT 0x8C7F #define GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH_EXT 0x8C76 #endif #ifndef GL_EXT_direct_state_access #define GL_EXT_direct_state_access #define AGL_EXT_direct_state_access #define GL_PROGRAM_MATRIX_EXT 0x8E2D #define GL_TRANSPOSE_PROGRAM_MATRIX_EXT 0x8E2E #define GL_PROGRAM_MATRIX_STACK_DEPTH_EXT 0x8E2F #endif allegro4.4-4.4.2/addons/allegrogl/include/allegrogl/GLext/gl_ext_list.h000066400000000000000000000302761173507505700257420ustar00rootroot00000000000000AGL_EXT(ARB_imaging, 0) AGL_EXT(ARB_multitexture, 1.21) AGL_EXT(ARB_transpose_matrix, 1.3) AGL_EXT(ARB_multisample, 1.3) AGL_EXT(ARB_texture_env_add, 1.3) AGL_EXT(ARB_texture_cube_map, 1.3) AGL_EXT(ARB_texture_compression, 1.3) AGL_EXT(ARB_texture_border_clamp, 1.3) AGL_EXT(ARB_point_parameters, 1.4) AGL_EXT(ARB_vertex_blend, 0) AGL_EXT(ARB_texture_env_combine, 1.3) AGL_EXT(ARB_texture_env_crossbar, 1.4) AGL_EXT(ARB_texture_env_dot3, 1.3) AGL_EXT(ARB_texture_mirrored_repeat, 1.4) AGL_EXT(ARB_depth_texture, 1.4) AGL_EXT(ARB_shadow, 1.4) AGL_EXT(ARB_shadow_ambient, 0) AGL_EXT(ARB_window_pos, 1.4) AGL_EXT(ARB_vertex_program, 0) AGL_EXT(ARB_fragment_program, 0) AGL_EXT(ARB_vertex_buffer_object, 1.5) AGL_EXT(ARB_occlusion_query, 1.5) AGL_EXT(ARB_shader_objects, 0) /* Those were promoted to Core in */ AGL_EXT(ARB_vertex_shader, 0) /* 2.0 with modifications. */ AGL_EXT(ARB_fragment_shader, 0) /* */ AGL_EXT(ARB_shading_language_100, 0) /* */ AGL_EXT(ARB_texture_non_power_of_two,2.0) AGL_EXT(ARB_point_sprite, 2.0) AGL_EXT(ARB_fragment_program_shadow, 0) AGL_EXT(ARB_draw_buffers, 2.0) AGL_EXT(ARB_texture_rectangle, 0) AGL_EXT(ARB_color_buffer_float, 3.0) AGL_EXT(ARB_half_float_pixel, 3.0) AGL_EXT(ARB_texture_float, 3.0) AGL_EXT(ARB_pixel_buffer_object, 2.1) AGL_EXT(ARB_instanced_arrays, 0) AGL_EXT(ARB_draw_instanced, 0) AGL_EXT(ARB_geometry_shader4, 0) AGL_EXT(ARB_texture_buffer_object, 0) AGL_EXT(ARB_depth_buffer_float, 3.0) AGL_EXT(ARB_framebuffer_object, 3.0) AGL_EXT(ARB_framebuffer_sRGB, 3.0) AGL_EXT(ARB_half_float_vertex, 3.0) AGL_EXT(ARB_map_buffer_range, 3.0) AGL_EXT(ARB_texture_compression_rgtc,3.0) AGL_EXT(ARB_texture_rg, 3.0) AGL_EXT(ARB_vertex_array_object, 3.0) AGL_EXT(EXT_abgr, 0) AGL_EXT(EXT_blend_color, 1.1) AGL_EXT(EXT_polygon_offset, 1.1) AGL_EXT(EXT_texture, 1.1) AGL_EXT(EXT_texture3D, 1.2) AGL_EXT(SGIS_texture_filter4, 0) AGL_EXT(EXT_subtexture, 1.1) AGL_EXT(EXT_copy_texture, 1.1) AGL_EXT(EXT_histogram, 0) AGL_EXT(EXT_convolution, 0) AGL_EXT(SGI_color_matrix, 0) AGL_EXT(SGI_color_table, 0) AGL_EXT(SGIS_pixel_texture, 0) AGL_EXT(SGIX_pixel_texture, 0) AGL_EXT(SGIS_texture4D, 0) AGL_EXT(SGI_texture_color_table, 0) AGL_EXT(EXT_cmyka, 0) AGL_EXT(EXT_texture_object, 1.1) AGL_EXT(SGIS_detail_texture, 0) AGL_EXT(SGIS_sharpen_texture, 0) AGL_EXT(EXT_packed_pixels, 1.2) AGL_EXT(SGIS_texture_lod, 1.2) AGL_EXT(SGIS_multisample, 1.3) AGL_EXT(EXT_rescale_normal, 1.2) AGL_EXT(EXT_vertex_array, 1.1) AGL_EXT(EXT_misc_attribute, 0) AGL_EXT(SGIS_generate_mipmap, 1.4) AGL_EXT(SGIX_clipmap, 0) AGL_EXT(SGIX_shadow, 0) AGL_EXT(SGIS_texture_edge_clamp, 1.2) AGL_EXT(SGIS_texture_border_clamp, 0) AGL_EXT(EXT_blend_minmax, 0) AGL_EXT(EXT_blend_subtract, 0) AGL_EXT(EXT_blend_logic_op, 1.1) AGL_EXT(SGIX_interlace, 0) AGL_EXT(SGIS_texture_select, 0) AGL_EXT(SGIX_sprite, 0) AGL_EXT(SGIX_texture_multi_buffer, 0) AGL_EXT(EXT_point_parameters, 0) AGL_EXT(SGIX_instruments, 0) AGL_EXT(SGIX_texture_scale_bias, 0) AGL_EXT(SGIX_framezoom, 0) AGL_EXT(SGIX_tag_sample_buffer, 0) AGL_EXT(SGIX_reference_plane, 0) AGL_EXT(SGIX_flush_raster, 0) AGL_EXT(SGIX_depth_texture, 0) AGL_EXT(SGIS_fog_function, 0) AGL_EXT(SGIX_fog_offset, 0) AGL_EXT(HP_image_transform, 0) AGL_EXT(HP_convolution_border_modes, 0) AGL_EXT(SGIX_texture_add_env, 0) AGL_EXT(EXT_color_subtable, 0) AGL_EXT(PGI_vertex_hints, 0) AGL_EXT(PGI_misc_hints, 0) AGL_EXT(EXT_paletted_texture, 0) AGL_EXT(EXT_clip_volume_hint, 0) AGL_EXT(SGIX_list_priority, 0) AGL_EXT(SGIX_ir_instrument1, 0) AGL_EXT(SGIX_texture_lod_bias, 0) AGL_EXT(SGIX_shadow_ambient, 0) AGL_EXT(EXT_index_texture, 0) AGL_EXT(EXT_index_material, 0) AGL_EXT(EXT_index_func, 0) AGL_EXT(EXT_index_array_formats, 0) AGL_EXT(EXT_compiled_vertex_array, 0) AGL_EXT(EXT_cull_vertex, 0) AGL_EXT(SGIX_ycrcb, 0) AGL_EXT(EXT_fragment_lighting, 0) AGL_EXT(IBM_rasterpos_clip, 0) AGL_EXT(HP_texture_lighting, 0) AGL_EXT(EXT_draw_range_elements, 0) AGL_EXT(WIN_phong_shading, 0) AGL_EXT(WIN_specular_fog, 0) AGL_EXT(EXT_light_texture, 0) AGL_EXT(SGIX_blend_alpha_minmax, 0) AGL_EXT(EXT_scene_marker, 0) AGL_EXT(SGIX_pixel_texture_bits, 0) AGL_EXT(EXT_bgra, 1.2) AGL_EXT(SGIX_async, 0) AGL_EXT(SGIX_async_pixel, 0) AGL_EXT(SGIX_async_histogram, 0) AGL_EXT(INTEL_texture_scissor, 0) AGL_EXT(INTEL_parallel_arrays, 0) AGL_EXT(HP_occlusion_test, 0) AGL_EXT(EXT_pixel_transform, 0) AGL_EXT(EXT_pixel_transform_color_table, 0) AGL_EXT(EXT_shared_texture_palette, 0) AGL_EXT(EXT_separate_specular_color, 1.2) AGL_EXT(EXT_secondary_color, 1.4) AGL_EXT(EXT_texture_env, 0) AGL_EXT(EXT_texture_perturb_normal, 0) AGL_EXT(EXT_multi_draw_arrays, 1.4) AGL_EXT(EXT_fog_coord, 1.4) AGL_EXT(REND_screen_coordinates, 0) AGL_EXT(EXT_coordinate_frame, 0) AGL_EXT(EXT_texture_env_combine, 0) AGL_EXT(APPLE_specular_vector, 0) AGL_EXT(APPLE_transform_hint, 0) AGL_EXT(SUNX_constant_data, 0) AGL_EXT(SUN_global_alpha, 0) AGL_EXT(SUN_triangle_list, 0) AGL_EXT(SUN_vertex, 0) AGL_EXT(EXT_blend_func_separate, 1.4) AGL_EXT(INGR_color_clamp, 0) AGL_EXT(INGR_interlace_read, 0) AGL_EXT(EXT_stencil_wrap, 1.4) AGL_EXT(EXT_422_pixels, 0) AGL_EXT(NV_texgen_reflection, 0) AGL_EXT(SGIX_texture_range, 0) AGL_EXT(SUN_convolution_border_modes, 0) AGL_EXT(EXT_texture_env_add, 0) AGL_EXT(EXT_texture_lod_bias, 1.4) AGL_EXT(EXT_texture_filter_anisotropic, 0) AGL_EXT(EXT_vertex_weighting, 0) AGL_EXT(NV_light_max_exponent, 0) AGL_EXT(NV_vertex_array_range, 0) AGL_EXT(NV_register_combiners, 0) AGL_EXT(NV_fog_distance, 0) AGL_EXT(NV_texgen_emboss, 0) AGL_EXT(NV_blend_square, 1.4) AGL_EXT(NV_texture_env_combine4, 0) AGL_EXT(MESA_resize_buffers, 0) AGL_EXT(MESA_window_pos, 0) AGL_EXT(EXT_texture_compression_s3tc, 0) AGL_EXT(IBM_cull_vertex, 0) AGL_EXT(IBM_multimode_draw_arrays, 0) AGL_EXT(IBM_vertex_array_lists, 0) /* AGL_EXT(3DFX_texture_compression_FXT1, 0) */ /* AGL_EXT(3DFX_multisample, 0) */ /* AGL_EXT(3DFX_tbuffer, 0) */ AGL_EXT(SGIX_vertex_preclip, 0) AGL_EXT(SGIX_resample, 0) AGL_EXT(SGIS_texture_color_mask, 0) AGL_EXT(EXT_texture_env_dot3, 0) AGL_EXT(ATI_texture_mirror_once, 0) AGL_EXT(NV_fence, 0) AGL_EXT(IBM_static_data, 0) AGL_EXT(IBM_texture_mirrored_repeat, 0) AGL_EXT(NV_evaluators, 0) AGL_EXT(NV_packed_depth_stencil, 3.0) AGL_EXT(NV_register_combiners2, 0) AGL_EXT(NV_texture_compression_vtc, 0) AGL_EXT(NV_texture_rectangle, 0) AGL_EXT(NV_texture_shader, 0) AGL_EXT(NV_texture_shader2, 0) AGL_EXT(NV_vertex_array_range2, 0) AGL_EXT(NV_vertex_program, 0) AGL_EXT(SGIX_texture_coordinate_clamp, 0) AGL_EXT(OML_interlace, 0) AGL_EXT(OML_subsample, 0) AGL_EXT(OML_resample, 0) AGL_EXT(NV_copy_depth_to_color, 0) AGL_EXT(ATI_envmap_bumpmap, 0) AGL_EXT(ATI_fragment_shader, 0) AGL_EXT(ATI_pn_triangles, 0) AGL_EXT(ATI_vertex_array_object, 0) AGL_EXT(EXT_vertex_shader, 0) AGL_EXT(ATI_vertex_streams, 0) AGL_EXT(ATI_element_array, 0) AGL_EXT(SUN_mesh_array, 0) AGL_EXT(SUN_slice_accum, 0) AGL_EXT(NV_multisample_filter_hint, 0) AGL_EXT(NV_depth_clamp, 0) AGL_EXT(NV_occlusion_query, 0) AGL_EXT(NV_point_sprite, 0) AGL_EXT(NV_texture_shader3, 0) AGL_EXT(NV_vertex_program1_1, 0) AGL_EXT(EXT_shadow_funcs, 1.5) AGL_EXT(EXT_stencil_two_side, 0) AGL_EXT(ATI_text_fragment_shader, 0) AGL_EXT(APPLE_client_storage, 0) AGL_EXT(APPLE_element_array, 0) AGL_EXT(APPLE_fence, 0) AGL_EXT(APPLE_vertex_array_object, 3.0) AGL_EXT(APPLE_vertex_array_range, 0) AGL_EXT(APPLE_ycbcr_422, 0) AGL_EXT(S3_s3tc, 0) AGL_EXT(ATI_draw_buffers, 0) AGL_EXT(ATI_texture_env_combine3, 0) AGL_EXT(ATI_texture_float, 0) AGL_EXT(NV_float_buffer, 0) AGL_EXT(NV_fragment_program, 0) AGL_EXT(NV_half_float, 3.0) AGL_EXT(NV_pixel_data_range, 0) AGL_EXT(NV_primitive_restart, 0) AGL_EXT(NV_texture_expand_normal, 0) AGL_EXT(NV_vertex_program2, 0) AGL_EXT(ATI_map_object_buffer, 0) AGL_EXT(ATI_separate_stencil, 2.0) AGL_EXT(ATI_vertex_attrib_array_object, 0) AGL_EXT(OES_byte_coordinates, 0) AGL_EXT(OES_fixed_point, 0) AGL_EXT(OES_single_precision, 0) AGL_EXT(OES_compressed_paletted_texture, 0) AGL_EXT(OES_read_format, 0) AGL_EXT(OES_query_matrix, 0) AGL_EXT(EXT_depth_bounds_test, 0) AGL_EXT(EXT_texture_mirror_clamp, 0) AGL_EXT(EXT_blend_equation_separate, 0) AGL_EXT(MESA_pack_invert, 0) AGL_EXT(MESA_ycbcr_texture, 0) AGL_EXT(EXT_pixel_buffer_object, 0) AGL_EXT(NV_fragment_program_option, 0) AGL_EXT(NV_fragment_program2, 0) AGL_EXT(NV_vertex_program2_option, 0) AGL_EXT(NV_vertex_program3, 0) AGL_EXT(EXT_texture_compression_dxt1, 0) AGL_EXT(EXT_framebuffer_object, 3.0) AGL_EXT(GREMEDY_string_marker, 0) AGL_EXT(EXT_packed_depth_stencil, 0) AGL_EXT(EXT_stencil_clear_tag, 0) AGL_EXT(EXT_texture_sRGB, 2.1) AGL_EXT(EXT_framebuffer_blit, 3.0) AGL_EXT(EXT_framebuffer_multisample, 3.0) AGL_EXT(MESAX_texture_stack, 0) AGL_EXT(EXT_timer_query, 0) AGL_EXT(EXT_gpu_program_parameters, 0) AGL_EXT(APPLE_flush_buffer_range, 0) #ifdef ALLEGRO_MACOSX AGL_EXT(EXT_texture_rectangle, 0) #endif AGL_EXT(EXT_bindable_uniform, 0) AGL_EXT(EXT_draw_buffers2, 3.0) AGL_EXT(EXT_draw_instanced, 0) AGL_EXT(EXT_framebuffer_sRGB, 3.0) AGL_EXT(EXT_geometry_shader4, 0) AGL_EXT(EXT_gpu_shader4, 3.0) AGL_EXT(EXT_packed_float, 3.0) AGL_EXT(EXT_texture_array, 3.0) AGL_EXT(EXT_texture_buffer_object, 0) AGL_EXT(EXT_texture_compression_latc, 0) AGL_EXT(EXT_texture_compression_rgtc,3.0) AGL_EXT(EXT_texture_integer, 3.0) AGL_EXT(EXT_texture_shared_exponent, 3.0) AGL_EXT(NV_depth_buffer_float, 3.0) AGL_EXT(NV_fragment_program4, 0) AGL_EXT(NV_framebuffer_multisample_coverage, 0) AGL_EXT(NV_geometry_program4, 0) AGL_EXT(NV_gpu_program4, 0) AGL_EXT(NV_parameter_buffer_object, 0) AGL_EXT(NV_transform_feedback, 0) AGL_EXT(NV_vertex_program4, 0) AGL_EXT(GREMEDY_frame_terminator, 0) AGL_EXT(NV_conditional_render, 3.0) AGL_EXT(NV_present_video, 0) AGL_EXT(EXT_direct_state_access, 0) AGL_EXT(EXT_transform_feedback, 3.0) allegro4.4-4.4.2/addons/allegrogl/include/allegrogl/GLext/glx_ext_alias.h000066400000000000000000000144721173507505700262500ustar00rootroot00000000000000/*Automatically generated by mkalias.sh DO NOT EDIT!*/ #ifdef AGLX_VERSION_1_3 /*GLX1.3*/ #define glXGetFBConfigs __aglXGetFBConfigs #define glXChooseFBConfig __aglXChooseFBConfig #define glXGetFBConfigAttrib __aglXGetFBConfigAttrib #define glXGetVisualFromFBConfig __aglXGetVisualFromFBConfig #define glXCreateWindow __aglXCreateWindow #define glXDestroyWindow __aglXDestroyWindow #define glXCreatePixmap __aglXCreatePixmap #define glXDestroyPixmap __aglXDestroyPixmap #define glXCreatePbuffer __aglXCreatePbuffer #define glXDestroyPbuffer __aglXDestroyPbuffer #define glXQueryDrawable __aglXQueryDrawable #define glXCreateNewContext __aglXCreateNewContext #define glXMakeContextCurrent __aglXMakeContextCurrent #define glXGetCurrentReadDrawable __aglXGetCurrentReadDrawable #define glXGetCurrentDisplay __aglXGetCurrentDisplay #define glXQueryContext __aglXQueryContext #define glXSelectEvent __aglXSelectEvent #define glXGetSelectedEvent __aglXGetSelectedEvent #endif #ifdef AGLX_VERSION_1_4 /*GLX1.4*/ #define glXGetProcAddress __aglXGetProcAddress #endif #ifdef AGLX_ARB_get_proc_address /*GLX_ARB_get_proc_address*/ #define glXGetProcAddressARB __aglXGetProcAddressARB #endif #ifdef AGLX_SGI_swap_control /*GLX_SGI_swap_control*/ #define glXSwapIntervalSGI __aglXSwapIntervalSGI #endif #ifdef AGLX_SGI_video_sync /*GLX_SGI_video_sync*/ #define glXGetVideoSyncSGI __aglXGetVideoSyncSGI #define glXWaitVideoSyncSGI __aglXWaitVideoSyncSGI #endif #ifdef AGLX_SGI_make_current_read /*GLX_SGI_make_current_read*/ #define glXMakeCurrentReadSGI __aglXMakeCurrentReadSGI #define glXGetCurrentReadDrawableSGI __aglXGetCurrentReadDrawableSGI #endif #ifdef AGLX_SGIX_video_source /*GLX_SGIX_video_source*/ /*ThisoneneedsSGI'sheaderfiletobeincludedfirst*/ #ifdef _VL_H_ #define glXCreateGLXVideoSourceSGIX __aglXCreateGLXVideoSourceSGIX #define glXDestroyGLXVideoSourceSGIX __aglXDestroyGLXVideoSourceSGIX #endif #endif #ifdef AGLX_EXT_import_context /*GLX_EXT_import_context*/ #define glXGetCurrentDisplayEXT __aglXGetCurrentDisplayEXT #define glXQueryContextInfoEXT __aglXQueryContextInfoEXT #define glXGetContextIDEXT __aglXGetContextIDEXT #define glXImportContextEXT __aglXImportContextEXT #define glXFreeContextEXT __aglXFreeContextEXT #endif #ifdef AGLX_SGIX_fbconfig /*GLX_SGIX_fbconfig*/ #define glXGetFBConfigAttribSGIX __aglXGetFBConfigAttribSGIX #define glXChooseFBConfigSGIX __aglXChooseFBConfigSGIX #define glXCreateGLXPixmapWithConfigSGIX __aglXCreateGLXPixmapWithConfigSGIX #define glXCreateContextWithConfigSGIX __aglXCreateContextWithConfigSGIX #define glXGetVisualFromFBConfigSGIX __aglXGetVisualFromFBConfigSGIX #define glXGetFBConfigFromVisualSGIX __aglXGetFBConfigFromVisualSGIX #endif #ifdef AGLX_SGIX_pbuffer /*GLX_SGIX_pbuffer*/ #define glXCreateGLXPbufferSGIX __aglXCreateGLXPbufferSGIX #define glXDestroyGLXPbufferSGIX __aglXDestroyGLXPbufferSGIX #define glXQueryGLXPbufferSGIX __aglXQueryGLXPbufferSGIX #define glXSelectEventSGIX __aglXSelectEventSGIX #define glXGetSelectedEventSGIX __aglXGetSelectedEventSGIX #endif #ifdef AGLX_SGI_cushion /*GLX_SGI_cushion*/ #define glXCushionSGI __aglXCushionSGI #endif #ifdef AGLX_SGIX_video_resize /*GLX_SGIX_video_resize*/ #define glXBindChannelToWindowSGIX __aglXBindChannelToWindowSGIX #define glXChannelRectSGIX __aglXChannelRectSGIX #define glXQueryChannelRectSGIX __aglXQueryChannelRectSGIX #define glXQueryChannelDeltasSGIX __aglXQueryChannelDeltasSGIX #define glXChannelRectSyncSGIX __aglXChannelRectSyncSGIX #endif #ifdef AGLX_SGIX_dmbuffer /*GLX_SGIX_dmbuffer*/ /*ThisoneneedsSGI'sheaderfiletobeincludedfirst*/ #ifdef _DM_BUFFER_H_ #define glXAssociateDMPbufferSGIX __aglXAssociateDMPbufferSGIX #endif #endif #ifdef AGLX_SGIX_swap_group /*GLX_SGIX_swap_group*/ #define glXJoinSwapGroupSGIX __aglXJoinSwapGroupSGIX #endif #ifdef AGLX_SGIX_swap_barrier /*GLX_SGIX_swap_barrier*/ #define glXBindSwapBarrierSGIX __aglXBindSwapBarrierSGIX #define glXQueryMaxSwapBarriersSGIX __aglXQueryMaxSwapBarriersSGIX #endif #ifdef AGLX_SUN_get_transparent_index /*GLX_SUN_get_transparent_index*/ #define glXGetTransparentIndexSUN __aglXGetTransparentIndexSUN #endif #ifdef AGLX_MESA_copy_sub_buffer /*GLX_MESA_copy_sub_buffer*/ #define glXCopySubBufferMESA __aglXCopySubBufferMESA #endif #ifdef AGLX_MESA_pixmap_colormap /*GLX_MESA_pixmap_colormap*/ #define glXCreateGLXPixmapMESA __aglXCreateGLXPixmapMESA #endif #ifdef AGLX_MESA_release_buffers /*GLX_MESA_release_buffers*/ #define glXReleaseBuffersMESA __aglXReleaseBuffersMESA #endif #ifdef AGLX_MESA_set_3dfx_mode /*GLX_MESA_set_3dfx_mode*/ #define glXSet3DfxModeMESA __aglXSet3DfxModeMESA #endif #ifdef AGLX_OML_sync_control /*GLX_OML_sync_control*/ #define glXGetSyncValuesOML __aglXGetSyncValuesOML #define glXGetMscRateOML __aglXGetMscRateOML #define glXSwapBuffersMscOML __aglXSwapBuffersMscOML #define glXWaitForMscOML __aglXWaitForMscOML #define glXWaitForSbcOML __aglXWaitForSbcOML #endif #ifdef AGLX_SGIX_hyperpipe #define glXQueryHyperpipeNetworkSGIX __aglXQueryHyperpipeNetworkSGIX #define glXHyperpipeConfigSGIX __aglXHyperpipeConfigSGIX #define glXQueryHyperpipeConfigSGIX __aglXQueryHyperpipeConfigSGIX #define glXDestroyHyperpipeConfigSGIX __aglXDestroyHyperpipeConfigSGIX #define glXBindHyperpipeSGIX __aglXBindHyperpipeSGIX #define glXQueryHyperpipeBestAttribSGIX __aglXQueryHyperpipeBestAttribSGIX #define glXHyperpipeAttribSGIX __aglXHyperpipeAttribSGIX #define glXQueryHyperpipeAttribSGIX __aglXQueryHyperpipeAttribSGIX #endif #ifdef AGLX_MESA_agp_offset #define glXGetAGPOffsetMESA __aglXGetAGPOffsetMESA #endif #ifdef AGLX_EXT_texture_from_pixmap #define glXBindTexImageEXT __aglXBindTexImageEXT #define glXReleaseTextImageEXT __aglXReleaseTextImageEXT #endif #ifdef AGLX_NV_video_out #define glXGetVideoDeviceNV __aglXGetVideoDeviceNV #define glXReleaseVideoDeviceNV __aglXReleaseVideoDeviceNV #define glXBindVideoImageNV __aglXBindVideoImageNV #define glXReleaseVideoImageNV __aglXReleaseVideoImageNV #define glXSendPbufferToVideoNV __aglXSendPbufferToVideoNV #define glXGetVideoInfoNV __aglXGetVideoInfoNV #endif #ifdef AGLX_NV_swap_group #define glXJoinSwapGroupNV __aglXJoinSwapGroupNV #define glXBindSwapBarrierNV __aglXBindSwapBarrierNV #define glXQuerySwapGroupNV __aglXQuerySwapGroupNV #define glXQueryMaxSwapGroupsNV __aglXQueryMaxSwapGroupsNV #define glXQueryFrameCountNV __aglXQueryFrameCountNV #define glXResetFrameCountNV __aglXResetFrameCountNV #endif allegro4.4-4.4.2/addons/allegrogl/include/allegrogl/GLext/glx_ext_api.h000066400000000000000000000205321173507505700257220ustar00rootroot00000000000000#ifdef AGLX_VERSION_1_3 /* GLX 1.3 */ AGL_API(GLXFBConfig *, GetFBConfigs, (Display *, int, int *)) AGL_API(GLXFBConfig *, ChooseFBConfig, (Display *, int, const int *, int *)) AGL_API(int, GetFBConfigAttrib, (Display *, GLXFBConfig, int, int *)) AGL_API(XVisualInfo *, GetVisualFromFBConfig, (Display *, GLXFBConfig)) AGL_API(GLXWindow, CreateWindow, (Display *, GLXFBConfig, Window, const int *)) AGL_API(void, DestroyWindow, (Display *, GLXWindow)) AGL_API(GLXPixmap, CreatePixmap, (Display *, GLXFBConfig, Pixmap, const int *)) AGL_API(void, DestroyPixmap, (Display *, GLXPixmap)) AGL_API(GLXPbuffer, CreatePbuffer, (Display *, GLXFBConfig, const int *)) AGL_API(void, DestroyPbuffer, (Display *, GLXPbuffer)) AGL_API(void, QueryDrawable, (Display *, GLXDrawable, int, unsigned int *)) AGL_API(GLXContext, CreateNewContext, (Display *, GLXFBConfig, int, GLXContext, Bool)) AGL_API(Bool, MakeContextCurrent, (Display *, GLXDrawable, GLXDrawable, GLXContext)) AGL_API(GLXDrawable, GetCurrentReadDrawable, (void)) AGL_API(Display *, GetCurrentDisplay, (void)) AGL_API(int, QueryContext, (Display *, GLXContext, int, int *)) AGL_API(void, SelectEvent, (Display *, GLXDrawable, unsigned long)) AGL_API(void, GetSelectedEvent, (Display *, GLXDrawable, unsigned long *)) #endif #ifdef AGLX_VERSION_1_4 /* GLX 1.4 */ AGL_API(__GLXextFuncPtr, GetProcAddress, (const GLubyte *)) #endif #ifdef AGLX_ARB_get_proc_address /* GLX_ARB_get_proc_address */ AGL_API(__GLXextFuncPtr, GetProcAddressARB, (const GLubyte *)) #endif #ifdef AGLX_SGI_swap_control /* GLX_SGI_swap_control */ AGL_API(int, SwapIntervalSGI, (int)) #endif #ifdef AGLX_SGI_video_sync /* GLX_SGI_video_sync */ AGL_API(int, GetVideoSyncSGI, (unsigned int *)) AGL_API(int, WaitVideoSyncSGI, (int, int, unsigned int *)) #endif #ifdef AGLX_SGI_make_current_read /* GLX_SGI_make_current_read */ AGL_API(Bool, MakeCurrentReadSGI, (Display *, GLXDrawable, GLXDrawable, GLXContext)) AGL_API(GLXDrawable, GetCurrentReadDrawableSGI, (void)) #endif #ifdef AGLX_SGIX_video_source /* GLX_SGIX_video_source */ /* This one needs SGI's header file to be included first */ #ifdef _VL_H_ AGL_API(GLXVideoSourceSGIX, CreateGLXVideoSourceSGIX, (Display *, int, VLServer, VLPath, int, VLNode)) AGL_API(void, DestroyGLXVideoSourceSGIX, (Display *, GLXVideoSourceSGIX)) #endif #endif #ifdef AGLX_EXT_import_context /* GLX_EXT_import_context */ AGL_API(Display *, GetCurrentDisplayEXT, (void)) AGL_API(int, QueryContextInfoEXT, (Display *, GLXContext, int, int *)) AGL_API(GLXContextID, GetContextIDEXT, (const GLXContext)) AGL_API(GLXContext, ImportContextEXT, (Display *, GLXContextID)) AGL_API(void, FreeContextEXT, (Display *, GLXContext)) #endif #ifdef AGLX_SGIX_fbconfig /* GLX_SGIX_fbconfig */ AGL_API(int, GetFBConfigAttribSGIX, (Display *, GLXFBConfigSGIX, int, int *)) AGL_API(GLXFBConfigSGIX *, ChooseFBConfigSGIX, (Display *, int, int *, int *)) AGL_API(GLXPixmap, CreateGLXPixmapWithConfigSGIX, (Display *, GLXFBConfigSGIX, Pixmap)) AGL_API(GLXContext, CreateContextWithConfigSGIX, (Display *, GLXFBConfigSGIX, int, GLXContext, Bool)) AGL_API(XVisualInfo *, GetVisualFromFBConfigSGIX, (Display *, GLXFBConfigSGIX)) AGL_API(GLXFBConfigSGIX, GetFBConfigFromVisualSGIX, (Display *, XVisualInfo *)) #endif #ifdef AGLX_SGIX_pbuffer /* GLX_SGIX_pbuffer */ AGL_API(GLXPbufferSGIX, CreateGLXPbufferSGIX, (Display *, GLXFBConfigSGIX, unsigned int, unsigned int, int *)) AGL_API(void, DestroyGLXPbufferSGIX, (Display *, GLXPbufferSGIX)) AGL_API(int, QueryGLXPbufferSGIX, (Display *, GLXPbufferSGIX, int, unsigned int *)) AGL_API(void, SelectEventSGIX, (Display *, GLXDrawable, unsigned long)) AGL_API(void, GetSelectedEventSGIX, (Display *, GLXDrawable, unsigned long *)) #endif #ifdef AGLX_SGI_cushion /* GLX_SGI_cushion */ AGL_API(void, CushionSGI, (Display *, Window, float)) #endif #ifdef AGLX_SGIX_video_resize /* GLX_SGIX_video_resize */ AGL_API(int, BindChannelToWindowSGIX, (Display *, int, int, Window)) AGL_API(int, ChannelRectSGIX, (Display *, int, int, int, int, int, int)) AGL_API(int, QueryChannelRectSGIX, (Display *, int, int, int *, int *, int *, int *)) AGL_API(int, QueryChannelDeltasSGIX, (Display *, int, int, int *, int *, int *, int *)) AGL_API(int, ChannelRectSyncSGIX, (Display *, int, int, GLenum)) #endif #ifdef AGLX_SGIX_dmbuffer /* GLX_SGIX_dmbuffer */ /* This one needs SGI's header file to be included first */ #ifdef _DM_BUFFER_H_ AGL_API(Bool, AssociateDMPbufferSGIX, (Display *, GLXPbufferSGIX, DMparams *, DMbuffer)) #endif #endif #ifdef AGLX_SGIX_swap_group /* GLX_SGIX_swap_group */ AGL_API(void, JoinSwapGroupSGIX, (Display *, GLXDrawable, GLXDrawable)) #endif #ifdef AGLX_SGIX_swap_barrier /* GLX_SGIX_swap_barrier */ AGL_API(void, BindSwapBarrierSGIX, (Display *, GLXDrawable, int)) AGL_API(Bool, QueryMaxSwapBarriersSGIX, (Display *, int, int *)) #endif #ifdef AGLX_SUN_get_transparent_index /* GLX_SUN_get_transparent_index */ AGL_API(Status, GetTransparentIndexSUN, (Display *, Window, Window, long *)) #endif #ifdef AGLX_MESA_copy_sub_buffer /* GLX_MESA_copy_sub_buffer */ AGL_API(void, CopySubBufferMESA, (Display *, GLXDrawable, int, int, int, int)) #endif #ifdef AGLX_MESA_pixmap_colormap /* GLX_MESA_pixmap_colormap */ AGL_API(GLXPixmap, CreateGLXPixmapMESA, (Display *, XVisualInfo *, Pixmap, Colormap)) #endif #ifdef AGLX_MESA_release_buffers /* GLX_MESA_release_buffers */ AGL_API(Bool, ReleaseBuffersMESA, (Display *, GLXDrawable)) #endif #ifdef AGLX_MESA_set_3dfx_mode /* GLX_MESA_set_3dfx_mode */ AGL_API(Bool, Set3DfxModeMESA, (int)) #endif #ifdef AGLX_OML_sync_control /* GLX_OML_sync_control */ AGL_API(Bool, GetSyncValuesOML, (Display *, GLXDrawable, int64_t *, int64_t *, int64_t *)) AGL_API(Bool, GetMscRateOML, (Display *, GLXDrawable, int32_t *, int32_t *)) AGL_API(int64_t, SwapBuffersMscOML, (Display *, GLXDrawable, int64_t, int64_t, int64_t)) AGL_API(Bool, WaitForMscOML, (Display *, GLXDrawable, int64_t, int64_t, int64_t, int64_t *, int64_t *, int64_t *)) AGL_API(Bool, WaitForSbcOML, (Display *, GLXDrawable, int64_t, int64_t *, int64_t *, int64_t *)) #endif #ifdef AGLX_SGIX_hyperpipe AGL_API(GLXHyperpipeNetworkSGIX *, QueryHyperpipeNetworkSGIX, (Display *dpy, int *npipes)) AGL_API(int, HyperpipeConfigSGIX, (Display *dpy, int networkId, int npipes, GLXHyperpipeConfigSGIX *cfg, int *hpId)) AGL_API(GLXHyperpipeConfigSGIX *, QueryHyperpipeConfigSGIX, (Display *dpy, int hpId, int *npipes)) AGL_API(int, DestroyHyperpipeConfigSGIX, (Display * dpy, int hpId)) AGL_API(int, BindHyperpipeSGIX, (Display *dpy, int hpId)) AGL_API(int, QueryHyperpipeBestAttribSGIX, (Display *dpy, int timeSlice, int attrib, int size, void *attribList, void *returnAttribList)) AGL_API(int, HyperpipeAttribSGIX, (Display *dpy, int timeSlice, int attrib, int size, void *attribList)) AGL_API(int, QueryHyperpipeAttribSGIX, (Display *dpy, int timeSlice, int attrib, int size, void *returnAttribList)) #endif #ifdef AGLX_MESA_agp_offset AGL_API(unsigned int, GetAGPOffsetMESA, (const void *pointer)) #endif #ifdef AGLX_EXT_texture_from_pixmap AGL_API(void, BindTexImageEXT, (Display *dpy, GLXDrawable drawable, int buffer, const int *attrib_list)) AGL_API(void, ReleaseTextImageEXT, (Display *dpy, GLXDrawable drawable, int buffer)) #endif #ifdef AGLX_NV_video_out AGL_API(int, GetVideoDeviceNV, (Display *dpy, int screen, int numVideoDevices, GLXVideoDeviceNV *pVideoDevice)) AGL_API(int, ReleaseVideoDeviceNV, (Display *dpy, int screen, GLXVideoDeviceNV VideoDevice)) AGL_API(int, BindVideoImageNV, (Display *dpy, GLXVideoDeviceNV VideoDevice, GLXPbuffer pbuf, int iVideoBuffer)) AGL_API(int, ReleaseVideoImageNV, (Display *dpy, GLXPbuffer pbuf)) AGL_API(int, SendPbufferToVideoNV, (Display *dpy, GLXPbuffer pbuf, int iBufferType, unsigned long *pulCounterPbuffer, GLboolean bBlock)) AGL_API(int, GetVideoInfoNV, (Display *dpy, int screen, GLXVideoDeviceNV VideoDevice, unsigned long *pulCounterOutputVideo, unsigned long *pulCounterOutputPbuffer)) #endif #ifdef AGLX_NV_swap_group AGL_API(Bool, JoinSwapGroupNV, (Display *dpy, GLXDrawable drawable, GLuint group)) AGL_API(Bool, BindSwapBarrierNV, (Display *dpy, GLuint group, GLuint barrier)) AGL_API(Bool, QuerySwapGroupNV, (Display *dpy, GLXDrawable drawable, GLuint *group, GLuint *barrier)) AGL_API(Bool, QueryMaxSwapGroupsNV, (Display *dpy, int screen, GLuint *maxGroups, GLuint *maxBarriers)) AGL_API(Bool, QueryFrameCountNV, (Display *dpy, int screen, GLuint *count)) AGL_API(Bool, ResetFrameCountNV, (Display *dpy, int screen)) #endif allegro4.4-4.4.2/addons/allegrogl/include/allegrogl/GLext/glx_ext_defs.h000066400000000000000000000360361173507505700261000ustar00rootroot00000000000000/* HACK: Prevent both Mesa and SGI's broken headers from screwing us */ #define __glxext_h_ #include #undef __glxext_h_ #ifndef GLX_VERSION_1_3 #define AGLX_VERSION_1_3 #define GLX_VERSION_1_3 #define GLX_WINDOW_BIT 0x00000001 #define GLX_PIXMAP_BIT 0x00000002 #define GLX_PBUFFER_BIT 0x00000004 #define GLX_RGBA_BIT 0x00000001 #define GLX_COLOR_INDEX_BIT 0x00000002 #define GLX_PBUFFER_CLOBBER_MASK 0x08000000 #define GLX_FRONT_LEFT_BUFFER_BIT 0x00000001 #define GLX_FRONT_RIGHT_BUFFER_BIT 0x00000002 #define GLX_BACK_LEFT_BUFFER_BIT 0x00000004 #define GLX_BACK_RIGHT_BUFFER_BIT 0x00000008 #define GLX_AUX_BUFFERS_BIT 0x00000010 #define GLX_DEPTH_BUFFER_BIT 0x00000020 #define GLX_STENCIL_BUFFER_BIT 0x00000040 #define GLX_ACCUM_BUFFER_BIT 0x00000080 #define GLX_CONFIG_CAVEAT 0x20 #define GLX_X_VISUAL_TYPE 0x22 #define GLX_TRANSPARENT_TYPE 0x23 #define GLX_TRANSPARENT_INDEX_VALUE 0x24 #define GLX_TRANSPARENT_RED_VALUE 0x25 #define GLX_TRANSPARENT_GREEN_VALUE 0x26 #define GLX_TRANSPARENT_BLUE_VALUE 0x27 #define GLX_TRANSPARENT_ALPHA_VALUE 0x28 #define GLX_DONT_CARE 0xFFFFFFFF #define GLX_NONE 0x8000 #define GLX_SLOW_CONFIG 0x8001 #define GLX_TRUE_COLOR 0x8002 #define GLX_DIRECT_COLOR 0x8003 #define GLX_PSEUDO_COLOR 0x8004 #define GLX_STATIC_COLOR 0x8005 #define GLX_GRAY_SCALE 0x8006 #define GLX_STATIC_GRAY 0x8007 #define GLX_TRANSPARENT_RGB 0x8008 #define GLX_TRANSPARENT_INDEX 0x8009 #define GLX_VISUAL_ID 0x800B #define GLX_SCREEN 0x800C #define GLX_NON_CONFORMANT_CONFIG 0x800D #define GLX_DRAWABLE_TYPE 0x8010 #define GLX_RENDER_TYPE 0x8011 #define GLX_X_RENDERABLE 0x8012 #define GLX_FBCONFIG_ID 0x8013 #define GLX_RGBA_TYPE 0x8014 #define GLX_COLOR_INDEX_TYPE 0x8015 #define GLX_MAX_PBUFFER_WIDTH 0x8016 #define GLX_MAX_PBUFFER_HEIGHT 0x8017 #define GLX_MAX_PBUFFER_PIXELS 0x8018 #define GLX_PRESERVED_CONTENTS 0x801B #define GLX_LARGEST_PBUFFER 0x801C #define GLX_WIDTH 0x801D #define GLX_HEIGHT 0x801E #define GLX_EVENT_MASK 0x801F #define GLX_DAMAGED 0x8020 #define GLX_SAVED 0x8021 #define GLX_WINDOW 0x8022 #define GLX_PBUFFER 0x8023 #define GLX_PBUFFER_HEIGHT 0x8040 #define GLX_PBUFFER_WIDTH 0x8041 #endif #ifndef GLX_VERSION_1_4 #define AGLX_VERSION_1_4 #define GLX_VERSION_1_4 #define GLX_SAMPLE_BUFFERS 100000 #define GLX_SAMPLES 100001 #endif #ifndef GLX_ARB_multisample #define AGLX_ARB_multisample #define GLX_ARB_multisample #define GLX_SAMPLE_BUFFERS_ARB 100000 #define GLX_SAMPLES_ARB 100001 #endif #ifndef GLX_SGIS_multisample #define AGLX_SGIS_multisample #define GLX_SGIS_multisample #define GLX_SAMPLE_BUFFERS_SGIS 100000 #define GLX_SAMPLES_SGIS 100001 #endif /* Fix for system headers that define GLX_VERSION_1_4 but do not define * GLX_SAMPLES and GLX_SAMPLE_BUFFERS. */ #ifndef GLX_SAMPLES #define GLX_SAMPLE_BUFFERS 100000 #define GLX_SAMPLES 100001 #endif #ifndef GLX_EXT_visual_info #define AGLX_EXT_visual_info #define GLX_EXT_visual_info #define GLX_X_VISUAL_TYPE_EXT 0x22 #define GLX_TRANSPARENT_TYPE_EXT 0x23 #define GLX_TRANSPARENT_INDEX_VALUE_EXT 0x24 #define GLX_TRANSPARENT_RED_VALUE_EXT 0x25 #define GLX_TRANSPARENT_GREEN_VALUE_EXT 0x26 #define GLX_TRANSPARENT_BLUE_VALUE_EXT 0x27 #define GLX_TRANSPARENT_ALPHA_VALUE_EXT 0x28 #define GLX_NONE_EXT 0x8000 #define GLX_TRUE_COLOR_EXT 0x8002 #define GLX_DIRECT_COLOR_EXT 0x8003 #define GLX_PSEUDO_COLOR_EXT 0x8004 #define GLX_STATIC_COLOR_EXT 0x8005 #define GLX_GRAY_SCALE_EXT 0x8006 #define GLX_STATIC_GRAY_EXT 0x8007 #define GLX_TRANSPARENT_RGB_EXT 0x8008 #define GLX_TRANSPARENT_INDEX_EXT 0x8009 #endif #ifndef GLX_EXT_visual_rating #define AGLX_EXT_visual_rating #define GLX_EXT_visual_rating #define GLX_VISUAL_CAVEAT_EXT 0x20 #define GLX_SLOW_VISUAL_EXT 0x8001 #define GLX_NON_CONFORMANT_VISUAL_EXT 0x800D /* GLX_NONE_EXT */ #endif #ifndef GLX_EXT_import_context #define AGLX_EXT_import_context #define GLX_EXT_import_context #define GLX_SHARE_CONTEXT_EXT 0x800A #define GLX_VISUAL_ID_EXT 0x800B #define GLX_SCREEN_EXT 0x800C #endif #ifndef GLX_SGIX_fbconfig #define AGLX_SGIX_fbconfig #define GLX_SGIX_fbconfig typedef XID GLXFBConfigIDSGIX; typedef struct __GLXFBConfigRec *GLXFBConfigSGIX; #define GLX_WINDOW_BIT_SGIX 0x00000001 #define GLX_PIXMAP_BIT_SGIX 0x00000002 #define GLX_RGBA_BIT_SGIX 0x00000001 #define GLX_COLOR_INDEX_BIT_SGIX 0x00000002 #define GLX_DRAWABLE_TYPE_SGIX 0x8010 #define GLX_RENDER_TYPE_SGIX 0x8011 #define GLX_X_RENDERABLE_SGIX 0x8012 #define GLX_FBCONFIG_ID_SGIX 0x8013 #define GLX_RGBA_TYPE_SGIX 0x8014 #define GLX_COLOR_INDEX_TYPE_SGIX 0x8015 /* GLX_SCREEN_EXT */ #endif #ifndef GLX_SGIX_pbuffer #define AGLX_SGIX_pbuffer #define GLX_SGIX_pbuffer typedef XID GLXPbufferSGIX; typedef struct { int type; unsigned long serial; /* # of last request processed by server */ Bool send_event; /* true if this came for SendEvent request */ Display *display; /* display the event was read from */ GLXDrawable drawable; /* i.d. of Drawable */ int event_type; /* GLX_DAMAGED_SGIX or GLX_SAVED_SGIX */ int draw_type; /* GLX_WINDOW_SGIX or GLX_PBUFFER_SGIX */ unsigned int mask; /* mask indicating which buffers are affected*/ int x, y; int width, height; int count; /* if nonzero, at least this many more */ } GLXBufferClobberEventSGIX; #define GLX_PBUFFER_BIT_SGIX 0x00000004 #define GLX_BUFFER_CLOBBER_MASK_SGIX 0x08000000 #define GLX_FRONT_LEFT_BUFFER_BIT_SGIX 0x00000001 #define GLX_FRONT_RIGHT_BUFFER_BIT_SGIX 0x00000002 #define GLX_BACK_LEFT_BUFFER_BIT_SGIX 0x00000004 #define GLX_BACK_RIGHT_BUFFER_BIT_SGIX 0x00000008 #define GLX_AUX_BUFFERS_BIT_SGIX 0x00000010 #define GLX_DEPTH_BUFFER_BIT_SGIX 0x00000020 #define GLX_STENCIL_BUFFER_BIT_SGIX 0x00000040 #define GLX_ACCUM_BUFFER_BIT_SGIX 0x00000080 #define GLX_SAMPLE_BUFFERS_BIT_SGIX 0x00000100 #define GLX_MAX_PBUFFER_WIDTH_SGIX 0x8016 #define GLX_MAX_PBUFFER_HEIGHT_SGIX 0x8017 #define GLX_MAX_PBUFFER_PIXELS_SGIX 0x8018 #define GLX_OPTIMAL_PBUFFER_WIDTH_SGIX 0x8019 #define GLX_OPTIMAL_PBUFFER_HEIGHT_SGIX 0x801A #define GLX_PRESERVED_CONTENTS_SGIX 0x801B #define GLX_LARGEST_PBUFFER_SGIX 0x801C #define GLX_WIDTH_SGIX 0x801D #define GLX_HEIGHT_SGIX 0x801E #define GLX_EVENT_MASK_SGIX 0x801F #define GLX_DAMAGED_SGIX 0x8020 #define GLX_SAVED_SGIX 0x8021 #define GLX_WINDOW_SGIX 0x8022 #define GLX_PBUFFER_SGIX 0x8023 #endif #ifndef GLX_SGIX_video_resize #define AGLX_SGIX_video_resize #define GLX_SGIX_video_resize #define GLX_SYNC_FRAME_SGIX 0x00000000 #define GLX_SYNC_SWAP_SGIX 0x00000001 #endif #ifndef GLX_SGIX_dmbuffer #define AGLX_SGIX_dmbuffer #define GLX_SGIX_dmbuffer #define GLX_DIGITAL_MEDIA_PBUFFER_SGIX 0x8024 #endif #ifndef GLX_SGIS_blended_overlay #define AGLX_SGIS_blended_overlay #define GLX_SGIS_blended_overlay #define GLX_BLENDED_RGBA_SGIS 0x8025 #endif #ifndef GLX_SGIS_shared_multisample #define AGLX_SGIS_shared_multisample #define GLX_SGIS_shared_multisample #define GLX_MULTISAMPLE_SUB_RECT_WIDTH_SGIS 0x8026 #define GLX_MULTISAMPLE_SUB_RECT_HEIGHT_SGIS 0x8027 #endif #ifndef GLX_3DFX_multisample #define AGLX_3DFX_multisample #define GLX_3DFX_multisample #define GLX_SAMPLE_BUFFERS_3DFX 0x8050 #define GLX_SAMPLES_3DFX 0x8051 #endif #ifndef GLX_MESA_set_3dfx_mode #define AGLX_MESA_set_3dfx_mode #define GLX_MESA_set_3dfx_mode #define GLX_3DFX_WINDOW_MODE_MESA 0x1 #define GLX_3DFX_FULLSCREEN_MODE_MESA 0x2 #endif #ifndef GLX_SGIX_visual_select_group #define AGLX_SGIX_visual_select_group #define GLX_SGIX_visual_select_group #define GLX_VISUAL_SELECT_GROUP_SGIX 0x8028 #endif #ifndef GLX_OML_swap_method #define AGLX_OML_swap_method #define GLX_OML_swap_method #define GLX_SWAP_METHOD_OML 0x8060 #define GLX_SWAP_EXCHANGE_OML 0x8061 #define GLX_SWAP_COPY_OML 0x8062 #define GLX_SWAP_UNDEFINED_OML 0x8063 #endif #ifndef GLX_ARB_get_proc_address #define AGLX_ARB_get_proc_address #define GLX_ARB_get_proc_address typedef void (*__GLXextFuncPtr)(void); #endif #ifndef GLX_SGIX_video_source #define AGLX_SGIX_video_source #define GLX_SGIX_video_source typedef XID GLXVideoSourceSGIX; #endif #ifndef GLX_SGI_video_sync #define GLX_SGI_video_sync #define AGLX_SGI_video_sync #endif #ifndef GLX_SGI_swap_control #define GLX_SGI_swap_control #define AGLX_SGI_swap_control #endif #ifndef GLX_SGI_make_current_read #define GLX_SGI_make_current_read #define AGLX_SGI_make_current_read #endif #ifndef GLX_SGI_cushion #define GLX_SGI_cushion #define AGLX_SGI_cushion #endif #ifndef GLX_SGIX_swap_group #define GLX_SGIX_swap_group #define AGLX_SGIX_swap_group #endif #ifndef GLX_SGIX_swap_barrier #define GLX_SGIX_swap_barrier #define AGLX_SGIX_swap_barrier #endif #ifndef GLX_SUN_get_transparent_index #define GLX_SUN_get_transparent_index #define AGLX_SUN_get_transparent_index #endif #ifndef GLX_MESA_copy_sub_buffer #define GLX_MESA_copy_sub_buffer #define AGLX_MESA_copy_sub_buffer #endif #ifndef GLX_MESA_pixmap_colormap #define GLX_MESA_pixmap_colormap #define AGLX_MESA_pixmap_colormap #endif #ifndef GLX_MESA_release_buffers #define GLX_MESA_release_buffers #define AGLX_MESA_release_buffers #endif #ifndef GLX_OML_sync_control #define GLX_OML_sync_control #define AGLX_OML_sync_control #endif #ifndef GLX_SGIX_hyperpipe #define GLX_SGIX_hyperpipe #define AGLX_SGIX_hyperpipe #define GLX_HYPERPIPE_ID_SGIX 0x8030 #define GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX 80 #define GLX_HYPERPIPE_DISPLAY_PIPE_SGIX 0x00000001 #define GLX_HYPERPIPE_RENDER_PIPE_SGIX 0x00000002 #define GLX_PIPE_RECT_SGIX 0x00000001 #define GLX_PIPE_RECT_LIMITS_SGIX 0x00000002 #define GLX_HYPERPIPE_STEREO_SGIX 0x00000003 #define GLX_HYPERPIPE_PIXEL_AVERAGE_SGIX 0x00000004 #define GLX_BAD_HYPERPIPE_CONFIG_SGIX 91 #define GLX_BAD_HYPERPIPE_SGIX 92 typedef struct { char pipeName[GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX]; int networkId; } GLXHyperpipeNetworkSGIX; typedef struct { char pipeName[GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX]; int channel; unsigned int participationType; int timeSlice; } GLXHyperpipeConfigSGIX; typedef struct { char pipeName[GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX]; int srcXOrigin; int srcYOrigin; int srcWidth; int srcHeight; int destXOrigin; int destYOrigin; int destWidth; int destHeight; } GLXPipeRect; typedef struct { char pipeName[GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX]; int XOrigin; int YOrigin; int maxHeight; int maxWidth; } GLXPipeRectLimits; #endif #ifndef GLX_MESA_agp_offset #define GLX_MESA_agp_offset #define AGLX_MESA_agp_offset #endif #ifndef GLX_ARB_fbconfig_float #define GLX_ARB_fbconfig_float #define AGLX_ARB_fbconfig_float #define GLX_RGBA_FLOAT_TYPE 0x20B9 #define GLX_RGBA_FLOAT_BIT 0x00000004 #endif #ifndef GLX_EXT_framebuffer_sRGB #define GLX_EXT_framebuffer_sRGB #define AGLX_EXT_framebuffer_sRGB #define GLX_FRAMEBUFFER_SRGB_CAPABLE_EXT 0x20B2 #endif #ifndef GLX_EXT_fbconfig_packed_float #define GLX_EXT_fbconfig_packed_float #define AGLX_EXT_fbconfig_packed_float #define GLX_RGBA_UNSIGNED_FLOAT_TYPE_EXT 0x20B1 #define GLX_RGBA_UNSIGNED_FLOAT_BIT_EXT 0x00000008 #endif #ifndef GLX_EXT_texture_from_pixmap #define GLX_EXT_texture_from_pixmap #define AGLX_EXT_texture_from_pixmap #define GLX_BIND_TO_TEXTURE_RGB_EXT 0x20D0 #define GLX_BIND_TO_TEXTURE_RGBA_EXT 0x20D1 #define GLX_BIND_TO_MIPMAP_TEXTURE_EXT 0x20D2 #define GLX_BIND_TO_TEXTURE_TARGETS_EXT 0x20D3 #define GLX_Y_INVERTED_EXT 0x20D4 #define GLX_TEXTURE_FORMAT_EXT 0x20D5 #define GLX_TEXTURE_TARGET_EXT 0x20D6 #define GLX_MIPMAP_TEXTURE_EXT 0x20D7 #define GLX_TEXTURE_FORMAT_NONE_EXT 0x20D8 #define GLX_TEXTURE_FORMAT_RGB_EXT 0x20D9 #define GLX_TEXTURE_FORMAT_RGBA_EXT 0x20DA #define GLX_TEXTURE_1D_BIT_EXT 0x00000001 #define GLX_TEXTURE_2D_BIT_EXT 0x00000002 #define GLX_TEXTURE_RECTANGLE_BIT_EXT 0x00000004 #define GLX_TEXTURE_1D_EXT 0x20DB #define GLX_TEXTURE_2D_EXT 0x20DC #define GLX_TEXTURE_RECTANGLE_EXT 0x20DD #define GLX_FRONT_LEFT_EXT 0x20DE #define GLX_FRONT_RIGHT_EXT 0x20DF #define GLX_BACK_LEFT_EXT 0x20E0 #define GLX_BACK_RIGHT_EXT 0x20E1 #define GLX_FRONT_EXT GLX_FRONT_LEFT_EXT #define GLX_BACK_EXT GLX_BACK_LEFT_EXT #define GLX_AUX0_EXT 0x20E2 #define GLX_AUX1_EXT 0x20E3 #define GLX_AUX2_EXT 0x20E4 #define GLX_AUX3_EXT 0x20E5 #define GLX_AUX4_EXT 0x20E6 #define GLX_AUX5_EXT 0x20E7 #define GLX_AUX6_EXT 0x20E8 #define GLX_AUX7_EXT 0x20E9 #define GLX_AUX8_EXT 0x20EA #define GLX_AUX9_EXT 0x20EB #endif #ifndef GLX_NV_present_video #define GLX_NV_present_video #define AGLX_NV_present_video #define GLX_GLX_NUM_VIDEO_SLOTS_NV 0x20F0 #endif #ifndef GLX_NV_video_out #define GLX_NV_video_out #define AGLX_NV_video_out #define GLX_VIDEO_OUT_COLOR_NV 0x20C3 #define GLX_VIDEO_OUT_ALPHA_NV 0x20C4 #define GLX_VIDEO_OUT_DEPTH_NV 0x20C5 #define GLX_VIDEO_OUT_COLOR_AND_ALPHA_NV 0x20C6 #define GLX_VIDEO_OUT_COLOR_AND_DEPTH_NV 0x20C7 #define GLX_VIDEO_OUT_FRAME_NV 0x20C8 #define GLX_VIDEO_OUT_FIELD_1_NV 0x20C9 #define GLX_VIDEO_OUT_FIELD_2_NV 0x20CA typedef unsigned int GLXVideoDeviceNV; #endif #ifndef GLX_NV_swap_group #define GLX_NV_swap_group #define AGLX_NV_swap_group #endif allegro4.4-4.4.2/addons/allegrogl/include/allegrogl/GLext/glx_ext_list.h000066400000000000000000000025631173507505700261300ustar00rootroot00000000000000AGL_EXT(ARB_get_proc_address, 0) AGL_EXT(ARB_multisample, 0) AGL_EXT(ARB_fbconfig_float, 0) AGL_EXT(EXT_visual_info, 0) AGL_EXT(SGI_swap_control, 0) AGL_EXT(SGI_video_sync, 0) AGL_EXT(SGI_make_current_read, 0) AGL_EXT(SGIX_video_source, 0) AGL_EXT(EXT_visual_rating, 0) AGL_EXT(EXT_import_context, 0) AGL_EXT(SGIX_fbconfig, 0) AGL_EXT(SGIX_pbuffer, 0) AGL_EXT(SGI_cushion, 0) AGL_EXT(SGIX_video_resize, 0) AGL_EXT(SGIX_dm_buffer, 0) AGL_EXT(SGIX_swap_group, 0) AGL_EXT(SGIX_swap_barrier, 0) AGL_EXT(SGIS_color_range, 0) AGL_EXT(SGIS_blended_overlay, 0) AGL_EXT(SUN_get_transparent_index, 0) AGL_EXT(MESA_copy_sub_buffer, 0) AGL_EXT(MESA_pixmap_colormap, 0) AGL_EXT(MESA_release_buffers, 0) AGL_EXT(MESA_set_3dfx_mode, 0) AGL_EXT(SGIX_visual_select_group, 0) AGL_EXT(OML_swap_method, 0) AGL_EXT(OML_sync_control, 0) AGL_EXT(SGIX_hyperpipe, 0) AGL_EXT(MESA_agp_offset, 0) AGL_EXT(EXT_framebuffer_sRGB, 0) AGL_EXT(EXT_packed_float, 0) AGL_EXT(EXT_texture_from_pixmap, 0) AGL_EXT(NV_video_out, 0) AGL_EXT(NV_swap_group, 0) allegro4.4-4.4.2/addons/allegrogl/include/allegrogl/GLext/wgl_ext_alias.h000066400000000000000000000141571173507505700262470ustar00rootroot00000000000000/*Automatically generated by mkalias.sh DO NOT EDIT!*/ /*WGL_ARB_buffer_region*/ #define wglCreateBufferRegionARB __awglCreateBufferRegionARB #define wglDeleteBufferRegionARB __awglDeleteBufferRegionARB #define wglSaveBufferRegionARB __awglSaveBufferRegionARB #define wglRestoreBufferRegionARB __awglRestoreBufferRegionARB /*WGL_ARB_extensions_string*/ #define wglGetExtensionsStringARB __awglGetExtensionsStringARB /*WGL_ARB_pixel_format*/ #define wglGetPixelFormatAttribivARB __awglGetPixelFormatAttribivARB #define wglGetPixelFormatAttribfvARB __awglGetPixelFormatAttribfvARB #define wglChoosePixelFormatARB __awglChoosePixelFormatARB /*WGL_ARB_make_current_read*/ #define wglMakeContextCurrentARB __awglMakeContextCurrentARB #define wglGetCurrentReadDCARB __awglGetCurrentReadDCARB /*WGL_ARB_pbuffer*/ #define wglCreatePbufferARB __awglCreatePbufferARB #define wglGetPbufferDCARB __awglGetPbufferDCARB #define wglReleasePbufferDCARB __awglReleasePbufferDCARB #define wglDestroyPbufferARB __awglDestroyPbufferARB #define wglQueryPbufferARB __awglQueryPbufferARB /*WGL_ARB_render_texture*/ #define wglBindTexImageARB __awglBindTexImageARB #define wglReleaseTexImageARB __awglReleaseTexImageARB #define wglSetPbufferAttribARB __awglSetPbufferAttribARB /*WGL_EXT_display_color_table*/ #define wglCreateDisplayColorTableEXT __awglCreateDisplayColorTableEXT #define wglLoadDisplayColorTableEXT __awglLoadDisplayColorTableEXT #define wglBindDisplayColorTableEXT __awglBindDisplayColorTableEXT #define wglDestroyDisplayColorTableEXT __awglDestroyDisplayColorTableEXT /*WGL_EXT_extensions_string*/ #define wglGetExtensionsStringEXT __awglGetExtensionsStringEXT /*WGL_EXT_make_current_read*/ #define wglMakeContextCurrentEXT __awglMakeContextCurrentEXT #define wglGetCurrentReadDCEXT __awglGetCurrentReadDCEXT /*WGL_EXT_pbuffer*/ #define wglCreatePbufferEXT __awglCreatePbufferEXT #define wglGetPbufferDCEXT __awglGetPbufferDCEXT #define wglReleasePbufferDCEXT __awglReleasePbufferDCEXT #define wglDestroyPbufferEXT __awglDestroyPbufferEXT #define wglQueryPbufferEXT __awglQueryPbufferEXT /*WGL_EXT_pixel_format*/ #define wglGetPixelFormatAttribivEXT __awglGetPixelFormatAttribivEXT #define wglGetPixelFormatAttribfvEXT __awglGetPixelFormatAttribfvEXT #define wglChoosePixelFormatEXT __awglChoosePixelFormatEXT /*WGL_EXT_swap_control*/ #define wglSwapIntervalEXT __awglSwapIntervalEXT #define wglGetSwapIntervalEXT __awglGetSwapIntervalEXT /*WGL_NV_vertex_array_range*/ #define wglAllocateMemoryNV __awglAllocateMemoryNV #define wglFreeMemoryNV __awglFreeMemoryNV /*WGL_OML_sync_control*/ #define wglGetSyncValuesOML __awglGetSyncValuesOML #define wglGetMscRateOML __awglGetMscRateOML #define wglSwapBuffersMscOML __awglSwapBuffersMscOML #define wglSwapLayerBuffersMscOML __awglSwapLayerBuffersMscOML #define wglWaitForMscOML __awglWaitForMscOML #define wglWaitForSbcOML __awglWaitForSbcOML /*WGL_I3D_digital_video_control*/ #define wglGetDigitalVideoParametersI3D __awglGetDigitalVideoParametersI3D #define wglSetDigitalVideoParametersI3D __awglSetDigitalVideoParametersI3D /*WGL_I3D_gamma*/ #define wglGetGammaTableParametersI3D __awglGetGammaTableParametersI3D #define wglSetGammaTableParametersI3D __awglSetGammaTableParametersI3D #define wglGetGammaTableI3D __awglGetGammaTableI3D #define wglSetGammaTableI3D __awglSetGammaTableI3D /*WGL_I3D_genlock*/ #define wglEnableGenlockI3D __awglEnableGenlockI3D #define wglDisableGenlockI3D __awglDisableGenlockI3D #define wglIsEnabledGenlockI3D __awglIsEnabledGenlockI3D #define wglGenlockSourceI3D __awglGenlockSourceI3D #define wglGetGenlockSourceI3D __awglGetGenlockSourceI3D #define wglGenlockSourceEdgeI3D __awglGenlockSourceEdgeI3D #define wglGetGenlockSourceEdgeI3D __awglGetGenlockSourceEdgeI3D #define wglGenlockSampleRateI3D __awglGenlockSampleRateI3D #define wglGetGenlockSampleRateI3D __awglGetGenlockSampleRateI3D #define wglGenlockSourceDelayI3D __awglGenlockSourceDelayI3D #define wglGetGenlockSourceDelayI3D __awglGetGenlockSourceDelayI3D #define wglQueryGenlockMaxSourceDelayI3D __awglQueryGenlockMaxSourceDelayI3D /*WGL_I3D_image_buffer*/ #define wglCreateImageBufferI3D __awglCreateImageBufferI3D #define wglDestroyImageBufferI3D __awglDestroyImageBufferI3D #define wglAssociateImageBufferEventsI3D __awglAssociateImageBufferEventsI3D #define wglReleaseImageBufferEventsI3D __awglReleaseImageBufferEventsI3D /*WGL_I3D_swap_frame_lock*/ #define wglEnableFrameLockI3D __awglEnableFrameLockI3D #define wglDisableFrameLockI3D __awglDisableFrameLockI3D #define wglIsEnabledFrameLockI3D __awglIsEnabledFrameLockI3D #define wglQueryFrameLockMasterI3D __awglQueryFrameLockMasterI3D /*WGL_I3D_swap_frame_usage*/ #define wglGetFrameUsageI3D __awglGetFrameUsageI3D #define wglBeginFrameTrackingI3D __awglBeginFrameTrackingI3D #define wglEndFrameTrackingI3D __awglEndFrameTrackingI3D #define wglQueryFrameTrackingI3D __awglQueryFrameTrackingI3D /*glAddSwapHintRectWIN*/ #define wglAddSwapHintRectWIN __awglAddSwapHintRectWIN /*WGL_NV_present_video*/ #define wglEnumerateVideoDevicesNV __awglEnumerateVideoDevicesNV #define wglBindVideoDeviceNV __awglBindVideoDeviceNV #define wglQueryCurrentContextNV __awglQueryCurrentContextNV /*WGL_NV_video_out*/ #define wglGetVideoDeviceNV __awglGetVideoDeviceNV #define wglReleaseVideoDeviceNV __awglReleaseVideoDeviceNV #define wglBindVideoImageNV __awglBindVideoImageNV #define wglReleaseVideoImageNV __awglReleaseVideoImageNV #define wglSendPbufferToVideoNV __awglSendPbufferToVideoNV #define wglGetVideoInfoNV __awglGetVideoInfoNV /*WGL_NV_swap_group*/ #define wglJoinSwapGroupNV __awglJoinSwapGroupNV #define wglBindSwapBarrierNV __awglBindSwapBarrierNV #define wglQuerySwapGroupNV __awglQuerySwapGroupNV #define wglQueryMaxSwapGroupsNV __awglQueryMaxSwapGroupsNV #define wglQueryFrameCountNV __awglQueryFrameCountNV #define wglResetFrameCountNV __awglResetFrameCountNV /*WGL_NV_gpu_affinity*/ #define wglEnumGpusNV __awglEnumGpusNV #define wglEnumGpuDevicesNV __awglEnumGpuDevicesNV #define wglCreateAffinityDCNV __awglCreateAffinityDCNV #define wglEnumGpusFromAffinityDCNV __awglEnumGpusFromAffinityDCNV #define wglDeleteDCNV __awglDeleteDCNV /*WGL_ARB_create_context*/ #define wglCreateContextAttribsARB __awglCreateContextAttribsARB allegro4.4-4.4.2/addons/allegrogl/include/allegrogl/GLext/wgl_ext_api.h000066400000000000000000000144351173507505700257260ustar00rootroot00000000000000/* WGL_ARB_buffer_region */ AGL_API(HANDLE, CreateBufferRegionARB, (HDC, int, UINT)) AGL_API(VOID, DeleteBufferRegionARB, (HANDLE)) AGL_API(BOOL, SaveBufferRegionARB, (HANDLE, int, int, int, int)) AGL_API(BOOL, RestoreBufferRegionARB, (HANDLE, int, int, int, int, int, int)) /* WGL_ARB_extensions_string */ AGL_API(const char *, GetExtensionsStringARB, (HDC)) /* WGL_ARB_pixel_format */ AGL_API(BOOL, GetPixelFormatAttribivARB, (HDC, int, int, UINT, const int *, int *)) AGL_API(BOOL, GetPixelFormatAttribfvARB, (HDC, int, int, UINT, const int *, FLOAT *)) AGL_API(BOOL, ChoosePixelFormatARB, (HDC, const int *, const FLOAT *, UINT, int *, UINT *)) /* WGL_ARB_make_current_read */ AGL_API(BOOL, MakeContextCurrentARB, (HDC, HDC, HGLRC)) AGL_API(HDC, GetCurrentReadDCARB, (void)) /* WGL_ARB_pbuffer */ AGL_API(HPBUFFERARB, CreatePbufferARB, (HDC, int, int, int, const int *)) AGL_API(HDC, GetPbufferDCARB, (HPBUFFERARB)) AGL_API(int, ReleasePbufferDCARB, (HPBUFFERARB, HDC)) AGL_API(BOOL, DestroyPbufferARB, (HPBUFFERARB)) AGL_API(BOOL, QueryPbufferARB, (HPBUFFERARB, int, int *)) /* WGL_ARB_render_texture */ AGL_API(BOOL, BindTexImageARB, (HPBUFFERARB, int)) AGL_API(BOOL, ReleaseTexImageARB, (HPBUFFERARB, int)) AGL_API(BOOL, SetPbufferAttribARB, (HPBUFFERARB, const int *)) /* WGL_EXT_display_color_table */ AGL_API(GLboolean, CreateDisplayColorTableEXT, (GLushort)) AGL_API(GLboolean, LoadDisplayColorTableEXT, (const GLushort *, GLuint)) AGL_API(GLboolean, BindDisplayColorTableEXT, (GLushort)) AGL_API(VOID, DestroyDisplayColorTableEXT, (GLushort)) /* WGL_EXT_extensions_string */ AGL_API(const char *, GetExtensionsStringEXT, (void)) /* WGL_EXT_make_current_read */ AGL_API(BOOL, MakeContextCurrentEXT, (HDC, HDC, HGLRC)) AGL_API(HDC, GetCurrentReadDCEXT, (void)) /* WGL_EXT_pbuffer */ AGL_API(HPBUFFEREXT, CreatePbufferEXT, (HDC, int, int, int, const int *)) AGL_API(HDC, GetPbufferDCEXT, (HPBUFFEREXT)) AGL_API(int, ReleasePbufferDCEXT, (HPBUFFEREXT, HDC)) AGL_API(BOOL, DestroyPbufferEXT, (HPBUFFEREXT)) AGL_API(BOOL, QueryPbufferEXT, (HPBUFFEREXT, int, int *)) /* WGL_EXT_pixel_format */ AGL_API(BOOL, GetPixelFormatAttribivEXT, (HDC, int, int, UINT, int *, int *)) AGL_API(BOOL, GetPixelFormatAttribfvEXT, (HDC, int, int, UINT, int *, FLOAT *)) AGL_API(BOOL, ChoosePixelFormatEXT, (HDC, const int *, const FLOAT *, UINT, int *, UINT *)) /* WGL_EXT_swap_control */ AGL_API(BOOL, SwapIntervalEXT, (int)) AGL_API(int, GetSwapIntervalEXT, (void)) /* WGL_NV_vertex_array_range */ AGL_API(void*, AllocateMemoryNV, (GLsizei, GLfloat, GLfloat, GLfloat)) AGL_API(void, FreeMemoryNV, (void *)) /* WGL_OML_sync_control */ AGL_API(BOOL, GetSyncValuesOML, (HDC, INT64 *, INT64 *, INT64 *)) AGL_API(BOOL, GetMscRateOML, (HDC, INT32 *, INT32 *)) AGL_API(INT64, SwapBuffersMscOML, (HDC, INT64, INT64, INT64)) AGL_API(INT64, SwapLayerBuffersMscOML, (HDC, int, INT64, INT64, INT64)) AGL_API(BOOL, WaitForMscOML, (HDC, INT64, INT64, INT64, INT64 *, INT64 *, INT64 *)) AGL_API(BOOL, WaitForSbcOML, (HDC, INT64, INT64 *, INT64 *, INT64 *)) /* WGL_I3D_digital_video_control */ AGL_API(BOOL, GetDigitalVideoParametersI3D, (HDC, int, int *)) AGL_API(BOOL, SetDigitalVideoParametersI3D, (HDC, int, const int *)) /* WGL_I3D_gamma */ AGL_API(BOOL, GetGammaTableParametersI3D, (HDC, int, int *)) AGL_API(BOOL, SetGammaTableParametersI3D, (HDC, int, const int *)) AGL_API(BOOL, GetGammaTableI3D, (HDC, int, USHORT *, USHORT *, USHORT *)) AGL_API(BOOL, SetGammaTableI3D, (HDC, int, const USHORT *, const USHORT *, const USHORT *)) /* WGL_I3D_genlock */ AGL_API(BOOL, EnableGenlockI3D, (HDC)) AGL_API(BOOL, DisableGenlockI3D, (HDC)) AGL_API(BOOL, IsEnabledGenlockI3D, (HDC, BOOL *)) AGL_API(BOOL, GenlockSourceI3D, (HDC, UINT)) AGL_API(BOOL, GetGenlockSourceI3D, (HDC, UINT *)) AGL_API(BOOL, GenlockSourceEdgeI3D, (HDC, UINT)) AGL_API(BOOL, GetGenlockSourceEdgeI3D, (HDC, UINT *)) AGL_API(BOOL, GenlockSampleRateI3D, (HDC, UINT)) AGL_API(BOOL, GetGenlockSampleRateI3D, (HDC, UINT *)) AGL_API(BOOL, GenlockSourceDelayI3D, (HDC, UINT)) AGL_API(BOOL, GetGenlockSourceDelayI3D, (HDC, UINT *)) AGL_API(BOOL, QueryGenlockMaxSourceDelayI3D, (HDC, UINT *, UINT *)) /* WGL_I3D_image_buffer */ AGL_API(LPVOID, CreateImageBufferI3D, (HDC, DWORD, UINT)) AGL_API(BOOL, DestroyImageBufferI3D, (HDC, LPVOID)) AGL_API(BOOL, AssociateImageBufferEventsI3D, (HDC, const HANDLE *, const LPVOID *, const DWORD *, UINT)) AGL_API(BOOL, ReleaseImageBufferEventsI3D, (HDC, const LPVOID *, UINT)) /* WGL_I3D_swap_frame_lock */ AGL_API(BOOL, EnableFrameLockI3D, (void)) AGL_API(BOOL, DisableFrameLockI3D, (void)) AGL_API(BOOL, IsEnabledFrameLockI3D, (BOOL *)) AGL_API(BOOL, QueryFrameLockMasterI3D, (BOOL *)) /* WGL_I3D_swap_frame_usage */ AGL_API(BOOL, GetFrameUsageI3D, (float *)) AGL_API(BOOL, BeginFrameTrackingI3D, (void)) AGL_API(BOOL, EndFrameTrackingI3D, (void)) AGL_API(BOOL, QueryFrameTrackingI3D, (DWORD *, DWORD *, float *)) /* glAddSwapHintRectWIN */ AGL_API(void, AddSwapHintRectWIN, (int, int, int, int)) /* WGL_NV_present_video */ AGL_API(int, EnumerateVideoDevicesNV, (HDC, HVIDEOOUTPUTDEVICENV *)) AGL_API(BOOL, BindVideoDeviceNV, (HDC, unsigned int, HVIDEOOUTPUTDEVICENV, const int *)) AGL_API(BOOL, QueryCurrentContextNV, (int, int *)) /* WGL_NV_video_out */ AGL_API(BOOL, GetVideoDeviceNV, (HDC, int, HPVIDEODEV *)) AGL_API(BOOL, ReleaseVideoDeviceNV, (HPVIDEODEV)) AGL_API(BOOL, BindVideoImageNV, (HPVIDEODEV, HPBUFFERARB, int)) AGL_API(BOOL, ReleaseVideoImageNV, (HPBUFFERARB, int)) AGL_API(BOOL, SendPbufferToVideoNV, (HPBUFFERARB, int, unsigned long *, BOOL)) AGL_API(BOOL, GetVideoInfoNV, (HPVIDEODEV, unsigned long *, unsigned long *)) /* WGL_NV_swap_group */ AGL_API(BOOL, JoinSwapGroupNV, (HDC hDC, GLuint group)) AGL_API(BOOL, BindSwapBarrierNV, (GLuint group, GLuint barrier)) AGL_API(BOOL, QuerySwapGroupNV, (HDC hDC, GLuint *group, GLuint *barrier)) AGL_API(BOOL, QueryMaxSwapGroupsNV, (HDC hDC, GLuint *maxGroups, GLuint *maxBarriers)) AGL_API(BOOL, QueryFrameCountNV, (HDC hDC, GLuint *count)) AGL_API(BOOL, ResetFrameCountNV, (HDC hDC)) /* WGL_NV_gpu_affinity */ AGL_API(BOOL, EnumGpusNV, (UINT, HGPUNV *)) AGL_API(BOOL, EnumGpuDevicesNV, (HGPUNV, UINT, PGPU_DEVICE)) AGL_API(HDC, CreateAffinityDCNV, (const HGPUNV *)) AGL_API(BOOL, EnumGpusFromAffinityDCNV, (HDC, UINT, HGPUNV *)) AGL_API(BOOL, DeleteDCNV, (HDC)) /* WGL_ARB_create_context */ AGL_API(HGLRC, CreateContextAttribsARB, (HDC, HGLRC, const int *)) allegro4.4-4.4.2/addons/allegrogl/include/allegrogl/GLext/wgl_ext_defs.h000066400000000000000000000310271173507505700260720ustar00rootroot00000000000000#ifndef WGL_ARB_buffer_region #define WGL_ARB_buffer_region #define WGL_FRONT_COLOR_BUFFER_BIT_ARB 0x00000001 #define WGL_BACK_COLOR_BUFFER_BIT_ARB 0x00000002 #define WGL_DEPTH_BUFFER_BIT_ARB 0x00000004 #define WGL_STENCIL_BUFFER_BIT_ARB 0x00000008 #endif #ifndef WGL_ARB_multisample #define WGL_ARB_multisample #define WGL_SAMPLE_BUFFERS_ARB 0x2041 #define WGL_SAMPLES_ARB 0x2042 #endif #ifndef WGL_ARB_pixel_format #define WGL_ARB_pixel_format #define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000 #define WGL_DRAW_TO_WINDOW_ARB 0x2001 #define WGL_DRAW_TO_BITMAP_ARB 0x2002 #define WGL_ACCELERATION_ARB 0x2003 #define WGL_NEED_PALETTE_ARB 0x2004 #define WGL_NEED_SYSTEM_PALETTE_ARB 0x2005 #define WGL_SWAP_LAYER_BUFFERS_ARB 0x2006 #define WGL_SWAP_METHOD_ARB 0x2007 #define WGL_NUMBER_OVERLAYS_ARB 0x2008 #define WGL_NUMBER_UNDERLAYS_ARB 0x2009 #define WGL_TRANSPARENT_ARB 0x200A #define WGL_TRANSPARENT_RED_VALUE_ARB 0x2037 #define WGL_TRANSPARENT_GREEN_VALUE_ARB 0x2038 #define WGL_TRANSPARENT_BLUE_VALUE_ARB 0x2039 #define WGL_TRANSPARENT_ALPHA_VALUE_ARB 0x203A #define WGL_TRANSPARENT_INDEX_VALUE_ARB 0x203B #define WGL_SHARE_DEPTH_ARB 0x200C #define WGL_SHARE_STENCIL_ARB 0x200D #define WGL_SHARE_ACCUM_ARB 0x200E #define WGL_SUPPORT_GDI_ARB 0x200F #define WGL_SUPPORT_OPENGL_ARB 0x2010 #define WGL_DOUBLE_BUFFER_ARB 0x2011 #define WGL_STEREO_ARB 0x2012 #define WGL_PIXEL_TYPE_ARB 0x2013 #define WGL_COLOR_BITS_ARB 0x2014 #define WGL_RED_BITS_ARB 0x2015 #define WGL_RED_SHIFT_ARB 0x2016 #define WGL_GREEN_BITS_ARB 0x2017 #define WGL_GREEN_SHIFT_ARB 0x2018 #define WGL_BLUE_BITS_ARB 0x2019 #define WGL_BLUE_SHIFT_ARB 0x201A #define WGL_ALPHA_BITS_ARB 0x201B #define WGL_ALPHA_SHIFT_ARB 0x201C #define WGL_ACCUM_BITS_ARB 0x201D #define WGL_ACCUM_RED_BITS_ARB 0x201E #define WGL_ACCUM_GREEN_BITS_ARB 0x201F #define WGL_ACCUM_BLUE_BITS_ARB 0x2020 #define WGL_ACCUM_ALPHA_BITS_ARB 0x2021 #define WGL_DEPTH_BITS_ARB 0x2022 #define WGL_STENCIL_BITS_ARB 0x2023 #define WGL_AUX_BUFFERS_ARB 0x2024 #define WGL_NO_ACCELERATION_ARB 0x2025 #define WGL_GENERIC_ACCELERATION_ARB 0x2026 #define WGL_FULL_ACCELERATION_ARB 0x2027 #define WGL_SWAP_EXCHANGE_ARB 0x2028 #define WGL_SWAP_COPY_ARB 0x2029 #define WGL_SWAP_UNDEFINED_ARB 0x202A #define WGL_TYPE_RGBA_ARB 0x202B #define WGL_TYPE_COLORINDEX_ARB 0x202C #endif #ifndef WGL_ARB_make_current_read #define WGL_ARB_make_current_read #define ERROR_INVALID_PIXEL_TYPE_ARB 0x2043 #define ERROR_INCOMPATIBLE_DEVICE_CONTEXTS_ARB 0x2054 #endif #ifndef WGL_ARB_pbuffer #define WGL_ARB_pbuffer DECLARE_HANDLE(HPBUFFERARB); #define WGL_DRAW_TO_PBUFFER_ARB 0x202D #define WGL_MAX_PBUFFER_PIXELS_ARB 0x202E #define WGL_MAX_PBUFFER_WIDTH_ARB 0x202F #define WGL_MAX_PBUFFER_HEIGHT_ARB 0x2030 #define WGL_PBUFFER_LARGEST_ARB 0x2033 #define WGL_PBUFFER_WIDTH_ARB 0x2034 #define WGL_PBUFFER_HEIGHT_ARB 0x2035 #define WGL_PBUFFER_LOST_ARB 0x2036 #endif #ifndef WGL_ARB_render_texture #define WGL_ARB_render_texture #define WGL_BIND_TO_TEXTURE_RGB_ARB 0x2070 #define WGL_BIND_TO_TEXTURE_RGBA_ARB 0x2071 #define WGL_TEXTURE_FORMAT_ARB 0x2072 #define WGL_TEXTURE_TARGET_ARB 0x2073 #define WGL_MIPMAP_TEXTURE_ARB 0x2074 #define WGL_TEXTURE_RGB_ARB 0x2075 #define WGL_TEXTURE_RGBA_ARB 0x2076 #define WGL_NO_TEXTURE_ARB 0x2077 #define WGL_TEXTURE_CUBE_MAP_ARB 0x2078 #define WGL_TEXTURE_1D_ARB 0x2079 #define WGL_TEXTURE_2D_ARB 0x207A #define WGL_MIPMAP_LEVEL_ARB 0x207B #define WGL_CUBE_MAP_FACE_ARB 0x207C #define WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB 0x207D #define WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB 0x207E #define WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB 0x207F #define WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB 0x2080 #define WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB 0x2081 #define WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB 0x2082 #define WGL_FRONT_LEFT_ARB 0x2083 #define WGL_FRONT_RIGHT_ARB 0x2084 #define WGL_BACK_LEFT_ARB 0x2085 #define WGL_BACK_RIGHT_ARB 0x2086 #define WGL_AUX0_ARB 0x2087 #define WGL_AUX1_ARB 0x2088 #define WGL_AUX2_ARB 0x2089 #define WGL_AUX3_ARB 0x208A #define WGL_AUX4_ARB 0x208B #define WGL_AUX5_ARB 0x208C #define WGL_AUX6_ARB 0x208D #define WGL_AUX7_ARB 0x208E #define WGL_AUX8_ARB 0x208F #define WGL_AUX9_ARB 0x2090 #endif #ifndef WGL_ARB_pixel_format_float #define WGL_ARB_pixel_format_float #define AWGL_ARB_pixel_format_float #define WGL_TYPE_RGBA_FLOAT_ARB 0x21A0 #endif #ifndef WGL_EXT_make_current_read #define WGL_EXT_make_current_read #define ERROR_INVALID_PIXEL_TYPE_EXT 0x2043 #endif #ifndef WGL_EXT_pixel_format #define WGL_EXT_pixel_format #define WGL_NUMBER_PIXEL_FORMATS_EXT 0x2000 #define WGL_DRAW_TO_WINDOW_EXT 0x2001 #define WGL_DRAW_TO_BITMAP_EXT 0x2002 #define WGL_ACCELERATION_EXT 0x2003 #define WGL_NEED_PALETTE_EXT 0x2004 #define WGL_NEED_SYSTEM_PALETTE_EXT 0x2005 #define WGL_SWAP_LAYER_BUFFERS_EXT 0x2006 #define WGL_SWAP_METHOD_EXT 0x2007 #define WGL_NUMBER_OVERLAYS_EXT 0x2008 #define WGL_NUMBER_UNDERLAYS_EXT 0x2009 #define WGL_TRANSPARENT_EXT 0x200A #define WGL_TRANSPARENT_VALUE_EXT 0x200B #define WGL_SHARE_DEPTH_EXT 0x200C #define WGL_SHARE_STENCIL_EXT 0x200D #define WGL_SHARE_ACCUM_EXT 0x200E #define WGL_SUPPORT_GDI_EXT 0x200F #define WGL_SUPPORT_OPENGL_EXT 0x2010 #define WGL_DOUBLE_BUFFER_EXT 0x2011 #define WGL_STEREO_EXT 0x2012 #define WGL_PIXEL_TYPE_EXT 0x2013 #define WGL_COLOR_BITS_EXT 0x2014 #define WGL_RED_BITS_EXT 0x2015 #define WGL_RED_SHIFT_EXT 0x2016 #define WGL_GREEN_BITS_EXT 0x2017 #define WGL_GREEN_SHIFT_EXT 0x2018 #define WGL_BLUE_BITS_EXT 0x2019 #define WGL_BLUE_SHIFT_EXT 0x201A #define WGL_ALPHA_BITS_EXT 0x201B #define WGL_ALPHA_SHIFT_EXT 0x201C #define WGL_ACCUM_BITS_EXT 0x201D #define WGL_ACCUM_RED_BITS_EXT 0x201E #define WGL_ACCUM_GREEN_BITS_EXT 0x201F #define WGL_ACCUM_BLUE_BITS_EXT 0x2020 #define WGL_ACCUM_ALPHA_BITS_EXT 0x2021 #define WGL_DEPTH_BITS_EXT 0x2022 #define WGL_STENCIL_BITS_EXT 0x2023 #define WGL_AUX_BUFFERS_EXT 0x2024 #define WGL_NO_ACCELERATION_EXT 0x2025 #define WGL_GENERIC_ACCELERATION_EXT 0x2026 #define WGL_FULL_ACCELERATION_EXT 0x2027 #define WGL_SWAP_EXCHANGE_EXT 0x2028 #define WGL_SWAP_COPY_EXT 0x2029 #define WGL_SWAP_UNDEFINED_EXT 0x202A #define WGL_TYPE_RGBA_EXT 0x202B #define WGL_TYPE_COLORINDEX_EXT 0x202C #endif #ifndef WGL_EXT_pbuffer #define WGL_EXT_pbuffer DECLARE_HANDLE(HPBUFFEREXT); #define WGL_DRAW_TO_PBUFFER_EXT 0x202D #define WGL_MAX_PBUFFER_PIXELS_EXT 0x202E #define WGL_MAX_PBUFFER_WIDTH_EXT 0x202F #define WGL_MAX_PBUFFER_HEIGHT_EXT 0x2030 #define WGL_OPTIMAL_PBUFFER_WIDTH_EXT 0x2031 #define WGL_OPTIMAL_PBUFFER_HEIGHT_EXT 0x2032 #define WGL_PBUFFER_LARGEST_EXT 0x2033 #define WGL_PBUFFER_WIDTH_EXT 0x2034 #define WGL_PBUFFER_HEIGHT_EXT 0x2035 #endif #ifndef WGL_EXT_depth_float #define WGL_EXT_depth_float #define WGL_DEPTH_FLOAT_EXT 0x2040 #endif #ifndef WGL_3DFX_multisample #define WGL_3DFX_multisample #define WGL_SAMPLE_BUFFERS_3DFX 0x2060 #define WGL_SAMPLES_3DFX 0x2061 #endif #ifndef WGL_EXT_multisample #define WGL_EXT_multisample #define WGL_SAMPLE_BUFFERS_EXT 0x2041 #define WGL_SAMPLES_EXT 0x2042 #endif #ifndef WGL_I3D_digital_video_control #define WGL_I3D_digital_video_control #define WGL_DIGITAL_VIDEO_CURSOR_ALPHA_FRAMEBUFFER_I3D 0x2050 #define WGL_DIGITAL_VIDEO_CURSOR_ALPHA_VALUE_I3D 0x2051 #define WGL_DIGITAL_VIDEO_CURSOR_INCLUDED_I3D 0x2052 #define WGL_DIGITAL_VIDEO_GAMMA_CORRECTED_I3D 0x2053 #endif #ifndef WGL_I3D_gamma #define WGL_I3D_gamma #define WGL_GAMMA_TABLE_SIZE_I3D 0x204E #define WGL_GAMMA_EXCLUDE_DESKTOP_I3D 0x204F #endif #ifndef WGL_I3D_genlock #define WGL_I3D_genlock #define WGL_GENLOCK_SOURCE_MULTIVIEW_I3D 0x2044 #define WGL_GENLOCK_SOURCE_EXTENAL_SYNC_I3D 0x2045 #define WGL_GENLOCK_SOURCE_EXTENAL_FIELD_I3D 0x2046 #define WGL_GENLOCK_SOURCE_EXTENAL_TTL_I3D 0x2047 #define WGL_GENLOCK_SOURCE_DIGITAL_SYNC_I3D 0x2048 #define WGL_GENLOCK_SOURCE_DIGITAL_FIELD_I3D 0x2049 #define WGL_GENLOCK_SOURCE_EDGE_FALLING_I3D 0x204A #define WGL_GENLOCK_SOURCE_EDGE_RISING_I3D 0x204B #define WGL_GENLOCK_SOURCE_EDGE_BOTH_I3D 0x204C #endif #ifndef WGL_I3D_image_buffer #define WGL_I3D_image_buffer #define WGL_IMAGE_BUFFER_MIN_ACCESS_I3D 0x00000001 #define WGL_IMAGE_BUFFER_LOCK_I3D 0x00000002 #endif #ifndef WGL_NV_render_depth_texture #define WGL_NV_render_depth_texture #define WGL_BIND_TO_TEXTURE_DEPTH_NV 0x20A3 #define WGL_BIND_TO_TEXTURE_RECTANGLE_DEPTH_NV 0x20A4 #define WGL_DEPTH_TEXTURE_FORMAT_NV 0x20A5 #define WGL_TEXTURE_DEPTH_COMPONENT_NV 0x20A6 #define WGL_DEPTH_COMPONENT_NV 0x20A7 #endif #ifndef WGL_NV_render_texture_rectangle #define WGL_NV_render_texture_rectangle #define WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV 0x20A0 #define WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV 0x20A1 #define WGL_TEXTURE_RECTANGLE_NV 0x20A2 #endif #ifndef WGL_NV_float_buffer #define WGL_NV_float_buffer #define WGL_FLOAT_COMPONENTS_NV 0x20B0 #define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_R_NV 0x20B1 #define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RG_NV 0x20B2 #define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGB_NV 0x20B3 #define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGBA_NV 0x20B4 #define WGL_TEXTURE_FLOAT_R_NV 0x20B5 #define WGL_TEXTURE_FLOAT_RG_NV 0x20B6 #define WGL_TEXTURE_FLOAT_RGB_NV 0x20B7 #define WGL_TEXTURE_FLOAT_RGBA_NV 0x20B8 #endif #ifndef WGL_3DL_stereo_control #define WGL_3DL_stereo_control #define WGL_STEREO_EMITTER_ENABLE_3DL 0x2055 #define WGL_STEREO_EMITTER_DISABLE_3DL 0x2056 #define WGL_STEREO_POLARITY_NORMAL_3DL 0x2057 #define WGL_STEREO_POLARITY_INVERT_3DL 0x2058 #endif #ifndef WGL_EXT_framebuffer_sRGB #define WGL_EXT_framebuffer_sRGB #define WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT 0x20A9 #endif #ifndef WGL_EXT_pixel_format_packed_float #define WGL_EXT_pixel_format_packed_float #define WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT 0x20A8 #endif #ifndef WGL_WIN_swap_hint #define WGL_WIN_swap_hint #endif #ifndef WGL_NV_present_video #define WGL_NV_present_video DECLARE_HANDLE(HVIDEOOUTPUTDEVICENV); #define WGL_NUM_VIDEO_SLOTS_NV 0x20F0 #endif #ifndef WGL_NV_video_out #define WGL_NV_video_out DECLARE_HANDLE(HPVIDEODEV); #define WGL_BIND_TO_VIDEO_RGB_NV 0x20C0 #define WGL_BIND_TO_VIDEO_RGBA_NV 0x20C1 #define WGL_BIND_TO_VIDEO_RGB_AND_DEPTH_NV 0x20C2 #define WGL_VIDEO_OUT_COLOR_NV 0x20C3 #define WGL_VIDEO_OUT_ALPHA_NV 0x20C4 #define WGL_VIDEO_OUT_DEPTH_NV 0x20C5 #define WGL_VIDEO_OUT_COLOR_AND_ALPHA_NV 0x20C6 #define WGL_VIDEO_OUT_COLOR_AND_DEPTH_NV 0x20C7 #define WGL_VIDEO_OUT_FRAME 0x20C8 #define WGL_VIDEO_OUT_FIELD_1 0x20C9 #define WGL_VIDEO_OUT_FIELD_2 0x20CA #define WGL_VIDEO_OUT_STACKED_FIELDS_1_2 0x20CB #define WGL_VIDEO_OUT_STACKED_FIELDS_2_1 0x20CC #endif #ifndef WGL_NV_swap_group #define WGL_NV_swap_group #endif #ifndef WGL_NV_gpu_affinity #define WGL_NV_gpu_affinity DECLARE_HANDLE(HPGPUNV); DECLARE_HANDLE(HGPUNV); typedef struct _GPU_DEVICE { DWORD cb; CHAR DeviceName[32]; CHAR DeviceString[128]; DWORD Flags; RECT rcVirtualScreen; } GPU_DEVICE, *PGPU_DEVICE; #define WGL_ERROR_INCOMPATIBLE_AFFINITY_MASKS_NV 0x20D0 #define WGL_ERROR_MISSING_AFFINITY_MASK_NV 0x20D1 #endif #ifndef WGL_ARB_create_context #define WGL_ARB_create_context #define WGL_CONTEXT_DEBUG_BIT_ARB 0x0001 #define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002 #define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091 #define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092 #define WGL_CONTEXT_LAYER_PLANE_ARB 0x2093 #define WGL_CONTEXT_FLAGS_ARB 0x2094 #define ERROR_INVALID_VERSION_ARB 0x2095 #endif allegro4.4-4.4.2/addons/allegrogl/include/allegrogl/GLext/wgl_ext_list.h000066400000000000000000000026371173507505700261310ustar00rootroot00000000000000AGL_EXT(ARB_buffer_region, 0) AGL_EXT(ARB_multisample, 0) AGL_EXT(ARB_extensions_string, 0) AGL_EXT(ARB_pixel_format, 0) AGL_EXT(ARB_make_current_read, 0) AGL_EXT(ARB_pbuffer, 0) AGL_EXT(ARB_render_texture, 0) AGL_EXT(ARB_pixel_format_float, 0) AGL_EXT(EXT_display_color_table, 0) AGL_EXT(EXT_extensions_string, 0) AGL_EXT(EXT_make_current_read, 0) AGL_EXT(EXT_pixel_format, 0) AGL_EXT(EXT_pbuffer, 0) AGL_EXT(EXT_swap_control, 0) AGL_EXT(EXT_depth_float, 0) AGL_EXT(EXT_multisample, 0) AGL_EXT(OML_sync_control, 0) AGL_EXT(I3D_digital_video_control, 0) AGL_EXT(I3D_gamma, 0) AGL_EXT(I3D_genlock, 0) AGL_EXT(I3D_image_buffer, 0) AGL_EXT(I3D_swap_frame_lock, 0) AGL_EXT(I3D_swap_frame_usage, 0) AGL_EXT(NV_render_depth_texture, 0) AGL_EXT(NV_render_texture_rectangle, 0) AGL_EXT(ATI_pixel_format_float, 0) AGL_EXT(EXT_framebuffer_sRGB, 0) AGL_EXT(EXT_pixel_format_packed_float,0) AGL_EXT(WIN_swap_hint, 0) /*AGL_EXT(3DL_stereo_control, 0)*/ AGL_EXT(NV_swap_group, 0) AGL_EXT(NV_gpu_affinity, 0) AGL_EXT(NV_video_out, 0) AGL_EXT(NV_present_video, 0) AGL_EXT(ARB_create_context, 0) allegro4.4-4.4.2/addons/allegrogl/include/allegrogl/alleggl_config.h.cmake000066400000000000000000000005721173507505700264110ustar00rootroot00000000000000/* Define if the Mesa generic driver must be built. */ #cmakedefine ALLEGROGL_GENERIC_DRIVER /* Define if glXGetProcAddress must be appended by ARB. */ #cmakedefine ALLEGROGL_GLXGETPROCADDRESSARB /* Define if dynamic linking is supported. */ #cmakedefine ALLEGROGL_HAVE_DYNAMIC_LINK /* Define if XF86VidMode extension is supported. */ #cmakedefine ALLEGROGL_HAVE_XF86VIDMODE allegro4.4-4.4.2/addons/allegrogl/include/allegrogl/gl_ext.h000066400000000000000000000044031173507505700236550ustar00rootroot00000000000000 #ifndef INCLUDE_ALLEGRO_GL_GL_EXT_H_GUARD #define INCLUDE_ALLEGRO_GL_GL_EXT_H_GUARD #ifdef __cplusplus extern "C" { #endif #include "allegrogl/gl_header_detect.h" #include "allegrogl/GLext/gl_ext_defs.h" #ifdef ALLEGRO_WINDOWS #include "allegrogl/GLext/wgl_ext_defs.h" #elif defined ALLEGRO_UNIX #include "allegrogl/GLext/glx_ext_defs.h" #endif /* GL extension types */ #ifndef APIENTRY #define APIENTRY #define APIENTRY_defined #endif #define AGL_API(type, name, args) typedef type (APIENTRY * AGL_##name##_t) args; # include "allegrogl/GLext/gl_ext_api.h" #ifdef ALLEGRO_WINDOWS # include "allegrogl/GLext/wgl_ext_api.h" #elif defined ALLEGRO_UNIX # include "allegrogl/GLext/glx_ext_api.h" #endif #undef AGL_API #ifdef APIENTRY_defined #undef APIENTRY #undef APIENTRY_defined #endif /* GL extension declarations */ #define AGL_API(type, name, args) extern _AGL_DLL AGL_##name##_t __agl##name; # include "allegrogl/GLext/gl_ext_alias.h" # include "allegrogl/GLext/gl_ext_api.h" #undef AGL_API #ifdef ALLEGRO_WINDOWS #define AGL_API(type, name, args) extern _AGL_DLL AGL_##name##_t __awgl##name; # include "allegrogl/GLext/wgl_ext_alias.h" # include "allegrogl/GLext/wgl_ext_api.h" #undef AGL_API #elif defined ALLEGRO_UNIX #define AGL_API(type, name, args) extern AGL_##name##_t __aglX##name; # include "allegrogl/GLext/glx_ext_alias.h" # include "allegrogl/GLext/glx_ext_api.h" #undef AGL_API #endif typedef struct AGL_EXTENSION_LIST_GL { # define AGL_EXT(name, ver) int name; # include "allegrogl/GLext/gl_ext_list.h" # undef AGL_EXT } AGL_EXTENSION_LIST_GL; #ifdef ALLEGRO_UNIX typedef struct AGL_EXTENSION_LIST_GLX { # define AGL_EXT(name, ver) int name; # include "allegrogl/GLext/glx_ext_list.h" # undef AGL_EXT } AGL_EXTENSION_LIST_GLX; #elif defined ALLEGRO_WINDOWS typedef struct AGL_EXTENSION_LIST_WGL { # define AGL_EXT(name, ver) int name; # include "allegrogl/GLext/wgl_ext_list.h" # undef AGL_EXT } AGL_EXTENSION_LIST_WGL; #endif AGL_VAR(AGL_EXTENSION_LIST_GL, allegro_gl_extensions_GL); #ifdef ALLEGRO_UNIX extern AGL_EXTENSION_LIST_GLX allegro_gl_extensions_GLX; #elif defined ALLEGRO_WINDOWS AGL_VAR(AGL_EXTENSION_LIST_WGL, allegro_gl_extensions_WGL); #endif #ifdef __cplusplus } #endif #endif /* INCLUDE_ALLEGRO_GL_GL_EXT_H_GUARD */ allegro4.4-4.4.2/addons/allegrogl/include/allegrogl/gl_header_detect.h000066400000000000000000000005651173507505700256420ustar00rootroot00000000000000#ifndef INCLUDE_ALLEGRO_GL_HEADER_DETECT_H_GUARD #define INCLUDE_ALLEGRO_GL_HEADER_DETECT_H_GUARD /* Some GL headers are broken - they don't define ARB_imaging when they should */ #if defined GL_CONVOLUTION_FORMAT && !defined GL_ARB_imaging #define GL_ARB_imaging 1 #endif /* NV header detection */ #ifdef GL_FORCE_SOFTWARE_NV #define AGL_HEADER_NV 1 #endif #endif allegro4.4-4.4.2/addons/allegrogl/include/allglint.h000066400000000000000000000145231173507505700222350ustar00rootroot00000000000000#ifndef gf_included_allglint_h #define gf_included_allglint_h #include "alleggl.h" struct allegro_gl_info { float version; /* OpenGL version */ int num_texture_units; /* Number of texture units */ int max_texture_size; /* Maximum texture size */ int is_voodoo3_and_under; /* Special cases for Voodoo 1-3 */ int is_voodoo; /* Special cases for Voodoo cards */ int is_matrox_g200; /* Special cases for Matrox G200 boards */ int is_ati_rage_pro; /* Special cases for ATI Rage Pro boards */ int is_ati_radeon_7000; /* Special cases for ATI Radeon 7000 */ int is_ati_r200_chip; /* Special cases for ATI card with chip R200 */ int is_mesa_driver; /* Special cases for MESA */ }; struct allegro_gl_driver { void (*flip) (void); void (*gl_on) (void); void (*gl_off) (void); void (*screen_masked_blit)(struct BITMAP *source, int source_x, int source_y, int dest_x, int dest_y, int width, int height, int flip_dir, int blit_type); }; struct allegro_gl_rgba_size { int r, g, b, a; }; struct allegro_gl_indexed_size { int bpp; }; union allegro_gl_pixel_size { struct allegro_gl_rgba_size rgba; struct allegro_gl_indexed_size indexed; }; struct allegro_gl_display_info { int allegro_format; union allegro_gl_pixel_size pixel_size; int colour_depth; union allegro_gl_pixel_size accum_size; int doublebuffered; int stereo; int aux_buffers; int depth_size; int stencil_size; int w, h, x, y; int r_shift, g_shift, b_shift, a_shift; int packed_pixel_type, packed_pixel_format; int rmethod; /* type of rendering, 0: software; 1: hardware, 2: unknown (X Win) */ int fullscreen; int vidmem_policy; int sample_buffers; int samples; int float_color; int float_depth; }; extern struct allegro_gl_display_info allegro_gl_display_info; extern struct allegro_gl_driver *__allegro_gl_driver; extern struct allegro_gl_info allegro_gl_info; extern int __allegro_gl_required_settings, __allegro_gl_suggested_settings; extern int __allegro_gl_valid_context; extern int __allegro_gl_use_alpha; extern GLint __allegro_gl_texture_read_format[5]; extern GLint __allegro_gl_texture_components[5]; #ifdef ALLEGRO_WINDOWS extern HDC __allegro_gl_hdc; #endif int __allegro_gl_make_power_of_2(int x); void __allegro_gl_reset_scorer (void); int __allegro_gl_score_config (int refnum, struct allegro_gl_display_info *dinfo); int __allegro_gl_best_config (void); void __allegro_gl_set_allegro_image_format (int big_endian); void __allegro_gl_fill_in_info(void); void __allegro_gl_manage_extensions(void); void __allegro_gl_unmanage_extensions(void); void __allegro_gl_print_extensions(const char * extension); int __allegro_gl_look_for_an_extension(AL_CONST char *name, AL_CONST GLubyte * extensions); extern _DRIVER_INFO *(*saved_gfx_drivers) (void); typedef void (* BLIT_BETWEEN_FORMATS_FUNC) (struct BITMAP*, struct BITMAP*, int, int, int, int, int, int); extern BLIT_BETWEEN_FORMATS_FUNC __blit_between_formats8; extern BLIT_BETWEEN_FORMATS_FUNC __blit_between_formats15; extern BLIT_BETWEEN_FORMATS_FUNC __blit_between_formats16; extern BLIT_BETWEEN_FORMATS_FUNC __blit_between_formats24; extern BLIT_BETWEEN_FORMATS_FUNC __blit_between_formats32; void allegro_gl_memory_blit_between_formats(struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height); int allegro_gl_set_mouse_sprite(BITMAP *sprite, int xfocus, int yfocus); int allegro_gl_show_mouse(BITMAP* bmp, int x, int y); void allegro_gl_hide_mouse(void); void allegro_gl_move_mouse(int x, int y); extern char const *__allegro_gl_get_format_description(GLint format); extern int __allegro_gl_get_num_channels(GLenum format); extern GLenum __allegro_gl_get_bitmap_type(BITMAP *bmp, int flags); extern GLenum __allegro_gl_get_bitmap_color_format(BITMAP *bmp, int flags); extern GLint __allegro_gl_get_texture_format_ex(BITMAP *bmp, int flags); extern BITMAP *__allegro_gl_munge_bitmap(int flags, BITMAP *bmp, int x, int y, int w, int h, GLint *type, GLint *format); extern int __allegro_gl_blit_operation; /** \internal * Stores info about a glyph before rendering */ typedef struct AGL_GLYPH { int glyph_num; int x, y, w, h; int offset_x, offset_y, offset_w, offset_h; } AGL_GLYPH; /* +--------------------+ | | | +-------+ | | | glyph | | | +-------+ | | | +--------------------+ < w > < polygon > */ /** \internal * Part of the Allegro font vtable's data field. * Contains all the info needed to manage the 3D font. */ typedef struct FONT_AGL_DATA { int type; int start, end; int is_free_chunk; float scale; GLint format; void *data; AGL_GLYPH *glyph_coords; GLuint list_base; GLuint texture; struct FONT_AGL_DATA *next; int has_alpha; } FONT_AGL_DATA; extern struct FONT_VTABLE *font_vtable_agl; /** \internal * Force the creation of an alpha channel in the texture that will be generated * by allegro_gl_make_texture_ex() */ #define AGL_TEXTURE_FORCE_ALPHA_INTERNAL 0x80000000 /** \internal * Checks for texture validity only. Used by allegro_gl_check_texture() only. */ #define AGL_TEXTURE_CHECK_VALID_INTERNAL 0x40000000 #define AGL_OP_LOGIC_OP 0x0 #define AGL_OP_BLEND 0x1 #define AGL_H_FLIP 1 /* Flag to request horizontal flipping */ #define AGL_V_FLIP 2 /* Flag to request vertical flipping */ #define AGL_REGULAR_BMP 1 /* Must be set for bitmaps that are not sprites. Otherwise the clipping routine will not test if source_x and source_y are legal values */ #define AGL_NO_ROTATION 2 /* If not set the clipping routine is skipped This is needed for pivot_scaled_x() in order not to clip rotated bitmaps (in such a case OpenGL will take care of it) */ #define AGL_LOG(level,str) #ifdef DEBUGMODE #ifdef LOGLEVEL void __allegro_gl_log (int level, const char *str); #undef AGL_LOG #define AGL_LOG(level,str) __allegro_gl_log (level, str) #endif #endif #define GET_ALLEGRO_VERSION() MAKE_VER(ALLEGRO_VERSION, ALLEGRO_SUB_VERSION, \ ALLEGRO_WIP_VERSION) #define MAKE_VER(a, b, c) (((a) << 16) | ((b) << 8) | (c)) #endif allegro4.4-4.4.2/addons/allegrogl/include/glvtable.h000066400000000000000000000055051173507505700222270ustar00rootroot00000000000000#ifndef ALLEGRO_GL_WINDOWS_VTABLE_H #define ALLEGRO_GL_WINDOWS_VTABLE_H #include /* Special structure for holding video bitmaps. This piggy-backs * over the regular BITMAP structure to provide AllegroGL with the * necessary information for maintaining video bitmap over OpenGL */ typedef struct AGL_VIDEO_BITMAP { GLenum target; /* GL_TEXTURE_2D, GL_TEXTURE_RECTANGLE_NV, etc */ BITMAP *memory_copy; /* Memory copy for reading -> subbitmap */ GLuint tex; /* Associated texture number */ GLuint fbo; /* Associated FBO number. */ int x_ofs, y_ofs; /* Offsets of this block */ int width, height; /* Size of the bitmap block */ struct AGL_VIDEO_BITMAP *next; /* Next block, if bitmap is too large to fit in one texture */ GLenum format; /* Pixel data format of the memory copy bitmap. */ GLenum type; /* Pixel data type of the memory copy bitmap. */ } AGL_VIDEO_BITMAP; void __allegro_gl__glvtable_update_vtable (GFX_VTABLE **vtable); BITMAP *allegro_gl_create_video_bitmap(int w, int h); void allegro_gl_drawing_mode(void); void allegro_gl_set_blender_mode(int mode, int r, int g, int b, int a); void allegro_gl_destroy_video_bitmap(BITMAP *bmp); void allegro_gl_created_sub_bitmap(BITMAP *bmp, BITMAP *parent); void split_color(int color, GLubyte *r, GLubyte *g, GLubyte *b, GLubyte *a, int color_depth); void allegro_gl_screen_blit_to_self (struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height); void allegro_gl_video_blit_from_memory(struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height); void allegro_gl_video_blit_to_memory(struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height); void do_masked_blit_screen(struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height, int flip_dir, int blit_type); void allegro_gl_video_blit_to_self(struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height); void allegro_gl_screen_clear_to_color(struct BITMAP *bmp, int color); void allegro_gl_upload_and_display_texture(struct BITMAP *source, int source_x, int source_y, int dest_x, int dest_y, int width, int height, int flip_dir, GLint format, GLint type); void allegro_gl_screen_draw_glyph_ex(struct BITMAP *bmp, AL_CONST struct FONT_GLYPH *glyph, int x, int y, int color, int bg, int flip); void allegro_gl_screen_draw_color_glyph_ex(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y, int color, int bg, int flip); void allegro_gl_screen_polygon3d_f(struct BITMAP *bmp, int type, struct BITMAP *texture, int vc, V3D_f *vtx[]); #endif allegro4.4-4.4.2/addons/allegrogl/misc/000077500000000000000000000000001173507505700175615ustar00rootroot00000000000000allegro4.4-4.4.2/addons/allegrogl/misc/fixver.sh000077500000000000000000000051631173507505700214300ustar00rootroot00000000000000#! /bin/sh # # Shell script to adjust the version numbers in various AllegroGL files. # # Note: if you pass "datestamp" as the only argument, then the version # digits will remain unchanged and the comment will be set to the date. # This is in particular useful for making SVN snapshots. set -e if [ $# -lt 3 -o $# -gt 4 ]; then if [ $# -eq 1 -a $1 == "datestamp" ]; then ver=`grep "^AllegroGL - [0-9]" readme.txt | awk '{ print $3 }'` split_ver=`echo $ver | tr '.' ' '` datestamp=`date '+%Y%m%d'` exec $0 $split_ver $datestamp else echo "Usage: fixver major_num sub_num wip_num [comment]" 1>&2 echo " or: fixver datestamp" 1>&2 echo "Example: fixver 0 4 4 WIP" 1>&2 exit 1 fi fi # get the version and date strings in a nice format if [ $# -eq 3 ]; then verstr="$1.$2.$3" else verstr="$1.$2.$3 ($4)" fi # Patch routine. # Write to $sed_script then call dopatch ... sed_script=fixver.sed tmp_file=fixver.tmp errcode=0 function dopatch() { for x in $* ; do if [ -f $x ]; then echo "Patching $x..." cp $x $tmp_file sed -f $sed_script $tmp_file > $x else echo "WARNING: $x does not exist, skipping" errcode=1 fi done } # patch include/alleggl.h cat > $sed_script << END_OF_SED s#\(define AGL_VERSION.*\)[0-9]#\1$1# s#\(define AGL_SUB_VERSION.*\)[0-9]#\1$2# s#\(define AGL_WIP_VERSION.*\)[0-9]#\1$3# s#\(define AGL_VERSION_STR.*"\)[^"]\+"#\1$verstr"# END_OF_SED dopatch include/alleggl.h # patch readme.txt cat > $sed_script << END_OF_SED s#^\(AllegroGL - \).*#\1$verstr# END_OF_SED dopatch readme.txt # patch make/makefile.ver cat > $sed_script << END_OF_SED s#^\(shared_version =\).*#\1 $1.$2.$3# s#^\(shared_major_minor =\).*#\1 $1.$2# s#^\(shared_major =\).*#\1 $1# END_OF_SED dopatch make/makefile.ver # patch projects/msvc2005/allegrogl/allegrogl.vcproj # There are two instances of Version= in the file. We rely on the fact that # the version we _don't_ want to change contains a comma, and that the # AllegroGL version number doesn't. cat > $sed_script << END_OF_SED s#\(Version="\)[^",]\+"#\1$verstr"# END_OF_SED dopatch projects/msvc2005/allegrogl/allegrogl.vcproj # patch projects/msvc6/allegrogldll/allegrogldll.dsp cat > $sed_script << END_OF_SED s#\(version:\)[0-9][.][0-9]\+#\1$1.$2$3# END_OF_SED dopatch projects/msvc6/allegrogldll/allegrogldll.dsp # patch docs/Doxyfile cat > $sed_script << END_OF_SED s#^\(PROJECT_NUMBER.*=\).*#\1 $verstr# END_OF_SED dopatch docs/Doxyfile # clean up after ourselves rm -f $sed_script $tmp_file echo "Done!" exit $errcode # vim: sts=3 sw=3 et allegro4.4-4.4.2/addons/allegrogl/misc/mkalias.sh000077500000000000000000000007371173507505700215500ustar00rootroot00000000000000#!/bin/sh # This script creates '*_ext_alias.h' from '*_ext_api.h' prefix="glx wgl gl" for name in $prefix; do src="include/allegrogl/GLext/"$name"_ext_api.h" out="include/allegrogl/GLext/"$name"_ext_alias.h" prfx=`echo $name | sed 's/glx/glX/'` cat $src | sed -e '/^[ ]*#/!s/[ ]//g' | awk -F"," "BEGIN{print\"/*Automatically generated by mkalias.sh DO NOT EDIT!*/\"} {if (\$0 ~ /^AGL_API/) printf \"#define $prfx%s __a$prfx%s\n\",\$2,\$2; else print \$0}" > $out done allegro4.4-4.4.2/addons/allegrogl/misc/zipup.py000077500000000000000000000035351173507505700213130ustar00rootroot00000000000000#!/usr/bin/env python import re, sys, os, pysvn, shutil """Simple helper script to create the release .zip, .tar.gz and .tar.bz2.""" def get_version(): """Find the version.""" regexp = re.compile('^#define AGL_VERSION_STR "(.*?)".*$', re.M) match = regexp.search(file("include/alleggl.h").read()) return match.group(1).replace(" ", "_").lower() def get_files(): """Find all SVN files to include in the release.""" client = pysvn.Client() files = client.status(".", recurse = True, get_all = True) return [f.path for f in files if f.is_versioned and f.entry and f.entry.kind == pysvn.node_kind.file] if __name__ == "__main__": version = get_version() dist_path = os.path.join("dist", "alleggl") release_name = "alleggl-" + version print "Copying distribution files.." shutil.rmtree("dist", True) os.mkdir("dist") os.mkdir(dist_path) files = get_files() # copy source files for f in files: target = os.path.join(dist_path, f) target_dir = os.path.dirname(target) try: os.makedirs(target_dir) except OSError: pass shutil.copy2(f, target_dir) # run some stuff so the user will not have to print "Running build scripts.." os.chdir(dist_path) os.system("autoheader") os.system("autoconf") os.system("misc/mkalias.sh") os.system("rm autom4te.cache/ -fr"); # docs print "Generating documentation.." os.chdir("docs") os.system("doxygen > /dev/null") # zip it up print "Generating archives" os.chdir("../..") os.system("zip -r '%s.zip' alleggl > /dev/null" % release_name) os.system("tar czf '%s.tar.gz' alleggl" % release_name) os.system("tar cjf '%s.tar.bz2' alleggl" % release_name) print "All done!" print "Make sure you have used an up-to-date and correctly tagged SVN tree!" allegro4.4-4.4.2/addons/allegrogl/quickstart.txt000066400000000000000000000141371173507505700215670ustar00rootroot00000000000000AllegroGL Quickstart ==================== AllegroGL web site: http://allegrogl.sourceforge.net/ This document: http://allegrogl.sourceforge.net/quickstart.txt Introduction ~~~~~~~~~~~~ You should read the rest of the documentation for details. This guide only contains minimal details on how to set up and use AllegroGL. Requirements ~~~~~~~~~~~~ See readme.txt or the HTML docs for the proper list of requirements. Installation ~~~~~~~~~~~~ From version 0.4.4 onwards, AllegroGL is an addon library for Allegro and the usual way to build it is by following the allegro compilation procedure. It will configure, build and install AllegroGL using default options (a shared release library). However, you if you need a custom compiled library, e.g. with debug symbols or a statically linked one, you can build AllegroGL manually, passing custom build options. See readme.txt or the HTML docs for the full installation procedure. This is just to get you quickly started, so a lot of details are skipped. Unix: Unzip the AllegroGL archive, and run './configure' and `make' from the top directory. That should build the library (in `lib') and example programs (in `examp'). Then run 'make install' to install the header files and the library. Windows: Unzip the archive. First run 'fix msvc' or 'fix mingw32' depending on which compiler you will be using (You'll also need to run vcvars32.bat if you're building with MSVC). Then simply run 'make' followed by 'make install' to build the library and install it. You can use the DEBUGMODE=1 switch if you need to the debug build of the library. DOS: Unzip the archive files MesaLib-4.0.zip wherever you want. Unzip AllegroGL Go to the root directory of AllegroGL type 'fixdjgpp' (without quotes) followed by 'make MESADIR=xxxx' where 'xxx' is the path to the Mesa root directory. Finally type 'make install' to install the library Mac OS X: Unzip the archive. First run './fix.sh macosx', then simply run 'make' and 'sudo make install'. The last step will require your root password. Using AllegroGL: ~~~~~~~~~~~~~~~~ Unix: For the compilation process, all you need to do is #include . You'll need to link with -lagl (or -lagld), `allegro-config --libs` (or `allegro-config --libs debug`), -lGL and -lGLU Windows: For the compilation process, all you need to do is #include . For MSVC: You'll need to link with agl.lib (or agld.lib), alleg.lib (or alld.lib), user32.lib, gdi32.lib, opengl32.lib, and glu32.lib (note: the link order is important). For Mingw: You'll need to link with -lagl (or -lagld), -lalleg (or -lalld), -luser32 -lgdi32 -lopengl32 and -lglu32 (note: the link order is important). DOS: For the compilation process, all you need to do is #include . You'll need to link with -lagl (or -lagld), -lalleg (or -lalld), -lmesagl and -lmesaglu Mac OS X: For the compilation process, all you need to do is #include . You'll need to link with -lagl (or -lagld), `allegro-config --libs` (or `allegro-config --libs debug`), -framework Carbon and -framework OpenGL. There is no support to build from Project Builder or XCode at the moment, sorry. Tests/Examples ~~~~~~~~~~~~~~ You can try out any of the example programs in `examp'. Most of them require mysha.pcx, which you can find in the Allegro example directory. - test.c and tex.c Show a very simple OpenGL program. - extextur.c Shows how to load and display textures. - exalleg.c Shows how to use Allegro code with AllegroGL to read/write to the screen. - exmasked.c Shows how to draw sprites that are masked using OpenGL. - extext.c Shows how to use the extended text and font facilities in AllegroGL. - exalpfnt.c Shows how to use FONTs that are alpha channel only, to save on texture memory. - excamera.c Shows how to use a camera in OpenGL. It uses Allegro to manage a quaternion. - exgui.c Demonstrates the use of the Allegro GUI routines with an OpenGL back-end. - exext.c Shows how to use OpenGL extensions with AllegroGL. - dialog.c Demonstrates switching in between Allegro screen modes and OpenGL. It can also serve as a test application for resolution/color depths. - dumbtest.c Just tests various features of AllegroGL, like mix-matching Allegro's rendering with OpenGL's. - exmipmaps.c Shows how to use a mipmap stack in AllegroGL for texture filtering. - fonttest.c Shows various AllegroGL FONT rendering types. - exblend.c Shows how to use Allegro/AllegroGL API to do accelerated blending of the bitmaps to the screen. Example code: ~~~~~~~~~~~~~ #include #include int main() { /* Initialize both Allegro and AllegroGL */ if (allegro_init()) return 1; if (install_allegro_gl()) return 1; /* Tell Allegro we want to use the keyboard */ install_keyboard(); /* Suggest a good screen mode for OpenGL */ allegro_gl_set(AGL_Z_DEPTH, 8); allegro_gl_set(AGL_COLOR_DEPTH, 16); allegro_gl_set(AGL_SUGGEST, AGL_Z_DEPTH | AGL_COLOR_DEPTH); /* Set the graphics mode */ if (set_gfx_mode(GFX_OPENGL_WINDOWED, 640, 480, 0, 0)) { set_gfx_mode(GFX_TEXT, 0, 0, 0, 0); allegro_message("Unable to set graphic mode\n%s\n", allegro_error); return 1; } /* Clear the screen */ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); /* Set up the view frustum */ glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glFrustum(-1.0, 1.0, -1.0, 1.0, 1, 60.0); /* Draw a quad using OpenGL */ glBegin(GL_QUADS); glColor3ub(255, 255, 255); glVertex3f(-1, -1, -2); glVertex3f( 1, -1, -2); glVertex3f( 1, 1, -2); glVertex3f(-1, 1, -2); glEnd(); /* Flip the backbuffer on screen */ allegro_gl_flip(); /* Wait for the user to press a key */ readkey(); /* Finished. */ return 0; } END_OF_MAIN() Contact information ~~~~~~~~~~~~~~~~~~~ Web page: http://allegrogl.sourceforge.net/ Mailing list: allegrogl-general@lists.sourceforge.net allegro4.4-4.4.2/addons/allegrogl/readme.txt000066400000000000000000000300221173507505700206210ustar00rootroot00000000000000AllegroGL - 0.4.4 ================= README file About the library ~~~~~~~~~~~~~~~~~ The library mostly provides functions to allow you to use OpenGL alongside Allegro -- you use OpenGL for your rendering to the screen, and Allegro for miscellaneous tasks like gathering input, doing timers, getting cross-platform portability, loading data, and drawing your textures. So this library fills the same hole that things like glut do. AllegroGL also automatically exposes most, if not all, OpenGL extensions available to user programs. This means you no longer have to manually load them; extension management is already done for you. License ~~~~~~~ The code is (C) AllegroGL contributors, and double licensed under the GPL and zlib licenses. See gpl.txt or zlib.txt for details. (You can pick whichever one you prefer.) About this document ~~~~~~~~~~~~~~~~~~~ This document contains installation instructions and pointers to other resources such as the FAQ, reference manual, web page and mailing list. General build instructions -------------------------- From version 0.4.4 onwards, AllegroGL is an addon library for Allegro and the usual way to build it is by following the allegro compilation procedure. It will configure, build and install AllegroGL using default options (a shared release library). However, you if you need a custom compiled library, e.g. with debug symbols or a statically linked one, you can build AllegroGL manually, passing custom build options. Requirements: ------------- General requirement: If you are building AllegroGL separatelly (outside Allegro compilation procedure) it will depend on Allegro being successfully built two directories above. Unix: You need an X server which provides the OpenGL/GLX functionality. If you have successfully installed 3D drivers (NVidia, DRI drivers, ...) then OpenGL/GLX libraries are already installed. Otherwise XFree86 4.x has OpenGL/GLX built in. We have also successfully used an earlier version, with development snapshots of Mesa3D 3.2 and GLX extensions. You also need to get the GLU library, preferably the SGI's one (see the Mesa sourceforge webpage - http://Mesa3D.sf.net/ ). If you want to build the generic driver you need Mesa 4.0 or higher (only the "MesaLib" archive is mandatory, the "MesaDemos" one is optionnal). Links to the relevant sites can be found on the AllegroGL web site. Windows/MSVC: MSVC6 or MSVC2005 IDE or GNU make is required for MSVC. Windows/Mingw: If you use Mingw, you'll need the OpenGL header files and libraries. These are normally included with Mingw. In case your copy of Mingw does not have the OpenGL headers, you can grab them here: ftp://ftp.microsoft.com/softlib/mslfiles/opengl95.exe This is a self-extracting archive. You'll also need GNU make (mingw32-make) to compile AllegroGL. DOS: You need DJGPP and Mesa 4.0 http://Mesa3D.sf.net/ for OpenGL rendering (only the "MesaLib" archive is mandatory, the "MesaDemos" one is optionnal). Mac OS X: System version 10.1.x or newer is required to build AllegroGL. Allegro WIP 4.1.11 or newer is also required, as older versions did not support OS X. Unix instructions ----------------- For an optimised build, run `./configure' and `make' from the directory containing this file. This will build the library (in 'lib/unix/') and the examples (in 'examp/'). Use `make install' to install the library and header file. For that part you need write access to /usr/local. If you want to build the generic driver, run `./configure --enable-generic' and `make MESADIR=xxx' where xxx is the path to the Mesa 4.0 directory. This will build both Mesa (GL and GLU) and AllegroGL For a debug build, add `DEBUGMODE=1' on each of the command lines. If you get errors about missing header files or libraries, either for X or GL, see the instructions at the top of `makefile'. Note that you need to have the X development package installed, if you are using Red Hat Linux or Debian GNU/Linux. Mingw/32 instructions --------------------- Mingw 2.0 and higher already come with the OpenGL header files and libraries, so you can skip the next step. If you don't have the OpenGL header files (GL/gl.h) and libraries, you will first need to acquire thrm. These can be obtained from the Microsoft site, or from MSVC. If you obtained the self-extracting archive from the Microsoft site, then run it. Move the produced header files (*.h) into C:\Mingw32\include\GL\ (replace C:\Mingw32 by wherever you happen to have installed Mingw). Ignore the other files, as they are only useful for MSVC. You need to set up your environment if you haven't done that already. Environment variable "PATH" should point to the "bin" directory of Mingw. You can check that by typing "gcc" in the console. It must display something like: "gcc: no input files". If it complains about a unknown command then type "set PATH=%PATH%;C:\Mingw32\bin" (replace C:\Mingw32 by wherever you happen to have installed Mingw). Also, you need to set MINGDIR env. variable. It must point to Mingw instalation directory: "set MINGDIR=C:\Mingw32". You can check that with: "echo %MINGDIR%". You will need to run 'fix mingw32' in the AllegroGL directory to update makefile for Mingw32. Since both Allegro and AllegroGL have native Mingw support I am happy to say that you can build Allegro/AllegroGL programs entirely using free software. For an optimised build, run `make' from the directory containing this file. Use `make install' to install the library and header file. Some versions of Mingw come with `mingw32-make' instead of `make', so you may need to run that instead. For a debug build, do the same but write `DEBUGMODE=1' on each of the command lines; for example, 'make DEBUGMODE=1' and 'make install DEBUGMODE=1'. Add 'STATICLINK=1' to the last two commands to build AllegroGL that can be linked to statically linked allegro. MSVC6/7/8 instructions ------------------ There are two completely different ways of compiling AllegroGL using MSVC. You can use the old-fashion way decribed bellow (similar to building allegro, using a GNU makefile and a command line), or you can locate the project file for your MSVC version in "projects" directory and compile AllegroGL lib and examples with a few mouse clicks. You'll have to manually copy libs and headers to appropiate locations. You can choose between several build configuration, depending against which Allegro library you want AllegroGL to be linked to. These configurations are: _____________________________________________________________ | Configuration name | AGL lib name | Allegro lib name | |-------------------------------------------------------------| | Release | agl.lib | alleg.lib | | DLL Release | agl.lib & agl.dll | alleg.lib | | Static Release | agl_s.lib | alleg_s.lib | | Static Release CRT | agl_s_crt.lib | alleg_s_crt.lib | | Debug | agld.lib | alld.lib | | Static Debug | agld_s.lib | alld_s.lib | ------------------------------------------------------------- All configuration except "DLL Release" produce AllegroGL library that is statically linked to the executable. Instructions for compiling AllegroGL using command line follow. You must have a working copy of GNU Make (useful for building Allegro, anyway). This can be either DJGPP's or Mingw's (recommended). Step 1: The first thing you need to do is find `vcvars32.bat', somewhere in your Visual Studio directories (most probably, it's in 'vc98/bin'). Running this batch file will enable the command line compiler for the current DOS session. If you will use it often, or find that typing 'c:\progra~1\micros~2\vc98\bin\vcvars32.bat' gets annoying after a while, then (under Windows 9X) simply add that command to your autoexec.bat** Note: If at any stage, you get an "Out of Environment space" message, then please see the Allegro FAQ for how to fix this. ** The procedure is different for Windows ME and later. If you're running Windows ME, you'll need to select "Run" off the start menu, then type in "msconfig". Select the environment tab. Add the lines inside vcvars32.bat in there by copy/pasting them. Reboot your computer for the changes to take effect. If you're running Windows 2000/XP (NT?), then open Control Pannel, then the "System" applet, then the "Advanced" tab, and finally the "Environment" button. Add the environment variables as they are in vcvars32.bat. This has to be done manually (yes it's long and painful, please redirect all flames to billg@microsoft.com) You will need to log off and log back in for the changes to take effect. Step 2: Much like making Allegro, to configure AllegroGL for your compiler please run in the command prompt: fix.bat msvc6 - for MSVC 6 and older fix.bat msvc7 - for MSVC 7 (.NET) and 7.1 (.NET 2003) fix.bat msvc8 - for MSVC 8 (.NET 2005) Then type `make' to build the library in optimized mode, then `make install' to install the library and header files in your MSVC directory. For a debugging version, add `DEBUGMODE=1', to the last two command lines. To link against a static runtime libraries, rather than the default dynamic runtime libraries, add STATICRUNTIME=1, to the last two command lines. To link aginst a static version of allegro, add STATICLINK=1, to the last two command lines. If you are using Mingw for GNU make, then you may need to run `mingw32-make' instead of `make'. DOS instructions ---------------- Please note that DOS support is currently in experimental stages. Unzip the archive files MesaLib-4.0.zip wherever you want. Unzip AllegroGL Create the environment variable MESADIR which defines the Mesa sources path : set MESADIR=xxx where 'xxx' is the path to the Mesa root directory Go to the root directory of AllegroGL type 'fix djgpp' (without quotes) followed by 'make'. The GL, GLU and AllegroGL libraries are built. Finally type 'make install' to install the library You're done! You can now use AllegroGL on DOS. Try the example demos... For a debug build, do the same but write `DEBUGMODE=1' on each of the command lines. Note that you can also build : - The GLUT library (based on AMesa, Allegro and Mesa). Type 'make glut' to build it then 'make install-glut' to install it. - The Mesa samples to test both Mesa and GLUT (note that you need to download the MesaDemos archive file to compile mesa samples). Type 'make mesa-samples' (Please note that not all the sample programs will be built. Now, as of Mesa 3.4.2, most demos are for GLUT which has not yet been completely ported to AMesa/Allegro). Mac OS X instructions --------------------- First you will need to run `./fix.sh macosx' in order to prepare the makefile for Mac OS X. Then `make' will build the library (in `lib/macosx') and the examples (in `examp/'). Use `sudo make install' to install the library and the header files; this step will require your system root password and will install into /usr/local. For a debug build, add `DEBUGMODE=1' on `make' and `make install' calls, for example, `make DEBUGMODE=1' and `sudo make install DEBUGMODE=1'. Further documentation --------------------- A reference to the functions and macros available to user programs can be found online at the web site (see below), and is also downloadable from there in various formats. More information ---------------- web site: http://allegrogl.sf.net/ The web site has introductory information, system requirements, downloads, and Allegro patches, along with an online version of the reference manual. mailing list: allegrogl-general@lists.sourceforge.net All the developers are on this mailing list, and most of the discussion here is about future development and bug fixing. General questions about using the library make a welcome change from the hard work of development, so newcomers are very welcome! If you're not subscribed to the list, make this clear when you post, so that people can Cc: their replies to you. Good luck... - The AllegroGL Team! allegro4.4-4.4.2/addons/allegrogl/src/000077500000000000000000000000001173507505700174155ustar00rootroot00000000000000allegro4.4-4.4.2/addons/allegrogl/src/aglf.c000066400000000000000000000444531173507505700205040ustar00rootroot00000000000000/* This code is (C) AllegroGL contributors, and double licensed under * the GPL and zlib licenses. See gpl.txt or zlib.txt for details. */ /** \file aglf.c * \brief Text output and font support in OpenGL. */ #include #include #include #include "allegro.h" #include "alleggl.h" #include "allglint.h" #ifdef ALLEGRO_MACOSX #include #else #include #endif #if defined ALLEGRO_WITH_XWINDOWS && !defined ALLEGROGL_GENERIC_DRIVER #include #include #endif #define PREFIX_E "agl-font ERROR: " static int aglf_font_generation_mode = AGL_FONT_POLYGONS; /* find_range: * Searches a font for a specific character. */ static AL_CONST FONT_AGL_DATA *find_range(AL_CONST FONT_AGL_DATA *f, int c) { while (f) { if ((c >= f->start) && (c < f->end)) return f; f = f->next; } return NULL; } /* allegro_gl_printf(FONT *f, float x, float y, float z, int color, char *format, ...) */ /** Equivalent to: *
 *   r = getr(color);
 *   g = getg(color);
 *   b = getb(color);
 *   a = geta(color);
 *   glColor4f(r, g, b, a);
 *   allegro_gl_printf_ex(f, x, y, z,
 *                        format, ...);
 *  
* * Note that the current primary color is not preserved. */ int allegro_gl_printf(AL_CONST FONT *f, float x, float y, float z, int color, AL_CONST char *format, ...) { #define BUF_SIZE 1024 char buf[BUF_SIZE]; va_list ap; if (!__allegro_gl_valid_context) return 0; /* Get the string */ va_start(ap, format); uvszprintf(buf, BUF_SIZE, format, ap); va_end(ap); #undef BUF_SIZE /* Set color */ { GLubyte c[4]; c[0] = (GLubyte)getr(color); c[1] = (GLubyte)getg(color); c[2] = (GLubyte)getb(color); c[3] = (__allegro_gl_use_alpha && bitmap_color_depth(screen) == 32) ? (GLubyte)geta(color) : 255; glColor4ubv(c); } return allegro_gl_printf_ex(f, x, y, z, buf); } /* allegro_gl_printf_ex(FONT *f, float x, float y, float z, * char *format, ...) */ /** Prints a formatted string (printf style) on the screen. * * \param f Which font to use. * \param x,y,z Coordinates to print at. They specify the top-left * corner of the text position. * \param format The format string (see printf() for details) * * For bitmap fonts, the raster position is set to (x,y), * 'z' is ignored. * The current modelview matrix applies to this code so you may want to * use glLoadIdentity() beforehand. On the other hand, you can use the * modelview matrix to apply transformations to the text. This will only work * with textured or vector (outline) fonts. * This function only accepts AllegroGL formated fonts, as converted by * allegro_gl_convert_allegro_font(), or loaded by * allegro_gl_load_system_font() or allegro_gl_load_system_font_ex(). * * Texturing must be enabled for this function to work with * #AGL_FONT_TYPE_TEXTURED fonts. * * Remember to use glEnable(GL_TEXTURE_2D) to enable texturing. * * The resulting size may not be what you expect. For bitmaped fonts, * there is nothing you can do about this appart changing the font itself. * Textured and Vector fonts are more flexible, in that you can use * glScale to adjust the size of the characters. * * If you need to draw the text without the black backround, we suggest * you set up a proper blending mode prior to drawing the text, such as: *
 *     glEnable(GL_BLEND);
 *     glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_COLOR);
 *   
* * If you want to emulate the Allegro drawing mode (no blending at all), * then you should use the folowing code instead: * *
 *     glDisable(GL_DEPTH_TEST);
 *     glEnable(GL_BLEND);
 *
 *     glBlendFunc(GL_DST_COLOR, GL_ZERO);
 *     allegro_gl_printf();
 *
 *     glBlendFunc(GL_ONE, GL_ONE);
 *     allegro_gl_printf();    // Same as the one above!
 *
 *     glEnable(GL_DEPTH_TEST);
 *   
* * Have a look at NeHe's Tutorial #20 for details on this technique. * http://nehe.gamedev.net/ * * The most flexible way to use fonts, though, is to use alpha textures * based on a greyscale font. Set the texture format to * GL_ALPHA4 or GL_ALPHA8 before creating the * (textured) font. Then you can set the colour and blend modes like so: * *
 *    glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 *    allegro_gl_printf_ex(my_font, x, y, z, "Hi!")
 *  
* * \return The number of characters printed. */ int allegro_gl_printf_ex(AL_CONST FONT *f, float x, float y, float z, AL_CONST char *format, ...) { #define BUF_SIZE 1024 char buf[BUF_SIZE]; va_list ap; AL_CONST FONT_AGL_DATA *range = NULL; int c, pos = 0; int count = 0; AL_CONST FONT_AGL_DATA *d; GLint vert_order, cull_mode; GLint matrix_mode; int restore_rasterpos = 0; GLuint old_texture_bind = 0; GLfloat old_raster_pos[4]; if (!__allegro_gl_valid_context) return 0; /* Check arguments */ if (!format || !f) { TRACE(PREFIX_E "agl_printf: Null parameter\n"); return 0; } if (f->vtable != font_vtable_agl) { TRACE(PREFIX_E "agl_printf: Font parameter isn't of the AGL " "type.\n"); return 0; } d = (AL_CONST FONT_AGL_DATA*)f->data; /* Get the string */ va_start(ap, format); uvszprintf(buf, BUF_SIZE, format, ap); va_end(ap); #undef BUF_SIZE glGetIntegerv(GL_MATRIX_MODE, &matrix_mode); glGetIntegerv(GL_FRONT_FACE, &vert_order); glGetIntegerv(GL_CULL_FACE_MODE, &cull_mode); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glFrontFace(GL_CW); glCullFace(GL_BACK); { GLint temp; glGetIntegerv(GL_TEXTURE_BINDING_2D, &temp); old_texture_bind = (GLuint)temp; } if (d->type == AGL_FONT_TYPE_BITMAP) { glTranslatef(0, 0, -1); glBindTexture(GL_TEXTURE_2D, 0); glGetFloatv(GL_CURRENT_RASTER_POSITION, old_raster_pos); glRasterPos2f(x, y); restore_rasterpos = 1; } else if (d->type == AGL_FONT_TYPE_OUTLINE) { glTranslatef(x, y, z); glBindTexture(GL_TEXTURE_2D, 0); } else if (d->type == AGL_FONT_TYPE_TEXTURED) { glTranslatef(x, y, z); } while ((c = ugetc(buf + pos)) != 0) { pos += ucwidth(c); if ((!range) || (c < range->start) || (c >= range->end)) { /* search for a suitable character range */ range = find_range(d, c); if (!range) { range = find_range(d, (c = '^')); if (!range) continue; } } /* Set up texture */ if (d->type == AGL_FONT_TYPE_TEXTURED) { glBindTexture(GL_TEXTURE_2D, range->texture); } /* draw the character */ c -= range->start; c += range->list_base; glCallList(c); count++; } glPopMatrix(); glMatrixMode(matrix_mode); glFrontFace(vert_order); glCullFace(cull_mode); glBindTexture(GL_TEXTURE_2D, old_texture_bind); if (restore_rasterpos) { glRasterPos4fv(old_raster_pos); } return count; } #ifndef ALLEGROGL_GENERIC_DRIVER #ifdef ALLEGRO_WINDOWS static FONT *win_load_system_font(char *name, int type, int style, int w, int h, float depth, int start, int end) { HFONT hFont; FONT_AGL_DATA *data; FONT *ret; ret = malloc(sizeof(FONT)); if (!ret) { TRACE(PREFIX_E "win_load_system_font: Ran out of memory " "while allocating %i bytes\n", sizeof(FONT)); return NULL; } data = malloc(sizeof(FONT_AGL_DATA)); if (!data) { free(ret); TRACE(PREFIX_E "win_load_system_font: Ran out of memory " "while allocating %i bytes\n", sizeof(FONT_AGL_DATA)); return NULL; } ret->vtable = font_vtable_agl; ret->data = data; data->list_base = glGenLists(end - start); data->start = start; data->end = end; data->next = NULL; data->is_free_chunk = 0; if (type == AGL_FONT_TYPE_BITMAP || type == AGL_FONT_TYPE_DONT_CARE) { HDC dc; hFont = CreateFont( -h, w, 0, 0, (style & AGL_FONT_STYLE_BOLD) ? FW_BOLD : ((style & AGL_FONT_STYLE_BLACK) ? FW_BLACK : FW_NORMAL), ((style & AGL_FONT_STYLE_ITALIC) ? TRUE : FALSE), ((style & AGL_FONT_STYLE_UNDERLINE) ? TRUE : FALSE), ((style & AGL_FONT_STYLE_STRIKEOUT) ? TRUE : FALSE), ANSI_CHARSET, OUT_TT_PRECIS, CLIP_DEFAULT_PRECIS, (style & AGL_FONT_STYLE_ANTI_ALIASED) ? ANTIALIASED_QUALITY : DEFAULT_QUALITY, FF_DONTCARE | DEFAULT_PITCH, name); dc = GetDC(win_get_window()); SelectObject(dc, hFont); wglUseFontBitmaps(dc, start, end - start, data->list_base); data->type = AGL_FONT_TYPE_BITMAP; data->data = NULL; } else if (type == AGL_FONT_TYPE_OUTLINE) { HDC dc; GLYPHMETRICSFLOAT *gmf; gmf = malloc(sizeof(GLYPHMETRICSFLOAT) * (end - start)); memset(gmf, 0, sizeof(GLYPHMETRICSFLOAT) * (end - start)); hFont = CreateFont( -h, w, 0, 0, (style & AGL_FONT_STYLE_BOLD) ? FW_BOLD : ((style & AGL_FONT_STYLE_BLACK) ? FW_BLACK : FW_NORMAL), ((style & AGL_FONT_STYLE_ITALIC) ? TRUE : FALSE), ((style & AGL_FONT_STYLE_UNDERLINE) ? TRUE : FALSE), ((style & AGL_FONT_STYLE_STRIKEOUT) ? TRUE : FALSE), ANSI_CHARSET, OUT_TT_PRECIS, CLIP_DEFAULT_PRECIS, (style & AGL_FONT_STYLE_ANTI_ALIASED) ? ANTIALIASED_QUALITY : DEFAULT_QUALITY, FF_DONTCARE | DEFAULT_PITCH, name); dc = GetDC(win_get_window()); SelectObject(dc, hFont); wglUseFontOutlines(dc, start, end - start, data->list_base, 0.0, depth, (aglf_font_generation_mode == AGL_FONT_POLYGONS) ? WGL_FONT_POLYGONS : WGL_FONT_LINES, gmf); data->type = AGL_FONT_TYPE_OUTLINE; data->data = gmf; } return ret; } #endif #ifdef ALLEGRO_WITH_XWINDOWS static FONT *x_load_system_font(char *name, int type, int style, int w, int h, float depth, int start, int end) { FONT_AGL_DATA *data; FONT *ret; XFontStruct *xfont; ret = malloc(sizeof(FONT)); if (!ret) { TRACE(PREFIX_E "x_load_system_font: Ran out of memory " "while allocating %zi bytes\n", sizeof(FONT)); return NULL; } data = malloc(sizeof(FONT_AGL_DATA)); if (!data) { free(ret); TRACE(PREFIX_E "x_load_system_font: Ran out of memory " "while allocating %zi bytes\n", sizeof(FONT_AGL_DATA)); return NULL; } ret->vtable = font_vtable_agl; ret->data = data; data->list_base = glGenLists(end - start); data->start = start; data->end = end; data->next = NULL; data->is_free_chunk = 0; if (type == AGL_FONT_TYPE_BITMAP || type == AGL_FONT_TYPE_DONT_CARE) { char buf[256], major_type[256], minor_type[2]; usprintf(major_type, "medium"); if (style & AGL_FONT_STYLE_BOLD) usprintf(major_type, "bold"); minor_type[0] = (style & AGL_FONT_STYLE_ITALIC) ? 'i' : 'r'; minor_type[1] = '\0'; usprintf(buf, "-*-%s-%s-%s-normal-*-%i-*-*-*-*-*-*-*", name, major_type, minor_type, h); /* Load the font */ xfont = XLoadQueryFont(_xwin.display, buf); if (!xfont) { free(ret); free(data); TRACE(PREFIX_E "x_load_system_font: Failed to load " "%s\n", buf); return NULL; } glXUseXFont(xfont->fid, start, end - start, data->list_base); data->type = AGL_FONT_TYPE_BITMAP; data->data = NULL; XFreeFont(_xwin.display, xfont); } else { /* Not Yet Implemented */ return NULL; } return ret; } #endif #endif /* ALLEGROGL_GENERIC_DRIVER */ /* void allegro_gl_set_font_generation_mode(int mode) */ /** Set the font generation mode for system fonts. * * \b Note: This function is deprecated and will be removed * in a future version. * * \param mode Can be either #AGL_FONT_POLYGONS or #AGL_FONT_LINES. * for creating polygonal or line characters. * Default is #AGL_FONT_POLYGONS. * * Subsequent calls to allegro_gl_load_system_font() and * allegro_gl_load_system_font_ex() may be affected by this function. * * \deprecated */ void allegro_gl_set_font_generation_mode(int mode) { aglf_font_generation_mode = mode; return; } /* FONT *allegro_gl_load_system_font(char *name, int style, int w, int h) */ /** Short hand for aglf_load_system_font_ex(name, #AGL_FONT_TYPE_OUTLINE, * style, w, h, 0.0f, 32, 256) * * \b Note: This function is deprecated and will be removed * in a future version. * * \deprecated */ FONT *allegro_gl_load_system_font(char *name, int style, int w, int h) { return allegro_gl_load_system_font_ex(name, AGL_FONT_TYPE_OUTLINE, style, w, h, 0.0f, 32, 256); } /* FONT *allegro_gl_load_system_font_ex(char *name, int type, int style, int w, int h, float depth, int start, int end) */ /** Loads a system font. * * \b Note: This function is deprecated and will be removed * in a future version. * * \param name The name of the system font ("Courrier" or "Arial" * for example) * \param type The font type to generate (#AGL_FONT_TYPE_DONT_CARE, * #AGL_FONT_TYPE_BITMAP, #AGL_FONT_TYPE_OUTLINE) * \param style The text decorations of the font to create * (#AGL_FONT_STYLE_ITALIC, etc - can be or'ed together) * \param w,h The size of the font characters that will be created. * \param depth The z-depth of the font. 0.0f is flat, 1.0f is very * thick * \param start,end The range of characters to create from 'start' * (included) to 'end' (excluded) in UTF-8 format * (ANSI only on Windows). * * \note * - In #AGL_FONT_TYPE_OUTLINE type, some system fonts seem to be unresponsive * to the size paramaters (w and h). You cannot depend on either a system * font being present, or the font being what you expect - it is possible to * have two fonts with the same name but with different graphic data. * - BITMAP fonts have no depth. * - The width and height parameters are also system dependent, and may or * may not work with the selected font. * * \return The loaded font, or NULL on error. * * \deprecated */ FONT *allegro_gl_load_system_font_ex(char *name, int type, int style, int w, int h, float depth, int start, int end) { FONT *ret = NULL; if (!__allegro_gl_valid_context) return NULL; if (!name) { TRACE(PREFIX_E "load_system_font: Nameless font\n"); return NULL; } /* Load a system font */ #ifndef ALLEGROGL_GENERIC_DRIVER #ifdef ALLEGRO_WINDOWS ret = win_load_system_font(name, type, style, w, h, depth, start, end); #elif defined ALLEGRO_UNIX XLOCK(); ret = x_load_system_font(name, type, style, w, h, depth, start, end); XUNLOCK(); #else /* Other platform */ #endif #endif return ret; } /** void allegro_gl_destroy_font(FONT *usefont) */ /** Destroys the font. * * \param f The AGL font to be destroyed. * * The allocated memory is freed, as well as any display list, or texture * objects it uses. * * You cannot use that font anymore after calling this function. * It's safe to call this function with a NULL pointer; a note will be * placed in allegro.log if DEBUGMODE was defined. * * If NULL is passed as the font to destroy, then this function returns * immediately. */ void allegro_gl_destroy_font(FONT *f) { FONT_AGL_DATA *data; if (!f) { return; } if (f->vtable != font_vtable_agl) { TRACE(PREFIX_E "destroy_font: Font is not of AGL type\n"); return; } data = f->data; if (!data) { TRACE(PREFIX_E "destroy_font: Font is inconsistent\n"); return; } /* Iterate through every segment of the font */ while (data) { FONT_AGL_DATA *datanext; /* Release all resources taken up by this font */ if (data->type == AGL_FONT_TYPE_BITMAP || data->type == AGL_FONT_TYPE_OUTLINE || data->type == AGL_FONT_TYPE_TEXTURED) { if (__allegro_gl_valid_context) { if (data->list_base) glDeleteLists(data->list_base, data->end - data->start); if (data->texture) glDeleteTextures(1, &data->texture); } } if (data->type == AGL_FONT_TYPE_OUTLINE) { if (data->data) free(data->data); } else if (data->type == AGL_FONT_TYPE_TEXTURED) { if (data->data) destroy_bitmap(data->data); if (data->glyph_coords) free(data->glyph_coords); } else if (data->type == AGL_FONT_TYPE_BITMAP) { if (data->data) { int i; FONT_GLYPH **gl = data->data; for (i = 0; i < data->end - data->start; i++) { if (gl[i]) free(gl[i]); } free(gl); } } datanext = data->next; if (data->is_free_chunk) free(data); data = datanext; } free(f->data); if (f != font) free(f); return; } /* size_t allegro_gl_list_font_textures(FONT *f, GLuint *ids, size_t max_num_id) */ /** List the texture ID of all textures forming the specified font. * * The font specified must be an AllegroGL font. * * If ids is not NULL, then the ID numbers of all textures used by the font * are written to the GLuint array pointed by ids. The size of that array * is specified by the max_num_id parameter. This function will never write * more than 'max_num_id' values in the ids array. * * If f is NULL, then zero is returned and the ids array is never touched. * * If the font does not contain any textures (because it is a bitmap or outline * font, for example), then zero is returned. * * \return Number of texture IDs that make up this font. * * Here are two examples of the use of this function: * *
 *   int num_ids = allegro_gl_list_font_textures(font, NULL, 0);
 *
 *   GLuint *id = malloc(sizeof(GLuint) * num_ids);
 *
 *   if (!id) {
 *     //handle error
 *   }
 *
 *   allegro_gl_list_font_textures(font, id, num_ids);
 *
 *   for (i = 0; i < num_ids; i++) {
 *       glBindTexture(GL_TEXTURE_2D, id[i]);
 *       // Use this texture
 *   }
 *
 *   free(id);
 * 
* *
 *   GLint id[10];  // Reserve a safe number
 *   GLint num_ids = allegro_gl_list_font_textures(font, id, 10);
 * 
*/ size_t allegro_gl_list_font_textures(FONT *f, GLuint *ids, size_t max_num_id) { size_t num_ids = 0; FONT_AGL_DATA *data; if (!f) { return 0; } if (f->vtable != font_vtable_agl) { TRACE(PREFIX_E "list_font_textures: Font is not of AGL type\n"); return 0; } data = f->data; if (!data) { TRACE(PREFIX_E "list_font_textures: Font is inconsistent\n"); return 0; } if (!__allegro_gl_valid_context) { return 0; } /* Iterate through all font segments */ while (data) { if (data->texture) { /* Add the texture ID in the array, if it's not NULL and if there * is room. */ if (ids && num_ids < max_num_id) { ids[num_ids] = data->texture; } num_ids++; } data = data->next; } return num_ids; } allegro4.4-4.4.2/addons/allegrogl/src/alleggl.c000066400000000000000000001107171173507505700211770ustar00rootroot00000000000000/* This code is (C) AllegroGL contributors, and double licensed under * the GPL and zlib licenses. See gpl.txt or zlib.txt for details. */ /** \file alleggl.c * \brief Allegro-OpenGL interfacing * * This sorts out having Allegro and the OpenGL library sharing a window, * and generally cooperating. */ #include #include #include "alleggl.h" #include "allglint.h" #include #ifdef ALLEGRO_MACOSX #include #else #include #endif #define PREFIX_I "agl INFO: " #define PREFIX_E "agl ERROR: " #define PREFIX_L "agl LOG: " /* Structs containing the current driver state */ struct allegro_gl_driver *__allegro_gl_driver = NULL; struct allegro_gl_display_info allegro_gl_display_info; /* Settings required/suggested */ int __allegro_gl_required_settings, __allegro_gl_suggested_settings; /* Valid context state */ int __allegro_gl_valid_context = 0; /* Operation to enable while blitting. */ int __allegro_gl_blit_operation; char allegro_gl_error[AGL_ERROR_SIZE] = EMPTY_STRING; BLIT_BETWEEN_FORMATS_FUNC __blit_between_formats8; BLIT_BETWEEN_FORMATS_FUNC __blit_between_formats15; BLIT_BETWEEN_FORMATS_FUNC __blit_between_formats16; BLIT_BETWEEN_FORMATS_FUNC __blit_between_formats24; BLIT_BETWEEN_FORMATS_FUNC __blit_between_formats32; /** * \ingroup updatemodes * \brief Direct-mode GL `screen' bitmap * * If you draw to this bitmap (using supported Allegro functions) your * calls will be converted into OpenGL equivalents and appear on the * screen (or backbuffer). */ BITMAP *allegro_gl_screen; /* Allegro GFX_DRIVER list handling */ static _DRIVER_INFO our_driver_list[] = { #ifdef GFX_OPENGL_WINDOWED {GFX_OPENGL_WINDOWED, &gfx_allegro_gl_windowed, FALSE}, #endif #ifdef GFX_OPENGL_FULLSCREEN {GFX_OPENGL_FULLSCREEN, &gfx_allegro_gl_fullscreen, FALSE}, #endif {GFX_OPENGL, &gfx_allegro_gl_default, FALSE}, {0, NULL, FALSE} }; static _DRIVER_INFO *our_gfx_drivers(void) { return our_driver_list; } _DRIVER_INFO *(*saved_gfx_drivers) (void) = NULL; static _DRIVER_INFO *list_saved_gfx_drivers(void) { return _gfx_driver_list; } static BITMAP *allegro_gl_default_gfx_init(int w, int h, int vw, int vh, int depth); GFX_DRIVER gfx_allegro_gl_default = { GFX_OPENGL, EMPTY_STRING, EMPTY_STRING, "AllegroGL Default Driver", allegro_gl_default_gfx_init, NULL, NULL, NULL, //_xwin_vsync, NULL, NULL, NULL, NULL, NULL, /* create_video_bitmap */ NULL, NULL, NULL, /* No show/request video bitmaps */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* set_blender_mode */ NULL, /* No fetch_mode_list */ 0, 0, 0, 0, 0, 0, 0, FALSE /* Windowed mode */ }; /** \addtogroup settings Option settings * * OpenGL has many options controlling the way a video mode is selected. * AllegroGL has functions to set particular options, and to state whether * choices are merely preferences or are essential. * * Use allegro_gl_set() to set options. All options are integers. The value * you set is, by default, ignored; you must tell AllegroGL how important it * is. There are three levels of importance: * * - #AGL_DONTCARE: ignore this setting * - #AGL_SUGGEST: this setting is a preference but not essential * - #AGL_REQUIRE: this setting is important, so don't set a mode without it * * To specify the importance of a setting, * set #AGL_REQUIRE, #AGL_SUGGEST, or #AGL_DONTCARE to contain that setting's * flag, e.g. * *
  *   allegro_gl_set(#AGL_COLOR_DEPTH, 16);
  *   allegro_gl_set(#AGL_REQUIRE, #AGL_COLOR_DEPTH);
  * 
* * Rather than calling allegro_gl_set once per setting you want to mark as * required, you can OR the setting flags together: * *
  *   allegro_gl_set(#AGL_REQUIRE, #AGL_COLOR_DEPTH | #AGL_DOUBLEBUFFER);
  * 
* * This has the same effect as marking the two settings separately. * * After saying that you #AGL_REQUIRE a particular setting, you * can still go back and #AGL_DONTCARE or #AGL_SUGGEST it instead -- nothing * happens until you try to set a graphics mode. At that stage, a mode is * set (or set_gfx_mode() returns failure, if not all required settings could * be satisfied), and you can then retrieve the actual settings used by * calling allegro_gl_get(). Note that this is largely untested; some settings * may not be retrieved properly. Please do let us know if you find any! */ /* void allegro_gl_clear_settings(void) */ /** \ingroup settings * Clear the option settings * All settings are set to their default values, and marked as * neither suggested not required. The mode setting routines will * now ignore all of the settings other than those which you * explicitly mark with #AGL_SUGGEST or #AGL_REQUIRE. * * \note You should not rely on what the default values actually * are - don't mark settings unless you've also assigned something * to them. * * \note Some settings are turned on by default. #AGL_DOUBLEBUFFER, * #AGL_RENDERMETHOD and #AGL_FULLSCREEN are set to #AGL_SUGGEST. * * \sa allegro_gl_set(), allegro_gl_get() */ void allegro_gl_clear_settings(void) { memset(&allegro_gl_display_info, 0, sizeof allegro_gl_display_info); __allegro_gl_required_settings = __allegro_gl_suggested_settings = 0; /* Pick sensible defaults */ allegro_gl_display_info.fullscreen = 1; allegro_gl_display_info.rmethod = 1; allegro_gl_display_info.doublebuffered = 1; allegro_gl_display_info.vidmem_policy = AGL_KEEP; __allegro_gl_suggested_settings = AGL_FULLSCREEN | AGL_RENDERMETHOD | AGL_DOUBLEBUFFER; } /* void allegro_gl_set(int option, int value) */ /** \ingroup settings * Sets a configuration option. * Use this routine to configure the framebuffer, *before* * setting a graphics mode. Options are integer constants, and all * values are effectively integers. * * Three of the options are special. #AGL_SUGGEST and * #AGL_REQUIRE are used to mark which of the other options * are merely suggestions and which are absolute requirements. If * the OpenGL implementation can't provide a feature which you mark * with #AGL_REQUIRE, the call to set_gfx_mode will fail. * If you don't mark an option as either suggested or required, that * option will be ignored (#AGL_DONTCARE). * You can OR (|) together the other constants when using one of * these three options to indicate your preferences for several * settings at one time. Selecting an option as one of the suggestion * modes will remove it from the others. For example, if you first set * the color depth to be required, but then decide that you want it to be * suggested instead, then the option will be removed from the required * settings. Setting any option to #AGL_DONTCARE will remove any previous * setting attributed to it, and default values will be used if necessary. * * The remaining options are: *
 *		#AGL_ALLEGRO_FORMAT,
 *		#AGL_RED_DEPTH,
 *		#AGL_GREEN_DEPTH,
 *		#AGL_BLUE_DEPTH,
 *		#AGL_ALPHA_DEPTH,
 *		#AGL_COLOR_DEPTH,
 *		#AGL_ACC_RED_DEPTH,
 *		#AGL_ACC_GREEN_DEPTH,
 *		#AGL_ACC_BLUE_DEPTH,
 *		#AGL_ACC_ALPHA_DEPTH,
 *		#AGL_DOUBLEBUFFER,
 *		#AGL_STEREO,
 *		#AGL_AUX_BUFFERS,
 *		#AGL_Z_DEPTH,
 *		#AGL_STENCIL_DEPTH,
 *		#AGL_WINDOW_X,
 *		#AGL_WINDOW_Y,
 *		#AGL_RENDERMETHOD
 *		#AGL_FULLSCREEN
 *		#AGL_WINDOWED
 *		#AGL_VIDEO_MEMORY_POLICY
 *		#AGL_SAMPLE_BUFFERS
 *		#AGL_SAMPLES
 *		#AGL_FLOAT_COLOR
 *		#AGL_FLOAT_Z
 *   
* * \param option Selects which option to change. * \param value The new option value. * * \b Example: *
 *    allegro_gl_set(#AGL_COLOR_DEPTH, 32);
 *    allegro_gl_set(#AGL_RENDERMETHOD, 1);
 *    allegro_gl_set(#AGL_REQUIRE, #AGL_COLOR_DEPTH | #AGL_RENDERMETHOD);
 *  
* * \sa allegro_gl_get(), allegro_gl_clear_settings() */ void allegro_gl_set(int option, int value) { switch (option) { /* Options stating importance of other options */ case AGL_REQUIRE: __allegro_gl_required_settings |= value; __allegro_gl_suggested_settings &= ~value; break; case AGL_SUGGEST: __allegro_gl_suggested_settings |= value; __allegro_gl_required_settings &= ~value; break; case AGL_DONTCARE: __allegro_gl_required_settings &= ~value; __allegro_gl_suggested_settings &= ~value; break; /* Options configuring the mode set */ case AGL_ALLEGRO_FORMAT: allegro_gl_display_info.allegro_format = value; break; case AGL_RED_DEPTH: allegro_gl_display_info.pixel_size.rgba.r = value; break; case AGL_GREEN_DEPTH: allegro_gl_display_info.pixel_size.rgba.g = value; break; case AGL_BLUE_DEPTH: allegro_gl_display_info.pixel_size.rgba.b = value; break; case AGL_ALPHA_DEPTH: allegro_gl_display_info.pixel_size.rgba.a = value; break; case AGL_COLOR_DEPTH: switch (value) { case 8: allegro_gl_set(AGL_RED_DEPTH, 3); allegro_gl_set(AGL_GREEN_DEPTH, 3); allegro_gl_set(AGL_BLUE_DEPTH, 2); allegro_gl_set(AGL_ALPHA_DEPTH, 0); break; case 15: allegro_gl_set(AGL_RED_DEPTH, 5); allegro_gl_set(AGL_GREEN_DEPTH, 5); allegro_gl_set(AGL_BLUE_DEPTH, 5); allegro_gl_set(AGL_ALPHA_DEPTH, 1); break; case 16: allegro_gl_set(AGL_RED_DEPTH, 5); allegro_gl_set(AGL_GREEN_DEPTH, 6); allegro_gl_set(AGL_BLUE_DEPTH, 5); allegro_gl_set(AGL_ALPHA_DEPTH, 0); break; case 24: case 32: allegro_gl_set(AGL_RED_DEPTH, 8); allegro_gl_set(AGL_GREEN_DEPTH, 8); allegro_gl_set(AGL_BLUE_DEPTH, 8); allegro_gl_set(AGL_ALPHA_DEPTH, value-24); break; } allegro_gl_display_info.colour_depth = value; break; case AGL_ACC_RED_DEPTH: allegro_gl_display_info.accum_size.rgba.r = value; break; case AGL_ACC_GREEN_DEPTH: allegro_gl_display_info.accum_size.rgba.g = value; break; case AGL_ACC_BLUE_DEPTH: allegro_gl_display_info.accum_size.rgba.b = value; break; case AGL_ACC_ALPHA_DEPTH: allegro_gl_display_info.accum_size.rgba.a = value; break; case AGL_DOUBLEBUFFER: allegro_gl_display_info.doublebuffered = value; break; case AGL_STEREO: allegro_gl_display_info.stereo = value; break; case AGL_AUX_BUFFERS: allegro_gl_display_info.aux_buffers = value; break; case AGL_Z_DEPTH: allegro_gl_display_info.depth_size = value; break; case AGL_STENCIL_DEPTH: allegro_gl_display_info.stencil_size = value; break; case AGL_WINDOW_X: allegro_gl_display_info.x = value; break; case AGL_WINDOW_Y: allegro_gl_display_info.y = value; break; case AGL_RENDERMETHOD: allegro_gl_display_info.rmethod = value; break; case AGL_FULLSCREEN: allegro_gl_display_info.fullscreen = value; break; case AGL_WINDOWED: allegro_gl_display_info.fullscreen = !value; break; case AGL_VIDEO_MEMORY_POLICY: if ((value == AGL_KEEP) || (value == AGL_RELEASE)) allegro_gl_display_info.vidmem_policy = value; break; case AGL_SAMPLE_BUFFERS: allegro_gl_display_info.sample_buffers = value; break; case AGL_SAMPLES: allegro_gl_display_info.samples = value; break; case AGL_FLOAT_COLOR: allegro_gl_display_info.float_color = value; break; case AGL_FLOAT_Z: allegro_gl_display_info.float_depth = value; break; } } /** \ingroup settings * Reads the setting of a configuration option. * * This routine can be used to read back the configuration of * the framebuffer. You can do this either before setting a graphics * mode to check what configuration you are requesting, or afterwards * to find out what settings were actually used. * For a list of option constants, see documentation for allegro_gl_set(). * * \param option The option to have its value returned. * * \return The value of the option selected by the parameter, * or -1 if the option is invalid. * * \sa allegro_gl_set(), allegro_gl_clear_settings() */ int allegro_gl_get(int option) { switch (option) { /* Options stating importance of other options */ case AGL_REQUIRE: return __allegro_gl_required_settings; case AGL_SUGGEST: return __allegro_gl_suggested_settings; case AGL_DONTCARE: return ~0 & ~(__allegro_gl_required_settings | __allegro_gl_suggested_settings); /* Options configuring the mode set */ case AGL_ALLEGRO_FORMAT: return allegro_gl_display_info.allegro_format; case AGL_RED_DEPTH: return allegro_gl_display_info.pixel_size.rgba.r; case AGL_GREEN_DEPTH: return allegro_gl_display_info.pixel_size.rgba.g; case AGL_BLUE_DEPTH: return allegro_gl_display_info.pixel_size.rgba.b; case AGL_ALPHA_DEPTH: return allegro_gl_display_info.pixel_size.rgba.a; case AGL_COLOR_DEPTH: return allegro_gl_display_info.pixel_size.rgba.r + allegro_gl_display_info.pixel_size.rgba.g + allegro_gl_display_info.pixel_size.rgba.b + allegro_gl_display_info.pixel_size.rgba.a; case AGL_ACC_RED_DEPTH: return allegro_gl_display_info.accum_size.rgba.r; case AGL_ACC_GREEN_DEPTH: return allegro_gl_display_info.accum_size.rgba.g; case AGL_ACC_BLUE_DEPTH: return allegro_gl_display_info.accum_size.rgba.b; case AGL_ACC_ALPHA_DEPTH: return allegro_gl_display_info.accum_size.rgba.a; case AGL_DOUBLEBUFFER: return allegro_gl_display_info.doublebuffered; case AGL_STEREO: return allegro_gl_display_info.stereo; case AGL_AUX_BUFFERS: return allegro_gl_display_info.aux_buffers; case AGL_Z_DEPTH: return allegro_gl_display_info.depth_size; case AGL_STENCIL_DEPTH: return allegro_gl_display_info.stencil_size; case AGL_WINDOW_X: return allegro_gl_display_info.x; case AGL_WINDOW_Y: return allegro_gl_display_info.y; case AGL_FULLSCREEN: return allegro_gl_display_info.fullscreen; case AGL_WINDOWED: return !allegro_gl_display_info.fullscreen; case AGL_VIDEO_MEMORY_POLICY: return allegro_gl_display_info.vidmem_policy; case AGL_SAMPLE_BUFFERS: return allegro_gl_display_info.sample_buffers; case AGL_SAMPLES: return allegro_gl_display_info.samples; case AGL_FLOAT_COLOR: return allegro_gl_display_info.float_color; case AGL_FLOAT_Z: return allegro_gl_display_info.float_depth; } return -1; } /* Builds a string corresponding to the options set in 'opt' * and writes in the config file */ static void build_settings(int opt, char *section, char *name) { char buf[2048]; usetc(buf, 0); if (opt & AGL_ALLEGRO_FORMAT) ustrcat(buf, "allegro_format "); if (opt & AGL_RED_DEPTH) ustrcat(buf, "red_depth "); if (opt & AGL_GREEN_DEPTH) ustrcat(buf, "green_depth "); if (opt & AGL_BLUE_DEPTH) ustrcat(buf, "blue_depth "); if (opt & AGL_ALPHA_DEPTH) ustrcat(buf, "alpha_depth "); if (opt & AGL_COLOR_DEPTH) ustrcat(buf, "color_depth "); if (opt & AGL_ACC_RED_DEPTH) ustrcat(buf, "accum_red_depth "); if (opt & AGL_ACC_GREEN_DEPTH) ustrcat(buf, "accum_green_depth "); if (opt & AGL_ACC_BLUE_DEPTH) ustrcat(buf, "accum_blue_depth "); if (opt & AGL_ACC_ALPHA_DEPTH) ustrcat(buf, "accum_alpha_depth "); if (opt & AGL_DOUBLEBUFFER) ustrcat(buf, "double_buffer "); if (opt & AGL_STEREO) ustrcat(buf, "stereo_display "); if (opt & AGL_AUX_BUFFERS) ustrcat(buf, "aux_buffers "); if (opt & AGL_Z_DEPTH) ustrcat(buf, "z_depth "); if (opt & AGL_STENCIL_DEPTH) ustrcat(buf, "stencil_depth "); if (opt & AGL_WINDOW_X) ustrcat(buf, "window_x "); if (opt & AGL_WINDOW_Y) ustrcat(buf, "window_y "); if (opt & AGL_FULLSCREEN) ustrcat(buf, "fullscreen "); if (opt & AGL_WINDOWED) ustrcat(buf, "windowed "); if (opt & AGL_VIDEO_MEMORY_POLICY) ustrcat(buf, "video_memory_policy "); if (opt & AGL_SAMPLE_BUFFERS) ustrcat(buf, "sample_buffers "); if (opt & AGL_SAMPLES) ustrcat(buf, "samples "); if (opt & AGL_FLOAT_COLOR) ustrcat(buf, "float_color "); if (opt & AGL_FLOAT_Z) ustrcat(buf, "float_depth "); set_config_string(section, name, buf); } /* void allegro_gl_save_settings() */ /** \ingroup settings * Saves the current settings (as specified by allegro_gl_set()) to * the current config file, in the section [OpenGL]. * * \sa allegro_gl_load_settings() */ void allegro_gl_save_settings() { char *section = "OpenGL"; int save = allegro_gl_get(AGL_REQUIRE) | allegro_gl_get(AGL_SUGGEST); if (save & AGL_ALLEGRO_FORMAT) set_config_int(section, "allegro_format", allegro_gl_get(AGL_ALLEGRO_FORMAT)); if (save & AGL_RED_DEPTH) set_config_int(section, "red_depth", allegro_gl_get(AGL_RED_DEPTH)); if (save & AGL_GREEN_DEPTH) set_config_int(section, "green_depth", allegro_gl_get(AGL_GREEN_DEPTH)); if (save & AGL_BLUE_DEPTH) set_config_int(section, "blue_depth", allegro_gl_get(AGL_BLUE_DEPTH)); if (save & AGL_ALPHA_DEPTH) set_config_int(section, "alpha_depth", allegro_gl_get(AGL_ALPHA_DEPTH)); if (save & AGL_COLOR_DEPTH) set_config_int(section, "color_depth", allegro_gl_get(AGL_COLOR_DEPTH)); if (save & AGL_ACC_RED_DEPTH) set_config_int(section, "accum_red_depth", allegro_gl_get(AGL_ACC_RED_DEPTH)); if (save & AGL_ACC_GREEN_DEPTH) set_config_int(section, "accum_green_depth", allegro_gl_get(AGL_ACC_GREEN_DEPTH)); if (save & AGL_ACC_BLUE_DEPTH) set_config_int(section, "accum_blue_depth", allegro_gl_get(AGL_ACC_BLUE_DEPTH)); if (save & AGL_ACC_ALPHA_DEPTH) set_config_int(section, "accum_alpha_depth", allegro_gl_get(AGL_ACC_ALPHA_DEPTH)); if (save & AGL_DOUBLEBUFFER) set_config_int(section, "double_buffer", allegro_gl_get(AGL_DOUBLEBUFFER)); if (save & AGL_STEREO) set_config_int(section, "stereo_display", allegro_gl_get(AGL_STEREO)); if (save & AGL_AUX_BUFFERS) set_config_int(section, "aux_buffers", allegro_gl_get(AGL_AUX_BUFFERS)); if (save & AGL_Z_DEPTH) set_config_int(section, "z_depth", allegro_gl_get(AGL_Z_DEPTH)); if (save & AGL_STENCIL_DEPTH) set_config_int(section, "stencil_depth", allegro_gl_get(AGL_STENCIL_DEPTH)); if (save & AGL_WINDOW_X) set_config_int(section, "window_x", allegro_gl_get(AGL_WINDOW_X)); if (save & AGL_WINDOW_Y) set_config_int(section, "window_y", allegro_gl_get(AGL_WINDOW_Y)); if (save & AGL_FULLSCREEN) set_config_int(section, "fullscreen", allegro_gl_get(AGL_FULLSCREEN)); if (save & AGL_WINDOWED) set_config_int(section, "windowed", allegro_gl_get(AGL_WINDOWED)); if (save & AGL_VIDEO_MEMORY_POLICY) set_config_int(section, "video_memory_policy", allegro_gl_get(AGL_VIDEO_MEMORY_POLICY)); if (save & AGL_SAMPLE_BUFFERS) set_config_int(section, "sample_buffers", allegro_gl_get(AGL_SAMPLE_BUFFERS)); if (save & AGL_SAMPLES) set_config_int(section, "samples", allegro_gl_get(AGL_SAMPLES)); if (save & AGL_FLOAT_COLOR) set_config_int(section, "float_color", allegro_gl_get(AGL_FLOAT_COLOR)); if (save & AGL_FLOAT_Z) set_config_int(section, "float_depth", allegro_gl_get(AGL_FLOAT_Z)); if (save & AGL_REQUIRE) build_settings(allegro_gl_get(AGL_REQUIRE), section, "require"); if (save & AGL_SUGGEST) build_settings(allegro_gl_get(AGL_SUGGEST), section, "suggest"); } /* Parses an input string to read settings */ static void agl_parse_section(int sec, char *section, char *name) { const char *end; char *buf; char *ptr; int strsize; int opt = 0; end = get_config_string(section, name, ""); strsize = ustrsizez(end); buf = (char*)malloc(sizeof(char) * strsize); if (!buf) { TRACE(PREFIX_E "parse_section: Ran out of memory " "while trying to allocate %i bytes!", (int)sizeof(char) * strsize); return; } memcpy(buf, end, strsize); end = buf + strsize; ptr = buf; while (ptr < end) { char *s = ustrtok_r(ptr, " ;|+", &ptr); if (!ustrcmp(s, "allegro_format")) opt |= AGL_ALLEGRO_FORMAT; if (!ustrcmp(s, "red_depth")) opt |= AGL_RED_DEPTH; if (!ustrcmp(s, "green_depth")) opt |= AGL_GREEN_DEPTH; if (!ustrcmp(s, "blue_depth")) opt |= AGL_BLUE_DEPTH; if (!ustrcmp(s, "alpha_depth")) opt |= AGL_ALPHA_DEPTH; if (!ustrcmp(s, "color_depth")) opt |= AGL_COLOR_DEPTH; if (!ustrcmp(s, "accum_red_depth")) opt |= AGL_ACC_RED_DEPTH; if (!ustrcmp(s, "accum_green_depth")) opt |= AGL_ACC_GREEN_DEPTH; if (!ustrcmp(s, "accum_blue_depth")) opt |= AGL_ACC_BLUE_DEPTH; if (!ustrcmp(s, "accum_alpha_depth")) opt |= AGL_ACC_ALPHA_DEPTH; if (!ustrcmp(s, "double_buffer")) opt |= AGL_DOUBLEBUFFER; if (!ustrcmp(s, "stereo_display")) opt |= AGL_STEREO; if (!ustrcmp(s, "aux_buffers")) opt |= AGL_AUX_BUFFERS; if (!ustrcmp(s, "z_depth")) opt |= AGL_Z_DEPTH; if (!ustrcmp(s, "stencil_depth")) opt |= AGL_STENCIL_DEPTH; if (!ustrcmp(s, "window_x")) opt |= AGL_WINDOW_X; if (!ustrcmp(s, "window_y")) opt |= AGL_WINDOW_Y; if (!ustrcmp(s, "fullscreen")) opt |= AGL_FULLSCREEN; if (!ustrcmp(s, "windowed")) opt |= AGL_WINDOWED; if (!ustrcmp(s, "video_memory_policy")) opt |= AGL_VIDEO_MEMORY_POLICY; if (!ustrcmp(s, "sample_buffers")) opt |= AGL_SAMPLE_BUFFERS; if (!ustrcmp(s, "samples")) opt |= AGL_SAMPLES; if (!ustrcmp(s, "float_color")) opt |= AGL_FLOAT_COLOR; if (!ustrcmp(s, "float_depth")) opt |= AGL_FLOAT_Z; } free(buf); allegro_gl_set(sec, opt); } /* void allegro_gl_load_settings() */ /** \ingroup settings * * Loads the settings from the current config file, in the * section [OpenGL]. * Note that this function will not clear any settings currently * set, but will add them up, as if each of the setting were set * manually. * * \sa allegro_gl_save_settings() */ void allegro_gl_load_settings() { int set; char *section = "OpenGL"; set = get_config_int(section, "allegro_format", -1); if (set != -1) allegro_gl_set(AGL_ALLEGRO_FORMAT, set); set = get_config_int(section, "red_depth", -1); if (set != -1) allegro_gl_set(AGL_RED_DEPTH, set); set = get_config_int(section, "green_depth", -1); if (set != -1) allegro_gl_set(AGL_GREEN_DEPTH, set); set = get_config_int(section, "blue_depth", -1); if (set != -1) allegro_gl_set(AGL_BLUE_DEPTH, set); set = get_config_int(section, "alpha_depth", -1); if (set != -1) allegro_gl_set(AGL_ALPHA_DEPTH, set); set = get_config_int(section, "color_depth", -1); if (set != -1) allegro_gl_set(AGL_COLOR_DEPTH, set); set = get_config_int(section, "accum_red_depth", -1); if (set != -1) allegro_gl_set(AGL_ACC_RED_DEPTH, set); set = get_config_int(section, "accum_green_depth", -1); if (set != -1) allegro_gl_set(AGL_ACC_GREEN_DEPTH, set); set = get_config_int(section, "accum_blue_depth", -1); if (set != -1) allegro_gl_set(AGL_ACC_BLUE_DEPTH, set); set = get_config_int(section, "accum_alpha_depth", -1); if (set != -1) allegro_gl_set(AGL_ACC_ALPHA_DEPTH, set); set = get_config_int(section, "double_buffer", -1); if (set != -1) allegro_gl_set(AGL_DOUBLEBUFFER, set); set = get_config_int(section, "stereo_display", -1); if (set != -1) allegro_gl_set(AGL_STEREO, set); set = get_config_int(section, "aux_buffers", -1); if (set != -1) allegro_gl_set(AGL_AUX_BUFFERS, set); set = get_config_int(section, "z_depth", -1); if (set != -1) allegro_gl_set(AGL_Z_DEPTH, set); set = get_config_int(section, "stencil_depth", -1); if (set != -1) allegro_gl_set(AGL_STENCIL_DEPTH, set); set = get_config_int(section, "window_x", -1); if (set != -1) allegro_gl_set(AGL_WINDOW_X, set); set = get_config_int(section, "window_y", -1); if (set != -1) allegro_gl_set(AGL_WINDOW_Y, set); set = get_config_int(section, "fullscreen", -1); if (set != -1) allegro_gl_set(AGL_FULLSCREEN, set); set = get_config_int(section, "windowed", -1); if (set != -1) allegro_gl_set(AGL_WINDOWED, set); set = get_config_int(section, "video_memory_policy", -1); if (set != -1) allegro_gl_set(AGL_VIDEO_MEMORY_POLICY, set); set = get_config_int(section, "sample_buffers", -1); if (set != -1) allegro_gl_set(AGL_SAMPLE_BUFFERS, set); set = get_config_int(section, "samples", -1); if (set != -1) allegro_gl_set(AGL_SAMPLES, set); set = get_config_int(section, "float_color", -1); if (set != -1) allegro_gl_set(AGL_FLOAT_COLOR, set); set = get_config_int(section, "float_depth", -1); if (set != -1) allegro_gl_set(AGL_FLOAT_Z, set); agl_parse_section(AGL_REQUIRE, section, "require"); agl_parse_section(AGL_SUGGEST, section, "suggest"); } /* int install_allegro_gl(void) */ /** \ingroup core * * Installs the AllegroGL addon to Allegro. * Allegro should already be initialized with allegro_init() * or install_allegro(). * * \return 0 on success; -1 on failure. * * \see remove_allegro_gl() */ int install_allegro_gl(void) { if (!system_driver) return -1; if (atexit(remove_allegro_gl)) return -1; if (system_driver->gfx_drivers) saved_gfx_drivers = system_driver->gfx_drivers; else saved_gfx_drivers = list_saved_gfx_drivers; system_driver->gfx_drivers = our_gfx_drivers; allegro_gl_clear_settings(); /* Save and replace old blit_between_formats methods */ #ifdef ALLEGRO_COLOR8 __blit_between_formats8 = __linear_vtable8.blit_between_formats; __linear_vtable8.blit_between_formats = allegro_gl_memory_blit_between_formats; #endif #ifdef ALLEGRO_COLOR16 __blit_between_formats15 = __linear_vtable15.blit_between_formats; __linear_vtable15.blit_between_formats = allegro_gl_memory_blit_between_formats; __blit_between_formats16 = __linear_vtable16.blit_between_formats; __linear_vtable16.blit_between_formats = allegro_gl_memory_blit_between_formats; #endif #ifdef ALLEGRO_COLOR24 __blit_between_formats24 = __linear_vtable24.blit_between_formats; __linear_vtable24.blit_between_formats = allegro_gl_memory_blit_between_formats; #endif #ifdef ALLEGRO_COLOR32 __blit_between_formats32 = __linear_vtable32.blit_between_formats; __linear_vtable32.blit_between_formats = allegro_gl_memory_blit_between_formats; #endif usetc(allegro_gl_error, 0); return 0; } /* void remove_allegro_gl(void) */ /** \ingroup core * Removes the AllegroGL addon. You should not call any more OpenGL * or AllegroGL functions after calling this function. Note that * it will be called automatically at program exit, so you don't need * to explicitly do it. * * \see install_allegro_gl() */ void remove_allegro_gl(void) { if ((!system_driver) || (!saved_gfx_drivers)) return; if (saved_gfx_drivers == &list_saved_gfx_drivers) system_driver->gfx_drivers = NULL; else system_driver->gfx_drivers = saved_gfx_drivers; /* This function may be called twice (once by a user explicit call * and once again at exit since the function is registered with at_exit) * In order to prevent crashes, 'saved_gfx_drivers' is set to NULL */ saved_gfx_drivers = NULL; /* Restore the blit_between_formats methods */ #ifdef ALLEGRO_COLOR8 __linear_vtable8.blit_between_formats = __blit_between_formats8; #endif #ifdef ALLEGRO_COLOR16 __linear_vtable15.blit_between_formats = __blit_between_formats15; __linear_vtable16.blit_between_formats = __blit_between_formats16; #endif #ifdef ALLEGRO_COLOR24 __linear_vtable24.blit_between_formats = __blit_between_formats24; #endif #ifdef ALLEGRO_COLOR32 __linear_vtable32.blit_between_formats = __blit_between_formats32; #endif } /* void allegro_gl_flip(void) */ /** \ingroup core * Flips the front and back framebuffers. * * If you chose, or were given, a double buffered OpenGL mode, you have * access to a front buffer, which is visible on the screen, and also a * back buffer, which is not visible. This routine flips the buffers, * so that the contents of the back buffer is now the contents of the * (visible) front buffer. The contents of the backbuffer is undefined * after the operation. * * Normally in these modes you would do all your drawing to the back * buffer, without the user seeing the image while it's partially drawn, * and then call this function to flip the buffers, allowing the user * to see what you've drawn, now that it's finished, while you proceed to * draw the next frame. * * When drawing to the screen bitmap, you may not be drawing to what user * currently sees on his monitor. It is recommended that you rebuild the * screen every frame, then flip, then draw again. * * \sa allegro_gl_set(), AGL_DOUBLEBUFFER */ void allegro_gl_flip(void) { __allegro_gl_driver->flip(); } /* float allegro_gl_opengl_version() */ /** \ingroup core * * Returns the OpenGL version number of the client * (the computer the program is running on). * "1.0" is returned as 1.0, "1.2.1" is returned as 1.21, * and "1.2.2" as 1.22, etc. * * A valid OpenGL context must exist for this function to work, which * means you may \b not call it before set_gfx_mode(GFX_OPENGL) * * \return The OpenGL ICD/MCD version number. */ float allegro_gl_opengl_version() { const char *str; if (!__allegro_gl_valid_context) return 0.0f; str = (const char*)glGetString(GL_VERSION); if ((strncmp(str, "1.0 ", 4) == 0) || (strncmp(str, "1.0.0 ", 6) == 0)) return 1.0; if ((strncmp(str, "1.1 ", 4) == 0) || (strncmp(str, "1.1.0 ", 6) == 0)) return 1.1; if ((strncmp(str, "1.2 ", 4) == 0) || (strncmp(str, "1.2.0 ", 6) == 0)) return 1.2; if ((strncmp(str, "1.2.1 ", 6) == 0)) return 1.21; if ((strncmp(str, "1.2.2 ", 6) == 0)) return 1.22; if ((strncmp(str, "1.3 ", 4) == 0) || (strncmp(str, "1.3.0 ", 6) == 0)) return 1.3; if ((strncmp(str, "1.4 ", 4) == 0) || (strncmp(str, "1.4.0 ", 6) == 0)) return 1.4; if ((strncmp(str, "1.5 ", 4) == 0) || (strncmp(str, "1.5.0 ", 6) == 0)) return 1.5; if ((strncmp(str, "2.0 ", 4) == 0) || (strncmp(str, "2.0.0 ", 6) == 0)) return 2.0; if ((strncmp(str, "2.1 ", 4) == 0) || (strncmp(str, "2.1.0 ", 6) == 0)) return 2.1; if ((strncmp(str, "3.0 ", 4) == 0) || (strncmp(str, "3.0.0 ", 6) == 0)) return 3.0; /* The OpenGL driver does not return a version * number. However it probably supports at least OpenGL 1.0 */ if (!str) { return 1.0; } return atof(str); } void __allegro_gl_set_allegro_image_format(int big_endian) { /* Sets up Allegro to use OpenGL formats */ _rgb_r_shift_15 = 11; _rgb_g_shift_15 = 6; _rgb_b_shift_15 = 1; _rgb_r_shift_16 = 11; _rgb_g_shift_16 = 5; _rgb_b_shift_16 = 0; if (big_endian) { _rgb_r_shift_24 = 16; _rgb_g_shift_24 = 8; _rgb_b_shift_24 = 0; _rgb_a_shift_32 = 0; _rgb_r_shift_32 = 24; _rgb_g_shift_32 = 16; _rgb_b_shift_32 = 8; } else { _rgb_r_shift_24 = 0; _rgb_g_shift_24 = 8; _rgb_b_shift_24 = 16; _rgb_r_shift_32 = 0; _rgb_g_shift_32 = 8; _rgb_b_shift_32 = 16; _rgb_a_shift_32 = 24; } return; } /* allegro_gl_default_init: * Sets a graphics mode according to the mode (fullscreen or windowed) * requested by the user. If it fails to set up the mode then it tries * (if available) the other one unless the user has "AGL_REQUIRED" the mode. */ static BITMAP *allegro_gl_default_gfx_init(int w, int h, int vw, int vh, int depth) { BITMAP* bmp = NULL; if (allegro_gl_display_info.fullscreen) { TRACE(PREFIX_I "default_gfx_init: Trying to set up fullscreen mode.\n"); #ifdef GFX_OPENGL_FULLSCREEN /* Looks for fullscreen mode in our_driver_list */ gfx_driver = &gfx_allegro_gl_fullscreen; if (__allegro_gl_required_settings & AGL_FULLSCREEN) /* Fullscreen mode required and found */ return gfx_allegro_gl_fullscreen.init(w, h, vw, vh, depth); else bmp = gfx_allegro_gl_fullscreen.init(w, h, vw, vh, depth); if (bmp) /* Fullscreen mode found but not required (probably suggested) */ return bmp; #endif /*GFX_OPENGL_FULLSCREEN*/ /* Fullscreen mode not available but not required : * let's try windowed mode : */ TRACE(PREFIX_I "default_gfx_init: Failed to set up fullscreen mode!\n"); #ifdef GFX_OPENGL_WINDOWED TRACE(PREFIX_I "default_gfx_init: Trying windowed mode...\n"); allegro_gl_display_info.fullscreen = FALSE; gfx_driver = &gfx_allegro_gl_windowed; return gfx_allegro_gl_windowed.init(w, h, vw, vh, depth); #else return NULL; #endif /* GFX_OPENGL_WINDOWED */ } else { TRACE(PREFIX_I "default_gfx_init: Trying to set up windowed mode...\n"); #ifdef GFX_OPENGL_WINDOWED /* Looks for windowed mode in our_driver_list */ gfx_driver = &gfx_allegro_gl_windowed; if (__allegro_gl_required_settings & AGL_WINDOWED) /* Windowed mode required and found */ return gfx_allegro_gl_windowed.init(w, h, vw, vh, depth); else bmp = gfx_allegro_gl_windowed.init(w, h, vw, vh, depth); if (bmp) /* Windowed mode found but not required (probably suggested) */ return bmp; #endif /* GFX_OPENGL_WINDOWED */ /* Windowed mode not available but not required : * let's try fullscreen mode : */ TRACE(PREFIX_I "default_gfx_init: Failed to set up windowed mode...\n"); #ifdef GFX_OPENGL_FULLSCREEN TRACE(PREFIX_I "default_gfx_init: Trying fullscreen mode...\n"); allegro_gl_display_info.fullscreen = TRUE; gfx_driver = &gfx_allegro_gl_fullscreen; return gfx_allegro_gl_fullscreen.init(w, h, vw, vh, depth); #else return NULL; #endif /*GFX_OPENGL_FULLSCREEN*/ } } /* allegro_gl_set_blender_mode (GFX_DRIVER vtable entry): * Sets the blending mode. Same implementation to all GFX vtables. */ void allegro_gl_set_blender_mode(int mode, int r, int g, int b, int a) { __allegro_gl_blit_operation = AGL_OP_BLEND; /* These blenders do not need any special extensions. * We specify only pixel arithmetic here. Blend equation and blend * color (if available) are reset to defualt later.*/ switch (mode) { case blender_mode_none: glBlendFunc(GL_ONE, GL_ZERO); break; case blender_mode_alpha: glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); break; case blender_mode_invert: glLogicOp(GL_COPY_INVERTED); __allegro_gl_blit_operation = AGL_OP_LOGIC_OP; break; case blender_mode_multiply: glBlendFunc(GL_DST_COLOR, GL_ZERO); break; } if (allegro_gl_opengl_version() >= 1.4 || (allegro_gl_opengl_version() >= 1.2 && allegro_gl_is_extension_supported("GL_ARB_imaging"))) { /* We're running a recent version of OpenGL and everything needed is here. */ glBlendColor(r / 255.f, g / 255.f, b / 255.f, a / 255.f); switch (mode) { case blender_mode_none: glBlendEquation(GL_FUNC_ADD); break; case blender_mode_alpha: glBlendEquation(GL_FUNC_ADD); break; case blender_mode_trans: glBlendEquation(GL_FUNC_ADD); glBlendFunc(GL_CONSTANT_ALPHA, GL_ONE_MINUS_CONSTANT_ALPHA); break; case blender_mode_add: glBlendEquation(GL_FUNC_ADD); glBlendFunc(GL_CONSTANT_ALPHA, GL_ONE); break; case blender_mode_burn: glBlendEquation(GL_FUNC_SUBTRACT); glBlendFunc(GL_ONE, GL_CONSTANT_ALPHA); break; case blender_mode_dodge: glBlendEquation(GL_FUNC_ADD); glBlendFunc(GL_ONE, GL_CONSTANT_ALPHA); break; case blender_mode_multiply: glBlendEquation(GL_FUNC_ADD); break; } return; } /* Check for presence of glBlendColor() and special parameters to * glBlendFunc(). */ if (allegro_gl_is_extension_supported("GL_EXT_blend_color")) { glBlendColorEXT(r / 255.f, g / 255.f, b / 255.f, a / 255.f); switch (mode) { case blender_mode_trans: glBlendFunc(GL_CONSTANT_ALPHA_EXT, GL_ONE_MINUS_CONSTANT_ALPHA_EXT); break; case blender_mode_add: glBlendFunc(GL_CONSTANT_ALPHA_EXT, GL_ONE); break; case blender_mode_burn: glBlendFunc(GL_ONE, GL_CONSTANT_ALPHA_EXT); break; case blender_mode_dodge: glBlendFunc(GL_ONE, GL_CONSTANT_ALPHA_EXT); break; } } else if (mode == blender_mode_trans || mode == blender_mode_add || mode == blender_mode_burn || mode == blender_mode_dodge) { /* glBlendColor() is not available and it is needed by the selected * bledner. Bail out.*/ return; } /* Check for presence of glBlendEquation(). */ if (allegro_gl_is_extension_supported("GL_EXT_blend_minmax")) { switch (mode) { case blender_mode_none: glBlendEquationEXT(GL_FUNC_ADD_EXT); break; case blender_mode_alpha: glBlendEquationEXT(GL_FUNC_ADD_EXT); break; case blender_mode_trans: glBlendEquationEXT(GL_FUNC_ADD_EXT); break; case blender_mode_add: glBlendEquationEXT(GL_FUNC_ADD_EXT); break; case blender_mode_dodge: glBlendEquationEXT(GL_FUNC_ADD_EXT); break; case blender_mode_multiply: glBlendEquationEXT(GL_FUNC_ADD_EXT); break; case blender_mode_burn: if (allegro_gl_is_extension_supported("GL_EXT_blend_subtract")) { glBlendEquationEXT(GL_FUNC_SUBTRACT_EXT); } else { /* GL_FUNC_SUBTRACT is not supported and it is needed by the * selected blender. Bail out. */ return; } break; } } } #ifdef DEBUGMODE #ifdef LOGLEVEL void __allegro_gl_log(int level, const char *str) { if (level <= LOGLEVEL) TRACE(PREFIX_L "[%d] %s", level, str); } #endif #endif allegro4.4-4.4.2/addons/allegrogl/src/amesa/000077500000000000000000000000001173507505700205035ustar00rootroot00000000000000allegro4.4-4.4.2/addons/allegrogl/src/amesa/amesa.c000066400000000000000000000244131173507505700217410ustar00rootroot00000000000000/* * This the Mesa driver for Allegro 4.0 * It is based on the work of Bernhard Tsirren */ #include #include #include #define GL_GLEXT_PROTOTYPES #include "GL/gl.h" #include "GL/glext.h" #include "GL/amesa.h" #include "raster.h" typedef struct _amesa_extension_data { void* proc; char* name; } amesa_extension_data; amesa_extension_data amesa_extension[] = { #ifdef GL_EXT_polygon_offset { (void*)glPolygonOffsetEXT, "glPolygonOffsetEXT" }, #endif { (void*)glBlendEquationEXT, "glBlendEquationEXT" }, { (void*)glBlendColorEXT, "glBlendColorExt" }, { (void*)glVertexPointerEXT, "glVertexPointerEXT" }, { (void*)glNormalPointerEXT, "glNormalPointerEXT" }, { (void*)glColorPointerEXT, "glColorPointerEXT" }, { (void*)glIndexPointerEXT, "glIndexPointerEXT" }, { (void*)glTexCoordPointerEXT, "glTexCoordPointer" }, { (void*)glEdgeFlagPointerEXT, "glEdgeFlagPointerEXT" }, { (void*)glGetPointervEXT, "glGetPointervEXT" }, { (void*)glArrayElementEXT, "glArrayElementEXT" }, { (void*)glDrawArraysEXT, "glDrawArrayEXT" }, { (void*)glAreTexturesResidentEXT, "glAreTexturesResidentEXT" }, { (void*)glBindTextureEXT, "glBindTextureEXT" }, { (void*)glDeleteTexturesEXT, "glDeleteTexturesEXT" }, { (void*)glGenTexturesEXT, "glGenTexturesEXT" }, { (void*)glIsTextureEXT, "glIsTextureEXT" }, { (void*)glPrioritizeTexturesEXT, "glPrioritizeTexturesEXT" }, { (void*)glCopyTexSubImage3DEXT, "glCopyTexSubImage3DEXT" }, { (void*)glTexImage3DEXT, "glTexImage3DEXT" }, { (void*)glTexSubImage3DEXT, "glTexSubImage3DEXT" }, { (void*)glColorTableEXT, "glColorTableEXT" }, { (void*)glColorSubTableEXT, "glColorSubTableEXT" }, { (void*)glGetColorTableEXT, "glGetColorTableEXT" }, { (void*)glGetColorTableParameterfvEXT, "glGetColorTableParameterfvEXT" }, { (void*)glGetColorTableParameterivEXT, "glGetColorTableParameterivEXT" }, { (void*)glPointParameterfEXT, "glPointParameterfEXT" }, { (void*)glPointParameterfvEXT, "glPointParameterfvEXT" }, { (void*)glBlendFuncSeparateEXT, "glBlendFuncSeparateEXT" }, { (void*)glLockArraysEXT, "glLockArraysEXT" }, { (void*)glUnlockArraysEXT, "glUnlockArraysEXT" }, { NULL, '\0' } }; #define AMESA_NEW_LINE (_NEW_LINE | \ _NEW_TEXTURE | \ _NEW_LIGHT | \ _NEW_DEPTH | \ _NEW_RENDERMODE | \ _SWRAST_NEW_RASTERMASK) #define AMESA_NEW_TRIANGLE (_NEW_POLYGON | \ _NEW_TEXTURE | \ _NEW_LIGHT | \ _NEW_DEPTH | \ _NEW_RENDERMODE | \ _SWRAST_NEW_RASTERMASK) AMesaContext AMesa = NULL; /* the current context */ /**********************************************************************/ /***** AMesa Public API Functions *****/ /**********************************************************************/ AMesaVisual GLAPIENTRY AMesaCreateVisual(GLboolean dbFlag, GLint depth, GLint rgba, GLint depthSize, GLint stencilSize, GLint accumSizeRed, GLint accumSizeGreen, GLint accumSizeBlue, GLint accumSizeAlpha) { AMesaVisual visual; GLbyte redBits, greenBits, blueBits, alphaBits, indexBits; if ((!rgba) && (depthSize != 8)) return NULL; visual = (AMesaVisual) malloc(sizeof(struct amesa_visual)); if (!visual) return NULL; switch (depth) { case 8: if (rgba) { redBits = 3; greenBits = 3; blueBits = 2; alphaBits = 0; indexBits = 0; } else { redBits = 0; greenBits = 0; blueBits = 0; alphaBits = 0; indexBits = 8; } break; case 15: redBits = 5; greenBits = 5; blueBits = 5; alphaBits = 0; indexBits = 0; break; case 16: redBits = 5; greenBits = 6; blueBits = 5; alphaBits = 0; indexBits = 0; break; case 24: redBits = 8; greenBits = 8; blueBits = 8; alphaBits = 0; indexBits = 0; break; case 32: redBits = 8; greenBits = 8; blueBits = 8; alphaBits = 8; indexBits = 0; break; default: free(visual); return NULL; } if (depthSize) depthSize = 16; visual->DBFlag = dbFlag; visual->Depth = depth; visual->GLVisual = _mesa_create_visual(rgba, /* rgb mode */ dbFlag, /* double buffer */ GL_FALSE, /* stereo*/ redBits, greenBits, blueBits, alphaBits, indexBits, depthSize, stencilSize, accumSizeBlue, accumSizeRed, accumSizeGreen, alphaBits ? accumSizeAlpha : 0, 1); if (!visual->GLVisual) { free(visual); return NULL; } return visual; } void GLAPIENTRY AMesaDestroyVisual(AMesaVisual visual) { _mesa_destroy_visual(visual->GLVisual); free(visual); } AMesaBuffer GLAPIENTRY AMesaCreateBuffer(AMesaVisual visual, BITMAP* bmp) { AMesaBuffer buffer; /* Buffer and visual must share the same color depth */ if (bitmap_color_depth(bmp) != visual->Depth) return NULL; buffer = (AMesaBuffer) malloc(sizeof(struct amesa_buffer)); if (!buffer) return NULL; buffer->FrontBuffer = bmp; buffer->BackBuffer = NULL; buffer->Active = NULL; buffer->ReadActive = NULL; buffer->DepthBuffer = NULL; if (visual->DBFlag) { buffer->BackBuffer = create_bitmap_ex(visual->Depth, bmp->w, bmp->h); if (!buffer->BackBuffer) { free(buffer); return NULL; } } if (visual->GLVisual->depthBits > 0) { buffer->DepthBuffer = create_zbuffer(bmp); if (!buffer->DepthBuffer) { if (buffer->BackBuffer) destroy_bitmap(buffer->BackBuffer); free(buffer); return NULL; } set_zbuffer(buffer->DepthBuffer); } buffer->GLBuffer = _mesa_create_framebuffer(visual->GLVisual, 0, /*depth buffer is handled by Allegro */ visual->GLVisual->stencilBits > 0, /*software stencil buffer*/ visual->GLVisual->accumRedBits > 0,/*software accum buffer*/ GL_FALSE ); /*software alpha buffer*/ if (!buffer->GLBuffer) { if (buffer->BackBuffer) destroy_bitmap(buffer->BackBuffer); if (buffer->DepthBuffer) destroy_zbuffer(buffer->DepthBuffer); free(buffer); return NULL; } buffer->Width = bmp->w; buffer->Height = bmp->h; return buffer; } void GLAPIENTRY AMesaDestroyBuffer(AMesaBuffer buffer) { if (buffer->BackBuffer) destroy_bitmap(buffer->BackBuffer); if (buffer->DepthBuffer) destroy_zbuffer(buffer->DepthBuffer); _mesa_destroy_framebuffer(buffer->GLBuffer); free(buffer); } /* Extend the software rasterizer with our line and triangle * functions. */ static void AMesaRegisterSwrastFunctions( GLcontext *ctx ) { SWcontext *swrast = SWRAST_CONTEXT( ctx ); swrast->choose_line = AMesaChooseLine; swrast->choose_triangle = AMesaChooseTriangle; swrast->invalidate_line |= AMESA_NEW_LINE; swrast->invalidate_triangle |= AMESA_NEW_TRIANGLE; } AMesaContext GLAPIENTRY AMesaCreateContext(AMesaVisual visual, AMesaContext share) { AMesaContext context; GLboolean direct = GL_FALSE; GLcontext *ctx; context = (AMesaContext) malloc(sizeof(struct amesa_context)); if (!context) return NULL; context->GLContext = _mesa_create_context(visual->GLVisual, share ? share->GLContext : NULL, (void*)context, direct); if (!context->GLContext) { free(context); return NULL; } context->Visual = visual; ctx = context->GLContext; _mesa_enable_sw_extensions(ctx); _mesa_enable_1_3_extensions(ctx); /* Initialize the software rasterizer and helper modules. */ _swrast_CreateContext( ctx ); _ac_CreateContext( ctx ); _tnl_CreateContext( ctx ); _swsetup_CreateContext( ctx ); _swsetup_Wakeup( ctx ); /*AMesaRegisterSwrastFunctions(ctx);*/ return context; } void GLAPIENTRY AMesaDestroyContext(AMesaContext context) { if (context) { _swsetup_DestroyContext(context->GLContext); _tnl_DestroyContext(context->GLContext); _ac_DestroyContext(context->GLContext); _swrast_DestroyContext(context->GLContext); _mesa_free_context_data(context->GLContext); free(context); } } /* * Make the specified context and buffer the current one. */ GLboolean GLAPIENTRY AMesaMakeCurrent(AMesaContext context, AMesaBuffer buffer) { if (context && buffer) { context->Buffer = buffer; buffer->Active = buffer->BackBuffer ? buffer->BackBuffer : buffer->FrontBuffer; buffer->ReadActive = buffer->Active; context->ClearDepth = 2 << context->Visual->GLVisual->depthBits; context->zNear = 0.; context->zFar = 1.; context->ClearColor = 0; context->ClearIndex = 0; context->ColorIndex = 0; AMesaUpdateState(context->GLContext, ~0); _mesa_make_current(context->GLContext, buffer->GLBuffer); if (context->GLContext->Viewport.Width == 0 || context->GLContext->Viewport.Height == 0) { /* initialize viewport and scissor box to buffer size */ _mesa_Viewport(0, 0, buffer->Width, buffer->Height); context->GLContext->Scissor.Width = buffer->Width; context->GLContext->Scissor.Height = buffer->Height; } AMesa = context; } else { if (context) { /* Detach */ context->Buffer->Active = NULL; context->Buffer->ReadActive = NULL; context->Buffer = NULL; _mesa_make_current(NULL, NULL); AMesa = NULL; } else return GL_FALSE; } return GL_TRUE; } void GLAPIENTRY AMesaSwapBuffers(AMesaBuffer buffer) { if (buffer->BackBuffer) blit(buffer->BackBuffer, buffer->FrontBuffer, 0, 0, 0, 0, buffer->Width, buffer->Height); } AMesaContext GLAPIENTRY AMesaGetCurrentContext (void) { return AMesa; } BITMAP* GLAPIENTRY AMesaGetColorBuffer(AMesaBuffer buffer, GLenum mode) { switch (mode) { case AMESA_FRONT: return buffer->FrontBuffer; case AMESA_BACK: if (buffer->BackBuffer) return buffer->BackBuffer; else return NULL; case AMESA_ACTIVE: return buffer->Active; default: return NULL; } } void* GLAPIENTRY AMesaGetProcAddress(AL_CONST char *name) { int i = 0; while (amesa_extension[i].proc) { if (ustrcmp(amesa_extension[i].name, name) == 0) return amesa_extension[i].proc; i++; } return NULL; } allegro4.4-4.4.2/addons/allegrogl/src/amesa/direct.h000066400000000000000000000345631173507505700221410ustar00rootroot00000000000000/* * Mesa 3-D graphics library * Version: 3.0 * Copyright (C) 1995-1998 Brian Paul * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #define DESTINATION(BMP, X, Y, TYPE) \ ({ \ BITMAP *_bmp = BMP; \ \ (TYPE*)(_bmp->line[_bmp->h - (Y) - 1]) + (X); \ }) #define IMPLEMENT_WRITE_RGBA_SPAN(DEPTH, TYPE) \ static void write_rgba_span_##DEPTH (const GLcontext *ctx, \ GLuint n, GLint x, GLint y, \ const GLubyte rgba[][4], \ const GLubyte mask[]) \ { \ AMesaContext context = (AMesaContext)(ctx->DriverCtx); \ TYPE *d = DESTINATION(context->Buffer->Active, x, y, TYPE); \ \ if (mask) \ { \ while (n--) \ { \ if (mask[0]) d[0] = makecol##DEPTH(rgba[0][RCOMP], rgba[0][GCOMP], rgba[0][BCOMP]); \ d++; rgba++; mask++; \ } \ } \ else \ { \ while (n--) \ { \ d[0] = makecol##DEPTH(rgba[0][RCOMP], rgba[0][GCOMP], rgba[0][BCOMP]); \ d++; rgba++; \ } \ } \ } #define IMPLEMENT_WRITE_RGB_SPAN(DEPTH, TYPE) \ static void write_rgb_span_##DEPTH (const GLcontext *ctx, \ GLuint n, GLint x, GLint y, \ const GLubyte rgb[][3], \ const GLubyte mask[]) \ { \ AMesaContext context = (AMesaContext)(ctx->DriverCtx); \ TYPE *d = DESTINATION(context->Buffer->Active, x, y, TYPE); \ \ if (mask) \ { \ while (n--) \ { \ if (mask[0]) d[0] = makecol##DEPTH(rgb[0][RCOMP], rgb[0][GCOMP], rgb[0][BCOMP]); \ d++; rgb++; mask++; \ } \ } \ else \ { \ while (n--) \ { \ d[0] = makecol##DEPTH(rgb[0][RCOMP], rgb[0][GCOMP], rgb[0][BCOMP]); \ d++; rgb++; \ } \ } \ } #define IMPLEMENT_WRITE_MONO_RGBA_SPAN(DEPTH, TYPE) \ static void write_mono_rgba_span_##DEPTH (const GLcontext *ctx, \ GLuint n, GLint x, GLint y, \ const GLubyte mask[]) \ { \ AMesaContext context = (AMesaContext)(ctx->DriverCtx); \ TYPE color = context->CurrentColor; \ TYPE *d = DESTINATION(context->Buffer->Active, x, y, TYPE); \ \ while (n--) \ { \ if (mask[0]) d[0] = color; \ d++; mask++; \ } \ } #define IMPLEMENT_READ_RGBA_SPAN(DEPTH, TYPE) \ static void read_rgba_span_##DEPTH (const GLcontext *ctx, \ GLuint n, GLint x, GLint y, \ GLubyte rgba[][4]) \ { \ AMesaContext context = (AMesaContext)(ctx->DriverCtx); \ BITMAP *bmp = context->Buffer->ReadActive; \ TYPE *d = DESTINATION(bmp, x, y, TYPE); \ \ while (n--) \ { \ rgba[0][RCOMP] = getr##DEPTH(d[0]); \ rgba[0][GCOMP] = getg##DEPTH(d[0]); \ rgba[0][BCOMP] = getb##DEPTH(d[0]); \ rgba[0][ACOMP] = 255; \ \ d++; rgba++; \ } \ } #define IMPLEMENT_WRITE_RGBA_PIXELS(DEPTH, TYPE) \ static void write_rgba_pixels_##DEPTH (const GLcontext *ctx, \ GLuint n, \ const GLint x[], \ const GLint y[], \ const GLubyte rgba[][4], \ const GLubyte mask[]) \ { \ AMesaContext context = (AMesaContext)(ctx->DriverCtx); \ BITMAP *bmp = context->Buffer->Active; \ \ while (n--) \ { \ if (mask[0]) *DESTINATION(bmp, x[0], y[0], TYPE) = makecol##DEPTH(rgba[0][RCOMP], rgba[0][GCOMP], rgba[0][BCOMP]); \ rgba++; x++; y++; mask++; \ } \ } #define IMPLEMENT_WRITE_MONO_RGBA_PIXELS(DEPTH, TYPE) \ static void write_mono_rgba_pixels_##DEPTH (const GLcontext *ctx, \ GLuint n, \ const GLint x[], \ const GLint y[], \ const GLubyte mask[]) \ { \ AMesaContext context = (AMesaContext)(ctx->DriverCtx); \ TYPE color = context->CurrentColor; \ BITMAP *bmp = context->Buffer->Active; \ \ while (n--) \ { \ if (mask[0]) *DESTINATION(bmp, x[0], y[0], TYPE) = color; \ x++; y++; mask++; \ } \ } #define IMPLEMENT_READ_RGBA_PIXELS(DEPTH, TYPE) \ static void read_rgba_pixels_##DEPTH (const GLcontext *ctx, \ GLuint n, \ const GLint x[], \ const GLint y[], \ GLubyte rgba[][4], \ const GLubyte mask[]) \ { \ AMesaContext context = (AMesaContext)(ctx->DriverCtx); \ BITMAP *bmp = context->Buffer->ReadActive; \ \ while (n--) \ { \ if (mask[0]) \ { \ int color = *DESTINATION(bmp, x[0], y[0], TYPE); \ \ rgba[0][RCOMP] = getr##DEPTH(color); \ rgba[0][GCOMP] = getg##DEPTH(color); \ rgba[0][BCOMP] = getb##DEPTH(color); \ rgba[0][ACOMP] = 255; \ } \ \ x++; y++; rgba++; mask++; \ } \ } allegro4.4-4.4.2/addons/allegrogl/src/amesa/generic.h000066400000000000000000000146521173507505700223000ustar00rootroot00000000000000/* These are the functions for interfacing Mesa with Allegro. */ #ifdef MESA_5_0 static void clear_color_generic(GLcontext *ctx, const GLfloat color[4]) { AMesaContext context = (AMesaContext)(ctx->DriverCtx); context->ClearColor = makecol(color[0]*255, color[1]*255, color[2]*255); } #else static void clear_color_generic(GLcontext *ctx, const GLchan color[4]) { AMesaContext context = (AMesaContext)(ctx->DriverCtx); #if CHAN_TYPE == GL_FLOAT context->ClearColor = makecol(color[0]*255, color[1]*255, color[2]*255); #elif CHAN_TYPE == GL_UNSIGNED_SHORT context->ClearColor = makecol(color[0]<<8, color[1]<<8, color[2]<<8); #else context->ClearColor = makecol(color[0], color[1], color[2]); #endif } #endif static void clear_generic(GLcontext *ctx, GLbitfield mask, GLboolean all, GLint x, GLint y, GLint width, GLint height) { AMesaContext context = (AMesaContext)(ctx->DriverCtx); int color = context->ClearColor; BITMAP *buffer = context->Buffer->Active; union { float zf; long zi; } _zbuf_clip; if (mask & DD_FRONT_LEFT_BIT) { buffer = context->Buffer->FrontBuffer; mask &= ~ DD_FRONT_LEFT_BIT; } if (mask & DD_BACK_LEFT_BIT) { buffer = context->Buffer->BackBuffer; mask &= ~ DD_BACK_LEFT_BIT; } if (mask & DD_DEPTH_BIT) { ZBUFFER *depthBuffer = context->Buffer->DepthBuffer; if (depthBuffer) { _zbuf_clip.zf = 1. / (context->ClearDepth * context->zFar); if (all) clear_to_color(depthBuffer, _zbuf_clip.zi); else rectfill(depthBuffer, x, y, x+width-1, y+height-1, _zbuf_clip.zi); mask &= ~ DD_DEPTH_BIT; } } if (all) clear_to_color(buffer, color); else rectfill(buffer, x, y, x+width-1, y+height-1, color); /* Call swrast if there is anything left to clear (like DEPTH) */ if (mask) _swrast_Clear( ctx, mask, all, x, y, width, height ); return; } static void write_rgba_span_generic(const GLcontext *ctx, GLuint n, GLint x, GLint y, const GLubyte rgba[][4], const GLubyte mask[]) { AMesaContext context = (AMesaContext)(ctx->DriverCtx); BITMAP *bmp = context->Buffer->Active; y = FLIP(context, y); if (mask) { while (n--) { if (mask[0]) putpixel(bmp, x, y, makecol(rgba[0][RCOMP], rgba[0][GCOMP], rgba[0][BCOMP])); x++; mask++; rgba++; } } else { while (n--) { putpixel(bmp, x, y, makecol(rgba[0][RCOMP], rgba[0][GCOMP], rgba[0][BCOMP])); x++; rgba++; } } } static void write_rgb_span_generic(const GLcontext *ctx, GLuint n, GLint x, GLint y, const GLubyte rgb[][3], const GLubyte mask[]) { AMesaContext context = (AMesaContext)(ctx->DriverCtx); BITMAP *bmp = context->Buffer->Active; y = FLIP(context, y); if (mask) { while(n--) { if (mask[0]) putpixel(bmp, x, y, makecol(rgb[0][RCOMP], rgb[0][GCOMP], rgb[0][BCOMP])); x++; mask++; rgb++; } } else { while (n--) { putpixel(bmp, x, y, makecol(rgb[0][RCOMP], rgb[0][GCOMP], rgb[0][BCOMP])); x++; rgb++; } } } static void write_mono_rgba_span_generic(const GLcontext *ctx, GLuint n, GLint x, GLint y, const GLchan colour[4], const GLubyte mask[]) { AMesaContext context = (AMesaContext)(ctx->DriverCtx); BITMAP *bmp = context->Buffer->Active; #if CHAN_TYPE == GL_FLOAT int color = makecol(colour[0]*255, colour[1]*255, colour[2]*255); #elif CHAN_TYPE == GL_UNSIGNED_SHORT int color = makecol(colour[0]<<8, colour[1]<<8, colour[2]<<8); #else int color = makecol(colour[0], colour[1], colour[2]); #endif y = FLIP(context, y); if (mask) { while(n--) { if (mask[0]) putpixel(bmp, x, y, color); x++; mask++; } } else hline(bmp, x, y, x+n-1, color); } static void read_rgba_span_generic(const GLcontext *ctx, GLuint n, GLint x, GLint y, GLubyte rgba[][4]) { AMesaContext context = (AMesaContext)(ctx->DriverCtx); BITMAP *bmp = context->Buffer->ReadActive; y = FLIP(context, y); while (n--) { int color = getpixel(bmp, x, y); rgba[0][RCOMP] = getr(color); rgba[0][GCOMP] = getg(color); rgba[0][BCOMP] = getb(color); rgba[0][ACOMP] = 255; x++; rgba++; } } static void write_rgba_pixels_generic(const GLcontext *ctx, GLuint n, const GLint x[], const GLint y[], const GLubyte rgba[][4], const GLubyte mask[]) { AMesaContext context = (AMesaContext)(ctx->DriverCtx); BITMAP *bmp = context->Buffer->Active; while (n--) { if (mask[0]) putpixel(bmp, x[0], FLIP(context, y[0]), makecol(rgba[0][RCOMP], rgba[0][GCOMP], rgba[0][BCOMP])); x++; y++; mask++; rgba++; } } static void write_mono_rgba_pixels_generic(const GLcontext *ctx, GLuint n, const GLint x[], const GLint y[], const GLchan colour[4], const GLubyte mask[]) { AMesaContext context = (AMesaContext)(ctx->DriverCtx); BITMAP *bmp = context->Buffer->Active; #if CHAN_TYPE == GL_FLOAT int color = makecol(colour[0]*255, colour[1]*255, colour[2]*255); #elif CHAN_TYPE == GL_UNSIGNED_SHORT int color = makecol(colour[0]<<8, colour[1]<<8, colour[2]<<8); #else int color = makecol(colour[0], colour[1], colour[2]); #endif while (n--) { if (mask[0]) putpixel(bmp, x[0], FLIP(context, y[0]), color); x++; y++; mask++; } } static void read_rgba_pixels_generic(const GLcontext *ctx, GLuint n, const GLint x[], const GLint y[], GLubyte rgba[][4], const GLubyte mask[]) { AMesaContext context = (AMesaContext)(ctx->DriverCtx); BITMAP *bmp = context->Buffer->ReadActive; while (n--) { if (mask[0]) { int color = getpixel(bmp, x[0], FLIP(context, y[0])); rgba[0][RCOMP] = getr(color); rgba[0][GCOMP] = getg(color); rgba[0][BCOMP] = getb(color); rgba[0][ACOMP] = 255; } x++; y++; mask++; rgba++; } } allegro4.4-4.4.2/addons/allegrogl/src/amesa/raster.c000066400000000000000000000462361173507505700221620ustar00rootroot00000000000000#include #include "GL/amesa.h" #include "raster.h" /**********************************************************************/ /***** drawing functions *****/ /**********************************************************************/ #define FLIP(context, y) (context->Buffer->Height - (y) - 1) #include "generic.h" /**********************************************************************/ /***** Miscellaneous device driver funcs *****/ /***** Note that these functions are mandatory *****/ /**********************************************************************/ /* Return a string as needed by glGetString(). * Only the GL_RENDERER token must be implemented. Otherwise, * NULL can be returned. */ static const GLubyte* AMesaGetString(GLcontext *ctx, GLenum name) { switch (name) { case GL_RENDERER: return (const GLubyte *) "Allegro 4.0 Driver for Mesa"; default: return NULL; } } /* * Called whenever glClearIndex() is called. Set the index for clearing * the color buffer when in color index mode. */ static void AMesaClearIndex(GLcontext *ctx, GLuint index) { AMesaContext context = (AMesaContext)(ctx->DriverCtx); context->ClearIndex = index; } /* * Specifies the current buffer for writing. * The following values must be accepted when applicable: * GL_FRONT_LEFT - this buffer always exists * GL_BACK_LEFT - when double buffering * GL_FRONT_RIGHT - when using stereo * GL_BACK_RIGHT - when using stereo and double buffering * The folowing values may optionally be accepted. Return GL_TRUE * if accepted, GL_FALSE if not accepted. In practice, only drivers * which can write to multiple color buffers at once should accept * these values. * GL_FRONT - write to front left and front right if it exists * GL_BACK - write to back left and back right if it exists * GL_LEFT - write to front left and back left if it exists * GL_RIGHT - write to right left and back right if they exist * GL_FRONT_AND_BACK - write to all four buffers if they exist * GL_NONE - disable buffer write in device driver. */ #ifdef MESA_4_0_2 static void AMesaSetDrawBuffer(GLcontext *ctx, GLenum buffer) #else static GLboolean AMesaSetDrawBuffer(GLcontext *ctx, GLenum buffer) #endif { AMesaContext context = (AMesaContext)(ctx->DriverCtx); switch(buffer) { case GL_FRONT : case GL_FRONT_LEFT : context->Buffer->Active = context->Buffer->FrontBuffer; #ifdef MESA_4_0_2 return; #else return GL_TRUE; #endif case GL_BACK : case GL_BACK_LEFT : if (context->Buffer->BackBuffer) { context->Buffer->Active = context->Buffer->BackBuffer; #ifdef MESA_4_0_2 return; #else return GL_TRUE; #endif } default : #ifdef MESA_4_0_2 return; #else return GL_FALSE; #endif } } /* * Specifies the current buffer for reading. * colorBuffer will be one of: * GL_FRONT_LEFT - this buffer always exists * GL_BACK_LEFT - when double buffering * GL_FRONT_RIGHT - when using stereo * GL_BACK_RIGHT - when using stereo and double buffering */ #ifdef MESA_5_0 static void AMesaSetReadBuffer(GLcontext *ctx, GLenum buffer) #else static void AMesaSetReadBuffer(GLcontext *ctx, GLframebuffer *colorBuffer, GLenum buffer) #endif { AMesaContext context = (AMesaContext)(ctx->DriverCtx); switch(buffer) { case GL_FRONT : case GL_FRONT_LEFT : context->Buffer->ReadActive = context->Buffer->FrontBuffer; return; case GL_BACK : case GL_BACK_LEFT : if (context->Buffer->BackBuffer) { context->Buffer->ReadActive = context->Buffer->BackBuffer; return; } default : return; } } /* * Tell the device driver where to read/write spans. */ #ifdef MESA_5_0 static void AMesaSetBuffer( GLcontext *ctx, GLframebuffer *buffer, GLuint bufferBit ) { AMesaContext context = (AMesaContext)(ctx->DriverCtx); } #endif /* * Returns the width and height of the current color buffer. */ #ifdef MESA_4_0_2 static void AMesaGetBufferSize(GLframebuffer *buffer, GLuint *width, GLuint *height) { GET_CURRENT_CONTEXT(ctx); #else static void AMesaGetBufferSize(GLcontext *ctx, GLuint *width, GLuint *height) { #endif AMesaContext context = (AMesaContext)(ctx->DriverCtx); *width = context->Buffer->Width; *height = context->Buffer->Height; } /* Write a horizontal run of CI pixels. One function is for 32bpp * indexes and the other for 8bpp pixels (the common case). You must * implement both for color index mode. */ static void AMesaWriteCI32Span( const GLcontext *ctx, GLuint n, GLint x, GLint y, const GLuint index[], const GLubyte mask[] ) { /* Not yet implemented */ } static void AMesaWriteCI8Span( const GLcontext *ctx, GLuint n, GLint x, GLint y, const GLubyte index[], const GLubyte mask[] ) { /* Not yet implemented */ } /* Write a horizontal run of color index pixels using the color index * last specified by the Index() function. */ static void AMesaWriteMonoCISpan( const GLcontext *ctx, GLuint n, GLint x, GLint y, GLuint colorIndex, const GLubyte mask[] ) { /* Not yet implemented */ } /* * Write a random array of CI pixels. */ static void AMesaWriteCI32Pixels( const GLcontext *ctx, GLuint n, const GLint x[], const GLint y[], const GLuint index[], const GLubyte mask[] ) { /* Not yet implemented */ } /* Write a random array of color index pixels using the color index * last specified by the Index() function. */ static void AMesaWriteMonoCIPixels( const GLcontext *ctx, GLuint n, const GLint x[], const GLint y[], GLuint colorIndex, const GLubyte mask[] ) { /* Not yet implemented */ } /* Read a horizontal run of color index pixels. */ static void AMesaReadCI32Span( const GLcontext *ctx, GLuint n, GLint x, GLint y, GLuint index[]) { /* Not yet implemented */ } /* Read a random array of CI pixels. */ static void AMesaReadCI32Pixels( const GLcontext *ctx, GLuint n, const GLint x[], const GLint y[], GLuint indx[], const GLubyte mask[] ) { /* Not yet implemented */ } static void AMesaClearDepth(GLcontext *ctx, GLclampd depth) { AMesaContext context = (AMesaContext)(ctx->DriverCtx); context->ClearDepth = depth * (2 << context->Visual->GLVisual->depthBits); } static void AMesaDepthRange(GLcontext *ctx, GLclampd nearval, GLclampd farval) { AMesaContext context = (AMesaContext)(ctx->DriverCtx); context->zFar = farval; context->zNear = nearval; } /* Write a horizontal span of values into the depth buffer. Only write * depth[i] value if mask[i] is nonzero. */ static void AMesaWriteDepthSpan( GLcontext *ctx, GLuint n, GLint x, GLint y, const GLdepth depth[], const GLubyte mask[]) { AMesaContext context = (AMesaContext)(ctx->DriverCtx); BITMAP *bmp = context->Buffer->Active; float* zb_addr = (float*)(bmp_write_line(context->Buffer->DepthBuffer, bmp->h - y) + x * sizeof(float)); while (n--) { if (mask[0]) zb_addr[0] = 1. / depth[0]; zb_addr++; mask++; depth++; } } /* Read a horizontal span of values from the depth buffer. */ static void AMesaReadDepthSpan( GLcontext *ctx, GLuint n, GLint x, GLint y, GLdepth depth[] ) { AMesaContext context = (AMesaContext)(ctx->DriverCtx); BITMAP *bmp = context->Buffer->Active; float* zb_addr = (float*)(bmp_write_line(context->Buffer->DepthBuffer, bmp->h - y) + x * sizeof(float)); while (n--) { depth[0] = (GLdepth) (1. / zb_addr[0]); zb_addr++; depth++; } } /* Write an array of randomly positioned depth values into the * depth buffer. Only write depth[i] value if mask[i] is nonzero. */ static void AMesaWriteDepthPixels( GLcontext *ctx, GLuint n, const GLint x[], const GLint y[], const GLdepth depth[], const GLubyte mask[] ) { AMesaContext context = (AMesaContext)(ctx->DriverCtx); BITMAP *bmp = context->Buffer->Active; ZBUFFER *zbuf = context->Buffer->DepthBuffer; float* zb_addr; while (n--) { if (mask[0]) { zb_addr = (float*)(bmp_write_line(zbuf, bmp->h - y[0]) + x[0] * sizeof(float)); zb_addr[0] = 1. / depth[0]; } x++; y++; mask++; depth++; } } /* Read an array of randomly positioned depth values from the depth buffer. */ static void AMesaReadDepthPixels( GLcontext *ctx, GLuint n, const GLint x[], const GLint y[], GLdepth depth[] ) { AMesaContext context = (AMesaContext)(ctx->DriverCtx); BITMAP *bmp = context->Buffer->Active; ZBUFFER *zbuf = context->Buffer->DepthBuffer; float* zb_addr; while (n--) { zb_addr = (float*)(bmp_write_line(zbuf, bmp->h - y[0]) + x[0] * sizeof(float)); depth[0] = (GLdepth) (1. / zb_addr[0]); x++; y++; depth++; } } /**********************************************************************/ /**********************************************************************/ /* Override for the swrast triangle-selection function. Try to use one * of our internal triangle functions, otherwise fall back to the * standard swrast functions. */ static void AMesaFlatLine(GLcontext *ctx, const SWvertex *v0, const SWvertex *v1) { AMesaContext context = (AMesaContext)(ctx->DriverCtx); BITMAP *buffer = context->Buffer->Active; int color_depth = bitmap_color_depth(buffer); int color = makecol_depth(color_depth, v0->color[RCOMP], v0->color[GCOMP], v0->color[BCOMP]); line(buffer, v0->win[0], buffer->h - v0->win[1], v1->win[0], buffer->h - v1->win[1], color); } static void AMesaSmoothTriangle(GLcontext *ctx, const SWvertex *v0, const SWvertex *v1, const SWvertex *v2 ) { AMesaContext context = (AMesaContext)(ctx->DriverCtx); V3D_f vtx1, vtx2, vtx3; BITMAP *buffer = context->Buffer->Active; int color_depth = bitmap_color_depth(buffer); vtx1.x = v0->win[0]; vtx1.y = buffer->h - v0->win[1]; vtx1.z = v0->win[2]; vtx1.c = makecol_depth(color_depth, v0->color[RCOMP], v0->color[GCOMP], v0->color[BCOMP]); vtx2.x = v1->win[0]; vtx2.y = buffer->h - v1->win[1]; vtx2.z = v1->win[2]; vtx2.c = makecol_depth(color_depth, v1->color[RCOMP], v1->color[GCOMP], v1->color[BCOMP]); vtx3.x = v2->win[0]; vtx3.y = buffer->h - v2->win[1]; vtx3.z = v2->win[2]; vtx3.c = makecol_depth(color_depth, v2->color[RCOMP], v2->color[GCOMP], v2->color[BCOMP]); triangle3d_f(buffer, POLYTYPE_GCOL, NULL, &vtx1, &vtx2, &vtx3); } static void AMesaFlatTriangle(GLcontext *ctx, const SWvertex *v0, const SWvertex *v1, const SWvertex *v2 ) { AMesaContext context = (AMesaContext)(ctx->DriverCtx); V3D_f vtx1, vtx2, vtx3; BITMAP *buffer = context->Buffer->Active; int color_depth = bitmap_color_depth(buffer); vtx1.x = v0->win[0]; vtx1.y = buffer->h - v0->win[1]; vtx1.z = v0->win[2]; vtx1.c = makecol_depth(color_depth, v0->color[RCOMP], v0->color[GCOMP], v0->color[BCOMP]); vtx2.x = v1->win[0]; vtx2.y = buffer->h - v1->win[1]; vtx2.z = v1->win[2]; vtx3.x = v2->win[0]; vtx3.y = buffer->h - v2->win[1]; vtx3.z = v2->win[2]; triangle3d_f(buffer, POLYTYPE_FLAT, NULL, &vtx1, &vtx2, &vtx3); } static void AMesaSmoothZTriangle(GLcontext *ctx, const SWvertex *v0, const SWvertex *v1, const SWvertex *v2 ) { AMesaContext context = (AMesaContext)(ctx->DriverCtx); V3D_f vtx1, vtx2, vtx3; BITMAP *buffer = context->Buffer->Active; int color_depth = bitmap_color_depth(buffer); vtx1.x = v0->win[0]; vtx1.y = buffer->h - v0->win[1]; vtx1.z = v0->win[2]; vtx1.c = makecol_depth(color_depth, v0->color[RCOMP], v0->color[GCOMP], v0->color[BCOMP]); vtx2.x = v1->win[0]; vtx2.y = buffer->h - v1->win[1]; vtx2.z = v1->win[2]; vtx2.c = makecol_depth(color_depth, v1->color[RCOMP], v1->color[GCOMP], v1->color[BCOMP]); vtx3.x = v2->win[0]; vtx3.y = buffer->h - v2->win[1]; vtx3.z = v2->win[2]; vtx3.c = makecol_depth(color_depth, v2->color[RCOMP], v2->color[GCOMP], v2->color[BCOMP]); triangle3d_f(buffer, POLYTYPE_GCOL | POLYTYPE_ZBUF, NULL, &vtx1, &vtx2, &vtx3); } static void AMesaFlatZTriangle(GLcontext *ctx, const SWvertex *v0, const SWvertex *v1, const SWvertex *v2 ) { AMesaContext context = (AMesaContext)(ctx->DriverCtx); V3D_f vtx1, vtx2, vtx3; BITMAP *buffer = context->Buffer->Active; int color_depth = bitmap_color_depth(buffer); vtx1.x = v0->win[0]; vtx1.y = buffer->h - v0->win[1]; vtx1.z = v0->win[2]; vtx1.c = makecol_depth(color_depth, v0->color[RCOMP], v0->color[GCOMP], v0->color[BCOMP]); vtx2.x = v1->win[0]; vtx2.y = buffer->h - v1->win[1]; vtx2.z = v1->win[2]; vtx3.x = v2->win[0]; vtx3.y = buffer->h - v2->win[1]; vtx3.z = v2->win[2]; triangle3d_f(buffer, POLYTYPE_FLAT | POLYTYPE_ZBUF, NULL, &vtx1, &vtx2, &vtx3); } static swrast_line_func AMesaChooseLineFunction(GLcontext *ctx) { const SWcontext *swrast = SWRAST_CONTEXT(ctx); if (ctx->RenderMode != GL_RENDER) return (swrast_line_func) NULL; if (ctx->Line.SmoothFlag) return (swrast_line_func) NULL; if (ctx->Line.StippleFlag) return (swrast_line_func) NULL; if (ctx->Line.Width != 1.0f) return (swrast_line_func) NULL; #ifdef MESA_5_0 if (ctx->Texture._EnabledUnits) return (swrast_line_func) NULL; #else if (ctx->Texture._ReallyEnabled) return (swrast_line_func) NULL; #endif if (ctx->Visual.depthBits != DEFAULT_SOFTWARE_DEPTH_BITS) return (swrast_line_func) NULL; if (swrast->_RasterMask != DEPTH_BIT && ctx->Light.ShadeModel != GL_SMOOTH) { return AMesaFlatLine; } return (swrast_line_func) NULL; } static swrast_tri_func AMesaChooseTriangleFunction(GLcontext *ctx) { const SWcontext *swrast = SWRAST_CONTEXT(ctx); if (ctx->RenderMode != GL_RENDER) return (swrast_tri_func) NULL; if (ctx->Polygon.SmoothFlag) return (swrast_tri_func) NULL; if (ctx->Polygon.StippleFlag) return (swrast_tri_func) NULL; #ifdef MESA_5_0 if (ctx->Texture._EnabledUnits) return (swrast_tri_func) NULL; #else if (ctx->Texture._ReallyEnabled) return (swrast_tri_func) NULL; #endif if (ctx->Polygon.CullFlag && ctx->Polygon.CullFaceMode == GL_FRONT_AND_BACK) return (swrast_tri_func) NULL; if (swrast->_RasterMask & DEPTH_BIT) { if (ctx->Depth.Func == GL_LESS && ctx->Depth.Mask == GL_TRUE) { if (ctx->Light.ShadeModel == GL_SMOOTH) return AMesaSmoothZTriangle; else return AMesaFlatZTriangle; } } else { if (ctx->Light.ShadeModel == GL_SMOOTH) return AMesaSmoothTriangle; else return AMesaFlatTriangle; } return (swrast_tri_func) NULL; } void AMesaChooseTriangle( GLcontext *ctx ) { SWcontext *swrast = SWRAST_CONTEXT(ctx); swrast->Triangle = AMesaChooseTriangleFunction( ctx ); if (!swrast->Triangle) _swrast_choose_triangle( ctx ); } void AMesaChooseLine( GLcontext *ctx ) { SWcontext *swrast = SWRAST_CONTEXT(ctx); swrast->Line = AMesaChooseLineFunction( ctx ); if (!swrast->Line) _swrast_choose_line( ctx ); } /**********************************************************************/ /**********************************************************************/ void AMesaUpdateState(GLcontext *ctx, GLuint new_state) { struct swrast_device_driver *swdd = _swrast_GetDeviceDriverReference( ctx ); TNLcontext *tnl = TNL_CONTEXT(ctx); /* Initialize all the pointers in the driver struct. Do this whenever * a new context is made current or we change buffers via set_buffer! */ ctx->Driver.GetString = AMesaGetString; ctx->Driver.UpdateState = AMesaUpdateState; #ifdef MESA_5_0 ctx->Driver.DrawBuffer = AMesaSetDrawBuffer; ctx->Driver.ReadBuffer = AMesaSetReadBuffer; swdd->SetBuffer = AMesaSetBuffer; #else ctx->Driver.SetDrawBuffer = AMesaSetDrawBuffer; swdd->SetReadBuffer = AMesaSetReadBuffer; #endif ctx->Driver.ClearIndex = AMesaClearIndex; ctx->Driver.ClearColor = clear_color_generic; ctx->Driver.Clear = clear_generic; ctx->Driver.GetBufferSize = AMesaGetBufferSize; #ifdef MESA_4_0_2 ctx->Driver.ResizeBuffers = _swrast_alloc_buffers; #else ctx->Driver.ResizeBuffersMESA = _swrast_alloc_buffers; #endif ctx->Driver.Accum = _swrast_Accum; ctx->Driver.Bitmap = _swrast_Bitmap; ctx->Driver.CopyPixels = _swrast_CopyPixels; ctx->Driver.DrawPixels = _swrast_DrawPixels; ctx->Driver.ReadPixels = _swrast_ReadPixels; ctx->Driver.ChooseTextureFormat = _mesa_choose_tex_format; ctx->Driver.TexImage1D = _mesa_store_teximage1d; ctx->Driver.TexImage2D = _mesa_store_teximage2d; ctx->Driver.TexImage3D = _mesa_store_teximage3d; ctx->Driver.TexSubImage1D = _mesa_store_texsubimage1d; ctx->Driver.TexSubImage2D = _mesa_store_texsubimage2d; ctx->Driver.TexSubImage3D = _mesa_store_texsubimage3d; ctx->Driver.TestProxyTexImage = _mesa_test_proxy_teximage; ctx->Driver.CopyTexImage1D = _swrast_copy_teximage1d; ctx->Driver.CopyTexImage2D = _swrast_copy_teximage2d; ctx->Driver.CopyTexSubImage1D = _swrast_copy_texsubimage1d; ctx->Driver.CopyTexSubImage2D = _swrast_copy_texsubimage2d; ctx->Driver.CopyTexSubImage3D = _swrast_copy_texsubimage3d; ctx->Driver.CopyColorTable = _swrast_CopyColorTable; ctx->Driver.CopyColorSubTable = _swrast_CopyColorSubTable; ctx->Driver.CopyConvolutionFilter1D = _swrast_CopyConvolutionFilter1D; ctx->Driver.CopyConvolutionFilter2D = _swrast_CopyConvolutionFilter2D; #ifdef MESA_5_0 ctx->Driver.CompressedTexImage1D = _mesa_store_compressed_teximage1d; ctx->Driver.CompressedTexImage2D = _mesa_store_compressed_teximage2d; ctx->Driver.CompressedTexImage3D = _mesa_store_compressed_teximage3d; ctx->Driver.CompressedTexSubImage1D = _mesa_store_compressed_texsubimage1d; ctx->Driver.CompressedTexSubImage2D = _mesa_store_compressed_texsubimage2d; ctx->Driver.CompressedTexSubImage3D = _mesa_store_compressed_texsubimage3d; #else ctx->Driver.BaseCompressedTexFormat = _mesa_base_compressed_texformat; ctx->Driver.CompressedTextureSize = _mesa_compressed_texture_size; ctx->Driver.GetCompressedTexImage = _mesa_get_compressed_teximage; #endif swdd->WriteCI32Span = AMesaWriteCI32Span; swdd->WriteCI8Span = AMesaWriteCI8Span; swdd->WriteMonoCISpan = AMesaWriteMonoCISpan; swdd->WriteCI32Pixels = AMesaWriteCI32Pixels; swdd->WriteMonoCIPixels = AMesaWriteMonoCIPixels; swdd->ReadCI32Span = AMesaReadCI32Span; swdd->ReadCI32Pixels = AMesaReadCI32Pixels; swdd->WriteRGBASpan = write_rgba_span_generic; swdd->WriteRGBSpan = write_rgb_span_generic; swdd->WriteMonoRGBASpan = write_mono_rgba_span_generic; swdd->WriteRGBAPixels = write_rgba_pixels_generic; swdd->WriteMonoRGBAPixels = write_mono_rgba_pixels_generic; swdd->ReadRGBASpan = read_rgba_span_generic; swdd->ReadRGBAPixels = read_rgba_pixels_generic; ctx->Driver.ClearDepth = AMesaClearDepth; ctx->Driver.DepthRange = AMesaDepthRange; swdd->WriteDepthSpan = AMesaWriteDepthSpan; swdd->ReadDepthSpan = AMesaReadDepthSpan; swdd->WriteDepthPixels = AMesaWriteDepthPixels; swdd->ReadDepthPixels = AMesaReadDepthPixels; tnl->Driver.RunPipeline = _tnl_run_pipeline; _swrast_InvalidateState( ctx, new_state ); _swsetup_InvalidateState( ctx, new_state ); _ac_InvalidateState( ctx, new_state ); _tnl_InvalidateState( ctx, new_state ); } allegro4.4-4.4.2/addons/allegrogl/src/amesa/raster.h000066400000000000000000000030101173507505700221460ustar00rootroot00000000000000#include "context.h" #include "colormac.h" #include "depth.h" #include "extensions.h" #include "macros.h" #include "matrix.h" #include "mmath.h" #include "mtypes.h" #include "texformat.h" #include "texstore.h" #include "array_cache/acache.h" #include "swrast/swrast.h" #include "swrast_setup/swrast_setup.h" #include "swrast/s_context.h" #include "swrast/s_depth.h" #include "swrast/s_lines.h" #include "swrast/s_triangle.h" #include "swrast/s_trispan.h" #include "tnl/tnl.h" #include "tnl/t_context.h" #include "tnl/t_pipeline.h" typedef struct amesa_visual { GLvisual* GLVisual; /* inherit from GLvisual */ GLboolean DBFlag; /* double buffered? */ GLint Depth; /* bits per pixel ( >= 15 ) */ } amesa_visual; typedef struct amesa_buffer { GLframebuffer* GLBuffer; /* inherit from GLframebuffer */ GLint Width; GLint Height; BITMAP* FrontBuffer; BITMAP* BackBuffer; BITMAP* Active; BITMAP* ReadActive; ZBUFFER* DepthBuffer; } amesa_buffer; typedef struct amesa_context { GLcontext* GLContext; /* inherit from GLcontext */ AMesaVisual Visual; AMesaBuffer Buffer; GLint ClearColor; GLuint ClearIndex; GLuint ColorIndex; float ClearDepth; float zNear; float zFar; } amesa_context; extern AMesaContext AMesa; void AMesaUpdateState(GLcontext *ctx, GLuint new_state); void AMesaChooseLine(GLcontext *ctx); void AMesaChooseTriangle(GLcontext *ctx); allegro4.4-4.4.2/addons/allegrogl/src/djgpp.c000066400000000000000000000402221173507505700206650ustar00rootroot00000000000000/* This code is (C) AllegroGL contributors, and double licensed under * the GPL and zlib licenses. See gpl.txt or zlib.txt for details. */ /*---------------------------------------------------------------- * amesa.c -- Allegro-Mesa interfacing *---------------------------------------------------------------- * This is the interface module for use AllegroGL with Mesa using the AMesa driver. */ #include #include #include #include #include #include "alleggl.h" #include "allglint.h" #include "glvtable.h" static void allegro_gl_amesa_exit(BITMAP *bmp); static void __allegro_gl_init_texture_read_format(void); #ifdef GFX_OPENGL_FULLSCREEN static BITMAP *allegro_gl_amesa_fullscreen_init(int w, int h, int vw, int vh, int color_depth); GFX_DRIVER gfx_allegro_gl_fullscreen = { GFX_OPENGL_FULLSCREEN, empty_string, empty_string, "AllegroGL Fullscreen (AMesa)", allegro_gl_amesa_fullscreen_init, allegro_gl_amesa_exit, NULL, NULL, //_xwin_vsync, NULL, NULL, NULL, NULL, allegro_gl_create_video_bitmap, allegro_gl_destroy_video_bitmap, NULL, NULL, /* No show/request video bitmaps */ NULL, NULL, allegro_gl_set_mouse_sprite, allegro_gl_show_mouse, allegro_gl_hide_mouse, allegro_gl_move_mouse, NULL, NULL, NULL, NULL, /* No fetch_mode_list */ 0, 0, 0, 0, 0, 0, 0, FALSE /* Windowed mode */ }; #endif /* GFX_OPENGL_FULLSCREEN */ #ifdef GFX_OPENGL_WINDOWED static BITMAP *allegro_gl_amesa_windowed_init(int w, int h, int vw, int vh, int color_depth); GFX_DRIVER gfx_allegro_gl_windowed = { GFX_OPENGL_WINDOWED, empty_string, empty_string, "AllegroGL Windowed (AMesa)", allegro_gl_amesa_windowed_init, allegro_gl_amesa_exit, NULL, NULL, //_xwin_vsync, NULL, NULL, NULL, NULL, allegro_gl_create_video_bitmap, allegro_gl_destroy_video_bitmap, NULL, NULL, /* No show/request video bitmaps */ NULL, NULL, allegro_gl_set_mouse_sprite, allegro_gl_show_mouse, allegro_gl_hide_mouse, allegro_gl_move_mouse, NULL, NULL, NULL, NULL, /* No fetch_mode_list */ 0, 0, 0, 0, 0, 0, 0, TRUE /* Windowed mode */ }; #endif /* GFX_OPENGL_WINDOWED */ static int allegro_gl_amesa_create_window (int fullscreen); static BITMAP *allegro_gl_amesa_create_screen_bitmap (GFX_DRIVER *drv, int w, int h, int depth); struct AMESA_DATA { int fullscreen; AMesaVisual visual; AMesaBuffer buffer; AMesaContext context; } AMESA_DATA; static struct AMESA_DATA _amesa; static struct allegro_gl_driver allegro_gl_amesa; static BITMAP* subscreen = NULL; /* Sub_bitmap of the virtual screen */ static BITMAP* saved_screen = NULL; /* Saves screen address */ GFX_DRIVER *amesa_gfx_driver = NULL; static GFX_VTABLE allegro_gl_generic_vtable; static GFX_VTABLE *old_vtable; /* allegro_gl_amesa_create_screen: * Creates screen bitmap. */ static BITMAP *allegro_gl_amesa_create_screen(int w, int h, int vw, int vh, int depth, int fullscreen) { int _keyboard_was_installed = FALSE; int _mouse_was_installed = FALSE; GFX_VTABLE vtable, *pvtable; pvtable = &vtable; if (keyboard_driver) { _keyboard_was_installed = TRUE; remove_keyboard(); TRACE("* Note * amesa_create_screen: Removing Keyboard...\n"); } if (mouse_driver) { _mouse_was_installed = TRUE; remove_mouse(); TRACE("* Note * amesa_create_screen: Removing Mouse...\n"); } if ((w == 0) && (h == 0)) { w = 640; h = 480; } if ((vw > w) || (vh > h)) { ustrzcpy (allegro_error, ALLEGRO_ERROR_SIZE, get_config_text ("OpenGL drivers do not support virtual screens")); return NULL; } allegro_gl_display_info.w = w; allegro_gl_display_info.h = h; if (allegro_gl_amesa_create_window(fullscreen)) { if (fullscreen) { ustrzcpy (allegro_error, ALLEGRO_ERROR_SIZE, get_config_text ("Unable to switch in AMesa fullscreen")); } else { ustrzcpy (allegro_error, ALLEGRO_ERROR_SIZE, get_config_text ("Unable to create AMesa window")); } return NULL; } /* If pixel format is Allegro compatible, set up Allegro correctly. */ if (fullscreen) { #ifdef GFX_OPENGL_FULLSCREEN allegro_gl_screen = allegro_gl_amesa_create_screen_bitmap (&gfx_allegro_gl_fullscreen, w, h, allegro_gl_display_info.colour_depth); #endif } else { #ifdef GFX_OPENGL_WINDOWED allegro_gl_screen = allegro_gl_amesa_create_screen_bitmap (&gfx_allegro_gl_windowed, w, h, allegro_gl_display_info.colour_depth); #endif } if (!allegro_gl_screen) { ustrzcpy (allegro_error, ALLEGRO_ERROR_SIZE, get_config_text ("Error creating screen bitmap")); return NULL; } __allegro_gl_valid_context = TRUE; __allegro_gl_driver = &allegro_gl_amesa; LOCK_DATA(&_amesa, sizeof(AMESA_DATA)); LOCK_DATA(__allegro_gl_driver, sizeof(struct allegro_gl_driver)); /* save the old vtable and create a copy */ old_vtable = allegro_gl_screen->vtable; memcpy(&allegro_gl_generic_vtable, allegro_gl_screen->vtable, sizeof(GFX_VTABLE)); allegro_gl_screen->vtable = &allegro_gl_generic_vtable; /* The generic driver does not use the glvtable (since it already uses * 'pure' Allegro gfx functions. However it needs the AGL-specific * draw_glyph method. * Hence this hack : we call __allegro_gl__glvtable_update_vtable with * 'pvtable' as a parameter since we do not want the regular * allegro_gl_screen->vtable to be crushed. */ __allegro_gl__glvtable_update_vtable(&pvtable); allegro_gl_screen->vtable->draw_glyph = pvtable->draw_glyph; memcpy(&_screen_vtable, allegro_gl_screen->vtable, sizeof(GFX_VTABLE)); allegro_gl_screen->vtable = &_screen_vtable; __allegro_gl_init_screen_mode(); /* Print out OpenGL version info */ TRACE("\n\nOpenGL Version: %s\nVendor: %s\nRenderer: %s\n", (const char*)glGetString(GL_VERSION), (const char*)glGetString(GL_VENDOR), (const char*)glGetString(GL_RENDERER)); /* Prints out OpenGL extensions info and activates needed extensions */ __allegro_gl_manage_extensions(); __allegro_gl_init_texture_read_format(); if (_keyboard_was_installed) { install_keyboard(); TRACE("* Note * amesa_create_screen: Installing Keyboard...\n"); } if (_mouse_was_installed) { install_mouse(); TRACE("* Note * amesa_create_screen: Installing Mouse...\n"); } /* XXX Maybe we should leave this for autodetection? */ gfx_capabilities |= GFX_HW_CURSOR; allegro_gl_info.is_mesa_driver = TRUE; _amesa.fullscreen = fullscreen; return allegro_gl_screen; } #ifdef GFX_OPENGL_WINDOWED /* allegro_gl_amesa_windowed_init: * Creates screen bitmap for windowed driver. */ static BITMAP *allegro_gl_amesa_windowed_init(int w, int h, int vw, int vh, int depth) { return allegro_gl_amesa_create_screen(w, h, vw, vh, depth, FALSE); } #endif #ifdef GFX_OPENGL_FULLSCREEN /* allegro_gl_amesa_fullscreen_init: * Creates screen bitmap for fullscreen driver. */ static BITMAP *allegro_gl_amesa_fullscreen_init(int w, int h, int vw, int vh, int depth) { return allegro_gl_amesa_create_screen(w, h, vw, vh, depth, TRUE); } #endif /* allegro_gl_amesa_exit: * Shuts down the driver (shared between windowed and full-screen) */ static void allegro_gl_amesa_exit(BITMAP *bmp) { /* Restore the screen to its intial value */ screen = saved_screen; if (subscreen) destroy_bitmap(subscreen); amesa_gfx_driver->exit(screen); AMesaMakeCurrent(_amesa.context, NULL); AMesaDestroyVisual(_amesa.visual); AMesaDestroyBuffer(_amesa.buffer); AMesaDestroyContext(_amesa.context); __allegro_gl_valid_context = FALSE; } static void amesa_choose_gfx_mode(_DRIVER_INFO *driver_info, int *w, int *h, int *colour_depth) { GFX_MODE_LIST *mode_list; GFX_MODE *mode; int i; TRACE("* Note * amesa_choose_gfx_mode: GFX driver : %s\n", ((GFX_DRIVER*)driver_info->driver)->ascii_name); /* Try to find a mode which resolution and color depth are higher or * equal to those requested */ mode_list = get_gfx_mode_list(driver_info->id); if (mode_list) { TRACE("* Note * amesa_choose_gfx_mode: %i modes\n", mode_list->num_modes); mode = mode_list->mode; for (i = 0; i < mode_list->num_modes; i++) { TRACE("Mode %i : %ix%i %i bpp\n", i, mode->width, mode->height, mode->bpp); if ((mode->width >= *w) && (mode->height >= *h) && (mode->bpp >= *colour_depth)) { break; } if (mode->width) { mode++; } } if ((mode->width) && (mode->height) && (mode->bpp)) { allegro_gl_display_info.w = *w = mode->width; allegro_gl_display_info.h = *h = mode->height; allegro_gl_display_info.colour_depth = *colour_depth = mode->bpp; } TRACE("Best Mode : %ix%i %i bpp\n", *w, *h, *colour_depth); destroy_gfx_mode_list(mode_list); } else { TRACE("** Warning ** amesa_choose_gfx_mode: Can not list modes...\n" "Trying %ix%i %i bpp anyway\n", *w, *h, *colour_depth); } } /* amesa_set_gfx_mode : * A light version of set_gfx_mode since when this function is reached we are * ALREADY in set_gfx_mode. No need to initialize some parameters. * Moreover we must choose our driver in saved_gfx_drivers and set the real * gfx driver (i.e. the GFX_OPENGL one) the right way. */ static int amesa_set_gfx_mode(int fullscreen) { extern void blit_end(); _DRIVER_INFO *driver_list; int tried = FALSE; char buf[512], tmp[64]; int c, n; int card = GFX_AUTODETECT; int w = allegro_gl_display_info.w; int h = allegro_gl_display_info.h; int check_mode = TRUE, require_window = FALSE; driver_list = saved_gfx_drivers(); if (!fullscreen) require_window = TRUE; /* try the drivers that are listed in the config file */ for (n=-2; n<255; n++) { switch (n) { case -2: /* example: gfx_card_640x480x16 = */ usprintf(buf, uconvert_ascii("gfx_card_%dx%dx%d", tmp), w, h, _color_depth); break; case -1: /* example: gfx_card_24bpp = */ usprintf(buf, uconvert_ascii("gfx_card_%dbpp", tmp), _color_depth); break; case 0: /* example: gfx_card = */ ustrcpy(buf, uconvert_ascii("gfx_card", tmp)); break; default: /* example: gfx_card1 = */ usprintf(buf, uconvert_ascii("gfx_card%d", tmp), n); break; } card = get_config_id(uconvert_ascii("graphics", tmp), buf, GFX_AUTODETECT); if (card != GFX_AUTODETECT) { for (c=0; driver_list[c].driver; c++) { if (driver_list[c].id == card) { amesa_gfx_driver = driver_list[c].driver; if (check_mode) { if ( ((require_window) && (!amesa_gfx_driver->windowed)) || ((!require_window) && (amesa_gfx_driver->windowed))) { amesa_gfx_driver = NULL; continue; } } break; } } if (amesa_gfx_driver) { tried = TRUE; amesa_gfx_driver->name = amesa_gfx_driver->desc = get_config_text(amesa_gfx_driver->ascii_name); amesa_choose_gfx_mode(&driver_list[c], &w, &h, &_color_depth); screen = amesa_gfx_driver->init(w, h, 0, 0, _color_depth); if (screen) { break; } else { amesa_gfx_driver = NULL; } } } else { if (n > 1) { break; } } } if (!tried) { for (c=0; driver_list[c].driver; c++) { if (driver_list[c].autodetect) { amesa_gfx_driver = driver_list[c].driver; if (check_mode) { if (((require_window) && (!amesa_gfx_driver->windowed)) || ((!require_window) && (amesa_gfx_driver->windowed))) continue; } amesa_gfx_driver->name = amesa_gfx_driver->desc = get_config_text(amesa_gfx_driver->ascii_name); amesa_choose_gfx_mode(&driver_list[c], &w, &h, &_color_depth); screen = amesa_gfx_driver->init(w, h, 0, 0, _color_depth); if (screen) { break; } } } } if (!screen) { amesa_gfx_driver = NULL; return -1; } LOCK_DATA(amesa_gfx_driver, sizeof(GFX_DRIVER)); _register_switch_bitmap(screen, NULL); return 0; } /* create_window: * Based on Bernhard Tschirren AMesa GLUT code. */ static int allegro_gl_amesa_create_window (int fullscreen) { if (!allegro_gl_display_info.colour_depth) allegro_gl_display_info.colour_depth = _color_depth; set_color_depth(allegro_gl_display_info.colour_depth); if (amesa_set_gfx_mode(fullscreen)) { TRACE("** ERROR ** amesa_create_window: Unable to set a gfx mode!\n"); return 1; } _amesa.visual = AMesaCreateVisual(allegro_gl_display_info.doublebuffered, allegro_gl_display_info.colour_depth, GL_TRUE, /* RGBA Mode */ allegro_gl_display_info.depth_size, allegro_gl_display_info.stencil_size, allegro_gl_display_info.accum_size.rgba.r, allegro_gl_display_info.accum_size.rgba.g, allegro_gl_display_info.accum_size.rgba.b, allegro_gl_display_info.accum_size.rgba.a ); if (!_amesa.visual) { TRACE("** ERROR ** amesa_create_window: Unable to create AMesa " "Visual\n"); return 1; } _amesa.context = AMesaCreateContext(_amesa.visual, NULL); if (!_amesa.context) { TRACE("** ERROR ** amesa_create_window: Unable to create AMesa " "Context\n"); AMesaDestroyVisual(_amesa.visual); return 1; } if ((screen->w != allegro_gl_display_info.w) || (screen->h != allegro_gl_display_info.h)) { subscreen = create_sub_bitmap(screen, 0, 0, allegro_gl_display_info.w, allegro_gl_display_info.h); _amesa.buffer = AMesaCreateBuffer(_amesa.visual, subscreen); TRACE("** Note ** amesa_create_window: Screen : %ix%i %i bpp\n", ubscreen->w, subscreen->h, bitmap_color_depth(subscreen)); } else { _amesa.buffer = AMesaCreateBuffer(_amesa.visual, screen); } if (!_amesa.buffer) { AMesaDestroyContext(_amesa.context); AMesaDestroyVisual(_amesa.visual); TRACE("** ERROR ** amesa_create_window: Unable to create AMesa " "Buffer\n"); return 1; } if (!AMesaMakeCurrent(_amesa.context, _amesa.buffer)) { AMesaDestroyContext(_amesa.context); AMesaDestroyVisual(_amesa.visual); AMesaDestroyBuffer(_amesa.buffer); TRACE("** ERROR ** amesa_create_window: Unable to make context " "current\n"); return 1; } saved_screen = screen; return 0; } static BITMAP *allegro_gl_amesa_create_screen_bitmap (GFX_DRIVER *drv, int w, int h, int depth) { drv->w = w; drv->h = h; drv->linear = amesa_gfx_driver->linear; drv->bank_size = amesa_gfx_driver->bank_size; drv->bank_gran = amesa_gfx_driver->bank_gran; drv->vid_mem = amesa_gfx_driver->vid_mem; drv->vid_phys_base = amesa_gfx_driver->vid_phys_base; return AMesaGetColorBuffer(_amesa.buffer, AMESA_ACTIVE); } static void __allegro_gl_init_texture_read_format(void) { /* 8 bpp (true color mode) */ __allegro_gl_texture_read_format[0] = GL_UNSIGNED_BYTE_3_3_2; /* 15 bpp */ if (_rgb_r_shift_15 > _rgb_b_shift_15) { __allegro_gl_texture_read_format[1] = GL_UNSIGNED_SHORT_5_5_5_1; if (_rgb_r_shift_15 == 10) { __allegro_gl_texture_components[1] = GL_BGRA; } } else { __allegro_gl_texture_read_format[1] = GL_UNSIGNED_SHORT_1_5_5_5_REV; } /* 16 bpp */ if (_rgb_r_shift_16 > _rgb_b_shift_16) { __allegro_gl_texture_read_format[2] = GL_UNSIGNED_SHORT_5_6_5; } else { __allegro_gl_texture_read_format[2] = GL_UNSIGNED_SHORT_5_6_5_REV; } /* 24 bpp */ __allegro_gl_texture_read_format[3] = GL_UNSIGNED_BYTE; /* 32 bpp */ if (_rgb_r_shift_32 > _rgb_b_shift_32) { __allegro_gl_texture_read_format[4] = GL_UNSIGNED_INT_8_8_8_8_REV; if (_rgb_r_shift_32 == 16) { __allegro_gl_texture_components[4] = GL_BGRA; } } else { __allegro_gl_texture_read_format[4] = GL_UNSIGNED_BYTE; } } /******************************/ /* AllegroGL driver functions */ /******************************/ /* flip: * Does a page flip / double buffer copy / whatever it really is. */ static void amesa_flip (void) { AMesaSwapBuffers (_amesa.buffer); } /* gl_on, gl_off: * Switches to/from GL mode. */ static void amesa_gl_on (void) { } static void amesa_gl_off (void) { } /*****************/ /* Driver struct */ /*****************/ static struct allegro_gl_driver allegro_gl_amesa = { amesa_flip, amesa_gl_on, amesa_gl_off }; allegro4.4-4.4.2/addons/allegrogl/src/fontconv.c000066400000000000000000001311131173507505700214150ustar00rootroot00000000000000/* This code is (C) AllegroGL contributors, and double licensed under * the GPL and zlib licenses. See gpl.txt or zlib.txt for details. */ /** \file fontconv.c * \brief Allegro FONT conversion routines. * * Notes: - Depends on the Allegro's FONT structure remaining * intact. * Bugs: - Bitmapped font support is flakey at best. * */ #include #include #include #include #include #include "alleggl.h" #include "allglint.h" #ifdef ALLEGRO_MACOSX #include #else #include #endif #if defined ALLEGRO_WITH_XWINDOWS && !defined ALLEGROGL_GENERIC_DRIVER #include #include #endif #define PREFIX_I "agl-font INFO: " #define PREFIX_W "agl-font WARNING: " #define PREFIX_E "agl-font ERROR: " /* Number of pixels between characters in a textured font. */ #define FONT_CHARACTER_SPACING 2 /* Uncomment to have the font generator dump screenshots of the textures it * generates. */ /* #define SAVE_FONT_SCREENSHOT */ static int agl_get_font_height(AL_CONST FONT *f); static int agl_char_length(const FONT *f, int ch); static int agl_text_length(const FONT *f, const char *str); static int agl_get_font_ranges(FONT *f); static int agl_get_font_range_begin(FONT *f, int range); static int agl_get_font_range_end(FONT *f, int range); static FONT *agl_extract_font_range(FONT *f, int start, int end); static FONT *agl_merge_fonts(FONT *f1, FONT *f2); #if GET_ALLEGRO_VERSION() >= MAKE_VER(4, 2, 0) static int agl_transpose_font(FONT *f, int drange); #endif FONT_VTABLE _agl_font_vtable = { agl_get_font_height, agl_char_length, agl_text_length, NULL, /* render_char */ NULL, /* render */ allegro_gl_destroy_font, agl_get_font_ranges, agl_get_font_range_begin, agl_get_font_range_end, agl_extract_font_range, agl_merge_fonts, #if GET_ALLEGRO_VERSION() >= MAKE_VER(4, 2, 0) agl_transpose_font #endif }; FONT_VTABLE *font_vtable_agl = &_agl_font_vtable; static void aglf_convert_allegro_font_to_bitmap(FONT_AGL_DATA *dest, FONT *f, void *src, int *height); static void aglf_convert_allegro_font_to_texture(FONT_AGL_DATA **dest, FONT *f, void *src, int *height, float scale, GLint format); static GLuint aglf_upload_texture(BITMAP *bmp, GLint format, int has_alpha); static int aglf_check_texture(BITMAP *bmp, GLint format, int has_alpha); static BITMAP* look_for_texture(int beg, int end, AGL_GLYPH *glyphs, int max_w, int max_h, int total_area, GLint format, int has_alpha); union mixed_ptr { FONT_MONO_DATA* mf; FONT_COLOR_DATA* cf; void *ptr; }; /* Stores info about a texture size */ typedef struct texture_size { int w, h; } texture_size; static int agl_get_font_height(AL_CONST FONT *f) { return f->height; } /* iroundf: * Round float to nearest integer, away from zero. */ static int iroundf(float v) { float f = floor(v); float c = ceil(v); if (v >= 0) { /* distance to ceil smaller than distance to floor */ if ((c - v) < (v - f)) return (int)c; else return (int)f; } else { /* distance to ceil smaller than distance to floor */ if ((c - v) < (v - f)) return (int)f; else return (int)c; } } /* agl_char_length_fractional: * Returns the width, in fractional pixels of the given character. */ static float agl_char_length_fractional(const FONT *f, int ch) { FONT_AGL_DATA *fad = f->data; if (fad->type == AGL_FONT_TYPE_TEXTURED) { while (fad) { if (ch >= fad->start && ch < fad->end) { AGL_GLYPH *coords = &(fad->glyph_coords[ch - fad->start]); return (coords->offset_x + coords->w + coords->offset_w) / fabs(fad->scale); } fad = fad->next; } } else if (fad->type == AGL_FONT_TYPE_BITMAP) { while (fad) { if (ch >= fad->start && ch < fad->end) { FONT_GLYPH **gl = fad->data; return gl[ch - fad->start]->w; } fad = fad->next; } } /* if we don't find the character, then search for the missing * glyph, but don't get stuck in a loop. */ if (ch != allegro_404_char) return agl_char_length_fractional(f, allegro_404_char); return 0; } /* agl_char_length: * font vtable entry * Returns the width, in pixels of the given character. */ static int agl_char_length(const FONT *f, int ch) { return iroundf(agl_char_length_fractional(f, ch)); } /* agl_text_length: * font vtable entry * Returns the length, in pixels, of a string as rendered in a font. */ static int agl_text_length(const FONT *f, const char *str) { int ch = 0; float l = 0; const char *p = str; ASSERT(f); ASSERT(str); while ( (ch = ugetxc(&p)) ) { l += agl_char_length_fractional(f, ch); } return iroundf(l); } /* agl_get_font_ranges: * font vtable entry * Returns the number of character ranges in a font, or -1 if that information * is not available. */ static int agl_get_font_ranges(FONT *f) { FONT_AGL_DATA *fad; int ranges = 0; if (!f) return 0; fad = (FONT_AGL_DATA*)(f->data); while (fad) { FONT_AGL_DATA *next = fad->next; ranges++; if (!next) return ranges; fad = next; } return -1; } /* agl_get_font_range_begin: * font vtable entry * Get first character for font. */ static int agl_get_font_range_begin(FONT *f, int range) { FONT_AGL_DATA *fad; int n = 0; if (!f || !f->data) return -1; if (range < 0) range = 0; fad = (FONT_AGL_DATA*)(f->data); while (fad && n <= range) { FONT_AGL_DATA *next = fad->next; if (!next || range == n) return fad->start; fad = next; n++; } return -1; } /* agl_get_font_range_end: * font vtable entry * Get last character for font range. */ static int agl_get_font_range_end(FONT *f, int range) { FONT_AGL_DATA* fad = 0; int n = 0; if (!f || !f->data) return -1; fad = (FONT_AGL_DATA*)(f->data); while (fad && (n <= range || range == -1)) { FONT_AGL_DATA *next = fad->next; if (!next || range == n) return fad->end - 1; fad = next; n++; } return -1; } /* Creates a call lists from given glyph coords. Returns list base.*/ static int create_textured_font_call_lists(AGL_GLYPH *coords, int max, BITMAP *bmp, float scale, int *height) { GLuint list; int i; int rev = scale < 0 ? 1 : 0; scale = fabs(scale); list = glGenLists(max); for (i = 0; i < max; i++) { /* Coords of glyph in texture (texture coords) */ float tx = (float)coords[i].x / bmp->w; float ty = 1.0 - (float)coords[i].y / bmp->h; /* Size of glyph in texture (texture coords) */ float dtx = (float)(coords[i].w) / bmp->w; float dty = (float)(coords[i].h) / bmp->h; /* Offset to apply to glyph (output coords) */ float xoffs = (float)coords[i].offset_x / scale; float yoffs = (float)coords[i].offset_y / scale; /* Size of rendered glyph (output coords) */ float woffs = (float)coords[i].w / scale; float hoffs = (float)coords[i].h / scale; /* Size of overall screen character including dead space */ float sizew = (float)(coords[i].offset_x + coords[i].w + coords[i].offset_w) / scale; int sizeh = iroundf((coords[i].offset_y + coords[i].h + coords[i].offset_h) / scale); if ((*height) < sizeh) *height = sizeh; if (rev) { hoffs = -hoffs; yoffs = -yoffs; } glNewList(list + i, GL_COMPILE); glBegin(GL_QUADS); glTexCoord2f(tx, ty); glVertex2f(xoffs, -yoffs); glTexCoord2f(tx + dtx, ty); glVertex2f(xoffs + woffs, -yoffs); glTexCoord2f(tx + dtx, ty - dty); glVertex2f(xoffs + woffs, -yoffs - hoffs); glTexCoord2f(tx, ty - dty); glVertex2f(xoffs, -yoffs - hoffs); glEnd(); glTranslatef(sizew, 0, 0); glEndList(); } return list; } /* copy_glyph_range: * Copies part of glyph range. */ static FONT_AGL_DATA* copy_glyph_range(FONT_AGL_DATA *fad, int start, int end, int *height) { int i, count, w = 0, h = 0; AGL_GLYPH *coords; BITMAP *bmp, *srcbmp; FONT_AGL_DATA *newfad = NULL; if (fad->type != AGL_FONT_TYPE_TEXTURED) return NULL; count = end - start; coords = malloc(count * sizeof (AGL_GLYPH)); /* for now, just copy glyph coords of the range */ for (i = 0; i < count; i++) { coords[i] = fad->glyph_coords[start - fad->start + i]; coords[i].glyph_num = i; } /* calculate the width of the glyphs and find the max height */ for (i = 0; i < count; i++) { int hh = coords[i].h + coords[i].offset_y + coords[i].offset_h; if (h < hh) h = hh; w += coords[i].w + coords[i].offset_w + coords[i].offset_x; } srcbmp = (BITMAP*)fad->data; /* allocate a new bitmap to hold new glyphs */ w = __allegro_gl_make_power_of_2(w); h = __allegro_gl_make_power_of_2(h); bmp = create_bitmap_ex(bitmap_color_depth(srcbmp), w, h); if (!bmp) { TRACE(PREFIX_E "copy_glyph_range: Unable to create bitmap of size" "%ix%i pixels!\n", w, h); free(coords); return NULL; } if (__allegro_gl_get_num_channels(fad->format) == 4) { clear_to_color(bmp, bitmap_mask_color(bmp)); } else { clear_bitmap(bmp); } /* blit every glyph from the range to the new bitmap */ w = 0; for (i = 0; i < count; i++) { int ch = start - fad->start + i; int ww = coords[i].w + coords[i].offset_w + coords[i].offset_x; blit(srcbmp, bmp, fad->glyph_coords[ch].x, 0, w, 0, ww, bmp->h); /* fix new glyphs coords while here */ coords[i].x = w; w += ww; } newfad = malloc(sizeof(struct FONT_AGL_DATA)); newfad->type = AGL_FONT_TYPE_TEXTURED; newfad->is_free_chunk = 0; newfad->scale = fad->scale; newfad->format = fad->format; newfad->has_alpha = fad->has_alpha; newfad->start = start; newfad->end = end; newfad->data = bmp; newfad->glyph_coords = coords; newfad->next = NULL; newfad->list_base = create_textured_font_call_lists(coords, count, bmp, newfad->scale, height); newfad->texture = aglf_upload_texture(bmp, newfad->format, newfad->has_alpha); return newfad; } /* agl_extract_font_range: * font vtable entry * Extracts a glyph range from a given font and makes a new font of it. */ static FONT *agl_extract_font_range(FONT *f, int start, int end) { FONT *retval = NULL; FONT_AGL_DATA *fad, *next, *newfad = NULL; int count; if (!f) return NULL; /* check if range boundaries make sense */ if (start == -1 && end == -1) { } else if (start == -1 && end > agl_get_font_range_begin(f, -1)) { } else if (end == -1 && start <= agl_get_font_range_end(f, -1)) { } else if (start <= end && start != -1 && end != -1) { } else return NULL; fad = (FONT_AGL_DATA*)f->data; /* only textured fonts are supported */ if (fad->type != AGL_FONT_TYPE_TEXTURED) return NULL; /* anticipate invalid range values */ start = MAX(start, agl_get_font_range_begin(f, -1)); if (end > -1) { end = MIN(end, agl_get_font_range_end(f, -1)); } else { end = agl_get_font_range_end(f, -1); } end++; retval = malloc(sizeof (struct FONT)); retval->height = 0; retval->vtable = font_vtable_agl; next = fad; count = end - start; while (next) { /* find the range that is covered by the requested range * check if the requested and processed ranges at least overlap * or if the requested range wraps processed range. */ if ((start >= next->start && start < next->end) || (end <= next->end && end > next->start) || (start < next->start && end > next->end)) { int local_start, local_end; /* extract the overlapping range */ local_start = MAX(next->start, start); local_end = MIN(next->end, end); if (newfad) { newfad->next = copy_glyph_range(next, local_start, local_end, &(retval->height)); newfad = newfad->next; newfad->is_free_chunk = TRUE; } else { newfad = copy_glyph_range(next, local_start, local_end, &(retval->height)); retval->data = newfad; } } next = next->next; } return retval; } /* agl_merge_fonts: * font vtable entry * Merges f2 with f1 and returns a new font. */ static FONT *agl_merge_fonts(FONT *f1, FONT *f2) { FONT *retval; FONT_AGL_DATA *fad1, *fad2, *fad = NULL; int phony = 0; if (!f1 || !f2) return NULL; fad1 = (FONT_AGL_DATA*)f1->data; fad2 = (FONT_AGL_DATA*)f2->data; /* fonts must be textured and of the same format */ if (fad1->type != AGL_FONT_TYPE_TEXTURED || fad2->type != AGL_FONT_TYPE_TEXTURED) return NULL; if (fad1->format != fad2->format) return NULL; /* alloc output font */ retval = malloc(sizeof(struct FONT)); retval->vtable = font_vtable_agl; retval->height = MAX(f1->height, f2->height); while (fad1 || fad2) { if (fad1 && (!fad2 || fad1->start < fad2->start)) { if (fad) { fad->next = copy_glyph_range(fad1, fad1->start, fad1->end, &phony); fad = fad->next; fad->is_free_chunk = TRUE; } else { fad = copy_glyph_range(fad1, fad1->start, fad1->end, &phony); retval->data = fad; } fad1 = fad1->next; } else { if (fad) { fad->next = copy_glyph_range(fad2, fad2->start, fad2->end, &phony); fad = fad->next; fad->is_free_chunk = TRUE; } else { fad = copy_glyph_range(fad2, fad2->start, fad2->end, &phony); retval->data = fad; } fad2 = fad2->next; } } return retval; } #if GET_ALLEGRO_VERSION() >= MAKE_VER(4, 2, 0) /* agl_transpose_font: * font vtable entry * Transposes characters in a font. */ static int agl_transpose_font(FONT *f, int drange) { FONT_AGL_DATA* fad = 0; if (!f) return -1; fad = (FONT_AGL_DATA*)(f->data); while(fad) { FONT_AGL_DATA* next = fad->next; fad->start += drange; fad->end += drange; fad = next; } return 0; } #endif /* allegro_gl_convert_allegro_font_ex(FONT *f, int type, float scale, GLint format) */ /** Equivalent to: *
 *   allegro_gl_convert_allegro_font_ex(f, type, scale, format_state);
 * 
* * Where format_state is the last specified format to * allegro_gl_set_texture_format(). If allegro_gl_set_texture_format() was not * previously called, AllegroGL will try to determine the texture format * automatically. * * \deprecated */ FONT *allegro_gl_convert_allegro_font(FONT *f, int type, float scale) { GLint format = allegro_gl_get_texture_format(NULL); return allegro_gl_convert_allegro_font_ex(f, type, scale, format); } /* allegro_gl_convert_allegro_font_ex(FONT *f, int type, float scale, GLint format) */ /** Converts a regular Allegro FONT to the AGL format for 3D display. * * \param f The Allegro font to convert. * \param type The font type to convert to. * (see #AGL_FONT_TYPE_DONT_CARE, #AGL_FONT_TYPE_BITMAP, * #AGL_FONT_TYPE_TEXTURED) * \param scale The scaling factor (see below). * \param format The texture internal format to use. * * This function will build a texture map and/or a display list that will * be automatically uploaded to the video card. You can only convert to * bitmap or textured fonts. * * You can't convert an Allegro font to a vector font (#AGL_FONT_TYPE_OUTLINE) * as the logistics of such an operation are quite complex. * The original font will NOT be modified. * * A valid OpenGL rendering context is required, so you may only call this * function after a successful call to set_gfx_mode() with a valid OpenGL * mode. * * You should destroy the font via allegro_gl_destroy_font() when you are * done with it. * * Scaling * * For #AGL_FONT_TYPE_TEXTURED fonts, glyphs in the font need to be mapped * to OpenGL coordinates. The scale factor ensures that you get the scaling * you need. scale reprents the number of pixels to be mapped to 1.0 OpenGL * units. For allegro_gl_convert_font() to behave like AllegroGL 0.0.24 and * earlier, you'll need to pass 16.0 as the scale factor. * * Alternativaly, you can make all your fonts be 1.0 units high by using: *
 *   allegro_gl_convert_allegro_font(f, #AGL_FONT_TYPE_TEXTURED, 1.0/text_height(f));
 *  
* * Note that it is allowed for the scaling factor to be negative, in case your * fonts appear upside down. * * If you are planning to use your fonts on an orthographic projection where * one unit maps to one pixel, then you should pass 1.0 as scale. * * The scaling factor has no meaning for #AGL_FONT_TYPE_BITMAP fonts, so * it's ignored if the conversion will lead to a font of that type. * * Format * * The format specifies what internal format OpenGL should use for the texture, * in the case of #AGL_FONT_TYPE_TEXTURED fonts. It has the same semantics as * the internalformat parameter of glTexImage2D(). If you would like for * AllegroGL to pick a texture format for you, you may supply -1 as the texture * format. The default format for monochrome fonts is GL_INTENSITY4. The * default format for colored fonts is GL_RGB8. * * \return The converted font, or NULL on error. */ FONT *allegro_gl_convert_allegro_font_ex(FONT *f, int type, float scale, GLint format) { int max = 0, height = 0; int i; FONT *dest; FONT_AGL_DATA *destdata; int has_alpha = 0; union { FONT_MONO_DATA* mf; FONT_COLOR_DATA* cf; void *ptr; } dat; if (!__allegro_gl_valid_context) { return NULL; } if (!f) { TRACE(PREFIX_E "convert_allegro_font: Null source\n"); return NULL; } /* Make sure it's an Allegro font - we don't want any surprises */ #if GET_ALLEGRO_VERSION() >= MAKE_VER(4, 2, 1) if (f->vtable != font_vtable_mono && f->vtable != font_vtable_color && f->vtable != font_vtable_trans) { #else if (f->vtable != font_vtable_mono && f->vtable != font_vtable_color) { #endif TRACE(PREFIX_I "convert_allegro_font: Source font is not " "in Allegro format\n"); return NULL; } /* No vector fonts allowed as destination */ if (type == AGL_FONT_TYPE_OUTLINE) { /* Can't convert bitmap to vector font */ TRACE(PREFIX_I "convert_allegro_font: Unable to convert a " "pixmap font to a vector font.\n"); return NULL; } /* Make sure the scaling factor is appropreate */ if (fabs(scale) < 0.001) { TRACE(PREFIX_W "convert_allegro_font: Scaling factor might be " "too small: %f\n", scale); } /* Count number of ranges */ max = get_font_ranges(f); /* There should really be an API for this */ dest = (FONT*)malloc(sizeof(FONT)); if (!dest) { TRACE(PREFIX_E "convert_allegro_font: Ran out of memory " "while allocating %i bytes\n", (int)sizeof(FONT)); return NULL; } destdata = (FONT_AGL_DATA*)malloc(sizeof(FONT_AGL_DATA) * max); if (!destdata) { TRACE(PREFIX_E "convert_allegro_font: Ran out of memory " "while allocating %i bytes\n", (int)sizeof(FONT_AGL_DATA) * max); return NULL; } memset(destdata, 0, sizeof(FONT_AGL_DATA) * max); /* Construct the linked list */ for (i = 0; i < max - 1; i++) { destdata[i].next = &destdata[i + 1]; } destdata[max - 1].next = NULL; /* Set up the font */ dest->data = destdata; dest->vtable = font_vtable_agl; dest->height = 0; destdata->type = type; if (type == AGL_FONT_TYPE_DONT_CARE) { destdata->type = AGL_FONT_TYPE_TEXTURED; } #if GET_ALLEGRO_VERSION() >= MAKE_VER(4, 2, 1) has_alpha = (f->vtable == font_vtable_trans); #endif /* Convert each range */ dat.ptr = f->data; while (dat.ptr) { destdata->has_alpha = has_alpha; if (type == AGL_FONT_TYPE_BITMAP) { aglf_convert_allegro_font_to_bitmap(destdata, f, dat.ptr, &height); } else if (type == AGL_FONT_TYPE_TEXTURED) { aglf_convert_allegro_font_to_texture(&destdata, f, dat.ptr, &height, scale, format); } if (height > dest->height) { dest->height = height; } dat.ptr = (is_mono_font(f) ? (void*)dat.mf->next : (void*)dat.cf->next); destdata = destdata->next; } return dest; } /* QSort helper for sorting glyphs according to width, * then height - largest first. */ static int sort_glyphs(const void *c1, const void *c2) { AGL_GLYPH *g1 = (AGL_GLYPH*)c1; AGL_GLYPH *g2 = (AGL_GLYPH*)c2; if (g1->w < g2->w) { return 1; } else if (g1->w == g2->w) { return -g1->h + g2->h; } else { return -1; } } /* QSort helper for unsorting glyphs. */ static int unsort_glyphs(const void *c1, const void *c2) { AGL_GLYPH *g1 = (AGL_GLYPH*)c1; AGL_GLYPH *g2 = (AGL_GLYPH*)c2; return g1->glyph_num - g2->glyph_num; } /* QSort helper for sorting textures by area. */ static int sort_textures(const void *c1, const void *c2) { texture_size *t1 = (texture_size*)c1; texture_size *t2 = (texture_size*)c2; return t1->w * t1->h - t2->w * t2->h; } #ifdef SAVE_FONT_SCREENSHOT static void save_shot(BITMAP *bmp) { int i; char name[128]; for (i = 0; i < 1000; i++) { /* TGA, in case it is a truecolor font with alpha */ sprintf(name, "fonttest_%02i.tga", i); if (!exists(name)) { save_tga(name, bmp, NULL); break; } } } #endif /* Helper function. This will try to place all the glyphs in the bitmap the * best way it can */ static int aglf_sort_out_glyphs(BITMAP *bmp, AGL_GLYPH *glyphs, const int beg, const int end) { int i, j; int last_line = 0; int last_x = 0; /* We now try to make all the glyphs fit on the bitmap */ for (i = 0; i < end - beg; i++) { int collide = FALSE; /* Place glyphs on last_line */ glyphs[i].x = last_x; glyphs[i].y = last_line; /* Check for collision */ for (j = 0; j < i; j++) { if ((glyphs[i].x >= glyphs[j].x + glyphs[j].w) || (glyphs[i].y >= glyphs[j].y + glyphs[j].h) || (glyphs[j].x >= glyphs[i].x + glyphs[i].w) || (glyphs[j].y >= glyphs[i].y + glyphs[i].h)) { continue; } last_x = glyphs[j].x + glyphs[j].w; glyphs[i].x = last_x; j = 0; } if ((last_x + glyphs[i].w > bmp->w) || (last_line + glyphs[i].h > bmp->h)) { collide = TRUE; } if (collide) { /* If there was a collision, we need to find the sprite with * the smallest height that is still grater than last_line. * We also need to redo this glyph. */ int min_line = bmp->h + 1; int min_glyph = -1; for (j = 0; j < i; j++) { if ( glyphs[j].y + glyphs[j].h < min_line && glyphs[j].y + glyphs[j].h > last_line - FONT_CHARACTER_SPACING) { min_line = glyphs[j].y + glyphs[j].h + FONT_CHARACTER_SPACING; min_glyph = j; } } /* If it can't possibly all fit, failure */ if (min_glyph == -1) { TRACE(PREFIX_I "sort_out_glyphs: Unable to fit all glyphs into " "the texture.\n"); return FALSE; } /* Otherwise, start over at the top of that glyph */ last_x = glyphs[min_glyph].x; last_line = min_line; /* Redo this glyph */ i--; } else { last_x += glyphs[i].w + FONT_CHARACTER_SPACING; } } /* All ok */ return TRUE; } static int split_font(FONT *f, void *source, void **dest1, void **dest2) { union mixed_ptr range1, range2, src; int colored; int i; (*dest1) = NULL; (*dest2) = NULL; src.ptr = source; colored = (is_mono_font(f) ? FALSE : TRUE); /* Allocate the ranges that we need */ range1.ptr = malloc(colored ? sizeof(FONT_COLOR_DATA) : sizeof(FONT_MONO_DATA)); if (!range1.ptr) { TRACE(PREFIX_E "split_font() - Ran out of memory while " "trying ot allocate %i bytes.\n", colored ? (int)sizeof(FONT_COLOR_DATA) : (int)sizeof(FONT_MONO_DATA)); return FALSE; } range2.ptr = malloc(colored ? sizeof(FONT_COLOR_DATA) : sizeof(FONT_MONO_DATA)); if (!range2.ptr) { TRACE(PREFIX_E "split_font() - Ran out of memory while " "trying to allocate %i bytes.\n", colored ? (int)sizeof(FONT_COLOR_DATA) : (int)sizeof(FONT_MONO_DATA)); free(range1.ptr); return FALSE; } (*dest1) = range1.ptr; (*dest2) = range2.ptr; /* Now we split up the range */ if (colored) { /* Half the range */ int mid = src.cf->begin + (src.cf->end - src.cf->begin) / 2; range1.cf->begin = src.cf->begin; range1.cf->end = mid; range2.cf->begin = mid; range2.cf->end = src.cf->end; range1.cf->next = NULL; range2.cf->next = NULL; /* Split up the bitmaps */ range1.cf->bitmaps = malloc(sizeof(BITMAP*) * (range1.cf->end - range1.cf->begin)); if (!range1.cf->bitmaps) { TRACE(PREFIX_E "split_font() - Ran out of memory " "while trying to allocate %i bytes.\n", (int)sizeof(BITMAP*) * (range1.cf->end - range1.cf->begin)); free(range1.ptr); free(range2.ptr); return FALSE; } range2.cf->bitmaps = malloc(sizeof(BITMAP*) * (range2.cf->end - range2.cf->begin)); if (!range2.cf->bitmaps) { TRACE(PREFIX_E "split_font() - Ran out of memory " "while trying to allocate %i bytes.\n", (int)sizeof(BITMAP*) * (range2.cf->end - range2.cf->begin)); free(range1.cf->bitmaps); free(range1.ptr); free(range2.ptr); return FALSE; } for (i = 0; i < (range1.cf->end - range1.cf->begin); i++) { range1.cf->bitmaps[i] = src.cf->bitmaps[i]; } for (i = 0; i < (range2.cf->end - range2.cf->begin); i++) { range2.cf->bitmaps[i] = src.cf->bitmaps[i + range2.cf->begin - range1.cf->begin]; } } else { /* Half the range */ int mid = src.mf->begin + (src.mf->end - src.mf->begin) / 2; range1.mf->begin = src.mf->begin; range1.mf->end = mid; range2.mf->begin = mid; range2.mf->end = src.mf->end; range1.mf->next = NULL; range2.mf->next = NULL; /* Split up the bitmaps */ range1.mf->glyphs = malloc(sizeof(FONT_GLYPH*) * (range1.mf->end - range1.mf->begin)); if (!range1.mf->glyphs) { TRACE(PREFIX_E "split_font() - Ran out of memory " "while trying to allocate %i bytes.\n", (int)sizeof(FONT_GLYPH*) * (range1.mf->end - range1.mf->begin)); free(range1.ptr); free(range2.ptr); return FALSE; } range2.mf->glyphs = malloc(sizeof(FONT_GLYPH*) * (range2.mf->end - range2.mf->begin)); if (!range2.mf->glyphs) { TRACE(PREFIX_E "split_font() - Ran out of memory " "while trying to allocate %i bytes.\n", (int)sizeof(FONT_GLYPH*) * (range2.mf->end - range2.mf->begin)); free(range1.mf->glyphs); free(range1.ptr); free(range2.ptr); return FALSE; } for (i = 0; i < (range1.mf->end - range1.mf->begin); i++) { range1.mf->glyphs[i] = src.mf->glyphs[i]; } for (i = 0; i < (range2.mf->end - range2.mf->begin); i++) { range2.mf->glyphs[i] = src.mf->glyphs[i + range2.mf->begin - range1.mf->begin]; } } return TRUE; } /* Destroys a split font */ static void destroy_split_font(FONT *f, union mixed_ptr range1, union mixed_ptr range2) { if (!is_mono_font(f)) { free(range1.cf->bitmaps); free(range2.cf->bitmaps); } else { free(range1.mf->glyphs); free(range2.mf->glyphs); } free(range1.ptr); free(range2.ptr); return; } static int do_crop_font_range(FONT *f, AGL_GLYPH *glyphs, int beg, int end) { int i, j, k; int max = end - beg; char buf[32]; /* Allocate a temp bitmap to work with */ BITMAP *temp = create_bitmap(32, 32); if (!temp) { TRACE(PREFIX_E "crop_font_range - Unable to create " "bitmap of size: %ix%i!\n", 32, 32); goto error; } /* Crop glyphs */ for (i = 0; i < max; i++) { int used = 0; if (glyphs[i].w > temp->w || glyphs[i].h > temp->h) { int old_w = temp->w, old_h = temp->h; destroy_bitmap(temp); temp = create_bitmap(old_w * 2, old_h * 2); if (!temp) { TRACE(PREFIX_E "crop_font_range - Unable to " "create bitmap of size: %ix%i!\n", old_w * 2, old_h * 2); goto error; } } clear(temp); usetc(buf + usetc(buf, glyphs[i].glyph_num + beg), 0); textout_ex(temp, f, buf, 0, 0, makecol_depth(bitmap_color_depth(temp), 255, 255, 255), 0); /* Crop top */ for (j = 0; j < glyphs[i].h; j++) { used = 0; for (k = 0; k < glyphs[i].w; k++) { if (getpixel(temp, k, j)) { used = 1; glyphs[i].offset_y += j; glyphs[i].h -= j; break; } } if (used) break; } /* If just the top crop killed our glyph, then skip it entirely */ if (!used) { TRACE(PREFIX_I "crop_font_range: skipping glyph %i\n", i); glyphs[i].offset_y = 0; glyphs[i].offset_h = glyphs[i].h - 1; glyphs[i].offset_w = glyphs[i].w - 2; glyphs[i].h = 1; glyphs[i].w = 1; continue; } /* Crop bottom */ j = glyphs[i].h + glyphs[i].offset_y - 1; for ( /* above */; j >= glyphs[i].offset_y; j--) { used = 0; for (k = 0; k < glyphs[i].w; k++) { if (getpixel(temp, k, j)) { used = 1; glyphs[i].offset_h += glyphs[i].h + glyphs[i].offset_y - j - 2; glyphs[i].h -= glyphs[i].h + glyphs[i].offset_y - j - 1; break; } } if (used) break; } /* Crop Left */ for (j = 0; j < glyphs[i].w; j++) { used = 0; k = MAX(glyphs[i].offset_y - 1, 0); for (/* above */; k < glyphs[i].offset_y + glyphs[i].h + 1; k++) { if (getpixel(temp, j, k)) { used = 1; glyphs[i].offset_x += j; glyphs[i].w -= j; break; } } if (used) break; } /* Crop Right */ j = glyphs[i].w + glyphs[i].offset_x - 1; for (/* above */; j >= glyphs[i].offset_x; j--) { used = 0; k = MAX(glyphs[i].offset_y - 1, 0); for (/* above */; k < glyphs[i].offset_y + glyphs[i].h + 1; k++) { if (getpixel(temp, j, k)) { used = 1; glyphs[i].offset_w += glyphs[i].w + glyphs[i].offset_x - 1 - j; glyphs[i].w -= glyphs[i].w + glyphs[i].offset_x - j - 1; break; } } if (used) break; } #ifdef LOGLEVEL TRACE(PREFIX_I "crop_font_range: Glyph %i (%c) offs: x: %i y: %i, " "w: %i h: %i, offs: w: %i h: %i\n", i, i + beg, glyphs[i].offset_x, glyphs[i].offset_y, glyphs[i].w, glyphs[i].h, glyphs[i].offset_w, glyphs[i].offset_h); #endif } destroy_bitmap(temp); return TRUE; error: if (temp) { destroy_bitmap(temp); } return FALSE; } /* Crops a font over a particular range */ static int crop_font_range(FONT *f, void *src, int beg, int end, AGL_GLYPH *glyphs, int *net_area, int *gross_area, int *max_w, int *max_h) { int i; int crop = 1; int max = end - beg; int ret = TRUE; union mixed_ptr dat; dat.ptr = src; /* Disable cropping for trucolor fonts. */ if (is_color_font(f)) { FONT_COLOR_DATA *fcd = f->data; if (bitmap_color_depth(fcd->bitmaps[0]) != 8) { crop = 0; } } /* Load default sizes */ for (i = 0; i < max; i++) { glyphs[i].glyph_num = i; if (is_mono_font(f)) { glyphs[i].w = dat.mf->glyphs[i]->w + 1; glyphs[i].h = dat.mf->glyphs[i]->h + 1; } else { glyphs[i].w = dat.cf->bitmaps[i]->w + 1; glyphs[i].h = dat.cf->bitmaps[i]->h + 1; } glyphs[i].offset_w = -1; glyphs[i].offset_h = -1; /* Not placed yet */ glyphs[i].x = -1; } if (crop) { ret = do_crop_font_range(f, glyphs, beg, end); } (*gross_area) = 0; (*net_area) = 0; (*max_w) = 0; (*max_h) = 0; /* Find max w and h, total area covered by the bitmaps, and number of * glyphs */ for (i = 0; i < max; i++) { if (glyphs[i].w > *max_w) (*max_w) = glyphs[i].w; if (glyphs[i].h > *max_h) (*max_h) = glyphs[i].h; (*net_area) += glyphs[i].w * glyphs[i].h; (*gross_area) += (glyphs[i].w + FONT_CHARACTER_SPACING) * (glyphs[i].h + FONT_CHARACTER_SPACING); } return ret; } /* Tries to find a texture that will fit the font */ static BITMAP* look_for_texture(int beg, int end, AGL_GLYPH *glyphs, int max_w, int max_h, int total_area, GLint format, int has_alpha) { BITMAP *bmp = NULL; int i, j; /* Max texture size (1 << n) */ /* XXX We should use ARB_np2 if we can * * Other note: w*h shouldn't exceed 31 bits; otherwise, we get funny * behavior on 32-bit architectures. Limit texture sizes to 32k*32k * (30 bits). */ #define MIN_TEXTURE_SIZE 2 #define NUM_TEXTURE_SIZE 13 texture_size texture_sizes[NUM_TEXTURE_SIZE * NUM_TEXTURE_SIZE]; /* Set up texture sizes */ for (i = 0; i < NUM_TEXTURE_SIZE; i++) { for (j = 0; j < NUM_TEXTURE_SIZE; j++) { texture_sizes[j + i * NUM_TEXTURE_SIZE].w = 1 << (j + MIN_TEXTURE_SIZE); texture_sizes[j + i * NUM_TEXTURE_SIZE].h = 1 << (i + MIN_TEXTURE_SIZE); } } /* Sort texture sizes by area */ qsort(texture_sizes, NUM_TEXTURE_SIZE * NUM_TEXTURE_SIZE, sizeof(texture_size), &sort_textures); for (i = 0; i < NUM_TEXTURE_SIZE * NUM_TEXTURE_SIZE; i++) { int num_channels; /* Check the area - it must be larger than * all the glyphs */ texture_size *t = &texture_sizes[i]; int area = t->w * t->h; int depth = 24; if (area < total_area) { continue; } /* Check against max values */ if ((t->h < max_h) || (t->w < max_w)) { continue; } TRACE(PREFIX_I "look_for_texture: candidate size: %ix%i\n", t->w, t->h); /* Check that the texture can, in fact, be created */ num_channels = __allegro_gl_get_num_channels(format); if (num_channels == 1) { depth = 8; } else if (num_channels == 4) { depth = 32; } else { depth = 24; } bmp = create_bitmap_ex(depth, t->w, t->h); if (!bmp) { TRACE(PREFIX_W "look_for_texture: Out of memory while " "creating bitmap\n"); continue; } if (!aglf_check_texture(bmp, format, has_alpha)) { TRACE(PREFIX_I "look_for_texture: Texture rejected by driver\n"); destroy_bitmap(bmp); bmp = NULL; continue; } /* Sort out the glyphs */ TRACE(PREFIX_I "look_for_texture: Sorting on bmp: %p, beg: %i, " "end: %i\n", bmp, beg, end); if (aglf_sort_out_glyphs(bmp, glyphs, beg, end) == TRUE) { /* Success? */ return bmp; } /* Failure? Try something else */ TRACE(PREFIX_I "look_for_texture: Conversion failed\n"); destroy_bitmap(bmp); bmp = NULL; } return NULL; } #if GET_ALLEGRO_VERSION() >= MAKE_VER(4, 2, 1) /* This is only used to render chars from an Allegro font which has the * font_vtable_trans vtable. If the target is an 8-bit bitmap, only the alpha * channel is used. Otherwise, blit is used, to preserve the alpha channel. */ static int dummy_render_char(AL_CONST FONT* f, int ch, int fg, int bg, BITMAP* bmp, int x, int y) { FONT_COLOR_DATA* cf = (FONT_COLOR_DATA*)(f->data); BITMAP *glyph = NULL; while(cf) { if(ch >= cf->begin && ch < cf->end) { glyph = cf->bitmaps[ch - cf->begin]; break; } cf = cf->next; } if (glyph) { if (bitmap_color_depth(bmp) == 8) { int gx, gy; for (gy = 0; gy < bmp->h; gy++) { for (gx = 0; gx < bmp->w; gx++) { int c = getpixel(glyph, gx, gy); int a = geta(c); putpixel(bmp, x + gx, y + gy, a); } } } else blit(glyph, bmp, 0, 0, x, y, glyph->w, glyph->h); return bmp->w; } return 0; } #endif /* Function to draw a character in a bitmap for conversion */ static int draw_glyphs(BITMAP *bmp, FONT *f, GLint format, int beg, int end, AGL_GLYPH *glyphs) { char buf[32]; int i, j; #if GET_ALLEGRO_VERSION() >= MAKE_VER(4, 2, 1) if (bitmap_color_depth(bmp) == 8 && f->vtable != font_vtable_trans) { #else if (bitmap_color_depth(bmp) == 8) { #endif /* Generate an alpha font */ BITMAP *rgbbmp = create_bitmap_ex(24, bmp->w, bmp->h); if (!rgbbmp) { TRACE(PREFIX_E "convert_allegro_font_to_texture: " "Ran out of memory while creating %ix%ix%i bitmap!\n", bmp->w, bmp->h, 24); return FALSE; } clear_bitmap(rgbbmp); for (i = 0; i < end - beg; i++) { usetc(buf + usetc(buf, glyphs[i].glyph_num + beg), 0); textout_ex(rgbbmp, f, buf, glyphs[i].x - glyphs[i].offset_x, glyphs[i].y - glyphs[i].offset_y, -1, -1); } /* Convert back to 8bpp */ for (j = 0; j < bmp->h; j++) { for (i = 0; i < bmp->w; i++) { int pix = _getpixel24(rgbbmp, i, j); int r = getr24(pix); int g = getg24(pix); int b = getb24(pix); int gray = (r * 77 + g * 150 + b * 28 + 255) >> 8; _putpixel(bmp, i, j, MID(0, gray, 255)); } } destroy_bitmap(rgbbmp); } else { #if GET_ALLEGRO_VERSION() >= MAKE_VER(4, 2, 1) int (*borrowed_color_vtable)(AL_CONST FONT*, int, int, int, BITMAP*, int, int) = NULL; //In order to keep the alpha channel in textout_ex we borrow //the color font vtable which uses maked_blit() instead of //draw_trans_sprite() to draw glyphs. if (f->vtable == font_vtable_trans) { borrowed_color_vtable = f->vtable->render_char; f->vtable->render_char = dummy_render_char; } #endif if (__allegro_gl_get_num_channels(format) == 4) { clear_to_color(bmp, bitmap_mask_color(bmp)); } else { clear_bitmap(bmp); } for (i = 0; i < end - beg; i++) { usetc(buf + usetc(buf, glyphs[i].glyph_num + beg), 0); textout_ex(bmp, f, buf, glyphs[i].x - glyphs[i].offset_x, glyphs[i].y - glyphs[i].offset_y, -1, -1); } #if GET_ALLEGRO_VERSION() >= MAKE_VER(4, 2, 1) if (borrowed_color_vtable) { f->vtable->render_char = borrowed_color_vtable; } #endif } return TRUE; } /* Converts a single font range to a texture. * dest - Receives the result. * f - The original font. * src - The original font data. */ static void aglf_convert_allegro_font_to_texture(FONT_AGL_DATA **dest, FONT *f, void *src, int *height, float scale, GLint format) { int max = 0; BITMAP *bmp = NULL; int beg = 0, end = 0; int max_w, max_h; int total_area, gross_area; AGL_GLYPH *glyph_coords; union mixed_ptr dat; dat.ptr = src; if (is_mono_font(f)) { beg = dat.mf->begin; end = dat.mf->end; max = dat.mf->end - dat.mf->begin; if (format == -1) { format = GL_INTENSITY4; } } else if (is_color_font(f)) { beg = dat.cf->begin; end = dat.cf->end; max = dat.cf->end - dat.cf->begin; if (format == -1) { #if GET_ALLEGRO_VERSION() >= MAKE_VER(4, 2, 1) format = (f->vtable == font_vtable_trans ? GL_RGBA8 : GL_RGB8); #else format = GL_RGB8; #endif } } /* Allocate glyph sizes */ glyph_coords = malloc(max * sizeof(AGL_GLYPH)); memset(glyph_coords, 0, max * sizeof(AGL_GLYPH)); if (crop_font_range(f, dat.ptr, beg, end, glyph_coords, &total_area, &gross_area, &max_w, &max_h) == FALSE) { TRACE(PREFIX_I "convert_allegro_font_to_texture: Unable to crop font " "range\n"); free(glyph_coords); return; } TRACE(PREFIX_I "convert_allegro_font_to_texture: Total area of glyphs: " "%i pixels (%i pixels gross) - max_w: %i, max_h: %i\n", total_area, gross_area, max_w, max_h); /* Sort glyphs by width, then height */ qsort(glyph_coords, end - beg, sizeof(AGL_GLYPH), &sort_glyphs); /* Now, we look for the appropriate texture size */ bmp = look_for_texture(beg, end, glyph_coords, max_w, max_h, total_area, format, (*dest)->has_alpha); /* No texture sizes were found - we should split the font up */ if (!bmp) { int height1; union mixed_ptr f1, f2; FONT_AGL_DATA *dest1, *dest2; free(glyph_coords); dest1 = *(dest); dest2 = malloc(sizeof(FONT_AGL_DATA)); if (!dest2) { TRACE(PREFIX_E "convert_allegro_font_to_texture: " "Out of memory while trying to allocate %i bytes.\n", (int)sizeof(FONT_AGL_DATA)); return; } memset(dest2, 0, sizeof(FONT_AGL_DATA)); dest2->next = dest1->next; dest1->next = dest2; dest2->is_free_chunk = TRUE; dest2->format = dest1->format; dest2->has_alpha = dest1->has_alpha; if (split_font(f, dat.ptr, &f1.ptr, &f2.ptr) == FALSE) { TRACE(PREFIX_E "convert_allegro_font_to_texture: Unable " "to split font!\n"); dest1->next = dest2->next; free(dest2); return; } aglf_convert_allegro_font_to_texture(&dest1, f, f1.ptr, height, scale, format); height1 = (*height); aglf_convert_allegro_font_to_texture(&dest2, f, f2.ptr, height, scale, format); destroy_split_font(f, f1, f2); if (height1 > (*height)) (*height) = height1; (*dest) = dest2; return; } TRACE(PREFIX_I "convert_allegro_font_to_texture: Using texture " "%ix%ix%i for font conversion.\n", bmp->w, bmp->h, bitmap_color_depth(bmp)); /* Now that all the glyphs are in place, we draw them into the bitmap */ if (draw_glyphs(bmp, f, format, beg, end, glyph_coords) == FALSE) { destroy_bitmap(bmp); free(glyph_coords); return; } /* Un-Sort glyphs */ qsort(glyph_coords, end - beg, sizeof(AGL_GLYPH), &unsort_glyphs); #if (defined SAVE_FONT_SCREENSHOT) save_shot(bmp); #endif (*dest)->list_base = create_textured_font_call_lists(glyph_coords, max, bmp, scale, height); (*dest)->texture = aglf_upload_texture(bmp, format, (*dest)->has_alpha); (*dest)->type = AGL_FONT_TYPE_TEXTURED; (*dest)->format = format; (*dest)->scale = scale; (*dest)->start = beg; (*dest)->end = end; (*dest)->data = bmp; (*dest)->glyph_coords = glyph_coords; return; } static void aglf_convert_allegro_font_to_bitmap(FONT_AGL_DATA *dest, FONT *f, void *src, int *height) { int max = 0; int i, j, k; int beg = 0, end = 0; int mask; FONT_GLYPH **glyph; union { FONT_MONO_DATA* mf; FONT_COLOR_DATA* cf; void *ptr; } dat; dat.ptr = src; if (is_mono_font(f)) max = dat.mf->end - dat.mf->begin; else if (is_color_font(f)) max = dat.cf->end - dat.cf->begin; else return; glyph = malloc(sizeof(FONT_GLYPH*) * max); if (!glyph) { TRACE(PREFIX_E "convert_allegro_font_to_bitmap: Ran out of " "memory while allocating %i bytes\n", (int)sizeof(FONT_GLYPH)); return; } *height = f->height; if (is_mono_font(f)) { /* for each glyph */ for (i = 0; i < max; i++) { FONT_GLYPH *oldgl = dat.mf->glyphs[i]; int size = sizeof(FONT_GLYPH) + ((oldgl->w + 31) / 32) * 4 * oldgl->h; /* create new glyph */ FONT_GLYPH *newgl = (FONT_GLYPH*)malloc(size); if (!newgl) break; memset(newgl, 0, size); newgl->w = oldgl->w; newgl->h = oldgl->h; /* update the data */ for (j = 0; j < oldgl->h; j++) { for (k = 0; k < ((oldgl->w + 7) / 8); k++) { int addr = (oldgl->h - j - 1) * ((oldgl->w + 31) / 32) * 4 + k; newgl->dat[addr] = oldgl->dat[j * ((oldgl->w + 7) / 8) + k]; } } glyph[i] = newgl; } } /* Reduce to 1 bit */ else if (is_color_font(f)) { /* for each glyph */ for (i = 0; i < max; i++) { int size; BITMAP *oldgl = dat.cf->bitmaps[i]; FONT_GLYPH *newgl; mask = bitmap_mask_color(oldgl); size = sizeof(FONT_GLYPH) + ((oldgl->w + 31) / 32) * 4 * oldgl->h; /* create new glyph */ newgl = (FONT_GLYPH*)malloc(size); if (!newgl) break; memset(newgl, 0, size); newgl->w = oldgl->w; newgl->h = oldgl->h; /* update the data */ for (j = 0; j < oldgl->h; j++) { for (k = 0; k < oldgl->w; k++) { int addr = (oldgl->h - j - 1) * ((oldgl->w + 31) / 32) * 4 + (k / 8); newgl->dat[addr] |= (getpixel(oldgl, k, j) == mask) ? 0 : (1 << (k & 7)); } } glyph[i] = newgl; } } /* Create call lists */ { GLuint list = glGenLists(max); for (i = 0; i < max; i++) { glNewList(list + i, GL_COMPILE); glBitmap(glyph[i]->w, glyph[i]->h, 0, 0, glyph[i]->w, 0, glyph[i]->dat); glEndList(); } dest->list_base = list; } dest->is_free_chunk = 0; dest->type = AGL_FONT_TYPE_BITMAP; dest->start = beg; dest->end = end; dest->data = glyph; return; } static int aglf_check_texture(BITMAP *bmp, GLint format, int has_alpha) { int flags = AGL_TEXTURE_FLIP | AGL_TEXTURE_MIPMAP; if (format == GL_ALPHA4 || format == GL_ALPHA8 || format == GL_ALPHA || format == GL_INTENSITY4 || format == GL_INTENSITY8 || format == GL_INTENSITY || format == GL_LUMINANCE4 || format == GL_LUMINANCE8 || format == GL_LUMINANCE || format == 1) { flags |= AGL_TEXTURE_ALPHA_ONLY; } else if (format == GL_RGBA8) { if (has_alpha) { flags |= AGL_TEXTURE_HAS_ALPHA; } else { flags |= AGL_TEXTURE_MASKED; } } return allegro_gl_check_texture_ex(flags, bmp, format); } static GLuint aglf_upload_texture(BITMAP *bmp, GLint format, int has_alpha) { int flags = AGL_TEXTURE_FLIP | AGL_TEXTURE_MIPMAP; GLuint texture; if (format == GL_ALPHA4 || format == GL_ALPHA8 || format == GL_ALPHA || format == GL_INTENSITY4 || format == GL_INTENSITY8 || format == GL_INTENSITY || format == GL_LUMINANCE4 || format == GL_LUMINANCE8 || format == GL_LUMINANCE || format == 1) { flags |= AGL_TEXTURE_ALPHA_ONLY; } else if (__allegro_gl_get_num_channels(format) == 4) { if (has_alpha) { flags |= AGL_TEXTURE_HAS_ALPHA; } else { flags |= AGL_TEXTURE_MASKED; } } TRACE(PREFIX_I "Want texture format: %s\n", __allegro_gl_get_format_description(format)); texture = allegro_gl_make_texture_ex(flags, bmp, format); TRACE(PREFIX_I "Texture ID is: %u\n", texture); return texture; } allegro4.4-4.4.2/addons/allegrogl/src/glext.c000066400000000000000000000454571173507505700207230ustar00rootroot00000000000000/* This code is (C) AllegroGL contributors, and double licensed under * the GPL and zlib licenses. See gpl.txt or zlib.txt for details. */ /** \file glext.c * \brief OpenGL extension management. */ #include "alleggl.h" #include "allglint.h" #include #ifdef ALLEGRO_MACOSX #include #else #include #endif #include /* GL extension Structure. Holds the extension pointers for a single context */ #define AGL_API(type, name, args) AGL_##name##_t name; typedef struct AGL_EXT { # include "allegrogl/GLext/gl_ext_api.h" #ifdef ALLEGRO_WINDOWS # include "allegrogl/GLext/wgl_ext_api.h" #elif defined ALLEGRO_UNIX # include "allegrogl/GLext/glx_ext_api.h" #endif } AGL_EXT; #undef AGL_API #define PREFIX_I "agl-ext INFO: " #define PREFIX_W "agl-ext WARNING: " #define PREFIX_E "agl-ext ERROR: " /* Current driver info */ struct allegro_gl_info allegro_gl_info; /** \ingroup extensions * List of OpenGL extensions supported by AllegroGL. Each entry of this * structure is an int which is either set to 1, if the corresponding * extension is available on the host system, or 0 otherwise. * * Extension names use only the base name. For example, GL_ARB_multitexture * should be refered to by: *
 *   allegro_gl_extensions_GL.ARB_multitexture
 *  
* * \sa allegro_gl_extensions_GLX allegro_gl_extensions_WGL */ struct AGL_EXTENSION_LIST_GL allegro_gl_extensions_GL; /** \ingroup extensions * List of GLX extensions supported by AllegroGL. * * \sa allegro_gl_extensions_GL allegro_gl_extensions_WGL */ #ifdef ALLEGRO_UNIX struct AGL_EXTENSION_LIST_GLX allegro_gl_extensions_GLX; #endif /** \ingroup extensions * List of WGL extensions supported by AllegroGL. * * \sa allegro_gl_extensions_GL allegro_gl_extensions_GLX */ #ifdef ALLEGRO_WINDOWS struct AGL_EXTENSION_LIST_WGL allegro_gl_extensions_WGL; #endif /* Current context */ AGL_EXT *agl_extension_table = NULL; #ifdef ALLEGROGL_GENERIC_DRIVER #include "GL/amesa.h" #endif #ifdef ALLEGROGL_HAVE_DYNAMIC_LINK #include /* Handle for dynamic library libGL.so */ static void* __agl_handle = NULL; /* Pointer to glXGetProcAddressARB */ typedef void* (*GLXGETPROCADDRESSARBPROC) (const GLubyte*); static GLXGETPROCADDRESSARBPROC aglXGetProcAddress; #else /* Tries static linking */ #ifdef ALLEGROGL_GLXGETPROCADDRESSARB #define aglXGetProcAddress glXGetProcAddressARB #else #define aglXGetProcAddress glXGetProcAddress #endif #endif #ifdef ALLEGRO_MACOSX #undef TRUE #undef FALSE #include #undef TRUE #undef FALSE #define TRUE -1 #define FALSE 0 static CFBundleRef opengl_bundle_ref; #endif /* Define the GL API pointers */ #define AGL_API(type, name, args) AGL_##name##_t __agl##name = NULL; # include "allegrogl/GLext/gl_ext_api.h" #undef AGL_API #ifdef ALLEGRO_WINDOWS #define AGL_API(type, name, args) AGL_##name##_t __awgl##name = NULL; # include "allegrogl/GLext/wgl_ext_api.h" #undef AGL_API #elif defined ALLEGRO_UNIX #define AGL_API(type, name, args) AGL_##name##_t __aglX##name = NULL; # include "allegrogl/GLext/glx_ext_api.h" #undef AGL_API #endif /* Create the extension table */ AGL_EXT* __allegro_gl_create_extensions() { AGL_EXT *ret = malloc(sizeof(AGL_EXT)); if (!ret) { return NULL; } memset(ret, 0, sizeof(AGL_EXT)); return ret; } /* Load the extension addresses into the table. * Should only be done on context creation. */ void __allegro_gl_load_extensions(AGL_EXT *ext) { #ifdef ALLEGRO_MACOSX CFStringRef function; #endif if (!ext) { return; } #ifdef ALLEGRO_UNIX if (!aglXGetProcAddress) { return; } #endif # ifdef ALLEGRO_WINDOWS # define AGL_API(type, name, args) \ ext->name = (AGL_##name##_t)wglGetProcAddress("gl" #name); \ if (ext->name) { AGL_LOG(2,"gl" #name " successfully loaded\n"); } # include "allegrogl/GLext/gl_ext_api.h" # undef AGL_API # define AGL_API(type, name, args) \ ext->name = (AGL_##name##_t)wglGetProcAddress("wgl" #name); \ if (ext->name) { AGL_LOG(2,"wgl" #name " successfully loaded\n"); } # include "allegrogl/GLext/wgl_ext_api.h" # undef AGL_API # elif defined ALLEGRO_UNIX # define AGL_API(type, name, args) \ ext->name = (AGL_##name##_t)aglXGetProcAddress((const GLubyte*)"gl" #name); \ if (ext->name) { AGL_LOG(2,"gl" #name " successfully loaded\n"); } # include "allegrogl/GLext/gl_ext_api.h" # undef AGL_API # define AGL_API(type, name, args) \ ext->name = (AGL_##name##_t)aglXGetProcAddress((const GLubyte*)"glX" #name); \ if (ext->name) { AGL_LOG(2,"glX" #name " successfully loaded\n"); } # include "allegrogl/GLext/glx_ext_api.h" # undef AGL_API # elif defined ALLEGRO_MACOSX # define AGL_API(type, name, args) \ function = CFStringCreateWithCString(kCFAllocatorDefault, "gl" #name, \ kCFStringEncodingASCII); \ if (function) { \ ext->name = (AGL_##name##_t)CFBundleGetFunctionPointerForName( \ opengl_bundle_ref, function); \ CFRelease(function); \ } \ if (ext->name) { AGL_LOG(2,"gl" #name " successfully loaded\n"); } # include "allegrogl/GLext/gl_ext_api.h" # undef AGL_API # endif } /* Set the GL API pointers to the current table * Should only be called on context switches. */ void __allegro_gl_set_extensions(AGL_EXT *ext) { if (!ext) { return; } #define AGL_API(type, name, args) __agl##name = ext->name; # include "allegrogl/GLext/gl_ext_api.h" #undef AGL_API #ifdef ALLEGRO_WINDOWS #define AGL_API(type, name, args) __awgl##name = ext->name; # include "allegrogl/GLext/wgl_ext_api.h" #undef AGL_API #elif defined ALLEGRO_UNIX #define AGL_API(type, name, args) __aglX##name = ext->name; # include "allegrogl/GLext/glx_ext_api.h" #undef AGL_API #endif } /* Destroys the extension table */ void __allegro_gl_destroy_extensions(AGL_EXT *ext) { if (ext) { if (ext == agl_extension_table) { agl_extension_table = NULL; } free(ext); } } /* __allegro_gl_look_for_an_extension: * This function has been written by Mark J. Kilgard in one of his * tutorials about OpenGL extensions */ int __allegro_gl_look_for_an_extension(AL_CONST char *name, AL_CONST GLubyte * extensions) { AL_CONST GLubyte *start; GLubyte *where, *terminator; /* Extension names should not have spaces. */ where = (GLubyte *) strchr(name, ' '); if (where || *name == '\0') return FALSE; /* It takes a bit of care to be fool-proof about parsing the * OpenGL extensions string. Don't be fooled by sub-strings, etc. */ start = extensions; for (;;) { where = (GLubyte *) strstr((AL_CONST char *) start, name); if (!where) break; terminator = where + strlen(name); if (where == start || *(where - 1) == ' ') if (*terminator == ' ' || *terminator == '\0') return TRUE; start = terminator; } return FALSE; } #ifdef ALLEGRO_WINDOWS static AGL_GetExtensionsStringARB_t __wglGetExtensionsStringARB = NULL; static HDC __hdc = NULL; #elif defined ALLEGRO_UNIX #include #endif /* int allegro_gl_is_extension_supported(AL_CONST char *extension) */ /** \ingroup extensions * This function is an helper to determine whether an OpenGL extension is * available or not. * * \b Example: *
 *       int packedpixels =
 *                  allegro_gl_is_extension_supported("GL_EXT_packed_pixels");
 *    
* If \c packedpixels is TRUE then you can safely use the constants related * to the packed pixels extension. * * \param extension The name of the extension that is needed * \return TRUE if the extension is available FALSE otherwise. */ int allegro_gl_is_extension_supported(AL_CONST char *extension) { int ret; if (!__allegro_gl_valid_context) return FALSE; if (!glGetString(GL_EXTENSIONS)) return FALSE; ret = __allegro_gl_look_for_an_extension(extension, glGetString(GL_EXTENSIONS)); #ifdef ALLEGRO_WINDOWS if (!ret && strncmp(extension, "WGL", 3) == 0) { if (!__wglGetExtensionsStringARB || __hdc != __allegro_gl_hdc) { __wglGetExtensionsStringARB = (AGL_GetExtensionsStringARB_t) wglGetProcAddress("wglGetExtensionsStringARB"); __hdc = __allegro_gl_hdc; } if (__wglGetExtensionsStringARB) { ret = __allegro_gl_look_for_an_extension(extension, (AL_CONST GLubyte*)__wglGetExtensionsStringARB(__allegro_gl_hdc)); } } #elif defined ALLEGRO_UNIX if (!ret && strncmp(extension, "GLX", 3) == 0) { XLOCK(); ret = __allegro_gl_look_for_an_extension(extension, (const GLubyte*)glXQueryExtensionsString(_xwin.display, _xwin.screen)); XUNLOCK(); } #endif return ret; } /* void * allegro_gl_get_proc_address(AL_CONST char *name) */ /** \ingroup extensions * Helper to get the address of an OpenGL symbol * * \b Example: * How to get the function \c glMultiTexCoord3fARB that comes * with ARB's Multitexture extension : *
 *  // define the type of the function
 *	AGL_DEFINE_PROC_TYPE(void, MULTI_TEX_FUNC,
 *	                                      (GLenum, GLfloat, GLfloat, GLfloat));
 *  // declare the function pointer
 *	MULTI_TEX_FUNC glMultiTexCoord3fARB;
 *  // get the address of the function
 * 	glMultiTexCoord3fARB = (MULTI_TEX_FUNC) allegro_gl_get_proc_address(
 * 	                                                   "glMultiTexCoord3fARB");
 *    
* * If \c glMultiTexCoord3fARB is not \c NULL then it can be used as if it has * been defined in the OpenGL core library. Note that the use of the * AGL_DEFINE_PROC_TYPE macro is mandatory if you want your program to be * portable. * * \param name The name of the symbol you want to link to. * \return A pointer to the symbol if available or NULL otherwise. */ void *allegro_gl_get_proc_address(AL_CONST char *name) { void *symbol = NULL; #ifdef ALLEGRO_MACOSX CFStringRef function; #endif if (!__allegro_gl_valid_context) return NULL; #ifdef ALLEGROGL_GENERIC_DRIVER /* AMesa provides a function to get a proc address. It does * not emulate dynamic linking of course... */ symbol = AMesaGetProcAddress(name); #elif defined ALLEGRO_WINDOWS /* For once Windows is the easiest platform to use :) * It provides a standardized way to get a function address * But of course there is a drawback : the symbol is only valid * under the current context :P */ symbol = wglGetProcAddress(name); #elif defined ALLEGRO_UNIX if (aglXGetProcAddress) { /* This is definitely the *good* way on Unix to get a GL proc * address. Unfortunately glXGetProcAddress is an extension * and may not be available on all platforms */ symbol = aglXGetProcAddress((const GLubyte*)name); } #elif defined ALLEGROGL_HAVE_DYNAMIC_LINK else { /* Hack if glXGetProcAddress is not available : * we try to find the symbol into libGL.so */ if (__agl_handle) { symbol = dlsym(__agl_handle, name); } } #elif defined ALLEGRO_MACOSX function = CFStringCreateWithCString(kCFAllocatorDefault, name, kCFStringEncodingASCII); if (function) { symbol = CFBundleGetFunctionPointerForName(opengl_bundle_ref, function); CFRelease(function); } #else /* DOS does not support dynamic linking. If the function is not * available at build-time then it will not be available at run-time * Therefore we do not need to look for it... */ #endif if (!symbol) { #if defined ALLEGROGL_HAVE_DYNAMIC_LINK if (!aglXGetProcAddress) { TRACE(PREFIX_W "get_proc_address: libdl::dlsym: %s\n", dlerror()); } #endif TRACE(PREFIX_W "get_proc_address : Unable to load symbol %s\n", name); } else { TRACE(PREFIX_I "get_proc_address : Symbol %s successfully loaded\n", name); } return symbol; } /* Fills in the AllegroGL info struct for blacklisting video cards. */ static void __fill_in_info_struct(const GLubyte *rendereru, struct allegro_gl_info *info) { const char *renderer = (const char*)rendereru; /* Some cards are "special"... */ if (strstr(renderer, "3Dfx/Voodoo")) { info->is_voodoo = 1; } else if (strstr(renderer, "Matrox G200")) { info->is_matrox_g200 = 1; } else if (strstr(renderer, "RagePRO")) { info->is_ati_rage_pro = 1; } else if (strstr(renderer, "RADEON 7000")) { info->is_ati_radeon_7000 = 1; } else if (strstr(renderer, "Mesa DRI R200")) { info->is_ati_r200_chip = 1; } if ((strncmp(renderer, "3Dfx/Voodoo3 ", 13) == 0) || (strncmp(renderer, "3Dfx/Voodoo2 ", 13) == 0) || (strncmp(renderer, "3Dfx/Voodoo ", 12) == 0)) { info->is_voodoo3_and_under = 1; } /* Read OpenGL properties */ info->version = allegro_gl_opengl_version(); return; } /* __allegro_gl_manage_extensions: * This functions fills the __allegro_gl_extensions structure and displays * on the log file which extensions are available */ void __allegro_gl_manage_extensions(void) { AL_CONST GLubyte *buf; int i; #ifdef ALLEGRO_MACOSX CFURLRef bundle_url; #endif /* Print out OpenGL extensions */ #if LOGLEVEL >= 1 AGL_LOG(1, "OpenGL Extensions:\n"); __allegro_gl_print_extensions((AL_CONST char*) glGetString(GL_EXTENSIONS)); #endif /* Print out GLU version */ buf = gluGetString(GLU_VERSION); TRACE(PREFIX_I "GLU Version : %s\n", buf); #ifdef ALLEGROGL_HAVE_DYNAMIC_LINK /* Get glXGetProcAddress entry */ __agl_handle = dlopen("libGL.so", RTLD_LAZY); if (__agl_handle) { aglXGetProcAddress = (GLXGETPROCADDRESSARBPROC) dlsym(__agl_handle, "glXGetProcAddressARB"); if (!aglXGetProcAddress) { aglXGetProcAddress = (GLXGETPROCADDRESSARBPROC) dlsym(__agl_handle, "glXGetProcAddress"); } } else { TRACE(PREFIX_W "Failed to dlopen libGL.so : %s\n", dlerror()); } TRACE(PREFIX_I "glXGetProcAddress Extension: %s\n", aglXGetProcAddress ? "Supported" : "Unsupported"); #elif defined ALLEGRO_UNIX #ifdef ALLEGROGL_GLXGETPROCADDRESSARB TRACE(PREFIX_I "glXGetProcAddressARB Extension: supported\n"); #else TRACE(PREFIX_I "glXGetProcAddress Extension: supported\n"); #endif #endif #ifdef ALLEGRO_MACOSX bundle_url = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, CFSTR("/System/Library/Frameworks/OpenGL.framework"), kCFURLPOSIXPathStyle, true); opengl_bundle_ref = CFBundleCreate(kCFAllocatorDefault, bundle_url); CFRelease(bundle_url); #endif __fill_in_info_struct(glGetString(GL_RENDERER), &allegro_gl_info); /* Load extensions */ agl_extension_table = __allegro_gl_create_extensions(); __allegro_gl_load_extensions(agl_extension_table); __allegro_gl_set_extensions(agl_extension_table); for (i = 0; i < 5; i++) { __allegro_gl_texture_read_format[i] = -1; __allegro_gl_texture_components[i] = GL_RGB; } __allegro_gl_texture_read_format[3] = GL_UNSIGNED_BYTE; __allegro_gl_texture_read_format[4] = GL_UNSIGNED_BYTE; __allegro_gl_texture_components[4] = GL_RGBA; /* Get extension info for the rest of the lib */ # define AGL_EXT(name, ver) { \ allegro_gl_extensions_GL.name = \ allegro_gl_is_extension_supported("GL_" #name) \ || (allegro_gl_info.version >= ver && ver > 0); \ } # include "allegrogl/GLext/gl_ext_list.h" # undef AGL_EXT #ifdef ALLEGRO_UNIX # define AGL_EXT(name, ver) { \ allegro_gl_extensions_GLX.name = \ allegro_gl_is_extension_supported("GLX_" #name) \ || (allegro_gl_info.version >= ver && ver > 0); \ } # include "allegrogl/GLext/glx_ext_list.h" # undef AGL_EXT #elif defined ALLEGRO_WINDOWS # define AGL_EXT(name, ver) { \ allegro_gl_extensions_WGL.name = \ allegro_gl_is_extension_supported("WGL_" #name) \ || (allegro_gl_info.version >= ver && ver > 0); \ } # include "allegrogl/GLext/wgl_ext_list.h" # undef AGL_EXT #endif /* Get number of texture units */ if (allegro_gl_extensions_GL.ARB_multitexture) { glGetIntegerv(GL_MAX_TEXTURE_UNITS, (GLint*)&allegro_gl_info.num_texture_units); } else { allegro_gl_info.num_texture_units = 1; } /* Get max texture size */ glGetIntegerv(GL_MAX_TEXTURE_SIZE, (GLint*)&allegro_gl_info.max_texture_size); /* Note: Voodoo (even V5) don't seem to correctly support * packed pixel formats. Disabling them for those cards. */ allegro_gl_extensions_GL.EXT_packed_pixels &= !allegro_gl_info.is_voodoo; if (allegro_gl_extensions_GL.EXT_packed_pixels) { AGL_LOG(1, "Packed Pixels formats available\n"); /* XXX On NV cards, we want to use BGRA instead of RGBA for speed */ /* Fills the __allegro_gl_texture_format array */ __allegro_gl_texture_read_format[0] = GL_UNSIGNED_BYTE_3_3_2; __allegro_gl_texture_read_format[1] = GL_UNSIGNED_SHORT_5_5_5_1; __allegro_gl_texture_read_format[2] = GL_UNSIGNED_SHORT_5_6_5; } /* NVidia and ATI cards expose OpenGL 2.0 but often don't accelerate * non-power-of-2 textures. This check is how you verify that NP2 * textures are hardware accelerated or not. * We should clobber the NPOT support if it's not accelerated. */ { const char *vendor = (const char*)glGetString(GL_VENDOR); if (strstr(vendor, "NVIDIA Corporation")) { if (!allegro_gl_extensions_GL.NV_fragment_program2 || !allegro_gl_extensions_GL.NV_vertex_program3) { allegro_gl_extensions_GL.ARB_texture_non_power_of_two = 0; } } else if (strstr(vendor, "ATI Technologies")) { if (!strstr((const char*)glGetString(GL_EXTENSIONS), "GL_ARB_texture_non_power_of_two") && allegro_gl_info.version >= 2.0f) { allegro_gl_extensions_GL.ARB_texture_non_power_of_two = 0; } } } } /* __allegro_gl_print_extensions: * Given a string containing extensions (i.e. a NULL terminated string where * each extension are separated by a space and which names do not contain any * space) */ void __allegro_gl_print_extensions(AL_CONST char * extension) { char buf[80]; char* start; while (*extension != '\0') { start = buf; strncpy(buf, extension, 80); while ((*start != ' ') && (*start != '\0')) { extension++; start++; } *start = '\0'; extension ++; TRACE(PREFIX_I "%s\n", buf); } } void __allegro_gl_unmanage_extensions() { __allegro_gl_destroy_extensions(agl_extension_table); #ifdef ALLEGRO_MACOSX CFRelease(opengl_bundle_ref); #endif #ifdef ALLEGROGL_HAVE_DYNAMIC_LINK if (__agl_handle) { dlclose(__agl_handle); __agl_handle = NULL; } #endif } allegro4.4-4.4.2/addons/allegrogl/src/glvtable.c000066400000000000000000002252711173507505700213720ustar00rootroot00000000000000/* This code is (C) AllegroGL contributors, and double licensed under * the GPL and zlib licenses. See gpl.txt or zlib.txt for details. */ /** \file glvtable.c * \brief Allegro->OpenGL conversion vtable. */ #include #include #ifdef ALLEGRO_WINDOWS #include #endif #include "alleggl.h" #include "allglint.h" #include "glvtable.h" #include #ifdef ALLEGRO_MACOSX #include #else #include #endif static GFX_VTABLE allegro_gl_screen_vtable; static GLuint __allegro_gl_pool_texture = 0; static GLuint __allegro_gl_dummy_texture = 0; /* For ATI Rage Pro */ static int __agl_owning_drawing_pattern_tex = FALSE; GLuint __agl_drawing_pattern_tex = 0; BITMAP *__agl_drawing_pattern_bmp = 0; static int __agl_drawing_mode = DRAW_MODE_SOLID; /** \defgroup glvtable Allegro Graphics Driver * These functions are used to implement Allegro function over an * OpenGL screen. * * Keep in mind that some restictions mentioned in Allegro docs about video * bitmaps and the screen do not apply when using AllegroGL GFX driver. Namely: * - Reading from video bitmaps is just as fast as reading from memory bitmaps. * - Doing translucent/transparent drawing on the screen can be very fast if * the source is a video bitmap. * - Drawing from video bitmap to a video bitmap will be pretty fast on modern * GFX cards with appropiate drivers installed. * - There are dozen of places in the Allegro docs where it says that a memory * bitmap must be used (drawing_mode(), polygon3d(), stretch_sprite() etc.). * This doesn't apply when AllegroGL is used. You can also use video bitmaps * and it will be quite fast. * * \{ */ /* Computes the next power of two if the number wasn't a power of two to start * with. Ref: http://bob.allegronetwork.com/prog/tricks.html#roundtonextpowerof2 */ int __allegro_gl_make_power_of_2(int x) { x--; x |= (x >> 1); x |= (x >> 2); x |= (x >> 4); x |= (x >> 8); x |= (x >> 16); x++; return x; } /* allegro_gl_drawing_mode (GFX_DRIVER vtable entry): * Sets the drawing mode. Same implementation to all GFX vtables. */ void allegro_gl_drawing_mode(void) { if (__agl_drawing_mode == _drawing_mode) return; switch (__agl_drawing_mode) { case DRAW_MODE_TRANS: glDisable(GL_BLEND); break; case DRAW_MODE_XOR: glDisable(GL_COLOR_LOGIC_OP); break; case DRAW_MODE_COPY_PATTERN: glDisable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, 0); if (__agl_owning_drawing_pattern_tex && __agl_drawing_pattern_tex) glDeleteTextures(1, &__agl_drawing_pattern_tex); __agl_drawing_pattern_tex = 0; __agl_drawing_pattern_bmp = 0; break; } __agl_drawing_mode = _drawing_mode; switch (_drawing_mode) { case DRAW_MODE_TRANS: glEnable(GL_BLEND); break; case DRAW_MODE_XOR: glEnable(GL_COLOR_LOGIC_OP); glLogicOp(GL_XOR); break; case DRAW_MODE_COPY_PATTERN: if (is_memory_bitmap(_drawing_pattern)) { __agl_drawing_pattern_tex = allegro_gl_make_texture(_drawing_pattern); __agl_drawing_pattern_bmp = _drawing_pattern; __agl_owning_drawing_pattern_tex = TRUE; } else if (is_video_bitmap(_drawing_pattern)) { AGL_VIDEO_BITMAP *bmp = _drawing_pattern->extra; __agl_drawing_pattern_tex = bmp->tex; __agl_drawing_pattern_bmp = bmp->memory_copy; __agl_owning_drawing_pattern_tex = FALSE; } glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, __agl_drawing_pattern_tex); break; } } void split_color(int color, GLubyte *r, GLubyte *g, GLubyte *b, GLubyte *a, int color_depth) { AGL_LOG(2, "glvtable.c:split_color\n"); *r = getr_depth(color_depth, color); *g = getg_depth(color_depth, color); *b = getb_depth(color_depth, color); if (color_depth == 32) *a = geta_depth(color_depth, color); else *a = 255; } /* allegro_gl_created_sub_bitmap: */ void allegro_gl_created_sub_bitmap(BITMAP *bmp, BITMAP *parent) { bmp->extra = parent; } /* static void allegro_gl_screen_acquire(struct BITMAP *bmp) */ /** acquire_bitmap(screen) overload. * This doesn't do anything, since OpenGL rendering context * doesn't need locking. You don't need to call this function * in your program. */ static void allegro_gl_screen_acquire(struct BITMAP *bmp) {} /* static void allegro_gl_screen_release(struct BITMAP *bmp) */ /** release_bitmap(screen) overload. * This doesn't do anything, since OpenGL rendering context * doesn't need locking. You don't need to call this function * in your program. */ static void allegro_gl_screen_release(struct BITMAP *bmp) {} static int allegro_gl_screen_getpixel(struct BITMAP *bmp, int x, int y) { GLubyte pixel[3]; AGL_LOG(2, "glvtable.c:allegro_gl_screen_getpixel\n"); if (bmp->clip && (x < bmp->cl || x >= bmp->cr || y < bmp->ct || y >= bmp->cb)) { return -1; } if (is_sub_bitmap(bmp)) { x += bmp->x_ofs; y += bmp->y_ofs; } glReadPixels(x, bmp->h - y - 1, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, pixel); return makecol_depth(bitmap_color_depth(screen), pixel[0], pixel[1], pixel[2]); } static void allegro_gl_screen_putpixel(struct BITMAP *bmp, int x, int y, int color) { GLubyte r, g, b, a; AGL_LOG(2, "glvtable.c:allegro_gl_screen_putpixel\n"); split_color(color, &r, &g, &b, &a, bitmap_color_depth(bmp)); if (bmp->clip && (x < bmp->cl || x >= bmp->cr || y < bmp->ct || y >= bmp->cb)) { return; } if (is_sub_bitmap(bmp)) { x += bmp->x_ofs; y += bmp->y_ofs; } glColor4ub(r, g, b, a); glBegin(GL_POINTS); glVertex2f(x, y); glEnd(); } static void allegro_gl_screen_vline(struct BITMAP *bmp, int x, int y1, int y2, int color) { GLubyte r, g, b, a; AGL_LOG(2, "glvtable.c:allegro_gl_screen_vline\n"); if (y1 > y2) { int temp = y1; y1 = y2; y2 = temp; } if (bmp->clip) { if ((x < bmp->cl) || (x >= bmp->cr)) { return; } if ((y1 >= bmp->cb) || (y2 < bmp->ct)) { return; } if (y1 < bmp->ct) { y1 = bmp->ct; } if (y2 >= bmp->cb) { y2 = bmp->cb - 1; } } if (is_sub_bitmap(bmp)) { x += bmp->x_ofs; y1 += bmp->y_ofs; y2 += bmp->y_ofs; } split_color(color, &r, &g, &b, &a, bitmap_color_depth(bmp)); glColor4ub(r, g, b, a); glBegin(GL_LINES); glVertex2f(x, y1); glVertex2f(x, y2 + 0.325 * 3); glEnd(); return; } static void allegro_gl_screen_hline(struct BITMAP *bmp, int x1, int y, int x2, int color) { GLubyte r, g, b, a; AGL_LOG(2, "glvtable.c:allegro_gl_hline\n"); if (x1 > x2) { int temp = x1; x1 = x2; x2 = temp; } if (bmp->clip) { if ((y < bmp->ct) || (y >= bmp->cb)) { return; } if ((x1 >= bmp->cr) || (x2 < bmp->cl)) { return; } if (x1 < bmp->cl) { x1 = bmp->cl; } if (x2 >= bmp->cr) { x2 = bmp->cr - 1; } } if (is_sub_bitmap(bmp)) { x1 += bmp->x_ofs; x2 += bmp->x_ofs; y += bmp->y_ofs; } split_color(color, &r, &g, &b, &a, bitmap_color_depth(bmp)); glColor4ub(r, g, b, a); glBegin(GL_LINES); glVertex2f(x1 - 0.325, y); glVertex2f(x2 + 0.325 * 2, y); glEnd(); return; } static void allegro_gl_screen_line(struct BITMAP *bmp, int x1, int y1, int x2, int y2, int color) { GLubyte r, g, b, a; AGL_LOG(2, "glvtable.c:allegro_gl_screen_line\n"); if (bmp->clip) { glPushAttrib(GL_SCISSOR_BIT); glEnable(GL_SCISSOR_TEST); glScissor(bmp->x_ofs + bmp->cl, bmp->h + bmp->y_ofs - bmp->cb, bmp->cr - bmp->cl, bmp->cb - bmp->ct); } if (is_sub_bitmap(bmp)) { x1 += bmp->x_ofs; x2 += bmp->x_ofs; y1 += bmp->y_ofs; y2 += bmp->y_ofs; } split_color(color, &r, &g, &b, &a, bitmap_color_depth(bmp)); glColor4ub(r, g, b, a); glBegin(GL_LINES); glVertex2f(x1 + 0.1625, y1 + 0.1625); glVertex2f(x2 + 0.1625, y2 + 0.1625); glEnd(); /* OpenGL skips the endpoint when drawing lines */ glBegin(GL_POINTS); glVertex2f(x2 + 0.1625, y2 + 0.1625); glEnd(); if (bmp->clip) { glPopAttrib(); } return; } #define SET_TEX_COORDS(x, y) \ do { \ if (__agl_drawing_pattern_tex) { \ glTexCoord2f ( \ (x - _drawing_x_anchor) / (float)__agl_drawing_pattern_bmp->w,\ (y - _drawing_y_anchor) / (float)__agl_drawing_pattern_bmp->h \ ); \ } \ } while(0) void allegro_gl_screen_rectfill(struct BITMAP *bmp, int x1, int y1, int x2, int y2, int color) { GLubyte r, g, b, a; GLfloat old_col[4]; AGL_LOG(2, "glvtable.c:allegro_gl_screen_rectfill\n"); if (x1 > x2) { int temp = x1; x1 = x2; x2 = temp; } if (y1 > y2) { int temp = y1; y1 = y2; y2 = temp; } if (bmp->clip) { if ((x1 > bmp->cr) || (x2 < bmp->cl)) { return; } if (x1 < bmp->cl) { x1 = bmp->cl; } if (x2 > bmp->cr) { x2 = bmp->cr; } if ((y1 > bmp->cb) || (y2 < bmp->ct)) { return; } if (y1 < bmp->ct) { y1 = bmp->ct; } if (y2 > bmp->cb) { y2 = bmp->cb; } } if (is_sub_bitmap(bmp)) { x1 += bmp->x_ofs; x2 += bmp->x_ofs; y1 += bmp->y_ofs; y2 += bmp->y_ofs; } glGetFloatv(GL_CURRENT_COLOR, old_col); split_color(color, &r, &g, &b, &a, bitmap_color_depth(bmp)); glColor4ub(r, g, b, a); glBegin(GL_QUADS); SET_TEX_COORDS(x1, y1); glVertex2f(x1, y1); SET_TEX_COORDS(x2, y1); glVertex2f(x2, y1); SET_TEX_COORDS(x2, y2); glVertex2f(x2, y2); SET_TEX_COORDS(x1, y2); glVertex2f(x1, y2); glEnd(); glColor4fv(old_col); return; } static void allegro_gl_screen_triangle(struct BITMAP *bmp, int x1, int y1, int x2, int y2, int x3, int y3, int color) { GLubyte r, g, b, a; AGL_LOG(2, "glvtable.c:allegro_gl_screen_triangle\n"); split_color(color, &r, &g, &b, &a, bitmap_color_depth(bmp)); if (bmp->clip) { glPushAttrib(GL_SCISSOR_BIT); glEnable(GL_SCISSOR_TEST); glScissor(bmp->x_ofs + bmp->cl, bmp->h + bmp->y_ofs - bmp->cb, bmp->cr - bmp->cl, bmp->cb - bmp->ct); } if (is_sub_bitmap(bmp)) { x1 += bmp->x_ofs; y1 += bmp->y_ofs; x2 += bmp->x_ofs; y2 += bmp->y_ofs; x3 += bmp->x_ofs; y3 += bmp->y_ofs; } glColor4ub(r, g, b, a); glBegin(GL_TRIANGLES); SET_TEX_COORDS(x1, y1); glVertex2f(x1, y1); SET_TEX_COORDS(x2, y2); glVertex2f(x2, y2); SET_TEX_COORDS(x3, y3); glVertex2f(x3, y3); glEnd(); if (bmp->clip) { glPopAttrib(); } } #define BITMAP_BLIT_CLIP(source, dest, source_x, source_y, dest_x, dest_y, \ width, height) { \ if (dest->clip) { \ if ((dest_x >= dest->cr) || (dest_y >= dest->cb) \ || (dest_x + width < dest->cl) || (dest_y + height < dest->ct)) { \ width = 0; \ } \ if (dest_x < dest->cl) { \ width += dest_x - dest->cl; \ source_x -= dest_x - dest->cl; \ dest_x = dest->cl; \ } \ if (dest_y < dest->ct) { \ height += dest_y - dest->ct; \ source_y -= dest_y - dest->ct; \ dest_y = dest->ct; \ } \ if (dest_x + width > dest->cr) { \ width = dest->cr - dest_x; \ } \ if (dest_y + height > dest->cb) { \ height = dest->cb - dest_y; \ } \ } \ if (source->clip) { \ if ((source_x >= source->cr) || (source_y >= source->cb) \ || (source_x + width < source->cl) \ || (source_y + height < source->ct)) { \ width = 0; \ } \ if (source_x < source->cl) { \ width += source_x - source->cl; \ dest_x -= source_x - source->cl; \ source_x = source->cl; \ } \ if (source_y < source->ct) { \ height += source_y - source->ct; \ dest_y -= source_y - source->ct; \ source_y = source->ct; \ } \ if (source_x + width > source->cr) { \ width = source->cr - source_x; \ } \ if (source_y + height > source->cb) { \ height = source->cb - source_y; \ } \ } \ } static void allegro_gl_screen_blit_from_memory( struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height) { GLfloat saved_zoom_x, saved_zoom_y; GLint saved_row_length; BITMAP *temp = NULL; void *data; AGL_LOG(2, "glvtable.c:allegro_gl_screen_blit_from_memory\n"); BITMAP_BLIT_CLIP(source, dest, source_x, source_y, dest_x, dest_y, width, height); if (width <= 0 || height <= 0) { return; } if (is_sub_bitmap(dest)) { dest_x += dest->x_ofs; dest_y += dest->y_ofs; } /* Note: We don't need to offset the source bitmap coordinates * because we use source->line[] directly, which is already offsetted for * us. */ data = source->line[source_y] + source_x * BYTES_PER_PIXEL(bitmap_color_depth(source)); /* If packed pixels (or GL 1.2) isn't supported, then we need to convert * the bitmap into something GL can understand - 24-bpp should do it. */ if (!allegro_gl_extensions_GL.EXT_packed_pixels && bitmap_color_depth(source) < 24) { temp = create_bitmap_ex(24, width, height); if (temp) { blit(source, temp, source_x, source_y, 0, 0, width, height); source_x = 0; source_y = 0; data = temp->line[0]; } else { /* XXX Report error? */ return; } source = temp; } /* Save state */ glGetFloatv(GL_ZOOM_X, &saved_zoom_x); glGetFloatv(GL_ZOOM_Y, &saved_zoom_y); glGetIntegerv(GL_UNPACK_ROW_LENGTH, &saved_row_length); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glRasterPos2i(dest_x, dest_y); /* XXX I wonder if it would be faster to use glDrawPixels() * one line at a time instead of playing with the Zoom factor. */ glPixelZoom (1.0, -1.0); glPixelStorei(GL_UNPACK_ROW_LENGTH, (source->line[1] - source->line[0]) / BYTES_PER_PIXEL(source->vtable->color_depth)); glDrawPixels(width, height, __allegro_gl_get_bitmap_color_format(source, 0), __allegro_gl_get_bitmap_type(source, 0), data); /* Restore state */ glPixelZoom(saved_zoom_x, saved_zoom_y); glPixelStorei(GL_UNPACK_ROW_LENGTH, saved_row_length); if (temp) { destroy_bitmap(temp); } return; } static void allegro_gl_screen_blit_to_memory( struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height) { GLint saved_row_length; GLint saved_alignment; GLint saved_pack_invert; BITMAP *bmp = NULL; AGL_LOG(2, "glvtable.c:allegro_gl_screen_blit_to_memory\n"); BITMAP_BLIT_CLIP(source, dest, source_x, source_y, dest_x, dest_y, width, height); if (is_sub_bitmap(source)) { source_x += source->x_ofs; source_y += source->y_ofs; } if (is_sub_bitmap(dest)) { dest_x += dest->x_ofs; dest_y += dest->y_ofs; } if (width <= 0 || height <= 0) { return; } /* Note that glPixelZoom doesn't affect reads -- so we have to do a flip. * We can do this by reading into a temporary bitmap then flipping that to * the destination, -OR- use the GL_MESA_pack_invert extension to do it * for us. * * If GL_EXT_packed_pixels isn't supported, then we can't use * MESA_pack_invert on 16-bpp bitmaps or less. */ if ( !allegro_gl_extensions_GL.MESA_pack_invert || (!allegro_gl_extensions_GL.EXT_packed_pixels && bitmap_color_depth(dest) < 24)) { /* XXX Bitmap format should be the same as the source * dest bitmap! */ if ((!allegro_gl_extensions_GL.EXT_packed_pixels && bitmap_color_depth(dest) < 24)) { bmp = create_bitmap_ex(24, width, height); } else { bmp = create_bitmap_ex(bitmap_color_depth(dest), width, height); } if (!bmp) return; } glGetIntegerv(GL_PACK_ROW_LENGTH, &saved_row_length); glGetIntegerv(GL_PACK_ALIGNMENT, &saved_alignment); glPixelStorei(GL_PACK_ROW_LENGTH, 0); glPixelStorei(GL_PACK_ALIGNMENT, 1); if (!allegro_gl_extensions_GL.MESA_pack_invert) { glReadPixels(source_x, source->h - source_y - height, width, height, __allegro_gl_get_bitmap_color_format(bmp, 0), __allegro_gl_get_bitmap_type(bmp, 0), bmp->dat); } else { glGetIntegerv(GL_PACK_INVERT_MESA, &saved_pack_invert); glPixelStorei(GL_PACK_INVERT_MESA, TRUE); glPixelStorei(GL_PACK_ROW_LENGTH, (dest->line[1] - dest->line[0]) / BYTES_PER_PIXEL(dest->vtable->color_depth)); glReadPixels(source_x, source->h - source_y - height, width, height, __allegro_gl_get_bitmap_color_format(dest, 0), __allegro_gl_get_bitmap_type(dest, 0), dest->line[0]); glPixelStorei(GL_PACK_INVERT_MESA, saved_pack_invert); } glPixelStorei(GL_PACK_ROW_LENGTH, saved_row_length); glPixelStorei(GL_PACK_ALIGNMENT, saved_alignment); /* Flip image if needed (glPixelZoom doesn't affect reads) */ if (bmp) { int y, dy; for (y = 0, dy = dest_y + height - 1; y < height; y++, dy--) { blit(bmp, dest, 0, y, dest_x, dy, width, 1); } destroy_bitmap(bmp); } return; } void allegro_gl_screen_blit_to_self ( struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height) { AGL_LOG(2, "glvtable.c:allegro_gl_screen_blit_to_self\n"); BITMAP_BLIT_CLIP(source, dest, source_x, source_y, dest_x, dest_y, width, height); if (is_sub_bitmap(source)) { source_x += source->x_ofs; source_y += source->y_ofs; } if (is_sub_bitmap(dest)) { dest_x += dest->x_ofs; dest_y += dest->y_ofs; } if (width <= 0 || height <= 0) { return; } /* screen -> screen */ if (is_screen_bitmap(source) && is_screen_bitmap(dest)) { glRasterPos2i(dest_x, dest_y + height - 1); glCopyPixels(source_x, SCREEN_H - source_y - height, width, height, GL_COLOR); } /* video -> screen */ else if (is_screen_bitmap(dest) && is_video_bitmap(source)) { AGL_VIDEO_BITMAP *vid; BITMAP *source_parent = source; GLfloat current_color[4]; while (source_parent->id & BMP_ID_SUB) { source_parent = (BITMAP *)source_parent->extra; } vid = source_parent->extra; glGetFloatv(GL_CURRENT_COLOR, current_color); glColor4ub(255, 255, 255, 255); while (vid) { int sx, sy; /* source coordinates */ int dx, dy; /* destination coordinates */ int w, h; if (source_x >= vid->x_ofs + vid->memory_copy->w || source_y >= vid->y_ofs + vid->memory_copy->h || vid->x_ofs >= source_x + width || vid->y_ofs >= source_y + height) { vid = vid->next; continue; } sx = MAX(vid->x_ofs, source_x) - vid->x_ofs; w = MIN(vid->x_ofs + vid->memory_copy->w, source_x + width) - vid->x_ofs - sx; sy = MAX(vid->y_ofs, source_y) - vid->y_ofs; h = MIN(vid->y_ofs + vid->memory_copy->h, source_y + height) - vid->y_ofs - sy; dx = dest_x + vid->x_ofs + sx - source_x; dy = dest_y + vid->y_ofs + sy - source_y; glEnable(vid->target); glBindTexture(vid->target, vid->tex); if (vid->target == GL_TEXTURE_2D) { float tx = sx / (float)vid->memory_copy->w; float ty = sy / (float)vid->memory_copy->h; float tw = w / (float)vid->memory_copy->w; float th = h / (float)vid->memory_copy->h; glBegin(GL_QUADS); glTexCoord2f(tx, ty); glVertex2f(dx, dy); glTexCoord2f(tx, ty + th); glVertex2f(dx, dy + h); glTexCoord2f(tx + tw, ty + th); glVertex2f(dx + w, dy + h); glTexCoord2f(tx + tw, ty); glVertex2f(dx + w, dy); glEnd(); } else { glBegin(GL_QUADS); glTexCoord2i(sx, sy); glVertex2f(dx, dy); glTexCoord2i(sx, sy + h); glVertex2f(dx, dy + h); glTexCoord2i(sx + w, sy + h); glVertex2f(dx + w, dy + h); glTexCoord2i(sx + w, sy); glVertex2f(dx + w, dy); glEnd(); } glBindTexture(vid->target, 0); glDisable(vid->target); vid = vid->next; } glColor4fv(current_color); } /* screen -> video */ else if (is_screen_bitmap(source) && is_video_bitmap(dest)) { AGL_VIDEO_BITMAP *vid; BITMAP *source_parent = source; while (source_parent->id & BMP_ID_SUB) { source_parent = (BITMAP *)source_parent->extra; } vid = dest->extra; while (vid) { int sx, sy; /* source coordinates */ int dx, dy; /* destination coordinates */ int w, h; if (dest_x >= vid->x_ofs + vid->memory_copy->w || dest_y >= vid->y_ofs + vid->memory_copy->h || vid->x_ofs >= dest_x + width || vid->y_ofs >= dest_y + height) { vid = vid->next; continue; } dx = MAX(vid->x_ofs, dest_x) - vid->x_ofs; w = MIN(vid->x_ofs + vid->memory_copy->w, dest_x + width) - vid->x_ofs - dx; dy = MAX(vid->y_ofs, dest_y) - vid->y_ofs; h = MIN(vid->y_ofs + vid->memory_copy->h, dest_y + height) - vid->y_ofs - dy; sx = source_x + vid->x_ofs + dx - dest_x; sy = source_y + vid->y_ofs + dy - dest_y; /* We cannot use glCopyTexSubImage2D() here because it will flip the image. */ allegro_gl_screen_blit_to_memory(source, vid->memory_copy, sx, sy, dx, dy, w, h); allegro_gl_video_blit_from_memory(vid->memory_copy, dest, 0, 0, vid->x_ofs, vid->y_ofs, vid->memory_copy->w, vid->memory_copy->h); vid = vid->next; } } else if (is_video_bitmap(source) && is_video_bitmap(dest)) { allegro_gl_video_blit_to_self(source, dest, source_x, source_y, dest_x, dest_y, width, height); } } void allegro_gl_upload_and_display_texture(struct BITMAP *source, int source_x, int source_y, int dest_x, int dest_y, int width, int height, int flip_dir, GLint format, GLint type) { float tx, ty; GLint saved_row_length; int bytes_per_pixel = BYTES_PER_PIXEL(bitmap_color_depth(source)); int i, j; glEnable(GL_ALPHA_TEST); glAlphaFunc(GL_GREATER, 0.0f); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, __allegro_gl_pool_texture); glGetIntegerv(GL_UNPACK_ROW_LENGTH, &saved_row_length); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glPixelStorei(GL_UNPACK_ROW_LENGTH, (source->line[1] - source->line[0]) / bytes_per_pixel); for (i = 0; i <= abs(width) / 256; i++) { for (j = 0; j <= abs(height) / 256; j++) { void *data = source->line[source_y + j * 256] + (source_x + i * 256) * bytes_per_pixel; int w = abs(width) - i * 256; int h = abs(height) - j * 256; int dx = dest_x + i * 256; int dy = dest_y + j * 256; w = (w & -256) ? 256 : w; h = (h & -256) ? 256 : h; glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, format, type, data); tx = (float)w / 256.; ty = (float)h / 256.; if (flip_dir & AGL_H_FLIP) { dx = 2*dest_x + width - dx; w = -w; } if (flip_dir & AGL_V_FLIP) { dy = 2*dest_y + height - dy; h = -h; } if (width < 0) w = -w; if (height < 0) h = -h; glBegin(GL_QUADS); glTexCoord2f(0., 0.); glVertex2i(dx, dy); glTexCoord2f(0., ty); glVertex2i(dx, dy + h); glTexCoord2f(tx, ty); glVertex2i(dx + w, dy + h); glTexCoord2f(tx, 0.); glVertex2i(dx + w, dy); glEnd(); } } /* Restore state */ glPixelStorei(GL_UNPACK_ROW_LENGTH, saved_row_length); glBindTexture(GL_TEXTURE_2D, 0); glDisable(GL_TEXTURE_2D); glDisable(GL_ALPHA_TEST); return; } static void do_screen_masked_blit_standard(GLint format, GLint type, struct BITMAP *temp, int source_x, int source_y, int dest_x, int dest_y, int width, int height, int flip_dir, int blit_type) { glPushAttrib(GL_COLOR_BUFFER_BIT | GL_ENABLE_BIT); if (blit_type & AGL_NO_ROTATION) { GLint saved_row_length; float dx = dest_x, dy = dest_y; GLfloat zoom_x, zoom_y, old_zoom_x, old_zoom_y; glEnable(GL_ALPHA_TEST); glAlphaFunc(GL_GREATER, 0.0f); glGetIntegerv(GL_UNPACK_ROW_LENGTH, &saved_row_length); glGetFloatv(GL_ZOOM_X, &old_zoom_x); glGetFloatv(GL_ZOOM_Y, &old_zoom_y); if (flip_dir & AGL_H_FLIP) { zoom_x = -1.0f; /* Without the -0.5 below, we get an invalid position, * and the operation is ignored by OpenGL. */ dx += abs(width) - 0.5; } else { zoom_x = (float) width / abs(width); } if (flip_dir & AGL_V_FLIP) { zoom_y = 1.0f; dy += abs(height) - 0.5; } else { zoom_y = -1.0f * width / abs(width); } glRasterPos2f(dx, dy); glPixelZoom(zoom_x, zoom_y); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glPixelStorei(GL_UNPACK_ROW_LENGTH, (temp->line[1] - temp->line[0]) / BYTES_PER_PIXEL(bitmap_color_depth(temp))); glDrawPixels(abs(width), abs(height), format, type, temp->line[0]); glPixelStorei(GL_UNPACK_ROW_LENGTH, saved_row_length); glPixelZoom(old_zoom_x, old_zoom_y); } else { allegro_gl_upload_and_display_texture(temp, 0, 0, dest_x, dest_y, width, height, flip_dir, format, type); } glPopAttrib(); } static void screen_masked_blit_standard(struct BITMAP *source, int source_x, int source_y, int dest_x, int dest_y, int width, int height, int flip_dir, int blit_type) { BITMAP *temp = NULL; GLint format, type; format = __allegro_gl_get_bitmap_color_format(source, AGL_TEXTURE_MASKED); type = __allegro_gl_get_bitmap_type(source, AGL_TEXTURE_MASKED); temp = __allegro_gl_munge_bitmap(AGL_TEXTURE_MASKED, source, source_x, source_y, abs(width), abs(height), &type, &format); if (temp) { source = temp; } do_screen_masked_blit_standard(format, type, source, source_x, source_y, dest_x, dest_y, width, height, flip_dir, blit_type); if (temp) { destroy_bitmap(temp); } return; } static void __allegro_gl_init_nv_register_combiners(BITMAP *bmp) { GLfloat mask_color[4]; int depth = bitmap_color_depth(bmp); int color = bitmap_mask_color(bmp); mask_color[0] = getr_depth(depth, color) / 255.; mask_color[1] = getg_depth(depth, color) / 255.; mask_color[2] = getb_depth(depth, color) / 255.; mask_color[3] = 0.; glCombinerParameterfvNV(GL_CONSTANT_COLOR0_NV, mask_color); glCombinerParameteriNV(GL_NUM_GENERAL_COMBINERS_NV, 2); glEnable(GL_REGISTER_COMBINERS_NV); glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_A_NV, GL_TEXTURE0_ARB, GL_SIGNED_IDENTITY_NV, GL_RGB); glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_B_NV, GL_ZERO, GL_UNSIGNED_INVERT_NV, GL_RGB); glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_C_NV, GL_CONSTANT_COLOR0_NV, GL_SIGNED_IDENTITY_NV, GL_RGB); glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_D_NV, GL_ZERO, GL_EXPAND_NORMAL_NV, GL_RGB); glCombinerOutputNV(GL_COMBINER0_NV, GL_RGB, GL_DISCARD_NV, GL_DISCARD_NV, GL_SPARE0_NV, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE); glCombinerInputNV(GL_COMBINER1_NV, GL_RGB, GL_VARIABLE_A_NV, GL_SPARE0_NV, GL_SIGNED_IDENTITY_NV, GL_RGB); glCombinerInputNV(GL_COMBINER1_NV, GL_RGB, GL_VARIABLE_B_NV, GL_SPARE0_NV, GL_SIGNED_IDENTITY_NV, GL_RGB); glCombinerOutputNV(GL_COMBINER1_NV, GL_RGB, GL_SPARE1_NV, GL_DISCARD_NV, GL_DISCARD_NV, GL_NONE, GL_NONE, GL_TRUE, GL_FALSE, GL_FALSE); glFinalCombinerInputNV(GL_VARIABLE_A_NV, GL_TEXTURE0_ARB, GL_UNSIGNED_IDENTITY_NV, GL_RGB); glFinalCombinerInputNV(GL_VARIABLE_B_NV, GL_ZERO, GL_UNSIGNED_INVERT_NV, GL_RGB); glFinalCombinerInputNV(GL_VARIABLE_C_NV, GL_ZERO, GL_UNSIGNED_IDENTITY_NV, GL_RGB); glFinalCombinerInputNV(GL_VARIABLE_D_NV, GL_ZERO, GL_UNSIGNED_IDENTITY_NV, GL_RGB); glFinalCombinerInputNV(GL_VARIABLE_G_NV, GL_SPARE1_NV, GL_UNSIGNED_IDENTITY_NV, GL_BLUE); return; } static void screen_masked_blit_nv_register(struct BITMAP *source, int source_x, int source_y, int dest_x, int dest_y, int width, int height, int flip_dir, int blit_type) { BITMAP *temp = NULL; GLint type = __allegro_gl_get_bitmap_type(source, 0); GLint format = __allegro_gl_get_bitmap_color_format(source, 0); if (type == -1) { temp = create_bitmap_ex(24, width, height); if (!temp) { return; } blit(source, temp, source_x, source_y, 0, 0, width, height); source = temp; source_x = 0; source_y = 0; type = __allegro_gl_get_bitmap_type(source, 0); format = __allegro_gl_get_bitmap_color_format(source, 0); } glPushAttrib(GL_TEXTURE_BIT | GL_COLOR_BUFFER_BIT | GL_ENABLE_BIT); __allegro_gl_init_nv_register_combiners(source); allegro_gl_upload_and_display_texture(source, source_x, source_y, dest_x, dest_y, width, height, flip_dir, format, type); glPopAttrib(); if (temp) { destroy_bitmap(temp); } return; } static void __allegro_gl_init_combine_textures(BITMAP *bmp) { GLubyte mask_color[4]; split_color(bitmap_mask_color(bmp), &mask_color[0], &mask_color[1], &mask_color[2], &mask_color[3], bitmap_color_depth(bmp)); glColor4ubv(mask_color); glActiveTexture(GL_TEXTURE0); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB); glEnable(GL_TEXTURE_2D); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_ADD_SIGNED_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PRIMARY_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_ONE_MINUS_SRC_COLOR); /* Dot the result of the subtract with itself. Store it in the alpha * component. The alpha should then be 0 if the color fragment was equal to * the mask color, or >0 otherwise. */ glActiveTexture(GL_TEXTURE1); glEnable(GL_TEXTURE_2D); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_DOT3_RGBA_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB); /* Put the original RGB value in its place */ glActiveTexture(GL_TEXTURE2); glEnable(GL_TEXTURE_2D); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PREVIOUS_ARB); glActiveTexture(GL_TEXTURE0); return; } static void screen_masked_blit_combine_tex(struct BITMAP *source, int source_x, int source_y, int dest_x, int dest_y, int width, int height, int flip_dir, int blit_type) { float tx, ty; BITMAP *temp = NULL; GLint saved_row_length; GLint type = __allegro_gl_get_bitmap_type(source, 0); GLint format = __allegro_gl_get_bitmap_color_format(source, 0); int bytes_per_pixel; int i, j; GLfloat current_color[4]; if (type == -1) { temp = create_bitmap_ex(24, width, height); if (!temp) return; blit(source, temp, source_x, source_y, 0, 0, width, height); source = temp; source_x = 0; source_y = 0; type = __allegro_gl_get_bitmap_type(source, 0); format = __allegro_gl_get_bitmap_color_format(source, 0); } glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, __allegro_gl_pool_texture); glPushAttrib(GL_TEXTURE_BIT | GL_COLOR_BUFFER_BIT | GL_ENABLE_BIT); glGetFloatv(GL_CURRENT_COLOR, current_color); __allegro_gl_init_combine_textures(source); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, __allegro_gl_pool_texture); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, __allegro_gl_pool_texture); glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D, __allegro_gl_pool_texture); glActiveTexture(GL_TEXTURE0); bytes_per_pixel = BYTES_PER_PIXEL(bitmap_color_depth(source)); glEnable(GL_ALPHA_TEST); glAlphaFunc(GL_GREATER, 0.0f); glGetIntegerv(GL_UNPACK_ROW_LENGTH, &saved_row_length); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glPixelStorei(GL_UNPACK_ROW_LENGTH, (source->line[1] - source->line[0]) / bytes_per_pixel); for (i = 0; i <= width / 256; i++) { for (j = 0; j <= height / 256; j++) { void *data = source->line[source_y + j * 256] + (source_x + i * 256) * bytes_per_pixel; int w = width - i * 256; int h = height - j * 256; int dx = dest_x + i * 256; int dy = dest_y + j * 256; w = (w & -256) ? 256 : w; h = (h & -256) ? 256 : h; glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, format, type, data); tx = (float)w / 256.; ty = (float)h / 256.; if (flip_dir & AGL_H_FLIP) { dx = 2*dest_x + width - dx; w = -w; } if (flip_dir & AGL_V_FLIP) { dy = 2*dest_y + height - dy; h = -h; } glBegin(GL_QUADS); glMultiTexCoord2f(GL_TEXTURE0, 0., 0.); glMultiTexCoord2f(GL_TEXTURE1, 0., 0.); glMultiTexCoord2f(GL_TEXTURE2, 0., 0.); glVertex2f(dx, dy); glMultiTexCoord2f(GL_TEXTURE0, 0., ty); glMultiTexCoord2f(GL_TEXTURE1, 0., ty); glMultiTexCoord2f(GL_TEXTURE2, 0., ty); glVertex2f(dx, dy + h); glMultiTexCoord2f(GL_TEXTURE0, tx, ty); glMultiTexCoord2f(GL_TEXTURE1, tx, ty); glMultiTexCoord2f(GL_TEXTURE2, tx, ty); glVertex2f(dx + w, dy + h); glMultiTexCoord2f(GL_TEXTURE0, tx, 0.); glMultiTexCoord2f(GL_TEXTURE1, tx, 0.); glMultiTexCoord2f(GL_TEXTURE2, tx, 0.); glVertex2f(dx + w, dy); glEnd(); } } /* Restore state */ glPixelStorei(GL_UNPACK_ROW_LENGTH, saved_row_length); glBindTexture(GL_TEXTURE_2D, 0); glDisable(GL_TEXTURE_2D); glPopAttrib(); glColor4fv(current_color); if (temp) { destroy_bitmap(temp); } return; } void do_masked_blit_screen(struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height, int flip_dir, int blit_type) { /* XXX We should merge this clip code with the * BITMAP_BLIT_CLIP macro */ /* Clipping of destination bitmap */ if (dest->clip && (blit_type & AGL_NO_ROTATION)) { if ((dest_x >= dest->cr) || (dest_y >= dest->cb) || (dest_x + width < dest->cl) || (dest_y + height < dest->ct)) { return; } if (flip_dir & AGL_H_FLIP) { if (dest_x < dest->cl) { width += dest_x - dest->cl; dest_x = dest->cl; } if (dest_x + width > dest->cr) { source_x += dest_x + width - dest->cr; width = dest->cr - dest_x; } } else { if (dest_x < dest->cl) { width += dest_x - dest->cl; source_x -= dest_x - dest->cl; dest_x = dest->cl; } if (dest_x + width > dest->cr) { width = dest->cr - dest_x; } } if (flip_dir & AGL_V_FLIP) { if (dest_y < dest->ct) { height += dest_y - dest->ct; dest_y = dest->ct; } if (dest_y + height > dest->cb) { source_y += dest_y + height - dest->cb; height = dest->cb - dest_y; } } else { if (dest_y < dest->ct) { height += dest_y - dest->ct; source_y -= dest_y - dest->ct; dest_y = dest->ct; } if (dest_y + height > dest->cb) { height = dest->cb - dest_y; } } } /* Clipping of source bitmap */ if (source->clip && (blit_type & AGL_REGULAR_BMP)) { if ((source_x >= source->cr) || (source_y >= source->cb) || (source_x + width < source->cl) || (source_y + height < source->ct)) { return; } if (source_x < source->cl) { width += source_x - source->cl; dest_x -= source_x - source->cl; source_x = source->cl; } if (source_y < source->ct) { height += source_y - source->ct; dest_y -= source_y - source->ct; source_y = source->ct; } if (source_x + width > source->cr) { width = source->cr - source_x; } if (source_y + height > source->cb) { height = source->cb - source_y; } } if (is_sub_bitmap(dest)) { dest_x += dest->x_ofs; dest_y += dest->y_ofs; } if (width <= 0 || height <= 0) return; /* memory -> screen */ if (!is_video_bitmap(source) && !is_screen_bitmap(source)) { __allegro_gl_driver->screen_masked_blit(source, source_x, source_y, dest_x, dest_y, width, height, flip_dir, blit_type); } /* video -> screen */ else if (is_video_bitmap(source)) { AGL_VIDEO_BITMAP *vid; BITMAP *source_parent = source; int use_combiners = 0; /* Special combiner paths */ if (allegro_gl_extensions_GL.NV_register_combiners || allegro_gl_info.num_texture_units >= 3) { use_combiners = 1; glPushAttrib(GL_ENABLE_BIT | GL_TEXTURE_BIT | GL_COLOR_BUFFER_BIT); if (allegro_gl_extensions_GL.NV_register_combiners) { __allegro_gl_init_nv_register_combiners(source); } else { __allegro_gl_init_combine_textures(source); } glEnable(GL_ALPHA_TEST); glAlphaFunc(GL_GREATER, 0.0f); } while (source_parent->id & BMP_ID_SUB) { source_parent = (BITMAP *)source_parent->extra; } vid = source_parent->extra; while (vid) { int sx, sy; /* source coordinates */ int dx, dy; /* destination coordinates */ int w, h; if (source_x >= vid->x_ofs + vid->memory_copy->w || source_y >= vid->y_ofs + vid->memory_copy->h || vid->x_ofs >= source_x + width || vid->y_ofs >= source_y + height) { vid = vid->next; continue; } sx = MAX (vid->x_ofs, source_x) - vid->x_ofs; w = MIN (vid->x_ofs + vid->memory_copy->w, source_x + width) - vid->x_ofs - sx; sy = MAX (vid->y_ofs, source_y) - vid->y_ofs; h = MIN (vid->y_ofs + vid->memory_copy->h, source_y + height) - vid->y_ofs - sy; dx = dest_x + vid->x_ofs + sx - source_x; dy = dest_y + vid->y_ofs + sy - source_y; if (flip_dir & AGL_H_FLIP) { dx = 2*dest_x + width - dx; w = -w; } if (flip_dir & AGL_V_FLIP) { dy = 2*dest_y + height - dy; h = -h; } if (use_combiners) { if (allegro_gl_extensions_GL.NV_register_combiners) { glEnable(vid->target); glBindTexture(vid->target, vid->tex); glTexParameteri(vid->target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(vid->target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); if (vid->target == GL_TEXTURE_2D) { float tx = sx / (float)vid->memory_copy->w; float ty = sy / (float)vid->memory_copy->h; float tw = abs(w) / (float)vid->memory_copy->w; float th = abs(h) / (float)vid->memory_copy->h; glBegin(GL_QUADS); glTexCoord2f(tx, ty); glVertex2f(dx, dy); glTexCoord2f(tx, ty + th); glVertex2f(dx, dy + h); glTexCoord2f(tx + tw, ty + th); glVertex2f(dx + w, dy + h); glTexCoord2f(tx + tw, ty); glVertex2f(dx + w, dy); glEnd(); } else { glBegin(GL_QUADS); glTexCoord2i(sx, sy); glVertex2f(dx, dy); glTexCoord2i(sx, sy + h); glVertex2f(dx, dy + h); glTexCoord2i(sx + w, sy + h); glVertex2f(dx + w, dy + h); glTexCoord2i(sx + w, sy); glVertex2f(dx + w, dy); glEnd(); } glBindTexture(vid->target, 0); glDisable(vid->target); } else { glEnable(vid->target); glActiveTexture(GL_TEXTURE0); glBindTexture(vid->target, vid->tex); glActiveTexture(GL_TEXTURE1); glBindTexture(vid->target, vid->tex); glActiveTexture(GL_TEXTURE2); glBindTexture(vid->target, vid->tex); glActiveTexture(GL_TEXTURE0); glTexParameteri(vid->target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(vid->target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); if (vid->target == GL_TEXTURE_2D) { float tx, ty, tw, th; /* texture coordinates */ tx = sx / (float)vid->memory_copy->w; ty = sy / (float)vid->memory_copy->h; tw = abs(w) / (float)vid->memory_copy->w; th = abs(h) / (float)vid->memory_copy->h; glBegin(GL_QUADS); glMultiTexCoord2f(GL_TEXTURE0, tx, ty); glMultiTexCoord2f(GL_TEXTURE1, tx, ty); glMultiTexCoord2f(GL_TEXTURE2, tx, ty); glVertex2f(dx, dy); glMultiTexCoord2f(GL_TEXTURE0, tx, ty + th); glMultiTexCoord2f(GL_TEXTURE1, tx, ty + th); glMultiTexCoord2f(GL_TEXTURE2, tx, ty + th); glVertex2f(dx, dy + h); glMultiTexCoord2f(GL_TEXTURE0, tx + tw, ty + th); glMultiTexCoord2f(GL_TEXTURE1, tx + tw, ty + th); glMultiTexCoord2f(GL_TEXTURE2, tx + tw, ty + th); glVertex2f(dx + w, dy + h); glMultiTexCoord2f(GL_TEXTURE0, tx + tw, ty); glMultiTexCoord2f(GL_TEXTURE1, tx + tw, ty); glMultiTexCoord2f(GL_TEXTURE2, tx + tw, ty); glVertex2f(dx + w, dy); glEnd(); } else { glBegin(GL_QUADS); glMultiTexCoord2i(GL_TEXTURE0, dx, dy); glMultiTexCoord2i(GL_TEXTURE1, dx, dy); glMultiTexCoord2i(GL_TEXTURE2, dx, dy); glVertex2f(dx, dy); glMultiTexCoord2i(GL_TEXTURE0, dx, dy + h); glMultiTexCoord2i(GL_TEXTURE1, dx, dy + h); glMultiTexCoord2i(GL_TEXTURE2, dx, dy + h); glVertex2f(dx, dy + h); glMultiTexCoord2i(GL_TEXTURE0, dx + w, dy + h); glMultiTexCoord2i(GL_TEXTURE1, dx + w, dy + h); glMultiTexCoord2i(GL_TEXTURE2, dx + w, dy + h); glVertex2f(dx + w, dy + h); glMultiTexCoord2i(GL_TEXTURE0, dx + w, dy); glMultiTexCoord2i(GL_TEXTURE1, dx + w, dy); glMultiTexCoord2i(GL_TEXTURE2, dx + w, dy); glVertex2f(dx + w, dy); glEnd(); } glBindTexture(vid->target, 0); glDisable(vid->target); } } else { screen_masked_blit_standard(vid->memory_copy, sx, sy, dx, dy, w, h, FALSE, blit_type); } vid = vid->next; } if (use_combiners) { glPopAttrib(); } } return; } static BITMAP* __allegro_gl_convert_rle_sprite(AL_CONST struct RLE_SPRITE *sprite, int trans) { BITMAP *temp = NULL; int y, x, src_depth; signed long src_mask; #define DRAW_RLE_8888(bits) \ { \ for (y = 0; y < sprite->h; y++) { \ signed long c = *s++; \ for (x = 0; x < sprite->w;) { \ if (c == src_mask) \ break; \ if (c > 0) { \ /* Run of solid pixels */ \ for (c--; c>=0; c--) { \ unsigned long col = *s++; \ if (bits == 32 && trans) \ _putpixel32(temp, x++, y, makeacol32(getr32(col), getg32(col), getb32(col), geta32(col))); \ else \ _putpixel32(temp, x++, y, makeacol32(getr##bits(col), getg##bits(col), getb##bits(col), 255)); \ } \ } \ else { \ /* Run of transparent pixels */ \ hline(temp, x, y, x-c+1, 0); \ x -= c; \ } \ c = *s++; \ } \ } \ } src_depth = sprite->color_depth; if (src_depth == 8) src_mask = 0; else src_mask = makecol_depth(src_depth, 255, 0, 255); temp = create_bitmap_ex(32, sprite->w, sprite->h); if (!temp) return NULL; /* RGBA 8888 */ switch(src_depth) { case 8: { signed char *s = (signed char*)sprite->dat; DRAW_RLE_8888(8); break; } case 15: { int16_t *s = (int16_t*)sprite->dat; DRAW_RLE_8888(15); break; } case 16: { int16_t *s = (int16_t*)sprite->dat; DRAW_RLE_8888(16); break; } case 24: { int32_t *s = (int32_t*)sprite->dat; DRAW_RLE_8888(24); break; } case 32: { int32_t *s = (int32_t*)sprite->dat; DRAW_RLE_8888(32); break; } } return temp; } void allegro_gl_screen_draw_rle_sprite(struct BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y) { BITMAP *temp = NULL, *temp2 = NULL; int source_x = 0, source_y = 0; int width = sprite->w, height = sprite->h; temp = __allegro_gl_convert_rle_sprite(sprite, FALSE); if (!temp) return; BITMAP_BLIT_CLIP(temp, bmp, source_x, source_y, x, y, width, height); if (is_sub_bitmap(bmp)) { x += bmp->x_ofs; y += bmp->y_ofs; } if (width <= 0 || height <= 0) { destroy_bitmap(temp); return; } temp2 = create_sub_bitmap(temp, source_x, source_y, width, height); if (!temp2) { destroy_bitmap(temp); return; } do_screen_masked_blit_standard(GL_RGBA, __allegro_gl_get_bitmap_type(temp2, AGL_TEXTURE_MASKED), temp2, 0, 0, x, y, width, height, FALSE, AGL_NO_ROTATION); destroy_bitmap(temp2); destroy_bitmap(temp); } static void allegro_gl_screen_draw_trans_rgba_rle_sprite(struct BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y) { BITMAP *temp = NULL, *temp2 = NULL; int source_x = 0, source_y = 0; int width = sprite->w, height = sprite->h; temp = __allegro_gl_convert_rle_sprite(sprite, TRUE); if (!temp) return; BITMAP_BLIT_CLIP(temp, bmp, source_x, source_y, x, y, width, height); if (is_sub_bitmap(bmp)) { x += bmp->x_ofs; y += bmp->y_ofs; } if (width <= 0 || height <= 0) { destroy_bitmap(temp); return; } temp2 = create_sub_bitmap(temp, source_x, source_y, width, height); if (!temp2) { destroy_bitmap(temp); return; } if (__allegro_gl_blit_operation == AGL_OP_LOGIC_OP) glEnable(GL_COLOR_LOGIC_OP); else glEnable(GL_BLEND); allegro_gl_upload_and_display_texture(temp2, 0, 0, x, y, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE); if (__allegro_gl_blit_operation == AGL_OP_LOGIC_OP) glDisable(GL_COLOR_LOGIC_OP); else glDisable(GL_BLEND); destroy_bitmap(temp2); destroy_bitmap(temp); } static void allegro_gl_screen_masked_blit(struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height) { AGL_LOG(2, "glvtable.c:allegro_gl_screen_masked_blit\n"); do_masked_blit_screen(source, dest, source_x, source_y, dest_x, dest_y, width, height, FALSE, AGL_REGULAR_BMP | AGL_NO_ROTATION); } static void allegro_gl_screen_draw_sprite(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y) { AGL_LOG(2, "glvtable.c:allegro_gl_screen_draw_sprite\n"); do_masked_blit_screen(sprite, bmp, 0, 0, x, y, sprite->w, sprite->h, FALSE, AGL_NO_ROTATION); } static void allegro_gl_screen_draw_sprite_v_flip(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y) { AGL_LOG(2, "glvtable.c:allegro_gl_screen_draw_sprite_v_flip\n"); do_masked_blit_screen(sprite, bmp, 0, 0, x, y, sprite->w, sprite->h, AGL_V_FLIP, AGL_NO_ROTATION); } static void allegro_gl_screen_draw_sprite_h_flip(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y) { AGL_LOG(2, "glvtable.c:allegro_gl_screen_draw_sprite_h_flip\n"); do_masked_blit_screen(sprite, bmp, 0, 0, x, y, sprite->w, sprite->h, AGL_H_FLIP, AGL_NO_ROTATION); } static void allegro_gl_screen_draw_sprite_vh_flip(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y) { AGL_LOG(2, "glvtable.c:allegro_gl_screen_draw_sprite_vh_flip\n"); do_masked_blit_screen(sprite, bmp, 0, 0, x, y, sprite->w, sprite->h, AGL_V_FLIP | AGL_H_FLIP, AGL_NO_ROTATION); } static void allegro_gl_screen_pivot_scaled_sprite_flip(struct BITMAP *bmp, struct BITMAP *sprite, fixed x, fixed y, fixed cx, fixed cy, fixed angle, fixed scale, int v_flip) { double dscale = fixtof(scale); GLint matrix_mode; AGL_LOG(2, "glvtable.c:allegro_gl_screen_pivot_scaled_sprite_flip\n"); #define BIN_2_DEG(x) (-(x) * 180.0 / 128) glGetIntegerv(GL_MATRIX_MODE, &matrix_mode); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glTranslated(fixtof(x), fixtof(y), 0.); glRotated(BIN_2_DEG(fixtof(angle)), 0., 0., -1.); glScaled(dscale, dscale, dscale); glTranslated(-fixtof(x+cx), -fixtof(y+cy), 0.); do_masked_blit_screen(sprite, bmp, 0, 0, fixtoi(x), fixtoi(y), sprite->w, sprite->h, v_flip ? AGL_V_FLIP : FALSE, FALSE); glPopMatrix(); glMatrixMode(matrix_mode); #undef BIN_2_DEG return; } static void allegro_gl_screen_draw_trans_rgba_sprite(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y) { if (__allegro_gl_blit_operation == AGL_OP_LOGIC_OP) glEnable(GL_COLOR_LOGIC_OP); else glEnable(GL_BLEND); /* video -> screen */ if (is_video_bitmap(sprite)) { allegro_gl_screen_blit_to_self(sprite, bmp, 0, 0, x, y, sprite->w, sprite->h); } /* memory -> screen */ else if (is_memory_bitmap(sprite)) { GLint format = __allegro_gl_get_bitmap_color_format(sprite, AGL_TEXTURE_HAS_ALPHA); GLint type = __allegro_gl_get_bitmap_type(sprite, 0); allegro_gl_upload_and_display_texture(sprite, 0, 0, x, y, sprite->w, sprite->h, 0, format, type); } if (__allegro_gl_blit_operation == AGL_OP_LOGIC_OP) glDisable(GL_COLOR_LOGIC_OP); else glDisable(GL_BLEND); return; } static void allegro_gl_screen_draw_sprite_ex(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y, int mode, int flip) { int lflip = 0; int matrix_mode; AGL_LOG(2, "glvtable.c:allegro_gl_screen_draw_sprite_ex\n"); /* convert allegro's flipping flags to AGL's flags */ switch (flip) { case DRAW_SPRITE_NO_FLIP: lflip = FALSE; break; case DRAW_SPRITE_V_FLIP: lflip = AGL_V_FLIP; break; case DRAW_SPRITE_H_FLIP: lflip = AGL_H_FLIP; break; case DRAW_SPRITE_VH_FLIP: lflip = AGL_V_FLIP | AGL_H_FLIP; break; } switch (mode) { case DRAW_SPRITE_NORMAL: do_masked_blit_screen(sprite, bmp, 0, 0, x, y, sprite->w, sprite->h, lflip, AGL_NO_ROTATION); break; case DRAW_SPRITE_TRANS: if (lflip) { glGetIntegerv(GL_MATRIX_MODE, &matrix_mode); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glTranslatef(x, y, 0.f); glScalef((lflip&AGL_H_FLIP) ? -1 : 1, (lflip&AGL_V_FLIP)? -1 : 1, 1); glTranslatef(-x, -y, 0); glTranslatef((lflip&AGL_H_FLIP) ? -sprite->w : 0, (lflip&AGL_V_FLIP) ? -sprite->h : 0, 0); } allegro_gl_screen_draw_trans_rgba_sprite(bmp, sprite, x, y); if (lflip) { glPopMatrix(); glMatrixMode(matrix_mode); } break; case DRAW_SPRITE_LIT: /* unsupported */ break; } } void allegro_gl_screen_draw_glyph_ex(struct BITMAP *bmp, AL_CONST struct FONT_GLYPH *glyph, int x, int y, int color, int bg, int flip) { GLubyte r, g, b, a; int x_offs = 0; int i; AGL_LOG(2, "glvtable.c:allegro_gl_screen_draw_glyph_ex\n"); if (bmp->clip) { glPushAttrib(GL_SCISSOR_BIT); glEnable(GL_SCISSOR_TEST); glScissor(bmp->x_ofs + bmp->cl, bmp->h + bmp->y_ofs - bmp->cb, bmp->cr - bmp->cl, bmp->cb - bmp->ct); if (x < bmp->cl) { x_offs -= x - bmp->cl; x = bmp->cl; } } if (is_sub_bitmap(bmp)) { x += bmp->x_ofs; y += bmp->y_ofs; } if (bg != -1) { split_color(bg, &r, &g, &b, &a, bitmap_color_depth(bmp)); glColor4ub(r, g, b, a); glRecti(x, y, x + glyph->w, y + glyph->h); } split_color(color, &r, &g, &b, &a, bitmap_color_depth(bmp)); glColor4ub(r, g, b, a); glRasterPos2i(x, y); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); if (flip) { for (i = 0; i < glyph->h; i++) { glBitmap(glyph->w, 1, x_offs, i, 0, 2, glyph->dat + i * ((glyph->w + 7) / 8)); } } else { for (i = 0; i < glyph->h; i++) { glBitmap(glyph->w, 1, x_offs, i, 0, 0, glyph->dat + i * ((glyph->w + 7) / 8)); } } if (bmp->clip) { glPopAttrib(); } return; } static void allegro_gl_screen_draw_glyph(struct BITMAP *bmp, AL_CONST struct FONT_GLYPH *glyph, int x, int y, int color, int bg) { allegro_gl_screen_draw_glyph_ex(bmp, glyph, x, y, color, bg, 0); } void allegro_gl_screen_draw_color_glyph_ex(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y, int color, int bg, int flip) { /* Implementation note: we should try building textures and see how well * those work instead of of DrawPixels with a weird I_TO_RGBA mapping. */ static GLfloat red_map[256]; static GLfloat green_map[256]; static GLfloat blue_map[256]; static GLfloat alpha_map[256]; GLubyte r, g, b, a; int i; GLint saved_row_length; GLint width, height; int sprite_x = 0, sprite_y = 0; void *data; int *table; width = sprite->w; height = sprite->h; if (bmp->clip) { if ((x >= bmp->cr) || (y >= bmp->cb) || (x + width < bmp->cl) || (y + height < bmp->ct)) { return; } if (x < bmp->cl) { width += x - bmp->cl; sprite_x -= (x - bmp->cl); x = bmp->cl; } if (y < bmp->ct) { height += y - bmp->ct; sprite_y -= (y - bmp->ct); y = bmp->ct; } if (x + width > bmp->cr) { width = bmp->cr - x; } if (y + height > bmp->cb) { height = bmp->cb - y; } } if (is_sub_bitmap(bmp)) { x += bmp->x_ofs; y += bmp->y_ofs; } data = sprite->line[sprite_y] + sprite_x * BYTES_PER_PIXEL(bitmap_color_depth(sprite)); if (bg < 0) { glAlphaFunc(GL_GREATER, 0.0f); glEnable(GL_ALPHA_TEST); alpha_map[0] = 0.; } else { split_color(bg, &r, &g, &b, &a, bitmap_color_depth(bmp)); red_map[0] = r / 255.; green_map[0] = g / 255.; blue_map[0] = b / 255.; alpha_map[0] = 1.; } if (color < 0) { table = _palette_expansion_table(bitmap_color_depth(bmp)); for(i = 1; i < 255; i++) { split_color(table[i], &r, &g, &b, &a, bitmap_color_depth(bmp)); red_map[i] = r / 255.; green_map[i] = g / 255.; blue_map[i] = b / 255.; alpha_map[i] = 1.; } } else { split_color(color, &r, &g, &b, &a, bitmap_color_depth(bmp)); for(i = 1; i < 255; i++) { red_map[i] = r / 255.; green_map[i] = g / 255.; blue_map[i] = b / 255.; alpha_map[i] = 1.; } } glPixelMapfv(GL_PIXEL_MAP_I_TO_R, 256, red_map); glPixelMapfv(GL_PIXEL_MAP_I_TO_G, 256, green_map); glPixelMapfv(GL_PIXEL_MAP_I_TO_B, 256, blue_map); glPixelMapfv(GL_PIXEL_MAP_I_TO_A, 256, alpha_map); glRasterPos2i(x, y); glPushAttrib(GL_PIXEL_MODE_BIT); glGetIntegerv(GL_UNPACK_ROW_LENGTH, &saved_row_length); glPixelZoom(1.0, flip ? -1.0 : 1.0); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glPixelStorei(GL_UNPACK_ROW_LENGTH, sprite->w); glPixelTransferi(GL_MAP_COLOR, GL_TRUE); glDrawPixels(width, height, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, data); glPixelStorei(GL_UNPACK_ROW_LENGTH, saved_row_length); glPopAttrib(); if (bg < 0) { glDisable(GL_ALPHA_TEST); } return; } static void allegro_gl_screen_draw_color_glyph(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y, int color, int bg) { allegro_gl_screen_draw_color_glyph_ex(bmp, sprite, x, y, color, bg, 1); } static void allegro_gl_screen_draw_character(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y, int color, int bg) { AGL_LOG(2, "glvtable.c:allegro_gl_screen_draw_character\n"); allegro_gl_screen_draw_color_glyph(bmp, sprite, x, y, color, bg); } static void allegro_gl_screen_draw_256_sprite(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y) { AGL_LOG(2, "glvtable.c:allegro_gl_screen_draw_256_sprite\n"); allegro_gl_screen_draw_color_glyph(bmp, sprite, x, y, -1, -1); } void allegro_gl_screen_clear_to_color(struct BITMAP *bmp, int color) { if (__agl_drawing_pattern_tex || bmp->clip) { allegro_gl_screen_rectfill(bmp, 0, 0, bmp->w, bmp->h, color); } else { GLubyte r, g, b, a; GLfloat old_col[4]; split_color(color, &r, &g, &b, &a, bitmap_color_depth(bmp)); glGetFloatv(GL_COLOR_CLEAR_VALUE, old_col); glClearColor(((float) r / 255), ((float) g / 255), ((float) b / 255), ((float) a / 255)); glClear(GL_COLOR_BUFFER_BIT); glClearColor(old_col[0], old_col[1], old_col[2], old_col[3]); } return; } /* TODO: Handle concave and self-intersecting. */ static void allegro_gl_screen_polygon(struct BITMAP *bmp, int vertices, AL_CONST int *points, int color) { GLubyte r, g, b, a; int i; split_color(color, &r, &g, &b, &a, bitmap_color_depth(bmp)); glColor4ub(r, g, b, a); glPushAttrib(GL_SCISSOR_BIT); if (bmp->clip) { glEnable(GL_SCISSOR_TEST); glScissor(bmp->x_ofs + bmp->cl, bmp->h + bmp->y_ofs - bmp->cb, bmp->cr - bmp->cl, bmp->cb - bmp->ct); } else { glScissor(0, 0, bmp->w, bmp->h); } glBegin(GL_POLYGON); for (i = 0; i < vertices*2-1; i+=2) { SET_TEX_COORDS(points[i], points[i+1]); if (is_sub_bitmap(bmp)) { glVertex2f(points[i] + bmp->x_ofs, points[i+1] + bmp->y_ofs); } else { glVertex2f(points[i], points[i+1]); } } glEnd(); glPopAttrib(); } static void allegro_gl_screen_rect(struct BITMAP *bmp, int x1, int y1, int x2, int y2, int color) { GLubyte r, g, b, a; split_color(color, &r, &g, &b, &a, bitmap_color_depth(bmp)); glColor4ub(r, g, b, a); glPushAttrib(GL_SCISSOR_BIT); if (bmp->clip) { glEnable(GL_SCISSOR_TEST); glScissor(bmp->x_ofs + bmp->cl, bmp->h + bmp->y_ofs - bmp->cb, bmp->cr - bmp->cl, bmp->cb - bmp->ct); } else { glScissor(0, 0, bmp->w, bmp->h); } if (is_sub_bitmap(bmp)) { x1 += bmp->x_ofs; x2 += bmp->x_ofs; y1 += bmp->y_ofs; y2 += bmp->y_ofs; } glBegin(GL_LINE_STRIP); glVertex2f(x1, y1); glVertex2f(x2, y1); glVertex2f(x2, y2); glVertex2f(x1, y2); glVertex2f(x1, y1); glEnd(); glPopAttrib(); } void allegro_gl_screen_polygon3d_f(struct BITMAP *bmp, int type, struct BITMAP *texture, int vc, V3D_f *vtx[]) { int i; int use_z = FALSE; if (type & POLYTYPE_ZBUF) { use_z = TRUE; type &= ~POLYTYPE_ZBUF; } if (type == POLYTYPE_PTEX || type == POLYTYPE_PTEX_TRANS) use_z = TRUE; if (bmp->clip) { glPushAttrib(GL_SCISSOR_BIT); glEnable(GL_SCISSOR_TEST); glScissor(bmp->x_ofs + bmp->cl, bmp->h + bmp->y_ofs - bmp->cb, bmp->cr - bmp->cl, bmp->cb - bmp->ct); } if (is_sub_bitmap(bmp)) { for (i = 0; i < vc*2-1; i+=2) { vtx[i] += bmp->x_ofs; vtx[i+1] += bmp->y_ofs; } } if (use_z) { glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LESS); glDepthMask(GL_TRUE); } glColor4ub(255, 255, 255, 255); if (type == POLYTYPE_ATEX || type == POLYTYPE_PTEX || type == POLYTYPE_ATEX_TRANS || type == POLYTYPE_PTEX_TRANS) { drawing_mode(DRAW_MODE_COPY_PATTERN, texture, 0, 0); } if (type == POLYTYPE_ATEX_TRANS || type == POLYTYPE_PTEX_TRANS) { glEnable(GL_BLEND); } glBegin(GL_POLYGON); for (i = 0; i < vc; i++) { if (type == POLYTYPE_FLAT) glColor3ub(getr(vtx[0]->c), getg(vtx[0]->c), getb(vtx[0]->c)); else if (type == POLYTYPE_GRGB) glColor3ub(getr24(vtx[i]->c), getg24(vtx[i]->c), getb24(vtx[i]->c)); else if (type == POLYTYPE_GCOL) glColor3ub(getr(vtx[i]->c), getg(vtx[i]->c), getb(vtx[i]->c)); else if (type == POLYTYPE_ATEX || type == POLYTYPE_PTEX || type == POLYTYPE_ATEX_TRANS || type == POLYTYPE_PTEX_TRANS) { SET_TEX_COORDS(vtx[i]->u, vtx[i]->v); } if (use_z) glVertex3f(vtx[i]->x, vtx[i]->y, 1.f / vtx[i]->z); else glVertex2f(vtx[i]->x, vtx[i]->y); } glEnd(); if (bmp->clip) glPopAttrib(); if (use_z) { glDisable(GL_DEPTH_TEST); glDepthMask(GL_FALSE); } if (type == POLYTYPE_ATEX || type == POLYTYPE_PTEX || type == POLYTYPE_ATEX_TRANS || type == POLYTYPE_PTEX_TRANS) { solid_mode(); } if (type == POLYTYPE_ATEX_TRANS || type == POLYTYPE_PTEX_TRANS) glDisable(GL_BLEND); } static void allegro_gl_screen_polygon3d(struct BITMAP *bmp, int type, struct BITMAP *texture, int vc, V3D *vtx[]) { int i; V3D_f **vtx_f = malloc(vc * sizeof(struct V3D_f*)); if (!vtx_f) return; for (i = 0; i < vc; i++) { vtx_f[i] = malloc(sizeof(struct V3D_f)); if (!vtx_f[i]) { int k; for (k = 0; k < i; k++) free(vtx_f[k]); free(vtx_f); return; } vtx_f[i]->c = vtx[i]->c; vtx_f[i]->u = fixtof(vtx[i]->u); vtx_f[i]->v = fixtof(vtx[i]->v); vtx_f[i]->x = fixtof(vtx[i]->x); vtx_f[i]->y = fixtof(vtx[i]->y); vtx_f[i]->z = fixtof(vtx[i]->z); } allegro_gl_screen_polygon3d_f(bmp, type, texture, vc, vtx_f); for (i = 0; i < vc; i++) free(vtx_f[i]); free(vtx_f); } static void allegro_gl_screen_quad3d_f(struct BITMAP *bmp, int type, struct BITMAP *texture, V3D_f *v1, V3D_f *v2, V3D_f *v3, V3D_f *v4) { V3D_f *vtx_f[4]; vtx_f[0] = v1; vtx_f[1] = v2; vtx_f[2] = v3; vtx_f[3] = v4; allegro_gl_screen_polygon3d_f(bmp, type, texture, 4, vtx_f); } static void allegro_gl_screen_quad3d(struct BITMAP *bmp, int type, struct BITMAP *texture, V3D *v1, V3D *v2, V3D *v3, V3D *v4) { V3D *vtx[4]; vtx[0] = v1; vtx[1] = v2; vtx[2] = v3; vtx[3] = v4; allegro_gl_screen_polygon3d(bmp, type, texture, 4, vtx); } static void allegro_gl_screen_triangle3d(struct BITMAP *bmp, int type, struct BITMAP *texture, V3D *v1, V3D *v2, V3D *v3) { V3D *vtx[3]; vtx[0] = v1; vtx[1] = v2; vtx[2] = v3; allegro_gl_screen_polygon3d(bmp, type, texture, 3, vtx); } static void allegro_gl_screen_triangle3d_f(struct BITMAP *bmp, int type, struct BITMAP *texture, V3D_f *v1, V3D_f *v2, V3D_f *v3) { V3D_f *vtx_f[3]; vtx_f[0] = v1; vtx_f[1] = v2; vtx_f[2] = v3; allegro_gl_screen_polygon3d_f(bmp, type, texture, 3, vtx_f); } void __allegro_gl__glvtable_update_vtable(GFX_VTABLE ** vtable) { int maskcolor = (*vtable)->mask_color; int depth = (*vtable)->color_depth; AGL_LOG(2, "glvtable.c:__allegro_gl__glvtable_update_vtable\n"); allegro_gl_screen_vtable.color_depth = depth; /* makecol_depth is used below instead of the MASK_COLOR_x constants * because we may have changed the RGB shift values in order to * use the packed pixels extension */ allegro_gl_screen_vtable.mask_color = makecol_depth(depth, getr(maskcolor), getg(maskcolor), getb(maskcolor)); *vtable = &allegro_gl_screen_vtable; __allegro_gl_driver->screen_masked_blit = screen_masked_blit_standard; if (allegro_gl_extensions_GL.NV_register_combiners) { __allegro_gl_driver->screen_masked_blit = screen_masked_blit_nv_register; } else if (allegro_gl_info.num_texture_units >= 3) { __allegro_gl_driver->screen_masked_blit = screen_masked_blit_combine_tex; } } /* Saved projection matrix */ static double allegro_gl_projection_matrix[16]; static double allegro_gl_modelview_matrix[16]; /** \ingroup allegro * Prepares for Allegro drawing to the screen. * * Since AllegroGL actually calls OpenGL commands to perform Allegro functions * for 2D drawing, some OpenGL capabilities may interfer with those operations * In order to obtain the expected results, allegro_gl_set_allegro_mode() must * be called to disable the depth test, texturing, fog and lighting and set * the view matrices to an appropriate state. Call * allegro_gl_unset_allegro_mode() to restore OpenGL in its previous state. * * You should encapsulate all Allegro code dealing with the screen in * between allegro_gl_set_allegro_mode() and allegro_gl_unset_allegro_mode(). * * If you need to use regular OpenGL commands in between, you may do so, * but you can get unexpected results. This is generally not recommended. * You should first call allegro_gl_unset_allegro_mode() to restore the * original OpenGL matrices. After that, you may freely call any OpenGL * command. Don't forget to call back allegro_gl_set_allegro_mode() to switch * back to Allegro commands. * * AllegroGL saves the current OpenGL state with glPushAttrib so you should * make sure that at least one level is available in the attribute stack * otherwise the next call to allegro_gl_unset_allegro_mode() may fail. * * Also note that allegro_gl_set_allegro_mode() implicitely calls * allegro_gl_set_projection() so you do not need to do it yourself. * * \sa allegro_gl_unset_allegro_mode() allegro_gl_set_projection() * \sa allegro_gl_unset_projection() */ void allegro_gl_set_allegro_mode(void) { AGL_LOG(2, "glvtable.c:allegro_gl_set_allegro_mode\n"); /* Save the OpenGL state then set it up */ glPushAttrib(GL_ENABLE_BIT | GL_TEXTURE_BIT | GL_TRANSFORM_BIT | GL_POINT_BIT | GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glDisable(GL_DEPTH_TEST); glDisable(GL_CULL_FACE); glDisable(GL_FOG); glDisable(GL_LIGHTING); glDisable(GL_BLEND); glDisable(GL_ALPHA_TEST); glDepthMask(GL_FALSE); glEnable(GL_TEXTURE_2D); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); glPointSize(1.); /* Create pool texture */ if (!__allegro_gl_pool_texture) { glGenTextures(1, &__allegro_gl_pool_texture); } glBindTexture(GL_TEXTURE_2D, __allegro_gl_pool_texture); /* Create a texture without defining the data */ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glBindTexture(GL_TEXTURE_2D, 0); allegro_gl_set_projection(); /* For some reason, ATI Rage Pro isn't able to draw correctly without a * texture bound. So we bind a dummy 1x1 texture to work around the issue. */ if (allegro_gl_info.is_ati_rage_pro) { if (!__allegro_gl_dummy_texture) { GLubyte tex[4] = {255, 255, 255, 255}; glGenTextures(1, &__allegro_gl_dummy_texture); glBindTexture(GL_TEXTURE_2D, __allegro_gl_dummy_texture); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, tex); } glBindTexture(GL_TEXTURE_2D, __allegro_gl_dummy_texture); } #ifdef ALLEGRO_MACOSX /* MacOSX 10.2.x has a bug: glRasterPos causes a crash (it is used in *'blit'). This stops it happening. */ glBegin(GL_POINTS); glEnd(); #endif } /** \ingroup allegro * Restores previous OpenGL settings. * * Restores the OpenGL state that have saved during the last call of * allegro_gl_set_allegro_mode(). * * Note that allegro_gl_unset_allegro_mode implicitely calls * allegro_gl_unset_projection() so you do not need to do it yourself. * * \sa allegro_gl_set_allegro_mode() allegro_gl_set_projection() * \sa allegro_gl_unset_projection() */ void allegro_gl_unset_allegro_mode(void) { AGL_LOG(2, "glvtable.c:allegro_gl_unset_allegro_mode\n"); switch(allegro_gl_display_info.vidmem_policy) { case AGL_KEEP: break; case AGL_RELEASE: if (__allegro_gl_pool_texture) { glDeleteTextures(1, &__allegro_gl_pool_texture); __allegro_gl_pool_texture = 0; } break; } allegro_gl_unset_projection(); glPopAttrib(); } /** \ingroup allegro * Prepares for Allegro drawing to the screen. * * This function sets the OpenGL projection and modelview matrices so * that 2D OpenGL coordinates match the usual Allegro coordinate system. * * OpenGL uses a completely different coordinate system than Allegro. So * to be able to use Allegro operations on the screen, you first need * to properly set up the OpenGL projection and modelview matrices. * AllegroGL provides this set of functions to allow proper alignment of * OpenGL coordinates with their Allegro counterparts. * * Since AllegroGL actually calls OpenGL commands to perform Allegro functions * for 2D drawing, some OpenGL capabilities such as texturing or depth testing * may interfer with those operations. In order to prevent such inconveniences, * you should call allegro_gl_set_allegro_mode() instead of * allegro_gl_set_projection() * * allegro_gl_set_projection() and allegro_gl_unset_projection() are not * nestable, which means that you should not call allegro_gl_set_projection() * inside another allegro_gl_set_projection() block. Similarly for * allegro_gl_unset_projection(). * * Have a look at examp/exalleg.c for an example of * combining Allegro drawing commands and OpenGL. * * \sa allegro_gl_unset_projection() allegro_gl_set_allegro_mode() * \sa allegro_gl_unset_allegro_mode() */ void allegro_gl_set_projection(void) { GLint v[4]; AGL_LOG(2, "glvtable.c:allegro_gl_set_projection\n"); /* Setup OpenGL matrices */ glGetIntegerv(GL_VIEWPORT, &v[0]); glMatrixMode(GL_MODELVIEW); glGetDoublev(GL_MODELVIEW_MATRIX, allegro_gl_modelview_matrix); glLoadIdentity(); glMatrixMode(GL_PROJECTION); glGetDoublev(GL_PROJECTION_MATRIX, allegro_gl_projection_matrix); glLoadIdentity(); gluOrtho2D(v[0] - 0.325, v[0] + v[2] - 0.325, v[1] + v[3] - 0.325, v[1] - 0.325); } /** \ingroup allegro * Restores previously saved projection. * * This function returns the projection and modelview matrices to their * state before the last allegro_gl_set_projection() was called. * * \sa allegro_gl_set_projection() allegro_gl_set_allegro_mode() * \sa allegro_gl_unset_allegro_mode() */ void allegro_gl_unset_projection(void) { AGL_LOG(2, "glvtable.c:allegro_gl_unset_projection\n"); glMatrixMode(GL_PROJECTION); glLoadMatrixd(allegro_gl_projection_matrix); glMatrixMode(GL_MODELVIEW); glLoadMatrixd(allegro_gl_modelview_matrix); } void allegro_gl_memory_blit_between_formats(struct BITMAP *src, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height) { AGL_LOG(2, "AGL::blit_between_formats\n"); /* screen -> memory */ if (is_screen_bitmap(src)) { allegro_gl_screen_blit_to_memory(src, dest, source_x, source_y, dest_x, dest_y, width, height); return; } /* video -> memory */ if (is_video_bitmap(src)) { allegro_gl_video_blit_to_memory(src, dest, source_x, source_y, dest_x, dest_y, width, height); return; } /* memory -> screen */ if (is_screen_bitmap(dest)) { allegro_gl_screen_blit_from_memory(src, dest, source_x, source_y, dest_x, dest_y, width, height); return; } /* memory -> video */ if (is_video_bitmap(dest)) { allegro_gl_video_blit_from_memory(src, dest, source_x, source_y, dest_x, dest_y, width, height); return; } switch(bitmap_color_depth(dest)) { #ifdef ALLEGRO_COLOR8 case 8: __blit_between_formats8(src, dest, source_x, source_y, dest_x, dest_y, width, height); return; #endif #ifdef ALLEGRO_COLOR16 case 15: __blit_between_formats15(src, dest, source_x, source_y, dest_x, dest_y, width, height); return; case 16: __blit_between_formats16(src, dest, source_x, source_y, dest_x, dest_y, width, height); return; #endif #ifdef ALLEGRO_COLOR24 case 24: __blit_between_formats24(src, dest, source_x, source_y, dest_x, dest_y, width, height); return; #endif #ifdef ALLEGRO_COLOR32 case 32: __blit_between_formats32(src, dest, source_x, source_y, dest_x, dest_y, width, height); return; #endif default: TRACE("--== ERROR ==-- AGL::blit_between_formats : %i -> %i bpp\n", bitmap_color_depth(src), bitmap_color_depth(dest)); return; } } static void dummy_unwrite_bank(void) { } static GFX_VTABLE allegro_gl_screen_vtable = { 0, 0, dummy_unwrite_bank, //void *unwrite_bank; NULL, //AL_METHOD(void, set_clip, (struct BITMAP *bmp)); allegro_gl_screen_acquire, allegro_gl_screen_release, NULL, //AL_METHOD(struct BITMAP *, create_sub_bitmap, (struct BITMAP *parent, int x, int y, int width, int height)); NULL, //AL_METHOD(void, created_sub_bitmap, (struct BITMAP *bmp, struct BITMAP *parent)); allegro_gl_screen_getpixel, allegro_gl_screen_putpixel, allegro_gl_screen_vline, allegro_gl_screen_hline, allegro_gl_screen_hline, allegro_gl_screen_line, allegro_gl_screen_line, allegro_gl_screen_rectfill, allegro_gl_screen_triangle, allegro_gl_screen_draw_sprite, allegro_gl_screen_draw_256_sprite, allegro_gl_screen_draw_sprite_v_flip, allegro_gl_screen_draw_sprite_h_flip, allegro_gl_screen_draw_sprite_vh_flip, allegro_gl_screen_draw_trans_rgba_sprite, allegro_gl_screen_draw_trans_rgba_sprite, NULL, //AL_METHOD(void, draw_lit_sprite, (struct BITMAP *bmp, struct BITMAP *sprite, int x, int y, int color)); allegro_gl_screen_draw_rle_sprite, allegro_gl_screen_draw_trans_rgba_rle_sprite, allegro_gl_screen_draw_trans_rgba_rle_sprite, NULL, //AL_METHOD(void, draw_lit_rle_sprite, (struct BITMAP *bmp, struct RLE_SPRITE *sprite, int x, int y, int color)); allegro_gl_screen_draw_character, allegro_gl_screen_draw_glyph, allegro_gl_screen_blit_from_memory, allegro_gl_screen_blit_to_memory, NULL, //AL_METHOD(void, blit_from_system, (struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); NULL, //AL_METHOD(void, blit_to_system, (struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); allegro_gl_screen_blit_to_self, allegro_gl_screen_blit_to_self, /* ..._forward */ allegro_gl_screen_blit_to_self, /* ..._backward */ allegro_gl_memory_blit_between_formats, allegro_gl_screen_masked_blit, allegro_gl_screen_clear_to_color, allegro_gl_screen_pivot_scaled_sprite_flip, NULL, //AL_METHOD(void, do_stretch_blit, (struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int source_width, int source_height, int dest_x, int dest_y, int dest_width, int dest_height, int masked)); NULL, //AL_METHOD(void, draw_gouraud_sprite, (struct BITMAP *bmp, struct BITMAP *sprite, int x, int y, int c1, int c2, int c3, int c4)); NULL, //AL_METHOD(void, draw_sprite_end, (void)); NULL, //AL_METHOD(void, blit_end, (void)); allegro_gl_screen_polygon, allegro_gl_screen_rect, _soft_circle, //AL_METHOD(void, circle, (struct BITMAP *bmp, int x, int y, int radius, int color)); _soft_circlefill, //AL_METHOD(void, circlefill, (struct BITMAP *bmp, int x, int y, int radius, int color)); _soft_ellipse, //AL_METHOD(void, ellipse, (struct BITMAP *bmp, int x, int y, int rx, int ry, int color)); _soft_ellipsefill, //AL_METHOD(void, ellipsefill, (struct BITMAP *bmp, int x, int y, int rx, int ry, int color)); _soft_arc, //AL_METHOD(void, arc, (struct BITMAP *bmp, int x, int y, fixed ang1, fixed ang2, int r, int color)); _soft_spline, //AL_METHOD(void, spline, (struct BITMAP *bmp, AL_CONST int points[8], int color)); _soft_floodfill, //AL_METHOD(void, floodfill, (struct BITMAP *bmp, int x, int y, int color)); allegro_gl_screen_polygon3d, allegro_gl_screen_polygon3d_f, allegro_gl_screen_triangle3d, allegro_gl_screen_triangle3d_f, allegro_gl_screen_quad3d, allegro_gl_screen_quad3d_f, allegro_gl_screen_draw_sprite_ex }; /** \} */ allegro4.4-4.4.2/addons/allegrogl/src/gui.c000066400000000000000000000445701173507505700203570ustar00rootroot00000000000000/* This code is (C) AllegroGL contributors, and double licensed under * the GPL and zlib licenses. See gpl.txt or zlib.txt for details. */ /** \file gui.c * \brief AllegroGL GUI wrappers * * These are replacements for Allegro's do_dialog routine and * standard dialogs (to use our version of the routine). */ #include "alleggl.h" #include "allglint.h" #include static struct { GLuint texture; int hidden; int xfocus; int yfocus; int width; int height; } allegro_gl_mouse = { 0, TRUE, 0, 0, 0, 0}; /** * \ingroup gui * \brief AllegroGL-friendly version of do_dialog * * This behaves exactly like do_dialog but forces a screen clear, * rerender, and flip, after each iteration of update_dialog. * * User gui components can do OpenGL or Allegro rendering to draw * themselves. They should take care not to alter any OpenGL state * (or be aware that this will affect other components). For the * main render, they will be called in order, but this is not * guarranteed at other times -- they may be called out of order; * however the results will never be visible, so just don't crash. * * Before drawing the final (in-order) pass, the color and depth buffers will * be cleared -- set your clear color to black or green or whatever you like. * You can overdraw it with an object of course. * * Further notes: This routine uses allegro_gl_set_allegro_mode(), so * your GUI components can use allegro_gl_unset_allegro_mode() to restore * the old state while they draw themselves, provided that they use * allegro_gl_set_allegro_mode() again afterwards. * * \param dialog an array of dialog objects terminated by one with a NULL * dialog procedure. * \param focus_obj index of the object on which the focus is set (-1 if you * don't want anything to have the focus * * \sa algl_draw_mouse */ int algl_do_dialog (DIALOG *dialog, int focus_obj) { DIALOG_PLAYER *player; AGL_LOG(2, "allegro_gl_do_dialog\n"); /* Allegro GUI routines generally use the 2D gfx functions therefore we set default behaviour to allegro_gl_set_allegro_mode so that we can use the GUI functions "as is" */ allegro_gl_set_allegro_mode(); player = init_dialog (dialog, focus_obj); show_mouse(screen); /* Nothing to do here. * Redrawing is done from d_algl_viewport_proc() callback. */ while (update_dialog (player)) {} show_mouse(NULL); /* restore previous projection matrices */ allegro_gl_unset_allegro_mode(); return shutdown_dialog (player); } /** * \ingroup gui * \brief AllegroGL-friendly version of popup_dialog * * This routine is likely to be very slow. It has to take a copy of the * screen on entry, then where algl_do_dialog() would just clear the screen, * this routine has to blit that copy back again after clearing. This is * the only way to do overlays without knowing what type of flipping is * going on. * * Also, note that we don't save the depth buffer or anything like that so * don't go around thinking that algl_popup_dialog won't affect anything * when it's gone. * * So, unless you need overlays, it's recommended that you just use * algl_do_dialog(), and if you do need overlays, it's recommended that you * just use algl_do_dialog() and redraw the thing you're overlaying yourself. * If you're lazy or that's impossible, use this routine... * * \param dialog an array of dialog objects terminated by one with a NULL * dialog procedure. * \param focus_obj index of the object on which the focus is set (-1 if you * don't want anything to have the focus * * \sa algl_do_dialog, algl_draw_mouse */ int algl_popup_dialog (DIALOG *dialog, int focus_obj) { void *backdrop; DIALOG_PLAYER *player; GLint read_buffer; AGL_LOG(2, "allegro_gl_popup_dialog\n"); /* Allegro GUI routines generally use the 2D gfx functions therefore we set default behaviour to allegro_gl_set_allegro_mode so that we can use the GUI functions "as is" */ allegro_gl_set_allegro_mode(); glGetIntegerv(GL_READ_BUFFER, &read_buffer); glReadBuffer (GL_FRONT); /* TODO: don't clobber */ glDisable(GL_DEPTH_TEST); backdrop = malloc (SCREEN_W * SCREEN_H * 3 * 4); glReadPixels (0, 0, SCREEN_W, SCREEN_H, GL_RGB, GL_UNSIGNED_BYTE, backdrop); glReadBuffer(read_buffer); player = init_dialog (dialog, focus_obj); show_mouse(screen); while (update_dialog (player)) { /* Redraw the GUI every frame */ glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glRasterPos2f (0., SCREEN_H-.5); /* TODO: don't clobber */ glDrawPixels (SCREEN_W, SCREEN_H, GL_RGB, GL_UNSIGNED_BYTE, backdrop); broadcast_dialog_message (MSG_DRAW, 0); /* Draw the mouse cursor */ algl_draw_mouse(); /* Flip buffers */ allegro_gl_flip(); } glRasterPos2f (0., SCREEN_H-.5); /* TODO: don't clobber */ glDrawPixels (SCREEN_W, SCREEN_H, GL_RGB, GL_UNSIGNED_BYTE, backdrop); glEnable(GL_DEPTH_TEST); free (backdrop); show_mouse(NULL); /* restore previous projection matrices */ allegro_gl_unset_allegro_mode(); return shutdown_dialog (player); } /* User mouse drawing callback */ static void (*__algl_user_draw_mouse)(void) = NULL; /** * \ingroup gui * \brief Draws a mouse pointer on the screen * * This function draws a mouse pointer on the screen. By default, it displays * Allegro's standard black arrow cursor. However the settings of the cursor * can be altered by Allegro's functions for mouse cursor management like * show_mouse, set_mouse_sprite, scare_mouse, and so on... As a consequence, * it should be stressed that if show_mouse(NULL) is called then * algl_draw_mouse() won't draw anything. * * Unlike Allegro, AllegroGL does not manage the mouse cursor with an * interrupt routine, hence algl_draw_mouse() must be regularly called * in order to display the mouse cursor (ideally it should be the last function * called before allegro_gl_flip()). However if you use algl_do_dialog() * then you do not need to make explicit calls to algl_draw_mouse() since * algl_do_dialog() takes care of that for you. * * \sa algl_set_mouse_drawer */ void algl_draw_mouse (void) { AGL_LOG(2, "allegro_gl_draw_mouse\n"); /* don't draw the mouse if it's not in our window */ if (!_mouse_on || allegro_gl_mouse.hidden) return; if (__algl_user_draw_mouse) { __algl_user_draw_mouse(); } else { #if 0 float x = mouse_x; float y = mouse_y; int depth_enabled = glIsEnabled (GL_DEPTH_TEST); int cull_enabled = glIsEnabled (GL_CULL_FACE); if (depth_enabled) glDisable (GL_DEPTH_TEST); if (cull_enabled) glDisable (GL_CULL_FACE); glBegin (GL_TRIANGLES); #define draw(dx,dy) \ glVertex2f (x + dx, y + dy); \ glVertex2f (x + dx, y + dy + 10); \ glVertex2f (x + dx + 7, y + dy + 7); \ glVertex2f (x + dx + 1.5, y + dy + 6); \ glVertex2f (x + dx + 5.5, y + dy + 14); \ glVertex2f (x + dx + 7.5, y + dy + 14); \ glVertex2f (x + dx + 3.5, y + dy + 6); \ glVertex2f (x + dx + 1.5, y + dy + 6); \ glVertex2f (x + dx + 7.5, y + dy + 14); glColor3f (0, 0, 0); draw(-1,0) draw(1,0) draw(0,-1) draw(0,1) glColor3f (1, 1, 1); draw(0,0) #undef draw glEnd(); if (depth_enabled) glEnable (GL_DEPTH_TEST); if (cull_enabled) glEnable (GL_CULL_FACE); #endif int x = mouse_x - allegro_gl_mouse.xfocus; int y = mouse_y - allegro_gl_mouse.yfocus; glPushAttrib(GL_COLOR_BUFFER_BIT); glAlphaFunc(GL_GREATER, 0.5); glEnable(GL_TEXTURE_2D); glEnable(GL_ALPHA_TEST); glBindTexture(GL_TEXTURE_2D, allegro_gl_mouse.texture); glColor4f(1., 1., 1., 1.); glTranslatef(-0.375, -0.375, 0); glBegin(GL_QUADS); glTexCoord2f(0., 1.); glVertex2f(x, y); glTexCoord2f(0., 0.); glVertex2f(x, y + allegro_gl_mouse.height); glTexCoord2f(1., 0.); glVertex2f(x + allegro_gl_mouse.width, y + allegro_gl_mouse.height); glTexCoord2f(1., 1.); glVertex2f(x + allegro_gl_mouse.width, y); glEnd(); glTranslatef(0.375, 0.375, 0); glPopAttrib(); glBindTexture(GL_TEXTURE_2D, 0); glDisable(GL_TEXTURE_2D); } } /** * \ingroup gui * \brief Sets (or clears) a user mouse drawing callback * * This function allows to use a user-defined routine to display the mouse * cursor. This allows nice effects like a spinning cube or any fancy thing * you can think of to be used as a mouse cursor. * * When a user mouse drawing callback is enabled, set_mouse_sprite has no effect. * However show_mouse and scare_mouse are still enabled. * * \param user_draw_mouse user routine that displays the mouse cursor (NULL if * you want to get back to the standard behaviour) * * \sa algl_draw_mouse */ void algl_set_mouse_drawer (void (*user_draw_mouse)(void)) { AGL_LOG(2, "allegro_gl_set_mouse_drawer\n"); __algl_user_draw_mouse = user_draw_mouse; } static DIALOG alert_dialog[] = { /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) (dp2) (dp3) */ { _gui_shadow_box_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, { _gui_ctext_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, { _gui_ctext_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, { _gui_ctext_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, { _gui_button_proc, 0, 0, 0, 0, 0, 0, 0, D_EXIT, 0, 0, NULL, NULL, NULL }, { _gui_button_proc, 0, 0, 0, 0, 0, 0, 0, D_EXIT, 0, 0, NULL, NULL, NULL }, { _gui_button_proc, 0, 0, 0, 0, 0, 0, 0, D_EXIT, 0, 0, NULL, NULL, NULL }, { d_yield_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } }; #define A_S1 1 #define A_S2 2 #define A_S3 3 #define A_B1 4 #define A_B2 5 #define A_B3 6 /** * \ingroup gui * \brief AllegroGL-friendly version of Allegro's alert3. * * Displays a simple alert box, containing three lines of text (s1-s3), * and with either one, two, or three buttons. The text for these buttons * is passed in b1, b2, and b3 (NULL for buttons which are not used), and * the keyboard shortcuts in c1 and c2. Returns 1, 2, or 3 depending on * which button was selected. */ int algl_alert3(AL_CONST char *s1, AL_CONST char *s2, AL_CONST char *s3, AL_CONST char *b1, AL_CONST char *b2, AL_CONST char *b3, int c1, int c2, int c3) { char tmp[16]; int avg_w, avg_h; int len1, len2, len3; int maxlen = 0; int buttons = 0; int b[3]; int c; AGL_LOG(2, "allegro_gl_alert3\n"); #define SORT_OUT_BUTTON(x) { \ if (b##x) { \ alert_dialog[A_B##x].flags &= ~D_HIDDEN; \ alert_dialog[A_B##x].key = c##x; \ alert_dialog[A_B##x].dp = (char *)b##x; \ len##x = gui_strlen(b##x); \ b[buttons++] = A_B##x; \ } \ else { \ alert_dialog[A_B##x].flags |= D_HIDDEN; \ len##x = 0; \ } \ } usetc(tmp+usetc(tmp, ' '), 0); avg_w = text_length(font, tmp); avg_h = text_height(font); alert_dialog[A_S1].dp = alert_dialog[A_S2].dp = alert_dialog[A_S3].dp = alert_dialog[A_B1].dp = alert_dialog[A_B2].dp = empty_string; if (s1) { alert_dialog[A_S1].dp = (char *)s1; maxlen = text_length(font, s1); } if (s2) { alert_dialog[A_S2].dp = (char *)s2; len1 = text_length(font, s2); if (len1 > maxlen) maxlen = len1; } if (s3) { alert_dialog[A_S3].dp = (char *)s3; len1 = text_length(font, s3); if (len1 > maxlen) maxlen = len1; } SORT_OUT_BUTTON(1); SORT_OUT_BUTTON(2); SORT_OUT_BUTTON(3); len1 = MAX(len1, MAX(len2, len3)) + avg_w*3; if (len1*buttons > maxlen) maxlen = len1*buttons; maxlen += avg_w*4; alert_dialog[0].w = maxlen; alert_dialog[A_S1].x = alert_dialog[A_S2].x = alert_dialog[A_S3].x = alert_dialog[0].x + maxlen/2; alert_dialog[A_B1].w = alert_dialog[A_B2].w = alert_dialog[A_B3].w = len1; alert_dialog[A_B1].x = alert_dialog[A_B2].x = alert_dialog[A_B3].x = alert_dialog[0].x + maxlen/2 - len1/2; if (buttons == 3) { alert_dialog[b[0]].x = alert_dialog[0].x + maxlen/2 - len1*3/2 - avg_w; alert_dialog[b[2]].x = alert_dialog[0].x + maxlen/2 + len1/2 + avg_w; } else if (buttons == 2) { alert_dialog[b[0]].x = alert_dialog[0].x + maxlen/2 - len1 - avg_w; alert_dialog[b[1]].x = alert_dialog[0].x + maxlen/2 + avg_w; } alert_dialog[0].h = avg_h*8; alert_dialog[A_S1].y = alert_dialog[0].y + avg_h; alert_dialog[A_S2].y = alert_dialog[0].y + avg_h*2; alert_dialog[A_S3].y = alert_dialog[0].y + avg_h*3; alert_dialog[A_S1].h = alert_dialog[A_S2].h = alert_dialog[A_S3].h = avg_h; alert_dialog[A_B1].y = alert_dialog[A_B2].y = alert_dialog[A_B3].y = alert_dialog[0].y + avg_h*5; alert_dialog[A_B1].h = alert_dialog[A_B2].h = alert_dialog[A_B3].h = avg_h*2; centre_dialog(alert_dialog); set_dialog_color(alert_dialog, gui_fg_color, gui_bg_color); for (c = 0; alert_dialog[c].proc; c++) if (alert_dialog[c].proc == _gui_ctext_proc) alert_dialog[c].bg = -1; clear_keybuf(); do { } while (gui_mouse_b()); c = algl_popup_dialog(alert_dialog, A_B1); if (c == A_B1) return 1; else if (c == A_B2) return 2; else return 3; } /** * \ingroup gui * \brief AllegroGL-friendly version of Allegro's alert. * * Displays a simple 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. * Returns 1 or 2 depending on which button was selected. */ int algl_alert(AL_CONST char *s1, AL_CONST char *s2, AL_CONST char *s3, AL_CONST char *b1, AL_CONST char *b2, int c1, int c2) { int ret; AGL_LOG(2, "allegro_gl_alert\n"); ret = algl_alert3(s1, s2, s3, b1, b2, NULL, c1, c2, 0); if (ret > 2) ret = 2; return ret; } /** * \ingroup gui * \brief Creates a viewport object where OpenGL commands can be performed. * * The viewport and the scissor are updated so that this GUI object behaves * somewhat like a window. The dp field of the DIALOG object points to a * callback function : int (*callback)(BITMAP* viewport, int msg, int c) where: * viewport is a sub-bitmap of the screen limited to the area of the * DIALOG object. msg and c are the values that come from the GUI manager. * The callback function must return a sensible value to the GUI manager * like D_O_K if everything went right or D_EXIT to close the dialog. */ int d_algl_viewport_proc(int msg, DIALOG *d, int c) { int ret = D_O_K; typedef int (*_callback)(BITMAP*, int, int); _callback callback = (_callback) d->dp; BITMAP *viewport = create_sub_bitmap(screen, d->x, d->y, d->w, d->h); AGL_LOG(3, "d_algl_viewport_proc\n"); if (msg == MSG_DRAW) { /* Draws the background */ clear_to_color(viewport, d->bg); } /* First we get back into a 3D mode */ allegro_gl_unset_allegro_mode(); /* Save the Viewport and Scissor states */ glPushAttrib(GL_SCISSOR_BIT | GL_VIEWPORT_BIT); /* Adapt the viewport to the object size */ glViewport(d->x, SCREEN_H - d->y - d->h, d->w, d->h); glScissor(d->x, SCREEN_H - d->y - d->h, d->w, d->h); glEnable(GL_SCISSOR_TEST); /* Clear the depth buffer for this scissor region */ if (msg == MSG_DRAW) { glClear(GL_DEPTH_BUFFER_BIT); } /* Call the callback function */ if (callback) ret = callback(viewport, msg, c); /* Restore the previous state */ glPopAttrib(); allegro_gl_set_allegro_mode(); destroy_bitmap(viewport); /* Redraw the GUI every frame */ if (msg == MSG_IDLE) { glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); broadcast_dialog_message (MSG_DRAW, 0); /* Draw the mouse cursor */ algl_draw_mouse(); /* Flip buffers */ allegro_gl_flip(); } return ret; } /*****************/ /* Mouse manager */ /*****************/ int allegro_gl_set_mouse_sprite(BITMAP *sprite, int xfocus, int yfocus) { BITMAP *bmp = NULL; GLint old_texture; AGL_LOG(2, "allegro_gl_set_mouse_sprite\n"); glGetIntegerv(GL_TEXTURE_2D_BINDING, &old_texture); bmp = create_bitmap_ex(bitmap_color_depth(sprite), __allegro_gl_make_power_of_2(sprite->w), __allegro_gl_make_power_of_2(sprite->h)); if (allegro_gl_mouse.texture) { glDeleteTextures(1, &allegro_gl_mouse.texture); allegro_gl_mouse.texture = 0; } clear_to_color(bmp, bitmap_mask_color(sprite)); blit(sprite, bmp, 0, 0, 0, 0, sprite->w, sprite->h); #ifdef DEBUGMODE save_bmp("mcursor.bmp",bmp,NULL); #endif allegro_gl_mouse.texture = allegro_gl_make_texture_ex(AGL_TEXTURE_RESCALE | AGL_TEXTURE_MASKED | AGL_TEXTURE_FLIP, bmp, -1); if (!allegro_gl_mouse.texture) { destroy_bitmap(bmp); return -1; } glBindTexture(GL_TEXTURE_2D, allegro_gl_mouse.texture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); if (allegro_gl_extensions_GL.SGIS_texture_edge_clamp) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); } else { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); } glBindTexture(GL_TEXTURE_2D, old_texture); allegro_gl_mouse.width = bmp->w; allegro_gl_mouse.height = bmp->h; allegro_gl_mouse.xfocus = xfocus; allegro_gl_mouse.yfocus = yfocus; destroy_bitmap(bmp); return 0; } int allegro_gl_show_mouse(BITMAP* bmp, int x, int y) { AGL_LOG(3, "allegro_gl_show_mouse\n"); allegro_gl_mouse.hidden = FALSE; return 0; } void allegro_gl_hide_mouse(void) { AGL_LOG(3, "allegro_gl_hide_mouse\n"); allegro_gl_mouse.hidden = TRUE; } void allegro_gl_move_mouse(int x, int y) { AGL_LOG(3, "allegro_gl_move_mouse\n"); /* This function is not called from the main thread, so * we must not call any OpenGL command there !!! */ } allegro4.4-4.4.2/addons/allegrogl/src/macosx.m000066400000000000000000000463661173507505700211040ustar00rootroot00000000000000/* This code is (C) AllegroGL contributors, and double licensed under * the GPL and zlib licenses. See gpl.txt or zlib.txt for details. */ #include #define ALLEGRO_SRC #include #include #include #include "alleggl.h" #include "glvtable.h" #include "allglint.h" #define OSX_GFX_OPENGL 100 #define MAX_ATTRIBUTES 64 #define PREFIX_I "agl-osx INFO: " #define PREFIX_W "agl-osx WARNING: " @interface AllegroGLView: NSOpenGLView - (void)resetCursorRects; - (id) initWithFrame: (NSRect) frame; @end static BITMAP *allegro_gl_macosx_init_windowed(int w, int h, int v_w, int v_h, int color_depth); static BITMAP *allegro_gl_macosx_init_fullscreen(int w, int h, int v_w, int v_h, int color_depth); static void allegro_gl_macosx_exit(struct BITMAP *b); static void macosx_setup_gl(void); static NSOpenGLPixelFormat *init_pixel_format(int windowed); static struct allegro_gl_driver allegro_gl_macosx; static AllegroWindowDelegate *window_delegate = NULL; static NSOpenGLContext *context; static CFDictionaryRef old_mode = NULL; static BITMAP *allegro_gl_screen = NULL; GFX_DRIVER gfx_allegro_gl_windowed = { GFX_OPENGL_WINDOWED, EMPTY_STRING, EMPTY_STRING, "AllegroGL Windowed (MacOS X)", allegro_gl_macosx_init_windowed, allegro_gl_macosx_exit, NULL, /* scrolling not implemented */ NULL, /* vsync, may use for flip? */ NULL, /* No h/w pallete, not using indexed mode */ NULL, NULL, /* Still no scrolling */ NULL, /* No triple buffering */ allegro_gl_create_video_bitmap, allegro_gl_destroy_video_bitmap, NULL, NULL, /* No show/request video bitmaps */ NULL, NULL, /* No system bitmaps */ allegro_gl_set_mouse_sprite, allegro_gl_show_mouse, allegro_gl_hide_mouse, allegro_gl_move_mouse, allegro_gl_drawing_mode, NULL, NULL, /* No video state stuff */ allegro_gl_set_blender_mode, NULL, /* No fetch_mode_list */ 0, 0, /* physical (not virtual!) screen size */ 0, /* true if video memory is linear */ 0, /* bank size, in bytes */ 0, /* bank granularity, in bytes */ 0, /* video memory size, in bytes */ 0, /* physical address of video memory */ TRUE /* Windowed mode? */ }; GFX_DRIVER gfx_allegro_gl_fullscreen = { GFX_OPENGL_FULLSCREEN, EMPTY_STRING, EMPTY_STRING, "AllegroGL Fullscreen (MacOS X)", allegro_gl_macosx_init_fullscreen, allegro_gl_macosx_exit, NULL, /* scrolling not implemented */ NULL, /* vsync, may use for flip? */ NULL, /* No h/w pallete, not using indexed mode */ NULL, NULL, /* Still no scrolling */ NULL, /* No triple buffering */ allegro_gl_create_video_bitmap, allegro_gl_destroy_video_bitmap, NULL, NULL, /* No show/request video bitmaps */ NULL, NULL, /* No system bitmaps */ allegro_gl_set_mouse_sprite, allegro_gl_show_mouse, allegro_gl_hide_mouse, allegro_gl_move_mouse, allegro_gl_drawing_mode, NULL, NULL, /* No video state stuff */ allegro_gl_set_blender_mode, NULL, /* No fetch_mode_list */ 0, 0, /* physical (not virtual!) screen size */ 0, /* true if video memory is linear */ 0, /* bank size, in bytes */ 0, /* bank granularity, in bytes */ 0, /* video memory size, in bytes */ 0, /* physical address of video memory */ TRUE /* Windowed mode */ }; @implementation AllegroGLView - (void)resetCursorRects { [super resetCursorRects]; [self addCursorRect: NSMakeRect(0, 0, gfx_allegro_gl_windowed.w, gfx_allegro_gl_windowed.h) cursor: osx_cursor]; [osx_cursor setOnMouseEntered: YES]; } /* Custom view: when created, select a suitable pixel format */ - (id) initWithFrame: (NSRect) frame { NSOpenGLPixelFormat* pf = init_pixel_format(TRUE); if (pf) { self = [super initWithFrame:frame pixelFormat: pf]; [pf release]; return self; } else { TRACE(PREFIX_W "Unable to find suitable pixel format\n"); } return nil; } @end /* NSOpenGLPixelFormat *build_pixelformat(int format) * * Given the options in format, attempt to build a pixel format. * return nil if no format is suitable */ static NSOpenGLPixelFormat *build_pixelformat(int format) { NSOpenGLPixelFormatAttribute attribs[MAX_ATTRIBUTES], *attrib; attrib=attribs; if ((format & AGL_DOUBLEBUFFER) && allegro_gl_display_info.doublebuffered) *attrib++ = NSOpenGLPFADoubleBuffer; if ((format & AGL_STEREO) && allegro_gl_display_info.stereo) *attrib++ = NSOpenGLPFAStereo; if (format & AGL_AUX_BUFFERS) { *attrib++ = NSOpenGLPFAAuxBuffers; *attrib++ = allegro_gl_display_info.aux_buffers; } if (format & (AGL_COLOR_DEPTH | AGL_RED_DEPTH | AGL_GREEN_DEPTH | AGL_BLUE_DEPTH)) { *attrib++ = NSOpenGLPFAColorSize; *attrib++ = allegro_gl_display_info.colour_depth; } if (format & AGL_ALPHA_DEPTH) { *attrib++ = NSOpenGLPFAAlphaSize; *attrib++ = allegro_gl_display_info.pixel_size.rgba.a; } if (format & AGL_Z_DEPTH) { *attrib++ = NSOpenGLPFADepthSize; *attrib++ = allegro_gl_display_info.depth_size; } if (format & AGL_STENCIL_DEPTH) { *attrib++ = NSOpenGLPFAStencilSize; *attrib++ = allegro_gl_display_info.stencil_size; } if (format & (AGL_ACC_RED_DEPTH | AGL_ACC_GREEN_DEPTH | AGL_ACC_BLUE_DEPTH | AGL_ACC_ALPHA_DEPTH)) { *attrib++ = NSOpenGLPFAAccumSize; *attrib++ = allegro_gl_display_info.accum_size.rgba.r + allegro_gl_display_info.accum_size.rgba.g + allegro_gl_display_info.accum_size.rgba.b + allegro_gl_display_info.accum_size.rgba.a; } *attrib++ = NSOpenGLPFAMinimumPolicy; /* Always request one of fullscreen or windowed */ if (allegro_gl_display_info.fullscreen) { *attrib++ = NSOpenGLPFAFullScreen; *attrib++ = NSOpenGLPFAScreenMask; *attrib++ = CGDisplayIDToOpenGLDisplayMask(kCGDirectMainDisplay); } else { *attrib++ = NSOpenGLPFAWindow; *attrib++ = NSOpenGLPFABackingStore; } if ((format & AGL_RENDERMETHOD) && (allegro_gl_display_info.rmethod==1)) *attrib++ = NSOpenGLPFAAccelerated; if (format & AGL_SAMPLE_BUFFERS) { *attrib++ = NSOpenGLPFASampleBuffers; *attrib++ = allegro_gl_display_info.sample_buffers; *attrib++ = NSOpenGLPFANoRecovery; } if (format & AGL_SAMPLES) { *attrib++ = NSOpenGLPFASamples; *attrib++ = allegro_gl_display_info.samples; } *attrib = 0; return [[NSOpenGLPixelFormat alloc] initWithAttributes: attribs]; } /* NSOpenGLPixelFormat *init_pixel_format(int windowed) * * Generate a pixel format. First try and get all the 'suggested' settings. * If this fails, just get the 'required' settings, * or nil if no format can be found */ static NSOpenGLPixelFormat *init_pixel_format(int windowed) { NSOpenGLPixelFormat *pf; allegro_gl_display_info.fullscreen=!windowed; /* First we try an aggressive approach, requiring everything */ pf=build_pixelformat(__allegro_gl_required_settings | __allegro_gl_suggested_settings); /* If not, then just try with what is required */ if (pf==nil) { pf=build_pixelformat(__allegro_gl_required_settings); } return pf; } static void decode_pixel_format(NSOpenGLPixelFormat *pf, struct allegro_gl_display_info *dinfo) { GLint value; TRACE(PREFIX_I "Decoding:\n"); [pf getValues: &value forAttribute: NSOpenGLPFAAccelerated forVirtualScreen: 0]; dinfo->rmethod = value ? 1 : 0; TRACE(PREFIX_I "Acceleration: %s\n", ((dinfo->rmethod == 0) ? "No" : "Yes")); [pf getValues: &value forAttribute: NSOpenGLPFADoubleBuffer forVirtualScreen: 0]; dinfo->doublebuffered = value; [pf getValues: &value forAttribute: NSOpenGLPFAStereo forVirtualScreen: 0]; dinfo->stereo = value; [pf getValues: &value forAttribute: NSOpenGLPFAAuxBuffers forVirtualScreen: 0]; dinfo->aux_buffers = value; [pf getValues: &value forAttribute: NSOpenGLPFADepthSize forVirtualScreen: 0]; dinfo->depth_size = value; [pf getValues: &value forAttribute: NSOpenGLPFAStencilSize forVirtualScreen: 0]; dinfo->stencil_size = value; TRACE(PREFIX_I "DblBuf: %i Zbuf: %i Stereo: %i Aux: %i Stencil: %i\n", dinfo->doublebuffered, dinfo->depth_size, dinfo->stereo, dinfo->aux_buffers, dinfo->stencil_size); [pf getValues: &value forAttribute: NSOpenGLPFASampleBuffers forVirtualScreen: 0]; dinfo->sample_buffers = value; [pf getValues: &value forAttribute: NSOpenGLPFASamples forVirtualScreen: 0]; dinfo->samples = value; TRACE(PREFIX_I "Sample buffers: %i Samples: %i\n", dinfo->sample_buffers, dinfo->samples); [pf getValues: &value forAttribute: NSOpenGLPFAColorSize forVirtualScreen: 0]; dinfo->colour_depth = value; [pf getValues: &value forAttribute: NSOpenGLPFAAlphaSize forVirtualScreen: 0]; dinfo->pixel_size.rgba.a = value; switch (dinfo->colour_depth) { case 32: case 24: dinfo->pixel_size.rgba.r = 8; dinfo->pixel_size.rgba.g = 8; dinfo->pixel_size.rgba.b = 8; dinfo->r_shift = 24; dinfo->g_shift = 16; dinfo->b_shift = 8; dinfo->a_shift = 0; break; case 16: dinfo->pixel_size.rgba.r = 5; dinfo->pixel_size.rgba.g = 6; dinfo->pixel_size.rgba.b = 5; dinfo->r_shift = 11; dinfo->g_shift = 5; dinfo->b_shift = 0; dinfo->a_shift = 0; break; case 15: dinfo->pixel_size.rgba.r = 5; dinfo->pixel_size.rgba.g = 5; dinfo->pixel_size.rgba.b = 5; dinfo->r_shift = 11; dinfo->g_shift = 6; dinfo->b_shift = 1; dinfo->a_shift = 0; break; default: TRACE(PREFIX_W "Bad color depth\n"); } TRACE(PREFIX_I "Decoded bpp: %i\n", dinfo->colour_depth); dinfo->allegro_format = (dinfo->colour_depth != 0) && (dinfo->g_shift == dinfo->pixel_size.rgba.b) && (dinfo->r_shift * dinfo->b_shift == 0) && (dinfo->r_shift + dinfo->b_shift == dinfo->pixel_size.rgba.b + dinfo->pixel_size.rgba.g); [pf getValues: &value forAttribute: NSOpenGLPFAAccumSize forVirtualScreen: 0]; value /= 4; dinfo->accum_size.rgba.r = value; dinfo->accum_size.rgba.g = value; dinfo->accum_size.rgba.b = value; dinfo->accum_size.rgba.a = value; dinfo->float_color = 0; dinfo->float_depth = 0; } static BITMAP *allegro_gl_create_screen (GFX_DRIVER *drv, int w, int h, int depth) { BITMAP *bmp; int is_linear = drv->linear; drv->linear = 1; bmp = _make_bitmap (w, h, 0, drv, depth, 0); bmp->id = BMP_ID_VIDEO | 1000; drv->linear = is_linear; drv->w = w; drv->h = h; return bmp; } void setup_shifts(void) { #if TARGET_RT_BIG_ENDIAN __allegro_gl_set_allegro_image_format(TRUE); #else __allegro_gl_set_allegro_image_format(FALSE); #endif __linear_vtable15.mask_color = makecol15(255, 0, 255); __linear_vtable16.mask_color = makecol16(255, 0, 255); __linear_vtable24.mask_color = makecol24(255, 0, 255); __linear_vtable32.mask_color = makecol32(255, 0, 255); } static BITMAP *allegro_gl_macosx_init_windowed(int w, int h, int v_w, int v_h, int color_depth) { NSRect rect = NSMakeRect(0, 0, w, h); AllegroGLView *view; int desktop_depth; /* virtual screen are not supported */ if ((v_w != 0 && v_w != w) || (v_h != 0 && v_h != h)) return NULL; setup_shifts(); /* Fill in missing color depth info */ __allegro_gl_fill_in_info(); /* Be sure the current desktop color depth is at least 15bpp */ /* We may want to change this, so try to set a better depth, or to at least report an error somehow */ desktop_depth = desktop_color_depth(); if (desktop_depth < 15) return NULL; TRACE(PREFIX_I "Requested color depth: %i Desktop color depth: %i\n", allegro_gl_display_info.colour_depth, desktop_depth); _unix_lock_mutex(osx_event_mutex); osx_window = [[NSWindow alloc] initWithContentRect: rect styleMask: NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask backing: NSBackingStoreBuffered defer: NO]; window_delegate = [[[AllegroWindowDelegate alloc] init] autorelease]; [osx_window setDelegate: window_delegate]; [osx_window setOneShot: YES]; [osx_window setAcceptsMouseMovedEvents: YES]; [osx_window setViewsNeedDisplay: NO]; [osx_window setReleasedWhenClosed: YES]; [osx_window center]; [osx_window makeKeyAndOrderFront: nil]; if ((__allegro_gl_required_settings | __allegro_gl_suggested_settings) & (AGL_WINDOW_X | AGL_WINDOW_Y)) { /* TODO: set window position */ } set_window_title(osx_window_title); view = [[AllegroGLView alloc] initWithFrame: rect]; [osx_window setContentView: view]; context=[[view openGLContext] retain]; [context makeCurrentContext]; decode_pixel_format([view pixelFormat], &allegro_gl_display_info); set_color_depth(allegro_gl_display_info.colour_depth); allegro_gl_display_info.w = gfx_allegro_gl_windowed.w = w; allegro_gl_display_info.h = gfx_allegro_gl_windowed.h = h; allegro_gl_screen = allegro_gl_create_screen(&gfx_allegro_gl_windowed, w, h, allegro_gl_get(AGL_COLOR_DEPTH)); TRACE(PREFIX_I "GLScreen: %ix%ix%i\n", w, h, allegro_gl_get(AGL_COLOR_DEPTH)); allegro_gl_screen->id |= BMP_ID_VIDEO | 1000; __allegro_gl_valid_context = TRUE; __allegro_gl_driver = &allegro_gl_macosx; allegro_gl_info.is_mesa_driver = FALSE; /* Print out OpenGL version info */ TRACE(PREFIX_I "OpenGL Version: %s\n", (AL_CONST char*)glGetString(GL_VERSION)); TRACE(PREFIX_I "Vendor: %s\n", (AL_CONST char*)glGetString(GL_VENDOR)); TRACE(PREFIX_I "Renderer: %s\n", (AL_CONST char*)glGetString(GL_RENDERER)); /* init the GL extensions */ __allegro_gl_manage_extensions(); /* Update screen vtable in order to use AGL's */ __allegro_gl__glvtable_update_vtable(&allegro_gl_screen->vtable); memcpy(&_screen_vtable, allegro_gl_screen->vtable, sizeof(GFX_VTABLE)); allegro_gl_screen->vtable = &_screen_vtable; osx_mouse_tracking_rect = [view addTrackingRect: rect owner: NSApp userData: nil assumeInside: YES]; osx_keyboard_focused(FALSE, 0); clear_keybuf(); osx_gfx_mode = OSX_GFX_OPENGL; osx_skip_mouse_move = TRUE; macosx_setup_gl(); [context flushBuffer]; _unix_unlock_mutex(osx_event_mutex); return allegro_gl_screen; } static BITMAP *allegro_gl_macosx_init_fullscreen(int w, int h, int v_w, int v_h, int color_depth) { NSOpenGLPixelFormat *pf; CFDictionaryRef mode = NULL; int target_depth; boolean_t match = FALSE; int refresh_rate; /* virtual screen are not supported */ if ((v_w != 0 && v_w != w) || (v_h != 0 && v_h != h)) return NULL; setup_shifts(); /* Fill in missing color depth info */ __allegro_gl_fill_in_info(); if (allegro_gl_display_info.colour_depth <= 8) return NULL; TRACE(PREFIX_I "Requested color depth: %i\n", allegro_gl_display_info.colour_depth); _unix_lock_mutex(osx_event_mutex); target_depth = allegro_gl_display_info.colour_depth; if (target_depth == 16) target_depth = 15; if (_refresh_rate_request > 0) mode = CGDisplayBestModeForParametersAndRefreshRate(kCGDirectMainDisplay, target_depth, w, h, (double)_refresh_rate_request, &match); if (!match) mode = CGDisplayBestModeForParameters(kCGDirectMainDisplay, target_depth, w, h, &match); if (!match) { TRACE(PREFIX_W "Unsupported mode %dx%dx%d\n", w, h, target_depth); _unix_unlock_mutex(osx_event_mutex); return NULL; } osx_init_fade_system(); old_mode = CGDisplayCurrentMode(kCGDirectMainDisplay); CGDisplayHideCursor(kCGDirectMainDisplay); osx_fade_screen(FALSE, 0.3); if (CGDisplayCapture(kCGDirectMainDisplay) != kCGErrorSuccess) { TRACE(PREFIX_W "Cannot capture main display\n"); old_mode = NULL; CGDisplayRestoreColorSyncSettings(); _unix_unlock_mutex(osx_event_mutex); return NULL; } if (CGDisplaySwitchToMode(kCGDirectMainDisplay, mode) != kCGErrorSuccess) { TRACE(PREFIX_W "Cannot switch main display mode\n"); CGDisplayRelease(kCGDirectMainDisplay); old_mode = NULL; CGDisplayRestoreColorSyncSettings(); _unix_unlock_mutex(osx_event_mutex); return NULL; } HideMenuBar(); CGDisplayRestoreColorSyncSettings(); CFNumberGetValue(CFDictionaryGetValue(mode, kCGDisplayRefreshRate), kCFNumberSInt32Type, &refresh_rate); _set_current_refresh_rate(refresh_rate); pf = init_pixel_format(FALSE); if (!pf) { TRACE(PREFIX_W "Unable to find suitable pixel format\n"); CGDisplaySwitchToMode(kCGDirectMainDisplay, old_mode); CGDisplayRelease(kCGDirectMainDisplay); old_mode = NULL; CGDisplayRestoreColorSyncSettings(); _unix_unlock_mutex(osx_event_mutex); return NULL; } context = [[NSOpenGLContext alloc] initWithFormat: pf shareContext: nil]; if (!context) { TRACE(PREFIX_W "Unable to create OpenGL context\n"); [pf release]; CGDisplaySwitchToMode(kCGDirectMainDisplay, old_mode); CGDisplayRelease(kCGDirectMainDisplay); old_mode = NULL; CGDisplayRestoreColorSyncSettings(); _unix_unlock_mutex(&osx_event_mutex); return NULL; } [context makeCurrentContext]; [context setFullScreen]; decode_pixel_format(pf, &allegro_gl_display_info); set_color_depth(allegro_gl_display_info.colour_depth); allegro_gl_display_info.w = gfx_allegro_gl_fullscreen.w = w; allegro_gl_display_info.h = gfx_allegro_gl_fullscreen.h = h; allegro_gl_screen = allegro_gl_create_screen(&gfx_allegro_gl_fullscreen, w, h, allegro_gl_get(AGL_COLOR_DEPTH)); TRACE(PREFIX_I "GLScreen: %ix%ix%i\n", w, h, allegro_gl_get(AGL_COLOR_DEPTH)); allegro_gl_screen->id |= BMP_ID_VIDEO | 1000; __allegro_gl_valid_context = TRUE; __allegro_gl_driver = &allegro_gl_macosx; __allegro_gl__glvtable_update_vtable(&allegro_gl_screen->vtable); memcpy(&_screen_vtable, allegro_gl_screen->vtable, sizeof(GFX_VTABLE)); allegro_gl_screen->vtable = &_screen_vtable; allegro_gl_info.is_mesa_driver = FALSE; /* init the GL extensions */ __allegro_gl_manage_extensions(); osx_keyboard_focused(FALSE, 0); clear_keybuf(); osx_gfx_mode = OSX_GFX_OPENGL; osx_skip_mouse_move = TRUE; macosx_setup_gl(); [context flushBuffer]; _unix_unlock_mutex(osx_event_mutex); return allegro_gl_screen; } static void allegro_gl_macosx_exit(struct BITMAP *b) { _unix_lock_mutex(osx_event_mutex); if (old_mode) osx_fade_screen(FALSE, 0.2); if (context) { [context clearDrawable]; [context release]; context = NULL; } if (osx_window) { [osx_window close]; osx_window = NULL; } if (old_mode) { CGDisplaySwitchToMode(kCGDirectMainDisplay, old_mode); CGDisplayRelease(kCGDirectMainDisplay); CGDisplayShowCursor(kCGDirectMainDisplay); ShowMenuBar(); osx_fade_screen(TRUE, 0.3); CGDisplayRestoreColorSyncSettings(); old_mode = NULL; } osx_mouse_tracking_rect = -1; osx_gfx_mode = OSX_GFX_NONE; __allegro_gl_unmanage_extensions(); __allegro_gl_valid_context = FALSE; _unix_unlock_mutex(osx_event_mutex); } /* static void macosx_setup_gl(void) * * Initialize a reasonable viewport. Those should be OpenGL defaults, * but some drivers don't implement this correctly. */ static void macosx_setup_gl(void) { glViewport(0, 0, SCREEN_W, SCREEN_H); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); /* For some reason OSX seems to set the scissor test weirdly */ glScissor(0,0,SCREEN_W,SCREEN_H); /* Set up some variables that some GL drivers omit */ glBindTexture(GL_TEXTURE_2D, 0); /* Clear the screen */ glClearColor(0.0, 0.0, 0.0, 1.0); glClear(GL_COLOR_BUFFER_BIT); } /* AllegroGL driver routines */ static void flip(void) { [context flushBuffer]; } static void gl_on(void) { return; } static void gl_off(void) { return; } /* AllegroGL driver */ static struct allegro_gl_driver allegro_gl_macosx = { flip, gl_on, gl_off, NULL }; allegro4.4-4.4.2/addons/allegrogl/src/math.c000066400000000000000000000200151173507505700205100ustar00rootroot00000000000000/* This code is (C) AllegroGL contributors, and double licensed under * the GPL and zlib licenses. See gpl.txt or zlib.txt for details. */ /** \file math.c * Converting mathematical structures from Allegro to OpenGL. * * This file provides routines to make Allegro matrices from * GL-style matrices, and vice versa. * This also provides a QUAT to glRotate converter. * * Note that Allegro matrices can only store affine * transformations. */ #include #include #include "alleggl.h" #include "allglint.h" #ifndef M_PI #define M_PI 3.14159265358979323846 #endif #define ALGL_NOCONV(x) x #define TRANSLATE_AL_TO_GL(al_type, gl_type, convertor) \ void allegro_gl_##al_type##_to_##gl_type (al_type *m, gl_type gl[16]) \ { \ int col, row; \ for (col = 0; col < 3; col++) \ for (row = 0; row < 3; row++) \ gl[col*4+row] = convertor (m->v[col][row]); \ for (row = 0; row < 3; row++) \ gl[12+row] = convertor (m->t[row]); \ for (col = 0; col < 3; col++) \ gl[4*col + 3] = 0; \ gl[15] = 1; \ } /** \ingroup math * Converts an Allegro fixed-point matrix to an array of * floats suitable for OpenGL's matrix operations. * * \b Example: *
 *    MATRIX m = identity_matrix;
 *    GLfloat gl_m[16];
 *    get_vector_rotation_matrix(&m, itofix(1), 0, itofix(1), ftofix(43.83));
 *    allegro_gl_MATRIX_to_GLfloat(&m, &gl_m);
 *    glLoadMatrixf(&gl_m);
 *  
* * * \see allegro_gl_MATRIX_to_GLdouble() * \see allegro_gl_MATRIX_f_to_GLfloat() * \see allegro_gl_MATRIX_f_to_GLdouble() * \see allegro_gl_GLdouble_to_MATRIX() * \see allegro_gl_GLfloat_to_MATRIX_f() * \see allegro_gl_GLdouble_to_MATRIX_f() * \see allegro_gl_GLfloat_to_MATRIX() */ TRANSLATE_AL_TO_GL(MATRIX, GLfloat, fixtof) /** \ingroup math * Converts an Allegro fixed-point matrix to an array of * doubles suitable for OpenGL's matrix operations. * * \see allegro_gl_MATRIX_to_GLfloat() * \see allegro_gl_MATRIX_f_to_GLfloat() * \see allegro_gl_MATRIX_f_to_GLdouble() * \see allegro_gl_GLdouble_to_MATRIX() * \see allegro_gl_GLfloat_to_MATRIX_f() * \see allegro_gl_GLdouble_to_MATRIX_f() * \see allegro_gl_GLfloat_to_MATRIX() */ TRANSLATE_AL_TO_GL(MATRIX, GLdouble, fixtof) /** \ingroup math * Converts an Allegro floating-point matrix to an array of * floats suitable for OpenGL's matrix operations. * * \see allegro_gl_MATRIX_to_GLfloat() * \see allegro_gl_MATRIX_to_GLdouble() * \see allegro_gl_MATRIX_f_to_GLdouble() * \see allegro_gl_GLdouble_to_MATRIX() * \see allegro_gl_GLfloat_to_MATRIX_f() * \see allegro_gl_GLdouble_to_MATRIX_f() * \see allegro_gl_GLfloat_to_MATRIX() */ TRANSLATE_AL_TO_GL(MATRIX_f, GLfloat, ALGL_NOCONV) /** \ingroup math * Converts an Allegro floating-point matrix to an array of * doubles suitable for OpenGL's matrix operations. * * \see allegro_gl_MATRIX_to_GLfloat() * \see allegro_gl_MATRIX_to_GLdouble() * \see allegro_gl_MATRIX_f_to_GLfloat() * \see allegro_gl_GLdouble_to_MATRIX() * \see allegro_gl_GLfloat_to_MATRIX_f() * \see allegro_gl_GLdouble_to_MATRIX_f() * \see allegro_gl_GLfloat_to_MATRIX() */ TRANSLATE_AL_TO_GL(MATRIX_f, GLdouble, ALGL_NOCONV) #define TRANSLATE_GL_TO_AL(gl_type, al_type, convertor) \ void allegro_gl_##gl_type##_to_##al_type (gl_type gl[16], al_type *m) \ { \ int col, row; \ for (col = 0; col < 3; col++) \ for (row = 0; row < 3; row++) \ m->v[col][row] = convertor (gl[col*4+row]); \ for (row = 0; row < 3; row++) \ m->t[row] = convertor (gl[12+row]); \ } /** \ingroup math * Converts an OpenGL floating-point matrix issued from the * matrix stack to an Allegro fixed-point matrix. * * \see allegro_gl_MATRIX_to_GLfloat() * \see allegro_gl_MATRIX_to_GLdouble() * \see allegro_gl_MATRIX_f_to_GLfloat() * \see allegro_gl_MATRIX_f_to_GLdouble() * \see allegro_gl_GLdouble_to_MATRIX() * \see allegro_gl_GLfloat_to_MATRIX_f() * \see allegro_gl_GLdouble_to_MATRIX_f() */ TRANSLATE_GL_TO_AL(GLfloat, MATRIX, ftofix) /** \ingroup math * Converts an OpenGL double precision floating-point matrix * issued from the matrix stack to an Allegro fixed-point matrix. * * \see allegro_gl_MATRIX_to_GLfloat() * \see allegro_gl_MATRIX_to_GLdouble() * \see allegro_gl_MATRIX_f_to_GLfloat() * \see allegro_gl_MATRIX_f_to_GLdouble() * \see allegro_gl_GLfloat_to_MATRIX_f() * \see allegro_gl_GLdouble_to_MATRIX_f() * \see allegro_gl_GLfloat_to_MATRIX() */ TRANSLATE_GL_TO_AL(GLdouble, MATRIX, ftofix) /** \ingroup math * Converts an OpenGL floating-point matrix issued from the * matrix stack to an Allegro floating-point matrix. * * \see allegro_gl_MATRIX_to_GLfloat() * \see allegro_gl_MATRIX_to_GLdouble() * \see allegro_gl_MATRIX_f_to_GLfloat() * \see allegro_gl_MATRIX_f_to_GLdouble() * \see allegro_gl_GLdouble_to_MATRIX() * \see allegro_gl_GLdouble_to_MATRIX_f() * \see allegro_gl_GLfloat_to_MATRIX() */ TRANSLATE_GL_TO_AL(GLfloat, MATRIX_f, ALGL_NOCONV) /** \ingroup math * Converts an OpenGL double precision floating-point matrix * issued from the matrix stack to an Allegro single-precision * floating-point matrix. * * \see allegro_gl_MATRIX_to_GLfloat() * \see allegro_gl_MATRIX_to_GLdouble() * \see allegro_gl_MATRIX_f_to_GLfloat() * \see allegro_gl_MATRIX_f_to_GLdouble() * \see allegro_gl_GLdouble_to_MATRIX() * \see allegro_gl_GLfloat_to_MATRIX_f() * \see allegro_gl_GLfloat_to_MATRIX() */ TRANSLATE_GL_TO_AL(GLdouble, MATRIX_f, ALGL_NOCONV) #undef ALGL_NOCONV #ifndef RAD_2_DEG #define RAD_2_DEG(a) ((a) * 180 / M_PI) #endif /* void allegro_gl_apply_quat(QUAT *q) */ /** \ingroup math * Multiplies the Quaternion to the current transformation * matrix, by converting it to a call to glRotatef() * * \b Example: *
 *    QUAT q = identity_quat;
 *    get_vector_rotation_quat(&q, itofix(1), 0, itofix(1), ftofix(43.83));
 *    glLoadIdentity();
 *    allegro_gl_apply_quat(&q);
 *  
* * * \sa allegro_gl_quat_to_glrotatef(), allegro_gl_quat_to_glrotated() * * \param q The Quaternion to apply. */ void allegro_gl_apply_quat(QUAT *q) { float theta; ASSERT(q); ASSERT(__allegro_gl_valid_context); theta = RAD_2_DEG(2 * acos(q->w)); if (q->w < 1.0f && q->w > -1.0f) glRotatef(theta, q->x, q->y, q->z); return; } /* void allegro_gl_quat_to_glrotatef(QUAT *q, float *angle, float *x, float *y, float *z) */ /** \ingroup math * Converts a quaternion to a vector/angle, which can be used with * glRotate*(). Values are returned in the parameters. * * \b Example: *
 *    QUAT q = identity_quat;
 *    float x, y, z, angle;
 *    allegro_gl_quat_to_glrotatef(&q, &angle, &x, &y, &z);
 *    glRotatef(angle, x, y, z);
 *  
* * \sa allegro_gl_quat_to_glrotated(), allegro_gl_apply_quat() * * \param q The Quaternion to convert. * \param angle The angle of rotation, in degrees. * \param x The rotation vector's x-axis component. * \param y The rotation vector's y-axis component. * \param z The rotation vector's z-axis component. */ void allegro_gl_quat_to_glrotatef(QUAT *q, float *angle, float *x, float *y, float *z) { ASSERT(q); ASSERT(angle); ASSERT(x); ASSERT(y); ASSERT(z); *angle = RAD_2_DEG(2 * acos(q->w)); *x = q->x; *y = q->y; *z = q->z; return; } /* void allegro_gl_quat_to_glrotated(QUAT *q, double *angle, double *x, double *y, double *z) */ /** \ingroup math * Converts a quaternion to a vector/angle, which can be used with * glRotate*(). Values are returned in the parameters. * See allegro_gl_quat_to_rotatef() for an example. * * \sa allegro_gl_quat_to_glrotatef(), allegro_gl_apply_quat() * * \param q The Quaternion to convert. * \param angle The angle of rotation, in degrees. * \param x The rotation vector's x-axis component. * \param y The rotation vector's y-axis component. * \param z The rotation vector's z-axis component. */ void allegro_gl_quat_to_glrotated(QUAT *q, double *angle, double *x, double *y, double *z) { ASSERT(q); ASSERT(angle); ASSERT(x); ASSERT(y); ASSERT(z); *angle = RAD_2_DEG(2 * acos(q->w)); *x = q->x; *y = q->y; *z = q->z; return; } allegro4.4-4.4.2/addons/allegrogl/src/scorer.c000066400000000000000000000305631173507505700210650ustar00rootroot00000000000000/* This code is (C) AllegroGL contributors, and double licensed under * the GPL and zlib licenses. See gpl.txt or zlib.txt for details. */ /** \file scorer.c * \brief Scoring system for screen mode selection (internal). */ #include #include "alleggl.h" #include "allglint.h" static int best, best_score; #define target allegro_gl_display_info #define req __allegro_gl_required_settings #define sug __allegro_gl_suggested_settings #define PREFIX_I "agl-scorer INFO: " /* __allegro_gl_fill_in_info() * Will fill in missing settings by 'guessing' * what the user intended. */ void __allegro_gl_fill_in_info() { int all_components = AGL_RED_DEPTH | AGL_GREEN_DEPTH | AGL_BLUE_DEPTH | AGL_ALPHA_DEPTH; /* If all color components were set, but not the color depth */ if ((((req | sug) & AGL_COLOR_DEPTH) == 0) && (((req | sug) & all_components) == all_components)) { target.colour_depth = target.pixel_size.rgba.r + target.pixel_size.rgba.g + target.pixel_size.rgba.b + target.pixel_size.rgba.a; /* Round depth to 8 bits */ target.colour_depth = (target.colour_depth + 7) / 8; } /* If only some components were set, guess the others */ else if ((req | sug) & all_components) { int avg = ((req | sug) & AGL_RED_DEPTH ? target.pixel_size.rgba.r: 0) + ((req | sug) & AGL_GREEN_DEPTH ? target.pixel_size.rgba.g: 0) + ((req | sug) & AGL_BLUE_DEPTH ? target.pixel_size.rgba.b: 0) + ((req | sug) & AGL_ALPHA_DEPTH ? target.pixel_size.rgba.a: 0); int num = ((req | sug) & AGL_RED_DEPTH ? 1 : 0) + ((req | sug) & AGL_GREEN_DEPTH ? 1 : 0) + ((req | sug) & AGL_BLUE_DEPTH ? 1 : 0) + ((req | sug) & AGL_ALPHA_DEPTH ? 1 : 0); avg /= (num ? num : 1); if (((req | sug) & AGL_RED_DEPTH )== 0) { sug |= AGL_RED_DEPTH; target.pixel_size.rgba.r = avg; } if (((req | sug) & AGL_GREEN_DEPTH) == 0) { sug |= AGL_GREEN_DEPTH; target.pixel_size.rgba.g = avg; } if (((req | sug) & AGL_BLUE_DEPTH) == 0) { sug |= AGL_BLUE_DEPTH; target.pixel_size.rgba.b = avg; } if (((req | sug) & AGL_ALPHA_DEPTH) == 0) { sug |= AGL_ALPHA_DEPTH; target.pixel_size.rgba.a = avg; } /* If color depth wasn't defined, figure it out */ if (((req | sug) & AGL_COLOR_DEPTH) == 0) { __allegro_gl_fill_in_info(); } } /* If the user forgot to set a color depth in AGL, but used the * Allegro one instead */ if ((((req | sug) & AGL_COLOR_DEPTH) == 0) && (target.colour_depth == 0)) { BITMAP *temp = create_bitmap(1, 1); if (temp) { allegro_gl_set(AGL_COLOR_DEPTH, bitmap_color_depth(temp)); allegro_gl_set(AGL_REQUIRE, AGL_COLOR_DEPTH); destroy_bitmap(temp); } } /* Prefer double-buffering */ if (!((req | sug) & AGL_DOUBLEBUFFER)) { allegro_gl_set(AGL_DOUBLEBUFFER, 1); allegro_gl_set(AGL_SUGGEST, AGL_DOUBLEBUFFER); } /* Prefer no multisamping */ if (!((req | sug) & (AGL_SAMPLE_BUFFERS | AGL_SAMPLES))) { allegro_gl_set(AGL_SAMPLE_BUFFERS, 0); allegro_gl_set(AGL_SAMPLES, 0); allegro_gl_set(AGL_SUGGEST, AGL_SAMPLE_BUFFERS | AGL_SAMPLES); } /* Prefer monoscopic */ if (!((req | sug) & AGL_STEREO)) { allegro_gl_set(AGL_STEREO, 0); allegro_gl_set(AGL_SUGGEST, AGL_STEREO); } /* Prefer unsigned normalized buffers */ if (!((req | sug) & (AGL_FLOAT_COLOR | AGL_FLOAT_Z))) { allegro_gl_set(AGL_FLOAT_COLOR, 0); allegro_gl_set(AGL_FLOAT_Z, 0); allegro_gl_set(AGL_SUGGEST, AGL_FLOAT_COLOR | AGL_FLOAT_Z); } } void __allegro_gl_reset_scorer(void) { best = -1; best_score = -1; } static int get_score(struct allegro_gl_display_info *dinfo) { int score = 0; if (dinfo->colour_depth != target.colour_depth) { if (req & AGL_COLOR_DEPTH) { ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE, get_config_text("Color depth requirement not met.")); return -1; } } else { /* If requested color depths agree */ score += 128; } if (sug & AGL_COLOR_DEPTH) { if (dinfo->colour_depth < target.colour_depth) score += (96 * dinfo->colour_depth) / target.colour_depth; else score += 96 + 96 / (1 + dinfo->colour_depth - target.colour_depth); } /* check colour component widths here and Allegro formatness */ if ((req & AGL_RED_DEPTH) && (dinfo->pixel_size.rgba.r != target.pixel_size.rgba.r)) { ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE, get_config_text("Red depth requirement not met.")); return -1; } if (sug & AGL_RED_DEPTH) { if (dinfo->pixel_size.rgba.r < target.pixel_size.rgba.r) { score += (16 * dinfo->pixel_size.rgba.r) / target.pixel_size.rgba.r; } else { score += 16 + 16 / (1 + dinfo->pixel_size.rgba.r - target.pixel_size.rgba.r); } } if ((req & AGL_GREEN_DEPTH) && (dinfo->pixel_size.rgba.g != target.pixel_size.rgba.g)) { ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE, get_config_text("Green depth requirement not met.")); return -1; } if (sug & AGL_GREEN_DEPTH) { if (dinfo->pixel_size.rgba.g < target.pixel_size.rgba.g) { score += (16 * dinfo->pixel_size.rgba.g) / target.pixel_size.rgba.g; } else { score += 16 + 16 / (1 + dinfo->pixel_size.rgba.g - target.pixel_size.rgba.g); } } if ((req & AGL_BLUE_DEPTH) && (dinfo->pixel_size.rgba.b != target.pixel_size.rgba.b)) { ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE, get_config_text("Blue depth requirement not met.")); return -1; } if (sug & AGL_BLUE_DEPTH) { if (dinfo->pixel_size.rgba.b < target.pixel_size.rgba.b) { score += (16 * dinfo->pixel_size.rgba.b) / target.pixel_size.rgba.b; } else { score += 16 + 16 / (1 + dinfo->pixel_size.rgba.b - target.pixel_size.rgba.b); } } if ((req & AGL_ALPHA_DEPTH) && (dinfo->pixel_size.rgba.a != target.pixel_size.rgba.a)) { ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE, get_config_text("Alpha depth requirement not met.")); return -1; } if (sug & AGL_ALPHA_DEPTH) { if (dinfo->pixel_size.rgba.a < target.pixel_size.rgba.a) { score += (16 * dinfo->pixel_size.rgba.a) / target.pixel_size.rgba.a; } else { score += 16 + 16 / (1 + dinfo->pixel_size.rgba.a - target.pixel_size.rgba.a); } } if ((req & AGL_ACC_RED_DEPTH) && (dinfo->accum_size.rgba.r != target.accum_size.rgba.r)) { ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE, get_config_text("Accumulator Red depth requirement not met.")); return -1; } if (sug & AGL_ACC_RED_DEPTH) { if (dinfo->accum_size.rgba.r < target.accum_size.rgba.r) { score += (16 * dinfo->accum_size.rgba.r) / target.accum_size.rgba.r; } else { score += 16 + 16 / (1 + dinfo->accum_size.rgba.r - target.accum_size.rgba.r); } } if ((req & AGL_ACC_GREEN_DEPTH) && (dinfo->accum_size.rgba.g != target.accum_size.rgba.g)) { ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE, get_config_text("Accumulator Green depth requirement not met.")); return -1; } if (sug & AGL_ACC_GREEN_DEPTH) { if (dinfo->accum_size.rgba.g < target.accum_size.rgba.g) { score += (16 * dinfo->accum_size.rgba.g) / target.accum_size.rgba.g; } else { score += 16 + 16 / (1 + dinfo->accum_size.rgba.g - target.accum_size.rgba.g); } } if ((req & AGL_ACC_BLUE_DEPTH) && (dinfo->accum_size.rgba.b != target.accum_size.rgba.b)) { ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE, get_config_text("Accumulator Blue depth requirement not met.")); return -1; } if (sug & AGL_ACC_BLUE_DEPTH) { if (dinfo->accum_size.rgba.b < target.accum_size.rgba.b) { score += (16 * dinfo->accum_size.rgba.b) / target.accum_size.rgba.b; } else { score += 16 + 16 / (1 + dinfo->accum_size.rgba.b - target.accum_size.rgba.b); } } if ((req & AGL_ACC_ALPHA_DEPTH) && (dinfo->accum_size.rgba.a != target.accum_size.rgba.a)) { ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE, get_config_text("Accumulator Alpha depth requirement not met.")); return -1; } if (sug & AGL_ACC_ALPHA_DEPTH) { if (dinfo->accum_size.rgba.a < target.accum_size.rgba.a) { score += (16 * dinfo->accum_size.rgba.a) / target.accum_size.rgba.a; } else { score += 16 + 16 / (1 + dinfo->accum_size.rgba.a - target.accum_size.rgba.a); } } if (!dinfo->doublebuffered != !target.doublebuffered) { if (req & AGL_DOUBLEBUFFER) { ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE, get_config_text("Double Buffer requirement not met.")); return -1; } } else { score += (sug & AGL_DOUBLEBUFFER) ? 256 : 1; } if (!dinfo->stereo != !target.stereo) { if (req & AGL_STEREO) { ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE, get_config_text("Stereo Buffer requirement not met.")); return -1; } } else { if (sug & AGL_STEREO) { score += 128; } } if ((req & AGL_AUX_BUFFERS) && (dinfo->aux_buffers < target.aux_buffers)) { ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE, get_config_text("Aux Buffer requirement not met.")); return -1; } if (sug & AGL_AUX_BUFFERS) { if (dinfo->aux_buffers < target.aux_buffers) { score += (64 * dinfo->aux_buffers) / target.aux_buffers; } else { score += 64 + 64 / (1 + dinfo->aux_buffers - target.aux_buffers); } } if ((req & AGL_Z_DEPTH) && (dinfo->depth_size != target.depth_size)) { ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE, get_config_text("Z-Buffer requirement not met.")); return -1; } if (sug & AGL_Z_DEPTH) { if (dinfo->depth_size < target.depth_size) { score += (64 * dinfo->depth_size) / target.depth_size; } else { score += 64 + 64 / (1 + dinfo->depth_size - target.depth_size); } } if ((req & AGL_STENCIL_DEPTH) && (dinfo->stencil_size != target.stencil_size)) { ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE, get_config_text("Stencil depth requirement not met.")); return -1; } if (sug & AGL_STENCIL_DEPTH) { if (dinfo->stencil_size < target.stencil_size) { score += (64 * dinfo->stencil_size) / target.stencil_size; } else { score += 64 + 64 / (1 + dinfo->stencil_size - target.stencil_size); } } if ((req & AGL_RENDERMETHOD) && ((dinfo->rmethod != target.rmethod) || (target.rmethod == 2))) { ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE, get_config_text("Render Method requirement not met")); return -1; } if ((sug & AGL_RENDERMETHOD) && (dinfo->rmethod == target.rmethod)) { score += 1024; } else if (dinfo->rmethod == 1) { score++; /* Add 1 for h/w accel */ } if ((req & AGL_SAMPLE_BUFFERS) && (dinfo->sample_buffers != target.sample_buffers)) { ustrzcpy(allegro_gl_error, AGL_ERROR_SIZE, get_config_text("Multisample Buffers requirement not met")); return -1; } if (sug & AGL_SAMPLE_BUFFERS) { if (dinfo->sample_buffers < target.sample_buffers) { score += (64 * dinfo->sample_buffers) / target.sample_buffers; } else { score += 64 + 64 / (1 + dinfo->sample_buffers - target.sample_buffers); } } if ((req & AGL_SAMPLES) && (dinfo->samples != target.samples)) { ustrzcpy(allegro_gl_error, AGL_ERROR_SIZE, get_config_text("Multisample Samples requirement not met")); return -1; } if (sug & AGL_SAMPLES) { if (dinfo->samples < target.samples) { score += (64 * dinfo->samples) / target.samples; } else { score += 64 + 64 / (1 + dinfo->samples - target.samples); } } if (!dinfo->float_color != !target.float_color) { if (req & AGL_FLOAT_COLOR) { ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE, get_config_text("Float Color requirement not met.")); return -1; } } else { if (sug & AGL_FLOAT_COLOR) { score += 128; } } if (!dinfo->float_depth != !target.float_depth) { if (req & AGL_FLOAT_Z) { ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE, get_config_text("Float Depth requirement not met.")); return -1; } } else { if (sug & AGL_FLOAT_Z) { score += 128; } } TRACE(PREFIX_I "Score is : %i\n", score); return score; } #undef target #undef req #undef sug int __allegro_gl_score_config(int refnum, struct allegro_gl_display_info *dinfo) { int score = get_score(dinfo); if (score == -1) { TRACE(PREFIX_I "score_config: %s\n", allegro_gl_error); return score; } if (score == best_score) { /* TRACE(PREFIX_I "score_config: score == best_score, should we change " "scoring algorithm?\n"); */ } if (score > best_score) { best_score = score; best = refnum; } return score; } int __allegro_gl_best_config(void) { return best; } allegro4.4-4.4.2/addons/allegrogl/src/texture.c000066400000000000000000001163241173507505700212700ustar00rootroot00000000000000/* This code is (C) AllegroGL contributors, and double licensed under * the GPL and zlib licenses. See gpl.txt or zlib.txt for details. */ /** \file texture.c * \brief AllegroGL texture management. */ #include #include "alleggl.h" #include "allglint.h" #include #ifdef ALLEGRO_MACOSX #include #else #include #endif static GLint allegro_gl_opengl_internal_texture_format = -1; static int allegro_gl_use_mipmapping_for_textures = 0; int __allegro_gl_use_alpha = FALSE; int __allegro_gl_flip_texture = TRUE; GLint __allegro_gl_texture_read_format[5]; GLint __allegro_gl_texture_components[5]; #define PREFIX_I "agl-tex INFO: " #define PREFIX_W "agl-tex WARNING: " #define PREFIX_E "agl-tex ERROR: " /** \internal * \ingroup texture * * Returns a string for the given OpenGL texture format. */ char const *__allegro_gl_get_format_description(GLint format) { static char str[256]; #define F(s) case s: return #s switch (format) { F(GL_ALPHA); F(GL_ALPHA4); F(GL_ALPHA8); F(GL_ALPHA12); F(GL_ALPHA16); F(GL_ALPHA16F_ARB); F(GL_ALPHA32F_ARB); F(GL_INTENSITY); F(GL_INTENSITY4); F(GL_INTENSITY8); F(GL_INTENSITY12); F(GL_INTENSITY16); F(GL_INTENSITY16F_ARB); F(GL_INTENSITY32F_ARB); F(GL_LUMINANCE); F(GL_LUMINANCE4); F(GL_LUMINANCE8); F(GL_LUMINANCE12); F(GL_LUMINANCE16); F(GL_LUMINANCE16F_ARB); F(GL_LUMINANCE32F_ARB); F(GL_LUMINANCE_ALPHA); F(GL_LUMINANCE4_ALPHA4); F(GL_LUMINANCE12_ALPHA4); F(GL_LUMINANCE8_ALPHA8); F(GL_LUMINANCE6_ALPHA2); F(GL_LUMINANCE12_ALPHA12); F(GL_LUMINANCE16_ALPHA16); F(GL_LUMINANCE_ALPHA16F_ARB); F(GL_LUMINANCE_ALPHA32F_ARB); F(GL_RGB); F(GL_R3_G3_B2); F(GL_RGB4); F(GL_RGB5); F(GL_RGB8); F(GL_RGB10); F(GL_RGB12); F(GL_RGB16); F(GL_RGB16F_ARB); F(GL_RGB32F_ARB); F(GL_RGBA); F(GL_RGBA2); F(GL_RGBA4); F(GL_RGB5_A1); F(GL_RGBA8); F(GL_RGB10_A2); F(GL_RGBA12); F(GL_RGBA16); F(GL_RGBA16F_ARB); F(GL_RGBA32F_ARB); } uszprintf(str, sizeof str, "%x", format); return str; #undef F } /* int __allegro_gl_get_num_channels(GLenum format) */ /** \internal * \ingroup texture * * Returns the number of color components for the given color fromat. * * \param format Internal color format. * * \return The number of color components. */ int __allegro_gl_get_num_channels(GLenum format) { switch (format) { case 1: case GL_ALPHA: case GL_ALPHA4: case GL_ALPHA8: case GL_ALPHA12: case GL_ALPHA16: case GL_ALPHA16F_ARB: case GL_ALPHA32F_ARB: case GL_INTENSITY: case GL_INTENSITY4: case GL_INTENSITY8: case GL_INTENSITY12: case GL_INTENSITY16: case GL_INTENSITY16F_ARB: case GL_INTENSITY32F_ARB: case GL_LUMINANCE: case GL_LUMINANCE4: case GL_LUMINANCE8: case GL_LUMINANCE12: case GL_LUMINANCE16: case GL_LUMINANCE16F_ARB: case GL_LUMINANCE32F_ARB: return 1; case 2: case GL_LUMINANCE_ALPHA: case GL_LUMINANCE4_ALPHA4: case GL_LUMINANCE12_ALPHA4: case GL_LUMINANCE8_ALPHA8: case GL_LUMINANCE6_ALPHA2: case GL_LUMINANCE12_ALPHA12: case GL_LUMINANCE16_ALPHA16: case GL_LUMINANCE_ALPHA16F_ARB: case GL_LUMINANCE_ALPHA32F_ARB: return 2; case 3: case GL_RGB: case GL_R3_G3_B2: case GL_RGB4: case GL_RGB5: case GL_RGB8: case GL_RGB10: case GL_RGB12: case GL_RGB16: case GL_RGB16F_ARB: case GL_RGB32F_ARB: return 3; case 4: case GL_RGBA: case GL_RGBA2: case GL_RGBA4: case GL_RGB5_A1: case GL_RGBA8: case GL_RGB10_A2: case GL_RGBA12: case GL_RGBA16: case GL_RGBA16F_ARB: case GL_RGBA32F_ARB: return 4; default: return 0; } } /* GLint __allegro_gl_get_texture_format_ex(BITMAP *bmp, int flags) */ /** \internal * \ingroup texture * * Returns the OpenGL internal texture format for this bitmap. * * \param bmp The bitmap to get the information of. * \param flags The flags to use. See allegro_gl_make_texture_ex() for details. * * \return The OpenGL internal texture format. */ GLint __allegro_gl_get_texture_format_ex(BITMAP *bmp, int flags) { if (!bmp) { return -1; } switch (bitmap_color_depth(bmp)) { case 32: if (flags & (AGL_TEXTURE_HAS_ALPHA | AGL_TEXTURE_FORCE_ALPHA_INTERNAL)) { return GL_RGBA8; } else { return GL_RGB8; } case 8: return GL_INTENSITY8; case 15: if (flags & AGL_TEXTURE_FORCE_ALPHA_INTERNAL) { return GL_RGB5_A1; } else { return GL_RGB5; } case 16: case 24: if (flags & AGL_TEXTURE_FORCE_ALPHA_INTERNAL) { return GL_RGBA8; } else { return GL_RGB8; } default: return -1; } return -1; } /* GLint allegro_gl_get_texture_format(BITMAP *bmp) */ /** \ingroup texture * Returns the OpenGL internal texture format for this bitmap. * If left to default, it returns the number of color components * in the bitmap. Otherwise, it simply returns the user defined * value. If the bitmap parameter is NULL, then it returns the * currently set format, or -1 if none were previously set. * 8 bpp bitmaps are assumed to be alpha channels only (GL_ALPHA8) * by default. * * \sa allegro_gl_set_texture_format(), allegro_gl_make_texture() * * \param bmp The bitmap to get the information of. * \return The OpenGL internal texture format. * * \deprecated */ GLint allegro_gl_get_texture_format(BITMAP *bmp) { if (bmp && allegro_gl_opengl_internal_texture_format == -1) { return __allegro_gl_get_texture_format_ex(bmp, __allegro_gl_use_alpha ? AGL_TEXTURE_FORCE_ALPHA_INTERNAL : 0); } return allegro_gl_opengl_internal_texture_format; } /* GLint allegro_gl_set_texture_format(GLint format) */ /** \ingroup texture * Sets the color format you'd like OpenGL to use for its textures. * You can pass any of the available GL_* constants that describe * the internal format (GL_ALPHA4...GL_RGBA16). It is recommended * that you check for the availability of the format from the client, * using allegro_gl_opengl_version(). No checking will be done as to the * validity of the format. The format is a recommendation to the driver, * so there is no guarentee that the actual format used will be the one * you chose - this is implementation dependant. This call will affect * all subsequent calls to allegro_gl_make_texture() and * allegro_gl_make_masked_texture(). * * To revert to the default AllegroGL format, pass -1 as the format. * * \sa allegro_gl_get_texture_format() * * \param format The OpenGL internal texture format. * \return The previous value of the texture format. * * \deprecated */ GLint allegro_gl_set_texture_format(GLint format) { GLint old = allegro_gl_opengl_internal_texture_format; allegro_gl_opengl_internal_texture_format = format; return old; } /* GLenum __allegro_gl_get_bitmap_type(BITMAP *bmp, int flags) */ /** \internal * \ingroup texture * * Returns the pixel packing format of the selected bitmap in OpenGL * format. OpenGL 1.1 only understands color component sizes (bytes * per color), whereas OpenGL 1.2+ can understand Allegro's packed * formats (such as 16 bit color, with 5-6-5 bit components). * * If the bitmap is not representable to the OpenGL implementation * (e.g. it cannot handle packed formats because it's earlier than * 1.2 and does not have the extension) this function returns -1. * * \sa allegro_gl_make_texture_ex() * * \param bmp The bitmap to get the OpenGL pixel type of. * \param flags The conversion flags * * \return The pixel type of the bitmap. */ GLenum __allegro_gl_get_bitmap_type(BITMAP *bmp, int flags) { int c = bitmap_color_depth(bmp); switch (c) { case 8: return __allegro_gl_texture_read_format[0]; case 15: return __allegro_gl_texture_read_format[1]; case 16: return __allegro_gl_texture_read_format[2]; case 24: return __allegro_gl_texture_read_format[3]; case 32: return __allegro_gl_texture_read_format[4]; default: TRACE(PREFIX_E "get_bitmap_type: unhandled bitmap depth: %d\n", c); return -1; } } /* GLenum __allegro_gl_get_bitmap_color_format(BITMAP *bmp, int flags) */ /** \internal * \ingroup texture * * Returns the pixel color format of the selected Allegro bitmap in OpenGL * format, given the pixel type. * * \sa allegro_gl_make_texture_ex() * * \param bmp The bitmap to get the OpenGL pixel format of. * \param flags The conversion flags * * \return The pixel type of the bitmap. */ GLenum __allegro_gl_get_bitmap_color_format(BITMAP *bmp, int flags) { int c = bitmap_color_depth(bmp); switch (c) { case 8: if (flags & AGL_TEXTURE_ALPHA_ONLY) { return GL_ALPHA; } else { return __allegro_gl_texture_components[0]; } case 15: if (flags & AGL_TEXTURE_FORCE_ALPHA_INTERNAL) { return GL_RGBA; } else { return __allegro_gl_texture_components[1]; } case 16: return __allegro_gl_texture_components[2]; case 24: return __allegro_gl_texture_components[3]; case 32: if (flags & (AGL_TEXTURE_HAS_ALPHA | AGL_TEXTURE_FORCE_ALPHA_INTERNAL)) { return GL_RGBA; } else { return __allegro_gl_texture_components[4]; } default: TRACE(PREFIX_E "get_bitmap_color_format: unhandled bitmap " "depth: %d\n", c); return -1; } } /* int allegro_gl_use_mipmapping(int enable) */ /** \ingroup texture * Tell AllegroGL to use Mipmapping or not when generating textures via * its functions. This will not affect outside OpenGL states. * Default is FALSE (off). * * \sa allegro_gl_check_texture(), allegro_gl_make_texture() * allegro_gl_make_masked_texture() * * \param enable Set to TRUE to enable mipmapping, FALSE otherwise. * \return The previous mode (either TRUE or FALSE). * * \deprecated */ int allegro_gl_use_mipmapping(int enable) { int old = allegro_gl_use_mipmapping_for_textures; allegro_gl_use_mipmapping_for_textures = enable; return old; } /* int allegro_gl_use_alpha_channel(int enable) */ /** \ingroup texture * Tell AllegroGL to use Alpha channel or not when generating textures via * its functions. This will not affect outside OpenGL states. * Default is FALSE (off). * * \sa allegro_gl_check_texture(), allegro_gl_make_texture(), * allegro_gl_make_masked_texture() * * \param enable Set to TRUE to enable textures with alpha channel, FALSE * otherwise. * \return The previous mode (either TRUE or FALSE). * * \deprecated */ int allegro_gl_use_alpha_channel(int enable) { int old = __allegro_gl_use_alpha; __allegro_gl_use_alpha = enable; return old; } /* int allegro_gl_flip_texture(int enable) */ /** \ingroup texture * Tell AllegroGL to flip the texture vertically or not when generating * textures via its functions, to conform to the usual OpenGL texture * coordinate system (increasing upwards). * Default is TRUE (on). * * \sa allegro_gl_check_texture(), allegro_gl_make_texture(), * allegro_gl_make_masked_texture() * * \param enable Set to TRUE to enable textures with alpha channel, FALSE * otherwise. * \return The previous mode (either TRUE or FALSE). * * \deprecated */ int allegro_gl_flip_texture(int enable) { int old = __allegro_gl_flip_texture; __allegro_gl_flip_texture = enable; return old; } /* int allegro_gl_check_texture_ex(int flags, BITMAP *bmp, GLuint internal_format) */ /** \ingroup texture * Checks whether the specified bitmap is of the proper size for * texturing. This checks for the card's limit on texture sizes. * * The parameters to this function are identical to those of * allegro_gl_make_texture_ex(). * * \b Important \b note: allegro_gl_check_texture does not depend on the * current state of the texture memory of the driver. This function may * return TRUE although there is not enough memory to currently make the * texture resident. You may check if the texture is actually resident with * glAreTexturesResident(). * * \sa allegro_gl_make_texture_ex() * * \param flags The bitmap conversion flags. * \param bmp The bitmap to be converted to a texture. * \param internal_format The internal format to convert to. * * \return TRUE if the bitmap can be made a texture of, FALSE otherwise. */ int allegro_gl_check_texture_ex(int flags, BITMAP *bmp, GLint internal_format) { return (allegro_gl_make_texture_ex(flags | AGL_TEXTURE_CHECK_VALID_INTERNAL, bmp, internal_format) ? TRUE : FALSE); } /* Convert flags from pre-0.2.0 to 0.2.0+ */ static int __allegro_gl_convert_flags(int flags) { flags |= AGL_TEXTURE_RESCALE; if (allegro_gl_use_mipmapping_for_textures) { flags |= AGL_TEXTURE_MIPMAP; } if (__allegro_gl_use_alpha) { flags |= AGL_TEXTURE_HAS_ALPHA; } if (__allegro_gl_flip_texture) { flags |= AGL_TEXTURE_FLIP; } if (allegro_gl_opengl_internal_texture_format == GL_ALPHA4 || allegro_gl_opengl_internal_texture_format == GL_ALPHA8 || allegro_gl_opengl_internal_texture_format == GL_ALPHA12 || allegro_gl_opengl_internal_texture_format == GL_ALPHA16 || allegro_gl_opengl_internal_texture_format == GL_ALPHA || allegro_gl_opengl_internal_texture_format == GL_INTENSITY4 || allegro_gl_opengl_internal_texture_format == GL_INTENSITY8 || allegro_gl_opengl_internal_texture_format == GL_INTENSITY12 || allegro_gl_opengl_internal_texture_format == GL_INTENSITY16 || allegro_gl_opengl_internal_texture_format == GL_INTENSITY || allegro_gl_opengl_internal_texture_format == 1) { flags |= AGL_TEXTURE_ALPHA_ONLY; } return flags; } /* int allegro_gl_check_texture(BITMAP *bmp) */ /** \ingroup texture * Checks whether the specified bitmap is of the proper size for * texturing. This checks for the card's limit on texture sizes. * * \b Important \b note: allegro_gl_check_texture does not depend on the * current state of the texture memory of the driver. This function may * return TRUE although there is not enough memory to currently make the * texture resident. You may check if the texture is actually resident with * glAreTexturesResident(). * * \sa allegro_gl_check_texture_ex(), allegro_gl_make_texture_ex() * * \param bmp The bitmap to be converted to a texture. * * \return TRUE if the bitmap can be made a texture of, FALSE otherwise. * * \deprecated */ int allegro_gl_check_texture(BITMAP *bmp) { int flags = __allegro_gl_convert_flags(0); return allegro_gl_check_texture_ex(flags, bmp, allegro_gl_opengl_internal_texture_format); } /* Integer log2 function. Not optimized for speed. */ static int log2i(int n) { int k; if (n < 1) { return -1; } k = 0; while (n >>= 1) { k++; } return k; } /* BITMAP *__allegro_gl_munge_bitmap(int flags, BITMAP *bmp, GLint *type, GLint *format) */ /** \internal * \ingroup texture * * Builds a bitmap to match the given flags. Adapts the type and format as * needed. Subbitmaps can be specified. Clipping must have already been * applied before calling this function. * * If NULL is returned, then the original bitmap can be used directly. */ BITMAP *__allegro_gl_munge_bitmap(int flags, BITMAP *bmp, int x, int y, int w, int h, GLint *type, GLint *format) { BITMAP *ret = 0, *temp = 0; int need_rescale = 0; int need_alpha = 0; int need_flip = 0; int depth = bitmap_color_depth(bmp); int force_copy = 0; const int old_w = w, old_h = h; if (flags & AGL_TEXTURE_RESCALE) { /* Check if rescaling is needed */ /* NP2 is not supported, and the texture isn't a power-of-two. * Resize the next power of 2 */ if (!allegro_gl_extensions_GL.ARB_texture_non_power_of_two && ((w & (w - 1)) || (h & (h - 1)))) { w = __allegro_gl_make_power_of_2(w); h = __allegro_gl_make_power_of_2(h); TRACE(PREFIX_I "munge_bitmap: Rescaling bitmap from " "%ix%i to %ix%i due to non-power-of-2 source size.\n", old_w, old_h, w, h); need_rescale = 1; } /* Don't go over the max texture size */ if (w > allegro_gl_info.max_texture_size) { w = allegro_gl_info.max_texture_size; TRACE(PREFIX_I "munge_bitmap: Rescaling bitmap from " "%ix%i to %ix%i due to max supported size exceed.\n", old_w, old_h, w, h); need_rescale = 1; } if (h > allegro_gl_info.max_texture_size) { h = allegro_gl_info.max_texture_size; TRACE(PREFIX_I "munge_bitmap: Rescaling bitmap from " "%ix%i to %ix%i due to max supported size exceed.\n", old_w, old_h, w, h); need_rescale = 1; } /* Voodoos don't support mipmaps for textures greater than 32x32. * If we're allowed to rescale, rescale the bitmap to 32x32. * XXX Apparently, this is a bug in one version * of the Voodoo GL driver. Need to figure out a workaround * for that. */ if (allegro_gl_info.is_voodoo && (flags & AGL_TEXTURE_MIPMAP) && (w > 32 || h > 32)) { w = MIN(32, w); h = MIN(32, h); TRACE(PREFIX_I "munge_bitmap: Rescaling bitmap from " "%ix%i to %ix%i due to Voodoo driver bug.\n", old_w, old_h, w, h); need_rescale = 1; } } /* Matrox G200 cards have a bug where rectangular textures can't have * more than 4 levels of mipmaps (max_mip == 3). This doesn't seem * to affect square textures. * * Note: Using GLU to build the mipmaps seems to work. Maybe AGL is * doing something wrong? * * Workaround: Use GLU to build the mipmaps, and force depth to 24 or * 32. */ if ( allegro_gl_info.is_matrox_g200 && (flags & AGL_TEXTURE_MIPMAP)) { int wl = log2i(w); int hl = log2i(h); if (w != h && MAX(wl, hl) > 3 && depth < 24 && !(flags & AGL_TEXTURE_ALPHA_ONLY)) { TRACE(PREFIX_I "munge_bitmap: G200 path in use.\n"); depth = 24; } } /* Do we need to flip the texture on the t axis? */ if (flags & AGL_TEXTURE_FLIP) { need_flip = 1; } /* If not supported, blit to a 24 bpp bitmap and try again */ if (*type == -1) { TRACE(PREFIX_W "munge_bitmap: using temporary 24bpp bitmap\n"); depth = 24; } /* We need a texture that can be used for masked blits. * Insert an alpha channel if one is not there. * If it's already there, replace it by 0/1 as needed. */ if ((flags & AGL_TEXTURE_MASKED) && !(flags & AGL_TEXTURE_ALPHA_ONLY)) { need_alpha = 1; switch (depth) { case 15: if (!allegro_gl_extensions_GL.EXT_packed_pixels) { depth = 32; } break; case 8: case 16: case 24: case 32: depth = 32; break; } force_copy = 1; } /* Allegro fills in 0 for the alpha channel. Matrox G200 seems to ignore * the internal format; so we need to drop down to 24-bpp if no alpha * will be needed. */ if (allegro_gl_info.is_matrox_g200 && !(flags & AGL_TEXTURE_MASKED) && !(flags & AGL_TEXTURE_HAS_ALPHA) && depth == 32) { TRACE(PREFIX_I "munge_bitmap: G200 path in use.\n"); depth = 24; force_copy = 1; } /* Do we need to do a color depth conversion or bitmap copy? */ if (depth != bitmap_color_depth(bmp) || force_copy) { TRACE(PREFIX_I "munge_bitmap: Need to perform depth conversion from %i " "to %i bpp.\n", bitmap_color_depth(bmp), depth); temp = create_bitmap_ex(depth, bmp->w, bmp->h); if (!temp) { TRACE(PREFIX_E "munge_bitmap: Unable to create temporary bitmap " "%ix%ix%i\n", bmp->w, bmp->h, depth); return NULL; } /* XXX Use palette conversion? */ if (bitmap_color_depth(bmp) == 8 && depth > 8) { int i, j; for (j = 0; j < bmp->h; j++) { for (i = 0; i < bmp->w; i++) { int c = _getpixel(bmp, i, j); putpixel(temp, i, j, makecol_depth(depth, c, c, c)); } } } else { blit(bmp, temp, 0, 0, 0, 0, bmp->w, bmp->h); } bmp = temp; *format = __allegro_gl_get_bitmap_color_format(bmp, flags); *type = __allegro_gl_get_bitmap_type(bmp, flags); } /* Nothing to do? */ if (!need_rescale && !need_alpha && !need_flip) { TRACE(PREFIX_I "munge_bitmap: No need for munging - returning %p\n", temp); /* Return depth-converte bitmap, if present */ if (temp) { return temp; } return NULL; } ret = create_bitmap_ex(depth, w, h); if (!ret) { TRACE(PREFIX_E "munge_bitmap: Unable to create result bitmap " "%ix%ix%i\n", w, h, depth); goto error; } /* No need to fill in bitmap if we're just making a query */ if (flags & AGL_TEXTURE_CHECK_VALID_INTERNAL) { if (temp) { destroy_bitmap(temp); } return ret; } /* Perform flip * I don't want to have to deal with *yet another* temporary bitmap * so instead, I fugde the line pointers around. * This will work because we require Allegro memory bitmaps anyway. */ if (need_flip) { int i; TRACE(PREFIX_I "munge_bitmap: Flipping bitmap.\n"); for (i = 0; i < bmp->h/2; i++) { unsigned char *l = bmp->line[i]; bmp->line[i] = bmp->line[bmp->h - i - 1]; bmp->line[bmp->h - i - 1] = l; } } /* Rescale bitmap */ if (need_rescale) { TRACE(PREFIX_I "munge_bitmap: Rescaling bitmap.\n"); stretch_blit(bmp, ret, x, y, old_w, old_h, 0, 0, ret->w, ret->h); } else { TRACE(PREFIX_I "munge_bitmap: Copying bitmap.\n"); blit(bmp, ret, x, y, 0, 0, w, h); } /* Restore the original bitmap, if needed */ if (need_flip && !temp) { int i; TRACE(PREFIX_I "munge_bitmap: Unflipping bitmap.\n"); for (i = 0; i < bmp->h/2; i++) { unsigned char *l = bmp->line[i]; bmp->line[i] = bmp->line[bmp->h - i - 1]; bmp->line[bmp->h - i - 1] = l; } } /* Insert alpha channel */ if (need_alpha) { int i, j; int mask = bitmap_mask_color(ret); /* alpha mask for 5.5.5.1 pixels */ int alpha = (-1) ^ makecol_depth(depth, 255, 255, 255); TRACE(PREFIX_I "munge_bitmap: Inserting alpha channel.\n"); for (j = 0; j < h; j++) { for (i = 0; i < w; i++) { int pix; switch (depth) { case 32: pix = _getpixel32(ret, i, j); if (pix == mask) { pix = 0; } else if ((flags & AGL_TEXTURE_HAS_ALPHA) == 0) { int r, g, b; r = getr32(pix); g = getg32(pix); b = getb32(pix); pix = makeacol32(r, g, b, 255); } _putpixel32(ret, i, j, pix); break; case 15: pix = _getpixel16(ret, i, j); if (pix == mask) { pix = 0; } else { pix |= alpha; } _putpixel16(temp, i, j, pix); break; default: /* Shouldn't actually come here */ ASSERT(0); } } } } error: if (temp) { destroy_bitmap(temp); } return ret; } /* Perform the actual texture upload. Helper for agl_make_texture_ex(). */ static GLuint do_texture_upload(BITMAP *bmp, GLuint tex, GLint internal_format, GLint format, GLint type, int flags) { int bytes_per_pixel = BYTES_PER_PIXEL(bitmap_color_depth(bmp)); GLint saved_row_length; GLint saved_alignment; GLenum target = GL_TEXTURE_2D; glBindTexture(target, tex); /* Handle proxy texture checks */ if (flags & AGL_TEXTURE_CHECK_VALID_INTERNAL) { /* allegro_gl_check_texture is broken with GL drivers based * on Mesa. It seems this is a Mesa bug... */ if (allegro_gl_info.is_mesa_driver) { AGL_LOG(1, "* Note * check_texture: Mesa driver detected: " "PROXY_TEXTURE_2D tests are skipped\n"); return tex; } else { glTexImage2D(GL_PROXY_TEXTURE_2D, 0, internal_format, bmp->w, bmp->h, 0, format, type, NULL); glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_COMPONENTS, &internal_format); return (internal_format ? tex : 0); } } /* Set up pixel transfer mode */ glGetIntegerv(GL_UNPACK_ROW_LENGTH, &saved_row_length); glGetIntegerv(GL_UNPACK_ALIGNMENT, &saved_alignment); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); TRACE(PREFIX_I "do_texture_upload: Making texture: bpp: %i\n", bitmap_color_depth(bmp)); /* Generate mipmaps, if needed */ if (flags & AGL_TEXTURE_MIPMAP) { if (allegro_gl_extensions_GL.SGIS_generate_mipmap) { /* Easy way out - let the driver do it ;) * We do need to set high-qual mipmap generation though. */ glHint(GL_GENERATE_MIPMAP_HINT, GL_NICEST); glTexParameteri(target, GL_GENERATE_MIPMAP, GL_TRUE); TRACE(PREFIX_I "do_texture_upload: Using SGIS_generate_mipmap for " "mipmap generation.\n"); } else if (allegro_gl_info.is_matrox_g200 && (flags & AGL_TEXTURE_MIPMAP) && (bitmap_color_depth(bmp) >= 24 || bitmap_color_depth(bmp) == 8) && (bmp->w != bmp->h)) { /* Matrox G200 has issues with our mipmapping code. Use GLU if we * can. */ TRACE(PREFIX_I "do_texture_upload: Using GLU for mipmaps.\n"); glPixelStorei(GL_UNPACK_ROW_LENGTH, bmp->h > 1 ? (bmp->line[1] - bmp->line[0]) / bytes_per_pixel : bmp->w); glPixelStorei(GL_UNPACK_ROW_LENGTH, (bmp->line[1] - bmp->line[0]) / bytes_per_pixel); gluBuild2DMipmaps(GL_TEXTURE_2D, internal_format, bmp->w, bmp->h, format, type, bmp->line[0]); } else { int w = bmp->w; int h = bmp->h; int depth = bitmap_color_depth(bmp); /* The driver can't generate mipmaps for us. We can't rely on GLU * since the Win32 version doesn't support any of the new pixel * formats. Instead, we'll use our own downsampler (which only * has to work on Allegro BITMAPs) */ BITMAP *temp = create_bitmap_ex(depth, w / 2, h / 2); /* We need to generate mipmaps up to 1x1 - compute the number * of levels we need. */ int num_levels = log2i(MAX(bmp->w, bmp->h)); int i, x, y; BITMAP *src, *dest; TRACE(PREFIX_I "do_texture_upload: Using Allegro for " "mipmap generation.\n"); if (!temp) { TRACE(PREFIX_E "do_texture_upload: Unable to create " "temporary bitmap sized %ix%ix%i for mipmap generation!", w / 2, h / 2, depth); tex = 0; goto end; } src = bmp; dest = temp; for (i = 1; i <= num_levels; i++) { for (y = 0; y < h; y += 2) { for (x = 0; x < w; x += 2) { int r, g, b, a; int pix[4]; int avg; pix[0] = getpixel(src, x, y); pix[1] = getpixel(src, x + 1, y); pix[2] = getpixel(src, x, y + 1); pix[3] = getpixel(src, x + 1, y + 1); if (w == 1) { pix[1] = pix[0]; pix[3] = pix[2]; } if (h == 1) { pix[2] = pix[0]; pix[3] = pix[1]; } if (flags & AGL_TEXTURE_ALPHA_ONLY) { avg = (pix[0] + pix[1] + pix[2] + pix[3] + 2) / 4; } else { r = (getr_depth(depth, pix[0]) + getr_depth(depth, pix[1]) + getr_depth(depth, pix[2]) + getr_depth(depth, pix[3]) + 2) / 4; g = (getg_depth(depth, pix[0]) + getg_depth(depth, pix[1]) + getg_depth(depth, pix[2]) + getg_depth(depth, pix[3]) + 2) / 4; b = (getb_depth(depth, pix[0]) + getb_depth(depth, pix[1]) + getb_depth(depth, pix[2]) + getb_depth(depth, pix[3]) + 2) / 4; a = (geta_depth(depth, pix[0]) + geta_depth(depth, pix[1]) + geta_depth(depth, pix[2]) + geta_depth(depth, pix[3]) + 2) / 4; avg = makeacol_depth(depth, r, g, b, a); } putpixel(dest, x / 2, y / 2, avg); } } src = temp; /* Note - we round down; we're still compatible with * ARB_texture_non_power_of_two. */ w = MAX(w / 2, 1); h = MAX(h / 2, 1); TRACE(PREFIX_I "do_texture_upload: Unpack row length: %li.\n", (temp->h > 1) ? (long int)((temp->line[1] - temp->line[0]) / bytes_per_pixel) : temp->w); glPixelStorei(GL_UNPACK_ROW_LENGTH, temp->h > 1 ? (temp->line[1] - temp->line[0]) / bytes_per_pixel : temp->w); glTexImage2D(GL_TEXTURE_2D, i, internal_format, w, h, 0, format, type, temp->line[0]); TRACE(PREFIX_I "do_texture_upload: Mipmap level: %i, " "size: %i x %i\n", i, w, h); TRACE(PREFIX_I "do_texture_upload: Uploaded texture: level %i, " "internalformat: %s, %ix%i, format: 0x%x, type: 0x%x." "\n", i, __allegro_gl_get_format_description(internal_format), bmp->w, bmp->h, format, type); } destroy_bitmap(temp); } } glPixelStorei(GL_UNPACK_ROW_LENGTH, (bmp->h > 1) ? (bmp->line[1] - bmp->line[0]) / bytes_per_pixel : bmp->w); TRACE(PREFIX_I "do_texture_upload: Unpack row length: %li.\n", (bmp->h > 1) ? (long int)((bmp->line[1] - bmp->line[0]) / bytes_per_pixel) : bmp->w); /* Upload the base texture */ glGetError(); glTexImage2D(GL_TEXTURE_2D, 0, internal_format, bmp->w, bmp->h, 0, format, type, bmp->line[0]); TRACE(PREFIX_I "do_texture_upload: Uploaded texture: level 0, " "internalformat: %s, %ix%i, format: 0x%x, type: 0x%x.\n", __allegro_gl_get_format_description(internal_format), bmp->w, bmp->h, format, type); TRACE(PREFIX_I "do_texture_upload: GL Error code: 0x%x\n", glGetError()); if (!(flags & AGL_TEXTURE_MIPMAP)) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); } end: /* Restore state */ glPixelStorei(GL_UNPACK_ROW_LENGTH, saved_row_length); glPixelStorei(GL_UNPACK_ALIGNMENT, saved_alignment); return tex; } /* GLuint allegro_gl_make_texture_ex(int flag, BITMAP *bmp, GLint internal_format) */ /** \ingroup texture * Uploads an Allegro BITMAP to the GL driver as a texture. * * The bitmap must be a memory bitmap (note that it can be a subbitmap). * * Each bitmap will be converted to a single texture object, with all its * size limitations imposed by the video driver and hardware. * * The bitmap should conform to the size limitations imposed by the video * driver. That is, if ARB_texture_non_power_of_two is not supported, * then the BITMAP must be power-of-two sized. Otherwise, AllegroGL * will pick the best format for the bitmap. * * The original bitmap will NOT be modified. * * The flags parameter controls how the texture is generated. It can be a * logical OR (|) of any of the following: * * #AGL_TEXTURE_MIPMAP * #AGL_TEXTURE_HAS_ALPHA * #AGL_TEXTURE_FLIP * #AGL_TEXTURE_MASKED * #AGL_TEXTURE_RESCALE * * AllegroGL will create a texture with the specified texel format. * The texel format should be any of the valid formats that can be * specified to glTexImage2D(). No validity checks will be performed * by AllegroGL. If you want AllegroGL to automatically determine the * format to use based on the BITMAP, use -1 as the format specifier. * * A valid GL Rendering Context must have been established, which means you * cannot use this function before having called set_gfx_mode() with a valid * OpenGL mode. * * \b Important \b note: on 32 bit bitmap in RGBA mode, the alpha channel * created by Allegro is set to all 0 by default. This will cause the * texture to not show up in 32bpp modes if alpha is set. You will need * to fill in the alpha channel manually if you need an alpha channel. * * \param bmp The bitmap to be converted to a texture. * \param flags The conversion flags. * \param internal_format The texture format to convert to. * * \return GLuint The texture handle, or 0 on failure */ GLuint allegro_gl_make_texture_ex(int flags, BITMAP *bmp, GLint internal_format) { GLuint tex = 0, ret = 0; BITMAP *temp = NULL; GLint type; GLint format; GLint old_tex; /* Print the parameters */ #ifdef DEBUGMODE char buf[1024] = ""; # define PFLAG(name) if (flags & name) strcat(buf, #name "|"); PFLAG(AGL_TEXTURE_MIPMAP); PFLAG(AGL_TEXTURE_HAS_ALPHA); PFLAG(AGL_TEXTURE_FLIP); PFLAG(AGL_TEXTURE_MASKED); PFLAG(AGL_TEXTURE_RESCALE); PFLAG(AGL_TEXTURE_ALPHA_ONLY); # undef PFLAG TRACE(PREFIX_I "make_texture_ex: flags: %s, bitmap %ix%i, %i bpp.\n", buf, bmp ? bmp->w : 0, bmp ? bmp->h : 0, bmp ? bitmap_color_depth(bmp) : 0); if (internal_format == -1) { TRACE(PREFIX_I "internalformat: AUTO\n"); } else { TRACE(PREFIX_I "internalformat: %s\n", __allegro_gl_get_format_description(internal_format)); } #endif /* Basic parameter checks */ if (!__allegro_gl_valid_context) return 0; if (!bmp) { return 0; } glGetIntegerv(GL_TEXTURE_2D_BINDING, &old_tex); /* Voodoo cards don't seem to support mipmaps for textures over 32x32... */ if ((bmp->w > 32 || bmp->h > 32) && (allegro_gl_info.is_voodoo)) { /* Disable mipmapping if the user didn't allow us to rescale */ if (!(flags & AGL_TEXTURE_RESCALE)) { TRACE(PREFIX_I "make_texture_ex: Voodoo card detected && texture " "size > 32 texels && no rescaling. Disabling mipmaps.\n"); flags &= ~AGL_TEXTURE_MIPMAP; } } /* Check the maximum texture size */ if (bmp->w > allegro_gl_info.max_texture_size || bmp->h > allegro_gl_info.max_texture_size) { if ((flags & AGL_TEXTURE_RESCALE) == 0) { TRACE(PREFIX_I "make_texture_ex: Max texture size exceeded but no " "rescaling allowed. Returning 0 (unsupported).\n"); return 0; } } /* Check power-of-2 */ if (((bmp->w & (bmp->w - 1)) || (bmp->h & (bmp->h - 1))) && !(flags & AGL_TEXTURE_RESCALE) && !allegro_gl_extensions_GL.ARB_texture_non_power_of_two) { TRACE(PREFIX_I "make_texture_ex: Non-power-of-2 sized bitmap provided, " "no rescaling allowed, and ARB_texture_non_power_of_two " "unsupported. Returning 0 (unsupported).\n"); return 0; } /* Get OpenGL format and type for this pixel data */ format = __allegro_gl_get_bitmap_color_format(bmp, flags); type = __allegro_gl_get_bitmap_type(bmp, flags); if (flags & AGL_TEXTURE_ALPHA_ONLY) { type = GL_UNSIGNED_BYTE; if (internal_format == GL_ALPHA || internal_format == GL_ALPHA4 || internal_format == GL_ALPHA8) { format = GL_ALPHA; } else if (internal_format == GL_INTENSITY || internal_format == GL_INTENSITY4 || internal_format == GL_INTENSITY8) { format = GL_RED; } else if (internal_format == GL_LUMINANCE || internal_format == GL_LUMINANCE4 || internal_format == GL_LUMINANCE8) { format = GL_LUMINANCE; } /* Alpha bitmaps must be 8-bpp */ if (bitmap_color_depth(bmp) != 8) { return 0; } } if (flags & AGL_TEXTURE_MASKED) { flags |= AGL_TEXTURE_FORCE_ALPHA_INTERNAL; } TRACE(PREFIX_I "make_texture_ex: Preselected texture format: %s, " "type: 0x%x\n", __allegro_gl_get_format_description(format), type); /* Munge the bitmap if needed (rescaling, alpha channel, etc) */ temp = __allegro_gl_munge_bitmap(flags, bmp, 0, 0, bmp->w, bmp->h, &type, &format); if (temp) { bmp = temp; } if (internal_format == -1) { internal_format = __allegro_gl_get_texture_format_ex(bmp, flags); TRACE(PREFIX_I "make_texture_ex: Picked internalformat: %s\n", __allegro_gl_get_format_description(internal_format)); } if (internal_format == -1) { TRACE(PREFIX_E "make_texture_ex: Invalid internal format!: " "%s\n", __allegro_gl_get_format_description(internal_format)); goto end; } TRACE(PREFIX_I "make_texture_ex: dest format=%s, source format=%s, " "type=0x%x\n", __allegro_gl_get_format_description(internal_format), __allegro_gl_get_format_description(format), (int)type); /* ATI Radeon 7000 inverts R and B components when generating mipmaps and * the internal format is GL_RGB8, but only on mipmaps. Instead, we'll use * GL_RGBA8. This works for bitmaps of depth <= 24. For 32-bpp bitmaps, * some additional tricks are needed: We must fill in alpha with 255. */ if (allegro_gl_info.is_ati_radeon_7000 && (flags & AGL_TEXTURE_MIPMAP) && internal_format == GL_RGB8 && allegro_gl_extensions_GL.SGIS_generate_mipmap) { int i, j; int depth = bitmap_color_depth(bmp); TRACE(PREFIX_I "make_texture_ex: ATI Radeon 7000 detected, mipmapping " "used, SGIS_generate_mipmap available and selected " "internalformat is GL_RGB8 but format is GL_RGBA. Working around " "ATI driver bug by upgrading bitmap to 32-bpp and using GL_RGBA8 " "instead.\n"); if (depth == 32) { /* Create temp bitmap if not already there */ if (!temp) { temp = create_bitmap_ex(depth, bmp->w, bmp->h); if (!temp) { TRACE(PREFIX_E "make_texture_ex: Unable to allocate " "memory for temporary bitmap (Radeon 7000 path)!\n"); goto end; } blit(bmp, temp, 0, 0, 0, 0, bmp->w, bmp->h); bmp = temp; } /* Slow path, until ATI finally gets around to fixing their * drivers. * * Note: If destination internal format was GL_RGBx, then no masking * code is needed. */ for (j = 0; j < bmp->h; j++) { for (i = 0; i < bmp->w; i++) { int pix = _getpixel32(bmp, i, j); _putpixel32(bmp, i, j, makeacol32(getr32(pix), getg32(pix), getb32(pix), 255)); } } } internal_format = GL_RGBA8; } /* Generate the texture */ glGenTextures(1, &tex); if (!tex) { TRACE(PREFIX_E "make_texture_ex: Unable to create GL texture!\n"); goto end; } ret = do_texture_upload(bmp, tex, internal_format, format, type, flags); end: if (temp) { destroy_bitmap(temp); } if (!ret && tex) { glDeleteTextures(1, &tex); } glBindTexture(GL_TEXTURE_2D, old_tex); return tex; } /* GLuint allegro_gl_make_texture(BITMAP *bmp) */ /** \ingroup texture * * Uploads an Allegro BITMAP to the GL driver as a texture. * * \deprecated * * \sa allegro_gl_make_texture_ex() */ GLuint allegro_gl_make_texture(BITMAP *bmp) { int flags = __allegro_gl_convert_flags(0); return allegro_gl_make_texture_ex(flags, bmp, allegro_gl_opengl_internal_texture_format); } /* GLuint allegro_gl_make_masked_texture(BITMAP *bmp) */ /** \ingroup texture * * Uploads an Allegro BITMAP to the GL driver as a texture. * * \deprecated * * \sa allegro_gl_make_texture_ex() */ GLuint allegro_gl_make_masked_texture(BITMAP *bmp) { int flags = __allegro_gl_convert_flags(AGL_TEXTURE_MASKED); return allegro_gl_make_texture_ex(flags, bmp, allegro_gl_opengl_internal_texture_format); } /* GLenum allegro_gl_get_bitmap_type(BITMAP *bmp) */ /** \internal * \ingroup texture * * Returns the pixel packing format of the selected bitmap in OpenGL * format. OpenGL 1.1 only understands color component sizes (bytes * per color), whereas OpenGL 1.2+ can understand Allegro's packed * formats (such as 16 bit color, with 5-6-5 bit components). * * If the bitmap is not representable to the OpenGL implementation * (e.g. it cannot handle packed formats because it's earlier than * 1.2 and does not have the extension) this function returns -1. * * \sa allegro_gl_make_texture_ex() * * \param bmp The bitmap to get the OpenGL pixel type of. * * \return The pixel type of the bitmap. * * \deprecated This function is deprecated and should no longer be used. */ GLenum allegro_gl_get_bitmap_type(BITMAP *bmp) { int flags = __allegro_gl_convert_flags(0); return __allegro_gl_get_bitmap_type(bmp, flags); } /* GLenum allegro_gl_get_bitmap_color_format(BITMAP *bmp) */ /** \internal * \ingroup texture * * Returns the pixel color format of the selected Allegro bitmap in OpenGL * format, given the pixel type. * * \sa allegro_gl_make_texture_ex() * * \param bmp The bitmap to get the OpenGL pixel format of. * * \return The pixel type of the bitmap. * * \deprecated This function is deprecated and should no longer be used. */ GLenum allegro_gl_get_bitmap_color_format(BITMAP *bmp) { int flags = __allegro_gl_convert_flags(0); return __allegro_gl_get_bitmap_color_format(bmp, flags); } allegro4.4-4.4.2/addons/allegrogl/src/videovtb.c000066400000000000000000001524051173507505700214120ustar00rootroot00000000000000/* This code is (C) AllegroGL contributors, and double licensed under * the GPL and zlib licenses. See gpl.txt or zlib.txt for details. */ /** \file videovtb.c * \brief video bitmaps (ie. texture rendering) vtable * Some of these don't work correctly or will be very slow. */ #include #include #include #ifdef ALLEGRO_WINDOWS #include #endif #include "alleggl.h" #include "allglint.h" #include "glvtable.h" #include #ifdef ALLEGRO_MACOSX #include #else #include #endif #define MASKED_BLIT 1 #define BLIT 2 #define TRANS 3 static GFX_VTABLE allegro_gl_video_vtable; /* Counter for video bitmaps. screen = 1 */ static int video_bitmap_count = 2; static int __allegro_gl_video_bitmap_bpp = -1; extern BITMAP *__agl_drawing_pattern_bmp; BITMAP *old_pattern = NULL; void allegro_gl_destroy_video_bitmap(BITMAP *bmp); static int allegro_gl_make_video_bitmap_helper1(int w, int h, int x, int y, GLint target, AGL_VIDEO_BITMAP **pvid) { int internal_format; int bpp; if (__allegro_gl_video_bitmap_bpp == -1) { bpp = bitmap_color_depth(screen); } else { bpp = __allegro_gl_video_bitmap_bpp; } (*pvid) = malloc(sizeof(AGL_VIDEO_BITMAP)); if (!(*pvid)) return -1; memset(*pvid, 0, sizeof(AGL_VIDEO_BITMAP)); /* Create associated bitmap */ (*pvid)->memory_copy = create_bitmap_ex(bpp, w, h); if (!(*pvid)->memory_copy) return -1; (*pvid)->format = __allegro_gl_get_bitmap_color_format((*pvid)->memory_copy, AGL_TEXTURE_HAS_ALPHA); (*pvid)->type = __allegro_gl_get_bitmap_type((*pvid)->memory_copy, 0); internal_format = __allegro_gl_get_texture_format_ex((*pvid)->memory_copy, AGL_TEXTURE_HAS_ALPHA); (*pvid)->target = target; /* Fill in some values in the bitmap to make it act as a subbitmap */ (*pvid)->width = w; (*pvid)->height = h; (*pvid)->x_ofs = x; (*pvid)->y_ofs = y; /* Make a texture out of it */ glGenTextures(1, &((*pvid)->tex)); if (!((*pvid)->tex)) return -1; glEnable((*pvid)->target); glBindTexture((*pvid)->target, ((*pvid)->tex)); glTexImage2D((*pvid)->target, 0, internal_format, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); /* By default, use the Allegro filtering mode - ie: Nearest */ glTexParameteri((*pvid)->target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri((*pvid)->target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); /* Clamping removed because we want video bitmaps that are set for patterned drawing to be GL_REPEAT (default wrapping mode). Doesn't seem to break anything. */ #if 0 /* Clamp to edge */ { GLenum clamp = GL_CLAMP_TO_EDGE; if (!allegro_gl_extensions_GL.SGIS_texture_edge_clamp) { clamp = GL_CLAMP; } glTexParameteri((*pvid)->target, GL_TEXTURE_WRAP_S, clamp); glTexParameteri((*pvid)->target, GL_TEXTURE_WRAP_T, clamp); } #endif glDisable((*pvid)->target); if (allegro_gl_extensions_GL.EXT_framebuffer_object) { glGenFramebuffersEXT(1, &((*pvid)->fbo)); if (!(*pvid)->fbo) { glDeleteTextures(1, &((*pvid)->tex)); return -1; } glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, (*pvid)->fbo); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, (*pvid)->target, (*pvid)->tex, 0); if (glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT) { /* Some FBO implementation limitation was hit, will use normal textures. */ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); glDeleteFramebuffersEXT(1, &((*pvid)->fbo)); (*pvid)->fbo = 0; return 0; } glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); } else { (*pvid)->fbo = 0; } return 0; } static int allegro_gl_make_video_bitmap_helper0(int w, int h, int x, int y, AGL_VIDEO_BITMAP **pvid) { int is_power_of_2 = (!(w & (w - 1)) && !(h & (h - 1))); int texture_rect_available = allegro_gl_extensions_GL.ARB_texture_rectangle #ifdef ALLEGRO_MACOSX || allegro_gl_extensions_GL.EXT_texture_rectangle #endif || allegro_gl_extensions_GL.NV_texture_rectangle; GLint max_rect_texture_size = 0; if (texture_rect_available) { glGetIntegerv(GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB, &max_rect_texture_size); } if (w <= allegro_gl_info.max_texture_size && h <= allegro_gl_info.max_texture_size) { if (allegro_gl_extensions_GL.ARB_texture_non_power_of_two || is_power_of_2) { if (allegro_gl_make_video_bitmap_helper1(w, h, x, y, GL_TEXTURE_2D, pvid)) { return -1; } } else if (texture_rect_available && w <= max_rect_texture_size && h <= max_rect_texture_size) { if (allegro_gl_make_video_bitmap_helper1(w, h, x, y, GL_TEXTURE_RECTANGLE_ARB, pvid)) { return -1; } } else { /* NPO2 textures are not suppored by the driver in any way. * Split the bitmap into smaller POT bitmaps. */ const unsigned int BITS = sizeof(int) * CHAR_BIT; unsigned int i, j; unsigned int w1, h1; unsigned int x1, y1; unsigned int p1, p2; /* Find the POTs using bits. */ y1 = 0; for (i = 0; i < BITS; i++) { p1 = 1 << i; if (h & p1) h1 = p1; else continue; x1 = 0; for (j = 0; j < BITS; j++) { p2 = 1 << j; if (w & p2) w1 = p2; else continue; if (allegro_gl_make_video_bitmap_helper0(w1, h1, x + x1, y + y1, pvid)) { return -1; } do { pvid = &((*pvid)->next); } while (*pvid); x1 += w1; } y1 += h1; } } } else { /* Texture is too big to fit. Split it in 4 and try again. */ int w1, w2, h1, h2; w2 = w / 2; w1 = w - w2; h2 = h / 2; h1 = h - h2; /* Even a 1x1 texture didn't work? Bail*/ if (!w2 && !h2) { return -1; } /* Top-left corner */ if (allegro_gl_make_video_bitmap_helper0(w1, h1, x, y, pvid)) { return -1; } do { pvid = &((*pvid)->next); } while (*pvid); /* Top-right corner */ if (w2) { if (allegro_gl_make_video_bitmap_helper0(w2, h1, x + w1, y, pvid)) { return -1; } do { pvid = &((*pvid)->next); } while (*pvid); } /* Bottom-left corner */ if (h2) { if (allegro_gl_make_video_bitmap_helper0(w1, h2, x, y + h1, pvid)) { return -1; } do { pvid = &((*pvid)->next); } while (*pvid); } /* Bottom-right corner */ if (w2 && h2) { if (allegro_gl_make_video_bitmap_helper0(w2, h2, x + w1, y + h1, pvid)) { return -1; } do { pvid = &((*pvid)->next); } while (*pvid); } } return 0; } /* Will make a (potentially piece-wise) texture out of the specified bitmap * Source -must- be a memory bitmap or memory subbitmap (created by Allegro * only). * */ static BITMAP *allegro_gl_make_video_bitmap(BITMAP *bmp) { /* Grab a pointer to the bitmap data to patch */ void *ptr = &bmp->extra; AGL_VIDEO_BITMAP **pvid = (AGL_VIDEO_BITMAP**)ptr; /* Convert bitmap to texture */ if (allegro_gl_make_video_bitmap_helper0(bmp->w, bmp->h, 0, 0, pvid)) { goto agl_error; } return bmp; agl_error: allegro_gl_destroy_video_bitmap(bmp); return NULL; } /* void allegro_gl_destroy_video_bitmap(BITMAP *bmp) */ /** destroy_video_bitmap() overload. * Will destroy the video bitmap. You mustn't use the BITMAP pointer after * calling this function. */ void allegro_gl_destroy_video_bitmap(BITMAP *bmp) { AGL_VIDEO_BITMAP *vid = bmp ? bmp->extra : NULL, *next; if (!bmp) return; while (vid) { if (vid->memory_copy) destroy_bitmap(vid->memory_copy); if (vid->tex) glDeleteTextures(1, &vid->tex); if (vid->fbo) glDeleteFramebuffersEXT(1, &vid->fbo); next = vid->next; free(vid); vid = next; } free(bmp->vtable); free(bmp); return; } /* BITMAP *allegro_gl_create_video_bitmap(int w, int h) */ /** create_video_bitmap() overload. * This function will create a video bitmap using texture memory. * Video bitmaps do not currently share space with the frame buffer (screen). * Video bitmaps are lost when switching screen modes. */ BITMAP *allegro_gl_create_video_bitmap(int w, int h) { GFX_VTABLE *vtable; BITMAP *bitmap; bitmap = malloc(sizeof(BITMAP) + sizeof(char *)); if (!bitmap) return NULL; bitmap->dat = NULL; bitmap->w = bitmap->cr = w; bitmap->h = bitmap->cb = h; bitmap->clip = TRUE; bitmap->cl = bitmap->ct = 0; bitmap->write_bank = bitmap->read_bank = NULL; /* We should keep tracks of allocated bitmaps for the ref counter */ bitmap->id = BMP_ID_VIDEO | video_bitmap_count; bitmap->extra = NULL; bitmap->x_ofs = 0; bitmap->y_ofs = 0; bitmap->seg = _default_ds(); bitmap->line[0] = NULL; bitmap->vtable = NULL; if (!allegro_gl_make_video_bitmap(bitmap)) { return NULL; } video_bitmap_count++; /* XXX We ought to leave the Allegro values intact * Avoids bad interaction with correct Allegro programs. */ vtable = malloc(sizeof(struct GFX_VTABLE)); *vtable = allegro_gl_video_vtable; if (__allegro_gl_video_bitmap_bpp == -1) { vtable->color_depth = bitmap_color_depth(screen); } else { vtable->color_depth = __allegro_gl_video_bitmap_bpp; } switch (vtable->color_depth) { case 8: vtable->mask_color = MASK_COLOR_8; break; case 15: vtable->mask_color = MASK_COLOR_15; break; case 16: vtable->mask_color = MASK_COLOR_16; break; case 24: vtable->mask_color = MASK_COLOR_24; break; case 32: vtable->mask_color = MASK_COLOR_32; break; } bitmap->vtable = vtable; return bitmap; } /* allegro_gl_set_video_bitmap_color_depth(int bpp) */ /** \ingroup bitmap * Sets the color depth you'd like AllegroGL to use for video bitmaps. * This function lets you create video bitmaps of any color depth using * allegro's create_video_bitmap(). You can create a RGBA8 bitmap and take * advantage of hardware accelerated blending, no matter what the current color * depth is. * This call will affect all subsequent calls to create_video_bitmap(). * * Default value for the video bitmap color depth if the color depth of the * screen bitmap. To revert to the default color depth, pass -1. * * \param bpp Color depth in btis per pixel. * \return The previous value of the video bitmap color depth. */ GLint allegro_gl_set_video_bitmap_color_depth(int bpp) { GLint old_val = __allegro_gl_video_bitmap_bpp; __allegro_gl_video_bitmap_bpp = bpp; return old_val; } /* static void allegro_gl_video_acquire(struct BITMAP *bmp) */ /** \ingroup glvtable * acquire_bitmap(bmp) overload. * This doesn't do anything, since OpenGL textures * doesn't need locking. You don't need to call this function * in your program. */ static void allegro_gl_video_acquire(struct BITMAP *bmp) {} /* static void allegro_gl_video_release(struct BITMAP *bmp) */ /** \ingroup glvtable * release_bitmap(bmp) overload. * This doesn't do anything, since OpenGL textures * doesn't need locking. You don't need to call this function * in your program. */ static void allegro_gl_video_release(struct BITMAP *bmp) {} static void set_drawing_pattern(void) { if (_drawing_pattern && !is_memory_bitmap(_drawing_pattern)) { old_pattern = _drawing_pattern; drawing_mode(_drawing_mode, __agl_drawing_pattern_bmp, _drawing_x_anchor, _drawing_y_anchor); } } static void unset_drawing_pattern(void) { if (old_pattern) { drawing_mode(_drawing_mode, old_pattern, _drawing_x_anchor, _drawing_y_anchor); old_pattern = NULL; } } static int allegro_gl_video_getpixel(struct BITMAP *bmp, int x, int y) { int pix = -1; AGL_VIDEO_BITMAP *vid; AGL_LOG(2, "glvtable.c:allegro_gl_screen_getpixel\n"); if (is_sub_bitmap(bmp)) { x += bmp->x_ofs; y += bmp->y_ofs; } if (x < bmp->cl || x >= bmp->cr || y < bmp->ct || y >= bmp->cb) { return -1; } vid = bmp->extra; while (vid) { if (vid->x_ofs <= x && vid->y_ofs <= y && vid->x_ofs + vid->memory_copy->w > x && vid->y_ofs + vid->memory_copy->h > y) { pix = getpixel(vid->memory_copy, x - vid->x_ofs, y - vid->y_ofs); break; } vid = vid->next; } if (pix != -1) { return pix; } return -1; } static void update_texture_memory(AGL_VIDEO_BITMAP *vid, int x1, int y1, int x2, int y2) { GLint saved_row_length; GLint saved_alignment; GLint type; GLint format; int bpp; BITMAP *temp = NULL; BITMAP *vbmp = vid->memory_copy;; glGetIntegerv(GL_UNPACK_ROW_LENGTH, &saved_row_length); glGetIntegerv(GL_UNPACK_ALIGNMENT, &saved_alignment); bpp = BYTES_PER_PIXEL(bitmap_color_depth(vid->memory_copy)); format = vid->format; type = vid->type; glColor4ub(255, 255, 255, 255); /* If packed pixels (or GL 1.2) isn't supported, then we need to convert * the bitmap into something GL can understand - 24-bpp should do it. */ if (!allegro_gl_extensions_GL.EXT_packed_pixels && bitmap_color_depth(vbmp) < 24) { temp = create_bitmap_ex(24, vbmp->w, vbmp->h); if (!temp) return; blit(vbmp, temp, 0, 0, 0, 0, temp->w, temp->h); vbmp = temp; bpp = BYTES_PER_PIXEL(bitmap_color_depth(vbmp)); format = __allegro_gl_get_bitmap_color_format(vbmp, 0); type = __allegro_gl_get_bitmap_type(vbmp, 0); } glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glPixelStorei(GL_UNPACK_ROW_LENGTH, vbmp->h > 1 ? (vbmp->line[1] - vbmp->line[0]) / bpp : vbmp->w); glEnable(vid->target); glBindTexture(vid->target, vid->tex); glTexSubImage2D(vid->target, 0, x1, y1, x2 - x1 + 1, y2 - y1 + 1, format, type, vbmp->line[y1] + x1 * bpp); glBindTexture(vid->target, 0); glDisable(vid->target); if (temp) destroy_bitmap(temp); glPixelStorei(GL_UNPACK_ROW_LENGTH, saved_row_length); glPixelStorei(GL_UNPACK_ALIGNMENT, saved_alignment); } static void allegro_gl_video_putpixel(struct BITMAP *bmp, int x, int y, int color) { AGL_VIDEO_BITMAP *vid; if (is_sub_bitmap(bmp)) { x += bmp->x_ofs; y += bmp->y_ofs; } if (x < bmp->cl || x >= bmp->cr || y < bmp->ct || y >= bmp->cb) { return; } vid = bmp->extra; while (vid) { if (vid->x_ofs <= x && vid->y_ofs <= y && vid->x_ofs + vid->memory_copy->w > x && vid->y_ofs + vid->memory_copy->h > y) { set_drawing_pattern(); putpixel(vid->memory_copy, x - vid->x_ofs, y - vid->y_ofs, color); unset_drawing_pattern(); update_texture_memory(vid, x - vid->x_ofs, y - vid->y_ofs, x - vid->x_ofs, y - vid->y_ofs); break; } vid = vid->next; } return; } static void allegro_gl_video_vline(BITMAP *bmp, int x, int y1, int y2, int color) { AGL_VIDEO_BITMAP *vid; AGL_LOG(2, "glvtable.c:allegro_gl_video_vline\n"); vid = bmp->extra; if (is_sub_bitmap(bmp)) { x += bmp->x_ofs; y1 += bmp->y_ofs; y2 += bmp->y_ofs; } if (x < bmp->cl || x >= bmp->cr) { return; } if (y1 > y2) { int temp = y1; y1 = y2; y2 = temp; } if (y1 < bmp->ct) { y1 = bmp->ct; } if (y2 >= bmp->cb) { y2 = bmp->cb - 1; } while (vid) { BITMAP *vbmp = vid->memory_copy; int _y1, _y2, _x; if (vid->x_ofs > x || vid->y_ofs > y2 || vid->x_ofs + vbmp->w <= x || vid->y_ofs + vbmp->h <= y1) { vid = vid->next; continue; } _y1 = MAX(y1, vid->y_ofs) - vid->y_ofs; _y2 = MIN(y2, vid->y_ofs + vbmp->h - 1) - vid->y_ofs; _x = x - vid->x_ofs; set_drawing_pattern(); vline(vbmp, _x, _y1, _y2, color); unset_drawing_pattern(); update_texture_memory(vid, _x, _y1, _x, _y2); vid = vid->next; } return; } static void allegro_gl_video_hline(BITMAP *bmp, int x1, int y, int x2, int color) { AGL_VIDEO_BITMAP *vid; AGL_LOG(2, "glvtable.c:allegro_gl_video_hline\n"); vid = bmp->extra; if (is_sub_bitmap(bmp)) { x1 += bmp->x_ofs; x2 += bmp->x_ofs; y += bmp->y_ofs; } if (y < bmp->ct || y >= bmp->cb) { return; } if (x1 > x2) { int temp = x1; x1 = x2; x2 = temp; } if (x1 < bmp->cl) { x1 = bmp->cl; } if (x2 >= bmp->cr) { x2 = bmp->cr - 1; } while (vid) { BITMAP *vbmp = vid->memory_copy; int _x1, _x2, _y; if (vid->y_ofs > y || vid->x_ofs > x2 || vid->x_ofs + vbmp->w <= x1 || vid->y_ofs + vbmp->h <= y) { vid = vid->next; continue; } _x1 = MAX(x1, vid->x_ofs) - vid->x_ofs; _x2 = MIN(x2, vid->x_ofs + vbmp->w - 1) - vid->x_ofs; _y = y - vid->y_ofs; set_drawing_pattern(); hline(vbmp, _x1, _y, _x2, color); unset_drawing_pattern(); update_texture_memory(vid, _x1, _y, _x2, _y); vid = vid->next; } return; } static void allegro_gl_video_line(struct BITMAP *bmp, int x1, int y1, int x2, int y2, int color) { /* Note: very very slow */ do_line(bmp, x1, y1, x2, y2, color, allegro_gl_video_putpixel); return; } static void allegro_gl_video_rectfill(struct BITMAP *bmp, int x1, int y1, int x2, int y2, int color) { AGL_VIDEO_BITMAP *vid; AGL_LOG(2, "glvtable.c:allegro_gl_video_rectfill\n"); vid = bmp->extra; if (is_sub_bitmap(bmp)) { x1 += bmp->x_ofs; x2 += bmp->x_ofs; y1 += bmp->y_ofs; y2 += bmp->y_ofs; } if (y1 > y2) { int temp = y1; y1 = y2; y2 = temp; } if (x1 > x2) { int temp = x1; x1 = x2; x2 = temp; } if (x1 < bmp->cl) { x1 = bmp->cl; } if (x2 > bmp->cr) { x2 = bmp->cr; } if (y1 < bmp->ct) { y1 = bmp->ct; } if (y1 > bmp->cb) { y1 = bmp->cb; } while (vid) { BITMAP *vbmp = vid->memory_copy; int _y1, _y2, _x1, _x2; if (vid->x_ofs > x2 || vid->y_ofs > y2 || vid->x_ofs + vbmp->w <= x1 || vid->y_ofs + vbmp->h <= y1) { vid = vid->next; continue; } _y1 = MAX(y1, vid->y_ofs) - vid->y_ofs; _y2 = MIN(y2, vid->y_ofs + vbmp->h - 1) - vid->y_ofs; _x1 = MAX(x1, vid->x_ofs) - vid->x_ofs; _x2 = MIN(x2, vid->x_ofs + vbmp->w - 1) - vid->x_ofs; set_drawing_pattern(); rectfill(vbmp, _x1, _y1, _x2, _y2, color); unset_drawing_pattern(); update_texture_memory(vid, _x1, _y1, _x2, _y2); vid = vid->next; } return; } static void allegro_gl_video_triangle(struct BITMAP *bmp, int x1, int y1, int x2, int y2, int x3, int y3, int color) { AGL_VIDEO_BITMAP *vid; int min_y, max_y, min_x, max_x; AGL_LOG(2, "glvtable.c:allegro_gl_video_triangle\n"); vid = bmp->extra; if (is_sub_bitmap(bmp)) { x1 += bmp->x_ofs; x2 += bmp->x_ofs; x3 += bmp->x_ofs; y1 += bmp->y_ofs; y2 += bmp->y_ofs; y3 += bmp->y_ofs; } min_y = MIN(y1, MIN(y2, y3)); min_x = MIN(x1, MIN(x2, x3)); max_y = MAX(y1, MAX(y2, y3)); max_x = MAX(x1, MAX(x2, x3)); while (vid) { BITMAP *vbmp = vid->memory_copy; int _y1, _y2, _x1, _x2, _x3, _y3; if (vid->x_ofs > max_x || vid->y_ofs > max_y || vid->x_ofs + vbmp->w <= min_x || vid->y_ofs + vbmp->h <= min_y) { vid = vid->next; continue; } _y1 = y1 - vid->y_ofs; _y2 = y2 - vid->y_ofs; _y3 = y3 - vid->y_ofs; _x1 = x1 - vid->x_ofs; _x2 = x2 - vid->x_ofs; _x3 = x3 - vid->x_ofs; set_clip_rect(vbmp, bmp->cl - vid->x_ofs, bmp->ct - vid->y_ofs, bmp->cr - vid->x_ofs - 1, bmp->cb - vid->y_ofs - 1); set_drawing_pattern(); triangle(vbmp, _x1, _y1, _x2, _y2, _x3, _y3, color); unset_drawing_pattern(); set_clip_rect(vbmp, 0, 0, vbmp->w - 1, vbmp->h - 1); /* Not quite the minimal rectangle occupied by the triangle, but * pretty close */ _y1 = MAX(0, min_y - vid->y_ofs); _y2 = MIN(vbmp->h - 1, max_y - vid->y_ofs); _x1 = MAX(0, min_x - vid->x_ofs); _x2 = MIN(vbmp->w - 1, max_x - vid->x_ofs); update_texture_memory(vid, _x1, _y1, _x2, _y2); vid = vid->next; } } static void allegro_gl_video_blit_from_memory_ex(BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height, int draw_type) { AGL_VIDEO_BITMAP *vid; BITMAP *dest_parent = dest; if (is_sub_bitmap (dest)) { dest_x += dest->x_ofs; dest_y += dest->y_ofs; while (dest_parent->id & BMP_ID_SUB) dest_parent = (BITMAP *)dest_parent->extra; } if (dest_x < dest->cl) { dest_x = dest->cl; } if (dest_y < dest->ct) { dest_y = dest->ct; } if (dest_x + width >= dest->cr) { width = dest->cr - dest_x; } if (dest_y + height >= dest->cb) { height = dest->cb - dest_y; } if (width < 1 || height < 1) { return; } vid = dest_parent->extra; while (vid) { BITMAP *vbmp = vid->memory_copy; int _x, _y, _w, _h, _sx, _sy; if (vid->x_ofs >= dest_x + width || vid->y_ofs >= dest_y + height || vid->x_ofs + vbmp->w <= dest_x || vid->y_ofs + vbmp->h <= dest_y) { vid = vid->next; continue; } _x = MAX (vid->x_ofs, dest_x) - vid->x_ofs; _w = MIN (vid->x_ofs + vbmp->w, dest_x + width) - vid->x_ofs - _x; _y = MAX (vid->y_ofs, dest_y) - vid->y_ofs; _h = MIN (vid->y_ofs + vbmp->h, dest_y + height) - vid->y_ofs - _y; _sx = source_x + vid->x_ofs + _x - dest_x; _sy = source_y + vid->y_ofs + _y - dest_y; if (draw_type == BLIT) { blit(source, vbmp, _sx, _sy, _x, _y, _w, _h); } else if (draw_type == MASKED_BLIT) { masked_blit(source, vbmp, _sx, _sy, _x, _y, _w, _h); } else if (draw_type == TRANS) { BITMAP *clip = create_sub_bitmap(source, _sx, _sy, _w, _h); if (!clip) return; draw_trans_sprite(vbmp, clip, _x, _y); destroy_bitmap(clip); } update_texture_memory(vid, _x, _y, _x + _w - 1, _y + _h - 1); vid = vid->next; } return; } void allegro_gl_video_blit_from_memory(BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height) { allegro_gl_video_blit_from_memory_ex(source, dest, source_x, source_y, dest_x, dest_y, width, height, BLIT); return; } void allegro_gl_video_blit_to_memory(struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height) { AGL_VIDEO_BITMAP *vid; BITMAP *source_parent = source; AGL_LOG(2, "glvtable.c:allegro_gl_video_blit_to_memory\n"); if (is_sub_bitmap(source)) { source_x += source->x_ofs; source_y += source->y_ofs; while (source_parent->id & BMP_ID_SUB) source_parent = (BITMAP *)source_parent->extra; } vid = source_parent->extra; while (vid) { BITMAP *vbmp = vid->memory_copy; int x, y, dx, dy, w, h; x = MAX(source_x, vid->x_ofs) - vid->x_ofs; y = MAX(source_y, vid->y_ofs) - vid->y_ofs; w = MIN(vid->x_ofs + vbmp->w, source_x + width) - vid->x_ofs; h = MIN(vid->y_ofs + vbmp->h, source_y + height) - vid->y_ofs; dx = MAX(0, vid->x_ofs - source_x) + dest_x; dy = MAX(0, vid->y_ofs - source_y) + dest_y; blit(vbmp, dest, x, y, dx, dy, w, h); vid = vid->next; } return; } /* Just like allegro_gl_video_blit_from_memory(), except that draws only to the * memory copy. */ static void __video_update_memory_copy(BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height, int draw_type) { AGL_VIDEO_BITMAP *vid; BITMAP *dest_parent = dest; if (is_sub_bitmap (dest)) { dest_x += dest->x_ofs; dest_y += dest->y_ofs; while (dest_parent->id & BMP_ID_SUB) dest_parent = (BITMAP *)dest_parent->extra; } if (dest_x < dest->cl) { dest_x = dest->cl; } if (dest_y < dest->ct) { dest_y = dest->ct; } if (dest_x + width >= dest->cr) { width = dest->cr - dest_x; } if (dest_y + height >= dest->cb) { height = dest->cb - dest_y; } if (width < 1 || height < 1) { return; } vid = dest_parent->extra; while (vid) { int sx, sy; BITMAP *vbmp = vid->memory_copy; int dx, dy, w, h; if (vid->x_ofs >= dest_x + width || vid->y_ofs >= dest_y + height || vid->x_ofs + vbmp->w <= dest_x || vid->y_ofs + vbmp->h <= dest_y) { vid = vid->next; continue; } dx = MAX (vid->x_ofs, dest_x) - vid->x_ofs; w = MIN (vid->x_ofs + vbmp->w, dest_x + width) - vid->x_ofs - dx; dy = MAX (vid->y_ofs, dest_y) - vid->y_ofs; h = MIN (vid->y_ofs + vbmp->h, dest_y + height) - vid->y_ofs - dy; sx = source_x + vid->x_ofs + dx - dest_x; sy = source_y + vid->y_ofs + dy - dest_y; if (draw_type == MASKED_BLIT) { masked_blit(source, vbmp, sx, sy, dx, dy, w, h); } else if (draw_type == BLIT) { blit(source, vbmp, sx, sy, dx, dy, w, h); } else if (draw_type == TRANS) { BITMAP *clip = create_sub_bitmap(source, sx, sy, w, h); if (!clip) return; draw_trans_sprite(vbmp, clip, dx, dy); destroy_bitmap(clip); } vid = vid->next; } return; } #define FOR_EACH_TEXTURE_FRAGMENT( \ screen_blit_from_vid, /* used when dest is FBO to blit to texture memory from video bitmap */ \ screen_blit_from_mem, /* used when dest is FBO to blit to texture memory from memory bitmap */ \ mem_copy_blit_from_vid, /* used to update the memory copy of the dest from the source video bitmap */ \ mem_copy_blit_from_mem, /* used to update the memory copy of the dest from the source memory bitmap */ \ vid_and_mem_copy_blit_from_vid, /* used when dest is not FBO, draws to both memory copy and texute memory of the dest, from video bitmap source*/ \ vid_and_mem_copy_blit_from_mem) /* used when dest is not FBO, draws to both memory copy and texute memory of the dest, from memory bitmap source */ \ { \ int used_fbo = FALSE; \ AGL_VIDEO_BITMAP *vid; \ \ vid = dest->extra; \ if (vid->fbo) { \ int sx, sy; \ int dx, dy; \ int w, h; \ \ static GLint v[4]; \ static double allegro_gl_projection_matrix[16]; \ static double allegro_gl_modelview_matrix[16]; \ \ glGetIntegerv(GL_VIEWPORT, &v[0]); \ glMatrixMode(GL_MODELVIEW); \ glGetDoublev(GL_MODELVIEW_MATRIX, allegro_gl_modelview_matrix); \ glMatrixMode(GL_PROJECTION); \ glGetDoublev(GL_PROJECTION_MATRIX, allegro_gl_projection_matrix); \ \ while (vid) { \ if (dest_x >= vid->x_ofs + vid->memory_copy->w || \ dest_y >= vid->y_ofs + vid->memory_copy->h || \ vid->x_ofs >= dest_x + width || \ vid->y_ofs >= dest_y + height) { \ vid = vid->next; \ continue; \ } \ \ dx = MAX(vid->x_ofs, dest_x) - vid->x_ofs; \ w = MIN(vid->x_ofs + vid->memory_copy->w, dest_x + width) \ - vid->x_ofs - dx; \ dy = MAX(vid->y_ofs, dest_y) - vid->y_ofs; \ h = MIN(vid->y_ofs + vid->memory_copy->h, dest_y + height) \ - vid->y_ofs - dy; \ \ sx = source_x + vid->x_ofs + dx - dest_x; \ sy = source_y + vid->y_ofs + dy - dest_y; \ \ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, vid->fbo); \ \ glViewport(0, 0, vid->memory_copy->w, vid->memory_copy->h); \ glMatrixMode(GL_PROJECTION); \ glLoadIdentity(); \ gluOrtho2D(0, vid->memory_copy->w, 0, vid->memory_copy->h); \ glMatrixMode(GL_MODELVIEW); \ \ if (is_memory_bitmap(source)) { \ screen_blit_from_mem; \ } \ else { \ screen_blit_from_vid; \ } \ \ vid = vid->next; \ } \ \ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); \ \ glViewport(v[0], v[1], v[2], v[3]); \ glMatrixMode(GL_PROJECTION); \ glLoadMatrixd(allegro_gl_projection_matrix); \ glMatrixMode(GL_MODELVIEW); \ glLoadMatrixd(allegro_gl_modelview_matrix); \ \ used_fbo = TRUE; \ } \ \ if (is_video_bitmap(source)) { \ int sx, sy; \ int dx, dy; \ int w, h; \ \ vid = source->extra; \ \ while (vid) { \ if (source_x >= vid->x_ofs + vid->memory_copy->w || \ source_y >= vid->y_ofs + vid->memory_copy->h || \ vid->x_ofs >= source_x + width || \ vid->y_ofs >= source_y + height) { \ vid = vid->next; \ continue; \ } \ \ sx = MAX(vid->x_ofs, source_x) - vid->x_ofs; \ w = MIN(vid->x_ofs + vid->memory_copy->w, source_x + width) \ - vid->x_ofs - sx; \ sy = MAX(vid->y_ofs, source_y) - vid->y_ofs; \ h = MIN(vid->y_ofs + vid->memory_copy->h, source_y + height) \ - vid->y_ofs - sy; \ \ dx = dest_x + vid->x_ofs + sx - source_x; \ dy = dest_y + vid->y_ofs + sy - source_y; \ \ if (used_fbo) { \ mem_copy_blit_from_vid; \ } \ else { \ vid_and_mem_copy_blit_from_vid; \ } \ \ vid = vid->next; \ } \ } \ else if (is_memory_bitmap(source)) { \ if (used_fbo) { \ mem_copy_blit_from_mem; \ } \ else { \ vid_and_mem_copy_blit_from_mem; \ } \ } \ } /* allegro_gl_video_blit_to_self: * blit() overload for video -> video blits */ void allegro_gl_video_blit_to_self(struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height) { FOR_EACH_TEXTURE_FRAGMENT ( allegro_gl_screen_blit_to_self(source, screen, sx, sy, dx, dy, w, h), allegro_gl_screen_blit_to_self(source, screen, sx, sy, dx, dy, w, h), __video_update_memory_copy(vid->memory_copy, dest, sx, sy, dx, dy, w, h, BLIT), __video_update_memory_copy(source, dest, source_x, source_y, dest_x, dest_y, width, height, BLIT), allegro_gl_video_blit_from_memory(vid->memory_copy, dest, sx, sy, dx, dy, w, h), allegro_gl_video_blit_from_memory(source, dest, source_x, source_y, dest_x, dest_y, width, height) ) } static void do_masked_blit_video(struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height, int flip_dir, int blit_type) { FOR_EACH_TEXTURE_FRAGMENT ( do_masked_blit_screen(source, screen, sx, sy, dx, dy, w, h, flip_dir, blit_type), do_masked_blit_screen(source, screen, sx, sy, dx, dy, w, h, flip_dir, blit_type), __video_update_memory_copy(vid->memory_copy, dest, sx, sy, dx, dy, w, h, MASKED_BLIT), __video_update_memory_copy(source, dest, source_x, source_y, dest_x, dest_y, width, height, MASKED_BLIT), allegro_gl_video_blit_from_memory_ex(vid->memory_copy, dest, sx, sy, dx, dy, w, h, MASKED_BLIT), allegro_gl_video_blit_from_memory_ex(source, dest, source_x, source_y, dest_x, dest_y, width, height, MASKED_BLIT) ) } /* allegro_gl_video_masked_blit: * masked_blit() overload for video -> video masked blits */ static void allegro_gl_video_masked_blit(struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height) { do_masked_blit_video(source, dest, source_x, source_y, dest_x, dest_y, width, height, FALSE, AGL_REGULAR_BMP | AGL_NO_ROTATION); return; } /* allegro_gl_video_draw_sprite: * draw_sprite() overload for video -> video sprite drawing */ static void allegro_gl_video_draw_sprite(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y) { do_masked_blit_video(sprite, bmp, 0, 0, x, y, sprite->w, sprite->h, FALSE, AGL_NO_ROTATION); return; } /* allegro_gl_video_draw_sprite_v_flip: * draw_sprite_v_flip() overload for video -> video blits * FIXME: Broken if the bitmap was split into multiple textures. * FIXME: Doesn't apply rotation and scale to the memory copy */ static void allegro_gl_video_draw_sprite_v_flip(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y) { do_masked_blit_video(sprite, bmp, 0, 0, x, y, sprite->w, sprite->h, AGL_V_FLIP, AGL_NO_ROTATION); return; } /* allegro_gl_video_draw_sprite_h_flip: * draw_sprite_v_flip() overload for video -> video blits * FIXME: Broken if the bitmap was split into multiple textures. * FIXME: Doesn't apply rotation and scale to the memory copy */ static void allegro_gl_video_draw_sprite_h_flip(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y) { do_masked_blit_video(sprite, bmp, 0, 0, x, y, sprite->w, sprite->h, AGL_H_FLIP, AGL_NO_ROTATION); return; } /* allegro_gl_video_draw_sprite_vh_flip: * draw_sprite_vh_flip() overload for video -> video blits * FIXME: Broken if the bitmap was split into multiple textures. * FIXME: Doesn't apply rotation and scale to the memory copy */ static void allegro_gl_video_draw_sprite_vh_flip(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y) { do_masked_blit_video(sprite, bmp, 0, 0, x, y, sprite->w, sprite->h, AGL_V_FLIP | AGL_H_FLIP, AGL_NO_ROTATION); return; } /* allegro_gl_video_pivot_scaled_sprite_flip: * FIXME: Broken if the bitmap was split into multiple textures. * FIXME: Doesn't apply rotation and scale to the memory copy * FIXME: Doesn't work for when FBO is not available. */ static void allegro_gl_video_pivot_scaled_sprite_flip(struct BITMAP *bmp, struct BITMAP *sprite, fixed x, fixed y, fixed cx, fixed cy, fixed angle, fixed scale, int v_flip) { double dscale = fixtof(scale); GLint matrix_mode; #define BIN_2_DEG(x) (-(x) * 180.0 / 128) glGetIntegerv(GL_MATRIX_MODE, &matrix_mode); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glTranslated(fixtof(x), fixtof(y), 0.); glRotated(BIN_2_DEG(fixtof(angle)), 0., 0., -1.); glScaled(dscale, dscale, dscale); glTranslated(-fixtof(x+cx), -fixtof(y+cy), 0.); do_masked_blit_video(sprite, bmp, 0, 0, fixtoi(x), fixtoi(y), sprite->w, sprite->h, v_flip ? AGL_V_FLIP : FALSE, FALSE); glPopMatrix(); glMatrixMode(matrix_mode); #undef BIN_2_DEG return; } /* allegro_gl_video_do_stretch_blit: * overload for all kind of video -> video and video -> screen stretchers * FIXME: Doesn't apply scale to the memory copy * FIXME: Doesn't work for video->video when FBO is not available. */ static void allegro_gl_video_do_stretch_blit(BITMAP *source, BITMAP *dest, int source_x, int source_y, int source_width, int source_height, int dest_x, int dest_y, int dest_width, int dest_height, int masked) { /* note: src is a video bitmap, dest is not a memory bitmap */ double scalew = ((double)dest_width) / source_width; double scaleh = ((double)dest_height) / source_height; GLint matrix_mode; /* BITMAP_BLIT_CLIP macro from glvtable.c is no good for scaled images. */ if (dest->clip) { if ((dest_x >= dest->cr) || (dest_y >= dest->cb) || (dest_x + dest_width < dest->cl) || (dest_y + dest_height < dest->ct)) { return; } if (dest_x < dest->cl) { source_x -= (dest_x - dest->cl) / scalew; dest_x = dest->cl; } if (dest_y < dest->ct) { source_y -= (dest_y - dest->ct) / scaleh; dest_y = dest->ct; } if (dest_x + dest_width > dest->cr) { source_width -= (dest_x + dest_width - dest->cr) / scalew; dest_width = dest->cr - dest_x; } if (dest_y + dest_height > dest->cb) { source_height -= (dest_y + dest_height - dest->cb) / scaleh; dest_height = dest->cb - dest_y; } } glGetIntegerv(GL_MATRIX_MODE, &matrix_mode); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glTranslated(dest_x, dest_y, 0.); glScaled(scalew, scaleh, 1.); glTranslated(-dest_x, -dest_y, 0.); if (masked) { if (is_screen_bitmap(dest)) { do_masked_blit_screen(source, dest, source_x, source_y, dest_x, dest_y, source_width, source_height, FALSE, AGL_REGULAR_BMP); } else { do_masked_blit_video(source, dest, source_x, source_y, dest_x, dest_y, source_width, source_height, FALSE, AGL_REGULAR_BMP); } } else { allegro_gl_screen_blit_to_self(source, dest, source_x, source_y, dest_x, dest_y, source_width, source_height); } glPopMatrix(); glMatrixMode(matrix_mode); return; } /* allegro_gl_video_draw_trans_rgba_sprite: * draw_trans_sprite() overload for video -> video drawing */ static void allegro_gl_video_draw_trans_rgba_sprite(BITMAP *bmp, BITMAP *sprite, int x, int y) { /* Adapt variables for FOR_EACH_TEXTURE_FRAGMENT macro. */ BITMAP *source = sprite; BITMAP *dest = bmp; int dest_x = x; int dest_y = y; int source_x = 0; int source_y = 0; int width = sprite->w; int height = sprite->h; GLint format = __allegro_gl_get_bitmap_color_format(sprite, AGL_TEXTURE_HAS_ALPHA); GLint type = __allegro_gl_get_bitmap_type(sprite, 0); if (__allegro_gl_blit_operation == AGL_OP_LOGIC_OP) glEnable(GL_COLOR_LOGIC_OP); else glEnable(GL_BLEND); FOR_EACH_TEXTURE_FRAGMENT ( allegro_gl_screen_blit_to_self(source, screen, sx, sy, dx, dy, w, h), allegro_gl_upload_and_display_texture(sprite, sx, sy, dx, dy, w, h, 0, format, type), __video_update_memory_copy(vid->memory_copy, dest, sx, sy, dx, dy, w, h, TRANS), __video_update_memory_copy(source, dest, 0, 0, x, y, sprite->w, sprite->h, TRANS), allegro_gl_video_blit_from_memory_ex(vid->memory_copy, dest, sx, sy, dx, dy, w, h, TRANS), allegro_gl_video_blit_from_memory_ex(source, dest, 0, 0, x, y, sprite->w, sprite->h, TRANS) ) if (__allegro_gl_blit_operation == AGL_OP_LOGIC_OP) glDisable(GL_COLOR_LOGIC_OP); else glDisable(GL_BLEND); return; } /* allegro_gl_video_draw_sprite_ex: * draw_sprite_ex() overload for video -> video and memory -> video drawing * * When mode is DRAW_SPRITE_TRANS: * FIXME: Broken if the bitmap was split into multiple textures. * FIXME: Doesn't apply flipping to the memory copy */ static void allegro_gl_video_draw_sprite_ex(BITMAP *bmp, BITMAP *sprite, int x, int y, int mode, int flip) { int matrix_mode; int lflip = 0; /* convert allegro's flipping flags to AGL's flags */ switch (flip) { case DRAW_SPRITE_NO_FLIP: lflip = FALSE; break; case DRAW_SPRITE_V_FLIP: lflip = AGL_V_FLIP; break; case DRAW_SPRITE_H_FLIP: lflip = AGL_H_FLIP; break; case DRAW_SPRITE_VH_FLIP: lflip = AGL_V_FLIP | AGL_H_FLIP; break; } switch (mode) { case DRAW_SPRITE_NORMAL: do_masked_blit_video(sprite, bmp, 0, 0, x, y, sprite->w, sprite->h, lflip, FALSE); break; case DRAW_SPRITE_TRANS: if (lflip) { glGetIntegerv(GL_MATRIX_MODE, &matrix_mode); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glTranslatef(x, y, 0.f); glScalef((lflip&AGL_H_FLIP) ? -1 : 1, (lflip&AGL_V_FLIP)? -1 : 1, 1); glTranslatef(-x, -y, 0); glTranslatef((lflip&AGL_H_FLIP) ? -sprite->w : 0, (lflip&AGL_V_FLIP) ? -sprite->h : 0, 0); } allegro_gl_video_draw_trans_rgba_sprite(bmp, sprite, x, y); if (lflip) { glPopMatrix(); glMatrixMode(matrix_mode); } break; case DRAW_SPRITE_LIT: /* not implemented */ break; } } static void allegro_gl_video_clear_to_color(BITMAP *bmp, int color) { AGL_VIDEO_BITMAP *vid = bmp->extra; if (vid->fbo) { static GLint v[4]; static double allegro_gl_projection_matrix[16]; static double allegro_gl_modelview_matrix[16]; glGetIntegerv(GL_VIEWPORT, &v[0]); glMatrixMode(GL_MODELVIEW); glGetDoublev(GL_MODELVIEW_MATRIX, allegro_gl_modelview_matrix); glMatrixMode(GL_PROJECTION); glGetDoublev(GL_PROJECTION_MATRIX, allegro_gl_projection_matrix); while (vid) { glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, vid->fbo); glViewport(0, 0, vid->memory_copy->w, vid->memory_copy->h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(0, vid->memory_copy->w, 0, vid->memory_copy->h); glMatrixMode(GL_MODELVIEW); allegro_gl_screen_clear_to_color(bmp, color); clear_to_color(vid->memory_copy, color); vid = vid->next; } glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); glViewport(v[0], v[1], v[2], v[3]); glMatrixMode(GL_PROJECTION); glLoadMatrixd(allegro_gl_projection_matrix); glMatrixMode(GL_MODELVIEW); glLoadMatrixd(allegro_gl_modelview_matrix); } else { allegro_gl_video_rectfill(bmp, 0, 0, bmp->w, bmp->h, color); } } /* FIXME: Doesn't work when FBO is not available. * FIXME: Doesn't care for segmented video bitmaps. */ static void allegro_gl_video_draw_color_glyph(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y, int color, int bg) { AGL_VIDEO_BITMAP *vid = bmp->extra; static GLint v[4]; static double allegro_gl_projection_matrix[16]; static double allegro_gl_modelview_matrix[16]; if (!vid->fbo) return; glGetIntegerv(GL_VIEWPORT, &v[0]); glMatrixMode(GL_MODELVIEW); glGetDoublev(GL_MODELVIEW_MATRIX, allegro_gl_modelview_matrix); glMatrixMode(GL_PROJECTION); glGetDoublev(GL_PROJECTION_MATRIX, allegro_gl_projection_matrix); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, vid->fbo); glViewport(0, 0, vid->memory_copy->w, vid->memory_copy->h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(0, vid->memory_copy->w, 0, vid->memory_copy->h); glMatrixMode(GL_MODELVIEW); allegro_gl_screen_draw_color_glyph_ex(bmp, sprite, x, y, color, bg, 0); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); glViewport(v[0], v[1], v[2], v[3]); glMatrixMode(GL_PROJECTION); glLoadMatrixd(allegro_gl_projection_matrix); glMatrixMode(GL_MODELVIEW); glLoadMatrixd(allegro_gl_modelview_matrix); vid->memory_copy->vtable->draw_character(vid->memory_copy, sprite, x, y, color, bg); } static void allegro_gl_video_draw_256_sprite(BITMAP *bmp, BITMAP *sprite, int x, int y) { allegro_gl_video_draw_color_glyph(bmp, sprite, x, y, -1, _textmode); } static void allegro_gl_video_draw_character(BITMAP *bmp, BITMAP *sprite, int x, int y, int color, int bg) { allegro_gl_video_draw_color_glyph(bmp, sprite, x, y, color, bg); } /* FIXME: Doesn't work when FBO is not available. * FIXME: Doesn't care for segmented video bitmaps. */ static void allegro_gl_video_draw_glyph(struct BITMAP *bmp, AL_CONST struct FONT_GLYPH *glyph, int x, int y, int color, int bg) { AGL_VIDEO_BITMAP *vid = bmp->extra; static GLint v[4]; static double allegro_gl_projection_matrix[16]; static double allegro_gl_modelview_matrix[16]; if (!vid->fbo) return; glGetIntegerv(GL_VIEWPORT, &v[0]); glMatrixMode(GL_MODELVIEW); glGetDoublev(GL_MODELVIEW_MATRIX, allegro_gl_modelview_matrix); glMatrixMode(GL_PROJECTION); glGetDoublev(GL_PROJECTION_MATRIX, allegro_gl_projection_matrix); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, vid->fbo); glViewport(0, 0, vid->memory_copy->w, vid->memory_copy->h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(0, vid->memory_copy->w, 0, vid->memory_copy->h); glMatrixMode(GL_MODELVIEW); allegro_gl_screen_draw_glyph_ex(bmp, glyph, x, y, color, bg, 1); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); glViewport(v[0], v[1], v[2], v[3]); glMatrixMode(GL_PROJECTION); glLoadMatrixd(allegro_gl_projection_matrix); glMatrixMode(GL_MODELVIEW); glLoadMatrixd(allegro_gl_modelview_matrix); vid->memory_copy->vtable->draw_glyph(vid->memory_copy, glyph, x, y, color, bg); } static void allegro_gl_video_polygon3d_f(BITMAP *bmp, int type, BITMAP *texture, int vc, V3D_f *vtx[]) { AGL_VIDEO_BITMAP *vid = bmp->extra; /* Switch to software mode is using polygon type that isn't supported by allegro_gl_screen_polygon3d_f. */ int use_fbo = (type == POLYTYPE_FLAT) || (type == POLYTYPE_GRGB) || (type == POLYTYPE_GCOL) || (type == POLYTYPE_ATEX) || (type == POLYTYPE_PTEX) || (type == POLYTYPE_ATEX_TRANS) || (type == POLYTYPE_PTEX_TRANS); if (vid->fbo && use_fbo) { static GLint v[4]; static double allegro_gl_projection_matrix[16]; static double allegro_gl_modelview_matrix[16]; glGetIntegerv(GL_VIEWPORT, &v[0]); glMatrixMode(GL_MODELVIEW); glGetDoublev(GL_MODELVIEW_MATRIX, allegro_gl_modelview_matrix); glMatrixMode(GL_PROJECTION); glGetDoublev(GL_PROJECTION_MATRIX, allegro_gl_projection_matrix); while (vid) { BITMAP *mem_texture; glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, vid->fbo); glViewport(0, 0, vid->memory_copy->w, vid->memory_copy->h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(0, vid->memory_copy->w, 0, vid->memory_copy->h); glMatrixMode(GL_MODELVIEW); allegro_gl_screen_polygon3d_f(bmp, type, texture, vc, vtx); if (is_video_bitmap(texture)) { AGL_VIDEO_BITMAP *vbmp = texture->extra; mem_texture = vbmp->memory_copy; } else { mem_texture = texture; } polygon3d_f(vid->memory_copy, type, mem_texture, vc, vtx); vid = vid->next; } glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); glViewport(v[0], v[1], v[2], v[3]); glMatrixMode(GL_PROJECTION); glLoadMatrixd(allegro_gl_projection_matrix); glMatrixMode(GL_MODELVIEW); glLoadMatrixd(allegro_gl_modelview_matrix); } else { int i; AGL_VIDEO_BITMAP *vid; vid = bmp->extra; if (is_sub_bitmap(bmp)) { for (i = 0; i < vc; ++i) { vtx[i]->x += bmp->x_ofs; vtx[i]->y += bmp->y_ofs; } } while (vid) { BITMAP *mem_texture; int _y1, _y2, _x1, _x2; BITMAP *vbmp = vid->memory_copy; _x1 = 9999; for (i = 0; i < vc; ++i) if (vtx[i]->x < _x1) _x1 = vtx[i]->x; _x2 = -9999; for (i = 0; i < vc; ++i) if (vtx[i]->x > _x2) _x2 = vtx[i]->x; _y1 = 9999; for (i = 0; i < vc; ++i) if (vtx[i]->y < _y1) _y1 = vtx[i]->y; _y2 = -9999; for (i = 0; i < vc; ++i) if (vtx[i]->y > _y2) _y2 = vtx[i]->y; if (vid->x_ofs > _x2 || vid->y_ofs > _y2 || vid->x_ofs + vbmp->w <= _x1 || vid->y_ofs + vbmp->h <= _y1) { vid = vid->next; continue; } _x1 = MAX(0, _x1 - vid->x_ofs); _x2 = (_x2 - (vid->x_ofs + vbmp->w) > 0) ? vbmp->w - 1: _x2 - vid->x_ofs; _y1 = MAX(0, _y1 - vid->y_ofs); _y2 = (_x2 - (vid->y_ofs + vbmp->h) > 0) ? vbmp->h - 1: _y2 - vid->y_ofs; if (is_video_bitmap(texture)) { AGL_VIDEO_BITMAP *tex = texture->extra; mem_texture = tex->memory_copy; } else { mem_texture = texture; } polygon3d_f(vid->memory_copy, type, mem_texture, vc, vtx); update_texture_memory(vid, _x1, _y1, _x2, _y2); vid = vid->next; } } return; } static void allegro_gl_video_polygon3d(BITMAP *bmp, int type, BITMAP *texture, int vc, V3D *vtx[]) { int i; V3D_f **vtx_f = malloc(vc * sizeof(struct V3D_f*)); if (!vtx_f) return; for (i = 0; i < vc; i++) { vtx_f[i] = malloc(sizeof(struct V3D_f)); if (!vtx_f[i]) { int k; for (k = 0; k < i; k++) free(vtx_f[k]); free(vtx_f); return; } vtx_f[i]->c = vtx[i]->c; vtx_f[i]->u = fixtof(vtx[i]->u); vtx_f[i]->v = fixtof(vtx[i]->v); vtx_f[i]->x = fixtof(vtx[i]->x); vtx_f[i]->y = fixtof(vtx[i]->y); vtx_f[i]->z = fixtof(vtx[i]->z); } allegro_gl_video_polygon3d_f(bmp, type, texture, vc, vtx_f); for (i = 0; i < vc; i++) free(vtx_f[i]); free(vtx_f); } static void allegro_gl_video_triangle3d(BITMAP *bmp, int type, BITMAP *texture, V3D *v1, V3D *v2, V3D *v3) { V3D *vtx[3]; vtx[0] = v1; vtx[1] = v2; vtx[2] = v3; allegro_gl_video_polygon3d(bmp, type, texture, 3, vtx); } static void allegro_gl_video_triangle3d_f(BITMAP *bmp, int type, BITMAP *texture, V3D_f *v1, V3D_f *v2, V3D_f *v3) { V3D_f *vtx_f[3]; vtx_f[0] = v1; vtx_f[1] = v2; vtx_f[2] = v3; allegro_gl_video_polygon3d_f(bmp, type, texture, 3, vtx_f); } static void allegro_gl_video_quad3d(BITMAP *bmp, int type, BITMAP *texture, V3D *v1, V3D *v2, V3D *v3, V3D *v4) { V3D *vtx[4]; vtx[0] = v1; vtx[1] = v2; vtx[2] = v3; vtx[3] = v4; allegro_gl_video_polygon3d(bmp, type, texture, 4, vtx); } static void allegro_gl_video_quad3d_f(BITMAP *bmp, int type, BITMAP *texture, V3D_f *v1, V3D_f *v2, V3D_f *v3, V3D_f *v4) { V3D_f *vtx_f[4]; vtx_f[0] = v1; vtx_f[1] = v2; vtx_f[2] = v3; vtx_f[3] = v4; allegro_gl_video_polygon3d_f(bmp, type, texture, 4, vtx_f); } static void dummy_unwrite_bank(void) { } static GFX_VTABLE allegro_gl_video_vtable = { 0, 0, dummy_unwrite_bank, //void *unwrite_bank; /* C function on some machines, asm on i386 */ NULL, //AL_METHOD(void, set_clip, (struct BITMAP *bmp)); allegro_gl_video_acquire, allegro_gl_video_release, NULL, //AL_METHOD(struct BITMAP *, create_sub_bitmap, (struct BITMAP *parent, int x, int y, int width, int height)); allegro_gl_created_sub_bitmap, allegro_gl_video_getpixel, allegro_gl_video_putpixel, allegro_gl_video_vline, allegro_gl_video_hline, allegro_gl_video_hline, allegro_gl_video_line, allegro_gl_video_line, allegro_gl_video_rectfill, allegro_gl_video_triangle, allegro_gl_video_draw_sprite, allegro_gl_video_draw_256_sprite, allegro_gl_video_draw_sprite_v_flip, allegro_gl_video_draw_sprite_h_flip, allegro_gl_video_draw_sprite_vh_flip, allegro_gl_video_draw_trans_rgba_sprite, allegro_gl_video_draw_trans_rgba_sprite, NULL, //AL_METHOD(void, draw_lit_sprite, (struct BITMAP *bmp, struct BITMAP *sprite, int x, int y, int color)); NULL, //AL_METHOD(void, allegro_gl_video_draw_rle_sprite, (struct BITMAP *bmp, struct RLE_SPRITE *sprite, int x, int y)); NULL, //AL_METHOD(void, draw_trans_rle_sprite, (struct BITMAP *bmp, struct RLE_SPRITE *sprite, int x, int y)); NULL, //AL_METHOD(void, draw_trans_rgba_rle_sprite, (struct BITMAP *bmp, struct RLE_SPRITE *sprite, int x, int y)); NULL, //AL_METHOD(void, draw_lit_rle_sprite, (struct BITMAP *bmp, struct RLE_SPRITE *sprite, int x, int y, int color)); allegro_gl_video_draw_character, allegro_gl_video_draw_glyph, allegro_gl_video_blit_from_memory, allegro_gl_video_blit_to_memory, NULL, //AL_METHOD(void, blit_from_system, (struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); NULL, //AL_METHOD(void, blit_to_system, (struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); allegro_gl_screen_blit_to_self, /* Video bitmaps use same method as screen */ allegro_gl_screen_blit_to_self, /* ..._forward */ allegro_gl_screen_blit_to_self, /* ..._backward */ allegro_gl_memory_blit_between_formats, allegro_gl_video_masked_blit, allegro_gl_video_clear_to_color, allegro_gl_video_pivot_scaled_sprite_flip, allegro_gl_video_do_stretch_blit, NULL, //AL_METHOD(void, draw_gouraud_sprite, (struct BITMAP *bmp, struct BITMAP *sprite, int x, int y, int c1, int c2, int c3, int c4)); NULL, //AL_METHOD(void, draw_sprite_end, (void)); NULL, //AL_METHOD(void, blit_end, (void)); _soft_polygon, //AL_METHOD(void, polygon, (struct BITMAP *bmp, int vertices, AL_CONST int *points, int color)); _soft_rect, //AL_METHOD(void, rect, (struct BITMAP *bmp, int x1, int y1, int x2, int y2, int color)); _soft_circle, //AL_METHOD(void, circle, (struct BITMAP *bmp, int x, int y, int radius, int color)); _soft_circlefill, //AL_METHOD(void, circlefill, (struct BITMAP *bmp, int x, int y, int radius, int color)); _soft_ellipse, //AL_METHOD(void, ellipse, (struct BITMAP *bmp, int x, int y, int rx, int ry, int color)); _soft_ellipsefill, //AL_METHOD(void, ellipsefill, (struct BITMAP *bmp, int x, int y, int rx, int ry, int color)); _soft_arc, //AL_METHOD(void, arc, (struct BITMAP *bmp, int x, int y, fixed ang1, fixed ang2, int r, int color)); _soft_spline, //AL_METHOD(void, spline, (struct BITMAP *bmp, AL_CONST int points[8], int color)); _soft_floodfill, //AL_METHOD(void, floodfill, (struct BITMAP *bmp, int x, int y, int color)); allegro_gl_video_polygon3d, allegro_gl_video_polygon3d_f, allegro_gl_video_triangle3d, allegro_gl_video_triangle3d_f, allegro_gl_video_quad3d, allegro_gl_video_quad3d_f, allegro_gl_video_draw_sprite_ex }; allegro4.4-4.4.2/addons/allegrogl/src/win.c000066400000000000000000001415431173507505700203660ustar00rootroot00000000000000/* This code is (C) AllegroGL contributors, and double licensed under * the GPL and zlib licenses. See gpl.txt or zlib.txt for details. */ #include #include #include #include "alleggl.h" #include "glvtable.h" #include "allglint.h" static BITMAP *allegro_gl_win_init_windowed(int w, int h, int v_w, int v_h, int color_depth); static BITMAP *allegro_gl_win_init_fullscreen(int w, int h, int v_w, int v_h, int color_depth); static void allegro_gl_win_exit(struct BITMAP *b); static GFX_MODE_LIST* allegro_gl_win_fetch_mode_list(void); static struct allegro_gl_driver allegro_gl_win; #define PREFIX_I "agl-win INFO: " #define PREFIX_W "agl-win WARNING: " #define PREFIX_E "agl-win ERROR: " static BITMAP *allegro_gl_screen = NULL; /* Windowed mode driver */ GFX_DRIVER gfx_allegro_gl_windowed = { GFX_OPENGL_WINDOWED, EMPTY_STRING, EMPTY_STRING, "AllegroGL Windowed (Win32)", allegro_gl_win_init_windowed, allegro_gl_win_exit, NULL, /* scrolling not implemented */ NULL, /* vsync, may use for flip? */ NULL, /* No h/w pallete, not using indexed mode */ NULL, NULL, /* Still no scrolling */ NULL, /* No triple buffering */ allegro_gl_create_video_bitmap, allegro_gl_destroy_video_bitmap, NULL, NULL, /* No show/request video bitmaps */ NULL, NULL, /* No system bitmaps */ allegro_gl_set_mouse_sprite, allegro_gl_show_mouse, allegro_gl_hide_mouse, allegro_gl_move_mouse, allegro_gl_drawing_mode, NULL, NULL, /* No video state stuff */ allegro_gl_set_blender_mode, NULL, /* No fetch_mode_list */ 0,0, /* physical (not virtual!) screen size */ 0, /* true if video memory is linear */ 0, /* bank size, in bytes */ 0, /* bank granularity, in bytes */ 0, /* video memory size, in bytes */ 0, /* physical address of video memory */ TRUE /* Windowed mode */ }; /* Fullscreen driver */ GFX_DRIVER gfx_allegro_gl_fullscreen = { GFX_OPENGL_FULLSCREEN, EMPTY_STRING, EMPTY_STRING, "AllegroGL Fullscreen (Win32)", allegro_gl_win_init_fullscreen, allegro_gl_win_exit, NULL, /* scrolling not implemented */ NULL, /* vsync, may use for flip? */ NULL, /* No h/w pallete, not using indexed mode */ NULL, NULL, /* Still no scrolling */ NULL, /* No triple buffering */ allegro_gl_create_video_bitmap, allegro_gl_destroy_video_bitmap, NULL, NULL, /* No show/request video bitmaps */ NULL, NULL, /* No system bitmaps */ allegro_gl_set_mouse_sprite, allegro_gl_show_mouse, allegro_gl_hide_mouse, allegro_gl_move_mouse, allegro_gl_drawing_mode, NULL, NULL, /* No video state stuff */ allegro_gl_set_blender_mode, allegro_gl_win_fetch_mode_list, /* fetch_mode_list */ 0,0, /* physical (not virtual!) screen size */ 0, /* true if video memory is linear */ 0, /* bank size, in bytes */ 0, /* bank granularity, in bytes */ 0, /* video memory size, in bytes */ 0, /* physical address of video memory */ FALSE /* Windowed mode */ }; /* XXX We should move those variable definitions into a struct, * for when multiple windows end up being supported. */ /* Device Context used for the Allegro window. Note that only one window * is supported, so only onyl HDC is needed. This is shared by the AGL * extension code. */ HDC __allegro_gl_hdc = NULL; /* Render Context used by AllegroGL, once screen mode was set. Note that only * a single window is supported. */ static HGLRC allegro_glrc = NULL; /* Full-screen flag, for the current context. */ static int fullscreen = 0; /* Current window handle */ static HWND wnd = NULL; /* If AGL was initialized */ static int initialized = 0; /* XXX Put those globals as function parameters */ /* Note - these globals should really end up as parameters to functions. */ static DWORD style_saved, exstyle_saved; static DEVMODE dm_saved; static int test_windows_created = 0; static int new_w = 0, new_h = 0; static PIXELFORMATDESCRIPTOR pfd = { sizeof(PIXELFORMATDESCRIPTOR), /* size of this pfd */ 1, /* version number */ PFD_DRAW_TO_WINDOW /* support window */ | PFD_SUPPORT_OPENGL /* support OpenGL */ | PFD_DOUBLEBUFFER, /* double buffered */ PFD_TYPE_RGBA, /* RGBA type */ 24, /* 24-bit color depth */ 0, 0, 0, 0, 0, 0, /* color bits ignored */ 0, /* no alpha buffer */ 0, /* shift bit ignored */ 0, /* no accumulation buffer */ 0, 0, 0, 0, /* accum bits ignored */ 0, /* z-buffer */ 0, /* no stencil buffer */ 0, /* no auxiliary buffer */ PFD_MAIN_PLANE, /* main layer */ 0, /* reserved */ 0, 0, 0 /* layer masks ignored */ }; /* Logs a Win32 error/warning message in the log file. */ static void log_win32_msg(const char *prefix, const char *func, const char *error_msg, DWORD err) { char *err_msg = NULL; BOOL free_msg = TRUE; /* Get the formatting error string from Windows. Note that only the * bottom 14 bits matter - the rest are reserved for various library * IDs and type of error. */ if (!FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err & 0x3FFF, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &err_msg, 0, NULL)) { err_msg = "(Unable to decode error code) "; free_msg = FALSE; } /* Remove two trailing characters */ if (err_msg && strlen(err_msg) > 1) *(err_msg + strlen(err_msg) - 2) = '\0'; TRACE("%s%s(): %s %s (0x%08lx)\n", prefix, func, error_msg ? error_msg : "", err_msg ? err_msg : "(null)", (unsigned long)err); if (free_msg) { LocalFree(err_msg); } return; } /* Logs an error */ static void log_win32_error(const char *func, const char *error_msg, DWORD err) { log_win32_msg(PREFIX_E, func, error_msg, err); } /* Logs a warning */ static void log_win32_warning(const char *func, const char *error_msg, DWORD err) { log_win32_msg(PREFIX_W, func, error_msg, err); } /* Logs a note */ static void log_win32_note(const char *func, const char *error_msg, DWORD err) { log_win32_msg(PREFIX_I, func, error_msg, err); } /* Define the AllegroGL Test window class */ #define ALLEGROGL_TEST_WINDOW_CLASS "AllegroGLTestWindow" /* Registers the test window * Returns 0 on success, non-zero on failure. */ static int register_test_window() { WNDCLASS wc; memset(&wc, 0, sizeof(wc)); wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; wc.lpfnWndProc = DefWindowProc; wc.hInstance = GetModuleHandle(NULL); wc.hIcon = LoadIcon(GetModuleHandle(NULL), IDI_APPLICATION); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.lpszClassName = ALLEGROGL_TEST_WINDOW_CLASS; if (!RegisterClass(&wc)) { DWORD err = GetLastError(); if (err != ERROR_CLASS_ALREADY_EXISTS) { log_win32_error("register_test_window", "Unable to register the window class!", err); return -1; } } return 0; } /* Creates the test window. * The window class must have already been registered. * Returns the window handle, or NULL on failure. */ static HWND create_test_window() { HWND wnd = CreateWindow(ALLEGROGL_TEST_WINDOW_CLASS, "AllegroGL Test Window", WS_POPUP | WS_CLIPCHILDREN, 0, 0, new_w, new_h, NULL, NULL, GetModuleHandle(NULL), NULL); if (!wnd) { log_win32_error("create_test_window", "Unable to create a test window!", GetLastError()); return NULL; } test_windows_created++; return wnd; } /* Print the pixel format info */ static void print_pixel_format(struct allegro_gl_display_info *dinfo) { if (!dinfo) { return; } TRACE(PREFIX_I "Acceleration: %s\n", ((dinfo->rmethod == 0) ? "No" : ((dinfo->rmethod == 1) ? "Yes" : "Unknown"))); TRACE(PREFIX_I "RGBA: %i.%i.%i.%i\n", dinfo->pixel_size.rgba.r, dinfo->pixel_size.rgba.g, dinfo->pixel_size.rgba.b, dinfo->pixel_size.rgba.a); TRACE(PREFIX_I "Accum: %i.%i.%i.%i\n", dinfo->accum_size.rgba.r, dinfo->accum_size.rgba.g, dinfo->accum_size.rgba.b, dinfo->accum_size.rgba.a); TRACE(PREFIX_I "DblBuf: %i Zbuf: %i Stereo: %i Aux: %i Stencil: %i\n", dinfo->doublebuffered, dinfo->depth_size, dinfo->stereo, dinfo->aux_buffers, dinfo->stencil_size); TRACE(PREFIX_I "Shift: %i.%i.%i.%i\n", dinfo->r_shift, dinfo->g_shift, dinfo->b_shift, dinfo->a_shift); TRACE(PREFIX_I "Sample Buffers: %i Samples: %i\n", dinfo->sample_buffers, dinfo->samples); TRACE(PREFIX_I "Decoded bpp: %i\n", dinfo->colour_depth); } /* Decodes the pixel format into an agl_display_info struct and logs the pixel * format in the trace file. */ static int decode_pixel_format(PIXELFORMATDESCRIPTOR * pfd, HDC hdc, int format, struct allegro_gl_display_info *dinfo, int desktop_depth) { TRACE(PREFIX_I "Decoding: \n"); /* Not interested if it doesn't support OpenGL and RGBA */ if (!(pfd->dwFlags & PFD_SUPPORT_OPENGL)) { TRACE(PREFIX_I "OpenGL Unsupported\n"); return -1; } if (pfd->iPixelType != PFD_TYPE_RGBA) { TRACE(PREFIX_I "Not RGBA mode\n"); return -1; } if ((pfd->cColorBits != desktop_depth) && (pfd->cColorBits != 32 || desktop_depth < 24)) { TRACE(PREFIX_I "Current color depth != " "pixel format color depth\n"); //return -1; /* XXX Why is this a bad thing? */ } /* hardware acceleration */ if (((pfd->dwFlags & PFD_GENERIC_ACCELERATED) && (pfd->dwFlags & PFD_GENERIC_FORMAT)) || (!(pfd->dwFlags & PFD_GENERIC_ACCELERATED) && !(pfd->dwFlags & PFD_GENERIC_FORMAT))) dinfo->rmethod = 1; else dinfo->rmethod = 0; /* Depths of colour buffers */ dinfo->pixel_size.rgba.r = pfd->cRedBits; dinfo->pixel_size.rgba.g = pfd->cGreenBits; dinfo->pixel_size.rgba.b = pfd->cBlueBits; dinfo->pixel_size.rgba.a = pfd->cAlphaBits; /* Depths of accumulation buffer */ dinfo->accum_size.rgba.r = pfd->cAccumRedBits; dinfo->accum_size.rgba.g = pfd->cAccumGreenBits; dinfo->accum_size.rgba.b = pfd->cAccumBlueBits; dinfo->accum_size.rgba.a = pfd->cAccumAlphaBits; /* Miscellaneous settings */ dinfo->doublebuffered = pfd->dwFlags & PFD_DOUBLEBUFFER; dinfo->stereo = pfd->dwFlags & PFD_STEREO; dinfo->aux_buffers = pfd->cAuxBuffers; dinfo->depth_size = pfd->cDepthBits; dinfo->stencil_size = pfd->cStencilBits; /* These are the component shifts, like Allegro's _rgb_*_shift_*. */ dinfo->r_shift = pfd->cRedShift; dinfo->g_shift = pfd->cGreenShift; dinfo->b_shift = pfd->cBlueShift; dinfo->a_shift = pfd->cAlphaShift; /* Multisampling isn't supported under Windows if we don't also use * WGL_ARB_pixel_format or WGL_EXT_pixel_format. */ dinfo->sample_buffers = 0; dinfo->samples = 0; /* Float depth/color isn't supported under Windows if we don't also use * AGL_ARB_pixel_format or WGL_EXT_pixel_format. */ dinfo->float_color = 0; dinfo->float_depth = 0; /* This bit is the same as the X code, setting some things based on * what we've read out of the PFD. */ dinfo->colour_depth = 0; if (dinfo->pixel_size.rgba.r == 5 && dinfo->pixel_size.rgba.b == 5) { if (dinfo->pixel_size.rgba.g == 5) dinfo->colour_depth = 15; if (dinfo->pixel_size.rgba.g == 6) dinfo->colour_depth = 16; } if (dinfo->pixel_size.rgba.r == 8 && dinfo->pixel_size.rgba.g == 8 && dinfo->pixel_size.rgba.b == 8) { if (dinfo->pixel_size.rgba.a == 8) dinfo->colour_depth = 32; else dinfo->colour_depth = 24; } dinfo->allegro_format = (dinfo->colour_depth != 0) && (dinfo->g_shift == dinfo->pixel_size.rgba.b) && (dinfo->r_shift * dinfo->b_shift == 0) && (dinfo->r_shift + dinfo->b_shift == dinfo->pixel_size.rgba.b + dinfo->pixel_size.rgba.g); return 0; } /* Decodes the pixel format into an agl_display_info struct and logs the pixel * format in the trace file. */ static int decode_pixel_format_attrib(struct allegro_gl_display_info *dinfo, int num_attribs, const int *attrib, const int *value, int desktop_depth) { int i; TRACE(PREFIX_I "Decoding: \n"); dinfo->samples = 0; dinfo->sample_buffers = 0; dinfo->float_depth = 0; dinfo->float_color = 0; for (i = 0; i < num_attribs; i++) { /* Not interested if it doesn't support OpenGL or window drawing or * RGBA. */ if (attrib[i] == WGL_SUPPORT_OPENGL_ARB && value[i] == 0) { TRACE(PREFIX_I "OpenGL Unsupported\n"); return -1; } else if (attrib[i] == WGL_DRAW_TO_WINDOW_ARB && value[i] == 0) { TRACE(PREFIX_I "Can't draw to window\n"); return -1; } else if (attrib[i] == WGL_PIXEL_TYPE_ARB && (value[i] != WGL_TYPE_RGBA_ARB && value[i] != WGL_TYPE_RGBA_FLOAT_ARB)) { TRACE(PREFIX_I "Not RGBA mode\n"); return -1; } /* Check for color depth matching */ else if (attrib[i] == WGL_COLOR_BITS_ARB) { if ((value[i] != desktop_depth) && (value[i] != 32 || desktop_depth < 24)) { TRACE(PREFIX_I "Current color depth != " "pixel format color depth\n"); //return -1; /* XXX Why is this a bad thing? */ } } /* hardware acceleration */ else if (attrib[i] == WGL_ACCELERATION_ARB) { dinfo->rmethod = (value[i] == WGL_NO_ACCELERATION_ARB) ? 0 : 1; } /* Depths of colour buffers */ else if (attrib[i] == WGL_RED_BITS_ARB) { dinfo->pixel_size.rgba.r = value[i]; } else if (attrib[i] == WGL_GREEN_BITS_ARB) { dinfo->pixel_size.rgba.g = value[i]; } else if (attrib[i] == WGL_BLUE_BITS_ARB) { dinfo->pixel_size.rgba.b = value[i]; } else if (attrib[i] == WGL_ALPHA_BITS_ARB) { dinfo->pixel_size.rgba.a = value[i]; } /* Shift of color components */ else if (attrib[i] == WGL_RED_SHIFT_ARB) { dinfo->r_shift = value[i]; } else if (attrib[i] == WGL_GREEN_SHIFT_ARB) { dinfo->g_shift = value[i]; } else if (attrib[i] == WGL_BLUE_SHIFT_ARB) { dinfo->b_shift = value[i]; } else if (attrib[i] == WGL_ALPHA_SHIFT_ARB) { dinfo->a_shift = value[i]; } /* Depths of accumulation buffer */ else if (attrib[i] == WGL_ACCUM_RED_BITS_ARB) { dinfo->accum_size.rgba.r = value[i]; } else if (attrib[i] == WGL_ACCUM_GREEN_BITS_ARB) { dinfo->accum_size.rgba.g = value[i]; } else if (attrib[i] == WGL_ACCUM_BLUE_BITS_ARB) { dinfo->accum_size.rgba.b = value[i]; } else if (attrib[i] == WGL_ACCUM_ALPHA_BITS_ARB) { dinfo->accum_size.rgba.a = value[i]; } /* Miscellaneous settings */ else if (attrib[i] == WGL_DOUBLE_BUFFER_ARB) { dinfo->doublebuffered = value[i]; } else if (attrib[i] == WGL_STEREO_ARB) { dinfo->stereo = value[i]; } else if (attrib[i] == WGL_AUX_BUFFERS_ARB) { dinfo->aux_buffers = value[i]; } else if (attrib[i] == WGL_DEPTH_BITS_ARB) { dinfo->depth_size = value[i]; } else if (attrib[i] == WGL_STENCIL_BITS_ARB) { dinfo->stencil_size = value[i]; } /* Multisampling bits */ else if (attrib[i] == WGL_SAMPLE_BUFFERS_ARB) { dinfo->sample_buffers = value[i]; } else if (attrib[i] == WGL_SAMPLES_ARB) { dinfo->samples = value[i]; } /* Float color */ if (attrib[i] == WGL_PIXEL_TYPE_ARB && value[i] == WGL_TYPE_RGBA_FLOAT_ARB) { dinfo->float_color = TRUE; } /* Float depth */ else if (attrib[i] == WGL_DEPTH_FLOAT_EXT) { dinfo->float_depth = value[i]; } } /* This bit is the same as the X code, setting some things based on * what we've read out of the PFD. */ dinfo->colour_depth = 0; if (dinfo->pixel_size.rgba.r == 5 && dinfo->pixel_size.rgba.b == 5) { if (dinfo->pixel_size.rgba.g == 5) dinfo->colour_depth = 15; if (dinfo->pixel_size.rgba.g == 6) dinfo->colour_depth = 16; } if (dinfo->pixel_size.rgba.r == 8 && dinfo->pixel_size.rgba.g == 8 && dinfo->pixel_size.rgba.b == 8) { if (dinfo->pixel_size.rgba.a == 8) dinfo->colour_depth = 32; else dinfo->colour_depth = 24; } dinfo->allegro_format = (dinfo->colour_depth != 0) && (dinfo->g_shift == dinfo->pixel_size.rgba.b) && (dinfo->r_shift * dinfo->b_shift == 0) && (dinfo->r_shift + dinfo->b_shift == dinfo->pixel_size.rgba.b + dinfo->pixel_size.rgba.g); return 0; } typedef struct format_t { int score; int format; } format_t; /* Helper function for sorting pixel formats by score */ static int select_pixel_format_sorter(const void *p0, const void *p1) { format_t *f0 = (format_t*)p0; format_t *f1 = (format_t*)p1; if (f0->score == f1->score) { return 0; } else if (f0->score > f1->score) { return -1; } else { return 1; } } /* Describes the pixel format and assigns it a score */ int describe_pixel_format_old(HDC dc, int fmt, int desktop_depth, format_t *formats, int *num_formats, struct allegro_gl_display_info *pdinfo) { struct allegro_gl_display_info dinfo; PIXELFORMATDESCRIPTOR pfd; int score = -1; int result = DescribePixelFormat(dc, fmt, sizeof(pfd), &pfd); /* Remember old settings */ if (pdinfo) { dinfo = *pdinfo; } if (!result) { log_win32_warning("describe_pixel_format_old", "DescribePixelFormat() failed!", GetLastError()); return -1; } result = !decode_pixel_format(&pfd, dc, fmt, &dinfo, desktop_depth); if (result) { print_pixel_format(&dinfo); score = __allegro_gl_score_config(fmt, &dinfo); } if (score < 0) { return -1; /* Reject non-compliant pixel formats */ } if (formats && num_formats) { formats[*num_formats].score = score; formats[*num_formats].format = fmt; (*num_formats)++; } if (pdinfo) { *pdinfo = dinfo; } return 0; } static AGL_GetPixelFormatAttribivARB_t __wglGetPixelFormatAttribivARB = NULL; static AGL_GetPixelFormatAttribivEXT_t __wglGetPixelFormatAttribivEXT = NULL; /* Describes the pixel format and assigns it a score */ int describe_pixel_format_new(HDC dc, int fmt, int desktop_depth, format_t *formats, int *num_formats, struct allegro_gl_display_info *pdinfo) { struct allegro_gl_display_info dinfo; int score = -1; /* Note: Even though we use te ARB suffix, all those enums are compatible * with EXT_pixel_format. */ int attrib[] = { WGL_SUPPORT_OPENGL_ARB, WGL_DRAW_TO_WINDOW_ARB, WGL_PIXEL_TYPE_ARB, WGL_ACCELERATION_ARB, WGL_DOUBLE_BUFFER_ARB, WGL_DEPTH_BITS_ARB, WGL_COLOR_BITS_ARB, WGL_RED_BITS_ARB, WGL_GREEN_BITS_ARB, WGL_BLUE_BITS_ARB, WGL_ALPHA_BITS_ARB, WGL_RED_SHIFT_ARB, WGL_GREEN_SHIFT_ARB, WGL_BLUE_SHIFT_ARB, WGL_ALPHA_SHIFT_ARB, WGL_STENCIL_BITS_ARB, WGL_STEREO_ARB, WGL_ACCUM_BITS_ARB, WGL_ACCUM_RED_BITS_ARB, WGL_ACCUM_GREEN_BITS_ARB, WGL_ACCUM_BLUE_BITS_ARB, WGL_ACCUM_ALPHA_BITS_ARB, WGL_AUX_BUFFERS_ARB, /* The following are used by extensions that add to WGL_pixel_format. * If WGL_p_f isn't supported though, we can't use the (then invalid) * enums. We can't use any magic number either, so we settle for * replicating one. The pixel format decoder * (decode_pixel_format_attrib()) doesn't care about duplicates. */ WGL_AUX_BUFFERS_ARB, /* placeholder for WGL_SAMPLE_BUFFERS_ARB */ WGL_AUX_BUFFERS_ARB, /* placeholder for WGL_SAMPLES_ARB */ WGL_AUX_BUFFERS_ARB, /* placeholder for WGL_DEPTH_FLOAT_EXT */ }; const int num_attribs = sizeof(attrib) / sizeof(attrib[0]); int *value = (int*)malloc(sizeof(int) * num_attribs); int result; BOOL ret; int old_valid = __allegro_gl_valid_context; /* Can't allocate mem? */ if (!value) { TRACE(PREFIX_E "describe_pixel_format_new(): Unable to allocate " "memory for pixel format descriptor!\n"); return -1; } /* Remember old settings */ if (pdinfo) { dinfo = *pdinfo; } /* If multisampling is supported, query for it. Note - we need to tell * allegro_gl_is_extension_supported() that we have a valid context, * even though AGL is not initialized yet. */ __allegro_gl_valid_context = 1; if (allegro_gl_is_extension_supported("WGL_ARB_multisample")) { attrib[num_attribs - 3] = WGL_SAMPLE_BUFFERS_ARB; attrib[num_attribs - 2] = WGL_SAMPLES_ARB; } if (allegro_gl_is_extension_supported("WGL_EXT_depth_float")) { attrib[num_attribs - 1] = WGL_DEPTH_FLOAT_EXT; } __allegro_gl_valid_context = old_valid; /* Get the pf attributes */ if (__wglGetPixelFormatAttribivARB) { ret = __wglGetPixelFormatAttribivARB(dc, fmt, 0, num_attribs, attrib, value); } else if (__wglGetPixelFormatAttribivEXT) { ret = __wglGetPixelFormatAttribivEXT(dc, fmt, 0, num_attribs, attrib, value); } else { ret = 0; } /* wglGetPixelFormatAttrib() failed? Abort and revert to old path */ if (!ret) { log_win32_error("describe_pixel_format_new", "wglGetPixelFormatAttrib failed!", GetLastError()); free(value); return -1; } /* Convert to AllegroGL format for scoring */ result = !decode_pixel_format_attrib(&dinfo, num_attribs, attrib, value, desktop_depth); free(value); if (result) { print_pixel_format(&dinfo); score = __allegro_gl_score_config(fmt, &dinfo); } if (score < 0) { return 0; /* Reject non-compliant pixel formats */ } if (formats && num_formats) { formats[*num_formats].score = score; formats[*num_formats].format = fmt; (*num_formats)++; } if (pdinfo) { *pdinfo = dinfo; } return 0; } /* Returns the number of pixel formats we should investigate */ int get_num_pixel_formats(HDC dc, int *new_pf_code) { /* DescribePixelFormat() returns maximum pixel format index in the old * code. wglGetPixelFormatAttribivARB() does it in the new code. */ if (new_pf_code && *new_pf_code) { int attrib[1]; int value[1]; TRACE(PREFIX_I "get_num_pixel_formats(): Attempting to use WGL_pf.\n"); attrib[0] = WGL_NUMBER_PIXEL_FORMATS_ARB; if ((__wglGetPixelFormatAttribivARB && __wglGetPixelFormatAttribivARB(dc, 0, 0, 1, attrib, value) == GL_FALSE) || (__wglGetPixelFormatAttribivEXT && __wglGetPixelFormatAttribivEXT(dc, 0, 0, 1, attrib, value) == GL_FALSE)) { log_win32_note("get_num_pixel_formats", "WGL_ARB/EXT_pixel_format use failed!", GetLastError()); *new_pf_code = 0; } else { return value[0]; } } if (!new_pf_code || !*new_pf_code) { PIXELFORMATDESCRIPTOR pfd; int ret; TRACE(PREFIX_I "get_num_pixel_formats(): Using DescribePixelFormat.\n"); ret = DescribePixelFormat(dc, 1, sizeof(pfd), &pfd); if (!ret) { log_win32_error("get_num_pixel_formats", "DescribePixelFormat failed!", GetLastError()); } return ret; } return 0; } /* Pick the best matching pixel format */ static int select_pixel_format(PIXELFORMATDESCRIPTOR * pfd) { int i; int result, maxindex; int desktop_depth; HWND testwnd = NULL; HDC testdc = NULL; HGLRC testrc = NULL; format_t *format = NULL; int num_formats = 0; int new_pf_code = 0; __allegro_gl_reset_scorer(); /* Read again the desktop depth */ desktop_depth = desktop_color_depth(); if (register_test_window() < 0) { return 0; } testwnd = create_test_window(); if (!testwnd) { return 0; } testdc = GetDC(testwnd); /* Check if we can support new pixel format code */ TRACE(PREFIX_I "select_pixel_format(): Trying to set up temporary RC\n"); { HDC old_dc = __allegro_gl_hdc; int old_valid = __allegro_gl_valid_context; PIXELFORMATDESCRIPTOR pfd; int pf; new_pf_code = 0; /* We need to create a dummy window with a pixel format to get the * list of valid PFDs */ memset(&pfd, 0, sizeof(pfd)); pfd.nSize = sizeof(pfd); pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER_DONTCARE | PFD_STEREO_DONTCARE; pfd.iPixelType = PFD_TYPE_RGBA; pfd.iLayerType = PFD_MAIN_PLANE; pfd.cColorBits = 32; TRACE(PREFIX_I "select_pixel_format(): ChoosePixelFormat()\n"); pf = ChoosePixelFormat(testdc, &pfd); if (!pf) { log_win32_warning("select_pixel_format", "Unable to chose a temporary pixel format!", GetLastError()); goto fail_pf; } /* Set up a GL context there */ TRACE(PREFIX_I "select_pixel_format(): SetPixelFormat()\n"); memset(&pfd, 0, sizeof(pfd)); if (!SetPixelFormat(testdc, pf, &pfd)) { log_win32_warning("select_pixel_format", "Unable to set a temporary pixel format!", GetLastError()); goto fail_pf; } TRACE(PREFIX_I "select_pixel_format(): CreateContext()\n"); testrc = wglCreateContext(testdc); if (!testrc) { log_win32_warning("select_pixel_format", "Unable to create a render context!", GetLastError()); goto fail_pf; } TRACE(PREFIX_I "select_pixel_format(): MakeCurrent()\n"); if (!wglMakeCurrent(testdc, testrc)) { log_win32_warning("select_pixel_format", "Unable to set the render context as current!", GetLastError()); goto fail_pf; } __allegro_gl_hdc = testdc; __allegro_gl_valid_context = TRUE; /* This is a workaround for a bug in old NVidia drivers. We need to * call wglGetExtensionsStringARB() for it to properly initialize. */ TRACE(PREFIX_I "select_pixel_format(): GetExtensionsStringARB()\n"); if (strstr((AL_CONST char*)glGetString(GL_VENDOR), "NVIDIA")) { AGL_GetExtensionsStringARB_t __wglGetExtensionsStringARB = NULL; __wglGetExtensionsStringARB = (AGL_GetExtensionsStringARB_t) wglGetProcAddress("wglGetExtensionsStringARB"); TRACE(PREFIX_I "select_pixel_format(): Querying for " "WGL_ARB_extension_string\n"); if (__wglGetExtensionsStringARB) { TRACE(PREFIX_I "select_pixel_format(): Calling " "__wglGetExtensionsStringARB\n"); __wglGetExtensionsStringARB(testdc); } } /* Check that we support ARB/EXT_pixel_format */ if (!allegro_gl_is_extension_supported("WGL_ARB_pixel_format") && !allegro_gl_is_extension_supported("WGL_EXT_pixel_format")) { TRACE(PREFIX_I "select_pixel_format(): WGL_ARB/EXT_pf unsupported.\n"); goto fail_pf; } /* Load the ARB_p_f symbol - Note, we shouldn't use the AGL extension * mechanism here, because AGL hasn't been initialized yet! */ TRACE(PREFIX_I "select_pixel_format(): GetProcAddress()\n"); __wglGetPixelFormatAttribivARB = (AGL_GetPixelFormatAttribivARB_t) wglGetProcAddress("wglGetPixelFormatAttribivARB"); __wglGetPixelFormatAttribivEXT = (AGL_GetPixelFormatAttribivEXT_t) wglGetProcAddress("wglGetPixelFormatAttribivEXT"); if (!__wglGetPixelFormatAttribivARB && !__wglGetPixelFormatAttribivEXT) { TRACE(PREFIX_E "select_pixel_format(): WGL_ARB/EXT_pf not " "correctly supported!\n"); goto fail_pf; } new_pf_code = 1; goto exit_pf; fail_pf: wglMakeCurrent(NULL, NULL); if (testrc) { wglDeleteContext(testrc); } testrc = NULL; __wglGetPixelFormatAttribivARB = NULL; __wglGetPixelFormatAttribivEXT = NULL; exit_pf: __allegro_gl_hdc = old_dc; __allegro_gl_valid_context = old_valid; } maxindex = get_num_pixel_formats(testdc, &new_pf_code); /* Check if using the new pf code failed. Likely due to driver bug. * maxindex is still valid though, so we can continue. */ if (!new_pf_code && testrc) { TRACE(PREFIX_W "select_pixel_format(): WGL_ARB_pf call failed - " "reverted to plain old WGL.\n"); wglMakeCurrent(NULL, NULL); wglDeleteContext(testrc); testrc = NULL; __wglGetPixelFormatAttribivARB = NULL; __wglGetPixelFormatAttribivEXT = NULL; } TRACE(PREFIX_I "select_pixel_format(): %i formats.\n", maxindex); if (maxindex < 1) { TRACE(PREFIX_E "select_pixel_format(): Didn't find any pixel " "formats at all!\n"); goto bail; } format = malloc((maxindex + 1) * sizeof(format_t)); if (!format) { TRACE(PREFIX_E "select_pixel_format(): Unable to allocate memory for " "pixel format scores!\n"); goto bail; } /* First, pixel formats are sorted by decreasing order */ TRACE(PREFIX_I "select_pixel_format(): Testing pixel formats:\n"); for (i = 1; i <= maxindex; i++) { int use_old = !new_pf_code; TRACE(PREFIX_I "Format %i:\n", i); if (new_pf_code) { if (describe_pixel_format_new(testdc, i, desktop_depth, format, &num_formats, NULL) < 0) { TRACE(PREFIX_W "select_pixel_format(): Wasn't able to use " "WGL_PixelFormat - reverting to old WGL code.\n"); use_old = 1; } } if (use_old) { if (describe_pixel_format_old(testdc, i, desktop_depth, format, &num_formats, NULL) < 0) { TRACE(PREFIX_W "select_pixel_format(): Unable to rely on " "unextended WGL to describe this pixelformat.\n"); } } } if (new_pf_code) { wglMakeCurrent(NULL, NULL); wglDeleteContext(testrc); testrc = NULL; } if (testwnd) { ReleaseDC(testwnd, testdc); testdc = NULL; DestroyWindow(testwnd); testwnd = NULL; } if (num_formats < 1) { TRACE(PREFIX_E "select_pixel_format(): Didn't find any available " "pixel formats!\n"); goto bail; } qsort(format, num_formats, sizeof(format_t), select_pixel_format_sorter); /* Sorted pixel formats are tested until one of them succeeds to * make a GL context current */ for (i = 0; i < num_formats ; i++) { HGLRC rc; /* Recreate our test windows */ testwnd = create_test_window(); testdc = GetDC(testwnd); if (SetPixelFormat(testdc, format[i].format, pfd)) { rc = wglCreateContext(testdc); if (!rc) { TRACE(PREFIX_I "select_pixel_format(): Unable to create RC!\n"); } else { if (wglMakeCurrent(testdc, rc)) { wglMakeCurrent(NULL, NULL); wglDeleteContext(rc); rc = NULL; TRACE(PREFIX_I "select_pixel_format(): Best config is: %i" "\n", format[i].format); /* XXX DescribePixelFormat may fail on * extended pixel format (WGL_ARB_p_f) */ if (!DescribePixelFormat(testdc, format[i].format, sizeof *pfd, pfd)) { TRACE(PREFIX_E "Cannot describe this pixel format\n"); ReleaseDC(testwnd, testdc); DestroyWindow(testwnd); testdc = NULL; testwnd = NULL; continue; } ReleaseDC(testwnd, testdc); DestroyWindow(testwnd); result = format[i].format; free(format); return result; } else { wglMakeCurrent(NULL, NULL); wglDeleteContext(rc); rc = NULL; log_win32_warning("select_pixel_format", "Couldn't make the temporary render context " "current for the this pixel format.", GetLastError()); } } } else { log_win32_note("select_pixel_format", "Unable to set pixel format!", GetLastError()); } ReleaseDC(testwnd, testdc); DestroyWindow(testwnd); testdc = NULL; testwnd = NULL; } TRACE(PREFIX_E "select_pixel_format(): All modes have failed...\n"); bail: if (format) { free(format); } if (new_pf_code) { wglMakeCurrent(NULL, NULL); if (testrc) { wglDeleteContext(testrc); } } if (testwnd) { ReleaseDC(testwnd, testdc); DestroyWindow(testwnd); } return 0; } static void allegrogl_init_window(int w, int h, DWORD style, DWORD exstyle) { RECT rect; #define req __allegro_gl_required_settings #define sug __allegro_gl_suggested_settings int x = 32, y = 32; if (req & AGL_WINDOW_X || sug & AGL_WINDOW_X) x = allegro_gl_display_info.x; if (req & AGL_WINDOW_Y || sug & AGL_WINDOW_Y) y = allegro_gl_display_info.y; #undef req #undef sug if (!fullscreen) { rect.left = x; rect.right = x + w; rect.top = y; rect.bottom = y + h; } else { rect.left = 0; rect.right = w; rect.top = 0; rect.bottom = h; } /* save original Allegro styles */ style_saved = GetWindowLong(wnd, GWL_STYLE); exstyle_saved = GetWindowLong(wnd, GWL_EXSTYLE); /* set custom AllegroGL style */ SetWindowLong(wnd, GWL_STYLE, style); SetWindowLong(wnd, GWL_EXSTYLE, exstyle); if (!fullscreen) { AdjustWindowRectEx(&rect, style, FALSE, exstyle); } /* make the changes visible */ SetWindowPos(wnd, 0, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_NOZORDER | SWP_FRAMECHANGED); return; } static BITMAP *allegro_gl_create_screen (GFX_DRIVER *drv, int w, int h, int depth) { BITMAP *bmp; int is_linear = drv->linear; drv->linear = 1; bmp = _make_bitmap (w, h, 0, drv, depth, 0); if (!bmp) { return NULL; } bmp->id = BMP_ID_VIDEO | 1000; drv->linear = is_linear; drv->w = w; drv->h = h; return bmp; } static LRESULT CALLBACK dummy_wnd_proc(HWND wnd, UINT message, WPARAM wparam, LPARAM lparam) { return DefWindowProc(wnd, message, wparam, lparam); } static HWND dummy_wnd; static void dummy_window(void) { WNDCLASS wnd_class; wnd_class.style = CS_HREDRAW | CS_VREDRAW; wnd_class.lpfnWndProc = dummy_wnd_proc; wnd_class.cbClsExtra = 0; wnd_class.cbWndExtra = 0; wnd_class.hInstance = GetModuleHandle(NULL); wnd_class.hIcon = LoadIcon(NULL, IDI_APPLICATION); wnd_class.hCursor = LoadCursor(NULL, IDC_ARROW); wnd_class.hbrBackground = NULL; wnd_class.lpszMenuName = NULL; wnd_class.lpszClassName = "allegro focus"; RegisterClass(&wnd_class); dummy_wnd = CreateWindow("allegro focus", "Allegro", WS_POPUP | WS_VISIBLE, 0, 0, 200, 200, NULL, NULL, GetModuleHandle(NULL), NULL); ShowWindow(dummy_wnd, SW_SHOWNORMAL); SetForegroundWindow(dummy_wnd); } static void remove_dummy_window(void) { DestroyWindow(dummy_wnd); UnregisterClass("allegro focus", GetModuleHandle(NULL)); } static BITMAP *allegro_gl_win_init(int w, int h, int v_w, int v_h) { static int first_time = 1; DWORD style=0, exstyle=0; int refresh_rate = _refresh_rate_request; int desktop_depth; int pf=0; new_w = w; new_h = h; /* virtual screen are not supported */ if ((v_w != 0 && v_w != w) || (v_h != 0 && v_h != h)) { TRACE(PREFIX_E "win_init(): Virtual screens are not supported in " "AllegroGL!\n"); return NULL; } /* Fill in missing color depth info */ __allegro_gl_fill_in_info(); /* Be sure the current desktop color depth is at least 15bpp */ /* We may want to change this, so try to set a better depth, or to at least report an error somehow */ desktop_depth = desktop_color_depth(); if (desktop_depth < 15) return NULL; TRACE(PREFIX_I "win_init(): Requested color depth: %i " "Desktop color depth: %i\n", allegro_gl_display_info.colour_depth, desktop_depth); /* In the moment the main window is destroyed, Allegro loses focus, and * focus can only be returned by actual user input under Windows XP. So * we need to create a dummy window which retains focus for us, until * the new window is up. */ if (fullscreen) dummy_window(); /* Need to set the w and h driver members at this point to avoid assertion * failure in set_mouse_range() when win_set_window() is called. */ if (fullscreen) { gfx_allegro_gl_fullscreen.w = w; gfx_allegro_gl_fullscreen.h = h; } else { gfx_allegro_gl_windowed.w = w; gfx_allegro_gl_windowed.h = h; } /* request a fresh new window from Allegro... */ /* Set a NULL window to get Allegro to generate a new HWND. This is needed * because we can only set the pixel format once per window. Thus, calling * set_gfx_mode() multiple times will fail without this code. */ if (!first_time) { win_set_window(NULL); } first_time = 0; /* ...and retrieve its handle */ wnd = win_get_window(); if (!wnd) return NULL; /* set up the AllegroGL window */ if (fullscreen) { style = WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS; exstyle = WS_EX_APPWINDOW | WS_EX_TOPMOST; } else { style = WS_SYSMENU | WS_CAPTION | WS_MINIMIZEBOX | WS_CLIPCHILDREN | WS_CLIPSIBLINGS; exstyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; } TRACE(PREFIX_I "win_init(): Setting up window.\n"); allegrogl_init_window(w, h, style, exstyle); __allegro_gl_hdc = GetDC(wnd); /* get the device context of our window */ if (!__allegro_gl_hdc) { goto Error; } TRACE(PREFIX_I "win_init(): Driver selected fullscreen: %s\n", fullscreen ? "Yes" : "No"); if (fullscreen) { DEVMODE dm; DEVMODE fallback_dm; int fallback_dm_valid = 0; int bpp_to_check[] = {16, 32, 24, 15, 0}; int bpp_checked[] = {0, 0, 0, 0, 0}; int bpp_index = 0; int i, j, result, modeswitch, done = 0; for (j = 0; j < 4; j++) { if (bpp_to_check[j] == allegro_gl_get(AGL_COLOR_DEPTH)) { bpp_index = j; break; } } dm.dmSize = sizeof(DEVMODE); dm_saved.dmSize = sizeof(DEVMODE); /* Save old mode */ EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dm_saved); dm.dmBitsPerPel = desktop_depth; /* Go around Win95's bug */ do { if (!bpp_to_check[bpp_index]) { TRACE(PREFIX_E "win_init(): No more color depths to test.\n" "\tUnable to find appropriate full screen mode and pixel " "format.\n"); goto Error; } TRACE(PREFIX_I "win_init(): Testing color depth: %i\n", bpp_to_check[bpp_index]); memset(&dm, 0, sizeof(DEVMODE)); dm.dmSize = sizeof(DEVMODE); i = 0; do { modeswitch = EnumDisplaySettings(NULL, i, &dm); if (!modeswitch) break; if ((dm.dmPelsWidth == (unsigned) w) && (dm.dmPelsHeight == (unsigned) h) && (dm.dmBitsPerPel == (unsigned) bpp_to_check[bpp_index]) && (dm.dmDisplayFrequency != (unsigned) refresh_rate)) { /* Keep it as fallback if refresh rate request could not * be satisfied. Try to get as close to 60Hz as possible though, * it's a bit better for a fallback than just blindly picking * something like 47Hz or 200Hz. */ if (!fallback_dm_valid) { fallback_dm = dm; fallback_dm_valid = 1; } else if (dm.dmDisplayFrequency >= 60) { if (dm.dmDisplayFrequency < fallback_dm.dmDisplayFrequency) { fallback_dm = dm; } } } i++; } while ((dm.dmPelsWidth != (unsigned) w) || (dm.dmPelsHeight != (unsigned) h) || (dm.dmBitsPerPel != (unsigned) bpp_to_check[bpp_index]) || (dm.dmDisplayFrequency != (unsigned) refresh_rate)); if (!modeswitch && !fallback_dm_valid) { TRACE(PREFIX_I "win_init(): Unable to set mode, continuing " "with next color depth\n"); } else { if (!modeswitch && fallback_dm_valid) dm = fallback_dm; TRACE(PREFIX_I "win_init(): bpp_to_check[bpp_index] = %i\n", bpp_to_check[bpp_index]); TRACE(PREFIX_I "win_init(): dm.dmBitsPerPel = %i\n", (int)dm.dmBitsPerPel); dm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | DM_DISPLAYFREQUENCY; result = ChangeDisplaySettings(&dm, CDS_FULLSCREEN); if (result == DISP_CHANGE_SUCCESSFUL) { TRACE(PREFIX_I "win_init(): Setting pixel format.\n"); pf = select_pixel_format(&pfd); if (pf) { TRACE(PREFIX_I "mode found\n"); _set_current_refresh_rate(dm.dmDisplayFrequency); done = 1; } else { TRACE(PREFIX_I "win_init(): Couldn't find compatible " "GL context. Trying another screen mode.\n"); } } } fallback_dm_valid = 0; bpp_checked[bpp_index] = 1; bpp_index = 0; while (bpp_checked[bpp_index]) { bpp_index++; } } while (!done); } else { DEVMODE dm; memset(&dm, 0, sizeof(DEVMODE)); dm.dmSize = sizeof(DEVMODE); if (EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dm) != 0) { _set_current_refresh_rate(dm.dmDisplayFrequency); } } if (!fullscreen) { TRACE(PREFIX_I "win_init(): Setting pixel format.\n"); pf = select_pixel_format(&pfd); if (pf == 0) goto Error; } /* set the pixel format */ if (!SetPixelFormat(__allegro_gl_hdc, pf, &pfd)) { log_win32_error("win_init", "Unable to set pixel format.", GetLastError()); goto Error; } /* create an OpenGL context */ allegro_glrc = wglCreateContext(__allegro_gl_hdc); if (!allegro_glrc) { /* make the context the current one */ log_win32_error("win_init", "Unable to create a render context!", GetLastError()); goto Error; } if (!wglMakeCurrent(__allegro_gl_hdc, allegro_glrc)) { log_win32_error("win_init", "Unable to make the context current!", GetLastError()); goto Error; } if (__wglGetPixelFormatAttribivARB || __wglGetPixelFormatAttribivEXT) { describe_pixel_format_new(__allegro_gl_hdc, pf, desktop_depth, NULL, NULL, &allegro_gl_display_info); } else { describe_pixel_format_old(__allegro_gl_hdc, pf, desktop_depth, NULL, NULL, &allegro_gl_display_info); } __allegro_gl_set_allegro_image_format(FALSE); set_color_depth(allegro_gl_display_info.colour_depth); allegro_gl_display_info.w = w; allegro_gl_display_info.h = h; /* Win98/2k/XP's window forground rules don't let us * make our window the topmost window on launch. This causes issues on * full-screen apps, as DInput loses input focus on them. * We use this trick to force the window to be topmost, when switching * to full-screen only. Note that this only works for Win98 and greater. * Win95 will ignore our SystemParametersInfo() calls. * * See http://support.microsoft.com:80/support/kb/articles/Q97/9/25.asp * for details. */ { DWORD lock_time; #define SPI_GETFOREGROUNDLOCKTIMEOUT 0x2000 #define SPI_SETFOREGROUNDLOCKTIMEOUT 0x2001 if (fullscreen) { SystemParametersInfo(SPI_GETFOREGROUNDLOCKTIMEOUT, 0, (LPVOID)&lock_time, 0); SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, (LPVOID)0, SPIF_SENDWININICHANGE | SPIF_UPDATEINIFILE); } ShowWindow(wnd, SW_SHOWNORMAL); SetForegroundWindow(wnd); /* In some rare cases, it doesn't seem to work without the loop. And we * absolutely need this to succeed, else we trap the user in a * fullscreen window without input. */ while (GetForegroundWindow() != wnd) { rest(100); SetForegroundWindow(wnd); } UpdateWindow(wnd); if (fullscreen) { SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, (LPVOID)lock_time, SPIF_SENDWININICHANGE | SPIF_UPDATEINIFILE); } #undef SPI_GETFOREGROUNDLOCKTIMEOUT #undef SPI_SETFOREGROUNDLOCKTIMEOUT } win_grab_input(); if (fullscreen) { allegro_gl_screen= allegro_gl_create_screen(&gfx_allegro_gl_fullscreen, w, h, allegro_gl_get(AGL_COLOR_DEPTH)); } else { allegro_gl_screen= allegro_gl_create_screen(&gfx_allegro_gl_windowed, w, h, allegro_gl_get(AGL_COLOR_DEPTH)); } if (!allegro_gl_screen) { ChangeDisplaySettings(NULL, 0); goto Error; } TRACE(PREFIX_I "win_init(): GLScreen: %ix%ix%i\n", w, h, allegro_gl_get(AGL_COLOR_DEPTH)); allegro_gl_screen->id |= BMP_ID_VIDEO | BMP_ID_MASK; __allegro_gl_valid_context = TRUE; __allegro_gl_driver = &allegro_gl_win; initialized = 1; /* Print out OpenGL version info */ TRACE(PREFIX_I "OpenGL Version: %s\n", (AL_CONST char*)glGetString(GL_VERSION)); TRACE(PREFIX_I "Vendor: %s\n", (AL_CONST char*)glGetString(GL_VENDOR)); TRACE(PREFIX_I "Renderer: %s\n\n", (AL_CONST char*)glGetString(GL_RENDERER)); /* Detect if the GL driver is based on Mesa */ allegro_gl_info.is_mesa_driver = FALSE; if (strstr((AL_CONST char*)glGetString(GL_VERSION),"Mesa")) { AGL_LOG(1, "OpenGL driver based on Mesa\n"); allegro_gl_info.is_mesa_driver = TRUE; } /* init the GL extensions */ __allegro_gl_manage_extensions(); /* Update screen vtable in order to use AGL's */ __allegro_gl__glvtable_update_vtable(&allegro_gl_screen->vtable); memcpy(&_screen_vtable, allegro_gl_screen->vtable, sizeof(GFX_VTABLE)); allegro_gl_screen->vtable = &_screen_vtable; /* Print out WGL extension info */ if (wglGetExtensionsStringARB) { AGL_LOG(1, "WGL Extensions :\n"); #if LOGLEVEL >= 1 __allegro_gl_print_extensions((AL_CONST char*)wglGetExtensionsStringARB(wglGetCurrentDC())); #endif } else { TRACE(PREFIX_I "win_init(): No WGL Extensions available\n"); } gfx_capabilities |= GFX_HW_CURSOR; /* Initialize a reasonable viewport. Those should be OpenGL defaults, * but some drivers don't implement this correctly. */ glViewport(0, 0, SCREEN_W, SCREEN_H); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); if (allegro_gl_extensions_GL.ARB_multisample) { /* Workaround some "special" drivers that do not export the extension * once it was promoted to core.*/ if (allegro_gl_opengl_version() >= 1.3) glSampleCoverage(1.0, GL_FALSE); else glSampleCoverageARB(1.0, GL_FALSE); } /* Set up some variables that some GL drivers omit */ glBindTexture(GL_TEXTURE_2D, 0); screen = allegro_gl_screen; if (fullscreen) remove_dummy_window(); return allegro_gl_screen; Error: if (allegro_glrc) { wglDeleteContext(allegro_glrc); } if (__allegro_gl_hdc) { ReleaseDC(wnd, __allegro_gl_hdc); } __allegro_gl_hdc = NULL; ChangeDisplaySettings(NULL, 0); allegro_gl_win_exit(NULL); return NULL; } static BITMAP *allegro_gl_win_init_windowed(int w, int h, int v_w, int v_h, int color_depth) { fullscreen = 0; return allegro_gl_win_init(w, h, v_w, v_h); } static BITMAP *allegro_gl_win_init_fullscreen(int w, int h, int v_w, int v_h, int color_depth) { fullscreen = 1; return allegro_gl_win_init(w, h, v_w, v_h); } static void allegro_gl_win_exit(struct BITMAP *b) { /* XXX For some reason, uncommenting this line will blank * out the log file. */ //TRACE(PREFIX_I "allegro_gl_win_exit: Shutting down.\n"); __allegro_gl_unmanage_extensions(); if (allegro_glrc) { wglDeleteContext(allegro_glrc); allegro_glrc = NULL; } if (__allegro_gl_hdc) { ReleaseDC(wnd, __allegro_gl_hdc); __allegro_gl_hdc = NULL; } if (fullscreen && initialized) { /* Restore screen */ ChangeDisplaySettings(NULL, 0); _set_current_refresh_rate(0); } initialized = 0; /* Note: Allegro will destroy screen (== allegro_gl_screen), * so don't destroy it here. */ //destroy_bitmap(allegro_gl_screen); allegro_gl_screen = NULL; /* hide the window */ system_driver->restore_console_state(); /* restore original Allegro styles */ SetWindowLong(wnd, GWL_STYLE, style_saved); SetWindowLong(wnd, GWL_EXSTYLE, exstyle_saved); SetWindowPos(wnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED); __allegro_gl_valid_context = FALSE; return; } /* Returns TRUE is dm doesn't match any mode in mode_list, FALSE otherwise. */ static int is_mode_entry_unique(GFX_MODE_LIST *mode_list, DEVMODE *dm) { int i; for (i = 0; i < mode_list->num_modes; ++i) { if (mode_list->mode[i].width == (int)dm->dmPelsWidth && mode_list->mode[i].height == (int)dm->dmPelsHeight && mode_list->mode[i].bpp == (int)dm->dmBitsPerPel) return FALSE; } return TRUE; } /* Returns a list of valid video modes */ static GFX_MODE_LIST* allegro_gl_win_fetch_mode_list(void) { int c, modes_count; GFX_MODE_LIST *mode_list; DEVMODE dm; dm.dmSize = sizeof(DEVMODE); /* Allocate space for mode list. */ mode_list = malloc(sizeof(GFX_MODE_LIST)); if (!mode_list) { return NULL; } /* Allocate and fill the first mode in case EnumDisplaySettings fails at * first call. */ mode_list->mode = malloc(sizeof(GFX_MODE)); if (!mode_list->mode) { free(mode_list); return NULL; } mode_list->mode[0].width = 0; mode_list->mode[0].height = 0; mode_list->mode[0].bpp = 0; mode_list->num_modes = 0; modes_count = 0; c = 0; while (EnumDisplaySettings(NULL, c, &dm)) { mode_list->mode = realloc(mode_list->mode, sizeof(GFX_MODE) * (modes_count + 2)); if (!mode_list->mode) { free(mode_list); return NULL; } /* Filter modes with bpp lower than 9, and those which are already * in there. */ if (dm.dmBitsPerPel > 8 && is_mode_entry_unique(mode_list, &dm)) { mode_list->mode[modes_count].width = dm.dmPelsWidth; mode_list->mode[modes_count].height = dm.dmPelsHeight; mode_list->mode[modes_count].bpp = dm.dmBitsPerPel; ++modes_count; mode_list->mode[modes_count].width = 0; mode_list->mode[modes_count].height = 0; mode_list->mode[modes_count].bpp = 0; mode_list->num_modes = modes_count; } ++c; }; return mode_list; } /* AllegroGL driver routines */ static void flip(void) { SwapBuffers(__allegro_gl_hdc); } static void gl_on(void) { return; } static void gl_off(void) { return; } /* AllegroGL driver */ static struct allegro_gl_driver allegro_gl_win = { flip, gl_on, gl_off, NULL }; allegro4.4-4.4.2/addons/allegrogl/src/x.c000066400000000000000000001330041173507505700200310ustar00rootroot00000000000000/* This code is (C) AllegroGL contributors, and double licensed under * the GPL and zlib licenses. See gpl.txt or zlib.txt for details. */ /*---------------------------------------------------------------- * x.c -- Allegro-GLX interfacing *---------------------------------------------------------------- * This is the interface module for use under X. */ #include #include #include #include #include #include "alleggl.h" #include "allglint.h" #include "glvtable.h" #ifndef XLOCK #define OLD_ALLEGRO #define XLOCK() DISABLE() #undef XUNLOCK #define XUNLOCK() ENABLE() #endif #define PREFIX_I "agl-x INFO: " #define PREFIX_E "agl-x ERROR: " #ifdef ALLEGRO_XWINDOWS_WITH_XPM #include extern void *allegro_icon; #endif static BITMAP *allegro_gl_x_windowed_init(int w, int h, int vw, int vh, int color_depth); static void allegro_gl_x_exit(BITMAP *bmp); #ifdef ALLEGROGL_HAVE_XF86VIDMODE static GFX_MODE_LIST* allegro_gl_x_fetch_mode_list(void); #endif static void allegro_gl_x_vsync(void); static void allegro_gl_x_hide_mouse(void); static BITMAP *allegro_gl_screen = NULL; /* TODO: Revamp the whole window handling under X11 in Allegro and * AllegroGL. We really shouldn't have to duplicate code or hack on * Allegro internals in AllegroGL - the *only* difference for the AllegroGL * window should be the GLX visual (e.g. cursor, icon, VidModeExtension and * so on should never have been touched in this file). */ #if GET_ALLEGRO_VERSION() >= MAKE_VER(4, 2, 1) static Window backup_allegro_window = None; static Colormap backup_allegro_colormap = None; #endif static BITMAP *allegro_gl_x_fullscreen_init(int w, int h, int vw, int vh, int color_depth); GFX_DRIVER gfx_allegro_gl_fullscreen = { GFX_OPENGL_FULLSCREEN, empty_string, empty_string, "AllegroGL Fullscreen (X)", allegro_gl_x_fullscreen_init, allegro_gl_x_exit, NULL, allegro_gl_x_vsync, NULL, NULL, NULL, NULL, allegro_gl_create_video_bitmap, allegro_gl_destroy_video_bitmap, NULL, NULL, /* No show/request video bitmaps */ NULL, NULL, allegro_gl_set_mouse_sprite, allegro_gl_show_mouse, allegro_gl_x_hide_mouse, allegro_gl_move_mouse, allegro_gl_drawing_mode, NULL, NULL, allegro_gl_set_blender_mode, #ifdef ALLEGROGL_HAVE_XF86VIDMODE allegro_gl_x_fetch_mode_list, #else NULL, #endif 0, 0, 0, 0, 0, 0, 0, FALSE /* Windowed mode */ }; GFX_DRIVER gfx_allegro_gl_windowed = { GFX_OPENGL_WINDOWED, empty_string, empty_string, "AllegroGL Windowed (X)", allegro_gl_x_windowed_init, allegro_gl_x_exit, NULL, allegro_gl_x_vsync, NULL, NULL, NULL, NULL, allegro_gl_create_video_bitmap, allegro_gl_destroy_video_bitmap, NULL, NULL, /* No show/request video bitmaps */ NULL, NULL, allegro_gl_set_mouse_sprite, allegro_gl_show_mouse, allegro_gl_x_hide_mouse, allegro_gl_move_mouse, allegro_gl_drawing_mode, NULL, NULL, allegro_gl_set_blender_mode, NULL, /* No fetch_mode_list */ 0, 0, 0, 0, 0, 0, 0, TRUE /* Windowed mode */ }; static struct allegro_gl_driver allegro_gl_x; static XVisualInfo *allegro_gl_x_windowed_choose_visual (void); static int allegro_gl_x_create_window (int fullscreen); static BITMAP *allegro_gl_x_windowed_create_screen (GFX_DRIVER *drv, int w, int h, int depth); static int decode_visual (XVisualInfo *v, struct allegro_gl_display_info *i); struct { int fullscreen; GLXContext ctx; int major, minor; /* Major and minor GLX version */ int error_base, event_base; int use_glx_window; GLXWindow window; } _glxwin; static void (*old_window_redrawer)(int, int, int, int); extern void (*_xwin_window_redrawer)(int, int, int, int); static int (*old_x_error_handler)(Display*, XErrorEvent*); /* allegro_gl_redraw_window : * Redraws the window when an Expose event is processed * Important note : no GL commands should be processed in this function * since it may be called by a thread which is different from the main thread. * In order to be able to process GL commands, we should create another context * and make it current to the other thread. IMHO it would be overkill. */ static void allegro_gl_redraw_window(int x, int y, int w, int h) { /* Does nothing */ return; } #ifdef ALLEGRO_XWINDOWS_WITH_XCURSOR /* _xwin_hide_x_mouse: * Create invisible X cursor */ static void _xwin_hide_x_mouse(void) { unsigned long gcmask; XGCValues gcvalues; Pixmap pixmap; XUndefineCursor(_xwin.display, _xwin.window); if (_xwin.cursor != None) { XFreeCursor(_xwin.display, _xwin.cursor); _xwin.cursor = None; } if (_xwin.xcursor_image != None) { XcursorImageDestroy(_xwin.xcursor_image); _xwin.xcursor_image = None; } pixmap = XCreatePixmap(_xwin.display, _xwin.window, 1, 1, 1); if (pixmap != None) { GC temp_gc; XColor color; gcmask = GCFunction | GCForeground | GCBackground; gcvalues.function = GXcopy; gcvalues.foreground = 0; gcvalues.background = 0; temp_gc = XCreateGC(_xwin.display, pixmap, gcmask, &gcvalues); XDrawPoint(_xwin.display, pixmap, temp_gc, 0, 0); XFreeGC(_xwin.display, temp_gc); color.pixel = 0; color.red = color.green = color.blue = 0; color.flags = DoRed | DoGreen | DoBlue; _xwin.cursor = XCreatePixmapCursor(_xwin.display, pixmap, pixmap, &color, &color, 0, 0); XDefineCursor(_xwin.display, _xwin.window, _xwin.cursor); XFreePixmap(_xwin.display, pixmap); } else { _xwin.cursor = XCreateFontCursor(_xwin.display, _xwin.cursor_shape); XDefineCursor(_xwin.display, _xwin.window, _xwin.cursor); } } #endif /* hide_mouse: * Hide the custom X cursor (if supported) */ static void hide_mouse(void) { #ifdef ALLEGRO_XWINDOWS_WITH_XCURSOR if (_xwin.support_argb_cursor) { XLOCK(); _xwin_hide_x_mouse(); XUNLOCK(); } #endif return; } /* If Allegro's X11 mouse driver enabled hw cursors, we shouldn't use * allegro_gl_hide_mouse(); */ static void allegro_gl_x_hide_mouse(void) { if (_xwin.hw_cursor_ok) { hide_mouse(); } else { allegro_gl_hide_mouse(); } } /* allegro_gl_x_windowed_init: * Creates screen bitmap. */ static BITMAP *allegro_gl_x_create_screen(int w, int h, int vw, int vh, int depth, int fullscreen) { int _keyboard_was_installed = FALSE; int _mouse_was_installed = FALSE; int create_window_ret; /* test if Allegro have pthread support enabled */ if (!_unix_bg_man->multi_threaded) { ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE, get_config_text("Fatal Error : pthread support is not enabled")); return NULL; } if (keyboard_driver) { _keyboard_was_installed = TRUE; remove_keyboard(); TRACE(PREFIX_I "x_create_screen: Removing Keyboard...\n"); } if (mouse_driver) { _mouse_was_installed = TRUE; remove_mouse(); TRACE(PREFIX_I "x_create_screen: Removing Mouse...\n"); } XLOCK(); if (!glXQueryExtension(_xwin.display, &_glxwin.error_base, &_glxwin.event_base)) { ustrzcpy (allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("GLX Extension not supported by display")); XUNLOCK(); goto failure; } sscanf(glXQueryServerString(_xwin.display, _xwin.screen, GLX_VERSION), "%i.%i", &_glxwin.major, &_glxwin.minor); if ((w == 0) && (h == 0)) { w = 640; h = 480; } if ((vw > w) || (vh > h)) { ustrzcpy (allegro_error, ALLEGRO_ERROR_SIZE, get_config_text ("OpenGL drivers do not support virtual screens")); XUNLOCK(); goto failure; } allegro_gl_display_info.w = w; allegro_gl_display_info.h = h; old_window_redrawer = _xwin_window_redrawer; _xwin_window_redrawer = allegro_gl_redraw_window; _glxwin.fullscreen = FALSE; _glxwin.use_glx_window = FALSE; create_window_ret = allegro_gl_x_create_window(fullscreen); if (create_window_ret) { if (fullscreen && create_window_ret == -2) { ustrzcpy (allegro_error, ALLEGRO_ERROR_SIZE, get_config_text ("Unable to switch in GLX fullscreen")); } else if (create_window_ret == -2) { ustrzcpy (allegro_error, ALLEGRO_ERROR_SIZE, get_config_text ("Unable to create GLX window")); } XUNLOCK(); allegro_gl_x_exit(NULL); goto failure; } /* If pixel format is Allegro compatible, set up Allegro correctly. */ set_color_depth(allegro_gl_display_info.colour_depth); /* XXX X can run on Big-Endian systems. We need to * make a check for that and pass TRUE to * __allegro_gl_set_allegro_image_format() in that case. */ __allegro_gl_set_allegro_image_format(FALSE); if (fullscreen) { allegro_gl_screen = allegro_gl_x_windowed_create_screen (&gfx_allegro_gl_fullscreen, allegro_gl_display_info.w, allegro_gl_display_info.h, _color_depth); } else { allegro_gl_screen = allegro_gl_x_windowed_create_screen (&gfx_allegro_gl_windowed, allegro_gl_display_info.w, allegro_gl_display_info.h, _color_depth); } if (!allegro_gl_screen) { ustrzcpy (allegro_error, ALLEGRO_ERROR_SIZE, get_config_text ("Error creating screen bitmap")); XUNLOCK(); allegro_gl_x_exit(NULL); goto failure; } __allegro_gl_valid_context = TRUE; __allegro_gl_driver = &allegro_gl_x; /* Print out OpenGL version info */ TRACE(PREFIX_I "OpenGL Version: %s\n", (AL_CONST char*)glGetString(GL_VERSION)); TRACE(PREFIX_I "OpenGL Vendor: %s\n", (AL_CONST char*)glGetString(GL_VENDOR)); TRACE(PREFIX_I "OpenGL Renderer: %s\n", (AL_CONST char*)glGetString(GL_RENDERER)); /* Detect if the GL driver is based on Mesa */ allegro_gl_info.is_mesa_driver = FALSE; if (strstr((AL_CONST char*)glGetString(GL_VERSION),"Mesa")) { AGL_LOG(1, "OpenGL driver based on Mesa\n"); allegro_gl_info.is_mesa_driver = TRUE; } /* Print out GLX version info */ TRACE(PREFIX_I "GLX Version: %d.%d\n", _glxwin.major, _glxwin.minor); #ifdef LOGLEVEL if (glXIsDirect(_xwin.display, _glxwin.ctx)) { AGL_LOG(1, "GLX Direct Rendering is enabled\n"); } else { AGL_LOG(1, "GLX Direct Rendering is disabled\n"); } #endif /* Prints out GLX extensions info */ AGL_LOG(1, "glX Extensions:\n"); #ifdef LOGLEVEL __allegro_gl_print_extensions( (AL_CONST char*)glXQueryExtensionsString(_xwin.display, _xwin.screen)); #endif /* Prints out OpenGL extensions info and activates needed extensions */ __allegro_gl_manage_extensions(); /* Update screen vtable in order to use AGL's */ __allegro_gl__glvtable_update_vtable (&allegro_gl_screen->vtable); memcpy(&_screen_vtable, allegro_gl_screen->vtable, sizeof(GFX_VTABLE)); allegro_gl_screen->vtable = &_screen_vtable; XUNLOCK(); if (_keyboard_was_installed) { TRACE(PREFIX_I "x_create_screen: Installing Keyboard...\n"); install_keyboard(); } if (_mouse_was_installed) { TRACE(PREFIX_I "x_create_screen: Installing Mouse...\n"); install_mouse(); } gfx_capabilities |= GFX_HW_CURSOR; return allegro_gl_screen; failure: if (_keyboard_was_installed) { install_keyboard(); } if (_mouse_was_installed) { install_mouse(); } return NULL; } /* allegro_gl_x_windowed_init: * Creates screen bitmap for windowed driver. */ static BITMAP *allegro_gl_x_windowed_init(int w, int h, int vw, int vh, int depth) { return allegro_gl_x_create_screen(w, h, vw, vh, depth, FALSE); } /* allegro_gl_x_fullscreen_init: * Creates screen bitmap for fullscreen driver. */ static BITMAP *allegro_gl_x_fullscreen_init(int w, int h, int vw, int vh, int depth) { return allegro_gl_x_create_screen(w, h, vw, vh, depth, TRUE); } #ifdef ALLEGROGL_HAVE_XF86VIDMODE /* free_modelines: * Free mode lines. */ static void free_modelines(XF86VidModeModeInfo **modesinfo, int num_modes) { int i; for (i = 0; i < num_modes; i++) if (modesinfo[i]->privsize > 0) XFree(modesinfo[i]->private); XFree(modesinfo); } #endif /* allegro_gl_x_exit: * Shuts down the driver (shared between windowed and full-screen) */ static void allegro_gl_x_exit(BITMAP *bmp) { #ifdef ALLEGROGL_HAVE_XF86VIDMODE XSetWindowAttributes setattr; #endif XLOCK(); /* We politely wait for OpenGL to finish its current operations before shutting down the driver */ glXWaitGL(); __allegro_gl_unmanage_extensions(); if (_glxwin.ctx) { if (!allegro_gl_info.is_ati_r200_chip) { /* The DRI drivers for ATI cards with R200 chip * seem to be broken since they crash at this point. * As a workaround AGL does not release the GLX context * here. This should not hurt since the GLX specs don't * require the context to be released before the program * ends or before another context is made current to the * thread. */ if (!glXMakeCurrent(_xwin.display, None, NULL)) { ustrzcpy (allegro_error, ALLEGRO_ERROR_SIZE, get_config_text ("Could not release drawing context.\n")); } } glXDestroyContext(_xwin.display, _glxwin.ctx); _glxwin.ctx = NULL; } if (_xwin.mouse_grabbed) { XUngrabPointer(_xwin.display, CurrentTime); _xwin.mouse_grabbed = 0; } if (_xwin.keyboard_grabbed) { XUngrabKeyboard(_xwin.display, CurrentTime); _xwin.keyboard_grabbed = 0; } #ifdef ALLEGROGL_HAVE_XF86VIDMODE if (_glxwin.fullscreen) { if (_xwin.mode_switched) { XF86VidModeLockModeSwitch(_xwin.display, _xwin.screen, False); XF86VidModeSwitchToMode(_xwin.display, _xwin.screen, _xwin.modesinfo[0]); XF86VidModeSetViewPort(_xwin.display, _xwin.screen, 0, 0); _xwin.mode_switched = 0; } if (_xwin.override_redirected) { setattr.override_redirect = False; XChangeWindowAttributes(_xwin.display, _xwin.window, CWOverrideRedirect, &setattr); _xwin.override_redirected = 0; } /* Free modelines. */ free_modelines(_xwin.modesinfo, _xwin.num_modes); _xwin.num_modes = 0; _xwin.modesinfo = NULL; } #endif /* Note: Allegro will destroy screen (== allegro_gl_screen), * so don't destroy it here. */ //destroy_bitmap(allegro_gl_screen); ASSERT(allegro_gl_screen == screen); allegro_gl_screen = NULL; /* Unmap the window in order not to see the cursor when quitting. The window *must not* be destroyed and _xwin.visual must be left to its current value otherwise the program will crash when exiting */ if (_xwin.window != None) XUnmapWindow(_xwin.display, _xwin.window); if (_glxwin.use_glx_window) { glXDestroyWindow(_xwin.display, _glxwin.window); _glxwin.window = 0; _glxwin.use_glx_window = FALSE; } __allegro_gl_valid_context = FALSE; _xwin_window_redrawer = old_window_redrawer; XSetErrorHandler(old_x_error_handler); #if GET_ALLEGRO_VERSION() >= MAKE_VER(4, 2, 1) /* Hack: Allegro 4.2.1 uses a persistent window, we need to restore it. */ if (backup_allegro_window != None) { if (_xwin.colormap != None) { XUninstallColormap(_xwin.display, _xwin.colormap); XFreeColormap(_xwin.display, _xwin.colormap); } _xwin.colormap = backup_allegro_colormap; if (_xwin.window != None) XDestroyWindow(_xwin.display, _xwin.window); _xwin.window = backup_allegro_window; backup_allegro_window = None; XMapWindow(_xwin.display, _xwin.window); } #endif XUNLOCK(); } /* get_shift: * Returns the shift value for a given mask. */ static int get_shift (int mask) { int i = 0, j = 1; if (!mask) return -1; while (!(j & mask)) { i++; j <<= 1; } return i; } static int decode_fbconfig (GLXFBConfig fbc, struct allegro_gl_display_info *i) { int render_type, visual_type, buffer_size, sbuffers, samples; int drawable_type, renderable; XVisualInfo *v; TRACE(PREFIX_I "decode_fbconfig: Decoding:\n"); i->rmethod = 2; if (glXGetFBConfigAttrib (_xwin.display, fbc, GLX_RENDER_TYPE, &render_type) || glXGetFBConfigAttrib (_xwin.display, fbc, GLX_X_RENDERABLE, &renderable) || glXGetFBConfigAttrib (_xwin.display, fbc, GLX_DRAWABLE_TYPE, &drawable_type) || glXGetFBConfigAttrib (_xwin.display, fbc, GLX_X_VISUAL_TYPE, &visual_type) || glXGetFBConfigAttrib (_xwin.display, fbc, GLX_BUFFER_SIZE, &buffer_size) || glXGetFBConfigAttrib (_xwin.display, fbc, GLX_DEPTH_SIZE, &i->depth_size) || glXGetFBConfigAttrib (_xwin.display, fbc, GLX_STEREO, &i->stereo) || glXGetFBConfigAttrib (_xwin.display, fbc, GLX_RED_SIZE, &i->pixel_size.rgba.r) || glXGetFBConfigAttrib (_xwin.display, fbc, GLX_GREEN_SIZE, &i->pixel_size.rgba.g) || glXGetFBConfigAttrib (_xwin.display, fbc, GLX_BLUE_SIZE, &i->pixel_size.rgba.b) || glXGetFBConfigAttrib (_xwin.display, fbc, GLX_ALPHA_SIZE, &i->pixel_size.rgba.a) || glXGetFBConfigAttrib (_xwin.display, fbc, GLX_DOUBLEBUFFER, &i->doublebuffered) || glXGetFBConfigAttrib (_xwin.display, fbc, GLX_AUX_BUFFERS, &i->aux_buffers) || glXGetFBConfigAttrib (_xwin.display, fbc, GLX_STENCIL_SIZE, &i->stencil_size) || glXGetFBConfigAttrib (_xwin.display, fbc, GLX_ACCUM_RED_SIZE, &i->accum_size.rgba.r) || glXGetFBConfigAttrib (_xwin.display, fbc, GLX_ACCUM_GREEN_SIZE, &i->accum_size.rgba.g) || glXGetFBConfigAttrib (_xwin.display, fbc, GLX_ACCUM_BLUE_SIZE, &i->accum_size.rgba.b) || glXGetFBConfigAttrib (_xwin.display, fbc, GLX_ACCUM_ALPHA_SIZE, &i->accum_size.rgba.a)) { TRACE(PREFIX_I "decode_fbconfig: Incomplete glX mode ...\n"); return -1; } if (!(render_type & GLX_RGBA_BIT) && !(render_type & GLX_RGBA_FLOAT_BIT)) { TRACE(PREFIX_I "decode_fbconfig: Not RGBA mode\n"); return -1; } if (!(drawable_type & GLX_WINDOW_BIT)) { TRACE(PREFIX_I "decode_fbconfig: Cannot render to a window.\n"); return -1; } if (renderable == False) { TRACE(PREFIX_I "decode_fbconfig: GLX windows not supported.\n"); return -1; } if (visual_type != GLX_TRUE_COLOR && visual_type != GLX_DIRECT_COLOR) { TRACE(PREFIX_I "decode_fbconfig: visual type other than TrueColor and " "DirectColor.\n"); return -1; } /* Floating-point depth is not supported as glx extension (yet). */ i->float_depth = 0; i->float_color = (render_type & GLX_RGBA_FLOAT_BIT); v = glXGetVisualFromFBConfig(_xwin.display, fbc); if (!v) { TRACE(PREFIX_I "decode_fbconfig: Cannot get associated visual for the " "FBConfig.\n"); return -1; } i->r_shift = get_shift (v->red_mask); i->g_shift = get_shift (v->green_mask); i->b_shift = get_shift (v->blue_mask); i->a_shift = 0; /* If we are going to need to setup a palette we need bit shifts */ if ((visual_type == GLX_DIRECT_COLOR) && ((i->r_shift == -1) || (i->g_shift == -1) || (i->b_shift == -1)) && (i->pixel_size.rgba.r + i->pixel_size.rgba.g + i->pixel_size.rgba.b <= 12)) { /* XXX Report something here? */ XFree(v); return -1; } i->colour_depth = 0; if (i->pixel_size.rgba.r == 3 && i->pixel_size.rgba.g == 3 && i->pixel_size.rgba.b == 2) { i->colour_depth = 8; } if (i->pixel_size.rgba.r == 5 && i->pixel_size.rgba.b == 5) { if (i->pixel_size.rgba.g == 5) { i->colour_depth = 15; } if (i->pixel_size.rgba.g == 6) { i->colour_depth = 16; } } if (i->pixel_size.rgba.r == 8 && i->pixel_size.rgba.g == 8 && i->pixel_size.rgba.b == 8) { if (i->pixel_size.rgba.a == 0) { i->colour_depth = 24; } if (i->pixel_size.rgba.a == 8) { i->colour_depth = 32; /* small hack that tries to guess alpha shifting */ i->a_shift = 48 - i->r_shift - i->g_shift - i->b_shift; } } i->allegro_format = (i->colour_depth != 0) && (i->g_shift == i->pixel_size.rgba.b) && (i->r_shift * i->b_shift == 0) && (i->r_shift + i->b_shift == i->pixel_size.rgba.b + i->pixel_size.rgba.g); if (glXGetConfig(_xwin.display, v, GLX_SAMPLE_BUFFERS, &sbuffers)) { /* Multisample extension is not supported */ i->sample_buffers = 0; } else { i->sample_buffers = sbuffers; } if (glXGetConfig(_xwin.display, v, GLX_SAMPLES, &samples)) { /* Multisample extension is not supported */ i->samples = 0; } else { i->samples = samples; } XFree(v); TRACE(PREFIX_I "Color Depth: %i\n", buffer_size); TRACE(PREFIX_I "RGBA Type: %s point\n", i->float_color ? "floating" : "fixed"); TRACE(PREFIX_I "RGBA: %i.%i.%i.%i\n", i->pixel_size.rgba.r, i->pixel_size.rgba.g, i->pixel_size.rgba.b, i->pixel_size.rgba.a); TRACE(PREFIX_I "Accum: %i.%i.%i.%i\n", i->accum_size.rgba.r, i->accum_size.rgba.g, i->accum_size.rgba.b, i->accum_size.rgba.a); TRACE(PREFIX_I "DblBuf: %i Zbuf: %i Stereo: %i Aux: %i Stencil: %i\n", i->doublebuffered, i->depth_size, i->stereo, i->aux_buffers, i->stencil_size); TRACE(PREFIX_I "Shift: %i.%i.%i.%i\n", i->r_shift, i->g_shift, i->b_shift, i->a_shift); TRACE(PREFIX_I "Sample Buffers: %i Samples: %i\n", i->sample_buffers, i->samples); TRACE(PREFIX_I "Decoded bpp: %i\n", i->colour_depth); return 0; } int allegro_gl_x_windowed_choose_fbconfig (GLXFBConfig *ret_fbconfig) { int num_fbconfigs, i; GLXFBConfig *fbconfig; struct allegro_gl_display_info dinfo; fbconfig = glXGetFBConfigs (_xwin.display, _xwin.screen, &num_fbconfigs); if (!fbconfig || !num_fbconfigs) return FALSE; TRACE(PREFIX_I "x_windowed_choose_fbconfig: %i formats.\n", num_fbconfigs); __allegro_gl_reset_scorer(); for (i = 0; i < num_fbconfigs; i++) { TRACE(PREFIX_I "x_windowed_choose_fbconfig: Mode %i\n", i); if (decode_fbconfig (*(fbconfig + i), &dinfo) != -1) { __allegro_gl_score_config (i, &dinfo); } } i = __allegro_gl_best_config(); TRACE(PREFIX_I "x_windowed_choose_fbconfig: Best FBConfig is: %i\n", i); if (i < 0) { XFree(fbconfig); return FALSE; } *ret_fbconfig = *(fbconfig + i); XFree(fbconfig); return TRUE; } /* windowed_choose_visual: * Chooses a visual to use. */ static XVisualInfo *allegro_gl_x_windowed_choose_visual (void) { int num_visuals, i; XVisualInfo *vinfo; struct allegro_gl_display_info dinfo; static XVisualInfo ret_vinfo; vinfo = XGetVisualInfo (_xwin.display, 0, NULL, &num_visuals); if (!vinfo) return NULL; TRACE(PREFIX_I "x_windowed_choose_visual: %i formats.\n", num_visuals); __allegro_gl_reset_scorer(); for (i = 0; i < num_visuals; i++) { TRACE(PREFIX_I "x_windowed_choose_visual: Mode %i\n", i); if (decode_visual (vinfo + i, &dinfo) != -1) { __allegro_gl_score_config (i, &dinfo); } } i = __allegro_gl_best_config(); TRACE(PREFIX_I "x_windowed_choose_visual: Best config is: %i\n", i); if (i < 0) return NULL; memcpy (&ret_vinfo, vinfo+i, sizeof ret_vinfo); XFree (vinfo); return &ret_vinfo; } #ifdef ALLEGROGL_HAVE_XF86VIDMODE /* get_xf86_modes: * Test if the XF86VidMode extension is available and get the gfx modes * that can be queried. */ static int get_xf86_modes(XF86VidModeModeInfo ***modesinfo, int *num_modes) { int vid_event_base, vid_error_base; int vid_major_version, vid_minor_version; /* Test for presence of VidMode extension. */ if (!XF86VidModeQueryExtension(_xwin.display, &vid_event_base, &vid_error_base) || !XF86VidModeQueryVersion(_xwin.display, &vid_major_version, &vid_minor_version)) { ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE, get_config_text("VidMode extension is not supported")); return -1; } if (!XF86VidModeGetAllModeLines(_xwin.display, _xwin.screen, num_modes, modesinfo)) { ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE, get_config_text("Can not Get ModeLines")); return -1; } return 0; } #endif static int allegro_gl_x_error_handler(Display *display, XErrorEvent *err_event) { char buffer[256]; XGetErrorText(display, err_event->error_code, buffer, 256); TRACE(PREFIX_E "%s\n", buffer); return 0; } /* create_window: * Based on Michael's `_xwin[_private]_create_window' and the xdemos * from the Mesa distribution (I don't remember which one). */ static int allegro_gl_x_create_window (int fullscreen) { Window root; XVisualInfo *visinfo; XSetWindowAttributes setattr; unsigned long valuemask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask; XSizeHints *hints; GLXFBConfig fbconfig; int use_fbconfig; if (_xwin.display == 0) { return -2; } old_x_error_handler = XSetErrorHandler(allegro_gl_x_error_handler); /* Fill in missing color depth info */ __allegro_gl_fill_in_info(); use_fbconfig = (_glxwin.major > 1 || (_glxwin.major == 1 && _glxwin.minor >= 3)); if (use_fbconfig) { TRACE(PREFIX_I "x_create_window: using FBConfig routines\n"); if (!allegro_gl_x_windowed_choose_fbconfig(&fbconfig)) { TRACE(PREFIX_I "x_create_window: Failed using FBConfig, switching " "back to VisualInfo routines\n"); use_fbconfig = FALSE; goto old_choose_visual; } /* Query back FBConfig components */ if (decode_fbconfig(fbconfig, &allegro_gl_display_info)) { TRACE(PREFIX_E "x_create_window: Cannot decode FBConfig, switching " "back to VisualInfo routines\n"); use_fbconfig = FALSE; goto old_choose_visual; } visinfo = glXGetVisualFromFBConfig(_xwin.display, fbconfig); if (!visinfo) { TRACE(PREFIX_I "x_create_window: Failed to convert FBConfig to " "visual, switching back to VisualInfo routines\n"); use_fbconfig = FALSE; goto old_choose_visual; } } else { old_choose_visual: TRACE(PREFIX_I "x_create_window: using VisualInfo routines\n"); /* Find best visual */ visinfo = allegro_gl_x_windowed_choose_visual(); if (!visinfo) { TRACE(PREFIX_E "x_create_window: Can not get visual.\n"); XSetErrorHandler(old_x_error_handler); return -2; } /* Query back visual components */ if (decode_visual (visinfo, &allegro_gl_display_info)) { TRACE(PREFIX_E "x_create_window: Can not decode visual.\n"); XSetErrorHandler(old_x_error_handler); return -2; } } /* Log some information about it */ switch (visinfo->class) { case TrueColor: AGL_LOG (1, "x.c: visual class: TrueColor\n"); break; case DirectColor: AGL_LOG (1, "x.c: visual class: DirectColor\n"); break; default: AGL_LOG (1, "x.c: visual class: invalid(!)\n"); } /* Begin window creation. */ #if GET_ALLEGRO_VERSION() >= MAKE_VER(4, 2, 1) /* Hack: For Allegro 4.2.1, we need to keep the existing window. */ if (backup_allegro_window == None) { backup_allegro_window = _xwin.window; backup_allegro_colormap = _xwin.colormap; _xwin.colormap = None; XUnmapWindow(_xwin.display, _xwin.window); } else #endif XDestroyWindow (_xwin.display, _xwin.window); _xwin.window = None; root = RootWindow (_xwin.display, _xwin.screen); /* Recreate window. */ setattr.background_pixel = XBlackPixel (_xwin.display, _xwin.screen); setattr.border_pixel = XBlackPixel (_xwin.display, _xwin.screen); setattr.colormap = XCreateColormap (_xwin.display, root, visinfo->visual, AllocNone); setattr.event_mask = ( KeyPressMask | KeyReleaseMask | EnterWindowMask | LeaveWindowMask | FocusChangeMask | ExposureMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask /*| MappingNotifyMask (SubstructureRedirectMask?)*/ ); #ifdef ALLEGROGL_HAVE_XF86VIDMODE if (fullscreen) { int i; int bestmode = 0; _xwin.num_modes = 0; _xwin.modesinfo = NULL; _glxwin.fullscreen = TRUE; if (get_xf86_modes(&_xwin.modesinfo, &_xwin.num_modes)) { ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE, get_config_text("x_create_window: Can't get" "XF86VidMode info.\n")); XSetErrorHandler(old_x_error_handler); return -2; } /* look for mode with requested resolution */ for (i = 0; i < _xwin.num_modes; i++) { if ((_xwin.modesinfo[i]->hdisplay == allegro_gl_display_info.w) && (_xwin.modesinfo[i]->vdisplay == allegro_gl_display_info.h)) bestmode = i; } setattr.override_redirect = True; if (!XF86VidModeSwitchToMode(_xwin.display, _xwin.screen, _xwin.modesinfo[bestmode])) { ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE, get_config_text("Can not set XF86VidMode mode")); XSetErrorHandler(old_x_error_handler); return -1; } XF86VidModeSetViewPort(_xwin.display, _xwin.screen, 0, 0); /* Lock Mode switching */ XF86VidModeLockModeSwitch(_xwin.display, _xwin.screen, True); _xwin.mode_switched = 1; allegro_gl_display_info.x = 0; allegro_gl_display_info.y = 0; allegro_gl_display_info.w = _xwin.modesinfo[bestmode]->hdisplay; allegro_gl_display_info.h = _xwin.modesinfo[bestmode]->vdisplay; valuemask |= CWOverrideRedirect; _xwin.override_redirected = 1; } _xwin.window = XCreateWindow ( _xwin.display, root, allegro_gl_display_info.x, allegro_gl_display_info.y, allegro_gl_display_info.w, allegro_gl_display_info.h, 0, visinfo->depth, InputOutput, visinfo->visual, valuemask, &setattr ); #else //ALLEGROGL_HAVE_XF86VIDMODE if (fullscreen) { /* Without Xf86VidMode extension we support only fullscreen modes which * match current resolution. */ int fs_width = DisplayWidth(_xwin.display, _xwin.screen); int fs_height = DisplayHeight(_xwin.display, _xwin.screen); if (fs_width != allegro_gl_display_info.w || fs_height != allegro_gl_display_info.h) { TRACE(PREFIX_E "Only desktop resolution fullscreen available."); ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE, get_config_text("Compiled without Xf86VidMode extension support.\n" "Only desktop resolution fullscreen available.")); XSetErrorHandler(old_x_error_handler); return -1; } _glxwin.fullscreen = TRUE; /* Create the fullscreen window. */ _xwin.window = XCreateWindow(_xwin.display, root, allegro_gl_display_info.x, allegro_gl_display_info.y, fs_width, fs_height, 0, visinfo->depth, InputOutput, visinfo->visual, valuemask, &setattr); /* Map the fullscreen window. */ XMapRaised(_xwin.display, _xwin.window); /* Make sure we got to the top of the window stack. */ XRaiseWindow(_xwin.display, _xwin.fs_window); } else { _xwin.window = XCreateWindow ( _xwin.display, root, allegro_gl_display_info.x, allegro_gl_display_info.y, allegro_gl_display_info.w, allegro_gl_display_info.h, 0, visinfo->depth, InputOutput, visinfo->visual, valuemask, &setattr ); } #endif //ALLEGROGL_HAVE_XF86VIDMODE /* Set size and position hints for Window Manager : * prevents the window to be resized */ hints = XAllocSizeHints(); if (hints) { /* This code chunk comes from Allegro's src/x/xwin.c */ hints->flags = PMinSize | PMaxSize | PBaseSize; hints->min_width = hints->max_width = hints->base_width = allegro_gl_display_info.w; hints->min_height = hints->max_height = hints->base_height = allegro_gl_display_info.h; XSetWMNormalHints(_xwin.display, _xwin.window, hints); XFree(hints); } /* Set WM_DELETE_WINDOW atom in WM_PROTOCOLS property * (to get window_delete requests). */ { Atom wm_delete_window = XInternAtom(_xwin.display, "WM_DELETE_WINDOW", False); XSetWMProtocols(_xwin.display, _xwin.window, &wm_delete_window, 1); } /* Finish off the GLX setup */ if (use_fbconfig) _glxwin.ctx = glXCreateNewContext (_xwin.display, fbconfig, GLX_RGBA_TYPE, NULL, True); else _glxwin.ctx = glXCreateContext (_xwin.display, visinfo, NULL, True); if (use_fbconfig) { _glxwin.window = glXCreateWindow(_xwin.display, fbconfig, _xwin.window, 0); if (!_glxwin.window) { ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE, get_config_text("Cannot create GLX window.")); XSetErrorHandler(old_x_error_handler); return -1; } _glxwin.use_glx_window = TRUE; } if (!_glxwin.ctx) { ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE, get_config_text("Can not create GLX context.")); XSetErrorHandler(old_x_error_handler); return -1; } else { Bool ret; if (use_fbconfig) ret = glXMakeContextCurrent(_xwin.display, _glxwin.window, _glxwin.window, _glxwin.ctx); else ret = glXMakeCurrent (_xwin.display, _xwin.window, _glxwin.ctx); if (!ret) { ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE, get_config_text("Cannot make GLX context current.")); XSetErrorHandler(old_x_error_handler); return -1; } } /* Finish off the Allegro setup */ /* Get associated visual and window depth (bits per pixel), and * store window size */ { XWindowAttributes getattr; XGetWindowAttributes(_xwin.display, _xwin.window, &getattr); _xwin.visual = getattr.visual; _xwin.window_depth = getattr.depth; _xwin.window_width = allegro_gl_display_info.w; _xwin.window_height = allegro_gl_display_info.h; _xwin.screen_depth = getattr.depth; _xwin.screen_width = allegro_gl_display_info.w; _xwin.screen_height = allegro_gl_display_info.h; } /* Destroy the current colormap (if any) */ if (_xwin.colormap != None) { XUninstallColormap(_xwin.display, _xwin.colormap); XFreeColormap(_xwin.display, _xwin.colormap); } /* Create and install colormap. */ if (_xwin.visual->class == DirectColor) { _xwin.colormap = XCreateColormap(_xwin.display, _xwin.window, _xwin.visual, AllocAll); } else { /* must be TrueColor */ _xwin.colormap = XCreateColormap(_xwin.display, _xwin.window, _xwin.visual, AllocNone); } XSetWindowColormap(_xwin.display, _xwin.window, _xwin.colormap); XInstallColormap(_xwin.display, _xwin.colormap); /* Setup a palette if needed */ if (_xwin.visual->class == DirectColor) { XColor color; int rsize, gsize, bsize; int rmax, gmax, bmax; int rshift, gshift, bshift; int r, g, b; AGL_LOG (1, "x.c: Using DirectColor visual, setting palette...\n"); rsize = 1 << allegro_gl_display_info.pixel_size.rgba.r; gsize = 1 << allegro_gl_display_info.pixel_size.rgba.g; bsize = 1 << allegro_gl_display_info.pixel_size.rgba.b; rshift = allegro_gl_display_info.r_shift; bshift = allegro_gl_display_info.b_shift; gshift = allegro_gl_display_info.g_shift; rmax = rsize - 1; gmax = gsize - 1; bmax = bsize - 1; color.flags = DoRed | DoGreen | DoBlue; for (r = 0; r < rsize; r++) { for (g = 0; g < gsize; g++) { for (b = 0; b < bsize; b++) { color.pixel = (r << rshift) | (g << gshift) | (b << bshift); color.red = ((rmax <= 0) ? 0 : ((r * 65535L) / rmax)); color.green = ((gmax <= 0) ? 0 : ((g * 65535L) / gmax)); color.blue = ((bmax <= 0) ? 0 : ((b * 65535L) / bmax)); XStoreColor(_xwin.display, _xwin.colormap, &color); } } } } /* Configure the window a bit */ { XClassHint hint; XWMHints wm_hints; /* Set title. */ XStoreName(_xwin.display, _xwin.window, _xwin.window_title); /* Set hints. */ hint.res_name = _xwin.application_name; hint.res_class = _xwin.application_class; XSetClassHint(_xwin.display, _xwin.window, &hint); wm_hints.flags = InputHint | StateHint; wm_hints.input = True; wm_hints.initial_state = NormalState; #ifdef ALLEGRO_XWINDOWS_WITH_XPM if (allegro_icon) { wm_hints.flags |= IconPixmapHint | IconMaskHint | WindowGroupHint; XpmCreatePixmapFromData(_xwin.display, _xwin.window, allegro_icon,&wm_hints.icon_pixmap, &wm_hints.icon_mask, NULL); } #endif XSetWMHints(_xwin.display, _xwin.window, &wm_hints); } /* Map window. */ XMapWindow(_xwin.display, _xwin.window); if (fullscreen) { AL_CONST char *fc = NULL; char tmp1[64], tmp2[128]; int c = 0; int h = allegro_gl_display_info.h; int w = allegro_gl_display_info.w; /* This chunk is disabled by default because of problems on KDE desktops. */ fc = get_config_string(uconvert_ascii("graphics", tmp1), uconvert_ascii("force_centering", tmp2), NULL); if ((fc) && ((c = ugetc(fc)) != 0) && ((c == 'y') || (c == 'Y') || (c == '1'))) { /* Hack: make the window fully visible and center cursor. */ XWarpPointer(_xwin.display, None, _xwin.window, 0, 0, 0, 0, 0, 0); XWarpPointer(_xwin.display, None, _xwin.window, 0, 0, 0, 0, w - 1, 0); XWarpPointer(_xwin.display, None, _xwin.window, 0, 0, 0, 0, 0, h - 1); XWarpPointer(_xwin.display, None, _xwin.window, 0, 0, 0, 0, w - 1, h - 1); } XWarpPointer(_xwin.display, None, _xwin.window, 0, 0, 0, 0, w / 2, h / 2); XSync(_xwin.display, False); /* Grab keyboard and mouse. */ if (XGrabKeyboard(_xwin.display, _xwin.window, False, GrabModeAsync, GrabModeAsync, CurrentTime) != GrabSuccess) { ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE, get_config_text("Can not grab keyboard")); XSetErrorHandler(old_x_error_handler); return -1; } _xwin.keyboard_grabbed = 1; if (XGrabPointer(_xwin.display, _xwin.window, False, PointerMotionMask | ButtonPressMask | ButtonReleaseMask, GrabModeAsync, GrabModeAsync, _xwin.window, None, CurrentTime) != GrabSuccess) { ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE, get_config_text("Can not grab mouse")); XSetErrorHandler(old_x_error_handler); return -1; } _xwin.mouse_grabbed = 1; } /* Destroy current cursor (if any) */ if (_xwin.cursor != None) { XUndefineCursor(_xwin.display, _xwin.window); XFreeCursor(_xwin.display, _xwin.cursor); } { /* Create invisible X cursor. */ Pixmap pixmap = XCreatePixmap(_xwin.display, _xwin.window, 1, 1, 1); if (pixmap != None) { GC temp_gc; XColor color; XGCValues gcvalues; int gcmask = GCFunction | GCForeground | GCBackground; gcvalues.function = GXcopy; gcvalues.foreground = 0; gcvalues.background = 0; temp_gc = XCreateGC(_xwin.display, pixmap, gcmask, &gcvalues); XDrawPoint(_xwin.display, pixmap, temp_gc, 0, 0); XFreeGC(_xwin.display, temp_gc); color.pixel = 0; color.red = color.green = color.blue = 0; color.flags = DoRed | DoGreen | DoBlue; _xwin.cursor = XCreatePixmapCursor(_xwin.display, pixmap, pixmap, &color, &color, 0, 0); XDefineCursor(_xwin.display, _xwin.window, _xwin.cursor); XFreePixmap(_xwin.display, pixmap); } else { _xwin.cursor = XCreateFontCursor(_xwin.display, _xwin.cursor_shape); XDefineCursor(_xwin.display, _xwin.window, _xwin.cursor); } } /* Wait for the first exposure event. See comment in Allegro's * xwin.c about why no blocking X11 function is used. */ while (1) { XEvent e; if (XCheckTypedEvent(_xwin.display, Expose, &e)) { if (e.xexpose.count == 0) break; } rest(1); } return 0; } static BITMAP *allegro_gl_x_windowed_create_screen (GFX_DRIVER *drv, int w, int h, int depth) { BITMAP *bmp; int is_linear = drv->linear; drv->linear = 1; bmp = _make_bitmap (w, h, 0, drv, depth, 0); bmp->id = BMP_ID_VIDEO | BMP_ID_MASK; drv->linear = is_linear; if (bmp == 0) { ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE, get_config_text("Not enough memory")); return NULL; } drv->w = w; drv->h = h; return bmp; } /* decode_visual: * Used to read back the information in the visual. 0 = ok. */ static int decode_visual (XVisualInfo *v, struct allegro_gl_display_info *i) { int rgba, buffer_size, use_gl, sbuffers, samples; TRACE(PREFIX_I "decode_visual: Decoding:\n"); i->rmethod = 2; /* We can only support TrueColor and DirectColor visuals -- * we only support RGBA mode */ if (v->class != TrueColor && v->class != DirectColor) return -1; if (glXGetConfig (_xwin.display, v, GLX_RGBA, &rgba) || glXGetConfig (_xwin.display, v, GLX_USE_GL, &use_gl) || glXGetConfig (_xwin.display, v, GLX_BUFFER_SIZE, &buffer_size) || glXGetConfig (_xwin.display, v, GLX_RED_SIZE, &i->pixel_size.rgba.r) || glXGetConfig (_xwin.display, v, GLX_GREEN_SIZE, &i->pixel_size.rgba.g) || glXGetConfig (_xwin.display, v, GLX_BLUE_SIZE, &i->pixel_size.rgba.b) || glXGetConfig (_xwin.display, v, GLX_ALPHA_SIZE, &i->pixel_size.rgba.a) || glXGetConfig (_xwin.display, v, GLX_DOUBLEBUFFER, &i->doublebuffered) || glXGetConfig (_xwin.display, v, GLX_STEREO, &i->stereo) || glXGetConfig (_xwin.display, v, GLX_AUX_BUFFERS, &i->aux_buffers) || glXGetConfig (_xwin.display, v, GLX_DEPTH_SIZE, &i->depth_size) || glXGetConfig (_xwin.display, v, GLX_STENCIL_SIZE, &i->stencil_size) || glXGetConfig (_xwin.display, v, GLX_ACCUM_RED_SIZE, &i->accum_size.rgba.r) || glXGetConfig (_xwin.display, v, GLX_ACCUM_GREEN_SIZE, &i->accum_size.rgba.g) || glXGetConfig (_xwin.display, v, GLX_ACCUM_BLUE_SIZE, &i->accum_size.rgba.b) || glXGetConfig (_xwin.display, v, GLX_ACCUM_ALPHA_SIZE, &i->accum_size.rgba.a)) { TRACE(PREFIX_I "x_create_window: Incomplete glX mode ...\n"); return -1; } if (!rgba) { TRACE(PREFIX_I "x_create_window: Not RGBA mode\n"); return -1; } if (!use_gl) { ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE, get_config_text("OpenGL Unsupported")); return -1; } i->r_shift = get_shift (v->red_mask); i->g_shift = get_shift (v->green_mask); i->b_shift = get_shift (v->blue_mask); i->a_shift = 0; /* If we are going to need to setup a palette we need bit shifts */ if ((v->class == DirectColor) && ((i->r_shift == -1) || (i->g_shift == -1) || (i->b_shift == -1)) && (i->pixel_size.rgba.r + i->pixel_size.rgba.g + i->pixel_size.rgba.b <= 12)) { /* XXX Report something here? */ return -1; } i->float_color = 0; i->float_depth = 0; i->colour_depth = 0; if (i->pixel_size.rgba.r == 3 && i->pixel_size.rgba.g == 3 && i->pixel_size.rgba.b == 2) { i->colour_depth = 8; } if (i->pixel_size.rgba.r == 5 && i->pixel_size.rgba.b == 5) { if (i->pixel_size.rgba.g == 5) { i->colour_depth = 15; } if (i->pixel_size.rgba.g == 6) { i->colour_depth = 16; } } if (i->pixel_size.rgba.r == 8 && i->pixel_size.rgba.g == 8 && i->pixel_size.rgba.b == 8) { if (i->pixel_size.rgba.a == 0) { i->colour_depth = 24; } if (i->pixel_size.rgba.a == 8) { i->colour_depth = 32; /* small hack that tries to guess alpha shifting */ i->a_shift = 48 - i->r_shift - i->g_shift - i->b_shift; } } i->allegro_format = (i->colour_depth != 0) && (i->g_shift == i->pixel_size.rgba.b) && (i->r_shift * i->b_shift == 0) && (i->r_shift + i->b_shift == i->pixel_size.rgba.b + i->pixel_size.rgba.g); if (glXGetConfig(_xwin.display, v, GLX_SAMPLE_BUFFERS, &sbuffers) == GLX_BAD_ATTRIBUTE) { /* Multisample extension is not supported */ i->sample_buffers = 0; } else { i->sample_buffers = sbuffers; } if (glXGetConfig(_xwin.display, v, GLX_SAMPLES, &samples) == GLX_BAD_ATTRIBUTE) { /* Multisample extension is not supported */ i->samples = 0; } else { i->samples = samples; } TRACE(PREFIX_I "Color Depth: %i\n", buffer_size); TRACE(PREFIX_I "RGBA: %i.%i.%i.%i\n", i->pixel_size.rgba.r, i->pixel_size.rgba.g, i->pixel_size.rgba.b, i->pixel_size.rgba.a); TRACE(PREFIX_I "Accum: %i.%i.%i.%i\n", i->accum_size.rgba.r, i->accum_size.rgba.g, i->accum_size.rgba.b, i->accum_size.rgba.a); TRACE(PREFIX_I "DblBuf: %i Zbuf: %i Stereo: %i Aux: %i Stencil: %i\n", i->doublebuffered, i->depth_size, i->stereo, i->aux_buffers, i->stencil_size); TRACE(PREFIX_I "Shift: %i.%i.%i.%i\n", i->r_shift, i->g_shift, i->b_shift, i->a_shift); TRACE(PREFIX_I "Sample Buffers: %i Samples: %i\n", i->sample_buffers, i->samples); TRACE(PREFIX_I "Decoded bpp: %i\n", i->colour_depth); return 0; } #ifdef ALLEGROGL_HAVE_XF86VIDMODE /* allegro_gl_x_fetch_mode_list: * Generates a list of valid video modes (made after * _xvidmode_private_fetch_mode_list of Allegro) */ static GFX_MODE_LIST* allegro_gl_x_fetch_mode_list(void) { int num_modes = 0; XF86VidModeModeInfo **modesinfo = NULL; GFX_MODE_LIST *mode_list; int i; XLOCK(); if (get_xf86_modes(&modesinfo, &num_modes)) { XUNLOCK(); return NULL; } /* Allocate space for mode list. */ mode_list = malloc(sizeof(GFX_MODE_LIST)); if (!mode_list) { free_modelines(modesinfo, num_modes); XUNLOCK(); return NULL; } mode_list->mode = malloc(sizeof(GFX_MODE) * (num_modes + 1)); if (!mode_list->mode) { free(mode_list); free_modelines(modesinfo, num_modes); XUNLOCK(); return NULL; } /* Fill in mode list. */ for (i = 0; i < num_modes; i++) { mode_list->mode[i].width = modesinfo[i]->hdisplay; mode_list->mode[i].height = modesinfo[i]->vdisplay; /* Since XF86VidMode can not change the color depth of * the screen, there is no need to define modes for other * color depth than the desktop's. */ mode_list->mode[i].bpp = desktop_color_depth(); } mode_list->mode[num_modes].width = 0; mode_list->mode[num_modes].height = 0; mode_list->mode[num_modes].bpp = 0; mode_list->num_modes = num_modes; free_modelines(modesinfo, num_modes); XUNLOCK(); return mode_list; } #endif /* allegro_gl_x_vsync: * Wait for a vertical retrace. GLX_SGI_video_sync is needed. */ static void allegro_gl_x_vsync(void) { XLOCK(); if (allegro_gl_extensions_GLX.SGI_video_sync) { unsigned int count; glXGetVideoSyncSGI(&count); glXWaitVideoSyncSGI(2, (count+1) & 1, &count); } XUNLOCK(); } /******************************/ /* AllegroGL driver functions */ /******************************/ /* flip: * Does a page flip / double buffer copy / whatever it really is. */ static void flip (void) { XLOCK(); if (_glxwin.use_glx_window) glXSwapBuffers (_xwin.display, _glxwin.window); else glXSwapBuffers (_xwin.display, _xwin.window); XUNLOCK(); } /* gl_on, gl_off: * Switches to/from GL mode. */ static void gl_on (void) { #ifdef OLD_ALLEGRO DISABLE(); #endif } static void gl_off (void) { #ifdef OLD_ALLEGRO ENABLE(); _xwin_handle_input(); #endif } /*****************/ /* Driver struct */ /*****************/ static struct allegro_gl_driver allegro_gl_x = { flip, gl_on, gl_off, NULL }; allegro4.4-4.4.2/addons/allegrogl/todo.txt000066400000000000000000000026471173507505700203450ustar00rootroot00000000000000AllegroGL Todo/bug list for version 1.00 ======================================== Core: ----- ? Resizable window support. This will need lots of changes to Allegro though, unless AGL manages the window and DirectX (or whatever is the equivalent in X). * Font and text support: ------------------------ * Check the font code with proportional and non-proportional fonts * Sort characters by texture before rendering. * Combine all ranges into one texture if possible. Allegro driver: --------------- * video subbitmap and clipping support * Combine video bitmaps in textures into less textures. * Ability to draw 256 color sprites on video bitmaps * fix flip&rotate drawing on video bitmaps when the bitmap is segmented * drawing rle sprites -> video bitmaps * rewrite drawing of primitives to video bitmaps using FBO ? System bitmaps Windows: -------- * X: -- ? Use GLX extension for full-screen support, when it comes out * When available use FBConfig facilities in scorer (through extension or GLX 1.3) Generic driver : (was DOS port) --------------- * Update the code to take advantage of Allegro graphics primitives (lines, triangles, ...).Currently the driver draws to BITMAPs pixel per pixel. * 8 bits support does not work at all. Especially indexed colors modes. * Complete GLUT for AMesa if somebody is interested in. * Use regular video bitmaps Misc: ----- ? Maybe convert a few of NeHe's tutorials to Allegro/AGL :) allegro4.4-4.4.2/addons/allegrogl/zlib.txt000066400000000000000000000015421173507505700203310ustar00rootroot00000000000000Copyright (C) 1999-2006 AllegroGL contributors This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. allegro4.4-4.4.2/addons/jpgalleg/000077500000000000000000000000001173507505700164435ustar00rootroot00000000000000allegro4.4-4.4.2/addons/jpgalleg/CMakeLists.txt000066400000000000000000000043371173507505700212120ustar00rootroot00000000000000#-----------------------------------------------------------------------------# # # JPGalleg # # JPGalleg contains some optional assembly code for x86. # In the end I decided not to enable it as we can't be sure we can maintain # it in the future, so this file never contains anything useful. configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/include/mmx.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/include/mmx.h ) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include) include_directories(${CMAKE_CURRENT_BINARY_DIR}/include) set(JPGALLEG_SOURCES src/decode.c src/encode.c src/error.c src/init.c src/io.c src/jpgalleg.c ) set(JPGALLEG_HEADERS include/jpgalleg.h ) set_source_files_properties(${JPGALLEG_HEADERS} PROPERTIES MACOSX_PACKAGE_LOCATION Headers ) add_our_library(jpgalleg ${ADDON_LINKAGE} ${JPGALLEG_SOURCES} ${JPGALLEG_HEADERS} ) set_target_properties(jpgalleg PROPERTIES LINK_FLAGS "${ALLEGRO_LINK_FLAGS}" VERSION ${ALLEGRO_VERSION} SOVERSION ${ALLEGRO_SOVERSION} ) set_our_framework_properties(jpgalleg jpgalleg) target_link_libraries(jpgalleg allegro) set_target_properties(jpgalleg PROPERTIES static_link_with "" ) install_our_library(jpgalleg) if(NOT WANT_FRAMEWORKS) install_our_headers(${JPGALLEG_HEADERS}) endif(NOT WANT_FRAMEWORKS) set(SUPPORT_JPGALLEG 1 PARENT_SCOPE) #-----------------------------------------------------------------------------# # # Examples # file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/examples) function(add_our_example nm) add_executable(${nm}_jpg WIN32 examples/${nm}.c) set_target_properties(${nm}_jpg PROPERTIES OUTPUT_NAME examples/${nm} ) target_link_libraries(${nm}_jpg jpgalleg) if(PSP) add_psp_executable(${nm}_jpg) endif(PSP) endfunction() if(WANT_EXAMPLES) add_our_example(ex1) add_our_example(ex2) add_our_example(ex3) add_our_example(ex4) add_our_example(ex5) copy_files(copy_jpgalleg_example_data examples/cat.tga examples/datafile.dat examples/jpgalleg.jpg ) endif(WANT_EXAMPLES) #-----------------------------------------------------------------------------# # vim: set sts=4 sw=4 et: allegro4.4-4.4.2/addons/jpgalleg/contrib/000077500000000000000000000000001173507505700201035ustar00rootroot00000000000000allegro4.4-4.4.2/addons/jpgalleg/contrib/pyjpgalleg/000077500000000000000000000000001173507505700222415ustar00rootroot00000000000000allegro4.4-4.4.2/addons/jpgalleg/contrib/pyjpgalleg/license.txt000066400000000000000000000016161173507505700244300ustar00rootroot00000000000000The zlib/libpng License pyjpgalleg is copyright (c) 2006 by Grzegorz Adam Hankiewicz This software is provided 'as-is', without any express or implied warranty. In no event will the author be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. allegro4.4-4.4.2/addons/jpgalleg/contrib/pyjpgalleg/pyjpgallegmodule.c000066400000000000000000000036371173507505700257620ustar00rootroot00000000000000/* -*- mode:C++; tab-width: 4 -*- */ /* The zlib/libpng License pyjpgalleg is copyright (c) 2006 by Grzegorz Adam Hankiewicz This software is provided 'as-is', without any express or implied warranty. In no event will the author be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. */ #include #include /* Wrapper around jpegalleg_init() */ static PyObject *pyjpgalleg_init(PyObject *self, PyObject *args) { int ret = jpgalleg_init(); return Py_BuildValue("i", ret); } /* Methods exported by the C module. */ static PyMethodDef PyjpgallegMethods[] = { {"init", pyjpgalleg_init, METH_VARARGS, "Initialise the jpgalleg library. Call after Allegro initialisation."}, {NULL, NULL, 0, NULL} /* Sentinel. */ }; /* Define the initialisation function. */ PyMODINIT_FUNC initpyjpgalleg(void) { (void) Py_InitModule("pyjpgalleg", PyjpgallegMethods); } /* Main entry point of the module for static link initialisation. */ int main(int argc, char *argv[]) { /* Pass argv[0] to the Python interpreter */ Py_SetProgramName(argv[0]); /* Initialize the Python interpreter. Required. */ Py_Initialize(); /* Add a static module */ initpyjpgalleg(); return 0; } allegro4.4-4.4.2/addons/jpgalleg/contrib/pyjpgalleg/readme.txt000066400000000000000000000036441173507505700242460ustar00rootroot00000000000000Pyjpgalleg, 1.0 by Grzegorz Adam Hankiewicz, 2006. -------------------------------------------------- I wrote this simple wrapper following python's extension tutorial because I wanted to see how much I could improve the speed of loading jpg files from my python image viewer. The viewer is written in pure python with alpy (http://pyallegro.sf.net/), and depending on the system configuration it has three different loading modes. 1) It can use the external unix program convert to transform the input into a bmp which Allegro can read. This is really slow. 2) If PIL (Python Imaging Library) is available, the input file is loaded with it (really good C implementation), and then converted into an Allegro bitmap with alpy's Bitmap.from_string (quite fast memory copy conversion). 3) If pyjpgalleg is available, the viewer uses Allegro' load_bitmap, which makes the image available immediatelly to Allegro, without any extra conversion (fastest method). I tested the speed of these three methods with a picture I took with my digital camera, a 3.4 MB JPG, sized 2560x1920. Here are the averaged speeds for each of the methods after loading and showing the image ten times on my PIII 800Mhz: 1) 6.3023s 2) 3.8314s 3) 3.3937s So pyjpgalleg is about 12% faster than PIL + memory conversion. Usage instructions: ------------------- Pretty easy, you run the typical "python setup.py install" and there you go, now you can do: import alpy alpy.init() import pyjpgalleg pyjpgalleg.init() and there you go, load jpg files with alpy.load_bitmap(). I've tested this only under Linux, but I guess this could work as is under Windows too. Enjoy! Download urls: -------------- jpgalleg, by Angelo Mottola, from http://www.ecplusplus.com/ or redirected from http://www.allegro.cc/depot/project.php?_id=522. You should be getting this pyjpgalleg from the jpgalleg package in the contrib directory. allegro4.4-4.4.2/addons/jpgalleg/contrib/pyjpgalleg/setup.py000066400000000000000000000027161173507505700237610ustar00rootroot00000000000000#!/usr/bin/env python # The zlib/libpng License # # pyjpgalleg is copyright (c) 2006 by Grzegorz Adam Hankiewicz # # This software is provided 'as-is', without any express or implied # warranty. In no event will the author be held liable for any damages # arising from the use of this software. # # Permission is granted to anyone to use this software for any purpose, # including commercial applications, and to alter it and redistribute it # freely, subject to the following restrictions: # # # 1. The origin of this software must not be misrepresented; you must not # claim that you wrote the original software. If you use this software in # a product, an acknowledgment in the product documentation would be # appreciated but is not required. # # 2. Altered source versions must be plainly marked as such, and must not # be misrepresented as being the original software. # # 3. This notice may not be removed or altered from any source distribution. from distutils.core import setup, Extension module = Extension( "pyjpgalleg", include_dirs = ["/usr/local/include"], libraries = ["jpgal"], library_dirs = ["/usr/local/lib"], sources = ["pyjpgallegmodule.c"], ) if __name__ == "__main__": setup(name = "pyjpgalleg", version = "1.0", description = "Simple jpgalleg wrapper", author = "Grzegorz Adam Hankiewicz", author_email = "gradha@titanium.sabren.com", ext_modules = [module] ) allegro4.4-4.4.2/addons/jpgalleg/examples/000077500000000000000000000000001173507505700202615ustar00rootroot00000000000000allegro4.4-4.4.2/addons/jpgalleg/examples/cat.tga000066400000000000000000001100541173507505700215260ustar00rootroot00000000000000€`_riŽ|’±§¸ÃÈ•©·¤²Œ¤±‘¨´–ª·•«·”ª¶—¬¸–¬¸”«·“©¶‘¨¶¥´‰¢³†¡²ž°yš¯t˜°—®½¹ÄʹÄʲ¾Å®¼Á­»Á®ºÀ¯¼À°¼Á®»Á­º¿®ºÀ°¼Á°¼Â²¾Ä³¿Ã¶ÀźÁÇÀÆÉÂÇÉÆÉËËÍÎÐÏÐÑÐÑÔÒÒÓÑÑÓÑÒÕÓÔÕÓÓÒÐÑÎÎÐÆÈÌÀÅÊÆÉÍÓÓÕØÕ×ÔÓÕÒÑÓÓÒÕÑÐÔÎÐÔÐÒÕÎÒÖÍÑÕÏÒÖÎÑÖËÐÕÉÎÓÅËÑÈÌÐÌÏÔÏÒÖÏÒÖÌÐÔÌÐÔÍÐÔËÐÔËÑ×ÌÑÖËÐÕËÏÔÌÐÔËÏÔÉÎÓÉÎÒËÎÓËÎÔÌÐÖÎÑÖÍÐÕÌÏÔÌÏÔÍÎÒÌÎÒËÍÒÊÎÑÊÍÒÌÎÔÎÏÕÎÏÔÍÏÓÌÎÑËÎÑÌÍÑËÌÑÊÌÐÊÊÐÊÊÏÊÊÏÈÈÏÈÈÍÆÇÍÅÇÌÅÆËÅÇËÅÇÌÆÇÌÇÇÍÄÄÊÂÄÊÃÄÉÁÂÈÁÁÇÂÃÈÂÃÈÃÄÉb…uŠ¢”ÃÌȸƽ“¯¬¡³À”¨¶‘§´•ª·˜¬¸›¯»ž°¼œ¯¼¯¼œ®¼š®¼•ªº¦·ˆ¢µƒŸ´€ž´‰£¸²¿ÈµÀÉ´ÀȰ½Å¬»Â¬¹Á¯ºÃ¬¸Á«·Á©¶¿¦´½§³¼¥²»£±¹¡°¸¬µšª³œ«³¢¯µ¤°·©µ¼·ÀÅÀÆËÉËÎÔÒÔ×ÓÕÔÐÒÔÑÒÖÒÓÙÔÕØÓÓÖÑÒÑÏÑÍÌÏÌÌÐÑÐÓ×Õ××Õ××ÕØÕÓÖÒÐÔÏÏÓÎÏÓÏÐÔÏÏÓÐÒ×ÑÓÙÏÓÙÍÑ×ËÎÔÌÎÔÎÑÖÏÒÖÎÐÖÌÐÕÌÏÔËÏÕÉÏÖËÑØÌÐÖÌÏÕËÏÕÌÏÕÊÎÔËÎÔËÎÕËÏ×ÌÏ×ÏÑØÏÒØÎÑØÏÑØÏÏ×ÏÏÖÍÏÕÍÏÕÎÐÖÏÐÖÎÏÖÌÍÔÍÍÓÍÍÒÌÎÓÍÍÓÍÎÒÌÍÑÍÌÒÌÌÒÌÌÒËËÑÊÊÐÈÈÏÈÇÏÈÈÎÇÆÎÆÇÍÅÆÌÈÈÍÈÇÎÆÆÍÆÅÌÄÄËÁÂÈÀÂÈÁÃÉÃÃÊfŠz†›‰‘ªšsœ„u‹ÊÍε¾È—©¹Œ¢±‘§µš¬ºš­º™¬ºš¬º›¯¼™¯½—­¼§¸„¡µ€Ÿµ…¡¸©·Ä·ÁÊ·Ã˶Â˳ÀÉ®¼Å«¹Â¨¶À§´¾¨µ¿ª¶¿¨³½¤±»¥²¼¥±¼žª¶•¥±“¢­Ž¨Œ§‘¡ª”£«ª±ªµ¼ºÀÅÍÎÑÖÔ×ÓÑÔÒÏÒÔÑÓÖÓÔÛÖÖØÓÔÖÑÒÓÏÐÓÎÐÌÈɺ·º¶¶¸¶º»ÇÉÊÒÑÔÕÔ×ÓÑÕÑÐÓÐÏÓÐÏÔÐÑÔÒÒ×ÓÕÛÕ×ÝÑÒÙÎÑ×ÎÑ×ÑÓÙÐÓÙÏÑ×ÍÐ×ËÏØÊÐ×ÊÎÖÌÐ×ÌÐ×ËÐ×ÌÑÙÎÑÙÎÒÚÎÒÚÍÑØÏÒÚÐÓÚÏÒÚÏÑÙÏÐ×ÏÐØÎÐ×ÍÏ×ÏÑØÏÐ×ÎÏÖÎÏÖÎÎÖÏÎÕÏÏÖÎÎÕÎÎÔÍÍÔÍÌÓÍÌÓÍÍÔÍÌÓËÌÒËÊÑÊÉÑÊÉÐÊÉÐÈÈÏÇÇÎÈÈÎÇÇÎÇÇÎÈÇÏÇÇÍÄÄËÂÃËÃÃÊÂÂÊQƒnŽžS|].lKs˜…²¹®¥“¢·¾œ®½‹£²’¨·–ª¸“§¶”§·¨·‘¨¸Œ¤µ€ž±x™°r–¯˜­À·ÀÊ·ÀʸÂÌ·ÃÍ´Á˰¼Æ«·Â¤³¾¢¯¼¢°»£°»£±¼¦±¼«¶Á®¸Â­·Á«³½«´½°¶¿ª°¹¤­µ¢ª³Ÿ¨²£¬³ª²º¶¾ÃÍÎÒÔÒÕÐÍÑÎÍÐÐÎÑÖÒÕÚÕÖÛÖÖßרÔÎϘœž›—˜™—™v}‚q{|†Š” ¶½ÀÄÇÌÊÌÑÉËÐÇÉÎÉËÏÎÎÓÑÒØÕÖÝ×ÙàÖØáרàÖ×ÞÔÖÝÓÕÜÐÒÜÌÑÙËÐØÌÑÙÎÒÙÌÑÙÎÒÛÏÒÛÏÒÛÎÒÙÎÒÛÐÓÛÏÒÙÐÓÛÏÐÙÎÏÖÍÐ×ÎÐØÏÑØÍÏ×ÍÏØÏÏ×ÎÏ×ÏÏÖÏÏØÏÏÖÏÐÕÏÐÖÐÐ×ÎÎÕÍÌÕÍÌÓÎÍÔÍÍÓËËÒÊÊÑÉÈÐÊÉÐÊÊÑÉÉÐÉÉÐÊÉÑÈÇÏÉÇÏÇÇÎÆÆÍÆÅÎÇÆÍÄÃÌ,oS˜‰GsQ!\8:lMFxWe=6}_’¯±ž°Á‰¡°Œ¤²Ž¤³‹£²Š£³„Ÿ±|š®s”«k‘ª‡¡·¼ÂλÂͺÃͺÆÏ·ÃͲ¿Ê¯½Ç®ºÅ¬¹Ã«·Ã¦³¿Ÿ®ºž­¸¥²½­¹Âµ¿Æ»ÂÉÉÏÖÓØàÕÙàÐÕÛÉÎÕÄÈÏÂÆÌ¾ÂǼ¿Æ½¾ÇÅÅÎÖÒ×ÝÖÚÛÔÚÔÐÕÕÐÔ×ÓÓÚÔÔçÝݵ°³QV`¤ž ­ª®†hqyKV]3<@?GH`mo™¯¸¾¼ÂȼÂɽÂÈÀÄËÆÈÏÌÎÕÒÖÞÕÚâÖÚá×ÚáÖØáÒ×àÐÕÞÐÕÝÎÓÜÍÒÛÍÒÚÍÒÚÍÒÚÍÑÚÍÑÙÌÑÙÊÏ×ËÎÖÍÐØÎÐØÏÐÙÎÐØÏÑÙÏÑÚÑÒÚÐÐÚÐÐÙÏÐØÐÐØÏÏ×ÏÎ×ÏÏÖÎÏ×ÐÐ×ÎÎÖÍÍÕÍÍÔÎÍÔÎÍÔÌÌÒÌËÒËËÓËËÓÊÉÑÊËÑÉÉÑÊÉÑËÈÑÈÇÏÇÇÏÆÇÎÅÆÍÈÇÎÈÇÎeFW‚k/gB!^9*a?%a=^6 W*f@pž—£³Â‰ °š«x–©p‘§m¥iާdŒ§s“¬²¼É¿ÆÏºÄͽÆÏ¾ÉнÈѺÆÏ¸ÄÍ·Á˰¼Ç®ºÆ¬¹Ä¬¸Ã¯ºÄ¶¿ÈÀÇÏÉÐØÔÛãÚâêÚâëÚâëÙàéÔÜåÐØáÍÔÝÈÍÔÂÇË¡¶¯w Žc•}j˜‚z ™¯¦¹¾¼ÏÌËÙÑÑÜÓÓ¦¡£zƒ»³´³±´ƒ‰‘gqyKTY9>AAGL>GL?HLOZ\x„ˆ¡«²²ºÁ¸¾Æ»ÀȼÁÉÂÅÍÇÌÓÍÔÜÒ×àÒ×àÑ×ßÒ×àÓØàÑÖÞÐÔÞÎÒÜÌÒÚËÑÙÌÑÚÌÐØËÏ×ÊÎ×ÌÐØÌÐÚÎÑÚÐÑÚÑÓÜÑÕÛÒÓÜÓÔÜÒÔÜÒÓÚÐÑÙÐÐÚÏÐØÎÏ×ÎÏ×ÎÎ×ÎÏÖÏÐ×ÎÏ×ÎÏÖÎÍÔÎÍÔÍÌÓÍÌÓËËÓÌËÓÊÊÑÉËÑÊÊÑËÊÑÊÉÑÉÈÐÉÈÐÇÇÏÆÆÎÇÆÎÈÆÎ!cA%b>X0\6'b=,e?-eA&b<Z/d8U‘}ž²¾ƒœ±t“¨n¥h‹¥dˆ¤iŒ¦ °ÁÁÉлÄͼÇпËÒÃÌÕÁÌÕ¾ÊÒ¿ÈѽÆÐºÃνÅÑÇÎÖÒÖÞ×ÛäÙßçßåíåêôäéôÜäìØàæÐÚÞÇÔÕÖÙÛØØÚÕÕÔÕÑΨ‘2|Qm?c0 b4 a53uSˆ›‰¸¶¯ÏÉÇÒḬ̀«­®§¨Ä¾¾¤¦ªv‰W_eMTYajqeqxansEMQ:FIn|€˜£©ª³º²¹Á¹½Å¼ÁÈÁÆÎÈÎÖÌÒÚÎÕÝÐÖßÓÖàÑ×àÐÖßÎÕÝÍÔÝÌÔÜÍÓÜÍÒÚÍÓÛÏÓÜÐÓÜÏÓÝÐÓÜÓÕÝÓÕÝÔÖÞÔÕÞÕÖßÔÖßÓÔÝÓÔÝÒÓÛÑÒÚÐÓÚÏÑÙÐÏØÏÏ×ÐÐØÎÏÖÎÎÖÏÐ×ÐÎÖÏÎÖÍÍÕËÌÓÌÌÒËËÒÉÊÒÊËÒËÊÒËÊÑÉÈÐÉÈÐÈÈÐÇÆÏÇÆÎÉÇÏ]6[2Z3Z3 `<#b;)c>2fB,fCf;b37€bŠ©¬Œ¡³s‘¦o¦iŒ¥„±¹ÃÍ¿ÇÏ¿ÉÒÃÏÖÄÐ×ÄÎ×ÂÍÕÂÍÖÈÐÚÐÖßÚÜääåìëìôæêòÜãêÓÜá¼ËÊ—°¦uš‰V†m?wW+jFaŠn°¹­¢´¡ÅÇ½ÄÆ¼pœzz†R‡eh7mD*qK@xX~•‚½º³ÏÈÆÔÍÎÆ¾¿»µµº·»–™ S\dNSZnu|s†ly€DOS"$!#% !"&-.GTXt‚‡’œ¢¢«±¯¶¼´ºÁ¹¾ÅÀÅÍÆÍÕËÓÛÑ×áÒØáÐÖßÐÖßÏÖßÏÖßÐÖßÐÖßÑÖßÒÖßÔØáÕØáÔÖàÖØà×ÙáÖÙáÕ×àÕ×àÕ×ßÔÖÞÔÕÝÓÔÝÒÓÜÒÔÜÐÒÚÐÑÚÐÒÚÑÒÙÒÒÚÐÐÙÎÐØÏÐ×ÏÏÖÎÏÖÎÏÖÍÎÔÍÍÕÌÌÔÊÌÒËÌÓËËÒÌËÑËÉÑÇÈÏÇÈÏÇÇÎÉÈÏ\3[3\3W/_; d=]4 _7,e@*gCi?h8!{S‰©¦ˆŸ²jŒ£l£ž°¿¼ÅÎÃÌÕÇÑÚÇÒÛÇÑÛÍÖàÜàêâåíàäéÝãåØàâ¿Į́Ÿh‡uPs^BhO.^=T.O' V-[4 Z4 iD;{Y„¢ŒÍËÆ®¼«¢¶¡ÍËǃ …i9h=3vTMc…˜Š»¸²ÎÈÇÑÊÊÊÃÃÆÀÁ³¶»”QU^[^gƒ‹’ly>IM!'*-27Q\cJTZ;BE&)*09;Yfjy…Š‹–››£©¦®´®¶¼·¿ÄÁÇÎËÑÚÒÙâÓÚãÒÙáÑØáÒÙâÓÙâÔÙãÖÚâÖÛã×ÜäÖÙãÖÙâÖÙâÖÚâ×ÚâÖØáÖØáÕ×àÖ×ßÕÖßÔÕÝÔÖÞÒÕÝÒÕÝÒÔÝÒÔÝÑÒÚÓÓÚÑÒÚÏÐØÎÐ×ÐÐ×ÏÐØÏÏÖÎÏ×ÍÎÖÍÎÖÌÌÔËÌÓËËÓÌÌÒÉÈÑÈÉÐÈÇÏÈÈÏÇÈÎ[1"`sHRn°¹¬ÈÈÈ‘¡²—§¹½ÆÑÈÑÛÊÔÞÍÖÞÒÙßÒ×Ú¼ÈÇ”°¥x™‡Yh@nQ1`B$Q3D%A (R30\<+]:!Z4X0^8a<a=a=3vU¨µ©ÎÎÆÇÊ¿ÖÓÍßÙÕ§³¢/sGf>&mICy^”‡·´¯ÆÁÀÊÄÅÀ»½½º»½½Á¤¨®‡‹ƒ‰}…ŒHNV"(3;A^ktcrz[iqQ\c8@D+// $+,>JO]imozs~‚x†|…‰‹“£¬·½ÁÊÑÏØßÕÞçÖÞçÖÜæÕÜåÔÛãÕÛãÔÛãÔÙáÔÙáÓØâÔÙáÒÖÞÑÕÞÒ×àÔØáÔØàÕÙáÔØßÔ×ßÔ×àÔ×ßÓÕßÑÓÜÐÑÚÐÑÙÑÒÚÒÓÚÓÔÛÒÒÚÑÒÚÐÑØÏÑØÏÑØÎÐØÎÏ×ÌÍÖËÌÓÉÊÒÈÊÑÈÉÑÈÉÐÆÈÏÅÈÎ(^@Jr\a‚j&^7U.2jI2mLc8a2h=@^rš~²¹ªÏÌÂÈÇÀ›« •®«§¼¼¥¼¸ÉÏÎØØÕÔÒÉÂÁ´u~$]?O,Q0L(G&F'F)"M04]@5bB2cA+c=`8`:a<c@kHp‘}¯´©ÈÈÁÝØÑÝÙÑÞÚÓ±º«1rFiCF{_P}c|”„º¸³ÅÀ¿ÃÀÁ»º½¸µ¸µ²·¬­±’•™’–šˆ”ejsQT`_iso|„fqyamsXcjGPU.35!*-5@DP\`V`d[_d[_dLV\5>C.66MVYo{€•¤ª¸ÇÍÏÚãØàéÖÝæÕÚåÒÚãÒÙâÒØáÑØáÒØàÐ×àÐÕÞÐ×àÑ×áÓØàÒØáÒÖßÓ×àÔØáÒÖÞÓÕÝÓÖÞÒÔÝÑÓÛÑÔÜÒÕÝÓÕÝÓÕÝÓÔÝÑÓÛÐÓÚÐÓÚÏÒÙÎÐØÎÏ×ÊÍÓÈÊÒÈËÒÇÊÒÇÉÑÆÉÐÆÇÏ>_RPr_/kG!`<_:&cAc@e?!oK‹£’µ¸®µ¹­ÍËÃÝØÑàÚÓ¶¾®AzRf=?z[w‘€›¤™·¶±»ºº¾½Á¹¹¼¶µ¸®­²žŸ¤„ŠŽ’–•›|…Œv€‡q|„y‚‹v€‡nw~\gl>EK!%('+-(,-27;PW[U]asw}s}…CNU GJNNW]N[aSdjwˆŽž¯µÂÏÖÓÝæÖÞèÕÛäÔÚãÔÚãÓÙâÔÚãÓÙâÔÙâÒØáÒ×áÑÖàÐÖÞÑ×ßÑ×ßÓ×àÒØàÔØàÓÕßÓÖßÓÖÞÑÔÜÐÓÜÒÕÝÐÓÛÐÓÛÏÓÛÐÓÜÏÒÛÍÐÙËÏÕÊÍÔÉÌÓÈÌÓÈËÒÈÌÒÇÊÑÆÉÐ6aO7oSiBf?[7T2*bEBpPIwXžÃÀµÆÃ³ÔÍ¿¼»¨Q}XX/'eBv‘€¯³®ÓÐÌÖÔ̳¹©g‹m)fN(W?+T7#P0I'F%F'G*$P1&T3#U1#V2$Y5!`=d?e?e?hBe–zÈÉÁÌÇ¿ÁÁµÑÏÈàÛÕÆÇ¼Zˆe+qK:vVnz·¸±½»¸»¹¸Â¿ÀÂÀú·»­¬±˜™¡vxyƒ…’€‰{…Žxƒ‹Œ”~‡ŽgrwALQ(-2"',;EKBILhkqt|ƒkryŠ‘n{‚7AFNTWmyky\ir[ipLX\0:=N[\{Ц¶¾Ì×ßÕÜæÖÝæØÞæ×ÜåÔÛäÖÚã×ÛäÖÚäÓØáÑØàÓØáÓ×àÑ×ßÑØàÑÖßÓ×ßÒÖßÒÖßÑÔÝÐÔÝÎÓÛÏÓÛÎÒÚÍÓÚÏÔÛÎÑÙÍÑØËÏÖÊÍÕÉÌÓÈËÓÈËÒÈÌÓÈËÓÇËÒ'rR oKe>[6U4M-R/5hERvUZb˜¥–ÕÍÁÖͼw“oZ0V04lM°·­ÂÁ¸¯µ«{•z>lF(YC(OO*P?.X:$R1G&G(G*J,!N-P. R.!S0T0^9d?e?d>gAHˆe·Ã´Þ×ÒÏËÂÄĺÔÐËÖÒÌzš~0vOt•€œ©›½½µ¿¾»¸·¶¼¹¹À½¿À¼¾´²´Ÿ¥Œ–‚……Œ‡Ž‰‘{ˆv‚ˆ]hn8AH#)0$( %*@KRIU^Zch•›€‹“u†…Ž—nx8AI6>Bmx~q~ˆjvepzm{;CE)-.39;*18'*Uek¨¸ÄÎÙäÕÝçÕÜæÔÜåÕÛäÖÜå×ÜåÕÛäÖÜäÕÛäÖÚãÔÙâÔÙâÓÙâÕÙâÑÕÞÑÕÞÑÕÞÑÖßÑÕÞÐÕÝÎÔÜÏÔÜÑÕÝÐÔÛÏÓÛÍÑÙÌÏ×ËÍÕÊÍÕÈÌÓÊÍÔËÍÔÊÍÓ!vOkAa;_<^;]<[8I{^–žŠZyXMwWŸª—™¦*d9T+P);nN»¿µÂÀµ\}^*]8*[C-WR+YF&UA$ZD"W:J(G(I*L,N,P,Q,S-[5c<e?c>c<&oJ<[•¯™ÕÑÊ×ÒÊ·º°¯µ¬Âľ®¹«ª·§¥±£—¨—ÄÁºÄ»»¹¶À»º½¹¹ÂÀø·º««±Ÿ ¥’•œƒ„‘†ˆ”„Š“xˆfmsR[b9>I')5',5HT\[jrP\bdkp”›¢‹•fqz‹”œmwALVZdkz…Žvƒr‹u„n{ƒ:BG*/0&+.5>F )@MWŸ²ÀÉÖã»ÉÖÈÕßÐÚãÑØãÒÙãÓÚãÒÚãÓÙâÕÛäÔÛãÓÙâÔÚâÕÛäØÛãÖÚãÔÙâÓØáÓØáÓ×àÑÖÞÑ×ßÐÕÞÑÖßÒ×ÞÑÕÝÏÒÚÎÑÙÍÏ×ËÏ×ÊÍÖÍÏ×ÍÏÖÌÏÔ~UzSwNoIgBY5Z8‚™ˆ»¹­•Št‡kRvTApN ]7V.P'9lN¬³¥‚—{(]4+]C/ZR0]G-c=(hHaIWHM2I'K,O-P*P,S.]7fAgBe?c;Oƒc›¨–Ž£‹ž±šÄȼ¿Ä··¼¯´¹®²¸­ÂžÜÖÕ˜«–e‹o³¹­ÂÀ¹¶·³¼º¹¼¸¸»º»¹·¸º»½²±´¬¬¯—˜¡‰Œ˜…‘t|†ipxfowks{gnwgqzn|ƒiu{R]bdmq—ž¥•™¢_ep{…Œxƒ‹BKULT[„˜Š–vƒ~Œ•›¥Wah#$).2/6A*0Aft„µÆÓÁÏܯ½Ë³ÂδÃÐÁÎÚÊÖßÌÖàÐØâÒØâÓÚãÔÛãÑÙáÒÙáÕÚâÕÜä×Ûä×ÜäÖÛãÖÚâÔÚâÔÙáÒ×ßÓ×ßÔÙáÓÙàÓÖÞÏÓÛÏÒÚÏÒÚÎÑÙÏÒÙÍÒÙÍÐ×ÍÏÖyRwOnF"d?![5K('_Bš¥˜°´¦ÅÁµ«¬—CkE4d@4hF(b=Y1=rQ†œ…@mF"X;,YR/\H/`;,c>9}[0„bsUbFS4S1R/T2Y8a<gCgBfAkE^ŠnÀÀ³àÔÏÙÐÉÔÏÅÔÐÈÌÊÀÐÏÅØÕÍÒÍÇÀÁ¹¡°¢g‹rU‚h’¤•°³­¥¬§°³±º···µ¶®¯±¬¯²¹¹¼¿½¿´°´›š£’œ…‹’~…‹|ƒ‹‰‘™“›Œ”x‚‰jrxQY]T\`Œ”š«®´’›y~‡ˆaltIS\v‰{…‘|ˆ’‡•Ÿ”¥¯cmx !5E{`q‰yPjf4_T*`<+_;._<3hF3oL=sTm—P‘p#|X!z\.zcH{jGv\d‡rt”}ž³¡¸Ä·‹©±’„ǧoÄžyß’Ĩ½Ÿ¥À¨ÐÐÇÏÎÃÌÌÄŒ¦’y•†Pyg.jRZƒo‡œ¢©¤®®®³²²±°°±°°®­­££¦Ÿ ¤œž¢•™ž§©¬µ³µ®¬®¢ ¤¢¡¥–—›ˆ‹swy`dfUX[X[^‚…ˆ§¨®±³¹±µºž¥«Œ”›œ¡¦–¥‰•žƒ™ƒœ†—£uŽ?GQALTv€‰” ­¬ºÇ¬¾Í¬¾Î«¼Ë¡µÄ§·Ç«ºÇ¥µÂ˜¨µ™©¶ž®»“£°sƒŽN]e[hpr€‰ˆ— ˜¢ªŸª±²¼ÂËÔÚÕÚâÚÞåÛàæÜàèÚßçÙÝåÙÝåÙÜã×Ûã×Ûâ×ÚâÕÙáÕÙâ×ÚâÖÙáU2T0!U4"Y6Y6Lu\}’‚ «œ¬°:d=N)V0X1]3[9 ^Cq|«©¡—›“…’zSuS6c@2a>9rQ5qOh„q£«£ž‡3\!Z$€[0zWVf£­¥®¹¬ºË»—¿¢<†W2’gJ´‰Nµ‰S°†Q¨~k¨ƒ»Å´ÑÏÅÄǹ¾Á¸W‡iD}a3qP*lKWksƒ„—‘¨ªªª«¬¥¥¦žŸ ¡¢¡   žŸ›šœ——š™š¯®°ª©«£¢¥¡Ÿ¡ƒƒ…knqklm[`cW^bX_buy|¡£§«¬±ª®²¡¥«•𠆋’”𑙢Е ‡‘Ÿˆ—£ƒœ`ivNYd‡— «»Ç©ºÊ¨¹É°ÀήÀÍ¥·ÅªºÇ¦¶Ä¨·Ä¯¼È§¶Ã”¥²x‡”IU`ZhovƒŒu‚‹x†Žqz‚GOUQ\c^irŒ˜Ÿª´»½ÅËÏÕÛÖÜâÛßæâæìâäìÝàèÛÞæÚÝåÙÜãØÛäÙÜã×ÚâT.Q/S2W3X4EtZzŽ}v“xW}[Q)R,S-W1[=#dK3wVƒ—…¦¨ ÈÁ³ÐȺ¸µ¥y‹o9jE7xY6pNrŒyª°¨˜©˜Qn*„^~XmCFvV›ªŸ´¼±ÑÑÉÆÊ¼n‘m+‡Z9¨z>ªz;¢tGq—´›ÙÓÌÇɼ¼Ã³­·¨6xQiC#jF0oOK{cs€˜“›š™žž ¦¤¥¯ªª£ŸŸ™™šžŸŸ  ¢™š›žŸ›š‘ˆ‰‹rsv]dh^dgW`dT`dU_daik‹©ª­¦§¬¡¡¨–™¡‡x€Š‰’œ‡œ“›©”Ÿ®™¨~Š™mz‡…•¡ ¯½ ¯¿¯¼Ë²ÁϪ¼Ê§ºÉªºÈª»È®½É­½Ê™ª·†–¢pfwƒp~‰ly„s…Ž‘™\foNZ`Weogu~Š•œš£©¤¬²±¸¾º¿Ã»¿Ä¼ÁÆ¿ÅËÉÐÕÖÜáÝâçáäëßáéÛÞæÜÞæR0P.R0U0T0:nSŒ™‹K|UV, R."U5S7R; _F(vP2qUg~v¸³§ÓʶÕͽØÐ²´ Va/yVsIT.#R2S7%Z>8lK*uL$nP/cU˰ÐÇ´ÑÉ·Öνµ¹£I€\,vR1{YQˆm“¥˜‚œ‹už…Wšv(vNX/ ]5BuV—©›ÖÔÌâÜÓÅŶ¦´Ÿ«Ã®’¹›š¶šÏÍÁÐ˽º¾ª¢² •«™I‚_f>d>%jI9qUXk–ŠŒš–”›šŸŸªªª«ªª  ¡¨¦§¢ ¤’”™‰Ž“€†‹y~ntxgotZdhHSVCNRDMQ3ILFPSgnr„‹‘œ¡§›¥®˜¤¯›¨´œ¨µ¤°½´¿Ë²¿Ì¯½Ë©¹Ç¤µÃ¢³Â¥·Æ£´Ã—¨¶¡®†—£ev…e{Š…š¨‡š©€—¦mZlwr‚…•¡{š†™¤…”Ÿo‰gu~cnvˆ•¨°¶¯¶½¯µº²·»´¸¼¥ª¯”™Ž”—Š’”s€YmhWqhLm`}”†¦²­a‡y P:F*O1Q5V;„–Š›¨”0j@U0O+5eE‹—€€—|H|eSwg5nJ†—ÊÁ°ÏƲÐǵÔʹ¢…(pI*tQ2|Z.yUE~b.uS=„aFl#h?S,Y2~_¿Ä»ãÜÖÂõ°·£Ü×ÐØÓÉÎÊ»ÜÖÌÝÖ˼À®ž„Nƒdg>e?gB0pQGx`P}ifŠy‚“Œ–œœ¥¥¦¬«¬¤¢¤›™š§¥¦ ¢¤“—{‡kt{YbhFOS>HL;CEGHH49<4;>145(,.*026>A3;=FNRbjn|…Šƒ—‡”¨™¨³©·ÃµÃͬ»Çœ­¹ŒŸª“¥±”¥²” zŒ—xŠ–bs~VfqZmyi{ˆlŽUhuFW`CS]Zmxrƒ{Ž™‡™£Š˜£_nwO[bals„Ž•¤­³®¶½«²¸©®³ª¯²Ÿ¥©‘•š•˜ˆ’|†‡o~{Xsi?iY3dK|–ƒ¯¶°„š‹F1/R>:dI"X:5bQ›¥šy•}$b>R0 M&FsX™¢–v—‹‹˜}$e7[b¿º§ÏÆ²ÐÆ´´¶ŸN\mG&qN1{Z0{X$qMg@oF"tM[1T.V/W0Z2cŒnÎÍÆ¸»«Ÿ„ÑÎÆÒÏÄËÉ»ÛÕËàÙÐÔÏÅz›€!h?d>!eBa<$lJ=v\Ct`X}nu‰ƒ‰‘’”𛣤¤¦¤¤«¨¨££¦“—z…]ehPX\=EJ-366;=9>ANOPHLMFKMW[KY]Vbg_lro}ƒ…”š|Œ•k{„`qzcu}oŒdvƒWiuL]hCT]GXaM]f\oxgxK^j5BK1:?M]ddv~xŠ”‹¨¨iuJTYksyˆ‘––Ÿ¦“›¢”›¡œ¢§™ž£‡Œsx}tz~r{}hsuoyxo}{_vo9hT9mM»ÂµâÜÜàÚÚ0O@Zpb…€f~jt‹~¶¸¬k‰nZ:V6O;5bYƒ“ˆ¬­žÍ¯‚—uX,PvW¾¸¦ÒƳý©l”r"oG"lG"oJ,vV2|[,wRmGoEh>W/V/U.T.U.Z1x•~ŠœˆVZº¾²¸¼«¶¹§ÚÓÉàØÏÕÐÇe‰kV, eA+lKb<dH3n[Duc^€ruˆƒ†Ž‘”•˜™˜   ­ªªŸŸ ~‚†fjnYY[?AE@DF9=>6;=OUYW]c_gjS_dMY_KV[GRWEQVHTZENVBMR1;>)26,69,6;6?C8BF?LQCQVDSZIY`M[cP^fQbkYirbow\goJW_ANT2-7=0;@5BICSZK[cTck^nvevet~^nxfyƒw…u‚ŒjvPYd'-1 (,)27EPWKW]Wci\gmhs{akrakrZemmv||…‰puyWZ]UY[[babfeipn[piCm^+sW:‡c¾Ë¾èâãáÞÞàÝÜàÝÛ6^LAiT;sT%iE^:O=IAM8S0_;2tRH„bE„a(xPpHnFqG,zSA„^'{TxNrJ lF!lG lI)uS3|[*uQnElC*eA"Y7[5W0M*L*O(2dCxzwq𦔛§‘–}=fCK&O+ Y3*c<;mI8pS+lOaC"^O7ieFkij}‡Œ™š¤¤¢–•–ˆ†ˆŒ‰‹‡…‡|}€x{~pvzdmrbovdpx`mucqzhu{yƒ‰…–ƒ™w…|‰”z‰’jyƒVgpRcmN`jFVa:HP6CJ4AG0;A,8=3BIN^f^muVfnRbj_pyp‰jxƒm|ˆ|™‡•¡}‰—Xbo:GP:FQ6AK2YFOCM3J)M*]7e>iBmFpIpIoEoEuM#{UzTzPvM nG lHmG"oL2yZ.xSjA2uR†—‡EpQZ3]5X2R/O*#Z7„—ƒ ¨”ª°›Š(Y1K'O,Q-![5+ccNTye1fQP<P0N.K,i?jAkCnFuL*~Y&~Z|U|S'yT%qJmGlEjF,sT0yVhAfŽw®±¨LxXZ3[4^6"_:#\<V5 ‹ÔÍ઒>hER,Q,O+Q-#Z6(_:CnOHpR!g@0pU=od8l_LmovŠˆŸ¦ž§§¤  ž¡–’’ˆˆŠx~‚_kqO]dTakUcnWeoerzn{‚†—€ˆ“\`p;?M'*8!-%+97@SN\rnx‡”j{†au€YnzWkuTgqSeoO_iTdmSclN^gUgobs{gv€cqzdt~›‡• ~Œ˜’£¯ ­¹¢°»¤±½†‘Ÿbo~fx‡guƒ`mwhs{w}‚jrwfpvahkpuv{~~aplUylMl)|^"ƒ_‰a&‹`¥Ã­éãäåâãàÝÝàÝÜàÝÜB,1VJ{‰†}‘~*_8N,P/U5qˆv¢¦•S‚]kAkAj?j@nD#{S0‚` {U{R"}W,yW(tO nGkFiC%mK.wU8xWªžµ¸®V~`a;^6]4b9*hL3mV‰£ÍËÂn‡kL$$W5R.O+Q/$[6(_:-a>QuYLwYFubK|mRxo^tx“œ—¥§Ÿ ¢ž¤¢ ˜––„ˆŠry~erybpx^muXit]nxiw€v‚‹‚•„Ž˜VZd86A10M*)H'(F0/Y00L&*4=IZu…•x‰•o‚exƒ\r}Zp}WmyZoz\pzZmx_oz]nySeo_oyn}‡|Š•ƒ‘yˆ”€˜„’ž“¢­£±»¤°ºŸ«µ˜¤¯‰–¢x…’nz…es|r|rzlsxdilinnpyvXxm;p\9f&ƒb…_Z[ž{ÙÚÕçäääáãÂÌÆÌÒËäÞÝC:)NIuˆ‚—ƒ2b?N,P.R1W|eª˜d—rzJnBj?h>mB%{U+[wNzS(zX'vT%tP!pHlGjD jE+tR^‹sµ¸°º»°e‡kd>d=c;e:"qJ-ydf˜…¤’@fEJ&#U4$U3M)S/'^9-c>0c?@kK[zhQxsd„~p„……Ž‘­­¨§¨ ¡¢Ÿ¡ ¡‘”v…yƒŠhw_ozbq{Yjuar}r€Šƒ˜‹– goyFELBAq67Ž-+u*(h.,y64…;;Y+/;M\kz›z™o‚bv„TkzMfuRkx[q}dx…m~Šj{‡dtcs}t‚‘Ÿªˆ•¡}‰”x…ivƒpŽ‹œª¡®¹¡«¶–¡ª—Ÿ‡˜‰{…Žju|nuw}€€‚ƒ|„‚VphBo_2w^(}_$ƒaX9Žf¸ÉºéäåçääàÝß|¥’›¹£èáàC8?)*YA-fHX7N/M,S1Kx\W”o)Y|KtE1{SEyW#oF"vP ySwN$yU%wUsPvO$uO!oG nF lE%pNO†l«³©¾½´sve>fAhCkAxN]6†oG{](U3*W9 S2*Z;M(S/)`jJ=iGVv^b~v\ysn}}•𛲲®¬­¨¬ª©š ‚Ž•o€Š`r}`oyOaliw€uˆr‚~˜ˆ”žv;@FCBUB@”""zYQ^#!JL‹58F/8CgyŠ}žwŠ™l\rJaqE^nOhvax†iŽo„w‰•z‰–‚›{ˆ”ƒšˆ”ŸƒŽ›}‰”ƒš’Ÿ©—£­‹•Ÿ‰‘˜‹’™z‡z€…w€ƒrx{„„‹‘Ž“›|”‹E{g/v\"}\}YXC‘jªÂ¯äááçææéäæ²Â¼&zULiÚÙÓ<#<I)`?]<O0J'._@_„k-„W}L{JP0€WKm8:‹58S+/7APbr„—}Ÿv‹›o†”^t‚G]l8O`C]mRm}hŽyŒšˆ›©„•¤‚‘†”Ÿ›¥•¡ª˜£¯…Š– ˆ‘š„‹‘‚І‘Ž–š†Œ{}}†ˆ†£¥¥‰Ÿ™b‘R†q4{`'}[+„^F’lw¨ºÊ¼ãàáØÛØêæçÇÎÍHŠl k=pC•³œ; @"P.cC^=R01^>l‚mQ_h?mBwJwLkAc;lFvOwOrJ uPvRvLzO{P,zQ,tL#pJ$oJ(tPo–€»¼´¸º¯tv&jCf? hE$oKe•yŸ±ŸKrO!T2$V4P-'X8?fL9cE+^:/a>:fFMqVfl‚“†‘›’•š—¶³±½»º§¬°Š—Ÿq€ŠSesL_o_r€hzˆt…“œƒ“Ÿ‡“Ÿz†”X_qCDJFB_)'‚iO@:D\ |,-d.0743{SL>G\aq‡xŒœ|’£uŽžoˆ˜e}WpPh|Ph}E_tHdwXr„xŸ›«¸¤°¼š¨´‹š¥‘œ¥¦°¶¨¯¸‘˜Ÿ~…Šhqsmts‡„£©§»ÀÀ§Ÿ={b7y\CgAdO†m{¡Š´Äº˜®žÈÑÇîêìµÁ¾XŽvsJ l?n?mAd=?"O0[<V8 T2cC€™‰y”w`4Z7N+K(_7g@rLwPzQ)€YS‹ka’twŸ‚”ª­´ŸÉÁ°Õʺ¾«hŒj&rJ$qK;}_™«ž¿¿¶½½³©˜]…i3qQ)mN:x[¥´§‰—M'M*"U3-^>6aC2a@?kMSv^e€mn‚tq‡y‡–©¬¬ÁÀÀ®²µ™¡x„Ž^o{ThxNh{^y‹q‡—|ž~‘Ÿƒ„›• ‰‘ƒš}‡˜r{‘ck‰UY{<=b!#B ;-/RBCnRW„_fˆck~fn€gp}`l~m}‘zŸ|“£x’¡tŸj…˜]yŒPm‚Ol€]w‰lƒ”}•¥‰ ¯™©µ®¹Ãª³½§¯¹¨²Œ•ž‡–†Ž’oy|nzy›¢ °¶¶}¡–Gˆq2x].rS-sQ;~]v‚´Á³ÔØÔÐÔÎåäãïìí©·µhIk>mAmAlA#b?F(X9[=T5S3 ^=@{`FvWZ2O,@ F%_8rMxPzQ~R?ŠaŠ…²²ŸÍųÒÇ´À½¨±µŸÆÂ±Ïɸ¥¬˜Tƒb*tL(tPxœ‰¼¾µ¾¾³¸¼°ž©šu’wW„cBz[~žŠ‚”€&U2O-R/S10_ABkOLrWQt[Xwco„x|Žˆ¥¢²²³¢§¬~Š•]pZogzˆl~Œrƒ’yŒ™~’ŸžŠ–¢–¡ª›§‰•¢€ž{Št”lyeqˆQZu*,A,.EOUrblƒkxp”z‹ž€‘¢ƒ•¤‚‘ x‡˜u‡™z‘¡€™§y’£r‹mˆ›e–j†™gƒ˜j…šsŽ¢†œ­¢²½®ºÅºÂ̦®¹™£¬ž¨¯‰‘—q{iuvyˆ†¤¬«Žª¢F“w$h ‰cbaH©}ÒÝÕôðòòñóðïðïîîáàãl‘„^<h>mAmAlA&a>S4bB\<S4R3 Z9b?\9N,D$=!F']9wP{P!}R~N@‹`}‘w–ž…Å¿­Òȵª­•fŠf”¥ÅÁ²¶¸¨“¡ir7xRK…h§²¨¾¾´¸»°·º¯ÈŸÆÂ±¯´Ÿž©•\|a/Z;2\=/\=5_B.]=6dCInTj€oz…”‹›£ž¯°°›Ÿ¥p|†eu€jz‡`u…[u†`yŒn…•yš€” ˆ˜£“¨Ÿ©³™¥±š§Š—¤‚’¡|Ž|Žžvˆšn€•MYo#%/,0@Uc}fxŒm’m€•u‰xŒzž…—§¡¯…–¥}Ÿ}–¥‚šª™©v¢d‚™\y‘[x‹^xŒm†™ƒš«¢±§¶Ã½ÈÔ±¼Ç£®¹Š’ˆŽu‚…g}z‚—…£˜G”x-‘m˜mi ¥n©uƒÈ§íëëòðñðððïïïïì²&fJ\:c=jAk@jA$^<^?gI^>S3R3Y7U1L(F&>">!E%[8wP!yMxIuCH…_mgRqP¯¯Íı›~&e77tMŠ¡ˆ§­Ÿ¢©ž¥ª  kuŸŒ¥³§´¸®·º­ÌʼÖÑÃÖÑÅ¡©–-[5'V7AfMJlSFlTNpVJmT]{ho…wu†~‹™“¢¨¨ž£¦zƒŒan|_p}gzˆk‘l„”qˆ˜vŒ›}’Ÿ“ ƒ“Ÿ™£¯ ¬¶’žª„ž~œz‰˜ŸxŒh~“M_y'.;!$'!$*.8JSjf–q‹žp‡™q‰›wž|’£„™«‹¢±‡›«€•¦…­€™«v¦n‹ m‰žrŒŸnˆœ^zd~“„š«£µŸ±À³¾Ëš¦s€Šl{„NfdRtgk—†A’u'Ži”kk £m"¨x8­~¾ÙÈñîððïððððñðñÜÞßT„p[9^;b=gAh>k@=pM(cFgI^@S5S5R0I%F%C&<"?!C$U2mB!rGn@k>l‹mdx\3Z9“›ˆ›¢‹NsOX1\0/sJw‘}˜£™§­¢³µªµ¶ª©²¤™¬œ—«œ©´¦ÊǺ»Áª‹ªŒR|^N(M'Q.-\>DkQa~in†si€qkƒy}‹•Ÿž–›€Šp{†v‚Žzˆ“v‡”x‹˜|Žœ‘Ÿ€“ ~’Ÿ’ž“ž¨ ª´‰–£x…‘xƒ‘Ž›‰—¥£¯f}:Ih$=(),;%(4&'3QE`xd€”m…–auˆcy‹m…–}”¤ˆ ¯‹£´|’¤~–¦›«{–¨w“§s¥oŒ¡r¢qˆ›s‰›qˆšyŒž„–§›ª¹ªoƒŒHgf9fV=€g1l ‘j•hœl§w0®…¤ql»“æçåðïïïðððððóñó·ÄÂ'gI^<_;b>e? a7*uKž­"aBcE\>R3O/G&E$F&@#;!?!C$R.c8l@f9AvR“—†WnPH(BiK?jG"V2T-]0_0DvVŒœ¤¬¡¯³©¸º®¼½²¸º®¢¯Ÿ”©˜°¹©¤°œV†n)bEO(O+O+S/'\8:iKSw`h„uo†|r‡€Œ™™ƒŠyƒŠ‚Œ•Œ–zŒ˜~›‚’ž†—£ˆ™¥Š›§‰œ¨‹œ§•¥®¡®¸š¨±š¥y†”o~‹’¢¯Sby$):$!#/"&; $5%+(3MZuˆqŠši€‘l‚“o„”w‹›˜§Ž§µ‹Ÿ­~•¦ƒ­‚®~š­y–ªt‘¦m‹¡m‰žd—i„™p‡›{¢›¬½ ­VpsDi_?|e5n)‘n&k)œs%¨z+­€ ¤o<®{ÈÚÍñíïïïîñññòòñòïò—¯¨`@_>_<`?`<;tQŒ¥ŽÙ×Í[>aCX:O1F(@"E$D%<"=!?"F'X3d9h>k@?xUXvZ(N.?"F(!R1Q/P,Z/]-/jD”†£« ®²§¶¹¬¹¼¯º»°·¸¬­´¥·»¬•¢?q`$bGQ,O+Q.'Z5/b>/a=*];^;`B)qSŸ¶¤ôèèøôõ[>bFV9J,?#="C%A%;!="D%O.]5b9e=lD!lBX0E%=">$K,M,L)Q,T*'`5bB>gKKo[\xhn‚v‹˜”Ž’•nv~\itUeuQbqXivgx…jz‡eu„`rYjwUeqYly_s€_r€csƒ`p€`pix…‰š¦ˆšªm~W`pPU_HOYBHS>EOBKVLZhXoƒrŽ tŽ _t„KZhBO\O_ldy…qœp’¤®ˆ¤´ˆ£³†¡±š­u‘¤tŽ¡~™«ˆ¡´¥¶…™«€¡œª·¨±ºŒœ l‰„P€oE…l@s?d,yV•c=¬y®Ðºêçèíëíîíîïïïñññóóóìêìr–‡^>`>\9 nKŠbi²îêæú÷øZ>bFU6I+=!>$A'>$="?"J(T.Y1[4^6d;lDf;U.A#?!D$G&H&J(K(&U4k…q¦›­±¦µ¸«º»¯¹º®¶¸«¯µ§–€#Y4 L-hL-‚d&yU&hE)fF*gH8mTAp\dxƒ’–šz‚ˆq{‚hqzU`lJVdCO]M\jZkwQ^iDO[>HR9ENIYeTguSgvWkzcs‚_o}]noƒ”p|‰\jz]jzWam]isS`mUdqTcoO_q`v‰oˆ™s‹œf~Ul~J_pG\nJbtMhzTpƒa|Œn‰™~—§…¬…­}•§uŽ l‡šZx_}’e~’v‹”¦¶§³¿|“”X}tW}oUƒrAƒi)iJ'h?h§€¿ÔÄêèéìëëìììîîîðððòòòòòòîìî}œ`@^?\9tLa/›kÃÓÄ÷ôòV=^BT5I*>"B'?%=#?#C$O*U,T,S.Z2^3g@nEf=S/K(I%I'G&F$I'%P0a{g˜¡—«°¥´·«º¼¯¹»®¶¹­£ª›FpO T,kK1‹l?¤‡/soPgL)nQ5x\Cu]d~o™•Œ“hqyt€‡„”}†vˆcnxZhuar€YgsIUaGR\ER[O\gP^hLYcR\hco}w…“grHTdXboLVcSbq]jxftao^o}S`kM]lJZjJXeNap?RbJ\lN_nRfuOctG^pF]n=O^;KY@Q_HZiVj{byŠbz‹^s„Wl~Xk~btƒ“ “£±¢±½‰žlŒ„^‡zJi;sX0dEz˜{ØÛÕìéëëêëéééëëëïïïòòòóóóñðñìè퇡˜!bD^=[9sJŽ`,•kµ™ñòì!V>V=O4F+A&B)?&@$C%H(T+X/ T1!Q/Z3`3b8lF*pJ'f?W0O(M(G&D#I'#P1Rt_’ž“ª®£³·«º¼®º»¯¹º®– 5tMzS2—t<«Œ?©-…hgI%gP5q\DxfQwgpy˜™—ƒ†MX_]iq†“Ž•›ƒŒ”w€ˆjw]lvMYfER_>IUES]S`kP[gXcnnxƒ‡’œ– ªŠ’žMWdQ\jam|Yeudq}rŽfsƒkz‡[itVdnHR^IWc4AMDP[tƒjx„R`lEQ_;KY>NZ:FQ8BJ;FN=JTIUbR`nL]lHXhXkycr€u…”ЬŒ­”¥´£«sŒk‘‡dŠ~Hr`jˆqÏÒÍîìíëëìëëëêêêêéêëëìçèêâäåÛÜÜÔÕÕƒž“#cE^<\:vL'“hC›|q°”ñóí0\@P9D0C+ D*B)A&C&F&O*W.\4#W3 K,W3d8b7f=0qK+nE[1U-Q*I%D"I&Q19lP‰™Œ¦­¡±´©º»®¼¼°®´¦p›€.Œh-šx6¦‡6¥ˆ+•w#tTeGcG-pXDyeRsfs€}ˆhqxPYaVcjv€ˆz…Œfq{s}†y…fuWdpHVaFS]Xfrs}ˆw…‘s„‘ov…’}Š–~Š˜YbqNUb|…“w‘nu€vŠp|‰eq{`irfr}hs€KXh1fH'jO9t_P€mq‰|•˜˜…‡Œflr]enHR[^irq|…gpyr{…sŠ_lwZgsXdpp|…‰”‹˜\hvBM[=HUEQaWfxTcvKSeV[j–¢–¢}z€Šs}‰dnxjuwƒŽ{†‘NZh6@OXixo‹n~Œj}‹p‚‘t…“esP^k=M[;M[FXfHYhResr‡—~‘¡|Ÿ‡™¦‡˜§y‹š]m~Vhy}ˆž£i‡ƒLvlD|l…­¢ÆÎÍÉÎÍÇÊÈÏÐϸ¿¾ÊÃèççìêìÞßàÞâáñí𤷳$eHZ:b=3ŒiK¡†R¤zµœñïè}\IK¥‰T§‰º¤ÄÉÁ=dE;dB'V5F,O2Z6R/O*S+U,Y1#a:&d;"W2N/6kKW}ab~b>iGP{]et.}W1uM]0 Y-f8^5K&-]=ˆ˜‹©®¢c”v"‰b‘j“k”j”hŽa yMd;‡˜«µ›w {CƒcFzcz†³°°ª¨©†Œkt}[el@HNIQZnw‚Š’–˜ŸŠ“›–ž¦–¥FMW!598:=<'-.+68#'&:{Rh=W1M*O+Qw\…žŒ\”r3Ša ˆ\‰^Œ^ƒWoFV,MvUÌÅ·ã×̳»©U„fFu_p‰¶µ´¼¸¸’—›ny‚]em:AH,2::DNLVaalvx‚‹Ž–žž¦«w}†00512//68(++-45177Z^g–›¦—ž¨Œ–¡†›s€[m}q~‹y†‘~‹–Š•Ÿ€‹—:@K"!+36 $' "$)+ #*LWe–£¬‘ž¨yˆ”aq}]n{}š¨…” hx…CQ`FUcjz‡€ŸŠ›«§²À}ŸŸJ–ƒ:£„{¶ ²À¼©»´°Ã¹­Ä¶ÁÏÃçèæñññôôôðïñÛáàééê­º¶x˜{ÅÊÀm°ž?¡„L¥‹Œ¿¦áÞÙI†n;aC@dE8aBLmSMoW \;V3T/S,V-!\4'a9$a90g@FtP'Y<X9W2T/R,T.#\6&a9]4HrRƒzCtP'hC]5]6 c@iIoL}b+x^$Y4K)G)!H+&O.$P-GkP¥ªŸÁ¾´´³¨i„hW2W4,eC›£°°¢y’y—£• BtR=oVc‚w¨§¥°¬¬¦¨«’–Ÿ‚‡z}‚Z^dDHO03:'*-'+.?DKbiw:?N"[TOPLG887 !')#&PYdƒŽš– ‹’ž™q€Œ^lyQ`n`p|p€r‚€Œ—‡“žw„’5=J!%'017?>@IF%(*Xdnš§³ˆ”¡x…cp{ER_0&W8U3W/U.R,S."Z5!]5Z0a|a‚y.iC$fB]6W1Q/aFtWmNU1K&H(D'"J,'Q0&R/'U1wŽ{º»±·¸¬œ‰]~a0gD*c@ˆ˜ˆ°¯£[}_:tSI|XmTHoa›žºµ¶°®± ¥•š¡Ÿ¥™› Š“z}‚wzty}|„swFJT$&. ")*+.$'+$)$(0EMXt~‰–ˆ›‡’y†’ix„WfrQ`m\juiz†q‚€Žš„‘œ{‹˜\iy)/;&,#&!()3>>=CA"$:CNp}‹Van5?H(19$+2'.6-5G,19(.6(+3)-7=CNis~pw‚V]eKSZWak`lvlw…“ ˜§µ”¤³Ÿ¯ ¯¼¹ÃлÂ΀¨£A–{4il¨ƒÆÕÉêèêêêêìííðïïòññèåèzœ”%bQ)hR!qO!wTwQJlª‹ËÖÆùõõüûüÚÝÜ/tZCeN7aE2a?,`A.^D#Y5X0T-P+S.:fAdb~š§¯[^[3`=\7T/F)L2[<Q+N)M)J%K(#Q.&T1&S/N*6`AŠ˜ŒŒœ‘u‹}Oz_5qRS0T1uymŠm9sJ9sK8oH?rP@uXcs¥¢£«§©¦¤§›£¦¨­±±¶µ¶º³´¸®¯´¨ª±¦¨­¤¥ª¤§­¦¨® ¢§™›£Ž’š†Ž—y…KT`]dpƒ–…’ŸŒ˜x†‘ixƒM\g@NZRcmgwƒpƒz›~‘Ÿw‡“_o}^n|ozƒry‚y†}‚ŠŠ‘‘š¡œ£«¤®›¤¯©²Ÿ«³žª´Ÿ¬¸¬·Â²¾Êª¸Ç—ª¹•¦µ¤³À°½ÊÀÈÓ‰©¦;Œnb¦ƒÈÕËèæèéééêêêíííïïïõóôÑÙØ?…hjH*gS*hU%rVwR‡°–÷íëùö÷÷÷÷øööæää‘­œ4]F'W6(Z5+]:3aH+bGHSR]e@JS+6>CNYN\fR_iv„œ£…—W^e5gI7`?/];)\84b@jˆo´»­ÓÏ´· …”xJuQc9d;,jD2iE_8_8_<X2Q.S1Q,N)M'J%H$M+%Q/#P/L)M*{Ž{»»± ©™Pz[GsXGrV(_>&^=/fCV€bMzX8lG:lHCpQ†—ÅÄÇ¡§¯p{‹Zdx=Fc@Lgnw‰‡Œ˜‹š‘•“–’”š”™”–œ‹”‘•›¤¦«œž¤„ˆŽfkrFLTot{¤¨¬‘–™]dm6=DHRY:DL%-34™u)§s„ȦâääëêëëëëìììïïïòòòîîïØÛÓíìé÷óöÞâä­Â»~§–d™ƒ—¸¦ñììÓÕÕ—«¢’§xƒSt]@fI7`@'Y51bA{Žz°´¤º¿¯ÃƵËɹÁ»«€—zrDuI?€^DxX `:_:`=X4S/U2Q,O)M(K'I' N-$P/"O-K)Q-WŠn£²¤¯°¤k…lOz^LsY)]=$Z9&_;7oJ?tO:nH8lF9lI{’…ÇÄÈ£¦°br‰6Em#*U!'L8@[mtƒ‹’›Ž”“œ•›”šŽ‘˜‹”–œ—›¢•—‚‡ŒfovRY`x}…˜œ¢ƒ‡ŒBHOD7BJ“‹–›Xah?HPcmvw€‡ˆ‘—’œ£€ˆ‘{†ŽƒŽ•‡’™†’Œ™£›§²Ÿ¬¹¦´Â²Áά»Ë•¦¸~Ž _pƒas…~Ÿ¦³¿ƒ²§W³‹¸ÔÄêèéëëëëëëìììïïïòòòõôõøó÷àãæš·¯K‰r$qQiHh@²–íåãÒÒÌ»Á·—©œh†sImRAhK6`A$T36bEŽœ¸½°ÈȺÂű½¿­¶´§‹Ÿ†(xIrGvN"rIc<`;b>[7T.V1Q,O)M(K'J( O-$Q."P-L+T-$yR_˜{—¨˜n‰q@yZOzcDoR)];\64pIDuR;mI3hB7jH„—‹ÉÄǨª³dtŽ;Kt,6b=A`egw†‰“˜ž¦•œ£•ž‹’šŠ’™Š•’˜Œ‘˜’–”›†hpx]enu|†‡Œ•djr16;;?CGPW7>D"%'#&P[aIQW+38o}„”anvHS]cnwy„ŒyƒŠƒŽ–ƒŒ•z„yƒŽ€Š“€‹–š†”¢ˆ˜§’¡±‰›°nšN^=KnJ\uexŠŠŸ®·ÄÒ¸¯v¶˜ÕÞØíëìëìëìììíííðððõóôáäå ¼µMŠulJgCjGfAL‡aÖØÎìçæèäáåàÞÌÌŨ° €’y4bF/X;'Q2*Z:Pza^‰p¯ž½Á²Š¦‹]oU†h'sJoGqGqFh?b< d>^9U0V0Q,O*M)K%I&M,#P.!Q.L([3rG"{RMŒmOƒe>xY]„lb…l,^;]3-qE=vL=oI6iC4kEnŒy·¶»±±¸‰‘ Wf‚IRq€€­«°««°¢¤¬™œ¤•Ÿ•žˆ˜‰’‡Ž—’™”š‡”~…Žov~_hrhqzov}Kn(.]&/b9Jwbw”–«»ÀÍÛ£ÀºžÃªâäâìììëëëíííîîîëëëËÕÓ^–„oOiElGkEiAC‚Y½ÇµîèéëèéìèèíèçíçèêääâÚÖ&Z<'W8&X8'a="fA_7.rPJ†f-~TvKoGi@nCrGtJ!oF!e=!fAb=W0[3[1R+ S0L'H&L,!P.N+#S,%k@tHsGvK(wQG|_d‡pT|aBjGuŠmqlW}]MuV:kFW}]•¢– ¤¬“™©€†šjpˆgk€uz‹”• ¯¬±µ´¸©¬²Ÿ£¬”š£‰˜‚Š“”›—ž‰–‡Ž•}ƒ‹sz\dnX`jU\c;AFJNRNRU7=AISY5 g@dAZ0Q„]q‘j5c:(^<Q-H'K)M+)S1k€f{•{?UuGtG(vPHwZIoR-`?Sz`ž£—”™ŠŠ“‘—‡wŒs£¬ º¼Ãx‡œgrŒqwŽlq‡fj‚gk}€’Ž‘Ÿ’–¢›œ¦ £¬™Ÿ¦”›¢–£‘˜ †•”›Œ‘˜„Š{‚ˆYahJPYHNSDKOfkp[_dAFKJRYFNSAJMLTYemuiotAFL7?GZgqP\h`mws†z…ŒuŠt‹x„y‡’€—Žš‡•¡’ª• ¬‡‘¢xƒ—kwŽHSx-=q=T…\|£ž³ÈÇÐÛÍÓÖæçæêêêêêêëëëìììïïïòòòàáàÊÑȳò¢¸¡´Å²ÔÖËëåãïêêëèçëèçìèçëççëçåëçæêääçàß%O2!\9%qI$pHe>c<b:oG0„`4ˆc4ˆcIi|ž~‡ž~Yc@…WT†]>sKa=CuP¾½©ÔË·‰–t;lK%Z6K(I(I&>hI §œ¼¹­›¦h‘m=€V4sO;fI<`AUrW}«­œ¾º¨ÏƶÒÈ· ¦Ž¦¯¥™¡°Vc†S\Xa~V^{TZ{SXycf€mr…{~”Ÿ˜¤¤©š¢§—Ÿ¥‹’™Ž•›“™ “š‰•}ƒˆ[biJRZKPVBGLuy~jpu`gmS]eP[dZagU]fkv~‡˜ls{>FKV`j_mwp{…zƒŠ|†r†s‰t€Šy†’„œŒ—¢Š—¤“ª¥±”›ªs}”huS_€GT}Uiw‹¦­¿ÆÏØÙÜÝèççéééëëêëëëíííñðñÞàßÙßÙõóô÷ôööòôøõ÷òðòîêëìèèëçæìèæìèçìèçìççìçæêäãèàÞKjQ>oO,sKlDf=g< e;%vMJiEŽgR‘mީޯÀ°Íij¼º¤´¸ŸÇ­¨¬‘_…a£¬•àÔÈâ×ÉÐÆ²ƒ”w6eCK(,T11_;'iBx˜„¹º¯Â¾²°±¤xx?kJVrQ›…Ⱦ®ÒȸÓ˹ÚÐÁÛÒÁÕ̹©¬”ª±­‡œlowzmr‰mpŠptswrx‹tyŒs{€†•‰›–Ÿ¦¥ª•œ¢’˜Ÿ–£‘˜Ÿ’˜ŸŽ‘˜|‡\biBIOV[bINQkrxpwlu{\ckAKT`lw>GOhqz~‡‘„•QYcIT]fr{uŒƒŽ–†™xƒz†ŽŒ”†‘š™£˜¢«˜¥w‚”„¢’™ª†¡u•u}”y—€‰¢†“ª’¡µ°¼ÉÞááèççìêìíêíîëíñíðÐ×Õ·É»éëèöööóòóóóóóóóïîîíééíéèìèçìèçìéèíèçíéèíèçìåâëâßyŒ|L`$sJi@h>h=kA~ ‚·À¦°”¬³žÇÁ²ÏÈ·ÐȸÓʺØÎÀßÔÆÚÏ¿Á¿ªÖϾàÖÇàÕÇâ×ÈÔË·šzf~X¢£‰y’v_4/rP†Œ¯°©’dƒkp‰m·´ÝÑÁàÕÅÍȶª´›¹»¨ÒÊ»ÓɶÀ¼­§ª³Š‹ ””¥©œ«“”¤‚‡z‚—t|mu‰lt‡rx‰~„’‰’žŒ–Ÿ˜¡•œ¢—£Œ“›‰’™‘—~…Œ]clCIP^djadhbioenw]iq^em?FN`kv.28JT]z†‡—[bkOV`Zfp~Š“‹˜¤Ž™£†‘›ƒ—˜¡”Ÿ¦•¢©™¤®§°‹’¡v€•t~•lv’jt‘w™}‡Ÿ‰¡xƒ¢u‡©ƒ™¶ÁÌÖÞàà¿ÍÊžº°š¸¬”³¨m‚Ì×Ëù÷øõõõòòòóóóóóóñððñîíñíìñîìòïíòïîóðïóñðôñðôïíôðímŠx@[pGi@j? g;+vQÂǵïâÕÓÌ»ÊöÉòÅÀ­ËóÑȸÖͽÜÒÃÙÐÁÏ˹ÝÒÅàÕÆáÖÇâØÉåÙËÎȵ¿½©Ôʾ‰žˆ"_B\C7oZQ|mQybuzµ¸¦ÛÐÀÞÓÁÙϽ©²™I‰]O‹eŒ¤‰»º§ÊÄ¿™š©‚†œŽ¢¢””¦“•¦ˆ ˆ›z€•v}{€‡•z‚‡‘ƒŒ”Œ–œ¤ª›£¨”›¡‡——ž}…\ci9@GlqwvzhntemwT^gIRZOV_LV^/4:5>Gz‡‘‘š¡fnwHR^bnwŒ™£›§¦”Ÿ§›¤• ¨—£«‹–£Š”¡Ž—£Š’¡{…™r}–kx”gs’]eV`ŠXe‹WcQ`–XoŸœ¯Ä´ÅÃA‚d qK!qKlCfšsõòïùøùööööööööööööø÷øùøøùùøùùùúúúúúúúúúúúúúúûúúûúûûG}a/zToDmAk? f:C~^ËË¿ãÚÍ©±œ—¢Žµ³ Ã½ªÍÅ´ÑȸÕ̽ÙÐÁÔ̽¼¾ªÅ²ÓʺÒÉ»ÌÅ·Îŵÿ«·¶¢À»ª†–&_DY=bCkI/rQ–„ÿ¯ÚϾÜѾËűo–ouBr?"sD„ ‰ÈÃÅ•–¦–•¦›ª  «¤£°¢£°¢£®™¨“™¥‰ž~†•uŽyŽŒ”›Š’™Š“™‚Ž˜–¡©˜ §…–‚‹”y‚‹X_h6;@ejq{€‡otzahsQZcMU]QZdRY`:AIMU]t}ˆ‘œ¨gp|@IUq}ˆ¨‡”Ÿš¦°Ÿ¬¶¤®·œ¦°’œ¦‚‹–†™†š|ƒ•|„™t—q}—sœvŸr|œs}p|œft]kˆ›·£¹¹E~a%rKmEp?¸Èªÿüþúùúùùùúúúùùùùùùüüüüüüüüüûûûûûûûûûûûûüüüûûûûûûûûû.rNvMpDl@g< ]4.kJr’}dŠk8lFxs¿·¦ÏIJÍIJ»¹§·¸¥ÅÁ­Ç®Á½§ÈÁ¬ÐƳº¶¢¶²ŸÎðÚ̺àÑÀâÔŬ°˜-g=W.^6h?i>I}_³³¢ÜоÓÉ´Ÿª8€RtAq=m;‹¦•·³½}‚™ŠŽ£©§²¯¬¶¬«·¦¨³¡®—œ©“™¥‹’ž€ˆ–|…‘Œ– ¡ª²™¢©s|„^hr˜˜¤…˜|„Žt|†LU`9?Fcjqz‰|‚‰fmvT]d[clBKVLU`JR\nx€~ˆ‰’LTa?KXn|ˆ‘§…œŸ¬¹­¹Ä±¼È‘œ©Œ–‹’™ˆŽ—}‡”z‚“y‚–‰ž„¢‚¥€§…‘«™°š£¸“ ·‰–³–¢º°¾Â@|a)vK?€P”°ƒ÷ôìüüýúúúúúúûûûúúúúúúüüüûûûûûûûûûûûûûûûûûûüüüûûûûûûûûû&uN"wMj?_6[2]0[.!`2@oAn…d´¯Ñųͱ½¹¥²´Ã¿©ÖÊ·ÚÍ»ÞϾáÒÁÜоÉįÛνçØÇèÙÇéÙÇæØÈÅÁ¯Y[Y.Y3`9g?h?|–}Ú̺Áº¡^‡bsDtAn<#rE—«ŸŽ£mtv~—ˆŽ¤§¦´§§³Ÿ¢°”™¨‰¡„Œž‰‘Ÿ–Ÿ«™¥® ª³³½Æ“Ÿªmz†gs€q…’Ÿ‰“ ‚Š–ku=GSCJSqy€‹“›|‚ahrLSY]fpKT]>FQQXeu‰Š“ˆ‘œAHT09Feq~‘§“©¦±¾¬»È’ °x‚Žqy‘•œ•˜ž„—x‚‘‡šƒ Ž—©•›®–ž±”³˜°’›²˜£¹ ¬¿¥®Ä¹ÃÏ ³›¸Å¢èæÓÿúõýýþûûûúúúûûûûûûúúúúúúûûûûûûûûûûûûûûûûûûüüüûûûûûûûûûûûû:^GxY a7]2KwT¢¥ŠŸ§ˆ¢¬Íİǿ®»·©­±Ÿ¯±›Â¼¥ÓȳÝмâÓÁãÓÀãÓÀåÖÃáÓ¾ÐʲÙÒ½ä×ÇðßÎñáÐëÝÌÔ;¦Ž8nC[0[3a:f>8uR«­™¢¤ˆ2sFpBrDm>;|V¦¬¬„œ€…›’”¨•˜¬¡±¡¤²›Ÿ¯‘–¦–¤–£— «—¥°¨³¾»ÆÐŸ¬º‚ŽŸ€‹š†‘ž‚Ÿ™¥²›¨’š¦{ƒCKZaitŽ”œŠ•¢lvdmtAHQis|hq|JS^MV__jsŠ”Ÿ•œ¨SZg8@K^ju˜£ž©³ªµÃ¡®¼†’¢jv…dlv~„‹£§¬œ¡¨†Ž›€‰–Œ“¢‹“¥‹•¨”¯›£´¢©¹ª°À¬´Åž¨À„‘°¨³Äøôïÿÿÿÿÿÿüüýûûûúúúúúúûûûûûûúúúûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûû?‚b?~^$wN#zRDŠj|¥~¨p£‰p£‰Z”v<€`gjÒÆ¨ëØÂìÚÄíÝÉñâÑñäÓòäÔôèÙóæ×ãÖ¾æØ¿¿Ç©²Ã¯ÖÔÄêÜÍØÐÁÅÀ²‰™}.k?^4]5!b>"g@@vTKxS$pCrFrEoBd’{¯¯º…ž•¨ ¯ ¢²˜œ¯š¡²šŸ¯“›ª™¨Ž™¨˜¦´®¼Ç¿Ëו¡²}‰›ˆ• ‡š ›£¢¦¶µ¸«®³­¯³–—œdhq…ާª³‡’fozpx‚V]hr|‰cm|MS`W`iKVbzƒ‘’›¨mt€V`kajv„Œ˜‘œ©¨¸—¢±ˆ“¢s|Š_frdks’™£§¯”š¤Š‘œŠ‘ž”™§–«˜Ÿ®˜ °™¡´• ¹š¶Ž­wƒ£œ³çêìþÿþüüüûûûûûûúúúúúúûûûûûûúúúûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûƒ\„]W€W"ƒ`&{VwNzOxKrF1}MÍȦþîãùïåøïæøñé÷ôð÷õóû÷öýõðçÛÆËœõãÏÉÍ©=dF—uk§ˆyªˆ«•‹¤ŽRƒ`i<d9*eA'gCe<d; oDqGoDrGˆ¥—ª«º…Œ¤•™® ¢µ£¥¶šŸ°Š‘¦†Ž¡}†šv‚”Œ˜¨±¾Ë³¾Í~Š›i{ŠX}}`†~6sZHy`~•‡¡š™©¨™©¦‹›–s~|†“®°¸™›¤~‚‡‘uy„px‡ZcqU\iahthp|„˜„Œ—w}‰^ivhr|…˜˜¡‹˜ Œ¤†’œ…Ž–{Šwx…’”™ª­´–¡†Ž›”™¨•›«‘˜«™­Œ–®…‘®Ž­†‘®…¬Žš²ÓØÞþþýüüüûûûûûûúúúúúúûûûûûûûûûûûûüüüûûûûûûûûûûûûûûûûûûûûûûûûûûûûûû„Z†_‚WU‚Z$yR0mE.nG*rK%sI™©‡ÿíÞúñèöìáôêÝöíâúôðóîçÚ×Ū³‘¾ºíãÌú÷÷óêØv¡m‚Xˆ_"Œb)Žg3‘l5g(Y*xP9qM$fBe@f@lCpFoC(vNŸ¯¨œŸ´}ˆ¤—¯Ÿ¢µ›¡±‘—©Ž”¦Š”¥‚ŽŸ•¡®·ÃΟ«¸d|…LpnIxn7hE^cŠ›“Ÿƒ›Žšœ‚¦Š²²‰¥©v¬°‚òèÚûûý÷øúú÷öæÝÀt k"„W ‰`#‹c"f%i)j*‹d7€\&nFeAkF qK#tOpJIe¸¼½˜œ±‹‘¨š± ²¢¦µ•¬†‘£†‘¢¢¬»¶ÄÑ„œ¥Rvs,hP6sZ7rW;oW!_=e<9|ZB…bWŠnVŠl`”q€—|l~p_tnl‚}†”’†‘tƒ|‡s{…mw|kz…‘z„…˜—ª¬®£¢šœ‰\ŒvNŒuW{WŒyJ‡o9w_8^O$J5+S??gWr„ƒxz—•›¬¬³“—¢…‹š—§“›®‘™¬Š•¬‹š±’Ÿ¶•¡¹‹–³¤¯Âñòóþþýûûûûûûúúúúúúûûûûûûûûûüüüüüüûûûûûûûûûûûûüüüûûûûûûûûûûûûûûûƒ\‚Y€T~S~UzN,€SN}T2c:4e@gHŹ–ýíßøêÜÿðåøÞLj¨„Ca$U6M-*W8-Y9*X6'Y39qM0zZrJ~U2Šj‹¤®ª´“¡ƒ“œ«œ¢²œ¤¶˜¢¸—¢·£¬Ááäéþýüûûûûûûúúúúúúúúúûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûûž¥›ž¥›£¨ž¨ªŸª­ Ï̼éàÎÝÙÈèâÖæÞÈäÕ¼¸¸•Ž˜iÞΫûôïôõöööö÷÷÷øøøøøøøøøøøøøøøööö÷÷÷÷÷÷óëáÞÓÁÔȺ¢§•CxT@wYd†q[…k;|Z0wT-tNg@f@$fAkƒtÈÇÉÄÄɱ·¿ª³¾¹ÁÍÁÌÙ‚ž¦/n[gBd<0jHDyTPX2lD,pN$qK'vO#tL‘¤{ýäÒïßÈõçÔûûþüù÷Ъoz`a}Zr—{’°¡œ·°d‹sƒœƒ™¨–Rw]?hL1aDQ3=fEÇ»›ðÞÉëÖÁǦ…°‹=›t%nJM-%U1)Z6(Y5(X4(^7)wO$}WrHtF}R/ƒa„Ÿ—¡¢­‚‹™~‰™•¬¤ª¸œ£³š¯ ª¾ÚÞäýýüüüüúúúúúúúúúúúúûûûûûûûûûüüüüüüûûûüüüûûûüüüûûûûûûûûûûûûûûûŸ¦œž¥›¡¨§ªž¦«žËǸéÝÏÕÒÂÎ˽¦±•‡—oª¨yÞάûñèöõõôôóöööøøøøøøøøøøøøøøøøøø÷÷÷øøø÷÷÷òéßÝÓÀÒȹ˜£Ž?vQc;c<5sR/tQ*sN4yU$jC]8X69_H’ž µ»Ä¨³¾§µÅ’¢°Xus(ZDc>e?(fD:|`e’€w| nImH-vR6}T'`:-T;3VD"L2'Q1'T1)T3$N0)N+ĸ—öÛ¿v†W!Z38jNwŒp£œGmE c;,rQKƒm8sR]:4dA¯©†Ò¾£—ƒ`xbg>7€Z‹²¦ ¾³ˆ¨—]€eAjJKtT>xU$oI$tJ*…^-žt*­&²€&³ƒ'¦y$}U)^9.];)Y6%V0%R,/W7;lN7…_1Œa.‹`*ˆ_R€Q…V€Qg¨…ñòòûúùâÙÖ²§¥‹Ž–• ­¹ÃÍìëìûûúûûûûûûûûûùùùûûûüüüûûûüüüûûûüüüûûûûûûûûûüüüüüüüüüûûûûûûûûû¢« ¥«¡¦¬¡©­ ¤©ª°¢¨´œWe¥ƒôéÞ÷÷öõöôõõôôôôõôóõôóõöõøøøøøøøøøøøøøøø÷÷÷ööö÷÷ø÷õóîäÖÙоƾ®h„c_2!d; b<Z2]3iDnI+sProHgE%N2E%E&!M,'T0'Q1 I*#K(¶¶™ÿíÛ‘—i']9,a@1c??jF2_:3fC/oK-qO#f=Z/SvN˹§¦Šˆzc‚ek;%zO{ª›Š®¢j’~Ov\n†\³«u‹_sF%`)¥w+²'´„"²€(ªx+’b'oE/c?0^<(W5*U28^@Oo[@}^-‰_:d5‘d1f‰^ˆZŠ\†Wd¬‰ïðïüûüÿÿÿû÷óÔÉÃ¥—‘¥›˜ðêåýýþûûûûûûúúúùùùûûûûûûüüüüüüüüüûûûüüüüüüüüüûûûûûûûûûûûûüüüûûû©®§¨®¥­±§°²¨˜¤–k‘w<‚X)zK¢·÷îæööôõöôõõôôõôõõôôôòõöô÷÷÷øøøøøøøøøøøø÷÷÷öööö÷÷öôòîãÕÔ̸º·£pŠi]1_6b;\4Y0_8 lI"pLDsS.T4F%E"F&"M,&R1$N/ I)E%h†eæÐ¶Œ“p%]7"Z4([62c@7dB9kH4qN$iC `:&\86lFOZ;rR[c7zP l9!yJlž‹i”‚P|`‘nÝ˪ÿâΛ­†`$¨w'²'¶…5µ…ƒÃ’¸Ì ¾¾“}Žc1hH*]<*P36U?MiZXxi2]0ŽbL—m?—j4–j%ŽdŠ_aŽaV­‡çîêýüýüüüýþþÿÿÿùóîáÔÊïæáûüüûûûûûûúúúùùùûûûüüüüüüûûûüüüûûûûûûüüüüüüûûûûûûûûûûûûûûûûûû­°©­°ª¨®¦”¤–`Œn*xKtAZeÇɹöïçöõóõöõõõôõõôõôôôôóõõõ÷÷÷øøøøøøøøøøøø÷÷÷öööö÷÷öôñîâÓ¾º¦¨©”‰—z^1\2^6^7Y0Y0e?mH[4H$F#D#E#!M,'R0"L-G(F'3eAjŠgEmJY2$]7#X2.^<9eF7iH/oL!e?!a;(fB#hBa7 f=*qIp@ m:%zLd’}N}cTyXš ‚Ĥ²¸œU•m—i"¦w(­~'¦z…·‰ûëÖÿøõÿõîÎÀ9hG$[@)P74ZEFn]F{f-‚\E’ia yKœq9˜n)f‹ac•gB©Ùèáÿüýüüüüüüüüüýýþýýþ÷õôùùùûûûûûûúúúùùùûûûüüüüüüüüüûûûüüüüüüüüüüüüüüüüüüûûûûûûûûûûûû•¦šœŠau?[&wH3}L†£zÊÇ®àÙÍòìäöõòõõõõõôõôôõôóôôóôõô÷÷÷÷÷÷øøøøøøøøø÷÷÷ööööö÷öóïíáѰ®•“›ƒ¥¦-e9Z0\3^6\3X/[3d@\8I%E"B"B""M,'Q0"K+E(F'\4^5Y/"\4,b=$[51b<@iG:jJ-kI ^9 a<"gAa9^3i?pBn< n:$wMF{a>mH_TH~T'wO&qFg;j@vL,€ZD}UÌÜÿøõùúýúûüîÝÅcyPN5#M6-^F4sT7|\Fceum¤T¢w=šq+‘ic—jšn3 uËâÖÿýþüüüüüüüüüüüüüüüüüüúúúûûûüüüùùùúúúüüüûûûûûûûûûüüüûûûüüüüüüûûûüüüûûûûûûüüüüüüûûûl’wYŠhQ‰c]gn’r˜¨âÖÆïãÕãÝÏñêâöôñôõôõõôôôôõõôôôòôõô÷÷÷øøøøøøøøøøøø÷÷÷ööööö÷õòîëßÑÍ¤§–RzTY-Z1Z2[5Y0X.[1"`9L'D#C#D%$M-(Q0"K,F'K'Z0[0[0+e?@kLAkHR€]Q~\@pN,gD!V1\8`8]0d9l@m< m; o:oAd:Š™iÜÊ£~•dlBuKsGoB oB,jCx†YõãÌúúüùùùùúüýðå’“j=! ?+/\E;qUJxaazon†{iŸP¡w5šp'—m•k›pšp,›nÉàÓÿýÿüüüüüüüüüüüüüüüüüüüüüûûûûûûùùùûûûüüüüüüüüüüüüüüüüüüüüüûûûüüüûûûûûûûûûüüüüüüûûûŸ©› ©›¦­Ÿ²³§¶´©À¾´éÞÓîåØâÜÍðêàöôðõöôôõôôôôôôôõôòõõôö÷÷øøøøøøøøøøøø÷÷÷÷÷÷öö÷öñíèÞÏÚÎÀ­¯™lrP{\\.Y0]2[4Y1W.Y.gƒ[brFE"D$E%$M.(R0"K+G&S*[.[0^5'dA9iHkbe‘pG€[@pO*]:"R-!U0\3c5l>l< m8 o; n; c5X€KíàÃÿú÷Úʪ@uG V&d$”g%—k%”f~¯ƒøéÙÿùùúúûùúüþ÷ò¸¯ˆ#F#$<*;VFMi[Zthezro…|e—|Bs(¡s$¡u˜n˜m—k9¡tÙçÞÿýþüüüüüüüüüüüüüüüûûûûûûüüüúúúùùùûûûûûûüüüüüüüüüûûûüüüüüüüüüüüüüüüüüüüüüüüüûûûûûû³µ¯´µ°¶·±¼¼´ºº±¿½µåÜÐïæÙãÜÎïèÞöôðõöõõõôõõôõõôõôóõôô÷÷÷øøøøøøøøøøøøøøø÷÷÷ö÷øöòîéÞÏÝÑÄ»·£DzR#mCb6\1!pF$oE[3X.V*ŒŸyÞÄšB\+C#H'%P.)S/&M- L3W/[-a8c<$a>W2DwSM“nC€]:iJ&T2'T0+V2%[4i<m? k8m8 m9 i8FxHÛÏ­ÿûúÿüûÊÁ¦4h?$yO/‘h/–k-™m)œp4¢vv¸’ÌØ¾ùîäýùøûúüåÕºlvM:R;C[KPi][tig|ro‡}S–u2¢u%©{"¤x—l˜l”g\°‰ðòïþýýüüüüüüüüüüüüüüüüüüûûûüüüûûûúúúûûûüüüûûûüüüüüüüüüüüüüüüüüüûûûüüüüüüüüüûûûûûûûûû±´®³¶®µ·°¼¼´¼»²½¼µãÚÐðæÚãÜÎîçÝöôðõõõõöôõöôõöôõôôôôôö÷öøøøøøøùùùøøøöööõôòöòíòéßÛÒÄÆ¿´¬«œL}WnA mCd8!rH4‡a"mCY/ X*’¦ƒÿôæ´¬y+O$L*'S/)U1'S9 L?U/^0'jB'fAZ6W/!xPJ›r~—w<`>%O/,V2-V4-Y6!j@ k:j7l6 j7c7k„]øæÔþþÿðåÖfƒ[W1&mDœr6q,šl>Ÿqz¸×àÈûóðñà̼©†jr[JaRRk^]uikvh†y;—q#¨v%¬}#¦y$šn#˜m%šk¦Ð·ýùûüüüüüüüüüüüüüüüüüüüüüûûûüüüûûûúúúüüüüüüüüüûûûüüüüüüüüüüüüûûûüüüüüüüüüüüüûûûüüüûûû°´®´¶®·¸±½½´¼¼²»¼³àØÎñçÛãÝÎíæÛ÷óïõõõõöôõõôõõôõõôõõôöööøøøøøøøøøùùùö÷÷õôóöîäèÜÃÆÂ©¥§f}^ApK)qF oD lC#qH2‰a.‚Yh= \/…Ÿzþóëüð㪤r/W.)X4!X3 S=#GCP5b8,kF$b;Y2oF(‰_]¢|†’t/U1%R.+V3)R0)U1 f; j5k6j5h7 _85b>¥°öãÕ¦ª‹#Z2Y3)e:X‹ii¤‚T¤{S¦~S¨P¨D©}5«~_¼’ÓÜÂõâËãɬykJdXPk__xmc|pfƒrU—y2ª}(­~-©{-£v!—h_®ˆæëçüúûüüüüüüüüüüüüüüüüüüüüüûûûüüüúúúûûûüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüüûûûûûûûûûûûûTRUEVISION-XFILE.allegro4.4-4.4.2/addons/jpgalleg/examples/datafile.dat000066400000000000000000002204011173507505700225230ustar00rootroot00000000000000slh.ALL.propDATE4-21-2003, 20:40propNAME JPGALLEG_LOGOpropORIG4/Users/lillo/projects/jpgalleg/examples/jpgalleg.jpgJPEG±±ÿØÿàJFIFÿÛCÿÛCÿÀÚY"ÿÄ  ÿÄF!1AQaq"‘¡±ð 2ÁÑáñ#B$Rb3r%C’ S‚“ÂÒÿÄ ÿÄM!1AQaqð"‘¡±Ñ2Áá#BRñbrS$34C‚’Â%Ed“”²&DFTcsƒÿÚ ?ø?ÆÅ ˜>? aKÅÎÖÀ…([Üq`a•~sôÆØÌf3@•—õç‚ÖoáŒÆåÁ øiç|hqê6ÁŒ€ãbÇË_¿¯¦Æ„ /×ïùÆø="·áÃÑÆ`Bù ˜/·>zÚÿ¾!ÂÓÇëéþ,8:Rò(}þøV„O¸‘Ôðå‚ ž¤q½Ç\xßEØ/¨ýïJ€è6_ÏO@ ™-n~@|ß ×l"ba°ÿO–þZÛ%\<9pñðåÁÀ €ñåôÁHJ7 †ÿñð·ùëáŠØmÎáþ>ï¦Ø¢7ò½þ;…½Œb:†¡nWëk—=¼pµºuü~ìýuÁ*pH¿+ýãÊ'® ¢6ñÒápº\CN_ *P-¶ûùyï¯/¦=†Ü¯‡M5ÛÊÜ̦‘Ê:‡?¿]oèáct§ˆûÇŒ\›i~˜%N¡¯×Ym¦ …즗ù}ˆßså|>#¾¸p·-ì pš-¼útˆGP÷BÃÈ?5Û‡MõËTŠ1î˜ðwÔPGk6@øxŒ"aßA×§õ¸óÃ–Žƒ2ÓÆ' 8¶ ,¾KõóÃ’2U=ÃÀéþÒxi§pBªÇ>½8FœºZxIÀiÃÃÃúBú…ƒ/Ø<0Êb`0Æ5´ºr×{rÓ+=þ›2h8PSý%hØ-°r×AÓ¦¸‹\@üÂmʘˆüFÓ]ì º†ß§^J 'pè8q÷zuð>Æ&²¨ý¦ç—ŸfyàÝ2ˆ” VÛ‡`¿ˆ+uç‹V2+¢B–ÂîȰˆ[@¸ê"Q°\0ËmXXµ¦ž”u® ˆ}ÄâÚ&Q-„xna×ÞÃ=NV¤ÉÝÓå§1ÌÌ|¹+n¤ƒ×Q}8uçkiˆ®¡âÚ‘‚6ïD½Òæý:r.Ã{ î""ˆìœâ&¸ˆˆøùóÓ—ÔGW‰- éEιƒOí÷ËN»jæeDˆFÛtÛA·O&8æÏÊÚ_Ô<÷ µÃ;ÍDÚ8Àáþ±>W¤*|G©Â2Å€€X7ߘX?o˜ùá5Qý\¬ýþw¶ yn:}ééö ªÜ}B퇧—×\6:‹ráÂѧÓáÄ[¡ZxÓ¯õoÕ9@Ôw>í÷¾ œ„~>ŸzàùÃKó»`¡ÀF×ëk|ƒ¯Øa½ÄÇ;ñ¼üäáBLŸðŽ<¯ñÂy·-¨à€oÏï×öÓÈᵸk¨yr¿Ÿ<9.;£¦¿;xsÖÛá)lžgÂxtÁDhuðÁC[yÛŸž‚?!ýÀ©‰m®=vˆ§ÐD>,d„6åço¿lX'„›}Gøò¿\ 9Ì|>ß¾ÔÓAøÝzrÁa'AøÿA…S$#¸˜nùà!Dz_Óø¸‡Ëª™W·.œ¾‡Öp-ôú½ %‡äPÇÓ¦Ø@J6óÂdzAî±­° 量x!tæ4ŸÔtë× ¼…_ÇÇýpŽ% XÆØɈÚúù~ú|0°f‚ñërÜ×ç¨ú`"!§rÒûôýüí„nS‘À‡/µ„üíƒBÇ}?\%‰üÃÃï\g«ýÏŽˆím<~ý~XSÓP½Æ­p4‘ÆÓà~4ˆ 3Ì ý#åñÀB‡/ß×÷}Gü~ß< 6y„ØH&7@‹éÆß °ˆtcËlÜáïy…ÿoÛà ž_CûÆ8C]^ºýp ·1úà|:ˆQãÌf3ŒÆ`~¡óúë1¹Ã_0ûý±¦4D‚9àôè<3ŒÆ`Œo€,"8Ÿõøý±˜P&­>ø×ŒÆc0,f3ŒÀ-<¿Æ3ŒÆc0V3 ¤Û̯ÛãÂì_]qî0˜5Æc1›ãp ß]Ì?¼©òõòÁ&L˜ã~XðïyÿoßcP(ö¾½p Ü4\9ilãXÀÐ1¹J&ÛØG`¾ ¢Oïm~…&t·#,™ŽS¯ÛÔ`D“@5æ?Kï…‘½€PÜ~Zxõ篦›Q¾ß.–éßË„âÄCôˆü´õëýÛË?ø_zÿ˜{k$Yþ‚E¿ôüuÖÇ‘ÂEU€EùqÓòž&}q7 ´š­r‡ŸÀ4ðå¯Ä-l$aO¶·Û@¯†ßN®$ã5·NW¸‡žºxï…4#Ìíím€m÷ô¾Øqg"T¸Nš?/—ޏ!U€q:rŸ‡ ‘†‰aÌÏü}é×s¨²Y!Ô¢>ƒçÌaøßæ¬DlP¶aÔ/¥ïÐDD7½°¾„"KZä9㦗ÖÚúáê›gÖcÜ8ý¼þØHºÐ?«Âü øOêf'FT¨p¨[òµ„6Úῆ <í|=8›‚‰…°¹ìü,òÃïý(a"q¸ßÈGÎÝoõ0”C¶¦à1ŠØ ¯1¶ÿ]yé‡v¶y_òô‹G=Ýzq‹[ U\žzuðÿw¨ÄR¬#†Â¼ð‰ê°/3Â:xˆý8ZNŽé•2oû†>ƒnÓQ°‚öÚà:_jzÙ¦£œ¹yÀ™ìnQØÞ Fú‡=çÒP„xØŠ$˜(ÙÚ|D8íÄÏ`Ô/¸à 8*Œ\‰9fd„EªW(iÂ&H§â ÂèÛ_tÃlN2í›R÷OwÄ 9ÇùЯŸ{áåê×ò¾+vjÑç—f¨¥ÂS.%è""6ÚÂðo¾rÊ—US’‚\\ Ì}´ ‘@ _Äyžš ©Ï* \ÑtýPŠ7Md˜¬s”.E¢©„Á~&&Ð}à _L…¡Í#VÊ"&îà›®:Ø7 õˆ–ákÛœ¥•”oÄÌ`[t¤(pA"ØmVdªnºîðÚ:ÇIÃNb’pªª)XNcp·)þ:XÛý7Ä]LQçP²sJ¥îçE¿äk€ÜÇÓRø^ûfÅhÈ&mHûîJTÓ –Â*®pM0µÄD¡ ÞÃÌ1ןú*‹Ž‹E4“Ô“M4J[ª«·€[—@½ÊS&A¸„DDÅ=³p("B¤‹jº × ‹ÎŒÄLo ÇÂ×Öß}mŠ"â™=QR¨‰lXèÞ%®`ÿl‰¥ïL:þ’€Ÿ‡Qáá°ÃÕòá1(f bƱ²”6 ˆræa÷ÏšÀ¸båf4XeÝ2Ö‘kïÕuE}:¡EFmÜ*“Sî%5„ª¨A°Š)ˆS8ΊîPn“Õsñï0ßsˆî<Ä1Ìvx¥*!¼¿ ø p20èÅx${Ö¶ºðõ¬õ¶ "ÓÀ‚}ê…ÒÚ†½wéµí· 6Ÿµ.—°h;mk_ÓÃOö^,ë($I1…ŠB‡-ÓÇQ·L žH.†÷—K€ÿì:rçŠó3ÊKe^á´Þ8Û^º|m©Ãí5Nð‘×Ëé>6˜°ªªZk­´Ä¡,‰R"ð”/`ùˆsßQòØCãôÄÚâ#~vè~zb]FRTwcQçmG?@aé—f‡p¿ˆùðÃ1ÕÄMÌ9ÛÄ6¾·å×®— ßn{ë¸߆˜s:&÷Ð>Æûõ¿_!¸aºä@·æ:é~ƒ{òñëË~qš†’瑟aöÂ7â>c÷ù|0Œ°X~b;}ùá-aµüÇãã×^wúáAuD~b>^£þ šþ=5éðÞÿκá™Öõ¿8ýt~cŽ¥\GÃÖ‡Ö‡”7/Qñøÿ6ø` ˆˆˆýù`sû×ñû þü±¡Q9‡oñ×¥¾í„E’IµíÎxpûß僂ÄI1Ï®œ5×é‚ÂKðDuåÊ×µÇ÷ÎìGoÜ`ñ¢LNaÔÔ<¾ZøL,7‰1¿ã{úŽ»yíáõ(f…N&Løé#ÕøF·…‡/ áå§?Òí‚¶9¹óûßp<‡›Qõ¿¾w~! "r…·µ¹–æ#ë×mð¢œ)wῦ£naü‡ÃL8·“-`‚&8x|õøôÂsTüÞŒp‚?kñÄj§ÿÇâþ„aºoÈGÖãÎãÌ~8“¿(½ˆÓMw¿Ç•­`ðÆ†Š[€4ça· énXÈÔ`„“¥ ì<¹ŸCíƒãáÊúpøëÀb5ü¶ÚˆÏ^›ÞÞAó 0£‹¿ µé§ ó—–¸‘Ï6°“ö½½炊Eˆn]·ðûòõê•ÌCTráÇݴŵ¹ò¶š±1¼8q4¼knsÀŽe`ÐCO+è;ú|0œ³a-饇È:‡îƒ”^Ü¢ÑÆÚÛ ©ß#ç~<>xc* ù‡ßÞûspEBkôñçï¦îÚâ!§?ä?ψ¢¬—k¦º†áá÷§(ÍM1I"ç6ý=u/mÀE®>ž½^pp¶›h=p¢7þä #õ傦(”Fá÷÷Ë .6A:Ï[O†\=OOñ®>À?z`< ¾0[`¶ö¸ßå üG(ÐõøàéH¿Çí?,k€€ÛîØ˜ mFááûí0QIg——ß Ž_¿f3ü­nw¿ÓO®ãCì÷÷¦À¦(µ¿€<ôþ÷Ƽá÷éŒÁ© $|ùõñõc1·º|ÃùÆ¢‡Ÿñ‚·Ó;Ê´¤ó^þã€n!€Î "¸ ãLA ®!óÀH#Që׫c"æO1Ac¯ù1¦3a ÂØÌkc1˜Ìf¯Ê}qÆc1˜Ìf ÆaÁ¶= D<Ãc0ð5pB Üs&y``(Üæ8Û∈`@¸`äE„}ñ¢dZâ›LÚãŸËL{ƒ% Øü —pó® @Ì-ëpÁÈ'Ë×®!5°j#¦ØQA+xoᯟ¯¥¹à¢ k/¯Øai©x|naß–ÁôþðåLâŸÓ©õúù'Y‚LzÓÚ7µ‚Úß^w~œ¾,YˆÛMÀþâþùȰDKAóÜ~n›ï‡ìc 7iÊ׿ӧQ×PÖOCÞ”[X:X›F±qkô× õOnÍì:ø¹Î€ãf1Âk{·Ô:hß宸u4‰Ð=Ë_=5ôù_ qQ@n ‡m@§-/¸u¾ÛêuK-,SEÊ„jG+7dŠk¹j#g*·2ÂvëÇŠD” €ãa(ñ$IžÑl>_A[W@åq­©U;l6òP ´\[»ËC€¥0„$¸õ£h(ÝÍßy–ÞK=ÓaÅ-H+L•¥0 ‘¼uvÂÒ'4b :µ·¯‡Øóצ’º\¡åpùh!äŠÒŒÌ†L¿šK$cRQÚJ @1D¢ªwi9€ÄàPÀ¨Ø=û˜ ôþcš6 ¤ÕQÙܦÍ\¹U.4•r*$œû\}áAALê•Nì¡ÇtÆíYkùg™Ñåïä•4 Ô-HU[•<†”R‘-"*YqÄ¥”€¤„—Í’p¦³e«X§qäV!å6 %¥ ¨o$+Þ.7S*’‘¬bƧ qÔ}-`¿Ó^ŸxRFt¹D>øõ½º€AÃæ 0ï˜ èÄŠÉâØLPtÖú~æ9²›ˆ:Avª›§n±AÒgŽÜÊ8*꜇(…ê—Ýia×îiOI’d–Ñ<Ê¥Ë2ÊœÍMˆBêON_C(Q©qõ$4‚«­$ÚbN·*ë©èP —j*§ 7 +ZP¥¨ ” ¢5Ý×£ø‡/Aè;zmáaÝe¼9ŠÂ¦ú€tÜC]/òÓ$ùÔÞœ–=Š’Š>\q(L¯V ýÑ8Šf!‹Â"#¡‡U³@MÍK¨áʽÒ#íMÄ6±„…"¢)FüBµ®ÅÏâ"j'd+•_â”ÿéÿàúN¶›bb½†¬TÿíFGOgr8ü£–/{fFJ×øø…þžx_nѲ U2 ô¾€6ñÐy^ápé×ä<¨ç¶ÊÔ( ²‚ÝO0AXꋃ?0!ˆPÐ ÊP·^áuf½2 í г"-‡¼8~} vÆ*e*˜¤íʦ9LQ0†‚ §ñ%‘$Gü^zÿ¦°·ÿÓ¬?ûÕ¯þ™Áiüîž­5(ÑÐ 1 {€l:Êü€5Ôþ`8 °²‘gâ!L¡nð†ÖÐt^Á¿ù>"FÖ¿M§M¡mL¯!•s—QæyÄxb7Q[ 7ýOnKF½b1c²‰ƒG`Ú)ÉʼD bß¼Vî %EQðˆ #¥ƒõŽr™ÊUâ3˜†Ð9ZI€@¢âG”€`0€€ã­Çû,“ÿMªGH$´•(åBEŠ>û؃Ágí €ˆÃ`°ð˜IŽ›ÏgFå–J/Wç=[żq ²@›ÉZù’æE³f4üqD†u.ÕÖÍS¶ŽÒq.î1©¾'må»)•¹´ÓÌQd´a1«¨Zn‘µ))KåkRR¼ … ¹)P Â_¨¬¨E%+nTT¼­ÖXe qÇoqL•ØX¦+ÕW”jÎv}®ãÈÜîr«„LÿpñÏ[ƒæŠ¦Š •° µBñ/fçwIMT2uýgIQ­U£©ò4V¦ž‹‡nV\Tì’|åÞ¹[(¨6jšË™2à˜”ا9¥ÛÇ7ó*¨`2ÁÂY_—µ#CR˸Œv«º’:&At„*G$2p¯§DžÍM# €‘FÇ—zÝUÔ™í(î¤E1•x Ú³M¯,šª¹BMEˆØ æI¢ Ø‚Ìá!:DX†ˆ$[òžÝ~1¶W+^e”ìÎ?´rú“MŸfueYrQ¸Éqtô̼Ƶ ¨Kåõåd!hVââ •“vUšU!ªŒî½p (ÑS¡5U#’]|-쬙ö¡h$;q™=¢{/Éæ,{4³)„ÄU2€I¿oRʸx£tŒV Z"ÖàªÏœ ’†2mQ÷Wxå³Q‚©{EdLW/\ËÎ<]1²Ô5þ˜©];šŸPÇI^œ+ÆŒš³Rêœ^9@H¦A3 ‚™Ã•lit¢Õ“e@ +ȹ…¢ò²‰„“v¢ÅTUd²mœ¢çU3&C ˆ)ƺ©MIJ‰dÒ~á·vÒ<&è$"¤TéŠEDÆv¼eHÖfë}í Š 7xc7Q4—TL$-(¯ÆhåHOð ˆí°Šp×ðüó|¶•$©eïø†Cî%! q(J`¡¤, ‚{+ÈR’=»8+'{x¿EFç°FìÞ *á½Å™§¤iüÖ–˜¬”ªag9v³‡Åe(Õã†ÊŠ‚>ȲX˶„ÀQ*É$`â K(*Oég“N}Ž1°œî”©äL·¹„À6 9Žã¸ˆVÉ™ÊZ–‘ªg;©I@‰’‰¦’/åõi߸#†ÄV>VŒrXÔ]=T‰))«ªç»)¬µTÕ´½dÈÈ‹ÇD6q2ÝG&‘vURI˶¤—*d]ãó‰„@¾È‘\xU2/Y;%ø¨ÙÜýæ²í²È†Í¼ò’Ò3ZÕY”切“RË­¢ªBBÂëIï:Ë{Å,y—g5ôHSùUg·¡ñ§y°ÕL CjJ‹o“» (è„­D #ÈP¬iÔŒgW/ÄMp"c®›@t°{¡§êÄ!S '2—Ð=í-§K[Ÿ…ü¶Äô©Ùëwd MÞ¤q²éœ41LÀ)Àn)€¦¸9b«%ÛÊ.ûÁq°ŽâŽÜÀ4 bæÍ(i«)ÓWFãUÏ 8ÓÌ©+mhP)*L‚ gË:gœie·R¤8ƒ BÁ X‚ AŸ3Ä_œÚQ0ˆ†ûiëéà?;EÒj‚` î:ø|ÿŽ~oÉ·Çpu01Än(úèà7Úþx`º‰’t#‰Àö(óên]®£pªsl¸…(„þœœÏ˜úbKJüÀ›XóÔˆ#Õüf›]¾i×âçÏ —0ˆØ|_-¾|ôÄšjAÙÆë…õ±½ßˆoa¿ï¾˜Ôit’¿¢X.r¸ÛQۯNJœ¼É„ñ$[Ao\xpóoÇ\ã„øO|yâ!;u” <Ç[ø[@Ÿw¸`?ÊÕ6¢QZm÷aÚ×Ä´¤:)þ”€|G]om=téòOUˆö(x¼½z_ÆýpÈõ¯)<"ÖÐs›iêøZ‡Ç8ŸÛŸéå7ÄrX“àè.c{x¥Bˆ\/éüîmè‡QÚDtÔyÏÏáÓ–="Û˜_Khƒo–¢Lœ¼ïhuN|dØŽï©ñ#Êß_—<&¶.– }Gç¶úsð áÀÖ>â(n½n`ÃdBá`ý¶×À}®Á‡36ÜZ[ö妶ðò×Ä1&Ë2‚áL£]¨Iå†÷ê¢o&óèk >1„öñwµÊççÜ=/…2EÀ"à:oãk¥÷ÇLû#öjìÛ]eIšùô$˘9ÇÑp”ÓI*Ò*˜#6Ì#œ§!(jLŒÍ ù˵·\H¬Ý›…]F` (bß Vk)1‰ËŠ/ 2Þ‹«T§b"')ºuÛäØ%3qo”höI*ÉÆΈwÎæA*±p¢KZv¡”ìîq˜dËÈê«—Tgn±–P·”mL8S¸½äT’‚m0)6v¦º•Š¡X†ƒè% ijRRM½íñ;Àoi`F¸ùÞ”À5ë¦á¿Ÿ ø_˜à#E‡Ý¿¥Ã¯ Ž/âs;–³¹nÂ*˜i)\¼˜xì´»xVŒ²¥B²lØE7n³]:©žÒoJ¢‹¨Å3qȘ L Iô†U08‡˜[†ÚâÅØ\÷*ÛªE½GJå%C%]õ+ŽÔÒRáB§P„$÷a;²¹7 º¾¾2BƒKø}úáÈfF¶…K_à…°XíD/ûíðÔ~6Á ¡q"J~Z -781/‹Aê~^§Þò€)€‡OëÌA¸ˆmÓïïà gl˜t°2lÚ¬é]jÝUÕðMÌ©õ¸X…ÐãµÇLU…Uœ(±Þ(@8U[¢$G0ЦÕ`Á¸qx›¨ ÖÕÕ ­>¨@UŽQ˜ÊSÞÞr20 S”JàÜEÐD¼\'L@-OúÀU!΃S±!Ä"Ò:.̈ÅI25Tªµ°„ b*™ú ‚د»~© ×lÆR“Ÿ.¬ÌV‘ʾ¡ºfʇOá®nÍĪ5ÃæÅ6K9…I[í0ÿÒÙqQÿÏLž09cÃHG"(&ªä‚Ê®ˆ‡JuÇ (¯ Cˆ7àW‚À@kâߣڧ1™LÓG…dÚ‘š&98L™Õà*ë‰,cJU×P¾à¢%^#<Ѓ¨f}±ÂÑ ÁÁµHýú®P*’Ò"‡"Bp$C½HÊ=Ù„x©€ßg¨Dç³ û¶Èp5,ƒlB–ÀFÄXånM4¹)FÚˆØlg™iÍ¶Ë ¡ Þæ Ÿu+ 3ðć<¨ö\ªµéÖÒä@¾€Éõ¨éLDh—@ Še°¬Pø€ÿBƒûH¨¢iXƒ.›fîdŸIºPâ•‹ùk2 ˆÿ¸b”¼_˜¬÷DJk ËlY¦túÅI"—ŠÅ(ú€[{t ƒ˜øëZó¶ Õ_ „à ÅXÅ$Ù&]ÄÇÁ–t»é4 k¤AD­J+*CHLDÅ0÷oη‘vGœ¡¸C¹ƒ™FNÉ »]OPúD}%RHµ‰1ŒS;•Vm5*•ï%„ÕU,ô²¤6zC®¶¡òâqNÇÉUR©˜Š]8ä Ý?¨¥“:Q§M±ŒUPŽ•AzuDJ")èR–æÒæÃývŸp²­š¼”˜9;…LNå¬yHR¨±R2Ê$‘ ^?y6ükJb$Sq$%Ü£erá¦*8$s4[š6-ÿpÌjdN.£UR[¾OŒ‚r9­Ý¾ËÊlÕ!™?{$â}½>Ñ .”ˆ8#‰.$EÁD36ÇDSà!NP9Š›`@I Ì›‹ð˜Î·qå7…³„Ú¤‰Ö;…ãTHV2'2]ÙER¦&ᵄ {”B× Ò¤y v±¥"`ÀŽ]`Y¦U‰Ý4J•ǃs›§úÀn!|7¢Íº8!FFºl°FàcK(š ±Š €]›¼/OrXn #‡¢Ñ¹Ø«Eš3¢ØD÷ÍJÏÚ¡Í*ÅâH”}àEd×N阂p€ËXØ=±©i·ØÙÜÍÖ]JVÛˆ¦Z’´ªRHAl^s•6²…×S¥i$—‚"gÂ}Z\ ÑÐÉœ€õDT›ƒNiY™Ò¢‘IÂ-Ä„]@!8@x1tÐq¤¥Eê´yO"ñRk‘g9Ûo7Ë+2åº hU0¶ƒ1½Ý©Cue27‚TJdH%M5m%bTªZ†Ÿ îíaE3¦ðDÁƒ¡ƒá% KRÉ™6ð [w ´j±—|ñtSDɪ(÷çPEnÓ*7Pn"6½r–³–¡+–4»ÕLÎ>yšR±(ûB®jEWY²ÑýêÄHÆ;URðvƒ†À'9¸Œ+¦ËÖN¦Û®±H©•QEjé2™.‚EP)ųr,Cé¹MCDã ±gTqi69AXªàî$®ê('n:'Dx«‡ت¦$:åHÐÿöç*\ ¦&˜†P€yGf»Y]±û[•æT- 9RÍ=kAD!úw¥i˜%$ÊI¦Tæ2ßŸå¬æ™eK$¥µ8Ê£ÞC‰:Ü kn c­ðJIº!3„‹uJß&P"ÀSØDÅ>‚&လLø†Ø²4 v´ü»G,Ýh┫“°tÄ^é •#ð©î8ÿlº\PFyþ’©¨¨7νlªÌÐ1Ìf†98»²ÜxÄM~›­Çö&— c¢ÞÍ>ªâ[²ŠbæEÙ\¤±\»DL²€’dLÆYs”‚D¦UuŒT’)Žr”ÞÇåP ±œÚ©ÄSÑš4Ö½PâÜSÓ¥ ó¯<àICm6€¥¸â””¡)**HåZ°ð¨]2§ï{”!7Z–U¸”¥"J”I$I IÄ3œôEÒ'ÌEK+ET œS‹  ¼”5`ìxERSSˆ² "CÃÃÊ6nÑ1!âAÓ6ny˜³µ^i¼ÝK0Ú.lTnÖ?¹IË&í¹ö‡Má˜AÖLÈ –CÙu¸<:î ²êX|ç®0ó'RÎ_È•&¨'OÑÌ ´ËXÈ‘~àìX®Š$º‰J¼$ÕxªÀ‘’j(6F¬¥ K±}Y2§â¤ë´é*y‹7•Y¶LPnñ$UU €a܇ûaÇ¥±æ'â ·¬×µ<ÝÜ‹)¬¨§ìû&®tå –nû_ÉædˆK¯-м¶š¨¸¬¾åRýIWBì>ÅÓìÝ*kj›C¹å[I5/*ìˆP ö*u\$&¡ÔG~àÔ´†À‹™‹}“6nžHG6<7çµ"Ò±ä“ G¥"ƒy&Í„žÔÑ!“Qf-—X‡nC$LÇ9ŸÑéF¸‚ON•éfÁÊî!(ýÂi‘Êð‰È(Š-§IdqÊ¢+Ù±>·§éŠZ;7ûCÖ©ÒÔ“%–^ŸËˆ#7qSKÎ=LÀÕ«¦¾ØéI)¥ÚYpjÈbNé릌ڹ](ë-òû´ïnYô©l“Ëa£èeä£ËE7«N-œ¸©^´[òÅxNè°I3]¡L²#$í3ñc›q?Äã)z\‹' ù£¹'G.1 åEVAs4ngÊD¬áùRlðŠó¯d:e?ŸCL¬Ùõ)ôîêÓ šE5{#)/S#“bŠˆ"Î1œíÈ“Öɘꦑ{+õH—2ë Š?ÉOÿ†Ã;d!Ð©ë ‡0ê µãu¤Ú6aòntÚè,G5¼œ|)(uRI̶X ))Ýœ0·]~=¦25²ÒO3{/›Ä·n¡I—•½Jï4æ!Q6¥p‹S·4C†À%Ç‚©NØ¢RJ²dîq(ÈöG8ÚçðÔS¸ê-Ò®¡±]R@6¦ Ar¹ä•€ð§á`¡O%@Ìö×!Ê*›¥®¨qd Ô!—\£iÅ%µ†\« önû»u·TÊ[¨iÆÖ¤âgŽ’5æ61d¡8ù´ ˜ÇÆ4kQNURoŒvìÕ;I„3 T@é  TJGf’©WfXø¦2ÏÝ¢‹xØöNTqä]3¼MŠˆÈº3¶¢£ó¾w`C,¢Ü"š€ Hráà C†\U²Ž3zZ™q_2§]¸SÍSÅKRpqJ&@eJ „Sp.Ȧ„š¯ÔT¦p©ÝêÜBÿù€ŒXSm—ð5&e:U9`ó/)ò<2 ª‘€ì³m[±L‹ªqHN§ g‘P80Ã[EY—UÔP×Ò¿E[J♩¥©il¾Ã©üÈu§V… ` ‚$q'aöj™j¢™Ößaä%ÆžiAm¸… J’ H ††ã›<é·tÒ¬kÚT’MÇ¥JC× ¹1LÍò’ŒJÝ´ÀW‘Y“¤Z0zU9ÖJMŠÇA¢‚³²,˜T ¦Kûa"UxQ"‡x¸àQß{öòÄÒÃ*óã´(9q£òC+%ؾbxÊn-Ðæ<šÑÁ¥ŸÉÍ8WAÜc¢‚©xS·XJºt‹³MuQJ@9¦äW]7Ð˯å²€nñ-;w nMTÎS€ FᥱÖ_‡ »ªu×¶'2}OSweܨº¢¢ÈšÆwq3 IH Jb·ÛÌ™´¥9» s{v¤$Fü‘ 1ýGBx™&I¼Ë#D@Æ6ä1‹¹•1u·>uðÄ1I´dSÈp± P°À6¶¶æ"!Öø“f?TN':¦¸ßkõ Ä5¶ÖÄ|öa\§¸ˆî&¶·°†¾ƒ¦÷tži”ï­pIáy6ÖütÖNšâMS_”p<8Ÿ.3ÈŒF^Á x…½7ðÖá~šaªä…¸ð”}‚ûân~>wÄ ½>ÿ§qDmmüC[xòú¦+OoþØß]ÿ;ßãýEÈJŒîIðíóùóÃ’+BcÞãÂÆ5´Þ|8â$r‰†à…¬>ߥ¿›á vª˜GÝ/ñ×M6çqå§–&…iãkîi®ü[ùZÁo.»ÛT…éó É{r° Ç®–·1½õ<5?³ªÿ–x@‰ƒîùÌÅçÈÛ [¯úr$Ûä~¸‡NÉA÷~¿0þ¾˜ÔŒ”~‘Ü4µ½oo›|¤õ`L÷Dv½¯°ék‡ßL¢Å´‡kúO+ ª¼¹§»Èú®®¨ª9Åh—nÜç4ÚŒš+F«= úˆqIªy à²³¨)í‚Eœ&¢i…Ù-7Ú¿´r•õAPädÿeÞËÔŒ#äêyZ²š”ÏÜâdšŒd¤‘mOG3èxç­˜€‘—U¤{ƒEºT êDâeÓæžÙëÓ˜vŸµëBn“2Z>êNSLÆZêG#ßÒº¥ïR¬4ÄûdÙ,löV‚í?´“>ÒâßIÿÈâ@è8Ãø±fu;Ùm½—æYTysE×5$<‡{BTÕÊ.%óN©J4#¸zµ*ꚥÚìÓorÏ‹Ÿch@DACŠ0 ÄH!ÄB˜Üíž¶ƒê;_üvëŠ1Èv(ÉL¹mC@ÓñMQ˜Ï(º.ò¥iöµ´å7C¥S™6ˆ ê¡:rXï]¦áeÞ*àî ’Fdáß5é¨^â ™8¹%ÂÛ{¡Ó×qÓp¶ø—v“êÌÖ°£y,2–Ò`ÆòŒ‘ËAã†Í°«îš§h*YQsëŸÄb>{q7»¯¯Çú·ÃqxÛˆØ4½öä#õØyi‰ÔUÄl^¼¾Î××—•‡¿¸M÷ ýö bê¯Ùõ-GÜ‘<­ÀÌxùZ׌DØ®€%\¦|®<ÏÖø‰O:û»ÞÜôûÓé‚§ŠÑ·‡Êø–Æmú>£û<&áÃqÿê?¾žŸ0Ã"öYGþìÜ‹oéÒ'^l+Nb›{ÂyÍôoÿÄœCêÆþ"-‡á¥þíl&-!páÐmËO½9}q1­ :û½@tùxoãá|"¹‡¿¹ðãÆÃ¿^¡vj½™RA=ÞþÞwáǯHVÖ` {× éó¿×®"5Xr¶šýzëqð[ ™‰ƒþ àq&¯¿»÷†ƒÐA '*â#ïKoñ·/,F_ÈFáokÿOé66az+D\‹ Þyya•ˆýÐõKñóÁ´ãÄm íåç~}9°ò$PÜ}ÝyyxòéÏ (ĈÛܾ܃kiáæþ§Ùõ©@n_¨×òýúΧºàºñøpøÇÇYÃ-8ßýyt×â:¯L,Xˆpô¸Ø, <°þF Då¿§®Ÿz<)§ £{ØvúéóÓÊÖÓlºÔü½`è?Ñ&÷àLë~Z¡^b÷Ï”iÇXÖäðçþRáF(@4-ý1,üGÐ}1¡àÌ©>!¯õ÷å…§d׺?–H2?ÛÆ'Y¿ùÁC3¯#®“»ã§„D Eˆ_ܽípçë}~ô䜴hëîôû×öé~C‰}xa Ü‚ †Ÿ=ƒ[]vç„7QB>ïØìØu½¹m®+6aH–àÅ tRÖ`7|-myñÄH»-ýÛ|Ö÷½½nXFY¸–ö0ןõüÜw =äx…ì[n ¹ý­m0ÓxÒÜ^í­{õž—å°nÚ™e%­éM†“Ó™Ë[qƒ‡zz¸¿®s箺# e’áÚö @wé¶œ»‡0ÛïÇ'ðñi¶†Ðu¶ÿFU;‡M¼CùéçãˆuKŽ<þç§éiókÞã˜#§Ì}v×àdˆ"#}6çûzó½°zR` c÷À)6#ô8ÎÞ£ûi¨ýßÓ ´¸ß ÃøñRÞÀ=½GÒHnäéëëÓå…¬´mÇCáò¿Iá¯B”­@øü4ùŒjÒÚÁ~›xõ[aÙ@0¸xhúôzôÃu²a}´ Õ¹‡+‘倀ܾÿŒIò¶ Zm¤óæ|â4Ã}JÄ1çÖöã3ò~Ã.]•¯¸øõÓPÄÇO¦PáÁ}.;xóßLD‘PˆømËmùðsÄÁr—ƒ].c¥¬5ôµñvì¥!Þkÿ3ý¼½r¶"9“–VŸtçÏç ŽªÕâ`µ2‹2€ˆ¸|Üç!8JulU8œJ ¨ :Ü,¸…âlÖ*èh®`I1"m“(Æ1•ÿäYAÿh@@… Äq.Tê ñX¨ñu ’§IÀxäY*uHèÉʬ/D©‘4JÜâSJ§¾mDl%mÆ-G2:i)>ÝWk¨Vè2pñƒuûÔ ©UVà©?J@"k„ ÿù¿¶Úÿmí 3e'y¼²—-Ë›3 nQµRòEÌnÔÕ>’?¸ÇÍ‘dµ‘Ó,ˆUCÔüN©>m¶ƒáÇ i_Ìã))©~f¢Ñ¬³åJ-Û¸¢Á #PD Ü5ÄlS˜nÅðÆ´‚„׈ŽÇMDt¿Óm´AΚš ¶_H°g*ÙÓéF¨´lÁ^-(Ñ%–\ pxß¼h.N‡LƘ  bÌ•[–&–Mq(ªïu¹y^ÁÏŸ@¶$߇  f}¢Ñ:¤o"…—* :ÎNmåW³äN¤SËJÒD‰øéçá‹þÝDýÒð’À—[M<ïoC*¿P×Rê6zHInŽÅ¤¡Q#ÕSR)"G™fb¨‚íV ¢Õ(—½+Ââ0OaP‚)™C¨"e1Žs„(˜Æ1†À¨ŽÀ{â¦eiÇç,›¬Ç¡$geJéC°Œ—‹y"‰sª’h‘G‘îLºÉ®"©šÀ (âøü`f‚Ÿg67#J æÅ~h¤ Jrš&éRTÒsƒ»"äºm 쾟~¿4¬"{ŠFiÁ<ê.'[R^4Ð눀ô†c‚ÏŸºEg“Í$Y±<•ÎA" À:r“x…PY$΢.Ê¡™Lª¼%AÙìáÓ¹z œ<´»â8•“q,œyb«r1dÑs{DŒs:Iw)¥‘U/…N"ݤœÐ‡Y)y,Ê¥©w¯Þ§Ü3ž”U¼À‰*Õe ÎYû@2dQ4ÌFÏq” ”mŠi›kµÏšZ&2}­TÖŸ¥`Y£h£eWzîBhÅ"ŒÔQ# hIµLþýÈr D¡aáì†UùÎYF‘&¢¶™¸‚gyÔŽ8·«]îi*˜îÙZ§MN¸êžGÅEÅÐÐèªÍ¨ŸÙ ‘LFâR‡2Ž—Ôoê!­ç6çƒ%¸š°4P 6¿éü¯Ï±W)u¥[C2n‘…" €Í`±,;…ÿMõצ¶Ã½Î/ÿêm¥ŒmÄGpë`ñcÙ ŠšŸ,¤ ¶;Š*vÀÜOô4€xH“÷œr½kÊz¦¡Ýã+uÅÎñ«ˆ‘ëç1‹&‘éeÓîÜ2Œ1Mÿ`rCÏÃß1è<«’͈º]•/£ú_¿•‘bþ!Ô\[(ÔŸº|3QdCÚYʉ”‰®¨÷ ¡L)—Ô|,ºÂ륶¦oËÞ×P°ö°j8lÒˆÒ‰IVµÊ9z¹ª‰Yu(jv¦ª¤e¡S¥¡¡'¥¡»t³iô]6N=œ¤ST‹"-¾²Àû¿?6þ/Z×gÙjfœf/íe1¥PBúi™ÊsSX¤¨ âÐ[”¸™ÝÞq•¥8žv_í ÎëT¿gFXàpJ «©¦îÛ©t¤ë P' h¼»Š+vª²¯*HˆÀ@åöíÛJœ¼*ƒi „—lÐnnà®NàD `)„ ¬®b›ÓtF_ªÊaËæOóB9ÂM—†#2VåYá^$Ê©‡Ú“â!@=¨\ §âåáºÎª)7ÓΩ˜j>N¬©"J•u œDÉiæÆnG ÛHÍËHÁÄægd‘ú­^¹8, Ñ\IcPÞÙ“5¬®`dýXÑe¢ŸóJÁ´µ’dаòO›Ãø~Þ=ª1±›ˆ‰æé¦‹¹PŽ2ȦÐÿŸ9cj{1¡i•¹VÂR¤—uÅßP –R´Kj'À 8îwcÜñ„ˆÊêiš”º’®dÜ¢$†En!ÉpïØåŸ«‹{él:{Xv¢4­1C6¤¢)ºqD•®^º4[)€©$4ÜJˆ0n¬4UÓ‚Ê;ID W”b© ˆš…4QÙÅY˜Œº‹,sA»‚»t쨦ݻf­›÷Î8v§tŠi"ŠgUeN§ d(˜FÁ|%TS欘ÖÏѦi´¶b²ÏZÜ©ÒôÍ<”ëË[)FIËÄ(5ìùQàA’Q„2R~À›‡ÎN²¦ôñµ,ld›+²”ƒ»Ïv¾‘–*]K®‡)ò,¹Šuæ2ä%Uï½IBÐPõ*³'ÞI"ŽØL¤f›Q˜æŽ¤L©Õ8ÒH+­}KM>³¼BzS†N*í -SfG$þ–…gÊ:129ÌYñ%9BP1®Ü ýÓ6îZ¦¤\Ë*vi¬ƒhî ûJ¨ Ц"YösË·•&q×9™Wf”õ$Ö]ⳕÊÊ.Í¢LÚˆ• &œM„T kÊN$"Ñfß¾YW‰¤. w¦´“óOif´½0´DC-3Sæ IIHæ#ôZRQü8$«8†2nA9“¨ ·2 –Ææ7l¼Á›®ê|·ìÃ/"ÁÛ¸ºû1ž‹bų©ù3,Z~‰”Eƒ5ÝJ8iÆd ØGL0!ƒÏ6r¡æØe q×V–Є‚T¥(€ä’tÅæëˆeµºá Ci+Q6)OÃç`þÆ¥ø¡ö–ÿYΪÊV]1gÙü¶ª¦TšSI4ÖvªI¦¤‹Óª|ÈßrÝÏi¥¢!d.²±U(a„Pqt5ì…¤Àz‘öî[QÅX®ÖòñÚpKÌ ·_2‚–©)UÝ)õ(À¤q ¤¸ÅBÞ šDÕ%SÄ Ä䉊B|‰·2¥Šh£4äÖ"e_¼3(É?cFGÙ̈ »f®Ìý'œlfGiª‘yCÚ <òÆIä¬*‰åülãuN‹Èï/ê:bz=a ¹x÷ýB¡…aîÏ ˜¦P7 ~Ó½¡æ)šŽIô?µ»l‚¦s?K™û˜×OQd©Y©7&™–wN×T«òž$ò©‘Éž3o ½FÒn&nB (µuÚý­N¦ŽhGGæýE Ƨ”dV•õáD×âå¤Ù(YXwÈ‚Ë*˜%"¬,ÁÒh¬ø.Š=•Øÿáã7dåûBië+hêƒ*) ©j—1ajeŽê±ÑÖ>`©šnÿ%qöŠK5•/"²Ž“›3ŽÐóM·y³™Ó1HºgJiTå­ä¥ hŠtW1¼”…¬¿U_º¥) CNU~Út˜Î³N²¤éŠ9h)Ý@I*í´ÔT¢…Žsò5ãv.Ôf£…™=1Ñv’©1¨Vç\§¢0’™œÕ×±ÈÁÓñíY¤€8U›WIF5h¢œHœR2`8\¢P´[,Ä£#çÚ;—É<ÄUDV"§-+RºKÚã)€·“!JÝ~ÿÉãTTðð‰nHÎ'ݳ²â²QZ2²}D•³”–LW£h‰Â¨v£fç3ʆ˜™‰€˜¤r²‰)Ä'2fÆ~#ÿ™îkžPíVÅSSÖ0¼š†ƒ8ËÝo0£ÏœÍi^ªA¬zŠ¡º¦Kb…TTŠy5éJÕJC,$:íçÙžÙQPe'(Íu¥·Tó´éT¨¦q +ºæ÷ß¹¸ .²e)è¹#>þQ¼ô"…ïÍìYFQè V é¡Št‰rÈêí—paRåV唂97×´ž|G6EØræþe’-‹c®»Vqå­&ŠÉ«u]œÎ”A»`I”pc®tÈS,c(&šeóS·´ë×ïåóÝwN¤š™›°V€Ê²5;cØ šl’¡“`ØFÁe·IP€à ††MäÄìUwQ×5³ä¥fê¹¹jŽué²+ɉ·ëÊI»#æÍ#YÃ×+,VŒZ6dÜܶnŠ"e¨»*ì«´ŸÛœ—1Ì2 ºJF_Ї–=Ô6¡}í-¤›ô牦Ñí&G]“Õ°ÅkN¸¤{ˆåRŽ¢Oź‘N mSpž¶Ü  [N¾ë¾®âãŽ#À²CËa×ÃkÃà8z¾§a•Õ w.¶áA-À6°ò¶$ÌŸÉlÓ¨k8T'eº¿?ÜTBˆ‘{\DežURâ‚nž»•¬jI˜é…ß MšD4SÚˆà=¼«· [¡Ø½¡mFE°9FÐgŠQm+Ktl”𬯵ÀTÕ%2V ’¢”-Çœ\!†Pã«'t%UnG–ÖçU¨¢£H+uåOtÃ) )ÇÄ”¤IZÔ”rC?/û4VY—·Ç Î.A1’9“U`_„AFqÉ”ÎÜ$P‡+…JÕŠ aÞ Šp$•HvrÈáÌ ¾‚­«Ê±üÅ+•óU²¦)õ™*fó c¡)é¹/ÊêxÈÆîÀ\&õH"èUpÄɽbeïE”¨d$e\¯Ú?³nHÈ Î*‰¢WÎÖ,AŸ±¸äk’“2îáÝwK$ÑŒ`2 ¡WŽj@ö%Y{Ù²Ž¨g‘§ëžÖÙ»ž¨eöXžŽšmKQtöJЉ úAÛŠ‚JH(¨jf¢›v²(ƒ4]ÎÔ)¶)ÊõÊÏDíŒÛö“·½½Ï*9}c;9@TCTY[ ©ä¶ #¾Ì*Zr©Ç@}l*••ªât&è Ø¼–´÷í*¹àóµ PAU§q†Ô–Ò™ , ›Ì!'Ù±¼UJΗwZWË=,ZRó‹4EIJ-ÔfS÷ ) r{Jn†Æ(šÂh¿Ta\§ÍL»¢«˜Jε Ýæ2•{ºqŒÜZu!be–cNÈȶV”{ÞY³e—[Û¥Ô±LЬœ»!„ $V›ÿ:2·¤ò‹-òO93ã>óy¡ã+ìÉ“ÿMÂ$•¨ªÚýx<ÀŠsJÓ±Qæu šÓ*- ²ݺ"‰Ž¢wÚ´ÌÊ €§ä]Ò”†[Ð9–m᩸ÇĬR‹¶`ªH£‹„“m$wîŒÙBÉ·“nÙK®b¥ˆ£ªv‡NàuY›-I Pëum˜ ûÌÕ4óJRÃ’ös#ZwNYL4%M(x)µ!CÈŒ|öçÏeºó"—;¹sEÕ”ˆ÷g-cJûbñÌuÊ‚-ê&Z5‘§Ýë4HUvŠÐª»tƒ(ù—îÄ äH¤Ö (Žʨ_A·˜é~z[Lì“í™g¦é>Æ5ÍI˜ÍEܲٳWQYJ¯E½+ÆEjjxÖuÔƒièÅSrvs”ŒS•¤ ÞTÔЙg[öNí/’YŠ„¥¡bs—gMKËTqô½\³ã1…Ÿ˜aæx´Ìƒ JYirÂoœÂ®©Ü‹¡r‚Ù_lciëZÈ6¥šfs7`Qæ4É 1XAHîÞbJ¨Ñ@´RË‚wZkvÚ=•9{*­Ë–µÓ¤Ë¬8wÖ×ú½V‹D+ÞO.lÒJ&Âå¹íkßm¾<þx‘òêïëZU¢q³r¢iØÕ?+¦Ú ö~@Ý&åFpÍ­’ršGIŸ¶­XÅQÑŠÝ5G ä\”å)ƒ„@Ö°rÐzßǽ1Ñ?Ã*]Jgµ4 ~Ï/d36O/)Z¦¤„¦H+U'´F“‹w54 ñÅÄ5qSwŽ%R*²þÎÍ8Bà\³è-±)Ùý‰Ú¼ÞÈ]ÏfŽÓªbjUDâ):ú•²™Fô¦N!9LÖfùe4Hzº™+{°ê ¦ØQãÆ:C˜ùxÚ¥¡hHnÓï_öS£*ñÙ‹#ëTåsAÝ1*ƒu”–Ï ÖZ^äû&ó ¥)úAüTSS<ŠJÈMôœ)$ÑSþÞ-TΙW)J‚‚nìMåKÚ$jI¹Ëf5õ?ZKVMß^^0­agVh,$ÓpÙôȲzÞ³„ä"çlK"óÞM£G ‘¼ËÎ33|Û4Í]îg˜×f¨r¶¥Ú•ÍÍ÷3s~8èV5-52cv†XLi 6–Ät„ãã÷ñjª×ˆ“ÊEÜÁj4r,òÃ.c¤ÈÑ…Z5ÔSŒÌ@€ƒví›&)«˜ë”H‚bTÍt”0®E@ÌâA ÓÚÉ&l [ · ‡`ñ¸ucç]f¦xvüí=˜ê4ö6²ùß^¶ˆeß.ìS´ìóªf™b ¹EN ©èh¶¡Äݰºà#f锩}ü¼ ‘J@CÀÁ ‡ËOLv¯áÃgJ¶N»0Sw¬«)JˆRØJ@“Â~=xT»y\fË_õm?ª8kx|±­ÅÿíÊÞùü¹âyÈ~Ç} ;MÉ;ÉL¯Ÿ¬ÒŽp“IYÄýŽ•ˆxá3,ÙŒ¥W:ê2žg$ñ"™F1JÉ~i `ÍɽÜYîĽ˜²Ã´Ne:Íœá£2Ò§$õÔ õu#™5ëÕ„E=DÓ3sq²[œ:³3È6rŒsb•»d—|ègô!DTݲÒVŸí3]™Ù/.Õµ'—µ=Fþžªẫ7±N†›­*x$"y8ÿƒR±w#w‹ÉÒ ¡ˆí[µL«bjÈrfͶ°Ÿj_”•%+B*{¥¡u5jIJ½‘§KIRTûÉT0±ìÖÍÔæÍ"²­ÅÓPü­Û?R[Þ-µ ŽñIQQ!{ã95ø8¾Ÿ¡èÌΨf¥WS0‡”¡)-ªl©x²¨ÝYù‰:®npÎRB>)e¤ÚšBŽŒ+ÏavÌJG„îqÓ æüÿŒ°:mQf½U™èºƒ•¨¥³³z~9Ó´{ÙÅØÀÐË4Ä;T™«(É": XÉÄÅÏ¥ûDe~UR…« ªGý°jÃecŠv‘’Êá˜É0‘}*éôdZÖŸz³¤¤X:x³x¥÷‰ f¥N¡ëýÛ¶mq—õiMvhÉÎÄMk‡¬¡¨ê‹´ævº®³j¥cKɼjæA¦[QQgÝ”Š¼,M[R®¢åp“’B¦Àè¿]­í;n«žSÎmcIKTIb‰” KtÍ6¸V³©JT“b³³Ù;(M K€SÅo,žeN)POØ€Ç6{Uþý˜²Þ‡ªëê7:3#.ãéöŸ÷ÕÛ(<ħž¬Æ%Yâc[ÓñT}PGî VI§þ£r˜‘e¿ü‰øc†íÙ2²´ä•_Y B±…€¦+¨f3éÓRT±A1ðÓð°R°sþÆ xi¨ÆKº+GaÏ+‘$Ôú¬­²ó8až¿«ó[ñH‡‰lÆŒ­høÊo){!ezµÙjÙši-(A8¾m%ùÃ6 ‹dcá–AR( ¤9t»…“ó±—áîç/©Gý§êìö­â(ÚB4'³ 6g¡ÞÈD¤ ‹)Z˜ÌjZ=Œ‚‚²ë Æ,`ÐhUSe·")¼d=®m6]PÚswÆy—•$<ÍSm&­‘¼ºz¶Ð‡ €Bj ­ª7–UÞ%%fÌeï¡F•ð J›R‹Dð iEIÝꀕ Nð§ãIh`8 Š[€Üo Ø7¸ˆuÜ.…ð–¤-ïîp÷Ð/ËÏ6`AEQ9“3Ç0K–ùÙü‘©³2qETUîV#UOÓP`E®³„7röž”Œ<Œs•X?{ífàܦöd@<0À[€…íË]­aØw¸kåkc©rJl³j²Ê|ß*Pv™ô¥E {È_»-­$JT ¥@èEøœWUNTeµ ¥©®!QÑ@ï5œx 1’@@@—Û[}øàUo a ’ÜÇN»¡{X’ Ãÿ y__;ùyŽ;3Ø‹²[@Ä'šYÜÊ™ŸÌ+²Z…Êj² „ˆŠ§£NeTV©®ã$Jô\K9j‚‹ÂÓ2¬Ò#ðRYË'R*2d;SQ“l.R¬Û72T®æŠ²“U_Sº–XJ ¤{ï¼¢PÃr£¼â›mÃrÖ곊¤ÓRÅ€[®™îÙnÀ©dq:%ÞZ¬!!JO>²K°åšT3Fzf›Ë\£# l注¶‘‘TAÀ4ÅQqÎÆ vQt¢ ¤»äâ<*†UƒçeAp%àÈó*³uÔÌ<Úð‘MV’¬;@f5G–¹/–ðPOýŠ¢Y¬;˜ëò¨xbHÄV……I!Pò’‰¤ÕwFìüþfÁMPõäE—Y•Õ-L×¥«¨ü¯Ël¿ªŒ[Se¹j\èæ¥T œÄf’ôÂ5 ±…,ýgmá•nÕùçTIåüv^eŒ©¬®¥‚¥®sÓ³yÏ0Ú< ‹‰Šw¹qOEÍ¿*u•Mv@íC6E:b—j>Ân]Î{UÚÜΡj£¬%&ñîi2Ô¡ BgÝïkƒTóú·ÛhªJhÜX´›7–S Z5ŽG¼íA$Çu ChLè7T¨å¨‰Ç6×ü7©øYHzµ6l¥YG:’h5IN:¤Ýž>1dH¼e44­(þ]³ú„ˆ4¬RSòÕ»£,áU|pά¬ò"¨mOW1à›9ptµ-R ƒ”aêflŸ:V<Ïn±±m’’f²`v«œ Š®Ú(Ùã¨øºê¬GþLÇ0i¸Æ’Gc7<ö›¢)c¤úAÛ´¤^´l¨»jŠ%á#AY ^àÆ(â¤ö»Ëº£´þQOшFÉÕuÿœÔÔ²qñ‘ç¥êjV1Êy£dÎ-$F²kAL¿Hýé¢f ¡Ñ@†tÙ>×¶“(¯e9ÕZó¬©Å¥-V% ©a ©êR”¼T‹Óªqµ!%(JBÂ|Ëeè*YQ¤hRT¤6¦‰ ¬¶É)ƒÁI IP§ù;Ø‚°ÎºL‹¬hzv=I7±QÑ3œŒü²ì@8×eͺÿö'9"›— !Ä»D1¥IE¤éÿ›4㌗y˜™~tn›€z’SжQ¸¹p"ÉGÇP‚ÇûlŒC«Â å1L7±EX@È|¶bíjš„†‡£ \î!w®jŽ×ªVxQYØsšY"ºE^5ÊI¹fn ÂbºË÷‰ÆKÔùŸX±d²`af«Ô,;“G W‚î9Û í\¦"F’*GQ1â1Œ)¤Ìÿµ½¥6Í–ÔR7•Šú´eèU2ÜH}i¦ßqh+RÔÊP¥’IÞ&ñÕÌÐ"šœ¾‡MAe¢ù8”÷Å .n¤BäÈcæ×´–H>ìõ\³ ª ع¹WÔä}J Æ7xÑšI¼’fÝ*/ ãŠ1UNEÛ"b$²c ̬Û@DA¾›ï¿¦ºl,7n\Ë…ÍŽÚY¡1FLžrŒŠ=5KÓò`ðÓ|Œ1ÖeÚ/YfÎ;ªuÛU[¹;eÑ·¸ŽxIò)X@4 mÎÁ×P^ž“d™FÑ䯮­´›Û®¥)B^]·””  L€ <0‚²º °ÓJ÷O¼”“%)°I$ž$žf#¨ØGn`7çÌ/§ˆŽ‹—ŸA·¥þþzÈ'n-,}·û×åm°ÐtŸÐ~_Î"9£A PŽ&má~‘¦‚ü4Ã2䦟§ì<ôŒ"¨¿€ßÓ—×àÊ¡¿ˆ_åý`¶#jüÇÖ·Ã’tñþч=Û-¯1ÛËïï| RñÝÇ(L¨zôßüá" A×Krý l<ƒ®ÿzàÚD‚Ûˆkál’b6‡Ó¥þ_º»vâkMKê:Ø:ˆu¸[7jjb£©õ·—¡3„î.8õ±Ôôõã¦4I®xê#ý릃ñÂ’(Àl €~ZøxßÃÛ³°À5¿_Qúé¦PåÐv¿–¾~_@ÄŠ—-R¢Rx§§„p…Ú€-Ò|íŸ 15Á6èë°ôÛËìë}\ÌR·Ú|íñ uÖöÛ¶·º;ÿ}6Þ÷ ù_v1£rû»ŽÖûûÞø˜åyJ‘îE [Mzsá~6j¨©?N¹NV‰ ܺ ÄCmô·¯ÓÏÇœ7@zß÷°ùØC\5"cå4ð_€‡­ÂS‡Žû€åÌyˆ}Bÿ0¾.™ËÊ ,¦|=Ð>rxDs‰æ/ÈVŸæ'—ž‡LH )è÷ñ W^›Œ º.€Ò2ŒLäÅlU(¦Ä…ÑH¥2¼@±C½9Ä 8–]Ò ,¤hj-áŠÐé•TéÄ ¹ ™8KÁ"å7)ÔEƒ‡‚÷⾸¢© ™Ìz*24²ˆ³ŠM6n (³¢»÷NRÆIE ‹l:›Q“N$Û4Zz=»p<±_ºxÙ“þ4A!Ãي*¦%²Êâ°tàݯÌ‹mVÑæ@ï"·;Ìßjó .±ßgH¤í-]4ê/áÆÏý —ÇpРœ¥@tÈ¢ P3pMkð¢sˆ\.k_l2þ6AcÚ>UDøŠZbªª‡ +»Cpwá^éPÕØ®7½ÙÁû{˜¿gk…ãÉîQ.»8DÉ ç­ú?´b´µ+^æ %Æ:6Œ¡ÝQÔ+T“]’¬ È YXŠEE‹ÂsœM8e6k™NÄQ´ÀºTîei|åz~ð«2’ÊÚ½ˆ%0V) œØûN~¹„1Âüà̃Ó;HµqݸšvÑw¥銄PJ¦·5’D¢!aL{Ž..Qæ9™å&UCŠö+ᯡÎA–n“hÌÀ m.~î÷@u°ãÔÌÿ³}œ9]rêvÛ¨¥Úœ¿4§FêS¹C³¹lÖXÚ×ýK5•55k2Bž¬Rà©Kž?{…÷œ%C¿§q‡Šl\0·’t”¨! ½ÁÓ¬öÍg•¡ã«î,úµ…iZ51ÌPLõb­Ï\FªTÀ@[ËÍ5•"È G N`ºE69y[×2tÜêú9{5’MFÒðîl³è•OûÈi†ßüj÷ ”{µ @U5ÒÌ hÛåís%Æew°Ð•©Ä&¼>¤‹ù)DŒòN6)èI6ª»LŽ'Ë÷Ò+ƒ…7ų.ZoóÊò}:Žj¢fâUí9K,hôY¼Iê‰ áIW)™dš}©T“j©Nnb¤¡üdv5±ôµ›;—e{bâ(Ÿ«ËCÍdÙJ©Ü¤£¬qª^è¯>IqË,¸¶ÓüÒó¡ ºF,ºNŶaš•=”§¼Co*¦§¼Iq R‚⌀¡¼A"L ¦IÖ˜J—/ž9bº@e&©%\Î¢Õ T; ®ò4ÃqJÿî OöÍªÏ;Ûεüª«dÖA1$tß"E8FàÂ*¼AAµŒ$9¸êþÏJ3³fFÀÄɵa šy—UEåÖSCnDè¥RT­Ä‰Uª‘ÉÐR™¤È#=/Ä`+†h{! 'pâ­j^Å´^]ågæžyg9”mdÇ$»>fæeOV¹€Ñ%П(èø F6œ›ULƒôŸ®È*™ÌídŠeÔc«ügöWR¢£—m™3#{(ʤLIŸã¦ýEζÓ»(Ú6ãùùM£JšžoûOWÂ%O—t}@U^S.¿+p­Î ~&æ0ØÜ$>ÅÀb€”¨ˆ_æ~–©)Åß·9Ó×…vár CN ˆ…¼JaÖÉs>VÙ”êf4ßeÌïËzM'‘Éæd×™w¢N_¼hÐÄ—ÊÔ¦&ªàtý諃‡l´X»#é‹v«#l¸Î¶uü:nŽYºÅÖœƒÄQ Û „}ฅÄ@m‰¶Áö½±ý§¢¡{>ªúg©ßqƒEš±OMX°ÛL:jjš®±*§—ÃiZœA.!ÔÂw‹Fs²ù¦Ï)´0´¸”¬;L·h¥$!J[M{þæñHI„”’n_ÈZmÃÍjZ˜œiO¥%ªgrOÇ = ‰ä¤›‹‡o&WI LÊW)]¾@@ä2„í¿gÇ9o?•“/h î¶€sžU$3:Z>¶uòSMWrEV]gÏcéohIòdN: q h“¤“cŠ*¤™9)NgÞXdiI·]”iîÔS# ^'C±Ëª*ßš’ ¨$j:Þ $T¢¢³›)³ô™¶t ºnƒ²ñ¨Â~%ò·³}qCÖy!•UNdJæwæ~Kä~fÆeÅDìBáë¬É{KEÇh{ RœŽt¬«7€Åvè7"øâ¯ÅNižæ›xÖX¼¿3g!Ùê&ir÷Ü£ªn†ºº±¦«3*ÊW–Øeò ”Ô SJRRªº‰¶»8§£§É•P¦]msÊqä%ÖÔó,´¥5NÓˆ ÞDî¸ø ðàJ¯ä¨ C.«Ãkþœ‡¤¢š1æq’ÿܸ£vd£ªÕò>!)Z†z2m'I‹ÆÕÅNd¾QWí^ ˆµzØ¢’•lu[¦¹L²;{ì#!ì«g2Lç-Íê*jóá9Zèj7eÖM][µmÿPÎÓ°Ë€Jf­½è;£ ;¶U»I_WKQJ†ÚbÔPº¾ù–ÒÒŒD¬8â“Æ1ÄáV'8å3j®¬êj²¥G1žfcš^(’RuU–ÕTE:dž£ìðAzç*â5”búq‚ŽÝ³–JYýJÎ1Û£>rÒ’´wgC­;UOU Ò•«IçsÒÁ$Áƒ$jg”õ.¹­ ³ZrÅü2îÐÉ™ô¥PŽ4µrùeÊ2}pWåëñdƒÎZc¶¦RdþyÖ-kÍËnϹ^½j(ÒtÍ*þ©³Òù敞NŽUzfff˜‚©iºuÅGOû Dûx–Ó_‘AÌHÌǧλ'ßÿĹ'³þ%K¹»3%ÔƒМN³-Ï`¬ßÏgszyœw1LÖáÇ]¬%[ߘòéŽÀ~9O˜Sò§SeíwAÐó½Ä '⨧¥*Úк iiXF1©ŠÌA¬a;r²½ÑÜ´* qˆ‚œ­§!˜¢`ý($½¿N»ùãèÏðÇ ÛÓ]œe+É™@’°™ªgR¨Ÿ°]+í0œc)”Ž‘ÌCISò¼L½ÃuVYTÌà§RGПÄMiÊ;«iJÜ:©È²tQY¨o2} ÇõÓ寡@ê…/Ç~´*¶­¥ )¬¨#Q³NƒbEœ}bØžær+µfT ‰‡kNÌsSRRî°ùÁ’S4Ü|52X³U¦j¨¼Åo,Àˆ¼)Ž·´@™$ŠQ8®\r?ñå®s†’ì‚æ˜Ÿ®; ÖtnofžTÑi-Ù~K1]U'ü²6[3ݼt3Õ˜)*Yª= 7 ÙÑšË0RΊ’‹ »¶LÒUëÕL¡“L ݹdÓ2¤+÷-Q.ºE5/ì»N÷TÙ\‰Pä òëò¸olv±œFbR²¯ëê+³wçDòßöTĤ]O@å1[·X†“áÍ Æ‘¤åfQQ);„Ši.ë1m튃³›oDòŒå¾Ê?-mKiÍ*i‘O“´âAg™RiR â)[KÙƒ­±Fê•b‹©¤VÒmʨdšfÖ\ªRO大 .€Gå.–¨÷VêU¤Œvg%çòó$`ò+#â2g²¥mš’02ì»Ìç§"b¥–J™üÑì””J S“•;—ý¹8‡$EÒk¾:o$޲*¬±u¬»aÃVã²£9{Õ´ÔlÛ†1°•ŽTS]œÑ3xó®ñXJâ}sÑë5w2¢¦;¦Q´ó„Û, œ©ª.<ì{”Y™NJW=¯ó&bá{E×ÓpY‘ùã?CfÛü¨£XÇO+?\C×”Lëf4Úu˜48XïÊeNÞ&%uÊÚXQL~.ˆ=o•¹Uä è·£žEaDÎV‘u…òD´dsÆÅ®Fдª—¢â]¼r'IHÕ+™BnZe¤©åÞ4óÍçªkª¨¨uÚªºÇÖóï:µ:õECî¸ë‹Q*qÇ\QRÔ¢T¥(’I8¼P†Ùm-¡)m¦”! (BR”d¥),a{´§âËØÃ³,Å@dæLÐõ¦måÍj•MR§Ù8|‘˦RŒ“véi¬Ñ¦Ù¾¬eY$õHÅŶ^×p1Žìã"¤ƒOcV>§?HÜŨ.qvZÍ4)wo3Š•ÆqDçUQ º¨Hˆy\»ÊFÌ2`´¢Ð’Ì=1DÞÈe;°/²$Zš2í€æ8ä*„¸ ÀÚßè!nzâ굦"š¢TSd€¡k :-,;¶¿Lu×g?…zݨÉÎsüÅÌ­5­¥Újv ¡µR¥ï@ ÁËLV÷hÍeÕ‹¤¡§MIiE.8£ Þ|þöî•mÛ(ä‰@f¬¶a²©ª2ÒY!“™UL)T×µVb/ ¬œ:3Œ!OFEDÈþtò±’oS0tŒ™™ÂQöÓXl¶ì™JUÃÚÇñ!¬YWSISÎ#»&µ­ŸW¹IE¬Í˜kYRÓíWwSÖŽ«7Я֒„lñ6ÿòH‰RK˜sJ†O2rö9’+BH;¦óHì¼D‚òtæ•L“Š6S»lüµI1p  ¯±RLw&VÜVô£ W 8ª'22±y0ÞB¨©¨§¦œÎ9—t <¦ê:,âz^¼d‘Ö"ÍIÛ9xõlî6Umì£Ï]¦l%_gešì¥Sâ¬Qû3ô•a;¢ªŠ²ºŠw t @Z˜z=Þù§7}ØÄãgó–³ìª›2mÑw}´L÷o4²‡?ÚH DßqI›Î)ãœâ°ÌØì«í%#DÒ°4`ŽQÑÔì–cQ©—\Òð¯_ÄÒÍZÂÀIQÀݪMRftV\%dVç0¡Ëh䕇fì¶?x‰ &µì"áϘølltOñS¯¢vs©¨yÔ³ªâ¤!åâ%ÙÊÉÔ1ÕhÆfU áfò®c•Eƒò³$ñÌ ù6ÓQ)·U›„\3üÒÉUÅý"ÄÆð¤P¿†öÓ†¾펂ü,×¹W[œd¨­ží5l ’BT7÷EâI“žâÚ3)mªJÔ€¼[QâAˆ›t8¼ý’òb¼­Õ««FÒkP9zâ*FU¤84NJzqÛ“ >ÈÏÐ]¡ˆávª¹’ âÌТˆA%IÖì߬jÊZ›¦ªÊ_,(|ÃQZÇó–ѹ–ÙÓé™Ú–ªªØF,ÒRqºSŽÑœ‹çŒã˜Æ"TŒÙÁÛ°)W†ˆvAgT×ï"%2JQ\©ËŠ8³y©;;H&… ›Y¦ê]y¨:nB w7uÅÞfQ®UY(&Mf)çíJPÖfV¡íE™î[NÔ]â2… «œ%5;šôEbò£¨w¢&£Ño ÝýÉÖÛsŒ‚æL8ËŠ[¶M³;e¶Ù“´®ïä™C®å9*e¥SS,¶ýr@;ªVcP…Ô‡ ,ÓVW=ÂbY²¹Oðœ¢.&*ꊚ²D(8´‚†Oä †Èw¼ï?9›4h ÞMªÕöjeÃhv/’ŽË·>ZǯN* ·r”s¨Æ È A#1}%¤›SN‚È4ä¿iÏÄ(æŠaÚ´ªbde%HäÖO£WÓÐË…M Ùú¦¼¥áœ¼P[™¢í¢ß?“jà‰¢ö9šV\µÿñí]˜”\$nMÇVÓR¹ƒ[0‘qPHyûð¦i—®Šyì ¸¬Tæª'Lܶi ÍÉVŒnÆIÂI éÌcÂsk'òe¨¶FRY9Ž9 rù0ÞØcØM‚Íöó4N_–£q¤A¨ªP=Û(‘$˜‰g9Õ.ML_¨2£fÛÞYä:sÇb2Gñ4ª³5óÚiÞKQ«ºÑUpåuaOÂ;UGÂ%dîJ†¯ê–ÖlnìΦF:#‘ ^õ@!mÔíwÚû4êhìÉj_³ÕA:Å»ôêÊâ2·©ÞPYrG¨™ÄkÊ’ XFõ\*înôí“u(œ‹„È Ì­Ž)ñ¡ RˆÁ¿ )”tЕþ?Lu³>q˜È´r¾¦[Sµ<­`íÖ`Ö±3ncë Ñ6o›KC ÒMÁiTi°ÀE»20b³dlÅ‹ÚauÝŸd4ÛBÆbœÆÚ™£ÌÜÜr•u WpúM‚™S¨î¾—h‰J•¸Ã³»bÎwZå éÍ;½Òždïo%Ä ôYa'xb¹‚ÚNÏ]š²ó%©Çòyƒ[ÊgeP ËSMè¸sJ2Ë­H°É½Sývðßà8f:ÿŸÿPÃÆHl&ò¿K[ùÃ5ȇ¿åoP ÿ8ƒg$w«ñ1¹ö8w¥¾ìrä“„…yÿõßpeQßÀ-ñÿ8-ˆšÿ1òú ;§AРÂñu(|>vÁÔS?ò°k§Þÿ=ôÁbÇË\*¶%Ì…øè?ÎܰõLåGÊ÷?o–8¨ÓKÒÝp}³pî=5ßqôý­àçfÏ‹‡Ýð !åÏ×ËðEŠ7µƒÀ<@4 ôb;_hæÀ<:.CýÃ|M²Š.ô¦Âñ+Þÿ_†*žÝOC©¼ë±»8Þ+0éãðßÄg;H½ÛmËŸÈ|CÏÇ ð°îdµbÅùãÕÑhÍâYÓ• ‹tÌ%)Ìk…)N!År”àډ̆oA¡RÉÔÕcÖJ½z®_S*T4lJhÎ=ªT^¡3f…°8~¥2Õ>"@%Ä®³4Ùí™4‰ÎêÍ*ªÐµ°”ÓUT!¥ -JövÜ­1½»½}ЭÒ0ÜÍ=vaÞš6»ÀÑJVK·@=å¦l ¥§\VÑ ÷oæéáqßm-·†l£=Àߦ›ëÊ÷¶‚#}6Å«£²&ŽªÇå™ÖLY G.(fƒÕ¤`)ŽWM”tƒ´LÞ"¨&`5¯ÂQÅvBR Äì´TCßom$ù“g'&£–í*‚+4Ž¡:ɦU B(©Hc Jcq »d¶‡d¶Ž©Ty>b¨e(RÛr–¦”²RžìÕ2ÐqR•–÷ˆH0×™Ðæt j˜îЩ¡ÆÜÐ '»R·DL áN9˜×(X-È@Gùæ>¼õÄŸKE–JZ*4N(BA“-Æ™;r’W‰sE9Ž'XäD ^% RÆËF‚";_ãoîþ7Óe‹T&úFž¨êˆè¶äÂÒŒb$瑊‘°2ž“‡ŒvU™Ý"áúf ¹IË‚¦ÝKw1ðþÍçÙÉþYʲ\ʽ$ëÞRQ<ó`q’´%)I$s8Œ0Mu}.¢¦®‚:8ê¯ ’Ià‚12=Ë ‚2R6ˆÎìÁd´\è¼~©:Ö4Yðé·ŽˆWŒî2(ª2çàfçà­H#˜¬$^DÈæWÏ=‰“¸“” êgkÔÜ*¶‡j‰KSΖXš§T‚'S-Ìr€¼ «ôÚÀ¡ŸÊþËH#F8{7—+°Ž`S,Ôün›RÏeeb[§ÇÄ»·Mš(ˆ¬¨@Âee˜™`…m—/éäËIÌÚœ5 Y’.»ŒR¦`Ùú)¶¤æß&)œ)Ç°Ž’"&–‘bÑFâ¹[¬:*”Þcã ñÎ\Øw1VvÀ¬Âq(ô^S¯!i•ŸöÈæg‚†hí³WMœ…Ç8(‰:„9;Òƽq?ì³l™mî¤@ßÿPñä#ñôÇ92D…ª3N­©zþ] JšrM¼¤²Š8“‘A죧(>\è5:¯]$©t©Û71–:ƒÜ#ÿÆ^“³d¨‘0°…ŠmaßAÔyó¿žžŒþr¿bاë–Õ×Ö©@Ä–Â@×[ȱý¨žÑj{ÜÝ a–’á*¼ãai·Ž’5;Jg-GNÔ”UÆ]eó—EN2J ¬£^ÍϤ™L“³¢¡ÈÕÌc÷©4ö‘NL‡ f Š\G2©˜ì‡“%Cg&c>ªãHBHVê*êQÜsW >zݵ ÉÅ“gˆÆ&©Ò:…`T×]7"¥#.©yÔ| •®kúvmeª Œòú²§ã·Š#pbÙÓè:‰“¨õ«¦‡–9ª¨@L)”I*ËZTõÅ-?/#šÕ#²¹r¨9¬(ŠJeÜ«I–¥xgS´«#±I”2 "q;’ L÷/œ‰ÛÎoükµ½´© E.dÖP€ ¥Á¨©²·RžSQHòÔ?æ-v ;c)}“fr–È…9NjTyûS®T$ž~ãˆñk®{”y#•âÑÆGet]"ƒ&J,Þ¤q¤ÅXôé2Gs•«i‰ªý`O…«%™ªˆŠi¦‘ RT“ËÈÊìU%_”±Ù†ˆH§0g€¬ttÒRI UûÂÊ´,LôaEb€ 9Ó_ônþ}g®Mdmää«ZާM¶¦£Ô“ ”®?ª¶ZJpŽKú5ñØ‘Ÿp) k¢`YA1•ï”b¶À~#ùfY'ËNVlŒ‘X;Dç+2©Ë~áU»¬£RTác‰K$Ÿù8¦m‡žËNºF¡¶Ô²9f™ùÓU–´Íê¢j«™U4“N ¯²³MCª›æd*LbãÓUU–N:5³FDUuÕ"QUNiÏìNÑm[T¹~[R®ña%Õ´´6€HJR€ÂÜÚ†…¥8ûè JR£€8'OÆÔ=¡ó]ýw+ ÚÓóŒ/wJÂRP]E#iØk:‹ 6 ( u”ùó³¹~¹}¡ÒƒŽºÐQ 騆‘íˆBˆOt× ´¸k¨i b¿eý/H1A³ ‘2Ž0¬:Ø7òè;Úji2ROËMBÚ·ÞÁá ú[|z=دgÙwgyHIÜ7¬ UmH‰I€{¤˜”ô€L›â…ÚÌíüúªaH¥j{¦É"DˆQú‹ŽS‹÷Jйúç*"ꬿ¤¡khYô–‡£fNÅ/Q<Œ˜U”“˜ÚÎlƒ!ŒÍÄ{˜™‡Í½«òïjADˆé¸žFhÓ¶ÄAqØ…ºQ²è¢ƒWo{Aå‹]“PT®œG¥O«2 ‹"°©)cÇ &«*h>Ó½£è´’Y¨NϽ‘r¿¶Õr¹W->×´¦u8œdꡜ¥èe*w)ÐÍe”tÎBeªŒVAdÕDUrͽ˜K6²BqÅ<ÉŒ ŽEÀÃSÐpTa³Úž^–­ê8HÃ,ÐÎéÙ×­—¦$Aû• b=‹›t›³.é]0<;P¬^aÚFÞÕ¬’]Û £ ÞüÁ¦ój¶™Iº„¡–ÛI‚E­hÅé³Í2•¡îWA1¡R©ZR΃ó,“§r“ñN_8iþÌTÌ]qÙ”rB ®Î:NžFeÆSùœ£Á‹„©êô§¢¦ø¨9Vr”±ê¶hÓ»ïß¶0#ö1b)ÓpEu4ÓGq ŠcŽöèÐBÂ7 …æÇ˜¦`r[³Âñ/dŸ<šÍ´ž‘W]Âí4dò„r‹æ¨¤ÝkYÑDœ<|d@Ç)„àf#§—LÞ€ð‰¦B[ÿ‘DÀ5½‚àQ0Þ¸€®Ñ§äs0*Š#L¾ƒfÔíÛJS´-+"ü³ôªâf'YqDˆ5|¬”n…1 &Op“"jJ–ö¸îAŽ‚S;sðw’—«¶‡7RNëM5L…å™ r08xôÅEÚ^ë44€ÝjS„t_<°ð4Šr NÍѸÑT¼)‡A(€»ëa×Pt  »#oJ¹iCe¬õjý.¤ îU(äTP©•Ì«¦È¨Ò-˜ªrÏ$Vlئ1@Ê—ˆzÙcðÛÍ®ÒPO3.N¦(x§¨¨ÍlÍ{UÃÓµcF®–JXêËÒ‘¯ŸÃÀ4U©ã\ËíÖUð®Ö›§;öWo<µ#PU/2êbªJ†§æ[gé²™˜~³ç “ap¼¹ŠŠ\zU{òà±KxrŸì¥”òÇ™tŒ,„ƒ gRGÊÒ‘îÅÇÆ2n„»'î§ß ¡j$Y‘²d)Œ™œ&¸ –¸å‡ý¤3ߟVÎìŠ*,â6wgèP¢ž ï³Qš¾ X).¥cP LâÇNÁä+Üöá]™–ÿ)®®x€x’šcLƒ<ŠJzF(…ø]öuìZÚ c>™Êv¥í#:FÒ4fOÆA<ÿ¦´ƒ†©’Eóªµ4×ü¾¦F)³w¨˜õ[†ÔüÂÄ#rSYT…935²&?'¤èlÉr͆bÉÑròÔ&gRÐjRUnPÀG;ŽiUSŒ¥áßΧzî.r!¼ƒ)ÆÑlgÝ(Ý©n±ÆÍ^ÔÔ nNÉç†nS4ÆngnÅEeNRÑ•s—õÑ#j°_é”ON7v¬±£ ì‰ÔRË4FŸˆ"«AÒ']VzTù—yyœuµiPKÓ4öOd¤t"êg„ïÝÎf}H´) õî â™`ÉT"Í+€¦lU[M¶;U¶UMWmNšgµ ¥h§^cTãíÓ!d)ÄR0Hb• P Z)Ûm+P@$y~U–åM©œ¶Šž ¸m(SŠ\_çp€`©Dmq!voËÂÿ†^VTµv]å¶aHדT¨´«óÍVõ`çuz‹ù—JD¹“}ÅâÇ•qQ¤XâF‹x–ɨÔîÑl ÷¦øWí[š‘]¤ÞÓÙ½MÔ”¤4ÞkÈFÇSµ{Fìj¸–´Kê6ÕÊ*‹Ã3ßJ3*««ÅnuÖQ3ªµCö³¨û8×]›û8eÄ\’S0sõæoÑ´ÅMWÑ1“”–aFR—”]Áåã’2-K™ªN¦€$ÜâR|äD¬Îaæ%g™¦w?YÔóÕlãµ u æb¤•w3&àÊç9Õzõu sŒaj#‰oc9IÎ;EÙÊmÝ䦵·–"@KD*OÃá8lÚºŸeȫܘ%•$i$¨|qЦ‹wm‘ ŽÉ”5°˜ZÀ|CE]›iÞÖ^MåDL_áöjö1Å)¬bËµÕ —/\Ãθ^¨ W”‹È¾í“¹óÌÒ¬^™Ä‹2¸ŸYÖ1þs£Ñ;Çl™$ q»rݱ;´Õp§…H‘x C®¹îqHu7¸™Lsê3'§òn·ŠyKæ 91ÌB3.]0p©7"NF fIK7|Ù 83¦Í1Ä b¦UqÔ_Œ|Ì1“l6@…Ú«ó<ÕÆÁü£-¤¦¢§R¿ÝüN¥(‹Ç8â»ì²›~«7­"í±ML•=ûŽ:°<=™²|S‰Î› ûgæ3„˜æŽRv=Êø¨9‰·TU!7Ú6æ6;Vî˜@Štü\³¸—îM‘dŽzT2n¡’"¨üŒ~6Õ?V~'Å˺B,‘t®EdþSeœ3Ol;çK¥#!šëLK¬²)-ùäÚ¹ši)R8Yó„X­NùB·MÿF¹¿QåI3dL£Fusjŵ/2ÿ4 ªT¥?—óI~I\I½”Šw6ÑœâÞ]À ít“`Ež$‘Pns§ñ›U8ªûf缬³ÊbYãج Ï+E/.î”N–›uL´•¦]TiçPR-"}îlÃ.é¢é8’lQlqÿg™iͶÏg¨Bwƒ¹•1PÿJ\JÈ_¤âÒÏÙUs¤ÁM:âñr"ß]Úy0mÑ ÃCi¡CLuC°ö[æG—•ÝU•ùùPäE@Ú¼¦KÉ0ʪ;4b'©úv"BT.ʪAÓ9ËÍ0 U*6Xá)ø5ãU´Xn‘I@:jm„C§Lv'²>j¶ÉÜ„+ú£.;DÓôÔÔó³B/e%rÕ𺑋h›æÓ{—µZ ™3`Õ¤¤ÔŒb¨ÙÐVh‚nï¯Äîd2ŽÈËP ƒœæùN ÔŠu/7P\$ ox$ŸxJvyOí[P"}’–®¨¨ÿs‰E(é?ô•uÔðÅÐ˺ÿ´=?9-LT] û6×’ôµHp PPU.Hf,›¬ÆápÊ“dÚFª ¤œ¹ ݬé.%ˆ’½Ê\GT ~Bþ;™¿É*)ó§a­sf›‘üú•®áj5ZÐÔÕKí´³ m´|´qK#9OÊ8–vð„2ìªmT+®&³Ælö”ÉTsK(§òç´–KÌÕ½¡*E²³4†5!Ö®#XI4EŽ^Ud:*Ž–¤ßµ#cTRñL2)´\vË&§!ŽËîÑY-•”‡hlàíì4|½q5/™Ù…˜1TÜiRž<"(‡qtä;6‘ë!G¦¼ˆ§!-íGN<ÜqY“Û<àÊé•W™PÓ$oê˜l™ßq#õÅõPçtÃÎ ©Sà:á' ` ΋I4ŒuWM "d!…E{B”Æ9Ä@ R…Ì# }BÑ_‰õ‰äühNÂ9eF ÔŒ2ò~œ¦«ª»3 ¢8]ÜÓ–±3±ªÒ•5VíÎp«G,<]ÙÚ¦™Ðâ¶EÄD^•e8þJ&¸„Ì„+¦ŒfšÅE5RRAHwoMì¥ý‘šÄŒp±_™¹ŠÑáÊV«uùßý6x9xÞ˜Î^ÐÞ›{,vôþr@¼ªÙE>ï^~*®e! g«:á!…6¤LÉðÀsø¤¯9^AÙfò­Æ©2góÊÆA -ׯ]—¸S0 AœÕ)$( Ö=1í›G›¬JªEK:„¤­÷Ò%oS-?NÃ=˜ël­¤r£´®tLÔ9šHËæªÎd©ùV]ÊJ4kIGÖN[À’iŒ£h$W: ªXtÑpé7…Ir χ,k¬ÞJ°ìé' ”y%KÃ0¦¨‡tíi;>éX†å4ÄõISU ¦*:š¡w"© ŸåñÉFäѺ©&^‡CS4Qóªgg3š¯~“§ŠƒÚú¡§d&™O±-2ø_TtlxǤ ªÏÆìîMOw»°LSU4C¹çñ¹oSNAGF:e?êZAª1ÜóbªúwÚÜFHĺ; kÝ™ºi»l ¿TUïLsã©j]£¨f©‚€õ;ˆu²¶ÐêР¤•6âT…€@”©$Å¢ãiu msº´”ª Iƒ¬)$z‚Ç?à?ÚÚBÎ4™AšE)—‹E1!ŠØ«9húq›ÖƺE?p¢g>Ê ðÔŸìÁSÓ-IϽw•HÊ£z¬ÚÐI(Ú()æŒÝªUãO/:變õ2¦å¼g²C‹¾9oÔžÍúnBEÎbV}›£ TdáhæÉÖÆYTnH’f3w#R'UG¤¢‰€*b%.‚Bm= …±Â'{™òõ÷j<¦AW•ŽÛÒ¹m™Ž&‡ªË80êJCÄ&Ágê¬'¸5Ônv(. S Ÿ­7âk¶JF¦§ÚjF˜am¦Ó³»;BBR',’H$ë&q_gû*âÔâò÷Tµ¨©J5ÕÒTL“jˆ¹Â>]v|c’³Oª‰ÜÇc'îšA7éÔ\Ĭ݉x窢•*€ñÉÔ‹IdA/h*†)ƒ@á4Ÿ—Ì*œü†¨ŸQÒ²™“qÑjÊö¢"Õ {\ŠH›Ô`ÙJ -é¶n£œŠH„p¹”I0M±ŠŒÁ††™õÓ"´i !ÍCN9”‘3ÇÊLÇÊH'ˆM%ˆÙ)vRMr‰d€ühpà)ø¤|ñÌ´Õ‡K(¨¶­)fQ•7-XHL¸NÄ:Xщ(´pb™Ìœ“„PBä"†ìm*½¯Û-¡Û¼íÝ¡Úzäæ³ÌSÓ9PšjZD–i[îÙBX£e†º™’–ÁZŠ”¢TIÄ+ʨrjDÐåì–)µ¸\qÓ¾áÞZŠÝRÖI<Ô`†)/âCTP°]…ó3.²j‡JeYgrùƒIgñ&G2©‰I÷®$V3wÔãÃwî;Y¦Ð„)9ñØ‚’Œ«¥¨HJ¡žÓëI&ö¡dC‰úž‡AY‰ÆD8(‘Šw‘L¶ ¤pXN±A2â™aüNêèÖ¹LÑ‘ÏݽV¢ÍšqDÊåáÞ6J2©™".€ég¿'9Ó2j P]pP‰¸2 w±sÉjT±Žàâ£%eÜÄ›D%¤ãá™´#§ HòMy%lÙ­;ÔÖS¼;µÄ¥MB˜äūضbþÏå¥m -½–lndšWA#º®¬oØè\qn­öW ÝÝ‘;Â7µŒ"¶§  \)/æ´åÔ‘;Ì´ ëÉ×úšB“7‰Ðã­9ËŸ4d»D²‚Žìë›Ù¼1q‘4ó >ŒŒVЦSY±˜5UåY0h†PeVPPÍÒ¸KO£Ú&&„e \±‰§ØF/ƒ, ª*ê>}Xö°®&;l×r¯äMPV4;çÌ¥%ýÁL÷r™»°v„iKÅÉÅMv•ìó ô¯–]8ìß§4\qQEcš9+#IûwæP Ý&˜ýÒ@%¤]­3?küªÎ‰ 2á(Ü‚Ëz|Äx):µÞcg<•QÑ¢qmT˜phvôXL¿!'_Ç gŽ£v’F|ŠâÙ \MqÉW•lÏhìö¬3Z @5G4g,Ø“T"¡&“8”@ ᎇjͪЉƒ…ÓUÉ“*‹¨¹è¤Á²MÓ &DÈR”6 †Þ_¶¸¬]œ Šœaž‰p¸ ®"¾¼ôÐyÞã‹PdÇ^|¬;ô·Lz)Ø.Í3ìU%qh ¼ÔûCŽ€­È‰˜˜ŽoÖ‹ÛJõÖæî2T{ªa¸”Í´'îA°PóåÌqdû>ÒðUTÛùˆ]'=:â™5BÂfj"ZëÒ³³…¹!_2]ëuÉù%P¨ P:Dïx«) !{…­o»†˜²ƒ-ªiyÊS1Aí#þ—¢çeäP¦ç**Ž B£=<ú=ìC7­c Y’³¢"´\¸{ÄÝTÝ5ÎüDU6×e9Ãn+uU•ù-;ŸÎò3:j¥&æÿÈ¥}r$Ât@l+jVÒR$4Å[‹<’iÖÜÿçq)óŸq•t J/š¹ÙFšÈ¬x8:â>|C¿UdHRÂTÏÓ7tMЀCELH¯JzÛÞgÒy%W7”ηu?XÖ1©ÀÌe­1"‹WŽ×dЕD:‘£íc²¯Nœ Bí$—/r˽Ny¯Ö¦êF´©rO7&*T#RJr¢¥¡¨Ú²\!Æ’Ö-¥™<]­TLÄ,äd{Ñ2"ÜÈȪ!C{{f¢uLVZP-Ó¬#WN]Z‚f¬Š“‡tÕx¸¢ÅĹîÎf.Hªs²é¢ò(dݧޠ)ð/çK(.:Ó`I[ˆHîP®/U«u*Q´~Žƒl `RÐL@@v°ion=.ôöaMOïu¾ãÐ4ýí¶a‘öXV¤²EÓ`áµ´ñ éÏá†Ä²Ÿ«® <üöùc¬^lPäm(·wFÈ:L”$Ÿ'— V¨=õcîI÷V± Tj:Þ0Æ’8\ÖNaÖ÷ðÛㆋ“^ýDß@×ïÇ9ÜM~b;uÐ>V5Ü_A]ÿ|T³’µ’'¬tùÜâSL˜ mÜñcŸ[ Ê À|G÷¿ËãsïäÎ4ÄeJd맆ƒ×ï‡ [ü¸|£D‚æðçÓâøZh]@|D~Óë„dGß·…þ?ÎÙò¾Þ÷ÃJ †“îøÇ»>ºüZÜ0ä øFÑäÔ¾ÁÏqßm6õ HH€‰té¦ÿè¿,1cãé‰"xvñ¿1äô¿Ë¶Í²•©¹Ú9ßÝça?{b;^¢µ¹Žq§ËÔbÄdE5RfM')"æ%<^I  š~Mþe%‹†oÐïûèò>õ“¢ Ä (©úMÑúyåO7–-#JÈU/¢ãµ—ÌJö]33rN I#âRDæ)#ˆ=á V. Û÷ˆÇÅ2Ç¢½™ê*o3¡šFœ,» èÉç((á”LÄ„ñhñÿtš¦E¡ÝÉ\À ¥ÞT1Sbø@×ô&ï/²Û*ayÁ\4–ü’š€–‹}Nµf•kXæeUì#à¡‘Ï\’äRUñPU’g)lVݵ;ÿâL¶”YÙ2ˆäíE]jÖG ¶ŸËs6Û$ŸúC§W+ô¡–@à(®&÷ó-<çnÇ/òæ£Ì í: Ž`h9C1¨"` _ÖÕ(p/IR²êH¼˜p´Ò¨„zŠ ˜•ŠwNÒ+ëñŸ³«wrnܾt²«ªª‡UUT0œêC ÎsÚ˜Ç8‰Œ#¨ˆˆëŽóUŸ×MŽz×ù…RÇgwháÊŠ²+‰ $"(Ì¥`znE8š7%¨£ª’ =U šÕÏëêû{‘Xe%’_‰ý—XV'>æÓkoŽšëÐ<0`´B»´,±²HKiqÒ™0¢ibO? lÝ,äu ¨¥:Iº†œ±kPj%éËk_Ì/këá­ï~xµ˜h‚UUV£’]´U(²ªª#7,€®D¨œ«‰ :g*DUÂst0 „hér€:\uÓ]zÛ{:‘Ô–^CåjÎÀ9©³³¨ÞÌ@µŽœž§À±§š´oN¨ipéN 22.%.’(ËDHF DåbÞ"™Ð?_vÿ™SìÿeÙÛ[én«;r‡%£L€§QRÝEZ@™ eÔµ’@0wA±œUûNºí££VéStiz­ÒgÝmHhÍÿüÃjoxÓ Bœì„{ÖR2ʳ¢")÷2ÒN_E¾+×ÓQX÷ììS(G'œj¢"ЭTETEP=ÒU©Äµöz‹É¬½£{XÕµAÐkÏåÖE·®hªØÔe¼‚2µ­V¥K7pñú*N7x¤¼(‘ÓµË7K-íI*¡n´ÚTëì¿wRfôÔ3j}gó‰žÐJ³5ÒŠo$±ž–QÆ¡$jq‘r›tj”c]2\¤]Ôü4A›¹n~\~#sH+!Ÿuq*3V1õÄgl¢Ëzº*}ƒ¸©ØØZ$ù…˜îÊÆ vñɸhñ­*Y—,ƒ˜ƒVdXû{²'æÚT¤¤ *PHÉ ç8¾É€Ià'኱Øþ(µQú„X8Îÿ=-ËKøc¢H(Õ¸ìkh~× Âúé`¾)¯gV_’ÒMŽ 2¤(ì(†ºÛO­´Å¡ƒ#ÚŽrl™|Å’ÌŒŽ¢kIúzhYúòZ’‚{NJ½k?&Æ—RB°‰VRZ57¢æzœY£\è‘ä½°‰.§p‹:•ËúY8Báƒs*fé˜DÉ€ˆÜ #¯ ¼mòê_ñ”ŽœíãPSQ•ZÕÛ\³¦(zj­d¢YiD¢KUNw íóåÔJ:nª‘‰ï‡Ù“:Ìî‘U.ÏQ‘î"‰Onʇé-„wÐD7A·@Õ‘Œ(Ùz„s ¤a›T #NÌ–äT.c¨'ãµp³˜'Å!Ñv Þ¤Í P9!“¤Ž‡ˆïòþFœ=OþbXõPm-P¦aÐiM€ªéÈ&ÿü…Y§9Œ̾ÁuÞK 9ût\Ó™C-˜óG×3´ô|u)3OÇÉMÔåk4º/j— È.å‹Xx $WjR•@ "¤­ÜŒV¼íåÙáü¼ Y]vDü>ªŽê‰­eeðKö¤í“ÿý4æ&EG/ßä.VÕq蟩žåjHç ™û„b%ž68{P¡^_Ú&ÚS­%;ûGšV¶ ٌʥy5Õ$ƒOTÑ $ï&gÎκȲ•ƒ;´̨ÿ®´°æ‘ýmªÐ#düN)6Y±Agu)– -]ÉvJ‰Éœèηy;ìýœrŽ]žG'%ò‚!´z®á×0­3)i*Ò!~Œ*_ÌÓ3èY%×l’¨Óÿ¤Ñ`’…â@&ánT¸Jk^ÖÓ¯A¾>³fò"‚ÊiÎÊÔå1–ý¥ò1ý>˳&UÒ,ÙQLIP64dG]f©ÄÓuýq<ÉC Œé%QrîM¡$ÝEšdù̮̑ÅY›SvvÍ4˜‘ Š ©2B2º¡%S05 j¦7ö l¢lj(Öî„HÖVÎ\ƒ2:qsþv–“)Û ¬ª­ÔµüZ›vœ­A!n¶AÜĨ‹©Ðx‰ö—¹U•µRÚJ½•É\L„ª/nÏ9¨¸šDFçrcëà{­‡ÑóÎ> ¢:$ø`·!j:ùpéÌ-ð¨TÁ€îÑ8 ì7ßQ1GïûÅ›“p!I² €U8ïÐðån¿¿£É7#àqCª € ØéÂÇãㄼ׉•$l‚íUE˜ Q9ˆQ Æâ%ÿ†£¿ÎòDdå)œò´]*)BÅ©<È•Tú áÌ"Ф^£–nÜÄ9\»aƒµ#™˜¯¤”hÄD¢ä£†ä³ –:˜Š‰dâJbYôt Ds$Žá䌼³ä#⣠˜ ŽÈÈ=lÅ“dÀê¸tº$CB~‹hÇ4áé”sš²Hg;Of«WRóÕ*iõS—îE¬kˆš V‰¨ÙšAû¤äªuS^Ì2—U$:q¬‘§»iíC!ìËfj”„ÐTm~mLó;?—–Ùuä<à-ÿ¬ot”PÐ(©Ð\k©Bi±yÆe;%³Õ»A˜¶ß#+¥q ­yhB’Õ{+Jo<ôÙîKŠˆBV»)“Ÿdàh¸L§¢³¶•¦_Óî¤ ¥/R,9M8+‘Õ_QGŸ—¢‰JÐÔÌ‚)÷ÍÌFb±’±¡{8d›IüÒ'jÌâiQÏÃËÑpT•[9–OÚÉ3!K5ÊŽªòÒ-Û•K32lÛ2v¹“n^äWs8šã4*z ža¦æ'/):%I<ÄšQhæ±Ò3oæPާ鶬!\ ²KË.V«;rÈœD;÷1ä%cg›ÆÏÔË„dzÖ­CAµ©ážÇCçJ=yS6Ÿbt¡ØS ³T\Šê‹s¨‹p\ Ø;¥ü¡ZÖâÖãŠRÜqJZÖ²T¥­D©JRŒ•)J$’L’I8é0@J@ H €ÇÁ¿lº²šÎÄ[4¦(zÍÞaPpaAS…Bö—cF¸ü¶ ƒ¦Ó’ŠVšŽaÒ,ðµ:•aÒI¨÷Ê6;“:|+{k‹ÙÙ׳ÝqÚ0à2£.Ö¦ØÔr1²ÒD’¬žÉÇÒÑ­ âב]Ìã˜62³eb©ÑIˆ–5ü‚‹¼Dˆ"(—+²’mŽhv„Í|ËhÙvñõÖd×5›œ‹9nÖ¨ª$ç áDÛ´LîEù²„jÔ‡P¦9[ QÉôùønež]…?˜ù™õ‰!àj'rv.•N›{Q®vú’²h?M—`Œ;KC¿v¤‹w,ÐY«uܱÊÔÎ;›³íîÍ?Û_¶4d5›V¬Qå.7‘_˜<Î[MR€¡º¥Q×\¹J…)J‚!TþÐR#?Ûœ³+rULÒCµ)›XA¨qµEÀx 3"ã¼F¢â-ÚÚ++d2ör”ìË[å+ÜÁF7–3^¼§•ŠŽ¦¢bÀ¹sâ°†fùÛ%"çý«Ö³Ë÷˘(WYYΣ[V¢³7"é|¾Ë:&“•’ͼÁϼ«iH™”l[RTîžÍTu#bíŒI£Ý,îT‡­Úî—Tˆ$ª€ÂíP×YÙÆ‹Ë¼ƒ[)éºg,3JˆC.b)Êí9J5ÌtŒ‹@ŽQµFœ›Ó¸±.ä’I@PN¬Z®‚Æç§ã}Û­…ü/r¯(éj¢Iü†|fQrë4§ÚID:AãJy™JÊö”¡,MUÀEÅ.Ô„d“˜¥%Y8]fjªÑ×=RñRÖ·Ÿ¨t©n8¥-Ç]ur¥­j%KZÖ¢¥-D©J$’I'ø m„$”€”¥)@€°Å7í¡øçEŸÐ£âwdQÉL¤(X;±áç>ÝèvW'í¿göA¦šÊözŽ)¨SKïöjØr£1R—ýNÓ½R(_ŸÊõ"Ñp€Lëc^̪²6ksE©uλRÞøÝ)¦VêpJÒÙyÒèG)ÆS±u­I ¥]^Ϊ² ÃQ4ÔC7rË€¬êEÒ‘ð"²žÖÓ£”ÎQ«OæÆ`çÞoætF{öÁ¥ÉžvËåj,²ÿ³L3$x*G³vS,c1"ͳ±YÅ~dä8XEãÔÞþ>ÝÙß‹là×ö—åˆTµ’ìÕKDÎí]}UmkªdïR¹B"æ 0BRÌé{Œ…ú…U]{Ê›L¶ÓIÆKÇÎ"Æf¶ÙkOóŸ=æjšO.PÊ9LꑤªJ²V ´Œ‘¡R›N„©¢Ñ‰dò&aã$d)ú±É™“tÙà-ŠÎÌÔŸý˜Ú8&úiêª9víÂΜºXEEWráC*ºÊœmÄ¢ªœêéŒa71ÇÒ§â9X5aÙ7<«ÙÇÒõC!”0tKZ’¬ZÍÈIWÕm )Ã6tÑ’K¨Ò¤“v›fÌSR=^º‰¢’ɇÏf¨akOƒ«pŠ€‡k€i¯…¼?æWüC´l½Õ$)-¹R©ÐˆI“òø9mÕGq¾nò’ÜLH$OÓN"qnÓS@ €Xö¸ µÓ§ØwÒb£‹ÉŠ2„1ù[Ñ™MútDÈ—J€FÔ±Ép9x‹¿õI—”ŽÜ\ñ¦tŽÈNN SLU˜© aÓnwJÊMEÇ&ЪbèÏ^ ØïEÂÉ‚¢§v*$‚Ê ÆD”0ªî*ìÅ j•.pTPÉÃ'L ´Ïhs2 ­ÞQr"¤,ŠBM½n¨É8IºUZQŽÙ9"k;¨ab ƒ–ê\ÿŒ,ä)‡È›]”æq›T Ú(¨è•’Cµé“¤ZdÄO²ê=Õæõ…1 ¥¦lëù‹®¼'H¬˜s}'LˆËnέóg7²ì­–s¥—•¥+[.rÁÜ×s]CÔ‡dÉg²ê0ŸNLÿé¹jpáã™ó…Ózå5J )óWÛ¤¦ó#·þb;¤iHzF€=)M³ƒƒŠ‰bÙÄU7ys>êE·t3Nd“wìj¬EÖLî bc"—sòj€ˆÏ^Ø]¡s^©žÓ.©jG%iŠR·i<ƒ¸Y¥Ðÿ™Î1ÔÚíX»i—Гë·xœ‘⛾`d™(édç•›e˜]¢3V¾E4¢*lǬçáÐH@Pk 'QH<‰fÜÝêÁìí#UjÙ ,­HÞ¨>øòÿe¹oñ]½ÙºMÝäœÉ‡"Fëk 3Òø×&ÑÔ{6M^äÁ­qÕ¼†¦"+ Æš¥'j9zJE»æÒ°.Ú°–bØÑŽŠ ´xý„£& ©L(¹QÓ™¡×D@¦P§-Þ™m•ôõEG¶í!P3p¬ ai©·”M-˜Ïd]Ón[°{I:bžjý¼›VKÆJ•AºÙ¨;|újRÍòÏ[fÍ Þ=c¢íúÎ#ÒQ7ÿ—4×j¨¹8;(ð´Mq±ˆ%P9qyÝÆÂ:“ŠüŠŸ•¨§a몊œšmQDB¶‚ŸB WW»rÕ¾2'h*¶ÿñ’ˆ¬fÝÉHÑw& ›ñrâ×ÚVJƒ=Ó “´ÀˆOv3\ø’› âœÞà¦a §f ‚¬ÿRóŠ•.uÞ4´Q?øBys‹â.í0•m´.jWì{ZfµkLÐcš^1Åf°è=üŒ²Ph¦WË …q ›U”JD¯Êdb-!ÀfÊò‰íÛÃ2YïúÔŸH7”ï,ò…¨ótÌ’k¨VÔ  ™# &p2.Èa+¤Öc­óAAU™}šôµ0¡iú5hZÑ&Ñp“rÏ›ÏTÛ¦Œ™¸Î’n‹W²é41Ú’4é%hÑd%98ßÙyê§{“•&‡!€@Å1w(…®ÖÃpµ±ì3bò=¹Û$dÙöù£4Î:Ú÷¥¦âH6ƒ:aïl3j¼Ÿ*5tQÞ‡™PÞ&Þ‡Ûúó¶D¤ëÚ’c4‘š–¥&è,³šgšÎB7‰”£Ä²!÷J›&-ȯ‡ÞÁæÙ£Û5’«8c™PŒ¸Eêºa”¹4ÉÙl€¶Et×/’pDÊ…#5 U `P`´Ö+§Ð£ÿÖáõ¸ü?¡P„sPLGBÇ"C<’t“TEASºKŒ}õ×2i¨¡6HáÁÈ’†M”9Hq/öu_᫲zzŠÊ¤TSÒÒ0íMMCÕA,±NÃ}ëÏ:²! ´Ú·¢RI×;[´¯8ÛM–Öã«Cm¡-ï)n-HJ”‰•)FIV†qBæ¿mÚu¬{8|äpÕÉ'­j+.];ŽEÉ•/ÞR>dxäQŒ|áÌkqTÂÝ¢Bá"÷1;fHËNN?Ír»•©ViÚô&[ÏåG‘¼I Ü F®UQb&Ù$S9ÎaP‡Å«©rö¥§ KrÆeÅ]T•‹cäEêNEÁÛJA)DcišÅ)Tp*ÑAdÍìvãàþ\MÅw¤”‘§˜;Nih20;§îÝ.ºS¿r—åÑ[ƒ$–AV†QW¬gDîˆÜâdÌz¿þü,ÿXPÿõo™ÞLq¿ÄâD3>ÑÏþëxþ-ðÝæçC¯3­ñBëºs>3…Å4žhÖR2¦Ƚˆ@ÌM\L±ä–9iÈX€vwÑ{íΠ5îJ»Žó¥]•ÔsFCÔ‘ŒREÃçÑ …²í®ÝF`wÇz *ð†Ið‘+rRâÕÌ•:¯2e"ÊGÙ\.€:bs¬ÕÏr¡“Ûd‘TÈ,ïQ2©$qLÅ1Ó!®R»cRs­¤ÚT´ÔL ·CØ[2«*jI¹™S’oS¯Ù‚®˜52EzEÊp¨#ÝŠê‚’Ñû;ØÝŠìWo+6?¼_ñ*mžï.w›ÌÄÙܤ…"Z*+ RFô€Fd9îk›mfJÖkºŸg]t$'wßþTd½‚x‘¬Ù!M·‡…^®^€£UŠ«â§?J“¥UXÖª(AÅ,Î-Ë£9—ö¢ªgghàé(Ô)Ò9± v鈣¢û:Ui°Í ªfФ\&BQ¢ë¿s˜T¡žŒš%ˆŽ|á´|h> Û¶UöD—|/Æô^Eåê¬çƒ))—Çd ¤òFYíXñ±¶YoÌ<³9%ûÖ ¹Ê±{µHtÈ âbÁ™É˜™eÚ‹œ%uOÁGš­F2–zœ V2°àº ÍŠI·x鄤ƒH×-dS,TL²ã:jùö‚ÐNI'À8»MÁð8­™ Ä„¥ 9K{€ÂÁ¸éÒá ï óÄäv·ÓðÐzkýÛž˜ƒ;;I"êšM¨•D§ …ŒSÀ b¬ !Â6Ü-|Y#µÊ6øßo=?¬z¹Ù›LÕl&Î9LR´`{°@PBw´ÐÏ |±Í™ú–Þs^—$(¾­l`éãhŒ7ÊÜv/Ãqø…ðù…š}N71* SŒ’MïæI2g—™gŠiAM#3[%Š*-äÛ¿£¦v©Ê¤ûÁ ¬i¢Ró/¡6GgyCŒ±Qœ>‚ƒV€Å U”ªp ·^‚?#®%´¶lTRà¥h&Å’aå8ܯ¢]*œ›ÈVŽï˜é5:­ª Ô#pDü\ ÌÉ2·ÝA åOk wõwÀ2~ì¯IDÂe(—Ø\Ë=‘—;1áq«¦G÷ÊU*ŠG1Š™¶þ ˜u"i'T”CªUädá•Mì¢u²ˆ¢FÌ\9Ud(´JÜÊŠïàvÂuËÅUÆ9Õ*õZŸ8ê‰ B1D$Œ4h?RÇŒ#6°Æfc{g³™ˆg9“Pàc&c@Ææ}›¥öÜó-§‰ßªjG@°O” ü¯°kÜ QÔ,ÿKJø‘’Ô( Å$ía*a{\9mÈBãmÃÄu×ô±®&Ôwþß Hrf%ÃÈÁéòÜ=mm±ÊœŽÃkè#ë·Ã3´ÎÛ ‹ДÅÅ’”-~|uŽ•ö^™Vñ*“n Ÿ#>s†Có\G]úïÔ=uùá¶àu7->ý>X^|`^÷‡—žËÌ=ï–ß–)\Å{ËT‘3ÆÑúpŒK©Äˉðåä&/‚&˜|íðÓcÓ~¡óǘaYˆ°:ê'Ö¸Z€úaƘØåépøí…¶†ÖÖçoŽ:|¾XXjox5ÜŸ ÿ|ñ%¢^êÓ}"|$¿.'Ï Ï'_ðW¡‡Ìiõ-ƒMà#· üq#Äâ[x ¼tû鈺<ú†Áaµüío!ûÚø‘â–—õ½=žÍÔ¥ nOößÃt;~Üq¯A!ZÚuñN§§å½ýê¦tŽlGɼiì«ḆLµ£S:覲ÇQ äìÛºl Œ˜‘t×T†1ãŽÀDeµ3&›×Ö\ÑxÒ]™¤+¹V™gMKÖ‹µ3…i'-ª + üH¢qÏÙ.áTÈ*=áÄÜ Ë*­Z:«¦ª”EÙà&I™£„“]h¶\‡]ª©+î7 ûÔ { ”â)ˆb‹ô ’ÙùÚtcjÙ ÉS(2:F(gàM”5:jfîa5{G¥FAò.éJi± PEÃB‰Ulé3´~E–DçN ÛV^ïñl£:JJ©krÄQ)À JjèžyjBÂJéê(M·‹n‘;ª‡’}>ÍUHL8ÍAt$Ø–BÕ¡AFñ¼žc5;’ÙËG¸«i~͵|8Tq“!•Ùž2Õ[{d’mœ*ú)ÂsUÑN@®G*ÄH sƒ9#‡0í¨‘ Už~9“ÙéGsÕNbäãzž¨’š¨TÊ*)*þh)hǯWy „ËÇÉ·l¨6GóVÑ¥"h¤~ôî«YkTvjÊiÌÃËl¤¯dC0ŽR'_Mg[PU¹Ë˜Õ;h¨õ¢—Eó“~Q)ì‘‹¯“J}t#–ɦ‹T1ä"!’žl¬ªªÈË<–—™ÿcjžXêGµU¹Õ`³Ã*¢ ¤")ÞNà,DýÞ¬ögi³}‘Íéó¼’¡õôÄî)ÆûJJ¬RãN•$ô…_ Ã/¥Ìé—IV‚¶\‰ QBAJ“p~#¦9…—Ý™ªy„ÛÊTQ²Í,ºéƱ‡píLyG=F=S™.ñdcÔuÝ("DÒ5”€Ñ´3ü¼‡ÿR=ˆË¨V§ãÜAÂD¹{<þ9xó.Áæ…zX×>Ðe Ý# Ýñ‚!Ÿ¸–”©¦Ý® iG¬A™€ÈÈ4nµPü˜ÍZGNɳ6¤HOíd˰Œ"ÜÏÏz$žÉåÌ=%Pæ÷hÙ8ÂÈå¶PStªÕ]g"åÂ&s ött™ÒôüŠ®[+"ýË´Öfݪîš&+$Bƒ¾Úv‰µ½ TÓTí6fjÓD•¢Š‘–Z¥¢¤î—TÕ3 BK®n¤8û¥ÇÔ”!²çvÚ”¹NG–d­¼¾Ÿº.]ukS¯;»ùBœY$%7„'u’ å(˜ún5*%¡ó{:ëJJŸª!Ê…C®nV S,©˜¸÷DÉÃ@¢õW«ÎB¸p™! Z*i7*¨)ûcnô\æ³¶íWHfŸkغ ˜¦!")GŸST»jUj–®xôïj)Z‚9ºMŽIöf4Ô².[¢å¼œ â..2Ž—êolzî±VZ¹_;ÑÙÑøŽö€§e¥’‰ž+:Ò•ì§M׉·rgОšœAEØÑá&UR ¡¸Íµ<œ ¶SZÉj5dÖ4ô¯z³§ «¸9ÕYe•8¨¢ª¨ ˜êª¡Ì'PçǘGìÿfŸÚ]¢¡¦KdÓ4ûoU8G¸– ¥IÒNyôƳ¼Á/8Hï‚–Ó7*6ÀMùyȹ4sbEC2j[$‰40\Ü!Ën¿Å±h;7ÇÉTYÝ—Qð† M#P'1¢Õv’rÔógÑgUªMEÓ,„s`2@'*€<IrÈ)SR’"d)lãpéÊÝ- Þx¸Œ"늃5W“ 2Ÿ5ób¥§à—V›m–°pSp´Ýc&ù“ fw5’¨¤áYÿÓ†Æ4‚òŒ˜ÌFÔ[0iå7F2„ïM³Ú².ÏvÓ¬7ì»9]IJR`!úŠCEJ`jï4zÄ×ÎUBªÌó/ïOy^Ë®s(C‰uÀð¥SÊdòÇs*¨ƒËÚÅWÒgŸp¼½(ÆÚµ8Ô‰”%%K•Wˆ:l± Cªí¹l(×# ³¨×‰Óô5gLL«vËÖ?êgsÑ„€y ÕñNØL(eT/ EÁ[ô…톜–iv—ÈI‡ÏŒ„¤’€üº=IœÝìù+3T5§£ãfÝ·©¦òÞigäc–g]š3r2)ºE ‚âÅÂ×@Çp§Ú¿ÈÜþí3BæUå½+IÖ5 ÅÙ/P5­£éPMÌ2“§§Z#RÁL=N<ª’0(„±Ú¸]okb§ä¢F/~õSçPÆ9Ô9„ç9Œn#æ6§1Œ"'¸ˆˆŽ'§¯ôô븆þ›ó븈Ž;²åŒ¯bؾꪜqã­Å€'ÀC¥ô«¶„œÙzØJ: '@m¬üBg‹88¼Ç£ëÊ24”„£“Ñîž/–ÀéšÎÛ9MÔ“×I'Ç èÉ&FΣÖ|в;€!Ô 1#3R™¤)¶O¢¡§jApwÎÒ+`n{çê¼p±¸š#£8ü¹¢¢G*¦‹d—âHãÀ6/1SÔ?HûU4¯;MPÉu‡Øqm<ˈ2‡u²•¡i ©*ƒ‹ hCˆSn!.!`¥hZB’¤›¤Aˆ"1Ȇ_„ ‰ZœÿôÇ5ÍIQéÆËIwùΓ%Uj´jEpH”fé´Ù³Qdïݪ¤{WD( ÕU u õkøm¬¬´e2÷1]Õtû&(JU5E1Ê"—ABÆ­ªÉÉvʸöËnòŽ)FÌ‚Á~‡Ô™¡8Êšž¯s*in¡’RV\È·¡iê}Ѓw”z@Rb±š¢šSQw ª$)x€)$Œîg~&‡Gdõ;[åg`:,©×9‘›‰RÒ´ ¯h)öê)L«Ê¶b.QÓj³t.¤¦¦ã‡r›²7X=•Š.-毱B2ööά0”Òâòì•ÚÄ ^æZºÍí{ß÷Ò,à’ ]{²ë{¿VTÞüÉH~­-3vSPônnsI´IT§gžÎ¹«0ÿ³>\å÷füõcG+Mæ5bØÈ+œ’P¢QÓ+ÃU™•˜I"²i\L¹EèR´lœ ‚¦ÂiTž¢‘ÔdÔæoT?‰¬ûЧ{Øæs/¡Ü´=5K6ŠÍøÌÞ€‹jÍ]+/(áùaWI”‹u$EØ;«ŽÈò¯×pÍ£Û¸s“9M”®²7³gbìÂÈü¶yEË2­3«&3/³~MVï^SpHi ­'3&¬vxèåæ1%˜1Œ®$‹”QYÒáòÛ‹ñIͼþ¦*^É™GT×òiIÉêjÖµ©šÕ™\CE®©GÕ„GQÓ²4°I51äeéy%"ëF¨4#EBšUÂSu}MVq´y¢êkj«³ŒÚ½Ð]©¬}êÊÊ—U Iqç”ã« BS*!))1"mªZ pÛ-3KLÊNëm! 4ÚEÎê‘ÌÀ¹’o«w=²ùGðÍY'PåfbÕ©3ÌzÔ™‡TRÌêz˜c]¦í²” D “yi(7r)¯ .¥&Š"ÝÂé‚«9*†ÄGÚ÷4¦hnÉ¢kÖõXC°¤òZ¬’‡h Z?{Qæìì{§®WQI÷rS½s w0H‰Ž¸¤‚«¥R±ÏçÉs:¦¨êZ›ðÈí§=PÂ1kN²ŸœìÏ—õš1åë(!CV gTdýì_¸n᤾\ϵíš¶]‚ =±±ÏÄ&¹Ï*;°S|©Íl³Êšò«ËL²š˜ílØC´K˜nÞŽ`ʽ£géj”ÌQ¯a²ÝX‰x¬Á…qR% +i)–’'x͵ ©IHT æIˆÂƒ`O,rO²lY˜±4KÅk˜v°†¼µ°ø‡a×P]!Û½ËxêÊQ7ðt¥iUM 2NÒa!"âeáy·¨UÀS`R¶hõ‚â›{w†ãŸç³Ã"1£Ä-¡}„:ïµ÷åØnÄÙÓLÓTõc@URŽuT%o œ¼ƒA«^¬FpOiÖñ±íÕq(ñϲF¨"'\H¨,D6«(Ÿqí¾MPßá“/¢¤BвúœŸ9­m°T¥SwŇVR›”²ª¶ßpBin* …=”U¡]¡>ë¤C誥eJ6J÷´¦L€¥”„u)A"äÚÄ!àªH:–Nm²¥„„Ì¿ÏÁ‰âã©ú6j9„s–™e[™Ôƒ$»ÇW .tˆ)?Ð'L€¨3J„Ë,§Êȵå'*ÜØ«óO'2î—TRlœST”ãÜÙ§˜'&) iZÆ9Ü]iKª¬ƒuV’‡Ÿ§YF¬æaºøé¢5;#¥8Õ¬“zx‘ªîvB>MGññ‹/²fÆrq•3*$p‰ÄÖÔ×" œ a#f–lÕôì]MÜNÄ«™•JÐMiØö.Haˆ„Eâ®Ô˜‰]r&²¦\çÁãqTW-ʼÚG.忤béyŠû0$é·±ywEA ëÙ™ó;t ,OöÒŒŽgìè§#.w(“W§îYUº´™m“’‚)fŽyåÀçÎuÕII̼XiÙ( $ó)A Nž-~ò> †T¥nñËǪ«„ÎFŽ>«üJçÅûEE:W(Éò,¶‡vd_UFfµÁJn¹”Ÿô¡%Ë`)=—"+"õU½0d¥ºp/x eDu'óE¾fäŽPæÖse%-•ùu'UÒÕEyWKLRSTäIÂMH …‰R5µŒ»7’ì#UzÄŠ‹Ù2Īg8ºK…šƒtÔvb…Ça× =~›Øzt;·=o›n2‚¶«êˆÚ¢¿Ö©RôcÈWÙ‘EÊå“C;”QÔ›4½=UIK7xý«Eî"ö TIuŽtDÀCQlnV4úg0pŠ…/­Ã¨ÚÃkÜzm„‡út«né«M.: Ð(ÂSÃ[àý¶pŒ™Æ’}ç”Ä‚}|m‹¯EÕÎiª¦ i’è éƒäÅ×'xƒs®Cµö•“ TM¹WÌŸÿ¨ ð€âúÔòãIÔbêHÒˬþŸlÉûxõ4 ‘÷ò0œk¢º*Å2Ž)ÑîÀÊ’ r _ryßÓ–÷èÞܱahîÒß•IRfuƒúÂs¾žŽnåTœ®•8SáÜ*C·fà³p ø¬©Å«øžÉ]ÎȶÂá–²æOš”JÔÕ+¯{F_P¨ë©v­—`*©Çõˆßg•i¥]nVê‚MB“UN yÄ 6ú/r¥6––‘ý­¬ð·KÌ™Vn OÔ²bŠ(«P)2æM‘}¢îÜ‚.¸Ñ1Œ(ªR)Ëôâ›ÍörZ¦Rw.ß8ö‰÷©8—¥%{³ïå¬*?ˆV9’EjsÜîXÈ6"h¨eIð$b·Ng¤³1®e§)RÂUðrtÜ”‹v+*G fZ~LŠ©¼IÛI2¡!íp,ñ«r8îT:]àÆÂ*胺”eŒu£¦»§©I¹z ʉSƒJG€X¨ T"áXlWI£`VÙ¦Î6G8¤Ïr:‘M_F­æÔ¤%Ö–“ù›uµYm¬P”¨j•$ÁŘeô¹+”u÷Œº!@ÕÁIPÑC†£˜"Øm'—UüÝÛ3&‚êGÒg•|GÒŠ¨Õ£“ɤšò)2lLéãÁQãælˆšÉ v'L Ýšõ;´þxÈå¦^¸ƒ‡‹€©3 …iÝ9Gå‘j»U ?R“„ûÈŽª ³V0õ%Ú¾Á!Ü›;§‚4¾hWéÇTiº*Ôí–î%{:¢$*¦*.åpxÖ¦p%IÓ÷­ˆÑÑâ(9xd/Íø´ªŒÛ­UÕS·ÏÕp°Š>ÞñËÿcfp‹vs©ìèuO`à!×Ue¸ uNZlþI]Ÿf”™}Kq×^@*H$6á+Q‚N·å‰m[4Tî>ò‚R”“ܘÐxâÄä|ªlK#$ºª[ Cãml:i¥·¾¼ñnØUS »V›…wQ̽fx¸èv€ÜNéó㦃NøÎWE4™¤¹Š«õø”;vEp¹PXÉ‚f†)ä‰bƒD€©”¥°iïXGK!~º½¾X¦!ÑTɪ™Št•LâSäÄ1l`8\¢|zGI² Ôök_°ŽT)NfY-EªžQsr½æ·éê%JPb±-:S©®(GsE£?g9 ÂiêÐèm a*mˆ07Û*H6ôE°æF„3Å]VùéR´«*‡ É–ZR³Nà²ÖŸû¾áa0‹Ùg¨*u½°îAvÂS™#²U>J­)PRsk/#BPõ\9ÎvQ$§#ª €Ií $¿·¤A§|S&íÖºŠ@ ™‡‡Ä…G)ÄÅS;c ÄDSSÙ[µ2j7&2¢eT:aÝöxšáEÝf×ó´Ìdz˺÷&v¡cØÿ¾™¸œ83C&ýqDä1û°D›ÜT7ù¡še•Ù.cY•ftÎRWåõRÕÓº!m<Ò·T$JV…[n ©·[R\mJB’£Ðõ Õ°ÕM;‰u‡ÛK8“!HP‘àFŠI‚••AqMÓÌ#¤«Œá»)UE¸Í5±cÙ¹;…&4gz±Š)&r˜]Ÿ¹*J ÅÀ‰Òp™Ç4¢èÇÔÔ%'H‰PYÅ^v’j&Ñæ)ÅqgøêÄÚ…ºÊ92%9½Õ€ó¨H:i™eó:¯ªj…TY¢ÊGav´0?öÛ·´S"¦ýd#•2+ÚD@ c "a0aÁ#[#<›u”fýŠ@Íc3¨1œi‰ÈbEPº°§Lʉ>=Gœ«´­¼Èò•äy>ÕgvV°¡ìÔµ%¢ØWæ T%>ÓN9l ÄIÃuNA“VTŠÊ¬¶•úAïo{x ÐOv³þô*m: )3JRÙ¤Òª+©61R¿©ˆ¼äÁ tÖ4r¯PIƒÜ9L(#Ý îŽÙQW^<•‘zé•ÅY÷“.ÖDýòdD T»€U¸˜È¤™J^ÊP/ R(ZošÉKW !` gP´ûI9)‡)ª ÚJQB™ƒvI*U Œb/Ūðª$ŠF‰¹Uâö§p Ö{"àµd^ñC€6H {”Æqœ¤ð˜Æµ¯¦!++RŠÜ*RÜ%jZÉ*YQ$­J2TTd•I2I8vNè©Â@  @a÷PÔ/•@ÑìV+6ÍUu$¼h ( O¼\о*À ¤˜œ©•Ãp(ÎWϤŸÊ(QºráÉîn3×TëÜ$â1„D@…âˆlìë¥*˜)uaÓqGGG*åÄ™Ð;›‘qf cÙGþå *äŠ.¢ÉLBœ„•2™+÷FZÖëçËMïË­úÛfTb«j)–¡)¦BÞ6Ÿ]xa“hîòõ‰‚ádpãúaó0¨Dt°ôûð×PóFŠ€‰¯Ô@-áÓæ?çGôʺ›Öá{iý}|±É)©‡‹¨h¾š€Ž-½©¨—ƒÄŽÓñ<Åã9j $ñ•º[¯†®Ísiÿ°ëèô!¨71þ?|*96¦ðP×êŽþoùÅCZ²¥¨ó?aô1êq(dXM­o8t?LDG®3ŒÃRÍã—ù¬/P yzÿ{úáM¹¬>Wø‡‡=zá%3XmÈ}5ý¯ü`òg°ƒm„?Ÿ®YB§¨ýÿL"Zg{ËáO‘® Uá…„C~[[â|Æ»)D5ûÓÏŸˆ"ÖÎ8lÓoÞÞ7åû­ØCÞè?ØuçÎúˆbc”×÷KAÞ5:D7çxw8j©gzmÏŸO‘Ô}8Â2S‡€8¼:tÜ:·Þþ;b÷öWíÃ[öf|›‰fNY¸rgT$”š‘®˜c Ü»¤æ½–@°«¹TS]û5cÝÇÈ™3Ù&/\žL¼Ìe%Ãmv |G_Ÿ-~xv4•¸ ‡–ãéà7DyÚዯ,ϲ×2¬Ù”TÒ¼J\ü͸ŸÈëNÛ¨’Rãe*L U ©¦QCˆ&Ф‘¼… “iIh`ŽÿKvÏì?Ú:™“ŽÌw14lì²Äa—9”Âv š¦ÑxüEy&™쑇)ŽšÏŸ6©šÊ™œ‘¹š¦QHϨ:°\ÊôËfˆí-—ÙuBLt²Ù×h ¿w ¼sû‚ÓsÓÕAkÈØU—]DX·‘u$”Ši¤UQ‡Î²©Ç¾(ƒ„“Ráa1€8ƒ® 7祂ވKÑ”óƒq²a¨ˆèPþµÞ×é½±Y×ö?¾â—”æ¨,¨’–ê€ßLÁ ßHH10$N„“7±µ*iÎö…MØ$Á˜ãÈN>¡ê^Õ½‚rî rjWñ¦*¨ç!$Æš¢è|¨ªªÊɪ"Ý&$déÍ.åzuÛ†« w ê h¨T¢¯|Iw7!ÏÎJ÷ñ ‡ÊH©ê+ðÙÈT²¦b¤MTªÎÒY´ŠU–jT¯”M2žf ––SBSæAè½sIùz¦0F’‰v˜ðò8´=:‰€ÀÝ=úDCï]ÆÞzÛGDG€ Òá ‡K‡¥ÂþÖÛQöCPIÌ36Ø ¨27Š…‰E‰˜¿žîÓ£wù4ê*:oÛ]tújñôÕMYÕõîcÏÌÕUeI(êr¡¨ªI'“3“rÏÖ¤¥ådUpúA륌e9r²Š¨s ŒqÄòÉÓxæänÜ ™HZ„…«w½}P]pÛUZ×ÒÑ®"Õ®UfNw• $È;‰’8q’yÍõ‰Äœ7q˜h#~ž~zâïvBí—LvYg˜ëÍQU5dòµP©%S!K‘tÂÓ.ÎÉÓ¿b|áfÒ.emÈ€©³Gfç(œÜÓ$Ÿ½ú·¸o÷ÓBDSO0Øy}ÿ_›ÕÑmWW”fANÑV% ëiuÖŠË/3P×¾ÊÐà y¦ÔBT‚wV J"•§¨jªbóRPJ«)µ{«2P¥Ë"dA“ÌÆÍš”œ=•ÙGšYw>åh”ÛÍš¬£+øÈø¹Ï\1aQÒNœ4üÝ&ˆ6’rÍë#¹5Mc JH·âIÙc¶ŽYÕf;Ê@ö‡V ±YyŸ®³Á¥i§oåã–ž’›…£¨úZ“˜$¤aYÄÕS3jÙÒ"d Š+¡Î+µ0q i‰†â7)u·Q¿®¶Áu=“~í-Çþߨo¯þ<©×{+ÊÊÑ™:”JP. &TwŒIžs|JS´•$A§I0 ܘŽ™ááÙtÉHˆ°"åÚƒ·ï ßè7ÃÅãÛß_-6ÿi¸è8KQÒiÄð°MþZïá„w/¥Æý9ü9yó×Mq:§u¬«-§ËYp©ºf«{Г}x‘Òp릛¡o¬Bœ;Ñ&Úq›DGîp;—w¾½Fÿ_»ép²J‹ˆŽþ¢?AÓöõ½ðUg":Ü|6 |o±ç‚¢ ˆßO¯ßË oÕ•¨’uãâ:‘ÏÃ]c ÐÔnWû}øáTŠõÛÎãè?ßò M×è>Ÿ·õ¯†—ÃlªÛÃ×-þôú©·PDÀ??æÝ5×j¤¤ƒ<µ6áåÐÒ6¦üúx}gKáÿà %4ß[rõò°ìBTBÁÄ!kl 6ðò~AËLFH»à°xÛ_/ Iý†üWׯ0½¬Óž%9veÝ”ûÑ¥¦yi}xÏ–Ÿ§ Ü4Ö|?YåàDÀÆPLr‡îÚÚí~¿[rÿÊ[£êiº~^6¡¦&å)ªŠoi‰ƒ~â2R=À¦¢&U£ÖŠ$º"¢*ª‚Å*€›†êª‚ÅQN™«4{ý@DÛü5ZoÏÏÛem Á±#$Lp‰Iµ€yì!¿…ôÄ5žÁóÅ8¹ Z‘+I$îÛ‡‡«;+lèÂe4ïDÁ›XÇYû´âÛç·d[š4sfxr©YwÏ›QQ´õ4ÕxÕܸUŒMG!KÂA;©Ú1Aq!›ÊFN×"o´YÃVj6`eÆSBÑÆj¼š'\Å:GrDLšn ‘L±QUT–M5LŸ$s¤©§ Žšr “L§›Vé&  JPä` ´ó°éçl™˜T ˜lQéðúéå‹·a;5Ù­ŽZkªTœË2H8vÊ¡7m7…^B®G=f!œçõù¨,¶ =9"R¼¡"Êpf zãªU¯âÖÂ"eãæ™O]IÅÈ É'&­šºn+³‹,x9fçØ<‹PUE“A‹‚²L¥9}˜Ç\Ê—½¹ûfJvȆ¡©–™qUR)Ó•{ª¦MõEV CùšêD;̘¢É¢Ù"«å@§;ÕŒgg)‚b’ÞA¢‹ÿ¼TÔÖö8_Køj¶·ÜzŽ”,`ÿ¸›tŠ#c€ÎÁkxô¶¶Ä;0ì[eW˜{N]Võ"V…¢¼v¤$$¤ÿÖÔ8㊟õ,:FXÚÌÄ0¨i¸AÝÔ·¼LAÝBBDka¬M°­—*þMÉ¡®™È‘x€tÔ@4Ôw¸ëã釃‰e[:e"Í@MäsærlVÐLƒè÷)2ãê-ï¾·ßåÏMqÎEØ–SWVíVÏf‡–V(_%Ö™Þ2PÊÕ¼à@2Vµ‘`òƒkª[i-×3ß­ ùuK€.¤ˆIW2“<çò§íUÙ/£êyŠYÿhnÔ¹ñ',”µ+šÓ5]]”p”Äši¬U¥ÒŠnõ¡[ ®ŽÑÒp!GM1|“>éäŒj¢C«ÏªÞ±Ï.ÓLöqV3Iá#Њ‡EñZ5iÙUÔnÙŒ²j¢¨•ʉ ÷(­"º š :QM9 Ržjn"4Já¨{¥ ®:yZÜîÔWjЀTHDÀ»pö£`¿PóÀv{±L¶’©ºŒó2MSM©*övFêWR¹s¡×­Ú×Ýl¢‚Ú”#}fH˜}N.&Lv’Ë̅ɸ  ËúλR² ‘“*®6"\;¨ä§Ïò‡TltÞ•7MÝ®¿zä]*’©¢±PMÃXþ)l«uÚ·šÉ*Õ:b \‡§jøV˜f ™>Þ…2»ù‡EîÄníÙP9Ĉˆ×¢n¤\¢U,`°€ðþ÷ò ­·š@¨Ä»¢—=D·¦ž#‡}¡ì‡d³ÕÕe¯¹•¥å-ךC®¼•¼â÷Ö´¥Õ¬4’¥–Ûm €”ÂZ¨ÌØe-Ô T„¥ )JH$Ô‚¢ª;Ê&äÎ%ÞÕý²_v‘‚¡(êo&ÜP0´„ŠR†œ©ÛÖ“o‚.Û/ìB™ƒü‰³´VfG¤j«…ž–9ªnW:i”€Û¦e~TÛÚ@J $0mk†÷°Ž¼·×Ç $]Çè‚VÒÞè[Ÿ!iËkòæpòI”–LJ ‚ÖÞÁ½¯ †$ÛSlªÅ&híK5{¥m(±,AÖ ¸|0ƒ:­s: —i’Úš'ÞÉ-Àùp×ÂúS½¼Ùe=-¦Y¾ªÚÁDFE•õHTZ5È* ~LôCó U×§Þ¦™Ê‘ÕXÄf'oJC2™Ê2©û:¿|ÑáMŒBÕ[bÆDŠŠÇV=ÓV3 œª}tÙòŒ™ÔI›¦<8¬Ï¤¸(!Ðl`Ööóë¨ï¨ß ;0Ý$¯¨_€>›‡Þ؃íeû;šæU9…-SÔ>Öó•/£½z ¹Pû…×Ý+¨[ŠÇR¡'t`èvŠºž¶\m/wiCh;¨Fꔤƒ I“:áVJ6¯sAµEONÓT¼|\D<õ@ê¨uÑŠB«†¨J½LŒxÉ9pÉ«…*ÙŠC»XÜBZ:_¹jŠØoÞº%$é{üHµ¸k4­{5m¶œh!(;Ä ‚`x€tç®%CIê:Ø7½ÿ¿^¥6ù’é¿‹~â:A¸ˆ·xÙQMR€Š;‘DŽâȦEDÄH©Q°³:‡½ëýÿ[`Ù%Àßò°€ßæ>Ÿ=qc/h™«aÚZ°Ûô϶¦_aä‡qµ¤%hZV•%i0A(H ‚0Â(VÒÐãeHq BÓ!IR`…¨P1Di‰‚1²®©Q íÉ÷ULükeˆÎ¬¤e¤"d^.±À /ENÒk–èq½ZbQ2‰JŠ P@JD·kœ½˜)X†4SB²ÉHºM†}³„ BEŠá*¹Ý.I‚®RQÒG!LTÞ(t„êkJ Ýnñ×av¾¸DuïˆTlˆÿêiÊÜ÷CÌqKg}”䵯.£%­9z\QW²­]ë(*¹ •JÒ‘&½º%”›IVÒCum·@è«U„ožf$dÉÄ«;y>íë'l3#;)¦å7|ê*Q7m–1[§þȵY´óˆ ‡ ‘DT›…Д8‚¾æ.tTõˆ–š­¤)ô,é±ç’Š„p£…”LEEÒ¦Ê& ÷¬šE'Ôn%#…sSeÙºwÿêMËü`úÑ;¦é€üJ;|þ~¸e¥ì]ê}¯7h4 ¨6™Q‹ Æ.xá[›P7OuL­è´™kÛÎ8EÉÄKNe䌻ÂHO¹]ƒÂw:¦á &&Qp&P) t Å §£˜B7MÉ”–(ˆ„l€XPD@Æš/H€ \9í ÛpØuñ³g×°q»‡øµùøé`X¼¶7!ÈvY N^ÊURc¼©p:tÐßtÀ9I¾!ù­mnbI}d6.–Ò}ѥȟÛÃ\Ií]€ÚÆôÿ:ÿuÐÉ`Xonƒ¯ß–€¥ñ#$“TLácRLÆ"–Àc@8Žb.&-Œcîpäqwìð:îÝ”L‘D­Š¡@¦ÍÆt(”ák‚†(øDBÂ6:»BÙmŸ©f—=Ïh²Ê‡XESlÔ­ajan8Ú]¨PÝRÙuÈ;ÈV‘väyjåÕ ¥eµ-´§u+ JŠ.EÀZUç¬Î%g±¢ý2¨‚§né á;qÀ¢QÿÄÀ$.b-©e«˜¡S½Œ4š`R&UÚ.b&C„E²åXU Åï•Âe/Ù0(a¾iS¨ ÞÖ˜”„9€ÀÈÆ€ ½¼J&ØvçËDUA 8’&nªKÂ)ª1“9€ªRœ c“ˆ·‰n#cj(ómŸìƒ¶×–Š\ã.©ÏéiÑ5Ùs‹jµ ¨î4—ÔRß´6•ï!Îô •¥!RM¥­Ú’@S”¯·DâÏòj¼ÑUŠŠ «»QT¤îÏŒUL͘QjZ&U5€LÐP Q(“; r“ˆ‚ c˜§5Ã@½ˆå=YV2‚¬lÓDX˃0r÷Ú¤páU7jÍÛ*U. ¦Éª"nôêÜ!Òa‚‡P@çdÜDz¦^›ëp õ·†›`tã☔ʲ @N& P(\L&ÄDt¸ˆ€_º_ÂFHÍJ]ªÚ*‡i­å7Ý„¨ H*˜Ôņ¶Â÷;M¬Se Ð!.‘[Ä€b$Ön<"ú,×.ÙE´q,œTÌÈ[ª€.jØÉ‰ÓP¼i @¡Œ< ‚é1(ÞØ Ú1Ê.CHM@ ¤›Y£>øDN ¨ªžÑrèX-õ¹·ĨƩ¬$Þ¶"¢Á²b œÅ)X%Ä^$“)1ˆñc8sÂtÃÝ\À8Š•Ø9Lö1'| œÿ¸sð\Êþ^°3À ÙeJê\¦ ‰IŽ8ÛçrG6¿;of€ÑÕ »+Z¼ŠŠl¹¦èý± ÕH¯u—kR£}Ú  S%MXÊèÕ_>Úë]ýH" }JwºPàYJÒÉÑ©Ôïš5+ÇðÍc ñ?eq ‚`É‚Ÿh~Sâ{ i¨D½Ò8Œbr&Žê9c@4(˜€#§…üyu×[± Ï<üî Œ`‰*l“(En w'˜ªDx š)¡rÜxÇÛ[ΨY¤r(…ƒ…"‡NAåÒܺ‡ÿ.˜F–^âmzú__ Ý:i¶#¹n&ñ¿KéËM·†rŽx¯â;õå¶ã{kä8a¾Væ7¨oãõ¸ˆ‡‡ÇÛCW¾âÌg‡HÒým÷ÂZ÷R NƒN<ø‰ôpŠäÿ1m÷~XKPtßQ¿Û\â6ð(}G÷ÁÇA¸|þíŠéõ«ž?cÌóùXm6äÔ›ó‰Æ˜ÓŒ:ËùÆÆù` &I<ðv‡ø†þ>??Kà¡ 7°ë¿¿L aé‡4. Ïð?l%QL€|/>aE%ymm¹ÛúúaY»½„9~áû‡í{·Ày‡¦ &­¬ú[øøtÕ5IA›}?o˜8!müyð#¯¯”aêÙè…®nC¨}9/»a}´…­ï[mo÷Îâtåˆí'(ê:uÞÛ‡¥ð¦“ˆä7¶¡{‡-Ãj<ÑH{@/?¿(úi8@í:U6ƒþ<ËÎ$´e-ïr뵿­Ð /`ývŸÅôˆb6#áÓÞ½ƒp–㸞ÞC¯ÇìçëHùÐqꟗÓUD&à_Ë•¯ñ‰±êq \u÷ôçqçáa¶ «+{û×½íë¸ÿL2ý¸Fâ¾¾;x]°žˆó°ù…µð¾ÞXÚóåŸë:3ýŸbh“: ð›ZDÇè užHn>ðë¶¼½?Í­€EþºO_ÏË Qv7ÞÝm{Ëé}¤ÿù†ž ð…yºÔ1>íýDùr¾M Ò4¶ƒç ¿ëÏâ?þ­|ôÿX2GãÈÂ=uÓö×o2ŠèÚ\@uëoóóÁ‚»ÛQÏPÛo6Pxð"ü}ÑxŽº øœiT½-mG‡A¡óúaèY „À#?½±¡ŸÞö6ƒå§†£ûi§˜5=¯ÿŸõØå;_/»í¾ÙGúÏ?¦¿l)£@éþ}}Õy{ëüòë¶Ý,8NUÈ?¯ë¸ìÎŒæüùxßú[†‡ÇŸóÛ^^8Fåq_âMørŸ+þÇ!˜õËçÖúk8Pyˆüzz‡®5ï-µúoá÷å¸`—}ëéòóçÓéÁPWëÓçÏï­‘š‚£úGÊçƒB@˜&þo_ (¦{۽𤒜!{€k×[ˆmæa!! t¿?ˆy`~ôBÖ¿ß/½0ko1ûñÖöÔ_〔òO Ûë¥ð¬G¨|-ûŒ›C—Ì<¯¦,<Ð;Ûê¢#Ð5ù_Ó]°2Jˆn<úßnvÞÚúr×LT”ÁwÓõùò™Âu¶ „pãá¤yÍäü°øfîÂ~{>¼÷ÖòBDÊÓ@¿÷çûâ2l¿†¾`#ã÷õÓ|+{w[ˆtôýõ†÷ó~¥Íˆ÷ˆÒàÏ/¤kœ#v˜+†¿[OC ¾ ˬ°[®×ñ¸xõ|Œ …‡Š×BöÞÝ>- 5_ˆŽý6~]õì ;ŽÖõ·?ˆcYâkùX5ù€i¯–˜N½ _÷Ÿ‰ÿHùÇMó±åãÇÏã…À—ªÄ;ïqÖÿ.^;[ K÷­ÃÞ¿[ÂÂê7çž"¥ë¿Ï•î6·+h8>ÚDD‚Q6à¿Kô· ô#^z¯ï:?ퟮuœš17`:y}/‡9ä„ !~zÃqé~/<5¶v…žz'ŒŽQŽÅgN\1Èó¿»±I1x‡Ç§+^Ø(y!¸ÜÚkn–ûß 3<C§ïõ¯ï‚Çv:‡øž_ç Ÿ¬Çó¿û,u´ÛöÁ‰¢H´i !÷Ž6œ;41GõZܹ|OPÀ¤™1çñú—ï aŠgw築ƒöÀBòßò ä?¼#^x³ýv·{²g…çôœš1¤ZÚ ùŽ—µã ä€á¡¬"úí·À*üu×Ç~|ï¿!åþYÅ~m¸½Fá÷éŒöàÅañ|v;á*óÅŸûËH:ëùtè"ñ¾4Ž¢#ñ ¼ÃoPñ¾ðt÷‡N…¿¦·ùi€ý°yšÃâ @·Øá*ó…ë¼xD[¿ éÔqÁ‚‘", G)´^GÇŽŸ©d­ÿ!·˜_Ì5ûNP@46Üïò×öùiv<¿ü¯¿1×àO]p)^!ôÛž€:øßLÂÁüæ-¡ÿo_ޤO98Ù¤Iñ·+h"ãÇCñ¶$Då„-ïiç¨z…´ë°ý0l%C™­ë ÿIúj9ñ:à³Ea¬sÝžñÐÛÁò“Ûêë}~;óßÇ|-´t"!¨ÞáÌGŸžßÇ-±¢êö±ºl?|úiÿÛ6nBáïz}ü¶é§)Yœ’´ÊæãScqÔrŠP÷xXß×ˤañ(ä£ eIÂi  ªŠÄïR2H‹¨&&ÃÂRåû¦5†ÖÄr”›åÚ,wmÊÙ$nt8À©¥XxLšh˜GP°ˆ Žk–ÃýŠå9†±€å˜t°‡+€í¨ÛaÃ=ôzÉÉ],e[î ¢C‚¤!¸ƒŒÚ¢Ê] qⵆØöÅ•ÔVœ«iBašA•Ö”J½›q÷j)\p ÝmÕÔ¾Ùp€”¸–У¼ã`¼ìµClûMÈBÖï´² ·åmĤTÚN¤!' õ%Y”üNTjb˜Kþؤ'Tâ^ ) ™ pÖÃÌCk†)zÄÔ¬˜J¸›&CŦàžÐª†°& „Jc€NA”·â q ’\ɨŠ õÇ TˆTS_B‚ið¨eü""(Ž¢†pw}âBás#ÇÄ&Mvè(¨BÜ@tn ˆ€& €k¦¦Å?‘gÙ®ÍæTù¶MVº:êU…¶êBV“ÇXSn % I ‰Ee5}:éªÚ²à!I$‚&Ò•$…$õI†˜µ„ÎÈTÙ$²ñ’Í×2]árVI‰xJ"`9Ó|¨@@›MÂV9 þ´`¼A+ ô€ ¦ÝžÔõ+8|˜¢) "P"JSŠNY=]Ô’)ÝâR&T…(4ÅLà$7ê™5€Ö ”{±0‡ ÀaÁ4%‘^'HÉ3Kí2ìÞ®‘Î’#fƒ·üS?èÇÅÇa²ö—·žÓ¶§,{'¯ÏÅ6]TÑf­Œ²Žšul¨n­§êZA«,¸’Pë-¾Û/!JCÍ­Œ0PlfÏeÕªfˆ¸ûj iu¸òZX …!µ+ºÞI¥JB”… ä›ãÑ€`"r4¨êTÊTÿÜA ÄŒQ±øQˆ°ùDÁîÜ8ŒI]ó"*ý±®XÅÆ9Ü éJ*+؉ ÏEÔY@Èq˜D€A[Ñì¬ýÙÙ Ì\,à®xšª™s(fè$Ü®Œ¹P©wB¡ —ÄÁ6hê£x’&ªlSŒ  ˆ¨º‚&:r <"©¸Î)}ÆétA0‰ÔR¦¤¤~¹öé©›Sޏ ”¥ LIŽ’ºêB–µ¥"I&0å¡X/#&´Ã°º‹,uÎnŒæ-`(_„¥.…(ZØ–äp”J|@ øŽú^ÖÓ##Ĉ“„€8†ÖÃß1ëÓ .î&°ßQ¶£¨[óé|tFUFÞÎdMQHåA;ê ±ãkáÔ Aª]U}bžþ„ÂP–@›Ç/QF‘qq5ǨòÐuún6×Ka å[‰‡ÃKè7¶šøuç~¸Sz¿ˆˆõøþãÏ{Ü5Ãyu.#ᯘúu˜ƒfµeŪó$Ÿ¤|üoÂ)›#tŸ§Ú88U _¿Ÿ¨`r,[€ˆðômõÂxy…þþú`@°¡”Ÿ·–£×†Qiðð½ú|= *sh`0yñó׃ƒ+€òG¸†Â!ÁC†Ãñ +ER£^:ü<0Y@ê=uœ+{@óâøÛ÷{í®†ð÷¾¸L*ÆÜC×ïO!ò Ú•ÏÌþ: Öàæpw¿ÛÝÒÚëôð¾0Þåò°ýpOŒ-¨ þXÜá~¸_$ëËO.}4å8Ño‘øóÁÐX,ˆx_m|ÿlULà´Âf=6ûú`Ô¾m+‹Ûˇ¡l¥C†qæ,g}ë ¿°øyá;¾6—ù[éo–)î:Àyôûûç… xóë:DÇ^œ¼_ëËì>: óâ[}ü4¿\ ßMÆ÷øyà–0Ú†Þê¿YõúcAëôòä9a@ú†&Þ¿a‚I˜t¸Û­öýü0t‚¾½?Ž¿<•qA??iÆŠAáxú|0g‹‚Úˆ>¿>£Ëo€c;ÛÞ÷ÜD? 4¶Ø,'Zý0˜DDooã§–JäŽmðùÞ~S® )#á6Á±=ím®é¨}øàÊj[‡Kôõúh>8KØ}9`Ñ 7ÿvm×%Ÿ¤ñáÏ׆@:ý|¾˜ZI[kоǧ†"¸Ÿ[ù†Ë €w}÷ßÇÇúÀgVÜÇ;ùúßë®·RF¦tyÏQÒ0Ø?½ÿLjçÐ`áÜ Ââ6ûýº_˜oqqýWóëè>;‡‚¨ñ[OùóúàRª !~¼¶õ¿× SVD_”|´à#…þWÁe™áÃYý'Ž(:€ñtó¿Çüö )ØŠ@` ùõ^¡õ놢+kÏpßå×çëËN¸wv¿^]>ÐéË{aþãñõõåp÷WÞ>6Ž$ 5ðÁò:±ÇÞæ<öé§Ã{sËž"‡¼#p~–ëÊü¯å²-é×â:òÒÜÀ0:‹\€òÖÁûtùy`&¬óŸ39ëÎ6ñ<þFÿyN5QÀòÜ|y[˜kó¾7nì@w翯§Ÿ.C¶¸JUMFÝGï®ãkzxãB*%‹›oûlRª3ÊþGŒrùrÔA¡Èu¼ÇÌß(ñ²ê눅î~ðß•ü~@\s°ü~ §7×Ï•´Òáðå¦ÔRÆÜG@Øoñ×ûÛ– 5GŸÀ“iôý°.é<‡À]_–À‡?¯îT\D7ø†ãoë %wƒÈ-ëÏ*@@GþpY«P™>­{’O Zñᆓk_§ÖÓŽ¸4eÄFúÞ€7õøò¾3ÚFÖ¸ûƒø·ùÂj†ÜÆúþØ ŒV¡Îû[•ù`•U«#OÓÏïàn`o§Ký¿n~R2ûöõKØ?l2â;úùõÁQVá½À6ñßîøÇ5„@mèÇØà…T¨ÜB×åò÷uã†ÆºstõË­Œ™QÔnø—í·ÃaÓ[yéôÁ10Žãâ?Þ4”÷ˆ`…TvÖþSž\xéÃÜO£ëÑðÁ¡[Qçäož¿}1ç´9˜à–X-qæ¾xNaÒþ:ÿ8$¾®ú‹^y||£a#øNEÏçð°\eƒP⿵òþºá8!¾¡óÆÜa®ú|üµÁ%óÎxÛM|}pÀ åç#ôÀâ¨Ûù†Ç˜a€Ì{€Øþ6çÄ÷ [¯Ý°A¨<æÖ×§èiÎG¸-ßEAìDŒiÞì,Æ¢` 7ëá÷Ó©õjmÃéËÃü `aAˆÏ—:Nyœï­ÎþŸãßø|¿¼ã 7ñðÇ‚~ç|ßc‡>ž<´úDá6áo tá=߀Z××{ßÎ7 oˆÛæ6Âp¨P‚6ùã;ÒÛåÊßqžÐ¡¡<–×ëätÆ$ÿoÃÃŒk}5ýÀ…½ñõ°õÐwߦäÀ!q¿;€ØCÄCŸ•ƒöÂ/tàB¨!a(íÈy}ü04U($ðý¿©¦Z´Æ¼ŒëöômÝê}ô—ò‡_!ò9Y< 5Û˜è!¶m÷¯8ñì:Xt‡ïÿŒ-6t!kÖçò0sçaó·L?åù†â“ïGIЈô:k00æ·‡/.¼Ç׌²Áí­¯Ïo>¾zé® ÖY¡Ú¹ ŠJ 7ÐD,6¶¡pæQ¸n_‹Gö·½Ëa‡=uûᤘ€½§€øi}·½úô¾,<·8eÖOR”<í–ÜiÀÛˆPIZ‚$A¯1¿L´,-²P´R¤˜ ˆ ˆ6"ßÊpš+Ó€ª‘1‰ÎeÉŽ¨½ƒ……É@€6²dL…XnaâÃ2BVi3 â×!ÄÂcª$"çPn ”íÀÂ#¨^Àk{ÀÒbJH¦¸€ùÃp4 ‡—AÜê³Wõ‘1`% ë x…ƒ­Ç¬Ç³˜ÌV§è_s.RÉRšlï2 ȃ! rHJF‘¦±Ÿf,$!ä%ø°Q¢®¡©ërM耕“v  T…Äü=âAÔ¶)Š"™nŒ^!þ`Nà!q ˆØ»œ©ä“öf@Å#u—Pî-ÃÅÆDÚ"A6æ)Q0ØGq™Nœhÿ"?ý@êô°† f©¸BÛ{¥× ‡ŸÓ] (ì¯+iRöl·"É@I:Zyóúp£´u*å2A‹É16Ó^zGéˆaýâÅs,ºŠ˜,*˜L @ð–ãb/p(7¸Ž$fqÌ¢Q B”ÀX55¿;òøkÌ㙀 „4ßNŸ¿=Ç«qä…ïïuç·¼‚ÿL?Ñå¹Πû (SðA¨ræ€X'_ƒ]~²¸‚ò¡Ø™Ýáoå=0aûýìm5çquý×b"7ŽÀëÈ:[ã¿úéåÄ}áéã§ ûßq¶Ë®"#¯˜òûøùoͳU:Uï“Ç_×ån¤ÆSÓ"üøð·È[Ry `7 \G÷ñåðÛ m¸a)SïÏ÷~AéôÀŠ(:ë¯Ð?‘øü°LÆâX„Ô¾\Q$ó$þÝ~1â0ðÛqñû×ãËïŒG¦3lëôÃy2Iç… |f3c0±ŒÆc0á„øÌAåðþ03l“#¨±õêó"0c”l>ñ©Fáž=À°˜;¦Ü¼y}¿|߀ˆnCéü}óóÀ¸Ìmi›GÌc1è †øóƒ’­áÔk‚°8\1¹Mo.a‚Àa.Üñ°o®Ý?Œ j/q˜:}C‚àa¶ƒ ýúcromÀ~_~'ã0.=ytǘÌ•ð?¿ßÑ-Hâ>o· d‡0ù†Û@DA·ßÞø2Q†»ïã÷Ë¥FÀé§Qû`¼'é¿¿ã„ÓûÁ©V„t˜úO®£ƒ ¦¢_—Pé ±¨˜GŸ+ïç‚ØôÃßï×%vƒÃ‰7×ÂñÊ|1šàéáå¦&Ãç÷÷ç‚D8_N›Ÿ<!ƒQØ/®ú?Æ äo0<ì8uÀJŽžñ¶âZú`¨!Ìluøôdž0€tû 9¯äùàÀ¾~¯öÀ ëíÇå{Áèûçý`dÔ}v¾»z}† €|ú}é 6=<µ p.ðs:ú>_tð‚-pyüøáM%Nz[–ÛõÞØ8*oËì5ß@¿®ɰ‡ßÓD}Ñ¡õÆÂô¹¼E¸ÚÞP<-בõl`*WØo~\ývÁ“*Ÿ÷­µ°èi¯ï®lpò°úëü`À¸7ä¿LføÒO1òûxcTx~Ÿ\¡ÄGKý9‡‡?ñ‚â ‰¬=m!ÓM9ãuÂ>`õþÇ„o®V8tÿëöÆ÷ËŸËÕ¾ØQL÷(€ˆl>ƒý‡Ïmp š ü.?<‘ínV°ì>aþ7ÆÊ˜7 tµÃë÷|¬øqøG¯;àarg§­p˜GÀ>ùãÎ1¾úôþ° Œ7ÓÃùþ1¥Ç{ë×*ãÙ:øjOíl4ñõM:`c›A×_Ÿ¯M<°Pâ7·.^>xpòÛïïL¥OAãõá¯Lo„4ßï_¿–0ƾÁ·ÇïúÀBp µ—÷8Í®»ýé‚”¡ '[Åý|úã1†5ü¹ó  |<ñî4=í§¯– *âN¾½pÀ’’o^º…ŒÆcÁ¸à¥.l4â}põâ$¦.uà9~ÿO0D.8нÃËÃïï¦4 tÆ¢ qÂu,ͬÏ×®†`@8…ï­þXÐFâ#×€B÷·ó÷÷¾6À çÄüÎ7—/žž¹Û\f9yõßúþ?m…Ç‚!aÁDˆ"úÈñãáÆÝxpD¤‹È??ZޏŒÇž9¹¯ñ÷üàcn>±æ3€•cãÓôCan o{õ¾_}p3ß2mn ‡˜±øàáTçê¿AûÓRp%¸ˆ#ïáñþÀD6`Rª! ýÿ^¿QÁí¼RDÃÄG­>\ *gzj9õ6áœ6¸Ø:€è>CËmµå­´ÂÂÄ-cykÒß ®Á†AæS[ÀGO†ßAßÈäK®¡â[ ÿ8w§Ì”Ü{ÆÑ8ÞxÇà œ§P#üqƒoåÏR‚öýFÖÛPúˆ88Y`Òæ¿vøb;#Ñ Œ¸kîÛöûóÀÀúÖ¹‚ÿý€@|uûÛ-g«HùxÒ/À„rHª4žyh- ¿V8PGc…‡Ç_^zà‚²B7÷‡qç§;_-mòÃ@_ÜQ}Pý‡ðü¯¦áqýíñ iÜõjY:q7>ïW·N#š4‹ÇÒÿúaÀâB÷÷¶ñæi·ÌC׫¼¾¿}m/l'(äîâ;øØÁÓîØ"¢â# ÜzýùzøjsE9>ùóð -÷…mSÅ ñoŒ`e—¸ˆþôþnc„å¸ßQåÓÇïèƧPDw¸óýîÁô.srן_מŸ}K&I'ÕÈøüE°µ âE¬tâNºÇ;žC]Nk¹}~ÿ¼iŒÆa½j$ž@üùàð1˜ãqòÓùûðÀ¢6˜Æñ˜Ìf3ŒÂ¨ãaÓ¦7Á|Æ XˆãÃÃŒÆc1°`ÎJ6x|À¤Û×øÁø-cCÆ}|#àRšúÿ_¿ïc1˜L‹ø`Æ3ŒÆÒLˆç À‘Ôßåž3ŒÆ`üD9ÆÅ5¼¹†)¹†¼°[“qòýÃA3˃€ !pǸŸ¨=~˜ã1¸s×0w0úà| ŽC\¦Æýtõô#ÜmkéJ§+Þ܇¿Ž8ˆZÃ×öÀx6Hâ}pð邈€?84'¸ˆh ¹Û_±éóÀ…òÞø$˜/Ô0p›Ÿì1$Ÿž·<<9òÒØÌQ°†Þ¿~X0Øp[ôß<$hHÆcÓ)a½õì6ûå€  \@GKßoãÀOú‡ÓèØQ̘á™óÆ`P0rð×\ Sì{í‚x›ŸìùåË÷øã0¤Cêt¿ï¶ Äú!ðþG Ķ㽷妘Â<%ÔysðÆÂ‰å¯ê‘úã1èœ.>··[í®)ôæ"!ñ üö˜O0j:ÚÿMÇË÷ |òÆcÕNÏKÞ÷¿]0PÇióß`óý‡ô§Ô1…GèDußž3‘AßÇ[ëÓ_…°cˆG[Þúý† 'ÏÓ÷Á¢þûç€ïÄóõêØÌ€Ì~Añþ1±ÿHú}C·¯ì8 1=ý~ØÌ Þ ùi¸؈cCœà>:úýóµðsòýÃ`²©10L‹E´Òúz  h°{׸|ÎÁ|Ð$LëÐà{€ü/éË_OŽ¸Ð»‡˜c ¸ùŽ“784h8[†<À'½õôòûß`þ¡ôú` ÓÏïã\jkXo·Îþ?{cl}ÃË÷¦J¢N—òûãLl¶»rƸÌ¥hùúå€F˜:éŒ0€Ü·°õåä#÷û`,fI&N J‰0F¼|±† €o÷ö°\oq¾üðc©Ë×öƱ°ad@¿:NÆc1˜!B úœŒÆcÁØ|‡Æ`3o¦Áóûþñïy¦Úü¿¯žÆc ˆ4¥ q­È×ׄ``8u°ýóÿªˆl`å¿Ø_炸Ìl(0¶’=|~x=ß§ÓøÆÝÿ‡ßÇ ø‚"q¾¿ÆPãêܼ=Z RŽ3ÌrŽs® ÷Æû·ñcäåü_öÀ'Ø<ÿaÀX PúÿöŽ3ëÊ6”'KðòúòÓ[óú_ÇlcëaMmòýõÆ`n>cõÁ%dôúüp`BFƒŒÞ1¹ŒÐ~Ï/¾XŒÁfÀž@à^sðýÆc1˜ÌŒÀgƒÔ~þù`Ÿ@ƸÌf3ŒÆcDÄuûúã1ÿÙpropBACKnpropDITHnpropHNAM datafile.hpropNAME GrabberInfopropPACK0propRELFnpropSORTypropTRANnpropXGRD16propYGRD16info For internal use by the grabberallegro4.4-4.4.2/addons/jpgalleg/examples/datafile.h000066400000000000000000000004231173507505700222020ustar00rootroot00000000000000/* Allegro datafile object indexes, produced by grabber v4.1.12 (CVS), MacOS X */ /* Datafile: /Users/lillo/projects/jpgalleg/examples/datafile.dat */ /* Date: Mon Jun 30 15:54:05 2003 */ /* Do not hand edit! */ #define JPGALLEG_LOGO 0 /* JPEG */ allegro4.4-4.4.2/addons/jpgalleg/examples/ex1.c000066400000000000000000000017011173507505700211210ustar00rootroot00000000000000/* * Example program for the JPGalleg library * * Version 2.6, by Angelo Mottola, 2000-2006 * * This example shows how to load JPG image files from disk. */ #include #include int main(void) { BITMAP *bmp; allegro_init(); install_keyboard(); jpgalleg_init(); set_color_depth(32); if (set_gfx_mode(GFX_AUTODETECT, 640, 480, 0, 0)) { set_color_depth(16); if (set_gfx_mode(GFX_AUTODETECT, 640, 480, 0, 0)) { set_color_depth(15); if (set_gfx_mode(GFX_AUTODETECT, 640, 480, 0, 0)) { allegro_message("Unable to init truecolor 640x480 gfx mode: %s", allegro_error); return -1; } } } clear(screen); bmp = load_jpg("jpgalleg.jpg", NULL); if (!bmp) { set_gfx_mode(GFX_TEXT, 0, 0, 0, 0); allegro_message("Error loading jpgalleg.jpg (error code %d)\n", jpgalleg_error); return -1; } blit(bmp, screen, 0, 0, 0, 0, bmp->w, bmp->h); destroy_bitmap(bmp); readkey(); return 0; } END_OF_MAIN(); allegro4.4-4.4.2/addons/jpgalleg/examples/ex2.c000066400000000000000000000017771173507505700211370ustar00rootroot00000000000000/* * Example program for the JPGalleg library * * Version 2.6, by Angelo Mottola, 2000-2006 * * This example shows how to display JPGs stored in a datafile. */ #include #include #include "datafile.h" int main(void) { DATAFILE *data; BITMAP *bmp; allegro_init(); install_keyboard(); jpgalleg_init(); set_color_depth(32); if (set_gfx_mode(GFX_AUTODETECT, 640, 480, 0, 0)) { set_color_depth(16); if (set_gfx_mode(GFX_AUTODETECT, 640, 480, 0, 0)) { set_color_depth(15); if (set_gfx_mode(GFX_AUTODETECT, 640, 480, 0, 0)) { allegro_message("Unable to init truecolor 640x480 gfx mode: %s", allegro_error); return -1; } } } data = load_datafile("datafile.dat"); if (!data) { set_gfx_mode(GFX_TEXT, 0, 0, 0, 0); allegro_message("Error loading datafile.dat\n"); return -1; } clear(screen); bmp = (BITMAP *)data[JPGALLEG_LOGO].dat; blit(bmp, screen, 0, 0, 0, 0, bmp->w, bmp->h); readkey(); unload_datafile(data); return 0; } END_OF_MAIN(); allegro4.4-4.4.2/addons/jpgalleg/examples/ex3.c000066400000000000000000000021161173507505700211240ustar00rootroot00000000000000/* * Example program for the JPGalleg library * * Version 2.6, by Angelo Mottola, 2000-2006 * * This example shows how to save a JPG image to disk. */ #include #include int main(void) { BITMAP *bmp; allegro_init(); install_keyboard(); jpgalleg_init(); set_color_depth(32); if (set_gfx_mode(GFX_AUTODETECT, 640, 480, 0, 0)) { set_color_depth(16); if (set_gfx_mode(GFX_AUTODETECT, 640, 480, 0, 0)) { set_color_depth(15); if (set_gfx_mode(GFX_AUTODETECT, 640, 480, 0, 0)) { allegro_message("Unable to init truecolor 640x480 gfx mode: %s", allegro_error); return -1; } } } clear(screen); bmp = load_bitmap("cat.tga", NULL); if (!bmp) { set_gfx_mode(GFX_TEXT, 0, 0, 0, 0); allegro_message("Error loading cat.tga\n"); return -1; } blit(bmp, screen, 0, 0, 0, 0, bmp->w, bmp->h); readkey(); if (save_jpg("savedcat.jpg", bmp, NULL)) { set_gfx_mode(GFX_TEXT, 0, 0, 0, 0); allegro_message("Error saving savedcat.jpg (error code %d)\n", jpgalleg_error); return -1; } destroy_bitmap(bmp); return 0; } END_OF_MAIN(); allegro4.4-4.4.2/addons/jpgalleg/examples/ex4.c000066400000000000000000000023241173507505700211260ustar00rootroot00000000000000/* * Example program for the JPGalleg library * * Version 2.6, by Angelo Mottola, 2000-2006 * * This example is the same as ex3, but also shows how you can specify * custom quality and sampling settings when saving the JPG image. */ #include #include int main(void) { BITMAP *bmp; allegro_init(); install_keyboard(); jpgalleg_init(); set_color_depth(32); if (set_gfx_mode(GFX_AUTODETECT, 640, 480, 0, 0)) { set_color_depth(16); if (set_gfx_mode(GFX_AUTODETECT, 640, 480, 0, 0)) { set_color_depth(15); if (set_gfx_mode(GFX_AUTODETECT, 640, 480, 0, 0)) { allegro_message("Unable to init truecolor 640x480 gfx mode: %s", allegro_error); return -1; } } } clear(screen); bmp = load_bitmap("cat.tga", NULL); if (!bmp) { set_gfx_mode(GFX_TEXT, 0, 0, 0, 0); allegro_message("Error loading cat.tga\n"); return -1; } blit(bmp, screen, 0, 0, 0, 0, bmp->w, bmp->h); readkey(); if (save_jpg_ex("savedcat.jpg", bmp, NULL, 65, JPG_SAMPLING_411 | JPG_OPTIMIZE, NULL)) { set_gfx_mode(GFX_TEXT, 0, 0, 0, 0); allegro_message("Error saving savedcat.jpg (error code %d)\n", jpgalleg_error); return -1; } destroy_bitmap(bmp); return 0; } END_OF_MAIN(); allegro4.4-4.4.2/addons/jpgalleg/examples/ex5.c000066400000000000000000000301441173507505700211300ustar00rootroot00000000000000/* * Example program for the JPGalleg library * * Version 2.6, by Angelo Mottola, 2000-2006 * * This example demonstrates how to load/save JPGs in memory and how this * could be used to make a preview of a JPG image for a given quality. */ #include #include #include #include #include #define ESTIMATED_MAX_JPG_SIZE(bmp) (((bmp)->w * (bmp)->h * 3) + 1024) static int sx = 0, sy = 0, old_sx = 0, old_sy = 0; static char last_path[1024] = ""; static char quality_string[64] = "Quality: 75 (medium)"; static char size_string[64] = "Size: ?"; static int quality_cb(void *dp3, int d2); static int quality_text_proc(int msg, DIALOG *d, int c); static int preview_proc(int msg, DIALOG *d, int c); static int load_proc(void); static int save_proc(void); static int mmx_proc(void); #define QUALITY_TEXT 2 #define QUALITY_SLIDER 3 #define SIZE_TEXT 4 #define SS_444_RADIO 5 #define SS_422_RADIO 6 #define SS_411_RADIO 7 #define GREYSCALE_CHECK 8 #define OPTIMIZE_CHECK 9 #define PREVIEW 11 static DIALOG settings_dialog[] = { /* proc x y w h fg bg key flags d1 d2 dp dp2 dp3 */ { d_shadow_box_proc, 0, 0, 465, 190, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, { d_text_proc, 98, 10, 96, 8, 0, 0, 0, 0, 0, 0, "JPG settings", NULL, NULL }, { quality_text_proc, 16, 30, 260, 8, 0, 0, 0, 0, 75, 0, quality_string, NULL, NULL }, { d_slider_proc, 16, 40, 260, 16, 0, 0, 0, 0, 99, 74, NULL, quality_cb, NULL }, { d_text_proc, 16, 58, 260, 8, 0, 0, 0, 0, 0, 0, size_string, NULL, NULL }, { d_radio_proc, 16, 80, 260, 11, 0, 0, 0, D_SELECTED,0, 0, "No subsampling (444)", NULL, NULL }, { d_radio_proc, 16, 95, 260, 11, 0, 0, 0, 0, 0, 0, "Horizontal subsampling (422)", NULL, NULL }, { d_radio_proc, 16, 110, 260, 11, 0, 0, 0, 0, 0, 0, "Hor./Ver. subsampling (411)", NULL, NULL }, { d_check_proc, 16, 135, 100, 11, 0, 0, 0, 0, 1, 0, " Greyscale", NULL, NULL }, { d_check_proc, 188, 135, 100, 11, 0, 0, 0, 0, 1, 0, " Optimize", NULL, NULL }, { d_button_proc, 106, 160, 81, 17, 0, 0, 0, D_EXIT, 0, 0, "Save", NULL, NULL }, { preview_proc, 290, 15, 160, 160, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, { d_yield_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } }; static MENU popup_menu[] = { /* text proc child flags dp */ { "Load image", load_proc, NULL, 0, NULL }, { "Save as JPG", save_proc, NULL, D_DISABLED, NULL }, { "Enable MMX", mmx_proc, NULL, D_DISABLED, NULL }, { "Quit", NULL, NULL, 0, NULL }, { NULL, NULL, NULL, 0, NULL } }; static int quality_text_proc(int msg, DIALOG *d, int c) { if (msg == MSG_DRAW) { rectfill(screen, d->x, d->y, d->x + d->w - 1, d->y + d->h - 1, gui_bg_color); sprintf(quality_string, "Quality: %d (%s)", d->d1, d->d1 < 20 ? "very low" : (d->d1 < 50 ? "low" : (d->d1 < 80 ? "medium" : (d->d1 < 95 ? "high" : "very high")))); } return d_text_proc(msg, d, c); } static int quality_cb(void *dp3, int d2) { (void)dp3; settings_dialog[QUALITY_TEXT].d1 = d2 + 1; object_message(&settings_dialog[QUALITY_TEXT], MSG_DRAW, 0); return D_O_K; } static int preview_proc(int msg, DIALOG *d, int c) { BITMAP *bmp; static int quality = 75, flags = JPG_SAMPLING_444; int new_quality, new_flags = 0; int size; (void)c; new_quality = settings_dialog[QUALITY_SLIDER].d2 + 1; if (settings_dialog[SS_444_RADIO].flags & D_SELECTED) new_flags = JPG_SAMPLING_444; if (settings_dialog[SS_422_RADIO].flags & D_SELECTED) new_flags = JPG_SAMPLING_422; if (settings_dialog[SS_411_RADIO].flags & D_SELECTED) new_flags = JPG_SAMPLING_411; if (settings_dialog[GREYSCALE_CHECK].flags & D_SELECTED) new_flags |= JPG_GREYSCALE; if (settings_dialog[OPTIMIZE_CHECK].flags & D_SELECTED) new_flags |= JPG_OPTIMIZE; switch (msg) { case MSG_START: d->dp2 = (void *)create_bitmap(d->w, d->h); bmp = (BITMAP *)d->dp; d->dp3 = malloc(ESTIMATED_MAX_JPG_SIZE(bmp)); clear_to_color((BITMAP *)d->dp2, gui_mg_color); d->d2 = 20; sprintf(size_string, "Size: ?"); break; case MSG_END: destroy_bitmap((BITMAP *)d->dp2); free(d->dp3); break; case MSG_DRAW: clear_to_color((BITMAP *)d->dp2, gui_mg_color); bmp = (BITMAP *)d->dp; bmp = create_sub_bitmap(bmp, MAX(0, (bmp->w - d->w) / 2), MAX(0, (bmp->h - d->h) / 2), d->w, d->h); if (!bmp) goto preview_error; size = ESTIMATED_MAX_JPG_SIZE(bmp); if (save_memory_jpg_ex(d->dp3, &size, bmp, NULL, quality, flags, NULL)) goto preview_error; size = ESTIMATED_MAX_JPG_SIZE(bmp); destroy_bitmap(bmp); bmp = load_memory_jpg(d->dp3, size, NULL); if (!bmp) goto preview_error; blit(bmp, (BITMAP *)d->dp2, 0, 0, 0, 0, bmp->w, bmp->h); rect(screen, d->x - 1, d->y - 1, d->x + d->w, d->y + d->h, gui_fg_color); blit((BITMAP *)d->dp2, screen, 0, 0, d->x, d->y, d->w, d->h); destroy_bitmap(bmp); object_message(&settings_dialog[QUALITY_TEXT], MSG_DRAW, 0); break; case MSG_IDLE: if (d->d2 > 0) { d->d2--; if (d->d2 == 0) { quality = new_quality; flags = new_flags; bmp = (BITMAP *)d->dp; size = ESTIMATED_MAX_JPG_SIZE(bmp); if (save_memory_jpg_ex(d->dp3, &size, bmp, NULL, quality, flags, NULL)) goto preview_error; sprintf(size_string, "Size: %dx%d, %.1f Kbytes ", bmp->w, bmp->h, (double)size / 1024.0); object_message(&settings_dialog[SIZE_TEXT], MSG_DRAW, 0); return D_REDRAWME; } } if ((new_quality != quality) || (new_flags != flags)) { quality = new_quality; flags = new_flags; d->d2 = 20; if (flags & JPG_GREYSCALE) { settings_dialog[SS_444_RADIO].flags |= D_DISABLED; settings_dialog[SS_422_RADIO].flags |= D_DISABLED; settings_dialog[SS_411_RADIO].flags |= D_DISABLED; } else { settings_dialog[SS_444_RADIO].flags &= ~D_DISABLED; settings_dialog[SS_422_RADIO].flags &= ~D_DISABLED; settings_dialog[SS_411_RADIO].flags &= ~D_DISABLED; } settings_dialog[SS_444_RADIO].fg = (flags & JPG_GREYSCALE ? gui_mg_color : gui_fg_color); settings_dialog[SS_422_RADIO].fg = (flags & JPG_GREYSCALE ? gui_mg_color : gui_fg_color); settings_dialog[SS_411_RADIO].fg = (flags & JPG_GREYSCALE ? gui_mg_color : gui_fg_color); object_message(&settings_dialog[SS_444_RADIO], MSG_DRAW, 0); object_message(&settings_dialog[SS_422_RADIO], MSG_DRAW, 0); object_message(&settings_dialog[SS_411_RADIO], MSG_DRAW, 0); return D_REDRAWME; } break; } return D_O_K; preview_error: line((BITMAP *)d->dp2, 0, 0, d->w - 1, d->h - 1, 0); line((BITMAP *)d->dp2, d->w - 1, 0, 0, d->h - 1, 0); blit((BITMAP *)d->dp2, screen, 0, 0, d->x, d->y, d->w, d->h); return D_O_K; } static void progress_cb(int percentage) { rect(screen, 219, 235, 421, 244, 0); rectfill(screen, 220, 236, 220 + (percentage * 2), 243, makecol(255, 0, 0)); rectfill(screen, 221 + (percentage * 2), 236, 421, 243, 0); } static int load_proc(void) { char buffer[256], *p; BITMAP *bmp; PALETTE palette; if (file_select_ex("Load image", last_path, "bmp;pcx;lbm;tga;jpg;jpeg", 1024, (SCREEN_W * 2) / 3, (SCREEN_H * 2) / 3)) { bmp = load_jpg_ex(last_path, palette, progress_cb); if (!bmp) bmp = load_bitmap(last_path, palette); settings_dialog[PREVIEW].dp = bmp; if (!bmp) { sprintf(buffer, "Error loading image (JPG error code: %d)", jpgalleg_error); alert(buffer, jpgalleg_error_string(), "", "Ok", NULL, 0, 0); return 0; } for (p = last_path + strlen(last_path); (p >= last_path) && (*p != '/') && (*p != '\\'); p--) ; *(p + 1) = '\0'; sx = sy = old_sx = old_sy = 0; set_palette(palette); popup_menu[1].flags = 0; } return 0; } static int save_proc(void) { char filename[1024]; char buffer[256], *p; BITMAP *bmp = NULL; int quality = 0, flags = 0; if (file_select_ex("Save as JPG", last_path, "jpg", 1024, (SCREEN_W * 2) / 3, (SCREEN_H * 2) / 3)) { strcpy(filename, last_path); for (p = last_path + strlen(last_path); (p >= last_path) && (*p != '/') && (*p != '\\'); p--) ; *(p + 1) = '\0'; set_dialog_color(settings_dialog, gui_fg_color, gui_bg_color); centre_dialog(settings_dialog); if (popup_dialog(settings_dialog, -1) < 0) return 0; quality = settings_dialog[QUALITY_SLIDER].d2 + 1; if (settings_dialog[SS_444_RADIO].flags & D_SELECTED) flags = JPG_SAMPLING_444; if (settings_dialog[SS_422_RADIO].flags & D_SELECTED) flags = JPG_SAMPLING_422; if (settings_dialog[SS_411_RADIO].flags & D_SELECTED) flags = JPG_SAMPLING_411; if (settings_dialog[GREYSCALE_CHECK].flags & D_SELECTED) flags |= JPG_GREYSCALE; if (settings_dialog[OPTIMIZE_CHECK].flags & D_SELECTED) flags |= JPG_OPTIMIZE; bmp = settings_dialog[PREVIEW].dp; if (save_jpg_ex(filename, bmp, NULL, quality, flags, progress_cb)) { sprintf(buffer, "Error saving JPG image (error code %d)", jpgalleg_error); alert(buffer, jpgalleg_error_string(), "", "Ok", NULL, 0, 0); } } return 0; } static int mmx_proc(void) { if (popup_menu[2].flags & D_SELECTED) { popup_menu[2].flags &= ~D_SELECTED; cpu_capabilities &= ~CPU_MMX; } else { popup_menu[2].flags |= D_SELECTED; cpu_capabilities |= CPU_MMX; } return 0; } static void draw_image(BITMAP *bmp, int x, int y) { scare_mouse(); if (bmp) { blit(bmp, screen, x, y, 0, 0, bmp->w, bmp->h); x = bmp->w - x; y = bmp->h - y; if (x < SCREEN_W) rectfill(screen, x, 0, SCREEN_W, SCREEN_H, gui_mg_color); if (y < SCREEN_H) rectfill(screen, 0, y, x, SCREEN_H, gui_mg_color); } else clear_to_color(screen, gui_mg_color); unscare_mouse(); } int main(int argc, char **argv) { BITMAP *bmp = NULL; int x, y, mx, my; int result, mode = GFX_AUTODETECT; allegro_init(); install_keyboard(); if (install_mouse() < 0) { allegro_message("This example requires a mouse to run!"); return -1; } jpgalleg_init(); if (cpu_capabilities & CPU_MMX) popup_menu[2].flags = D_SELECTED; if ((argc > 1) && (!strcmp(argv[1], "-window"))) mode = GFX_AUTODETECT_WINDOWED; set_color_depth(32); if (set_gfx_mode(mode, 640, 480, 0, 0)) { set_color_depth(16); if (set_gfx_mode(mode, 640, 480, 0, 0)) { set_color_depth(15); if (set_gfx_mode(mode, 640, 480, 0, 0)) { allegro_message("Unable to init truecolor 640x480 gfx mode: %s", allegro_error); return -1; } } } clear_to_color(screen, gui_mg_color); show_mouse(screen); alert("JPG image load/save example for " JPGALLEG_VERSION_STRING, NULL, "Press right mouse button for contextual menu, ESC to quit.", "Ok", NULL, 0, 0); while (!key[KEY_ESC]) { x = mouse_x; y = mouse_y; get_mouse_mickeys(&mx, &my); mx /= 2; my /= 2; bmp = settings_dialog[PREVIEW].dp; if (bmp) { old_sx = sx; old_sy = sy; if (bmp->w > SCREEN_W) { if ((x == 0) && (mx < 0) && (sx > 0)) sx = MAX(0, sx + mx); if ((x == SCREEN_W - 1) && (mx > 0) && (sx < bmp->w - SCREEN_W - 1)) sx = MIN(sx + mx, bmp->w - SCREEN_W - 1); if (key[KEY_LEFT] && (sx > 0)) sx = MAX(0, sx - 8); if (key[KEY_RIGHT] && (sx < bmp->w - SCREEN_W - 1)) sx = MIN(sx + 8, bmp->w - SCREEN_W - 1); } if (bmp->h > SCREEN_H) { if ((y == 0) && (my < 0) && (sy > 0)) sy = MAX(0, sy + my); if ((y == SCREEN_H - 1) && (my > 0) && (sy < bmp->h - SCREEN_H - 1)) sy = MIN(sy + my, bmp->h - SCREEN_H - 1); if (key[KEY_UP] && (sy > 0)) sy = MAX(0, sy - 8); if (key[KEY_DOWN] && (sy < bmp->h - SCREEN_H - 1)) sy = MIN(sy + 8, bmp->h - SCREEN_H - 1); } if ((sx != old_sx) || (sy != old_sy)) draw_image(bmp, sx, sy); } if (mouse_b & 0x2) { result = do_menu(popup_menu, x, y); while(key[KEY_ESC]) ; if (result == 3) break; draw_image((BITMAP *)settings_dialog[PREVIEW].dp, sx, sy); } } if (bmp) destroy_bitmap(bmp); return 0; } END_OF_MAIN(); allegro4.4-4.4.2/addons/jpgalleg/examples/jpgalleg.jpg000066400000000000000000002176611173507505700225650ustar00rootroot00000000000000ÿØÿàJFIFÿÛCÿÛCÿÀÚY"ÿÄ  ÿÄF!1AQaq"‘¡±ð 2ÁÑáñ#B$Rb3r%C’ S‚“ÂÒÿÄ ÿÄM!1AQaqð"‘¡±Ñ2Áá#BRñbrS$34C‚’Â%Ed“”²&DFTcsƒÿÚ ?ø?ÆÅ ˜>? aKÅÎÖÀ…([Üq`a•~sôÆØÌf3@•—õç‚ÖoáŒÆåÁ øiç|hqê6ÁŒ€ãbÇË_¿¯¦Æ„ /×ïùÆø="·áÃÑÆ`Bù ˜/·>zÚÿ¾!ÂÓÇëéþ,8:Rò(}þøV„O¸‘Ôðå‚ ž¤q½Ç\xßEØ/¨ýïJ€è6_ÏO@ ™-n~@|ß ×l"ba°ÿO–þZÛ%\<9pñðåÁÀ €ñåôÁHJ7 †ÿñð·ùëáŠØmÎáþ>ï¦Ø¢7ò½þ;…½Œb:†¡nWëk—=¼pµºuü~ìýuÁ*pH¿+ýãÊ'® ¢6ñÒápº\CN_ *P-¶ûùyï¯/¦=†Ü¯‡M5ÛÊÜ̦‘Ê:‡?¿]oèáct§ˆûÇŒ\›i~˜%N¡¯×Ym¦ …즗ù}ˆßså|>#¾¸p·-ì pš-¼útˆGP÷BÃÈ?5Û‡MõËTŠ1î˜ðwÔPGk6@øxŒ"aßA×§õ¸óÃ–Žƒ2ÓÆ' 8¶ ,¾KõóÃ’2U=ÃÀéþÒxi§pBªÇ>½8FœºZxIÀiÃÃÃúBú…ƒ/Ø<0Êb`0Æ5´ºr×{rÓ+=þ›2h8PSý%hØ-°r×AÓ¦¸‹\@üÂmʘˆüFÓ]ì º†ß§^J 'pè8q÷zuð>Æ&²¨ý¦ç—ŸfyàÝ2ˆ” VÛ‡`¿ˆ+uç‹V2+¢B–ÂîȰˆ[@¸ê"Q°\0ËmXXµ¦ž”u® ˆ}ÄâÚ&Q-„xna×ÞÃ=NV¤ÉÝÓå§1ÌÌ|¹+n¤ƒ×Q}8uçkiˆ®¡âÚ‘‚6ïD½Òæý:r.Ã{ î""ˆìœâ&¸ˆˆøùóÓ—ÔGW‰- éEιƒOí÷ËN»jæeDˆFÛtÛA·O&8æÏÊÚ_Ô<÷ µÃ;ÍDÚ8Àáþ±>W¤*|G©Â2Å€€X7ߘX?o˜ùá5Qý\¬ýþw¶ yn:}ééö ªÜ}B퇧—×\6:‹ráÂѧÓáÄ[¡ZxÓ¯õoÕ9@Ôw>í÷¾ œ„~>ŸzàùÃKó»`¡ÀF×ëk|ƒ¯Øa½ÄÇ;ñ¼üäáBLŸðŽ<¯ñÂy·-¨à€oÏï×öÓÈᵸk¨yr¿Ÿ<9.;£¦¿;xsÖÛá)lžgÂxtÁDhuðÁC[yÛŸž‚?!ýÀ©‰m®=vˆ§ÐD>,d„6åço¿lX'„›}Gøò¿\ 9Ì|>ß¾ÔÓAøÝzrÁa'AøÿA…S$#¸˜nùà!Dz_Óø¸‡Ëª™W·.œ¾‡Öp-ôú½ %‡äPÇÓ¦Ø@J6óÂdzAî±­° 量x!tæ4ŸÔtë× ¼…_ÇÇýpŽ% XÆØɈÚúù~ú|0°f‚ñërÜ×ç¨ú`"!§rÒûôýüí„nS‘À‡/µ„üíƒBÇ}?\%‰üÃÃï\g«ýÏŽˆím<~ý~XSÓP½Æ­p4‘ÆÓà~4ˆ 3Ì ý#åñÀB‡/ß×÷}Gü~ß< 6y„ØH&7@‹éÆß °ˆtcËlÜáïy…ÿoÛà ž_CûÆ8C]^ºýp ·1úà|:ˆQãÌf3ŒÆ`~¡óúë1¹Ã_0ûý±¦4D‚9àôè<3ŒÆ`Œo€,"8Ÿõøý±˜P&­>ø×ŒÆc0,f3ŒÀ-<¿Æ3ŒÆc0V3 ¤Û̯ÛãÂì_]qî0˜5Æc1›ãp ß]Ì?¼©òõòÁ&L˜ã~XðïyÿoßcP(ö¾½p Ü4\9ilãXÀÐ1¹J&ÛØG`¾ ¢Oïm~…&t·#,™ŽS¯ÛÔ`D“@5æ?Kï…‘½€PÜ~Zxõ篦›Q¾ß.–éßË„âÄCôˆü´õëýÛË?ø_zÿ˜{k$Yþ‚E¿ôüuÖÇ‘ÂEU€EùqÓòž&}q7 ´š­r‡ŸÀ4ðå¯Ä-l$aO¶·Û@¯†ßN®$ã5·NW¸‡žºxï…4#Ìíím€m÷ô¾Øqg"T¸Nš?/—ޏ!U€q:rŸ‡ ‘†‰aÌÏü}é×s¨²Y!Ô¢>ƒçÌaøßæ¬DlP¶aÔ/¥ïÐDD7½°¾„"KZä9㦗ÖÚúáê›gÖcÜ8ý¼þØHºÐ?«Âü øOêf'FT¨p¨[òµ„6Úῆ <í|=8›‚‰…°¹ìü,òÃïý(a"q¸ßÈGÎÝoõ0”C¶¦à1ŠØ ¯1¶ÿ]yé‡v¶y_òô‹G=Ýzq‹[ U\žzuðÿw¨ÄR¬#†Â¼ð‰ê°/3Â:xˆý8ZNŽé•2oû†>ƒnÓQ°‚öÚà:_jzÙ¦£œ¹yÀ™ìnQØÞ Fú‡=çÒP„xØŠ$˜(ÙÚ|D8íÄÏ`Ô/¸à 8*Œ\‰9fd„EªW(iÂ&H§â ÂèÛ_tÃlN2í›R÷OwÄ 9ÇùЯŸ{áåê×ò¾+vjÑç—f¨¥ÂS.%è""6ÚÂðo¾rÊ—US’‚\\ Ì}´ ‘@ _Äyžš ©Ï* \ÑtýPŠ7Md˜¬s”.E¢©„Á~&&Ð}à _L…¡Í#VÊ"&îà›®:Ø7 õˆ–ákÛœ¥•”oÄÌ`[t¤(pA"ØmVdªnºîðÚ:ÇIÃNb’pªª)XNcp·)þ:XÛý7Ä]LQçP²sJ¥îçE¿äk€ÜÇÓRø^ûfÅhÈ&mHûîJTÓ –Â*®pM0µÄD¡ ÞÃÌ1ןú*‹Ž‹E4“Ô“M4J[ª«·€[—@½ÊS&A¸„DDÅ=³p("B¤‹jº × ‹ÎŒÄLo ÇÂ×Öß}mŠ"â™=QR¨‰lXèÞ%®`ÿl‰¥ïL:þ’€Ÿ‡Qáá°ÃÕòá1(f bƱ²”6 ˆræa÷ÏšÀ¸båf4XeÝ2Ö‘kïÕuE}:¡EFmÜ*“Sî%5„ª¨A°Š)ˆS8ΊîPn“Õsñï0ßsˆî<Ä1Ìvx¥*!¼¿ ø p20èÅx${Ö¶ºðõ¬õ¶ "ÓÀ‚}ê…ÒÚ†½wéµí· 6Ÿµ.—°h;mk_ÓÃOö^,ë($I1…ŠB‡-ÓÇQ·L žH.†÷—K€ÿì:rçŠó3ÊKe^á´Þ8Û^º|m©Ãí5Nð‘×Ëé>6˜°ªªZk­´Ä¡,‰R"ð”/`ùˆsßQòØCãôÄÚâ#~vè~zb]FRTwcQçmG?@aé—f‡p¿ˆùðÃ1ÕÄMÌ9ÛÄ6¾·å×®— ßn{ë¸߆˜s:&÷Ð>Æûõ¿_!¸aºä@·æ:é~ƒ{òñëË~qš†’瑟aöÂ7â>c÷ù|0Œ°X~b;}ùá-aµüÇãã×^wúáAuD~b>^£þ šþ=5éðÞÿκá™Öõ¿8ýt~cŽ¥\GÃÖ‡Ö‡”7/Qñøÿ6ø` ˆˆˆýù`sû×ñû þü±¡Q9‡oñ×¥¾í„E’IµíÎxpûß僂ÄI1Ï®œ5×é‚ÂKðDuåÊ×µÇ÷ÎìGoÜ`ñ¢LNaÔÔ<¾ZøL,7‰1¿ã{úŽ»yíáõ(f…N&Løé#ÕøF·…‡/ áå§?Òí‚¶9¹óûßp<‡›Qõ¿¾w~! "r…·µ¹–æ#ë×mð¢œ)wῦ£naü‡ÃL8·“-`‚&8x|õøôÂsTüÞŒp‚?kñÄj§ÿÇâþ„aºoÈGÖãÎãÌ~8“¿(½ˆÓMw¿Ç•­`ðÆ†Š[€4ça· énXÈÔ`„“¥ ì<¹ŸCíƒãáÊúpøëÀb5ü¶ÚˆÏ^›ÞÞAó 0£‹¿ µé§ ó—–¸‘Ï6°“ö½½炊Eˆn]·ðûòõê•ÌCTráÇݴŵ¹ò¶š±1¼8q4¼knsÀŽe`ÐCO+è;ú|0œ³a-饇È:‡îƒ”^Ü¢ÑÆÚÛ ©ß#ç~<>xc* ù‡ßÞûspEBkôñçï¦îÚâ!§?ä?ψ¢¬—k¦º†áá÷§(ÍM1I"ç6ý=u/mÀE®>ž½^pp¶›h=p¢7þä #õ傦(”Fá÷÷Ë .6A:Ï[O†\=OOñ®>À?z`< ¾0[`¶ö¸ßå üG(ÐõøàéH¿Çí?,k€€ÛîØ˜ mFááûí0QIg——ß Ž_¿f3ü­nw¿ÓO®ãCì÷÷¦À¦(µ¿€<ôþ÷Ƽá÷éŒÁ© $|ùõñõc1·º|ÃùÆ¢‡Ÿñ‚·Ó;Ê´¤ó^þã€n!€Î "¸ ãLA ®!óÀH#Që׫c"æO1Ac¯ù1¦3a ÂØÌkc1˜Ìf¯Ê}qÆc1˜Ìf ÆaÁ¶= D<Ãc0ð5pB Üs&y``(Üæ8Û∈`@¸`äE„}ñ¢dZâ›LÚãŸËL{ƒ% Øü —pó® @Ì-ëpÁÈ'Ë×®!5°j#¦ØQA+xoᯟ¯¥¹à¢ k/¯Øai©x|naß–ÁôþðåLâŸÓ©õúù'Y‚LzÓÚ7µ‚Úß^w~œ¾,YˆÛMÀþâþùȰDKAóÜ~n›ï‡ìc 7iÊ׿ӧQ×PÖOCÞ”[X:X›F±qkô× õOnÍì:ø¹Î€ãf1Âk{·Ô:hß宸u4‰Ð=Ë_=5ôù_ qQ@n ‡m@§-/¸u¾ÛêuK-,SEÊ„jG+7dŠk¹j#g*·2ÂvëÇŠD” €ãa(ñ$IžÑl>_A[W@åq­©U;l6òP ´\[»ËC€¥0„$¸õ£h(ÝÍßy–ÞK=ÓaÅ-H+L•¥0 ‘¼uvÂÒ'4b :µ·¯‡Øóצ’º\¡åpùh!äŠÒŒÌ†L¿šK$cRQÚJ @1D¢ªwi9€ÄàPÀ¨Ø=û˜ ôþcš6 ¤ÕQÙܦÍ\¹U.4•r*$œû\}áAALê•Nì¡ÇtÆíYkùg™Ñåïä•4 Ô-HU[•<†”R‘-"*YqÄ¥”€¤„—Í’p¦³e«X§qäV!å6 %¥ ¨o$+Þ.7S*’‘¬bƧ qÔ}-`¿Ó^ŸxRFt¹D>øõ½º€AÃæ 0ï˜ èÄŠÉâØLPtÖú~æ9²›ˆ:Avª›§n±AÒgŽÜÊ8*꜇(…ê—Ýia×îiOI’d–Ñ<Ê¥Ë2ÊœÍMˆBêON_C(Q©qõ$4‚«­$ÚbN·*ë©èP —j*§ 7 +ZP¥¨ ” ¢5Ý×£ø‡/Aè;zmáaÝe¼9ŠÂ¦ú€tÜC]/òÓ$ùÔÞœ–=Š’Š>\q(L¯V ýÑ8Šf!‹Â"#¡‡U³@MÍK¨áʽÒ#íMÄ6±„…"¢)FüBµ®ÅÏâ"j'd+•_â”ÿéÿàúN¶›bb½†¬TÿíFGOgr8ü£–/{fFJ×øø…þžx_nѲ U2 ô¾€6ñÐy^ápé×ä<¨ç¶ÊÔ( ²‚ÝO0AXꋃ?0!ˆPÐ ÊP·^áuf½2 í г"-‡¼8~} vÆ*e*˜¤íʦ9LQ0†‚ §ñ%‘$Gü^zÿ¦°·ÿÓ¬?ûÕ¯þ™Áiüîž­5(ÑÐ 1 {€l:Êü€5Ôþ`8 °²‘gâ!L¡nð†ÖÐt^Á¿ù>"FÖ¿M§M¡mL¯!•s—QæyÄxb7Q[ 7ýOnKF½b1c²‰ƒG`Ú)ÉʼD bß¼Vî %EQðˆ #¥ƒõŽr™ÊUâ3˜†Ð9ZI€@¢âG”€`0€€ã­Çû,“ÿMªGH$´•(åBEŠ>û؃Ágí €ˆÃ`°ð˜IŽ›ÏgFå–J/Wç=[żq ²@›ÉZù’æE³f4üqD†u.ÕÖÍS¶ŽÒq.î1©¾'må»)•¹´ÓÌQd´a1«¨Zn‘µ))KåkRR¼ … ¹)P Â_¨¬¨E%+nTT¼­ÖXe qÇoqL•ØX¦+ÕW”jÎv}®ãÈÜîr«„LÿpñÏ[ƒæŠ¦Š •° µBñ/fçwIMT2uýgIQ­U£©ò4V¦ž‹‡nV\Tì’|åÞ¹[(¨6jšË™2à˜”ا9¥ÛÇ7ó*¨`2ÁÂY_—µ#CR˸Œv«º’:&At„*G$2p¯§DžÍM# €‘FÇ—zÝUÔ™í(î¤E1•x Ú³M¯,šª¹BMEˆØ æI¢ Ø‚Ìá!:DX†ˆ$[òžÝ~1¶W+^e”ìÎ?´rú“MŸfueYrQ¸Éqtô̼Ƶ ¨Kåõåd!hVââ •“vUšU!ªŒî½p (ÑS¡5U#’]|-쬙ö¡h$;q™=¢{/Éæ,{4³)„ÄU2€I¿oRʸx£tŒV Z"ÖàªÏœ ’†2mQ÷Wxå³Q‚©{EdLW/\ËÎ<]1²Ô5þ˜©];šŸPÇI^œ+ÆŒš³Rêœ^9@H¦A3 ‚™Ã•lit¢Õ“e@ +ȹ…¢ò²‰„“v¢ÅTUd²mœ¢çU3&C ˆ)ƺ©MIJ‰dÒ~á·vÒ<&è$"¤TéŠEDÆv¼eHÖfë}í Š 7xc7Q4—TL$-(¯ÆhåHOð ˆí°Šp×ðüó|¶•$©eïø†Cî%! q(J`¡¤, ‚{+ÈR’=»8+'{x¿EFç°FìÞ *á½Å™§¤iüÖ–˜¬”ªag9v³‡Åe(Õã†ÊŠ‚>ȲX˶„ÀQ*É$`â K(*Oég“N}Ž1°œî”©äL·¹„À6 9Žã¸ˆVÉ™ÊZ–‘ªg;©I@‰’‰¦’/åõi߸#†ÄV>VŒrXÔ]=T‰))«ªç»)¬µTÕ´½dÈÈ‹ÇD6q2ÝG&‘vURI˶¤—*d]ãó‰„@¾È‘\xU2/Y;%ø¨ÙÜýæ²í²È†Í¼ò’Ò3ZÕY”切“RË­¢ªBBÂëIï:Ë{Å,y—g5ôHSùUg·¡ñ§y°ÕL CjJ‹o“» (è„­D #ÈP¬iÔŒgW/ÄMp"c®›@t°{¡§êÄ!S '2—Ð=í-§K[Ÿ…ü¶Äô©Ùëwd MÞ¤q²éœ41LÀ)Àn)€¦¸9b«%ÛÊ.ûÁq°ŽâŽÜÀ4 bæÍ(i«)ÓWFãUÏ 8ÓÌ©+mhP)*L‚ gË:gœie·R¤8ƒ BÁ X‚ AŸ3Ä_œÚQ0ˆ†ûiëéà?;EÒj‚` î:ø|ÿŽ~oÉ·Çpu01Än(úèà7Úþx`º‰’t#‰Àö(óên]®£pªsl¸…(„þœœÏ˜úbKJüÀ›XóÔˆ#Õüf›]¾i×âçÏ —0ˆØ|_-¾|ôÄšjAÙÆë…õ±½ßˆoa¿ï¾˜Ôit’¿¢X.r¸ÛQۯNJœ¼É„ñ$[Ao\xpóoÇ\ã„øO|yâ!;u” <Ç[ø[@Ÿw¸`?ÊÕ6¢QZm÷aÚ×Ä´¤:)þ”€|G]om=téòOUˆö(x¼½z_ÆýpÈõ¯)<"ÖÐs›iêøZ‡Ç8ŸÛŸéå7ÄrX“àè.c{x¥Bˆ\/éüîmè‡QÚDtÔyÏÏáÓ–="Û˜_Khƒo–¢Lœ¼ïhuN|dØŽï©ñ#Êß_—<&¶.– }Gç¶úsð áÀÖ>â(n½n`ÃdBá`ý¶×À}®Á‡36ÜZ[ö妶ðò×Ä1&Ë2‚áL£]¨Iå†÷ê¢o&óèk >1„öñwµÊççÜ=/…2EÀ"à:oãk¥÷ÇLû#öjìÛ]eIšùô$˘9ÇÑp”ÓI*Ò*˜#6Ì#œ§!(jLŒÍ ù˵·\H¬Ý›…]F` (bß Vk)1‰ËŠ/ 2Þ‹«T§b"')ºuÛäØ%3qo”höI*ÉÆΈwÎæA*±p¢KZv¡”ìîq˜dËÈê«—Tgn±–P·”mL8S¸½äT’‚m0)6v¦º•Š¡X†ƒè% ijRRM½íñ;Àoi`F¸ùÞ”À5ë¦á¿Ÿ ø_˜à#E‡Ý¿¥Ã¯ Ž/âs;–³¹nÂ*˜i)\¼˜xì´»xVŒ²¥B²lØE7n³]:©žÒoJ¢‹¨Å3qȘ L Iô†U08‡˜[†ÚâÅØ\÷*ÛªE½GJå%C%]õ+ŽÔÒRáB§P„$÷a;²¹7 º¾¾2BƒKø}úáÈfF¶…K_à…°XíD/ûíðÔ~6Á ¡q"J~Z -781/‹Aê~^§Þò€)€‡OëÌA¸ˆmÓïïà gl˜t°2lÚ¬é]jÝUÕðMÌ©õ¸X…ÐãµÇLU…Uœ(±Þ(@8U[¢$G0ЦÕ`Á¸qx›¨ ÖÕÕ ­>¨@UŽQ˜ÊSÞÞr20 S”JàÜEÐD¼\'L@-OúÀU!΃S±!Ä"Ò:.̈ÅI25Tªµ°„ b*™ú ‚د»~© ×lÆR“Ÿ.¬ÌV‘ʾ¡ºfʇOá®nÍĪ5ÃæÅ6K9…I[í0ÿÒÙqQÿÏLž09cÃHG"(&ªä‚Ê®ˆ‡JuÇ (¯ Cˆ7àW‚À@kâߣڧ1™LÓG…dÚ‘š&98L™Õà*ë‰,cJU×P¾à¢%^#<Ѓ¨f}±ÂÑ ÁÁµHýú®P*’Ò"‡"Bp$C½HÊ=Ù„x©€ßg¨Dç³ û¶Èp5,ƒlB–ÀFÄXånM4¹)FÚˆØlg™iÍ¶Ë ¡ Þæ Ÿu+ 3ðć<¨ö\ªµéÖÒä@¾€Éõ¨éLDh—@ Še°¬Pø€ÿBƒûH¨¢iXƒ.›fîdŸIºPâ•‹ùk2 ˆÿ¸b”¼_˜¬÷DJk ËlY¦túÅI"—ŠÅ(ú€[{t ƒ˜øëZó¶ Õ_ „à ÅXÅ$Ù&]ÄÇÁ–t»é4 k¤AD­J+*CHLDÅ0÷oη‘vGœ¡¸C¹ƒ™FNÉ »]OPúD}%RHµ‰1ŒS;•Vm5*•ï%„ÕU,ô²¤6zC®¶¡òâqNÇÉUR©˜Š]8ä Ý?¨¥“:Q§M±ŒUPŽ•AzuDJ")èR–æÒæÃývŸp²­š¼”˜9;…LNå¬yHR¨±R2Ê$‘ ^?y6ükJb$Sq$%Ü£erá¦*8$s4[š6-ÿpÌjdN.£UR[¾OŒ‚r9­Ý¾ËÊlÕ!™?{$â}½>Ñ .”ˆ8#‰.$EÁD36ÇDSà!NP9Š›`@I Ì›‹ð˜Î·qå7…³„Ú¤‰Ö;…ãTHV2'2]ÙER¦&ᵄ {”B× Ò¤y v±¥"`ÀŽ]`Y¦U‰Ý4J•ǃs›§úÀn!|7¢Íº8!FFºl°FàcK(š ±Š €]›¼/OrXn #‡¢Ñ¹Ø«Eš3¢ØD÷ÍJÏÚ¡Í*ÅâH”}àEd×N阂p€ËXØ=±©i·ØÙÜÍÖ]JVÛˆ¦Z’´ªRHAl^s•6²…×S¥i$—‚"gÂ}Z\ ÑÐÉœ€õDT›ƒNiY™Ò¢‘IÂ-Ä„]@!8@x1tÐq¤¥Eê´yO"ñRk‘g9Ûo7Ë+2åº hU0¶ƒ1½Ý©Cue27‚TJdH%M5m%bTªZ†Ÿ îíaE3¦ðDÁƒ¡ƒá% KRÉ™6ð [w ´j±—|ñtSDɪ(÷çPEnÓ*7Pn"6½r–³–¡+–4»ÕLÎ>yšR±(ûB®jEWY²ÑýêÄHÆ;URðvƒ†À'9¸Œ+¦ËÖN¦Û®±H©•QEjé2™.‚EP)ųr,Cé¹MCDã ±gTqi69AXªàî$®ê('n:'Dx«‡ت¦$:åHÐÿöç*\ ¦&˜†P€yGf»Y]±û[•æT- 9RÍ=kAD!úw¥i˜%$ÊI¦Tæ2ßŸå¬æ™eK$¥µ8Ê£ÞC‰:Ü kn c­ðJIº!3„‹uJß&P"ÀSØDÅ>‚&လLø†Ø²4 v´ü»G,Ýh┫“°tÄ^é •#ð©î8ÿlº\PFyþ’©¨¨7νlªÌÐ1Ìf†98»²ÜxÄM~›­Çö&— c¢ÞÍ>ªâ[²ŠbæEÙ\¤±\»DL²€’dLÆYs”‚D¦UuŒT’)Žr”ÞÇåP ±œÚ©ÄSÑš4Ö½PâÜSÓ¥ ó¯<àICm6€¥¸â””¡)**HåZ°ð¨]2§ï{”!7Z–U¸”¥"J”I$I IÄ3œôEÒ'ÌEK+ET œS‹  ¼”5`ìxERSSˆ² "CÃÃÊ6nÑ1!âAÓ6ny˜³µ^i¼ÝK0Ú.lTnÖ?¹IË&í¹ö‡Má˜AÖLÈ –CÙu¸<:î ²êX|ç®0ó'RÎ_È•&¨'OÑÌ ´ËXÈ‘~àìX®Š$º‰J¼$ÕxªÀ‘’j(6F¬¥ K±}Y2§â¤ë´é*y‹7•Y¶LPnñ$UU €a܇ûaÇ¥±æ'â ·¬×µ<ÝÜ‹)¬¨§ìû&®tå –nû_ÉædˆK¯-м¶š¨¸¬¾åRýIWBì>ÅÓìÝ*kj›C¹å[I5/*ìˆP ö*u\$&¡ÔG~àÔ´†À‹™‹}“6nžHG6<7çµ"Ò±ä“ G¥"ƒy&Í„žÔÑ!“Qf-—X‡nC$LÇ9ŸÑéF¸‚ON•éfÁÊî!(ýÂi‘Êð‰È(Š-§IdqÊ¢+Ù±>·§éŠZ;7ûCÖ©ÒÔ“%–^ŸËˆ#7qSKÎ=LÀÕ«¦¾ØéI)¥ÚYpjÈbNé릌ڹ](ë-òû´ïnYô©l“Ëa£èeä£ËE7«N-œ¸©^´[òÅxNè°I3]¡L²#$í3ñc›q?Äã)z\‹' ù£¹'G.1 åEVAs4ngÊD¬áùRlðŠó¯d:e?ŸCL¬Ùõ)ôîêÓ šE5{#)/S#“bŠˆ"Î1œíÈ“Öɘꦑ{+õH—2ë Š?ÉOÿ†Ã;d!Ð©ë ‡0ê µãu¤Ú6aòntÚè,G5¼œ|)(uRI̶X ))Ýœ0·]~=¦25²ÒO3{/›Ä·n¡I—•½Jï4æ!Q6¥p‹S·4C†À%Ç‚©NØ¢RJ²dîq(ÈöG8ÚçðÔS¸ê-Ò®¡±]R@6¦ Ar¹ä•€ð§á`¡O%@Ìö×!Ê*›¥®¨qd Ô!—\£iÅ%µ†\« önû»u·TÊ[¨iÆÖ¤âgŽ’5æ61d¡8ù´ ˜ÇÆ4kQNURoŒvìÕ;I„3 T@é  TJGf’©WfXø¦2ÏÝ¢‹xØöNTqä]3¼MŠˆÈº3¶¢£ó¾w`C,¢Ü"š€ Hráà C†\U²Ž3zZ™q_2§]¸SÍSÅKRpqJ&@eJ „Sp.Ȧ„š¯ÔT¦p©ÝêÜBÿù€ŒXSm—ð5&e:U9`ó/)ò<2 ª‘€ì³m[±L‹ªqHN§ g‘P80Ã[EY—UÔP×Ò¿E[J♩¥©il¾Ã©üÈu§V… ` ‚$q'aöj™j¢™Ößaä%ÆžiAm¸… J’ H ††ã›<é·tÒ¬kÚT’MÇ¥JC× ¹1LÍò’ŒJÝ´ÀW‘Y“¤Z0zU9ÖJMŠÇA¢‚³²,˜T ¦Kûa"UxQ"‡x¸àQß{öòÄÒÃ*óã´(9q£òC+%ؾbxÊn-Ðæ<šÑÁ¥ŸÉÍ8WAÜc¢‚©xS·XJºt‹³MuQJ@9¦äW]7Ð˯å²€nñ-;w nMTÎS€ FᥱÖ_‡ »ªu×¶'2}OSweܨº¢¢ÈšÆwq3 IH Jb·ÛÌ™´¥9» s{v¤$Fü‘ 1ýGBx™&I¼Ë#D@Æ6ä1‹¹•1u·>uðÄ1I´dSÈp± P°À6¶¶æ"!Öø“f?TN':¦¸ßkõ Ä5¶ÖÄ|öa\§¸ˆî&¶·°†¾ƒ¦÷tži”ï­pIáy6ÖütÖNšâMS_”p<8Ÿ.3ÈŒF^Á x…½7ðÖá~šaªä…¸ð”}‚ûân~>wÄ ½>ÿ§qDmmüC[xòú¦+OoþØß]ÿ;ßãýEÈJŒîIðíóùóÃ’+BcÞãÂÆ5´Þ|8â$r‰†à…¬>ߥ¿›á vª˜GÝ/ñ×M6çqå§–&…iãkîi®ü[ùZÁo.»ÛT…éó É{r° Ç®–·1½õ<5?³ªÿ–x@‰ƒîùÌÅçÈÛ [¯úr$Ûä~¸‡NÉA÷~¿0þ¾˜ÔŒ”~‘Ü4µ½oo›|¤õ`L÷Dv½¯°ék‡ßL¢Å´‡kúO+ ª¼¹§»Èú®®¨ª9Åh—nÜç4ÚŒš+F«= úˆqIªy à²³¨)í‚Eœ&¢i…Ù-7Ú¿´r•õAPädÿeÞËÔŒ#äêyZ²š”ÏÜâdšŒd¤‘mOG3èxç­˜€‘—U¤{ƒEºT êDâeÓæžÙëÓ˜vŸµëBn“2Z>êNSLÆZêG#ßÒº¥ïR¬4ÄûdÙ,löV‚í?´“>ÒâßIÿÈâ@è8Ãø±fu;Ùm½—æYTysE×5$<‡{BTÕÊ.%óN©J4#¸zµ*ꚥÚìÓorÏ‹Ÿch@DACŠ0 ÄH!ÄB˜Üíž¶ƒê;_üvëŠ1Èv(ÉL¹mC@ÓñMQ˜Ï(º.ò¥iöµ´å7C¥S™6ˆ ê¡:rXï]¦áeÞ*àî ’Fdáß5é¨^â ™8¹%ÂÛ{¡Ó×qÓp¶ø—v“êÌÖ°£y,2–Ò`ÆòŒ‘ËAã†Í°«îš§h*YQsëŸÄb>{q7»¯¯Çú·ÃqxÛˆØ4½öä#õØyi‰ÔUÄl^¼¾Î××—•‡¿¸M÷ ýö bê¯Ùõ-GÜ‘<­ÀÌxùZ׌DØ®€%\¦|®<ÏÖø‰O:û»ÞÜôûÓé‚§ŠÑ·‡Êø–Æmú>£û<&áÃqÿê?¾žŸ0Ã"öYGþìÜ‹oéÒ'^l+Nb›{ÂyÍôoÿÄœCêÆþ"-‡á¥þíl&-!páÐmËO½9}q1­ :û½@tùxoãá|"¹‡¿¹ðãÆÃ¿^¡vj½™RA=ÞþÞwáǯHVÖ` {× éó¿×®"5Xr¶šýzëqð[ ™‰ƒþ àq&¯¿»÷†ƒÐA '*â#ïKoñ·/,F_ÈFáokÿOé66az+D\‹ Þyya•ˆýÐõKñóÁ´ãÄm íåç~}9°ò$PÜ}ÝyyxòéÏ (ĈÛܾ܃kiáæþ§Ùõ©@n_¨×òýúΧºàºñøpøÇÇYÃ-8ßýyt×â:¯L,Xˆpô¸Ø, <°þF Då¿§®Ÿz<)§ £{ØvúéóÓÊÖÓlºÔü½`è?Ñ&÷àLë~Z¡^b÷Ï”iÇXÖäðçþRáF(@4-ý1,üGÐ}1¡àÌ©>!¯õ÷å…§d׺?–H2?ÛÆ'Y¿ùÁC3¯#®“»ã§„D Eˆ_ܽípçë}~ô䜴hëîôû×öé~C‰}xa Ü‚ †Ÿ=ƒ[]vç„7QB>ïØìØu½¹m®+6aH–àÅ tRÖ`7|-myñÄH»-ýÛ|Ö÷½½nXFY¸–ö0ןõüÜw =äx…ì[n ¹ý­m0ÓxÒÜ^í­{õž—å°nÚ™e%­éM†“Ó™Ë[qƒ‡zz¸¿®s箺# e’áÚö @wé¶œ»‡0ÛïÇ'ðñi¶†Ðu¶ÿFU;‡M¼CùéçãˆuKŽ<þç§éiókÞã˜#§Ì}v×àdˆ"#}6çûzó½°zR` c÷À)6#ô8ÎÞ£ûi¨ýßÓ ´¸ß ÃøñRÞÀ=½GÒHnäéëëÓå…¬´mÇCáò¿Iá¯B”­@øü4ùŒjÒÚÁ~›xõ[aÙ@0¸xhúôzôÃu²a}´ Õ¹‡+‘倀ܾÿŒIò¶ Zm¤óæ|â4Ã}JÄ1çÖöã3ò~Ã.]•¯¸øõÓPÄÇO¦PáÁ}.;xóßLD‘PˆømËmùðsÄÁr—ƒ].c¥¬5ôµñvì¥!Þkÿ3ý¼½r¶"9“–VŸtçÏç ŽªÕâ`µ2‹2€ˆ¸|Üç!8JulU8œJ ¨ :Ü,¸…âlÖ*èh®`I1"m“(Æ1•ÿäYAÿh@@… Äq.Tê ñX¨ñu ’§IÀxäY*uHèÉʬ/D©‘4JÜâSJ§¾mDl%mÆ-G2:i)>ÝWk¨Vè2pñƒuûÔ ©UVà©?J@"k„ ÿù¿¶Úÿmí 3e'y¼²—-Ë›3 nQµRòEÌnÔÕ>’?¸ÇÍ‘dµ‘Ó,ˆUCÔüN©>m¶ƒáÇ i_Ìã))©~f¢Ñ¬³åJ-Û¸¢Á #PD Ü5ÄlS˜nÅðÆ´‚„׈ŽÇMDt¿Óm´AΚš ¶_H°g*ÙÓéF¨´lÁ^-(Ñ%–\ pxß¼h.N‡LƘ  bÌ•[–&–Mq(ªïu¹y^ÁÏŸ@¶$߇  f}¢Ñ:¤o"…—* :ÎNmåW³äN¤SËJÒD‰øéçá‹þÝDýÒð’À—[M<ïoC*¿P×Rê6zHInŽÅ¤¡Q#ÕSR)"G™fb¨‚íV ¢Õ(—½+Ââ0OaP‚)™C¨"e1Žs„(˜Æ1†À¨ŽÀ{â¦eiÇç,›¬Ç¡$geJéC°Œ—‹y"‰sª’h‘G‘îLºÉ®"©šÀ (âøü`f‚Ÿg67#J æÅ~h¤ Jrš&éRTÒsƒ»"äºm 쾟~¿4¬"{ŠFiÁ<ê.'[R^4Ð눀ô†c‚ÏŸºEg“Í$Y±<•ÎA" À:r“x…PY$΢.Ê¡™Lª¼%AÙìáÓ¹z œ<´»â8•“q,œyb«r1dÑs{DŒs:Iw)¥‘U/…N"ݤœÐ‡Y)y,Ê¥©w¯Þ§Ü3ž”U¼À‰*Õe ÎYû@2dQ4ÌFÏq” ”mŠi›kµÏšZ&2}­TÖŸ¥`Y£h£eWzîBhÅ"ŒÔQ# hIµLþýÈr D¡aáì†UùÎYF‘&¢¶™¸‚gyÔŽ8·«]îi*˜îÙZ§MN¸êžGÅEÅÐÐèªÍ¨ŸÙ ‘LFâR‡2Ž—Ôoê!­ç6çƒ%¸š°4P 6¿éü¯Ï±W)u¥[C2n‘…" €Í`±,;…ÿMõצ¶Ã½Î/ÿêm¥ŒmÄGpë`ñcÙ ŠšŸ,¤ ¶;Š*vÀÜOô4€xH“÷œr½kÊz¦¡Ýã+uÅÎñ«ˆ‘ëç1‹&‘éeÓîÜ2Œ1Mÿ`rCÏÃß1è<«’͈º]•/£ú_¿•‘bþ!Ô\[(ÔŸº|3QdCÚYʉ”‰®¨÷ ¡L)—Ô|,ºÂ륶¦oËÞ×P°ö°j8lÒˆÒ‰IVµÊ9z¹ª‰Yu(jv¦ª¤e¡S¥¡¡'¥¡»t³iô]6N=œ¤ST‹"-¾²Àû¿?6þ/Z×gÙjfœf/íe1¥PBúi™ÊsSX¤¨ âÐ[”¸™ÝÞq•¥8žv_í ÎëT¿gFXàpJ «©¦îÛ©t¤ë P' h¼»Š+vª²¯*HˆÀ@åöíÛJœ¼*ƒi „—lÐnnà®NàD `)„ ¬®b›ÓtF_ªÊaËæOóB9ÂM—†#2VåYá^$Ê©‡Ú“â!@=¨\ §âåáºÎª)7ÓΩ˜j>N¬©"J•u œDÉiæÆnG ÛHÍËHÁÄægd‘ú­^¹8, Ñ\IcPÞÙ“5¬®`dýXÑe¢ŸóJÁ´µ’dаòO›Ãø~Þ=ª1±›ˆ‰æé¦‹¹PŽ2ȦÐÿŸ9cj{1¡i•¹VÂR¤—uÅßP –R´Kj'À 8îwcÜñ„ˆÊêiš”º’®dÜ¢$†En!ÉpïØåŸ«‹{él:{Xv¢4­1C6¤¢)ºqD•®^º4[)€©$4ÜJˆ0n¬4UÓ‚Ê;ID W”b© ˆš…4QÙÅY˜Œº‹,sA»‚»t쨦ݻf­›÷Î8v§tŠi"ŠgUeN§ d(˜FÁ|%TS欘ÖÏѦi´¶b²ÏZÜ©ÒôÍ<”ëË[)FIËÄ(5ìùQàA’Q„2R~À›‡ÎN²¦ôñµ,ld›+²”ƒ»Ïv¾‘–*]K®‡)ò,¹Šuæ2ä%Uï½IBÐPõ*³'ÞI"ŽØL¤f›Q˜æŽ¤L©Õ8ÒH+­}KM>³¼BzS†N*í -SfG$þ–…gÊ:129ÌYñ%9BP1®Ü ýÓ6îZ¦¤\Ë*vi¬ƒhî ûJ¨ Ц"YösË·•&q×9™Wf”õ$Ö]ⳕÊÊ.Í¢LÚˆ• &œM„T kÊN$"Ñfß¾YW‰¤. w¦´“óOif´½0´DC-3Sæ IIHæ#ôZRQü8$«8†2nA9“¨ ·2 –Ææ7l¼Á›®ê|·ìÃ/"ÁÛ¸ºû1ž‹bų©ù3,Z~‰”Eƒ5ÝJ8iÆd ØGL0!ƒÏ6r¡æØe q×V–Є‚T¥(€ä’tÅæëˆeµºá Ci+Q6)OÃç`þÆ¥ø¡ö–ÿYΪÊV]1gÙü¶ª¦TšSI4ÖvªI¦¤‹Óª|ÈßrÝÏi¥¢!d.²±U(a„Pqt5ì…¤Àz‘öî[QÅX®ÖòñÚpKÌ ·_2‚–©)UÝ)õ(À¤q ¤¸ÅBÞ šDÕ%SÄ Ä䉊B|‰·2¥Šh£4äÖ"e_¼3(É?cFGÙ̈ »f®Ìý'œlfGiª‘yCÚ <òÆIä¬*‰åülãuN‹Èï/ê:bz=a ¹x÷ýB¡…aîÏ ˜¦P7 ~Ó½¡æ)šŽIô?µ»l‚¦s?K™û˜×OQd©Y©7&™–wN×T«òž$ò©‘Éž3o ½FÒn&nB (µuÚý­N¦ŽhGGæýE Ƨ”dV•õáD×âå¤Ù(YXwÈ‚Ë*˜%"¬,ÁÒh¬ø.Š=•Øÿáã7dåûBië+hêƒ*) ©j—1ajeŽê±ÑÖ>`©šnÿ%qöŠK5•/"²Ž“›3ŽÐóM·y³™Ó1HºgJiTå­ä¥ hŠtW1¼”…¬¿U_º¥) CNU~Út˜Î³N²¤éŠ9h)Ý@I*í´ÔT¢…Žsò5ãv.Ôf£…™=1Ñv’©1¨Vç\§¢0’™œÕ×±ÈÁÓñíY¤€8U›WIF5h¢œHœR2`8\¢P´[,Ä£#çÚ;—É<ÄUDV"§-+RºKÚã)€·“!JÝ~ÿÉãTTðð‰nHÎ'ݳ²â²QZ2²}D•³”–LW£h‰Â¨v£fç3ʆ˜™‰€˜¤r²‰)Ä'2fÆ~#ÿ™îkžPíVÅSSÖ0¼š†ƒ8ËÝo0£ÏœÍi^ªA¬zŠ¡º¦Kb…TTŠy5éJÕJC,$:íçÙžÙQPe'(Íu¥·Tó´éT¨¦q +ºæ÷ß¹¸ .²e)è¹#>þQ¼ô"…ïÍìYFQè V é¡Št‰rÈêí—paRåV唂97×´ž|G6EØræþe’-‹c®»Vqå­&ŠÉ«u]œÎ”A»`I”pc®tÈS,c(&šeóS·´ë×ïåóÝwN¤š™›°V€Ê²5;cØ šl’¡“`ØFÁe·IP€à ††MäÄìUwQ×5³ä¥fê¹¹jŽué²+ɉ·ëÊI»#æÍ#YÃ×+,VŒZ6dÜܶnŠ"e¨»*ì«´ŸÛœ—1Ì2 ºJF_Ї–=Ô6¡}í-¤›ô牦Ñí&G]“Õ°ÅkN¸¤{ˆåRŽ¢Oź‘N mSpž¶Ü  [N¾ë¾®âãŽ#À²CËa×ÃkÃà8z¾§a•Õ w.¶áA-À6°ò¶$ÌŸÉlÓ¨k8T'eº¿?ÜTBˆ‘{\DežURâ‚nž»•¬jI˜é…ß MšD4SÚˆà=¼«· [¡Ø½¡mFE°9FÐgŠQm+Ktl”𬯵ÀTÕ%2V ’¢”-Çœ\!†Pã«'t%UnG–ÖçU¨¢£H+uåOtÃ) )ÇÄ”¤IZÔ”rC?/û4VY—·Ç Î.A1’9“U`_„AFqÉ”ÎÜ$P‡+…JÕŠ aÞ Šp$•HvrÈáÌ ¾‚­«Ê±üÅ+•óU²¦)õ™*fó c¡)é¹/ÊêxÈÆîÀ\&õH"èUpÄɽbeïE”¨d$e\¯Ú?³nHÈ Î*‰¢WÎÖ,AŸ±¸äk’“2îáÝwK$ÑŒ`2 ¡WŽj@ö%Y{Ù²Ž¨g‘§ëžÖÙ»ž¨eöXžŽšmKQtöJЉ úAÛŠ‚JH(¨jf¢›v²(ƒ4]ÎÔ)¶)ÊõÊÏDíŒÛö“·½½Ï*9}c;9@TCTY[ ©ä¶ #¾Ì*Zr©Ç@}l*••ªât&è Ø¼–´÷í*¹àóµ PAU§q†Ô–Ò™ , ›Ì!'Ù±¼UJΗwZWË=,ZRó‹4EIJ-ÔfS÷ ) r{Jn†Æ(šÂh¿Ta\§ÍL»¢«˜Jε Ýæ2•{ºqŒÜZu!be–cNÈȶV”{ÞY³e—[Û¥Ô±LЬœ»!„ $V›ÿ:2·¤ò‹-òO93ã>óy¡ã+ìÉ“ÿMÂ$•¨ªÚýx<ÀŠsJÓ±Qæu šÓ*- ²ݺ"‰Ž¢wÚ´ÌÊ €§ä]Ò”†[Ð9–m᩸ÇĬR‹¶`ªH£‹„“m$wîŒÙBÉ·“nÙK®b¥ˆ£ªv‡NàuY›-I Pëum˜ ûÌÕ4óJRÃ’ös#ZwNYL4%M(x)µ!CÈŒ|öçÏeºó"—;¹sEÕ”ˆ÷g-cJûbñÌuÊ‚-ê&Z5‘§Ýë4HUvŠÐª»tƒ(ù—îÄ äH¤Ö (Žʨ_A·˜é~z[Lì“í™g¦é>Æ5ÍI˜ÍEܲٳWQYJ¯E½+ÆEjjxÖuÔƒièÅSrvs”ŒS•¤ ÞTÔЙg[öNí/’YŠ„¥¡bs—gMKËTqô½\³ã1…Ÿ˜aæx´Ìƒ JYirÂoœÂ®©Ü‹¡r‚Ù_lciëZÈ6¥šfs7`Qæ4É 1XAHîÞbJ¨Ñ@´RË‚wZkvÚ=•9{*­Ë–µÓ¤Ë¬8wÖ×ú½V‹D+ÞO.lÒJ&Âå¹íkßm¾<þx‘òêïëZU¢q³r¢iØÕ?+¦Ú ö~@Ý&åFpÍ­’ršGIŸ¶­XÅQÑŠÝ5G ä\”å)ƒ„@Ö°rÐzßǽ1Ñ?Ã*]Jgµ4 ~Ï/d36O/)Z¦¤„¦H+U'´F“‹w54 ñÅÄ5qSwŽ%R*²þÎÍ8Bà\³è-±)Ùý‰Ú¼ÞÈ]ÏfŽÓªbjUDâ):ú•²™Fô¦N!9LÖfùe4Hzº™+{°ê ¦ØQãÆ:C˜ùxÚ¥¡hHnÓï_öS£*ñÙ‹#ëTåsAÝ1*ƒu”–Ï ÖZ^äû&ó ¥)úAüTSS<ŠJÈMôœ)$ÑSþÞ-TΙW)J‚‚nìMåKÚ$jI¹Ëf5õ?ZKVMß^^0­agVh,$ÓpÙôȲzÞ³„ä"çlK"óÞM£G ‘¼ËÎ33|Û4Í]îg˜×f¨r¶¥Ú•ÍÍ÷3s~8èV5-52cv†XLi 6–Ät„ãã÷ñjª×ˆ“ÊEÜÁj4r,òÃ.c¤ÈÑ…Z5ÔSŒÌ@€ƒví›&)«˜ë”H‚bTÍt”0®E@ÌâA ÓÚÉ&l [ · ‡`ñ¸ucç]f¦xvüí=˜ê4ö6²ùß^¶ˆeß.ìS´ìóªf™b ¹EN ©èh¶¡Äݰºà#f锩}ü¼ ‘J@CÀÁ ‡ËOLv¯áÃgJ¶N»0Sw¬«)JˆRØJ@“Â~=xT»y\fË_õm?ª8kx|±­ÅÿíÊÞùü¹âyÈ~Ç} ;MÉ;ÉL¯Ÿ¬ÒŽp“IYÄýŽ•ˆxá3,ÙŒ¥W:ê2žg$ñ"™F1JÉ~i `ÍɽÜYîĽ˜²Ã´Ne:Íœá£2Ò§$õÔ õu#™5ëÕ„E=DÓ3sq²[œ:³3È6rŒsb•»d—|ègô!DTݲÒVŸí3]™Ù/.Õµ'—µ=Fþžªẫ7±N†›­*x$"y8ÿƒR±w#w‹ÉÒ ¡ˆí[µL«bjÈrfͶ°Ÿj_”•%+B*{¥¡u5jIJ½‘§KIRTûÉT0±ìÖÍÔæÍ"²­ÅÓPü­Û?R[Þ-µ ŽñIQQ!{ã95ø8¾Ÿ¡èÌΨf¥WS0‡”¡)-ªl©x²¨ÝYù‰:®npÎRB>)e¤ÚšBŽŒ+ÏavÌJG„îqÓ æüÿŒ°:mQf½U™èºƒ•¨¥³³z~9Ó´{ÙÅØÀÐË4Ä;T™«(É": XÉÄÅÏ¥ûDe~UR…« ªGý°jÃecŠv‘’Êá˜É0‘}*éôdZÖŸz³¤¤X:x³x¥÷‰ f¥N¡ëýÛ¶mq—õiMvhÉÎÄMk‡¬¡¨ê‹´ævº®³j¥cKɼjæA¦[QQgÝ”Š¼,M[R®¢åp“’B¦Àè¿]­í;n«žSÎmcIKTIb‰” KtÍ6¸V³©JT“b³³Ù;(M K€SÅo,žeN)POØ€Ç6{Uþý˜²Þ‡ªëê7:3#.ãéöŸ÷ÕÛ(<ħž¬Æ%Yâc[ÓñT}PGî VI§þ£r˜‘e¿ü‰øc†íÙ2²´ä•_Y B±…€¦+¨f3éÓRT±A1ðÓð°R°sþÆ xi¨ÆKº+GaÏ+‘$Ôú¬­²ó8až¿«ó[ñH‡‰lÆŒ­høÊo){!ezµÙjÙši-(A8¾m%ùÃ6 ‹dcá–AR( ¤9t»…“ó±—áîç/©Gý§êìö­â(ÚB4'³ 6g¡ÞÈD¤ ‹)Z˜ÌjZ=Œ‚‚²ë Æ,`ÐhUSe·")¼d=®m6]PÚswÆy—•$<ÍSm&­‘¼ºz¶Ð‡ €Bj ­ª7–UÞ%%fÌeï¡F•ð J›R‹Dð iEIÝꀕ Nð§ãIh`8 Š[€Üo Ø7¸ˆuÜ.…ð–¤-ïîp÷Ð/ËÏ6`AEQ9“3Ç0K–ùÙü‘©³2qETUîV#UOÓP`E®³„7röž”Œ<Œs•X?{ífàܦöd@<0À[€…íË]­aØw¸kåkc©rJl³j²Ê|ß*Pv™ô¥E {È_»-­$JT ¥@èEøœWUNTeµ ¥©®!QÑ@ï5œx 1’@@@—Û[}øàUo a ’ÜÇN»¡{X’ Ãÿ y__;ùyŽ;3Ø‹²[@Ä'šYÜÊ™ŸÌ+²Z…Êj² „ˆŠ§£NeTV©®ã$Jô\K9j‚‹ÂÓ2¬Ò#ðRYË'R*2d;SQ“l.R¬Û72T®æŠ²“U_Sº–XJ ¤{ï¼¢PÃr£¼â›mÃrÖ곊¤ÓRÅ€[®™îÙnÀ©dq:%ÞZ¬!!JO>²K°åšT3Fzf›Ë\£# l注¶‘‘TAÀ4ÅQqÎÆ vQt¢ ¤»äâ<*†UƒçeAp%àÈó*³uÔÌ<Úð‘MV’¬;@f5G–¹/–ðPOýŠ¢Y¬;˜ëò¨xbHÄV……I!Pò’‰¤ÕwFìüþfÁMPõäE—Y•Õ-L×¥«¨ü¯Ël¿ªŒ[Se¹j\èæ¥T œÄf’ôÂ5 ±…,ýgmá•nÕùçTIåüv^eŒ©¬®¥‚¥®sÓ³yÏ0Ú< ‹‰Šw¹qOEÍ¿*u•Mv@íC6E:b—j>Ân]Î{UÚÜΡj£¬%&ñîi2Ô¡ BgÝïkƒTóú·ÛhªJhÜX´›7–S Z5ŽG¼íA$Çu ChLè7T¨å¨‰Ç6×ü7©øYHzµ6l¥YG:’h5IN:¤Ýž>1dH¼e44­(þ]³ú„ˆ4¬RSòÕ»£,áU|pά¬ò"¨mOW1à›9ptµ-R ƒ”aêflŸ:V<Ïn±±m’’f²`v«œ Š®Ú(Ùã¨øºê¬GþLÇ0i¸Æ’Gc7<ö›¢)c¤úAÛ´¤^´l¨»jŠ%á#AY ^àÆ(â¤ö»Ëº£´þQOшFÉÕuÿœÔÔ²qñ‘ç¥êjV1Êy£dÎ-$F²kAL¿Hýé¢f ¡Ñ@†tÙ>×¶“(¯e9ÕZó¬©Å¥-V% ©a ©êR”¼T‹Óªqµ!%(JBÂ|Ëeè*YQ¤hRT¤6¦‰ ¬¶É)ƒÁI IP§ù;Ø‚°ÎºL‹¬hzv=I7±QÑ3œŒü²ì@8×eͺÿö'9"›— !Ä»D1¥IE¤éÿ›4㌗y˜™~tn›€z’SжQ¸¹p"ÉGÇP‚ÇûlŒC«Â å1L7±EX@È|¶bíjš„†‡£ \î!w®jŽ×ªVxQYØsšY"ºE^5ÊI¹fn ÂbºË÷‰ÆKÔùŸX±d²`af«Ô,;“G W‚î9Û í\¦"F’*GQ1â1Œ)¤Ìÿµ½¥6Í–ÔR7•Šú´eèU2ÜH}i¦ßqh+RÔÊP¥’IÞ&ñÕÌÐ"šœ¾‡MAe¢ù8”÷Å .n¤BäÈcæ×´–H>ìõ\³ ª ع¹WÔä}J Æ7xÑšI¼’fÝ*/ ãŠ1UNEÛ"b$²c ̬Û@DA¾›ï¿¦ºl,7n\Ë…ÍŽÚY¡1FLžrŒŠ=5KÓò`ðÓ|Œ1ÖeÚ/YfÎ;ªuÛU[¹;eÑ·¸ŽxIò)X@4 mÎÁ×P^ž“d™FÑ䯮­´›Û®¥)B^]·””  L€ <0‚²º °ÓJ÷O¼”“%)°I$ž$žf#¨ØGn`7çÌ/§ˆŽ‹—ŸA·¥þþzÈ'n-,}·û×åm°ÐtŸÐ~_Î"9£A PŽ&má~‘¦‚ü4Ã2䦟§ì<ôŒ"¨¿€ßÓ—×àÊ¡¿ˆ_åý`¶#jüÇÖ·Ã’tñþч=Û-¯1ÛËïï| RñÝÇ(L¨zôßüá" A×Krý l<ƒ®ÿzàÚD‚Ûˆkál’b6‡Ó¥þ_º»vâkMKê:Ø:ˆu¸[7jjb£©õ·—¡3„î.8õ±Ôôõã¦4I®xê#ý릃ñÂ’(Àl €~ZøxßÃÛ³°À5¿_Qúé¦PåÐv¿–¾~_@ÄŠ—-R¢Rx§§„p…Ú€-Ò|íŸ 15Á6èë°ôÛËìë}\ÌR·Ú|íñ uÖöÛ¶·º;ÿ}6Þ÷ ù_v1£rû»ŽÖûûÞø˜åyJ‘îE [Mzsá~6j¨©?N¹NV‰ ܺ ÄCmô·¯ÓÏÇœ7@zß÷°ùØC\5"cå4ð_€‡­ÂS‡Žû€åÌyˆ}Bÿ0¾.™ËÊ ,¦|=Ð>rxDs‰æ/ÈVŸæ'—ž‡LH )è÷ñ W^›Œ º.€Ò2ŒLäÅlU(¦Ä…ÑH¥2¼@±C½9Ä 8–]Ò ,¤hj-áŠÐé•TéÄ ¹ ™8KÁ"å7)ÔEƒ‡‚÷⾸¢© ™Ìz*24²ˆ³ŠM6n (³¢»÷NRÆIE ‹l:›Q“N$Û4Zz=»p<±_ºxÙ“þ4A!Ãي*¦%²Êâ°tàݯÌ‹mVÑæ@ï"·;Ìßjó .±ßgH¤í-]4ê/áÆÏý —ÇpРœ¥@tÈ¢ P3pMkð¢sˆ\.k_l2þ6AcÚ>UDøŠZbªª‡ +»Cpwá^éPÕØ®7½ÙÁû{˜¿gk…ãÉîQ.»8DÉ ç­ú?´b´µ+^æ %Æ:6Œ¡ÝQÔ+T“]’¬ È YXŠEE‹ÂsœM8e6k™NÄQ´ÀºTîei|åz~ð«2’ÊÚ½ˆ%0V) œØûN~¹„1Âüà̃Ó;HµqݸšvÑw¥銄PJ¦·5’D¢!aL{Ž..Qæ9™å&UCŠö+ᯡÎA–n“hÌÀ m.~î÷@u°ãÔÌÿ³}œ9]rêvÛ¨¥Úœ¿4§FêS¹C³¹lÖXÚ×ýK5•55k2Bž¬Rà©Kž?{…÷œ%C¿§q‡Šl\0·’t”¨! ½ÁÓ¬öÍg•¡ã«î,úµ…iZ51ÌPLõb­Ï\FªTÀ@[ËÍ5•"È G N`ºE69y[×2tÜêú9{5’MFÒðîl³è•OûÈi†ßüj÷ ”{µ @U5ÒÌ hÛåís%Æew°Ð•©Ä&¼>¤‹ù)DŒòN6)èI6ª»LŽ'Ë÷Ò+ƒ…7ų.ZoóÊò}:Žj¢fâUí9K,hôY¼Iê‰ áIW)™dš}©T“j©Nnb¤¡üdv5±ôµ›;—e{bâ(Ÿ«ËCÍdÙJ©Ü¤£¬qª^è¯>IqË,¸¶ÓüÒó¡ ºF,ºNŶaš•=”§¼Co*¦§¼Iq R‚⌀¡¼A"L ¦IÖ˜J—/ž9bº@e&©%\Î¢Õ T; ®ò4ÃqJÿî OöÍªÏ;Ûεüª«dÖA1$tß"E8FàÂ*¼AAµŒ$9¸êþÏJ3³fFÀÄɵa šy—UEåÖSCnDè¥RT­Ä‰Uª‘ÉÐR™¤È#=/Ä`+†h{! 'pâ­j^Å´^]ågæžyg9”mdÇ$»>fæeOV¹€Ñ%П(èø F6œ›ULƒôŸ®È*™ÌídŠeÔc«ügöWR¢£—m™3#{(ʤLIŸã¦ýEζÓ»(Ú6ãùùM£JšžoûOWÂ%O—t}@U^S.¿+p­Î ~&æ0ØÜ$>ÅÀb€”¨ˆ_æ~–©)Åß·9Ó×…vár CN ˆ…¼JaÖÉs>VÙ”êf4ßeÌïËzM'‘Éæd×™w¢N_¼hÐÄ—ÊÔ¦&ªàtý諃‡l´X»#é‹v«#l¸Î¶uü:nŽYºÅÖœƒÄQ Û „}ฅÄ@m‰¶Áö½±ý§¢¡{>ªúg©ßqƒEš±OMX°ÛL:jjš®±*§—ÃiZœA.!ÔÂw‹Fs²ù¦Ï)´0´¸”¬;L·h¥$!J[M{þæñHI„”’n_ÈZmÃÍjZ˜œiO¥%ªgrOÇ = ‰ä¤›‹‡o&WI LÊW)]¾@@ä2„í¿gÇ9o?•“/h î¶€sžU$3:Z>¶uòSMWrEV]gÏcéohIòdN: q h“¤“cŠ*¤™9)NgÞXdiI·]”iîÔS# ^'C±Ëª*ßš’ ¨$j:Þ $T¢¢³›)³ô™¶t ºnƒ²ñ¨Â~%ò·³}qCÖy!•UNdJæwæ~Kä~fÆeÅDìBáë¬É{KEÇh{ RœŽt¬«7€Åvè7"øâ¯ÅNižæ›xÖX¼¿3g!Ùê&ir÷Ü£ªn†ºº±¦«3*ÊW–Øeò ”Ô SJRRªº‰¶»8§£§É•P¦]msÊqä%ÖÔó,´¥5NÓˆ ÞDî¸ø ðàJ¯ä¨ C.«Ãkþœ‡¤¢š1æq’ÿܸ£vd£ªÕò>!)Z†z2m'I‹ÆÕÅNd¾QWí^ ˆµzØ¢’•lu[¦¹L²;{ì#!ì«g2Lç-Íê*jóá9Zèj7eÖM][µmÿPÎÓ°Ë€Jf­½è;£ ;¶U»I_WKQJ†ÚbÔPº¾ù–ÒÒŒD¬8â“Æ1ÄáV'8å3j®¬êj²¥G1žfcš^(’RuU–ÕTE:dž£ìðAzç*â5”búq‚ŽÝ³–JYýJÎ1Û£>rÒ’´wgC­;UOU Ò•«IçsÒÁ$Áƒ$jg”õ.¹­ ³ZrÅü2îÐÉ™ô¥PŽ4µrùeÊ2}pWåëñdƒÎZc¶¦RdþyÖ-kÍËnϹ^½j(ÒtÍ*þ©³Òù敞NŽUzfff˜‚©iºuÅGOû Dûx–Ó_‘AÌHÌǧλ'ßÿĹ'³þ%K¹»3%ÔƒМN³-Ï`¬ßÏgszyœw1LÖáÇ]¬%[ߘòéŽÀ~9O˜Sò§SeíwAÐó½Ä '⨧¥*Úк iiXF1©ŠÌA¬a;r²½ÑÜ´* qˆ‚œ­§!˜¢`ý($½¿N»ùãèÏðÇ ÛÓ]œe+É™@’°™ªgR¨Ÿ°]+í0œc)”Ž‘ÌCISò¼L½ÃuVYTÌà§RGПÄMiÊ;«iJÜ:©È²tQY¨o2} ÇõÓ寡@ê…/Ç~´*¶­¥ )¬¨#Q³NƒbEœ}bØžær+µfT ‰‡kNÌsSRRî°ùÁ’S4Ü|52X³U¦j¨¼Åo,Àˆ¼)Ž·´@™$ŠQ8®\r?ñå®s†’ì‚æ˜Ÿ®; ÖtnofžTÑi-Ù~K1]U'ü²6[3ݼt3Õ˜)*Yª= 7 ÙÑšË0RΊ’‹ »¶LÒUëÕL¡“L ݹdÓ2¤+÷-Q.ºE5/ì»N÷TÙ\‰Pä òëò¸olv±œFbR²¯ëê+³wçDòßöTĤ]O@å1[·X†“áÍ Æ‘¤åfQQ);„Ši.ë1m튃³›oDòŒå¾Ê?-mKiÍ*i‘O“´âAg™RiR â)[KÙƒ­±Fê•b‹©¤VÒmʨdšfÖ\ªRO大 .€Gå.–¨÷VêU¤Œvg%çòó$`ò+#â2g²¥mš’02ì»Ìç§"b¥–J™üÑì””J S“•;—ý¹8‡$EÒk¾:o$޲*¬±u¬»aÃVã²£9{Õ´ÔlÛ†1°•ŽTS]œÑ3xó®ñXJâ}sÑë5w2¢¦;¦Q´ó„Û, œ©ª.<ì{”Y™NJW=¯ó&bá{E×ÓpY‘ùã?CfÛü¨£XÇO+?\C×”Lëf4Úu˜48XïÊeNÞ&%uÊÚXQL~.ˆ=o•¹Uä è·£žEaDÎV‘u…òD´dsÆÅ®Fдª—¢â]¼r'IHÕ+™BnZe¤©åÞ4óÍçªkª¨¨uÚªºÇÖóï:µ:õECî¸ë‹Q*qÇ\QRÔ¢T¥(’I8¼P†Ùm-¡)m¦”! (BR”d¥),a{´§âËØÃ³,Å@dæLÐõ¦måÍj•MR§Ù8|‘˦RŒ“véi¬Ñ¦Ù¾¬eY$õHÅŶ^×p1Žìã"¤ƒOcV>§?HÜŨ.qvZÍ4)wo3Š•ÆqDçUQ º¨Hˆy\»ÊFÌ2`´¢Ð’Ì=1DÞÈe;°/²$Zš2í€æ8ä*„¸ ÀÚßè!nzâ굦"š¢TSd€¡k :-,;¶¿Lu×g?…zݨÉÎsüÅÌ­5­¥Újv ¡µR¥ï@ ÁËLV÷hÍeÕ‹¤¡§MIiE.8£ Þ|þöî•mÛ(ä‰@f¬¶a²©ª2ÒY!“™UL)T×µVb/ ¬œ:3Œ!OFEDÈþtò±’oS0tŒ™™ÂQöÓXl¶ì™JUÃÚÇñ!¬YWSISÎ#»&µ­ŸW¹IE¬Í˜kYRÓíWwSÖŽ«7Я֒„lñ6ÿòH‰RK˜sJ†O2rö9’+BH;¦óHì¼D‚òtæ•L“Š6S»lüµI1p  ¯±RLw&VÜVô£ W 8ª'22±y0ÞB¨©¨§¦œÎ9—t <¦ê:,âz^¼d‘Ö"ÍIÛ9xõlî6Umì£Ï]¦l%_gešì¥Sâ¬Qû3ô•a;¢ªŠ²ºŠw t @Z˜z=Þù§7}ØÄãgó–³ìª›2mÑw}´L÷o4²‡?ÚH DßqI›Î)ãœâ°ÌØì«í%#DÒ°4`ŽQÑÔì–cQ©—\Òð¯_ÄÒÍZÂÀIQÀݪMRftV\%dVç0¡Ëh䕇fì¶?x‰ &µì"áϘølltOñS¯¢vs©¨yÔ³ªâ¤!åâ%ÙÊÉÔ1ÕhÆfU áfò®c•Eƒò³$ñÌ ù6ÓQ)·U›„\3üÒÉUÅý"ÄÆð¤P¿†öÓ†¾펂ü,×¹W[œd¨­ží5l ’BT7÷EâI“žâÚ3)mªJÔ€¼[QâAˆ›t8¼ý’òb¼­Õ««FÒkP9zâ*FU¤84NJzqÛ“ >ÈÏÐ]¡ˆávª¹’ âÌТˆA%IÖì߬jÊZ›¦ªÊ_,(|ÃQZÇó–ѹ–ÙÓé™Ú–ªªØF,ÒRqºSŽÑœ‹çŒã˜Æ"TŒÙÁÛ°)W†ˆvAgT×ï"%2JQ\©ËŠ8³y©;;H&… ›Y¦ê]y¨:nB w7uÅÞfQ®UY(&Mf)çíJPÖfV¡íE™î[NÔ]â2… «œ%5;šôEbò£¨w¢&£Ño ÝýÉÖÛsŒ‚æL8ËŠ[¶M³;e¶Ù“´®ïä™C®å9*e¥SS,¶ýr@;ªVcP…Ô‡ ,ÓVW=ÂbY²¹Oðœ¢.&*ꊚ²D(8´‚†Oä †Èw¼ï?9›4h ÞMªÕöjeÃhv/’ŽË·>ZǯN* ·r”s¨Æ È A#1}%¤›SN‚È4ä¿iÏÄ(æŠaÚ´ªbde%HäÖO£WÓÐË…M Ùú¦¼¥áœ¼P[™¢í¢ß?“jà‰¢ö9šV\µÿñí]˜”\$nMÇVÓR¹ƒ[0‘qPHyûð¦i—®Šyì ¸¬Tæª'Lܶi ÍÉVŒnÆIÂI éÌcÂsk'òe¨¶FRY9Ž9 rù0ÞØcØM‚Íöó4N_–£q¤A¨ªP=Û(‘$˜‰g9Õ.ML_¨2£fÛÞYä:sÇb2Gñ4ª³5óÚiÞKQ«ºÑUpåuaOÂ;UGÂ%dîJ†¯ê–ÖlnìΦF:#‘ ^õ@!mÔíwÚû4êhìÉj_³ÕA:Å»ôêÊâ2·©ÞPYrG¨™ÄkÊ’ XFõ\*înôí“u(œ‹„È Ì­Ž)ñ¡ RˆÁ¿ )”tЕþ?Lu³>q˜È´r¾¦[Sµ<­`íÖ`Ö±3ncë Ñ6o›KC ÒMÁiTi°ÀE»20b³dlÅ‹ÚauÝŸd4ÛBÆbœÆÚ™£ÌÜÜr•u WpúM‚™S¨î¾—h‰J•¸Ã³»bÎwZå éÍ;½Òždïo%Ä ôYa'xb¹‚ÚNÏ]š²ó%©Çòyƒ[ÊgeP ËSMè¸sJ2Ë­H°É½Sývðßà8f:ÿŸÿPÃÆHl&ò¿K[ùÃ5ȇ¿åoP ÿ8ƒg$w«ñ1¹ö8w¥¾ìrä“„…yÿõßpeQßÀ-ñÿ8-ˆšÿ1òú ;§AРÂñu(|>vÁÔS?ò°k§Þÿ=ôÁbÇË\*¶%Ì…øè?ÎܰõLåGÊ÷?o–8¨ÓKÒÝp}³pî=5ßqôý­àçfÏ‹‡Ýð !åÏ×ËðEŠ7µƒÀ<@4 ôb;_hæÀ<:.CýÃ|M²Š.ô¦Âñ+Þÿ_†*žÝOC©¼ë±»8Þ+0éãðßÄg;H½ÛmËŸÈ|CÏÇ ð°îdµbÅùãÕÑhÍâYÓ• ‹tÌ%)Ìk…)N!År”àډ̆oA¡RÉÔÕcÖJ½z®_S*T4lJhÎ=ªT^¡3f…°8~¥2Õ>"@%Ä®³4Ùí™4‰ÎêÍ*ªÐµ°”ÓUT!¥ -JövÜ­1½»½}ЭÒ0ÜÍ=vaÞš6»ÀÑJVK·@=å¦l ¥§\VÑ ÷oæéáqßm-·†l£=Àߦ›ëÊ÷¶‚#}6Å«£²&ŽªÇå™ÖLY G.(fƒÕ¤`)ŽWM”tƒ´LÞ"¨&`5¯ÂQÅvBR Äì´TCßom$ù“g'&£–í*‚+4Ž¡:ɦU B(©Hc Jcq »d¶‡d¶Ž©Ty>b¨e(RÛr–¦”²RžìÕ2ÐqR•–÷ˆH0×™Ðæt j˜îЩ¡ÆÜÐ '»R·DL áN9˜×(X-È@Gùæ>¼õÄŸKE–JZ*4N(BA“-Æ™;r’W‰sE9Ž'XäD ^% RÆËF‚";_ãoîþ7Óe‹T&úFž¨êˆè¶äÂÒŒb$瑊‘°2ž“‡ŒvU™Ý"áúf ¹IË‚¦ÝKw1ðþÍçÙÉþYʲ\ʽ$ëÞRQ<ó`q’´%)I$s8Œ0Mu}.¢¦®‚:8ê¯ ’Ià‚12=Ë ‚2R6ˆÎìÁd´\è¼~©:Ö4Yðé·ŽˆWŒî2(ª2çàfçà­H#˜¬$^DÈæWÏ=‰“¸“” êgkÔÜ*¶‡j‰KSΖXš§T‚'S-Ìr€¼ «ôÚÀ¡ŸÊþËH#F8{7—+°Ž`S,Ôün›RÏeeb[§ÇÄ»·Mš(ˆ¬¨@Âee˜™`…m—/éäËIÌÚœ5 Y’.»ŒR¦`Ùú)¶¤æß&)œ)Ç°Ž’"&–‘bÑFâ¹[¬:*”Þcã ñÎ\Øw1VvÀ¬Âq(ô^S¯!i•ŸöÈæg‚†hí³WMœ…Ç8(‰:„9;Òƽq?ì³l™mî¤@ßÿPñä#ñôÇ92D…ª3N­©zþ] JšrM¼¤²Š8“‘A죧(>\è5:¯]$©t©Û71–:ƒÜ#ÿÆ^“³d¨‘0°…ŠmaßAÔyó¿žžŒþr¿bاë–Õ×Ö©@Ä–Â@×[ȱý¨žÑj{ÜÝ a–’á*¼ãai·Ž’5;Jg-GNÔ”UÆ]eó—EN2J ¬£^ÍϤ™L“³¢¡ÈÕÌc÷©4ö‘NL‡ f Š\G2©˜ì‡“%Cg&c>ªãHBHVê*êQÜsW >zݵ ÉÅ“gˆÆ&©Ò:…`T×]7"¥#.©yÔ| •®kúvmeª Œòú²§ã·Š#pbÙÓè:‰“¨õ«¦‡–9ª¨@L)”I*ËZTõÅ-?/#šÕ#²¹r¨9¬(ŠJeÜ«I–¥xgS´«#±I”2 "q;’ L÷/œ‰ÛÎoükµ½´© E.dÖP€ ¥Á¨©²·RžSQHòÔ?æ-v ;c)}“fr–È…9NjTyûS®T$ž~ãˆñk®{”y#•âÑÆGet]"ƒ&J,Þ¤q¤ÅXôé2Gs•«i‰ªý`O…«%™ªˆŠi¦‘ RT“ËÈÊìU%_”±Ù†ˆH§0g€¬ttÒRI UûÂÊ´,LôaEb€ 9Ó_ônþ}g®Mdmää«ZާM¶¦£Ô“ ”®?ª¶ZJpŽKú5ñØ‘Ÿp) k¢`YA1•ï”b¶À~#ùfY'ËNVlŒ‘X;Dç+2©Ë~áU»¬£RTác‰K$Ÿù8¦m‡žËNºF¡¶Ô²9f™ùÓU–´Íê¢j«™U4“N ¯²³MCª›æd*LbãÓUU–N:5³FDUuÕ"QUNiÏìNÑm[T¹~[R®ña%Õ´´6€HJR€ÂÜÚ†…¥8ûè JR£€8'OÆÔ=¡ó]ýw+ ÚÓóŒ/wJÂRP]E#iØk:‹ 6 ( u”ùó³¹~¹}¡ÒƒŽºÐQ 騆‘íˆBˆOt× ´¸k¨i b¿eý/H1A³ ‘2Ž0¬:Ø7òè;Úji2ROËMBÚ·ÞÁá ú[|z=دgÙwgyHIÜ7¬ UmH‰I€{¤˜”ô€L›â…ÚÌíüúªaH¥j{¦É"DˆQú‹ŽS‹÷Jйúç*"ꬿ¤¡khYô–‡£fNÅ/Q<Œ˜U”“˜ÚÎlƒ!ŒÍÄ{˜™‡Í½«òïjADˆé¸žFhÓ¶ÄAqØ…ºQ²è¢ƒWo{Aå‹]“PT®œG¥O«2 ‹"°©)cÇ &«*h>Ó½£è´’Y¨NϽ‘r¿¶Õr¹W->×´¦u8œdꡜ¥èe*w)ÐÍe”tÎBeªŒVAdÕDUrͽ˜K6²BqÅ<ÉŒ ŽEÀÃSÐpTa³Úž^–­ê8HÃ,ÐÎéÙ×­—¦$Aû• b=‹›t›³.é]0<;P¬^aÚFÞÕ¬’]Û £ ÞüÁ¦ój¶™Iº„¡–ÛI‚E­hÅé³Í2•¡îWA1¡R©ZR΃ó,“§r“ñN_8iþÌTÌ]qÙ”rB ®Î:NžFeÆSùœ£Á‹„©êô§¢¦ø¨9Vr”±ê¶hÓ»ïß¶0#ö1b)ÓpEu4ÓGq ŠcŽöèÐBÂ7 …æÇ˜¦`r[³Âñ/dŸ<šÍ´ž‘W]Âí4dò„r‹æ¨¤ÝkYÑDœ<|d@Ç)„àf#§—LÞ€ð‰¦B[ÿ‘DÀ5½‚àQ0Þ¸€®Ñ§äs0*Š#L¾ƒfÔíÛJS´-+"ü³ôªâf'YqDˆ5|¬”n…1 &Op“"jJ–ö¸îAŽ‚S;sðw’—«¶‡7RNëM5L…å™ r08xôÅEÚ^ë44€ÝjS„t_<°ð4Šr NÍѸÑT¼)‡A(€»ëa×Pt  »#oJ¹iCe¬õjý.¤ îU(äTP©•Ì«¦È¨Ò-˜ªrÏ$Vlئ1@Ê—ˆzÙcðÛÍ®ÒPO3.N¦(x§¨¨ÍlÍ{UÃÓµcF®–JXêËÒ‘¯ŸÃÀ4U©ã\ËíÖUð®Ö›§;öWo<µ#PU/2êbªJ†§æ[gé²™˜~³ç “ap¼¹ŠŠ\zU{òà±KxrŸì¥”òÇ™tŒ,„ƒ gRGÊÒ‘îÅÇÆ2n„»'î§ß ¡j$Y‘²d)Œ™œ&¸ –¸å‡ý¤3ߟVÎìŠ*,â6wgèP¢ž ï³Qš¾ X).¥cP LâÇNÁä+Üöá]™–ÿ)®®x€x’šcLƒ<ŠJzF(…ø]öuìZÚ c>™Êv¥í#:FÒ4fOÆA<ÿ¦´ƒ†©’Eóªµ4×ü¾¦F)³w¨˜õ[†ÔüÂÄ#rSYT…935²&?'¤èlÉr͆bÉÑròÔ&gRÐjRUnPÀG;ŽiUSŒ¥áßΧzî.r!¼ƒ)ÆÑlgÝ(Ý©n±ÆÍ^ÔÔ nNÉç†nS4ÆngnÅEeNRÑ•s—õÑ#j°_é”ON7v¬±£ ì‰ÔRË4FŸˆ"«AÒ']VzTù—yyœuµiPKÓ4öOd¤t"êg„ïÝÎf}H´) õî â™`ÉT"Í+€¦lU[M¶;U¶UMWmNšgµ ¥h§^cTãíÓ!d)ÄR0Hb• P Z)Ûm+P@$y~U–åM©œ¶Šž ¸m(SŠ\_çp€`©Dmq!voËÂÿ†^VTµv]å¶aHדT¨´«óÍVõ`çuz‹ù—JD¹“}ÅâÇ•qQ¤XâF‹x–ɨÔîÑl ÷¦øWí[š‘]¤ÞÓÙ½MÔ”¤4ÞkÈFÇSµ{Fìj¸–´Kê6ÕÊ*‹Ã3ßJ3*««ÅnuÖQ3ªµCö³¨û8×]›û8eÄ\’S0sõæoÑ´ÅMWÑ1“”–aFR—”]Áåã’2-K™ªN¦€$ÜâR|äD¬Îaæ%g™¦w?YÔóÕlãµ u æb¤•w3&àÊç9Õzõu sŒaj#‰oc9IÎ;EÙÊmÝ䦵·–"@KD*OÃá8lÚºŸeȫܘ%•$i$¨|qЦ‹wm‘ ŽÉ”5°˜ZÀ|CE]›iÞÖ^MåDL_áöjö1Å)¬bËµÕ —/\Ãθ^¨ W”‹È¾í“¹óÌÒ¬^™Ä‹2¸ŸYÖ1þs£Ñ;Çl™$ q»rݱ;´Õp§…H‘x C®¹îqHu7¸™Lsê3'§òn·ŠyKæ 91ÌB3.]0p©7"NF fIK7|Ù 83¦Í1Ä b¦UqÔ_Œ|Ì1“l6@…Ú«ó<ÕÆÁü£-¤¦¢§R¿ÝüN¥(‹Ç8â»ì²›~«7­"í±ML•=ûŽ:°<=™²|S‰Î› ûgæ3„˜æŽRv=Êø¨9‰·TU!7Ú6æ6;Vî˜@Štü\³¸—îM‘dŽzT2n¡’"¨üŒ~6Õ?V~'Å˺B,‘t®EdþSeœ3Ol;çK¥#!šëLK¬²)-ùäÚ¹ši)R8Yó„X­NùB·MÿF¹¿QåI3dL£Fusjŵ/2ÿ4 ªT¥?—óI~I\I½”Šw6ÑœâÞ]À ít“`Ež$‘Pns§ñ›U8ªûf缬³ÊbYãج Ï+E/.î”N–›uL´•¦]TiçPR-"}îlÃ.é¢é8’lQlqÿg™iͶÏg¨Bwƒ¹•1PÿJ\JÈ_¤âÒÏÙUs¤ÁM:âñr"ß]Úy0mÑ ÃCi¡CLuC°ö[æG—•ÝU•ùùPäE@Ú¼¦KÉ0ʪ;4b'©úv"BT.ʪAÓ9ËÍ0 U*6Xá)ø5ãU´Xn‘I@:jm„C§Lv'²>j¶ÉÜ„+ú£.;DÓôÔÔó³B/e%rÕ𺑋h›æÓ{—µZ ™3`Õ¤¤ÔŒb¨ÙÐVh‚nï¯Äîd2ŽÈËP ƒœæùN ÔŠu/7P\$ ox$ŸxJvyOí[P"}’–®¨¨ÿs‰E(é?ô•uÔðÅÐ˺ÿ´=?9-LT] û6×’ôµHp PPU.Hf,›¬ÆápÊ“dÚFª ¤œ¹ ݬé.%ˆ’½Ê\GT ~Bþ;™¿É*)ó§a­sf›‘üú•®áj5ZÐÔÕKí´³ m´|´qK#9OÊ8–vð„2ìªmT+®&³Ælö”ÉTsK(§òç´–KÌÕ½¡*E²³4†5!Ö®#XI4EŽ^Ud:*Ž–¤ßµ#cTRñL2)´\vË&§!ŽËîÑY-•”‡hlàíì4|½q5/™Ù…˜1TÜiRž<"(‡qtä;6‘ë!G¦¼ˆ§!-íGN<ÜqY“Û<àÊé•W™PÓ$oê˜l™ßq#õÅõPçtÃÎ ©Sà:á' ` ΋I4ŒuWM "d!…E{B”Æ9Ä@ R…Ì# }BÑ_‰õ‰äühNÂ9eF ÔŒ2ò~œ¦«ª»3 ¢8]ÜÓ–±3±ªÒ•5VíÎp«G,<]ÙÚ¦™Ðâ¶EÄD^•e8þJ&¸„Ì„+¦ŒfšÅE5RRAHwoMì¥ý‘šÄŒp±_™¹ŠÑáÊV«uùßý6x9xÞ˜Î^ÐÞ›{,vôþr@¼ªÙE>ï^~*®e! g«:á!…6¤LÉðÀsø¤¯9^AÙfò­Æ©2góÊÆA -ׯ]—¸S0 AœÕ)$( Ö=1í›G›¬JªEK:„¤­÷Ò%oS-?NÃ=˜ël­¤r£´®tLÔ9šHËæªÎd©ùV]ÊJ4kIGÖN[À’iŒ£h$W: ªXtÑpé7…Ir χ,k¬ÞJ°ìé' ”y%KÃ0¦¨‡tíi;>éX†å4ÄõISU ¦*:š¡w"© ŸåñÉFäѺ©&^‡CS4Qóªgg3š¯~“§ŠƒÚú¡§d&™O±-2ø_TtlxǤ ªÏÆìîMOw»°LSU4C¹çñ¹oSNAGF:e?êZAª1ÜóbªúwÚÜFHĺ; kÝ™ºi»l ¿TUïLsã©j]£¨f©‚€õ;ˆu²¶ÐêР¤•6âT…€@”©$Å¢ãiu msº´”ª Iƒ¬)$z‚Ç?à?ÚÚBÎ4™AšE)—‹E1!ŠØ«9húq›ÖƺE?p¢g>Ê ðÔŸìÁSÓ-IϽw•HÊ£z¬ÚÐI(Ú()æŒÝªUãO/:變õ2¦å¼g²C‹¾9oÔžÍúnBEÎbV}›£ TdáhæÉÖÆYTnH’f3w#R'UG¤¢‰€*b%.‚Bm= …±Â'{™òõ÷j<¦AW•ŽÛÒ¹m™Ž&‡ªË80êJCÄ&Ágê¬'¸5Ônv(. S Ÿ­7âk¶JF¦§ÚjF˜am¦Ó³»;BBR',’H$ë&q_gû*âÔâò÷Tµ¨©J5ÕÒTL“jˆ¹Â>]v|c’³Oª‰ÜÇc'îšA7éÔ\Ĭ݉x窢•*€ñÉÔ‹IdA/h*†)ƒ@á4Ÿ—Ì*œü†¨ŸQÒ²™“qÑjÊö¢"Õ {\ŠH›Ô`ÙJ -é¶n£œŠH„p¹”I0M±ŠŒÁ††™õÓ"´i !ÍCN9”‘3ÇÊLÇÊH'ˆM%ˆÙ)vRMr‰d€ühpà)ø¤|ñÌ´Õ‡K(¨¶­)fQ•7-XHL¸NÄ:Xщ(´pb™Ìœ“„PBä"†ìm*½¯Û-¡Û¼íÝ¡Úzäæ³ÌSÓ9PšjZD–i[îÙBX£e†º™’–ÁZŠ”¢TIÄ+ʨrjDÐåì–)µ¸\qÓ¾áÞZŠÝRÖI<Ô`†)/âCTP°]…ó3.²j‡JeYgrùƒIgñ&G2©‰I÷®$V3wÔãÃwî;Y¦Ð„)9ñØ‚’Œ«¥¨HJ¡žÓëI&ö¡dC‰úž‡AY‰ÆD8(‘Šw‘L¶ ¤pXN±A2â™aüNêèÖ¹LÑ‘ÏݽV¢ÍšqDÊåáÞ6J2©™".€ég¿'9Ó2j P]pP‰¸2 w±sÉjT±Žàâ£%eÜÄ›D%¤ãá™´#§ HòMy%lÙ­;ÔÖS¼;µÄ¥MB˜äūضbþÏå¥m -½–lndšWA#º®¬oØè\qn­öW ÝÝ‘;Â7µŒ"¶§  \)/æ´åÔ‘;Ì´ ëÉ×úšB“7‰Ðã­9ËŸ4d»D²‚Žìë›Ù¼1q‘4ó >ŒŒVЦSY±˜5UåY0h†PeVPPÍÒ¸KO£Ú&&„e \±‰§ØF/ƒ, ª*ê>}Xö°®&;l×r¯äMPV4;çÌ¥%ýÁL÷r™»°v„iKÅÉÅMv•ìó ô¯–]8ìß§4\qQEcš9+#IûwæP Ý&˜ýÒ@%¤]­3?küªÎ‰ 2á(Ü‚Ëz|Äx):µÞcg<•QÑ¢qmT˜phvôXL¿!'_Ç gŽ£v’F|ŠâÙ \MqÉW•lÏhìö¬3Z @5G4g,Ø“T"¡&“8”@ ᎇjͪЉƒ…ÓUÉ“*‹¨¹è¤Á²MÓ &DÈR”6 †Þ_¶¸¬]œ Šœaž‰p¸ ®"¾¼ôÐyÞã‹PdÇ^|¬;ô·Lz)Ø.Í3ìU%qh ¼ÔûCŽ€­È‰˜˜ŽoÖ‹ÛJõÖæî2T{ªa¸”Í´'îA°PóåÌqdû>ÒðUTÛùˆ]'=:â™5BÂfj"ZëÒ³³…¹!_2]ëuÉù%P¨ P:Dïx«) !{…­o»†˜²ƒ-ªiyÊS1Aí#þ—¢çeäP¦ç**Ž B£=<ú=ìC7­c Y’³¢"´\¸{ÄÝTÝ5ÎüDU6×e9Ãn+uU•ù-;ŸÎò3:j¥&æÿÈ¥}r$Ât@l+jVÒR$4Å[‹<’iÖÜÿçq)óŸq•t J/š¹ÙFšÈ¬x8:â>|C¿UdHRÂTÏÓ7tMЀCELH¯JzÛÞgÒy%W7”ηu?XÖ1©ÀÌe­1"‹WŽ×dЕD:‘£íc²¯Nœ Bí$—/r˽Ny¯Ö¦êF´©rO7&*T#RJr¢¥¡¨Ú²\!Æ’Ö-¥™<]­TLÄ,äd{Ñ2"ÜÈȪ!C{{f¢uLVZP-Ó¬#WN]Z‚f¬Š“‡tÕx¸¢ÅĹîÎf.Hªs²é¢ò(dݧޠ)ð/çK(.:Ó`I[ˆHîP®/U«u*Q´~Žƒl `RÐL@@v°ion=.ôöaMOïu¾ãÐ4ýí¶a‘öXV¤²EÓ`áµ´ñ éÏá†Ä²Ÿ«® <üöùc¬^lPäm(·wFÈ:L”$Ÿ'— V¨=õcîI÷V± Tj:Þ0Æ’8\ÖNaÖ÷ðÛㆋ“^ýDß@×ïÇ9ÜM~b;uÐ>V5Ü_A]ÿ|T³’µ’'¬tùÜâSL˜ mÜñcŸ[ Ê À|G÷¿ËãsïäÎ4ÄeJd맆ƒ×ï‡ [ü¸|£D‚æðçÓâøZh]@|D~Óë„dGß·…þ?ÎÙò¾Þ÷ÃJ †“îøÇ»>ºüZÜ0ä øFÑäÔ¾ÁÏqßm6õ HH€‰té¦ÿè¿,1cãé‰"xvñ¿1äô¿Ë¶Í²•©¹Ú9ßÝça?{b;^¢µ¹Žq§ËÔbÄdE5RfM')"æ%<^I  š~Mþe%‹†oÐïûèò>õ“¢ Ä (©úMÑúyåO7–-#JÈU/¢ãµ—ÌJö]33rN I#âRDæ)#ˆ=á V. Û÷ˆÇÅ2Ç¢½™ê*o3¡šFœ,» èÉç((á”LÄ„ñhñÿtš¦E¡ÝÉ\À ¥ÞT1Sbø@×ô&ï/²Û*ayÁ\4–ü’š€–‹}Nµf•kXæeUì#à¡‘Ï\’äRUñPU’g)lVݵ;ÿâL¶”YÙ2ˆäíE]jÖG ¶ŸËs6Û$ŸúC§W+ô¡–@à(®&÷ó-<çnÇ/òæ£Ì í: Ž`h9C1¨"` _ÖÕ(p/IR²êH¼˜p´Ò¨„zŠ ˜•ŠwNÒ+ëñŸ³«wrnܾt²«ªª‡UUT0œêC ÎsÚ˜Ç8‰Œ#¨ˆˆëŽóUŸ×MŽz×ù…RÇgwháÊŠ²+‰ $"(Ì¥`znE8š7%¨£ª’ =U šÕÏëêû{‘Xe%’_‰ý—XV'>æÓkoŽšëÐ<0`´B»´,±²HKiqÒ™0¢ibO? lÝ,äu ¨¥:Iº†œ±kPj%éËk_Ì/këá­ï~xµ˜h‚UUV£’]´U(²ªª#7,€®D¨œ«‰ :g*DUÂst0 „hér€:\uÓ]zÛ{:‘Ô–^CåjÎÀ9©³³¨ÞÌ@µŽœž§À±§š´oN¨ipéN 22.%.’(ËDHF DåbÞ"™Ð?_vÿ™SìÿeÙÛ[én«;r‡%£L€§QRÝEZ@™ eÔµ’@0wA±œUûNºí££VéStiz­ÒgÝmHhÍÿüÃjoxÓ Bœì„{ÖR2ʳ¢")÷2ÒN_E¾+×ÓQX÷ììS(G'œj¢"ЭTETEP=ÒU©Äµöz‹É¬½£{XÕµAÐkÏåÖE·®hªØÔe¼‚2µ­V¥K7pñú*N7x¤¼(‘ÓµË7K-íI*¡n´ÚTëì¿wRfôÔ3j}gó‰žÐJ³5ÒŠo$±ž–QÆ¡$jq‘r›tj”c]2\¤]Ôü4A›¹n~\~#sH+!Ÿuq*3V1õÄgl¢Ëzº*}ƒ¸©ØØZ$ù…˜îÊÆ vñɸhñ­*Y—,ƒ˜ƒVdXû{²'æÚT¤¤ *PHÉ ç8¾É€Ià'኱Øþ(µQú„X8Îÿ=-ËKøc¢H(Õ¸ìkh~× Âúé`¾)¯gV_’ÒMŽ 2¤(ì(†ºÛO­´Å¡ƒ#ÚŽrl™|Å’ÌŒŽ¢kIúzhYúòZ’‚{NJ½k?&Æ—RB°‰VRZ57¢æzœY£\è‘ä½°‰.§p‹:•ËúY8Báƒs*fé˜DÉ€ˆÜ #¯ ¼mòê_ñ”ŽœíãPSQ•ZÕÛ\³¦(zj­d¢YiD¢KUNw íóåÔJ:nª‘‰ï‡Ù“:Ìî‘U.ÏQ‘î"‰Onʇé-„wÐD7A·@Õ‘Œ(Ùz„s ¤a›T #NÌ–äT.c¨'ãµp³˜'Å!Ñv Þ¤Í P9!“¤Ž‡ˆïòþFœ=OþbXõPm-P¦aÐiM€ªéÈ&ÿü…Y§9Œ̾ÁuÞK 9ût\Ó™C-˜óG×3´ô|u)3OÇÉMÔåk4º/j— È.å‹Xx $WjR•@ "¤­ÜŒV¼íåÙáü¼ Y]vDü>ªŽê‰­eeðKö¤í“ÿý4æ&EG/ßä.VÕq蟩žåjHç ™û„b%ž68{P¡^_Ú&ÚS­%;ûGšV¶ ٌʥy5Õ$ƒOTÑ $ï&gÎκȲ•ƒ;´̨ÿ®´°æ‘ýmªÐ#düN)6Y±Agu)– -]ÉvJ‰Éœèηy;ìýœrŽ]žG'%ò‚!´z®á×0­3)i*Ò!~Œ*_ÌÓ3èY%×l’¨Óÿ¤Ñ`’…â@&ánT¸Jk^ÖÓ¯A¾>³fò"‚ÊiÎÊÔå1–ý¥ò1ý>˳&UÒ,ÙQLIP64dG]f©ÄÓuýq<ÉC Œé%QrîM¡$ÝEšdù̮̑ÅY›SvvÍ4˜‘ Š ©2B2º¡%S05 j¦7ö l¢lj(Öî„HÖVÎ\ƒ2:qsþv–“)Û ¬ª­ÔµüZ›vœ­A!n¶AÜĨ‹©Ðx‰ö—¹U•µRÚJ½•É\L„ª/nÏ9¨¸šDFçrcëà{­‡ÑóÎ> ¢:$ø`·!j:ùpéÌ-ð¨TÁ€îÑ8 ì7ßQ1GïûÅ›“p!I² €U8ïÐðån¿¿£É7#àqCª € ØéÂÇãㄼ׉•$l‚íUE˜ Q9ˆQ Æâ%ÿ†£¿ÎòDdå)œò´]*)BÅ©<È•Tú áÌ"Ф^£–nÜÄ9\»aƒµ#™˜¯¤”hÄD¢ä£†ä³ –:˜Š‰dâJbYôt Ds$Žá䌼³ä#⣠˜ ŽÈÈ=lÅ“dÀê¸tº$CB~‹hÇ4áé”sš²Hg;Of«WRóÕ*iõS—îE¬kˆš V‰¨ÙšAû¤äªuS^Ì2—U$:q¬‘§»iíC!ìËfj”„ÐTm~mLó;?—–Ùuä<à-ÿ¬ot”PÐ(©Ð\k©Bi±yÆe;%³Õ»A˜¶ß#+¥q ­yhB’Õ{+Jo<ôÙîKŠˆBV»)“Ÿdàh¸L§¢³¶•¦_Óî¤ ¥/R,9M8+‘Õ_QGŸ—¢‰JÐÔÌ‚)÷ÍÌFb±’±¡{8d›IüÒ'jÌâiQÏÃËÑpT•[9–OÚÉ3!K5ÊŽªòÒ-Û•K32lÛ2v¹“n^äWs8šã4*z ža¦æ'/):%I<ÄšQhæ±Ò3oæPާ鶬!\ ²KË.V«;rÈœD;÷1ä%cg›ÆÏÔË„dzÖ­CAµ©ážÇCçJ=yS6Ÿbt¡ØS ³T\Šê‹s¨‹p\ Ø;¥ü¡ZÖâÖãŠRÜqJZÖ²T¥­D©JRŒ•)J$’L’I8é0@J@ H €ÇÁ¿lº²šÎÄ[4¦(zÍÞaPpaAS…Bö—cF¸ü¶ ƒ¦Ó’ŠVšŽaÒ,ðµ:•aÒI¨÷Ê6;“:|+{k‹ÙÙ׳ÝqÚ0à2£.Ö¦ØÔr1²ÒD’¬žÉÇÒÑ­ âב]Ìã˜62³eb©ÑIˆ–5ü‚‹¼Dˆ"(—+²’mŽhv„Í|ËhÙvñõÖd×5›œ‹9nÖ¨ª$ç áDÛ´LîEù²„jÔ‡P¦9[ QÉôùønež]…?˜ù™õ‰!àj'rv.•N›{Q®vú’²h?M—`Œ;KC¿v¤‹w,ÐY«uܱÊÔÎ;›³íîÍ?Û_¶4d5›V¬Qå.7‘_˜<Î[MR€¡º¥Q×\¹J…)J‚!TþÐR#?Ûœ³+rULÒCµ)›XA¨qµEÀx 3"ã¼F¢â-ÚÚ++d2ör”ìË[å+ÜÁF7–3^¼§•ŠŽ¦¢bÀ¹sâ°†fùÛ%"çý«Ö³Ë÷˘(WYYΣ[V¢³7"é|¾Ë:&“•’ͼÁϼ«iH™”l[RTîžÍTu#bíŒI£Ý,îT‡­Úî—Tˆ$ª€ÂíP×YÙÆ‹Ë¼ƒ[)éºg,3JˆC.b)Êí9J5ÌtŒ‹@ŽQµFœ›Ó¸±.ä’I@PN¬Z®‚Æç§ã}Û­…ü/r¯(éj¢Iü†|fQrë4§ÚID:AãJy™JÊö”¡,MUÀEÅ.Ô„d“˜¥%Y8]fjªÑ×=RñRÖ·Ÿ¨t©n8¥-Ç]ur¥­j%KZÖ¢¥-D©J$’I'ø m„$”€”¥)@€°Å7í¡øçEŸÐ£âwdQÉL¤(X;±áç>ÝèvW'í¿göA¦šÊözŽ)¨SKïöjØr£1R—ýNÓ½R(_ŸÊõ"Ñp€Lëc^̪²6ksE©uλRÞøÝ)¦VêpJÒÙyÒèG)ÆS±u­I ¥]^Ϊ² ÃQ4ÔC7rË€¬êEÒ‘ð"²žÖÓ£”ÎQ«OæÆ`çÞoætF{öÁ¥ÉžvËåj,²ÿ³L3$x*G³vS,c1"ͳ±YÅ~dä8XEãÔÞþ>ÝÙß‹là×ö—åˆTµ’ìÕKDÎí]}UmkªdïR¹B"æ 0BRÌé{Œ…ú…U]{Ê›L¶ÓIÆKÇÎ"Æf¶ÙkOóŸ=æjšO.PÊ9LꑤªJ²V ´Œ‘¡R›N„©¢Ñ‰dò&aã$d)ú±É™“tÙà-ŠÎÌÔŸý˜Ú8&úiêª9víÂΜºXEEWráC*ºÊœmÄ¢ªœêéŒa71ÇÒ§â9X5aÙ7<«ÙÇÒõC!”0tKZ’¬ZÍÈIWÕm )Ã6tÑ’K¨Ò¤“v›fÌSR=^º‰¢’ɇÏf¨akOƒ«pŠ€‡k€i¯…¼?æWüC´l½Õ$)-¹R©ÐˆI“òø9mÕGq¾nò’ÜLH$OÓN"qnÓS@ €Xö¸ µÓ§ØwÒb£‹ÉŠ2„1ù[Ñ™MútDÈ—J€FÔ±Ép9x‹¿õI—”ŽÜ\ñ¦tŽÈNN SLU˜© aÓnwJÊMEÇ&ЪbèÏ^ ØïEÂÉ‚¢§v*$‚Ê ÆD”0ªî*ìÅ j•.pTPÉÃ'L ´Ïhs2 ­ÞQr"¤,ŠBM½n¨É8IºUZQŽÙ9"k;¨ab ƒ–ê\ÿŒ,ä)‡È›]”æq›T Ú(¨è•’Cµé“¤ZdÄO²ê=Õæõ…1 ¥¦lëù‹®¼'H¬˜s}'LˆËnέóg7²ì­–s¥—•¥+[.rÁÜ×s]CÔ‡dÉg²ê0ŸNLÿé¹jpáã™ó…Ózå5J )óWÛ¤¦ó#·þb;¤iHzF€=)M³ƒƒŠ‰bÙÄU7ys>êE·t3Nd“wìj¬EÖLî bc"—sòj€ˆÏ^Ø]¡s^©žÓ.©jG%iŠR·i<ƒ¸Y¥Ðÿ™Î1ÔÚíX»i—Гë·xœ‘⛾`d™(édç•›e˜]¢3V¾E4¢*lǬçáÐH@Pk 'QH<‰fÜÝêÁìí#UjÙ ,­HÞ¨>øòÿe¹oñ]½ÙºMÝäœÉ‡"Fëk 3Òø×&ÑÔ{6M^äÁ­qÕ¼†¦"+ Æš¥'j9zJE»æÒ°.Ú°–bØÑŽŠ ´xý„£& ©L(¹QÓ™¡×D@¦P§-Þ™m•ôõEG¶í!P3p¬ ai©·”M-˜Ïd]Ón[°{I:bžjý¼›VKÆJ•AºÙ¨;|újRÍòÏ[fÍ Þ=c¢íúÎ#ÒQ7ÿ—4×j¨¹8;(ð´Mq±ˆ%P9qyÝÆÂ:“ŠüŠŸ•¨§a몊œšmQDB¶‚ŸB WW»rÕ¾2'h*¶ÿñ’ˆ¬fÝÉHÑw& ›ñrâ×ÚVJƒ=Ó “´ÀˆOv3\ø’› âœÞà¦a §f ‚¬ÿRóŠ•.uÞ4´Q?øBys‹â.í0•m´.jWì{ZfµkLÐcš^1Åf°è=üŒ²Ph¦WË …q ›U”JD¯Êdb-!ÀfÊò‰íÛÃ2YïúÔŸH7”ï,ò…¨ótÌ’k¨VÔ  ™# &p2.Èa+¤Öc­óAAU™}šôµ0¡iú5hZÑ&Ñp“rÏ›ÏTÛ¦Œ™¸Î’n‹W²é41Ú’4é%hÑd%98ßÙyê§{“•&‡!€@Å1w(…®ÖÃpµ±ì3bò=¹Û$dÙöù£4Î:Ú÷¥¦âH6ƒ:aïl3j¼Ÿ*5tQÞ‡™PÞ&Þ‡Ûúó¶D¤ëÚ’c4‘š–¥&è,³šgšÎB7‰”£Ä²!÷J›&-ȯ‡ÞÁæÙ£Û5’«8c™PŒ¸Eêºa”¹4ÉÙl€¶Et×/’pDÊ…#5 U `P`´Ö+§Ð£ÿÖáõ¸ü?¡P„sPLGBÇ"C<’t“TEASºKŒ}õ×2i¨¡6HáÁÈ’†M”9Hq/öu_᫲zzŠÊ¤TSÒÒ0íMMCÕA,±NÃ}ëÏ:²! ´Ú·¢RI×;[´¯8ÛM–Öã«Cm¡-ï)n-HJ”‰•)FIV†qBæ¿mÚu¬{8|äpÕÉ'­j+.];ŽEÉ•/ÞR>dxäQŒ|áÌkqTÂÝ¢Bá"÷1;fHËNN?Ír»•©ViÚô&[ÏåG‘¼I Ü F®UQb&Ù$S9ÎaP‡Å«©rö¥§ KrÆeÅ]T•‹cäEêNEÁÛJA)DcišÅ)Tp*ÑAdÍìvãàþ\MÅw¤”‘§˜;Nih20;§îÝ.ºS¿r—åÑ[ƒ$–AV†QW¬gDîˆÜâdÌz¿þü,ÿXPÿõo™ÞLq¿ÄâD3>ÑÏþëxþ-ðÝæçC¯3­ñBëºs>3…Å4žhÖR2¦Ƚˆ@ÌM\L±ä–9iÈX€vwÑ{íΠ5îJ»Žó¥]•ÔsFCÔ‘ŒREÃçÑ …²í®ÝF`wÇz *ð†Ið‘+rRâÕÌ•:¯2e"ÊGÙ\.€:bs¬ÕÏr¡“Ûd‘TÈ,ïQ2©$qLÅ1Ó!®R»cRs­¤ÚT´ÔL ·CØ[2«*jI¹™S’oS¯Ù‚®˜52EzEÊp¨#ÝŠê‚’Ñû;ØÝŠìWo+6?¼_ñ*mžï.w›ÌÄÙܤ…"Z*+ RFô€Fd9îk›mfJÖkºŸg]t$'wßþTd½‚x‘¬Ù!M·‡…^®^€£UŠ«â§?J“¥UXÖª(AÅ,Î-Ë£9—ö¢ªgghàé(Ô)Ò9± v鈣¢û:Ui°Í ªfФ\&BQ¢ë¿s˜T¡žŒš%ˆŽ|á´|h> Û¶UöD—|/Æô^Eåê¬çƒ))—Çd ¤òFYíXñ±¶YoÌ<³9%ûÖ ¹Ê±{µHtÈ âbÁ™É˜™eÚ‹œ%uOÁGš­F2–zœ V2°àº ÍŠI·x鄤ƒH×-dS,TL²ã:jùö‚ÐNI'À8»MÁð8­™ Ä„¥ 9K{€ÂÁ¸éÒá ï óÄäv·ÓðÐzkýÛž˜ƒ;;I"êšM¨•D§ …ŒSÀ b¬ !Â6Ü-|Y#µÊ6øßo=?¬z¹Ù›LÕl&Î9LR´`{°@PBw´ÐÏ |±Í™ú–Þs^—$(¾­l`éãhŒ7ÊÜv/Ãqø…ðù…š}N71* SŒ’MïæI2g—™gŠiAM#3[%Š*-äÛ¿£¦v©Ê¤ûÁ ¬i¢Ró/¡6GgyCŒ±Qœ>‚ƒV€Å U”ªp ·^‚?#®%´¶lTRà¥h&Å’aå8ܯ¢]*œ›ÈVŽï˜é5:­ª Ô#pDü\ ÌÉ2·ÝA åOk wõwÀ2~ì¯IDÂe(—Ø\Ë=‘—;1áq«¦G÷ÊU*ŠG1Š™¶þ ˜u"i'T”CªUädá•Mì¢u²ˆ¢FÌ\9Ud(´JÜÊŠïàvÂuËÅUÆ9Õ*õZŸ8ê‰ B1D$Œ4h?RÇŒ#6°Æfc{g³™ˆg9“Pàc&c@Ææ}›¥öÜó-§‰ßªjG@°O” ü¯°kÜ QÔ,ÿKJø‘’Ô( Å$ía*a{\9mÈBãmÃÄu×ô±®&Ôwþß Hrf%ÃÈÁéòÜ=mm±ÊœŽÃkè#ë·Ã3´ÎÛ ‹ДÅÅ’”-~|uŽ•ö^™Vñ*“n Ÿ#>s†Có\G]úïÔ=uùá¶àu7->ý>X^|`^÷‡—žËÌ=ï–ß–)\Å{ËT‘3ÆÑúpŒK©Äˉðåä&/‚&˜|íðÓcÓ~¡óǘaYˆ°:ê'Ö¸Z€úaƘØåépøí…¶†ÖÖçoŽ:|¾XXjox5ÜŸ ÿ|ñ%¢^êÓ}"|$¿.'Ï Ï'_ðW¡‡Ìiõ-ƒMà#· üq#Äâ[x ¼tû鈺<ú†Áaµüío!ûÚø‘â–—õ½=žÍÔ¥ nOößÃt;~Üq¯A!ZÚuñN§§å½ýê¦tŽlGɼiì«ḆLµ£S:覲ÇQ äìÛºl Œ˜‘t×T†1ãŽÀDeµ3&›×Ö\ÑxÒ]™¤+¹V™gMKÖ‹µ3…i'-ª + üH¢qÏÙ.áTÈ*=áÄÜ Ë*­Z:«¦ª”EÙà&I™£„“]h¶\‡]ª©+î7 ûÔ { ”â)ˆb‹ô ’ÙùÚtcjÙ ÉS(2:F(gàM”5:jfîa5{G¥FAò.éJi± PEÃB‰Ulé3´~E–DçN ÛV^ïñl£:JJ©krÄQ)À JjèžyjBÂJéê(M·‹n‘;ª‡’}>ÍUHL8ÍAt$Ø–BÕ¡AFñ¼žc5;’ÙËG¸«i~͵|8Tq“!•Ùž2Õ[{d’mœ*ú)ÂsUÑN@®G*ÄH sƒ9#‡0í¨‘ Už~9“ÙéGsÕNbäãzž¨’š¨TÊ*)*þh)hǯWy „ËÇÉ·l¨6GóVÑ¥"h¤~ôî«YkTvjÊiÌÃËl¤¯dC0ŽR'_Mg[PU¹Ë˜Õ;h¨õ¢—Eó“~Q)ì‘‹¯“J}t#–ɦ‹T1ä"!’žl¬ªªÈË<–—™ÿcjžXêGµU¹Õ`³Ã*¢ ¤")ÞNà,DýÞ¬ögi³}‘Íéó¼’¡õôÄî)ÆûJJ¬RãN•$ô…_ Ã/¥Ìé—IV‚¶\‰ QBAJ“p~#¦9…—Ý™ªy„ÛÊTQ²Í,ºéƱ‡píLyG=F=S™.ñdcÔuÝ("DÒ5”€Ñ´3ü¼‡ÿR=ˆË¨V§ãÜAÂD¹{<þ9xó.Áæ…zX×>Ðe Ý# Ýñ‚!Ÿ¸–”©¦Ý® iG¬A™€ÈÈ4nµPü˜ÍZGNɳ6¤HOíd˰Œ"ÜÏÏz$žÉåÌ=%Pæ÷hÙ8ÂÈå¶PStªÕ]g"åÂ&s ött™ÒôüŠ®[+"ýË´Öfݪîš&+$Bƒ¾Úv‰µ½ TÓTí6fjÓD•¢Š‘–Z¥¢¤î—TÕ3 BK®n¤8û¥ÇÔ”!²çvÚ”¹NG–d­¼¾Ÿº.]ukS¯;»ùBœY$%7„'u’ å(˜ún5*%¡ó{:ëJJŸª!Ê…C®nV S,©˜¸÷DÉÃ@¢õW«ÎB¸p™! Z*i7*¨)ûcnô\æ³¶íWHfŸkغ ˜¦!")GŸST»jUj–®xôïj)Z‚9ºMŽIöf4Ô².[¢å¼œ â..2Ž—êolzî±VZ¹_;ÑÙÑøŽö€§e¥’‰ž+:Ò•ì§M׉·rgОšœAEØÑá&UR ¡¸Íµ<œ ¶SZÉj5dÖ4ô¯z³§ «¸9ÕYe•8¨¢ª¨ ˜êª¡Ì'PçǘGìÿfŸÚ]¢¡¦KdÓ4ûoU8G¸– ¥IÒNyôƳ¼Á/8Hï‚–Ó7*6ÀMùyȹ4sbEC2j[$‰40\Ü!Ën¿Å±h;7ÇÉTYÝ—Qð† M#P'1¢Õv’rÔógÑgUªMEÓ,„s`2@'*€<IrÈ)SR’"d)lãpéÊÝ- Þx¸Œ"늃5W“ 2Ÿ5ób¥§à—V›m–°pSp´Ýc&ù“ fw5’¨¤áYÿÓ†Æ4‚òŒ˜ÌFÔ[0iå7F2„ïM³Ú².ÏvÓ¬7ì»9]IJR`!úŠCEJ`jï4zÄ×ÎUBªÌó/ïOy^Ë®s(C‰uÀð¥SÊdòÇs*¨ƒËÚÅWÒgŸp¼½(ÆÚµ8Ô‰”%%K•Wˆ:l± Cªí¹l(×# ³¨×‰Óô5gLL«vËÖ?êgsÑ„€y ÕñNØL(eT/ EÁ[ô…톜–iv—ÈI‡ÏŒ„¤’€üº=IœÝìù+3T5§£ãfÝ·©¦òÞigäc–g]š3r2)ºE ‚âÅÂ×@Çp§Ú¿ÈÜþí3BæUå½+IÖ5 ÅÙ/P5­£éPMÌ2“§§Z#RÁL=N<ª’0(„±Ú¸]okb§ä¢F/~õSçPÆ9Ô9„ç9Œn#æ6§1Œ"'¸ˆˆŽ'§¯ôô븆þ›ó븈Ž;²åŒ¯bؾꪜqã­Å€'ÀC¥ô«¶„œÙzØJ: '@m¬üBg‹88¼Ç£ëÊ24”„£“Ñîž/–ÀéšÎÛ9MÔ“×I'Ç èÉ&FΣÖ|в;€!Ô 1#3R™¤)¶O¢¡§jApwÎÒ+`n{çê¼p±¸š#£8ü¹¢¢G*¦‹d—âHãÀ6/1SÔ?HûU4¯;MPÉu‡Øqm<ˈ2‡u²•¡i ©*ƒ‹ hCˆSn!.!`¥hZB’¤›¤Aˆ"1Ȇ_„ ‰ZœÿôÇ5ÍIQéÆËIwùΓ%Uj´jEpH”fé´Ù³Qdïݪ¤{WD( ÕU u õkøm¬¬´e2÷1]Õtû&(JU5E1Ê"—ABÆ­ªÉÉvʸöËnòŽ)FÌ‚Á~‡Ô™¡8Êšž¯s*in¡’RV\È·¡iê}Ѓw”z@Rb±š¢šSQw ª$)x€)$Œîg~&‡Gdõ;[åg`:,©×9‘›‰RÒ´ ¯h)öê)L«Ê¶b.QÓj³t.¤¦¦ã‡r›²7X=•Š.-毱B2ööά0”Òâòì•ÚÄ ^æZºÍí{ß÷Ò,à’ ]{²ë{¿VTÞüÉH~­-3vSPônnsI´IT§gžÎ¹«0ÿ³>\å÷füõcG+Mæ5bØÈ+œ’P¢QÓ+ÃU™•˜I"²i\L¹EèR´lœ ‚¦ÂiTž¢‘ÔdÔæoT?‰¬ûЧ{Øæs/¡Ü´=5K6ŠÍøÌÞ€‹jÍ]+/(áùaWI”‹u$EØ;«ŽÈò¯×pÍ£Û¸s“9M”®²7³gbìÂÈü¶yEË2­3«&3/³~MVï^SpHi ­'3&¬vxèåæ1%˜1Œ®$‹”QYÒáòÛ‹ñIͼþ¦*^É™GT×òiIÉêjÖµ©šÕ™\CE®©GÕ„GQÓ²4°I51äeéy%"ëF¨4#EBšUÂSu}MVq´y¢êkj«³ŒÚ½Ð]©¬}êÊÊ—U Iqç”ã« BS*!))1"mªZ pÛ-3KLÊNëm! 4ÚEÎê‘ÌÀ¹’o«w=²ùGðÍY'PåfbÕ©3ÌzÔ™‡TRÌêz˜c]¦í²” D “yi(7r)¯ .¥&Š"ÝÂé‚«9*†ÄGÚ÷4¦hnÉ¢kÖõXC°¤òZ¬’‡h Z?{Qæìì{§®WQI÷rS½s w0H‰Ž¸¤‚«¥R±ÏçÉs:¦¨êZ›ðÈí§=PÂ1kN²ŸœìÏ—õš1åë(!CV gTdýì_¸n᤾\ϵíš¶]‚ =±±ÏÄ&¹Ï*;°S|©Íl³Êšò«ËL²š˜ílØC´K˜nÞŽ`ʽ£géj”ÌQ¯a²ÝX‰x¬Á…qR% +i)–’'x͵ ©IHT æIˆÂƒ`O,rO²lY˜±4KÅk˜v°†¼µ°ø‡a×P]!Û½ËxêÊQ7ðt¥iUM 2NÒa!"âeáy·¨UÀS`R¶hõ‚â›{w†ãŸç³Ã"1£Ä-¡}„:ïµ÷åØnÄÙÓLÓTõc@URŽuT%o œ¼ƒA«^¬FpOiÖñ±íÕq(ñϲF¨"'\H¨,D6«(Ÿqí¾MPßá“/¢¤BвúœŸ9­m°T¥SwŇVR›”²ª¶ßpBin* …=”U¡]¡>ë¤C誥eJ6J÷´¦L€¥”„u)A"äÚÄ!àªH:–Nm²¥„„Ì¿ÏÁ‰âã©ú6j9„s–™e[™Ôƒ$»ÇW .tˆ)?Ð'L€¨3J„Ë,§Êȵå'*ÜØ«óO'2î—TRlœST”ãÜÙ§˜'&) iZÆ9Ü]iKª¬ƒuV’‡Ÿ§YF¬æaºøé¢5;#¥8Õ¬“zx‘ªîvB>MGññ‹/²fÆrq•3*$p‰ÄÖÔ×" œ a#f–lÕôì]MÜNÄ«™•JÐMiØö.Haˆ„Eâ®Ô˜‰]r&²¦\çÁãqTW-ʼÚG.忤béyŠû0$é·±ywEA ëÙ™ó;t ,OöÒŒŽgìè§#.w(“W§îYUº´™m“’‚)fŽyåÀçÎuÕII̼XiÙ( $ó)A Nž-~ò> †T¥nñËǪ«„ÎFŽ>«üJçÅûEE:W(Éò,¶‡vd_UFfµÁJn¹”Ÿô¡%Ë`)=—"+"õU½0d¥ºp/x eDu'óE¾fäŽPæÖse%-•ùu'UÒÕEyWKLRSTäIÂMH …‰R5µŒ»7’ì#UzÄŠ‹Ù2Īg8ºK…šƒtÔvb…Ça× =~›Øzt;·=o›n2‚¶«êˆÚ¢¿Ö©RôcÈWÙ‘EÊå“C;”QÔ›4½=UIK7xý«Eî"ö TIuŽtDÀCQlnV4úg0pŠ…/­Ã¨ÚÃkÜzm„‡út«né«M.: Ð(ÂSÃ[àý¶pŒ™Æ’}ç”Ä‚}|m‹¯EÕÎiª¦ i’è éƒäÅ×'xƒs®Cµö•“ TM¹WÌŸÿ¨ ð€âúÔòãIÔbêHÒˬþŸlÉûxõ4 ‘÷ò0œk¢º*Å2Ž)ÑîÀÊ’ r _ryßÓ–÷èÞܱahîÒß•IRfuƒúÂs¾žŽnåTœ®•8SáÜ*C·fà³p ø¬©Å«øžÉ]ÎȶÂá–²æOš”JÔÕ+¯{F_P¨ë©v­—`*©Çõˆßg•i¥]nVê‚MB“UN yÄ 6ú/r¥6––‘ý­¬ð·KÌ™Vn OÔ²bŠ(«P)2æM‘}¢îÜ‚.¸Ñ1Œ(ªR)Ëôâ›ÍörZ¦Rw.ß8ö‰÷©8—¥%{³ïå¬*?ˆV9’EjsÜîXÈ6"h¨eIð$b·Ng¤³1®e§)RÂUðrtÜ”‹v+*G fZ~LŠ©¼IÛI2¡!íp,ñ«r8îT:]àÆÂ*胺”eŒu£¦»§©I¹z ʉSƒJG€X¨ T"áXlWI£`VÙ¦Î6G8¤Ïr:‘M_F­æÔ¤%Ö–“ù›uµYm¬P”¨j•$ÁŘeô¹+”u÷Œº!@ÕÁIPÑC†£˜"Øm'—UüÝÛ3&‚êGÒg•|GÒŠ¨Õ£“ɤšò)2lLéãÁQãælˆšÉ v'L Ýšõ;´þxÈå¦^¸ƒ‡‹€©3 …iÝ9Gå‘j»U ?R“„ûÈŽª ³V0õ%Ú¾Á!Ü›;§‚4¾hWéÇTiº*Ôí–î%{:¢$*¦*.åpxÖ¦p%IÓ÷­ˆÑÑâ(9xd/Íø´ªŒÛ­UÕS·ÏÕp°Š>ÞñËÿcfp‹vs©ìèuO`à!×Ue¸ uNZlþI]Ÿf”™}Kq×^@*H$6á+Q‚N·å‰m[4Tî>ò‚R”“ܘÐxâÄä|ªlK#$ºª[ Cãml:i¥·¾¼ñnØUS »V›…wQ̽fx¸èv€ÜNéó㦃NøÎWE4™¤¹Š«õø”;vEp¹PXÉ‚f†)ä‰bƒD€©”¥°iïXGK!~º½¾X¦!ÑTɪ™Št•LâSäÄ1l`8\¢|zGI² Ôök_°ŽT)NfY-EªžQsr½æ·éê%JPb±-:S©®(GsE£?g9 ÂiêÐèm a*mˆ07Û*H6ôE°æF„3Å]VùéR´«*‡ É–ZR³Nà²ÖŸû¾áa0‹Ùg¨*u½°îAvÂS™#²U>J­)PRsk/#BPõ\9ÎvQ$§#ª €Ií $¿·¤A§|S&íÖºŠ@ ™‡‡Ä…G)ÄÅS;c ÄDSSÙ[µ2j7&2¢eT:aÝöxšáEÝf×ó´Ìdz˺÷&v¡cØÿ¾™¸œ83C&ýqDä1û°D›ÜT7ù¡še•Ù.cY•ftÎRWåõRÕÓº!m<Ò·T$JV…[n ©·[R\mJB’£Ðõ Õ°ÕM;‰u‡ÛK8“!HP‘àFŠI‚••AqMÓÌ#¤«Œá»)UE¸Í5±cÙ¹;…&4gz±Š)&r˜]Ÿ¹*J ÅÀ‰Òp™Ç4¢èÇÔÔ%'H‰PYÅ^v’j&Ñæ)ÅqgøêÄÚ…ºÊ92%9½Õ€ó¨H:i™eó:¯ªj…TY¢ÊGav´0?öÛ·´S"¦ýd#•2+ÚD@ c "a0aÁ#[#<›u”fýŠ@Íc3¨1œi‰ÈbEPº°§Lʉ>=Gœ«´­¼Èò•äy>ÕgvV°¡ìÔµ%¢ØWæ T%>ÓN9l ÄIÃuNA“VTŠÊ¬¶•úAïo{x ÐOv³þô*m: )3JRÙ¤Òª+©61R¿©ˆ¼äÁ tÖ4r¯PIƒÜ9L(#Ý îŽÙQW^<•‘zé•ÅY÷“.ÖDýòdD T»€U¸˜È¤™J^ÊP/ R(ZošÉKW !` gP´ûI9)‡)ª ÚJQB™ƒvI*U Œb/Ūðª$ŠF‰¹Uâö§p Ö{"àµd^ñC€6H {”Æqœ¤ð˜Æµ¯¦!++RŠÜ*RÜ%jZÉ*YQ$­J2TTd•I2I8vNè©Â@  @a÷PÔ/•@ÑìV+6ÍUu$¼h ( O¼\о*À ¤˜œ©•Ãp(ÎWϤŸÊ(QºráÉîn3×TëÜ$â1„D@…âˆlìë¥*˜)uaÓqGGG*åÄ™Ð;›‘qf cÙGþå *äŠ.¢ÉLBœ„•2™+÷FZÖëçËMïË­úÛfTb«j)–¡)¦BÞ6Ÿ]xa“hîòõ‰‚ádpãúaó0¨Dt°ôûð×PóFŠ€‰¯Ô@-áÓæ?çGôʺ›Öá{iý}|±É)©‡‹¨h¾š€Ž-½©¨—ƒÄŽÓñ<Åã9j $ñ•º[¯†®Ísiÿ°ëèô!¨71þ?|*96¦ðP×êŽþoùÅCZ²¥¨ó?aô1êq(dXM­o8t?LDG®3ŒÃRÍã—ù¬/P yzÿ{úáM¹¬>Wø‡‡=zá%3XmÈ}5ý¯ü`òg°ƒm„?Ÿ®YB§¨ýÿL"Zg{ËáO‘® Uá…„C~[[â|Æ»)D5ûÓÏŸˆ"ÖÎ8lÓoÞÞ7åû­ØCÞè?ØuçÎúˆbc”×÷KAÞ5:D7çxw8j©gzmÏŸO‘Ô}8Â2S‡€8¼:tÜ:·Þþ;b÷öWíÃ[öf|›‰fNY¸rgT$”š‘®˜c Ü»¤æ½–@°«¹TS]û5cÝÇÈ™3Ù&/\žL¼Ìe%Ãmv |G_Ÿ-~xv4•¸ ‡–ãéà7DyÚዯ,ϲ×2¬Ù”TÒ¼J\ü͸ŸÈëNÛ¨’Rãe*L U ©¦QCˆ&Ф‘¼… “iIh`ŽÿKvÏì?Ú:™“ŽÌw14lì²Äa—9”Âv š¦ÑxüEy&™쑇)ŽšÏŸ6©šÊ™œ‘¹š¦QHϨ:°\ÊôËfˆí-—ÙuBLt²Ù×h ¿w ¼sû‚ÓsÓÕAkÈØU—]DX·‘u$”Ši¤UQ‡Î²©Ç¾(ƒ„“Ráa1€8ƒ® 7祂ވKÑ”óƒq²a¨ˆèPþµÞ×é½±Y×ö?¾â—”æ¨,¨’–ê€ßLÁ ßHH10$N„“7±µ*iÎö…MØ$Á˜ãÈN>¡ê^Õ½‚rî rjWñ¦*¨ç!$Æš¢è|¨ªªÊɪ"Ý&$déÍ.åzuÛ†« w ê h¨T¢¯|Iw7!ÏÎJ÷ñ ‡ÊH©ê+ðÙÈT²¦b¤MTªÎÒY´ŠU–jT¯”M2žf ––SBSæAè½sIùz¦0F’‰v˜ðò8´=:‰€ÀÝ=úDCï]ÆÞzÛGDG€ Òá ‡K‡¥ÂþÖÛQöCPIÌ36Ø ¨27Š…‰E‰˜¿žîÓ£wù4ê*:oÛ]tújñôÕMYÕõîcÏÌÕUeI(êr¡¨ªI'“3“rÏÖ¤¥ådUpúA륌e9r²Š¨s ŒqÄòÉÓxæänÜ ™HZ„…«w½}P]pÛUZ×ÒÑ®"Õ®UfNw• $È;‰’8q’yÍõ‰Äœ7q˜h#~ž~zâïvBí—LvYg˜ëÍQU5dòµP©%S!K‘tÂÓ.ÎÉÓ¿b|áfÒ.emÈ€©³Gfç(œÜÓ$Ÿ½ú·¸o÷ÓBDSO0Øy}ÿ_›ÕÑmWW”fANÑV% ëiuÖŠË/3P×¾ÊÐà y¦ÔBT‚wV J"•§¨jªbóRPJ«)µ{«2P¥Ë"dA“ÌÆÍš”œ=•ÙGšYw>åh”ÛÍš¬£+øÈø¹Ï\1aQÒNœ4üÝ&ˆ6’rÍë#¹5Mc JH·âIÙc¶ŽYÕf;Ê@ö‡V ±YyŸ®³Á¥i§oåã–ž’›…£¨úZ“˜$¤aYÄÕS3jÙÒ"d Š+¡Î+µ0q i‰†â7)u·Q¿®¶Áu=“~í-Çþߨo¯þ<©×{+ÊÊÑ™:”JP. &TwŒIžs|JS´•$A§I0 ܘŽ™ááÙtÉHˆ°"åÚƒ·ï ßè7ÃÅãÛß_-6ÿi¸è8KQÒiÄð°MþZïá„w/¥Æý9ü9yó×Mq:§u¬«-§ËYp©ºf«{Г}x‘Òp릛¡o¬Bœ;Ñ&Úq›DGîp;—w¾½Fÿ_»ép²J‹ˆŽþ¢?AÓöõ½ðUg":Ü|6 |o±ç‚¢ ˆßO¯ßË oÕ•¨’uãâ:‘ÏÃ]c ÐÔnWû}øáTŠõÛÎãè?ßò M×è>Ÿ·õ¯†—ÃlªÛÃ×-þôú©·PDÀ??æÝ5×j¤¤ƒ<µ6áåÐÒ6¦üúx}gKáÿà %4ß[rõò°ìBTBÁÄ!kl 6ðò~AËLFH»à°xÛ_/ Iý†üWׯ0½¬Óž%9veÝ”ûÑ¥¦yi}xÏ–Ÿ§ Ü4Ö|?YåàDÀÆPLr‡îÚÚí~¿[rÿÊ[£êiº~^6¡¦&å)ªŠoi‰ƒ~â2R=À¦¢&U£ÖŠ$º"¢*ª‚Å*€›†êª‚ÅQN™«4{ý@DÛü5ZoÏÏÛem Á±#$Lp‰Iµ€yì!¿…ôÄ5žÁóÅ8¹ Z‘+I$îÛ‡‡«;+lèÂe4ïDÁ›XÇYû´âÛç·d[š4sfxr©YwÏ›QQ´õ4ÕxÕܸUŒMG!KÂA;©Ú1Aq!›ÊFN×"o´YÃVj6`eÆSBÑÆj¼š'\Å:GrDLšn ‘L±QUT–M5LŸ$s¤©§ Žšr “L§›Vé&  JPä` ´ó°éçl™˜T ˜lQéðúéå‹·a;5Ù­ŽZkªTœË2H8vÊ¡7m7…^B®G=f!œçõù¨,¶ =9"R¼¡"Êpf zãªU¯âÖÂ"eãæ™O]IÅÈ É'&­šºn+³‹,x9fçØ<‹PUE“A‹‚²L¥9}˜Ç\Ê—½¹ûfJvȆ¡©–™qUR)Ó•{ª¦MõEV CùšêD;̘¢É¢Ù"«å@§;ÕŒgg)‚b’ÞA¢‹ÿ¼TÔÖö8_Køj¶·ÜzŽ”,`ÿ¸›tŠ#c€ÎÁkxô¶¶Ä;0ì[eW˜{N]Võ"V…¢¼v¤$$¤ÿÖÔ8㊟õ,:FXÚÌÄ0¨i¸AÝÔ·¼LAÝBBDka¬M°­—*þMÉ¡®™È‘x€tÔ@4Ôw¸ëã釃‰e[:e"Í@MäsærlVÐLƒè÷)2ãê-ï¾·ßåÏMqÎEØ–SWVíVÏf‡–V(_%Ö™Þ2PÊÕ¼à@2Vµ‘`òƒkª[i-×3ß­ ùuK€.¤ˆIW2“<çò§íUÙ/£êyŠYÿhnÔ¹ñ',”µ+šÓ5]]”p”Äši¬U¥ÒŠnõ¡[ ®ŽÑÒp!GM1|“>éäŒj¢C«ÏªÞ±Ï.ÓLöqV3Iá#Њ‡EñZ5iÙUÔnÙŒ²j¢¨•ʉ ÷(­"º š :QM9 Ržjn"4Já¨{¥ ®:yZÜîÔWjЀTHDÀ»pö£`¿PóÀv{±L¶’©ºŒó2MSM©*övFêWR¹s¡×­Ú×Ýl¢‚Ú”#}fH˜}N.&Lv’Ë̅ɸ  ËúλR² ‘“*®6"\;¨ä§Ïò‡TltÞ•7MÝ®¿zä]*’©¢±PMÃXþ)l«uÚ·šÉ*Õ:b \‡§jøV˜f ™>Þ…2»ù‡EîÄníÙP9Ĉˆ×¢n¤\¢U,`°€ðþ÷ò ­·š@¨Ä»¢—=D·¦ž#‡}¡ì‡d³ÕÕe¯¹•¥å-ךC®¼•¼â÷Ö´¥Õ¬4’¥–Ûm €”ÂZ¨ÌØe-Ô T„¥ )JH$Ô‚¢ª;Ê&äÎ%ÞÕý²_v‘‚¡(êo&ÜP0´„ŠR†œ©ÛÖ“o‚.Û/ìB™ƒü‰³´VfG¤j«…ž–9ªnW:i”€Û¦e~TÛÚ@J $0mk†÷°Ž¼·×Ç $]Çè‚VÒÞè[Ÿ!iËkòæpòI”–LJ ‚ÖÞÁ½¯ †$ÛSlªÅ&híK5{¥m(±,AÖ ¸|0ƒ:­s: —i’Úš'ÞÉ-Àùp×ÂúS½¼Ùe=-¦Y¾ªÚÁDFE•õHTZ5È* ~LôCó U×§Þ¦™Ê‘ÕXÄf'oJC2™Ê2©û:¿|ÑáMŒBÕ[bÆDŠŠÇV=ÓV3 œª}tÙòŒ™ÔI›¦<8¬Ï¤¸(!Ðl`Ööóë¨ï¨ß ;0Ý$¯¨_€>›‡Þ؃íeû;šæU9…-SÔ>Öó•/£½z ¹Pû…×Ý+¨[ŠÇR¡'t`èvŠºž¶\m/wiCh;¨Fꔤƒ I“:áVJ6¯sAµEONÓT¼|\D<õ@ê¨uÑŠB«†¨J½LŒxÉ9pÉ«…*ÙŠC»XÜBZ:_¹jŠØoÞº%$é{üHµ¸k4­{5m¶œh!(;Ä ‚`x€tç®%CIê:Ø7½ÿ¿^¥6ù’é¿‹~â:A¸ˆ·xÙQMR€Š;‘DŽâȦEDÄH©Q°³:‡½ëýÿ[`Ù%Àßò°€ßæ>Ÿ=qc/h™«aÚZ°Ûô϶¦_aä‡qµ¤%hZV•%i0A(H ‚0Â(VÒÐãeHq BÓ!IR`…¨P1Di‰‚1²®©Q íÉ÷ULükeˆÎ¬¤e¤"d^.±À /ENÒk–èq½ZbQ2‰JŠ P@JD·kœ½˜)X†4SB²ÉHºM†}³„ BEŠá*¹Ý.I‚®RQÒG!LTÞ(t„êkJ Ýnñ×av¾¸DuïˆTlˆÿêiÊÜ÷CÌqKg}”䵯.£%­9z\QW²­]ë(*¹ •JÒ‘&½º%”›IVÒCum·@è«U„ožf$dÉÄ«;y>íë'l3#;)¦å7|ê*Q7m–1[§þȵY´óˆ ‡ ‘DT›…Д8‚¾æ.tTõˆ–š­¤)ô,é±ç’Š„p£…”LEEÒ¦Ê& ÷¬šE'Ôn%#…sSeÙºwÿêMËü`úÑ;¦é€üJ;|þ~¸e¥ì]ê}¯7h4 ¨6™Q‹ Æ.xá[›P7OuL­è´™kÛÎ8EÉÄKNe䌻ÂHO¹]ƒÂw:¦á &&Qp&P) t Å §£˜B7MÉ”–(ˆ„l€XPD@Æš/H€ \9í ÛpØuñ³g×°q»‡øµùøé`X¼¶7!ÈvY N^ÊURc¼©p:tÐßtÀ9I¾!ù­mnbI}d6.–Ò}ѥȟÛÃ\Ií]€ÚÆôÿ:ÿuÐÉ`Xonƒ¯ß–€¥ñ#$“TLácRLÆ"–Àc@8Žb.&-Œcîpäqwìð:îÝ”L‘D­Š¡@¦ÍÆt(”ák‚†(øDBÂ6:»BÙmŸ©f—=Ïh²Ê‡XESlÔ­ajan8Ú]¨PÝRÙuÈ;ÈV‘väyjåÕ ¥eµ-´§u+ JŠ.EÀZUç¬Î%g±¢ý2¨‚§né á;qÀ¢QÿÄÀ$.b-©e«˜¡S½Œ4š`R&UÚ.b&C„E²åXU Åï•Âe/Ù0(a¾iS¨ ÞÖ˜”„9€ÀÈÆ€ ½¼J&ØvçËDUA 8’&nªKÂ)ª1“9€ªRœ c“ˆ·‰n#cj(ómŸìƒ¶×–Š\ã.©ÏéiÑ5Ùs‹jµ ¨î4—ÔRß´6•ï!Îô •¥!RM¥­Ú’@S”¯·DâÏòj¼ÑUŠŠ «»QT¤îÏŒUL͘QjZ&U5€LÐP Q(“; r“ˆ‚ c˜§5Ã@½ˆå=YV2‚¬lÓDX˃0r÷Ú¤páU7jÍÛ*U. ¦Éª"nôêÜ!Òa‚‡P@çdÜDz¦^›ëp õ·†›`tã☔ʲ @N& P(\L&ÄDt¸ˆ€_º_ÂFHÍJ]ªÚ*‡i­å7Ý„¨ H*˜Ôņ¶Â÷;M¬Se Ð!.‘[Ä€b$Ön<"ú,×.ÙE´q,œTÌÈ[ª€.jØÉ‰ÓP¼i @¡Œ< ‚é1(ÞØ Ú1Ê.CHM@ ¤›Y£>øDN ¨ªžÑrèX-õ¹·ĨƩ¬$Þ¶"¢Á²b œÅ)X%Ä^$“)1ˆñc8sÂtÃÝ\À8Š•Ø9Lö1'| œÿ¸sð\Êþ^°3À ÙeJê\¦ ‰IŽ8ÛçrG6¿;of€ÑÕ »+Z¼ŠŠl¹¦èý± ÕH¯u—kR£}Ú  S%MXÊèÕ_>Úë]ýH" }JwºPàYJÒÉÑ©Ôïš5+ÇðÍc ñ?eq ‚`É‚Ÿh~Sâ{ i¨D½Ò8Œbr&Žê9c@4(˜€#§…üyu×[± Ï<üî Œ`‰*l“(En w'˜ªDx š)¡rÜxÇÛ[ΨY¤r(…ƒ…"‡NAåÒܺ‡ÿ.˜F–^âmzú__ Ý:i¶#¹n&ñ¿KéËM·†rŽx¯â;õå¶ã{kä8a¾Væ7¨oãõ¸ˆ‡‡ÇÛCW¾âÌg‡HÒým÷ÂZ÷R NƒN<ø‰ôpŠäÿ1m÷~XKPtßQ¿Û\â6ð(}G÷ÁÇA¸|þíŠéõ«ž?cÌóùXm6äÔ›ó‰Æ˜ÓŒ:ËùÆÆù` &I<ðv‡ø†þ>??Kà¡ 7°ë¿¿L aé‡4. Ïð?l%QL€|/>aE%ymm¹ÛúúaY»½„9~áû‡í{·Ày‡¦ &­¬ú[øøtÕ5IA›}?o˜8!müyð#¯¯”aêÙè…®nC¨}9/»a}´…­ï[mo÷Îâtåˆí'(ê:uÞÛ‡¥ð¦“ˆä7¶¡{‡-Ãj<ÑH{@/?¿(úi8@í:U6ƒþ<ËÎ$´e-ïr뵿­Ð /`ývŸÅôˆb6#áÓÞ½ƒp–㸞ÞC¯ÇìçëHùÐqꟗÓUD&à_Ë•¯ñ‰±êq \u÷ôçqçáa¶ «+{û×½íë¸ÿL2ý¸Fâ¾¾;x]°žˆó°ù…µð¾ÞXÚóåŸë:3ýŸbh“: ð›ZDÇè užHn>ðë¶¼½?Í­€EþºO_ÏË Qv7ÞÝm{Ëé}¤ÿù†ž ð…yºÔ1>íýDùr¾M Ò4¶ƒç ¿ëÏâ?þ­|ôÿX2GãÈÂ=uÓö×o2ŠèÚ\@uëoóóÁ‚»ÛQÏPÛo6Pxð"ü}ÑxŽº øœiT½-mG‡A¡óúaèY „À#?½±¡ŸÞö6ƒå§†£ûi§˜5=¯ÿŸõØå;_/»í¾ÙGúÏ?¦¿l)£@éþ}}Õy{ëüòë¶Ý,8NUÈ?¯ë¸ìÎŒæüùxßú[†‡ÇŸóÛ^^8Fåq_âMørŸ+þÇ!˜õËçÖúk8Pyˆüzz‡®5ï-µúoá÷å¸`—}ëéòóçÓéÁPWëÓçÏï­‘š‚£úGÊçƒB@˜&þo_ (¦{۽𤒜!{€k×[ˆmæa!! t¿?ˆy`~ôBÖ¿ß/½0ko1ûñÖöÔ_〔òO Ûë¥ð¬G¨|-ûŒ›C—Ì<¯¦,<Ð;Ûê¢#Ð5ù_Ó]°2Jˆn<úßnvÞÚúr×LT”ÁwÓõùò™Âu¶ „pãá¤yÍäü°øfîÂ~{>¼÷ÖòBDÊÓ@¿÷çûâ2l¿†¾`#ã÷õÓ|+{w[ˆtôýõ†÷ó~¥Íˆ÷ˆÒàÏ/¤kœ#v˜+†¿[OC ¾ ˬ°[®×ñ¸xõ|Œ …‡Š×BöÞÝ>- 5_ˆŽý6~]õì ;ŽÖõ·?ˆcYâkùX5ù€i¯–˜N½ _÷Ÿ‰ÿHùÇMó±åãÇÏã…À—ªÄ;ïqÖÿ.^;[ K÷­ÃÞ¿[ÂÂê7çž"¥ë¿Ï•î6·+h8>ÚDD‚Q6à¿Kô· ô#^z¯ï:?ퟮuœš17`:y}/‡9ä„ !~zÃqé~/<5¶v…žz'ŒŽQŽÅgN\1Èó¿»±I1x‡Ç§+^Ø(y!¸ÜÚkn–ûß 3<C§ïõ¯ï‚Çv:‡øž_ç Ÿ¬Çó¿û,u´ÛöÁ‰¢H´i !÷Ž6œ;41GõZܹ|OPÀ¤™1çñú—ï aŠgw築ƒöÀBòßò ä?¼#^x³ýv·{²g…çôœš1¤ZÚ ùŽ—µã ä€á¡¬"úí·À*üu×Ç~|ï¿!åþYÅ~m¸½Fá÷éŒöàÅañ|v;á*óÅŸûËH:ëùtè"ñ¾4Ž¢#ñ ¼ÃoPñ¾ðt÷‡N…¿¦·ùi€ý°yšÃâ @·Øá*ó…ë¼xD[¿ éÔqÁ‚‘", G)´^GÇŽŸ©d­ÿ!·˜_Ì5ûNP@46Üïò×öùiv<¿ü¯¿1×àO]p)^!ôÛž€:øßLÂÁüæ-¡ÿo_ޤO98Ù¤Iñ·+h"ãÇCñ¶$Då„-ïiç¨z…´ë°ý0l%C™­ë ÿIúj9ñ:à³Ea¬sÝžñÐÛÁò“Ûêë}~;óßÇ|-´t"!¨ÞáÌGŸžßÇ-±¢êö±ºl?|úiÿÛ6nBáïz}ü¶é§)Yœ’´ÊæãScqÔrŠP÷xXß×ˤañ(ä£ eIÂi  ªŠÄïR2H‹¨&&ÃÂRåû¦5†ÖÄr”›åÚ,wmÊÙ$nt8À©¥XxLšh˜GP°ˆ Žk–ÃýŠå9†±€å˜t°‡+€í¨ÛaÃ=ôzÉÉ],e[î ¢C‚¤!¸ƒŒÚ¢Ê] qⵆØöÅ•ÔVœ«iBašA•Ö”J½›q÷j)\p ÝmÕÔ¾Ùp€”¸–У¼ã`¼ìµClûMÈBÖï´² ·åmĤTÚN¤!' õ%Y”üNTjb˜Kþؤ'Tâ^ ) ™ pÖÃÌCk†)zÄÔ¬˜J¸›&CŦàžÐª†°& „Jc€NA”·â q ’\ɨŠ õÇ TˆTS_B‚ið¨eü""(Ž¢†pw}âBás#ÇÄ&Mvè(¨BÜ@tn ˆ€& €k¦¦Å?‘gÙ®ÍæTù¶MVº:êU…¶êBV“ÇXSn % I ‰Ee5}:éªÚ²à!I$‚&Ò•$…$õI†˜µ„ÎÈTÙ$²ñ’Í×2]árVI‰xJ"`9Ó|¨@@›MÂV9 þ´`¼A+ ô€ ¦ÝžÔõ+8|˜¢) "P"JSŠNY=]Ô’)ÝâR&T…(4ÅLà$7ê™5€Ö ”{±0‡ ÀaÁ4%‘^'HÉ3Kí2ìÞ®‘Î’#fƒ·üS?èÇÅÇa²ö—·žÓ¶§,{'¯ÏÅ6]TÑf­Œ²Žšul¨n­§êZA«,¸’Pë-¾Û/!JCÍ­Œ0PlfÏeÕªfˆ¸ûj iu¸òZX …!µ+ºÞI¥JB”… ä›ãÑ€`"r4¨êTÊTÿÜA ÄŒQ±øQˆ°ùDÁîÜ8ŒI]ó"*ý±®XÅÆ9Ü éJ*+؉ ÏEÔY@Èq˜D€A[Ñì¬ýÙÙ Ì\,à®xšª™s(fè$Ü®Œ¹P©wB¡ —ÄÁ6hê£x’&ªlSŒ  ˆ¨º‚&:r <"©¸Î)}ÆétA0‰ÔR¦¤¤~¹öé©›Sޏ ”¥ LIŽ’ºêB–µ¥"I&0å¡X/#&´Ã°º‹,uÎnŒæ-`(_„¥.…(ZØ–äp”J|@ øŽú^ÖÓ##Ĉ“„€8†ÖÃß1ëÓ .î&°ßQ¶£¨[óé|tFUFÞÎdMQHåA;ê ±ãkáÔ Aª]U}bžþ„ÂP–@›Ç/QF‘qq5ǨòÐuún6×Ka å[‰‡ÃKè7¶šøuç~¸Sz¿ˆˆõøþãÏ{Ü5Ãyu.#ᯘúu˜ƒfµeŪó$Ÿ¤|üoÂ)›#tŸ§Ú88U _¿Ÿ¨`r,[€ˆðômõÂxy…þþú`@°¡”Ÿ·–£×†Qiðð½ú|= *sh`0yñó׃ƒ+€òG¸†Â!ÁC†Ãñ +ER£^:ü<0Y@ê=uœ+{@óâøÛ÷{í®†ð÷¾¸L*ÆÜC×ïO!ò Ú•ÏÌþ: Öàæpw¿ÛÝÒÚëôð¾0Þåò°ýpOŒ-¨ þXÜá~¸_$ëËO.}4å8Ño‘øóÁÐX,ˆx_m|ÿlULà´Âf=6ûú`Ô¾m+‹Ûˇ¡l¥C†qæ,g}ë ¿°øyá;¾6—ù[éo–)î:Àyôûûç… xóë:DÇ^œ¼_ëËì>: óâ[}ü4¿\ ßMÆ÷øyà–0Ú†Þê¿YõúcAëôòä9a@ú†&Þ¿a‚I˜t¸Û­öýü0t‚¾½?Ž¿<•qA??iÆŠAáxú|0g‹‚Úˆ>¿>£Ëo€c;ÛÞ÷ÜD? 4¶Ø,'Zý0˜DDooã§–JäŽmðùÞ~S® )#á6Á±=ím®é¨}øàÊj[‡Kôõúh>8KØ}9`Ñ 7ÿvm×%Ÿ¤ñáÏ׆@:ý|¾˜ZI[kоǧ†"¸Ÿ[ù†Ë €w}÷ßÇÇúÀgVÜÇ;ùúßë®·RF¦tyÏQÒ0Ø?½ÿLjçÐ`áÜ Ââ6ûýº_˜oqqýWóëè>;‡‚¨ñ[OùóúàRª !~¼¶õ¿× SVD_”|´à#…þWÁe™áÃYý'Ž(:€ñtó¿Çüö )ØŠ@` ùõ^¡õ놢+kÏpßå×çëËN¸wv¿^]>ÐéË{aþãñõõåp÷WÞ>6Ž$ 5ðÁò:±ÇÞæ<öé§Ã{sËž"‡¼#p~–ëÊü¯å²-é×â:òÒÜÀ0:‹\€òÖÁûtùy`&¬óŸ39ëÎ6ñ<þFÿyN5QÀòÜ|y[˜kó¾7nì@w翯§Ÿ.C¶¸JUMFÝGï®ãkzxãB*%‹›oûlRª3ÊþGŒrùrÔA¡Èu¼ÇÌß(ñ²ê눅î~ðß•ü~@\s°ü~ §7×Ï•´Òáðå¦ÔRÆÜG@Øoñ×ûÛ– 5GŸÀ“iôý°.é<‡À]_–À‡?¯îT\D7ø†ãoë %wƒÈ-ëÏ*@@GþpY«P™>­{’O Zñᆓk_§ÖÓŽ¸4eÄFúÞ€7õøò¾3ÚFÖ¸ûƒø·ùÂj†ÜÆúþØ ŒV¡Îû[•ù`•U«#OÓÏïàn`o§Ký¿n~R2ûöõKØ?l2â;úùõÁQVá½À6ñßîøÇ5„@mèÇØà…T¨ÜB×åò÷uã†ÆºstõË­Œ™QÔnø—í·ÃaÓ[yéôÁ10Žãâ?Þ4”÷ˆ`…TvÖþSž\xéÃÜO£ëÑðÁ¡[Qçäož¿}1ç´9˜à–X-qæ¾xNaÒþ:ÿ8$¾®ú‹^y||£a#øNEÏçð°\eƒP⿵òþºá8!¾¡óÆÜa®ú|üµÁ%óÎxÛM|}pÀ åç#ôÀâ¨Ûù†Ç˜a€Ì{€Øþ6çÄ÷ [¯Ý°A¨<æÖ×§èiÎG¸-ßEAìDŒiÞì,Æ¢` 7ëá÷Ó©õjmÃéËÃü `aAˆÏ—:Nyœï­ÎþŸãßø|¿¼ã 7ñðÇ‚~ç|ßc‡>ž<´úDá6áo tá=߀Z××{ßÎ7 oˆÛæ6Âp¨P‚6ùã;ÒÛåÊßqžÐ¡¡<–×ëätÆ$ÿoÃÃŒk}5ýÀ…½ñõ°õÐwߦäÀ!q¿;€ØCÄCŸ•ƒöÂ/tàB¨!a(íÈy}ü04U($ðý¿©¦Z´Æ¼ŒëöômÝê}ô—ò‡_!ò9Y< 5Û˜è!¶m÷¯8ñì:Xt‡ïÿŒ-6t!kÖçò0sçaó·L?åù†â“ïGIЈô:k00æ·‡/.¼Ç׌²Áí­¯Ïo>¾zé® ÖY¡Ú¹ ŠJ 7ÐD,6¶¡pæQ¸n_‹Gö·½Ëa‡=uûᤘ€½§€øi}·½úô¾,<·8eÖOR”<í–ÜiÀÛˆPIZ‚$A¯1¿L´,-²P´R¤˜ ˆ ˆ6"ßÊpš+Ó€ª‘1‰ÎeÉŽ¨½ƒ……É@€6²dL…XnaâÃ2BVi3 â×!ÄÂcª$"çPn ”íÀÂ#¨^Àk{ÀÒbJH¦¸€ùÃp4 ‡—AÜê³Wõ‘1`% ë x…ƒ­Ç¬Ç³˜ÌV§è_s.RÉRšlï2 ȃ! rHJF‘¦±Ÿf,$!ä%ø°Q¢®¡©ërM耕“v  T…Äü=âAÔ¶)Š"™nŒ^!þ`Nà!q ˆØ»œ©ä“öf@Å#u—Pî-ÃÅÆDÚ"A6æ)Q0ØGq™Nœhÿ"?ý@êô°† f©¸BÛ{¥× ‡ŸÓ] (ì¯+iRöl·"É@I:Zyóúp£´u*å2A‹É16Ó^zGéˆaýâÅs,ºŠ˜,*˜L @ð–ãb/p(7¸Ž$fqÌ¢Q B”ÀX55¿;òøkÌ㙀 „4ßNŸ¿=Ç«qä…ïïuç·¼‚ÿL?Ñå¹Πû (SðA¨ræ€X'_ƒ]~²¸‚ò¡Ø™Ýáoå=0aûýìm5çquý×b"7ŽÀëÈ:[ã¿úéåÄ}áéã§ ûßq¶Ë®"#¯˜òûøùoͳU:Uï“Ç_×ån¤ÆSÓ"üøð·È[Ry `7 \G÷ñåðÛ m¸a)SïÏ÷~AéôÀŠ(:ë¯Ð?‘øü°LÆâX„Ô¾\Q$ó$þÝ~1â0ðÛqñû×ãËïŒG¦3lëôÃy2Iç… |f3c0±ŒÆc0á„øÌAåðþ03l“#¨±õêó"0c”l>ñ©Fáž=À°˜;¦Ü¼y}¿|߀ˆnCéü}óóÀ¸Ìmi›GÌc1è †øóƒ’­áÔk‚°8\1¹Mo.a‚Àa.Üñ°o®Ý?Œ j/q˜:}C‚àa¶ƒ ýúcromÀ~_~'ã0.=ytǘÌ•ð?¿ßÑ-Hâ>o· d‡0ù†Û@DA·ßÞø2Q†»ïã÷Ë¥FÀé§Qû`¼'é¿¿ã„ÓûÁ©V„t˜úO®£ƒ ¦¢_—Pé ±¨˜GŸ+ïç‚ØôÃßï×%vƒÃ‰7×ÂñÊ|1šàéáå¦&Ãç÷÷ç‚D8_N›Ÿ<!ƒQØ/®ú?Æ äo0<ì8uÀJŽžñ¶âZú`¨!Ìluøôdž0€tû 9¯äùàÀ¾~¯öÀ ëíÇå{Áèûçý`dÔ}v¾»z}† €|ú}é 6=<µ p.ðs:ú>_tð‚-pyüøáM%Nz[–ÛõÞØ8*oËì5ß@¿®ɰ‡ßÓD}Ñ¡õÆÂô¹¼E¸ÚÞP<-בõl`*WØo~\ývÁ“*Ÿ÷­µ°èi¯ï®lpò°úëü`À¸7ä¿LføÒO1òûxcTx~Ÿ\¡ÄGKý9‡‡?ñ‚â ‰¬=m!ÓM9ãuÂ>`õþÇ„o®V8tÿëöÆ÷ËŸËÕ¾ØQL÷(€ˆl>ƒý‡Ïmp š ü.?<‘ínV°ì>aþ7ÆÊ˜7 tµÃë÷|¬øqøG¯;àarg§­p˜GÀ>ùãÎ1¾úôþ° Œ7ÓÃùþ1¥Ç{ë×*ãÙ:øjOíl4ñõM:`c›A×_Ÿ¯M<°Pâ7·.^>xpòÛïïL¥OAãõá¯Lo„4ßï_¿–0ƾÁ·ÇïúÀBp µ—÷8Í®»ýé‚”¡ '[Åý|úã1†5ü¹ó  |<ñî4=í§¯– *âN¾½pÀ’’o^º…ŒÆcÁ¸à¥.l4â}põâ$¦.uà9~ÿO0D.8нÃËÃïï¦4 tÆ¢ qÂu,ͬÏ×®†`@8…ï­þXÐFâ#×€B÷·ó÷÷¾6À çÄüÎ7—/žž¹Û\f9yõßúþ?m…Ç‚!aÁDˆ"úÈñãáÆÝxpD¤‹È??ZޏŒÇž9¹¯ñ÷üàcn>±æ3€•cãÓôCan o{õ¾_}p3ß2mn ‡˜±øàáTçê¿AûÓRp%¸ˆ#ïáñþÀD6`Rª! ýÿ^¿QÁí¼RDÃÄG­>\ *gzj9õ6áœ6¸Ø:€è>CËmµå­´ÂÂÄ-cykÒß ®Á†AæS[ÀGO†ßAßÈäK®¡â[ ÿ8w§Ì”Ü{ÆÑ8ÞxÇà œ§P#üqƒoåÏR‚öýFÖÛPúˆ88Y`Òæ¿vøb;#Ñ Œ¸kîÛöûóÀÀúÖ¹‚ÿý€@|uûÛ-g«HùxÒ/À„rHª4žyh- ¿V8PGc…‡Ç_^zà‚²B7÷‡qç§;_-mòÃ@_ÜQ}Pý‡ðü¯¦áqýíñ iÜõjY:q7>ïW·N#š4‹ÇÒÿúaÀâB÷÷¶ñæi·ÌC׫¼¾¿}m/l'(äîâ;øØÁÓîØ"¢â# ÜzýùzøjsE9>ùóð -÷…mSÅ ñoŒ`e—¸ˆþôþnc„å¸ßQåÓÇïèƧPDw¸óýîÁô.srן_מŸ}K&I'ÕÈøüE°µ âE¬tâNºÇ;žC]Nk¹}~ÿ¼iŒÆa½j$ž@üùàð1˜ãqòÓùûðÀ¢6˜Æñ˜Ìf3ŒÂ¨ãaÓ¦7Á|Æ XˆãÃÃŒÆc1°`ÎJ6x|À¤Û×øÁø-cCÆ}|#àRšúÿ_¿ïc1˜L‹ø`Æ3ŒÆÒLˆç À‘Ôßåž3ŒÆ`üD9ÆÅ5¼¹†)¹†¼°[“qòýÃA3˃€ !pǸŸ¨=~˜ã1¸s×0w0úà| ŽC\¦Æýtõô#ÜmkéJ§+Þ܇¿Ž8ˆZÃ×öÀx6Hâ}pð邈€?84'¸ˆh ¹Û_±éóÀ…òÞø$˜/Ô0p›Ÿì1$Ÿž·<<9òÒØÌQ°†Þ¿~X0Øp[ôß<$hHÆcÓ)a½õì6ûå€  \@GKßoãÀOú‡ÓèØQ̘á™óÆ`P0rð×\ Sì{í‚x›ŸìùåË÷øã0¤Cêt¿ï¶ Äú!ðþG Ķ㽷妘Â<%ÔysðÆÂ‰å¯ê‘úã1èœ.>··[í®)ôæ"!ñ üö˜O0j:ÚÿMÇË÷ |òÆcÕNÏKÞ÷¿]0PÇióß`óý‡ô§Ô1…GèDußž3‘AßÇ[ëÓ_…°cˆG[Þúý† 'ÏÓ÷Á¢þûç€ïÄóõêØÌ€Ì~Añþ1±ÿHú}C·¯ì8 1=ý~ØÌ Þ ùi¸؈cCœà>:úýóµðsòýÃ`²©10L‹E´Òúz  h°{׸|ÎÁ|Ð$LëÐà{€ü/éË_OŽ¸Ð»‡˜c ¸ùŽ“784h8[†<À'½õôòûß`þ¡ôú` ÓÏïã\jkXo·Îþ?{cl}ÃË÷¦J¢N—òûãLl¶»rƸÌ¥hùúå€F˜:éŒ0€Ü·°õåä#÷û`,fI&N J‰0F¼|±† €o÷ö°\oq¾üðc©Ë×öƱ°ad@¿:NÆc1˜!B úœŒÆcÁØ|‡Æ`3o¦Áóûþñïy¦Úü¿¯žÆc ˆ4¥ q­È×ׄ``8u°ýóÿªˆl`å¿Ø_炸Ìl(0¶’=|~x=ß§ÓøÆÝÿ‡ßÇ ø‚"q¾¿ÆPãêܼ=Z RŽ3ÌrŽs® ÷Æû·ñcäåü_öÀ'Ø<ÿaÀX PúÿöŽ3ëÊ6”'KðòúòÓ[óú_ÇlcëaMmòýõÆ`n>cõÁ%dôúüp`BFƒŒÞ1¹ŒÐ~Ï/¾XŒÁfÀž@à^sðýÆc1˜ÌŒÀgƒÔ~þù`Ÿ@ƸÌf3ŒÆcDÄuûúã1ÿÙallegro4.4-4.4.2/addons/jpgalleg/include/000077500000000000000000000000001173507505700200665ustar00rootroot00000000000000allegro4.4-4.4.2/addons/jpgalleg/include/dct.h000066400000000000000000000031551173507505700210150ustar00rootroot00000000000000/* * __ _____ ______ ______ ___ ___ * /\ \ /\ _ `\ /\ ___\ /\ _ \ /\_ \ /\_ \ * \ \ \\ \ \L\ \\ \ \__/ \ \ \L\ \\//\ \ \//\ \ __ __ * __ \ \ \\ \ __| \ \ \ __\ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\ * /\ \_\/ / \ \ \/ \ \ \L\ \\ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ * \ \____// \ \_\ \ \____/ \ \_\ \_\/\____\/\____\ \____\ \____ \ * \/____/ \/_/ \/___/ \/_/\/_/\/____/\/____/\/____/\/___L\ \ * /\____/ * \_/__/ * * Version 2.6, by Angelo Mottola, 2000-2006 * * Fast Discrete Cosine Transform coefficients. * * See the readme.txt file for instructions on using this package in your * own programs. */ #ifndef _JPGALLEG_DCT_H_ #define _JPGALLEG_DCT_H_ #ifndef M_PI #define M_PI 3.1415926535897932384626 #endif #define SQRT_2 1.4142135623730950488016 #define SCALE_FACTOR(i) ((i) == 0 ? 1.0 : (cos((i) * M_PI / 16.0) * SQRT_2)) #define AAN_FACTOR(i) (SCALE_FACTOR(i / 8) * SCALE_FACTOR(i % 8)) #define FIX_0_298631336 2446 #define FIX_0_390180644 3196 #define FIX_0_541196100 4433 #define FIX_0_765366865 6270 #define FIX_0_899976223 7373 #define FIX_1_175875602 9633 #define FIX_1_501321110 12299 #define FIX_1_847759065 15137 #define FIX_1_961570560 16069 #define FIX_2_053119869 16819 #define FIX_2_562915447 20995 #define FIX_3_072711026 25172 #define IFIX_1_082392200 277 #define IFIX_1_414213562 362 #define IFIX_1_847759065 473 #define IFIX_2_613125930 669 #endif allegro4.4-4.4.2/addons/jpgalleg/include/internal.h000066400000000000000000000124621173507505700220600ustar00rootroot00000000000000/* * __ _____ ______ ______ ___ ___ * /\ \ /\ _ `\ /\ ___\ /\ _ \ /\_ \ /\_ \ * \ \ \\ \ \L\ \\ \ \__/ \ \ \L\ \\//\ \ \//\ \ __ __ * __ \ \ \\ \ __| \ \ \ __\ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\ * /\ \_\/ / \ \ \/ \ \ \L\ \\ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ * \ \____// \ \_\ \ \____/ \ \_\ \_\/\____\/\____\ \____\ \____ \ * \/____/ \/_/ \/___/ \/_/\/_/\/____/\/____/\/____/\/___L\ \ * /\____/ * \_/__/ * * Version 2.6, by Angelo Mottola, 2000-2006 * * Internal library definitions. * * See the readme.txt file for instructions on using this package in your * own programs. */ #ifndef _JPGALLEG_INTERNAL_H_ #define _JPGALLEG_INTERNAL_H_ #include #include #include #include #include #include #include #include #include #ifdef TRACE #undef TRACE #endif #ifdef DEBUG #define TRACE fprintf(stderr, "[JPGalleg: %s]", __FUNCTION__); _jpeg_trace #else #define TRACE 1 ? (void)0 : _jpeg_trace #endif #define CHUNK_SOI 0xffd8 #define CHUNK_EOI 0xffd9 #define CHUNK_JPG0 0xf0 #define CHUNK_JPG13 0xfd #define CHUNK_DHP 0xde #define CHUNK_EXP 0xdf #define CHUNK_DNL 0xdc #define CHUNK_DAC 0xcc #define CHUNK_SOF3 0xc3 #define CHUNK_SOF5 0xc5 #define CHUNK_SOF6 0xc6 #define CHUNK_SOF7 0xc7 #define CHUNK_SOF9 0xc9 #define CHUNK_SOF10 0xca #define CHUNK_SOF11 0xcb #define CHUNK_SOF13 0xcd #define CHUNK_SOF14 0xce #define CHUNK_SOF15 0xcf #define CHUNK_APP0 0xe0 #define CHUNK_APP1 0xe1 #define CHUNK_APP2 0xe2 #define CHUNK_APP3 0xe3 #define CHUNK_APP4 0xe4 #define CHUNK_APP5 0xe5 #define CHUNK_APP6 0xe6 #define CHUNK_APP7 0xe7 #define CHUNK_APP8 0xe8 #define CHUNK_APP9 0xe9 #define CHUNK_APP10 0xea #define CHUNK_APP11 0xeb #define CHUNK_APP12 0xec #define CHUNK_APP13 0xed #define CHUNK_APP14 0xee #define CHUNK_APP15 0xef #define CHUNK_TEM 0x01 #define CHUNK_RST0 0xffd0 #define CHUNK_RST1 0xffd1 #define CHUNK_RST2 0xffd2 #define CHUNK_RST3 0xffd3 #define CHUNK_RST4 0xffd4 #define CHUNK_RST5 0xffd5 #define CHUNK_RST6 0xffd6 #define CHUNK_RST7 0xffd7 #define CHUNK_JPG 0xc8 #define CHUNK_SOF0 0xc0 #define CHUNK_SOF1 0xc1 #define CHUNK_SOF2 0xc2 #define CHUNK_DHT 0xc4 #define CHUNK_SOS 0xda #define CHUNK_DQT 0xdb #define CHUNK_DRI 0xdd #define CHUNK_COM 0xfe #define SOF0_DEFINED 0x01 #define DHT_DEFINED 0x02 #define SOS_DEFINED 0x04 #define DQT_DEFINED 0x08 #define APP0_DEFINED 0x10 #define APP1_DEFINED 0x20 #define DRI_DEFINED 0x40 #define IS_PROGRESSIVE 0x80 #define JFIF_OK (SOF0_DEFINED | DHT_DEFINED | SOS_DEFINED | DQT_DEFINED | APP0_DEFINED) #define EXIF_OK (SOF0_DEFINED | DHT_DEFINED | SOS_DEFINED | DQT_DEFINED | APP1_DEFINED) #define LUMINANCE 0 #define CHROMINANCE 1 #define PASS_WRITE 0 #define PASS_COMPUTE_HUFFMAN 1 /* This expression is made to return: * Quality = 100 -> Factor = 10 * Quality = 1 -> Factor = 0.1 * Other values follow a logarithmic curve */ #define QUALITY_FACTOR(q) (pow(10.0, ((q) - 50.5) / 49.5)) /* Default quality/flags values for save_jpg() and save_memory_jpg() */ #define DEFAULT_QUALITY 75 #define DEFAULT_FLAGS JPG_SAMPLING_444 typedef struct HUFFMAN_ENTRY { int encoded_value; int value; int bits_length; int frequency; } HUFFMAN_ENTRY; typedef struct HUFFMAN_TABLE { HUFFMAN_ENTRY entry[257]; HUFFMAN_ENTRY *entry_of_length[16]; HUFFMAN_ENTRY *code[256]; } HUFFMAN_TABLE; typedef struct HUFFMAN_NODE { HUFFMAN_ENTRY *entry; int frequency; struct HUFFMAN_NODE *parent; struct HUFFMAN_NODE *left, *right; struct HUFFMAN_NODE *prev, *next; } HUFFMAN_NODE; typedef struct HUFFMAN_TREE { HUFFMAN_NODE *node; HUFFMAN_NODE *head, *tail; int depth; } HUFFMAN_TREE; typedef struct DATA_BUFFER { short data[64]; } DATA_BUFFER; typedef struct IO_BUFFER { unsigned char *buffer; unsigned char *buffer_start, *buffer_end; int current_bit; } IO_BUFFER; extern int _jpeg_getc(void); extern int _jpeg_putc(int); extern int _jpeg_getw(void); extern int _jpeg_putw(int); extern INLINE int _jpeg_get_bit(void); extern int _jpeg_put_bit(int); extern void _jpeg_flush_bits(void); extern void _jpeg_open_chunk(void); extern void _jpeg_close_chunk(void); extern int _jpeg_eoc(void); extern void _jpeg_new_chunk(int); extern void _jpeg_write_chunk(void); extern void _jpeg_chunk_putc(int); extern void _jpeg_chunk_putw(int); extern void _jpeg_chunk_puts(unsigned char *, int); extern void _jpeg_mmx_idct(short *, short *, short *, short *); extern void _jpeg_mmx_ycbcr2rgb(int, int, int, int, int, int, int, int, int, int, int, int, int); extern void _jpeg_mmx_ycbcr2bgr(int, int, int, int, int, int, int, int, int, int, int, int, int); extern void _jpeg_mmx_rgb2ycbcr(int, short *, short *, short *, short *, short *, short *); extern void _jpeg_mmx_bgr2ycbcr(int, short *, short *, short *, short *, short *, short *); extern void _jpeg_trace(const char *, ...); extern HUFFMAN_TABLE _jpeg_huffman_ac_table[]; extern HUFFMAN_TABLE _jpeg_huffman_dc_table[]; extern IO_BUFFER _jpeg_io; extern const unsigned char _jpeg_zigzag_scan[]; extern const char *_jpeg_component_name[]; #endif allegro4.4-4.4.2/addons/jpgalleg/include/jpgalleg.h000066400000000000000000000054341173507505700220320ustar00rootroot00000000000000/* * __ _____ ______ ______ ___ ___ * /\ \ /\ _ `\ /\ ___\ /\ _ \ /\_ \ /\_ \ * \ \ \\ \ \L\ \\ \ \__/ \ \ \L\ \\//\ \ \//\ \ __ __ * __ \ \ \\ \ __| \ \ \ __\ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\ * /\ \_\/ / \ \ \/ \ \ \L\ \\ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ * \ \____// \ \_\ \ \____/ \ \_\ \_\/\____\/\____\ \____\ \____ \ * \/____/ \/_/ \/___/ \/_/\/_/\/____/\/____/\/____/\/___L\ \ * /\____/ * \_/__/ * * Version 2.6, by Angelo Mottola, 2000-2006 * * Public header file. * * See the readme.txt file for instructions on using this package in your * own programs. */ #ifndef _JPGALLEG_H_ #define _JPGALLEG_H_ #include /* Library version constant and string */ #define JPGALLEG_VERSION 0x0206 #define JPGALLEG_VERSION_STRING "JPGalleg 2.6, by Angelo Mottola, 2000-2006" /* Subsampling mode */ #define JPG_SAMPLING_444 0 #define JPG_SAMPLING_422 1 #define JPG_SAMPLING_411 2 /* Force greyscale when saving */ #define JPG_GREYSCALE 0x10 /* Use optimized encoding */ #define JPG_OPTIMIZE 0x20 /* Error codes */ #define JPG_ERROR_NONE 0 #define JPG_ERROR_READING_FILE -1 #define JPG_ERROR_WRITING_FILE -2 #define JPG_ERROR_INPUT_BUFFER_TOO_SMALL -3 #define JPG_ERROR_OUTPUT_BUFFER_TOO_SMALL -4 #define JPG_ERROR_HUFFMAN -5 #define JPG_ERROR_NOT_JPEG -6 #define JPG_ERROR_UNSUPPORTED_ENCODING -7 #define JPG_ERROR_UNSUPPORTED_COLOR_SPACE -8 #define JPG_ERROR_UNSUPPORTED_DATA_PRECISION -9 #define JPG_ERROR_BAD_IMAGE -10 #define JPG_ERROR_OUT_OF_MEMORY -11 /* Datafile object type for JPG images */ #define DAT_JPEG DAT_ID('J','P','E','G') #ifdef __cplusplus extern "C" { #endif extern int jpgalleg_init(void); extern BITMAP *load_jpg(AL_CONST char *filename, RGB *palette); extern BITMAP *load_jpg_ex(AL_CONST char *filename, RGB *palette, void (*callback)(int progress)); extern BITMAP *load_memory_jpg(void *buffer, int size, RGB *palette); extern BITMAP *load_memory_jpg_ex(void *buffer, int size, RGB *palette, void (*callback)(int progress)); extern int save_jpg(AL_CONST char *filename, BITMAP *image, AL_CONST RGB *palette); extern int save_jpg_ex(AL_CONST char *filename, BITMAP *image, AL_CONST RGB *palette, int quality, int flags, void (*callback)(int progress)); extern int save_memory_jpg(void *buffer, int *size, BITMAP *image, AL_CONST RGB *palette); extern int save_memory_jpg_ex(void *buffer, int *size, BITMAP *image, AL_CONST RGB *palette, int quality, int flags, void (*callback)(int progress)); extern int jpgalleg_error; extern const char *jpgalleg_error_string(void); #ifdef __cplusplus } #endif #endif allegro4.4-4.4.2/addons/jpgalleg/include/mmx.h.cmake000066400000000000000000000000321173507505700221120ustar00rootroot00000000000000#cmakedefine JPGALLEG_MMX allegro4.4-4.4.2/addons/jpgalleg/license.txt000066400000000000000000000016071173507505700206320ustar00rootroot00000000000000The zlib/libpng License JPGalleg is copyright (c) 2000-2006 by Angelo Mottola This software is provided 'as-is', without any express or implied warranty. In no event will the author be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. allegro4.4-4.4.2/addons/jpgalleg/misc/000077500000000000000000000000001173507505700173765ustar00rootroot00000000000000allegro4.4-4.4.2/addons/jpgalleg/misc/fixver.sh000077500000000000000000000016731173507505700212470ustar00rootroot00000000000000#!/bin/sh # # Shell script to adjust the version numbers and dates wherever they appear # on the JPGalleg sources and text files. if [ $# -ne 2 ]; then echo "Usage: fixver major minor" 1>&2 exit 1 fi ver_str="$1.$2" year_str="$(date +%Y)" echo "s/Version [0-9]\.[0-9], by Angelo Mottola, .*/Version $ver_str, by Angelo Mottola, 2000-$year_str/" > fixver.sed echo "s/JPGalleg [0-9]\.[0-9], by Angelo Mottola, .*/JPGalleg $ver_str, by Angelo Mottola, 2000-$year_str/" >> fixver.sed echo "s/\"JPGalleg [0-9]\.[0-9], by Angelo Mottola, .*/\"JPGalleg $ver_str, by Angelo Mottola, 2000-$year_str\"/" >> fixver.sed echo "s/JPGALLEG_VERSION .*/JPGALLEG_VERSION 0x0$1\0$2/" >> fixver.sed files_list=`find . -type f "(" -name "*.c" -o -name "*.s" -o -name "*.h" -o -name "makefile*" ")"` for file in $files_list; do echo "Patching $file..." cp $file fixver.tmp sed -f fixver.sed fixver.tmp > $file done rm fixver.sed fixver.tmp echo "Done!" allegro4.4-4.4.2/addons/jpgalleg/misc/runner.c000066400000000000000000000041621173507505700210560ustar00rootroot00000000000000/* * Silly little bodge for getting GNU make to pass long commands * to broken programs like the Microsoft and Watcom linkers. This * tool is built with gcc, and invoked using GNU make. It echoes * the arguments into a temporary file, and then passes that as a * script to the utility in question. Ugly, but it does the job. * An @ symbol marks that all commands from here on should go in * the argument file, and a \ character indicates to convert slashes * from / to \ format. */ #include #include #include char **__crt0_glob_function(char *_arg) { /* don't let djgpp glob our command line arguments */ return NULL; } int main(int argc, char *argv[]) { char buf[256] = ""; FILE *f = NULL; int flip_slashes = 0; int ret, i, j; char *p; if (argc < 2) { printf("Usage: runner program args\n"); return 1; } for (i=1; i= 126) { fprintf(stderr, "Runner oops: command line is longer than 126 characters!\n"); remove("_tmpfile.arg"); return 1; } } ret = system(buf); remove("_tmpfile.arg"); return ret; } allegro4.4-4.4.2/addons/jpgalleg/misc/test.c000066400000000000000000000042731173507505700205270ustar00rootroot00000000000000/* * Benchmark test program for JPGalleg * * Version 2.6, by Angelo Mottola, 2000-2006 * * This program tests the speed of the JPGalleg loading functions. */ #include #include #include static volatile int timer = 0; static void about(void) { printf(JPGALLEG_VERSION_STRING "\n" "Benchmark utility\n\n" "usage:\n" "\ttest [-f file] [times] [-nommx]\n\n" "-f file\t\tThe JPG image file to test with. If this is not specified, the\n" "\t\tprogram will try to use \"jpgalleg.jpg\" from the current dir.\n" "times\t\tNumber of times the test is repeated. Defaults to 30.\n" "-nommx\t\tDisables MMX optimizations before doing the test.\n\n" ); exit(EXIT_FAILURE); } static void timer_handler(void) { timer++; } END_OF_FUNCTION(timer_handler); int main(int argc, char **argv) { BITMAP *bmp; PACKFILE *f; char *file = NULL, *times = NULL, *memory = NULL; int arg, i, n, start, end, size; allegro_init(); install_keyboard(); install_timer(); jpgalleg_init(); set_color_conversion(COLORCONV_NONE); for (arg = 1; arg < argc; arg++) { if (!strcmp(argv[arg], "-nommx")) cpu_capabilities &= ~CPU_MMX; else if (!strcmp(argv[arg], "-f")) file = argv[++arg]; else if (!times) times = argv[arg]; else about(); } if (times) n = atoi(times); else n = 30; if (!file) file = "jpgalleg.jpg"; bmp = load_jpg(file, NULL); if (!bmp) { printf("Cannot find %s!\n", file); return -1; } size = file_size(file); memory = (char *)malloc(size); if (!memory) { printf("Not enough memory!\n"); return -1; } f = pack_fopen(file, F_READ); pack_fread(memory, size, f); pack_fclose(f); LOCK_FUNCTION(timer_handler); LOCK_VARIABLE(timer); install_int(timer_handler, 10); printf("Average timing for %d function calls:\n", n); start = timer; for (i = 0; i < n; i++) bmp = load_jpg(file, NULL); end = timer; printf("load_jpg: %f seconds\n", ((float)end - (float)start) / 1000.0 / (float)n); start = timer; for (i = 0; i < n; i++) bmp = load_memory_jpg(memory, size, NULL); end = timer; printf("load_memory_jpg: %f seconds\n", ((float)end - (float)start) / 1000.0 / (float)n); free(memory); return 0; } END_OF_MAIN() allegro4.4-4.4.2/addons/jpgalleg/plugin/000077500000000000000000000000001173507505700177415ustar00rootroot00000000000000allegro4.4-4.4.2/addons/jpgalleg/plugin/datjpeg.c000066400000000000000000000274661173507505700215420ustar00rootroot00000000000000/* * __ _____ ______ ______ ___ ___ * /\ \ /\ _ `\ /\ ___\ /\ _ \ /\_ \ /\_ \ * \ \ \\ \ \L\ \\ \ \__/ \ \ \L\ \\//\ \ \//\ \ __ __ * __ \ \ \\ \ __| \ \ \ __\ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\ * /\ \_\/ / \ \ \/ \ \ \L\ \\ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ * \ \____// \ \_\ \ \____/ \ \_\ \_\/\____\/\____\ \____\ \____ \ * \/____/ \/_/ \/___/ \/_/\/_/\/____/\/____/\/____/\/___L\ \ * /\____/ * \_/__/ * * Version 2.6, by Angelo Mottola, 2000-2006 * * See README file for instructions on using this package in your own * programs. * * Grabber plugin for managing JPEG image objects, derived from the * Allegro datimage plugin. */ #include #include #include "allegro.h" #include "allegro/internal/aintern.h" #include "datedit.h" #include static char quality_string[64] = "Quality: 75 (medium)"; static int quality_cb(void *dp3, int d2); static DIALOG settings_dialog[] = { /* proc x y w h fg bg key flags d1 d2 dp dp2 dp3 */ { d_shadow_box_proc, 0, 0, 292, 190, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, { d_text_proc, 70, 10, 260, 8, 0, 0, 0, 0, 0, 0, "JPG import settings", NULL, NULL }, { d_text_proc, 16, 30, 260, 8, 0, 0, 0, 0, 0, 0, quality_string, NULL, NULL }, { d_slider_proc, 16, 40, 260, 16, 0, 0, 0, 0, 99, 74, NULL, quality_cb, NULL }, { d_radio_proc, 16, 70, 260, 11, 0, 0, 0, D_SELECTED,0, 0, "No subsampling (444)", NULL, NULL }, { d_radio_proc, 16, 85, 260, 11, 0, 0, 0, 0, 0, 0, "Horizontal subsampling (422)", NULL, NULL }, { d_radio_proc, 16, 100, 260, 11, 0, 0, 0, 0, 0, 0, "Hor./Ver. subsampling (411)", NULL, NULL }, { d_check_proc, 16, 127, 100, 11, 0, 0, 0, 0, 1, 0, " Greyscale", NULL, NULL }, { d_check_proc, 188, 127, 100, 11, 0, 0, 0, 0, 1, 0, " Optimize", NULL, NULL }, { d_button_proc, 106, 160, 81, 17, 0, 0, 0, D_EXIT, 0, 0, "Ok", NULL, NULL }, { d_yield_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } }; /* creates a new bitmap object */ static void *makenew_jpeg(long *size) { BITMAP *bmp = create_bitmap_ex(8, 32, 32); int buffer_size = 32 * 32 * 3; char *buffer = (char *)_al_malloc(buffer_size); clear_bitmap(bmp); #if ALLEGRO_VERSION*0x10000+ALLEGRO_SUB_VERSION*0x100+ALLEGRO_WIP_VERSION>=0x040104 textout_centre_ex(bmp, font, "JPG", 16, 12, 1, -1); #else text_mode(-1); textout_centre(bmp, font, "JPG", 16, 12, 1); #endif save_memory_jpg(buffer, &buffer_size, bmp, NULL); destroy_bitmap(bmp); *size = buffer_size; return buffer; } /* returns a bitmap description string */ static void get_jpeg_desc(AL_CONST DATAFILE *dat, char *s) { BITMAP *bmp = (BITMAP *)load_memory_jpg(dat->dat, dat->size, NULL); sprintf(s, "JPG image (%dx%d truecolor, %ld KB)", bmp->w, bmp->h, dat->size / 1024); destroy_bitmap(bmp); } /* exports a bitmap into an external file */ static int export_jpeg(AL_CONST DATAFILE *dat, AL_CONST char *filename) { PACKFILE *f = pack_fopen(filename, F_WRITE); if (f) { pack_fwrite(dat->dat, dat->size, f); pack_fclose(f); } return (errno == 0); } /* draws a bitmap onto the grabber object view window */ static void plot_jpeg(AL_CONST DATAFILE *dat, int x, int y) { BITMAP *b = load_memory_jpg(dat->dat, dat->size, NULL); int w = b->w; int h = b->h; fixed scale; if (w > SCREEN_W-x-8) { scale = itofix(SCREEN_W-x-8) / w; w = (w * scale) >> 16; h = (h * scale) >> 16; } if (h > SCREEN_H-y-40) { scale = itofix(SCREEN_H-y-40) / h; w = (w * scale) >> 16; h = (h * scale) >> 16; } rect(screen, x, y+32, x+w+1, y+32+h+1, gui_fg_color); if (bitmap_color_depth(screen) == 8) { if ((w != b->w) || (h != b->h)) #if ALLEGRO_VERSION*0x10000+ALLEGRO_SUB_VERSION*0x100+ALLEGRO_WIP_VERSION>=0x040104 textout_ex(screen, font, "", x, y+18, gui_fg_color, -1); #else textout(screen, font, "", x, y+18, gui_fg_color); #endif else #if ALLEGRO_VERSION*0x10000+ALLEGRO_SUB_VERSION*0x100+ALLEGRO_WIP_VERSION>=0x040104 textout_ex(screen, font, "", x, y+18, gui_fg_color, -1); #else textout(screen, font, "", x, y+18, gui_fg_color); #endif } else if ((w != b->w) || (h != b->h)) #if ALLEGRO_VERSION*0x10000+ALLEGRO_SUB_VERSION*0x100+ALLEGRO_WIP_VERSION>=0x040104 textout_ex(screen, font, "", x, y+18, gui_fg_color, -1); #else textout(screen, font, "", x, y+18, gui_fg_color); #endif scare_mouse(); if ((w != b->w) || (h != b->h)) { if (bitmap_color_depth(b) != bitmap_color_depth(screen)) { PALETTE pal; generate_332_palette(pal); b = _fixup_loaded_bitmap(b, pal, bitmap_color_depth(screen)); } if (b) stretch_blit(b, screen, 0, 0, b->w, b->h, x+1, y+33, w, h); } else blit(b, screen, 0, 0, x+1, y+33, b->w, b->h); unscare_mouse(); destroy_bitmap(b); } /* handles double-clicking on a bitmap in the grabber */ static int view_jpeg(DATAFILE *dat) { BITMAP *b = load_memory_jpg(dat->dat, dat->size, NULL); fixed scale = itofix(1); fixed prevscale = itofix(1); int x = 0; int y = 0; int prevx = 0; int prevy = 0; BITMAP *bc = NULL; int done = FALSE; int c; show_mouse(NULL); clear_to_color(screen, gui_mg_color); blit(b, screen, 0, 0, 0, 0, b->w, b->h); clear_keybuf(); do { poll_mouse(); } while (mouse_b); do { if ((x != prevx) || (y != prevy) || (scale != prevscale)) { prevx = itofix(SCREEN_W) / scale; prevy = itofix(SCREEN_H) / scale; if ((b->w >= prevx) && (x+prevx > b->w)) x = b->w-prevx; else if ((b->w < prevx) && (x > 0)) x = 0; if ((b->h >= prevy) && (y+prevy > b->h)) y = b->h-prevy; else if ((b->h < prevy) && (y > 0)) y = 0; if (x < 0) x = 0; if (y < 0) y = 0; if (scale != prevscale) clear_to_color(screen, gui_mg_color); if (!bc) { bc = create_bitmap(b->w, b->h); blit(b, bc, 0, 0, 0, 0, b->w, b->h); } stretch_blit(bc, screen, x, y, b->w-x, b->h-y, 0, 0, ((b->w-x)*scale)>>16, ((b->h-y)*scale)>>16); prevx = x; prevy = y; prevscale = scale; } while (keypressed()) { c = readkey(); switch (c >> 8) { case KEY_DOWN: y += 4; break; case KEY_RIGHT: x += 4; break; case KEY_UP: y -= 4; break; case KEY_LEFT: x -= 4; break; case KEY_HOME: x = 0; y = 0; break; case KEY_END: x = 65536; y = 65536; break; case KEY_PGUP: if (scale > itofix(1)/16) scale /= 2; break; case KEY_PGDN: if (scale < itofix(16)) scale *= 2; break; default: switch (c & 0xFF) { case '+': if (scale < itofix(16)) scale *= 2; break; case '-': if (scale > itofix(1)/16) scale /= 2; break; default: done = TRUE; break; } break; } } poll_mouse(); if (mouse_b) done = TRUE; } while (!done); if (bc) destroy_bitmap(bc); destroy_bitmap(b); clear_keybuf(); do { poll_mouse(); } while (mouse_b); clear_bitmap(screen); show_mouse(screen); return D_REDRAW; } /* reads a bitmap from an external file */ #if ALLEGRO_VERSION*0x10000+ALLEGRO_SUB_VERSION*0x100+ALLEGRO_WIP_VERSION>=0x04010d static DATAFILE *grab_jpeg(int type, AL_CONST char *filename, DATAFILE_PROPERTY **prop, int depth) { int x = datedit_numprop(prop, DAT_XPOS); int y = datedit_numprop(prop, DAT_YPOS); int w = datedit_numprop(prop, DAT_XSIZ); int h = datedit_numprop(prop, DAT_YSIZ); #else static void *grab_jpeg(AL_CONST char *filename, long *size, int x, int y, int w, int h, int depth) { #endif PACKFILE *f = NULL; BITMAP *bmp; char *buffer; int buffer_size; int quality, flags = 0; if (depth > 0) { int oldcolordepth = _color_depth; _color_depth = depth; set_color_conversion(COLORCONV_TOTAL); bmp = load_bitmap(filename, datedit_last_read_pal); _color_depth = oldcolordepth; set_color_conversion(COLORCONV_NONE); } else bmp = load_bitmap(filename, datedit_last_read_pal); if (!bmp) { bmp = load_jpg(filename, datedit_last_read_pal); if (!bmp) return NULL; if ((x < 0) || (y < 0) || (w < 0) || (h < 0)) { buffer_size = file_size_ex(filename); buffer = (char *)_al_malloc(buffer_size); if (!buffer) { destroy_bitmap(bmp); return NULL; } f = pack_fopen(filename, F_READ); pack_fread(buffer, buffer_size, f); pack_fclose(f); destroy_bitmap(bmp); #if ALLEGRO_VERSION*0x10000+ALLEGRO_SUB_VERSION*0x100+ALLEGRO_WIP_VERSION>=0x04010d return datedit_construct(type, buffer, buffer_size, prop); #else *size = buffer_size; return buffer; #endif } } if ((x >= 0) && (y >= 0) && (w >= 0) && (h >= 0)) { BITMAP *b2 = create_bitmap_ex(bitmap_color_depth(bmp), w, h); clear_to_color(b2, bitmap_mask_color(b2)); blit(bmp, b2, x, y, 0, 0, w, h); destroy_bitmap(bmp); bmp = b2; } buffer_size = (bmp->w * bmp->h * 3) + 1024; buffer = (char *)_al_malloc(buffer_size); if (!buffer) { destroy_bitmap(bmp); return NULL; } quality = settings_dialog[3].d2 + 1; if (settings_dialog[4].flags & D_SELECTED) flags = JPG_SAMPLING_444; if (settings_dialog[5].flags & D_SELECTED) flags = JPG_SAMPLING_422; if (settings_dialog[6].flags & D_SELECTED) flags = JPG_SAMPLING_411; if (settings_dialog[7].flags & D_SELECTED) flags |= JPG_GREYSCALE; if (settings_dialog[8].flags & D_SELECTED) flags |= JPG_OPTIMIZE; if (save_memory_jpg_ex(buffer, &buffer_size, bmp, datedit_last_read_pal, quality, flags, NULL)) { free(buffer); destroy_bitmap(bmp); return NULL; } destroy_bitmap(bmp); #if ALLEGRO_VERSION*0x10000+ALLEGRO_SUB_VERSION*0x100+ALLEGRO_WIP_VERSION>=0x04010d return datedit_construct(type, buffer, buffer_size, prop); #else *size = buffer_size; return buffer; #endif } /* saves a bitmap into the datafile format */ #if ALLEGRO_VERSION*0x10000+ALLEGRO_SUB_VERSION*0x100+ALLEGRO_WIP_VERSION>=0x040104 static int save_datafile_jpeg(DATAFILE *dat, AL_CONST int *fixed_prop, int packed, int packkids, int strip, int sort, int verbose, int extra, PACKFILE *f) #else static void save_datafile_jpeg(DATAFILE *dat, int packed, int packkids, int strip, int verbose, int extra, PACKFILE *f) #endif { pack_fwrite(dat->dat, dat->size, f); #if ALLEGRO_VERSION*0x10000+ALLEGRO_SUB_VERSION*0x100+ALLEGRO_WIP_VERSION>=0x040104 return TRUE; #else return; #endif } static int quality_cb(void *dp3, int d2) { int quality = d2 + 1; sprintf(quality_string, "Quality: %d (%s) ", quality, quality < 20 ? "very low" : (quality < 50 ? "low" : (quality < 80 ? "medium" : (quality < 95 ? "high" : "very high")))); object_message(&settings_dialog[2], MSG_DRAW, 0); return D_O_K; } static int jpeg_settings_proc(void) { set_dialog_color(settings_dialog, gui_fg_color, gui_bg_color); centre_dialog(settings_dialog); popup_dialog(settings_dialog, -1); return D_REDRAW; } static MENU jpeg_settings_menu = { "JPG import settings", jpeg_settings_proc, NULL, 0, 0 }; /* plugin interface header */ DATEDIT_OBJECT_INFO datjpeg_info = { DAT_JPEG, "JPG image", get_jpeg_desc, makenew_jpeg, save_datafile_jpeg, plot_jpeg, view_jpeg, NULL }; DATEDIT_GRABBER_INFO datjpeg_grabber = { DAT_JPEG, "jpg;jpeg;bmp;lbm;pcx;tga", "jpg;jpeg", grab_jpeg, export_jpeg, NULL }; DATEDIT_MENU_INFO datjpeg_menu = { &jpeg_settings_menu, NULL, DATEDIT_MENU_FILE, 0, NULL }; allegro4.4-4.4.2/addons/jpgalleg/plugin/datjpeg.inc000066400000000000000000000005141173507505700220520ustar00rootroot00000000000000/* registration code for setting up the JPEG image plugin */ { extern DATEDIT_OBJECT_INFO datjpeg_info; extern DATEDIT_GRABBER_INFO datjpeg_grabber; extern DATEDIT_MENU_INFO datjpeg_menu; datedit_register_object(&datjpeg_info); datedit_register_grabber(&datjpeg_grabber); datedit_register_menu(&datjpeg_menu); } allegro4.4-4.4.2/addons/jpgalleg/plugin/jpgalleg.scm000066400000000000000000000000071173507505700222270ustar00rootroot00000000000000-ljpgalallegro4.4-4.4.2/addons/jpgalleg/plugin/jpgalleg.scr000066400000000000000000000000071173507505700222340ustar00rootroot00000000000000-ljpgalallegro4.4-4.4.2/addons/jpgalleg/plugin/jpgalleg.scu000066400000000000000000000000071173507505700222370ustar00rootroot00000000000000-ljpgalallegro4.4-4.4.2/addons/jpgalleg/plugin/jpgalleg.scv000066400000000000000000000000141173507505700222360ustar00rootroot00000000000000libjpgal.liballegro4.4-4.4.2/addons/jpgalleg/readme.txt000066400000000000000000000677061173507505700204610ustar00rootroot00000000000000 __ _____ ______ ______ ___ ___ /\ \ /\ _ `\ /\ ___\ /\ _ \ /\_ \ /\_ \ \ \ \\ \ \L\ \\ \ \__/ \ \ \L\ \\//\ \ \//\ \ __ __ __ \ \ \\ \ __| \ \ \ __\ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\ /\ \_\/ / \ \ \/ \ \ \L\ \\ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \____// \ \_\ \ \____/ \ \_\ \_\/\____\/\____\ \____\ \____ \ \/____/ \/_/ \/___/ \/_/\/_/\/____/\/____/\/____/\/___L\ \ /\____/ \_/__/ Version 2.6, by Angelo Mottola, 2000-2006 (build system modified by Allegro development team) Thanks for downloading JPGalleg! This add-on for Allegro will allow you to load/save JPG images using standard Allegro image handling functions. Its main advantages are: * Supports baseline and progressive JPG decoding, and baseline JPG encoding. This should ensure it'll load almost any JPG image you'll throw at it * Full Allegro integration: use load_bitmap() to load JPGs as if they were BMPs or other Allegro supported image formats * Fast encoding/decoding * Allegro datafile support: store JPGs in datafiles using the Grabber (plugin included), then load your datafiles from your programs and use JPG objects as if they were normal BITMAPs * Encoding/decoding work on both files and memory data * Small footprint: compiled library weights only 40K and is self-contained, in that it doesn't depend on external libraries other than Allegro It does not support arithmetic coding, but this shouldn't be a problem at all as most JPG don't use it as it's a patented type of encoding. Standard baseline and progressive formats are fully supported; if you fail to load a particular JPG image, please let me know! JPGalleg needs Allegro 4.0 or newer to run, and should work on any platform supported by Allegro, even if it has only been successfully tested under Windows (MinGW32), Linux and MacOS X. Install instructions -------------------- JPGalleg is shipped in source code form, so you need to compile it first in order to use it. Supported compilers are DJGPP (DOS), MinGW32 (Windows), MS Visual C++ (6.0 or newer) and gcc (Linux, BeOS, MacOS X). If you're willing to use Visual C++, you need GNU gcc and GNU make in order to install; you can grab a working copy of these for Win32 from the downloads section of the MinGW32 project site: http://www.mingw.org To install, the steps to follow are almost the same under all platforms: If you're under DOS/Windows: fix.bat If you're under an Unix variant: ./fix.sh Where must be one of "djgpp", "mingw32", "msvc", "unix", "beos" or "macosx". This will configure JPGalleg to be compiled for the selected environment. Next you just have to start the build process: make Under platforms that supports it, this will assume a dynamic version of Allegro to be installed on the system; if you have a static Allegro, you need to use: make STATICLINK=1 This will build a version of JPGalleg specifically made to be linked with the static version of Allegro. You can also build a special debugging version of the library instead, by issueing: make DEBUG=1 The debugging version will output lots of messages to stderr, and it could be useful when dealing with a JPG image JPGalleg fails to load. In any case, at the end of the build process you should get the compiled library (in lib/libjpgal.a or lib/libjpgal.lib if you built the normal library, in lib/libjpgad.a or lib/libjpgad.lib if you built the debug one; the same but with a "_s" suffix if you built with STATICLINK=1); you need to install it into your system so that your compiler will know where to look for it when you link against it (warning: this step requires root permissions under Unix and MacOS X): make install Congratulations! You have now successfully installed JPGalleg, and you are ready to use it in your own programs. See the next section "Using JPGalleg" for details. You may also want to install the JPGalleg Grabber plugin; this will let you manage JPG images easily from the Allegro Grabber utility, so you can store and use JPGs in datafiles. You need to have previously installed JPGalleg, and you also have to set the ALLEGRO environmental variable before being able to install the plugin; this variable must contain the full path to your local Allegro directory. If you don't have it set yet, proceed this way: If you're under DOS/Windows: set ALLEGRO=C:\ALLEGRO If you're under an Unix variant: export ALLEGRO=~/allegro supposing you previously installed Allegro C:\ALLEGRO (for DOS/Windows) or into ~/allegro (for Unix-like systems). Once you have the ALLEGRO environmental variable set, just type make plugin to install the plugin. This will rebuild the Grabber that will now support JPG images natively. For more info on the plugin, see section "Grabber plugin" below. Using JPGalleg -------------- JPGalleg is a library, and as such you need to link against it every time you want to use its functionalities. If you have successfully installed the package, the library libjpgal.a is already available for your compiler to use; you just have to specify the "-ljpgal" command line link option when linking your programs (on gcc based platforms); for example: gcc myprog.c -o myprog.exe -lalleg -ljpgal On MSVC, you need to add libjpgal.lib to the list of libraries linked to your project. You also need to include "jpgalleg.h" at the beginning of your source files, in order to use the library functions: #include See next section for a reference of the JPGalleg functions. Functions reference ------------------- int jpgalleg_init() Parameters: none Returns 0 on success, -1 on error. This function initializes the JPGalleg library, by registering the JPG file format with the Allegro image saving/loading and datafile subsystems. You don't really need to call this before calling any other library functions, but if you do, load_bitmap() and save_bitmap() will recognize files with the JPG extension, and datafiles holding JPEG objects will automatically decode them on datafile load, meaning you'll be able to work with them as if they were normal Allegro BITMAPs. Note that the invokation of this function automatically causes the static linkage of both the JPG encoder and decoder code to your executables; by not calling it you may loose full Allegro integration but you'd save EXE size if you only use one of either the encoder or the decoder of JPGalleg. Currently this function always returns 0. ______________________________________________________________________________ const char *jpgalleg_error_string() Parameters: none Returns the latest error message string. This utility function returns a string briefly describing the latest error occured during the encoding/decoding process, if any. See the "Error codes" section for more details. ______________________________________________________________________________ BITMAP *load_jpg(AL_CONST char *filename, RGB *palette) Parameters: filename Name of the JPG file to be loaded palette PALETTE structure that will hold the JPG palette Returns the loaded image into a BITMAP structure, or NULL on error. Similar to the other Allegro image loading functions, this is a shortcut version of load_jpg_ex(), specifying no progress callback. ______________________________________________________________________________ BITMAP *load_jpg_ex(AL_CONST char *filename, RGB palette, void (*callback)(int progress)) Parameters: filename Name of the JPG file to be loaded palette PALETTE structure that will hold the JPG palette callback Progress callback (see below) Returns the loaded image into a BITMAP structure, or NULL on error. load_jpg() loads a JPG image from a file and returns it in a BITMAP; it is similar to the other Allegro image loading functions. The returned bitmap will be 24 or 8 bit, depending on if the loaded JPG stores a truecolor or a greyscale image. Allegro color conversion rules apply here, so pay attention as if the COLORCONV_TOTAL flag is set (as is by default), the image will be automatically converted to the current color depth before being given to the user (see Allegro documentation of function set_color_conversion() for details). If image is in greyscale, `palette' will be filled with a greyscale palette, otherwise the generate_optimized_palette() or generate_332_palette() Allegro functions will be used to build it depending on if the current gfx mode is 8 bit or not. You can also specify NULL in this parameter, in which case no palette is returned. The callback parameter can be used to specify a callback function to be used as progress indicator. The function must return void and accept only one parameter, an integer, that will range 0-100 specifying the percentage of progress achieved at call time. Pay attention since the number of times this callback gets called varies; it can be called up to several hundreds times, and thus receive the same percentage value for more than one call. On error, this function returns NULL and sets the jpgalleg_error global variable to the proper error code (see the "Error codes" section). ______________________________________________________________________________ BITMAP *load_memory_jpg(void *buffer, int size, RGB *palette) Parameters: buffer Pointer to a block of memory that holds the JPG data size Size of the memory block palette PALETTE structure that will hold the JPG palette Returns the loaded image into a BITMAP structure, or NULL on error. This function is a shortcut version of load_memory_jpg_ex(), specifying no progress callback. ______________________________________________________________________________ BITMAP *load_memory_jpg_ex(void *buffer, int size, RGB *palette, void (*callback)(int progress)) Parameters: buffer Pointer to a block of memory that holds the JPG data size Size of the memory block palette PALETTE structure that will hold the JPG palette callback Progress callback (see load_jpg_ex()) Returns the loaded image into a BITMAP structure, or NULL on error. This function behaves exactly as load_jpg(), but tries to decode a JPG image held into a memory block. The memory block size is needed to ensure the JPG data integrity. ______________________________________________________________________________ int save_jpg(AL_CONST char *filename, BITMAP *image, AL_CONST RGB *palette) Parameters: filename Name of the file that will hold the JPG image image The BITMAP structure holding the image data to save palette PALETTE structure holding the image palette Returns 0 on success, -1 on error. Similar to the other Allegro image saving functions, this is a shortcut version of save_jpg_ex(), saving the image with a default quality of 75, no subsampling, no optimization and no progress callback. ______________________________________________________________________________ int save_jpg_ex(AL_CONST char *filename, BITMAP *image, AL_CONST RGB *palette, int quality, int flags, void (*callback)(int progress)) Parameters: filename Name of the file that will hold the JPG image image The BITMAP structure holding the image data to save palette PALETTE structure holding the image palette quality JPG encoding quality, in the range 1-100 flags Miscellaneous encoding flags (see below) callback Progress callback (see load_jpg_ex()) Returns 0 on success, -1 on error. Saves an image held in an Allegro BITMAP structure into a JPG file, using baseline encoding. The image can be any color depth, but the saved JPG will always be a 24 bit truecolor image (or 8 bit if saving in greyscale). Quality ranges from 1 (very low) to 100 (very high) (other values are clamped in this range); a value of 90 already gives an image that is hardly distinguishable from the original one. Obviously higher quality means bigger file size. JPGalleg supports chrominance subsampling; that is, while luminance (which specify the brightness of each pixel) is always sampled once for every image pixel, chrominance (which is used to specify the chromatic components of each pixel) can be sampled from every image pixel (no subsampling, also named mode 444), only on even pixels horizontally (mode 422), or only on even pixels both horizontally and vertically (mode 411). The mode name already tells you the subsampling type: for example 422 means that for 4 luminance samples, only 2 chrominance samples are taken. Subsampling helps reducing the final JPG file size and is hardly noticeable by the human eye, expecially if you use high qualities. A good compromise in quality/size settings is for example a quality of 90 and a subsampling mode 411. You specify the subsampling mode in the `flags' parameter to this function, by setting one of the following constants (defined in jpgalleg.h): JPG_SAMPLING_444 For mode 444 (no subsampling) JPG_SAMPLING_422 For mode 422 (horizontal subsampling) JPG_SAMPLING_411 For mode 411 (horizontal and vertical subsampling) The flags parameter can accept more options, chained together by a bitwise OR. If you pass the JPG_GREYSCALE constant, the image will be saved in greyscale mode; only the luminance component of the image will be saved, therefore any specified subsampling of the chrominance is ignored. Passing JPG_OPTIMIZE to the flags parameter will activate optimized encoding; the routine will take twice the time to complete, but the saved file size will be reduced by an average 10% compared to unoptimized mode. The final function parameter can be used to specify a callback for progress indication, and works the same as seen in load_jpg_ex(). This function returns 0 on success, or -1 on error. If an error occured, you can get more details on it by checking the jpgalleg_error global variable. See the "Error codes" section for more details. ______________________________________________________________________________ int save_memory_jpg(void *buffer, int *size, BITMAP *image, AL_CONST RGB *palette) Parameters: buffer Pointer to a memory buffer that will hold the JPG data size Size of the memory buffer (see save_memory_jpg_ex()) image The BITMAP structure holding the image data to save palette PALETTE structure holding the image palette Returns 0 on success, -1 on error. This is a shortcut version of save_memory_jpg_ex(), saving the image with a default quality of 75, no subsampling, no optimization and no progress callback. ______________________________________________________________________________ int save_memory_jpg_ex(void *buffer, int *size, BITMAP *image, AL_CONST RGB *palette, int quality, int flags, void (*callback)(int progress)) Parameters: buffer Pointer to a memory buffer that will hold the JPG data size Size of the memory buffer (see below) image The BITMAP structure holding the image data to save palette PALETTE structure holding the image palette quality JPG encoding quality, in the range 1-100 flags Miscellaneous encoding flags (see save_jpg_ex()) callback Progress callback (see load_jpg_ex()) Returns 0 on success, -1 on error. This is the same as save_jpg_ex(), but encodes the image in a memory block rather than into a file. The `size' parameter has a double function: on input, you must set it to the size of the memory buffer that will hold the encoded JPG data (this ensures the function will fail if the buffer is too small to hold the encoded JPG), on output it'll hold the final size of the encoded JPG data in bytes. ______________________________________________________________________________ Error codes ----------- All the JPGalleg functions set the jpgalleg_error global variable to a proper error code on error, so if a function fails, you can check this variable for more details on what went wrong. If you want a more human-readable error message, the jpgalleg_error_string() function can be helpful, returning a string briefly describing the last error occured. Here's the list of possible numerical error codes (defined in jpgalleg.h): JPG_ERROR_NONE No error occured during last operation. JPG_ERROR_READING_FILE There was an I/O error reading from a file. JPG_ERROR_WRITING_FILE There was an I/O error writing to a file. JPG_ERROR_INPUT_BUFFER_TOO_SMALL The memory buffer holding the encoded JPG data is too small for the JPG itself. The JPG is truncated and can't be loaded. JPG_ERROR_OUTPUT_BUFFER_TOO_SMALL The buffer specified when saving a JPG image is too small to hold the encoded JPG data. JPG_ERROR_HUFFMAN An huffman encoding error has occured while saving a JPG. This should never happen and is considered an internal error, so if you ever get this error, please report it to me! JPG_ERROR_NOT_JPEG The file/data being loaded isn't recognized as a valid JPG image. JPG_ERROR_UNSUPPORTED_ENCODING The JPG file/data being loaded is encoded in a format not supported by JPGalleg. Currently the library can only load baseline and progressive encoded JPG images. JPG_ERROR_UNSUPPORTED_COLOR_SPACE JPGalleg supports only greyscale and luminance/chrominance JPG images. If the JPG being loaded isn't encoded in one of these color spaces, this error occurs. JPG_ERROR_UNSUPPORTED_DATA_PRECISION JPGalleg only supports 8 bit data precision. If the JPG being loaded is not encoded using this precision, this error occurs. JPG_ERROR_BAD_IMAGE The JPG file/data being loaded is corrupted. JPG_ERROR_OUT_OF_MEMORY JPGalleg ran out of memory while decoding a JPG image. Grabber plugin -------------- JPGalleg ships with a plugin for the Allegro Grabber utility. This allows the Grabber to easily handle JPG images into datafiles, so you can store your JPGs and later load the datafile and see them as normal Allegro BITMAPs. For informations on how to install the Grabber plugin, see section "Install instructions". Alternatively, you can copy the whole contents of the jpgalleg/plugin directory into your allegro/tools/plugins directory, and then recompile the grabber by calling make tools/grabber from your root Allegro directory. Be sure you already successfully installed JPGalleg before installing the plugin, otherwise the plugin will not compile! Once you have a JPG-enabled Grabber, you can create and grab new data objects of type "JPEG"; these will hold the compressed JPG data of your images. To create a new JPEG object, use New -> JPG image. A new temp 32x32 JPG image will be created and assigned to the new object, as if you created a normal bitmap object. You can now use the grab command on that object to load any Allegro supported image into it; obviously you can now grab JPG images, but you can also grab the other Allegro supported image formats, which will be converted to JPG before being assigned to the JPEG object. Conversion to JPG only occurs if the selected image isn't already in JPG format, and by default the conversion will use a quality of 75 and no subsampling. You can alter these settings at any time by using the dialog which appears when you select the menu item File -> JPG import settings. Beware though that the new settings will only apply on the next image conversions, not to images already imported. When you load a datafile holding JPEG type objects, these will automatically be decoded into normal BITMAP objects at datafile load time. This means that if you have stored a JPEG object named "MY_JPG_IMAGE" into a datafile, after you've loaded the datafile into `data', you'll be able to call: BITMAP *bmp = data[MY_JPG_IMAGE].dat; blit(bmp, screen, 0, 0, 0, 0, bmp->w, bmp->h); As if MY_JPG_IMAGE was a normal BITMAP (and infact it is, after you've loaded the datafile). A final hint: when storing JPGs into your datafiles, do not use compression, otherwise it is likely your datafile will be even bigger than the uncompressed version... Frequently Asked Questions -------------------------- Q) I get a "undefined reference to: 'register_datafile_object'" message when linking my program, while the examples shipped with the library compiled nicely. What's wrong? A) Try swapping the order with which you link Allegro and JPGalleg to your program. This should solve the problem. Q) My JPG image won't load! What can I do? A) That JPG is probably not a standard baseline or progressive encoded JPG. JPGalleg can't load arithmetic encoded JPGs; these are rare, but it could be your case. In order to load it, you first need to convert it to baseline or progressive format; most paint programs will support at least one of them. The encoding format is usually selected in the same dialog in which you set the JPG quality when saving. If your image is already a baseline or progressive JPG and it won't still load, please contact me and send me the image; I'll try to spot the bug and maybe fix it in the next JPGalleg release. Q) Why isn't arithmetic encoding supported? A) Arithmetic encoding uses a patented algorithm, so it is unlikely it'll ever be supported in a free library like JPGalleg. Q) Why JPGs saved by JPGalleg are bigger than (my paint program) generated JPGs? A) Saving a JPG is a complex task, and the compression relies on several factors. The quality factor as an example, is implementation dependent, and is therefore different from the one used by other programs; a JPGalleg quality of 90 may correspond to a completely different quality elsewhere. You should also check subsampling: activating it will help reducing final file size a lot. And you can also use the JPG_OPTIMIZE flag to generate optimized huffman encoding tables that will help reducing size by another average 10%. Q) Why can't I save JPGs using progressive encoding? A) In order to be compact, JPGalleg only supports saving in baseline encoding. Adding support for saving in progressive mode too would add weight to the lib, and IMHO it's not really worth it, and behind the scope of this library. Versions history ---------------- Version 2.6 (May 2006) * Added more JFIF variants compatibility * Fixed 1-byte memory leak in the decoder * Made compatible with Allegro 4.2.x * Refactored source code to avoid linking decoder or encoder functions when one of these is not used by the user application * Introduced a new jpgalleg_error_string() function to return the last error message in string form * Small makefile fixes * Added Pyjpgalleg 1.0 in the contrib directory, a Python wrapper library for JPGalleg by Grzegorz Adam Hankiewicz Version 2.5 (July 2004) * Now directly works on and returns a 24 bit image when dealing with truecolor JPGs, instead of using an intermediate 32 bpp buffer * New faster YCbCr <--> RGB MMX routines * Refactored I/O subsystem, now always works in memory internally * Optimized bit stream fetching resulting in big performance bump * Reduced memory footprint * Fixed a possible memory leak in the decoder Version 2.4 (June 2004) * Changed the decoder IDCT algorithm to AAN, ensuring faster decoding * Added an experimental MMX IDCT routine * Small optimizations on other parts of the decoder * Fixed a bug in the decoder not recognizing some EXIF images * Tightened a bit the encoder code * Reworked build system to use different target directories on different platforms * Added a small benchmark utility Version 2.3 (March 2004) * Fixed output colors bug when decoding JPGs while in 32 bits mode * Small optimization to the decoder * Refactored encoder code, enhanced compactness * Added progress callback functionality to both decoder and encoder * Enhanced errors reporting * Reworked encoder quantization resulting in big output size reduction at the same quality; also changed the quality curve formula * Made ex5 to report expected size of file when saving JPGs and to show progress when loading/saving * Added a license Version 2.2 (February 2004) * Updated codebase to be compatible with latest Allegro WIPs * Added debug capabilities to the lib * Added optimized huffman tables generation to encoder * Added support for loading JPGs with a 422 subsampling mode with an 8x16 MCU (previously supported only 16x8) * Can now load EXIF JPG images * Now loaded images are either 8 (greyscale) or 24 (truecolor) bit, rather than always 32 bit * Fixed loading of JPGs with a restart interval of 0 * Fixed little endianess related issues * Reworked make system, added MS Visual C++ and MacOS X support, added a "plugin" target * Replaced example images with smaller ones * Fixed some small bugs in the grabber plugin Version 2.1 (May 2003) * Small bugfixes to the library and the Grabber plugin * Optimized the decoder * Now supports progressive JPG decoding * The encoder has a new better quality curve formula * Updated the docs and added a FAQ Version 2.0 (April 2003) * Complete rewrite of the library * Faster, more baseline JPG compliant decoder * Added a baseline JPG encoder * Uses dedicated MMX routines for YCbCr <--> RGB color space conversion when available * Proper Allegro datafile support: decodes JPG objects on datafile load * Added a Grabber plugin * New examples * Uses a dedicated makefile for each supported platform * Now compiles as a standalone library Version 1.2 (March 2002) * Faster decoding by using fixed point math in the YCbCR -> RGB color space conversion. * Fixed compatibility with C++ * Modified makefile to support multiple platforms. Version 1.1 (June 2000) * Added support for loading JPGs from memory * New examples with better test images. Version 1.0 (May 2000) * First public release, supports baseline decoding from JPG files. Contact informations -------------------- Got some questions about JPGalleg? Do you want to provide some feedback in general? Feel free to contact me at the following email address: a.mottola@gmail.com Also, be sure to check for updates to JPGalleg at the official project page: http://www.ecplusplus.com/jpgalleg Thanks ------ * Shawn Hargreaves and the many others who contributed to the excellent Allegro library; keep on rockin'! * The Independent JPEG Group: the fast DCT algorithm used here comes from their great jpeg codec package. * Cristi Cuturicu for his JPEG compression and file format FAQ. Without your document, my work would have never been possible. * David Wang and Vincent Penecherch for the patches for supporting 64bit CPUs and for Allegro 4.2.x compatibility respectively. * Grzegorz Adam Hankiewicz for Pyjpgalleg, a nice Python wrapper for JPGalleg. allegro4.4-4.4.2/addons/jpgalleg/src/000077500000000000000000000000001173507505700172325ustar00rootroot00000000000000allegro4.4-4.4.2/addons/jpgalleg/src/decode.c000066400000000000000000001253661173507505700206360ustar00rootroot00000000000000/* * __ _____ ______ ______ ___ ___ * /\ \ /\ _ `\ /\ ___\ /\ _ \ /\_ \ /\_ \ * \ \ \\ \ \L\ \\ \ \__/ \ \ \L\ \\//\ \ \//\ \ __ __ * __ \ \ \\ \ __| \ \ \ __\ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\ * /\ \_\/ / \ \ \/ \ \ \L\ \\ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ * \ \____// \ \_\ \ \____/ \ \_\ \_\/\____\/\____\ \____\ \____ \ * \/____/ \/_/ \/___/ \/_/\/_/\/____/\/____/\/____/\/___L\ \ * /\____/ * \_/__/ * * Version 2.6, by Angelo Mottola, 2000-2006 * * Decoder core module. * * See the readme.txt file for instructions on using this package in your * own programs. */ #include static HUFFMAN_TABLE *ac_luminance_table, *dc_luminance_table; static HUFFMAN_TABLE *ac_chrominance_table, *dc_chrominance_table; static DATA_BUFFER *data_buffer[3]; static short quantization_table[256]; static short *luminance_quantization_table, *chrominance_quantization_table; static int jpeg_w, jpeg_h, jpeg_components; static int sampling, v_sampling, h_sampling, restart_interval, skip_count; static int spectrum_start, spectrum_end, successive_high, successive_low; static int scan_components, component[3]; static int progress_counter, progress_total; static void (*idct)(short *block, short *dequant, short *output, short *workspace); static void (*ycbcr2rgb)(intptr_t address, int y1, int cb1, int cr1, int y2, int cb2, int cr2, int y3, int cb3, int cr3, int y4, int cb4, int cr4); static void (*plot)(intptr_t addr, int pitch, short *y1, short *y2, short *y3, short *y4, short *cb, short *cr); static void (*progress_cb)(int percentage); /* _jpeg_c_idct: * Applies the inverse discrete cosine transform to the given input data, * in the form of a vector of 64 coefficients. * This uses integer fixed point math and is based on code by the IJG. */ static void _jpeg_c_idct(short *data, short *output, short *dequant, short *workspace) { int tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; int tmp10, tmp11, tmp12, tmp13; int z5, z10, z11, z12, z13; short *inptr, *dqptr, *outptr; int *wsptr; int i, temp; inptr = data; dqptr = dequant; wsptr = (int *)workspace; for (i = 8; i; i--) { if ((inptr[8] | inptr[16] | inptr[24] | inptr[32] | inptr[40] | inptr[48] | inptr[56]) == 0) { temp = inptr[0] * dqptr[0]; wsptr[0] = temp; wsptr[8] = temp; wsptr[16] = temp; wsptr[24] = temp; wsptr[32] = temp; wsptr[40] = temp; wsptr[48] = temp; wsptr[56] = temp; inptr++; dqptr++; wsptr++; continue; } tmp0 = inptr[0] * dqptr[0]; tmp1 = inptr[16] * dqptr[16]; tmp2 = inptr[32] * dqptr[32]; tmp3 = inptr[48] * dqptr[48]; tmp10 = tmp0 + tmp2; tmp11 = tmp0 - tmp2; tmp13 = tmp1 + tmp3; tmp12 = (((tmp1 - tmp3) * IFIX_1_414213562) >> 8) - tmp13; tmp0 = tmp10 + tmp13; tmp3 = tmp10 - tmp13; tmp1 = tmp11 + tmp12; tmp2 = tmp11 - tmp12; tmp4 = inptr[8] * dqptr[8]; tmp5 = inptr[24] * dqptr[24]; tmp6 = inptr[40] * dqptr[40]; tmp7 = inptr[56] * dqptr[56]; z13 = tmp6 + tmp5; z10 = tmp6 - tmp5; z11 = tmp4 + tmp7; z12 = tmp4 - tmp7; tmp7 = z11 + z13; tmp11 = ((z11 - z13) * IFIX_1_414213562) >> 8; z5 = ((z10 + z12) * IFIX_1_847759065) >> 8; tmp10 = ((z12 * IFIX_1_082392200) >> 8) - z5; tmp12 = ((z10 * -IFIX_2_613125930) >> 8) + z5; tmp6 = tmp12 - tmp7; tmp5 = tmp11 - tmp6; tmp4 = tmp10 + tmp5; wsptr[0] = tmp0 + tmp7; wsptr[56] = tmp0 - tmp7; wsptr[8] = tmp1 + tmp6; wsptr[48] = tmp1 - tmp6; wsptr[16] = tmp2 + tmp5; wsptr[40] = tmp2 - tmp5; wsptr[32] = tmp3 + tmp4; wsptr[24] = tmp3 - tmp4; inptr++; dqptr++; wsptr++; } wsptr = (int *)workspace; outptr = output; for (i = 8; i; i--) { tmp10 = wsptr[0] + wsptr[4]; tmp11 = wsptr[0] - wsptr[4]; tmp13 = wsptr[2] + wsptr[6]; tmp12 = (((wsptr[2] - wsptr[6]) * IFIX_1_414213562) >> 8) - tmp13; tmp0 = tmp10 + tmp13; tmp3 = tmp10 - tmp13; tmp1 = tmp11 + tmp12; tmp2 = tmp11 - tmp12; z13 = wsptr[5] + wsptr[3]; z10 = wsptr[5] - wsptr[3]; z11 = wsptr[1] + wsptr[7]; z12 = wsptr[1] - wsptr[7]; tmp7 = z11 + z13; tmp11 = ((z11 - z13) * IFIX_1_414213562) >> 8; z5 = ((z10 + z12) * IFIX_1_847759065) >> 8; tmp10 = ((z12 * IFIX_1_082392200) >> 8) - z5; tmp12 = ((z10 * -IFIX_2_613125930) >> 8) + z5; tmp6 = tmp12 - tmp7; tmp5 = tmp11 - tmp6; tmp4 = tmp10 + tmp5; outptr[0] = ((tmp0 + tmp7) >> 5) + 128; outptr[7] = ((tmp0 - tmp7) >> 5) + 128; outptr[1] = ((tmp1 + tmp6) >> 5) + 128; outptr[6] = ((tmp1 - tmp6) >> 5) + 128; outptr[2] = ((tmp2 + tmp5) >> 5) + 128; outptr[5] = ((tmp2 - tmp5) >> 5) + 128; outptr[4] = ((tmp3 + tmp4) >> 5) + 128; outptr[3] = ((tmp3 - tmp4) >> 5) + 128; wsptr += 8; outptr += 8; } } /* zigzag_reorder: * Reorders a vector of 64 coefficients by the zigzag scan. */ static INLINE void zigzag_reorder(short *input, short *output) { int i; for (i = 0; i < 64; i++) output[i] = input[_jpeg_zigzag_scan[i]]; } /* free_huffman_table: * Frees memory used by the huffman decoding lookup tables. */ static void free_huffman_table(HUFFMAN_TABLE *table) { int i; for (i = 0; i < 16; i++) { if (table->entry_of_length[i]) free(table->entry_of_length[i]); table->entry_of_length[i] = NULL; } } /* read_dht_chunk: * Reads a DHT (Define Huffman Table) chunk from the input stream. */ static int read_dht_chunk(void) { int i, j, table_id, num_codes[16]; int code, value; unsigned char data; HUFFMAN_TABLE *table; HUFFMAN_ENTRY *entry; _jpeg_open_chunk(); do { data = _jpeg_getc(); if (data & 0xe0) { TRACE("Invalid DHT information byte"); jpgalleg_error = JPG_ERROR_BAD_IMAGE; return -1; } table_id = data & 0xf; if (table_id > 3) { TRACE("Invalid huffman table number"); jpgalleg_error = JPG_ERROR_BAD_IMAGE; return -1; } if (data & 0x10) table = &_jpeg_huffman_ac_table[table_id]; else table = &_jpeg_huffman_dc_table[table_id]; for (i = 0; i < 16; i++) num_codes[i] = _jpeg_getc(); code = 0; for (i = 0; i < 16; i++) { if (table->entry_of_length[i]) free(table->entry_of_length[i]); table->entry_of_length[i] = (HUFFMAN_ENTRY *)calloc(1 << (i + 1), sizeof(HUFFMAN_ENTRY)); if (!table->entry_of_length[i]) { TRACE("Out of memory"); jpgalleg_error = JPG_ERROR_OUT_OF_MEMORY; return -1; } for (j = 0; j < num_codes[i]; j++) { value = _jpeg_getc(); entry = &table->entry_of_length[i][code]; entry->value = value; entry->encoded_value = code; entry->bits_length = i + 1; code++; } code <<= 1; } } while (!_jpeg_eoc()); _jpeg_close_chunk(); return 0; } /* read_sof0_chunk: * Reads a SOF0 (Start Of Frame 0) chunk from the input stream. */ static int read_sof0_chunk(void) { int i, data; _jpeg_open_chunk(); if ((data = _jpeg_getc()) != 8) { TRACE("Unsupported data precision (%d)", data); jpgalleg_error = JPG_ERROR_UNSUPPORTED_DATA_PRECISION; return -1; } jpeg_h = _jpeg_getw(); jpeg_w = _jpeg_getw(); jpeg_components = _jpeg_getc(); if ((jpeg_components != 1) && (jpeg_components != 3)) { TRACE("Unsupported number of components (%d)", jpeg_components); jpgalleg_error = JPG_ERROR_UNSUPPORTED_COLOR_SPACE; return -1; } for (i = 0; i < jpeg_components; i++) { switch (_jpeg_getc()) { case 1: data = _jpeg_getc(); h_sampling = data >> 4; v_sampling = data & 0xf; sampling = h_sampling * v_sampling; if ((sampling != 1) && (sampling != 2) && (sampling != 4)) { TRACE("Bad sampling byte (%d)", sampling); jpgalleg_error = JPG_ERROR_BAD_IMAGE; return -1; } data = _jpeg_getc(); if (data > 3) { TRACE("Bad quantization table number (%d)", data); jpgalleg_error = JPG_ERROR_BAD_IMAGE; return -1; } luminance_quantization_table = &quantization_table[data * 64]; break; case 2: case 3: _jpeg_getc(); data = _jpeg_getc(); if (data > 3) { TRACE("Bad quantization table number (%d)", data); jpgalleg_error = JPG_ERROR_BAD_IMAGE; return -1; } chrominance_quantization_table = &quantization_table[data * 64]; break; } } _jpeg_close_chunk(); return 0; } /* read_dqt_chunk: * Reads a DQT (Define Quantization Table) chunk from the input stream. */ static int read_dqt_chunk(void) { int i, data; short *table, temp[64]; float value; _jpeg_open_chunk(); do { data = _jpeg_getc(); if ((data & 0xf) > 3) { TRACE("Bad quantization table number (%d)", data); jpgalleg_error = JPG_ERROR_BAD_IMAGE; return -1; } if (data & 0xf0) { TRACE("Unsupported quantization table data precision"); jpgalleg_error = JPG_ERROR_UNSUPPORTED_DATA_PRECISION; return -1; } table = &quantization_table[(data & 0xf) * 64]; for (i = 0; i < 64; i++) temp[i] = _jpeg_getc(); zigzag_reorder(temp, table); for (i = 0; i < 64; i++) { value = (float)table[i] * AAN_FACTOR(i) * 16384.0; table[i] = ((int)value + (1 << 11)) >> 12; } } while (!_jpeg_eoc()); _jpeg_close_chunk(); return 0; } /* read_sos_chunk: * Reads a SOS (Start Of Scan) chunk from the input stream. */ static int read_sos_chunk(void) { int i, data; _jpeg_open_chunk(); scan_components = _jpeg_getc(); if (scan_components > 3) { TRACE("Unsupported number of scan components (%d)", scan_components); jpgalleg_error = JPG_ERROR_UNSUPPORTED_COLOR_SPACE; return -1; } for (i = 0; i < scan_components; i++) { component[i] = _jpeg_getc(); switch (component[i]) { case 1: data = _jpeg_getc(); if (((data & 0xf) > 3) || ((data >> 4) > 3)) { TRACE("Bad huffman table specified for %s component", _jpeg_component_name[component[i] - 1]); jpgalleg_error = JPG_ERROR_BAD_IMAGE; return -1; } ac_luminance_table = &_jpeg_huffman_ac_table[data & 0xf]; dc_luminance_table = &_jpeg_huffman_dc_table[data >> 4]; break; case 2: case 3: data = _jpeg_getc(); if (((data & 0xf) > 3) || ((data >> 4) > 3)) { TRACE("Bad huffman table specified for %s component", _jpeg_component_name[component[i] - 1]); jpgalleg_error = JPG_ERROR_BAD_IMAGE; return -1; } ac_chrominance_table = &_jpeg_huffman_ac_table[data & 0xf]; dc_chrominance_table = &_jpeg_huffman_dc_table[data >> 4]; break; default: TRACE("Unsupported component id (%d)", component[i]); jpgalleg_error = JPG_ERROR_BAD_IMAGE; break; } } spectrum_start = _jpeg_getc(); spectrum_end = _jpeg_getc(); data = _jpeg_getc(); successive_high = data >> 4; successive_low = data & 0xf; _jpeg_close_chunk(); skip_count = 0; return 0; } /* read_appn_chunk: * Reads an APP0/APP1 (JFIF/EXIF descriptor) chunk from the input stream. */ static int read_appn_chunk(int n, int flags) { char header[6] = { 0 }; char *header_id; int i; if (n == CHUNK_APP0) header_id = "JFIF"; else header_id = "Exif"; _jpeg_open_chunk(); if ((n == CHUNK_APP1) || (!(flags & APP0_DEFINED))) { for (i = 0; i < 5; i++) { if ((header[i] = _jpeg_getc()) != header_id[i]) { TRACE("Bad %s header, found %s", (n == CHUNK_APP0) ? "JFIF" : "EXIF", header); _jpeg_close_chunk(); jpgalleg_error = JPG_ERROR_NOT_JPEG; return -1; } } if (n == CHUNK_APP0) { /* Only JFIF version 1.x is supported */ if (_jpeg_getc() != 1) { TRACE("Not a JFIF version 1.x file"); _jpeg_close_chunk(); return -1; } } } _jpeg_close_chunk(); return 0; } /* read_dri_chunk: * Reads a DRI (Define Restart Interval) chunk from the input stream. */ static int read_dri_chunk(void) { _jpeg_open_chunk(); restart_interval = _jpeg_getw(); _jpeg_close_chunk(); return 0; } /* get_bits: * Reads a string of bits from the input stream. */ static int get_bits(int num_bits) { int result = 0; while (_jpeg_io.current_bit < num_bits) { result = (result << _jpeg_io.current_bit) | (*_jpeg_io.buffer & ((1 << _jpeg_io.current_bit) - 1)); num_bits -= _jpeg_io.current_bit; _jpeg_io.current_bit = 8; if (*_jpeg_io.buffer == 0xff) _jpeg_io.buffer++; if (_jpeg_io.buffer >= _jpeg_io.buffer_end) { TRACE("Tried to read memory past buffer size"); jpgalleg_error = JPG_ERROR_INPUT_BUFFER_TOO_SMALL; return 0x80000000; } _jpeg_io.buffer++; } result = (result << num_bits) | ((*_jpeg_io.buffer >> (_jpeg_io.current_bit - num_bits)) & ((1 << num_bits) - 1)); _jpeg_io.current_bit -= num_bits; return result; } /* get_value: * Reads a string of bits from the input stream and returns a properly signed * number given the category. */ INLINE int get_value(int category) { int result = get_bits(category); if ((result >= (1 << (category - 1))) || (result < 0)) return result; else return result - ((1 << category) - 1); } /* huffman_decode: * Fetches bits from the input stream until a valid huffman code is found, * then returns the value associated with that code. */ static int huffman_decode(HUFFMAN_TABLE *table) { HUFFMAN_ENTRY *entry, **entry_lut; int i, value; unsigned char *p = _jpeg_io.buffer; value = (*p & ((1 << _jpeg_io.current_bit) - 1)) << (16 - _jpeg_io.current_bit); if (*p++ == 0xff) p++; if (p < _jpeg_io.buffer_end) { value |= *p << (8 - _jpeg_io.current_bit); if (*p++ == 0xff) p++; if (p < _jpeg_io.buffer_end) value |= *p >> _jpeg_io.current_bit; } entry_lut = table->entry_of_length; for (i = 15; i >= 0; i--) { entry = &((*entry_lut)[value >> i]); if (entry->bits_length == 16 - i) { _jpeg_io.current_bit -= 16 - i; while (_jpeg_io.current_bit <= 0) { _jpeg_io.current_bit += 8; if (*_jpeg_io.buffer == 0xff) _jpeg_io.buffer++; _jpeg_io.buffer++; } return entry->value; } entry_lut++; } return -1; } /* decode_baseline_block: * Decodes an 8x8 basic block of coefficients of given type (luminance or * chrominance) from the input stream. Used for baseline decoding. */ static int decode_baseline_block(short *block, int type, int *old_dc) { HUFFMAN_TABLE *dc_table, *ac_table; short *quant_table; int data, i, index; int num_zeroes, category; short workspace[130]; short pre_idct_block[80]; short ordered_pre_idct_block[64]; if (type == LUMINANCE) { dc_table = dc_luminance_table; ac_table = ac_luminance_table; quant_table = luminance_quantization_table; } else { dc_table = dc_chrominance_table; ac_table = ac_chrominance_table; quant_table = chrominance_quantization_table; } data = huffman_decode(dc_table); if (data < 0) { TRACE("Bad dc data"); jpgalleg_error = JPG_ERROR_BAD_IMAGE; return -1; } if ((data = get_value(data & 0xf)) == (int)0x80000000) return -1; *old_dc += data; pre_idct_block[0] = *old_dc; index = 1; do { data = huffman_decode(ac_table); if (data < 0) { /* Bad block */ TRACE("Bad ac data"); jpgalleg_error = JPG_ERROR_BAD_IMAGE; return -1; } num_zeroes = data >> 4; category = data & 0xf; if (category != 0) { /* Normal zero run length coding */ for (; num_zeroes; num_zeroes--) pre_idct_block[index++] = 0; if ((data = get_value(category)) == (int)0x80000000) return -1; pre_idct_block[index++] = data; } else { if (num_zeroes == 0) { /* End of block */ while (index < 64) pre_idct_block[index++] = 0; break; } else if (num_zeroes == 15) { /* 16 zeroes special case */ for (i = 16; i; i--) pre_idct_block[index++] = 0; } else { TRACE("Bad ac data"); jpgalleg_error = JPG_ERROR_BAD_IMAGE; return -1; } } } while (index < 64); zigzag_reorder(pre_idct_block, ordered_pre_idct_block); idct(ordered_pre_idct_block, block, quant_table, workspace); return 0; } /* decode_progressive_block * Decodes some coefficients for an 8x8 block from the input stream. Used in * progressive mode decoding. */ static int decode_progressive_block(intptr_t addr, int type, int *old_dc) { HUFFMAN_TABLE *dc_table, *ac_table; short *block = (short *)addr; int data, index, value; int num_zeroes, category; int p_bit, n_bit; if (type == LUMINANCE) { dc_table = dc_luminance_table; ac_table = ac_luminance_table; } else { dc_table = dc_chrominance_table; ac_table = ac_chrominance_table; } if (spectrum_start == 0) { /* DC scan */ if (successive_high == 0) { /* First DC scan */ data = huffman_decode(dc_table); if (data < 0) { TRACE("Bad dc data"); jpgalleg_error = JPG_ERROR_BAD_IMAGE; return -1; } if ((data = get_value(data & 0xf)) == (int)0x80000000) return -1; *old_dc += data; block[0] = *old_dc << successive_low; } else { /* DC successive approximation */ if ((data = _jpeg_get_bit()) < 0) { TRACE("Failed to get bit from input stream"); jpgalleg_error = JPG_ERROR_BAD_IMAGE; return -1; } if (data) block[0] |= (1 << successive_low); } } else { /* AC scan */ if (successive_high == 0) { /* First AC scan */ if (skip_count) { skip_count--; return 0; } index = spectrum_start; do { data = huffman_decode(ac_table); if (data < 0) { TRACE("Bad ac data (first scan)"); jpgalleg_error = JPG_ERROR_BAD_IMAGE; return -1; } num_zeroes = data >> 4; category = data & 0xf; if (category == 0) { if (num_zeroes == 15) index += 16; else { index++; skip_count = 0; if (num_zeroes) { value = get_bits(num_zeroes); if (value < 0) { TRACE("Failed to get bit from input stream"); jpgalleg_error = JPG_ERROR_BAD_IMAGE; return -1; } skip_count = (1 << num_zeroes) + value - 1; } break; } } else { index += num_zeroes; if ((data = get_value(category)) == (int)0x80000000) return -1; block[index++] = data << successive_low; } } while (index <= spectrum_end); } else { /* AC successive approximation */ index = spectrum_start; p_bit = 1 << successive_low; n_bit = (-1) << successive_low; if (skip_count == 0) { do { data = huffman_decode(ac_table); if (data < 0) { TRACE("Bad ac data"); jpgalleg_error = JPG_ERROR_BAD_IMAGE; return -1; } num_zeroes = data >> 4; category = data & 0xf; if (category == 0) { if (num_zeroes < 15) { skip_count = 1 << num_zeroes; if (num_zeroes) { value = get_bits(num_zeroes); if (value < 0) { TRACE("Failed to get bit from input stream"); jpgalleg_error = JPG_ERROR_BAD_IMAGE; return -1; } skip_count += value; } break; } } else if (category == 1) { if ((data = _jpeg_get_bit()) < 0) { TRACE("Failed to get bit from input stream"); jpgalleg_error = JPG_ERROR_BAD_IMAGE; return -1; } if (data) category = p_bit; else category = n_bit; } else { TRACE("Unexpected ac value category"); jpgalleg_error = JPG_ERROR_BAD_IMAGE; return -1; } do { if (block[index]) { if ((data = _jpeg_get_bit()) < 0) { TRACE("Failed to get bit from input stream"); jpgalleg_error = JPG_ERROR_BAD_IMAGE; return -1; } if ((data) && (!(block[index] & p_bit))) { if (block[index] >= 0) block[index] += p_bit; else block[index] += n_bit; } } else { num_zeroes--; if (num_zeroes < 0) break; } index++; } while (index <= spectrum_end); if ((category) && (index < 64)) block[index] = category; index++; } while (index <= spectrum_end); } if (skip_count > 0) { while (index <= spectrum_end) { if (block[index]) { if ((data = _jpeg_get_bit()) < 0) { TRACE("Failed to get bit from input stream"); jpgalleg_error = JPG_ERROR_BAD_IMAGE; return -1; } if ((data) && (!(block[index] & p_bit))) { if (block[index] >= 0) block[index] += p_bit; else block[index] += n_bit; } } index++; } skip_count--; } } } return 0; } /* _jpeg_c_ycbcr2rgb: * C version of the YCbCr -> RGB color conversion routine. Converts 2 pixels * at a time. */ static void _jpeg_c_ycbcr2rgb(intptr_t addr, int y1, int cb1, int cr1, int y2, int cb2, int cr2, int y3, int cb3, int cr3, int y4, int cb4, int cr4) { int r, g, b; unsigned int *ptr = (unsigned int *)addr, temp, p0, p1, p2; #ifdef ALLEGRO_LITTLE_ENDIAN r = MID(0, ((y1 << 8) + (359 * (cr1 - 128))) >> 8, 255); g = MID(0, ((y1 << 8) - (88 * (cb1 - 128)) - (183 * (cr1 - 128))) >> 8, 255); b = MID(0, ((y1 << 8) + (453 * (cb1 - 128)) ) >> 8, 255); p0 = makecol24(r, g, b); r = MID(0, ((y2 << 8) + (359 * (cr2 - 128))) >> 8, 255); g = MID(0, ((y2 << 8) - (88 * (cb2 - 128)) - (183 * (cr2 - 128))) >> 8, 255); b = MID(0, ((y2 << 8) + (453 * (cb2 - 128)) ) >> 8, 255); temp = makecol24(r, g, b); p0 |= (temp << 24); p1 = temp >> 8; r = MID(0, ((y3 << 8) + (359 * (cr3 - 128))) >> 8, 255); g = MID(0, ((y3 << 8) - (88 * (cb3 - 128)) - (183 * (cr3 - 128))) >> 8, 255); b = MID(0, ((y3 << 8) + (453 * (cb3 - 128)) ) >> 8, 255); temp = makecol24(r, g, b); p1 |= temp << 16; p2 = temp >> 16; r = MID(0, ((y4 << 8) + (359 * (cr4 - 128))) >> 8, 255); g = MID(0, ((y4 << 8) - (88 * (cb4 - 128)) - (183 * (cr4 - 128))) >> 8, 255); b = MID(0, ((y4 << 8) + (453 * (cb4 - 128)) ) >> 8, 255); p2 |= makecol24(r, g, b) << 8; #else r = MID(0, ((y1 << 8) + (359 * (cr1 - 128))) >> 8, 255); g = MID(0, ((y1 << 8) - (88 * (cb1 - 128)) - (183 * (cr1 - 128))) >> 8, 255); b = MID(0, ((y1 << 8) + (453 * (cb1 - 128)) ) >> 8, 255); p0 = makecol24(r, g, b) << 8; r = MID(0, ((y2 << 8) + (359 * (cr2 - 128))) >> 8, 255); g = MID(0, ((y2 << 8) - (88 * (cb2 - 128)) - (183 * (cr2 - 128))) >> 8, 255); b = MID(0, ((y2 << 8) + (453 * (cb2 - 128)) ) >> 8, 255); temp = makecol24(r, g, b); p0 |= (temp >> 16); p1 = temp << 16; r = MID(0, ((y3 << 8) + (359 * (cr3 - 128))) >> 8, 255); g = MID(0, ((y3 << 8) - (88 * (cb3 - 128)) - (183 * (cr3 - 128))) >> 8, 255); b = MID(0, ((y3 << 8) + (453 * (cb3 - 128)) ) >> 8, 255); temp = makecol24(r, g, b); p1 |= temp >> 8; p2 = temp << 24; r = MID(0, ((y4 << 8) + (359 * (cr4 - 128))) >> 8, 255); g = MID(0, ((y4 << 8) - (88 * (cb4 - 128)) - (183 * (cr4 - 128))) >> 8, 255); b = MID(0, ((y4 << 8) + (453 * (cb4 - 128)) ) >> 8, 255); p2 |= makecol24(r, g, b); #endif ptr[0] = p0; ptr[1] = p1; ptr[2] = p2; } /* plot_444: * Plots an 8x8 MCU block for 444 mode. Also used to plot greyscale MCUs. */ static void plot_444(intptr_t addr, int pitch, short *y1, short *y2, short *y3, short *y4, short *cb, short *cr) { int x, y; short *y1_ptr = y1, *cb_ptr = cb, *cr_ptr = cr, v; (void)y2; (void)y3; (void)y4; if (jpeg_components == 1) { for (y = 0; y < 8; y++) { for (x = 0; x < 8; x++) { v = *y1_ptr++; *(unsigned char *)addr = MID(0, v, 255); addr++; } addr += (pitch - 8); } } else { for (y = 0; y < 8; y++) { for (x = 0; x < 8; x += 4) { ycbcr2rgb(addr, *y1_ptr, *cb_ptr, *cr_ptr, *(y1_ptr + 1), *(cb_ptr + 1), *(cr_ptr + 1), *(y1_ptr + 2), *(cb_ptr + 2), *(cr_ptr + 2), *(y1_ptr + 3), *(cb_ptr + 3), *(cr_ptr + 3)); y1_ptr += 4; cb_ptr += 4; cr_ptr += 4; addr += 12; } addr += (pitch - 24); } } } /* plot_422_h: * Plots a 16x8 MCU block for 422 mode. */ static void plot_422_h(intptr_t addr, int pitch, short *y1, short *y2, short *y3, short *y4, short *cb, short *cr) { int x, y; short *y1_ptr = y1, *y2_ptr = y2, *cb_ptr = cb, *cr_ptr = cr; (void)y3; (void)y4; for (y = 0; y < 8; y++) { for (x = 0; x < 8; x += 4) { ycbcr2rgb(addr, *y1_ptr, *cb_ptr, *cr_ptr, *(y1_ptr + 1), *cb_ptr, *cr_ptr, *(y1_ptr + 2), *(cb_ptr + 1), *(cr_ptr + 1), *(y1_ptr + 3), *(cb_ptr + 1), *(cr_ptr + 1)); ycbcr2rgb(addr + 24, *y2_ptr, *(cb_ptr + 4), *(cr_ptr + 4), *(y2_ptr + 1), *(cb_ptr + 4), *(cr_ptr + 4), *(y2_ptr + 2), *(cb_ptr + 5), *(cr_ptr + 5), *(y2_ptr + 3), *(cb_ptr + 5), *(cr_ptr + 5)); y1_ptr += 4; y2_ptr += 4; cb_ptr += 2; cr_ptr += 2; addr += 12; } cb_ptr += 4; cr_ptr += 4; addr += (pitch - 24); } } /* plot_422_v: * Plots a 8x16 MCU block for 422 mode. */ static void plot_422_v(intptr_t addr, int pitch, short *y1, short *y2, short *y3, short *y4, short *cb, short *cr) { int x, y, d; short *y1_ptr = y1, *y2_ptr = y2, *cb_ptr = cb, *cr_ptr = cr; (void)y3; (void)y4; for (y = 0; y < 8; y++) { for (x = 0; x < 8; x += 4) { ycbcr2rgb(addr, *y1_ptr, *cb_ptr, *cr_ptr, *(y1_ptr + 1), *(cb_ptr + 1), *(cr_ptr + 1), *(y1_ptr + 2), *(cb_ptr + 2), *(cr_ptr + 2), *(y1_ptr + 3), *(cb_ptr + 3), *(cr_ptr + 3)); ycbcr2rgb(addr + (pitch * 8), *y2_ptr, *(cb_ptr + 32), *(cr_ptr + 32), *(y2_ptr + 1), *(cb_ptr + 33), *(cr_ptr + 33), *(y2_ptr + 2), *(cb_ptr + 34), *(cr_ptr + 34), *(y2_ptr + 3), *(cb_ptr + 35), *(cr_ptr + 35)); y1_ptr += 4; y2_ptr += 4; cb_ptr += 4; cr_ptr += 4; addr += 12; } d = (!(y & 1)) * 8; cb_ptr -= d; cr_ptr -= d; addr += (pitch - 24); } } /* plot_411: * Plots a 16x16 MCU block for 411 mode. */ static void plot_411(intptr_t addr, int pitch, short *y1, short *y2, short *y3, short *y4, short *cb, short *cr) { int x, y, d; short *y1_ptr = y1, *y2_ptr = y2, *y3_ptr = y3, *y4_ptr = y4, *cb_ptr = cb, *cr_ptr = cr; for (y = 0; y < 8; y++) { for (x = 0; x < 8; x += 4) { ycbcr2rgb(addr, *y1_ptr, *cb_ptr, *cr_ptr, *(y1_ptr + 1), *cb_ptr, *cr_ptr, *(y1_ptr + 2), *(cb_ptr + 1), *(cr_ptr + 1), *(y1_ptr + 3), *(cb_ptr + 1), *(cr_ptr + 1)); ycbcr2rgb(addr + 24, *y2_ptr, *(cb_ptr + 4), *(cr_ptr + 4), *(y2_ptr + 1), *(cb_ptr + 4), *(cr_ptr + 4), *(y2_ptr + 2), *(cb_ptr + 5), *(cr_ptr + 5), *(y2_ptr + 3), *(cb_ptr + 5), *(cr_ptr + 5)); ycbcr2rgb(addr + (pitch * 8), *y3_ptr, *(cb_ptr + 32), *(cr_ptr + 32), *(y3_ptr + 1), *(cb_ptr + 32), *(cr_ptr + 32), *(y3_ptr + 2), *(cb_ptr + 33), *(cr_ptr + 33), *(y3_ptr + 3), *(cb_ptr + 33), *(cr_ptr + 33)); ycbcr2rgb(addr + (pitch * 8) + 24, *y4_ptr, *(cb_ptr + 36), *(cr_ptr + 36), *(y4_ptr + 1), *(cb_ptr + 36), *(cr_ptr + 36), *(y4_ptr + 2), *(cb_ptr + 37), *(cr_ptr + 37), *(y4_ptr + 3), *(cb_ptr + 37), *(cr_ptr + 37)); y1_ptr += 4; y2_ptr += 4; y3_ptr += 4; y4_ptr += 4; cb_ptr += 2; cr_ptr += 2; addr += 12; } d = ((y & 1) * 8) - 4; cb_ptr += d; cr_ptr += d; addr += (pitch - 24); } } #ifdef DEBUG static void dump_chunk(char *msg, int length) { char buffer[65536]; int i; for (i = 0; (i < length) && (!_jpeg_eoc()); i++) buffer[i] = _jpeg_getc(); buffer[i] = '\0'; TRACE("%s%s", msg, buffer); } #endif /* do_decode: * Main decoding function. */ static BITMAP * do_decode(RGB *pal, void (*callback)(int)) { const int x_ofs[4] = { 0, 1, 0, 1 }, y_ofs[4] = { 0, 0, 1, 1 }; short coefs_buffer[384], coefs[64], *coefs_ptr, *temp_ptr; short *y1, *y2, *y3, *y4, *cb, *cr; short workspace[130]; intptr_t addr; int pitch, i, j; int block_x, block_y, block_max_x, block_max_y; int blocks_per_row[3]; int blocks_in_mcu, block_component[6]; short *block_ptr[6]; int block_x_ofs[6], block_y_ofs[6]; int mcu_w, mcu_h, component_w[3], component_h[3], c; int old_dc[3] = { 0, 0, 0 }; BITMAP *bmp; int data, flags = 0; int restart_count; int depth; jpgalleg_error = JPG_ERROR_NONE; TRACE("############### Decode start ###############"); #ifdef JPGALLEG_MMX if (cpu_capabilities & CPU_MMX) { idct = _jpeg_mmx_idct; if (_rgb_r_shift_24 == 0) ycbcr2rgb = _jpeg_mmx_ycbcr2rgb; else if (_rgb_r_shift_24 == 16) ycbcr2rgb = _jpeg_mmx_ycbcr2bgr; else ycbcr2rgb = _jpeg_c_ycbcr2rgb; TRACE("Using MMX..."); } else { #endif idct = _jpeg_c_idct; ycbcr2rgb = _jpeg_c_ycbcr2rgb; #ifdef JPGALLEG_MMX } #endif memset(_jpeg_huffman_dc_table, 0, 4 * sizeof(HUFFMAN_TABLE)); memset(_jpeg_huffman_ac_table, 0, 4 * sizeof(HUFFMAN_TABLE)); y1 = coefs_buffer; y2 = coefs_buffer + 64; y3 = coefs_buffer + 128; y4 = coefs_buffer + 192; cb = coefs_buffer + 256; cr = coefs_buffer + 320; _jpeg_io.current_bit = 8; if (_jpeg_getw() != CHUNK_SOI) { TRACE("SOI chunk not found"); jpgalleg_error = JPG_ERROR_NOT_JPEG; return NULL; } /* Examine header */ do { data = _jpeg_getc(); if (data < 0) return NULL; else if (data == 0xff) { while ((data = _jpeg_getc()) == 0xff) ; switch (data) { case -1: return NULL; case 0: break; case CHUNK_SOF2: flags |= IS_PROGRESSIVE; /* fallthrough */ case CHUNK_SOF0: case CHUNK_SOF1: TRACE("SOFx chunk found"); if (read_sof0_chunk()) return NULL; flags |= SOF0_DEFINED; break; case CHUNK_SOF3: case CHUNK_SOF5: case CHUNK_SOF6: case CHUNK_SOF7: case CHUNK_SOF9: case CHUNK_SOF10: case CHUNK_SOF11: case CHUNK_SOF13: case CHUNK_SOF14: case CHUNK_SOF15: TRACE("Unsupported encoding chunk (0xFF%X)", data); jpgalleg_error = JPG_ERROR_UNSUPPORTED_ENCODING; return NULL; case CHUNK_DHT: TRACE("DHT chunk found"); if (read_dht_chunk()) return NULL; flags |= DHT_DEFINED; break; case CHUNK_SOS: TRACE("SOS chunk found"); if (read_sos_chunk()) return NULL; flags |= SOS_DEFINED; break; case CHUNK_DQT: TRACE("DQT chunk found"); if (read_dqt_chunk()) return NULL; flags |= DQT_DEFINED; break; case CHUNK_APP0: TRACE("APP0 chunk found"); if (read_appn_chunk(data, flags)) return NULL; flags |= APP0_DEFINED; break; case CHUNK_APP1: TRACE("APP1 chunk found"); if (!(flags & APP1_DEFINED)) { if (read_appn_chunk(data, flags)) return NULL; flags |= APP1_DEFINED; } else { _jpeg_open_chunk(); _jpeg_close_chunk(); } break; case CHUNK_APP2: case CHUNK_APP3: case CHUNK_APP4: case CHUNK_APP5: case CHUNK_APP6: case CHUNK_APP7: case CHUNK_APP8: case CHUNK_APP9: case CHUNK_APP10: case CHUNK_APP11: case CHUNK_APP12: case CHUNK_APP13: case CHUNK_APP14: case CHUNK_APP15: TRACE("APP%d chunk found, skipping", data - CHUNK_APP0); _jpeg_open_chunk(); #ifdef DEBUG dump_chunk("First 30 bytes of chunk: ", 30); #endif _jpeg_close_chunk(); flags |= APP0_DEFINED; break; case CHUNK_DRI: TRACE("DRI chunk found"); if (read_dri_chunk()) return NULL; flags |= DRI_DEFINED; break; case CHUNK_JPG: case CHUNK_TEM: case CHUNK_RST0: case CHUNK_RST1: case CHUNK_RST2: case CHUNK_RST3: case CHUNK_RST4: case CHUNK_RST5: case CHUNK_RST6: case CHUNK_RST7: TRACE("Unexpected chunk found in header (0xFF%X)", data); jpgalleg_error = JPG_ERROR_BAD_IMAGE; return NULL; case CHUNK_COM: _jpeg_open_chunk(); #ifdef DEBUG dump_chunk("COM chunk found; comment: ", 65536); #endif _jpeg_close_chunk(); break; default: TRACE("Unknown chunk found in header (0xFF%X), skipping", data); _jpeg_open_chunk(); #ifdef DEBUG dump_chunk("First 30 bytes of chunk: ", 30); #endif _jpeg_close_chunk(); break; } } } while (((flags & JFIF_OK) != JFIF_OK) && ((flags & EXIF_OK) != EXIF_OK)); /* Deal with bogus restart interval */ if (restart_interval <= 0) flags &= ~DRI_DEFINED; bmp = create_bitmap_ex((jpeg_components == 1) ? 8 : 24, (jpeg_w + 15) & ~0xf, (jpeg_h + 15) & ~0xf); if (!bmp) { TRACE("Out of memory"); return NULL; } pitch = (int)(bmp->line[1] - bmp->line[0]); block_x = block_y = 0; restart_count = 0; memset(data_buffer, 0, 3 * sizeof(DATA_BUFFER *)); progress_cb = callback; progress_counter = 0; if (!(flags & IS_PROGRESSIVE)) { /* Baseline decoding */ TRACE("Starting baseline decoding"); if (jpeg_components == 1) /* force 444 mode for grayscale images */ sampling = h_sampling = v_sampling = 1; blocks_in_mcu = 0; coefs_ptr = coefs_buffer; for (i = 0; i < sampling; i++) { block_component[blocks_in_mcu] = 0; block_ptr[blocks_in_mcu] = coefs_ptr; coefs_ptr += 64; blocks_in_mcu++; } for (i = 1; i < jpeg_components; i++) { block_component[blocks_in_mcu] = i; block_ptr[blocks_in_mcu] = coefs_ptr; coefs_ptr += 64; blocks_in_mcu++; } mcu_w = h_sampling * 8; mcu_h = v_sampling * 8; plot = plot_411; if (sampling < 4) { plot = plot_422_v; if (h_sampling == 2) plot = plot_422_h; cb -= 128; cr -= 128; if (sampling < 2) { plot = plot_444; cb -= 64; cr -= 64; } } progress_total = (bmp->w / mcu_w) * (bmp->h / mcu_h); TRACE("%dx%d %s image, %s mode", jpeg_w, jpeg_h, jpeg_components == 1 ? "greyscale" : "color", plot == plot_444 ? "444" : (((plot == plot_422_h) || (plot == plot_422_v)) ? "422" : "411")); /* Start decoding! */ do { for (i = 0; i < blocks_in_mcu; i++) { if (decode_baseline_block(block_ptr[i], (block_component[i] == 0) ? LUMINANCE : CHROMINANCE, &old_dc[block_component[i]])) goto exit_error; } addr = (intptr_t)bmp->line[block_y] + (block_x * (jpeg_components == 1 ? 1 : 3)); plot(addr, pitch, y1, y2, y3, y4, cb, cr); block_x += mcu_w; if (block_x >= jpeg_w) { block_x = 0; block_y += mcu_h; } restart_count++; if ((flags & DRI_DEFINED) && (restart_count >= restart_interval)) { data = _jpeg_getw(); if (data == CHUNK_EOI) break; if ((data < CHUNK_RST0) || (data > CHUNK_RST7)) { TRACE("Expected RSTx chunk not found, found 0x%X instead", data); jpgalleg_error = JPG_ERROR_BAD_IMAGE; goto exit_error; } memset(old_dc, 0, 3 * sizeof(int)); restart_count = 0; } if (progress_cb) progress_cb((progress_counter * 100) / progress_total); progress_counter++; } while (block_y < jpeg_h); } else { /* Progressive decoding */ TRACE("Starting progressive decoding"); blocks_per_row[0] = bmp->w / 8; data_buffer[0] = (DATA_BUFFER *)calloc(1, sizeof(DATA_BUFFER) * (bmp->w / 8) * (bmp->h / 8)); if (!data_buffer[0]) { TRACE("Out of memory"); jpgalleg_error = JPG_ERROR_OUT_OF_MEMORY; goto exit_error; } for (i = 1; i < jpeg_components; i++) { blocks_per_row[i] = bmp->w / (h_sampling * 8); component_w[i] = component_h[i] = 1; data_buffer[i] = (DATA_BUFFER *)calloc(1, sizeof(DATA_BUFFER) * (bmp->w / 8) * (bmp->h / 8) / sampling); if (!data_buffer[i]) { TRACE("Out of memory"); jpgalleg_error = JPG_ERROR_OUT_OF_MEMORY; goto exit_error; } } progress_total = (2 + (3 * jpeg_components)) * blocks_per_row[0] * (bmp->h / (v_sampling * 8)); TRACE("%dx%d image, %s mode", jpeg_w, jpeg_h, sampling == 1 ? "444" : (sampling == 2 ? "422" : "411")); while (1) { /* Decode new scan */ if (((spectrum_start > spectrum_end) || (spectrum_end > 63)) || ((spectrum_start == 0) && (spectrum_end != 0)) || ((successive_high != 0) && (successive_high != successive_low + 1))) { TRACE("Bad progressive scan parameters"); jpgalleg_error = JPG_ERROR_BAD_IMAGE; goto exit_error; } restart_count = 0; block_x = block_y = 0; memset(old_dc, 0, 3 * sizeof(int)); /* Setup MCU layout for this scan */ blocks_in_mcu = 0; mcu_w = mcu_h = 8; for (i = 0; i < scan_components; i++) { switch (component[i]) { case 1: for (j = 0; j < sampling; j++) { block_component[blocks_in_mcu] = 0; block_x_ofs[blocks_in_mcu] = x_ofs[j]; block_y_ofs[blocks_in_mcu] = y_ofs[j]; blocks_in_mcu++; } if ((h_sampling == 1) && (v_sampling == 2)) { block_x_ofs[1] = x_ofs[2]; block_y_ofs[1] = y_ofs[2]; } break; case 2: case 3: block_component[blocks_in_mcu] = component[i] - 1; block_x_ofs[blocks_in_mcu] = 0; block_y_ofs[blocks_in_mcu] = 0; blocks_in_mcu++; mcu_w = MAX(mcu_w, h_sampling * 8); mcu_h = MAX(mcu_h, v_sampling * 8); break; } } block_max_x = (((jpeg_w + mcu_w - 1) & ~(mcu_w - 1)) / mcu_w); block_max_y = (((jpeg_h + mcu_h - 1) & ~(mcu_h - 1)) / mcu_h); /* Remove sampling dependency from luminance only scans */ if ((scan_components == 1) && (block_component[0] == 0)) { blocks_in_mcu = 1; component_w[0] = component_h[0] = 1; } else { component_w[0] = h_sampling; component_h[0] = v_sampling; } TRACE("Starting new scan (%s%s%s, %dx%d MCU)", _jpeg_component_name[component[0] - 1], (scan_components > 1 ? _jpeg_component_name[component[1] - 1] : ""), (scan_components > 2 ? _jpeg_component_name[component[2] - 1] : ""), mcu_w, mcu_h); /* Start decoding! */ do { restart_count++; if ((flags & DRI_DEFINED) && (restart_count >= restart_interval)) { data = _jpeg_getw(); if ((data < CHUNK_RST0) || (data > CHUNK_RST7)) { TRACE("Expected RSTx chunk not found, found 0x%X instead", data); jpgalleg_error = JPG_ERROR_BAD_IMAGE; goto exit_error; } memset(old_dc, 0, 3 * sizeof(int)); restart_count = skip_count = 0; } for (i = 0; i < blocks_in_mcu; i++) { c = block_component[i]; addr = (intptr_t)(data_buffer[c][((block_y * component_h[c]) * blocks_per_row[c]) + (block_y_ofs[i] * blocks_per_row[c]) + (block_x * component_w[c]) + block_x_ofs[i]].data); if (decode_progressive_block(addr, (c == 0) ? LUMINANCE : CHROMINANCE, &old_dc[c])) goto exit_error; } block_x++; if (block_x >= block_max_x) { block_x = 0; block_y++; } if (progress_cb) progress_cb((progress_counter * 100) / progress_total); progress_counter++; if (progress_counter > progress_total) progress_total += (bmp->w / mcu_w) * (bmp->h / mcu_h); } while (block_y < block_max_y); /* Process inter-scan chunks */ while (1) { while ((data = _jpeg_getc()) == 0xff) ; if (data == CHUNK_SOS) { if (read_sos_chunk()) { jpgalleg_error = JPG_ERROR_BAD_IMAGE; goto exit_error; } break; } else if (data == CHUNK_DHT) { if (read_dht_chunk()) { jpgalleg_error = JPG_ERROR_BAD_IMAGE; goto exit_error; } } else if (data == CHUNK_DRI) { if (read_dri_chunk()) { jpgalleg_error = JPG_ERROR_BAD_IMAGE; goto exit_error; } } else if (data == (CHUNK_EOI & 0xff)) goto eoi_found; else { TRACE("Unexpected inter-scan chunk found (0xFF%X)", data); jpgalleg_error = JPG_ERROR_BAD_IMAGE; goto exit_error; } } } eoi_found: /* Apply idct and plot image */ component_w[0] = h_sampling; component_h[0] = v_sampling; mcu_w = h_sampling * 8; mcu_h = v_sampling * 8; blocks_in_mcu = sampling; for (i = 0; i < sampling; i++) { block_component[i] = 0; block_x_ofs[i] = x_ofs[i]; block_y_ofs[i] = y_ofs[i]; } if ((h_sampling == 1) && (v_sampling == 2)) { block_x_ofs[1] = x_ofs[2]; block_y_ofs[1] = y_ofs[2]; } for (i = 1; i < jpeg_components; i++) { block_component[blocks_in_mcu] = i; block_x_ofs[blocks_in_mcu] = 0; block_y_ofs[blocks_in_mcu] = 0; blocks_in_mcu++; } plot = plot_411; if (sampling < 4) { plot = plot_422_v; if (h_sampling == 2) plot = plot_422_h; cb -= 128; cr -= 128; if (sampling < 2) { plot = plot_444; cb -= 64; cr -= 64; } } for (block_y = 0; block_y < bmp->h / mcu_h; block_y++) { for (block_x = 0; block_x < bmp->w / mcu_w; block_x++) { coefs_ptr = coefs_buffer; for (i = 0; i < blocks_in_mcu; i++) { c = block_component[i]; temp_ptr = data_buffer[c][(block_y * blocks_per_row[c] * component_h[c]) + (blocks_per_row[c] * block_y_ofs[i]) + (block_x * component_w[c]) + block_x_ofs[i]].data; zigzag_reorder(temp_ptr, coefs); idct(coefs, coefs_ptr, (c == 0) ? luminance_quantization_table : chrominance_quantization_table, workspace); coefs_ptr += 64; } addr = (intptr_t)bmp->line[block_y * mcu_h] + (block_x * mcu_w * (jpeg_components == 1 ? 1 : 3)); plot(addr, pitch, y1, y2, y3, y4, cb, cr); } } } /* Fixup image depth and size */ if (jpeg_components == 1) { for (i = 0; i < 256; i++) pal[i].r = pal[i].g = pal[i].b = (i >> 2); depth = _color_load_depth(8, FALSE); } else depth = _color_load_depth(24, FALSE); if (((jpeg_components == 1) && (depth != 8)) || ((jpeg_components != 1) && (depth != 24))) bmp = _fixup_loaded_bitmap(bmp, pal, depth); if (depth != 8) generate_332_palette(pal); /* Hack to set size; image may be really slightly bigger than reported. * We assume final user always to access data via line pointers and NEVER * assume data is linearly stored in memory starting at bmp->dat... */ bmp->w = bmp->cr = jpeg_w; bmp->h = bmp->cb = jpeg_h; exit_ok: for (i = 0; i < jpeg_components; i++) { if (data_buffer[i]) free(data_buffer[i]); } for (i = 0; i < 4; i++) { free_huffman_table(&_jpeg_huffman_dc_table[i]); free_huffman_table(&_jpeg_huffman_ac_table[i]); } TRACE("################ Decode end ################"); return bmp; exit_error: destroy_bitmap(bmp); bmp = NULL; goto exit_ok; } /* load_jpg: * Loads a JPG image from a file into a BITMAP, with no progress callback. */ BITMAP * load_jpg(AL_CONST char *filename, RGB *palette) { return load_jpg_ex(filename, palette, NULL); } /* load_jpg_ex: * Loads a JPG image from a file into a BITMAP. */ BITMAP * load_jpg_ex(AL_CONST char *filename, RGB *palette, void (*callback)(int progress)) { PACKFILE *f; BITMAP *bmp; PALETTE pal; uint64_t size; if (!palette) palette = pal; size = file_size_ex(filename); if (!size) { TRACE("File %s has zero size or does not exist", filename); jpgalleg_error = JPG_ERROR_READING_FILE; return NULL; } _jpeg_io.buffer = _jpeg_io.buffer_start = (unsigned char *)malloc(size); _jpeg_io.buffer_end = _jpeg_io.buffer_start + size; if (!_jpeg_io.buffer) { TRACE("Out of memory"); jpgalleg_error = JPG_ERROR_OUT_OF_MEMORY; return NULL; } f = pack_fopen(filename, F_READ); if (!f) { TRACE("Cannot open %s for reading", filename); jpgalleg_error = JPG_ERROR_READING_FILE; free(_jpeg_io.buffer); return NULL; } pack_fread(_jpeg_io.buffer, size, f); pack_fclose(f); TRACE("Loading JPG from file %s", filename); bmp = do_decode(palette, callback); free(_jpeg_io.buffer_start); return bmp; } /* load_memory_jpg: * Loads a JPG image from a memory buffer into a BITMAP, with no progress * callback. */ BITMAP * load_memory_jpg(void *buffer, int size, RGB *palette) { return load_memory_jpg_ex(buffer, size, palette, NULL); } /* load_memory_jpg: * Loads a JPG image from a memory buffer into a BITMAP. */ BITMAP * load_memory_jpg_ex(void *buffer, int size, RGB *palette, void (*callback)(int progress)) { BITMAP *bmp; PALETTE pal; if (!palette) palette = pal; _jpeg_io.buffer = _jpeg_io.buffer_start = buffer; _jpeg_io.buffer_end = _jpeg_io.buffer_start + size; TRACE("Loading JPG from memory buffer at %p (size = %d)", buffer, size); bmp = do_decode(palette, callback); return bmp; } allegro4.4-4.4.2/addons/jpgalleg/src/encode.c000066400000000000000000000755231173507505700206470ustar00rootroot00000000000000/* * __ _____ ______ ______ ___ ___ * /\ \ /\ _ `\ /\ ___\ /\ _ \ /\_ \ /\_ \ * \ \ \\ \ \L\ \\ \ \__/ \ \ \L\ \\//\ \ \//\ \ __ __ * __ \ \ \\ \ __| \ \ \ __\ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\ * /\ \_\/ / \ \ \/ \ \ \L\ \\ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ * \ \____// \ \_\ \ \____/ \ \_\ \_\/\____\/\____\ \____\ \____ \ * \/____/ \/_/ \/___/ \/_/\/_/\/____/\/____/\/____/\/___L\ \ * /\____/ * \_/__/ * * Version 2.6, by Angelo Mottola, 2000-2006 * * Encoder core module. * * See the readme.txt file for instructions on using this package in your * own programs. */ #include /* Standard quantization tables for luminance and chrominance. Scaled version * of these are used by the encoder for a given quality. * These tables come from the IJG code, which takes them from the JPeg specs, * and are generic quantization tables that give good results on most images. */ static const unsigned char default_luminance_quant_table[64] = { 16, 11, 10, 16, 24, 40, 51, 61, 12, 12, 14, 19, 26, 58, 60, 55, 14, 13, 16, 24, 40, 57, 69, 56, 14, 17, 22, 29, 51, 87, 80, 62, 18, 22, 37, 56, 68, 109, 103, 77, 24, 35, 55, 64, 81, 104, 113, 92, 49, 64, 78, 87, 103, 121, 120, 101, 72, 92, 95, 98, 112, 100, 103, 99 }; static const unsigned char default_chrominance_quant_table[64] = { 17, 18, 24, 47, 99, 99, 99, 99, 18, 21, 26, 66, 99, 99, 99, 99, 24, 26, 56, 99, 99, 99, 99, 99, 47, 66, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99 }; /* Standard huffman tables for luminance AC/DC and chrominance AC/DC. * These come from the IJG code, which takes them from the JPeg standard. */ static const unsigned char default_num_codes_dc_luminance[17] = { 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 }; static const unsigned char default_val_dc_luminance[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; static const unsigned char default_num_codes_dc_chrominance[17] = { 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 }; static const unsigned char default_val_dc_chrominance[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; static const unsigned char default_num_codes_ac_luminance[17] = { 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d }; static const unsigned char default_val_ac_luminance[] = { 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa }; static const unsigned char default_num_codes_ac_chrominance[17] = { 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77 }; static const unsigned char default_val_ac_chrominance[] = { 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa }; static unsigned char *num_codes_dc_luminance, *val_dc_luminance; static unsigned char *num_codes_dc_chrominance, *val_dc_chrominance; static unsigned char *num_codes_ac_luminance, *val_ac_luminance; static unsigned char *num_codes_ac_chrominance, *val_ac_chrominance; static int luminance_quant_table[64]; static int chrominance_quant_table[64]; static int current_pass, progress_counter, progress_total; static int sampling, greyscale, mcu_w, mcu_h, pitch; static BITMAP *fixed_bmp; static void (*rgb2ycbcr)(intptr_t address, short *y1, short *cb1, short *cr1, short *y2, short *cb2, short *cr2); static void (*progress_cb)(int percentage); /* apply_fdct: * Applies the forward discrete cosine transform to the given input block, * in the form of a vector of 64 coefficients. * This uses integer fixed point math and is based on code by the IJG. */ static void apply_fdct(short *data) { int tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; int tmp10, tmp11, tmp12, tmp13; int z1, z2, z3, z4, z5; short *dataptr = data; int i; for (i = 8; i; i--) { tmp0 = dataptr[0] + dataptr[7]; tmp7 = dataptr[0] - dataptr[7]; tmp1 = dataptr[1] + dataptr[6]; tmp6 = dataptr[1] - dataptr[6]; tmp2 = dataptr[2] + dataptr[5]; tmp5 = dataptr[2] - dataptr[5]; tmp3 = dataptr[3] + dataptr[4]; tmp4 = dataptr[3] - dataptr[4]; tmp10 = tmp0 + tmp3; tmp13 = tmp0 - tmp3; tmp11 = tmp1 + tmp2; tmp12 = tmp1 - tmp2; dataptr[0] = (tmp10 + tmp11) << 2; dataptr[4] = (tmp10 - tmp11) << 2; z1 = (tmp12 + tmp13) * FIX_0_541196100; dataptr[2] = (z1 + (tmp13 * FIX_0_765366865)) >> 11; dataptr[6] = (z1 + (tmp12 * -FIX_1_847759065)) >> 11; z1 = tmp4 + tmp7; z2 = tmp5 + tmp6; z3 = tmp4 + tmp6; z4 = tmp5 + tmp7; z5 = (z3 + z4) * FIX_1_175875602; tmp4 *= FIX_0_298631336; tmp5 *= FIX_2_053119869; tmp6 *= FIX_3_072711026; tmp7 *= FIX_1_501321110; z1 *= -FIX_0_899976223; z2 *= -FIX_2_562915447; z3 *= -FIX_1_961570560; z4 *= -FIX_0_390180644; z3 += z5; z4 += z5; dataptr[7] = (tmp4 + z1 + z3) >> 11; dataptr[5] = (tmp5 + z2 + z4) >> 11; dataptr[3] = (tmp6 + z2 + z3) >> 11; dataptr[1] = (tmp7 + z1 + z4) >> 11; dataptr += 8; } dataptr = data; for (i = 8; i; i--) { tmp0 = dataptr[0] + dataptr[56]; tmp7 = dataptr[0] - dataptr[56]; tmp1 = dataptr[8] + dataptr[48]; tmp6 = dataptr[8] - dataptr[48]; tmp2 = dataptr[16] + dataptr[40]; tmp5 = dataptr[16] - dataptr[40]; tmp3 = dataptr[24] + dataptr[32]; tmp4 = dataptr[24] - dataptr[32]; tmp10 = tmp0 + tmp3; tmp13 = tmp0 - tmp3; tmp11 = tmp1 + tmp2; tmp12 = tmp1 - tmp2; dataptr[0] = (tmp10 + tmp11) >> 2; dataptr[32] = (tmp10 - tmp11) >> 2; z1 = (tmp12 + tmp13) * FIX_0_541196100; dataptr[16] = (z1 + (tmp13 * FIX_0_765366865)) >> 15; dataptr[48] = (z1 + (tmp12 * -FIX_1_847759065)) >> 15; z1 = tmp4 + tmp7; z2 = tmp5 + tmp6; z3 = tmp4 + tmp6; z4 = tmp5 + tmp7; z5 = (z3 + z4) * FIX_1_175875602; tmp4 *= FIX_0_298631336; tmp5 *= FIX_2_053119869; tmp6 *= FIX_3_072711026; tmp7 *= FIX_1_501321110; z1 *= -FIX_0_899976223; z2 *= -FIX_2_562915447; z3 *= -FIX_1_961570560; z4 *= -FIX_0_390180644; z3 += z5; z4 += z5; dataptr[56] = (tmp4 + z1 + z3) >> 15; dataptr[40] = (tmp5 + z2 + z4) >> 15; dataptr[24] = (tmp6 + z2 + z3) >> 15; dataptr[8] = (tmp7 + z1 + z4) >> 15; dataptr++; } } /* zigzag_reorder: * Reorders a vector of coefficients by the zigzag scan. */ static INLINE void zigzag_reorder(short *input, short *output) { int i; for (i = 0; i < 64; i++) output[_jpeg_zigzag_scan[i]] = input[i]; } /* write_quantization_table: * Computes a quantization table given a quality value and writes it to the * output stream. */ static void write_quantization_table(int *quant_table, const unsigned char *data, int quality) { short temp[64], temp_table[64]; double value, factor = QUALITY_FACTOR(quality); int i; for (i = 0; i < 64; i++) { if (quality == 100) value = (double)data[i] / 15.0; else value = (double)data[i] / factor; temp[i] = MID(1, (int)floor(value), 255); } zigzag_reorder(temp, temp_table); for (i = 0; i < 64; i++) { _jpeg_chunk_putc(temp_table[i]); quant_table[i] = (1 << 16) / (int)temp_table[i]; } } /* setup_huffman_tree: * Sets bit lengths and codes of each huffman tree node, and computes total * tree depth. Also creates lists of nodes containing all leafs of the same * level, from leftmost to rightmost leaf, if "list" is not NULL. */ static void setup_huffman_tree(HUFFMAN_TREE *tree, HUFFMAN_NODE *node, int bits_length, HUFFMAN_NODE **list) { HUFFMAN_NODE *tail; if (node->entry) { node->entry->bits_length = bits_length; if (list) { if (!list[bits_length]) { list[bits_length] = node; } else { tail = list[bits_length]; while (tail->next) tail = tail->next; tail->next = node; } node->next = NULL; } } if (bits_length > tree->depth) tree->depth = bits_length; if (node->left) { setup_huffman_tree(tree, node->left, bits_length + 1, list); node->left->parent = node; } if (node->right) { setup_huffman_tree(tree, node->right, bits_length + 1, list); node->right->parent = node; } } /* find_leaf_at_level: * Finds first huffman tree node holding a leaf at specified level. */ static HUFFMAN_NODE * find_leaf_at_level(HUFFMAN_NODE *node, int level, int cur_level) { HUFFMAN_NODE *result; if (node->entry) { if (cur_level == level) return node; return NULL; } result = find_leaf_at_level(node->left, level, cur_level + 1); if (result) return result; result = find_leaf_at_level(node->right, level, cur_level + 1); if (result) return result; return NULL; } /* destroy_huffman_tree: * Frees memory used by specified huffman tree. */ static void destroy_huffman_tree(HUFFMAN_NODE *node) { if (!node) return; destroy_huffman_tree(node->left); destroy_huffman_tree(node->right); free(node); } /* compare_entries: * qsort() comparision function to sort huffman entries by frequency. */ static int compare_entries(const void *d1, const void *d2) { HUFFMAN_ENTRY *e1 = (HUFFMAN_ENTRY *)d1; HUFFMAN_ENTRY *e2 = (HUFFMAN_ENTRY *)d2; if (e1->frequency < e2->frequency) return 1; else if (e1->frequency > e2->frequency) return -1; return 0; } /* build_huffman_table: * Builds an optimized huffman table, given the frequency of each value. */ static int build_huffman_table(HUFFMAN_TABLE *table, unsigned char *num_codes, unsigned char *value) { HUFFMAN_TREE tree; HUFFMAN_NODE *node, *new_node, *src_node, *dest_node, *right, *left, *list[17]; HUFFMAN_ENTRY *entry, *fake_entry = NULL; int i, level, max_frequency = 0; TRACE("Building new huffman tree"); tree.head = tree.tail = NULL; tree.depth = 0; for (i = 0; i < 256; i++) max_frequency = MAX(max_frequency, table->entry[i].frequency); table->entry[256].frequency = max_frequency - 1; table->entry[256].value = -1; qsort(table->entry, 257, sizeof(HUFFMAN_ENTRY), compare_entries); for (i = 0; i < 257; i++) { entry = &table->entry[i]; if (entry->value < 0) fake_entry = entry; if (entry->frequency > 0) { new_node = (HUFFMAN_NODE *)calloc(1, sizeof(HUFFMAN_NODE)); new_node->entry = entry; new_node->frequency = entry->frequency; if (tree.tail) { tree.tail->next = new_node; new_node->prev = tree.tail; tree.tail = new_node; } else tree.head = tree.tail = new_node; } } while (tree.head != tree.tail) { new_node = (HUFFMAN_NODE *)calloc(1, sizeof(HUFFMAN_NODE)); new_node->left = tree.tail; new_node->right = tree.tail->prev; new_node->frequency = new_node->left->frequency + new_node->right->frequency; tree.tail = tree.tail->prev->prev; if (tree.tail) tree.tail->next = NULL; else tree.head = NULL; for (node = tree.tail; node && (node->frequency < new_node->frequency); node = node->prev) ; if (node) { new_node->prev = node; new_node->next = node->next; if (node->next) node->next->prev = new_node; else tree.tail = new_node; node->next = new_node; } else { new_node->next = tree.head; new_node->prev = NULL; if (tree.head) tree.head->prev = new_node; else tree.tail = new_node; tree.head = new_node; } } setup_huffman_tree(&tree, tree.head, 0, NULL); /* * Adjusts the huffman tree by removing two leaves from a level and * repositioning them at a lower level. Right leaf replaces the parent tree * node, left leaf is placed at the first convenient place at lower level. * This algorithm is used to reposition entries which appear to have a bits * length higher than 16, which is the maximum allowed by the JPG standard. */ while (tree.depth > 16) { TRACE("Tree depth > 16; adjusting leaves"); src_node = find_leaf_at_level(tree.head, tree.depth, 0); right = src_node->parent->right; left = src_node->parent->left; src_node->parent->entry = right->entry; src_node->parent->left = src_node->parent->right = NULL; level = 2; while (!(dest_node = find_leaf_at_level(tree.head, tree.depth - level, 0))) level++; dest_node->left = left; dest_node->right = right; right->entry = dest_node->entry; dest_node->entry = NULL; left->parent = dest_node; right->parent = dest_node; tree.depth = 0; setup_huffman_tree(&tree, tree.head, 0, NULL); } /* * Find rightmost leaf and replace it with fake entry. This is needed * as the JPG standard doesn't allow huffman entries with all bits set */ node = tree.head->right; while (!node->entry) node = node->right; node->parent->right = NULL; TRACE("Exchanging rightmost leaf at level %d with fake leaf at level %d%s", node->entry->bits_length, fake_entry->bits_length, (node->entry == fake_entry ? "(fake leaf == rightmost leaf)" : "")); fake_entry->value = node->entry->value; /* Save generated huffman table */ memset(list, 0, 17 * sizeof(HUFFMAN_NODE *)); setup_huffman_tree(&tree, tree.head, 0, list); for (i = 1; i <= 16; i++) { num_codes[i] = 0; for (node = list[i]; node; node = node->next) { *value++ = node->entry->value; num_codes[i]++; } } destroy_huffman_tree(tree.head); return 0; } /* write_huffman_table: * Writes an huffman table to the output stream and computes a lookup table * for faster huffman encoding. */ static void write_huffman_table(HUFFMAN_TABLE *table, unsigned const char *num_codes, unsigned const char *value) { HUFFMAN_ENTRY *entry; int i, j, code, index; for (i = 1; i <= 16; i++) _jpeg_chunk_putc(num_codes[i]); memset(table, 0, sizeof(HUFFMAN_TABLE)); index = code = 0; entry = table->entry; for (i = 1; i <= 16; i++) { for (j = 0; j < num_codes[i]; j++) { entry->value = value[index]; entry->encoded_value = code; entry->bits_length = i; _jpeg_chunk_putc(value[index]); table->code[entry->value] = entry; entry++; code++; index++; } code <<= 1; } } /* write_header: * Writes the complete header of a baseline JPG image to the output stream. * This is made of the following chunks (in order): APP0, COM, DQT, SOF0, * DHT, SOS. */ static int write_header(int sampling, int greyscale, int quality, int width, int height) { unsigned char *comment = (unsigned char *)"Generated using " JPGALLEG_VERSION_STRING; /* JFIF 1.1, no units, 1:1 aspect ratio, no thumbnail */ unsigned char app0[] = { 'J', 'F', 'I', 'F', 0, 1, 1, 0, 0, 1, 0, 1, 0, 0 }; /* 8 bits data precision, Y uses quantization table 0, Cb and Cr table 1 */ unsigned char sof0[] = { 8, (height >> 8) & 0xff, height & 0xff, (width >> 8) & 0xff, width & 0xff, greyscale ? 1 : 3, 1, 0, 0, 2, 0x11, 1, 3, 0x11, 1 }; /* Y uses DC table 0 and AC table 0, Cb and Cr use DC table 1 and AC table 1 */ unsigned char sos_greyscale[] = { 1, 1, 0x00, 0, 63, 0 }; unsigned char sos_color[] = { 3, 1, 0x00, 2, 0x11, 3, 0x11, 0, 63, 0 }; _jpeg_putw(CHUNK_SOI); /* APP0 chunk */ _jpeg_new_chunk(CHUNK_APP0); _jpeg_chunk_puts(app0, 14); _jpeg_write_chunk(); /* COM chunk ;) */ _jpeg_new_chunk(CHUNK_COM); _jpeg_chunk_puts(comment, (int) strlen((char*)comment)); _jpeg_write_chunk(); /* DQT chunk */ _jpeg_new_chunk(CHUNK_DQT); _jpeg_chunk_putc(0); write_quantization_table(luminance_quant_table, default_luminance_quant_table, quality); if (!greyscale) { _jpeg_chunk_putc(1); write_quantization_table(chrominance_quant_table, default_chrominance_quant_table, quality); } _jpeg_write_chunk(); /* SOF0 chunk */ if (greyscale) sof0[7] = 0x11; else { switch (sampling) { case JPG_SAMPLING_411: sof0[7] = 0x22; break; case JPG_SAMPLING_422: sof0[7] = 0x21; break; case JPG_SAMPLING_444: sof0[7] = 0x11; break; } } _jpeg_new_chunk(CHUNK_SOF0); _jpeg_chunk_puts(sof0, greyscale ? 9 : 15); _jpeg_write_chunk(); /* DHT chunk */ _jpeg_new_chunk(CHUNK_DHT); _jpeg_chunk_putc(0x00); /* DC huffman table 0 (used for luminance) */ write_huffman_table(&_jpeg_huffman_dc_table[0], num_codes_dc_luminance, val_dc_luminance); _jpeg_chunk_putc(0x10); /* AC huffman table 0 (used for luminance) */ write_huffman_table(&_jpeg_huffman_ac_table[0], num_codes_ac_luminance, val_ac_luminance); if (!greyscale) { _jpeg_chunk_putc(0x01); /* DC huffman table 1 (used for chrominance) */ write_huffman_table(&_jpeg_huffman_dc_table[1], num_codes_dc_chrominance, val_dc_chrominance); _jpeg_chunk_putc(0x11); /* AC huffman table 1 (used for chrominance) */ write_huffman_table(&_jpeg_huffman_ac_table[1], num_codes_ac_chrominance, val_ac_chrominance); } _jpeg_write_chunk(); /* SOS chunk */ _jpeg_new_chunk(CHUNK_SOS); if (greyscale) _jpeg_chunk_puts(sos_greyscale, 6); else _jpeg_chunk_puts(sos_color, 10); _jpeg_write_chunk(); return 0; } /* format_number: * Computes the category and bits of a given number. */ static INLINE void format_number(int num, int *category, int *bits) { int abs_num, mask, cat; mask = num >> 31; abs_num = (num ^ mask) - mask; for (cat = 0; abs_num; cat++) abs_num >>= 1; *category = cat; if (num >= 0) *bits = num; else *bits = num + ((1 << cat) - 1); } /* put_bits: * Writes some bits to the output stream. */ static INLINE int put_bits(int value, int num_bits) { int i; for (i = num_bits - 1; i >= 0; i--) { if (_jpeg_put_bit((value >> i) & 0x1)) return -1; } return 0; } /* huffman_encode: * Writes the huffman code of a given value. */ static INLINE int huffman_encode(HUFFMAN_TABLE *table, int value) { HUFFMAN_ENTRY *entry; if (current_pass == PASS_COMPUTE_HUFFMAN) { table->entry[value].value = value; table->entry[value].frequency++; return 0; } entry = table->code[value]; if (entry) return put_bits(entry->encoded_value, entry->bits_length); TRACE("Huffman code (%d) not found", value); jpgalleg_error = JPG_ERROR_HUFFMAN; return -1; } /* encode_block: * Encodes an 8x8 basic block of coefficients of given type (luminance or * chrominance) and writes it to the output stream. */ static int encode_block(short *block, int type, int *old_dc) { HUFFMAN_TABLE *dc_table, *ac_table; int *quant_table; short data[64]; int i, index; int value, num_zeroes; int category, bits; if (type == LUMINANCE) { dc_table = &_jpeg_huffman_dc_table[0]; ac_table = &_jpeg_huffman_ac_table[0]; quant_table = luminance_quant_table; } else { dc_table = &_jpeg_huffman_dc_table[1]; ac_table = &_jpeg_huffman_ac_table[1]; quant_table = chrominance_quant_table; } apply_fdct(block); zigzag_reorder(block, data); for (i = 0; i < 64; i++) { value = data[i]; if (value < 0) { value = -value; value = (value * quant_table[i]) + (quant_table[i] >> 1); data[i] = -(value >> 19); } else data[i] = ((value * quant_table[i]) + (quant_table[i] >> 1)) >> 19; } value = data[0] - *old_dc; *old_dc = data[0]; format_number(value, &category, &bits); if (huffman_encode(dc_table, category)) return -1; if (put_bits(bits, category)) return -1; num_zeroes = 0; for (index = 1; index < 64; index++) { if ((value = data[index]) == 0) num_zeroes++; else { while (num_zeroes > 15) { if (huffman_encode(ac_table, 0xf0)) return -1; num_zeroes -= 16; } format_number(value, &category, &bits); value = (num_zeroes << 4) | category; if (huffman_encode(ac_table, value)) return -1; if (put_bits(bits, category)) return -1; num_zeroes = 0; } } if (num_zeroes > 0) { if (huffman_encode(ac_table, 0x00)) return -1; } return 0; } /* _jpeg_c_rgb2ycbcr: * C version of the RGB -> YCbCr color conversion routine. Converts 2 pixels * at a time. */ static void _jpeg_c_rgb2ycbcr(intptr_t addr, short *y1, short *cb1, short *cr1, short *y2, short *cb2, short *cr2) { int r, g, b; unsigned int *ptr = (unsigned int *)addr; r = getr32(ptr[0]); g = getg32(ptr[0]); b = getb32(ptr[0]); *y1 = (((r * 76) + (g * 151) + (b * 29)) >> 8) - 128; *cb1 = (((r * -43) + (g * -85) + (b * 128)) >> 8); *cr1 = (((r * 128) + (g * -107) + (b * -21)) >> 8); r = getr32(ptr[1]); g = getg32(ptr[1]); b = getb32(ptr[1]); *y2 = (((r * 76) + (g * 151) + (b * 29)) >> 8) - 128; *cb2 = (((r * -43) + (g * -85) + (b * 128)) >> 8); *cr2 = (((r * 128) + (g * -107) + (b * -21)) >> 8); } /* encode_pass: * Main encoding function. Can be used one time for unoptimized encoding, * or two times for optimized encoding (first pass to gather sample * frequencies to generate optimized huffman tables, second pass to * actually write encoded image). */ static int encode_pass(BITMAP *bmp, int quality) { short y_buf[256], cb_buf[256], cr_buf[256]; short y4[256], cb[64], cr[64], y_blocks_per_mcu; short *y_ptr, *cb_ptr, *cr_ptr; int dc_y, dc_cb, dc_cr; int block_x, block_y, x, y, i; intptr_t addr; _jpeg_io.buffer = _jpeg_io.buffer_start; if (write_header(sampling, greyscale, quality, bmp->w, bmp->h)) return -1; dc_y = dc_cb = dc_cr = 0; for (block_y = 0; block_y < bmp->h; block_y += mcu_h) { for (block_x = 0; block_x < bmp->w; block_x += mcu_w) { addr = (intptr_t)fixed_bmp->line[block_y] + (block_x * 4); y_ptr = y_buf; cb_ptr = cb_buf; cr_ptr = cr_buf; for (y = 0; y < mcu_h; y++) { for (x = 0; x < mcu_w; x += 2) { rgb2ycbcr(addr, y_ptr, cb_ptr, cr_ptr, y_ptr + 1, cb_ptr + 1, cr_ptr + 1); y_ptr += 2; cb_ptr += 2; cr_ptr += 2; addr += 8; } addr += pitch; } if (mcu_w > 8) { if (mcu_h > 8) { /* 411 subsampling */ for (y = 0; y < 8; y++) for (x = 0; x < 8; x++) { cb[(y << 3) | x] = (cb_buf[(y << 5) | (x << 1)] + cb_buf[(y << 5) | (x << 1) | 1] + cb_buf[(y << 5) | (x << 1) | 16] + cb_buf[(y << 5) | (x << 1) | 17]) / 4; cr[(y << 3) | x] = (cr_buf[(y << 5) | (x << 1)] + cr_buf[(y << 5) | (x << 1) | 1] + cr_buf[(y << 5) | (x << 1) | 16] + cr_buf[(y << 5) | (x << 1) | 17]) / 4; y4[(y << 3) | x] = y_buf[(y << 4) | x]; y4[(y << 3) | x | 64] = y_buf[(y << 4) | x | 8]; y4[(y << 3) | x | 128] = y_buf[(y << 4) | x | 128]; y4[(y << 3) | x | 192] = y_buf[(y << 4) | x | 136]; y_blocks_per_mcu = 4; } } else { /* 422 subsampling */ for (y = 0; y < 8; y++) for (x = 0; x < 8; x++) { cb[(y << 3) | x] = (cb_buf[(y << 4) | (x << 1)] + cb_buf[(y << 4) | (x << 1) | 1]) / 2; cr[(y << 3) | x] = (cr_buf[(y << 4) | (x << 1)] + cr_buf[(y << 4) | (x << 1) | 1]) / 2; y4[(y << 3) | x] = y_buf[(y << 4) | x]; y4[(y << 3) | x | 64] = y_buf[(y << 4) | x | 8]; y_blocks_per_mcu = 2; } } y_ptr = y4; cb_ptr = cb; cr_ptr = cr; } else { /* 444 subsampling */ y_ptr = y_buf; cb_ptr = cb_buf; cr_ptr = cr_buf; y_blocks_per_mcu = 1; } for (i = 0; i < y_blocks_per_mcu; i++) { if (encode_block(y_ptr, LUMINANCE, &dc_y)) return -1; y_ptr += 64; } if (!greyscale) { if (encode_block(cb_ptr, CHROMINANCE, &dc_cb) || encode_block(cr_ptr, CHROMINANCE, &dc_cr)) return -1; } if (progress_cb) progress_cb((progress_counter * 100) / progress_total); progress_counter++; } } _jpeg_flush_bits(); _jpeg_putw(CHUNK_EOI); return 0; } /* do_encode: * Encodes specified image in JPG format. */ static int do_encode(BITMAP *bmp, AL_CONST RGB *pal, int quality, int flags, void (*callback)(int)) { unsigned char *tables = NULL; int i, result = -1; jpgalleg_error = JPG_ERROR_NONE; TRACE("############### Encode start ###############"); #ifdef JPGALLEG_MMX if (cpu_capabilities & CPU_MMX) { if (_rgb_r_shift_32 == 0) rgb2ycbcr = _jpeg_mmx_rgb2ycbcr; else if (_rgb_r_shift_32 == 16) rgb2ycbcr = _jpeg_mmx_bgr2ycbcr; else rgb2ycbcr = _jpeg_c_rgb2ycbcr; } else #endif rgb2ycbcr = _jpeg_c_rgb2ycbcr; quality = MID(1, quality, 100); sampling = flags & 0xf; if ((sampling != JPG_SAMPLING_411) && (sampling != JPG_SAMPLING_422) && (sampling != JPG_SAMPLING_444)) { TRACE("Unknown sampling specified in flags parameter"); return -1; } greyscale = flags & JPG_GREYSCALE; if (greyscale) sampling = JPG_SAMPLING_444; mcu_w = 8 * (sampling == JPG_SAMPLING_444 ? 1 : 2); mcu_h = 8 * (sampling != JPG_SAMPLING_411 ? 1 : 2); fixed_bmp = create_bitmap_ex(32, (bmp->w + mcu_w - 1) & ~(mcu_w - 1), (bmp->h + mcu_h - 1) & ~(mcu_h - 1)); if (!fixed_bmp) { TRACE("Out of memory"); return -1; } if (pal) select_palette(pal); blit(bmp, fixed_bmp, 0, 0, 0, 0, bmp->w, bmp->h); if (pal) unselect_palette(); for (i = bmp->w; i < fixed_bmp->w; i++) blit(fixed_bmp, fixed_bmp, bmp->w - 1, 0, i, 0, 1, bmp->h); for (i = bmp->h; i < fixed_bmp->h; i++) blit(fixed_bmp, fixed_bmp, 0, bmp->h - 1, 0, i, fixed_bmp->w, 1); pitch = (int)(fixed_bmp->line[1] - fixed_bmp->line[0]) - (mcu_w * 4); progress_cb = callback; progress_counter = 0; progress_total = (fixed_bmp->w / mcu_w) * (fixed_bmp->h / mcu_h) * (flags & JPG_OPTIMIZE ? 2 : 1); TRACE("Saving %dx%d %s image in %s mode, quality %d%s", bmp->w, bmp->h, greyscale ? "greyscale" : "color", sampling == JPG_SAMPLING_444 ? "444" : (sampling == JPG_SAMPLING_422 ? "422" : "411"), quality, current_pass == PASS_COMPUTE_HUFFMAN ? " (first pass)" : ""); if (flags & JPG_OPTIMIZE) { tables = calloc(1, 1092); if (!tables) { jpgalleg_error = JPG_ERROR_OUT_OF_MEMORY; goto exit_error; } num_codes_dc_luminance = tables; num_codes_dc_chrominance = tables + 17; num_codes_ac_luminance = tables + 34; num_codes_ac_chrominance = tables + 51; val_dc_luminance = tables + 68; val_dc_chrominance = tables + 324; val_ac_luminance = tables + 580; val_ac_chrominance = tables + 836; current_pass = PASS_COMPUTE_HUFFMAN; result = encode_pass(bmp, quality); if (result) { TRACE("First pass failed"); goto exit_error; } result |= build_huffman_table(&_jpeg_huffman_dc_table[0], num_codes_dc_luminance, val_dc_luminance); result |= build_huffman_table(&_jpeg_huffman_ac_table[0], num_codes_ac_luminance, val_ac_luminance); if (!(flags & JPG_GREYSCALE)) { result |= build_huffman_table(&_jpeg_huffman_dc_table[1], num_codes_dc_chrominance, val_dc_chrominance); result |= build_huffman_table(&_jpeg_huffman_ac_table[1], num_codes_ac_chrominance, val_ac_chrominance); } if (result) { TRACE("Failed building optimized huffman tables"); goto exit_error; } } else { num_codes_dc_luminance = (unsigned char *)default_num_codes_dc_luminance; num_codes_dc_chrominance = (unsigned char *)default_num_codes_dc_chrominance; num_codes_ac_luminance = (unsigned char *)default_num_codes_ac_luminance; num_codes_ac_chrominance = (unsigned char *)default_num_codes_ac_chrominance; val_dc_luminance = (unsigned char *)default_val_dc_luminance; val_dc_chrominance = (unsigned char *)default_val_dc_chrominance; val_ac_luminance = (unsigned char *)default_val_ac_luminance; val_ac_chrominance = (unsigned char *)default_val_ac_chrominance; } current_pass = PASS_WRITE; result = encode_pass(bmp, quality); exit_error: destroy_bitmap(fixed_bmp); if (tables) free(tables); TRACE("################ Encode end ################"); return result; } /* save_jpg: * Saves specified BITMAP into a JPG file with quality 75, no subsampling * and no progress callback. */ int save_jpg(AL_CONST char *filename, BITMAP *bmp, AL_CONST RGB *palette) { return save_jpg_ex(filename, bmp, palette, DEFAULT_QUALITY, DEFAULT_FLAGS, NULL); } /* save_jpg_ex: * Saves a BITMAP into a JPG file using given quality, subsampling mode and * progress callback. */ int save_jpg_ex(AL_CONST char *filename, BITMAP *bmp, AL_CONST RGB *palette, int quality, int flags, void (*callback)(int progress)) { PACKFILE *f; PALETTE pal; int result, size; if (!palette) palette = pal; size = (bmp->w * bmp->h * 3) + 1000; /* This extimation should be more than enough in all cases */ _jpeg_io.buffer = _jpeg_io.buffer_start = (unsigned char *)malloc(size); _jpeg_io.buffer_end = _jpeg_io.buffer_start + size; if (!_jpeg_io.buffer) { TRACE("Out of memory"); jpgalleg_error = JPG_ERROR_OUT_OF_MEMORY; return -1; } f = pack_fopen(filename, F_WRITE); if (!f) { TRACE("Cannot open %s for writing", filename); jpgalleg_error = JPG_ERROR_WRITING_FILE; free(_jpeg_io.buffer); return -1; } TRACE("Saving JPG to file %s", filename); result = do_encode(bmp, palette, quality, flags, callback); if (!result) pack_fwrite(_jpeg_io.buffer_start, _jpeg_io.buffer - _jpeg_io.buffer_start, f); free(_jpeg_io.buffer_start); pack_fclose(f); return result; } /* save_memory_jpg: * Saves a BITMAP in JPG format and stores it into a memory buffer. The JPG * is saved with quality 75, no subsampling and no progress callback. */ int save_memory_jpg(void *buffer, int *size, BITMAP *bmp, AL_CONST RGB *palette) { return save_memory_jpg_ex(buffer, size, bmp, palette, DEFAULT_QUALITY, DEFAULT_FLAGS, NULL); } /* save_memory_jpg_ex: * Saves a BITMAP in JPG format using given quality and subsampling settings * and stores it into a memory buffer. */ int save_memory_jpg_ex(void *buffer, int *size, BITMAP *bmp, AL_CONST RGB *palette, int quality, int flags, void (*callback)(int progress)) { int result; if (!buffer) { TRACE("Invalid buffer pointer"); return -1; } TRACE("Saving JPG to memory buffer at %p (size = %d)", buffer, *size); _jpeg_io.buffer = _jpeg_io.buffer_start = buffer; _jpeg_io.buffer_end = _jpeg_io.buffer_start + *size; *size = 0; result = do_encode(bmp, palette, quality, flags, callback); if (result == 0) *size = _jpeg_io.buffer - _jpeg_io.buffer_start; return result; } allegro4.4-4.4.2/addons/jpgalleg/src/error.c000066400000000000000000000034671173507505700205410ustar00rootroot00000000000000/* * __ _____ ______ ______ ___ ___ * /\ \ /\ _ `\ /\ ___\ /\ _ \ /\_ \ /\_ \ * \ \ \\ \ \L\ \\ \ \__/ \ \ \L\ \\//\ \ \//\ \ __ __ * __ \ \ \\ \ __| \ \ \ __\ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\ * /\ \_\/ / \ \ \/ \ \ \L\ \\ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ * \ \____// \ \_\ \ \____/ \ \_\ \_\/\____\/\____\ \____\ \____ \ * \/____/ \/_/ \/___/ \/_/\/_/\/____/\/____/\/____/\/___L\ \ * /\____/ * \_/__/ * * Version 2.6, by Angelo Mottola, 2000-2006 * * Error reporting utility function. * * See the readme.txt file for instructions on using this package in your * own programs. * */ #include /* * jpgalleg_error_string: * Returns the latest error message string. */ const char *jpgalleg_error_string(void) { switch (jpgalleg_error) { case JPG_ERROR_NONE: return "No error"; case JPG_ERROR_READING_FILE: return "File read error"; case JPG_ERROR_WRITING_FILE: return "File write error"; case JPG_ERROR_INPUT_BUFFER_TOO_SMALL: return "Input memory buffer too small"; case JPG_ERROR_OUTPUT_BUFFER_TOO_SMALL: return "Output memory buffer too small"; case JPG_ERROR_HUFFMAN: return "Huffman compression error"; case JPG_ERROR_NOT_JPEG: return "Not a valid JPEG"; case JPG_ERROR_UNSUPPORTED_ENCODING: return "Unsupported encoding"; case JPG_ERROR_UNSUPPORTED_COLOR_SPACE: return "Unsupported color space"; case JPG_ERROR_UNSUPPORTED_DATA_PRECISION: return "Unsupported data precision"; case JPG_ERROR_BAD_IMAGE: return "Image data is corrupted"; case JPG_ERROR_OUT_OF_MEMORY: return "Out of memory"; } return "Unknown error"; } allegro4.4-4.4.2/addons/jpgalleg/src/i386/000077500000000000000000000000001173507505700177235ustar00rootroot00000000000000allegro4.4-4.4.2/addons/jpgalleg/src/i386/color.s000066400000000000000000000255501173507505700212340ustar00rootroot00000000000000/* * __ _____ ______ ______ ___ ___ * /\ \ /\ _ `\ /\ ___\ /\ _ \ /\_ \ /\_ \ * \ \ \\ \ \L\ \\ \ \__/ \ \ \L\ \\//\ \ \//\ \ __ __ * __ \ \ \\ \ __| \ \ \ __\ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\ * /\ \_\/ / \ \ \/ \ \ \L\ \\ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ * \ \____// \ \_\ \ \____/ \ \_\ \_\/\____\/\____\ \____\ \____ \ * \/____/ \/_/ \/___/ \/_/\/_/\/____/\/____/\/____/\/___L\ \ * /\____/ * \_/__/ * * Version 2.6, by Angelo Mottola, 2000-2006 * * MMX optimized YCbCr <--> RGB color conversion routines. * * See the readme.txt file for instructions on using this package in your * own programs. */ #include #ifdef JPGALLEG_MMX #define FUNC(name) .globl _##name ; .balign 8, 0x90 ; _##name: #define GLOBL(name) _##name #define ARG1 8(%ebp) #define ARG2 12(%ebp) #define ARG3 16(%ebp) #define ARG4 20(%ebp) #define ARG5 24(%ebp) #define ARG6 28(%ebp) #define ARG7 32(%ebp) #define ARG8 36(%ebp) #define ARG9 40(%ebp) #define ARG10 44(%ebp) #define ARG11 48(%ebp) #define ARG12 52(%ebp) #define ARG13 56(%ebp) .data .balign 16, 0x90 /* 10.6 factors */ f_const_0: .short -27, -5, -11, -21 f_const_1: .short 19, 38, 7, 0 f_const_2: .short -21, -11, -5, -27 f_const_3: .short 7, 38, 19, 0 i_const_0: .short 64, 113, 64, 90 i_const_1: .short -22, -46, -22, -46 i_const_2: .short 64, 90, 64, 113 i_const_3: .short -46, -22, -46, -22 level_shift: .short 128, 128, 128, 128 .text /* * void * _jpeg_mmx_ycbcr2bgr(int addr, int y1, int cb1, int cr1, int y2, int cb2, int cr2, int y3, int cb3, int cr3, int y4, int cb4, int cr4) */ FUNC(_jpeg_mmx_ycbcr2bgr) pushl %ebp; movl %esp, %ebp; pushl %edi; movl ARG1, %edi; movd ARG2, %mm0; movd ARG3, %mm1; movd ARG4, %mm2; movd ARG5, %mm3; movd ARG6, %mm4; movd ARG7, %mm5; punpcklwd %mm2, %mm1; /* mm1 = | | | cr1 | cb1 | */ punpcklwd %mm5, %mm4; /* mm4 = | | | cr2 | cb2 | */ punpcklwd %mm0, %mm0; /* mm0 = | | | y1 | y1 | */ punpckldq %mm4, %mm1; /* mm1 = | cr2 | cb2 | cr1 | cb1 | */ movq %mm0, %mm5; punpcklwd %mm3, %mm3; /* mm3 = | | | y2 | y2 | */ psubw (level_shift), %mm1; punpckldq %mm3, %mm5; /* mm5 = | y2 | y2 | y1 | y1 | */ punpcklwd %mm1, %mm0; /* mm0 = | cr1 | y1 | cb1 | y1 | */ movq %mm5, %mm6; pmaddwd (i_const_0), %mm0; punpckhwd %mm1, %mm6; /* mm6 = | cr2 | y2 | cb2 | y2 | */ psrad $6, %mm0; /* mm0 = | r1 | b1 | */ pmaddwd (i_const_0), %mm6; psllw $6, %mm5; pmaddwd (i_const_1), %mm1; psrad $6, %mm6; /* mm6 = | r2 | b2 | */ paddw %mm5, %mm1; psraw $6, %mm1; /* mm1 = | g2 | g1 | */ movq %mm0, %mm7; psrlq $32, %mm0; punpcklwd %mm1, %mm7; /* mm7 = | | g1 | b1 | */ punpcklwd %mm6, %mm0; /* mm0 = | | b2 | r1 | */ punpckldq %mm0, %mm7; /* mm7 = | b2 | r1 | g1 | b1 | */ punpckhwd %mm6, %mm1; /* mm1 = | | r2 | g2 | */ packuswb %mm1, %mm7; /* mm7 = | | |r2|g2|b2|r1|g1|b1| */ movd ARG8, %mm0; movd ARG9, %mm1; movd ARG10, %mm2; movd ARG11, %mm3; movd ARG12, %mm4; movd ARG13, %mm5; punpcklwd %mm2, %mm1; /* mm1 = | | | cr3 | cb3 | */ punpcklwd %mm5, %mm4; /* mm4 = | | | cr4 | cb4 | */ punpcklwd %mm0, %mm0; /* mm0 = | | | y3 | y3 | */ punpckldq %mm4, %mm1; /* mm1 = | cr4 | cb4 | cr3 | cb3 | */ movq %mm0, %mm5; punpcklwd %mm3, %mm3; /* mm3 = | | | y4 | y4 | */ psubw (level_shift), %mm1; punpckldq %mm3, %mm5; /* mm5 = | y4 | y4 | y3 | y3 | */ punpcklwd %mm1, %mm0; /* mm0 = | cr3 | y3 | cb3 | y3 | */ movq %mm5, %mm6; pmaddwd (i_const_0), %mm0; punpckhwd %mm1, %mm6; /* mm6 = | cr4 | y4 | cb4 | y4 | */ psrad $6, %mm0; /* mm0 = | r3 | b3 | */ pmaddwd (i_const_0), %mm6; psllw $6, %mm5; pmaddwd (i_const_1), %mm1; psrad $6, %mm6; /* mm6 = | r4 | b4 | */ paddw %mm5, %mm1; psraw $6, %mm1; /* mm1 = | g4 | g3 | */ movq %mm0, %mm2; punpcklwd %mm1, %mm0; /* mm0 = | | g3 | b3 | */ psrlq $32, %mm2; punpcklwd %mm6, %mm2; /* mm2 = | | b4 | r3 | */ punpckhwd %mm6, %mm1; /* mm1 = | | r4 | g4 | */ punpckldq %mm1, %mm2; /* mm2 = | r4 | g4 | b4 | r3 | */ movq %mm7, %mm3; packuswb %mm0, %mm2; /* mm2 = | | |g3|b3|r4|g4|b4|r3| */ punpckhwd %mm2, %mm3; /* mm3 = | |g3|b3|r2|g2| */ punpckldq %mm3, %mm7; /* mm7 = |g3|b3|r2|g2|b2|r1|g1|b1| */ movd %mm2, 8(%edi); movq %mm7, (%edi); emms; popl %edi; popl %ebp; ret; /* * void * _jpeg_mmx_ycbcr2rgb(int addr, int y1, int cb1, int cr1, int y2, int cb2, int cr2, int y3, int cb3, int cr3, int y4, int cb4, int cr4) */ FUNC(_jpeg_mmx_ycbcr2rgb) pushl %ebp; movl %esp, %ebp; pushl %edi; movl ARG1, %edi; movd ARG2, %mm0; movd ARG3, %mm1; movd ARG4, %mm2; movd ARG5, %mm3; movd ARG6, %mm4; movd ARG7, %mm5; punpcklwd %mm1, %mm2; /* mm2 = | | | cb1 | cr1 | */ punpcklwd %mm4, %mm5; /* mm5 = | | | cb2 | cr2 | */ punpcklwd %mm0, %mm0; /* mm0 = | | | y1 | y1 | */ punpckldq %mm5, %mm2; /* mm2 = | cb2 | cr2 | cb1 | cr1 | */ movq %mm0, %mm5; punpcklwd %mm3, %mm3; psubw (level_shift), %mm2; punpckldq %mm3, %mm3; /* mm3 = | y2 | y2 | y2 | y2 | */ punpckldq %mm3, %mm5; /* mm5 = | y2 | y2 | y1 | y1 | */ punpcklwd %mm2, %mm0; /* mm0 = | cb1 | y1 | cr1 | y1 | */ punpckhwd %mm2, %mm3; /* mm3 = | cb2 | y2 | cr2 | y2 | */ psllw $6, %mm5; pmaddwd (i_const_3), %mm2; pmaddwd (i_const_2), %mm0; pmaddwd (i_const_2), %mm3; paddw %mm5, %mm2; psrad $6, %mm0; /* mm0 = | b1 | r1 | */ psrad $6, %mm3; /* mm3 = | b2 | r2 | */ psraw $6, %mm2; /* mm2 = | g2 | g1 | */ movq %mm0, %mm7; psrlq $32, %mm0; punpcklwd %mm2, %mm7; /* mm7 = | | g1 | r1 | */ punpcklwd %mm3, %mm0; /* mm0 = | | r2 | b1 | */ punpckldq %mm0, %mm7; /* mm7 = | r2 | b1 | g1 | r1 | */ punpckhwd %mm3, %mm2; /* mm2 = | | b2 | g2 | */ packuswb %mm2, %mm7; /* mm7 = | |b2|g2|r2|b1|g1|r1| */ movd ARG8, %mm0; movd ARG9, %mm1; movd ARG10, %mm2; movd ARG11, %mm3; movd ARG12, %mm4; movd ARG13, %mm5; punpcklwd %mm1, %mm2; /* mm2 = | | | cb1 | cr1 | */ punpcklwd %mm4, %mm5; /* mm5 = | | | cb2 | cr2 | */ punpcklwd %mm0, %mm0; /* mm0 = | | | y1 | y1 | */ punpckldq %mm5, %mm2; /* mm2 = | cb2 | cr2 | cb1 | cr1 | */ movq %mm0, %mm5; punpcklwd %mm3, %mm3; psubw (level_shift), %mm2; punpckldq %mm3, %mm3; /* mm3 = | y2 | y2 | y2 | y2 | */ punpckldq %mm3, %mm5; /* mm5 = | y2 | y2 | y1 | y1 | */ punpcklwd %mm2, %mm0; /* mm0 = | cb1 | y1 | cr1 | y1 | */ punpckhwd %mm2, %mm3; /* mm3 = | cb2 | y2 | cr2 | y2 | */ psllw $6, %mm5; pmaddwd (i_const_3), %mm2; pmaddwd (i_const_2), %mm0; pmaddwd (i_const_2), %mm3; paddw %mm5, %mm2; psrad $6, %mm0; /* mm0 = | b3 | r3 | */ psrad $6, %mm3; /* mm3 = | b4 | r4 | */ psraw $6, %mm2; /* mm2 = | g4 | g3 | */ movq %mm0, %mm1; punpcklwd %mm2, %mm1; /* mm1 = | | g3 | r3 | */ punpckhwd %mm3, %mm2; /* mm2 = | | b4 | g4 | */ psrlq $32, %mm0; punpcklwd %mm3, %mm0; /* mm0 = | | r4 | b3 | */ punpckldq %mm2, %mm0; /* mm0 = | b4 | g4 | r4 | b3 | */ movq %mm7, %mm4; packuswb %mm1, %mm0; /* mm0 = | |g3|r3|b4|g4|r4|b3| */ punpckhwd %mm0, %mm4; /* mm4 = | |g3|r3|b2|g2| */ punpckldq %mm4, %mm7; /* mm7 = |g3|r3|b2|g2|r2|b1|g1|r1| */ movd %mm0, 8(%edi); movq %mm7, (%edi); emms; popl %edi; popl %ebp; ret; /* * void * _jpeg_mmx_rgb2ycbcr(int addr, short *y1, short *cb1, short *cr1, short *y2, short *cb2, short *cr2) */ FUNC(_jpeg_mmx_rgb2ycbcr) pushl %ebp; movl %esp, %ebp; pushl %edi; movl ARG1, %edi; movq (%edi), %mm0; /* mm0 = | |b2|g2|r2| |b1|g1|r1| */ pxor %mm2, %mm2; movq %mm0, %mm1; punpcklbw %mm2, %mm0; /* mm0 = | | b1 | g1 | r1 | */ punpckhbw %mm2, %mm1; /* mm1 = | | b2 | g2 | r2 | */ movq %mm0, %mm3; movq %mm1, %mm4; movq %mm0, %mm5; movq %mm1, %mm6; psrlq $16, %mm3; psrlq $16, %mm4; punpckldq %mm0, %mm3; /* mm3 = | g1 | r1 | b1 | g1 | */ punpckldq %mm1, %mm4; /* mm4 = | g2 | r2 | b2 | g2 | */ pmaddwd (f_const_0), %mm3; pmaddwd (f_const_0), %mm4; pmaddwd (f_const_1), %mm5; pmaddwd (f_const_1), %mm6; movq %mm5, %mm2; psraw $6, %mm3; psraw $6, %mm4; punpckldq %mm6, %mm5; /* mm5 = | r2+g2 | r1+g1 | */ punpckhdq %mm6, %mm2; /* mm2 = | b2 | b1 | */ psrlw $1, %mm0; psrlw $1, %mm1; paddw %mm5, %mm2; paddw %mm0, %mm3; /* mm3 = | | cb1 | | cr1 | */ psraw $6, %mm2; paddw %mm1, %mm4; /* mm4 = | | cb2 | | cr2 | */ psubw (level_shift), %mm2;/* mm2 = | | y2 | | y1 | */ movl ARG2, %edi; movd %mm2, %eax; movw %ax, (%edi); movl ARG4, %edi; movd %mm3, %eax; movw %ax, (%edi); movl ARG7, %edi; movd %mm4, %eax; movw %ax, (%edi); psrlq $32, %mm2; movl ARG5, %edi; movd %mm2, %eax; movw %ax, (%edi); psrlq $32, %mm3; movl ARG3, %edi; movd %mm3, %eax; movw %ax, (%edi); psrlq $32, %mm4; movl ARG6, %edi; movd %mm4, %eax; movw %ax, (%edi); emms; popl %edi; popl %ebp; ret; /* * void * _jpeg_mmx_bgr2ycbcr(int addr, short *y1, short *cb1, short *cr1, short *y2, short *cb2, short *cr2) */ FUNC(_jpeg_mmx_bgr2ycbcr) pushl %ebp; movl %esp, %ebp; pushl %edi; movl ARG1, %edi; movq (%edi), %mm0; /* mm0 = | |r2|g2|b2| |r1|g1|b1| */ pxor %mm2, %mm2; movq %mm0, %mm1; punpcklbw %mm2, %mm0; /* mm0 = | | r1 | g1 | b1 | */ punpckhbw %mm2, %mm1; /* mm1 = | | r2 | g2 | b2 | */ movq %mm0, %mm3; movq %mm1, %mm4; movq %mm0, %mm5; movq %mm1, %mm6; psrlq $16, %mm3; psrlq $16, %mm4; punpckldq %mm0, %mm3; /* mm3 = | g1 | b1 | r1 | g1 | */ punpckldq %mm1, %mm4; /* mm4 = | g2 | b2 | r2 | g2 | */ pmaddwd (f_const_2), %mm3; pmaddwd (f_const_2), %mm4; pmaddwd (f_const_3), %mm5; pmaddwd (f_const_3), %mm6; movq %mm5, %mm2; psraw $6, %mm3; psraw $6, %mm4; punpckldq %mm6, %mm5; /* mm5 = | g2+b2 | g1+b1 | */ punpckhdq %mm6, %mm2; /* mm2 = | r2 | r1 | */ psrlw $1, %mm0; psrlw $1, %mm1; paddw %mm5, %mm2; paddw %mm0, %mm3; /* mm3 = | | cr1 | | cb1 | */ psraw $6, %mm2; paddw %mm1, %mm4; /* mm4 = | | cr2 | | cb2 | */ psubw (level_shift), %mm2;/* mm2 = | | y2 | | y1 | */ movl ARG2, %edi; movd %mm2, %eax; movw %ax, (%edi); movl ARG3, %edi; movd %mm3, %eax; movw %ax, (%edi); movl ARG6, %edi; movd %mm4, %eax; movw %ax, (%edi); psrlq $32, %mm2; movl ARG5, %edi; movd %mm2, %eax; movw %ax, (%edi); psrlq $32, %mm3; movl ARG4, %edi; movd %mm3, %eax; movw %ax, (%edi); psrlq $32, %mm4; movl ARG7, %edi; movd %mm4, %eax; movw %ax, (%edi); emms; popl %edi; popl %ebp; ret; #endif allegro4.4-4.4.2/addons/jpgalleg/src/i386/dct.s000066400000000000000000000251531173507505700206670ustar00rootroot00000000000000/* * __ _____ ______ ______ ___ ___ * /\ \ /\ _ `\ /\ ___\ /\ _ \ /\_ \ /\_ \ * \ \ \\ \ \L\ \\ \ \__/ \ \ \L\ \\//\ \ \//\ \ __ __ * __ \ \ \\ \ __| \ \ \ __\ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\ * /\ \_\/ / \ \ \/ \ \ \L\ \\ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ * \ \____// \ \_\ \ \____/ \ \_\ \_\/\____\/\____\ \____\ \____ \ * \/____/ \/_/ \/___/ \/_/\/_/\/____/\/____/\/____/\/___L\ \ * /\____/ * \_/__/ * * Version 2.6, by Angelo Mottola, 2000-2006 * * (Inverse) Discrete Cosine Transform MMX optimized routine. * * See the readme.txt file for instructions on using this package in your * own programs. */ #include #include #ifdef JPGALLEG_MMX #define FUNC(name) .globl _##name ; .balign 8, 0x90 ; _##name: #define GLOBL(name) _##name #define ARG1 8(%ebp) #define ARG2 12(%ebp) #define ARG3 16(%ebp) #define ARG4 20(%ebp) .data .balign 16, 0x90 const_0: .short 0, 0, IFIX_1_414213562, 0 const_1: .short 1, 1, IFIX_1_847759065, IFIX_1_847759065 const_2: .short IFIX_1_414213562, -IFIX_1_414213562, 0, 0 const_3: .short -IFIX_2_613125930, 0, IFIX_1_082392200, 0 const_4: .short 1, 0, -1, 0 const_5: .short 0, IFIX_1_414213562, 0, 1 const_6: .short 1, 1, -1, -1 const_7: .short 1, 1, -IFIX_1_414213562, IFIX_1_414213562 const_8: .short 0, 0, IFIX_1_847759065, IFIX_1_847759065 const_9: .short -1, 0, 1, 0 const_10: .short 1, -1, 1, 1 const_11: .short 1, 1, -1, -1 const_12: .short 128, 128, 128, 128 const_13: .short IFIX_1_082392200, 0, -IFIX_2_613125930, 0 const_14: .short 0, 0, 0xFFFF, 0 .text /* * void * _jpeg_mmx_idct(short *data, short *output, short *dequant, short *workspace) */ FUNC(_jpeg_mmx_idct) pushl %ebp; movl %esp, %ebp; pushl %edi; pushl %esi; pushl %ebx; movl ARG1, %esi; movl ARG4, %edi; movl ARG3, %ebx; movl $8, %ecx; .balign 16, 0x90 pass_1: movw 16(%esi), %ax; orw 32(%esi), %ax; orw 48(%esi), %ax; orw 64(%esi), %ax; orw 80(%esi), %ax; orw 96(%esi), %ax; orw 112(%esi), %ax; jnz pass_1_start; movw (%esi), %ax; imulw (%ebx); movw %ax, (%edi); movw %ax, 16(%edi); movw %ax, 32(%edi); movw %ax, 48(%edi); movw %ax, 64(%edi); movw %ax, 80(%edi); movw %ax, 96(%edi); movw %ax, 112(%edi); addl $2, %esi; addl $2, %ebx; addl $2, %edi; decl %ecx; jnz pass_1; jmp pass_1_end; pass_1_start: movw (%esi), %ax; shll $16, %eax; movw 64(%esi), %ax; movd %eax, %mm0; /* mm0 = | | | i[0] | i[32] | */ negw %ax; movd %eax, %mm1; /* mm1 = | | | i[0] | -i[32]| */ punpckldq %mm1, %mm0; /* mm0 = | i[0] | -i[32]| i[0] | i[32] | */ movw (%ebx), %ax; shll $16, %eax; movw 64(%ebx), %ax; movd %eax, %mm1; punpckldq %mm1, %mm1; /* mm1 = | q[0] | q[32] | q[0] | q[32] | */ pmaddwd %mm1, %mm0; /* mm0 = | tmp11 | tmp10 | */ movw 32(%esi), %ax; shll $16, %eax; movw 96(%esi), %ax; movd %eax, %mm1; /* mm1 = | | i[16] | i[48] | */ negw %ax; movd %eax, %mm2; punpckldq %mm2, %mm1; /* mm1 = | i[16] | -i[48]| i[16] | i[48] | */ movw 32(%ebx), %ax; shll $16, %eax; movw 96(%ebx), %ax; movd %eax, %mm2; punpckldq %mm2, %mm2; /* mm2 = | q[16] | q[48] | q[16] | q[48] | */ pmaddwd %mm2, %mm1; /* mm1 = | (tmp1 - tmp3) | tmp13 | */ movq %mm1, %mm2; pmaddwd (const_0), %mm2; psrad $8, %mm2; psrlq $32, %mm2; psubw %mm1, %mm2; /* mm2 = | ? | tmp12 | */ punpckldq %mm2, %mm1; /* mm1 = | tmp12 | tmp13 | */ movq %mm0, %mm3; paddw %mm1, %mm0; /* mm0 = | tmp1 | tmp0 | */ psubw %mm1, %mm3; /* mm3 = | tmp2 | tmp3 | */ movw 16(%esi), %ax; shll $16, %eax; movw 112(%esi), %ax; movd %eax, %mm1; negw %ax; movd %eax, %mm2; punpckldq %mm2, %mm1 /* mm1 = | i[8] | -i[56]| i[8] | i[56] | */ movw 16(%ebx), %ax; shll $16, %eax; movw 112(%ebx), %ax; movd %eax, %mm2; punpckldq %mm2, %mm2; /* mm2 = | q[8] | q[56] | q[8] | q[56] | */ pmaddwd %mm2, %mm1; /* mm1 = | z12 | z11 | */ movw 80(%esi), %ax; shll $16, %eax; movw 48(%esi), %ax; movd %eax, %mm2; negw %ax; movd %eax, %mm4; punpckldq %mm4, %mm2; /* mm2 = | i[40] | -i[24]| i[40] | i[24] | */ movw 80(%ebx), %ax; shll $16, %eax; movw 48(%ebx), %ax; movd %eax, %mm4; punpckldq %mm4, %mm4; /* mm4 = | q[40] | q[24] | q[40] | q[24] | */ pmaddwd %mm4, %mm2; /* mm2 = | z10 | z13 | */ movq %mm1, %mm5; movq %mm1, %mm6; punpcklwd %mm2, %mm5; /* mm5 = | | z13 | z11 | */ punpckhwd %mm2, %mm6; /* mm6 = | | z10 | z12 | */ punpckldq %mm6, %mm5; movq %mm5, %mm4; /* mm4 = | z10 | z12 | z13 | z11 | */ pmaddwd (const_1), %mm5; movq %mm5, %mm6; /* mm5 = | ? | tmp7 | */ psrad $8, %mm6; /* mm6 = | z5 | ? | */ pmaddwd (const_2), %mm4; packssdw %mm1, %mm2; /* mm2 = | z12 | z11 | z10 | z13 | */ psrlq $16, %mm2; /* mm2 = | | z12 | ? | z10 | */ punpckhdq %mm6, %mm6; pmaddwd (const_3), %mm2; pmullw (const_4), %mm6; /* mm6 = | -z5 | z5 | */ psrad $8, %mm2; psrad $8, %mm4; /* mm4 = | | tmp11 | */ paddw %mm6, %mm2; /* mm2 = | tmp10 | tmp12 | */ movq %mm2, %mm1; psubw %mm5, %mm1; /* mm1 = | ? | tmp6 | */ punpckldq %mm1, %mm5; /* mm5 = | tmp6 | tmp7 | */ psubw %mm1, %mm4; /* mm4 = | ? | tmp5 | */ psrlq $32, %mm2; punpckldq %mm4, %mm4; paddw %mm2, %mm4; /* mm4 = | tmp5 | tmp4 | */ movq %mm0, %mm1; movq %mm3, %mm2; paddw %mm5, %mm1; /* mm1 = | w[8] | w[0] | */ paddw %mm4, %mm2; /* mm2 = | w[16] | w[32] | */ psubw %mm5, %mm0; /* mm0 = | w[48] | w[56] | */ psubw %mm4, %mm3; /* mm3 = | w[40] | w[24] | */ movd %mm1, %eax; movd %mm2, %edx; movw %ax, (%edi); movw %dx, 64(%edi); movd %mm0, %eax; movd %mm3, %edx; movw %ax, 112(%edi); movw %dx, 48(%edi); psrlq $32, %mm1; psrlq $32, %mm2; psrlq $32, %mm0; psrlq $32, %mm3; movd %mm1, %eax; movd %mm2, %edx; movw %ax, 16(%edi); movw %dx, 32(%edi); movd %mm0, %eax; movd %mm3, %edx; movw %ax, 96(%edi); movw %dx, 80(%edi); addl $2, %esi; addl $2, %ebx; addl $2, %edi; decl %ecx; jnz pass_1; pass_1_end: movl ARG4, %esi; movl ARG2, %edi; movl $8, %ecx; pass_2: movd (%esi), %mm0; punpcklwd %mm0, %mm0; /* mm0 = | | w[0] | w[0] | */ movw 8(%esi), %ax; movd %eax, %mm1; negw %ax; movd %eax, %mm2; punpcklwd %mm2, %mm1; /* mm1 = | | -w[4] | w[4] | */ movd 4(%esi), %mm3; punpcklwd %mm3, %mm3; /* mm3 = | | w[2] | w[2] | */ movw 12(%esi), %ax; movd %eax, %mm4; negw %ax; movd %eax, %mm2; punpcklwd %mm4, %mm2; /* mm2 = | | w[6] | -w[6] | */ punpckldq %mm3, %mm0; /* mm0 = | w[2] | w[2] | w[0] | w[0] | */ punpckldq %mm2, %mm1; /* mm1 = | w[6] | -w[6] | -w[4] | w[4] | */ paddw %mm1, %mm0; /* mm0 = | tmp13 |~tmp12 | tmp11 | tmp10 | */ punpckhwd %mm0, %mm4; /* mm4 = | tmp13 | ? |~tmp12 | ? | */ movq %mm4, %mm2; pmaddwd (const_5), %mm4; psrlq $48, %mm2; /* mm2 = | | tmp13 | */ psrad $8, %mm4; psubw %mm2, %mm4; /* mm4 = | | tmp12 | */ punpcklwd %mm4, %mm2; /* mm2 = | | tmp12 | tmp13 | */ punpckldq %mm0, %mm0; /* mm0 = | tmp11 | tmp10 | tmp11 | tmp10 | */ punpckldq %mm2, %mm2; pmullw (const_6), %mm2; /* mm2 = |-tmp12 |-tmp13 | tmp12 | tmp13 | */ paddw %mm2, %mm0; /* mm0 = | tmp2 | tmp3 | tmp1 | tmp0 | */ movd 10(%esi), %mm1; movd 2(%esi), %mm4; movq %mm1, %mm2; punpcklwd %mm4, %mm1; /* mm1 = | | w[1] | w[5] | */ punpcklwd %mm2, %mm4; /* mm4 = | | w[5] | w[1] | */ punpckldq %mm4, %mm1; /* mm1 = | w[5] | w[1] | w[1] | w[5] | */ movd 6(%esi), %mm2; movd 14(%esi), %mm3; movq %mm2, %mm4; punpcklwd %mm3, %mm2; /* mm2 = | | w[7] | w[3] | */ punpcklwd %mm4, %mm3; /* mm3 = | | w[3] | w[7] | */ punpckldq %mm3, %mm2; /* mm2 = | w[3] | w[7] | w[7] | w[3] | */ pmullw (const_11), %mm2;/* mm2 = | -w[3] | -w[7] | w[7] | w[3] | */ paddw %mm2, %mm1; /* mm1 = | z10 | z12 | z11 | z13 | */ movq %mm1, %mm3; movq %mm1, %mm4; punpckldq %mm1, %mm1; pmaddwd (const_7), %mm1;/* mm1 = | ~tmp11 | tmp7 | */ punpckhwd %mm3, %mm3; /* mm3 = | z10 | z10 | z12 | z12 | */ pmaddwd (const_8), %mm4; psrad $8, %mm4; /* mm4 = | z5 | | */ punpckhdq %mm4, %mm4; pmullw (const_9), %mm4; /* mm4 = | z5 | -z5 | */ pmaddwd (const_13), %mm3; psrad $8, %mm3; paddw %mm3, %mm4; /* mm4 = | tmp12 | tmp10 | */ movq %mm1, %mm5; movq %mm4, %mm6; movq %mm4, %mm7; psrad $8, %mm5; /* mm5 = | tmp11 | ? | */ psrlq $32, %mm4; /* mm4 = | | tmp12 | */ punpcklwd %mm1, %mm1; punpckhwd %mm5, %mm5; /* mm5 = | | tmp11 | tmp11 | */ punpckldq %mm1, %mm1; psllq $32, %mm6; /* mm6 = | | tmp10 | | */ psllq $32, %mm5; /* mm5 = | tmp11 | tmp11 | | */ punpckhwd %mm7, %mm7; /* mm7 = | | tmp12 | tmp12 | */ pand (const_14), %mm6; punpckldq %mm4, %mm7; /* mm7 = | | tmp12 | tmp12 | tmp12 | */ psllq $16, %mm7; pmullw (const_10), %mm1;/* mm1 = | tmp7 | tmp7 | -tmp7 | tmp7 | */ pmullw (const_11), %mm7;/* mm7 = |-tmp12 |-tmp12 | tmp12 | | */ paddw %mm6, %mm1; paddw %mm5, %mm1; paddw %mm7, %mm1; /* mm1 = | tmp5 | tmp4 | tmp6 | tmp7 | */ movq %mm0, %mm2; paddw %mm1, %mm0; /* mm0 = | o[2] | o[4] | o[1] | o[0] | */ psubw %mm1, %mm2; /* mm2 = | o[5] | o[3] | o[6] | o[7] | */ psraw $5, %mm0; psraw $5, %mm2; paddw (const_12), %mm0; paddw (const_12), %mm2; movq %mm0, %mm1; movq %mm0, %mm3; psrlq $16, %mm1; /* mm1 = | | o[2] | | */ movq %mm2, %mm4; punpckhwd %mm2, %mm1; /* mm1 = | | o[3] | o[2] | */ movq %mm2, %mm5; punpckldq %mm1, %mm0; /* mm0 = | o[3] | o[2] | o[1] | o[0] | */ psrlq $16, %mm4; /* mm4 = | | o[5] | | */ punpckhwd %mm4, %mm3; /* mm3 = | | o[5] | o[4] | */ psrlq $16, %mm5; /* mm5 = | o[6] | */ punpcklwd %mm2, %mm5; /* mm5 = | | o[7] | o[6] | */ punpckldq %mm5, %mm3; /* mm3 = | o[7] | o[6] | o[5] | o[4] | */ movq %mm0, (%edi); movq %mm3, 8(%edi); addl $16, %esi; addl $16, %edi; decl %ecx; jnz pass_2; emms; popl %ebx; popl %esi; popl %edi; popl %ebp; ret; #endif allegro4.4-4.4.2/addons/jpgalleg/src/init.c000066400000000000000000000034571173507505700203520ustar00rootroot00000000000000/* * __ _____ ______ ______ ___ ___ * /\ \ /\ _ `\ /\ ___\ /\ _ \ /\_ \ /\_ \ * \ \ \\ \ \L\ \\ \ \__/ \ \ \L\ \\//\ \ \//\ \ __ __ * __ \ \ \\ \ __| \ \ \ __\ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\ * /\ \_\/ / \ \ \/ \ \ \L\ \\ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ * \ \____// \ \_\ \ \____/ \ \_\ \_\/\____\/\____\ \____\ \____ \ * \/____/ \/_/ \/___/ \/_/\/_/\/____/\/____/\/____/\/___L\ \ * /\____/ * \_/__/ * * Version 2.6, by Angelo Mottola, 2000-2006 * * Init function and datafile type registration. * * See the readme.txt file for instructions on using this package in your * own programs. * */ #include /* load_datafile_jpg: * Hook function for loading a JPEG object from a datafile. Returns the * decoded JPG into a BITMAP or NULL on error. */ static void * load_datafile_jpg(PACKFILE *f, long size) { BITMAP *bmp; char *buffer; buffer = (char *)malloc(size); if (!buffer) return NULL; pack_fread(buffer, size, f); bmp = load_memory_jpg(buffer, size, NULL); free(buffer); return (void *)bmp; } /* destroy_datafile_jpg: * Hook function for freeing memory of JPEG objects in a loaded datafile. */ static void destroy_datafile_jpg(void *data) { if (data) destroy_bitmap((BITMAP *)data); } /* jpgalleg_init: * Initializes JPGalleg by registering the file format with the Allegro image * handling and datafile subsystems. */ int jpgalleg_init(void) { register_datafile_object(DAT_JPEG, load_datafile_jpg, destroy_datafile_jpg); register_bitmap_file_type("jpg", load_jpg, save_jpg); jpgalleg_error = JPG_ERROR_NONE; return 0; } allegro4.4-4.4.2/addons/jpgalleg/src/io.c000066400000000000000000000113201173507505700200020ustar00rootroot00000000000000/* * __ _____ ______ ______ ___ ___ * /\ \ /\ _ `\ /\ ___\ /\ _ \ /\_ \ /\_ \ * \ \ \\ \ \L\ \\ \ \__/ \ \ \L\ \\//\ \ \//\ \ __ __ * __ \ \ \\ \ __| \ \ \ __\ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\ * /\ \_\/ / \ \ \/ \ \ \L\ \\ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ * \ \____// \ \_\ \ \____/ \ \_\ \_\/\____\/\____\ \____\ \____ \ * \/____/ \/_/ \/___/ \/_/\/_/\/____/\/____/\/____/\/___L\ \ * /\____/ * \_/__/ * * Version 2.6, by Angelo Mottola, 2000-2006 * * Input/output helper routines module. * * See the readme.txt file for instructions on using this package in your * own programs. */ #include static int current_byte = 0; static int bytes_read = 0; static int chunk_len = 0; static void *chunk = NULL; /* _jpeg_getc: * Reads a byte from the input stream. */ int _jpeg_getc(void) { bytes_read++; if (_jpeg_io.current_bit < 8) { if (*_jpeg_io.buffer == 0xff) _jpeg_io.buffer++; _jpeg_io.buffer++; } _jpeg_io.current_bit = 8; if (_jpeg_io.buffer >= _jpeg_io.buffer_end) { TRACE("Tried to read memory past buffer size"); jpgalleg_error = JPG_ERROR_INPUT_BUFFER_TOO_SMALL; return -1; } return *_jpeg_io.buffer++; } /* _jpeg_putc: * Writes a byte to the output stream. */ int _jpeg_putc(int c) { if (_jpeg_io.buffer >= _jpeg_io.buffer_end) { TRACE("Tried to write memory past buffer size"); jpgalleg_error = JPG_ERROR_OUTPUT_BUFFER_TOO_SMALL; return -1; } *_jpeg_io.buffer++ = c; return 0; } /* _jpeg_getw: * Reads a word from the input stream. */ int _jpeg_getw(void) { int result; result = _jpeg_getc() << 8; result |= _jpeg_getc(); return result; } /* _jpeg_putw: * Writes a word to the output stream. */ int _jpeg_putw(int w) { int result; result = _jpeg_putc((w >> 8) & 0xff); result |= _jpeg_putc(w & 0xff); return result; } /* _jpeg_get_bit: * Reads a single bit from the input stream. */ INLINE int _jpeg_get_bit(void) { if (_jpeg_io.current_bit <= 0) { if (_jpeg_io.buffer >= _jpeg_io.buffer_end) { TRACE("Tried to read memory past buffer size"); jpgalleg_error = JPG_ERROR_INPUT_BUFFER_TOO_SMALL; return -1; } if (*_jpeg_io.buffer == 0xff) /* Special encoding for 0xff, which in JPGs is encoded like 2 bytes: * 0xff00. Here we skip the next byte (0x00) */ _jpeg_io.buffer++; _jpeg_io.buffer++; _jpeg_io.current_bit = 8; } _jpeg_io.current_bit--; return (*_jpeg_io.buffer >> _jpeg_io.current_bit) & 0x1; } /* _jpeg_put_bit: * Writes a single bit to the output stream. */ int _jpeg_put_bit(int bit) { current_byte |= (bit << _jpeg_io.current_bit); _jpeg_io.current_bit--; if (_jpeg_io.current_bit < 0) { if (_jpeg_putc(current_byte)) return -1; if (current_byte == 0xff) _jpeg_putc(0); _jpeg_io.current_bit = 7; current_byte = 0; } return 0; } /* _jpeg_flush_bits: * Flushes the current byte by filling unset bits with 1. */ void _jpeg_flush_bits(void) { while (_jpeg_io.current_bit < 7) _jpeg_put_bit(1); } /* _jpeg_open_chunk: * Opens a chunk for reading. */ void _jpeg_open_chunk(void) { bytes_read = 0; chunk_len = _jpeg_getw(); _jpeg_io.current_bit = 8; } /* _jpeg_close_chunk: * Closes the chunk being read, eventually skipping unused bytes. */ void _jpeg_close_chunk(void) { while (bytes_read < chunk_len) _jpeg_getc(); } /* _jpeg_eoc: * Returns true if the end of chunk being read is reached, otherwise false. */ int _jpeg_eoc(void) { return (bytes_read < chunk_len) ? FALSE : TRUE; } /* _jpeg_new_chunk: * Creates a new chunk for writing. */ void _jpeg_new_chunk(int type) { char *c = (char *)malloc(65536); c[0] = 0xff; c[1] = type; chunk_len = 2; chunk = c; } /* _jpeg_write_chunk: * Writes the current chunk to the output stream. */ void _jpeg_write_chunk(void) { unsigned char *c; if (!chunk) return; c = (unsigned char *)chunk; c[2] = (chunk_len >> 8) & 0xff; c[3] = chunk_len & 0xff; for (chunk_len += 2; chunk_len; chunk_len--) _jpeg_putc(*c++); free(chunk); chunk = NULL; _jpeg_io.current_bit = 7; current_byte = 0; } /* _jpeg_chunk_putc: * Writes a byte to the current chunk. */ void _jpeg_chunk_putc(int c) { char *p = (char *)chunk + chunk_len + 2; *p = c; chunk_len++; } /* _jpeg_chunk_putw: * Writes a word to the current chunk. */ void _jpeg_chunk_putw(int w) { _jpeg_chunk_putc((w >> 8) & 0xff); _jpeg_chunk_putc(w & 0xff); } /* _jpeg_chunk_puts: * Writes a stream of bytes to the current chunk. */ void _jpeg_chunk_puts(unsigned char *s, int size) { for (; size; size--) _jpeg_chunk_putc(*s++); } allegro4.4-4.4.2/addons/jpgalleg/src/jpgalleg.c000066400000000000000000000031001173507505700211550ustar00rootroot00000000000000/* * __ _____ ______ ______ ___ ___ * /\ \ /\ _ `\ /\ ___\ /\ _ \ /\_ \ /\_ \ * \ \ \\ \ \L\ \\ \ \__/ \ \ \L\ \\//\ \ \//\ \ __ __ * __ \ \ \\ \ __| \ \ \ __\ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\ * /\ \_\/ / \ \ \/ \ \ \L\ \\ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ * \ \____// \ \_\ \ \____/ \ \_\ \_\/\____\/\____\ \____\ \____ \ * \/____/ \/_/ \/___/ \/_/\/_/\/____/\/____/\/____/\/___L\ \ * /\____/ * \_/__/ * * Version 2.6, by Angelo Mottola, 2000-2006 * * Common library data and functions. * * See the readme.txt file for instructions on using this package in your * own programs. * */ #include HUFFMAN_TABLE _jpeg_huffman_ac_table[4]; HUFFMAN_TABLE _jpeg_huffman_dc_table[4]; IO_BUFFER _jpeg_io; const unsigned char _jpeg_zigzag_scan[64] = { 0, 1, 5, 6,14,15,27,28, 2, 4, 7,13,16,26,29,42, 3, 8,12,17,25,30,41,43, 9,11,18,24,31,40,44,53, 10,19,23,32,39,45,52,54, 20,22,33,38,46,51,55,60, 21,34,37,47,50,56,59,61, 35,36,48,49,57,58,62,63 }; const char *_jpeg_component_name[] = { "Y", "Cb", "Cr" }; int jpgalleg_error = JPG_ERROR_NONE; /* _jpeg_trace: * Internal debugging routine: prints error to stderr if in debug mode. */ void _jpeg_trace(const char *msg, ...) { #ifdef DEBUG va_list ap; va_start(ap, msg); vfprintf(stderr, msg, ap); va_end(ap); fprintf(stderr, "\n"); #else (void)msg; #endif } allegro4.4-4.4.2/addons/loadpng/000077500000000000000000000000001173507505700163025ustar00rootroot00000000000000allegro4.4-4.4.2/addons/loadpng/CHANGES.txt000066400000000000000000000112011173507505700201060ustar00rootroot00000000000000------- April 1999 ------- ?? Wrote load_png wrapper ??+1 Cleaned up a bit, tried getting grayscale and auto-MagicPink conversion working. 9 Now can read gamma from environment variable. Changed default gamma to 2.2. 13 Added save_png, using pieces from allpng.c 15 Fixed stupid bug I created in save_hicolour. Added copyright notice. Now uses packfile routines. Added #ifdef __cplusplus hack. Released: version 0.1. ------- December 1999 ------- 22 Updated to work with Allegro 3.9.xx. Fixed alpha channel support. Added alpha.c test.c renamed to example.c Released: version 0.2 ------- January 1999 ------- 3 Applied fix for < 8 bpp images (thanks to Dave Dribin) Released: version 0.3 ------- October 2000 ------- 12 Updated const-correctness in accordance with Allegro. Released: version 0.4 ------- April 2001 ------- 11 "Fixed" RGB/BGR problem with loading RGBA images. Use GFX_AUTODETECT in examples (GFX_SAFE changed in Allegro). Released: version 0.5 ------- July 2001 ------- 13 Reverted to 0.4 codebase, as 0.5 was really broken (oops). Added "depth" argument to examples. Commented out the BGR flipping code, which was incorrect I think anyway. Someone with a BGR card should check it out. Released: version 0.6 ------- January 2002 ------- 03 allegro/aintern.h -> allegro/internal/aintern.h (Allegro 4.0) Released: version 0.7 ------- February 2002 ------- 25 Fixed a problem with passing NULL for pal to load_png. Released: version 0.8 ------- March 2002 ------- 30 Tentative fixes for loading/saving RGBA images. Thanks to Chris Graham for reporting the problem. Minor changes to examples and makefile. ------- May 2002 ------- 06 Added shared library (unix) and install support into makefiles, and cleaned them up. Thanks to Robbert Haarman for the start. Minor changes for -W warnings. 07 Dave Dribin fixed a problem that surfaced with some buggy versions of libpng (1.0.13, 1.2.2). Moved the thanks section into a separate document. 08 Fixed a puny mistake in the makefile. 12 Released: version 0.9 16 Tentative fixes for sometimes-problems loading RGB images. 19 Released: version 0.10 ------- September 2002 ------- 03 Dave Dribin fixed two problems with images with alpha channels. 04 Released: version 0.11 ------- April 2003 ------- 27 Mostly incorporated Ceniza's changes (load_memory_png and loading from datafile support, plus an example). 28 Reworked those changes a little. ------- May 2003 ------- 02 Miscellaneous changes; put examples into separate directory (now that we have three!). 04 Signal errors on read/write failure. Released: version 1.0. 20 Calling load_png with NULL for palette argument was not converting paletted images to high/truecolour properly. Fixed. Thanks to Lothar May for pointing it out. Released: version 1.1. ------- October 2003 ------- 13 Changed the method of scaling of palette values from 6 bits to 8 bits. Instead of just multiplying by 4, now we use _rgb_scale_6[] so that e.g. 0 -> 0, but 63 -> 255. Thanks Nicolas Lemal for the idea. Released: version 1.2. 16 MSVC doesn't like pointer arithmetic on void*'s, pointed out by Chris Condrat. Re-released: version 1.2 (I forgot to update version constants anyway). ------- April 2004 ------- 26 Jon Rafkind suggested to use _getpixel*/_putpixel* in loader to speed up loading of large images. Split up the code into three files. This prevents the linker pulling in unused code, e.g. many people don't need save_png. 28 It turns out that loadpng's origin (example.c from libpng docs) was in the public domain, so now loadpng is in the public domain as well. Released: version 1.3. ------- October 2004 ------- 09 Made save_png handle non-memory bitmaps as well. 10 Fixed some bugs with load_png(). Now everything in PngSuite loads properly, and with correct gamma correction, except for: - bKGD chunks (solid background colours) are not respected. I chose this in the past, but I wonder if I should change it? - pHYs chunks (physical dimensions) are not respected. (BTW, this was all tested with Valgrind - no errors) _png_screen_gamma can now be 0.0 to disable gamma correction, i.e. if you don't know the screen gamma, it might be best not to guess. Got rid of inefficient BGR-handling hack and did things properly. New example: browse.c (for mass testing, e.g. PngSuite) Released: version 1.4pre1. ------- August 2005 ------- 18 Emmanuel Anne made _png_compression_level actually work. Released: version 1.4. ------- April 2006 ------- 9 Fix an endianness on big-endian machines, from Siarhei Siamashka. I haven't tested it. Released: version 1.5. allegro4.4-4.4.2/addons/loadpng/CMakeLists.txt000066400000000000000000000037311173507505700210460ustar00rootroot00000000000000#-----------------------------------------------------------------------------# # # loadpng # find_package(PNG) if(NOT PNG_FOUND) return() endif() include_directories(SYSTEM ${PNG_INCLUDE_DIR}) include_directories(${CMAKE_CURRENT_SOURCE_DIR}) set(LOADPNG_SOURCES loadpng.c savepng.c regpng.c ) set(LOADPNG_HEADERS loadpng.h ) set_source_files_properties(${LOADPNG_HEADERS} PROPERTIES MACOSX_PACKAGE_LOCATION Headers ) add_our_library(loadpng ${ADDON_LINKAGE} ${LOADPNG_SOURCES} ${LOADPNG_HEADERS} ) set_target_properties(loadpng PROPERTIES LINK_FLAGS "${ALLEGRO_LINK_FLAGS}" VERSION ${ALLEGRO_VERSION} SOVERSION ${ALLEGRO_SOVERSION} ) set_our_framework_properties(loadpng loadpng) if(PSP) target_link_libraries(loadpng ${PNG_LIBRARIES} allegro) endif(PSP) target_link_libraries(loadpng allegro ${PNG_LIBRARIES}) sanitize_cmake_link_flags(static_link_with ${PNG_LIBRARIES}) set_target_properties(loadpng PROPERTIES static_link_with "${static_link_with}" ) install_our_library(loadpng) if(NOT WANT_FRAMEWORKS) install_our_headers(${LOADPNG_HEADERS}) endif(NOT WANT_FRAMEWORKS) #-----------------------------------------------------------------------------# # # Examples # file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/examples) function(add_our_example nm) add_executable(${nm}_png WIN32 examples/${nm}.c) set_target_properties(${nm}_png PROPERTIES OUTPUT_NAME examples/${nm} ) target_link_libraries(${nm}_png loadpng) if(PSP) add_psp_executable(${nm}_png) endif(PSP) endfunction() if(WANT_EXAMPLES) add_our_example(example) add_our_example(exalpha) add_our_example(exdata) add_our_example(browse) copy_files(copy_loadpng_example_data examples/alpha.png examples/exdata.dat ) endif(WANT_EXAMPLES) #-----------------------------------------------------------------------------# # vim: set sts=4 sw=4 et: allegro4.4-4.4.2/addons/loadpng/README.txt000066400000000000000000000030701173507505700200000ustar00rootroot00000000000000 loadpng: glue for Allegro and libpng This wrapper is mostly a copy and paste job from example.c in the libpng docs, stripping out the useless transformations and making it use Allegro BITMAP and PALETTE structures. It is placed in the public domain. Requirements: Allegro http://alleg.sourceforge.net/ libpng http://www.libpng.org/pub/png/ zlib http://www.gzip.org/zlib/ Usage: See loadpng.h for functions and their descriptions. There is a simple example program called example.c, a program demonstrating alpha translucency in exalpha.c, and a program demonstrating how to load a PNG object from a datafile in exdata.c. To compile, just run "make" (or perhaps "mingw32-make"). To use loadpng, you need to link with libpng, zlib in addition to loadpng itself, e.g. gcc mygame.c -lldpng -lpng -lz -lalleg I recommend you copy loadpng's files into your own project's directory and compile loadpng as part of your project. Notes: - Grayscale images will be loaded in as 24 bit images, or 32 bit images if they contain an alpha channel. These will then be converted as usual, according to Allegro's conversion semantics. Be aware of this if you have disabled automatic colour depth conversion. - save_png() doesn't save any gamma chunk. I'm thinking of making it write an sRGB chunk by default. If you want tight control of how your images are saved, I recommend hacking save_png() to suit your needs. There's simply too many options. Enjoy! Peter Wang (tjaden@users.sf.net) http://members.ozadsl.com.au/~tjaden/ http://tjaden.strangesoft.net/ allegro4.4-4.4.2/addons/loadpng/THANKS.txt000066400000000000000000000005321173507505700200330ustar00rootroot00000000000000Peter Wang is me. Thanks to Martijn Versteegh for allpng.c, from which I took the actual routine which saves 15 / 16 bpp images. The following people reported or fixed bugs or did something else (assuming I didn't forget): - Dave Dribin - Lennart Steinke - Chris Graham - Robbert Haarman - Ceniza - Nicolas Lemal - Jon Rafkind - Emmanuel Anne allegro4.4-4.4.2/addons/loadpng/examples/000077500000000000000000000000001173507505700201205ustar00rootroot00000000000000allegro4.4-4.4.2/addons/loadpng/examples/alpha.png000066400000000000000000000657201173507505700217250ustar00rootroot00000000000000‰PNG  IHDR\r¨f IDATxœí}é’£ºÖl »»¿}ßÿ]Ï¹?PŠT²$„‡v{E6h”k”DšgœfààóíG ÎÏ3pš)Éó]ïkó<¦mzGÚïµ1rLò›ìyLíoúüÈãÎçô˜Ú¿æß÷¸ä2WK»õx¿áþgù[õôÚ¸ãù³Ík>.¹~Ž›çsÊ©‘~+¥à²ëÏ¢óN?î¥éÆüIÎÖÑ£ßÙ#érGÙ .øŒ.¸ýy]ïè)aÅÿsŒ½? þ½¶åþg¬ïümLÒÀé¼›­O¨x팥à Ç_à-ý:ü[ï{²ß#LÅ{KQ=­kŸAþÉÎI{÷ªƒZÇŒ×;ZP3#ïÝÁMðóZŒ`´£Ìß3&Ò(c8·¡E~J»gJÿàßÛvüh0öÝ=ÌÒž·ûUÀߣQ@%äÿžqIÏö¦Nž=:ciþ=Fð(Ògrµ¶” ÜD绉•Z’ÿ‘Àï1¬d¿þ¿ULjvâ =a è½²QŸŽ‚·Å>´Ú#UQÕ¯tÁ±û¼`ËøÛ±§,·˜®1(jð+)#PzSp& ¦À]Là0ªöŸƒ²Ý—ãiG$~TLjtqÀú l•÷>Ü*©[ßëï1šGS4j®–DˆžSdŒŽ\-»W†¾‡¶êv¤(µ´£L‚BÕý-s êuâ~ ààoQK½o]kµÕ’úª¡ì´üØïQÑ£²‘šì}x¶FàRgF¬nGÌëaÄD¼íƒ:ЩÉ0ÂHþÝk&¸ Òþ jÛnÞË>ü½ºzi{àW©Þ"OoßUôGØç=Ißc€Ïô ¨šîp ÂÒÝ/‚WûÓz_=BM†£L€íê¹’j ­zF©%:L -FÀˆ‚ÿ¨ãQÁ¯)Ñ¿;Fû¥Ôÿ#¤qôzí£‚‘DŽàÏòÞ°œ›úKRôw«?{LÀÉ}QŸúL 7f[ÌbÄ’tm¾…´_ʯ ? Ôñax]G¤|D{à¿Ç†ÿ=±ÿ=õþQ&ÇQROµ$óº¢ft{L`¯/èôÇ™ÛhOµwð?BкÜ×"L ‚äý  þ[Ã[k_¶mÕ&FÂpþ=é: ¨øoô=зÿÑÑ€3V09ÕLpºEì(}àFÜ\оø{ÒÂ5H‡¤}FÐc­2{äL ãhËæ£  þ=;½E{qüÑ:G½ò£àP{ú=æ2B-»ÞÛúhð“TåTmÀÍÍw´¯­Qz4Òi+=“y{àq2j;î8ôðáf u™9Þ³úßÐj1€žyü#á½–´‹êl…óøÛ²æÿQ&©ü=GÝíIû$×1Åø(qð+È£ùz>JÎ0"ãQ“§g2ì™)Þ÷(òáãÓCˆ­ E<ïùö´‹|_©áHi-²\Õ-ù÷<üGê‹l{½Þʵmo€õìüQ5Þ©•æõiã³4}Þô¤GZçï1‚–ªIk—¾£¦@Oh1¼Ï8Õ"ºÇ? L es ¸åL¨»pÄx¤Ú¯¿G…ñêGù½½=à÷ú¶ç<Ükg¯þž_ÂßÁN=Ï¢7ù¯Ï¢go[IÙ‰ZO/äHê°§xGgˆúŒÃ#‘×îd‰L`Ê€?m™@Ý´2€Tûô·ÔsÔ«Od/„7-Ñ,üÞGUY—ø +ð½¶c„8P߰މÞ\€]ÐÖ˜i°k=† &Šƒ?bG"î+1 ¼_{L a”¡Ë¥¬ ¤Ë– ”P`Z*lkÏRûGÀ? |–?âÕÆ%~ïå·Ôû–Ê•‰TøÑçê ÿ,€}ÐÁÚÒ œfùUiª¤ïÇÓzfD˱7ê;hE1´^Œ„[žÿQ&«†Õ}2« 1aìLß øà(š¨£’ó–Þžª?ÂHö´‰=€>Ï[¤xÏÿð‘ÄAþíE1)Ãpi뒨έHÐÖ€ š×5Þü-×cÀØ<¯ûpð«&@&0M–V9{À£ÔþQð·Ê·€}²ôž3숪¿çT;bÓ'l%MK…WÓÈóîÑg‚Ÿíªúš ƒD3¢eBŒD"SˆßqÄZ¦ÏIÚÏhž@>lÍ*lE Íô0Õ²OÙXë‰@Â×üQhÏ=ü£^ý= ¶ìúž-;ð=,éõ)ðø.¾"õTje‘œ°ešß¥÷^¤A)Z4½÷=Ó > Fmµh€ ¤ÆQ¥%馸€\ϼçøLµÒ¶K{M'íIæ#ñú#RÞÏ#}K½×õã³%û3H¿ƒ"2!ÔLÐ1ù €ÚLpj™ ‘Ʊgð:°ÕZxo:QHý#ÔaiÀ'2e ø­0ÓQºWíWIÚ’#`=¢êû3ˆÊ·Úd½ üÈIç÷ šB”æ}ûN¤`tUY7ðpp¨_¨£ ,ãù Zžþ[·ãõL$ŠL›æ@&ÐÒ6GÊ¿ù¯Z@¤<«|$Ô§4Ú{¦ª?²k“ÿGÔûSˆêþnŒÀ´Á¡êw使bÝËÃŽÚžƒK5„g0­/ò=´˜Ôæ@’ßaðÛÁ:—ÿ­ynLÜJ÷ªý=_Ë?|ýøÑ}é$œø­¾ìõÏïý+„ýöˆ£ŠÒ,’z –j1ݤ̀@ÕhÒ#AÏ4ˆêÐôæ€Æ÷q+ø ú H¥¿®Ðù‡ ÓE*|ËÎí•a{-ɯõôqÏRõ=^Oõž-hrÆ5¢(ù½+ð{•>›x´é¹uä}'ñž"û=ò²+ÀÜC®fBË_ðÙ¦Á 9Pd05€|žÄ ˜Î2dÓÀ‡î:®É8ÀÔó•øüÝ“ü£ª¾Ö«×÷L‡àû¶½÷{Dh=3¾2€¯è$tÏþÛÉ/}Kòû5½î!E`_À÷ø(Ó 5@ÉMƒ=& ÷’)‰Ã¯bXÍu9¹âîéEõ/÷à@XêÙÆKéð„¯×ÕuôžÖRé¢>ë3Òº¾q°+øÉø Û±§…I¸dt'!wƃë@Mˆ¦)³oJGA ´-Ó`„ t–«_™3°Ê MÇx|´ç„Žªý-‰Íº¢ö{à€ÏºTÕwißsØõ–ÊT”‘ôâØSšìÚW!“^Õï^xX©ê|ļ½–³M™A/‚p„ø¤"g@Ñû¼‘ tA T‹{z ÁõuL2 xıԛñ·i©S¦~Jþ=à·@¯çÚÇžßóäûóŠ4—žÏUz¯KIëÓþžù?’|7½1©Èù¥&ƒú`å[¡D`EPÍ Š ´Ö DŽ>yü»ùiL ißÍ|*!=Îò3ÿG:ÓpB~@mÏ9B­ ?žNêÙüz8þ=UßóލúQ¿´mصdÿ#¡¿çprà·´ž&dËæf~’JwÚÖÎHnôžWd&x!ò´f“ó&„ $‰ÚM•?ÕL J뀗3æÊñw¯ñ"餃öàß‹ ¨ÄQõ#û½õœ˜‡ÀúÔRéG{úL[L÷3iÂÖé·ÔhFŸ‚Øjì }ÓÂÍŸqø(Ó@ûë̬ǤݔóTàwFÿ aÁ•hèÀuºum¿ƒ?÷-àTð=ðGíºÔo©ú-f˧}b]‘Šï …Œ`d ´·1€føÊŸv½÷~ÇV}v‡˜J\–qð÷¦óy?Â4Ðpß½L`ZÀ©~e-¿üŠÕñ§L€éÑ Á³ ÷÷-¸6=á=ç©û~ÝAu/ø£û‰T}  üà‘ª®ùZ¶}KÅwà·pDÑsײ¿빇~KÛ>ø[ù:È(®X,’àÚ.° /Î’7}Ï4P&à¦ßG$Ñ•Q 0®Ö¶¯“Œ`š%OÀ¦ü‹„90Y}€¶ÕZ p„"ð«4kÙú@üäG€ßÏ<{ª~|g‚½P]¤«„ùj>½§_ˆŸÑ3hðOþÅÊ î¡Èt X4Wɧ Ò\‹p-*b,­M˜‡») [j½kà®= 4F²f0!ksÌ þàù˜>•œÔiíë=É•‹l}ÒG‚ÔÎï¨U|ؾ:í”´Îè9Ž8¡~«®gô°2—„½²Nj:xdÁt ne>ñÈ5‡Èlð<½©ÆG˜iGHÔ2ÃH@mÿc•è¼ÝJÝ&a“@f .L®µ¸7Åwü’„H}¿ƒÃÏë*å÷€Ï_—úz® ×󞚯Ì@½õÑ}x¿ýyõÔy×b6ÿšå—€ #h‘š ZOdB(PÕDpFÔf=ÎÔÎX÷êM@—ëR  2$2cEh1ªc£»¿Ó$‡—k¿šVd 'õ#àk[~ž¬œöÕÛqÐûÞúü®Æ{™èš×óÛ{}$ù‚ž?XA¬=YÿØ9ëúZ£`ye n"¨ æÏUÊê DuFÒ?2t2ÑkG©¥ è=Ø-Ÿä&À¶œÏWóü` ÙüøUúGŽÒø£îà÷ël÷'¶>`[·öÕ…½Ø‚ÞÛi=»„¶ ïíöÁO9?âL¼…ÜÑö +#ÐëJsã?û©&DoDFÏyÔ<`Û¥–ÓñáLÁ}ÀÊö´À/„ ¤–&lC|LSi s Öd„DYZàw5ZmÿQ‡_ ^†é§ Œ{÷#mÂM”ü=½Úø-5?’ò½Öégn =SòG¤‹bNr͉£ìOp­eBüÆV àÿ–y ¤ýRU_ëSA²|^ÖëmM"jéTÒ›¿)bz\$Ÿ_×k:Q¨ÇdaÑÚ—#_‘üÀýà÷vz±ýžºù \hI}¯[U|-TÍÿäÕãgPG!:Ð?rZpoú¯’]®LAM× €•¸ö æ‡–wù†:’àÚ€j3ˆÖ8#!wà©<þ)`n0o‹ \ë!ÜeòhÇ5¸@%Wû[’·å¼»üb;ߥ»þz›øYÿÉʪùz]Ÿv{ÏôQ†ã÷âýúhŠón缟ȄP«ôÿ…í¼ƒV?Ü<àuô9§³Ðý ­{ò1ÔšMH©Ÿ¥{aâñ'˜2@Ã1XÍ€ä™ò°ºÖÃÉHV¦óô¨þžäç¯ü^^N üÞføüï*¿KýHÅ÷þ´~øz5ðõzÄpÜþu¤ÇœŸM¾Ò÷uH/ÒäîKˆÌƒ½9n°-øÖ÷šrš2íŸû¢‚N"’2”è ïa¿ µ&àL`R†aL`jù4ê¡U“G1§@GüQð³lOåwðëuþgY.ˆRðkèÐM‰è¿ÿ*øõ-¸—Þ©ñúˆQ|&ð¸:½áÀÊ ˜‡×h—+#`n@Ò{ŒÀµ}®ïXÞmªƒä!ØY— €–ƒ0ÐPÔ|˜t/i™ ôB„Õ<¦cü€ü.ôh ê²‚¦~°#’ÿÙào9G˜@KêÿjôC5j®ÎGæ’ÿÿ …ÕZQ J]þlmj;Ÿ›šj*ð™Fÿõ«Y¢*;ëq“@Šš Z¯1‘Ί@RJ{3Ê<(2€öûm3€– ¹-ÕŸðã¶ÿø[Ò+Kíw0Œ€_m}•üÊìý1ø'ì«úü(üè÷¤Lî+0«ýwFÀ{s‘£ê7ó«Ô½by®ÔT5WmÀ¥>ÛJö˾P 9 eÜ/À~)hÝ+gÛµ|ÃOï·Lú1&PÍp-@Í[ P˜Jn›Í-ïcïÓ`G©¥’¶Ô~¥Ôȧ@íIþ£ö¾k=µ?b¡üí…ôðûœ…HÕ?K¾БvãÌ÷3‰`uFàóHX•¬3ø‰5þ®¾5zfj”ÖЉ<ʘ´Êœô ÉRG¨$¸zëL ;?àÀ7P9o™¤¤0Rõ"/¾–êuu÷ð»Ô×Á£Àïx4Ó]ê;ðUâk^½%¿ö©¥jù$‡“:Òœ¨ãÐM7 ifìÍ!h1õ èLB–Ûó ä¹û€Iâè©ïΰS&aë dHPëç± ›½µ:À<-¢=uÔ·KyÍç TOêõL>¯gü~]¥~ üðµ]}†þ,õ¾ô^¢¼I veL‹ò;“ðHBË4¸ 6 4lHPjØ’Þc$M‹´¿/õÎsî>v˜%¶JwÙ“ ä&7àW3€u8Ð#× @¦ï}0úOréßSÿOVNó(øUU>*ùõ|øÌ§a>­Çû§@ï…öö€Ôª¾÷½§Öû3õ|Ÿ9@Õd•úÜçÎG™j *Q#FÀ¼:ÁÇÆ³Õ¡L@ŸÛ(€¥'++Œ€`#ð© ¤)ýœ_Sö ¤ «tÎ*þ„À&îL)?óL2ÜÔ¡Hæ‘Û™’ÔÍç fÑÔßEq^÷êÿ ~C²:ø,;ªö[ðó¿rÞ’ú®±œ­ní'$ŸöUM›Ï$_lãZ‰k‘¹àŒ@ï=Š0¯ÏP†s à9%¿æaßs^‚ Tו)d€V²"`“ù” L¢”#šG å­LI'às8#pOrèÃS°¸”Ré« véï c¾G€_M—ÞĽŸH#ñÿêèséÿußëm©öÎàXïgÛÿ@=Ý–Œ€ÒZïájùÝtq¯zÄÔ7À¼®öëu vF!B¶õI§Ë}ªÍ^™r½¬ÅWs xs•ˆÌ„öÜ5¢ƒ2=˜i¥ïMÀ%Ÿ>'•ü-ðGÒ1’üÑþ#àW©ïþÉ@Ýo=Ï÷âúð!ÿݳï÷p–ò{ª½kþŒ?‹tÒJN¦‘ÈÔThiÊúfÚþÔX^5…V¸PëjFàýêØ<–Á%}bX}9‘°‚½Ì P‰0>¦W¡Âëš^òéýŸ£o*EƒP¨ªÒ.ÑüZgKíwð{ýGÁ¯qþðù; |•ún•ú{À×çxF üðú›ìWï –÷ä³ç|:o4PËèà#¸ÌÚwe#ˆ¢LgÈp–#!Þ¹(š; fÛ²Ûh9uóŽÂD *ÃȘ€Í$¡æ¢!IÁ_†³DŠ€úË@=Ï?É×d×\u8“pÉç’x,ø#u:’ì{Àï©û-à;ø[R_ï§õLõw’|­<¢ µ×mä Âs‡€ÑÝz8øÏØj®hèuEf† [Œ€ýý7¸O5[ÌIX ›Ž&° Íæ€2ò?bè0È1Éum[ò+#ˆ¿ ýWjI€TšEàŸp›ÃOÛ ¾ƒ8|ï§K{¶Ý~¤Ú·½³)Èw&àÒÜ'ü°Ý9Èçy” \Ðè¯i»eK}n0Oo‘üÚ‘(# 4èŽ2þw& ž~ýŸò¯NRÇ!ûÀºm¸P"|.)«ÛÛvàGÒÁ«9¤¨N‘ä?û¥À‰ÀïÀçÖ/l½ó£žýÈÏ1Iº¶§L³|oOŸ]‹!ÀòFŽD_#¤ª0¨ö™lG5׸À VúÎÖ–Þ«jÚ¿#`_NXýÔ Øv4o@¨,ÂQï¿w2é µô†[™°:[‰˜f¦@¥b´l§Èˆò&ËÛªO5µ$¿k{à~£U{ÑÆ|íOâkÿô^ZÀ×ÁÞÁìšÓ”Aûû8Bë%¨\ý‡+H#ß™jÊô®RÎïƒeh"ô4Õ ~Ûý8ÈFµÛn~÷ÕÔ[†ât©¯1JåH2L’¥ÉQ•@=åòhheˆà í‰@@ìù¤ÿõ2}Oú»&lÁ3ÉùøPú4£Xÿ-!=‚Ä…ðôÞ½~mG™P?ÿïýs&Û ÿF“bTbªZ~F­(c¸`«¶;3Øcú £¨Jz`:Ô|Lê¨ë3&P›„å¨ „ÞP¯<ãül'äÿ¤¦ÀŸ|ݤúdæxø%Oi?_›€:"PMz] ¤@üLrÉ©o€¡¾(l±_`q鵟R ©·¥îÛ‰<-ˆ¥þ„-sŒ¤=ûå NIÓØ6ƒ^ËÏA¾wù%pg+ÇçÂòª%(#`~’kZöÍ'µ6 æ‚:µ.~¢ž(äL€Z°Ñªí·à3jçj`ó¶6G²2£Y^ÓUKÿ,»:5GEj¿k •¢Ú–‚Ͱ;G%?°Né=Iö¡~Ò(øUz÷À¯À×ün^ô˜2¯ŸQû"¢Ð6 ” (“aù3€‹QÕb~éw |þ:­Ò´YBåÀ;ªp€­/íGÏ]ã¸X»ÕÃRà_I¥¢’K[€N ‚(MUdÖ=YþúÿhVß„Zú»ÚßRùãàœ|~Uõ•8ð#¦HêiB¤Ö3¾×”‘¸‰»®ÏJÕs¶ªô4 ¨)(pYFµÒ`ÚGí—O>e š€í,=­ŸÒ±,¶i £(Ñ€àh–?­ gb´˜¨”Ë÷½ÖMvéÇk.H=Ð÷HË©ª­ Ø“þÚ"û¿2Ú°‚ÿÔµן¬>qÈY-uÁ5¾›^|5+”ö€Þ³ÿIÑtXÒOÄa3e,tüUÓÀëV鯦IçðÙ¨ƒÐû;Ém³²ƒ±‚]3‰š€¾š CS€ÞzJÿVT@%¿ªêÀÖ»oöÕ?×¼Þ–Dgõ•-õ$1É™@$™Ïù#(Ó"—þ®•ôÀÿ;ø{’ߥ¾3€©¯y]è_AÔÀWÆIeîè#È”ð~Z>2æWF@j™Njjð¿šHy>@â‘€ôOÓïzèTL€]+<Ìÿ‹#0ÊãŒÀGÄ(&I·þ¬¤ݦ®Ô’H‚Òò|¿zîa¿-é¯àoIo7a™èáRŸÇO«sü‘ÔW/¾;ú~J>gªì¿úGþŠÚÖyºþ#âÈëÓX2$iݤ&P†_ÖBª_€%°KyÓ¦ž¬>e({Z€·¥y5°Dl&#_àuBàØ rÛßݳý}ž=Rð»G<’ú`¾ƒºþœÎ„x/‘“Ï™ßmÐ}à³_™ÜixÅò¼`,# -óXô$¬j~/dÔ&2e(TL@cã X4‹4Κ—ìâþ5ÐK¨/G#*qÁÆs&Àc]˜¯MÒVÕ?À&1ÍÖææqìm²G·zþu 8´ž£~ü“ßþHê³­?Q¸ÆâÒøoßÉÐfÔô¾Éjf2cyö¾¶À‡>uæ P–ê¦\w‘îW ýDå„› 21)\ÐïóUi •I. š°õ%dÍ'ÒÊrâœoãL¨†çò|{Û‚Gª©ž+õ´—þ̯³ß´ e,£ Ñ ?-Û¾µ¢ÏU~ ~c~Uç]êëùé·§{œþ¿|§#Œ@ÇP¯üS!°uϨ52 몾„U:#3Oª¶Ô&xòó°I‚ È‘JS`Fñ¨ãöçœÿ>ƒºô€7“ ~?ØFñŒî ìöy$ù]zGÒŸi‘ç?’þ-GÜøa×Z1~팀_íýøY÷ø]sø/‚_)b>Ç`²_X:ÇWÄÔ$P’Û©æÃ›† Ú@ù—Ì,@2&PÊOˆ%=Mm@€[•IM- Jœ‚KÚàm‚Yù0b ƒý$ל"Ï ÒDÞ ¶TË)¸¼-j1Ú=µÿ^ðO’güð(ù{L€&~°e” °þóz­HM`•ÌîM'ˆÕKo mF´¼ON¹YÒ&ËÃõoØ~Dd/"ÉÔ+©ATZ@Ä\ýž‚k=Ï¿¿ÏÓóü;ð@Z’Ï¥¿3“‘~#’ÄÙ§çnóGàwsäo$×øž¹Q‡Ž‘;™@Ê×Ò ë6]ª9‚=!z]&@»ž¿Éê÷r:/€ ‚}Rp[_@¤ÃCÅz€þwm€”,oOú«örÊ@LÏ5ïø¶qø¿úZà×]Šÿfð+¹6ðØ2Íâœc¨Q)°õ ˜)~fPªçý0EZ€/RỈF®XD Eˆ³' f&'ÉsÁ†¬0íù€èz˾÷‡Ob=#žÿ$eˆz V&ÿ/)OàõÀß;ÔÎ IDATSûH~¿Ž Uû_àߟwïq&pƒ9@Û_mq,@›Ts+`¨ kT ×=õL̦lN€×*-€¡@$Ô&AÖ¦l T†,é' Ða )7¶xRã?¾‡yÎA^Wϵ>U‘Ý1 ?œÉô‹¼~¯ÚÿCÒ´_/µœ¸©'°0wÔßïÔJl¨Wç ˜€íÖÙÂ&“Þ¸¬€/à#øõLXcñb{«0½¡ Â|°NNr_—ö°ß@ ×ad .V %µýyÞ’þ@ ´“ÕÁ|züj\‹ì~ȵÈ9w¯ÚmlòröÝFÊÔOP/ RÐ{Ì?Ï(CC4heF`Bm04˜5t]™@å'ж€í¢¡üqÓ HÛ2à÷är6ý{ˆO€}_é "ŠJÿA²´¥+¹öÅû£ïö©ê?"ùµÿêˆÆÀ¯fÇ ü·ÓOÔk€úƒ#zTêôªçsú8Ù¨™@Q³ç,€ h\ÃßÀ¨vð™PÖç“Á”ÅGѼ€|ߨæ°ïD`¿5„îe‘÷tJÿ=Ï¿†×N®ß( Õ㯀SÕŸÀìßC}Î, õ(øO¨ï÷üû‰ÎA`;iHI˜@Ù‹_€Àêe“aKéê1|Ö‘ç„a@ÕS@©¬¤dÖ1ÒˆàʧÑO4¶Zƒ´1„Çkå.Ñ÷ü+Ø–~¬Ž3œ;Ò ÿUõ'ø]Mï} ®Ej¿ƒßµ?Û|yùK{¡B¦e/=€­GÜ4gåP;âT›ê(À„52°ªûÉÊ0¯Fx½Ð9QD``û°=à1 `Ãâò/Áyþ=¬½¶”1h¸ÏÁ¯69Ëi;=µ?¡ þŸR?ëù¿ /zõ¢X@D&PH™€‡ÈZ½Æsµ×@©ÛÖ „A=XW?.fÌ)”g•hüqP1©Ì(<˜{þI^¿¶ëž¥Èñ9ýZv¿¶Ãsß»cüjÿ¿€ÿ\¢o@Ã{ȯ5ÏéO— g3j&@éëRyº­7UëjIî3ÌÈde•±P Ј€h›ÝƒO¨'¹@–oB³b¶€:ßZäa´^¯7¡òëþ…ì”þ=ð;x]õW&yûaå¢6-TíÿãHmz ÞØCíà7¬qü¶ yÐÆ‡€wB½­7¨“„.9O^/PiIê熢d×µ/iíSa>3bÛ^Ì”Ï8¯ã²=`ZLXmaæsð·Êê|×[~!.çÚƒ2ª[ÁïuèZ~õôÿÿ/ú0"ð#¿6 ãAÀñ†M(ŒL`²¥ºÈ×ÓœM0»÷›uˆYúƒZç ÌÒŸŒ¶P–%ëߔӢ5^^C}ú™†MÀ¤ ˆž÷æhzΈ™([Ú#e*ý“¥yÈе?g>¿¿Èîwµ?a÷ÑÇ“‚¨Ãxë×@®Ø~hóŒ5lGЪ®¦µ€?¨Na®M0Rï$ÌÃÓ{‡û&.òrÔp ]È"ðG¤1¢=0+Ub:H½>ÞMäùg~þ¶ì~•ÜGìþ3ÆÀÿ’þJe€kØŽf®çWÛXå8~5g O4J“‹@VS@¶øR‰]ö$øÀÿj@V}×ó¬uTßPíƒí¶Êó<¡bT:÷_¿MÀ4 &k9ø\w€•Ƭ¬«ÞNÉ~}‚{þµ =ßSýµ=eNÊ zàÙýN9ù*õ• PXxO|Ü>, յ㒗 Œø¡‘ì ¨V þB©€ÔQØ>vqþAîa 8I»œëP°è9úä• 8K"¹¶ çîP$˜z†*åuÂKÿdçÎ|Ôñ¨¶½Çùü#ÏìE¥Hꕃ  ˜@zGm¿ï˜›ï¨?@w÷á’Ý("Àr [`jYÖ§ê¼Jü$åt™pà ¨ž‡µ‹|-Ž[‰y„|îTRéëŽ6æoÒßÁÙí-éÏv[ª?ëzÍðûRÔ¿‡æ"&ÀÃAï¡AŸ@ª?à$×4´çZ€û å´>”DgŸ—I¨QPë÷Èj3ðØ™€ RŸü£y¢2\Kúzþø-»_¥Ä`¼Ì üŸJ.GBÔê3%4LS0°ÙYw³wäð>Ú¶ó8e8ÒÞs´€Î d[êPf¡ýè=9ô9ÞÆ"€&ûMþñr @:ô¤¿ßƒP™‚þWíB# x¿öéþO¡hආ €$(Î(Kz«…4Ù–Ÿ€ZZžð P`ý2°å/û ¨Ú.Z@)h“öGÓ$/D¹wÕ´ýàÙðùø³\è‘€ªÉùaTj:)’äK_jbo}ÖßžçÏñGÆã|×FÜËÿ¢§“ƒ?ä.TæÀÄó P¢ËZ|†9¨4Iý¹ áMª-äΩdžL POàq_óçvªïäñ^´€?rÿ'cÁóü.t+ÐZö<ø#H–Ùþ@{oͱ·øÉFÀIÿø?…6ï%]}¢Î)¬ÒšÒ—ªõYêT€„Õª%Á(×Ô0¡DB€:ñh Øf!Õ~êáý'Ôæ†1‡•F¥»¿•ˆ–©àS[ÔzÛîüSéÏv5ç;YyÍ÷ÓÊ»ôÿÃhà#ç92¢¾¶Ôš€QYŸÑ˜Ó&_À A8¯Ÿ ,ÔRß]JG×#°DŒ€äÒ¿zcùpÛ_ÁŸìº2wú%Ôf@äíÿÃI‡T‹L´½ôjxéD ™)8ezìFò_Q>•ÊXAÈ=ÔZÀyßfÃPš³ô_gjýLW­BV@NÙ€€QT÷OAXQPàö<õÎt<•ÊžW¯3MGAKúG*ý„-ˆu40¯÷%RùÉÀzÌìE%bEGÒ#ÙRÍØ;ç<n£\& ©J,à!ÐNàåŒuß þ¦€šìKZ™ËðýÑëP÷§8:ý» Õ'Ä-àŒ¹ ~}K-ÒÉ?ê-gÏ•X3Ï£@U鯪T§Þ‡JqÈ¿ö×}/ú0êÀ{ÓPÛíXÁ¿ÑtÎ?Á£ZÀUÊÛ8=P›Iw2æ~5ûŸXyj2\î ›„* ГÈJ샟b εڤèÅþ[4Ùm‡€¿Õö÷ù /z*õä@‹)Ü“Þd9TWƯμS\>K`YD@Çbµiˆ·Iý^ÿó¤ }h•D§ïá¼ô}÷þÓztÎM ­ ‰Ò[o1²Ç=G=‰y¿ÜI1™–ô×:^Òÿ©4,¥?â蘅 0 Àt—®Ì§h…ËþDËðÖÚ®IÜ)hÓ¶:*ËÛˆ6i©÷GÉsì$‡ªî^÷/ì·¥é”þ/ð?¾øíz`;ÿÞœ€…¨j>Ie*Y‚P·ú‘¬nñ)”vt"ÒȤ ¶ïSƒ«wqt&àÞ„Ÿd¿®Z„j·kYe"î$¸I-MCû©Å–ô×ÿ/z ù°x4Coÿè¡N:Èz×4ÖžrûѼÝ5ˆeõ ãð¶uRO &…÷ïó‚÷pÛT`JÔ=R0™ü£Àv¦ é‘ôg{4Kú¿è) ¼€£´½ôðïÖŸCƒ%O fFPâü0iD€uª£î„²½8TróøLÿZÿ¦µþêˉCà÷ûK¨>RºÒ³¾ HÒ^ª'ß%¶ßIþSéÝ’þG=ÿL{Iÿ§¿â„-7ÑHúðïÖŸ¥ma'KÏZ$"0õÎ@Zw®¯|Õç*LÄ7 !¨uÕ^îǤ¾€[@ZË®ôlà¤*¹½É?¨_#àïµý_à:õèǽé{G³¼j@í °ˆ@Q̓ˆÀÆÀòÔtf ÉÔàÒ?Õzûþßpï+}4b 'ý±9ÿ̧י¿'ý_ôà½çGß=Ÿ°n-„ÛˆÀYÎÅÕ®Xfêù~“œû.¾ºص…8ÐiÏÙGŠt¨´ç.ý¶ôjß„:_ÒÿÃ)Rš Ò{ÒG@0T?UuÙ@„“o¬q~]/Ôëj;] ë„E Ž– ·ú¯Ñ=¼/ZNü¼áZþѼ-âGwåþ³/G=ÿ/éÿºEJ}©ƒê=°\$]™¥¼æÌÝ=xj´Ë‘°. æ9Fôá™­yncTºè´WšìË-žÿ—ô8}{ðCJ3f™¢»ù¿7癑~8” ¨Q†I€|¨ÙÒú–•èÖ\bÞ&©W¿ö×€öõ‘ÌêEjàó÷‘Lj·û)ÀÊ š6ÎÀ*Ÿ:uíÀGÜ?ûÆ­Ìtƒ ¿¾§­ ªtD,Ií#õ§åýIÿ§h`µp”¶—~$ÔwKýaºhÍöe¡‰óëÝ5níÆŒÀÃ÷oR¾|wXµéãé[ŽD,¸"p%lIòü*ý{eo!©YÛzyþ?üÑ ö|$ýøÞþ”í³òÔ˜%Nl½úϼÿÜÎÔ ƒÌ05v&Gj‡G€¢½$@vÞŠÿ+Ø}fâžôÑé7Àý¸7}ïxXûˆ@è¼K(fh0/)h?Xt×ýg­¸å €ü.të§Á¨¤(üù-”x篵þ§Q€Ý{~ðo?íêÄ ž°Æý³$™@Ž$<åþ%$¶ý{ úR†fÀÝž©N·$¹{ÿôvH¾hCþÈ=-¤÷¤€àCÚoxØ‘ãë¥üÕê½2~5<¨fãî_A‹© *ó3[¤½ÓX¾‚Þ'ÿ¼èÃé)õWŒ÷ÓWà»ûúê@ÿ¶öNö ï1‹Ç3€[¤m þ³—\þÛ«ÿ‘^tˆ^à¿O ⯆ u2Á=:1ˆ6þ}¬ßå#kuý¨”Vi¯ê»ªÿšîwò¢§“KŽGçÃãüݾ;õØì <|$ì Ä}Ï1ÜCQ4’~¢fÚã—=ÿi œ€¢´½ôO‰óvûÔ.À¤_ ’o„åi^‰\ÇÛ×´•>Ó/Qÿ_ô!äàÙ·óVû:G ¡^Ôk?ƒ¿ª²߀F:íC~z4pVŒÙêʦ^€ÿrÔà~Ü›¾w|ëö ýt)põ¿UÂv³Áö!¿ =’hÍGìÿ„uÁmö¢¥Ñ~ïùQÀýçÚO¨¿”Ðܨ{žC”­tص…>ÊHhO7ŽYÓsèÅT†¨÷*Z ¹'}„ŸÒ¾€ ›Í:în_ç [ÉŸC†ZøÖö#†ð ŸåòÞéÔ^¿¯øþ§S(¥^ÇÇ¿€ô?»Æ¢îK Ë•úŽÏð>“ïE_š^àŽt;؆ëç¯ÿ×iÄÀÃöXé™&@B=ƒÏwþõ´–_t\2•z<<÷¤ï¯öåŒz|¸?`nK¯öËuÿÁí£*óbÝ"¥^Çç€ü>Ÿ\°Ú÷sÕò‹>t¼Ž/~ø¬ÃÍC -ÿ?Jà6Äd¿ü¿iùEX_¼þ>òø¶qþ‘c`·§µÏ Fy~Á:#° Øc+#x˜±€>å_^KöËÖ¯xEžDÑ‹o à(m/ý[ÄÙ¿Sû3Ö…Aù|â§Å½ìûxûZv¥g0€Ùþ_¼£Þ™— bj”{ÍÒ¿„üÑ ükâì_½ý?–ž¥ÿ„èebnU~Cûß…ž¥\¬ÅüYäŠÕµð¢§QoúqoúÞñj?¸N3# Æ¢úó»<²@- BËh{¥gú(ý'ù¥Y0ãåx2À{ÏøoÕþ;6K€Þ~«þ ~PúóÜf½^[èÑ `¶_`ë èåÇöë@/:Li'-$÷¤ ÂoÝþû´Ÿµá~¦gµW¬Òÿ†ö#†ð €vöÛM@h¨êÿ‘&Às–>})ФÌëø¢C{ øß;e¨ 4¶Û; ¿Ts ¢?xíóÿÒü:p¨}}؆•ú{±ÿô´ü$Кޱ|=x4@5Xˆ/¦0D)ø}äñŸŽófûd0°eóÁößÇktÂÊZ’ŸŽ@Nâñ¨é¤èŶp”¶—þŸ‹³fûôæ_°W,Ÿðf Õ¾zÿ©þóå-ÁµM[陀üQÜ]§ø4è' cx1„&9ø£Aðeâܯö×ô÷Ä“Jûߨ¢nò»Ð#€Ïæ;2«¯5pпf v©7ü¸7}ïxµßHc®Ï‹ú?´¯Z@Cåü.ô( 螀Z€Î àÿw¬~æÑÙƒ¯ÉCÃðÞó£þÕ>ªIšqzÕj‹úÔëýf @o¶oÚò“´Ï_‰(éyc:‚=§vA&ÐCÄŒ†¤ÄëøØCÕñ €ÓÙ…ùd>ÿ.ÀoíGã€üÞÏžm›Ó‰H0xCß àÒcþ’þûè |ŸpôÆ)º:‡ßçò_‚:=¿`ÆfŸ@=HËÿ[€Úé#±þ#ôÀ?vMÃ:­ø=ÿ¿ØoT–³¿éŠÀü>òøÏÆÙïi_Õt†ÝhµãUí¤?ÁÿÌûWf³“9ÿBdnO«Ã­EoX¥3½ÿØ)s„4HRéÞÒ²£¥äã“a}³°bõâìš (m/ý?gtûüVÐD’|ÊŒ,cÒ¿Äù½þ?ºÿYúgsX¾ô Bs¤´œk¼®Ž8Ja ꣈@&è#g # +˜¤ŒJþo¢8ø£Að%ãÜÿ…ö9Éæ}ýŸrtJ—ïNª (È3Ÿvÿ¬_" é ËÇCs €•Q,Èw0âYWí€Z@©ð ÔšLÄf€–‹´j-߈zÜ{Ó÷Ž¿¢}JQ•¦Ü•ÇÕ3p­Ï+µ<ØÆû¦û÷5 ìÏÖ°c°}Û.B´b*áZÕN¨I?™¬ZYνÔsðE¤`ׄßX À÷žÜ_ѾJ|³ý« ;4tw‰þÔûW³$3+(c’üZ®à÷2ªŽ­¯@µ€GОù Ž@õ¨@fðM}Îo=-$÷¤ ¿¦ý@úWëñ]ú•æ¶/c­Ò*qÿ4}™Ô«åPõùž0`oyï(ÍXýƒ¶CùZ=¥âkÈ$¾™p‹”x¾[“‘/à]Òÿðøt-€/ öÛ{GÒ¿tœý+µO‡_ ý'nÉížÿüzÃ!`ºÜ÷7béŸë™²ô‡^ ¸ëþ@òݦôÂrJj·¸@¼dØ}n (ˆõšN@ÚóüÁÂxÔiBSà“´ôÿ³qö¯Ô¾ÄúaÒŸàç5Ý—?]ò<Hyú¤&K2—ߨB ãåz'c7Ý¿™+e ¤ÏöKP²7.Ç:£ ) Ó‚é p-€ê=†jì‹ç¥‰ ó>Ñè p?îMß;þÊö=ìÙþYZWa?•Ôœ¤Î¿ÛØ€Óë¬bù;~‚‘û_I@ Ô£éNj‡;{õFšÍjª(3¶š$°H|¶áLâiôÞ{~p]ûj‹÷âþÀww@Šç¿lëEëò_ÒF´jÑ—€Ø? fznL£Ï\÷Ó÷Àï*¹:ÜX–Ÿ£ô¥/€€§ ×œ”9¸d÷-É le@Ê8>Å!Ø{”ýv[úÿÊöeò :Ò@\‘çY3(à¤4¯ý ú/c½0Õ:.Ö?«³{ÿÖ@ËPPÐ25Zk?cnÚ+ :æ%Po™Cpµÿ4ZZ€öÿ"y¢ˆ°†ŸÌ"®ý:>á ÝÏÿG<ÿ°¼ ²í—Ö5m©™q¨S°þ. @=é=Ú³ûöÊ@j,¹×¦ªç«›ÊTÞ°né3ó÷Ö°OObú^Ç'¦Z7ãþýŒZµn-ûU)­L¨™ÃŒ±€°-ì´1£À×@ḌÅ3æM1‚ÈLP€èÒ`¯CA>âr$0ÜdˆTúш€Þ³2©'I~ç¼Ìß&ÎþUÚo­õwéï’·÷Ÿh·›ê2›Ž°¾_oIú¹qÿ—¸~ÈïÂÔs¬ÒTAX¥nÂÖ p¦¡¶;%°×?[~IJÔz³©9ô´Þ+Ë>Ɉ|kGi{éß&Îþ•ÚWI©ëýÒ¢­ÌúãZüªNÕÞ×#OÉUMïÍpP¶´ØÒ”Á±¬›w’ƒ?ÄEœý+µ¯ üë¾ü©Íù/ëíÕëŸóVàG]®€ß¤)ŸÕÿªý#÷ÏößÖþDË“µüªú“ZóôªÚÌnPÊöÔè–ÚOÏ&çðÎfÿà øeÆû.ùµF@•ÿæ>ýÀ:yèNê p?îMß;þêöéIC­úôÎÛ=ÛŸùlrNý­Â†nz¼cÕB4ÖúÀzÜCG (Ï®2ù©[IßÓ< êmâ“‚X. ìd3êúÔ`}‘À¾*ص~F$ÔS†ï`£øÞó£€ûkÛϱuø!à/q–!àÄž® ÔÒßTÿJâ« ³ÿªû!) vÉïÒ¨U5¯€÷É: ¸w1{a=5Tå¶Sƒ z’ú˜W5 õ-¸°7/à-—¥ï£ L;èH;iÑ ½'}uûy+¯~ó¤—±ÐþEˆìIø…1àÊØ<õeL_¬ÎÌP”qÞãŽô×rµà Ró[é>-XÓÔ6‡äS-@ëìM "CPÆá¦@B[ `›*ÉU "ÐO¨ç¨&@`·H©×ñÄCæùW¡;Uµ5Ü6[¦©´•½²¿]õ†þ”iDoR.ºO—þç¡ctLPu_Û²¯#"xÝC9½ ìoÛ¼Hú|“{9¡úõ/ðÁCÁ¯R›‡,Ì©À¯ŒAít—þ^ÎcöîùgÚ^g;wg#‚ÿz8ã0àb~ÜjPêÛ9ºÙ†O "ˆb i½@ *ES alPO"Е DOÓ–ÙNg‘ü>òøvqö¯Ò¾:É|¦ß(øß±î ì`$H=<È<¶Ò/ÿU꘱ÕFxÿþ÷ ÎHúÛ¹ŽÓç~\%¾šêÔs 2]IHTNµÈ5_xDéM-ÀCë‡FTò›S0z°­¥í¥Ë8ûWh_À8Ñ!I~Æò/’îàoIäúÕa¨ýe€«ÿx®Ê'¤ˆ¨ IDATTr%Ô4™È¬ß%ˆÒ5 J·~(òDÎ3÷ D‘‚ óåÆÜ$¡v2j|ªè¤u ud@ÏÕ´  9ø£Aü×ÅÙ¿Bû ~žÓ¡g>‚¿ æcü×\jû#ÿRõ/q~ÝôCûÏ•Ú2¬õVmËäŸ#Ïò»Ð£4u&Ä“‚˜©íZ—æ&i}=-€mÑ «!ýf?¯RF¯wf ö^€÷¦ï}ûª†Ï@ú·OÅfû¬ ÀÍ…Ö9PÙþðÊqHàuaí .VÞíýµ¿÷ü ¿ E À3ú…eªƒ¤q]¾ªë>1ˆ¤ÌEµ¶¥D3ût‚I™ÛÒþð (/ý?äGÜ_Ý>'Òøavuê›-?ùüù:Ìó_ÕGÀË¢@ʳ?Ò§æý«í/Ñg8­ç©×W<ú† $‚²fû¤ê¶;PëVjïÌJÊ\ü`ªYè½D¦€×µÿ-Èš@ê¬l Ò{ÒG@ð×·€_AÍ÷™ÞP;Ü8Ž\úº„½Ú!Ò¿^3Ï?ÓŠôÇZ¶ÌCpæ£}ˆ~ɘZÏO4‡r]|€kôaÖ<jÚ¢JÒ“äÓ©ÁÑ>jSÏR¦¶f@/"à{ò®Õ`_IÚ2‘7l(ü ¤ÿ“h¯ãWûi»+x üHõ»#ý#Õ¨wûQ­`¶¨A¯}¾yÔïÝ뛕Ñþ{Þ ]NFZ¨eTrÙ%褹?€äaDå˜Q½ PÍ ÒÔ¦Wg$°uñwɦõ–Ò ‹„Q&€×ñi‡ƒ_¥<Ï߃Ÿuh~QÑ7ÒRNÏyhèïŠz⬜¶½3',ãy\Ãк©íˆ£rÕ$ ÕZ‚4½å/P‰®v¿ûR§ Ø›¬€W?CÏ@®3KH?ÖË&p‡ðmãì_¡}õ¿çf÷Wÿ/X·ÎîyýÍö¯fýñWUg°ÿRŽË7{(Ó9r(£³4äôÅìP À™€ÎÑßsöÒÝ·À6Tš÷ÈÓG"‡¹tç]‹fy;N¾:°•ÏI¥´–Ñ:Ü ê>2ºÜwÔPb›ëCGîB:燫皎x€£“Ö{ùQù{Ó¿}û~Jz¨ ÿõ¾úœìC`ºÝHÿRžL@™ Dzkÿ(ýaÏh+ŒÃï7þÕD `JsPÿÎógòsÚ:[vº’:É ®L¨ãîu› ù† %Ô’]¥?ÿ«ªÏ{QŸ„jì‡2éG{é„-M@Ïóòá4¡i ¸väØ+oú·h_o´ïiã øC½:Ψ²·T ’äÕ~îüÛ[ïÏþ³^DDö¼›ù^7ÏÏ"¸uÙ³_‰›‚.ÿWRuÚý­Ï‡§ÆþFÌ…`œ%OBýÑŽH ñíÃ[Ë…• °~¿'õGH?åEœÖ—ÈCýaçÀfŽÀ&í4˜GŸ»ö ü0›jó;àz^€ƒßý,/v? üaÜ?ê?ÇFôÞ|‘–Ÿ×ôÊŒ¹Hºç¿Hºöƒ8¬œ€÷P¤Ú«”ö5÷šÆs žÄãZ,oB=1Hëeš3Ö­L@€r^bÇD=¸” °H¾È »óF@Ð+oú·hßãü¦ö#%çÈÂSð7bþ¥~—ü¬ÿ7Ö8ÿÏuÿÞŽû eÙ>–{ƒæ1Ð{LZæ©_&ˆâIAj›ëœ€«ÔáZ{·ÎˆNrîóÈÔhE¦åãŒE¥û‰EúsPMùXcËk<è 4Fðš+pãa_ï©âü|7ê#@”!ì߀_©éøÕŒàÑòü³<¤þw9€º?kïÖ¦iG™éã€Kò‘IA®‚³¬û(©=Ÿ’F€ú  ÛiÂj L … ÐÉWüœ¿šu+èÅ,øt@}—#šàãSt9¡ÆÁOÐ5øY¦'ùp>áGÁï¶:P3?ÜöoMüѾ´¶þòº;ö¿3…ž©hçc!ÁÙÊD¯G¯÷6!é‚35]mv0#L€/?oA5©6|8ø–q~wô)(Ub÷ÀŸÏ'¿‚)’üîŒfF’Ÿª¿ŸíÃêq-Å™ˆj@Ý­Pð0êJçŒÝÁ¹7@ÉóÎX}ìÁ=½ ªþ™Ð5ÿ¬WýXógªÿ@Ŧ r}wÎjý”™»Vž€é„Z¸X|á8ûgµ¯`yǺžßÕñ èMœßÁyûüe=¾OÄá<mÿ*õå|SVý«y ~ qÞ•ÿ,O…koö|ÀwŸ?ÛQBÉßÓT}h–Võ«žYò:ðñˆ@Ôc (èE€Þ+xD ˜xþgÉ*µ~zǪ pcI,y&Nr“@ó ~a°ó¿.Îß¿NeÀÏ<›8ÿ øË.¾WiXw"Hc ~QÍ5 PÀÿ^ç)÷ûŽõ»þürŸ'¹·”Ǿªÿ“Õ¹ißÛÌyÚ3T?p‰ì[‚“"My<" mèQDÀ‚® h?ø_§GºNΧöyåVð2:,€O6˜9@€õ °™©”—ïLàŠ5Ü(·Ò̽é{ǧ¶OO;߇ªý|¾;6ök…úZ6?ËÛdüFÊ›êXÚ»´iÚÉFšÏvÿ4-…I”çë>€«¤«É£é¹+µ€ªý@¬ èI®QˆœìùÞf!­ˆ€¦Eþ‚Ý™À,}- ëaô Tq|=§TÉš€ÎLs2zÿE¥+LØLâcjêèùQÀJûW'`j? ü®ö—óÉ_TbSû«™~l`¥ši3jáàW`³ H}°ùª™ì$vîŒA5Ñ¢ÚÛD¯5Sh­ts`þkèMÓY}Àº!É5%g³\ãÈ4lºp‘öÆدJ… `]Çf(‘å®#¸b1Y¡B¥ˆzé# ¼§þ›Û'²äuðW6¿ªý¥üð«ÚOA¡à/Lï§!ùu]J¯ƒ¿åˆÔ‡§š¢nú!R»™ÿMP–ôhNƒäYÊô4`|Kj-@ÁßÒN¨×x{.¹}„ãL€w'­lþŽ&àL s ”Åú€Ë¬ÁÜõ µ&0c1)®ÖÞùPÛX¨ý»¡>=ï¿¡ö—²ªö{ß"ð·îM%®Ö¯ B´ˆ¦çV΀_37'üPJ¨¨Tv:bçûZ@B9¾oÙñN*õ•1Q…j ÝËhÈtá²F€/¥¥ ¼É52­ã¿ÈF€¯àpð«T…”ù³òQÉ‚_ûÇ<­É>°ëÚgeV¾JQÁêŒØÆýõˆâÿš¶3?€´üw @™€Òϵ& PfEZ4ceÔtoþ–°2H3ÊüþJM?ÊRÎ3a•ÚòHBmàbç°ò`ß"ÎïN5>¯_%àS HýjUŸ3 à>ðûÞþ Ê|mÒ4bx;‘ô‡Õ§Ï£'ý±Ö5üþ¯(fÆBgÌÀö4'Wóh #ó€Ú‰§L@µ„ˆ ä¶6d)ŸX—ä”™€ L Â^ÄLþmvjàª~æ!¨g`Êý3‚ÜÞ”ëAÀ¾|œÿ} ‡Ù$>Ca•CLæõOT_{à&øhý4ýðOù=|î/Á_Öû !ÿ[}­ô¿!ý«þžÿòü&P€šfÞÿ‰ÏVÞãâ£@I¬Œ`\²»/@ëki­ˆ¯ÒS&ÀßwÔ›ˆŠV‘~Ilÿ”°xmÊ<ÿIÃqààHÓr@¤÷DmòàOr@ÊŸd]Ö¼S®—u2˜Î™yÈ SGá—Žóg0”õòøà—t‘Ðe¿IºG òó#° 3¡¹ õÃÊ7À_ÙÈ4)fé_VýÕ¸¹e<׸Õd>C1‰ª0&Û@Wq~5¥€PKÐ>B~¢Àj®´L‹€›;[¥ÏAžwÔ+™®Þyg¼~ êK¨M‹Ì(™‘ ‘9µž&BËÈU­‚ Iž’¼­Åx¿°‘&‚0øüb¡ß}êOà€²…˜°2…ËÒwÝb Ô*hº$T~¨yÀ{¼ZŸäT ¢ºÿ£çïvÙ°üÍÀ¯ââdhl%ýœùüº'Àµ>kßlþªþ?Ø®ï7µz¯®ú+3ãûµ¾V`–þAÚ-f÷ŸëóPõWÃçlït!5"àæ BéÏ|G"‘)•!³Ñ° k,Á†×ðK@B`é2bÎÛ7Ç ö§’.ê »HÝ)øƒõ«ÃQ¤€÷tÅúò©9Ðìàý¸Ã0—ߨ•@5S±Š+ƒÉG%rïXA`;ø`Ç»ü @Ê Õ|øÌòõ*ޝ Öš"©o*¥‰°ýÜ÷Mœ_| ˆæògð—8?ê~m$´JfÑ ï`SŽý£ôòlæ8ã„Âû_jãŽ@#á?ZKJïiÑ `{£å¯9¯h)—¯Tòœ-ý›¯em ‘‚rT@ò_`â¨^J4g€uq%¬þÖÏ|Î íÐdIXMØá "I½ü¯³½}ȳãï»ýú¡ùè à‡ª¾ì"G ü×àÐ>h]‘·ÿ‚íVÞ”ú@Í¢{lI>“(Ê¡f?ÏÏt3È|¼¢/9øT«êîš«ù¬3Iz¤)$ÉËk­ˆ€k,GG˜@¿2þ“ ¤ýÁê+à‹u& Ò[_ 3Ús:¾Š ¨† e´$mø`PÆàQ…è¸4®GÀw èáàÓAèÌ€ù"ð»M{ü*÷ÀÅæ+>üzŸ{à×{ó>÷žkë9Žúœ¢ºT+ v½Å@®\Ñ÷=ŠZõ¶4ƒlTœMc÷#L ÉÃÓ—-L`ÒyZ¦;7 ‡ª ¨P  #˜¦A©Çµd×Z‘}B?o¹Š¶«ýWà_->gµßõÙˆäšü~IU­¯ço¨ü f µÁÚ`_U›ˆ$µöMŸÅÕò5ÞÑ¡yþ¬í€üŽoBRÚ>ü‘#°åW0- ½aÙ—OmcSf+3‰`yˆeð«T6“ Äq]ò§%A”Ö~L¾HÚ(a4ÕÉòä2ÅA)aÅ4å:¢eízs;Êàë äª| æ@`=*1ç5Ô~z·0¡Ûû¬?×S-¤©ÏwX9ø²Ó¯´Ï÷o’??ߣ†*¯X}ª± ÿ|ò\ÿþüµ<¥~ÓÄ&tä.´ÇZþ«ü§ip‹#PÓØ–25’䧪OÏyfÉn´¬ÉOëÃ+éù˜~é0—S.K 9#8cG–Þ—¾&9È|ª0ßÛÚ§ÉÌ0ÿ5·¬€'¨èwx“<9€JK( $5îßÎÑJ‹Ôz`Ýpöü n–Íý‡NÞ¿_™dY«Ôà»{³_Õ} ^ϯLâ*æÁ<ºú®+ù üt*G%Ÿ¡1ML¦qmžËÛ•Èè X¥QÕ_Ë÷ÀOmbF½W@‹ hû¢ hÌ~ÃEUr'¬›ƒ< :Yˆà¾bUÍÕxFe”¬ªµ0’æÃz­H$F h\¬M 6€zP€î7&}6ÁÑMWµžç¦ÆBûl¤}IÔ}†ålGR¿ÒFX'Zñ´ÞqœÿŠò5ájùmôœ9[OÛ׈‚jyn–DÏ×L *, ëƒ<ÇÍ»¡âï+x·…Â/°-É Ä½–%ÙàL…ùv˜@y¶ÃNªÓ%¶8‚‡ÂèÀ?ËÅÄã_ùïSˆ•á#(çYJ¨4\¥ÎÖ‰?™ÀÁ«Ìroù”µ û#@ÞäYéý8ß0þªF¥^óå÷©ƒ¸¨ùI—ùû%ÎÏ2fn8ð7q}ËË)à¥}?þgç .¿©ýp:ûð]Ê«YâçWË/L¢j?zšF³IÞO5kûMcE}´PÁ©§à¬7ÒXÏŸÒ¯ôÆ’2õ Û]xôÞ€Ðk^èX|Ì§Ì Ò fé 5‚T¿Pýgݦ”Jy #p›?LúªhEfJ°÷ÒCiT³ÓJœÛûÇöù~ÌÆ'(Ê^ :ÐUÚðÕÆß±J|±ñ!Gêh=¿=ÛÒOKAÈqhà/ ÎŒÈÁOéÌø Ïµ~×€ ›ùö^ÙÆ‚üž‘ v}ñSàDÎ Œ˜ócL ·•òy¥šÀÆCÏ븢©êoVñ)(z_í=~Þ‡MœÚ01½/tÿQh/¿çÓçÕyWÈõÄ @}LIvÝM×F˜€çÓs27,ËyUòçöËàî1„⬘PÇéçíC* dHÈÁ”ÓfA5¨÷Ô|LWàÿ°>0Ö¹§tÀÓŽh`*àõÙ²_)¼ßãú÷Ÿç~Sû7L*b^GÁ¯}êgÐbÞž{AûÃV ÒZó®ro1ÖMê1ø€ì¡P¦ÅVv0Áć+Ñô†¼nŒÀ#!#p‰¯×Ð*éèºÀHòq¹qÅ)(˾)#I¨™n;<pp)Ïçû/ßw歀ϼâÙß¿§íLì©" |}Ÿª–+øjÿð—øF RŸ¿2äºïÑÇA{(Tç¤ùÝÞWí’h2ô?,Î9UÿõMXדÓù¦Là"ŠÁ#Œ`R³€LÀ~'`]8äjõo,ëùæú³ Ä¡ÍD"_n\iù…N¹ õ‹©0eSÀv`0Îß9zåKúŒ­ü*é)/àôÏooÔÝw”%³hÊSš}!ÁÏPèf%ð;ðÉ h£à¯æ!õ½\Q–4—™îR>ÿ(2p•ñ¯¸°÷£ÎE¶@‹æH# E^?ÙÖáõ6˜@ñtg&P å›·ó°‚YãìÀº€F ü<B&P”}¾áȤõgf›°ô¥¤ùKÓ„à*//­å«yòx{G'­þÝúóÀ†h¶ò³”oߤ~a¹LÂ?¨÷˜Q{Õéò<«~®¿R÷±‚¿8,ü|‡¾Ü¹ìg@‡ŸhMðËûžäÿ† è3¼Hÿ„¡éó/ÀB-0 êEF´€A&à!¿Ê 7ùÜ_NŠY À©fòš1ƒ¬³UR§5?vœ„epöé"õ“!DÎ;Þ¬íS^ÎŽ½ô½£Y^¥dGõ‡žw€ßR÷7»ò þ_LĆÚ_yú¯R¿Ûùì‹I}ø½iþ«´ßPû«mÆ{à×g'ù yä¹½›¹.»Ò¨ Ôšl½ö~Ö×bR¦Ü8° pªygT ìœÀ¸J:U¯”ëÖzõA;ÈýR& rVqü|ê$, çŠz^‚G Ô–÷û“{¬" z¿À:P޽ó£€ßœ›ÝêÛjmò+pôø¼×húîí}øµ=ýP‡1 ûààWKƒþïÆùMíïNô1i_iLùUã¡÷|í}ésX¿Žud1PÄ \ pû^‰Ì Å$;\®± ý⎂„õås確† „Öœ(R`æ€2©ê%eF Ÿ)/Ì'aÝeˆÏ†iê„TFÔ«ü„ë/7‡Ú9H&'šW ÄRÅá£[žïIÕesP>°óø.õ1cÅçLXÖó³Nûå³)éƒàW©¿™ç ÷Yê$Vû«8?†MïyºÏÿ"ýóq,÷_Þe5xt1PË ]q,"àL@Ú(RŽ÷@¥ 8Ø<<•Ìn¯¥‘‚à5¿ºÏÛ¦¤ŽLªýúU ýï^ý„ú¾z‘†Ï< øÕ3¿ßµ{+®ÿ;(ãí™–Ð/¼lAê÷ÚPû7“z"àû¡ùÜT¸¢~ÖÈïv&àz}¥–À|*Éé¾a’¯ÿ-L€ÇÃÉΣpa èKê17À¼ íyì—‚ß5¶ÑmÏOeÐÕ®×÷ÇgË<|/ߊëßû_÷í6ø£ç=³K'ìš2ƒ÷F) `0 p”¢ˆU SðKµ‰¶®0‚ró=&ð†u%¯L ZRû&à‡3›70Ñ$ÐéÄ,§fƒš¾[uBòD1à|ŒxûŸÂÆôØ:Ÿ-¯9ÀíÇ8\ê·€0†‡Áï`¿üSðL6}Õgãà7ÏUÿÀ»ñ0îJçJi¿Ü ¤L€$L€7Eû¹„y€5ŽÏõú@ͤÿÓ¬U¿åæ7R“Q‚3Ê’\øÄ!` ¥p-¶¥x'ÏfÁÔšN fP¾ à „{ JŸ«| ÚgZpmo€Ü”~±ô ðòùkgØGÿS_çQÖÛ7€O€A¯ëûÂ|ŽcM§(K]›8»i_%ί> õé¸õÿ³Ôïjþ-÷çàÏmUýÛyÿ|Ç5€ÈP¢9Ðb©N#È‘°:´Võ˜à† bP}gOÀ…ó«·ßh“i›8ë„u>õÊë,B zÀ…1ÌØîC˜°‚?aÙ 3‚”ߨfpKß¡ç0ÇöÏ_~ÜUÿGÒß%ý§Wi‘„&xDÚWa:‚£åÕÇ Ž’~môM¥5É_m*r•ûWŠÔŸÄÙWÊ€Ÿ÷9'Uð+C»ÖõWý Þ_ëý¯tdCX™@´F`„ (QÏL xÒ… ü©"ŠI€¬ à{¨RNgn³0 ]Pĺ< 3aã,„·ÃÃ×°MœHÔ&‚õúL4€š7ÍþGéT¯Ò#WU|žËQiAÁÆœðz5ÿ;ê‰HQÛ¥½©üÕTóÀ¬–CÝ¿+¶q~–wÕ_û-yq ò‹ä‡€ÓG?sVB«…ŽFF5gzMo¨~ «O@#Ëp@$¬“a¨FÒžÿ!íx¤€‡: *dÿj†£Ë#(é¸þOج6, /_ƒå)÷/¾0æçýñùù=wÜr®€7•¹Ê¯Œ(-P¯Ï§š/y6q|Ô¾Hõù0í+ßá,¿ïÒ¶ï÷§ï› BC|ÊT´¿='ž3É -ãÏÓßÇÕÎu¦©iR^ÇB# €R^™[a:¯Dp-ƒ@"¬<ö@ñ °ÍJ#à ¹Hy–ÓÏo§ú83(Ì*3ŸX(IÛR€eã$mj;<¼î ôÍ<æ&PºÀr’ ËçÑRýÜFDUý#é&½¸g?4ÍóFç"U˾üšG˜òoäí.ëéÕ>¿í¹£OÔú*ŽnÌ£ÌC0uŸí°o›õü½ûÉ Þ/Aó_×¾UÒ_Í.‰à5Á¯ëQJîQ ` 8ENA‘–¥£<<ô§L€7 À ˜@õàÉ” ¨ ú¯çt¶ÁÚל俘ê/ØÌ%@PÇŒíÚŸ¨¬ö'¡ah•½÷P5ÞTø&ðyèóvß˳¹ZO¯@ô:ü®J»Ö  AÁ|ü^·[ýž_üÍwHþÛ0¦ øá+ª4ÜW©ƒ?b,1`»g¾¦©I@õ^Á1Ù5='Ñü¶Ò0|Á쳆õ&˧÷â&0à(Âðï`Ù{h ¦ßƒe£z¢<ü j )3P_ßAÀk£žð#&ã̦ż^æí_lÿæ³|Ê9ðU[Ê´ü>´çûaTû©æÐ‰lAÝñ TÒZƒ5_Ù™ÖwÈѶÞ$*z$ýõܦM)ž ùtK.FÞƒ¶µN}Iþ·^:Û‹BÚ—g2ØŠ§Þ®©cB>kþWàè+o»¿%u[Rÿjå9n"ðK›ÅÛ> þ Ô×̯÷åÌ@£µ_Èoýuà:ekÛëõš@iXfÚ©ix³¶ÛÍ”/¼I³ŸeŒ+3T‡?ØJókNgý­þ)óÉεø #`(@=ÁÇB‰ú¼ôèÅá'`xÄzçñòw¥_¥ýŽêÙ,Ÿó•õú”ôöøŽ‹ÿ&e<Á,¾ª~`ÃÊwflÏòjƒÿnœŸýÓ¾ÉoøüöÀoÏRf¥3æÓ®Î“3ØzÓó €Ò”Ž:JÇ ëšøYÒ… pP&ÌçaœÓ˜@µo=Mù®'‡›97qvQñ§È<ÐÅFgyAZ™ƒ˜îå.í'+»ÿ†êߋߛ¾|üyZõ ðK„è”W8‘ Ìò³ÔÏòVߤÌ@Wïåk%=·‹Á_Æ·æ×:ÄáXÎ/ñÓ¿>[ÍcÏ~%jy['Š sIDATÛ\1)PÒ²*U9ÀUbª½Ì0^ËÈ ‡2 ½aÑ6šÛÔH™Š9 á}2Ÿ‚k%¯/6bš–gùR Ò(«×°-½î¦Ñ^ùg¤+ð]Õî•7Û¾òäó]J›ÏƒGítTýP ð°¬}¹/xŸªý›8¿©öežAã>ªç7¨ö÷À;êÝzœÞíüli M ØÊ”r0ªÑÉnˆ>Æ5Ö­ Õ‡áæPï›Ï ‘•æ(,ýu .}./4I_’ôk¿*8a‘8ôüÙÖk@?ºÐ*ÿ¤óp0ŠÓ@а>±í7ûÚ;p¿e7çshßÈà,â™|lOËS‚ÆÔ3ί I€2<ÓÝ©¹gó[øoËHùæ7+õöÈ5øÕ‚Ö‰2¨/¨HÍýWâüb … Y¿o–!NB®5GB1ÐS;ÚH×ôZÖò³®Á/¾‚j½yph8µ8}®ÁŒÐð×øŒô¤ÒE7,Ø»¿yÍyò«8·jú?ò” Ȫõü6‹/l_Ëqœ¾'õyý”×çž1=¸§BÁ_1Yû¿n J-àø¥cd)·Pd´´UµªÔš®L€×s !AùÏ: È“ÔlC‡äÐ*uõÿHhQýJT¦àáL­Ÿ^~vþl?óPžzì zÀøM5ßAâ¦Ï5øoªþ¦Þ^hÏÿÏÁ¹m¨ä®GÏVë¿ßÕ@3`D P“ÀÌ$L De¬Ç£ÚŽ2^»…ˆiKkA࿈"Õàh…£¥‡÷MÛ¹cÞÿSÕE!.Ïï÷tIntÝëãû$p¢¾Ýü¨/Znü-M&÷ÜIßadsP5¨j'ÖRð[:š:d“ƒ_AìŒ 2 øðE)ØRöö“ñ<öW¯;“PFЊ ø3JÙ“ë{^‚öŸt„Ñ–Ö¡ƒ\ÕyMóÃï[똷žüMžèº‚ž×£¾i™ð§[€¯ÿ/Vfüþü[ý8pðÏÀvG Õ#I²”Å4ì`ªo@óë©âðÆÊ'º9ø¢ïfP¶ö.í#¨ÊkžKCªiPk@ùDø&‚Àûãý;ƒÈù&,unžOBÙ‹`³—!û¿÷|ïLUÞÕy¬á:ðz«| ½«O„7@_ÅÑiORúgÀ/ó ´ÿ²Þoëg³<ï?çk®ç×þí=ÿ@ú¼_}öãåëÀ”øÔ©òôžåþÂ(Ì(Ü=`U žu6ÀK©]¢2DBÅñ]ºjÔ`âK¤FÀ¾ pÜ.¨´‘É@ÖÁ6Œ±!YûŒ˜ðëý¿@œçË ˜Ìvu7Û`”ò3˜t<‘‰ À˾þù¼J¿Hû bÖ­yµ/šç”´qøEàðÑ|þ³å±©¾­÷Ã{+‹›fèì¿´€rgëljw°z¸V):â6sò±ã¨|SÖ«í_¬/ü¯³ ¹P/@bryw(Jžj"P²¼Ê¶^óù>(}ï(åsð7;ã^ƒò‘OðÏØª÷’üß°ñáïÒÃŒÞn«?,kuUÏ/°ù­çêòç{àýñÙrå".G¾ h´;øBhAÙêœÀàyB XªÖsZجbjsF ÌB4XŸ|º1l92x*1<ÝïÕÉ[ÿIç{Çn}&±a÷¦Û;«<ýæÉ÷üj‰o€…ü/íéûÛ~øK£<ïOÔþ°¿{Ïß}Gž¿öKM€ ò·gÉ¥Z@B3" 7T^ÒГæcA΂Ûs ò˜¬þl¾DšÞÃLÚ?^ohURg’ÔLF€l”ûw­„š–^ú¹€Á»hôžô½c¸~½'>Ó ×±¦GÀ×ð]Õ~àØ«Ò¯>€úýß™@³|Vû«ï\ë<›õüÑýë¯Iÿ‘ç_þÏÒæÜ[LÐ7À?<@"•{¯ÌHtÀ} 1p#iž¬Ù®Gõ!8÷û‰ÌÎ)êŠZK“Ù¯èyyî_íh»%å5o°õVYpõóV™žªïuDõE Î#þîÿ–g/Ï ¹ï |L|›©»½£å ¸‡ Põv@ŒøZ¡¿HÒ²Ÿü &­c/”Ⱥ4f¯L¡·kQ4àüyžÏ>Ž NŠÛõ^—, áù3Šž×àw$~·o pgRÿI?¥™&mÿœ35$´Q—‡W§¯%l˜@ÓÛéL€u&lAèL@_€«òë3Öõü‘FÐØ=ÆâþMÓþ&,‘>#ÕFʃ´‚Cqþ½ct€ó9›u7õ¸´}ë½À¯¼ý£À×2jçkÞˆ9Œ<ý­À×ò×õ?.({!¶5aÅÙE/=°‘8 E€×|ßúüyàËÍ·6͸Ê<^ãÀ·p!"u§uUže5rঅ֯õÊ€)óþ‚ÍóѾÑ_™ þüôº0ŒÍ<ƒ‘ò–Ö;ºqækð~ßË¿øêý¦~c‡´‡MûÄ)b&üMyc"e?í·¶‘óU÷,×­êð‡Ï/ÂëÉý˜²äOø] 8éÑšq~;/qÊ`ž€Û¾º9ÝÛþÚ¨ âèæå¯ú§^Xî$ÔšYHé` ò0ïýÞ¿Hÿ’þž'(åûÍ„ÞóÍ“‘ŠöÀ÷µßx?7Çù5Ý@µ×GÚ×ç„íÂ8½3p)-ïí_ëôÉêjNâi½?Íð^˜Ýÿøµÿƒqþêþü)ƒ¿þ0(ÐgLa㦠Ú!ïœx»æ@’ü¾>¾üW†à!5“¼/Ÿ°šÓ ÜotZÚ¶õ Z¿Þgtÿ9_Xž ƒ+™, Ú{?{Ç^yˆí^má}m”ïù2¶ƒçC}­üo¼3XÝþ®6ÿ[ãG®{6{ Dí·TùÈæÊ⦅Àæ/à&¹””$£ùÊ ¨:gê|•.!Â膢EDUù`e!—Ëöq)/¾‚ͤ¯ƒ{øýñ°þÉÒ“¼ÈÜ‚vªÍAüÞ[÷ŸP;z)óÞýÛõ&ÊWé:ðL’ï¶ïj{f‹òiý­(ƒ·©ë Û ˜X•×<üh€Ÿï°yÿûñû,å;“Êó1›ßÁ¯ï+Þø3ºai\wùus íÕÁ‹Ê,³ìÜ,ûà‘M°q”X}lC'rÈÞS)÷ß’8S}Mðçâ÷¸y~¾¡ IðÔ)ߨ¸ý‘t ãݶ|ôþ=Ÿ^ÓYu>Á¦­9ú¾Ý„dýѼ„kP¿ÚûžŽFûv?aûïòQýtò]!3ý°a¥ÜÀi‡ Ìð†m¢¿ØV‡£D`Œ lêׇ>a³ÓPõñ-O Z”®›ö/¨Ts­ …Xµal­Þ¼?%5M°Üë¦ÿ½òÞþNú^ù!±ü½ÔyvÛŸõûó»®íTícm·ÛÿàÙëDRÿ[†¤÷Çñgþ—Mÿýþ”‘©–ù¾S>ª_Ë“l~u˘å 5_4{n¹.Ñ2°@PïÀ6%-ñš3‚Ö(ÎXÕeÜ·ç,»‹Sƒ™½êÁ-Žj ®²œZ˜€ö‡T"©åY•É»¢öTÞIÀFh·ý‘ô`0W »ùFÛ¼T ~oc§Þ0_«_®Ñ\-Ý®¨Çg‹LCÒr›ú?ž®uRú·Àú¬þ+ éÒáG.BR†Ò`.M T°Bt—^å|„"I¡dÀ,}– T…Ž<¯Ö3ð¶¾íÇ£ûÝ`7‘Jt±ï«´[)’ú €ß]ÿ%ü{j¥ ó.L‡IEND®B`‚allegro4.4-4.4.2/addons/loadpng/examples/browse.c000066400000000000000000000071711173507505700215730ustar00rootroot00000000000000/* browse.c * * This is not really an example but a program to help me test loadpng * on a large set of images. It's not really well written. * * Usage: browse [-bpp] *.png * * Keys: * Escape - exit * Space - next image * Backspace - previous image * Plus - increase screen gamma * Minus - decrease screen gamma * * Peter Wang */ #include #include "loadpng.h" static void checkerboard(BITMAP *b) { AL_CONST int depth = bitmap_color_depth(b); int c1, c2, c; int x, y; c1 = makecol_depth(depth, 0x80, 0x80, 0x80); c2 = makecol_depth(depth, 0xe0, 0xe0, 0xf0); for (y = 0; y < b->h; y += 16) { c = (y % 32) ? c1 : c2; for (x = 0; x < b->w; x += 16) { rectfill(b, x, y, x+15, y+15, c); c = (c == c1) ? c2 : c1; } } } static void load_and_blit(AL_CONST char *filename) { BITMAP *dbuf; BITMAP *bmp; PALETTE pal; int depth; RGB_MAP rgb_table; bmp = load_png(filename, pal); if (!bmp) { textprintf_ex(screen , font , 0 , SCREEN_H/2 , makecol(255,0,0) , -1 , "Error loading %s" , filename); return; } depth = bitmap_color_depth(bmp); dbuf = create_bitmap_ex(depth, SCREEN_W, SCREEN_H); if (depth == 8) { set_palette(pal); } else if (bitmap_color_depth(screen) == 8) { AL_CONST signed char rsvd[256] = {0,}; generate_optimized_palette(bmp, pal, rsvd); create_rgb_table(&rgb_table, pal, NULL); rgb_map = &rgb_table; set_palette(pal); } checkerboard(dbuf); if (depth == 32) { set_alpha_blender(); draw_trans_sprite(dbuf, bmp, 100, 100); } else { #if 0 blit(bmp, dbuf, 0, 0, 0, 0, bmp->w, bmp->h); #else draw_sprite(dbuf, bmp, 100, 100); #endif } acquire_screen(); blit(dbuf, screen, 0, 0, 0, 0, dbuf->w, dbuf->h); textprintf_ex(screen , font , 0 , SCREEN_H - 8 , makecol(255,255,255) , makecol(0,0,0) , "%s (%dx%dx%d) gamma=%f" , filename , bmp->w , bmp->h , depth , _png_screen_gamma); release_screen(); destroy_bitmap(bmp); destroy_bitmap(dbuf); } static int eqf(double x, double y) { AL_CONST double epsilon = 0.01; return (x > y-epsilon) && (x < y+epsilon); } static void run(int nfiles, AL_CONST char *filenames[]) { int n = 0; int k; Redraw: load_and_blit(filenames[n]); while ((k = readkey())) { switch (k>>8) { case KEY_ESC: return; case KEY_SPACE: if (n < nfiles-1) { n++; goto Redraw; } break; case KEY_BACKSPACE: if (n > 0) { n--; goto Redraw; } break; case KEY_EQUALS: if (eqf(_png_screen_gamma, -1.0)) _png_screen_gamma = 0.0; else if (eqf(_png_screen_gamma, 0.0)) _png_screen_gamma = 0.1; else _png_screen_gamma += 0.1; goto Redraw; case KEY_MINUS: if (eqf(_png_screen_gamma, -1.0)) ; else if (eqf(_png_screen_gamma, 0.0)) _png_screen_gamma = -1.0; else _png_screen_gamma -= 0.1; goto Redraw; default: break; } } } int main(int argc, AL_CONST char *argv[]) { int nfiles; AL_CONST char **files; int depth; if (argc < 2) { allegro_message("Need filename arguments\n"); return 1; } nfiles = argc-1; files = argv+1; if (argc >= 2 && argv[1][0] == '-') { depth = atoi(&argv[1][1]); nfiles--; files++; } else { depth = 32; } allegro_init(); install_keyboard(); set_color_depth(depth); if (set_gfx_mode(GFX_AUTODETECT, 800, 600, 0, 0) != 0) { allegro_message("Error setting video mode\n"); return 1; } set_color_conversion(COLORCONV_NONE); run(nfiles, files); allegro_exit(); return 0; } END_OF_MAIN() allegro4.4-4.4.2/addons/loadpng/examples/exalpha.c000066400000000000000000000032701173507505700217100ustar00rootroot00000000000000/* alpha.c - alpha transparency test for loadpng * * Peter Wang */ #include #include #include "loadpng.h" static void toilet(BITMAP *b) { int c1, c2, c; int x, y; c1 = makecol(0x00, 0x00, 0xe0); c2 = makecol(0xe0, 0xe0, 0xf0); for (y = 0; y < b->h; y += 16) { c = (y % 32) ? c1 : c2; for (x = 0; x < b->w; x += 16) { rectfill(b, x, y, x+15, y+15, c); c = (c == c1) ? c2 : c1; } } } int main(int argc, char *argv[]) { BITMAP *fg; int depth = 16; const char *file; allegro_init(); install_keyboard(); switch (argc) { case 1: file = "alpha.png"; break; case 2: file = argv[1]; break; default: file = argv[1]; depth = atoi(argv[2]); break; } if (depth == 8) { allegro_message("Truecolour modes only.\n"); return 1; } set_color_depth(depth); if ((set_gfx_mode(GFX_AUTODETECT_WINDOWED, 640, 480, 0, 0) < 0) && (set_gfx_mode(GFX_AUTODETECT, 640, 480, 0, 0) < 0)) { allegro_message("Unable to set video mode (640x480x%d).\n", depth); return 1; } /* We can't lose the alpha channel when we load the image. */ set_color_conversion(COLORCONV_NONE); fg = load_png(file, NULL); if (!fg) { set_gfx_mode(GFX_TEXT, 0, 0, 0, 0); allegro_message("Unable to load alpha.png\n"); return 1; } acquire_screen(); toilet(screen); /* Enable alpha transparency, then draw onto the screen. */ set_alpha_blender(); draw_trans_sprite(screen, fg, (SCREEN_W - fg->w) / 2, (SCREEN_H - fg->h) / 2); release_screen(); /* Ooh, ahh. */ readkey(); destroy_bitmap(fg); return 0; } END_OF_MAIN() allegro4.4-4.4.2/addons/loadpng/examples/example.c000066400000000000000000000030101173507505700217110ustar00rootroot00000000000000/* example.c - annotated example program for loadpng * * Peter Wang */ #include #include #include "loadpng.h" int main(int argc, char *argv[]) { char *filename; BITMAP *bmp; PALETTE pal; int depth = 16; /* Initialise Allegro. */ allegro_init(); install_keyboard(); /* Get filename from command-line. */ if (argc < 2) { allegro_message("usage: %s filename.png [depth]\n", argv[0]); return 1; } filename = argv[1]; if (argc >= 3) depth = atoi(argv[2]); /* Make Allegro aware of PNG file format. */ register_png_file_type(); /* Set a suitable graphics mode. */ set_color_depth(depth); if ((set_gfx_mode(GFX_AUTODETECT_WINDOWED, 640, 480, 0, 0) < 0) && (set_gfx_mode(GFX_AUTODETECT, 640, 480, 0, 0) < 0)) { allegro_message("Error setting video mode (640x480x%d).\n", depth); return 1; } /* Load the PNG into a BITMAP structure. */ bmp = load_png(filename, pal); if (!bmp) { set_gfx_mode(GFX_TEXT, 0, 0, 0, 0); allegro_message("Error loading file `%s'.\n", filename); return 1; } /* If we have a palette, set it. */ if (bitmap_color_depth(bmp) == 8) set_palette(pal); /* Show it on the screen. */ clear(screen); blit(bmp, screen, 0, 0, 0, 0, bmp->w, bmp->h); /* Write the image onto disk. */ save_bitmap("saved.png", bmp, pal); /* Press any key to continue... */ readkey(); /* The End. */ destroy_bitmap(bmp); return 0; } END_OF_MAIN() allegro4.4-4.4.2/addons/loadpng/examples/exdata.c000066400000000000000000000025101173507505700215300ustar00rootroot00000000000000/* exdata.c - loading a PNG from a datafile (exdata.dat) * * Ceniza & Peter Wang */ #include #include #include "loadpng.h" #define DAT_PNG DAT_ID('P','N','G',' ') int main(int argc, char *argv[]) { BITMAP *bmp; DATAFILE *data; int depth = 16; allegro_init(); install_keyboard(); /* Tell Allegro that datafile items with the "PNG" type id should * be treated as PNG files. */ register_png_datafile_object(DAT_PNG); if (argc > 1) depth = atoi(argv[1]); if (depth == 8) { allegro_message("Sorry, this program doesn't work in 8 bpp modes,\n" "because we don't have a palette for our image.\n"); return 1; } set_color_depth(depth); if ((set_gfx_mode(GFX_AUTODETECT_WINDOWED, 640, 480, 0, 0) < 0) && (set_gfx_mode(GFX_AUTODETECT, 640, 480, 0, 0) < 0)) { allegro_message("Unable to set video mode (640x480x%d).\n", depth); return 1; } clear_bitmap(screen); data = load_datafile("exdata.dat"); if (!data) { allegro_message("Unable to load exdata.dat\n"); return 1; } /* Once loaded into memory, PNG datafile objects are just bitmaps. */ bmp = (BITMAP *)data[0].dat; draw_sprite(screen, bmp, (SCREEN_W - bmp->w) / 2, (SCREEN_H - bmp->h) / 2); readkey(); unload_datafile(data); return 0; } END_OF_MAIN() allegro4.4-4.4.2/addons/loadpng/examples/exdata.dat000066400000000000000000001332541173507505700220700ustar00rootroot00000000000000slh.ALL.propNAMEBACKDROPPNG µúµú‰PNG  IHDR@Èf¯üµÁIDATxÚí]?ˆÛæû¿á;ÜÐá†7t¸¡C:ô C:ô C1Š¡C jÈC†`2“!˜ Ad(C@ÊD† 2tÃn8ƒ7O4Ž |‘^ªX‡ù:VÿÍÍos}>˜¯ÃB¿Tl Nù:Ìô#Õ}¸àL¦dö¤7_ûæ‚©>ïMÍýÜܪ_Í×îÌÜŸ™GšÎûôRú¯gæNaÞF¡ŸïV¿=s?6ï*2Ÿ.„wn~™_Ác"s¡øtp¨“}ü\_ÃdI¯¶Ð¿ŠùŠkof>~n®öR¿Ã0§‹_êçÂ[R‰Ì_ Ì+«çª3êýG暨“‘ù¾yoA†×*ÈñV]õ`õ·|uA&úâ¨C]4W](u;Ñ·ž9£ÇܵRWO_@xJ¦oÕoGæ1x\ˆ[sÇ5O÷èéøÌôá‹ðÍÛÀoaf¾š ¿,øöõ{VŸn®hAY®I¸8•¾b™YÅÒܯÖEµ.Õ±ÒgôõºZ­«uóøÿì¨K“|­º.±8 å« T¯oXX„^}õgÔ¨Ào 0‚¯'ׄ…ßnh¾NýÆæ`y˜‹Ìê‘^¦×Ÿ?Ãå‚¿àÒtf¸.Õªr3û×W_ìøÃpÑpw£Cc¸Bô+ƒ[ƒá ÐË^ýáK^X¸ªu–š ·Ñ” &X0/qFfÊØDcn¶^ó…³ÚšSSxóæ´éÎõ×[2cÕ7ËY ê¿°JЀ˜ûpÒâªâÇ{3²6„gu¨GâgˆdµàÀ>ÆÚÃÖähÇÔïÀÚ"׳…æ1€|fŽL¿Ž7Ågœà¤s`^°§àÑ1&÷óöôÃÌ¥ÇÄk–™Ï2¥Ç›«¡À¦.éè\RÝêË\걘×êÂü×\¨±ßÐ@N]–ÑLÿ×1¯çDÿ‰±ù-Þ^béþÐüEu ÏÀô‡œ)~;®ù/à™­½mF®ÓŒ¾‚LoU!­(pmW4$Æ´XWÈޙߕ…î¿Ààøi?9¦x¡ñ/Ðf7XûŠ 2¼`©èkð >Ù¡Õ'gˆ@„è”,-}jtaŸ†Åçs _¹sŽ Ñ=Çó꿎Ysã Z7äŽ'¸€ÆfëÕÃ{,£¹õ÷<²èl³¿G¨ f¼~"Xm~.\w²'à8„€=sx‚-ð !0ã3 $CóV‰Ø\ÈÅdz ›×h‚Sãç19¾@TãÕžé×1xhwàKá˜+9"¬òI@ãȼøˆœäá¹~¤>9Ñ'gæöBÿ õõéGž™_™7_ʾ+×XlØ ¼ Úå \a‡ Å5„}€±5 ‚ñRÛ^p›5t´Ò¯ÿ-ÞIx“#« ®Kœ[{«“þo†ž! Yy;zO)ìœéØÉ'W ` û1B¢áPÍ1ôBó;G„ûÂyÖK H«S£w†«mdOJpŽ +)ô¯^áQóŸë0†uæŸiÁUF#̆“æ|HŒoe† Î!á©Å§/á:§Unî@" wܹ݉Ùƒ¹ãUaz˜´¬-`±GgÖ&ƒ· Kv4EЎ͆‹É¥WöfuX OÞ%ì¹âÁ›Ú§è4Ìܦgð)Úqä1£68rï5€…ItÌoø=ú‹pUÚÅ<ØÔÇh¸f×À÷IÙ;Ä?{stÅý9F¿ðjiØà*±“¬°:¸@}À¬ñ>l`|%mð ÀS¸@wÉ¥˜<à˜Â\=N¿q6 2&1iaŠ20ÀE…Ð-ŒçlÑK -«*™eñE¾ ½çÞèÁxüpì™}\ PGɵXªÕÃȇ|XoÎH»3‹LH¡·L‡?·å(Ïx ß‚åçÍ% «žÁÄQÁÑ5—»à}b¶fŽ6 —½õxµôáê Á>4o~L9<Ø¢Â"Á/ô0A˜‰B•š`? ©ÈÄÙlpp cÇlŒG&ècC®k4A›á®¹?¦ÔFÑ3Œ_0§ÀÄçôÜnÖ`ʃ†”j+ÂE¨$eKJA/µùÍU:/¢óÄyâ îŽú7½›ƒñC'x)Ã[,ÊK:^`ÔaÓË‹æÁ†7)l’0ÎòÉ\ÇTÃÄÚ©±ÏPO‚•”Ðã*®F ¬‘Æ™À3EÚø‡ ÅÈu‡… FÞŸà‚œ +=·a­Š¯®‹Î©"¥þ›×옟“¥‡ñ˜@7 ¢;™ß0«yÑ?¯ýmŽe!(,C*Á7©ow.jà9)xÅs@š,©ûʪ‡9B(ÀøT÷‚Ï ÎNLmø. ©݃º@DoØ7f‚ôG¦XApgö¿.U•õÅ?<·á nšSt×9™Î3ãwÚâÙ$ؤŒ‚+'®Š*žáY2zäö~vÕq£?¼7ö_†Ñ$-ʪܨúþ;l.%;ÉÉRßrb,,Ð Çt1Ó€&›…ô •“Æø°QáëÉÉÎóv+ñ\ ÕAŸÏÈ¥/ð/Æ™H€SK>¹Í‹ ‹ÈÌõIŒ•gV•À8™@œäñÝQ€Mh^“­¨?§EŸ . ~E¡8*lÞ>h0qnëÉ!Õá8 «~«¬\+ @æ´!ÎuhqÙD¶Pb€O³}£ H,¼kDTÌçBwH›\LdhÀ}Îá™biÏ8°!bÊmfˆ7}ä3Gz+¼I!e…«ë‚’ ¯Û¼ Ï3çEØ¿3>ùµô}÷äçÞø±ç½‰dK¨¯0ù\Ö™ÿš,t!ªGK´„àýJrÖÁ\ç⢓¯k1f¾fXv°&·qaCk›*[ˆša•©Hø_‰ ÚÏSe]nràÙîq±—¹¶bD..Ÿ×UY³Zâ!xsËåBg>§âpn!µXÃú)àe˜;¡¹¼¸:i·ŠJL@XÏ… ÔžeR`9ªÄü]p‡D½yø^"ŠƒÐtû Û«d¼…´á¤ó1EFxfAÈ(xÎm)(˜á 8+‘£Ÿ‚Ùfø"f–-'÷\ûf AÑ_nf¥ó"ê?ð:¿èýØëßsÜ—Qx‘¥K‘¾ª(–ŽÕ?ŸzÕb#b²KŒá¨(ù[0&ZûưÁ«oŽÍNÄø_&sŒxa…bc»8ØN˜=W J&—v7A/}L&ÀL ©fe@,Íi0B&ÒKèa:ZÎ-¾q°À„ G™ïÁ.(…p~͙∠ûæsäº!¤3›`ü“ ÆÎ±)3*MOqŒ ØÀ#E¢åBs£3[ ;>¥Í>…¥ÅdçÙ±™@ 1 sé( rŒ5`Ûâ¢C-… W©0I¢¯ò`YnÂò{ï’á¿{Ï=ü¡{ô}¯{{<|øï’Ô¸„g@¥\!†±€´n¡O®ÿ¦å¨öìhQNrQF2®r”!ñéoTÀ@ÏŠ ¡ÒW± tcaHÁ3O—Â…–N{½ X ÈE><"#"r–\åò™° 5µ„@HÙܲKÅaÈ-CÔ§Q]˜¢karN™ í8…çÙ#À£´Tpö`sM’Üò¨ƘÞ7O÷ç–¿‰!æ´Ó1—s¯0™©¤|„ Ž«µ÷“Ù„…M[,¬+‹\Î\Фèõƒ‚hgäÈ2GE&7 ,€›fA»€:¦åøe¬ÌìáOÃïzÇ¿ú}çEetÜk›® ïj‰ì«’é“åß²î3ÿK¼¹pF»#åD  ™t³”T„qD¹hŸÊÅÈ”69*¬QUC–uI–Ú'l h¶€ŒÈahœK´ÓŽÀ$LjÂ]xÞ±™vû'W›ÍuM‰M=Ã" g³Ý %u(¢ƒ„6XWõCj0r¯G]çh÷` ‹8k‘‚ùÈñœÜœÂfØbÇäþÄK‰c“,l€-È ¬$ìw`󹨣¥Ù Ãý‘hÛÑÒ¦9|øï‚Rß&ü¹õ«¹ö>.¢ï=+GÏãÎ÷ðûþáugð$ô'…Ý;–”:rÑ‘œòÚ^*ü¶–ÿmèÕ©œ“,ló B‚\ÓˆL+?°€Ê3GÒW¤h66›}L^qDkjÜù”–â&ü™8<…æ'¨P2ù¡¤´¥¯†yW€4V!ÃcˆÖÐtdTòZ2°G4/(«ŽÎ©Xj^Ê™ÙR溦H /Ö¢7³ñ9›AëAˆk¹V[ö,èã›§¤æš`GÎÒ>†‹+àcÇRIÁEAß&](xúý,Ñ>G”kŒÍ¥ÆòÞ·Qõ˜Ð\OÜ;,pyàV^>P®œA^pRöG¿ŒtïyÃgQ0+­ÿÌÚ¼1ý>—b¿†î… oà º¥°ÀÀÜ Hxý¯‹ÉMJ K·²Í7|À–<Çh–S81[MátG”ä›Ý(5€ÏÄ@ZðRÓ –T´4ͰdO:æ²#Ú‰+Ë™L[Ë¡^7³©àiâÞœè–s¢UO±øäN ƒ@ë’³ze‡o,G-Á§ˆ1,ЉɾÅÐl¸@#£½Dfê/êŸÔ<Œ·¹ÌEYI8_RÐ!öˆ€ÒZ1!0$¬F%ÚXÈ]G0Qnø”%m%ç°°ý•6ùDqDyˆ{C*8§éáÏ£Þ}ß9Ëüy…¶aaË¿ÑÂâ6^ù™¶rp¤3jdÿ¹Üì\­ÿm?šÈÁˆ0Å®9Ö<8ƒa0å-Q|s[‚O [Ðã¶[”/¥†ž’`¼¤ªý²vðyXÍ`š’…]»‘Ã"b)„`%æ³Í,3, ³O¬,èÅa²®Õ¯FÆÁö»8–U® æÝ1Oñ9ÆËõoa¢÷Î9!ÀAQ•…k*>©=¿Àå+7/ûßn‰±`1íhaÝæc5˜m)tóÖØÍÐ…-#)-àc²Ø!ÅÆaa‹dåí°CSt¹¨Ï>z•ý>VÐ…KQR"Í6.ñ«ä/7YÚ‹ƒ½GkÄpiˆÐØ„$lï¿ÀÚB ¾D²°ž°åoP}О–hñl~˜œ:uGy¼ÙW€(2i¸¥s©Yé50/)ÙÈýbP9 ¯]XåÐÕ¯)9ÌT€Ê¹L~äz‡Á.õµŽ'¶™øÉÎëÃ.µÈú¦àÄ5R0ï.`xn×hHˆl@Œ/1³ 4)k4}¸,гž•´gñ:®£=e›¼D“Ž. ¹Ç O¦RúØqN¦x‰xNàí‘Ugó þ8ä1ï•æ8ãFMžù*T|ö¦e÷®wr˽ŒÝó"Ì*4¿ ËíÁ˜bi=ؘvÊŒíÍL\¬p=4Vÿºü³èFZÔrÏ@…##s‘v‰ r R% Kr}ÍŠ´Xp ÈØpæ)z¥.ªTe¶(“¬Œ³Bßæeõ†wGýßû£ûc÷©¾ ËEùOðkùÕÖ$|Ìš(löY‚×ÖH¶¿HÛ›S›kð*Þõoö‡w´?Øôî’ÞÕv¸sÐOxçRøè›“¤(Á&ÃBOKë´' ¢[Q‰(æêt©ýgpªýÌV}!¸Õ'¡{)CÊø@V• ¬€‹,nZÈl£ kÇ…eø±d/Ô Ð».­ *×–PCG$\ËåZú†U›+‡ëJ]™y¦ íYèJ`®o#å ½Ýç¾óÔ?ñÝ¡æN‹”ëŠ9vçø4Ð$ t@ƒ”¬ŠòTd¡©Óˆ–ØQläìYÏ=¤I(<­+âiÔƒeàKÛ× eóÞïÿUxðåáÉOý/ö>ßg;Üù©søõÑþþ~l4P­ŹáC§s£Ä¨-Ç+á&ªµ† +Çd$Б×{-JŒT“ÊZBØæidH„ñÈK£ÌêKZýÚL4™gQS^ši6‘^‰Å .®`ÕêI%Îd(Ô{¾HÝgþð3zè¨m]ƒÖ\ÿžÞ†¿ï[—)1,±èL¬Ñ.¼ÐJh ÌþiSïaDÅ 0>5­6k'¨ð$éÐΙI\OpæÏC$¦±à?C:ZÔºðú–”De¯×ʺ&³¬ós÷ð›#Û½½=ã9ïïíí+OZ™ßáÝQt'“´f)§Õý­ß¿=Â<<£×°¬fY-1— úõNdž›…M b\”fk KPp]Ýjî-l¾ SÐóš®°Ÿ‹á)¹%Z‚f ì ¶•ÛQ>IYkoÈA§E¥|®ñoxw¬™jç‰FmÝ‹þ÷°)wþî@À ¡Å-Mq^¹¯"çU„ß Ë.`AI©ÒÌÄ®© ŒÝ TØñ¦Ö'äÒ‘µ0sŒy¨hÔ,ë™ÆŠvo âóäà«Ce{UÀ¦ ïþìâ?&›Õýµ'3« «;‡ßî;Å ™!ˆÞ ÿ.73X™þªÕq“`$ïðÁú&}’hH¾ p3¡ÍC}äÑ9z7ðâØõ•[ÕN¾>(¶¨å±9¨®ÍÁEÁÌPÃótôÈëÝï9 ·š\T§TõRÈ¿‚‰õwÿ%«™fËÂ:¬†¼”îX)jYJ‚D$BšˆšäK™Í²4í)”•OÖ‚ËDëˆa’Ud‡É„* ì¿ DuÖýÞhwÌ0Þ=88?r‚7!ä`d¼· ž^P³{F='8ö¹´Ýù uw„L¨Z ìò“—–¨ œJTÉXØò/k’¡^A•äÂÆÕ!÷÷gb’ë¼>?…÷$t‹ú@³%éd¥Úˆû·ÇêðÞÆi^’PÔ6iýïáBÿ>Z`ª gb+GZ¶I}!¦u/l¹,lT`jSˆÁ¶84¥ ÅævÚŽZ”Vî«´ó2)ªh<ð^úÊU>úöX›ßÿíb=IþÀ™ÏöT˜' ži^ìîí+² Ú2·(" *«þ‘°Ê$å¥n0ϹZl“YÔ€3ÎmÊ hüÁ=³l‰Ðî¾ fE‚w)UÁ¥(ZÂtî¢r^†Ãá}G…»\ .–5V¯$ùýëdeÿ¾¡¯ôŸ á¢2îÖEÚ¿ï¨0ØJÒÈi ÌX þ#ŠÓÈTïxÜI0Ãá RËc2cöÉ5,[Ë)…ƒÓWc°ÀÞ ÿø»ãÃ¯Ðæ~Æõ¤]åW«ØxwW£úø‡NQ”–4^­•íÝÛ?L §Ÿ[Þ³Ê6‡r˜7/i{#R/Œhy¨Î-u³M‹Úä±0·c\øº3yTˆ¢ÑQ"Ò9…ô+½¤²˜jæá´èÝ 8ñ¬à‰*ºU›6åê_×¼óÿ­ô-\貕 M”,@¯‚®ÿ:Þ{ñ¼—•=j„±ˆ*pEú4‡…|cÛ09Ì.ùÏ–'˜Û) }Á-r‰PÌÀ¶êªn{+|Û`c{5z¿:<ùáDÁµsà=ó:?w5zwvö¿ØÞ†5ª\µ?r¿;ÉÌT‘‚Ø]ö“B˜¬1ĽÌ0a ë'6夤Iv84ÚÎ@ùXpnd‚öœ‰X—» ôϹ‘Ð΂¨K/Èù)Õ¢IvòËÀ?M0qe$° ëm¤¼èrU§åÿ[űvþL¸V–s½¨å[£†á•0¼fA ·¯‚áýñàîÈ{¹?­DBkJ1 Ëʈ~CµL½9-ßI:‰)„0ÇŒóUéy°Íq p.8½K÷Zùnr&Æxï·¾ÿ28üúpïsƒá]]@Ý9‘ÐÒ†yo_WÁ°óØuŸùþ«P¿óK7+Ë‚x,Ö/±_Ÿ½hœ?$;þ2¿P¢þ`\ë`=’¡d¶cFú$õΩæ(óÊr!^WÐXÒzõqY›„„ãAòêø—ApžúïâñoüØsÔç}EÓ4Qð²Ö+nûdþw¸Ó;ŸÎ´Vm攑YVÍ2c²¤î¥¢Þ!\(!z¡ËudF]éöÓ–¤{§„ ¶ì¬Q\ÊJL,¬¶pÀ'ÄL&\DR– ¸F2£ ç\hßKî. ³M8ke˜CÊ¥=ò†\åvíß9üêèè›#Ë“Ÿ:ºbD? Ìuè2„•Yîû/|e±Ý§¾‚ñÑ÷'‡ßw~íüØ9ù©×¿3=ôü7qRTÜÌW”v"ÞE@,ežÌ @¶­jn/²àÆ@¹T{§‰SÞ\° ¶à‰qvœ!‹Kk{á¿Ã‡ÞÉÏ}u¡œçv£„$%HÛá·¼n6Ãm*ËþàëÕrÖ²‡A4XÓ*ôŠåJ Ë ¿(3·…  r|ë¾”÷8zà8Oýdž±PRd© ‚ua”@Åò7‰Á^à迨I®ÁÅ!¦s1þkf_-€sa^Ú¾_¿žxGßuö¾8ÜÿòHÝ|u´p¨Úƒ¯5Ûù»›PÝÛÛS0§º™ÍRÇîîÁ—‡ñEÒ½ÑëüÜóßhñu«Œ³Â°Zú»ûGßv‡<ÿ<>ÈtÃGãìÌÖ€øAhF¹ 0² W¿ mÀÂúÛHŒ¡]ú:Ðý.-’#jRʶXŠ6iå0ù½[Ãã_úÁYÒvÙ²€£QÖ%²ŠFõ¯Ñ¸Ûù#pmöÔF¤ ÚPÜ6¾ JÀpö˜YͶ.R!Gn-.³¶£®è–ÐJ’AË·¨ÝQÙ2c$„ @ü5$¥r_(-Bf‹%ÚÂÙ²?<ŽÌŠ×›¿N2eC´¢•2¶ßž~s¬@»·¨[v,ó¬Û»Ñ;þîX9ÒŸ;ã‡ããïÕùõóeçtǦ¬wM¢zÙ½ƒÝÏv÷wö”a?r_E½›Ž÷&Ž©‹(¤,4{r4 Îy£ Ì0uÕ¿û™®')< ºÖó°·Ðû} ¼hïu´ÿű2òßîópôØW¾h\T‰lÄÏ-ý“ ¯m±šS®Ž[`Æò”Î1Ó³r+@ebX)Ÿ m&Çʨ3Þi:x¨§‡Žžøá´HI%;+m?³å„Vv†F.‹êJ'8 ¡8[®m»M«- ÑFûúzËt¥??V½Ïš¶J2›þF#®@=ª•M5•«ZäóíT”ʆd°q»ŒEÔ’*– ;ß,.l’õbs rÜÈv%BZ£¨R¼V^T±xMf5D¤\Ésý¹5/¾¬!ÍjƒýÜŒBž£™YޱÉcUv¬„ÞžJãÑCgxo<~àônô»¿õÔ¡fÃÜ5¸ÝU¸Ug”ó MWúäîîþûÝ_»Þ3otDÜ;úöXûÕŸí*¸«àøûÎÑwZV»è{*Ì>9ø¦Óý}g%zÐ~P g¶7Èâg ©;’G–A׋ì†-\ ‘g&%ƒˆblæxÀ5/Êѳ°{kÜ»ãzï’hVáNJú!¨4Ä`†ê=ÄA¥åxK^ I6‰«µˆ×Ú¤#šÿÝ̳n@ºµ€ò)lµ•ÇXµý­U€Š6 v1‡²ÅÊŠæHEX¦æ³½å]3%”¦b A\ÚT'®K7²ªs,Ó´‘¬‚³Ì;KÝÓtô"<òTàÔ¹åôn¹½Ûc½2Ôý»c}ÜÑG_ßq´þðÝq÷¶sòëðäÆH}«ÏôÇÁèE<~™Œ^fÃ7Ùèm6~—ßã7Ùàu1z­îgBWp(ÛÓ¡|²¨ŒôlŠnX°(a1ee•äE:Ë¢ÓøäÇŽûÌó_Îcgp{  Ý¿ÙWwøPÿU^tç§ŽB/=€½:z|Ü0Ϻ3<üú¨óK¯óK_]£ÿîŸ%É¢JES^”Û¡¤<ô< Î#šYâxû¤¼é‰-ÌŸ ÙMr@Pøå‘TÌ"Í÷`’ x›£áã ˜–gÊ2÷K’Z‰‰3•ÕK—5%íTèò"ƒ¥>ûÿ»nªÀK=ÚR$hÚÚ.•gÛäm«¼\’oìUC%·!yÝéZ£i£K^êݱl ó—öÂeR¨§uqW=Õ+íx‡8·á–$}á“Ò?/ü³Ây“ ½{^ï®×½£÷ä×±Â^ç¦Âž7xŒßÄÎÛÔ{—ú™ž©ÅÎK‚Fy¥\GuSÌK󚙚ºïÌñ&¿NF/¢Á“ {×WGOÝÞñ:w¼“»þÉݰ{?è=Oú¯ª g‚MH5ñ37æB,ðº´ô¹ÆÎ¯ž¢(5CãUðqIiÑY<¸5t{zfÍ ÉÈ©áqsÌÁ˜Â1Gb™?³»,l0&Q{ž‡ä6¦@ÐÎż8ê”°ùù|=zvnŽuKIQÕÆ»‰‘w8ª¢1ÂNL®`Û™IK4ÈXe H­`†¤W!U“ùX 0WuF© WWGmÇs[Úìr—Û奪¶™©›òrüj;պĖk«2Ûèà¼qQÚ/åFrò˜Ð‚Àê(û±Hv¯‚‹Ò¿(<ÔW±jÿ¾×»¯QªŒjGÕ»Þài4z•Œß(“›yçE8«`¹D‚UkGï.ìèÝ8·“8½ÄèãÂRêâ]y0ëlŠþ$ pð@98̺ˆ3T¥Ä¹õ*ÎÄ4KÞNô!-òbY)ô¯ÃO8eå>÷wÇɼ`~˜c˜ue’9™ÍJAºÎ¹°}ÑÐ& ÝÑ.mXðÁš‡Ì¼›Äb;j÷=ºwÝpZ±#ˆñ|[“û£ö+$Æ^‘ùåtf%D”*K›±ýÄp¦©BÖ³F+XÕo†wCÞ˜‰F²‹¦Z7“á—p7Á_J†ÒjCrµjök¥ZûɶÍeeG7@bÈ”sÊHƒål8e•2Œþ$s^Ççáàaйãœü6VXUÖoð$½Hœ×©³?«°~Ã% ^žcPÀòh™(„ˆÁÐa\“Ý^Ù ³½# X)r¶çö¿ëúðñ5²ª:Ú+±/4²HM;ºªë«¯ÚŒ³°õ"ˆeQÇ8[Ö*´™–—Èr_bž œ#y@[¹IÑèë)8Oµ%;¯RmNiÛh¥ý9ÃmªŽ>-6IÉñÈ…P”49³‡"19Þ6ÈÄÌÕ›‚™µŸ#’Gg(…7ž ª;Œ8é6ÞA\* ‡¢­}ÙÊ0ö–«O2H^®PÌNi +„Ù˜¥.”ÃeXÀî»VœÄŸá< 7Ãm.`—dŽl4Úœœ§,†¯¾úžÉD˜ãž9î:]“¤0']ýÛ;º˜dn]u¨óýæö¾þ¯ŠŸ÷½á#oøØ7·Þèià< Ç*†z:ÏC÷U¤·±÷.ñß%ÁENTT•S=iIÑ\q¦V”™;êÏÓml£çéézeZ–ñ¢JJ3y¯¬`$Íõ¬›óÖ²5é+ÖíyAçKºÏ…ÇgõùA6µ$€]mt\•ÀK‘Çb…`2Éif\àIiü4YÓ…•>‹¨¯ûì˜ufvxl0%k nˆÚLqšFe3Gä™– XIÞ´–f@ZèfÔËNH†YÁ!­æ€ZöY×g‘¶;jtdv²XL0·2qÊùBô  ãáÇ|ªÔåºV ðÍl*àÊØ‹^ ²_\Ø~ÝÐôNúØê „cÜin•øAßæê9M ÍIStOpVe½LHäˆ2aRÔóX4›61bÏ_)àùg©Â¤û&ñ^'ÎËØQ»ÿ‹Èy5zñ> ´ax «Ã<ò»œÞ}·wßì&»inGj×è¨[sôÌaîŒ5¹õ–8n»¿»7_Ý_'?öO~îu~îŸü¢DªôïŽÕv3xè:ÏÿM¨Ú€ó¥Ýgì°»¾¶Ùr¬~Ñ.P®j“t!DE$.ëN±L¼­ÀÕl[v“ã§v|!L‘µÃ„xݹ_œ´ÄèÈádíL°vÔ·¼o?“Ц8°GM¬È+têb˜:¡uCò¥¶Õ^Ð ¢z92®r[´d© —§«œ™[ówÇ4Ï'ÙÈ3r–¸”bIaÙ8c~{7eU}º²¡ìòÏå𞃥,³·F$XJàK³ÖœuÍ9f_c‚‚ØÁ'6úæëðç6wåÏQÈ:´ü)²bbšž,„ìF‰Ép¸Ã“ßÒ…×^Ø—v°ªÌ’îõÃwÑ'eù0‚±Ñc7¼H™Ž†‘ðBD7¹› ³Ëƒ¹UöóçÂõo2v4Z•寪AJ(ZD’Z8#'ma›ìØ·¥KŽ …•Ô†hÈ+ŒÒíÂNNŠ‹Ú€¥P(ØÍ‚fµ±ÒeLIM=»@ùëˆTJÃQ…ã‘k=!4°"æu…2ÝWNûøy8|èun ¾Uîœü6жúiMR´d]/†q±@tÎeËz¸º´É㲪•Ñf¦8ýÖäJÊÄRÌž¢žlH`0k'ÊI«QИ0»;¡ ~†cŠ|rŒ]ÈáH1×X6eÆg4ÁóaL®/fYhÔ ’E3¸¡ûxIâ”'€{rôyéZGÖüELžÍ„4 ‡šqY»Æl*KºŸáþ¸ª>-w§‘üô^þë˜K¦hßh­ƒ„:”‚A×…*·ù˜ ûêQÊx”@8õfuag! ÀyÁXôýB›¡QPG}›ê ¼>ä«“ÒBÂÙ÷Ï##óÎÂ^Ì_Ü\š'‘Õƒ…-z… ì¬ÊB¢AiÁ˜ R úòl[ÒÔX(µÐÈçqz#È+ÿ¡¿€Â†”! !/£ì1íå.…µ%E˜Kt®Á ²éê>œÑ'íÁÉS‚®ñcr¤Á­…Gâ¬À)Ò‰8ÏäÍ…äYDïÐÞ§@Ο’ 'Á¡M“js+¦cÙH¥µsMĤä=ÀÎ7:‹?)Õ¶Y–X®Í õfá€5â!G¹ÍЀ•¡7É9wfy”%)À\3#½˜“„Í™ß6N5kwz3tLbêšVßΈ ë©‡9ø<—+à’AawO€ÊÛ(ˆ1°ó¥¿Aè¯ÊÅѧÁ·ØØ -Ð$ióÙ}–Z C‡-@{iå  §ÇPÓŒ[¾o¢ûÒ}› jvÃÉï£ã‡G?:¿ÂGOTï ¹ã§¾Ç“HãZ5K;,Yœ–¶y Ñ>"$¢Ì°‚¤läÁŒñ™ðýùfž˜#…Àlž£ñ„ù€c£Ûª,ðàl=<3Ó ¤õý3Bû…¾?"¨ÃØsÄ-Œug8NÁÌŸ;]¥MÎÀÀðöˆÇ©2žýËŸ{æÔC7·œ$,“º0*„ ñ4Ó“ÊêÂùå0.¥ûÔu;ïÍ%Ù<á»Dˆ8Êà%Žäû:¢A׊ÕH¼¹5°µ­0ÓÌŒíõæ¨OvGsg–˜©¾;抠ÐGŽ…¨Èì P‹hd!Àöe–óaí)êÆSÜ|A¾ú1 ¯'š<‹g›=xuë˜[ÆP‚†aŽs!QgÞ¡®Bβ jYAcÜIö@=Ò™¡ìA@òA]ß“…M¶XwVWš 1ÑÔ£à\S ýILËx^ÆuE$Œg—¶ÄêBhSJ$È.Mp{ì¨N™"•Fèùæ1Û+ÛƒÓK‡7Å;ÎÝã¡1¼®åŒ°cîb‡§zˆ‘ú`\kD5ÄÌSÚɤ Ë›ÛÐ.ʬohÄ]ynÓ`3ƒ¸^Àì]PTLÛA@ 4šÛÜUœÙ{P†=p´ÿ¼jϓ£ïN޾=öž{Û`9¼;ÔbÑÿÛéÝè]În¯„XBx{¯ÂŒÆsÆœ‹¦H2佤9ܽ¨é³{6&ipÖ=àfý•÷2äÛðjÏH}k‰±w¦.8@˜˜ø¥Ú1Í™Û*N`2õ<F7†d›9p‡èÌ@FÆ" çµÁ8áFÕÙ;3ü¯›#>íðGÕyÐT‘¹~ʂ̾A¯G°‡÷ìƒ17ÎyP ê˜OÓ¤¹Ó^&¡˜D8êÌ•MŽB‘r'“Úk Û.›¾+‰FsÑ&–תPÑÑ[æ¦.}À0ጦ’f@rïÔXÚsò¥Ïô1|gLñÝû SÈÀD;æ< tùf>(*š)*ÜàÊØ£b Ï^€]˜ Þ ; ß©[`(ÁÏdÈjþ$+æ%v8SÕù¥«üçMƒ»«~ -Á£{£m°tŸ¸Ð‚tôÍQY^Í+·m’Ž{êË‚Nø–¡2³&IAÝH”“÷©ÁÎx”JðI³.Êjí–1Ò€§.økPw§è¬ikiœ/0È.!ӄ܇æ8³Ê3ÉKÏŒ¤Ò[óójÊ~ê6CÄSúÁÈXàŸL¢CsÆÍz‚¬Y±¸×g:^ƒ×w3œY©î8ôøÑ”vcÌbÅ÷ÏÍçxÞ5‚ÞÜs?Çñ— `7Þúzs¡åÄRd ‡Ç<œ™ûv–‚e \hN5§&*À2_æ+}'P~ði¡Æ¥PB„‚䓯0•wt†CŠÏ…Æê𠯲·CƒÏ‘¹3§úÔ˜bx _GÈ _P óçbêçLp?2´®Xšàá»ôiL!lÞ!rã “db_P&ccbq"m¡ÓWÝ_{YV´¢WÝöo ¿9R-—å6b||ŸüpÒû­FWKfÙàÎ(¡`6-ĵz.êŠtQ@½¡éãõöPæ;2‘X"Âjʧ—_ií™ ÌÐC¨ š%tžŸŠy!{¿ ™â\u@&$D†æ;‚_éA“æVÁRÍ:o2ÇÉ8`ˆ¬Y±Ú˜ûCãÖÁoÇêül=œé;xr²LÕ®ù¯kî/ôcÒcófôý6¸ÐÔ¥.ôÛÍØ•<ööÉçHF" FCDÅ?îå†ÎŸ”:ÛÁ½ÚaÀT¨{Æ%æC"-±"aHiç€î.Qj)…:*>ÕrqÌ»ÓfsÕ`>'4‹êp|{ª‘ì0æOÍù ãNûŒ›|F¹kЇ=˜åKÄÀ€ˆ"ÚÒæôÝ\ Á‡2Õè‚\÷ ‚1œmè~aëÌ<Ƽh̾f”."+?V¯äúïj£U³ªŠEY­ªõªÔG•UˬÌÓbžTËBÞ¯WOÒβÎO} UnLbËø «O”Bžžð ˜äIŸ¨S—c®‹):1Et Œ¤GME;[ç«çÆ`¯¨¦®ÐhBË}f=^ø¦ÆS\HBÀ9ÉL„eÎ+¸Îõ­:˜Tç&GÆêŽ:96 Ùá§N"Â'¸À¤h½YÌÌÓÍýÄ™AæÄ—†794H»iö2ó‚3F ûÑáí‘qiΞъš5KÁ9]"ŒÅ¼Ã$òDøÏÎÅÌv¤"nÍlÁiLã Í4€„Ö~ `Áš)‹:f†Æ9bu|Ž.ôˆÜéÍòEÀ›‚d ¤§ ƒ!e˜%¼‰-óªÿ‚OîšAGCs@Z»viÄ¥íÃüO1§Âõ°pnóX˜ˆ.më•óØ=_"r¢¡[)§Õ"Ž^:Îí®sódxãxøÛÉøf·˜ÇëªX¯®×RNçÙÉÏÝŒH¿¨k¿$EHê‹–:;L5ëý!±l[`í-!žˆ©fÄY’[ñ÷XÈqS8µ©¯ñ„2 TÀƒt1˜Gä„[ vÕXàØä))FS:i•¶®dx•-ÕØ6ÀS_4˜tm–ÏÍWK‹@;2ÐIýx3üW=±wf|ò9ކ7A#6Óô½€éÞ:}¦wȨ¹fã€é¶øÑ¦6Àö3Ì«ù¹Í‡…ÝȾ4kÜ©õÁ—‚ãRÖx¶édn9Ìóû´õ3ËèL·°%Ÿ¶ Œgè;”šÓ ^ PÉgHG;SôÉÝs[[r'6.òȾn@|]pÝáEpÌ÷šzxYv–s ff†Y*ÿTT•ˆÎ¢vÄ·Àdxo¬àj»´‚²ºE\f~ø¸ïý~”<í¥/ûÅ»ñ:óÒwÎè÷“ªˆ×Êkû\]Àšû•üØ_bŠ™ðýj»JI‘F«ø¹³ÂB¹Ì… †Œ5u+ÛcDÌ„$X Àï‹YÊžl&¤.±ß!à„©éð]›3:GS¦AuF¶” ÍØÖ°4–°o°:0–`8E‹ †t`îè“ëþ)¦HaOW'SýÛ¾Aµú•z±1³ó‚#cÔêŸ"Dû&ÜC=›oþ¢Cær4ãZ>F€pêúòæµüVP—cE1,«˜ýçDŒÃ"%¹yˆ3[ãpnÛè¬~r&š¿i¹{"`Ì„—{8D×—]âsbbQÂyT7 ›Z1˜_O”ˆm‹rl>íý:¯Àq¯ù£C°Æf­h§}‚©lÀ9xÚÐddzO‘Ó­¬w‡.¥Ùø ŠÞ¿5Œ/’Z\»_­‹¨8u»'é‹Þú|°~×/_÷×£õd¼žzÁÃ~9 ×e¦ípU^ËÇ“¤û[˜·@NJ€“dŠŠÚ‘^šè·ÔÄéH‚$e¼R’¦,”0-Q(–í,¦ (Ofs1ŸØ9ÞÊ>Ä€ãÀ9š¬pzyŠÐÜB̉ôž9Àc6ô‡ ÆÃ:ÏàÁi¿z‚–¡Á$ž1Ù¯ÁMñà@NÕ0Ëçtç‚~†!úè?Øp¼1äÎŒm7Ö΃M±ãÐØØ¿p\ffe1‡ù¤$b³#=çDŒ`ÇYX !^ˆþ! »%€}Û”FbÆúHÜe:ÅL£-›j°{.’Õô+ç½å1¨mÂH›zÃ][—ØÉŸÛ8Ä!Ÿþ–c’dü ·bÆ‚*G®À¦QXÈ1pœW BÉ,ÛÞÂ&/úñ½ãêugý¶»>í®ß©£¿>í¯Ï†ë©[ž¹Õ4(§a6‹5ÚW×°²üýß,‘ ½ÙR?£Ä•aDaúJp1[I„ÇÔØ^fA†ÆƒthD#Ô°wi‡¹¤äÐ…ÀǦ6µ²\ ¡ÇEfŸÊ{h‡/°Ûã˜MÙ 7ñÁ9¥¬„; –vpHMÐ28µ>GS<0¹€Öp‚ ž!Gõ,0ã܆fkó> Û˜¼q½Y˜ ehÞü˜Þ9$ä És-Á‘vÉü¸²lI²mQа¶8avøÂNIs«i_˜åÍe˜†…üåSà B7#o“}ijî ¨óbK8‰è"²$"í¯¾3¡úÈ'·9hLfЈAÆ•y“˜B3ÆöË‘¡a;`–'H,t:ÀÎiÂèÏðä$æ01½ ˜jz½N²ÞÍAFŽf":¢ûøÑqñ²›=9N•/NÖo’{½Ú»ÊïÜàñ¨Z¤ëåõ,°ÿ:ܱP”‘ìlQ'ðJâSVÚ—.prrDrí¼åûI±©6ZÔºçYGÒ*B…’±pNDeJÚ³ft§8”ĘhŠX»(¡¥C!0¹ä¯Ž¨`{Ïí‡äNkËyŽpÕŽô!™ŒêÎLÐgÖƒ|N>ö9¾>:sæs|{`Ì!M3ž!ž ãpô#¦”„ƒêcH÷ú¤ Êî´¿°#/0ï`¶ÚŽ{Ó…âðŽÈ(2geû¥h£_†ÍÜfw,¤©î´xWa”ª¡†[ö´Ý ˜]ÙÏ@Dh û Û“ä“öšG¹+ËzÍ%jz|ì0ÃkúÄâ`;쑆¿Å;^”åÝ3"cÑd†à]Ú»9,ª6ç9‹¢‡½èÁQñ¬S½:Y¿>®^§µ~§|éÑúB»ÐñË¡÷`Pe& ®ªk%±¼çþø‘Ëý¡:âͨXú¹Ô_åÍ­®½3EÂÆKLYéíïUÎ ½Cw`~ I²,a*¨A±d/5EKHqq ”l e~ŽCñ.ýy-}5º@Û„ŸÁ)ó|Ý;G4ÎÑröÍ1€€Ö8_CiDéÚäá9b,mÿŒ^Ÿ¼hÀ³ ƒûäÉPcžÑ©½Çxj½‰áÆÀˆaª¥±-d?×–0R+ €Óú¬N9ÚVÉàϱôȃÜtŸ‹öW™5†(à’‰WF š¡WìLêßYclKšÙ;ØÁ;¡9 ¬,9·s·™¶rW°sX´Í;C àϰ]{ËŒ^J>["×\43hRÀVŒÿ.éݲ6jƒº\T•qô¤=êTo»å›Núä°zÓQÎsöìd}1Û›½»wºñóñºHL"úÚ•¤ñCÇ{–$(“,D%6Ã-är0¸˜#èMÎÓ]!‰Âë:/÷¿íw~‡zËÑÒÊDM—U2`&Sº°m€ÉÂ4 …ϳ |1=_jŽ%=̉Ì0ëËiÎá‘m)‚r€j~Û;[÷'Tu(¤ #2[ hlß™_ÓÃÎô9_Oœãë@9ž¨oÏ×]`ØzæW˜Ä¾@çÞÞ¶›á½h®lc²zŠÆÅ9%]§yšÆqxC;ÉÂŽi6– )dâ 2\ØU5(²Rdr" NØçTìɈòfÞ¥K­‚¬±Óhñçlùä>­Þš ìÊÍž‡ùD©ó)Aí‰f)¼Ú,:÷3°‚Ñ/] ¦&@‰QKÿ<Üs ‰½ªªYòÖ ïw˳AuÖ«N»Åónñº·žôËóaöz=í»wzѳ±6¼‹ìZ¹+©Õ»1Ï“Œ&T¤DÞj3‚wŽi¿›„"³ ÆoÐHFz‡ßu’cƒ%ùh¦ƒŒ·’’¡ÉMiü…m>-p±í¥¬Ö äP°û ¹w˜ËœRºòR„^ÀíH䙟çÖ̈l?<·píÓy­ù•þí©6x×§áCNPÃÛ?G«;à­Œ9{Úg £÷>ÁÊØá1Q r!,…ÁɤØÂ’at!<)[±c¢/D¹iù†úLNÍ´Ym\5Ås›å ¦”ÁžÛž¯€¦fAVÉ5¬Q¦§ÖØ^Ž·9»Ñœþ¨<ƒ+È,Ë—Kmøž¹Š›|Ð ™XΆ¥)H”:ËZ Œí¯Uïö(-Ja5€Ã£jæUÓñúbTžÒç½ðÁ‰ûëñø—#÷n/yãUyB¥£r³±Áé¿×…NgÙÉO]è8Ë*1"˜RY(0VØ1‹k©ËÕ{ºïRe¸»6ô]®Ý×Ñþ—'á´ˆÌ älmçàhn…¡/$½1 #¤ü<\4Ÿ ΄´Y¨Ø  §Qí» Ðqb±ªQ`ÓÎѲ!/ÈfÔõÿÜ7 ê¿#{kÓ{‹–!MèÅ3úÁÚ 7'ÿÃSôÉûgX7FÇH„œÇ¦RósZü8KŒ22À6u)f9OŒ°ñ3;D>ÁxaçÖGÊXQ&ž.չĠ@D¼,ÁÅ"›X-¨šb¿ޭ‘ÿ.®öXñiàÝëzÞí®·<è+›œMÂ23ÞòÚtyycÓs^­ßÛÏ Üf÷©7¸7¦Ú`äzo†¾S“ÇÊÐq> Œ_ÇÀ£ŠYðÕ½Þ›xÿ«“hZ€½Uo7!}Rõ"ÅûÔmy}ü(J”¾ ³íâ ÁÅ©~Èr1Ï9Ç\€VáJ»©ï0„ɤ CÌ< ‹ÀçdcÏ>ÏÅy8yfÁÜ{‡[@ÿ¹Ðæ1#£é†m‚þ4b›fˆ«-¤/0Ó6¦Ý›dgˆ[Ìòˆ ‡t=¾V…A"joØI)»Ð»ˆm&Oî˰êË„»€ ôÁœÄøÍS|‘–`;¢Á³(QØÜòB‰€âNk±;Š›æ”£â :xS¡HœÛw‰ÞŽ(·õ’pRöùº‡‹'€Ðoe!o=·3»àdÜËùgk~s¬C‡¦ÿ6îܤE%æåUÕ²Ìf‰Bl6 Ë2Y¯ šµúqƒ³¢ìþÚΓ’§dTØ“””¶õ€JƒÒ*ìèvyefß&Ç¿» ’›V¸Vb`çetðÕIœ¬«Ž¹è>8¥¦•Sóõú31%¸f¢þGqðj]*ûƒw ¢C¢ÜŒÏÀh{'„dƒØži€] î rþ"Õþ9aõ‘<8EÄ‚¡b怞 ¯¶Ûæ¹#Ê~ ÏðaÃsª9“3¯3^S κˆÞ ²5Ë…„Œrº&ƒ|ò=)/WZ6ÎNRÖëF"+ñ ¾y à ò ¬!…bÔ›;l˜Ì±÷Ý@‘^B&&‘Ú1ù–‹)Y7›Õ„ÅY,‚²ì¬m0G µø’ÃïÁ´ IT%’Ö˜é¢9Eøóµ”΄ô•,&È*:ˆéðdåE¹¥Z«ÕŒª¢È ⮯!Ô¾ ³,{oú*xüÜ-HEMF ‰ù ‡$d#õ€üwÉÉ/=b‚Ä•  é<Žî§e•ñ8ŽÎ³“Ø>ÁÊ~(Ǽëî˜\ꃚ¼w%}`Ú:gD›½@Ê:0¥@{.ìípBÝHÆ.ÈTž£‘ ¬Q"­Å?%sɘëÞ;‘ ãpòÕg6• ­¯#Ypb'%ÛÆT2¶ËܬÜ6EqV“æd‡–Mi,U¿ »YF<ÿf.Vp.ÆLòØkÑH ?Ù¶æhG…•>ñèWVü×Yy¢lWžF\g¾°ô/H>8}ÅÑïÔ­9wÅ](E6ťަ«¨Q\Pa¸°¢Á!u/€ޤéÎ Iá“î ›S˜Íjéñ r+M„±cŽÄ7Ž´í–ä—4]º$*|Žwð¥JÛLÑBŒrñ !aÃ#-KµøôŒZŸ4gÝ™ø-é+äéAÌæÏl2,.ló Ոʚf‚ºUŽôÉÝè<µƒp¤Äþv¬ uô.*Šâê Oã£oSåF³ÈøÒª¥Õ†³V¶ÿŒ›¨ °«£{Þ»Ø 2Uëà< Ïõ”þ½ñྒྷ5F¨“v_JƒŽ¸¹ kHäª@’«Y ÐâHÊpÐÁ´g‹ 0©©×ÿØIæYUï(ŒÏãà5ŠE'“DÙXö–MÆKXݯ®àhkó[VŸºãG.É-y îÒÎ(°3«ê‚Á ïÝwoŽ’¢JhZoç·ÁÞÇ£'^ÏLNÄ&<«ªé3#Úzì¥ÕŠI>Îf=çäQ3]E åÁü¼™`ÎI~%è=LmŠ  èf³Q+Ľ§Ø‚Ž©©SBé¹…7Úç ‘…>³¾1’CÎlšmÈö‚ܬñ9¶þC,àfÄ©œa˜k¿Ì?ã)Íe+ÀhE4˜´o±Œg”³eŽ[Vm ™±ÀàÖŽº*ûn5\¹¢#JÄØ):·‰ß@x¿¾HŒ…œ•QÇ9)†±°˜M,j—µÆ7ºƒjT'ëÜù§1kkÂPâ¤h¶ÎE"BfÉR9°+^؈¡(†rêuA…"ïepôÝIšeÛ¤°Š¼`'É´8Ç?t”õµó®X{eiÇêÚíF*±ë«é³âðûŽŠu‡|ÿ4QïñϽþGYæÝƒ£ñS?{AB“ŸÓÆæ¥T+D¼@Z._Xkg¨×š 2²ëXçèÂ’O,ªg–ŸçI <ža÷/I/‘SÄpŒÎE.êoûë^X‚úÌùè´Oˆ5}FÌÊs‹dN;C¶yÄ·ST@îð É3µ>œŒ¶rj[’¹ZZô&àHŒÿŠD™$4ó¯0žÙ:P­{O²®[-1[æ®yë­Xi5Ê~ÁcüŠƒ²pi ÚB¡è µGtYéh€çéÑOý£ŸÑ´Lrë4)œÕÃÙÓ³`Îl9J¦¬Ãõ2’PÇ;¥µÀ<#C§—^‡Ê¿Mf駘í_ZžÌ«à$xÎz(«£™FçsQ4G+DM!&ÈD¥(·éë@ÜçÙ‚@š¸¼D{LXX›²,÷¥íþ‰HK„ifÞ^Tuðmwçócuìœìœ¨Û“߆Îˈ»&­’ϼÌ)–.š¢ÊIaLÒÒ–|åð7}Kžj#¦Bj­ŒŸ:ƒ;ÃbYÚ™Fš3Y«¢T‡¾S–«ªZUp«_le”w6,·íá×GÝ_ºÙ¢lÊ»ÃÐ¥ÖSð4I)üŸ[¿ù•5Iñà,Ý?8ÑW +˜ã¼äù Œü„g…6GŠ{ßÜŽ#´ã©r[Š·ÃŠ3«UÄc wÍf¹˜ŸÄRx3+Q±±KêSlåRq²­KPÔa“ëËŠ<Ð9-æcp•¹€ëP´Ϭý³_0ÁþÈQ!‘Èç méñù "5Sûg°RYŽä8¿FEXTfVàõÍêüй>‡fÃÜêƒû™aò:-Q Iàw—V5ß “úaH|n«!„¿¢…­’i гTÈ»ëªp.Ê+ï]Ò½5ÞûºsøCß}'…í‚¶¾qIè]]{šNÂÓ.kvlYË]• ýzæ¹(ËÑÃññO'Gߟ9ÎKoôl<~6=íô†Õí gп=èß ï÷Õ1zÐ?º/ÆþkÏ{éy/<÷¹Û»Õßý|wp{ ŒðæìÙ²²ÛNÍ[ŠÙWËÚtX&f ¥¢¨¾Zz‡?t{·õ`ÁÎqçÆøä—AçÆhôð||á²ðÇ­<3A°ŸÙV×ÈtŒ¹×m‚í»`0ÑçÈ÷RX E©ñ9‚–˼P£F¹ò Ñ›¹Ùh‚ÉgüC%œI±° œ(ôgBÑŽƒ^V2+jEû´ à…€“àgÒ ò›YI[Otä²frM|cnUùa/€¶ÏP’çøåÙ€9G.}­ˆ¾ò€sK¥@²œ—UPu×,8çu4zìw~uoŽÃ¹VÁ=ŽîÓUvXgžiµbžgeOÃÒ­D‚,ýçU}î‰ÆU5zìôïã" ‹$È#8§#ç¬dCuøÓÁøuß»®ÂðÜ s'ÊÇúÈÆ¡‚qî‡yΓ(Kâ"K™÷&ðžy ÷ºbË ôKlî3ø øVv4pª’²êßww??>ø®§<—„ÚÀ—ó5€‡Á´@Ÿ%«á#¢ßÚä…0{UR~Ñ6œ›j‘H»Ø)M¢iŒ5ÉQ‹gŽjÌRbÑä)ÉÇÉfz–ª='‚©ø4:oA¬Cšcê¾Àn„™­KK•yg.šæbß!ÖƒoòµÈ°€¢ÌB¨C ¿’g²¦¤U¸ÃRýqƒÙ_ØÞW6¤ÜÖçS/¾Ë…©m ógBVnV³Ø¼³Úh3ÁáoFìPâ 8Œ¡§xI½‘ L2q.ÊN£[ —À{“îÝÝÿ¶»ÿMG-Je’ƒóbÿ»®²'ÉÆ[îàB}ã,n±´ƒj¬ù­¬ûÚ˜ªn2ÃåÑO'þEfI%Þ4t§Þèuϻ賾?ï»ÓÞø]o<9Ž7ù(,a>ç Þco>ö°§‘?‹Ã\a8¦±óÄ5ZЩûÔS`Þ†ñy’Ì2œÛÎcà)–邨T™.«Ýî­ÑþW'ýÛê*¥¬HœW켊;7Çqa§Éºç…wš‚Óf¥jij!g(Ã…Èq䤵6·C-CRbæ6@ÃÞº:+i¶Ì“÷æ6ä WåeÛÓËCh–‚‚²°žs$fX&„dÿ,sOïðç#w2vÎ\ç<ðÕÕíYà¼t‡÷†ê•ƒ×áàöðø‡“Ã¯Žö÷ö¿8<ù±ã<õâIj'Sò÷¥7[V–Õ¬>Tx‘ÿÔ?ü¡çŸ%©F$Òyý<¿Jœ·Iÿqp|ct|c<|ZbðòÁðí‰s1t&ãáëáè| €hÛ;ð&ýáënÿi§û wr¿×¹§Bèáø¹3|8êþÖ=þþ¸w£—åZ¤(Šè,?rÔ_Üý|wï@ýÝè<‘¹qàÀÕ:8M¿íœüÒæ´ésMˆ;ŠÀU5zvnºêè? Üש?­0µ Â\t¹äv²Y¸cD ;Ô’v3›àäÉfAQÛß}JµÚT Ñ{½œp›áð=6¤™f.uê1䯽 sˆÉ-H0žZ‡ ´m‡T»PeqZs›YÈPâ*Guh`þCè µÜ’vËÃî@Èû,­YZÚÖ‘„Âbî³ÁFœ™•³âp'-ÌêjÌS;××j»N ÕS¡Æ ®õ„Ô•$ج6÷?a&FfVâ#€Ì{½Ñ—ä˜"Ä.½KZˆæ1ÃG~çæHÅÆ ‰'s ”pZZ2S±97}IU_s'ÍŠñ#÷èû“ý/޾;ÞE§±†V¥ÙŽ Záitôãñè‰3zê ŸŒO†Ý{'λ1òf£ÁË®7u”_=|5rNÇþ|æã`>ê?=½ø3ÏŸ‡ÊüŽ_)äŒ:¿w:QÐõ_ú^%ˆŠn»7ú»{û»Ÿ ïÓ¼°µð«Kƒ^ïM´ÿåQ÷·A’WL̰Í©¦ lh{K™J•Ù7>m@¤Ú€ª#ÉPÇT fj‡%ä¤aœY2ŸÝåE1’) ˆy$9⋾7ÛÀHjòcPÀ¸ ÙÚ©”’?ŒÆùœ4†‰‰=žY;Ìž9’;”3s¦"C4«ÍCĈ2Ã0å™"‘ÙA§0¸ÔR YfŒ<Ä”Å(3”›´ƒs3µ2QS^OH=;<ˆDÐ'ˆy_ÌŒãCÁTT æõo]Loaa:®Bñ G?³•áx!: QÂêä ïZ·Î¥**Þýòäð»îñoƒþ=7<Ë áœ 6¿îXP¬hËEd{³¼Þï|y4zä(ßµ\ÕsKÌ‚žÄ£‡c`åK»ï‚á‹Q÷aWÁ¸û Ó{пu¼‹`ôÒ¿qü©ëÏ\÷|Ô½w÷UÐ[réˆê:Zź*VUZfîÿð×㽎~;V¾q÷aüÒQøìÝœÜìvnu»·:ƒ‡÷ë¾QþjçDyË?»Ï½t‘]•’iÞ†zK_z;ÊŸþò01; Å¢êÝ*Ûë¿ Q)–®š‰ýÂæ±ctFà3jÏlÔÊTPØvîZ¸ÿ±ZÒ˜ì…ãRX$Ô’ HS“ ‹rä…* á´\XeÍË„šÜœ|`ò±ÌnÖ´L {WÀÕZøKb*æŒÏì@3¿•—Â0,¬Næö—6Äcîú×ö1%°$:á™Àzù楊w¿8ÜÙÛ?þ©›Ì‹B’œM1Æyêí™4Ux7È’ëí6CDˤÌúÎß= ÝY4~ë÷Ÿ»÷úÇ7;‡?ŸüÒ9ùµsr£{ðýáàñ(\¤a¦>H?]*rö^úÕ‡X‹fåÅá×G*Þÿâðø‡“D…ÄÈÇ”iº& ©´#M@NBá!“ZfÈòy2¡)!x!ìÁFQbùFÔW£ Ѳ63J)ø€ÊžgH‡…¥vEB2>,lM<|ÛZCž žúÔš íAÙáГÌR—­Lj&JVS+3n ×Sò–gba‹xПÛ.Z ––¼dGCdAcŠvÒ…Õ—`I[•±(C×o~§õ¼ô9Ý^ˆQCSJ‹×aǃggûÊ3 U%ܺ‚¶E• žŽÙàŸüîD êΟ•Ý»îþ7Ê»êØÿ¦;ÉÙ—³¬eª`‡§Iç—¾ÂðÞ‡£G!ÔŠªGÙ®½þ­a–—eÝäV«Ë°¤¢_e~WþPÙÛ,öf¡7‹ü,VG¸ˆƒBS¬”)>ùõ¤{§ç]‘ò¥KåN'½»}ç…;~<îßTUõ{wvvvwwPX-ÀpeÛ•¬Oi¥pÐ3*ö$ë n}Ь7¯³,HSðÉVÔòØÙ]çØ˜9’_-õ 1‚<'aE"smÕ& «-{õ¢çõD ‚”/c2L”k¿š#±Ù#•hÂóŸÌ:•¢ší‹2›m (í€ïH´ÁF ¡J™,êì󼿵†btM-¡%š0¡W“‹Fì3ã-äº.pÄ.´eÛf± ¥ÔgÖ«ñ9ú%~uPÏK¹» r Ÿ"’Ôtߥ?öÃy õ ï<ëÞv”AöÎSä]q•ˆy‘ ÁOZ¢Ûì½ ¿Qñ¾ çÊ íêˆ÷‘[.kýWR\•q–öîôýYäe‘ð\݉ý"Ë$,’p‘èx+ÐÂ#u>OFÏtÍ©{«ç¾ðXÇã~‚7¡ŠO~8QÞ?8„Ò1ç¥ Ñè›H=Òöc‡Tªñ9W¼l»g— ê%(æ&3lZ¢b˜—ÐT›ÃÒØx)DW¢ Åjµ…P.°nZ Œ‘ÂÖW£Âªóc¶¼ñZnI#h¥ Qdæâ-l‚†F…Xâ°ÓÅÄ2˜Èc +¹Õ™ƒÂm Æ£³;ŒÂO0Džeds“Ä⾤DèQ0škë5^äy–”…<ãB{T+¶S?)§åÉÁ 3»O{uç™'úzhÍ­T@S|‹Õž ‘´ÌªãßFã—‘Ôï‹—µ^|KÌ(mGŽÔ²*Lî ×t^î÷ö•ϬÈce;·{ ãGãàMðÁ¶·ós7¹HŠ¢8úæHaXý—», "xdKbÛb^À %³"áź>BýLï&–JÁ"Á^Þœ=C¨Ÿ))c„<€Íß”tCv!‘ å rž~È#H`à¸í'Ï„›œT'~!!?Cß;¤¶¡P°Á|™Ì›Šº £&§m‚Vr(G|ˆÌ²Vxš‹´-„;]ˆ>9cw˜-h¹r Á_-ê)ø¹.â,¼dV¢+Åí]s‘vŸ‰aÙ<*eb;N¸zĤonS&ì Ô™èv 6&øòÆ/c…aÿ¢`‡íR䪒ډ–ØÖËME¶»ˆÊ-ÁÛhwoç»zôn½ƒïбhQ•ñ}fù’9áÏbgLXà «Ït’ƒN¨MŠ…òBùÑŒ"ï,ëü>ì½ó_zÝÑã€ÊfBÓg®l:‰JfØŸ2SZËj½þ0I:=¡,û÷téÈ;ûF ½£s¯ÿz|t»Û9V¦XÙX]ÎÓ£•#,³p¡;³ ûx8|íèZñkí]{¿÷>Š^xïhGzOÅÅ¢*êâ•hë¨SŸs–?ûòœ(:b„²'8 ~!ÊHL·*j(v’pE\×Â6„F²ªTbÑ6+'š£¤9‡ÁVa&·fÉæ½rÑ Ãy{føa¯Ÿ`‰D™Õœà¼o˜‹%Ê ¥&gëlçdg‚Y9…·Ìþ!°üRÒ8ÊÉ&‰%5â¼–`²«¸Ë)o<µªE’GÅzÜ8w;«$>ªkuŸ ïtýyœ,Re¥¾;æhöSZ­û7 À;Ÿíé`˜è¢œ¾JäÐYBß­óŒX1•ΛÙü­Gãx¬U¢¢±pzÙ–àœH—¥»Á5®‘†E}$PaGv±°Âé¼.¼¨mÉ ™ÛW¶º‹ò¯d¨@À½¡03A^S’ôR_ªÊÕE/d–:‹°÷ƒºt¶•‘lº´Šœµ „æW¥!3!«Äí",8æ‘“_­N6I¹9 ÷ÌÄ4ù Kj&7#{K+)»`,ŠF£§áñÝáø,êÞv0 ^nÈY/²\6û¹QV­éÝÏöU¬xÝ„sÍy^UYYŒœ7ž>.|eoOôŽîtïTô(ëÎC¿ˆ#ν/÷Õm²ÈTô;x¥|ìaÿµsøûñàÕXä¸Ì²Ué>w»¿tÿ ¨%|œdšî~¾¯0|ðõ±r¤-‹caµrÐÿ&ë¨=+²¹­‹b#~nK ‘ì9©ërÇ%ù€<ø†,˜Ç˜Ë <¦Cȶ؃{žrK³ 2›EÜ ™H™BÙ© RÄ«°ókí1¶1…-pr \#ÀˆhÙ#¹VGo†µ%-†sŒöã Ë{;)Qm’ÜFƶ”,âNüJ]0ÛhúŸÕŠÚ<†»1%Tî7V:O¤ûQ#<Ǭ#Ë_ƹ–˜+î½KúÜÑÓ€¡›,k榢šŽèé'éþ_zUUcY]$:úgéÉï]lâŸGw;‡·;ƒ3wt(óëM#_g°t IØý¯÷U0¬¼hçÌï<è÷ß8ÊöžÜë)‡Eœ, ­b¹,÷÷÷£ÓèX}:Í‘þLáÑc/âXvTEaE$Y¬’¸ÿ8ÏÜ‘ãQ´¬ístY8àD18ÕRØŒ«Dœ=–’†‘œ›1C­Àx~€- ‰ M@Š­6èÚãa.è}™ib;¥øÍ”V,•9EP©beu)N Û!å<0[¾ÊÑ9•äΫñ–‘P=iérEm\ˆ®"äÔkÖaßDÀZd™åšúR"tnÓð˜ˆ*×(¸ÁSˆÓÊÊ›=,©¹8CïÐÀ±8³wp\dR'‘R’ÜN´Í ëZÎÉOý/Ó:Éùº¡oY•Ù²=;/½¨H”«|tëäèNwpæ&þh¢SSî,ÒuàE¬Ó΋ôà»Cï,ðÏÃÎýž²ºÝǃ£ÛÑ©«ëLe’jéYMv;Ÿ;Äcx¥{˜w¿8Øùß¾2Âñ¼°rB$²+Î@x=žF-ú^8 Íê¥þ‚&ZÁv¼¬)Bk'Ý–¡ÅE¨b/©mÕäiYþFØZZ¥(#I=½h)´Pe®‹ÎpW}H#xjùm‘Xâó:Cê”ô¥V”™fа `щ鳫+*Õ¡ðØ!d€õ¼ÃÎ4Ç"Ò°}Õ ‚Ü+×a½ÙÀÂofj(õæMR$|ÙQÛxbS²¹™i̬€"9³ÒáIsºŸ¤[Ô¥$+!UpæºÑè‘£œgÿuX }Wדb/Mé(ž§ß»qžx“èàÆñÉÝÎðÜœ9½g*²õž½Yä:ƒ–©2¼G? ŸŽnt/ÆÝ'ÃΣ~ïÉÀÍBåQEâ¼ò²JËD¥6ÂñYüá&½.õy÷Æ;{ûê=ñ@:¡4RBßH0ª‘S9„ š›l)Éct§d·gµ¬¯l]à–ψóÞ€ Ò©°ö¶À}?à#šØQ¯¶N5Xˆ’Ü]c¥l믺BtJQ»ó‘RRâXÀÐäÕt¾õˆ›X lœ²´_®Tå"Û<U¥†øäxPŸƒŒÏ9èØ±2n ëð `Në…ÂæT«Ù²õÌŽÕ +‹uÖ:ÃóÚT^´öóºZ.föfÔk‘×f‚ÖÊ‹nQ^ƒ)Ï95üªLèÑY eî|îîíkç¹^ì½®6Ô«RÙÞÁÑûÆßûñP9ã³ ûTáv4ýz¼÷Íþ襫@{|·7xçŒgÊÍU¨Ü½?P0Vqrb0\ÅÁÁA|ÿ‘ŽjÝ¿¥"ჽC÷ehG„Äj¬óä9‚Ť¹ ²Ï‰}•Õ(ÄAVãáØÊ ;¨î’5Yæ)Íê4ôƒK90$šxü¬\íêZÔÑ[R×q‰É1Iÿ$bf-Ï:‰K|Œ[»¬-`;·$Š¢6Ì-)žfÓ{c<µ0]É¡ïØà°¬OúÎm¾×N<ƒBBiGuÛºs.z‰ç¶üÉd2#?CËþ9Ëb¢A¦B4l"±˜`ÌQ.œE>…EÄx'[Øé'Ül„«:SÖ±IVAFÇyì6‚Þk:pQ•Áyxøãñþ·‡?wï÷/Ç#ÃÊè<ž<軳ÀÏ5KXEÈïüîþèñhÿëƒ O†¯´ íÌBg8óPyÔÊ\‡†­¥œ*ü®ÊÑýQï·Þzõ¡˜\hu„ç©1ÂÇ?õ8â€z£ï[0S弩%ú$Yî Ip¿Þc!”[¸òf]›•ÉŠ³æ¹õäPƒóŠ6à€ì„%eÂU9vN\Å$ú†Éž€Ø%jGBYM‚¸Œá¶^`÷r‰S€VPšÖÏjj›˜qïo¸ÐÜä§2Õ¸°–Ê’o¸78nj&$‘²z×e&¨Ž¹­¼Y‡<t61W)>¶wYN \Ú܆L2Ãó‰sz5ž3æQ+ô™3i{—¢]A*°“¼†ržO~êeµmè«GÀìß|w´ÿÝ¡žÃpî{óЙÝÇý“G=g껳Hóœ³D·á¨Hx¬Ë¿áð•ëÍU¬ûÝ·~ïn¿XiXîìíjõÙ'#èyPG÷á`ðÒQ¡²°2ÚQ‘(GZ=REÂݽ« ó,ÒŠÂ÷y`RYýûŽ%ùð0tqH‚:öÓÍ(º›Ö{`ò&¹Ýà(·ùËh&òO…¨ùËlHnƒaVue+6£ù`²,\ÔŽ °Fp.)±L˜Œ@£«æ·´FX§¯hHo,SaLÖ¢0a´@5,+’ÕÇô–ìåç5Þ[àpac`C¥„Q×ä?'œ ”¦2·ŽtL}‰‘¨ïóðkK« +K›[Æb’¶¡,í`;jŒƒs Ý®ª¤a{ÂäVÔ`$†ô±özAS ¤’Æè¡³³»7~8þ(,Eõ‚á»P7•™2˜aaÐû¨øÛIÿÅx| žG§¾kZ‚2{÷þ»°0Ù©ƒ¯´=”ì~5~çuîë:°7‹œó Ȱñ03^txí±ŸNÓ1¿p[áH§d^|s¼óùNe-¬–Ú€’aä8Tà ÌŠšø+å`ƒÆ@³L¸rùF3ƒ23¬S°0%ƒcx ,ýQ‰¼!P‡¢gsfõ±xâ’?Œ]âˆm;ëc‰í1–:!¥E *SÑFà/ììV}õò:KLÛB0¶*A;cõò42<ÐõPļQfIíöë”.±¬¤1e$¯E׉ ^ÇùCòÒTBƒÞ.Õ*\—$漑µâ]À%͹^Òðë˜ÖqVÊö}«ß>Êä^õšÃ»C繫y‘EæIïÉhÿ—£þãÑè­×}0¾s‰Šou§‘sto©È³€H»÷{oÿ«ƒ8K•¥ ²¨s¯§0¬ Þ6êÞë+c”Ã&•¥ý£ïŽ®½ï¬ê³H‰Á¢EH>Ûß;8R!1_ÛDNúÍ­ó%©òXó\PÃvFN`ÞlÞ–•žZd+XM‘Ðg1[ïÔr¿Ä›±ùWÁ£´9gâ„H:g“âK‘óÀÔÊv>r$Œ-@Kj~ä«&ÕÃ%Jó¢eÂw-5:«á€ÇGÑÖ@Àäí0tSI0÷^‹W3ô¡ÆŠÝ‹Zwø½X’Í6l&s*8óÄ£âùÎJŒá-ÄêRXÚ…³"Ü6p=Üå¬U±Zó8l8·‡;ÿÛõ_ô¶ºÐŸ;* 5vi8OOGî©ïMÂÎÝžFïL“(‰¯ìjïñÐ}m ¼æ¹î3oç³h®ýäñKW¡]|øÒUà¼+$k#\hZeZi^ÇèÁøøûãл³ƒH)ï<õÀ‹? š^ô†?q!Ä"D«°”zêóèxXa˜Y²;nR]”‹µn„LÔ“Dä ›'ËŸn>Í…æc.&•¶›ÓQI½ç1f#L0N ›åÏ9v8.mðÌÕfî=ô³šÀ]ÄׅоÎkì±X(R$5j§‚!ýg¾Ê¨®Lœ'ÎW'¢ “í呜¶¨SR~˜°*'\Z¦Š´æXÀºªUˆ6eeýX¶Ó$m£¯ˆ{eW±ÝÏöŽ¿?)—¼8}[8-4Æ’"‹‹D›ÓyÔ¹Õ½rtd›…ºaŽÏüã›…sVi/Šb÷³ÝÑãqœ§[=…y÷,½tOîöÔSü™® ‡¦hœ”E¶*ƒw¡òº¯ÕÞP‰˜Sñj›‹.Ò½/”>ù¥o·K‘e¦j, 3ÍÖ¼¹)EB¨-Ì-….ÊDÒ$«7!ˆX—_¹1}žEêÂF€ I*¨~AJ\\›ÈV Ç Ç0c–h^ )¯‚ì°ŒŠÖÍŒ‚¼M³7³ea_Ú^¦_ˆ€BæÁÁ8á\Ýrøjc`‘ÜŠeÁ]’+òæßÀŠè¶ê¥¥….¶¬ªÍ*q§²U\;£hiq+šûª©&Y²í>¤«ÌÎήº]¼ŸàuлÙÏ–…Š“2YpüÞÑ4Éyìe! bEÝýá“qQÁ0pü9üê°ó[×y¡›ƒI4|:½tº:¥‚ái€Üé\GÂÉŒˆåw83«?²w(¨æ˜ÚÖKgB5гòZÂ…'i%£–zU¬ÅÁ°mQ^Öz3"*2…B5µæ§H~TiSè+±óOTPV¡$*¥ÈU¤ Ù8qœ[O»!h•kˆÂä'+Gˆ-Hņ»‚2‚4Š0¯Ä y’˜³ª‘K¡¤QYÐ2;’ç'dK Â%ßz_‘ZÄŸºÊ—eõ<º?ržº ]ÊëÖ¢‹ððûCï40}‚º§_ëlÌb÷"8úí$ž§¿=~0ÞÛÛëþÚõßZkßêŽO}wâ÷ž~=V¦ÛX`S^Ç? ï ?$U594­ò³ýÏÝ!î¼ K¹µ¥ òÔ¸›¯æó™ ³¾\ƴɤ¼&=Î-PZàXR²ú >¡éвSD¦ùX¥UÆã!㑘~`éV†Åd=d²%\ep¥t­iì[Â1¤±¼”‹náÜewa­"[Û+x×hÍ,t*‚.·"*¯ùÌ{SÔ6`ýòÊÞL áؕM PÙBf$ªóãËU]_ni•"¥º:÷$Èq'™¬Ñ ú’Ýfs_ºÊmÞùß·Ñ!.ùéüÒ ÎÂT,‹fÉÑÏÇ*ÊMW…rzuRz¡;“tfëÁ`ôd\nÄÝé4U^ôÑ·G ½ÊÌ:¯½Þ#MÃê=©ãøVÇÏtÿpll»²óÝ›½Î¯ëæÉ1†0˜Z²”½ûùÂpç·2 !RYˆ"_æF™: E2ÝEõ¤¸Q5u [^šÓß•\H&™5Â|,h•¬›ŒH;s‡†xØèá+:Ã?ôÜXŒ˜HØ‹F%dM¬-å6ÚçûLømÉ‘Ø>HšŒ_RnwÙxÃ+Ž2ô´cÁÆ”#°e‚*‘m·< ž§HWu*¡W²qzت>s‰Læ²m€’ÕÌU"Æ0Ù™J$®äÿÂßÙÙñž}Lÿ¹ZUÇ?‡‘²½q–tïöÇ/u:Z—”J=XTÏ Hüitô³2¿IÕ–8;ùáäøûã¬PÏ*z·ûΩ²½£þ‹±{ª˜Y7?¦Ne-‹áÃÑñÇÕõËHÖæ)m‹êØxÑ*.J‘ä;¢fÁ«ÅvÆg"ø’:V™+D9#³F¢ûHXi›CS5eÆ+*jT¢8¯?’›3’õ¡ÅÌŸÅÖ*mý2®ÏjL(ùœTB¨´“å£Â¶FDV‘²x6z/jœ;!™x L1¶B« fbñÐ~…(üM8ýE,(æoñp]–°éb!’†övM·Âu½‰¯²#䋪VÞÿµ1íÒF¶ð[êªJ,ÍF½wc)÷ï+Eñ\V À'Ñ4VˆõÞú›º)ÑèMõäÓ· î÷ï †Få–´wð*ØÝÝõ^úñ,9¾ÑéÝ _:Êðv¯œ@YàR'Æâ"IŠTEËG?U«êºI¬š#M0îßíì*/úÀ{e„[+(f©³ šeù‹±Ì!QO®¥KrjífhÍéY‹Zê4®ÌŒ7Až p M¯h!þĢƟ· …E}åó4À…•°ŽE ‰'ȧB±˜£Ó„EE–VÓ–µµŒº%NµZ»ÐQ½‡þ\†1pa‚œ‚ŠI¹°«…@/«Ò¥IC)niQéÒ*¶Z7˜ÁV5iŒÕº6AªxbXeËÕF QUŸšYz+Ú#Ömš8ÊÞßßWžêÇõŸËªìüÞS¦UÁuôlÍc…1í<i”馅(Kƒ‹èøç“4Ï.1ã'?ž~sÍÿ"Ò™ç¹æpøë‘™ç i˜º¼ ûÊ;üî¨\–×îFb6¥ Ï]LúløÐåt¤S*ËÇ,ÜÁöjQóÎÐô-ìKé‘d¡œÄ%s[ž”œü˜ÊgXù·¢MÍî‚ñoá]WK·n¦XêÉ¢¾U(j÷8D>äÉD^°,Å ù…툪é½RZ®1,Nö±”W$XÐÅ€C´“”¢ &ž$·6ÖnK û^Ù|×Zäá»”y&N>--‡QZÑJ–sÉÂWÜ`PÕh÷öŽð·«ÊþªÚî¶šßøú¡S6J RŸMñ†Íæñœj­Ñ,¡Î1vF†$“[C!žÎ¯Pز¥ílá!©¢k8ö å\Sbõ¢IšÒ¼¦BN%<,3s$x/àt4»«QaIÔ˜iÏm_³9÷åMÝŽ’¢öÊêOïÈ‘"Y#%™Æ’ÏXakÛÞRB·Þ*P®›ŠÊÕ‡öúTõdrï[ýðÕeÖ‚R_èÒÇþ)• ½Òƒ¼±†dæ-$Eê¾ö÷¾Þ&ñ‡ÁLÛá‹øè‡#“Ð2ÙlW+ôª¿^ÄߺÕêxþâ’šÄ~ÿŽðþ—Gv›®sã`«Äj¶ÉQß°Ò¶M¥ž KøW ñ" àEØ—-ˆ-¿´wR!Ÿd…Y¸[F,}Àa£7&il(¥@lez$K1\º²÷ÑŠƒìò2˜€K:dÑ$>F á0ç¢ÖÅÎ…›`Vpiûu21² (m'@!¥dvª¨¬{\ʰvÃ*®†—¶¦ÛõꪹÈ̱õ§ä×ß €§é§( ­ia¶,•ÏìP :˜Dû߸/½¢j¡\«Ý$z]fUz7zý›}>Ô;?w:¿tO~ìw|ôÝñá×G_*[ªoÍÏÑ7G'?œØãÇõʃÛ÷‰¼’IS6Õ[U°ÿÒÿø6L,c*Ka¸{«7zêh9X#—Õ@¯º8ê]iP‹rÎóLW† Í TÛ„~Ͷ—½V1©‘ކÃ}îëÑg»{µn‡e}˜cY7Ë\•XÖ†¶fuT·v’IòO&íJYo5ãµZÖx{ˆáª–R­uªç¸"ЊÇÃ_ǧ¬1ôÄr ¶©’û‰»FE±CÕL±I·)®E³¿š ´<ò—§á¦²3½lÌ©Éh/Šä׳S¥ùx5'Ù<=+ $uÒù¹{¢ ø›†ßàöPAWXíåêp;îSWÏ<ÿ…_;^ê[ï™§`¦·æPH ßEÊ@©ÛøßƒàSü=Áh­1Œ¦ñ¶e¿Y]ϼk kËЭVí²ÈZºÚ+Àjû«êÄÕÚ¥åQÛ^±ºOWŠñq…Y…i¡\‰2™Ñ4‹ÎÓð, ÞÆþëÈ{8ÏüñSoôÄ=tFÝÑ#} Ô¶{w4¸7Ü«û#åܩߪ_=t÷Ç}uþî¨wsÐý}л5ìß÷8ãG®óØ?õ]å> ÜçûLÝÔ_ N“hšª÷P¬kí4¨Ù²¦3™åš$™HÎ¥±k”uíÛ]·éŠ—‚7%kãE-#”õ KÐ,±Óvº¦.²Ž¿¶ÍwÔä]¤³4:ƒ·‘ÿ:TÖÒ{î+»Ú»ÑW0PîŸò™Ëå_­­?ê+gû“þ 3XT#MËÒx ô*hЮ+ºó‘·6Þ…À»»8 já1MNVðË¢³$xù/•‹á;O=…™ágpGù8#¤ÞÍ¡òÅ:¿ö:¿˜[u¨ÿþÖïÞè+°©ßö5ØFÃûŽ:F÷ \8x*k{Ó©Ì2Î*äÖÆù§îѷǺòòKO¹ßÞ« :Õoãi„²ÖÊ]×û¢J•Çž›¼]¦oñ¾=ŠT…Ë*Õî½²ÒeByÆœW+Õ–ªäÛ˜1“ºº`«`Z^³•ﱺöŸSFoooÏ{î­ÿûÙþ32½–šmºÝ³xÿJ0 Fyyú0A™røxôTõù)|¥÷ž¯™ñªR8|¹Ï4Iáäø‡““Ÿ:'?vì}rôCGÇúèêjëÏ=u˜”Þ k{uôo:¿ö{·†Ýß]êètÃmM£PQŒIF&!µó‡¶jƒkýkûˆ.´~µ’®þøW’qŸ‚ÅñOúéÝè)ŸüØyڂ§Äg±.ã¿ uª øÑ©.æ+èŸI‘ný·(Ë4ËâIªæð4 !z§ïGg‰>©náŒ9ôõàà­z|ì¿ á>üW= >Otfj–ê¼ñÒ¢ë÷CtŸ¤–¬®ãúnXÚ$Pù~mËø®¦ðîîÇíCú‡ý@³´ðèþèÚ—w–ú/üè]´ T`uþº“œþ‚U K6X’±@µÚ7Ú*Lm¼Ò.IiŸÀ›v•ÿv#Ñ×ÈQÉ@⣄»íooYu~ê(Gú?#¼¹p»¿v•ùýëÅÿ? ò–¸WX.iYCid³ê67ôŠ «ð_å6WÁÞ5'¥9ÆÞ¹Ò›¾äc¬·„7Ëè?˜·Å÷ùhì[·¼z¿õÆÆŸH‘ãïš¾:‹w?ÛUæ÷ýú>áŸZeÝb3¯»Ý[&Âr aÛ[É‹æ$SYœd6`{‹v¸D×Z:ÏðÄ÷¼ƒ_ƒÖªíØx|Í=–€Ì<ËôÝÇK5¿wUFFYç‘ónùš¨MMùÏ{󻺚)Z]-^Õs:!îµc=r¼9âe; ¸…”æ·âauv§å}o³·Ð|ÓZ®ZrÎ2¦µä±‡ñÆfŸ¾üh¹+L ,ÊK^'>¾<ø×‘¶G¿Êüžüpò·6¿- ò½øÜ‚@\<­´ÿúJû“³Q…bþò "Io¸¿Óºè[ Ö«¶ËÑöáí#YÓbWx-$AŒ!Ýè1úp ¼B>“r½çP#”uUGø6¼„ÑÚù¹óçtöÿÅTÜ¥<ç½Ï÷.¸…‹üW;6â¸KŒp£Ø‹6¦¾ž9ƒÕHSµ¬ÒյߤôŠÙ¢ó.„m½–S²¬åßšeáWÀ¶YòE­®kÃÝúÓ›«V“~å…X…UÝsñ®¡Ö¢Â³°î[Øòjé,ÕÍýOܵ6Ù幫lžâ¯ÿÒ^ú¾ ÕuÍ•#ó×$hI  Ö„D,þ¬w*SM˪ÑúÞÂhX]Êš¾zº{µnÙk¤‹º^o_w®šÁÚâi7.W±k{‰ùp¼‰ÛKܘs˜·;~j©]òÛtš}stôí‘î^ýÑÛ¿Ù×*Ù[ЫL.àVJ²Øë¹ÒM‚Þ3ï¯óq6+ Ð6í¢Ü´‡5/cõ'¾ù &sròmïlݽÖíA|;ÒVëfлÚw²Ü`‡ RGm×üØ? ‰æµ•)>88PÆüŸ^Ù^ué*ôn£=+{÷dxgø—Úû¤©hØFj[ˆÛŒlWÛÁö‘vÙ·ÓBÉ^5ðÎe@«¤Æö¢QEÍE´Ò6®jrWó‹¼ú«© âáƒ/’G÷Fÿx²4 WŽ­¤+zèJÛñò–ß{݆wÿZnf‰Ø Y†»5âàÿGÎ|“Aܨ7’^;Í…¾Þ”¯®ˆoЭluKD ²eÿc^¬K™nWÿQoLYããïŽÕÊîþÚ½,ö·Fï²:ùáäðëÃ}Œ•:Ô€i8´–ò¨GÎèþHýVÁFÕüuZ»ÚmÀjk ØbŠWïAÚz kv/‰Ä“Ôæ–´s­í¡Õ¬5`¿Ù„ÑÀ³¬÷6-ó5 o©Ç©…j©½_ùoú¸;„ûj=ñýîÚWo2z)¤¬±ZåjÉþ“h[j“Ríøû㆗¡¾ uÅ”AV€TNµBxÿ÷¾‚¨Â*Häp$Y˜y™Ñ÷o8kê«ÑjX¯y¥Žÿw F»ß'ß/®¹Ò•ÔÍ~¦šKÜù¸Û¹õC]n纋ÿ3>>ÕѽÀhá-cY©ó ÛÀGû£ÑìJg_•µQVá±r°ÿr¦æл(,•ó¼yq´‚¤‚4möLÐU'•†xr ›˜Ô[Þi¤ üuGÛ:iþQ´êMCÝzæÊÀ–Ù©†ó¼UËq+€WèS5Pб 5Ÿö†Éëüiµ8Ô*Ùº•®ô”ÅP@Aý£d¤Ô¢WñèÛ#ã¿ux¬àÔ»ÑSáƒAÅ´¡FÀ¬®ÏæÕVÿ5ô<õÛ¿Üô‰+„Э©¦Ö6»ëâ¶‘obË×RjnüÅ«øÊêê›u#ki—í£·[ú—ÕÖäYÛ‚Ø[3U+ý0µz>VVY‡ÇÏ5Œ¿ÒNµ2JZ6õM¨ Nr‘€Íÿ+§¬Ô¦¦Â å¡|ܨ^}jåÃÐ,p‹Z¿/uÅþß%cµnO m!&¶èƬë‘êú²P¼F”h´¯·Ó.hãØyÿç¼”·ÝðËm­¬iù4;Eƒ$?·Ë—lßDÔByÂÊ¿U‡¼¦Ž‡ã†Ú³rÿtYè£2‡Ô«©×T>øò`pk«Vý]õ”c¯nªµ„o^ü?CDAXµê¨Fí;p•>²d¤ì¤ÌïåÖBkuÑþ¼ ²Z_#)+Öy{û¦ÉY·÷Ì]F%\µ{¬lxù*n%¨qŶ¯¤ ]³›lçe3µ]û«õ·Õp­å™óÃüjju‚Æ+µp•IÏíE­ê¯(Ü*ƒ¦âIJ÷BÁþÍ>ˆè«…«Þ†BÄ„\oûˆ?ê*pBdÛýµÛù¹s¬§©[ˆºÙWoõJ»˜à']Ѫ¿ºËJ}pµwèbòŸìž´¹¸›Hh±uoYŠllZ—šöÓ¦gºÑÿÓî“.›üņ-Ü|çWËBKÜ.ë¦rÕ$‹´8Ï˪шÜàgo+>5ßô5q¥E˜ðÿÎÇPo@½ ….*BypôÍ‘º¯À¦ò[L¡S"L¥r8Õ¤üs€F··üQ›‚Ú¡Ôn¥‘{#H«-®Àí­Î]Í3µËÀ+¨Ûë]º-5½ÁݺOÝ?5¿j)ou³§ÙQ³ÚÎl#;µ÷*-7ÔT·T^· Kµ>r» ÝÐXVí—`ÝDo£7ŠŒi‘(¿zÀü§õ_#×ÿÇsH4pDû´÷F`3•‘S©nÁrê¤÷—û_ìï}¾§~v?Û…CÞ—‡:¯idjwøöH…£Wcì­rÔSÀP«w¥gVNÓ«ê;Ò¤hG¨C^˜¥êr©Eÿÿ "ÖïÉ-µÈßlОžfC§2Ö&3»‰M¨€L ÝxËâoi(X^J¥”Û†ä¦4‘¼XËf¨Z낈饳Ѣ³Ó–¯þ+0(ÔrT0Sùÿš¥|˜Ìü¨7£ì*ÌV6S—åð.]å l ±ÊPR¡NO-2ý Ìß~`ñ–ªÄÿÏß]Û€žfa¦ Ï-€­ÜÇJæ‚‹Ü>Z8ˆëöõo-ð²‰XÛ··¬½Z;ºf-[…`7z&ÖuÆxÛ‡ 6£âj#0ÞTå½¶[œ-jUqmaCU ×zYÚ£%‘³Mc}Mʦ:tÝ…hf§—Øëÿ'ÿ¨UY9CÊÚÒŸœú柫(œlÛjuŒýw#œmVn¶rx…­kD­ëõZ&Ÿk¯Éíoh»o¶ï®[ÃRæQ–Z[rÑm'á);5)9Ù9¹lï×mûÃyB©YÙžßÚì‡\¶Iõþe~ÒY ÊïíÂûïç8›á«Œ7»ùk̓ K[O5€¥Ém°£Z‡!mÁ¬9›BÒÝŠLÕQÝ àZLoi§¡«ÞLÖ]·ìvÝ QF‹†VcËaqMél¼—°õßÏG(Ùȃ\ÏýH‹j³5G)à(¹÷rÞ_3˳܊ùÖá! OxsZ« m0kÁp=›»$7ÒC4Ze;Ū ãKBÐÃϪoKSÛmuY¼ödõ¿ä¾w9mð7«$µµ±l‘}Üì¼mÀ¦¥ãUÌͼ,G»¬U}x"'œ³y%·&«¶MØÝir¸WÅ®mÙ©L}»­~ï·R'x5BûÉÅ.…Tgên”ȤsÕ¬Hµ†Í­%‡¿µ“¼¹á¶iMlÊ¡l*?4J)­þáZÌ ¹ä[¾îÇi'Q­Ú”ÖWÍífÓ‘F•´fÚyuCÒH#_ò‰j”Dá'[Ð wr›½mÔ¹y=w`kÕkg{ol®—)ò¬¯,W/ú!-\©¨Íc j[ZÕ䩨ôà ÍiŸNRïÏwž›Zùõüçf'Y«!OëªÉGmH5Ô–õ†ëîA«+<`Õ ÚÜVÚÑØj‡Û,^{ÛÃ6{¶nÖP,htíz.k2éMÂÅz½é0oþìlvð5d«š½TËf[F»‰ß°~­™ÛvV[:_ÖæMÔ:™hvÛzcDE»ȲÓÄð_ß´nÙ7Ç;n–Fl{¾Î›„¡Ö¢@c…4,õûFVï‹··ö—Ú’M"q#…ÛºHZ8¼Nbí®¶äìßR˜œ²æE×ÞL›߄ÖÝmdž‘UuSÎÃ×6í[C™ºÁºn×6Óîrƒ×=1`BŽ{j$«y¨LÍcY”›Ò›€†­n‰ø—p[³Ë¦Á© æeôª6ÔñäºEK¹àš#}õt”‘Îs|‡ìòÙ *7Ã:‚j ôKËüm‰¹Ö—±,7-¥ÃÜ‚Þ ŸYn—KêµZãˤ3ÚN6¼ÓÍýþîŠmEêeÛ#™Ê5$yu1†xÌ%Dð9n½nX¡?»*s­°pc³“J`›W¾ÆXV5§µ#¥!oÂL}ùõë ïÏw®6lx½ƒo+]wµÞ¾­Ú\èe‹Åk¨a´v l¶ø·›Êz’™—(ûÒè?Ë”•ì¸BQ­áæìÔ²ê[zß^·g.ÙÞÇ2i¯m¬+ ß²Óº©³E3Íš–¹,YFÿ×ÇIÀ|T«[[ÇË:~« sɾ¹®sÔ9Ö½\Hµ‘…nÞw­(`Ýæï4ÒQmÕ–lpk¶¥µçV¬iÀ›T×ë¿zN´ÖWG+°¦¸(sVͶŸFw3Ýdï¼§öu5°mK·Ÿi}ú– ÝâoÔßRÀE|._ssxÚ¦@ÉV2Í¥tÖ¾ëÇʵ擗ÒÞ[FOµ']ÚtÛÓWصúP«û¾ºÝæÛn&Y®XªGµj°àuÈô^#XØÊ>¼d0a¤oÈc±e€Ìr-Ò®¿æfçPäØÖÜ´¬Z:ï——iĶ·"´>w#Øâ~·ùäjøæÉš·¼e?jm9nõ‘¶Î=Þ䯯ÿ†7‡›7D˜–5#,ÙZ}YV×Tâ¾d“úH¤ËʧUu½{Ý’T—1*{ª VƒÑL,mÚ›¶qÖM"ƒÈBs™·VþäR°ù Z+ëº4϶ݹр±ÓêÐ7>O‹Dír£•·žLúK`Ùì½ØTÃ[¾Çý¾bï2É’¶í£%ÓWÛÓ«ë!¶µµ£¡^²Mɤñ6.a³H®?šoÿcÂ׿Îe ]5+±Í$èf/j%heD r‚JЋoØ k_–%ÍeÐkÝiÓÄ }¼r gã¶›Ÿeÿ,ð6q MÍeÝH‡Ö¦´ Sk¯å,«V–é¶]£…õö>u’Ö\Eãûn›¸Z· ¬´Ìæø0ãj Qaݦ괬¶î«?ÀyºÊFóéBýÕ¥ºÛbò¶ ·5Êv¸áÊÉ$(Ö8d™GLÕl¶ZŒ™1ù ì?ó`‘l€ÍNu“¶¡&Ëñk½=>©ýÛ Ÿ›*ë¦tÖ¶ÙÂÛÆ¬´LvÝ"Œr[uÝ–ËY6+.ísqÖm%ñÖXqµÞÆq»ª!Z½‡êøƒÿÿ˜ÿH´“$«ló¡êF¬)u¼¬ñµ2ͦÖîûß"ÌYÕ¥¹6Ä@Zë–µ\§]bëÞÓSuyšç/ͳxÿ¦¶Ë²­­ÁÑzÝP–’„ŠÍªÓ ¤µ9.|Q6þ´,šØ›i¿â l²$AÁG=ì|À »Jƒø•¡õ–üÞ¥•ý¦¦öê2KÕl\mŸF·Þ¢bõFÅÕaõ#¾àßÑ_ñÂn„¾—¸Þ¸ƒñ¿HmJ#i9?"RÝ,sÔË ôŠ€´Kz#SË9*þÛj7[Í–ŸX+—1Bÿ´tÈŸ¶Äÿk'þŒêÆ%»ycéoI†œ´ÌÍ"¥0›rkyM›^ 䆂²Œ«›¹ÛõZ¦¸7emÚµ¦×—Í_ךÖï÷'¯4ïûÿwóþÓ^ó?`_ùú¼‡ºÚ¨x××[‹lUk|ÛÆ%ÞVlÖ‡«ööUŽm&Ln Vâ–N@[fä/ÊÆ›lÄöµqY]’äÛ¹$Ñw=ò ëû“T/VŸ f«ÿ€úžTðµÜ4Ù£»Þd¯ZVpKz¿µ ²®÷Zm”—¶æ2¤[Þ@_ŠâSY6›äêD‰–€Ž^¹!´ÊÉ3[Ø“T ú£-ä³-–ugÛ‡Ü&±W£Ö¾7óL¡¿çC³”ͼú4«ù*QÜTÆøorܦ–Z·„5{Û¶÷ÕȘ›CvêºhußB•Ê⪙4i•žãQ­÷ƒ_yà hXìͦ€š˜ÖZÄâüÙh–y2>Yu\V—§Nk’:-$˜KRDïKØnö‹þi.èe‚^íªíG<ŠòÓáðO¸°›u Q„î7fè´Hœ ¸6\ÄöªÞº>=l½n×—ªÛ\ú}5êÆLÛh'ç/jɪ͜hƒ›$á %+N’ÁŒ»bE²ºQ¾áÂòæ¢Ý¹ÄclØÏ–¢ùòj´áöKW¸ÚZS——½±U»VËV%ƒKÇMlýÈW,Û®¶–Ó>Ú»Vº{µnh¯nÄÚVl,¡võ¶ ºÎåï{®çåÏ]·p–ÀK×`“—*ùÉM]„eKkñf«¥Á:ƒgOg–¶Ç³oFÂí¾Û¤žÛ{î6uÖëFËèÿ×,É­6yµÕ?¼Òv°½§¼Ùß6À®5NÙÔÊo·oë-ý@×2ì@üXmìÝëöñw›Â®-a{l‹Tð¶ÔéªÅ´´ ·_ièjQIæMM¬Í¾‚ÍV¼¦h΢~‡8•ÌöeSOfY5Òf­_âN#¹wEíª•¤˜²úcža‹Äv›‹ÑX"­<³ËÐÕÚáÐ ×[^¶±]n2Ûã½?ä¢_M¿¦EÖCÒæ—Uû¤Ü NBKá´ªÉ'¶T•Ú¶Ñëj‹DaÛ•i°hk˜i¥m\’gÞ"ÿÂDkIá&a´¼yQûsõi„k:íâjì\æ8]Ú"ûG9·ïíMY~ǸEÛmÓý»,EÙFm >­Ú<Þ®”–\Z+¾é6Á°Ÿ—ùê—BúªŠß— © lK¿}&Vc2}S½yÝæø¼¯œÁ¦¯=nZoÕÐz¬Ü²ÍØ6$`…úd{ujÙT5—Ö¸Ñüd}Î)¬× –h3 ýñ æv†Níñó% Õ«­¶±e“ÚæÁ®¯ŒµöuÉ-ÓáÖúU•wÅ,úu»v?ô+kIþ½7øß „VëîÜý®/#‡o¦]Û%·¸]ÍV–å–aÕÖÆ›MIZ¹A·0±æ®u±y5ùaeÙ’ù§¸s•éOUKÞÖ!°jw¨šR²ëöÖDü%“Y6Iä«+Õ<[í[“¡~ɃW—™ŽëÕÏÞûÝ­®¶)_K|ã [I3ѺºêîsImy3lÙ#V[=‹÷xS}¶Ñ·l"¶!nS“a`fu]¬£ñ² ºX#MÀõs¹Ôw®½©¯>9€Ûù7—XàíbßÛ4VÞ›ôºdÛ¾¤"u•à¢VŸÜ\sŸt²Á§ÿîþH±àCü‹-Woó¶O-Z¯[´—mÍê­ªº"Xm¤¸Z—_3ÓÞªø³y»!Y!?ÚÎú/õóÞñ(«Kÿm®Äê 5†÷:¢«¿Zþµ?œñº!Ø.UoDÝT_ÝLv^RÎhìΛ}µÛ¤Z†¹HM¬¿ô—t5¯õ=x[]ÙW\ÿ7$íß´llî-¢Ð«-¹’u[ŽæŠI„u›• °m=ð­L„¿Á…þD¶nõ2ÿƒq{¬Ô^ÃÿD‹¶­îµUfÃÌìü÷=þ÷óßOÍ­ýóý¯+†l—43ü÷óßϦø¯ø–Þ÷ÞþY Üzjëo{IEND®B`‚propBACKnpropDITHnpropNAME GrabberInfopropPACK0propXGRD16propYGRD16info For internal use by the grabberallegro4.4-4.4.2/addons/loadpng/loadpng.c000066400000000000000000000256451173507505700201060ustar00rootroot00000000000000/* loadpng, Allegro wrapper routines for libpng * by Peter Wang (tjaden@users.sf.net). * * This file is hereby placed in the public domain. */ #include #include #include #include #include "loadpng.h" /* We need internals _color_load_depth and _fixup_loaded_bitmap. The * first can be replaced by the new get_color_depth() function which * is in Allegro 4.1 branch. But it's not worth it to break 4.0 * compatibility. */ double _png_screen_gamma = -1.0; int _png_compression_level = Z_BEST_COMPRESSION; /* get_gamma: * Get screen gamma value one of three ways. */ static double get_gamma(void) { if (_png_screen_gamma == -1.0) { /* Use the environment variable if available. * 2.2 is a good guess for PC monitors. * 1.1 is good for my laptop. */ AL_CONST char *gamma_str = getenv("SCREEN_GAMMA"); return (gamma_str) ? atof(gamma_str) : 2.2; } return _png_screen_gamma; } static void user_error_fn(png_structp png_ptr, png_const_charp message) { jmp_buf *jmpbuf = (jmp_buf *)png_get_error_ptr(png_ptr); (void)message; longjmp(*jmpbuf, 1); } /* read_data: * Custom read function to use Allegro packfile routines, * rather than C streams (so we can read from datafiles!) */ static void read_data(png_structp png_ptr, png_bytep data, png_uint_32 length) { PACKFILE *f = (PACKFILE *)png_get_io_ptr(png_ptr); if ((png_uint_32)pack_fread(data, length, f) != length) png_error(png_ptr, "read error (loadpng calling pack_fread)"); } /* check_if_png: * Check if input file is really PNG format. */ #define PNG_BYTES_TO_CHECK 4 static int check_if_png(PACKFILE *fp) { unsigned char buf[PNG_BYTES_TO_CHECK]; ASSERT(fp); if (pack_fread(buf, PNG_BYTES_TO_CHECK, fp) != PNG_BYTES_TO_CHECK) return 0; return (png_sig_cmp(buf, (png_size_t)0, PNG_BYTES_TO_CHECK) == 0); } /* really_load_png: * Worker routine, used by load_png and load_memory_png. */ static BITMAP *really_load_png(png_structp png_ptr, png_infop info_ptr, RGB *pal) { BITMAP *bmp; PALETTE tmppal; png_uint_32 width, height, rowbytes; int bit_depth, color_type, interlace_type; double image_gamma, screen_gamma; int intent; int bpp, dest_bpp; int tRNS_to_alpha = FALSE; int number_passes, pass; ASSERT(png_ptr && info_ptr); /* The call to png_read_info() gives us all of the information from the * PNG file before the first IDAT (image data chunk). */ png_read_info(png_ptr, info_ptr); png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, NULL, NULL); /* Extract multiple pixels with bit depths of 1, 2, and 4 from a single * byte into separate bytes (useful for paletted and grayscale images). */ png_set_packing(png_ptr); /* Expand grayscale images to the full 8 bits from 1, 2, or 4 bits/pixel */ if ((color_type == PNG_COLOR_TYPE_GRAY) && (bit_depth < 8)) png_set_expand(png_ptr); /* Adds a full alpha channel if there is transparency information * in a tRNS chunk. */ if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { png_set_tRNS_to_alpha(png_ptr); tRNS_to_alpha = TRUE; } /* Convert 16-bits per colour component to 8-bits per colour component. */ if (bit_depth == 16) png_set_strip_16(png_ptr); /* Convert grayscale to RGB triplets */ if ((color_type == PNG_COLOR_TYPE_GRAY) || (color_type == PNG_COLOR_TYPE_GRAY_ALPHA)) png_set_gray_to_rgb(png_ptr); /* Optionally, tell libpng to handle the gamma correction for us. */ if (_png_screen_gamma != 0.0) { screen_gamma = get_gamma(); if (png_get_sRGB(png_ptr, info_ptr, &intent)) png_set_gamma(png_ptr, screen_gamma, 0.45455); else { if (png_get_gAMA(png_ptr, info_ptr, &image_gamma)) png_set_gamma(png_ptr, screen_gamma, image_gamma); else png_set_gamma(png_ptr, screen_gamma, 0.45455); } } /* Turn on interlace handling. */ number_passes = png_set_interlace_handling(png_ptr); /* Call to gamma correct and add the background to the palette * and update info structure. */ png_read_update_info(png_ptr, info_ptr); /* Even if the user doesn't supply space for a palette, we want * one for the load process. */ if (!pal) pal = tmppal; /* Palettes. */ if (color_type & PNG_COLOR_MASK_PALETTE) { int num_palette, i; png_colorp palette; if (png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette)) { /* We don't actually dither, we just copy the palette. */ for (i = 0; ((i < num_palette) && (i < 256)); i++) { pal[i].r = palette[i].red >> 2; /* 256 -> 64 */ pal[i].g = palette[i].green >> 2; pal[i].b = palette[i].blue >> 2; } for (; i < 256; i++) pal[i].r = pal[i].g = pal[i].b = 0; } } else { generate_332_palette(pal); } rowbytes = png_get_rowbytes(png_ptr, info_ptr); /* Allocate the memory to hold the image using the fields of info_ptr. */ bpp = rowbytes * 8 / width; /* Allegro cannot handle less than 8 bpp. */ if (bpp < 8) bpp = 8; dest_bpp = _color_load_depth(bpp, (bpp == 32)); bmp = create_bitmap_ex(bpp, width, height); /* Maybe flip RGB to BGR. */ if ((bpp == 24) || (bpp == 32)) { int c = makecol_depth(bpp, 0, 0, 255); unsigned char *pc = (unsigned char *)&c; if (pc[0] == 255) png_set_bgr(png_ptr); #ifdef ALLEGRO_BIG_ENDIAN png_set_swap_alpha(png_ptr); #endif } /* Read the image, one line at a line (easier to debug!) */ for (pass = 0; pass < number_passes; pass++) { png_uint_32 y; for (y = 0; y < height; y++) png_read_row(png_ptr, bmp->line[y], NULL); } /* Let Allegro convert the image into the desired colour depth. */ if (dest_bpp != bpp) bmp = _fixup_loaded_bitmap(bmp, pal, dest_bpp); /* Read rest of file, and get additional chunks in info_ptr. */ png_read_end(png_ptr, info_ptr); return bmp; } /* load_png: * Load a PNG file from disk, doing colour coversion if required. */ BITMAP *load_png(AL_CONST char *filename, RGB *pal) { PACKFILE *fp; BITMAP *bmp; ASSERT(filename); fp = pack_fopen(filename, "r"); if (!fp) return NULL; bmp = load_png_pf(fp, pal); pack_fclose(fp); return bmp; } /* load_png_pf: * Load a PNG file from disk, doing colour coversion if required. */ BITMAP *load_png_pf(PACKFILE *fp, RGB *pal) { jmp_buf jmpbuf; BITMAP *bmp; png_structp png_ptr; png_infop info_ptr; ASSERT(fp); if (!check_if_png(fp)) { return NULL; } /* Create and initialize the png_struct with the desired error handler * functions. If you want to use the default stderr and longjump method, * you can supply NULL for the last three parameters. We also supply the * the compiler header file version, so that we know if the application * was compiled with a compatible version of the library. */ png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, (void *)NULL, NULL, NULL); if (!png_ptr) { return NULL; } /* Allocate/initialize the memory for image information. */ info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); return NULL; } /* Set error handling. */ if (setjmp(jmpbuf)) { /* Free all of the memory associated with the png_ptr and info_ptr */ png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); /* If we get here, we had a problem reading the file */ return NULL; } png_set_error_fn(png_ptr, jmpbuf, user_error_fn, NULL); /* Use Allegro packfile routines. */ png_set_read_fn(png_ptr, fp, (png_rw_ptr)read_data); /* We have already read some of the signature. */ png_set_sig_bytes(png_ptr, PNG_BYTES_TO_CHECK); /* Really load the image now. */ bmp = really_load_png(png_ptr, info_ptr, pal); /* Clean up after the read, and free any memory allocated. */ png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); return bmp; } /* read_data_memory: * Custom reader function to read a PNG file from a memory buffer. */ typedef struct { AL_CONST unsigned char *buffer; png_uint_32 bufsize; png_uint_32 current_pos; } MEMORY_READER_STATE; static void read_data_memory(png_structp png_ptr, png_bytep data, png_uint_32 length) { MEMORY_READER_STATE *f = (MEMORY_READER_STATE *)png_get_io_ptr(png_ptr); if (length > (f->bufsize - f->current_pos)) png_error(png_ptr, "read error in read_data_memory (loadpng)"); memcpy(data, f->buffer + f->current_pos, length); f->current_pos += length; } /* check_if_png_memory: * Check if input buffer is really PNG format. */ static int check_if_png_memory(AL_CONST void *buffer) { unsigned char *buf = (unsigned char *)buffer; return (png_sig_cmp(buf, (png_size_t)0, PNG_BYTES_TO_CHECK) == 0); } /* load_memory_png: * Load a PNG file from memory, doing colour coversion if required. */ BITMAP *load_memory_png(AL_CONST void *buffer, int bufsize, RGB *pal) { jmp_buf jmpbuf; MEMORY_READER_STATE memory_reader_state; BITMAP *bmp; png_structp png_ptr; png_infop info_ptr; if (!buffer || (bufsize <= 0)) return NULL; if (!check_if_png_memory(buffer)) return NULL; /* Create and initialize the png_struct with the desired error handler * functions. If you want to use the default stderr and longjump method, * you can supply NULL for the last three parameters. We also supply the * the compiler header file version, so that we know if the application * was compiled with a compatible version of the library. */ png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, (void *)NULL, NULL, NULL); if (!png_ptr) return NULL; /* Allocate/initialize the memory for image information. */ info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); return NULL; } /* Set error handling. */ if (setjmp(jmpbuf)) { /* Free all of the memory associated with the png_ptr and info_ptr */ png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); /* If we get here, we had a problem reading the file */ return NULL; } png_set_error_fn(png_ptr, jmpbuf, user_error_fn, NULL); /* Set up the reader state. */ memory_reader_state.buffer = (unsigned char *)buffer; memory_reader_state.bufsize = bufsize; memory_reader_state.current_pos = PNG_BYTES_TO_CHECK; /* Tell libpng to use our custom reader. */ png_set_read_fn(png_ptr, &memory_reader_state, (png_rw_ptr)read_data_memory); /* We have already read some of the signature. */ png_set_sig_bytes(png_ptr, PNG_BYTES_TO_CHECK); /* Really load the image now. */ bmp = really_load_png(png_ptr, info_ptr, pal); /* Clean up after the read, and free any memory allocated. */ png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); return bmp; } allegro4.4-4.4.2/addons/loadpng/loadpng.h000066400000000000000000000040441173507505700201010ustar00rootroot00000000000000/* loadpng.h */ /* This file is hereby placed in the public domain. */ #ifndef _included_loadpng_h_ #define _included_loadpng_h_ #ifdef __cplusplus extern "C" { #endif /* Overkill :-) */ #define LOADPNG_VERSION 1 #define LOADPNG_SUBVERSION 5 #define LOADPNG_VERSIONSTR "1.5" /* _png_screen_gamma is slightly overloaded (sorry): * * A value of 0.0 means: Don't do any gamma correction in load_png() * and load_memory_png(). This meaning was introduced in v1.4. * * A value of -1.0 means: Use the value from the environment variable * SCREEN_GAMMA (if available), otherwise fallback to a value of 2.2 * (a good guess for PC monitors, and the value for sRGB colourspace). * This is the default. * * Otherwise, the value of _png_screen_gamma is taken as-is. */ extern double _png_screen_gamma; /* Choose zlib compression level for saving file. * Default is Z_BEST_COMPRESSION. */ extern int _png_compression_level; /* Load a PNG from disk. */ extern BITMAP *load_png(AL_CONST char *filename, RGB *pal); /* Load a PNG from some place. */ extern BITMAP *load_png_pf(PACKFILE *fp, RGB *pal); /* Load a PNG from memory. */ extern BITMAP *load_memory_png(AL_CONST void *buffer, int buffer_size, RGB *pal); /* Save a bitmap to disk in PNG format. */ extern int save_png(AL_CONST char *filename, BITMAP *bmp, AL_CONST RGB *pal); /* Adds `PNG' to Allegro's internal file type table. * You can then just use load_bitmap and save_bitmap as usual. */ extern void register_png_file_type(void); /* Register an datafile type ID with Allegro, so that when an object * with that type ID is encountered while loading a datafile, that * object will be loaded as a PNG file. */ extern void register_png_datafile_object(int id); /* This is supposed to resemble jpgalleg_init in JPGalleg 2.0, just in * case you are lazier than lazy. It contains these 3 lines of code: * register_png_datafile_object(DAT_ID('P','N','G',' ')); * register_png_file_type(); * return 0; */ extern int loadpng_init(void); #ifdef __cplusplus } #endif #endif /* _included_loadpng_h */ allegro4.4-4.4.2/addons/loadpng/regpng.c000066400000000000000000000021471173507505700177340ustar00rootroot00000000000000/* loadpng, Allegro wrapper routines for libpng * by Peter Wang (tjaden@users.sf.net). * * This file is hereby placed in the public domain. */ #include #include "loadpng.h" /* register_png_file_type: */ void register_png_file_type(void) { register_bitmap_file_type("png", load_png, save_png); } /* register_png_datafile_object: */ static void *load_datafile_png(PACKFILE *f, long size) { BITMAP *bmp; void *buffer; buffer = malloc(size); if (!buffer) return NULL; if (pack_fread(buffer, size, f) != size) { free(buffer); return NULL; } bmp = load_memory_png(buffer, size, NULL); free(buffer); return bmp; } static void destroy_datafile_png(void *data) { if (data) { destroy_bitmap((BITMAP *)data); } } void register_png_datafile_object(int id) { register_datafile_object(id, load_datafile_png, destroy_datafile_png); } /* loadpng_init: * This is supposed to resemble jpgalleg_init in JPGalleg 2.0. */ int loadpng_init(void) { register_png_datafile_object(DAT_ID('P','N','G',' ')); register_png_file_type(); return 0; } allegro4.4-4.4.2/addons/loadpng/savepng.c000066400000000000000000000156121173507505700201160ustar00rootroot00000000000000/* loadpng, Allegro wrapper routines for libpng * by Peter Wang (tjaden@users.sf.net). * * This file is hereby placed in the public domain. */ #include #include #include "loadpng.h" static void user_error_fn(png_structp png_ptr, png_const_charp message) { jmp_buf *jmpbuf = (jmp_buf *)png_get_error_ptr(png_ptr); (void)message; longjmp(*jmpbuf, 1); } /* write_data: * Custom write function to use Allegro packfile routines, * rather than C streams. */ static void write_data(png_structp png_ptr, png_bytep data, png_uint_32 length) { PACKFILE *f = (PACKFILE *)png_get_io_ptr(png_ptr); if ((png_uint_32)pack_fwrite(data, length, f) != length) png_error(png_ptr, "write error (loadpng calling pack_fwrite)"); } /* Don't think Allegro has any problem with buffering * (rather, Allegro provides no way to flush packfiles). */ static void flush_data(png_structp png_ptr) { (void)png_ptr; } /* save_indexed: * Core save routine for 8 bpp images. * */ static int save_indexed(png_structp png_ptr, BITMAP *bmp) { ASSERT(bitmap_color_depth(bmp) == 8); if (is_memory_bitmap(bmp)) { /* fast path */ int y; for (y=0; yh; y++) { png_write_row(png_ptr, bmp->line[y]); } return 1; } else { /* generic case */ unsigned char *rowdata; int x, y; rowdata = (unsigned char *)malloc(bmp->w * 3); if (!rowdata) return 0; for (y=0; yh; y++) { unsigned char *p = rowdata; for (x=0; xw; x++) { *p++ = getpixel(bmp, x, y); } png_write_row(png_ptr, rowdata); } free(rowdata); return 1; } } /* save_rgb: * Core save routine for 15/16/24 bpp images (original by Martijn Versteegh). */ static int save_rgb(png_structp png_ptr, BITMAP *bmp) { AL_CONST int depth = bitmap_color_depth(bmp); unsigned char *rowdata; int y, x; ASSERT(depth == 15 || depth == 16 || depth == 24); rowdata = (unsigned char *)malloc(bmp->w * 3); if (!rowdata) return 0; for (y=0; yh; y++) { unsigned char *p = rowdata; if (depth == 15) { for (x = 0; x < bmp->w; x++) { int c = getpixel(bmp, x, y); *p++ = getr15(c); *p++ = getg15(c); *p++ = getb15(c); } } else if (depth == 16) { for (x = 0; x < bmp->w; x++) { int c = getpixel(bmp, x, y); *p++ = getr16(c); *p++ = getg16(c); *p++ = getb16(c); } } else { /* depth == 24 */ for (x = 0; x < bmp->w; x++) { int c = getpixel(bmp, x, y); *p++ = getr24(c); *p++ = getg24(c); *p++ = getb24(c); } } png_write_row(png_ptr, rowdata); } free(rowdata); return 1; } /* save_rgba: * Core save routine for 32 bpp images. */ static int save_rgba(png_structp png_ptr, BITMAP *bmp) { unsigned char *rowdata; int x, y; ASSERT(bitmap_color_depth(bmp) == 32); rowdata = (unsigned char *)malloc(bmp->w * 4); if (!rowdata) return 0; for (y=0; yh; y++) { unsigned char *p = rowdata; for (x=0; xw; x++) { int c = getpixel(bmp, x, y); *p++ = getr32(c); *p++ = getg32(c); *p++ = getb32(c); *p++ = geta32(c); } png_write_row(png_ptr, rowdata); } free(rowdata); return 1; } /* save_png: * Writes a non-interlaced, no-frills PNG, taking the usual save_xyz * parameters. Returns non-zero on error. */ static int really_save_png(PACKFILE *fp, BITMAP *bmp, AL_CONST RGB *pal) { jmp_buf jmpbuf; png_structp png_ptr = NULL; png_infop info_ptr = NULL; int depth; int colour_type; depth = bitmap_color_depth(bmp); if (depth == 8 && !pal) return -1; /* Create and initialize the png_struct with the * desired error handler functions. */ png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, (void *)NULL, NULL, NULL); if (!png_ptr) goto Error; /* Allocate/initialize the image information data. */ info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) goto Error; /* Set error handling. */ if (setjmp(jmpbuf)) { /* If we get here, we had a problem reading the file. */ goto Error; } png_set_error_fn(png_ptr, jmpbuf, user_error_fn, NULL); /* Use packfile routines. */ png_set_write_fn(png_ptr, fp, (png_rw_ptr)write_data, flush_data); /* Set the image information here. Width and height are up to 2^31, * bit_depth is one of 1, 2, 4, 8, or 16, but valid values also depend on * the color_type selected. color_type is one of PNG_COLOR_TYPE_GRAY, * PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_PALETTE, PNG_COLOR_TYPE_RGB, * or PNG_COLOR_TYPE_RGB_ALPHA. interlace is either PNG_INTERLACE_NONE or * PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST * currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE. */ if (depth == 8) colour_type = PNG_COLOR_TYPE_PALETTE; else if (depth == 32) colour_type = PNG_COLOR_TYPE_RGB_ALPHA; else colour_type = PNG_COLOR_TYPE_RGB; /* Set compression level. */ png_set_compression_level(png_ptr, _png_compression_level); png_set_IHDR(png_ptr, info_ptr, bmp->w, bmp->h, 8, colour_type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); /* Set the palette if there is one. Required for indexed-color images. */ if (colour_type == PNG_COLOR_TYPE_PALETTE) { png_color palette[256]; int i; for (i = 0; i < 256; i++) { palette[i].red = _rgb_scale_6[pal[i].r]; /* 64 -> 256 */ palette[i].green = _rgb_scale_6[pal[i].g]; palette[i].blue = _rgb_scale_6[pal[i].b]; } /* Set palette colors. */ png_set_PLTE(png_ptr, info_ptr, palette, 256); } /* Optionally write comments into the image ... Nah. */ /* Write the file header information. */ png_write_info(png_ptr, info_ptr); /* Once we write out the header, the compression type on the text * chunks gets changed to PNG_TEXT_COMPRESSION_NONE_WR or * PNG_TEXT_COMPRESSION_zTXt_WR, so it doesn't get written out again * at the end. */ /* Save the data. */ switch (depth) { case 8: if (!save_indexed(png_ptr, bmp)) goto Error; break; case 15: case 16: case 24: if (!save_rgb(png_ptr, bmp)) goto Error; break; case 32: if (!save_rgba(png_ptr, bmp)) goto Error; break; default: ASSERT(FALSE); goto Error; } png_write_end(png_ptr, info_ptr); png_destroy_write_struct(&png_ptr, &info_ptr); return 0; Error: if (png_ptr) { if (info_ptr) png_destroy_write_struct(&png_ptr, &info_ptr); else png_destroy_write_struct(&png_ptr, NULL); } return -1; } int save_png(AL_CONST char *filename, BITMAP *bmp, AL_CONST RGB *pal) { PACKFILE *fp; int result; ASSERT(filename); ASSERT(bmp); fp = pack_fopen(filename, "w"); if (!fp) return -1; acquire_bitmap(bmp); result = really_save_png(fp, bmp, pal); release_bitmap(bmp); pack_fclose(fp); return result; } allegro4.4-4.4.2/addons/logg/000077500000000000000000000000001173507505700156065ustar00rootroot00000000000000allegro4.4-4.4.2/addons/logg/CMakeLists.txt000066400000000000000000000026151173507505700203520ustar00rootroot00000000000000#-----------------------------------------------------------------------------# # # logg # find_package(Vorbis) if(NOT VORBIS_FOUND) return() endif() include_directories(SYSTEM ${OGG_INCLUDE_DIR} ${VORBIS_INCLUDE_DIR}) set(LOGG_SOURCES logg.c ) set(LOGG_HEADERS logg.h ) set_source_files_properties(${LOGG_HEADERS} PROPERTIES MACOSX_PACKAGE_LOCATION Headers ) add_our_library(logg ${ADDON_LINKAGE} ${LOGG_SOURCES} ${LOGG_HEADERS} ) set_target_properties(logg PROPERTIES LINK_FLAGS "${ALLEGRO_LINK_FLAGS}" VERSION ${ALLEGRO_VERSION} SOVERSION ${ALLEGRO_SOVERSION} ) set_our_framework_properties(logg logg) target_link_libraries(logg allegro ${VORBIS_LIBRARIES}) sanitize_cmake_link_flags(static_link_with ${VORBIS_LIBRARIES}) set_target_properties(logg PROPERTIES static_link_with "${static_link_with}" ) install_our_library(logg) if(NOT WANT_FRAMEWORKS) install_our_headers(${LOGG_HEADERS}) endif(NOT WANT_FRAMEWORKS) #-----------------------------------------------------------------------------# # # Examples # if(WANT_EXAMPLES) add_executable(play_ogg play_ogg.c) target_link_libraries(play_ogg logg) add_executable(stream_ogg stream_ogg.c) target_link_libraries(stream_ogg logg) endif(WANT_EXAMPLES) #-----------------------------------------------------------------------------# # vim: set sts=4 sw=4 et: allegro4.4-4.4.2/addons/logg/LICENSE.txt000066400000000000000000000020411173507505700174260ustar00rootroot00000000000000Copyright (c) 2007 Trent Gamblin Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. allegro4.4-4.4.2/addons/logg/logg.c000066400000000000000000000111701173507505700167020ustar00rootroot00000000000000#include #include "allegro.h" #include "allegro/internal/aintern.h" #include "logg.h" /* XXX requires testing */ #ifdef ALLEGRO_BIG_ENDIAN const int ENDIANNESS = 1; #endif #ifdef ALLEGRO_LITTLE_ENDIAN const int ENDIANNESS = 0; #endif static int logg_bufsize = 1024*64; SAMPLE* logg_load(const char* filename) { OggVorbis_File ovf; FILE* file; vorbis_info* vi; SAMPLE* samp; int numRead; int offset = 0; int bitstream; char *buf = malloc(logg_bufsize); file = fopen(filename, "rb"); if (!file) { uszprintf(allegro_error, ALLEGRO_ERROR_SIZE, "Unable to open file: %s", filename); free(buf); return 0; } if (ov_open_callbacks(file, &ovf, 0, 0, OV_CALLBACKS_DEFAULT) != 0) { strncpy(allegro_error, "ov_open_callbacks failed.", ALLEGRO_ERROR_SIZE); fclose(file); free(buf); return 0; } vi = ov_info(&ovf, -1); samp = (SAMPLE*)_al_malloc(sizeof(SAMPLE)); if (!samp) { ov_clear(&ovf); free(buf); return 0; } samp->bits = 16; samp->stereo = vi->channels > 1 ? 1 : 0; samp->freq = vi->rate; samp->priority = 128; samp->len = ov_pcm_total(&ovf, -1); samp->loop_start = 0; samp->loop_end = samp->len; samp->data = _al_malloc(sizeof(unsigned short) * samp->len * 2); while ((numRead = ov_read(&ovf, buf, logg_bufsize, ENDIANNESS, 2, 0, &bitstream)) != 0) { memcpy((unsigned char*)samp->data+offset, buf, numRead); offset += numRead; } ov_clear(&ovf); free(buf); return samp; } int logg_get_buffer_size(void) { return logg_bufsize; } void logg_set_buffer_size(int size) { ASSERT(size > 0); logg_bufsize = size; } static int logg_open_file_for_streaming(LOGG_Stream* s) { FILE* file; vorbis_info* vi; file = fopen(s->filename, "rb"); if (!file) { uszprintf(allegro_error, ALLEGRO_ERROR_SIZE, "Unable to open file: %s", s->filename); return 1; } if (ov_open_callbacks(file, &s->ovf, 0, 0, OV_CALLBACKS_DEFAULT) != 0) { strncpy(allegro_error, "ov_open_callbacks failed.", ALLEGRO_ERROR_SIZE); fclose(file); return 1; } vi = ov_info(&s->ovf, -1); s->bits = 16; s->stereo = vi->channels > 1 ? 1 : 0; s->freq = vi->rate; s->len = ov_pcm_total(&s->ovf, -1); return 0; } static int read_ogg_data(LOGG_Stream* s) { int read = 0; int bitstream; int page = s->current_page; s->current_page++; s->current_page %= OGG_PAGES_TO_BUFFER; memset(s->buf[page], 0, logg_bufsize); while (read < logg_bufsize) { int thisRead = ov_read(&s->ovf, s->buf[page]+read, logg_bufsize-read, ENDIANNESS, 2, 0, &bitstream); if (thisRead == 0) { if (s->loop) { ov_clear(&s->ovf); if (logg_open_file_for_streaming(s)) { return -1; } } else { return read; } } read += thisRead; } return read; } static int logg_play_stream(LOGG_Stream* s) { int len; int i; s->current_page = 0; s->playing_page = -1; len = logg_bufsize / (s->stereo ? 2 : 1) / (s->bits / (sizeof(char)*8)); s->audio_stream = play_audio_stream(len, s->bits, s->stereo, s->freq, s->volume, s->pan); if (!s->audio_stream) { return 1; } for (i = 0; i < OGG_PAGES_TO_BUFFER; i++) { s->buf[i] = malloc(logg_bufsize); if (!s->buf[i]) { logg_destroy_stream(s); return 1; } if (read_ogg_data(s) < 0) { return 1; } } return 0; } LOGG_Stream* logg_get_stream(const char* filename, int volume, int pan, int loop) { LOGG_Stream* s = calloc(1, sizeof(LOGG_Stream)); if (!s) { return 0; } s->filename = strdup(filename); if (!s->filename) { free(s); return 0; } if (logg_open_file_for_streaming(s)) { logg_destroy_stream(s); return 0; } s->volume = volume; s->pan = pan; s->loop = loop; if (logg_play_stream(s)) { logg_destroy_stream(s); return 0; } return s; } int logg_update_stream(LOGG_Stream* s) { unsigned char* data = get_audio_stream_buffer(s->audio_stream); if (!data) { if (s->current_page != s->playing_page) { int read = read_ogg_data(s); if (read < logg_bufsize) { return 0; } else { return 1; } } else { return 1; } } s->playing_page++; s->playing_page %= OGG_PAGES_TO_BUFFER; memcpy(data, s->buf[s->playing_page], logg_bufsize); free_audio_stream_buffer(s->audio_stream); return 1; } void logg_stop_stream(LOGG_Stream* s) { int i; stop_audio_stream(s->audio_stream); for (i = 0; i < OGG_PAGES_TO_BUFFER; i++) { free(s->buf[i]); s->buf[i] = 0; } } int logg_restart_stream(LOGG_Stream* s) { return logg_play_stream(s); } void logg_destroy_stream(LOGG_Stream* s) { int i; if (s->audio_stream) { stop_audio_stream(s->audio_stream); } ov_clear(&s->ovf); for (i = 0; i < OGG_PAGES_TO_BUFFER; i++) { if (s->buf[i]) { free(s->buf[i]); } } free(s->filename); free(s); } allegro4.4-4.4.2/addons/logg/logg.h000066400000000000000000000015231173507505700167100ustar00rootroot00000000000000#ifndef LOGG_H #define LOGG_H #ifdef __cplusplus extern "C" { #endif #include #include #define OGG_PAGES_TO_BUFFER 2 typedef struct { char *buf[OGG_PAGES_TO_BUFFER]; int current_page; int playing_page; AUDIOSTREAM* audio_stream; OggVorbis_File ovf; int bits; int stereo; int freq; int len; char* filename; int loop; int volume; int pan; } LOGG_Stream; extern SAMPLE* logg_load(const char* filename); extern int logg_get_buffer_size(); extern void logg_set_buffer_size(int size); extern LOGG_Stream* logg_get_stream(const char* filename, int volume, int pan, int loop); extern int logg_update_stream(LOGG_Stream* s); extern void logg_destroy_stream(LOGG_Stream* s); extern void logg_stop_stream(LOGG_Stream* s); extern int logg_restart_stream(LOGG_Stream* s); #ifdef __cplusplus } #endif #endif allegro4.4-4.4.2/addons/logg/play_ogg.c000066400000000000000000000011351173507505700175530ustar00rootroot00000000000000#include "logg.h" int main(int argc, char** argv) { SAMPLE* s; int voice; if (argc != 2) { printf("usage: %s file.ogg\n", argv[0]); return 0; } if (allegro_init() != 0) { printf("Error initialising Allegro.\n"); return 1; } if (install_sound(DIGI_AUTODETECT, MIDI_NONE, 0) != 0) { printf("Error initialising sound: %s\n", allegro_error); return 1; } install_timer(); s = logg_load(argv[1]); if (!s) { printf("Error loading %s\n", argv[1]); return 1; } voice = play_sample(s, 255, 128, 1000, 0); rest(s->len*1000/s->freq); destroy_sample(s); return 0; } END_OF_MAIN() allegro4.4-4.4.2/addons/logg/stream_ogg.c000066400000000000000000000011501173507505700200760ustar00rootroot00000000000000#include #include "logg.h" int main(int argc, char** argv) { LOGG_Stream* s; if (argc != 2) { printf("usage: %s file.ogg\n", argv[0]); return 0; } if (allegro_init() != 0) { printf("Error initialising Allegro.\n"); return 1; } if (install_sound(DIGI_AUTODETECT, MIDI_NONE, 0) != 0) { printf("Error initialising sound: %s\n", allegro_error); return 1; } install_timer(); s = logg_get_stream(argv[1], 255, 128, 1); if (!s) { printf("Error getting ogg stream.\n"); return 1; } while (logg_update_stream(s)) { rest(1); } logg_destroy_stream(s); return 0; } END_OF_MAIN() allegro4.4-4.4.2/allegro.cfg000066400000000000000000000353061173507505700155230ustar00rootroot00000000000000# # Configuration file for the Allegro library. # # If you leave a parameter blank, Allegro will autodetect (ie. guess :-) # # This file should be kept either in the same directory as your program, # or in a location pointed to by the "ALLEGRO" environment variable. # # On Unix, this file may also be stored as ~/.allegrorc or /etc/allegrorc. [system] # Unix system drivers: # # XWIN - XWindows # LNXC - Linux console system = # Keyboard mapping file (this can be a .cfg file on disk, or an object from # keyboard.dat). Currently available layouts are: # # BE - Belgium # BR - Brazil # CF - Canada (French) # CH - Switzerland # CZ - Czech Republic # DE - Germany # DK - Denmark # DVORAK - Dvorak # ES - Spain # FI - Finland # FR - France # IT - Italy # NO - Norway # PL - Poland # PT - Portugal # RU - Russia # SE - Sweden # SK - Slovakia # UK - United Kingdom # US - United States keyboard = # Language translation file (this can be a .cfg file on disk, or an # object from language.dat). Currently available translations are: # # CA - Catalan # CZ - Czech # DE - German # DK - Danish # EN - English # ES - Spanish # FI - Finnish # FR - French # IT - Italian # NL - Dutch # NO - Norwegian # PL - Polish # PT - Portuguese # RU - Russian # SE - Swedish # SK - Slovak language = # whether to disable the screensaver (0:never 1:fullscreen 2:always, default 1) disable_screensaver = # how long to take for menus to auto-open (time in msecs or -1 to disable) menu_opening_delay = # use XInitThreads (default = 1) in the X11 port XInitThreads = [graphics] # DOS graphics drivers: # # VGA - Standard VGA # MODX - Mode-X # VBE1 - VESA 1.x # VB2B - VBE 2.0 (banked) # VB2L - VBE 2.0 (linear) # VBE3 - VBE 3.0 # VBAF - VBE/AF # XTND - Xtended mode # # Windows graphics drivers: # # DXAC - DirectX with hardware acceleration # DXSO - DirectX without hardware acceleration # DXSA - DirectX in safe-mode, with all the fancy features disabled # DXWN - DirectX in windowed mode # DXOV - DirectX overlay (fast windowed mode, only works on some cards) # GDIB - GDI mode (slow windowed mode, works on all cards) # # Linux console graphics drivers: # # FB - fbcon device # VBAF - VBE/AF # SVGA - SVGAlib # VGA - Standard VGA # MODX - Mode-X # # X graphics drivers: # # XWIN - standard X Windows # XWFS - Fullscreen X Windows # DGA2 - DGA 2.0 mode # DGAS - DGA 2.0 software only mode # # BeOS graphics drivers: # # BWSA - Fullscreen BWindowScreen with hardware acceleration # BWS - Fullscreen BWindowScreen # BDWN - Fast windowed mode via BDirectWindow # BWN - Normal windowed mode via BWindow # BOVL - Fullscreen overlay (only works on some cards) # # QNX graphics drivers: # # QPAC - Photon with hardware acceleration # QPSO - Photon without hardware acceleration # QPSA - Photon in safe-mode, with all the fancy features disabled # QPWN - Photon in windowed mode # # MacOS X graphics drivers: # # QZWN - Quartz windowed mode # QZFL - Quartz fullscreen mode via CGDirectDisplay interface # # You can also specify different drivers for a particular mode or color # depth, eg. "gfx_card_640x480x16 = VBE3", "gfx_card_24bpp = VBE1", or # you can provide a number of alternative drivers, for example # "gfx_card1 = VGA", "gfx_card2 = MODX", etc. gfx_card = # driver to use when autodetecting windowed modes gfx_cardw = # whether to disable synchronization with the vertical blank when # page-flipping (yes or no) disable_vsync = # DOS and Linux: where to look for the VBE/AF driver vbeaf_driver = # Linux only: fbcon device file (see below for fbcon timing data) framebuffer = # Unix/X11 only: whether to force window centering in fullscreen mode # for the XWFS driver (yes or no) force_centering = # Windows only: whether to disable direct updating in color conversion # mode for the DXWN driver (yes or no) disable_direct_updating = # Linux/fbcon mode timings. Duplicate then fill in `X', `Y' and # the timings themselves. You can copy them from fb.modes directly -- the # first two figures on the geometry line are X and Y here, and the figures # on the timings line are the first fields here (up to `vsync_len') [fb_mode_XxY] pixclock = left_margin = right_margin = upper_margin = lower_margin = hsync_len = vsync_len = vmode = sync = # You can customize the mapping of X11 key codes to Allegro keycodes here. For # example, if you want to swap Y and Z on a German keyboard as can be useful in # some games who assume Z and X are next to each other, you will see lines like # this in allegro.log if you run an Allegro program in debug mode: # al-xkey INFO: key [29: z Z] assigned to 26. # al-xkey INFO: key [52: y Y] assigned to 25. # 29 and 52 are the X11 codes, 26 is KEY_Z, 25 is KEY_Y. Using the two commented # out lines below, you would therefore swap both keys. [xkeymap] #keycode29 = 25 #keycode52 = 26 [mouse] # DOS mouse drivers: # # 0 - none # MICK - mickey mode driver (normally the best) # I33 - int 0x33 callback driver # POLL - timer polling # WNT - Windows NT 3.5x/4.0 specific driver # W2K - Windows 2000 specific driver # # Linux console mouse drivers: # # 0 - none # LPS2 - PS2 mouse # LIPS - PS2 mouse with Intellimouse extension # MS - Microsoft serial mouse # IMS - Microsoft serial mouse with Intellimouse extension # GPMD - GPM repeater data (Mouse Systems protocol) # EV - Event interfaces (EVDEV) - set mouse_device = /dev/input/eventN mouse = # number of buttons (specifying this overrides autodetection) num_buttons = # whether to emulate the third mouse button (yes or no) emulate_three = # Linux only: name of the mouse device file (eg. /dev/mouse) mouse_device = # Linux only: default EV input mode (0=relative, 1=absolute) ev_absolute = # Linux only: for absolute EV inputs, minimum and maximum values # (specifying this overrides autodetection) ev_min_x = ev_max_x = ev_min_y = ev_max_y = ev_min_z = ev_max_z = # Linux only: scaling factor for tablet mouse (1 by default). Good values are # usually between 1 and 40, higher numbers for bigger tablets ev_abs_to_rel_x = ev_abs_to_rel_y = ev_abs_to_rel_z = # Windows only: mouse acceleration factor (1 by default, 0 to disable) mouse_accel_factor = [sound] # DOS digital sound drivers: # # 0 - none # SB - Sound Blaster (autodetect breed) # SB10 - Sound Blaster 1.0 # SB15 - Sound Blaster 1.5 # SB20 - Sound Blaster 2.0 # SBP - Sound Blaster Pro # SB16 - Sound Blaster 16 # ESS - ESS AudioDrive # ESC - Ensoniq Soundscape # WSS - Windows Sound System # # Windows digital sound drivers: # # 0 - none # DXA - first DirectSound device # DXB - second DirectSound device # ... - etc # AXA - first DirectSound device using Allegro mixer # AXB - second DirectSound device using Allegro mixer # ... - etc # WOA - high quality WaveOut device # WOB - low quality WaveOut device # # Unix digital sound drivers: # # 0 - none # OSSD - Open Sound System # ESDD - Enlightened Sound Daemon # ARTS - aRts (Analog Real-Time Synthesizer) # ALSA - ALSA Sound System # JACK - JACK Audio Server # # BeOS digital sound drivers: # # 0 - none # BDIG - BeOS digital sound system # # MacOS X digital sound drivers: # # 0 - none # DCA - CoreAudio digital output # SNDM - Carbon Sound Manager # digi_card = # DOS music drivers: # # 0 - none # OPL - Adlib (autodetect OPL version) # OPL2 - OPL2 FM synth # OPLX - Dual OPL2 (SB Pro-1) # OPL3 - OPL3 FM synth # SB - raw SB MIDI interface # MPU - MPU-401 MIDI interface # DIGI - DIGMID software wavetable # AWE - AWE32 # # Windows music drivers: # # 0 - none # W32M - win32 MIDI mapper # W32A - first win32 MIDI device # W32B - second win32 MIDI device # ... - etc # DIGI - DIGMID software wavetable # # Linux music drivers: # # 0 - none # OSSM - Open Sound System # DIGI - DIGMID software wavetable # AMID - ALSA Sound System # # BeOS music drivers: # # 0 - none # BMID - BeOS MIDI synthesizer # DIGI - DIGMID software wavetable # # MacOS X music drivers: # # 0 - none # MCA - CoreAudio MIDI software synthesizer # QTM - QuickTime Music via Note Allocator # DIGI - DIGMID software wavetable # midi_card = # sound input drivers (same format as above, can usually be left blank) digi_input_card = midi_input_card = # how many voices to reserve for each driver digi_voices = midi_voices = # how loud? (range 0-255) digi_volume = midi_volume = # sample mixing quality (0=fastest, 1=full 16 bit precision, 2=interpolation) quality = # toggling this between 0 and 1 reverses the left/right panning of samples flip_pan = # DOS, Unix and BeOS: sample output frequency (eg. 44100) sound_freq = # Unix and BeOS: preferred number of bits (8 or 16) sound_bits = # Unix and BeOS: stereo output (1 or 0) sound_stereo = # DOS only: soundcard port address (usually 220) sound_port = # DOS only: soundcard DMA channel (usually 1) sound_dma = # DOS only: soundcard IRQ number (usually 7) sound_irq = # DOS only: FM synth port address (usually 388) fm_port = # DOS only: MPU-401 port address (usually 330) mpu_port = # DOS only: MPU-401 IRQ number (usually the same as sound_irq) mpu_irq = # DOS only: instrument definitions for the Adlib driver ibk_file = ibk_drum_file = # Unix only: OSS device driver name (usually /dev/dsp or /dev/audio) oss_driver = # Unix only: number of OSS driver fragments (buffers) and size of each buffer oss_numfrags = oss_fragsize = # Unix only: OSS MIDI device name (usually /dev/sequencer) oss_midi_driver = # Unix only: OSS mixer device name (usually /dev/mixer) oss_mixer_driver = # Unix only: name of the Enlightened Sound Daemon server esd_server = # Unix only: card number and PCM device for the ALSA 0.5 sound driver alsa_card = alsa_pcmdevice = # Unix only: device name for the ALSA 0.9 sound driver # format: [:,] (e.g.: hw:0,1) alsa_device = # Unix only: mixer device name for the ALSA 0.9 driver (default: default) alsa_mixer_device = # Unix only: mixer element name for the ALSA 0.9 driver (default: PCM) alsa_mixer_elem = # Unix only: number of ALSA driver fragments (buffers) alsa_numfrags = # Unix only: size of each ALSA fragment, in samples alsa_fragsize = # Unix only: card number for the ALSA 0.5 midi driver alsa_rawmidi_card = # Unix only: device for the ALSA 0.5 midi driver # device name for the ALSA 0.9 midi driver (see alsa_device) alsa_rawmidi_device = # Unix only: name for the JACK client (default: allegro) jack_client_name = # BeOS only: MIDI synthesizer instruments quality (0=low, 1=high) be_midi_quality = # BeOS only: MIDI sample mixing frequency in Hz (11025, 22050 or 44100) be_midi_freq = # BeOS only: MIDI interpolation (0=none, 1=fast linear, 2=linear) be_midi_interpolation = # BeOS only: MIDI reverberation intensity (0 to 5) be_midi_reverb = # MacOS X only: CoreAudio MIDI rendering quality (0 to 127) ca_midi_quality = # MacOS X only: CoreAudio MIDI reverberation intensity (0 to 5) ca_midi_reverb = # patch set for the DIGMID software wavetable driver patches = [joystick] # DOS joystick drivers : # # 0 - none # STD - standard 2-button # 2PAD - dual standard 2-button # 4BUT - standard 4-button # 6BUT - standard 6-button # 8BUT - standard 8-button # FPRO - CH Flightstick Pro # WING - Logitech Wingman Extreme # SW - Microsoft Sidewinder digital pad # SWAG - Microsoft Sidewinder digital pad (aggressive) # SWPP - Microsoft Sidewinder 3D/Precision/Force Feedback Pro # GPRO - Gravis GamePad Pro # GRIP - Gravis GrIP # GRI4 - Gravis GrIP (4-axis only) # SNE1 - SNES joypads connected to LPT1 # SNE2 - SNES joypads connected to LPT2 # SNE3 - SNES joypads connected to LPT3 # PSX1 - PSX joypads connected to LPT1 # PSX2 - PSX joypads connected to LPT2 # PSX3 - PSX joypads connected to LPT3 # N641 - N64 joypads connected to LPT1 # N642 - N64 joypads connected to LPT2 # N643 - N64 joypads connected to LPT3 # DB91 - Pair of 2-button joysticks connected to LPT1 # DB92 - Pair of 2-button joysticks connected to LPT2 # DB93 - Pair of 2-button joysticks connected to LPT3 # TGX1 - TurboGraFX joysticks connected to LPT1 # TGX2 - TurboGraFX joysticks connected to LPT2 # TGX3 - TurboGraFX joysticks connected to LPT3 # SEGI - IF-SEGA joystick interface card (ISA bus) # SEGP - IF-SEGA joystick interface card (PCI bus) # SGPF - IF-SEGA joystick interface card (fast PCI bus) # WWAR - Wingman Warrior # # Windows joystick drivers : # # 0 - none # DX - DirectInput joystick # W32 - Win32 joystick joytype = # BeoS and Linux only: name of the joystick device joystick_device = # alternatively you can specify it for each joystick: # joystick_device_0 = # joystick_device_1 = # ... # Linux only: axis number the throttle is located at throttle_axis = # alternatively you can specify it for each joystick: # # throttle_axis_0 = # throttle_axis_1 = # ... [grabber] # stored grabber variables (editor state information) xgrid = 16 ygrid = 16 backups = n index = n sort = n relative = n dither = n transparency = n griddle_xgrid = griddle_ygrid = griddle_mode = griddle_empties = griddle_autocrop = griddle_type = griddle_depth = # edit these shell commands to whatever helper programs you want to use... data = start /w notepad bmp = start /w "c:\program files\accessories\mspaint.exe" rle = start /w "c:\program files\accessories\mspaint.exe" cmp = start /w "c:\program files\accessories\mspaint.exe" xcmp = start /w "c:\program files\accessories\mspaint.exe" pal = start /w "c:\program files\accessories\mspaint.exe" font = start /w "c:\program files\accessories\mspaint.exe" samp = start /w "c:\program files\cooledit\cool.exe" midi = start /w "c:\program files\cakewalk\wincake.exe" # or if you are using Linux you might prefer something more like: # # data = xterm -e fed -b # bmp = gimp # rle = gimp # cmp = gimp # xcmp = gimp # pal = gimp # font = gimp allegro4.4-4.4.2/cmake/000077500000000000000000000000001173507505700144665ustar00rootroot00000000000000allegro4.4-4.4.2/cmake/AllegroFindOSS.cmake000066400000000000000000000043271173507505700202510ustar00rootroot00000000000000# - Find Open Sound System # # OSS_FOUND - True if OSS headers found. # This file is Allegro-specific and requires the following variables to be # set elsewhere: # ALLEGRO_HAVE_MACHINE_SOUNDCARD_H # ALLEGRO_HAVE_LINUX_SOUNDCARD_H # ALLEGRO_HAVE_SYS_SOUNDCARD_H # ALLEGRO_HAVE_SOUNDCARD_H if(OSS_INCLUDE_DIR) # Already in cache, be silent set(OSS_FIND_QUIETLY TRUE) endif(OSS_INCLUDE_DIR) set(CMAKE_REQUIRED_DEFINITIONS) if(ALLEGRO_HAVE_SOUNDCARD_H OR ALLEGRO_HAVE_SYS_SOUNDCARD_H OR ALLEGRO_HAVE_MACHINE_SOUNDCARD_H OR ALLEGRO_LINUX_SYS_SOUNDCARD_H) if(ALLEGRO_HAVE_MACHINE_SOUNDCARD_H) set(CMAKE_REQUIRED_DEFINITIONS -DALLEGRO_HAVE_MACHINE_SOUNDCARD_H) endif(ALLEGRO_HAVE_MACHINE_SOUNDCARD_H) if(ALLEGRO_HAVE_LINUX_SOUNDCARD_H) set(CMAKE_REQUIRED_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} -DALLEGRO_HAVE_LINUX_SOUNDCARD_H) endif(ALLEGRO_HAVE_LINUX_SOUNDCARD_H) if(ALLEGRO_HAVE_SYS_SOUNDCARD_H) set(CMAKE_REQUIRED_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} -DALLEGRO_HAVE_SYS_SOUNDCARD_H) endif(ALLEGRO_HAVE_SYS_SOUNDCARD_H) if(ALLEGRO_HAVE_SOUNDCARD_H) set(CMAKE_REQUIRED_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} -DALLEGRO_HAVE_SOUNDCARD_H) endif(ALLEGRO_HAVE_SOUNDCARD_H) check_c_source_compiles(" #ifdef ALLEGRO_HAVE_SOUNDCARD_H #include #endif #ifdef ALLEGRO_HAVE_SYS_SOUNDCARD_H #include #endif #ifdef ALLEGRO_HAVE_LINUX_SOUNDCARD_H #include #endif #ifdef ALLEGRO_HAVE_MACHINE_SOUNDCARD_H #include #endif int main(void) { audio_buf_info abi; return 0; }" OSS_COMPILES ) set(CMAKE_REQUIRED_DEFINITIONS) endif(ALLEGRO_HAVE_SOUNDCARD_H OR ALLEGRO_HAVE_SYS_SOUNDCARD_H OR ALLEGRO_HAVE_MACHINE_SOUNDCARD_H OR ALLEGRO_LINUX_SYS_SOUNDCARD_H) # Handle the QUIETLY and REQUIRED arguments and set OSS_FOUND to TRUE if # all listed variables are TRUE. include(FindPackageHandleStandardArgs) find_package_handle_standard_args(OSS DEFAULT_MSG OSS_COMPILES) mark_as_advanced(OSS_COMPILES) allegro4.4-4.4.2/cmake/Common.cmake000066400000000000000000000065451173507505700167320ustar00rootroot00000000000000# For OS X frameworks to work you must add headers to the target's sources. function(add_our_library target) add_library(${target} ${ARGN}) set_target_properties(${target} PROPERTIES DEBUG_POSTFIX -debug PROFILE_POSTFIX -profile ) endfunction(add_our_library) function(set_our_framework_properties target nm) if(WANT_FRAMEWORKS) if(WANT_EMBED) set(install_name_dir "@executable_path/../Frameworks") else() set(install_name_dir "${FRAMEWORK_INSTALL_PREFIX}") endif(WANT_EMBED) set_target_properties(${target} PROPERTIES FRAMEWORK on OUTPUT_NAME ${nm} INSTALL_NAME_DIR "${install_name_dir}" ) endif(WANT_FRAMEWORKS) endfunction(set_our_framework_properties) function(install_our_library target) install(TARGETS ${target} LIBRARY DESTINATION "lib${LIB_SUFFIX}" ARCHIVE DESTINATION "lib${LIB_SUFFIX}" FRAMEWORK DESTINATION "${FRAMEWORK_INSTALL_PREFIX}" RUNTIME DESTINATION "bin" # Doesn't work, see below. # PUBLIC_HEADER DESTINATION "include" ) endfunction(install_our_library) # Unfortunately, CMake's PUBLIC_HEADER support doesn't install into nested # directories well, otherwise we could rely on install(TARGETS) to install # header files associated with the target. Instead we use the install(FILES) # to install headers. We reuse the MACOSX_PACKAGE_LOCATION property, # substituting the "Headers" prefix with "include". function(install_our_headers) foreach(hdr ${ARGN}) get_source_file_property(LOC ${hdr} MACOSX_PACKAGE_LOCATION) string(REGEX REPLACE "^Headers" "include" LOC ${LOC}) install(FILES ${hdr} DESTINATION ${LOC}) endforeach() endfunction(install_our_headers) function(add_our_executable nm) add_executable(${nm} ${ARGN}) target_link_libraries(${nm} allegro) if(PSP) add_psp_executable(${nm}) endif(PSP) endfunction() # Oh my. CMake really is bad for this - but I couldn't find a better # way. function(sanitize_cmake_link_flags return) SET(acc_libs) foreach(lib ${ARGN}) # Watch out for -framework options (OS X) IF (NOT lib MATCHES "-framework.*|.*framework") # Remove absolute path. string(REGEX REPLACE "/.*/(.*)" "\\1" lib ${lib}) # Remove .a/.so/.dylib. string(REGEX REPLACE "lib(.*)\\.(a|so|dylib)" "\\1" lib ${lib}) # Remove -l prefix if it's there already. string(REGEX REPLACE "-l(.*)" "\\1" lib ${lib}) set(acc_libs "${acc_libs} -l${lib}") ENDIF() endforeach(lib) set(${return} ${acc_libs} PARENT_SCOPE) endfunction(sanitize_cmake_link_flags) function(copy_files target) if("${CMAKE_CURRENT_SOURCE_DIR}" STREQUAL "${CMAKE_CURRENT_BINARY_DIR}") return() endif() foreach(file ${ARGN}) # The "./" is NOT redundant as CMAKE_CFG_INTDIR may be "/". add_custom_command( OUTPUT "./${CMAKE_CFG_INTDIR}/${file}" DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/${file}" COMMAND "${CMAKE_COMMAND}" -E copy "${CMAKE_CURRENT_SOURCE_DIR}/${file}" "./${CMAKE_CFG_INTDIR}/${file}" ) endforeach() add_custom_target(${target} ALL DEPENDS ${ARGN}) endfunction() # vim: set sts=4 sw=4 et: allegro4.4-4.4.2/cmake/FileList.cmake000066400000000000000000000265051173507505700172130ustar00rootroot00000000000000set(ALLEGRO_SRC_FILES src/allegro.c src/blit.c src/bmp.c src/clip3d.c src/clip3df.c src/colblend.c src/color.c src/config.c src/datafile.c src/dataregi.c src/digmid.c src/dither.c src/dispsw.c src/drvlist.c src/file.c src/fli.c src/flood.c src/font.c src/fontbios.c src/fontbmp.c src/fontdat.c src/fontgrx.c src/fonttxt.c src/fsel.c src/gfx.c src/glyph.c src/graphics.c src/gsprite.c src/gui.c src/guiproc.c src/inline.c src/joystick.c src/keyboard.c src/lbm.c src/libc.c src/lzss.c src/math.c src/math3d.c src/midi.c src/mixer.c src/modesel.c src/mouse.c src/pcx.c src/poly3d.c src/polygon.c src/quantize.c src/quat.c src/readbmp.c src/readfont.c src/readsmp.c src/rle.c src/rotate.c src/rsfb.c src/scene3d.c src/sound.c src/spline.c src/stream.c src/text.c src/tga.c src/timer.c src/unicode.c src/vtable.c src/vtable15.c src/vtable16.c src/vtable24.c src/vtable32.c src/vtable8.c ) set(ALLEGRO_SRC_C_FILES src/c/cblit16.c src/c/cblit24.c src/c/cblit32.c src/c/cblit8.c src/c/ccpu.c src/c/ccsprite.c src/c/cgfx15.c src/c/cgfx16.c src/c/cgfx24.c src/c/cgfx32.c src/c/cgfx8.c src/c/cmisc.c src/c/cscan15.c src/c/cscan16.c src/c/cscan24.c src/c/cscan32.c src/c/cscan8.c src/c/cspr15.c src/c/cspr16.c src/c/cspr24.c src/c/cspr32.c src/c/cspr8.c src/c/cstretch.c src/c/czscan15.c src/c/czscan16.c src/c/czscan24.c src/c/czscan32.c src/c/czscan8.c src/misc/ccolconv.c src/misc/colconv.c ) set(ALLEGRO_SRC_DOS_FILES src/dos/adlib.c src/dos/awedata.c src/dos/dfile.c src/dos/dgfxdrv.c src/dos/djoydrv.c src/dos/dkeybd.c src/dos/dma.c src/dos/dmouse.c src/dos/dpmi.c src/dos/dsnddrv.c src/dos/dsystem.c src/dos/dtimer.c src/dos/emu8k.c src/dos/emu8kmid.c src/dos/essaudio.c src/dos/gpro.c src/dos/grip.c src/dos/gripjoy.c src/dos/gripfnc.s src/dos/ifsega.c src/dos/ifsega2f.c src/dos/ifsega2p.c src/dos/joystd.c src/dos/mpu.c src/dos/multijoy.c src/dos/n64pad.c src/dos/pic.c src/dos/psxpad.c src/dos/sb.c src/dos/sndscape.c src/dos/snespad.c src/dos/sw.c src/dos/swpp.c src/dos/swpps.s src/dos/vesa.c src/dos/vesas.s src/dos/wss.c src/dos/ww.c src/misc/modex.c src/misc/modexgfx.s src/misc/modexsms.c src/misc/pckeys.c src/misc/vbeaf.c src/misc/vbeafs.s src/misc/vbeafex.c src/misc/vga.c src/misc/vgaregs.c ) set(ALLEGRO_SRC_WIN_FILES src/win/asmlock.s src/win/dllver.rc src/win/gdi.c src/win/wddaccel.c src/win/wddbmp.c src/win/wddbmpl.c src/win/wddraw.c src/win/wddfull.c src/win/wddlock.c src/win/wddmode.c src/win/wddovl.c src/win/wddwin.c src/win/wdsinput.c src/win/wdsndmix.c src/win/wdsound.c src/win/wsndwo.c src/win/wdxver.c src/win/wdispsw.c src/win/wfile.c src/win/wgdi.c src/win/wgfxdrv.c src/win/winput.c src/win/wjoydrv.c src/win/wjoydx.c src/win/wjoyhelp.c src/win/wjoyw32.c src/win/wkeybd.c src/win/wmidi.c src/win/wmouse.c src/win/wsnddrv.c src/win/wsystem.c src/win/wthread.c src/win/wtimer.c src/win/wwnd.c ) set(ALLEGRO_SRC_BEOS_FILES src/beos/baccel.cpp src/beos/bdispsw.cpp src/beos/bdwindow.cpp src/beos/bgfx.c src/beos/bgfxapi.cpp src/beos/bgfxdrv.c src/beos/bjoy.c src/beos/bjoydrv.c src/beos/bjoyapi.cpp src/beos/bkey.c src/beos/bkeyapi.cpp src/beos/bkeydrv.c src/beos/bmidi.c src/beos/bmidiapi.cpp src/beos/bmididrv.c src/beos/bmousapi.cpp src/beos/bmousdrv.c src/beos/bmouse.c src/beos/boverlay.cpp src/beos/bsnd.c src/beos/bsndapi.cpp src/beos/bsnddrv.c src/beos/bswitch.s src/beos/bsysapi.cpp src/beos/bsysdrv.c src/beos/bsystem.c src/beos/btimeapi.cpp src/beos/btimedrv.c src/beos/btimer.c src/beos/bwindow.cpp src/beos/bwscreen.cpp src/unix/ufile.c src/misc/pckeys.c ) set(ALLEGRO_SRC_LINUX_FILES src/linux/fbcon.c src/linux/lconsole.c src/linux/lgfxdrv.c # Listed with UNIX files. # src/linux/ljoy.c src/linux/lkeybd.c src/linux/lmemory.c src/linux/lmouse.c src/linux/lmsedrv.c src/linux/lmsegpmd.c src/linux/lmsems.c src/linux/lmseps2.c src/linux/lmseev.c src/linux/lstddrv.c src/linux/lsystem.c src/linux/ltimer.c src/linux/lvga.c src/linux/lvgahelp.c src/linux/svgalib.c src/linux/svgalibs.s src/linux/vtswitch.c src/misc/vbeaf.c src/misc/vbeafs.s src/misc/vgaregs.c src/misc/vga.c # src/misc/modex.c # src/misc/modexgfx.s ) set(ALLEGRO_SRC_UNIX_FILES src/unix/alsa9.c src/unix/alsamidi.c src/unix/arts.c src/unix/sgial.c src/unix/jack.c src/unix/udjgpp.c src/unix/udrvlist.c src/unix/udummy.c src/unix/uesd.c src/unix/ufile.c src/unix/ugfxdrv.c src/unix/ujoydrv.c src/unix/ukeybd.c src/unix/umain.c src/unix/umodules.c src/unix/umouse.c src/unix/uoss.c src/unix/uossmidi.c src/unix/uptimer.c src/unix/usigalrm.c src/unix/usnddrv.c src/unix/ustimer.c src/unix/usystem.c src/unix/uthreads.c src/unix/utimer.c # src/misc/modexsms.c # May be used without enabling the entire Linux console port. src/linux/ljoy.c ) set(ALLEGRO_SRC_X_FILES src/x/xgfxdrv.c src/x/xkeyboard.c src/x/xmouse.c src/x/xsystem.c src/x/xtimer.c src/x/xvtable.c src/x/xwin.c src/x/xdga2.c src/x/xdga2s.s src/x/xwins.s ) set(ALLEGRO_SRC_MACOSX_FILES src/macosx/cadigi.m src/macosx/camidi.m src/macosx/drivers.m src/macosx/hidjoy.m src/macosx/hidman.m src/macosx/keybd.m src/macosx/pcpu.m src/macosx/qtmidi.m src/macosx/quartz.m src/macosx/qzfull.m src/macosx/qzmouse.m src/macosx/qzwindow.m src/macosx/soundman.m src/macosx/system.m src/unix/ufile.c src/unix/utimer.c src/unix/uptimer.c src/unix/usystem.c src/unix/uthreads.c ) set(ALLEGRO_SRC_PSP_FILES src/psp/pdrivers.c src/psp/pfile.c src/psp/pgfx.c src/psp/pjoy.c src/psp/pkey.c src/psp/pmouse.c src/psp/psound.c src/psp/psystem.c src/psp/ptimer.c src/psp/pvram.c src/psp/pvtable8.c ) set(ALLEGRO_INCLUDE_ALLEGRO_FILES include/allegro/3d.h include/allegro/3dmaths.h include/allegro/alcompat.h include/allegro/alinline.h include/allegro/base.h include/allegro/color.h include/allegro/compiled.h include/allegro/config.h include/allegro/datafile.h include/allegro/debug.h include/allegro/digi.h include/allegro/draw.h include/allegro/file.h include/allegro/fix.h include/allegro/fixed.h include/allegro/fli.h include/allegro/fmaths.h include/allegro/font.h include/allegro/gfx.h include/allegro/graphics.h include/allegro/gui.h include/allegro/joystick.h include/allegro/keyboard.h include/allegro/lzss.h include/allegro/matrix.h include/allegro/midi.h include/allegro/mouse.h include/allegro/palette.h include/allegro/quat.h include/allegro/rle.h include/allegro/sound.h include/allegro/stream.h include/allegro/system.h include/allegro/text.h include/allegro/timer.h include/allegro/unicode.h ) set(ALLEGRO_INCLUDE_ALLEGRO_INLINE_FILES include/allegro/inline/3dmaths.inl include/allegro/inline/asm.inl include/allegro/inline/color.inl include/allegro/inline/draw.inl include/allegro/inline/fix.inl include/allegro/inline/fmaths.inl include/allegro/inline/gfx.inl include/allegro/inline/matrix.inl include/allegro/inline/rle.inl include/allegro/inline/system.inl ) set(ALLEGRO_INCLUDE_ALLEGRO_INTERNAL_FILES include/allegro/internal/aintern.h include/allegro/internal/aintvga.h include/allegro/internal/alconfig.h ) set(ALLEGRO_INCLUDE_ALLEGRO_PLATFORM_FILES include/allegro/platform/aintbeos.h include/allegro/platform/aintdos.h include/allegro/platform/aintlnx.h include/allegro/platform/aintmac.h include/allegro/platform/aintosx.h include/allegro/platform/aintpsp.h include/allegro/platform/aintqnx.h include/allegro/platform/aintunix.h include/allegro/platform/aintwin.h include/allegro/platform/al386gcc.h include/allegro/platform/al386vc.h include/allegro/platform/al386wat.h include/allegro/platform/albcc32.h include/allegro/platform/albecfg.h include/allegro/platform/albeos.h include/allegro/platform/aldjgpp.h include/allegro/platform/aldmc.h include/allegro/platform/aldos.h include/allegro/platform/almac.h include/allegro/platform/almaccfg.h include/allegro/platform/almngw32.h include/allegro/platform/almsvc.h include/allegro/platform/alosx.h include/allegro/platform/alosxcfg.h # include/allegro/platform/alplatf.h.cmake include/allegro/platform/alpsp.h include/allegro/platform/alpspcfg.h include/allegro/platform/alqnx.h include/allegro/platform/alqnxcfg.h include/allegro/platform/alucfg.h include/allegro/platform/alunix.h # include/allegro/platform/alunixac.h.cmake # include/allegro/platform/alunixac.hin include/allegro/platform/alwatcom.h include/allegro/platform/alwin.h include/allegro/platform/astdint.h include/allegro/platform/macdef.h ) #-----------------------------------------------------------------------------# # vim: set sts=4 sw=4 et: allegro4.4-4.4.2/cmake/FindDDraw.cmake000066400000000000000000000021311173507505700172670ustar00rootroot00000000000000# - Find DirectDraw # Find the DirectDraw includes and libraries # # DDRAW_INCLUDE_DIR - where to find ddraw.h # DDRAW_LIBRARIES - List of libraries when using ddraw. # DDRAW_FOUND - True if ddraw found. if(DDRAW_INCLUDE_DIR) # Already in cache, be silent set(DDRAW_FIND_QUIETLY TRUE) endif(DDRAW_INCLUDE_DIR) # Makes my life easier. if(MSVC) set(HINT_INCLUDE "C:/Program Files/Microsoft DirectX SDK (August 2008)/Include") set(HINT_LIB "C:/Program Files/Microsoft DirectX SDK (August 2008)/Lib") endif(MSVC) find_path(DDRAW_INCLUDE_DIR ddraw.h PATH ${HINT_INCLUDE} ) find_library(DDRAW_LIBRARY NAMES ddraw PATHS ${HINT_LIB} PATH_SUFFIXES x86 x64 ) # Handle the QUIETLY and REQUIRED arguments and set DDRAW_FOUND to TRUE if # all listed variables are TRUE. include(FindPackageHandleStandardArgs) find_package_handle_standard_args(DDRAW DEFAULT_MSG DDRAW_INCLUDE_DIR DDRAW_LIBRARY) if(DDRAW_FOUND) set(DDRAW_LIBRARIES ${DDRAW_LIBRARY}) else(DDRAW_FOUND) set(DDRAW_LIBRARIES) endif(DDRAW_FOUND) mark_as_advanced(DDRAW_INCLUDE_DIR DDRAW_LIBRARY) allegro4.4-4.4.2/cmake/FindDInput.cmake000066400000000000000000000021741173507505700175000ustar00rootroot00000000000000# - Find DirectInput # Find the DirectInput includes and libraries # # DINPUT_INCLUDE_DIR - where to find dinput.h # DINPUT_LIBRARIES - List of libraries when using dinput. # DINPUT_FOUND - True if dinput found. if(DINPUT_INCLUDE_DIR) # Already in cache, be silent set(DINPUT_FIND_QUIETLY TRUE) endif(DINPUT_INCLUDE_DIR) # Makes my life easier. if(MSVC) set(HINT_INCLUDE "C:/Program Files/Microsoft DirectX SDK (August 2008)/Include") set(HINT_LIB "C:/Program Files/Microsoft DirectX SDK (August 2008)/Lib") endif(MSVC) find_path(DINPUT_INCLUDE_DIR dinput.h PATH ${HINT_INCLUDE} ) find_library(DINPUT_LIBRARY NAMES dinput dinput8 PATHS ${HINT_LIB} PATH_SUFFIXES x86 x64 ) # Handle the QUIETLY and REQUIRED arguments and set DINPUT_FOUND to TRUE if # all listed variables are TRUE. include(FindPackageHandleStandardArgs) find_package_handle_standard_args(DINPUT DEFAULT_MSG DINPUT_INCLUDE_DIR DINPUT_LIBRARY) if(DINPUT_FOUND) set(DINPUT_LIBRARIES ${DINPUT_LIBRARY}) else(DINPUT_FOUND) set(DINPUT_LIBRARIES) endif(DINPUT_FOUND) mark_as_advanced(DINPUT_INCLUDE_DIR DINPUT_LIBRARY) allegro4.4-4.4.2/cmake/FindDSound.cmake000066400000000000000000000021541173507505700174670ustar00rootroot00000000000000# - Find DirectSound # Find the DirectSound includes and libraries # # DSOUND_INCLUDE_DIR - where to find dsound.h # DSOUND_LIBRARIES - List of libraries when using dsound. # DSOUND_FOUND - True if dsound found. if(DSOUND_INCLUDE_DIR) # Already in cache, be silent set(DSOUND_FIND_QUIETLY TRUE) endif(DSOUND_INCLUDE_DIR) # Makes my life easier. if(MSVC) set(HINT_INCLUDE "C:/Program Files/Microsoft DirectX SDK (August 2008)/Include") set(HINT_LIB "C:/Program Files/Microsoft DirectX SDK (August 2008)/Lib") endif(MSVC) find_path(DSOUND_INCLUDE_DIR dsound.h PATHS ${HINT_INCLUDE}) find_library(DSOUND_LIBRARY NAMES dsound PATHS ${HINT_LIB} PATH_SUFFIXES x86 x64 ) # Handle the QUIETLY and REQUIRED arguments and set DSOUND_FOUND to TRUE if # all listed variables are TRUE. include(FindPackageHandleStandardArgs) find_package_handle_standard_args(DSOUND DEFAULT_MSG DSOUND_INCLUDE_DIR DSOUND_LIBRARY) if(DSOUND_FOUND) set(DSOUND_LIBRARIES ${DSOUND_LIBRARY}) else(DSOUND_FOUND) set(DSOUND_LIBRARIES) endif(DSOUND_FOUND) mark_as_advanced(DSOUND_INCLUDE_DIR DSOUND_LIBRARY) allegro4.4-4.4.2/cmake/FindDXGuid.cmake000066400000000000000000000013751173507505700174230ustar00rootroot00000000000000# - Find dxguid # Find the dxguid libraries # # DXGUID_LIBRARIES - List of libraries # DXGUID_FOUND - True if dxguid found. if(MSVC) find_library(DXGUID_LIBRARY NAMES dxguid PATHS "C:/Program Files/Microsoft DirectX SDK (August 2008)/Lib" PATH_SUFFIXES x86 x64 ) else() find_library(DXGUID_LIBRARY NAMES dxguid) endif() # Handle the QUIETLY and REQUIRED arguments and set DXGUID_FOUND to TRUE if # all listed variables are TRUE. include(FindPackageHandleStandardArgs) find_package_handle_standard_args(DXGUID DEFAULT_MSG DXGUID_LIBRARY) if(DXGUID_FOUND) set(DXGUID_LIBRARIES ${DXGUID_LIBRARY}) else(DXGUID_FOUND) set(DXGUID_LIBRARIES) endif(DXGUID_FOUND) mark_as_advanced(DXGUID_INCLUDE_DIR DXGUID_LIBRARY) allegro4.4-4.4.2/cmake/FindSvgalib.cmake000066400000000000000000000012701173507505700176600ustar00rootroot00000000000000# - Find svgalib # # SVGALIB_INCLUDE_DIR - where to find vga.h, etc. # SVGALIB_LIBRARIES - List of libraries when using svgalib. # SVGALIB_FOUND - True if vorbis found. if(SVGALIB_INCLUDE_DIR) # Already in cache, be silent set(SVGALIB_FIND_QUIETLY TRUE) endif(SVGALIB_INCLUDE_DIR) find_path(SVGALIB_INCLUDE_DIR vga.h) find_library(SVGALIB_LIBRARY NAMES vga) # Handle the QUIETLY and REQUIRED arguments and set SVGALIB_FOUND # to TRUE if all listed variables are TRUE. include(FindPackageHandleStandardArgs) find_package_handle_standard_args(SVGALIB DEFAULT_MSG SVGALIB_INCLUDE_DIR SVGALIB_LIBRARY) mark_as_advanced(SVGALIB_INCLUDE_DIR) mark_as_advanced(SVGALIB_LIBRARY) allegro4.4-4.4.2/cmake/FindVorbis.cmake000066400000000000000000000030431173507505700175350ustar00rootroot00000000000000# - Find vorbis # Find the native vorbis includes and libraries # # VORBIS_INCLUDE_DIR - where to find vorbis.h, etc. # VORBIS_LIBRARIES - List of libraries when using vorbis(file). # VORBIS_FOUND - True if vorbis found. if(NOT GP2XWIZ) if(VORBIS_INCLUDE_DIR) # Already in cache, be silent set(VORBIS_FIND_QUIETLY TRUE) endif(VORBIS_INCLUDE_DIR) find_path(OGG_INCLUDE_DIR ogg/ogg.h) find_path(VORBIS_INCLUDE_DIR vorbis/vorbisfile.h) find_library(OGG_LIBRARY NAMES ogg) find_library(VORBIS_LIBRARY NAMES vorbis) find_library(VORBISFILE_LIBRARY NAMES vorbisfile) # Handle the QUIETLY and REQUIRED arguments and set VORBIS_FOUND # to TRUE if all listed variables are TRUE. include(FindPackageHandleStandardArgs) find_package_handle_standard_args(VORBIS DEFAULT_MSG OGG_INCLUDE_DIR VORBIS_INCLUDE_DIR OGG_LIBRARY VORBIS_LIBRARY VORBISFILE_LIBRARY) else(NOT GP2XWIZ) find_path(VORBIS_INCLUDE_DIR tremor/ivorbisfile.h) find_library(VORBIS_LIBRARY NAMES vorbis_dec) find_package_handle_standard_args(VORBIS DEFAULT_MSG VORBIS_INCLUDE_DIR VORBIS_LIBRARY) endif(NOT GP2XWIZ) if(VORBIS_FOUND) if(NOT GP2XWIZ) set(VORBIS_LIBRARIES ${VORBISFILE_LIBRARY} ${VORBIS_LIBRARY} ${OGG_LIBRARY}) else(NOT GP2XWIZ) set(VORBIS_LIBRARIES ${VORBIS_LIBRARY}) endif(NOT GP2XWIZ) else(VORBIS_FOUND) set(VORBIS_LIBRARIES) endif(VORBIS_FOUND) mark_as_advanced(OGG_INCLUDE_DIR VORBIS_INCLUDE_DIR) mark_as_advanced(OGG_LIBRARY VORBIS_LIBRARY VORBISFILE_LIBRARY) allegro4.4-4.4.2/cmake/Toolchain-mingw.cmake000066400000000000000000000052011173507505700205250ustar00rootroot00000000000000# Use this command to build the Windows port of Allegro # with a mingw cross compiler: # # cmake -DCMAKE_TOOLCHAIN_FILE=cmake/Toolchain-mingw.cmake . # # or for out of source: # # cmake -DCMAKE_TOOLCHAIN_FILE=../cmake/Toolchain-mingw.cmake .. # # You will need at least CMake 2.6.0. # # Adjust the following paths to suit your environment. # # You might want to set MINGDIR to prevent make install making a mess # in your normal directories. # # This file was based on http://www.cmake.org/Wiki/CmakeMingw # the name of the target operating system set(CMAKE_SYSTEM_NAME Windows) # Assume the target architecture. # XXX for some reason the value set here gets cleared before we reach the # main CMakeLists.txt; see that file for a workaround. # set(CMAKE_SYSTEM_PROCESSOR i686) # Which compilers to use for C and C++, and location of target # environment. if(EXISTS /usr/i586-mingw32msvc) # First look in standard location as used by Debian/Ubuntu/etc. set(CMAKE_C_COMPILER i586-mingw32msvc-gcc) set(CMAKE_CXX_COMPILER i586-mingw32msvc-g++) set(CMAKE_FIND_ROOT_PATH /usr/i586-mingw32msvc) elseif(EXISTS /opt/mingw) # Otherwise you can get a MinGW environment using the script at # . It downloads and builds MinGW and # most of the dependencies for you. This is a suitable location. set(CMAKE_C_COMPILER /opt/mingw/usr/bin/i686-pc-mingw32-gcc) set(CMAKE_CXX_COMPILER /opt/mingw/usr/bin/i686-pc-mingw32-g++) set(CMAKE_FIND_ROOT_PATH /opt/mingw/usr/i686-pc-mingw32) else() # Else fill in local path which the user will likely adjust. # This is the location assumed by set(CMAKE_C_COMPILER /usr/local/cross-tools/bin/i386-mingw32-gcc) set(CMAKE_CXX_COMPILER /usr/local/cross-tools/bin/i386-mingw32-g++) set(CMAKE_FIND_ROOT_PATH /usr/local/cross-tools) endif() # Adjust the default behaviour of the FIND_XXX() commands: # search headers and libraries in the target environment, search # programs in the host environment set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) # Tell pkg-config not to look at the target environment's .pc files. # Setting PKG_CONFIG_LIBDIR sets the default search directory, but we have to # set PKG_CONFIG_PATH as well to prevent pkg-config falling back to the host's # path. set(ENV{PKG_CONFIG_LIBDIR} ${CMAKE_FIND_ROOT_PATH}/lib/pkgconfig) set(ENV{PKG_CONFIG_PATH} ${CMAKE_FIND_ROOT_PATH}/lib/pkgconfig) set(INSTALL_PREFIX ${CMAKE_FIND_ROOT_PATH}) if(ENV{MINGDIR} STREQUAL "") set(ENV{MINGDIR} ${CMAKE_FIND_ROOT_PATH}) endif() allegro4.4-4.4.2/cmake/Toolchain-psp-gcc.cmake000066400000000000000000000206751173507505700207540ustar00rootroot00000000000000# Use this command to build the PSP port of Allegro: # # cmake -DWANT_TESTS=off -DWANT_TOOLS=off -DWANT_LOGG=off -DWANT_ALLEGROGL=off -DCMAKE_TOOLCHAIN_FILE=cmake/Toolchain-psp-gcc.cmake . # # or for out of source: # # cmake -DWANT_TESTS=off -DWANT_TOOLS=off -DWANT_LOGG=off -DWANT_ALLEGROGL=off -DCMAKE_TOOLCHAIN_FILE=../cmake/Toolchain-psp-gcc.cmake .. # # You will need at least CMake 2.6.0. # # Adjust the following paths to suit your environment. # # This file was based on http://www.cmake.org/Wiki/CmakeMingw # The name of the target operating system. set(CMAKE_SYSTEM_NAME Generic) # Location of target environment. find_program(psp-config_SCRIPT psp-config) if (psp-config_SCRIPT) execute_process(COMMAND ${psp-config_SCRIPT} ARGS --psp-prefix OUTPUT_VARIABLE PSP_PREFIX OUTPUT_STRIP_TRAILING_WHITESPACE) execute_process(COMMAND ${psp-config_SCRIPT} ARGS --pspsdk-path OUTPUT_VARIABLE PSPSDK_PATH OUTPUT_STRIP_TRAILING_WHITESPACE) else (psp-config_SCRIPT) message(FATAL_ERROR "psp-config was not found.\nInstall the PSPDEV toolchain or update the $PATH environment variable.") endif (psp-config_SCRIPT) set(CMAKE_SYSTEM_INCLUDE_PATH "${PSP_PREFIX}/include") set(CMAKE_SYSTEM_LIBRARY_PATH "${PSP_PREFIX}/lib") set(CMAKE_SYSTEM_PROGRAM_PATH "${PSP_PREFIX}/bin") # Which compilers to use for C and C++. set(CMAKE_C_COMPILER psp-gcc) set(CMAKE_CXX_COMPILER psp-g++) # Needed to pass the compiler tests. set(LINK_DIRECTORIES ${PSPSDK_PATH}/lib) set(LINK_LIBRARIES -lc -lpspuser -lpspkernel -lc) # Adjust the default behaviour of the FIND_XXX() commands: # search headers and libraries in the target environment, search # programs in the host environment. set(CMAKE_FIND_ROOT_PATH ${PSP_PREFIX}) set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) # After building the ELF binary build the PSP executable. function(add_psp_executable nm) get_target_property(PSP_EXECUTABLE_OUTPUT_NAME ${nm} OUTPUT_NAME) if (NOT PSP_EXECUTABLE_OUTPUT_NAME) set(PSP_EXECUTABLE_OUTPUT_NAME ${nm}) endif(NOT PSP_EXECUTABLE_OUTPUT_NAME) set_target_properties( ${nm} PROPERTIES LINK_FLAGS "-specs=${PSPSDK_PATH}/lib/prxspecs -Wl,-q,-T${PSPSDK_PATH}/lib/linkfile.prx ${PSPSDK_PATH}/lib/prxexports.o" ) add_custom_command( TARGET ${nm} POST_BUILD COMMAND psp-fixup-imports ${PSP_EXECUTABLE_OUTPUT_NAME} COMMAND mksfo '${PSP_EXECUTABLE_OUTPUT_NAME}' PARAM.SFO COMMAND psp-prxgen ${PSP_EXECUTABLE_OUTPUT_NAME} ${PSP_EXECUTABLE_OUTPUT_NAME}.prx COMMAND pack-pbp EBOOT.PBP PARAM.SFO NULL NULL NULL NULL NULL ${PSP_EXECUTABLE_OUTPUT_NAME}.prx NULL ) endfunction() set(PSP 1) # Use this command to build the PSP port of Allegro: # # cmake -DWANT_TESTS=off -DWANT_TOOLS=off -DWANT_LOGG=off -DWANT_ALLEGROGL=off -DCMAKE_TOOLCHAIN_FILE=cmake/Toolchain-psp-gcc.cmake . # # or for out of source: # # cmake -DWANT_TESTS=off -DWANT_TOOLS=off -DWANT_LOGG=off -DWANT_ALLEGROGL=off -DCMAKE_TOOLCHAIN_FILE=../cmake/Toolchain-psp-gcc.cmake .. # # You will need at least CMake 2.6.0. # # Adjust the following paths to suit your environment. # # This file was based on http://www.cmake.org/Wiki/CmakeMingw # The name of the target operating system. set(CMAKE_SYSTEM_NAME Generic) # Location of target environment. find_program(psp-config_SCRIPT psp-config) if (psp-config_SCRIPT) execute_process(COMMAND ${psp-config_SCRIPT} ARGS --psp-prefix OUTPUT_VARIABLE PSP_PREFIX OUTPUT_STRIP_TRAILING_WHITESPACE) execute_process(COMMAND ${psp-config_SCRIPT} ARGS --pspsdk-path OUTPUT_VARIABLE PSPSDK_PATH OUTPUT_STRIP_TRAILING_WHITESPACE) else (psp-config_SCRIPT) message(FATAL_ERROR "psp-config was not found.\nInstall the PSPDEV toolchain or update the $PATH environment variable.") endif (psp-config_SCRIPT) set(CMAKE_SYSTEM_INCLUDE_PATH "${PSP_PREFIX}/include") set(CMAKE_SYSTEM_LIBRARY_PATH "${PSP_PREFIX}/lib") set(CMAKE_SYSTEM_PROGRAM_PATH "${PSP_PREFIX}/bin") # Which compilers to use for C and C++. set(CMAKE_C_COMPILER psp-gcc) set(CMAKE_CXX_COMPILER psp-g++) # Needed to pass the compiler tests. set(LINK_DIRECTORIES ${PSPSDK_PATH}/lib) set(LINK_LIBRARIES -lc -lpspuser -lpspkernel -lc) # Adjust the default behaviour of the FIND_XXX() commands: # search headers and libraries in the target environment, search # programs in the host environment. set(CMAKE_FIND_ROOT_PATH ${PSP_PREFIX}) set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) # After building the ELF binary build the PSP executable. function(add_psp_executable nm) get_target_property(PSP_EXECUTABLE_OUTPUT_NAME ${nm} OUTPUT_NAME) if (NOT PSP_EXECUTABLE_OUTPUT_NAME) set(PSP_EXECUTABLE_OUTPUT_NAME ${nm}) endif(NOT PSP_EXECUTABLE_OUTPUT_NAME) set_target_properties( ${nm} PROPERTIES LINK_FLAGS "-specs=${PSPSDK_PATH}/lib/prxspecs -Wl,-q,-T${PSPSDK_PATH}/lib/linkfile.prx ${PSPSDK_PATH}/lib/prxexports.o" ) add_custom_command( TARGET ${nm} POST_BUILD COMMAND psp-fixup-imports ${PSP_EXECUTABLE_OUTPUT_NAME} COMMAND mksfo '${PSP_EXECUTABLE_OUTPUT_NAME}' PARAM.SFO COMMAND psp-prxgen ${PSP_EXECUTABLE_OUTPUT_NAME} ${PSP_EXECUTABLE_OUTPUT_NAME}.prx COMMAND pack-pbp EBOOT.PBP PARAM.SFO NULL NULL NULL NULL NULL ${PSP_EXECUTABLE_OUTPUT_NAME}.prx NULL ) endfunction() set(PSP 1) # Use this command to build the PSP port of Allegro: # # cmake -DWANT_TESTS=off -DWANT_TOOLS=off -DWANT_LOGG=off -DWANT_ALLEGROGL=off -DCMAKE_TOOLCHAIN_FILE=cmake/Toolchain-psp-gcc.cmake . # # or for out of source: # # cmake -DWANT_TESTS=off -DWANT_TOOLS=off -DWANT_LOGG=off -DWANT_ALLEGROGL=off -DCMAKE_TOOLCHAIN_FILE=../cmake/Toolchain-psp-gcc.cmake .. # # You will need at least CMake 2.6.0. # # Adjust the following paths to suit your environment. # # This file was based on http://www.cmake.org/Wiki/CmakeMingw # The name of the target operating system. set(CMAKE_SYSTEM_NAME Generic) # Location of target environment. find_program(psp-config_SCRIPT psp-config) if (psp-config_SCRIPT) execute_process(COMMAND ${psp-config_SCRIPT} ARGS --psp-prefix OUTPUT_VARIABLE PSP_PREFIX OUTPUT_STRIP_TRAILING_WHITESPACE) execute_process(COMMAND ${psp-config_SCRIPT} ARGS --pspsdk-path OUTPUT_VARIABLE PSPSDK_PATH OUTPUT_STRIP_TRAILING_WHITESPACE) else (psp-config_SCRIPT) message(FATAL_ERROR "psp-config was not found.\nInstall the PSPDEV toolchain or update the $PATH environment variable.") endif (psp-config_SCRIPT) set(CMAKE_SYSTEM_INCLUDE_PATH "${PSP_PREFIX}/include") set(CMAKE_SYSTEM_LIBRARY_PATH "${PSP_PREFIX}/lib") set(CMAKE_SYSTEM_PROGRAM_PATH "${PSP_PREFIX}/bin") # Which compilers to use for C and C++. set(CMAKE_C_COMPILER psp-gcc) set(CMAKE_CXX_COMPILER psp-g++) # Needed to pass the compiler tests. set(LINK_DIRECTORIES ${PSPSDK_PATH}/lib) set(LINK_LIBRARIES -lc -lpspuser -lpspkernel -lc) # Adjust the default behaviour of the FIND_XXX() commands: # search headers and libraries in the target environment, search # programs in the host environment. set(CMAKE_FIND_ROOT_PATH ${PSP_PREFIX}) set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) # After building the ELF binary build the PSP executable. function(add_psp_executable nm) get_target_property(PSP_EXECUTABLE_OUTPUT_NAME ${nm} OUTPUT_NAME) if (NOT PSP_EXECUTABLE_OUTPUT_NAME) set(PSP_EXECUTABLE_OUTPUT_NAME ${nm}) endif(NOT PSP_EXECUTABLE_OUTPUT_NAME) set_target_properties( ${nm} PROPERTIES LINK_FLAGS "-specs=${PSPSDK_PATH}/lib/prxspecs -Wl,-q,-T${PSPSDK_PATH}/lib/linkfile.prx ${PSPSDK_PATH}/lib/prxexports.o" ) add_custom_command( TARGET ${nm} POST_BUILD COMMAND psp-fixup-imports ${PSP_EXECUTABLE_OUTPUT_NAME} COMMAND mksfo '${PSP_EXECUTABLE_OUTPUT_NAME}' PARAM.SFO COMMAND psp-prxgen ${PSP_EXECUTABLE_OUTPUT_NAME} ${PSP_EXECUTABLE_OUTPUT_NAME}.prx COMMAND pack-pbp EBOOT.PBP PARAM.SFO NULL NULL NULL NULL NULL ${PSP_EXECUTABLE_OUTPUT_NAME}.prx NULL ) endfunction() set(PSP 1) allegro4.4-4.4.2/demos/000077500000000000000000000000001173507505700145155ustar00rootroot00000000000000allegro4.4-4.4.2/demos/shooter/000077500000000000000000000000001173507505700162005ustar00rootroot00000000000000allegro4.4-4.4.2/demos/shooter/CMakeLists.txt000066400000000000000000000006221173507505700207400ustar00rootroot00000000000000include_directories(${CMAKE_CURRENT_SOURCE_DIR}) # for shooter.ico add_our_executable(shooter WIN32 animsel.c bullet.c dirty.c expl.c star.c aster.c demo.c display.c game.c title.c shooter.rc ) copy_files(copy_shooter_data demo.dat ) #-----------------------------------------------------------------------------# # vim: set sts=4 sw=4 et: allegro4.4-4.4.2/demos/shooter/animsel.c000066400000000000000000000071571173507505700200060ustar00rootroot00000000000000#include "animsel.h" /* d_list_proc() callback for the animation mode dialog */ static char *anim_list_getter(int index, int *list_size) { static char *s[] = { "Double buffered", "Page flipping", "Triple buffered", "Dirty rectangles" }; if (index < 0) { *list_size = sizeof(s) / sizeof(s[0]); return NULL; } return s[index]; } static int anim_list_proc(int msg, DIALOG * d, int c); static int anim_desc_proc(int msg, DIALOG * d, int c); static DIALOG anim_type_dlg[] = { /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) (dp2) (dp3) */ {d_shadow_box_proc, 0, 0, 281, 151, 0, 1, 0, 0, 0, 0, NULL, NULL, NULL}, {d_ctext_proc, 140, 8, 1, 1, 0, 1, 0, 0, 0, 0, "Animation Method", NULL, NULL}, {anim_list_proc, 16, 28, 153, 36, 0, 1, 0, D_EXIT, 3, 0, anim_list_getter, NULL, NULL}, {d_check_proc, 16, 70, 248, 12, 0, 0, 0, 0, 0, 0, "Maximum FPS (uses 100% CPU)", NULL, NULL}, {anim_desc_proc, 16, 90, 248, 48, 0, 1, 0, 0, 0, 0, 0, NULL, NULL}, {d_button_proc, 184, 28, 80, 16, 0, 1, 0, D_EXIT, 0, 0, "OK", NULL, NULL}, {d_button_proc, 184, 50, 80, 16, 0, 1, 27, D_EXIT, 0, 0, "Cancel", NULL, NULL}, {d_yield_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL}, {NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL} }; static int anim_list_proc(int msg, DIALOG * d, int c) { int sel, ret; sel = d->d1; ret = d_list_proc(msg, d, c); if (sel != d->d1) ret |= D_REDRAW; return ret; } /* dialog procedure for the animation type dialog */ static int anim_desc_proc(int msg, DIALOG * d, int c) { static char *double_buffer_desc[] = { "Draws onto a memory bitmap,", "and then uses a brute-force", "blit to copy the entire", "image across to the screen.", NULL }; static char *page_flip_desc[] = { "Uses two pages of video", "memory, and flips back and", "forth between them. It will", "only work if there is enough", "video memory to set up dual", "pages.", NULL }; static char *triple_buffer_desc[] = { "Uses three pages of video", "memory, to avoid wasting time", "waiting for retraces. Only", "some drivers and hardware", "support this.", NULL }; static char *dirty_rectangle_desc[] = { "This is similar to double", "buffering, but stores a list", "of which parts of the screen", "have changed, to minimise the", "amount of drawing that needs", "to be done.", NULL }; static char **descs[] = { double_buffer_desc, page_flip_desc, triple_buffer_desc, dirty_rectangle_desc }; char **p; int y; if (msg == MSG_DRAW) { rectfill(screen, d->x, d->y, d->x + d->w, d->y + d->h, d->bg); p = descs[anim_type_dlg[2].d1]; y = d->y; while (*p) { textout_ex(screen, font, *p, d->x, y, d->fg, d->bg); y += 8; p++; } } return D_O_K; } /* allows the user to choose an animation type */ int pick_animation_type(ANIMATION_TYPE *type) { int ret; centre_dialog(anim_type_dlg); clear_bitmap(screen); /* we set up colors to match screen color depth */ for (ret = 0; anim_type_dlg[ret].proc; ret++) { anim_type_dlg[ret].fg = palette_color[0]; anim_type_dlg[ret].bg = palette_color[1]; } ret = do_dialog(anim_type_dlg, 2); *type = anim_type_dlg[2].d1 + 1; max_fps = anim_type_dlg[3].flags & D_SELECTED; ASSERT(*type >= DOUBLE_BUFFER && *type <= DIRTY_RECTANGLE); return (ret == 6) ? -1 : ret; } allegro4.4-4.4.2/demos/shooter/animsel.h000066400000000000000000000002261173507505700200010ustar00rootroot00000000000000#ifndef ANIMSEL_H_INCLUDED #define ANIMSEL_H_INCLUDED #include "demo.h" #include "display.h" int pick_animation_type(ANIMATION_TYPE *type); #endif allegro4.4-4.4.2/demos/shooter/aster.c000066400000000000000000000103121173507505700174570ustar00rootroot00000000000000#include "aster.h" #include "expl.h" #include "data.h" #include "display.h" #include "dirty.h" #include "game.h" /* info about the asteroids (they used to be asteroids at least, * even if the current graphics look more like asteroids :-) */ #define MAX_ASTEROIDS 50 volatile struct { int x, y; int d; int state; int shot; } asteroid[MAX_ASTEROIDS]; static int asteroid_count; void init_asteroids(void) { int c; for (c = 0; c < MAX_ASTEROIDS; c++) { asteroid[c].x = 16 + AL_RAND() % (SCREEN_W - 32); asteroid[c].y = -60 - (AL_RAND() & 0x3f); asteroid[c].d = (AL_RAND() & 1) ? 1 : -1; asteroid[c].state = -1; asteroid[c].shot = FALSE; } asteroid_count = 2; } void scroll_asteroids(void) { int c; for (c = 0; c < asteroid_count; c++) asteroid[c].y++; } void add_asteroid(void) { if (asteroid_count < MAX_ASTEROIDS) asteroid_count++; } void move_asteroids(void) { int c; for (c = 0; c < asteroid_count; c++) { if (asteroid[c].shot) { /* dying asteroid */ if (skip_count <= 0) { if (asteroid[c].state < EXPLODE_FLAG + EXPLODE_FRAMES - 1) { asteroid[c].state++; if (asteroid[c].state & 1) asteroid[c].x += asteroid[c].d; } else { asteroid[c].x = 16 + AL_RAND() % (SCREEN_W - 32); asteroid[c].y = -60 - (AL_RAND() & 0x3f); asteroid[c].d = (AL_RAND() & 1) ? 1 : -1; asteroid[c].shot = FALSE; asteroid[c].state = -1; } } } else { /* move asteroid sideways */ asteroid[c].x += asteroid[c].d; if (asteroid[c].x < -60) asteroid[c].x = SCREEN_W; else if (asteroid[c].x > SCREEN_W + 60) asteroid[c].x = -60; } /* move asteroid vertically */ asteroid[c].y += 1; if (asteroid[c].y > SCREEN_H + 30) { if (!asteroid[c].shot) { asteroid[c].x = AL_RAND() % (SCREEN_W - 32); asteroid[c].y = -32 - (AL_RAND() & 0x3f); asteroid[c].d = (AL_RAND() & 1) ? 1 : -1; } } else { /* asteroid collided with player? */ if ((ABS(asteroid[c].x - (player_x_pos >> SPEED_SHIFT)) < 48) && (ABS(asteroid[c].y - (SCREEN_H - 42)) < 32)) { if ((!player_hit) && (!asteroid[c].shot)) { if (!cheat) { ship_state = EXPLODE_FLAG; player_hit = TRUE; } if ((!cheat) || (!asteroid[c].shot)) play_sample(data[DEATH_SPL].dat, 255, PAN(player_x_pos >> SPEED_SHIFT), 1000, FALSE); } if (!asteroid[c].shot) { asteroid[c].shot = TRUE; asteroid[c].state = EXPLODE_FLAG; } } } } } int asteroid_collision(int x, int y, int s) { int i; for (i = 0; i < asteroid_count; i++) { if ((ABS(y - asteroid[i].y) < s) && (ABS(x - asteroid[i].x) < s) && (!asteroid[i].shot)) { asteroid[i].shot = TRUE; asteroid[i].state = EXPLODE_FLAG; return 1; } } return 0; } void draw_asteroids(BITMAP *bmp) { int i, j, c, x, y; RLE_SPRITE *spr; for (c = 0; c < asteroid_count; c++) { x = asteroid[c].x; y = asteroid[c].y; if (asteroid[c].state >= EXPLODE_FLAG) { spr = explosion[asteroid[c].state - EXPLODE_FLAG]; } else { switch (c % 3) { case 0: i = ASTA01; break; case 1: i = ASTB01; break; case 2: i = ASTC01; break; default: i = 0; break; } j = (retrace_count / (6 - (c & 3)) + c) % 15; if (c & 1) spr = (RLE_SPRITE *) data[i + 14 - j].dat; else spr = (RLE_SPRITE *) data[i + j].dat; } draw_rle_sprite(bmp, spr, x - spr->w / 2, y - spr->h / 2); if (animation_type == DIRTY_RECTANGLE) dirty_rectangle(x - spr->h / 2, y - spr->h / 2, spr->w, spr->h); } } allegro4.4-4.4.2/demos/shooter/aster.h000066400000000000000000000004111173507505700174630ustar00rootroot00000000000000#ifndef ASTER_H_INCLUDED #define ASTER_H_INCLUDED #include "demo.h" void init_asteroids(void); void add_asteroid(void); void move_asteroids(void); void scroll_asteroids(void); void draw_asteroids(BITMAP *bmp); int asteroid_collision(int x, int y, int s); #endif allegro4.4-4.4.2/demos/shooter/bullet.c000066400000000000000000000041731173507505700176400ustar00rootroot00000000000000#include "bullet.h" #include "data.h" #include "display.h" #include "dirty.h" #include "aster.h" #include "game.h" /* position of the bullets */ #define BULLET_SPEED 6 BULLET *bullet_list; /* add a bullet to the list */ BULLET *add_bullet(int x, int y) { BULLET *iter, *bullet; bullet = (BULLET *) malloc(sizeof(BULLET)); bullet->x = x; bullet->y = y; bullet->next = NULL; /* special treatment for head */ if (!bullet_list) { bullet_list = bullet; } else { for (iter = bullet_list; iter->next; iter = iter->next) ; iter->next = bullet; } return bullet; } /* delete a bullet and return the next in the list */ BULLET *delete_bullet(BULLET * bullet) { BULLET *iter; /* special treatment for head */ if (bullet == bullet_list) { bullet_list = bullet->next; free(bullet); return bullet_list; } else { for (iter = bullet_list; iter->next != bullet; iter = iter->next) ; iter->next = bullet->next; free(bullet); return iter->next; } } void move_bullets(void) { BULLET *bullet = bullet_list; while (bullet) { bullet->y -= BULLET_SPEED; /* if the bullet is at the top of the screen, delete it */ if (bullet->y < 8) { bullet = delete_bullet(bullet); goto bullet_updated; } else { /* shot an asteroid? */ if (asteroid_collision(bullet->x, bullet->y, 20)) { score += 10; play_sample(data[BOOM_SPL].dat, 255, PAN(bullet->x), 1000, FALSE); /* delete the bullet that killed the alien */ bullet = delete_bullet(bullet); goto bullet_updated; } } bullet = bullet->next; bullet_updated:; } } void draw_bullets(BITMAP *bmp) { BULLET *bullet; for (bullet = bullet_list; bullet; bullet = bullet->next) { int x = bullet->x; int y = bullet->y; RLE_SPRITE *spr = data[ROCKET].dat; draw_rle_sprite(bmp, spr, x - spr->w / 2, y - spr->h / 2); if (animation_type == DIRTY_RECTANGLE) dirty_rectangle(x - spr->w / 2, y - spr->h / 2, spr->w, spr->h); } } allegro4.4-4.4.2/demos/shooter/bullet.h000066400000000000000000000004771173507505700176500ustar00rootroot00000000000000#ifndef BULLET_H_INCLUDED #define BULLET_H_INCLUDED #include "demo.h" typedef struct BULLET { int x; int y; struct BULLET *next; } BULLET; extern BULLET *bullet_list; BULLET *add_bullet(int x, int y); BULLET *delete_bullet(BULLET * bullet); void draw_bullets(BITMAP *bmp); void move_bullets(void); #endif allegro4.4-4.4.2/demos/shooter/data.h000066400000000000000000000112421173507505700172620ustar00rootroot00000000000000/* Allegro datafile object indexes, produced by grabber v3.11 */ /* Datafile: e:\allegro\demo\demo.dat */ /* Date: Fri Apr 9 15:55:51 1999 */ /* Do not hand edit! */ #define ASTA01 0 /* RLE */ #define ASTA02 1 /* RLE */ #define ASTA03 2 /* RLE */ #define ASTA04 3 /* RLE */ #define ASTA05 4 /* RLE */ #define ASTA06 5 /* RLE */ #define ASTA07 6 /* RLE */ #define ASTA08 7 /* RLE */ #define ASTA09 8 /* RLE */ #define ASTA10 9 /* RLE */ #define ASTA11 10 /* RLE */ #define ASTA12 11 /* RLE */ #define ASTA13 12 /* RLE */ #define ASTA14 13 /* RLE */ #define ASTA15 14 /* RLE */ #define ASTB01 15 /* RLE */ #define ASTB02 16 /* RLE */ #define ASTB03 17 /* RLE */ #define ASTB04 18 /* RLE */ #define ASTB05 19 /* RLE */ #define ASTB06 20 /* RLE */ #define ASTB07 21 /* RLE */ #define ASTB08 22 /* RLE */ #define ASTB09 23 /* RLE */ #define ASTB10 24 /* RLE */ #define ASTB11 25 /* RLE */ #define ASTB12 26 /* RLE */ #define ASTB13 27 /* RLE */ #define ASTB14 28 /* RLE */ #define ASTB15 29 /* RLE */ #define ASTC01 30 /* RLE */ #define ASTC02 31 /* RLE */ #define ASTC03 32 /* RLE */ #define ASTC04 33 /* RLE */ #define ASTC05 34 /* RLE */ #define ASTC06 35 /* RLE */ #define ASTC07 36 /* RLE */ #define ASTC08 37 /* RLE */ #define ASTC09 38 /* RLE */ #define ASTC10 39 /* RLE */ #define ASTC11 40 /* RLE */ #define ASTC12 41 /* RLE */ #define ASTC13 42 /* RLE */ #define ASTC14 43 /* RLE */ #define ASTC15 44 /* RLE */ #define BOOM_SPL 45 /* SAMP */ #define DEATH_SPL 46 /* SAMP */ #define END_FONT 47 /* FONT */ #define ENGINE1 48 /* RLE */ #define ENGINE2 49 /* RLE */ #define ENGINE3 50 /* RLE */ #define ENGINE4 51 /* RLE */ #define ENGINE5 52 /* RLE */ #define ENGINE6 53 /* RLE */ #define ENGINE7 54 /* RLE */ #define ENGINE_SPL 55 /* SAMP */ #define GAME_MUSIC 56 /* MIDI */ #define GAME_PAL 57 /* PAL */ #define GO_BMP 58 /* BMP */ #define INTRO_ANIM 59 /* FLIC */ #define INTRO_BMP_1 60 /* BMP */ #define INTRO_BMP_2 61 /* BMP */ #define INTRO_BMP_3 62 /* BMP */ #define INTRO_BMP_4 63 /* BMP */ #define INTRO_MUSIC 64 /* MIDI */ #define INTRO_SPL 65 /* SAMP */ #define ROCKET 66 /* RLE */ #define SHIP1 67 /* RLE */ #define SHIP2 68 /* RLE */ #define SHIP3 69 /* RLE */ #define SHIP4 70 /* RLE */ #define SHIP5 71 /* RLE */ #define SHOOT_SPL 72 /* SAMP */ #define TITLE_BMP 73 /* BMP */ #define TITLE_FONT 74 /* FONT */ #define TITLE_MUSIC 75 /* MIDI */ #define TITLE_PAL 76 /* PAL */ #define WELCOME_SPL 77 /* SAMP */ allegro4.4-4.4.2/demos/shooter/demo.c000066400000000000000000000066521173507505700173010ustar00rootroot00000000000000#include "demo.h" #include "data.h" #include "expl.h" #include "animsel.h" #include "display.h" #include "title.h" #include "game.h" /* command line options */ int cheat = FALSE; int jumpstart = FALSE; /* our graphics, samples, etc. */ DATAFILE *data; int max_fps = FALSE; /* modifies the palette to give us nice colors for the GUI dialogs */ static void set_gui_colors(void) { static RGB black = { 0, 0, 0, 0 }; static RGB grey = { 48, 48, 48, 0 }; static RGB white = { 63, 63, 63, 0 }; set_color(0, &black); set_color(16, &black); set_color(1, &grey); set_color(255, &white); gui_fg_color = palette_color[0]; gui_bg_color = palette_color[1]; } static void intro_screen(void) { BITMAP *bmp; play_sample(data[INTRO_SPL].dat, 255, 128, 1000, FALSE); bmp = create_sub_bitmap(screen, SCREEN_W / 2 - 160, SCREEN_H / 2 - 100, 320, 200); play_memory_fli(data[INTRO_ANIM].dat, bmp, FALSE, NULL); destroy_bitmap(bmp); rest(1000); fade_out(1); } int main(int argc, char *argv[]) { int c, w, h; char buf[256], buf2[256]; ANIMATION_TYPE type; for (c = 1; c < argc; c++) { if (stricmp(argv[c], "-cheat") == 0) cheat = TRUE; if (stricmp(argv[c], "-jumpstart") == 0) jumpstart = TRUE; } /* The fonts we are using don't contain the full latin1 charset (not to * mention Unicode), so in order to display correctly author names in * the credits with 8-bit characters, we will convert them down to 7 * bits with a custom mapping table. Fortunately, Allegro comes with a * default custom mapping table which reduces Latin-1 and Extended-A * characters to 7 bits. We don't even need to call set_ucodepage()! */ set_uformat(U_ASCII_CP); srand(time(NULL)); if (allegro_init() != 0) return 1; install_keyboard(); install_timer(); install_mouse(); if (install_sound(DIGI_AUTODETECT, MIDI_AUTODETECT, NULL) != 0) { allegro_message("Error initialising sound\n%s\n", allegro_error); install_sound(DIGI_NONE, MIDI_NONE, NULL); } if (install_joystick(JOY_TYPE_AUTODETECT) != 0) { allegro_message("Error initialising joystick\n%s\n", allegro_error); install_joystick(JOY_TYPE_NONE); } if (set_gfx_mode(GFX_AUTODETECT, 320, 200, 0, 0) != 0) { if (set_gfx_mode(GFX_SAFE, 320, 200, 0, 0) != 0) { set_gfx_mode(GFX_TEXT, 0, 0, 0, 0); allegro_message("Unable to set any graphic mode\n%s\n", allegro_error); return 1; } } get_executable_name(buf, sizeof(buf)); replace_filename(buf2, buf, "demo.dat", sizeof(buf2)); set_color_conversion(COLORCONV_NONE); data = load_datafile(buf2); if (!data) { set_gfx_mode(GFX_TEXT, 0, 0, 0, 0); allegro_message("Error loading %s\n", buf2); exit(1); } if (!jumpstart) { intro_screen(); } clear_bitmap(screen); set_gui_colors(); set_mouse_sprite(NULL); if (!gfx_mode_select(&c, &w, &h)) exit(1); if (pick_animation_type(&type) < 0) exit(1); init_display(c, w, h, type); generate_explosions(); //stop_sample(data[INTRO_SPL].dat); clear_bitmap(screen); while (title_screen()) play_game(); destroy_display(); destroy_explosions(); stop_midi(); set_gfx_mode(GFX_TEXT, 0, 0, 0, 0); end_title(); unload_datafile(data); allegro_exit(); return 0; } END_OF_MAIN() allegro4.4-4.4.2/demos/shooter/demo.dat000066400000000000000000014056741173507505700176370ustar00rootroot00000000000000slh!ïALL.ëðOpr¿opNAMEëðÿASTA01RL¿E Ø û<ÎÄü(ë „=7§ëÿò5TT¬3ý˜ T>KXXIÿAíó:ggŸgt[7KMk¡ï#EEHÌEjÿffa?[\7>ül´KE8qîþíQt´a°a?ÿ„K5[>´[÷´ggTƒKGýv <>taggÿfat\57K7ß59gff"TT÷¡KŽ »9°ßgTTTgæ5K¿=„´jj9bgÿTgj´XAïöPA?˜TgtKïo=taj9¡ÿ¡9>„>=lŸïò=TSa¿[[?aafk9ÿ¡„=[[=\7?-ðòKš/PTfaWT7ŒÿV=K\\XGŽÿñó A9füWº gj9>K\7558IØO»>[°Æü òÿ=7XXGlQñζX7`háTjÿ9?[KK\5XïElE+ !cGoç¬jf$Wƒ9¡ï>=\5= +G7~B ñŽ:otUîXjto: 73Kÿ5:+llXXVÿEñð»Em½tßTg°¬~ 8ÿ+’+E++lGýE÷cñï<»#?UgTfÆ+ÿ8++:+8lGÿXX\´Eðîÿ§¬affƒj¯ja[#a EÚ"7ß\E„„qÈ q¿7´°gfXï+EX7 5\VÿE#>8ïíÿI[?f°°´3ÿX+X5775XÿX7V5Q#¬Xþ0AX¬¬KKï7+¼X0XX:ÿXK7Q’```ÿcðìŽ\=ßE+H¼E XXüÞ  5?¬3vðßëcXD0:55E::’§+b0ÿXmtVŽïêÿclQQG7XýE ++57X3ÿ?3»îéQ¿+8G57#ƒ0XÿXo77m7qíÿéqE5KKÿ[KooX#3¬ÿmE§Aìç ÿA»c§Q7VxÿVK+HéâAlG<[(Ú7öþ%2öBìÚ?CÿæAßê vÿQ5>gg7QÿAäíŽX9þèg=IŽæð¯q+>iƒ69ÿ9RGçñ•úúgc@tfTgK«8Au5kfNtû¬?"g>#-ßêñ>šTR??TPTtt˜ßgPTa\´0òùvYÉ?[?TT¹ƒŒBN9>8¹@ùInBa?`V9üái?\XŽíòXR$t¨¨@k¿gg97EQ òû3¾ƒ?tV3|æDÑf[E8IOóc°¾Éf?K=øz@©@Ñgƒ=+¥žq0óŽjP$Yaž9 V>9aiQP?75X•qq?Y{þ•@gt=KV\EïE=„f_@R=X>WRq[t`R±"IA¿?KKK559¿Ra9\QqÿA7\3tg°ÔDW>®=ÑP„„z!޵E7K[TýfËCgR`>>=ÿ3\KV=VK÷K¥A !ŽX7Kó?9ÉQxƒ>V=·==\a7E¨ ñ?I1#xtIQáß9[[3öXGߥ¥§Aò(`AQ5x¬R1f©@<`>÷51lh`còðŽ13¬tƒXÎ#°>V> ++ÿG¥òïl#ç??pQg9„ýK 1G¥GGE÷7Žó`Ž5>RûaÑTfjfëaR¤a1©`¥11ÿX7Aóî+Ÿ[a°°RÉPóP#ûX7•òíÿlRaf°Rj»a?¥`++1,0+ÿX\K=\\ñþpqa3x`>ß`7¥++÷ ooþ”0=„>K=qñö=0¥3/1’’+Xÿo=[mxKo\¿KK5K»<0ÿŽXE§-§E5Ýowr7KVÕ xGþpëQ8§:5÷ox#“0X73mÿK1E:-íëÿŽ¥17VmKÿ7##X5m35ÿX#mŽìêÿŽQX[`3KKÿ#5mx55mmÿcëç I¥:ÿ##K31:X:ÿQqêävQ£»ãOá?ý÷3É‚ûî0…çÿAާX1+§c¿åíq[»fÿKQAèîIì˜ Ã¡X€@ðAmG¹ a``7§y8ŒB´37X{0EA­E{U!]Pÿ´[51XE\3õH­7çƒat9ë?ƒP+ÿ ´EHæËòVFó>``ÿ?ff7EK`j¯´X5§ìq˜fÿj>`V[[jg¿77?aTaŽ€HÎ §fƒe‹€3Vß„9f=`Vjj÷ƒjGO+t9føºËã@„9>´>ý>{@ƒ9?¡7q¾XRK`99>ý€ÿ?>t¡>9t[ï?„`tQPVKV»7<“E3>`V¿>´a9`?d?ÿ[VV`Vƒgjö¨p1-‘H7o[g„=>£9t£^_9ƒ¡Kø I‘ûŽ7•‘x„?[xÿ´t?¡9`VKï\K[Vb`75Hþ“qKK>KK3ÿV``xt´?´ûga‹‘7\=K7ÿ\7:AðñÿKK`33o3K`„tf´jgÐPKXl+15\à m< 1ëVoÛ÷t9a5Tƒ[K÷\:+à 571QÞ`ñHVx3+[>„9”A9„`,0ß771El×ñ¿qXK=``sa{a?h¢fj3#¨`¿1XG+l§ˆ »XK[>V?C Ç?9ƒ³@!P{0+G¿1+l+Eq`ÿ<7`9`[>9÷?9tï gaa9w35E¸¡:E5l`ÿïcX„a>>¾Üttƒgò`WK7Eº Gä`<¾¡qE„f?ƒ„¢ ÿ´´>tƒfa[û71š G17=[ÝIóaHVgÌ3=¿[t´[3`[ 1þ» G15=>¡QÞóaA79?¨0V„?[[V75G>!%pß7\[¡¡l`í³lK100X1C`¼œ#pZ°\=[‹½ íÿH1QI¼-Iß’+::+õ 53ÿK\V`¡9¡j11qާÎ`0BpVÿ`[xx``=9߃j´g5`ëÍQ¼px3¨px x[×[`>i¡½Pë¿AcEX3Kx Kþß°3o7tjEþ‰0èA-§8Ž÷<’+ú°¼HHŽ£»ì/óûù4„ Ì9ÂÏSÅíûAIGAÞî ý1w¡7§Žý?AŽçﳄ6d¿[#99Ivx€ù‰b ^`RR[G»ë@Aj¼XioR?V5´pñ}ˆø!º`Wf9[#+Ë»íÓÀ3˜ãÀÔoPn?°lðÀK|]R¿fRR>?oQs#+h° ñ##Þ#f?`¥¡a¿t1G5#XNñ¿7`?aQ#ƒû>x¯PV„t>Xß+#5G§Pqÿ>x[`agagÝôxK#¨°3`½ú +51v“HÛjx3R=ß°`Výo15K[#1ß+17Glå òÿ+gR?gjatî'0K=5•17[>Û>V1G+;0ò遼gRPt##÷o7or¡K=R>_>>:\V±PHµw•Rg& ?x50ö.0\oK°?¡„+ó73]!Npò»[nggtx q11¨°ÿ#=[>„\+1ëo76°vf!K¡R¿ƒƒ9x1Xî`1ïo55K•‘7G:ó75Ÿ 7â\>9j~Ò¡X1EXXK<~ KXE:7X• îy¢K„¡·Ð351Ú¿Ð7‘p3tÿP5E¿E1::15×òÿA5„aat2ýÑ\Ímàa>Ò€ o8E15Npñ¡ ½R7 75#\kà#V>aÌX» V±¡ÔåPx@`¨€#”0K[ût¡¤a§1:G:»X16¡»+K‡„úàÑ5|p[¡xV½56±:+77Npï×5`'¢:’0#=ûV>ú7+§+Gú ð3¨!•„ƒR÷¡K3½àoK=Vÿ33\#58+Eß11:7„ ïv=K5o57hà¶ \=qál:î`X÷K9‰eòGl§8ù’}0<X#KKE}l:°5\\¡¡`ÿîŽXX8¼’é’pÆ€E` X#\Þ—ð[g\ð 0»lä”0÷5¸ » 13>¿[>gP;0땼+vr{00RûjRgPVïçÿ-E7oKxxïK[aƒ("¡cïåqc81PÐþ—Tƒ5cíáÿA‰§7[G•P®€SÏÏ+Æ5þ4üb² Eò:zèopqßàêcŒA°X¿<âë +¾Ä9?Gqäìú@ŒÅÿm+»»<§Žêçí†Êû`°98ŸêîŽ"nFt;?XÚEgTѼÆöÂt>ÐÁïq?»°Rf‡gj°Û€t÷m3+PðqVït9ƒ¼Ä°ƒj¿¬>?`mmíÐ:þq0ð#TR¬¬ýtd??>¬?„÷V3KªpE’ïwñc>?¡ËCÿa``m>>m=¶á±7Xf7íRù°åÁÂ9¬m3Kß=K#K=BX+æàQ»OQÊRgttçt¬V§€Íð53ß>3E7I®ÑGPd{@¨SmÌà ::Û #V#X?•®ÑÙ=aRHA?c0EEÿ+§88:X7=ïm53?ñÐóHyjÕ¢A¬3:ê`øº!  Em#-ðô q>¡gõðþÌQfKE8§8¼ã§:œ h0(0\5+~1!»>jajÌQ?TR58Q§º!g0¯EK==R°X;0óß §V¡?^"¬gX¼¼½ ¾ 8E ¿KK+GG:â+û=t_"aK:Q§ü±ú°X\m>m3yGØ dðòIKv`ÿTm5’¼§ÿ’888+’EXÖnáE5õ Iá‰=þ½`gaRKX¼§É8p" 5vð#`7G·X=z@ƒtK+¼88’ M8È€#7Þ °p¡Àâï§3RR¡`5+QÞ18§GXÀp57¿’E573¡»ÿ5¡jfR5E¨90X0ÉÐ\–18 9?§ððIžÑP¶ 8§(ÐEEé`’ö `>„ ðAIÇ:+Qñ0˜ X:õ+U0G  ¡:ïÿïq-G§H8¡¼ >ðްõ G*qNmìIþ G°þú°G5K\3K3Xî×°Ž’Ûx1‚0üúQ`•îé»ï+#KEí0+7Vÿ¡¡>„¡„„A¿îçŽEìò=ýj¶Ðja>Eí?å <#K#­@ÄÀûm•¸@ä Ž#¬ßK+QIIÙqã£qqâB+Æ6^ëd|B…áTO–EäX•åå8T‘ÿtHæç A3ú†„’`€ìc+Aïÿ »9=S9=ÝEw€ívà[Ü(R(P´K p’ìÂóvºÂf‘õ=7Û#+ q2gó°9;RºTg`K5ê€ðqºÁ9?ó?´ÀÃáÁj?KQúÑAÓBg?[``Í´àgaõð7QòkÑŽÓAÆÀƒt>>ý?dt??„„[Ë3#½RH’­ja°“g´=œ1i0‡ô"v’pSÇÁÕ‚jg?75ÌñŸÐ:-I`Çô"qsÐUÓUdTg§´>KDàà1Ž EŽòó!H>3И­[b˜?[rápðXî# 8E»úQ•>´$½T¿Ã>Íð÷ ’~0m W+1‰úQX:PêD6§=E`+1@õ < pó!§?ßbT`71’’:œñÚWp8ÿ1HúQ8`¾àTt5’’~ñ7â}Ð1?p(pÓPó HóK9éC§58’XºÛ#Ű5:8"0+~0óAX`°è@fVõ1ÉÑ7Ÿ35+:Ý5ï`XEai2»’­:ð1QâÐ# q5³+1îàÎ\[ ï‰:8H8Q!ðæ¨±#X}ðX°1EKÿa+ïîŽ+HH§5R ÌQ6±+îóP\j9‹Ðíc±’ƒ0á–p5G¼11÷7„gù0ì‰:ÂÛ1W°¨€ü6p=aßGíë  KEðepJà9ð›´3ì7ê»HÐXGJà @s[>EpÀé<à|là­ƒ´a´´Ë€Çè§ãÐÜðÅÂg+ÿêç AvŽ<Hz0Û §é•O[O*Ç%7^é…‚kß]‚ÿAÝéŽRÿ3»þAþqÿ<’‰è뻾±fXx?3-@P÷X:´ÀíqXüàÖa:ëðçA-7à ¬Á`7Pà¼KÐòû-àƒa°T°s¡`Õà`E§-1‘ý»a9[x[^ý?¡VKSpc1‘{‰9ÔgRR9ʰk=oèÐ>ë=5iRwGƒ?2j¡¡M°~û?R9¡=[pịQ»?Š êBjÞèÐ33VàRV¿=VKK\+ óŸQ?a±&aßaR?>?aRvXð\7ðÑó Gù°aP ƒgfR¡Rrgƒàà:»×` §xÐßS—P»9RÒf9=pG÷1G+â ó!<3¹9sįjjf¿afg¡[#— ó!§-úPß"Ž7?ƒ¿aTgñfäS¡ÐV#X+¹:jÀù°EŽóf AïXxRßafg|w¢1`K5X’Gªaþ±cóò!§o‘tâÀÅÀ´T`˜ðÓ #·KXGxà7\Š ò!‰EVÞa“ Þ¡aßo1’§Gîð[Þ$à5#=`Õ¡ AßHG[°“ g°ófRA ¹ðK3KV÷t¡VñáKòÿñ»§:K?9K9>pá§Qðà?”Ðû„=ëð53Gò¯ð-Q;0\Ëð:ûE#qÐ9RaƒjÓR[_0 #`ð¹»h ``+1\3±Rãaf*‘„`˜0+7qýòFð¼’8¼8:ë7 à?>à?7Gòù²G¸ðâ ïAHþg #„>„>>¡§a9Vê0ð1Ø0+ü­ÐŸp¼+o>„Ví[’±=X„ G1EßG8XRApAù8@_Ð>¡??KÚ~°§ !1¡à0íù- Žà>tRR=~ìð:E7[+HïÀ÷ìŽÆ`5V>fþÅP[3\KR1êê<5[#ÑþP afRX-éÿé A¼7ŽI5ÿjPg[+qç?ãAcAä dJS8^èŒÂkÞdÏΪÉê A>ð:05ŽÿãîŽ--§ý9é„t-8‰æ÷î#™tm?7}H¾€ëïŽýBü–t°R?`¬¼ìf/PŽ[ß `°°}R!ñŽ?ƒbì•gâTaXGòA?oaTPƒ[5ÙÍûjK§§??TPã9„õsT°t}Këó qoxÞ`øÚQ, ‘9V=#Kÿ?°ƒ9¬¬VKû7l¤ðó ‰33Ï?ag¢à=\§\#Xçð§p7Ïð:~Dðó Žo3`/ ;aRôñg9=Ìà¾X111G8§¾!Þ’Ð7x[R&QR>†wP>[Šqp0pð]¡GöûÔ33âgatå[wð=Í`¤a5El<ðûÒ~„0’ â’)°oàœ¯á°K5lcà?¢~^¹ðR°aÈà?²°ÏK\7°éà7ß8ll++…°ó!ߎQ+X[–±?„ù`ô0ÐK9ƒg?jtVXl§ì ha"c:X+5?½Ðs??1à_àK>Rãu>`8 EXA‹¡ýŽœ0Xotƒ°Û?„è9tÂуtb°lÏpðÕ¢Ž5µðïK?ƒRY[?a?°ƒ°ƒa?Z {0?=77\§þãÞîM VK=WP„?„í[Ý1E¢0>Kê~àE±¡~ð+¼§>¼ 17#o7< Ñàî¿07tt[t-•ó °§¶ðIRð± :þep77o3V=Kÿ3ag¬=V„t}=±Ž+EEHåñÿK>9RRaaÿjƒƒ°aaga¿„[tjg\B±Ž’+’5x¬9¤ðþ­9„„>?„½[‹tgt~†±Ž.¢0`tR2ÑR8ð» ü¨p¾7=tŽñ?îŽ:7KÙPÐ]\³pl§lö lÑ`ÿ„lðíŽK¥¬¥ã\¾°C lVð\÷\\7ÔìcXÿ~§Ktj9>VüªPÝ5=~ìÿçAŽŽccIÿ\>lŽI:7ŽQë©ÏgÏiK9xDâ’ò…EØj° éqH¿1V´\IAÇÀßqQG#¡aTTÿj3QAåïãqm“¢9q f>7ÿ8»èðAVÜ—¡Óff²ƒKÿ+»êð§g0Nà(a'¢V7XMP_mRR°fLaf±Ú{Sm€ð¼Ž@ñHR¬`?9°×€ƒ=>S '¢ðKÑ¿A#93mR‘fk=7¹`TÀñ9K.pïom`5LÑ5Rm½Kаƒ?mRÐTÿ´¡´9m=K?\\Km¬¬É’Ðï9xomO„9?þYg´=¡R´­9Ú Vm¥àmôðôÿ"A5#5o¬?ÿ`m?´?mmVö|à\@¡>¡¡í´8€j7ùPô#IûV+~àxx„fgß?`==mõ13>nYàaaÂAmXŠ ÿô#H7¬9x#_Km9gfœàKq ÿ=\XEGlG+ÿK?TTf935ülð 9a9KXoñ` °Å ¨`7\\1þ90Q+15Km=zª`Q!8>>3úà¯`°a?'7_01›1:1+l Iö!IxÌao39R „6à 5}0÷°¬à½1d7pD"Žìa[ଡz ˆîP£`‚ +`¡Sðûpmê"Aópx€ñm?m4]°`ðG §+€0‰àõ\ »‹¡-#oxÿoo37\V`\–òPE:® l@@+õ+p„×á!AE#3ï`í¡6â¨!Ò |à5EG=KVVòü }Ž›ð#5’¼8‰àôgp-p\U"XElXê ±I1¼¼+á1<ðÄqWðýpX:lß:Km9v2AQý8epE53=\+å’ª0+m°Î11m¡Ïjƒ´>³òö ?afjSà`V¯ÐòÑ|ðÝ>2Ѓfm†°Iò`K-!¦=m?9??„3#\„s / Î²ðêŽjp8à11ßX\>>9U°aƒ<6À±aèAE0 @þÈP7Km>aPKýcÔçA+7:íX¡àmKép?a<ÿíã AcXaþõàX>¡ŽìàaÞ°pu‡10„ÉÍ’BŽ…ÃjO°ÊCÿ’§cAßë û»„rRR9K5{ŽæàA§7m8€ùRQ&Q>¥vèßñA+R“fRüLb „7céò±nRÃPMàfR:>ûm„ð 8CëóÛŽ˜’TT ðf°òÿB>î0„ðGqì—ô»-Um¦‘/¡TíVh0VÉ víôlTRT?ñ0÷momÑRTPgõ`503žà7QCîÿôX>Rmo_#KoK?R›Q³>3ì2XàlQ¹pôû X>Kx?O¬3:@0VàÿX§¥¥‰ðÏô!8g˜ šR9`‘Kppð¦P]á"¥»:qÑ!c°?ÿ9mVmxKo7¾|á9ƒR\ïÑ:ïGQ8E¥°ô"Žý?±°Ko##xmÏm3m>pop7¥ÿ¥EE¥1El§ûEE…°ô"v„>·x¬mÿpV`QmøÍ!¬!rðll¥l¥{X5d¡!3?`ð°ÿKxm`99V\ÚèðG¥Eäp¥¥_:5\3Ee¡Xt°¯?37xvP`3`§ÿ++¥G¥¥l1ìƒ`ð>„¸!ó#-¬m?¬3ox4°£V7ê † ˆ ¥ßpXÿ:5=9„5GŽýô³`A#K`>`ûx¬¿`K5¥Q8Æ]ðGGbð9ñð=58Ø`ò"’+@·`<ÿX¥§:¥:+¥:U`588lM°×aÿò"Ž’:73måxs Xƒ ’pEEEöƒ0GG;qG:5KÞÿa!qGX¼°oX:¥¿À§Q’p"€0æîñ77Ó`mð C-¿XK3E’Ip§‡§Q’ 0Ð1bðƒð>ÿgg\óîCߎXG¥XP01lo¥’8’¤`§lbðß=„TT7×àìýŽ m>=E§¥ç’§Q… Ø"3gT=ñë3€cpáçG+’Èqc jTg¾×ÐêAc1)0Kû=3\°5:¥17ÿ=ƒTT+ðè'Cl²°Ý mW!€ÿPP=ïæŽïcIXVéà¬V>þl¡Pcïâ »ÿX>Gc+lA‰CQ-0°OnO€J1ˆÄɲ}‚•ŨU›‰ëÿv<•<¼X-à?ðv=gå@•¡ÿƒR3#XIŽåñ¥ü‡èÒ@>{\§ð@óC7›ý°•°R?[Xqê¿ó§TPùÈT¿°m3¬jgº7v(QlgT@W”gó°R`•°9>[EëCì)P¥ë‘g?¬ý°Þ‘R¬m`¬xlE ËKQ>:¼’þÄ ¬R9¬K##ßm`3K` ÐX7E~íó5¸ äo`o£ ?@K=`9T[:G+H‰R3C[Ê›PgƒPpÓmm`1ÐKž°lIýC­PŽ?jjRO>?>>1s°ßQÿo„ƒR78I8÷¥l•­Q§=RjO9¬9?¨ ð9`û##@58¼¼8û§:Ðô •7„þ7P°9373x[q„m8áql+¥õ°8ÑQC¼3yP¡mwV[x1::¥‡!ÿ’¥ll8XEC~ØÑv7Vx9RA ?m``mxo© 6p÷X5E l’\1þÐòGKV¬9¬#5K``[™ ß#Xl¼§øàG:®© =XHu  À[ÿ?¬mKx>„¬ë„3pE«pG¥:ÞK°K„X+@ò ÿ~§¥7[`m3þT°9`5E+:5ý1€\K7\=9÷VE+öñv:çE5xO`üPoX+óQ1ð71X=UV`KàV²ìа[°Vj$°èI×99[4à\g1[?þ ÐjgPVñçÿ9g97:ý3K[¥àKŽH@ÿ vX33>?Vþ• ëáQK+£~çšZI2ˆÄ›äM•ő%ÏiÇìŽÿX3+»ÝîývßÁT\8ŽŽÿH¼»äï+Ô “þf 5Ê€ðõ< •fµÀR>`3·18-ñ@v5ÑTå„>ÒgðTàVKX?vêñ==ÅÂø —°71»ë7òG…Ôƒ`yÒé¿g>K5GA>‘-î'•gR?fa3‰#×@]‘KƒÓÄ€R}fMàa¬KX°=XÀóXP? ?¡9RVÞÐxP= ûEE<0XQîó¯QK+Ñ95ðRR³xx ‚`"11>ió»#=u ð/?x`Róà5ðä0Ý1,p5GH‹EK÷Rffsà93#`[¬3 E+ä0EmàßVG+qðŒ-\üÊ0Y ¬35o`¬òVPo‡0ΠX7m#{1<ÛÑŽ=`3—`í9ð #x•°9mog5X+ÏÐÁ X§ÛÐÿ»7#73>ý?s K`xxVmU3‚`+÷àKúàXõP×òvÎÐ7!P#XûXmø‘751EEî 778æ +ñÿñŽ881=m}3ðÐ`„VKok ÿ¼¼I¼§G1§}#Í0ñðc @¿Vx#7#V5ï+¼+:Ar+„Ý>dàðŽ<1Kx'#3> !Oñ1àõ°ÿj»ñïõ<0Ð7£ RR`3ÿ7E8§XKX1»8+¬`¡Xðöñ7û\X´R9„7:÷¼+X¡ =KX5w¡j¡ÚÐí8É ÿ3mm=5+§Eß5mR=KÔàag÷gKïðA»ŽQþb0X+853„j×RVð9aïoécIàK9Æ0þ:99¡g7Xv>ñA:ðjƒf`ð¹jì 9ð7§ï €<ößðf9fa¡„ßV9¡KièÿA1Vaƒ°jaõfïÀ¡5ð„5îÿç»1#?°a}R!Pf¡a9D€¿æc#Vƒ&’gï>\EIÀå ‰ÿ8GE8-cŽAQèhÏ*ÏI3Ž‚²›xÞÿ"èLŽ×áìó°>ЂgXÿ»Q§åíŽü:ÒNQa?f¬ECOçî˜Ä ‘Ê߬7¼Aé÷C\úea¤ÐmoE7cúK –jttt?ô”P$0EöÀñŽj6'–T3¢ÐmV4à,ð~=ñ+9´f •Ÿ>39tm` EHÉ5´ðÒKŸ5R?m3mà¹àCÍíç`tì¾?>÷K73rP>aaVÿ7EqíòŽ7t>9 Pgy 0ÿKox`¬tRtï>VK:‰Pò§7`=3 R‰Ðný#;°Kx`>mV÷\E-B§\55gPaÛ‰ÐûSÿooK3o5:€ý84€òAX+E…g‰‘x‰ÒX Øq,ðH¯QQ§cáQ&0=¹Vk00#5E›:þ;p:++H€QQíEt¢C+/a733p‹‘D1Í  €¼€Â1Xt gà>àE7„Q6áý5`7E€--H¦Â85îpgàE¿á=÷=#5»Eoxm/xm#+åHÅpéoðC-ÏÐ7=¹àç8+oŒ :8Qÿ-¼8€QEvñŸîcE,à¹à+ùXÊÑÑѼHH¼§÷€+EÈàíH5XUàEX#Æ€²1€»€€J §+7ð›C:¥!5\ç`½8ýQ»::8873¿ðìŽ5hpoû=Và:8§E#½\½ :EKŽ© qÌÐ73`@@Þ¤0ìé0þà€ïÆ vXEtå ›8HàK>>­ÿm9>qïëìŸ`[à88÷Ð?jtÿ>ƒƒ´tgHî¿ëާ+“ 7Û\>ŸÀa´QgHÿíëC+EVþ¸ófj´jfjTÿ=»ìêqQû\fæÃ9``tƒý´è CŽ»Žÿ85\=m`´TEéßCŽ¿À("äÿ‚H4ŽD{¦2›Eùq~?¶JŽŽþÿI5+IAãìýè‡T´?[#+ŸèíCßÃ)•9ÿo<éîq3þêŠT´K:ŽêÏïvfÙê‡ft~ <ëïEÏAÞ²gƒ´\“ <ìðŽ ÀEG80v`|ÐÐC\g?jå®™Ä99\ÍѧÀòŸI=f„1ðFTýƒÖ@E:§+§§~‰PóCK[VåPý`Ðg´=5:E¿+l§8+IuÑHç5l:á“Tj´y¡`e¡Q§l+Àâµ@<à\à-Qg´`ãV=ô`¡ ;`l§§¿îñH+¡àEÏfPg[ŠÐU EE·lX+@ EEtÐñ™ïãP>`<á.`Xñ:Ô º†pl»ïÿñ»5K[„%[ç`XÐÐHR+k \`ï:8-ðfàAE3t9´„=#\¬Ñ¹:¿ÏÐE’’Ì@§=lP ðH#°-=¬Ð+’Äp’àãpy’)ð."qE>´ÕþãP:’§¼HIQÿ8§H8QHHI÷+X7`ï<>Ût?rK7G --¥§ÞHg!Õ Kt ïÿH``>„V„KX¼-<-’·o5+HH­PE7çàßïI=`‚ „oåEÓP¼:qÏ`-§’ò×P:a¬àxV`[³o+ÉpÏ`8’ïA’o’E7oavy h±à ÐÑ’}àQ§P¹5wàÈàîHG`7<ÎÑà§QIH|pƒ`Ð éq ×+·QIÔn`›7¥#üÐì¿»»H+l8¢ §þP7[¡¡>>¡û3`¸Ðév-+îdPKV``Сa´÷9?30æŽlÏ5jjƒðÎÁ9EþÁAqŽQ7E<ŽACëÃ??:Ë5’y„µ?r†…«[wçÿAŽCþCãÿé »+TPa8ETKcvæö1ó€KQ Ðt5HëCé$@»Jgg?ïx[7-pðH|ê‹ a¬[3:÷ÁsCX¹~Ø€to’=cò‡Á ”I9E3Ðò+[>PFK‘\§ñáD¡EA"b ¿E\?`V3ÑØ(ÒK‘ÐV+TÑC[Ħ7 >41<‚Ò°a9Z¾ðcuÑŽ>_°K.Pù\œEºñR¡>V5Ý+ó‰Ú`>>[FP`jЂ ÐW>Ÿ„\X88ß ™ÒRjKð=\`‹u¶„¿K5:8E:¹Ñ8KÑg8ñ*”“ð[tÏàQCÛÑ»7j¨ðúÎÀ+Cgg¡„3ã\5mPÎÄ ñ:ùa%Ðrgat>K©#š°âQƒ`\Ã!ñ‹HD@geJÑÍ¡+±€¾o`;P#AwPg§R°40ëÀR[ï §§§¼’Q’ÛAÌŽÐVQX>:‘Òt[ QQ€8õP¿ác 6ñCµR°‘Űþ†§’§88:XíQQ+’P ñH¯X7`t °$Xÿ§8’’’¼¼:‡E§’qP ‡á `¿Ra°aj?ˆ€’Á’ÏQ¸ )ðq`— ðÿAŽH7¬RaaR=E€+²Pâßü.‘aícK¬R׬x7®’à’+Ú. ’DPovñCQ­K<à+HM`§K 8Ý’›àX#ouìmAK°8€Ã€¼ÎPìm`ÐÐox¸ÐëA €ª ¼‘P¡ u 6ÿAïêCc+êQ`§­ÑEöÐxo¬—?#î†ðŽM±™7·oooê `+›ðívQ§3D@ttRýaà‰:7„ÿa=ŽëÜvãCêZ>ÅB01’IÄé²VÅßê¯.·ëß~Cõ_íÿCdFB·Ž~þÿ q~‰I§ªG÷lII× î~pÿXFFF……pŠ­X:àXX}!IÈßCŽ/X5p°XEŸFppFŠÎa pwª§c)€ñs;àü²m°Špp…FF>Œ±§lQ-qbïÃ33 QÖ‘ª°È²:+ß:Š·H,Š òÿ,FXXKtxÝ7ŒàpEBȲBE¿l+p0H-„ðò{6ȱVVm=rüe±ì±ŠXKGEp×0§Hñ‚/ì±X5Ï#t?[Sà–FE쀳ddE\@õ@ö$"é°p/"/ÿD"·6,Š#?EXld-B‹Ð¯ðßñŽM"f°ª/""§0§à‹àÿ,‚,5m3K7ß6çìYà‚6ÿ,X1Ýs‘À…¯Ef±s§û•<×±A0Xd/ÿDD0DFm3V[1X5¯…B.ßB0·lQókAdçÐB®ÐŠ…6 ùtq²CB”0lIû³d9 ó ‚Bd¾dÀB"”BBÊ [í9ÓXXTDd³ïQ§d-€Â”B³–!DFeж° 5ÿEŠEFD6d¥ï³Id-Çô!~¾"·u·/·ÿð0ísÏÀEoÒð¯s"Þ&Ð¥Qd,ÚPô"÷Žu"ìÐ/s1dÎÌÐd"s˜b s0ÿ·ddšIl,<—šAòËvÐÒ0ÿ¯³/0/-66ãFXª°  II<ÿŸ-Žòó!MÿBD"0s/§·ÿ/¯Š¥··6·üMÑ šd-G§<ûšQ~"””Bÿ…Bs/BB¯sþÐsss³5·šÿdd-I§·-I½·ïó A‚h…ÿps"sBslIÿŸ/00/ps·ÿMŸšQdd§§~ ò~†DBe°û0DKs§II6]/(ŸŸ, GÐñb”@Fuí…‰ÐEGP6ŸšÿŸd-,d0·0þU’ŽB@Fsõ"Dï 7¥/l¾|Àd,šdQ÷°ñßA,uÐssþ®À""0Bs·I÷EdŸVQ<îÿðvbbD5Xþ©°s·d··uÏsIQ•~™ÐîÿïŽbbBFEýFxðs0ŸŸsŸ=QI·ŸÃÁ$!vöaàssÀX…065"@îvNï6І·"0\ûXI-Q·ª³F5Þ­€ñ,† /…œíÐÐÂp71]PaÐs»FsÀÐñN`bï†+d6y¡šMMm/ PIdW°0váÑýCO`‚§I-/Þ àd€M8À§dï0ªª<áA‚6ÿ-I<‰††½†Ž`M†ªINpþÁ2v †<<ÿ,-‚ M†dw‚ 0x 55GÌ ÿî;M-‰N¿NŽ‚M‚d}alß³5xIUáCNßN,‰‚<É`,M~¹ Bx371cnàÿAŽ<<†M÷€·/«`,MdŽûqéLðAcN/ÿ,NAáêqG‰CÝO??'5403“Orµø'kwä¿C~‰NCæ ÿŽ6·dMª15oX¯·vÖ vé²~”ñ57Š/MNŽ2óv,ßò¡±5XŠŠvÐзcìpïwÇÑ÷FFŠì1g7pO¯E³§c@Âpàþ±s52mj>xpÿEG§dŸs/<þi`ðŽFFo4ûKKÇð#7Ko5û5ŠKdŸ·"·¶@ ðçÐX2tFß7XF57Ð5:Ï0Gšd¼@ævý”Ȳ1ªF5³d¾™s³·E·šæI¾–ñŽ0¯Cs¯· F"ŸM­Q÷F0šª@šdIšö‘-ÇÑ0/B6Ý/õ 66H0§ÿª·§•šššI1~`RÇÑÏÀMMÒà}/ÜЧª§I•ç—§•qƒQŽÒM°MÿM6"/66·0o6/ŠªIšR€½I¥R,·"DdÿMMªª6·6"W¯60Àdó@Ÿ”Pú¥R ÕPDBsMM¿Ÿ·1§M ÏÀªñª P;P•P§~ò÷ò ŽADB”ŸùŸ ”/0+ªð‘PQ½€ò b"þ.@µBµMŸMš÷ŸŸ-óÐ0³dª~¶€-š<šII‚Pü#@PDµB" šíd3MI×À·/ªé+}YP§=PòŽÙDuP dì€M6õI€6·d-6ï·"§v„ŽDBµµµ"  d† ­MEЧ6ºQ/|µÝ0Ðò ¸@ïµ µM³àŸI6ö`‚X|Àš§·BõEÖ’,abµµ ÷Ÿd‚ ŸIšIµd’€šö0p:;Â~÷b "6dŸñ,]Ðè8P·§§0ï:¯:s]ÁC‚ŸbMbb"; \`Mý·µ€ŸM§·+ŠßK#7E•WwÿM,Ÿ/I-dÿ+6Ÿ‚·0:I}IT :Kx77ß1ob6MCÐcIå?•Ÿ60E+!•ûK0áNb6§•ïccš·ù€Ÿ-‚ÿ·EI·po5Xý0Ì ð~NŸšß-c<<6ÒÁš,µ·dG##1^°ú– cuàN‰N,6÷,dNˆ §GKKýšiðŽ•‰MMþº bMŸ,,‚du§ÀCiðCŽÉ`ûŸt§éíÿCýC~N‚Mï§NN6²ðdCéïäCåÐB~æâCçï1(45’04èo²=5ÞG¿X8¿Ž‚6-Žqó ùCGP…/ŽA{Cè|0q·……ÿ5XFXŠEDްëŽNAÀ²@†0û/-nàކB5øšrÐñ pKX…Dcoìí25!Àº³s5¶qp0‰Á`}Žj22K27²rüË0À°X/dCî/î†pKÀ ÁnûÐK#$ÐdÀÐï~0Ðгp“ðß#xxgйÐ0‰Ú»ñC@Fp2Dpç§BBÿÀŒñd8Š=09ñC†R)áÿu6+•uDX§¶0DBàP·šÆï†B”siBD6ÿ§,60+<ý6‡€0·I+·dê<¢NC0Ó"·¾¡‘†·,6·.@+_§88§§]qüT¯Pµu6M6·ÿb6"ud·DB½DéÀ8³+q‹Aޏ²ÁRúÀMdMÙÀu÷/u`8³0+³³ƒó ©N@¯P³†µ,  ,·#Ð6ÿ·u³88³sG¾4ÒA"BŒF†}µË dI§šÄ ýu…@+§+8+Bî¤òu`ÐB"B×"µ"‘Iæu†þ §§E§+p§eC„µҨІ·–PŸ=ÃàF •I+€ÿI<š-ª#7Dû‚F9`šINï7[EÀ`òq÷~‰‰ù`‰131ÿ·†XF/š-§,·dXt9€áàïv,NÈ`XK7ÿ‚F#š<-dN0s#[=~ÝpïvN-ì`5K€ÿ‚"=•‰6šd¿7X``€ëí v÷N,oÀ6NM1ÿI-M0F5tt}X©pvN†"éàÿ,,+³dsXoÿ=ŠšŽêì{C<Ä N,·p#ÀÛ·Ž”p A( †X÷X§‰¤°ê~‚ÿ6d-Càé£CÜÿXÿd³7k´ßäf2xµÕ>?€5èŽÿCÞé N”"€Ž,·/ŸN0ÿꎣB+£”¾uÀBB+švðïŽ/£B^…s…öuÀ+•¨qCŸB±£Å=Ñ=‚BuÒ ímŒ€£”öÁXE BßFB0dŽÛ`v°öÁõÁ(Áë°Xp»p,† ‚Òа:À³qEóBscA.ÀïC£þÔð¨¨@24±4\ÀùBB/«cKÂùAÀA@4±±U±©3t;BacLÁNïF24#@@±4o—Ko# À”¨' d>o@ðŽ£Fýð1wo53=ÁFD0  Ò4-‰ÂCPFÙAXF¿EX75X5c6®:àdšQx‚‚öÀ”Z:ÀF+@XXNF#Q¬- Ê@,A>Q‚¡À2Ó±±ýñѰ¨ë±Bu»†Ÿs€ddQ|Ðñ~ B¨4±Ur•AøPJ@â6M-šdï·ps<`QvDŒƒ24;P#PÿEÐbæÇAdQaƒP ND3ŒF;ÐDµ1àEÐùEÈ  P0³QCóÿò!v†"DM[b†¤ÑBB«”Ñü¬èA0ld³Aóÿó!v·†"MË‚,¥µÎPêÑuuë·01 ³0€·lQÛŸò¡PŸ/é‚Nô  Pu£"0FBþD EXE•dulýlô"Cš€2kl”Bï…0ªcïAg£X5u@¨¨>P}¨Õ…0Q,,ãÐóïV@öXFuupoÀ§‚À¯,d‰ŸÐ7ï~‘Á0/̉`³F2¾@÷0uMÖÐd®Xðqë0"4ï¨F”D9@X7E¯……Du×Ñ·Rqé§÷À?@4DD0ªB5E1¯0‘×0B0|Òvì1@4ßU42@¨ä@"uþüA0”DdBû0EX†FF/ã"BÖÀBD/»D"1 ªs³ŸÐóÿ C/ŠB6u”"†M†u"B:Ñl÷0pÐuMªª~’ÿv§’€‚b6‚§N‚bÈЯòB¶P6ø°•ÐÉó!C9E÷BE³ë‘AN‰ŸŽŽN<û7¯àíC~‰{-§•Q//"”KÿDB53>xdÿïèqŽcdÛ/0eÀD£þ€5xûgXQ@åC~ŽýŽ!°"·‚,·FaŠ3@x¿@¿T910qôÉÎ\òluÄ4ÿrñÞÿCŽèàv<û""¸°â~6£ÿ£B",éä ÿC-+B££//ý0å Ž§§+ÿ"£·§d-H‰Cìæà-ß-d" D*B”¿u--§0·fÑQý-Ý€ð~<‰Hk- E ”/FD”€~(àdd€Qd-¿à6@,N( ,-Æ v`ÏD ¾d–Ð*ÀQ€ö6àï! ,,NHûuµS DDu6HŸd/d€d‰Ð•`ïÿA,‰,NN-&¦µµÁ Ì””€›Pð1! òЂ؀{¬@Ûu6° u-®íÿŽNc‰N,<,õHHз…зBEE{§-ìމdàþµp,-XE/duî?XEcv°~Nï,-¾‚  HuFkFpÚA§_°Žn ý,  µ54±FKÿm7ŽëéŽýbtáNBx`UB{"D©ðé C‚·`ÿB‚B`7FŽçïè Žß`FBuÿF·CæçACAAá!¿ç¯M÷4’XôßñâeõÕÉï óãÿCCãäqÿ€d~äå qý§U@Qúý0I–ô"C/Dÿ”/pp/G¯Š÷#3mÀX1¯pÿB0dHdàïCöi -I5 dI‚·ÿD"d6"0”…¿·vìî=`Nî[-MMH`D·"w"d…ó`íC˜ ûŽc·M"BXF¾éê~Z`<ÿ-<,0X22dí·û`é Ú6b<½-ªðF”vè˜àqûNNr pXoF·ÎÏ è Žqa¾`Cå¸?Í/!uC01³™À÷b´¶ÏoXtÿw';CÿC'ÿ;âíC')ÿ±|W*!!r±ÿ±];;;w©Éþ¥ ïwS)UWÿWOr±r±U±ÿU| y2r¨)ÿ! ;íð'ÿ|W@||@žWÿ±žr)WW*$ÿ¨Wr@))%]ýí„'W±rrWÿW|žWžž¨)ÿWrWr±$2$ß!e !;àòÿ'±UUU±Wrˆˆ)žO@*qpÿW$!–rr–yÿ¨!'ïóÉÿWˆ!!WUUrž|W¨$r±LpÿWW±UW@S2ïO)]ïQ@ÉS!ÿWW@!±!Urÿ*O*@Wr*@ß**e–$ñpWUý±»pÉòô#iÿ!e)!!Se–×!*^ýpWõp›*ÿS$¨2U±±UûrWq]óô%¿'@e@)S6€]ÿS]e)–)|@þÍp–W±WU–Wÿ¨2›2WU!nCõó&;]:€ú9€!8€n!e!Sÿ2Ur¨$**rÿW±@4›@$2ÿy!]'É÷òw&z][€e!eh€ÿ])]SSkS@ÿ›Sn$2UW2ÿ@!¨@)@!WeSwøñ&äpïeS–± !]!Ëek“€SÅp€)¨û¨›·€S! S©ßùð&'°€e!÷!eˆ`‚SSi%ÿ]k!!|!ˆ!ýr`€›@%!¨)ÿS©úð'©SÛk%·€!)ë€))Þ;€]!!i…€yWý%À€S)]›O!ïe]©ûÿ€;!%ÿ%!n))ˆW¨?e–*!^!€‘€]Sˆ!]]%¿]SnS]])(ÿ']%ˆS–|WûU$Ÿ€U!@!ˆ¥|!‘€“€kA‘›ý^b€©üñ)wÿ!|%WS*44ß4O›OWúp!)•e*_‚k¿€9ÿ'üò*wˆrÿr!W!r¨¨Wÿy2U2%))yÏ@)$S‘€!ˆïWS!%Q]!@ÿÉüó*w]žþpr@±!)W2U)))U22̓e]6€€QŽ€'ûó)nã#€²pÿy2WW¨U¨Wó±O8€f] Sÿ!)S%)@|SÿS)Súó(nü$€Sp±U! )Oþ!€¨4!@%¨±íOb€ Sí¨ž±ï!Sy]Ó€ó&]ü%€H€¨*U$S›ÿ2U4›n2›yï42W*$S@!û››¹€@]÷ôÓ&Éép®pRQpU¨¯@¨±4¨ú€@Û@–€!›6€Orû›ö zS!–WW***#€2à À€ÿ)n ))›2!ÿnS!$$›nn¯n'Éöw@'Á€e©!¢pÕp*—€Sò¡¨µ õ€ 9€¨Sè°óÃ;g°€óp¾ $SçS%eÉ Ñn!Sï$ nzÀ0z;>¶W›|r|‰€6€÷)SWn ]SWûSîapC;''!ÿ!–@ˆ$e–)ý%•‘›)U@^n'íìC;6€ïeU!ˆâ‚!4±£Sêƒ`M°Á€–!ÿ*¨$!éæ ÷CÉ'”°;www£ÉéÒoäk2ódÑäÕ²uÇ­¿ë±é‡ÿ;;n]]zâÿë')yyWWÿr$¢iCC'Cßçì]Ä*|ûyžÏ !W]‡èv:`ziæprU)b€ý)Žpž$r)Swÿ‡‡ìñ‡i{S@r€Ur)@ÄpyWyŒž*@”€ï!;‡î»PzS*ÿ)SˆrUU*@»@yÂW|O ]ë!O7À;Ð)@ïS!@W €ˆ@ˆù%쎀))@Œ@¼C°@ð;$ @ß@!|U@‘Á)!ÏŒ@¨@ C°]‡ñÄð;k†±%¯)ŒŒ)ðq±±Sß;ñî:€]S¾ë€S)4¢!¿ $÷) %Ï ŒS@iÆéÀia€‘`€%!ÿ$k@WS ˆ)»*±2  zò Ð'çk!kÁ€Gi¢]q@ŸS¡±@)i(Ðñ’µ€]] !°Ð€þ YÐép)]pïï i!ki!S^ùˆb§%¢^S ÿ!¢**@! %S;õñ#CÍÊh‘)!-ÐíÁ¢rÿ!!$!*])Œÿ!!n%wöòÿ%z!yžWˆ|oˆˆk@1ÒkiQ÷kS$¶!r! ÿ^ŒrSz÷óó'C7p„p@rS!Ã*ˆ+ [õÑ@‘!¢l$¡Î‡øßÐ]žãGˆžrçwq+  ¢ÚöÒ%£À! …€iøŸô)]Uƒp¢qr é m ÂÀ1Ñiý“þÀüÏ€`¡õ*'UU2¬£qYp@*š 4C ¨;) ÄÁk]4o‘7Ü[aà+©^ÈpU$ÿU¨Ur@2)yF†±UUS¡¸€Pâ]¦àþ'áSiúõ,‡ßŒ¨!!ž €W$eWÃà2·ž€Œ%óÒØ¢§à7ƒ;û¿à©%ÿ^!k*$$|¨ý$_°!y)4¨¨À3 Ï€Ð€QnA‘nOÞQ’ô+‡]\p@rî;À±@^ÔÁŒ±%@~ Ò‘ñ;òC°n  o*C;]U *!s€k¢± rÏÐ@S°ã]W,àðVÑ%])Êíàðƒ€!Á¡ÏpU2ŸŒ4)OŒ?Ñ%ñ$WÐùÓ:€úï$/wS%*À@&€Q¡/]¨S¨í4Àîb€!@kŽàî#‡·]WžaWWÇnS Œ!Œa ó3 ~€zùíw=³r*±S¡ŒS(  ïSn!¨¢'©ö/ì‡* )p°T ÞÄàSŒ!¢a€^$ÿU^¨^]ôëûzA°)Œ**!7]*!( 4Sý j€ÿ¨'zóéCyw1ÀZÐ!S*Sß]O2Œ]†Àæsz; ÐŒ!¨ ÿNíâCw]špÿCê꿲¿æi%3ód—ÄuœÚÿ䇩©‡©z½æ§ z'yžØÁ;õçƒ`'=|ž)yë)¶(ð]”`ëCÞxp|ˆ¶W4°ž¶ÿ@(]N'zì»êŽpU¶ˆ–à@vÓ!'+!rÉ ñˆRp‰âÓÁ]';ïÿê!* ]ˆÚ›à¨¡‘!y’ CßðëzÆñk$Ôú€kwÐ) Ð!'ÎèÀë(mÏÁ)Sá(G‘ðÐ` Cóì]ˆwÐ[€ºÀÇ)ˆkÇÐG„â 'ÿóí'yˆ)äñÀðÀ(ÿ‘uS% ÿ(S%!†óîƒ'³oБ`€\(øô ‰Ð1ð;óð-;¼¶ˆ $žÐïч(!n°ÐpL óß"Cb@±2p|W7)ˆ|rÐ|(4Ð'á½nA‘!kk ô«#w¢q)áž¾Ð|„Äpÿ’(!n‘ÖÐ,$ù©£pSpr|]y)|¶oÐê€(:€M –!ú8(iÐõ&CS$þ£q¨r¶Oy*UCS¢ÙpË‘±á!I½'U€õ&‡!;¡Uß*UŒ¨žA¨±Ì_À¢!( ô¡(±÷S'õ '!$±Ïr¨±±ùÀ®ÐWUŒxÒE ÍÐŒP9ÐŒøà ×€,¨Œ$ŒWœÄàA !Œk¿‰ã(w]¢@àSSC€€%w(S@|kÐFS0±O“pÉ’:€i !.mñ S‡N1CÍÐVðÚù’±þ‘]'_ÐSiß]Si(( ñŒSSw÷ñ$z" "+ kAÀC°Œ7ÀÕ‘ü@“v'÷ï";S)$(k2¢·>IàŒ*Œ]rNáC0ú8€%RÐ!÷î"ÿ;(r¢!2S á2žÂÑ£V ¶žŒü+ ©€í!')*¨¿r(**2)¨~‡ä S¢!)¶6€l°@"Cˆ°@!ÏqåŒ)¶Ð€›"¨k(»$¨áð$SCôð!7C %”S)•p°þ‘ð@*Œ¶)!žß]])k¢Ôàbøÿì;%!O¶.É‘% n@ L Øðý)¨!!*ON÷Wë‘€$Í@µáþ°¡±rW!S¶yySJ #0êC]X°l-àO × @Uœ0ÿžž]*|†õ§è;vA‚ ¨[Ñn÷@¨U‘Sn†ôçQðSÂÐÁ€ÚAþš n¨]ñäþøðS@4!U$¨ù@6lã CN'ÿ]*$@Œn†Nÿ~íßzN†Q~¿¤éf4ódAyRòu7Q_“UçCzÿCÿC‡ãè§i%òð i-±'ý©AC(r|!÷¶%± @¶¶@]÷%]%_pë©!ýW˜Ð)|O¶Wyüó—ÀS;îíÏzSOW¿Ð‡p|WÓr|mÀ¶„À©ðŸí'*ùP=Àž<è=k%@|[€>è©Ožˆž†p’À;%yÇÐ]ˆ±?°Äí(ÉÀCNÀW!)yWˆžyCÐA ìÄ[€©ò CSUr4±yOˆUqÑ>Í@%¶¨2|öÒQ¿‡óñ!CháU 4Ј—@’â02ÑH®ÌÑS©ô‘`‡•b± 8ð.Ð%ˆ»!•p!ÄÝ!6ò";Ö"U*À‘Áà‚](Jß2/å(ÚaNH€£qOU¶ÿ¶!|||%S@í( !–F"!SOÍwÚ`!za`£q¶|žÒˆ%k*j!Äiî@!ó'p©(@µ¢#€±¶ÀžO£€!4óÒiNánÌ(pÕ þ ¨–¨!y@±âýð|Ài0ÊÑ(k() ñ ©s!¢ RŶ+0*:óõÑb€Oi  RâWü‘?ÐG€i0Õ(hsSG0 iÐð sCi cSn q¡øñ– )¢WO›ý;jЇ((!WVp¨k‰°WÝäSÀ|DÐ5€ôî;þ‘>¹€!›*¨]|À üH!â0S!O*wõ"%€C€ðZ02 O]Ñ4Ðü’0Pá)¨WO@N?õíz(l! á¢ó@pó5Ð0Ñ@2 ý)Ï ìi)!%2G0±‚Áá]UÎp›àZ ‘ô')O!pÞå›]–@LÀ*`Ÿ¢yO* %p®€Sý(‘±W* n!þ¸ð(4!(!OS9¶°iÐì‡#ÑCÑû› à WS@OW!%žW2WJp‡êi›ú+P>°Sÿ)–)42O¨(=© z!!A† ·OO4åÑyyèSOñé"ð°¡¢%ðÓ*O™`²ð¶¦ÁçÿiSOO›¨44ÿ›±44WOU)ý›YæiUS%ö[p›¨4‘izíÿå wS!r@Wþ† @izëãÿN@2!uzCèâCNCå’_4\_ʳ5ÀÕØ’Íó˰Ÿæ'©âÿçC'@rkûS'§é 'n—ï—Wr±³'æÿê;W)¶—Wï—|¶)2pzèŸêŒrWÀÐÏP@Ýy, !;ê'2ßW|—¶@ÀžžÿU|¶y*S;ìÿìz2rW|ë)|NÀ|b !|WÏ$±)%§Àìå(/p$>‘Àrryßr^!!¶ÎQ]wuòÎ]pÀU±*ûï¶rˆrÿP)——ñ$ô`ðTî;*þž¡¨W±2¶—ˆÿˆ)ˆ%ˆ¶)±õžôÒSÌïC)¡±PÀ/pÅ ãѶ À*ãU—?Šà€ð z$¢„ 2Q ¶×ðH2ºíÂSü¢]$Œ´UÆ›Àkkªp¿ PS(ï—S(k%pð 'ƒ$!<â^ :²>a¡Ñ(Ç)r—=ÝqR0(S»W¨„ $)¶›Ðkû%¶­á()@W%\S#€ï 'p^ Œ%@k •ЉâS0Ž@ç(!ŒÏ Ü %—)WUWW±`gžhI1@$€" @SV@%] ŠÐA8 p íSg±îÌ0WS— ò ^ï@@Eð?°Fð!÷%!z$€z]Œã^)òÀ³0ñ)^WÄÞãî ]} › ® Wr€% pc€‚p®tú Í@¡*W@ë ë )R$p!(úÄ $­í;$@ß$*SW2Šà@Wµ2NÄià^'™ ý's y@^S¢S7*±* ]¢Mâ€yña/WS((VA¸ò!Öq×`nW^¶ÁCìSp ±@Ùਠij™ ]5@(z¡;³›*Uô€n)Ht(¯k]'ðóÀ‡:Ñn÷%¨W.á$4!¢n]$$!Œ‡tó'à!!)^¨!ÿW¨2^@)] Ç'Cïðé@]· ±(01*^\¡ê;S¶($$:Ð?2!U];© ÜW@@¨^  èÿ'!¨¨@¨nwÿäç'¨ !ÿ;âæw‡à(Ÿ·6Ô”ËËÒá•iÁ£ßãÓã–Ðþóïå wn@@—WiÞ æ z^»ð!—þ¡°‡éè‡'þð@{ˆ@ˆ)kûk©oÐ'@W¨ý¨·!ˆU2ˆ!ÿ;ëé!—*ïW*O|<°k)!ü.ð*'—$Wrï@)|SŸ°@%)÷SO!…ì;]÷)$r¥àr@%!¿*|—U|±Äð©:òP]À**rž ¿`ÿSSU—ˆry—߈!|'ï.`C ÎYàr±±ŽáÐ!ˆ{|rº°y@O]z Çî;V@K‡ U* ))ig¡‹ 60S;;ò÷²@¨$,pž ÛW$ !kV`±žuž/ð%û¡î C/û@$ÈáU¨UW2É*íQpr8ðä°iCýöõði*!n@*­±à*^ò@%<°)/|y|{æð% Ð%ñ'{n(){—† :à O?1)ˆ@; ÕPüÄ%ð C(S^—ë!—²WWkU)á|_pÏ@ÄM0ì]÷S^(Ra^±±{¼i1Ó¡y{!)]ó] %ñð€—Wy±q$àNkS{ð±ý]Fó;O@*r±—WW–×0Ã}0!Í{™ –2r€$ñS?rW—)¨—!ýààô`W±‡b‹j)W*.Tp—^ ÀW1?1ô³¡Û Ï î©@ý¨R ±@W{(SIU-Àbq{®` P{ô³ßz!)*W/ð–U\0žð ^ŠPÃ뀻 w@22c W){-‘!(Ò@ÿ°ê"ע 039y­0Û°!)¬ ýúBp{—Àî')2‘±»ðÀ±v°9n`ŒpB¢àpÆ–)_pŸ ŒŒ nS6ÀU3('¶Âm]{vÐs0g*@@äb€–zÔÀûCõ@ )±–@ÐøqaÁå¯AwÐ;ë{O* )ò@r)±Ù¨ ö0)nrë½n@ð**¨2pnÿ;‡‡‡w''N?Cîë ;cÁG@Œ'‡äâߦßf[7’Ô”ý´á•óŒïÔß©''wCüÑ'!ÿ@—^^!(;èÿè z(!——o@$Wy@@'é?àg©!*R`.ðWWWp{e^] ë;n9ÿr*W@*W!$®ï!e%wjá'SprÿW**W^¶)$®€ÀS!eàî:wù@º°Q *@U@y_r)]ieÍ`]CÐÿìC^W)ˆ$M*¯ *W„ à0e›°­iDÐn4Ð*‰@ŸW¶*!œbq¾p%¾)Ñ!œ(¶ˆ $û*)V!% ekúr0) Ðë]œ(ÿ–±¨$$¶¨|ò¾`S~° °k!‡ñ>· 'Sœ¨@Tpˆ ‡rr¨¥ð¿pBëÃ'•€0áE‰ ^]Ÿ!%|!ˆ¢p¿ìÿ;y)$¨–œ~¨àWrˆ|$!‘0Ïk!)UÃ0XÀì?!r!$œ–ÀÈá+W¨˜1œ³à¶µP´`÷í©‹ (!–œ< !––]œ{@ê1÷!œ©j€;r¶½%û°WW^Wuñ±©œ»2L€ˆAwkñ‡ÿ¨rr$)r@—Lqð/p¨^¯à¹1!]àV@z÷lð'á¡¶ !¾ÇàU$*–Œ_]Ú_àyDð]'î1b¨ï¨U±y¡U±rS@Œ"0{kS®`þø`zøï#n4ï!¨yW»A$¨rÏ@–]@WÐ(B)¨üȈa‡øð#z¨rO¶)¾ðUðŒàë)œ.¨÷b]W!ýk'a(÷ï"œýO¹ð±U¨rUt\½À¦°2U$6ÀeBp(=1× KA]€OH¼@¶Âp!!–Ò€Óbfaú€0©K@!wœ)roW4t$C¨–q°C–Sa0ÝÀBpuÀ)jðÿï!;!y )rß¶*yW$Àq! ø©Á¦°cpœ]eU|Y;¼A%S‘ )C nœS(]œœ×`Ù^ °Óbez¼@ wÙO €³q!! *$‹*@7B$­`îÿ‡' )œSŒ¹—ÐÿÀ (Wаi¹Œâp0À^'zŒ€Ûz;àœO„€¨OeOp€)Û¿p(''ÿè;!)2ŒbÏ;;w; ®`n!ûŒbÑ æz‡ùש'Ð'I Ú£CëË‘ºÙ8Ô“ÙŠÏR½€§_åÿz;‡âé Cÿ'µ!$)—^(ÿS;Cçé 'ÊV)i @Ààêïµ¢$±Cr@^ÿ—^!]èëù‡ßb$@@!^7—'zG ; ð3öÜðr—'`!e'ë" '²6!—ðràÀ{Cí!OW±±`´ @ `WcÐWSn`Ç'O 0X0‰W@rg±W¢)'mß]›)$X0—±?W$¶@!¬!bpÓ;ðÕÁ=O ð$)ÿ@¶¬$U—)$û!(|ñ(©ñïÿC'!Oy)¶·!U—¨€{)‰À{÷ee@­sCòðçCSàü !@^O))Wj& 9`)ê±¼6ÀÞàð;›¼0rÿ‹±‹!^k(!Ã$$@ÿPr€{ iÍîù`S¨ @Ur‹ï¨]{e¨ðj±¶äOð©Àe}‚xÀð›¯O@)Ok‹š€)7$^±%Ð{]ngñþ'ð]±rOO±!¶t`¢^UÅ^Bð¶0Ñgñ¸q!ÏUrr4Ÿ :±¨¿W¢!¨W›«0^|±B^€óñ!'ž@Û44Êਗþ ¢eÿ$$‹$ )|)ãS%W°°ë€ñ!Sü`Ÿ¡UW)k]e»@(Ú!]!¶Ji¥{õ0%Ë€ðpU®p4|4`úp{^$)^¼ð±@D@žð1±Siîp"í'V@U¨1àUryþ`$U$±^W$ðÉñ/Áˆ@k0ñ#nWsrOÔpfU$!qà$¢^$±—Sè`4ÐÁ°S#ññ#ªpø û¨O,p$)W¨$½^6$$@— À]ë±!À±©… $ {!‹Œ ¨$W{Š €U)º±WW„(?€UŒ°Ž°ðaøb;x‚å0 ›O2‹@€a—¢@FPs…°€äMÀ+!-À&WeeK!œ P]=q4 U ÐâÂ0gxÀF²pr—e¯œ(œ¢<'`p ù]-€±‹‹rUß)O›‹U$¢¿¢œ]µi¢ì‡lÃÒ™Ã4O€4¨Eò0¬´`Μ!](>7€ð!]±jõqhp:ÌOÿ°)¢±y°Cwe¨(ÜÀð! »Âãf‹ Ð3`¹°^^rÓU!í1“!^ÛÁð!äñ¡Ë ¨#À:0!n¨@Se¢FAÄqhtà‡ð" æÂš®pÑ)à œš€âàób‹A‡ö>R ')UU@ňпU@*S%R¢@›Ú±â(®Áœ(„€ð!¿zS¨¨Se`*î$0)!@ØU^Sì°Â«$!òàï 'ÿ‹))‹)±^@¿›)!^O!ê`tì<2ób!k•àï zþfP¨)r—))%qS›àw^]nñü~€LPî]S¨Oœ`)%!Ê@Ì!ûœ$‡’S(e^'ßôî;%°@!f'SSP™œ(o6ÓAeœÈpîý`eÿWO|œ œS WeS)¹!ŽÐe¨àwóí'!;àÏ)*@› !P@@ÿ^œ! !œˆ%þpì S)])Ø@®@Ø!œûà@¢ßSœ)%'1© o)¨!U3q)—›0ÿe!$^—e %û|!pëC;@ó$k4q­@S¢!]ó!^`0‚iòé'¨œ!Sk“@ï(S¢*f (œSwkˆSª0èw­’þmp!¢¨^¨Sœo^S¢@‹1çs¯%k)SP°$öAeþ+!©òå'y]+6à)]e(%A÷@!ñ5@C;!rì,@ê@œ2ì1%Sñïãwë@!¬^ÿ^UW@±kœSÿzñâC')¿@)e@$)´ œ¿]ðà '‚0'ö%PS—¸a߇µÿ;ÿC'';©(oÿÿ“ò1s¤ÒB€¥ûªGÛ©ÚðˆQóC;ݰéw!ÿ)¨]©;]!Wïr)O!lp'íÿé!W±W¨WýOÐrUW%‹!½±Uꇨ*þ>°*Wž±ržr~w0]wïêPiOz@qP±>€W¨0¯(SCð `C‹€W_¨) *!a*Îüñ¹`ë©*rU b ))*ˆPŒpAP•–‚€ñ{P]¥°É !ù cðŸ‹UW(Sßee]iñŽ0C@Ô=Pf` æ`2 P¨Oó*(h‘÷aìzUÿ¨*¨@) ))ÿ¨@O@@@‹WW*!W!1w1wȰ®ØP)O)>°@ÐUñ@P€~pª2'‹‹*ÿ4W)ržWW**ì r^i°¬’0q]Ê¡€=)!O°™(0#Òzó+`õð@ïr*gž`¨))[!*{@B`]m0÷ì¨ãPWfWUûOž‹â)U2r$øÀøÀ™í;r@»$‹ër±@NQ /)W*WmpeQìqÇín?€HÀ`¨@W!%%@‹2¢à¸ò0³‘,0C@8fù*ÜP{€))4±!ñ^¡À$1€î©OñRÌøp40r¨%%?!@¨W*2«à¡æ+1;`€rr!r‡ÐUEð r2^õ@W>€!%¨!œ-°zÒïKŒn!2í'ß]'(]r†P$¨!Œ2@¨%á! k0ÿñíCCÿÝCœ$U !e¬Hàñ@'=‘'áà$Û$WæÐe$ãáS!­UgðéO€^1$½¨4eeSœ©éÂMA*Hà90Eð–^;Ÿíç'\L4®\(;ìÛð‡9@(ý!o!e!2ë_æ znç°e²`ïe!7êÌð‡!@Ú%@P‡êÀð~'''¨›^;é—@OCCCèÌŸÞŸ3ÎCÓë3òÛEá ÿÝ/É]O!Äàà­‘bßW¨]''ÎãÏz'n‹Ôð#PO  °1ä]`fð÷þÓ !! )Œ;wÿ];öå©‹~pUf@!ÁáÁ´Ð›É÷žðŒ±©PÙyì:àÿr%)Ú {;÷Oæ]5`W¹P›SOÚ!SnZ ˆ°÷oç;>4ž°P)y õ°®ñÑpñðÿè;r4r±|îM4y]œ€!'iù)1 °÷é©i‹=x°rr`!]!°§n']ကSÔðëãC‡ð"PwðrU9Æ¡P]i!!0}à(zÿ÷ì')¨W—|ryœ—~j#Œø€û öî C ]p!ˆx±‘r‘¡ÝibÐ '½p!C n‹í )x² …Â!"ú£Sœðï!]‹yO)O|@à¡ f°Ø}ä2S%’ð"ÉX` @—"P1"ÏðÀ¡P‡±d€j €`w!;eë%{s€±Ÿ±9WÉObâ0 ¿€ ASŒ±@¶y Áy±½°fô‚à!«ñ]]%{t0õЈœ ñ"zF‘Y{ƒÀ1"‹g^€W ±D À!ñPô U!®bÜ”€|ð!]Œ¸â!@ëeW“°ñF‘(i $‹g4¨O‹P¯] )%?!õÐ{»!¢ùÁò"zx` ]eWr‹‹Oì!ö·0S]0SO]Œv {S«Ðò"É! ÿeS@O‹¨‹!o{UOS¶`)S´¾#!r¨!(–§`òüÀÑ!rU$¨$ööO(ó Sn2_ Wg±!Œ€ó1!þ¸qS{‹$Œ%^Å@1ÀSö€$±0Ðr^º;U ;;¢ÐSP!@WQ¿€*Pû±–Çp¢òðC’¢^€’à· à´T0ý9Ê€@!òï=i¤Ð]) Œ· <w2]^¾PS@{°#e]À!7àiP$?@€¢a4·0D1$0'0àï;SSˆð°ºÑcî™Ñ)Si¶à{(S¿Éñî'?€S/—U@@m°]J°bàügKpðîC©ÿÉÿÉ)W!  ! @!~`¢`jÐ{i]<êC Ÿ°o@$2Wae¢ç¡­'DQ©D‘$gP$wr{eÀB](©÷ê'] @)24ñ{ã`uÑpwíêý´%({¢W¨þP ^¢!¨^ìv¨0w^kpe–)ÙpÞ¶ ¨nnCÿ@n¿W—)¬¨$Eâ(?zéé z¸0/`þsÐ$'çè C÷;]¢_a]Cæ×åÉ Pw CSÉã ÿÿ4/ô×Üqe@%W*¤(ÐK!U ` g°ö@À¹ey  ])—Ö€!W(Œ 1% ࢰ”à÷)$!à î;e=(­!¨Œ@r°Ù^p¢!œ0àìX}ðáÐÇð)yo`$ÐðþJÐ@)¢©ñìÏ]*SưÓÀS%ö°^2ëÀ$¢)n^làì!±À!{`þŒ’2)!^œ)œÿ@œCðí;×±±*; %·Ð Sß@)W@^¬À¨¢û]ï,€ ^)O±³—n—Ò $@z`]ÿ@]zïîwñ^°ìð{`¨!22ü p@`(¢Žîî;¨’ñév÷©à~ª€'íî‡Ðà¯!œ)W>€—™Ð*þ\Ðiiwìí¿]UW—W*ÌPŒ÷!!¢• ¢œS©ÿëíCbŒ2ÿU2¢S(œ^@ÿ¢^¨¢'wéÿëw'¢^S!ÿ±—('©'!;¿çé'œø°z?áéCÜSO!OJ3A5/ôØ1’<õÎ Ÿ|K•éàwN']µH°Ínõàè„@…`UUÝ$¥€WSCÌ€‡ábÎP`(P©ð¨¨f¿U2 n'w€ ;OPry) *ÀŒa `Þ *n;ð Їnž—WrW¾ÀYâB¸z±Ü`NÀ!;w» ñ#;OyžáUžùSÅ’¨ð42r2U×rW2½€]rò&µ—Wž@||ˆðǨ22çaÛðWUþ“@Wy*24r!/!'CøH`zë6‡**WyP`P¯@ÝB2^NÁW¨2OSP*£À½‡ta‡¢WOa@ÿ@@!—)±@±÷@)$2€±ž|ž÷)! â)!*$ß@›–S]G`+;k%)**?$Ð~àú—¡*J0ž±±ykèù~àr @ASwû?ô,S)—ÄЖ€üù%Ðk !±!]kW!y|‚Q'°ˆpüàSÐ!wüõ-!zi Á¥ Ðkö ¡Püú Q`!|±WU@Ÿ—*!SkʰÌP'Âå¡;;€ˆÀÛÐðy)û^)`U!yU)o(!!|Á)y€QÁ]§p*²øäЗW{–%PU*r—¢ï| R—d S|!×UžžŸWé€!¨››‡å ,z¶áíb%¿r@!O@2v2áyËP*p‡ Àžy–ç)@¢~à´ ó)Cyw’PµÐ@*O)Uù*“@ ¨!y!Wó¨*Š fp)@–]û^wÆQwie)!þ½—42*U44¾È`±O*W› ¨þS ¢)O@@›!NïPð%'¸Ðt@¨ˆ@z])Þb±*@$¶”À)¨ nwÿ±CÊ×`)Wà`.q‰@r÷¨±2é€@n¢*ÿ%–W)]›4$ÿ;ùï$w]@¯@ rr3¨5Á¨Ï¨4*$ËPÐ|*Û!@Ì@~QÀ"]òËP@)`È›2O4¿$!^±U*2ÿ)$@*U)*–û'÷³À‡@SW^þ?@2±›O¨ ÿ 2›)O›)Sý±˜`¨±r@@'æ×ÀSQ@^SÝOeS%2‡ÀnO¿^¨)OU¢S!ñç;yÝ@+`W2!ý]"ÀS*U¨]nï*O›W (]‡òñS4±7 v)PW*ëð›2 *pÿ›)*O±O]SÿNðñ]r@?Wr@±W—hÀzÑé*0· *D€<ïgñ]/À‡ *± `ÚxÑ%: ¨SqÀ'Cÿîñ;—!–6«€)4€))>`Àý*ÃÐ'ìðS`¥€à5 QÐV@±£°wëðr𣱠àæ}à%@„ »àwêßïz2S“!–öÂ0((¦Á¢SCé¿îz‡'5àw{‡'¹0$!%Fô0_å~b~ðåJŸüŸ$ñBOOM_ÿSPLSAMPw‚)â@)àÿz.Å‚[kÿ™Ggw²¾Apÿ~”•–’¦ÿ¤¢¢ ¢¨®¼ÿ¸¼¼¼ºº¸¶ÿº¸´¶¸´´²ÿ²°¨¤¢  —ÿ›‹……‚ÿ„}wwsw{ÿ}|imllnWÿQSUWclp{ÿ†„¦dÿdOE22 þŸá&6CC>IÿI>AGS___ÿafhaq{ƒ…„Š”‘šSàÿ¬°´°°´¶ÁÿÅÅÁª¾áÝÝÿÉÍÕñåñùýþÜáùñíåÙÑÉÿÁ¼´ª“…ÿvpica[Y÷QQQàKGMYÿ]je{vpe[ÿSQKIGGKOþ‰à_chpw}†ÿŠ˜  ¨°²ÿ¶ÁÁÁÉÑÕÙûÕÙ-ðÕÑÍÍÉÿÁ¾ºº¶°ª¨ÿ¢›–“ˆ€ÿ}zsspmhhÿb]M>.2_ÿƒŠ‡wmkpeý_öàOKCOEWÿYY[S_flgÿhfdaUQUSÿcdjxy“‹ÿqntŽ ®¾ÅÿÑÜìüüøÔØÿ¬¾¸“ky{Mÿ>dƒ¢™‘†€ÿulbG3>ÿMdxŒ¨ÉôüÿüìÔº¨uirÿ‡•¢®ÁäüüÿðàÈ´“eA7ÿOd‚¾ÜÌÁ´¦ ƒ{sh@ ÿ[[ahhjuzÿ~…ˆˆŒŽ‰¿”Žw‘°\àºÿ½¶°°°¨¦ ÿ›„ŽŒ‘ÿ’‘Ž‹„}{ÿusopiW'ÿ7I]p„¬ÐÔÿ¬x|‡ˆŒ–ÿЉ‡®»®“ÿ~dQ;' þ3#+7;ÿDLUflx{‚ÿ‘œ®¬³·ÄÌÿ̹•¨ÀØèøýüY Øš˜”Žÿ•™ÀÀ¢‹rÿbB#BJB33ÿ;7337;B?ÿFJRW[dipÿy~„Ž˜› ¦ÿ¨­ª¦±½½ÈÿÈÀÀĽµ¹±ÿÔÀÄÌй«ÿ¯œÔÐÀµ«œÿ‘„}pjhd[ýahð[[WWVVÿWPTVWTJNÿVLYYkxw}ÿuv}spunnÿrpupuuysÿpvz}yƒÿŽŒ}tr šûš’kˆˆƒ…†ÿ… ¢†ly¤ÿÄàÔÔÀ¯Œ“ÿ›ž»ÜÐÿ»µ«“‡€_7ÿDZu‘©À§»ÿ«­©³œ‚gmÿyui]]\_XÿZlbl]m{uÿussŠ•§·Äú¦ØKÐÐÄÀ½ÿ·¹£±·½µ£ÿl^L;7/û'#e'+/37ÿHJP\jgyvÿƒ–š§§­© ÿ¥±½À¯À½Ìÿȳ«ÀÈØÔÜÿàààÜÜØÌÀÿ·¯£Ÿ•‹„{ý| ðZTRNJ?ÿ;;;7?;7XÿeeVD7+' ÿ #++ÿ377;L^JFÿ^{¥³Äïû÷ÿ÷ëïÛãØµþEÐÛçççëëÿçãßÔÐȽµÿ­«½È»³š€ÿn\N;,,$ ý¸$(0;FÿR\fpyƒ“ÿ•¥¯µµ¡˜£ß©µÓ÷ú!ïãÿÏÀ¯¯«£›‘ÿ‡vr`\`ÿPdj`a|ovÿ—ÇÇŠˆ\JÿTNfyœ¹Ç¹ÿ­—ssrkZ@ÿ<@LRgxŒ–¤œÿ¦¬ÍÜͽ¦‡ßlR:'#¸ÿ ''/6ÿBBNW_aRPÿJV}‘ŒµÉ¿ÛßçëòöXDîÿãÛÔÐÌÈŽÿ··Ìº¤}~}ÿ|xw{xzÿ™Œ|oeXÿTNNE3ÿPd—¥³Á×ÿ½¯¸³ÄæÐÁÿ褔†oaTÿIIGEBKNVÿXVX]hoq~ÿ€Š“’˜š¢¥ÿ²´¯½Ä½½¥ÿ•ÌÞÓÏÌĽÿÀº§¢“Š‘pÿMRP_„¯È¯ÿˆZKuV_nhÿjnntux|vÿ’¡šwaG4÷,óI,VŒÿ©¸ÓÄÀ¹°©ÿ£¡§§£©¬¬ÿ¬²²¶¹¸¸²ß¬´¶´¶¼ÃÿÀÀÃÏÇÇÏÚûáÚj ÎÎù¶ÿ§¡—‘Ї†ÿƒ}‚ˆŠ‡…ÿ|{‚„ŒŽŽ’ÿ”|wuvwrÿuz{…‡…|ÿnkifgiibÿblnjid`ZÿX\XS^dbWÿ\vUWFCs”ÿ‹•¦±¼ÃÊÒþ.ñÎÊû·¬£ÿ˜““¥’„jÿqwO#*1plÿ^SD<1..*ÿ#&.5*9Lqÿbƒ”¬¨µ¹ÆïÎÕàãßãàÜÿçòàãÑ¿¯¡ÿŒzhUG=52÷.22x0@@DPÿLRYSLDDzÿ†­»ÊÔØûçñðQêæãÜÑÿµµÂ­»³œÿ[]P='þ `+9iTmYl¿vƒ“–Ÿ’³ÿ¾ÛÔœ˜»Æÿ•“jl~z€ÿ‚†‰‹«¨ÂÿɯŒyx_VÿMGIKTXbgÿt}‹‘…{zÿotsq_PA>ÿVYbv‰–ž—ÿ•——˜›ÿ˜Ž‡˜ÿœ–Œ‡‚‚€…ÿ†„‚~€{ngÿu…Š‘šžŽÿ›© œ…t{ÿ³Á®£ÄÒÀ·ÿÖîç¹¥®¬°ÿ±³®¥ª½°™ÿ®‰ei^?;ý&¹*8ÿ5CLI<1*'ÿ'.8CKNWdÿmw|~‡–¨¼ÿÇÇÃÃØÕâíþØléÑÊÔÔʸÿ°­¨£–yÿ^@/6G\`c¿RG(qÿ9=6/%!,ÿ%2h}xY3ÿOn{q[Dmÿ²Å©’‘«ÿ¦ ¸É¸ÿ©±Â»µ˜ˆÿ‚{y~‰—»Ìÿµ›ŠbQfl_ÿObS0AHSkÿ|Vipru|ÿzq}Š ºËÜûæêcpÒ¥€]QÿSPHABH_ƒÿ†}{~{mM;ÿ18H]·º´ÿª¢ž–œ¬ÿ¥™‹•¡ªÿ¦¨°´´¶¶°ÿ«²«¨¥¥“•ÿž›£ ¨ «¶ÿÊÑ××ÔÑÊÃûÇÀšp¨¤Ÿœ¤ÿ®™sVAÿ4''$$!ÿ!+118ARÿ]Y|€ƒ…‡lÿxŒ·¾ÊÚääóäá]€aƒà×ǽÿ·°¥ž““’ÿ‡~yslf\cÿ{xfVNH<5¿,5?<95‡€?ÿIEILQ[foýtFˆ‹ŒŽÿ‰’˜™¡®ÃÏÿÉÉÏÒÒ̶¶ÿ¼ÃÆ¿¶©’zÿo‰°¿Â³¥œÿž‰oL@36=ÿr¨Â³”xkSÿpgUf‘‘™ÿ™‰˜‹‡†yÿ_QJT'$'GÿJRj`T(4Jÿk£»µ°¥ š––¢²¾ÎÑŽÿËÈ×ĸ®©šÿ£µ»°n`]ÿ\VDAMWWDÿ2%&5GSav““‰Š”²¸ÿ±¯ ‡|~Š“ÿ‘ž§±´¬§ÀûÙß@Ö½¯¯Ìÿß±½±ºÒßÕÿɱ‘V<69039>;J^dWHû97Ì·>MR]cÿizŒ¦¾¼²­û¢š¤ …†}rÿiWFFIS[nÿnod^dadrÿ€|x‚’ÿœ¥»ÂÄÂÄËÿ˺³©™‹ÿ’Žƒ}xrprÿvzƒž‘ƒ‚ÿŠ…„„…‘“Žÿ”¥«µÆÊÊÿÊÈ÷£ŒrlÿflwŽ•™¡ÿ¦†{sjy“–ÿ ¦›ƒj_jn¿sk`M[q²0\ÿ]g|„~{’—œœž¤¢’Ü0þ¶ ™‹yš˜œÿ¨¸³¥–™‘ÿ‚‡}lslkoÿ€œ”…u_ZEý<”À:?HLSZÿcr†”“—“Šÿ€„|p\M=?ÿDKQXjgTXÿXft‰ž´ÆÆÿ»«§¤Ÿ˜£÷žŠ€e°’Œÿ”žœœ¡¤¤¦ÿ¦¤’ŒˆŽŒÿ~v€Žžšÿ——›‰‚{ouÿ~|xuw~{ÿxvpnzvzrÿrqmjeo{„ÿ‰ ª¨—›þÜ0šž›’„ÿvsu|wssÿokv”Ÿ£¥£š”Žž™›ß”«­§§`­±ÿ­¢§¯µ¯›‘ÿ­ÀÀ¯šŽÿ“Œ|tpkRPÿDL[dbUSWßY`aWJàQBÿ@B@JYhnuÿtu’”ƒvÿ~Œ‘š¤“ÿ”‚vmb_UÿOOSVXZZ`þ–€sprz‡‘˜÷¡•™ª µ¹»»Í¿¤Ñ½·£Ó¤Ñ¯«ÿ¡”„ui`]ÿRJDDJYerÿfbgimiquþ-`ƒvv}ƒwïapnrG0bbdïelkyì°iƒ”ÿª Š„…†ÿ‚|ywrrlgÿdghecdgmÿt{…„†Š‹‹ÿ‘›žš™˜šŸ›£©«±XáYà²ÿ¥£Ÿ¡Ÿ˜§ÿ££¬¨¡–‹Œÿ£ª–œ™ˆÿvlhilmlÿbOHHQQJUïy{ut{ tqlÿcelrtmv…ÿ‹Ž”ˆ‚—“ß–šƒkkiPrsÿnwlMKZagÿog_]XOMQÿXal}„‰ÿšš–“˜žšÿ𩵰§ª¬³õ¹–á±'С¦±¹þP¸·±¯ªŸ™ÿ›¡”†|mdfÿ`]UTRTUR÷VWK¿áMPKKÿPOV_jifa÷m€‘+Ѓ‡˜ÿž‘𑙢²·ï¬°³° Pž›œÿ £œ™†ˆŽÿ•š–Š{z‚ÿww}sgaaÿ\aZZZYMMMP^k}Ÿàÿ–“”—–ŽŒ¿Œ‚|‚›yÿtv†ˆ…{ÿy}yy}z{~û‚€L0‹‘—˜—ÿ……‹‘‘ÿ‘š ›–”ÿŒ‹roqsÿror}‡•™–ÿކ‡’™¥¥ž£¨ –Œ€ÿ‚…}teYQOþ{ñV^^YSQSïY^ci—€~€ûƒ„]࡯²±®¿Ÿ¤©±² ô°ýª ñª ”’…ÿ‚xmie__ÿa\\]\WWQÿOQQR\ail¿omhott’Ðzÿ{qz€ˆŠÿ—››£­±¯ÿ¬ª¦¡œ››™ÿž¥¨š‡†‹‰ÿ‚zypnkgcÿZWXTRRTTþÆðbec\Y_eÿkpuy}‚…‡÷ŠŒNP“–žžÿ›–Ž”—‘ÿŒ’•ž›žÿž•–˜›œ™˜ÿ—˜˜›¢®­œÿ’Š„‚„{t¿loszzw±0qýq`Pkrplicÿbb_]l|Š‹ÿ‰ŠŽˆ|v{ÿ}„Œ‘–ÿ›¡ª­«š’?•›£•r`Cðÿ”‹Œƒÿ|xvx}††ÿ†‚wsx}|ÿylcYV]amywqrvy+0ÿ„‰‹€xÿ}yvsqtuqÿle^VWWW_Ïiz‹‘,Ð猉ÿ‡‘‘‘—¡©ýªà¤Ÿžœ•ï‡}ywÔЇÿ‹…ƒƒ|zstÿ}sru}ƒ‘’¿™™’‹Š=PŠÿ‹Š‹ˆ€z|ˆÿ~}{tjkÿojcejddqÿmhiovmsqÿlovyyx|߈‘‘‹Œ7¥šï’‰{²0eb_½[M\gjp×0~…†ˆ‘”–¦bÿ”•–••˜šÿš—–—›™˜˜ï™ž¡¯ ¢š‘¿‘”Œ‡‡\PsþH0z|~}}Šÿ•“Œ‚~vmdk]^ž]¢crÓñïvociÿÀrt|ÿ€„‡‘—›í£Á¢¢Å££œþOð‹‡‰……€xÿpclpyxskþ—€xx}„ƒ‰‡ýƒ¹„„Љ„ˆ»Œ‡{ {{yñÐ…ý‚Kàvwvtnnÿnps}€€{rÿqv‚ޓމú à "”……ý𤋆‚}voÿlfjmorswÿxwvuuwvy„…ƒˆ”šœ-ÿš™œœœ›˜”ߑދ‡‡| rqíoÿÐcdd(ejlÿmpsx|€Š’ÿ‰‰ÿ’‘ŽŽÿ’”•‘ÿŽ‹‡‹’þU ƒ€„€‡ÿ†ˆ‡‡Œ‡ÿ}xyytpffÿfkrrontyýx‡0py€€~wßmrwyyS€Ž”Û™–r€“‘‰ “ÿŽˆ‚ƒˆŒý‰;ð‹ˆþ‹‹Š‰ˆ‡|?vu{|z µÿ~|zvutqqùq7!3|yy{zïz}~à }}|ÿ|}z|€‚„†ÿˆŠ‹‹‰€x}z7‹„‚1ÿƒ…„‚}xwwÿvwx{}}}„ÿŽ‘‘‰ˆˆˆß†€yw{X…ÿ‹‹‡‚ƒƒ…†ÿƒƒ‚ƒ‚€}·yz}Yp0{Ö0{z~1y†2|ûÑЄ‰Œç’’‘r€ð‰‰‡ÿ„†„ƒ„ˆ½‰™€{wu0xô€1î }|zxvÿssppoooqÿqsvvurpp¿u‚ˆGðŽ¥‹Ý0ŽÞ0é1ï1¹‡(Àž ƒƒ€Æ0vïtvvxF0wstouvy~ÐÐ……øÞw0†ˆŒ@Š=ˆÿ}€{ŽðöÐûxz2xy{||ýz1@yxx{€åo@y@J1€ƒ†¾îƒƒ„…„Y‚þ\@ˆ‰‡‡‰ŠŠo‹Œ80€v@ö4x{@††„ƒ;~L@wtsCÉ sz~p0Å0wy|0v‰Œ©B‹‰†j@»‰‡¦ ŠŒŠ´@„:h0„¨0~|{0à f#0}~È@,@<0=A6#Àz0€H@ŽðîA}}~€Ü@Úb@†…ˆ‡˜†Šø¼@õ Q…„ƒ3|yI0‡0|}(PK0{‡0‰@6Q30~0&PÊ@{}{•@{|}z¶@„aAƒ„„‡V0õˆ Q…òІƒ‚Òî…QQ_Q†ø0~?„‡‡„=Qã@T\ƒ2}íA€mPƒ«Ts‚î@)P~‘0€þiPPY@WSk2´Q€ñ@}ð@»PI@~`ãQ¸QäRöR}0{|äQ€[ÇRÄR@hQøÑP‚ ¦Qy0uAêP¾2z6a`z0Agî |LRx0ÙðbBAa@w0ô@ÐAÍ@z00KPÒB¾2bAdô@ÿBaaÊSbBP•bQM0»P“aŽcI@ÏbŠfü@b‘b%c²bbAXA³còcgbèQÔc”bîBŠd€c½b¤Q²díbuAôBÏd¼PQ¬U¯Sia÷@-q-qÒA‘a¶b>sr~d,räS9vòdÌQˆt•u¼dòAArˆŒeü>ŽH‡~propÿNAME ÿDEATH_SPÿLSAMP%]-Ì‚@Ì€%œô@{è‡û‚êŠýˆù‰ý„ìþùa€„ vqvÜÿ…þ‚vvq퉄›€‰ô@vq:÷†€½qV{‰„Ž3‘{_vmmv{5€;þvvqm{‰Ž—ÿ—„’‰„{mhóqvî9€„Žhÿqmc{މœœÓ‰—RŽqS’{€ÿŽhmmUqŽ€ÿ—¥{œ’„€hÿcv{’‰€qhÿm€—’qhc€ÿ¡‰¥¥€œŽ€ÿv^hv{Ž„vÿchm’—mq^ÿU—’‰ª‰{œÿ‰vhP€‰‰‰þÂhvŽ^hZPÿvœ‰¡„q’„ÿqqZh‰’—‰ÿh^m¡v€ZKÿŽ¡—½¡{¡‰ÿ’vZZ€‰¡‰ÿ€mq„œ^hP¿P„¡œ¯—k{{qZÌ‘‰ccvÃGB{’¡Â„% ÿq{cq{Ž’’ÿvhŽUmZ=Pÿ’„ªª’¡‰{ý€þq€vhmvÿœZ‰cGh‰vÿ¡‰qœ€vmc÷h€„ôq€Z„ÿUBqœ’ÂŽ€ÿ’„{ŽcZvqÿ„ŽqmŽŽUcÿB4‰—¥ÐªŽ~OvhZqqŽÚÿœ‰PmB=„‰÷ŽÇ¯] v€mmÿqm‰’{„—‰ÿchBK„‰ªË×´¡—Ì ^ 0‰’ÿ„‰¡GmU/Pï{„¸Ë9 {‰{ÿ^mq‰‰—ŽŽÿªh€ZGq„’߯’¡{£ qŽÿ‰ŽŽq‰ŽGqÿ^8c‰‰¯½„·¡’v¯‘Ž— ’ÿPh^=^Ž’¥Ì'°ã v„fÀ5„—ÿqUKcœ¡´½?Žœ„m€hÆп‰’^m=BE°Â›¡€Ë¡Zc™¡D°P÷ZB8¤¯€mŽ×’€€ž‘„Ëqcÿ‰GP’¡—¸cïh‰„q±¡vcÿqŽP„mBm—?œ¯´^„‰ê °ÿqmm{ª{‰^ÿUŽ¥—ªŽm‰ÿ‰v—€’¡’c÷cZŽ PP¡´?œ¡qZ{‰e°ÿZU^—U€GGÿq´ªª{Uv„þà°„¡¡‰m^cÿŽc{Pc—ª¡û¯c°h€€—œÿ‰qcq’qqPB‰œ¥¯—mw°þ÷°¡——cc€€ÿU^KUœ¥ª¡ö {vÅœ—„mÿm„^v^Pv—ﯴ¥hw’—œ¡ý„,ÀŽ€mBvŽ÷¡¯¡e’vm¡œ¿¡mc^’ZL —¿¥ª´„^{/ mî?ÀŽ^cÜ{Kqß’¥ªªc 0qmÿ’¥¡’m^mŽÿm{Pm’¡¸¸ü°Ž q¥œœvcÿc’ZcUG’¡û¥¯ŸÀqvvm‰ëœ¡+Àm‰ÀGqŽ×¥ª¯ÁÀq/ ¥œÿ—vmhŽ^€Pÿ^‰—ª¯—q‰þrm¡—œ€^hÿ—vU^BZ—¡÷¡—h. mhvªÿ¥ªccc‰P€÷BU„ Ðmh€{þ•Á¡œ‰c^vZÿv{K{Žœ¡¡ùcz¹ ¡œ’mcÿm’h€UK—œöÖc„ÕÁ¥¡¡vÿ^c’{^^Gm¿œª¡‰cm¬vÿŽª¥œ{hcŽoZ€G^bÐ¥hÑûhv,Љ^^Ž€ÿ„hB„—¥¯œüuÐïÁ¡¥Žch„_„Ph=UwÀ¡ªÀëmvwМ‘Ðc€U'€qP„ÐÑm9Ðÿ’hhv’q{Gõ„AÑvÉ‘mq¡¡ý’×^vBP’¿œª¥{mvãÐq¥—†Áv€G߀’ªª€ÒmŽÿ¥¥—hccœ^žÀ ’—¥¥3uÐhülÀOÒ‰ZB’’ª_¥Žh„q¨{AÐ÷chh§°=Z‰¡û¥ªÑ mvcvœ¿—¥„cm„­ÐGe„"à¡~ °——× ¿cqœc„G/°¡¹¡4(àmœ—nÀm¿—hmKGvÑÀ„?h{m€€qeà+À?c{Z„B^ÑÀÑßq„vŽœ¢°^m‰¿°Bމ™Á³°„÷h¡’±Á‰„Uc¿=UŽœªœªÀhW{c{¦Ð^1àZÛÐç„’¯áÐù°„vœÿ’¡Žcm{’vŸ‰KvŽŽQà5‰ÿhœ’——hhq¿„Z€KP—Öà„hvh‰hm—Ðÿhh‰^cPGm퉼Àhvžq’ŽùœÏY°€Uq’‰÷¯ª‰ð€Žm’’ó’—¤°¬ÐPBŽ„‹¥´À^¤±–°ïÀUžòª´ŽvZ°šà—;¡œ}À{h{-ó¯m‰c‰:ð{‚PßvUP’Žtð{mî=᎗œSðvPqumÔá¸uv‰{ä°üθÐqcG€Ž—߸¡{€hÂÀq—ö°ÀvqžPc‰—i¯*°ÀqÕ ’€¡ÐÇmvZ°1ð¡ €mù„Öð8hUcKZ·Ž—´2ðqqð€Ü¢V^{Kþн¸È“Qî—… ·UZî¨àª’‰«vm„s‰—gÈðKU„%°Ôúçðv°’q ZqÿcK’Ž½Â¡ŽôðB‰àcP^Zž𜸗‰šw°Ž{‰’tPhcZNàÓ½¥¸°œ±‰¸²UZŸ^Pq’—: H€¼°Ê¡vZhm)¡´¯ú p¦ðÿ°yŽœ´S9‘ø‘º°òðÀw¡¯ªl€„{M‘¿{vcPcZ²à¡%¯jàUÿ Àðœ€ðõã^ZoàlgðmU^wh€ŽpŽœœÎùh#ð™ ——Ž€h÷h^€  Ž—’m¯hZUhCáv= {½Z5 —¥—œTh?BG‰—´œÉ°•Ðöyà¡¡ú €v€PëPZwÀŽã°’vU¸Hü°B°€UPQ°¥<ÀÀÊPPmœtð<Àï„^Um4À€{mÿ’{mP^{¥¥½¡ð€qhPhÿÐ’=€Ò ZUZ‰i éðŽ^GZŽ¥¯ôÎáàUP^ à𜡟{PZh—ÞÀÌ’yZÀšÀmv¡— év‡hœ|Ðc{¥{Ž{„cZco້q´ðmUKæÀ’w‰v‰<ðZ^{3°ÿ€€ŽŽmZZv–?Áv€TZ…á÷’ß’cUU’§Ðvh·„Žm†ðœ¥•„ÿ’€PUv¥¯¯ÿq^Z„{hPqþKÀ—cZ{v^UŸq—¸´œŒõ{Oœ¥´œïÐ3^q ½—ÞðmmZh4ÀŽþKðqcUhޝ¯;¥mþ^U{wÀôÀô z ª·ðZchUŸUm¡¯¸& ©ÀZ¿q’´¸´vò^?P„œª´ªÀ¯ üÀÀch^KPmÒP —X ™ mŸð¯v­^ŽU€¥Àª hëPKÈ ¸ZÐh^BßPh¥´¸â hhGUv¡´´ŽoÀt¸ô!¥ÉÀhUPÓ!þeÐhcBUŽ¡¸¸~ ŒÐ˜¯´‰‡ hGc„œ½½¡ Ðþô𜪽´—^hßcP=P—’v~ÿ°=^‰¯´¸0ÿc^G^„œ¸´ó{c‡ £´¯’^oqvcK ¯¸0ÿvhKKmª¸½÷‰^ZKàGcª¸wÇŽc­Ð^KhPõª° €`€¥Ç´ùŽ ü€¡Âª„Ü :m’´~àc‰Ý¥ñ Žª¸SЄ¡ÿªZU€œª„^ß^v—¥q7—œ}hÉð¥¯vK^ÞàïmUv’Ű^hqmP–ªªgð„^»ÿ——¥‰¥—ŽBëGP»Ð„YàœvB÷Bhc°À€Žq„÷{PBJ¡’{œÚ¡¡^ãÐ¥œà’—žˆ mŽœhȰ¢hzŒ qa@¡—’œ•¿h^„„’’™ œ{^UPhM@°ZÐqKGàH3°Ž{^Y ˆÇœá<ðc ’ñ €tï s°‰ ЉvZ—0󀡰{cUm"*Ð{Cz‘æñ{„†°›‰Žàm{u…‘‰yhrÐÐŽ—¥œâ Íàv…ŽÐd‘@ÐÞÌ ŽŽ{{ÊvmÝŽ+¡ÀÐGÑ“ñØ –‡vc€sA\ .°{?‰€‰’‰{Ë´àZÀÐ{\@¥—GÀKàß{‰’ÇÂáÐqU¿4Bh’½ªà—×m{^h —õÀ‰¡?ªcUqvŽŽ w@щÿÐÎcàKÆà¸¸>8ÐP¡¡mª;°°ÿ%=UG¥¸¸´û’h”@’¡´Âªÿ—v{¡*K=P몪ë Góàv¥—n½ÀUh¡5Z¯¼ÁéP;ÀwÀÂ] qv=cPPŽªªŽX ó{q:°E Uc’€þQ¥¡´Ž„^‰þ“¡¡ªÇ—Pqýœ^PPq¥¸Žv³UUw ŽP´Ž’À—·hUKõÐ’Ž°€õmõÇºà‰„GUsUZÕ :„vZYà¡{^KŽK—?¥½¡’PUV E°ß´œqKK÷PUí¡&°vP[€—Žÿ´ÂmB^¯^^wZP{žPvKmV _œ’œ¯€‹`¯ ï{¯´€äÀ„€c~F°´qU8U¯† Z¸´´¡²  ¸ÿ¥m8c½€UhßZvªªqOÐŽŽßc¡œœ—I0U¯çPmcð°PcŽ’ý^ÀªvB4Z¥½¡¬0¯ª¯v“—ûœ{à¥m/h^ß¡ZZKh¼Àqc¦ýÀq—’' ^GZ;^¥ÊÐvZ’7Àœïv^*Z'@ZG—Ó—¯Û{9ð¯qý/š m„Kc¡¸íœ)p’’‘€¯vÞЯvqBŽÐ¡Žûmm_°¡’„¸mß8Bv’G‹0ª´Ï¯„hP² @¸’c^Z‰Ufp›eÐ{œŽò‰œŽU¸GmZB9à\PÙœý„7 „hZŽ={nr`´ª¡Àp’{ëûŽ’4 ‰BhZG¿¡ª¸œ’c™@¥µ—‚`P ^G À´Ï´—ŽqͰ q„¿q^P%4€®°¥¾œÁ’€½Ç¥Ô°Uü°ð“p€Ž‰ª¡^E‰º¡TÀŒ°€P’N°éKéÀÃaŽé—Ž—ç{Kc;®¯¯¡òUŽ*œ°^Ph4½4ìÇ´ª€lp—7{¸ÂëPcs@¡Í„Ø—’`З„îÛ ^‰U]à—ª¥v‹„ZæÂŽqBÏÀÿGUZq¸ª¡{îE`¸ªœPvBBqËÚÇZK&Ðÿ’€¥Ð¸¥’=¿P^mKU€°¡ï„4GBÓ°Ë´ý’f`ZBPq¯¸ÿ´¡¥„KK4c/‰ªÇÂØð^0þ¯€^GK88ޝûǸS`ZmK4^߸¸Â¥q¶À4^ÕË €PZ/ÿU’´Ð¸ZBÿc8=B¡ÇǪý—ž0U4h„ÐÕÿÇvUBcB8’ÿ¡ËнZ=ZGß/Z’¸Ðì BBßP8q¯´Y0PBÿU%*¥—¸Âª~N°=/=¯¯ÂÈPÿ^{U%q¥´Â¯P4*®°PàZÿqG%4—ª¸¥ý¯o K4m¡½Âû¥‰° /%Ž¡´ÿª—’Z„v/G÷œ¯Çà^‰h4÷€Ž´! PPcGû=¥„0ª’8hhß4^¡´Ç¤PZcûPKð€Ç´‰=8ïP/8¯0ª—BÿZUG^œ¯½´ÿªŽU^8=€¡>NcZUBKÒ @ÿUcq4K„¸½úHðP®pqœË˯ï€P=^}°œ´¸ÿ¥—GPhBB€û´ÇÈ0P^P=Zó„ª80 @U=hœÿ´Â¸¡ZPhG=PŽ¸Â¡œæãcKpPžP0àKP€ÿ—½¸¡vUZc×KG—I¡„ 48ïv´ÂÂ2€c^=çZ’Ëò€ P4v^ò¯¡U^Ä^2þ‘ÐZhUBq¥½Ô}P2PG51¯Âðhca4F0ˆÁ Â¸¾FÀ/c—ǽ/àm?qB4{¥Ë4|0÷/4Z3 —q€hÿm4Kq¸ËÇœý€fÐ4G€œÇ¯}’k Z48‰¥êPÿ‰ŽmB*=—¯ÿ½—‰mŽh^/ÿZ„¸Â¸‰vŽÿcP/U‰½Â¸ý’q@P%^—½Çý¸`p{G!/œ¸7Ç½ŽžÀK/ô¢ÔÿcK=K{´ËÇý‰KBc{ªÇþ÷ m{G8=„¯¼±0@àU=Kh ªçv^„¼ ê Õ¡hýK·0B^‰ÐãÇÿcBP{U=U{ÿªÚÇ—=U‰cÿGZv¥Ú½œGÿZ’cB=v¯Ëÿ¯„PZ’¥=KïZ¥Ðǹ@ޏ8ÿ8ZŽÇÂq^Uÿ‰¸¥/Kc´Çÿ¯cZZ¸½„4ïUq½½\à„¯ª?/Bm¥¸œ>ð´ ß/Gh¡ª®àŽ´¿¯€8Um——nœpB=P¨ð{‰cП¡GGKcV$ð’—mGBUó0j@@»m=«°´’‰ùð„ßv8Bh€êЯ¯nIÐ4Gc|ŽœŽðº™^7ÀŽvm BÇ%h‰ÊÐó + 8qÿ{œ’Uqœ¯¯ý’½€h{qG—¡Î¯€‰KZŒ!P¯ŽÔPôðq+@¥hGÿGU^½¸œ„‰žå@^Pm{÷ ` œ·½‰Bª—P¡ÿ´€c€qZ{Zó8cÆ09°U=4/ÿPZ´Õн¥výnP¯¯ª¸’œ„K/8qv½eÐû—ª%ðG^ch’ÿ{„´„h=8Ãcmd°¾pô@o—‰ÿ{GB^¡¸Ç¡ÉmÉ€ —Ü€†@4BûZmXÁ^m’œœÙŽBP©`qm_@vPÞ•À¥¸ª¯S`Ž€ÿ^hm½½’‰ÿZG44hÐÐÐÿœ€—B4/h_¯½ªŽZt04> ÿª‰m„GB/¿€Ç´´{Uø‘œÿ½Ð½‰hª4Gÿ!¸ÇÇÇŽZÿ„m/€Ž½ãœ’€^!!°ütòò0½¯½vhœß8==4cð¡hëh’‘ ´õPmŽ„/UB=ª½€K ÷‰m/¾!¡Zª¸¿*8=/ËÐL@BÿvmG’¥Ë¸¯ÿ€„½!G/8´ùÇl<@/{’¥ªÿ¸hq¥*BK4ïv¸—h €ŽPB÷¡Âœ  Çq!G¿PKÂˉœà^ÿ8¥¯¸Çªq—ÿ¡*=GPÇǯ¿¥¡KvK8À¸ÿ¯^€ª44Gû—Â!PGc^4cÿ¥¯œÂ‰^’=ÿKKcǸ‰ªhGPG8¥Â…pÿc¡v =PK¸å¸“K쀾´¥hÿ¥¥8Gh´oh—´^ÈÀ—ª‡àÿUv´!8=Gœ]½2 KqhÞ ¡û0ïZ¯=/Ï0¸—€g¡cKm L@ªœ `¯GK^ªK¥ÏP^|HДðq½¡8PÔ ÿ¥cœ—c‰mqÿÇœ’¡hGœU!ZZcÇ—Z´€ÿ‰Z4¡¯’´ŽßBcœPÛp½„¿œ—=vv8Èp¯ÿªm’¸4PPPÿÇœ¡¡^€výP瀸¯Ž{¸ÿZKP¸½m„¡îëÀ8œÇ0à^P¥û%¹Õœm¡U÷=vB»`¡ª„G÷´c%À´qœÿ‰=qc4½´œ¿¯¥c¡¯*là½ÿÇv¥¥U„mBþ%¯¯U„ÂBÿ=K¯Çq’¥Bßqv/€ªÝ0^m¯8P=€¸ŒpÿZPqGZ¡—„ÿ¯‰c¸PKKÿU´œh¯ŽKqï^4ª¥²p‰Â—ÿBBUœÇÂ{ªë¥vú@¯›à—c¯ÿÇ*PK^ÇËcþÙ0ŽZB´Ž€¸ý{×ÐPP8¯´¿c—„=vm°€ÿ¥’Z€œG^÷B½Â¯àUhh=÷¸½œÿ€œ½=8UGÂÐ¥—¡NPÿU¡Ç’¯´GvÿÇ=KP´ÐvÿޏBcm4{½ÿœ¥ÇZm¸4ÿ8G—Ç„v’Zßmm8Z½±àmhý¯JGvË¥v¡þóGG¯œŽÂq÷Z½4¸ÐªËª¥þ¡`vPŽ´¡¡¸ÿ{—ÇKGBGªï¸—¸ùZ€¯—’´P€Ë%X¿—½{{½PSmýªœ@UmÇ%==ëP’:°œý@8h´ÿ¥’ª^^¡/B÷BK‰P°—Zhqó8UÃ𠀡4KB-B¯¡UPP±ppÿ¯¥4BGG¸Ç½¯mmKœð—ÿK¡¯4B8q¸ÿ„œŽhv€Gþ'ð´œG—½BPßKc¸Â‰vZÿP¥¡’¡qUŽu45qk ’^c®p¾,p¥mU‰4ÜhïÕ¸„œæ0^4´ýª” G¸//K=ßcд’¡c ^GþW¡hœ¸=PGGÂ˯¡œ^a ì€Ó`Ž´5B¸Õ»¸¡'v4€oð´ÿ4Žª/4Pc¸ï㎥œÈ@BŽ´ÿ¥ª¯PŽœ4*ßKm¯ÂŽ• mZ÷K‰¯pZ¡4B×%GvÐàœ PUBÿޝªªm^v8þù‘Õ¸´€Ph„ÿZcŽ¡¡’c€½=ñZœÂ—Á {ÿvP´¥¥œvPÿª4UGGmÐÂ}œØ vqP¡ªÝàÿB€%ZGB{ÚÎd€Ghv2@ž c¡ÿ44=Bh¸Õ¯õ¡>0m+pª¥—^ÿv==8¥Õ½×—Z ðœè‘€¸ÿ8/*4PªË¯û¸€‡@=’¡œ¸ÿ¥¥„%/B=ŽýÂ) mUZZ’œÿ¡¥¥—´=G/ï=hª½ð€K^ÿv‰¯¡¥’Âv¿=44ŽÂ v¿mhcŽvª3@½¿/^4/UœØðmí—ªp‰„ƒÀËh8¿/=/ªËœ0{û„UÃ@œœZ‰4ï/B4„ì Ž^vúl`€ À’¥^=þa°½¥’qhU‰ù{|€‡ h8B/¹ª  h„ÂU€vßhŽqZ1 ª’½’ìЉËª=`´ë!U¾€¯ø hGKû„q q{K=*¼)qjh4Kvð°¸ŸŽ€UP ž`I ¥·{*PÁи½ê0cÿ=ZZ¡ÐǪ¿Ž=K^q€^œß€qB*x`Ç´—ZUKm{ª1ðÿŽm%84P€¸þ9±PPhm¡Ç¯þZÀ‰B88v¸ÂS½¯¿0ðÀ´!a‰=c²ª¡PUÐ0_ ?‰h„=P4ÔÊ¿ZmGc„Žƒðmÿ€GU4U¡¥Ç?¥¥ŽhK{:P@(p4UÇ‘€¶Q¦pô€ÿv{8UB½½ò8€Uh°–ª{ŽPƒ/ƒp —€>Ð÷€÷{m ’ÂË´ç’ZU¤`ÐáqŽ4õ!c0¸xq=Kvv¥´‰Ž‰UDý‰)¡q„m^^zM€¸î@—K48µ`¾ˆcBv‰€œÿŽPK!PZmªÏ½Âq’RÐñÀ¯’öW0¡KL¯ÂÇ’ö_à„‰æÀ—¡8ÿG^qÂÐŽUPÿBq{h’¯‰¥{G4h{m{p몪·ð{`ª„Žþ°À^^P^^q’߯¡¸=B&`„œöÚ0€c8cZcc³{¯hP)pm—ÜÐvïccc¤€¯Ç¡nõÀh—€“P¥„1À^¯ÚÐGZ=?п—´¡—½ŽÑ°ŽŽ¥.@œ¸p ®ðÅáîjp^UGÙ´½½¿Ž=BZ^Žªÿ‰vPUBUm€V6`´’mQh’Я=°ŸUBZc{J “€4Va°vÇý°ho ^QÀÿ’œŽ„„mPZÿZ„¥´´¡Žh¶mÐUZÃ@¡¡)pZ;q^h¸¯‰H€`Pߥ½¥¯„”°8€ï½ËÚ¸’ÁPZhýªªm4B4UvX°Ú¡B0ZGP+°õ´B10¡¡Ë¸ÿ—„mh=U4‰ß´´´½œyàKq뜴U0‰®p*P„-°¥mBG°9P¡p¯qP%‹´Bÿ=m—½Ë½Ž€ïmB8*®0¯¯´whU^ô°´ÂÇ4@ZZ8G{¡Âÿ‘_P==v´€œŒ`ù4ˆ`4 —m=UB}^S0½¥€cU´`鎼PÊpBÍ௪½œÕðKZGZÊ ª½’ ^m€¥nð„^hUPhÀÀ‚`P÷Uch¿@’‰{cwUcZ·A¡’vmÐßZc€¸¸ø°mc{^BsÀ˽ªm˜ ·B8{ °¥h:ÐBû8vó¡’{’mÿUGB—ªÇª’ë{q)pU“ડŽ]Zµ@GP€Ø0Ž?PïŽhBK7°’mBómŽêðR`¡{hh„œhhU„ª–ÿch€’mcm{‰—vhqv‰öp¯{cZ€þp{p’^ZK{’‰’€ª—GBK^„PÙœ˜@»`c€š@Ž„vmv‰qcqºÀßvh{Ž„°q‰ï€v{hsp„Ž’ìàhm§À€à1-€‚Pÿ„€ŽŽ‰‰„„>q‰„’Ž0Ð`x° ‘³€qv€’1pmmÄÀvœÀv{°pÓ„{ pç`vvp’„o„Ž€„†p„€-Àüú¡Ð`€€’œ{{êp‰³p’–`‰vh{Uc^Àœ’„qÎû€P­ð¯‰UZv÷€qŽ×Ðq€—vý„¼0Ž’¯’qKýq˜ph€vމ—4%€ €:À„„cp—ûZc× ¡„v{€ÿ‰mcUvq’Žz¬Ð„–p^’v{BpÁ„5@Qp¹`Ìp]€—œ}Ž%p€€‰{‰–p߉qhvv0v—°G€Ô@ä_p€„¨@{Ýma€qccЗvêæp{Ÿ‚—~P{€^÷mZhÀ’——Ž~¹¡mv’Ž—„ð çh{„ÓpG€q{qG€vœô0º`pŽî '€„vŠPpœ…€™ é{}p9€€Å`{Ž—œïÀmm„_€»€‰Ê³@q-pv `剒ׄ€q^0„’¢^À€FÀ¯ }P{¾qq7{Ž{9pq’x€*€¿€Ž€qcv(€q {S‰„Âqê€5€:À½vU€„‰€6p€^H@„€€vj€Žwv„Épw€‡¦ÙpwW{€{—p‰Îpq‡p:Àª{”pÍpÌp(|’ƒæpŽ0„ª’Øq‰˜ v{Võ€ù02‘5‰'‘€{€‰v¬Ðx €’;{Ôð8€Þp¨€Ã„’×pØqÔp:À€‰li’•’{{z€„{ ¢ÂpÙ€ø1{€€áw€„€þ‘4V€7  ¡:À{ÂU ]ˆ‘Õ@G˜’ÙpI€Ð€{”€0 Ùqž‘š’{€‘ëpsøb­p@¡Îpo‘Öq§Õ@‰ `ù0Íp™À€1 ¢x×{t’q6q¡¶¡Ìp%€ ¡k¢¡¯¡”€‰’‘k¡Ð€š‘±ýH@±‘²©¡°¡]¡p qÇ¡×pº¢ëp“£N¡Gý´˜¢¢™¡H€„¡ÀpR¢~¡O’p#³Q¡ö¡t²”¢1 u‘pÁp™“‘p‘s‘y±P¡a±}¶×µL±|³Ä¢Ÿ’J¢Ò£ÂÁ@²FÀ¯´²"”p™’^¡7vÎR€[I€•qM q{Œ€j€¿q«’Âq‘¡Å¡Ìqβ¶¡‰¡KÁd³Ô²³¿‘¢©¶ª²kU \ݱN´—‘Å¢±€±o²¥±ëp²£¡ÁoÂ\€óÅ‘¡ À÷±ÌÄÓl²Èê³ÓŠ¢­±²ú¢ҙö¢R²u²µÔÍÆõÃÕÓ”Ù’ÙT±ØŒß–Ù—ÙÃÞä×ÿpropNAMEÿEND_ïFONTá7Ý9â à > àÿ%á5ïGïYïkï}ïï¡ï³ïÅïÏæ/ïòî$âÿÿ(ÿ@:úÿãóï;þuÿøâï¥ÿ]ø¿ÿÑÿ#âqÿýÿ@!3EWi à”ÿ‘£µÇ¯ÿnùêpöøõC.XO¦¸Ôæø+ €+/=/O/ʽ†vbò’%Ùýk ˜!r*Zù×)Õ*—%ºþ ?Óó€”(…*x+_/Ìy?„7/¨?º?Ì?Þ?ð?OOc<3s*k.`öO>fOÊODLgjþ¬(7_RO[_™G/Nª_¼_Î_à_ò_o—?*oÿPÿbÿtÿ†ÿ˜ÿBßïÎÿàÿòÿ(Òß-\ ½ÿ€v¯ÚÝ¡ÀÅ×éH /DVhzí.><~yù|Kº,Ûíÿ/Ǿ©I<ÿ€/’/¤/:È/Ú/ì/þ/Z?Ÿi‘o_F?X?j?|?Ž? ?²?Ä?Ö?ô?OO®/¿¡ß³ß¿”Éßc˜¿ïõ®N¿ÙÏkï}ïï%ß³ïÅï×ïí¿û©ÿ¯%ï2ÿ(¿ýlõªZ(ÊÏrÛ¶ŸÈŸÚŸßÿñÿ £ï1C Ÿw‰Zl ãõ˜€ª+=õ³bÒ•§¹ËÝï//Dv¯=/O/rßq/e/“/¥/·/ë/ý/?!?}E?W?i?{??Ÿ?±?Ã?Õ?ç?ò¿ý?Oô?OOeOwO‰O›O­O¿OÑO-?õO__+_=_O_a_s_…_Ù.Ê/ª_¼_ˆ/â_Ö_oo”_Jo\ono€o’oÎ òOºoÌoëæòÙ²¯ü\ô_)Rcu’«ÈÚìöv©o,>Pbt3OÅ}È7/+o²ŽÑ¾{˜ôÚ¤ùÀÜ{÷“Û³úE¹öߟ“ל˜žRœ¸ŸHŸ¹ü ÿ­ú{óãÛï­éš€V¯ÆŒñ¬”«p¯Ï® 󯿿)¿d¯=¿-‘ï]‹ÿq#û¿²¿Ä¾Ý¾œ®œ­©¾ÏZ|u¾JÏ3o~ÏϢϴÏÖ¯ØÏêÏüÏß‘¯äÞÏû.Ïeßw߉ß9šü¿Cß™ßAÏðßì¾üDOzÏxïŠïœï®ïÓÏÕïçïùï ÿ°¯&߯ŠUé>îîkÿÿÿ¡ÿ³ÿÅÿ×ÿíý1oiÿWÿEÿ3ÿ!ÿvˆš¬¾ÃïâôQÀßIÞÐßdÿr6í¦¸ÊÜî/”‚pUï¼ßoŽ/ /²/Ä/Í%Òñ/??$÷j7<ëÿX?j?|?Ž?°ß²?¤?Ö?è?ú? OO@?BO cOuO‡O™O¡Dà/ÅO×OéOÂ=þM(O _2_D_V_n/z_b_ž_°_Â_Ô_ æ_oo)o;n´O_oqoƒo•oñO´4~­2-/ýoú_!3M-6ìd/oÿ>ïz®‚[Àn8E"4FXÄ|Ž ²Ä×éû ŸŸ1ŸCŸTIaŸOŸ…Ÿ—Ÿ©Ÿ»ŸÍŸßŸñŸ¯8¯J¯\¯n¯t¢y˜¯®´¯Æ¯Ø¯ê¯ü¯¿ ¿2¿K¿]¿ ‡¯„¿–¿¨¿@¾¿¿Ñ¿ã¿õ¿ÏÏ+Ï‹~NÏ`ϬWì¯o®ÏÀÏÒÏnöÏßß,ß°¿îoälâoQÿ ¢þro_Ñß¹m«ß™ß‡ßußcßQßA//Dߦï¸ïÊïÜï¥Oÿÿ$ÿ=ß•Mÿ_ÿqÿƒÿ•ÿ§ÿ¹ÿËÿÝÿïÿ _ÆoVhz…þï©»ÍßñžíïÅ#oê?ƒ˜{ÙhzŒÇ©±Ãyixì/‚Ì‚Ï1/C/&ìd/œ/®/À/Ò/ä/êÏ??,?>?3\œ_? ®{ÜÌÙÑ®:s.Ì?yê÷?ÈyˆÌOã߉äzì`Oe~OS?³OÅO×OéOî/ __1_C_U_ÙßÃoOéo¯p]&Ò_ä_ö_oo,oÀ_®_œ_Š_x_f_»opÍoßoño _*<Na_ò×{Ÿ ¯GÏ£µÇ}sŸiŒ/ 1CUgyš¬¾Ð_ôŸŸ*Ÿ<Ÿ¡o_‘_£_µ_Ç_3o»ŸÍŸßŸñŸ¯EoWo7MÉkš?êoƒu´o¬¯¾¯Ð¯â¯è¢í ¿¿0¿>Ÿ­®.î\?ˆ¿š¿¬¿ íoX¼_ïy¿¾¿%Ï7ÏIÏ[ÏmÏŒ¡Ï³ÏÅÏ×ÏûÏ ßß1ßòÛV¿#|ÏxߤO?ßJŸ«ßj›–߯ï+¯]g.ƒ¯èßvïˆïšï¬ïëÏÐïâïôï·ßwý‹Ï5ÿGÿYÿkÿ}ÿÿ¡ÿ³ÿÅÿ×ÿéÿûÿ @Rdv⚬¾ÐöwÏõ+=Oas…—©»Íé /ÿXÞOï_ïG/Y/k/}/鯔³/Å/×/âï!ï9¯joÏAM/mßÿŒK¡œ`oº?aA <"®ÙßìßÀO6OHOZOlO~O¢/¤O¶OÈOÚOìO]?? __^¸Ä?m¼èm]w_‰_›_”;æZ9µ]à_ò_.[è€Ú(oMZ>¡Ÿvo|o£oµoÇoÙoëoýo/!3EW÷/?=?._”?¦?Ú?Õß1OëÛ~po-;Œdl­˜Ÿ«Ÿg·ÉÛíºïŸ#Ÿ5Ÿ\ ï ?3?—j=pß’Œ¯;./ÝßõŸQŸ¯+¯=¯O¯@a¯‚¯”¯¦¯¸¯Ç«Ÿë¯ý¯¿ ÿ ýH¿Z¿A¿~¿¿¡¿´¿Å¿Ø¿Í¿í¿¿/¿2OQÏcÏuÏ~ÅÚ¯¢Ï=ç¸ÆrÓÏåÏ÷Ï ßß-ß?Û;èÏpßBßߑ߲ߵßÇßÙßwï‡Ï6ï¬Ïc]dïvïˆï@šï¬ï¾ïÐ»È /ïÿ!ÿxß:ÿ[iÒQÖŸ©_Õ_g­ÿ¿ÿÑÿãÿõÿ+=K þïo“¥·ÉÛíÿ#5GYk}¡0³Å%Ìä^É&%{þ=/O/a/s/…/—. ø»/Í/ß/ñ/??#ÈŸï¹|KØdU¿ÉšzP_K‹ƒ9Øw¿Ëç?ù? OU/OAOSO`?jO|OŽO\g‡?:N‰e_š?÷O __?ÏOÅM ¯€_’_¤_®VýïÑ_ã_õ_oo+oèy€;qÝŸno€o’oÞïÕL@l-oñoO'9K]¦Ot†žpùÎ4IŠR;1_èú lŽ^‹VîÂx±|u‡™›/½ÏáóŸŸ)ŸÏ=˦ÏÉoÛoíoé?ýo#5GYk} o…+™OÏœ†Goå÷ Ç3m±z¢|Ôÿk}ÈiºÌÞðŸŸ&Ÿ³¿Å¿×¿sŸ…Ÿ—Ÿ1Ï€CÏUÏ7Ÿ•¯¯'« ªU¯g¯y¯‹¯…jKTÖ[Ưدê¯ü¯Ço(¿:¾žÿ]¿o¿¿“¿¥¿·¿d ´­² Æh¶kÃm"Ìê¿@ä·'lÆozόϚÊM¿¾Ï¹¿]Œ1]‘ö9kß#ß5ßGßÙšÐÏߣ£ßµßÇßÙßëßýßïÛÏ&ï8ïJï\ïnï€ï’ï©OÕŸç˜æ»îïÿÿ…_6ÿHÿZÿlÿ~ÿÿ¢ÿIoºÿ”o™o¹ïÕÿF„(¨&)ÏJhzŒ 3ÿÁÓå÷ -?QPßZM™°æ‹ÚôÅ®èÔÒ-çšÉÆZݹkT \B/e/w/‰/›/=¿«/Ñ/ã/õ/??Y†K¦IOŠ É5š¿ÍÇÿSÅìà¿Z/ì?þ?&ÿ"O4OFOXOjO|OŽO2Èÿ@9Q?øÿ ¥O;@~?ö½F_€?+_¸/¦_¸_Ê_Ü_î_oÒ¸TÊ{?s^Co>oPoyotooÝ?ËoÝo¢ÏÔNeAS'¿¯2?›­}·šûo);M_qìúo©°ÿØêü Ÿp2ŸDŸVŸiŸ–ß“Ÿ¥Ÿ·ŸÉŸÛŸíŸÿŸ¯#¯5¯G¯µ>Õ=8\­J¯Ÿ¯±¯Ã¯Õ¯ç¯ù¯ ¿æ/¿A¿S¿e¿w¿‰¿›¿­¿¿ ¿ã¿õ¿ÏÏ+Ï=ÏOÏaÏ¿…ϗϩϻÏÍÏßÏñÏßßvÏ9ßKß]ßoßߓߥ߷ßÉß*ßíßÿßï#ï5ïGïYïkï}ïÞß¡ï³ïÅï×ïéïûï ÿÿ1ÿ’ïUÿgÿyÿ‹ÿÿ¯ÿÁÿÓÿåÿFÿ -?Qcu‡™úÿ½Ïáó);M®qƒ•§¹ËÝïPb%/7/I/[/m//‘/£//Ç/Ù/ë/ý/?!?3?E?W?¸/{??Ÿ?±?Ã?Õ?ç?ù? Ol?/OAOSOeOwO‰O›O­O¿O OãOõO__+_=_O_a_s_ÔO—_©_»_Í_ß_ñ_oo'oˆ_Ko]oooo“o¥o·oÉoÛo Ã/†?˜?ª?¼?Î?ý)à=ý1ö94ÿ2þ5Cb3)GG5OGN7bO`8*C…Eý8™Ké?ÄOÖOßEu?__'_9_™I–F…HˆGü)¾Kÿ7¹O¼JYZ¸\_Ù_ì_ð_CfYX^]FoXojoykt?œo®oÀoÒoäo¡_iu·_œW2z9K) Gzt[ ²ÄÖèäO 0B†_ƒvnj_`Z%z2Hy‰GJ+iϘ{Ñãúo#Ÿ5ŸMfŸxŸŠŸ½/®Ÿ_?͟ߟ³ŸµŸ¯'¯ëŸˆob¯t¯†¯ú? KGŽgZW¤LyˆÈ¯ƒª‹¿ô?ׯB¿½¯>¼œ®’U¯ã¿ ¯ÊÏ&Ï8ÏJÏ\ÏnπϒϤϫÃÒ¿ÏÏáÏóÏßß)߯nºe\ª^NŸ=¤˜ª*K)F.y4*B;ËßÝß¶ßIEí”ÞßkßWßCß„ï –ï¨ïºïÌïÖæ ¾Ïúï>ÞQJ›¦"ÿviŒ¥©{ïÿŸÿ±ÿÃÿÕÿÿùÿ /ASew‰›*ÿ³Å Íäö@(:L^pyòÿ¯ÁÓå÷ //-/?/)i&l _p/‚/”/¦/Ø/ê/ü/? ?0<Ñ¿S?e?w?‰?›?­?ï«h/ß?ñ?OO·Ï9OKO]OoOO“O¥OwïcïOï;ïß$·œÚ ëìÖ-_™ª9Y7µ:YYWœ×:·[íOLï^ïpïªOoo(o:o6?^opo¼?í_¦o¸oÊoÜoîo$ÚïHZlþ=¦‹z™oÉÛíÿ#5ëÿYk}¡³ÅרOîŸN-"ŸDŸVŸá&Ÿ •o«Ÿ½ŸÏŸÖ“OúŸv}˜˜ž¼1¯N.ŸŸk¯}¯¯¡¯åŸÅ¯yŸQ'¹[?ö6·¶å¨Ó¯:¿L¿^¿p¿´¯”¿õM±¾Ç¿Ù¿ë¿ý¿Ï!Ï3Ï?CÏiÏ{ÏϟϱÏÃÏ ¿ª¿ìÏþÏß"ß4ßFßXßZù~y奒v yÛϱßÃßù VÏïïzŸ»§;÷Nï`ïrï„èGé›êžÙÇ ÂïÔïæï øï ÿÿN ðßaÿsÿ…ÿ—ÿ²¿œÿÍÿßÿw¿ïÿ'9K]o“qÜõ®´þÿÞ˜“W¼'»ÿQcu‡@«½ÕY‰å7ùçù•wÞ[éYT¯D/V/h/z/Œ/Lϰ/Â/Ô/æ/ø/ ??.?@?Á;ûd?v?‰?œ?®?Ì?Þ?ð?OO&O0F©/TOfOxOŠOœOõ“=á̯ ÜO3_§ÿ$_[1¡ç6^q_(™|NZºKR«Æ_ûOê_o o2oDoVo>OzoŒožo°oÂoªO¼OÎOàO _.;_RL^ãZ¸v~åoõ_°ÞËù2):L^p‚jo¦¸ÊÜî/¡ gf†|UŸZ?®_#,Ò^h__ÏŸž_ŽŸÕ_¯^Ÿ 7q¯ƒ¯•¯§¯æß˯ݯﯿ¿%¿Úo>¿`¯2¿P¿†¿U¯+ÙŸÍ1ÿ³æÆ;æ œĤ[¿+Ï=ÏOÏÿtÏUÌvž>Ÿ¸ÏL}Å¿ ŽýÏé*‹™!¯DŸ_ßáÏŸ•ß^ÏÉßÛßíßÿß!Ƕßï0ï¼ßsÏeï¨Ï‰ï»Ïß¿ïßãïõïÿ9ßKßnßOÿÑï¤ß…ÿMï¹ÿËÿÝÿïÿëtïvŸ—¿¬ÿxïYœï}¯ïsÿ³ÿ× ÿÿ-ÿ?ÿ;CÅ-yE­¿Ñãêhªý“Í rÿew‰›¾Ÿ/óÃ/Õ/ï/*+N/?±/„e?—™?«?½?Ï?ñEî­/?(O[/P‰_~m‘o‘£µ%ÙÿoýËoV1ŸCŸL¯gŸyŸ"Ÿ©ïiÇŸo¯ ¯%¯7¯I¯V©Êz¯Œ¯ž¯°¯U‹LŸÞš ¹¿o¿½3¿E¿W¿i¿{¿#c4ý¯ë¯Ù¯Ç¯Co —¿/ÏY†:o¹¥i£ê~ÏϲÏáŸÇÏ®ÏëÏýÏß!ßÃÏâ·Ÿ1ßs߅ߗߩ߻ßÍÏý¿ïï$ï6ïuÅÆßTïfï†ïÕß›ïï¿ïÑïãïõï—ïUß ÿ=ÿOÿaÿsÿ…ÿÿ©ïïÜÿîÿ?ïœÿÌ_|¹ï£ÿµÿ·ï"Ÿ±Ãe#ÿ5ÿÛ/ASåwÅÿª¼Î i¯A/(/w‰‹ms/…/—/9/÷ ¯/ñ/??'?¹/K/™~??¢?´>ó°ŸÓ?”Ÿø? OO.O@OROdOß?O¶?ôÍkà/vOäOöO__,_>_P_~O{_¢Oôá»Ú”a/__Õ_ç_ù_ oo/oAoo_lo§O*/Ä_ºoÌoÞoðo&ToQch¯‡™«½ö¿R?ŸC}`/¸_„¿_AÝ®bP†˜,öäÒ'Ÿ9ŸKŸ]ŸoŸt^ÏÒ‹¶Vè„Ï“ŸÈ½ÞxñŸ­— ®AzF 7©ÂỈ[ªºX¯Ï¹)Šž¯Â)‹Ã¯ÁïŽÜŽ_/ ¿ÆŸB¿T¿f¿x¿}3¿š¿¬¿¾¿â¿ž_9eÍ ¿rª,ÈÔ»XÏjÏ|ώϠϲÏO©Æü›*½ÎÏñ¿FßXßjß|ß¿…šÏO¯ßÁßãßè¿ú¿ ÏÏ0ÏBÏTÏÀÏtï†ï˜ïªï¼ïÒÏäÏöÏßßïâß]ÿoÿÿ“ÿ˜ßàßIþÒîAïýÿïï&ï8ïJï\ïÑÿ|Ž ²ÄÚïìïþïÿ"ÿ4ÿFÿew‰› ÿ¿›Ÿ­Ÿ¿Ÿ/P>,öä†/˜/ª/¼/Î/à/t/b/P/>/,//o??“?¥?·?¼å/Ü?ÿ?OZ?H?:/L/^/p/÷?O¢O´OÆOØOêO??$?6?6O$Oy_‹__¯_Á_±Ë?ê_ü_o o2oDoVoÕß÷O£¯·ëßüݳd¯zoïÿ(:L^É?‚”¦¸g_Ú ™s¥àx4_$¿ŒûLÛõ{A¯“kÕ¯íx?{㟎 —†[]DW.Ÿ@ŸRŸdŸiŸˆŸšŸ¬Ÿ´ŸäÿãŸõŸ¯¯+¯=¯O¯a¯s¯…¯—¯©¯»¯×œÞlʉS_e_ÍŸ>¿P¿b¿t¿k¿Ÿš¿¬¿+¿Ã¿Ï¯ó¿ÏÏ)Ï;ÏMÏ_ÏqσϕϧϹÏËÏá¯ó¯¿¿)¿HßZßlß~߃¿Ë¿ÇÿúOâÏÝ¿Ðßýßï!ï3ïEïWïiï{ïïŸï±ïÃïÕïëÏýÏß!ß3ßRÿdÿvÿˆÿߘÿÃß¿ÿâÿôÿõï+=Oas…—©»Íßñÿÿ+ÿ=ÿ\n€’¤«ùºßÈÚøÿô ß*íl‡…o‰JvoI±ß¬/îÐ/â/ô/??9?K?]?o?®“?¥?·?É?-?Þ?ð?N>K!Hp.qoOOaOsO1,4L#MOÅO×OéO __._@_NZ?r_„_–_Ão7 / Ý_ï_MŽœ‹=Œf.õ_Yodovoo‹Š o ÇoÙoëoýot a_);£_ÊþcuÊ}º_Ø‹ºOs,*LöŒE+j*G犜(òRdv š¬¾P×韜®ÀÒäö,>ŸÞŸðŸ†¯&¯8¯ Ÿ·/Œ-ÿŸ&Ÿ8ŸJŸ\ŸnŸ€Ÿ’Ÿ¤Ÿ¶ŸÈŸV¿h¿z¿¯ž¿°¿Â¿%µ”eâ³½"±]ÿ¿•¯§¯¹¯Ë¯Ý¯ï¯¿¿%¿7¿ô¿×ÏéÏ¿ùÏß1ßCßÍÿ[ßyßRÏ!Ï3ÏEÏWϸÏ{ÏϟϱÏÃÏQïcïuï ß™ï«ï½ïƒ-(Ù¶Úíƒ,–ߨߺßÌßÞßðßïï&ï8ïÆÿØÿêÿóõ‰ï);M_qƒ•§¹Ëaù¹]ÿB/ý7ÿÔ^ýM Ÿõ%F"€o…l¨l*Â$Na¯//'/9/K/X) |/Ž/ /²/Ä/Ö/ø¦KÌ]mÝ?(?:?×_–úÀ[Ã_J?>‹<ˆïÛ?í?ÿ?{O(OÅïÿ}û_ßv¡I1O‘o9Zýõ __/_Å?S_e_w_¼O_¢_‚_UOgOyO‹OO¯O³_ÓOåO÷O…o—o©o?_ÍoßoñoFoc¯u¯üoÏ_á_ó_o$o)oMo_oqoÿ#¹oGYk}lß³I[m›‘£Ã€ÇÙëyŸ‹ŸŸ¬›BˆÜŸÓêüŸ¯ ¯2¯5[¯¼Ÿ¯ˆú»ÿA¯½¯ ϯá¯G¯ ¿o’q¯4¿ÖŸö†å¶¤¯u¿‡¿™¿«¿½¿—è¿ú¿o¯Ï ™Þ¿ó¯[ÏmÏÏe¿¨Ï<ÌÏÞÏðÏ?÷ŒJûŽ®®?Öèú~ßߢ߈þ]Þw; ³;þßï"ï+åÁÏOïaïsï…ïôñé¶Þ,ÍðéåÕ¾ÿÿ*ÿ<ÿNÿ`ÿrÿ‘ÿ£ÿµÿ±ÏÅÿëÿýÿ¿ï&‰ÿAßSßeßwß“¥·¿ßÑßãßI/A×ÿew‰ ¢EUgy‹ //1/Óå÷ —/©/»/Qß/ñ/?³yÿÏáó/>/™?«?M/_/q/ƒ/O#O5OË/YOkO}OO—ê¥ê³ïQ?c?u?‡? __-_Ï?á?ó?ÀO“_¥_·_MOÛ_í_ÿ_?Jœ oÈOÚOìO'oD_’o¤oF_X_j_|_ .6ïRdvˆš¬¾Ð?ç!™›VùmŒž°Â¾_æø ŸŸ.Ÿ@ŸRŸ÷jmeßæloÍm;Çb´Y¹±ŸY¿„ŸÛlz˜ûo#¯5¯G¯Ck¯}¯¯{¥¯·¯„ҿ¿$¿6¿H¿Z¿ïï¥[hÚׯ½¿Ï¿á¿Z¯ÏÏ)Ïá¯AÏSÏ®¿ê¯ˆÏšÏ¬Ï¾ÏÐÏâÏôÏz¿Œ¿ž¿xÏ[ßmßßø¿£ßµßÇßjÏ$<ÁoFß…Ï#ï5ïGïYïkï}ïïß'ß9ßäïöïÿÿ“ß>ÿPÿbÿtÿûÛ‡ü£ÿïºÿÌÿÞÿðÿ&¬ï¾ïÐïšÿŸ±ßÕçùÛß$-Û˜øß7ƒ?Ûoo·kLéß¿Láôù̾K-ÿU/g/y/t/¢/´/¦¿^ †™v§?)?;?嚈…›aj×,¼/ ?²?8Çï?OOÉ/+OIOEWi{ŸfOÃ-/Ê?ð/_/îOpr¿opNAMEh`ÿENGINE1R×LE R`)qR÷R`ððÿýÂÂÂÿÿÇøÿÂÓáïÓÕÕÍPÇÍÊÔÔ×Âù›Qå库¦QÿÂSºÌ̺þ¦P ÂÖÖ“ÃÿÜÈÓúþ ÿÈÎ¹ÜØ¹ÇýûÌQ“ÃÆ¸™¹ÿºÕûÿ Âÿ“ÜÀÙÆÎÑþåSÈÄÆÁÓýáóTÀÀ™Ü“½ÏeÄÆÄ“ñUÖïÃæßÙdǹ¸Àâ™ÌSÊ+bÿSÎÙZ¤ß“ºþ*cS¹ÁÁÙÙ¹ùÈ×P-`Ö¹¸ÃÀü`×Qã̹ß÷ÆÆÖËPÂå×ß“¸ÃúËQÂÇÿã“̹×ÂûÿýÂÍSSºs˺×PŠ`Ïå›`„`Z_2mTaP»`zU;ÿúCCøûûCÉŽPüÇCÑýÑP ÇCÓÊàßàCú¿PÓÔÔÚS˺àëaÿÇSã““ºýÊë` Cºº®ßιÞÚCåQCS“®¹¿Ã“SòRÿC®¹Ã¿Î®ýº8a C¹ÎÆ—¸ÀÎpü0p/`¿¿ÀÜ_ÃË=rÏ¿S̸™ÙßIs ÿCÓËÌÀÀÙ™þýPû hǺ®ÆÄÀÀÓÍ=pþlr¿ÙâßÃãÑýÇyqhÞ®ÄÀâïÄÜÞÑ[rÊ“ÎÿßÀÀßÜ®Úûþ]pÍã¹Ä¸™™ûÜ®ipÿ Óº¹^7pÆÜ“ͳrv`ßÀ™¿“àråË¿®¹ÄÃÎËpþÿ ÑSÞ¹ÌÌ®þ’aþ CSË“®§“ëÎpìpÚ`Ë)SÖQ¢o3mTN‚zUùDË`ŽPúÛèÉÿùþCCCÕïÍÿè¦P CÛ?áçÍSÍ>€>pÿÕÍÍʺËïSÿÕ‡pÿ Õ~›`º““ÈçåQÿáS׺“¹®®ýSÀráS®¹ÎÁ÷ÃÃȤpÿ ÕSÿ¹¹ÐÐÎÐÈþd ÊS¹ÎâÐïYÁÈS‚ǺÐÿYÀФ¦“SÛþ>qCЦ¦¦Yýй…S¹ÆÆYÆû¦Î«þ ®Y?ÀÆÀ¦¹S=qpÿ¹¦âYâY®S|¥q“€ÀÀÀâÐhqþ2pºÃÆÀÀÆÐû®Ô¥ph×ÌYçæâÙup¥rºÌÀsYߨ€` CÊop¿¦ÆÙÁÖÕç‚ÏÿS“ÁæùºuèØRÈ p¹ÈäP{þ 2¹“ȺÖRÿÍSÈÈ×[èúE4mTMŠ’ÚzUCƒQCÑ`ÂCûþxqÂÏÂÓÂÿÓÑÑÂÂÏüÿhýÓS_ºSÔÑÂyqÍý`¿ºÖËSSÊxrÔÿSדҮ““ÞþZsÍ˹Îݹ¹ûΓõ€ hÊÞο¦Ð̹̓æ ÿhÑËЦÀݦøþ¸ S¿ÆÆ¿ßÆØ“SáÇ’º¿ÿÆ™¦éÃÖÓzyqáЙÄÜ®£{CSŽpÆÆÃ®ZrÿhhS“Ü™™™³Ý“8`Šp“rpÆ£Ã×;‘@¤d ºÔ‘ÿhÿ S“¦é™ç™ÌË`{£Ä¦À÷™Ðº` hÓSÿ“éÙ™¿ÝSÓ~—¤¦Ìй®ˆpg h†€|€º²¢»CðpÖº¿¤åº“ºSÕÊ`JsŸ5mT4ö¢zU*ƒQ÷ùÂ¥PýÂÂï‡ÚÚϦP Û‡ÂÑÂÛ‡`°k€ßºÈ×SÀr›ºÖn€SˆçPS“Ò䨨®ã8bÿ®ØÝØÌäýºÀq ÑÒÅÀŸÃ¦Î×ÚÆg€S^f°ÝÀÅãC²Õ퀟™ÁÙÃËŽèP¹î’κC´¹ÄÀ÷ßÀÃEb ÂË®æßÆ™äºÏn±w ºp¡âκőþ°º¹æZÀ™ÁëÞÛåQÊR ÙÄÄûÌËÒ²ÛÖ¦Äçß™Ýß±ÍQ¦ÙÄ÷Á¦ºî²ÔÖÝÎ([±`Z“åp“ bþ°ÏÞ®ÈÖ^€‡`þ 7ͺÈ× ÚҰ߯å6mT-IÂzU#úÏÇ÷úb€Ï`Ç÷ÔÑC¦PCý÷ÊS±CCÇßÏSÞËÊlÂÿ÷C×áÇúýÿÏS¹Ì¹ºÔœËQ“€Ø¸Áå€caÕר¸¸ÜÌËQÍ“ÐÆ¸YÌ¿¡~ÍP¹Á_æÀاÁûÿ °æÀY¸ØuSqÊaqßÙ¹’aÿ ÛÔËØÀÆY÷™¹S–¡CÈØÇYYYæÀpp“äõÆ3`¹ÛÂÍÈØ™÷LÀYÌÄÑ˹¸çYÆæÒíp¹¸Æ'¸ÐÌ-ÓÆÀÐûÛÀþ Ïר¹ä`šÜrCÿ`ÈÞJpêsºH^ÐtÀØQÇÀ›`å/ÏòiP7ò¯±ûáöüCÔÓÓkÀÖ§ÿæ`¥PþCÂË׺ԾQŸCÔºÈo€ê` {CÏÐй¹“ºÊP÷ hÏÝÐÝÅ“×ýÑäÒ˹ÌÅYݽÈ÷` hÊ×øÐæû¹Èp hÚÖÅ¿YÀY¿“å×ÑãYÆZ¿À®´Àÿ ÓËYÆÀ¿ïÅ“åÂxqá“?¿ÀÀYÅÈ1â2p·ÒܤF ÈÚ¤¡Óÿ¹ÜÆÆÙ¿ãýÚòP ÂÒÃÀߤâ¿Ö͇` hÿÔ“ÝÆLÀ¿ÖþýÒÚ×¹âYÆÅëËÂäÑÑЀ¸¸ÅõȆáÂ×°¿¿ÝÌìÉQ0ÐÚºº ÖºÏ|oaÛÐÖËÔÉËPËɺÑà²Ñ°àÂ×Ñáø}Ù fS_SÿPLSAMP»–XëâV"ëàPý`ûàabehjnÿrvz~‚…‡‰ûŠ‹ñŠŠ‰‡†ÿ…ƒƒ‚‚€ÿ€€~~}}~~Ñ€›`ðñ€#ðzyxuutttr?òò<ðuHó<ñqnmlûjiXðjmptyÿ~ƒ‰Ž“šŸ¦ÿª¯²µ¶µ³²ÿ®ª¦¡—’ÿ‡‚}xrmjfÿeeefilprßuxz}€ ñ‹ÿŽŽŽŽ‹ÿ‰‡…ƒ~|xÿuqmiea^]ß\\]^`òqtxz~…‡Š’ñÿދІ‚}vqÿje^YTNJHÿFEEHIMQVÿ\bjqy€†‹ÿ’—¡¥§©§ÿ¦¥¡™“‡ÿ|uplhdaÿ`^`aeimrÿx~…Š‘•š÷¡£¥Ã€¥£¡žÿš–’†zuÿpjfa^\Z\õ]þðn_ò‘•™ÿ›Ÿ¡£¦¦§§û§¦•އyÿrlfa]YURÿPMLJJLNRÿX^dlt|ƒ‹ï’™ž¢çð©©§ÿ¥¢ž›–’މ÷…€z¤ðjihiûilµðvz}‚÷ƒ…††…ƒ‚ÿ}zxurpml/iihf™hz¸ñsƒ† óñƒ‚€ŽuvHñvŠó†‰ŠÀñߎ‹‰†ƒvt}q“hhijlðÿy}†‰“ÿ–™š›››š™Ÿ—•“‘šðÏyûvu>òtvx|~}‚è’“–––öýŽÅñxrlhb^ÿZXUTRTTVÿY]aflqv}¯ƒŠ‘–åñ§gŸŸ™•Špb `«ðR]®ò„ðµð½ïyzz|i}||'zzyrg}'ðÃx ð óœò€}}|7ðt¹Eñvd|~€ƒÜ… ðŽ‘—šÿž¡¢£££¢ÿŸ›—“‹‡ƒ'€|y‘ÙpwÆ(ð‚ƒá´Ônl¯ifebúð]õ^Çadh2c𳟟ÿŸžž›™–‘‹û†€Ee`\ZYçXYZø]vy|þñЋޑ’’’‘‘™ò²uŒGñœƒ òÀñšò‚ß~zvrnM^^ú¯ðfò€ƒ‡‘ü"·¡Ÿ›š—×–“’Ì~nmïmmnp~…ŠûŽ‘——–•’‡Šd ìÜmè‡ñfqxqpnÛ!ppq?óØ UñÜemÝ"pÚ ufdn#úþðp4‹‘—›Ÿü —“މƒ¹€h Ÿ"pquå‹ù1„&žš—•ã‘oi!1bbdßfjpuz21“•ô°!’!†óðnf`Y¿RNJIIJØð]þX…•›¢§«þjñ¶·¶³±­§Ÿ¡™’Š‚ôðM^ÏZVTQNPLMÿNQRUX\`d_inrx|¦•ð‘5 ‘9 ; Î4Í4­¼ÏÕ!rqqqü!nÀ'"w"ðnt …‰Ü_0²› ™–’ÅñÇÙ ‡ð`ð} •Až2@C5 ðë0 qrGðv•ëøðJMMNPRVZ%Ah\ðG@æ#ì¨ð\ÿÀûZ]²1u|ƒŠg•šž @£¢?1À À ðvð.“—b80£8B‘Ãí2¡ ¢!à HAe$ò8åBý0pxvtÁ"ðù^ôr#tx}‚‡‹•“’:"ß3yžshedd‚ðñ$q|ˆñ ŠŽ’–™0@<@šD~ytm# 1ÿPPQTX]dj/ry‡ › ˜CÁ@JPnifñ°ðƒCý‘äñ©«®¯¯®ï­©¥Ÿïð†€xóqlm!WhlptÏx|€…!åñ«­ÿ®®®­«§£ŸšE¢ðž%ÚCÛà‚þÄPrmha\XTsQN]@WQ\`eY0è儞òyémll¡!ÎV'òðëA¸<ðÜ@ù|20„Q¦ª­¯±—±±¯P¡kj1xctrú %@P“_ߦª«­«rðš“ÿ‹ƒzri`XQÿJEB@@ABFÿLRY`fmtzZ«P‹”ðŽBtk @ùðýàW0µ1{ Ç–ðŽÍ…‚€Ž¬dÿ2xº`AŒð§‰¯dÚ$0aŠðßð€}ÅCõz(@ŽV`£ª¯µÿ¹»½¾½º¶±ÿ«¥ž–‡€xÿnf^VPIDBÿADHNU^hr?}‡’›£©8a=`ý£p‰‚ztmfû`ZLNNPQUY^dhm}»a½` r%aÊA^wajnplTÊ ðƒ S•PH0½‚ÒqmhdPZ€|B0^QU` À¸Cš!–·!Œ#ñ€¦~` ’-@ ¢2¾Bøi!ø@o ]^^abOfimqä¼ð4 ~p–—U š@ DÌðßUQMJHm`>>ÿ>ABEINTZ%a 0|6P2$“Q·!øQ XXY\`‘b¥P&B P•õÁ‹†pÅ¡!(!Q’—e›²Q®,qqð¢›4qJ˜3`!^&€Sž)pü‹Q»Sއ€vmeû^XMLNPTYç]diZ30ž¡¡ôÕq€sQd`\YwVUTæ€VX\Gp¼„B^£©«­ºQÿ–…zqh^VÿNHB>==>A?DIPU\au"šb)‹¬ ‚š\—€pp6‘4ŽžA×!G@0ßbW ùp:QžŸÒ€Œ —•’g!ÊÜáäšeÄ0‘@’{ðjd]ÿVQLHEDDEHJNRÚðï€0ãòôA—ðð€xpiÿaYRMIFEF+ILz0bÆ€|S`y€%Ÿ·¢A‰IQôq"`î}…ޕߣ©®³Œ0µ²¾‘0𑉀vo0XùR€œU]fnxÅ€üaÌqBŽŠ =@å1c¤ -a^§ùª¶PPž–ƒyÿmaUJ@6.)ÿ&&(*.4:AJp\\SY‚/’“} hUŠqâs]Zã‚CUXdA´1RaÒ‘¢2Ÿš“…}væ‘ÎU2ntz`Q¢q§©}«\`«ª§£¡Ö€!0g QðFADôdŒø°ˆîBñðz‚èQª0P.YPbhm_ñ‡‚ß0™‚K3"PbaV0yú –ú‘±²²±®ÿ©£›“Š€ujÿ`ULB<520ÿ025:>ELR×Zbj1“„0­¯²²³²<`†€uôßpÈŸ$ˆð.b•¢pÍp£¢¸?8rÎðIEA€BÿFNV`jt~‰ß’›¢©¯þ¹¹~0¯«¥Ÿ—‘Œ€•v’¡f#Pd'PzrcTusAWð˜Ç"¢ ó †ôÂñ;‚i"d©ð“ppI€~Bï4®±±Q°Þ»Pž™’‹¼ nh£aZÏðÓð›P#qy‰‘–° ¡°±‘ÀfÀBí0ÚBš`‰‹’–‹A¦ctñ"niåqöìp²òé°÷¦ƒ‘†£`‚Áuqv@ú@öBs l'€‡AÏ‚Š!šØr6ql•¢\Zî‘&±çzƒ‹s°ü‘¹º»ûº¹ q•‹‚xÿne\RI@80ÿ)"!ÿ)2=IUbn|ÿ‰•¡«³»ÂÆÿÇÇÆÁ»³©ž?“‰}ria=uðR"2z-"«e!xÕ<¡ã}aÆrÕ‘”Ó”AC1“ C’CAØCÀÇÂ1ÐÃrRì¨ðQVVZcÐrz‚wŠ’šÑ·¹ºÔÿ“‹‚yqib\óUP€Ã“\biq`Åp¶!â2tqUõÓ½ù4¹`v=âò¤j`$ñ5ñÀ"R4ðq|‚¢„û±³n𯫦¡›€EÏ~ãƒ`­BaªÕ«Ø ©¼P›A`\=Vs0FEDBšÆ^xa203 Ž;A¶J`~¦ð`\XURR®2ÀÞÓ0ÑžÒC‘xtöððq!dÁ<¢ÏQFã`¼qÄ`½Ñ P° ™š/BAP•‘‹©±Þ€!•wnËšž£~€²³pà/³±¯«1p™ 2@AкGão’uôád^ùZƒÔðLQX^fÿnv€‰—ž¥šM´ªR¢ztG VX¡¡û¥ ÙqñWsê0 ²Ñºa”›½a} À Qí– ¦©“઩¦ã¢ž¥À¼£IVTRýR,^emv‹ÿ–¡«µ¾ÆÎÓÿ×ÙÙ×ÓÏÉÁ¹¯¦“  ·‚±"°\¤¢{çaàP7ñ‰Z§á—“LànÀørÀˆP9a®ª£•þU pe\QIA:ÿ521126D0±r¦`…¥Y"Ú1Êg—Ù~„âÂÊb¡‚¡BvÀrXš^‘¢°é¬rà —5\ZH‚^@NÜBgàrŽ`]Q.êp`aa?°dÿ² `€ß!ì£>ò£T!ˆáà—”-’¯ ™Ð¢ˆSƒ€«?c…q>@sòSp¥B7Q-AŽ ëá3°ÅTlpt‘ªÃxšcÃ0„pƒ~xq‘YTPLÁÑÁ€^djqx!:Q ±g‘"2qÌà2À#¢Q»ÀP“DÃ_!Š@ gPfù@ð)â±ÁÝ–¥ÿ«³ºÁÆÊÎÏÿÏÏÍÇ»³«¿¡–‹€th,ÐAÿ:6569>ENÿXbmxƒŽ™£ÿ®·¿ÆËÎÏÎÿËÇ¿·®¥š0‘q0¡ÓZaБЖA„±¹hi`IBÿ=8422259}@º°^fpx~Ë‚Kš™Øq…Û‚ùB^‘aþ`@…à†W’Z€'ð@¶ °q{àÄAQAü±içÀý}0ž§¯·½ÃÿÇËÎÑÑÒÑÍÿÉý¶®¦ž•Ç…~óà#àrpuyá€E ¯ íóô𛕋ÿui]QD8,ÿ" ÿ &1=IT`ju€‰äÐv°MÀ~0q—‘Šƒ}vÐ\1À’pXVV¡¡fD°}jЇ°RZàúâüáíq§¤qÂÏp§¦qÑq) –Ci‘×° Pÿ±¦P+1“𡦫¯²pàœñ¡½Aíâ?@†Áa=¡ ñë´SuPBZà˜¡H€<Âl“±<üP†Ï ¸b˜†èBxÐpj¸€!9Ÿ52246g± pŸyƒ–Ÿ 1HÐÆÿÿº³­¦Ÿ—‚qqŒaħFÀçÑq»ÿ·²­¦ž–ކM~n1ee¤PmÀŠ'p窱µÓΰ¦Ÿš×’Š)ÐZ <8ÿ54469=AFÈZPË•–&ð/ñ…~ïvpib““BAAZpMu`hp¢šà&¡+¡ H`"äqr$‰á\‘a‘iPÀÂàH`Ëà[à“ab|PD±†¨‘HÀ±¢þ· 0'Ñf+Qzj lY0‘™Ÿ¦JÁÞW𧢚“ÁB]T?LE>941c°€¿IQYairÑšñŸ$ Ôp]ñ‚|tmóhb€»€JIIIWJMPŸa'²…ßF´ žŸ±'£-ð—à€‡‚atОÕb óø¡†ï‰“é𞟟`8S €o’¨ÁuzSQÿ™¡§­³¹»¾ÿ¿¾½¹µ®§Ÿ1—žAÞ±À^`”`sp(ÊðMqYsmYâ`ûà‘`¸ÂƒÐ|¾pçbå  GRa`caš2A°ð~Ð%àp!÷£`ð‘mt|¤Qÿ¡¦­±µ·º»Ÿ»»º·µœðõð™èØ€Pï`tgÐ…‹‘Ž—À¢¦ªkN Ù ¦¢›à FÃñÊð(Sภa,ðØp‰‚y™"JFBA@ABFŠðÇ]dj'‚Ãp ‰…ü—!‘A=9655ÿ58:=AEJPUZ’ô½õôaÊñ‡8hqsaÁr‘““<’ÌÁ-“Z€›ž‡p °äR^7‚†…ƒƒÜ!‰¦"\‘s^7€­ŸÂq…ÇqƒÐ7AÈ┡:óe0:/@‡0Š ´ç : ¨Àç°IÕsà€åX²L±Õáaej‚Ç‚Š¦r ´³ríàe€~Ômpäñ“H¡«²B»¹á¶¢ÀBkR €QXaÿlx…’ž«·ÃÿÍÕÛßâãâßÿÛÖÏǽ²¦™ß‹~pdV^°64~Í@:>DJPVØ@m!BH~bøâýäRçTUVæÀty|ÎR‘’ÏÂ2°}x…q¦ð\ž¡Ђ 1!J¤ª§‚°è@á‚ûH› Å€É’}ëÀ×a¥œÁ“à­­­80šà/ð¸qmÐ¥pX±*ð‰sh‘4¼ °`€ðNLÁP0V\`då²×òô±³†ec,‘â°h&á×É€†…A€…`àd*🟻0¾‘+ð‹p¶ $ð&ñ °ê"ÀuÐËa÷S:Ë šJ²²Ó·µ»AUÀƒÿzrjbZRMHŸDA@@@ù@WYÉ‚&`ˆÐñçPíáž7¡#à÷á÷Z Óaá pñÀ3ànqÉqÒ á­Á\YëXUR emu‹~‡÷¦ü‚/–Á€„¾ð‡~a›°ÙaN°³ˆ{°Á`u‘» ×ÀÊ1hah² À0@ p‰‰ÔÂì7ñ°MLfNQU feчá ÀÍÀ'¡²ã’Û‘½"d`LBkDDÓ@Tl±}†£@+81ƒ±¨ÀÌÓ£`^Ip Û@ºà“ŽÐˆs—Ù€ìPÂÄò ö¡!ðG‘qsž›ð[ÅDBBUž€ßÐNYàÛ‘QXä!!·Âü2 ‚=âì²Ud&Xáee’‘LauOjÐFO¡i‚P‡¡¥Ä`‡•‰l0M@¨òiH‚ ëÁ!•§1‘“!öƒa_áµðx}/„Ëí [‡à€rmq1]$©ary~ƒsq¾0ãqjÎáã¡Z`fmÜ@‰Ž‘²‘<‚’‹ÂàÓ…ð0@õq `WÀÑÒoPá¤^ÞÕ¡Û§®0bÁÁ4`»·?³®©¢›“5±ô0Éq(@„$žìð´0¢ÿ–†}tlb\wTNI±DFIÕA½bOPv|…£ø)³óõ£TMHB@===@AEI°€ ÌP'q©.¡`÷Ó^aJ`Û@…°a§®ÿµº¿ÂÅÅÅÂÿ¿ºµ®¦’‰ß}tjaX7p<8ý6?p>EMU^hr}‡‘›£­oÑ¿ÃÃÃÁ¾¹tA™Ñ“QÁUà#1j!Sy}!­‘‚q=‚•rƒvaH@¨wñ¢§fÞ°eâ³t ‚0`ŽùÐÜ€· ñ"É"2ûRFÅñ$áapæ“éÀ¸tp’“Ø€4^°¯…Íq~~iq[£Ÿra±¿rÝ#4 `äá2½5…`É1ed´³b#SY¡€nq¢g°ÇrÇqÌ£d±ÁtñpÈáD㮀Ž1]µÃ¼ÄdÁˆÀIÁT‘ŒÃÛáRP|ÀÕÿAŠ“ž¦®¶»œÑÿ¿½·±ª¢™ÿ†|ri`VPûIDøANV`jvÿ‚Žš¦±»ÅÍÓÙÝÝÝÚÖÿ·®£™ƒynÿd\TMIHFH±`ê »Ò '?T±±B¢Y€ó¢‘aÐhâõbOq AAÉ ]â¯Ôárú!éÑ|…AÇÁ¢©¯¶ºÑÀo¿½¹³9b…| ç\UQ¾QWdmvPZ1°@’@–A«"ð…OðoYPF@P 58Ÿ|‡’¦nÐÈô­ÿ¥›‘†|qf\¿RJD>:8‹ÐDßLT^itZ0›£¿«²¹½¿Â𹲫¥“‹ƒ´Qÿa]YUTQQPQRâpãû2–ð†È @ÛÕü!e´°-hl&¡0|ßA10§*±.“©À2/¡y˲zfÀÓ–›^0\Q¹ü±«ì± À‚}®Â`]YVÒ$@`ñ£Á sønõØ¡_MIEA><;׆Á2 £§O«®®®81À’Ü(¬ñ®ÀõVÛðHy á¡#NP(Sß IÕ ðÁÌPƒŸ 4„V°¿í0LH„-V¢¢Ž ç0k0AxUÒ‚É bÀÆÀ“¯A¾ôÁ½¶¯§œAÀ§Scõ2zâ²`ð~ƒ†£qøÑ?á†òPØÐdr á}|zVc'â– :¢yçÒ‹áZÁAǃ\ì‚ÅÒ–wÿÒÉœTfþÄÀƒ•¥«²·½ÁÂÂÁ¾xÑfeQypB`F`ae 3òJ°•§Pûƒ©¥Ÿš—“‹…´Pf#r QgQRT‘JqvzÈ f±Eá~}|Ò²F3ö_qxyBA‚^1‚pp¤ôÞÇwÁâ—JJLÁa òÁòµÿº½¾¾¾º¶±“«£F0ZBIpqð1²Ú1]P¶µ±­©’†Õ p£@‘‘¡ òÑ1€7‰qŸ RÓ(2s¡ÃV´ ZG`¼²$Q›ðzÁE0€àDȰ$í°Ô€r±–)¡€•q¬ð§äÁüP×1ß@—×›¡¥û¯ß`«§ £®Rƒ~8°½ b%.‚Ö€:ALÀ@€W‘0^Ü›þ:9:ApFLT\enyá ¶0üüeA¢|tld]X&ñNN'1ª0embàài³jóÎÑšÂVdnmmv•anqñÐƒŠ‘€¡Æ(‘ª§«P PÀƒ~)z±ñ¶ÑtRP±aP« ¯­§ÝÀ,Ñä€ÁA Aèt^4^0«cSUqÀB!à^qâå‘ûAmmmQˆPgI2Õq³ÑµÐ –b”` €AÀˆÀ’ d r‹‡{ AU23AŠÀóµþd@¦¡š•އ‚f¡6 à203БՒwÓƒ‚‰!oqvðeaÜx2åMQVqx/~…Š‘С?P 3²sÀd^yÃh'ZÙŽQ€8a¥£è`—“ÿއyqh`VÿNF=60)%"ÿ!"%).5=HÿR]ivƒ‘žªÿµ¾ÇÎÓÖÖÖÿÓÏÊŽµ­£çQ­Ò7¢pæÀaqú`ð¢q²ÍŠBÌÓÏrYr`qB걆ԃ<áDB¯ðtÚ°ö> a]ƒMPRVI\¨N€’zqÍ"tˆ±¸`}ÀÐeltÀ‘@©pÒ>†šÂw‘Ùazì°gñ\±ŠÂG€Š `tQâcP~b0Çt›rhÀ·P"“&(À¡!¸r‰¬âf²åŠ7à“ÿ¢¨²}ytOpmif× â]^ã°«Q§Q¡ ~ƒ áF „ßr âb’£"ŒáLRv¿}…‹’™ž 1­­nŽq½Ó¡qR1Kp²íÁš;!š—8q†£‚|LSbÐnAyyvó`žT¶ÒØ@VC bh‚à2¡æÁy3âL°›Ÿ¡£££¢¡i@µÔðiбLIÔL]N ðemt r‘=àÄP ÀÚâRNÜð€2éà½jÅÁ‘—ž¥¹0³+µ³6R•—jÄ@s¡ëX]Í€|á$¹½ÁÿÃÅÅÿº³ªÿ¡–‹ulbYQ&<99¤AÑqÿz†‘𣫱µŽø’µ±ª›aýÁÄ@U û2*2»!­ 0¢$ÈlBßrle`Yz2LNÈvJ£¡©|0±‘‰nn`ib]šA=¡@ÿ<>BINV]eŸmv~†ŽÂ%Àªà‹s I¸puG€…Šü]aó±µ¶¶¶³fÀŸ™„‘æ€^X° æàñbl"°+P!E&„²jf×qÙ!a‚>À‚šá}]¤=0‹%ùBŽQrItRP2@†½â!¤uƲP€!gs ðÛ2–Å ™cÀšpÐâOáoqî²Nµ™–®q†ƒ€}J@€¡$ÑR7ᕇ‹K Àofb^\ø1QPÚ)0\`bÓ2œáMáñA Q#lgpX¢¤p‹—pz !zìPœ#±¶ÒtÌRVáðÓѧíR.àx}ƒ‹7 æ'â€o@Z!ýC¸i!бD­ª¦à€ŽöB`pi1ÐNHDA>==>@BHÓÜ5å ¶¹º*¯©ù¢0“me\TLÿE>952224ÿ8´Z¸QZžñÑÂøÀpEÅÒ“– 10PîñfAƒàÛ±¸¢*ÐAÓ@qzƒÿŽ—¡ª³º¿ÅçÇÉÉËàï §Ÿ–Žä.•òö:òûš€»XP°544·@FMV`jt~¿ñÿª±¶º½¿ÁÁ~í!­¦“‰€‹°Ÿ]VQMIuÐqÀY`fnuPúS2púó®ÒҘҞы–pZáq÷le^qÐHB>:ÿ620..025þW!T\bjqy€£…‰7C[Ó„ Ÿ,€£Ù¥ Q`A±²ô!¯®„ Àˆ“@hóÛÀÊ jÖtñ‹’ŸÀªï®«0¬°û‘@ð0pm÷` áÐxA3¡N &¢nRa^à‹¾ þ1È¡<y‡·Ž–îâ¹¹¬À­ÿ¦ž•‹‚ypfK]U¼!<”‘Ë$xÆ÷•—à"›™“x„ ÐÚaÑR7@` t`Ò1šb¡ÂaVà‹‰µÐÐ`$@Dx*Ajá¨rf¡ì¦ð´!d]s`>81ÿ,(%$%(-2¯:BJRª@v)P’à‰B´F@ˆÁÿ¡lntž0`‹‘–›†s‹p¥ùQ±q‚Fð§bGña¯ayÒ °UóE‹mC,ÀTp²ÑÒ—¨QsGo¡]uMÐì£rAUp60‰û&)@DNZftÿ™¦±ºÂÇ]Êž©Ÿ–t1hÖð˜¢P ÁÛptš¡Qð€  @Hqˆaá¡uÒ ‹÷‘—zªªª§·¥¡›³Àzh#Z*ÑŠQÊ 91{`IQAFqPR,0“PxÓ1ƒvrhð" L°Ïr}!~ ÁZ’¿â|t¢VBˆ\AóØq€jiCí@‘b°0—)¡¤ðç1““‰‘63R††6P‡‰½ò7SüC¡Dák6Q ±àÓ2(§@^@¡Aylbi"aÆ@ ì¢b'by‚ððeAD€šAŸBõñHPuanHæa♵1̆€,¿@rcmq:ᆭ8[‘ô=@4ÑrÓaZVTP'NMM°²r2á3¥ñ•“wýÐ2©@]Q¯0eP’!ôk`.01lÔéÑPxy©AeB±°ƒØ!©ñëã`èd0-`•6€©ª­ý­ðQ¡›•ކ~¾½ÃIB<61hÑ)-16=DJR(At,` df…`{ó~^bÀea/â00žÀè¡jniÁ‹ b4b(à`¤áHpxHPÛ0ß3•™¡è‚O©§¢0ÀÂP`f‘þÔJPU\dlu¿€‡‘™¡©† ½“¾½Ká К€ÌvÀ?0{¢š½0 àƒRIý@œp$ !Û%*¤qXbšÐŽ™ÿ£­µ»ÁÃÅÆÿž»¶±ª£Æsà‰rS §µNRßX^fnx§Á›Ÿû¢£8@–‡~tûj`èÀ>8400÷15=eàm|Š™÷¦³¿2±ãåãáÿÝÕͶªž’Û†z`ÑJD¿ 54üðÀ¥ \fr€‹—ÿ¢­¶¾ÅÉÍÍ{Íʶp³«£›Ç€a~ñ00¡ÀX€~†^”®©c®]±Ž ¢|àAÿ=:866689÷:>A ZaipÀEÐ$¡òrp.ãQa]“ZY‚“a^ €TTU1ÓP‰1~°¶²¡µR´ ³(ÀÝÀ¢vQ‹2Єñ‰°ÂôàôØ1vàYA€.q' ªð‘Žú@BQHpû`Çá'‚ÕNBìÑ•3OteeÑA`P[p=YC`@‚âkD0Ò‚@QPÕ4YRâG nQ}§üp—’‹†zˆaiZpnrx} `ì_€ˆpµµ¶¡ž—¿†~umd\F|ÍQ'‘u€‰‘—¥`ðFâ³À‘p]ÐndZQÿIB>:8889ÿ=AEJPV]e ¤Ái¢l¡ °Ï`rãqTp2ZplŒ2(jlƒÀÒrØpôà"Q»¨ð-£|RØžP €`ÀUTaÂbhÿpx‚‹–Ÿ§¯ÿ¶½ÁÆÉËÍ˽ÊÀºµ®§¸Âxø°Ä lqy‰Þ̺½¾¿Œ¤—‘tr|TTþ€Z1q&ú †ƒQM2ñ5ñëN=ñadh’Pp¿0ÆòfÌôxuªàÕqu`ò…êà®ócSD1“ñH gb©àŠbr"p×PŸa à7ž¡£ì1¦¥K mñ2Ž|™^2…Š0½AÿÂÇËÎÎÎËÇÿ»³ª¡—‚MxAMH ‘ëPï‘l@} ^AÍb{QTpe€Xpw`­á|pqPŰ`žþ XXVXaI°YƒZZc”cd ïpƒq¥ß«³¹¾Â ÿÿ»µ®¥›“Šÿxpib\VRNMLLK]©¢ÒÁÑÿ¿ÁÂÁ¾º¶±!«ÛÙÑÈð,q’ôq3@æ_c¿¾ËAÀvlïaXNH°2.-ÿ,,,--.0258: ; \¡ñ %s# ›ð‘sp%ð°G°`Z\^"pÐp¿1+ÐƒŽŽÊ2K4M0çò•×—›ž‚°®°º»½½½ÐXÐÁÉPDA|ž¡¡¢FNX`h0߆‹“š¢ú’ÇÊqʵq¢uáqjdG±PVðÌp‰PÌ Ž ¢I#‘‰E`zàN/ñ¥€÷± `hã …e2pÀæào0¾ïá}ytmf‘JwHFEžpFHIP`ŒˆQy~‚‚ðÀš›À’ÀÙÒTÀGQ±1z.ΡŸ¦­“áº¢È îë±RLHÓ€FLTÿ^jx…“¢±¾ÿË×âëóùýþÿýùòéÞѳ¿£“…vi]cÐ:ÿ510..149@HQY®€FÂPÂzÌ’¤±JEÑ €>D…Ixtƒ྿pŒ€‰ñ‚d°Í€}à94.*ÿ(&().4:B¿LU`jt}˧þè@¿ÂÅÇÇÇÆÿ¾¹²ª¢š’±ŠèP›ÿÐ…‰0¥­³ºÁÅÃB‰‚YÐ ЇM ͳ4Q倘òZUÍ1ÞÑMó¨B¯AXÁYÄ|°PHÕ•Žü+ cUMD=61ÿ,)((),18/>HQZÇ|@ð~,¡‹‡|upOðT‚Q&cz¢çA¿þçÉÉÆ==·=>@ÈÀRYzpxÿ‰’š¢ª±¶ßº¾¿¿½ËB™’1‹Ÿ@X¡1ee @²“žO à‰ƒxPu0µ1a0Nг¶7@r–ކ}u9€ÊbQpò i7àüQtrrrÁu¬¡À0Ýñòbðd¢à‘qnÀ8ÀFAH@×644ïÁ>ôÂr}û†Þpª­®®­åª"–*"HbPPQaTÉ¡þ’2`±¹·Ðî,À—“Ñtmiø `ÙB’z‚Š’š±¡ÔÀ6a†Ã¿>qŸ—‘Šƒf@ãІ2j‚ž1e€Q 0!b À¬1iájÁÕ{A 1ddeõQ=…@@èæQÆ`lËUR‡L‰<ð\aÌ˥ϻ¾Ô$!›’ÞDaha\X°BdjÏrzƒªÂ… ÃÅŸÅÅÃÁ½Ž Ap3…}=»±]]ý±'`ä~fŽé Ùà››™øv÷0`À`XPHAû:6íÀ58=BHÿPXalv‚‹•þþÁº¾Âÿ»Xçp¢ d¡qmïPh®3 qr?xáb4Ó–pvQD@q 89824ÿ,06=EMVaÿit|…“šŸ£§©¯¥ˆ°ø+gQJFÆÆ¢fmC¾[q£©«®±.1«g©£ž¶€µ°rlÉaýY1rz…Ž—¢ÿ«¶¿ÉÒÛãëÿò÷ýÿÿÿûõÿíâÖɺ«ž¿tf\QHhƒ(k)*961.Ÿ`28Þt°V`iqư“þ™@Šƒ|tjb?XNE=50›`q‚÷Val —¡ª²í¹WÉÉÕ²µ¯©ó¡™fq. `]YXƒVVOòRp0P$¡ê—ï™››"žžŸ`‰0 Z¢  —ð¡Ÿü <ÿ¡‚q‡5€=‘ÿñ°À’ qÃT`x‚á² ·»Ó¹‰#±·f€k<9Ø!BÆ¡^eI‘Í~G°†‡Q2¦QtpÁl¶âbaãðÞQ‹‘ÜT¡¤§¦£ó0‘‹x¦#A”É€y~…‰ Ã&;Y€‚â‚?Q‡@€>0 r`§’=0# äóš0mNP†Ž–º}’½ƒa»¶±øÿ…ymbVLB9ÿ1)"ÿ")1:ENXaj‹ñáP`Qä‚vá À¯0µ`(¡‚t¢Gb¿QMJIIIÖP\ýbx€†‘𥮶ï¾ÅÊͽRº²©ŸpyWàfðð¢Ø&¾™›% –Îh æ¼TTr‘û|…?™¡ª±·»a`c`ú= «‘¡…|rlb#\UÀ”È‘•\SqÝS´WQòñ‰vQxu?°tu¬P¤†‰Æá€Ñ4’OІ‚Íqü0h¥@~nQMLHEDÑSïRZdm䙢­wµ½ÃÃAÉÅÁ>`qƒz½¡ù´•ãßR`U±ððß‚úÁÏpqqFÑ…A!……ó`šn#ª`aÒ1dÔar00z|}oâràCPPð1¶1*ø`4ü€¹170ý’©ðž¡¢¢¡žÐÐ!eÒÖ@T0Vs‘mvÿ‹•Ÿª³»ÃÿËÑÕÖÖÕÑÊÿù®¢•‰zmÿ`TF<1)!ÿ$).!5ÁÑÊ¡-pÇ"ÚàË ŸBé£H*!¡€61ãa :p¹‘]#b «¢Äâ—Õ¶µ²©áØáE@‡ ‹ÑN0 ÀNPÜ0|΀Ð,Ö€åcãà@P~}òõC~º0 #€}}||}} @P”“úðÊí]ñ€Vù3²jm°ÖpÚ`a |Ñ–—¹p—$ÇBtQ€¡@°r­0æ°0¿ñJëÀ­0pp¯0oU:²2|¸2…†‰1&ñàHé`O±L±î@}zxCtqZR÷S"À±p¿õ£X¡ªÀ@ž™“޼è’c°RNLJP`Xš1A€Ï ¡§TÑ[Щ¾ØÁ‚yqh`º¡BB`0MTZ*€Ä¡!ªÑÐ`¡†ÁÜÐX’ œr¢q1ašSt…qÜ”ðð@e“U€ž c `¦œlq@‹†ÅcÛ R HðgÀ\^±a0.‘PЉ§÷Чஆ²ØÐGq^¿YTQNNMCðRTXZ`ÁàÊðØ€á9ºðÌR<ðQRV¾áqy‰‘Þp«>¦á«¦¡š’~1 àÁZq’ šƒ92›<(9›™•G0耖€uv´3620ÿàF1 °Ð@mn†Eú2V³0óàB¡õ P&‰‡‡<Æ3i`^YRNáÐùPßEINU\*€‰ï•ž©²¦…ž¶ÿ«¡“‡ym`U{LB Ð9AFLQV\bhnZðñ¤Á>pFmhaZU’&eó‹•3!í!Á¿½ºÿµ®§Ÿ—‡f¶ fa!Pt TU§aýlÇÑ•›¢©®²Ë¶¹p»tù‡~ü±Ð´À@:51..ÿ15: Ð8B°BFMJé€Y]”âvЀ.€‡‡dpÒÁ™2Ÿ2Óñåàzyv¬0p¢'Ðòh¨$QàiM²Š’ª^³²¨á¦Ë·ð<°ÐPñ lq~`йP¡££Ô„¹ñRøòtÓˆ—ž£©­Ý¯)Ò¢›’0Àh]ÿTIA:521149>FNV^c@ÿ‚Š’™Ÿ¥©«­­­ª¦ÄP·ñ,q!¡/1‚£ƒsUùÅ;0š% Üã‡üP‚P°û2

0@0“ünÿe\TLFBA>>@AEIMRØP–ÁaénñŽqÒkcFðU1ñàtÞ1§€PP³pnÍ2 PYYQò`cab]á×0|a…ŠÐaöù°ÁÆÓ°ÖÙÛÝ»ÝÚ'ÀÇ¿¶ÀôïP™`ZLJHH½HYbju5@ž¦ãR³p¢ÐmÚ€ˆà#ZY‘ÂÞ€Ž@V³‡Ž‰ƒ»aÙ"Äa› rï|†Ž“ºQª­¯û±²½A£•‹ëvl¹±B¶Â9<@ÿDINTZ`flÂÁ €þA² h`šcMLMPÞà”Àèð•ðÓ)š«ñ,­fò¦Á@`a)qì1ã);P’ðtÒ¹@-¶²p®«\`¡mÐàø‹!Ù f°IFDA@v”ðAD 0NRUì`ÉfEáq¸ Ö\\‹3´†Aó0”€ªJà(!ðÏriQÏqÔu‰’—û¢âP¶º¾ÁÂûÃÃò º¶±ª¥¥Ñe`«2Ù¡´PÆ!@:rNN0A`à½!}b€Š>ð¡‹êqS‘ƒ0]ÏYURP“ “àHJÿMQV]diqv}µP!s’ƒ÷’±—°í`|aN€5c“ Ì@R‘¦Up±3©òª„ÉÕŽB4ê§2vpy…¡‘—Ÿÿ§¯¶¾ÆÍÓ×ÿÚÚÚÙÕÑÍÇßÁ¹±§6°ulö±ÀLHvqFJPVæ1@u|JÑÉᙕކ}tjbYR àý@áJQYaiqàP`S‹‰ o y@€B =Ñ‹1³†Bã´ t3miÓÒqxÎ`äþù°¿ÂÅÆÆÆÃÿÁ»¶¯§Ÿ–‡ƒyq¾`U1fÁà!iî|€‡Ž¡±¯¶»ÿ¿ÃÆÇÉÇÇÅ¿~Á`›—‘Fq=ƒx›@cÀ°EDEE&`eM9Â\ía^ …‰1ÀŽ¢çҀɡ,„0^]0#¶ð?Ñy`ntÜ@QêÑëÀ.qllƒCÍÀéJdŸ†b³(Ðóá–ïaVNH?°<=AÖÐ`iãàk2ÂÉoËÎÏÎ.°Â½®°Ã©£ÅQŠƒPC‘šžLHðª§x Ýaq:°ÿMD<4,&!ÿ "&,4<96689Y!o°åëðÇ‚øj“ald\UNýHœp5446P« ÀR 0ÐB_R€1HÁ—™U°¥£CPQˆ‚LRðÁYRÅq/P°Qåû%3€úÑüÐBP“FSP¢‚ QÛ2¢‘Ž€yLp&0ÁqE€WõbˆRø ]´ÎRIEB@=<:¼ÃPUÖ"¡aqcpÑAÜC;r9€“B(¡²Ñ~€‹™Ñª¶0a0¹“öéÁ¥  à0>‰#¶1¹2Ÿ” Û‚š0PtpAAA›ðP¥Qéce÷E_r‹ë“h!qárËCƒ tnÖàŸYUQNL|‘&ñUhÑið€ýC½€¡ý. È@ràÃC‘"‚ƒ¢4ñ‰Êì‘U°ž‘@ÔØ“™( BMТ;0ýª’ž™‘‰€vûmdàE>:64ÿ100026c·ñÁÑúÛñɵز¿tÍó, ì±ñ’Î5Ô1ÚD[¡bâ";SÎ`9ñ3bN„BÁ0ŠÔAO£'b˃”‚‡_@7QÀÒÏò¿Ä`"`ÁÖ@DâJ0hf1A@h,1’ òö6¤ÓórZÅë[A5q(°Pü‰‘êQTX]djqox€‡v¹º»!¯©¢š’a`n Ð\ðbqy‡Ñ?!yÑ?£ž—†|™ ˆÍN(ñbiôÀtž£ïª®³¶Ñ ¹µ±ë«£~Ðpb\VQõ†M‘‘b 0@ a¹pU@úÐ1Á=~H1éa¹àXôpñ²Ï€×P~yrmfaZ¡R¾hpz…Žä­½²"Ò·³¯ªБª%x»r3#Ž^ƒ¥¥~ò‡¢cÅ $¾ÑA›\“ t„‡µ`ù hÓp‡ ð`P0HAü@P@gðRWñeÒd`Y$ðêQ%Pâác ª?±·½¿Â³…Ç—Ž‡›PU„Àflçry‚žáÛÀ½¿Á÷Á¿½¶¦ž–…zr1Ѳôq½½Q¡ƒ/P•€Ó’ÇjÀ`­àS¡2ó 0–€Åq”Á‰~vtqlñ@N0Üáefà“Û°½€íãáó¡°c¢ ¡òÐqr˜‰–ž¥«±µ Bm»¢™Ðrj+°›YYmy‚t90¦ç§¦¥l€Srph`·YRM`ILgbõjkàŠ]P¦«¯³nØr±­§e1~ud`ÿRLD=840.é-Î ¥4lzd©­±Þgð¶³±«;“ŠÑ‚Wq{pîÁf‹p|Ä$â—•Q² &pjËe`ÎQ>àŽPTÿY`fnx‚—ÿ¡ª²¹¿ÅÉÍÿÎÑÑÑÏÍÉß¾¶®¥›¡ñ‡±U]îqÐsÒ|ß01PQ”ÃvÃuºœBh“ªH´’œâ…@è``°²XóZ` ±³ð‹‘–›øy±_0eQ¢–‰¿‚ztmf`‡àQ!P¯R‡qR0X‹v°²ª§¥Ÿš• PPdµ§@@rƒR¡Ù`©¿îÜb—’‹–0me]ÙV‹×|0mu{až¦ªð¶Ûp­ãÀ“ÊxÚ‘h+mpªBú"’0ó¶ƒmAâ„abâáD¥E`H‚´ÐTPt¼aã°´ÐÚ¶¡øµ5û1ùPyDÄA@XBñ3›À3€ûBá0•< ©«¯±²²¯ˆ`¢ž;`³¡è@rq­:ײóãqµ¶ÑAÌ1ÃaÊ2UÄcØ0ØAá«»€µlÀeB@hjFÐ-‡¿ÑžŸ žçÑÍаà€O1 !€cQ`:0< °!—‰úðàQÏRPPN7± mt zð¦Wb©±!‚Ðktpcàa8@\]¸’ôPiÂß0‡Š®p!²õ¢¸´ñçI¡P¢a ÇpTÀÉ⌲aheµìaï``d(Py€†X1a «­­­«g ßb0€´azH‹"·óZAÒ1`¥p‘&!| XVá¯XZ^bÜ"…dš†a€¦¦Ý`ma³Þ€lQjð‘©D±ÁŽP’·À~q€|vqjfkÓ x0YïadôQ³ñm,£5rt ã€bà_ñAúÕp³Ýp£›“‰~ÿrh]TJD>9÷869†ñZdmvÙ`ñz°­®ì ¥¡û›–­Ð~xrlf1aÎó3°íQ^d\ðÑ"Ù½3’àÁ<Šx*²óèPÌÁ\òa¹ÐŒž*Z‘“p€ƒ PnO…¢`‹ â‘pž€š!ž/p•zƒ ¢F’€PDÌpx²®—dQg"—m ‚|v¡&€i’á ’ÇQœËB5pvql|QðEA>PTThp$r“4S`A1¬Ðƒ|R~qLOAsÐrx1"…@£@ðBñŸ:`ÔQÆãP®`§0›À×¹G~y|\0d¡€UÁa\¤P°bó¡y€¹áÁÇTÍS_Ðb°»@h {¡îcimðUÒœp‡–“n b’&!µ’` % ¨@ºá1|CAdþ”`MIDA>@AÿEJQY`hpvÉ}Å¡Ö`¢¤‘–A‹†™€„Ðv `^S@EÐy×}ƒ‰u°›Øaª«®„d¢àa6Á˜¡À1Éœ„W’u–­€Âð᠀ؑ=¡á‘Á‚ýâó£vøs þ àTRQPQ8±`elrZ eæPôÇѬЂ†°aYRLÿFA=:888<ÿ@FMU^hr}Ÿ‡‘š¢ªfðê±ß«¥ž–Ž+ðia7XQLÓINÙòÑ0ÿ“ž§¯·¾ÃÇÿÉÊÊÉÆÂ½·ß±©¡™sðleæÄÀQNÐ÷2qx~í…â ¡§•ðµµµ²¯q˜B™Â¢"j±õäÁu&G!€Øáµ\Zìy3ˆs|‚ ™ž£ðüÀmš‚±ypf]VQLIIILØðÎ ±v|ƒ\ äP¡¡0¨’`K2àƒba>°ƒ ‘üo¢ù œ¤%a ÀfaàNdûû!•š¡üæ𿾽º¶±ˆЫ°p@‹l0¤ãv ]‚-°R„Žâ’²+àŽÄ°°¥rëà1€†1“ñ™’aÝ2•†~ÿvpid]XRNLSñ>ÐÒ@®ñ`‘OÑåìÑv(±QYY\\ÿP°TÐÀñ²€±°Ja`ÁŲˆM°4@œR=c@Ï´£¡ªqÔþ±zå ÝI±¢a1 Ž m¢bÔ’ubᇒ!DY]]m‚ßÓ››aƒ|Íô=à\Ï1‹–¡«ÿ¶¿ÉÒÙÞâåÿåãßÚÒÊ¿³ÿ§™‹}peYPÿH@:6569=MBˆðaiÓÀþB›*ÀD+ÀçÒ‰p!Ì Úâee“füTeüáù‘¿ãq£f±¾sßWa¢¨-¤ P¼€ÃtÀ[¡‚JÐŽ‘•%À/žŸ¡¢Ï¡"=@pvqõQÒ ïÃü@#€HåPÑ‘íQ…,ð‰±IÁdGMRXÔ@QIÑŽ·! ¡p'²ÍðL Óñ‘ZaÖA´òQ°›Q‘8@—=A}´³DÎÄÞÐaçQñ!ÊÊQpaŒáïbipxÏ`›£«ß²·»¾Á¢ ¿½ÿ¹³­¥“‹‚qz-ð;€O PRXзpv~"ž¢b!©Æ`—‘D!² 4ÑIJ$Az`dŒà%` {Àýphhffeeæ÷P]\ð@BHFF„<Òh– ¬2r¯`³±®ª¦1€{Q›0Õàøï²þ`®³¹¾Á¿ÃÅÅÃÂÁ§ ®žð¡_¢&`#à¿ÐåT~qüç@° bYQJE@<999:=A¡`Ý H¢‘Åó9ÆÂ@ß¡Ðæ¡çâQ]aJÑPK¢tQpg@¡Ón@0_Ð@@eÒþ hjé¢À´@RUÂ}r ie@QãNL!@ÏÁrzƒÿ–ž§®¶»Á·ÅÇÊÚb¾ºáÁ›•IñÉR\XKDŠR项ä½!Èàðº"ÿ±Äàè¥ka]¾aA<8ß54245žbTZÕ@¼Q‚_B—f@à³çq¦xAè|˜Á”€b‰Aq¶0 v°‘zž2A ™¡‡`?1¦¦ÇÐkA–o“ŽŠƒæ1e`é€?LIFEDD:Ð#@Q!Žáè£'bp·ò>a>B:Èñf„P\Z\| °àйQu]`|gcv!Ô!]\퇭3³Ÿ  A{àÿ¥›’‰~tja¾´889<@×Qb½j𙡩PàÂ?ÅÇÇÆÅÁXàïJ1(¬!Ʋ½â΃‘àx€E`6ÒcàQXVV|4Œ.A…v ožP§ÀÛ‰‚ê@f`¡D>Í:…À44;Œ²fpûz…Lâ¶¹ºº¹„Ýpžñå0q0Ð Ú!tã|… Àñhñ²®©ÿ£•…|tlÙeè‚ÔñRXÛPy‚S‹•"ÀÕr¿¤ ¾Üpת¢šrñl€°IBû<8à8=ÿ==@DIPV`½i¦`’¦¯›ÐÃ_ÿºµZ±“W‘ܧsw€…Šƒa£§©ª©§ß1õ1>°š’^@Š'¥€®’x‚1q=°ý¡ñ°þ¡àbpÑ!Âà@uqx}½ƒÿñ¡¦ª®–±¾õáž™’‹ƒ@fa²PŒQ°H¡nו°®P$ƒ3ëÑ–šo¶šl éqðN`jÎ FÐH•rˆ"R’2`Û²Ÿá°‚rìpNgª%¾ò¶rEB@LJHA‚²±V ü0ƒ† Þ@è!Ý1@v ‘ë€$@@ CÌq›×¢©¯Õp½Ûp²«3¥^p@ieøQ1Þ"•›£©­b³®ÿ©Ÿ–‹€ti^ÿUMD=8411k26Ê7“d®±q]®4À“Ђա`ÂáßÖ‹$‹(SaÁlÀ`‚Q£q¸q‹qbb“qr. G”éÂ¥£¢¿”ç@† fÍPNÂÉ`hßnv€†Žý`¦«û¯²s¦Ÿ—‡Éë²Ð]z CÑbfwlqv`•šèÁ Ñ£ÄsC´á,Ru:P~òÂð«€Ë¼à'06 ð0NNQRýr–q¼ò1q€“ïÒ<` 1RÂP¬áÇPž1°Sb+BŒ‹0Ó²%–³B‰ÁIPróí WQ]S¯„¸‚_`‚3õ HR¾‘OS`À`ÂFQ0x!¸‘/1ñ¡3ø¡_‘ýdkÇpçÓ¢-ÔDbßi`ú¤¤@XBŸ‘/`N¡š4ñÎ’Ò‘:@ä²[€Ñ"d…PÙÔ`ÑOÀ³ç2ð ð (`¡•y¡íÅôÀ@á±¢PX.¡n`&N¸ xa¤#©@Rs‰4ÅQ¨q@+tò rÀ³ñ]2|ù¢a```“ræÓáQ¸Ppp໺·²aŸ€y)ál`TŸ@DÓÈpy;~‚iPŽ¥áñ:±ï±v1mp´Òg±›Ã|Û±g ™“ކ}˜LB<65‰À=‘©þßñ¿ÅÊÍÎÍË?ÆÁº²©ŸsÑZVUUUX\|`¥tVó¡»^°ƒÞjQ7¤²°{a­ ¥±2#¢U”uÁA‘’E2”Á›qQTQ š‹Q:a§Á€` 27y’;2:0ƒ‚ 6à´Ã'`±SdÁö €|vÑqR=‚°IX`flrD°ãÁÙ²$¢m!ˆ‘ÕrÂCeGjˆ~ƒ ´"•u€’ÈÑ+vÃÄE‚KÑ}± ÕRb°»€¸Á†ù‰Æ’zp£¥¦§§´òÁ¤mOàUQ·¡TÿX^emu~‡‘å™ÿ`²‡AŠ@²­¦—ž•`q^eqéRQVÁn‚™°Â Ç1ß’:p\Ð\ZÏàHÑ©!^B/0ò¢÷ã‘N }Эå"ú3ñ¡þ0©ª«­®®«ªvÀgA4pJ$þÏàeinry}ƒ‡ "{qß³3ÑÞ™Bv1äƒ‹š¢¹½Áåñÿ»¶®¥šƒx}mzáD@>>AÕñ?]env‰H²¡ñ‹¶³3Á“Sta› MD¹ PðaØrð†-=y9Ñ`]YU=€í‚×QTX4lc‚‡Ð!)PíÀóÀžñ‹†‚ÁkCÖæÑû°½Áµceâ@¨‘+c±¼€†Æ²'ÐT‘)cõ?ðÏ1\Ñè‘hll€~÷R4ðQ‘ý•<ñtldZRLÿE>9520--ÿ-.059@FNXajrPp'RñÂbñ)‹_fJ€rèÐâÀ?•š¡¥ª­oÐÀÚw…5Qfbå‘]^ú u”Ñ¢«³»ÂÿÉÍÑÒÓÒÑÍ¿ÇÁ·®£—–`—XQMŸ`E°(!f ’².p—šS ”P¡âo!ˆ½Ak£t`FÁuvÍz~1ŽËÑqtnp8RÀ½pXà^fnÁ ×Ž•šý1¥øà–‘Õ‰¿i¢E ¡LQX`Nï“€ea%ÝPÖúefß |À¡ªÿ³¾ÅËÑÓÕÕÿÓÏËŽµ«¡^•ui`Uf€:ˆ°ÿ>BHNV^fp&eÐŽ“ #d!ŸW‚ã±ÔÌÑÆp0£T”pLJVàÁq`&p£0®B2@ @Â!3°àê2û#¾Ñ‰Ý|@fÐ# +ÀFRÎ#Q‘—È q­­Ì ¥`ðùÀ‘*jÁ,€’Ù±]QÛp›òð a攌š"špZ^€›€¦0Š ª0–°1›žà2Ñsù¡"Lec¦q«á~®ÐÁC«å «2‡0Ú’3`÷hž0ši±3A)`-`7“ ““¡‰<a` .Q‹‚ùjzP"4qÁ‘1 €Â@¼âÛ! `%2 `yÅt@]FðJôö“rxEbð ajh¥§ïaù}Qpßñ¾ÅÉËÎÿÎÍÊÇÿº³Õ­q‚R\— QQR#@Ž nu{ƒ–á_RýàÈ0u pmã°à0]±¸0…3a|vpBóVX^pZ }@WPþÃ1ˆÝ‘¾@O0q ôòðy0º`y• ÇàY\Ü0 ÀŸ…‹’™ŸBn±ï¯­ª¦J‚ypÿiaZTMHDBABEJPU]`øKÀÎq\ó›–’‹†àD"ºàE?aœ‹‘–@ôð3[@"3‹2ôì.É¢hä`XPÁTP¡·ÅÁð0›Hmðý †~€‚zÒEê’™˜ŽËàpibÜ%íMNQZhq¿yƒŽ–Ÿ©¡°Ã¿ÇÉÊÊÉÆ¬±«£š‘‰Ìâ?Q#·¡ÑÆPÅP‘Üñ1ñ0 ÊIñnµ#@Kpl‰§qÉ G0ÈjP˜1ž3yB³ýžH£¯¯¯®­©ðA¾cÁ>QMQU\×bjtÇ¡f·¹!¹n‘@Ãåñz\Ñ~€ó£©„A±®ª¦'¢ž™1R<€a£0áTUØ0¿€]Óq4ÉB(Úñå2ïòuÀBeýòPÐCÁù‘Ép€Ó•%`’Š…€°p“a-^Ðÿ•›Ÿ¥ª®²³öp·¶; ª¥ž–O‰‚z‹’µ d’~°,r>áq«Š¢à Bý³XJÈKRáÀ’(`@²Ó<@‡ ë1!0AЉxàÖP…%1Ü1brniþs`RLFB><<ÿ<>@BEIMR!VÄp‘ Êq`Ò™í!ÞpBD nþ°Íò ¤0‚! „±½Q¡QæñTa¨Ò› ü0I TÀ­€©T¢¾"@àq-³ÒÚñz'wJb6Õ5%31€r"9ÅKÎX°€y0Db_ ÖR»Q7ÑÁPusÑxв—¢é€Û²Ì2HJð¿§Bt$ -ðŠ2ó!?ðu!ÆPUaQ‚Ÿg£¥§Ï!€¢ŸÚuõðr©RÉPA" ‡1‘05‘>ò ôF@M°±¡qÁaYIAÀPÖ1\^btAá4Z2^4€A@1P@ [ÓyÁ}©c§§T¡bè¡yvE@<°wž¥ª¯ †A‡ƒ9€ b±3°TÐlmmNAm0±oPtRñ¡žÐyÐuxõdšáôÎÔ°“Jàvne]çVPJVâmÁ\dl¾Æ€Ž–ž£ª`ºíºd£›Fjb]X!‘²àð‚¬d6Ž€t ˜=ÁUTýÀpY°¸À‡’Ê ÿ`ÕpU¡é–‰Sjôp =rˆ°9ÂþñV×” *EÐ4’ ƒQ`È:ÀGp]ÐóúÖÀT1·4i Ò£ÐæÓÏqÇ¥§ª;®€ˆq‚xÅp.¡P»tœpÀt|‚‰RÉ‘°Õ Ï‘m@™ó²2ºP±QBÑ]‰P™—Ävàpj<ÁƒåpÿropNAMEï GPP_MUÿSICMIDI×à3eRðSPÿÿX÷ÿYSPÿQß¡ ÿ/SP3ÿÿ!‡@ÿÿGarretÿ Thomsoný´–Pgart@ÿterraporßt.netˆS 6þRÿ Disýt¸PedGuitÿ̼wÿ¼ @œ>ÿ¼9 [ÿZ]2<œ>ÿ:<:7ÿ<7><ªûQbb bªbb bb ªb b b b þ a? ±4 aØt‘r>5ærK2Úx2øx£r>3øxñsnˆE9Zb-2`aC>ú‚:Zbí‚«C<ú‚/˜Bú‚BzZb@`a8I<8V`mIZa:7a>@ a+CEú‚@Zb6*˜_“X™5“·‚C@Z˜:<—k>N b9a?4Za³>/ bM’75b9Ê b8b3b÷r:.ªb2b8 b6b42êž6Æ—²“<7`bÅ’+?7Zb4`b9&¨e’«7fb9Zb9`b, fb5Zb8`b ¢^“b„FE‚98Æbuƒ£6Æb3ºb:Àb7˜¨¹’„ªU-€¨2r8r6–—¶ls?&,§B/r.¬ZbÛ‚B2r2~gBY5r³’B9nrBtp¼w‰›­¿Ñãõ+=OasX…—…Â<%¸ˆ=Öˆ=š‚4 ‚,£HsËD;š‚/ ‚7rD4VšGQ;²,A²*G²UM;²)A²&G²I;²U$ÓÈ>ßÈG²BßÈ- ëÇF2›²¡²Ñb«F/›²¡²§²'ª›²¡²§²%›²ª¡²§²"Qا²ªõ²û²ºbªû²ºbÂû²²“ØŸØSbEû² ªºb  ”‚š‚ ª ‚¦‚ š‚ áØ ªš‚ ‚¦‚š‚ª ‚¦‚š‚ ‚¦‚š€‚¬8¿J¿\¿n¿€¿’¿¤¿¶¿È¿Ú¿ì¿þ¿Ï"Ï4ÏFÏ—©»ÍßñŸŸ'Ÿ9ŸKŸ]ŸoŸŸ“Ÿ¥Ÿ·ŸÉŸÛŸíŸÿŸ¯#¯5¯G¯Y¯k¯}¯¯¡¯³¯Å¯×¯é¯û¯| ¿¿ÿ|¼dˆSû;îÇUThe ÿdrums wiÿll rock ÿyou.Éß¹y¹æP¹[ÿ]<™x™&&&49"ër<:!YE!$r<$; }K"eQ"D#V#öP"*YZ$*<*Çe<*G%"~ $]3x#$7o%Ix%™N!&&N‡"}%$©5o"’ Nx+e‡"YT"t >–%Eo%Yx*K$8o"Nä%­&@Ï% w&ì!„%@2':–%§#‘NÕ(°#§#E„%} B¬±"õ".r,4.} :W$)–%4o"I8mE±"9R $BË1$8Y5Eó'å$Ió(õ#¼ D"š!×#t/†/˜/ª/¼/Î/à/ò/??(?:?L?^?p?‚?”?¦?¸?Ê?Ü?î?OIÞOðO__@&_8_J_\_n_€X2.`¾ïR20eZ0&E0r¢Z`/<@ŸB|ûµ[-r<-M O-O?OQOcOuO‡O™O«O½OÏLÐoâoôo*<N`r„–¨ºÌÞð&8J\n€’¤¶ÈÚìþŸ"Ÿ4ŸFŸXŸjŸ|ŸŽŸ Ÿ²ŸÄŸÖŸèŸúŸ ¯¯0¯B¯T¯f¯x¯Š¯œ¯®¯À¯Ò¯ä¯ö¯¿¿,¿>¿P¿b¿t¿†¿˜¿¸ª¿¼¿Îº&-9"$h9!^"Þ¹:!NF"¿Â}&ùÂBð°¿Â¾ÂÄ|]P"2‚`LÂ~`$@Ï0}<` Ë*™ ÁÃ*Ø$ÓòMÂNËÄ Á&$6È–VÞT$Á,ÒLÂ*%ÐqÆíPÞU À!×$<·*FÔ$BCØ)2Ø)AÆÞT*& cØ9*\`Rß*0ØÞÐdjÃiÖ18ÅiÕ$8ôÔˆ`aZÕ Á/¯ÛuÕ#Ô(JMÂECØ.íWYÚ+gØ,$2¨VØÌÒcÄ/3*šÕ@CØfÓ$Ónà½ÜM¢ÐÖ’àVå&Y[Ø$Øs× ñLÂ$Á®Ó ddÔß ß2ßDßVßhßzߌߞ߰ßÂßÔßæßøß ïï.ï@ïRïdïvïˆïšï¬ï¾ïÐïâïôïÿÿ*ÿ<ÿNÿ`ÿrÿ„ÿ–ÿ¨ÿºÿÌÿÞÿðÿ&8J\n€’¤¶ÈÚìþ"4FXj|Ž ²ÄÖèú //0/B/T/f/x/Š/œ/®/À/Ò/ä/ö/??,?>?P?€b?t?†?˜?ª?¼?¨À8¼ÊQÓ?8"æ<8<Eû88' dV@^A85dILáæ@8d,O>A8ñ4 d^PJD:8øRLY`aO*e8ñvL;a†M&8x d>@žA 85d=>¨L888a"UžÁK89hcÓK2Ç8 âLk`ñO*e 80\;gWÇ8#'_;`9[ 8Ã38a‚PL_^Q8ã: dÉ`jT78ñr\;`_*e8ã!–\7q¦]*8… d7¼SÜaÇwÊZ8+8aÉeáR²aç_UqúTe…i?o´w/jˆ’@ö? c/ Cÿp>€A8- d"PJD58¶mzpÉoe'8àm’E‹H²eŠ`9œC!)eo²B ç81šÂJ 8Á28a>@Yk}e"Ç8”}–W(8 d+€.Qao>Vdàƒg@jT.8ýYÉÿ™8\8Nvp8B“¡8N?OpW8YPœÄ9žÁ8©Ál#Á`&I#Á&eß÷C)žÂeCÏC4(E°ŸÀC@>òÀ.Y<.Ì2E°û*ÁC,*re²F°2E¢D`±Â3C1,Pn´D5Bm²"¨ÀD[S‘²¥±0k´¨° «Á1ÎÄDj°¨°™±ðÆ8¨±¬Á¡µ5*'ÚÔµ4¹·*{GC'ˆE¢EE±$üD`±­BCÈšQ­·E±.:ÅF°6³*:n´‘@.rY´D3ÕDÀ±ÊPm²Ì±!*Ô ÅÓ³-ßPßbßt߆ߘߪ߼ßÎßàßòßïï(ï:ïLï^ïpï‚ï”ï¦ï¸ïÊïÜïîïÿÿ$ÿ6ÿHÿZÿlÿ~ÿÿ¢ÿ´ÿÆÿØÿêÿüÿ Q¿c¿u¿‡¿™¿«¿½¿Ï¿á¿ó¿ÏÏ)Ï;ÏMÏ_ÏqσϕϹÏËÏÝÏ+=Oas…—©»Íßñ'9K]o?“¥·g?y?‹??¯?Á?Ó?å?÷? OO-O?OQOcOuO‡O™O«O½OÏOáOóO__)_;_M___q_ƒ_•_§_¹_Ë_ú¯bxŒ" Él™&Œ#& t±4–q4aU}2²:2²82²}$4”%3±32²9±s2±$:.°>Õr1¤bÌÞð1Ñk//)/;/M/_/q/ƒ/•/§/¹/Ë/Ý/ï/??%?7?I?—o©o»oÍoßoño'9K]Ñ_ã_õ_oo+o=oOoaoso…o}ŸŸ¡Ÿ³ŸÅŸ×ŸéŸûŸ ¯¯1¯C¯U¯g¯y¯‹¯¯¯¯Á¯Ó¯å¯÷¯ ¿¿-¿?¿Q¿c¿u¿‡¿™¿«¿½¿Ï¿á¿ó¿ÏÏ)Ï;ÏMÏ_ÏÀqσϕϧϽKà$e°ƒ<Õƒ&Y¥q¯Ô’&ÇÐ$:¾Å¯ƒN ÐhåIN±Ó°‚EtåmàBŒ‚}>°.r$@Åâ^mà:$)¾Å4°‚/I&e¶åEŒ‚B“5BI’Néæ2Êà‹â/20€EÂä8©0$ëâ0^€I"ú/4dàÄâ/ÅÒ&r ô Ð-r<-àò(:L^p‚”¦¸ÊÜ$Ÿ6ŸHŸZŸlŸºÏÌÏÞÏðÏßß&ß8ßJß\ßn߀ߒߤ߶ßÈßÚßìßþßï"ï4ïFïkÿ}ÿÿ¡ÿ³ÿÅÿ×ÿéÿûÿ 1CUgy‹¯ÁÓå÷ -?Qcu‡™«½Ïáó//)/;/M/_/q/ƒ/•/§/¹/Ë/Ý/ï/??%?7?I?[?m??‘?£?0µ?Ç?Ù?ë32}ð:ñA}ud,ðOO'C/R@„.HPð-4p:HeðWâï+r<+*S7ð[7[K o{CþT,o>oPoboto†o˜oªo¼oÎoÞàj&%î0&8 ²Œ†&}öj³Æ€x³dàx³Pyã;ûò1&}³rƒÃ‚ *e$’Y$‘ë1ØPRxøƒ­Zgò-IñP:A,ð0Y“‘?HzpPð/e«‘«tÆ€µÇÙëý!3EWði{Ým2eð]Dw“øhˆ“y”‘ÊàxDñzPð Ÿô6 ”"ECœXŸL3 -Iø„:HŒQ rVó«ÇŸÙŸëŸýŸ¯!¯3¯E¯W¯i¯{¯¯Ÿ¯åo2v@Í«k±ÛŒî«˜±4px€\ßÀ»ñ6¨@8°°Ä3¶}94p?¿ì29d¤Å1Æ€.A¼¡º£Å³"`‹Ÿ™¡°©™°°ÊKDYÐ<"`ñr<ÿ2<0}<0ÿÐ ]<ÿ[ž‘(rÿ4Y‡@4(+‘Ð#à°°¨p©Àï&e‡@0q)_5_‡@5DàÞò$Yƒ`ù£,Gß Spà,ÿ"G._pâZ@"Ñt@Xå IÏ,Bpjàà"Aó.dàtãN+t=à¨p…àY,#à>ŽãS+S¦å{põ#=à#Nñø7Eÿ;=4>–&ÿ@:„@>ÿ@‚];L4ÿ27:9™tÿF9‚FEÿ<:>ÿE 27à Öïèïúï ò´ ï1ïCïUïgïyï‹ïï¯ïÁïXðQÿcÿuü*<Nn€’¤®N‡@±éÖróßÂÿ^²y² ²ê’¼Ltÿ€†ÿ˜ÿªÿ¼ÿÎÿàÿòÿƒ¤»1CUgy‹¯Õç{//Ÿ/±/µï/??É í²éÕ 5â Slÿap Bass ÿ2Ä%´¿´ Z´ã[ÿ ]é”([r<º ((‰21‰2U}‰28‰23‰2/‰2<‰2ˆ3 3 3š9”3 3Y@‰1¥s+6é27é2Ueé2>ï82é2Né2ªè3-é29é2}û88Xï8B•³&9IB8IBU}IB5[H4IBYIBQeOHNCHC:IB7IB¹E—±á3)}<÷)¥B©B>©B¨C.©B0ª©B4©B9©Br©H:*ÓH6µB3µB7ßG‡?™?«?½?Ï?á?ó?OO)O;OMO_OqOƒO•O§O¹OËOÝOïO__%_7_I_[_m__‘_£_µ_Ç_ Ù_ë_ý_o!jA5b<ª5by5b,5b-AngT_hvcc;h*Áx/ƒbU\‰b‰b&‰b`‰bU*ˆ"‰b+‰bP‰bU'ˆS‰b$ ˆ#9‡«+E%r %rx"ª%r%r%r(%r:ª%r%r“ˆ%rZ%r‡‡&.IrIr©IrȃIrIrªIrIrIrùˆjIrIr ù‡(#bU5b 5b 5b5b©;Ÿ5b 5b5bª5b 5b5bq˜v5`´˜d4}<91 ‰a/@ÅжÓ*„4½7‘‘-}<-Ðà,V‘(:—’}’E£‘c4I‘’ˆb)s-µ‘V«c/N’}£’.‹˜(2‚“Y‹’r‘‘Ë“c/<»’¢õ“//‘Û-Eµ‘$eçÁ0en¿Ð+%q.eõ¡[0"Q¡$K¢rQ¡³21£‘åÃ2e£‘3ÿY<35rY<>>0¶.8íð• eZ672õð 0uQ¯P¯â¿ô¿ÏÏ*Ï<ÏNÏ`ÏrτϖÏ(¿ºÏL¿^¿ðÏ‚¿ߦ¿¸¿Ê¿\ßn߀ߒߤ߶ßÈßÚßìßþßï"ï´ÏÆÏØÏjïüÏŽï ß²ïDßVßèïúï ÿÿ0ÿBÿTÿfÿxxÿŠÿœò‚Â@·ôûÜ6u OvrdÿriveGuitßó³ §@³!n#šß “/e(‹à0eÛ(0âðY(çñY(þ»à6N(67÷e(7 r(9ÿ;Y(;<ÿe(<>r(ÿ>@r(@ÿBm(BCo}4Cß4ä÷>r<Ø}<@ï‚,@rýCeý<ëG}Y÷ÏArN÷?e}î÷<<}7xÿeC0>ÿr¿9>@r…þÞ>N(@r>ÿ$>SCG·@>»_W8°Cf±Yß)> ë@eÿ9@>@,>ï>Yq>ÿ@SC2@ÿ>I">þr²x@N Cÿ>&@>Bΰ>9êEÿY>EïGr;GÝICeEHCÿFm‚FÏEe4»²@rúCk²±eo> ÿCrWC!CrÿtC@}‚büš±<°e ><ÿ@rj@ÿ>S6>=ÿ>= ÿ<$;:ÿ;:9ÿ8"7ÿ645¿45öÈúØÕ3#ÿ210/ÿ/.-ÿ,+(ß*+8Òÿ*) (ÿ'#&%ÿ $ #ÿ" ! #¿ eÒ¿ qÒÿ ÿ ÿ ÿ ÿÿ“;ÿãÿ ÿ  ÿ  ÿ   ÿÿÿÿÿÿ"$÷(:Ò.1îòÀ<°°ž°ÂÔæø .@Rdvˆš¬¾Ðâô//*/$°e6ÏY;N{9à4rÖ7esä7k_Ã7_…ñp:;Aeú¦ãÏàAB:IîÕ<7N…ñAKƒ:_ÕRлâÏà> eº7S ?à.@Rdvˆš¬¾Ðâô//*/Qà;@îKà91Ãà7<î?à5:€ð48î3à25tð0(î'à/'!à-+þ¨P+(+³ïdÿ!à+ÿÿ!ÿÿ OvrdrivÿeGuitÈÿ¸\¸ û¸@ ][næ˜>ŸüPŸbŸCmJN4z‘ºpC‚˜J_™à’Ÿ(¤Ÿ¶ŸÈ•Lõr՟甿EmLm<0pJeùŸ ¯¯/¯A¯S¯e¯pw¯‰¯›¯­¯*è¯Ô¯æ¯ø¯ ¶˜¿&¿8¿JJºCAÀS\±‚Bâ@ lÀl¿~º´‚¿‹²¨¿ C×@9À¿Ò¿ä¿ö¿ÏÏ,Ï>ÏPÏbÏtφϘϪÀè®ÏÀÏÒÏäÏöÏ€ßß,ß>ßPßbßtß ˜;è‰ß›Û¯ßÁßÓßåß÷ß ïª$?>àÿ;9ý7I 20½ á,)G°÷&E±#!ÿý5°ù›Ñ(°ë°± ÿ  ÿÿ$˜ÿFèß¹± ³ °¬²'±ùž±œ°¿"%H±*ÿ-/ï13I 6þm°89ÿ:;<í¡>àb?¿>=2Àÿ; :9ÿ87û6 8¢4ÿ3'21ÿ0$/ .ÿ - ,ó+Á„¡) ¿( '’¢ÿ$ #"ÿ! ÿ ÿ!ÿ ÿ ÿ ÿ˜Fÿèÿ  ÿ  ÿ 4ÿ.ÿ!Çǰ۰Á² ÿ   U³±¯°î²ž±J:°À†±Áw±úu°3=¥78ºk±:g°=a²?ÝàÆ¸Ee¼Ooaaʺi`º¿ º[nv`ç š€o’o¤o¶oÈd´€J_Ôoæoøo .@Rdvˆš¬¾Ðâô|ê(:L†šVhzŒžà°ÂÔæø‚>9CeŸŸ&Ÿ8ŸJŸ\ŸnŸ€Ÿ’Ÿ¤Ÿ¶ŸÈŸÚŸìê🯯&¯8¯J¯\¯øn¯€¯’®š; 9꤯¶¯Ó¯å¯À÷¯ ¿¿-¿?¿Q¸‚üÛMºEe8~Õ Pÿerc OrgaÿnË»}¿» @»qc[ÿ(]ZƒÑ›÷Sr<‡àO-AReª27‡222 “2R™2$Ÿ2€3:‡2,2U,“2™2,Ÿ88«8•“2,™24Ÿ8Î9 ·8/Ã8.Ç!¿/Ñ/ã/õ/??+?=?O?a?s?…?—?©?»?Í?ß?ñ?OxO'O9BÊ@»EeóN„~ßaaÀ°ÿd‚/°ÿmÿ&ÿ  ÿÿ!+%4!ÿ9%^)-ÿ-g1V5Wÿ9A=0Bÿ1F8J:ÿN'R-V.ÿZ^cÿ g k ÿo s wÿ{U{ w sL`ÿkgÿc^ZÿVRNÿ J F%ÿJNRÿVZ^cgia8g`d`TawwO`L`þI` g c ÿ^ Z Vÿ RN ÿJ F B ÿ= 9 5ÿ 1 - ÿ) % !0ÿ%)-ÿ15ÿ9=B«F‰`nŸbÿs w {ÿ '{ÿwso_kg˜`“aýV pNJÿFBÏ=9û`ø`ÿ-)%ÿ! T!ÿ%)/- 1Ý`_q]påBUp‡bLrVcZrap`m`k´a¿sw ckÿ^Z Vÿ R N ÿJ F B ¿= 9†q1í€q)ða! `ÿ+ÿ!%ÿ)-1ï5rFÒOpJq”a§u o s(fb›`Cr%^’`Jq pJr$€æp9üafq)¿%! € ÷| b % Ã)ã`épæp^r=ÿBFJÁPqŽa p1ƒsÿo swsož`@p4€€OƒIs‰`Rp%€Žr]qçr-eqýg%€À[‚ s”dЂ aÁ€KoÎ…–aÞ„æ‚üpî† 1 -o ) hq1üg“tbFp9I‚?p/ßsw]aÏ{5užbgÿc^ZV R ÕrÿF3JNRw`tb±®ða£’É€6p{]]b¤`¡`ž`›bš`3€´”N Ë’Fp£p–:pÁ€R`:õ’0–qfÊÈ` Ìe¤‚z`ÓV²Èrc¹bk obbw7õ•Ѓ¢øHqÊÇ0JFBSq¨µFpq`µƒüÜ–{D{5r3£ý“q`þËp VR;N1¹‘Ÿt4ƒžc%p<Ê +p82r†Š’gM‚¢Ÿp“¡Ør(¤…U€Ð–k`Ó¢á‘êé’S2rs¯p ­q«‘ ÀbÎpÈ`ï N bB¡‚   pU€R‚”¡`f°³=d²÷“k`¦pu°ZV ’¢>„³B Vq’·Ä.ƒ¦pk¢¾€@€w91¨Lƒ pr>°‹`þÆFB=?3B F0°¦€àŒ`'²”jÊ€%p w{[µµ0ú¢¤Ðw`‘£0° €ܰF€`Ë`ϰ“Ê€¤`ÿ w{:w%p¯p»‚±¯¯‚)±ü‰bTq B =9S=#‚@£€u•”a²†‘¾€4gÈÀFv“²çåÀîƒû`1"bqi€q%‚–vó£F«k,µÜ…]‡ ”w–ùÁ›c¾€>uÙ…D–†äÀ9—wš˜`Ù#ÈLsÓXpp—-ƒ8ðBpŒ‘Á  ?2uʃIƒˆ£ÕÓↀ[pz%` Þbp5«Ðî€åÀ'ÀRpÇz`â Ëp ^6b¡Ï ÁRsòa‰êrò`%% ÿ!  ÿo!ÿ%)-ÿ1G-)1-1 Þa9=BÁù;1Áâq 5 Ÿ1-}q¡à!ý”â ÿ  ÿB…a’ô€6ÐÉâBß°‡.B‹r`qcðÖóa% ‘â$‚Ã)€—0²N.àSup^pãõ`)5qúa«Ð[pNã$‹ax+€ËpÈp c rbµÊ’ƒ±-:ÅôÆ Æf²ž’”a{µÍ† ÷^ʲR>5aJF>ÁY¡å?)J3ÀÔ`4=ÿ95ÿ1-)ÿ%!!>öqx€~q0ÐÐá =аÚp6ò6Òƒágp¸ò`òpì`,%jr-q‚þcXpF Á)Pr‚K“þbƒáð‹‚%8ò„àDõ ” £à ‰xE’‘Ó‚ûÑ)U²“$d².•² ,= =Ú}“üÄÊ€ ÐùÒÕ†A—Ù6 …å‚à–sbV±è*aµàö¦p£tV£€Ø°<Å’©ˆ ‘úcÚðè“#€aµ²`0–£U‚©ñ}Y 9H7ïÓ“ùaôA*¹ÂÙ’YÜ䄃V!ãÈ™©i&ßÝy9P"*)%0nS+Td÷ɨ°ÀRÖly ß ÞôM /ð< Q´“ÃGКZ‚d B£Ü ;‚Ó'P3ûP˜Q`#À€Ó†—}¥\ƒ$³ .fiÓ²2þDK5xòº<º6¤kª•b‰øÔ\ ð…0R-!C)6ù'W4p6@¥@)æÕÑ)²c+"ôð––a&DÁ÷  g%Çܽº‚„d2ðø@0÷3êàÀ@¬#X!šc¸’ÂÔôc¨°!‘×ÊS2‰ò·FF¡õà ñåT@®&C™`ðÆk§@ÐÂS¾nªI@#›U  =XAª`sð“ðÄúíSà®°¸µ¥²1'F2úSA².W@·¢€@¯$ìSše£V‘s`µÀ¹ÂKŸp„ I`Gðãð£0/þR8 ô£f Ã`µÀ£qhÊ ¶ðwSrã$ÙP“Rš˜ðqà/]dà{÷Fáw s!6̱½Á\€hP È2& ¸ŒðÒ BF?95#7ÕoúfXq4†Áä­Pá¦foã‚!CטteäÁEq„Àuað¸e%ã¬"ñ 1- ò1’É©VáÄ€3ÐëÆabxcBÀÐQQÜ@Z"7bC†Ç´âÈÀ>ìÂ0Krw¤–ÉJßtÀ1ªR“ a…ÀèÀ‹ÀäÕucüæ­7`B=@OácÙ~Ãp2ÑQìÂÀdb `{aqR2Á“ƒB;!Rr ã^hSq< ØøyeÊQ–p& 2a«ahƒB$ê{g‡¦8&Ö“à%Jö]¢!¡ò^ cgk M8˜ÂHµ-ÖZØò `vœpݳ¤ó .rBS,Jb¶¶R–<ôÂfa {! tA×0pƒ0”@»rQ–`cÚÔ.âÕb·`æªQÓIb:!Ó–,þ»xÖþ‚üfvXq¾ñ^bÀc/ÃüÇ„ 1-&çˆÃ½À`x`»àÁg†Á¾óÇùó•%)Q.¶Â¢cƒÖÃR³lõ½‘ JF#Ç&"AsÔÔ3ÐK³êÕÀ`% ŠaPàSB+Ph؇Át:|ápHÕ)tŸ@ "CÀïõÔ×3Ðn7Ò¥pÿ okagu ²`ñÀ¹âefôxt:Àd^½‚B€ó*úÑb¦Ç³kSâÔ>×pä@™@K1F†«"3Ðl³c`ÄZ1½ÿ‘D¶Kr‡Á¸k&t-RÊ0CÂý†fa3ÐaXrwæÅSp"–‘c# ÁÔÝt ã«pn&i$íÄT ¦zYðGóTÝp_É{I$ë=ÀÈVy €ýK)0ŠêU’)ÔpP0;ìÅ ;fp„èƒ8PcÐ  %#U%õQ`&ñÂL4:@y*¡ÔeÉgw³8P:ÂÂVU:9gäˆÀëÀB_sÄæ<n¶-=:æUá–rDw c.µ`v~¦ð¦…׃R–ŠŸCC„èca9Ðp ÿòZs,èJÖQ`Óƒ´#Âû°àRK`—æðQ‘5(ÞÇP0{¯ w ¸ ±‚ ÿc ^Z¯V ªÅEâ xòà3Ý€ )(FUC˜Rä;²ýVöa²`‘ÀŽÀ ŒÁC!Zp»Cc\€gž£ÀVò çF§R}0 5ç 1€‰0 %ù 4¢’° ÿ  Cû E`#ÿ(!<ÿ%')2-ÿ+1&5"ë9¹ÁBJÿNRVZ^ŽPü FðoCk’  žÈ“ ‘±ÁÿB =9ÿ51ÿ-)%ÿ!,ý#Ua ÿ2=‚ÿ'  ÿ   ÿ !ÿ%)ÿ-15þpbBFÿJNRïV•Q^ÿcgk¿os€R €©u~ £FÃÅ׃ò0¼ ² ° @bþ¯¡ *Žq°¤H Œ²À}pñ1þ²ý°Ùð‘ðBûF±` N ëR ˜QZ À c½4roϱw*CrÞb"aºó¯usœ Œ°¥r;¡!F¨)µßö ùÒ9ô·‚3n3y’’¦wqÜ ±Ž6iÁQ˜ãI˜ À$%ÿ³fÐþ°ð°²QI¨”*-p™à†eqÊ“û°7 -¿WQCöJ ‹Eû§zƒì0ð5 Ã’QAÁ’H}ò`^Ÿ`3p(¾ÿosw{ u _?uõ–ðKͰ°à30` ) à ²p9 ‡sñ`¿ &Rðý ‘q ϰ9`Ï%)0` O59º`·`µa”Èq“ Ðr èBñ)À bƒà¹™Q’àð 95%DA”€OäMƒí”P¨‚}ðÑàV¯/¾r£P¯ÀK4ó”P_°êä ›ÁkEp s#Ütö„k¶Û#NR5½„2 )í1!AÓa;`߀¡ ù¡m¡GàÃp¯Àƒð5££À b†^€g ˜ÁêQPµ@ 0UèPö"O&uÔ9`Ðû '_ÁÃÁUÂRä$žƒ¶’^À@³*ظ&馷Óû³0`$‘±©Pá&׸4€€9`Iq´ Äaq'¢ïF aNsR…b-pcÀýßrsw{‚x Â_²úÀNy4òþÑQGàó°À0`é06`w !ý`T`ýFb* ,€)€¥vxrGTºvª¦€ðŒ¢<ñ~OðÅ $èP·µO1AnJa1@E¶Ô+†€4Þ’=¬r1HSƒ˜ö›‚ ãžeà[°ôÀ" QÝ^ÀÀ2ã.LÙF€†p%!3Ð8€††@šFí%ÿD[ÂkÑvÕ€åÎ&ev?<Ïñ0!¢pŸp:œpð’ ŠpB`¢s~pÓð=QDÓV]ÓÔ¢ÝÔ´²á³0pC _ ×âßô *²rKSjœÌpÀ•w3ls>€†‚2Ñ !¬r¾Ã= ÈÔÙS .qVq ƒlu„!$¹Â1·ÕIçZV2õ g%¹¸h†O@ø%ë" ƒ!¦r®Óz€Lÿz¦&ð¥(øN””ù{ô` %* É;ëi“OêýC{çQ âØ~Õ„Fet—äú&ƒB`$£ràÓ¬ò‘6Læø²äQXÀ \Âb9’|rã™pÿ! úøõžqáà@°ÑLçÎ2û³ 7Á€ûqó³†@B݇z@a4xp¯õêCy0œ´ÜÀ!5…ÿ_„¤pë‘'áUð‘«Áæã’¡ð‰0†2/`±= ÷B" N Ír <¢ŽP AµñÀPµ@tà#Ÿ—Á3Œ#‡@ÓàK“„5‚ç 'â¼)€‰;…çD×2À÷¡ƒ³NpKpÅ XÀI¶ -T5èP(&Œã’ (õÜä”óL)õú$pp€t††‚Žƒ”]S”PÀXxšB× bù$Jâ¡z@»Ã€F@¬Pì¦RF`ø5  5²_€¿ @¹îP {$QæÉ'@8%¿‚¬N$2Ä'â râu$ûåIäÐPøAÃ’ ‰àåK$ôð¦räFvÀ𢉰Àôð °#‚«úƒÇJ×øŽùZ5á ­ÎµP!ðÆDí* àö{ÿ  ý Fa"0ÿ1!)%ÿ)%-%1ÿ59ÿ=BFûJËàRóV41[gÿkosþÉ04{!ÄPÏ0³’$=€ªpžp?…¢Ë ‡rp@ð݃€’  ÿ 9={BrN<,±ôxÁì (b1ÿ-)%÷&!V@ÿ ýó’ ç}{_"›Áÿ1!#ÿ%2)&-ý1jb9=ÿBFÿJ,NRçV+uUP>kþΠ)s+wÿ{"ƒ'/{w

ØEŽ“´ÓDæÃPCt•âûz @ à\"?b%~3³°Ñü§àÒP259ÿ?=B ßF J Æâ ëVò "kòa` àb÷À^¹%Ù˜0#ùdvÀ8C–Ð#€¨p.fH[öÏÖ^Âf`ðÁâ`!sÒîkÕ$S+“5à€ÛP܆,Ñ×fÓ}âw¹!s¶}×€jÆÎãž wv  ‘ÀF>ñ¼w€ùÒ5xÐ(à Ðù‚( 'бÕûÖª¤ïòEÔà@Gà§~³µ’ä.Ãw€âÙ÷kxyG¤ö÷ ,Ч€)£jöW‘*âg„“sU€wÐ ‚´•“ ƒŽ`ç--‚°ƒÓ§à§ ÆvbOÀÜ!ZpÚÖ`A[q^ N±Vx²êP¦÷!qð%±,%ÖƒRcg(kEhb(ÓKãâ^Š 1!ðµMÒi†‘ý±áÁ1R¢€£¶ÑtNpüCK j`eP ¼Z²yÐwÇ þdqkFgcÿ*^ZÿVRNGÿJFBþ8°+95·1¤).D!6é ÊØpïV N²cgkePþR^ Z"VÿRNÿJFBË=5°)3±ÈAó)b‹25?/qÍ¢³‚€%±³ò¢Ð;têLÔ#P þaac gk×kgP`4ôRÿVRXNþpbB(=ÿ9 51ù…b à!7ýrà ?° 7j¤aÒâÓ‰cÔ²“þK  cg[c^÷Rï&R~"Fÿ*B=ÿ9%51&Îb%°ð#`+ÿ p NµÈ†¤€ÉpuH|vôçp o9ÄqÿgHc^çZK±þQ JÿFB=95¦¼’P‡`%rß/€ mâá“7w P›Æzã òs{wÑÿkgcP¿^Zëb ÿNJFïBìr95ÿ1 - ý)÷0,!ÿI1Tat¡#¶\"ñǪ³®ÅS ZÓpQbRúXrU‚RßNCJ"bÿ=95$·1-±) þrü®ñ†=P ÿ)>ª 0lØâ™7ƒÀÙ!Q²Ý"POÄþó`+F B ¿= 9 R Þá % ‚?1ƒNsçCS„³fª„üÁFaPP WcÙacP°?‘*TW•|ù‘CÖÒC8P{¥7v¾P64ðþã k9g¨á!þM‘üÁJê  ¿B = vr ^j’ )rÂÖBÿ'ÿ  Akèá²#õ㇖€Ä®rª„¥¢ÍÀÊ3à 7â¿°ÇÒ'ÖÙ ³DÀåø¦x~1]§#ñêp#ƒ@vÐ,o§Â€%ôBI-ͨ1TÉd¢}èâS’ÿjáÔ@ù7ƒÌdص·< £Ðw3´€ðmÒÙ±¢Pá´•ð§=›ªP oÅàŒ—æÉ’ä°À{(nžá0âmQMp«ãNãxÑ×ܰ5 s‚ÁDü´B€D°Ã 3DM1Ðs ~ñÌqâ²¼• £JOF ^’3  Rüuƒó€!&ÿ xÿ; ?e²Yó“ƒñ“è¶# ÑBj —Bé‹w"B®pÖŸÀ(Æ'¤~HK1Ä=Èè ¤FI,Åäß“'% F¥·Àe‘…,( æÑ"&ç`Â(+B?뀿áïõ£ñs°ZYð%‚sâõ”ƒæ´7Ÿà¦ *€ ¯£¨F#Ð/’ç4¤ù&À-uá­ƒ±6œ¤Ÿà s2ºº¡‹5öŒ ±`ªP_#s°H î–÷¸oéº7w8Ââ )À1óvÚ±`ß@˜ ›P6Kï—nD©6H_Ã.+B¯¥âóVÀ‚WŒ ð­P¿ oŒÐ !€ø:}v!5–«Mp $€©8C/ÊÀCⳄóÐ €ú‚ù€ ˜Pɼq£³é sÌÒé »2·~<…!Ó 9‰»õ">I{CÈÓ2н#Áºù&Óa’ß5+1 =¢{%)‚ _ÐÈ65"läÿ@_SIL0\'@Ð0œ`Âm±¤Ä¶ÀþÊ F B =*d’ |¸TвÄFUÑÍ0bùáqYUD @ôm’˜ Šð ©b€òæI£Øäã#BRÔ'È1åÖ·óiõ‚'ŒPóùõH£  ÿ  ,«!›q¡ &%`䔜VUª÷%¯ñLpÙ Ñ,zÙ)XüýÔ0  q_² N°o" !è’3JÆ;ôÀ¥õ¾Ô¸²±ÿÀ'éá-éÙ‚TìÓ9¸YAœp Ž‚)sú<>u“KùcÀ fÀ¾¥/´÷’;´›P©e÷’MÄàÀf—¶¿Õ¢° wB€Ò#ïŠÂæm3.QÙ£ø&r€?Fð1—¢u1v²P¼d,19œ¡Ã#xSÿÀÚÿ/O@ÿÿ!ÿÿ- "DEMÿONICS" -þLNCopyright 1995LDýTEby Gaÿrret ThoïmsonŠNSenÿd commen¿ts to:LDþTEgart@tÿerraport¯.netLDTE ÿOr visitúÍE TEwww.ÿcybertheOque.Â@LDTEÿ/galeriÑe@P ALD)TEFor non-ÂBÿrcial use only.LDü‚_ŽXpropNAÛMEO@G¥P_P{AL±P O@þºQ???ÿ(?8?E?¿??W@ÿ0(((8ÿ(D4ÿ ?G1?ÿ7 &0 7?.ÕÄP-O@]ºP ïQO@-3·P.(`0¸PßPÝ ÔPP?ÎP%÷7?1"`??÷?ÄP ÿG3 ÿ ÿ.F??ÿP 8 ÿD ÿ 2 ÿ. ?<ÿ0  ÿF#ÿ1%ÿú1 ÿ ÿã$#H ýDV° üÿ"!#ÿ" ÿ7 8ÿ8 Dÿ 1ÿ . ý ÷P?ÿF?6 7 û3 V°.ÿ,! å%ÿ$ G-ÿ+ 2(ÿ"ÿ?&?ÿ4 8 ÷.t ÿ-?3 1! ÿ&$ ï7 —`.ÿ ù(&-)÷'DO@FÿE'%7 ÿ2 2 ÷0 ÿ L3$ÿ $ÿ"  þ…p7ÿ ÿ- ÿ??0ÿ  ÿ30 ÿ-'& ! ÿ  ý÷¹p ÿHD#ÿ-?ÿ8÷ ÿ !?ÿ: 3 2?ÿ - ? ¯p:pÿ:?( ÿ 2þyp)("ÿ3  ÿ#"îÿH 8?1 ÿ ?$ÿ !ÿ23 ÿ?8 "!ÿ?>?ÿ '&ÿ.%ù?;ÿ  -%$ÿ ÿ8 ?%ÿ?? ÿ  ÿH?98 ÿ?#?,ïû?"¹R?÷ ?'΀!?÷*Z°?ÿ-ù ?  ?®€ÿí?.~ö0? 2 Þ€¿@{‘.?~ ??$,€ÿ? ÿå???& ?(7ÿ?û^Ê€"ú Ýp W@ÿ?#?úÿ? +—++OAüŽT×Qÿ- -Å=ë`¿5 ŽTÄþŽT22&Ÿî5>)’ X?GO_BMPÏ·Pû Ö’@€Ž_õŸ¯¯+¯=¯O¯a¯s¯…¯—¯©¯»¯Í¯ß¯ñ¯¿¿'¿9¿K¿]¿o¿¿“¿¥¿·¿É¿Û¿í¿ÿ¿Ï#Ï5ÏGÏYÏkÏ}ÏϡϳÏÅÏ×ÏéÏûÏ ßß1ßCßUßgßyß‹ß߯ßÁßÌ×ÞßåÓÌßïï,ï>ïPïåßõ߆ï˜ïªï¼ïÎïàïòïRïÿ(ÿtïLÿ^ÿpÿ‚ÿÿ¦ÿ9ÿÊÿÜÿîÿ$6“ÿZlºÿ¢´AØê~ ÑDühz8ž°ZÔæø…/./ÁR/d//ˆ/D/¬/m/Ð/â/ô/›/?*? b4†˜ª¼Uàm(:Ê^ø‚R¦yÊÜî/™$/±H/Z/l/~/ /¢/;/Æ/—/¬/ü/? ?2?D?Ü/h?õ/Œ?ž?°?Â?R?æ?~? Oè?ñ?@OROdOvO OšO'O¾OÐOâOôO_–O¯O<__`_5_„_–_¨_º_Q_Þ_l_oo&o8oJoë_ò_€oSo¤o‹oÈoÚoìoþo”o"°oFXj|  5Ę­ú 0B×f󊜮ÀOäyŸÝò>ŸPŸbŸtŸ†ŸŸ%Ÿ¼ŸÎŸàŸòŸ¯“ŸªŸ:¯¯^¯6¯‚¯”¯¦¯¸¯L¯Ü¯j¯¿¿$¿6¿H¿×¯í¯~¿T¿i¿´¿Æ¿Ø¿ê¿ü¿¿ Ï­¿DÏVÏhÏzÏŒÏÏ1ÏÂÏ™Ï®ÏøÏ ß×Íß>ßßbß)߆ߘߪ߼ßÎßgßrßïÛßðß:ïLï"ïpï‚ïWï¦ï‹ïÊïÜïîïÿŽï$ÿ¶ïHÿ ÿ5ÿ~ÿQÿcÿ´ÿÆÿ™ÿ¥ÿüÿß2DçÿzRžy—¥ø Úì@ 'vˆ\h¾—¬ô/Üçoobo/o†oRolo¼o˜o¬oòoËoáo: ^4‚R¦qÊ•±Üñ6Z#~Q¢ƒÆ’ê´ŸØöDŸ Ÿ5ŸzŸUŸžŸfŸˆŸÔŸ¬ŸøŸ¿Ÿ¯åŸ@¯R¯¯;¯ˆ¯e¯z¯¾¯™¯â¯©¯Ñ¯¿ñ¯<¿ÿ¯`¿'¿„¿K¿¨¿”¿—¿¬¿ð¿Ì¿Ï&Ïí¸(ÏUÏ.ÏyÏÏÏcÏÁÏÓÏ¯Ï¾Ï ßéÏ ß?ßßcß)Öißßjߴ߯ߢßêß°ßïÓßùßDï"ï6ïzïWïžï°ïÂïÔïbïøï„ïÿ.ÿòïRÿÿ>ÿˆÿfÿŠÿ¾ÿ›ÿâÿôÿ¥ÿ<Éÿ`$„H¨•™­ðÍ&8J\é€ ¤hÈŒ³þÝò4//X/j/|/Ž/ /?/Ä/¡/è/«/ ?Ï/ø/B?!?6?x?U?œ?®?À?Ò?`?ö?ƒ?O,Oî?POOß ß5ßtßRߘߪ߼ßÎß[ßòßßï(ïçßLï ï9ï‚ïdïyï¸ï–ïŸïîïÿÁïÝï6ÿÿZÿlÿ+ÿÿOÿ}ÿÆÿ¨ÿÈÿüÿ«ÿãÿ2D!zYž°oÔ“ÁÚï. R'vˆIe¾â¡/Å*///3/r/P/–/}/º/Ì//Ï/?—/&?å/J? ?7?€?b?w?¶?”??ì?þ?¿?Û?4OOXOjO)OŽOMO{OÄO¦O»OúOØOáO0_B___x_W_œ_®_m_Ò_‘_¿_Ù_í_,o oPo%oto†oGoco¼o›oàoòoÃoóo2pM”i¸Ê‹§ß$ãH4~av´‘›êüŸÙ2ŸŸVŸhŸ'ŸŒŸKŸxŸÂŸ¥ŸºŸøŸÕŸßŸ.¯@¯¯¯v¯U¯š¯¬¯k¯Ð¯¯¼¯¿ì¯¿<¿¿#¿r¿„¿E¿a¿º¿™¿Þ¿ð¿¯¿ÏÓ¿ÏÏ0ÏnÏKÏ’Ïg϶ÏÈωϥÏþÏÝÏ"ßáÏFßßjßDß_ßtß²ßßÖß½ßúß ïÍßïBï×ßfï%ïŠïIïvïÀï£ï¸ïöïÓïÝï,ÿ>ÿÿïÿtÿSÿ˜ÿªÿiÿÎÿÿºÿèÿüÿ:!p‚C_¸—Üî­Ñý/lHe´Æ‡£üÛ /2//V/3/A/^/s/°/‹/Ô/©/ø/ ?Ì/ç/@??d?$?ˆ?H?¬?—?¢?¶?ô?Ï?Ü?*Oo|oWodo²oÄo†o oúoØo0ñoT>[p®‰Ò¨öÊä>b#†Gª‚Ÿ´òÍŸþ:ŸLŸŸ(Ÿ‚Ÿ`Ÿ¦ŸgŸÊŸ‹Ÿ´Ÿ¯äŸøŸ6¯¯¯l¯~¯A¯Z¯´¯‘¯Ø¯ê¯¬¯¿Ð¯ö¯D¿.¿<¿z¿S¿c¿°¿Â¿…¿ž¿ø¿Õ¿Ï.Ïð¿RÏÏ:ÏZϚυϾϛÏâÏ¡ÏßÉÏùÏ<ßß`ß#ß„ßGߨß~ßß²ßðßÈßï&ïåßJïï=ï€ï\ï¤ïhïÈïŒïìïÁïáïöï4ÿ ÿXÿjÿ)ÿŽÿoÿÿÄÿ ÿèÿ¬ÿ ÐÿóÿB%9xPœ®€„³öÒ,ðP7W˜}¼“à /Éö://^/$/‚/H/¦/z/š/¯/î/?Ü/$?ä/H? ?:?~?X?¢?h?Æ??ê?ü?O´?2O×?VOhO(OŒORO~OÂOœOæO­O _ÑO._@_R_öOv__š_¬_m_„_â_Ï_oß_*oó_Nooro„o–o9oºo^oÞoŸoÉoóo8\%€’m¶ÈÚ|þ "äF7|S jÄèú Ÿ­0ŸBŸãfŸ(ŸŠŸSŸzŸÀŸ–ŸäŸ°Ÿ¯ÔŸ,¯>¯P¯ðŸt¯¯˜¯ª¯n¯Î¯­¯¼¯¿Ù¯(¿ ¿L¿¿p¿‚¿”¿1¿¸¿V¿Ü¿£¿ÏË¿$ÏÏHÏÏ*Ï~ÏÏ_Ï´ÏÆÏØÏtÏüÏ™Ï ßéÏDßß-ßzߌß^ßpßÂߔ߿߶ßÒßïøß@ïïdï0ïˆïVïoï¾ïÐï ï¶ïÿÚïæï<ÿÿ*ÿrÿ„ÿUÿdÿºÿÌÿœÿ°ÿàøCg1RxÁ¥÷ Ûé?Qcu‡*½–ªó/Ðî;/M/Û(/ƒ/•/§/¹/Ë/^/n/?Ù/í/7?I?[?m?? ?£?0?Ç?Ù?ë?ý??!O³?EOO0O{OOŸO±OÃOQOçOÏO __/_A_ÕOe_÷O‰_i_t_¿_Ñ_ã_õ_o•_¦_=oOoaoso…oo*o»o‘oßo·o'9KÙoêo“¥·É^oÿÕ#úGYk} ¡/Å×éû‘Ÿ³CŸŸ,ŸyŸ‹ŸŸ¯ŸÁŸOŸåŸrŸ ¯¯-¯?¯ÖŸc¯øŸ‡¯[¯o¯½¯Ï¯á¯ó¯¿“¯)¿¶¯M¿_¿q¿ƒ¿¿§¿=¿Œ¿Ý¿²¿ÏÏ%Ï7ÏIÏØ¿è¿ϑϣϵÏÇÏ_ÏpÏýÏÏÏ!ßõÏEßWßiß{ß ßŸß,ßÃßÕßçßùßßïµßAïïeï8ï‰ï›ï­ï¿ïQïãïpïÿÿ+ÿ=ÿÓïaÿúï…ÿVÿ©ÿŠÿÍÿßÿñÿ—ÿ'´ÿK]o¥?É©¬ÿ#5ËYkø¡³ÅqrûÊ/ïC/U/g/y///¯/?P?b?m5ްÓúñ´æ ~° ; ÿÀ°ÿÿÁÿsÿÂÛZy¬3#y´0ÿsuu¾3+ýuÆ1ÄsôÙ0Ò3*Ù3Åókï1è3kk_ë__è3Tý0[[?ÿÆ @@ž C[[Z"@ C(®"@UUU C+0@UÿTTÿÇóTGC@CTT<é7X@@CX@6++‰+\Dg@*t@\Dt@(´‚@ND(˜Ñ#@C#@Dôñ°â° C ÷ C <"° C ±é1_ûÒ3%±žÒ3 ¯@À17¬3…@Ÿ1Ó Ø{ ‡9Ç{  Ç4(œ4¼@®2%{î¾4Z~~Ò3 k~ CQê1 uMP:PAVQÓ{{:P^BsfP{{~´0È [sQ´‚PwS7RyyÇ0ÉÒ  SÏ2Êý kŸSuu«0§QÎ1²QÚ2•Ë•0 ¿Usò1ÉQ7üÒRÖPkkjÿÌ âUý0ÿ0íQñ*ï2úQBÍC_øSB%@afD"Ca+B4b0BÎà#ZDfêp 1+œ0®2y @Ô1(uDPÆ¿B*{MPDPyQ#±y ZQ—Q [-‚~i{%@§Q,„{_v`š†r*K„{suaaÙ+^ƒtPU¤ühâ°o¥!£”½¦;r7ª©B+v¼R¤ò’ý>x%˜™Atgu%™™ÑC.kt o¢i‘wpu{s pR¡À4“hµ“q¤rR 4“ LŸwŠ (*4 “±wc+7Èq$AÔ¦°Ø4 À±×qvw»ƒ ÿ(UZ[[lmt?vwxlY5Paÿ#(55)"½àÎ [½>À -/*WÀ1ç<2@ê1_}_ð ƒ°ÿå‰Bûu{¶ÍDÂ%¦±å°_k¼Å0߃ ÿè67û{w<<þnÀæus(oÿì•0UMPýuÍ“áu_[ÿï`:‚ô¢Ä¨Àà‘Á+ÿE󨀞Á»Ç¨ÀÞ¬À_ÿöÕ€8P-‚ôƒÃ…ÃܬÀTÿ‘ù¨QBPMP}TÀ ÿäuûsü=k­Àÿû¨PKRþeQ_<÷< ÿTuóuüÿsûkò_+Z°Àý¨P cSb€7<öˆÀ [âU[ÿð_ lrŒÿ¬­­ÞÞßã/’ÿîPuq‚‚PýUgÓàÁÑ›R°S öï<+8àTÿîâîéç¿æ%*7UlÀT¿ ÷ s®Usî1ã%UàYèîþèÐðîìéçÿãàÍÍñ| QÔR@U öã <¾V,‡âU¯1<ìÐáîÕàëÿççãßÍÅ®¨£—z PãSA.A†a~s@ô ÏW¾ÑÒ+ZÌàT~Ðàé­™•äæ„Bòâ<`€AÿbÜ¡?óUáWжñ#ôÞ]€T0côâ6:ñþcÜ¢?tGpËJðU˜Ããÿ*[!ì듆͒TT:û¸@Ä@È@ëøR@k±ós 7õU@<ôðwU[Ìàé<Í*sa%Èõòß@npþr"ÿ&$/òæåö[[šÐ4à* ‘[öñûòH%WuçA ÿ ÿ""&/:9@AÿDDc0ð*9À¨˜;__¿ýT.ÿò<§<+] $/¯0::@o‚ss““…ЇÐãè1*y7š;+__Ìá¹ðâÑ_X4ÔÿÍŠŽ¼ÏÑsÓáq0s1ææç°0IÞ–À{1ô§ÿ Ž3W4ýÖ¦0q3®3ýèë0ééèÿEø¾€0²0øŠ!u‚P©2­4ê1íé'Bëëx0÷ùOvYp6:²•TAG&Dæ+Aëë´1îÀý¯úèA5¦Z?y{{é3aEüjAj@ìé,ÿô °fµ‘q©¦‰@ÿ~üèøéÿùëý쬊ÐÐÀ~¼%FGZýÏA÷ëüìÿãÿòÃo°œ·º±Í–ÿùéöëì×ãÞ“=0ñPÁ³qS¹ðÕpCcW*ÿûéúë½ 6P’C1JÀí_̵YÖrÿtw|vZ<$ÿüé íèeQ-JÀä¯<Ô±mQtïZ5 Ä/’‚1–ÀÛ¾qâpÿ*))$_õŽ ë{~ÖPß *5€Áç'À%d©±‚FBÌsJC%v»s1¶òx`i‚ûZF•ZT(ÁàkAÀ^¡°fÂUZÿ+è_þúÆ6%ÚÎõ#¦±À°[_úÀî‘À_(ãŸs~ ‚hb_ r`\àõ[Àâ‘ÀU¿Þ%s~’gäÑéÕáì[ìC”p(}M‚yÐzYà©q677dqc µr4p5 Tÿ¸çйÑéÒìì!àÎé maÒjWâ7+4ópó dq.¢mpþóðøðüÿïôîìã/Î …yTqYàëû7’,q(<‚´rVéòðŠƒ¹Ò¶éÓë3³Pp°OÆ *ÉÕès ópš¢T+r ‚EƒÞþN‚ûïúîÿëçæàßͪ<ÓU[nÀqÐ_•Àà -ÊÔuk2â ë ýa6(B„/ Õð# çå€Þ®Ç¥™|uqìâ2öï uûƒuuWÎWâ 6 ’•7ì/"’Vã‰ïÞio:’j/úË ¥ ~…2À _Måî“ d“ZZ?Ù8q3r·<7“‰ãƒUÄ÷ᘒ%AõÅ2ôÀ %*NåsY¶‘ ªUQºÃ”B†?X\bb_fhi°T›ö|zò [øÕ Ü;Ê’…£ F±ümq/"<<5%)4÷55=e°D\bcÿhh€„ŠŠþݬ¬½ yã÷Yó *+´Ìް:¶s´q“òñïG²¥³ aX\ccê¾±‰Ã³­ÀÂÂÂ?ÃÃÞÞÍc°¾ž1 +è²GÁãݰ‚£3rbî¢³…<„żÍö}Âßà„Àáãâà½FÁÈ!ÞÀø_NÁ:¾D…<7Þï3pZwuwUƒ77Y|Á›àÍ„Àãã¨0©0æ|ßÀé2‚¾}nÌ ¦ÁE åÞ° ë¤óð¾xPx¶¹¾‹~…dÝÂé5ëžE'@ݰy%  6%GÁj|rß±q”ÿbî“77Z»Ð‚Ъ´tTàÒäØqýìAÑççåäâ­å\ 7`YÑ%U)jÿ|rkÑ:A„4qÿÞÞ77dÍÔÕ/ÖÖÖÅ준—Ôô Ñk á±!¼™?ï¿« gköE E`8Ô`~ÕÞ<7dÓáÜ2íÓƒXã© ëéèü¤Ñ±!ȶ™rY5Âe26‚+† YÑ%ÄÔŽ#òE`1°Á˃]ÞV7SdßÞ1©1d3r­k"ÿÔÐȾ©”lVÿ) É Ì.)WÓZ€äxqñáö0Ñ–¤“b7Yÿßåøå­þmpT–Ͼ¸¼Ç߯ÏÓÖD“p°ôÄ%WÒ¸`õ0âx°p•@±h7VÍt1þÞÂææ­diªÍ÷ÓÖâ¯2’ÑëÄ(#:#Zs?÷sußà*ð¹ðVÆ7TÞ®0æ¯çñçÌAFÐÒ#" 4Ð# ×ä`¢j ã|0-à–¤7ÝT©àç÷”òöéÿÞÓ\Ì!€3#k‚쀿÷uUÀòà¾@åîÐ"CÜñýëýûPé-Ô àG1„5Ê0kñûó_<›œP„¦óiýçdGìøì¾šÒ’Õ½9Å r ¹óPATpÏåp×óYã܈’Òðîßð'Õú7=@† Xp£ kPAÙ8` ›ÿ<7÷7ßTÞîé¹ëï×8G¤Ê0ÓZÙ(€k `Ÿæ-â•¥“Þ–Ðïöï—‚ØAT¢óð&Xp k'‚Sq–ÒêÛ´DéEù(FÍ T<* è¶P{íï“ðôN€ïü>>Kܬ¢PñT› ˆ"* ã±A€Ý¥hïòÞ"ùïý…Ý"aPEXТUQT(aàÜÛRg*ÉõêòúQ õU"êÝ’K? ߨq|`Ü~a€T; ÛPøÝ›%—£òüÔ ˜"ìÞ“‚3æ˜PärP²%zv[Ò½#ó‹PLA‚YìðÔ!– Ž¡ Ißí  °%\¿!> pÞ 3þ¡!1ÿïÿ %òêêï“‚E ™Pêß ,™R:Ò×[)d0éUÉ.p ýf!%ÿÌ\úUWpÿÎçP¾Cª÷îPÐö1#gbYßw—xZ6íÿíÒj (”cY”v¿Y*  `g=L¾¬ÐID¿eU* Ÿ`*÷<3 Ð ( KRÀ‘é°átqZ9"·Ï Usàgb7(ײ@ š'­Ó.p*ùA[×ÿîysU*Þ; ° Zëg*í 4@ P`*<s&ÑÈ!¾DUZ_IDosU(¥€ªZ@S~_øA”bŸ` &r®/ &Ïj›Uð@tq%ðAq7—¥”A~ °”dfÉ`^rwP(²0×+k‚¿@msÿttwwx”””ÿ–—™™¢££¦ÿ¦¥£T:Oq_Vr7 ù`x`ìuPvQ)²0<ÿô<^ÅÏWÏÏÆJQÅOR»UPB£ ˜r½@°òb¨B1Sjp*u@WÒT¨GUNSUQ?Ž¡ a€›puUÑ%Qh!ÈàTÃ{UæWÒ!…GPH\ªã &p* á`– 1_âs:À¢p7¨rD‚0â}Sðm€#ZFQHPÿĨ¥££ž——Ÿ”|wutÃÐÕ³UUbp” º`(›ÁpýQñÍò½ƒ<*É0{k‚%T¨ÍÐQ ªq”`T áå’铼/á`’% scƒk`›DbB⽃õÂ)Qm%jc…ÑGPÅŠ^Epí’zÆJ¡‘B`r¬ƒu:Àm€%°g^à<< )ea -ƒÛYÅÊ`ÁeVr(¼J Ÿ öU¡_ [úƒy~±¶üa(wUZp å(É0{€êr¨ÑїѪYk‚,qà Y äˆp ;p7Q”<'Aˆ%+TvNÑh^t ëq…op¨VWÒÈr±( ‡1%(_«•[›AŽ&qc“t¤]q'Òbqsà‰pÑ¥ L`AP%‡1bð- 0R~º€ Žs¢¸°yaÝE7¡ÏøZ~°ƒöÃb¥ƒó<ý+ý6'P™B¾€WÿWYTŽ)7x`¥~°ÜF<% t¥”5Â]&wÁpp…TÏWYÔ¨‡%·Žb¥kWeVÏ«‡Ø±<<» &>@)‡êp¨L`òwpWdez+“l2’nrrl6€át°µDƒ^@ÿ%Z[ö[p< %eaÈPm¡7¥Ñª^AU[ ‰ÿeqrrnn…ú‡‘‹Œ“?Ž ø³{°Ú³*7ˆ+µGÁc$bqω)§qÑÁ6 Ñ©¢fY䙢¢ÿ¢¥¦¦¦˜ÇŽ 7Ѷ÷ÁÅ`Dmð®—_á⽑†ÿ)YÅÅY<±÷Ô‹Ò1ÿ£¹©vY5#ò ™Òà¯Ü>$°÷k^CвÙóð‰ gë iÓÿÕÕÔøÔߪ˜¢ÇϨ   ½í7#á(³< t‰ VTP‰ŸUuößЛÖ*#ea>PvàÊÄäþ àÑѬ¦a3€‹ &qUŽÜž`_EÉ0#œƒñŒä<<˜Eè£âÍÿŧ"€ ɪÐjáTräöb¾`C#>@è\БãîqÅÑø}Ñ=ÀB¨,! 'p_Ù{à,A[6m0†á äÆîYÍÄ£ã§àϬÿ©ýûK$N C@žu\¶Ä#m1>@#3*äã‹â<¥ïåHöÿÅ«ý(ÖböUD`~{¶ó( m3É0I Јíáä¡ÓG÷D¬Dàp@òr[pn^A7% j5†áXP6ñîVÆÂÓíõÍOò­"$éQ- ¼Ða 7({ð÷/Ô‡àÌ$Šóù¬€Ã>ÍÍÍÆ®çSj$Bv$? ôðog! % Ô¾PeԀž>ÑÆ¬@W@è *è`µ`j· wwaÍ6AðÚð‚ð ìÌ 6òTÅ‚ͬ?@!´¡0ìÿsuwwl<%®´ë6á7û7ŽÄÓ‡D-»  h w%{ðæWÑôð•0Yê°ÕÃDÝ-Å »Á ÿ (c0ëé{ u@+îi0I–T* 5A¸ðö&pTo ÿ>XòXYõj˜m\ +(?~*uID‚‘<  iA+Pú@¬ UÚ¾’5¸#mw•Óttÿtm{%Óu~\EÂ6Ü"è©Aì W‚ðVçXVX.1y#ewuÿ÷ujys~}· ŽgRT<¤BëE&pMX‚ð&4-125Yñ}w0`l[[eTÌÓ~°àok`PÄ· Y$*çE2Q&ÁY¦o(524-2l1uët[y#TdTT(?k<_Q Î]cTT,XÞòYÕ*>V@nÁ2XXZ~2lYy%ó$ µð…si Ãò]AY"HÀª4b` M AAq5oòóteÀ3y!;÷{ë`h"{õQ€ªP\dÖ`µRu½³f0YÎè+6bBeBVe0}1Ð0/2B`àÖ@Þ€pg"%EbyWŽFT7 ¸T\d'ÀýX @VöV/Yvp@ZCdD|Øa(Sf#(™c€Ñ#hS) ³dSèH´@RÉ1Z¶DÉCXç¾R%e$%šbyˆ™pñ2‚ *y'ÀWQ RAlUtDßV7÷7 d“%ðåqZò2N3*£ x\p­QV @ÿV6EP7EÒuH (Ài8€ÓñKo F°õõJ°Yš³”””|?|6x&5ÔÌЉâ“3ƒ×cÀk!­%£ Kœr(ܲãVxç´½pÌx 4€ÒÍÓ6·*ÛÓG¡ºl ÄJ¸0é34¤l7Ä||x?xy ËÔ^á$ààNÕ(ÛÐ?0ãÖjÅwJ @5Ôò›"ZŠÅò;z5AÏѰâ±ð ÑŸ3Z•ÓPÆáô>!ItÁQ3懃VvÂâÂmz^áõàñná¤ÇãâÕ7èkHtÁÉ;*ÕAQe7ÒãÁwwŸ|*ñôZb÷só{yÎä*†peöoÔ#cöÍ Ww†×?Y|)õ]ñ‰OÀ.ãZ°Ð6Q+ã7½ùõGtÁäËÖÓamˆÕp@ ~²ªð#\ó´ðó×u*é0uâ7zñóàÉÂé(<”Í¢Z‡Öww5ç€:åR%¸óÖêö6†pñWFð¡ØE@9v&瀀?àSìè4´#´ïeEÖ±© aeâÀ¾(å ‚#³%(¬0£ZY…<û%Ó€ìFÎ @© ÚVüÕÑ)ãvVƒó­0èsuzwå[ âçoÐ @´,ðµÓl8ÓoYf†o(ë_mðß|oX)´ãÕsÁeôY8Ðl<ý$2 %ï%%$þÞýK¹)Y;ï ¾ Mˆý{ OˆyÉz¡j±3—ÿÙ¯¾-Q ñòòðÜ—ðÕî4Ò ú¡áôòðÞ¡$MSõÏdXáöòðàbð%ýB 1 OÃÒ þ„°÷§ &ÿ$$'//444ÿ588;;=>>ÿ=4^yí0lœwZ3 ñ¡ÒÍ¡„°ø€~õð']ó]¬`û]] jU [7éDZv‰f ¥j" ‘€lÄ #M_ƒ‚ÌÝrd" â c2Ý#àôƒ×í ]¿YõY qkÇ_>5y!àIw Z{á…T*£ Ø`ú0B „ö è÷YûkZ Ñ$PþR F7~{Y†Y¢ ^á ^2I¢®Î³ …ž|ò(²["AŒX> D(y~™Z¡%01PAAPªÂ(Ó "|ü÷kÐ0YX÷ïX¨ðB —0-!¦ [3þ5úù7ðº‚f¿'ŠFYX(±õ[c!õh ( ¯@(ŠA_Y¡%%ü6B!K ¹†p”#‚‚õðÁ§"F qd ôXÿV+*?×UâAsY¢×[5Quõ¢*ƒöCî4/2Úð”#;õð?ÓÓ´{€d ò0WU>`=Ç _ãB. f1ÑøFˆ‘/8 œ!ªE2(°Z 2ðU¿ < [‹Rkõ£<ûD(¢.<»ì>e" ¼ pÆ@XYlmd øþH1_[U; »TŒQyuWõ£%CGEd-4 ?2ÞÜ3jkj d•g±¯x"û#_#ò0Q(,cÆ Þ°‘€*_F´™bŒ( Š1*CýZ1Xeš  ÝŽEmssp; Ñ[ÐÂõ¢Ô 7PkúÙ`…²€@1|EþÙA~~$$jCly`%G@_õBIs¤D–ÝkñàlΜ;ÐEÐe}}~~} ÈRïm~}{ °;&("tWR0¡‘€”dq€N`hQè…²Ø$QÒAYýj„@Zz{}}zþ0p5Y^| o›jG@sss¤¤CRŠx-3â#à ~¿xU0@Fuzÿz{{#ï€ìsápÃ&a®ÔT YjÐm^Ñ6I À%…üB–ñ‚¤–„eSçQ…²}'i[úa e^Ñ[I *|†`örø†L¶adÃa}f_ßPþ[ÑsI(_HÚŒ€ÂQ óˆS“ J$jÔ0|'h  YsIP?yJ 1—aý–_÷_ÈHïâÍ ]qÔT YzÐlÁ7K ò\…“žaáåÐаNീâàë[r(í²±³UÁ‡æøÁÜ¥ÓfA*Áéûrç¾(WàÉà‹á€ ‚ Ú$+½ ðçq&Áþ+ËW#ØÑá÷aQT%äý–Á%6|©µnÄY(† ØñOóÀà<#Áà»séàÓÀ;ú¯±[Â[7úNø¼ÐÛvÒør ÑÀa ö°À%¨ð×ÿzˆN öÛûù ëñ"=¿ý7 AZ¿T( ÿËlÐ÷ßyuu°ÿ;lÐôsk|€ÿeÏlÐò²€ ÿÐlÐÿñ_Tÿ­ÑlÐð[žÓÒlÐïéZK¡ÐÓlÐîUûÆÑðT½ý ÿîÁÿ7ü7Žÿ@+66„!m‘±%~•Ðò%Á2þ€²6 (ÿû(õ%ï##Æð ÿ $45)ÿ$? %ÿ<ýTT%¿  äÐßóû#¡µÿ "%4é;¦"C >`"û$"’8[x T6  PáÿðÝâ- õ!¢&C5ó aà )5ßTl  Á?zÀðq±ÁGõÁÀágeZŠeåXxû"E",÷“[ Û¯`í©ÐU ŽàK`ÛpÒ!í4W+¶°Ýé ñB[æMQ%´"ÏÐ"þe"V (ÿ_ +_7 èXó‘ã _ k[6?€¶ nB%Pîlñ 'õ0(Þè“Vÿ7t!¾-°(>ð`ßî1èçÿååäâÖÖÔÔÿÐÏÏÇ»&‘Üh! #)T÷á,üM€í#"Ô ÿÔÒÐÏÈÇÿ¾¼¶¶¶±±± }Z’h'ÿ6YX4+ÿksT ÷ý_ Ïб û€1}ulÿZT*%ó“h  %VZXþ{ð/j_÷U[ñs sj_[T9ÐÕÚ'Ñ`$ð[kÿýT [?7 û7‘ð1ú5¯p<>þPÀ_jû[ D+œth!MÙ@=»áî²+ðU<¿+ +ðÒ#§›Úi#a-ß[Z ú.@[µ&peAù+ÜÑšìÂ5ìòVð Z÷óTh`%*_ù*ÿИs@ù’/üT_kU(“@(¾@— ˜h 0¢—VßV1 €76?+ýTê€ð€Ýðj< ÏÐ ÿ% ü%ý#¿—ÄA ì瘢-2°7üþùk!¹ L US–s@µ$ôGXý@0óÐ*ç* ½•çPTs!Þ‚áúýŠà Å•ÄA_5¥¢3í*¶ ä 's»PÃá Ü¡ËP7 –R9¢7¢÷XVÓ0%* þv”su ÿý û ÆÀ“ÄA0¡Æ¡8¢¾a/% {V<ks"üPŸûˆ@cy £b³? €²/<<(þñæqðž>`ø“ÙaS&VÿV>@ýTò+@û°‘ ý×ü aœPVs÷Vj … Vbþ3²uy · <À Á7‘q`€ ¢bŸ > 6x”¯uÿT ÿ!&!‘ c¦¸£Au Äa@&¿`ÿ&&//::@@ßADAq` Þí²9ÿ° Þ‚²[#D¿`Dcÿc‚““ý’2s$VöVÍf€C ÂÛß“¿`““~|ãèë’q`·>er$@pó ñY #è÷ è!òôöù{üIŽrZY `ýø¤` <((¯âwù] þöÜpû Žr %¿*7TZ[j¼À5ÿL "þÿüþýý?üúö’”&À4Ðÿ Btÿu%öÿ ööòïîÿéçå­™˜ÿ4â âÖÑÏǶ¶d­Ðÿɱœw×[<%zÐÇD€ ¾­Ð´UÛ£ô^€gÑCD€ˆÈÆD€%À³Ä°À p@ÂÈá|ÀÌà#%8ÑíÿÊÀQÀky{ây‘Ñÿ樀 77<7U_¡§sæÒ¡ÐèÓpú¾=@U_kâÐZoÿ騀 <P¾PTZ_á©Ð#’•ÐëÓpoÐQ€[¿â[ZMÿõ쨀 IÀ7<[mý[zZëZ ãUZtÐ3’”Ñíû î€T—¶¶¹ÿžT7TUóU÷îT¾B÷ 8@¿YÅÔÖo­àE'c"î‚“+øï+ü*(ÀÇ ())ÿÐú<ÀCÐ(µ ’T[_ý>T•äÿTuzumåZÐ5²¦¢TZw{uWzµ#ªÿþ ùþ ýýû]ñPÀ¥´ï[“°±UuÿwumU* y)´ñWu{y"°Ýõ}² ZµðT*û í±< þ _ýþúD°ê ‘žë²Z_ä©ÐÄБýå±° [uwtjÎÃÀ%F¡X¤jyúx±ôµ  YÞ¯ ä`ûý ’!üüúé“‚’}’UIÃU ÿ’è _wueð# ­‘iµTÏTsyu± tÁŸ*+f ä` Ÿú Ò!Ó ô£êV—Ã@¤°¨ÐßmvЬ{ãꯓ•ë±°<°À[>»°*TU¢¦ÀûukrÂ6ýô<õ<ýò5Àòûï&ñ­€“OÔõ€__m…ÞÔêãéê´qúöÿøöòó–ìaPˆ€× +÷ V²¢[WuuY€PZ$eTpñÿ%{%ÿü7ì ÿììëëèèèæ±Y‚”‘rqêòïþÖ ö’—ç¿)%L±Z¾J¥TTkuj˜Òõ&dÏU~¯ ¯c 9 ¿ß ß|­Ç­­„ê³}¡ï“ü®<áúñØÒÖ –ƒæ¥A ÚàŒÐX¤V~•Ò7* Ôÿ~{ü7ÿc cDDÏBA== “ ‘¶ôXó>âðú"€ó~|“’K—NâTø¡[W´™ÐøÑ*Ë Ìà tq;éõ°âÿ2(~O×%$%6<Ý>áúòø¥áÞÞÝ““ÿcch9-œNà# ¶â[½ålÀósY¾ðÌá*YÿYkTÿ7<ûUý´a2Î,0 ÄÕî€;9ç==?Àõhÿ‡‰‰“Þ(à­:›SÀ!((ñXàeÆsùÐÌà`À«TlÑ0 õð ,° h±[óŠ€*P×@+7ó7í„Uîï¢ðòò¬!t ÷ÛÐ3òñk*ð$± kZT§6 € Y e1õô# _ ÿ__U<7ø7k#"Þv£úúX óú2Ó a·–ôŽÒ÷ Yks°Um5_ uÆ€W.°ÿUZ7ÿ7U7÷7$bD‘ó]$õæÂòð 3oÞ ›°°*¼Ôΰ´  6>ð @¼‘Ù€)7;à[ >4âF1Â#À¸àìm³¡[s° ü®¾PZ¼‘õí7KXê 2ìȰáG0ýÐv0Ⱦº¶¶¤/X· %°ßZT;²à*[ÿ[_<£,òÃAÂÁ€­²á¼H1ú¾¶¶²€0 }~¶07#žoÅk_±£ ¤Ð ÿ(kkk__û_¬°&DP•Ä °Ñ‹E G%‚0m¸0#U `¤o<½_yÝ8ð(À$—T …`ðÁD‘uþ— }yusk¯_ZUTOÀ«o¼—òÄ%ýKð_ë[ 9 Á!ûT9}‘­€k_[Ý &d/T7<#â#]%Á·  û¾ðjÿkT òT#‰´ë(°ªo¸âú{±Õ@ Zô«€óPÀPT cqriò•Äô=A‡ ¨oÚ0½Ã“²‘¶@<`ðÁé7++6OÀ…§o ¾Àh1'@ Ó3Kð<.°sU_ < m¡í=@vm@÷–@¦\°£ü |±%šPTû7 ²‘% _Ó@ q bß[{y< ùÞ¡Óhýk €‘‚ ècn[[YOE!‹±O<<[#g‘"Yp˜b…Šƒ1pæ ¿"$%'4ècTèA¯!|±V@ ýÇ¢T bXu+‡‚-qwpÿ""&$//99ÿADDDc!ðDa»¦2¯Só uв*Õ=%Àqv"ÿ"$/4:9@B·BDD€ðäðüÐsöQ_ksmøÿmj* ß% `ß<%ï{Ãq:99@ÊpðÚð…ðäðDààæã}Ðr*[_ml`~n`yyuuU¨ï (À,7ñí@Á€€9ABDSc‚‰ðÂEàN÷ëìímÐÝ¥ê?[sla¾‚ÿZ% _jïmsu· %7ÿü7 D‚‰`ƒe€O¯nÐþøùúö¼õßU7ÚÈCJTïmÐoÐùúþ=âúöôð’ÿwâ[q Xæï€ í‘öù<àT e¿ìçäÖ)‘‹"¡°<’P#‘òÿïìéæâÖÒÏÿ¼¶—4ÿáæ,“Þc“`ðîëÿèåâÕÐÆ¾¶ß±œtU(PÿßþU<7YóööÿòïîéçåâÔÐǼ¶±uº°õ yÚU77­¿çèåÖÔ϶‘ oz[7#YPÿÔU¿7eǾ¼K }omT(¢ ÿÏUÿ [~sU*u yÉUQÿÃ6ú×ñ¥%  ÿ#Dˆ_ǰà™`ôñlQ¿ÿúé# ÷%+ÝàU[kuÿyêyu_³<Û¬ ÐãSÒÉÒ0sèosk5€ÿH Æ|Ð R ïÄ?ÂZ_ÿkèk_(ýŠ¡í ’¢<À™ÃZÐû£@ Bl÷Ý[¤ÀüŠ¡î+ÈÔr£µàT^ÝàZæZV²ú0¡Ÿïüp,&<àͬô¤ø (iòYéëêtã¡â÷ŸœÓT~÷m¾ð*N@T<±Ñ'ñ´ë­Íéñžð­­].H·*Ì ­áïâþZöæàÞÞ“‚˜*T²0ýV{ð<)Tÿ ý{T<r„´:uÁä­¬üñŸ‰‡„f´Hƒ¯%6dëêãÉðÞÿ““hcD=ß5$¥sÿ_T<×[~®0\@ öé<Ðíó²VbbÿD??==;55ñ5‡ÓmÓùA(D’ï‚DA8c556ý;„>>>?$»§®à_5Z÷{KTUUçðIè¡9óò7*$$ Sgâ…$õ7„=‰XXD\ÿ\bbbffhiÿi€ƒ„„ˆ-ÿ¢_Z2T ZÒ°Ò²í p‚` èˆb+õ²T䀄w„‡Šüò¬3û¥­9  ý[ßúT—üy=KpúU±ÑC°oŽahq’ æÞd9žñÂÃñÚð;ñ;ñÓÓjð ¼×rÓa Ð÷u$çóôžäp(*T 3À6p•PRP¯ñ•1¬Í6ñÿààáãããââ¦ÕáäåáóÖ£ Ïss)ô ` ?õ> *Èv@1*’‡!X朲›àì[òôàëéòã’£þð Wk6ï%l`ssçü[çð‡ðöü´¡mÓ7Zo”˜ið>ÑeQ’²“îô¿îüì òâèûç“A`__ùkQ x÷Û?#7h4ðÞÞåX±ZŽ´77]ñìËÐä”"çæååÿäââÖ ùÕ¢®à*ssWskkè0#u°ª!]e%5$µP Çá3÷]põ¤Þìóàá#þè ÖÖÔÔÐÐÈÿȾ¶D¯ÿVZT6 <ËçðŠ¡« <2f$#âa¹p6Ä(²ïåâá:5Ⱦ¾ÿ¹¶²²²±tï; ¢¦SYT-Tu°©"µº¡ƒQcBÀ“¢Ž¶7xŒ3þ‘0±¯ šzm[}<`Á¤7ICŸ2[ S32à±6oBe@’² 1Uzÿ±   ~{kÿ6( °¿_[С-kÃÁ ª!2¾µÀøT÷£U½[ü _[ZU`° ÿ´ý[  _0Z<@E2Éâœ@Ã`°QePYTÿU[üTŸjkk±Ñ« ªñú‚DF0Z§Q/þçðj_k¼Áa #7 „A+ï®øQ_[ûüTªp ýT¿*k7Ͳ ÿ(T¿_uu<7Û€ëÇT ³ Aü°ü[ýð<7üȰðküs÷j<α(77È kZf²®`ÝØÑð71²¯j‹p«pm±* ­Ð¿& í oê7¿£ò%Ðÿ+**ÿÊ%7+*û `$%û’Pß7É+mµ B* DÀ›«î1 AEÀ%§+Tå@ZПP7ÿ ù7[wœœ£7óðmµ·XÑPr##{ªëYT `ëP›p(ßsûuøpûÿ7 T¬Öäç/éìî“ȶSl|\`º1©Ør?# ÷Ñîp™kÐ3b “õk‘„f² 6g\a_cÁÂÑcÀ½R@< %ßPý5` TãìëæàßÞ­‰Tf²ã*Zhªf¿¿ §Aq-ýìqTTk×<§pÛ€]ÿ‰hDB9S54Q Ùb#èlø`e Epú§ýQßW Dpç(øÒžqWuÏ6 1aÛ€;?84/$"ÿ>$Ðö7*ïiBu[ ÐJpÕ¢ÿ! 6|øÑ„ð'(Ń(=pCq qk‡q°•sš{ñqc¨1@*ó _sDZq ÇpÒr8 e…s%ç~÷q›pŸ ×Ðvbÿ{s ë “¡*ôr 7 2+7‹új€ l0¥üÝ@Ñ T! ù K‚va?±_2 B€ Šƒ3Ç!0 ;…º„üŒ€Ä$û¦î$ K÷<É@±€¯"%߃è䂽1Ƀ×$$ÿ%)445"¤ÿý[$#K%3?±L ø 6`½0¿0CÀA%Ò(À…îå‚$%%3;=?ÿD\bc&¨ gyuy„ˆ ˜ÀþÀzl<K!0¡ýðð_1*BÂÈEв5*äƒs“8=ÿ?BDbch€~+£Zsˆýuˆ‘yZ#o+ÀjC  °¡’uÁn°p10ñU ÿ D$%'4ß48=A?Ô“‰óvÞÒÿ%/Oü8²¥Z[¡û[Z²55(2C¹Âß…ÓÔÔÒ¨AÈÈÿ¿¾¾½¹¹¶±ßeŠûPZT%@Ñú€ÒAEÁÍåsâ0îCTvï¾¾¾¹P²²²±  ~ujTÈà%}VÏA PF"Ó6h”!`6¾ÓZ}þEP zm[T*÷%Û°²ü[W_Þ0Û°WQ* é!é"ª¬–G#Âþ@[žÿ_Z;jkLCWQ(º’ Q7¡ð,¥U£ %œýüs1WTüZ”ÍPVð WQè"ÛS7z/Ðè3Ð+› QßVT `__ýFÐ è¸ÙCÚS/ÐêU#ð7× œu1~ ¿kU < úÑ E?0™c¥-Òö3ÐvÐõmИ±AßT‚ [ksFЃÞkÀJ‘ã4é!aéõT4Ò–u1<7**ÄÂ5ÓÀ´a0AË~CTìTD1í<>`–u ý*¹ ð 7s ý×À+Ukyu¤ S+ÿ÷Tü<ùW7 +6Д Aÿ_Zü*ý%?6TM€“Pkk"FÐwÐO¡@Ë£º“ùcD0oQpü q,â(’%ÿ_!*(%fâT&úÙ9 äR†w»bßR}d r£tì0­þ!á “ü[* ¼¯Òƒ _s ÑÌèaC`;‘e£ZjmtlŠt6v¤tôvÆðS˜ {àq)ß £ÐïT%$„7û6º‘r©¾ÏÐ'ÔÖ]SÏv+E‡N„þš# ‘ü[)ïúTÜàkÏ7úr%7ýµåçèéèÏèçæ¬ã3¹e7*ØŸŒø€‘0@À‘~Ô`W%(êSV;@Zum€q‚+ËýÖ€äàÍÍíӬd2†ãƒ%òŠ Ý ï%u _[( 6Tëлr•÷5¬0„€dŸbX>;5ÔuÚS6ªKš wÃ|Á‘pZç) ßá¬Ò~ùyçbr*77<¼r…(%$›  +‹‡D0#S•¦–ÿ‘«?ý[- %ñ;B=Ñ€“Í#Ï6$Û’û€ rò áÛV<+ ¦“üÿ“¡ ÏÔ`T,qüÌ`ßàm€é×ðÏ+tÁL¦ DÊÔuR¦Z¢pÀ gQÿ ¶  °PFä¯Ð!pw¢"g76ý—yÀ/@e77â¥qÁgTmPýNP_[8[[_<%¯Ày¡•Ë€ ⥠rÀ±¡»d**p± ø€ ²Äþ$àŒ __mø‰°‰±f°(+¿67 wlhÐ+êùÁ*w€ÿ¥µÉ‚^TNºgð55»6;o`‹[–Á%?6Z =àhÐ+y¡ w€+¥´U°Å©R*™³cï$ôè²¶²Vc dbw¹æ°$,%=!³4*V´®Pðð1Å`÷cD1(%()ý)¶²>XYbddÿiq„…ŠDìºÀ~°9!*ð®T#`ôT‹†76;;ý>MÀ]dgiq…ÿŠŠ˜˜¥ªÃYÂ_À7cÃpÇk óZZ9@†]bdiÿiƒˆŠŽ¬¥ÿ¥ÂÁÅÅÍÑÓ׉í[À_À6°~A$`´Ås!__¼ÆYýˆN¬¬¥ÂÃÅOÍÍÓÓý0DðÛÂÅ _À3/A7AõÃ__¸âa‘@ÛS…ÂÁ ÐÑïÓÕÕÖ@óÔÔ¬× î[À _À1á(pÁ?@âaä`ss[Î…TÍÓKÐNDÕÔÿÐȾ©?ï:[À _À.äQ¿àªoÐsÀ°s¼Æýãáý։Ѿ¶o5ëñ[À _À)#Z#‚kg²sUüÆàºÒýÐÀв}Z*kô[Ày # {rèpàË@sÖÁ‰Ñ¶²œm< ø–Pí_Ààò7ÿ W£¹²±w¿Y(ý–Pî+á+˜rÿ><<;;66%¾¬árø` T7~¹á‡Pýë(<<ÿYlõleüA0”06ñÿo(TßsuYÀ)TÿZ~{{*œÐ ¤`’Ps`Æ2<TZeCúóÂY’c<%õ%³÷p\°v ÿ <‡7 öP“#àÅ3ÿ<TZøZ? YZYY¢å!ÿ<+ô+Þžp u"ñç_uWÀ0ÔYýy7< D·  A+C`(<òTip>¸’ïTûa¯0ù²Dq_TTWT  `K ‘f ra+(1Ÿ <<–ñîs*ó*6¹’õZñZ®dpr_Y3þÚ@lZ{"ý<ýT#àû ,(1<<làÆ¢"îâ¯lñl–apaa×øT   faù<§6À?`-C`#K*¸RT‘V’ !¼DóexòG d¿qý_3`us¹2uPÒÎp*X ÷¢IµYdñY[²}ü+<Ëó±n¸yà ï v|°[[+(*+n0s$‘ *ÃP÷¢Iµª°®²„¡5‘Q%´²u±ÙPþžw w__# é±%ÿÐ|0‹R#„ ±à¹ –P(²žbù%È az÷uyÙÒu ý(ðp ˜™ë…ÞÒHà 6<óq™ñ±q_ó2ñÞpYlqrv…àÿ˜¢¦©©»¨6ßá !àŠS2äö1õjkã…‹ÿ˜¢¥¨©«»¼ÇÇǫ׹à%!!à1TÀÿUnçò´ÞTi ¦†àÅÅŠàÈȾ¾Øáà%#!à.å`Týåð÷suZc¥T¨ÆÆ³ÏÏðõ`¶”@pÙv'Ð%ë^ +'á­UosutÁ[Ürý˜‹ñ¾¾¶³t_<Û'Ð&!à'ŠR˜`sÈÀwä» …ùá²mÝÁßz'Ð)ð (b¢Þp‚ TxUðl6¯ã^ð+!àù<ðŸaT[uaß*ç‘à/ìÿ#*ô'á'à6¹pëH  Рö ïÐàúéñÄðÎôÈð ïN# 7+%ÿ ÿÅûÿy_%ÿýÈìðùs_7ÿÉìð÷kP€õðÿËû[û¯Z+õðÌìðúj´A7ª€%ô(qûÿÍúúÑ@91Ò`ËÿÎõ~P*±?ˆßz\@ ×õ /À<ÿ'5=;;8ï4$Â0ÉÝ Ô "”$$÷:ˆb'Xÿ÷X YXXYßX;(Â0ÃÿD úDûchh-9žÿ;XñX¿ýY ZþpT½*±¾Þ¹ÞÿúßÞ,õ8q£ôX]v||teXÙYþÐøPU(Š¡ ÿ #%$ÿ ïüÿï òðòòòôôôó7rüÍùq¶¿¿¹—¹²”X*á²qTÿ§<7%ý `ý ÷ý¿þþýÛ2Ð4%[ê"TTk~[Ðý<¡Spý2çVÓ£Blm½ô°@X‰¡w$ðÐ(+<ÿÐ~02@6\QT&P) ‚QPÓë¢p þ1ò4@Xü@jjjlÆPjlQf@q0%à‚¤‡¡< ?04AVT)ï* É€<<5ý˜A®1 üALRXXZ[÷[ñðË_[¿#*Û{¤·Y *³q[Zé!ÿTuu7}{ðp0Ø‘ÝpñA®1üBOT¯T6‘[É0Á!í‘ó’1 ÿdûT[ $Ùs¥°4@þÔÐVñVqó¶¹Ô"!©8\ë#’¡[k¿T[_<±º£ =ὄmÿ} |eVîÖ?€Y”"!³‘²r·`«qWUp«nâ”P›P<†áñQD0†€Û€©÷©”^€‚Yt÷°° a’}Vó`Oq`ýZ;ò€j[ !;’Îñ/;3A YYíWô6+ñ%)6þ†eZltyysm§_ZUÛ±€dÓ° þ6%(_j³_¤2÷ <¼Ó5A2C !°öã!°þÀÓ¡õlÅÝ@ *ÿüUj_kl“Q^;ñC2¢3A%gÂkÀ*r#•výOpZ£_¼p !±ð¡É(ß”C 5Õf aT(Ïsð`æU£"wàíA; i1ñç£ß1é!U÷UÿýZU%ÿqý[_[ÿ"6+ZkÿüsjTà°±ð <¯1ÙPT€¯VVÿPó¤¡÷o«q[<7ßâ2ÁÊ¢ÿ6TøTh~C4ãÔÐU±UTûým¯ 2Tøs<Ç¡j2TóÔ¡ÿTVUòUÿ7mý[%]* $éP=EPÿ TõTñ~B°(h%ã€þºP2%sûuÉ¡;‘9s Tmì›1T_°7•ïgû[?8PT<ö_4Þ½5Té~•`<û7`úá g¯ 0ýT¯u¯ââÀ3¿ÝCBðT›ÙaÓc(õ(á ds£<yUva€<; 2ãFPÿ %*&üV"ñU[jsuyßy{ykWÜWœ¿²²²š[%±€ÆvÍàAëŸ@) óö¥ÀYWýòa«m6&PÊÍàCQß(<ñpZZßTÎðHìžl€ %ôÓÐ#ÿÒ`÷ ð ûÖìà~úéñìáünö ÿOˆÈî·ÐÿÿÓíyÿsZ( ÿ×¾ îs u?Z¶°ÿÚ çk¬€ ÿÿÛûZÞŒ0[ZîP UÿÜ å@÷<<7h#ñ7«+H Ý` ,Á(¿%ê%á ÿýÞL ïÏ÷ÝЋ!ÿúëýþx 7ø_ìëàGƒ°÷ ‚q´ÿ õ ö¿ ûüš ûDý€$=û]bê"]?5"ÿ¯ üÿôö$Ûü%@Bý€ÿ'\bòbû\5쀬=ÿý=ýAü?OBD.2ê!c83ßhhAâÀ ñ5ê#î î dnolýdê!X% ”ý$†à üÿý“ô­¿ ÂÂÁÁÞ|2“{AÐ "]Q0ü‹2é!…±²²~½uZ0]]Y*rpŠ¿*<­€%ÿ7 7æþ»1èòè é}ëÇ1ìë’@ÐÏ$4]×3Q2b”ÎÓ‚²¯|’0×05%å±€];±ŽÀë U  <)ÿ ô ýÿôöôöêöò?Ñÿ8]õ]bx±±±²¶Ó½q×3>;;(ø€Vý˜£(çU*päSý ÿ÷ýùüöúßöö’%C4ÿ]ô] rœïœ¤6@³¶xÿ]ö]='ÛÐP Y¤VT,W* U¡þÿÂ#úÿûúûöüô¯òðÊAîÏAì÷ìÞ%B"]~/@e}}}š…Cÿv"]ñ]·X8$\àK|Pý ¡% ùT ü÷TzaìïììëéPèççWçæå&Pâ*QÖ/P·Õ­%C X~BÏtz||æ@è@lï]ïõ@^jZÿ%Bws¯TVý`" ß  õã< ÿÔ üÔoÒІQÉÈŒSÄ9Ñ:ÐqpÛÑ}Clî¤pyzzGPtx}@SP`àjj_+Æ »H’‘TT5 üEã`¹ü÷¹ûˆ€² ±Ë±¯awS°Óq¼=P/@^stAuÿuzz>]?ð] Yì`ìaÿ:Zwwtýkq`TVTs{ [{Y ñèøâHã  þg@ û ~yum[+—°¥BÛÑ£T ta<þÀ ]÷]X×>]Y¢0]ëaj_Ÿj*F±rÿ7~yWTüœÒÑÐ÷¤§Qe*(#¿ ^ÐHÆÐ78×0…`×3Ymým sskí"Ôb]Yë`XŸ%TeeZa£ :uu Z¡ yY +¡ÓþûÑ­ü­“SÑà§7XÎdëbaò mêÙb%|ð=ÐfY]Îó%TÕ`7í@Ð!¢T5è’ñBätQSc ÿýcDDB ‚)s ëbìbì`¾PkF Qrëa…`)ââÿ*Uÿ:}[¢TTYhPO d!÷Ç S%%%$€)r1 ·p ‚†aZ\Ò`kk#¼ð'¶qf„Y5‰áŽáL£ÿTT T#Nz‚T ±ÃùÒS›Ù! *q YõYÎÚÑ[ã`Xt‚ ;\oÀxÀE@UÎÙZ–¢E€<«ÐZ~ß{{g¡ ü]Â=ôýȨ!º!n‚t‚£ ú[÷*¼ð$YôúŒ€<6ã `< Ï € »ƒÑѾ_ ûø;TðX·p&‘€ ´¾…ƒîÑÐ4á ëLfP ßpgZ{"º€FÔ<S/ çòÆ *qG04X)—‰’ËTìà1$)“&XY±îÐß D{‚Zç7{´àް _TùU ]@¢ê‘M€„£ `5¡ÿ“¡‘‚[ÏZ(F ý°VT³> W…€qZ@Zïü[ú°íQÑà.£XX<|`077ª¥ö“ZsÖ__õF"°fPZyß+U QT<ÝU@kPkûs uZàí³ÑIð%ðÁ¤3€òñ_ XŸóX Y` UïFv¢6¿%u#ŒÀßu oys=kgÐ6*%VÐÑ] ²4¬£;éííñ;$² mz«zzeàuÕ cÒY¾™`kk @æ ?% %½`ÑþÑ #*6Uï(Jð'Ò¬£:` á|´l~½~HQz6IØ 0"Z ŒÀnàc@ï Yp(ÿ6TZjsz~¯[_`H 0ól³5 86$³l4Áœš‚°þ£ZVTTZÿT6j_Ï%[ ¤bFbu? u}ÀkÂo~ykUZPHâûe£XZUO__ I@žÑM¤ÕXïô‚ fØ 73 Ó Gäk€S UžQ#°øÀ°µöš@d ý7ï%k oàû TD0)X÷ÐÀõVâ°c5àZþÂ++k±sjqƒñ« TžQçXõNà @7{_ž __W°07**:Ê)`ú‰V  VîV½Kð>7€­k€L¡WhP÷ íq[<³T6_`_` J 0{ 5ºYlz›{ÐÿeVìV ;Å-âÅÁÛw T!w §€T ïq³WW­I 0Ù O@oŸäÄl5ÿVíV $iѱÃ`K÷â[._Ø]¢ÓR¡ ID0þFX”±©§¤¤Ÿœœ|YÅï<Â`°:`I­ý ðZ[ÙPƒý%ºm—•}|z_wuts(±YÝð]\²óM «Pïuuÿ%+ zwl%šàIžPAplæv¢Z°°p©—M!‘01?€6d|"´#ã`°!Ìe4Ùauu’Ç1Oê'Ð1?6· ³¡ÞO€TUTã`élrÈQl `}}lªP@‡/$tZ¢’{7ã °03¥@Z}~Wšœ7@«;@R@,6 BVÁÐz áž>pss_7Á—aY_• ëÀ¬;@ÿTë);ÎÙrTWZŒDû1uuù[mr©`Zœ±±¯l®;@V¬@%÷5tVY[_äü0ñm”°çBVe¿¯t6°ÚPYÿì 6þtTVWYZYYÿTøTYm_l) ³ÚP\ Pÿ%;T¿ñT;%Ãà¶ú;@` Pw%5;t6%a°¹zÔ°þb¾¦wúñj%–tPÿ NLjÈcPŽR';Ù‘(*+@ð‘ˆMµ€(»P‘€9€ÿÿæö7÷TZ_ÀBíu·sU!@ÿéÇPõÿ7<7U[k__kêkÐÐ(ÞPíëñ ü7ðjyzý_M7uÃAsÿ_[(wsù  §À {Yü+ýT±êè68 ÉQUsç  4ÀnÂ{ysïk_ZU%MÞáF€¡Ð@ýk#]õ]÷ [ÄAsk+ï'uu]þdBVT467þ˜à< 7 ÿ7ˆiYXY]eÿ…–§©©©««¿«®®Â­ Ò`Zæ ð$Ws™qb]^êŒBUk$&ɳ$%ï+T[kÀ°- ge1à%DÀ?+7ë‚“Ò÷<<—`Í{ÍÞpÀÁ­wÀw¬¬}Âh]פ9øðp!ÀZ__ÐÁ´äW±Ë±)¯1·Ð3ü°"P<ÿkT *Ì@!0 sósáÿ ýÿ‰‡‡„€€ÿhhfccbbDD&„Â=Y‚ÑpxˆBŽ0"]ô¬¥6Ãà2w€„AZøCÿVu)ü7 üyyD ÿDDB??A==ÿ=8555444µ)N„Â=!Àwø]ÎÐ__¤ Ú"5šs]YÐYYõ2Àö] W„Aè¤ó/ßÕ…ÑYYUT¿6[ZK’ÿVsjT+ÿ{{yWT÷ýTï±ÿýüû_÷_+á0âéPBÁ´ ý°Yö÷Yðà4ýÿ[y=Tàý<XÆ>B0üáàö|à  ]vü‘XhÑX¬P›UUæ34ƒÑ¤â_¿[Z 2ˆAÿ u%U ܱ;Ò  b „a.#{%ßâ§pèáËVA+µ¡äeõk Ñ2mÐ_[Tÿ÷Tus[÷Tz<<ßT(zàýýµ"Ôé!³P+ÿ\–1>þ|Ô]<*+7<^m#=Yô]ð^Ô°%3ü[ž0ÿ 5uïkUo€U üpàÐ ( `é$ÈÁîâRA†@7¢ò÷ X|Ô8%*ôîÐÕ%£â XYYÖ; k­álà?skZäñï³T %þ÷‰AŒB¿Bgs+ >3 0RÌ0û> %Ü\@a0Yó]ðt}¿yu(5nÿýk_Z I%ÑSA8Ð^ÄTvà_ &•Âcd°jÌX਱â̽pv ©ðƒÑ[!X%wž°æÖÐ3ûhð}@VÿZT;ý_O#[ ²Á‘4Pÿu üu yWu_6ØÝ …ÿ*ÐüÒ`8  ù7#TjU¼™³{ÛRÈï ;Mà]l^Æ£âýX$°å'± mÿ5û[3¯[_ Ã’!û?7Tk—±š²ÿ}u_Z<*õ C0SÖ`&5þMádx¯|müPrewœ  °?²•*5ðœý ’`%%_~‹AZ<ü<Ðøó°ÞÀH`Uk~~ÿykZT*# Úä`\Ö`%8!YYývP€²²¯[ÿ*Zeeellmïtz~!w5úUà*õ[[Y 5üU \A½U Ðjjkнøò± 7¡Puf€f p$$qwZz~O€±Z ¬Áï %T_œ’{u[vÿ`:²! à@O _ I@Ç"*‡€—n pùàq5ÿ+Ujuz w!à=òÐö1ü €<7ÓsUóªÀ‹1"þ™%4 (%ûN2Z:ks·ö<_P mçqúø]ð5 ÿOü[ý7Ï k ±ƒ³*‹ ì4Ì0xäXÿX<+(Lþ±![[7û7Òð*s ú<Ø©@b!í35â÷XYYW*ªÀùIÀ à1#+=p_s `Ä2 ¦QE=‰r]CPß F(9A[ÿ*s ¯<<ì0n†ÂX«îB7ÐE ['[#Cý  ³zªÀ ¾B$XëAÝUÃpBµ!)ÿ )T Ou kÑÂ2 é@ýo+áXèXÿU7?ümAð Ÿ[u©Pƒ±êˆ0o†Á$RV<õ+MÀ<Ý1__W1ßTu —+ ÖP pü’%TT6*úŠÐ<ÿ@ ÿ6T{{uÚ>Ðì0iáý‘"X;ç@6#%3@m1ÿ_Z0ýTû{ëÑÂ*º@ fྥ 5­S5ÛªÀ8ü6YTÿ"ý³0Zu~üÝT¢Pe㥿)ÖDdY|.±œ ð· %VÄBÆà÷:ujàyuû % á ;#Úì0b®`³gœœóœš¢’wÑ;Xûðc9ýuÿyZ#ÿ*Z tuz§w[6,P ðíaý'Demyyyuy’¨÷¤q qó…R¸Ðÿa#%#ß,b£pZDeYÇjjÖÑõ k³bVpXVŽp<#’htkDeWÿðUU¨òx4r’p“¡<´—ð›xDe6+óð*ŠñìÈ`ÃqórT“+6­ qc†ÀØw%i±ÑY0ð06ŒqœÃsá€(“va¦De áûï²€ÿV÷VWZÛZ1‡aÿ%(454ÿ)($¢ÿÊúñôÔxк  MˆÈp;íùÀ å3ðìö€´Ðܾq€ÿîÏ*aÂÊÀ1QAÁ"üü¢É¢Xãîîîìö‡ÂéY‡´<7(_ë(%‡Rð0ç4RÁþÃenlý^ªó5 ^ÿ 6T *ÿ üúñ16­²Þî÷î­4Ãi¡r—B¹øa@õrQ¿@ó 5ªÃÉÑeœ±~·u[<©óXW Ÿ* ÿÀ*$þia*TZeY6A×ýÓQ(n¡Ïîïï„À`ÑãXþk¤7ÿ=85'%$"ÿ$ùQ[àVT(ÿ*eÿ——oT(*?#àN>­²1YìðïëÐ`ÑóìzÃÇ¡ÃÅÃêâÁá 㪪ªÝ@‚Ò 4Õÿe} ² }sZç(¡Ò¢àõYÿ= ûV%ÿ (TU*ï %*TT%éØÒóà×Àø7/2<ÞðêÖ“ž¤i ›dẰâá‹ä±Ö½Õ˜áÍO¤ðó8ÕUÀbu ;²+ % Xð:ãXX""¾ÑþQ % Wþ~ @;ß;;665!@))é)Ìqð"\2Z(îJr;m9X ý$®!TTTsÿUT÷ 0ZTø?TT< 07#D=%…A$$##‚L û*CX]Oø]È;BDH~Ëò!__YUõZðÚðTS ERס07%“BòS°ôAÈ€øE‚*@Q4]÷]ì×Ñ34CIXû€ _aÿsyUq ÷PmQ˜1724£ÿCö±žcPØgP™a‘¡AÅX9D r1u0¶C>ç —Püuÿss*U_ ûT*2)xvHÐ677gQþp€øüoüaPg“žÓ6áVpn°ã5òöD)Pû_ÿøTu~7TZZ‚ ïTT CRTTžx% &s°(˜gPcQ² E€Çƒ™.pÙQ ¾á¢ÒVEëSI@ôÂ=rV« ï_[Y³ _uÿkkZŸZ[4Ö¢TÎaà ßÒ LHfT³#…AfÀ*í ígБ$6àXtJ€t>r0÷X6@ÿ#[[ß%s$ÇZã ™dCPª Ï (ú¡*Ã#Âd#“‚Ù¢ZZTÇQíZБ4Àà Y~Øf5XõXê ÆÁ   YýTÜð_s[Ÿ__ZG#L## cñ 9 h⨠n 1uX`ip¨ kk#U ¼@aR  [çÿ)XýY›'£4õÃpce?}–R`ÿk*[ ɘ1K#<Ÿ`‘r‹#hâ)°q†‘kss[T7} M QþÃq%)5ü´F÷Àw+ í<¯q[ ZðUq_ û?TTT*^åÖ°Ÿú7'o Óyßyk[T*XRÿ$)6VZlv|÷œ±²Ã€Y}Zæ€%*ïÄçY>;ãbüÁYví ý &ôc@ _ý§ _ ýTË+1 ’qPÐ^óã#÷Àȳ]q÷>%À<*ÿw*Óu ATTTî±Ð?†Qûî_p>$ *ý_Z  _Zu§Pî°Õ‡,ñùÀèé`) ó'0kpWo<¨‚M!¿6 ÁN@@Xçé`¢ (ð`W;sN#Æ ˆ,ñï>X˜Á; û$kp¾;a  Zš ×ýT¼À†§½;èÃ>"h°'o3¸°‚áœ@ß5Xé_pV>ï !zÁ[T0ßúTüT—@ ýâ²$5V›XÉÁ;  €[ß(%N ön@Æ ~äÎaÿ%>XYlûwZþ°íXVÿXVV!_ÿ_# ý[¯$Ø Æ }þ;">X ½Zè€Z+Uþ°ïÏXýVÆà[" }y§ƒuu60p_ zl%¸°|§ÿVXYýo< 5LԀႠVtbÅXb`ý#ÐÓZ# ÿ*U[_jm§su,¼ÀèÒ¹@ŸYw œª ; ÷%TWoeV÷VþpJ×#+á{§îpem~z¨@ö %Ôð áRàøþVà$}{f&°-Àfƒuu¨@ÿò+<°’Ñ â á‘ç peZßk+ïg`S(<·æ¾äÆâ%peëUZ7íÎ`ó ÐÄ áì ÎñÌ€VØõV(qñð}á(åä¯5€”àÚP³'uaua<(íó}à%;ƒK€Øò³â¿6 d@6þåå‚…ÎK€"iÀ ãVY÷V6(aà$5\àá„”àˆÊpÿ 5VêªÈÐ)`À…”àŒÊpÿ%5>VÿôV6$ÿˆ¥ó °`öB ÿŒvúÉñØs<fä9ÐN¿ˆµG®úñ ý@P]Pˆ“pK€Í#ð (7p)TU³Zj¶q+*Ñ «סú”à K€ÿ*<ò<Á!€±q´p+ekUêö”à ,ñ#<ÿù<"WmuƒsY*%34p©q¬rZj£ô”à ,ñ{ÿ%Tx¶¹¹¹±â…<„B%s*t<+ ëó”à,ñ *<ÿú<'Y«Ð¿ÐÐÈÈÈ‹)5àùAKaîA»b òú”àð<ÿ÷<(dÍÖÔ%"˜)<7hAaD`[ ! "#"ïiÓâ]"ÖÖŠÚ,%$÷ÊQ_bˆ¸°"½%"+fãå‘#äÃâ],%úýE[Uý^Ü $Ý4!B$€P ï%(p(#ÜPî„' b¿àçççææ‘!Þ<øV7 !CíDÎó@\Ì€¢$;¿Y÷Yü_p;ÿL#6 o6P ä""Vßò K2æ;æ„U#6*+ËËìÅ`g2%Ê‚¾AEYdvvl¶D>þ—@"V$+l¿ZT7î°÷ð<ÿö<­çøÏçæû  TæÕ„WWTAs<ýXÀÂ=YøYÿo±w[7Ñ(ÿôAó26@÷VopTTý)¢05T l——mT((<È@Û%Ѱä!7ÚC3„K7ähê#e…¿…nqqqlLAe·øe¦`WÁý%"2 m±Ÿ|jÿT( >XöçX ³ãÌÐûTÿ")T o—ÿoT(#Tï(PИä"RE1YãN4ö þ"V˜¥¥¥¢}˜ÁAŽŽ‹ÊBÏnVâÂ!3 eÿ ±}sU*k%pBâX%ªÿ*[ ýVüTÿ (T [vÿW*  O<TäЀ›A™ ¬0 Þ­Bö"Â~ª2ŠÆÆÆÅ@PßÄÄÁÁ®HP«ªïªª¨AÒC >YýÜA~±œuZ+æ\ (ëF£ðuzws êòþ…q(W V@Q&J.T‘ »ÍXµC]ÓÖ¼QÕ»ÕÕ%"ÑÑÑì®× VT`â`öÿY t±y_—7#Ð6ÿ²uCXÛV8VTG°ÿkZ%6·T ršQ°T#H0“#(`ÍYµCX÷Þää]#ââááá¼RÖÓ0ÑSÞpÚQÿZ±}kT%¿(<ëS[^LB; þ@CÿWu_yUÿT*úTlUAØ &H %dgäâÂ-`¬0 ¥8e¿ÖöÖI`WÞPñYõVa%ïð(+Tîÿ²azé`Z ó opÉ0VTT{y T*aí˜a" Yàî&câÓª2T˜ÔîÔÍÇc›ØSX™€WqŸ%+7TøåàußzzW rp# ÿúT2+< cTëÐpÙà+Cw qÃBQ®ª°cÿV¢ÐÈïÈ¿¦XPñ6Ïb%4ë #HpñCö)mzÌЗYK€ÄÀÐa!Ŧu*ô b†àe6|3:  ûPï{Q %(7* øbluû(÷qæ<Yßz °² ˜“z¯6ZPñÏb¨=tˆðô Zá‚’Ð5ÿ4jT  ÿ*67ýTÍ  up)(Ï…ŠiY€‰qT[ÿuõ ~ÿ~yukU%µ]‚<Ïb5ëò0ZLå’Ñ)ö@ÜpU~_ +÷`kqM .Ë‚(VÂBï…id^%¡elvý|S”x5Õ ² •ðcuñYëô÷€ëUZ½[š%ý`VËT¬€P607¯TU(–2‘ù<“,dŽŽŽŠþÓ…ö…i·mK*¿3 .Áë™ú±ã~“Ò ZôcjsWT;¶ wYY ¬€  Y€üTâéT|À “} _[[YH±Yˆ`ÿlZyÿ[TT vŒ< -–#*<Óâʃ>)ü0E²5*5îÌ oð(*ý%È¡ýX8ÄëyÀ_Kâ’Ð â)ß ý[AûþQðsôTKU`Zñëp ,³˜ÓÒ«°6)j3º´#}$ !oä +*%þÐÇ¥¥uŸ_k_(³äÇ ¡Á@ÐAÿUyu%UÄŽar ¬£­±Ò<*h :8Âü˲ Pé$ɢʢ%@â(³kkð¥íõ þ²ZýV@6uw Cà+ZŽ‘¿Ê Y{)ëZkkS^wC cÒY@ÿ/UZú[_üTÇI9’£Á+½À!Ó(Ô !ÓÀÂ@pQÁEÐ}XÒÂks’Þ·å ðÀVTO#s”` ™¿ ûT<75Í 2‘$ «°8”± !Ñ8%®" ÔþÀ 4ïYXã¢*ksjàÇVÑ  ÀþTøTÿ[s[ìî ~ÑT<%þQ ñ%+¬´<7%E ý%w#Ä o²Ñÿ5X÷X#€kùsò”³â #ü^ÝÑk=Z([ ñÑÍ4mT”Á 3¢Â"#Â%%ãÇË6ÒÌ1òŽ0.Ò:! aö ¸Ð 5ûXa°> ó%Dâò´<÷ý[ ý_7[ $ }ÐÌ1 K à4dpÒ«±ØÑ ±“[[9(%Ç#D )óÁ!õ`8Ð# %{*<ì4$ Ê¥þY , _? [_ ÒÐ0m–A à2ƒãò)U[ak[T$ü)óÓ 5)Ïýh!¥ %ÿ }TýTtá¹R!Ô+Â# ®w±V5"Ì :! ÿu›sÍ3T–Àó"ýUe`òXýVý ÏÒ)ýó[a`>ÀUu}bà<<#5_**5Xr@iÁ¿÷V)ìþ'_W  7u ûT#1þV +Xùùe1ûôVÿ50ý· 6Ža$"0½ŸU°é@/úXî¡0$–À'¿Z9~y¡° þͰ <¥X`±ãÂi1ó¡1÷ À&¯mTÛ1¡à1¾ ;Xü12új0ð¡0* ¾ðÀ_[UT&0/w¼! a,áÃKáí"@$îð¢!ÿ:<* Îûàšæ×Ð`*6öhÂè"@ ý_#˜àXŸà{)_`Û0w˜ä™€$;iÂ÷ZZYj0ìVþÐp% uuy~ÄAyu#âp¿!=@–Þ¦@ $>Lre|mðZYTB»@° ý yuuZ%(U2¶0í–n@Â0XY'|šjìAìBWž2¯!î…P3EA-Ú=@•n@²tZoÿ% (UZøïZUÐpøVùñaõÀe+”n@-HU<ApE€7ìAÏqçÀôcÐp6lR”p ²taÐÃ÷ÒTP]PÐ**A<•RäòÑ ¤RV!DôÙX=EÞ`+*%;”PÌs) ì¤R½ áUV þ2‘  [”VT g“vÄðïq Ð 6ÍTTéPfCñXõ£I`U°>ñ6“QÎÎqf¥Q1p £**ö¥YÀya t@+­<ÿT<Œb•ÔgDóèÀqG6›S‰ag¹a.’a $ocX aÐa³Zê°ÍT*âb–Ľa›Ð;ÏÔua8Ð7ºYZdh¥P—>Ô<òµ€Q¾j y{{kä5×i¥P˜V  w ÉR5ì? k~y{ÀÎq¯)j¥Pšº1ÿ%;VVïV6 êð[¨Æ}#¤àk¥Pœà1**6TVbPÇ;*º²ÈQ}#ëmoP à"…*ñWtÀËRÍS;_%ooP¥EŸ%U)²@Y¼ÌSYðZT(sðrÿ´ ë%+ˆðs:m_Z×U*ìv-€»yœÐ3Ñ}ìåÛúñä¦Ûå WN óÿÂr€Æ%ÿ½Ä{êê邃„ý÷ýûƒƒýýÌ—ÿÜ‚󘀥Ü¡zó xƒPçÿÁ¾€Áÿÿ¿'ˆ¡/#½ 4à±À¾`ˆ„oP!JÔ26ÉRçÁ ²œá› `К0õ¡VT,¿ þÑ ýú`*<÷n1ÀT®Ò“ÁÐÒõy«3PôãTTd¦ªÀÿ£¢¢™™˜––ë–”NÀXé z_÷XXtÀVw—u—P$àá* µ‚Ò „Áz²ÿ…Ð÷Ð!»ùY³táX¨ÆÆÅÿÅż¼»»»©~ Ч¦™”¯ ý ÍTUs{¿_yWT µðê}ÀÙ)ÇYÅÿÏøÏ!®dä¼£ô☙Á\ÑÏÏÏ÷ÆÆÇhÐAoÿ[z|z¿wt £TÿTT~y!»+Ü€9Ò%fz²˜cҥѪ^ùÃöùÑ<9ÃÐöÐÿýX?|W Ÿá3Pý+²0%ß6< Ñš)Á z² d¥ÓИýY‹ÂT‹ÐðüÂÐñ€wYXüX 6ø7@ß<ç×$øXܯ uÀjðuuç B@ÑúTæÞÀ`ˆÅVdÿZïZ ý}@5 jsYšpšb[§q÷e¯psÞPU¼Zj¡ðÑ Gz² TYW¦–Qç±7zXY¹'Xšb´P 3@§pþ3PTuuë f€ŽPZñ+4ÑFœ76ÿò6ý+#ÿ{ýYüX¬ÀNB 1A_Øb ÿ5u» f€*Z(’4ј-à A±G%w÷%åÀ{wð¶ šc^A[ÿWTøT[ÿuTZZ¯[ ûT͘rz²ß¡ õ ·{às`ï Ð öT¿s #f€® P[ü°0<ÝÁ rG6‹Â‹  ß|’ åt &`ç4   uyjòbyA/['àw[túTp°ªCó(ã— ÷-@ÔÊñËñtO€à ~šdV 2@ý uÀ k¯#[û°0Á 1™y°À%D¢A øA >  ¡ ×0Ó ÿ7j_TW[ù°0+#Á m"ñÓÌ Š Ï‘zÑ‘)öýoPâ¡ zšàïa–"/_a! ’ÑàpˆÅ'6“#ËpG>±Îõà(% ‚"’  ]'1b p€ò_Z~ðÿU_jß_kúT°ÜàpÔ´ü7ÄýUßýZåà<þ'2$)6>ÿYdr…vzÿXYeo• ìÐ00W !À&*¿_jk (Öo± Pp¸ õ×<#7€kº1ssü1°den‹–žÙ©ƒÏ3v mÐzk÷ lÁðsw}œï  1ûUÄ7Tn.‘ ùT¯ «1ê™Ð|°\ð_kjü4A°W”¹÷¹ÿ¶³³³•$ßiVŸ kÿ  mü[î˜ ‰<7{5f€_këà·TA  Bû<ÆàlŸ²ýôÐà|(uÞ¾0uz}þi5*kkÏskT ° ëó*àŠÀî<ÿZ}²²°° ö´D~ZLp~m;ïj_Wÿ<7_«k\@ Ë €ë$ ó«@TZyþ´B{s[U6ÿ%~#?ý_L±+Ð×ksÙ@7Ý@)ï$ ø<ýÿ`kZT+%þ’¤[Zÿ+UsûTN^ - }`Γ /«f‘_ÚàÞ % CQîwpäj4ÿ7s úT·Äšbf‘ û)p +su_ ÅÜà§ÿ4û[$ÿ  7uÿuyT7ú£QÁoÀXVõV>³P  R`_ +u\@HPûÀEsXVü[ý"×  7¿Ty{HP³ÿ#XVÿý_:{yû êP²³ ðaâ"ñX°_ÿY(< ¿{~{kT a¶Ï šáÞâ)w k>)‚Pý_ µû¿XîV$Ù sk'Õ_)HP»Àòña®±^`_'%Ï%$€ `ºÞ› [Z ï__2u+e6‹`­!HPÁ¨w`VÿTuuyuyÿZ (tßuzwa6y@±ÿ'XZ| ¯YV Ð|‘ ÿ2  õ8*HP¯Vm%(IJ²ûfò€®XXc Ðr|‘5q´(ð§®°[@6qǧ7+™p‘²TŠq¬ÿ7XXÿ öÐtTiÜ€²ýX¿;z‘lÚò€±(ñV²±TTýkÜ€¬)XüsX\@­>œâ¿+TUZÑmj7qkhk_ÙnÍðÔ¯ÃpVVµŒò€¯x°úÒqß±6VÜ€¯#*5%®°ÒH¿}Уy€À þú’TYZT)u¾€ÄT*z_€ðõ[‹ßF€ æA@ w€Ä¿üuU¬ ÿýÇi€úus7_ÿÊi€÷m€_dÌ^€½0¾0™‚ÿkTÿÎÿùÞü­¬¬h ÿÂÐÿôýüüøýµ÷ýýüÌÿÏÙ ìÉ€¾€óÑ‚öýßüü’£êׄ ì‚åƒPÿíÍý…ê–üK Ž…€’€€"‘øæ‚Içÿ˦¼‚Ý.ˆŽý2‘ÿû1+é¿ 5ÐêüM‘@üÝ)ê7m`);,a!ß;% ¡‘ýüi’Á€'ëÿ%>XòX¿ YU7*…‘ÞºM‘ú‘Û'à$÷>{“X^mtùe {“6*+7T–¥#‚ØŠ‘²‘øw%º"+bþ—`Y–¶¹²²•ûXXàû#%Ö‘7ÖßýüæýS»%c +À•Xÿi»ÈÈÈ¿¿¿ýeÍ•; } ¡(%À5P?ý ûø€Ý#º5¢ …ÙÏšÀ7 Èq¢¼Éñ=  ÿ@^ÿ)5Y ÿ%*6<66)^«` ý ¡²e¢Xà …\ÔÐ;Îd|£% ìßPþz"aùXOÿ%< <#¿ ýý’;"u°-c,aþîÀøÐ¼X÷X5•Úëõ5Paf" û)UÑ'6ÿWel[TÞ  ý¡KÎø¢%Rc,aqÏmÉd´È˜³<*Fû%%cQ÷S;zðz_?66 $‡Ð.ýT³)mž—lT *¥0®î ýý*‘"…À8V±"—`dÅÏw¡w¡ñÇÈ ±SÐ776+t0w± ¤|Üáï;ô+q!ÿ*v—ÿT6Ûýð¡I¸²ù$òR©RY©Çø”u€l±öðZc1Ä77++qß!þ—`%YY ¼ir„q  )üð(ù‚ h ý ý5ý+!& H# ÷V¼hÑÇǾ¾»Ç¸Ö³Yj@[õ[¿ZàU \籜'ðõP uÇs!„qÈ`*Wÿ µ*Z@h üç€ûùEyÂ"pöVóq¸ ÐñÁ¼¼¼…~5ÂmvttmÂñº ÂUÕá“!ïzu£áVT ÿk o<çü }ܸ²ƒ˜ðûôÖ (ks›s lQW5<Ä0xWR¾Ð@x¶¹÷%P¶ûv'°_k uÿuz}}~m;÷:Dý7ÿü+[ko+ ð'òQá¿(<ï<pÿðØÌó€°ˆaQ0×Z_s€¯Ñ÷uYV‚°øVˆþ2­<έ‚;VçðÌ‚ß*úTq±µWW ýgðuƒÛÐ<û%r€½WVö4Yy2ÄU*ûz­0úñü2‘<“ï û``ZUT¯7*(%|°‰pÿÿÎ÷uÿsU ÿÑoõg[(ÚÿÿÕøs®t‘k7_ØûÿÞý­¬…vomk¢‘¾P<ÿÚ÷ÿúûöôðÿðîìêéããàÿÞÞ’ÿÛÿöúõöûùôM±Ç•ôöýôC¶°Ø›À­±‘ÿöúööö‡ôôç‘®‘Ì“  òï1ÿÙ¦ôô9ݓݓò1¦Ï¿ô“ÿ×C§ó• O©ÅÖ£ ãê l¡Ê’ ‚ÿ7ˆ{úïõúøv¡3½éV[`ØôŽ¡Ì÷h I1ëÿ $8û?]¡\=4" ¿Óú‘¡ù¾v¡/ì5Ð ÿ"=]ø] ÷b]]ì >$ãÐϡ̕ 1½.Þ 8¢]ß]eoldæ¢5—(%ˠ̪¤Ö ÷Ý-Þ #>þ ´q£¹² œeþ ´]\%(ÿÉú |Ë‘ ó,{Àw:µb¾6ð÷¹½–æ£4 ï(‹Mÿ^ ßú _´Ìni²4Iµb¢6ñz6ð£æ¢ \Ê0 UßàŸa$ \´µïò*Þ ?3]Yö°v±£¾{±6ðï™]÷é %ù ÎÀ#@QdvïvlY)çð $¿TT9ú‘¡üzh¢*{À"]Àþ ³™¾ø¾í…  5X‘ þƒaRw_ >;$ûûç(3\´2Àó ;)®°'@ÁÀ»Y–}ุ¼và¶¼°SÁ<+*(WÿPŸ|ýL1VX<Þq‚Eú ±”PŽ„Â4ªÐ‡ù°Yÿ…©¶ø¶ù–äÀIµUTT77þ©À%#cýXýpV%ZYé;€v‚5ÇPú]‘¡öö™ )öÐÇ04²Ñ†Àe¤¤Ò©}à¶e÷´ö±Ê@}UûÁ6+%bå.XpûVH ´ý²¢/Ñç1/±Ò9Ò]—¤–‘ѧ§ à‹@Ä@Á[éjðYÒ%bÀ#®Ñ€XÚÒ.Ï çú Ë‘)Ñ(æ®° "âh %v{œžèÓ¤¤œdÞÁ~Ã]ssmmj¨Ó÷w¾ÓUsË{–à%ÉÁÌöûöEÕÒXöÿX&e———œò8äqÝÁ:ÓYo|z·uutÿÐkj-Pÿ[zz_|zZOà©PV³#÷ÉP< Ñ ±‘ú#àÝ.Ò>X÷1àYx••à5à6àùv:ÑóÒXYeœ—w•}|Mã6bpÿuzusômàÁ ù'ú n}ä(­ñ4.ã¿n|||””•á•ów]g#¹!e¤§¤ï¤œœ®áu ÿJX4+ñÄ`Q€>‚VT0ü_+úÿ“Ì.Òû.â]x|¿ø|wYâýdG屩§¤Ÿþ8à%dVe6ý(€y~~{_6+ÇP+Á–¡óÝãŒà0à §oxxìà”ñvKó÷e©¹HѶ¶±±ÿ©±YJY/XeÔ5ñp>ÿ < {~o (*X!77Mú±‘j 6ò$þ.â^wøw{lœôq¶¾¾Ý@þ¥ód?7Y~>5T ‡×)ñÌ`YT«*M+Áø~ñ ¸Ýã‡/á lwUo^â]‹ÛBÝ@ï]a”4%ù¿TuYˆPO<7T¥@Þð?´ÓÁ7ñ".â ZUvstl]0àq¤hÿ¹µ4Z[[»ûå@ Z£0ÿøT_sWTß;W9pTUâ;ù ™ „ùY^ç^Z^Kð0àYl땲´v ¿BT< âý±€XV Ÿ[_óV€LðÉÁîÕ6òXçXYeuçR×  °oHpC65ýYå÷T Ìp YT¯(úU\±úï¼5óäàõXúåXYZemu~®ûaz<Oþ%XX5 jsY1êü[RÒáÞŒ3* rMWÑÊ@[_jáa÷s{~ý{mTÿ%K>Yå¢áЂ‚VöqTpÐ@äðÝ*7ñü-à›WZõZï ‰° öZaUh"% |³bX _ZV3×j0j0 ©#à ÊÀü¡1+#þ™÷UüZo]9ÑX0¾º!û[Ø€P'úx!0°+”0àßVUTUŠ!7¯\ùâ•VMV ` ¤ £0Q+Á5ý~ó+á<¼# Qÿ÷T%W  )¡á¹•‚Yp [£0TZT;t`!0Òáì ª±á±€X"æÜÒ6+O4Ùð7ÿWøXn3AV€q[Z¢1÷/ý_; úgúó;2ä)nGÿ** f< ¯ûX-PW€jÿ_ù_ôT ÿê êê’ÿ 'ï²a²b†Ð$ÝÙ4ÿpk ñ ¢á•rÆ[[Tÿ( û(6¿VYe'[@ó>ÂÌ3 ½}C¶ðíå µbý[ÿ  /kZÿ‹ ‹˜ÿ£·¼È¿¾=Í(á5A³cX$üÀ;p§ÿýXt}ÝïB_W/‘ üïk¾ê ¾ý¹£)áóÍwV> ÷–P<“=pü¬A`ÀH%* ÿkju|œþ"À4__kß² ü²&Pd‹+ @$±`ŸDÏ4vB@ A‘ï$V$-ð÷ Iå z}ÿú[4jkþi   ¿ [- @ÿ5VöVýX°÷%#¯ %€x™â—ÿ—–—”>Fÿ'Xûkuuíý``÷_[Jq %—%âp0 @$€÷óVæøUï TT;†Ð^ž¹÷ø¹€;Zo;ôQï<7_Ð)6]°@ 5ñõ!)ŠR¿YZ[jjªÐYvYBl±ŸR—bÀ÷ !pSý+ªvà0­`6ÅQ;Pè¿VY”¶f³·³³±¶ðu‚q[íW?`8ò†ñ)VÞ›pXo²±ól àm1[!û4$`;ô¿6Vï1alßœ°°° eaZ÷{sP4+s¿" ?öß¡³%<öa `m~\zZ%Zü!¿V5 p ï*J$`Lÿ $5;<<<_;;;¶ÐþIÀ=Y z[ý7ËÐ;$Ý’VT2và7 zÑhÈ;×êw 1KÐ'É¿ q§±±²üÒ–îãX( á6÷'Y¶XV<wüT#0Dô$ ÊÙÒûßÒûåÒRâ9¾É gœ¤±²à²Úcà…aÒ Xg‘ çVÃð úVŸ$(T"ÔÑàüRÜÕüÀõ°0Sá‡À~«ád•œŸ²áµ±®Ðö¾àYTf’¿@²œ ü—VDƒFŒáØÐú"ÜÒüçâIðâ‡ÀcП wšœœÿáðxn ó[ZZÀ`*#»Ð×#0E“ôä5óýÀò0|öGór}}•Oó³œÈÀcÐ d`ZUUT(i þs‚Ws_uÿUT%ô úÞÞèîî3ó8žaÒ"d|}ñòOð•Ïdbb]TÁþñmsûkjo0Z%S÷Vazwt”TGwúÚò¼ =/KÐ.$]]þðD_bbvzzðõYEzDeùskk_2P5S-iQ7‘t€ÿ%y~yUTÿ %6<= Pôá2ðn–ãî1</\¾]b]ew|…|ððlSÀ¹Eïðzýyg[;Y¿4#+ qmÿ + >s‚3*+Íñ›ø5ó) ŽòX]÷]#btuw½Ïz|wXË.d|לš}ÕuýV=ÅÓ/ **T4.á¼ÕÐÑóùðý¥ì÷/ãò4]ö] lÌ‘ølÎ b”£ñ9jwPû5 V5ƒ¿~~V0àZÛÓg°Žñ]õ] st|Íu†d—²àz0_Aÿ<[YTVOö ö7áø9é‹ñT@=]ÿæ]l| °þ7d´²Y<ýXê1;ùV þ°Re<ô± µà Žñ ]YÿYY]ð]Ÿdlwcž0 Z=úXS >3BXû[RÍô ‘ü30¼ Žñ)BÝ0YöØ3Ze-Almsu×{~8Aé2w6ÿ AüXüXãû]q€ÇÓC÷ô Ì'11b˜@'“0Ù1Ù3YZüý_}yy{{{}ý~@yZ*S?f€Ü0 4sP/17Øà µ@20$~A~A$@çYYUÖA‚AT#(×(*(Ä`É`Cî®1YX 2XVi×ôµý31ý1„!YøYÝÓA÷U† H úœÿ<lX íFa[[sVÿZT6/[[aÂ7PçÑð" 0ðîB~A.‚ÖB f¾Ðc #E`_þp0 TTü_/[_þ .ôQ‹î^S41€·QXü0°X„K ïûVp`ý_™PwñýÞâP¿¿-ðá5µQ~A’N(Yÿ>$ Y½”qXYº0 ~’P#÷›Pò ýò©¡ÿìãÞÞÞ“/¯%(Pp,„!8ÿXöX >%ó%%á@NJ÷-pt[{2p__Z=.ÿÞ Þ“Ÿ‚D=ã@á@;ÿXbi……ù-0Tfÿ#%%bÿVYet• þ‹Q[W *+ÿ_jk( ÷(Œp]e…Šÿ˜¥©ÅÆÐÐпÈȨ.a4ÿXõX  ÿÿ´(*ÿsw}œ  ÷œý`p_[6ÿjkk»ÿ»ÇÈÐÈøÿÈý¿¾…×/a"îcþ"À ßö nß?üX uyŸ{}u`dq4ßökW$0ÈÈ¿¿¿¾{pLÿÑ¡ Ÿ5@aîcï=™pÿø %ÿX; úÐ8ñpmk ¯œQpKP<¿ks¶ŸP¶ÿû²±±¯ V3ðñí>îb5«q Û=“$@x²ÿœ”vlZV$õNQp%`Wü7ýÈp  ùÿ zm[Tï%5a$XßôX<ãA#  ýp÷X]”Ÿ4œEÞpý_KP½7P*(<¯pj¿ jZ7ð ü©0àpXòXë€AUð%";æ¼QeŸ> Ÿ1xýerZV Fþ|XðXýÿYùX YvþŸ4±Z7õXû$v`XG½ñäñ%XèY`d=—Ÿ4—g½` €"÷úÆpsTï Lóòà 'Xûï¼€Zv °Ý°ž0YÞTXó öBrÞ:R:yyÉð·7ú€R÷‚Á}5îbYlzê2s*JàçX9Q|`Tÿ^ ÿ$%4555æ’VV< ì0O°²m`"5¥?±¯œ@|e qzr²>øAúTlÈ ¿­ <<°mþÈ ±6VúTýo2±*5×%öuÈ ¿ú·V‹£%rÈ ¹ŸýZWÆÒ%àYïZT)·°òOúñös÷páâ° \¡q³­pé@ÿÎú°ùNLÑ(<<úcð+qàôw€ÀÙ Ã*½<0ÃTZ[j[psÿ[Z7*% ÞÁãhÿ<ö<TçZ_tZp×ykZ+ÿèLÀúJpÀõ<ÿ„äàÓÍÅÁªï¥˜–xgu_Tÿ( ÿîçõŒqyÁüåÿúäâáÖþ‚À®ª¥™‹e5O ÿñLÀ›Á U¯„æåÍÁäÒÀâzÖÂáÜÁÖÖÖÔÀ½ò½Ä<÷ÈÀTCßæÌÂÒÁÕÃÜÅ@ºÃ˜sÁòŠæùÏÞÂÂŒ”ÀÔñÇ&×ÖÇÖÏÖ0ÿÔ NÂ*×&ÓÑÇÜ­ÀmÔÍñÃVàÖ+Ü-ãÿïLÀ¢ptÕçç%Ñ'ÛÜÁ•ÁÈÒ¡× ×Ò&ßÖðÓ ÀÍÙïžÚÁÿíãHÕXqã/à1â°ÛáÓHãñú#ì]ïÖÀ‚ÿì¸wãQë1ïâÍ ãûœñÏÔ“èèˆê+ÖCgÿëÏãHÕYæßãô·çÑÄÞ”Àë•üñ+ÐÓ­ ÿÒÃCHˆUÜ)ñHÕÇ]çè7ô‹ì–ÐCéZKpšqµUñý+ûüfõŒë0Aìÿ$8?bÿdddbD9" ±ŒôHÕbeñ8ÿ{òý>¸ð &?fôÃðÃðcÂòb4­¯”)… +0Á7Î0­ééžÿÓÁ,½=¸ðAggdccµS?²p745tÕ€(úð0Âæ bè(hÿ<Þ¸ð!Df‹ßŸyebQ9÷9­1YX÷?° ÎÔÞé', àÿ;íþ—dq¤¹¹²¿{eb÷bÈ8drtjY ÿûTûT_3ô°i;øÈÀ7fèÍVÒ·’:¸ð Hcëdbô²p² vþý49wÿ[7%;$û½¢VT1øT?  'l ð0ÂÌ' ÌÂà9Îè"Âñcqo±±²ú ²|ý÷>±qkTÆg0 հѰÇPÿ 2 &EƒhŽw~Ö‚§ç=MXgœ½ ¹³¹¹‹ý?X% GE çXV°] )ÿT"+ &+< 7<Þëö·åoß8è —÷b}œî¸²œd)#Y+#ÿ 3±œu[É+‰ æ’pÀ±4ÿ6T< %r„7phéëZ"ô.ÿCs"\bÿbcb dw~û~š…  ±obÿöbYT+ÿ6#¯XXm`Ì 0ÿ7 %½"ÞÇ#'"ð­7èç!bê ow}}}ð"eù#ß[ZT* U€V[ÿZwwýTûý  _uWT_ ¶!$¿#æ„€ë•0[/æå:òD2ø ÿezz~T1l?ýûd©7EÿX[zwutIº Ù5_°µ Ǽ•?·âÞ7Q`ß Dbø¸0dt÷yz{T1mîù"mk©:ÿûVýÿ[_ZTøÿT;ý__Z[–Q`“Ü¿}z“9a=]ÿõ]üU“Z_ÏP‹Àjf0ºK?VVO‘ Ý A küÿ_X Xùë-¬æ9ïúmpL¢ YTTUÞ° *¡ ÿVXû[ ÿWT3UT?7 7-§ÓD®.“:¢¡ L¢ þÀ²UUJVÿ$  YúVù‚ƒ€Rë q ‡¢Û«OR4¢¡ó£„Á°ži0ôX €w±Zïv[ñP;jjkZ2P ™PTt˜¤ÿãßÞÞ­ÿb#%(((×3¢¡ó£6*ÿ++77T?(ýX ±ßeo} 8pY{T.à _k0ù ™PÇ èßÞ­“ÿhb?6*(ÿ*((6>Ydi…Ž˜ª®‰‘ºÏ5%%(Ÿ°2 zßktuƒ ¯œwU±[T!Õ`1æ æÑÀû­<Ú°;Vbg…ÿŠ¥ªÄÆÐÔoÔÔÒÐ:ÀŠ;³¾—³4‹°ÿÁ}}Ÿ¯mm €4ïjkÊ ÿ ‰€i<ÿT¥ÅÏÐÐÒÐÿ÷ÐûÈß¾D5=·;_ Póv ÿ@šßí·‘_[ÿ<ss $ÿ   ¯(7T¦:ÁÈÓÄ¿÷¿¿¾ÞÀ¹ž­7¢ Y‚Y!”ï Èõÿ 5XX6þ\suëþ²W6+û¿s + –Qý?7W©ÀÛÅ;Ñ[¶¶cïÁSÑîÁ; ù8±Ñ $XXß]| }Z°2 ÿ #(%*%$÷·À_[üÿ*ks7û ì77[©ê?гc„¯Ÿ‘ }jo);¢ *$UÒsYYSоÐ;^ЕÌÔkÐYª`0ï%00_[ÿZ*(+ÿT077ût±¨Ó  ykÿZ<* @KÐ)X¼Ò¾ÕXß;(ÌÑ]4B‘eœ±ûÑ<ïYX,m _[!ï#4µq 7 ÿ{s[U+%oI¢ $¾ÒÿõYX>;o$"'=A’Xn‰ Û±±ßÐWüGàóX ¬pT   TKÐÿ>YöYqµ³@“X^|c‚û}]VXT ksÌYñრ?ã³äÖÐwâCrþaƒe)“>”ÛøS°e•É„8ì5 6"†Ð ÿuy ÿ^ô =ø²èá8ñ Yl} « °DÐV\8"wôV£p[[ Võ,'PÍðl û47òYZluý~ž’|6:üoV.%S`uU°ÿ p "×*T[”~˜zjû6Ѐ ýÿXëV*ý ÓY& ï6w _ [á?æR]Bá[T"Uð4üðeµ‚0Y`8!M°—ý[YcºÕ7#ÝìæðT Œñ_&·%%¿C~q% __meRßyuy ¢°UU5Ð(4ÂðYõPÿT üuuZÿ&suzw[6þz±'XXÿZ|œ_ WVó qôP : û*¯VóøVw0Ze½ 0¹à0ßVThÒµwXÐ7 ÖïVTfÒ´V6Ð+àå0j¾¬7X!aaõý¼@ ÐÏ6üŠQå0i°ÚÁaøæ¯5"XX«%A n9®‚QV«VðÐs+¯ZŒ|E¿ uYqEÓ<×Qpe‹<+ËA dr#ë*A u9µW³W ÞDATw9Áþu0VYZT(~¦Â_Z|cÐMr4°úñcÐÌÔa4°ÿ \nað9°ÿØ¿Pö¤À S *%tÈÐöàú )ŸP÷TT<!5%#›\àÿè@aðÇ6å1K±="V¢¿˜…d;%("ð7 ¤À" ŸPü"6ÍÍÍÏÏÆÿÄ«¦˜…];#¼ àöø ¤À%É$]"`$Âi#˜"ÅÅÿÅ«¨£‹qX$/ÿü~$K°^%CqÑi"—#ž ž ÄÒ 9h©#að&*]!#§V®ÑÀ#˜&ÄÐ!®É©"U!%!å#<!@{!Cxê6DM9ÅÅ¥3Bͽ8ŠÓFJÆ%0“ÿ÷`D—5ÆoFz9˜Þö÷½7ŠýÔo@øÑýÍû —$&ÿöµB#˜4ÍÂ@oE3Ò—!öØ@½8ŽÔüéA›N!ÿõ<RàCYÍÕéHy6¿‰PˆCšðæYÕÕRFKÅJèü¥WUΗ3YÑg_Q0ûHë&ð /9?Db\\?:a 5 Ñà½8ÕÓQk]ßÅFìÒÐï:\bdEb\"ý)5?Y(ÃUŽXÜ—T›IhEìP »/\T€òb­€ÿ*ýYüX·ç ½8˜¼ÓR™]ÅCìP÷ 4bT€bf‹—÷zZ\öR(ÿ^rvlY#÷)T #?Žcûá·jTÚ<Ú(O5T ¬` r%µfôtšZD/r =dþ‘rbqš ²³²w yUd9âðòe Þ9 (ao™À  aðÀ5¬HsptXÁ«À‹qóQþÝae~±²´¿±}_böC`ÿ%²œuZ+óvjûV0 bqÈqjt]¹ÕÔ{D@@G {&ôP d|›®šp±[<ƒ<à[Ÿ7ùV8ù¢Tÿ+ ÏÑÀ5¥áÈÔquwÉ3 G ý/>`db u}½~[e èc]ýÃàX[ uwéÇÚ#mÀ …#€‰‚,†–ŒC:z­„4Ýabl–Bœ)cÐÚ`‰’‹‘(<àg=Ó€wtØ*!mÀÀuöï¡…<–‰U¬>¯†· dy‘~$ÌÐÿbøb]]û[+ÿP VÿXwzzW _Ÿwu 7²´G˜èY‘jtdÖe”½k&Û>Õ`$ôs+syŒ‘%ÌÑ$*“1ÿ]dk7*ß+7TYXr m ¯+ $ù¡Wûuº°67èfÐ\•­áD —‡Ýtjþ@=Õ`ƃeh—{}7ÌÑ0¤]ÿmk+5ûX¾úÀ R~{ü2§È•D¡h–‚ØtS!|’ öRWdsg[Ù/-’þòÂlys%ïXX\5þVT TO**À3¢ø9¦§Â⪭êA|’Û=È£eugu úÌÑv¦]ezysÿ7YïXY:VX)ÿ (TUZZ[ZTùT*¡°7àîHõYû‹<:èù¹“¾ê@ÌÁ¦²±esÏ Ô¢8þMµ]d}~}y%7ÖÐIjïöT, _T~°q÷±È•yârÀD®Í=3±,0À±²ls'À-Á)‘þòÃd}~}_ÿ Xü/X ZƒÑZ„Ž sFúøºè³ ºÄ‚ dkú˜ÀUà4]øÿ]l~y 65_±ùð… < ý[ûø%Ys*TUaÀûŒÁjtiÜrÁ“½Õ͉Ä=bõd¢kÿÀ ý=£Æx± ~ÿ(%þ1àYX _YÙMðö_!úZ3 :ÑÒµÃHÒ½cñÆõb÷jnÐT"õ\£Ånôà  (ä²À0ð˜ÑMðû[ÿöT%!_ü<ÚäHßÔ\Ñ¢4gÒmÐkm;)/èÕbrœ?ñöÑ?( 2ð¶áß%÷V“Ð[}üWTð‡ $ñæàµÞ‰ä$çÓ—DÁ£–ÜУde>`TàÆ³vô㲟œhòŽÐùý°p[YVTPrŠáý‚ ?Ð<<7?3³iäšäuÊÃÁ£ÿbóbù]ÏbevwðÍãv ØÐjáÿÒjü_[7Z[aÀñ጑èÿÕ@’7±#ðddelmtwûpú¯ð¯Îà•%  4ÙàÿYX jXøþrà [[Zwk_S .Àâjt„aðšè–„ÂÛ?ï4°]‚ZÊi¡{~Z€ñ²|ÿ)ó e²VV· [çàZ þ`mü¸ö 7˜2ÍÊÿì½`“öR]båYïó}öñŒð~Zÿ,> îà³<¡Ñ_W þ, j_7‡ &‚ ùàûàš„Óåå8D¨­¬ƒ"¼*•Þ¡TU[y`zÿ[6" >$ƒýàôT)[_?%.™¦øá7T7ÀÞ0K‚ô)”ߣTo°6*(%û) %îvVV_[=ß_jZ+7˜a ÉðrÈÔT÷Ñ­‡  e:vÐÝ¥]]µÿ%1#(*6îXpVYtà 5û"LpûkK p6›úáÍuÄÿÕÓÍÅÂ¥˜ÿˆqfbX>6*¾ä;89ãñÿX]ö]Xþ 1%* ÿýjw|œW œMð 4Uÿk , ôÇiqÓÍ„Xý<ä*;>]diÿ…Š˜¥ªÁÅÑ™ÔS`íÞ¡”Xï(+7Ï€šký ÿÀuz}}š¿ ¾Á[ÿ/5ökþ~à ücûà¬ÍÅÃÃÂßd7dŠE!ÍÔÿõÔÐD:ãðÞ õ¢Ý+E°Ñ¦Ðÿ_ZI# Ÿ—eiÿd\??V{…±/gá~ÐlFæáßVT1*'ÁuÜòà (SCZu³fD›ðMãð&å"à¡YÎCÓA5  '>ÐÿYXv m÷% á±XV5$»tà )@¿ssTpÿ ë&@X0 ?¾¥ÃYïY«pû]|Žð[)úîÚ€<)–B[Z#ÿ  +u·yun i0 óXËC)PôY TÛàŒ@œŽðTþPã°ÿ÷V[[ÿ ûy jQ`Phà)PïõY äAd|±ï²¯œ$6VXÿXVû[;»uTn lñ4°>YöYØáöjádw/ð°t}*¶PñV¢Ð} †àK p(€÷ÊP÷YüßX Yl4P¯²}œ% |Q5Jkÿ`¯+øwfÀŸTZZhàhàdûlmŠóš<'øñ@ à* þ1# ÿ%6T*€Tl!ññ÷ñ}}[A! ®på >°%ƒï(+p°ZU7÷%@%úûXþ` ý_$ÿ[a<$Û¥@¹TpV[Ùö¡% %ôüÑ Ñ '_jmtÿu(ÁWïYV³qV<?[syР´ð tu,ç`ÿ±%XY|ûš_†V ûVºðaT¨p h`¿¶VZ vƒVÿTe½ÿ 7TZ!m“p¯LÂŒ,pé³¶Q o,p¯>WVú‘rÍ q,p_±;VH‘rlp¯*!  €ÿµUW ýV«ü‚u,p¹²ðô$ ¹‘z“p»_s5ƒ&ÖœÀúñÕ¢L‚õÆœÀ cÀaÛ7YÿÃ^€Þ¿Þ“ ÿÄhü÷üêpƒüüPÞeƒüêeÿüKˆ´­y€êàçP 44'%$""P?Ž€i`ßK¦€4tÛà Q^ ;5ŒàÓÀ€ËÀèÐ04¢ñYø¢P  ‹ÿ‹‹l>" 5÷@p¦€ÑRÿQ¿n”‹‹xo«<$þ€ó@p¦€‰"Ì€ÍP÷’x×rV$$0ï$”øâ°¡ñ6br”‹””ÿ‹xöxo÷%î‘æ‘$óAQ‘Øàd_‘5’Ÿ÷xk“¦€3;v”äAr”©‡–ü*P”XöX ‚ð_ª’:”F’(‘5Â’¨’ƒ“Ó”·YðÞ” “]¨É“¬’Ó”¢q…4è“qï“„”ü“J€õ§ ø”µ ÷•J¡ ,¡'öÂ’q]¢ü‹ü®Zò@p½‘ ¢Â“Y¤`¥‹¡µ,¡%U£q–]¢ ª¦¤Z"’½‘–¥–©–ž¦5“"’,¡$âè“nä å¥…’‹ZùôøÅVX÷Xâ¡Â£ƒ 4j ±ü§l.°Â _÷”ý‹ˆ¡õ>±R ¸,²Q·\²,¡å"Â’ M².µ‹d_Mˆ1i`ÆŽípXøß¤N²å§oGˆŽ q›%³e´å§d÷Eì„A"/ÿ8>?>=4þ`45_<66·)$0¦€xHpwx‹–ø(Àí”{±CíP &}>‘X$Ž7ÐÍq›Ñ×rVVëe˜(Âù.ÀdBÂ4À ûP½ Ð5ÿdvv%ïƒ$ß<¹ð¢¦€Hpâ‹aÀ÷×–ú.Â@4À ~çÑbbextZóû÷]†°_7ÿ%;;6ü·Vó`B­Ð ¾,¡VöVܰ˜»˜˜ß»d?4Àÿ\bv±Ï±uU`RËBX÷-`<üVõƒµ *+T ( â’;Qøé‹ýÁ)Áû.À>þ4À=bw²²s6 5$T^cP,Àq%¨«VJQð ,¡öÄ™ôýÉå¡d:â&b÷wòМk( ý;zÕYYﱜVX¿tz úB@Uþ„à*T¯ â’6RÒ§X‹™¢ÐµÂýcÒ<þiÑ=bmž/ð}[ !ÕhàŸ_7Að ÿwuýVùûT~àŠžÀ ,¡›ÕeàýÊeþáXbbûe}!à±zUüePÉÕ(V[ÿUuwtm Ùaqgpsˆ —óP â“RÒ¸áfâß·;4À}ÇÁdy~!àŸœ_7 %-ãšQYÿ(X[z|ÿzutjT%§ó`Ó Yî™Ã˜–ÿÅuàÜãyÀb¿s{~}û6+å]Y>7VXxÿwz|WT#ÿüVûTï%y~y°á%ˆñ»åøÀ Èæ¶ÁeÐ;öc0@ñb]Ÿey}~m0ÞàVìôç×À#ûVX wXmìÐ6qþ6q0*+++7ULÀ ,¡öÃdÉâøËé8ð¶Ñ \bøbt{}_'@òQ€Œâ6c÷X²P÷  {~ÿ{{**­+™1TžÀ â’)¦öË¢ÉãÍç‰{?ey{sq0êQóç52YX,ý6rTT <w ~H_T`6Tàq }q6€þ|qd™ø™ýטûžðe{4wb÷syuÇ æQ>šS1àZ¿‹¢igçz$yuÁuÃeuy%L„ÔÊC6b[’ÐÕP½5ÐX%ˆ ßúT_”À üXV _[_Y9qÝMà(ùUc€ýåÀ1T÷TÃV…˜)ÍâF c0 ½=dkký$(]vuß*%|@XYë5Ösü@÷Tÿ e#UZ¶(` Ò±<þ"X—#I¥'ªò?ÁçZk(À&6d|~ÿ#ýXýXså ™A-9÷ù!$Töàp03Iz@8ÿbbý]jíj¶ò ;c$]rÿ T*;S' PPaÿû[úTB×#óPg8Y›¢¥Ô:™˜ûp1$i ³&"Ðk¾! $S~ùârœ² jp—ýYP $°À©¸0ç QóPù!#hÌ4;DÂ"{#$vÁ~"ÔZk"8ÌÒÜdPo@²¯ í@´ ¤‡ÒVY`_o[7ø[TàÒ±Å2G¥;Kûpæ1¼}à{Àñ]90eýxÀв² [¿  oQ ç uj­rO5 T¿ZT6&õðA }ù Tï÷oÀ5~$ÀYum/Ñ¿X éB €â`TDqûº€³WrÐ`£° i }µZ¡p>ç0ËA»úYÅà% \!Ó$ÛÝ@z>0ÖZÁ¸0%Öð¿uu7W Ï%‰d àzÿuj[U7*% BðMÑ÷8Y XY>Ï8;;>A$ÀZ}º>0BVÛ`[ÿ ·uyžP ³à~Êp PÏ¡ XY×£G1â¤Xÿly üXÿõV> 6¯sTžP{ŠÿY÷YX(±ÛAã¤| ñ—¢ù³Q˜p% ¿~uÀ|>J±'Yø!µâ¤/Yo µð嵐ß) 0À~ó?);QÌ“~)µZv¯<žÀÏ ;àZÁîÿV ü[+%×7T*žP€ÕÇ*TÌ“ÝAÝ@Zm¿| °|j`ç =á¬ÂVû$ ö¢(%%Û7ëÐ*¡pƒþ' *7UZþ9p[aalmmuû}¾`œ<ß %*6ð¢ì¼UÐÞñV `8ÿa[<$ÿ+oU[_kE€uy²ðþ``w6X·[ú uyïp#ÿTUsu(~‚À+[Å÷yj6ô WYçWVB sûyy‘Ày ÿ4’  íÌpƒ œÏ_ WrÀÌT öGF ¶ŸXZnÀ$ÿf½ ¿ TVnÁk¾!еXqðÚ¦á вM1;· ;µTi!гßXV¥áTÿeÐÚBnа=â—øThЭ7¢åpTþ3 ª >ül±È<+T|!@ZаúVŠÐ}¯á²VVyè ½o­ÑXVŽnÐÍ]ú‘ÑË0 rÐÆ5<ýTK@ûÀ)ÐýTû;%ÝѹýZùYUÒBWZT)÷ snлjsÿƒ.úéñ„¡pà ÿc÷ÿÂ4àusU¿# ÿÆ4à þŽÁu_7ÿýÉ^€ Þ­¬‹ûvkD±ÿÌÿùöôðîìý‚hãøöôôûð wæôô’ûÿËkà÷öóõ ’á—á’"þÕ"÷"ÿ &"&&&"ÿ ñöî|áê©âbÿïbdl*ïîÂäPý#Õ 4Xbÿñb lttt?[)ëÂánà¿ê&õè1>‚ôb dùàñÿ[( éö Þmá‚(«á ]ÿbõbltÿ÷tZ% ëæ(ñúÇá(ú»°‚öbdÿotôtY÷äKôK)ò«á8ð^ðet_ötsùà*ló•ûÇáUó9ócóys£°’õI)Wñüèôòt6Uå(ñü˜ø ¤öógðdöpÕðÙñ½ô'Ýé]bÌôRb l`¬•Öp¿î_Z¬Ý•´=RbÃaõúÐð&ð¿ò-‘Ç/vtRaøgð‚éÐ+Õ#Ç@ tQó[›ð*»°w À90à»@*Pól¦`463 ew%VðÀò P²uøvúgð†°E%¢ž-ªZ‘€ÿ)5_76Áƒ Vñà°Ý@ޱr¿v÷vüññ¿Qbb/‘€ZW$ƒ  VñfAêµe"ç)x÷^v¡ üT½‘€ZTZQ'Æ»°(³4#(ýJP!=Yß>;ü6 <ÐÚÐTTBžPb!ùh%Xdwwwþw5H\ ÿTY]XÝ-AVVíÐÿTT!5T šS&»°á¤)²oôµ Ãýgðo Fÿ =±²ßs+ 90+ýð¢V%7(T/[o© TÜàé"?XöXáþ ÿövtt<¿Nv ËA-ü GPuz }nÀ#YT#O ]%»°;<2ü!õvµ&v0VV]ÿ]Yy_Ó"X’ ÑÒý k0  ³ZQr1<2á^ƒ0´!ÃgDwXiC(žÀÿ ukUöTµDò@$s8lÒ2õþØ0Sj7ýÈ‘ 'ÿXX[zz||ZÿuwtjT(qþ¬1ß ÷T /3Öú2È3YÏ9YÿP}4 ÿYY!TXýûXb0 <# ¾ÒÀ(y+Ä`#âs24È3AÒ6Kbey{~ Î ÿY-VVm ÿ6 ýVýf1WTüŸ+ôTS‰AÑ y3UDµ&Z¤@]bÿty}&YþÒ`Va6}-Ò~{†pïZP< Pöc!s1ï z2vx*Uü¶"mÐ@\ö =ÀøYÿYXûXs[[áhÐjs)PÏûUO öQ"x#Uh¶ $H ïd 84‘]YºsA?pZ[|`%ysv±æ ‘ s1ï =1``û÷wÉGüb ý/É‘o~×+5k@dÐXVË ù€Y«2Ã`T.«ýZü –bsSùd¤ah%A8?bú] š”PwtÓPX5æpvxV+À[_S_ m!YÓQX=IPVX JKÀÊnÀ,ÉP!ø0,qˆSÑ!Á/°^ñb|S?€Eý ]_÷ ;ÉýY}m!X% [2ÿXV_[&wUTÅp $ì€7 f;ºÒÃü;sSfoEýbîS1YY0XXì#@~sÑ`VT5kú[^ Ôq~uz|ÐYç{w5Cò@æ7 §p4’° ýXøV‰C gr€|`¯Qs2ç5V[€k°nxo÷xü«`o`Xb] ÍS  )ÂÏ slÂSÑ ýr±[ZVTÿVZT;ý_±|`‚°q‚y…Yº‚‚û“p;C}ðÿxœé]p¾@ žÒVV· gqZ ÒÀWj_-À2ø0Qï)Vö¿@l‹x¿øxw*Pvÿ Dö]vÿz¯± *Xú\€ÿ<[[ýK_6O ÔB'’ုöx5‘<ì€b]š³°O ï ÐÁpo0#n0Qé%'—pý“pVÿýçô@Ÿ2aÿü[_Z_  F_ Wñ}'’Xx‹‹.“ÿwwXWÿšm6;;#üXÿ ý[ ¹7ð$SÂVÿZt ~zusjZUT6(8àÕU¬p¯ !€còëVÖÁp( ¿6y{ueáû+ „û  `SY í4"X% XV úW Íp.úÑp–'`Y rý9Á* üÿ[' {ÿmT6?(X0¯ Ÿ1€qD¯ 4) —'`Xÿ¯| )s@ž3íÐ ’ûÀ¿#%)Q ÿ–[allmo<o@û£Pô$p^Д̠#ýXÿTT%yuûyyPà! UUZÿ[[jmtu(ÿ™{}zjûßsWWýÂ<[s·uuÙÐyUéИÿ šjZ¿YW ü|€TÿV7 ÿ*¯¿VVZRoT`ËZ ùÿÑUÀiÒýÙ³Tfý³IP66+ëUÂTXáµï" VÂTT nHáÓ—";gà»°Z2X~@n¾:¯üXú}â¯>&Ò6Ts¯á0ªr~@oZீcŒ¬¹â V~@pZà­ï‘:±6÷VúÖá¯#ÿ**%*š“ÀvZàÀ—#ß²T÷<%r3à¹[ZïýVPYZ÷Æà»_ÿsƒœ¯úñPõ‹Jð ÿ c¿ ÿÃbð ÿyysk[U(ÿÿÉ ¼ Á à_7hðÎþbðãàÞÞ­ÿ¬˜xtsssk×U(xðÒbððýï­ñîîîìëçûàß•ð¥,ÿÿÔúïöîýì“Àñ÷¬óïîøîììëÑóù¬ôÈñì’ÿ«Óy`ððõ÷ùðëû r1 ÿ!"&/ÿ0:9=A9/?äðîð¬òÞöò’&uch÷ïh_(ÿâð ýðÛüï é C ïdfhho÷h¿immmRàð±ñ’÷’)ÄÀ$Yqf¤q«ffl}ÿmmj(Þ¯ðü\ùùðãw+D¤øÝ´¶*ÜÓð ZÆðú?‚ý-Ô°"fõf~  m÷mìÏÚð Áûã×,Ó&ômOkUóû?ýK?föŒ 5;ÂÆðýÖùðê lmãõ6†PcûïÝü?C-s1/dwf÷W#ÛWéû\nb±dËÝ_±3›ÍøÌdÊ[(ï ¶“îyÞÂQdödájîµÆðîdßõdó^6ÕÝú\$Ÿ=bd÷% ZZP!U$1ðÊ«ddh`d$T¼òŸ òð¦!­ðÝ+.ò:E€b‘!E€êZ¼ U!ïïûí?#bøbã‘ Ÿ  ùò¥"¬%&böwb$ßò#n¦"ðî›\3Ö[3 ÷#ð“Ê3:(ƒ?7ï.N3 +"‚ó Õ÷#’3:+oáò ‹4î o4ù9w6] G4ÿ8=>>€<6å«1÷"“4 bûõbJ"TG÷]ë ¤€Yph·ò Ý3ê 3/þ¿:FübJ ß )<Âÿ#<:òý·ò’4,6½ö6Y?+0/ÿ[7(;<;;;6OQÚ™à3Rò >Bêâ¯#"šr’C–$<ÿ\]]ÿ %Y kTÿýX^ò u÷ P¯"XQü‘D37H6 8]7ý]k+£áÊa}Tâ")TPoòºAê¯#¡œqpP˜E%ì€w÷»°²œû€rVXïwsÂ!WîËp }AòòKÀC=ÈCR}7Bÿo X[]ø°-‚r4Pþ‰ã,›Qòr2ï]õ]J"*9Ÿ X»°»°Ÿ6mU`ÁßWu{Åp ;PP WQÔ¢g]öå@}4k Ð]Y,Vaz`çZ 0@ÓbHêñ ¿æ3­V7Aÿ]s{~})õ/póÐuzzWÓ “À`ãÅp!~SPIIæSy%íS–$O˜€þ»°-XXm M+nÐvá™ÁÙ`_*+þBZ`îcXíRlsÛmV@U€bbõªÀ.`pXaï šÀyß~**n€0ºM1"íRdm³dÿ?b]eu{û N‚XXöÅa5óATTÿ~~{{_T ¾0à*ü7up/n˜°?N€ø¯gíÄÐ>Ps ý>xaY" TÿýXXVý{V’`+ïT^*qMrqrqì`³`õø^»`]eû·Y±p³@ôlàUÀuYÿ+7TU9^°!;wbL‚û]e:t_5ï\ ŽBmuZ——‚pÀÐ[ûV_[òÿT_sWT;_$<<ϰ °!£!Ђ»±mðm¼€´(=ý 0]ûd +QîfСX^Šáus/Ñ °--ž4ˆe ‚q?l;eS5€ÿ]Ym~û·X5PX ¡þÏajZ;¾ P )M1 ?YõY‚&ƒ÷mm+ÅP=búØp +P]Yv{Ñ jY©`~ÌáNúZi¹@ëi„gà'ž’YöYdð%„} ^uPs(xau`îü04†RXVܰ  T÷`ÐЮ(‘ Ñ"Ђl’½„TÓ:{ü  º°]Y¿( ÒXoüV}`V ³ÿ6!UZý¯¢ o¢( ÞàrL•ZW”“8{„¿nœý1]å‚V?ÀWšÀ5Z[ôÁ@¬Ç>*‘ü0ÿ‘lt¸œñ¹„ˆ7b3qó84Á@°¯ ¿k÷XÜãz3‘.¯ø[hpý*`aXöXÇYtS¡º‚"€ï5XQò]ý¨@  »4‚ÐX¦à~Zp [[_Å žKP6&õA£GAE;L£eT£“:09 ÿwœßøX ÍãXVç#–íàTŸTü_3ÀÀ›¡¥L¤m©¦€%¨Àtÿz 5SX…PÌàùÀ IP·,ù_&p )`a42¢¦s£#€l+àÌ@ÿ]d{1 ¨€å‚“ÐùÀ2†p#äJÀ¬‚쩪£mm*ÿKš  ¯9` 9Áß[‹ [[_Z;__]Ð £‘Ë$L£Zs¶ ÿLœm5 +òL¢ 1¶s<DÿY{mU*ÿ(*zkÿkkjj|œ—  ùÀ#þ@”€jÕkªÐ ø‚L¢Yþlepškyÿ}} ¯m;_yÀ!ü7ÖQ&pÛ 'œ¨eäaZ¾lÀ[UÐ>Y])/ k€ðÿz}}œíýùÀ$ý+sbS‚ ã WÁê¤Yäÿ[XYrnleeÿZYW<6*üÑwa$5}m;߉ Wÿý+ý*%+ë ã &¨·Zjïljll±À™¼¼÷¼¸¶Ò©£ÿ9ü]4#ý‹ _[ü+ÿøs 7 W&œ¢8; §^}Ëá7QGÁWWîÐyÁ)Åç5Q³ÞàZ|²ÿö²”$ýJ˜pYX üXê‚’ t •9{×{sT €Ï{4ù‘Y[uÂâ¿~}tWÀH¯úY$S²-#P,o{u#Ð9'à?  tÀ½uP%Y Ó Oo×5QŒÀß:ykTãàŒ¯ (I“$'”Xù"×PòеýVéV ꊡ/À)5ð–aÿa œ<éVûH`E[a<µ!±à”“À2`›ïWïG kýu‡òyyyu÷672±à›yjûù“ZYVý¡p< yuy¿u,a6(±à“ÿÿ'XVZ|¿ YV rCVïV eð¶XþTVýVúõ@õ€¯ùXúÜ kôðÈ77 ûTg³°¿67+ Ø j¾ ¬7XÕá·ý³pY Ru@6óñ°=`ÖæÐK‚lôð¬)*ì@ìAØ nôñ›r3ÎPd¯'z·ùT´PhAùëVØ oôð±ùVûúQ¯<­“;sÉúØ uôðÂûVûûTtð³(UÿýZýTV¿VWZT(¸ÿ»jsƒ?”úñâìýƒæ c¿ˆÈ:0 ÿ[U7( ïÿÉþTZ»mu€Àus_ ßÿÐþ<ÿ<ÞèæàßÍÁÿª¢–wuss[ÿT( ÿÖþþ!ik7ÖŸë.åïå‚*xà hüE!>#øilÿkkZÕëÿ üëüéÿûèûçûæ?åà ´à-pÿ(lqiñißük_¹ðÓÿë ýëúéÿüèúçü׿k .¤  ÿ7miói ü„ à!TÒëñ ½$•#Ê!ß0®¤ YE!h 0iïhhhiß$k[óѺ! ûéú÷èüÈ"C1Æxà 00t"ieÿk÷k(ùЋ$Á&ææß}ßbhõhQ@ÊJ3%Q3û&2•#æyæ50¨Q9hör0ÝiJ2_Q0ììë±0'{Þ62fš3u4+D0¬0°?~’4!š6ÅöM0Ý5ä1,Þ&Ç3Dš3I3ÐÞ2QB$u3“3o:Aè FG**A•8g¡3ÄÚ@uBJIR[FBÎ;(¸ ©MàŽE&š3õfC ×A ýìx‚1’ +0-281É7 =1f=1u4<ñÔ W(0Ä “2vlp(QfffQRUjJ36Q Qú"úEQ,JRAfö±f8F fRüì$4ý>FVfõƒPu4¥#‰ ì#0–UUÚyS/€Z_¸YùéNGUb€Su4*L º»Pû–UèyS*€SdC aaSÛ’óS?€YTÿ=/8>?>ÿ45_76]6%ì 5dýgûUPffddd¼„au4<Øpbç]"y“ Zÿ# î çîì¶aå4’3flp8ƒb†adfÙTþµ <õ]C û)<÷r$<:_ìú–RQÍJSbÎaÍbffúÏF5d /_7%ÿ;>;ü6õ à ëôT0øT? î µiÂc?"dõd A¦1ÿ2Xb!'ÿY ±|jT&VVIîByWëã óTD[pdMfÿ71=ÿ¯²s+ îÅÀ].°Vüþ‚VTDî© µcä2‚QsXrýmJ38vÿ]±œÝȤVQ€¾7.?q ½îµfã2ù€S9bÐa(‚d:GGn ÿz_7öoXš- å?q ‡Ñs bgbbdn€o€dblFõF±ÑEçñs{òÔ° 9ð€ ýî^aëãÃc'q€òq„b(` B<ïšj +VÿV[z|z|ZŸww ÙðÖðH×Ðtß]böbÿX6ÿbm{~}4þþà]Y#TX|~¡MV1%V€— „ìÅ0Rrôøƒ(d p]eûû]+0¡Vm 6Ÿ ÖðÕðþÔ°ôT„40ñ‚?øƒOf7sy ùY+‹°û7{{þÀ7TîÉœ•P*@RrbÓõû€]TÝÐbe·y{ „ ¼“àÕà5MÿjT  ö³‘üî Q33ø%²?–‰TD]Yÿ^T*TúTÔ°y/ Áîœä P½–Ç“u64b_be Yà!ñ ÎðX<ðúq~ðÖðÿ < yYq¯V€¢ìì ¤ù"ªàP*\ ÷]m™Y}ÕãýVú“€_WYúT€˜£|¾”ƒ+A;LÐ}¨`U<1½V’Vý[³ _ÿZTøT«Üà ³‘‚3Ë4ŸÁÇ“ßv0ýb°p]]js¼àÑ% o~ýà‘VXT ‰ÐýYÙðZs ÿlZTUÑìÝ »”çÁ8†šU÷1ú]Ýq÷Y/tâ‘ð³ß_[[ÝûÿUZëÿ ëëèç3»ëà.ŸÁ ÞÇ’ lkm4kþ¶ b ek(ý ‚Ñ®pemw. [z¿ _ÁYïTkÁü_ÿ²ü²K}Oð/ ¢ïÃ^ï°¼ð´P*&]ðp±ÿ < Ý ³<§à ýY€Àj_[_ÿôT u umUÆ0Q¢š×zQÄ#Þàb]÷¥°ÿ^{œ/ØEöqÔÁ[[A@ 6ࢢíÕPÁõÒ´¡\þ^РïôXÈ¢Vþo°[=jjZqáCb>ï µÀPÀQÂý*!  (n#ÀX À'ÐU_ÍÐ „,ÌqàÅ5¢¡šÔÇãà!ÿ=jU&|kÿll¯wœÂVT ¯ùk õá£5°p¯q9ñZFåmÿmTekÿmsš û mjã!<7»5÷P_k.` / 4?Á ;ñ…€ö[Ñ]j4[_j·6À)#Æð ÿsušÝdñ6+'¶P zñ$†ñ¡`ÂñûZjÍò[]Y[ZŸ*g0šñY÷/m~o÷;ÁW7ÿ+++*3 ü7±¹àYöYùZÉÐÀY]”©§ÿ¤œ”wme<».ÃÀY]Qkâþøñ**ks<¸ð ¢ Yõ  Àÿ[ZYY‹±©©ÿ©§±±±¤¤5û+dÐ]S_[W"ý(í ¢ ßXUUZZPx¶õµY±WY,øOYM%Lq°"%Oýuwð ¢$ ÿ>#VYY…©¶½†eÿÐY±Yß4)f!ÿ*Ïsssu;o$¸Ãò a¡`;)=‚ÿø¶µl§(/9ñ…€2 °¿û_=kTñà Æ7±ôö a‹¹ä=½nÿÑn >Xu çûVõq¿<4f;/uuÿôOkÐü¢a~Ydž¹÷þŽÐ]=ý;#ŸûX÷VðlâT•Vwð5¤Á{ÁY¿Yn©¹øŽÐ§—4>dÑ%·°øqþf+6u™TnµáxkÑdû|²ò³²r ý<â‘÷X» ŸâXX f æÀK%€0ÿ%;>YZlu³\ð1 ln1òjpŸ`A"rŸ  cáºÐß5 là"ÿ ·{m!°+/ñIßg ßd )ìG " øqîVÿ)ôTÿ 6T*ö¸ð”X ù ÁÐTT$ÿ ü[(%%ü‘ äЖ[a ÿ< %*½6R#üV f%ÿaa"|­!8}~càþOVëV m¯uyuu0y(ð7¯_jçð(wð›ïzjI€eïWVe‘VT<w°ûuy ˱"Àÿsu,·XY|š_Z60{ ƒTTÇ{µöV€þyÑfÊŸTņ ¥a+si€ö€ i´b~vÐÆ< ÀaçŠäÇcÌmÔAÝ5 (é`ø€ÿýiú_wj_úaûÂc¼tSlÃ5³Q¤ÆQÈPifq=ajóa °6vqBtRl@§I0btgpiðaóbT»aÇü=uCWwbœ¨qªriie¶`ñrœ»c¾pˆåÅvQk:þœr€iöiS óbÉÑ»cýÂb±å‚ÇgòDœr9iõi òqr´a*c<€„åBˆîRi:6³PhØ&ƒ=`i‚_ aG<<@CˆM‡­Z„ÿ!i÷i hÝiòc__UBaG<<{BðB0•‚7DêshhíuóaÁé…¶‚BƒŠkÏ„ihS‘X“³`òr‹àC`?<„æó‚‡ØU €:øYhî`-„_+ÎPTm“TÍr“»ŒáΖ‚/chö—e¦ƒ|a~ÏP<ææ­ŸúÑA-‹’hõp—ñsvÐÍRåŸ.Qc“7ã±AΕ-„ý%Pæ üæÿûåúäûâ¿üá,ÿ“Ú£lÕ”jQY¡ ¯á6£&Γýg`•7Ìç Ç烡è—ÉtÖ΋’bΔ •ÿ248")5ÿ_<66(¥³¡¸¬Çd6£fÎ’ f±s2‚1°Àÿ]]"üYb$ O¡渢3œÎ z7¢9”’ fherpî ’(3Sà#dÿvvjY# û)O[+cà€Âº0_2 –Í­°å8f¡4cÄ,…*4 V]†òÿy_7#å@}2zÐGçÕ™ÁúžÂûøÀàæ[ÃbcÆÍñ_j#X;ñÿ,V[Zw÷w “2TWu{ÿUT `éÀ:ÒÀV EÐýÃfõfÀj³æ€üþÿXX[|zzzZßuw R@"ŸWT<”Æ?ÓüäFÔuá=Öqs#<ÜË¸Ñ å0Xwïz70ÔC^,PçüÕý™ÐE‚ýà ¤Ó_‘óbÉbey}~ ;òÿYY*üX +ÿýVûTïYTÕÓ ûÞÕäàìÒ&¢¶Âdã\Òpp7ÇÀ{ÿ} ÷Y,Veû6Ý0!~{+Çç(á?ÐV ä.6ã\¶Äd‘ài°ÞmÂj:iÐYYßYY~Á5ûܳ Tÿ(*+77ý7’°è èç¬ñ›¶àÈãÖâdø1ñ—âòrZ)ÿb]sZ? T€Áé óN~1Tu¿ )T ñ7á<éÂyæ5áq8dÓödgÄòq(Ie ÛàÆn BY‘1T1ÕпèûßÎ$óbŠóDæ ÿ\ý]ÿX Z[þ¾!VV  Z÷[[€1VTõY@0%ÕÐûUŸè÷r‘Cþƒó"dõd üßâ¶`T(]]Ÿbd 8Íü!àcð<üYýçX \ó>0/-Z!ò6¹¤ÞÓó?Šô?}j'%]bb2°ßls/ÍYYý,V ÞžYTø@Ysÿ jZ;èÓ€ 09f¡d?÷d b˜âÁÄý&u°kkþàv (û% 5øV ÿ[_÷T ÿa#úZç¥ ™ÇŒˆá/1òbídªdd “jj*ç$ K2±dk ýÑY>Y~¦ñX'ü[g1¯MæœÁýäÒ AèªMši±îor"àb]bÿk ;^ÐYY ´ îõ0'0XXþð Yk6ûÑÐ.à ÿàÍÞÞ­­¿Š„$ o#24Kðšõ°q²Ð$ù]~çâjB#ýÙ0[W.ÿ7"*úÿ*; ÙÁl7û[[@0T¿ÿù¿ý¾½¹¹±=34ÙÃ$ÀÂjj +ÿd{šŸ  sýòV_XYü[A9Âÿ##¶ÿ¶³²ø² Z 5…ò6Sÿ%X]+ÿý÷X€Àý[?ÿkkZ  ÿü  zuk[U%64õÃ#aÜã_j ÿQ#(ýX þgào}Qjjÿ E ›@=49µ`TÇÀÿZ{kW*)ÿkjjlmms¿w œØ0ô>oâ1 C]%ü[Óøp+Y]&üßXšksíÄ2Y õB4Ã"ý_òßá[4€Æ@Y2uÏuy}Ãë!_[ï"ý+ÕÐ0ý âB/bøbyL.„]X% Añÿ]]$. kssÿuz}}}o;üû+'õ AŽ4X—^«Zþ/ƒb]xœ}m6ß$èá4,ÿ #((*ÿû[5øs <› LT °VR]ù]0@0]]vÿœœ~t6ïý]  ÿ59û[*(/6R%1²2±ß]bYZZ0]]ùqªP¬Pœœ[ûèá]YO(üÄÅ #?%suPOQÿ=]ö]ï>*7UkÐq±ýŸåQtÿXZû[#_æ`" eý?b?;]]p¤±±±¡ªP¿| 'áÏøY+ ÚÁÀ5 “?10Wß@eñ?] q§²Y`Y`ï•¶Ñ(<÷X Ï4VV4ÿ[[$  ÿ+u<Þ‚e&]òŽ`…±û³²Õ`±±œÿ/Y> Z}ÛÓ0ûÙ0WTÿ $*¿  BÕòXo]õ]ó‹¶qþÔ`—2öXÞ~ÁXV@1[(ÿ 6y{|P®BY]÷ p¿ež¹¹¶¹qxÿ "Y ü÷Y"52VX*&qYPDžqT`qr÷e|¯Õa²²³±Y.Èt¿  43 ~ÖA' /PÿI÷ ÿ$5Vly~ÿ   ¯²o'(X.!{%WðG ‘ÁßTU PX ¿ +U\ð*Ï. „ ‰sÿ²|éûV×)#%úÕÐ)ÈP•ýaç%RñÎ1T÷ ™ 7[aß<#LP”ÿssÿXXZZýV ÿüuýy)t¿u(¸+Ð+ÿýyyZ× U€,Y€±û%X& ZYVß ýT|VV eµ»ÙxÑ}T‹¯>3 TTƒ˜‚•g €´‘‡Á8À}f‚6;yÓõk €².ÀX_†Áj €m³ç`Ê;Çõ²+Ðç`Tlg­ #‚Wð%Š€±ýVX<‘Ö£€V9Ào‘úVýáÁnÿ¿¿±øV‡ Ìz9Àr Æ*<Û°Ýu€ÄûT@VTýt€ÀýTTÿWZx4_úñ|•$vý ˆaˆõÈ€4  ÿ ÿíו“"Ñ2X>>ÿ;54'%$"ß ÿá•“ñ'UñZsד……?&õ¤æ•ðs5lÖ•Xd¦þ‘o˜i="‹Pÿë•mï‘P;𙋨þ’~þ¢d8¤ÿðîù$ð“Ñ2d¦¨¦ÿø¦ £¢¢¢ÿ™‹b49ÿèç´P7¡%V÷V  J¨‚¡ß™e0å‡ÿ!0Aciii¹8f£ ç X¥«««r´ï¦ï£&1…Áus+[dSÂñ*³7q§£oÀ¬Çð¥ÁɰïTsjÖ²hhjñ±ÜÁ#$yÒ¸ð“«ÁìÎ$1ÑËumŽÅö@°Môƒ<®ð’VéÃð®Ä"¥CÑjl^˜µhihg¯Ð+f¡†ZÒ#­‚#Ò+ÕîË/;1H°DŒÖÓEf£õ]Ô®‚iÑ®³ÔxîÉÑH± iø‘À—hü”ÀœÓæÐ#i™ìÓV²Õ«¨3ÃÊÂտŠ-ÐØ—ÑTµXÑöƒÑ€ëÒúàçq®®÷ÕrŦ¦‹¤‚ÐOáAÑ×Òdæ#C<³àqá4á{æ©îÇ7/2ÊÑh›åØÐqaçòeâ­p$6påÇTTi{à÷Þä0Üè—Ñ íå#´ä™¾á|îÓàOá=ÝçÒ%k¶Û¡øƒ5>óεàTe»Hù4ÄŽöÔâ”Ð÷hÕçátñ yñÿ<ø< T<ý˜‹ôø«û¨ìJ°]ò’ÐøhGf˜Ð¹0uòù{ó³ä<ÿ>€766)]âúd1*9ç dÄŽÊ÷¨¨^çòö@æ–&à!c¡Z#ù‹P <ö‡<@Áå3À:ë3£4^+þ#1$^vvlYÿ#ýV ÿ#<3j¥±ûd1(9dÁŽÚ‹ü˜bªòfúÛÓTP9<;i%Ò}D ÑØùÕìgõfhÝf®(00÷±|41V< |©Ó®€ ײœ@æ!çwspïÐ/Ÿ3"ÑY#ÄÅ@/A‘ œýóffB0êà=ÿm ÿX]ü]Yÿz[7ü.‘V cÔ"ï`Þ@× ýG`юŦ+÷ÒT ñ"›33&QÝTÓ Xža4ŸUuw %Ó,âu¯C 2ž&Å¥$¹!ñA07Q%òÿœ0€o!]ÿV[zzzý|z€%+÷T¥± 6Ê1B+94ñ É!25Î!ÿ })óg`A+XXÿwz|Wuuÿ TV3%)•!¿0ž$ÁË7ÛÙ¥ !øçf&Q/ð ÷bß{~ "Yÿ+ üV ÷6¾‚ykiï`X€¾069#ŠË3¦#‹ó®Ý1 Û=I@÷f't{ û]0ýŽpï „‚T-ÿ**++677W•9X+Cø4‹ô?DföôMA°ó5Pe]ëYF€¶@V5ÿøT< ü÷{ ÏD7ÁñT®ÍÏ–y{ÁªCpêbö`¶u:3 ýÿbû] ý] ïù Ör%Ý X¤ ÿWk5+UT #la>Âð…ÍÍÍ–sÊ8þªsDfd÷ýdø ]bΈ€] yP@rœó »'û§X|pêqù<ª~˜|ÁÁ®®ª èbƒ ˜`z‚Î#^@Š€]ÿ^k";ÿ]ýY² Ëšƒ@¡ÿ[[T.$"<­ i¯YÁÃJðªpÄ ?"dõdOÒ/ðïXàî]¿4ÐßlXÔ‘Vþ=;k¿_Z[¦€·< ­˜0ÁÿÁ¥………qiiùgöa}P(##ß%.3‘?dûö|„% ï]ÿ¯±s Ò‘³ zqw_ZVu@VTGÊaßú<dÅ€ªª¿¥YH°VTlœÀ®½ûð"[_jp¾Âñ¯øVú7ûÿ¿jÌûTo®_*Gs ðÀ¨O1÷!V2t„ »VÿYZT(uÿæúñê°Õª ^0aoˆºÃð÷+0ûÑ ÿïÿèËXçX×rØpYX8ÿ&" ÿìûùÌ%>Xüš‚IáYd””q>ÿ" ÿð]øFX} óïq––”;e;ÿôÌÿX÷XïY]‹–9””xÿe5ÿøýHXøXý6–”ö”ßxd4àüwö¡XösôU{÷‹‹xxU>‡ Œ’xî›ý‹Çð9 _&:BhÅÌÀß;XP Yü™yø”‹‹YF€i¼Ô›’ e»ìßD÷i·ÌÀõıÞ ä! YCi€i¿üÀõ ’e–ûø–}?¯<8€ÃI%%’ó‹˜Y"ïd?·jUÓ î’d–z ÷–ýù> AYi´i!Ž"$”#…™œ#ú÷” =sksÆüÀ Ø>Þãd< Y"¢!Lßiie¸Ñ$".’…™½$ûÅ KoKhiÇ Ø]Ú#d˜0˜æúY$§ _li/hie_õ 1²é0,=q1ih»B®ð œP¿’›‚Y+0.,=$I0¾íðy1Ã/ƒ3[2½$”ÿ”vI hhwihhÑQ<µB ;q¡„9™ý™\ –”'ŸCBi0H &Ü1"_‘ƒ4qï3-9_…GÎ0Àíð 5-Þpí5¦½$4Ÿ04B:A"ÅAGVE-0/5x«Gr0ÂBó)BE_–¢™ïø™ .55C»Í0ih Çð¶üíð”A VöVŸe¢¢wG»‹¯D¼AÄ`ÐÞ&!%V÷ðXÞ§Cý˜ûX@;D9iÇñA"ÎByÔ@§@÷™/2ÿ‹pÿ>?>€<6·6(cð &!$¢úBP&Rª@/2=ÿTZ÷]ÿYYc$›À Õ"äþÑù<ÿ*((<X÷µ€YxóöÜrFà=öh½Ö1„ÒseB†Ÿ;8iÇÂàAK;;‚%pCû]pÿYm=? ÿ45Zkn@ AÒrÿe‹‹xõxëý]píàff#_b]%Jsm6ð5u‚5Òr…¯€°€ýø´ƒ^kbbûP´##<^Á[TÐÐÒrd á°€ÛpÿwwFhÿfe-]"ÿw[7%;;ÿ66$eøLÀX Íqõ)“v™e‘?±|kT®$0ud1bÒ 2dÀÅtQ ׃’±‚wý$»‚ =ÿ³s6 5]ö²-– YY¹l!1!(dÐ<íT“@ Íw r”ü’áƒmf÷v=¡ tzý DTTHõ&bV;‚ ]‹”øä’ÙrÅ0Chfÿ=o÷V]JÐ]ÿýVwuý¡V1 WÑ ÍqÒrãq¤¯€'sr?ffhf1\þã°)[lÿ;tkUó Ÿ#o1Uu+×¼ð 5ˆYø ä•'s5@÷fû+w±YY/z½zf (È V[T7Г Íq^£ýl¹­v< þ{  a_4×Т+ÀX ŸT# Ã’š°¯WT'¼ð ÐA;Ñ1¼¸¡ä“St;ï=z¡%}½~«#+-àmÿ÷TWu,*++677Ñ’› tp ¡se¸Q±¤³ >( $ÿbs{}j×ý]–ÀÛ0GX HÀF :¢Ÿ366ºàÏ ’?²5Ó¡rx£·l£XÿIfa]Ëe–À-¶iÐA -*…°+70À<‘í²¡ UÃE²¢´S¸‰ÁdîÄp$ýȰ^{7° T E²Û) Ìü~°VTÕ7°B6ð tp)ôTÓÒ…LÍYG·dfþlðXûVøûT¥ < ÿyYTUúð tQVöVd–LÅ¢¦`ßFýdÀîPmuZ±úYõÉ€*à Z¿[[T uà'›ûTõà ÍrçÂÿ…–”ø”üß‹x‹fD¿fdfdd2]ï] ;myû7ýXúV ZÑmZ§VTZ  &bïüŸV[Y1–PZ¿úUýZÝÀ‰Y¢çÃr”ÐîÅä’nÎ'ÀdfþÐ_9bÙÁ€À]Å€YY÷5vÂVVþÑVTøT :ð5‚‹Ù•Úï$CRÐü_ÿýb^s÷'B]Yî 4Fú[ïùT%!+ÍqçÃqBâ–Øïr@OÑfdöî€ýÙPjkþA]rùŸ*•8¶Æå[Z'á/UTøk u‚6ŒÓX‹“ãºîËä4A_À½R]ûY`œ;h k 2»ªL€ðR„ÍqvçÂe“ä÷”<п>dQÐ,¾Æ°mÂÁX¯ýXÉã .[T.W@"@ñуòçÂýåîÆ;Y×XÁ€ ¹áÿ 4YlXøXíËÁ6ËðTõí[tpTþŒÒe–ø–ýùYðx nmßwœ±±—€ùóX nÐÖ±Vý[§ü_Xàó%çòÿü–û”ù‹ÿ>\õ]þý±±!>{ wû[?èà6ÝÀÐAˆ0:Ÿ€?P(5˜£Œ!÷Xv…rrXVŠýÐÏÏÆÅÅÅÿ¼»»«©¨/„(Vzð÷• 9ò_ 5û"@jjkyq€êT}°ï VYlIeXVÿ…ÐöÐcý pddLjjÿtu|œ=«7TËðk‹ êãT0zn06**=*\…ÐõTÑ õC[8 &üX ÿy}¯m}Ùâ0*i€Ù Þñ>A<'á ¿V$%>OõñT>Ðbddûd[À]$%Xß uu€ñ_[û!¶p· duY rÿfïfgÿsWý^Ï ^,qàa<íž "bðñfÿmsssj(ý & ¶ds ,sÜ`%ß ß ;cbñfŸøf ejpjpm=<æødypQsß^^½øQÑPÑþÑflsøÿsZ$1ÿc€¾h¦u,ppµs\¨Ñþôsfdts÷sÿml*-ÿBhi€½¿d üdËauZÓ`:ÀbŽpèu!¨áÉpõssÿ4€ii¼÷d Ðü^*å`%z c^€u"ÿmsós[ÿ*nqe_µû‚ï0V‚Ï8cccz!€deü€9€mm,ÿ m[Vh€€i×€i¿{ˆ#‚ÏbcbbÄ€€cdûotšƒj3½®‚ùdE0F#‚"Æ€ò‚Å€eÑ€ü€Ìqms).·kUÅá„;#‚³Dó…Ž€mtþ†ÿm0Y€ÃÖH€úÐ$#‚böbMð.ÿ…Ý7 usÆ•5òAQ’lX‘.‘þŠ”;ii¹´H‘t’Q’ùd…“U<íh—‘ E‘Xª3Ñ4|—s†˜;_¿l ihe˜úÅ’4t“ ]b÷‡bÏÚ“šsÐ98•G€ö“3Ò|“øW’Ù“šr9hßihhi_ó–…4â\|“ ¢‡“‰‘j6O à‚€èæ^¡3«¥(2¿Aiiih° ¿e eeàÝ;]¢?ðøÿbmt÷tsu¡99ûh´à¦R eº u!$]¢Ó]¯Ðò„dÓ§s6¿8ihÀè§›%8ú¡ý¤l~¸ 4ýiÃè£:½¡#²]Z°XÐüZ±°ôtst÷T4°Åe {½ eX3ÑÏ/]ö³à6°õtët Û€ihÆæ·¡üeú‘$±X÷]÷D0botÏötÜÐ3õßh½e ²õ3Ñ"†³etòýtòad>?ÿ)5ïY|`e]  ² 4â?†³øµ°h²z =hf"ýð]'üX^ÿ# eýe]ƒà‡â†³°úß±(Àfh"ô]¿dv+öÿZTÇe2ÁÂ;̆³Ò ót7’OÀfXb!=Y›@ÿ7(;>;{ý6Ÿ‘$4`½LÀ3ekÂ$¶ÂiàøCÇ6ÿ<fhhfÿv±±ïuUÑŸÿ|jT;¾.ñ@Aoo|Mეl5$Ðÿf[_s{{eâ[PûXxò|WW ó®0 ·@­·¡e7ÀŒâ@âXd˜á³Ðå×(6À35ÑYYÿ.Vm +ó^£WTÝ(ûÁe8„â8XöX€þâñøƒ’9ñ%y}_× ñ›0Y ùXýAÐÿ ÷T{ÿ~+77¿gg"ëâm?ò^GôøÎÂÿ5cf$beåF1,’1f05þõý{ (*þ¸777<<¿ddó'ü?üä DZý". Zÿõ>ó$?òevoövü»Ò=ôq÷e_]A]b ÷ûY)Ë3  Zôñ$ð07<¾ÄPTU'ƒ'~.>X÷‘YvõvýúÓ{<½pý] bòýìÐYY ý[å a$ð ÿôT"J´aÍ‘ŽépÐîVà/f,Ðf/²l 'fá‹@X>XX[Á/M ÃasÃŽÉo4¥á8¡àï8b]² øYíX5`[÷[û&QZ®jÍ‘?òs^w•9%:L€ïfd°à çb ^±-°ek(e ÈÑG@0>Ñ?XVf¸v’µ4Žl}m°fÿdødýb¿_úY­ÀÿýYüXÞ¾@X[Ó1ZVÚ0U^ÀUZBÐTÿzÍ‘ ?òYvwÉÿ÷vtv6{7qûb F1ÿrœýX—üV`@W÷R ˆð ö‰lÉôvóo | ýp]bÿ]]² ÕûŒÑ¾[VÿTQ++Y%¦PÍßp"üs#wÐ6"fd·Xü¡  Ð]ÿ] ?4XXjžQÙ!þª VZ[ÿT0_˜Š Í‘”óÓewT0þ!ø0ýQbðb] Y]eowœ ±.A vŽÐ# jÓ1ÿü_Í ÍÍÞ _¢ÅÑVÿT <[O_UTR© d"Žïdvó0Rÿb] d{ ÿ¯± ß%¼2VVü[üZ2Í1ZÄ¢5¾@øB÷mЀþ³ÑaP\þ†±ý}ß P üt1“@[_Z;_j_kZ¢p «!Ã% eGBà´ÒveõVÐð<ÁP6ï “b[ ÿ]œm5 #(‡PÞÈà} J _[ûY >P+_j7«!&"eº2÷XemÈ@oeXYÿ©È¾¸©§£™ÿ–‹‹…rlXÿVY{j¿W*%|kí@jÿjlmmsu}œûI 7jjku© †à;GAÞRVXalP[XÿY¢ÈôÈÛ¾i¡bdà]&~A@ zz}l½![05a j#k,ð¢pR<Ðþ1žSTUUU‘à"PóÿÈ4ûbd°db[ÿ] Y)6÷œa û[ÿ<7ôT 'ssYA†à#ð`Sþ»ð;;XXï˜ÈövPŽo/d,Ðd Ä`ìW7ÐY$ sßo;7<Îð+6ï ·p>ü®Uu0;5>XY™ösS‹;4dù÷b®ÑY]4‰çøsY@ A%V×óV™`£sSi¿7dbÿðï59£@___ßZ*(íP ~·p Þ UïYWV<ÐTT<ÿ uyuuu"ÿT[su,ï±àðY¿V TV[ eÿ¶XZé ›áç¯ùXT< %ñ®’ÑVTgý€³A@î0€TTõÀTfþ逳XX;û6õ‚Tkï¬7X!XXß røü“ Ë6HÑl(‘_økTh週˜ry@nh’VVr‘²ô¦‰‘os–yYÜàÏûf‘ÿß¿Ëú˜‘¯¿**¹pVýsé€ÂûVûTth’%U #ñ$ðYÿy&ú×ñð•ê ÿgÿ ˆÄÿXV6÷# ¡ÀXíö WlP6%ŸÿÌ ö¹U'¡lP<%ƒ@ÿÙРöôUi€(æ ÿÔ ,VUÿòUTT*õX Ø XXWÿWUïUTåT/ Ù\£y ðUukP*o£ XX<£Üy P To¡‡ VV¤ x ¥¤ÿˆžXX‹ ¥¡ Tiðãûÿ-&ÿ-íVG Vº ¼¢x¡öª¡ÿíÿ!&09B÷Dc€²€€lû+—°¶Xç w¡¸¡UóÞà*î<À€ÿï€ikkÿZ êV¡ ö¡þ¡¿¤ŠpñtÀ:ÿi€ð€qþí@_%èV ö¢x¡e _0j±ß%mlp°ó€÷ líAkTÿ Dh€iÿ€i»V èY´_±y ÷àÝïcÐ7mp°õ€ó M°¥²[&ÿ÷i·W ú÷W¥¥<î °bÚ²lkÿøk*ÿ$€il_ÿµW ûWñ]²^²<£(ìÏ9³±²iißikökvÑ÷k[ÀÀYÇY†³/Æ;¢=ÀcBô°iùiÀPÁ*7ý5IÀ÷i¸W ÷W8¡0Ç’°=À?iõi ÂPÁÿ jU;i€ÂYbÉŲ:£¯ë>À:KÀhÑh÷ÀûÁNÃU¬°Xi7ÃWÖÀWWdÈ»£5Uÿ°|ÁcààöøÀhhÄssÆY n TѤÁ:£(ïÃ2ØþMÃ[+he¸LÑYQÒÝÄ:¤ýïÂBhöhºÁÆ*}Ðii¹"ÁÑWˆÑÜÆÓ*Ò÷hõ§× *ÿhhºY ü×YSÔ¤¡ÕŸÑ/¤ÓgÕ*ýÄëÐ#À½Ñ#áÜÇU<ò*Ò0Ð¥Ù,?h_¹Y ø ÑRTÐøúÑ' %ã¤Ó^tÕ%÷Á¾QáªñÐòô±ãA¤ÓeæŽÅ%ûÁƒá û·YRÒöWÈÁŸÑØÛ-ÝPâñÐý¦À¾Ö¹ ÂãäŸäÿU&hiÁY øY ×Ý6Ââb=ì#ü7ÑÓÀ ùY ÒØ%Âãmäfuæ úÀihÃÔÁñÐè½ÐZÕÂâAf[hh“óhhŸæêLѸEò#àdÄ ŸÑ ?føf”ðÃÆ~§ð ôYÓ¼-âföføS=?–QáEðú½ñø(ðìó=ÖRù]"^Pd@w»sj‚TV#Q #gYwäà$é€!‚dT%fþÛ"oÿ X]]Y-ïüXWVT+ÿ YÝðZpƒ=dwödè" &2ÓÞÜX¹a]Y÷*Vþ`kUýùV‘ 6‘.Ü6 ! z cÀ‚d!‚ÃÆ:ðÛ*ÿj7ý]wt  ’I¯Yp±ƒ Pecd"cTà$”ðÿa_]mç{~¶`~aÿTXXÿXwzzW<÷# E€úT*RP ]€?PtYqY5]#œbc 0bd íb=ÖZÚQWXÿ Xm÷TÿykYT§ý+ Yq$ #³bc1L0cbT$ýö~ Y]Xí püLe ¿ÝVspy~E€ëYþ" "9b÷öbè#ôf¯]e 6$:p¾†÷ ýTþâ {~{{ß_T+éP7<á¹Yq¾òbõì¢0ÃÆX/pYY,ÿûV *TUZÿZ[ZVVüTÍRP*x@;0•ò›#ƒ$Ÿ3²&+="bbµ1~a¿X põ TVx€YTûö/0_Tä€< yûYE€TU *@pï1œ 2Cçý…a_ýbÇù}a»0‰ Y¿ Z[bXýV-1WT;AjˆE0CŸ2dä±mâ´(©@%ý` 8Y] ü.ýV•dP ˆ`Q`O‘ÿVs_TTÊ×@‹B0Cž3eýmòEkk**öabjsS/`/p,PeqßT_¦‘T1ò„@ áàùW®…° ƒ õ<&ÿdf=bÜdP`bk òýÎê_YÛ búûa[À€OVFF Wšbþ±R&Ÿ2ÏdmmÂCAûd¿ü_ý]RÿøY>Yv®qX˜pVVßpõM,CÐ!V#ò‚lš)œR–E³le8ð$%dãboQÌ!]Yÿ*ùX÷ÿV ü[5øZ TvT1RçHQU>{áfdnauc¿nœ)cD× __ÂpWÿ7ÿ"666Vß17<êbœS8HU¼`ñD*$ý f³d¢pp] e0ß° ®qÝ)—°k¡€U_( ó(Z! ƒ# rqplóCóB_ $ôd€Xòpû]ÄQ)YX³l¯p1€Ð` ïTZµ/28pͱ@q&naHrù]V0vkT?ÿb]ñ]W2w’ßpïk_1q o ó ´@ Aqepèsœqþ`kôqä±ÿV¯±!<{ Æd 7=€ÿ[_WTR ¿óàs êt¼Rÿ`OU{à@µpÿ~'>$ c2!ae@€ÿ[[Z÷_ÿ÷¿ü#%­€éžôa]ö]üd9‚kßm*>epÿš  ½yRVVØRZÛ;ýl€U±ûZîý°žR]õↀlƒORw bß d[ Ì€3ß6<ùX.PXYet• *Ñaþ@ 5,_kÿª ûª _««®«®“ǃÑ&ƒƒîBöpjÿ`TÿLZ{}}ujÿU*%*tw|œ[Ð`VT ˜‘˜FÿY8X8ü[‰X{€¥¢ 7!"0oR/w> ¾¹¹¿¥³eËÀ™ddÊpïý]U¯‚YT8ÿsu ÂÀ!6"7"pR¿P™¾úB°¹ÿ£q>0~}6!8 ¿54T‘[ÿ#4ß îp¡;YÞÙñ]d£B±¾½þF°¹¹qΘ{v@µ ýX½€05"¯‚_ß[!s°ÞÒ°XY²lo©¹½½Š°½¹Œ°ÿd1lßkF]„2hhihlýÕ¯d0Á8ÐSJ1&iŒ0Š0ø¿1ÎÔ‘[~º1ÂV üìиª55`KDŒ0ãøhT0Û#Ò*÷õh?P¶V èl3ÝP|2h£õ÷0T#Ó‘€hѽAëÐp î:h¿öh g¦_>á!9hÇÙ1ëÐ$–îð û#PB ¤Ô‘þÔ%J>?þÞp~(VÑkDJB'Býj¿ý_üj^o÷ýXlÑZŸ$ V¡C¢IC@}C‡‘Ù#T/Àh÷h!1‚#dvýqÀ83ÓVÜ1puB |'C+%j_$ ÿ!vZ;Y¿ z[7P ¼üá„PFVU‹î-PF,$Ï0ÿh hfÿ\…±ÿ%Y Ÿ|j{T5Á<Cã÷T<=p*(7`QR–m"DâEÊ2þF*#hfdÿ_ =±ë²€îY]}/8À*[ Vã÷ )À[o 8a­SÉ\R&EèÙ#+ Hü'ðhf0~Àp>!Náò@—Q¤Ò!WT™(Л@5Àpà[SODV1X3â hÿfffhf1ýY[7#5ÿzuîä0W`e¶RObh}c€`hèCzˆ‘%µ`-ha? X™ î ý0X[ um÷Uà!_ÿuWT \ÏA d È!¿2ø~`aÆe_j ý½af'šj ÿûYÿ|zutjTç%üàáGVýXaTUTïüq=föfÔø3T#TäpfxP[_þ¶`m)úî¡#÷Ð uz ¿ <*ä þ_  %(*+{+ï°VXaô_ _r*esfõèopˆµ`!f)Ïm ãR“r~@ 6ýí°VTukM`¯*+pXawUTU€Tôûšfr"lr dúÏ1õÿft{} ù¿YYàÿ þüâTT{{ÿ**67—VXa € óÀ'J»PltiV@df$be àbÿY+ûXýTÿ< ~{{{jT<<`†½rW€}‚œð_|bÒrljø»@ÿ>]b þ\²^7¿YT 8ÀÞ~ÀZTVùP"û7Tp VV“WW}}‚öß‚/ÿføfdf¼6…à"!üfõþì¡XX ïZX`VVëWKPJÀ ¿< uY ÿýUT OTTWW‚÷’"Îßbˆ~"%û!Cffe_ïý]'àð [Ÿ[ýXVàa~øpTWY JÀíÄ€û‡‘ L+ЀWTЀ0’%Þ‚Gd¼‘C ¡j016_" ¡$ßP\±ÿXZó[…á@XXÿ[ZVTTsÿjTTys.Tñ‘&’'ú/“ “9fdøOd f•„ïB>ù@ïbls /³YÏo~( AAà<ó ô±cðVT1ú U‰‘Z¢Ð*‘|õ÷¢‘cd£öd#VÝ ¾dÿa_ 8b¿ý]b9°kÿ Y]]tsÁ àjYÁ@î8À û[þHTçëE2Ï¡"dÿõdûjìÝÏ0  fdÿbýbÿZs( ]YÏXY…àBV¿û[÷T%_`!÷To6}î?db .…±bdeìƒ+ç¡Cÿûbk}¡Yr2`{X8À_Z ß<$î0Tu ­á%΢bƒ°ùbÙ³¤ödùª€û¡ ý]ÿrœ_> ±XX' ¥3 ÐöÌøk°6ú [q±óàµòè0ϲ¡/×²Š°Ý³î€â { ë ÷dÑç]b ípá`²õ ®²÷Ðý[S¿<ö<Œ<õ<|ô{²\b×öbT0kiU%ÿ&fdýXûAb] ýYß Q »sj‡â[Y _VZó¶€_Àÿ66++6tÝÂäÀ7éÂ<7{²k¦5úAþ®À]]¯±ëâ𚥠ÿ[[[ý_ýƒp*ÿ*%(ó(ü-*F1ôP8ùÆîÿT5"b]ÿ ±±ß  ‡äV<ÿ[WS$ÿ$¿÷úŽžîbõWÀë„ÿ6õ]š~eÒ% YvàÞ@ý[5ƒp¿  ÎÔ *ÖÒÜБÔ"Â5‚ü–ÃÏ04X/ÿîXü[ýð;j_kZÿ))?øö(ð€ên!?Í+/bÿ]šm5ý 0VX} ÷(+Ð__Y o*"Õðñнî‘T(tàÿô«î™Òö»@~ó@bd{}î`ÿ(*}œç¯œÀÐ#€+j¯k<½pZem¿w   <²ÿ³´l* ¿  ' Ç‘ÿo  Ý<¢Vð‘P5íY:«p+ÿ ?ÿ*Uky~ýdÐZ=÷(X¯± œ¯ÝCXV‹p üß[>)FŸ àÐÿ@eöXñÈYXZm| ¯þ`y °@TVÓÁ}.‚ )y ÿ|[[ÿal<ï%ý¿ÐT þZà$%%3zDq'}~dÐßV[ þ™aV% __k÷uuy<0uy'÷[j+D™{}ÿVXeWWVýT=1ûZ#ŸðT[ÿsuzw[6(ÿ¸Z|œjZYV ™cîÐ@9 `àµþ °Zo%ýV÷ýVàeï®VX ¸F`AHSTf¦0³¶•püg VÂ1´þªð6+ é6£rIPis0¬<¯XüXØA/2TÛTk¦0°k‘V÷6IP;vÂ0°;bXòSŽ@­ à €nÿª÷ýX”@+TKùè2®Ð’΀•`àh@¯ ÀÿyYqÿÿ¿­ ‘þ@±6VúTýohA#*5ö¢pTu@µWWÛ º4Tv@³Ÿ(UWâ2tÐYïZT(œ@¼_úñÐE¬Ê@ÿ e׈À@©ÿÿÓ~©9bX%àÐóÿÖ«© =bõbª 7RÙ²©QPTÜWùA$QbE {<Rß7WÿbT <(ïÿâà >MT Ë0\QP™ådP© lSP Zɱ}Qß ‡UôŽUE ð P  ÿ  ÛµDùÛ@?ìÞ?Q úv°7û!î  "0ï@D€ïP(oci¸ÒúÛ@™ ÏPT ÛPÉp"þgQ&:Bÿcöq_ý€»û c'S÷#!³` c„òS`U`#al_Uÿ & ïii€i/` ü|n `÷]T·"©Ta–$`€yp(÷ ka¼Àðýn  y`±e÷ #ß[soli$`q”ðû[li€€ii¯e_ÅP dPê­aõ}`XS$þ¿a_s[YŸõl’ñb`wü€¿0a À¹YzcØU%¿a oks[€"b €’òþ›`€iÁŸ X¬€¯ îa('ß kmp ÎaÏaøà]õøPX ·)¡ïø] ɱ'ú©jp÷ €q r”ðc‘uJpÿÂY ûY¢÷  päV'M`m:ïQîQ€i¥tü@€}s ie¸ÿYYYip­¬äS &8«DÚs€ €qt_ö=àhôqX ŠÂY÷„rØPɱ&Óq Úr! €ú¤ußàhi¹?⬭ÿs3]] e&€…þãxiie¹ÿX âYiö¸S%L‚íP€ø€ e&†ÿühºâââiÄv…S>L‚€õ΀¤u¿Öâ â€àq]Âéƒðd%,±&€ö€ ãvÿ"i÷ihZеâ ?âÍXoÐvƒîðd%M`ct4’І*øhhÀ‘‡â­Yç…&xl¼4”—ùhï ¹ââAh: ç‚S(-’0 ø˜ì‘¥tZùûh¼ßâ„X§ùX¯°Sl’pr—‚ê’z—ØÖ ¿ÖbXõXŽr+$‹æ˜i™`’òï…ihÄÿÍ ÍXú<¤ D¢:iõ¯iù_GÂJÆÿ ÂXáô=£÷`n‘öPöi¾—(8e Å?:¡$q• ɰG0#ô€¢ þW¥ A=?ûßá5ýQ¶ )¿„ „:¦%*D£9Q£ie hãuƒ¯>÷]ÐXþE@[# §d RÐ:¦¡¢Xj€!²"°hhÑ…%Ž ÿb]ö]^ÿvûX )Õ<´3EÐ3pó=£Õ¢`°$²i°ùh¥té ffeÿ!tZ'w[ÿ >;;6y ƒ2DX—µ…  ³=i°®²i¸ƒÿffÿv±*kTwX%Y ÿ;À7<ñ<÷)!á. ã41Ñ…(,úð"ò}a]±±Ÿû Ç0r†` ökÏa×ý_;1ô7+ú$0 (344¾W§! ˜!ÿ𠝱ÿ Tý j_"ôÿT V øVç<ÿÐÓ3666Ý7Ý2É9d÷õd„¥>~ º`@-ÏÁVË3%ê@(C*!C>Åábdöƒ ;7ÿ@ýÊ]0@¼0 0 ÿ-_j_ZÏT¼B‹°;ên@rBxA##%—Éë2}Ñ ÿb[  ÿ]œm+¯©a?>?Þ°cX"Éb¯õbú kabovšš~qa úPûb ]Y ÷59 [[$ÿ+T0 8ÚÉ8ÀbZ$adbÿqœœœš~~}ÿW õb_ {{ ¨QëY®6`8Åâ\býöÿ`XTUZZdßbiœ rY÷ _cv~» ¨ó]Y#¯ðÿ)û[ô{T*` )qûüc>(Ybsbe>p‰pœštp¿ôb {TÕÐ]û5 #5$__>mT&tÿ bôb{X?…pŸ±± ‰q»}’@n ÖП¾ù@)L`Ð(ÍZi’}ZŸ°ðÿaellm$XýX@TD[a<ï#rpPï >À|5ÿssýVX[ZWXVùšà›à%[_ÿmuyuy¯67`(ó`™ÿy}yj#UãWYW mRÀ[s¿ýuýyŸ #tuzwa6 û±®Pšj ÏWV ±• ÿ*¸m%s Ñ›àeO óˈ°eBýTgO³OñŽ á0é fAâfO Ç7ó+ÞpVTi¬7XgÀßX úÁThês °$‚ëàT»6Œ °ü3Á+Z¢kO ¯þ ñ×%Æ nO ª¯>#V=À»77pTTos ¯yýj ïúTjO _±úVbðVê¡ï¯>‹°¿ÿ¿Ë@s~Ú¡**Æ!}us µUW  ¾žÑ;%rs¡ß%U YÔ´V÷)I°»jÿsjZT*zÿ†úñ댵u†° »dtˆ¸%°÷ˆ¹%°ˆºöO  íÆáÿâ÷ ¶°Bhÿ?ÿåý ¶° Biibÿ7+ÿçû ¶° AiiûiYð7ÿ©éo€¶°é°hì°<þï±<% ÿë{¶°@hÀóiTð°Á<( w1Ú, µŸ ¶°9ŠóåPEÄÿ<((ñþcP"&&&³Ï›¹P<ÅfØÝ0EÁ#Â<*Ø@ïÿ -:·DhÁiÔ° ?h€€ë°±°k ¶°<Åhd}Àä}ÀHÄ<à‚Aÿ&@D€öÿl7¯ &  Á»ó`Æ©Êhb|Á»Ã»Á*ým€c„„»ÖÀ€j¡P€ý€½rpu¶²:{ÐhÀ°ÿÄÝ2Í€m€-ÐúÑi3Q ý€[a_3À ,Õ÷5ÐùX·Å@Ñ<<ý÷ Ðumehø€€ÁÐþô0m[VhÄj…`¶²/#òVAѼyÒ?Ò øÃ°UskU?‘Ðï €€!áÿ<5€i¶°áìñ>ĸÓ}ÒÝ0 !ÆÐ_ ss[<ÐÔ€WÐîúñ ôi£°î îÑëó²ÂFÄ·Òî%À"ÆÐ(ukZÂÖЕÒÈÌô…À!2â[òÒ¹båä#B l]ã§ãÙÑŠÚ­Æ…`ð-Ñ&}"þ·]<÷<îÁ*$ÆÐuáq£ã¦ââœñiÍiª°TÀÂâòfp6Ð ÂAÓð°%#m€Ç7…_ådåûðýUhª° ñÄàñ ð(´ÒIãûÁó£è­äýõ_lhiëhe<òò[`"ddæñyÓvÅ"úZa`àø€ ^ðã_Í»áóÓ°vŠñdˆf÷óôŠäÁ ¢ò@€_ö€gšRTý°gih¼=ñÉ%!41C¬Â½Ù$wÔÝ37Oá¦mhèó®ãİ-Ïiiøô²&Ö¬æÙ#Ù úÂuÇL& ±èò°õ İ_AiiòÀ¾»áöm€ !Q¬ÖÖ.‹@dØ ]õ·Ã=*áó9€÷®ñîóUç°ihÀæÑ†Ð ùØa¢Ö„d÷dffôŒãñ¢(-§ãë°i6#%_ ýiÁ›ÆÐ5 âbæÓfë2³ÑæXòu±ô­ `Ášà+ÖÆØa¦‘ðFÆAÑ 0Nq:Yê@À}ÅæÑú*qƒÔÂ(QŽS#PxÔg û!JÑc€i¯÷i6#(Ô°iþ¢Ñû+:)QvÖÔ¥øRúPhÒ‹ï±v"þ[9ihþºàü,] &ÕÖõU'Q]4ú»Ä5"0Xñ}ûñ38>?) ÿ ÿQ 76ï6)` ý[+Æ„ôV!P8ÒµÓ$Áý*çbiö~ó*6ýbPû |‘XX;´  †ÀÄ*Ô¡hÀbsÐEäºÃ%5"íö" h˜34}_ ]M )E±¾ï-[T1;ÖÔÍ»r³Ò¹Ô ÁE5#&@%}ððäøàÿhf/ÿz_7ý6þ˜£TD \y:ÔÁ»qƒ·Ñ7 ñD§3¬1íh1õñÑfÿXb…±?¹Â@‚ U±äP ÿ5!\ÿ\]b]Öø¿ÖÔÔª‡3T\uÓÿÅ N §4:h-S@pÀÿ=³¿ Y+õ¢Vÿ@[o]ßý]HCýÔ÷˜»rù< ÂEåhC£3òÃðæ þpÀf vý¿]Z+uzusý@÷TV$]P6T]]G@”%6PŠücY¸Ã¶ÖÂhB×° BòÁ1ó7ÿûf=ÿý] >û#’‘ zu þ½3]÷GA÷ÖüB²@i/3*PzÃ,S*hBñn@nÒõÙ"oÁËà2!p2ÿ<umUýl±Us{ÿWT%]‹]Vч3tÒä&<ý#hB!hõhÇú_xp¦ÀåAf'ÿœj7ý]ÿ|zzÿzZ%ôƒ¡k±5Q­¿­ÁÅÓd#Õ‚QÅE@Mq:˜õð°ÒcA®ÒõTİ fÿõf+YYÿXXuÿzzUT#¬5b6@TÚP!`ÿ] ü]*_diˆ¬H`ÍOAÉ]]1Ò$TtøÅŶq bõ;!þÌá"]ey}~û !p]Y86s¡ï5+·Ðþ Qó]!dƒiiÉ`XaÏd}Ó)% Úåc®Ò f‚õÿfy} ùYû)ãq ýU°üT{ÿ{+7]?è]ü'Px 4´ûÃÇÂ9Rs1óþ¬ff+]·]Y,ãƒT²2ÿü7›€YX k›@¡÷XV$[_WTåQޱ,g ¶X ^²ì –acµ#¹¢ÓDÀ²õ+‰ dßödÍc]]ç;–€ì¡mYYX‘þ”ý[_[/а"Öu0RÑý:›²YõY]TUÒá7 ¶¹¢‰a{E$ü§A]¤Y]  Ï4ì  0Üy x¢ñ°_[ÿZ TZ)õ[oÔƒQ Ó€ÄYô‹ÀüЮ³…’¤qÄà··ð#ÿî] ±ÿYXµ”#€ ükÀYûT pP[[2ÔêÂDñÄŸ úÁ9’T )ÅÇà« dˤ<œàb]0*X y¤ÿV<û[ýÿ_ù_ÆÆÏψSÕ}%ˆÂX7òÑp©rÒ‡a÷}Ñd®U#ý0qœÏ ‘›@þ%üZ ÿ#¢ ¢£Û¢ SÕ=¿Öó7¿+=¡"ðzãÄðK¥‡8  ÿðXýV%ÿ ._kZÿeel5& j°ì¡ ÃV¿+6+7öÑp(Æ ÒA §— Uÿ"]5V÷X ÃpYeo}û ý¡_[YTSÿ* *+faâlå Â>+và4váó%rÒ 4æÐü{Cbd@%*_ œ$#€Ópÿ_k ß+SÕ>¸háiá ÁX;*1ñ+6ñE*ãü`ÐÔ¯ t ½p<ÿ+kmsÛ„ [@ ½PñÄ$üj° 0øX5?#%%%(šð2ò *â=Åðí—!µpût![Gûkvjõ6+'аÿ U UUïT7±Xýò‘ñ;•óçb6ù ÚÀù ü!|[X=û > ð~o;÷nðUTýÿ7+*kÿs6 6ÿü6 {íñ ¤qõ6 $bb6Ÿ /s!!éûù`‚‹Ð û#œð%$¾Þ@7+Ópÿøs ÿ ŽòYYZZýZÛð<7+*(פqÜZÙZpðÎ|~Kj¿ WZÁQ÷øYQnðVTý€°*s"ÿüÞ°mtotomþålj[6Æ= "MóÏd¤^bïdx~­/i]±ÃPö£ƒ¡¿[=kT0ýy$(*ÿ6Ò v_!t†¿]nœPà5YñY(2Ð÷XÞ@_7uky. DŸ04†Þˆ1 …  £!}?–`ÆÁ_ yõ@ PàåmÀXö€Ð!bÿób dx±=±à"%  à!ï6ŒñõXï lrñVÝüÐ[Üà¿{u. Eîÿ0?$R d—÷²²²16ϲ %ñ%ð·rõ@"ñ°[Ÿ[Y8{|°ƒ åFV1 [0]` q¤½³d0²±±<µ ÿ? ± T Ÿ(+ò^Àÿ¯~šà) „1»_U=`UU Hí÷> '3sdq•xd0£2ˆÑýÂÑÿY^m| ÿ¯| nÃrVîQ$ Fн.Óp *ƒ ÿLù%Zlmu} ¤1ÿ²Ÿ%0aa÷#T‰ñVXýújP_( ÷ PûöÀ%_u¶p D@oè0z5{~›@ßZZYVÂpTVß% uy—@u ÿ +7TTUZ[¿_jmtu(f@Wï %[q@|Z»Dàzjt ÇWYÕÀš‘ ÿ% û[6«@Y ÿ Zœý_/`YV TV¿Teµ¶šà¥aVýAÿ®V  ³ 6bÎBTjPµ{X‡<7™’þ‰ gµ6ÿ++üTë(i@P¬<6Ä@V‰ÐVT@‰ õýB°›€VVý;‰ mÿ¿¿¯úV‹±}“‘> 6¢@~™’l°¢¼‡Rú ûTk¯+#uôëi¸f@V2:iÿöi€X7ú{ã.EpsÇúTpV2/iôióÂ`{á%'ÿrû€h«i¹f@ûuó€T÷7÷|à3¯g_ý ÿ&hhihi÷òáph4°{á&ÿ €€÷€ÿjl hhºp•0"Ù“F€}ƒ÷f7{á&ÿ!€!ih¼úf@ •0h÷§hH€H€d8s >€€ iFk€û ›hóh½º]7øÉÒ0¿i€ühÚ` í •0àhŠhÇôh=ÐÃvÜ€i¯BiÅÏ CaÆíÄòƒÅÐgq*«F»€Àf@ •0 [cîЮòƒV!“·%+Ý€ù•‚¼TbÀ¡ŠÐШòƒTþæs+ý€šG€h¬p ßa^fÖb‘Иò:q{)piiF»5Á¶f@ö)q bàŠÐÔÐåÐñ€õõ€dt &½»riõh$p ía \?°ˆÑÒºŽ„Ä høõ€bc7/³Þ€8G€v •0Dë‘‹ÏÒð‘ií€@°B£]þ“u&õiA>>ÿc<6uf@•0B?°7„ÍÔÂÐÆA³Ã¡øÄ ø„~/heï[Ó±]]#y %ði±X;SPÛ±q?V§Ð®îÀ²hf –.ýhû<Õ°b]J÷‘@TTû#<Ð`ZTÕa†á„ÆûÔÔð‘ШfôÕfˆ.h€y =ÿ=Y w_ß;666<À$©@9QE‘0•0k=çàƒì ÔÐð‘Ù˜õ£,†*»‚hýb¢\bÿv±*jTÏüVeQfP$Û*Tá0 æ0e=6ài7±!¢ÐŽõ£æQ†( §{‘l_þY³ ²² ÷]/òP8(T"ÎbâÚˆ°Å{Á¥¢ãЄ¢Âý†‚'ö¥’a  wû  >U$ú aP">Ðy°6L`7@K!×´Æî£id«¢ý®„&þ¨±húf&Xû]¹>y[7' PïVTG`ú "%Ê¥¢ÆMñHñ‹Âø€î:q$¥’ühë2ý*P;¿Zu áTVÿTUu{UT%)±j@#ƒyÆï¢¡®LôIóåpgqípiÿ_hf-Yû]À]Y+Vÿ[zz|z (ÿúVüT¸ÅÀñL`üD`ý$¼ðiÁÔýÔ¿úШ<¹fñÀ.‚*@° hÿf#s{~}ï üY °û P|W_ _uu ATÐÿ(y%ÿ6<ý6ãð&üfÁ{Äݳ?Иdôd*G”û?k #beÌÁk X4´ô Vmßuu eÃ?WTôTʱÑe"®šÕ³Ðީյq±_Ð3ú¹/t  ü80|Ð{~~{**û7}±ù(òî2hqˆŠ˜¥ª®ÄÆÏß²Ôñö ¯ ýXÅÀ6<¼ÀÐÁeðí2í2 ä()ýî¬Ða_Ü%÷]ÿ^{œ=˜ & YÊ VAû†0[[ZÿZUU1Ð õÐÅͱã$’¡3<7ÞÖ'íÂ>š .bK0 ý ñÇüÇÿ ÈÏÈÈÈÉ7Æ€±8õ¡ü¶1Ó„#üf¿e_d—0 _]36\D((*üP¹Dcdµ Í0jp ÿâbÿd[Xýû]1ÔÐ}m;ß!_WïT<`++*ÿ*ûs +÷  ž@  ®`VB±@óþ_@>#%%(îR+*Ø dF  &À]á•Г0÷<áÿ%*%#þL26ks+ÿ +*(%Ï %ΰü@}QXëƒSM[_Ÿo}ð®áŸ]]U ºÏ7 ÿ@a<7û+%XþY]ö]ÿ ½çP&]à^NN0_+àÿ#%ðë-ü²YÀ%1?( (ý@@hA+#8>¤„ þ-b= ÷4a$_ýbZḿt}} `Zv†ñ ÏP+sɰ? 17`æP%5w`Pb´2ÿ]]X6*%]Šc"òdd°ÿZb db ÷Z[Y£P}T ¿øY-ýX =@ »)w mTÉÀý$Ã`%4;áV*bÿà¤@ZU7ý+ç` :dû¡R4+ÿkôž° Z}JNßðýŽA_ ï ûy?`%ÿ #(ß6TU[jŸp×:]à.Ü}Y£&ñV”0ß ;KlÀ0¿ M¯û 4 ¯ 6ýY%ðï%üXZa_Z ¾òð .ÉÀPÿ>b± }ð—²± øÀ¿ ' £{o¼° V!ì0pY!` ûp+Þ}°d <}°]÷dxâAýY¼Ðbò }‚Ÿ* ”1À ÿ 6T)ý!pR&] çû²øÀ%Pe!ý~ë ZmG"~0TV$ =@½1?ð (äqS%&}@ï[al!Ž1åVÿ ý[%5þVZ{~rÿ|5}~XZZWßðû¾ÀVT% ÷yuyYuu! {UU¤@jmsuðPÿ›yj#ZÿWWV ûV~`ZsWþ Z&suzw{a6ðP±%#໚_‘ðV æñTÿT 7,ïµ!àôVéN‘íðf´½ÎÒPNúTl`¡o<* Ëú^¡ÿ¯*ùTíqÝÁ"³VTï;%rݹýZëá0yÝ»jÿsjZ|Mðª@úñsP4ߪ@u ÊÀ_"0ˆ * ï'ˆ¡* &ˆý¢´%ì Jý¶Ýý$ì -‰‰\ ¿ÿý#ì ÿ‡‰‰]+ÿ<c€õ¾´"ì  ‰ÿ‰‰X77A€€i€iº–=!ì  ‰°-°÷7Jp„_€€6°¼? } ì  h‰‡i°ýTjA%ï¯øi·? ì ›ci±‡‡UPj@(ÿ&€€e¯ý€À? ì ëD†³„jC7*ÿUsk ýë€Ó–ì Aö†³‡°´7*ß<T± ×sjÆ–ì  í:Í´‡iC"·ü€Ô–ëÍ 0Ú¬±„­°‡hCÿÙMÀ -Â:ÂfCý P€iiõ¹å€À„¿÷„dEŠ)ÀÍ0¹ÐPÃì Å[Àö_Àºàz1 ïýmài_hhg_¸f€}Á€„õ_À“z1µ ûpU° uÀhö9° }Á h„áô_À% z1Þ°õ€¦üÀ›ÀÅÂ}ÁÍc\Â:À×Äû!6°lhiih<µ-À飳:ÄþÁ„ùË z1 üi«ÃÀ¿–ì  AþÀ1Ñ1ÑZÑŒ³:ÂA=ÑýhãÀEÑû}Á9ðw aÖ(3³ÕBÑÁf€À0ö‚Ò€C% ýi6°€iiij_³ÑÒ À=-Zјô¬ÐÄý#Jpi€g_÷ ÃÀ÷hÛa¹÷  .À€×Ñ·ÛÓÄo4²itеÅf€À  áŽó¾©ÛÓ@Äôÿiöh½ ÝÀ h2Њ¼ÿ¾¦÷ü à‰Ä€iÿH48>?>{ÿ (ºRÀ Àc_Ḿ¾¥ á à—°õ€‰Ä!ie?Zýb%m€ôß  ®Àb—°ˆšà¾á˜ŸàU°ää±Ä õÐ=ã$dr³v)« G€<$b o 1ÁBäàû„»Û྘€ôüâÀ×Ä üh®Èð."–@;Âp%ý;Ð; $ýVFP€] ÀAñ· ñû¾Ž%úýhûáf\ÿ/±|kT®F2<—¢ßÿ 5T Ý À9ñ©¿bfòŠ%ó5Ô«qiqÑoa_*feVÿ =±²<ÏVV˜¡  ç)T‹à꺰0/äᦾ¿¶ò„ˆ%óÖz1³PÂÁ6ðhh!v Ûaÿ-üVtzë  #˜@  kÙ€("äá‹¥¾¶ó¸ããºÐ4±€¼aÖŽPøhtÀfÿ o ÿýYz_7ïÐqw×u ë‘"˜@ ð»h5°¢ ¶ò¶f¿Ð5±¾ÐCù(¹°Ðúf.ò)¸Ðt_mýV« ˜@Ù ó€K &Ði˜Ûà¶ó©Ì¼ÓüÐ°Õ h_øÿf#_7 %]û]1YY+Xÿ[wut}7ê’TT ÷TL°Û ޾ÿ÷¾¦i{ôiCæ2Øðÿhf!t{ ¾6s>YÌqXÿwzzW<#ç<í‘ 6+m<Špj c¿Ð/оöw¢{bÄÿ/fh$ÿ]e]YwY4“ XÐpÿVXmwusÏ[+ é’1üo+<úñÑÑ+DÈõw˜{‰Äÿ0õf{¿} ü]-~€Xÿa6÷ N’VTgy~ ŠpÀ7B¿Ð„¼fò¶óý¾,+/ôf)ž–XXK Ž0Xë¡V < ß~~Q67Õ §ðÀ1@q!Úáy&¾{±Äôh4¹0ûs IZÿ7YýYþ»ƒ *TUZZÿ[ùT+67uÙ€À%:Љƒòx'ŠÈÑÐhÝi×Ä 98ðþ¾0]e øYÿXY ZXv5¢V\ /6j@gä3í›3E2¿ƒ„„……Š^@‹OAhórÐ  ïhAhfïýf^0 'þ5r65 YŸX>ýV)ð4@[{Yµ TU#0çî~Á@Ýhm aÙ2´0dÓðïû] 1Y»]v!5C VûXÆVTûwúZÄ ï¦Á_chÜh†Ø*€þðffúdßb]^0 šÔcž}3@´Ç‚ N§ðð%° ÉbSCöÐãrÐEä(ÿhföfûÂÐdfü_0Fk Í;Øa(`Âà%_úV ÇZCTÿñDþêÀм¶œyusV·Ptt¸QoÁQnCþEä%hfûd´0]bæ#B ŽQÃàX) üXüVvpÿYTQò¦c°?êÀt#©´PŸôuoC‰Äÿ,fd*ûÛ]'€ýÝ0köo0ùš@ ý—[ïA-çм`ÿó9h÷fhi25¾©•u?öumyCd`ô~a‰ÄjÀa_)Ð^0-€þqÀ êp b°b°…ÿnœXÿY?8 ^}¿üX÷V€UÿT ÿuybÏúbÛ‘ÛY;ó(%mÃGÐ# &\C¡D¡ïİÿ=  ý ð4bñbo}@rqý&ç@XV õa [ê°6,ÿ{{eü½e-¡bbVÇ‘*ÿ(# È& Ü‘,¢+ÂD¢bV¿6%8 ÿ \b ý ÿ6 Yý )AYX#ë  p±_[ZÿX% C%+óZkÙd·Q_ZU<îÇ’%q>eÀÃÓ˜´Ü‘—ÃܹÀ+ÿ ?bö8`—À—²±¯ß üX”@X!ý rXV[[ÿ# o6$€°5¢ÑsÙeskPbÿ%#7é['æHãmOãkk_öî@+CÁ¯<÷?]0bexï)XŒTXX/°çð"M`ß0½,øð(u€Ç àpÀ5pÿ ÿ 7_kÿssuðuýsVá[ '] ³²÷è€de ò ¤aß  |s0ê{V>Á )Ê€ç +šá‰À ¾£ã%((í¢ÿ % ¤ß%•˜ea œ<TH!¾ pTV Áp&ÿ#%$íe”ù{ý~¨p[ZYXŸûV Ç€Ù`yücðcð77÷tu(áÀÂYVYW ³ eñW€_ %3Mл¤@þ˜@V7ÿ,¸·o%3ð²j?®þÐw0}l¦ðµXlðs [ìòTf¸ðëÇð "VTiþMЬ7XX½r@ÒóTëTh¸ð²0@Våø±€IÀTn·²çA%Цð­ÿÍp‡‡%#Þ|qЀ€oih -Ípÿh‡÷‡û ]Æ’6+ »C € `ß_lU@heë_¸,O!c‡ËöX X!é ¯!…G ¼ÚMÐ+O!DU" „s‡XèÊóEðý*¨":‡ø‡„„‡„CÐÆ’@ÿý€ühe¶XàTÏ) pý&Ë"„‡‡„„üõ€"€€iAiš0(³‘ý!ÿ ÿ ¨,2´Ñ 6í g¿_ýiú\Pjí_õ' pþ+1‡„÷„ y/8+ÿQ ´lÀáÀ" p-ø2¶-™,4„@ Åñ¢ûZøqXXb$vßÁ ! p @ÿ޶µ™„õÏ f¹1Ìÿij4hý-•`b]"^vÿvjY"  «)<½pFú@ Aý€‡B¶¶˜ôÈ’@ ·"n0WPßff/`(;÷ü6V$c×ñÒñÀ` pW h†@Š¡ŽÑFîg2G ÷hça\ÿYX¤|›¹r<æòéð¾W€5!¿@. p D@ ˆ¢Tý]52++ |É00hl_ãaÿd_=ÿdw¯³ YŸ-ýX„(Oao_QmB@ „¤€¡¶sTgC|þ1üfwý ²>#vãàøˆ°UT#¿@Íp9¿Q €¡ŠB €Xyz.÷ýh1°YYß#+ðïzu ÓôY¿T  òàÖ p%/¿Q¢ cµˆXbAbAC €Ž#+b ñ4Pä@žphf÷ XE;Uuwum3ð|€÷R òà­ p&!bA˜ c¶±µa@i!h"€€¶% ¾Ðih iŠfÿh*š_ ûYÿ+azuuË …5àH@Ž p€@ ÌAÄR©~Ðõ€ Vyöò+‘Pf!m{~}) (b÷Y)ü|àwu÷ à"%yû~y¢a%6ë<Ép@h>Ð޶ø¶‹€'Ñôpõ€"hfÿ$bey}më S¢#ýXÿVm 6ýVúTE`_67¿@aqûcÐж÷¶?¤€óvr/Aý6Ü f_EùÿY,Va  ó<`éò-(*F´PAgUÃr£Éuþb+2da]eu{ waY­ Wðáj€5|ðÞÔñ{~ °To++7àAëAC „ƒµ™ô ‡èÅàfhMÿ]]÷PÝFRXV†à_ý_?jTTû™  ZUZ]paqhC ˜u’X0|“•Af1 AJ0ü’( ddýb û/°m~o+5á€J’oV< ³ YVUP×lZ;,°aq cz0u’e:|“édr A‘ýfíD$±YÏtvàuà5ýâý[ß!UZà î­`b hŠ‹Ÿ‹‹Š‹Š¡‘¡@c:c|“×Bñ¢(“‘ïd ]©A]]^÷s&ˆÑúV ¿[_øTHP>{ÁBiÝ¥£Æß 5Phf÷$”’ù]?__"j -ñï&ü[w 6}}¡$àí{Á9Þ¢ h]üà3ð õff¿d÷d½¢]ç] èQ“pnœÚ…Óãà*Ð[~†°Nô±±iÞiïZ%Yý „pôdýb÷ ;¿ Y]² üYü6`¯kâóz à/!°Z[´PÛ x°!™1xÿo÷o!ro[orß°oo¾„iw ú0Yr66>ïXbjàYs]/à©‘V)Ъ³3İ¿@ ̰ ùî±¶`¤}uöuüi(Á…Tcþ!?b]ï]ÿxœ ±ùçX GRJ’ Þ•ÒZTÀá[2:(  ̰cÒ± r§}uòuF0Ê0øƒ°`m‚þ§de)"]ÿ¯± ï< å<¾l°_[ WÀU­T q†ÁŠþ vœyuõufG ô ÁÐs6 Á0×a_n #PÀÿš ³>$¥qãàü¾°#müP aqDw ý„±‚µœzuÉ÷’Àƒ°V5#¥ ü•µ¡*X].¿üX à<7__à Sƒ‰Pyq€ – Ôhóƒ°e06"ðÿùdb/§šm—q>Pãà¯} 7ðÓÀðT jjk”à»­` :‰Piß§¾¶õnp£øó ™ÔTÓ¦ÓÿddY{ÿ+zkjlÿu|œ  ÍÏÀ[7ÐÑñà6̰ &ßÑ£¾äг€¿©÷ó 8™ÕÐrÜ !’PG°ÿdbdGšÿk}}¬†à°[>E`t°v̰ ‰Ph˜¾8äo5L«f‰Pf33+:0þ7fdýdÿdb])"ÿ'X mssßuz}pÁ ýû+cksjµT¡̰£áŽ•¼Œá¸ u]¨LP†âò¡ óº3+l0DÿýbddbßX'€]]ß-_kï`¯}ooÀU÷P+¿*&+ ( Vèá c‰PŠòá¾÷æêCú!5Qhfÿøfú+6ü΀™b üdïbbdÍ =÷bž±7ü[ý+8O€-èáDƒÓ¸dð÷å‹L÷ ò¡~ñó dª£¿2[_ÿn}ýdúb?%b’q’pÞë5X9oÀ g*(6ñ$Á?‡á÷—¤§]„™ ^ò!8fôÛðbª£Û+(d b^ÍÁ ÿbdbùb_ [pî] R(ÎÀ__Y¾÷PýuõqöèáA*pf…•—ßœœ¤¤©mR¶¤´ôò!D3**«¢%ülÀMbdZ¾Mt~ {€&ú>P.Dñ[T ßsu@öèá9~ftw|¿|••œœŸ!©÷˜áfóö6(* % üdà“ðbdTZßbdw¼à·{TÝ€55€!¾ÅÐW­`û4Ýd[jmtïwz|}çŸ45ò!ø$%ÿlAñ ñðK°¬4+ÿœ]bg§°Ý€2´°ß)¼°%  *uÓÀÚÔÐ —áÜfX¾_msuwFe’=¨•‘Ý÷]ù8*ðúb võ(Ý€ _°>;;#Þ±±VXÀ[_­Wªp ®ð CáýÄf=%*7½T±ksttìÐñb 0Éø’è@ ÕÝüpdb%’ðr¾n õXÇÀýf;y{sTíPù‡ Dþ$fb ë(6<*" \øù‘øG° bߤ± ÿXbÿ›6 Y Tb°u@#[!!¼° ÀýK]pûñÄ=!{!5Ë  Ð50tAŸ °|±°ÇÀÔ®ÅÐ.Ip)O€ß(Uk’ s·[U<Ç0#Wà÷<@èuíswÁ* €% ïŸ%€awalm—`<1„î«0TV ` [8aa<$O€ÿ +Zsÿuóu s_ŸU7+*(÷@·°(Õ[,B2A+eP ÿ T!ssÿ}~ ZZóWVd°\@ muy·yuu¶@y°p—_j´(O€¼À÷%TUÔAZ÷ZïT+ƒ@ ŸTZZ[’€é@ýðsàZ#~ÿ}Z7{}÷zj‹` YV{üˆ€TT »AÿyZ% û%UÇÐtu,¿“ ÅàY|œ_Z:‚½Vý€ 9•¼Dб°Zm%™`Ù õaìq»®wX)0 îpþ=agµVÿ<7ýûTp°VfúOP²‹`ýVüíq~P¬VcVbÉìpt¼À¦pü?P Tw¹Íî@YY?a=aWZïT)uD`Âj3Z|ñìÐúñðndõæìÐ Ñ \ˆßµD`i÷Õ¼{뼂¹¼o<ßøi¶OPCÿ„+%ñ×i2 ¼OPDÿ66ý„*¼ Ї`CiJ ÿi €l_ß k[ÆÎ0Gÿ+Us ¼gpÞ`õi¸¾aþÔp#€ _»UÅOPB‡ä‘+ÿ+*€÷uÇÎ0? ‡‰w‰‡c&’6('€ÿs he¾ü`:‡‰GrýÕasrùý€`<ù‡ l†±8±p"œbûD×àý6 þ¾pýií»OPE9²+o"›ÀhºPßA‡‡×à6÷+p hiý½OP? ‡‡„‡ÝV'“6¸`e_ë=Áh½a<„ÎÁp„„„ŸÐ碯€iùÀ¿P:íãp¤Ãý·iùða_ž`ÿ8õ„ú+û×i?ÃÀÎ03Ÿ‡„ „Çq§òsÂ,PEõ¥Â*ôp€i_ höðce_¢pq¦Á(?€î½€öhºq@ ;iGÃ+%¸bØ`ýhåa<„„÷h©ã+%[ÿ48û)54`3µ¢·„Ÿ‚¨‚+÷6>p[ÿ&#>Í0 3¶™ €¡€» ¨‚6qjÿ:h/÷]rvlY'@Q» ûÉZT À1¿µ¶µ˜×ànI¡í°ñße-Y"—@=Yÿ%;$ßýVwR·)3‚ D©£ír£àfÿXb]Xߟ|jTo¢;û ý¿ÐV<  Ë*Tº0 ^’I ù í°‡áj_0 ÿ=bw¯²~ P]-ýXÃÀË% vPOaT*¯[oÚà À3ÿµ6+Úê`0h5’f þè][ÿ+úVws›QaT$ÓÀ1Ñ?oý€ó/n¿ff=p þ"[7~¿P wu ËS÷TTÓÀ  ï 3¿¶ˆ€e €;€XüÓ6 šÁïö&¡0ÿñ]Yý'¿P<úTWs{ÓÀï ãà 6 µ€d¡€ô`€Â`+ß ôh‘°2ìHÀ[z¿wwtóQTëT"ÓÀד* ®¡€oý+ÿÑ*zðýË`]mï4 _¿uz<ò#ó üƒ¢ýðY^Xû5ƒ‘V) *p¯ê@`R[°usWÑ;<<ãà 9™`ša÷ii7Ó*2d»fe°e ƒ¢ßXêQ­WÍ’T0Úà4Ñ ¹a¯ ÂOq ÷9h >pfeMÐ ÿð¹ÐóÅÁ†[[îIÃ_À<%»ûTxÐ \Á™Ë¶ñpN€ip(Ýxñeþ"d_b]d ±¿P=ØPXV ì@í@÷T÷I0usUUË@æqp˜Ë€.r% ïhÕñ/Ófz bÐv ÷']ì 65õ ÖÁSBVV ± :1I¡PZÀê``;BË„+%æ¼ :!Šð]þýñYv~¢05 _Yà ëXÅÐ'T5úëZtrpŠý‹žÐüŠ=ç9có“qf¿hff—ðb]b]] 2ñ;YzÑXêRÜÁ[û_`TPC„ÿ fõf—ð /Ñ’ð]ý%à ;úÀ¡ç0 ýY÷«V þ_åÁø!5ÿ!øZ#½[@ i]áò+ÿ6 ýhõdßýbë±YYOrœ ¾!‹À'—@7VX`!³0ïùTI? iûhYó+ öf±ý iÐ Ð8üôùX4 'u6p Dñ_[/3à÷ø[˱$roëorÃàoÇâroÑ×p$‚$€X¦‚*èàÁÐÃÐ \]ï)¡1üX¹Ã!èðZ4õ¼á ³6 Öqò§‚Byß°ÃÐwœøX øþgà<__ ô,þ_N0 4óh³ n‚²Ð-Á*ÝÂÑ*Î@> ù PØP< 7þ [[ YT,´éðs vÀi*š“+Þ1  fËa5ÿd{ ¯±ÿ V$§ýXþ V!VßT#  m$€„õp %Ãw6 Ñdd-kÐÿš  ò»Xù1VV,@_j_Z[C‘qüp¡eÐfdbÿ]œm¯6<ò0íPYet}$5í`T_j_kSÁMBNƒ+ ¦ðÐe€ÿbdZ{ÿW*)kjÿw|œ õü@VÉ7T÷_jÓ¸¶ÿh f<Ü>²ÊpÊþâd]<+k š91ÿ[ü7 5Ïök> ÿ¼¾¸¸¶æ¿Àhf$Âip)úâb…p]/%Xï ks±œzç0B_ý7ª°ß+kT¢ î‰÷¶» hýf h®Òá0bûd ½Ð ÿýdb[ŸX= 5ÀqÐ$ÿ+ jkkmssuz}~~oA¿WT7ûs «° ¾ý¸àfõ¼ ®p*ûdÐ/dªçb™GðÈÒÿ #((*%$ß+*@"»< Í0 ÑÊÒ»¥"à¿Dbo} ù$ÿbùY 8÷X84@__Zûý(ì0 fiû—‰$*+ßZ[—Ÿ}{_ñàà$ßõX"%âÀ_[ßY9suj ýÚ!h…ž¤ÿ¤§©?f#ÿüdbZ ýÿ}dbvù~ðáàyÏ*s" @fÿz|}—œÿ¤©¶©!üç+ —§bbTÿ^bdxû}MÐ]] ÷) ìQVV5"ûÈ !· s ²œ÷Ÿ3÷’0)+n À¡ÿöY,ýX~/0<)ý%X°yuZTúŽ .°19fÿýfdf"÷b Ô ÿqœ ð¿Y Z}`|Û0âÀW   ÷À 2\1\4êñï/ :èšîX bÍðX·Y£0X 9`üÿXü[;uT8!/ bÿПÆÂwfdZ \\ ï6ýàYXŸ ú1UBÿû[ $ÿ~yUôlAP ˆ3fb8½†@7L1fÿd ÷=\    þß°e—²±¯ o<ýáø`çv1?`XXÞ¸( T s{}~•4bâ2üI3 25üÿ²±<eÿx(ýYùh0°ð[×Ó±á_)°ëUU+AFË` /ÿbbn•û?²*½ƒÀ_ ¯|ÚÂZPû #à*%%êà )P"–T¿XûV „ð<ï–<ý+LP[+ ÿT(}W›P¿P`V [_muP}uù@ +7(Pí(å€5ÁZ["ï}Z8 8yïj>? WY½_SV< ø@ußy#½0 }4P“óÿZ|šjZZYV ýV÷P߯VèAø«VŒPÉP¹Q}¯›P  ¡@ÓRPaÓQµwX9`ûTh»Q7ýXã Q’ÉQõgøP³À"¿ ýbPösQ³ðüTél añnQTTjú5`¯BXV%ùûTipª³>XLä@ToæQ¯VVùäQxQßÿ¿fÀ*%ùTqD`ëÃIÃwÊP¹ýZý'QYZT(uþÊP»js_ßZ|´x`úñëde£^` \‡ý©`þ%b{ cú[Ái¢pB‰„û=ºcC6ÿ%„§ö€V€ºqD ðÿ„ ¼V€øpC€@°ÿh m[ãXhÂøqyq6ÿuk ü€Ü‚)€E>±!ÿ€€ s_U;ûiÃÊPA ‡‰f~fr*×Bq¿"‰‰‰‡Gp‡Ýca’6‚qus ie¸\qˉ+qv±êq¯ur³pÙqýï6…g¡€t·pc³p 4Ïjlý¡repý§+ý­`opÖpeþ€6B‡Çr gç_Øâ‚>ý„ß ‡„Vx³+½ul_¦’gÞ:„þp„„燇„“¯Ñúh»þá`8„„ ý6+CàAu¡øa—5‡íq m±Ð0}ý q3ð„ãå™Ðu  qC•7õ‚0Ûð °hCÖÕ(˜aÔ°hÅÞ „„i΂6+¿÷iõh²` 3™£¨`² ±ÐݱÀH/±€ÿ#V76>”Ð 3 ¶¢ï€®ƒ¿66¹îApZÛ€&+|ö°ÏМP÷ 5® dÞYÓ+Öàijû<ß°%vv&W)Õ¡VQ <êÀýY’1¶¶µ˜æà æ€æ6úÕá½Ã=;Y ÿu[7;6¹¨R)R(‘ÿ.еŽþ«Öýihÿûf\bß…± ƒÀ-ú®1V ýVVûT<¼ *]!£ *c¿`™ðÚ­rrp¾Â_±²8]2 “+~‹Á%ðPY«%´7â¡ ^ ½€ýiÑhÿ!wY]•,Ú ðÀr0¾²"Þ> ¢  @/ €YMð€ÔàûØ!mïV]ö ÿ>_7#ýXzu 6bîzYT$ ;üã ­ ßà•÷hç&ÜqÚ0ý]ýzÐ/;Û ‰QJÀWuó{>¤`&ß µ¶µ€€Íí >²5€_þšpff(œ_ îzÐ]Y*/Ðzÿz÷T÷T þÙ“*޶øs€¡‘.ühð~jÐm){À¾qÑ;ðwz|Wwu¦áÿT(y~yWîa° P2¶©€ û6,µÐÿ÷búYÿ+ ÜÒ‘Ð67”ÐCú4€f_DÈÒ<À½;ñXVeßS3ìÄ´0 %7pˆ ÷¶£µÂ6+5[fajÐeâz}ýñX5ûV€P? ~~ÿ@SÁ2¶™ iÁy<âñàà8[Làû ÿ¡YYZù/Ñeã) (Tû­RuW'ôv´¾±ýiå iDóp ¿fde–± ]ûYAM%0XÂ’P ûVT’< yYîä7ýöÁ 4 øÛbò€™`iý+ÿ8h#ýdÿa___ ·\ÌÀ]ïXYüVP¡ï5TU ü·€ € –1¬æàÑšá]$0Uó<r0/Ð [Ó[6a)PKøÂ€˜M“€ !ƒÐl‘ÿ4fûd]ÂÒjs oÑY)ÐÇ+5h0¡0ÙÑ r"àY­RGÐYsYMÐulQјЀ!RsÏ6%îÚhf­¹Ðìá z û¿Y (%A;Ÿ jY=Áþòýƒð÷T ûïUZRð!7iŠ‹ŒÐŠŠ‹Ð’Ò»=¬q++"}Ž2ü_ÄÐþlðZsYYÏ$ æf@nAöàT)÷ñ_É+„òhœÊâ ëññ ½sú’wû[ /k ? iq)¡êù‰4d_ þ0bd ]3¯+<ä°vîÐ8ûk®ñBý+5º€ ÃóêªÿYZU*)ý¿j}œñ Ÿ(XÇ0 ½2j h<Ër6ç !!‘18ódvÀGšk}"¸!<7) ÀÞwð ¾ö¶›îhfɲópÛå0 bbçA'õ[šÿí[[»Z å`ôT& ÷¾Ú¼¶ŒäÑâÑffç‚À\P=c8e_ 5™ýdGX= ý& .ks÷}o6à _[ýß7ý*2Àí¸•¶¶@ ýh“â¹€+1€ˆ®84dZ »Ðÿ8ý[÷7+®@øs ë7Å “¾¸û/t¢#ddÿXbn}÷bÜ!5õnA[¿Z*(6>0÷h—Y¶'ù+bd^[§ÐÞ![üÐùYžT X+(ù20Tï8ýudà þ> hhn•—œœß¤¤©©]4üÿb ~}ܳÁÀBá]YýS]áVT1+sò uÉ@±°9f•—§©4vÀ^µbdô÷{—]Y À*ÚPê° ®%» ¹ÐsûT0wzÿ¤4dc#% 4"0šÿYbm×â7ëáVÿV4ý¯[=Wý 72 ÷8fhÐm=ófÿM2 þz!db&n÷ 5 ÐXY&ýûXä°ü[õ80+<1 uïuD4dýûd–0òbõœ^0"b0˜m1n0 @ áìRú X+T±\8B3ýñót¯þÙ@]b ›6¢3#"2ËÐóVý_) Á0û{uÆ1õfß5ð >b+# Ñàdý0 @»`8b0ܱG oÒj°»ïÇÀ* vÑ8ÿu}~ymUTú¹€„Ðdf¡÷òúñîвÀ²Àÿ4q¤z¶À ¶@ )XºÑß œ¯ÚQîßV ü[  +ç6T›À+@ Rû$]ƒ@q• ÷e+À5™1ž2ç@÷^m¥²VýVû n@[[(#º¬@7°A"ù€ÿ%Bewl! `õXVô²ÿ C[a<#þº` [U7+ß+(8~ Tÿ'{}fbÐ[UP@HÂÏV kú@÷@%¿TUZ[[jóó5 P S~|ÿZ`ZYWV þG²Vúu%ÝÐT[1ù`·_VY| Ø@ 'PúF’ ŽQ¯V ÇûVô°#ðÉQ¯ùÇX F’9aQµ_V¬S+QÇd ;ñ9aõPû³ä° áP¡$ÑÉSXV§;]SåQ±ú’: `nÊP¬ *Ä‘ñÕ•ÂmÊP²ÐX>§øôQØSò sê2`°’"Œc­‘2`Í`1`)`Ý5O@5ªh/‘2àÿ\]X û'\Ф|üXýƒ üTù)™DîZ bT„ü÷iHÒd_"ß6 5]ö-û?V*[ ý@5Q¿VT(aoÜ ÿ4‹ü+ÿ66ùhþìff v>þãuz üËV"¢ @Ü‘A¹d H%¢hî\€f/°]Yÿ>y_7÷UáVX¾°ýT7P+w ^ = y`g€€Xʰ€ úpß"h+¡ïXÿ¡9tçm O¢P¡Us{?_uW—¢¾°_¶ûXpÃàýop h_Î1à)jXÀ°o|Z€t ¡¬J°úà 5Ä` S…ÿ(f*}Q4ü ^°°"è°ä°ù4Q5Q.%÷6<© 4ò€ïý+g(ï!hfì2{~ ý°!#+7TüÀ°Q ü»TîPVT`àó*íP± %ý€½q6+/ D¾ª“YðXe 9h© %Ä`½Sƒ6+^RÐYÝYÔðXò¡Výö,Ð< {~Ÿ{{jTN°º°ß=ü€Ûq6ïf%„ZvÔ°]²â°7YX ’@ oÓî°÷*TË‘Vu¿uYT&+À<þÁ &¤¶ ×µ™ Â7¬s*1íúðe‘b ½" !]Y+üê±%^B@úT-Q@@~Ô  -€6Ð[e†ò*Û0çe ö {qÿb] ]](Z[iBЂŸTTj*ÐàYs!û[Á˰i€¦Á{ pàc«ìæÐ„Ñàb |~àp¢ T< ÃÑ×¢QV» Z[¯öT ,_ "ÿi˜óiüó+1âúñb]ßls/Càoo~Žàýïàÿ[[YTøT,kúU…°Ài ã·++¹°fï‘;29S0Ñà]ý ª“t ï*%Žá8Øbл°ÊÐ I@_[þ a:ÿbý‘Њý‹ÿ@9ú+6ÿ öfýf¾ºp bxà]]dk(Cá_>YÖ v n¶°Vòá[V¿°mÛÑD¶ƒ 1Áß ú_ øòüöK0jkÁ ù(ûY@ó%,pðý[/5ˆ @ë ? ? hi]¬r*þ€føfödëøËðY€àrœÿûY' V#5 ïÂWƒ O†°Û<êr]¡a% ÷!dÕáô°2Ð]]² gÿX kø“à"cá&rrOøoêq ’Yí66QÑ;Ч°¶ª’]440ç sj_ñò þGBZVTVZïT6E†°Ýhf }û¸pihÕ g‘Có° ØàøX ò~%0< #ƒŸ_YVT8ºpÇ0 ·4h¡ Ûb+Ýñ°dd B ÿ$b]ö] ¯Tð ¢Peð{<ƒý_ºpÞÜb3`&Ô–Ýpà0+ó°ù~™@Rð ¯ v ‚5ÚºpR žp„ ¯±œ úpÜ£+y»ö [*ñý …P( .»__äñ ]pqó(aopûd}„$šmv ¾Û@Yeo}HÓWíTm°G_ ¼¶ žÜsß üf„ÿ]ZjW*%ÿ|k |œ¹ƒKhû_T¸¶$Çr Ö2/¾QbbBŽòyõ}˜@á_[/Í*%@jk‘@Ž[¼0 äh—°ÊÛb Ì0 ±Ç ï]®°$%¿Xükµ@}í5Ò_Z ò^`å`5°Žý¼Ü¸¶ ôñ Ÿçhf~ìbùÿ[_ d~[\=ÿY1uu~ïo;À_[|^`¥¸¾Ôÿ¸¸¶…¹ýCû+ §úbºp4> 4ï#,0ü*ïks@ ý¸{¸¶$fûôÐ6*DÛb 0p¢]Y¿5;œZ}Vhi—íÿ¶ù¶4fï *+5Áb¿d_ø]ÿYX õXï%ý[W ¿=…•œEðî÷Bf$»Zõ~)ÐWZ[T,¾3Ð34,0#ï4F€|¿| 42í›3üÛ "ßú[<k]! ú® Ÿ4ÿf fb#½Å"bbb€l¿k¦°Yó8 ëâi±ýIÐ_[$  +uZ¤ ý<¨! 9f$v/ ÷!à þCb …ÿš~yß8]HÀYYõ+v jð[F*þê"msutå´À ¼!Šdf/÷b©bß+ýYö ›y½RòVÄ_o<sTúÀ@o bkÑfÜ4÷!±O0bbýÏ 0öXNÇ` cà’Q!û[Z/1ß  DöÒ×=bM0œ—²×² g‚Ï jCÀ5÷ °á) ÿ/úfÓ øñjÓ÷Ñîÿd5³¯²¯—0 ödx(XÀþ¡1¯ n @pàoê`°PV³PZ_ ‡5õ@»PÐÑÂPu±êÀ`­ ÍS}üR¯#*ØÀw*PVTt`iÄÆBoQ;òQÁëP¯TYy`Êlºö"bà‰~p†bi¸`õƒI`»`C„*ÿ/& úûi¶pC+(ýWp„j vXp„`ii¼`ÿ[ü„rq·ý€¾7a€ °¿li M€€­l-p€iYaG p¯ukàÍ`Eþ(À6_7÷ü€Ô`@ý‰ïý6 û+a?üï‡dos(ÞÚuça=ïú‡aqÎ €Ep¬P;ÍÕ` '‘RqgqAp€€õ_maDÈã6+ ¼Ka^l h1rDÜ’¸€!pÜŸ’2pDMò++©8úp´PX`(Á5Ö‡àg|pT€q9¹jq'€„„‚ãüšp]q¡p8ü„‡„ýe’ÿ€€gýÛiÀµP6‡p‡„ \a63ó€žp(pÓpí ×p„7“q++¿€€ùhâPéDÜ¡“p#Á³hÖàÅPC’+'+$À$Àsðûs?? „„i7 Ïú_ úpTa> ö“phÍb6+^ÿ=>>)5¿ZD?4™„ €€Ÿh+g[€iÛe@ó°#OÀYa{#t 3 ¶|€H‚€Øqp’Á‚ ö¾êpdv. Àû¿T [TF€/ ޵¶¶˜ß„bU‚66ûý¤fe==ÿY(;>ã;N’¡zà ,m„ ¶Žâ€Ô`_h1Àhtÿ±(Ÿ|kTïýV¢ƒT!ï 5T †°*cç §Ð7ùÞˆàl_pe_ÿ=³• µ³°~ ¡V×!(% [Z‘ 4Ï ’©Òþ0á?w üYÿ²œuZ+ÿVVtzÿwsýTüTeÊ n° Er»+`hhï‘.Ü,Z0z_y’V¹ ÿ°¢,Ò’;µ¼`€¼`zòþÔ`fh þ’À]4<U¿wwumA?TTWsœÐ g :[ˆ`:âÛ+ æ‘„f1ý3ÑYYÿV[||{zº%ø¤Þ*˜Úµ©õf` "+6ë+k32Ò#TÿX uzzWþ€TT%y~¿yUT ‰ +«< [@?2Üö¯À6,uÀ2ü] »² YXÀ@VŸV +Ë‘ .gü+ГנÜ£¼&£÷°'öX¸ eû AT2+7þnð &€ˆ »i<µr++(D° ’5ð&‚Ðù]°±V»5T,°{ç_TÞñ?A€úKp6B°f*[ûÀbs ?õ]±‹@7Y†½Ð5i Ê€náv@ú˜ÐB"â§¶iì‰`Ö²i7>6+2ýé±b]e ^üÐúYr0ž ¿VV%Y[2¼Ðr &Z‘£ÿ µ˜€€ ¼ µ>\1Ð]÷bm 0]Y&—[[ 7¢é ÉB›jeÁ4ÜQŸpYf¦ƒvc©`7!ïd]ÉÀ õ8DÀ[@U<;XàX¼å!ßû[w@VTÿ_TTWôT"ö4žpkÿhf/fâUð+У±˜0m;~*@Ò< jð3¿jZTUþàßý€ ³ò6+Ï#0½ û«d0“à”¢tûà5 _ûYêã ý[÷¾ ðe#úZµ ß%ý‹Ћ@÷:ck+m å°Tð¢±Ï]]^kL2çýiË`Lr*÷dó÷†Á^k÷ÑÆ¯ ÇkäÀr0€kûVÐѬáØÒwAï+#ذ ó?oroCÃá³hÈâD`ºÂÿ"díX¢°b üÑY]ï UàYYsl¥ábà lá ý_Z[8ðh qöÁb´s+Cðÿ]mwß÷VÚðý¿_ZV A nh°ü_nð 5ˆr/ û+a·€Û ï""€ vézñ/@P7ž:__W>Œµ  Œ¶$Vµrÿff>5 " £À¿#÷_?¾©`òh³ñ÷üf[{}?üàà¾Óñ_Z=kmñ »ý¯€ƒ©÷ÐÍDb D1I0deî¢b [$œóm,$1”ð• üþØð5" #ö?+ £þa6 ¨ìá¿ ÷a_[YZþ±°*/sw}œï  ‹Ð_[6÷__òÐý¸fû0hyò´ð Å Ï8d=ÀðY<ý%Çkz}_š ¯mÅâ[5_kÐá¾¾¶$ f5vLq6 í°dðöª[ò°Y("'X mkËðÿsuuz}íÙ9Ðî! ýQpksõ üÀ ö¾¸• _ Õà ª‘ˆ=Ìacžðàã°Š ªd[v/Ð=ÍÐ4sÑðï}~çÑ[UTo<7Kr*3Î8y×Únúðþôÿf+6ÿdøb;b§l[d0-ÿ #(%*þ"á[[ý+*»< öp Qs.~ æ±+*ñ¿o}ôz³Q’áZý(¿#+T0 ÿfh—¤§©Bþ‰ Z[ýd÷ÿbü]XÞ\ X+%ŠÒYTï8su¯ ÿffn•—œß§©ƒ?fý%‰ bZdbÿbbv}}ç XÒ¢dRü[ÿôT#ßúuÜ€ÿz|¤©%û*edbdÿTZbZZY4‘´ð,î{Q ¦![3{ sð 4Ûÿwz%dfb$Ó%µðB" „àÿnò×YKû  *u77)! ÙIÀûm|&f" üðD vqœ›~zŒÂÿ X>8;;>oYX )1VIó÷D+l$kstuÿýdñbÿš}!br¥À¨0[ y¨1¿ý[(À {½{òÐ +a7 I2°^ìÇ Fð]à   ïY Ø ¾;@ îVKñYïT° ÿ< ÷ H1 ÿ?b.õï'äÃøXïr›  üÛX‡0 ø_Yÿ! ÿ s{~{kÿTTxG1êâÒdfëV0ÿ4û²±ùsqê–Ù’a ©ó+÷…‡`ø€çüi¹Zrçƒ÷€¥p¬b­Ãï++ 7a€üð€ªb6D‡ ¼¬Ñµaõ€¨Q½ýÅa=„ô`„û„V¯Ò66—il¥pW`Ó:0p«c<”c6Ÿý€ð€ q7=/qù„!ð–`½€ri_øÖàaNÅa4«`$` øQÌ´PfqüÒ@p1÷hÎ`„ ü6ëqÛZq++Û±£ài ÜPC¯Ð®°ùijaÅ©p?÷ý„áRü€»jñà9hÇÌp.ÿ0„™£ NÔp„h Âagp.ý>(‡@ÿ 3µ¢„ûq„á>‚ãpheÆ [VÓ##°X\0»ž@ 7þpødCbø` €ÿj4h+ýbýÑ#rtl$ï)$PT ÿ#†Á4 < ÀïTßÒV÷Π7'¬o“¤¶Ó„²„²7bò6*þS°dbb ºÓÁ]Yl²ûWu±VT û< ê ý7{<b3Ò ÇôýÑêlZ×úUo‘â`€!ü­ÁKÐ%úfoýfýï±]$ПjY´A!þ‚Ba!oUZ‚€ ŠŠ‹Š‹mÀ_Š=:`ó6 iðpWÐZ?s(ùYÐpvÐ[i2çÐıòg`!AÐ[c6 ýûñú_ $îð"düàk÷ ;Àù ÅšÁÀ¡3Ð,á×CAÐFáQ íÚ°ìáýb5A Ynœ‹àV0ÿ' kXÏúV 6hàT-÷7—Ð >hÿiiY+6ÿ&ôdübÿZk"; w² X°XÂÎI`øT%çð—ÐÿŽvo roÿrroüiýOh iB’C1ðýg`&dÞPàò]Ò- ýj˜4XVý_þÌATZT;k_õ[• K4÷ð…`Hphà\,Áç Aîàoà×!X'ÿ û[÷TTr°j_²bÀ ý5?Ñihû6ÿ+deý+›°b] tz?¯±- ÂÀßü[{p"ô T x2ŠvàB‘äP ,õ]š„𿱠ª0ÿV$  ùeVð5²I!@п„ µœ gp^àâ6+Z#e ÿ Xý}ñXPðo@jko "q=qÚàhBb›àÞ_"dõàddßC6<ëÀYeït•û ð*,ßj_kðôs¶’b-` +òöa ýsð]Z$ÿ%* kjÿtw|œ±œwý["¬ùkbÀÿ ¾¸¶ïh,À õÞñ¢N ms/s  ‡ð ">Ušñ×RË“h<ÿ666+ çödæÐ]ï ]%Ãð%Xÿûksuy}û8_ZI#~éñ ö¶`x©ƒ°–ã%ÞþŸû],_kÿ~}o;é;êTnñ¾¸ÓÚ²Ú° ®ÿd]b rŸ=%s¢- ‡'(*†"{1¬3ðþ™…©¶¼¾ÿ¾¶¸$fÿöf6*$çbd©Ð }%*(ø€þÓ i—ÿµ¶¶¸¶?^ÿ[[ [ó÷ X1$õX#ýûèò#ýîI Û°…•»©6ó  ÿý}ôbóXl42)û Á[VTç7Ûp5¡}ÿ—!ü+Õœba^eU[¯Y /¡6êX?V5"§ñƒý‡uzÿf ffb#%ýbÐñþ¼8l÷m ‹>XyÛ< _Z<ê÷<Á ý9Éjmùfæ  ìÒò …ÿn ñY'k1¹@ž=0ûyp°w±ßt Z%f/¯ 4d+ œ' "ûb ýX~Z0›y —4þ!_[) êD yH$6P <Ç \ö"×â#±±k bd6üYG #% /0ý¦ñ__Z %ÛK‚€õ ÿ7  D~%fd  O@÷?/I0'ÙZ0«°X&/0ÿ52¿u}~ymUô+]bÀñ[àý…À5ÿ³³² ?¿(XW3X¿X¯/0ýï-0* ý[/®¬TC0(G19Sļ+W0Òqõ$]°ëÔ1$7#Û%/¿à$ }(\¤%ÖPÿaaelO%Št€XA÷ fð%¿$¿à.û*¼0}~zï5sÄ0ÞÈ[ZWOÁT÷% Ý0yuÿ 67TTUZû[_ê1 1Tèó2}1ò0®ðzßZ9{}ðe¿ZYYV ¼ƒV? Zsuuà0Û0÷@ %Uû[1½@¸Z|œ¯jZ0STB¶?XZm%/@[A}c@®VÕpV< ïDïµXj@<7 î¼VVc@²7VXú §@YCüAŠ@|‹ß@6k0~þB®øVù7@ë*Ï1²) uûYTÿB¯Úq2 µ¶™»»ß„ fò++oh]€:h< ïfe!Pp]#ÿ^rvl$½«À$ûÓV à^’TD€YTv¥ ‚`i•àö|Á{ðfùd{ì±]bk Œ°Þ=¡Ytg!;¿ _YÀùÑBe{:cÀ b¹`oiŠ‹‹kÀmÀ¹@wÀ—â+m±hûf= dü_¹4 Â°^sC§ýXÈ1fðTO÷THˆ åà+ƒ / {ð à?¡·/ÍÁøÙƒ±Ãr^ –±!gDô1âkÿ6+ZTþ¶  Cú6 öf÷õd ] ]÷]± )ý) [[W.û69Ñ >ýiÜäRÐ%bÁü*àŸÐ ý]ýYù ñB û[ýSˆ v 7oroÐ ×ÑyðßhhXfaŠà– ˆr8 ‡‘úY f@XlXY) @Àø7@çVZ2á  4ü»iÁpió6õC2°2àû}BXV<¿ [§ñYëTR¿à4Ãáih ÿü+6Þõ#ô]"V ç> Ô}D ½;ï;;>XYp^}þAAXVöVû?[ °¢ó3üÿ/±ÿ bbßûYÏ“yÈí£Äã úç{ëD÷+b7¿ bffõ xö  ±ð¿ Y k YÿXøXÿ% íVû[ï:~uì þ#f8{w°õd3jÀÿ õ' yý ¸€üV/ ú‰Ð'ñ0kTT¦–á ücጠfÿdü²ÿ ?be“k k !•£DÐ)ÿ [[+¯%6T*FAÿ³²÷¿)Zee ^ | ‰^mô0¿XV$ îÐ0úÈ )pÿq[aÇ%ìÁCÐ[A þ %#%[a<#Ýrõ(=0{A0|5ÿ{~YVýT kª0þª0"+7[ßjmtu(ÕðÏTU#y01ñÿ[|ZW7XeâV?Ñ%0ý ¨0yyyuZ#ïT¹1“ÿ 'X÷VY|°V øV¦^pÔ£á4³ÁX<<<æ³÷VTgÐ1± ßBÜ241²xÐ6 ;Ê2A$C7ûX·q>ÐáO@°åÒÇCy2øæÎ1®?Ð5ÀV%eŠ+PËcö2®~0"jAŒ«AìÃÁ1°J³@ÖÈA<˜pq+P±×;V˜pr¾@ÈJßAt¾@ÁìAy¥P_¹ýZß@W0« Ó@ð\ßR{\u`ß`ÿÿ¿€hú¶ai)QBŠ„Ý+¡Ðøiß`CÏ„+;ŒQóaC÷€6+Š „¿!öil[Q÷Ci¯`ehÿ €€ m[íDREçaßTsk ñP o<5÷£QEpÿ_7ü€ß ujl iÀvIA‰+ó*üŒ@ûup:"‰NäB‡‡dCqæpðQûõ)Q<ü‰÷+6û`u÷qñP€iî½Q:ÈQ ]ÞAt…jp€€Õ4`Ó1p9ýP úo+ ðQø5PÑi],b†P Ï€!’ÑWREÖ\â8iUb@ýÿ‡ý6 i€çl_&c`;ì’`@a„<úÓ+ýýpAiúh»¦1p6Ba¡Qäb6W+4`»rXÀæøQ4žP’`÷„Y®±¯`·``™Ã-aü` ¸a×`j§_ Ó‹`IÁþ úiöhße___Þd+Žça6Îb»bn`_@ „iea+´°j¸a™`ÆÁ`= pøp$¡žà€45¿Z/që=i>¨p2 ¶µ™­p­pÇ0’è`ypihíÁpe {²%vïvjY(˜p ûTõ<ð3_p.„cŽq@¬ Dq]€ÿiiJ ÿ=Y z[7Ò<ðx€˜p¶À ø‹T ïCaÑSa_aÕn±-f€0V<ó ?Ð ATT#×5T Õð,‡`ˆ¯µŽ·pÑ€úXÀk²e_²³s+ 8]-À?,ûV 9Z2ž¥ 3¶P€ûÒ6ëTRíp!vß ü]/’uv€V°ƒ£±M€?Š €~œÑýÑ‚fh0ý]ü ÄVwu=_“.ðÂqOˆ €1Rö@™Aÿ+õh-hë)ð2J9tçmUB°^’WuÞÆÐ  ° 3# µµaŀĀâáø‘ßôh÷ j7÷úYŸ€Xzýz0ww%Õ‹Á!Óà&: *ט¶ Èp JÃ(ÿ f÷bÃm{šrЇ/ÀëŽ5ÀuzÿzUwus_W<#”Óà i!ê7à PàÕð2µß©€ V¯²6*û!À&}~ þªrm  |ø¢Z2WuukÓàšZp7ÉÐ&`@¬¶ç¤.òûÐöfßt{} ã ]Yú@¡ X VaÞP ÷bYTk*¢Tu %z¹_±ûÐ)cî€y»{ È‘]Y’-ÿøTTÿ ü7ñTä`@€t LÀ_àÅØp$!Ñ2¬Á;^B Y‡­p|Fá±1+![[Cpc fñ' ÷ &dÀöd|'Ðl  ;pÃÿY]r (\õ?"'·V~pö‡Ñ_Zˆ0 ßUm5ÆÐ'w#ƒ`@h%P{ÓÀFù] ¾ð“Y‡}Àvй’½üøÁ A ]e’+w6 ¢p ̲ÿübú]ûÿY¯ m©2Á8ÐŠà ºîÐUð&rÐûo’QDA’PXþ&’a_ôdøš ¤°.Ð]û4ˆjXýXýV †ÒËZTÂÐ TÐ Ÿ}ýhÔp½ùÒ66AÏ`þ5p ±ËC+0xþÜ1k_ü_NÖà 4bãÀ !²÷+6o@fe)õ&Ó°ßÐ!< ¿ üV7Á[¹ Óà¼À_ùÑ ÷™…¶_©œV'’DÛÐûž  ¯±"ÿ>$ ûV›ÿ±[5' Z ÿh„òh®âã6 ,ãnm#ïý_ôp .ïjjZWÑ2³hc&P ÞdÿEšm5 *þ~0Yet}[ÿ__ *ð¾·Ò_kkð û¡ð žþ[p úfddH|kt}àw œ  Œàã7TóðÑVá¸$ {h<»c+$ÿ4dýdï]<%«€ uÿuz}}šï Çá[[/¯5r µðŸ¢h/ +G6 ôª »ñõ$þ ß msu2€_[Ý'–ðkñ ×¾¾ð ä ð¨ñhñhð!Á66$Ïd îò•[çX=…ð”à+jÿkuuy}}ý}Þp[<79þä`¸¼¸¸¶… €áì¨ðkñýÍà4d÷úb+à=bûüŠð ÿ#(%*=7ý+ûàq©¶ÿ¼¾ýh-Dø³ð¹ð”65X8¾R "*(6ý —¸¶¯4f WA ^s[µðîò5ýð×j?+ ÿ[YT4îÕð=jQn•—ÿœž¤¤©µ¶~90?f#)ïddîð~Ÿ} Xa7Výd 6su{ZTúp ¤Q½Òpdf!ƒóbþbdb }Téu‘73U£5"ÿý[<sTþÍwzŸ¿Ÿ!#%Žàõû–€)œßm¡€Y4| !o )Â~À2+uë!^" 9ÔjØ÷}•æf éÖàÖá ¦pqûœëòYÎI>%W C XVÿ_W ß uyŠ  ÷Af PýfÙ¥Ð)ý–€dbÿ   š}ßb°°|@ ? ›y½¡ßôVÒ(õUyY »DQ@\€dýdžd#‹±±ý¯y\bYÿ úY#÷% o XV.ß$,{Ÿ üDá€fb5û¨>býÙýb¿'% «€ïïVÔ( ÿ {~ymýUM6o8bÍ`¿ff?b¨ 4ÿ <dxß)X3À °  °{éà * ¨°ë[-V Ñ )ý# R']zäáZde màßúYü£`ZmÿûXM%%ü¥àY <+*ï*#+qàÿ% Ÿ%2[alœ<€px¦p ž@VV ý| %%$‰$ÿ*[Iz5@VZZYVìAs¿V% muµ y77´ _jœà¼ ÿ á1üX;‰1S3Ͱ£2V‹á1uÀVVy> ´1­¾P„„Vþ¦R6+€€µøahØP<u@û:ŸS„ü+ïý6Û‘Bwiù·Q6ÁP;‡ ÊQ+bY`ú~RaÜQ6ó„9P‚vPiÒ@ÿ5‡„ ü6}Êà*ûiÙPêÐÂú D“s+*9ü£ÀýACü6+ÿ(ý€øi÷öh½FA„„ý"²ü€9ûhÇÝ@3™£ úhbhéC6%^>»>à`)y`skèðÃp™S@qS@Œ€F+ú@ÿ[&ÿ÷]'>>0 3 ¶™ea>`¿d6…áßij0Ð ýÿb%dvvlY;)#z Œ0þã` . „޵7¶µ˜ha Pà ÷“Áýf/û"p;Y wŸ_7(;"¸p1O( ¥àZ ýP&R{Q,p}°àû\«¤|kûTµpX;õýP2òÐ*Tí CÀ+B€¶ïŽ ]Oƒ+ýøàÀl_9¯²®_à5]«+uÁV{øbT#)X°ÿ YY&7À7 Ýeo` ôpVTÿy~67úÑ%wP µ£Þà+ôf*G ÷YXEVT }<ˆ~{{{_üpo È’Xæóÿ<)ìÆ°£ 9± YT7<p;8ñaï 9òdb¿nõ°yÿY>8; ïZ}æóøVü8î [W ß ûyà þÉð-üfüd÷:dãœ}]rpXµy:‡á‚× 6.†pB@à bðS¥Ódÿx±  Kµ‘Y=’7!íðÛZXY¢øÿf < ÷ D °ôd ÿ?b9'™ BÀ< ëp@‘XV#[?ûüñ4b }¡ü×zÒDbdÿêd4ÿ³²±<¯?¬€ î Ÿ ) ±>ÀXïX¯Ãü»¦qü[# ¯ k Tà(öä F` $bßb û²Qàü;À€^m|¯¯3T$ `Ñy/Ž€  7 ëÓ°(•ÐÚ$ ¤( ae- <ù|°|êV ü_ß7aa"†p.ý(V |5"¿XZ2%çy° s +7ët~!0U!ýÿZZZƒWVûV Z¯ ø³ ° ຜ_ÿZYV üVsD¡é$V!45ýø!®VX_  ïÀôqVU0´œ0s° VƒD¡1 1›0°7+ 6ws0>0ýµ¯üÉ$U1´V±61ä#›10löç ®5XV=<–1­ >EÁDÀÛ< Ð+Tû0¯eÝÃR0—1¯/ÍŽ;1>ßÁ±1¯<×0ËÀû0Æ0}Ê05%ûT§1sà ß3E <%r×1îvrYZxç »_÷sëÀ*zµæLÖB`ði»-B€c›P€îüAÿ¿G@‰Ï‰6#`Qøûi·F@C+_„ ›P_p¾uA]lh_p kXµ €º@EëP¿6Uu@P×õi¸F@FÂ@+/7+Q[@ùPç@ K@¢á++ íý_#u4`=tÐ@Ñ@do£*˜Au KÀÌ `:O@§‰‡“P»  ‚}ýR:‡‰ #PÎqg`,P·g_Ó `9Ð@þ‚+ýj«l£Ðh4RI!@ u@PÞ`B ‡Y€¾ªBõ€œ@úb€¾ `A ‡‡Vör6™Pilw"iÎqT„Qw:R‡„ €÷+™‘Ai¹ÙS`8ŒQ‡»„ vAý€\PnÙSjÅR4iPü+ýiÎqþùP1h„9ó%`Uq*ú@rö@D 6+ùwiu`ihÄ}QÝTsiÃ0€iUb€Å `?é0!@Û6—p€›°8N3a<?` Ph sÿ6^=?>õ4V`Zc¶¢„;‘a„„'aÚ`þiÀ9&bÿb]b]Õ“¡Y: ‡b5ýw„“bfrõf€jð‘!ó]ï^v+öc$ó$<ðÁa /„ÿ޶¶¶˜„ÿõü6ýiõ‹PiàhfKÿz[7%;>›; ´à Íõq2÷øT Y,„„犕QÈp,ÿh"Yš‘ '3 jT’ ¢À;Õ5s´à2Y+ý¾KpµŽ bUr6µ+àAHPd?_±² Ÿpép~rqøT(eoÕ‘ß3µTPùëhjb1¤°Y × > ü ?0TpE  Yàz`²q (9YþÛ°ýiIV]ëÞqpaûVwu%põ&Yà$3¶ˆSàR—qÞ—áûf-²5tkU u2þœrs{_uýUC„! ¶µ¿„€ù€°Rêíiáf(ïšj7qÿX[zú~€w‚€%øTíEY5üÛ@€ >E±+6) œàã±Ï2üY á^p )<Í!L‘ÕÐ  àÑ»4U€ VÏS+û)÷àf#beû±Y)ýV÷Vm]qyp!ÉWuYà÷ý+žÑ%ýùž“Ô0f_õfÑ+€ñy°1 û‚û (! WT{~~{‹‘Û7TK %3€ˆ ¯¶£@'"r ýŽÁYY,ûVÕý×ÐT|{jTO **qа< Àÿ2µ™ ü€·<ݱ+50à²r2M‚Z±<εY5ô1) ÿ(TUZZ[zÀûT<#6 ¾Õ‘8ý€ŸR€si7;ƒëh_•Ðý,rY]?Y ZXš /}¤€ <6 >à2 µ˜àî0ºžQåý6 ¾P"þµÐdda_ ]\Øpbm ð³ËX ƒ°ÉÐö ý èp_[ûT^Yá_T,] 76°ý ”66üfûÈ ]d ÷;n°]YükX`½“XŰ÷ZVTaps¿-ZU] ›A˜°AÑýþâ4fžsàýbª°'~o±m~% 4þÞ [[YÿúT,úUýZ}Lýi!³õÎrSfdy9b°¦±mk ‚ñý/0YX5 ÷_Y0Xý[ßeYýXÛÜÅ ‰á[[ª‚!+¯!t€B@Ó6ï6 ÿàhf[&Öß¡ Npý]v°]r *õ³’&½Ý¤€'#Ò± B÷ý66P õf7õd¤± ’hïjý±'{ !VVÔà¿YT7Z[àÐ »< oÀhi]£â+ÿ Df fÿdödø] =üñ°² …³””‰áTþq¡vo÷o;r_ÀixQ¸@7hhXtÃ+¯Épßdüb Rò ÷4€ släȳ 1Ù°#ÑVZûý_Ãa Ÿ}ÙxQ$±Ñc@éß¡G ö û±^ÀXVo #Ôà_[ ½¼`ý_4]à5ïôh b$úrípYüYÿùXo ç •À‘%þÚ±#{ÛkU©+$бºÒújdÀÿ5ü²ÿ¯<?ÿbb(XígÁø`°Ÿ þ£Ö°ïT) É$ ß %× FîVà '‘¡n• ÷$ýYÀ_Zm|ÕÀp’^ ý[.€) ÿ#ï7k ðlTö0VpT ý¿[%ßÐ<×#*P”‹àºÚÐϰ[ZW!ßüVyY!!û67Ã` TUŸ T[-@$ƒ¿YWVy1ÿ[sýu~* Z#T]ðwa6(å@“ °pjZYY P VT= *ç }ÒºðeÂPï®V) ß<€<66(ûƒÀ9üü÷ûá‘;Zÿ ú]û dz;Z·$Üá8ÊS¼{€—bijèÀhûe AÐ&drvÿjY)üT#×TTÿ3õp-ÿ„„޵¶öËP„ß66hi‚ ÷heÅÿu_7(;ß<;~ VTýF/€,ýû+ýb`hh÷hÀŸ]X íÀ|õp“›s"5T¹ /€mpŽ©±6kÅqÜ0pÿe_ =ÿ³s6 8]†Ùq,–çðT½`(ÕT¾ào? mpº”Q‘‚püûh2y >Ï[+è Ž°½\0ýTDt€(ÿ: µŠ ç €û²q¾EÁihúfð=¿X]Œr_7#áÀ_zu |ÀHt€3µˆüRD÷+ pöhåçà1ŰÎ3ÿuwumUýÿVUsw_uW)€ß3¶ËP€Óq% €@ì¸AþA X÷f»+ö‘]Y*û eÿz|||Zu?tjT(Z1!€Ù6ÛåQ5Ös€½³+* Wùf+d$ 0 Ðÿwz|U 7ò[21§.à B <¾­S6(çàhf$}~ ñþöpûXuusO[+´!üV°Ûç€+7p %f×PðPÌ )Àý#¹àty ý]Þ¯;Yxž Ž°—À  ‚þx Ty~×**Û p$ž€@ˆ iX€OÂß(cf#w ü+]ÿp’:p)àÿ<(*ñ[TƒÀ> ¶Q7Î`ÚÒP3Ià4°?~à¡X5Z£) *TUZÐïVTøÎWTB~`2µ™“¹i‡àýA*0ÆÀ¾ªbøY'ÐÿýVùT ¯< u7ð<©TýU“€2¶˜Í·Pii`,¢*ú•À¤pab]Çm øùE°YE ™°@Ó³ à|À—WS $Ÿ •’J p8Ø1 ÐPÌb(a`Ëe:ÑdÞ  K;prÍZà•öѰwÁVT9—UU“àC­àáÿühýf/wf2dZÀÿ]js/]]ÿo~+5xx!½€ü¢_Y‚aÙ18 ¼pZ”€ýû€#]`+ýhV`³Ãà¹à]]kk Çáÿv (%ý?Y;Жý|Áa:þ”€ ihŠ‹Š÷‹Ü Š‹@žc6 ga<Ðÿýfü_ ÷b§ ek(ç'ñ:±|¾È‘YüX ¾¿ðTøT%ÊÀ!–`DÒC ¤qaÑ ~M üb  ¢ßYrþP Ú‹‹³;CErë'Á¨ bƬq ÀÀ‹ ím%ÂV}áWTQ¸SòÁ&‘&abû]óm–±X Ój°­×üPzàÿxoýrrooror• ¼CÀ PiY+¢@+wè"dÿÁûò°€Y]ÿ)YüX t ׳ _Zü 6k¿ðçUT[ðð ¿hýh¬Aö8³AAÐñ]z?PÐXXÑË_Z>ÀT‹€EÀ_[Î3 B ´²X@»dÄ€<$AÐϱ±.g±, <î~á_W Ñ€,ù_ïUT“€ }chPж$VZƒÿ6  fýfÿ?œ ±±Ï">$€€–ß_[VTRS€ßih„(ý?R ï&f/Z÷ ¿‚XVZv—aŸ^І` ß* 8³6 ßûfb=œmß+< @‘Ye_t}(Að[„!ÿ"jj³kk.à÷Ѹ'SB6ï6 WüdïY{« U&û|k–Ðjw}¿œ œ|À[ªúÀ H@ 0ràþÃ`¼¸¸%ý{+]`ž êµ&ðQd ûm ¯Ð[_ ü7} Åð_kÃÀµ ð À= f€fìvP'’‚°!übÿ])#'Xÿy}__õ'Û‹à $é £–á þP ûh¿ùfhä_cd Ü0eÐÇ ÌÑœò)p\ÿY$+_kkÿmssuz}}}¿m;BðT¹ppûsñÿ¸¾¾¼¾¸¸ÿ¶n üfÛö¡hf?À+dýdà鯂mÀšÀ ï#øÀ_[I÷7 ` ÷D•à¾.ßfõf¯ æœñórrpS_oZý(HT04!^XÀi—3àÕð'bZ[>Ÿ _ ñqr€"×õX pf`hf¯…µUð?h€bÿdü[ý}ª½6€ðaRŸ?û[~ñ ûfÿ••œ§©òfü+ IñºIð½'7‘5v¬ÃûÃð)J”€þ£Ðjmtuz|ÿŸ/4dÿýd)+ßbn ò«`;X¾7 XýV}p_øÀ[õ+yÄp7úà€6à8 jmÿ|•9fïûfuûbþbš¿ óY’°>ÿ8;;>XX¿^}ýX Û7÷uy t¿ýfÑfëd/¼Ášû}0‰ y¾‘ôV> ¡ ã1 ]Y]òbÿ‹± \b÷ ]²ð ŸY öXq •¦}à_[œë{ïÏ =Z¶ÿ57ïýdcÿ>± û°—²±¯ ÿ'Y XYþË  ýVîVÿ û[' ÿ }~yk­6K:TfûV?bfÿdïd ±<þi@?exÿô)Xþ0YXœ¯ÎŠsÀð÷* n±# ß)Ã`÷+*+Ü0 &]ÿq•³²ßee þP>—± ¯¯q¡Bõ*Ð1 0 *^¸Ð +<ì àП%1ýa" ’ò¾Ô“V à8÷a<3° .*þÐàz5ssÿ{~›¿X[ZYVNþ~!TV% __ëkuúyþ 777¤ðsul 6 ÿ7UTZZÿý[%ƒþ€bV ZsýyüZ%¿ su,L@±þàVY|šjÿýVV:ièÐä È:q bwTV‘!Ò¸aš\0ã ¶ŠP 7à ¶!µ! €º!³¶sÀ6ä0 „j>ä ¬7X"Ë Ò ¿²ýV Œ$TÝ6â!°ü:Våʃkó ˜!%úR2¯€Ó‘ðs,1nþ`ýVŠ82XV?0~.0>VúTl82½>2ËúTo@0ÆÇ5Pbt†˜ª¼ÎàòŸŸ(Ÿ:ŸLŸ^ŸpŸ‚Ÿ”Ÿ¦Ÿ¸ŸÊŸÜŸîŸ¯¯$¯6¯H¯Z¯l¯~¯¯€¢¯´¯Æ¯Ø¯ê¯ü¯²°¿)¿;¿M¿_¿q¿ƒ¿•¿§¿¹¿Ë¿Ý¿¼ê¿Ï"Ï4Ïí¿VÃDÏpςϔϦϸÏÊÏÜÏîÏßß$ßNË-ßVßhßzß3ßWϰßÂßÔßæßøß ïï.ï@ïRïdïߦߚï¬ï¾ïxïžßôïÿÿ*ÿ<ÿNÿ`ÿrÿ„ÿ–ÿ¨ÿÐïëïÞÿðÿ¼ÿâï8J\n€’¤¶ÈÚì0"4F&|Ž ²ÄÖèú //0/Wuf/x/Š/ZSÏÀ/Ò/ä/ö/??,?>?P?b?t?š/º/ª?¼?Î?.QÏOO'O9OKO]OoOO“O¥O·OÝ?þ?íOÿO_á?'_G_Y_k_}__¡_³_Å_×_é_û_ _B_1oCoUo$_ /‹oo¯oÁoÓoåo÷o -?do‡ou‡™io­Ïáó);M_qƒ§Ë¹ËݽñŸ%Ÿ7ŸIŸ[ŸmŸŸ‘Ÿ£ŸµŸÇŸëŸýŸ¯!¯ŸyoW¯i¯{¯¯Ÿ¯±¯Ã¯Õ¯ç¯ù¯ ¿.¯T¯A¿S¿e¿4¯F¯›¿­¿¿¿Ñ¿ã¿õ¿ÏÏ+Ï=ÏOÏr¿˜¿…Ï—Ï©ÏhÏŠ¿ßÏñÏßß'ß9ßKß]ßoßߓ߶ÏÜÏÉßÛßíßy¿þß#ï5ïGïYïkï}ïï¡ï³ïÅï×ïùß ï ÿÿ1ÿïÍÏgÿyÿ‹ÿbÿ³ÿÅÿ×ÿéÿûÿ‘ÿîïCUgy9Zÿ™ |Îa²ùîïunÖ ^ÈÏe±iNë=ÎÂþŽEÿ/5("4/”'/Qÿƒ¾_(roÉæ/ø/—/ ?{-¢/??>7Ó/;C3A? ,@8w?t:4Z¤7¥:^?¨?7O¯?%O*?{JGOOsOƒŒ?ž?”OæG[ÿOþ?M/_w_‰_XOjO|OÑ_U_o?¤OÖOÉ_ _OoÄN/_,gK_zo4oÄo ?Ôoo«oÛ_Fo9[Úlso…o'mþßoño–ï_d|`+VÁ^ _OÞÂÔæ¼MŸ]Ÿ¨gŸrŸtŸ˜ª Ÿ ŸÌŸßŸïŸÝž©ýŸŽ¯¯oŸéŸ“Ÿµ¯•mÆ>ØŸ¿žÜ¯ ¯Ð¯1¯h¯g¼ƒ¿v¯Ë¿Ý¿¼¿¾¯"¿%Ïô¯÷©¿(¿:¿ü¿Í9g?HÏŽ¿Z»¨„ÏßÏ£_pÏÏ&ßjω߹ÏtÏhߘÏß©ßóÏöÏòÏÇßYïÑß:ß²Ÿ^ßjï‚ßÍïýßÁŸ¬ïÜßÅïïì:îqí¦ïšÿÿ‹ÿï2ÿôÿ ¿œZÓÿôïíÿÇÿ*ÿ<ÿNÿvÿ }ÏÙëÌÿ|Ò_q1 §ÛKü¶³>?/+/¤/¦G/µ?h/c/±/q/€/Ç/¡.?/ãõš_\?n?BP/¨/Š?€?«?¦?ô?´?Ã? O>ËŒ#?5?R/œO®O&O™J]OAO_jÿä?óOA__ÇOw_×OåO–_†OZ_í_ÿ_Ù_¡_…_Go_(_7o…oIo o»o¸_)oØooo1CÅ_åoÉo‹lo{ÉŽOÿšm™Ž?Nu‡‰>a ‰B¶¼ ŸÊõ@Ÿ+=$ŸŸ¶ŸÈŸxŸ£ŸCŸÍŸ†žùŸ:¯M¯ ¯¯ƒ¯\Ÿ,¯€Ÿf¯íŸù¯ ¿»¯è¯‘¯ò¯£¯=¿ëB¯Q¿a¿Ç¿×ÿ8¿ª¿K? ü?Ï’\Ò¿®¿c¿û¿‡¿™¿’Ï¢ÏèÏ'yÏÖ=&Ï-·§Ë‡ßbÏê¯ßýϪÎÅß0ßW,Ößçß,îîoßGßLTDeïjÏÌï–ïºßTï!ÿpÏï¯Ý$ïÿ.ÿíïvíöß>ÿxpÿè åŸûïúÿ{ÿ/ÿÖÿÓï<^p›ÿ¿ÿßèOG¾Ï(¿ÃÕ¢µ'Ý(ÞC/X’/ F////*?7Ý/K?Ö/,/?P/b/t/¢/Î?ª/€?ݯ)ß5O™??vo?OFOß;?¢?°OðŸ_ _œO8_(^•OçOB_”_õè¹OÙ_Ì_VÏïºOmœ_oZoí_so†m˜o¿oŽ_?¡o#O¥o=õ_‹o,ÞoTœ®}ËÝß7&[m‘Kµ ÄëýŸ!Ÿ3ŸEŸiŸ{ŸŸŸŸ±ŸÃŸÕŸçŸùŸ ¯¯/¯A¯S¯e¯w¯‰¯Ño­¯¿¯Ñ¯ã¯õ¯¿¿+¿=¿O¿a¿s¿…¿—¿©¿»¿Í¿œ¯ñ¿ÏÏ'Ï9ÏKÏ]ÏoÏϓϥϷÏÉÏÛÏíÏÿÏßYŸ5ßGßYßkß}ßߡ߳ßÅß×ßéßûß ïï1ïCïUï$ßyï‹ïï¯ïÁïÓïåï÷ï ÿÿ-ÿ?ÿQÿcÿuÿ‡ÿ™ÿ´ÿÏÿáÿóÿ);M_qƒ•§¹Ëݬÿ%7I[m‘£µÇÙëý/!/ðE/W/i/{//Ÿ/±/Ã/Õ/ç/ù/ ??/?A?S?e?g‰?›?­?¿?Ñ?ã?õ?OO+O=OOOaOsO…O—O©O,ÍOßOñO__'_9_K_]_o__“_¥_·_É_Û_í_ºo#o5oGoYoko}oo¡o³oÅo×oéoûo 1CUgy‹¯ÁÓå÷ -?Qcu‡™«½ÏáóŸÀŸ)Ÿ;ŸMŸ_Ÿl™pr¿opNAMEl ÿINTRO_BM÷P_2 )}B™’¶:lŸ¸ŸÊŸÜŸîŸ¯¯$¯6¯H¯Z¯l¯~¯¯¢¯´¯Æ¯Ø¯ê¯ü¯¿ ¿2¿D¿V¿h¿z¿Œ¿ž¿°¿Â¿Ô¿æ¿ø¿ ÏÏ.Ï@ÏRÏdÏvÏ~ÄÁ~ϦϸÏÊÏÜÏîÏßß$߃ϑÏZßlß~ßߢߴ߯ߨß7ßEßï ï2ïDïVïhïzïŒïêßúßÂïÔïæïøï ÿÿ.ÿ@ÿžï­ïvÿˆÿšÿ¬ÿ¾ÿÐÿâÿôÿQÿcÿ*<N`r„–¨º "êü 2DVh=ßמ°ÂÔæø //y@ßR/1*Z/ƒ/•/a/¹/Ë/¤/³(E/ ?ø'?:?L??p?‚?[?l7û/Â?f?æ?ø? OÖ?.O@Ož?¯?vOOšO¬O¾OŠOâOôOQOcO*_ÎON_`_r_>_–_¨_‚__Þ_»_oo&oò_Jo\o_Ë_’onožoÈoÚo¦oþoëoýg‰oP,t†˜d¼Î©=à(:Lp‚^uo¸“ÜîŸÌ$Ÿ6ŸŸIŸìzBŸŸ„ÏiŸŸŸåŸÁŸÓœÑŸ«¯öŸ¯_¯s¯–¯¨¯„¯Ì¯÷Ù³¯ü¯É ¿ê¯B¿T¿¿`¿¿§?s¿Ž¿€ož¿°¿ϼ¿û¿Ï:/ô¿BÏÑ¿RÏdϼÏpϯÏÐÏÜÉ£ÏñÏÝ¿ß3ßkß}ßÚϡߧ“×Yß§ß6ß·ßéß!ï3ï߯²'NßIïCëï/qïƒïÛïï,¿Êì²ïÄïðï¡ï"ÿ4ÿŒÿžÿûë‰ûïƒÿ«ÿ\þêÿîÿFXµÿ~ürþ.Z Œžöe,eÿâb¿@Rª¼*&–Åñ///j//ã¿ëD/V/‚/¿´/Æ/?0? ?ß+ãí_ð_o(oùYDb2o=lKoAdpoBo©o‹oŸoßoñodefÍo {`o@N{“kƒ­‡ÑÂÖÁþô=8sM—acÃØäŸ\7ŸIŸñû]Ÿ(ŸÚžŸ©Ÿo#ŸýŸ¯·Ÿ3¯#¯:¯F¯²ŸT¯ÄoèŸÃ¯Õ¯®¯?¯ý¯¯é¯%¿B¸?¿&¿J”¿¦¿~¿Áo7¿Š¿Þ¿ú¿¹¿Ð¿¶¯ZÏlÏDÏ{Ï#ÌwÏ~Ï«ÏÖËÔÍÖÏÕÏ)ß;ßßJßP߃ßÌÏ_ß߮߾ßïßï©ßïnßIï“ߤ߶ßÇßÚßµïÇïUïÏ4ïÕïòï ÿ›ïŽï[ÿÿÿÿwÿúïzÿ¸ÿ0ÿ­ÿrÿ"ÕÿSe Òÿ­â¿s7ÂÿÈ+Ó·˜sè “’Ziçù¡ÍfþŠ//¿Ñ«/½/e/v/*/?N/q/+?„/–/q?ƒ??=?ð/Ë?A?e?f?¶?\=Ô?GOYO{ïÆ0E|OR>›OœOOé<5O_"_.™O¿ÏO&O0_×OéOûOÖ_è__;¿V_Â_y_‹_9oÿ¯1oœo®o÷_–ßo×onmüoaoÜoöo`r»oOº¬ç'9³ƒ8J´»O€ Ûíÿy$þŸÜæ&ŸÑÄ_Ÿ?ŸtˆŸÄŸÖŸ£Ÿ®ŸìŸ¯gŸyŸ‹ŸŸ¯Š¯œ¯&¯¯²¯ƒ¯×¯Û¯Q¯Æ¯±?P¿b¿t¿¾¯x¿•¿¿`:¿~¿¼¿ª¿#Ï5ÏÏÏà¿}Ïå?Ø¿ê¿ü¿ÂÏéÏûÏ„Ï˜Ë ßÝÏÍÏUÏ8ßÔϺϫ߽ßÏß’¥ßòßùß)ïþß…ßï ïƒï•ïÞßkï@ïžïïïGïJï\ï!ÿIÿ[ÿ*ÿ Ïqÿ£ÿíïoÌÿœÿ4ÿ!©ÿÎo6¿²ÿÄÿÖÿQúÿÕçùc °aþN¥àÿ>¨º$uÐ/X\Ùü’m//N/oìe/¿Ú/AÃ/X/3?E?W?¡zß+?è/ ?ú/y??—? OO‡?w?Š?(O!¤.Ò?eO¤OIÉOÛOoO¹O5/_òO‹OžOD_o__¡__>O/Û_?_Q_ñ_u_4oh?go¯?ˆoá_-oooºo¢o-É_¹_åo‚XU{iÙEá˜áoH‘.Af0ë Ës2ƒ/i{-Ÿ5ŸZŸÑ‘ŸçŸHŸ«Ÿ½ŸÚ–­oüŸÅŸ4¯xo`¯¯~¯o¯M¯°¯œ¯Ä¯Ê¯í¯._&¿½ý¯ï¯ü¯>¿¿N¿Á¿¯¿_¿ê¿Û¿Ï-Ï?ψ¿cÏuχϙϫϽÏÏÏáÏóÏßп)ß;ßMß_ßq߃ߕߧ߹ßËßÝßïßïï%ï7ïIï[ïmïï‘ï£ïµïÇïÙïëïýïÿ!ÿþ*õpropNAMýEÙ INTRO¿_BMP_4Nð ï/FWòà6*ÿvÿˆÿšÿ¬ÿ¾ÿÐÿâÿôÿ*<N`r„–¨ºÌÞð&8J\nà€’¤¶ÄÄêüÒÖ'/9/&/&Z/M'r///Á/Ó/y/¹/å/ö(7ò/é/=?K?x?Y>ƒ?­?…?f?È?Ñ=ï?Ú?IO,OYO|/}OOgOIOO;ÐOyOïO__?_rOc_u__?«_ÞO“_†__Í_e/K_;oMo&oolo¶_§oÚ_²o¢oÐlÐo1o"4Üoú?joëoD–|{—x”J?¥XJ=ô$³{oÖ Úì|Öƒuo(ŸÃ~úŸEŸ˜_„ŸvŸJŸÉŸZŸ´–to¯¶¹ŸßŸ²Ÿ$­‘Ÿo(¯¦¯¸¯Y”¯¯ì¯¿¯¿ãŸ<¿¯~¿¿:¿Õ¯¢¿Ä¿x¿Ú¿º¿`¿S¿6Ïê¿hÏù¿EÏÔ¿œÏ¾ÔÏϧÏIÏýÏp¿@ßRßß—Ïcß»Ï¬ß ß€¯ÒßkßЮ¶ß)ïºßøß•ß]ï¤ß9ïpåZï±ïúŸï•ï ÿ™ïF¿uï=ÿ„ïÿ¨ïHÿ2ÿÝí9ÿßÿñÿœÿZÿK~ÿÏÿq´ÿÆÿ·ÉY ²DÚh>ž%¡³]×ÅÌßã//“Iц/˜/n/¼/A/Äß«/‚û/[/ò/^?p?,?”??¥?ë/ý/?¯?Š?H6OHOŸ?-O[OoOÃ?ò?ç?‡O¼OœO‘O _2_ìOV_ÛOD__¥/”_ãO±_Ž_ø_ o`_í_os_doØ_©_IoÍ_]o4oâoôo¿oüooÈo±nT¤o1/O¹Ëªá4Mj >2£µ“^oŸõOxŸÐyŸ‹ŸŸgŸ£ŸôÒŸØŸ© 8Ÿ¨ŸøŸæŸ_¯q¯õŸL¯¯¦¯Ë¯A“¯"¯•¯‘¯7¿I¿[¿"¿d¿y¿¿—¿Ç¿œ¿n¿¸¿©¿!Ï3Ï´¿ ÏÜ¿hÏÏÀ¿Ò¿µÏ†ÏÏùÏ ßßËÏ(ßtÏRßYߪÏ^ß3ßzßqßãßõßtßÌßžß*ïOïˆß6?:?¸ß“ï»ïÍïßï¬ßëï6ïþïïïlï ÿ÷ï¢ï“ÿ¥ÿ2ÿ{ÿÿ"ÿìÿ¸ÿ#dÿ+œQzŒ ]n»Î×…o8Kô5_q(?ÁÓ±×½.é/B/T/+/)/b/‰/®/z/ó/ª/ï/?,?Ë/?:?•/^?|?Q?œ<í/¨?Õ?¥>Oç?%Oš?GOD?F?!Ÿ‚EÌ?ˆO³O+OåOµÇO]OÀO/O‘O‚_·O_)_½_v_ä/š_3_$ogOoâ_AoJoo6o§o_oŠo oo/oñoÚ_ VJeÐ_DrpæÆß½w=“iMý‡ê_œ–  ŸkAŸ-OŸ4Ÿ‚ŸrŸŒŸ~ýðŸMoÿŸ¯¼Ÿ¢ŸïŸ;¯j¯{¯¯±Ÿ¡¯§¯Ê¯ê¬¿0ŸR¯#¿=¿g¿K¿‹¿%»–¿™¿v¯Oæ¿t¿Í¿¿;Ï Ï1ÏqσϕϧϹÏËÏÝÏ-ÏãÏ÷Ï%ß ßIß[ßmßߑߣߵßÇßÙßëßýßï!ï€3ïEïWïiï{ïï*²propNAME*°ÿ INTRO_MÿUSICMIDI¯Àâx*°ÿÿXïÿY*°ÿQ¿ûÿ/*±:ïÿ!ÛàTÿubaÀ:°ÿ° <ÿ$d$‚Ký+ð+S*dÿY*+d‚gù+ÛàåìBassïÁ ±ýà± PÓ‘ÿþ?ëæHornÂ<²ýàÿ² x’Ddÿ`DCdhCÿBdB{j?ð?j<ðõ< õCëåTroÿmboneÃ9û³ýà³ (x“ý8‚ð87dhï76ð6jÿ3b3j0¯Y‚g0 õGëåÿTrumpetïÄ8´ýà´ dÿ”Hd‚IHÿHdhHKïdQKwHÿKdwKOêðO õEëåBrÞ3ñÅ=µýൠ÷Z•œðI<¿ßdKd;+Mdß;M>oOÿd;OQd;ýQdñAdRdÿ;RTd;T÷Au\V\§‚gV§ñã䣅 2_Ç0·ýà·?ð™—£•ðo?ª-Jèu<B oBÿDdDÿFdFHdùå+JdMd%J&2ÿPdPM¼,/R!P_dTd9P,O]V]D2ëçÿimpÈ/¸þýภ2˜0hw00B;!UL"a"P"b!¯7j;76 <:"LV:"d;!tL"y:!¯+=+Z D^"Rª^"\^"d^"r^!7¯‚g7 õu<Dîûðs¹ý๠@ÿ™1E$Ywÿ$1y9G¾¨$9y1I¨(Nú´&¦ (E(ÿ(S((õ^á"iá 19u$u·#ãä?p?)?;?œï ±ã¿SPLSAMÈÝop2+p0g€ï€€„2€Š2~Œ1„0ƒ2Š0“1®•3€‚¤3~´0~~‹0Š1¡0‹1ø•:Ã2–1‚‚ñ€¯0¡2Æ2{‚€ÿ{y††{vÿ~ƒŒ–’›‰tÿb{{‚o[ÿuugo_]qÿijdVd„œÿ«‰‡™±Á§ÿ²Á¤®¶“—¥ÿ‘“„“›‹‚ÿ˜™©‰ˆuÿ˜jjr_bÿvd~zqbpxÿWa]O>9=;ÿBP^PQYRTÿ\W\_[eW]ÿdanyubisÿoptk|€‚ÿwzszz‹‹ƒÿœ——ž§«¥Ÿÿ‘–ž˜“…ÿ•›œšˆpnÿsxuozw}|ÿ„–‘•¡¬¢Ÿÿ°Ä«³¸½«­ÿ¶»¾¸¯´«ªÿ­¬§•ƒ†‚xÿys]erishÿu–¢°›¥˜–ÿƒs‡…ƒ•ûˆ“ü0z|lxwÿrŒŒˆ‚~}lÿ~nkX\[`cÿ\~_]]F;)ÿ+UtohOLTÿYHXc_Wewÿq‹yurrŽ{ÿqlR^k€l`ÿI849aisjÿ\cW]_`]cÿqr^u{~fgÿk€‘–ššÿw‰’£¯¾²ÿ¼¡ž•„š¶Àÿ×ð™§½ÏÁÿÌÛÃŶµªÃÿǺ¹¸¡˜žªÿ½¾™‘’}ƒÿ{Xo˜¯ŒyÿUXo{Œ„•ÿŒscelpeÿj^bXA?(CÿUlj]ˆzh^ÿbPihxoquÿkJE.In‘•ÿ}ZOv±“––ÿ–Œ‡º¥ÿ–Ÿ‹R_wžÿµ£ycbkÿ•ªÄ•‡UEiÿ~—‘z„”ÿmsv†wˆŒÿ•uZMk˜ƒuÿ{”y{€vaˆÿ‹yxy€„wiÿQVhvjgÿu‹ªŽ¦Žyÿnƒžm|ÿkS2_ƒ““bÿ\q^PPsÿ…Ž´°‡ko…ÿœ¢˜—¢mpÿIg†ˆ‚{‘ÿ|cqzt€‡`ÿa€€VGJvÿ—¨“anƒ ©ÿ© º¤§’¢¥ÿ§œ…{~kapÿŒ¤šƒ–~zkÿW/a‰µ¬}LÿSUcsto‘€ÿx]gM@fg‚ÿ¤¯ nTF8‚ÿ”¦Ð¬–±¦ÿ¡·µ™»¥¸ÿžjls˜¬£¨ÿ‘}ƒ®Î³Š{ÿx˜‘ª˜¡——ÿŒrzn‰ †›ÿ¾°›’}[6HÿޱœqVM_rÿhm€”—¢—zÿT!Oq}“•¡ÿ†1!?\aƒÿx…m]btbÿq]eniM9Kÿst}]knmÿ¡¨“’_[TNÿl„Švags@ÿ1\ÿl‹š”“eÿ:\µ —‘rÿ¤”‚{zSbÿd4ƒoVz‹ÿ„Š|`s €ÿw¾»¢¥‘š¥ÿ¯£|snA^mÿQ52‰ƒzNÿ%-EgàõÜŸÿ­ÅµÈßÔÀ¼ÿ¹‚f…£¿¸ÃÿÁÊß§[Bl²ÿØÊ«Žeb‡ÿŽqt†X?‚¯ÿ•}du†yn~ÿT;9ZThb‚ÿ‚€–‰¢°˜ÿx”—‘sPN=ÿf|q*#ÿw¡²ybns{ÿry}…U.ÿY_v•¤¸©¯ÿ†E9P±Ê¢€ÿUWkgg…mpÿTb\_Œ}ÿˆ®Ë›kVSqÿ““on‡¢²ÿ«¡—”¦tGmÿd'!PZÿ94Œ‹³åÿëæóêðþãÌÿ¹ª’¥“Š€ÿ¯Æ»†ˆaÿÃËÝ¿”xuÿuu†oocvZÿ5NƒŒ€Œ“”ÿ’_0Us¨­’ÿv€›§®ž„®ÿ¡””‡ˆk^ÿ]uwkYC.'ÿ~•jLs‚“ÿŠ}†syi[ÿ~zacŒ¨¦¢ÿ“†Uq¢·¸ ÿ†_[jmseYÿ`hŠrYN@uÿs™–’‰oBJÿ½Ê³…oœ¦ÿ –””†}rÿV6'6;ÿ% iÅ©“ÿ€£¬Åí߯¶ÿ˲½¼«£–ˆÿ˜±»š•stTÿpÔÓ „kQgÿwx€]mn¦ÿ‰_XL_„§±ÿ†„T=U©¹ ÿ€€~¶”h…ÿ³Ÿ…£«inRÿ?XlP;ÿ>¸Í‹dnTnÿ§¤¤œˆ~ÿ•{V~…ªÄ¤ÿywzDsÇÝ—ÿuvTi€zzTÿ`aUŠ•R^nÿbJ˜»¤—Dÿa²ÈÁ­¢œÿ¯²x|€ÿ}H6,_6ÿ-Yž}ÿ޶¡ÍíÖôÿùá×ȼº°³ÿ¬ÂÓ¿‡|tJÿe²é¥…yF\ÿ‹‰h]l`bvÿ[CYSEQvÿ{˜‹aZ–´žÿy†‘•‡viÿwp—¥…}aPÿ)g…ˆ‰Y6ÿ(Q‚˜u_^Zÿ`x_}•­œÿuj€s‹Ÿÿ˜eBO’É´ÿ‡sUs„Š“ÿž‰ƒwfVtiÿNi€†k„vvÿwyžÄ¾¬ÿ‚˜†pŒÿv]\&&9PÿZWP5t·ÿ–¥©ÂØËËÈÿÁÛþÝÅ©¿Ãÿ¾¿›™¤˜qLÿStš±ÁpOqÿsišœ™£¹‚ÿmnbXRq~pÿ{kG\‡Èÿ³”“Àcw‘ÿ_]‚}UhrWÿV]s—ŽiÿfQ_¡”l[…ÿtH[yiaš›ÿŽ{‹–©Ÿˆÿ‰™nANCNœÿ¹uGSVeuÿ•ª²›w\]ÿf…‚hr‰q]ÿNL„ᾓ¸Äÿ­“““„}…~ÿnWOE64ÿYQ@W-?wÿ‚¦¼¨¸¿ºÿÀÈÛËÍíµºÿ½Ê̽©œƒ–ÿ`(X—¯ŽeLÿLjq{—µ¹ªÿ¨ƒ;bŽo[€ÿ€rƒxQ;X¹ÿÕÀ¤¼ „iÿw—†_peYRÿQ-5ZmyŒÿyWk™„r•™ÿP[nfpŒ€„ÿœŸ›¨”˜¨¼ÿ‹ƒ‚{l46pÿ“¦t;>lkiÿŒš™Âºm\dÿvlWjmvˆoÿY?]ŽÇ覜ÿܰx{‚Š‚ÿwhPKP.ÿM:?IN57Mÿl–®š˜ ´¯ÿÁÏ˽ØÌÄ¿ÿÀ¯ÍÏŸ‹–ÿ^Q?_©\ÿHkv…‰’­Íÿ¾czpeZdÿi{†my`SaÿÒ뫤ÕÃt{ÿЉƒq{vR[ÿOA,Fj‹Ÿÿ}—^]€ªsÿhlj_rwzÿœ™œ­‘ƒ¸³ÿ‚€¡ŸhL@3ÿy‹|SI6 ÿ"ZuY?I6ÿ@‹¢‡†˜Ÿ¬ÿº§¹áÐÅØÒÿ¸¬Ã‘”­©ÿˆa^Ki®’{ÿ_Yb”£š—£ÿ½˜y‹yv|ÿm~˜hw|WFÿ‘Ÿ–”©—ÿ«ƒŒŽ~ˆ~ÿ[MD)9”¬™ÿŒ‚_GIªŒÿ}~ƒ~xpj‘ÿŽ‘˜ª„w{…ÿŽŒ žjYFÿc•¯oHH8wÿ­‘{Œ…€ÿrrkmxm‡†ÿjrZ>_¬²’ÿƒƒš›„z‰ÿƒƒ˜zcKÿBd^Q8$ÿ&h‰„´ÿ¨¼¼¸ÆÖÒÌÿ¾žŒ“¡­³Ÿÿˆ‚aVT—É›ÿa@Xލ¦…“ÿ•’ž‘ƒ|x|ÿˆ}yŒƒ|_Mÿh”¼¢€„š­ÿ›‰~…€†—ÿˆlG2y¦ÿ“zvQS}®Ÿÿ”•~Œqyytÿ{‡ª™‡ˆ\}ÿ~¤­™‡‡vLÿ`y­¨_5.nÿ‘‰x‡ˆ›ÿswq~~oo|ÿv]UN(ÿ OŒƒœ“ ”ÿ’¥«£²´ØÏÿ³œ¯Ô´ÿ|˜—j[cªÆÿ€K8n”ª‰ˆÿ‘Œ‘·“gs•ÿ‚ƒm‚nnQÿNfŠ¢Žyÿɘtr•“ÿ’a>'>˜šÿˆwcDq—¦ÿ–›ž{p‚ƒÿ{«–twhÿhŒÅ©ŒŠ”wÿ][‘½­\APÿŠ €ƒu®ÿ›kfˆu|ur}ˆ^[REzÍPÿ]’À¦mpŒŠÿ–†rsZ%ÿDkeaT!)Lÿk†„„‰›Šÿ“›œªÀ»¥µÿ£‚q¡Ñ»¤Žÿ€|^xœœfÿRTl‘ ‰‚uÿ€—–‡yo~—ÿ‹|…“xtuYÿk—ŸxJyª”ÿy}fn‘“އÿ€VBHf„¥—ÿ„\bs‚¯¸ÿŠª“€{‘ÿ˜‹€•xU„ÿ©¢©¥~tvÿ €|j@nƒÿ’ŒŒdb|xƒÿ}hjs~‰|nÿˆ†Šm‰·—ÿg}°Ž„’YOÿn{|}aST<ÿJdŠ–wjTdÿU‚Ÿ{€ˆ€ˆÿˆkk¤‹‰ÿ§gy¯Ã¯µÿ …ƒ|tÿi5>c{vz^ÿTX[]~wy…ÿ˜ —€|”~ÿk•¥`p’¤ÿ——iu†ª¢ÿ–sUA9v¦¬ÿ¤’pnjv“ÿor††er„ÿ“‚~™¥¨‰mÿ¤¸¨ˆxTg‹ÿ™›“qlGqÿ™ Ž‚q„ƒÿ™ˆއ‘xÿ{€“g[ZYFÿ3:Š©‰„~ˆþºPº–ŸyeNeÿ ¢tn\RIIÿfmptwƒ„‚ÿjrˆ•¦¼½¦ÿŠ„¥¼¥…xiÿX[bqrgZQÿGw‹µ£lƒ‘ÿ˜ž¬•^JEuˆ™€„uv†Rðÿ}k•œ™‹†ÿwx„“‡xeUÿ>s¬4'=ÿFf›©•„xƒÿ‘¡¥›¡ÃÁ¦ÿ¥Ÿhg“†‡‹ÿznNj„Œ{zÿn7:xÑ©ÿ»§”|ž’ƒoÿflocxSgzÿ•…›“ˆ Éÿ¨ÀʘvOLVÿ€~„q34b—ÿhQ]wT]rxÿyˆrx‰®¬–ÿ´¥¢¤“xjÿqgWs›–Ÿ™ÿl‚„‚ziƒÿÊÊ”y„rlsÿb{™…\e[pÿ~zn`_ljzÿ©±ÓÊž”އÿ}SbjiJAHÿ8C€•‡|q—ÿ›Žr—µ¸~Jÿ0:Qƒ‹€yˆÿox{g‹´»­ÿ› •—œ‹‹ÿ|O`|ƒ‡Uÿ6TF,Gˆ©ÿ¯™”wŽŸ”™ÿ¸Ë²¥–tn”ÿ|uoanˆÿrfy‡bOSWÿv}Š³È¤‡‚ÿ¬•u\eqPdÿm‡ž—–¨­‹ÿ¿¾±¢§‡ÿl74R`rƒÿfx™Œw—œ­ÿŸ§¨€Šÿ”‡Œ ¥¢Œxÿl5.K`E5Wÿvˆ©lsˆ‚ÿy}¯Ì©uŒÿ†j[eq}ZbÿYksef||}ÿƒmp›ØîÑÿ˜•v`PI?ÿVPB8d‹’ÿk}“œŒƒ£Äÿ¥‡odSAKSÿrŸš‚‰}o¥ÿ¹±©¢ˆngaÿz‰ŒmqW`oÿzbHLS@'.ÿ>’–¢¯§ÿ®ÈÑÐØÐÇ¢ÿpŽ™} …aDÿIVmckp€sÿGVannžÉÚÿÁ½°¬®€E€ÿw_Qf~n…¥ÿ¡‹‹Ÿ½Å¿¤ÿކ…o\K<ÿLbHYgaFoÿt‚†œ¥«´–ÿyˆ²´®£³±ÿ½¥€][ecdÿV('Ti‰©ÿlzlg›®ÿ~š}l]fiÿgJ8[|‚•ÿ¬ª­3)UÿÔûüÉ•[AÿIM;=O40`ÿtX}}Ž’ÿ{ »½•މbÿ]k±Ã»i0ÿI^‘Ÿ±žŒÿbzŠ„œ¼¦ÿµÄ”`nr^ÿ8 %0`s÷zjY Dk·ÏÿÇÏ¿¢“~sÿoK:v‚p|„ÿšš’§µ†|}ÿtv†xiW)ÿ+=c€‰haÿ§nq—†“˜ÿ”€–§¦Òè¿ÿ™…‡te‡Ÿ^ÿ:!\›²ÿ·˜˜‚v¹Õÿ¬ «°p_kRÿ[IGDS{¨ÿæá§Še5ÿÝÔׯwY`WÿYCB53D(1ÿs¦§ÂÌÿ®«¾Ï¿´ŠÿcHx„bzˆ|ÿ_|¾–’bXÿ`e]b…¹ÿ™h‰»¦‡š´ÿlNW%DS‚ÿºáÒ¬Þè²·ÿ­¡Œ¢½“ocÿ,&&4ÿ>siDr‹}YÿU…“¿üßÁÏÿ§šŸ”kHyrÿNW]w„ ØÃÿš¨eœ €ÿƒi6-cÿo[W†”¬£ÿ¡ºÆ¢¦µ¼ºÿÞÍÁµ‚rdtÿ{kb&ÿh•£•‰{mÿ«µ£Ÿ”²±ÿ‡n^Y]‰ÿ”„§ÃÝɵÿ“|wr–µ·ÿ²‰lƒˆ‰1ÿ,8hZ{°ÿ¢¦”‰¥«ŸµÿÏË»O?<4ÿZPqƒ„…‰€ÿ‚žwv »®ÿ Œ†’‹ygÿq^j|P1;Eÿ V’ÇØÍ´ÿÑÁ¨°¸¶ª¹ÿ¼‰]JS0%Nÿcew_k—™¥ÿž‹t]Jgcrÿ­¿¶~ž£›ÿmHLYIUleÿYuŸ`RUÿ‚˜¦ºØ¢`<ÿ84ji}ÿi•¢”›§ÿ³Ñ¶ ÜË·©ÿ˜yJfpU$ÿ # h¤Äÿµ½¤ÂËíË­ÿȾ yYTRJÿ+GjjP}¤£ÿ°Æ¶…pwnYÿjc|±º˜pžÿ“fG?2|†ÿzx–§¨¤¤’ÿ—µ¿ºïñÉØÿ]C.H5>Wÿllhegl‚wÿkŽš°¤{€ÿÉÓˆ€vaqlÿ:*SY=DR~ÿ«á͵¿³¼¥ÿ¦w”§{RQ8ÿ1$,Twtÿry»×¥…“ÿ‡{QfÈÜàÿ­‹Ÿ‘oY43ÿkXcau˜‰Zÿ^m_cŸœšÊÿÂ’[]S5",ÿPsކ]¬¥ÿ›°´±ÆÁ«°ÿ©¼°«xugÿXE* )AÿDn›—°É¶ÿ±Ä¶«»œ…ÿ‚dbslZƒÿs¨˜˜¸Ó´™ÿ‰tNK_o†ÿ›©¡rQ6ÿ.=6euv§Ÿÿ—’Š•›ÍÒÅÿçð£ŠL9ÿ#Y€Qgq÷€~‹Y0µ¶È·ÿ ­«¤‚Refÿ;A'=tq[ÿ{’¡­Î¶´ÿ¶­ž«nd_ÿND?>&alÿf‹ ¢¶À¢˜ÿšzXM8PÀÿ¬µ®¯{iLRßC@B_tÓ@owÿma~¢³ÊÇÿƾšrQ-0ÿ_WPv†ª½ÿ¯§¦‘|²»ÿš®¥œœ‘_hÿN"E44?Urÿ^k“£µØÛÆÿÃÏÏ®‘™{‡ÿŠllZ=.67ÿWo†±¡®¦ÿœˆweGW…­ÿ¿¸·¯šuWD¿=@=‡Žà“ÿ¬†‘®¤®À½÷˜ŽŒp,DÿOXz­½°°ÿ­³³–œ‘‹§ÿ ¶{V<6BÿMOAM\vp}ÿJh³¹Á° ÿ¡«¡vpxzzÿi]]dt7/Mÿp‚¬¯¬¬‹yÿbaUQt¢ÄòÿÝÅiST5+ÿ6`shwiapÿš”®¾Úþïÿ²§¯–o/ ÿ;l˜‚®ÿ¬±¼Ñ¤–£¦ÿªª²¡¨Œq*ÿ7>7@cw–ÿ´Žfeƒ·È·ÿ¹¬¥°—rƒˆÿqqjleP`^ÿ_o€²¸ž³¤ÿ„g__M&:ÿJi‡£¾àêÍÿĽ­‘v„oÿ^O\Š’Œw\ÿh`TMWnd{ÿ˜Œœ’•œÿ¯ÌÉÊÊ×Ì­ÿu ,I# *ÿ®® ’{ÿ“˜ÃîíÍмÿ’”qN;J4ÿ+?‚ª›­àÿᵊƒ‘µÊÕÿ­€Œq92IDÿ3FR˜¤­ÿÜÖ¼¹–~wÿ”|„„ˆxiGÿ2/C@KG+\ÿ ”£”bJÿX]|§³³ºÖÿ¸˜’vnXDAÿ:0;DV`.Cÿh†±´´»ÇÏÿÀ§•†sT77ÿ+5A]€ƒšÿ³ÓÌÅ¿¹¹ÿ»®ˆ[9@Uÿ€^nTCHM^ÿƒˆY‚¼É¼¦ÿ§®¶¡™£¤²ÿ§‹ši]WÿA6N…°Âœÿ‡‚q‹À´²ÿÊ´–y~dgoÿT477H^“¶ÿ°ª¥ ¨šŸÿ¿¶Á½°xTÿB "1/8Oiÿr¦¯Â®vNOÿ‹·Ô±¤ŸŠ^ÿMHDA&5dÿ¦£Ž˜›¬¬¡ÿ„Š{}moˆuÿ…›† œ‰q\ÿB>NG^smÿcB,_”Ë×ÿÔéû鴖ކÿjC1(#!3Uÿ‘”Љ“¥ÆÿÍ“yU¶§kÿGPaV2998ÿI‹¯Êøýà±ÿš˜¦›¬ª °ÿYGY\LQZÿJQ~z_Wr»ÿæÑ¨›–w~ƒÿ››™–¬ž±ÿ }mSRR]Qÿj’”u|okmÿvupf Ã¼‚ÿgŒ®ŸT171ÿ-=^u„’¢ªÿ¬ÆÏζ°½ÈÿÁ’nYK2ÿG†™¯ÇÿǤ‘›ž´–Œÿ““‹‰†Šmwÿrtgav¦‹’ÿŸ °…i8+ÿb–¬«•‡ƒqÿep}' Gdoÿhx‘•­®šÿŠ‘¿ßÙØè÷ÿºœtI\j–’Œ«ÿˆ`‹®‡ƒÿ˜©³¦™yfÿN)>wˆ·ÿ¿ÇÓ§¦¤©Àþ± ‚fQRHKXÿU:+9]|]\ÿ}‹œ¤§ ˜”ÿ¿Ç¯€r‚~uÿ‰‰fGHG?ÿ_”£¦¤“†ÿ ¥³©w¾ÿÅ”‡rJ_F:ÿ&/DK'4lˆÿ‘}|•µÏààÿ㸵³§ybÿgHDFdvEGÿak~’›«•–ÿš‹¥§sZaÿZz‚klld„û“ŠßÁ™l„ÿyl{”¯”ÿ‚jƒ¦‘u[ÿ'3Hxœ‡O1ÿb—¤|Œ¨Áÿµ£‚›©—•uÿ[hv`\n–Ÿÿ’sV$)T–§ÿÃÀ‚qusŠ‚ÿkŽz••uTcÿ„–¶¹ ¡¯¤ÿ{fm‚wX:ÿ%q¦‘’rWjÿ©¬¬¦u_ÿaW17ž¼ ÿmi…ƒ®¾£œÿªŒG=Po–¦ÿ–|Tu‘ƒkzÿlw™Ÿš‘ŒŠÿƒaYiy‚†¤ÿ±‹dxO5_kÿ“ÈÒÞŸ~ebÿnŒ’u‚‚yÿfw{y•ŸÆÏÿ©›€xYAC.ÿ$~Š…¶©œÿ•‘”»åÉ×Áý~½ W\‡‚~`ÿ]d_cy±­ÿ‚_URYj˜¸ÿ¤¬¾rŒel¿”Žƒv‰‘ cÿ5YSi—°·ÿ¬†M5 f¨­ÿ¯¶œvNP[Tÿ")—}‚tuÿ©¤€ž³ÂÙÈÿ®–mMV@ÿA‡”{j|]}ÿm”°£¢…vÿŒ¥ž—¨›qfÿk~‘p\`Qbÿƒ]61_|‰ªÿŽ´åÕ³º·ÿ“Ÿ¡vuSMÿC:GKILItÿkƒž¨¹†h˜ÿ«ÒùÔ’j\ÿ^\sqisÿvxqu§ÄÀ²ÿ¤©«­•œŽÿc(_}‰hÿU_rnr¡£„ÿ°†z}ÏǦÿ·”–¦Žpy–ÿƒe?6\ÿ§£¥ZbŽœÿ¦¬Ä¸À¨}rÿŠrmeJL@ÿª¦‘c^lkEÿM³ÇÊÌŸyÿ£~‚ŒˆX4ÿ'3B6NXl{ÿ‘˜…•¼¾¡“ÿZq¢¥·¢Ÿÿ|`l¹œf]CÿMi~{‰•ÿ]:3n£¬²®ÿ¨¦“’m..]ÿtž•—µÌ×ÿny|†½ºšÿoGi‰w¢˜ÿ »–tm_XXÿ= j{‚™}ÿ‚žš‚g‡¡êÿÿö¶›’€byÿ…zdP^oXÿbUSQ$+;ÿY¦ÏÒÕ·š›ÿƒ9M“’wSdÿm~º²Žzozÿ}ˆ—›ŽˆY+ÿ7mˆšœ¿’yÿƒkTCf„{gÿVfoRhÿho’ÊÕ÷ôÔÿ§U;/Peƒÿ`Lntbaa|ÿ|‚¯›‹_‹ÿìæÆ |w€ÿƒJ46*>ÿÀб¹Ô™‰ÿ¢ ‘›³¬{ÿev]QodWFÿWe}wg{yUÿFUrŽ¥¼ÝüÿëÊââÌ¨Ž¦ÿAJF('DLÿh`Xrxj…“ÿ•l…„c')Œÿªªº¬¥t?ÿWv|~§£‘—ÿ–³£[cˆ€ÿ™¥˜}qIÿ*]OV~t]ÿqpek„Œ­¨ÿœ‹ª¹ÄÑÞßÿ—› wxMÿ Fn³ÿ¸˜¤«¹“¦¾ÿÉŸ‰—f(Jvÿzx_†o~ÿ›¡Œ™ž·sgÿhfm¨Ã«¦¨ÿ„‰ŠVYnk2ÿ*ZnNe€†£ÿ¨¥¨¸²£¹×ÿĂ𒉝Åÿ™ƒZ4_ÿ`†‘Ÿ¥w}„ÿŽŽˆ¾Ë“¡¥ÿx‚…X!'ÿÜâ¼ÈÄÆ¯ÿ¥‘š¡wcVÿM^Z~z‡‡Xÿ:@AI\v4ÿ)Qd–éñâËÿü®åîÀº¨ÿ™ƒ~yAZe@ÿ$I05Gy›ÿ‰j, ?•ÿű£¢†r…ÿiYpo>AqŒÿµÏ¸ÄÐÅ‘†ÿ¢“ƒ[2CÿL^‰”‹cOÿ\k|moƒ‘–ÿ¨¦‡’ ¢£ÅÿÅÕÒ¶¦¤Å®ÿjR:Ru}ÿˆŠ¥Ÿ¨ŒYfÿR6GŽrv‡ÿw{šˆ†‹rÿagyx€8Gÿ›Å²ÇÚÄÜÑÿ¾§“‹±Ë¨Žÿo;1'Djjÿ@D¬ÇÇÙæ÷ÅzÛ€w“pÿM^4!ÿ7t‡‡’Œ€¡ÿή“…¸µ·ëÿ໨–P;BKÿ77bÿ§ßç°²´‘yÿiYu¤Ÿ}sÿd}µŽbCS<ÿMœÅ|ŸV0ÿ6k’¼Ãœ–Ïÿ¹€qœ–pxuÿJ'"3jt‹ÿ¤¨ˆŽÏϨŽÿ»•~¡èá×ÎÿzVIBND*ÿ%h†qa– ÿ©Í–Ž|ŒÂÿ¸Ÿ“€[Urzÿd[w}l˜Ø“ÿu§ƒ}m–˜ÿŠqq–´p„ÿŽxn—iF?ÿH;g–¸É³ÿÊ⸌—Ÿ¶ïúÒ—¡õð+cAÿB';a76Œÿ…gi`Fbzw﯎¡FP™¯©ÿww€_\µâÄÿ±Â¡¡¥ˆŠ“ÿ…|qŠub„ÿ€’šƒkO ÿ9o`€’sŠÿ¢™ƒ¬zgz‰ÿµŽjO>%0ÿ, %3OXÿTmTf€v}ÿyQn”—ÿ†ˆŽ„mrS6ÿL~­ˆ• °ÊÿÙÑ»ÌÀª«¤ÿ¡¥‹{c„uÿqyH V{tlÿ‘•”®¡§ ‘ÿ•²Âßùÿê¼ÿ´°˜†©®ÿˆ„wŒ”‚Ž˜ÿ’|tŒvV~šÿ©…†„tº¬·ÿŧnr_Mfkÿ„{l†vmwoÿ›™›€œ‘fÿs…~]][I(ÿFdÿYvŒšÈÞÆ’ÿ”¥ÁÒ×°¨¨ÿ¬ˆ{Zx_L:ÿ@JQ0(=s£ÿ´ƒ€…„‰•˜ÿ¤¥¦|{€Ÿ‘ÿ·³{XqxSZÿ{nvb_UgfÿK(%j–Ú÷Çÿ¬½¬ª˜xhTÿ9&)YqVTÿOEi¿ËÀܬÿ·¿°Ùؽ‚Rÿa—±—cgdiÿzqh‰ž°¶ÿ¯ÂÀΖ{—Ÿÿ¶Íѧ–½‘hûˆ-9iv€ÿx[kNev‹™ÿ”‹€~‚‹^ÿjX^_RIU[ÿhZ_=R{gLÿl|¾Ø­¡hrÿ‚rЬ‹mPÿqUIQB!!ÿ<$#2=,':ÿr¦ª’Œ‰½çÿæèﺢ™±ÿÆž^>7*2hÿymŽ¿¯­Ç¶ÿ¯£‚o¬À¤šÿv>Foq{ª¾ÿˆr½³¥„^ÿ8;¢¢ˆ†‡ÿƒ}u|¡¡Çÿðè·°©@'ÿ)Gagg¾ÿÄ­œž‰¨öØÿ»¯ª”¡|TCÿ !ÿ:hiofv±Þÿá¸ÃØò¦}Žÿs™·”x|¿kxO_P2H€ŸÿˆZ?Qmokÿzu ÇÛëÙ¯ÿUIbnXT`ÿur€k€‚‘ªÿ¤ÁÔ£h\ÿp€–“^-nÿ©Æ±‰œ­xoÿ•¼£›˜“ˆÿ—­Š±Ó¶ÿqib5.Of`ÿ5 #f‹•Œÿ«ÞºÃÔ¯ØÌÿÆÁ›Úš™rdÿdŽŠfjmcuÿtƒbRv„i_ûcfßpxO€„wÿv‹³–•Ok’ÿ€NU„^($$ÿHATos‰ÁÿÙ®cZ’±½—ÿ—¹~[Mf]Iÿ' ?kOižšÿ‡¯»”Š£nÿ*H&ÿX›¬¹³À¾µÿ·­§¡“‹‘ÿ{–jqÅȬÿÝëÚËÙÐÄËÿžmG/) ÿY™ÐÀÕ×ÃÿÎ×Åǰ§­†ÿƒ“ŒUC5=ÿj‹¡¦’ †|ÿ¬•`P@q‘”ÿŽˆcY¤¯²ÕÿÇȦŒ~ŠÿsB$7CWgUÿ.@12GBC:ÿ5hÅõþüÀ•ÿ¤lum?8@ÿUUq‘ £‘œÿ ´¥Ž†„ˆ©ÿ„}{F$ÿNy–¯™ ÿ¿ãêÎÙþæÕÿÊ”…­‡VmgÿKV_rƒ¯¡—ÿq£Ê¸„”xUÿ‘°“‚‚td^ÿT;niF:{ªÿž¨Áئ–}vÿutІr™ª—ÿš–iEaX\–ÿnOP>+4VVÿkaŒ”‘Ĭ†ÿ çÜäü몮…iu#TÐÿiŒµ¿©ÜÿÀ›ÂÌ¿ëÏÖÿÁ™¨ÃÍ·€ÿhu—”··yŽÿ~€€7<.Eqÿšµ»¿zŒ¦•ÿ¡¾¡pS1 :ÿ-(QIll‰ÃÿÉœ¯¯²ÖǶÿ¹¦‚xœ­°˜ÿPfLGRW'ÿHq‚w‡šÿŒ¨ ˆ¡¾¶´ÿ·Äj~~šªµÿ Ž¬»xo€¢ÿ‹­„„¥†oÿbiNbZ3/kÿ‚`-ÿ4BSaIu|ÿpެ‚’̯‘ÿ¿ëßÄ»¾WÿnzW uÿ ¬Ñ»ª§†rÿNgiYks„uÿ£ž{t¸¢Œ˜ÿˆj^98O\Pÿ779gfxÿ‘˜¥ÅÐîîõ¿È”r‚^7 ÿ`rph†š½²ÿ£«¦¤mw°®ÿ©Úëˆg`-ÿVNCQ<;S[ÿlu—É­t^P÷W|±ý𖔨¥ÿoŒ•rc[ÿEFSburÿ|\‡²«ªîØÿ¢—¦–zz]ß>TGò` 6ÿk¶Æº¾È½Êÿ¸Ó¬ÁýùÛÆÿÅ®‚š˜…|ÿY1JUoZoÿ]`7AY‹Ÿ‘ÿ¸¸°ÒΧx¯ÿ¯–€p>(6Iÿ?AXPk…¤Çÿ⿜ˆ…]McÿYa€¤œwh@ÿ"5Mopuoÿ`“«¨»É—œÿ—z…§¨“™ÿf_qiÿ#4,-eÁÿÓÔÀšª¡¶ÆÿÝÍßûëÏÙÒÿ¨”—sM=Fÿ€¦©®ÿ~ƒ›§‡q{…ÿˆ‘™’sr“xÿyÅ®…l‰rUÿ†˜Œ–ª–sÿLGhy“Ëôéÿƈ„zsytJÿQP(B , :ÿr‚‹»²°Ï³ÿ”¤¥ ˜‡–ÿ¤©y“uaÿg+4DEess÷nF^jP\P^·ÿåüþûÝßâÅÿÊÅ¥Žv0ÿG_pŠ´¯Çáÿ­›—‚¯ÔÆŸÿ‰H"Lt‚ÿV;8Lvtmtÿ¥ˆˆ²²ª¦ÿp‰¡”š¦|²ÿìÚ¥}nT5ÿ+M90Qsÿ‡Œzb…€›Âÿ¥ª¾¬ºº®¦ÿ‚Q)g†nEÿ B`RH^ ÿ½Å¨½˜„‘ÿ…‹°­on‰ÿ¼„tY\:Lxÿ~¦”r]„zÿ‡dJV‰ÏøïÿŹ»Jb}Zÿ(37ÿ_¢í÷¼Žž¾ÿ¤®±ÕÖ¯‚kÿ`q§œ™yUÿ[?2Hsxwÿ”‚a>>u­ÿŽ¥·ÝòÄ‹ÿ‹Ž]9.ÿ-Xgv¦´ÄÂÿÊéøß¬»ãÍÿ¾»Ò³uX:ÿ6L/&9grÿ†tuŽŠ–c«ÿá§ŒyyŽ›£ÿ€z{†œ­iFÿdX;"_PVÿaoej„|x€ÿŽz~´ÒäÊšÿoh…S1=ÿ6I>Mh¤ÌÁÿ½¥µ¼£ ”¦ÿ pbD,*ÿHZ£¬†jhxÿ‘«•Æüà¦ÿ¥zƒ¬¾¶«Ìÿ×й¾»£˜cÿ./=ÿ|€€‰¯«²·ÿ¼«³Ã³ ÍÒÿ««•sqs{‚ÿ^clE/g‹ƒÿ€j=szklÿhU”· ‘±Çÿ‡ˆŸx}wgVÿkyƒ†soÿ’¢‰xÿv–Á½’¥ƒÿ`PJ?(=V[¿]{“œ°ª`œÿp~¾Å“…~yÿ™uIOui[zÿ_4>ACFIxÿ{lbRu‡¨®ÿ¿Ç¾ ‰|¦žÿdeRT?ÿ "y¶¬²ÒÔÿ¯›­¡ž–œÿn‰™pYE=/ÿU`dmfUjcÿQf’fg˜ªÿ‰›ºœÁÖàèÿöÝÛϯ§£†ÿ†W, UU;KÿZm•–|¯ÿ†ªŽ|m‡•ÿ–¥›]aloiÿzu•‡…z|‚ÿ¢¡Œ„u~uÿUetl‚´‘—ÿ…{A6hŒnÿhnj–œ—–ÿ…yxž«µ®®ÿŸš…{}fGÿ]J!/)*Qÿs›ˆ¨°»ÿо¦–މ¤¯ÿŽƒŒ„tbnÿakUGsbsjÿ‚eLINM\ÿ¤™¸×ÅÀ”fÿIaƒ‹‡mWIÿLE=h£“ÈÿȳÊÈŽ‹‹¨ÿœd{›†`ggÿk]B6I‡‚‘ÿ—xDCs†¤¾ÿÈ}“žŸ¯ÑÃÿ©Œ®š€vRQÿMVWHemW\ÿj‚›‘ŒšÆÏÿʳ®–K;n™ÿšÄ¬‹hq{ÿl^c…¨šÿ}ps…‡wfwÿ€{ptq~‘tÿz®š¬’cÿ>z¤º—{‹ÿ{xa‰ˆÿ³É§l|‹~^ÿYgb@7]mÿ}[n‡©¹Ã¯ÿŽ„F;q³µ¦ÿxN\‚‚cuŽÿ‹sj}txhkÿ““†}uQVÿ~—’¥š°¿»ÿѱsAPÿŠrMNTgnŒÿœ¡‡¿èǬÿ§Š{™ž„zbÿhT]osWjÿn€§·ŒTG;ÿPw½ÎÇŽ~ƒÿ®¸¤˜ˆ†mšÿ¡{‡s…¢‚ÿt}cnXu…Šÿ~y„”­¤¡šÿeXF‚¿×¯qÿhCgqgˆ¢–ÿ’«Âº—l‘}ÿ€„n[UF?=ÿPkm_t™¸ÿ’ypOG|©°ÿ’sh’{{“¯ÿw‰q‘o?ÿ^_L>PIYr|igÿŽ¥˜“Ž«»Àÿ¶ ¢—s‚ˆmÿnkaƒŒyVYÿxƒžit{hÿ`im‡m‚’ÿž«¶‘«Î¡ÿ§†jWf‚owÿfz›†‹y8ÿM_c|uhz™ÿpunS»Ÿ†ÿ¨§“¸¸˜aÿpf}qn|u•ÿ”i?KESŽ[ÿH.!>Nm‚‡ÿ† Ù™Ž¨ ®ÿâÕ“ƒpÿtqh|ŒIBÿv}Zfc@g>ÿ31=nw¶ÿ÷µªÉÐÇÅ´ÿ¡¿¦£ªŒ…‚ÿsJRndgZHÿHˆnj`$=Vÿ„„v|Žh‚ÿ¤¸ßè彿¯ÿ¥†‡iMSŒÿ¡}alxˆoÿJI1c‘˜—œÿt™¥p‚l\ÿq–Ÿ³×½¹¢ÿdf•’Ÿ ~nÿw]XDQDNfÿn„ˆ†€€˜£ÿ››œ¤¯¢ÿ{oqdZˆ¿ÖÿÆ—}‹”…R.ÿ85A>8FaTÿIoŠŒ—Ž„¦ÿ«¡¬¯›‘ˆkÿ ‘mpmn†ÿ¤›h6%SPLÿi]Wmwr~ÿž¦©¡Ê¶Ÿ¡ÿ’‚ku‹kÿie‡†q[:CÿKi…¦—{iaÿoŠ’“‡‘°¨ÿ• …slQ3ÿŒv…ƒ¯ªÿ‹„uh”ŒWNÿZ;)p•Ÿ›œÿ›¢†Ÿ«­¹±ÿ¢ymŠ…‘ —ÿŠq[„‘ÿ¨›œkNGK1ÿ-266Sºÿ¿ÔÁ¼±Ž™±ÿ­ˆ‹“”vÿ]ql¤Š™†ÿfddUYBKRÿt|YomSuŽÿ’®¿œqgÿ†–~R]”ÿ„´­¥¡Œs€ÿfJN[sZtcÿ_ˆwxkWgxÿdz‘˜wwÿw{n‰›ª¡ÿz¦‰kVt]Kÿ{]r‹fcp|ÿ„ƒ“” ˜zÿyN5X“«¥¡ÿ¥¸ˆŸ˜¡´ ÿuldfZh^nÿ‡`dwYp˜ÿ˜´••¦}i‹ÿxs{omn„«ÿ·¡¤ž…yzÿ‡v}|k~~eÿbyp…‘nŸ¢ÿq„—„Žv|¤ÿžxurPasqÿ¥ÔЬ¦§ƒkÿoNerY[\QÿPixˆrj ÿ˜‰’™‡€ÿbqŠ}rzVÿfrŒ§  „`ÿuhDM9@‚sÿ:އ¾©œ¤÷«‹ˆ° pm‡{ÿv—¥ ˆWbUÿVP\‘Š|rhÿhDF`¦¥¦ÿ¶¤¤±Š’—Žÿyu[g}€¬ÿ—qzˆš’_ÿIF%A^\œŸÿž©ž›«ž‘ÿІŒ”Ь¢„ÿ€†¦šp}yxÿw|‚m`kgÿn^W?poz¢ÿØÎš™{t{\ÿŽ ™œ ¢œyÿž‹yteÿPQShYEieÿp •{9M}ÿŸ¤Á©—›ªÿ›‹nr‹ˆw`ÿ{hb]P^eVÿ[u_–¶¯ºÿŸjqu‰š€QCAq”­«‡/Ðÿde…avrvcÿi‘Ž„’¡³ÿ—¨b{™ÿŠ…jup{xPÿZUW޶¤¥‹ÿˆ˜y‹wŒÿ~ˆo[U@ÿZgthhœ›Šÿ’³…}‡‘›˜ÿpLHIl¡¢ÿ¹»£‰²¢ÿ•{X]ef{kÿo‚¤Ã»|zwÿ’†ƒ\OyÿŠrZffy‹™ÿÃÌÓ»¡„WIÿJb^egZrƒÿskoo‡|sWÿchba‚|m˜ÿ¥ŒŸ­‡flÿ|™‘«ƒ~‘ÿ„—¬˜gu€ÿKhiRj`^wÿU]¡Á¸›¬ÿǬ‡zvsb:ÿ@0(H´ºƒÿgY‚’”}ˆÿfoni‰¨¯Ìÿ×¼¬Œ{…ÿ`L>0WHM~ÿwu\*:P›¨ÿ°¼©mn^\ÿm¨·ÅÅ̽»ÿ¸¯—‘‡xfoÿc]qmzz{dÿm^|Y@>dÿx‡–‚…¡’¬ÿ²¯µ³±¡gÿe€Šrm„£šÿ‡ˆuZpnylý[³°kWD7WŽÿ˜ËöØÝÖÁ ÿ€€v‚vtX^ÿfzk}chƒjÿLNBGgs}ÿ“”¥ ®„\ÿ‚wŸ›ƒ–ÿlu{xŸ‹y•ÿp{n]bTMTÿclafv“žÿIJ´Âª”gÿJ<ÿg—Ž´‡XWÿE:JT=8@FÿH?mZZyXÿBR>6\gvzÿ\‰wšš¢ÿˆ_g‡u˜}ÿhs}n°ªÿ²š‹uŠˆrŽÿ™€š|•œw´ÿ¼®ÅÊ¢›§”ÿ„‡€sttž³ÿš¼ªµ¦…†›ÿ¡¤­­šžÿ½§¸ÀÀе“ÿ«¡‡~~vqhÿaewV†“‚©ÿ—|–xW€†ŸÿŒ…}“‹†˜žÿ¢¿…–‹w†ÿ||j9tpc|ÿlr‰TNF ÿ 3Eb`@TUÿ^d[‚xqzÿuVNfspY[ÿtg€pkplMÿ]ZD$@HJ>ÿ7:<3FL¦ºÿž‚|Šodf|ÿ˜nvrŒÿª•ƒ‚sjlgÿ€‡‰…µºÀÿÃÜøìÍìͲÿ¥xr‘«ÆÅÂÿĸ¹µÆÂ«¢ÿ—‘›„¨~€¿ƒ™·øÿƒ…p[pxiwÿz˜± Ž„f<ÿ7e|€\ZM<ÿ\\QNTLl~ÿsz”„ƒqdÿ{TZ?Inkmÿ“’y|†yÿŠ’tnXE8ÿežÙƦ¬†žÿ±‹˜†pp}ÿ™š¡¤´³ª”ÿ•‘vmobfÿXe^Zx‚šwÿ“¨r„CB\[ÿ—°Š…xŒ”™ÿ§•ƒˆiCKÿ_Um^LhK6ÿfuhjox—oÿmtvq’žœ¬ÿª„j7Gp…¤ÿ¤Š_>___Kÿ[Z]cg|zÿ¡¨¢›¢›‰˜ÿ‰†Å§œ¬ŠŸÿ¢ž——ž žÿX"!$gwv‚ÿyvqp‰Ž‰~ÿu“™ ¤°«ÿªÍ®²™©‚ÿqcwZYKSÿgŽ‚Œ²¢hFÿQov¤«˜w…ÿ‘‚ž°¨±ÿŠpWdpyÿzjueH^„ÿ‰td…–Ž£»ÿ¬•œ§~GD‚ÿ¥×Ó©‘ˆ¦ÿ•·²¥ŽugZÿ[f}‰}Žª•ÿ‡{z†j¦ÿtˆq†¶Ã½ÿž|`8“z^ÿaF8idj{ÿ]mˆ—ueÿs‡‰“²¤ˆ¬ÿ·½¥œmZLÿ_N=DC>! ÿPyaR<1ÿ&OVgtˆ‚”ÿ°® Ñ­—Ywÿr_k[\t.0ÿMZn|o~f~ÿ”£«ª«¨ŸÂÿ½ÌÓ°‘s{¥ÿ®—”›¯†NbÿQXePL_Ytÿ›µ¨ÈñÓÆÎÿåäб›˜q‘ÿˆmxµÃ”ƒ{ÿJ8AS5ADCþG°šÍ½­¸ÅÈý äPƒ£ng…’ÿ«““²—‰”vÿF Pl{ÿvzgi’vdlÿlQenr~•šÿ ˆ€}ŠŠmoÿYS\<<]wƒÿrrq‰[LRÿLg{ruj„ÿŽ™Œ¨¢~sÿ€|nxeyÿ •†{€Zimÿ‰—¢¨Æ»«ÿ²žˆ”šŽ¡ÿ¹¹™—¬–†ÿy|tmi[Tÿarned¥—ÿ•‚œŒŒ¦zxÿ¬»©¬×ðÎÜÿÖµ´¢¢yI*ÿ"6"2JonuÿŠ‹‚u|erÿŒz‡‰œ®«¯ÿäÇȶ¨WGÿM# +ÿErr:RGVxÿgez“­’®¸ÿ¦»È¯°Ž{ÿveORV33&ÿ%) :ÿTe{ÅÝÍùÔÿ¯Î š’›·œÿ¨¢–¯„OYPÿ_l9W<1Ofÿrm£Ê°ÀļÿÂÁ¨`oT]ÿ¥ÁÕÔŽ…Œuÿ|mcRnSkÿg]•°’–¾ÿ×ÅÈ‘ƒ¤}—ÿ˜¥}¡ÿški^g—‘¤ÿtktrkwtƒÿƒ¦ff\iÿNtƒx}{˜¬ÿ§˜œ ©œ™‘ÿkŒ…\dC*<ÿIo‡ƒ…[‚‡÷y‡ˆ'|z‚ÿ™¬©”¬‘Š•ÿŒk^OlkIUÿWINg€…|wÿO7RŸ‘rÿnsi§ÁÝÑáÿÔȧ¢—ztXÿYR)89HSbdebxŽx[Àÿ~‘‰a/e‡³ÿæí´½£’“hÿfqwQ.:")ÿPoq {ª–vÿ¥–º¼§·˜˜ÿdz¿»™µŠ`ÿNTuŒ¥oÿ!ex}‡ÿ¦²¹²”£‘±ÿ¢ š°´¨ÿ•£”v‡iRXÿ76@ @…ÿÂãÃÁ·±³¶ÿ™°£¸¦Šš“ÿ©È±¨c<ÿ :06Sn‡ÿ‡{j\‡prÿˆ†ƒ}“›³³ÿ¶¿Ñ£}yECÿ|ØÔ„ve…wÿ”‘voi77ÿUmonk||lÿ}‹…}}ownÿ‘—†‘¤¸ž›ÿ¤xP;?bmlÿJ!I¢Äÿéâ¼­zuWpÿyiZch‹ž¿ÿ泸™rdKQÿfK6&/&!ÿ9]¿Í©‹e]ÿ‘_œ™ÌÁÞÿÕÉÔý‘‚yÿi6C8JC/;ÿ©Â¤„tÿQ`E>0'$0ÿ6ie•ÿ ¢µ¿°¡“Žÿ•–¤©™£¤›ÿšš~h=D5-ÿ4@@Yiz‚ÿ\dK\}Ñ»™ÿ|\w„|Іÿ¢ÍÈ~¢—…ÿwtv\WU[_ÿJ4_Vt”±ÿ»¾¯¨¢xx\ÿz©Ù¶²¥›Žÿ•›› ¥žaÿQJTOccPeÿtR{‹”‘ˆ„ÿŒ˜Ÿ¤¼¯·¦ÿ®£”ljÁÔÄÿ¹{_>4',:ÿ13jgƒ¬»Èÿµ¢œx~bgxÿx’—Ÿ»Á ÿsaSjnN0 ÿG›µ¢h^ÿjvz”€oˆ›ÿ•¢’¥¹¦——ÿ››’Ž}pmÿ`[GilL@SÿVZ[MECY¼ÿÓÂ’v‡z“˜ÿ°Ï¾ä´–‹ÿn”ƒˆVC;ÿIQ2IK:V…ÿ•©²¾À£­­ÿ|c}§²ÙÑ’ýƒŽ€˜yhwUÿ'W‘¢˜ÿ¼Ïȱº³‘ÿª¸È¡´×ÿÄ¿Ž_3$fÿˆc16Q[ÿw²•›¯Â¹àÿÊ‹Ž’”˜¡ÿ£–x…­€wxÿdgY]dbV0ÿ*GŽÁ½žˆÿ—œ–¯¸¬“¤ÿŸŠ}†šmyÿPTMQXOOBÿ7/%'?DQeÿe38`™‘Òÿúü›•y•‘ÿ‚‰¬¥¨¬†ÿnqTMi*%ÿGOc}‰®™±ÿ¼º®›—‡§‚ÿ†¢bŒ×éõ»ÿ±~UnqlviÿMG'19wiÿ‹z‹ŒªŽÿ‡“•Æ©À·ÿÖÀ´ÒžI:ÿWi² TJ`nÿw‚rž’ûr_²°}¢Ëɳÿ¿Ùų¡wiZÿe}‚yP6ÿK…‹œ¥ÿ°Ü©±°·£ ÿ¼¶¦«´¬§ÿ”tsi5262ÿ +7KPÿ”£•sOSÿÉüýر™´ÿ±®§œŠmb`ÿXci/9/*ÿ#Sz—žË´¾ÿ¼¡­š£z”ÿvW€Ìبÿ`:1QI1ÿJ€t…g¤ÿº¦´·–™µÿÅÙ¸š­›Ÿ™ÿ ¬©Xxyg?ÿ5kŠhF!Sÿy£—³ÔÚÙ­ÿ—’}Œ€•œ…ÿ¥¸»³–Šp]ÿXCSd6M?eÿcf^,@lˆÛÿλ¼”†¯ŸÄÿ–¦‹{y`…ÿndO9,F\~ÿƒa.1KX^…ÿ‰ÃØÚ³¤dÿ$"L”¬–’ ÿ¯¿½­†^Oÿ`8%1Jk_pÿZSsis–¥ÿ‰„ˆ ¸žÔÏÿµ§~fSCQuÿªÇªšyffCÿ.?NTpm…ÿº»Òß¼¢ihÿˆ¢˜Ÿ–¸âÐÿº¨¶–eJK7ÿ& %_|ÿi‡‹…ÔÙåÇÿÕÓÆÆµ³¹§ÿŒu€…’ˆ‹ÿz}oXE6ÿ%97Taokÿµôêºxunÿ‰Ÿ¨Æ³¼­Áÿ‘moHWcX@ÿ=YLrvf^`ÿdsš²¼À¶ ÿvkSQZs¤”ÿ}Іœ’ÿœœuf(ÿ37PAFS<°ÿÌ¢ŸŽ|–ÉÊÿßÉÓͳ·v9ÿ!,rއM_2ÿ&U6PrWNvÿb‚ÏããÁªÈÿ °®˜¥‘y“ÿ˜«Èˆ«|zÿxrC;|ÿµ‚ûÊÕÌÿ½­ˆ…ˆz~ÿy¨y™¢‚”ÿxf¨Š~t„ÿquˆlkzf„ÿ‹y¢§¨™3#ÿ^…aŽy¹ÕÿÔ¢ŠŽ|kV@ÿ' !PEÿ7WiŠ——Ÿÿ“qŸŽ„Š—ÿ¿çç¶€ˆ~—ÿŽ£jWOÿ'5NQzµÿµ¶Ó£šž¢Œÿu ––¢´˜ÿz~g=`kjDÿ953DLT™£ÿµáϱ½¬¬ÿ£¯µŽuv^@ÿTz‡’•­¸Áÿç¿»MDP3ÿ8p— ÍÀÿ®¶‰„ƒ€ƒ~ÿ‰œ™™££Ÿ£ÿ|uœŠdc8%ÿ<;NHC}]]ÿ“ˆxD€‡uÿ™¥„¶žÿ tryŒ‡ÿ‚xG')XÿEVpг°Îÿ»¦Æ› ¯€}ÿ}¨˜†‰[%ÿ1+Q‚“™šyß],#>^P‘ ÿ¤œ˜Šˆÿ‰vƒqŽŠ~û°y€œ°„›ïiqWfûƒ®Êÿİ—Šrq|}ÿ¤˜Ÿƒ…¸µÿ kdoÿ|mTI;7VŠÿ‰Š‹w…‰pFÿJˆ‰ž¦´¯˜ÿTUKcŠxtÿJM4Ia`ÿm~‡¡µµ˜©ÿŒyjbSGewÿl_/k™ÿÅ¡lts‘‘‰y¨¨žš¨’Ðÿ£´Ìº‡Œpmÿƒ…‘†Š”šÿ™‘i_=_–“ߨ’hyŽ9…˜ÿ¯­ ›ŽkYlÿuŽ’›žœ¿©ÿ¨†•†kQdoÿ€}JB;@HGÿAEn´¶¿®ÿ’šž˜š¥}mÿhOLYGg‡ÿysjN2.(ÿP‘‹gdXu`ÿMz¸Ä†UWiÿ™­ª§¢±Š}ÿTddz{•¡žmqex‹›~ú ÿ ·×¯•XÿD‹«²©¢Ÿÿ¢fo–‘µÿ¨l^a}™¨˜ÿxl‹˜vwS*ÿVƒŸ«ª¤ÿ¦ŠYiu´¿ÿµ”’un–uÿy‹ƒq‹–¤ÿ€tli{ivbÿd[bvzhbÿ}\dkr“µÎÿµž‡„gŒjaÿˆÎ¯’’›ÿ­‹†„[ZdƒÿhƒwO>]j]ÿjujW3)']ÿ‚Š{¶¢²®Žÿyƒ†”w? ÿ\y—©¬œÿus‘{†j~ÿiP\Oa=>[ÿWt¯‰†‡™ÿzŽ“´¸°“ÿŽ}fj]nhÿbXTF^x{zÿdƒÀÁâúüÒÿµyÃÆÙÍ­ÿ½Ò»ŽwZgUÿ‰–qz‰Œ‹Ÿÿ¥¯˜y¦ÉÉÿ¨Ã§“º}ˆjÿO/9ECÿPKJf˜›–¡ÿ˜}ps`dQÿm¢¡¦Š¨‰‡ÿizˆƒ¢„wlÿŒŒšo@@,„ï»Ê¸€ 0hMOÿ-&Q5@&ÿ"-:C_h`€ÿ²ðýìе˜ÿ‹„{Q^T`zÿ¤¨•Z|’•ÿ¡¶¬œ˜}¦ÿ³¢‹qvVµÿˆ~B2cƒ‰ÿž½»²Â †gÿY‚ÀÊÓ§{tÿl…©ØªŒÿsUl’¡wƒ±ÿ–À¯Ž —roÿsxN]–|}ÿwv]egcsÿ|”‡qwPMhÿR&N>1_iÿ¤À®µÔ¢…§ÿ­œx¶Ð©’ÿY9;AP\‰ªÿŒ™˜›z]mÿ4Zeo›»ÿ©›«¨y`ofÿJeMUv‡¦ŠÿŸpPS@Pg{ÿ›ÒÃub{jÿsz{mfm±œÿ š§™k{aÿ}‚—ÃЬ¯³ÿË¡Ÿ”ujK)ÿfµ£¬”„h ÿ%":>‡£Ÿÿ§®Å·¯¥³ªÿ–¯íÝÌ׸ÿÅaa:^ÿ8‹ §ò謤ÿ•™€qVpƒqÿ˜¶˜‰iu‰†ÿ€dU‰£€€xÿaK-WZoLHÿoSI„‹¨…sÿxmqu’›Œÿ¡~sZY_uÿ}kmbZ‡¨™ÿ¥s`¤˜Žžÿ¥l4$  ÿ1"5>Zow„ÿ‰pŸm…£ÿ†¶ÜÖ͞¬ÿ •¯žŽ—vvÿuz‹›N67Tÿ«¿ÐÐÇ£¦´ÿ­˜uG#QVwÿ‹bƒœ†¸¶wÿdL_|•’§¬ÿ²²¤Ó¿n8:ÿ.E€ …‡ŠoÿgxRb”ÿŒ®™·±Ò¼¬ÿ«•™¢œþ„Pcÿ '"·”n}ÿ—žàÙÍÆÈ–ÿŒ²¨»³~}•ÿµØÆŸ–tŠ„ÿ‹ Ž__Sn‰ÿz1/gvpŒVÿ!I3:dtwwÿru{Š›„{€ÿt‡—‰`sWrÿu€yŒŽx¦®ÿ’ƒ|Og›—™ÿœ¯£›œ”n‘ÿ‹q“†nCpqÿ„¯º»¯£Ž}ÿz:MsW`ÿqsyM=?WLÿ‚¿Çßöëʼÿp‘¥degÿ{«Í¬”ª}ÿh8>bx”šÿ˜–¬~^ÿte“°Ÿ¨’“ÿzY^MNCISÿa}…“‹za‡ÿ«wggm¬Œxÿnpƒh<ÿ9;aˆµ°Çÿܘ¶–jNb²ÿ¸‡†{CTÿW9'-Eoÿqs dOŸˆ¢ÿ«”¥¯À ½áÿå¿áÃtr|Šÿ™ˆª™‚n«ÿ«~‘‹ŽhVÿ„†”–ƒ{†ÿsh‚keSWWÿ(Z¬faJmÿn^‹¡ž¯§·ÿ’Vm¢¡¬ÿŠŽ†~rSÿ'Yœ~m…owÿN.[``NŠºÿ¥¸Ê«”kn€ÿe8AD;OxYÿdIhFFuqwÿš¬£¥È¹·¡ÿŠy‘™Ã½ÿ™mˆ€_w‡aÿ|ƒy}‘”µ‚ÿ¥©d„uhlÿz“¦›Y~©‘ÿ’uC;}ÿœÍ‘ˆ‘œ œÿ€:+`–o“ÿ—¬‚ybk`*ÿ>‡¥ØÞ¼¬mÿ‚¹¢ŒhNVmÿ†¯“²ˆjUUÿH *BO[y^ÿ[iMlœ©Â¿ÿ£Ë°’Ÿ¿ÇŽÿ˜Œ…–œœoÿXM7gpŠªÿgjVdoUYÿœ¥ž§žmC4ÿk’v‚‘ar’ÿ¥ˆA?Lœœÿ™šrJCj‘tÿj…J“È›•˜ÿ‡SC“¨žˆÿbY¬™† ÿ«·¡‹š ˜ˆÿªŒˆO )oÿ‘rhr>:\[ÿ\rbc`ÈñÿêÚ¯»´¹¨´ÿ´Ÿ¡¬©¡”“ÿW9y¯›…n>ÿJ‘‰—ª’†ÿ„„ª‘VT}…ÿs¡Š‡…dgaÿm6\waâãÿ¤ªŒ}’¿¢Xÿ)CC,]eo}ÿqk~ckMfqÿ„y‹„cV¢‚ÿe¸Ð¤¤©whÿ›ªxP^TMyÿ‹u=" ;XÿnŠ—Œw}ˆÿu”a›ìÅ™ÿ `1q–vp˜ÿ­ Š}J†«˜ÿª³™Žp9-ÿFpozz’…ÿ›¾ÂÅ·‡“ÓÿÒ ŠzjV}jÿ—§¨‹‹fVpÿ¢‘o—¾ŸfJÿ=BN¶ÄËŬÿoxxc„lUNÿ}~•;2KÿhOŒ•{…sÿ*NHHlgŠÄÿ§‡OftµÓÜÿááéУ}œÅÿ°…¢’‡}yaÿ4_N_„kÿ–l‹xC‰ÿ˜’q#5ÿb~Á »Á¢…ÿTf€x¿¨˜ÿ†gUW=j¢¤ÿ…mudfK`kÿWm{]OMA5ÿB|—š…½Ñؿʣ‰•ˆ¦€Éÿ±RA7=RDkÿgaz«¨¡·Áÿå×廎ZCJÿ_‡ „‰™ §ÿ“t€¶Ç«—¢ÿž¢‚wkD}ÿapŽÌÏ´ÁŒÿumu”¢f>ÿ%*0Ktx“´ÿ¼ljy‰™ÿ˜­”‘vq…Žÿ{“V1K‡•wÿ”œw¨‡LlUÿ&3,RqMÿ-`š›ž²¿ÿÓ½¦¡“‡8 ÿ*FR`]goŠÿ¦‚œŸºïåÁÿ¿·«qA[jwÿ˜‹“m„reÿm€s‚§š‡žÿXGTLfxgIÿuˆšvnWY‡ÿ‰†’|Œ]';ÿo‡«©ºdrµÿ£¡‘¬Ÿ¿³ŸÿnqB3YS@_ÿv{µ¢¹žÿµÌ©¾å®Èß*-cƒp\ÿ_bT™¢¾ÖÿŽ·À“{ŸËÇÿʳ˜u²½¹ ÿ¥¬ml¬ŒaVÿ)$Ys“‚ÿbÄ›tI]efÿo¹‡peY4@fd}€ÿ_rx}x…L=ÿQsZ€’œoÿtTOw€mvvÿmrºµµÅÄ¢ÿ²ÌÂÀ§“¨ÿº—|’˜nw’ÿƒ…˜§–š§Èÿ²È—ƒž˜›ÿƾ§¶Æ‰p®ÿÆŠÔÏ’³³ÿ²Çʪ‘´¯ªÿ®½…‰m<2ÿGr€¨’~“ÿcPc_\F’pÿMrfbY]ŒŒÿÀ”Œ»’uG{ÿaaiqwbr]ÿ6IQsuzyXÿQJJ#>=ÿ2'LT%5Gc›“—„XZqPÿ¼šŸ©£ˆvpÿm[n}¨€’ƒÿy?50nSF,ÿGKjqUasRÿbwŠ“¸£zvÿAl†£v{Œÿ\iºæñîãûÿøêÕ´³¼·Øÿ®¤²ª ¢y–ÿ°‡­­¾¬âùÿ¿eqcrx†²ÿˆq”ɽ÷ÿô˛Ğvpnÿb\JJU78%ï6/bm³@’nÿR*`dwz‚•ÿlmsnb—œÿV`ZqsuXlÿaQ\wpy}eÿfp}ކ†{{ÿdSi´„^Msÿˆ«œQv‹”û™´s˜€tzÿ}osh™oCLÿsK23a…®ÿ Š¦Œmc•ÿ–ЇWuŽÿ˜“už¦o›¸ÿ•xMJc€£ŒÿX T{•‹‹ÿx”Ue`EPÿJl`»˜{ˆoÿœçûæØÊ«ÿ±¤…z^%ÿ9}ˆŠkWdSÿ?tœ—gmm‰ÿTF#2e`”ÿªÀ­Í÷ËÔÿèÎÔrOYf¨ÿ®°‹°´„g0ÿTiƒ¥‚uÿv\6Mnlyÿ„vˆ‘Гַÿžh€Vk·Âÿ˜mNN“skÿxeVi]QÿXp…|[?@3ÿ8‘ÊÑß­|eÿ¼ÃñÿÆ›–ÿL]Lche‘©ÿb]Ic[ÿ©š…¡–kg­ÿÁÅɣІ®©ÿ·Ë¼ÜþýÓŠÿv¥² ˆQ[iÿurGhibnrýP@ejmJX9ÿ E ¦}ÿš³á×ÜÓÙ±ÿ¡yiT[F}sÿcP{ŸK''ÿY|m=E#.ÿ`†©}Œ—šÿ˜¦¯áÉ—±ÿw`c61QDQÿ`tXmzi‚žÿœl4Gu¶Éÿ©ƒ¥ˆyŠƒÿÊíÛ¶¸²Ïÿ¸ÀȶʼnI8ÿFYu·¾µlIÿ&;FT{š}ÿ^hHKY€–ÿš{’”²²ÛÿâÐää©»ªŒÿ|„™qC;ÿj””‹”­u-ÿG]i‰P>4ÿ ,0MUÿ›ª¤”²»öûÿ÷Èp;V޹ÿÄÅéÜR{kÿg†u¡‡]I!ÿ$NumaŽ”–ÿm}ŸÜðÚܪÿŠr}¥¶™s›ÿ¨šj`urœ‘ÿ¦“hHXby–ÿ“}Ÿ¿bMNÿŒ©¥¢˜d ÿ¿×ãàøì˜Tÿ;)U‰“œ°§ÿj *ÿAO\82Y™ÿ±’sig‡ÚôÿèðÿñóÖ­¡ÿ}tmiH90<ÿEBO@W‡waÿZi€…•o!'ÿ;CF`{‡ÿ™‹«íòñÈÆÿÖ¿v4%-ÿ ,k—€–‘ƒÿq˜€R$%iÿypm{ctvqÿ€±ÛÜðíóÿÖ»Á©t/47ÿ@,2l„ƒ ÿqz^@„›¦Èÿïd—­ ¢ÿ‘´«Ï½•¾ÿâçà޾̿ÿvQpUG]l«Á›ÿvpvpfjÿkZUiWXOzÿŸ±±ÂÁÉÎÿå×–rLmI6ÿJM£¨‹›Šÿ‹|ikpYKLÿD@%Sy†mXÿ,LtŽƒŽŽ†ÿpg€c6F;ÿvš™­©—ŒÿÜòÚ‡nqodÿo5{c`K^ÿqw•s™ÿ¢ˆq_𮮝ÿ‰oŠ˜Ž’—šï~w\&k\eÿelf„}pµ¨ÿŽgL€‘~pˆÿ‹°ÔúàÏï¶ÿ­ŽWGY^Qÿ<0™Ï ›’}ÿ‹¤nVÿ)"* C€ƒÿØûýÿøñÿþÿëÁÆh…†pÿlgo“¥‚”ÿŠ˜CPe0Aÿ;AHooÿ´²¹ÆÈ°éÿÒš²†vyM3ÿQZSsbHžâÿµ‘jU^4ÿ 1nav‡bÿn‘…¡©£ÿ¼«Ìòµ©ŠbÿkaXihB0^ÿZ39;ÿˆ¢¦­¬·Öÿù”yr†¤¸ÿÒ²¶òØ·¿¬ÿ¯Å¢pZPA=ÿ!6ƒŠnÿ€Ž”‘ijÿT>3EFŠ”ÿ’»§ºÊäòýÿõÅ–dCJ23ÿ2I[£Ÿ™ÿ»´˜jUDÿ2-R‹xuM,ÿUav«Í®‡§ÿ•^S>%Q\?ÿcpŒ™‡ŒÅüÿýÿÜš–ƒz‹ÿu`Sj=7GBÿ@²­…«rŠÿyzq Ÿ˜„`ÿoXd“¤ÿ§~pdSŒ“|ÿuG=H2Ga›ÿ ˜p0Kgn‚ÿ‡o†ÌÌÁÀ½ÿ¬á‰RLGÿJ)dÉÀrJÿ\N]fpUSFÿ6&-3 /GDÿ”Ž®÷ëûýþÿýþä­Ÿˆÿžu–—ƒ’|{ÿqc±¦„G1Lÿ;./1[==ÿZzt¾»ÁãìÿÐÄû˜Œ©xÿ^3!RF"kÿßú©hxq}ÿY'0*WfwlÿA;v¤©‡r¬ÿ¬Î°ÂÀ|QÿRN;Yqoš‘ÿl{|_NPgeÿc]h—Žfzzÿ§Ùžpjww¾ÿ¿ÊоÂÃÖ«ÿw£«–[(@ÿP%EX|˜kYÿ©Ž‚}iu‹ÿVhm[A6jÿolf¥²£¬ÃÿáùêŽf†ÿnZOGWœÆƒÿ€Qp–¬|KQÿQ%MDYgLÿEEE…“®ÀÞÿ̨º¯¤tp‡ÿKP?„ˆih‰ÿ¸ó쮞™§ÿ”\}_*XvNÿ8G†¥¶ˆƒÿ¥µ³›—n]ÿwUkf`^“ÿ¬œ˜ª¬ƒm²ÿ³jZbV9GTÿI˜¶gEE`ÿŸq‹…|¦ÄÎÿ¥qp‘‰“lEÿWcWm“ÙÞŽÿ›’]z]Rwÿ†eP`gKLÿtl½àê÷éÿÍÝþ਋v…ÿ†Ukˆs…£–ÿ…^N›¸€Sÿ=CYF*7 ÿ6PNtŸ“¥Ìÿñç×Íɱ}†ÿ¬pEG8?$Wÿv¢ìØŸ„mqÿ‰T! (s]ÿV&"Bq•¢¯ÿª³Àܼºç¡ÿŸ“ZsÿG>(J‡©’gÿ†‰ž™u†Sÿ/fƒPo[NWÿC7m³£ªäÌÿÓ⨎Ÿ›Šgÿ8K\W^uDZÿ¼èÈÄ­mpÿŽYfE_bG(ÿ,OLvœ{£‰ÿ{µÔžfke{ÿaRj‚Š_œÿ“Êut|ŠÿwZN36Y|lÿ?„€enHnŸÿ±•‡‹Œ¼¹ºÿ°¡–wqfG<ÿ25b¥„¡§ÿwbx{]m~ÿo{oST]anÿwq–µçüÿòÿÆÞìÓŸ|haÿs_oq{“‹ÿŽŒŠ¬Ÿn?ÿAWh\.ÿ+Rz¯ÁªÐâÿÄÐÔ¯ˆtpÿ|G6Di£ÿš»òÙ¨‰ÿvY-)NjÿtjMu¢—¤¥ÿœ­ÙĆ”»‡R^:R]IsÒ€ÿ¬“€šŠ{wcÿI9d­uYÿƒ•rj^©¨ÿ¸ÍТ¤¥–¨ÿoŽkX;$,ÿDƒ_Nj{OZÿŽxmq‚pÿk_TSMPŠ‹ÿš}·óã¬ÿÑäÁ~\\sdÿHG0NF|ž©ÿ’”¿šŽvQWÿx„t5K}Y$ÿN‹¾ËÝÖäÿ«¼££hBÿ)$_³ÎÌÿÑ×ô¶¡¢”}ÿoVOZ&;YVÿ]h“¤¥½Š›ÿÉÑÆ{RaWÿ8P`vŒŽŠ›ÿ¥š­•v”xÿYC3]o}TÿU˜rlyƒ´ÿ½‘rqWk«¨ÿ§‹€HUBNÿWsž¢ƒšcÿ_vbm|g\hÿWTfL]]hpÿfXrµêÿÿïÿÏÏ®šŽfpÿ‚uw|\iŒ‡ÿ’Žœ™‚hMUÿ]cXS,ÿ=ižÑëþãÓÿÊÉë·¨‹rpÿK.(d¡®ÿ·¡Ë¯»¥qvÿq]$=dÿctŒ§¡£ªÝÿäôâ¾¹|\ÿKJÿ_{gMg>2Jÿ)7h™©ÃÓ½ÿëØž»¿›‰ÿh4‚ÜÓÿòƦŮ  “ÿwnnUW< 6ÿb[at•­²šÿ˜äÞ·Ù˜\Pÿ.$O…˜”›”ÿš£q…¶˜ÿ—NR{nÿslStqqŠÿ¾ÆÜ¬¦sNvÿŬv€NÿK’“Ê£Žÿqknƒ|odbÿj`C9eia›ÿ‚œ{fyÓÿüÿùⱟ}rcmÿnywqŒl[Tÿ“™Ÿ}™€3ÿ'FcU}bÿG¡ÉÓÙÛÿÚØš‹ª²‚ÿUKO Нÿ··Žœ•ÿ†{hEE(ÿ;~~}uœÊŠÿ|¿îéãÓ…sÿ{`Rf{lafÿu¨hZˆ¢¡¥ÿ—‚:E—Àÿ¹¥q\|O‚©ÿÂÝÏÐÍê´‘ÿ¤¾°cFwTÿiž¾ªyJÿ]Mj¦¨†qÿobYgwkÿbv§«†¤Óôÿîʘ‚—wgtÿb{ZL]`F"ÿQ„»¢–€ÿ"8[€’oC0ÿ<^h…šÃ¦§ÿ¯ÛÇ‹•¦‰ÿ[IQ; hÝÿýèÊ£ž—Œÿ‰eRXbnWÿKUznLb¬ÿŠ–œÁÓ¶Pÿ=MTJf‘‡‰‹¤ˆ{}£Æ ÿexQ7HqŽzÿg38c‰†¥ÿ›¾¡¢§ƒˆ‰ÿ¶¼Šm_d?ÿI†ËÄ«uzŠÿžŸrwvYHQÿqcbHSgpuÿz±œŸÌîÿýÿù¾›ŸŒfkÿoots–{—€ÿ†µxce]FÿI4hsY/*ÿ(w~˜ëîÞÝÿðž©‘yIÿ)6.Ds²Êÿ¬ƒ[pŽŸoXÿcUONR 0=ÿ0…”‹‚ £¢ÿ²²Ëá·€uoßUvkDnžðv|ÿŠum‚ƒ|kÿZ1J[«ÔÆšÿftkš—Ž¶Åÿ¹»Ëµ­±‡§ÿ›uM'9"2lÿ—½¥‰n_JNÿih—Ÿ‘€ŠÿuYKmzbquÿ…™›±ßòݨÿƒ€{zxcVrÿjoqcOMg—ÿ¾­žˆij@?ÿ|…UM;@kÿx·È¸¸Ï³ÿ¼µ•Š~VOÿ- bÇôüæÿ­£™…„“zlÿk\\TfSJwÿ‚|‚‚|œ¨«ÿÎ×Э‚p;ÿ*@T‡~…””ÿ†v†aÿEC.It˜tÿSZkˆ‘ŒkŒÿ–PJu€…‹bÿp ¸ÀÑнÿv[ˆ}ZK[mÿt_Rf>Iÿª¼¤kNsqvÿ}‚wn?Bpyÿzœ®±ÇÙ¢®ÿÖ¦muv_p+ÿ(b“ÁäáÍÿÁ“¦²™|qÿpgTlZTgÿs‹¥q¬ÖÚÿØÉ¸¢…Y:*ÿ8X~¹©†ÿ²§Šƒ”–£zÿ<4?h~uh[ÿ\H`§¢ª±ÿ¿ÙËŸvl`]ÿropTq™­¤”ÿ€|Š›•{aÿbelr7"0ÿR{ ºÈ´ÁÑÿôéÈË•qy]ÿJEPaa`‹ÿŒª“®¡ÿ`-.L‡¡Ÿÿ–‘Œ¬ª£ÁÅÿËÓÍÄ´œ„tÿpn\C.1gŒÿ©°¬§{`b[ÿ@4TjvŒ‹ÿx^ody•ÿ”Ž˜ˆ“ÆÃ¯ÿ‰{g…†b^hÿg`s|d^7 ÿW†šœl^Uÿc‡‹_0Akÿs^€¤¯µªÆÿ±·¦‹~ieQÿ%-RC8…¾ÌÿÇ©™ªÊžŽÿŠsti`cG6ÿNf‰‘›©©ÅÿËÔãП‚^]ÿV+[}Ÿÿ¯­¦˜”¥¦­ÿ|RF<8]‚zÿdKUp¢·£Éÿн×ͱ¢w4ÿ9OhrEP^…ÿœ£×Õ©’anÿŠy^LTWZVÿs]lvZ|ƒ£ÿÀ¢¥”v޽ÓÿÑ¿˜ŸŸ˜qrÿ}~„‘…€ˆvÿh{‚‡hE;ÿmg‚€Q><>ÿVRDVu°ØÚ÷ßкÀnc-$ÿ;8O~‘žuÿduŒ ¢€iSÿ]hYF$!ÿQšÁ¼¿ ¾áÿÜãÅœ}ia]ÿWB6Rqs…‘ÿ‚¨«‰”«ƒÿf;%=Rc…‹ÿz€ª³×еÔÿåÖÖ¾’Šˆdÿcm<@[Tu³¿´¶¯hu*À<ÿ =z|‹cuÿiy¸­«§~ÿ¾É³¾«xƒÿvtŠƒW`~sÿ–…W\S-\šÿ§ŒFQ€ˆxÿŽhI[P_’˜ÿuŸ¿¸ÂÂŒ¢ÿ«†nxD@aRÿKo~Ь²¡žÿ£œÁ™rZstÿlX==NEgƒÿ¡¤¨ŽÒÚÕÿÒš~sVI<$ÿ&IŸ©—œÿ›‘•¦¦‹Y/ÿLPÿLOfŠ…Ž©¬ÿÀ¯½ÅÜÓ´¯ÿwvshID``ÿLS…¤«¢~xÿdrƒhQ4ÿ{“‡mXhs|ÿ”¢º—Ÿ¦Ûÿ«­ª³š€qhýq­°†œ„ƒkcÿbMjŒ¥}e;ÿ]‘odgp[jÿu€«žŽ§Ôä÷ÌŸw€iFqhÿmf†±‡iŒ¡ÿ¼¸¤¥¡]Sÿw„r]5[weÿq¨¾Á©€ ÖÿΨ••€fTHÿT9 i¬·¡ÿ‡~¨œ‰’ŠqÿE;vi@Tfÿkxm‚–¾ÂŸÿ´ÐµžmroHÿL€{lnŸÿÉ–l}‡~qÿ†iP/Jk[ÿE2_ˆw€¦¹ÿ¥œ³×À—~™ÿ¤¾©Žt}{WÿV›¤“ƒ}’•ÿ¡Ž‘rUEPÿƒsP>PRawÿ‹†‚ƒz¶èâÿÍ™–ªs7Ekÿhkf‘˜ vÿŒœ´§ƒwxgÿ<[s`eGVQÿ\Yƒ­ÑæÍÃÿâÒ¡{†„…qÿPLGaGs®ÿ¦is—ssÿbgW`qhB5ÿ`€ÆÁ¬¿ÉÁÿ ¦ÁƵ~ÿoCC`ˆfuÿ”™€]ag†Œÿm\>).d’ÿ“_i{mjsŽÿ™¸’³°˜{ÿ†‹°‚gbS`ÿ[`~‡nn{ÿyQUo€™mlÿ}J;BNrŽÿ™£‘¢ÆÓÿÁ”‡‡l?Faÿav†—ª}Xÿ~ŸÖà̲eÿHHgkseQ]ÿx~³ÈÛʾÿÆÂ¤‡…~nsÿjIH\bÿs~ŽygºÿÑÌÉ®¡`/Gÿ]ki_f~‰hÿjz¨·¹ª~yÿ[;]fhMCJý^¹ÈêßÚäÿÝ—tq|‰nSÿFPFJiƒº­ÿ𙬦{xypÿmSIj{9+:ÿh¸ØÖÚèÊ¡ÿ¤¶Â¶…~s]ÿ\x„‰¬ÿ} ’ŽlfÿpQKti<ÿlÂñºÛæ¾¼ÿÖµ±«„VegÿIO^k‘x¤ÿ¬y|š‘¡—VÿQF+;W…ÿŠn¨¥›Ÿ§±ÿÕÀš°³|`fÿtŽžaZxkˆÿ¤¢›ª’mŽŽÿ])$Jp•xuÿ‰dJKoŸÀ ÿƒ¢ ™’’©µÿªkauztZzÿ¢•‚†Ÿ„H>ÿnµÞ„qpÿfZp„n?Z‰ÿˆmw¡Ìß¿£ÿ·¥‰tw—„Sÿ/=GC)=o¦ÿ¹¤°«xLbÿxzG5WM%ÿC„Ƹ”¥²¼ÿÁ®»Ã•Z@hÿY/o¦¦•ÿ­¨yn…¯ÅÿMKQA3;IiÿrPa‚™“Ÿ»ÿÝ⮧ƦjDÿLs Ÿ}~‡ˆÿ‹£ºº€ªÿ–o[S`ƒjVÿkdNFn’µ£ÿ~Ž¥“~qxšþ¸àˆ—{_n–¥ÿ†sŽkbk†ÿ®¤udaahyÿ…ˆwEMr„gÿL`‡·ÌÈÁÆÿ¯s†›™|JDÿR\brrŒŽƒÿ†‡™—n‚™}ÿ`V]iS!Kÿ°¾À¿×ǶÿÎɪŠbexiÿGYau„}Šÿ{…¼®ˆsMÿBE4++Ihÿu©­•¦ÓÅÿÁ±Ÿ¢‘nmsÿes[QTtŠ–ÿ³¾š‡~}ÿB*58hqrsÿuTQ›£«‘ÿ¤ž–§®‘‡…ÿTgv}mx˜ïˆ“˜Û€qržÿªˆwkw‡|þIPl‚„Š™ª™ÿ¾¨ «›ˆ“˜ÿ‘„`KV^Zhÿb]d’Ÿª«ÿ‡}xpuc`_ÿC5J_kŽ}ÿ¤£¥ÁÜÒ¸œÿ[f|eL8-?ÿi‡‹®–Œ£ÿ°šiaN9Lÿo]DH7Erxÿ€¬ÎËÖÀ½Ëÿ³ŒxeU`xkÿuŒ}³²£¨ÿ…žtxm\ÿXUINQ;Iÿ”Ÿ¨Œ‘«¤‹ÿ”Šm|tn™“ÿxq}‚‹ƒˆÿ‡umŠ—–‹eÿKSOU€™‡mÿULyŒ{jz‚ÿŒ¦¸¾À¬‡”ÿ“ˆ‰\Ngfgÿyœ–}ggu†ÿƒu˜ˆsggÿs]87Yt‹’ÿ®ÀÇżÚÒ­ÿƒf„’sXeÿ†liysu‚ÿ´ÉœoUW`Gÿ3?R42Y~¡ÿŸ˜¤Íδ­ªÿ­™yj‡”kEÿÿ4CQc––ž³ÿ®Ä­ÁƤ”Žÿv|mMIpÿm„™©«“•ŠÿvlB4Hbÿ_hrh}˜ÿ“¡•—Ÿ«ªÿ–ˆ€iwuejÿi’¡¡††‹ÿ”‚jv{cYyÿz…‡|vfjxÿpŽ—Ÿµ»ÿ¥œ—‰‘}ÿxfTQex|fÿ^_gjž‘Žÿqisp{kMVÿ`^g†—ƒ‡Žÿ°«°±¡˜ÿ}qt`JCF^ÿjƒ”¢‘šß„x`W[Åàj_ÿ[Uk{†’˜­ÿ´ÆÍ¹£¨§‚ÿcQTR–¤¿ª›¡‰ˆŒù@€ÿ^fjardbaÿ`fn‹“˜Š~ÿ£±ž…gZkÿ†¥¡ˆytrvÿ„€ƒ•‹ro˜ÿŒlRZ{vwfÿrzgf\…Ÿÿ‡vy–¾Õÿµ›‰‚zWH\ÿ…{fƒ’maÿw œzb]tkÿkdtŠpo[yÿwWe™ÝÝǺÿ­£u‡¨žrÿ^Wwtcxš¢ÿ~nŽ“fONÿli_WMS0+ÿPŸÀµ¤­£ÿ‹ ¸Â§ˆo{ÿ}YH`‹™‹xÿ€—ez•›ÿaLR;/EtŒÿ•~lˆ‘xmÿ»¿°•“ƒlÿ”•‘^Zxzÿxš¤œ„‹ÿŒ]>Pvœ©{ÿpdKVˆ¦¨ÿ‘‰›¥±¸ÿÀ¤xz‡kKMÿh„tmtnCÿN€°»˜ookÿURf}€mdnÿ‹”t}¢ÅѬÿ”•—ˆv‡’~ÿ^^Z]W>b›ÿ±° „O:ÿYwxf\TiTÿ$^Ÿ¸»ÿ¡ŠŒ€]y›•ÿ‡hTY`[Rlÿ~zxqt†kÿ†Ÿ­«‘‚|qÿOZ”©¢’tfßyge†ÿi=Io‹w^ÿ\iXdƒš“ï–‘Š|ˆ Æµ ÿ‚y\6HnŽ™ÿ‚wzrclˆžÿ¢‚h[^lhwÿyxz€‘ybÿyàïɰ˜ŽßzŠ‘‡§Ðnsÿs‡‘¨ˆ“‚þVpuffXJÿ5Aq˜Ì¿¸ªÿ¢“š¨©¨Šÿ‹xiDOfލÿ–|wp€ˆÿŒfl[JD-Uÿ\}‰‘Љnÿx¨¸šœ„„ÿzpƒyŠ|qkÿj}}“–’„Œÿ ˆ…<-Mhœÿ™†hn]MvŠÿ £“¬‘£ÿ¡Ÿ ŽŠzvYÿG`uƒwˆvlÿkEc––tÿcpS[njloÿšˆx‹£Çÿ¶·—“ƒ†ÿ{gjr\rcXÿlŠ¥¯¡‘vÿGAb{stZZÿh]bpŸ ¯ÿ ²°©®ª¢–ÿŸŠ†m;5hœÿª´§{o‚ÿ–‰zmZitcÿ[gno…“ÿ~{‘¦£§‹ˆÿŠueZsƒ€Žÿ„~zrz{†ÿ•‡„|^BKfÿvqc^`\tÿ‚Š¡ž‘¡™ÿƒ„ §–pÿBJRr”˜†sÿvwzvuwysÿefa]nj[xÿ†˜™yy…™ÿ»Ñºªªz~ÿlqƒgxvƒÿ“‚{„œœ—ƒÿUQWXauTÿXLUjp¬Âÿ»Ãª”­›‹˜ÿ¥ŠwkSchsÿ~”¥ŠŒyzÿˆ~teV[Jÿ[TUW‡¥œ¥ÿ|u™§·²‹ÿ…‚†ˆxgZrÿ~x…r•›ÿšªŒŽjHS[ÿjqŽƒkoWrÿ‡‹™¤¨”Ÿ¢ÿ ·œ{“„uÿa>iyƒ‰Ž‚ÿgxhs|miÿ‚ot]Mn_eÿnƒˆt—¬ÿ£œ•¡¢||ÿšrqhiquuÿkŠ€}~¦šÿƒGMgitgaÿOOZmŒwÿ“¬¯«™ÄµšÿƒpQa|ÿ“†‘š†~ÿš‹‡n`j_^ÿhurk[]ˆ˜ÿН²® “ÿ”‰ˆ‚~soXÿ\†„†ŒŽ‹ÿ‹ŽŠub`kÿxqWZ^]gwÿ…¡”‚Žœ™žÿ›Ÿ˜“yuˆ‹ÿybbt…ˆ€‰ÿxl}ˆ”“XÿN[cal|{ÿ\jŒŠŽ‘Š—ÿ§¡”«œ›–ÿ™ˆuZe{h|þE°Šsq‚€gÿgtodXfYAÿbit‚xޤÿ¦²¬¹´—„ÿ{he`|€}ÿ{ƒvrƒ®Ÿÿ†mQc]Tb`ÿeQOY~Š–Žÿ‘¯¤¤ ¡Œÿ„Žˆn[Oh¿m|}Ÿ¶m°Ÿÿ‘oip]akiïsdek©€•šÿ´¡¡´µšzÿx}s^^Šy„ÿ‰yzr{މÿyw[dvsa}ÿ†^ljfŠ™}ÿ‹žž¦ Žž“ÿ‰ƒšyYUÿu€tˆƒv}uÿ|•˜yfpeiÿscZdUUuzÿ…s†žŸ™®¼±¨”€‚…w±ÿ€~‚ƒ‡‚‘ÿ”–ˆnX`g]ÿfehoUaw€ÿ‡Œ¥µªšÿ‹‹ˆ~r|nNÿdt~Œ‰‹—ÿƒ|…|jW]ÿyhUh[Vgoÿ„¯¥Œ†–˜§ÿ¥”š™uxŽÿ€t^€Ž‰†ÿzm~x~œ‹TÿUbXmrnŽ‹þ]`ˆ•œŠ”±žÿ©©•¢“‘œûƒlÕ°ƒƒ’—ÿsiƒ{‚[qÿˆtniSPhhÿj‹…r…™Ÿ³ÿº«²¢ƒ€qÿqrelƒ}q€ÿ|o„ˆ–¥—~ÿhYPfugc[ÿMXtu‹Ÿ“¢ÿ¡š›¡”|…ÿ…wqXJ\]}þ”ð’‹Š‘z€‡ÿxo\ZaigZÿov–‚Š’˜ÿŸ®¹¤Œƒsÿ|omsr„x€ÿ‡iu„–ƒÿofZc^tv‡÷Ša\s}‹•¢ÿŽœžŒÿ¡Ÿ€lknhwÿ…––shlƒ…ÿˆŠz‹s^duÿr_Ua€ˆrvÿ{ŠŠŸ¯¶¼«ÿŒs~y~ÿserƒŠ†…ÿœ¦‹zojliÿq~|]TXjnÿ‰ªš—ªÿ „‡ŠˆhWÿWcg†––¡”ÿ}wˆƒ„}wmÿaT]^eYab÷vˆ“±ÐŽ˜§¬ÿ§qt€uzˆÿxx€|v„~ÿ€{}„{i`ZÿL_wzxztrÿ~~†’›œ›‰ÿŠ—¡—›’’ÿ’oog€•ts€`„iÿdykup]^_ÿnyut}‰ ÿ²¾¯§¥Œ‹ƒÿtywpjkoyÿ~w‚‡„––¿}s\clz÷`Rÿ\gxˆ˜Ÿ•¥ÿ¤¢¡•‡‘…ÿsk]PZd}‘ÿ”ˆ›’•‘‡û‡…paegifÿ~‚ž–‹’Ÿÿ¦¶¹™†€{qÿtknymp‹ÿЇ€|ƒŽtÿjc[\q}ƒtÿnprr~†ŒŸÿ˜ƒ‰’’–ˆ…þ–‚‡norzÿ›Œnwutz}÷{wPpiaiÿfuof}ƒv„ÿ’£ª¦‘¡¥“ÿŽ}}†€luÿ„‚‚ƒƒÿ„gim|‚vÿVSfhdw|†ÿš—´±Ÿ˜ß‹€il¢Ày…ÿ•œ‹„“Œ…„ÿˆucQ`p\ï[aUlæ ©ž™ÿ¥¬±ª‹|‹‚ÿkrs_vzu‰ÿ–ŽˆŠˆ…‚xÿqn`H\edqÿqfyŒ†‡›œÿŸŸ“–¨œ‘™ÿ…yŒ‚wxvpÿ~˜˜“„zÿzvyefghhÿohgnknz|‡…¥žBPÿŠŽ‹v|}okÿpw{‚‚wuzÿw…Ž{uxf{ÿ€tcj^bpvÿu‚‰Ÿ—¢ÿ •—‡€nphÿT`mo„†ƒ”ÿ„ž‘“€oÿns`gta\f¿ew–Š ³·ÿ¢’–~w…nWÿbckƒ‚}œ•þ.`‚‚_cqbÿjofiugrÿ‘•¢Ÿ£Ÿ‰ÿ¡›{wulxzÿckŽ—ž€ÿ€nhffÿ^ipZj~pmÿyry}{Ÿ™ÿ‘”‘–‹†•ÿ‘~vu~ƒ{ÿ†—‚ps{‡ÿsav~~‰|fÿbgcu„{sv–˜á ”‡~ÿvhfcgƒ†tÿy‹€„–”ý…ïÐcfgcf[ÿJW~ƒƒ•ŸªÿÁ´¦¦Œyÿ{ƒZId|qƒÿ‹‹š—†ŒxÿnnZkrYOcÿjZtŠ“¨§¡ÿª¶™¦­—Ÿÿgb{o_mm†ÿœŸž¢”wŠŠÿˆˆlQMa_bÿloxxp|ˆÿ„—“¢®š‡Šÿ‚}„…~sÿ‚ƒy}†‰‰|ÿj^ryqgnvû‚ƒãÀehw†ˆÿƒyx…””˜ÿŸŽŒsk`ÿ`vzwstt}¿…‡œ •‡:@uÿnqmeZP^nÿ„†‹¢±»»±ÿž™‡~‚xcPÿNQe}zˆ“›ï‘”‹Cmxqÿ]^KUhhsÿž–¦ª£«›™ÿ{_\Vcfþ¬ £˜ š’‡ÿŽ‹†hRRLkÿg^csqk…ÿœŽ•¡«”…ÿ‚~ŒŠ‰ƒÿy†ˆ”•Šˆ‹ÿŠmhmvzleÿn‰€vr~vÿv€‡‰xu…šÿžœ”˜ˆyÿ~ql}ŒŠtÿqp‚††‚…ÿzpx‚€jebÿg\KXxŒ’šÿœ´µª¢Ÿ•ÿ{pmYPYuý‚h ‰…‚Ž‹ÿydfkt]LSÿdv{‚‘›žŸÿ¬¹·®“‘€ÿ^W[erkn‡ÿ–“–•”‘€ÿ|zbIR`hqÿh`ljpz’œ÷¦ •9€Š†ÿ‰vokgz„’ÿ”˜‡~ƒtioÿlqu{do|uÿ|}xvŠ|}Žÿ‚‡Š”›  †ÿ…~~zzy|ýl¤ uw…•”ÿƒ†yuƒƒ‡ÿz`rc`jnƒÿ›Ÿž—¥¥¬§ÿ£•–ojZ`ÿ_n‡Š‚{ÿ€…‰Š„€foÿtkh]Zktuþ0 𥮲±£Œÿs`\bkrÿoq€Šÿ•‰ƒoh[aÿlwf]YZgmÿrŒŸš“šœŸÿ—ˆ‡ƒsqÿqpz”›ŽÿŠ|vlvzÿcborxpr{ÿu†ˆ†“¿¡§Œ…Œ°`t÷~qE@€y‰ÿz}rnpoÿ‡ygmhieÿfy”¡š•¤¨ÿ¤˜”š‡yzÿnojqŠ|ÿuy{yn|‡}ÿkklmuieoÿ|}~‰”—›žï­¶°”mpwhaÿpzont‚‹‡ÿ†ˆŒŠ‚€tnÿ_dfsuh`dÿinjx¢ž£ÿ ž¤Œƒ‹ÿof^glq|Šù–$ Tql‚sbÿgnyplit€ÿƒ‹•—š™£ÿ¨—Œ{y|f`ÿfvvux}‰‰¿Šzˆ‚ƒ³nÿvˆzprspzÿ|€›¤—”—¢ÿ¢–‘ˆŽƒqmÿooxy‚Ž‚ÿ~ˆ~vx|ÿrsqy{vjmÿ|vv‡–˜ÿ¡§¢’„}vnel}stƒÜ…~ˆ‡}y þðe_bepsƒÿŠ———•™–ý—°snotxþýà„ˆ‚†wïuula=`wskÿuzx‚‰’•ŸÏšœ“9ðŒ@fqÿvy~ˆ”މ€ÿ‚‚}snmlnÿqtunkfozÿ|ˆ“š™— ÿŸž”‡ƒwsÿn{y‚„…†ÿt{~}}poÿjkfk|utpþyp‹Œ˜£¢¢ÿŸ––‡…ˆ}tÿlqt|}}ˆÿ‚}…ƒ€vvÿnosopwokûky8ð†’œ›•ߢ ’Œ„!€hdÿz{€‚ˆƒ…~ÿx‚ƒ}smmlÿsqp}}nfvÿ{…‹’“ž˜ÿ‘’Ž‚xy|tÿmeny|{…ˆÿ†}z‚ƒtÿwxupsvstÿqvƒ…ƒˆŽ’–•‹—•‹€¯`ÿvsq|}‚‡ÿ~ƒ}…ˆyk¿rrqwyyMpÿ{„„‰•—•÷”zP€|qmýrËð…‰‘†z~¿‚€€rwÖwþow†ƒ‰Žÿ“ŽŽŽŒ€}ÿ}{zw~…‹…‡ˆ…†‡ö ÿqrntst~ÿtt~€†‹‹ÿ•“ˆŒ‚ƒ‚ÿ‚†}prx‚…þ$ˆ‚x{}{uÿovwwwuwtÿssz…‚~Š÷Œ‘X ‚yzÿz}y…ƒ~ÿ|xxz„ƒtÿmmuqvrtzÿslo}†Œ“ÿ™•‹ˆˆï…ˆ{v‹Pƒ|}ÿ‡ˆ‚|}„}û{tZrqrsvÿy†„‡‘ÿ“‘’‘‡€vxïyuuzÀ€†ÿˆ€zsmÿqx{{ƒ{yýw9P““Žˆÿ……‚~|ßuu‚†M`‚|ÿ{{z~~û}zm`zƒ„„„ÿ†€ƒˆ‰ŒŠ†ÿ‡‡~z~|€‚ÿ~|€y{}ÿƒ‡„‚zruwÿ}yvxpuÿx|†Š…‡Žˆß††„ƒqPtqÏrz€†Ð`ذ}€ü©`YPsnqpxzý|íQ‰‰Œ„ÿ|{utt|……ÿ„…†‚€ƒƒ†ˆ„~{zrv‚`ü%`Ú ‡ŒŒ†ü ç0‰‚€{||‡‹e°€yÿ}{€}zz{}yú`‚†ƒ~‚b`¿‹ŒŠ…€Bp€ßƒ†…_ {zþ«@z{{u}}ÿ}yqqxwy€ÿ‰‹ŒŒ…ˆ…‚…„‚€zuXpÿ‚~ÿ€‚€~zstÿrpqrˆþcQ‹ŒŠŠ{z¯xsw} p}©`½ƒp~tttû0€ÿ~~xz~‡ŠÏŽŒ† `@}ÿ{y}}„†ˆÞ•pxyy{‘pƒ~Þ×0x€…ápƒ€û„ÍP…€~ß}„ˆ†…ôqxyæ¹`ƒ‚åqìP{zÿyv~‡ˆˆ†ïƒ„‚³`‚~wÿusx|€„†‡óƒ€”ÀõP„yuÿqpru~‚~ƒý!p‡‹‡‚vïusuvŽP†}û|z@‰‡‚zu¿vwx{|z‡P¿‚†ŠŽ‡—`y÷z~8€}~€€?†ŠŠ‡…‚ÅQðûzzL x|…†þI€~…‰ˆŠ†½‚ºð~ƒ‡‡0}ü÷qÖp}zx{~¿}zwyv„`‰ß‹Žˆ‡…¨`‚„„þpz|œp—`ï€ÿƒ‚‚{vwpÿsx{ƒ†‰†‡ï…„‰‡ãà~yOwvvz€£p’á¿€{yuvvšpy¿{|~„†0‰ýˆn€w{z{yxÖÈ`€ƒ“q{~€zzþ§p}{vxwxƒ×‡††ðƒïp€€þê°}|€…„„ï}~z‘p‚‚€­|ýP~~N|Âq…ˆ„……‡#€ð€~€Üûp‚Å`}ƒú¢p}`ty‚ý„«0ˆ‡ˆ‡‚{ÖÅ€yyö€•`~„ÿ„ƒ…}|vº,pw@…„‡¶€‡M‡ï€~}€Ép€(€î怀€J|x|Ü/pXpƒ`pƒÇƒƒ„ß‘  €…„©ƒRp¤`|<~{pyäÕ€ð~ p„‚}!y` •a°~ª@Ñ€=à{`½€ Y ˜ïƒ~}yz‘€ƒ‚ª@ðËOzpÉp†„…ˆˆŠ‹‰y€€ªPèp×`Ö@|üŸpþp}}~‚……÷‹‹…è`z{€‘B •`€Ö@h ÈpÒ€“{|´ ©PŸü`ƒ~6 z|}|{ƒC }~€~F ì ƒ€-p´¡AíPª`N{{~zî ª@€¡N倄ƒø §€x_q µ`…€„P`ÈpUPס|ìP |~y}~<|z‘ ƒ„á€hpä‘÷|]…€‚Å|Â`~Qpë°ôzz~‚ƒ…áD°| €>°Ç`š¡ÿb‚t L°{~ ¨ ³”Ä¡ì€~€p€¦pçàoP&pРø€‚‰„ Ê¢y‘Kp€Äpæ°o€±€Ÿ±z}M] ±°Á`»°ë¡p¡ ÁбJ L±û`n í IÅ »°©`è°?‚J€ ç ÅPæ°€?4 p€Ëü`€ q°q°ƒ…å€"`{pM°€ƒ(€™ ¢h ¦pÁ‘„ €÷€a°¬`( ø@‚±’¡Ã±ªÀK€é`o¡’0€p»°Ë ÈÀ{°@’pÀj 9ðð˜` Â6 á z  r±ƒœ<±a’Ë|Æ¡ìÀ,À«` Lp>±ßƒ†ƒƒƒÆ±|‘|ø@€×`¼±€Ä-Ñ›pƒB7€¿¡z{`Õp `dÀ9Ñ–€„Áœo€Zp„«¸±{€€±€Ä±®Â¢p=ÀI€ƒë m°цÁ©P^±ì OÁl_ÑJ ‚€ÞÁ}  Á Œ°wÐ"`ðp¡ð€‹Òr °WÐ6°"Áh°{°ípè ì ç0±°éÑ  3ЗaÑ£Ÿ¡Â {°£Àp¡ÈÀÁ¿ÑdÀ¢ÿ‘¨Â£q“Â&áÂÁaÁn¡–`eÑÀp§°þÀİâì –aÉ€0,À&ᣠ‚S°ýÁeÖ@ Áï‘f¡ØÁ‰â<Ð! pUP€ÄP{+ábá‘á]²qpQÀø€š£š¡àÆ¡C  Óg¡à @žeDp¤q±+Á€;ÀOÀh 8 A°žpp{{ïÐ2ñ|á.Áá°Á䀠ë o€* ñÑHò$ᔂ;(Сe{ÃÐӌӨ`pô‘À„`pö°’0‘’¢C ¶áÑl ¸ ˜ÒCpÁ¢>¡6 Ñ`°á}ó’¬ñ:ÐbáÒ¡ájòÿyⳡœqø€ÁÑǡءUPzÑÐâGá½° ¢ØÁ õ¡­ð\ÿÁ‘¡‘ÛäHáõ èñM²Ôãò¿ Å±­Ñ〿Ñi¥ šááÓlÑÇKå€ïÃÐËêÀ €o¢–€p¡Ñ±;Ê‘ÖñÙôѸ±8 ï±ªP§±“|‡°Áò”È¡ÒÒ{Á”p¬ñҀšŸpð ¤àäÀêÁS°ê ¥ Â¡Ânñïâ…ÑjáõUP$ÑÍÁÑOáÆOÀUPÁÐf¢àÑÔãêÁââÝÑoP±Ô ´ãòÐ$ÁoáÀ6ªPÁÁnÑ4’¢ûãð±oP£ñ~á+É##ï‘|fã”áÆÂ:"ßÒiãâÒ±Þã¯ÁàÒ_ñSó#ƒ±¼ò2#<#Ûó[$Pâ#à¬(^'Oâ$±€proÿpNAMEÿROCKETR×LE ï Íý"÷ ï ÃúCûú7cü0ÿg¥üû»PýK0QH`™™>RíZ`™Ó†Q›.&ï&&.¤xP‘‘¿œ?`Aa&&}ÙPa«ïZZ˜.¶P¤¿¦÷¤ZL‹`L½.Yu;†Q)ka«¤™ðPšui½c«;`§Q¦yYP`½˜.™bŸ¨.J&&TPðP˜<P@b.&}.c˜`9˜ßb§R«‘½@PÔco‹.JJÞc«‘Pö±d&.TPUU_7LL½§RYYÊ`ù`õ.n`'†Q4.&J×}L™‘`½q|žÀCa“PÙPbWP§P¿Å×ÅÅY®P}"P¤ix†Qía&`¦¦¤«åaÆYs&}ûadls¿¿­Yã`½½zp]~s}.&`Y`Œr±b"P¹d uü|P©`½L«½}^´u.}}.r.>e=_P`¤ÄU4¦V7qÊ­P«0pëv`¤™ÿ¿Y™L.¸r2ÿr±UUή““ÿÖ±eCz¨™ÁÿŦ¸Y™™Y¸Ürqƒ&¤S†P¦ÿ}¸;ú™.¸³ÉCñPp˜ÚRC÷í)[„Y}Y;ÿú¤.¸wÿöxP_L¤U¨@Þz€O&¤ ^ULý¿ˆÅwÿ N÷NW®¸‚±¢wÉïì¨.£Þzפ«&p})sCíÿCwz÷ÝùUxP§QĦU)ŒÿCáÝ wÉ—ý“>€“ȱez‡àÞz¤LÏ€ JÐqÜPàá€âp‚`÷O)zò']±ÒÛÒÒ»‚;;z…_ÎJÓ…ò€ã€É`ÄžoP4¨Œ!ñ€Ò=2²ã4ht’ð5^Ùú1ÚãÚB‹ CÛÛàDœ‘C¦“)AÛÜ"0FÜ»=EÆ›ÝTGÞ‚aHÝìž·G¯¯?EÞøµI1¯Cªðµ ðÿIXâC!wÿõð™™Cñé âQP_T‘ní·'.!z¡¤¤€£Lo«²²½`U%¡Ý)•£‡ñ ïQ‘²ÿ.²¤U±U!íï].@z 5¤.ÖàPLZXR¤S‹‘§RL.Á ¥PoR:€õ§‡Ä²yË¢m`ÏQ}¿‘.&²¤.zP¤¸Z½¤æa§S©`Zß½LL«_àQ_²)ž³¼pJn`«Ñ€ýP Lêp™¸­PßaP¨Uö3pZLa¤¤²rË¡_ûQJ}ZPýP~`Ž P¤™ÅðPn²%´_XY²VP3q_‘u²ZÆPJ°™¤‘E°þPç YÃY¤²)q—´‡¡(ßp.²8±±Ë¡Ll`“P¶p`Z‘~`}L‹°¦ÃÁ¤²&dáaßawÁÐYž±__Zæ³…«î°&ñ`©aB±ü±ÁÃÅY²&¹dÀ3qçYÁÁ¬QÔ L²U?õñ6z½ŽP°¾«R}²‘}Lç Á?ÃÁ¸½&‘*sÀößbYY©`_ZZZ‹½‘YÂÉD°°s}ﲫ}Zç¡ÎÁÁå½(u_… @Y¿¿eÁL¼ YÂ;.}°|ÀP‘«‘‘«.!Pÿ¤ÁÒÅÁ.J²¸bàR@ÁÃÃÀ¤¯«½L½ÌÄ}kc™ö‰pZ«Ã°}&._?ÅÒÃÁ.&á±ñÆæ8ÀÃÐOÀÔ ½²Ð¢ZÁ' ÐÐZP™PZþvp}._ÁÎÅÁõ½a™_¶¤¦ÁÐÜ‘XPL²ÅZÀ7]ð¼pêð,l²².Z}!_9À° e×YÃÃ5°ÿL.Åzöñ­SÄY¿©`™Y`ZÿU}_ÅÐÐÃÒþý€Êÿ'¤ÁU>7Ц¸¦ÅÃ:ÀÐßÁ¦Z.¸¶Ñ ÿ}_%òS&Zù¤ ±TPY4ríï¤}¸‡óÑ!&_!ûÐ}ZYÀ6qî€Ú âwóÒ½¤à }{Zعƒ±]ɇ à;²Á.àßS™`Ðû²LcÐrí;;ëCõNà'䆿rŒ{!ßNàCww±¸¿““±ÊCzvá]T©Àp²’‹vá'©`8»Â$âvá‡''-“BàCwÉváQá±YघäõUOĦ¡4@!n•ßÑ>3ã4zùâð5pÚú1ÙÛBð CÚÜD!ñC+ó)AÚÝ0FÛ@ð=EKûÞTGcðaHÜqþ·GŒÿÄžÿ̕ߵI¶ÿÈúôÿ!]èX§éï; zòñð¤UîãwàR÷qoP'ï÷¨Z'ÿò¿î]¾ˆ`Z_}¤L`rú4_¸î!þÀ_L}¤½_Uÿ±rbïUZ]Nÿð6Z‘àPUÀZ)vÙ¤¨UZP_Z.XGwawõ¦¤Nì° ±ÔP`Á}@p&“L½öm__þ¡¤Y¸Y‘Y1€âQÙ£LO%À}0šÁH°˜‡±.˜D°zp §Q¸ÝP™ˆÂ§TYaOõ7C½{²KÒÅᆱ;_«@P&.}X#áTê†_,²Sþ‡ÅPä&ÁÄaLÔÁ¤a««˜Â~`.=p!¨a7pÅÅ„ï7wÓÀÏ€&`V°«LÛ`ÆPL«@pF±L`$^öÃÎȰ›³!þÒÀØ“îQ­P‘&}Z‘‘LTn`dÓ PY¸9ÁªSZ›þ'´¼†ÒVP«}‘˜ú±«ËL½ma_¹`dÔ™¸G¸¸ÁªqPÂébïj¡³«ü½Ó€L‘S"öp_û`dÔÜÅåÐS‚7LL)þ].p~±¤Š`qÝnñdþ©`YYÁÎäêäÝ¿¹LZyþ }˜¿²æ‚‘ü°zî±ÈîQÝP¸² êäÎV°W±š$‘L±Hb4!ˆ©ÀüQla}­ÑS‘Ã#¿ÓÅÎþÁPÂWþ›}ù½ÖßaZL«L_Z˜ÿQ%Zõ aˆÀ¿K€YYåÐÎ"/°rÂþ@/#O!(ðP4'ÿ‡çÈ“¿}¤±Ÿ±±CwZÜPt;½þJ2@&¤]ñCÿU¤’4!ðz½½±‡1W[€ï¨«Rš1¦ÿ4@µð~.‘ýU‡2½¤]ï~ï']®®Z€Ò±±ÿ~~zðw½L>Å0àUL˜—ÐqÿUU!ðC~;åñå0ŒC3#áO!6Þå0zwiû€û€±/±‡Cz AUèp'Áê*r! AOýf¿‹)Þ B~](®´äww1‡Cê9 AŒU|Qè¿U‹@!'Þãî4²p”uB}•k܇‘×ãÝŽ’§@–“ØÞàŸ”¸Aª“ÂC¶‘Øß"½–Ù×@èõâKàá—ú@‚î˜Ú^a§#_5_Uáø_©M__Zø›'ëÿCöCŒ;óÿ]bìùCÇ‘rë“05²Ja¿­ß›ó¤Y™Q‡.DZës`aP`UYë­)°PÄ™Qw­Uø»PÔ¡¢à__¿Y­uO°P™™P6;­aN”€L_a¦T‡Àþóò¤_­U||¥ž`¨c™ íëP'E­ÕÀ­ ·°’.3aÏ_U.‘l°n±²‘sL.®`õ¨¤¤z$ab)f_“qa&‘..².­°ÐVÀ4€MiÊ`‡$a]­˜Ûa íÀ_².bq`‘ÿL‘‘²­.²²/¤‘¤.4€Ys8€%w$a e ’F{âí±.´`°¿ ™‘£²²Œf€;$a!4e"+`LÛ _oπ둑­ÐL¿ x`²dÐt}R2Zñ+`#pÉÀ.‘.¹™Z²úaî£>yñ)sïPºÁLJ­q²ž`³`dp²­á Œls8@.©b̲pÏ&­²°&q²>˱™¤.²ÄÂhq-'$a¨.naJР@qçL².Øpv`­­­,8`¹`¤Åàq¸ÃkórÅrùs&á¬ÐÙpL²ã­J €âŤ²i²ì€Pj]$a4­Yp:ÕÀ’_²õPê`öï"&.á ¸_‘.5ÄMj_fƒU­ì±Ð,ß`‡ õP­k`±†R2¸Z€t:Ÿ†-ÕYû¸Ä¡ÕLUCzzíÞ@äÄó±.™rÿr±44±rr4U4±UL¤S$`7U­ p!‘pepý²t€U¤­™wõ_›­¤ ‘¿’ñ]¡ä\,;õO;­_5’Uİà¼=âAà'¤²¸/¨}²‘⛑Úpû­­íÀ™U¨ó/‡wÉìwbq¥Óï‹›nÜwCÉw}ÈBÈÈwCCŸ‘¯›Z‘² p.t€YãU¨Ÿ‘@¡Ô¸U)]!Ÿ‘‡bbJAÒh‘³wɱ’'p²²€”‹êŸ‘b51¦ˆa‹@›+µÜãî5õäƒ"¢õ;yÝ ñÖÞò9 ó×ß$ôJ¡/óT£.;ñ×àBöØi èõ"t«áf÷Œ søÙš®æ÷ˆµ¯Ç¯èEâÇù߯ñªûßzŒ'êÇùû!'ú!;è°¿~.¨ê 4£V¦ÿUCý˜rû÷C˜‹5±;­‹êŸ ¦˜«ßaå~­þ·PUû·P45±'?­rê ¤‘’³åË;þÒQûÒQ5°'­£á_ZײR2ì‚!ÿ¤«ºÀ¡ÓY來UŒÄ°›¨¤æ“±3†a‘J.˜|rê2YW‘˜a6¦`¤­Îp˜­qAžÑr˲µ×a‘.Z_Táìo‚ˆ€‘­v ˜.˜ÿL_«.‘­L«I­s4ʳ Û° b.¢±ä’ça.RXÀ‘?LZ­«_­+Àúº‘!ùpäbE¤¹€æd.ý.é°˜.««‘ÿ­Z¤­­˜.Yä|ʳŒvÁüq¤Äà€ƒÁ@$À Á.&˜¹˜¢q ÁYžžý·)¢3„ÄPsÑ¡ .-`«µL˜³€.˜þФUL!À™×Ä¿5°4øté&úRr˜p&LL¶#Àà˜­÷.u­±Wb¸CéЋ.L‡s§Ìp,ÐpHÄÀ’ÀŒ˜âÀ°&žÀ9ž}KÔ4˜Z5„ ?€YÁL&[Âp·¿¤&BО|ØÁ¤;Y‡NÑU.ZÙaÞakY¦q´€&&€åa­.˜£à®Ð Ñ`VXa™©¾Ó_³’ÑÑL€ÙÕ³°\LŒÀ¤žžFÑóְЫ„>±„_L­J_ï°À„þï°¤«˜‘.¤rfØÃ¤;.äüTĦ–Ðþ¦´LŒz©©ÈÈb«Ø!–Чž|`üheá¦.¤;õ0§âþ1‹³‚žpÅP74!þ’ü2àâ¸ì $ÒD²4»@†Âæ­¤'žáUãZYÕàÐ2e“;©‡ÚÂà«Æá¦˜dáãã‹‘lÐÀºÄU!¿öw~Cèð]þ[4ĸŨ!6Ûîðz;'E©Cz^?ñ4«‘[À˜½‘£4!?ñØâ:D@>ò;s]]L@MB;w‡Qò\ôá ÄUŒ?ñ]60ÕÄs24v@ÛzI SÿHOOT_SPLÿSAMP VîÆò+ÆðN€€ÿ€~|zz{{{ÿzyxwy|~~ÿ~}|zxttxÿ~Ž˜—‹i@)ÿ/Mh‹™ÿ—‚J-:Z•Áÿ²ŽnPRfh_ÿP58_}™ª´ÿ´¨˜‡{|‚Šÿ’‘Š‚wsy‹ÿºÓ˼¤”™¥ÿ¹ËÁªŸ——™ÿ–Šˆ–¡ªªžÿŒpQ8&+>Jÿ[o¦¿Á¨œÿª³«™uL+ÿ F‚¥Àº•ÿ{c`{‘ÿ{’´¿½£sTÿ4$#Vÿ¤¶«–€iYKÿFI`’·áå½ÿL4CÿUp¡¬­¨¥ÿ¤¨¯¦|V3ÿ ÿL{ÃëÿþäÿÁŒik€¬ÙÙÿÀ–W3 ÿ)Icz…tÿ[BJ\[RPSÿf—ƒxutsÿn[G4""ÿ$6R«ÿÊáéãÁykßmx€ˆîœ¢ÿ¦¨£…`K?JÿkÇãô깕ÿuir•œ~Tÿ@6Gh‚¢«©ÿª³½ÐÚÙгÿ™’¦ÃÔÞÌÿ¢ŽƒŠ¤¶Á·ÿƒS0&:Soÿy€­½Ã³€ÿ]?:^…²ÓÙÿÓÆ®‹Y7ÿ*Cn·Æ°‘ÿ`7-+%ÿ.Rs¤Æåÿðãˤ€aReÿНÜêíëæáÿÛÔÈÁ½¾ÉÒÿÓʪ‚hWkšÿµÇ¹…]5%3ÿEVefiw©ÿÊÐǶš– ÿ·ÈÓÚÚÚÝáÿçéÙ¼ ycKÿ:* ÿ+>OW\UJ@ÿ8:GWt€xgÿG43?_€‹‹ÿ€os…žÅÜðÿôëÚµdA2ÿ.:M[gig_ÿTPUf¯ÐàÿßÙÓÏËÊÌÒÿÙÞááÞÓ¢ÿ…\?)&>ÿZq„ƒraI9ÿ*")ÿHm–½ËÍɾÿ´¨¤¨°ÇÓÚÿÖëŒnS?7ÿ6:@<.+0>ÿ]{©ÇÛßͲÿeF+-@UtÿŠŸ«³·º¹®ÿ ŠtZA-ÿ#4Sr¢¼ÐÔÿÐÆ·ª›‹mOï:)" å  "ÿ(3>PYUMAÿ65:MmŒ´ÃÿÆ·–zYL\tÿšºÏÛÜÙÓËÿÇÂÃÇËÒÒÇÿµpQ>ARtÿœµÅ¾¤‹fOß6+&&+ŒÀ)%ÿ(-5@Odz›ÿ®ºµ–zWCEÿSyž¯³¤‡jÿG>FQhyŒšÿ¬¸ÃÊÍÏÍÌÿËÊÉÉÇÁº®ÿŸƒnRECKdÿ}˜­²«™{eÿL?402468ÿ9:<>EQgƒÿ–¤¥›‡fVSÿZoƒ™¨©¤š÷†€Úðz|~ƒÿŒ•¢«´¸¸¶ÿ³­¤–ƒjYHÿELWn€”£²ÿ¸·²©ž”Š‚ÿ|{}‚Š˜žÿ¢¡™ƒyphÿc_ahq}Ššÿ¥®²³²¯«¤ÿž–އzsmÿf`ZVSRTVÿ[]`dhnszÿ~„‹”˜›š–ÿ‘‹†ƒ‚…Šÿ‘’–›¢£ÿ¡šƒxrppÿqqnkf`\UÿQLMT\is}ÿ„Œ•—™››ÿœžŸž˜‘…|þÆ1^^]]^_cÿehmpw|†Œÿ’–—˜˜™™™ÿ˜–”ŠˆŠÿŽ—ž¤©¬¬ª÷¨£Ÿö1€si^ÿWSSSUVY\ÿ^`ccefgjÿou~ƒˆŒ’ÿ˜™—”‘Œˆÿ„€{uqkhfÿfghhhikpÿsrqoorw{ÿ€„Š‘’’þù0ƒ…Š‘™ ¥ÿ©ªª¨¦¥¤¢ÿŸ™”Œ†„„…¿††„}{Ûðyÿspkjknpq÷twyÅ@|„ŠÿŒŒŠ‡…„‚ÿ~ysnjjmrþØ@ƒ~yqkgeýet@rtsojgfhmsx{}éòÿrrruxyxxÿx{‚ˆ–šœ¿œš”‹‚xŠ@gÿhmqy~†‹ÿ’†€{ww·xy|Pywíð|¿ƒˆŽ‘””D@—–’ކ{x6Pÿ„‡ˆˆ†„ƒÿƒ‚‚ƒ„…‡‡ÿ†…‚€}}€„߈ŒŒˆƒå@km¯ou{mPpP}wrmji“@iDPÿ‘„zqhea×acfŠP|Öð}{þQxxuuttuÿx{€†Œ‘•—ÿ—”Š‚}yyÿ{|€‚ƒ…†ºÛ@ŽÌTŽŽžpŒïІ‚zæAnr{ûƒPŽŠ‚{s}mŒAimnooÐ@ox}‚…Á@yrÐ@ÿ{‚ŠŽŽ†€þåAgedddefûhjöPnnkihûgfAknquzß~ƒ‡Œ¢@Œß†‚{up‹@eeöAiiÍAsx|‚ÿ‡ŒŠ„€ïytnjAjmo?prstuwk`Péy’0Þðz=¢@€µðM¯_¯q¯ƒ¯•¯§¯¹¯Ë¯Ý¯ï¯¿¿%¿7¿I¿[¿m¿¿‘¿£¿µ¿Ç¿Ù¿ë¿ý¿Ï!Ï3ÏEÏWÏiÏ{ÏϟϱÏÃÏÕÏçÏùÏ ßß/ßAßSßeßw߉ߛ߭߿ßÑßãßõßïï+ï=ïOïaïsï…ï—ï©ï»ïÍïßïñïÿÿ'ÿ9ÿKÿ]ÿoÿÿ“ÿ¥ÿ·ÿÉÿÛÿíÿÿÿ#5GYk}¡³Å×éû 1CUgy‹¯ÁÓå÷ //-/?/Q/c/u/‡/™/«/½/Ï/á/ó/??)?;?M?_?q?ƒ?•?§?¹?Ë?Ý?ï?OO%O7OIO[OmOO‘O£OµOÇOÙOëOýO_!_3_E_W_i_{__Ÿ_±_Ã_Õ_ç_ù_ oo/oAoSoeowo‰o›o­ox¿oÑoÛfÛo&8J\n€’¤¶ÈÚìþí`€…ÿðoBTfxŠœ®ÀÒäöŸŸ,Ÿ>ŸU,.€Uþ\’BŸƒŸ•Ÿ§Ÿ¹ŸËŸÝŸïŸ¯¯%¯7¯I¯[¯ìm¯¯j›m™ l“l’1Â¯Ô¯æ¯ø¯ ¿¿.¿@¿R¿d¿v¿ˆ¿š¿œ¬¿¾¿• €Þl‘ª¡’ l‘è°ò¿ÏÏ(Ï:ÏLÏ^ÏpςϔϦϸÏÊÏÜÏîÏß— Ы¢ï²ª qÚ²Ñ3ßEßWßiß{ßߟ߱ßÃßÕßçßÀùß ïï/Ò œ¢q’°¡Zá_ãtï†ï˜ïªï¼ïÎïàïòïÿ€ÿ(ÿ:ÿLÿ^ÿpÿ𲛢°£à°˜ó°¯ÀÿÒÿäÿöÿ,>Pbt†˜ª¼‚pâÛ²0ÓpáÙ0ß$6HZl~¢´ÆØêüЍl‘oéÚ±_âÒ°üÒïoY/k/}//¡/³/Å/×/é/û/ ??1?C?Wå¯ùZá¯ñ-€bpŸš?¬?¾?Ð?â?ô?OO*O•ÑDgUp5eàÂèpqqyŒ`f[fUý"\+;WjqsuwwyqªsºÝï%7I[mí@”… h›†¦€i™ŠÜÌ vloY«|&3ÿ>Ujuwy{{yoOkbúŸ/ŸAŸSŸeŸwŸ‰Ÿ›Ÿ­Ÿ¿ŸÑŸðãŸõŸ¯Û‹usY$~/]/JfquwjDGR:¯]¯o¯¯“¯¥¯·¯É¯Û¯í¯ÿ¯¿#¿ø5¿G¿ HQjuyuù[+¬'P@bnqsy{u^5u¿R¿ª¿¼¿Î¿à¿ò¿ÏÏ(Ï:ÏàLÏ^ÏpςϒÌ-`qü‚°j¿ J^jnoswoQ«u¼ÏßÏñÏßß'ß9ßKß]ßoßßà“ߥ߷ßÉßÑÔ$Sfósw¨ÏÌÁ]dhloqfBGUüßï1ïCïUïgïyï‹ïï¯ïÁïàÓïåï÷ï ÿ#TL^lùqg¿AHY`bfljY34ÿÿiÿ{ÿÿŸÿ±ÿÃÿÕÿçÿùÿ ð/AKFWdjóoq(¯'PHU[^bfdM«v|Ÿ±ÃÕçù /AàSew‰Ž>QÞþÑnqoW—5HQUY^`]DF¼ßñ//'/9/K/]/o//“/¥/·/É/ÿ9HU]`dhj{nlØ~;JM¾[S9ó/Í/(?:?L?^?p?‚?”?¦?¸?Ê?Ü?øî?Oi5@JSYvã"hS— >Fý!UH*3O OhOzOŒOžO°OÂOÔOæOøO __ø._@_LX+;@DOÿUY]bdffOþ— ->DFHMQ“O<æ{RLY/ª(û((kn$"" ³""×]µ(&ÇSù$âT/© "$&Ÿo&o8oJo\ono€o~´ˆ19;>JQ~ûddž-<>@D/HMH1²lLÂhµ‡ÿ"DW^^]Q/þ¯Y(3UYQHÏHJSOðjõi]Y¾F¢"LW[O+«+FFp[ïkPbÀt†˜ª¼ØŒ/3¿/3BMSW`ÝM«n9;<¾`@&æò|F>‡âe53<ÿSjqsqndSþ+§(U^djj^ÿUQW`fdS/Ý*¬P(($–T"ÿ$/Q[fnqlþ‘ H]hnhMö–X+¢`SQWblldS•§¹àËÝïŸÛÖ+/*ï$$>JbQ^^L.¯\17ür9–V:”÷B5-«*BB@÷9Ãgz¤<-o»FÿMQH;++>buy{{ysYkTÿ&Wjsusn^ÿH5/7Oluwÿwusssqodž#r$5J]@ðÁÀuÿhD" 7DOWç^fhê&(p^^[ïO@1-Å wywnÆŸ¿*¿<¿N¿`¿r¿ø„¿\¢7FLî¾]]J¯[/5Û33} ;+ˆ¶*3î¼±97(OªJUWûO<Ô°+[ow{÷{{u²¤&Ufo¿ssndO3_ <ûbs­¡wson`ý>U‘&5F[bfþán[5"5D@;` smlOÇ_ZÏlÏ~Ï0Ï¢Ï´ÏÆÏ(œ² °×DLOäp[ª¼*3531½°5‡Ì°ýÁ¹/IÉŽYQBDA$ô*€lqê#$Sdl¿oonfWBLSÛWHñc"L>ð^Qlæ±:€Wnlub”«–ߨߺßÌßÞßðßï4Ò}*ÜÂ5DJåÏÒ\P7ûÀýÀ-IÆ/î<à133VI"FSÏWSH3Â9ÑsuýnªbJ`jllÏjh^J²*ÒwyßsdSJ;R„$HýUårS; 37¿55;BLMƒS"íJëaUBÔ³"QhHÐwnQIÏÛïíïÿïÐÿ#ÿ5ÿK¯*kS5ñB$ãmÔsV751/G/11Ô·ùÀ|ñ/k FQWSJ7kRÿ9S^fjnobýBR*Yfhhf·fbU‘ã"O_€sßuq[>-kU@ÿMQSWYS@(¿-131¨àDþÃbBU]]YUûJ3[Lbjouw±¦"4FXjP|–öYõ`öYjû¥à1-///kWyñ½É*–WžòMáð§Q-tg€dYk}À¡³ ™ Ä/9Ù9Í ¸--‡@ŸOUSOFT“ÙðSßY[]YFña MÝ`û[U@Êã$MÕ]å!j*HêðFJƒJ;ž±%|ñÔ² ÐWOUQLDeâ›ñDE€lqoWJ›/­/¿/0Ñ/ã/õ/;&+†!ïžC>;73¾‡1nù/-+ñg&M ÛJ>³+>PSS»L7U‘ L]; YûUMq27MY¶íjfªh+9¼aBë5 ªP+¥0("nU‘BSt!F;DEÿ FU]bhnl*NÙ?ë?ý?O!O3O îxQ7¡±%?;@31¥0*$û z%HWWQM{H>Ö/FQY>€fê~_+_=_O_a_s_6=-+n†"953?8(]0MûH<&19<<×<91-s±2MJö9¥1-/35;£ f {`` YBMJ¹Q´ïTæJ9€95À*SYWQJB1fàÿ&*-(&&"þÓ/DLLJF@Þ‚¤->FL¤PQ@º“ø*&91(Ji*×S[Yv 7kG1B JP]M‰ßÚìþpŸ"Ÿ4Ÿoû-+*W‘Ý+åð3;H¥±`bùbŽ8ñMHB<7]1Ê6 FOy’-˜Uù·@]€@1 &í*ä@Šy"9D·FDB“¤1ªALcMH‚§Jâ€73ã"’›B‚§añ$€W?$¯€ ¯2¯D¯V¯h¯z¯5_93*"–¢"¤0g-7J¦PífOÊ8(O´1>9–µ¦ï"O^]‘5/+×-*& ®+Ý@>9þ³*5;<@BDSD;Ê8yð3€5Q8 ֨ɇ(9cðã°NxR¿Àd¿v¿ˆ¿š¿¬¿€¯95ý*kF"/HÝW¥¡hhQO(HWYUOHBϧõ¶Ö-Yb^²€à¡æ¯?ï179;“$-58:À`Ɉ9;ÍPвÊ;+Äww+<#0UUF÷‘ϣϵÏÇÏÙϼëÏÆ9<9- ["½Hˆ1hljUÊ7"‹Q`ÁFÇ5Ö“õýOË@[UM>+&ü _X2-1551*O$ $*)pPà1—Wï9By@777Ðww7 \ÑB3@cAO­ãÌßÞßðßïðï&ï8ï?<@;/öcÜ JE`jlnn>‰(-]fb]ù°¶‡þuî$Wjjd]W3O>cß14 (æðU‘+--*(&"èEþÕóJD@<;;7>ˆË"UhhbÜ µ×-;DJMQOÌ™€ÿ#ÿ5ÿGÿYÿkÿzû"ïDF>1¡í L`¿fjnoqqI =Q‹0`YSJö–´ÿo&Ynn¸ðQ>%Ïn$13O0*(Ç༩›0LOJF˜Ð7üŽˆ•âllf`[SýBÑU9BHMOOL< TfxŠ8œ®ÌFOD7gvÎnosG?†$Ynojd^WJɆ>ô&[oojxà¯î †333"À þŠ~HUUOLHÓD@¢C$ n›àUBþ!1@HLQQMD¿C‹¯ÁÓå¾÷+UO;G"ÿQfnqsuyuý[?†&]qsnhGb[HÑV4/q0YD!üC;YÁ-v~ü²Ú¢Mô™èälo\) 9HÃÑH!sÊ/Ü/î/ð??$?6?(W[ùHŸÛÓSjquw{y{)(1fuu[ å[u±At?$YoÅs÷MÑW_@WF;e>šÐ3Ó·HKSdñàÙS´Ø[5lq÷]HþkD"DMQSQL>¡9O"O4OFOXOjOÎ [f]Çß–ánu÷w{{h8 Snwmy›0[>˜P7É€œ³Oìàouqp_) »7763@BºQ+YŠt`j‰àYŒŠþr’Mhsqnh`%J!³`ÝPDÿU_Àg_y_‹__¯_ƒEjn™WD_O`qf0§I$ÿ[sy{wql]ã9¶0vqó_ Oélv0pSô$;w<<1a$>FÙàfü`/*cy¬FhnP÷^S;ŽLBbqosold*„&J?PÍ¿?•o§o¹oËoÝoïoÎÃTluo긤ØfsöäRwdÉ…&[s{ÿ{ysn^>(&ó;>Ï3Ddûqu0RYJ*"""(@HHB5PÕo5DHFùA55Úã-(CX!p`Q3ž}1Wlq1Pª£" FO`H Ðâôð*Ж+UhsguoWÞ<«‚[ld1ßyywlSkä$Wÿqy{yundUÇHDBs„0Uj¿qqqolh O?JJLMMHƽ iJ[šÑ5À‚3-Yo-`ooW`^LˆÎ{FãnjY+Ëà? DOSSMN× ŸÀŸ-Ÿ?ŸQŸcŸ_l>OÝ`¥ðl^F„n"HŸ]hlno¥‘‹– ÿOjuwwsndáYÿ€6³Ÿ ÐB]h?nonljf×1¾qí;¡6;·‚>;9¶›Ð99ù <7Œ×F`jjhfb{3þ |Q^fjjbO_*"&@Mš @îF€H¯Z¯l¯~¯¯¢¯i-HÿS]^``^[M|Ç©"+/;LYÇ¡¼ä¡Ë¦@]lÞfÇ[QDîDó¯kÁFY×`hhâb2OL^È5Dø’<ýÿ9;<>BDFDý5ÂY^^][WùMI·¤7FHJÀHûB9ßê&15;BáFÁ" Æ±`^WãL>Ö4ÏkÁ@MYÿ][YYWUOF¥@~º~yp<=±;×<@BÀL 9Î!ÀHFD/3BÿMWYWQOJB>~¿ÍÏßÏñÏßß'ß®ðø&*+GÒ*+Ï"&&(FÔIÚ+@Æ·€@1ußÕñ3BÿHHFFFD<-½(_ *7@Ùá9ü>±C°FJLOQL™9¤'FÑ** 4(3@¢ÐB;¦Ûïï+ï=ïOïaïsï…ï—ï•JG*+* ·î~2*ßâÞ 1QS¹À73135777;Žÿ0US@ŽOÿÙæ(ÛßJÿ\ÿnÿ€ÿ’ÿ¤ÿ¶ÿÀÈÿÚÿìÿþÿº\UbÿfbO<1& ÿ$+//17>Jð´À`/[m‘£µÇÙëý!3øEWÂVqodJ/¶Ž’;9LF[]_/š¬¾Ðâô//*/‹w/L†^^Y¯Û/í/ÿ/?#?5?G?Y?k?}??¡?³?Å?×?îSíYu€u`y"J[È¡WOO-O?OQOcOuO‡O™O«O½OÏOáOóO°__š“tw^݉"L^bdb^Q\¿[_m__‘_£_µ_Ç_Ù_ë_ý_o!o3oEoWoš“ÛQn2Pd/Ȉ*U?bdd`YFÝŽšo¬o¾oÐoâoôo*€<N`r„– ¤DfsywnY(Ȇÿ H]ddb[M7ȉÕçù /ASew‰›­¿üÑ#ªUjquqjùWw¿ 1U`d`[OŸPŸbŸtŸ†Ÿ˜ŸªŸ¼ŸÎŸàŸðòŸ¯¯º%BYdlþø ]J(" ÿ*HSY^]WM<ŠoY¯k¯}¯¯¡¯³¯Å¯×¯é¯û¯ ¿¿1¿C¿üU¿RÈO[`bfdû[O ÑLW[WUQF;H¯˜¿ª¿¼¿Î¿à¿ò¿ÏÏ(Ï:ÏLÏ^ÏðpςϔϑÛJO[]ÿ[UQOOOQUQJDPbt†à˜ª¼Î ->fwþs`9/F]nqlWÁ/%/7/I/[/m//‘/£/µ/Ç/àÙ/ë/ý/?"¬9lw÷{u[‡²/LfsulO>ïT?f?x?Š?œ?®?À?Ò?ä?ö?OOð,O>OPO"\oyyoýQã5YqysYAÿ”O¦O¸OÊOÜOîO__$_6_H_Z_l_~__~"ë[syyjFúà Jlyt`ž_Õ_ç_ù_ oo/oAoSoeowoÀ‰o›o­o¿oÑo#ê]uï{wb5Þd9dwÜt@C9"&C4 &]"Êr&(C5 uèÇC?Qcu‡™«½Ïáóê„ò;u[%(^u€@ç¿/SbbJ@ÔŸæŸøŸ ¯¯.¯@¯€R¯d¯v¯ˆ¯š¯îa²QDôúÅ~’[ƒC(OMHÿ91@duqW"ÿ+Ffss`5"FUhsw@Ÿ"DUdã¡ã(ÿYd[<+(3Lho`-¯¿'¿9¿K¿]¿o¿¿“¿¥¿·¿É¿ÄÛ¿/ƒ^öe}”â(Yÿ`S@+$;luÿqU"">duÿs[1+FLSfÎÀ¡-&D ÂB„([ÿjjS1<dsnzOÏaÏsυϗϩϻÏÍÏßÏñÏßß’i™Sæ0€yÁõ¡fÿbH+&Yns÷jM /0juo[¿;JJDFb@€[ó5B_ÓBÔ[lqdDDÁ+`uB‰ßŸß±ßÃßÕßçßùß ïï/ïHAïSï\å$±Ym•O‚€ÿ QjlW31bol]>o@ÿnunYQM@/3bÒ;F> â‚åuoW1:„‚ßÓïåï÷ï ÿÿ-ÿ?ÿQÿcÿuÿ‡ÿ¸™ÿîmmâwfB·P/ÿdqjJ$(Ußdh]F*®RwnUQ@+/`­à¯YD;*àñw´¢/ßdsufFDÂ1hÂ);M_qƒ•§¹Ëß¿2‰}’ýq¹á UnsdBÿ*-L[^YF+þ{”o[D+ 5ÿhwylO;(Ï5huó²wq Y3rU™àƒáFXj|Ž ²ÄÖèàú / ßs˜/€uufüzÑôðsbBJMQçUM@9/p„¯ ufJ÷ôð=!ô±ná3Ô&]qsA"__)_;_M___q_ƒ_•_§_¹_Ë_ß2Ø6Á|Òòïawd@-*p†Â= o8= 7²1oST€ª2ùôfq€2DoVohozoŒožo°oÂoÔoæoˆøo -Uq6dž0UqfÑðR"ª1`+%Ùñuw#UwÅBH&?+[qwd7÷VÁA„–¨ºÌÞð@&8JZŒs yutÞlàQ`f[?s$OWqud;À;3ô&[qubwr•ˆ«0ÿfB/>1+Sns](ˆ‘MÐôÃÕçù ŸŸ/ŸAŸSŸeŸøwŸ‰ŸžMUluwu¼¶‚làHY]W~„÷ Oh?`-$ "û9;Q!-bqqYøôÕ—•fDLF5ß*Fbl^(Wd}…¯¯)¯;¯M¯_¯€q¯ƒ¯•¯§¯¹¯Ë¯Ø©"ÿH^loon[-ÿ  9B>7"F`lhTа¶ÿ"UjnbMLÿ>(5S`^F?" ;QUÿŸO¿a¿s¿…¿—¿©¿»¿Í¿ß¿øñ¿ÏÏ&9M[ÿ^``^S@73?39B@B>3¿+FY^]Wú ;5-GÀW?¿Ï¡Ï³ÏÅÏ×ÏéÏûÏ ßß1ßCß~Uß*9BHJmÐD<97799 hžBÂ@HJH¨à‘2Ï9FH@Á‚”×ü•Ñ3$3@B;71+(zÚÉßÛßíßÿßï#ï5ïGïYïkï}ïïîþ¥&*+¬á*(&d³à$«à f"( e ÕçÞé&²àD ÿÿ/ÿAÿSÿeÿwÿ‰ÿ›ÿ­ÿ¿ÿÑÿãÿõÿ+=Oas…—©»Íßñ'9K]o“¥·ÉÛíÿ/#/5/G/Y/k/}//¡/³/Å/×/é/û/ ??1?C?U?g?y?‹??¯?Á?Ó?å?÷? OO-O?OQOcOuO‡O™O«O½OÏOáOóO__)_;_M___q_ƒ_•_§_¹_Ë_Ý_ï_oo%o7oIo[omoo‘o£oµoÇoÙoëoýo!3EWi{Ÿ±ÃÕçù /ASew‰›­¿ÑãõŸŸ+Ÿ=ŸOŸaŸsŸ…Ÿ—Ÿ©Ÿ»ŸÍŸÀߟñŸ¯¯'¯9®pr¿opNAME9  ÿTITLE_FO{NT]¡Æe£óeÂ9 ÿ 9¯¯¡¯³¯Å¯×¯é¯û¯ ¿¿1¿C¿U¿g¿y¿˜‹¿¿¯¿|¯Ê³‡þʰüì§¡þþƯþþµé±µ£é±é°øé°æÿ©þÔŸÛþÂÞ°þ³Ê°Ø£îÊ´‹Ø·ÀþþŸ;ä"Á›Ú«Ê¿<ËñÄ¿`ÏdÀ£Ÿÿ“øÎ­þ«‹ÿþ³þî³=•ö°ÔðÞ°ÀdϩϻÏÍÏßÏT OÏßøß*ß/Ñ™‹““¾Âþ¹îÖ/ѯïþ›‘þÀ•ŸØÿúŸÂþ±•Ö½þgÓÌ—Àæ}Ð/Ñ»þ‡þ-Àÿ¿èú¿ÐþÈÿ½©âþðÞúÿöÞΣþ¥9‡ Áe ü…§#À/Ð?½È§Úƒ/ßÃßÀÕßçßèÏ ïï#â©üö—ůþ±Ô£ðþÂÖ—Â¥ügÐøÁðþßô›èþîHÑþÄïôþþtÀþþد¹îì#àìë±}•#àüþü©/åê…æ·Tà—ZÐÿÄþþÚÎÖÿ…ƒðþüÿÒþ䙇îþôwÈhÖ¹ögÐ;òزÎþÎÏâü± ”À#âðܱîïÿòÁ ï*ÿ<ÿNÿXöâÌ¥¡ÆæEÑÿÖöÒþÔÚÚÞ½ð¡à‰üГfàëì»Xð§XÐþÜ÷¯ú‰QÒ¯þÞóênÐZÐþ¹•þçÎ¥þàXðÚâÄßþ§ÚÜ™ñ‹ÿâþÒþ§¯ü}اÒÂô‡“Ðýø—ÂòÌ©þµù«ì°Náþ¥¿þ¡÷Ÿþ¿XñÐü…¹ïþŸ¡þŒñƒøÞ™þ±µþ¥EáÞÐÞèò±Ñ½üÏàÂ܇ä6€HZ ÿ~¢± …ù«áåÀêþüÈ…þ±âþúöþêþ—ëþö“…ÚþDOÒ³àҖѱà±ÞÁ÷Òþö±Ìþðúê°Æ±Ÿþþêü«þêÔÞgÐð—Ä‹ñîgÐÒÆàÞþìôûþü*£…³þÿü‘“òþø¹æ“ü‘%ÀÂþ…âë°ƒë«ègÐê¡àÜþø¿øþþöÆøöñ‡ÿÆöüⵇ›ƒê౟±ÃÌ|sÂ{ÀÀ‡ÀÁÅ /Ž/ßE/ä㯞Eщðú‘ùñœÒ— þòÔÔKÐñö°ü±€uá½à§àt•Д"Øpàˆ"†"ô²{"À¨àÿ±ºðô¦Ó§þäK"Ä ÑØ/*/ü/ 9¯§Ò·Þü¡ 1—þêãÖÖ“#£þ±óòÎþè 1µþþ¡à71áá0ááå°Ü±±þ‘Àe uþvÒìŸþîQ1wàþ± 0­þâQ1ðò/£<õ/Ç?mÇí§Ø³ÜúÁü·ÊÿΗµ‰ìþêûâüñ°¡êØÿ›½þ±îÞ.ˆ1Ö‡ÆÔ#O5OGOYOkO}Oï¡O³OÅO³—ÆÌ±ô»!ÖAíÔ¦ÓÎî7öîî­ngѯS$2º"3o1*ßñ”?T_f_x_€Š_½¿®_À_Ò_ä_ëS±ª$0™ÄmÑì±ð ¡ðä°§Ñ&Ui¤_@o¼RoWaÊÞÞ›QÄÂÎáwo‰o,o­o¿o¼Ñoa0¯‘úæñþȇðà—Ïì/&{Û­Ïâ¥þä2ÊüÖëâîâ&q“öó·þ5›´òöQ1ƒú÷–ÑX‡1½àáâìê&q‘éµþ1¶ðúÔƒøÜ°âb£à²òêò&rö Ê&½v áóL/ù»\rsÁòþþèÀþôbÚþüÔøþè¶±Ðþöð±þ†1Òßþü‰‰oáƒø´a?0ð þÀ‚2þ çÕ"*é±§Ñâºà©NmƒôþàpÐÁ9Ûôr1»þ9Q½þçú“ßßñÒþø;úþýD¯æþP¶@ÈÚÿoêŸ'‡âÀ`áŸü<’E=‘•Î<’¼ R› A Àg’1ÞmŸtg’¯ú¢"çH€ Ÿ‡OÄŸÖŸèŸÕ˜”¯»öþбы]€þÿþàðþþ³Þ¥©*ÆV€««øXÎõ±³YÑüÀîu9Tê°ÀPqøþúáâ…êþx"/1Œ3ýlaîúüâñ‡¨€gÑOлÞÞÔƹ^"”¯¦¯¸¯¹ŸÜ¯´î¯×Op¢»&Àòð*w€SáEЇöà»Ï¡ÒþÈ0÷òKêþÜó¡"€Ö!…fÑÑØQ1ˆ€gÐ☃ØÌ¿ÂîÍ$Žñ"Ͳԡ7•ЧÞ þµàÔ›RàöÀ±Ò›¯›±ßº¿Ì¿Íð¿ÏÏ^¢§F¥€R!³y‡ià=´ÊþÜîosŸ—üþ—òS™!þêŠr§P‡x‚ìþ›âŸ;€»‹îðgÔêã‡c ŽÂ¿ “€f!ª$El€Å¥$k3+ð†"ƒÀòáÏÀóÏǯß)ß;ßAÒ‰¶Hq‘à"€þì¡àîÊáþþ™íñøÎÄ…µ\qÜfàAÒ‚€„ÊþþúÖþB¤àPæ>jП¡¹æ,©´G ƒ…yàjÐÒà]€_ÒA©7#1_ÀzWáƒn ÔØã‰­C_øß ï ߈.ï@ï5Ê0TƒàêòC…îf“ \£5½$¹ütclaþð˜Ììc ò‘w0ö“[¿þ  þþ³p‘]ÐXˆ€…€‚€ìR·…¡ÕöX€‡ «p0ô³Ì°…؎˜’§ÒÞÀHröïÿÿï>ÿ`PÿDÞsòu2RÞƒkþS›‰ŸŸŸ‘wÞþôp¢‹ú’ôDî¾#62¸"?„^¢qú?¥;€0Ôþö©´ôa`òxƒñpµà,-ÿPbt«âîáÒŒâN0'°z0‰úþëà‹Øàƒ`‰•ä”w€‰@^0‡öþGÖ¥üöŠ0PôÝÁ„Ä m£G P`±ê5—]€¥±ðì‹RpR œƒ‚¯àÜæ¼±»ªw±àG î˜°«[Ñä‘¢—Ÿ§Å&89p\n€†Ÿ¿·J£8Éàc³càÒ½üùiÀD_Г€›Ãày xÀÄ\0Ž$1þþÚˆ€ApµàÞîk⡱PÒ‰üTfà…¿èèöþíü{³™ü“#æþe"€å= Þ.˜ó»þêÝÄ…˜á2/àD/oWz/†(¿Ð…:\0Â80¹Àfã#¿¡øþ«Áʇ‡ðä0/`/á/ó/Ÿ³Ö‹‘»íȧ·½˜óãƒÀÒ~‡µ‰üö‡­ƒpÀG°‡:UNQ?c?u?ì‡?òå‘Θr—ÖØ¯©0°·…±2ì³L©°x°æ­p¢l€ÆçÓ?ƒ·òþüΑ£×1ãþÖôCã2³tƒ¯ìoä6p8=O)O;O:ó!ö–Àò²ðò±‰:òj6·ð½6Øq¢üÂ…€Â¡Û1÷;ö_Ÿ aͳöd–Ÿ¨Ÿ=_ÌŸüÞŸðŸ‘ÚêÆ¡b…ƒ‘Р0·±âº @ÜðÛÑ€0ò0W¢¡@üY°âï0¹ Ã1t°Ð›šÃëPÞ˜Á Ñöò0„ Ú`¥t°Ìs±Qñ8¢Õ°hñj°ßpâv¡©òÂ2ÏŸþú“j±Bb·þõöÒÀú·³—ÊÜ¿÷ìþò·µ‹òþìDæ“ÌÌvÆà¯ò¯ð™¿(¿a(—ÀÚÉØ’ÃäòûàPе¯Ðþò‡ðþ±ëPi³ô4B€½ô3ünÂI­Ðe€Е0þê$m üCГ‚°è…‚±ÀEðÍ6¿Sp±¢ò±±3°ò²Oíàò²à`ÈôI‹äêDïÏÏp~o:ÏLÏ]Í›ÔÚQóã0x€…€‹ÝðÐò09-»/ü‡Ðè„¡}ê–ÀÈøöƒ‹¡JI€ƒÀà‘-ã]ÁØ0ÂÝðK!ÑПy­Å±ßPàîø­0šëPü‹¡Ê•ï0·PܬüCÆyÁà…‚‘¿Î¹_$ß6ß7ÏZßþlß“¡¯¹¿Î§Ê‹ÚºQüA»3äþÿú‰­¯Øþö ¡“…‚¿Ð֩߉Á¿Õ‘ÎÈßÚßìÚÈ´ß è‰½íå*ï<ï=ß`ïrï²oG©§ƒŠÀ«PÚ ÖîÓ"öðÖ\€\öðÎ ùð"´âìºæ’0²äô]´â$áBÜç™ÝæÈS«PÚW¹û€ä\€þ£óÀÀÀß øƒ‰XÓðü@h±‡¹èPÜÓ™Q’:ÿLÿMïpÿ‚ÿúŽø—……þÊ‹½Þ¸2Ôþè¹ ñ‡?úþÊ£þþÛ0€0Q«Q€, ‡Âàà€Ðþü…ëP÷pßP±¡ï0B`ðà¹ÔñúþÒ4žCÿPÍÂÂþºP¿¢>qý0%ñü@€«PŽñp%`’PzÓ³÷pI[mnÿ‘£|µÁ·ä™»Îaî{Òôþ·ªà…­ÙÄ…/—…æþküƒ¼Ðøó1Ÿƒ‚°¹—˜@öþ«ðàþY§€y2³³ü@·I ÞB`âþ¿Èü@È·làð ñÂâçPØÐt"ÿÎþÎöþÊþèçæþÊÄÒPŸþøüW’»çPòýð<U €Ô Ipþîâë0ß `€¬0Spò0}¡îø’à—ȸ3©»Íßbÿø//oÞʯ›¹¼m!0€§±þêúðìŸþü‰üx0òPÖÆ¬QòƒÓPp€€0·ü·òƒöØß \ &!Ú —3óa:c¡À& ˜6z£àüôÂ2%€Ò8B€/ P›‡öÎàÚ ¢¡À­‘ÀÀð “Û0£Æßð/ñ?&?wÖ6öïÄþƱØ‹úþóÆÜ3ð•¯þø=n!â…øF   @Ù°èH¡6Q0‚°/ œ#Âà‘$+¡`Bd«?½9Œ ¤›î’ÀyÔ¿fñ?O?'O9Oÿþe0¹Ôâîîîþ÷ô›‰‰ÕŸ½ÞCÞÞ4p@¡`Á4ƒ˜£@?ƒBcà O·ò?ƒ§Ã£áø!¢Ÿ#¿DºPðîîóâÀŠÁüC¡³úðv@ÚÎÌ>ûO __ã"OE_;¸—‘ÿƒôþøîÞµ©á…’ªàBbðàBbî‚]¿¢î›_­Z>!íPRÊÇWôPR«¾Ôb0±¿ÿÔµ‰ØêÖÂɯ6ÿýU4_!oŸ(p±ðÙS³3r²J èˆàÂR¥t#…üЪ#bÞÙS½3™Kdô*ScÒÁS¯t#F #aÕêÙSÄ3£Kcƒö`÷à»o oßo噕Ü0øðüþ·ƒ™¢¹b΂+ #âÖKcÞ(0#âêKcîOZsÿ™£úþ½¡ìÞÞÔο¦ü¯”¦œ¸Ç{¥îî_€{Òæüq a“¯þè±þìV!ì¾@æ ¯Äá£þô‡ƒð2‚69q­î¹b™îò¿2DVhzŒžµŸÂÔæø ŸŸ.Ÿ@ŸRŸ dŸvŸˆŸšŸ«¿½—œ´”Ò¯Õ—«ŸñŸ1_¯t'¯c ¿rÃîøB3…ÈðÂRçÀß/i¯{¯¯Ÿ¯±¯Ã¯Äoç¯ù¯ ¿®¼“ڱѰ…¶°ôý—v°òÚþ¿…ö?þ§¿þ¿©€D°/‘ê“—q£’ÑÀ°ÿúÐäþ¿¿þ¹å“p™yÁS±ÚÔ³ƒôµ¿‰¿ÿŸ­¿¼»‡¥Øw³¾ÔÖ¿ì¼²•¾¡DŸþÞÜw°Ÿëþâ*ð»†QüŸþÑê†Qóá†Qĉ…“þú€1õ°è©áÞÀÌ»ƒ"ðøþ™àÂðú¤4QÏcÏÙ¯‡Ï™Ïl«Ï¸É™¹‹ö†·ÂþîåîþÆð>ªà‡àü‰©Ê è0Ý»W!³…¿öà³þÿ¹³þÔ‡òþ­ÿ‹ðüîþä‡Âøàé?$ßvÏHß‚íÚèrÞ´qßÛµ£Úê×Àj°ö¦àÞþÔ÷¡þîªà™Ÿþìý«£þÞ½þØêu`ÞùÀ @³þèÖ Þ…ÐðÖŸÔ¢DÛßíß?ßï#ïô5ïâôrÞþúÊýæPääþ©èÿþŸ³þÄ“þöÏ™ÌþÎq…0¿þÿôÄ­Ÿ‡¿þÀÿαþ̃ÿÒþÒ‹òüöþòÖüâzä¦ï°æïÃúÜŸ«Ž0ê»@ä‡ÐÚïþÀúæ ­³­øöƒ‚P¯îþòî}‘1þî¡‘òR îÿ'øÒÂñBÿTÿï°xÿŠÿœÿ¡ñ¡Î‚Q•ßüþüܯÞðòèÿþâƒøþ­Îþ;ЙøðÚþÄ9p_¿þÊða±¿ƒ@￯þòŽ0ăàûþøjà§‘¯îÅ!ƒ±€úð¹ÕàP±Ž0úm“̡ڸ4™¿0;×4þáàÊTáS\n­üÖ•‘†Pò Àì ƒ@‹RîÒ¯Qî£î…¨ÜÒ s¯þð†Pà͵‡ÐüI±± ——ôÒ;äó <*λ—yÇQÛ‰öÜp‰nPð)“Ã;ús‡ÐÞ±…‰ÈQŸ¿C_,*عÖ~Q›‰öË ™®Ö0îü‹ip¨ü°©P°QÁÓ0‰òÀa»õHhÿö`PØ©ƒSEüÃXŸ¹qt£¨Ðßæ›üèþ°èKþ·þ°»\ ÀöçpΗPþîP"~ Ÿþóäð|àþ°§þü“üþ°v0ÒðÔ…aÎZ‹/m¬+»Ä§]¿ipµøçpþ]à¤qAq@‡áÃãÁƒ6Á•Óþöst›‡Ð…èš4?¼%?7?I?[?m?Ú?›Mƒ@ðþ_ħêÈ…ðÂ7›Ôø5°þÒê oPüO±þþæàÀnQÜoP»Â¯ÈQþþ·oP©iµ+ÀÀ¡oP¿‡ÑDq@Ý!¿ÓÁ,ðäÁ¿´Ðê+ñ‹ÈPÎ qÈú“›§“Ы€?%O7OIOãmOO‘OÝtû…iзÌþú¥¤oPåpØoPðpÞoP±è€oPúðÞ—P½þqÜÇQºÐØH»þÎÐ…À«îÁ÷O _[OÀ-_?_Q_È´0°H`øôóÒ£ qÀ“…úþß¹Þþ¡ÀPÄþÓàµ3Àá0¿üðÆþýìùÁØþÚ¯þÚÿòþ½üúÄŸþüÄÐer•¢»_Í_)ñ_ooa;§cüò‰"‚ÀûþÜôþÖ¹þkôƒ¹0>À›¿LcUŸ>À.À‹ÀÄï±Ïþþ“ö|àÀÔþiúö@Α½9bêÎkQØÁ8cŽkêþMƒ›€_¿oÑoão;ï«@öpàoþôÜ¡¿ìâÀæþ©ÎþÊ‹ÎðúR°§¡PÎþ»¹þõÆ@¯D°àþ¯÷·þÄ.À¯‘øö‰ôAp@ÖM!grlÒâ çsÞçsÊ]àI¿ï‹ü­|—…ÚµgþöµAâÂâüÇq©¹5Á"€6ÁË"#-"‡ø"@ÿ_à~5GYb…‹Úþ_âƒìÎÔ·{öƇпþÖ·3Àÿ©þü«›Ùæ·0b€‰ÜHq™«ÿÚþôÈþâ?ìþä‹Ö½@¹Q#›kRÁÒ$öŠK™NàÎaR±’‡ïÔþÎ{ÞÆüGþâ¹cs.Ÿbt»Pr‡NáVŸzŸŒŸžŸB –A`عp ÀÁ@‡È­Ð@Þ±Ú 3ÀÞþ«Î¥ÕòÎÔñäÝAäÿ—üþÐìüô}üÍГìö­ìÕÔ€P¤¯cŸ5¯G¯Y¯k®…ßÈ‹Äʃ¯Ð½ÒÞË Èþ³À0pêþï“«þÚ4—þðå¯ÀƒôPqèþør¥aÐìáãàþþÈJEîlt—½Û¯ß  1¯à¿¿'¿9¿K¿Ä÷­Ì ¢ÆþĽÿþ¯‹êµìþŸ«¯þ»·v€™§¿þÄÚþö«IÐâÑÀÒÀ4¶B¯ZoàèÊq–°³ð^M°Üþð‘Á¿YØìš•ÀpŸSŸ€Þ¿ð¿0¯Ï&Ï8Ï£Âû‹¥‰ÎþÈÐþ_Ö‘üþ—_`ÞóÁˆÄÐ?ñÉ0ÚïsÒ² þÿ‰úþÚþèÿ·þæ…ðþ§}Ú°—Ú¥¯öͳ€ q¤Ïö¿ÈÏÚÏìÏþσßÈ™¡Ò‘¯Ðè¯Þ²P¿þÒ¡üðÞþÿµ—þèƒúþ“o‡þü¡ê ö°0œfÀñðþ·¶Ðk‡p« ÿÁPÿÁöþ»ãsÝÿÀ­þúNá‹ðï0Ñ7b½Ïߡ߳ßÃÜ?“½ÎâöÞŠÀoáߣ•Ì©¿[!õê²½¯€‘úþ­aÚþаñæñ¡üª€oá—øîæÚ!ÎeÑï/ï4á †ßXïúß™ˆa¯æîîê-`™þîMŸ¡Žï ë½³ä—ìþ¹»rüCþÖkR£0jáÒ¦0à ïèïjâ™Qjâ½þô÷³ÄÚÝqàêÖÂA­Í¿zßCÿUÿÕäî­bÞÓ rÿ„ÿ–ÿ¨ÿºÿÌÿ nôëÿFïüŸ“1yîxQ€ƒ‰‡Vt`bqmsÏõð2Y ìþtPº×ãÚöC‘ìþšÃ£wöþä¡ÂäþÌYИ¹T¹ò¥aƒó£ÎŒPàèØÎ¿ ¯ã ÿÿ+=ÜO‹»Î·öAµì×·@Ò±‹ ­þÈw±Ôü$‘‘µpqµÎ·Ê¯¡³Å×éû /Þ_1/C/U/g/y/‹//¯/Á/Ó/å// ??-???Q?c?u?‡?™?«?½?ô/á?ó?OO)O;OMO_OqOƒO•OÌ?¹OËOÝOïO__%_7_I_[_m__¶O£_µ_Ç_Ù_ë_ý_o!o3oEoWoŽ_{ooŸo±oÃoÕoçoùo /foSew‰›­¿Ñãõ>+=Oas…—©»Íß(Ÿ'Ÿ9ŸKŸ]ŸoŸŸ“Ÿ¥Ÿ·ŸÉŸŸíŸÿŸ¯#¯5¯G¯Y¯k¯}¯¯¡¯ØŸÅ¯×¯é¯û¯ ¿¿1¿C¿U¿g¿y¿°¯¿¯¿Á¿Ó¿å¿÷¿ ÏÏ-Ï?ÏQψ¿uχϙϫϽÏÏÏáÏóÏßß)ß;ßrÏ_ßq߃ߕߧ߹ßËßÝßïßïïJß7ïIï[ïmïï‘ï£ïµïÇïÙïëï"ïÿ!ÿ3ÿEÿWÿiÿ{ÿÿŸÿ±ÿÃÿúïçÿùÿ /ASew‰›ÒÿäÿÑãõ+=Oas…¼©»Íßñ//'/9/K/]/”/“/¥/·/É/Û/í/ÿ/?#?5?l/Y?k?}??¡?³?Å?×?é?û? OD?1OCOUOgOyO‹OO¯OÁOÓOåO÷O.O_-_?_Q_c_u_‡_™_«_½_Ï__ó_oo)o;oMo_oqoƒo•o§oÞ_ËoÝoïo%7I[m¶o£µÇÙëý!3EWŽ Ÿ±ÃÕçù ŸŸ/ŸAŸxeŸwŸ‰Ÿ›Ÿ­Ÿ¿ŸÑŸãŸõŸ¯¯PŸ=¯O¯a¯s¯…¯—¯©¯»¯Í¯ß¯ñ¯(¯¿'¿9¿K¿]¿o¿¿“¿¥¿·¿É¿¿í¿ÿ¿Ï#Ï5ÏGÏYÏkÏ}ÏϡϳÏê¿×ÏéÏûÏ ßß1ßCßUßgßyß‹ßÂϯßÁßÓßåß÷ß ïï-ï?ïQïcïšß‡ï™ï«ï½ïÏïáïóïÿÿ)ÿ;ÿrï_ÿqÿƒÿ•ÿ§ÿ¹ÿËÿÝÿïÿJÿ\ÿI[m‘£µÇÙëý4!3EWi{Ÿ±ÃÕ ù ////A/S/e/w/‰/›/­/äÑ/ã/õ/??+?=?O?a?s?…?¼/©?»?Í?ß?ñ?OO'O9OKO]OoO¦?“O¥O·OÉOÛOíOÿO_#_5_G_~Ok_}__¡_³_Å_×_é_û_ ooV_CoUogoyo‹oo¯oÁoÓoåo÷o.o-?Qcu‡™«½Ï);M_qƒ•§¹ðÝ%Ÿ7ŸIŸ[ŸmŸŸ‘ŸÈµŸÇŸÙŸëŸýŸ¯!¯3¯E¯W¯i¯ Ÿ¯Ÿ¯±¯Ã¯Õ¯ç¯ù¯ ¿¿/¿A¿x¯e¿w¿‰¿›¿­¿¿¿Ñ¿ã¿õ¿ÏÏ+Ïb¿OÏaÏsυϗϩϻÏÍÏßÏñÏß:Ï'ß9ßKß]ßoßߓߥ߷ßÉßÛßßÿßï#ï5ïGïYïkï}ïï¡ï³ïêß×ïéïûï ÿÿ1ÿCÿUÿgÿyÿ‹ÿÂïÔïÁÿÓÿåÿ÷ÿ -?Qcu¬ÿ™«½Ïáó);M„qƒ•§¹ËÝï//%/\I/[/m//‘/£/µ/Ç/Ù/ë/ý/4/!?3?E?W?i?{??Ÿ?±?Ã?Õ?ç?? OO/OAOSOeOwO‰O›O­O¿Oö?ãOõO__+_=_O_a_s_…_—_ÎO»_Í_ß_ñ_oo'o9oKo]ooo¦_“o¥o·oÉoÛoíoÿo#5G~oo}¡³Å×éû 1hUgy‹¯ÁÓå÷ Ÿ@-Ÿ?ŸQŸcŸuŸ‡Ÿ™Ÿ«Ÿ½ŸÏŸáŸŸ¯¯)¯;¯M¯_¯q¯ƒ¯•¯§¯¹¯ðŸÝ¯ï¯¿¿%¿7¿I¿[¿m¿¿‘¿£¿Ú¯Ç¿Ù¿ë¿ý¿Ï!Ï3ÏEÏWÏiÏ{ϲ¿ŸÏ±ÏÃÏÕÏçÏùÏ ßß/ßAßSߊÏw߉ߛ߭߿ßÑßãßõßïï+ïbßOïaïsï…ï—ï©ï»ïÍïßïñïÿ:ïLï9ÿKÿ]ÿoÿÿ“ÿ¥ÿ·ÿÉÿÛÿíÿ$ÿ#5GYk}¡³Åüÿéû 1CUgy‹ÔÁÓå÷ //-/?/Q/c/u/¬™/«/½/Ï/á/ó/??)?;?M?_?–/ƒ?•?§?¹?Ë?Ý?ï?OO%O7On?[OmOO‘O£OµOÇOÙOëOýO_FO3_E_W_i_{__Ÿ_±_Ã_Õ_ç__ oo/oAoSoeowo‰o›o­o¿oö_oõo+=Oas…—©àoÍßñ'9K]o¸¥·ÉÛíÿŸ#Ÿ5ŸGŸYŸ}ŸŸ¡Ÿ³ŸÅŸ×ŸéŸûŸ ¯¯1¯hŸU¯g¯y¯‹¯¯¯¯Á¯Ó¯å¯÷¯ ¿¿R¯?¿Q¿c¿u¿‡¿™¿«¿½¿Ï¿á¿ó¿*¿Ï)Ï;ÏMÏ_ÏqσϕϧϹÏËÏÏïÏßß%ß7ßIß[ßmßߑߣßÚÏÇßÙßëßýßï!ï3ïEïWïiï{ï²ßÄß±ïÃïÕïçïùï ÿÿ/ÿAÿSÿeÿœï‰ÿ›ÿ­ÿ¿ÿÑÿãÿõÿ+=tÿas…—©»ÍßñL9K]o“¥·ÉÛí$/#/5/G/Y/k/}//¡/³/Å/×//û/ ??1?C?U?g?y?‹??¯?æ/Ó?å?÷? OO-O?OQOcOuO‡O¾?«O½OÏOáOóO__)_;_M___–Oƒ_•_§_¹_Ë_Ý_ï_oo%o7on_€_moo‘o£oµoÇoÙoëoýo!XoEWi{Ÿ±ÃÕçù0/ASew‰›­¿ÑõŸŸ+Ÿ=ŸOŸaŸsŸ…Ÿ—Ÿ©Ÿà͟ߟñŸ¯¯'¯9¯K¯]¯o¯¯“¯ÊŸ·¯É¯Û¯í¯ÿ¯¿#¿5¿G¿Y¿k¿¢¯¿¡¿³¿Å¿×¿é¿û¿ ÏÏ1ÏCÏz¿gÏyÏ‹ÏϯÏÁÏÓÏåÏ÷Ï ßßRÏ?ßQßcßu߇ߙ߽߫ßÏßáßóß*ß<ß)ï;ïMï_ïqïƒï•ï§ï¹ïËïÝïïÿÿ%ÿ7ÿIÿ[ÿmÿÿ‘ÿ£ÿµÿìïÙÿëÿýÿ!3EWi{Äÿ±ÃÕçù /ASeœ‰›­¿Ñãõ//+/=/O/†s/…/—/©/»/Í/ß/ñ/??'?^/K?]?o??“?¥?·?É?Û?í?ÿ?6?#O5OGOYOkO}OO¡O³OÅO×OOûO __1_C_U_g_y_‹__¯_æOøOå_÷_ oo-o?oQocouo‡o™oÐ_½oÏoáoóo);M_q¨o•§¹ËÝï%7I€m‘£µÇÙëýŸ!ŸXEŸWŸiŸ{ŸŸŸŸ±ŸÃŸÕŸçŸùŸ ¯BŸ/¯A¯S¯e¯w¯‰¯›¯­¯¿¯Ñ¯ã¯¯¿¿+¿=¿O¿a¿s¿…¿—¿©¿»¿ò¯ß¿ñ¿ÏÏ'Ï9ÏKÏ]ÏoÏÏ“ÏÊ¿·ÏÉÏÛÏíÏÿÏß#ß5ßGßYßkߢϴϡ߳ßÅß×ßéßûß ïï1ïCïUïŒßyï‹ïï¯ïÁïÓïåï÷ï ÿÿ-ÿdïQÿcÿuÿ‡ÿ™ÿ«ÿ½ÿÏÿáÿóÿ<ÿ);M_qƒ•§ð¹ËÝë propïNAMEë TIÿTLE_MUSIÿCMIDIŽõ ðë!ÿXÿÿYýëÿQ±Šû‡@5 q°ÿý/ëFÿ!þ;Copyrÿight 199û5´QGarreÿt ThomsoûnÃQgartÿ@terrapo¿rt.netCýEKÿWaÿrm PadÀÿY°y° ÿD°[]ÿ‡@CN>eÿ;Ye°@ÿ;>ÿ C`Bm>ÿm9m°@ÿX@QBÿ> 9ÿ@rYõxÿ9>Bý$Ý ;eC­YÖiÅlÊ?C>½Ô÷9eÝ‚@é5åÍì@mÖ"mÝmþÿ9<@u7 @" SQ í@!Ý>3_») ]Å×éû //1/C/U/g/y/‹!3&3š/¬/¾/Ð/â/ô/??*? >À@°> ÊÁ^‚_°= àÀ½‹TáÂàÁ<üË; Þ:ÛU9,Û8;Þ7MÛ6\ÛU5kÛ4zÞ3ŒÛ2›ÛU1ªÞ0¼Û/ËÛ.­”•.µ—.À.ÚÐÔ”-U í,ë+*ë*9îU)Kë(Zë'ië&xîU%Šë$™ë#{¤#¨àú¨à <°" «!Áë µ¤ ½¤ hÐàÐàˤÓ¤ ÷ãTâ©øãûû.þU@ûOû^ûmþUûŽûð$¡ñ« §÷²ó³ñª¾þÐûÓ´Û´¨ßðæ·ñð  ª! 0 ? Q z` o` võ{ Š0 ú” ¢  y±ÌÄ ×ÇèÁ3 CÚ• SnÿthBrass ÿ1Á>±[ÿ± I±]û[O‘+}ƒ`ÿ+&rƒ`&ÿ-}‡@-+=Oasž…-„õÕ@ý_ÞDrumsÿÉ ¹ÿ¹ 8¹](ÿ[Z¥@™$l<ÿ$4,R<,ïx$Rá$yÚáyè4ò<$UJîîrájèŽó$Wáó-(ç2\#p< 2<þ#p0<0/}p(n<(p_W,#qW‰!u,pR‰!0yu ë0Ož"Lž!$yó(y€!< 1*/$];!*¸ Ä ó4 #Æ *]$eDÑ%2°$Õ!y<Õ!Ï6$LÑ(Á%*7Tò"ñ#-8jò"7+#Î"3(é%8$]Ô 4Ã!j89ò!.D×$j;!.Ä 0ã$O1?Ë ò"](2é=e!Õ!=k $Rêe (Ã#.´€O(0“j«!u34q ¾0(k1W_P_b_t_†_˜_ª_¦Ÿ¸ŸÊŸÜŸîŸ¯¯$¯6¯H¯Z¯´Æ¦o¸oÊo”Ÿ2¿D¿V¿h¿z¿Œ¿ž¿°¿Â¿Ô¿æ¿(7RjQýt‘"X—.¾ "ÑúÂMÙ±® n!Æ 0já¢.dÔeÁCÊÇ‹ *W „¿$¿hÏzόϞϰÏßÔÏæÏøÏ ßê¿ü¿Ï Ï2ÏDÏVÏÄßÖßèßúß ïlï0ïBïTïfïß.ß@ßRßdÕñ9¯ Zò°|ÑTòÃ$» ‰ØÉ ”ߦßêïüïÿ ÿ2ÿDÿVÿhÿzÿŒÿ¸~ïï¢ï´ïÆïØïRdvˆš¬¾àÐâôêd®(2j‘&–‘¹¡%‘9› 4‘A’±¡9;¶ Œ¥#Âc˜1îô(b‘r#$rX—˜ ±±r„–¨ºÌÞð//&/^?*<N`æ/ø/ ??.?@?R?d?v?I-C9BxWC{BxZ{BPz_E¿__RÀrœÀq_“_<ÍtyA/]<]€¥&;…BA&ˆC@ŽBë»qyØuÉyät([A~7[ŸÉ ™:|0`<`G ¡+O=OOOaOsO…O—O©O‰?›?ÈŽ±ô(2=^!Ù£k!Rp$Ó5(0j…!Ü5ˆ#(å9(¥÷>ˆû8O$Om‘£µŸÀÙëýŸ¸?Ê2(·ð½ðy»ñb&@v•Z“û$yÏ5W2j(pÐ2yŽ!î2^!È£“–12* Ù’3–0yxÒ磰²c¢pÓA /cÜ"yâ!F/>»ŸÍŸßŸñŸ¯¯'¯9¯K¯]¯o¯¯Î?à?ò?O©ŸG¿Y¿k¿}¿¿¡¿³¿Å¿×¿é¿€û¿®ÿÀÿÒÿäÿöñÍ <3“0j² !Ò„Á .O{ÏϟϱÏÃÏÕÏçÏùÏ ßß=ï'Ÿ9ŸKŸ]ŸoŸŸEÏcÏuÏãßõßïï+ï‹ïOïaïsï…ï ϯ¡¯³¯Å¯×¯é¯û¯ ¿¿1¿C¿?ÿQÿcÿuÿ‡ÿçÿ«ÿ½ÿÏÿáÿóÿÏ-Ï?ÏQÏÿ-ÿËÝï€s7I[mK(-LÒI]!r~‡.r¹ ^×pnÓ*/$$IöIÑ"oÒÞ$2eŽÔ*e70rv.}Ñ"ev)0}v/r<¡õ1Ó l²4,RC<,Ð@•2F0yJ0Dé@U8xÆDoÑF0jJ2à3>2F?X?j> (5šLÒ:LÒY|2»Ñ(-N!(e!$»"D³¨e¯CÓó2ÿÂ/./@/R/d/v/ˆ/hz¤ï¶ïÈïÚïìïþïÿàò//BOTOfOxOŠOœO®OÎ_úÿ 0BTfxŠœú? OO0Ož_°_Â_Ô_æ_ø_ oZÒOäOöO__,_>_P_b_t_†_$6H¨l~¢(o:oLo^opo‚o”o¦o¸oÊoZâ`r²•\Ã4ó•z€Ç’d„#rÞ2‰¡îN½„Þ!žÐ }*B¸Ôð7GæÒ(SÝ2ÌÜS&'K<&s–\€NQ„ÿg9I]„%ˆ$Y ˆz€€â`}‚U‡âe‹… ¤¾$NT…ž°ÂÔæø ŸÀÒäö,þ>‡¹• _Â$_ÙIˆ]Æ~~„ÏpÆ\]À†Ã}}°ÏpÆh]ÀÞ²Ã||ÜÏ ™z"ƹãÄ{{ßã ™v…]ÀÓzáz.ßœÉ\Á0ÓyÉyZßpÆ7]À\ÓxÃxƒßÓÔÁ…Ówƒw©ßÓW±]À«Óv'vÒßpÆj]ÀÔÓuuûßÓi±]ÀýÓtt$ïêØ­=¹+ässPïôÆ<{ÑRãrryï›×{ãqqŸïÒŒ²<]À¡ãppÈï·ãx–´]ÀÊãooôïòpÆ9]ÀöãnnàÿÒª²]ÀómÁmFÿp³µ]ÀHólãlrÿ<ítókÉkžÿôÆ4]À ójÃjÇÿÓ\ÁÉóiƒiíÿÓ’]Àïóhÿh™(]é¹õÁ(yà!õÁ3›]À#gÁgUpÂE˜]ÀWfƒf„pÅW’]À†e7e° ™]’4¢²™²]À²Ãj> dd ð Ãxu›]Àñ cc!ðõÁ‡˜]À#bbâP™“›]ÀRaÁaqÁ¥ž]À`K`´™Ïoº£¹µß™(S à __ñ.ǯK¼]Àó^^)*™xÛ®]À+)]][*ðqÁð«]À])\\à*n( ´]À)[Á[¿*n¸]ÀÁ)ZƒZñ*n(-´]Àó)YY#:n(?±]À%9XXR:qÅK±]ÀT9WW~:qÅÇÔ€9VVª:ëÙ¬9UUÓ:éÕ9TÇTü:=ìþ9SãS(Jié*IRñRQJœÖSIQQxwJ¸éyIPP J<áì¢IOOÌJ ùÎINNõJ6ù÷IMMZ_ü YLÇLJZ=ìLYKãKvZ·ùx^JÃJ¥Tàö§X¦TI IÂ=4ÍQݸÀ]ÀØRÌRç ïSHHdó±]ÀhdÿGG™0j€42abþ¸]À=b1bxc TcFFidð6òákhjdEEÀdÑÂ]À‘hdD#D»dÒ( ²¹¼i¼dCCêdõÅ5Á]À<ìhëdBBte7øÓÂxrAÁAôÅ7‚êDrWt@ƒ@btáåYÄdxct?‡?ŽtqÌxt>‡>ºt̼x»t=‡=ætÉÌèxçt<‡<„õɈ„;‡;;„Ù=ˆ<„:‡:d„GÜfˆe„9‡9„sÙ’ˆ‘„8‡8¹„œÖ»ˆº„7‡7ß„ÂÙáˆà„6‡6”ëÙ ˜ ”5‡51”é3˜2”4‡4Z”=ì\˜[”3‡3†”i鈘‡”2‡2¯”œÖ±˜°”1‡1Õ”¸éטóš0Ç0àí¢¯/Ç/ ú2¢B¯.Ç.5ú[¢k¯-Ç-^ý„¢—¯,Ç,<í°¢Ã¯+Ç+¶úÜ¢ì¯*Ç*ß÷²¿)) +²*²<·-((;jña²>z¿''m’³>©¿&&œ ²<Õ¾Â%%Ð ö²¨õ²çÇ<5#ï# IÏ"ã"baÃxÏ!Ã!‘£‘­Ï  ÆØÆÁæÆÂðÊ/'Ò>"ß;/M!|;ÒTßm/ø!mÒ†ßðŸ/±!ŸÒ¸ßáÑ/ã!ÑÒêßÃ?ìáâïÇ5?4ãKïÇd=dâwïÇ=â£ï§¼:¼á$»â|æ6ê ãヒü ø| ó;I ,ÿ|8ódF Rÿ|^óŠI {ÿ|‡ó³L §ÿ|³óßI Ðÿ|ÜóY ùÿ|1\  %|1L  Q|]‰Y  z|†²V   øÑT¡Ý_  àÔùTÕêi(0jñCkýPù vf ø4@œl ú`0Èo ø}‰÷l ð©µ#yêå ÕÕI|ó õ³D¹dýÿÒÀÿ!ÿÿIcÿe RainÃÿ[³³ ÿ³[Z]ÿ9 ÿ@ÿ“Lr†9LÿJr9JHeÿ†-HHr;ÿHG_3Gÿ Cr†CpÿLrrLJr‡@JK/]/o,–~//n/¶/È/¤,Ùÿ3 $µ% Sÿynth Basÿs 1Ä&´¾5 ´ L´C"ÿ[]ÿ@”ÿ!o\1?<d0ýPt1&U<&<Ç$U<ÏÀü2õ4+F¶h1&a A$PHKxB BCP<@%oþ2o@}3JBC—<U@@HbB¡5a?s?…?—?©?»?Í?ß?ñ?OO'O9OKO¼]OoM˜0(8Á4g<4 ШR&0Qg2<ÞP¹S$*Qç0diaUdtd]N|fG>CEþØ LNH_E_EHç ÿLYHr÷EY&¶ZGe?C_Jeæ °WGZ!°L"µL(±ïƒ>-±@>u@°N²YE±ù*°^²GIJÿmOCOúæ GаYJ_kOS”·EV²Hm‚±Za°E.°GS޲N¦¸ïSLmµ¹ONíC°JmK±G­Oe°<6²7j²8^p±GmCİYK·éCè°G°_ï´CZÿEILIHY`Ý·Àê±J²*ÂBÁ}m#ɃBG8ó°·E9'°C8±9ÿeBS>Yê°BB!ZzÀ>_ÇBN†À°‰À;Y›>D°N°°;ïBNŽÁ9_„ÌÀƒÂZÕ±´°²¼²ƒB ¿¿0¿B¿T¿f¿x¿Š¿œ¿®¿À¿Ò¿ä¿ö¿ÏÏ,Ï>ÏPÏbÏtφϘÏüªÏLâ;24O29.¸Á°P;÷Àÿ9(;,4/ù˜âQâ";+û4-§ç47;4'90¸Á«à4eàÇàÝ-ËãZ49§à9í5Åá47§è1;»1«â45ãá@ÿ:;897Ã48§á:ЫâŠà.;@0Èà4.§ä:Ð.dá-@à-Èç:ÐtÒá+ð5ÎÐ94ËæÞðZ@>ið4(Ç9,³àþã—à@ýEûà4;96ظÁóÒà@@nð9Äà ð3þá°PðEFÿ@Q;/4ñ3ÈçðÀNò4@@K;@ùÐó9I_ùNÐZEK3@Snðíñ@NÿÄiñRDÐeÓð9 ð9zø±KìÄiðùÐ@Cöóë93éâ@§æ4G{;òðeE}ÐÇ9YGù`шÑ4I÷Emóð;BJN9S¸ÁÉõ`ÑþÞà;E4E9÷NJòðGESèïÁ®ò2ôJ÷Ðr@"àNœš`¸NÑÏäÇI4ƒX"á@_öñ¯oZÁëvÁ;ƒ·ÂðÀæ “õEýeÀm4_;º^yÏZHmBá; SxmöñÌãLÓÒàÿ-8µ@)•¿-q46%Ïðþ¢ð@9;5 ÿ9 @;ÿ‚,46(4Pÿ-8D-p44õÏðçà@4;ÿ0';@OÿA8; ;ÿ=Ak@81@ÿ/9T<8oÿ< -?H-¯l45-Ïð«6ÿ;2‚:9ÿ;@4ý."a-4P-dw45+Ïð 9.ç¯@5C´3º8ÿ7; AG9ÿ+@8g@Mÿ>9Oµ@•¿>)<"uû•åP9/53ÿ )<9¿ 5ð<¿7@7m ð'ÿ@&<&93ÿ&9R)94ÿ584@79ÿ26@9:ÝA‹ð9\AN!)ÿ(5-@9+@ <7_0 ß•(>*ux•w<¥ð98Zdáÿ>@B‚(~*96&;9Ðÿ,9(:4ÿ4749I39ïE@BSR@ÿ;`9E4ß( ð@ÿA(=;C¿8A49(0 ÿ•;@(ÿ84$r„–¨ºÌÞð//&/8/J/\/n/€/’/¤/¶/È/Ú/ì/þ/:ƒHÕÏçÏùÏ ßß/ßAßSßeßw߉ߛ߭߿ßÑßãßõßïï+ï=ïOïaïsï¼ÏÎÏÖOèOúO __0_B_T_f_x_Š_œ_®_À_Ò_ä_ö_oo,oð>oPoboti„:0'ÿ0212¿707¯ðB‡—F7@FþáZ€>È€a€^—`6òƒ»2S4+˜à7™6Y`€96u„x`<Èp.>L§ôaÈp×:>@>Ó‡>K7 ðLЇàB²€™Z€Ô‚Z6:-FúÝ6O€Z66ó2B¾”T€6Z7>ÌF/>Ý Tï-BÍ‘66Å’-HZl~¢´ÆØêüŸ Ÿ2ŸDŸVŸhŸzŸŒŸžŸ°ŸðÂŸÔŸæŸø•ĵïdÿ°6ÿÿ!ÿÿKalimbaÿÆl¶ß¶ d¶°ð ÿ[]Ùï@–>d&°@aí<‘q^<{pH[Xó²Uù²Rÿ²UOÂLó²Iù²Fÿ²UBÂ?ó²<ù²9ÿ²U6Â3ó²0ù²-ÿ²U*Â'ó²#ù² ÿ²UÂó²ù²ÿ²UÂó² ù²ÿ²Âò¿ÏÏ(Ï:ÏLÏà^ÏpςϔϦÈ´òºð(pQB(QÿS9(SÿXJ(X];ÿ(]_?(_ÿdB(d¯iN(i° G´!b×N(bª H®!]Gö¨!XK¢!VO(VÚ’ P–!LSŠ!JUí(èàEK„!@Y(þW¡Y(9ÃÈÿK‡@˜Eo†=ÿE C>qCÿ@P†HK <™°þa0H†D@GÿIxCaG†ÿBEPCKEÿAa†HCGÿAiEPCÿ†DH[EÿMHGh‡@LHG‡#ï·» ¸»µ{ŵ ÿGlockensÿpeilÊ }ºÚ°º &º© è°â²~ š‚/”/¦/¸/¸Ê/Ü/î)>@(`Eÿ9Q@Ê0(ýšÁ0E; ç4g 5€; û4?D4;ê ±4DC KE ;½ WE&4!?E÷4KE!;(ÞWE4 ?Eû4?E34#ó@'¡@D@Ç4?Aù`CAó@HDÐC4;Ï@¡XC4/î™ @2ðH-;½r?rB'rU'r+'xD'r'rU!½xFr8]r2'rªÚs:]r0'r,'r<*Õ~OrPrS'rtsU6'r'rUux)5ˆAWrÎqps'rH]r•;ˆI]r='rvƒ`ªrbrdíx@½xfH5ˆÚs&shƒ]rJ'r ʃU]rF•ˆF\€Yƒþ'p´LÉ‚ ™ÿ*<**&þ’@&4&ç&5‘‘Y&ûe<“.e<._<$e<$r"‘î/“2e<  0r<~ $r7r< E$-r1–.”Y’x/’.”6}4”6oZ’Y’Ž.™<$Ng˜“Z’6rŸ¯—_ŸqŸ¿Ÿ•Ÿ§Ÿ¹ŸËŸÝŸïŸ¯¯%¯s¯€I¯[¯m¯¯‘¯£¯Á¢‚Ù» p¼´]ôfAcÿou Pianoß̼ڰ¼ ÷(¼s(ƒ@œÿ9R¼@ ÿœ@R4Lc¿H]EW¯ðLû$|±ZE ÿLHEW?JÿQ9HC÷Q?Á0H)QÏrHyˆ`ð9HÿJH&HRûQLÒ`JjQÿ HZJ8ßGr HÅ`@ÿ9Hj G2GcHVP¿Ey8E10ÿ<7] ¼@+ÿ@œC]Gÿ$Gy0G ÿJ"JGyÿOj?OGÿ4OGy)ÿC6GOÿC>jENÿ'ErN"ÿ2>SNÿEjEjšfÐ8ŒÀ>r.!¯ðJ£OjHѰ¯ð2WE†D8ãN·ÿ>CCßHeƒ`…±NkGE×àÁñY(¯ðçGYÛàGCewJS…ŒàCe€Ÿr4J¯1ðY–ÀñEr@rêàyÀ¿L}ON†ûà<ŸQNEeñäjá}ÿLY‡@HLüïÿ ÿ2ÿDÿVÿhÿzÿŒÿžÿ°ÿÂÿÔÿæÿøÿ ·Ë,½êe %ÿCÿlavinet¯Î¾ ¾¾à¾þ`¹ç@ž-Nÿ-9}>9ÿ:9}697ÿY-74Y,ÿ4L2e52ÿ4e:42ÿe12 7r`ÿ79Y:9ÿ7e17 -ÿe-!9rÿC959r39ÿ 7Y*7ÿ4e-4K2Iû*2<I<2Yÿ4-2 7r¿Y79eñ4ÿ7-Y-ÿ9r79Aû9rñ27 4ÿe44D2N8ÿ24r84ï2Y/ST7ÿ$9N.97ÿe<-r7ÿ-9}89¯@9N^e}rú@-Hr-9ÿ0-e6-ÿ2}S2%4ÿ}<+r 42+‚àãõ+=Oas…—©»Íßñ//'/9/K/]/o//“/¥/·/É/Û/í/ÿ/?#?5?G?Y?k?}?0?¡?³<ÉžF@ÊÕ ØG~ãH}ïF žï-¾ðA| žK9}É|Q Q{P?ž9¾RRz(Qž9NÉ*R…y9SPÕ0É;PxBMVÓ@Û0ÉOPwdS§ ž4þAfPvuZžöÌBu ŠWt ž0¦ÍAtü@Ö@t•Q s«P žë2É­Q«R…rÂPü@ó0ÉÄQ ûqÖY ž2o¾p ëSž4 QÚìPoûWž+ÍAn *nP ` fžBÉ«m )gl4kkChj½ü@ ¾jTj®O` iefP E¾fahydS{`gŠfRBSYÉŒ`f¡c Ó@²ÿ@fóPœae ¸eènPP¹`dËhc ž¥2HQc×aàabè` æP*@Éêaèbaÿ`b\Übq `sæP(6@És_*x^6qÓ@´É8s9œa] Mx XPB@É\ dw[ÒBR¶R[op}uZ†xY’x…XRdXžpPÍA¨rõW·vP¾VQ Év­sÊpUÜvP¬[@ÉT ñuÓ@g¾SóPHQS …ÖmTR ‡Q&ž21IÉ(‚'PæP€éPóP/P:€ O6P„ž2œaOnPu`N g‚åTNB‡“æP°@ɉ=›–HÃb[‚<²“åTp8ª 9:;%<Š-=5>=jóó»S[»ck»s{»ƒ‹ » “ › » £ « » ³»»ÃË»ÓÛ»ãë»óû»" "»""»#"+"»3";"»C" K"!»!!S""""["#»##c"$$$k"%»%%s"&&&{"'»''ƒ"(((‹")»))“"***›"+»++£",,,«"-»--³"...»"/»//Ã"000Ë"1»11Ó"222Û"3Ë33ã"4§@ì!55Ý5ó"666û"77Ý72888 299Ý92:::2;;Ý;#2<<<+2===32>>>;2hñhñþ+ø WELCOMÿE_SPLSAMÏP^ i0VÞl^}zx9{{}‡1~Œ0€8Œ1œ3›69”? 9Š3œ4‡2æ6 …2…4Ú4±?·6"@‚Œ&H"A»:æ9Ö2{ôVCx3xcJwwvv¯tsstu@q|Csþƒ@ttvwxxzS{}0$D„šA…ŸAÿ‡ˆ‰‹ŒŽŽÿ’“–—šœ ï¡££¤·@£¡ ÿœ™–“Œˆÿ„~{wtqmjifecbaÔ@ÿbcefhilmopsvxŽ@‚žBû„„/A~}{xw÷tspÍ@hebaÿ_^[ZXWUUÿWXZ[\^abÿehjloqtwÏz}€œE¡CŒÿ’–šž¤ª¯µÿ»ÀÃÇÊËÍÎÿÎÍÉÿ¹²­ÿ¥ž—ˆzsÿmhb^[XWTŸRQQPPYPZPQÿRTUWZ\acÿimsz€‡Œ“ÿœ¤«¯´¶¹»ÿ¼»¹µ®§ —ÿˆ€vlb[TßPJFC@hð@BÿCDFJMNPQÿRUX[^aefÿimqvz~‚…ÿˆ‹ŽŽŒŒo‹‰…ÉAojÿ@÷bbc¤Ps{…ÿ™¤®¹ÃÍ×áÿèêìììêéæÿâÛÑÆ¼²ª ÿ–Ž‚wme^WÿPJC=82.+ý*Œ +.49?GÿPZep}‡’šÿ¤­µ¼ÀÄÇÊ¿ÍËÊÆÀ»~Pžÿ“…xme\UKïC;41À /25ÿ9=CJPU^eïmsw{ªP‰ŒŒÏŒ‰‡…ÆBNPcaã_\SP QQehlÿpsx~„‹“ÿ—ž¨´ÂÍØáïéñ÷ûm`úöðÿéáÒÀ­š‰}¿obUJ@<09ß9;×Ô˜D/GEÚÖÙô–B0@š1ò0aK˜öVAÍõõôúô´÷ï4VBhóA–Cÿâ÷å—Eöù5C2CŒfñ[Ex;‡3- >å9bB`C™õØÖ(O B–5ï3î5aBr@)ŠðŒð…2Ö×#G³÷ZF¨  ò‹›1WRŒ9ä2ZAoA±áˆ6ì´õž TñøÁ ¬‹WA6Dä3XFQ:Š ZBB&ç$BØãÂ}æ<å9j&×0VDB)¥0Jé:Þ*¡ó‘DúóBå6h(CLI l @E,%º÷ã8ŽD|(-Drmä›á:Ó#n6#Aÿˆ•¡§¡qÿbTKMUajvÿ‚Œ•™™“‰{ÿoc^ap…– ß¡—Œ~’pmqgw€‰Àâppa;€ÿaj{•²ÆÇ¹¿¤Œve_cB€tþÄ`ŒŽ‰‚tf\ïX[ft^`Žˆ}ÿm_[_it€Œÿ–œœ™“Ž…}ms°owó’•€ÿ}xx€¥¶»ÿ²¥•€hUJFÿGKT^ivˆû‰‡^€a\^blÿw…’—–‡~ýx¦€„‹’••’÷މ‡¸Pwz‚‹ÿ–£«®¨œ‹zŸlb\[_ÁÐ3wÿtpjfccfmýx`ž—Žtóopw —¡žÎšÁjb_ÀPxÿ‰Œ‰‚{tût{à‡…~smÿp{‰Œ‡€{Üpè`xtq×BŽ‹ÞœÀhfipÁp„ztsvú€zprÀvó}‚@`‰–ìmÀ˜áz€2ð€‡Z}Ђ­€mm÷@z5`‹„‚øÁv×À¨€ð€~&€‚þàOÑúÀvgwzñXPzv¦Æ7ˆ‡KQ(ÕÀw}‡‚€°ÐÁyƒð1€åA碇‚ßÒ`2ðgPkñÈГ°vojh/fjt8@Œë C`ÛpoÐà{‚r@zEs—€tà`ódò{ê`8 àSååà…‚~ñxP~®ð ð„€ùÁéaåàÆ‡ŒŒñâ÷à8‚~Ôà€òÐÂ)œâ+%œQìÿ!ÿòñÕápRótñÊÑ÷áòTà À#Ð!„Pâ®ò“còÒÑJ$ÖPWÐаPó;ñìc[Ûp˜€s¢áŒP„Ü–áTQ‡‰Œ$ð‹Žýð’’•ÿœ¡§­¯±²´ÿ´´µ¸¹¶´¯ý®/p­ª¤œ“‹¹„ÁPüÁf_ZÀKïGDB@KqCDCý@$ÀBFJMNMMNPRRTTÀ°àºÐ{Àlp0ñ±pswüÄP×ч’¨ÄÞèÿåØÑÑ×ßãèÿíññïêæåååâÚʵž–Ðû’ˆ °f\URU{[\·Ð[cpxš°ùoßE€z{zsl¾P°faWNFSp?ÿ<8521/-*ÿ+.48999=;DKRX^¸Á  üÍ 1…“¯ÐéÿñèÛÕÛåìíÿììïïíêéêÿíïìâ餙÷–——¡pwqlcþ~ÀURMFCFP_o}‰–ž Ž°æU@––°ÐЀwmÿbWKC<99;ÿ;84.+*+-ÿ-+(''*.4ß;CKRU¼°UZôæpYlÐá~‡“ÿ«ËêøöéÞÞïèðóðÏöïêÿêììèÜ˸£ÿ’ŒŒŒˆ{phye¢‹ÐTNJGê0ÿmw~…’¥»ÿÿ±¨§¨¤œ~ð‡zmc\ÀÿF5(!%*+(ÿ%%+.-%!#¿(/2458¹ Z¼jq1ÀaaejF°pÿsz‚£ÀÜìßêáØÚã€ïñÿóñïìíðóíïâÒ¿«¯€’Œ‚æPc_·ÐEpFDIïQ\hq‡ðzŽÿž±¼¼²§ žÿžœ—„wiý_ºXQF8+$ÿ$(.11.*'ß%'*/5Úp89¿±£ s{„‰ÿŽ•™šš–’‰„~û@ö(à^X5°IFDG¯JJFB%ÂFA GKNQTºÑ¡½ÀC±ÿt}‰š®ÀËÑÿÑÑÔÚÞßÞÜýÜäÀÞßâããÞßÔÇ»¯¥™À‚x<àQç`jfa\®À c PóP s±õÀfðózv®A‡ÐTRRQÿNKIIJKKJßGFFGJ¿ RUØ0Ó>À¸àim圪´»¿ÃÇËÍZ°ÿÎÑÕØÚÚÚØ_×ÔÑÍÇíÀ¥ 1$ðP$àpo„ÑzÁ9^ ÐGñptw¾pò)8ñȰ=ñeÛ9À|À?[ZXXWW[½¶ëRTÐ^Eàw‹ÿ’—šœž¡§®ÿµ¿ÇÍÎÍËÎÿÒØÜßáÞÚÕÿÑÍÊÉÇÄÿÿ¹´­§¡š—“Žˆ‚ô@¯á€°\ùZ>à«pZWRPNÁN^pdpÐdq#ÀWW@1Ð Â;á&Á6Â#ÁZÐä½ÁQ@‹éÐÖ°¥­´ï½ÇÍÐß±ÔÛßýáç²ÎÍÊÇÆÂ¿½¸²«¥¡àˆ àƒÐ9à;á¹°cq¹²PPQTWZ\2ÁºÐa¯±mq_¬´Áà¨-â ÀDàhì`j¡ÿ—™™—™ž§±¿¼ÄËÍËËá´ßŸÛ×ÒÐÎhÀlÀ¹·µ¯ªrÁ’‹"àtGojfÛ ª Náp½Q%ÒJMQU¹±R@•À³Ñlqb€~¡-Ða²Á°Aá²Á5á´àeeΰ‚Û•à–ÓÀÆÍ½ÑgÀÐÕÜâ–pßýÜd°ÕÒÎÊÄÀÿ¼¸´®¨£–øž >P)ãXWTPJFCBCFJK…Ð]CB MQT»±Rɱ@©ÀbBñ>ð8áBà_­³ø3àb€-Ðcfjq}ÿ‰“——–—§ý²ÕÀÑÔÔÒÔ×ÿÛáãåãáÞÜ¿ÛØÕÒÍÉkÓ§û šû±}xslcˆ(°bpBTp¯¡­ D¹F“ÒÑX\aAÒhÀIñ=ð¾ç¬¶E±´áeißpz‡“œ)¤ÿ­¸ÂÊÑÔÕÔŸÒÕÚÞâßÑäÐÔýÑiѽ»¶±ª£ÿœ–‹…~xsmeüÒ,°JŽ: 9°€5±â"ÁBÁWô`êbjfªàihÀ¡Òcc1Ðã\_à àô`osz¿„Ž–œ×°¯ÿ¹ÂÉÎÑÒÑÑÞÙÐÚÛÛÚf°ÐÎ?ËÇÄÂÀ½ó°n²ÞŸ¡sle^µ²TPQK†Ó<°-°JÑXºÀ¼ÐD©Ñ?ñ+ã9ПÐG°à¯ÒEÀ¢áäa@‹•šÿœœž¥®¶½ÿÄÊÎÎËÊÊÍìVàXàÐËí±Â¿¼¸îÁqàõämhb²°[wZURš€FGI¿  Ò:°›Ð ÀD°£ÓQ ªð‚§òc0á'ѱñ¤Ñóal¼¡°vpx‹•Lážÿ¤«±¸¿ÄÇÇÆÆÆÇÊÍÎZÀõÊï°Ãì໸µ±ÿ«¥ œ—’Œ‡}wsm­K ‡P/±M Ô–ñÐ4ÒVÍ *áÃÁ)àCà)ЦѨôô‰²Fô~ËÀœššœñ Ù°U°àñÉËÎÐþÙàÎÊÉÉÊËÉÆÃlÐpÁùðü²®@8‡‘  8°MPPñ–ãD±e,áI±$ä¦ñ#ñP¬àìbõ`æ`oøawˆAÿ—œœš¡¨¯ÿµ¹¿ÂÆÇÇÇþpÍÐÑÑÐËÉfçÆÄìÀîÑœ—W@]„ÎPifc‰N”ðþ”QPNMKKMÀ @²ò©®à°R Áóæ(âijÍ÷atw{ÿ€‡Œ“™œœÿ ¥­²¶¼ÀÄ5ÇëÍ]ðËÍ[ðï°ÂÀnððà ˜ ü°x°Gpibþâ†ñÒRÀM\r ÄB°_&­CP©òCìbg€s‰PtlP¿~…Œ–™Õ°£ÿ¨®´¸¼½¿Â¢hËhðó÷¿ñõšŽˆ®A ‘*²\qŠÁƱ( cpšãB:%À>»IÊòÖaa…‰F ™šãáéÊjÀwû²pО!uâüÁ^‡¼°žNŸaq@crÑ£Ò+Äâcpþ`¼V"ÃQ…ˆŒ2€™ÿœ ¥ª®²µ¸ß»½ÀÃÄàðÆÄ~ø ÃÀ½¼¼»+q竤 ø±ž¡zvq ‘ЇÀ¼ºT8Ä-Â?ÑÀ9$бªàÇñÍ#Mcwz´™PB`„^ “å ž¿ ¤ª®±²i ¿ÇÀÂÃx4ú0¸¶Ã²®ñÀ†!ž ùÀpl2ÂÑ Ñ›'"eq4ó¥òÄõÉñÏV`^`\1%~¸Q…—`p’g0d ÿ¥¨«­®±´¶÷¸¸¹ý3¸¶µ´§²±¯2p‹0‚‰ …P>pi‡±*±Â³1A±5ò5óÂñÈ#Í[ÄÖ_`zñr…b°P‰‰ÿ‹Œ“•–—~à¡£¤¥¨ªõ0ù¯.r1p«ª¨§¥ÿ¤£ œš–“ùÝ@"axvsol@®â9ÑÑ6Á‡ÂÐU?Á33¢ÓÄóVBØ"îpÆPâ3Œn@2`ŒŽ› pûB“-•P––€—wA^•QðšQ™ PMГi’ØPs°ˆ¦a~}×`z±èb¾,ÒDR­°Ü€'Ò ÄÐ@4×GaKñDúD’qŽ&Pp–Q5bRŽb|b“a°TŽbˆfŸapªSn`¬b“°xxvÔL`ûbÞ`îYÒ!Ö’X`Ù!0 b°boRÂcˆ‰lA#iƒˆˆœQ£c}b±ïp{_`•³aØîrc®P€`ˆpP®WÇY/Q’³œ°sÝ`pps›±“a×2M`ßQcØP{{cb¯SuPœPÈR9cÒP€oP„`Dbáb×PØQîféb^e×eC`~Ö`|påbîhKaøbáb|p‡aúdàdrkc­VÄSA`®Y°Wc%rÖaHq'tád'q@u+|Ëîm«uæBetÄTë@ ÇSÉSuçgKa:r hûdŸvŸtŸrÖa$rØbÓQór•rR‡˜qs–‚€dy˜‚¡s£xùcìj d`bØeu¯„„`@aeses¨‰^sv”sžu£zà·tÊ…^bêwa›~‚‰ÿ‰wfcs‰ÿ…sls€‡vÿqv~„ztv{}„  x~„„/Pû€‚,Q…—šÿ}ooz„‡zþ“‚}vv{€€ zWa¢ s\@ßP™aW`üÙ!¨`w~‚€vqx…ˆz{-P.P~‚……ÒP‘sÝ!û„r‚~{{Ì黀€~lQØ`~wÿsz‡‹€ts{Ý…v±}‚‰Ü‘„‹¿‹…}{‚‰÷À}÷ˆ‹{‰Œ¿ˆ~€„‡ €È`åà0~Û !p„ˆÿtmt‚ˆ‚wÿoov~{spt~€{Œü‘`b‚«€}°ÖQ~à‚/„‡‡‚`0„z \`ïwtw}k pszm€yÀtv[`zw  û€{ …}z~ÿ„‹Žˆ}‡ˆ…ÿr}Ö z©P}Û ‚€x«¡7{wxGpzw[@ b\ `_b}z{”€×¢|®Qy ~„…‚}[ üÕP_0{xz€•’}€„Ç¡à‘œ‚¡@¾°……}vwo €ìÖ ”}xô {{€ë‚K°~D±€€{{wwô¡zwvx1Pþ\°zqt€…€qïltˆu²‡xÓvz}¡Þ‚á v{ÿ„‰‰‚tlmz‹‰ pQ›ŠtŸ{‡‹ˆ€ÛQÖÿŽ…xpp}Œ—ÿ•…tmv„ïˆ{vv¶a…‹‡ÿ~sopv~‰ÿŒ}lep‚ŽŽÏ‚vptаG¡wlÿjt„’‰{q{qw¸`‚ˆ‰…P ÿ€‡ˆwv~ˆ>(P„{ss{A °üÝ  ~toq{‚þí@tiivˆ’Ÿ…zvxØQû}ÿwx~‡‰‡~vþa ‚–’„voëq}?À„Õb‚…ˆþ€°ss~‹’‡>f¡}…Œ‹‚‹ ±·€~zÅ}… ÁoVÈà‚‡øÀv˜ …" Ü·`YÀ‹ˆ‚ŠÀx€ÿ‡‹‰‚{tqtð  P [ 4±wssv …ÀˆøÀwƒ³ü ÷ÕQÙzL°è‚~ÞPvx~® ¤ Ù!Q`kSç x{€…ˆÁ E±›‘óà ]a7±±D°vvx@ ±2PR ›rf²oP~ÛPÒ[t``@¢]`E¢ ±¬^0¢†~~ÑÁ~²{z`±‘KrwDbrÑP…‡o‚ÜcÞ2'…öˆy‚x‚çbäfFb5v¦bóÜÌ]EÓPdbuPQˆï@–P’QÂ$ãŽ÷CPöA‰P’“"P6á%P™PRÂÕP4Rm;CP¬C%A­!<@314òehÆñÒhU`1Å`ð.a}RQ@à–š ¨5® A­ö2¼ÀúB­§£ ž—@Š ´ÁÉoQB¶e!°#^^âñ^Úááà\[X!T$3§¶1^ ñÏšU2xÞ1…‰q@ì0šÿ¡«¶½ÂÃÄÄþéÎÒØÜÞÞÞÿÜÛÛÚ×ÒÎÇÿ¿¸±­¨¤ œÿ•Ž…}tlfa\XTNJFDWò?FIMT\bDOœë âB€€}Ž"XÿURPKGC?<ÿ;;<<<=?@ßDJNRU ðaeùhг„ˆŒ•zw@šÝª´½Æf{ÒÔ·ñÕÕÔÒ¿ñÿÔÒÐÊü´«µ£Hð‡á ql’ [÷UPI†ô=?BFJNT\emt_Bm‚b‹ŒP‰‡ØÀ×zslØàW”GDŸC@=;9‰ð?ÿBGMQUZ^bkflkñ}ß ‰Œf1þXž£«µ½ÄÆûÇÊíÑÒÒÑÐ÷ÎÍÍrÍËÉû»´ƒ œ“‹]ÀoÛicéàTQ„ñ=<ý<;=BINRÿX_is}…‹¢ì0—QP#R‹þ°vÿmfaZRKF@ÿ<9865444ï569;ðCIMPTX^ejo¿ø*ùñ öÀÉÍÎÑ×ÛÜÛÚØ×Äð×ÐÎÎAÎÇð¶±ÿª •‰€vohÛa[MK ?<þFJPU[cm¿w„œ¤§€A«Ã¨¤Œ0@(PŸ@xpÿf^UNF=5.÷*'%*'*/2ÿ69=@CGKNÿQTW[ahmsÏw{‡é2J— ÿªµ¿ÇÍÑÕÛÿáåååãâÞÚÙÕFeÍÉߨžÿ•‰~siaXQÿMIFCCCDC»B@‚CFJ\ÿclt~ˆ“§˜æ@ÿ¤žÇà¡tÿpje_XQJBÿ92+%!ÿ!$(-28?ÿFKPTWZ\aÃch%)òþA— ï«¹ÄËÊÞåéÿêéèåâÞÛØ{×ÕÔÍÇÀ¸âÿ–Œvj_UMãD?›¥m@BDýGÃZ_hpz„ÿŽ–ž¤ª±¶¿ÿÃĽ¸´®§ÿž–Ž…~wqj÷e^WxD?6/¿+(%#!!»1ÿ6<@FMT[_ƒbeð˜`kQà0Äa‹ÿŒ™§µÃÍÑÿÔÚßæêìêéæãáÞÜÜÛÒÿÒÑʶ­¤œÿsf[PF?ï952/0;==ø¨!¯ls}‡’ª¯í!ÂÆÆÿÀ¹±ª¤œ•Œÿ„zoe^XRMûGB 62.++ÿ-./1258;Äð¬Z™ðLDN0jiöV!qq˜ ˆš±ÆÿÔÚÜâêñö÷ÿöóðíêèææûåá9ðØÑõ¥ÿš‚sbRD8û.'-*-19?ÿCDGMRX^cÿiot{„œ¨ÿ²¶¹½ÀÀ¿¼ì…0úˆ:ÀqiaÿWPJGC=85÷455£=@DI®8QQTÄ@ZÞà^âMR_âáÚàÞâafoÿ}’­ÉáìðóûøýŒ0þþøóìýæ 0ßÛÕÑÇ»ÿªšŽ‚tcP=ÿ- #(ÿ.5=IT^foëvz„ ˆ ¨¯¸7¼½¼Ã0¹±0=°‹pl^àav2jàƒðFOGKQWR!›ðpyð]a8 NKK8RïûKMa0NKIJMïRZbjÀ§Ä·ã÷þŽ0ÿþ0ûïôéÜÒO«¡“ý‚Œ!D6(ÿ'6CMU^jÿw…’šž¡¡ ¿žž ¤¨«„@­ÿ¥¡™“‰}mÿ^QIGJQX_÷cfj䱄‚{sèzðËUat`sofÇZMBm pGMïPQRRúáW\bßiqz‚‰”µÇŸßóûþû¦@0ôÿåÒÀ¶´´´¯¥š‡}qf8 ÿI=2*(.9FÿUbjpwŽœý¥ ¥ š™œž  œ—“‹ÿzoaTJFFMÿWaiosx‹Å“‡ŒnÀüP«`qoýmPjc[NC<8ð\0KRZãàðÿ[_eimpswÿ}„Œ•¡££ÿ¨¶ÐèøûöíÿêíôøôéÕÃÿ´­ªª§ —ýˆiea[RIÿ@;9?KXclÞ °‰—£«ž™}—2™–‰…™ÑßxobWM@T[\³±–—–¸@vüAïspmlQf_UçKC=òIMRûW[õàTU[bhým÷°…‹“•ÿ•“’’–¤¼ÕÿêôóïìïöúßöèÒ»¨H@žšç•‰0 4 aTIÿ?;0¹Ã0µü‡ Îð€wmcZWî•@b^XÌaaa\?Z[aiqx² ˜à ;€úR-þðnpŒ±pv@üPë!ijjhebq^háý€¬Q_bak€wZ\_p0bcf#PÐrAxÓT +‰“àŽ•× ­µ±@¶°ðÇÂÿ¼»¼¿Âý¯¹µ±®ñQbvóqj`h0UPKK~*0\___bfóõw7À‡#᎒—œwš–J’Žˆ švÐqTPy[ñKõNþ0K“ñWW[b î@'à䎀ˆÀ…í„ pž£Æ¨¯µÿµ´®«­±¶¹öš¶µÌ¯«¥¡{š•ˆ`‰„}tÏàßlhaXR:WUQNPRðšðQ€øR {Ga—šœœš¡—׀߀`xðh-€WÄÄ`øáPÿ1q€”ð\aU!kðù°$ÀúñM¢IàûŒ^P­«§¨­ÿ±²¯­¨§ª­˜±à»à½à®ªÔ@J`Ž‹Ç Wà^ßàÚåáá+^ab@mð vÀøpìR ÷PŒ)ˆ‰ˆDÇ è q"¡r2ìRlàRÌ 9 zàcU$C ®”žøó— ¨f ¯é®ó _ µ™¶´±>O@¨¡œ—•°÷{vì€ib\[Ò _Q}Xrà"ô€ºðxÉÁ„…ˆðKàŒGáÜa[ÐÍáì Öð຀8ac0ƱbfjàÑàQVÒãS¡“Ÿ¥«ª¤ ¬ c ¨ýª°á»»¶²¯¯ý±¿à¡œš™—O•‹„6Ðd€f‘cÇ€+±ëáðS ɰf jÍ€]Ñ…øp+â?áL`ˆˆ‡Àë‚g€úƒ÷àR;fà€à@¥DЄþ÷ð‰‹—¡¨¨õ£Œ±±AP­¯²´¿¸¼¿¼µ±+À¯?¨¡šôPÏòP«˜ c^i1m€Ë`ýT;_aa_afam©’®a"ádp•—`"àÉàœÀì€Ò0b_V’Ë Å~€Ò ’P@¢ÝÑüpÐæ Œ•ž§ª¥_¡¡§­®'±-Ãí¯NBžœ ™•’÷ˆÀvtoh=cb@ie^ZtàÛáøð,0,€_bipt°à«À¹Là‹Ž`“Aޝ¡è°wÐv@Ñ0eÖ0låàQ^_dà^_øfó…ãß ‚…ˆŽ•ÿ£¤¡ £¨®ÿ®ª§ª®²´µöÂ0¹´°²®¥ž¿ £¡œ–¬ ‡9€êÐÐ1jmm_ñá$´ ‘_^_±_ÂÏp‡f Jàâ„‘‡±Ò1ccq0¾ÕÔ¡1°œ¡øòljÁŽ—ž¡ ÿ£¨ª¥£¤û¨®ÉÀ´¸»µ­n“°¯ª£eР ï‹„}`xsm4°mjeb`Àäà,Ñ€1Ñ»ÐT ð‘ à‚±‚¯’nPÀ€} aw´ë€Ñ0hOàfe¹ÐcɰVáðä ÏÑj‘`Š€ÿ‰’™œœ™™£¥¤££¥ª®á/¶¸µ®(À®ùÐÙ@àÿÑå­°O‘ÐÐqmheXà"áõÀÉÐSàT œ À>ЬÀ~ n¾‘~ý{Ðqpptz{—xqjPácÕ ©àfh÷€ºpå ½á¿àþAÒÐþ\ ‚žª«¥žÿž§²¶²­«±þ™¼ÂÄ¿´¨¤§«ª ƒa²ßÀºpÿie__epxzsjhΰoð3á,Î0_tz‚Œª°{L€îŠ‘_ciQ^WT r0Ño«`ñQð¿wvqmji vøNÒÐPoq{«ÿÆÔÑù¿ÍØÿÕǽ¼ÄËÐпÐÍ®–‡Ïp}¿ma_fmoPTßQRXaj&}„~ÞО™’–š¢aü™á#bXW[cjpùs! 7Ñmllpwÿ{}{vpib^X˜À ‘‰ WRœ’WšÁ¬/0uBz€‰ÿ{xwz„»ÔÿÜÒÀ¹½ÊÐÉÿ»±±¸ÀÆÇÆï½­“~ðzsiÿcejswvmc¿[X^iv€žÑÿ–œœ“‡}}…ÿ•’‡zspp¯olfa°c`‰—ˆ‚~jÀ‚ÚðÎ}ê·Q@KòJNTÏWURQ­ŸÁmoÓswO  „;à~}øÍàÒൌ¥Æâ÷êÞÍ€ÕÐÆ»ÿ´´µ¹½¼±šOlbaZàÐcÄðÿsmhflxˆ•zwᜢ`…{w¡ ï…}oaèÀ_a^ÿZ[bo}‹—ž•ˆ%ÑrÑhÿ[M@9;BJNØ:Ú1X_ƒ€vt¯pljlðt;Ðzñ~1àmq(ð‰„…ÿ—´ÕìóêÛÐÿÎÑÒ͵­ªÿ«±´¯ ‡m\ÍU]ÂbféPqPttÿz‡•¡§¥ œü§°þomsx{xùo¹€*Ñabhqÿ’¡¨¥šŽ…‚ß‚‚€{víf_ÿTG=89?IQª7`UÁ²Z¤ qPl‚nAp*âBð˜Ñ<°ß`…¿„…‰™¶×æ`áÿÑËËËÊûµÿ²±²²­žˆmWKKR\›%P[€ßvw€Œšˆ±—Û’Œ2 ttBðxpëc[Ì`\ºpo{Œ¿§§‚ªÀ€÷~zsîðje\P?F==DNX&аöðÀWZ*qpjc‡_aeäðlâÌÍpˆç•—ôPÀPØñúÿðÜÍÄÄÄ»þD«§¤ •…p\QPU_jtrкl{‰€‡—Å o™‡~V€qwôðùog‚dls}‹šßª®¥—ˆ¬`~ûwoq°mf\QF?@?CJT[Ä¡”Áø¿°J yÐb\\bj<Üá7w€ˆŽúPê ÿ‹‚{}Ž®Ñÿðÿúåʹ¶½ïÃÿ¹Èµ²¨ÿ“x^MIPasï~zp‡ðmooÿpx…•£ª«¤ñ™p` }}~{scTMPZfÍ€ÿˆ’ž¥¥š‹Ï}vv{¼ JPa[ÓUQäp'qUKJMPTkðbìá6Ð? ûw}Çàztt{…øƒPÐlp‹ž½ÞöÏûðÛÆ;”0»»ÿ»¸¶¯ž‡mXÿPPZhv~€zýqm@cflv€‹•ž¤¥¡•…¤pþD¢„„€tcTKïMUcpŽ ‰“ÿšœ–‹€z}‚¿‰Œˆ€ti¹±TÞˆGJNRæ0FCÿCIQZ_b_\GXX\XPZð&PoPË€Œ€mд‡šÿ¹Ü÷ÿöÞĵÿ±¶¼ÃÇÉÇÄ÷À¼´_^jwß„{obX0@ivî§p—žŒqx}…ÉŽ¨`l`i©âhx„ÏŽ‹€OðLA‰€¥vê‘jZ²É¡PUpF¿JNUZZU;`U@ý1ÜÀÿ@mÎqŸÑ‹@ÿ€‚‹¸Øñøÿêе¨­¼ÍÛÿáÞѶ±«¡¿~phhlƒwýmæAKXiz‚„á‚G À”€š—ÿ‚se\[blt¨¤ìBë€s@0ÛPl}hÊÑllic\Z‘{KMÇ`PNMJ‹ŸNQXai’ÐZðoÿlow„™œ™ÿ’‰„‚„ˆ¡ÿ»×íöìÔ¹£ÿœ¥»ÑãéâÒßÀ±£—Ú€„€ý{`vl^PFDM\o}‚€x1s€Œ•—•¥Óa…Ð@. ¡áÝ }{dho0eÀ jåàac3ð€ ÐÅ¡P4 5¡f±—¢oÈ›mp‹ÐðÓÀ“™ÿ¨ÂÚêìÜÆ±ÿ¥¥±ÃÕãæÞ¿Í¸¤–ŽŒuà–óŽV€IÀZUTWy\yñjbahtRðè­¢¸‘×BŒ§`ˆ}pýiÀ@wxtlc\ø < õ€b^\_cffÖà!°À\À¸pj‘[â qòð~~Ò±ÿ‡Ž“™šššžÿ«½Í×ÕÊ¿¹ÿ»ÀÇÎÕÚÛ׺V«!À¥§¡Ö0xƒtpá"°B"üð·peâ`zBÑ~±qÁ“—œßžœ“ˆ}€‚}vlT— X@[AUΡ‘ Ö!*Ðbçá5hÙ p 0txÍàoQιPŽ’ßap—šÿ£«´¶´­¤ w ¤ªïиµ¯G{œšfÑ–‰MSØ\€" TàfhxÐljHpûðqÑÐmàxmà wÔÐàw8p["· ÕÑ+q”ñNp£áîƒ? ÿákáŠ`2áz±„мor/PÑ@€"3ã}supK¢ôŽ€Ó––’’˜àpR@á{®°ðAJ‚ÌrqO€RÍaûâäuÆ q04ÂÀy°sQ ‚ѰqÐ+pór7qòsÀ.1E`™Ñâ *·‘ŽÞc­pP£ÐzqÕa;° †‚EàÄuìDïtƒ21‚§Á“ƒ%‡†„ ƒÓ°?ákrlR±’’r=ã‹p‰p…î‡ývmtâ ¾¾å¡lS¿sQ31G`Âs"‚0ríE QLiá6‘Í ”sp8â#‘›ÿr솮Ђ‰„„’!ƒ6à•sÖ†‘€rr“‰rÇ“ „’’+so‚ä’“óðûq‰sÿsö“ê„ „•„’“ôs‚ýt¶Q³–º‘äƒü‚Q§–þ•É”ôŠM£ë™…Ea¤r¥©$‡11X¤¡•”:°t”z–á{ì’¨óx²ðxm·hiogÁ„ŒN@…¾P°vojms;?…‹‰ÀpS°o±@"!í Û‹…Úñhb_ðlvñ~L`?ÀÀtpmm_pt{„‹¦p–ªp÷ˆ}Þilqxõî ’â°…{sjœ©àÀ@z‚ˆ¢Ñv¹pîð À}‚ˆЇ ÈáYðtwÑÀªÒï{~…ŽvÀˆÝw§ cfm‡•£­®£}oOÀÿUW_p…šª´ÿ¹¶®‰q^NÿGGMWcs…–ÿ¤ªª£™Ž€qþÞðZbmx‚‰ï•––(±{xs÷lhfžÀpv}‡Ö÷P‹…O0t àpw}…‰Œ³pG±4“BÐ2à‚€Bà z~ü•€jqŸ’»”DÂA=Óª‚A0w— ¶0š‡° he&àtJÀÏ@\°µÐ7ÐsÒcpP)±–”ƒ„/0<Àvpˆ…©Ã¼ÄDâAvdq™nq ƒ @…°Àà:°ë¡‹!™¿tw{ ЂËÀxF’”@Í@qàØàñpà3p‘„ˆ‹M€·rœÑcrÜÁ"QpAqØÑñÀoS2„ÈÁ‚ìÀ5à&’¯Ñ“AvÑ~5zŸ`}ÅÄ~ò©<“Ër¼0€Aá„;ÁU|sÓÓ‘ÄÁ‹K€‹‡`›àGÁyb…0~{}…‰M—ÑÁpŠ`€>ÐÒ€Òá0qñ¬°@pv ý@`àlo‰PðCÓpîð@a°9Á‰pþÐ0q9À€ÀPH€éÐ;°­±‰Ý`°øò ô ãb™œžžž¿œ™–•“àb“~°vÁrËqÛríð}ð¥á0ÔI¥Dðë<””ð†ðäàcëár0|ñ~ðíñ¡ŸÑƒ‡‡™ÐY‘åÐ`‡öupŽ’– ¤¥¤£é¡ õ ð àš™–ñ“ÁEÁ™ãmlif1ðp0ZppoŽ@aÒÆhnÑ’ÒœpŒØðws–°*ZpiCàl—P\ûñ¬Q$QvñmRpÍ`oV Ëü“‡ „€„Œ—£«ÿ±µ´±­¨£žÿœœ ¥®µ»¼»¶±ª£ ¶p”À˜%ËpÓpjf™P [Gafl`Ф¨³€>ÐAŒäðýá›B¡pÊÁx‹PYpp9`__Ž*`Æ+`bf<ðßpNuvxü±Ã]ˆ€„‹“ž¨ÿ±¶¸¶´¯ª¥ÿ£¡¤§­´¹¿ÿÀÀ¼µ­¥ž™¨¸ð±¤s@àjhñXC!\bhm{PÿÆx±Ž\âéò›rŸA—Âfeeef™Ã` ¸`\\ØÖà0µV à[Žs©§À€~ÿ‡š§²»ÀÀÿ½¹²¨¡œ™šÿž§®¶½¿½¸?±§“Œ…NP7qÄ^/ðc;`¼`ajpà2ÑMà+˜@,Á’ŒˆÐÅÁäð‰ ýA“Q0`Q)c _b`³ò!z®´æx~…ïž«µ½Û¸¯§¿ š—™ ¨ÙÃ_À»²¨G@vô@|pÀùolhc_„½b {´Pàðââ0áEÀZŽ`‹‹½°™PÝàYpfu`ß)`_’Ruñ²FàÐdz³þ+!„‰š¤¯¹ÿ¿Â¿¹²«¤ÿš™ž¥®¶¼¿¿¼¶®£—b@pœ˜±)pwtp™Z[_e‡PÞð“ÁÁáVṄjàÀ„{sââz‚‹’–—•ŽX H/á'ÀM1zˆÀ!`[=``V@…#Ñà¯Pv}Q#ò"€!3‚‰– ÿª±¶¹¸´®§ÿž—“’•œ¥±ÿ¹½½¸®¡“‡çzqlÂùApib7^[Z ej^q±KÀì-€ @åБúða°þϰŒ““‰‚0€Páq¼1*áplª€«aŸäO§ÅÀ…á…AÊ€+ÀçÑ‚„¿‹• ­¸½ "šÿ•“•š¡ª²µ?´®¥œ„P’‹R­0Öà_óoŸÀ>Ð‹Šœ!xðÒ…™ÐxPp- òð‚¦°–0A KÀ~woha[X; °cb_«`p!paЀ¯°œqƒ1ûpñÀqPuPwïw{…’K0¼¼µÿ®¤™™œ¡§ÿ­±²®§’‡03ÀÒpgðÞbeÊ1,ñ]j‘ €ˆÀ“!ÀÑ@H"Fq^äℌ‡“——ðšÑ:Á¬zsle_\\E«`„"d3ñv±‰ÚP‚à•„Áˆ@aâŠÑÒpb°ˆ–µ¸¯!¨£ »žF§£œIAx!qYB£>ñÅrwd°c –“}@ˆä1Ð2 ×àô{Pøòlp{„Œ•?££“ˆZðg2zWÒi¨`ZXXZÕ pn6á#á1‚‰h° %@¢²ÆÐ­°ÙÐ}ÒAtì 0_ Œ™º"»µ­Dö0©p–«pVÎ j0¯±5¡Hñ¢ÀRðnQ¥Ð…xpi2á'q&†ÿ–šž—Žt’r°h9ñ7ðho0Þbïchow*P{vÀMp½eѧÀ„=0‹øÃ¤à‹•ž¥«Þ¥ðœ–•–w@œw–‹Í{to˜@o$á3(£prQzŽ M’Òpqt“-€Žb0‹‚Ä aðCauòÍá3ðj|0,‘Br5‘]šp„øÐ:³x]¸r¿s9Àÿ‡Œ’–œ¡£¤‚Ÿ@š…ánâÉÁ¶PÌàiV`Uá3±i”7€ƒAšÐ4P ááCá‘ñÑa”„ŽP0Lj~sšÀØà3fi‘mTqÏn v®ÀÆÒ{EÀ”!map‘æ",€á1ô±¡ƒ}À–šœœ™ªp“’oâýáà€`—3Á‘ÐÏå¹q{§°ßq¹Q@ñ*ƒí!,òÀ‹Wði ²âà0ð? vÝÀ–10ÿÀæ,€”àípA{ž±0¶°%Ò€ìð  á­°7€Õ P™:p•{g±•Œ‡‹t3Á `‚;°óá°°Áp|ÐH°•ÀÞÀx=±¸Qt‡ð@““äÁÎÁpêÐwtr AœÀ!Mƒt¿Àà‚,±_Ð{Érq}sĠ̀ØÑI¡„âa’C¹Bpåò€@‡QPMЛ1Är RÄaS§ÐŠB‡ò”áñâyb‘êâEÀøk1y1pMƒÜ ‡ðÆ À¼áZ‚9ÀÿÂ:Áh nÓ@®’d“F!ãÄ;ÑõÑ—æÐ˜€èòa;±ö§v¨±âÔ“²Ò葲„§0Ð2…0 m‚ ppq¹DRÑÕÁÂã©‚Þ1À‚f“ ³a³‚ù•ÉSá |Ð38£ÊË(“> aÃi¢3æ’å£Õ^—¼Ã¡!ÄÓrñáa^qpö`!b3¡òУǡÇÀDÓ  ê‚g“‘ñ»ƒ6Ñü ¡NÇ6Ô ‚´aˆD‘N’AË9£ÜÁOÔa¡—ñ}Ñ8ÓeÅqÂÙÄ a$áY`¡o“¡±á Óô¢þp0‘V“˜ñ²Z²âÙ’;“ÜÒê!KµÙÐ:20‚t¥À°Å^‘ÙRÏ…š±Pãac—ãQýÁu‚´q’¹ÃÖñ‹Ò£±¡äÐ’ÀMPüÑÍp \qyÐYÀ†ÑÎÓ‰þK´ ¢z¡"µt+¥à²˜´³“rÀ™à$Û“î¢1q0²bÐè!ªÃ~'‘ËR£ÄR³àä¢Ûc5²¹ƒ¢Ä¶ƒ°ÂbQ\`1£»ÃJÐtÁ“ós’Ès'Ñ}sV´Ð‘S@ ¢´ákƒqœÑÂÕ1G‘€1Ñš¢€`]ÞàÍ1'P’U³'„Ó Æ•¶$£’RÔ}°“ñ¥wmÒÂç!VÔÕÁ/†¢r•l—³eâ‘x²Ù‘g¢óÄÞQ½Ây¢®ƒ&”ÎdÁuí’’$”t´ Ó´á\þö¢·³~‘óƒÖ€’F¡Û²r´°Êrè’¼’³b‹‚‚AT“oÂ÷“²†¢ƒâ ÓÚSl‚ЃŸ±„‘‚¥A¢Õ §ÿå„Ô/ ‰±·´†Ä£8ãƒÓËÔ¡;´ZÄ&‘œã²Å gøJõ€`óªÓÓÕj˜iƒ3Ct„aÔq…2ô/aZâÁ)-tϺӲ”,a¤-s!+B/µÂ,BB³¬p{Ô¼âú¢ræ}óF²Æö_`ºA‚PXÁ'÷Ú´4ôËåÔâ£'„±o Ô8æÚÂi’møküÍç‘ÿôsäµ>³¢Ãi£!ÈrÕ'm—[Ĩ Ô ÔÿèˆÓð,³Ãö±propÿBACK½n‡DITHH÷NAMdem§o.h‡¦E ÿGrabberIWnfo‡PŒ2‡ïRELFSORõTy‡TRANÞXGRD1•6‡Y&iÇ þ!For intÿernal usÿe by the gÀallegro4.4-4.4.2/demos/shooter/demo.h000066400000000000000000000003311173507505700172720ustar00rootroot00000000000000#ifndef DEMO_H_INCLUDED #define DEMO_H_INCLUDED #include #include #include #include #include extern DATAFILE *data; extern int max_fps; extern int cheat; #endif allegro4.4-4.4.2/demos/shooter/dirty.c000066400000000000000000000052331173507505700175020ustar00rootroot00000000000000#include "dirty.h" /* dirty rectangle list */ typedef struct DIRTY_RECT { int x, y, w, h; } DIRTY_RECT; typedef struct DIRTY_LIST { int size; int count; DIRTY_RECT *rect; } DIRTY_LIST; static DIRTY_LIST dirty, old_dirty; /* adds a new screen area to the dirty rectangle list */ void add_to_list(DIRTY_LIST *list, int x, int y, int w, int h) { /* dynamicall grow the list of dirty rectangles */ if (list->count >= list->size) { if (list->size == 0) list->size = 256; else list->size *= 2; list->rect = realloc(list->rect, list->size * sizeof(DIRTY_RECT)); } list->rect[list->count].x = x; list->rect[list->count].y = y; list->rect[list->count].w = w; list->rect[list->count].h = h; list->count++; } void dirty_rectangle(int x, int y, int w, int h) { add_to_list(&dirty, x, y, w, h); } /* qsort() callback for sorting the dirty rectangle list */ int rect_cmp(const void *p1, const void *p2) { DIRTY_RECT *r1 = (DIRTY_RECT *) p1; DIRTY_RECT *r2 = (DIRTY_RECT *) p2; return (r1->y - r2->y); } void clear_dirty(BITMAP *bmp) { int c; DIRTY_LIST swap; /* clear everything drawn during the previous update */ for (c = 0; c < dirty.count; c++) { if ((dirty.rect[c].w == 1) && (dirty.rect[c].h == 1)) { putpixel(bmp, dirty.rect[c].x, dirty.rect[c].y, 0); } else { rectfill(bmp, dirty.rect[c].x, dirty.rect[c].y, dirty.rect[c].x + dirty.rect[c].w - 1, dirty.rect[c].y + dirty.rect[c].h - 1, 0); } } /* swap lists, so the just cleared rects automatically are in this update */ swap = old_dirty; old_dirty = dirty; dirty = swap; dirty.count = 0; } void draw_dirty(BITMAP *bmp) { int c; /* for dirty rectangle animation, only copy the areas that changed */ for (c = 0; c < dirty.count; c++) add_to_list(&old_dirty, dirty.rect[c].x, dirty.rect[c].y, dirty.rect[c].w, dirty.rect[c].h); /* sorting the objects really cuts down on bank switching */ if (!gfx_driver->linear) qsort(old_dirty.rect, old_dirty.count, sizeof(DIRTY_RECT), rect_cmp); acquire_screen(); for (c = 0; c < old_dirty.count; c++) { if ((old_dirty.rect[c].w == 1) && (old_dirty.rect[c].h == 1)) { putpixel(screen, old_dirty.rect[c].x, old_dirty.rect[c].y, getpixel(bmp, old_dirty.rect[c].x, old_dirty.rect[c].y)); } else { blit(bmp, screen, old_dirty.rect[c].x, old_dirty.rect[c].y, old_dirty.rect[c].x, old_dirty.rect[c].y, old_dirty.rect[c].w, old_dirty.rect[c].h); } } release_screen(); } allegro4.4-4.4.2/demos/shooter/dirty.h000066400000000000000000000002751173507505700175100ustar00rootroot00000000000000#ifndef DIRTY_H_INCLUDED #define DIRTY_H_INCLUDED #include "demo.h" void dirty_rectangle(int x, int y, int w, int h); void clear_dirty(BITMAP *bmp); void draw_dirty(BITMAP *bmp); #endif allegro4.4-4.4.2/demos/shooter/display.c000066400000000000000000000136031173507505700200140ustar00rootroot00000000000000#include "display.h" #include "dirty.h" static BITMAP *page1, *page2, *page3; static int current_page = 0; static int num_pages; static BITMAP *memory_buffer, *back; ANIMATION_TYPE animation_type; void init_display(int mode, int w, int h, ANIMATION_TYPE type) { char buf[256]; animation_type = type; switch (animation_type) { case DOUBLE_BUFFER: case DIRTY_RECTANGLE: num_pages = 1; break; case PAGE_FLIP: num_pages = 2; break; case TRIPLE_BUFFER: num_pages = 3; break; } set_color_depth(8); #ifdef ALLEGRO_VRAM_SINGLE_SURFACE if (set_gfx_mode(mode, w, h, w, h * num_pages) != 0) { #else if (set_gfx_mode(mode, w, h, 0, 0) != 0) { #endif set_gfx_mode(GFX_TEXT, 0, 0, 0, 0); allegro_message("Error setting 8bpp graphics mode\n%s\n", allegro_error); exit(1); } page1 = NULL; page2 = NULL; page3 = NULL; memory_buffer = NULL; switch (animation_type) { case DOUBLE_BUFFER: case DIRTY_RECTANGLE: memory_buffer = create_bitmap(SCREEN_W, SCREEN_H); if (!memory_buffer) { set_gfx_mode(GFX_TEXT, 0, 0, 0, 0); allegro_message("Could not create memory buffer\n"); exit(1); } break; case PAGE_FLIP: /* set up page flipping bitmaps */ page1 = create_video_bitmap(SCREEN_W, SCREEN_H); page2 = create_video_bitmap(SCREEN_W, SCREEN_H); if ((!page1) || (!page2)) { set_gfx_mode(GFX_TEXT, 0, 0, 0, 0); allegro_message("Not enough video memory for page flipping\n"); exit(1); } break; case TRIPLE_BUFFER: /* set up triple buffered bitmaps */ if (!(gfx_capabilities & GFX_CAN_TRIPLE_BUFFER)) enable_triple_buffer(); if (!(gfx_capabilities & GFX_CAN_TRIPLE_BUFFER)) { strcpy(buf, gfx_driver->name); set_gfx_mode(GFX_TEXT, 0, 0, 0, 0); #ifdef ALLEGRO_DOS allegro_message ("The %s driver does not support triple buffering\n\n" "Try using mode-X in clean DOS mode (not under Windows)\n", buf); #else allegro_message ("The %s driver does not support triple buffering\n", buf); #endif exit(1); } page1 = create_video_bitmap(SCREEN_W, SCREEN_H); page2 = create_video_bitmap(SCREEN_W, SCREEN_H); page3 = create_video_bitmap(SCREEN_W, SCREEN_H); if ((!page1) || (!page2) || (!page3)) { set_gfx_mode(GFX_TEXT, 0, 0, 0, 0); allegro_message ("Not enough video memory for triple buffering\n"); exit(1); } break; } } void clear_display(void) { if (num_pages < 2) { clear_bitmap(screen); clear_bitmap(memory_buffer); if (animation_type == DIRTY_RECTANGLE) clear_dirty(memory_buffer); } else { clear_bitmap(page1); clear_bitmap(page2); if (num_pages == 3) clear_bitmap(page3); } current_page = 0; show_video_bitmap(screen); } BITMAP *prepare_display(void) { switch (animation_type) { case DOUBLE_BUFFER: /* for double buffering, draw onto the memory bitmap. The first step * is to clear it... */ back = memory_buffer; clear_bitmap(back); break; case PAGE_FLIP: /* for page flipping we draw onto one of the video pages. */ if (current_page == 0) { back = page2; current_page = 1; } else { back = page1; current_page = 0; } clear_bitmap(back); break; case TRIPLE_BUFFER: /* triple buffering works kind of like page flipping, but with three * pages (obvious, really :-) The benefit of this is that we can be * drawing onto page a, while displaying page b and waiting for the * retrace that will flip across to page c, hence there is no need * to waste time sitting around waiting for retraces. */ if (current_page == 0) { back = page2; current_page = 1; } else if (current_page == 1) { back = page3; current_page = 2; } else { back = page1; current_page = 0; } clear_bitmap(back); break; case DIRTY_RECTANGLE: /* for dirty rectangle animation we draw onto the memory bitmap, but * we can use information saved during the last draw operation to * only clear the areas that have something on them. */ back = memory_buffer; clear_dirty(back); break; } return back; } void flip_display(void) { switch (animation_type) { case DOUBLE_BUFFER: /* when double buffering, just copy the memory bitmap to the screen */ blit(memory_buffer, screen, 0, 0, 0, 0, SCREEN_W, SCREEN_H); break; case PAGE_FLIP: /* for page flipping we display the back page */ show_video_bitmap(back); break; case TRIPLE_BUFFER: /* make sure the last flip request has actually happened */ do { } while (poll_scroll()); /* post a request to display the page we just drew */ request_video_bitmap(back); break; case DIRTY_RECTANGLE: draw_dirty(memory_buffer); break; } } void destroy_display(void) { if (num_pages == 1) { destroy_bitmap(memory_buffer); } else if (num_pages == 2) { destroy_bitmap(page1); destroy_bitmap(page2); } else if (num_pages == 3) { destroy_bitmap(page1); destroy_bitmap(page2); destroy_bitmap(page3); } else { ASSERT(FALSE); } } allegro4.4-4.4.2/demos/shooter/display.h000066400000000000000000000007531173507505700200230ustar00rootroot00000000000000#ifndef DISPLAY_H_INCLUDED #define DISPLAY_H_INCLUDED #include "demo.h" /* different ways to update the screen */ typedef enum ANIMATION_TYPE ANIMATION_TYPE; enum ANIMATION_TYPE { DOUBLE_BUFFER = 1, PAGE_FLIP, TRIPLE_BUFFER, DIRTY_RECTANGLE }; extern ANIMATION_TYPE animation_type; void init_display(int mode, int w, int h, ANIMATION_TYPE animation_type); void destroy_display(void); BITMAP *prepare_display(void); void flip_display(void); void clear_display(void); #endif allegro4.4-4.4.2/demos/shooter/expl.c000066400000000000000000000033641173507505700173220ustar00rootroot00000000000000#include "expl.h" RLE_SPRITE *explosion[EXPLODE_FRAMES]; /* the explosion graphics are pregenerated, using a simple particle system */ void generate_explosions(void) { BITMAP *bmp = create_bitmap(EXPLODE_SIZE, EXPLODE_SIZE); unsigned char *p; int c, c2; int x, y; int xx, yy; int color; #define HOTSPOTS 64 struct HOTSPOT { int x, y; int xc, yc; } hot[HOTSPOTS]; for (c = 0; c < HOTSPOTS; c++) { hot[c].x = hot[c].y = (EXPLODE_SIZE / 2) << 16; hot[c].xc = (AL_RAND() & 0xFFFF) - 0x7FFF; hot[c].yc = (AL_RAND() & 0xFFFF) - 0x7FFF; } for (c = 0; c < EXPLODE_FRAMES; c++) { clear_bitmap(bmp); color = ((c < 16) ? c * 4 : (80 - c)) >> 2; for (c2 = 0; c2 < HOTSPOTS; c2++) { for (x = -6; x <= 6; x++) { for (y = -6; y <= 6; y++) { xx = (hot[c2].x >> 16) + x; yy = (hot[c2].y >> 16) + y; if ((xx > 0) && (yy > 0) && (xx < EXPLODE_SIZE) && (yy < EXPLODE_SIZE)) { p = bmp->line[yy] + xx; *p += (color >> ((ABS(x) + ABS(y)) / 3)); if (*p > 63) *p = 63; } } } hot[c2].x += hot[c2].xc; hot[c2].y += hot[c2].yc; } for (x = 0; x < EXPLODE_SIZE; x++) { for (y = 0; y < EXPLODE_SIZE; y++) { c2 = bmp->line[y][x]; if (c2 < 8) bmp->line[y][x] = 0; else bmp->line[y][x] = 16 + c2 / 4; } } explosion[c] = get_rle_sprite(bmp); } destroy_bitmap(bmp); } void destroy_explosions(void) { int c; for (c = 0; c < EXPLODE_FRAMES; c++) destroy_rle_sprite(explosion[c]); } allegro4.4-4.4.2/demos/shooter/expl.h000066400000000000000000000004461173507505700173250ustar00rootroot00000000000000#ifndef EXPL_H_INCLUDED #define EXPL_H_INCLUDED #include "demo.h" /* explosion graphics */ #define EXPLODE_FLAG 100 #define EXPLODE_FRAMES 64 #define EXPLODE_SIZE 80 extern RLE_SPRITE *explosion[EXPLODE_FRAMES]; void generate_explosions(void); void destroy_explosions(void); #endif allegro4.4-4.4.2/demos/shooter/game.c000066400000000000000000000274001173507505700172600ustar00rootroot00000000000000#include "game.h" #include "data.h" #include "bullet.h" #include "expl.h" #include "star.h" #include "aster.h" #include "dirty.h" #include "display.h" #define BULLET_DELAY 20 /* the current score */ int score; static char score_buf[80]; int player_x_pos; int player_hit; int ship_state; int skip_count; /* info about the state of the game */ static int dead; static int xspeed, yspeed, ycounter; static int ship_burn; static int ship_count; static int skip_speed; static volatile int frame_count, fps; static volatile unsigned int game_time; static unsigned int prev_bullet_time; static int new_asteroid_time; static int score_pos; #define MAX_SPEED 32 /* handles fade effects and timing for the ready, steady, go messages */ static int fade_intro_item(int music_pos, int fade_speed) { while (midi_pos < music_pos) { if (keypressed()) return TRUE; poll_joystick(); if ((joy[0].button[0].b) || (joy[0].button[1].b)) return TRUE; } set_palette(data[GAME_PAL].dat); fade_out(fade_speed); return FALSE; } /* draws one of the ready, steady, go messages */ static void draw_intro_item(int item, int size) { BITMAP *b = (BITMAP *) data[item].dat; int w = MIN(SCREEN_W, (SCREEN_W * 2 / size)); int h = SCREEN_H / size; clear_bitmap(screen); stretch_blit(b, screen, 0, 0, b->w, b->h, (SCREEN_W - w) / 2, (SCREEN_H - h) / 2, w, h); } /* timer callback for controlling the game speed */ static void game_timer(void) { game_time++; } END_OF_STATIC_FUNCTION(game_timer); /* timer callback for measuring the frames per second */ static void fps_proc(void) { fps = frame_count; frame_count = 0; } END_OF_STATIC_FUNCTION(fps_proc); /* the main game update function */ static void move_everyone(void) { BULLET *bullet; score++; if (player_hit) { /* player dead */ if (skip_count <= 0) { if (ship_state >= EXPLODE_FLAG + EXPLODE_FRAMES - 1) { if (--ship_count <= 0) dead = TRUE; else player_hit = FALSE; } else ship_state++; if (yspeed) yspeed--; } } else { if (skip_count <= 0) { if ((key[KEY_LEFT]) || (joy[0].stick[0].axis[0].d1)) { /* moving left */ if (xspeed > -MAX_SPEED) xspeed -= 2; } else if ((key[KEY_RIGHT]) || (joy[0].stick[0].axis[0].d2)) { /* moving right */ if (xspeed < MAX_SPEED) xspeed += 2; } else { /* decelerate */ if (xspeed > 0) xspeed -= 2; else if (xspeed < 0) xspeed += 2; } } /* which ship sprite to use? */ if (xspeed < -24) ship_state = SHIP1; else if (xspeed < -2) ship_state = SHIP2; else if (xspeed <= 2) ship_state = SHIP3; else if (xspeed <= 24) ship_state = SHIP4; else ship_state = SHIP5; /* move player */ player_x_pos += xspeed; if (player_x_pos < (32 << SPEED_SHIFT)) { player_x_pos = (32 << SPEED_SHIFT); xspeed = 0; } else if (player_x_pos >= ((SCREEN_W - 32) << SPEED_SHIFT)) { player_x_pos = ((SCREEN_W - 32) << SPEED_SHIFT); xspeed = 0; } if (skip_count <= 0) { if ((key[KEY_UP]) || (joy[0].stick[0].axis[1].d1)) { /* firing thrusters */ if (yspeed < MAX_SPEED) { if (yspeed == 0) { play_sample(data[ENGINE_SPL].dat, 0, PAN(player_x_pos >> SPEED_SHIFT), 1000, TRUE); } else { /* fade in sample while speeding up */ adjust_sample(data[ENGINE_SPL].dat, yspeed * 64 / MAX_SPEED, PAN(player_x_pos >> SPEED_SHIFT), 1000, TRUE); } yspeed++; } else { /* adjust pan while the sample is looping */ adjust_sample(data[ENGINE_SPL].dat, 64, PAN(player_x_pos >> SPEED_SHIFT), 1000, TRUE); } ship_burn = TRUE; score++; } else { /* not firing thrusters */ if (yspeed) { yspeed--; if (yspeed == 0) { stop_sample(data[ENGINE_SPL].dat); } else { /* fade out and reduce frequency when slowing down */ adjust_sample(data[ENGINE_SPL].dat, yspeed * 64 / MAX_SPEED, PAN(player_x_pos >> SPEED_SHIFT), 500 + yspeed * 500 / MAX_SPEED, TRUE); } } ship_burn = FALSE; } } } /* if going fast, move everyone else down to compensate */ if (yspeed) { ycounter += yspeed; while (ycounter >= (1 << SPEED_SHIFT)) { for (bullet = bullet_list; bullet; bullet = bullet->next) bullet->y++; scroll_stars(); scroll_asteroids(); ycounter -= (1 << SPEED_SHIFT); } } move_bullets(); starfield_2d(); /* fire bullet? */ if (!player_hit) { if ((key[KEY_SPACE] || key[KEY_ENTER] || key[KEY_LCONTROL] || key[KEY_RCONTROL]) || (joy[0].button[0].b) || (joy[0].button[1].b)) { if (prev_bullet_time + BULLET_DELAY < game_time) { bullet = add_bullet((player_x_pos >> SPEED_SHIFT) - 2, SCREEN_H - 64); if (bullet) { play_sample(data[SHOOT_SPL].dat, 100, PAN(bullet->x), 1000, FALSE); prev_bullet_time = game_time; } } } } move_asteroids(); if (skip_count <= 0) { skip_count = skip_speed; /* make a new alien? */ new_asteroid_time++; if (new_asteroid_time > 600) { add_asteroid(); new_asteroid_time = 0; } } else skip_count--; } /* main screen update function */ static void draw_screen(BITMAP *bmp) { int x; RLE_SPRITE *spr; char *animation_type_str = NULL; switch (animation_type) { case DOUBLE_BUFFER: animation_type_str = "double buffered"; break; case PAGE_FLIP: animation_type_str = "page flipping"; break; case TRIPLE_BUFFER: animation_type_str = "triple buffered"; break; case DIRTY_RECTANGLE: animation_type_str = "dirty rectangles"; break; } acquire_bitmap(bmp); draw_starfield_2d(bmp); /* draw the player */ x = player_x_pos >> SPEED_SHIFT; if ((ship_burn) && (ship_state < EXPLODE_FLAG)) { spr = (RLE_SPRITE *) data[ENGINE1 + (retrace_count / 4) % 7].dat; draw_rle_sprite(bmp, spr, x - spr->w / 2, SCREEN_H - 24); if (animation_type == DIRTY_RECTANGLE) dirty_rectangle(x - spr->w / 2, SCREEN_H - 24, spr->w, spr->h); } if (ship_state >= EXPLODE_FLAG) spr = explosion[ship_state - EXPLODE_FLAG]; else spr = (RLE_SPRITE *) data[ship_state].dat; draw_rle_sprite(bmp, spr, x - spr->w / 2, SCREEN_H - 42 - spr->h / 2); if (animation_type == DIRTY_RECTANGLE) dirty_rectangle(x - spr->w / 2, SCREEN_H - 42 - spr->h / 2, spr->w, spr->h); /* draw the asteroids */ draw_asteroids(bmp); /* draw the bullets */ draw_bullets(bmp); /* draw the score and fps information */ if (fps) sprintf(score_buf, "Lives: %d - Score: %d - (%s, %d fps)", ship_count, score, animation_type_str, fps); else sprintf(score_buf, "Lives: %d - Score: %d", ship_count, score); textout_ex(bmp, font, score_buf, 0, 0, 7, 0); if (animation_type == DIRTY_RECTANGLE) dirty_rectangle(0, 0, text_length(font, score_buf), 8); release_bitmap(bmp); } static void move_score(void) { score_pos++; if (score_pos > SCREEN_H) score_pos = -160; } static void draw_score(BITMAP *bmp) { static BITMAP *b = NULL, *b2 = NULL; if (!b) b = create_bitmap(160, 160); if (!b2) b2 = create_bitmap(160, 160); blit(bmp, b2, score_pos, score_pos, 0, 0, 160, 160); clear_bitmap(b); textout_centre_ex(b, data[END_FONT].dat, "GAME OVER", 80, 50, 2, 0); sprintf(score_buf, "Score: %d", score); textout_centre_ex(b, data[END_FONT].dat, score_buf, 80, 82, 2, 0); rotate_sprite(b2, b, 0, 0, itofix(score_pos) / 4); blit(b2, bmp, 0, 0, score_pos, score_pos, 160, 160); if (animation_type == DIRTY_RECTANGLE) dirty_rectangle(score_pos, score_pos, 160, 160); } /* sets up and plays the game */ void play_game(void) { int esc = FALSE; unsigned int prev_update_time; stop_midi(); /* set up a load of globals */ dead = player_hit = FALSE; player_x_pos = (SCREEN_W / 2) << SPEED_SHIFT; xspeed = yspeed = ycounter = 0; ship_state = SHIP3; ship_burn = FALSE; ship_count = 3; /* 3 lives instead of one... */ frame_count = fps = 0; bullet_list = NULL; score = 0; score_pos = -160; skip_count = 0; if (SCREEN_W < 400) skip_speed = 0; else if (SCREEN_W < 700) skip_speed = 1; else if (SCREEN_W < 1000) skip_speed = 2; else skip_speed = 3; init_starfield_2d(); init_asteroids(); new_asteroid_time = 0; /* introduction synced to the music */ draw_intro_item(INTRO_BMP_1, 5); play_midi(data[GAME_MUSIC].dat, TRUE); clear_keybuf(); if (fade_intro_item(-1, 2)) goto skip; draw_intro_item(INTRO_BMP_2, 4); if (fade_intro_item(5, 2)) goto skip; draw_intro_item(INTRO_BMP_3, 3); if (fade_intro_item(9, 4)) goto skip; draw_intro_item(INTRO_BMP_4, 2); if (fade_intro_item(11, 4)) goto skip; draw_intro_item(GO_BMP, 1); if (fade_intro_item(13, 16)) goto skip; if (fade_intro_item(14, 16)) goto skip; if (fade_intro_item(15, 16)) goto skip; if (fade_intro_item(16, 16)) goto skip; skip: clear_display(); if ((!keypressed()) && (!joy[0].button[0].b) && (!joy[0].button[1].b)) { do { } while (midi_pos < 17); } clear_keybuf(); set_palette(data[GAME_PAL].dat); position_mouse(SCREEN_W / 2, SCREEN_H / 2); /* set up the interrupt routines... */ LOCK_VARIABLE(score); LOCK_VARIABLE(frame_count); LOCK_VARIABLE(fps); LOCK_FUNCTION(fps_proc); install_int(fps_proc, 1000); LOCK_VARIABLE(game_time); LOCK_FUNCTION(game_timer); install_int(game_timer, 6400 / SCREEN_W); game_time = 0; prev_bullet_time = 0; prev_update_time = 0; /* main game loop */ while (!esc) { int updated = 0; poll_keyboard(); poll_joystick(); while (prev_update_time < game_time) { if (dead) { move_score(); } else { move_everyone(); if (dead) { clear_keybuf(); } } prev_update_time++; updated = 1; } if (max_fps || updated) { BITMAP *bmp = prepare_display(); draw_screen(bmp); if (dead) { draw_score(bmp); } flip_display(); frame_count++; } /* rest for a short while if we're not in CPU-hog mode and too fast */ if (!max_fps && !updated) { rest(1); } if (key[KEY_ESC] || (dead && ( keypressed() || joy[0].button[0].b || joy[0].button[1].b))) esc = TRUE; } /* cleanup */ remove_int(fps_proc); remove_int(game_timer); stop_sample(data[ENGINE_SPL].dat); while (bullet_list) delete_bullet(bullet_list); if (esc) { do { poll_keyboard(); } while (key[KEY_ESC]); fade_out(5); return; } clear_keybuf(); fade_out(5); } allegro4.4-4.4.2/demos/shooter/game.h000066400000000000000000000005011173507505700172560ustar00rootroot00000000000000#ifndef GAME_H_INCLUDED #define GAME_H_INCLUDED #include "demo.h" /* for doing stereo sound effects */ #define PAN(x) (((x) * 256) / SCREEN_W) #define SPEED_SHIFT 3 extern int score; extern int player_x_pos; extern int player_hit; extern int ship_state; extern int skip_count; void play_game(void); #endif allegro4.4-4.4.2/demos/shooter/music.txt000066400000000000000000000020151173507505700200570ustar00rootroot00000000000000 The music in the demo game is by Garret Thomson (g@sirsonic.com). Garret has written the music to two IBM shareware games; Clyde's revenge, from Moonlite Software, and Maximum Justice, by Supremetek software. He has also contributed to Boston Audio Consultants' collection of MIDI files. They in turn sell the music to industry-leading multimedia developers. He has been involved in music for the past 14 years, and has been writing music for the last 4 years. He is always willing to take on a new project, and provide any original music a programmer might need for a game. He writes all styles of music, and can compose anything from rock to techno to jazz; whatever you have in mind, he can meet your needs. If you are interested in contacting him, email him at g@sirsonic.com. For more information about him and his music, point your web browser at http://www.cybertheque.com/galerie/garret/ Incidentally he is also an excellent Webpage Author and computer graphic artist, if you are in need of a webmaster or artist. allegro4.4-4.4.2/demos/shooter/shooter.ico000066400000000000000000000125761173507505700203720ustar00rootroot00000000000000P0h(P`hÿÿÿÿ¢ÿÿÿÿ¢¢¢u¢Ó}ÿ8‚ÿÇÚ‚ºÿßÿÿÿ,Ie‚¢Ããÿeÿ–ÿÇÿÿÿ}ÿÿÿÿÿ 8]Ae$8IMimQ} 8aAÿÿ 44]IuU‚0EI$0(,8óÿ$8E(> 1) + 1) >= SCREEN_H) star[c].oy = 0; } } void scroll_stars(void) { int c; for (c = 0; c < MAX_STARS; c++) { if (++star[c].oy >= SCREEN_H) star[c].oy = 0; } } void draw_starfield_2d(BITMAP *bmp) { int x, y, c; for (c = 0; c < MAX_STARS; c++) { y = star[c].oy; x = ((star[c].ox - SCREEN_W / 2) * (y / (4 - star[c].z / 2) + SCREEN_H) / SCREEN_H) + SCREEN_W / 2; putpixel(bmp, x, y, 15 - (int)star[c].z); if (animation_type == DIRTY_RECTANGLE) dirty_rectangle(x, y, 1, 1); } } void init_starfield_3d(void) { int c; for (c = 0; c < MAX_STARS; c++) { star[c].z = 0; star[c].ox = star[c].oy = -1; } } void starfield_3d(void) { int c; fixed x, y; int ix, iy; for (c = 0; c < star_count; c++) { if (star[c].z <= itofix(1)) { x = itofix(AL_RAND() & 0xff); y = itofix(((AL_RAND() & 3) + 1) * SCREEN_W); star[c].x = fixmul(fixcos(x), y); star[c].y = fixmul(fixsin(x), y); star[c].z = itofix((AL_RAND() & 0x1f) + 0x20); } x = fixdiv(star[c].x, star[c].z); y = fixdiv(star[c].y, star[c].z); ix = (int)(x >> 16) + SCREEN_W / 2; iy = (int)(y >> 16) + SCREEN_H / 2; if ((ix >= 0) && (ix < SCREEN_W) && (iy >= 0) && (iy <= SCREEN_H)) { star[c].ox = ix; star[c].oy = iy; star[c].z -= 4096; } else { star[c].ox = -1; star[c].oy = -1; star[c].z = 0; } } /* wake up new star */ if (star_count < MAX_STARS) { if (star_count_count++ >= 32) { star_count_count = 0; star_count++; } } } void draw_starfield_3d(BITMAP *bmp) { int c, c2; for (c = 0; c < star_count; c++) { c2 = 7 - (int)(star[c].z >> 18); putpixel(bmp, star[c].ox, star[c].oy, CLAMP(0, c2, 7)); if (animation_type == DIRTY_RECTANGLE) dirty_rectangle(star[c].ox, star[c].oy, 1, 1); } } allegro4.4-4.4.2/demos/shooter/star.h000066400000000000000000000004361173507505700173250ustar00rootroot00000000000000#ifndef STAR_H_INCLUDED #define STAR_H_INCLUDED #include "demo.h" void init_starfield_2d(void); void starfield_2d(void); void scroll_stars(void); void draw_starfield_2d(BITMAP *bmp); void init_starfield_3d(void); void starfield_3d(void); void draw_starfield_3d(BITMAP *bmp); #endif allegro4.4-4.4.2/demos/shooter/title.c000066400000000000000000000526531173507505700175000ustar00rootroot00000000000000#include "title.h" #include "data.h" #include "star.h" #include "display.h" #include "dirty.h" /* for parsing readme.txt */ typedef struct TEXT_LIST { char *text; struct TEXT_LIST *next; } TEXT_LIST; typedef struct README_SECTION { TEXT_LIST *head; TEXT_LIST *tail; char *flat; char *desc; } README_SECTION; /* for parsing thanks._tx and the various source files */ typedef struct CREDIT_NAME { char *name; char *text; TEXT_LIST *files; struct CREDIT_NAME *next; } CREDIT_NAME; /* text messages (loaded from readme.txt) */ static char *title_text; static int title_size; static int title_alloced; static char *end_text; static PALETTE title_palette; /* author credits scroller */ static int credit_width = 0; static int credit_scroll = 0; static int credit_offset = 0; static int credit_age = 0; static int credit_speed = 32; static int credit_skip = 1; /* text scroller at the bottom */ static int text_scroll = 0; static BITMAP *text_bmp; static int text_char; static int text_pix; static int text_width; CREDIT_NAME *credit_name = NULL; static CREDIT_NAME *credits = NULL; /* timer callback for controlling the speed of the scrolling text */ static volatile int scroll_count; static void scroll_counter(void) { scroll_count++; } END_OF_STATIC_FUNCTION(scroll_counter); /* helper to find a file or directory in the Allegro tree */ static int find_relative_path(char buf[], size_t bufsize, const char *name) { static const char *locations[] = { "", "../", "../../", /* Allegro root, no build directory */ "../../../", /* Allegro root, with build directory */ "../../../../", /* Allegro root, MSVC build configuration directory */ NULL }; char exe[256]; char dir[256]; int i; get_executable_name(exe, sizeof(exe)); for (i = 0; locations[i] != NULL; i++) { replace_filename(dir, exe, locations[i], sizeof(dir)); append_filename(buf, dir, name, bufsize); if (file_exists(buf, FA_ALL, NULL)) { return 1; } } return 0; } /* helper to open readme.txt and thanks._tx */ static PACKFILE *open_relative_file(char buf[], size_t size, const char *name) { if (find_relative_path(buf, size, name)) return pack_fopen(buf, F_READ); return NULL; } /* formats a list of TEXT_LIST structure into a single string */ static char *format_text(TEXT_LIST * head, char *eol, char *gap) { TEXT_LIST *l; int size = 0; char *s; l = head; while (l) { if (l->text[0]) size += strlen(l->text) + strlen(eol); else size += strlen(gap) + strlen(eol); l = l->next; } s = malloc(size + 1); s[0] = 0; l = head; while (l) { if (l->text[0]) strcat(s, l->text); else strcat(s, gap); strcat(s, eol); l = l->next; } return s; } /* loads the scroller message from readme.txt */ static void load_text(void) { README_SECTION sect[] = { {NULL, NULL, NULL, "Introduction"}, {NULL, NULL, NULL, "Features"}, {NULL, NULL, NULL, "Copyright"}, {NULL, NULL, NULL, "Contact info"} }; #define SPLITTER " " static char intro_msg[] = "Welcome to the Allegro demonstration game, by Shawn Hargreaves." SPLITTER "Your mission: to go where no man has gone before, to seek out strange new life, and to boldly blast it to smithereens." SPLITTER "Your controls: the arrow keys to move left and right, the up arrow to accelerate (the faster you go, the more score you get), and the space bar to fire." SPLITTER "What complexity!" SPLITTER "What subtlety." SPLITTER "What originality." SPLITTER "But enough of that. On to the serious stuff..." SPLITTER; static char splitter[] = SPLITTER; static char marker[] = "--------"; char buf[256]; README_SECTION *sec = NULL; TEXT_LIST *l, *p; PACKFILE *f; int inblank = TRUE; char *s; int i; f = open_relative_file(buf, sizeof(buf), "docs/txt/readme.txt"); if (!f) { title_text = "Can't find readme.txt, so this scroller is empty. "; title_size = strlen(title_text); title_alloced = FALSE; end_text = NULL; return; } while (pack_fgets(buf, sizeof(buf) - 1, f) != 0) { if (buf[0] == '=') { s = strchr(buf, ' '); if (s) { for (i = strlen(s) - 1; (uisspace(s[i])) || (s[i] == '='); i--) s[i] = 0; s++; sec = NULL; inblank = TRUE; for (i = 0; i < (int)(sizeof(sect) / sizeof(sect[0])); i++) { if (stricmp(s, sect[i].desc) == 0) { sec = §[i]; break; } } } } else if (sec) { s = buf; while ((*s) && (uisspace(*s))) s++; for (i = strlen(s) - 1; (i >= 0) && (uisspace(s[i])); i--) s[i] = 0; if ((s[0]) || (!inblank)) { l = malloc(sizeof(TEXT_LIST)); l->next = NULL; l->text = malloc(strlen(s) + 1); strcpy(l->text, s); if (sec->tail) sec->tail->next = l; else sec->head = l; sec->tail = l; } inblank = (s[0] == 0); } } pack_fclose(f); if (sect[2].head) end_text = format_text(sect[2].head, "\n", ""); else end_text = NULL; title_size = strlen(intro_msg); for (i = 0; i < (int)(sizeof(sect) / sizeof(sect[0])); i++) { if (sect[i].head) { sect[i].flat = format_text(sect[i].head, " ", splitter); title_size += strlen(sect[i].flat) + strlen(sect[i].desc) + strlen(splitter) + strlen(marker) * 2 + 2; } } title_text = malloc(title_size + 1); title_alloced = TRUE; strcpy(title_text, intro_msg); for (i = 0; i < (int)(sizeof(sect) / sizeof(sect[0])); i++) { if (sect[i].flat) { strcat(title_text, marker); strcat(title_text, " "); strcat(title_text, sect[i].desc); strcat(title_text, " "); strcat(title_text, marker); strcat(title_text, splitter); strcat(title_text, sect[i].flat); } } for (i = 0; i < (int)(sizeof(sect) / sizeof(sect[0])); i++) { l = sect[i].head; while (l) { free(l->text); p = l; l = l->next; free(p); } if (sect[i].flat) free(sect[i].flat); } } /* reads credit info from a source file */ static int parse_source(AL_CONST char *filename, int attrib, void *param) { char buf[256]; PACKFILE *f; CREDIT_NAME *c; TEXT_LIST *d; char *p; if (attrib & FA_DIREC) { p = get_filename(filename); if ((stricmp(p, ".") != 0) && (stricmp(p, "..") != 0) && (stricmp(p, "lib") != 0) && (stricmp(p, "obj") != 0)) { /* recurse inside a directory */ strcpy(buf, filename); put_backslash(buf); strcat(buf, "*.*"); for_each_file_ex(buf, 0, ~(FA_ARCH | FA_RDONLY | FA_DIREC), parse_source, param); } } else { p = get_extension(filename); if ((stricmp(p, "c") == 0) || (stricmp(p, "cpp") == 0) || (stricmp(p, "h") == 0) || (stricmp(p, "inc") == 0) || (stricmp(p, "s") == 0) || (stricmp(p, "asm") == 0)) { /* parse a source file */ f = pack_fopen(filename, F_READ); if (!f) return -1; textprintf_centre_ex(screen, font, SCREEN_W / 2, SCREEN_H / 2 + 8, makecol(160, 160, 160), 0, " %s ", filename + (int)(unsigned long)param); while (pack_fgets(buf, sizeof(buf) - 1, f) != 0) { if (strstr(buf, "*/")) break; c = credits; while (c) { if (strstr(buf, c->name)) { for (d = c->files; d; d = d->next) { if (strcmp (d->text, filename + (int)(unsigned long)param) == 0) break; } if (!d) { d = malloc(sizeof(TEXT_LIST)); d->text = malloc(strlen (filename + (int)(unsigned long)param) + 1); strcpy(d->text, filename + (int)(unsigned long)param); d->next = c->files; c->files = d; } } c = c->next; } } pack_fclose(f); } } return 0; } /* sorts a list of text strings */ static void sort_text_list(TEXT_LIST ** head) { TEXT_LIST **prev, *p; int done; do { done = TRUE; prev = head; p = *head; while ((p) && (p->next)) { if (stricmp(p->text, p->next->text) > 0) { *prev = p->next; p->next = p->next->next; (*prev)->next = p; p = *prev; done = FALSE; } prev = &p->next; p = p->next; } } while (!done); } /* sorts a list of credit strings */ static void sort_credit_list(void) { CREDIT_NAME **prev, *p; TEXT_LIST *t; int n, done; do { done = TRUE; prev = &credits; p = credits; while ((p) && (p->next)) { n = 0; for (t = p->files; t; t = t->next) n--; for (t = p->next->files; t; t = t->next) n++; if (n == 0) n = stricmp(p->name, p->next->name); if (n > 0) { *prev = p->next; p->next = p->next->next; (*prev)->next = p; p = *prev; done = FALSE; } prev = &p->next; p = p->next; } } while (!done); } /* reads credit info from various places */ static void load_credits(void) { static int once = FALSE; char buf[256], buf2[256], *p, *p2; CREDIT_NAME *c = NULL; PACKFILE *f; if (once) return; once = TRUE; textout_centre_ex(screen, font, "Scanning for author credits...", SCREEN_W / 2, SCREEN_H / 2 - 16, makecol(160, 160, 160), 0); load_text(); /* Don't load top scroller with small screens. */ if (SCREEN_W < 640) return; /* parse thanks._tx */ f = open_relative_file(buf, sizeof(buf), "docs/src/thanks._tx"); if (!f) return; while (pack_fgets(buf, sizeof(buf) - 1, f) != 0) { if (stricmp(buf, "Thanks!") == 0) break; while ((p = strstr(buf, "<")) != NULL) { *p = '<'; memmove(p + 1, p + 3, strlen(p + 2)); } while ((p = strstr(buf, ">")) != NULL) { *p = '>'; memmove(p + 1, p + 3, strlen(p + 2)); } p = buf; while ((*p) && (uisspace(*p))) p++; p2 = p; while ((*p2) && ((!uisspace(*p2)) || (*(p2 + 1) != '('))) p2++; if ((strncmp(p2, " (", 9) == 0) || (strncmp(p2, " (email", 7) == 0)) { *p2 = 0; c = malloc(sizeof(CREDIT_NAME)); c->name = malloc(strlen(p) + 1); strcpy(c->name, p); c->text = NULL; c->files = NULL; c->next = credits; credits = c; } else if (*p) { if (c) { p2 = p + strlen(p) - 1; while ((p2 > p) && (uisspace(*p2))) *(p2--) = 0; if (c->text) { c->text = realloc(c->text, strlen(c->text) + strlen(p) + 2); strcat(c->text, " "); strcat(c->text, p); } else { c->text = malloc(strlen(p) + 1); strcpy(c->text, p); } } } else c = NULL; } pack_fclose(f); /* parse source files from root of Allegro directory down */ if (find_relative_path(buf2, sizeof(buf2), "src")) { replace_filename(buf, buf2, "*.*", sizeof(buf)); for_each_file_ex(buf, 0, ~(FA_ARCH | FA_RDONLY | FA_DIREC), parse_source, (void *)(unsigned long)(strlen(buf2) - 3)); } /* sort the lists */ sort_credit_list(); for (c = credits; c; c = c->next) { sort_text_list(&c->files); } } static void scroller(void) { int c, n; TEXT_LIST *tl; starfield_3d(); /* move the scroller at the bottom */ text_scroll++; /* update the credits position */ if (credit_scroll <= 0) { if (credit_name) credit_name = credit_name->next; if (!credit_name) credit_name = credits; if (credit_name) { credit_width = text_length(data[TITLE_FONT].dat, credit_name->name) + 24; if (credit_name->text) credit_scroll = strlen(credit_name->text) * 8 + SCREEN_W - credit_width + 64; else credit_scroll = 256; tl = credit_name->files; n = 0; while (tl) { n++; tl = tl->next; } credit_offset = 0; if (n) { credit_skip = 1 + n / 50; credit_speed = 8 + fixtoi(fixdiv(itofix(512), itofix(n))); if (credit_speed > 200) credit_speed = 200; c = 1024 + (n - 1) * credit_speed; if (credit_scroll < c) { credit_offset = credit_scroll - c; credit_scroll = c; } } credit_age = 0; } } else { credit_scroll--; credit_age++; } } static void draw_scroller(BITMAP *bmp) { /* for the text scroller */ char buf[2] = " "; TEXT_LIST *tl; int n, n2, c, c2, c3; char *p; char cbuf[2] = " "; FONT *bigfont = data[TITLE_FONT].dat; int th = text_height(bigfont); /* draw the text scroller at the bottom */ blit(text_bmp, text_bmp, text_scroll, 0, 0, 0, SCREEN_W, th); rectfill(text_bmp, SCREEN_W - text_scroll, 0, SCREEN_W, th, 0); while (text_scroll > 0) { text_pix += text_scroll; if (text_char >= 0) buf[0] = title_text[text_char]; textout_ex(text_bmp, bigfont, buf, SCREEN_W - text_pix, 0, -1, 0); if (text_pix >= text_width) { text_scroll = text_pix - text_width; text_char++; if (text_char >= title_size) text_char = 0; buf[0] = title_text[text_char]; text_pix = 0; text_width = text_length(data[TITLE_FONT].dat, buf); } else text_scroll = 0; } blit(text_bmp, bmp, 0, 0, 0, SCREEN_H - th, SCREEN_W, th); if (animation_type == DIRTY_RECTANGLE) dirty_rectangle(0, SCREEN_H - th, SCREEN_W, th); /* draw author file credits */ if (credit_name) { int x, y, z; int ix, iy; tl = credit_name->files; n = credit_width; n2 = 0; while (tl) { c = 1024 + n2 * credit_speed - credit_age; if ((c > 0) && (c < 1024) && ((n2 % credit_skip) == 0)) { x = itofix(SCREEN_W / 2); y = itofix(SCREEN_H / 2 - 32); c2 = c * ((n / 13) % 17 + 1) / 32; if (n & 1) c2 = -c2; c2 -= 96; c3 = (32 + fixtoi(ABS(fixsin(itofix(c / (15 + n % 42) + n))) * 128)) * SCREEN_W / 640; x += fixsin(itofix(c2)) * c3; y += fixcos(itofix(c2)) * c3; if (c < 512) { z = fixsqrt(itofix(c) / 512); x = fixmul(itofix(32), itofix(1) - z) + fixmul(x, z); y = fixmul(itofix(16), itofix(1) - z) + fixmul(y, z); } else if (c > 768) { z = fixsqrt(itofix(1024 - c) / 256); if (n & 2) x = fixmul(itofix(128), itofix(1) - z) + fixmul(x, z); else x = fixmul(itofix(SCREEN_W - 128), itofix(1) - z) + fixmul(x, z); y = fixmul(itofix(SCREEN_H - 128), itofix(1) - z) + fixmul(y, z); } c = 128 + (512 - ABS(512 - c)) / 24; c = MIN(255, c * 1.25); ix = fixtoi(x); iy = fixtoi(y); c2 = strlen(tl->text); ix -= c2 * 4; textout_ex(bmp, font, tl->text, ix, iy, c, 0); if (animation_type == DIRTY_RECTANGLE) dirty_rectangle(ix, iy, c2 * 8, 8); } tl = tl->next; n += 1234567; n2++; } } draw_starfield_3d(bmp); /* draw author name/desc credits */ if (credit_name) { if (credit_name->text) { c = credit_scroll + credit_offset; p = credit_name->text; c2 = strlen(p); if (c > 0) { if (c2 > c / 8) { p += c2 - c / 8; c &= 7; } else { c -= c2 * 8; } c += credit_width; while ((*p) && (c < SCREEN_W - 32)) { if (c < credit_width + 96) c2 = 128 + (c - credit_width - 32) * 127 / 64; else if (c > SCREEN_W - 96) c2 = 128 + (SCREEN_W - 32 - c) * 127 / 64; else c2 = 255; if ((c2 > 128) && (c2 <= 255)) { cbuf[0] = *p; textout_ex(bmp, font, cbuf, c, 16, c2, 0); } p++; c += 8; } } } c = 4; if (credit_age < 100) c -= (100 - credit_age) * (100 - credit_age) * credit_width / 10000; if (credit_scroll < 150) c += (150 - credit_scroll) * (150 - credit_scroll) * SCREEN_W / 22500; textprintf_ex(bmp, data[TITLE_FONT].dat, c, 4, -1, 0, "%s:", credit_name->name); if (animation_type == DIRTY_RECTANGLE) dirty_rectangle(0, 4, SCREEN_W, text_height(data[TITLE_FONT].dat)); } /* draw the Allegro logo over the top */ draw_sprite(bmp, data[TITLE_BMP].dat, SCREEN_W / 2 - 160, SCREEN_H / 2 - 96); } /* displays the title screen */ int title_screen(void) { static int color = 0; int c; BITMAP *bmp; RGB rgb; int updated; int scroll_pos = 0; text_scroll = 0; credit_width = 0; credit_scroll = 0; credit_offset = 0; credit_age = 0; credit_speed = 32; credit_skip = 1; text_char = -1; text_pix = 0; text_width = 0; text_bmp = create_bitmap(SCREEN_W, 24); clear_bitmap(text_bmp); play_midi(data[TITLE_MUSIC].dat, TRUE); play_sample(data[WELCOME_SPL].dat, 255, 127, 1000, FALSE); load_credits(); init_starfield_3d(); for (c = 0; c < 8; c++) title_palette[c] = ((RGB *) data[TITLE_PAL].dat)[c]; /* set up the colors differently each time we display the title screen */ for (c = 8; c < PAL_SIZE / 2; c++) { rgb = ((RGB *) data[TITLE_PAL].dat)[c]; switch (color) { case 0: rgb.b = rgb.r; rgb.r = 0; break; case 1: rgb.g = rgb.r; rgb.r = 0; break; case 3: rgb.g = rgb.r; break; } title_palette[c] = rgb; } for (c = PAL_SIZE / 2; c < PAL_SIZE; c++) title_palette[c] = ((RGB *) data[TITLE_PAL].dat)[c]; color++; if (color > 3) color = 0; clear_display(); set_palette(title_palette); LOCK_VARIABLE(scroll_count); LOCK_FUNCTION(scroll_counter); scroll_count = 1; install_int(scroll_counter, 5); while ((c = scroll_count) < 160) stretch_blit(data[TITLE_BMP].dat, screen, 0, 0, 320, 128, SCREEN_W / 2 - c, SCREEN_H / 2 - c * 64 / 160 - 32, c * 2, c * 128 / 160); remove_int(scroll_counter); blit(data[TITLE_BMP].dat, screen, 0, 0, SCREEN_W / 2 - 160, SCREEN_H / 2 - 96, 320, 128); clear_keybuf(); scroll_count = 0; install_int(scroll_counter, 6); do { updated = 0; while (scroll_pos <= scroll_count) { scroller(); scroll_pos++; updated = 1; } if (max_fps || updated) { bmp = prepare_display(); draw_scroller(bmp); flip_display(); } /* rest for a short while if we're not in CPU-hog mode and too fast */ if (!max_fps && !updated) { rest(1); } poll_joystick(); } while ((!keypressed()) && (!joy[0].button[0].b) && (!joy[0].button[1].b)); remove_int(scroll_counter); fade_out(5); destroy_bitmap(text_bmp); while (keypressed()) if ((readkey() & 0xff) == 27) return FALSE; return TRUE; } void end_title(void) { CREDIT_NAME *cred; TEXT_LIST *tl; if (end_text) { allegro_message("%shttp://alleg.sourceforge.net/\n\n", end_text); free(end_text); } if ((title_text) && (title_alloced)) free(title_text); while (credits) { cred = credits; credits = cred->next; if (cred->name) free(cred->name); if (cred->text) free(cred->text); while (cred->files) { tl = cred->files; cred->files = tl->next; if (tl->text) free(tl->text); free(tl); } free(cred); } } allegro4.4-4.4.2/demos/shooter/title.h000066400000000000000000000001741173507505700174740ustar00rootroot00000000000000#ifndef TITLE_H_INCLUDED #define TITLE_H_INCLUDED #include "demo.h" int title_screen(void); void end_title(void); #endif allegro4.4-4.4.2/demos/skater/000077500000000000000000000000001173507505700160065ustar00rootroot00000000000000allegro4.4-4.4.2/demos/skater/CMakeLists.txt000066400000000000000000000025261173507505700205530ustar00rootroot00000000000000include_directories(${CMAKE_SOURCE_DIR}/addons/allegrogl/include) include_directories(${CMAKE_BINARY_DIR}/addons/allegrogl/include) set(SKATER_SOURCES source/anim.c source/backscrl.c source/credits.c source/dblbuf.c source/fps.c source/framewk.c source/game_sk.c source/gamepad.c source/global.c source/intro.c source/kbd_sk.c source/level.c source/lvlalloc.c source/lvlfile.c source/lvlstate.c source/menu.c source/menuabt.c source/menuctl.c source/menugfx.c source/menumain.c source/menumisc.c source/menuopts.c source/menusnd.c source/menusucc.c source/music.c source/oglflip.c source/pageflip.c source/physics.c source/quadtree.c source/scrshot.c source/skater.c source/token.c source/transitn.c source/tribuf.c source/virtctl.c ) add_our_executable(skater WIN32 ${SKATER_SOURCES}) if(SUPPORT_ALLEGROGL) add_our_executable(skater_agl WIN32 ${SKATER_SOURCES}) set_target_properties(skater_agl PROPERTIES COMPILE_FLAGS -DDEMO_USE_ALLEGRO_GL ) target_link_libraries(skater_agl allegrogl) endif(SUPPORT_ALLEGROGL) copy_files(copy_skater_data demo.dat level.dat ) #-----------------------------------------------------------------------------# # vim: set sts=4 sw=4 et: allegro4.4-4.4.2/demos/skater/blender/000077500000000000000000000000001173507505700174215ustar00rootroot00000000000000allegro4.4-4.4.2/demos/skater/blender/ademo_export.py000066400000000000000000000342651173507505700224730ustar00rootroot00000000000000#!BPY # Version 9: Modified "top", so upper edges means all on the upper side of the # mesh, not any edges facing up. Took as long as all the rest of this # script. # # Friction is now sum of R, G, B components of material color. # Version 8: added the "top" property, and an error message # Version 7: "foreground" meshes and objects now possible # friction can now be set for materials (using color components) # Version 6: merge object types, round numbers to integer # Version 5: objects # Version 4: read edge_height property # Version 3: process geometry into clockwise triangles # Version 2: materials # Version 1: only mesh geometry """ Name: 'Allegro Demo Game Level (.txt)...' Blender: 237 Group: 'Export' Tooltip: 'Export Allegro Demo Game Level (.txt)' """ __bpydoc__ = """\ All mesh objects are exported as triangles. Coordinates are scaled by a factor of 10, so something at Blender coordinate x=10 will be x=100 in the game. And the y axis is flipped, since in the game, positive y is downwards. Every mesh must have a material assigned for each of its faces. You can do this by just giving a material to the mesh object, or also by applying per-face materials. A material must have texture slot 0 and 1 filled in and set to Image textures, where the first texture's image is the base texture, and the second the edge texture. The sum of the R,G,B components of the material color is used as friction. All other material settings are ignored. Mesh object understand the following properties: "edge_height" - The edge height for all faces in the mesh. "foreground" - All edges are marked foreground. "background" - No edge is marked collidable. "top" - Only upper edges of the mesh are marked as edges. Selected are all those edges part of the outer contour of the mesh, which are lying between the leftmost and rightmost vertex of that contour, in clockwise order. Objects are inserted as Blender "Empties". Each object has the following properties: "bitmap" - Name of the bitmap to use. "sound" - Name of the sound to play. "bonus" - If 1, this object does not count towards the number of needed fruits. (So if a level has 30 fruits, and 10 are marked "bonus", only 20 need to be collected. It doesn't matter at all which out of the 30 though.) "foreground" - This is a foreground object. "deco" - This object is not collidable. There are some reserved names. Empties whose name starts with "player" or "Player" mark the player starting position. Empties whose name starts with "exit" or "Exit" mark the level exit position. All other objects (cameras, lamps, ...) are ignored. Currently, there is no sanity checking done, so be sure to: - Assign materials to meshes/faces. - Make only 2D meshes. Blender will happily twist your meshes around, but the exported level simply will crash. Only a planar mesh is allowed. - Don't forget the Empties for the player and exit positions, and set at least one other collectible. """ import Blender, meshtools, sys, time # scaling factor when exporting vertex coordinates from blender SCALE_X = 10 SCALE_Y = -10 COMMENTS = False # Set to True to enable additional comments in the output # can be modified on a per-mesh basis via the "edge_height" property DEFAULT_EDGE_HEIGHT = 2 message_string = "?" def message_draw(): # clearing screen Blender.BGL.glClearColor(0.5, 0.5, 0.5, 1) Blender.BGL.glColor3f(1.,1.,1.) Blender.BGL.glClear(Blender.BGL.GL_COLOR_BUFFER_BIT) # Buttons Blender.Draw.Button("Oh oh", 1, 10, 40, 100, 25) #Text Blender.BGL.glColor3f(1, 1, 1) Blender.BGL.glRasterPos2d(10, 310) Blender.Draw.Text(message_string) def message_event(evt, val): if evt == Blender.Draw.ESCKEY and not val: Blender.Draw.Exit() def message_bevent(evt): if evt == 1: Blender.Draw.Exit() class MessageException(Exception): pass def message(str): global message_string message_string = str Blender.Draw.Register(message_draw, message_event, message_bevent) raise MessageException def transform(matrix, vector): """ Given a matrix and a vector, return the result of transforming the vector by the matrix. matrix = [[0, 0, 0, 0], [0, 0, 0, 0]] vector = [0, 0, 0, 0] return = [0, 0] """ vout = [] for j in range(2): x = 0 for i in range(4): x += matrix[i][j] * vector[i] vout += [x] return vout def direction(tri): """ Given a triangle, determine if it is counterclockwise or not. tri = [i, i, i], where i is a global vertex index. """ v1 = (V[tri[1]][0] - V[tri[0]][0], V[tri[1]][1] - V[tri[0]][1]) v2 = (V[tri[2]][0] - V[tri[1]][0], V[tri[2]][1] - V[tri[1]][1]) v = v1[0] * v2[1] - v1[1] * v2[0] return v def upper(i1, i2): """ Given two vertex ids, determine if the edge is an upper face. """ v = V[i2][0] - V[i1][0] return v def get_prop(ob, name, val): try: prop = ob.getProperty(name) v = prop.getData() except AttributeError: v = val return v def make_contour(ob, base_i): """ ob # the Blender mesh object Returns a pair (edges, upper_contour). edges = {v: n} # maps vertex to sucessor upper_contour = {v: 1} # set of vertices in the upper mesh outline """ mesh = ob.getData() # count how often each edge is present in the mesh boundaries = {} for f in mesh.faces: prev = f.v[-1] for v in f.v: vs = [prev.index, v.index] vs.sort() vs = tuple(vs) if vs in boundaries: boundaries[vs] += 1 else: boundaries[vs] = 1 prev = v # map each vertex to its connected vertex topmost = None edges = {} for f in mesh.faces: prev = f.v[-1] for v in f.v: vs = [prev.index, v.index] vs.sort() vs = tuple(vs) if vs in boundaries and boundaries[vs] == 1: if not base_i + prev.index in edges: edges[base_i + prev.index] = {} if not base_i + v.index in edges: edges[base_i + v.index] = {} edges[base_i + prev.index][base_i + v.index] = 1 edges[base_i + v.index][base_i + prev.index] = 1 if not topmost or V[base_i + prev.index][1] > V[topmost][1]: topmost = base_i + prev.index prev = v # Build the contour list. We start by picking the topmost vertex, then # finding its contour neighbour so we are facing a clockwise direction. cv = topmost # pick topmost contour vertex next = list(edges[cv])[0] # next one ok = False # find the face this edge is part of edge = (cv, next) for f in mesh.faces: for i in range(len(f.v)): if (base_i + f.v[i - 1].index, base_i + f.v[i].index) == edge or\ (base_i + f.v[i].index, base_i + f.v[i - 1].index) == edge: j = base_i + f.v[(i + 1) % len(f.v)].index if direction([cv, next, j]) < 0: ok = True break if ok: break if not ok: next = list(edges[cv])[1] full_contour = [cv] # a list of vertex indices, representing the mesh outline prev = cv while next != cv: full_contour += [next] v = list(edges[next])[0] if v == prev: v = list(edges[next])[1] prev = next next = v leftmost = None rightmost = None if COMMENTS: print "\t# contour:", for vi in range(len(full_contour)): v = full_contour[vi] if COMMENTS: print "%d" % v, if leftmost == None or V[v][0] < V[full_contour[leftmost]][0]: leftmost = vi if rightmost == None or V[v][0] > V[full_contour[rightmost]][0]: rightmost = vi if COMMENTS: print if COMMENTS: print "\t# left: %d right: %d" % (full_contour[leftmost], full_contour[rightmost]) upper_contour = {} for v in range(len(full_contour)): if rightmost > leftmost: if v >= leftmost and v < rightmost: upper_contour[full_contour[v]] = 1 else: if v >= leftmost or v < rightmost: upper_contour[full_contour[v]] = 1 return (edges, upper_contour) def write(filename): global V file = open(filename, "wb") stdout = sys.stdout sys.stdout=file print "# Exported from Blender %s" % Blender.Get("version") print "# on %s (%s)" % (time.ctime(), time.tzname[0]) print "# do not edit, edit %s instead" % Blender.Get("filename") print # Retrieve a list of all mesh objects in Blender. meshobs = [ob for ob in Blender.Object.Get() if ob.getType() == "Mesh"] # Export all current Blender materials. mnum = 0 materials = {} print "# Materials" print "{" for m in Blender.Material.Get(): t = [] for tex in m.getTextures()[:2]: if tex and tex.tex.getImage(): t += [tex.tex.getImage().name.split(".")[0]] else: t += [""] print """\t{"%s", "%s", %f} # %d \"%s\"""" % (t[0], t[1], m.R + m.G + m.B, mnum, m.getName()) materials[m.name] = mnum mnum += 1 print "}" print # Export all vertices of all mesh objects. V = {} print "# Vertices" print "{" i = 0 for ob in meshobs: print "\t# Mesh \"%s\"" % ob.name matrix = ob.matrix mesh = ob.getData() for v in mesh.verts: pos = transform(matrix, [v.co.x, v.co.y, v.co.z, 1]) V[i] = pos print "\t{%d, %d} # %d" % (round(pos[0] * SCALE_X), round(pos[1] * SCALE_Y), i) i += 1 print "}" print # Export all faces of all mesh objects (split into triangles). print "# Triangles" print "{" base_i = 0 for ob in meshobs: print "\t# Mesh \"%s\"" % ob.name mesh = ob.getData() meshmaterials = mesh.getMaterials(1) edge_height = get_prop(ob, "edge_height", DEFAULT_EDGE_HEIGHT) foreground = get_prop(ob, "foreground", 0) background = get_prop(ob, "background", 0) top = get_prop(ob, "top", 0) edges, upper_contour = make_contour(ob, base_i) for f in mesh.faces: # First triangle. tri1 = [base_i + f.v[2].index, base_i + f.v[1].index, base_i + f.v[0].index] if direction(tri1) > 0: tri1.reverse() tris = [tri1] # If the face has 4 vertices, add another triangle. if len(f.v) > 3: tri2 = [tri1[2], base_i + f.v[3].index, tri1[0]] if direction(tri2) > 0: tri2.reverse() tris += [tri2] for tri in tris: # Handle one triangle. print "\t{" for i in range(3): v = tri[i] if i == 2: next = tri[0] else: next = tri[i + 1] flags = "" edge_ok = False if v in edges and next in edges[v]: edge_ok = True if top and not v in upper_contour: edge_ok = False if edge_ok: flags += " \"edge\"" if background == 0 and foreground == 0: flags += " \"collidable\"" if foreground != 0: flags += " \"foreground\"" if flags != "": flags = ", " + flags print "\t\t{%d, %d%s}," % (v, edge_height, flags) try: print "\t\t%d" % materials[meshmaterials[f.mat].name] except IndexError: message("You forgot to assign a material to mesh %s (or \ one of its faces)" % ob.name) print "\t}" base_i += len(mesh.verts) print "}" print # Retrieve a list of all empty objects in Blender. gameobs = [ob for ob in Blender.Object.Get() if ob.getType() == "Empty"] obtypes = {} n = 0 print "# Object types" print "{" for ob in gameobs: if ob.name.lower().startswith("player"): continue if ob.name.lower().startswith("exit"): continue bitmap = get_prop(ob, "bitmap", "") sound = get_prop(ob, "sound", "") if not (bitmap, sound) in obtypes: print "\t{ \"%s\", \"%s\" } # %d" % (bitmap, sound, n) obtypes[(bitmap, sound)] = n n += 1 print "}" print collectibles_count = 0 print "# Objects" print "{" for ob in gameobs: if ob.name.lower().startswith("player"): continue x, y, z = ob.getLocation() anglex, angley, anglez = ob.getEuler() deco = get_prop(ob, "deco", 0) if ob.name.lower().startswith("exit"): type = -1 else: bitmap = get_prop(ob, "bitmap", "") sound = get_prop(ob, "sound", "") type = obtypes[(bitmap, sound)] bonus = get_prop(ob, "bonus", 0) if bonus == 0 and deco == 0: collectibles_count += 1 foreground = get_prop(ob, "foreground", 0) flags = "" if deco == 0: flags += "\"collidable\"" if foreground != 0: flags += "\"foreground\"" if flags != "": flags = ", " + flags print "\t{ %d, %d, %d, %d%s } # \"%s\"" % (round(x * SCALE_X), round(y * SCALE_Y), round(anglez), type, flags, ob.name) print "}" print print "# Level" print "{" for ob in gameobs: if ob.name.lower().startswith("player"): x, y, z = ob.getLocation() print "\t%d, %d, %d" % (round(x * SCALE_X), round(y * SCALE_Y), collectibles_count) break print "}" sys.stdout = stdout def fs_callback(filename): # Mesh access is better done outside edit mode I believe. editmode = Blender.Window.EditMode() if editmode: Blender.Window.EditMode(0) try: write(filename) except MessageException: pass if editmode: Blender.Window.EditMode(1) Blender.Window.FileSelector(fs_callback, "Export Allegro Demo Game Level", "mylevel.txt") allegro4.4-4.4.2/demos/skater/blender/level.blend000066400000000000000000003071141173507505700215440ustar00rootroot00000000000000‹ì] |UÖŸIAu5*jUÔ¨»Ú]‚ø¨«@ ˆUA" Ôw […6–‚E³>ë*_XWÔ ºÛ]E㪘Uøˆ¶Õà3îç®ÁÇZŸf}Feå;grçÎLh›€Ä‡_è2ÿÿ™sgîœsçν“‘c;yôqÎsØá‡MèÑ4­mæ—+ᦳÏwð™8µº®Z³/'hZ#ü~÷‚ÑÈø5G¶*gÈ¡euµ3«këëÈ÷:ûÛüÒߌÊ^0ZáïÓn÷m7‚‡¶¡‡:ÀÎE7êõé*òéL¡köetÙ¤²ÌÖlÆ©üþ#·q^+`Ôež"Êk%¼$`ný¡¼$áyÖCYOÝ/nþN ^ZõðZ£.ciÕ?ÂK®\Ïí©¼$áyþ þ1^«KÝ/nþN žj¯’ðZ£.ãßrÅ^+á%Wþ—û§ò’„çÁºÀxšÅ¿ˆ€“‚gñð4¦Ëðä~‹Ñ?ø~ãu1žc<\˹]„ëÝ©¯Xo’\ÜιM€Q‹vñüX¹M„lÚþ>sެÜ(áZ»Z´Ùº^ÖuÎÅíœëŒZ¬GI®Ÿp[£Ö¬wÿµs[7 µÉ,Ü$á–èíj=ëˆÛ97µflp° Ü`Ôšv¸ÂÕ\í†iû{g.nçÜrÀ¨Åý;qË 7µx’Üá&£Ï¯—”› \OÄAXÇcëÄÅíœ[µÉ,Ü F-–­Ò&Ü4`Ô¶fᦠ×ñÛ´å8àvÎmŒÚd»Í„‹yµxÌœêCœp5¦Åc`µÛ1¿41nñ.™\Åë–1é7r]xüЬßkYÇ¥•­»´>}>,ºW+‚ãÁÁ~6[Ýpí$s¬{›v#¾c»å»­_ÄÊ—Ü&Ã[[w§ªnšg\UcuCmÕŒY½+ÇqÓjkëÎëȲ ×;Ì¿ÖüÍýN¿ÃýÚ ,ǸêY5ùì3_¿ÇèÝû¾r¿ƒÔgðÛ;žYÕ¸ó^js?åüê©9»m.Ýù¾r¿ýýẅrŒn¨º(Ÿ}æëwOŽ7úÊýöl mE(ǨúºY Uµu¹íüý¾ÞÕ½ßè+÷;ËqÜôé°ßÜ|Æ%_¿_†ø³¸¿SÄïèvWa½¼¾þ‚ܽÞ|õë÷}å~‡¶o7Ìc^ÕÐX;uFµç„:ˆƒUS-·$›Ýïlõë÷}å~WþÚmPމõÓ§ÔO››ë~ ¿ÑWî·wh·@9ÆÏn ÌÎc¿ªë¦U7ä®Ç¥»ë}å~kG±ùî7_}Oâ úÊýÆüåÀ¼“û^ó÷»'q0Nü6XSß0³j ÖŒƒó·`»kÛÎÛ_}à3tèÐúi Éf›Ù[¥ù^mþÕjFáß›®ú]ïåMÉHM‹u¨±îâÇFàÞð¶!3ûæ½8rYh) –o’ž)ÓtÂÆòöí¦|6âáàÞê'½ðùÑЊ—ˆ ‰û]äý‡{@¦¿Ë¼¯ù^Þ÷o*Ÿðþ¢_ïÕ’ëû‘uÙ®kýú}X¤ãý‡þ´Ëùþ#Û¡eâå+Ù Ê·‹¼'õ>¥ãŸêfµñäú•ô» ~êw.zŠaºiD'üøø-üí þÓõ]t¹>@ÏlÏ”O×_Ñ?×±„ßö"‡r´íÖn´í!﯌]á¾zW™çpÇ/ü9“ªêfM‡ æñ7Ôª¡‘QÝ«æÑiµÕ Ö…º\¯½,â×bË6îwbW5îb9†Žöà®õ ž@žçë·ÿ¸ßû;øweÎǹÌo~^gâÒ¢cíVƒ#òû.?}êµ¹°zmÓÿõž2ë··.ýí» ¾]“ãþƒÚF®«M}üTßí£¥N>™eû‘ÔVg–é»nó¤#˜ö°‰Ñ^ßÿ\<Îgåõô;ç2æ»ÅñÜ‹õšæ^¬ó2÷:ÕñŸs/]dî¥{îÅ|ÄsSòÀvsﻦÏYôÈ]çýzÛw~=¸êÈJ¾¾î%æ†{]™ÜÊs]ÇÜÄ×ÕÜär•Cn¾¿ö,}©ÐVø•ÌMXÇèchi[kùç¦õ½¡Û–ý´?m47•è™rMe~—ï“)Æ…Lýo=kã{¸xć¿wvðós1ĉÖ(||¸æf¬Ïõ îÇŽ[“ën¶}Û78?ZåùcÀÎh¾‡þ¹½WËÞéôŒ3³È²â±{ZË/ìáDMé¾íK¬R?vËà­]£®¯ÀõÇq³yޏÉ÷™¿¨[Aleâ¶ÎîEfèV+7e/_¦N´²²,eå2<í–s;¥\Áhæ\ãßËØßò‘rݾÌ#瞯Ëò€ßÁßî»1ø7“sæÞû(Ê…ºZ{xÌÇ2јå•1ß¹|?Ç|¹ôôÆyóqÁ`ŽÕbcÆø¸¦{.ÝÎÖÆê]_Ÿ¦µk™Ïû!øúš\Oh´Ÿ¢¨¨C䘓æó‹½íF×á2æ7 ‚û·Á2æã:ø=r~ }èè+ùXŽBïCÇû1<¼ kHæx‹>‚Ó]-‹}«•õàvOó5C9Üá¶e{t5ÕZû–Û¬ØûŒ!™{(•k{öÝ5ì»mÙÇ7$SÏš¾š}ŸYt-3®<ËwîX26-æ÷„xÜù=!^xNÄ=¡ã9زÏ1z[Ì%ÛsŒé~dÓ÷æ9Fþ±íÿ×sŒŠ«òYy=ýîÇzŽõš¶°Î‹öA–8ósû@.ÝÝòù68džϷ‰ìÖaàüÉ9ìÐqõÓªgxTÛ¢Íväâ£Ûfø4 k7¢ð‰_š™o³ömŸ#´÷‹¾ìóÄ_ÓÙë:Ÿg¶ø<‹ò£ÚmMeÎ+'¼fÀ†à>¢ÌÛh&¼úÉxèåÅÏ(…²žÅ¿Râà˜ôQWü#¼fÀ¨cö^3áÅ——r{·é„#<µ°§òp›ðpŒñ"VÿOcº OÚ3ÇÌMÆÌ3C<>\+ÆÌnño3õÏKÌ‹Û9·pœqñ8Y¹•„Ûµæ¹tà¶n 0j å¸JnŠpKi7Pk–ÍÁ.nçÜ `Ôâ1ˆ9pƒ„ŒZ´sð!F¸îcÛ ÔšõÏ‹Û9·0j˳ح ÜVÀ¨E»üÚßãEûd‹ùÝ“z‚¾Šö÷hûï!@_Eû{"´¿Oùi¼‡}íoÀXŽB}A×42ÞŠøÝ6 Úß°>qjCm qdÍÜüÎès÷—nÛß“HûûThOÜòïOÀãíôþz¼ÑWÑþ> Úß“2÷ ¹ÜçðesÅŒ¢ý}iO†ö÷©ùßïü~£¯¢ý Ë‘oû;_=.ݶ¿‰ß‘ hOÆ÷>Ì®Ëçþ0_=.ݶ¿+HûûthOÆö÷¬ÆêºÜ[þùúÝ“ø¾Šö÷Ðþ†rL¬¾pvuÝÔœÏ×ïž´cÑWÑþ†v –£ oÓòh üíAôU´¿c9&TÍ äó™ÍÕ¯‰}—¢ýMüŽíï3±Ÿ­¡¡¾ÁcYË¥#{sµcqíï³HûûlhŸÉú³ÂÁ½ï#ü1úÑWÑþ>ÚßP޲™S<ã§NÍy¿›ËoôM´¿Ï!íïs¡ý}væ~§þ"³'"§GT?Æs)ôU´¿+¡ý}NþýöùÞ/áÒmû»’´¿c9òÝo¾úžÄÁñ»­ Úß•xß0£>ÛâÍæ7ú&ÚßU¤ý=Úß°í„™Uçås–óõ»'õ}íï©Ðþ®b÷Åfÿ`=ÔóßïžÜÏ£¯¢ý ÷XŽB}ïÞûŠö÷4ÒþŒå(Ô÷®Ñû´.âw¤ÚßÓ ÷½k¸ˆöw5iO‡ö7ø=jvÜÌÓ´‰³¦WMímMý1Úƒè«hŸíïjîwîÉ?F?2ú*Úß5Ðþž®ø]°ýÈè«hÆrŒ©¯Ë«×æÇ8Þiâ7Ž»ÂrŒ«ŸV;½6÷žäMçwöç$è++‚å€ö` w³ZÔesù¾ññz8ÞÏa ] ¾çÇòe³Íì­Ò´%£5í¦58gí¹eúš“ÿü§ÑîxßÕ›cŽÝËøç2ÿ/]üŠÁg²Í´T(,Ÿ‡•éæo0–wÇòébîòøÜd]»6ô“-;Ÿ?×±”|>¿ÓÜý©;nýîçùüöÅMö`i´(s7pbÖk>G Ç»bçsÄœëx4Êß±ÓÙq}Ùóú®ž÷À>#‡|úŽïúmev¾}Ñûfþ~eþoÖ]°×Šïï•9Þšißù8vÿœ“‚e¡sR°œ|NJ¶xöóœ¹ôtÎ*Žíæã¼Ë2óJ̱æGɱ÷›Ê'ÇÝRÄgÈõ¿’õGØö~Ú6xEöûª¾ýQïö½–îûþfàÇZ>,/ΗÁòò1ït.ˆ+½Ìö¾¶oè0oî >o.(?Ácþãì…à?]ßK—ëÙöþp†°dÇö¹Ä…9ñù,åK6‚ÏóÚô¸§ÌoV»án”÷?¸ÎÛ+ø=j¶ôœÜC´]]›Ûzó•¶³°¸ß]Þ$~OÒ»¯%žѦ¸H}¯%Ö5»ÕÞµ ~9ûé>/<•ßõZ?ô>þ]oëõýݽªbXå Õë#wjk¬_»Ö–'6l˜»†ï¿(ýk–ëjS?µ<ö+CmS|oFL9ôºCÿ<Ì:”îsÕQ7ŽÐÚ­Ø}ÁÊc5u>(Fâê]ß²»}÷Å]g¯Ç5™¯Î(›1£ú¼†zÏèê™õžã«fjƒkêgV®žQ[5kð )3̑ăgέ¿¨n°6˜±‘l¶Çéê ÁZ`ð¨úºÆêºÆYƒ'TϪŸÝ05Ÿ^çeæÜÕsªg jl"]hy½Ç#sìµ¾â;—C=¶'}7 [>Û¢|è¯ß¨´åF§š=_jÚšl‡Òõ½t¹ÎÛ¡ÛiÛjøn˜ˆ–i‡f{7LM°Ý(ݵÃ(ýKĨ½ÌˆÍo7Z.#ó¶æ“çÖ—ýtÚ¡è+m‡b9 ½Š9ÏÏ‘:”wÃ`]s¶\2J+]þŒ²îÛÍEqçŒK²¼&¢l¿|Ý7ë»aÚ«âwíFÉ—èÌ•>ià'ø¥ún˜C¿™}þ]¦E¤ŒF1çñ5þNèÃDo\Þn ½ñ#é{²Z…>^ÜiÓ£†ë+‡}ÔGõÞ}ìúJ¢F{T?!rƒôÿ»>Bôî+ÚÊËUÿ©>Ub×£†ëkGÔýG©Þ?È®¯!ú(`´'õ¾U´üá¡v}”苯l7j,zº÷Ñv=j¸>8ªèCŠ>0Ü®} 0Ú£zåü²ëcD﹪Ý\©ú_¾îbyþO°ëQÃõM€cý'§TÈó²]ßDôqÀhúOõ©‰v}œèK®†œcÑSÿý§Ûõ¨áú ย*Ç?|Ž]$ú`´Gõtÿîiv}‚è½×´AEŸRôZ»5\ß 8aÑSÿãuv}3Ñ'£=ê¿rý7ÚõI¢/m¬ê£ÔÿÐ\»ÞÔ0}pÒ¢WÎÿ|»>Dô]€Ñ­¡ÕGÈó¥]ßEô¾kÛP³ºª_k×£†ë[wYô‡ÝEžÿíú¢OF{ÔªÜj×§ˆ¾ü÷ÐF¹V­ÿÔÿøv=j¸¾pêZõüÓãï½Ç®o%ú4`´Gõtÿ¡ûìú4Ñû¯k7Z¯Ö_ªOýÙ®G ×·N[ôÔÿÃv}Ñk×·hOêÝ«iý ?f×£†ë+·Yôtÿî'íú ¢F{R_¢è+íú0Ñ ÿ[ôÔÿøÓùÉÿ€Ã׫þÓøá}Á!ÿ}0ڣǟÆÐKùŸèÝ7@þ_ îŸêS¯:äÿHþQô°OzýÿÃ!ÿ}0Ú£íåúÛ!ÿ}ñÿ-zåúß!ÿßHò?àè ªÿÊõÿ‘Cþ'ú`´GãOøøuQ®‰æÿ‰Þ‚ü£ºª÷~åÿC$ÿŽYôé’EBúÎ!ÿ}0Ú£þS}jƒCþ'ú’› ÿ‡ÔøIý÷÷}Ñžÿo"ùp<¤ÆOzüÃÛÚõA¢OF{TO÷ïvÛõ ¢÷Þ ùÿ&5~R}`W»5"ÿNXôÔÿøžv}3Ñ'£=zýR½×c×'‰¾ôÀ=õ?ô+»ÞÔ0}pòfõú§úÔoìúÑwF{TOý÷{íú.¢÷Ý ùߢW®ÿ#ìzÔˆü¸ë5þR½û»¾…èS€Ñ©¿Š>à³ëSD_~䋞æøqv=jDþœ²è•öÿIv}+ѧ£=Z~åþÏo×§‰Þ¿òÿmêþ•û¿SízÔˆü8mÑÓüá?Ó®o#zívÈÿ Uÿ•û¿J»5"ÿn[¨Æ%ÿO·ë+ˆ> íÑø©äÿ ìú0Ñ-ÿ-z%ÿìzÔˆü8|»ê¿rþçØõ•DŒöÈñ/Sîÿ.±ë#Dï¾ò¿E¯´ÿ‚v=jDþ±è•ëÿj»¾†è£€Ñ‰ßŠ>|]%úâ?@þ·è•ø“]‘ÿGïPýWâÿB»>@ô1Àhž?%ÿßi×LjÞs'䋞æ_ï½v=jDþ³è/0HèC´ë›ˆ>íÑúKõ©ìú8Ñ—,‚ü¯è£Qª÷?âÿ‘ü8®è}«hùÃËò?Ñ'£=ª§ûw/wÈÿDï½ ò¿¢)úÀ*‡üÉÿ€=õ?þ¬Cþ'ú$`´GÛÊùïpÈÿD_z7`‹^9ÿkòÿÝ$ÿN*ú”¢O½îÿ‰¾ 0Ú£zê¿ÿ-‡üOô¾{ ÿß­æåü¯sÈÿ÷ü¸Ë¢WÎÿùŸèS€ÑÍ?ÊùÿÄ!ÿ}y+ä‹^9ÿÿqÈÿ­$ÿNYôJûÿ‡üOôiÀhêiü ­wÈÿDï¿ò«š¿©>¥¿dÏÿ÷’ü8­è+”ö“¿Ÿ]ßFôÚbÈÿ÷ªzš¿ÂÛÛõ¨ùp›E¯ôÿíl×W}0Ú“ú€¢ìnׇ‰ÞXùߢWúÿÚõ¨ùpx±ê¿rÿ¿¿]_IôÀhê•ûÿƒìúÑ»ïƒü¿Dõ_¹ÿ?Ä®GÈÿ€#Š>ªäOÿav} ÑG£=?}ø(»>JôÅ÷Cþ·èéõçf×£FäÀÑûTÿ©>0Ò®} 0Ú£íåú?Þ®½çÿ½OÑ{ÇÙõ¨ùpÌ¢Wâÿ»¾‰èã€Ñm?”žµ£÷šl×lj¾äOÿ=ä¢÷Ÿm×£FäÀquÿQªO±ëƒDŸŒö¨þÙŽ1†É]c×'ˆÞÛù_ÑûVQ}`¦]‘ÿ',zê¼Á®o&ú$`´GÛTïm²ë“D_úgÀ=õ?t©]oj˜>8©è£Š>u¹]"ú.Àhê•óßl×w½ï/ÿ}JчØõ¨ùp—E¯œÿ[ìú¢OF{´ý œÿ»>Eôå@þ·è•ó—]‘ÿ§þ¢æoåü/±ë[‰> íQ½rþÛìú4Ñû„üoêùØŸ¢÷?èÿ$ùpZÙ¿Oñ?vÈÿD¯-…üÿ ª§ñ«õQ‡ü¿”äÀm½Ò¹Ì!ÿ}0Ú£ùSi¿.wÈÿDo<ùߢWò×*‡üÿÉÿ€ÃKUÿ•û×çò?ÑG£=º¥ÿºÃ!ÿ½ûaÈÿ©ù_é¿\ëÿ&ùpÄ¢§í?ïùŸè£€ÑÕ+ýo9ä¢/CþWôW*í·Ô:‡ü&ùpTч½ÿ‡üOô1Àhê•çן8ä¢÷<ù?¬ú¯Œ_øÜ!ÿ?Bò?à˜EOÛooò?ÑÇ£=ê¿2~a½Cþ'ú’¿BþWôQ¥ÿÆëŠÛóÿ_IþWô)Eêg׉>í‘ø;Ré¿ÞÞ®O½÷QÈÿ½rýïl×£FäÀ‰¿ªþÓøÞÝ®o&ú$`´G÷¯Ü¿îm×'‰¾ô1À=¿ýízSÃô!ÀÉGUÿ•üu]"ú.Àhžê¿÷P»¾‹è}CþWô!µýz˜]‘ÿwYôJûõ(»¾…èS€Ñm?+í—av}ŠèË—AþWôQÍŸá‘v=jDþœ²ì_i¿”Ûõ­DŸŒö¨þÕ%ׯÙõi¢÷?ù™ê?ÕÇ'Øõ¨ùpZÑkõß[a×·½üÿ„Ú~§ûm×£FäÀmýâÀß…>5Å®¯ ú0`´GÛïTﯱëÃDoü ò¿Eÿ ñ?<Ó®GÈÿ€ÃŠ>¤èݳìúJ¢F{TOý4Ùõ¢w? ù_ÑG}üR»5"ÿŽXôÔïv} ÑG£=Ú~§úP³]%úâ§ ÿ[ôÊù_`×£FäÀQEï^­œÿ[ìúÑÇ£=ªW΋]#zÏrÈÿоDÑ»ï¶ëQ#ò?à˜E¯œÿ%v}ÑÇ£=ÚþTΛ]'ú’¿Cþ·è•óÿCþÿ;Éÿ€ãоbõÓôþåQ‡üOô ÀhêéþS‡üOôÞÿ}@ÑûW8äÿ$ÿNXôÔÿð‡üOôIÀhú,É?îçò?Ñ—®lÑiÿõ‹ù%Éÿ€“+Tÿ©>þŠCþ'ú.Àhê•þ«7ò?Ñû¢ÿ-zeü¿ò”äÀ]ŠþJµÿú]‡üOô)Àh¶•ç—:ä¢/_ùߢWÆ/|êÿW‘ü8UýWÆ/|éÿ‰> íQ½òüú[‡üOôþÕÿW©þ+ã~pÈÿ«IþœVô‹Ôñ }ÖÚó?Ñkk ÿ¯VõÊø…þv=jDþÜfÑ+ý×;ØõDŒö¤¾M¿0À®½ñ4ä‹^¹ÿÛîGÈÿ€ÃŠþ1eÿî}íúJ¢F{T¯Œ_ÿ¥]!z÷3ÿ}T}~ñk»5"ÿŽXôÊøåÁv} ÑG£=ê¿2~ùp»>JôÅÏBþ·è•ñËGÛõ¨ùpôÕeüê»>@ô1Àhê•ñ«£íúÑ{žƒü¯è;ÔûÿízÔˆü8fÑ+ϯÆÛõMDŒö¤>¡Ž_d×lj¾$ùߢWž_a×£FäÀñçTÿ•çWçÚõA¢OF{ôúSú¦Ùõ ¢÷>ùߢWÎÿùv=jDþœˆ©õÆïÖ™v}3Ñ'£=ºeüMÀ®O}é €-zš¿|v½©aúàäóªÿÊøÙ‹íúÑwF{´þSÿ“—Ùõ]Dïk‡üÿ‚zþ•ç¿WÙõ¨ùp—EO÷¼Î®o!ú`´Gë¯òüú&»>Eôåÿ-zê¿çv»5"ÿN)ú÷Ôú»È®o%ú4`´GõtÿÑÅv}šèýÿ}Jím³ëQ#ò?à´EOý¯|È!ÿ½ö"äÿNÕ%~<æÿ_$ùp[§züiüОtÈÿDŒöèþ•þÏ•ùŸè— ÿ+úEêõÿŒCþ‰äÀa‹^i¿µ;ä¢F{T¯\ÿkò?Ñ»ãÿ_Rã‡òüá ‡ü'ùpä%5~P}ò-‡üOôQÀhÆeüß;ùŸè‹×Bþ·èéþƒ]ù-Éÿ€£q5~(ã>uÈÿDŒö¨žúïùÒ!ÿ½çeÈÿkÕú«Ü¿|ëÿ_&ùpÌ¢§þG78ä¢F{´þ+÷_}_¶ç¢/yò¿EOý¯ÜήGÈÿ€ã½òüh'»>Hô Àhƪ×v·ëDï}ò¿¢_¯èãízÔˆü8aÑÓë·u»¾™è“€ÑÕ+í·»>Iô¥¯~U-?Ÿ¾Av½©aúà¤eÿJûóp»>Dô]€ÑÕÓø™<Ú®ï"zßëÿ_SýWưëQ#ò?à.E_¢Eôåo@þWôî‘´ÿÛsŠ]‘ÿ§,ûWÆ_œf×·}0Ú£zÚ=Ë®O½?ùÿ Õ¥ÿ}Š]‘ÿ§}Jy~QYc×·½ö&äÿ„úüHÿPg×£FäÀm=Ý¿Öh×W}0ڣϨ>>×®½ñÈÿ==~­—Ùõ¨ùpøMÕåùÍUv}%ÑG£=ª§ý·¾ëìúÑ»ÿòÿ?Tÿ©Þ}“]‘ÿG½OÑ'Úõ5DŒöèó'ª/²ë£D_üä‹~éñz×Ûõ¨ùpTÑkÕûÛìúÑÇ£=ªWŽßƒv}Œè=ÿ„üoÑÓþçøÃv=jDþSôÑ(õ?ô¨]ßDôqÀh>¿RÊÿ„Cþ'ú’AþWô!Eï~Ê!ÿÿ‹äÀqEUôñùŸè€ÑÕ÷ãYþÕùŸè½oCþWô)EïÖ!ÿ¿Mò?à„E¯”ÿ‡üOôIÀh>?RÊßéÿ‰¾4 Ø¢WÊ¿Ö!ÿ'IþœTô%ŠÞÿšCþ'ú.Àhê•ò¿éÿ‰Þ·ò¿¢÷©åË!ÿ¯#ùp—E¯”?éÿ‰>íÑç'JùßsÈÿD_þä‹^)—Cþ‡äÀ)‹^yþö±Cþ'ú4`´GŸŸP}è3‡üOôþw!ÿ+ú+ÕçŸ_8äÿwIþœ¶è•ç—ß8ä¢×Þƒüÿ®ª§ÏÏâß9äÿ÷HþÜö®Z~úü,ôƒCþ'ú0`´G÷Oõ~×+öüOôÆûÿ-zúü̽]‘ÿ‡-zeüx»¾’è#€ÑÕ+÷o¿°ë#Dïþ7äERïw²ëQ#ò?àˆ¢_¤öìj××}0Ú£ýJù‹íú(ÑùߢWÆ ´ëQ#ò?ਢLÑ'÷µëDŒö¨^yþy€]#zOäEUÇŸh×£FäÀ1‹^v°]ßDôqÀhö_(ãφØõq¢/ùò¿E¯ÌŸ8Ò®GÈÿ€ãŠ>¡žÿcìú Ñ'£=ªWÆŸ•Ùõ ¢÷~ù_Ñ¿§ÖŸ1v=jDþœ°è•ñÇ'ÙõÍDŸŒöèý¯rýb×'‰¾ôcÀ½2î4»ÞÔ0}pRѯWôî³ìúÑwF{T¯ÌŸ­²ë»ˆÞ÷ äÿUÿ•ñÇÓízÔˆü¸Ë²eüé »¾…èS€ÑžÔ÷Y£Œ?½Ð®O}ùÿBþ·è•ç7sìzÔˆü8eÑ+ÏŸæÙõ­DŸŒö¨^yþø;»>MôþO!ÿÃú¸ã¸~Û5ódûçv»5"ÿN+ú>Šwêo#zí3ÈÿŸRýúÕT_Qúª=ÿFò?à6‹~ׇnzßñv}ч£=ê?ÕÇγëÃDo¤ ÿ¦?ª¯¹Ý®GÈÿ€ÃŠÞ½æERþæçíúJ¢F{TO÷_ìyÍžÿ‰ÞýÈÿŠ~7E_¹¿]‘ÿG,zê¬Ä®¯!ú(`´Gý_óU«l?l×G‰¾øsÈÿ¨/“ú½-õ×8äÿÏIþUô»)úôµùŸèc€ÑÕOŸþ¢Ð'¯wÈÿDïùòÿçªÿT»Ñ!ÿAò?`´7‰Ô?êøf‡üOôqÀho9þ«¿J }â‡üOôøÞÍ&E¿›¢×nsÈÿ_’ëŸÙ“úŠÿ% Uýöðßéy ÓäÊ|"_fÞûê|5Û–YtñO|ohùÎóþ!ļ¯ 1ï·BÌûÀóþ4ļo1ïçCÌû Í÷%7JÌû2ó~Qļ1ï¯EÌû~ó~dļOÚôÿ8âÿâÿÑÄÿÉÿƒˆÿ%Äÿý‰ÿ‰ÿ»ÿw"6Ù{uÌý!1ßé?{a–ñ\‰ù˜s_“$æcULû'JÌÇИöGHÌÇö˜ö—˜ÏCÌã'b~-™6o–8¶½¬¼¾™xù=’¹¯_IÌßÏd–eO‰ù{£Ì²¸É±Ú–«¾äXmûâïì2í%1—˜iÿ#‰ù;ÎLûoKÌß½fÚ•Ø‰ØØšØ_Iì?Iì?Fì?Lìÿ™Ø¿Ø¿‡Ø¿ƒØ¿•Ø¿‘Ø¿–Ø¿’ØŸOìÏ%ö‰ý:b¿–ØŸFìŸCìŸNìO$öO&öO öGûÉý£‰ý¡Äþ b¿„Ø?€ØßGbþ¬Ôäô%1a©óßJÌŸ-›ûúTbþÌÛôç¢ HÌÛ%¦ÿ×8_´þóqLæõržÔòühÆŠÛ$nÞQjyAÜå&eLâÀ¯Iø%‰û’²ìAÊ;€”kú“8Ó‡ØgãXMûßJÌÇךö?•˜û5í¿+1lÚSb>NÚ´ÿ"±ÿ<±¿†Ø_AìGˆýG‰ý‡ˆý6b ±7±ßBìßBì/ ö›‰}67£í_*1Ÿ3‚˜Ï?AÌç² æóbLûSˆý³‰ý âÿâÿ8â9ñ$ñ±±±(±±¿?±¿7±¿;±¿3±³Dæ >_Û´Ó"1ŸGnÚY 1Ÿßnúy¹Ä|Þ½i¿‰Øo ögû5Äþbÿlb2±?ØGìOì$ö‡ûGû‡û‡ûûûû‰ý݉ý‰ýí‰ý~ľNì¯'9ô’CÿCrè'$‡~@rè:’Cß"9ôu’£×ûÄþ³Äþ*b9±¿ŒØ„Ø€Øÿ#±/±'±¿Ø¿‰Ø¿ŽØ¿šØû—ûsˆý±±?د$öÏ$öO%öýÄþIÄþqD{¾ŒŸü>Úš#²µø¼Óþò{>Ìôù b-‰ÿí¤-÷ ‰á+%æãúLûIÌÇšel“˜ƒ4Ã"’Co'9å&’C¯#yç*‰ùxVÓÿ‹‰ÍíIŒêGb‹‹Ä¨õäÚù†\;Ÿ“kçrí|@®uäÚy‹Û7ȵ¹–Øï öŸ#öWûËÉ÷¿“çˆ÷9™û#1ï 3÷;CbÞGgî·JbÞwhÚ?Ø?…Ø?‰ØCì—ûÇûGûCˆýƒ ¿˜´Ó|¤þ/#e?Pòùióüî+¿ç}Oæ÷×;×ùlmþÜݬ“¬Åj'Ûu”Í& °)mòñ ›Ò&3±)mò瘛ôx~¼Žg×fðsÅfðó©ÍpÞŸØ e/~eÓ—}Wù=ïEÜ“{þ<ÔªÍç>ˆ?£Ý”6ùsãMi“?ËÞ¤eHâùÁ›Èæ/oúãùݦ·ÉÇFlJ›|¼Â&µù É›·“ó•¥ß@i’>>–Ä䔼ֽ6K_“cµ“Oÿ'´)mò±K›Ò&Oµ)mò1^›ôx®Ý dzs3Ï6Ãñ|v3ÏÕ›Áf›¼®ùsÚ_×Ylf‹3ÔOªím A->çÁßIÆß¤ã¿“Ù©ÃÀß«Cœý÷é¶ìï$÷öw§=5rõƒg‰ßI.ùûMø\쯔ëôÛÉôw’óÙ¿Và¿“|ðe;ÿÿþ;ÉX¯ùï$;wXçùï$«u\þN2òøï$Wî°árÔ8-[ïï$ãï ãñâ¿'ìÐaà±ÄgÎ)…õ{Âè÷4Vü=U,SŸ–Á²øï c™èï cyùï g+ŸGûù÷„ù‚]¶ßž8·AìÙ­ÃhdÜŠÉ_”Çvâ„¡‡Ž«j¬n¨­š¡ÕO«žá™X[wž<'»w-{v øûu~ø„ÆÃLJñAÑúC}ºŠR®g÷ËMÖ÷ç~7Êôþr?»¿‰“±ýä÷ƒî¸”÷ƒŸv®à>pÉèÌßšQpÐV=X´L¬÷À ˲ñûÁïû¬elÑ¥˜¬ãOk™z ·×Ÿ¡€uÃFö:ò>»ÎŽëËžŸÐwõ¼ö9äÓw|×ÏhëQ¼ÔY÷ÀWæÿfÝ{­Ø8*s¼5Ó¾óq¼¡hcÇ—÷å`Yh_–“÷åd‹M6bwðF¶ý\x8Zé´÷ b›˜·›eúc¬ïƒßn*Ÿ°ýÛ¯ˆ÷ºÈõýȺ‡l‡+²ß‡P[ }¬?¥}œmáåÃ2ñòi>¸;TÞãÑ>” Ž÷YmlØp-žü…ˆ½AüœøÆXó9Ì¡EÿñAJ_øK×'kr½‚mÏ”¯OŸåÚC.lÿ?ªÏw,Ÿ÷hðy¸<Ápÿ[*Ûÿ¸ÎÛu>ïO§ý¾r¿ÝC: ,Ç–nÿCxÝÐßè+÷; ˱¥ÛÿPK~èÎï$ñ;|ä‰![¾ýíßÿvç7úÊýí0°þ†ê9µÕå¼WÑ?ÇÒßè+÷Ûx‡åÈw¿ùûÝ}ýF_¹ßž# ö@9&ÖTÁyÎýñEþ~w_¿ÑWîw 0–cRuSãì†êœ÷š¿ß£×wçwŠø=²ÃÀrŒ« xN¨Ë=„çï÷Yßwç7úÊýÕa¤˜ß“êsßkþ~WšÇ»–Ýoô•ûyË1¡jf Ÿ‡s›ëºÄkû¾Òþ,Ǹچ†úϤ†ªºY-â÷Æã7nÁö ïc(ùm¦}"û¾]”Í2kµbÃ(-xëÓ¬OÁ\ÿËÃsžÞ°á¼MÞÇ€m1d™ÞªÏZ Èû°L¼¡dX‡å•} öò-?ñúá\]¾r¿+w0Û–¿nš=âšÚ#‡ÇüS°©}öÖíÃö-)qΆ±æö‡o«ñï§nøûÅ\fö1< ú@óðp{+غôû€×=`wØâú³ZÇ”-¸<šÜéf³á™ÃÏñÞ­g®|òæЇ•o?3ÂwþÇÿú¼)èÃðÃO˜9|ÝŽ8{À¸•`ceêX¯ïò½ý=¸ïãeàCÙú›¶t»†Ÿ4u5ÜçÝØë ŽZ}îÀááÛЂÅÿé·M«#»}\6äúe«÷úæžhß=çŒ<äüWý»Ïã#ç÷kõåÛÎÎ÷øýc_߈_îtÝŠeøåŠE÷XùÏñO‘>ûbk”o¡ö1XÇÕ¼¹ÏˆóKÑxÐ÷Jß ^t¬Q.JŽÂzÍÇ á½Öy>nhc×pfÁ>Oìã}9Öõž/[rÜ\66nH.¼íÇÀc)û1œ>šXvÚqž1'Œ=βmðìY ™q)µu ƒù°óotrÌ®k¬mœQ=-3^&{TGÉú1NM ²uüß‹^¤ßñS¿sÑS ÓMæ50»¯˜¹t0¹Ïçëd;ö`RT¡›ýØ.žYÔ% þ—qÂy·ó<“ÅßYÂêÑä~ŸØ-ö®/ZY½ïËýJЯý ü®ÇÙ\ØqÖ^ØãÍc?{Ó°1·ŸDýƒ$.óE|ú]?6|kŽi=¯÷û7õÙÏó¦=~jyºïËVóLÆVÏóŒ:¦ëÛq5¿÷Y÷ÙÓï6Ó˜V%Ïà5Œõš·S£; ¬ó¢­èXÇ-‹9>—i£~ô¨C"Í£ÿ\=pû–¥[||"æQ,Ï£x­cyEí¶|[wÅãEó(K‘G³;¶‘ÑCï½îé²ßiCuò=à•a¦?&½µÞ{çøPëtœýkOR·sŽ«mÇý£k>„xMä˜7žñèŠñ—D~‹ú_¨°Æ‡#àûÃO-ò²ïƒèSZC7>Á÷~7ûïÝyÎïø}Ñçüî Jyìq8—ûQÜ'æÑA°_jkX³æÑÅoþÁgÝgO¿û±ò(ÖkžGƒ“: ¬ó2:ÕqËRàyËÄó(^ëX^™G»+ßÖGñxÑ<ŠÇRæQçcçÑ~Σ|é.ò¹†8¿Ï5l½¢ÃÀ¹‡’sø¡«/œ]]7UyÈÏ-¦A[z&äaøWu•ð)¿Ôi®a¢ÛFñ“Ï1C[|ŽYiEö¹†¸óš£.ÃPç6^0·ik!¼4à&Á³øGx¥§Ãq>ÆTÿN'þN {*¯‰ð"€Q—±·9~SøGxiÀM§Ë¹†”—&¼Ò3À?aïK]ñï âà´°§òš/u¸}’KåE/ ¸Ið,þÖ™ÈÜ¿>ªgªs Ógpÿ$Ïœût&™ûtf†SÊÎ׊¹O„kœ•©¯Xo"\Üι~ÀQÆM;pý„Ûµf];ÝÎm!Ü$`Ô¦+èy—Ü$á–œ íÙ³2õ·ÉÁ.nçÜ`Ôâ1ˆ8p„ŒZ´qð!B¸Ú9F€qÓvq;ç–F­Y§Ï°sË 7µéÓeý¢Üá&—3n“7A¸žs!“±éÄÅíbî)`ÔšÇÁ[C¸aÀ¨dᆠ7 µ¸'nšp}•j±>¤¸¸]Ì=ŒZ<NÜfÂF-‡Ò3íÜ8ábüF-ÖG'.n§sQ›v°‹í:ÌüÞÌ]“Ùί!5væ¿ð8ýY_jYÇåA¶îÒúôù°h©ùÌð:ÝyÌsK5ÔŸéÒÇŠ)Flš+„ë|¬PÉԟΘ`ô•ûŒåØÒc‚{2'0MüÆó€åØÒc‚{2'}¥cʰ[zLpwsq Ö~_Ưy_¶Ïúl¶™½UtÞþsÛƒ›mÞ^Ë™E¶mùâ4¦ ï-°LôÞË+ï-œË÷óܹôtî Æ~žŒÚÌýæYÞN£íŽ|—œç¾h¹Ï}Á2ñòy–—çpÌ‹¼m÷^é ¶¾©¿½Xk›7ÈÇjhšõý_ÿŸ‡¿|r_—”ÿ=²=3÷Ýc–/ÛÜwíü£µÎù^ëV¶Ï Žžo™<ùÀåê\`m¤}½û…ÏÁõdŠ="£Ã¹ÁÚÈžÌ ~ŒùV;o½ü„uCñÓi¹˜ûYæ´Îç{¦s…ùº[øÍçè©~gï_±÷aŸ/úÎû|ñ¼`¹dŸ¯S9rË¿ËOŸC½VôÓ§O·ÛÑ^ï³~ÇÇ uïÓ½¨>¨åÙ¼ói=l¼wr‹.JŸ/æ^¬×4÷b—¹×ùZ5s/öëM*›p¼¥Æ|îm²©ºôÌãÖ£îr/æ#1ïtÄÃZy/!÷ÛN×ðÊò=ÎM§º2¹ç+öü‹®ãǺ•¸Uß Ÿéý³Üƒ_y´Ñ97=ƶ󘟾0Ó1ÿ7ÎG¯g1Ý þÎc‡¿çë;±í½ùÖgbÜé…dÜ)”Ë%c¾S9 /æwS_½SÌÿÍ÷où¬ßýóíËO5æc½¦1뼌ùÎ×êÏ1_.2æ;?ËsñçȘÏa0ðgÒêt w¾µw¯îGp\é|}G—\w»è\|—k’ëk3¶g‰ù‹:ŒØ%Î1Ÿ§âvþ<5Ö”áÉ穃Zuòhá»a_)߯k]—±ÿk†w!±Ÿ¯»Ùö-ùÂÃs‚º Oµ¼Z‡å\+ÆV]CÆV]“©ÈÅ2Y¹~ÂmŒZ´uà¶n0jÑfô*Y?ÄØ*Â-iî0Pkû«í\Ü.ÆVN2»>n€p#€QÍ®v-Ü‹5göïÄÅíbl`Ô¢¿NǬœpC€Q‹õÞçpB„›\θA„ëk×´}•3·‹±U€QkÖ[n áb\@­/ 7ü{uüj5‡slÎsþ½lŸ¦®cu’]Û¼i›hÉõ¹s‘V”ósg,“x®~K&žò:á#×ôů§mí©'ׯìÕÜ—;a'¯i²‡¯¦Éõ”Fûyt}‘¾› K˜í] Í7tÍ7ÉsÐu=Ôër|®‹w€/`ãIñ%LÓëfzü õê†ÆÚÞýÞËiµÕ Í#i^¯½,ÆÍ,¶lï_`y8”cèhîÚüœ@žçë·ÿ¸ßû;ømÎ5ºÌ5ºÉ2×èôAsÖ¶ì}Bêµ¹d»O8ðá"Û}­Kcû.Û}Bþ×Õ¦=~ªïÝÿž[fÙø\£l Ž(±Î5êzf„ÏÊëéw?Æ\#¼OÀzMï°Î‹ûÇ:þó˜/ºô´oóÏMØÆÇ\dm›(ië‘»λýýìÖw±¯c¿r—.ÛÞ˜{èúždû^ÍMýûu}ì‚ܫݟ%÷Æo_ï&íXÇñˆiŒÇ%ßÜtB —:jø» ÚhnÂóå:ŸùÝt[¦|ØŸ”©ÿƒmõ¿e—Ìof:_2¥¥“®¬?ˆ‡ñ¯'|>¾6¾‹Ï~ØúKlÝÌ7lÿ5Ü—…ú¶ÍF|É,ÁQòoÓ M»êÊç+´àòÅyì„}žOç†ÐfYüY–‹?«Šß×Ämdî_Ö2ò¥g¿‰eA| ó‹÷%þÇí…ò[Ù»ú[øÎ}<^üûÑ8v É;÷³»epŒÖ®Q×Wàúã¸ÆÙ<GÜäûÌ_Ô­ ¶2y23âX×fèV+Ý¿s¿••…ÿ†Iè¨÷·“ß01ËÕûß0™GÎ=_—åÉï7Lîc~Ö2Ÿ+ÿ1Êð ­'õx#¿Ï çf†®s<ï3HYø:=7ÒÖÅ£3e±ÿ>'úf¾Šß½îYï¿'šÅoÈ1.<Ö«4í›QÖuêïì÷D©¿|ÝͶ˥§¿'* ÉÛåè7o—cNÂ2Év¹S¶ìï«äšÓùï«ì·f¼ëô›+?ÿ¾Š}ù©ößc½V~SöNÚ.wŽ/?·ËåÒÓv9¶Åé3[l§‹¾AKŸ[¾Ël'¯õ¿YÖq‰°uœ“·Hÿö‰iãõ,ãAì0ÜK¥‘Ö£üÙ.ÇuÞ.o¾7Ã[[w§ªnš‡¿ˆ»—/!?nZ­å‰Fï—îæˆ¡¯ÜïŠÅ–c\õ¬š|ö™¯ß=™“‡¾Š9K: ,ÎÉó̪nÄçò¾÷ñSίžšÇÜ8\º¹„ÌŒåÝP•û]hùûÝ£9ÄïØ}–cT}ݬƆªÚºÆÜÞ®Ÿ¯ß=šyŸô»åþËqÜôé°ßÜ _¿qäânüF_¹ß5ì0°åõõäó;›«ž`]à~£¯ÜïÒ?uXUCcíÔÕžê VMm¬­¯û1ýÎVOÒÄoô•ûm´uXމõÓ§ÔO››ë~ ¿ÑWîw0–ã§0-‡÷êõvr8ß8Êø; þ›ºçÉ÷~ `Ô›çNðßÖý'I~ á'û'âð8ÉO~IîwgÁÿJ|äp~p’ñwüïõäÑ’ ü`Ô# ø?èîÃ%?BøÚß:Œãï*øšË7Hò‘Ãùå€#Œ¿áJ$¿œðC€QxwÁ¯rµî/ù!ÂO.gübÁÿH”üá{žì0BŒ¿‡à¬k»K>r8¿p‚ñ÷üwuïN’_CøaÀ¨G¼—àߨ»yQðÄŸ\Ãøÿ&=|„ä§ ß÷T‡fü½ÿVÝï•|äp~3à4ãï#ø­zjÚZÁo&ü8`Ô#ÞWðïÓCçJ~œð‹—wÍŒïü?éÞ3$9"þŽ3þ~‚ÿ=>Iò+ ¿ 0êï/øKõÀxÉo#üàJÆ?@ðÖÝ'J~ŠðKÿñŸñ)øa=rDüÜÅø‡þ0W|OÉo"ü(`Ô#>Tðqv•ü(áQˆÿŒ?Hðv¹Ý’ÿG°à_â o+ù~ÂoŒz³ì‚±ËßWò[? ØÏøC?µ¡SÆÂ/YñŸñüù®Ðw’ÿ'¨à_êò~%ùÂF=âÉ?ñÏ$?BøÚjˆÿŒñ'ð‘ä#GÄÀÆ?RðçºÜïK~9ᇣñQÄŸðÛ’"üàrÆ/%þøÿ!ù Â÷¬øÏøG þe®Ô«’ÿ'ÿ·ôø¿$ù5„ŒzÄǾ÷É~p ã+øó\ñ§%?Mø¾§!þ3þ0ÁŸí ¬”|äˆø8ÍøÃÿ—ûIÉo&ü8`Ô#!ø§ºÂI~œð‹ŸøÏø>ÁŸæò?,ùÈñpœñËWWêÏ’_Iøm€Qx¤àïà Ý'ùm„Ÿ\Éø£¿ŸË{ä§¿ôYˆÿŒ?Zð—éñ;$9"þN1þq‚¿\Ü*ùAÂF=â1‚ÖÝ7J~ŒðÝÏAügüã¼¾Vò‘#â?àã— þ™ºÿJɯ üVÀ¨G|‚<¿zj¾ä·~à Æ?Qðç롹’ßEøÞÄÆ?Ið¯Ô½’ÿw1þXÁ¿X×I~áG£ñ8Áÿ—¨•ü(áÏCügü“?¡»§I>rDüeüñ‚ÿ²>Gòý„ßõ¦VðŸÒý§K~ á'ûÿÁ_¥§&’øOø%/@ügü ‚ÿœ:™ÄÿHüœdü‰‚î=ÄÂF=âI‚ÿ=>ŠÄÂ×Ú!þ3þ©‚›Nâ;‰ÿ€#Œšà_¦»&ñŸðC€Qx²à_¡‡‡’øOø ÀåŒ_!ø×èþA$þ¾§â?ãŸ.ø7ê©ÿ;Hüœ`ü3ÿz=t‰ÿ„ŒzÄg þïuï>$þ~p ãŸ%øó]•ÛÉû‹4áû:!þ3þÙ‚ßè õ•|äˆø8Íøçþ$Wtiÿ~0êŸ+øç¸Rß’ö?á¿ñŸñ+ÿR—çKÒþ‘ÄÀqƯü}\þOIûŸðÛ£ñÁ_§»HûŸðS€+ªàÿ[¿CÚÿ„_úÄÆŸ&ø§¹RÒþ‰ÄÀ)Ư&üÖ™¤ýOø1À¨G<]ðç¹¼ƒIûŸðÝqˆÿŒáÇMÚÿqÿÇ¿Fð/s~)ù„ß õˆk ß½¯ä·~à Æ?ŸðÃ{H~á{×Bügü Úc$9"þîbü„ŸÚAò›? õˆg þ%®Pɾñ2ÄƯüs]Þ>’ÿG¿^ðÏpÅˆËøOø-€QoÆ^ÁŸè |+ù-„Ÿìgü ’Ëý¥ä' ¿äˆÿŒß ø§¹ÂŸJ>rDüœdüY‚ªËÿ¡ä?õˆÿ Wê]ɾö*ÄÆŸMŽgè_’ÿGŽà·éÞ7%¿œðC€Qø"Á¿V¿"ù!ÂO.gü&Æ÷k¯é%?Aøž× þ3>„Ñ_{Ww?/ùÈñp‚ñ/þå ¯‘üÂF=âKÿ—…ä‡ ? ¸†ñç ~™+‘ü4áû^‡øÏø— þ‰®Ð£’ÿ§¾à¯Ó½I~3áÇ£ñe‚ÿ–o“ü8á¿ñŸñƒ‚ljä#GÄÀqÆÿà¿®»ï–üJÂoŒzÄ— þ³z¸EòÛ?¸’ñ¯ügtÿ-’Ÿ"üÒÄÆ¿Rð×ê©’ÿ§ÿ*ÁOè¡fÉ~ 0ê_-ø7èÞ+$?Føî7!þ3þ5‚õÿRÉGŽˆÿ€cŒß,ø—ë&ɯ üVÀ¨G|­à_¡»gI~+áw®`üß þ2=rDücü˜àÿE/“ü ÂoŒzÄÏ þRÝÿyþKø]€+ÿÂO=@žÿ¾÷ˆÿŒßNü ý‘<ÿý„ÄÀ]Œß!øsuï½äù/áG£q§à_¢Çï$Ï ßø_ˆÿŒÿ¢àÏÑ Éóßÿ%ñp”ñ_üFÝ}yþKø-€Qo^;‚ÐÃב翄Ÿìgüµ‚_«û¯–ü$á—| ñŸñ_&õ!”|äˆø8Éø¯Ðã‰ä?õˆ_ü‡tïɾöÄÆMðÖãÉGŽˆÿ€#Œÿ:á.ürÂF=â7ÿ¯º{ºä‡?¸œñ‚­®”üá{RÿÿMÁ¿N÷Ÿ)ùÈñp‚ñÿAø©S%¿†ðÀQøˆ?!?‰ÿ„Ÿ\Ãøo þÕº÷$ÿ ß÷ˆÿŒÿOÁ¿\GâÿHüœfü þi.ÿù¤ÿŸðã€QømÆ÷¹NЃaÒþ'üâÏ!þ3~RØ_¦{xEÆÿÏIügüu‚_ïJ¾Eúÿ ¿ 0ê¿#ø³\î7Hÿ?á§W2þ»‚?Çå[Kúÿ ¿ô ˆÿŒÿžàÏuÚIÿÿ$þN1þû‚‰«õÒÿOø1À¨GüoÁŸïН$ýÿ„ïþâ?ã ø—¹´'Iÿÿ—$þŽ1~—àŸäò>Fúÿ ¿0ê(øc]•‘þÂï\Áø~¨ôÿ¾÷+ˆÿŒÿ1áG“þÿ¯HüÜÅøŸÿS‹Hÿ?áG£ñÿ¾çvÒÿOøÆ×ÿÿSÁ¿Ô忉ôÿMâ?à(ã&øs]Áë$ßOø-€QoÖ=ÁŸí _%ù-„Ÿìgüÿþ…®äe’Ÿ$ü’o þ3þç‚?Óå¾Xò‘#â?à$ã!øé©íIÿáG£ñ—‚×CýHÿákiˆÿŒÿ•àŸëòºHÿOšÄÀÆÿZðÏsÅדö?ᇣñ7‚ÿµø†´ÿ ?¸œñÓ‚ÿÝý9iÿ¾ç[ˆÿŒÿ­à/Õßöÿ·$þN0þw‚Öýö?ᇣñ÷‚šžZ'ùaÂO®aüõ‚ºz‹ôÿ¾ï;ˆÿŒÿ_ÁoÓ½oþŸïHüœfüHyãkIÿáÇ£ñÁoÖ$þ~ñ÷ÿ?SA•î~Žôÿ|Oâ?à8ãë‚?W¯"ý?„ßõˆ]‚?O÷/'ý?„Ÿ\ÉøEÄŸðïd>J~ézˆÿŒßGð!?Γ|äˆø8Åø}ÿ}=5Gòƒ„ŒzÄÛþ³zèBɾû¿ÿ¿Ÿà7ëÞ’ÿÇßücôøtɯ üVÀ¨GÜ_ðê*Éo%ü.ÀŒ¿­àÏÑÝgI~á{€øÏøÛ þ Wø4ÉGŽˆÿ€»{Á¿Èå?Eò›? õˆ!øû¸R'I~”ð ÿÁ÷ºBc$9"þŽ2þŽ‚ŸÐ½e’ï'üÀ¨7Ïà¿§Ç‘üÂOö3þN‚ÿ=p¤ä' ¿Dë4ZgÁBw‘|äˆø8Éø»>Ü,ùÂF=â‚ÿ¢/&ã_Ó;ãï*øízÀGÚÿºä—Ž0þn‚ÿ¼žZFâ?ᇣñîäzñ(ý~p9ã ~\÷5Êü˜ |«Ó1þ‚?É•ÜWÚGŽˆÿ€Œ¿§àOw…%ãÿ ? õˆ÷üJWüaÉ~p ãü —ûA2þ‡ð}EF˜ñ÷ü .ÿS$ùÍ€ÓŒ¿àŸè }&ùÍ„ŒzÄû þWücÉ~qŸN£™ñ=äzwwI>rDügüýš+¾‚Ìÿ"ü6À¨G¼¿àOv¹Ÿ"ó¿?¸’ñüq.ÿdþá—öí4Úÿ—$þÄ‹Iüï+ùAÀ)Æÿ=_»’øOø1À¨G| àŸçòïDâ?á»·é4‚ŒàŸì ý‚Äÿm$¿pŒñK¿ÞïOâ?á·F=â_ þ%.÷6$þ~à ÆÿàÏt…’øOøÞ~F+ãLòiè2ÿ«Ÿä7îbüCª+þ™ÿEøQÀ¨G|¨àÏu¹¿!ó¿ß0:&Æ$øó]~‰ÿ†äûG0ã—¹Óý’þÂoŒz³ìÂþ—ÿ 2ÿ‹ð“€ýŒ?DðÇ»üï‘ù_„_Òâ?ã&øç¸BI2ÿ«?‰ÿ€“Œ?Tð/pÅß"ó¿?õˆüy.÷›dþákÛBügü#Èùõ¿FæmKâ?àã)ø ®ÐZ2ÿ‹ðC€Qø(Á?Éï$ó¿?¸œñK‰?îÈü/Â÷lñŸñ¦çëY2ÿk;ÿ'ÿ·‚_ç ­&ñŸð5¦GŒï,5Ïù [´P[¦þàœß>ñ19.óƒèK=¦MÓhîƒøû«Se°Á‡Zœ_‚sàÏbZ|ÏÂZ¶ßàœKïÑðŸ©Èû=3 ÚÀ98¯¼‚ø‹ËOæÍc«æf}ýƆ ;j.+ÒN—©+1°³³S²ƒ:7ÿ„q³êkg š23 Úàû<ØyûOuѬgåÑ…GÇ?Ž]nˆk;ÐãX;µÚá(Éãè¼ý§ºäsñØñ㈠WÉãÔX°*å8:lÿ©.¹ÇÉã3ma|OÊ)’3¹¾a†ý-$Vnð¡ó†öž2r9} sÿd÷Àþž‘ÎŽe÷µ œ_æO Lýš¿S$8¢³cì°[ëf™T‘ïhÇyåNÇlRŤê&‡w,Qn?¶^2®òáÛ[o€…¿ìsb1ã°Ø ÝqÇMƒÜ>ä{í}üHMûÒ7Þ3ŸÄ¾ÇùÔÇñ#GVÕÁ¿Yvßûh´ô¹nòÓóg¿ÙÍû ²½‡&³1»&ÛzïÞѬú¸)~{$¿E֙Ѭ§™u‚nÿüj/}láó¸ßmß8`Xæ:’×6þí#tvßR{ÁýÛÞ¹¿ɴ鳬g?—½Zðú@Óè#Ž-6ïg™¯SjgVm$#Y~U©r`F‡6ƒdmNq¼’~¼…—ËÆË‰ –{VýìþŽ¡µœÁ½Õròu³¾äû¢Þ<×0–ñ¸†óÞ0ÎI‹kƒ¼Þ!D[hqm¯e§<="x_AÇ5ÕÇ­+®ù÷ë4ûv\CùõÎ}ím\‹î§^ï|½â–Æ5,woãZrµœ|½âÆ2×pþ/m³Ñ¸vÑb\Ûÿñ?|\“>n]q-| ä˃ ;®¡üzç¾ö6®yR¯w¾^Hq ËFã–»·qÍW¢–“¯R\ÃXÆã¾ãœäȸ6”h 1®õý¨­àãšôqëŠkîC _ZØq }ä×;÷µ·q-xˆåþì‹kX6װܽk­‡ªåäë…×0–ñ¸†ïƒI•8ǵɶÐâÚ“ï–<]¹ð¦‚Žkª[W\ |yXaÇ5ô‘_ïÜ×ÞÆµäËýÙ‹kX6װܽkÚPµœ|½âÆ2×ð½Xç$GƵ#ˆ¶ãÚ¥U7|\“>n]q-~$äË£ ;®¡üzç¾ö6®ùŽ²ÜŸUxq ËFã–»·q­²Ôò|¤´ðâÆ2×ðý€á¡ÎqíH¢-ĸö‡C|\“>n]qÍ{,äËa…×ÐG~½s_{×ZµÜŸ[xq ËFã–»·q-:Ìò|dXáÅ5Œe<®á{R1ÎIŽŒkGmÁŵÖmŸ>·ÐïC·®¸*ƒ|9²°ãúȯwîkoãš6Òr6²ðâ–Æ5,woãšg”åùȨ‹kËÄøµ: Œs’#ãZ)Ñb\Ù~KÁÇ5éãÖ×Rc _–v\CÅøµòǯo¹?;¾ðâ–M¿6&‡ñkå–ç#å…×0–‰ñk'wñQÎqíh¢-ĸö+maÁÇ5éãÖ×üc!_Ž+츆>Šñkãr¿6Ör6¶ðâ–M¿66‡ñkã,ÏGÆ^\ÃX&ƯMì40ÎIŽˆkC¼D[hq­fñskþsÝm×T·®¸>òå„ÂŽk裿6!Çñk,÷g /®aÙ”ñk§ä0~m¢åùÈÄ‹kËÄøµÓ; Œs’#ãZ!Ï7À˜±Ãä¾U}ܺâš{2äËŠÂŽk裿V‘ãøµÉ–û³É…×°lÊøµÉ9Œ_«°<©(¼¸†±LŒ_;§ÓHMtŽk…<ßcÆÁûösÕÇ­+®΂|yvaÇ5ôQŒ_;;ÇñkgYîÏÎ*¼¸†eSƯ•Ãøµs,ÏGÎ)¼¸†±LŒ_›Öi`œ“× y¾Aøý׸WßQÐqMõqëŠkñ*È—S ;®¡büÚ”ǯM±ÜŸM)¼¸†eSƯUå0~mªåùÈÔ‹kËÄøµÚN#|Žs\+äù3¾øú΂kÒÇ­+®yσ|YSØq }ã×jr¿vžåþì¼Â‹kX6eüÚy9Œ_«±<©)¼¸†±LŒ_«ë40ÎIŽŒk…<ßcÆëß]ðqMú¸uŵРȗ3 ;®¡büÚÌǯʹܟÍ,¼¸†eSƯÍÈaüZåùH]áÅ5ŒebüZc§qNrd\+äùç>qÝšC–L,踦ú¸uŵԅ/gv\CÅøµY9Ž_k°ÜŸ5^\ò)ã×.ÌaüÚ,Ëó‘Y…×0–‰ñks;xs\+äù•ë¬ÙmÒ™×T·®¸æ¿òeSaÇ5ôQŒ_kÊqüÚE–û³‹ /®aÙ”ñkå0~­Éò|¤©ðâÆ21~m~§qNrd\+äù3üVðqMú¸uŵð<È——v\CÅøµKs¿v©åþìÒ‹kX6eüÚ¼Ưͷ<™_xq c™¿ve§qNrd\+äùuÿ\·zQó~×T·®¸æ¾òå…×ÐG1~íŠǯ]n¹?»¼ðâ–M¿vyã×®°<¹¢ðâÆ21~íÚN#5ß1®VÈó 0fLùüWפ[W\ \ù²¹°ãú(Ư5ç8~íËýÙ5…×°lÊøµkr¿v­åùȵ…×0–‰ñk7vç$GƵBžo€1cÿ >®I·®¸¿òå‚ÂŽk裿¶ Çñk ,÷g /®aÙ”ñk×ç0~íËó‘ /®a,ã×ní4Â×:ǵBžoà]úRtÉà3 :®©>n]qÍ{3äË[ ;®¡büÚ-9Ž_»ÙrvsáÅ5,›2~íæƯÝby>rKáÅ5ŒebüÚÆ9É‘q­çÄ/z"úîÔ©×T·®¸ºòeKaÇ5ôQŒ_kÉqüZ‹åþ¬¥ðâ–M¿v{ã×î°<¹£ðâÆ21~ížNãœäȸVÈó 0fìýÝ9פ[W\K-‚|ywaÇ5ôQŒ_»;ÇñkwYîÏî*¼¸†eSƯ-ÊaüÚÝ–ç#w^\ÃX&ƯÝ×iÄïpŽk…<ß`ÖkýF9~»‚Žkª[W\ó/†|¹¤°ãú(Ư-ÉqüÚbËýÙâ‹kX6eüÚâƯ-±<YRxq c™¿öçNãœäȸVÈó 0f¬ìXðqMúøì|U×ÿ H R¥HèB“Iv¨R¢JC¯B@º@"M:¥Hy ˆtdB ÙAH²IABa鈔ÿ=¸sgÎu—÷ÝkÄó>óßÏguçr3û;;s¿wOîïÜX‹köUl¾\M›k ‘û×VKú×V ùÙjz\ƒØm•„m°>²†×€eÜ¿¶1^Î} ®Q®7fÄÏCžk†FkqÍ›/¿¦Í5ÐÈýk_Kú×6ùÙz\ƒØmƒ„íka}äkz\–qÿÚ–xŵÆ3×(×|ñ…ªF7‹y~¯—kX£µ¸¾‰Í—›is 4rÿÚfIÿÚ&!?ÛDkò¯m’ð¯mÖG¶Ðã°Œû×vÄ+À9£Á5ÊõÀŒ<Ã4ò\34Z‹kÎml¾ÜN›k ‘û×¶Kú×¶ ùÙvz\ƒØm›„-FX‰¡Ç5`÷¯íWì[œk5(×lê¶1¸yëŸHs k´×\·Ø|y‡6×@#÷¯Ý‘ô¯Ýò³Ûô¸±!ÿÚ- ÿÚa}ä=®˸ía¼â¼á™k”ë Ú%NNjrŠ4×°Fkq-ô›/§Í5ÐÈýk¿Kú×ùÙz\ƒØí„íwa}äwz\–qÿÚÓx8gô1¸F¹Þ vN¿à›‹&Í5¬ÑZ\³?fóåÚ\Ü¿öDÒ¿öDÈÏžÐãĆük%ükO…õ‘§ô¸,ãþµŒ pÎècpr½A¯›Ö~@škX£µ¸æŸ!A |)4×@#÷¯¹µúì_Ë€ó3÷1%®AlÈ¿Æ4úì_{ Ç©Sâ°Œûײ&(®§ž¹F¹Þ cÞ Ž9is k´×Â6_f¡Í5ÐÈýkY世ªàñ®SâĆükŠï\óËŠãÔ)q XÆýkþ pÎècpt½Á–oû~¡Í5¬ÑZ\sfgóeÚ\Ü¿–CŽkA9ðx×)q bCþµì¾s-,'ŽS?¦Ä5`÷¯åMPìY=sr½ÁŠC9´V=n’æÖh-®æfóeÚ\Ü¿–GŽkѹ…ü,7=®AlÈ¿–Ûw®ÅæÁqêÇ”¸,ãþµ‚ pÎècpr½ÁëÕýµ7?¹EškX£µ¸U€Í—¯ÒæhäþµW叿÷ªŸ½Jkò¯ðkqœú1%®˸- AÎ} ®Q®7Ø!§qè6i®aÖâš«›/‹Òæhäþµ¢r\ {MÈÏ^£Ç5ˆ ù׊øÎµÈ¢ÂúHQz\–qÿZ©ÅYÐ3×(×ü\¤¾¶¢ìUÒ\íŵÐl¾,I›k ‘û×JÊq-¶„Ÿ• Ç5ˆ ù×JøÎµÔ’ÂúHIz\–qÿZù8gôá\«I¹ÞÀ>¯®Öv)m®aÖâš½,›/ËÑæhäþµrr\ ('ägåèq bCþµ²¾s-¨¼°>Rž×€eÜ¿˜ çŒ>×(×|䪭Õýñi®aÖâše6_V¡Í5ÐÈýkU$ýk•…ü¬2=®AlÈ¿VY¿VEX©BkÀ2î_«™ ¸Ê{æåzƒbEzkÿ™µž4×°Fkq-¼:›/kÐæhäþµ’þµêB~V× 6ä_«.á_«)¬Ô¤Ç5`÷¯ÕKP€sFƒk”ë ¶Ìé­Ùg®%Í5¬ÑZ\sÖfóeÚ\Ü¿VGÒ¿VGÈÏêÐãĆükµ%üku…õ‘ºô¸,ãþµ Å^Ó3×H׬é­uß¹š4×°Fkq-°!›/ÑæhäþµF’þµ†B~Ö× 6ä_k(á_k$¬4¢Ç5`÷¯5NP€sF[ŸžC†ôí)\j\ËÜ¡ƒVeÀ¤¹†5Z‹kQ66_ª´¹¹M•ô¯©B~¦㽻Ǒôâ|}Dük6 ÿZca}¤1=®˸í8gôѹV90дp@kO[•ÒìžEškX£µ¸æjÆæË´¹¹­…¤­¹Ÿ5§Ç5ˆ ùךIø×Zë#-èq XÆýk¡ г±®™¨qmë®’Z×ôsHs k´×B[³ù² m®Fî_k#é_k-äg­éq bCþµÖþµ6ÂúHz\–qÿZ»8gô1qÍ´p@k“¯”ÐF›KškX£µ¸f›Í—mis 4rÿZ[IÿZ[!?kKkò¯½-á_k'¬´£Ç5`÷¯uJP€sF×L Ô¸Ö8¹¸Ö*êSÒ\íÅ5ÿl¾ìH›k ‘û×:Jú×:ùYz\ƒØ­ƒ„­£°>Ò‘×€eÜ¿– ¸Úyáši£"j\[»¼y®aÖâZx6_¾O›k ‘û×Þ—ô¯uò³.ô¸±!ÿZ ÿZ˜°>FkÀ2î_ë• çŒ>&®™6*¢Æµ •Šiq+iç¡X£µ¸æìÎæË´¹¹­‡¤­‡Ÿõ Ç5ˆ ù׺Kø×z ë#=éq XÆýký{˜®™6*¢Æµ/3»×þ‡4×°Fkq-°/›/ûÑæhäþµ~’þµ¾B~Ö—× 6ä_ë+á_ë'¬ô£Ç5`÷¯…'(À9£‰k¦Š¨qínõ[Žï»,%Í5¬ÑZ\‹ÈæËA´¹¹m¤mŸ ¢Ç5ˆ ù×Jø×Â…õ‘pz\–qÿÚð8gô1qÍ´Q5®Uøôy®aÖâšëC6_£Í5ÐÈýkÃ$ýkC…ül(=®AlÈ¿ö¡„m˜°>2Œ×€eÜ¿öQ‚â ÷̵ª¦Š¨qmƒãžãΗKHs k´×BG±ùr4m®Fî_-é_%äg£èq bCþµQþµÑÂúÈhz\–qÿZd‚œ3ú˜¸F¸Þ {ŸŽŸ‹Hs k´×ìãØ|A›k ‘û×"$ýkB~Akò¯“ð¯E ë#‘ô¸,ãþµÉ pÎècâázƒ/¦ýîØ1}!i®aÖâšÿD6_N¢Í5ÐÈýk“$ýk…ül"=®AlÈ¿6Q¿6IX™DkÀ2î_›ž ¸"½pp½AÉöËâ¦e®DškX£µ¸>•Í—Óhs 4rÿÚ4IÿÚT!?›Jkò¯M•ð¯MÖG¦Óã°Œû׿$(À9£‰k„ë N^—<§*i®aÖâšs›/gÓæhäþµÙ’þµÙB~6›× 6ä_›%á_‹ÖG¢èq XÆýkóût/\#\oйîü¸'µj’æÖh-®~ÆæËy´¹¹mž¤í3!?ûŒ× 6ä_ûL¿6OX™GkÀ2î_[œ çŒ>&®®7h;rfÜÚ ¯“æÖh-®E}ÎæËE´¹¹m‘¤m‘Ÿ-¢Ç5ˆ ù×>—ð¯-ÖGÓã°Œû×–%(À9£‰k„ë Æü1<×°FkqÍõ6_FÓæhäþµhIÿÚB~ö=®AlÈ¿ö ÿZ´°>MkÀ2î_[™ 8{áázƒ–í"ã>;Yƒ4×°Fkq-t›/¿¢Í5ÐÈýk_Iú×VùÙ z\ƒØm…„í+a}ä+z\–qÿÚº8gô1qp½Az¥—íÇéÕIs k´×ìkØ|¹–6×@#÷¯­•ô¯­ò³µô¸±!ÿÚ ÿÚ:a}d=®˸í›8gô1¸Vp½Á•=l7ºÐ^7À­Å5ÿl¾´Óæhäþ5»¤m£Ÿm¤Ç5ˆ ù×6Jø×ìÂúˆ×€eÜ¿¶5Aq­óÂ5ÂõㆿOžkX£µ¸¾…Í—ßÒæhäþµo%ýk[„ül =®AlÈ¿¶E¿¶UXÙJkÀ2î_Û• çŒ>&®®7·“Íö+í<k´ל1l¾ÜA›k ‘û×vHú×vùÙz\ƒØ-F¿¶SXÙIkÀ2î_Û— Ø·záázƒGޱ巒æÖh-®îeóe,m®Fî_‹•ô¯íò³½ô¸±!ÿÚ^ ÿZ¬°>KkÀ2î_; çŒ>&®®7˜ÿI;[âö ¤¹†5Z‹kQ›/÷Óæhäþµý’þµýB~¶Ÿ× 6ä_Ó$ük„õ‘ô¸,ãþµ# pÎècâázƒþûlÝ*%Í5¬ÑZ\sbóåaÚ\Ü¿vXÒ¿ö½Ÿ}Okò¯’ð¯ÖGÓã°Œû×’ç/\#\o°¶Zœmí·%Hs k´×BÙ|é¤Í5ÐÈýkNIÿZ¢Ÿ%ÒãĆük‰þ5§°>â¤Ç5`÷¯OP€sF××dýÁa;Þ© i®aÖâšý(›/Ñæhäþµc’þµcB~vŒ× 6ä_;*á_;.¬§Ç5`÷¯JP€sF××ÌÈ|À6>©,i®aÖâšÿI6_þD›k ‘û×~’ô¯ò³“ô¸±!ÿÚI ÿÚOÂúÈOô¸,ãþµ³ Šë¸®®7ˆëu<×°Fkq-ü ›/Sis 4rÿZª¤팟¡Ç5ˆ ù×ÎHø×Î ë#géq XÆýk¿$(À9£Áµê„ë ü–²-r•×€eÜ¿v3AÎ}L\#\oPãaNuaÚûy`ÖâZÔ 6_ºhs 4rÿšKÒ¿æò3=®AlÈ¿vC¿vSX¹IkÀ2î_»Ÿ çŒ>&®®7Xø}ò\íÅ5×6_Þ£Í5ÐÈýk÷$ýkw…üì.=®AlÈ¿vG¿vOX¹GkÀ2î_{” 8ozáázƒw7eW¯­¢‡bÖâZèC6_þA›k ‘û×þô¯=ò³‡ô¸±!ÿÚC ÿÚÂúÈô¸,ãþµt‰ pÎècâázƒ²©ÙÔØtUHs k´×ìOÙ|é—Hšk ‘û×ÜZ}ö¯¹ŽçgîcJ\ƒØí©„-ŽS?¦Ä5`÷¯eNT€sF××üÜ:›:rDyÒ\íÅ5ÿŒl¾ÌD›k ‘û×2Éq-2#ïú1%®AlÈ¿Æ4úì_Ë„ãÔ)q XÆýkÙWºDÏ\#\o°.¤¦Úâq.Ò\íŵð¬l¾|™6×@#÷¯½,ǵԬx¼ëÇ”¸±!ÿZVß¹æ— Ç©Sâ°Œû×^IT€sF××ÜM©©Îý$i®aÖâš3'›/ýis 4rÿš¿ׂü…üÌŸ× 6ä_Ëé;×Ârá8õcJ\–qÿZþDÅžÍ ××”Zùºº§RAÒ\íŵÀ¼l¾ÌG›k ‘û×òÉq-:¯Ÿå¥Ç5ˆ ù×òúεØ|8Ný˜×€eÜ¿V8QÎ} ®Õ \oÐsO-µß—…Hs k´×¢ ²ù²m®Fî_+$Ç5¿BB~Vˆ× 6ä_+è;× ë#…éq XÆýkÅàœÑÇÄ5Âõé®×&Ï5¬ÑZ\seóe1Ú\Ü¿VLŽkaB~@kò¯õk‘Å„õ‘bô¸,ãþµ2‰Š³°®®7¨ðR]uÝÂ"¤¹†5Z‹k¡¥Ø|Yš6×@#÷¯•–ãZl)!?+Ekò¯•òk©¥…õ‘Òô¸,ãþµŠ‰ pÎècâázƒËG~ );ê(i®aÖâš½<›/+Ðæhäþµ ’þµ B~V× 6ä_+ï;ׂ* ë#éq XÆýkÕàœÑÇÄ5ÂõÛKÙÜíi®aÖâš ›/«Òæhäþµª’þµ@!? ¤Ç5ˆ ù×%ükU…õ‘ªô¸,ãþµZ‰Š«¢®®78±æy®aÖâZxM6_¾N›k ‘û×^—ô¯Õò³šô¸±!ÿZM ÿZ-a}¤=®˸­A¢œ3ú˜¸F¸ÞàÄ/ŽÓ«hç¡X£µ¸æ¬ËæËz´¹¹­ž¤­žŸÕ£Ç5ˆ ù×êJø×ê ë#õéq XÆýk!‰Š½–®®7x·ýîïŽ&“æÖh-®±ù2˜6×@#÷¯Kúׂ„ü,ˆ× 6ä_ ’ð¯ ë#Áô¸,ãþµ¦‰ pÎècâázåÈö/g;Is k´×¢³ù² m®Fî_k"é_k"ägMèq bCþµÆþµ¦ÂúHSz\–qÿZ«D8gô1qp½Á× ·Çm,ýi®aÖâš«›/[Òæhäþµ–’þµ7„üì z\ƒØ­…„­¥°>Ò’×€eÜ¿öV¢âlê™k5 ×tÙ²9.¥ÿ¤¹†5Z‹k¡¡l¾|“6×@#÷¯½)é_ ò³Pz\ƒØ-T¿ö¦°>ò&=®˸íD8gô1qp½ÁÏÅ7ÄýÚð'Ò\íÅ5{;6_¶§Í5ÐÈýkí%ýkí…ü¬==®AlÈ¿ÖN¿öް>ò=®˸í½D8gô1qp½ÁÏa+âöþNœkH£µ¸æß‰Í—is 4rÿZgIÿZ'!?ëDkò¯u’ð¯uÖG:Óã°Œû׺%*®w¼pp½Á“ó‹Ès k´×ÂÃØ|Ù•6×@#÷¯u•ô¯… ùY=®AlÈ¿&á_ë&¬t£Ç5`÷¯õIT€sF××$4XWß6×°FkqÍÙ“Í—½hs 4rÿZ/IÿZ/!?ëEkò¯õ”ð¯õÖGzÓã°Œû×>HTìݼpp½A¥#}[ß'Í5¬ÑZ\ ìÏæË´¹¹m€¤­¿Ÿõ§Ç5ˆ ù×úKø×ë#èq XÆýkCàœÑÇÄ5Âõ×vÜ©õ€4×°Fkq-*œÍ—ƒis 4rÿÚ`IÿÚ`!?Lkò¯…Kø×†ë#Cèq XÆýk#àœÑÇÄ5Âõßö Ï5¬ÑZ\s cóåÚ\Ü¿6BÒ¿6\ÈφÓãĆükÃ$ük#„õ‘ô¸,ãþµ±‰Šsˆ®®7èxñcÇkciç¡X£µ¸ú›/ÇÐæhäþµ1’þµ„üì#z\ƒØí# ÿÚa}d =®˸m|¢œ3ú˜¸F¸Þ`ÇÔ eí]Ò\íÅ5{$›/?¦Í5ÐÈýkKú×>ò³éq bCþµH ÿÚxa}d<=®˸mJ¢œ3ú\{p½AëõzÜ&Í5¬ÑZ\óŸÌæËOhs 4rÿÚ'’þµÉB~6™× 6ä_›,á_ûDXù„×€eÜ¿63Qq÷Â5Âõ‰û i'⯑æÖh-®…Ogóå Ú\Ü¿6CÒ¿6]ÈϦÓãĆükÓ%ük3…õ‘™ô¸,ãþµOàœÑÇÄ5Âõ“jÒ½rƒ4×°FkqÍÅæË9´¹¹mޤmŽŸÍ¡Ç5ˆ ù×¢$üks…õ‘¹ô¸,ãþµ…‰Š}¦®®7h×­ öÊ%i®aÖâZà|6_. Í5ÐÈýk $ýkó…ül>=®AlÈ¿6_¿¶@XY@kÀ2î_[š¨çŒ>&®®7ÈÛâUírôMÒ\íŵ¨Ål¾\B›k ‘û×–Hú×–ùÙz\ƒØm±„m©°>²”×€eÜ¿öe¢œ3ú˜¸F¸Þ`TÁ乆5Z‹k®h6_.§Í5ÐÈýkË%ýkË„ül=®AlÈ¿-á_[.¬,§Ç5`÷¯­NTœK½pp½Áæ¯òkïm£‡bÖâZèJ6_®¢Í5ÐÈýk«$ýk+…ül%=®AlÈ¿¶R¿¶JXYEkÀ2îóXŸ¨çŒ>¶aC†÷¬Xý¬Îµt~iû¨½<Åç{ß¾.Q xíIñ#Ãö>¿ç¿Ë5¬‘×þ¼~˜k™ý$¹.7®¥²kOyµiϵ¿U¾÷­cnfû:clÂCçè6sC=v¶õž›{Öc.Òž¨ÀÔûºÇœ­ïîzâóý#c.tïc.|c¢2}pµdë¥AÏïùïŽ9¬‘Ƙûó‘Vß%¼¹hvüí´Æ\è×1ÊÁM1|ÌÁ}íâ˜íŸýýGÚƒƒ{v(ß!á>‚v=vî¥ßjʱv%*0^üxŸæÝ{vÒ³ëøÜÔæ‰_´c‹hÿÍ_¬ñ¿q|<ÇK¿ƒåî;i}ßÓü;Ø“—~§¤—~‡ð»âƘëëq$½¸÷jì¼ô;$¼ô;¯ÆN#ÎðÿÅ÷ÖòÁóØ]&/ý¾DŵÕ×ðÜOkñ§{k·Ž~NškX£µ¸¾7Q‰Š¥Í5ÐȽô±’^ú½ÂïŠ÷Òãüô{%¼ôû¯Æ>z\–q/ýw,¯ßå…k„½ôã®öÒÚºæÖh-®956_î§Í5ÐȽôû%½ôû/ý~z\ƒØ—^“ðÒ¼èq XƽôGû>/\#ì¥øµy®aÖâZà÷l¾&®öÒß+ã¨Óx2i®aÖâšë(›/Óæhä~ã’^úcB~vŒ× 6ä¥?*á¥?.¬§Ç5`÷ÒŸJTœI^¸FØKÿn£mŽÅaIs k´×BO²ùò'Ú\ÜKÿ“¤—þ¤Ÿ¤Ç5ˆ yéOJxéÖG~¢Ç5`÷AMT€sF×ïÝÿêØnŽùª’æÖh-®Ùϰù2•6×@#ß 6Ur/ØT!?K¥Ç5ˆ í{Fb/سÂúÈYz\–qÿÚ/‰ pÎècâá½ûÛ5éå˜w¦i®aÖâšÿE6_^¢Í5ÐÈýk—$ýk…üì"=®AlÈ¿vQ¿vIX¹DkÀ2î_»–¨¸Îzáá½ûÓž Ùzº)i®aÖâZø6_^¥Í5ÐÈýkW%ýkW„üì =®AlÈ¿vE¿vMX¹FkÀ2î_»•¨çŒ>תÞ»tÜ¥ÑyTÒ\íÅ5ç 6_ºhs 4rÿšKÒ¿æò3=®AlÈ¿vC¿vSX¹IkÀ2î_»Ÿ¨Ø¯yáázƒ·~¹c;Õ 7i®aÖâZà]6_Þ£Í5ÐÈýk÷$ýkw…üì.=®AlÈ¿vW¿vOX¹GkÀ2î_{”¨çŒ>&®®7Ø’þ¶­@æü¤¹†5Z‹kQÙ|ùm®Fî_ûCÒ¿ö‡ŸýAkò¯=”ð¯=ÖGÑã°Œû×Ò;àœÑÇÄ5Âõ!Ô·Ïç Í5¬ÑZ\s=eóe:'i®Fî_skõÙ¿æçÄù™û˜× 6ä_{*á_K‡ãÔ)q XÆýk™Šó‘®®7˜S¤˜š¿àˤ¹†5Z‹k¡Ù|™‰6×@#÷¯e’ãZlF<ÞõcJ\ƒØiôÙ¿– Ç©Sâ°Œûײ9àœÑÇÄ5ÂõÁ‹Z©Ó\9BžßëßåÖh-®Ù³²ùòeÚ\Ü¿ö²×^Æã]?¦Ä5ˆ ùײúε l8Ný˜×€eÜ¿öŠSÎ}L\#\opkUKutÞ×Hs k´×üýÙ|™‹6×@#÷¯å’ãZ¤¿ŸùÓãĆükþ¾s-:ŽS?¦Ä5`÷¯åw*®l^¸F¸Þ Y¹ÚÞ6óHç¡X£µ¸ž—Í—ùhs 4rÿZ>9®¥æò³¼ô¸±!ÿZ^ß¹æ—Ç©Sâ°Œû׊8àœÑÇÄ5Âõ…–÷Ôr_ Í5¬ÑZ\sdóe!Ú\Ü¿VHŽkA…„ü¬=®AlÈ¿VÐw®…ÖG Óã°Œû׊;{~/\#\oP¼q5mÕûQ¤¹†5Z‹kl¾,F›k ‘û׊Éq-:@ÈÏèq bCþµß¹[LX)FkÀ2î_+ãT€sFƒkÕ×´9¨½}x6i®aÖâZT)6_–¦Í5ÐÈýk¥å¸æWZÈÏJÓãĆük¥|çZ@a}¤ =®˸­’SÎ}L\#\o0iVuírÿ¹¤¹†5Z‹k®òl¾¬H›k ‘û×*Jú×*ùYz\ƒØ­¼ï\‹¬(¬T¤Ç5`÷¯Us*Î2^¸F¸Þàhd mrèg¤¹†5Z‹k¡l¾¬J›k ‘ûתJú×…ü,× 6ä_ ”ð¯UÖGªÒã°Œû×j9àœÑÇÄ5Âõ—ßâø²ÌxÒ\íÅ5{M6_¾N›k ‘û×^—ô¯½.äg¯ÓãĆük5%ükµ„õ‘Zô¸,ãþµN8gô1qp½ÁùÆ›m‘¤¹†5Z‹kþõØ|YŸ6×@#÷¯Õ—ô¯Õò³zô¸±!ÿZ= ÿZ}a}¤>=®˸-Ä©¸jyáázƒûÖ;RÕHs k´׃Ø|L›k ‘ûׂ%ýkAB~Dkò¯Iø×B„õ‘z\–qÿZ3§œ3ú˜¸F¸Þ ÈæŽ)Œ!Í5¬ÑZ\s6fóeÚ\Ü¿ÖDÒ¿ÖDÈÏšÐãĆük%ükM…õ‘¦ô¸,ãþµVNÅâ…k„ë ziìõi!Ò\íŵÀ7Ø|Ù’6×@#÷¯µ”ô¯½!ägoÐãĆükoHø×Z ë#-éq XÆýko9àœÑÇÄ5Êõ¿6r$õ+HškX£µ¸ÊæË7is 4rÿÚ›’þµ7…üìMz\ƒØ-T¿ö–°>ò=®˸í]§œ3ú˜¸F¸ÞàöÍŽ?Ö%Í5¬ÑZ\sµcóå;´¹¹íIÿZ{!?kOkò¯µ“ð¯½#¬¼CkÀ2î_{Ï©8ßò̵ê„ë ªìlí¨5¬i®aÖâZh'6_v¦Í5ÐÈýk%ýk„ü¬=®AlÈ¿ÖI¿ÖYXéLkÀ2î_ëæT€sF××ϱ4¤S™ö¤¹†5Z‹kö06_v¥Í5ÐÈýk]%ýk]…ü¬+=®AlÈ¿&á_ë&¬t£Ç5`÷¯õq*À9£‰k„ë E¯)Úå-Ò\íÅ5ÿ^l¾ìM›k ‘û×zKú×z ùY/z\ƒØ­—„­·°>Ò›×€eÜ¿öSquóÂ5Âõ-6í¹[¸i®aÖâZx6_ Í5ÐÈýk$ýký…ü¬?=®AlÈ¿Ö_¿ö°>ò=®˸íC§œ3ú˜¸F¸Þ`ÓÕ¯C–6nMškX£µ¸æ góå`Ú\Ü¿6XÒ¿6XÈÏÓãĆükáþµ!ÂúÈz\–qÿÚH§bÿÀ ××ìýŠíõK´× °Fkq-p8›/GÐæhäþµ’þµáB~6œ× 6ä_.á_!¬Œ Ç5`÷¯u*À9£‰k„ë 2u)`›µ»8i®aÖâZÔGl¾C›k ‘ûׯHúׯùÙz\ƒØí# ÿÚXa}d,=®˸m‚SÎ}L\#\oP¹]vÛö'eHs k´×\‘l¾O›k ‘ûׯKú×>ò³éq bCþµH ÿÚxa}d<=®˸mŠSqŽõÂ5Âõ·¦g±Ýù®i®aÖâZèd6_~B›k ‘û×>‘ô¯Mò³Éô¸±!ÿÚd ÿÚ'ÂúÈ'ô¸,ãþµ™N8gô1qp½AíÏ—Û®ÌIškX£µ¸fŸÎæË´¹¹m†¤m†ŸÍ Ç5ˆ ùצKø×f ë#3éq XÆýkŸ:àœÑÇàZ ÂõÇÇ®°ÙŸÒþ{ïX£µ¸æ?‡Í—sis 4rÿÚ\IÿÚ!?›Ckò¯Í‘ð¯ÍÖGæÒã°Œû×:×L/\#\o’~­mòžL¤¹†5Z‹káóÙ|¹€6×@#÷¯-ô¯Íò³ùô¸±!ÿÚ| ÿÚBa}d!=®˸í?N8gô1qp½ÁÿU¶Ê¿d&Í5¬ÑZ\s.fóåÚ\Ü¿¶DÒ¿¶DÈÏ–ÐãĆük‹%ükK…õ‘¥ô¸,ãþµ/Š}¡®®7ðkùÐv®ìÓçwúw¹†5Z‹kËØ|¹œ6×@#÷¯-—ô¯-ò³eô¸±!ÿÚ2 ÿÚra}d9=®˸mµSÎ}L\#\o°²ÁcÛÜ‘æÖh-®E­dóå*Ú\Ü¿¶JÒ¿¶JÈÏVÑãĆük+%ük«…õ‘Õô¸,ãþµ¯ pÎècâázƒº1÷m·×g ‡bÖâšk›/7Ðæhäþµ ’þµõB~¶ž× 6ä_['á_Û ¬l Ç5`÷¯mv*ÎÕ^¸F¸Þ`ÉÑ»¶*Éÿ~ i´×B¿aóå&Ú\Ü¿¶IÒ¿öŸ}Ckò¯}#á_Û$¬l¢Ç5`÷¯mw*À9£‰k„ë îç/¡NÊž4×°Fkq;•Í—Ûhs 4rÿÚ6IÿÚ6!?ÛFkò¯m•ð¯mÖG¶Óã°Œû×ö8àœÑÇÄ5ÂõM²–Tç ¥ýû5¬ÑZ\óßÅæËÝ´¹¹m·¤m—Ÿí¢Ç5ˆ ù×vIø×v ë#»éq XÆýk§âÚî…k„ë Æ)­6¸u“4×°Fkq-|›/ãhs 4rÿZœ¤mŸŸí£Ç5ˆ ù×öIø×Âúˆƒ×€eÜ¿vÈ©çŒ>×j®7Xóv)u¦íi®aÖâšó›/¿£Í5ÐÈýkßIú×¾ò³ïèq bCþµþµƒÂúÈAz\–qÿZ‚S±;¼pp½AjÌ[êŒúK‚ŸßëßåÖh-®aóeOkÀ2î_Kq*À9£‰k„ë 6Wk«¶¼?—4×°Fkq-*‰Í—É´¹¹-YÒ¿–,ägÉô¸±!ÿZ’„-EXI¡Ç5`÷¯ýèT€sF×׌ S]â·›4×°FkqÍuœÍ—'hs 4rÿÚ IÿÚB~ö=®AlÈ¿v\¿vBX9AkÀ2î_ûÙ©8S¼pp½Aåq¡jd‹ŸHs k´×BO±ùò4m®Fî_;-é_;%äg§èq bCþµSþµÓÂúÈiz\–qÿÚy§œ3ú˜¸F¸Þ  h6õËfSHû×°FkqÍ~–Í—çhs 4rÿÚ9IÿÚ9!?;Gkò¯•ð¯ÖGÎÓã°Œû×~u*À9£‰k„ë æÊ®fì1™4×°FkqÍÿ6_^¦Í5ÐÈýk—%ýk¿ùÙ/ô¸±!ÿÚ/þµËÂúÈez\–qÿÚu§â:ï…k„ë V¤äTÃHs k´ׯ±ùò7Ú\Ü¿ö›¤횟]£Ç5ˆ ù×®Iø×® ë#×éq XÆýkwœ pÎècâázƒäŽ9T퉤¹†5Z‹kΛl¾¼E›k ‘û×nIú×n ùÙ-z\ƒØí¦„í¶°>r›×€eÜ¿ö»S±_÷Â5Âõ'ë§Ú¢¢Is k´×ï³ùòm®Fî_{ é_»/äg÷éq bCþµûþµÂúÈz\–qÿÚ§œ3ú\{p½Á¸Êçmõg|AškX£µ¸õˆÍ—is 4rÿÚcIÿÚc!?{Lkò¯=’ð¯=ÖGžÐã°Œû×^JR€sF××¼²ö´-©ârÒ\íÅ5Wº$Å?Ci®Fî_skõÙ¿–> çgîcJ\ƒØÅí³-ŽS?¦Ä5`÷¯eIRœO¼pp½Áðý?ÙåZAškX£µ¸š™Í— m®Fî_S丛wý˜× 6ä_Ëì;×R§~L‰kÀ2î_Ë‘¤çŒ>&®®7È~y‹mo@ i®aÖâš=›/³Óæhäþµìr\ ÈŽÇ»~L‰kò¯eókA9pœú1%®˸-O’œ3ú˜¸F¸Þ`Í‘­¶bõ·‘æÖh-®ù¿ÂæËÜ´¹¹-·×"_ò³Wèq bCþµW|çZtn§~L‰kÀ2î_{5IqåðÂ5ÂõyßÜe›±x i®aÖâZx~6_ Í5ÐÈýk世š_ÈÏòÓãĆükù}çšß«8Ný˜×€eÜ¿V4IÎ}L\#\o0øý[j•oIs k´ל…Ù|Y„6×@#÷¯‘ãZP!?+Bkò¯öka¯ ë#¯Ñã°Œû×J&)öW½pp½Á+³{Ù¢gÒÎC±Fkq-°8›/KÐæhäþµr\‹..ägÅéq bCþµâ¾s-¶„°>R‚×€eÜ¿V.IÎ}L\#\oÐqÈ[Ëß·’æÖh-®E•aóeYÚ\Ü¿VVŽk~e…ü¬,=®AlÈ¿VÆw®”ÖGÊÑã°Œûת$)À9£‰k„ë Æ÷íj;û9íõP¬ÑZ\sUdóeeÚ\Ü¿VYÒ¿VIÈÏ*ÑãĆük%ük•…õ‘Êô¸,ãþµIгœg®Õ"\oÐ"ú=[ĸ¤¹†5Z‹k¡ÕØ|Y6×@#÷¯U—ô¯Uò³jô¸±!ÿZ5 ÿZua}¤:=®˸­N’œ3ú˜¸F¸ÞàtÁAÚ×gãHs k´×ìµØ|Y›6×@#÷¯Õ–ô¯Õò³Úô¸±!ÿZ- ÿZa}¤=®˸­Q’œ3ú˜¸F¸Þàìûhmü¤¹†5Z‹kþ Ø|Ù6×@#÷¯5”ô¯5ò³ô¸±!ÿZ ÿZCa}¤!=®˸MMR\u¼pp½:¼¿Ö"íïkX£µ¸ÂæKm®Fî_³Iú×B„ü,„× 6ä_ ‘ð¯©ÂúˆJkÀ2î_k‘¤çŒ>&®®7˜V ŸV¶ m®aÖâš³)›/›Ñæhäþµf’þµfB~ÖŒ× 6ä_k*á_k.¬4§Ç5`÷¯µIR쪮®7¨2£–¾á>Ò\íŵÀVl¾lM›k ‘û×ZKú×Z ùY+z\ƒØ­•„­µ°>Òš×€eÜ¿Ö6IÎ}L\#\o°}zoíÁÁ½¤¹†5Z‹kQo±ùòmÚ\Ü¿ö¶¤ím!?{›× 6ä_{K¿ÖVXiKkÀ2î_똤çŒ>&®®78ÓK[wo7i®aÖâšë6_v Í5ÐÈýk$ýkï ùÙ»ô¸±!ÿÚ;þµÂúHz\–qÿÚûIг­®®7ø:_/môBÚþ5¬ÑZ\ }Í—]hs 4rÿZIÿÚ{B~ö=®AlÈ¿öž„­‹°>Ò…×€eÜ¿Ö#IÎ}L\#\oðý´žZóº´ë °FkqÍÞÍ—Ýis 4rÿZwIÿZw!?ëNkò¯u“ð¯õÖGzÐã°Œû×ú%)À9£ÁµÚ„ë ;{h·nÑÞÏk´×üû°ù²/m®Fî_ë+é_ë#äg}èq bCþµ>þµ¾ÂúH_z\–é\‹þ Iqõ0s­UÏûT ¬ŠVçZ:¿´}5=êó½Î4Tà®mYGÚgkü/äZ@ºtÞ¸ö÷iÏ5%(FYÍž06áf†ûÚõØõñc‚ç3áI Œ?ÞÇ=>ªásÿSãã`oßÇGløÿ2«çØJø¸||À}íâø€1¡ ¡IJôÆGu|îj|ôYàûøðúÿLJÌÃêãÃÞ}§þÆN>>à>‚vq|À˜à>ÚÑìûU¸y|´Òu`ïžâ¹©å£;´Ó~úéñ5þŽ?ïycØÆÝQ´óFШçS‘#åòFçœOéÇpÎAGÒ‹{èqBlzœpM n_óF×H§~L!oÔã„ØÌù1ÄÝmÐÀaþ?ožó¸ïYîÍm°25"I úWVŠÙ(5V~ÒéGYõÖsY91"²¡þôðÏ‘žÊ;+=çymX£µX86I  ÍJÐȽ¹ã$½¹c…ß=¥ÇJˆ¯ý²kqûìÍ'¬ýŽ£ÇJˆ ­ýŽó•K"0+¼îtR’ìÔûšXYM8)V.^rÙQ9ÿҬĭÅJ¿ lžD›• Q[åX>3D?¦ÄJˆMóÙ5™à;+£&â8õcJ¬„ØÌ¬„¸}eå€I˜•ÀG•‘Ó“”Ô¬¬.œ+ûG\vôÈ|4+±Fk±Ò9…ÍÁÓi³4òZÖ©’µ¬S¯ÆTz¬„ظWš]ˆÛçZÖi‚Wz=VBlÈ+=ÕwVÖŸŽY |ä>—9IŠ}’GVÖÎGŠ•¯nþűèþ}ҬĭÅÊèYlŽ¢ÍJШ­ØÙr¬ôŸ¢Sb%Ä¦Ç ×âö••Q8Ný˜+!63+!n_Y™mf%ðQgeÀ‚$%rºGVÖÎGŠ•¶Ç7üNš•X£µXþ›ƒçÓf%hä{?Í“Üûé3¡¶á3z¬„Øxm1»&·Ï{?Íj‹çÓc%Ćj‹çùÎÊSó1+ÜGµ$I ã‘•¯ ç#ÅÊFqçÒýAš•X£µX´ˆÍÁKh³4êc+l±+í‹0CôcJ¬„Øøz?»&·¯¬t.ÖûÓc%Äff%Äí++×/Á¬>ꬌ]ž¤;õ¾&VÖÎGŠ•©ÛÎ8št§ÍJ¬ÑZ¬ôfsðrÚ¬¼Öd™d­I´PkM•_ïg×âö¹Öd™°Þ¿Œ+!6´×2ßY9f9f%ð‘:Iq-ñÈÊÚÂùH±2>ÇiGÃõ´Y‰5Z‹•©_±9x5mV‚F>¶Vɱ2t%fˆ~L‰•_ïg×âö••á«„õþUôX ±™Y qûÊÊ–«1+:+þNRb—{deá|¤X™·æIG”F›•X£µXi_Çæà ´Y ùÞ ë%÷fX/ìͰž+!6¾ÞÏ® ÄíóÞ „õþ ôX ±¡½«×ûÎÊÂ_cVù¾ƒ[’”¨ÕžXY5P8)V¶[ñƒãÚ§´Y‰5Z‹•‘ß°9x3mV‚F^ϲIŽ•®o„z–oè±bãëýìš@ܾ²Ò³°Þ¿™+!63+!n_Yym3f%ðQg¥ßŽ$%ìk¬$]·3/÷1ǪÑf%Öh-V†ncsp mV‚F^ϲ]r/ÃmB=Ë6z¬„Øøz?»&·Ï{nÖû·Óc%ĆþÖÓvßY¹+³øÈ÷éß›¤;õ¾&V’®Û³9ÙñuôCҬĭÅÊ€ÝlÞK›• ‘׳ì‘ceÔn¡že7=VBl|½Ÿ]ˆÛWVÚ÷ëý{è±b3³âö••3öbVùÞdûÙ¿íðÈJÒu;™':}îÑöWbÖb¥+ŽÍÁûi³4òzMŽ•a¡žÅA•_ïg×âöyïMXï×è±bC{Kj¾³²ó~ÌJà#ÿ»v‡“ç^¬$]·3éR‚ãÄ•¤Y‰5Z‹•±Ù=u˜6+A#¯g9$ÇÊÀCB=Ë!z¬„Ø8CØ5¸}eeè÷Âzÿ÷ôX ±™Y qûÊÊŠ‡1+|Ϥ$%z¿GV’®ÛÉÐ<ÞÑì íG¬ÑZ¬ŒJ`s°“6+A#¯gI”c¥_¢PÏ’H•_ïg×âöùoå9…õ~'=VBlèo1$úÎÊGNÌJà#ß¿ò‡$%ü°GV’®Û)ZêˆcÏ4Ú{g`ÖbeØQ6§ÍJÐÈëYŽÉ±ÒyT¨g9J•_ïg×âöyÿÊcÂzÿ1z¬„ØÐþ•Ç$ö¯<ŽY |äûWžJR€z_+I×í”9uØ1+ã]ҬĭÅÊÀ“l>E›• ‘׳ü$ÇÊè“B=ËIz¬„Øøz?»&·ÏûWþ$¬÷ÿD•Ú¿ò'‰ý+OaVùþ•ç’`§Þ×ÄJÚu;ÙŽ8Â"o“f%Öh-Vú¥²9ømV‚F^ÏrVŽ•á©B=K*=VBl|½®IªÄþ•g…õþ³ôX ±¡ý+ÏJì_y³øÈ÷¯¼œ¤¤žòÈJÒu;g×;]Ë/#ÍJ¬ÑZ¬t^dsðeÚ¬¼žå’+ƒ. õ,—è±bãëýìš@Ü>ï_ù‹°Þÿ =VBlhÿÊKûW^Ƭ>òý+¯')ösžXYtÝNÛÏÎ…ÜÚÕ4+±Fk±2ú*›ƒ£ÍJÐÈëY®É±ÒÿšPÏr+!6¾ÞÏ® Äíóþ•¿ ëý¿Ñc%Ćö¯¼&±åuÌJà#ß¿òN’yÙ#+I×íœé{ÃöCÏš¤Y‰5Z‹•á7Ù|›6+A#¯g¹%ÇÊÔ›B=ËMz¬„Øøz?»&·ÏûWÞÖûoÓc%Ćö¯¼%±åmÌJà#ß¿ò÷$%ôºGV’®Û™¼£…Ú4<iVbÖbeÐ}6ÿN›• ‘׳ï_é¾gùþ•ì˜ï_ùr²ûÔ#+I×íŒkö®zäÜҬĭÅJ»Âæà¬´Y y=K9VdÁ Ñ)±bãëýìš@Ü>ï_™Ç©Sb%Ćö¯Ìâ;+ ¿ŒY |äûWæJV¢L󿉕¤ëv®je«Ò*‰ôï+±Fk±22›ƒýi³4òz–œr¬tåÀ Ñ)±bãëýìš@Ü>ï_éãÔ)±bCûWæô•×ü1+|ÿÊüÉJØËYIºn'hM€­Î²þ¤Y‰5Z‹•¡yØœ6+A#¯gÉ+ÇÊØ<˜!ú1%VBl|½Ÿ]ˆÛçý+óâ8õcJ¬„ØÐþ•y}gå®|˜•ÀG¾eádØ©÷5±’tÝN£è¶ñm;“f%Öh-VdspaÚ¬¼ž¥+£ b†èÇ”X ±ñõ~vM nŸ÷¯,„ãÔ)±bCûWò•3 cVùþ•ÅÙ¿å÷ÈJÒu;#®¿eÛ4´iVbÖb¥«(›ƒ‹Óf%häõ,ÅäX€¢Sb%ÄÆ×ûÙ5¸}Þ¿²ŽS?¦ÄJˆ í_YÌwVv.ŽY |äûW–MVœ…=±²:éºE_ϱ}Ÿ®/iVbÖbel)vO•¥ÍJÐÈëYJ˱2°4fˆ~L‰•g»&·ÏûW–ÖûËÐc%Ćö¯,í;++–Ŭ>òý++'+ÑÅ=²’tÝÎ\ÇÍuO$iVbÖbeT6W¢ÍJÐÈëY*ʱү"fˆ~L‰•_ïg×âöyÿÊJÂz%z¬„ØÐþ•}gå£J˜•ÀG¾ed%¼¬GV’®Û¹å÷$$t2mVbÖbeXU6W§ÍJÐÈëYªÉ±ÒY3D?¦ÄJˆ¯÷³kqû¼e5a½¿=VBlhÿÊj¾³òHuÌJà#ß¿²N²ìÔûšXIºnçó=™m—wEf%Öh-VÖbspÚ¬¼ž¥¶+£ka†èÇ”X ±ñõ~vM nŸ÷¯¬-¬÷צÇJˆ í_YÛwV.©ƒY |äûW6JV€z_+I×íŒzœÍ6s,iVbÖb¥_67¢ÍJÐÈëYʱ2¼PÏÒ€+!6¾Þפ﬌j(¬÷7¤ÇJˆ í_ÙÐwVh„Y |äûW6NVRëxd%éºàõ¯ØúìIš•X£µXé aspcÚ¬¼žÅ&ÇÊ ›PÏb£ÇJˆ¯÷³kqû¼¥*¬÷«ôX ±¡ý+m¾³²~cÌJà#ß¿òdÅÞÈ#+I×íüX÷UÛ»ï%ÍJ¬ÑZ¬ŒnÆæà´Y y=Ks9Vú7êYšÓc%ÄÆ×ûÙ5¸}Þ¿²…°Þß‚+!6´esßY™í ÌJà#ß¿òÍd%²±GV’®Û)°­¼-uNҬĭÅÊðÖl¥ÍJÐÈëYÚȱ2µµPÏÒš+!6¾ÞÏ® Äíóþ•¡Âz(=VBlhÿÊ6¾³òT(f%ð‘ï_Ù>Y }Ã#+I×íÔVÝæ¬Öƒ4+±Fk±2¨-›ƒÛÓf%häõ,íäXio+Ô³´¥ÇJˆ¯÷³kqû¼e;a½¿=VBlhÿÊv¾³r}{ÌJà#ß¿²s²ìÔûšXIºn'²xM™Ø…4+±Fk±Ò¿#›ƒ;Óf%häõ,äXÙQ¨géH•_ïg×âöyÿÊNÂz'z¬„ØÐþ•|gå˜Î˜•ÀG¾e·dÅÕÞ+k®ÛY°¾yVbÖbeêûlîF›• ‘­®r¬ êYÂè±bãëýìš@Ü>ï_ÙUXïïJ•Ú¿²«Äþ•Ý0+|ÿÊ>ÉJlg¬$]·s¦C[ا]I³k´+í=ÙÜ›6+A#¯gé%ÇÊ€^B=K/z¬„Øøz?»&·ÏûWöÖû{Óc%Ćö¯ì%±eÌJà#ß¿r`²ÕÍ#+I×í4Z0Ԕ܋4+±Fk±2²?›ƒ? ÍJÐÈëYȱÒÕ_¨géO•_ïg×âöyÿÊ„õþè±bCûWØ¿òÌJà#ß¿rh²ÖÇ#+I×í$Þ‰ ¿Ž5Z‹•¡ƒÙü!mV‚F^Ï2DŽ•±ƒ…z–ÁôX ±ñõ~vM nŸ÷¯"¬÷¡ÇJˆ í_9DbÿÊ1+|ÿÊQÉ °Sïkb%麦u&Ù"ߤý÷Á±Fk±2`›ƒGÑf%häõ,#åX5B¨gA•_ïg×âöyÿÊ‘ÂzÿHz¬„ØÐþ•#%ö¯…Y |äûWF°ê‘•¤ëvî¿3ÝÖgmVbÖb¥k ›ƒ#h³4òz–qr¬ +Ô³Œ¥ÇJˆ¯÷³kqû¼å8a½=VBlhÿÊqûWF`Vùþ•“’ç(¬$]·S{ñ„Ç“f%Öh-VÆŽg÷Ô$Ú¬¼že‚+'õ,è±bã a×âöyÿʉÂzÿDz¬„ØÐþ•$ö¯œ„Y |äûWNOV¢#<²’tÝÎêZŸ…Lh0‘4+±Fk±2j ›ƒ§Ñf%häõ,SåXé7U¨g™J•_ïg×âöyÿÊiÂzÿ4z¬„ØÐþ•S%ö¯œ†Y |äûWÎIVÂ'yd%éº)® yÿ"mVbÖbeØ,6GÑf%häõ,³åXéœ%Գ̢ÇJˆ¯÷³kqû¼åla½6=VBlhÿÊÙûWFaVùþ•ó“`§Þ×ÄJÒu;rn'ÿ½k´+?csð|Ú¬¼žež+£?êY>£ÇJˆ¯÷³kqû¼åòý+—$+ÀN½¯ÁÊš¤ëvÊVÚ²ù½ ¤Y‰5Z‹•~‹Ø¼„6+A#¯gY,ÇÊðEB=Ë"z¬„Øøz?\“EûW.ÖûÓc%Ćö¯\,±åÌJà#ß¿ry²’:ß#+I×í<Èr4äðo´×v°Fk±Òù›ƒ—Óf%häõ,Ñr¬ ŠêY¢é±bãëýìš@Ü>ï_¹LXï_F•Ú¿2ZbÿÊ嘕ÀG¾åêdžÄ#+I×í<Èt.äìÄY‰4Z‹•Ñ_±9xmV‚F^ϲRŽ•þ+…z–•ôX ±ñõ~vM nŸ÷¯\%¬÷¯¢ÇJˆ í_¹RbÿÊÕ˜•ÀG¾¶³>Y‰\nfe耮ÿzuV¦ûË¿ü½GXñc>§ðuÉJí¡ê¦kužËʲ¯¯h˜ù|ˆðÿéù§¼³ÒÓyàüžÞþ5þ7²2]:¯¬dמòj Vð÷H;VÂ;Îïz;¼%èF{0°ÇÐÿÐÁ:a`½©þcc²ºú/c®r``Uñ|dÆ\ ÓœÿíÖjã H9¬ÑZc.Œ]#xÊ«ýçÇ\àFÏctÿÝ17c£PG°Ñ´GÔf–ç®÷4æ^ÏGf̹6%+ÁÃ[ªËì!¤ÇÖh­1Àî+xÊ«ýçÇÜGp,Ž9ÐýwÇ\ËÍÂ^C›Myø¶dŹÑÓ˜«%žÌ˜³oMV¾«Ø\íµ¼ é1‡5ZkÌ¥²kOyµi?æ´ŽQ¶‰Qô1gßêyÌî¿;æ²mò¹m¦|ng²µÙÓ˜«-žÌ˜ ßÁ¾·ÄµWëœ*HzÌaÖsÑìÁS^í ÈçvxÉçv¤A>·CÈçvšò¹=,ŸÛæiÌÕÏGfÌ2Í™æ¶S÷‹’sX£µÆ\»Fð”Wûò¹=^ò¹=iÏíò¹=¦|.Žås;=Œ¹ªâùÈŒ9×¾dEYÔV}mLiÒck´Ö˜ `÷<åÕ¾€|nŸ—|.. ò¹8!Ÿ‹3åsX>·ÇÓ˜{1¿·Ïò¹žÆ\uñ|dÆ\ Ó<üHgµ@TfÒck´Ö˜ cמòjÓ~Ì-ŒQÂŒß[Æ{ÉçâÓ Ÿ‹ò¹xS>—Äò¹ï=¹âùÈŒ9—3Yw°‹:fWzÒck´Ö˜ `÷<åÕ¦ý˜»|8F‰=bŒ9¸ ý/ù\RäsIB>—dÊ玱|.ÞÓ˜«)žÌ˜³MVŽ S&= y^¿{ÌaÖs©ìÁS^mÚ¹ÚßÇ(þ‡MësG½äsGÓ Ÿ;&äsÇLùÜ,ŸKò4æ^ŒE*Ÿ;‘¬äµwWgκDzÌaÖsÑìÁS^mÚ¹)c”°CƘ ?á%Ÿ;‘ùÜ !ŸûÑ”ÏbùÜ1OcîÅøP¤ò9¦ùj`/õö…ŸH9¬ÑZc.Œ]#xÊ«Mû1wâ@ŒbÿΔÏò’ÏJƒ|î”Ï2ås©,ŸûÑÓ˜{1>©|îL²R*}õÐ/I¤ÇÖh­1Àî+xÊ«Mû1WvŒâwÀ”Ïñ’Ï¥¦A>—*äs©¦|îËçNys/Ƈ"•ÏOVÊ%õUßÿúé1‡5ZkÌ¥²kOyµi?æF:b”PÍ”Ï÷’ÏOƒ|î‚Ï]0ås—Y>—êaÌU{1>©|î—deüöþêíi±¤ÇÖh­1Í®<åÕ¦ý˜;¸/F‰Ž3ås¿xÉç~Iƒ|î!Ÿ»lÊ箲|î‚§1÷bÖ ¤ü–LóË¥ßVm[Ë“^+À­5æÂØ5‚§¼Ú´súƒçsW½äsWÓ Ÿ»*äsWMùÜ –Ï]ö4æ^ÌZ”ßòz²R⇷T¥b é1‡5Zk̰û žòjÿù1÷ÿ%Ÿ»‘ùÜ !Ÿ»aÊçn³|1G·fÕ~+Y¹;æ-uJÁš¤ÇÖh­1—Ê®<åÕþócÎ~ËK>w+ ò¹ÛB>wÛ”ÏÝgùÜ OcŽîï-Ãï%+~ëªnÊpƒt>‡5ZkÌE³kOyµi?æ"7Æ(ïÚMùÜ=/ùܽ4Èçî ùÜ}S>÷ås·=¹ó{ËùÓüEõ®êàùž;Ïý×)ÒûÏx;öm|`ÖsaìÁS^mdšï×Vv]Œrpi}î¡—|îá_Ç\¯ACzöòüMÎP>÷PÈçšò¹',Ÿ»ïaÌU1¿·”s®ÇÉJÎ]ÔEž_?7¥ãéFúÓÃ?Gzþ)ïcÎÓyž×†5Zk̰û žòjÓ~Ì]^£LYkZŸ{ì%Ÿ{ò÷Ç\Ë'B>÷ĔϥOQœ=¹S?'3æìéR”R7;¨Gß©OzžÃ­5æRÙ5‚§¼Ú´s«WÇ(ÍÖ˜ÖçÜúþ’ϱö¿;æ²¥OÁù;æù\¦%ꉧ1÷bÖ dÆ\xFv=ûôR.OGzÌaÖsÑìÁS^mÚ¹èõ1ÊÈ ¦|.£ç1ºÿî˜;’9g<ŸË’¢„¦Oñ0æ^ÌZT>Ç4¿\¬“ºòD5Òck´Ö˜ cמòjÓ~̽Û(F©½Ò”Ïeñ<æ@÷ßÎç²à1ãŒçsÙSƒz_c̽˜µ©|.[ŠòMDgUù²âsÇ܈ß5ÒŸþ9ÒóOysžÎó¼6¬ÑZc.€ÝWð”W›öc®@Ãe{CS>—Íó˜Ý;ŸËŽÇŒ3žÏåbù\OcîÅÔHåsþ)ÊòÔ÷Õš# ‘žç°Fk¹Tvà)¯6íÇ܉úì»eS>çï%ŸóOƒ|.—Ïå2åsyY>—ÝÓ˜{1ësRù\žeöänêˆ9H9¬ÑZc.š]#xÊ«Mû1×laŒry¡)ŸËã%ŸË“ù\!ŸËkÊç °|.—§1Gx}Ži.б‡úNa…ô˜Ã­5æÂØ5‚§¼Ú´s‘c”Õ Lù\/ù\4Èç ù\S>W˜åsy=Œ¹„÷·,”¢ì¸õŽ:ýÓ¼¤½_X£µÆ\»¯à)¯6òŸ÷[ò’Ïþë˜óÙoYXÈç c.µ(Ëç ˜Ç\“A‡z<ß?2æü+HäsLs×&Õ"n=wÌEm™¬?=üs¤çŸò>æ<çymX£µÆÜßüùÜJ–Ï­2åsEñ˜ã¯½¨1>K°Ü«°y|Øúé>à/,îŸïÖ>ê;·˜æà*UÕ‡Ž÷HÄÿ ÇGÀÿ­ñQ¶UŒr°•1>à>‚ÿ‰ãÆÿ}`é%µ¨ðmTÏ!â¹õñAåQ²üp­s™ïH¬ñ¿p|ðŸû¿1>ôÿ]icØ+¤(%Ìãàí={þõ‹µqóô{Ú¢µ)¤ÇÖh­q^Ž}ÿ(Oë÷úCÏQ@£ž£èZ}ýûË©åþü9ýïëÇpÎ=ޤ÷Ðã„ØÌ¹Äíëß_ö«€ãÔáœÿöß_Ö¹,ãkUSàœÑç×¼þÝV*Z¡=µÂ¿ï&Í5¬ÑZ\sVNQ\Uhs 4êã]×ê+ׂªàñ®SâÄfæÄí+×Âqœú1%®Ët®…¿ž¢Ø+xâšç¿1Aå7·žöeŽí¤¹†5Z‹k5Ø|Y“6×@£>Þu­¾r-ºïú1%®Alf®Aܾr-¶&ŽS?¦Ä5`_·®—¢çŒ>:×<ÿ*²}ýµòk“æÖh-®EÕaóe]Ú\úx×µúÊ5¿ºB~V—× 63× n_¹PÇ©Sâ°Œ¯Ã§(À9£Î5Ï5MTGëwh'—“æÖh-®¹²ù2ˆ6×@£>Þu­¾r-¬‘Ÿ5¢Ç5ˆÍÌ5ˆÛW®Eá8õcJ\–qÏS“ÅYÏ×<×Qyœ˜° äåt}Is k´×BU6_6¦Í5Шw]«¯\‹U…üL¥Ç5ˆÍÌ5ˆÛW®¥6ÖGÓã°Lçšë8gôѹæ¹6ÊcÚ¶¥¶=Q!¤¹†5Z‹köæl¾lA›k QïºV_¹ÐBÈÏZÐãÄfæÄí+ׂÞÖGÞ Ç5`÷;½™¢çŒ>:×<×?Ryd¹yÁ¶éi Ò\íÅ5ÿ6l¾ ¥Í5Шw]«¯\‹l#ägmèq b3s âö•kÑ¡ÂúH(=®˸­}ŠâzÃ×<טRy4ÈZPÍ0úù{ÿÛ\íŵð¶l¾lG›k ‘û×ÚIú×Ú ùY[z\ƒØ­­„­½°>Òž×€eÜ¿Ö9EÎ}t®y®ã¥òÈßÚ¦ÖOö'Í5¬ÑZ\sv`óeGÚ\Ü¿ÖQÒ¿ÖQÈÏ:ÒãĆük$ük„õ‘Nô¸,ãþµ®)н½®Uõ\+Må1¸[e­ÚdzHs k´×ßgóem®Fî_ “ô¯½/ägïÓãĆükïKø×„õ‘0z\–qÿZ¯8gôѹF»ÞàìÌ—´açæÖh-®Eõ`óeOÚ\Ü¿ÖSÒ¿ÖSÈÏzÒãĆük=$ük½„õ‘^ô¸,ãþµ) pÎè£sv½A˔ʎ¯¾*HškX£µ¸æêËæËþ´¹¹­¿¤­ŸŸõ£Ç5ˆ ù×úJø×ú ë#ýéq XÆýkƒSg/O\£]oïQEÛÊeHs k´×B±ù2œ6×@#÷¯…Kú× ùÙ z\ƒØm„-\X §Ç5`÷¯ OQ€sFk´ë ì7ì¶32“æÖh-®Ù‡²ùrm®Fî_&é_&ägÃèq bCþµ¡þµáÂúÈpz\–qÿÚ˜8gôѹF»Þ É"?µYØÕç÷úw¹†5Z‹kþ£Ù|ùm®Fî_ûHÒ¿6ZÈÏFÓãĆük£%ük ë#Ñã°Œû×>NQ\Ã=qv½AÀÏåÔÏO^"Í5¬ÑZ\ `óe$m®Fî_‹”ô¯EùY=®AlÈ¿!á_ûXXù˜×€e:×àœ3úè\£]oP°M?Uù|Nðó{ý»\íÅ5çD6_N¢Í5ÐÈýk“$ýk“„ül=®AlÈ¿6Q¿6YX™L‡k­Ø[Ï„ø’¢”pkz0ß{­‚›õ0à¯?ûW¨é÷—ù~ózï }ÿ|¤e#ãßÌèFøÿöOÏÆb5?¿LüÒ=ûÐÓ1UÙþTö¿Ð€®ü{üß=FŸýÿÏבÒ)éüþúøóœ—§¤(áS}¯{,Âî©wÙÿACA¿?¯_:­ìsS”té…yö/Ÿ‡·ëöçgÈ®ICó{A¬žÞ«ìü´{/ý¾„{Q¿/Sg¤(pŸêgnܼû_6û÷ó¿Uø}Z&SCÏïIð¾L÷—¤ïKçôåÝÿî} <Ý+~óÒþ¾„X=½×‰OÓþ¾„{Q¿/ÎNQÌÌ„ûrTÓ!]?ü¿czAA¢ëÈÿûòÙ#mîËí³R” Ùÿî} ^/!Öu_½¨ß—ðHa¾/CtÚkÐð;âûR|oâ÷eò2zNŠRvî¿{_‚†u_B¬ÿô<Þ¶±Ÿß#·þ¢î÷‚ûÞ|æ¶›WþpPß•»}îgÚ»ÜPÉÎäý~|ö¾A>ÿ§û5úñ{>£Ÿâ‡/øŸ?ŸGÓÈ`÷O}ýµù:˜-Þ§ûEÿ<à3Ð?˜ í¦û>¾Ý{íþìáC ÝÏ㲿ÜçŸþyÀýg¾GÜŸþ0ÐûÒý<¦ä”û<à3à÷<æáÏ£7|½xö‰Ûýÿ_¸?ÊæðíóhÅ>ƒìÿ¡ R”@÷¹j/òÓÆ­z~Øç/öÀðú}ó—÷l¶±>Ú8ÏHvµäùì7psö, ¾GÓiõSo ‚—΃‚‡H ò0O>{¼Ææ´tnÚêË ´èç‚üÚ/gøSSM÷ûÖ *¹o¥_à^þ¾‘éŸ6Œ-¾¯yȦFF›ßÓ}]_Û÷Ò•ƒÌm×ÚçßwËÚ®&eßðÝW¨í×—Òï Øvµ•P/Dz'jc}bYß`ÔöÝW±ìœ¨½g,{oÔÆ´Å2¨Å°—Å‚ÚüþŒYì×H챊çƒXÅ÷…XE}«Ä*Æ }ÄÏÎ%~~ðžâç ÚÄë1ˆ×mê’Á¹z63]ß Oƒ"]{w¾Œôm_ºjWÉ·l¨ímÛÕFb?µ}¿Øâcë¡¶øm½ƒÄ¶ßBÖŶÎ_ µmº½&Hl›~ötl•î¥P[èÜSAbÛô Lûv|™¿ÇÂŒÁb[J«BûÎÊ€Új®,,¶­?Vi_µ"§Ðç—£r¥`±­Ø¼ûVÝ€Ú&üV?XlkԼžÜ{†¡¶åËš‹my7¾½o̬,¨mD淃Ŷ :ì‹ÛÙÐÜ–óÔ»Áb›ºýÝ}á«“öméŸÞÉÞ18°yF4¦aì`cX¤óæÙ¿=ûoñgÿ t¿†¶ô¦×•Ý}¡-ƒ»^Wt·CÛKîvx]ÞÝmÝí𺬻Ú2¹Ûáuiw;´ev·Ãë’îvhSÜ홹Ú?Û²¸Ûáu€»Ú²ºÛáõkîvh{Ùݯ »Û¡-›»^¿ên‡¶ìîvx]ÐÝm9Üíðº»ÚrºÛáuw;´ù»ÛáuQw;´år·Ãëbîvh{ÅݯK¸Û¡-·»^—r·C[w;¼.ãn‡¶¼îvx]ÎÝmùÜí𺂻Úò»Ûáu%w;´p·Ãë*îvh«ên•>¾.ì~]>ÅŸý¿ˆû5üûkî×EøgRüY[€ûuQþ™ÖVÜýºÿLŠ?k+é~]‚&ÅŸµ•v¿.Å?“âÏÚʺ_—áŸIñgmåݯËñϤø³¶Šî×øgRüY[e÷ëJü3)þ¬MGULŸŒ¿T6˜à»AU÷g÷”~¿ýùÙe|v?é÷Z!wôÑï×WÝmpé÷^wôÑï÷Âî6¸ßô{±¨» úèãå5wÜú½YÌÝ}ôñànƒûQ¿WK¸Û >^‹»ÛàþÔïÝRî¶L~~|¼—t·ÁýªßËeÜmÐGçEiwÜ¿ú½]ÎÝ}tÞ”u·Áý¬ßëÜmÐGçUywÜßú½_ÉÝ}tÞUt·Áý®…*î6ýû_ Ÿ~d~v=õ±ñç5ÏοcÂ÷Jý;&ümWøÎé>…ñ—„ñ÷ˆž÷í_¾;~™¢ŒÌjüØ0v¼:ùùß1;±à¾dXsÓ/eà=‚ÎçÛ§ehÿÌ—;cØxõë]l¾|Ç-ú¹ô«ü©©¦û}¿½0XËlOæþä§~OÕ¦]©›m‘z[ýyª¹1ÄÜQl¤Öëø!ÔïLÇ’ê°©§Q¿üÚ(mÖڨߓ™-µSÊô¾íëÖüŠîGmÞ­6ÔPÛñ£µ÷f:PÛÃã´Ó§âÐ{lJÞc,jË»n¤V²%î7·a5µÖÒt¨­Ô„áÚÄ|¸ßÊKZïôSÑû®]ÜD5ËŽÚ~ÿhgˆöq Ô–îj+µÏQg°ù|ûæ†kŒÃï1 *³úi¦{!æŸÝ³ÅO=“=µ ~š1¸ßµ¶è=f½Õ^«ødê×`Huëðr¨ßÞëÚ¸V±¨ß´×ûjÍr~úžtÓ±¹ÒBÔ¯s½Õ¶¦ÝŸ¢ëÖâLN­ÎõY¨Ÿ-[_íi®%è|·zõ×"Ú,Cýꣵl´õk~/BU4õ»Ø¤V=x!ê×(w¸ºâÚ#4~›žËª~Ö-?ê×qzo­ùÊù¨í“>~ê¼£8ò9{iö¥óP¿Ð¬yÔ=«¢¶ ;=µÉŸ¡¶ÔóÔðx'ºníöÐ"TÜ/Ðùž6{Ít[âÅîZÕ;Ÿ¢~]ºS <ŒBçkT¦›6îî×ä›\Z¡³Qè|±["öùwlŠÚÎd¨«–oUýl¶Yïk£±¾2?±¹Ž½Ž~6ðDõÜ‘FHKÝßÚ;¾.›õk}¤³V¹2þœO§¬Ž~'úÙkKh‡£1³Kuª,w.ØÜ6æVm鵨߄<ÚÕ†˜‰áƒÔm;î™Û†ì¦Þíû1zßïε×rß]„~vJÂ2ÛøÏï ~ïMqÜ(Óõ[1¶ˆ}ûBmÉkÞÖ‚ò}Úv=É£ZS}Ã^/iK}õû¬ÏmÛfíwtÿµ™ÛR žðÝÏçÚT{Ò¤/óÞæÚ²_£óý0´µv~ž»?)^G}ûtN̺°ÿ„ÜߌÚRâsªîTBšßµ½«w?dnûLi©Õk…ß÷¡j£©ôÙ/ ÌnK_,ê÷ýžæÚòÑ›ðw‹qI¶—êVGïÛw@nµNfâ ¨=Ž5ó"Q[ŽƒM´zÊVÌöS7lÕ6dBç»Ý$P+Þfê7_ ÖNoÛˆÚûTm_áí¨m[ójjå/®£Ï¾L\ˆÖgy î×±Z¿[etÝrW Ö2ÞÆý”M=´zñœ2õ^#íÒ,ÜoÇmivÜïڤÿ`}üÕ™J¢¶Uã¾²-¯˜}?ÔÍ®ÅîÂÌ9ós}­Qüù-½ãè^p4j»Ü»˜:í—$ôÌžrÞöð²è=ZT©§=Zù þ\^ž7g.¾–žTQå¹îûËÕ¨ÌÐç—ntíä7ø~^i¨ÚäÆ&¤eJ±o¿EˆßÃõ•-Ϭ˨Ÿí«êÑU Ñ{|¿°–vòì<Ï\ªf»öúÙoFhE¾ÁÌ9ñé×6{%?ô ž÷–š°±;z;«kjûšá9ùÊËcl!=ªâ1˜ïÛÉñåQ[¹S´û~Ÿây5¡º6Ï…çŠôéµ ÓÓP¿6gNشɯ£~±~vDÄáxsä­¦ë2sc|­ïÃÙøûÁÍ@-2Ç ÔVH‰Ô¾*¸µÍ=XE»˜‚µüq¹‹ºëÈ‚ ³–L_TÖ¶¼‰ûm`ßYï§Ã÷é¸q•´?ZOÃß›šöÓnÕÀZÞjRQ[W÷»Ÿ¾«¶çžgVe© •©‚û-þ¹©öàæÁƒå´ö“q¿õé*k2`–ì¼^F;>p:êw9ä‚ã½ùKQ¿«u°‰Æ×£JÀ&ÛÕ{x¬®íSJ[Õm&jksé©ãj_|vÚO¾ÞÝk—ö•Voÿ†¿Ó´ÊVB›¹y6:ŸúÀ6®òAtŸ®ý]\æëyñ÷ûj¨‘)%ƒÌmyÚÕ®¯ÆßA.žh¨Þ²áï\£¯—Tg”Ú‡Þcz©ƒ¶;£ áÏå‹tjÞê}¡°V1;þñã¦/mcCýο›êÑÎßÕ®i[=:j«õIA-ã•è|s2•Ö.´ùÿìÇ/©ã üŠ>¿øvÕ´Ùó'¡~! h;rŽ¿OÎv”ÉûþN“pÔVîRMÔïî°ƒŽ×íøžl¹8Ÿ–¿'>ßÄ…AÚÅoð\[7C^­v+Üo[ð%ÇøŽø3¸¾½Ÿê÷ÍÖ½æ¶,µoìÅc:õñ+Zžaø;õ·öWÕJsàïuLJªæ.CŸ}â”ôŽCŸgEýÞÏKûù6¾najV5gƒ—Q¿ÛçÔ­o¡ÏùÍÙ}µáÕ·àóçÔøáïã ¶üd[|ª ê÷ñõ?ÇZâïÀM½¬<ŽïƒïçÖÞì6µ¹–dÓÆ'ÎÁßÑ?ª¯¾Wç5|¡U鎿±¯å9Û°ã…Q[ÍëYµlé1Ÿç;Bm7šãœs÷ÈÚˆ,»QÛ‚ÙB:Ä”@m§ŠeÑV/™…ÎW½N~­í[x^È}ê’­N|ê—¾ÇuhÝtÝæ6ˬ¼ŠùòsÇß§öàïÅóõÑ.äÅ|žâ´EäÁŸý;]3j]ý±¾†O3j_<Æc«áÂ[îÞ8ÿ-]¢¹mf¬¹_~´ry1¯nÅÖSùãkÙÓuʾê×àAœcY÷‰¨ßˆé´ô.|=Þ®¬¨ e3£¶öG³«UßÄ×èn½~ÚÈikQÛ̵O_Áüû­ÍT[É·k¡~C×5U¿ù¡/ºÇgv_m»P캿O}è(6™kUrª&ÃñÖoáX”µ½÷jsõØ”ôï^o¤–[‘ßWÍî8ü;,FïÑ{\OÕíDŸý­‘7÷NŠiƒ¿S/Ë« «‹ïµÇÍ]ŽáAÿAç[Z;Õ¶þcœ÷̯4@{üÃgèg?½^W-ØçQþE¯9¾HŠÆsh!%¤ÚºŽ¨ßòeµ<1‹GÊå˜÷NfÔæHwÙ‘uírÌÝNmÕŸýj¢ù²Væ ¶§¯`-{œïª¿oEŸË¯/:€ײrÀk!'Óa}3Ÿw¬Áý¶¹šª½lÅÑ5ã¬#Ý ÜoÍíqZóßðïTó9ã¨ûî‘i€–53ìVàiGÈ1ï—åµ* ï÷8éÈ»lž§¿žmÛûjMÔO¹ÐPmq/þ.¿¶¦z6ì%üýoýqG»ÊøwF«¶öÕ²íÆyEÓw2©.ã\wyÌ)Ÿ‡¢~/eHqìOgÔ~ÀLÛþåø÷믆ª¯w‰®å´±ÍâN½¿Swk™è8Ù Ïoš«ïdB×#än^uI]œÿÞü´½šúYŸXs¿y‚ÕãßIOOÿ£å$<¯*ÚOÛ~çj_½•N½òî ô”é×Bõ|ýÎã ×`õø—‹¾t¡ùÔ£©˜MuÇOŸÐß÷ÛZ~ŽßcЮ}ŽîÃñ÷Ø&™üÔQÇ÷ ÷¨´(›úÅxþ(p-—º9 ÿîkYÛÝŽ«'£¶ðÎÛm³‚ý–/»uTmËŸyqx¿lõ×Û^~„ù—øívÇ¢Ðù:t=d]µ5ž`Öm=þýøƒ]%Ô~ ÷£~OvÕùäãwQ¿MãTu͙ɨŸkÁ[§§wQ[Û[eÕ×vâïÔ1í¿p¬¯Ûé[Ü]kRnj̓<݇©[Dç«Ü¢¿ÖeÃNô³³¯ß³e‡¿ÿZ©„š£ìyÔ–ãç#¶?G?{/`càÚ÷q>ÓôGÛÝø÷ò=ò×Qÿ(_õË8¨‘6¦ÓÌ&¥—ú{Ý hìßÞ3Ûqåa;ô³[Ößuä/‹óîÑAWl¿·ÀyÊ]×6[k¼ŽóM—ÆZÑcxý( —·#ê¡~ÝŠ}âÚª9:_ÕÖ¹ÔÊëñï<Ò/ë§}×wjËÑ8@]Zç$:_ö6EÔ¶%³¢ó•ˆm m¿Œ¿ƒ Ë£^™€¿'ÆÎ«¤ÆÜMDç+›'܉Çoëþ Ô²«ñï"/ÿþv+3¾w—µW—­Ê>çOžØîÞÀùeóÖÿ±¾–½Ç¬U´§³qžÜõÉ`õ‘úºÿ÷Üh‹ytiîæÈ9¡4:_áWl¶N%  ó5kYTÍ–ÿþå?ÃÚ:ª·.ŠÚ”¸ ê !×}§Ìhí{ûœ3…4T'üWzHkê¨ÜëUt¾B{j©+¿ÇùŒkFí‡øûs¿:CÔ;½Bñ<3¶®#WaüYÝßÞ_›Ùç.ý78úÝÂßáN–t<*‘®CÔã·{ad-çP»¾‚ú}Ó|¸væT:_bÍ×7òã~%. S—Å÷Dç+2á¤mÔyœÃž~3§£àX¬å@‹sކspš<¦‘:ªTüýo×!?Or¦\~ŽV{ó¡óµ_Á±·^&Ôo˱Æj“Ý]¾ÆÑm[VáÜ Xݳqïo*„Îw¾ßÉà¼Sñ÷µŸïÔw̸‡×Õ 4îªN+¸2Èü³_5‹›‘»8GWZ«[Z”E÷³3cquzµ+xþ½”É6°¾wÝùe\âÿ£ì,À¥ª¢öæ—îîîîž3÷ÝÝÝÒ-Hww‡t+‚ *ÍAQP BDEÂÿ¼÷œÅ~×¹ßó=ÿOŸ‡ùÍ{÷ÙgŸk¯]gê5¹±*„Æ=ÓÏû÷›UƒÍ³é|9·isìÑJº¯–kv\æwu;O=xFlïÚÚ¯û¹ðäðůt;ÿé^–`Ǥ%Ôµy7׉ë9¢¶Ò^»Ò+Øã÷¿O«øî|ZžsНôõOb2fÒë°%{Ô^z¤×žæ7mLöã8•÷ŠÃ?Ôvw÷¾QÁ×öPáN~~8¶Ba=~+P³Ã™•SZ+­Âõ‘Á™•6ªkÿÍûoìõiz¾©séÎÁ‹~TÏVäP®àæ§O´ßþq¥ð‚zLuûiì¯K´/•k_&Šï;«´¼’aSl½sº-„»¬ ý<³µÒš•^{¸@9¥•_:p?}Oß7Ù?‰½˜H·zó¯õìZÁ·ïê1NáàŽÀgú¨k{¼—$xoÓ õgþ]êû…ö1—Õþ9TžCŽ+z?°þ@?ßÅÿ¾‹-ÚE÷Q÷‹' “\Wí£ý¿écÞ¹¤¯=P¢Qðþˆâzm¶q±˜îEu¸Írßœ¢}†>Uz÷ M|†ï;tC˜T»õó6˜³4Pr£öî_íÓá™Îçæ»ºOçö©øzT-¼}B÷ƒéŸ Æ$ÓZªµcÒœê¢}Ûâ?Æ]]¨û™•›+çH£Â½1ÂÌ?JÛØ!#–Æ$ÿSû9;Ûd m]Hiy>­Î0j— ÈLôým;›o™øMSuíå#CG:yü—´5‚ÓŸ§WZžÂ9Ã1_.Sšoi`òoÏ«{”t:¦án[ÝãÒõ1Ás6Òkš)Ê÷ŒÿN·Ëö™ƒY3{æA.~³¶z5ßýökbßk¢×Á.®Œé¦çðΕú=vçx]Ç/FüÚï¾Óí(é¨`õ£çôÚqÎU±«–T÷ø±­Û{¿^ÛÝ´xôí{Ÿïü$ö‡ ×Tݘ٪qðñ?é•–²[òØ?¦ê²|-ñϱ£ k£Êž´±sêéþèóTý 2éûV?’5öjM=¦ÛVnpø~zMý³ÚQÁ<ƒtúìGycçÖ¾ÔNkp¸N× êÚôŠÄöýQç󪯄׭×ýÌç“KÇΨ¦ã{iC—àø¸M6k½V-½E§y\‡®±•þÒãŠv)¶ÇÖ©×z[Œ\ûuŒž‡{w^ÝØë užæZ˜2ÜðΫ<û£Ãû¿Ðs–Ãc÷ÇöÌüLåK…š­cGÓ}÷³‚E‚w·é> dÕ .Z²L][hw 8¡üg*\ÆKÝcßË¥ëßš—Û­iãÔü}ë-÷c;§ÕãÁ);X!¤çTœûQ}Ý>^?7<øó©÷Ôµ­v .>pBïi;’5X¹ŒöU¶ÍÜV²˜ 7mÆäسó´0 ñºØ.?èµ;GJëŸÿFåÁ‰·Ç§*¯â»º{fì^ߤêUÃåFèy•Ïê\E=ÔcºMu2Ƕˢý¿GöÜØ1Obt]5"¸cã^ußc æÇî}9V…³þÌ.ºZ¯µå9°0¶Û.ãÉtÁ‹%Ë)­ÐžÅ±>Ð÷ý¨j`ɆºjðËÒØ _?ïÕÿÄN¯ûÆÄ‡—ÅöÞUAçÁÃå±?}TGçUþAáméõþ«\WÆÖhPK…ûô˜ð—/iÿ`UûÕ±9¯TUáêŽ-¼žXï,½åZ¨ÕbÝöŸÞn<—®Õ ç&ޝX¤Î—ê „²~=H]»ùÌèpÑŒzMýV׿ÁÒ½®ÆœU欽‘\ÛØ¿ZwÞ(Ÿ—îç½<(˜ú³>íj•NÁ2yªªpµ ¶hô¥ª=›ö ¦Þ•D…»T CpìÍX¥í½Û%Øc@I¥=]Ð98¨Fy¥U®Ö-Xrla¥*1$¸eÉM•¾-¿ Þþ¡JËýS‚ï<üG…;¹¦gpÓžŒ*¾;É;—Ö­­´ ÓÛzÔHië¦÷ÍîWÚî¶Ýƒ—ìºJ[:´[ðÈ·•¶oÕ€`§ti”öeÉAÁÑê¼Ú5$˜ç_KiÝ›ö žkTAi· õ.ïPJii;ô {RHiy'ô ~š«š.ßφküê¼74Å”ÍØzÿ<ëÚ¡ÁÙ ÿRyµ§R¿àÕÄÙÕµÿ´ḵg‹Ò.û;DÆÓ”öU/B5zë1ì?¥? Å=Öcœ±…î'ÑûæN–ù8tÿ¾¶M¿ÿ04ä_í#-éw6ô{´n«mÎ_ ýÚZï³\ü0ÔæÛ?ßóL[.‡òÜÑmpËè+¡'ê4ïØùYèf9=Qüý ¡…eôZ̑󟄢Z¬Vš}ç|¨I%½¾ðúï‡N{ìË]¯'O:DùõülýiÁtS—+íòðiáêE¯ÒµQÏ[mŸNßæk¥íØÜ"<»áNÏ)Z†«4~UiØ/¿£ªeaÿ>Ž`~ü½âÿuNSÌônå0¤D–á—}†%<‚ö· —!ý)ñ3—Ÿœ×H—ø‘<9·nDz[â+.#>9Ó¾AœÂȽpFd€ex ñPâÄ£ wrÙ{fÌ&–4xÏÙÄÛ\öž%«F,að÷TÄÕˆ;¯tçy*ÿF\ËgØvqËy³T'øU7 ÎM° / ¾@a¾vñÉY²4ø¡Ë0J-Éÿ þËeœ C<žø5ânü84È2¼ô/‰¯¹ŒsBý,ÃAÒwqëžOγe¤çvÃà¬P¬eøK⿉ßs¯Å™¡S–áò¤W#þÕeœJJü6ñ»Äg]Fz³[†sKšqÖ¨°Ïpcâ÷‰Ï»ì=›—“¸¡&‡‡å^|f/'…vgÍÚZ†G‘>–øs—ù¼ø6±Ä sÄ2|‚XlŸÌKñ€[»aòYÎ9wáúÄ5(Lo—ó[binMz—ñ÷B–ár¤K˜‚‘[Z†S’~™ø[—ŸœW$]âÇ9i×à¤#Ná–ŸuM,ñã<]âÎÄ+ˆ·ºŒøäq=÷ZœÓ›o~x-…Ùè2Ò(ç0ÁÿK:q¦oªeøñ]â¿Ýð8ë׌x±ä98ŸË8 8Ì2¼š8½Ï°å†Gz+[†ëKúq¶p˜ÏðâCÄ\FÝ—:E,u¿ÚôÌ2\‡ô]FuÒ2\‹té§öê–á:Ä÷Ý0x3wcËp'ânĽ8Œ›?xûí`Ëð·ÄÿWwï…~Xú\°ô×Hcmâ>Ãw‰%Í5"ÿþjNFz*â®.׌ü;Ã2¼”ø±ä-^hÒÜ2<“ø*ñ÷.Ç¿|ŠXÒÎé2ò^êLz\° ç$}ŠË6åXü%\$–ðà\naðÒÞ2¼x„Ïðnâ}.£–þü7±”)î_Ï2¼‡XÒP×2ý2¸ñPâ7\F| ,ûˆ%~´¡ÞÄÒŽp]#â]Ä÷\Æ»Þ'.ä3üñu—_Ëð=â[n´¡v–áNÄû\F͈åZðÏ.7üÛÕ2|™¸"…Iïæ-âkežLÜÂgXâG½¾b¾JüË-,ã#‹ï%>è2úÕ—,ÃI—¾µåO+Ê“V”ÎÖ–ûŽ(—7‘ž.Êp—ÛDþ}jŽòÎJ¼ØeøD>â±Ä\nGe׎҉6Ô‘XÚ 8ÚMÞµöŽeøñYâŒnxÄ·Â2,qv¤8‘±Ãg¬$–1BË´kð2â£Ä-Ýð¨_‰ëÏv÷›ßÝ2ö|†Xú;°ôq=p-ñKÄG‰ÅÿìiÉû´¾Gúâ´nž ]‰¥?‚=;.å3<ÀeÜ'ñâß\Æ»fÇZ†Ûþ±Ï½/Æ@|†ƒÄ·]Ƹ¿ ñSbïcœ-ãhðb¯aü=”XòíOÚøbiƒÛU&þŒXÆwèÏ¥ïŽïÛIÏìÞ ¯•Ìè3\š¸6ñ—‡ÒsÁÿZM\Ìgx•ËxûÛ⟈!–ú0‚òj¤e|Wð}âv>Ç]F}‘º÷϶ ?&®Iaü.ãž2¦Ce„ºÓÍgø±Ô™q‘7[†·ZÎàí¤ï$>@|Îå—#ÿN!žFü1q÷¾Hï+–aûc®"?ñb™£Àu“,Ã=HßåòDä­eøñïÄ2®™DéŸDñL¢4£O“>,}ÙzÞ)~ªeÆ àÜð;Ë2ü1q'7Ìt|× îM,mvQüIðb±‡ðÅWß"–± Ò5Ï2܉ôþ.£n.± ûIuyŽeæýÀ}‰WË|àÜÈ¿7-Ã?'§0'\FY†û“~ÉeŒ ‹o$Þâ2ÆÍ‰¥Ž¡“þ Ü’tñWqÿå–ቤK[Æw'Ž2\’¸qÀå%”ŸàúÄ…Ü0(s)k°Œ#öÃÄÒÿ"½kˆ%ÍàÔnœðZù ÷$`Uäß7-Ã26$–± lmzb±·HËËðÒ%=˜3 œŒôT.¯CËð!âóÄ2oî@<Çåõ–óná Ä?á†GÚÅ~‚Ï˳`®ômËð_ÄO\ÞDiÞDéy5òoœe8éyˆó»ù€´lµ Kz¶Dþ=M&–g‹Oˆ8ÄþãSìÿËÌÿ€CÄçˆw×í¶ KßñÐbË ì^b °2ŽÃß÷[†% |d±Ïøûë–áÄÃÝ0øû–áܤK˜Äû–e8 éríÁÈ¿-ÃYHÏF<Ïe”¹ÔO´§Ÿá‘Ä{\ÆýÅ·Ÿ%–ô ®}c~BüÜe؆£ÄÒ?bnõñ‡>Ãÿ¹Œû˘âJû‘ø ï'þ8»[Ž˜«[é3¼–ø#—RÚpÏÓÄRWGþÍç3<žøcâ¬nx<ŸÌŸ çÂ<–MÜŽXü4ÌñŸ$¾N,sûH£´¯Ó”N´ã>ùˆ¥>„,3.&þƒø/—q±W`iË(©˜c(D|’XÒ;!ö ñ‰Ýû€âü0òosâöÄoKß„z-~/XlïG‘?µ ?&.Kaª7Ž2ÜÆe¤ñ˰ØgøSâ·àïŸY†"Žvà½f"ÎB|ÌeÔAñ‘ö>Ãe‰ÓDn@ܸqSâ–Ä­ˆ[»Œç9ðwÄò,ŸGþíGü:qqR7Nø&‰‰e>ç‹È¿i}†/%–vŠtÉÎJæí¾%–ùº¯,ã‚ǯ&þÔe¬'$–¹zÜS|Úk‘‹ßî@,>$l¤ØC°ÌÓ"½2öü–Òüå3î)þóõÈ¿ïð~‡XÖtnXf>¯øºà%¤K:qYƒ‹¯þƒeìøOâ'ÄÏ]Æ:XkbYSû1òïâíÄßßti‘qÍJÏO”?x¦nÄò\¿Xfž,Ã2†Â¼{*âtÄÒfáSÈÜ&ìØsÄ'kÖà?ˆ%þ‡¤?$kòµˆ›K ;‘„XƘˆO|?ÔYû¿C,õu99qbña;«Ëüî#ý>æËÅþƒen9¾Ž»Œ5iS¸NÚæAû Ëœ'8“˘û”9OpâÅÄ2ׄ1ŠŒ pŸÄÄÒ‘.Ûb®TæEÁ“‰—»Œûg%>ír"ŸÙßžOüŒ8ʽÒ"ë8`Iʳ3±¬{b~ú ±¬ã#ŽTÄÊSÚ5ÖgrËêÅeb©ˆOêyjäñ2âSÄg\†/ >*ìúTâ¹ÄbçqŸLÄÒ¦0†B,k”ðYdÞ,¾ æçJ×&~ÍeÜ' ±Ü Ïטø qØe\'~5Ê¿$±Ôü=±øZ°Á²¿ÏE,aP>²ž…¿Ë˜ y)ãhˆó»y’7ÂE}†³‘žƒ8§ËðaÅwÍGu,~,æÆ^!^O,seHË6bI¸¹ËèKeÿlƒØì©L|žø—‹Pü`ñyÀ͈[¸Œ<ÎBºä ædÞ,{u0#s5`Y÷)A÷7!ß uAæÃKR}Ë|8ææo&¾êriªó¥©Îîˆ ‹ ?Ø”XüUä·ìÁ:d5b; ½AbI'ÖIꋟV‰Ò ¾H|•Xü½ÊTŽ`™{¯ùìN<”x?±ŒãÐçÔ$ÿÏ$맘³ìM,ö×Éœ!úRéCa^#–9Ì-$–¾qÈüÆm2FC›–}‰1 Å–þqÈÜò^öŒ!¿Å'Áß›Ëã]Y—G,ã\ì_ ãN™ó„m Ë-ôŸ‹‰¥ßlJiÆ~“ˆ?$NeXöœ í2^kNéǼ¦Ìgbί'ñ$┲îIu¸ =oz^ÌûŠß–ž·•ÒÒ…XÆðqÄ·Á:Ò+Äbë0¶“ù^ÄÑ‹øMbYヺ„XÖAºS=ïNõ¼;Õa¬-ÈZ@Oʰ̅âþ²¶Ø‹îÛ—ò,cŒÏÆ¿N,c4<ŸÌ!Ã>I[Æ\õ8b™¯ÆýGËšæ ŸéSÀ;ˆß!–¹‘x;çòPÊì-:Dœ<ÊpQYÿò™=HËXbIÆ+Ë8e åÃÊ+Ä!¾ž[öS¡}Ë~æñ”~„ÿðª3)?Á2·Œò”1È$ªçˆcšÏ°ø™ðd>Ô,Ÿá¹Ä‹\F3ˆ—¯s÷ÿŠXÒ0ƒâŸAqΠk‘Üð³( ³(ülŠþÅÇÄÒa,(ëžà›Ä?ºŒ8d`¥íLÚþ¾’Xæ à«'>E,û]—Sœ˜oÞJ,sΈ{-±Ä?b'±øk(ý`YÏE²6„ú"~Ôªó`YGCXñI°.!k`Ù‚=²¯ýóEbiˈCü™­ô\ð­Ä·ç'®GÜŒXü:ŒÝe_4XÆïh÷ïK{ÙIù;'k—Ø"mi”1l¤øè«ÏKv,ísŠÒÖ‡Œ¯bC`³Åf¾ù¼A,~287q^—Ÿì—~—êÕ»T—ŽS;N:æA¯‹†°2Ö€Ï(>4é¯ã¨LÁâ_…(OVút|Š/}Žò }ø‡ÄÒ_C“yi°ôéˆCü7´]i³ÐÄ—»Hé&{*¾¤º{ væÕ“o(ÿ¿¡2$›þßç2â[qƒÊè]{“Ú æfd uJü‡©mÞ¡ø¡É¾ |Þ#–=CËžFüý±„&cU´QÙÓMÆ­ø”~ ójωe¯2Æ4™ˆe\ƒë¤_{B×þGåøœâÁ§¬ib.6=±¬ ãïbgP&’ÿè¥Îàïb`?ê7!–qÂÊ|>åYð)Ï‚O£áSƪ9<,m3'1>¥àSê@Ègâ ŒI鹊E>ËW"öËØ0òYž¸"q-F>ËW&®êrIЧ$å98Ï–UŠâ/Eé×p¹4Å_šž\Ýå2”ž2ôŒàÚ.ãï¶Ëø{—‘Æ—‘–š.#-±.ãþÕ\Æýëº\•ôª5J[u _ƒâ¯Añפ¼­Eé©Mé¬MñסòòS<º6H÷·uZ;—Ñï5#–þ®>ÕíúT·±öÒ’XÖP’–¹¬É4%–ð×Êø½-¥çíÄïÂÞ7Ùû‡s{o—ŽŒ?S\Žÿ='ÜCÖÜœ¾ÿ%zqïefYâ×:šœ IIl9Káhr/àÓšÏÒ÷Àœ9[àh2n:Jáäì]vfÎÿ anPZà_\·Äßp49_g[Z3gÿÜgsÃlóhÑžkåœ]5–Ìs­œ»[éÑ’{®•sxIøÙÔŸ49g÷ªOk)<×Êþ›£¤Éت4]+gìz4s†ÏÑäŒÞŠ󑘫Œ# þü¬¤t-|o³Vçh˜ß2ûQ ó󾆣É^at䉙ûr49GW8JkæÜ £]·,Zïp49GÄ÷ÅÇŒ‘ óGf/¨£Á¯Â܉ùÔD/öEw$MÎÉåðhæÌŸ£‰ŸÐ“¡O3s¶Ž&gçú´fÎæ9|gÌ[¶ káfO¨{7®Á>­™³x&_'‹Hƒm1{MÎÌݶ´fÎç9æ 0gуÂÉ9•¥¤É9ºÖ>­™szŽ&{Ÿ¹^a¾ slK(\~7®>>­™3zŽVÀr”óhù-}­ìë¼D÷µ®L¤É¹¹‚>­°ô=0gaæQ sûhs¯R|rfîkfÎê9ÚàB·Š ¶œí¸œ;âÓš9§çhðåáÛ"-—k 8}¨ÏÆ?v4Ìך}Ž>éŸt_ìu4ûõMÎÉýkiÍœós4sŸ‹ËcKÌs¤¦ød¯W irNî¾G3çÿ >6ìÒ[NÖ{ß# c'Ìy §ke¬ÁÏ‹1æ1Z“&gÞîú´fÎï9üwøù7Hƒm1s±æZÄ•‚4Œ½ÍjG“1ỤÕwíH!ªÏrÖ-§Okæ Ÿ£É~ïß)>™XFáäüÛfÎÑ™<ýÑ'seކ½f/³£,‹æ fÎÖ9šì—*A×ÊyÛ­ãu´ÿôåmÎ9šœ}Ûci-`é´Èül. 'ç)2R|rîm—¥5sÞÎÑdž“ûnÌ­bμir.5sÖÎѰcö‡8|œ½ž~UÎÄÝòiÍœ¹s4´Áãž2Ÿ—°dŒ£ÉÙ¸Ÿ=š9oçh2žœòTæù*Q89ÿ6ÙÒš9wçh˜‡0热 Û®¾ñÄgÎ$8ÖßÌFüߦSEÉj“æ|£É¸}–ÖÌ>GƒfÎÖ:ö(`Œò'i°ÙfŸµ£aüŸ²,…C›Lâi—˜£AßÕ“49ר£™s|Ž&{¾ëQ` ë^R8ÌWmwË]4ÌÙaž/3¥9¯k_Ù®Éü\*óNnÚªXZkçI3üÉl®O)Ú†Ùwïh˜ƒBѵ°“å}òûÍŽ†9J³ÿÅÑpn®“'-rv–ý!Ì}cîü=Òd¯Ñ5ÒdO·AY;¿Jš¬ã|Ê}€åœä´Ànšu“§fŸ±£É{ Æ‘†ùXöÃd¿£Ð/b½)i¹e1šî+ëÚÓ)œ¬ã}Næú±n0Ÿ4ô‹fíÓÑdÿ5çœO~ƒ4Ì×™sªŽ&ïwùšÂa­~Þh 'çÎÚQ8Ù«Õ†ÂaŽÚ¬É;æ–7{ìÖ8áÓÍ¡k‘/È“ÞNöxðXuÒ¼_ÅÑ௢oe_gëÌ;€Œ6Ԓߌ7Ï[Õ§}[9¿3“颴Ÿ#ïæ¸Lá0‹rç2OìúL‹éÚ1nÚ^óh#¤aï‚y÷¹q¥#-¹Û&OPZd]üÒälŸÇ»qõðimŒça×ö5¦pr†¬;…“sw»|Z3gù ¾¹9†ÿ¢_ì•IDáäÌ]ž(­™3}Ž&ûQº“;~Í'ûVMÎá½liÍœçs4<—y_†£Á6Ýôi_`šeÑYF£M±ô=ÐÆÍ;I íÅì'2ך}ꎆ½æ ˆ£¡øÍ§}øðسzý=Ú4Ï=0ÆCþÒ‡}4æÌ©£É{C8_°Ú¼‹ÁÑ`¿ÌþGà ³ç×ÑäŒÞ%fÎ:ö¨™=tŽßs¨ 龘3&ކñzKÙå\e½Ží³œÙ›èÓš9OèhX?Ÿê“½ñކõÓ>Ù¿æh°Ãæ]<Ž&ç-ø9äl%á+›=7Ž&ë·ƒ(>¬ášýŽ&gúRGiÍœOt4Ùgði[Üþ©¸ÇfãùøÙdÛ{ôµæ}Uކ1 ƾ ú“ÍœÅr4øñfžÑðý{9÷7ܧ5sfÐÑäì"ÏñÀ梯æ~ZÎæöiÍœ)t4yÏa#Ò°¦ Ÿƒý597˜Æ§5sÑÑŠº¶žÇ—ÈwÌ}ó¼7ìxMŸöõà›=fŽx®Ç†a¼dÞ«åhr¦ð¬¥5söÑÑd_(Ûb¬  Ÿ7}|t|]Fûâ¶?`¾ çÔ+³ÙÑdÏÉÙÃÍœ‹t´ë–³‡žÇ¦XÛ1ïÂp4Ù'x‡4Œ«`ŸØ/–w˼Dš¼g‚×v޹iË¥µwÃKkæ ¦£aß”yߤÑÌ;Mö¦Mõhf›£Áß0çÇÜûú,Úçïh8÷ˆ´}áÑN[:Ͱã°á<ŸˆùÓœQzmGÞ»âóhøþÝerkæÉ{sÕÑä åzKk漦£ÅXí¡4šy瀣Ág…_Æþ¸ìÉäò…Ÿ‡q ûz°Å§|zþg'Íùv£}`é4ËžûOIC¿cÞ çhrÎ2Ú£™3šæZÌáWôhæ}hŽ&ïhàq­œ1?GšœñïÑÆûtyÈyÉï,­™3¡Ž&ïŒãúßǼ·ÂÑà ™óŒŽ&ïÜ©@|bÌ ³_Œ=ÄæýKŽ&ç'›{4sæÓÑ0dÞcæh˜'0{ù ý±Ùïhræ’çiòYÎx½‚¥5³ßÑ®ºi«eiíŠ'ÍØ;„~ï1]‹> cÌÆž4›=×nþù,:¿êh˜ï…Êþ©œ=øˆî‹s‚8—Xš´©–sfÑhÑñg8Í{õœpЮzžMÞ/Ë>f*wÝŽçTe¾™ŒŽ÷gÌ;p«š÷Ú:Úï®æú|ËMÛßí{Oš±Ž•ÏÒåVßýÎë[ò~4žß@ŸlÞGæhè“?öô²¯½Å'g?K{4sFÕÑä.'<¾ó: Æ}æ]Ž&ïò8OáPŽS-9“éh/ÞEZ&×ßâú÷ܵ‡¼Î _ʼ;×Ñ0'hΊ9šœ}hiÍœKu497Ò•ÂÉYWoÉ9!¶§ÐðësE7.ž‹”³VÛ(>œ/EÚÒZZ3ç]MÞ-Íë«òŽižƒÂš=|ÊÙͼÿǤ¯®çyå=W¼Çá/7m=Úž4Ë{«Ø“÷WqŸ ÛiÞ‡çh˜;4ïär49«Á6õóÜ<ÇýÄMÛÛí/Ošåü-¯kÈ™8¿a.óë%éZy'/Ï À75ïv4Dš÷=wÓöG{âI3ö™w^9úEÌ!ðüÆ´æ]rކù]s^ÌÑd¯3k²OžýºçnÚº’ÿþÌnÒp®ö¹'üló¾DG“ó?ìgcLlÎýšçÀ3ðø\ÞiÂû¯°.9Ùs­œÍ­aiÍœýu4y¿ô Kkæ]÷Ž&çx=š9ÿàhÁçeXÎ6ðZo*7m¿ZZKæI³œód{ g y­s9æ½èކñ~–(9«êhðmÑŸñXöËœ‘q4œ 6gî–ʧӌùóž(üß6OÜ>°þaÞëíhhã¨G\‡à[™óކyzÌ—òz™œ'¾èÑÌ™fG“ß)`¿.‹ë»p¾dqã:hi-“çrÞÇ—XGÌíÙ«>ƼÈhY|ú²/™×ð=±G“=ÎØ×ëìoŽŽÿ.{«¹öËÞåš®&{¨ÍßèøýDz7¹Ž«ÉÞl³·7:~ϲ쩶]Mö:ÛQ²·9úÅ^kìý ¸¾ËžíW“=Ö±Q²¿::þ»ìÿŽu5ìq–=äÎâD/ö^×’½ÍÎ}ͻ՜p²˜ÛŒì!f;.{‰¹Ÿ–½Ã¬É¾aÖdÿ0÷çøŽ~ž5\×Às-â/áÓÒÑÐé5ç° ÏeÎ;ü…zžç…ÿÑÈæ!ë{ò@Þ¹•ÂÉû¹ö¾Ð¢_¼+r;…“÷~íö„;`É{ÅœpuÝr4û¬Ó¾Ø mö[§}ñ›éZùMŽ”fìÉNú?høÞËÒ¾›õéh«i]güÛ¡ÚådØs…dØõ/'«¶íódªiÝØ#{îkyþ“ìÐì½dÞ¿µ¨~9™{ù…>5òý§Ú—„ãÿª¸ÏV‰´øô ÏØûå’Óˆ&ɶy1/g؈ ÿŠ#OÄÂùâÿ·â÷¨'–´¸q]_øy2èÕ;iªìÞ·`ã±1y~íqÆ¢ßÚpsNL¹ãk”öûÚU1í+oRZê‡cîÆPÚ’¬ùb~HÕWiWn7 ¬ý¡èIküo‚ý™#îl—¿Ï;'K][tšµ;I;ÅôJö>]õ|kÚŠ1· ¯WÚ½æ)c~üu‡Òþúï`àß}”Vp}þÀôåã”ÖºhÕ˜{vq•æ:¾g’”þíkC3]8Ó«h•æÁË'Îdýâg-Eï’qÍßß®Âø!cLÞ^ÓT4]58.gõ‰.êù±i³c&w:£Ò·ê¥1vÙAÕ=>ÊW)0zïs•¾Ø¯SÅtLåSϱ¯bî¸.%;æøÆÇ,;SuóK*}Í>8˜Ù£¶Jßå‹b¦—ݯ⫗yvàúÓŒªŒVäý%°/´_i'Vˆ™¼1‰ºvh¶†1]GWRÚ™ofNeŒVZ“++ì®'©ør•㻽R¥/[‰JqýÊ•p¸žY7ÄÜ ¼¥òïëá?v¾[EÝãðç“büí×)-Ï–þ1lPÚßv¹ž§ºo·¦ÇÏ|ÙÿS•? «uæþ§óH‹z~ü/nß­$ª|Wv9è:h©z¶Ç‹ž™z:½Òf]}¦Ë…ôgøÚb¢âŽ®^¨î[1®AÌŠ™óTšG~\+fEûy*ÍÝßL÷gª§ªåzR3®Â  *ÿRUÝvºÒþ}ä¨çÿî÷ïGüǾøß¯ú5bK`Û0!¶Ú±âÿML,¿G‚¿G'&.@\„X~Ï×%"ÎI,á‘–ßkÁ}’g .L\Œ¸qy—qž%q>âü.£OJOœ¸ qqâ’Ä]ަ8Á¥ˆKËoJÁØ%–ô'§ô§ gOAÏŽùÄò\©( ˜ûÏCœ—8±Ä‰³!i‰3g!.M\Æe\—Ž831‡)ër: “Žò\‚X£|²g'æ0ˆ¥\2Ð3â|IAbùìyÊI,õ33=;>sK>àŒInâ<Äùˆ¥\²Q:ñʼnKËså xrг ½…ˆ%ÍHc)bIgnJCn “‡âÏKñƒ¥}å£kóQ˜üOJ¸(±Ômä}Eb'ÿøä^E)<òFÚZ)z|J;*Kù‰ë¤íT´LùÂþ¥ƒaˆuÎâZä™±Eø/Q|~™²u4É[³O3ú…+@á¾\žkK»ñ¥¡kÅö¤"Mêh Òäy£)>䙩·Žf¹y—˜´¢nÚÊ‘VÈ “î!u7?…KäæKNÒÄ–ä# õÃØG›ÉkHåÜ´•§ûŠÝä½(bÏ9>ésø9ÓžMê ï=,eYd“ÍsäóÜCú'í’ã“qDbO8Ó8êcv&íï!õÜ 6¢_ô•HËàÞ“ÓŒ|Êk%Ì+Ó í¢¬'-bc³{4csŒ†ï<\ÞMKrJÒÏâsvÑñuÅØ?çZØÒtžøPÏŒÿ`Òl콟ôMeHËìjièZ±•))Ú_fO8´Ô¿‚¤ÉãJc~Ðÿr2Œ9%TÓºMûŽP¦\9üYfŒ¹¶IÂ1fµ—“¥ëfâùÞ¡Õÿ>ÆÄ¾Hì™@P›3½ªÅbúmj`ÑØªEvÇü_ƘH‹Ä•nŽ3Æ 'wÒTÙ½ïû¿HñÁ­~¦ïù²É•â^Y\2†µÔ™ÿ‹™æ½3¬åÊ›*SÊ8IÃó)‰ž¿Wm~Ü­1KÕµNiwsq7¥Åd_3îã’*¾Øµ;âÎ}¼U…Uqs\é¾o(íl¿•qWÖíUZÜÛoÄ$m£â«’ui\×ó«U8¤ùù_“ÿí{þs¥â¡>o&Šåp[¶õŽûgì8umøÝ;q_÷|Mi'žû¢Ó¥}ñ˃¸ê«*­NäÙò<ÒÚÁ«YBïôý]ÇwêbÜôþ;µV>&îÊœÖJ»¹ÇÚã§”†ç^ûo¥½÷}ªØžýDZ6ðv’ÐÁî—U¸“qµcÒ<ž®êA‹é?žÛ¿¢ wfÔ°¸Ùi^RÚ˜½'bZ‡‡«¼?½öû¸‘ÅuõÜ·Eµ³JÛúʘ‚6ج¡N¾;; ÷ì›1ß—:¤Ò7qá˜ãåóœd-㊎qç:6Ñy°ê˸‡I$xŽ efÆx¯}y~¶½‘2jSç–Ò&EêäWµ·(íØgyC]?~ ´#yp±Å»J;©§]ÛT^Užt6®üô·t}i˜3TÿÞÏJû¨FѸʇb”vwÏ'1sç}¤âkUwGÌäo3(mÒõr¡I©ßz~7’æ·þ|¦âÛÉ«•ßïRZ³ZéCîÿ¤´ûáEÿx¬Êc~Áç·I¬Â [(4wûŸº V/³3åºe™ºÿ_§½e8O…kIËï­â+~rz\:ÿ*¥¡îžÍ–YiMwÎŒiÓ¬§ºÇ¤ñoƵ ½©Âeù2[ܱ>y”v!ëÛ§¯õJ• î^ÉW_¥/_&1Ŭ=JC¹ÍìUH]{éY©P¥ž‰Uy ¯†ßö);´îQñ@ͯó©kßX±..ïû›”–ïôŸ‹ßVÚŠJVèÑùcJ;±aeæiíñõõ1á´]T}Y¹¶ÁïçU¸"W’Æ­Kž]iÉ#ýÂíýÔµ«coÅ ,yCiF¼doÝ­û”ÄC3ã½o¾oʪpþHß}ò7ÝÆE|‹ú›6'¨“:TUêÁŒ²¹TúþŽÔñ´ûΪôÕØØý™þÑm?’/WNÖ61M™Ðó¡ÿê~!ÒÇÜÓ¾ì_Òj«û‹Ø¦ÃYg«phÓóçG)íÜÏB­hû¼ev¥Ðýsñ÷}¡E÷¬VÙGáÅÏ÷Í8Áð3áOËù+Ãã¿*ÄU‰Ç¹ ±,q]âŽÄ½\†/ß‚¸%q[â>.cœ™ŠXæw০$®M<Œøe—1~ËL\ˆ¸(q—1^«AÜ”ø%â‘.{£>qqâ¾.'£0É( X~?㧆Ĉ‡KxÌ ä&.EÌs…òÛ§))ΔgJÊÃT”ç`)#Œ‘³×#®O,¿­‡qU.â"ÄE‰;¸Œ1[zâ<Ä%‰å·U1fÌD\šØ&–ßçDÜYˆ›våÓ…XÊs+ňËW&–ß“ÌDéW"–ß›EÝìH܃XÚNJ'¸±¤eR¸>±”ʳ±”)Æöy‰+×"–ß¡Å8º:q¸;ñ@—1WT‡¸9ñâá.£¾ð|ebi×u³7±ÔÉf¾9åúŠ–ÄÒ_@“úߊÒÙŠÒÙšž,¿Û†ò§=å[{Ê[´EéûPþ]ˆ¥/îL÷êBzWJ¸?±Ô±ît¯t/´oiË}ˆûQö§xPâ;½Dù9ˆò—¶0ò<ÑåWˆã}óˆs‡9aØ î=ŒˆÿE u¿§$ i66Ëhƒ-µF{al³£!ýhÛ´¦%ö>—G3mÚÑ`“¯æhâËÐÞ­ø{˜~ÌÑÄ×êëÑðÖ¶¢Ä×ãÑð=+i°°“%<šégMÆ=H“q ½§( uÉØ£uuuÑÄÆ7õh¦Í9žÕ¶Ä®9šØ zaê Ê6±Gjé2G`ún£á;½;&JüÿRÍôSކ¾¾pZ–ÅRëDQU]¢3ÆQìóˆ†v`l´£¡þ_ÚÑlË"?Ýh¥-õ΋(ÔÓo:lu>Kú(GCG{.çÑŒ¯èhˆ?“çâ3pþÉØ…Û| 3vq4ÔÔsnGâ÷Ñ;u¢d|•è…%ã,:'%vޝE2¶ÐÑà·˜q¸£‰ý‹ñhC,uV!J|*.s鯸½¡Ÿ0>²ÑÌøÁѹéx4ãs9ê­ñÅVÒÒ¶Dú‰Íô»Ž&~S VßRb| GÐGšŒ]¹|QŸyžMÆ|e<¾sGÝ3ãs£?ÖѤýT}¡EÇ×+3á„“ù¶÷â{±Ý@y›1˜ÑŒæhâÃѾ…(é§^!M|Uh­ÝôÉX‘ëŒ%¹ŸA›±­£É\½k# ö>hO8ãÿ˜pm,K™{ ~.K™w‰öhfžÆÑd|=Ú£á;Û?ÿ" Ï`ætŒfÆ>ކ6Ž>&›G3sdŽ&c;¿GÃwîCÑÌØÛÑ`7ŒßèhhfžÀhfNÇÑP>fNÌÑdÜ^Ç£ ·´mGY˜±­£‰/ÛÊ£Ñ\[ÓÒõõÙÌç9šÌÝqÞ#ŸàŸç#Müu¯f|MGCy?ÙhÍ,mëdÖýeÀ€5—“aO€„z±Àl‰ÿOêbº)G¬íŸp9Ùù&އ‘ïKÇýï{pçÈßñÜ£V¢™áãÓjů m{{[ì«CJÿŸö -×ßóœ=£Ó8iªìÞ·ïÁ×ÂÖÑl´îõ|q’}áë f=ÿ4מðƒÅ•–²ç®ðÂDe•†øÚI¯´±ïç»SQi5»m¿‘ªšÒ†Þ®ž£¶Ò–u­n|#Fiçb6‡GÇ$H_ìáüJû£÷¦ðîQu•ö~ñ>á9õ›(-whC8û§õ•öZ³õáTcêçøwmxþŠFJ{éìšðÓÚ•vïÀêpÌH­µ:°*.¥µñß­ ŸŸ§ã[Ü~£LS.×Êð³:-;›­oÉÙ@i§,§ÝªŸ·ÄÑ%áJY«êø¦- Ïéi'HKžÇ1 ®½¾¯ŽÒÞ™°(œq½.·1}„O÷ŒUš?ÿ’ðÖgº,GìŸ~oc½ùÜãF@ißmX®œLßwwæÅá»{¦åTiýç&tß:ÜZi¾]^?^?[ß§=¿Þh¡´Êg…»¤o©´ok/ ï¤ó4Ç;}ÃÅŸ6JP‡†ÔÖiùjÓ‚p‘ ºŒŽ§ž“CߣÑÎùá­š)mf¢ùáÉïèpÛÌ ºÛF׫tmç¿í®´[›ç†˜Ñ^içOO ÐLסV?Í 7oÝ1A[ݺ”Ò*Õþ§L'Ý.·Ìçè¯5´éDãË)­ÚÍYá;ßê{ >·²tyÌX16ÜóNóå‘lg‡mkõwº®eë33œý÷v Ò7ôóVJK;#œ%µÎ¿¬mê…Óþ¤Óòî½¶áá±=”ö`îôpLêé¼ÑUäó蛺^¹:5üÍ•æ ò¥f#_±¢SÃáM:\ìSÂ)ÃZ;üzóð³}ú9ž°_×É¢“&…OÏÖiYpû•ðùt½šÔ¨Vøó¯Ú*íìÀ á†-u;úêP£pÒµºý>Êùr¸ö/mV_»û§Øðs›$ÈûcuÀ?M7ºF‚¶p÷ºÎøzãÚ$(£…u›/ðYA´·;}u»„Ÿ2X×+ø §ÚkþÐýÛ:}w¶ÖG—ë™ ®ªèkáS?ù^ûuï·©Þ·§·Òà‹öN­ËrnTµðèºmÁO|ô’îC‡ÿY%üïÐ>¤ùâ}Ökk¿ýùKãuyÀ§Ù~ªe‚ô=ˤÛÚï¡òÚ†aÚì &°/™3è¶ñBË}± êU‹GúZôe·¶Lü¥ËvòôH}ôÝ›Nè:ޱËwϵŸƒþèÈýê©Oô}1ÖøsŽ ¾tÞ¨ûPغÙu,öZ•ðÒÜœ¾¨ø=K•Ò[ÆÅ˜æ¨ÿ§3ŠÿÛ¹DY“Âß§ –0ø{âÄ»]NLá6)q%b ¿GW"–}ø{rbÖe- ƒôÜÄ6ñ\âù.#¾”ÄÈ—¹œ‚ž%¥×¥&^F¼ÑeÌ]'îKÜŸXÖ¿_âħ÷Ìa>b ï=[˜øM—ñ÷ôįKü=q-b ¿g$®E,k»ø{fâÄë M‰¯ ^ã2Ÿ3ÌLq‚e þž•˜õÃ.ãïÙ‰_%–0˜“ÌIœ‡x ñ6—³Søìgv ãÝ/$ù“âÏIá1ç^¸0qoâu.£Ì"žK¼ÏeÜ'?±< æ«K—&.C<‡x•Ëù,SÁR—ò[b‘Ž%–û g,@a Ð3¤g/Hz!Ëì$æý?«]æó“…)ßÇâÄÒN1ÏZ“¸6q=bÙSŒò³å[1º/ìDâ¾Ä‹]F¾Š@|¥‰%N¬›Ô nKÜŽøm—‡”)>ËK™B+OÌúZ—1÷ I<Šx¿Ëˆ¯"q+b‰}Z¸.ñâ½.óùÕŠ'x‡Ëè[ª‹=—÷…Ï&–kñ÷jÄuˆ%<â–~ak×!–z våÖ†¸-ñ —_mb‰v·5±Øg„õK¬C×Ö¡ô#l qOâí.Û–ÙžO¼ÐeÔ…Ä#ˆ¥nà>AâÄr/Ø€ÞÄ[\Æuu‰åZhõ‰¥n@k@Ü’XÂàï‰[OukVˆ'o ~Çe¬™÷ îE¼˜ø-—qÿ&ÄS‰ç¹Œ¿7#îJ,aЗ®!^O|ÄåøßE"îJ|Èe¬cM#žN¼’XúÄ׆x±ÄÙ’ž ,ùöº–XÚâkK,qB›†ÏöÄbßÌû>@,aPO‡ >è2âèD<™XâôîËšL<Óe¬Av#îN¼ˆXêC ß…âéBáQnóˆ%Ÿ»QüÝ(<´Är/h½ˆE‡ öˆ¿÷!–: ­/±èÐÄ×…ÍXH¼„øu—v±ô¹Ð‹Múw|&–¾¾ä$âåÄâ[âº!Ä«‰÷¸Œ¿%O,aðwÞç6žXêú/ ìb Mì$>¥ÅçhbéO¡%G,aÆ’~™x—Ëã<,×"ìâ]ÄbëÆS>Œ§gá}}(<´)Äb?QVK‰—K=AÛšI,mñM#^I,ñOµL{AØéÄÚ,b±o°=Ò¾piS;—X£_;Mü=„•~ŸÒ.ÐI[ƒ&md åÉʇ¥”?KIGý_—zŽOéVRžÀ§Û‹º/到Òwàs±ô#Ð6ï$–0m#Ÿ×m%ÞIü†Ë[=ü®Ë;IßI÷BÝ”:?HÆ ¨#bóß x0Òëùsý¥¸VæHh¯×ÿø> ™IáÑ|žke®d·G‹ò\+ó"•ÏÑdî'—G3sEŽ&>¿‹¸°{Ý:VПÌÏÌñh…=×bþ¥˜'œÌÉÐÞÏø¹–’­Œû}•G+í ‡²…ÏŒ4øLfÜéh2?³Ö£™ùG“y–V­¬çZñI;x4ãÏ:|TÔó€GÃw~•ÌËìðhfÈÑdÞe¶G«è¹Væ^êx´Êžkeþ¥žG«â¹VæTŠz´jžk‘÷°'l_j»×õôh5=ñɼÊvVÛs­Ìƒ,ðh~ϵhf e´…–nû2ORÁ£™¹GƒÏgæã¶ÂÒ¿½[×k¯G Z ËaZz´ºžkeÎeªG«ï¹íóØÉ<Ú,KÖMæOæy43Ÿãh2oÒÕ£5ö\+s$‡žkáo™5Gëï^÷ŠGëë‰ý“™£q4™7*âÑÌ<“£a|ƒ¾«œG3ëŽ6ЫG็ì‘ǾxÙ#?÷ÃËɰg^B½Ø#o5Åÿ÷â=y·î‘ï±ör²GMK#ßÿÞý¿ï‘YÎïÔ! ÷ø¦é¡±—rÇï/·»jö²ÿÓy¤Eâ’÷äÕJ뤩²{ß™ï|z”>“Ú×PvF‰ð±ô>ޝ® -ëÍïe³žÏP'të¦q)¡Y铆۴« ÷…”N3¼´Ò¾î95tkæk*¾Ìû&…¢n¾§´S-„ú¿¢´yŸLµžsHiíýZ³Qïá_]*¼³™Þ[ÔsN½ÐÞ~OÕµ¿5ªÎlé}&Ÿå<z6=‹ÞSr SxEçTJ›þcÎp¯MÉ”¶ñÄÈP’$ÇÕ=.>lú5úŽÒjW¿*°^çý‘|©òÚ1nåŠ ¡“¯§Uá2½õ}èÛ“™•6ôêìuE—ÑW·¯…ZwÏ®ÂÍÊ2/TâÀ×:}Ý¢Ã]‡WWá.•};Ôí·Jû!K¶ðÔP¥Η#¼?]R¥MÑ:tqÆ/êO»Ž ¥vTi·†• Ÿ¾§÷ÕÔX?-4ñ«*\…ôÂÃ:çÖ{‹ ® ei®ËyõR «Ò~Ë’"l7Õg9ÞÍþïI:¥M‰äËáÙçÕ}‡ŒZ:Ý<¹ 7>Ñס:ïéºÑ`à–Põº,]+®Õ%A¹Ík¥ŸãÝGãBí§ézÈž*ü×ä’zßYþ¡Š“ty´;04äîYuíÌ轡k¥u™g;“8Ü2™Þ·kÊ?¡)t»\9,Q¸×5]ÂS„Ú¾­ï{%RŸk”}¬îûj®¨ðoWË«p½ö& _™­÷¶?(Tþß§SÖ…>k©ó/噡öwô³!}Gêkû{ðÚÓ*ÜšëÛB¯ó9ÇoGCscu¾ ¯æœÉ§ó9bsή¹­â{¨Κ³› —xNÆð·CtºÔ²røäÀî î[éK}ë;î…üw )íßHûx¯þ~ußê‹?už“R…{òÖ™P¯S9äÕÓSGt=ˆØö†“uûè5*CxöqÏhG/K¬´Zß.}ñ¹Šoíó÷C¡ºÞ£} ¾¥ó _ÄÆ6ößW×Îi–:ܱy1®zÚ!+E6¥8ón¨\Q]76Gìé¾ou_qþð¥ÐŒ*Ô«o'Ðu7cºpµ­yt¥þ$4v[ ¥Å>+þäG½_µáý;¡3‹( ýLl9]ÇGÚïóŽûTúÎ *~²U··ú¯ä Wü K‚|^—;Zi£?ÿ(Ôé» ÚG‘“º,asnÉ¥4”QÖiØïÓé|AÛ/9Cï7?5¡W¨ä¢Kê9ºDìKêð‘}Êîô9¸‘¾ûµ£:æ^ÈnUU?l{ÁCô=‡¾ÑyšrxÖp嶺O‰ªü_è\¬¶ã-{çW­ ó¥ÂÚ¡\9ø}±Qñe^ÀS_êÿ¶$Ô(ÿC–¡ÙÃy7ëþíí™B‡Ú>G‘#œóšNl]‰?ô¡ ]v†VîÉš ^}ÿP×IØÎMCµÝý6âsUªuPÝwÅÌá÷¢t4)Ò׎ërM…ƒÿ²/‹¾G’6…v÷ÓyÐqRšðsµB_±s´¶±E‹W±ú‘¯—(þÙìZyu_ñ¥Î¬Ðçç+>¾H·#ØÓн_ýåï«z'(óQ_VIð­ÿÕv~Äàiú, Úô„ ºÿ…}ùæ¨>K ;ôÚ&ýÅg—?X¦ÏꌌøW/=ý$Æ.ö™Þ_¿³åM½Ï8í™láßgéz?»ÿ"½Gvcw奡/ËßDÛ ø Ë §MÏò—QÚ²ÐëϾTκÌÑÏDç̨íiÄÆ~鱓°aßwÖõ ¾Ôž%ÚŽÃçúõº.7´Õ[gõ=¦ž}*ä9?Û¤a®ð ”Ú¾ÌX”3üÁ2ý¼hƒç†j[_´ýŽÔ üس´ýC;ÿ¨Bêeôjv­Áß-Õ^kðÛÇ&ÕìÕŸ´û÷ì¼NÚoßÕº¿,—Ë ¿Ô_ûHkøè¼:±Crh džOç=|‹»ô9Gø GJê~¾@…ºÿ@ùC%ÝVGú…¯úžQ÷­±hÿc?ëmÃЗh¤ýØœ¥¹túàcúè2š¹16ôÅNKið#’ÜÒ}|åí*&ÈÓ“Ÿ—KP×^öœÿÄØ4bݦ:a‡zÚü.ÒH»œ_+ôóµg1¬a<](ƒea|¹ÕîÄ€ìWÃ͉{Ë:7.IIÜx±ìÀÚtzbþ"~?©ìÅId™=à3Äq.'¶Ìo€‡O#–õ{¬g&.Cü*ñi—½g 2ó»JeŸP4…‰¦0`Ù÷‰ìÄüDbÙ£ƒ5îüĵ‰K°þ_¸ ñ!âS.£ —óÙ)GÌ…e ®BÜ’ø˜ËX !Ï$–}¢XÿnM<™x±ì½À:x,ñDâIJgëáÉÇo%ÞF¼ÝeÔÙ¼Äõ‰¥Þf <É@y–½bXË.N¼šx=±ì_D=ÊO,勵éBÄ5ˆ{Ë^(¬=g#.E±ìWF}©M,u–»;ñ,âuIJǫ eÎ3€›· îá2êc â)IJ7v·ñ8b±½E(àáÄ›ˆeê”ÔŸb”Îb”N°´ ÔÓÄÒ±o§7ñâyÄrVeC<‡XÊí 3±´/”yWâ1IJÿ ýR+âħ]öž£¨NlË>Zô·ý‰KŸ[ž®¿L<Ãeô·•ˆ§KÛĺz?âaÄ[ˆ¥B|µˆ'KühëmˆwuíOÚZUг*Å ~ø¤Ë¨›üÎV©“È×öÄ’Ÿ¨ï-ˆ¥ŽyÏT4"–ºZ‹ÒS‹ž±6…Ç>‚ÞÄüŽ×ÄR'±¸R—¸5qbÙjÓ³Ø'ló(bÙ‰ú>›Xê<úá&ĉeÏ7úÿéÄâÔ¥tÖ¥´¥ß‡/Ó™x<±ø3°m‰¥}am¾ñzâ ÄÒçbÿEsâ>Ä“‰ÅiLáSx°øÉÈ›ÄoËþQØ­fÄ=\næáQÄR.Í龨Rწ%ß ve*ñqb±3(ÉÔ…ÄÒÖßb7Ç#‰×K>£ õ%–öÛÒÓÁÒç(Þskð=‰Go –€eœ2‰ò6f±”/ü©S-Ó.ÀÒ~a_Å®âSl5êæbñ÷ðw±áø¿e.¥y.å9þ.m ŸÒ¦`Ä&@[J,cɥĸ”qårÊg°øáø»´£•”~ÔG±ÕkèYPæÇˆÏK@Xiƒë)hÒùìúÿÓ.ó¹‚-–±Ðd̈O©ø”ºO©W;)¯vѳï¦gǧ´|J[À§Ô|JýAYIA“þŸÒ×àSì*>¥þàSêÏ1Ê7hÒœ |À¼Q¦ÈÀûDÊ»áá+ÿ%zá?ñïcîró$·G3ã,G{Ë}†Xfü G;àæÇD†ïü—ÇÝçêÑð÷ˆ"ßQËICÿe|GƒÍ‚íJìÑ̘ÕÑPÿÑNè}ËñåiÆ¡FÛcé½Â2'Æûˆ`‡Ìœ’ÑŒ=v4Ø ã£8ìü®Ômº%s3Ž&õ“ßVæÞxoœûݼã3úEÿÈçO¤Ïá½ïr^„ŸvÒŒŒ†ï|®þñµ uÅÌ퀥ëŒ]‹y43nt4”Y>K—ÆHfnÒh¯Xê]¹/üþí^éùÜ‹øõ<šño ¶ÕøïŽ&~BGÒÄV%!MÆ“¼—v v*G3sbކv{3È£™>ÞÑPãgöhž÷ÇÛUø=¼ öÆø¨F3sŠŽ&g8è=±/Æ…µ<š:šm9>'ÿ®®ÌÃñ>@”…™75ZK×gô™fnÓh3-ݶ¶XoÖÏÒ¿Í,sã=¾g! våöõÀø¼Ž†~|¶'}ðuÌØÁh=,s8ÊviGÛgi{…þv³ŒG;ni{Šr3c"G“±+½k8¾_†_RÀóx†’¤IŸÝ€4?Òû›ãm½SímKŸ;°-‹æP ý¼™w2Ú&K×]Øv3–p4ø5‹ÿ ßé÷âÿ5þ½£É<Ûqôëf~Âh,m1ÏjærVÊÒu}›ñw¶ËÒýï 7½ônïøç‡ŸDï¿~1‡Í{îeÂu\æuÇy4|çþv>f>ÒàóbÌÃçêdNqŠGÃw¶C°¨\7dŽ*±G3ëEŽ&>ðIvÒÒv\æy¹C=5óøŽ†yÌUfõhf^ÜÑd¥¥G«bÉú‹£Á†Ã÷d;.ó6É<ÚK·}ØØ|¶÷ˆk¸'>93ÈmAæ¯y/¸Ì™ôñhf|êh2®f›(ó<|õí†Û |}3Î6ÚJKÖ ùdæÛ†ïœè?ÍÜ„£á?´IîgPÏÌ|°£õ°,š7š™Ãq4Øø­M<š™r4YIæÑÌÚ £¡ž™y[GC›4sûF[gi{*kIƒ=¾ÓïhÄ·?ØÞ’ ßó‘vÚrìvÂÒý«n ÌPÆ>fÖMÖÝê“&뫜f™ób¿}Œ™¿v4Ø3_j4|gû"ó´Y=šYÿr4ä§Yw5ZmKÞ-çh²ÎÓÕ£uõ<|G³Žåh}Ýïì¿Èd[Òà³ÃÞ±Ÿ(óiH“ydÎ9SÖÈ£5ò<ÇQ7~ȼ û¢²Æ²Ú£™õ@GCEæ6 [0Ù“æEîw¶²—€óen[º?Ǹ ý­§ÈkÎçîs±ß.ó˜ìoÄYŽ¥`Ÿc£cMÎhà\†œÑÈ–ï‹d8³!¡^œÑ0yüÒ.^Îv,ÁÙ‹©ç/'Ë—ô‹úÁÈ÷á?þïg4zF"ÜɰF¦ÁÅßãŸ*‡ì-i«Åó›×àÚ[öQ¹Nq¸váâ6ÿ½s‚µ_6¼2vÖIs­õüê¥Ôü]KÒµQÏ·çÿÓùtú)—,oÙ@êÓë°–dÒ3»Ú/)Ôµjóì”É6«{Ô»±ËþmG?ß¶öeWÿ+©âÛ“ëýêüê9R&P½Ü¦ÚnÁ›IK‹4Vñõš™$0gAO¥­¹Z>ð~ö)'X³n³o†þVé[öY–À…¢Nò}·>Èhrç.ɇ)uÒ¼©´¯ô°'ü1M][êãrÝQ÷­Q¥hàFó¡êyËdýÞî:½«zÞë#2žJ«î1uH™@¿Óó)¾¨çe æ ä+ºO•ïàÏ.Ø7?ï¡òà­oŠ>œÞXÝ7û€<q½Nr|þ¶ei§æU÷½ÙâU{üƒÕ*Ü[Ù3ìÛ¯«ç}´5Sà·ï>SÚ¢åëº×W׿Nõ—k] õ¼©ÿ{ÕNyý”ºo§•‹mßë_ëëþ·]·ÎTõl7Þ¬èþuuí­å3ì4傪ͪ^1ðÊTyd~r×®\{“ª»ÿZc‡;ìPù\ s¶ÀÕïW«{ P!|ëóZ¬õÿy…ÝîÒBnøµìÚÍûª4w)$0®~Z¥û¾lÀ:™J•ÑÆ˜‹v¹â;Uú~½³Æ^0ô¸j 3gœý±»Js†F›ì?:7R×6:š&ÐqÅ*•¾kùÊ|T_Ý·ïù'ö®ªTµ(~À>Õ³€Jóµ:Ù“Ö´>É÷ø¹wñÀ€!MT™ïo“.0÷ß™ê¾çÖåäm»_iYŽV¬}TXÙµ} Þ·¿iWO¥eþåćK¼HKü~ø]ìÉßTõeý‘mM:¨4}|Þ‰¥gûøM|QÏ·Í·NkÑÙÏ÷°2¿wì®ǵY[Òwkí©Å*ÔákǯX»Ýòsª®Õ¾¼¢Núù)U|ÿ4ø½ÎÍ\_«k;†Òø‡ÏùS]û^ôâã÷ûûÕµi/µ©“,sv¥m Ý­u"ÅßêÚS7~¯3r‰z¶z ?¨Sªæumúë…üÏúI¥å“5ü­zý£âË;¦–¿Êžu*>ÿEüY›®Vñ%ÍÓÉŸ$.‰ ÷ã­aþàË©T¸7v¾é?W0èç2êšlŸ]ú—TM˜$à·ÿQuãýQwíK‡ªzðg G`@¦Ãµ9¾j7û/¾S‘îë{~{ÀQ»Ö¥µêN,·EçTñxü‡ì³Ñ*Üßÿ-ñ×ÿ¢šŸµßï´?¬ôP÷ }þ²OVë¢Ûôªùþ"y«<(˜áMÿº]”vúÙÿÜÀ uÌ=—Û–¾ªÚù©ûí‡÷«{4Ÿ²¿ZÓ\µóON¯öïÛ:Wåó/£ƒOPמœ6Ë¿pñ4ußœg£ïäȦÂ]:yÈÿgÕ>ÖïÌXÖé‚Ê«¢-3f×[¯ê½Uæ¬ÿ¥_Ê©ôÅå³}eõ=ÊŽ¶´|[õ=GJÏ·oÿM¥ïFî¤2¥Ë«k-ð–~4N=Ûû/}bW«5R…{ê9Ü‚"*-V»vvèÆªÜÎÝ\h'þísuߨŒÚÿÜn¤Ê­ÕÜãþÄý“©øê¾|ÁÞzc› {s‘Ý<÷{*ÿ5xjwëÒæƒy' ÌS÷Vúº¿ö‡*Ÿƒ¾è@á/êÚ*o§œZ[—Q²·í©?öWÏ6ûçóþ_°S,i«Ò²hG»ÈýjŒsíQÖ@ô_yT½[+‹]á“‘*¯.mOo_ÝQ×.ïø»ýð³…êG–²«¤MªÇ¡eSJdž¬Òüóüöà¶©U¸ygûÛŸìyMåi®|ì7,¿ºÇ©ùì«¥P×~õð7ûÙ›CT¸3¯®²ís)•Ý8ºâw;g!ߊ½¹íÏÿ?ÒÞNŽâhïÙ;%DYd!ˆ#*…v%H $‘ÇÞíÞÝr{»§Ý½$²É`’1`&˜l0Á`r„I&‘s&&|ÏSÝ=S}è}ß÷ÿŸTÓÏÔT÷tîêêÞžQAxuSͤÎûñì'myí[ïg-\¼1óyIÇf“>]÷Œ ^-wË™™{GîØÇ‡½ùŸÌ¹£NòùšËÖ›4àÒã‚|¹b^cæ±ãgí÷àÍÌl=zn0<œÝ-3@{Ðo¼»í¬Ì´kF†kT—\‘™³Ç A:Ú/[yRñó“‚÷žòÖÀIÜ6»¢ð‡Ì1÷n}~/×éŽÙÀ®rï ×å™\í®A&ùÛAá´“‰Lò»hz÷ûxˆOTüïæš©ß7H|¼âŸ®ð.n²Þ$¿"ö{ªˆÿ¦ðÆ‘•`’߯ ˆc›Ýh¼ªâïêÞE¼›ÃL“ÿMû •v.túß×oèÂáú¸ß“Mì+ñ¶N†ûý~âKLÂßÒÉôÿþ›?ït¨Š÷ùß‚¨ø þƒ’ù·ã3lÿ 7â­ß¿‹kì‡+ì÷¦ÿGñ¿U¸ÞÅŸûlý~^âcLÂÿJñwtòŒ‹ÿޱ߻AÜ °'×úýok‰+ Ÿ¯d¶våȽ>k™ûßQÿQá{”Ì!ÎïªJ~Uã[„ÅKœ<÷ Tö¿!þâûÅ|âI ïîòûÕüo§‰wVØŸ+N¼ƒóË<óߦ#ÞÀ$|Ÿ‡Ü§²žÂç*|©óK¼‹÷eøºDì¿B|—Â÷*™žêâ¦Ï'ö¿+ èÞµ¶I~KϽ:yâ§©Âû»ð¹‡ÃŸA|­Âo™Df¤–wx=•ëÅù`ñÛ.â.žÜCöµIðþŽÏ¸odìó|„Iê$ñë'¿Ç¶uj‰Â¾¾±~]fì÷5RÉëßcS9ð{«‰ÏPxt”ÈìåðÆqÜì>¬÷LÂßÚÉpo«ÿý±ÿ½Ê¦&ù=á¦ê]Äç(ìûUâM\º_ÿí>Öñ…}Ýæsû6ÿûvî]%x¶ÃÜGu±IðC.â'~ZÉü¨øË¹¸ñþÜ­UÚ‰ý÷$ˆ)ü©Âûºø°>žìøÄƒß×CîGòߌ"ögëäøŒ‹ÿm<÷ÎÞ¨ð[s»?›ø&…ßQ2>߯Çùf÷6ù~ø}‡Ù§úßVq’ßJ¼A”ð')ì÷1¾^àØø…7t2ü-€ÿí+qYá L"s«ÂO(œráÈ™é.TÊüï ‰wq|¶3ÿ[¯]T‰}[£båÛ5ñrQ‚×s2“üæøÏ ?ïâÆýšG)ìÇJâ[þHÉ4ºð¹¯ý_N†x”‹¿âÇ_â£ö¿[#öcî~³ÎŸÝCÞ4…ý~Vb¿•ÏýyÄ»)¾–ñûYõ÷îèÎPØËç»>C½—x–Â^~wçä;u–çågšäLý:ý{iî=ž­°?7¼½ö¿MØ[ÉpOá<…ýoÅû#n_çW#Ž{VØÿ–˜õ½UáKœ_b_Ÿ‰·TxœÃì'|ÿ@üœ ‡ø¿ŽÏ>rÂþwzüI¯Âk»zÂ8jì÷sl’ßp/êóN†xH”à-\ܸ7ד‚øu…ßSx%ç—øP‡©ƒûq„ØëÞÄ{9Ì8úóUñäo%Ê ¿ádˆç»ðõ™àM*L†—sòÍ*Lb¿GœÏóN&ׂÂþì~Êú3DˆÛÿX…½_öÙ7)¼Ha?®û1…uÇ× â´ãsß·/#â-¿`’ïS?Æ…O|‘â?¢ø_9~ÿßoûøsOóê.|âížëâÆ9ŸŸëg¾¯?ý¿_çó¶¤ÞŲ½Ua_¾Ä?(þ|÷^†çÏå!öu¸S…Ïöño'CÝçuÇ'~Oa?_ .ï.z½ã×LÒ®»” ÇI?>{}ž:ŽÿM;ÛâR÷.âµ£{}’sÜ¿9yöýG+ü­ÂõÎ/Ç=?_&öóe¦ûXÇ'ö¿çµXa?¢ð 7º¸1.þ»WĸpŽ1I]"^ÙÉóý'8þ®ô5…ÿë0õ,¯__¥°ÿ^m¢¯áÂ?^¥÷•FöI¯+ìûŽá~¼–oÝ(¾×ÍôoÚ‰_t˜¼3~Á…sZ,c÷ÛïìÂ$>ØaöC^7&öçGÿKáÑ.|ÿ­û™ê]Äo*ü®Â*ü±Ã´‘øºDüŠÂ»w1ï½½‚øS‡ÏQñ$ÞÄ¥EÓø1÷.âWöñäëQ…ßVØ—#±Ÿ{ò7^Ÿ'öúuR?7á¾zžñó÷—)ìu?Êþݽ÷“è“Ä~ü%ãÂgúüïö‰pòÄ+ìÓÎ6áë?m-¾Ÿ¹Ø$ó Žù?™ûwû±þR“Ôsb¯Ç2M~x™Iæ€ÔßßWx ó˸ûóˆ½!ýr•–+Lr¾ñ?ßëêľŸ¿Ò$ýq¤øÞÁ¶ëÛ,ñýNžº°·{½÷“Ì8w¿Qa?g:ü¹Ri!®sáð7©þüâaQ‚3Jf…røz“Øè¨×?¯ðH߯¿ñø½“!þYaŸUü9Î/r~‰ý¼ŒáýUá;<ñ7 ûwQüHaßrœ|Báþ«IÎt`Þ<£°O;ñÁ³l}9ÒŸ?;ƒøK“ð}ÜhúÀÉPö>…½<ñ &m?‡¸ü¤~ú¸I°·1ŒŸ¸Nñ}8,+oG]d’þŠx_'Ãñí9“àÏœ ñŠïõg¾óa'Ã~"%xs…Ǹði£zÈÉ?mþzQÂ÷v*ÖqߦèïIç÷!å—ïÌñÙ—ø1”}§·GPü5\˜ô÷”“!öýð?M¢³Ïu˜y?ÕaÆåGç—a¼ °‡øc…?w˜cר(Á£žå0ëÝjî]Ä;+¾¯{Ô‰ÖVxŠ“'ž®ø>?Ÿ5‰nI̺ð…I°/w¶u?î?o’y óÀû/¨´¿Ë¼Ã/›¤ÏyY¥—x¦ “c¯_›`¾¾iü¹ÃÔ>SØÇóu“è¨ô÷®“yKżŸ²~ÎÅñÁ ÄÞîÁ¶ëëÀ‡qGJó‰Ã«¸}¢òð37¶õoŸx “ó oÛ§}ÅÛRˆ}9Òß÷Î/LJoö:'ËÙ—/±/_úûÙɳÏóó>Öe?æþh’öȱws…}[&çø ¯ÎaêûÞÆÅ±ÎÛšØ7xyÊúô²]úöHìõRæ½ï÷˜_ÇGŸ'Cá.ïdˆ7s˜¼^ÑÉoªðf¯ËŒw…½<ëiFa_?)»–“'^Gñ7R؇Cûî& ï¦ð~³쬰û$?gù¾b¤à½^+ŽÃHé¦;LÞº û¸­ã‘’¯¾Ž­Çm¤àý¦MÔÛBÙ7o§°ï'ÙÖýzÁFqÚGJŸç㼉 sSUv££¤­ÒÕw+…':̺éë$çú~ŽOÙ± Ot2Äsžç0eÇ;yâ=ßËóùöN†x'ÅŸ¡°÷»*¯ícù‘âNTxš“ÙI…³s\î#û>B”ôóTù2¼ÉNf¢ “uv'“Qa²zûóäX~¤àyïªê±_™%ãË´8Î#EÖ×áq>Œ”÷ °×£fÅåkeç8™9*ôw ÂÞï1)®Ÿ3rMþ¡µŒáo{¹.À4Òî˜Ø$ù—|/1á Ûfb÷´r´qÎxâoiêó hãÕvav„3/‘KìÂÉù)±ÁÎ ä"yNþ Åóö_ÞžN&ùmuJìÁ3¹± z7å×Û«“ßÎŒÛô*<Ú³hË«ôz»Pòm¿HÆ’¬ÑçzDÒWÐ&7^ñXîZïáŸ_Óþ*æØïL·ïµ¶mäî¶ûÄVlãLÛDÆ$ó¾—sÎÕS<ö‰¾jýr¼Iô Ëóçù«üzÛ[rFFJÆwŽó‹ÏÛ™“¼²ñg:rJîÇOx‘Ìéôº¬ÏÓd}Êúõ¶*í—ýp¢oñ¯Nä(Ó¬Þë¿|¤òëm€‰œµ òþPå—sê ]ë÷<Ž#ÔW&*õÐÄ^gyÔ£ôz8ÿX^ÉÒʱ|´ÍÁ—ybÓåß@Y»×{ ˜Úæ“5›. «øQ¯ãÜLkÛï©Ñçtù>=9«¢^Ê<ÑAmx&\àŸ×)Qi㜔kc”ßKQkè–Gû©¶Ñ²M/2FÙ»­œ·ÕTm‹ñ{Îè³%R±-姘Åç½óêD‡HÖC,y¯÷âÐ/ó$™7Y9ÚÔ´Ír/˜ÐöÇüó¶ºMò÷±ã=¥âìuž½ãw üÌÀo}l¯$æE±ü¬J‡·»§óÃÄÆfßëç’ÉY‘ÔÇĆfý²liOZ+æÕË<àã Qlw|7æÙ6£ç¾”ó6Ÿÿ(9Úòô>Ê1­z“<ÚR´=ˆ<¦Aïß :y* Ëò"£íÔö½œ‹ëõhÊq¾ôzk_?Üè3ëã9ÐQ&ñë÷$%çŤD¿Ð{2(çõÊíÔ{½ ÷Må—¶Ó3^ÏŸêÇãýcÊ/m!‹Œ>&Š÷kœ¡x~ÖaʯßÓõm?ïW<¶µÍƒö–Š÷6$gªÔǶ®d¼¬‹÷®U~ÙFEÞnãçmäç(¿Þ¦üªòëmÎIX{ŠÞGÄðØ/ë=MŒŸßϨ÷2²,õ^8{Œµ½^¦ââ¿©ý˜’óóÔäü²T¼®|ç׆¯÷óù6¨÷6ðϯ•žsêb›óÃ1/%6f½…áy{S¢ûX;¤Þ/Â?æ‘ÞOÅ?oã~ æ¤Än|aÀ‹â3i’}¡¤m°^¬ä¹w·(Û>ÛÚÊêÔ¹ôúžŒÆ–çCÊ/õ²7Lxæû—I&±+SΗk¼Áãª×ýUxÞ&o6G\gŽE[+u(ŽGó6èË¿Q¼WM÷ìo’=¢6Î~Òr*ïé'Ùgfåh<Æè>l@l¯S~Yæ‰Mߦw´kWIÛO‰úOßHl¼×éðsè$.VLÖœmü9w÷{ÃûYñü^–£ïu£÷ÉÙð¨G$û ¬çc,»äŒ¯(Þ7«û{¿×o•/Þ&u·’c¨÷ÉñÏÛ+ž_³‡—’v®mŽüóëß›DŽõŒïiT<öz-ÊoÛ’óJœß;•ßo\ZîT~ýþ»¤Ÿ´kz‚rœ;rMz{Å£N¦mÈäÑfu©ÑúZ$ë8œg$g]”qlõ@wLÅkß(žß¨Ç¿¾‘¤Ãê‘\X¥Ÿe’sʘ¯÷¯òÏÛøtÿç÷¢¼§ä8žëýÌ”£í,±·ñ¯.¶§mªÊœú}²faãÂ~)Y°rœ“%{-iKö[çz'ÿØ%kíVn7WçWU<¿a€Š‹ßg›ä_JìU´‰­£ÒÆ4‘¿ŠÊ+oßKäLl™¢ôS¿6¬u ¿ÿçuõ^Ö¡ã?=Ñå1Ê&mãìmŒk)Û_²OÀÆÙïÃXM½wS—†U¾\jÂ}ξ|7 ä’}¡?šÄ/ÇÝd_¢åu£~¯`yÞ»‚Š3ëç\É|+Š÷­&óäñ¾Ä#v»ÄhÓë÷[¨Â£}âAxu±^ë¢\_à:ƒ>o–s5½6Ì?ŽÓ‹¿©xÿŠ>G–õ”uô÷1o`ü;€D—¤í²êöë÷X&õÞÚØ&é¤|õ¾x/G™Tùú}Êz¾à×ΓrKl¡s”_ê[ú·ôë÷ ?i9ÚH· üFñ~rvá@± N âÅöÕ=Õ{ý~ð”_¿'£^Å…í[ï“öóŠ£m)YûL~_by~_ë!Ê/m·cƒ¸Dñ¾-ý‹¶×ókÈÔ­vRïð¶à*m~¿÷&Q(7#È—d@ç(¶9o¯Úuåd¿´å±ÝsUÒöëÄFJ›éQÈãý*.œïëýVüã<#ÙkkýR¯h4Z·HIx ë:åׯ­k› ß—”Œ¡õñ>ƒŒŠ‹ÿÝA2‡M‰N§#ÃðüÚ¶>c“ºVÆø=ÇÖ¯ß×0L½—m•u!ioQü[ž­”߃"½_ÂòØ×'ë®–ç׉f*ž_çLxQl+__•Ã[;ÒyÉú×Ñ®Tiók`‰}­>Þç³²òK;!m„[ļ^²'ÅÆkLzÍ•~ýoÂÎRácL°ÿ‘l«ú73üókV;«<à|5Yϱ<Æûü6Sic_hÂs¥YFÉ_ÚûY&IyDÂKölX9Æomžßí×>’>»^ÆýÛ:þùßöè3^ý>¨”œ_«ßYåŸÿmÒ$Żݥ59[;%å–ü&‹%zÍŸñïžTþùý,‰]/’¸ÝÄ/’z¦×™^¿ç(ѹL¼÷.yïé#“ß<Ø<`º=HGò»‚„7 S’±+ï= Ò6ÉØyË-1§>Öë’ùŒ‰Ï‚åù¯þ,ØCG.̳a™ÙÅlI¯Ø?ß7Œ˜vç/Îx¶áÒÁ#F&gÁfp¿hÃ¥¿ÓõŽT2ïþÚ…÷ßñÑõ‹yå§+d.šöO$åÿþ,Øaî½ä}{Š= v¶‹Ó¶îoþaîýÛTÎøpøm{ûŽcî×<´ØûÖÚeI«ûy÷×ZtVû±_¾ƒùÉ4û3Ü}|««s˜¼”Ã)Å—ïÙ1Ǩ|©sòö~¥¸ Yn¾ ½t0ËÔÇÉ•áVÛl“XÅùçÏ1ÿlÊ/ËpÿÞ¦I'ã~·ÿ÷2d|©­¢xŒÏÅÏv/þ÷G ñþÞ ·O:êø/2ÿ/eȸø°^ÿµ-ó"§mÝ{ï˜úifØz‡e|8?ý|ûIË/yó¼â"Í8o­%¡\ÝÏ´ô.^¡ü»@®qŸ»­ö¯cÚ#‹ï›Z¬ý>ÞûÉ¢«784û©4þ¾~Ü>;å’kïõòùÜÓ« XrÈ=ø‹‘_.Ò~‡-^¼øwµr 7þ¥™é›ÖÓvõ[ßÿ»õ xŸæf.>ëþo—ß¾¸èä·†ñ›´ù%õ«×¼—þôäâζžÀ﫯²ä˜ÚÅ÷hÞÜÝnÉœÝqãýšÇ2ºeÄ:Ã6°±{æë:ÿt=YÕñYÆ^"¢ðP…WTx˜ò»ŠÂ~ -¥øl?¾/§ø+:\¯â@¼¼Â+(™•`’ßfûo‰T~ªð*¿U<Åòö7Þþ]ƒU<«w Vù0DåÏ•'CT|†*ù¡&Ñm–7É7b–7IY¬¢0˳ ™Ê>aŒIÊ.e‚ï¤|ZÔLx¼OúöTʧ[õ÷)ÿne_K­èî#Åóå“|Ci ø%/ÑsLj—ž„WŸòyœ|g@jˆÑõȆç¿3’èÀFâ¢ë!yCŒ²!§|}HxÄ/yƒ•œ¯s /Jùú™|Ûg`Ê÷ñì×}?l󥃹¬>>Ñ|ŒŠkÛÁýEß½h³¥ƒŸlHÂø ÷ ÿ߯iöñ#ºK–žÙÇð)ÇÓÿû>žqñaù3Ûg»8ùqú—}|êç®?'³dI×"Íûe¿_·Œ~?§™æÿ¿ã4óñÿfœf¹m£äX¦>N³¦ÎË÷&¼ ò—ïùå8=x‹¥ƒ3'aì€ûm&ÿïeÈuÛÑ)mϳï(¯rwúÙÞ‚Lƒˆÿ{Ô‡ÿ_Êqñay]ë±Õmœ¶uïÝà„Í36\÷ÞcR?oÕ¾iæ±ü»Áy#×<¸QæÜ_ xsî‘yþò‡Þ燮ŸYÍÜðv{cÝÌ£¯ü6à­wàºxïaïî—×ÍÝ4à:gýÌzu/çKÝɈÌç—ÞÉ×n”pÒ­ÁùMó6Í|-¼Kó˜Þ{k«çœLxmëÌŸ —ro_9.óæÄ?á¿h»ÌÍ•¶ð½kì˜Y¾qiÀ›æN™9_m¤£¼ÊοHï—§í”yöœsÞ…CwÌ ÿ Ì¿ÕoØ.Sk{8à =k\føÎ/¼Íß:³í©a¹Ý[Û<³Ã)‹Þ=£·Ê,ùì¾€wû‰ÛdŸx{Àû䈱™¡Ï]ð.ûn\桼•?Ÿ™øö)ïÈô¶_w=oñgã3CWÝ9à-:>3ãÊUÞUŽÍ¬qÃ{AžnpÝ6™ß]rGÀÛjêV™a¥ Ó[m;;àðÒèÌí¯„rç_°IæÔaw¼ãÊ,ØåÀ÷òAeŸ½z¿m™yòî o¥-Gþ¢|»™¾Í©oTóF™‹æß?•éx/ÌçM¯Ý$óÖ©ay¼óîèÌüÏÃr[yÿ;'Þò‡­ƒ3„Öª?¯/•,¹ï}l——úùáxzVðŽi·}ù Þ‡›¬œîï÷øE ýxæç¾®š8sû!Aüò;¿6ñ‰ÿœ„7ùÐü/xöœ“>ãü­¿åvîÇK ¯ÿ{é·üî\ÿ„_„wo­ú‹ðÈëýöoà±Oß¹þ€°ïÜzIú¡W?êÐè×îK?{ñãoöéw§z&¬Ï©íîH_þü5ï‚¥·¦GE—¼jÛÍé·¯ ëó¬é×§³½—‡m潫Ów<Öñ»g\‘Þá”7Þ—¥‡ß14Èûó¹$ýí–[¼ÃW»8Ý]^帀wMî’ô¸ž Æ™g]•ž¸Õ’4ïŒóoH‡ã–ùù•­oI¾õ·w'¼ÔÏ/ì}{zÖï÷¹[Ë]ºöÝ|opöÝ>Wß—¾þ’BðÞ5V_’ôÖuü€Çq®ß÷âô‚]Â~í¸Â%xÇ…aù®uYº¶áµïÀÜåé»g„g`¯´ÛU飻'ིäÚôMá¸õÅÓÆ;xsúÆé¡Ü%ßš^Õ0¼_oOO»í–p,k¹3}såšpL¾ù®ô{§\ðÎÛõî_¤÷ß{›Ì>o½ðþöõûé—úyöo¤ÓÅ·¹¾ß¼”nšÖñ«/|6ýüåO¼]>}:}׋ÞåW?™Þ¨ïÏoÂkO¤7?)¬§«}ýDzøg¼‹·{2>âÄ€‡w¦3Ûð˜ðTº{fgÀ;$z:=bbsÀ»îó§Ó—Û/à-·þ3éû¶Ü#à­Ó½4}󿙀÷òwϦתß.àíyíóé¯oÛ"à-8þÅôÔ)£ÞÔÓ^N¹~Ý_ðî¿dí€wÓ×/¤ÿ2mµð½÷>—nº!ìë.þtiúÃM¢€÷ØyϤ0¡.°ÓýÿJ?¸úýô¥WÚò/¯xá¿ÒÓS¼™+?“þͧ¼5_x&}øj¡{Ê×KÓÛ=:=Ô' Ï¥?;vð¿ßþ…ôYK¾Úê~&ÝZAÀ;xÐSé'>!hû•]gô%'ìöXºûÈ5‚ïÌÚðÑôN½Ç¼ã=’^õ¸EïâËMozíÀû4ïÛ-Oÿuöè€7zÌÓéýwœðõ\z|·ïû¯¤{º%à•~‡qV¼ÔÏ{oþqúdÓÈõ½ðeÚ<†·í¸ïÒo. ßûÀ†?¦O:cÓ€×tÆÏé=~[×/Î&ƒò Ò{‘1™Ó¨¼¯û)ýÆFCÞr×ÿ¾øÓMƒ|þîøïÒs”Ñô‰_§Ïø×Ò€×{ß§ã× ÊüÓ¦—»'ð^_õÝô陿€÷ÙÕo¦—{.gózúŠôùï‡[_M·ž}ÀËlûjúª ÿð¶¼–þ`OÞ¯N}3íHõkÓï¦/øý€·Â ÿNopÛÊï‚u?Oþþoб_§WÞÇ€÷þÒoÒcŸ›ð®_óÛô¥{ìðÆ£|û>h xùÕ¿O¿ðv_ÀqÝ÷éïû¿o|ŸÞ³é¬€÷Â}ß§/¿è÷áx4ûûô+þ1àí}úwéÝ—ÿSÀwØ·éµúÍߎzå›ôëßÞÎ!^ù*=ÿÌ%¿Súóž¿ü³4õyÍ{cÊgé£×Ç£yÛ~š>¤ttÀÛá”Ñ·—Þoç}”>£!ðJ×½Ÿ÷^¨Ã=vÙ;xï¾ýæöo¦ç/ åþñ›×Ò—ýñÐPošþJz­;Þòg½”Ž><2àeŽx1ý÷ÍÃyãŸ×}1ýÕ¡­`Ü /¦_ó’€÷Íu/¥¯^ê÷Ö^a_ðæ<ðZúÕÛï禇¿™~ñ«{úÕ¿wÒw‡s«¯{?½ùÏ¡ÜÅÃ>JßújÞws?NTøÞ×ø4ýÛaݸtçÏÒk^si¿yÏ׿èOÿþöWéôIï¼Ç~™þyóú oZgëÏ¡û¬ð[ñ“ômo­ö‰˜^çŸ#Óûî“#Þ€;^Og åj÷¿œ~ýž0¼[þðBú¢¿ xð\zϯSo½o—¦/~øÍ ƒŽ]šþ÷Þw¼U?[šžqæÙïê­žKqQcÀûp“ØŸ¼¼”N=óß ]ÿãWÓßý`À›æ›Ðco x_æßMrÄýoë³?LO>ô€wõ…Ÿ -„cã'+}‘þçc3Þ…½_¥÷]ñô€‡ùa¦¿NHžQ”{÷ÉåúñRÂ{þòP{h¥¡™O x/šùfthSúÜò™ß•ÂúwvzÅÌVí x•Vʼ¹0¬ã‹Y9óòwa[˜pò*™9;‡¼³«f¾[3ôû̬Õ2;ݶ&­ž9j|¨óo3~Ì–÷Þ¶µ×Ì„úx ýÁÚè·ÜîŸÏü4ìù€÷Ô£k"¼WÃ6x홎÷BÝûÄSVÏ4Î%7i[-sÓß>è§ó¯ú »èꮜ¹rÅP.wú°Ìj¿Îg¶\)óÕ¡~ÙC+d>ÿé©Pço\>së‚p>sÝçËe>Ü$?X–Åë?ÿ }÷õµŒ¡½™öóÑË8¯yM‡µýœØï‰Lò=cmW'^]ñ½<Ÿ×;™:%C<\a¿?”²œ<ñ–Š¿•Â^ž²<ñ抿…Â>Êúó¦‰ßûåóÁN†x´âo¦°÷KÙ!NžxÅßTaeýú ñJŠ?JáöaÒŸ_O$^Qñ}8|î×%“ó M°ž˜¬©ÙsœýZçŠ&Yë¤;La¿ÿˆx#…}œ)ë×.‰G(þ† ûp(ë×y‰×Wü öáèõMâõßûåóÕœ ñ:Š¿®ÂÞ/eWwòÄk)þÚ ûp(ëÏ›&®øÞ/Ÿûv4<æ[¼µÃk™äüåµãðí9Åë:¼nO{¦ðú¯o’³7ˆóÇž¼¡ÃŸÏöü_Ö0ÝQÓÝØaº›8LwS‡éúó‚éú3¦éú3yéúóÄéná0Ý-¦ëÏçÝJå×ÖÆ(ìßD¼½â{cדœ·KwœÂþ7cc•<±ß 6.–±gÚn«°ÿ†÷x%Ïçþ¬ðmM²_n[%¿Šçöê½Û+™Lræûqøö|[9Ÿ °ŸLOtü 1ßžEëù4_3Eá6‡ûŸ ÛæÂ$OŸ ëùýÏõ|}ÞëtÅïö«ç÷?ûµQñ½Œ>ïuw%“œýjÏõüþg¿¢ø^FŸK<_ñ½<ŸïådöT2ýÏ=Xñ½Lÿ3dVü.‡õy²ÄUů)ìå);×Éw*þ…+ û0ûŸW»¿â pYa~ÿ3m÷S|Ž>ßv%³oŒíY·þLçýMr¶5Ý.9¿¨øðùAN†¸]ñ‹ w(ìá?Þ.qAñS؇IÙùNþ`%OìË‚Ïq2tý·"誰¯ÃäeŸ¸Eñ[öò”õçÞç?¯°‡²þ Ü&%¯Ï±ÕçÕæc¿ö Yîp«Iú„Bœ?ûof’scé¦Ûá0]>,]~7]®+]ÿͺþ|ºþ›tý™­5þ¥Gaÿ{}bV`IÎ5¦Û§°?Ç<ÿ½>Å'ïpÇ'~Pñ½ ŸûóÄW2Ä/(ìûOÙ#<ñ³ŠÿœÂÏ+ìá¿£œ_âg©Â>LÊú3a‰ÿ¥øÞ/ŸãdˆŸV|/ÏçÇ:™c” y¿r|â§ßËð¹?ŸøIÅ÷ò|î¿éBü¸â?¡°÷KÙœ<ñÝŠÂ>Êú³†‰ïR|ï—ÏOr2Äw*¾—çs¶ûIJ†<žìÉŠOÞ©ŽO|‡â{™þgÈzò~íø§)>yþ _âÛßËðùN†ø¯Š›ÂÞ/eýyµÄ·*¾÷Ëçg9™3• yg;>ñ-ŠïeøÜŸ}LüÅ÷ò|~Ž“!¾Yñ½<Ÿû³n‰oR|/Ïçç:âßËóùyN†øÅ÷ò|î¿m@ügÅ÷ò|þ;'C|½â{y>ÿ½“!¾Nñ½<Ÿû3j¯dˆ?WØŸGIY®.ñ§Šÿ™ÂÞ/eýYÞÄ+þ' ûp(ë¿Dü‘âÿ[ae/vòÄ(þ‡ ûp(ë¿cD|¥â_¥ð» ¿§ðû ûw1¼K]˜—¨0É»Ìñ‰¯P|/ÃçþûÄ—+¾—ÿ£IÎù½<æÛóp¯tøJ“|û„îÕ û3:ˆßRøm…ßQاaø³w‰_Wü7öáSÖÛæ%Oì‡ÉçþÌ_â¯ÿ…½÷߯ ëÏí¥ëÏö¥{“ÃtýÓtý»tý73èÞê0]f.]æ/]61]V2].]ÿí"ºþ|[ºþ»DtïUØŸïAüO…ýDÙûœ<ñ£Šïýò¹?™øÅ÷ò|¾ÈÉ?¬ø^žÏ;â‡ßËó¹?óz±’!ö¿©æsÆîÅ'ÏŸNüªâ{>ÿ»“!~Yñ_QØû¥ìƒNžøEÅIae½Ž÷ ’È$çó>d’säÉógÐÓ}Ôaºþ,]ºÿt˜®?w˜®?7™®?“—®?K—®ÿn]V;]ž2]ÿm*ºÏ:L׫ƒ®ÿN]Æ®>göÅ8OìÙ²/;ü²IÎm%Î[{n¬Ï‡×Mòâÿ8Lž?g–®ÿn]¦0Ýw¦ëÏ–¥ë¿ E×;‡®?÷™®?s–®ÿv]:]¶,]¶,]v3]î-]æ,]æ,Ý/¦ë¿WA׿‡®?‹ö•<Ãè;…ý¹óäùóg‰ý™¶Ä?(ü£Â«E ^]aÿàïMr6÷Mr÷&9g™îO û0ÉógÚþ¤øÂsqþYñÉóç°›Hí+>÷çYV|/ÏçþÜÛ”’!Ï[¨Nñë£äêzÅ'Ï×m€â“çÏɨøƒ¢ä t‡(ìϨ¬âÉçþ{Ä++¾—çó¡Nf9%ÓÿŒÝaŠïeúŸ·»’â{y}Æî JfÅ(9sy¥(9zX”œå½r”œÉ»J”|#mÕ(93š®?³›®¯«\ó9bucø›ÚNé‡6Qâä|©:ái;«q8±Ãò/ÛVõïüwt<}NŒ·»&çx%¶Õ•_o{Ý6æÕÇöÕí•_oßÕçÝlçü%rÄ.J;i¼¡ iÛÅh;ªõKhÆèsžê„—ØL­mT´Yí£äös÷óT:h¿Ú/àEÂóg¯z9Ú°öx‘ð´­Í8¬mnÌ—NÇKÎbµgkjÃ+™ÐVF¿Þþ¥Ï[àŸ£üz›™>£‡ö—Ë£L»’£m¦ÒOŽv´9{veöV~½½MŸ-GûN5‹b]AÉÑTë'GÛÜA\$rþ<[ï×Ûóºúñº9kß#/ž·õ&rõ"G¾>ßv¾»Ÿ¥x‡¸0ž=ÇŸ…ëåh{Oìòü«‹ÏßmS~i[<Ä„çï6šþçê¦âszûû¥ÌîJ޶úiýäüY¹ýýúóv½_o¹ÏÚ7ûÉêîõY¶‡ºûÅË:ÿú|8oÿÌ÷“ã½>g–öЬ ÏŠõ6Òä¼×b¤Í°;æÕ /±)Úðh'ì x‘ØûúñhûÓ¶Cò4¡ ‘uÈÛ“3B-&ïïê½´jÛ"Ã{Á„6F†÷’»ÿ»’£~øR?ž·/&ç´Ù³;(ó7Å£>ùrÀ‹b;åsJŽºæ+ˣ̳ýä(£Ï¤íòˆ@.½õUž'øš»_ÒÏ/ý-U¼×œÌbÅós‚„ÅöÓgúÉQf‘âÑnzd ɼâ¡@.Ší«ÿR~v2÷+m¬G™ðÚgé'çm¶úìÙG¿{vÛcMx¾(çMrQlßÕg&=ædîQ<ÚuÈE2÷z,‹bûïÊ/çeÿ\†eWr´ð¢Ø>œøMìÇú|Â_Ÿ èíÆw)9Ú‰OxQl;ÖgóÑn|¢ Ïæ£Íø¤~<ÚˆO^÷wŒO xəƚGûðiËàñ^Ÿ‹C»ð¯^ÛŠoë'Çû¿*íŧ¼(¶!ߪäh?>#àEb/>s<ÞߢüÒf|VÀ‹b;ò_”íÆg¼(¶%߬äh;þMÀ‹b{òMJŽöãs^Û”oTr´!ÿ6àE±]ù%G;ò¹/ŠmËúü&Ú’Ï xQl_Ög{Ñž|¾ ÏÎò6æë”íÈ¿ xQlsþÂ$_˜Ð^Ç1åKÇû“ vfm§fxŸ›Ð^M¿_¹°þ¤ä¼ZŸ!ÎyùWˣ̧ýä(s­âqÿuÀ‹Ä®}Aà7ŠmÝŸ(¿œÿ³ ¿”ù¸Ÿe®Q<ÚÂ/ 䢨¶rây›ù¿•ß×ÌÕý£Œ>×”öó‹^$6›×¿QlgÿPù¥=çeÈQæƒ~r”¹Jñhÿy3àÙsîþøb[üûÊ/íEo-Ã/eÞSr´%½½ 9Êèó‰ßY†Ü»/YG¸Rù½Äñ¯T~/5&X+ð<ÞëoApàÒ€Åk—+9®\ðÈü><²Nx+Ä6ëw˜³ $¼HxþÜQ/GûQb—²áy›ÒêJnegWªÂ[ÙÝ/×On¹HŸQ›{ÃÊÏžý9$Ògî¥Ä®°JÀ³çò>Šy&¶%éoxÛQây»Q½ây›ÑÅóö¢ŠçmEƒbÞ@±ˆÝDÅÏÛ¾"åw5'£Ï ^ÍÝÿ¤xÞŽÛÔ÷É¡&¶Ó%~ëcÛ`rfu*¶þ·÷É™¼ãè¯óêâ=¹k(¿þ,‹„Åûrõùkþ܋Օœß§›œMj±ÞãÈt¬åxÉ9‹)Ù›«÷ó2¼­M¸ßWÊÒÉè3×váë3[ý¾ß-•÷H®ÝOnw¯¿Ã1À˜`1åü^à-”÷Y®øâýÛ+9îÁ\·ŸÜzî^Ÿ¡Ë½Ä¿Q¼¿XŸ÷Ï}œë™ðüSî+ÈEñ^ãÍúù¥?}:÷‚®oÂ3ýže}èc÷j9îOdÂo‡Œp2Ô_¿ySÅÛÐØ=¨Ã”_¿÷y%Ç}¨ö“ãÞæÁœ=;Ÿ2+)¿~ôƊǽ¬#¹(Þ7=JÉo´ ¹QÏî¡ÒOÎï«^1æÙsa— xQ¼·z%Ç=ÖCÞ3}æ^“Ù®éøêþ>cÛhÛv>ë†ÇG®w:f„Ý1?eÏIcæ•1§|ô¶øœ–¹`î9iÖÔFT’†Ÿiè¬ä»MCK¡RÅM1‹k¯é3 Méí(”pÉ➨žz 9šL)Û‘?hìøù¦«jZŠÙVSh.—ñ”…\S±ÜÜ΋ù\¶–õâÛÌ7d%wµrÍtfs¦¹«ÒçÕˆÏZ_gÞTÛÊ=íù>ÓY®ÊólÑ?›«4—syúÍó¦AÞÐГ/´¶ÕªöUãÆÎ7Ý­•rW§Àj±ËW˜‡˜šJ¾…Á3Œj­"r‚ óÆÅ¿ÐYF"*後ÂÕbW¥³Í44T›+…N¼­AŸm®YåB6•òx^ÆÛj‰F ¸40~’eˆ*EªÆ^Æ¢i¨æ‹E&·Ù5›†®R®ÜØÔÕb0/HPÍåŽNæ°‘8WóùvdfµšïÌVjÙbg[–y;Æ4 UdÝ|)ǸTM¹Rk+7V›³Å¼ÉU²=ÄÓså–\0Û™¯Ôº*Ânjo“Ì·°©­:XA Ú#í¦ùÚ\³¥0f;qC¶T@!˜††ŽBgG¶ó 1à—Û k\K…ùQë̶æ%+‘MD²·’ï4}¼ÔzùZ£ÎGRøxK§È5tf›Ûó9V+[Ÿ ù ¸«õ"oayÄhT;ó@•|5ꆜñh¬©å{›Ëq«¹k)ß*–“d7”›c² g:+åÃìµO® 飳Pj5å–êAãæKqÐ…°¤©¹\D-@´‹¦b¬i7¹|Kcw¶ÂG-ÙfS*Wè€CÐI·'[·¡-[ÊIú¤ò4Tkt«¦Ê¸Ué Õ‡×Z…Sí*"¦ÍÈYæ!5{tC®\¨m6z3 ”y± ¹Æ»î|¥Z(—LÖ ®KRÅ˘íPp…Ž,keSþ Üá¦vÐøùøoÊMr3n¾¤U<1×m]*•kÅlŸ¡7Äé쬵!Ÿñ¬YÊBêY©\¨æ¡~5uMS…¹QªUØ I6´òÒÄ J·ÆˆÂCGkãn¼³Í]¥l¥Pëã]¹¹–íÆë[ZªùQk ž•¹1ÛQî*¡RVË]5ÏîRcÏ¹Ž•ë8¹Žçµ#ßÛI—^;PH’J‰¶M‘À„Ù”­ª Že~Ù²¯”;¥3%èó@zVË`]Ï£“ès.úfVö–B¾‘eÐÜ–G¯H³,e›ŠY#mØ&µÊ’nè,vµ¤ShÂ]¾ÔM©\W……† €Å…æJ')LÄÈ2zé ž›ß¹öš|)_ií“<4UÔÛÏHË0mÈàšÉÖjcx‹;›‹Å¤¨–[j-ßzÌvtò¦EéŠTr°’ík”gôÅhaŒmß_Égñš2Üõ%p!ºe‰S[¶X®ÖЕ Ë*uut¶•Ѿ«î®šÏVšÛxÓÙfË=Æ‚Žféâ\äùœælWµVhnÂPÀÛ"jl®Ð%ÁµË=ÌÑxè;O„1Ý "' :¤æŠ\[åŠÜ/T*¼´òÒd²M^µòbòdzÉzÀË%‹è­ Iéõ1²ÉC³5fÎ@®„Á«9_jîCÅÈWKù"=iÜXˆï¬Â|"åej½Å#Ђ~/÷»vî‘Іþ ƒúY^ÇJÅj,rìC€Žù.c_³© ól†¼ä´<·¦«)á4•ˬ…LH®‘#‚ƒ¬ˆf«ð$¯ÒÚ„ñݳ­7(ÏÆ^_%‡}Ý"ëFKÖôŽb£4×\¡¥… J‚d¡ÇP%ZÛ0LW™¹tIc³l@•ôrÙJ»^ØÖs$È£‰ äT³J™Œ‰Ð»È@ßÄ|è)¸jRA®¹Ñ¡Ö^Fµf7Ñùº[0P;§É¹_`›bÚE—+÷R;¦ÓQT¶û.C.”ZÊÔxŵzãØdDª4KaÓv# ·PYjÔV˜•,F Œ0…ZG¶ …=W)à1^E}Òtu»ÁÕ…¥, JêŠ]¥zÎc4¢^×Ñœh¨Y'gyUCG>×J¦»“ÖÝÁ! ½OÊj8+xyin e´ËjWGÙ©mK\ —s+I- º£íì:ÊeW}Ñïå ÝΩH7ØUi±Št(,ÐVÆ›¼U…›+ÒïQ£DnÈõð®Ê7—ÙJrFV@gFwחᵤ-£â^5o(æ»QH®QÍ´7 ùŽ]³PCFëÚBD¶J¯I‡›‚äd"Óo„&Ñ`B‹Dad?!*t‹¼(Y\j¶Ÿv7‹Î–í…bU+óx òÍc| #w‰J¯uúŒ«ÃÐ +è;­¾Ÿc?_+täe4,Zò¼a†A+—^9-”ºRÄW0Š~„k\³5Úf ¼"6eD'+½-ûŒÜKR¶=HÙ2™˜.¹v˵Ǵ ï@'Òcr]&×mPb ˆŒôE;H¯•³˜‘y*u²NWýáŽáe,/ãxaåp³Wt;¶éAå¬p¨kÈÚ¡ÍœÙZâp 5eWÔÏ‹·”¯¡7II«’¯èuÚX†~.óS›œS$s¾+/7%:¥LÊE´ÊªmsÖBÐY¶3.‰²T.uSï .©†äp¶RvjbªÐ$ Õ;§Y»-jæÍMŽÓÜd-ÍÍRýàî&z"Ú³G¾om3Sñ’>ÜïÝ•-²ôr=“ûjùêì|enQ@Æõ¸ªÝ3ƒ}D1ŸívžPÜTëšM¸¡9g_Ù ¦r[ ÔúIÉ­Évå åF‹»1Á)7bfýwOü]k¹ÓO*͘ú—…Iœí±5ÕX±Ž®ÞF±´Ö’{‘CZ—Æ6ÄO¬HU(P4½ö¹¥j‡îŸ6«¥¸$ÈMKK‚År‰©_+ê-]b”“—µ¢Kû5T©çÈuº\'C­*«Ð†!ÔË^Ðôɵ¥’_ [ÃÙ„ùÂÆWä{ÞVÈ4€í U7½eÕ³+½Õæ6ÓÇKos‡>^zÙCT¼8ÐS8êäGªˆ·¯ª1™ø®*TÝäÌvب5åfVö ónì|kÁ±‘*Ûš‰Æ‚4`|ÊÛDstCûÉ7rÒZÉçºPe³Ði1i”é©L•ÅD;åƒÉoÍvaDTk]EqmøD4Ñ-$¬6t¦t«¨ó¹B -³‘ÃY‰ƒ†YÈVßRnF7´ÐzYX-´Ò³Øô>µÓg4Ë„aúŒŽ|­­œðæ·é3r‰æÓ'M•}!TùŽ¢XæÊM]ÖâÐÌF]im2}-²œblbÐ]U; ½Pe¡R°k)æã÷ØY^_èM^lQb·£Q°Rn\ÉöÅfÀI“d=¥j± ™þi*÷$i¬ÈpØ‘—7Y%fú v£{C# ä@ÜãÛwù¥¼JRàl“&Ù¹`íU¨Ev9J 2´Ó[ÎVd)Ez„í8‰)WJΠ¥§ÖÔeµÉ\¾•CVº*%™D‹Íõ ý§hDÕ|+ÓR»\U´œBs¾êæÌÈc̬iÐot9èî8›•ø»{4\䀺Cvµ–ü½ÕëeÜèæ½ ͈;mÙ˜©À¢%Ê„¤׬̗+P­E9èñs´Z3aX#¶K­[ã ¬µ 4êZy¶(7Ânà”• ±}Œèµr¹Xõ °tœè*ílL‡¡ªØŒn@›˜Â ͶªPò œi¶Ú•½…år‡]>2èHLHl-¶Gàâ¢3—Ñ`mÖXPÁ PVS’Ùï’©)kxòŒwÉ3ˆáÑå¯ß­Ÿ¬-l fn  Sž!“[Q¹0âQWíf¦¬Þê–ÔúĜΞ]G³NÄ ŠLÛZAúyiÔe»Ð#ö&®se;r½rí)»æIY””p¤>°Dœm5° ÊS-ßË«UPIJ8Ñc'’=Ô Lò„Ëœ6ÓvÞ‚¾žÂ蟺Z F¬>c'Y4²Îˆm§&Ú‘X£ÆÚE‘±²D"IÄ­¸c0­3íyt嚸Y±Å 4[F¯sûL¥,éì›c}+Ôh¾q€\—¬eJßÑØ9ÌJ1ˆÔ¸˜ÐlgìF @¦2v&ˆfÁ5]¸,#ÛÌjÙ¦²ŒÊMöZ–’mçÌC&¹ªÍÙ‡¿Èꤹd1×.€Wò60¤qåàXeÀm?_âBÿ%»Ì_¤æG kµB­h· pÝøíÀuß. UdŒ-¹1Túªl-ˆ÷ Tò5NX˜Ift8è²ZºJÍ\ºlà“NS.w²"U θ@S8¯UL·ó¦ÜÅuiL ¸ZZ®ä]ØYm´ µAô Ú¬Ð?Qé@eC6Љ=L¯\ûhj)7Ê+-¶H©m5¶ÓîÉÍÞ„ZÌ·Ô$sù¸T‘<ÃÓ”—À+¸k”…;HTûJ5¨Î]%.Rsy(ÇÆÃ¹q£l ¨õÖ\}jBKr[=bvàn ãª-oÖ2Ë:&YÁ‹m:¶Hv Q«*úI‹5õpi¤S«F ,\Ê“^ÓÁ¥¿JµXpN£M­»ªìP¾/F1¯Ñ+ËMš…m¾Ã±éÛ!øö(æµ™\•áW¡Œçª µÊ—äÉË“—'/^ åZ(×B¹‘«æÚ€x¡úh¡ú@Iòå¸ Î ¦¯C/1ôR¾Éi!§œrÊE§nç0 ŠmYDz;j8öYdÛDYFC4‘l‘ydÚ Ð„ïžãd–Õ}íV·c¥ÑÕ,wg ÷ðÊõañ) Å]•‚,,‹ÛçÞŽªV”uäûÆÆØO£íj1‚åË¿¡™-SëßzØ•–ò]˜9ˆÝš‰Ü©à…ÇŠ¿.Y%c£{PpÓØVQ¬ÜÙÕéx×=c½‘»ø†µ(¾±IŠo}ñ ýgb¼ó¡µå¹´'€ê.I“Õ¾11’$¯à0eÇÙJÞ¦“Ùg-ž>kºlÙ¦I@còÀD1—”AÃN¾7AITõ½Û[»ö(74fTmô ½«üÈm®,¸$V É“r Bå¢M“ÜÑ@, £-1*$KY•ÍÒdåæƒMnúb»3›—K lJ`wíú[)T}yHEC²”ê—$V–j¤¸d«Cœ™_1ÅÈ ·«`D4µîq9ãÇ$Œ¥5YdªU¡¸Ô8¦ÔJE´…j~ײrá²±ëâ9²XëpMŒ’H敘ÇÛå{º9gÉ®boåóÉЇ.9¾±Ó¾ø–oêŠï˜0p‚{D.¹ïêßV©Åw}-v3ÜÞŒŽ•Žb`\Ƥµ-Ÿ/Jwn—.;|bÛÚ%KgÕ|¥“û8ȉJCݽŸ³ Ä·è"hðÛ$˜Vy̼rT¦¥ˆÊÜ+ÇFÏjÆ„·cÅg²š ݺ#o÷ºq®"ºMÕ.ñ65rx•‹7²sÈÞ íT ±ahg€NCl´¶ ¤ÇV[f?†YÈ+eKíù™¹Ú‘Ýpýbf±)7Q-@G ÌT¨}ДÒ]pû˜ØLdâÂ*€z¾å”rÜW5˜~zÝ·"µÖx1_Ж!zWA@Ùv¨§É [1»¹`dºÇ€ÆÚ.,žûQßð¸Ìá®ÌÑέH˜j =<2½Ñ>² O´2™.sUÂC0|ˆ+Œ’b8õš(gÁ¤Ã[]×·:H-™ûˆV,*1%«=ˆ‰ ÁÚ&K+Ü1jÃ(w"b·‡ÁÝù’å”K¢U•êŠ&3¨ÿåí:aƒXÕñòV·µ]z9D!äX+ªT¶ Æe™$Û¾³•ŽF/Bìň¡×î[è6®e9®ò:–koâ_=ÛÅ yD¢™›‹µ¶ÙÍ»âJW-f2»MÄn$ih’aY’ž555ú8[ÙŠç9ýo}jäÆ'G´?g_¶Øš˜14·´pÇ'o í,J–6Fßjº2^'q·Bc²û‰Ö¾Šô(2“w¿VA¹æKvKQWعì™u{ÊÜDW‹íª¥e ûVávyµV²ñ3iˆ¥ØMjÕZzQg]§Òîú”"ZµÀ…´ ²–r.eá­®7kê*¶Æi‘ÎŽ?x±;š¥·`EäjiKÒ·Ÿ]ê!ulûÄUnI÷ü²&€G3»³¾jÜz•ˆF»ÑD¶T”4«‘“5¤©——>Sî)9ÑZÙt#Uù=Œ™lÆ2 öûÆ*[x¹Âiò®`+«-É1Îk¨âM\ƒã…ÛÙU¢“¯tÓ(ˆËÜR†5™-â­Ö%GÞow »±ÆjFÖa×èÓikxWÅǽ![,Úßy4 i’1£X¬ lÒA¤*{_ËWkMè_äGÍ}ÍÅB³d¿ŠÕÁ-+ì›Êíù6Ãå>.õa6Æ}tx 忘—ÎR@ƒÛ£êîÐwPû‘ê¸bvÇUìMEšXPÕzÚh:a÷Ñicæ0{*7/[D»ä*/…‚#×7‹eô¦]r•áÁ.NåQC 93“¥8Ýèd61(mc«r-ÈUöÑÍñ:N8ã„3N8ã…3^8ãÑù4× ¼´˜SbS% U~:÷)Ô¨ft–Íù¾Éb 0sÅò*¯ççÛg²•ï¸Ï–QÍ®v k¶Ý´3C¬Ëö*¿ƒšÑ1¹«ÅÌ‚/ãF6ÂÙbÐ Úu²¼zWn‰˜ eÕL-uÏ‚²‰g³ÜŒfrlÚ/‹²˜å´0êÆ¹ü<özÓÅš¿ï4Zå*ÁÍ‚&>•ªãd“˽™Œše&çÎCªóɳeãԞܨ¼+Je«3“Gù]¥ð¹c‡Ù2Ån³²üyÓhŽ”?³,Ü—êÙ¬©Üö:Ëî³$ÌÌšk»¥YsíJÏ^Íò*'·ŸíÓf¹=ˆÿ¹vlÀ›‰Á¶Ðœx›€3¹ CBÀ™T©È©„3K~;°¦@g¤Ž0™çý‚‚ æ[s·r¹=Œ|¹¥Fõ%ŒW¹\ÌgKËJ‘i²a‹r&ëKÓ$»ƒ³i6wpr+Ó·ÑŽOFàfZÿ}{Sì>=)”½š+3wò¾b¿3ôaK›h®Ý¹¶Ÿ,ºÎ‘•PiY“º »rS†Dnï.”»„5mÚ¬Î|kr?‰SH›dζçØÄ2¬ ÃXŽHLG3™æ–[ç!ÔY²¼jæ![’d[§•1‡A,§ser_4¨qSÌ\Îù¥¢=Nâú© W*eÆ:aXÔéÀdöö‚æbZ!@Z-w"”jhü“9TÙý<öñ^4²iÍ•õ$œ´g[Ù\£þžÅ¬Ò)Ø×ØÅïÈCN'¬<‡";Š)…ŠÙ«”·Mƒ½+xf­aṵ̂®x0M‚QþP#fJ‹ÙbT Ó4ך=àH›ƒ+íp6 #Ò»Mƒ‡™K‹t ‚\/$“_Ð%[¤šæŠ~ëÍì5æÊ¸5•‹˜¬4˜ÁïËß"ÌSíŽzixÀR[½Ë]uҌȈ3U¢ ùÜDíŸf#ôh˜«Ì•´¦i­{þf^c†¿A¯ÜTÎVrþÞû÷÷ènŠ2ùó Tï$Ü9²q=¹‹½¡ÑTQÄþ6 Íïè5M»—ûD»òϦöÊê(^E)ÄDLµOr»r9Ûí+–4íä^r<¹ÝuJ‚™éý½KËJn}$œþÐTè2Z©ûxOq“~(¹µ™–Ü»¼Rò3¹ÛÙßÄ”$JÓPðn˜lšk§X6ÕÓ¹aÐ5©zòv7TN¦Üä{]ÛºMì>ý­„à{Í]ûoy×,T"îÝ¡ G3¹´}^Y³æ”¡e¡çiÏkîLLÑÉU(ÍÊöjwíõ—rqCk—Wkæ4ÑÓ9øjî7‘œIùñìî\;C d_o¿¨¶m[Xæf?‹¥³d¯N¹qj5Ré'QÉáÝäb—íéy³[W~.”8ßcÚ¡Çßñ|‚y3§îÉ9#)9áƒÿËùƒ 6ÃÌòø7î03B®Û˜)ž Ùfj¸nrf5 åÍx9 aóUê3;nNŽ®1Ç›Ìxs}T4;˜LÄóGo³.ˆaÓϯÍ<3Á<„PV“wÙ÷7SÞþ¸!1Ál2æVp3¸ É µÞDÄÓåì#¢Ñý&sâ‰ðÍÁõuÃ[žŠ;Ú<™%gÓõšQftôB›'±þB{Ò,2WàÉÃ3Àn2¯ËÇwzh¹ÌMƒjˆßpH GÊÿf®‰îÀ»xêź.†›m"žª»<â”ÁûÃÝ ²»ÁCÓE<2æ¤p¤&Àçj¸~/bÊ<™*"GêåÄŽŒ¹¡ÖG³ÍnÑÄc HÍÄ•ÿ&È[¶@ 3¹0 ¥0Ür4Lòoy9ûdî¼9»>%ç_¤ä Œåäì žÏAªƒ”-}ž¾²B\˜ â9HrŽKf®‹eêÍ@³2î½Ü ܯ‚{/;÷«Æ5ËÊSr5¹&~áßêâ'ñ7¼5\¬GLëózÄ|MñǧC@ˆJj‡ÈY ðòf-÷…Ä”Ä||¬ Þ <[´ªY;þŠ ßÀ‡›uðN> É5!ÁSkxÒ Ÿ­‹ð˜—ëÊù,ëÖ—Ó[x2K½Ùïåw'ý—ú6Þ´)$——0×u_â«7 âw¨Ù¡og[ºp¶m-q]éG]cxzsÊŒ“8l€øñ ˜ äTû5¼z³h{Äbyë_½Ù´Þ±3d'€vÁýDýê\½™šŒ8³L¦€¦:Ã%-üº#óq†8OMíšÚ´h&hhOÈíš ¼·¤m}39RçJz.hrgMÏ}Kû"—öíoxʲ-§ O找<…—§î¦L£á‰²õ& jBœ›n¡æqß‚g­ 6àr|8ða vPÔœ/!çýW«üWªªð_uA¦ÔÜ ê-:t$è(ÐÑ c@Ç¢W”ø‰¿Žt<Þ}èDðN‚ÌÉ S@§‚wxlϧKÞn.u]¿ç ©Oõ¨o[ ,˜)äQJêß™? 5deIÃ(s6è7?ô[W6çª29áœ/§ ò¤Àzä©ÍÏ @"ÆKÞ2þºt èRÐe ?‚.]ºtèjÐ5 kA]ºôgÐ  öM ›AݺôWÐm.=>ž·ƒîÝ º ¼»A÷€îÝ'uy¹´x1h èÉÖ'¦¿=ïæïÈ“ñìh5ì=,eY/uõУ ÇoÿD«§êòãRÖ)óÄ2ÊûIÐS §Aÿ=Z zVåñs çA/ ŒA/ž¸ËvSR÷^5<¹–'¦Ì†§ò 2oÞ½#§à¥Ì{ˆçû €?}ú7ècÈ|úôèsð¾}‰zýUܦ¶‘7­"÷cÐlÚz\;Õiúô è? oAß¾ýôèGÐO ŸA&d"P Tª    - Z´hEÐJOÀãit©ø´ûÕ¢zäu½Y¼5@k‚†ƒÖ‚üÚ u@ë‚Ö­Ú4´!üŽŒì©€Á?ƒ6m  Ú ÔÙÍA[€¶mÚ:òm ŒÅÈžœ¢¦±-žoÚ²;€vŒ˜¯cÍNórœÙ¼  ]@AiPò“@“wMMMMGwÍí±lÆ»1Ę=ð|fÄg[3Rú¬íЦyþývè¿·7³àgOÐ^ Ù ½As@s#ß禠›¤Ì>Q8Nî‹ûý@ûƒ:t0ˆíg>ÜC¢0î1|ÏPÓ:4²õ%Ù°›ð®n×vº\ûi†ß(í(ãj p+¨MÒ‘2æ/ò±š¨TŠv’¸•cYä?¨íŒ1–gøï,ú%ÓÔ)|ûþp+ *¨êuƒz@½§´aޏ¸±ÿœ }äQò'Ž1^“£]}‚ÿæbÄÛQåÁÑ’£Í1 cA¿’üH›ã¢õÌñóe¨9!ÒùQ/ã‰óÊÆù$Z¾1 Wx¿7ÒÂûAæ5Ðëxß 7£9(K+÷èm<{ô®È 2ïAæ}БÕ?Œ¨±Ùx|Ù±åßÑ<÷®AæcÈ}íýÖÊ “Q cž}úܵ•/@_‚¾} ú&Ú×Å/eþñ«,SÆ}?¤Ð§ãd¿}÷üôð -F"w€‹åëÍOÒ>túeÒ¿üìâfR)R)öÆÔU2’ÿŒûÀzÐ`ÐÐr ¡©Ìò)_‡BúùŠƒD…:β]!µ‡Ì•VL±N,s)êp+¥îh3,5zk¢ƒ¬ þ* UA«áý«§†˜5 ³&hxÊ÷Kl?óÍZ©CÌÚ)êäCÍ:)¶§¡fÝû²¡f=¸ë§Ø®l{Øï‘²íbÔm#SvÌØÍ×sÃS6_6»)h4h3PhsР-A[¶mƒ¸ŽGXÛ‚¶mÚ´#h'ÐΠ  ]¶‰ 4¨ –; 4ÏvMq¼j¦ SAÓ@ÓSlóеð¾ Ý!÷”ëxßLÜÏJQ—Å\²{fƒöN5š9©CÍÜÔ83Ï÷Iq|O™}áîÿÿ€ÿýSYs@ªÉ:(Õ ýߌhFÙ1ÏmžPg´õåêë\½98eËl~Šõ¯Qfȇ€×˜Jêü¡x–5šA9PÔjµ¥rROÊÑ¡ès1OAzKåM{ªÅ]v€J 2¨´TUA5–)¨ïìI¥dÖ‹û¾õãz³îáà!u;gŽÄýQ ­0cÚÄÕ¹£ñìбð÷+¸ÇŽ>“€O:tè× ÓÎpÏ:;µ«ù èÐoQ–ç‚wè|©·˜{€÷{Ðà]¿ÁýèbÐ% KA—¥¦š?¦ZÅ~ãu×'œn|9ž_ºtèjÐ5 kA]—²úëN‡½ïø3x7€nݺ™õt èV¤í¯©”袷áþvР;Awîݺtè~Ð"ÐbÐø{ô7ÐßA²>bÛ=Þ£ Ç@ÿä;À{Bòz%ëw›Ô‘'ñì)ÐÓ®Îü î3 ¥ gAÏž½zéy á¼ zôjª€ñ‹ß»)ÈX±1ž¿–ª—p^‡ü)ö‡¡^1o¢ý¼…goƒÞ½ zô>èЇ @ÿ–~ɘSí苇˜OàïSð>KÕKßøyª(v8ö‹_€÷%è+Ð× oRv|øÜoAß¾ý7Õ!¶šØN\:J±'ç¨TrýeÙüœ²};ਮ1‡Æ^×nêꊦ¾®Þ ¨Kêô@àA í]Îz϶2¸ý3h9ÐPÐòkЊ •@Ãê8ÿE? wЪ Õ@«×ÙyÚÐÀk‚†ƒÖ­ Z´.h=Ðú  @#@‚F‚6ª«=gðÆ M@›‚Fƒ65€6mQ·¦Ù´UÝf뺡fðÆð]2Ö±L™±ˆ÷8Ðxж í@ÛƒvíÚ ´3hhÐDøOƒ2 I É ]AS@SAÓ@ÓA»!Ž3@»ƒöÍÍ‚ÿ=áîš Ú4¼¹ y }@û‚öí:t è :cÍR·@tëÆ:{1¿*ĺ²}T¿"VÖÏCñ<[ÇúY…î  qjå@yPK-ÇV„ß\jÁ땀ˠNЂ:;÷ªÔ•QØ_Œ6ÕºVSÃ}WmCMw]ÁôÀ_/¨´txëÙ sü : t4hTÄùÞsL]›9¶ŽãÍ󫺪9u±×t˜ãëì¸tdO”¸¦D¯ß>ª™“p2èÐþ2uA’q ‹6¦D§Ÿ|*âqd :½Žö¯nÌ`ø}¢É«3ðü̺^sžŸ üÐ9 ß‚Î:ô»:k—ø=Ü {!è¢:æC—ùC]·¹¸®Ï\Rgû—Këlqîÿºt…ËsÚì®DW®]ºô'ÐuuÖÖ ÙëAݺtèfÐ_@·€nýò·n¯ÛÞÜ:~'xwñ9òêî:Û^ï{oÝBà5åßÚf sÚÄý Eð»´ôèoý;èAÐ?@="u©úòÿ”o‡ÿ/ÏŽÀ;ÿ§gÐ÷ëØšÇPþ‰4<^çm²˜ ? ¹§˜¯ žaÿàæYÌ“¥uÖÞôlSw$4Äe½Ë–ÍÙ ç@σ^½XÇ÷B¿wùËw¼Œx¼"ymÌ« ×€_½Qgõ°7á¾Ugç.œoÐFòvÝQ˜ëÿOiä;|´ï:ôŽ´©z±·7Gƒþ'ÿǘw‘Æ÷ðÎ÷A€>¬³úÄG®Œÿ ÷cÐ'uÇšOá~VG»eÊ|÷ ¤çK¸_Õý }ÁÿÇ¡æk—ßÔùù'ób¨ùOÝqæ[÷Îïà~úoÝñÈïÿ-¼Q懺Ìuv^Êüý ôs]½GXv¶}NVópS?È [LªþDÌ}ÿ§ð“²nø®“P«ÿ'Ù¦®£"h@=çpô‹q ÷ƒ@ƒAC@ˆ‚–­€8¬X¿†Y 4¬þdŒÎË û³r½µ7Ø0O…ް,9ÆÏ–ó*õ§I;Z¶Ìp³j½]‹&á 2«Õ1«×³¯kÖÀ»Ö¬gzÙå²Â@Äóµêm~¯ wк õ@ëƒ6m Ú4 ´1hЦ Ñ Í@  ÍA[€¶mÚ´ h h,hhÐBÐá #@G‚Ž :t,èW ã@ǃN: t2èЩ Ó@¿:t&è,Ð٠߀Îýt.è<Ðù ß~ºt!è"Ð@ןmV—o=ítÄ3Í%õg™KA—þºtèJÐU «ÿO]ç¥Uqà»?ïβ,Ê‘…EDu)*ˆØE¤Ø0bìQ!&1 ‰ILIL%¦7•"¢ºtBYºt¾.½KoRÔØóÝ;ïÿþs¾óÞ?oæNo÷Î9e0FÀH£a 2Ǹäi×é¥{ûñ¦³JlöŒ´JÝÇS/ð;&A9L†)0¦Át˜A΄Wñ? fØ‹Û<˜ `!n‹à5ÞÃX ˱ò?HúɇIOvI=][VGù>NzË'Ô×§ŒƒeyuåÏÏR…Md”¶Ç¸S÷”ÿò¡:àV ¡¦F»ª­ëÎÐB9jé³bä"-Ú|ÿ‚Úº?‘³4‘:jùëïå³ÕÖvý¥®ö—b¨§ñFØú*¾ž/ÑÌvGÕGçE›l-h€ÿsÔæÍD"ó\}Îo˜è’—µšÍÐlƒÑnm†Òˆ4Ñv8•¥Ý5Ðï jŒ{Ö¶mk1¾mÄÛ„8·¦p\f¼ˆg©æK3h®¶¿ -H[Kµõ޵³ÅæËÅ|¿„4Î'žKu ´‚Ö”Õe:HÚèór9ßÛÂȸ’çU¤åjÞ¯ñòLLvÓ`?_p-a¯ÓX›Êõ.£PÚiVgbåô¢ëOo@N{Üo„ú’Û8:âÖ :ÃMȾnÑ!|³»™†äì &ëVµµÂPæ?;ù0ôߢ]dž “~7Ô°Ïùé#Q¯rñuÛÕô”ì›Ôt(¦;eÿ„[W¸¾wÁÝõš³‘ï÷Â}p?2°vÂCð0tƒîðkãGx>B?ý*mäkðu5ÝÜËò¨š-êÒg÷y½rŠôž^Ïú =^×Zæö [’–ý7Õæú^n—o ßÒ2i"Ãi—v/Úðâj—1{M•]¥²¿íá å;:‚šµ;ÜF¤ãv ÷eö]ø^®® äû´“Çu¤ß°Ó4µ±þ??ôv3Êõ¥Ù8ã~k´ëÑ›Jkù‘Fÿõd õŸ‘#÷'ýÿ?ƒŸëXë£7êÑ{âþ ç7óØÿ_æWð¿ÔVÑ!ô´WÓÅøæ÷›šz½'ò„N0ë¨ûÇðókýF£ Ó]ÿV'â¿T~‡ûïá:Ijû‰“reùXZ½xþžÔl>M®évËåOm8æÛ_¼\&ûil¹ZŸ9HzþÊ·¿ÁßáðOø—Nñ:ø·Nõ;€ª%åÌ v¿c9ÿËå?ZU¾O¥ñ[šžÖìÞ6›Ži¤c’<ƒ{okgÈî«Ó½­ôÓ¨Ë^.3HW7y6'3¡Ï$ô™XfýqÏQ¦u¦Ÿ:²xiÖ_Fž÷ñ$†ÌóxQ_¥„?ï×ü¼„¬!:ËÏõËÅkié(C5ÖÍ0Ü_V+§Ù¹6ç)ßl¯<'·h”k#&c®ëº¢;ûbâ*Óª3¦S7úpÜFÀHâ¥óüôTvü­Ê¬W;»1š´ŒÑùŒKGì§c _Ët”šmk¬ItA.ßÖoÇãgL„IP® sexr\Ç2ÇÇecÆ"·‚Z»Œ¿)0Ó`ºZÛ}ÍÛò ò=ÓÛ+kÍÚ`¬í.ö>vr\³`¶.ñù­ˆ6RÃïEÆÿi'´-kSs4Û–,ßK݆hö¹¤ȧ÷Í y_de­Ö¿±Êž Z&‹3–¨ÙÍËRÞ—ù\eí _–à X 6>@¥F½ä*ž«a éX ë`½.Oíòù²¿aiÝ [tsééöE±®ð6I ¯ôMu‘k\w°¹v_íJ·%,'ß[‰{€·»6’ɮѴBêûý·ø«â k¶´Ýn'-;`'ìJËe7ï{`o:ö™ý}ŸF;Ý~žà ¼ ‡4ža:¬¦K{Ä80ßÕØ®M/d¶6óó¼­•ÒÐï ®ô¹ºk&¶'Ë×;6F¦mÂlß-ݦP!ï¦8S)ï!÷}êã­²Áš}éCþÃ'ð)ƒÏ@B¾ôÊ+•¼Ð±¤P2!æ³ZXå'mì~ä Scripts Help Browser -> Export -> Allegro Demo Game Level you will find some useful tips. 4) Save the file (use compression before committing). Export it as .txt from the export menu, choosing Allegro Demo Game Level. 5) Update level.dat using level.txt, the new level should appear in the game. allegro4.4-4.4.2/demos/skater/demo.dat000066400000000000000000013044071173507505700174350ustar00rootroot00000000000000slh!ïALL.ëðpr¿opDATEëðÿ7-12-200ÿ5, 13:24îöñNAMýñ audio.datöñïORIG FILßEgy@½öù6-162ú8dingú't.wavSAMP-æ7V"Þ ¦ù€¸´ƒ†‰‹ÿ‹‰„~xsrxÿ€‡Œ‹…{qÿlnuŠ•œ ÿ’…ymhp}ÿ‰‘ŒˆŽ‘yÿe`cjs~°ÿÓÝÂŽZ@>Jÿ\prnrw…¦ÿʯd@IVdmÿtxz|~„¯ÿæë¬U#0Qkÿ‡t| Ðœ@ÿD^lvy}ƒŠÿ–Åõ×pQÿmx~‰žÁšdÿ™Îm+Ljyÿ‚‹ É¯OAhÿ{~€‚…œÍÿ÷߃3 >`tÿ{}‚†‘®Ò«ÿO5[t~†ÿ¬ÝÙC3Qeÿmuz}€ƒŠÿÊÎt3Djy|ÿ}…ˆŽ£¬~ÿ^fpz€†’ÿ±¿ŠTQerzÿ~‚…Œ{~ÿ„•™}ir~‡ÿ–³Ñ»‚H<[ÿt}Š“Œˆ£ÿªƒmmjho{ÿ‡›½ÎªxN>ÿRo}}„~vÿ}…‡Š…mhwÿˆ›¼¹‡ZNÿa~¢¦vervÿwƒ€caksÿ{„’ª±‡RRÿkqwˆ’qzÿ”½Ê¡lQOÿ[p€{s‡tÿp–´³ˆVBÿTiu{‚‡£ÿ¨‹nqw€iÿUi¥˜sXRÿayŽ–››‚‚ÿ„_Ms¥«ƒfÿTUr•š€obÿ]q…zrލ“ÿo}‘£žnGÿMh{Œ‘…ˆ§ÿ©xakdivqÿbftª¤oÿ`ƒˆjj‚ˆ“ÿ¯¥‹œ³œw^ÿOM_u†“ÿ……†mkˆ™~ÿcvŒ™¯Ã¯ƒÿkkx‡ˆt[`ÿmlglru|ƒÿ…Š˜®·®˜ÿka\Zcr~…ÿ˜…}|ulÿdbo¢˜Œÿ…qo’‘Œ…ÿxqier¡–ÿ…vehstyÿwmt‰˜™¦ºÿ¬‚vœ˜•ÿrYV^n†ž®ÿ´™kQXhs{ÿ‚zyª²²­ÿ’rifVWn‚ÿ…‡›²ºµ †ÿq]U]pˆ˜ÿ{ooqgeu€ÿ€Š—‡nku}ÿŒž‹hanz‚ÿ‹„ofo|„Žÿ«®¬¤’ŽÿŒ…rf`XaÿyˆœŸ‹|ÿzg]boŸ»ÿ½«ŽmY_t‚ÿ™‘vjqƒ¤ÿµŸ€viUPdÿ~w|ƒŠž´ÿ°Ÿ†]E[…‘ÿЉoYZg€ÿ–ž„„~qtÿ‰ˆŽ”™ž˜ÿ…wukYYfgÿ[[cfiyŽ—ÿœ„ddpkqÿ­ÃÒ¿…[\ßhefqoã~€ÿ’އ~kk÷®¦0žž˜ÿŠeIQitƒ›ÿ—nXeq|™Ÿÿs…• –sÿYSTb‡±Â¼ÿ¡lCJq‹˜œÿSH[fk}Œÿ˜‡{‹‰jÿ\p…¢µ ÿpXBM`ds–ÿ«“yvos¦ÿŸ’‰hOXlrÿ~—¦—zhl‚ÿ•„]Sewªÿµ™|~ƒ~…–ÿ™ƒcEOy¢ÿ»Ã³‹nv‚sÿhklnv}„‘ÿ™ˆmbfs“¸ÿ¼yq€‘ž ÿ—|bXRQÿarshl~Š–ÿ™‡|˜ÀãŒÿvneUTnŠÿ”ŠybTatwÿ{‡–¤³§€qÿ”´¬‘u\Wpÿ†wros‹–ÿƒx||l_`oÿ–ÆÓ²‰oblÿ‡’‡zuj]`ÿky‘ªªqvÿŽŸ’kLOo’ÿ¨±©–ƒzxzÿ‰¢“qJ8Sÿ‡²Á­‘}m`ÿVQYn‰—§ÿµº³˜nKE[ÿyŒtoywdÿ`s‹£¬œsWÿYg…££Šƒ”ÿ–‚z‡“™|ÿ[a|’•ƒfZÿw©ÇátTTÿeny•²¼«‡ÿc\£›xa]ÿn”§’perÿ’‚v|vVEÿQršÁг“‘ÿžŸ”~klzƒÿvrlq|mTÿVw––|daxÿ¦ÓÒ±–ŒƒÿkOIhnKÿKcމƒ‹–ÿ˜‘z_c‡£¡ÿ‡‹ž³¤oBÿ>Thx€‚‹›ÿ˜zq†£½Ç§ÿpLVx’›ˆqÿ¡£ˆqgbhÿsngyžµ­ŒÿdTs¥¶˜vdÿcp}{y’±¸ßžwRJl€Pepÿ„Ž€`QmŒ–ÿ˜“Œ•®«€SÿKi®¯–‚ÿ|gF8Nq•¥ÿŽqp†¡«™xÿp„’…ncbnÿ‰ž—ˆ–sÿL6J~­µ Šÿ|}‡ˆ€z~„ÿo[Vq˜ „ÿq|š·ºiEÿH^t…Œƒ…ÿx[Oh†™‚ÿdl•·À­Šxÿ‹¢–q[YVP¿LIQgP0kÿŒ³·¡Ž…†…ÿxaXp“›…bÿ=6Qcacu‘ÿ¨²«‘‡š£Šÿmdjƒ•pNÿNg‘‹vioÿl^U_¢¹¯ÿ”¦XBÿQu‡vlflÿ€‰ƒ¤¡}Oÿ;Ltš§•„‡ÿ“˜ƒol„”ÿ‡o^bzŒƒxÿˆž¦•k6"@ÿl…Œ–¤·Ê¿ÿ’bTbmoh_ÿcz‰|aQ^}ÿœž~egpqrÿv€š¼Ê±‡oÿimwqbj‰šÿŒrbj‡ª¸¡ÿ‚qp}‚q[bÿ‚¡«Ÿ‹}ÿhOTr—µ¸›ÿsišœŠsfÿfeWHMf”ÿœ¡¸ÌÄ£vÿWYz–Žyu~ÿ‚vj]Wey|ÿhZcw‘¬¿ÄÿÁ·§ŽqYPZÿoulcbgqoÿffx“‡xpÿxŽ›ˆ“ª¼ÿ¹qRS^^WÿZdv‰Ž„|Šÿ¢¬£‹ttœÿtcm޶»›ÿuc\Y^`hƒÿ£ª‘voy›ÿŒk`sŒ˜‰kÿ]sŸ¾Ä¼ªŽÿrV=:U~ ªÿ—sX]|Œ„xÿw„“š—ÿŠ‡ŠŽ‘˜rÿK9>Pk‹”÷¥¯¤ P„ ¦ˆÿf]m€Ž“–ÿ¦¨Œ_EFXrÿƒ ÁʵŒÿg]r…vrqÿtzywНÌÉÿ§~^^w€phÿu‹ ©š|jgÿf_\ew˜´°ÿ˜Ž¡ºÈ½œyÿfda^YRWiÿvvsz†‹Š€ÿpw¡Ì̦oÿtŠ—€vlWÿ>6AUp‰œ§ÿª©¬±œtaoÿ‹˜“pu‹—ÿ‡recoypXÿL\tˆ• ¬ÀÿȲ‰bT^vˆÿ‚rp€†ÿŒ•‡iY]hÿovuz’¹Êµÿ”ucgx†‹“ÿ›—Š{or«ÿ¬iSNONQÿ`}›·ÆÄ²žÿŽ~fQM[tÿ“ns}xjdÿfp„zjixÿ—¾Ì» ‹|pÿf\Xe’„ÿ†ŠŽ‚psŠÿ›—eXdœÿ«°«œŠpVNÿ[s‚|“«ÿ¹©Šrmu|tï]JJ[ô‹¦¹û³”âp›ž€{þé ~laaYHÿCOfuxyˆªÿÍâÛ±~b_eÿf`bs‰~_ÿT[kvsjkuÿ…ƒ|¹Âÿµž…{|ubIÿETm‚ˆ‚{€ÿ„}w{†’–‡ÿoj€ ¸·¡psupg__êpÿ–¢›„hTVßo‹’h{`¬»ÿ¹°­¦ˆaB;ÿLex‚Š—¤žÿ{SFYw‹‚ÿ}ª¹±™‰‹ÿ‡zh\Y[XÿOQhŠ£©–zÿs“Švÿ•—‰‡”Žÿv`]caTLWÿx¦Êʯ“††ÿˆ~k`dqxxÿvz¨«”~{ÿ…Œ…qZXtšÿ®ª˜ƒxrdQÿJUizƒƒˆ¥ÿÉÙȤuƒŠÿy\PYj{~kû_ip]Zh”ÿžž ¨³±˜xÿly‰ƒb>,9ÿWo~ˆ˜¨¨–ÿy}ŠŒzfjÿˆª¹¨†kgvÿ}nWGJZhnÿx¯Á·“ojÿ‚•ˆhPSx¤ÿ¶©Ž|{rÿa_lodY_|ÿ¢¶§‚mvŒ—ÿrbtœ¶©ŒÿusŽ‹~vsÿp]<*:f˜·ÿµ¢š«ÅÄŸkßNQi‰A`‡wÿZCBVmrgcÿr­»²–Ÿÿ¦›{[OWfoÿry¡œg`ÿv“žˆdWlŽÿ©«˜‡Š—šŠÿp]\cghn…ÿ¨Á½zn”ÿ’rNCWv‰…ÿzz„†…ÿ™¤–~r ·ÿ­zŽŽyQû01B~‡—©²ÿ¯ª¥œ‹qUFÿU€©µy^Tÿ[_WLQct}ÿ…‘¤µ´œ„~ÿ£ VFXzÿŠxmtƒ‡}ÿokpuuqtÿ¸Ì»“vxŽžÿ•sTPeÿŽ’‹xaY_ÿlmaXfвÇÿ»Ÿ’°ª…Wÿ=AYs†’›¢ÿR8Bczxÿhj‡µ×Ñ®ˆÿ}‡‘ze[`ÿd]TXiƒÿqq‰œ’s\cÿ‡°Ç¼ŸŒŠÿˆxcZ^_YTÿ^x™°©Œ}‹ÿ£ª•nQUtÿ–Ž…ƒ‡ˆvûy‡Í i|¥Ì×ÿÁž‚qdP;1ÿ;Oew‡—«½ÿÁ´¦žšš–ƒÿkbqŠ|_Eï?OeofP”¬´ÿ¶ÀÁ¬‹n[_ÿzŽ€]HN]lÿtn`bv‡‡…ÿަ¡‡rªÿÐЮ‹—‡ÿa;.>Wejrÿ„ž²³ Ž‰ŠÿcIF^‚¢­ÿœ˜®µ¥ƒjÿhuzoc`frÿskgsŠžŸ‹ÿzƒ¢ÂĦ€kÿo}ƒ|skf`ÿREG_ƒ¡®´ÿ½ÈÆ®…X?Nÿs–—¤¤ÿŽjM=8=FSÿe–›‡’®ÿ¼¬ƒ^Yl‚‹ÿ†ƒ‰”•…skÿmtuj`m‘¶ÿÀ©ˆw˜ŸŠ¿gLHPZbãp´ÿ°™†…‘|]ÿKXz˜œˆrsÿ„”’‚su†“ÿŽyƒ•šŒ~ÿ…š¢Š_4$9ÿ\x‡Œ•¥´¹ÿ±©¤œ‡iUWÿo’¦ž„vslÿZC48Nhy~ÿ‚Œž®³©œœÿ£Ÿ‡gSZw“ÿ–„uz™‰iÿKCN_hp€šÿ³ºª…•ˆÿiQQmœ”‡ÿ„‘  Šm[WÿTQRa‚«ÇÃÿªš§ P3ÿ8UvŠ“–•–ÿ‘oG;Okzyÿ{Œ©¿»£Œ‡ÿ—¨¢ˆk\_hÿi^UZk{xÿrw‚nZ^{ÿŸº¾¯ ¢ª£ÿ‹lUP\ffc÷jyˆL0•£¤ŽÿiOPi‡–‘ˆÿ‰”›•„nceÿiecpФ²¨ÿ’Œ˜¢˜yU>ÿAWnyƒ—²ÉÿѧŽvcQÿPiŒ •w_\ÿo‚mXS_nÿy†¹Ñѳ‘ÿ{zp]LK[ÿebbj{•¬®ÿ˜€trrnhkÿ¢¹»­Ÿ˜—ýWPOi~ƒ|zÿ‡žªŸ‡rhkÿojen†š¢šÿ‘“¡¦“oMAÿLaqrou‚Œÿ‰ˆ’ £”~ÿtz‡ƒttŒï«¹­ŽwÐK?;ÿPs—°³§œ˜ÿ“‚j\a|—¡ÿ˜ŒŽœ¤—xVÿEEFEHSjˆ¿ §¡Ÿª¶@lÿiswqim€™ÿ¥š‚ojhe`ÿaqŠ ¥›”›¿ª±¢€`T @hÿjy”«±©•ÿŽgQN`z‰ÿ†||Š›‰rïhrƒ‹êÀ}‹”ÿ𣭮™vL,ï.HfzR­¹·ÿ¦•‹~hX[ÿn…ŽŠ………vÿ\HAJ_t†û‹—~`š‰ƒ……ÿzh`hy††€ÿ‚Žœ—bQTÿcnmip†Ÿ®ÿ®¥œ˜‘€j^ÿcv…†yq{•ÿ§£ŠjUOMLÿPa€¥ÁÉ¿°ÿ¢“yYAAX}ÿ–œ’„sXwGOg\0omxŽÀÿ˜§¶º¬qcÿcd_WXfx‚ÿvsy€€thÿj|•¥©©ª®ÿ­bTV^bï`_gyêPšž¡ÿš†l\aoz|ÿ|ƒ“£§œ‡pÿdbbabp‡™ÿž™”–œš‡jÿUQZgorxŽÿ¬ÄÊ»žpbRL[y”šŒ“`ÿ~…‚tgfp{ÿ…‘£µ»¯˜ÿ†~wiWJIUÿchky”°¿¸¿œ}mopk@šÿ°·³¬¢”ƒmÿ\Ydptrtÿ“¦¦•qnnÿkdbl€“Ÿ¥ï­´³¢ÐR[cÿefp…–š”‹ÿ†—˜Œ{|ÿztox’­¼¶ÿŸ‚hWK??Nÿhˆ£®©›…ÿ|qin~—ÿ…ƒŽ—“‚n`ÿ\]ZQLThÿ˜œ£«¬¡ÿ~utz}xx€ÿ™›~rnmÿf_as‹œ££ÿ¤¦¦›‰vjjÿnokfiv‹šÿŸœ—“Œ~k\ÿZdov|…“¡ÿ£–€ngn}Žÿ’ދЉˆ€{ÿ†—Ÿ“wZF?ÿFUf~˜±¿ºÿ§“ˆ„{mcfÿu„ŒŒŠˆuÿlfabksvuÿw€’££•‡ymgkx‡ÿš¡ž‘nbÿdjg^^n…™ÿ£¡˜ˆƒzqÿv‚‹ˆ„„‹™ÿ¡›†qda`[ÿVZkƒ›­¶ºÿ¸®—x\QYlÿ}†Œ—Ÿ—‚fÿPKXnxwwÿ‡ˆ†…Š™«°ÿ¦šŒyi`UMÿUiƒ•˜…ÿ}vmdcm|‰ÿ’ž¯¼»«‘u÷edh›z‹“‘ÿŽ‘ˆ|rqÿwxsr{£±¿¯štng‰°hÿzŒšŸŸ¡Ÿ‘ÿ{hbekjhiÿtŽ«¶¯¥ œÿ“€fRNUf|ÿ”§®¢‰lTMÿWgqtsyŒ¡ÿ­¬¡”‹…}qÿf_]\YV\qÿ¦©—•‰yÿhWR^p€Žšû¢§Lwkjnr÷sxƒh•rrÿvsh_^ft‚ÿŠ™£§¢”†ÿ{vqgZVczÿޔޅ|ywuvy€Š“’Ñpÿ˜†€„ˆ€kÿRAATq‡–¢ÿ©©ž‹whfnÿtyƒ”¥«¢Ž¿we\[ZU5€~ÿ”“‘‘’ކÿ~€|y}‡ÿ”š–“‘†vÿh`^_er„—ÿ§°®¢’…~|ÿxqllv‡•™ÿ“Š…„€wlcÿafls{‡•Ÿÿ —‰}urpnÿnv…•¡¢™‹ÿ€wqopvÿu`SYp‰™ ÿ¡Ÿ›’‡{oeÿgs‹“–’ÿ‚m]VX_ekÿu‡š¨ª ‘…ÿ~uj_[bq‚ÿ‹”šœ™”Žÿ‡ynb[cuÿ†‘”‘‘‘Œß‚ujgkžà™£ÿ¥¡”†~{ujÿ^UT_s‡• ÿ¦ª© ’ƒwoÿjfgo€“¡¥ÿœ‰s_QLMUÿcvˆ”¢¥§ÿ¤˜ˆ{usrpÿmjlsz~ÿ„‡†|ndemÿw€ˆ‘¦©£ÿ™Œ~rg][dÿvŠ–—‰ˆˆÿ‚wlginu}ÿ†‘›¡¡š‡ÿ…n_Zcr€ÿˆ‰ˆŒŽ‰‚û{tF mrŽ›ÿ£¤¤£œŽzeÿTMUf{Žž¦ÿ¢”kaafmët~Лµà‡€xûmfK0wxy|‚ÿŠŒŠ„|vÿrpu}‚„‡Œÿ’——Ž€tonýqú˜›—‘Œï†|pdÐA…ŒŽÿ”™š’ˆ~uÿmhhmz‡‹ˆ†‚wmgñ`ÿ{‚‰” ª±°ÿ©š‡r_RQ^ÿtˆ“’‡|vtosrqró ŒŽÊ0ߌ‰†‚~`cÿint|„Ž—š÷•ˆx˜0kq{…ÿ”—™›™Ž~ÿpiinw}~€ÿˆ––‡|s¿nlnu€ŠÌ0Œ’ˆ}peÖ0¿q{†“ c zÿl_[_ix†ÿ–—˜›œ—‹ÿ{qc[\h~–ÿ©­£“~i]Yù\OPÈ0‘Ž…ÿ}vpmmnrzÿ‚ˆŽ“•‘Œ„ýw¾ckt{ƒÿš£¤Ÿ–‰{pÿjkqz‚†‰Œÿ”“‰ykehÿmouƒ’š›ÿ—’Žˆunlÿorvy{ˆ“û™–‚psmjkrÿ}‡–š›˜ÿ€pgfltˆÿ’‘‹ƒ|{~ÿ€|tjdeo{ÿ‡“ž¢ž‘rþ¸ðmkoxƒ‹÷‘’Ãpmhjoïv}ƒ‹P0”‡zÿrpqqsv{‚ÿˆ–œž˜‰wÿg`dnruz•’‹À}rlýoÆ1••‘ˆû|qVjlqz†úP”@rkkpvÿ|€ƒˆ‹Žÿƒvmigiouÿ|ƒŒ’–˜–ÿ„uiglrwz¯}ˆŽT0‚WÀiÿmv€ˆ‘—›ÿ™‘†zojklÿosv}‡””¿’…|toŽ@zÿ~…˜š‘ƒvûnf–Ðpz†‘™ÿž¢£ž”†wjÿfimry„š÷œ•‡â1hjpyŒŽjP‚vÿonprttw€ÿ—š”‰wqÿlils|…Œÿ•ž£™ˆzrrÿuvtrv~ˆ‘¿””“‡{Ç@wwƒ„¡@˜•‹:ðýsÁ0sw}…Œ”ÿ™™“ˆ{qmn¿opt|‡’>P‡÷ymh5Pw†Œÿ“™œ”†ypýné@x|„“”Õ)0u`w „Œÿ•—’‰womÿmmos{…Ž“ï‘Œ‡€7`otxÿyz~‰–œ—ß‚ytrqÄ0zŸˆ’˜š—³Ðô`x¿wux‹“ý0€ÿztpnosz†–žž“…Faÿqqqu{ƒ‹ÿ‹ˆ‚zsopÿuz{}‚Œ”—’ˆ}tpprîPùyJP ‡~urtïvwuu@›™ÿ€wttromr]zJP”—”P tÎPÿolq~œ™ŽÛƒ{i`sr8P‡ý“îЃyttvvûrn@’’Šûƒ}¶`xy{}ƒÌ¶QÝ tt* ŸA•—ú3`À`wxxw|ÿˆ”—ƒ{y{ÿ{wrprx€†ïŽ•™—vuv¿smmuƒP„û{À0twz~ƒÿŠ’™˜vsÿuwuoko{ˆÿ‘‘މ…€zÿvwz|{{€‹÷–˜‘® zxrlýkP‰’“‰ö¿`vyÀ`|Š”•¿Ž…~zxuÕðrûy€ç`•’‰}vþ)uqpx„îMP„€|À`vxzÿ~†‘—•‹€yÿwyxsmlr|ý†¯pŒ‰„}xvÿwxvtwŽ•ï“Š~wh`smküËqÕP‘ˆyy|ÿ{uqs|ˆ‘“ÿ‡‚€~ysnþ7P‚†”–‘‡ÿ~zzzwpklÿu‹Œ‡„‚¹U`]0z€‰o`…ÿ~{|{xrnoïwƒ‹ŽF@‡€Ï|||z‘€P‘Šÿ‚~~~yrmnçv~†;Pý0|{ÿzvqpv‹‘¿Ž‡‚€}8vk{~Å•’p}N¾ôa‹‰ˆhpwÏwyyxüAÝ€ÿ}tkhmw‚ý‰Ž0މ|zyßxustz±ÀŒ„€‚}tno4ÿ‚Š’–“Œƒ}¿||{wqpA‹ÿ‡…„‚}xut÷uwzù0•”Œ„ÿ~}|yrkjrÿ|…‰‹‹Š‡ƒ»~{€wvye€ß‹„€otßy…ŠŽ€‚÷~}y”`y†ŽŠ„‚~“Pžp’¯“ˆ‚æ€wûPv?‰ŠŠ‹ˆõú€ýxa0‘“ކ÷€{qPu}ƒ‡½Šñ€†‚}zØpu÷{…‡@ƒƒ‚~ÿwpmov~„‰Ý;‚}'`pw„‘„ƒ‚µqê@€.ëp‘‡n}‹@í€ßŠŠ‰‡†Ö€zxýxp‚‹’’Œ…¯‚~‚ƒ\ŒïŠ…€È€zwx}…‹ŒŠ†…3 î“b{‡˜“€|ÿupqx€‡Šˆÿ…ƒ„„zsp4p€–€¸@V’ß…„ƒ…ˆ‰€|{÷ywvü@Š…Ûƒ‚om+`ƒ‡û‰ŒÎ0ƒ‚zt?qs{„‰‹ô8¢ÿpqv|‚ˆÿ‰…ƒƒ}wÿsrw~„‡‡†ß‡ˆ‡‚zÌðvzß…‹Œý„‚ÿ|tmlqx„ÿ†‡ŠŠ‡‚~zwutëA©¡ÔðŽ@|€…‹Ž†€³pC€þ ‰Š‡…††„ý€Jpux{€‡ŒÐÐôúT!…ý†‡”Õq{© ‹”6 }uoot|€‚ï€&󀀄 Op‚üü~sllqw|ÊàûÝ ~zusßuz‚ƒÈ0…}ý|°tuy€ˆŽ>°q††ƒ~w§`-a·…†ˆ³p~{À`z袀•¡0zÜPuz}é~°¬ ƒµrw~…÷Œ…±„|tqþJ`{„ˆŠ‰‰yŠÏ0í‘w~+P‰„~yLqš v°‡ìb ™@opê@„ÿ…€…‡ƒ}xtÏuz€…Œ Ì ˆ„5~‘sᄆ@¡ô€xttx~‚„6°ý‡PxtrsuyòwŒŸ¢Ç°w~|[~…ˆ€ƒ‚7 {û€ð©¡Ú f0ûqv{Ñ0 5 k€y`…î_¢‰…|ÜPs{‚?ƒƒŒŽ‰Œ‘•pÃz}·€ZÊ>°st|©`ñ€ˆ‡‡…€‰°¼@™`‡Š‰… v¿tty€†‰°±ˆÿŠsmt|}yùw€”°‰†{v½vôÀ…†„„À~kxv‡ y)P†ˆü°xg1i  ƒ†‰ˆ´pÑy‹p`°Ô€…2 ‡~©°x{|}ƒª¡® yz} ÀƒáPлІPÀqrtÁ‰ŒÎ€|x`8Á…Á7…„}ÐawyS°Ú ö`|xGP~}~µ‚8±Évwðˆ¿‹ŽŠƒ;pwçy|~硈€‚€«|xÕ ƒû Š3 wqswp±NЧÀ'{ybðš Šf0Ø€FMp{€^ Àgp{K`Ç{{z\`Ü¡s`rt[{‚Àà†ˆ^ö€Õw }•ÀŠ…±xu°ÑÀ…‡‰ô‚¶`GQ¹…›ÐÊzvvÕ †W†€Í°‚sÀw%€?}€ƒ‡‹Ô@؃×y}‚Á‚B‘xz®+Єˆ3 ƒ„ sqsx~•À€žz?y{~~~*Q_‘wssvHP¿±øÐ àz{z{|;ÐÍ úÐâey â¨2~€zuw{÷0•À‰€sÐ+Ñ]‡-PŒ†sÀx.á”o0v²}wÐ{ÔКш™ƒÐÔ¡€ê >…€Ð*à+ÐZC •p5Á‚Á„–ÁgpÑkpq°‰ˆ¯†ƒ{îÑ9À„~ü„„ƒ}vsÁÖÐÑp€ÀÀè!xÀ“âåxÔ }ÙáÎ|znK`||~¾°†…V zËÀ{ðïµ°ñà€ ¨ã¨À}}npšáfÀéÑtÙ=àƒêჀ~np Mð)P²²ÔpÖpyÀ—À’á^€8Ððb òPâ@¡ ið«€ïÑr@€ ƒÐ àÃÀnÐX°Ðñð¹Ñ/ˆ„}–à{ƒÀzÁõ‚pçá#03Јñ›ñ𘪪ÀïÐ}}ÚA¢} ù€ïÐiÐ0ÑÐ{@€}màѰ¡â€:ÐAàgò€+|~ŠàƒÙ‚þà©ðzá[Ï1ñá‘@wÁD vá@yâÌ KKñgàˆÒ°<°*á fÁÀàíÐ*ФÀˆuð‘€ÅàDò¢â5 „ÀJ2ÍÀªà†¶óÌÀ ÕЃñ€}C5† ±np÷0 áñKóëðýñ¿à€^€yá¾ñkÈ€&ÃÀ‡BH°ƒÈÈñiÐ9°]Ná ª·ðÇð»ñ €vàVÀmá Öó¡†ñNò² ð!TÌá}ðñ@æ€fCñ·ëÒ›ór¡JñâᳩWÐé ® Y°@¸ñ˜`ê 0ŒÀÀ€ðÀÙÚnpjâб_±èáë¾ñÍà!#Hô@”.êšáÇ6$}ñFòñtñ!Þ,ç-C#¥Iñs «8&o%ñ>"Ÿ% n! ° "‚!E%màº/D%ã#ø%áà¨"„IõÆàäê¢%m)g4Ðe!="ªD Ëñ@#d"æäØ©$v4N3ª}òõÀW45¡6k%X2Ó#n$‘šá÷"ï ²#*(3@€å"ƒ1È‹1Éàî1BHo" 21òÏàÁ73H2Š2Ͱ:C%F‡4Ë0*A"QD:B-ð`ˆ$E1X1i%‚1€~e!å"í7k$ DOáÉ"j€{AÎÁ8IÎEà1ÙEwC!JÒ3ìC D*$„nð4ìE)1Ò$PäFDES(GÚCÑÀäBABhEU VD„8‚iTWkTk2Ì2:Dà’CG4BáGCD*Eåá¦QäE02Ïà B"¦UY5YY£T‚OS+d#ljRw4Çàn`nULljfX0/óhVÊAkdC`Vib@Ce$U¬coR¥ZEãC'òRØV.dÙV RgDÐ¥Qci4¦SyB šf·€ŽdüWìhØg>tndˆ4m`BaÁmêOr¦P…täábt—wm`DÙuÃwxãbwÀj2ÍvÇyýc'%t€€ar RÊT¼sTs¡p¹WÈcüdc……ukbfÊrØd‰t€tˆuÜqB`H1 Ñ¢ƒár®‰g3 …ápìQ‹@Ÿ‡‘aÎQ˜h!þ>’Y3Êxê…=’I3r†ÆAt‘ŸrjQAC‚iQãCw˜r“\‘+‹g͇/„`sGsБZ’,‡ –ʂÜ’brÍ•(‰ÏPZ“àr¥Þtê‡_“à˜7£*›¥5§Ä—ü“¨£“4sq’Ï…Acs‘¦•³¢â•Bc¥¥Í¥å¥o”¢bu³¦”ѤĘ’’¥”-²£`¨=¤T¨@¨à•5¢´¤å’´=ª2‚¤“°\»<¹_’N¸‚ªƒ´A‚y”Á¢ö±·“ò¸«dĪЦ[•·¸¾µÃ££”.ÆR¶yµHÆRÃä˜%ÍSʶÁµ%̇§\Ê,ÈàÍ“ÎIÇà™â´Ï²$Õ€±§—ö¶3ÕǨÕ5´å³€²KÏÙ=‘‚’ýÍ1±€²tÓ4ƞ։ء”ÊÛ•Ï£²¼Åöߣ´RÉ1ž´tÓéI×ð@b`>’"ÙpropÿDATEÿ7-10-200ÿ5, 13:24î~áNAM…ádoíoàen~áORIõG†à ¦å.wavÿSAMPµ@þÊâV"Zœÿ€€#€-€ÿ?€C€Q€O€]€X€`€Rçàý1Ýà÷€ëÿ2€Þ|_{Ž{ÿëzH{øzJ{ÿB{Y{¬{ì{ÿ¾|<}w~Šýrû຀÷/Tm`F̃ÿ>‚΄ƒv…ÿ ƒø„ø‚׃ÿå ‚t€ïÿO€,z|wÿw„tXtApÿ"ql.m{lÿ-kn¢jInÿÐnr*tGyÿ${d~ç€%†ÿņå‹ù‘ÿ÷–¦•L›M›ÿ˜ŸiŸï¢¡ÿT£*£G¢£ÿâŸJ ñ›ýšÿç—Í“‚ŽÆ‹ÿ-„ê€z†wÿÞrmnÌldÿ,b›^mZvTÿ+TZP7RûQÿÉQxTRÝUÿVJW3[o^ÿJ`¶d¤jmqÿ±vU¯‡‰Œÿ‘“˜ œ ÿA§K« °²ÿ¥¶ù·:¹E»ÿþ¸ï·Â´²ÿЮū¨à¤ÿUŸ9—“ÿKŒÕ…y vÿ·p|hŸaª]ÿ¥ZFTRéMÿìJÄHùCÉCÿšB–C¸EbFÿaHNKyLOÿZSœX¸Z£_ÿfdÚhp–xÿVÀ‡ÓÒ–ÿ $¢®¨¦®ÿÞ±¶ºB¾j¿ÿ¸ÁÎÃtÅ/Æÿ)•À]¼ ºÿºµp°´«Þ¥ÿØ¡0›Ä•sŽÿï…þ|ßuÌjÿJb\ÐTàPÿKËGõDÔBÿAV?K=y<ÿö=ô?ÂBìFÿIûK|QVÿ[Ç_e£hÿ p w™~ê†ÿ¯—°œ{¢ÿ]¨Ñ¬±Ž¶ÿª»ž½;¿tÁÿýÂdÅý¿ÿd½Þ¹*·J²ÿ·­¿¨¤²ÿt™"“Q‹—…ÿ*}¸t¦kÈbÿ­\]V QjMÿÀIuGQD'Bÿb@ABµCÿG JFMËOÿÏT,Y„^Mdÿ&i*nsˆyÿ§Ž…¶‘”ÿš°Ÿ£é§ÿ«¯ˆ±i³ÿOµp¶^·Ð¶ÿȵZ³³°“­ÿ0«T§Ì£‰ ÿ›Ò—)”ãŽÿFŠÏ„¼{yÿ}qÇj@d _ÿZxV`SYQÿÎN~KñI¶HÿœH!I*L„OÿR5UcX\ÿ `de“jnÿ¾ráwù{Úÿˆ)@•öšÿ‘Ÿ*£â¦å©ÿ–¬d®ê¯-±ÿb²‰²g²Û°ÿñ­«˜§Ó£ÿ¡-œÙ—º“ÿ‡µ‹·†›‚ÿz~éyÁsvmÿˆgHbÞ]’YÿSWV“T|RÿÞP&P‰O9Pÿ–RÕUÂY]ÿæ`d®g¡lÿRpNtxü{ÿœWƒˆ"ÿø’˜cœœŸÿH¢w¤§¦¨ÿʨª©Þ©ŠªÿÕªs©2¨x¥ÿù¡éž›'˜ÿ”!¼Œs‰ÿ™…Øñ~Ð{ÿxËrÊmEiÿ–dS`S]W\ÿ][5ZdYŽXÿ"XóWYl[ÿ ^¨a‡dúfÿjymÐptÿyw^z@}»ÿ[‚…ʉ7Žÿ’•â—gšÿrœÔ[Ÿ„Ÿÿ5 R¡¦¡L¢ÿT¢q¡ÌŸóÿœ š“—à”ÿ”’%zUŠÿчý…^ƒÿ{Êv×qlÿÀg¯d’bÑ`ÿ_²]Ï[GZÿ.YYUZ\ÿ¯^•`áb3eÿ×g½jËm±pÿºs„vòx |ÿŸ„‰7ÿV‘ž”D—šÿœ{О& ÿi¡Ë¢Æ£7¤ÿ¤£[¢¡‡ŸÿÁ‡›H™n—ÿ• ’@Gÿo‹'ˆw„±€ÿü{uvæp…lÿæh$fd bÿ`ñ]¾[ÌYÿ+YÕYãZY\ÿ^Ñ_Áa"dÿpf=i;l¾nÿgqÄsšvhzÿ~Nƒü‡Î‹ÿkì’•¨—ÿš™ ›¨œYžÿH ¢·¢Ñ¢ÿa¢ê¡ò jŸÿà‡œ1›¦˜ÿÅ•ï“B’ ÿ;3ŠŒ†‹ÿû{zv·qÒmÿêjChçe›cÿµ`°]n[=ZÿÃY4ZÓZp[ÿ¥\å]__WaÿªcBf›hÑjÿlmJpæs~xÿ6}¨B†hŠÿŽL‘”k–ÿ{˜Üšd ÿF¢|£¤†¤ÿz¤Ÿ£H¢€¡ÿ Íž:œè™ÿþ—Õ•f“¸ÿ¼º‰Â„ÿGyytXpælÿSjkm†oÿr(v z~ÿ#‚†|‰xŒÿøŽäœ’ß”ÿ™—#šþ›šÿûž£Ÿ{Ÿ/Ÿÿ%ŸážËYœÿèšQ™²— –ÿ_”¹’¡-ÿ߈ñƒ¹~Ãyÿ~ur=orlÿ\i*fcs`ÿ˜^u]#]R]ÿ]f^I_¢`ÿwb†dŸf”hÿj¢l(o#rÿ´uŸyØ} ‚ÿ†Ñ‰îŒ=ÿõÔ’O•˜ÿ€š€œQž¸Ÿÿ   öŸÿŠŸ­žRÏ›ÿTš€˜Ö–g•ÿÝ“y‘9Ž-ŠÿR…€ëzŽvÿs%p8múiÿšf™cÍ`ã^ÿ¸]?]I]’]ÿ^§^æ_–aÿšcbeNg iÿk¢mzpãsÿØwþ{>€l„ÿ{ˆÏ‹Ž!ÿQ’•Š—û™ÿiœ^ž_Ÿ§ŸÿÔŸ  „ŸÿxžOú›0šÿv˜—Ä• ”ÿߑ׎‹&†ÿí€Ø{bwösÿÇp†m,jÝfÿcï`â^š]ÿ"]-]F]H]ÿÂ]õ^™`lbÿddfßgòiÿrlIo¨rzvÿdz¥~ƒ?‡ÿqŠÛŒ/Á‘ÿ7”å–¤™Gœÿ@žlŸåŸ9 ÿ³ ¦ ! bŸÿržâœ›q™ÿ-˜ç–5•“ÿ3ŒH‡³ÿg|úw"t¼pÿƒmjÁf‡cÿÉ`ž^J]Ù\ÿÀ\µ\]Ç]ÿ_÷`ceÿñf i'k˜mÿ~p®s$wñzÿ@Ãć׊ÿtã’R”ÿ³–:™•›Hÿ&ž°ž2ŸXŸÿŸÆž!žÿ€›î™”˜c—ÿT–ò”#“ªÿhˆ1ƒ~ÿ°yñu°r{oÿLl.ifDcÿ2aû_x_N_ÿ:_s_÷_+aÿÈb€dHfh÷µiÇ`'párÿÕuny±}íÿs…sˆñŠÿúŽêN“ó•ÿ˜†™oš›ß𛝛µgp]›ÿ‰šd™;˜_—ÿ––P•”ÿø‘ËŽ´Š†ÿY3}¬yfvÿ?s2p m÷iÿgêduc¼bÿIbbòa:bÿcdje¼fÿûg+i»j˜lÿ¸nÓp~sêvÿÔzš~þñ„ÿ„‡³‰Œ‹©ÿ2ì’ •¿–ÿ˜õ˜}™í™ÿgšÊšÔš[šÿŠ™Ê˜:˜Å—ÿs—ï– –B”ÿn‘™)‰É„ÿÕ€V}zõvÿÆsŒpUmfjÿêg:fejdÿàc~cocÃcÿkdUeJfgÿùgCiájYl÷@nÁ@w1{ÿ~œ&„2†ÿ!ˆkŠ7Ýÿ#’”°•É–ÿ–—Y˜ ™â™ÿ5ššº™X™ÿõ˜Ó˜Ö˜¬˜ÿ˜¦–3”©ÿ£Œ”ˆÆ„:ÿì}®zuwÿs÷—pWÉ@›hgÿf&e‘d,dÿdsdúdWeÿÓe›fŒghÿÈi^k m¢pÿësOw™z¢}ÿ€‚„Ÿ†ÿb‰&ŒÃŽ‘ïû’ˆ”Â0–1˜ÿJ™šyšŠšÿmšqšŸšîšÿ+›ðšÈ™~—ÿI”šŒÄˆÿA…Õb~ÓzÿwmsúoþlÿkjghÑfžeÿ—dÚc˜c»cÿÍcâcFdédÿØe¾f«giÿQknLq¼tÿKxy{ò}M€ÿ¸‚f…<ˆ%‹ÿö…Ä’r”ÿê•a—ª˜Ñ™ÿš›!››ÿóšþšZ›²›ÿ—›’š˜•ÿÚ‘ŽXŠÞ†ÿpƒùN|‘xÿÕt[q8nrkÿ-iugñe·dÿdÀc²c›cÿ¥côc¨dceÿfÇfhjÿl‡oírWvÿOyÊ{0~›€ßMƒ †ÿ‡@£ŽÿÙÅ’‹”4–߯—þ˜×€ ›ÿ=›W›¢›>œÿМúœDœ’šÿã—„”çQÿÙ‰k†ë‚ÿ!{Tw›s+pÿ=mÐjªhÚfÿ‡e dd¾cÿcc0cVcácÿddÏdŠe™fÿq4tÕvÿSzl}Q«„ÿ°ˆû‹+“ÿu•´—(™í›ÿÜœIžŒžáŸÿ¡+¢££ÿ_£¾¡ÃŸ¦›ÿ€˜“<`Šÿƒ½~wFrÿÝkÿeß`èYÿÕW¶S-S¸PÿHP±RSXÿX[c_ÊaThÿ²i^påtzÿ^€ …È‹ªÿÅ•š¤œî ÿ•£¦e¨S©ÿî©Þ¨´©Ý¤ÿø£ØžU›y•ÿa’©AŠÓ†ÿ€h~dzísÿ(qnl‹k%hÿ’fÜcÎ`£`ÿ(\µ]H\,\ÿ$]øadÀkÿžq)uËzê~ÿ‚x‡|’ÿ¸•JšfœEžÿ÷ŸZžqžaœÿ˜œÝ𛳗ÿ–ì“)‘“ÿ‰|„ƒ}kyÿ™rVn_mûhÿ6g¢dgb `ÿ€\J]]aÿib²ePh¹iÿmk¼oÒp¤rÿ|uºw¹|ä‚ÿ͇õŒ’æ”ÿ¦—Z›Áž ¡ÿY¨¨f©>ªÿí«Q«¿§¤¤ÿ :›—K’ÿ$‰K„½ÿäy´q©k¾bÿŒZÜUïPçNÿÀKsKK–Kÿ®KÔKMQÿÜTzZñ^fbÿöh§o&v/}÷ƒèð]˜. ÿP§g®X±‹µÿ$¸˜¹«»Š¾ÿU½ï»hºl¹ÿ9·ý¯K«'¦ÿ¡ºš”>Žÿn‡ {«qÿk•a­X Oÿ=HiC?µ<ÿé:.:;919ÿ;?1CIÿ OvU3[3cÿvjCs·zñÿ¥ˆöŸ˜B¡ÿ€«U³ÀºÀÿÈÄãÇÊÊ{Ëÿ¨ËüÊfÉ7Æÿ·Áê»SµÁ®ÿú§ÜŸ$™Aÿq‰ñ‚4{#tÿwl-e†[íRÿ0K¬Dï>Û:ÿÇ7Ü5þ2>2ÿÅ2v4}7Y=ÿ›BñGÜMSTÿ\LdŠlsÿ‘{΂‹F”ÿ@ž §ë®µÿVºi¿ÞýÇÿÉÊvÍ@ÏsÏÿ_ÎmÊÆjÀÿ×¹ ´™«ù£ÿÜ›W”²‹-ƒÿ#{Brêg^ÿ=UÕMüF!Bÿt?–<–9m7ÿ6l5E7‘:ÿ[?D²IÎNÿ Uh\bÿhÿ[o¡up|x„ÿVQ–÷h¤ÿÚ©É®p³Ç¶ÿ¡¹Ó»™½u¿ÿ.¿¿/½»ÿ—¸±µ“±ª¬ÿ÷§ £—ÿz‘劧‚Îyÿ¢qiaÝZÿ‹VÐQNzJÿÎG™E–EÇFÿ1I LôM‹PÿÄSõVeZ/^ÿbGfˆj§oÿûuÌ|ñ‚^ˆÿ7’Z–Èšÿ¬ ¡¥¤¡§ÿ³ªq¬­ö¬ÿƒ¬¸«5ª¶¨ÿ´§o¦§¤Þ¢ÿÚ¡@ŸÎš=•ÿjŇr€šzÿ±uøpYl™gÿob¦]ŠY WÿQRUÿgYÎ]]b•gÿrmÐs½z¨ÿlˆÖŽß”Ê™ÿ3žÜ¢¨"­ÿα¶.¹Êºÿ»Ñ»q»ë¹ÿ[·h´ä°È¬ÿΨµ¤ôŸ[šÿ«“Ü‹ ƒFzÿ@rÂk,f²`ÿE[ÏU™P6LÿÓH«F˜EïDÿ—D9EöFBIÿLàNêQ’UÿðYð^Ëd'kÿr”yu‡ÿØŒ:’l—`œÿF¡¦ZªÎ­ÿ‹°M³Úµf·ÿP¸»¸(¸Ñ¶ÿ@µ³ ±È­ÿO©d£œs“ÿ ‹sƒC|tuÿ{n‚gÒ`äZÿV´R•P¥NÿMùKKLÿæLòMWO;Qÿ“S¼VˆZó^ÿdjVpÇuÿ…zƒSˆÿ–/“t˜»œÿ "£s¥§ÿw¨œ©Vª½ªÿ„«\¬5­c­ÿĬܪ§½¡ÿ¢›Ã•mF‹ÿ†‚€Þzûtÿ~oäjg‘cÿB`]]F[SZÿöYûY!Z5ZÿiZ%[i\^ÿœ`fd¤hUlÿ˜oŽr_u`xÿî{5€)„b‡ÿŠÃŒVØ‘ÿ§”J—\™Öšÿœ>`ž[Ÿÿ ñŸ¶žIœÿ™é•E“üÿšŽú‹Åˆ…ÿC~s{Kyÿ4wuürGqÿ¾o1nˆl§jÿi?h h@hÿgi¨kAn‰pÿ@r“s‘touÿÝv#y™{}ÿ%¥€óQƒÿ…®†ï‡±ˆÿŽ‰åŠ²ŒðŽÿ.‘×’“À‘ÿã‹.‰‡ÿt…„º‚:ÿȨ~6~n~߯~³~oó0~ÿó}§}í|$|ÿ {ïzz¿yÿzïzà{³|ÿc}Â}í}s~ÿ«Ô€‚èÿô¿ˆ•ÿÜó²|ß„ûÿµ€á„ÿâ„Áƒ—Cÿ\}|{)zÿ÷x7wGuˆsÿœr«r^sŠtÿóu€wUy…{ÿ…}˜€äÙ‚šƒ„qÿGŠŒQ£ÿ€Œ[ŒcŒÿ—Œ¶ŒÃŒ•ŒÿŒž‹'‹bŠÿE‰ç‡_†C…ÿ—„<„냃ÿ ~³z"wÿÛsq…nl÷¨i‚w(e eÿoe.fûfÓgÿikmWoÿrûtx{ÿ4~‚o†öŠÿM7“–ý—ÿ°™[›„žÿšŸ ÎŸ©žÿ]Ù›Rš£˜ÿ˖͔ϒëÿJØô‹&‰ÿ?…P€{üuÿIqmþheÿ_aû][ÒXÿ2WqV5VÄVÿNX¯ZI]×_ÿkb3eâg]jý §€#uYz!€÷†iý°|”­˜ÿØœœ ¤î¦ÿä¨4ª«—«ÿ›«#«æ©¨ÿ¡¥á¢l \žÿeœÞ™a–½‘ÿ-Œ6†J€zÿuco¦iCdÿ_rZ VºSÿwQP•O¿OÿIPëPèQ”SÿþUšX»[k_ÿ¯cŒhöm~sÿ´x‚}‚Þ†ÿô‹1‘š–þ›ÿå F¥©h¬ÿ ¯ú°;²Ó²ÿ¡²²V±Ê°ÿ°¢®Ñ«x§ÿ«¡›>”´ÿš‡j {°tÿ=nh€b…]ÿY/U?RPÿsNMKLELÿÛL¦MÏNgPÿ‡R°UñY$_ÿÔdwjpluÿ¶z€‡…èŠÿô”ª™&žÿb¢H¦Á©á¬ÿM¯±Â²Q´ÿƵ ¶K¶‡´ÿ+±º¬†§&¢ÿ˜œo–¿™ˆÿ- z‡sªmÿPhrce_û[ÿYGVT_RÿQ%PƒO:OÿfO–PSªVÿÁZÛ^Ëb¥fÿ™jot·yÿd …hŠ_ÿÇ“¬—5›xžÿM¡¯£¦¥¨ÿz«®A°T±ß±=¯w½h¥ÿ,¡~œ*—x‘ÿÁ‹4†¬€ {ÿ£u‰plhÿ—dÆa„_ ]ÿÿ[¬ZsY_XÿúW·X”Zö\ÿ…_ñaZdÏfÿ¹iWmpq‘uÿ—yn} ‘„ÿˆÓ‹‡÷’ÿÁ•>˜‰šèœÿAŸh¡Ú¢\£ÿº¢6¡EŸÿÏšT˜‡•.’ÿŽàŠ9‡Uƒÿvü{y™vÿRtBrCp2|9éEÿ®SÁ^äk yÿ„Ü•ð¦ëµÿæÃÑåÔÙÿßÿÛ]Û!ÚÿíÖ¿ÍÀÆt¿ÿÜ´„«´¡ÿ‚Ãs¸e£[ÿKWÕO K€Kÿ·HóFaI{MÿUOU¤YÔ]ÿ%gpp:wãÿ&‰ù‡¸‹iÿ#‹‰ŠOˆÿ™‚½Î{ŸtÿGr%nüe®`ÿõ[­®§,¤ÿFž/—°‘Œÿ\…¡~5xQnÿfž^·W2SÿgRoQQÆSÿ¿S—U€ZY]ÿ _bad„fÿlás¯x.~ÿô‚º„’…-‡ÿù†t‡ˆ‰Ÿ‰ÿf‰½ŠïŒÿáŸoŒð‰ÿŇ…N…šˆÿ‹\”–ÿ™E'ŸzŸÿAŸž£œ¿ÿbŸ¹žÓ€›ÿµ• hˆÐÿñxõrl´dÿe_ZaUÝRÿ}N2I EÕAÿ…>a?BEÿ]LESZXþ_ÿ¦hÚpèx7ÿ¢ˆf¸˜À¡ÿ»©ã±º¸¼ÿá¿Á©ÀYÀÿ®¿¼¼Á¸?µÿî¯|«t§ä ÿÅ—ÅŽÀ„ñyÿíqk]eÁbÿs_[¡Y¡X÷pWuð TUSÿ¢UvYª]cÿêgåjnpÿqÞrvuvÿ‰wøy¾{Õ~ÿ󂹄„rƒÿî€á~ûFÿ „ ŠâŽœ’ÿÄ–››õž¢ÿܤ¥?¥5§ÿ6©Íª­=­ÿs«‘¨j£»œÿ—Á‘rŠÛƒÿ0}žuEoœjÿæcM\|UðLÿELAR=v<ÿº>í@3C,GÿëL‡R)Z;bÿh3oùwj€ÿZ‰†“Lœ¤ÿߪT¯n±b´ÿi¶M¶óµŠ´ÿ±w®ö¬š¨ÿœ+“£Šÿ4ƒa{âuÔrÿ6pamglókÿkklšjÿ¿ikmÐpÿƒuny—|ÿ~ý£pø|È{•yÿx²vt sÿ¡twsôqToÿˆj­gfeÿ£fæj_o„sÿIy“~Pƒ-‰ÿ©Ž‘ДØÿ¹œÿ¡§´«ÿ¦®o°è®½«ÿá¨M¥E ‡›ÿ‰•’w‡_‚ÿë{,vÉn‹eÿÇ]êV QÑMÿéM¥N¿O•RÿnUäXÂ^ÿdÿ‡i°nÇsXyÿ{€[ˆ¨—ÿú¢k¤©¦ÿª§§e¦¾£ÿþž›ø—““ÿuÈW€Mxÿ±pNi-d!bÿ_„­…ÿä†Â‡"ˆ1ˆÿ‹‡†…†‡ÿ†¥…ðƒÊ€ÿˆ}Þ{Ûzözÿ„}–„ˆÿñ‹ d”v˜ÿ"› UŸ\¡ÿ £á¦ø¨ªÿmªa¨˜¤ ÿÑšª”‘<…ÿ‚|÷t”nhÿXaoZFRJJÿeD?T<Æ;ÿ)=f?ÌBÞGÿTN;V~^±eÿnlËs4{÷ƒÿ}Žy˜I¢]«ÿ?²þ¶jº¼ÿ ½Z½ÇºÓ¶ÿ³‘¯a«–¦ÿ  '˜³Žµ…ÿä|Tup~lÿâiágPf®eÿmf«gIhähÿ¯i/jVl pÿtžxÊ|+ÿÛ‡†~Ð}ÿ}/{œx¯vÿNuãsÝrTqÿ1nÁjôg´eÿÅdfi,mÿéqÓvX|Ç‚ÿ5‰¶Žþ“ØÿÏœø¡f§@¬ÿè°¥´‹¶Ÿ¶ÿÕ´‘±”­¥¨ÿÝ¡á™f’F‹ÿ7„Á}rv˜mÿhd­[ÂSãLÿýGEçCADÿ«E±HºMUSÿ¥X_^“còhÿp‚xŸO‹ÿ_”œ<¢/¦ÿ–¨_ªF«ê©ÿÔ¦ª£f >ÿ¾š4—¬‘·Šÿ>ƒ%|Ñu>qÿpnBmmÓlÿ>m\oÐq7tÿw×xOzÅ|ÿO€Ì„ŠÿÑ’ÿ”.•Ø“ÿh’‘ŽÅ‰ÿ_…¸€Š|ayÿþu‡q`l/gÿ`b¥^“\7\ÿ¶]·`âcƒgÿŸlÇqòva|ÿ§€~„܈Àÿ “ИNžú¢ÿl¦¨Ú§È¦ÿE¥Ó¡êœÆ—ÿS’Gúˆ_„ÿU~\w4piÿÉb±]ùYCXÿtXaY[£_ÿ!diLn‘rÿqvÔz€Q†ÿPg”Üš% ÿ¨£¥³¥Ç¥ÿߣ[ ë›õ–ÿO’ƒŽ§Š1…ÿd~¾v¦n.gÿ=aË\aZÕYÿ°YžZ]\`ÿ¼dœiÙm~qÿcuöyŸ<†ÿTÄ“3™Îœÿ.žëž‚ŸÇžÿÅœ™™¶•Ô‘ÿzŒÿˆž„ÿYŒy3tÓoÿZlkLk÷kÿymÙo¦r)vÿzl}ÿU‚ÿë„ ˆ ŒYÿa”ۗÙN™ÿæ—¥•’‘ÿBˆ_‚À|/xÿ&t±o™j eÿ _°YMURÿ(Q$R„TXÿá]dktrÿcyŒ…æ‹ÿ“!›Š£˜«ÿ³x¸f»ô¼ÿC½ë»¿¸´ÿÀ­§Â Êšÿ”Œ»‚fxÿOnÎd\ŸVÿMR=OMâLÿ¡M×O×RVÿöX¸[ú^€cÿŒiZp¦w ÿЄ ‰˜Œ¸ÿ’Ž“ç“î’ÿ‘¼¤gÿeɉ0†ÿQ‚Ió}º}ÿ¡~a€U‚¤„ÿʇ[‹ÏŽ{‘ÿO“…”ñ•þ—ÿ!šÂœ7Ÿ6 ÿqŸ1Ñ™=•ÿî´‰j‚Ëzÿtn™hcÿ\ÄUO^Hÿ÷B®?B>é>ÿ§AEªJ^QÿY4aMi'qÿÐxq ‹•ÿŸù©ë²ú¹ÿY¿ÃèÄ,Åÿ‰ÃÏ¿»3¶ÿ~±¿¬ §aŸÿ –ƒïyÿrkneõ`ÿ>]™ZˆYžYÿJZ[[ö[e\ÿý]Ï`—d©iÿrot±x|ÿŠ~J€k¯ÿs€Š~È|µ{ÿ½{Õ{óz¤yÿ³wu6s§rÿsátÎw0{ÿô~¸ƒ5‰ÇŽÿ+”d˜l›RžÿK¡b¤S¨›¬ÿܯ—±’±µ¯ÿ4¬í§¦¢Æ›ÿÍ“q‹rƒ…|ÿ¸uLn¥fW^ÿ•UÁM|GÅBÿ%@œ?‘@¦Bÿ[FJK%Q‰Wÿ¶]‚cíiqÿÑxÁw‹ž”ÿÅœ|£É¨f¬ÿú®Z° °T®ÿ»« ©Õ¦6¤ÿ‹ Ñ›ó•úŽÿ/ˆåa|¦wÿ>t{q£o´nÿÊn—oåp•qÿïq¬rêsÊuÿyø|2Ü„ÿˆfŠy‹äŠÿÀ‰s…ö€3|ÿZvæq=lfÿ¨_­XR·PÿðQX¦`™eÿLmòuæ~/Šÿb—û¡³ªM±ÿ]±ú°2¬ï§ÿ<¤.£¡?ÿJ—¶ƒ×{ÿsn”loÿôtôxÒ{¥|ÿœ|›~-‚_†ÿvˆ[“ž‰ÿ\Ywún¿jÿíhkf6d`\ÿ©TPO‰J–KÿÆR£_'rÇ‚ÿøòš°¡ÿ¨ÿ™±¹¿¾ÌÆÿÊ0Èò¿d°ÿ¥žŒí{ mÿ#aüR‰Dò8ÿ§-›&ž'J-ÿ—9FIŠYÔjÿ;yú†©—‚«ÿƒº ËÒÔÔ×ÿŽÙA×j̺ÿ%©™–—‰ÊyÿDh½YìH´8ÿe2E.•+x4ÿY?’MH\/hÿv`‰Ï˜I©ÿ,µ¹¾¯½ÿ½gµ`ªÁ ÿš™g‘ƒßvÿ^h{YOÚKÿjIÐJ*TZ\ÿ gntÑ~ÿ‡íŽšæÿ'Ξ*›™ÿÁ”‘Š$…Yÿ—w¨m¬d¤YÿTCRgY.dÿo}Û‰k•ÿ€œÛ¨½²&ºÿÃ_ËáÌaÈÿ$ÂÙ¶J«Ó˜ÿ‡£y÷gwUÿÄEì3f%ÿ'€+"Ë,ÿÕ8ýF²R cÿqx¯‹‘¡K·ÿÉɾԡØjØÿiÖ]ÏUÁö·ÿȫΛ)={ÿ¦g V+E;ÿ :ˆ<Ý@½IÿíPL[”kM|ÿ‘ ¢Ý³vÂÿçǬǃÇðÇÿ˜Ã2½Ö·T«ÿÿsyWfÿÛSõC±;Ä9ÿ±9>çBUEÿMU3]&iÿ(vÁ¸ŒžÿÑÛ J‹ÿŒ{ˆƒœ|ÿlskkf dÿƒgÒqg|‰ÿž”÷›a¦”±ÿǹÃŒÌæÓÿÙèØ@ЯÄÿnµ`¤t–À…ÿás)cQS?ÿI0a$  ÿÿ%t.29ª@ÿ‡JOYkhäxÿ ‹;ý¬ÿ·ÿbºƒ¸=³pªÿ®£˜›˜‘#ˆÿ}p0c±Vÿ L IÞJoOÿªX"`Ðgçsÿí€ÝŽÈžÂ®ÿD½ÌÈÍÅÌÿñÊ4ƹÂô¾ÿ¸¯õ£O•ÿ0…uXdÞXÿÄR‘OSQ¾SÿÀSVY¸[ÿ»_se$lUsÿ½v?uÄr£mÿµiBhYf)dÿ“a#]OXÅUÿG2Pÿ \¶h!w÷†ÿT—1¨,¸ ÂÿôÆOÈÕŰÃÿ_Áë¼"·ç°ÿ,§Ã›ƒŽÿúsìkgZgÿ—ikãmâoÿ+q¶s~vŒzÿœ€ „…ƒ¸€ÿ8zgsçmchÿ2cE_«YOSÿƒMGôD/HÿOáZWiÀvÿ „²ž›¢¦ÿͰº:Ä}Ìÿ;Ð*ÏœÈ~½ÿ;±0£õ“û…ÿZwhœY)JÿZ=6i4Ï8ÿBìKŠVšbÿ¬o4~¦Žüžÿ°#Àj˶ÐÿÊÏsÉÓ¿f´ÿ¦|—9‰zÿkíYæGõ9ÿy/F*,•0ÿ7b@QKzWÿPfav,ˆ›ÿƒª¶µ÷»x½ÿ4½o¼"¹t´ÿ¯8§¦y‘ÿ‚2tâh2`ÿ ]ž]`1dÿËhmIr‹wÿî}´†´Ž^”ÿ8—‘•1‘÷Œÿ£‡ù}ãvÿÏoEhç^&Wÿ•SðR¯W´`ÿlkìv‚¾Œÿà–º N©Ÿ²ÿc»òÁ¨Å¤ÃÿÜ»“±b¤I•ÿ؆¦wDhïYÿMJ0;0y(ÿå&¹+Õ3æ=ÿêIVÎd›uÿ膖™â¬â½ÿÎËÔÕ+ÒÿõË÷ÁƶsªÿZÕ6‚!qÿå`ÏQOFÆ@ÿ°?ºA¥FGMÿgUç_Àk¿yÿû‰™N§¢±ÿ)¶’·¿·Jµÿf±Z¬6¥UÿN“7…KvØgÿîZ7RÀM®Lÿ¡N.RßU¿Zÿ”_Be³mwÿ€Iˆ^Œÿ¶Œ¥Š4ˆZ†ÿ²ƒÿ€·}¡wÿbqÞlajØkÿ¬qày„ÔŽÿJ˜@¡~©=°ÿ6·¾ÄÉÿôÉFÅó¼±ÿA¢ï’‚¿rÿ(d0TüCb5ÿé(ü ^;"ÿ¸(&2l<^Hÿ»Vfwp‰ÿ1›~¬³ºSÂÿÅÝɾ·ÿÛ­D£™ÜŽÿÚ tÄeÊXÿ`PL5LõOÿÝU2]ÖffqÿD}¸‹šW©ÿ¿¶¿ùÂ’Äÿ7ÃÀ÷ºZ³ÿ™«¿¢–$ˆÿÂxühä[uRÿL´IHJ Lÿ(O¶ReÃlÿ$tYy#|/|ÿ{zx\tRpÿ.miøc¨^ÿ¼X"T SïTÿ-Zûb—m®yÿó…X‘Åœµ§ÿ¤±Þ»ÜÅaÍÿŸÑ?ÑAÌ÷ÃÿÓ¸S«©µÿrrMcTÿ¾HÜ@=>ÿµAèG)PYÿFe³rA€}Žÿª÷ªµÑºÿb»K¸%²Ä¨ÿ厒˜†‚zÿmÝ]GO(CÿD:ç525ï7ÿ>ËE®OÈ[ÿDi@x0‰Ö™ÿD¨Á³o»mÀÿ7Ã×ÂÀ4¼ÿ”¶¯ˆ¦IšÿzŒK}sjÿµd·a:bdÿpfÆiŠmÑqÿãwð~P…1Šÿ4ŒÂ‹á‰Z†ÿÐl}–xðrÿmf_ZÿW&WZ^`ÿisx|é…ÿ_Õ—b F©ÿ_±a¸8¼—»ÿU·ˆ¯ã¤B™ÿB€És×fÿWYM2C=ÿ‰;’=C_Kÿ.Uß`´nû|ÿ¤‹H›yªr¸ÿ{ÃSÉ›ÊÈý†Þp¸­Š¡]•ÿ¸ˆzjj>[ÿùMqDš><ÿY>ŸBÆHhQÿ¨[gát™ƒÿ’9Ÿ©±¯ÿç³ú´³g°ÿH«?¥Užµ”ÿ’ˆ„{¿n-dÿF\>WVÐWÿZœ^ŸcµhÿOo†w6€ëˆÿ½Í“•c•ÿM“Úy;‰ÿ¤„Ô~âwqÿ$krg~f hÿÃl=t"|„ÿyŒ/”Ž›g£ÿ«Ó²B¹;¼ÿ|»›¶ª­Ð¢ÿš–ñˆL{Zmÿ›^ÌOÞA[6ÿæ.‹+D,!1ÿ©8JBšNÀ\ÿÇk|ÅŒ£ÿÉ­cºÚÂãÆÿ\ÆU¼÷²ÿò¨‰žÇ’¿…ÿsw8i3]ATÿ‡NâLxN3RÿPXp`îi@uÿ:‚ë¿©ÿ²ã¸þ»é»ÿ¢¹Ú´>®Ù¦ÿ|é‘=„Zuÿ#gÿZìPgJÿìGÜGËIMÿGQ¥V½]fÿšoØxˆ€„†ÿŠS‹c‹µŠÿ­ˆ†™‚~ÿ*y tòoØmÿÂmGpJv/~ÿ醙˜è ÿ+©þ°ä¸„ÀÿÆÌÈ¥ÇëÁÿҸ׭ø  “ÿ›„{uf[Vÿ‘Gf;2|-ÿÐ,/å4û<ÿ8G`Sa[oÿc~õ[œ5¨ÿ°I´-´S±ÿ«¤‚›(’ÿç‡n|ºo–cÿHY†QwM5Mÿ“OæTf\eeÿQpÂ|–ŠU™ÿ¬§´_¾FÅÿÆÈ€ÉYÇ­ÂÿA¼h´±ªÙžÿƒzÿr±eÿÿZíSÎOkNÿOšPIS Wÿ,\ºbj÷pÿwW{}5}ÿ8|Yz²w–tÿÎpÕl~hudÿÚa§`€a£eÿl‹uµ©‰ÿ”“Y¹¦,°ÿˆ¹ÛÁ›È¤ÌÿRÌ È²À·ÿ˜«ðž[‘/ƒÿ|t~eÁWLÿcC>=n?ÿ:DFKfTb_ÿGkÔw…0’ÿ-ž&¨®¼¯ÿ®U©7¢6™ÿ d„yžlÿÃ_ SIÎAÿR>>AÒFÿŽNdXdvqÿ£€J@Ÿ­ÿœ¸ÓÀ,ÆŠÈÿ=È‰ÅÆÀˆºÿx²ì§Y›Žÿ£€­tÿç?œCIuQÿ+[g8t½ÿUñ›_¦4®ÿ\³Üµ¶´L°«ÿ£à2àÿz„ýxosgÿ¡b¦`å`Èbÿ¢e2intÿ­z“…ˆCŽÿÜ‘3“©’àÿ'Ž"ŠO…Äÿ–y”sºm9hÿFd“b£chgÿ m£sºzÀÿ@‰A‘ ™ ÿÞ§Ý­<±±ÿ@­§Ÿu•ÿ¦Šü~ˆr+fÿZ¶NmEK?ÿ¨££§§­ÿ8±›²„°ñ±ÿ¡‰Û|xsÿuŠz€zð~ÿøz¼Æ…Œÿ8™AW‰"‚ÿß|vtÑrOwÿóg…^¦c]gÿ~y:ˆ¯–ú¢ÿ²¥,´z¾}ÌÿµÐÃ$¶ø¥ÿ ’zSncÿ¾D×2+d'¿Å1Š8Hš[ÿpBƒøš’¥ÿ­¢Ÿ šíÿ܃?ƒnyD^ÿfPÀE´CVIÿ”Oª`‘ixÿ²¤¢À­ÌÿÖÏnÓýÖsÒÿ”Ì3Ðí¿£ÿnN|~uSlÿ eÊb·X„Wÿ¸X¢bÐoÇoÿnk¿j-nHjÿlþvXmtaÿÚ\×]{k¬rÿ±~U†Â‡êŽÿ–å¥`¯[©ÿt<“€ˆztÿÀk³gÃPü>ÿµ2›2í‹•ÿù¢Àªž¦Œœÿ8“À³‡ÿu{’suh;aÿ!dÅgìghÿ3gRedŠgÿépdv¢t3qÿ r»xS€u‰ÿK“s™š›Ž¢ÿõ°­»zÀ±Áÿœ¾Ë·¸­¥ÿŸE“ÿÌkÿ0]¦TNäLÿcNÌNîNkXÿJj°y[…åÿÖ’ÿ”½”,—ÿ©˜Åžqÿ=eV\šT.QÿXPNvMçWÿ‘iUys‡“ÿ}2¥ ¬,·ÿ¿º½¦³ž§ÿ_Ÿ+—(Žx†ÿ»}Kq²ffÿŽiklþkÿ±k…jåktßÜz;{ù-€%xÿ}‘ƒa‹>ÿ¥&‘‡šº£ÿѧ»§›£´œÿ¶‘ ˆG‚æxÿVi(V?GË>ÿí9‡:G@`FÿK½VulIƒÿW—`§"³)»ÿO¾ŒÂµÆ>Ãÿz¶¤œ“…ÿÖvlRd‰[ÿ RgQhZ%eÿªoYxâs…ÿ=‰p‘šœÿ™•‡‹Æ„3ÿÌyhv…s]mÿFf€g¦nvuÿd{j‚Gƒÿ,„“Š,‘,’ÿ5Œ]…ò‚"‚ÿ"ƒ›†S‰‡ÿQ„^‰T‘Ø–ÿ*˜C•”¿‡ÿ}‰{ÐvºlÿF]ÀOÉGiCÿîCµI×P‡Uÿ^Rp5†M›ÿŒ«r·w¿rÁÿ†ÃrÆ?ĸÿ¡¥ “r‚xrÿmeP\~SoHÿ©CÿHZS÷_ÿëjv‰›†ÿ†‘ Ÿ¦¨ý¨ÿ1£1žÚ™•ÿ#‘ Žz‡ã|ÿlwŠw¡yC{ÿßyžxvtXoÿ|oörãsømÿÖe0a __ÿ™b$hHjãjÿ8r"~U‹•ÿ‰šlžošÿ¶šÒ›J˜qÿªCy%sñoÿIqút>u½vÿ¸Ñž"ªÿ¨²Å·r¶J´ÿc³º°ô¥}’ÿí}Tk?ZÌKÿxBa;Ó1ß,ÿ¢0¢;ôJ—Xÿæffs¢|ˆÿ¸–ޤ|©>¦ÿ™¡ ,˜ˆ“ÿ×™‹s¯zÿy¼{ ˆÿ€;~¿y¼xÿÊ|±€ãzÿ­w(wâxu}ÿ±…¿Š9Œy‘ÿÜš]§‹°ý´ÿÙ¶7²â©¢ÿJœ®“4ƒîoÿ^ PÅD ?ÿå>Ù<¨;Ô@ÿóLP^£mF{ÿë†-¡‘E—ÿü ž=–ŽŠÿFJu&lgÿfŽaõ^;bÿÛl|x‰Õ–ÿ¢ö¨V¯2¸ÿ:ÂÅG¿¶ýmoq˜‘_ˆÿ{!o¥gçfÿShhµh gÿëba`;c iÿj§f*cHbÿ-cYf—n¦tÿ¢vÈy»€óŒÿH—Ÿó¡É ÿM›'•0’wŽÿöƒ+uqfTZÿfPÊKCN‚PÿÙR#Yf{ÿ£ŽÙ ê°H»ÿTÁÇ>θÐÿÊÉš¼R­œÿŸŒWuKiÿ]HTˆSRYÿn_ûfémoqÿYsxŠ€8…ÿü‚ö|wxqÿ…kÀiÚhmdÿŸ_g]{bÙjÿrèyÁ½ÿw‚ ‡áŽ­’ÿ ‘uŠFˆÿR‡«‹›WßóE’Ë0¹¨ÿ¬®ªî£;›ÿ–ᑌˆTzÿÒjš]kQÔIÿ²IÓJLÅNÿ¨W…h“zø‹ÿŒ›¦ÀªÑ­ÿ:³ÁµM°­£ÿ4”Œ„Js”eÿ)\SRPHƒ?ÿf>]EÿNE[ÿOhúrÕzÁ„ÿ“±Ÿÿ¥\¦ÿ¥Ê¢ ž_ÿ½œ™¬’h‹ÿý‰?Œ!ŽKÿþ°þ†wƒÿh„õƒø~švÿ?oIhYb#bÿ­cŸd&dkeÿùmyyƒ²ŒÿÓ’\“ÿpÿ¾„Žß†|ÿVr4h˜` _ÿ{_¹`)a¿eÿr}ïžÿû©¾®3°ô³ÿ²¶L³1¨ ™ÿ[‰ÒwHi,_ÿeV,N‘ECÿÙH”R_÷lÿeywµ‰]–ÿø¢oªÎª¨ÿģ䜘ˆ”ÿ¬ˆ<~?yÿyJz!|À}ÿ\| vYq¤qÿsÅqÏlhÿªd´aÏc´hÿˆnQrÉuÿŒ™°¤Ð­ÿÙ°4­Ã©Õ§ÿÛ£NšŒ^}ÿqmG_©VÇQÿQOúK}K RÿÉ^ m|-Šÿ“Å—Užî¥ÿªÝ¦ÀžÝ”ÿ.ˆí|ùt\oÿEjDc©_äbÿ­j¸tf€Ä‹ÿ’S–—g¦ÿ÷«Àª!¦MŸÿΕ¦Ë††€ÿxœlhdÒaÿžbÎd{hüjÿ‚hÚe‚glÿþnõmÇléjÿ?ikpÈvÿ5{‘}œƒŽÿÆ™c¤Ë­L²ÿƒ¯«j¨Ò¥ÿCžµ‘ÓƒésÿádZüSõQÿ»OOUaÿVqd‚”1¡ÿ²¨Æ¯"¸œ¾ÿ°½¾¶+¬Zÿª]ÐsniÿÏ\ŸQ[L5Mÿ¡QYÂbÛhÿ&lnqz+‚ÿÉ„c„Ø}ÿyˆvTvXuÿqýmˆoJuÿ~|”…}Ž’ÿÁ’%•jšžÿ/¤š>–áÿØŒ‹OŒKŒÿˉ‰ìŒ]“ÿT™zŸV¢jžÿ—‘+ÿ…ÿˆz’mÕ^ˆPÿøD>>£<á;ÿØ;@bL[\ÿnŸ¬‘ž›ÿÅ¢ «H³/µÿú°Š¨ì›Þÿ8€šuXmŽcÿ YíSíTZÿ-cÕoƒzÕÿ‰” §ÿUª@ª?§b£ÿ™ŸíÛ›ü•ÿWŽ3‰ö‡ä‡ÿ׉šŒ‹ý„ÿ«~e|—z{uÿòn¶f÷]MVÿPQ×PQ÷PÿpQ WDaÙlÿazφ®vÿÆä”å–k”ÿ0ë†j}Etÿ'n•lòkåjÿlTsë~`ŒÿtœçªÛ³5¸ÿ–¼F ñ½ÿ‹³é¤”‘‚ÿûsÇhi]PQÿHªEÝG3NÿWY„d¤lÏrÿ.|ˆvÖ”ÿu•Ä’8މÿì…’ƒ‡~©vÿopñnÎoºsÿ‡z½~A~šzÿÏy¸z[y6tÿŒkï_~SùKÿ×MåX‰høyÿE=¦ÄÂYÜÿ}ô‚ø»ívßÿ’Í;ºÑ¡‰ÿAaGE>15)ÿí.Ù5ŸALÿ2aZyÔ—Õ¡ÿÕ¥u§7¡…—ÿà•Œ7o/aÿKT™VîU½Yÿn]¿eÿrY‚ÿJ’厕Øÿø‘Ž‘H}ÿ«rÎrzsg~ÿ³‚ù‰¬…‰ÿ1ÿ­/¬äÿ—BŽlƒ…ÿH†kÒ\SÿMZna!k¤pÿðoÎzû…_—ÿ˜’”ŽŽ”‡ÿx€€‹n†xzÿ•zàwÉ|ò€ÿYŽÀàN”ÿÝ›ù˜…`vÿèküYƒL7LÿV8§0O3 Gÿ\ p:„ë•ÿʰ°É^åêéÿvߨÐÛÁñ©ÿ$¡ìŠØbzGÿ“6¸7:KÿOT¹^óm’Šÿ9¦R¬+ª[©ÿ{ B’ú’Ù~ÿei)UœMNÿxR^«fÒwÿ¾‰h¢Ô®å¯ÿ®ç­>ŸŸšÿ}“Ów‰a³SÿÀV(Us\…cÿßlË{p•˜³ÿ‡¼ µÔ°i«ÿ£œ‡›¯ˆJlÿÁN:=7à5ÿI<æ; CüPÿÞnÏ‹-©¨ÿ\¶å³Ñ·ýÂÿ¹º¨–ªÿG„1}Evîpÿ+lÇkîvØzÿätåt”|ayÿ*‚‚yTpÿŸn¢tåv®|ÿ€{ê{Î~|ÿÓžÔžA•B–ÿЄŒN—ƒ’ÿy‚¿m`j!jÿ£klkjhidÿ›bsmTwˆuÿaoÊpOh©nÿ&x`zx½xÿ»€…h—ÿ‘œ œA£%¬ÿð¨ž—ß ‡ÿ#vbtÔnUfÿ][kbNršÿŽŽ"˜¯¢B¬ÿ˼ëÈ]Ã#°ÿ¢ôˆ|xnÿãX0=ù$a ÿÌ!Ô.­>qMÿfXkžŠ6¥ÿS¬F±´·¨ÿé¥í ¤–)€ÿ¯nÎfãb±dÿ$hp xX‡ÿ£˜n¡3Ÿö£ÿpž —‘•tŒÿÞyd^^\ÿ^]˜`ìg'pÿ2œ ¹“ÂÿLÂôÅÁ¾‰»ÿ²µD§š‰ jÿ=UG³?(8ÿG29.Ð6GMÿe£q‚ôŠÿÕŒù–jŸ}þhà^yËqƒjÿhÕeciÿÉy4‚؃cÿå¥dªÿI¥_›Ô˜!˜ÿ˜f•œ ‰ÿ͈X’Ò›à”ÿ'‹Û‚"„ÿúˆ‰‡=ušdÿR^]£[¥Zÿ³XT}Uœcÿâp¸r[wwÿÊxÕ€h‹ÿÿN¶‹K‹×‹ÿ Ž‰Äƒÿû„–Š6‚ xÿªsdjèdcdÿßfa&\MdÿÐs¯|0™ÿL£#¯ñÁ%ÑÿCÏÇÈC»T¬ÿZ¢§™ö‰6oÿ Y MPJ MÿÄTšXZYdÿX{1Š5Žt‘ÿXy†p€ÿ&wd¶U]OÿŸM(OVä^ÿÃhÒyŽŠ˜ÿ‚ »¤ã¢‹¡ÿ²¡ûœyŒ|ÿÀsrp¿mSoÿßr v¡€æ™ÿ¯yµ`¸È¶ÿs³Ë¯­¬¡ÿ ˆ—lÁYqNÿ8Fª@8;™8ÿ B´Yom‚ÿú’››õ¢Ã­ÿ°¸ßµå§fšÿžŽY€;tŠkÿÎ`ËUMWñ^ÿ`?cªhÔnÿNu~Q„ÿw|‰{~/€ÿ“†€0~Ä‚ÿ “”v œ¢ÿš AŸO£Û«ÿv©…™V‰é€ÿ{Üur¸kÿ-a3`Ëjßpÿâs¢sJq‡pÿ²uYb‚Kÿù{Ÿ{á{Ñ~ÿç8ž|*„ÿž‰ˆ† „€ÿ·yÂs4u“uÿömhlnuÿŽ|„!Œ^ÿØ%©$³³ÿœ¬i &”P‹ÿ_…Äv&aNÿ·DÆCKIîRÿ¯X]n‡ÿp™2¦Û­À®ÿ„ªšª¬ƒ¢ÿB€ u"lÿh\iöilÿôw»ƒ÷ŠIÿp¨‰Èˆÿ8/qWa%XÿÂRŠOdR÷VÿÄ[»lBŠñ¡ÿ…±ËºÀ£ÀÿWÀŠÀÔ´œÿò-k[RNÿEi;Ç4A=ÿrPÊdÑxê‡ÿH’Ý™X§²ÿ›¯˜¤™®ÿ)€wåpÃfÿª_¢eÙm9tÿ${äƒd‹’ÿlœg¡AžR–ÿ¡‘rŽ!ŠÙ…ÿ¢~—uöuL~ÿß‚<„1‚ñ~ÿ¶{f€à‡2…ÿNx¥këe‹`ÿá]#^àYµSÿ¢YJgùs¡|ÿÂÏ„C‡B‘ÿ«œ±¡Øž‡›ÿܘv–A—–ÿùŽ}Šm½ÿ1‹Þ†”>xÿžq•qÄn²fÿ¶`×cýhoÿÉwû4…Q‘ÿ£Æ°@¶3³ÿ%¬õ¡œº•ÿŒ‡1q…\\OÿªHhIúLcLÿM[±mù}ÿd‰º¾vÿà‘pŠV{ÿZoKf `©`ÿf±i3r%‚ÿç’“¡üª}°ÿÖ¯Õ¯÷¯K©ÿIšSŠ9~asÿMlöiZg%fÿarN†§˜¨£ÿaªÌ¬•©ö¨ÿP§o›û‚jÿêUÒEl:3ÿ7*Ö&,1]Eÿ'^)t@‡“ÿÌž™®º…¹ÿM°W¥—ˆÿœ~uáfW_ÿp`ïeòjƒqÿ zuj‡³‘ÿǘ –ü‘?ÿÄŒ+Š6ˆi‚ÿg}R[Šü“ÿC˜š×˜]˜ÿÀžé¥Ø¢•ÿûˆ¾}›a—…‘VÿÓˆ¿€¢zbzÿÏò‡‡Œ&Žÿ÷‹³‹y’î˜ÿÄ•žŒ3ƒàyÿqµnsj bÿ$[^^Ûh)rÿ={€P€v‚ÿKŒ–Œ™—ÿX”.Œé‹ÿP‡Ô€À{'|ÿ+||&{AuÿhlyhÎhyeÿ`(^ù_›aÿ6irÉyŠ€ÿWŸq­¶ÿ5¸‘³Y¬5©ÿY¤ž—¶„sÿDd\Â[•Zÿ¤X›Y¥dtÿ4ƒ÷|—d•ÿî“g——ÿô‚äv6i aÿ`ªaÙbÑgÿku„ ’óœÿ¡¡ò¡©¡ÿW›6B‚uÿÒhÜb4^µZÿËZfxëˆÿu˜C£ ¦ö¥ÿ¦©©0ŸYŒÿxyêe“V­LÿnDeÉJ;^ÿør²‚}šÿx§®¯g²˜­ÿ<¢j“³†Ä{ÿènYaLY2VÿiW¥_si0oÿ]sÃ|Î…ÕŠÿ­Œ¸‹ð‡p‚ÿã~|Hwþsÿpw€~tˆ"“ÿ㙜y ¨ÿ䬣¬[§¥ÿ ‘¥†Ô~žtÿ¶f¾\ÓY=[ÿ;b©jÝmUlÿpjx€ …ÿý†Ž…ñ~€ÿ’•{Ozÿüz8~„‰ÿ)‡iƒ8ƒ4‚ÿË}}8{„wÿUu‹wÝz&{}y„)Ÿc ÿÉ¢@žŸ™e—ÿN’‚ˆa{Pmÿt`ÎX¾VÂ>ÿÆG÷Wÿj'yÿJƒ„Bœ£¥ÿÌ©ñ§ Ÿ“ÿöˆû€Ÿv¼lÿ_gte×hðrÿ•~…ñŠì“ÿœÕŸª 3žÿ—æz†Bÿût1mvjÍkÿ©pÍwÕ{7|ÿ\g…퉫Š÷ˆÀ>plÿ)e\lWÇWÿ!]hõt•{ÿ~0…iG˜ÿ`žW¡ŒŸêšÿÝ—š–›‘çŠÿ•…/‚ïm…ÿw‡£ƒ¾~|ÿÃy›v¡tIrÿ¤n§l±oqsÿu€y¶‹ÿz–¢H§]¥ÿž¢û œ’ÿ…ØuÎfý[ÿ÷VøQ,MLÿ^Qx[ãj$zÿÆÉ„ðˆÃÿ‹’ŽØ‰:€ÿuMo1nlÿÓlžqÿyŸ…ÿm•E£ò©“¬ÿÔ®Û®•ªZ£ÿý˜r‹Ã} tÿwkÍcQaeÿªml{΋¾–ÿ¹› P¤’£ÿáœÄ‘éºnÿj^ÈRZFm:ÿr4´6š@ºRÿÆgzx…ž“ÿ¢²¬.²A±ÿ#©Àœ5’5ˆÿÞ{öo@gbÿÁb%k©t¼zÿ€R‰‚‘·–ÿ晚þ”Žÿʼnµ„é}6yÿüxé{í‚HŒÿn’2•™Ÿÿð¢à¢¶žÁ•ÿ ‰E~uáhÿL[þPTKðJÿÏQœZÛ^Š`ÿùeën’wÅ~ÿäƒJ„ºíÿ-ƒûPø}ÿ~­Y‰†ÿÎy}ÿ±ŽõŒcˆ÷;…¸)àR„ë„ÿˆ9Þ”zÿü †žh›?™ÿf”†‹y€Ksÿ eÅ[(W_SÿP®PàUC`ÿ0p¬ýˆÅÿ¿’f—<™Ø—ÿ¾’‡¬zIrÿÈl9g_c©cÿÜf¹n‡{V‡ÿb ¡’Ê“ÿÀ‘Ëp‡}ÿws'mƒhOeÿÃfŒmÖxˉÿ¸œ)«´Z»ÿÁÁ¼ù±ÿÄ¡r~{ lÿª[{K@p<ÿY@îLï\jÿ\tÀó‹m•ÿš›î“¤‰ÿ΀£x:olfÿ!`³\»_­iÿÎt(}…’Žÿ—€œ[ U ÿLšè’·Œ†…ÿ—|ÈuWrBrÿwÕ~„¢‡ÿÜ‹’—ë˜ÿí—´‘dˆ´€ÿzDqžg`ÿå\¯^Cg`qÿfw {䀉ÿ*=–½™>—ÿ!’›Žw‹’…ÿ`~Èwƒr‚qÿÖt¥wÜv‰tÿXsrqãqÿq0nYm½oÿnrÅtsyêÿã‡>“uŸÕ¦ÿÔ¨X©¬©i¦ÿQŸ÷•Ûˆ“zÿôo%i˜b\ÿÆY [øa—nÿv{—ƒˆnŒÿËÌ’ë’ÿL…Yz"s nÿ¨jýh5jþmÿ¾vU„äb˜ÿCœNŸòŸHÿ™‘Ó„’xÿÆnýe­^†[ÿê\zcQpÏiŒ)•†œºÉ ÿA¢è›e¡ÿÔqBfZ÷Nÿ$HéFjMy\ÿÌnÆ~Œ¢™ÿø¦ð°6·v·ÿ°á¤ù™¿Žÿ‚‚uZj bÿq`µeÀlŒrÿ\xÍh†®‹ÿ/rt‹J…ÿP€izÍs oÿ´l–mˆs@|ÿ—ƒ”ˆ<Ž=•ÿ]šzœ{–ÿ5‚„í{0qÿÕe\UTÿZûatgmkÿÓq/z³‚†‹ÿž‘U’²¨ÿ±¨Žo‹Ü‡ÿ …Q†]‹ÿZ‘‘óŽÿŒ(‰Ýƒÿ¢u}{Çxÿøw4xŠzó€ÿLjaê¯ÿÓ‰{„ý|ÿrúe“]¬XÿÄTRíQOUÿP^¿lØ{$‡ÿØŽð•Ñ›ÁŸÿ¨¡æž'–¡‹ÿˆƒñ|wsÿ¼pípŠv!ÿ‹ï‘§•w˜ÿ™Ù—T•-ÿ…Ìz°rÓkÿäf_e…gnÿk{ÒŠ˜’¡ÿH©z®m¯–¬ÿ¥O— †óuÿÓf)WµH =ÿ‘79NDCSÿ aem»zÞ‡ÿ0“Û›2Ÿˆ›ÿd”„u†º~ÿwço5k¾lÿ|tB~ã†kÿ˜XŸ¥kªÿfªÌ¤ˆ–ÿ1¼ƒY{ˆtÿòptr_w²{ÿ·~ñ‚ˆkŒÿTXyІ‚ÿ{ssœjaÿ;YvS_S·YÿVb÷hn¦uÿ›}†§Ž*”ÿ”«‘ð…ÿM‰Éƒo}ûwÿšv°yJ}~ÿÐ~"[b€ÿ/‚9‚'€)ÿȺ€R‚³„ÿZ‡Ú‹æ“Qÿ¯£‹¦¨¬§ÿ‡¤2Ÿ*—ãŠÿ}¬qhÿ_ÿ“XSÔPTÿù\‹gªo³uÿA{3€d„P‡ÿ%†Éwêq¿ mÜjâiÈàlÿäsW€¨Œ«•ÿZœë ê¢(£ÿÉ¡Eœn’ˆÿu~ŠucnjÿÛhwl vø‚ÿ¨Ž*˜E ¦ÿŸ¨*¨e£˜ÿeŠì|ÙoÀbÿåVYMßG¥IÿÏSñaGoì{ÿ ˆ”žž/¦ÿI¨;£†š‘ÿ¢†’{:pädÿÛ[óX§\÷bÿ¾imq_yÿøˆ"à’æÿ޽‰ù„3€ÿ|Äxx'|ÿpƒŠ `–ÿ¾œ¢è¥·¦ÿ5¢Wš½‘ˆÿô|4q‘eÙ[ÿŒWÌYœ^´bÿg‰l@sW{ÿ=„/Š'‹BŠÿ˜‰Vˆø…‚ÿ¦}ylx|ÿ4€¶‚„›„ÿ„7…h†`…ÿ2‚[)}3{ÿzdyÊx!zÿŒdž"Œ¼ÿU’b“™’›ÿ'Œ¨ƒóyJrÿl¼gPd@bÿkbegÞq¥}ÿV‡q•ršÿ^žË ¦žù–ÿRF„|EuÿÌoæjhŒjÿ'rJzÞ€ê…ÿ/‰ªŠŒ‹t‹ÿz‡Ôœw pÿ}ie&c«cÿdh÷r»€ãÿ…™=£(ªß­ÿÅ®þª5¡”ÿN†&xÆik\ÿÏP˜H„GÐNÿ6ZLfÃr”ÿÜ‹K—ô _¥ÿH£Ÿß–LÿB‡Ã~ŸuômÿÝk£oçu}ÿp„c‹£‘˜ÿ"¬›™\“ÿÅ‹ƒ„zlrÿ·jµeïe˜iÿðmÞrÔxÿ1…òŠާŒÿ=ˆƒÚ|Àuÿ:n…f`g^ÿ±bdi pÄvÿî}Š…kŽÆ—ÿã3ŸžœÿʘG”yŽÃ†ÿò~{B{|ÿV}¦}R}Ø|ÿÄ}pO`}ÿ©{¨zDzÚzÿ¶{|ó}mƒÿbŠ!U” —ÿ—-–©“hŽÿ:…‰zùp•hÿ6a+[]VgSÿ`UÙ\bf:oÿ)wX~§„ÞŠÿ s‘ú‰ˆÿoƒMº|C{ÿ°yƒy~ˆÿDg˜©žC¢ÿ£Z¤™£Øžÿ1–Œ¬²wÿ‰o{iGeeÿ[jHsÏ|Ö…ÿ¾b“å–^˜ÿõ•dŽ¿ƒ^xÿ®l3aûVâMÿdGhGÅNSZÿgutÚÿ€™i£B¨Ð¦ÿ{¡Gš¿‘™ˆÿð~?tÆjqfÿÎgl s„zÿÜ7‰R‘Š˜ÿÓ›ñš¼—û’ÿVö‡–‚É|ÿùxwyù|_ÿa†à‹å€•ÿ´™G›O˜ÿ‘ÿŠ•€äuÍjÿS_ÛTíN§NÿœQ¹UêZ aÿZhÇq@|Y„ÿ¤ˆáŠ9Œ§Œÿ_ŒåЇ ‚ÿPœƒ‡/Šÿ‹ŒŒŽƒÿt‘€‘rÂŒÿŠs‡±…óƒÿ†u€†‚s†ÿJЧõ}ÿ߈ŽËŠ¡ƒÿ{2s5lbfÿ bZ^î[™]ÿ"dÝlXu$}ÿ¾ƒ@‰ŽŽÒ’ÿL“dˆ-ÿfzøt‚pçkÿÐh)jîopwÿ™…5Š„ÿÙ2“’Ÿÿ«‡=L{4wÿ»tvsEuì{ÿë…¼0›¤ÿRª®¯!­ÿ|¥:šË~ÿMp“bU÷JÿFF¤H°O5YÿFd®oèzY†ÿ±©–!—”ïÔˆX€{rÿjüfšhªmÿ·t‘|„†‹ÿœ“Áš:žÿç™ý“댆ÿÞ~;w^q‚oÿúpLt@y%ÿ…X‹É‘!–ÿŽ–ñ““’‰ÿx‚ÐzLr&jÿjemenhµlÿŸqêvß|ˆ„ÿâŒ×’•Ë”ÿÀ’YI‹Ý…ÿ!~×uupÛnÿDo‡pÕqsrÿ7s±uy7{ÿÄ{â{|µ|ÿ`~î€ñÿ´…-‹ïF–ÿ,šñ›fœò›ÿ™Æ’¯Š;‚ÿÐyWrlGfÿyaI`¤cŒiÿ6pøv}‚ÿdˆ¢°«ÿB‰%„|,|ÿ…yvvGtŒuÿŠzsœˆwŽÿõ‘ñ“Ø•Œ–ÿð“üî…©|ÿ³slgÂbÿzaåd,lzuÿòˆp@–ÿaš.›¥—Éÿí‡ß}ÒsTjÿ3aÖYGWÐZÿÁbam[y …ÿT‹›o¥üªÿ«-§n ã—ÿ­Ž„yïmÿnfæcneÃiÿŠo‘u(|܃ÿ‹Š|—ŽÿŒŠ¾…-5|ÿxvâqjpéqÿ’uêzЀs†ÿWŒ]’l–Ô–ÿ”ÙŽy‡æ~ÿ¶u»kba[ÿYXZí] cÿ iUpÐyO„ÿô’b–ì—ÿ>˜æ—ç•,‘ÿK‹E‡ †Ä†ÿFˆs‰e‰‰ÿŠ—‹Ê‹0Šÿn‡îƒŸ€~ÿy{xOu tÿ v yœ|‚ÿ$C‚ô‚Ôÿ3~%y¢sOnÿ$j/gtd`bÿ)c¯g¥n¡vÿ§~¾… Œg’ÿ˜”š&™Ò”ÿ÷މ „–ÿÃz¯v‰uþwÿ }9ƒÄˆƒŒÿdr’Ÿ” ”ÿŠÐйƒé|ÿ°w¨s^pNoÿüqxZ€|‰ÿ¸‘å—Sœþžÿ†žî™Ò‘‡ÿ‹zÊmraˆUÿgKžEEbJÿ S^£iŸuÿT‚EŽ¿–½šÿ›¸˜º”ÿƒŠ2ƒ£{¯vÿÝuºx@~Í„ÿ.‹»‘ÿ˜¨Ÿÿ‚£¢£4  šÿÄ’|‹±ƒ8{ÿ™s•nœlmëp\uzŽ÷Rÿñ‹üŠ¥‡P‚ÿé{ëtmeÿH_þ\ø]]aÿ'f‰kôqGzÿƒr‹¬4“ÿ]“’‰Œÿ•†’z%wÿÅv+xñy{ÿ‡|}ƒ¢†ÿˆI‰V‰‰ÿwŠ‹­Šø‰ûiŠ ð‹“S–ÿ_—|—Ö–E”ÿ:Fˆ€UwÿsožhbY\ÿY=Y<\PaÿngkmVsæyÿJ€n„l…îƒÿ ~$|¢zÿ¶xwwèzÿÄ€Ù‡0Ž˜’ÿü•[™Ì›¸›ÿ°˜ä’‹4ƒÿ|wWrooÿÉo‡szb‚ÿ{Š‘s–šÿœ#š •LÿÓƒêypofÿã]†X¬WG[ÿ‘bæk±u›ÿЍ“šgœÿÕš–C½‡ÿLqu[kcÿ­_`dùiÿ£pxÞ€§‰ÿq”•“ÿ ҌꈄÿD#|j{}}ÿÑî†ÿ‹—‘ÿ‚—œÑ£œÿc˜~‘$‰ùÿêu¢kèb>]ÿéZ[o^†bÿ)h pEyÎÿdˆ¦ŒÅŽÿªŽŠ•„ÿºÍ|| }ÿ)~u~Ü~²€ÿMƒF…†?…ÿUƒa€à~ÿØ|zy”yÿ|ø«ƒp†ÿΈNJp‹HŠÿ„‡dƒ¿~³zÿ]wt q¡oÿ‹pÅsËx´~ÿ?„Z‰ÑŽÒ“ÿœ–8–á’pÿb‡ßº|Jwÿr¯nn€pÿätqy}B€ÿêƒ&‡ºˆò‡ÿ¢„ˆXzNvÿ-s¢pƒoâpÿ.uD|…Çÿ蔪šŸÿ ÿ²Ÿíší’³ˆÿ¥}ŠržgË]ÿÀVÎSUw[ÿIdNn!yÓ„ÿ¶˜ëzŸÿÓ ša•cÿ£‡!âwœsÿùr”uëy°~ÿ„€Ší¦•ÿP—X•…WŠÿåƒù|buëmÿÔgVd5d(gÿ¿k)q®w÷~ÿ¢…ˆŠ׌ÿ&Šú…߀¼zÿt4n{jiÿ2kÒnls1yÿº€^‰k‘}—ÿÝšª›Ãšº˜ÿ•=ú‡ì€ÿ†{xÈwäwÿÕwLx>zD}ÿM€‚dƒ)ƒÿÒ‚ ƒ(ƒY‚ÿÅ€kc+ÿ„Ú†ˆª‰ÿCŠÁ‰¤‡´ƒÿ~™w~qlÿg£b•_¬^ÿG`ldFj†pÿwa~«…}‹ÿêŽÍ½ŽúŒÿ~‹Šˆî…ÿ’„3…ˆ‹Œÿí”s–јÿšËšf˜“ÿG‹ƒ{uÿZo×juhiÿËl%s'zx€ÿù…•Š–>ŽßŒí†º‰0Joÿ gˆ_ZÍWÿŠY1_gqÿs{h†ã3™ÿPž¯Ÿ‘+™ÿ—“ÛŒ§„­{ÿs/ntl`nÿŸrðwN~å…ÿíí”i™¦šÿ™–b’ Žÿ¿ˆØ‚e}µyÿ»xXzH}΀…µ‰ä‰ƒÿÈˀŸxÿ¿o‰f^WÿâS•S×UüYÿö_hÍq¼{ÿ‹„O‹æê’ÿµ”Ë”¯’ÏŽ÷oŠë“ _…†ÿz†-‡ðˆ•‹ÿBŽñá@Žÿ7Œ~Š·ˆ#†ÿ¹‚V#}ö|ÿ~¦€f‚׃ÿ…’…!…Fƒÿß{aw•sÿp´l#jðhÿ¦i‚lÔpuÿ‰zð;…U‰ÿ3‹dŠ[‡iƒÿ§%|€xÖtÿr.qórÞvÿ{{ÆóƒVˆÿ¢Œj‘+ÿ¾Œ«ˆ …‚ÿo„}ß|e~ÿ‚͈Žf•ÿ/š¼«Ÿ?ŸÿÇ›÷””‹Þ€ÿ¼u¹js`ñWÿWRªP.S Yÿø`RjªtÿˆÛŽƒ’“ÿŠ‘žŽ`Š”„ÿÂ}3w~rÚpÿbrv¡z-€ÿÆÓ”ä—ÿc˜å•Å‘ûŒÿ­‡·:{ uÿ“poŽptÿ¯xL~„åŠÿjô“¢”¡’ÿ¼Ž•‰aƒt|ÿ„u‚o}kjÿ´jól»p7vÿ}(„KŠZŽÿÒŽŒÿf‡G•z·tÿépGoänoÿëor·uzÿ=~$Û‚@„ÿÚ…J‡Þ‡V‡ÿ7†­…ª†‰ÿº‹ñŠ—ÿ‘wMŽ4Šÿ΄®y“tÿØo²k¥hŒgÿßhlvp•uÿQ{6~†NŠÿ닃‹ŠoˆÿŸ†[„­@ÿú}~×€’ƒÿô…ˆŠ"Œÿt茩‰-„ÿç} xûr®nÿ#kÕhÖhõkÿ¼q³x™ä…ÿe‹éõ’›“ÿ_‘±Œ~†ÿdxŒq´kÕgÿg‰ioHvÿ°~«‡m˜ÿu¦Ÿ˜ž›ÿø•x‰‡¡~ÿ¯uon4j]iÿþjFnèrßxÿ¶y†¥‹Žÿü8Œ¨‰i†ÿL‚X}&xtÿ]r?sõuÌyÿn~œƒÿˆËÿ£Œ™µˆÿ‘‚„{õs_lÿ¦eú`_ë_ÿéb÷go~wÿÙ€å‰r‘÷–ÿ­šºœáœíšÿ—ã‘ÁŒÛˆÿg†¸„TƒV‚ÿ5‚)ƒÚ„/†ÿ†œ„²‚ë€ÿ¹|}yÆuÿÏrÄq¨rœtÿÍvÜxÀzš|ÿ@~ö~0~:|ÿØy‚wBu3sÿ>qÉo©omqÿÃty~‰ƒÿòˆÔY‘ ’ÿ«‘n·Œ¾‰ÿ[†½‚%¬|ÿ@|Ÿ} €œ‚ÿ1…á‡ÉЉÿýŽ(Ž2‹3‡ÿ,ƒ€B|]y÷w`E.|CÿG†“ŠòRÿQ‘»‹á„ÿk|'s×iaÿcY¾SIQ¨RÿtWà^$h~rÿ$}m‡@‹–ÿï™›:š¸—ÿ}“♇‚ÿ¾~~–X‚ÿ8†‹}Ò•ÿ™™€š˜Ä”ÿüŠQ„P}ÿþu²oåkõjÿalso¢s—xÿ;~øƒyˆŒŠÿ Šw‡Tƒ~ÿxqik–fÿüc¤cJeÖhÿ%nêt§|J„ÿ“ŠÝŽk‘v’ÿá‘zU‹é…ÿ€ˆ|WztyÿNy×yO{~ÿ‚^†¨‰½‹ÿ7„Ž~¹ÿ³ŽŒSŠ%‰ÿ9‰ŠÎŠ*‹ÿîŠ`Št‰x‡ÿლy'tÿoAjÐeþaÿ©_Œ_xaÕdÿpiÍnŸtŽzÿÝ“ƒ„…O†ÿ™††ô…å„ÿŒƒ¯‚3ƒ…ÿª‡4ŠŒ¯Žÿââ’¢“’ÿ<Ž0‰ýƒ6ÿ{Awt–rÿ¨sHw||)‚ÿt‡û‹Ûá’ÿ!”ƒ㎉ÿ ‚ozßrÎkÿÿeŒb-b¶dÿ¤iHpßwÇÿ^‡¡l‘b’ÿ‘Ž—‰¯ƒÿŠ|Ütãmwiÿh*iQlüpÿïv~¸… ŒÿQ‘w“°“¥’ÿ®×ï‰/…ÿ¯€·}}U~ÿ›„«ˆ#ÿš‘Ì”•«“ÿ”ˉՂ {ÿörþj[d`ÿ$^ž^Jafÿ„ldtÝ|„ÿÄŠk‰’דÿ+“…7ŒK‡ÿƒùØ}A|ÿ.{Íz“{“}ÿïxæÏÿ¬}è€oÿ}¶zœy,zÿ÷{M~€‚ÿy„ˆ†ˆZˆßu‡Ä…¤— ÿ™| z3xªwÿvx`z'}u€ÿ„އcŠ‹ÿΊ׈U†ƒÿ‚€}nyKvÿÂtôtPv9xÿHzt|  ‚ÿŽ„g…W„‚ÿkï|âzyÿw wyx|ÿx†z‹–ÿÞ’3•Εדÿk‰p2yÿqMiÜbÊ^ÿå]4`Ne€lÿöt ~;‡ªÿ&– šÇ›u›ÿD™L•±çˆÿ‚»|¦y²xÿgyg{y~…‚ÿ‡‹ÝŒIŒÿÖ‰?†õ}ÿiwqPk]gÿùe%gPjÊnÿ4t‰z~î‡ÿœŒòŽÿ­‰…ªÖyÿ tñpo#oÿq²tëy€ÿ™‡éº’–ÿÒ—ï—0–|’ÿí†na}ÿvzfxüvcvÿwpy­|¨ÿÊYƒ¤„¼…ÿN†Ì…þƒ¢ÿÎm9€ÿà€#Dgÿ}ÓyÿWvær­olÿ¤i—g&gnhÿSkƒo•tFzÿi€b†6‹pŽÿ`€‘ý‘בÿòLlŒÿ]ŒûŒÆiŽÿÙŽZüöÿ>Ž’Š’…€ÿÞz%v×q÷mÿ@k±jœl‚pÿxuz/ƒÿÞ†f‰ô‰Nˆÿ«„ƒyy"sÿðl…gæcÓbÿƒdµhònvvÿ›~Ô†NŽí“ÿ— ˜+—Ÿ”ÿƒÓŠÿƒ)}ÿÄwÍtFtÆuÿÀxô|a‚ňÿ¯“–m–ÿB•“Ïq‹ÿñ…€.{xÿw»wšy:|ÿ‘^ƒ½†ˆˆÿ7ˆÐ…£'|ÿÇuÀng(aÿ{\ZÞY÷[ÿ#`Rfan—wÿÀíˆÄ!•ÿÀ˜ešÛ™<—ÿR“Nô‹Y‰ÿG‡‹…G„ôƒÿé„—†ý‡”ˆÿˆKˆð‡@‡ÿ²… ƒÚ.}ÿÅ{¨{]|@}ÿÿ}Ü~€!ÿ|這²}ÿ†{2y¤vÑsÿDq™o,o pÿöq«tùw±{ÿGÞƒ+ƒ÷´‚ô©@ho}ÿ‰{züz•|ÿ»~Mƒð…ÿ‰2ŒŽ:ŽÿጸŠjˆL†ÿ?„)‚ˆ€4€ÿ³Ï„¶ˆuŒÿ„ß‘~“Û“ÿF’ƒŽ½ˆtÿ[yüpÉhiaÿÏ[ÝXëX×[ÿa hp¤xÿ&{ˆÜ9‘ÿ»’}’‰ÝŒÿ¶‡óë|£yÿfxèxÃz´}ÿ´’†Y‹ÍŽ5°Ç÷‡ÿƒÝ}jxësÿZqqÕr vÿIz„…†‹ÿcH“÷“€’ÿO¯Šç„X~ÿÈwrím‘kÿ kSldotîy¿Î„È ÐÿüŒÂŒŸŠ­†ÿ¡™|ˆxuÿsQr»qjrÿÐt}x‚|€ÿƒÆ…?ˆGŠÿO‹ãŠi‰Á‡ÿφ̆b‡û‡ÿ@ˆ\ˆvˆPˆÿ|‡Ñ…dƒz€ÿ\}5zëvŒsÿ…p|nÆm‡nÿ‡p}sBw¸{ÿe€„„†‡e‰ÿ}Š ‹ ‹RŠÿÀˆ»†…„ÿ„I„}„ƒ„ÿ¬„*………ÿü‚¬¿{ãwÿ}t€qænmÿ½lŠnar„wÿó|‚å†c‹ÿE‘‚‘·ÿ*Œ^‡Óì{ÿ=v•qÉnHnÿ"pùs8yXÿå…Œ!‘J”ÿˆ• • “‚ÿnŠñƒó|”vÿrâo‘oÍpÿQs;wj|‚ÿð†Št‹[‹ÿ<ŠKˆO…)ÿX|×w²tysÿtõuÅxm|ÿÇ€0…»ˆ¤ŠÿŠÉˆy…ô€ÿ{uœo±jÿhgfµf0iÿ«mtô{?„ÿŒæ’r˜hœÿ•ž”ž9œ˜ÿ“RŽŠc†ÿç‚Äy}x|ÿŒ|}b}S}ÿ!} }Ü||ÿMzÌw_uÙsÿsCtTu~vÿãw§y£{f}ÿ‘~ ÷~†~ÿÏ}»|6{ƒyÿ-x w$x”yÿÉ{™~éN…ÿˆæ‰±ŠÓŠÿ ŠŠ ‰O‡ÿA…Šƒº‚á‚ÿƒL„ü„ù…ÿ‚‡@‰aŠ1Šÿ¢ˆ.†ƒð€ÿ}~ñ{‘yx÷xÎ+€¨[‚ÿ „q††‡a‡ÿ˜…‚'}EwÿápajXd¡_ÿÞ\˜\õ^“cÿói§qCzƒÿ+‹Â‘ˆ–Œ™ÿ𚩚‡˜‹”ÿ]ŠË…0ƒÿ7‚m‚–ƒÃ…ÿåˆdŒ;“ÿ )Ž4‹‡ÿ&ƒÕ}ówcrÿ*nÿkìkxmÿIp=tAyÒ~ÿ„ç‡Ø‰Ñ‰ÿˆé„ƒ€ {ÿKuÏolk©hý«}0ûjWouÿ–{߃‡.Œ÷ª©•0ÄŒÿĈñ„þÀÿø}¯|U|o}ÿüEƒw†"‰ÿ`‹aÌÿ.4xŠè‡ÿ0†&…N„Hƒÿ(‚/€ÿ™}ƒ{þxEvÿ‚s¬p¼mâjÿ’hGgEg†hÿÕj(nfrQwÿC|œ€„¯†ÿɈ}Šš‹Ý‹ÿE‹tŠç‰í‰ß[ŠÈŠõ`S‹ÿÔ‹î‹ïŠŸˆÿi…å ~¿{ÿyÓv\uluÿ\wÓzß~Ö‚ÿ†ñ‰þŒÿ¥EŽ‹t†ÿõ€ñzÓt)oÿ»j4hôgàiÿ~mLrÒwš}ÿú‚B‡ ŠJ‹ÿ"‹¥‰Á†x‚ÿ=}ûwÈsrqÿqCr¿tƒxÿŸ}•ƒh‰ Žÿî+’4’S‘ÿrGŒû‡Cƒÿ.—|Ä{c|ÿû}[€‡ƒ.‡ÿ¹Š%à´Œÿµ‰e… €èyÿbs+mþg}dÿîbYc¼e%jÿepÔwx†ÿšŒU‘}”¿•ÿé”’Ð=‰ÿÿ„eD~}{ÿRyHx§xzÿÇ{C}m~„ÿ˜€N'ñû!~†{;|=}ÿg~ž&ƒÿ(…ن̇õ‡ÿ‚‡§†`…‡ƒÿ[~ì{Szÿ¾yzñzq|ÿ`~a€ûä‚ÿ ƒõ‚Ž‚Õÿ›€â~}®{ {2{ª{Gÿ`ÿt~f€p‚ȃÿÛƒà‚HªÿK~õ|{pzÿ5z{{.~£ÿ…Ö‡1Š%Œÿp|ወÿ¼ƒ%~Dx{rÿ@m3iggÿ‘in×s¡zÿð/‰‘w”ÿ‘—õ˜­˜Ã–ÿ'“ Ž#ˆ~‚ÿ~L{zçyÿÁz¡|hc‚ÿ¤„z…Ö„ƒÿ¯€¸}z£uÿñpçl{j#jÿ¯k¬nÍrxÿ0~œ„GŠ<Žÿ(.™Ž´‹š‡’‚}1ðý·r¡tÌxÿ~öƒŽ‰UŽÿé‘û“x”1“ÿ6ø‹<‡¿‚ÿô~â{fy¦w÷wA 9}Ýÿ‚ʃQ…j†ÿ†^…ƒC€ÿõ}™|î{k{ÿÝz_zLzŸzÿýzþzkz\yÿ$xìv”uýsÿ?rÐpMpüpÿÖrªuLy¤}ßa‚õ†áKÿ’K“¶“-“ÿØ‘8¿Žÿ¤Œ„‹4Šöˆÿ ˆG‡†ãƒÿ®€í|DyvÿXsÝpËn»mÿ”ÿå‹Kˆ…ÿ1‚€2¤ÿé€N‚aƒ„ÿ™„æ„¥„lƒÿ2„~.|ÉzÿYzzz¹z,{ÿ|‘}9€ÿ¹€ëØ~ÿg}h{Äxèuÿs4rýq¯rÿtåuIxízÿd}dဂÿã‚lƒƒ"ƒÿš‚D‚i‚ƒÙƒ¾„Ø…k `ÿ%‹þ‹ ‹EŠÿˆí†j…Ѓÿ‚›€€ß€ÿ°‚Å„z†´‡ÿ¨ˆb‰}‰gˆÿ±…s+|wvÿÊprkÆfUcÿ¬aQbCeÐiÿ’ovå|”ƒÿ‰Ž‘_’ÿ’JΈÿ„æò|…{ÿm{\|.~æ€ÿ:„‚‡Ú‰ÇŠÿWŠàˆÎ†+„ÿÄ€§|`xåtÿ s*sôtéwÿÌ{€†ˆ‹ÿÔA’’‘ÿ Žô‰Ñ„Ö~ÿx×rtnËkÿójÈk!nrÿw™|àK†ÿ~‰T‹ª‹pŠÿ‡ „,€—|ÿ¶y{wøu`uÿ%vfxÀ{jÿÈ‚«…0ˆKŠÿ¬‹Ó‹Štˆÿ†J„8ƒ‚ÿØt€x€÷ø€w Ç€Žÿ,~Â|{÷xÿŠv\tssÿ)t0váx$|ÿ¶3ƒ.†~ˆÿ#Š7‹¸‹†‹ÿ–Š ‰C‡›…ÿ4„þ‚Ç—€ÿ¶Qˆ~ÿ}õzxrvÿåtµsÃr9rÿ­r}t›w‚{ý‚=€Þ†eŠ|ÿxÅ:Ž8‹ÿP‡ƒŒ~1zÿ_vµsÊrÉsÿZvâyð}K‚ÿ¤†vŠ@ºŽÿÂŽuïŠF‡ÿ¸‚Ñ}UyvÿPt.tZu¬wÿ{1…ƒ9‡ÿŒ‰iŠЦˆÿ„†ƒüzÿ²v¤sWr³rÿ=t—vÆyÏ}ÿB‚(†œˆ1‰ÿˆ³…ˆ‚®~ÿ8zduîp£mÿ*l¯lo$sÿ´xxΆõÿ!”͘½›Ôœÿ œp™W•Zÿ*‹9†·­}ÿ>z×wÞv:wÿPxyyzA{ÿñ{^|&|{ÿyïv`uÌtÿuÏu±vðwÿÓyO|é~ÿ{‚'ƒ^ƒAƒÿž‚<-ë|÷{/ùõz5|ÿö}(€•‚ã„ÿ¾†/ˆ‰ª‰ÿꉨ‰ïˆâ‡ÿɆù…t…,…ÿ …%…¨…i†ÿ܆t†…ÿ‚÷Ë€Êó{=yÿßw„wXxúyÿÀ{;}v~³ÿ쀚ÿ³{©w‰s©oÿ.lRig‚gÿi˜ms6yÿÅk†ÇŒH’ÿm–옹™ì˜ÿ­–(“ÌŽ=Šÿ?†Zƒ±ÿby‚I„s†ÿRˆ0‰ÉˆE‡ÿ…C‚ì~ÝzÿMvëq›nmÿcm>o*rûuÿ·zþ…͈ÿ·Š­Šëˆ†ÿT‚º}x#sÿ‡nbkj”jÿ²lVpbuu{ÿÙć–ŒöÿΑ/’‘¾Žÿs‹Ô‡r„¤ÿˆ.~Æ}¢~ÿÆ€´ƒº†R‰ÿY‹ÛŒº®ýcß ‰†?ƒ‡€ÿ{~¿| {yÿˆxdxÊx%yÿyRxfw}vÿŽu8tprapÿ²nnËnšpÿ)sMvöyú}ÿû¤…·ˆ)‹ÿÿŒ9޾ޅŽÿ¬mŒ‹á‰ý®åPj†³…X…ÿ…@„½‚²€ÿ‚~ª|G{$zÿytx¡xûyÿf|P,‚³„ÿ‡_‰:‹í‹ÿõŠQˆp„øÿf{åv¤roÿ lük/mÑoÿEs#wO{”ÿƒƒ†^ˆÑˆÿˆ)†xƒ'€ÿ·|Æyöw¨wÿ¾x{>~4‚ÿ˜†ØŠ9Ž?ÿÛT䎚ŒßV‰-…¤)ÐÌyÿšxÂxÙy¯{e~Õ`…5àÿŠˆw†uƒÆÿo{|vOq¯lÿwi2hìhakÿToªt{‚ÿ­ˆ>Ž1’P”ÿÏ”®“‘HÿÈ„Âþ{ÿìxÅvÎuCvÿêw(za|X~ÿ€l]‚†‚® €N~$ pÿB}ñ}½~æÿ¸„t†5ˆÿ ‰‰¡ˆÌ‡ÿG†äƒ¼€g}ÿ›zÅxäw³wÿxåx_z4|ÿ ~¡Ô€»[‚°‚’‚þð߀u#¡ÐPÿØÆ€Ù“‚ÿ”‚׺€£ÿ½~í}},|ÿÒ{U|³}ÿ=·‚„•…ÿ󆥇 ‡õ„ÿµþ}Vzõvÿ×s/q…ooÿmqu™y–~ÿ±ƒÝˆ·®‘ÿW”P•¡”’ÿ:‹d†¾ÿ¹}Îz yžxÿ yIz-|[~ÿ3€"ù€ñÿS~I|¾y”vÿs p}é<‚ÿðƒ… …/…ÿ°ƒ0>~{{ÿ^yÞwÅväuÿouÎuwÚxÿtz|{ý{D|ÿ|j|´{KzÿŸxqw\wxxvzè|¹ÿçÐÿIŠƒÆ‘ÿÎ’4“ð’Þ‘ÿº4‹ºˆÿZ†„#‚™€ÿrQ~Ò|Ðzÿ’xˆvýtãsÿÿrArþq rÿYtévÃyy|ÿ‘„$†ÿÿ†I†*„/ÿï}¸z—w®tÿ_r?qºqÍsÿïv™z‹~½‚ÿ÷†ÜŠÅgÿ¢‘ŽŒÚ‰ÿ§†eƒ‹€½~ÿL~Þ€Rƒÿ<†L‰ Œäÿ{ŽÉŒ|‰ÿ†ú<}fxÿOtšqyp®pÿâqösñv“zÿ&~Ä€Üiÿш}±z8wÿ*s o²kõiÿ3jKlçoÇtÿÙz؉Èÿ•±˜ƒš­šÿT™––²’ŽZ‰á„ç—@ÿâzU{Ã|~ÿF€´Ó‚„ƒÿƒ¨‚Æ€`~ÿ|sz›yNyÿ9yjy-z¾{ÿá}ö]éÿâm˜€ß²|¨y ÿÐsÿèreshtvÿhxC{3~Ù€ý@o†›‡CˆÿIˆÆ‡‡”†ÿp†Œ†Õ†S‡ÿˆºˆ ‰­ˆß¬‡Y† qÀ“‚ÿ4ßî~¢~ÿñ~Ž€„€ÿ±?‚‚ÿ¢€~¨z'wÿásàpnìkÿØjtkÝmœqÿ vÀzŸ„ÿ;‰‘÷Q qˆÚ„ÿf–~É|%|ÿŽ|Ç}Ýÿ"„ú…ñ†ô†ÿ†„–‚ôÿÊ|sy°v9uÿku'wäyO}ß`ö…Žw >ÿR¼Žù‹aˆÿøƒ·~çxEsÿºnèk÷j¬kÿÕmNqýu{{ÿø€ª…‰ìŠß„‹÷ŠMó SƒÿÑÐ|‡zyÿ¥x?y {Ó}ÿI„‡‰ÿtŠüŠƒŠóˆÿ†¯ƒø~ÿ_}|{¼zÿ;{‰|!~rÿ-€t€€N€ÿ›~ø{¨yÿówNw¹wÏxÿMz3|«~–ÿ£„C‡J‰Š÷I‹õ€Šˆÿ¥…ƒ¹€»~ÿ}×{{zÿ1zžyÆxàwÿ9w÷vw+wÿxw,xyÛ{ÿ¤~~)„¦†ÿ‰}‹,ˆÿUŒä‰Ê†‹ƒÿV€}ùy[wÿàuîuPw„yÿ|×~ç…ÿì‡Ö‰|ŠÚ‰ÿ2ˆÑ…ó‚ÎÁ|?zËxž/Pýs¯@‡€Oƒ¹…ÿR‡Ù‡T‡ñ…ÿÔƒ“}·yÿv]sr!rÿms¢u¥xk|ÿ•€f„)‡cˆÿˆ½†­„üÿ—~¡z±v£sÿ-r”rtèwÿD|©Ë‡÷ÿ<“î–̘û˜ÿ¼—4•m‘›Œÿ(‡¯º|¨xÿu·ssÄsÿ^uewny5{߈|T}p/pJ{ÿˆyx,wwÿRwëwëx¨zÿ;}3€ì‚Û„ÿ †¤†Ò†n†ÿ…Ï‚æ}ÿ{!zôyDzýÓ@¾~m!„ÿ†XˆÅ‰ÔŠÿr‹c‹šŠ1‰ÿ£‡K†3…d„ÿ»ƒIƒƒÍ‚ÿV‚]€–~ÿ/}í{¸z|yÿWx—wowßwÿ¤xxyNzW{ÿŸ|Ê}>~–}ÿñ{Áy’wªuÿt’r¤qÍqÿus•v©zÿŽƒ#ˆÅŒ ‘ÿd”=–z–K•ÿ“)¥Œæˆ÷2…%`Ü~Ê~]V€ŽÁ]pÿ¢ƒë‚xuÿì|ãy„vKsÿäpÚoWp!rÿÏt5xD|¿€…3ˆÏ‰Â‰Àÿ'†)ƒaËzÿßujqCnèlÿQm/oJr¢vÿ|‚㇜ŒÿÒ‰‘ÿ‘_‘ÿ®¦‰!†ÿƒ­€<±~ÿЀĂW…ÿ·‡ƒ‰‰Š¹Šÿ Šcˆ½…Z‚ÿ¾~r{¾x¢vÿûtÑsqstÿ£uyw yzÿÎz>{c{æzÿ°yãwvuÿuv‘wlyÿÎ{Ú~l‚†ÿB‰Â‹ÒŽÿ•¦ŽÎŒÿgŠì‡»…åƒÿW‚&€‡ÿÿ~\~‘}É|ÿ2|Ú{¥{z{ÿw{Ñ{±|~ÿÅnô‚v„ÿ†g‡ ˆc‡ÿ…µ‚‚^|¿Ly;vOsŽ pÿuprhtwÿôyK}Þ€„ÿj†x‡X‡[†ÿà„ƒ!DÿÛ}s}#~Íÿ‚§„S‡é‰ÿŒZ—ÈŒÿ‹¥ˆŠ…ÔÿÛ}1zvwvÿv$wøx…{ߪ~ÿÎÃ0¦†ÿœ…±ƒ*~ÿ2züur„â‚Àÿú€}€2€€ýEÝ@€R€ÖÿNá~‚~~ÿˆ} }Ï|}ÿ¥}s~E%€ÿ@‚yƒ«ƒÿØ‚0,9}ÿr{Ãy;x7wÿ5wyxÙzÌ}ÿ瀄l‡ÓŠÿç¯äÿé5‹ ˆ„ÿ¾€&}@zpxÿÐwxêx zÿi{Ý|~´~ÿ˜~Ë}f|’zÿlx1vEt7sÿasÛtnwÊzÿ»~ƒŸ‡¦‹ÿƒŽÈˆŽÿ·‹ˆˆ„ÀÿÆzqvsNrÿ®rOt wózÿÒ …½‰>ÿ@ãgøÿ‹Mˆk„‡€ÿ2}®z!y†xÿòxVz~|ï~ÿ7ï‚胄ÿcƒÒt™|ÿ¹y@weu tßhsSs,µ0¯xÿ}{ï}Ñ5ÿ-‚¢‚[‚?ÿž~<}A}ÿö}|€p‚þð°ˆ;‹µcÿ]ͬ³ÿ©¶ŠT‡„ÿ?å~Û|{ÿÂyÝx=x²wÿ#w¡vKv.vÿLvvòvšwÿ¡x z¹{t}ÿ-ø€×‚t„ÿR……ÖƒóýäópÇ{žyžwÿTv2vGw;yÿ—{$~ÿ€@„ÿš‡~ŠUŒèŒÿdŒ,‹“‰³‡ÿª…®ƒ!‚cÿ™•‚óƒg…ÿÚ†,ˆ"‰d‰ÿ»ˆ‡¡„€ÿâ}ïyÿušrÿCpJoŸoqÿAs"vy}Ý]i‚å›Ð¾~ÿM|RyvNsÿ°q«q;svÿÉy~~„Šÿ…È“e–i—ÿ—®•“eÿÇŠÒ….e}ÿ¨z÷xFx®xÿ zN|³~΀ÿA‚ò‚ë‚2‚ÿÙ€ }@{ÿÚyõxƒxŒxÿ>yÆzò|?ÿ+l‚ƒ0ƒÿ¶‚e |ÿåx@v“tÓsÿÀs1t\u‚wÿŸz?~Óá„ÿT‡V‰‹&ŒÿtŒÐ‹Š‰ÿÛ‡ü†Q†º…ÿ>…ó„Ç„‚„ÿ„Oƒn‚Šÿ£€¦Š~l}ÿ}|ë{¶{Á{ÿî{I|ì|¸}ÿE~~}€{ÿ¶yx«v_uÿBt¯st’uÿòwÅz»}×€ÿ7„º‡×ŠóŒß´3χÿè„ ‚_n}ÿ|§|_}b~ÿœƒ‚´ƒÿD„ „ƒ‡ý˜±°B{xysxx¤y²{k÷@ÿ…jˆ9‹ÙŒÿúŒÖ‹•‰ƒ†ÿ¶‚$~ y tÿøoom¥lbmÿTohr¤vÍ{ÿ&Ì… ‰ÿŠ÷´‹E°ˆÝ…ÿ™‚kå|W{ÿÅz{A|F~ÿõ€×ƒg†=ˆÿ!‰‰1ˆ{†ÿ„5U~Ñ{ÿÙy|x¶w¬wÿxkz×|Dÿ8Ÿ‚€ƒÞƒÿ˜ƒ€‚¤€f~ÿ`|{uzwz÷Üz±ýà‘a‚ß…M‡Ð?`DŠÿ'Š ‰‡N„ÿQ¢~z|Äz^yNxÄwÃ-Pÿ±x5y´y8zÿòzÙ{Ð|º}ý¯ùp(§‚.„ÿ£…‡ˆ©‰ÿŠQ‰¼‡…ÿPƒþ€•~|ÿÕyIxÃwBxÿiyçz¤|Î~ÿp,„]†}‡ÿp‡…†%…žƒÿë€G~î|ÿo|Ü|ñ}@ÿ™€öQƒh„ÿ愎„Vƒ]ÿÚ~þ{þx-vÿtÜrîr"tÿ=v yb| €ÿƒM†ó‡fˆÿ݇˜†µ„/‚ÿæ{7yµwÿ£wáx"{:~ÿ*‚׆©‹Öÿ­’ø“Ç“l’ÿ¾Œ[ˆCƒ~uyâu|¿Pÿåq¼r¤tBwÿzX|ð}È~ÿû~¡~Ã}‚|ýAÀ yÐxyÿïyr{¹}Ž€ÿhƒÌ…€‡{ˆÿÀˆ:ˆÇ†b„ÿbW~Ý{=zÿ`yyUyezÿƒ|€Ò‚Ý…ÿPˆ5е‹ÊŒÿ'‡ŒíŠÀˆÿ‹†¨„ƒªÿP€'X~Î}ÿ`}à|3|s{ÿ»zz\yŸxÿçw^w.w_wÜw—xœyï÷¿“}"~þ}à |ÿ |{{µzÿÈz{H}“ÿ‚½„{‡xŠÿ‚n‘„‘ÿr–ŽIŒ§‰ÿ±†ƒ§€y~ÿE}ë|}W}ÿÚ}›~y€ÿ€Vç} |ÿúyáwïultÿ´stauwÿsz¦}@„ß܆eˆ©Ë0ø…ÿiƒ!€:| xÿ7ttq7p„pÿrÃt~xG}ÿ²‚ö‡IŒCÿÝo‘‘Îÿ§”Š ‡¹ƒÿgŽ~l~ÿ€‚‚ª„ÿ^†5‡‡ê…ÿ„±Ê~™{ÿux¸u¥sPrÿÃqrgs¡uÿ[x{B}í~ÿ€‘€q€÷~=‹ÀöyÜyÿMz({Œ|Ã~ÿÌ:…mˆýŠÿÑŒŽ°ŽžŽÿw‹¬ˆµ…ÿƒä€‘}a|¼{ª{òsÿ¥|ê|C}Ã}ÿV~Õ~&Yÿ €·€aÿ ‚Å‚xƒÛƒÿ—ƒŽ‚߀ß~÷Ë|·£ vËtÿâsôsÅt(vÿâwz¬|Ñÿô‚|…ø†h‡ÿ*‡ †ô… …ÿ⃭‚á×ÿ‚®ƒÓ„à…ÿð†ˆÛˆ‰ÿYˆ´†N„z÷w~vEp vquÿ]uTv"x‚zÿ@}(€Ö‚˄ߴ……x#s€ÿ›}`z1w·tÿqs–sðtÿl~­}M}}ÿy~ÒPâ‚ÿ´„Ó†øˆŠÿ$‹Š ‰ ‡ÿË„P‚Ÿã|ÿ†zîxCxMxÿ´xJy6zm{ÿÇ|ê}e~8~ÿ`}7|ýzÐyÿÎx.x8x'yÿ{}¥€Úƒÿ ‡ô‰3Œ\ÿPŒô‰‡ÿtƒe9{‰wÿìt¸sèsBuÿ wûz9ÙƒÿˆZ‹KŽÿæüŒ0‹lˆÿâ„´}-{ÿyàxÛx¢yÿA{x}µ`ÿ ‚õ¡ÿÅ}‰{y¿vÿßtºs^sÖs÷,uuYà¶}Ï€ÿiƒ]…«†G‡÷‡›Ð‚‚î€ÿéve¾ÿ½€‹‚…ù‡ÿŠEŒTÂÿš¬Œ¾ŠÞ‡ÿs„ ~Ÿ{ýšcpžvvvÿ§vNwçwvxÿyóy×z‘{ÿ|V|½|e}ÿL~MY€tÿŽ‚hƒ¶ƒRƒÿ^‚¹N~ÿÔ|l{UzÖyzíz:|Ü5 ÿ}‚b…ˆ ŠÿÿŠ‹¤Šõ‰ÿ ‰À‡&†€„ÿQƒÄ‚Á‚ì‚ÿƒƒZƒ±ƒÿÔƒVƒûÒÿ'}Sz…wétÿ³r&q‰pqÿ‚rÆt†w˜zÿ¹}“€Á‚øƒÿA„±ƒ|‚»€ÿz~ñ{–yúwÿ…wPx(zÓ|ÿ:€Z„áˆ2ÿ‹’“‚’ÿÿ¤Ža‹G‡ÿÆ‚ƒ~{½xÿsww˜wyÿ[{þ}Z€÷ÿ¼‚Ê‚X‚lÿ €;~>|ozÿyoxexyÿXzT|±~ú€ÿȂ׃„ˆƒÿ8‚5€ }×zÿMxav@uÔtÿu2vRxy{ÿ;ƒ_†.‰ÿ„‹\~Ž–Žÿ𾋉©‡ÿô…m„õ‚žý°ß@T€o€O€ÿß=¨~"~ÿ‰}¹|²{ºzÿzÕyÿylzÿ{ù{ä|}ÿÈ}’}$}¦|õ0á ,Ï@£z{ÿ |g}ñ~±€ÿÆ‚1…•‡`‰ÿ'Šè‰èˆŽ‡ÿ†A„;‚%€ÿh~c}!}c}ÿÙ}q~Iq€­Œ‚Â>ë0ì˜~Q}+Àÿ{¯{ }ÿ9‚ƒ»…¨‡ÿðˆA‰zˆ°†ÿ„Ú€#}*yÿQu*r.pˆoÿ1pùqÃt€xÿó|—Á…ñˆÿóŠì‹Œr‹ßñ‰‡‡v…À·~ÿó||ò{y|ÿ½}Æ=‚‚„ÿ†}† †ð„ßeƒt$½(z6x w¼v=IÀÿ­za}E€ê‚ßü„R†ß`£…ÿ䃦OJ}ÿÎ{Þzqz”zÿ‚{a}ýÄ‚ÿ)…憈žˆÿ›ˆÏ‡ †ƒÿ›€â}ª{ôyÿ•x‹w wEwý-u`Íz |1}ÿh~¬Ï€™ÿÿ*‚f‚Ì‚ÿgƒ„»„g…ÿ†i†N†™…ÿX„Ç‚_¤}ù{“z£©ÐÿŸymzš{=}ÿ]¾äƒV…ÿñ…á…p…Ó„ÿüƒÑ‚büÿÓ~ö~=÷~Í­ Šÿcd€³~®|ÿ¥zÄxwÍuÿu6u[vfxÿ{ë}ê€Ôƒÿd†?ˆ2‰5‰ÿcˆâ†Ç„:‚ÿƒ}e{¿zý+0„~Dž„ÿ0ˆ[‹ŒvŽÿ.Ž÷ŒýŠ<ˆÿ¨„n€|/xÿGu{s¯r¾rý·¡PHx+{±}ÿmW€§€ˆ€ÿ €Ç}J|ÿ{TzUz{ÿL|/~¡€PƒÿÍ…¯‡¯ˆÂˆÿÿ‡„†f„Êÿx|zy„{ÿp~ÖU…XˆÿgŠY‹D‹dŠÿψ€†tƒéÿg|y•w­vý™Q Ãx{÷}ÿÔ€ƒ„9…ÿQ…ÿ„@„ƒWŒ ~%3àýQy°ÇºÓƒÿ£…Ɇ‡x†ÿ'…+ƒ¥€Ã}ÿÛzDxOvuÿ¥tùt9vyxÿ”{z‚h…ÿº‡n‰rŠšŠÿljˆÁ…sƒÿa£~¼|wÂ{o_`y|$‰ÿÅ}÷}@~w~ÿb~é}?}Ã|ÿµ|}Ñ} ~ÿ¥€ÒØ‚ÿƒƒÆƒ°ƒ`ƒñ‚]‚©è«`þD "€²€ÿÈ‚/„`…ô…ýÄS°Íƒ‚ÿ[{}µ{azÿ­yy™yÙyÿOz1{r|¹}ÿ~Ý~‰~ò}ÿY}Ø|k||ýñÀ¢}l‰ÿ¯ƒ¼…¡‡3‰ÿ*ŠDŠc‰š‡÷$…<1Ð÷{$yÿ wøuv4wÿ@y |fƒÿ©†‘‰~‹^ŒÿWŒƒ‹è‰{‡ß^„ϰ¦yÿÑxžx"y\z×(|`8Aàhÿh~+}ž{ÁyÿÐw;vburuÿXvíw)zþ|ÿF€šƒ€†—ˆÿ½‰Š€‰\ˆ÷©†œ[§€Fÿp~3~¦~ìÿìO„†ZˆÿЉŠŠO‰ÿ¨‡/…5‚2ÿ…|NzzxôvÿåuuvAwß»xzCs°T}ýMsÐ/ö~š~ÿr~¢~¡ÿ0€Ñ€ƒ‚ÿY‚/‚«í€ÿ€Jr~œ}é|Ž|¯|Nðÿ¿‘¼ƒü…ÿã‡#‰±‰½‰ÿv‰íˆˆº†ÿ.…¶ƒ”‚»ÿg€Ç_ÿC:ß~ä}÷O|kCðôv‘ußht–sd°£uÿÌw6z®|.ÿ¨Þƒx…;†÷†(o ÜÙÿì}[|†{™{ÿ|S~°€Šƒÿ¦†¥‰Œ’ÿ Ž•WŒfŠÿ½‡t„Ó€b}ÿžzÈxÝw³wÿ6xy‡{û}ÿF€æ®‚¶‚ÿD‚Y€½~ÿÉ|ØzWy—xÿ›xFy}z9|ßb~­€ª! b„ÿôƒÜ‚;3ÿë|¨z¾xlwÿ×vwxäyÿ­|,€åƒ\‡ÿFŠ…Œ ŽÄŽÿˆŽPB‹ÅˆÿE†ùƒè€ßO~}‘µ°}÷K}[K D}G}ÿ}’|³{Ázÿzèy#zšzÿ,{ð{ô|%~õD?à‚Õào€9€ýîq@õ~z~C~ßm~ú~Û½°~‚ÿ„h…5†`†ÿ †c…”„’ƒÿO‚怘ª~2~~%~I!ÿct€v÷ÿÌ1€XýžMD}Û|ø|ÿÂ}–€‚ÿVƒ†„s…Ø…ÿu…4„1‚©ÿß|zTwuÿŸs+sÍshuÿÑwàzm~.‚ÿ·…•ˆ…І‹ÿ¯‹‹µ‰‡Ö„óu¢W ÿ(|M|}r~ÿ=€û%ƒ†ƒÿ.ƒS‚6Öÿ!~ |zxÿÅwÛw´x&zÿ#|³~¢~„ÿĆˆ{ˆþ‡ÿ݆1…ƒ­€ÿC~,|¦zÒyÿ±yUzÅ{å}ÿ]€½‚³„†ÿↇp† …ÿð‚y€~|ÿdzy#x°wÿx0yëzÉ|ÿn~ÕS‚ÿOƒÒƒ¿ƒAƒÿ°‚[‚Q‚k‚ÿ‚‚—‚À‚ƒ÷1ƒ"›°ëõ€ßïæ~ÓeÉ{ÿ!{íz4{ä{ÿú|}~S€7‚ÿЃ܄Z…k…ÿ3…¾„ûƒå‚¿¨‡€ª$~ÿ7~ç}ß}$~ÿv~n~Ø}Â|õ|ù@jP,xòwÿQxvyP{Š}¿Ô‚Q„Pˆß›‰ß‰/åÝ…ÿ¹ƒ}Z—}ÿ||:|×|)~ÿ€0‚„µ†ÿXˆ-‰‰Dˆÿ¿†š„ܬ~ÿc{wxPvuÿ«tótîu¯wÿzÈ|$É€ÿ©ñÙq÷œ€Só@[|y{ÿS{à{ó|t~ÿb€«‚…ë†ÿ ˆ5ˆƒ‡1†ÿk„R‚û­}ÿ©{6zy“yýr€±~Èù„ÿÖ‡Š˜‹SŒý{t{ |ß }-~QðlÝk@¦~„[G~ÿ‚~>p€Ñƒ4„>…@‰pÿV‡Õ†……™ƒÿf+ }&{ýªËÆx£y?{ÿb}Ý’‚>…—‡F‰Š-ðÿ»‡š…ƒ*€×y}K¯€ç—€ßxÿ­y{|ë}ÿ¹~â~‹~ï}ÿ.}2|øz¡yÿ„xÿwGxUyÿúz}²³‚ÿÐ…ˆˆhŠC‹ÿ.‹iЉa‡ÿ>…ß‚€¢~ÿS}´|À|{}÷à~ÉI`Ü„U†ÿ#‡>‡¨†j…ÿ‘ƒHÒ~w|ÿcz©xOwtvÿNvûv]xzÿ²{}R~kÿM€Î€È€R€ÿ¯3 ÿ -cßÿ£€pû!‚ÿðžN÷€ÿv€Æ«~ÿ®~- €7ÿ£‚;„È…‡ÿÔ‡#ˆ ˆ¦‡ÿô†ò…ª„<ƒÿÓ€bC~÷9}g›0Ç{›{ {Gz7y>-pÿwávÓvwÿñw]y1{(}ÿþ‚å„ÿg†/‡‡8†ýÞëµ%€Á~ÿÄ}f}Ë}Ü~ÿ`€#‚„†ÿχ‰™‰j‰}ˆú†ó„‹¥P÷w}gÃP?y(yÿ­yÈzn|`~ÿ7€’>‚K‚ÿá'€®~ÿô|:{Þy0y÷8yÍQ*|~ÿ(€2‚¥ƒ>„ÿÿƒ%ƒöˆ€ÿß~ }F{áyÿ+yHy,zÒ{÷)~å€v‡#ŠÿŒ1tçŒÿ‹Ž‰‡„ÿú¤‡}¼{ÿmz×yz¨zÿp{|˜|}ÿd}“}i}â|ÿ,|“{O{j{ÿ¾{+|Æ|²}ýõ˰‚I‚£‚ÿ½‚§‚v‚‚ÿAU€}ô~ÿÌ~õ~YùÿÖ€Ó¿‚fƒÿ³ƒ¬ƒpƒƒÿ‚é&a€ÿ¶7ç~Ä~ÿÜ~Eø³€ÿ$¶€€ý”±~<~â}Ý}D~×MÐÿ0ׂƒÿƒa‚÷€ ý7GÇygxiwÿ wƒwÒxÇzÿ(}ȉ‚8…ÿ‡‡5‰ŠŠÿk‰ˆ:†ÿƒ¨„Ø}¾ý ÿ||e}¦~ÿý}d÷ç€09 ~½|ÿL{7z»y÷yÞz>|~<0ÿH…N‡sˆœˆß󇽆 pâ€ýtU°fzPyúxýQ]°ÿ{(~…€¬‚L„;…wÐÿ+„Á‚ú€ ÿ2}œ{cz˜yÿPy·y×z|ÿZ~€ˆ¶‚ý©iðw„„bƒ_‡‚ÎP5Žw ÿ€_€ç€l xŸŸ`ÿ Þ~í}}c|>|‹|5ï°ÿU¶€‚9ƒÿ„h„|„L„ÿ܃+ƒ?‚2$€4~^#ÐÿH|D|q|™|ÿt||‚{{ÿêz÷z {i{ßú{ù|iùàËÿgƒø„ކˆÿûˆ0‰†ˆ.‡÷w…¤Ý€y~÷D}ªßx}‰~É1¨‚M`ÿ9…Í„½ƒ1‚_L€-~ã x@ÿOw¹w±x)z |~úZ«b‚?‚ËÐÿ‰~J}x|B|¢|k}~OÐÿ„Þ…û†<‡ÿ»†·…d„Ó‚ÿþ€ü~}‘{ÿÄz¿zw{Ø|ÿÓ~Kÿƒ†ÿ˜ˆà‰GŠá‰ÿʈ‡Ý„J‚ÿ¬#}ÚzéxÿkwvvvwÿxAyIz2{ýáp2}W}*}ÿÝ|¹|å|`}ß~½~¡ Z‚ÿêƒ4…†c†y†f††vå`Cƒ(‚Yä €÷¶€ò§‚¨‚ÿƒ ƒÑ‚i‚ÿåAt€ÿ…~š}ß|T||î{2|±K@÷x}hU À|‡|ÿe|J|7|N|´|q}d~[£€ÿ óå‚§ƒÿ݃_ƒH‚Ý€÷p'EP|„{ÿ|{4|¡}‹ÿ¯ëƒ1†[ˆý#A‹‹Ê‰ÿˆØ…oƒü€ßÄ~õ|­Á°«zÿâz…{w|l}ÿ~A~ÿ}o}ýµŸðÂzˆyaxÿ¤w“w9xxyÿ{-}šE‚ÿ΄½†É‡ô‡ÿo‡z†,…ƒƒÿ}¡}K|ÿ¦{­{T|•}ÿi§÷ƒö…÷X‡I°i‡O†ÿ¿„Ö‚Æ€È~ÿ}°{Ãz\zלz@P]@±€ÿrí‚Ñÿ€/~_‹} }¥µ@~—ÐÿÖ}¡~#QÿSMDÿ“~è}S}}ÿX}~ë~€ÿZÝ‚_„ª…ÿ’†‡6‡‡ÿ¯††…ôƒÿ·‚sG€=ÿg~Ö}–}~}ÿT}î|X|Á{ÿX{&{{{ÿI{»{|±}w÷~2ÁP‹‚ÈѰÿt…T…w„ƒw—-`3}i {{v|¯Ë ÿœ€9‚½ƒÙ„ßX…!…S`£ÿ€`~ë|Ù{ýWÇp|&}–~ÿE€‚|ƒn„ÿÆ„„„5ƒÿ‚›€›}ÿ¢|?|f|ò|ß×}Áàʃÿl„B„|ƒT‚ÿó€]‰}˜{÷×yžÀ„xŠyÿ){U}õÂÿ\…]‡•ˆüˆÿ°ˆÎ‡X†x„ÿN‚ €á}ý{ÿyzsyygyÿRzŽ{Ð|ô}ßð~Ãb €¢€ÿI€ßœ™ÿÈ €d€ô€ÿÛƒ.„…ÿ_…U… …Ÿ„õðݰ†=`¬~·}ÿ"}Ö|Ç|ü|ƒ}F~ ¤) € €ð¸©PÿÁ~!~”}/}ß}}@Ñpy~ÿ%•»®÷›ŸpÊÞÿ €i€û€§ÿD‚΂Sƒòƒÿ”„ì„´„؃ÿƒ‚‹?~ÿ}|f{Q{ÿì{}›~;€ÿí°ƒZ…«†õ_Yà†M°zƒ„ÿpd}¢{Azõe·`;ËÀÂzé{}ð}o~ˆ½ð~}}È|þE`û {áà|ö}¸ÿÄ„ƒ†žˆÿЉŠ9ŠN‰ÿˆ^†a„‚ÿĵ}<|v{ß[{Õ{Ü‹°]€ÿS‚ëƒã„)…ÿÖ„„¿‚ÿ56}X{Ëyÿ©xxðw„xÿ³yG{î|m~ߪ¡€M¯‰ÿk€º/÷Ò~Œ/àn~Þ~ÿ¸À±R‚ÿ©‚Ö‚ñ‚æ‚÷‚ç €f€ €ß€h€ã0g‚ÿsƒ‰„d…á…ÿõ…´…=…•„w®ƒv@jçW ÿz{¢zzáyÿÜyÎy§ylyDyLy‰y囀ÿøzÔ{ø|T~ÿ¾e‚¼ƒÿ…>†Û†Á†ÿ†á„¥ƒr‚ÝI*ˆã~ÿ³¯€Çù‚ÿ9„S…††ý‡`ƒuÂw~¡Õ{G`<|L}~Ï_ÀßMYëuQ~}´{©] ÿz–zt{®|ýIyþkƒ'„ÿ7„¼ƒï‚íÿ®€2¥}V|ÿ•{{:|u}ÿ'OÔƒm†ÿ«ˆ:ŠéŠÄŠÿŠÙˆ,‡…ÿœ‚€¼}¹{ÿ(z$y¿xyÿÅyÔzê{ß|ÿ¥}5~‰~‘~÷P~Û­@#}}1}k}Ì}zçÀ÷Ø€©°ƒ²ƒÿ·ƒƒƒF‚ÿ#îì~H~ÿü}î}~Š~ÿJC€> ‚ÿ–‚邃 ƒÿû‚˜‚ù=ÿ‰€öŠHÿ6[¢âÿðÅ|2ÿ~Û~º~™€ÿ£~à~1…÷Ñ1}@5rÿ.e€H%~ÿ}8|u{ázªz{ù{\ãÿ€X‚&„Ü…ÿ3‡é‡à‡-‡ÿ†–„ý‚Hÿ˜~ø|U|ÿ-|h|ó|º}ÿ¤~€€Y€A€ãW˜÷`Õ|)|í{;Éÿ(~‘D.ƒ÷…”qpe‡º†ßš….„zu°C~ÿ|]zAyÞxÿyíyI{&}ÿTz6ƒM„ÿ¶„’„„ƒÿÔM€¯~1}ÿ|E{{E{ÿ|f}þ~–€ÿöƒ¹ƒ„õQ€õó@€õ—¯P¬GÝ~Œÿ_€wœõ›™ +ߨ°~ÿê}|}n}}÷ô}‚Ã@s€•_„‚ƒ[Ñ@9ݰýDû€Ñ~ª}ÿº||‰{V{ÿg{Ÿ{Ý{ |ÿ1|m|Ì|J}ÿÙ}w~. €ÿ(‚2ƒ„ÿý„ä…Á†Z‡ÿk‡Ô†³…L„ÿÞ‚/€à~ÿ¿}ý|Â|þ|ÿ‡}1~ø~åßð€ÞjÐÒÿÒ€¡[~}ÿá{äzFz'zÿ†zM{Y|’}ýëµ Nø1‚‚”ã€ÿðÿ~P}}E}ÿå}Ú~€¥TƒÚ„å…HÓP×`…i]`¿0i~ÿ }A|||ßv}Í~•ß ¶„ÿZ†P‡}‡ ‡†»„ó‚Ð÷Ðÿ|zZx7wߥv³v]÷pòyÿe{³|À}~ÿjuYÝ=Sðf¯ pŸ€ÿ}®‚ „@…ÿ†„†¢†††ÿ(†p…K„à‚ÿp?€fÛ~ƒ~`~Ž~£ÿ©€A”°ÿ¬Œ;¡€÷ÌÜ#àK}Ê|ýv k|¨|ê|÷}·P&}J}ÿy}©}Þ}~ÿz~ð~sóßz€ØÃ ä‚ÿÍ‚G‚„¿€€yó~—GÿÚ÷€)‚ÿ_ƒ¨„û….‡ÿÿ‡(ˆ¡‡‡†ÿ…tƒ¸äÿ~Œ|_{³z÷|z›w0‹{@|õïw –/À }|ýÀÒzŠz±zÿR{c|Ç}kÿLMƒ5…§†ÿe‡v‡ñ† †÷Ø„YGPšÉ}ßk|²{žu }ÿn~H€[‚?„ÿ¤…^†x††ÿR…8„É‚ÿS³}j|‹{ÿ"{7{Ï{Ò|W ~IþÁPd/ ý…•¼~Ø}}†||ô{%ý`ÿÄ}å~à–€ÿ]€f} ¹@Ÿÿ…÷¢€˜ÿÈ‚úƒë„…ÿ¶…µ…†……ÿN„$ƒ½K€ßï}ÅÀ|ÿÝ{æ{ý{|ÿ%|F|‰|í|ÿZ}Ø}a~þ~ݬ  ¯#€ƒ­ƒ„÷ƒYS I7€8<ç0ý‘;0d|æ|œ}ÿk~_€¼ÿÑ‚}ƒ—ƒ1ƒw‚–¬€¿30%~¹}¶}³ÿ‡o€eK‚ÿö‚>ƒ"ƒ ‚ÿ×Û€¾‘~ÿ€}»|a|z|ý÷ÐÙ~%€‡ÿµ‚pƒ”ƒ3ƒßq‚tD°a}ÿù{ñz{z©zÿ^{„|~€ÿ8‚S„õ…ç†$‡Ì††Òu@ÿZHG}”{ýU÷ by¹yœzä{]}É~ö i¸È0ÿù€³€…€r€ÿ€Ã€]<‚ÿ6ƒ„~„¡„ß„!„y•€ÿ’(~ }C|ÿÅ{x{v{Ú{ÿ§|´}Â~œÿ3€˜€æ€¹€€m·ðÿf~)~~~U~µ~tѰßÙ€5;p™€ÿ»€Ú€5ÿq®õU‚ÿÆ‚"ƒ/ƒÓ‚ÿ‚;]€›ÿê~N~Ù}³}ÿó}†~G€ÿñ€çí‚Ùƒÿc„]„ăÀ‚ÿ‚-€Ç~\}ÿ|ñzHzzÿBz¯zN{|ß }õ}ªý°3ÿÔ~€~,~ÿõ}ù}V~ÿ€gâ‚€„ÿ$†‘‡†ˆØˆÿ„ˆª‡q†ð„ÿ%ƒ"}ÿ½{üzÔz){÷ñ{1éЦ€6‚ÿ?ƒ¦ƒƒÿ‚ÿ3‚ À+~ÿ|.{3z°yÿ¤y zéz-|ÿ¦}E€uAà˜·àš€ë/Ðÿ·~X~/~E~ý¾à¾€èÛ‚÷Œƒøá`-„åƒßIƒt‚˜ w€ÿ?€'€6€„€ß#ùÍ ¬ƒÿ©ƒwƒƒn‚ÿe€”~%}ÿì{ðz.z£y÷dyp1à zŽzýúë€ |¾|Š}ýW¥Pë´€~ÿE‚ƒÄƒ‡„ÿ2…’……ý„ß0„Jƒe°›€ýÃ7 Õ~ç~6}ªÃ߀¿±A€ÿÁƒ‡ƒÞ‚ø €ç0ßÄ| |Ð?0´}wL~ü]@€@5€ß‡Ñ~ù ÐA|÷˜{@×Ä{’|ÿ¨}û~|€ÿÿDƒ„U„"„ýœ-ìÆ€ˆßn~²}{WŠ~ÿ£ׂ½„ÿq† ‡ˆò‡ÿB‡0†Ä„ü‚ÿ‰~ |ìzÿ·yyËxyÿèy{p|§}ÿ•~2‹±_«{*€‰€÷a~–pÕâ€ýò‚–ƒêŸðß¿ƒ6ƒWY0ùÿã~~Š}:}ý!¹Pû}6€ýVS°Ê‚7ƒ†ƒ¥ƒtƒç‚Y0×e€Ä‰ðÕ€u~ÿ‹~±~Í~Ø~õÙ%á9Àõ~ó~÷ê~è/ +ÿe¿/€‹€Ý¥9€ï\õ°x~(~é}Ï}øÏÀý% Ú€ÅË‚ßâƒÒ„[ç`Ê„ÿæƒÚ‚»Ž€ÿV5~Q}Ë|ÿª|Î|}Ž}õ*¡€“×`4€ €ÿ³?É~]~÷ ~ì{›~hÿn€—Ø‚„ß…ž…£5`6„ýÿñ`Ó~C|ÿÖzðyŸyÒyõw½`gâ€x‚ÿƒƒÿƒ„Ãÿ8ƒ^‚3Ø׃~mßÐs=0}ÿç}t€²ßŸ‚(ƒLÑй‚Ýûd€†•>~õðyL7€ú€_º6‚r 8qÿø€€+y~ÿ~È}²}Ð}÷>~×` ÌÿB‚z‚ƒ‚[‚ýéP€Õ~¾}ýÛé ´{l{j{ÿ·{>|Ú|r}ÿ~Ÿ~N€ÿÖ€‚‹‚ÿü‚hƒÍƒ(„ÿ…„Þ„… …ÿ „Þƒé‚èÿæ€äé~ ~ÿb}}õ|}×V}»ð+÷ »€ÿü€Ñ€Q€´ß~åÀ×|÷¬|ÙË€Ý}~~ÿ4ú¼€O÷Žp1j€½÷w‘ à}~ÿ“~fp€¤ÿì‚ „ …‚…ÿx……@„Eƒ×‚Àƒ`&yü|÷} Y§!ÿ¬‚÷ƒ¼„æ„ÿ†„¿ƒ«‚Ký›ÉpÎ{ zâxÿx×wx½x÷ëyj0[~j÷,€µŸ =:ÿÜ€°€¡€ß¼€ –-°mƒÿr„D…Æ…ë…÷¹…7@Dƒïÿ’€X\~Ÿ}}Ü|ø|¡ÐÿtZ€oÿ¹àÑmÕ±ÙÐÇðXQ y|ÿC|K||ð|ÿN}›}Ü} ~_p~È~«Pt/pûÏ‚°€Ô€XÿçX‚…‚l‚ÿ‚Åx4ô€º€œ€¬@ß[ÏH'€„ƒÿ8„¾„Ù„q„ÿžƒŠ‚b0€ÿò~µ}|±{ý1q  {<{–{ß$|Ô|€U%~~Ô}•}b!pÿ:}f}Ñ}Œ~ýs` ‚Vƒ’„ÿ…'†:†Î…û„Úƒ€‚÷ƒ`ÿâ}¿||õ{ßH|}'wÐj÷ƒW«:…ÿ„ÿ|„²ƒ™‚0ÿŸ!~ñ|&|ÿÃ{¹{|Í|ßÙ}ÿ~ý€á€õзð×@±~ç}ÿ)}™|G|A|ÿ“|H}T~‹ÿµ€¨Y‚Ç‚ýù+€‹‚ð7÷‹€Ðz×°;AÀ%Šǃÿ „8„„̓ÿ$ƒ"‚á€ÿa~e}¡||ÿŸ{ˆ{¿{1|ÿµ|1}¥}~ýªÝàÙK€—€Ì€C‡= ß‚^‚“-€D‚µý€=€„ðÿ/~¨}R};}ÿ`}±}!~¹~ÿˆ†€:‚}ˆ ‚¹QE0÷Y€ÐŰB]wè³@£€ O0ß×ÀM…ðÍUþ ˜o0æ°mPÿ€"‚ýÕùƒ‚åþ€îÃ~£ßÐÿ8|+|Œ|G}ýU£€Oæ‚1„ÿñ„ …Є)„ÿ:ƒ‚ƒ€×~÷:}ÝàzzqzÿÓz¦{â|Y~Á瀳,Ã0÷‚‚k)P©!÷ª€ZPY€·€wW!‰{ƒ½ÃðÿCƒ•‚¤v€w(áŸpï{Xq ÿûz_{8|b}Ÿ~¹™€JCÀw9‚OU°l¦‡ðßOÖ~tð~ÿD~­~-šßî*€eÓ0ñ€ÿ õ€ßð€,Яú+‚"‚ßÉ0ÿ™€3€Ï÷q-Õ Gÿ„×L€é€ÿ‚‚½ÿ :€`‡~ý¦Ÿp |‘{k{ß‹{Ô{=?“}_u~BÓK"' üòïÿÃÿ™€C‚ƒÿ„…ì…„†ÿ²†e†¦…‹„ÿ0ƒ£õK~ßÐ|¸{à6{ýßýpP~Ô7_5‚·‚Ë%Pûÿ@€ø~ž}m|ý’¥p{S{ô{÷ô|<[š€Fý‘O0n$µ€€và~}€ý‘!ðà÷+ƒ0¼„§„ÿJ„¦ƒÌ‚ÚÝð³ðŠðÜ~ÕAÅ Ì×°ëù@ ‚÷ÎXg0}B~ým 5{–z(zÿûy'z§z`{'|ç|¡}bà ×€¿ýP¬Q°@‚Ž‚Û‚&ƒuýð÷úƒý×P@ƒž‚×ñH ` PÕä#ó½šûó€ÿ¡‚‚É_TÔ€U!ãß~Ê}ÂqÐø}ÿ)~~ô~e÷ž†pŒ~ö}Öb }µëŸí½}³~Êó€ÃàÿçƒO„S„ýƒÿhƒœ‚«¥€÷±õGŽ~å~ÿŠx€©ý‚ß5„…e_0¤„ÿǃ¨‚Cžÿã}E|úz"zÿµy°yzßzß |^}‰2€]‰;0½€ž« Þϰý ëú~Oçÿ»€´ ‚Uƒ÷´ƒ¶ïpÔ‚ ‚]éí~÷àóÿü|}‰~½ÿô€ûÆ‚]ƒßƒ郺ÅàU‚_r€¤òà÷Ù}œ1Àñ}G~߈~¯~ËÁp&QX< s]ë7 9€§à7·ðݨC†€^µð€ÿíμÃÿå €k€Ó€õ_¡p«Ÿ`ƒÃ‚ÿ/‚ƒÓ€!€\›~ý}”µ {}¨}é}P™ ÿ €V€\€õ- `±¿bL÷V‘ep«€aׂÈcÀÁw sƒ÷½‚Â…ðW ~ÿÔ|Ó{*{ëzÿ{£{‡|¸}õ"ÐÝ=ÐJƒpƒßSƒù‚aMÀ{€_kˆ~íá@¡3ÀÝk…`A€*Ù0‚ý‰ ›/ €ýñ©€ ~;~~õ:Ÿ7 䀮ÿD‚‚‘‚V‚ÿæJ€Éÿ p~û}¸}Ý«g°o~5 ¶€ÿ/tƒÿBÁ€€/}d°H}÷|ÈÕá@UaP¨³@Ë€\áC‚qA ÝqÃ0j‚oñq‚÷u‚h! Þ`w΀;Ð&ªƒ÷å}¯· ®}ß}ù8ÃÐ`-€I€Ý8QÀ踯@2ÿð~É~Å~ß~/kÆÿ‘€À€±€n€€ÁHpý mì‹€þàx‚ƒ\ƒÿvƒHƒØ‚:‚ÿ}¯€ß"ÿ~6~~H~ÿ©~:õÀ€Ýpƒ0ûÉÿ’€ÿ9:~<}`|ÿÄ{z{w{µ{}6m€ö}þ~êñ`ÿ\ŠŸÿ“cÑ€ÿ€Ž€§€ã€×EÆ¿àÓåp7ƒÿ ƒ°‚(‚€Ý½}.…_°­}õ‡ ö‡>íÿ~€î€6ZýU½ °€€…ÿø~†~'~Û}ý­ á}7~~ýÛ«0J‰ËÝýµ0€ ‹p$€}MQà¶€õ€:¹˜¡’y³ W<%pɽ€5€WŽ€¤y@ E°Iû`}ÔÕ€ÿ“$@wA~è1 ž}¢C]Úã@w~àgǰwmchsW`ÿ©éJ€¾€ß7ª ­‚ÿ¸‚†‚!‚“ÿï€A€“ñ~_r~!~ P†aP±m€%½gPUD! ÁP+§@Ú9÷œ~=Ù ~ ~õm‡f§à€7€õ,' ç¥àcݲ`~s€ ÷Š"C Mµýìmpà¨Vwò€‡°ÊŒ; Ým`í\ï@#[uvYG°U°ñ°¡´ËÍpßò}~h1 %Ýx=€LÁ€©€u®AP‘À‰€ŒA ×˜€¢cÀ ·ðS€_€â®µ€UO`÷S (Wuœƒ U½€Þ€ôáàÕâï@¯ÀV³ð€uðрߵÀë ýFM€á£×nAp³°ÿ~ý.…°Ç€t€uÇ=0@,í¯àU7K`l1ÐÜ3 Ó7 _T¾8;0#ÐÝp5À'Ú¯ðþõwùp‰‘ð+~5~_b~²~'¿<Ó0}öµ@'(Í0_¹€s€2¯Âô£ ÷:€zgpú€õ%p±Ã€ÿ•×)ŵ°:ã°%~ßQ~¢~ €]pC ÷€5ÐüSà×w€(À¥°K÷;E; ŸÐýøK4€T€o€|€v€c€N¯°×@€D§ÐYG †€Uš¿€žAoÐ9ÿ`}úY`¸¢™•À_®Êði Ç€ßôͦµ€Xw,c€å~íÓÀ]r·#°4}Àu[1PYà_€`¥ÐÝooÀ¶€ç{ð@_e‹É0F% }—ñ°ÀYüŸà}‰p“~Ä~ ƒ°ÕÎ?|Ó0¾µ˜€wg€#K`w'c€]Ë;àÖ~ýñ ‘=PÕ1 àrÝÀi1P=€õõ°½ÇÀ ´Ü€]€³M0ÕNÉ0€0IC0Ï€w‚€0ÅÀ pÕRƒ°’ÕÐñ°E€O€H€1€#Àÿ‚:û~Ê~W¤~›€š©0 ݙӀC£Ð€U²µ±ª§À±‰àU¶K0¿Ï0©Ã n/°w-€uPеÍÐ_›¡²³0õÛÀ]?}ÀU€KÃÐ%ð÷ñÑðšˆu~¯@y¿à–­ÿÀU¿÷°˜¿àtñÀh²ÝŽ) ï&‡à•€×Ê€ùyÐ-`å€W´€}­Ð ?€¼;ð]²ÕÐò#‘Ï0×Ì€ÈeÀ…µà €}¿ÉÀ%ë~Æ õÁ° ­0šâ¥ MÐñ6“ õúé@ËáÐÜö«€Jk𦙰ÀÓ0Œ«€b=ÐüÏ€°N»F§àr§¹À1ªÝÀ¨ßÞw@Ó‰à‚î! €Û;ð†i¿Z[o/𡾠ðÄÔã×ÐòêY àÑÓÜ䪑`°6³àK! Dúð:à"€€¿€ûû ª›ÐDðF# &% ýªÑ€Í) ©à›Åp¤ªð˹ÀÃÀ!ÿ`> €€ÐP]"ÃÐN€amà€‹ðU{ à4‹Í`lãð]+¯p*DW ¢µÀUàŠÅ ±Ó0›kðÝU_óÈÛ˜u”;P±ý$Ûà}Q« I€<€+G©õj¦±@Ä ºGÐfkÀ–€”‹ðk®ð%€ùáÐ¥Çps:ñÀu%À¯ØO”uE³à;­À €æߥ}¯0vÕ‡ÛÑMPX€õq{@àƒ€u€UhÀV/°DP;ÃÐU2#ðÐéY`ÆàÑ¡«àPCšƒÀÉ׿ü9 ›€_ €€÷ó å pWÞÝ pèÃððÝ»àýó“`ìUê¹ÀñO±â];ÐÕŠÑ0¤Ñ0‡OàC€W€ø)·ÍЗ`Õ§{àØƒ #ð0€u/‹` ±ÀÏ«ÇpUf¥€H‹ÐZ…°™ÕUùåE1Pc·0i¥Ð]T¯°-€“ SÕ.ÁÀXŸÐaÀ€wl€RI`€ïÕÐU©Qð}Ð~Ýð­‡`ù€5€G/°uKÁÀ*}@ðÒûÐW W`ƒC ûÐ]̯ïþ™ÿ`U“ wàS'àU=_ÀX à_àT§Ð}EGÐ)€€cUøƒ öM©@§Uë¯Ó= ¹ƒÀ¥“Щžàþ 郠ûª—ü•`»à‹pê?"=! UÀh€jª¥ÐRÃÐ¥ç•мª±@ª ¿)ïÙà,®q [€d¥ÐXq 1ªI õY`½  Åp£ª÷°Áé@í#°©@ªÇÐó•°ÜË€Ãõ Ǫáæ#°GÐV0rªYhÇPH=Ðe°èªY`ÎáÐÓ pó»ÀªA 7ÃÐ5y »àð¯ÚÅà¨ÍУ«¬[ÀÔ•°ûqЪQà, +#ðI ª‘ à 2 £ªe°øÃîK€à½0×ú+ß•°÷proÿpDATEÿ6-16-20ÿ05, 23:2Ý8ANAMAp{opAORIG@ý:@.wavSA¿MPTBëV"T@€ÿ‚ƒƒ}}}õi@„…†…ûƒ‚wA„ƒ€~|ÿ~†‰‰†}ÿ{{|}}~ÿ„††ƒ€|{|Ý~I ~~g@ƒ†¿ˆ‰ˆ…„ƒ~@]~o@~~}žB‚zAo„‚€~Ë@€xArÔ@ƒ£@µ€~||•@I €}Ÿ  @!PÚ@»@§@hA„È@1ðt@¤AËBàt@ƒ°@üB@%Qùƒk@u@wgO;ÿ8Hg‰¢°¹ÄÿÔäéèདྷhÿE1+/;HSZÿ^acdfhjlÿlkmt€Œ•›ÿ ¦­³»ÈÝïÿñéŠ]>+"ÿ%3CKLKKNÿXgt~ƒ‡ŠŽÿ–§ÄéóðÛÿc<,*3ALNÿLLS_mz‚Šÿ’ž°Ö÷÷òÇÿŠ_KC=77=ÿCLZkz„Š‘ÿ›¬Îò÷ôÛ ÿpRD=626>ÿFSdt€‡Ž™ÿ«ÍôöóΔhÿL@87=DGJÿUeu‚‹–§ÅÿïùóÔ—kRGÿ?89>FP`rÿ€Š“£¾éúõÿà¥tVF:23ÿ319DRbûr`Øõôà­ÿ|ZF5*,:IÿYjzˆ—«Îðÿòç·ƒY;&ÿ,?Pasƒ“§ÿÇíóæºƒW9ÿ$ -@Qap€ÿŽ »àòíÍ“ÿ[/0GZlÿ|‹¶×ìâÂÿ•f@&*@Wÿm€‘ ¯»ÃÅÿÆÁŸ[ ?ý_bÉåíã¸|ÿC)DZkwÿ~‚ˆ“•†ÿ…‘ž›Žƒ|vÿrpi^URT]ÿlƒ¢Íí辋ÿbH837BNXÿbqž©®¯ÿ®©›ˆxsv‚ÿ—¨«‰|wqÿbQC<ÿ10:L_rƒ”ÿ¦¹ÇÊĶ¢‰ÿq`YXY[[[ÿ\__\\`gqÿ~Ÿ±½ÅÆÀÿ²…p`VUZÿfv…Žˆƒÿ~yvsomr|ÿ‡Œ‡€ztqÿqqsw€Š”ÿ¥«®¬¦’…ÿyme`^_abÿ`]\_enwÿ‹–¢¯¹¿ÂÀÿ·©—†vh^XÿUUX]eozƒç†…¦@¥@‡ÿ’•–˜œ¥¯¸ÿ»·­¢—Œ€rÿcWLB=—`•“‰›A-põqsì°ux{ÿ‚„†ˆŠŒ÷Ž‹ˆ ±zxvuÛvyq@‚A€Þ·@~€„‡÷°7‹ˆ×@|wW ÿsw}‚‡‹ŒÿŒ‹ŠŠŠ‡„ƒÿ…ˆŠ‹‰‡„€ÿ|vpjeceiÿotzŠ’˜œŸžž›—’ °këigSPpÄ€…Šî—`–––ܰ‹…={T‘yz|$P£@Ö½@{zì@}‚À…†öÁŽŽ À„zuÜè°ÄˆŽz™•ÿŠƒ{upli~f°nty„‰? /‘‘”€…æDÀ<”AaŒ‘6À¼÷€}{{°rsvy|€„ˆ‹Žú±÷†‚}å±onorýw£€’•———–õ”vÂxÑprux2§°†mÀrÀ”’(r·°ÿstvzƒˆß‘”–•’)rtrúаy< ”˜™˜þF¡€zupmllómq/ÂÄÁ‘Š;ˆ…Áwxx€ÀÖ°ÅkÐŒAȰuyÿ~‚…‰‹ŒŠ}‡+quvwz}À;‹ŽmІ‚~ˆÓiÀÚõÀŽÒІ%ÀtsæÂ‘y}Â@–À‰‰ˆ)‡°@É@|x°zÖÀÏ@Øj@ÎѲ°}|Àttvwxz‘ÁèÐÄBO¡@æ@ôAÀ$Q á¢A}zÁà‘ÀéÐÑÒÈ@‡Òopq/twy{'á…ÖÒôC }q ÎA‚PƒÁµBq û{{•Aƒ…††‡i†Ä°"àx{àyz@à=€oà‡‡‡†|@†‘x°SGÀCä€×Bâ‘EM¢ áãÔÀ’@Qj@½â Äá°~àâÒª±ŠÔÑ‚ý~Ðvvutttð°Ô°ÓAÁ~ëA­á•@gC…Á~w± ð¸Ae@·B PàŒÁ³B¼@yuÐyÜÁÐB†††Â{yåwøÐx€âP‡ˆˆÄþ°ïÑ{yá€À©°ˆ†¸,P â_ðy}kð‰ñˆÔÐPT uuwzÀBÎЈá×Ðm@q ŠÀ±€~ñˆ†ñØÒÔÀ8ñÂÓÐrálA·óïAQôñ…Á€tA ã ÅóÎA+áÚð…@…AÓÃÎB†âsàÈA|yá(IñÔ°ª²ŒAÁµ°ßÐ@ãÜó"Éáüò%RÙAÏA á°@¸ñÁ¨ñWðl@SáÌâ„ÂÁÏB×Ñ Ro@ÁôMâÀK¤*Pä€Þòx@‹äGÁ´áÓBá£B‰ÁiL¢sûôPypgAôÈç+ñwqüóá$P*Pƒ@ØBüösB*%R(PvýB*RéXáQ RP‚@¯ƒòfiˆñóQ«äúCr¤DäMâèw©÷”nn$¶CgA#R`ã¤?óýÑ„´òøXã䤽ÜÐáC$RRáàBeD„ÖѨÊád@'¡©â±{´BãBáÔ$ƒÁã$[#ñB½Ö%&#ÛJ#DTûvlIã)4 $ì!&n35€5w7!4G·!kì#"æZ4OvË#•S)Jã*Ja4Ä$eC¹4t3Û»8ð$ Bôš–4!5†•y1#“mBwQ54F{9ÝMDõOX~ Aû3Yž_ð@_/Az:`[propÿDATEÿ7-10-200ÿ5, 14:07îrQNAMyQskßatingrQORëIGzP šT.waÿvSAMP˜ý–¼R¬DLÿG-€µ€*–ÿ÷L‚£‚óÿ‚AƒƒÚƒ&ÿ„j„¨„ì„*ÿ…c……Ì…ñÿ…††ø…Éÿ…t……„ãûƒ7P Ìbÿ€µ`~ºÿ}}f|Á{#ÿ{•zzµyhÿy/y yýxõ¿xôxøxú/`øÿxùxûxyþ'` yüxÜx©ÿxdx x«wMÿwñv¨vtvVïvSv^U`”v¬ÿvÅvávûvÿwWw¦wx§ÿx`y;z2{;ÿ|Q}r~˜®ÿ€Â¼‚Ÿƒiÿ„ …¶…:†ºÿ†4‡¸‡Zˆÿ‰ç‰ÜŠå‹øÿŒŽøŽÇkÿÖ ‘ ‘×ÿ{uÜÿŽ?ަÿŒŒ©‹H‹åÿŠ}Šÿ‰m‰´ÿˆÙ‡Ù†´…|ÿ„9ƒñ·€ÿt~s}„|¡ÿ{ÎzzSy±ÿx(x´wew0ÿwwüvðvÕþS`mvv¨u-ÿu«t't¯s?ÿsær§r€r{ÿr”rÖr@sÕÿs–tuŠv´ÿwíx6z{Èÿ|~8P€XÿF‚ƒÅƒXï„Ó„4£àÓ…ÿ†l†Â†‡€ÿ‡Ü‡7ˆ†ˆÄÿˆôˆ‰*‰-þcp‰ðˆ»ˆhÿˆÿ‡‚‡ì†Iÿ†©… …p„æÿƒlƒþ‚š‚6ÿ‚È]ñ€ˆ¿€)€Ü¢/@kÿ`^P7ÿ¾~_~ìÿ}l}ä|X|Îÿ{E{ÈzSzèÿyŠy>yyØÿx¾xºxÂxØÿx÷xyAyj¿y‹y§y¸×p¯ÿy“yfy+yïÿx±x{xYxJïx\x€Ãp ydÿy½yzcz®ÿzôz8{€{Ìÿ{|s|×|@ÿ}´}1~¾~Yÿ€Ô€³¢ÿ‚œƒ™„˜…‘ÿ†}‡Uˆ!‰ßÿ‰‹Š.‹Î‹ZÿŒÞŒXÂ"ÿŽtŽÀŽBÿ€¼ò)ÿSifJÿŸ PÿŽhdŒE‹ ÿŠÂˆl‡†­ÿ„Oƒé„€ÿ¸}U|{Æÿy¢x¡wÐv-ÿv®u^u)u ÿuýtótñtòÿt÷tu"uMÿuuÚu3v™ÿvwlwÙw=ûxŸ1`Vy£yìÿy&zYz€z›ïzªzµÃ€ªz£ÿz•zvzTz'ïzóyºÓp`yRÿy[yƒyÑy8ÿzºzS{ü{¤ÿ|V}~·~cÿ€›€,¬ÿ‚y‚Ë‚ ÿƒFƒƒ»ƒþ¿ƒG„”„ßéPoÿ…¬…Ý…†)ÿ†F†e†‚†¿†®†½†Ä‘`£ÿ†ƒ†Q††¿ÿ…_…ã„V„­¿ƒî‚‚K) Éÿ3Ð~›~“ÿ~¹~ø~J¤ÿüI€…€¹ÿ€ì€9cÿ„¢±¸ÿ¶§}ÿk\aqþw»ï)‚\ÿ‚‚´‚ÂÀÿ‚¥‚f‚ ‚ÿ\€²ÿj~á}p}ÿ}ß|½|»|Âÿ|Ö|ö|}?ï}_}s1ð~}mÿ}L}%}ô|Å¿|›|x|iÓƒÿ|¥|à|%}rÿ}Ì})~Š~òÿ~WÆ9€»ÿ€BÕn‚ ÿƒ©ƒ9„»„!ÿ…m…’…‘…xÿ…C…ü„²„_¿„„½ƒ^Ajû‚É `E€q˜ÿ~Ì}}y|úÿ{’{@{þz·ÿzxz3zñy­ÿyty=yyø¿xÞx×xÔE øûx'#`Åy6z»ÿzG{Î{P|Àû|#©±}ò}6ÿ~ƒ~Þ~D²ÿ%€€ñ€I¿žé9èÿ‚Gƒ¦ƒúƒ<ï„f„t E„ ÿ„Òƒ–ƒaƒ<ÿƒ ƒƒƒ/¿ƒJƒ`ƒ{ÝPÿƒ¤ƒ—ƒ†ƒj¿ƒGƒ6ƒ,`bÿƒ¯ƒ„Œ„ ¿…‚…ë…8!wï†t†`wp5†&ÿ††† †ëï…·…iýP“„ÿ„˜ƒ"ƒÁ‚s¿‚0‚‚ØsˆÿP§€9ÿ€§I~xÿ}š|¯{ÂzÔÿyéx x6wjÿv¯uu[tÎÿsSsôr¼r¤ÿr´rñrNsÀÿsMtÜtuuÿvŠv wswÛÿw:x‘xëxCÿy¥yzzþ[ œ|}{~Žÿ¦€ÁÔ‚ÚÿƒÎ„³…€†0ÿ‡Ã‡;ˆ•ˆÏÿˆäˆÚˆ¸ˆ}ÿˆ<ˆý‡Á‡‘ÿ‡l‡Q‡B‡4ÿ‡#‡ ‡ô†ßÿ†Ã†²† †’ÿ†|†\†,†Þÿ…p…à„0„oÿƒ§‚×hÿ€ÍL×~€ÿ~6~ú}Ê}¦×}Ž}ÑÀ}ûÐ}†»}…1ðy}tß°€ÿ}”}·}å}ÿ~Z~–~É~úÿ~ Cf‰ÿ¸è€Gÿ€n€‹€Œ€{ÿ€U€€Ô|ÿ'Ó~‚~=ï~ø}º×°Q} ï}ð|ÆÏs|Nÿ|/|||ôÿ{ð{ô{|"û|M×À| }[ÿ}«}þ}N~žï~ê~3/@Èÿ€g€Á€%‘ÿ ‚‚ƒ±ÿƒI„â„u…ÿ†‹†û†\‡¢ÿ‡Ò‡ê‡ò‡äÿ‡Ð‡°‡‡tÿ‡S‡2‡‡äÿ†§†S†é…bï…„o€‹‚ÂÿP€¡òÿ~?~ƒ}´|Ñÿ{×zÎyÆxÃÿwÔvv]uåÿtštvtxt—ût¿‘€0uou¤ÿuåu.v€vçÿvZwÝwpx ÿy¬yJzâzq»{ø ðõ|lé°aþm cêy€ÿ•&‚¿‚Wÿƒýƒž„H…õÿ…¤†H‡å‡xÿˆøˆh‰Â‰ÿŠ:ŠWŠaŠZÿŠ>ŠŠÔ‰Œÿ‰3‰Ùˆxˆÿˆ­‡A‡Î†Vÿ†Ô…@…£„¿„Qƒ©‚ÿ}Çï€6€ªÀ¨~(ÿ~®}6}Ë|kÿ|*||ö{ ÿ|3|l|®|çï|}2»2}ÿ}ñ|Ê|¨|šû| ¯ï|8}“ï}ï}LOÒ~ðîUâ~´ÀK~!ÿ~~þ}~8ÿ~s~µ~Kÿ’×€^ÿ€ž€ã€#X¿z…)ûÛ:0%€Êuÿ-æ~¤~]ÿ~~À}d}ÿ}«|S||Çÿ{–{h{C{û{éÀ~zGzÿzõyéyýy0ïz‚zòÏð!|Ûÿ|§}ƒ~vpû€u«‹ƒŒ„s¿…?†ä†o…Àÿˆ7ˆFˆCˆ/þ=Ð㇪‡a‡ÿ‡‘† †|…Þÿ„;„–ƒö‚_ÿ‚àh¯ÿ€i€+€óÂû›p,õ~»û~†í°.~ ~óÿ}ê}ä}ç}î¿}ù}ÿ}{à úéЫÐ+~7~Gÿ~S~X~[~Q¾¯À+~~üƒààþƒàõ}~N~•ï~í~Pià;€¶ÿ€0£‚Zÿ‚‘‚±‚¶‚¢ÿ‚z‚@‚õªÿb倽¿€¡€‘€ŽÀˆþûðl€J€"€íÿ¼‹cTÿ\y´ùëKåàñÅà_îw˜›ð–Žÿ€nCïË€vÀÂpÿ4 þ~û3ðKJ9ú5ðÁçÐã}`}ÖþóÐØ{f{ {¼¿z‡zjz_­ëzÕÍŠ}Wÿ~)ô¯€RÿÙ?‚Š‚²ÿ‚‚»‚ª‚Œþ÷ \‚Q‚U‚n‚Ê÷Lƒˆïƒ¶ƒÎŸð²ƒ~¯ƒ2ƒÔ ücÀ"¿¼€S€èßÐûŒ©à}3}Üû|–uÐX|]|n»|wÐÌ|æ·ý¿|û|ô|êÛÌï|¾|«‹Ð‘|ˆÿ|Ž|§|Í|¿}M}¡}§p·ë~ Ÿp‹iàú1¿€w€Æ€!!ðëÿV‚º‚$ƒ‡ÿƒëƒJ„°„ÿ…}…î…[†Éús°ŽÐ+ˆlˆ£ÿˆÆˆèˆýˆ ÿ‰ ‰ ‰øˆÞûˆµ;Ð5ˆÔ‡eÿ‡ã†C†™…Üÿ„„^ƒ ‚û¯eèÅ0'“p“þ»Ðø~š~/~²ÿ}-}ž| |pï{Óz,œ¿xþÿw;w{vÍu4ÿuÂtt\tnÿt¦tõtTu¸ûu[`–vÁvØÿvävôv w+ÿwUw”wßw,ÿxˆxáx9y–ÿyðyGz§z ÿ{w{è{_|Õÿ|P}¿}+~’¿~ì~<ƒë¾ÀŽ€Û€3Ðï‚}‚ÿ)à„±ÿ„G…Ø…a†àÿ†V‡µ‡ ˆGÿˆyˆ¢ˆÂˆØûˆðC‰8‰Qÿ‰g‰n‰r‰l¿‰b‰P‰@7Ð4ÿ‰=‰[‰Š‰Èÿ‰Š[ЦпÿŠ‹#‹‹þÿоŠ^Šå‰ZþÑ`ˆB‡z†¥ÿ…Ñ„÷ƒƒ<ÿ‚[z€¢ÿ~±}·|¹{¸ÿz©yŸxŽw|ÿvduVtKsNÿr_q„pÊo1ÿoÃn€nln…ÿnÇn-o«o<ÿpÛp€q%rÏÿrzs$tÙt”¿u]v.w9`ïÿyèzà{Ý|Òÿ}¾~¥†€bþ{ðƒåƒª„eÿ… †Œ†í†$û‡0—°Ê†n†ÿÿ…“…9…ò„Êÿ„¿„Ò„÷„,¾ëP‹…¡…¦ _ÿ……·„D„É¿ƒEƒ»‚< lû+°LÿƒÁú%ï‚>‚J' E‚Cú- O—~‚œ‚¸ë‚Æð¸…pq‚Aþ™Î‰;àþ+ðÿ†‘ÿ~&~Ð}Ÿ}ˆ¿}Œ}³}âë°_¿~£~ã~"p¢ÿá)€o€²ÿ€é€-,ïý€¦€z?€R€?€.eà˜#߀ûËkàGÿý~±~p~A~W#~± 9£à`¡àßA~ ~¿IÀæ|ßf|ê{uWð¯zÿbz$zåyµyÿ‰y\y/‚ƒìƒß´„d…Õÿ†ÿY‡ž‡Ë‡ß‡ÿâ‡Ó‡´‡Œ‡ÿ_‡*‡õ†¹†ß„†A†7{…ß<……ÓåPŠ„p„S„+„ñ± ÿ;ƒ¹‚#‚xÿÏ€€sË~ß,~‘}øÓÒ{ýBYðEzày•yÿcyPyUynyý’Õ€éyzFzÿzz²zñz<{ÿ”{÷{e|Ñ|_F}¸}-m qÿ €‡€xõæ=p‘߂ڂÿ¹‚€‚+‚ÆýTO s€€ºýx¿°.!_W ÿó°ýñçõ~û~Õ Ý0££÷)Oå´ò#€Q€p€Š _Àò€7ð7 ÿ;ƒÙƒl„ó„ß_…±…ã 0 †ß†ñ…Ëù]… …©„8„ÁE0ßÁ‚N‚ìÐOßÜ€§À1€÷ç¡pÖ~u~ß~´}UY0§|ÿW| |É{Œ{ÿe{G{8{={ÝT€½{ €â|ÿ^}Ü}[~Ï~ÿ2…Äëÿ€ €€€!€,€<€M‘ ÷T€FÛÐÿÕÿ£vQ6Ý °ê~¿k 4~ÿË}V}Ó|T|ÿã{ƒ{7{{Ýî0 {;€Ó{ÿ9|°|5}Ç}ÿd~ ¹e€ÿ´O‚å‚ÿnƒóƒr„å„ßU…¼…#'0Ú†÷*‡g‹° ‡”‡ÿ\‡ÿ†€†Û…ÿ…O„{ƒ°‚ÿñH¶€B€ßäŸjAð/}W ð~Ô~°­ ÷%~Óݰ}Ê|ÿ†|U|7|.|ý-EP+|||ÿæ{Ë{±{¯{ÿÃ{ï{=|¤|ýã°ó}_~Á~'–€¼%àÿN‚?ƒ8„7…÷*† …Àyˆ‰ÿw‰Í‰ŠŠ ŠÑ‰t‰ê=à÷}‡¯ P…A„ÿ‡ƒØ‚1‚Žÿä€3€~¼~ÿù}.}g|¦{ÿíz7zyîxßRxÄwH¿ÀpvÿvÔušusuÿOuAu:uBuÿ[uƒu¾u vÿhvÌv?wºwßDxÒxkùpÅz€{<|í|—ãõ£Û0F1ð‘¥ÿ½Û€5€ßt€¿€{ÒýCƒðBƒÒƒm„ß …¥…@/N‡÷Ň8;‰a‰ÿ¶‰÷‰-ŠNŠßUŠKŠ6‹Pô‰ÿމωɉʉ÷ЉÒW`ȉ¼‰ÿ¦‰‰|‰h‰ßY‰L‰:ðˆÿ·ˆbˆê‡]‡©†Ü…ó„ë©ðÿ¤n€3~÷Ý|Êë`ãyyÿ@xpwšv·uÿÉtÏsÔrÝqÿöp-pƒoÿnÿžnbnEn>nÿRn}nÁn#oÿœo-pÒp‰qÿ?rør®sXtÿu¦uVvwÿæwÉxÈyÖzö{}/~F]ÿD+‚ƒÉƒÿ„8…Þ…w†ÿ‡„‡î‡LˆÿˆÖˆ‰‰ý,p‰ ‰åˆÿ¼ˆŽˆXˆˆ÷Û‡—° ‡È†ÿ†>††Ñ…ÿ§…„…j…Y…ÿN…R…g……ýÌõ@‘†‡™‡Wˆƒ{°ëp™Q¸‡.‡ª†3{`ÿž…t…U…6…ÿ…߄ބ#„ÿ¤ƒ ƒc‚¯ýþÀ–í~F~ÿ }û|P|Ÿ{ýçÑ€Vy}x¦wÿÊvvJu°tÿ=tås´sžsÿ£s²sÇsàsÿ÷st0t_týŸ¡huòuvÿ9wíwx>yÿÖyYzÌz0{‡{Õ{|VÇðÿÍ|}S}š}ßß}.~v¯@ÿ~_9k”ðÍw ÿõ€0€]€Ý“ï&{`/‚ÿƒ‚Ø‚)ƒnƒÿ®ƒîƒ*„k„÷©„ìyPˆ…×…ÿ)†{†Î†‡õf‡Àp¼ˆ'‰ÿ¡‰%ŠªŠ)‹ÿ ‹ŒGŒoŒÿxŒgŒ=Œú‹ÿ­‹Q‹çŠqŠýì+Ĉ"ˆp‡ÿ¼† †Y…±„ÿ „sƒÞ‚D‚ÿ¥í€&€Jÿ\~c}a|i{ÿz·yyux×ýwš×ÉPöuÿkuÐt,t‹sÿñrrrrÖqÿ¿qÌqþqJrÿ«r!s¨sBtÿñt³u“vˆwÿx©yÉzä{ÿö|ó}Õ~˜w<€Ëý ¤‹ÿ¶‚ƒfƒµƒ÷ûƒ0=0]„N„ß(„ Ø‚÷k‚úk³€ÝX¹0Ñ WÀkÝW»Ð9uÈ~õ”» ,¯Ðà}Ô}ÿÞ}~5~~~×Û~AÝ@7ïGýÚõþ‚Šƒ „ýzï…5…7…ß(……Ö€„h„`„l„…  Þ„…G…qùË…ô…†M÷@ÿ»†÷†:‡s‡ÿ¡‡Ì‡ë‡þ‡ÿ ˆˆˆô‡ÝÖyQ‡ç× ´…}ì• ƒ'‚3 ÿb‹~Ã}}ßI|Ž{Ø àYyÿœxÛw(wxvÿÌu7u«t3tÿ×s”ssstsÿŸsòsgtûtÿ¨ubv%wðwÿ³xsy*zÚzw{Ó@4}£‡àß@~h~{óm~÷T~3O@î}Ð}¯}—}‚}v  ÿ…}µ}û}]~ÿá~z+€ä€ý›¡0â‚aƒÃƒÿ „3„I„Q„ßP„K„M=0Z„÷g„n;0d„H„÷„á™ Hƒó‚ÿ£‚[‚‚ãý°°a/ü€ÿÀ€}€4€ïߨl5ç0è~ÿÎ~Ä~Ã~Å~×Ñ~å9ð)ÿà΀_€· ßlÌ0Íàó‚ýTkÀ„o„Õ„õ<ûÕü†a‡Õ®0óƒÀµ0ê†ýZ-0…g„ºƒÿƒo‚ÙUwÝ€uŸ ¾d °”~~„}ß1Àÿy{Ðz2z«yÿByøxÐx¿xÿÍxîx!ybyw°y_ð·z_0÷o{„_@ƒ{v{ßp{z{£9À\|ÿè|…}0~Ý~ýƒÀ¡€ÿÜ*‚o‚©‚ÿ΂á‚܂Ăÿ›‚]‚‚Ö×’W±ðúïÀ€÷ª€›û0w€d€ÿH€-€ €ßW­t§@ô¥Ðr· ßÿ}Æ}S@}ÿÇ|w||Á{ÿ]{üzšz:zÿáy‘yIyyÿðxãxýx6yÿ˜yz¸zg{ý*°©}f~#ßÖ•€W“ ƒÿõƒà„¿…‰†ÿ=‡Î‡;ˆˆßĈäˆ÷C‰w/‰O)‰²‡PõßM`ÒÛ°ˆ‰R‰‰Åˆwˆ)Sÿw‡‡£†#†ÿ’…í„6„xƒÿ®‚åU€÷’ÒéÐI}||ÿ¨{ÑzzDyß—xx·ÙvÿvDvòu•uý1•€€tEt1t÷GtÑu8vÝâ¹€ x›™°Eyßy©yÚñPmzÿàz{{>|,}ÿ7~aœ€ÞÿƒC„S…H†÷!‡×Љ{‰ÿó‰aŠÓŠA‹ÿ±‹ŒŠŒúŒÿ^ºŽ9ŽÿOŽBŽ޵ÿ3ŒÏ‹úŠÿ Š<‰\ˆ‡ÿ¦†É…ð„„ÿ;ƒV‚v€ÿ´Ø~~<}ÿl|©{ßzzÿEysxŸwÆvÿÜuñtþsÿrÿþqÿp p#oÿTn£mm¬lÿklIlGlalÿ•lælPmÔmÿpn+oúoÖpÿ¿q±r¢s•tÿŒuŒvšw½xÿøyF{«|~ÿ|Õ€‚5ƒÿ-„…Á…h†ÿþ†‡ˆ—ˆÿ‰Ž‰ù‰^Šÿ²Š ‹[‹°‹ÿ ŒmŒÊŒ&ÿ}ÀõŽÿ!ŽŽÿ×¥cÇGÐÿŒÀ‹k‹"‹ÿéŠ½Š’ŠwŠÿSŠ)Šð‰¤‰ÿJ‰Ýˆkˆó‡ÿ‡‡Ã†|†ÿD††û…â…÷Ã…£/0A…ý„ÿ«„G„Õƒ^ƒõãó€õW !¿€÷[€ðßÐç~E~ÿŒ}Á|å{ {ÿ3z^yxÌwÿ wKvŽuÆtÿt>sƒrÜqÿKqÒp|p9pÿpõoÖo¾oÿžoyoQo)oÿ oónðnúnÿoJoŠoÚoÿ2p›p q‰qÿr r9sÙsÿ~t,uÝu–vÿWwxêxºyÿŒzX{!|Ü|ÿ}8~Ø~uýÃàd‚ׂߔƒO„e7†ÿ¾†6‡¨‡ˆý‚yÀ…‰ŠÄŠÿz‹?Œâÿ½Ž“`‘ÿº‘K’³’þ’ÿ"“'“ “à’ÿ¡’[’ ’¹‘ÿo‘#‘ׂÿ§jŽÿ µŒ°‹—Šÿo‰@ˆ‡ô…ÿé„ùƒƒ]‚ß²$¢@À×Sé'{M}ÿð||[|!|ßý{ä{×ÍpÒ{ÿÎ{¾{›{_{ÿ{šz zeyÿ¬xäwwHvÿ~u¾ttosãrjrr» àÿvq{q™qÐqÿrer¸r sÿYsœsÕstÿ.tTtwt tÿÒtuWu­uÿv{vúv†wÿx·x]y zÿ³z[{ù{™|ß/}¾}K)l}ü±°+ÂWç@ÿjƒéƒc„Ñ„ß=…«…ÐÛ†ÿ5‡‚‡À‡õ‡wˆ3Xˆopõ¼1'µ‰ø‰ÿ1ŠfŠˆŠžŠÿ£Š–ŠuŠAŠÿú‰£‰>‰Ðˆÿ^ˆò‡…‡!‡ÿÀ†^†ö…‰…ÿ…~„âƒ<ƒÿ›‚øhê€ß~€)€áe°„÷_C%P(-wHqe°ñ9Q ÿ³€à€ø€  çðÿ4Snÿ‚‘–…ÿd6ó€¥€ÿI€ê‰,ÿÝ~ž~k~G~ÿ)~~â}ª}ÿa}}||ÿ„{òzqzíyÿpyóxtxïwÿ_wËv;v´uÿEuûtÖtâtÿufuÏu;vÿ­v w]w¡wÿÝwx]x¨xÿyqyáyRzÿ¼z{f{Ÿ{ÿÌ{î{||ÿ5|J|h|ˆ|ÿ²|Û|}K}ÿ}Ö}(~}~÷Ü~@P€l€ÿÓ€6›‚õr§0O% 8„µ„ÿ2…»…G†Ü†ÿz‡ˆËˆw‰ÿ#ŠÆŠX‹â‹ÿRŒ§ŒàŒûŒßøŒÚŒ­GÐ&ŒÿÚ‹‘‹K‹ ‹ÿÇŠ‡Š:Šá‰ÿs‰ôˆ[ˆ®‡ÿí†%†V…’„Ûƒ4ƒ¨‚3Ë ÷V þ€Ý€ý¬ C€€¿wy3k°½~ŽñwE~(ÁÀé}Èëÿ}Z}=}}ß }þ|ü;ÿ|} }}5ÿ'}/};}9}W4}ÃૃpÛi@ÿ¼z!zyâxÿVxÏw^wûvÿ¨vcv'vþuÿÜuÉu»u½uÈuáuv0ãPÿ²vüvOw§wÿûwTx¤xòxÿFy—yêyBz÷¦z°Ö{5|ÿ‘|Þ|!}b}ÿž}ê}A~ª~ÿ,Åt€9‚Ì‚“ƒT'Ðw …% 0Άìù@ý¥ÐÄ…8…¥„„±ƒuƒZ €_§ƒïƒ?90É€ÿû„ö„é„ß„ÿׄá„…;…ý†•ÐK†¿†?‡ÿƇWˆôˆ›‰ÿGŠÿН‹`ŒÿùŒwÞŽÿŽþ­)ÿ{Œ«‹¸Š­‰ÿŠˆ\‡!†æ„ÿ¢ƒb‚#êÿÁ~©}©|Ë{ÿ{…zzÝy_¶y§y¢a g0ÿŠyuygy]yÿVyQy^yjyõ|i œSÀ¸yÏyÿèyzLzŽzßäz={¡uj|ßÎ|-}‡6~݈-PUÇð÷¯¬•0n:×ö~©ùÿëL}ÿ}®|e||ßÙ{Ž{<­ezÿäyRy¸xxÿ‚w÷v|vv÷Øu¨/À˜u©ußÊuÿuHq%w÷¿w}3ð^z|{ÿ¬|ê},c€÷Žé@/„Ë„ýI)`ë…'†Q†ÿw†˜†·†Ô†ýésú†å†Ï†÷©†z%p†Í…ÿ‘…\…%…ñ„ý»õP„„уŠƒIƒƒÏM ÿ•‚š‚·‚ò‚ßKƒ³ƒ)€&…–…ÿ…T†£×ß9‡š‡ǰ"‰ÿΉxŠ‹¤‹÷ ŒCA€ŒÃ‹ÿ?‹˜ŠÚ‰‰'ˆB‡Z†q÷ÿ´ƒä‚#‚nßÉ€7€²I@Á~÷S~ì‰;}î|ÿ´|}|N|#|÷ñ{¬i@ázPz¬yûx?x‡€÷:v©1ÀÌttt÷*t䯀wsKsÿ,sssórÿârÔrÃr´rÿ­rµrËrsÿZsÖsotuÿÒu‹v;wÑwÿNx«xûx4yýd°ÈyzUzÿ±z{š{-|÷Õ|•«°NK€ÿSo‚‰ƒ¥„ÿ¾…Õ†ë‡ùˆÿþ‰ÿŠ÷‹ÙŒÿ«]ŽãŽEÿ~‡kÿB"ñŽÿçŽÓ޶އŽÿ3޼UŒl‹jŠV‰6¡àö…ã„܃ßPÿS€˜î~ÿA~¡}ü|W|ý°ÝàgzÃy:yÿÈxnx/x xÿxþw xxÿxúwáw¹wÿŠw\w6wwÿww/wUwÿ‰wÏw"xxÿðxjyûy•zÿ?{ü{¾|Œ}ÿ\~)ô´€r!‚Ê‚h߀ý‹_‘…†ˆ†ÿ†r‡â‡Kq`ÿ#‰Š‰õ‰]ŠÿÅŠ&‹{‹¼‹ÿè‹ù‹Ú‹˜‹ÿ.‹šŠæ‰‰ÿ5ˆN‡n†–…ÿÑ„„zƒç‚ÿ`‚ØQË€ÿ?€«†~ÿ÷}i}à|\|ÿÍ{2{•zæyÿ/ymx wÞvÿ%v{uêtutÿtÌs•shsÿBssörÏrÿ¥r{rTr7rÿ$rrrrÿ,rGrhr’rÿÌrs…s tÿµt~umvwwÿ›xÑy{I|ÿv}‘~™‡€ýa“ ý‚̃¨„ÿ“…†Ž‡ˆ÷‰‰mƒÀô‹Œÿ‹ŽrŽÿòŽyÿ…ÿ‘f‘°‘Ø‘ÿÚ‘¾‘„‘4‘ÿÇH»ÿdŽŸÊŒë‹ÿ‹Š;‰^ˆÿ‰‡¹†å……ÿ-„:ƒ9‚*ÿ€ý~ê}Þ|ÿÚ{èzúy!yßRxŠwÒu•ußu²te­ptÿtt"tPtÿ’tçtWuÙuÿjvw¬wExÿÖxWyÌy;z÷ŸzmÊ{/|÷|ã™ \}w}×}s!GS&}ÿ*}0}E}e}ý}µÁ}é}~\~£~õ~V¿þ¬0€/©-‚w²‚;í`e„+pÿQ†ø†›‡4ˆÿÁˆ8‰›‰Ý‰ßŠŠèÛ°W‰ÿæˆeˆØ‡D‡ÿ©††n…Ì„ÿ„nƒ»‚‚ÿL€ú]ÿÊ~>~½}+}ÿž||\{³zÿz_yÇxGxÿáw™wqwewÿwwŸwÖw&xÿ{xßxKyÀyß:z´z3Ç0!|ÿ|ö|W}´}÷~pq .ŠÕåË€†Q°ó+°'ý.Ap ÷€wå€Þáð퀯àßFg†ýðœýŠ[p3쀜€L€ø±z§ ÿDIfŽÿÏ€g€Ä€(#‚À0ÿ3„…Ý…±†ÿt‡ˆ“ˆÛˆÿïˆÍˆ{ˆˆß†‡ü†s«ðŒ…ÿ<…ÿ„؄DŽßÀ„΄ç'Ð"…ÿ=…S…Q…6…ÿú„–„ „Wƒÿˆ‚›ž€š÷š~¦}°|[{ÿÛz|zCz%zÿ z)z?zSzÿczhzgz[zýOëp;z>zEz]zxz™z»áÿúz{-{K{ýlÍ ¬{Ë{Ý{÷ß{ÉÙàS{ùz}”íp¿yeyï ÿäxëx y>ywwy¾#@Jz•áß{k{Ä-@ª|ÿE}ú}¿~žÿ†€jP‚$ƒýñ?@J…ç…†Ýy+ˆ©5Ðd‰ß•‰œ‰xÓ°ÓˆÿZˆß‡d‡õ†÷•†B70Ð…ž…ÿm…3…î„“„ÿ!„’ƒè‚ ‚ÿ48€*~ýûËà{dzßyß‹ymy{] zÿ‹z{¯{O|ßí|‰}ø~ÿCw™¡¥¤®ÇIð÷I€´ÃÅ[‚ÿè‚iƒËƒ„ý=- S„N„<„1„0„5„LW÷Š„¬½pæ„ø„ßú„ô„ê·p½„ýœ; 6„탓ƒÿ*ƒ¬‚&‚ÿ–€*€ÎÿŒ\A0÷&m ô~Ö~u³¡ dq°~ëu°w¥}ƒ³B}$§ßá|¾|˜°R|ÿ*||Ý{¶{ÿ’{y{^{M{ÿ;{/{ {{ÿúzçzÔzÁz}¶¡°¼zÐzë°÷${@_a{h{ÿm{r{}{‘{ÿ±{Û{|L|ÿ†|½|ì|}Ý1`Q}^OPy}ÿŽ}«}Ì}ô}ß!~L~ƒõ~ýA± íQ€Â€ÿ7¾H‚Ô‚ýe÷@‰„…’…ÿ†k†»†ô†ß‡-‡9 ¦8‡ÿ4‡'‡ ‡Ñ†ÿ††&†®…,…ÿ¨„(„¸ƒSƒÿƒÍ‚‚t‚ÿF‚‚Õ„_(½€Oc°kÙ }¨³0 ~à}Â)pß¾}Û}ë`~~ßÁ~<¹ÐªÿÕõ€8€ß^€€«O° ÝOG°â9W0ü‚ÿ`ƒ¼ƒ „C„a„^„@„E ÿ6ƒÃ‚Q‚è_HäO°ÿ߀ã€è€ò€ÿú€þ€ Ý ½ òOp½€ý’q %€à”ÿBó~~J~ýø]}}â|³|Ž|p|b›@ßO|E|;Ã0|÷é{Æ‘ ƒ{w{ÿ{–{¿{ö{ÿ3|o|£|À|¿|œ|T|ì§ÿ¿z zGy|xÿ¯wêv,vzuýÙ7ÀÎsessÿÝrÂr¹rÉrÿòr3sˆsís}eG`su v§ÿxÉx yŽzÿ—{¹|ú}Mÿ³€%‚•ƒÿ„ÿb†¯‡ìˆ Šÿ‹ ŒãŒ§ÿKŽÜŽN­ÿþ;o™ÿÆã‘‘ÿ‘‘ã¤ÿBÉ5“Žÿä*sŒ¼‹ÿ‹oŠÙ‰P‰ÿψ\ˆñ‡‰‡#‡¼†E†Ê ÿŸ„óƒ=ƒ~‚ÿà [€³ÿ•~~µ}ÿW} }Å|Œ|ÿZ|1||ö{}è#€à{õ{ï ÿ˜|ç|B}š}ßì}2~aŒ~ÿ„~v~]~F~÷7~,~~ßù}Ù}ŸÝ°ø|Ý…÷ ~{äóp“yÿ×xxUw”vÿÚu6u¥t3tÿás°s›s£sÿÂsôs6t}tÿÉtu`u¡uÿÛu v)v@v÷LvWeÀ_vivßxvˆv›Q¼vÿÎvÛvóvwÿSw³w3xÑx÷y`ß@$|ø|ÿÄ}€~2êÿ¤€pZ‚Zƒÿs„¡…Ô†ˆÿ‰Š‹Î‹ÿvŒ{æÿEŽ’Ž×Žÿ$)íŽ÷­Ž]/ ”&ÿ²Œ<Œ½‹:‹ÿ¶Š,Š™‰ýˆÿaˆÄ‡&‡‹†ßí…U…Ä ¦ƒ]$1A‚âýðlõðÿUqžÒw‚E£‚—W0ÿ‚‰‚‡‚™‚Æ‚ƒaƒÈ‘pýšù …-……ÿЄg„àƒ?ƒ}‘?Pc€¯G ×]~Á}`£Ã0³{ÿL{ðz£zVzÿzÍy‡y7yýÛp xw wÿ‡vv—u;ußútÚtÐwÐñtß u!u$Ðu÷øtéG÷t+uÿxuâu_vëvÿpwòwixÒxu6_ 7ðY{?ßç}ß~Îí@ÿK‚õ‚†ƒ„_e„ª„Ò É¡€ÿG„Úƒeƒà‚ÿ[‚Ü^î€_}€€¢Íð¾ÿÔ}h} }Ä|×–|€#p²Ï€>}÷”}í¹†~Å~×ì~ IP(µ Uÿ…Æ(€©€ß=ê¥Uð8„ÿ …Þ…­††‡eˆE‰-ŠÍPÿÐŒŸ\ŽþŽÿ’c£ÿÅȱzÿ3ÓeïŽÿtŽõpäŒÿJŒ£‹éŠŠÿ1‰<ˆ?‡6†ÿ/…2„@ƒ\‚÷®C M~÷Œ}Õç°•{{ÿœz:zÙyxyÿy¡xx–wwkvßuZiPÿŒt?ttÒsÿ§s‡slsXsýT·àks‰s±sÿâstItltÿŠt›t£t¤t÷ŸtÑà§t´týÍ‹ÐuGu‚u÷ÄukÀÊv,w wx˜x&pÿez{å{º|ÿœ}‰~t_€ÿE%‚ÿ‚ك߫„…Js€Ô‡€ˆ‰“‰ì¿ÿ:Š7Š"ŠŠÿò‰ä‰Þ‰è‰ÿü‰ ŠŠŠý )P±‰p‰'‰ÿ߈›ˆbˆ4ˆÿ ˆï‡Ò‡±‡ÿ‹‡Y‡‡Ç†ßp† †£³pÕ„ÿ„3„胤ƒÿ`ƒƒ¸‚M‚ÿÎ8•€ð×L³ÀÀíÐ(}ÿù|Ð|·|¢|õ—°®i`0}—}ý’â߀€ Ã×¢·ðšå€ºÿ¸œauž%³w`ò|¶­w|u|{|ƒ­÷ |¼/@ú|}wD}nÏ­}»]Ã}¼}§}’íðßG}}Ôã°C|ÿ|Á{”{v{ýj©r{~{Œ{ß‹{‡{z«f{ýd˜{È{þ{ÿF|‰|Ê|}Ý,Á ^}cu`T}ÝCS%}I=}ÿx}Ñ}I~â~ÿ‘T€)üÿÌ‚šƒ\„…ÿµ…P†Þ†[‡ÿˇ2ˆŒˆÞˆÿ+‰{‰Ê‰ŠÿtŠÄŠ‹/‹ÿ8‹‹ÑŠcŠÿ̉‰Uˆ~‡ÿ†¯…¼„»ƒÿ­‚—€qßx~›}éÇ |ÿß{Ó{Ù{ï{÷ |-s‡|Ã|ÿ}|}ñ}y~ÿ†€v€ÿâ€Fª‚ÿ‚‚ô‚lƒÝƒWH„˜0âÇЮÃÐÿ „˜ƒƒ‚ÿýbÅ€€w}ÙÀ™}÷¹ý›çpz6yQxÿkwv¾uuÿ`tÜsnssÿÛr³ržr rÿÄr systÿËt¤u•v“wÿx~y]z#{ßÔ{h|è'p°}ÿý}<~x~±~÷í~5}pþƒ€ÿ%Ù£‚vƒÿL„#…ð…¸†ÿk‡ˆÅˆa‰ÿò‰€ŠûŠj‹ÿÌ‹!ŒkŒ¢ŒÿÌŒçŒôŒïŒÿÒŒ ŒPŒæ‹÷b‹É)ðr‰¹ˆó‡3‡i†˜wãƒü©€KˆC ÷PÝ] .~å}õ›`éÛð|®{÷V{óz {ÿ:{n{ª{ä{ýó Y|l|x|ý‚ã°—|ž|¨|ݰù®|›Ýð_|ÿ2|ÿ{Å{…{ßE{{ïM€ãzß {F{Ÿ·|W}`ša Z»ðÿÌò €€ÿ&€.€C€\€ÿw€Ÿ€Ì€û€ý+APp‡•wš›S ™˜Ð÷¢¥S ŠfÝ1§ ¡€FÏ t} I I~ò}¤íÐ1}}è|Ô5ßÍ|á|E}ßÿ}|~­ O€ýëï@â,‚b‚þÝ ‚v‚s‚}‚ÿ–‚Å‚ƒNƒý—ã„>„T„_\„Y„J +ÿ³ƒfƒú‚i‚÷¹ð5 .J~ÿu}º|"|«{÷Y{#Ÿ@ÿzýzþz{{ü€_{{4«½-@}¸'p ~Â~{à_Ê€VÖï¶g€}—û€ „;…áÁP=‡ç‡…ˆ»`ÿŠvŠÉŠ‹ÿR‹†‹¯‹Ç‹ÿÏ‹¿‹”‹G‹ÿÚŠNЬ‰ëˆý /P|†¶…ø„ÿI„«ƒƒu‚Ó&m€±0÷ß}û÷  {0zÿEyVxYwXvÿLu2tsrÿøpp%otnÿámvm>m,mÿFmmßmdnÿ oÀo†p\q+rór£sCSÀ>u¥uvjyÀbwxºx†ùà÷N{5Áê}­~ÿa €¨€CýÜ;@ƒ”ƒ%„ÿ£„…x…Í…ÿ†e†°†‡÷h‡Ý/àøˆ’‰ÿ%еŠ.‹•‹ÿé‹6Œ{ŒÂŒ|ígU@ÿY½ =ÿQI(êÿ H掀ŽÿŽª@ÕŒÿoŒ Œ«‹K‹ÿ슃ŠŠ‹‰ÿòˆHˆ‡‡´†ÿØ…ð„„ ƒÿ‚€~}|{0ÿSyxÌwwÿ„vúu|uuõ©ÅàóGÀFsòrÿŸrNrþq¸qÿwqDqqôpÿÓp±p‡pXpÿpäo®oƒoÿloo±opÿŒp%qÏq„rÿ=sést4uÿÔuuvwºwÿ\xy¦yBzÿáz€{(|Ù|ÿš}n~O;€ý1 ð ƒäƒ©„ÿ`… †¬†I‡ÿ釆ˆ,‰Å‰ÿYŠâŠY‹À‹ÿŒZŒ‘Œ¾ŒÿÖŒèŒìŒßŒÿÎŒ¹ŒŒ‰Œÿ}ŒtŒzŒ‚ŒÿŠŒ‡ŒuŒGŒÿÿ‹™‹‹qŠÿ·‰èˆ ˆ#‡ÿ+†)… „ƒß‚-Vo0ÿ~1~ì}¶}݇#À }äõX|w|Çÿ >{û™ÿ{z@zzõyßéyóy€}zÿÀz{O{{õì«P³ðÉ}r~_+çœÛ0Ó»Ðÿ¦‚ð‚%ƒRƒßyƒšƒµ§`ӃݩPWƒþЂÿuå€[€ÙßnÆ À^~ÿ/~~Ê}†}ÿ6}Ú|n||ÿ¤{J{ {ázWÎzÍM€ïõ ‹à]í { ‰B߸{û{Bõа|Î|à|Ø|É™ð‹|k|P|@ñ ÿa|•|æ|R}ÿØ}m~½÷[€î›ÀÛ8‚ÿ…‚Ç‚ƒ>ƒÿqƒ ƒÊƒæƒßòƒëƒÑoðhƒ÷!ƒÕÝ'‚Ëßišo Ú}„wpù~ôÍ5N[AuPw`o`è~à[} wp–úp3`ÿs‚‘‚ƒÿ£ƒ„‘„õ„ÿH……º…â…ýøí@†,†G†ÿm†š†Î† ‡K‡‡¬‡Éqÿ·‡†‡:‡Ó†÷[†Í𦄄ÿƒ"ƒÇ‚†‚c‚R‚W‚f© ß‚ž‚´³ Ö‚ýï!Ð&ƒ:ƒHƒÿAƒƒ×‚n‚ÿÛ!P€oý|ƒà¢|¼{Ýzÿÿy#yCx\wÿrv€u’t¥sÿÀräqqMpÿoÜn7nšmÿmŸl@lýkÿàkæk lWlÿÇlZm nÖnÿÅoÇpáqsÿHtŽuÛv5xÿyözh|ã}ÿjü€‘‚!„ÿ§…‡|ˆÀ‰ÿçŠí‹ÝŒ¶ÿ{Ž/ÖiÿêU‘´‘ü‘ß.’P’b›pT’ÿ8’ ’É‘{‘‘©+¥ÅÀÿŽã:‡ŒýÃC@Љˆß‡†sàQƒÿ‚´ê€€ÕMp¶%ÀNQÐ({õµI€àC€ÿx~xÿíwUw½v.vÿ²uIuuÏt÷¶tº9ìtuÿWu›uîuOv¾v9w¹w>Å0ý5Í@zbz°z÷ðz-ž{×{ý ~|»|ý|ý@ÕPÓ}*~…~ÿæ~K°€ÿh€²€ì€×*-k0?Ð0__§ ÐÏ ÿ@„¸„…T…ÿs…}…z…u…ÿv…†…¤…Ë…ÿï…†† †ÿä…¡…P…ñ„ß›„O„7ÐÀƒß¡ƒ|ƒG³˜‚ÿ‚’ø€a€ÿÖXì~—~ý[Ã~~~ÿ;~r~µ~ßd¿A t€ÝsA  €«w`½~ßH~Þ}…ëð }ß}!}AQ¾}ÿ~n~Ô~?ÿ¦€o€»€ÿý€$;<ÿ%ý€Æ€y€_(€ÌlK¢[ Ù}{}&}Ûoÿk|M|J|\|ÿ|Ú|;}±}ÿ8~Æ~Wëÿ€¡4‚÷¿‚G­P6„‹„ÿÊ„æ„à„µ„ÿq„„ªƒ7ƒuËë`ñ¡ 2Ös ×,€áý€tð-ÿö~É~“~õ=!cËr||ß­{i{5í Ùzÿ•z>zËy=yÿxówQw³v7vÔuuaáàßEuOulYÀñuÿavõv²wxÿŠyzÀ{æ|ÿ~<f€’ß¼‚ïƒk€‡ÿ¥ˆ¸‰¼Š¥‹ß~Œ;Ø=àÀŽÿ,0ÿðŽ«Ž[ŽŽÿµm)êŒÿ®ŒlŒ&ŒÕ‹ÿ€‹!‹ÂŠjŠÿŠÛ‰¤‰y‰ÿS‰0‰‰Óˆÿˆ:ˆÓ‡S‡††Y…‡— ÿ¯‚®¤€–ÿŽ~‡}„|‰{ý1À”x™w–vÿŸuºtùs]sßãrr}e rÿ¨rºr¿r°rÿ‘r_r)rìqÿ³q}qNq&qqépÕp· ÿùp6qqþqÿ†rs®sAtÿÊtFu·u'vÿ”v wŠwxÿ«x?yÎyMzw½z+€¸{ Ùð÷õ|‘UðÿÏ€žk‚'ƒ÷؃‡'0ý…Ò†ÿ‡ÀˆÍ‰äŠÿó‹óŒÚ§ŽÿO×=†ý²‹°¾œhÿ½IÌŽ÷B޶  ¢Œ%Œ}´A@ꊊ9?ðÿ‰:‰×ˆ~ˆÿˆ¿‡e‡‡ÿ±†W†÷…‹…÷…›Ý`ƒä‚ÿN‚¸+£€ß%€±9߀>~ý¯Kˆ|í{W{ÿÈzBzÅyTyýéeÐx¶w\wÿwÛv½vÃvÿåv.w•wxÿ³xUyz²zý]/ž|9}Ê}ÿN~Ë~Aªß€L€ƒಀ÷¬€†Ñ€ÿ ÷.­À¢}}ßš||©gPÛzÿ„z8zzÚyÿÆyÁyÍyäyÿzz&z.zÿ(zz z÷yÿêyæyèyðyýõwPæyÌy£yÿoy;y yÜxÿÈx¾xÐxïxÿyHy~y²yÿïy,z~zÜzÿO{Ò{k| }÷¯}\) ¡A€ÿဆ5‚ë‚ÿ²ƒ}„O…#†ÿ솳‡iˆ‰ÿ¨‰5жŠ*‹Ý“7àGŒŽ PâŒõéP¼#PEŒò‹ý¢?0 ‹ÙйŠ©ŠªŠ²Š¿cÀ÷£Šq;𦉉ÿjˆ³‡ú†A†ÿ–…÷„f„Öƒý\ÕÐb‚êtß–€7»™ÿ]$ü~Ö~ÿ¸~~Ž~‚~ÿ|~€~z~q~ÿ\~9~~µ}Ý[ „|ÑN{ß÷z¤zSð¦yÿEyØx_xêwÿxwwÈv‘vßyv~v¢¿0,wÿ“w xˆxy÷Ÿy6éP[{è{ýg`6}‰}Ð}}q~¤~Ù àÿ5S_Q÷0î·€,~¾}÷M}â÷ÐG||õ{æ{î{·°ÿF|s|¬|ç|ÿ,}u}À} ~ÿN~~Ç~ø~}}73 KPÿà~²~ƒ~Q~ÿ$~û}à}Í}}ÅoÐÐ}Þ}÷¡ðÿ<~o~³~oés€[ ý/K3ƒƒüƒÿI„„Í„…ÿR…—…Ý…†ÿM†s††€†ÿu†\†F†5†:†S†Ž†æoßꇈ;!ð›Šÿ=‹Ð‹MŒ±ŒÿûŒ%4 ý÷  KŒÒ‹N‹ý³=ðb‰¬ˆö‡ÿ4‡s†³…ó„_4„~ƒÏ[`‰Ù _€ÓJÃÿº}:}À|D|ýÈÿP´zz^yÿ‘x§wªvœuÿ‡ttsnr|qÿ¡pêoPoÔnÿznCn+n?nÿ€nînˆoOpÿ4q;rWsttÿ•u³vÉwáxÿôy {"|5}ÿL~XN€,ài‚Ê‚üµ ýëõ`i‚ ‚£ý7o|€9€€Uô“`Ñ€˜Q€F_ ÿ‚m‚ׂIƒwÁƒF›ÐQ…Õðß±†û†:)°|‡w‰‡…±àc‡@[ðᆤ†^†×`ÿ…*…É„X„ÿу5ƒ‚‚¾ÿõ€)€nÇ~ß@~Ô}ëð}ÿê|Á|¡|ˆ|ÿ||†|©|â|ý-UPâ}3~i~_‡~„~j·ÀùSPÝ~"} ÿ|ý ðH}z}½}ß~h~Ì]  €z€ê€[›P_R‚Ô‚YÓ Kïÿþ„3…M…L…ÿ6……Ó„’„÷G„òQ`Pƒƒÿµ‚e‚‚Éßy·™°Ø]go`š~S¯°OPÿ\~˜~Ü~!×`‘¿ð×…Ðû_€€G°4; ÿW€n€€¹€ÿí€4€Òÿ-‚~‚Ë‚ ƒÝ@C`’ƒ²­P߃wéƒìÃðÁƒ‘]òÿ¡‚?‚܉ÿ>ë€ß€ÿç€ø€ ÿÿ€¼€R€ÿÆ7~B}ÿ>|7{.z5yÝG¢víûpºtÿ9tÎsts0sÿsérârçrÿñrsssÿssñrÕrÿ¶ršrŒrrw®rä¹@Ásg¿@ÿv!w6xVyÿ„z®{â|~ÿ`´€‚xƒÿä„Q†¯‡øˆÿ$Š'‹Œ¿Œÿ_àNŽ´Žÿg¶þÿ:i…˜ÿŸ ¡¦ÿ±ÇÙìÿú÷Þ«ÿZðnØŽÿ6ŽðŒWŒýËãÐÖŠ]ŠÜ‰÷P‰©íÐ%‡L†m…Š„°ƒÞ[`ÿsÑ€3€‘ÝçÃf}‹™zÿy}x`wKvÿ;u7tEsbrÿ¢qýptppÿ²otoAooÿõnÝnÉn¾nÿ½nÐnënoÿUoœoìoDp}Ÿ [q¼q)1ÿs—s$t¾tÝfCèvÖUàzÿP{´|#~¡ÿ‡‚Ûƒ…ÿ†‡Ù‡ˆÿ‰‚‰Ú‰Šÿ8ŠCŠ<Š#ŠÿŠÕ‰ª‰…‰ÿ_‰;‰‰ôˆÿˆwˆˆ‡ÿ ‡d†¡…Ù„ÿ „4ƒc‚–ÿЀ€Y°~ß~}üñ-|ÿç{º{§{¬{ßÈ{ô{3ÍÌ|÷}pP#~†~ÿù~|€Á€ßQ‚/#0…÷ë…Í_Œˆc‰ÿ3Š‹¸‹oŒÿ •ŽOŽÿyŽwŽQŽþýˆ§>Œ€‹·Šÿì‰+‰rˆÆ‡ÿ‡q†À……ÿ(„8ƒ)‚÷Ø¥á K|.{üÔ°#pewŽvÄuÿuFtœssÿ}rr²qeqÿ-qqóp÷pÿqRqªqrÿ«r?s×shtÿïtcuÅuvÿhvµvw]w½wx€xÕÀÿJyny…y–yÿªyÉyöy-zÿzzÑz6{­{ÿ,|Â|q}A~ÿ3I€΂ÿ$„t…²†Ú‡ÿàˆ¹‰mŠ‹z‹ã‹:Œ…@ßïŒ § ÿòŒÏŒ§Œ„Œÿ`Œ8ŒŒê‹ý½ =‹ôŠ¡ŠÿPŠø‰¦‰Z‰ÿ‰Îˆ‰ˆBˆÿò‡š‡(‡¯†ÿ"†Š…ä„>„ߘƒõ‚]i0OÕ€b€îrµ€ÿY~·}}H|ý‡[°zgyÎxßPxäw©wÿ÷vÑv¶vœvÿ‚vivQv6vÿvvæuÄuÿšueu uÎtÿotts9sßêr±r–c Írÿ s’st»tÿhuvØvœwýa€ zñzÛ{ÿÌ|¾}±~›߀€\3oàÖƒÿ£„r…:†ÿ†ÿ¸‡dˆÿˆƒ‰ÿ÷‰SŠ¢ŠàŠÿ‹A‹f‹‹÷‹‹‰™ ]‹,‹Ýï@tŠ:¿pâ‰ÿ¿‰­‰”‰}‰ÿ\‰&‰ßˆ€ˆßˆ{‡Ö‰€W…ýˆÃÜ‚ ‚B÷‰€ä{Ê~V~ýëUP#}º|O|ýÜ•øz—zLzÿzz zVzÿ§z {w{å{ÿS|º|}f}×´}ÿ°Ÿ³[ýÄß@½€Láý†‘Ðツ.…ÿ½…2†…†·†ÿȆ¸†–†d†÷#†Òy€…„ÿ⃃‚Ñ€ÿlÞ}:|ƒzÿËxwˆutÿ rTq/p.oÿVn®m>m mÿ mMmÄmhnÿ.o pøpòqÿírçsätæuÿçvçwæxÛyÿÇz¨{y|A}¿~Í~£íÿ©‚σû„'†ÿ9‡.ˆùˆ•‰ÿŠEŠiŠuŠÿsŠvŠpŠwŠß†Š—Ѝ¡0ÁŠýÃcÀ¥Š…Š`Šÿ1Šþ‰»‰m‰ÿ‰ªˆ$ˆŒ‡ÿÛ† †9…P„÷gƒ×à q€ÿüZ*ý µ€Ó~Á~·~߯~¼~Øs`9ÿ€Ì€e€ß¦€ä€Ûðdý…‹Ð¹ÊÚýß'PÔÍÆÿÀ»¾Â÷Å̯ðÓâ÷üg£‚ƒÿmƒàƒJ„™„ÿƄȄ¡„N„ÿƃƒZ‚zÿ€™œ~›}ÿ—|•{z®yÿÊxöw1w‚vÿÙu6uœtÿsßjsÚrWy –qÿfqVqjq§qÿrurs£sÿ^t&uýuåvÿÑw¾x¢yvzÿ>{ì{|!}ݹŠí~¢1`&×ë¡MÊQ„ÿ³„Ý„…/…ÿi…³…†o†ÿ͆ ‡^‡w‡ÿh‡6‡Ù†V†ý¾;@j„ă,ƒÿ­‚L‚‚Ðÿ³£—Šõ|PIY€Û€÷º€œ£°y€w€ÿ~€–€À€ñ€}:`çC‚œû`ÿ5ƒlƒ™ƒ¼ƒÿ܃„.„h„ÿ«„ù„X…·…ÿ††ý††‡ÿˆ«ˆK‰ë‰ÿƒŠ ‹u‹¿‹ýçc`Ë‹–‹M‹ÿ󊌊Šv‰ÿLjí‡ë†Ç…ÿ|„ƒ¬5€ÿÉ~\}û{›zÿ6yÈwMvÇtÿ™‚÷÷ƒX ˆ6‰ßRŠI‹   e†€ñ`F"üŒÕ± ÷sŒ6YÀ¥‹W‹ÿ‹¼ŠŠGŠ!ŠŠá‰¹# ÿ‰ˆ×‡ñ†ÿç…È„™ƒp‚ÿUJ€Pj~߆} |±à´yÿ«x«w¾vïuÿ@u´tBtêsÿsNsùr¥rÿHrëqœqbqýF }qÖqSrÿðr¬s‡tquÿkvxw†x™yÿ¡z©{§|¢}ÿ—~˜©€Òÿƒw„ñ…w‡ÿþˆxŠÞ‹"ÿ7Ž)åuÿà‘>‘4‘ÿ ‘ÀYÚÿE Žé%ÿVŒu‹‡Š…‰ÿxˆb‡F†,…ÿ„ ƒ‚ÿ(€35~)}ÿ |èzÉy´x¾wïvKvÚ/0ÿ„uˆu§uÏuwþu4O švÏS ÿ9wnw›wÃw_çw x( 0Š] ÿ9y¾y`z{ÿä{Æ|²}£~}–Cf>‚Ëðÿj„…Š…†ÿr†Ñ†#‡f‡ÿ“‡¥‡œ‡t‡/‡Õ†c†éu€ý7°H„ôƒªƒßSƒè‚lÿP_^€˜ÓgÐë€õÄñà`à+||ÿû{Ü{Æ{´{ײ{DZP+¥Ó|ß4}Œ}Ñ'ð0~ÿJ~W~c~p~~©~à~Ë€ÿ¯ø2€a€ý‰P»€Ø€û€ß+e¦ÃP*‚ÿ^‚z‚‚h‚3‚î“3ñ ÿ€€B€€þ÷€ÛàB€]€÷p€oï€=€ €ÿ×—Y#ò~Å~¡~~×0ÿ)~ì}©}^}}Ë|‘|eá0õO‘§}i}wÁ}ð»~àÿ…Ç€D€õŽPE`-‚¨‚ÿ ƒ‚ƒÓƒ„ÝS„Ú]€…ƒÿ_ƒIƒ3ƒƒßƒÙ‚¤ë ‚ÿÈ„T@ÿJp®ÿÿ[‚³‚ƒOƒ÷Œƒ¹s0èƒïƒÿóƒ÷ƒöƒûƒ÷„?`P„r„ß‘„¬„¹EðŽ„ÿQ„üƒ“ƒƒß‚‚pË…ÿÏ~~=}g|÷ {å]°ÈyuyÿQyVy‚yÐyÿ2zªz/{±{ß2|±|$—€ä}ÞÔ~‘~®‘°Ü~õò3Ð@GßB, _з~Œ~d~K~:€w#~»}oÿ¢||{ëzÿwðwÂx©yÿ¢z¤{­|±}ÿ®~¦€s÷N‚O{„…ÿt…Ç…ø…†ß0†>†R©Ð§†×ñ†ZIoM¾‰ÿjŠ ‹—‹ Œ÷_Œ“± Œ|ŒÿDŒŒ¸‹j‹÷‹É£0Џ‰ÿX‰÷ˆ˜ˆDˆß÷‡±‡s»à‡ÿÁ†n††~…ÿå„8„}ƒÁ‚ÿ‚O¨€ €ÿ{÷~u~ú}÷}àm|/|ÿ|î{ñ{ÿ{ÿ|:|V|c|ýX•à{m{ßz÷7zuP!xwÿwËv™v†v÷„vŽ0¬v¸vÿËvÝvw,wÿqwÁw xx÷Üx.c  yÃyÿáyþy1zszýÅu º{M|é|÷‡}"aÐAÊýG#`0›ößG‚„‚±kàÓ‚ÿς‚©‚‚×t‚VÕðCÀ÷}êgàÞÙØ+Pŧw1…w[€ÊYÐŒ~æçàÿ°|*|»{a{ÿ!{õzÖzÍzßÒzázÿáh{¹{||+÷w~Bg ÷€ÝÿÀ‚«ƒ„m…ÿH†‡Ö‡€ˆÿ‰†‰Û‰Šÿ"ŠŠŠè‰ýÇË ‰|‰h‰ÿL‰-‰úˆºˆÿhˆˆ˜‡$‡ÿ´†J†ì…›…ýaÕP…þ„ø„õûÃ;@……ÿ턼„s„„ÿ¦ƒƒ†‚ãÿ4{€¸è~ÿ~4}Z|~{ÿ²zúyayãxÿ‡xCxxùwýÞW –wcw%wßévºvŸ×ÐÂvÿ wuwôwˆxÿ#y¹yCzÀzÿ){…{Ö{!|ÿb|£|ç|#}ÿU}‚}}¬}ÿ¨}›}…}l}w[}Qà[}mÿÐÿž}«}²}®}÷£}Š# c}T}ýY# —}Ô}~ÿr~É~(‚÷Ò"ñ€º€ u`!P}°Ý‚=‰ȃëƒñƒÙ]€ýk£ÐÒ‚‚`‚ÿF‚C‚U‚s‚ý“ƒÁ‚¾‚¢‚ÿv‚9‚ù¼ÿ†bNX÷l‘àâ‚‚‚‚í5Pÿ„Bþ€´€ÿr€7€€Öÿ±–uXÿ4î~È~ý¤ ]~G~;~ÿ2~<~N~o~ýž«€(èßV€Ì€D3P7‚÷§‚»ð˃!„ÿk„¶„ö„7…ÿv…ª…ä…†wQ†‹S°‡9-Àߟ‡Â‡Ôð¼‡ÿ™‡k‡1‡ü†Ć”†`†)Ðõ™Oð³ŸÐWƒˆ‚ÿ¥€§£~ÿ}™|‹{zÿpy[xGw3vÿ&u*tAsyrÿÐqSq÷p¾pÿ©p¤p°pÇpÿápõp q(qßKq|qîrXstÿtïU ÿèwÛxÉy¬zÿ‰{[|/}~¿ã~䀄à‚ý1—£„B…Ñ…ÿQ†¾†‡y‡ÿʇˆiˆµˆÿ ‰[‰¯‰ŠýB£0ŒŠ‚ŠXŠÿŠŠ‰îˆ8ˆýu· Õ……W„ªƒ ƒ{‚þÙ€w6ð`›€!`ÿ±€Ý€LÝ•AP7‚”m kƒ÷ÞƒQ›Ð…h…ÿ©…Î…å…ç…ߨ…À… S€=……°„K„Ö‡ÿ·‚‚c¶€ÿ€bÈ~>~ÿÁ}P}ò|œ|ßQ||Ú‡{ÿe{I{6{{õ ç0ç#зz¨zÿ“zŒz’z£zÿÉzûz?{{}çÑ`›|í|1 à}q«T}'}ä1Ðÿ0|È{\{îz߃z"zÇÓ/yÿðxÂxŸxxßfxGx2ÅÐxÿñwïwöwxý=¡ÀÖx?yÂyß\z{àc0Ñ}ÿö~)€i§‚ÿÖƒó„ì…Ćÿz‡ ˆ†ˆòˆÿN‰¡‰í‰/ŠßkДаÁ@ÄŠwоÅ@¸Šºõõªo`VÅð’‰ ‰ßwˆæ‡SM€u†ý([°Ò…²…¡…ÿ…q…]…C…×0…‡ÐúÑP®„ÿn„„­ƒ/ƒÿ§‚‚ÿ”€$€¶NWæ~}°)àýÿ0ý‚mÀ<|||ýè…€¥{{f{ÿO{H{J{Q{ß_{l{qsV{ÿ.{òz¥zAzýÓÕÃx+xw÷ðv]}PkuuÿåtÉtÄtÔtßëtu30!uÿuuìtÛtÿÊtÃtÅtØtßu:u’·°‚vÿ#wÑw”xXyÿzÔzˆ{-|ÿÆ|\}ó}“~ÿ7𶀈ýfÇP/„… †ÿ‡î‡ãˆÏ‰ÿ´Šˆ‹IŒóŒÿ€øRŽœŽÿÕŽÿŽ$8ÿFD5ÿÚŽ˜ŽKŽôßCë ÀSŒÿŒÐ‹•‹`‹÷3‹ Ÿ0ÕŠÇŠ÷²Š–±@<Šî‰ÿ‰ ‰žˆˆÿˆ‡õ†i†Ü…wX…Ó¯ÒƒVi\‚ÛQ·IÀÿD^~X}0|ÿëzŽy)xÈvÿuu7tsrÿLqœppoÿ&oÑn„n=nÿøm½mŠm`mÿGm;mDmemÿ—mÞm3n•nÿo|oûo†p¿!qÐq–r³Àtÿ™uÍvxsyÿÓz/|†}Ð~€#,‚!•÷°„RK°I†¦†÷ê†-çP¤‡â‡ÿ&ˆbˆ–ˆ¾ˆÿ͈±ˆrˆˆÿx‡É††3…ßd„›ƒôgàè™_Az¡yýxQxý çpHv°u)uÿÀtstKt?tÿLtwt³tuÿ`uÑuMvÙvÿw4xùxËyߨz„{^•€ù}ÿ¸~bý‰€wj?@ó¹ßݘ:½\€ýð#PFø~ô~ £`ÿÑ~~6~ÿÒ}h}}·|ÿƒ|p|€|¸|×}•-°Þ1°e€Ý9k Ý‚¬Û°A…ÿü…²†\‡ò‡ÿˆˆ‰Ž‰ Šÿ‹Š‹‹õ‹ÿfŒÆŒNýdpFÍŒÿzŒŒÄ‹r‹ß"‹ÌŠ|YÐÀ‰ÿR‰ÝˆTˆÁ‡ÿ(‡‰†è…G…}¯óP‚ƒ÷‚aqÿ(y€»ì~ÿ~(}7|J{ÿ]zxyžxÏwÿ wUv­uuÿƒtÿs˜sDsÿsðrër sÿ9sƒsÛs;tÿ tuiuÇuÿvlvµvùvÿ8w~wÇw$xÿ’xy²ybzU¿ž…PÞ‹P¡÷ßÔ~Â~ŸÏàB~~ë}Í}·ÿ }¢}­}¾}ÿÚ}~,~\~ýŽ1ã~ 1ÿQ|¤Ìÿú(€K€k€ß}€‡€‚ßpn€ýdépq€Š€¯€w߀y„¿A@ÿB‚Ђ܂7ƒÝ˜™U„°Ð=…ßu…¤…ÓG0U†ÿ¨†‡‘‡ ˆÿ¸ˆS‰ñ‰Šÿ‹ž‹'Œ²Œÿ;ÏeŽÿ0³‘ÿi‘‡‘t‘3‘ÿÀ$f”Žÿ²ÉŒà‹üŠÿŠ:‰Uˆe‡ÿi†V…1„ù‚ÿ²^€£}ÿA|ãz†y/xÿØv”uRt$sÿrþpp4oÿqn¾m m‹lÿlk)kØjÿœj{jxj‘jÿÉjk…k lÿ³lqmFnFoÿVp‡qÃr tÿOu‰v­w²xÿ–yUzéz^{w´{í_ 7|SÃ`ÿ”|Á|}W}×½}3ÃÀ7“P5€ý¦õ0jÀ ‚ÿ†‚ü‚ƒ„ÿ±„V…û…•†ÿ)‡­‡"ˆ‹ˆÿìˆK‰¤‰ø‰ÿLŠ™ŠãŠ‹ÿ[‹‹º‹æ‹÷Œ3% vŒ‰Œ]˜ À—Œ‹ Àe% ÿ>Œ-ŒŒŒ÷ã‹´p‹¯Šÿ,Š™‰öˆEˆÿ•‡à†5†”…ÿ„~„ „©ÃPÿƒµ‚W‚êÿe€ €8ÿT~a}r|„{ÿ©zßy'yxÿ xŸwKwwÿÓv®vvzvõp{pt‡À­vívýAÉ0Dxëx§y÷oz9PÅ|q}} óÿ~WÇÀÝâÙàÖ©%@ ýÆÃpñ}} }Õ˜[¦{³C`Öyÿty yØx˜xÿbx3xüwÃwÿ„wDw wãv÷ÇvÆk` wOwšwãw.xm›ÿÇxíxy@yzyÅyz‚ß0ßg{ß{aë0“}ÿC~ åÍ€ÿ»«‚ŠƒY„ÿ…­…3†¢†ÿ‡]‡´‡ˆÿlˆÕˆ>‰®‰ÿ(ЍŠ1‹Â‹ß^ŒþŒ¨ ïŽÿ„ {Ò÷‘NI€‘¥‘ÿ³‘¼‘¹‘ª‘ÿ‹‘U‘‘‹ÿøCjŽtÿ^Œ1‹÷‰±ˆÿk‡$†æ„«ƒß‚X/q€Ï}ÿ|>{åy‹xÿ8wöuÕtàsÿs”rŠ…ŠÉŠw ‹MÀå‹;ÀÿæŒ0i‘ÿ¡¢“oÿ<ñŒ”ŒŒÿp‹Š¨‰ˆÿ6‡Ñ…\„å‚ÿv€È~—}ÿ…|{¸zzÿty y½xxýz `xIxxÿáww5wâvÿšvuvv»v}(…pxlyYPÿ0|}Ø}~ÿ;Ô]€à€_WÉ;-03ý0ÿO„ì„…,†ÿº†<‡‡æ‡ˆ'ˆ1ˆ.1Àÿ3ˆ7ˆ?ˆ9ˆÿ"ˆú‡«‡6‡÷ž†å•Ð+„6ƒÿ=‚@D€Hß?~/}q ·yÿx?wvÈtÿ˜spr^qWpÿfoŒnÏm*mÿ®lMllþkÿl)l^l£lÿîl7m‚mÐmÿ#n…nþn•oÿZpTqƒrñsÿu_wSyQ{ÿ\}XGƒÿÉ„d†Ø‡@‰ÿ’ŠË‹úŒŽÿ æ›!‘ÿz‘§‘¬‘‰‘ÿL‘‘®Nÿî&¼ŽÿDŽÄ6Œÿù‹R‹¥Šú‰ÿW‰¶ˆˆ‡_æ†P†°“ÐtY /ƒ‡‚éPMPÝ4CEã½K~ÿ~ÿ}ý}~7~v~Ã~ÑpßÛ0€yñpЀՀȀ¡€s©àÿü½†Oÿá~£~Z~ÿ~¤}6}Ä|÷W|ïã@`{F{ÿN{|{Ê{6|ÿ¼|M}ñ}Š~ÿ$ª€z€ÿ»€å€÷€ü€×ô€é ÀÜ}Ðù€÷3c n{uvGà0ãð¡€J`÷™H/`Ö~®~׈~aÉàøàK}õßõÐÙå@ÎzQzÿãyŒyFy yÿäxÅx§x‡xÿZx#xàw–wÿ6wßvvGvÿvýuv%vÿivÃv2w§wÿxŽxôxGyÿ{y¦yµy½y}» °Àyáyë@ÿ&{õ{ü|3~ÿŒø€i‚ʃÿ…'†‡Á‡ÿCˆšˆÖˆöˆÿ‰%‰7‰H‰Y‰b‰j‰g?àý]=à\‰l‰‰‰ÿ±‰Û‰Š0ŠÿGŠJŠ5ŠŠwljr¢ˆ2#pÿH‡ß†t††ÿ¸…j…&…ì„ÿ»„“„m„@„ýY ŽƒHƒý‚÷¹‚‚0X‚m‚w›‚âû0žƒ@ÿ¥„Ü„ù„ü„ÿ脺„}„%„ÿÃXƒç‚s‚ß‚˜.#`k€w €®Ïpë~„Ðÿ°}G}Ù|k|ÿ|Š{ {‹zzlyÓx;K`w„vv¥ÿ²tItásysÿs¸rir$rÿùqÜqÍqÊq}Ò ðâqàqÛ³ ÷Ãq¾ ðîq+rˆrþrs4Ÿÿ¤u`vwÙwÿ–xYy)z{ÿò{ï|ý}!L€±‚ÛÏõ[0Êé`1‰Ç‰ÿNŠÎŠJ‹Î‹ÿUŒáŒw Žÿ‘ŽzÊÿçÿªXðŽ}ŽúqåŒUpÿ6‹®Š(Ф‰ÿ‰‡ˆÞ‡'‡ÿJ†K…4„ƒÿÉ€aE~A}`|™{çqPÿÇyJyßxŠxÿLx,x/x\xÿ¯x"y©yDzÿêz‰{'|¶|ÿ?}Æ}L~Í~JÉG€Á™PÝ‚G`õr»àq`N‚<‚ÿ!‚ ‚úìÿÛξ¡ÿ~I µ€ýV`Š%Ë~÷|~@Apò}Ù}ýλp·}¨}Œ}ÿf}0}è|’|÷%|¶aÐÙzwzÿ2zúyÜy×y}ßõ@zz Yß"z)z5ÇÐzÿÅz{t{Õ{ÿ9|–|ð|@}ÿ‰}Ê}~H~_…~Á~©Ð‰ À÷€p9Ðoý¼A@/‚R‚f‚ýe_ N‚@‚6‚ÿ.‚)‚'‚$‚ÿ‚‚üëýÔûp¶¯©õ§–ùpmR×8,ÁàF0½ÿ‚~‚Þ‚@ƒÿ—ƒØƒ„'„÷A„P@k„z„W‹„¡¯àÓ©PþA0ÿ… …þ„ë„΄ª„‡„dëÿ „„äƒÃƒÿ¢ƒ~ƒNƒƒÿÇ‚t‚‚¾÷Xõ9@&€²÷8µÐn}¯|ÿç{{Dz€yÿÏxž~ ~}ˆ[P¥|:|Éã0ÿãzfzçycyæxnxôw‰©0ÿ·vXvÿu¬uÿ^uuÞt¬tûƒtÅ!‡t¶tûÿtVuÉuIvÒ¿v\wÜwGÕÐòÿx+yVyy«ÿyây+zŠzþÿzŠ{#|Ê|tþP¶~EÇBÿ€·€/´Kû‚û#à­„«…½ÿ†ß‡‰2Š^ÿ‹‹Œ»ìŽÿM‘u’“ÿ”p•(–µ–ÿ—A—G—&—åÿ–€––`•—ÿ”£“’3‘µÿŽfŒ«ŠëÿˆB‡²…7„Úÿ‚“U€#õÿ}¿|Ž{\z*ÿyxîvèuúÿt$tdsºr"ÿr¢q5qØpžÿpnpepyp«ÿpùphqïqÿr5säs–tFÿuêuˆv$w¹ÿwMxâxwy¿z¤z2{·Õð‹¿|â|)}c9°Ûÿ}~]~¦~îÿ~/b…»‡)P-îMÐNÿ~õ}–}7}Ø¿|~|&|àg–ÿ{›{¶{ô{Eÿ|¡| }€}öþo@ð~oþ”þ™PÈY‚Û‚Hÿƒ™ƒÏƒèƒòïƒïƒåo°èƒô¿ƒ„„!³àÿ„„ëƒÉƒ«ÿƒ•ƒ}ƒsƒu¾=@}ƒzƒqÓPPþЃõ‚á‚Òë‚ËŸPÒQ@ô‚þÉPZƒƒ°ƒç¯ƒ „_¥à퀔¿…ë…J†³€ƒÿ‡é‡Jˆ¡ˆõïˆ?‰w¿‰Î¯‰Ñ‰·OàCpbÿˆÄ‡‡H†iþÁ@•ƒ­‚ÇãîÇàB×@'}Žÿ||‡{{·ÿzezzÐy‹ïy?yð[>xÛ¿wyww¾{p1þñàòuèuîuÿvv+v7v:ÿv.vvãu¨ÿucuuÃtnÿt#täs³s–ûs‰ P»sïs8ÿtˆtÝt2u…¿uÒuvZã àÿv0w”wx¬ÿxfyBz7{Gÿ|i}š~Ó ÿA‚ƒ¼„ÿÿ…?‡†ˆÊ‰ÿ‹QŒ„¡Ž ÿx"‘Ÿ‘çï‘ý‘í b‘ÿÿ’.Ìtÿ+쎳ŽwÿŽ5ŽåƒÿtŒÇ‹‹9ÿŠb‰ˆÀ‡ÿ‡]†¿…5…¶ÿ„6„±ƒƒwÿ‚»î€€.ûU• Ê|*|¡ÿ{1{Ôz†zC¿zzÄy…»ð ÿyÐx–x[xïxÇwmÿžv,ÿv¼uRuöt®¿t|tetià º¿tuvu£zÿwex]ykzt¿{r|a}.—bÿÍ€c€¬¿€ï€D¨õ€¤ÿ‚2ƒËƒi„ ÿ…ª…L†Ý†bÿ‡Ê‡ˆ%ˆ ‡*e€}…uÿ„Rƒ.‚ ¿€"\~¶9Íÿ|…|N|-|òÛàöó0Xaü{û{ÿú{÷{æ{Ð{ÿª{€{S{#{ÿþzåzÞzízw {:k¬{Ú3 ß||½@ð{}ã`í{ |/YÐÿ‹|Ã|ü|B}ß}ï}b@˜ÿS€-‚ƒýƒô„î…ÝUðÿµˆ—‰rŠI‹ÿ ŒóŒÈŽPû“ePÿ‘‘œ‘†‘O‘ÿ ‘ºhÿÓ’K÷ŽÿŽŽŽOxŒÿo‹EŠùˆ™‡ÿ-†º„Hƒãß„€:ýã0Ë{ÿÐzðyyYxÿ¤wîv9vzu÷³tâap"r‡¼†<†Æ…ßZ…ñ„ˆ´ƒ÷Aƒ¾©Šà€ß%€b—·@}ÿ;|€{Êz%z÷‡yô ñw~wÿw¯vUvúuß«udu½ Œtÿ@tès†ssÿ®rCràqqÿ\qCqWq”qÿüq’rGstÿ u vwxÿyzÔz{ÿ(|¦| }V}}Ÿ¿0"~o~ÌÀ÷·H‡Ð†,‚ßׂwƒ÷…ÿ{…Ä…î…ñ…ÿØ…›…K…ä„ÿw„„›ƒEƒ_ÿ‚Ï‚¸k°¾S@ÿ킃ƒƒƒƒà‚«—àÿ$‚׉Aÿÿ€Ë€«€™€Ýœ Ë€úÇ‚©ÿï0‚x‚Á‚ß ƒYƒ¬çg„ÿÍ„6…§…†ÿŒ†‡|‡þ‡ÿ‚ˆ ‰’‰Šÿ“Š‹i‹´‹ÿ苌 ŒŒÿò‹Ó‹®‹€‹¿K‹ ‹µŠ^ð‰ÿ=‰Ÿˆð‡A‡ÿ–†î…Q…³„ÿ„gƒ©‚Öÿé€âÐ~®}ÿŒ|l{cziyÿˆxÁww_vÿÁu0uªt-tßµsJsæ%ð0rÿÚq€q0qápÿ‘pGp pÈoÿ•obo4ooÿØn­nn\nÿ?n.n,n6nÿOn€n¹n oÿvoðoŽp@qÿrs t,uÿXv‚w§xÅyÿÓzÔ{É|º}ÿ¬~¡Ÿ€¥ÿ·‚Ƀ鄆ÿ ‡;ˆM‰YŠÿ_‹YŒCŽÿÞŽ‰ÿñ?‘}‘¸‘ÿì‘’O’’ÿ²’Ü’“"“ÿ2“>“;“*“ÿ “Ø’’2’ÿº‘&‘yºÿÝŽóøŒö‹ÿïŠë‰éˆï‡ÿ‡†1…W„÷}ƒ« E€ÿ€Â~~i}ÿÒ|?|²{${ÿˆzßyyNxÿlwv’u±tÿçs9s¬r?rÿëqªquqLqÿ!qüpäpãpÿþp~°~ÿpÈ%€„€wã€N»,‚’ÿÿAƒ…ƒÀƒîƒß„>„[ó•„õ¤Ý²Ý¨„™„Œ„~„e„N³àý÷g@Sƒè‚c‚ÿÕ7‹€ÑÿN~}¨|ÿÐ{üz0zryÿÍxKxêw°wÿœw¢wÀwîwÿ#x_x›xÔx×yR€Ø‚àz}F±07|½|Yu×·~r½•j‚ÿƒŠƒöƒO„ÿ”„Ì„ö„…ß>…_……E Ì…ÿï…†5†X†ÿ~†Ÿ†Ã†æ†ÿ‡)‡X‡Œ‡ÿˇˆtˆÝˆÿO‰Å‰5Š‘Šÿ抋=‹:‹ÿ‹èŠŸŠBŠÿÕ‰^‰ÜˆOˆÿÇ-‡œ† †ÿƒ……„"„ÿ¾ƒbƒú‚”‚ÿ"‚¤—€ÿ€ƒ š~ÿ9~ä}š}O}ßþ|©|E?ÀV{ÿÏzJzÆyQyýíÇPNxxðwÿÌw¶w˜w|wWw0wûv¸Ý@ÿvµuMuátÿyttÅs‡sÿ_sLsYs|s÷¶s Å ñtƒußvÆvvùÐÄxÿ`yäy_zÃzÿ{Y{˜{Ï{ÿ|L|˜|ì|ÿD}¦}~i~ßÏ~AÀÉè€ÿš[‚'ƒüƒÿ΄˜…Q†ù†ÿ‰‡ˆvˆÜˆß7‰‰âÃÀŠŠÿ׊‹V‹‡‹ý¡m ¯‹‹c‹ÿ‹ÊŠ^Šä‰ÿW‰¶ˆ ˆV‡ÿš†Ï……F„ÿ‹ƒá‚H‚ÑßxD0Ï[u ›Ž‚ºÙ€ßö‚ƒ M@ƒÿƒ!ƒ+ƒ2ƒ×7ƒ6ààË‚ÿ‡‚5‚Ðhߟ€E ºÿƒNØ~ÿ†~~›}}ßR|”{ÉK(yÿ^xšwêvGvÿ»uFuçt¢tptNt=t3u0 tttPÿAtlt©tuÿau×u\vövÿžwYx5y*zÿ@{i|§}î~ÿ'€Sd‚Vƒÿ-„ç„•…9†ýÚ£Ð6ˆàˆ…‰ÿЇŠÑŠøŠÿûŠßвŠ{ŠÿHŠ Š ŠŠÿŠŠ8ŠGŠßKŠ<Š×Àn‰ÿìˆIˆŒ‡³†É…Ù„æƒóÿ4b€¤í~ÿB~”}æ|8|ýˆÐzPy‹xýËÙ@fvÄu8uß½tUtIБsÿfsFs(ssÿss;s‚sÿæsmtuçuÿÒvÃwÂx¿yÿ»z¸{µ|·}ÿ¿~Õ÷€*‚ÿ]ƒ“„Ç…ë†ÿˆýˆå‰±Šÿh‹ŒŒŒùŒÿV–ÃÙàÖ¸’™pý%‰ðžŒNŒñ‹ßˆ‹‹ž¹à™‰÷‰-`Œ‡‡w£†0“PL…Ñí÷ƒ#ŸP¼ë€ÿ€ ~ü|ÿÝ{´zŒygxÿKwHvVuztßÁs"s¡øqÿÅq©q q¯qÿÎqrHr™rÿôrSs¨sùsÿ:tvt¦tÔtþt8u†uâý ÿÖv_wëwqxÿíx^yÊy3zÿ£z{´{Y|ÿ}Ø}¨~lÿ-€â€ƒ‚÷°‚N#@®„…ÿb†R‡QˆP‰ÿJŠ5‹ŒáŒÿªcŽÅÿl‘”‘ ’÷]’Y°i’’ÿ“‘ó0SÿhŽmkŒb‹ÿXŠW‰Zˆh‡ß|†Ÿ…Ë%À*ƒÿZ‚ƒª€Ëýë“ 8}j|±{ýŸ Ìy/y‘x÷éw:¡°ÀuuPt¯ss¥­°ÿçqq_q/qÿqq"qaqÿÍq[rsésÿ×tÍuÀv­wÿxcy.zîzÿ°{f|}Ä}ÿd~÷~yôÿ_€É€2›‚{‚é‚R; õûý€gE£„Á„ßá„…*íh…ÿw…v…g…G…ÿ…ï„„„÷^„+ù©ƒWƒýðÛöjÙ€÷B€¯ •~ ~÷‡}»@|´{]{{ëzÛkÀÿ{D{ { |ÿ¾||}P~6ÿ+€ ‚å‚÷¯ƒcÍ …1†ÿ½†H‡Ï‡WˆÿшA‰œ‰ã‰×Š5ÅâM·à;Šÿ/ŠŠæ‰¬‰ßa‰ ‰®Óàá‡÷z‡ãÀ!†—…õò™PbŸP~v€ÿfV~@}/|ÿ{zyxÿ!wMv—uuÿ¢t_t:t0t8tDtTtaãPýwP¡tÃtôtß5u{uÌ_ÐqvÿÁvwqwÓwÿ>x»xOyõyÝ«ùPG|$/€ß~ÿ®s€¢ÿ‚B‚`‚U‚ý8åpàÉÂ÷å!3 ë‚eƒwÙƒAÀË„èq@ýÜ{ „„A„ñƒõPœ‡ „÷€ÿy€ €ºŠÿjiktÿ~}xhÿ^\`uÿ—Åû0€ÿg€—€Á€å€ÿ ,X‡ß¶ë b‚ßv‚Š‚˜÷ß‚ÿ%ƒ„ƒþƒ–„ÿ>…ô…²†p‡ÿ&ˆËˆ^‰Ù‰ÿ:ŠŠ®Š»Š°ŠˆŠ?ŠÚÙÀÿȈˆZ‡Š†ÿ³…Ü„„.ƒÿe‚¯h€ÿÔFº~!~ýa€c|Ï{M{ÿázˆzBzzÿôyÜyÈy¶yÿ¢yŠyty^yLy=y1y$ €ÿyÚx²x…xÿSx&xüwßwÿÒwÈwÉwÎwÿÕwÞwæwôw÷ x1k»x"yÿ—yz¨z4{߸{=|³÷‘}ø}^~Å~é°÷­ÚÏñÞ÷¸’K H3w1Eé°«ù­`ý´ |Ñ$‚g‚œ‚½‚ÉW@ÿ·‚š‚q‚F‚ÿ‚ùáÜßö#‚hû$ƒß—ƒ „‚‘Àk…Ú…S†Ì†J·ÀÿRˆÔˆK‰¶‰÷ŠV± ¡ŠªŠß¥Š‰Š]Ë้ÿD‰¯ˆ ˆN‡ÿ‘†Õ……{„ÿçƒeƒí‚y‚ÿ‚|ê€K€}žéà6~}}É-ÿk{Çzz‚yýìÉPÞwnwwßÅv“vn!PZvÿivŠv¹vþvÿRw·w&xšxÿyyíyLzõ­€t‘`_|Þ|ÿe}î}n~é~ÿW¾)€’€ÕñÐ*àuÀµ„ÿ;…¥…û…7†ÿ^†|††£†ÿ·†È†Õ†ß†ÿá†é†è†à†WÞ†Üu@Ó§0ºa@ÿy†I††Ë…ÿ‚…-…É„R„ýÊ9 V‚qq€ÿ[7~ }Þ{ÿ¿z¥yœx£w³vÜuuW³ ÿ*s·rNrþqÿ±qnq(qàpÿ˜pUppÝoÿ½o±oÆoîoÿ9pžpq­qÿErërŽs.tÿÌtbuòu}vÿ w§wOxyÿîyäzò{}ÿX~§u‚ÿùƒ•…J‡‰ÿûŠçŒÖ޵ÿt’”d•‡–ÿt—5˜Ô˜]™ÿÙ™UšÒšK›ÿÄ›0œŽœÖœÿýœÄœÿiœè›A›pšÿy™]˜—Æ•ÿP”Ä’/‘ˆÿÕŒNŠzˆÿ•†¥„­‚¯€ÿŸ~|ozLxÿ%vtñqóoÿn\lÙj‡iÿihug®ffÿwee«dkdÿMdUddÔdÿGeÚeyf(gÿÕg‰h@iúiÿ¾j“k{lsmÿznˆo¤p¿qÿÚrùs!uRvÿwÕxz_{ÿ‘|¦}“~`€ˆ€õ€W{ ÿ‚ƒ‚ñ‚cƒÿσ5„’„æ„ÿ7…~…Ç… †÷P†e@ü†.‡Z‡‡Î‡»ÀâˆW‰Ô‰D#óŠ(‹B‹I`ÿ7‹&‹‹öŠ÷ÜŠ¶Y kŠ@ŠÝ"ËàŠ#ÕÀZŠ÷mŠnuŠ»‰ÿF‰¾ˆ2ˆŸ‡ÿ‡‹† †‰…ÿ…£„<„èƒÿ¦ƒyƒhƒgƒ÷vƒ†‡ÀyƒGƒßò‚„‚ý#àÌ€ß.€Y~ÿ¤}.}±|5|ÿ»{B{ÌzXzýå÷ yŽx#xÿÂwsw7wwÿ#wHw‡wÛwÿ5xƒxËxûxý €yÛx©xwpx0m­w`qÿÆv}v=v vÿíuôuvjvÿåv‡wIx(yÿz{|}ýG€Ô¥€mÿ.‚ꂃJ„ÿå„s…è…D†÷‹†»§0Ɇª†ÿv†.†Ì…T…„'„‚ƒØàÿ  ·€_€ÿ€Ø[ÿÊ~~F~ÿ ~~#~P~ÿ”~ë~G õösp‹% C‚¸îOÿ8‚+‚‚ñÿÊšn<ÿ Õ€›€c€}/E þ€Ampß¡BÕ€oƒÿòƒV„¢„ׄÿò„ÿ„…û„÷ô„ï+ õ„…_…<…iYßG ýQÿ`µ†Û†ø†ÿ‡‡‡ ‡ÿÞ†˜†2†¢…ÿø„8„fƒ–‚ÿ͆€€ÿ¨U¸~ÿ]~ù}“}#}ÿ³|H|â{Œ{ÿ7{æzz6zÿÊyKyÀx(xÿ‹wèvKvºuW3uÀ½…Ï€ÿßsÿs+t]tÿ–tÑtuXu÷ªuÇ`w“wÿ.xÒxxy#z_Èzj{ ;0Z…Ðÿ²~Zý—€Ý$p‚uý,ƒƒƒÛƒ,„€Àÿ…I…€…­…Ý…ý…"†>­pÿU†K†8††Ýûi€Î…Õ™ +†ÿp†Â†‡U‡÷„‡¢‘€™‡‡ÿa‡@‡‡‡ÿà†¹†‰†G†ú…¢…M…õëÿX„„Þƒ¨ƒÿqƒ=ƒƒÌ‚ÿ‚Y‚%‚ðÿ¾„Hÿ¹€i€€Õõ•Y E_0$ßü~Ú~ªÁ.~ÿì}°}y}Q}ÿ0}}ô|Ð|ÿ›|^||Ä{ÿy{9{ {îzÿäzïzýz{÷&{0{{ÿ×z¤zlz,zÿéy°yzyIyÿ'yyy yyy!y9wîxÅ[Àux\Mÿ…xÐxFyáyÿŸzs{\|P}ß=~,‘м}‡„Ô„—ŸÐ÷ ‡ºcàˆV‰¯‰ð‰Š0y8Š2Š-Š()`÷Šù`›‰L‰ÿíˆ}ˆý‡p‡÷݆?aö„C„߃ƒ³‚ÚA €ÿ)~C}t|ÿ·{{”z2zçy½y±y»í ÿzYz¬z{ÿj{Ç{|q|ÿ»|÷|-}^}ÿ†}¯}Ö}ü}ÿ+~^~•~Ø~ß!{Ýл€÷0¥×P‚Þ‚÷5ƒxW`ăӃýɹ‚&ƒÇ‚W‚ßÒF­E rÚ~D~³}+çpýCëp{T{+{ÿ{{{/{ÿI{a{|{”{ß­{Ñ{{б|ÿ,}Â}i~ ßÖ€€cp‚ÿL‚€‚™‚¡‚ÿ—‚ˆ‚n‚S‚ÿ6‚‚ ‚ÿuáààH‚PãÐý+_p¤Lï€ýœ!p:€;€X€ßŽ€Ï€ nÝ{epX2ƒ°í€ýØÓÄ€À€¸€}£ï°T€€ÏU ý(5àˆ~:~ò}ÿ®}r}M}4}ß>}a}¤…Ðz~ÿþ~~ø^€©€Þ€ñ€÷‘ÐýÑk0˜€z€^€ÿC€(€€ÿßú€)àw€÷³€êM Ð÷Gý¥ó R¯€ÿŠ€§R‚ÿƒÒƒ¦„~…ÿW†(‡ä‡ˆÿ‰Š‰Ó‰ù‰Šó‰Ö‰¸­Ðj‰I‰*‰ÑàÿÁˆ’ˆXˆˆÿÚ‡£‡t‡I‡ÿ*‡ ‡ì†À†ÿ„†:†×…`…ÿÔ„;„šƒö‚ßX‚¿*'à&€ÿ´O÷~¤~d~0~~ßÇ߯}¡}œ°…}÷t}V7 î| |÷A|ÎÐázuz÷zØÑ»yÝy÷zy[{Ô{ÿR|Ê|@}¨}ÿ ~g~½~Wœà)àý]opJ€€ÃÿM¿~~m}ÿº| |_{¼zÿ(zŸy y«x?xãw•w_‡×3wBÁ`‘+ÐxõF 0É!@dy¿yÿ(z›z{{ÿñ{X|²|}ÿK}”}×}'~~~Û~B¨«À߆€ƒUp€ƒQ„,…u@ÿ›‡DˆÐˆ<‰ÿ‰ì‰9ŠŽŠÿôŠe‹Þ‹cŒÿâŒ^ÅŽÿCŽRŽ@Ž Žÿ¬,ŒÓ‹ÿ‹5Ši‰ ˆýî-À¿†@†Ã…K…Ê„?„­à_Œ‚‚‘ëÐàC@×I€ïU ò3 }ÿª|Ó{ÿz‚ìG@˜€ÿ€Z«~õ}ß<}‹|ÜC yzÿÈyy`x¯wÿwovæupuý»Ott½sÿ†ses^s‚sÿÐsMtÿtÙuÿØvðwy=zÿ\{v|}}t~ÿb>€ Ëv‚ ƒ‹ƒìáP÷]„h³€6„„ÿă‚ƒDƒƒUå}2°´•0¾K@ßÓ‚æ‚[°fƒß§ƒâƒ3 H„ß5„„¨½€Æ‚M‚Ï\éC ÿ€|Ü~+~ÿk}˜|Á{ðzÿ/zyyÖxOxÿÔwgww¯vßhv0vñð/vÿuvævwxÝwß‹wRw,`w}$ÙÀUwvw˜0ÿxMx§xyý˜¶zE{Ð{ýKC'}‡}ì}T~¿~/ªA@©€+­4ðÿ7ƒ´ƒ*„Ž„Ý„……èãPÿ„tƒÉ‚‚÷jѳÀÓdÝþ;p ~£‡°|÷|‡ÇzƒzÿWz-z zÞyw­yo3äx¢™Ðÿbxtx­xyÿ“y8zõz¿{ÿ|_})~î~ÿªe€Ø÷‚j# …ø…ÿÔ†©‡iˆ‰ÿ¡‰ŠfŠ¢ŠÿÌŠçŠöŠÿŠ÷‹ÿ9ÐÙŠ«ŠÿoŠ)ŠÏ‰r‰ÿ‰µˆkˆ'ˆÿ釭‡m‡ ‡¹†<†ž…ôAÀÿƒÓ‚:‚Âÿk.wú€ögÏ€¬ÿÐùc°¦¡W€€¶ï€ú€;5°’žþ‡Tÿ€€ÿ€qÔ~1~Œÿ}é|G|¢{ôÿz:zpyšxºÿwÒvêuuEÿt’sûr‡r2ÿrøqÙqÑqÜÿqõq!r\r¤ÿrûrYsÆs<ÿt¿tOuðu¤ÿvkwHx=y?ÿzM{e|y}‚û~ze>‚¹ë‚`“ ‡‘p`…¨û…àW@††¾k †(†W_@Õÿ†%‡x‡Ê‡ïˆUˆˆï่·ÿˆ˜ˆdˆˆ¹ï‡H‡Ð­pÐ…[ÿ…â„w„„§¿ƒAƒÚ‚v‹ ®þï¶€s€5ÿ€ì¢DÛï~a~Ú…°¾|2ÿ|µ{C{ízªÿz}zsz„z³ïzÿzkûÀ’|Gÿ}~É~’P¿€™s »þS€Ã‚‘‚<‚ÑþáÐÝ€h€ €¿ÿŽ‚–þ‘ÅÜäéÿæÙÏÆûÀ'0ÁÃÍ¿Õßõe,¯€V€ƒÉ ðK€X9°‚Jþß0§‚Ñ‚ù‚ÿƒ!ƒ"ƒƒôÿ‚Æ‚Š‚=‚ãÿz‘€ ¿€…]Àþåp½|_||°¿{`{${ò·°Íÿzßz{1{f¿{›{Å{äѰõÿ{ø{ú{ |1û|r—ÀC}Ñ}sÿ~Ê{€*ÿÍo‚ ƒ›ûƒ%‹p …k…¹ÿ…ú…)†R†l†ž£€Ò†íÿ†‡‡‡þþ³p™†5†¶…ÿ…i„£ƒÏ‚øþðL€‰Ë~"ÿ~„}ð|b|Þÿ{U{Éz=z¦®CjxÉ»šóð¡ïuNu +u`ÿu°uvvöÿvnwæwfxóÿxy;zþzÐÿ{©|{}<~Üë~WmàÓ!0Ǥ¯ˆwÕ g .ÿ€—€œ*ªKõ°[Z=Iþ‰€2‡ž‡ˆcÿˆ¯ˆðˆ‰ÿ‰‰èˆ¤ˆOÿˆñ‡Ž‡.‡×¾/K††Úc kÿ…%…Ø„|„ï„©ƒ:[‚îÿ‡,Ó€ï€6€íïj*û~`~Eÿ~,~!~~'þûE~\~p~„ÿ~˜~©~®~³ÿ~¢~‰~c~/¾w°Á}™}ƒP¡ÿ}Ú}2~™~ûrg /€v€µû€ìßÐ\áû) à°‚í‚%¿ƒZƒˆƒºM°5ÿ„x„¹„î„ÿ…)……ò„¶ÿ„f„„±ƒXþa0…‚ ‚p²ÿ€ÌÀ~†}1ÿ|ÇzVyÞwqÿvuÅsŽreÿqVp\o‰nØÿmTmúlÒlÛÿlm^mÊmLÿnÞn{o!pÍÿpƒq>rþrÂÿstXu víÿv¶wƒxPyÿzúzÕ{¼|©ÿ}™~‘„€}ÿ|‚{ƒ|„†ÿ…Œ†”‡˜ˆ”ÿ‰€Šc‹2ŒìÿŒ™2Ž¿Ž>ÿ¾5¦ÿ‘‘ß‘3’tÿ’ž’¨’’Oÿ’ç‘c‘¼úÿ(NŽw¤ÿŒã‹1‹–ŠÿŠš‰.‰Ëˆlÿˆ ˆ©‡;‡Èï†P†Íc€Ä„D¿„уmƒÁ€™þ} O‚/‚ ‚ÝîpUñ°éFÿœ~Ý}}Nÿ|{¸zôy;ÿy–xx‘w<ÿwwîvñvþÝÀ~wÂwûw/ÿxXxgxkxVÿx/xúwÃw‚¾ÝÀwÏv–Ó`?¿vvÙu›#€ ÿu»tnt!tÝÿs¤sspsxÿs–sÎstvÿtât]uäunÿvww8xÓÿxpy z˜zÿ{“{þ{]|·û|yàß}V~ï¿~—Q€½à¾ÿ‚ƒP„…«þ{@Û†h‡ï‡sê‰@gÀ$ƒŠÿŠ_Š!ŠÄ‰X¯‰àˆa§w»pÎ†z1o†ÿ†š†¶†Ï†àÿ†ë†î†Ú†Áÿ†£†}†T†,îm é…ÏW­…ÿ…‹…t…T…2ÿ……Ì„“„Zï„)„úõ°°ƒ‘ûƒv-P:ƒƒý»‚ß%ໂÀàä¿‚ý‚ƒ‘ðí‚cc°ž;ëÞ« E 0͉ÿ8Ó~W~Å¿}"}v|ÃG oÿzÙyMyÐx[ÿxêwxw wœÿv-vÆuhuÿuÞt»t¯tÆÿtït2uˆuçÿuJv²vw^ÿwŸwÒwówÿxxx&x=ÿx]xxÙx8ÿyªy6zÙzï{P|"óØ~³ïŽ€Z  Ï‚oûƒÿ½Pí„N…¡ÿ…ì…*†`†ˆï†¦†·+pº†®êë0…/p{×0¦†Öÿ†‡?‡j‡{û‡f/À¾†)†m¿…˜„ºƒÛSPJÿª€$€»eÿ#õ~×~Ãï~Á~Ìé€ñ~ÿß~£ÿ~Q~à}i}ìþãû{œ{J{ º#µ³°†z~‡€ïz¿zùÛ¦{®)}Èmð(0¦ÿ€b ‚Ü‚‹ÿƒ2„ׄt… þ:‡Ð‡fˆ÷ÿˆ}‰ó‰VŠžÿŠÐŠäŠâŠÁûЉ‰Ú‰d‰ß¿ˆFˆ¦‡ÿu ¯¿… …g„È]0yþ¿ÿ€2€V|þ'Ó||b{¿þ)¢yyœxÿx›ww¬vJïvìu¡·p8uÿuûtçtÛtÔþ#ðtuJu‹ÿu×u)v†vâÿvLw½w:xÆûxfõzÛ{Íÿ|Í}Ó~×Ýÿ€Ò½‚—ƒdÿ„…Î…m†þÿ†Š‡ ˆˆêÿˆC‰‰‰¶‰Âÿ‰¯‰w‰‰¡ïˆˆm`/†¡û…,?À’„s„iï„p„†Íà¿„Õû„ä™Ú„º„Šÿ„Q„„°ƒY»ƒü=°C‚éñ N¾½ à€Â€² Ñþÿ %&ÿ¿€L€¯èÿ~~ }|÷ÿzïyèxîwþÿv vOuŒtàÿsGsÏror)ÿrróqr&ÿrbr¿r0s¶ÿsUtuÀu€ÿv?wx¹xnÿy!zÓz‹{Eë|aÀ}³àØx¿€‰ e0 þYp„£„)…³ÿ…0†«†$‡šÿ‡ˆ­ˆE‰òÿ‰ ŠU‹Œ¦ÿŒ@¼%Žyÿ޳ިŽÜŽÄÿŽŽŽ3Ž»$ÿzŒË‹‹{ÿŠñ‰v‰‰¯ÿˆGˆÐ‡:‡€ÿ†°…À„΃Öþ»@!g€ÊHþÙ o~~š}.ÿ}¹|D|Ï{Yÿ{èz‚z!zÑÿyŒyYy@y9ûyIïÀ‘yºyØïyéyâ¿ ‹yCëyôOlÑÀ'xÿx(x9xTxuÿx›xÅxÿxJÿy¤yz’zÿ{µ{W|÷|•û}0[€OÑJ»€­ï 7WãÐKþÉ쀰€q€7þq0ðèêôëµÀ!OÀ!€ï€öÔW@hÿÄ~]~â}^ÿ}Ê|*|{Õëz ÃÝp‡wÿ¿vŠv+vè  ¹ÿuÒuvpvðûvŒýðyßyÃÿz®{|’}‘ÿ~š€¢³ÿ‚ƃބó…ÿ‡ˆ"‰%Š"ÿ‹Œ÷ŒÒ¢ÿŽd¾^ÿ‘ô‘€’“|ÿ“ë“L” ”Þÿ”•#•!•ÿ•Ê”m”ì“Eÿ“k’Z‘§ÿŽ[‹Ÿ‰éÿ‡L†à„¤ƒ ÿ‚̆€óÿ`³~ê}ÿ}|{zõïxòwëñtòÿsñrïqöp÷ÿo o/nqmÊÿlAlÛkŒkVÿk7k.k9kUÿkŠkÑk-lšÿlmŸm3nËÿngopÉp–ÿqwrxs›tÜÿu-wxûyYÿ{£|Ò}Þ~Èÿ•€Iî‹ÿ‚,ƒÔƒ}„+ÿ…Û……† ‡¨ï‡#ˆ‚óà ‰:ÿ‰]‰{‰–‰©ÿ‰Ã‰Ú‰þ‰(ÿŠ\ŠŠêŠ=ÿ‹–‹ð‹EŒ•ÿŒÍŒùŒÿ쌮ŒY¿Œâ‹Q‹œ›éÿˆù‡ú†ý…ÿ…„ƒ5‚Pÿk€ˆ©~ο}ý|9|Ž©’ÿz;zýyÎy°¿y”yƒy|ÕÀ‰ºé ÊÇÐ1zh€Êÿzôz{6{Xÿ{{­{Ú{ÿ|A|h|†|š¿|Ÿ|œ|—Кÿ|©|½|Ö|ôÿ|}+}G}eÿ}ˆ}®}Ô}ÿ~0~U~r~}ë~yuàVã@7~=ÿ~X~…~Æ~û|0[€á€jë ÷ t¯€ò„¦þ†"‡e‡Š¾@ª‡¬‡¯aР‡c›@߆»†³%…¨Qp¤ÿƒƒx‚ÎûE÷š~À}ÿ}V|½{H{îþÙ’z…z‹z¢ÿz½zàz{=ÿ{o{¤{Û{ú @­ c}¹}ï~Y~±àÅ~Ïÿ~Ò~Ô~à~þÿ~,i²ûÿI€‡€Ã€õ¾C0T€®iÿ‚#‚2‚.‚ï‚óÁéhG¯2+Ã8°.ºð÷;àŽ€N-°ßþï}S&ùï~Ç~’ÁÐ,~¯~ä}Ò€ÍÏ`÷»}Ù@J~kõ@®¯~Ø~A`•0K¿€ª€eéÐÝþOÀå»nÿš€€’ÿp~×}>}¦ÿ||u{çzfïzðy‡· ÷xÇþGx†xŒx¦ÿxÍxyRy®ïyz“ëÀ¨{Hÿ|}Ù}Ë~áÿ\‚µƒÿ…H†g‡aˆ3ÿ‰Ö‰RгŠÿ‹D‹†‹¾‹øÿ‹#Œ@ŒPŒEÿŒ'Œò‹¢‹Cÿ‹ÈŠ9Š‘‰Æ¿ˆî‡ó†ç‡ÀÿƒÂ‚Öxï€ €Ä_@Œ‘ÿ˜§´¸ÿ»¶±Ÿÿ„c3ýþ]€}~3~ç}§ÿ}h}4}}úþõ  }(}P}wÿ}›}¯}³}û}q/ðÑ|w|!û|ÛóÀ–{™{³ÿ{Õ{û{!|F¿|f|‘|»õ Cû}¤¿Ð~ì~?ÿv€\ÿ¢~~x}Ðÿ|5|¡{#{ºÿz_zzêyÒ¿y¾y¹yÅ‹ðéÿy z2z]zŒ¿z¾zøz% @ÿ{ {·{Á{Æþ­ð¸{¯{®{¶þ¯ðâ{|-|[ÿ|‡|¸|ç|ÿ}C}x}²}óï}8~ƒÍÐ#zúP0Óó€`Õþ¯àæ‚~ƒ„¼»„ai ª†Lí`“ÿˆ=‰é‰žŠ`ÿ‹/ŒðçÿŽÜÛבÆï’¢“f±°’•æÿ•––•Kÿ•¡”À“³’ÿ‘,¹Ž0Ÿÿ‹û‰OˆŸ†çÿ„)ƒj­÷ÿ}A| z yÿw vt8sØÿq€p*oÝm¥ÿlŠkjÁi+ÿiËh¢h­hàÿh:i°i;jÖÿj}k@lmÿno9p€qáÿrKtÁu.w–ÿxèy%{J|Zÿ}Z~QH€A¿?‚HƒSõðmÿ†d‡Jˆ‰Æÿ‰TŠÓŠ5‹Žÿ‹â‹0Œ}ŒÊÿŒUŒ±ÿĽœ`ÿ•ŒŒ[ÿ‹Š«‰°ˆ§ÿ‡†w…d„Xÿƒ`‚x¡€Ôþg€C~r}š|ºÿ{ÒzßyúxÿxKw•vûuÿu uÜtµtžït¡t³%u7ÿuzu»uvEÿv‰vÊvw;ÿwqw¤wÞwûxh‡à7y¿ySÿzýz²{c|ú5ày=ÐÃf€ÿÆ’‚kƒUÿ„O…N†V‡QÿˆK‰;Š‹ñÿ‹¶Œq!ŽÀûŽIÙPX}ÿˆ{RÿÖy‹ÿŽóCsŒÿ‹†Ši‰1ˆÞÿ†{…„~‚ðÿ€\Ð}R|åÿz›yoxjw„ÿv¹uuat¹ÿsskr¿qÿqspæoso&ÿoönõnokÿoãopGq8ÿrDskt¦uó¿v>x~y´C@Óÿ|»}”~Zï€è€´QÀtƒ^û„Sµà=‡*ˆþõ`„Š‹ˆ‹Ðÿ‹ô‹÷‹Ö‹Ÿÿ‹R‹øŠšŠ8ÿŠÓ‰k‰‰“£›@Á†b¯††ê]ºc ï…Q…ù¯@ÖƒÿƒW‚‰Å€þs0•~4~د}{}!A°xË óþ¯ð¨{{v{Vÿ{/{ýzÁzƒÿzwwüvîÿvàv×vÇv¯ÿvŽvlvBvÿvøuÞuÖuâûuûPSv‘vÚÿv/w–wx¶ÿxqyQzF{Oï|g}³P€Ÿÿœ‚Žƒˆ„‡ÿ…”†­‡Äˆãÿ‰óŠú‹îŒÅÿŒŽ9ÔUÿ‘M‘iÿ‘X‘.‘ØhÿÛ;‘Žä¿4ˆŒåÅிŠЉ*ãàxÿˆ8ˆˆí‡Ïÿ‡±‡„‡O‡ û‡·á€ê…~…ÿ…¦„E„áƒÿƒ#ƒ¼‚U‚êÿ|¹€dÿ€€Ò£oÿ? Ô~†ÿ~+~Ã}A}³¿||a{¬‰ð+ÿyhxªwùvRÿv»u@uÙtÿtdtMtVtl¿t’t½tê+8ïuTum –u¯ÿuËuñuv@ÿvgv…vœv©ûv®É0±v¾váÿvw_w»w'ûx˜•àhy¼yüÿy*zCzOzQûzGï2OzmzÿzÌz{m{Óû{?·Ð}u}Ë¿} ~@~eé@¤þ_€ WÀ@þÁ~7‚÷‚ÄÿƒŽ„Y…$†äÿ†¤‡Xˆüˆ™ÿ‰ŠŠîŠ8ÿ‹q‹ž‹À‹Ü¿‹ï‹ù‹ÙÿŒŒ"Œ0ŒGÿŒbŒ…Œ¬ŒÖÿŒüŒÿúŒÅŒwŒÿŒ¥‹'‹ ŠÿŠˆ‰öˆkˆãÿ‡^‡Ü†Z†å¯…j…÷‘³@;ÿƒÕ‚t‚‚Ç®e0@U †Å@ÕÿV½~~3ï}L|`¡pyÁÿxx‚w w°ÿvrvCv%vûv Ñ@!vGvÿvÑv;w²w5ÿx»x@y»yÿzyzÅz{8û{j¯Ðà{&|sû|¾-ðP}‰}ºÿ}Ñ}à}Û}Ðÿ}»}¦}Š}n¾1ð-} }æÇð†ÿ|M| |Î{ˆ¿{<{÷z¬…ð ÿzµyVyíx€ÿxxˆw wþÁ »usuHu<ÿuSuŒuãuPïvÐvU5dxèûx`— Nz¼z*ÿ{{÷{a|Çû|;ÑðC~é~©ÿ‡€®‚èÿƒ2…„†Õ‡ÿ‰@ŠP‹HŒ%ÿ쟎AÙÿ_×=‘Œÿ‘Æ‘ã‘à‘Äÿ‘‡‘3‘ËOÿÂ+”Žùÿ\ÂŒ1Œ¤ÿ‹ ‹žŠЍï‰+‰±;0»‡@ï‡Í†[‹@t…üÿ„z„íƒWƒ­û‚úÿЀäI¿Â~^~a ²ÿ}—}s}D} ÿ}À|d|ý{•¯{,{Øàn›ðiûzŸðúz4{lÿ{˜{»{Ð{Ô¿{Ï{Ä{²©ðˆÿ{t{_{I{.ÿ{{özÏzªûz‰`YzKzN¯zcz|‚â‘€ û{™Ð½zz7ÿzÛywy y”º—Å@ƒv÷³0ìÿtwtt´sl¿s6ss Á2ÿshsºs#t ÿt7ußuvQÿwxÚx§ywÿzL{%|}åû}Æ{P‚€M ÿ‚¸‚Uƒëƒv¿„…–…&WÐ_þí`zˆóˆ[‰´ÿ‰û‰:ŠxЏ¯ŠùŠG…Àä¿pÿŒŸŒÁŒ×ŒãÿŒíŒøŒ #ÿBh«ÿÁÊËÀÿ©ˆd:ÿÐŒŒAÿŒì‹”‹8‹ÒÿŠnŠЉ ¿‰tˆÆ‡øuÐÿ…„ƒ‚ ïD€y9°~{ÿ}Ü|>|—{ëÿz8zˆyáx<ÿxŸw wyvíÿuauÚtXtÖûs_û°‘rArýÿqÊq©q–qŽÿq›qºqñq9ÿr›rssÿt¬tCuÛu|ÿvwÍw‰xRûy%‘€Í{š|Oÿ}é}g~¾~ûÿ~/1;þ• _†µìþáð|€É€aÿ«í&‚Tÿ‚p‚y‚n‚Nÿ‚‚Þ˜Mÿ Í€£€Œû€‘°á€1ÿ‚…‚ ƒ“ÿƒ„™„…uÿ…Ê… †9†Xÿ†k†q†u†wÿ†††Ÿ†À†ë¾YÐY‡”‡»A0Çÿ‡—‡F‡Î†8ÿ†„…½„åƒÿƒ9‚m«€ëÿ:‘~á}<ï}|î}€µz$ÿz¨y:yÝx’ÿxVx*xxâÿwÎwÃwÆwÔÿwõw-xxíïxty} ˆ{]ÿ|9}~ï~Áÿ‰€>âmÿ‚í‚[ƒºƒÿ„a„±„…[ÿ…·…†p†Ç_aÐó‡;þgΈ‰Z‰îoÁ‰­w !‰³ÿˆ3ˆ®‡,‡³ÿ†E†ä…‡…0ÿ…Ó„g„ôƒeÿƒÅ‚‚[”ÿ€Æö~%~Uÿ}Š|À{{GûzÍ Qx»w#ÿwŒvõuYu½ÿt%t™ss¶ÿrkr8r!r$ÿr6rVr}r±ÿrîr9s™s ÿt™t=uùuÊÿv£w…xhy<ïz {Ùp\}%¿~õ~Î¯í –ÿ‚ƒ”„˜…¤ÿ†®‡¼ˆÐ‰äÿŠø‹Žï㱟°ç‘Mÿ’‡’’r’&ÿ’¯‘‘X|ÿ‰Ž‚gŒ8û‹ý½€P‡å…nû„ô~Fÿ}|Æz™yvÿxVw2v uìþïÄqÏpöoJÿoÎnynVnRÿnnnnÛn!ÿotoÓoBpÈÿp{qRrYsÿtëupwy«¿zH|Í};³`ûŒ»`òƒn„Èÿ„………øÿ„Á„p„„·ÿƒXƒƒÇ‚Ÿÿ‚‚’‚«‚Óÿ‚ƒ>ƒ‰ƒÙÿƒ=„³„7…Ðÿ…{†-‡à‡’¿ˆ,‰±‰#Ù`¾ÿŠõŠ)‹g‹¨ÿ‹ý‹[ŒÄŒ.ÿ“õCŽ}ÿޢ޶ޝޔÿŽgŽŽ·=ûž+0‹'Š+ÿ‰$ˆ!‡ †+¿…C„fƒ—Ù°ÿ+€GP~Jÿ}0|{Òyšïxaw1Ÿósèÿréqôpp,ÿoUn†mÈlÿl„kk¢j\ûj;¡ Yj˜jôÿjikók l\ÿm1nop ÿqr+sOtuÿu¬vîwû‡3#°N‡q‡œÿ‡Æ‡î‡ÿ‡ÿˆý‡é‡Ì‡³ë‡¤#€—+°™‡Žÿ‡v‡E‡‡ªÿ†A†Ì…L…Éÿ„@„¬ƒƒjÿ‚¶õ€-€eúuðéл|C|áþ)P:{òz±zoÿz0zzÚyÇ®ç@»yÀ‘ðÆ?¶ûy²ã0Üyzzþ`š{L|}¼ÿ}c~ô~gÄÿ€M€€»ÿ€ô€5yÄÿ‚b‚¶‚ÿƒdƒ·ƒ„Fÿ„m„„„‚„cÿ„.„ƒfÿƒ/ƒƒä‚Ç¿‚§‚}‚G÷Ðÿ € €«ÿ<Ñ~p~ ï~™} û |{«{óc`'àÒ“ðØïyàyáÀºyŽÿyQyyÚx¡ÿxqxJxxõ¿wÄwwQ­ äÿvÁv´vÆvóïvAw£Ù x)þç@RzïzŽ{3ÿ|Þ|Œ}>~ëû~“áð¿€GÊÿC‚·‚'ƒ›ÿƒ „ƒ„…„ÿ…†§†M‡÷ÿ‡¨ˆ\‰ Š­ÿŠE‹Ä‹2Œ†ÿŒËŒ-Rÿp…‚ÿkFÒŒOU@䋲ë‹ÛàíÙ`Ù‰ÿ‰)ˆ ‡ý…Åÿ„‡ƒA‚ý€³ÿf~}Æ{t¿z&yéwǹÑÿttjsáruÿrrãq¾q²þñÀðqDr¬r7ÿsÐsntu«ÿuAvÝvzwÿxÏxy]z2ï{|ìó„~Dû÷?d"‚îÿ‚Àƒ›„u…Iû†€qˆúˆlÿ‰Â‰ú‰Š þ¿À‘‰%‰¦ˆÿˆ‡‡›†@ÿ†ú…À…‘…\¿……Ë„_Y0Xþý4‚¨ ¢ÿ€"€‘î~8ÿ~Z}b|O{&ÿz÷xÔw¶v·ÿuØt!ts%ïsär•ÐÝrÿsCs†sÍsût`‡pøtGu™ïuðuQÑ05w½ÿwZxyçyÚïzø{7õ €†ÿƒw„Ð… ï‡'ˆÕ`½Šo¿‹ ŒœŒ! pàÿŽ@ŽJŽ<ÿŽ"ŽúΡÿo7ñŒ—ÿŒ!Œˆ‹ÃŠßû‰ÖÁ€q†6…õïƒÆ‚©õ°°Ï¿~ú}+}Z À—ÿz y§x­w¾ÿv×uuhtéÿssTs:sAþepsÜsIt×ÿt‘utvƒwºÿx zm{Ñ|"þpropDATÿE6-1ÿ6-2005, ß23:27ZáNA}MaáwaveZá¯ORIGbà‚á.þ‚àSAMPÙÝžâV"žà€@®ïÀïÒïäïöïÿåòÿ~~}|zvphÿb^_`abcdÿfghijlmnÿpqsuwy|ÿ…Œ”›¡§­²ß¶¸¹¹ºCò¹¸ÿ·¶´²¯¬©¤ÿ–„zpeZÿQIFHIKMOÿPRTVX[]_ÿbfks}ˆ’›ÿ¢§©«­°²µÿ·¹»¼½¾½¼ÿº¸¶´±­ª¦ÿ¢ž›—”‘Š÷†‚ðke`[ÿVPIB;4.(ÿ$" !$'+.ÿ158;>AEHÿKMPSUY\_ÿcfjnrv{ÿ‡’˜ž¢¦¨ÿ©©¨§¥¤££ÿ¢¡Ÿ›š˜—ï—––•àð”””ÿ“’‹„{qcÿTGACEGILÿNQSUXZ\_ÿadgiloqtÿvy|€…Œ—¤ÿ±½ÃÆËÐÕÖÓÌù¯¦ ÷ŸŸžØñ–”’‘ÿŽŒŒ‹‹‹ßЉˆ‡‡€†‡ß‡ˆ‰ŠŠ:†ƒÿ}{yxvuÿroke]VPJÿE@<85567ÿ9:;<=>>@ÿABCEFHHIýJ`ðRTWY\`ïdhlp1ðxz|ÿ~„‡‹“–ÿ˜šœ ¤¨«­ÿ«¥šŒŽÿŽ‘’“”ÿ–˜›¢ª®¯®ÿ®¯³¹ÀÆËÌÿËÊÈÆÆÆÈÉþ¸Ç¼§urÿrrsstvwxÿyz{|~„ÿ‰Ž•ž§±¹½ÿÁÆÊÉÁ·¬¡ýšì™™™ ¬²ÿ°©¢š’Œˆ…ÿ‡‘Œ‹ˆ…ÿ‚{nT>88<ÿBFGIJH?5ÿ039?A?>AëDBmDKNRÿW\^__^\[ÿZYXWWVVVÿWWY[]`ciÿvŠ˜ž Ÿ’rÿccgkptx{ÿ~ƒŠ•§¯ÿ±±°±²´´µÿ´±«£œ–’ÿŒ”—ÿšš˜˜™˜ÿ™›Ÿ£¥¥¤¤¿£¡žš™—.~3‹‰‡…„‚Oÿzxwutrpoÿnlkjjjihÿhea]ZYY[ÿ`c`ZSPPMÿGCB@>94/ÿ-..,,059û::°ðDGJNR»VY/`bc%ñi“jk,ð.ðrÏT€ÿ‚„†ˆŠŒŽÞ§™Ÿ¥ª³¾ÀÿÂÆÇ´•–ÿ•–—˜˜š›ÿž ¡¢¢£¥¦ÿ¨ªª«¬­­­ÿ®¯°´ºÃÎ×ÿàääåæèëíÿîêáÒ¶¯«{©¦…Ÿžœ›ó™™˜˜—–•/ãŒH=Cˆˆ‡ÿ…ƒ~{udB¿339=<=v >öz!= £¢ ›œù™¶ ‘’•––ÿ‘ˆhMRNOP·TWZØceÙ1v|†Œ•¥6P®­®°³µ¶H1ÿ³°¬§¢—½‰–~{{z¤Pxßusrqq£igÿeca`][XVÿTPJC:40-ÿ+'#$%%&'ÿ*-/00123öÊ𯫿ÅÈÿÆ¿¦¤®°²©ÿ•¤›’˜‹ÿŒƒ„pm|yvÿWKUQY]^Z¿ZXN6,9€ C¿HNRSRS=Xÿ[bkt„‘–šÿ˜Š“˜Ÿ¡ý¢ š‘šš–’¤¹ §0vp‚\€e¿eecc`^óPbocaa`0ZX!ðÿabhjllkRÿAPSTSPMLþÔ]djhiouÛz{瀖žÇ`¤§ÿ§¨©«¯²¶¼÷ÃÇÄí0ÃÁ¾»¹¸¼»·´²Nñÿ¥Ÿ™•Œ‡€ßwrnjg¡fduakðq½pttuG@ö¼jk®@pqpoøA@À@£jigd_ïZQ4 ÎQ002ý51LQUUTTûTV|^]]ahÿot{ƒŽ–› ¢5q±°°@c ³õµ Ãhrž¶ÿˆ‰zvuúß`mã€wwx}†ÿ–šž¥©¢‰ÿ“™š ¡›„‡ß“—›œŸC0´¹ÿ¾ÂÁ¼¶±}w‚ƒ€£Py{|r`û‚’ŽŽ’•“ÿ“•˜›ž¡¥§{§œ50}}ƒ@ûˆ‹=0’“ŽŠ‰üÖaò…|S>=7_789:< >%¿JNSYZ\ÿðhßkpuvy ’˜ÿ£¦§©¬¯³ÿ·¹¸µ²²³±÷®«¨‚ ˜–Ï–“‡±¡ªPqiß`\TNHÞPB=÷6+! 0#(+/ï4;AEÏ0U_hÙpÝ0t1xu€ sqûqpÎ@nqtwwyuJpP‡‹ŠˆÐ`ÿŠ’–™˜—”ŠŒ”™žÎ ¯§¤lA@l+ q;rtm`z~€nBÒ€ÿ˜ ¤¦©±ºÂÆÈÍÑÔØÛ`ÿäæçåàÜÚÖ?ÐÉÀº´°ˆðú ˜•‰“ððÜjhfedfjkÃAÿ^VMGA910ÿ-(&'+2;@ûA@mFGHKNŸPOONMqPp_þ{Phgffhhhfd°eb8`âƒ'y{}±po@ˆD •–˜—›™— úTp¤°©ª«ªž©%Û«°¸|ð¼ÿ½ÀÂÄÅÆÇÆÿÄÃÂÁ·§«ªÏ©£›Ûðj0’ß•–šŸ!§§ÿ¥¢™–””߈ƒ~xe°okòÀ@p/ð­PqqjT÷TSQøó^\R;m?‡!JJöðPPn×M9/ó 7Š0:=ëDIoPFdðY_bgmtxnY_Ú!î w{}Š‰Ž–ïœš—” ›Ÿó¥«µ0QÀ¬¬ª©¾u𬥉zÌw440¸ NƒPàÿ—œ ¡¥­¸¾S¿À ê0Á]0·H0ÿµ³¯«¦¤¥£þÛ¨¨¦¦¥Ÿ—ÿ’ŽŒûŒ‰×ayvrolûhc3WRLJMÿOQRNHA>AýHÆÀPKILLKwJIJ„ÐJHJÖ ?fmqoon¼A¿ð×uv{&У“•?“ŒˆƒPðvµayx0À~~ñ¶@pyyÈÒz|·`~¿‚†Š‹‰„n@ƒ¶Œ•žWp³½êÃÿÂÃÆÉÌÐÓÔÿÔÓÓÐdz®°þŒP¯°¯¬ª¥”ÿ˜££–‘–„möpne†ÐGFDB<1"*/37Ï oDGMSûð`ajñŸqtz‰YK`¯îE2¶²°‹P«¤œï~tzršÐhhgûhl)¡qw~„™£§§£–‡£ÿˆƒ“‘‚ÿ‰Œ‰xwƒ„‚ÿvy„ƒƒxaß_fgfgãjcïG;A?‚ ACFÿLNOQTXWU¾a@WX^goº`‡÷ˆ‹çp’…ouà¬@¦*¢, ™±prußzƒŒ”—TpŸ£ÆÏð§«HÑß´0¥££¤¤¥¦££ù ÿ˜“Љ‡‚€_ƒ…„ƒ…Ö`„Z€àPx`©@gÐÃ@ifcÛhkÜ |90‰ˆï‹Š‹Œ^Ð~f]Ïcabb  ´Pbaîƒp\ZY‡pdegŸinu{€«°€ÿœœž ž¢¥ìÎðã ²±Jਫ°°= ««§ßáQП@Û‹„§`ts% qoþ³Pdec_\YZ_ZZ]ci¹ãjæ oq(¡pШñQú`ï^XTU bb_ÿ\\ZXZ^fnúêuî…“–û——‘›™–“‘ã‘’À¨Q ”–—üþ‘‰‡ƒ€‚÷ˆŽŽq0€~ƒ3ˆŠ÷?0–›(Öà÷¯³´÷‘ª­°²ÿµµ²®ª§£oz†ƒƒÞÐz=@Ÿsrnkl/€»aŽû‘#Q’’‹uWý\4ðfhnuyzù}¤0^ ‰ŠŠ…~û|{· |yz||ï{|„‰gP•–™þ윚”“““ß‘‹‡„²`…Š!‘”ìð2°Û€ýo±€[ZE7?@¾AC@;99ê@<ÿFNQRP<4>Ÿ=AHMPa@’ðlÐWvtoÀð—0çÀи@ã/  yPŠþ|—•Œqgos¿z‡Ž•™œ ¨þ ­µ··º¿ÅÿÊÏÓÙÚÖÒÐÿÐÏÊÁ³”“û’“€ÀŽŠ„}yÃwugÐ]àpÓÑ„ŒúŽ‚© Ъª¬°²ß®¬«¬°ý¶³ÿ±±²°«¦¢œ×•Œ„Õ {ö`wsÿnhddca__ÿK8;8::52û32ÐP1..13ï46;DÁÀNML¯MNPQÄÀSûp`ç`bdå°³Afko3qt¾p-€rtðÀSËŽ’•’ÀÑàš›ûš›G!›œžžþRñ¡§®³¸¿ÈÿÎÎÌÌÏÒÓÑÿÐÑÒÔÔÖ×ÕÑÍÊľ¹µû¯­tñ œ˜”ý‘vp…€}xsmùiÀ‹ðZXUPJÿGC=+').û362RY]\YûWVoSRQQRj³Á]ž0o¦ðx{d¯ytu{ÒÐy¶¡|ß~„‹”|À˜šÿžŸ¡£¢¢¢ÿ£¦¨¥¢¡¡¢Û£¤‰À¦§a ¢˜ÿ}wxwyy|ÿ‰ŽŠ…†ˆ‰…ópj‡ pˆˆwÏ|ˆˆE @˜˜~¸‹syyus Ù|,p‹‹"™˜—–oO@…?`FÁþû!“’‘Œˆ‡…¿cVYY\Gh·qxuuy£0€ÿm_kns|…Šÿ„yˆŽ–“ˆ“ï—’{&u^bŸcejeSGº@mÿieWENQTTßRPQRRêPTX¿^acippÐ×…‹ŽcPލ¬þ@à±°¨“|ƒ~¯ztqs p~±pÿ€{z†ˆ•÷“|u40nmqr–ˆ€‚…ª°‹†<‘ÿ‰…~hSZWûWZ°\[[]cÿgihhiklmçpuxpž`‰”ß™ ¦©¦RТ¡/ Ÿ ¢èà¥ßàRÀߪ©§¡šæð˜˜ß’Ї…‚Ѐ…ƒ»{Åvvy¥@p|²P3 UUUQR¦àqÓ uw=@ ±+€sÞPtvz€âБùŠ9ZÑŠscgc›ff  deÇ@0 g´†ð!r Q|‚òšw¥¬Pº¿Äs¡ÿÊÐÔÖÖÓÓÓÑÑÐÌD—P¡0œþóàŠ‡„€{rjc^[ZXV€Ð]Jõ@UY]Ù@aˆö¶_]ðP[XWZÿZWROSVVW»[_·PVSY.à^_cgklih:`¥tôp~óð«°Š0ŽÇ|v|Pe°6à„‚½ƒ$ñŽp¡Ð‡ÞÓ€¢¥§sð¥¨æM`±°Ä@@௫¤w  £Wp¯°±j öØpº»ó±¬¨§ÿ¨¤Ÿœ™”‰î± sXWO _dhõk#ptš!|rUT¿NGDEA;”à<ÿ:=ABGNSXû`gÝ xz~~}ï{|}{«àkbÖ²Phm&prj°nq¯sgSZ7`f‰`owquz£„‡vp—y_eä°iß^àþ‹“•š ¥ñª\pͰF·»¼½ÿ»»º¶´´µ¶ÿ²¨—{~}xwÿv|~€……‚€ûrgËàuwwr`ÿ`ifZVfloÿnXTZ[bgnrsddpà0P@Szf@ðsâ0}#Pµz1€OP”˜Ž žÿž¡¢ ›’zov€ pp.z†§ÏŒŒ‘”Ç¡ ¦¤ÿ¡‹Œ˜›£¤Ÿ÷‘œ‘À’‘“ÿws{|‚‡„ÿŽ“”„|‚z½np|u[U¡pPÏQUY^û!œ°x€ˆ“› ¡œˆ°ß€eRWX,à\\^)!ommn€} `‚ˆŒ’—žmQ׬¦§Ъ[ð¤¤\ýPO žš•``›ì@Œ‰ˆ‰’‘{ û‡ˆ®â–‘‹‡…û„dÐuqle`]ZVTQLK±ÿZZUPMMNKóGHS@²ÀYUTUÛWZR nu2Àƒ€àƒ€é „b0O‚€€~Ü€ lã€ùzÈÑ< †ŽŽÏŽ{mcÏ€‡‹ÿ•šž¡¨ÞAົ·²È@°²ÿ´³±³¸½¾½ÿ¿¿¼¼¼»¹´¶Æ@®¬'±¤£‘1 ßŸ›ššT€•’÷Ž zvplÿkgaZS9((ÿ#&),-+))ÿ)+-./4CG÷LRUt@`acdqfw0g€Ð~€„ý‘øP“ƒ‡‰ˆŒ÷’’ŽYБ”—›ýž\ ©¬°´µµÿµ¶´ª‹ˆ~~ƒ…Šlàqà{‰‘¦0—”–œ‰Á_¨ª§ŸŠŽaŽ«¿•xqz{dPŠf(ð‹@‘ø`k‘—Ž ›€¢Ÿ¾“{àkkjÿga\[_dfRýL ÀJD@@CFJKKHEEEö€Y]`ceec’бs[°©°&‚~ÏPˆùŒ²ž¥«­­=ªŽÀ—”‘ŠìpŸÀ“lq{ . w¡qóðƒÿƒsdkfd``¾°jlpslÿ0kˆ9PžÐì~„0ܤPqëu{Ëb‡À¡~3‹“™›ž¤Pп¡—{uuuÀh{gdtpddff‰àûlpËðˆ‘˜Ÿë¢¦áà±°·µ¶ÿ¶·¹¶­——šÿšŸž–†“ÿ‹}ƒƒyelnÿkfhc[fntçtp[žàµÀZS]÷aXHyPLAJÿT^e_au|ÿy†’œŸ•‡Œõîð‰Ö€|hbh¿gggkpvóp…牑R ¢˜~¿z‚|xtr—w¯wzˆ>Àœƒ ûŸ¦nQ·¹¾¿ÂÿÅÅÂÃÅÆÉÉÉÈÆÆÃ¾µ£€î7 …ww±ð_[XÿUTSTVQMN$ø€ordƒ@y0o0gÐÿkkgcTQX\ÿbeb]ZYXWÿSOOPRVZaçjrw äŸ¤§¯§¨ ‹ŒÓP›¾€—‰ƒŠ‰¡ ŒÿŽŒŒ‚pqksd^h1Æ`prtÏЗ}}vvpsР @|¿‚†Œ“šž:pŸ†’‹‡’U|ÿ‚……‡†„‚ú3À€p„Œ’™£÷ª­­-q¤¥ª­?®«§¦›ŒÒ€e°æ9À‡‡ð{à~|wÿqeHBC>=?›FL.°`dL^z~Õ ~…”›¢]Àÿ°±´··³´´ß±¯«¥ DÀ“+kj/ðfÖkûþI d`]_`^]Ï^bhnèqA{zôœ " ŠÕ€……‰Œw’ª™š™¸ þz`‘’“”•™Ÿ§¡žšÙðB@…p‰ß|vqn»àkoWsuwí`{ÆptYßc`U99%áHL·PTY0ce3xõ|„0“Š!š¡ “xpg__eœð[nq~þà„©@ÿ‘“–šœž¿ž¡¥¦¨­Ø@¶ÿ»½½¾ÁÄÃÀÿ¼¶³²¯«§Ÿÿ—‹‹‰ˆ‚z¼Ñ0Œ@}€|Òpm×lhf\A_4±XZç[]^1àðfjfÿ_\UTVVUU¿VWVWUXVPiú’eöÂ`^\^b¶@ikU`v{Ë€ŒÓ‹ˆñeQÜ𔓿‘–••—s“‰ŒŠ<Ào‘EÐAy¿“—˜›Ÿ¡Vñ¨ý«kð²¹¼»º½ÿÀÁÃÄÄÂÁ¿ÄÁ½º¸¶ ¯ÿ­©§¤ ™—×’‹†€}ŸÐ{xuqnpsur¡bÿXTMGEFHIûKM®QNGCDÿFGHKNMJGýDÁÐHMRTRTíU0`^M@UVZ×^`eÀh‡ñho¿sqmihjgyE~h’Žàðó%§½°{¬ªV Ÿš˜Jõ”QЙ½!ˆˆÞ­¡‡ŠŽ’§ –•~@@‹‹ŠŠ‹‹Ï°Ÿ†ˆ†„@U0?{wsqpèP%PþŽ@‚‰Ž“œ§­¿´·µ³±¯É@­ÿ®±³µ¸»¼¼Ï¹¶·µqnð¡›?•‘Š…‚~ðÁÁ0²^\ ÐTS(`RÿLIJGECBBÿAAACGJPSÿU\ceb\TQT‰ []`tpDPnpplhhec‰ðÝcDPou~Õ`qÎ+Àsx}ª°§±~}Ÿ~€†‘`àÿŸ¡¤¤¢š™W”Ž}ð†ð‡%àÖ…`‰ŠS°=–œû¥®þ°º½½¼½¿¼¿ÆÉÊË'ñÌÿÌÌÍÌÉÆÄÂÿ¾¹´®ª¦¥¤ÿ¡ ¡Ÿš•îËPxvs4PpiUÿPOKJHF=.ÿ25699-.:ÿ@A8@JOTYöfAPG¸\`[NëQSÇ WrA^_aÿ^X]aejpponlbkÎp#`£[‰‹pœ¡€§€îŸ0ª§¢  Ÿžü×ðâñ•“‘Ž—ùš€po˜™œŸ ÿš–†{{unê¶ eZPo¶poruWx}ƒð‹ù`Œ¡ ׎FГGБ‘žù𔚞 ê@¼ “Ó•”=Œ…q÷mnh_][\]ÿ\][UPH40ÿ6579;<>B_GOZ`b xÀp?‚„ˆŠŠ€‘Fá_…‰‰† ‘÷Pß››Œ”_Àˆ†/ƒ{gdx0lHP—Àÿ“‘„ƒ‘•ÿ–’‚ƒ‹ˆÿ‘š•Žœ’ÿ˜˜•’…Ž•÷”Ÿ“¦—Ÿ¡’þ°¤¢™¤©«¯ÿ²® Šˆ…†Þ•°†xzƒ† ‡‡ÿ•˜“„‰ŽŽÿ‡z‚‡ˆ‚v}ß|ompd2Ðj\ÿchla[inpãfW˜w0v°fahÿfhjnrv|}ßyfaghñÐov놶AŸz`”™ÝœžÀ›œ›~p—–fu”˜a8à‡ïû{vžtpifec_XA>@@ ßPTUZaAowß~~{xx P…ûˆ‰`ƒ†Š‹ŠÍŒ‡˜š àŒúáÀ‡´@Ž‹†‚…ƒ‚â`œÒ0ñ±‡Šd™ñ‘߈ƒ€€ãáznoXUON 0TTÇ ù[Z@dccba²Íáj¹ FàŠµ€˜öÁÁŸŸÛPŸžœÞ•0¢¡Ÿ>ðŸŸßœ——–—ᔓ§f°o{çz°ì°¿p¢Ð Pƒ†6{·wrn«Àmp.Àylò°À “éñˆ„Ëaß}ynUR °W[µ]o0Zmp\e wÿ{{yxy}…‹ÌôPxŽ‘H°”3¥¥¿£££Ÿ À”ߎ†~‚áà€¡Ù`ø`eзð“TÀ”»”’Œ`…ˆŠ»Á“í‘WÐŽ„Š‹‘úœÀ˜¥0’…}zÿwrljlmidÿ^XSQSSRRþÑÐMMOQSX\ß]]][W« VXoZ_ceÀPopÚàö‘ñ~¿…„‡‰ ‹øPœÄôà0€V ᬭž0«ô ¦ÿš˜•’ŒˆþÁpwspj]C?¿@@BCFKžRþH€QQSYaiq÷x}¶A£¨«­ÿ°³¶¹¹º¼¼¿º®©¨¤¡[!’þ †‹€~€vuÿjja_X]VVÿNQOFL@HBï:AAEPGKOÿQU[abdefþB¡fmt{}{{óxw¢pçà‚ˆ€ÿ‡‹ˆŒœ—“ÿ𒔢Ÿ— ¢ÿœž¦ © ¦¯ÿªŸ¨¬¬ª§¤ï”–žœतŸ?’šŸ¥©kàŽÐÚ¸±¢‡œ’ò`xu}r¸pquy}~‘ýE°•——›Ÿ ¡¥¨ª¨š‘@pþ¬‹†xxtlÿqokfc^YXßYVQC@V€[_Ï\K?F¬»ÐRVÿ^adigTRYå[<iÙáÉqusphÐUS1“áÐYÎM`iouyqœ¤ý¬ü°¸¹¹¼ººÿ¼¿¿¾¿¼º¸ç´²±‘Ðj`­©¥2„™JÐꃜÐïÀÞm€y{}×1…ˆù‡ð>À€uXLKŸJMOTWž@°aÝ`†ðosx4ÀzxîÐp{|{LP‹“”ࣣ¡ÊÀðñPÿÐ’ŽŽ‘=TÀ¿ðÿ•’Žˆ„|{»~€ uvxî‘õ|ÌP{@sv}¿‚‚ƒ…‚Å‘†¯……†‡ ðŠ:Љ††ƒ~|zv»pþPsrstspqÆ&st    0Àzx·vtq pj¸ pæåw{õp©pvoûkjñÐldQTXZ°eç`ptáð€p™ ÈÀ¶¸¸ÿ¹¸´³¶·´¯Ÿ®±²°°‚P à§ÿ¦¤£¢œ–’Žï‹‡‚}ã`mkiô½P1Ðo‹ðg_M8½<0EILM@Qükp¹àeghlv€ñ†»ÝX ®²°¨_’‰†€Õb‡ Pß„ƒ}~:À`˜p‚ N 1b ƒƒã@þ¢p{yuoZNNþipX^ejmv}{mjqrw|Ë€÷ˆyzã@xlt}ÿ‚ŒŠ„Ž…ˆÿ’Š‘’˜žœ½˜»ð‰ˆ…ƒ@ЇÜð@àƒƒ€îtt™vRàì°{zPÊa‚xÔb@`× „ˆ‰…h!)†áPy€ððˆâPÿàÿ‚€z}„…ÿ‚’—Š‹™˜ÿ œ™§ž›¦¥ÿœ¥««œ–Ÿ ÿ–˜š‹Œ”—Û—ŠçÀz{f ƒ‰Ÿ‹‚t|‚R( ˆ·|ƒƒ´ÀŠŽbђd`ƒƒõ‚àa„›p‚yrwmjjiqpl‹à]VTVTOO0€ýOfð\`\UUW+YZŠ \ýÀZjðÐ*ãÐ`³PSÀa%ÀÑóloqÀ» |‚‹•ÿœ£§®·»ÂÈëËÌ*ðËõ¡ÇÈÊÿÍÑÕÕÓÐÎÍ¿ÉÄ¿¸±¬>0žÿœ›—‘‹vlhÿ`]YUOHDDÿDBABFNW\öqgiÁlk^bl³mmnÍ l€ëBß||€„ƒðŒ* œmСƠ  1|^ÀÚ ——•’‹P'}{zÿàˆ`„$à}`ÏŒ‰„ç@p€|}ß{yzyvçÀtp/notz Äó-‚ò@}‚ÚP€þ@„0Ü Qi‰‡‡Ò°‡Œömˆ…‰`€~|y¿wurnic¼àef#Ðef=Öðfh!°ÿrvz}~}"6}3ÀÉ08ÀƒDöîë±|~ 0zvvïobca‘ilnŒðÐâkiî` ~0‚ÿ†‹”§³¾ÅûÇÉQp×ØÙØÖÿÔÒÏËÈ»µÏ¯«¦£ZÀë1„þÛ€hea^[YTÿQPMJIHIL.i0WW\Ðn9 Dàþ †…}j_e7db`»áeh€€Þ}oÒ xzxwx±@÷{yyjP„ƒsßWZ[ZZ@gi3mt„@j Œïà– ï™›ššÀ›ž ÿ£©¯²´µµµï²®¯°„P°°²¿±¯®«¨¦X! Ÿš–.à˜¿pÔp<Ðs„~Gð&Pmjgp€þçÐ_ZWUUUTÿRSSUUOKKÿKLKLLMOOûMK¹ÐOQTUS×RPP!0XpYVS´àY_fóÐ+PtÅw@!•^ QðŽ“ë—›ÃÁª-³³±û¬¥à ¡£¦¦§ÿ¨¨¥¥¦¤¢ŸûžZ —”’’Žç‰…‚ ƒ9à”–ÎLÀž  ÅÃ@œœœ››˜•”eÐþÖ‘„wdfcgj·mli­Ð^aÈ owuxz€0ƒŒ’œÀ{ŒD`Š“•Ġǥ£‘ µò} kÿiigea`_^ÿ\\]^^``aodjptâñŒàÞÍP©ªª¬µ°°´ÿ¶¹»¼½½º¶û²«Å@–•—–lÕ±æpwr"À^\½QÿfdaS>>:4}3+@DEDB¨àïLMPTÅ€glcü¹€¬¡LKKNTZÿ^^^_^`flÿrx}‚ˆŠ‰=ˆÄ`’•—•ðà!¡¢¦ª­°²5’a§È«pX ±ðš—Òa/’Œ‡åàx| ë@yxphŠ¡n12€UÿGG@<>@ACOEJRVä°½álª@ºDààà‚BÑ”ÜOÐ £§ª§ð¤Ÿ¯™•””¼@˜\À’œGЇqdqŠql6? ehx€kq÷ѓ¤ ©æ0Ÿ‘”¿›¡§¨ší‘£ÿ¥£–›¡££—_˜™•…P†æðŽ„qqS`þuÀyz|yti`åhitHPèÀ‚‡Š~‡”šœ±`¿rpnnkgxn+t{j øðŽÿЛ ‹Œï°Ž÷Œ’‹ŒŠ|jÓomœPéÐd­`cfÔðge?KðswùÐð€Ï`8°‘–™˜‰˜°Ìð”Ì !áýPw¿utrngb· ^ó\[« OSWZû^eÐjknsx‚EäððLèðé/jejeÇ gõÀø¥ :€Üà…Ž—£òÄ©¤ñtЧ¦£¢?£¦¨¨¦¥Á0­pÏ£¢¢¥Å”À¥¤û£ [ –‘Ù‹ y@„…ð†‚û|vç€kfa^]¯[[`am0fb°häs0.€g°®ÐVTTæ®"W[!°¼áfdb÷_[X @YWXW¿STVX[_¿PjÝm'±‚†‡áQ{výsEPrty€„†.' ––—Çð å0¦ñ稪®iàÚ ³´¸»º¹´¨™ 0ô°ÿ’•–™Ÿ¤§¿¦¡“ŠŽ‹Ð`Žÿ‹’“˜ž¡˜“ßšœŸ¢Q ¨ª÷§—‘¹ðŒ‡{{ÿ€{swrmskÿ\^a^W_a[ÿ`[`]\Zhc÷fndP0cY`b7X^XÓÐWYØÐÿdcekfmciÿi^hopom^ÿ]hhhiov~ÿˆ‘Œƒ‹’ÿ˜œŸžž¡¢¤o¦¦£˜»–™„°ÿŸ’š ’û–™~€‰‰Œ†ŠŒƒLPÿ€vƒˆ‡qÿrv{~~rfkïlqstÀ‡ˆ„¿vhnrtrHPx?rbbort~ÜP„‰_Д†„ÿ‹„|€z„†ƒï†z‚|îpnnxxopzufi°€¯fWRUµà_‡ðxþþŠŒ„rrsuù|g`»’“†“ÿšš‘Žšœ”‰ß”•™–®`•‰ÿ‰ˆwyø,°çPðˆos{þàŒŒ‚ƒŒ““ÿˆ‘––~€‡ÿ‹’˜ž™Žšš÷“ŠvR`x{€„ç…„`„@~~ßzeiljólq~›{xqmmp¡N‡@~|~ÙP“}°@úôz)Òqruz}¾™pzvqoeÐ]úèÀg¤ pqsy€ë‰Œ"À™­0žš›Ç›Ÿ§¦ð™À_ ²ºûÃÉJpÁÀ¾»¸ÿµ°ª§§¥¡žöÝ@“‘;`„xsýoœPhe`[XVÿURQTTOKLÿMJHGHJJFûB?0NW^dkgoot`ÀÓ €ïAìÙPÚP‚M€yxw¶Pvt À__®g–fnqÀwñQ€†fÞ ™›§pãЪ¯|Pÿ¶µ¶··¸¹·öQð¥ Ý@ŠŠ‰ïŠŒ†€áptcSÝV]`ds€qu»{U Š~„¥àŒï“—ž¡À§›šó›š, ¥À¦¥£ŸÞÉ@{pus'rownnp6à}wk=€ÿsusgcinvŸztgksƒ@cÀ…σ}ljÎ ðtvÏsfY\] a_[aeÐqw¸@†waî@`Š‘— š˜”‘¬0G°b =`œw6P„ƒI€³Ayýt(@vrlhhe¯eecaM nÑ0v»w{ØP†ŠJ@—¾ÞÐœš———ê±ˆ´@`—Pr”ppm‰pjþ…pOSPOQONNNp^dѹ³G@_—¢¨A±¦ÿ©¬­®¯¯±³~2°°³´³²l@¹¡õûБ‰‚ë`f/^[ZY\Zp@þðÀXUPNPSVÿZ_abbcccçfknX.Pwzƒƒ…í°mÁ`ȰÛ@”ÿŒ‡uotrol{ÈÐ(ð3PòIÜÛ!É —ž¤Ø µ¹û¼ÁLpÌÎÐÑÒÿÓÒÒÐÌÉÆÄÿÁ¾¹±«§¤ }žì —“‹Š ÿ|yvsruw{§yvtxàÎ0mUPgífâqov€fbb/a\YXµÐ[]<ï^[UQ° LLKåI{PîgàVZ]ŽLcfhXP¸Ð {ƒ}}ô@€1–ð`l›ûž¡ë  ¡¡žâ|У¯ÀŒP‹°¤£¥]©Q@³µ´¹°7Þù ®­«§¯p™•ý‘Ë@Šˆƒ}voþ¯c`^^]]ZçWSP0´Ñ^\VTkRQUÄ Sn±n¿ I€Üà|Ïp†÷††„`“—ߘ˜–““–ÖA–—7Й7ð˜A•ä°”PJ`ka!‚vñ€Â¼°t-Ð*Ѱˆ|Gy~ 2ò }ðuhNKëÑ&pn€BÐr!ñ `þÇP——˜šœŸŸ_›“……‰ÞQ† P®‚`……zske±f}icàfg]KOµ óaeÉ€R †‡‚|ŒÅP#0•z`éP*2™š™—Ž}þ I€î!üb€ÜPŒ’–”‹“÷œ¡¥¢À¤™Œ¾šàŽŒ‹‡œp‰ß‘‰|{˜ñ~{rrÏàˆŠ}wŽñÿ|wf``^\_{dhUvncjèáüÈqU ’“†‚Šý“#0‘’—›šŽo€……ƒ×P„E0ÿx€ƒˆ‰Š‰†Ïzlpp /°ƒˆÿ‘‘‘…‰ýˆ€‚…‹‘‘»„~>0……ˆ ™{9И—‹ˆ( ×—–‡Êp…OPzh΀potwó[scüÚ€®ðbbddcfî@qv| @–›‘ù‚Ä`¶ …‰p€£°A`OPomW¾s€ponmnq/twwyä@C€¤¬2Q¾°}~×P‚„@‡o…jh‘rwwÿ à4q2±Pm@"¢Ÿœë˜‡ó0†mPއï~rqzæP„€¾·à‹’”†â0¿ˆvmonr6P|É|¢ð @}E€``x»rs§rtuÜxtåpÅAx÷P~|{B€à0Pðœ@Á ËÀ†wmÙq-Žprr’prrÁvñ ÚP pŽÀÌñ¬°ÿ²´¶¸º¼º·ù¶pPÙ𺺸¸¸[µ±] ¡œÍ •Iö¾‚{ÒÂhfa\ÿWTOHECAAûDF{ðHGGIKüG ÐWWVUTUãUSI #°jll;mkØkkcpH O^_`c"ñÐtܾ@ƒ†ˆŒÑ`”«˜âШء´P ²ÿ³³¯¤ §«±Ý°Ä¦¡•ʰ½ŠÏ —–Ì ˆÿЇ…ƒ„ß{~‚yt{à€tÿt}ƒ‰ˆ}‰ÿ‹…~„|‡†ˆ“‘‹’Ž‹0 ÿŠ†ŠŠŒã’”3 ÿ’ü€}yyþ½°youyyonvttkgå ÑÀ?Àÿylkt{vp{û~Ó yg_a§___+pÐl?€|¿†‹Œ» ™n+ ¤¤¦?Щ¥= ½¡²`¢£¡–rÀ‚Ù~ŽQƒtp’AleÿZagmqm`^ÿb_SKQSUYÿZVQXYNOXÿ]Y]ili[Sÿ[_cg^bmpinx{rryPËrh·ðsÈæP‰~º œž›Ž‚ƒ›ðe…Î@Œ§àçð”.0þ{žŸ›—˜œ¡ÿ§®µ¸»½ÀÆÿÊÊÊÉÈľ¼ÿ¸´£–š˜—””—˜–PqÁqXpû}s¬±yxkdiÞÀm\XZ _aÿccWWcfihÿ_`npjjsqïjrvlYÀh[]}bkaY^a rusk^dl0ÿ~‚†€v|€ƒë†ŒS°•00žŸøÔ ®À–À¬«§¦§ÿ§¤¡Ÿœš•ƒuxù!ùàR€tõ0|kÿ°LP@€{ ©°õàzŸmqxutìp§xó|€.°D€~{|€'…‡ƒ' -°}ÆÀød€Í€Áð„ƒ‚€|KxyY€zIXPzTN¸ðpol~€1y-€æ•ð~~|à @”™œ°ÉpËðÙ@à –‘sÀ}ß{xtniäàjjÓji_°ÐlT0hi=kÝpsw| P› `ï m=À—¡|~à÷ˆ†‚ð}~‡Š¿€~‚s;àŒºçð‰$ †„™!OˆŒ“K°.0•û°+‰†}m…<0à㌈>`§A‚‚†¢ª€Ð!p\P‹î±£‘± gpŽÁ€„ÿ€}ysnlhcÿa`bc\PSW¿XZ]cikùs¿ttv{‚†!À—_œ¢§ª­˜À­OöBÐ¥9`„€{zß{ywsqq€fbu`C ^Î0jnq?€ïnps{ŽŒ‘šL°™½ •“ŠVÑš>~0–•‘‹…Ë€°@®× zwpÖÀ]èUUTSSU¤ Ð à‚€I0^°&ðwáwx{{~{Þ z~†@»‰‰È€€~€`ŠÐ@ €P3°ˆ?0‰ˆÎưŒ‰ŠÂÀÚˆ…K~kÐd_@Àj•aúP€Âð†‡ŠŽ’Ù—zйp “ p—›ü'¡‘À©¬¬«©©ó¨ž pšyxx|O€|yÕÓ ‰¨€—…‡‰ •Np4@˜­š,À–“S`˜ˆ‘n¦0ŠŠŒ‘Šp÷|z÷poje[ÿE;=979::ÿ86899X ¬«¨¢œ)°:°ß€£vwPn»hfApnmn_lihiiÁQn-úslx€osvutwuxy0……‚ €þÚ"yzwrnjg×cbc‹`^`heçded€À§³~|xâl`wß‘‡Š±Ä }i!0cŒˆZ`Ð ƒ‚Që‚‚uˆ“’””1“o ¯ ³!†ÈÀÊ€íz]„‚ÈÁ„‡ˆ¾­ÀЋЄrc°tx{{z-P×p °ÏAÔàŠŽ…ZÁ‘–[™›&¡¡˜r$!zYÀ†ì€ƒ{Aà{‘‘ܱˆ|JÀj>€nÄlùptJ x[P" ƒ˜šž)‘”{0g€;°‰ñ€ µûЏ@ƒxeAqÿpmpxytg^~ppa]PEJN²Ð¿UQOQRSµPHßINRWX3_b{gkMPiahl:‘ÿomy}w~…Rá‚}àZ †tƒ€Àý‡ÏAŒ‰…‰†yÿ€‹ˆŽ•—“ÿŒ“…‰Š‚†ï“˜’— ’“‹ÿ”𔑙’Ž~ÚŠ›š–¢#=¤!Еš‘Œ@$€O‚}rx†0÷¡ Ÿ|{tš ^°€~nclê!õѱЈ¶[P‹Žˆ„Ç@vÿvwyy|€~tŒ.€’ðqs •ð™ €ßtnst+rwÿ€„‡Œ‹„vx>ÿ=<>BFJOU2‘_bfjÆâPO :õ…è€srÎÖP8ácçWZ\ V0aa^Ç[ZZlÑlpš€v{Ó‚‰Îà‹á|áž ý¤"¦¦¤£¡ ¯¢£¢¢€ œ¹ÐI‰qÀzÀ€ÃÌQ‡2ÑŒ °@Ð…ˆî´å0|ÚÞðx³àttÀz~%@Šˆy?ge^ZZZ6›jqwX`¿0•ÐÁ0 0מ žkaj`š›Bk`šü —Àp ȃÁÄ—pÞðyX`$À)À{~€ °zÊËWÅ‘¡J ~}{¶ Ù Ç`žV0bb_[%X UzU°WrðabdgÀ˜«°ƒ§0“H@ ‚snv/± !ZÀ­Ì1í’ŽÁ›œr ¤ª¬±¶¹·³²³î€ÿ´¯®¯°²±±ÿ³²°¯¯¯®­×«§¥´°¤ ¡Ÿœù ’M@·€¡|I`ï°è@ø@e¢P_ÿ_\XWVUSQþå±OLHFGHGÿILORTTWYÛY]Gegp_`ï^[VVà°VTQ‰PÀaÑWR0“ þàm nsÐ$r°$ ï"¡ñþˆÁ—¡¢£¤¤ß£¥ª¯±³ð²°ï±´µ¸È@»»ºüyP[À·¶µ´³²ÿ±²³³±®§¢gŸŸ~ù’àú­ÁˆÌPƒ€~‚ÿ€topke_ZÿXWUTUTVX¿Z\]^`dzñ{Gàßц/ ‹tà¡ðtá”)@jP•*`Œáêàˆÿ†ƒ{wrnjýg£`\ZYYVÿRPOMKHGDÿCBAAEJMO[NNÐ`XYºi#ÀÚƒq;°|@à‘Æ—“•“j¡Ö0Y@~xX`t@)nnrv¡ðæP‘ ' žðŠŒ‘”ï—™ ç€¬®²Ÿ³°®®¬¼@–0¥ß£ œ–’~aŽ‹‡€|{xºàÖUâ~ªÁ|ê©ás¸àwê`{{~¾€ˆ’–›¬ð£~,¨¨ª­°²JÁw±¯­½@¦¢£D@…‚>ðwqkþ×±a]WH??;ÿ8631///2ÿ3468:>ACÿFILNQUY^ßdgjou9€Šÿ•˜š›˜‹‡ŒŽîàŠ‹Žª0ñ”ØàŠoЋЉ5`ŠÁãrq|ð ¬@ˆ†wþчŒŠ€|„ýŠ«0–’Ž’‘{‰~ÄP}†‹îà·„…‹‹0”#`Žûކ`ƒ„‹„‚ÿ‰Œ„~†‰ˆ~ß~ƒ‚yyðŒŽÿ‹†xmokhh•€q*б~4зa𿙞•…¹‡`…wÑìÐÐ0‘а¸5Pü`"„xz l}h”_]\[[W Õ^tða_°i y{ûolœauvy|ýƒ¹€xtz|ì}p }xè}z¢K`uÐÆP|0~“ €c€€Ë5²²a€r¿pèôP8‡0ŽgQ”•™nY ¡¤‹P ŸG¡šŒjÒ…À¡ ‡ìÞV@‘•™œð ›;ŸžY𜘛ðµíƒprwÔ oejßonfhlÂ`jlþichmni]ý_§lkaahlýpVrnuzwt~/Ðzx~yt.°®ìQurt}Ðu҂󄇆°”Ž€z>:‘“”’€`ᯋŠ,` p—Ÿ˜šœžRðl`ž¿Ÿ¢¥¦¥¡ž0—u—e ˜AP‘‘Ž`ù€ãà¹0yxvuwx­ðnm 0ž@S`h$¢û0dÿ°S`j"Àßnquw—8†Ñ ±À¡‚ðn@©@·~~ăå0aAíPzoum\X™À_a8ˆšÃà…š òÐ>М÷¢¨­©±®®¯¯­­¬ªO€ïð9@¡õ ¡Ÿð¡›œ›˜ø‚°Á´}|zvçrmiPN°WSQOMLMNOOÏÿE=ADHKNNÿMOSVWY\a»eg @ptu y¾& ‚~‚ˆÓ𓕘œ¢¦¨«90 ¸°BÀ¸°A@ê ˜q šy—}`ý ‡yst(À³rr=\`†‚Šp}}t—ðv€„‚w0îá~|„À‚‚yîÑ‘€våy}‚~°z~„‡„ÎP‡††‚„ÐÓ ¨ xsy„ ÎP^zsqxê)@”•—mP·’‡‰ËQ€~<°yô5°q‚ƒ†‰Õ] ½ÁñÊðÄ0k Òƒa{è2G j~@ed÷b^\\ ^ZWTçQONß’@cfj¸a hÐÐŒ‘•iP•ƒ’ˆ ÿár w0¾„µ~ö` °ulý2]žp_behÏ ¤ {Ô8P‘•Ž0¢—Ñ©¬ô“­²©x ©©§¥a¤§Tðõ y`——äå‘ðЈưe€uqn°"ÀÎ@kkéAcäPb'P’`mnn‘qqa öàÕ öàrpWrvxE¡pÚPi‚@‹nq€€]3ÁÇ ‰©ЃÄŽŠ0ÝŽÝ ‘”»‘§‡yxzùaw’ðuýoypzx|yy}û}y4y{xxyíx¼0~~Šp‚†Œ{ŒŒ––âç–—ªÀ`’—ÿœž £¤¨¨¥åk°‘¦0¾‘”˜¿ššš—Œ‰Íð÷•›é𣠛ù™6¡€Œ€{vqolecdŒ ci–"Õfü@db^±!Àp »¡{f‡Â€Ø0b€mІ5P~yº ãBô@1m¾„ cccbaâRÿRSRQRQE=Í?ÓÔW]¾Pa x~‚;€l GàUAà¶ÀÚñý›/𥤤¥¦¦=¥û0¦¥ž‹M|ÚeÐvÐqprpoqö(Áy~Å Š–›öCШ©»@­¯°­/@eÁ°­ª70S"€OŽŒ‰…d€#°v@°Žu#mifl0ŽÀóÀ\΀flr§0ðvv&Òt¥ v1P³¡lðWtrl+nÌmä`?pmcZ[ZÀk0'eglp¼¢‚  Âöᑘžù0©¬¯±þxP··¶´²¯­ÿ¬«¬®®®­ª1§ŒQQQ¾²ŽàþŽ |yj_^\[]``bccÀ"v’ AÆñ$1™ªh`å™y`™I0tÀ’ÿ‰†ƒ~xo^WÿWVRNKHHHGGGIëÀÀá¼P¾àanqtz;Ðœ¡50ªª©[¨©§¦‹Q›‰á•“Pè@¼‘Ðzvpßkiif`Π[\¯\YUTä°PîÀU÷[abÅ`hefhjÉàÁPuw¦ hpóPuw|«’ 8ѵa\š¹€ˆÔƒ'`‹€VpžaУ 0«á°†þP1 ¤©®°²³ÞPÀ¼¿À½WÀµ¶^ `··µ²¯°­“ÿª¦¢ œ˜“ɉ ‘<±sÒÀ¶àa`H€`@%YÉé°NàÁÿEDBBA8.4:<<<>AEñ²öK ZYˆP^bgk)Ð|…ŠõÐæCqt›àŒ°™E€›”†íBöõa€ƒ P”——'’†…°ÁIðÐáðÞR𜟣¦®±]´ZÀ¸¸¸î€·aÀ÷¯¬©UО›–^ÿ€‰ƒv mP$,€’ jPo}0‚Á'}rf1€Éàk"Áƒp^0Àuo°Psôàÿvwukhouzwyrv¢À‚~sààý~Á ……|ƒï„~zŠ`vvs;kmtusì eÐtsmomko@ìyq¨ð†„M0ŽŠ„Ÿ‡‰‡~z$p­†Ïƒzx}»PÄ ˆ†÷‚~„Ý ‘Œ‹;‰ŒËP†‰Ž¬xRÿ}{|€ƒuMx0‡€P£Žw`‰°… "…#ð ¿‹€ttrpÒxÀ,°Aò°á¡žaˆœ» '€ebaù@Ö°f `°ð¡ÀªáÁQ‚nÑ‚2ƒÀ{"p ÖrŽ B{à‚,pp{ þÑrqg_dfjwmorÐrhkÐ~£€zmeeceñr )ÑÓàÒ Û Lð’–“ˆà ‚ ð 9àÔýÐ!ñ”—››zq u¡ª«¨£,ò¨O ¤ž”þ“—”‘Œ€~ƒ„ºÿ{sqxzrlosumk~ à`±0jïdafe¤@jpt7tkeijá€V€øð¥ÅQ„„…ƒzBûÀwBÛ¢êA°ƒA<{À5À††‰‹ÉÀ·Æ›pˆ‰Kðspž‘.€ì!² SŠÐì`$°¤ 0íx0}þà}•€Üàƒµð‹l±º%Q’¿ß l!– þ ¢€q`_[VS_STVWXì_ÃàýaÔ0lpuyz}|‘`æ¡¢¦§©ª) p¶°‚ nÀ ‹†€Ý{ˆBpnm’@omkljÒ€dñpigÙ˜¢BÀ@sucpS„‡à  {Àþpi†ûˆ‰ƒ|ph™h.a\°cfá€hÃhiÀ.À¤à¼Q†‡÷‹’qa–‘€{È!ÐÈp¦ð‚Ð00 ¤ß¦¨¦ž¡°`¬¯ÿª£©°´¬¥«ÿ¬¬­¨¡£§¨÷§£˜–`™œžž»—‰²‘‡‰Ç‚mx€Czqz1fgmàŸsvrlq,}à”pà Ôs€Àǰ¬¡¨À|meà¸0Ü€êþoàruy~wt>BrmqruhаýqØ€uutkgnïuyys3z|yÏos{Wà¦à„n‰€€ 0rs;pûqo© uxvoqþpyy€†‹ˆÍQ€wð~„‚ÿzv{|~„‰_ÐŽ¥pŠ}àõ©Ùƒt€s’(ð¡¥î¢€Ÿš¡ £¢š„j_0“\Ð(uP±À‡¡~Ò°°1P¸ k@lÁlŸ õ!èQ}ࡃvŸ0~}xwt'À§nki)‡0uBj'\W[ÙÁa`^+!™¡&”p†‰Æð«ŸùPÓ@ŠNЬ§Ð©V [ð› QÊ`™—°ÐÁPp!ÿqeTONLKLÿOQQRSUWY˜÷@ÝÐwtvúà`„=„ËQŽ’–˜€`“Ð]¢­Ð˜—•vÀà1„'Eð†xPé`!‡@wŸvspliÜ‘êsÈp‚@ ‚ŽÀ¨[¬Üà‰ÿð “¡V=|5¢à}|yuuØà  Üà…ƒ‹öп³„LzàÞÁð༰I¡ o!z0îaG’Á€{s 3QAÕàöá©PxzApyx¤æÀ}àÀEð Â ¯–0‡‡ÌÉ z€‘•]0™˜dŠ€YÀ'‘èAƒ€¹À*:‘{tàz |¡Ð tøàS}Fîà ðX‘œr onlÖk˜Õ`€ ßfjx)rrol• o:À裩PùvÈÐ |tc`c9dŸPmáqon‘ðRþø—šž¡ ¢¦«¯±´¸º· `¸ºº¼»º¸`ÿ­­«§¤¡˜ž(Pƒ~~ @Ñtcj`šP™²á`loÙ€krutmov¿Àÿ}}vtyz|xÿrwzzvmnsAvMòàÉpÛ€— oPÆÌÑ{qGá?À!€‡‹Ž’••vQvPëAŒýp‘0ŒŽÛ j€þŸ«¡¡(@ª–©¢€§Ï¦£ ŸZ0f!Œˆ›‡„±Àyyu@Lpsßuoa^YÀ1W[{^`€0hjotðÿ„‰”˜ ¡£¥¤š•˜•< _’•–”‘>0‹ó‚aàÕjigf|ØÊ b`[OL'ÀÇMQW–‘Ô00"…ŽgŽ…ƒ zqj–}˜V𠢤¤›\ÀYìà:ÑŠ„:°{Sõ(°{B|}‚qz  ²ðô’†€u{Ñcwuz‹`R€€¢q†a€µ? •””Éðë‡v­Pp˜Ðihf*Ë gÙÑrØ0|| zâ1E0—”–š€›˜—ºð”‘zp‘Ù’.0ÒÀ‘\ÂŒ‹Óˆ„e0ó qØ`jlÀá`ã€Ë€ãƒ•Ñ´1b^E]ײYdDÉàèr;Á‚ÃÐoü@=àP¡!¥Ü‘`UP—šœ¢¡£ÿ¢¢£¦ª¯²³ÿ²´¶·¸¶´³þEº¼½ÀÁÁÁÿ¿¿À¾»¶³°ó« "PÎaˆ„{ÿoffa][XVÿTTTRPOOIDFGHJLLÎÿQTVUOOTWëXXÅàa3puz€„¢pÍ –1ÿ‘"ðA0~†ð•“‡zsQ@ãtwÉÑ©±6 ”™ÿŸ¦«®ª¢¢§¾²`²²« .ð ¿Ÿœ—˜œ™†ðŒ¿‡‰Š‰…}í!}wynn qqh^üú@R€`WZ`fjpvz}x»ÑÐ"p‚¢pi“‹}xá„ ò€€ !"Ó dÀ†È vt€~ŒaUôÂ^iÑyvob\g@ à`mrmp‚‘#±‹EÂð#1•‘N0ŠŒƒ²¼¡‹Ò ì`£B nò2è`7µ}uÒO‘ 0y`yÚ0*Ðá˜ÀÉP!uptš°–Ðnr~ nþ¡€…‹­ðý’3ž¢§¬®°ÿ³µ¶µ´´³±×°¯¬´¤;¡¡÷ ŸŸP–“‘ІƒMàÜÐ} ÿh[TVVVWWõUsU]aVZ`b¯bb_b›Pg™ sÔ¦ ½€o®Quo@tuãnhäb`µA“„Å|oÀ|mÐqˆ‹ø;0ÑÁ< –™œŸ¢¥©ª©«¯´Á`?°­¨ š”M°}‘ÿ|yvup^Zý]j_`adinWrtw®AˆôP—G1 Ÿæ ¸ðQP2 ý8ð~qliec?`[TPMI:P:QåK”PYg@žPlquiyÒpжB˜›è §œœž7 À˜æà7ЉŠÔðŠˆb°àø=!@…0polidÿ[MHIIIHF}F\0MSX\a<€upÞ }¼P‚xwpÐÍc°‘• Pހ𓸠å0¶@•—™›žÙ¢u°31™˜MÀ™•y‰!€ÿrƒ…‰o‘ë‡<Фp’š ß£¥¥£›(0š™’ËÀ–Àtð¢Óp'€Á@Ô0Û1`°[«wl Ó’élæ€ÄpÍßÐó ÷lch¸áxzxo…lÖ oT0–Ð(@Õ twyzŽ y%Ð_àz0h˜ÀЪ …±pŒèá›èà’’´¼ñÀ«à  óÀ§?xóljÅ€& hffhmq®PuxÂÁÊ¥pê¸@š©`›RЖ’‰ys­P× ¦°Ð\࣠˜ #ñN°ƒFðÒ2‚Ì6¡aðvyRð°{rü8À5@wru~€{_z~~wtÚ |°FíPzvÿ‚?«a‚*†ˆ¡îÀÐÚ —A“–—–‚Óp…>01Š`Á`ÀSAŽ…Èa˜np)€˜ÀyrI€,…³ysJ‘<°‡ŒÕð…9},  Ðzxu5@Ú{{'p„‚‚†4к18PŠŠ‡ÈwÐ̰Bаoè€Ëp7@ê`†?0dÀ­ˆ?09Q^ÀÀ@1ÑPÔq¾ ^°€8†!|zíÀÈÒÁ«@qÃswjÑEQ8@tÀvtàϰ°Ðð_ Рkh^Z^_acó`ðò PùzðÉ𗛞ŸžÿŸ¢§ªª«®°g±±¯i ú°«©µ¿¢Ÿž›–‘_À‰¸fÀyàiÀƒ~J0pÿhZWXY\_aŠÔÑmý¡}_ð$1y°””°ºqˆðT@¶pe€°B0 Àï€ØP……°Àz‡tniÞ€ßR€“ gÊðp1AsVð-¢zvNñë¡tÁÐrNp]à9AJ‘sñÎR›a'pëŠ5P‰:ñ¹°7@=‘(€Øp¶ Ñ@ƒ1ÕcxÇqG ~€}p¸Ðàš ¤QP+€°ŒŽ“þOМž¡£¤¥©«ª§¥¥§«—âVžà¤Ÿ†0˜lŽhQ‚õÀF Ûñr¼`¾a`þåpbUNNMOOïPRSTX\b'hkní$wrÐQ†¹Qp“ÒÂÂQ_ÑŽ~P‚{m#¡åòÐq ssmR{ç²!¨€áá]…a˜š›QÑ–ºð™•ž wŒ*xñ„ ±G@ù·Ñàðh«`j§kmpz Ñ– ·‘”–v .0œœš™œœ›™Œ„80€‹R`ÄÀ µÐi7ea`ýð\Y0ÀÍ Ì þáfk.A `hbEeúâc§pç {·QŸ‰ŠŒ“ß!áŸÎF€›˜˜á!â ˜•Y‘‹M²Œ:ð‚MpéyЯÑqÚÐmh_Ì”ofi0çPmioç ïÀ~!O°\@³•>Œ…„€|5sÕbïÂíp… QB”NÀ/0æ!ÇŸ ¡5˜0s°¡ŸãŸž.0rp¤@•’ŽÂÖñ}tƒqÑÜÐnl3lmû/@qoApðþj‘qpmjifdÜÚ‘†“hjh€a_þýð[ZYWWXZó]ba.@nnpreà|ˆÑa  ì°A€²€=–*𘘓† p^``Ž Ö=AªQq‘“)1ÿ¤§ª­¯®­¯Þ<`±±²³® ²¯_¬«©¨¦'  Ar€—Y€§…‚}aa_lhZMK_0Eb0ÿKNQRRRQQÿQTX^dglsËza°‡îq~¡˜›10<¤¥¥r°r±* Î+ ™”ø M†‚ÿ}xsmf`\X{TUJ VUVU pÿRMC@BBDE÷HLRR _cjr|wPA€‚wwç²®]ÐˆŠŽ`ŠÁ~\KqçÀ{xp,köàê0€oñ~8Ї‹ñ“À‚1 ¥¦§©£©¡Ã‘—€a˜ !“1à˜¿0†ð”Ë–ÕPvAï2z Sàûà¶ahʰw{0‰ùŽTÑ“‘Ž„wFâpsqñÕ‘îcƒxà‡†t•°÷àÀ¢Õ ¼ŠÁ’À|oj\°q$å@>@}v°Ð~Úw`ý…ŒÀ~{~|yzvtwupŸRâ@õQÐï@r0uðâz?°}Ç€yv;q¹A¥ñ‹‰ñ‚ÃÁ<Й"•šž  š’‘‘ZBå î n5 šŽ§òŒÄ€‡àŽ\ÕzuuÁX‘fàÎtÐxoh÷c w}q~ *Ч}zmk°;omb pnmð†À\£ñq‰Œ‘bJÀÀ¼€˜VÂ_€¬1‚‚„Wa„ú0c€ÐÝð$€•kS°i_ i“òY dQgY´Ó‘x•Qv_QpGqJr¯Áè2|qäñihhkð€ð.“ߘ›œž0ð¦§ÿ¨ª®±´¶¸¸ÿ¶µ³±¯­«¨dJ`Ÿ2š`ÍðŽŒ#ð&F‰‡Ê€´ uÔ ÐbøñÀäñki2@ñnêðcÀhhig‡c_] ”€ ±+@l7Ðkl\°à4p>A QÚ!Œ”^@cA5ñG§ðDŽ1\@”í K€é¢ ü‘"Їƒw€±S0¼`ð€[Ðr<¢ ‘"žžá[p¡àI ÊÐã™J¶5 ¾0 âD0€À «Apfca»__q`\ZqSßQMKJL¡GFÿFEEDB@?=ÿ>?@CHMORTVŽad0ö‹@$žRhà„ºÑ—A¢ -ð÷£¦§ÜÁ·¹º¹ÿ¹¹»»º¸¶³÷²²²=`­ª¨¦ã£ž…0…1 0˜–’ä» E0€_ Ðk]T÷QLI" FHKO÷SX^”kpu|ì.$•—а¢¤§~_p«¬­®¯¯bâU¦¬€˜ÇðŒP‘tõàÿb]]\YRNPÿRQKHIJJEÿ=>CGJMOSçWZ]x¡iko}u’@ƒƒˆ‹‰Ÿ+‹3°¿ðˆeÀ– §Œ‘‘Áp±• 0—÷”•’Œމˆ‹žêЉ‹Š‚±‘ºÐ‰ßŠ“’‹ŠP…Šõ°ˆ€?†‹‹Œ­BðìPj@Œq‹Š…¥}¯ —PpúÐ]^]]_c` °…€DqÖ!þ`¹R@á`Ÿ ™@’Ž!…PØ0ÝA˜`чN„¶°šQpü*Ñ€mg]YZY™ZÐðÇ!__æ€op^±Ä°ÇQ£ ”•–4ñŸ×Áÿü𧧨¨{©¨lp¥£Ÿ˜Š`/ŽŒ‰‰ÁPˆpå12%ÀwÐ? liµa`.µ`fecæàe‚„à§p2@Ö€b"½qpib„‘ö’°@qYªPþ? ”šž£¨«­ó®®ip© §¥£ œ *›˜•Ÿ„ÜpA§{rg}€a_Ë```g„@,ápuoy~„‹â—œ3ý¢J ¦¨©ªª­·°°­F`¤£>žkœ˜:0ˆq¡XÓQ­ðX€€Àxq þ#€gdb_[ZZ[]×ð][`{€¼…”Bqsoe§`1`Ï sxòsoq`Ø!“„~8@ÚzQ: Š‹…ë0<þàB í"®óò§ª¬{«~¬Îý¡•‘NY`‡†“‚~Pw`†W`‰RŽ.KÁ’“–Š™Ð¡²›¢‰aPÌP/ð ÿ{vrmcXSOûKGá>=?@@ÿADEGJNRV/Y^cg0zK°0À•ó±þÀ pW`à}rQ1omi-Á ÐÖ€÷me]1ilprûnhÞñvwrrv;{€º0ˆ†€úPrÀWP¼@pÌÀŸàñ¡ø:ê‘õ‘¶¸¹º¼ÿ»¹¸·´³²±ÿ°¯®«¦£¢ŸÁÑÃp–`=0®P…Ï{tnjùÐm€]^Ï`bb_È –[\Œ!z€n`k AÖ€$b¦À˜ÚLqd€kf°`}€bå`‘ _Š€¨ptx|4Pp¼p”0` ¢W¡ÍÐîK ¤¢¡ÇПœ—¹’¼‘Г‡²ðŒüÿÀB0ƒ~ƒ„ß~€zu@pjnZors@sp@žp|}{y`˜PxùxhñšPvssvyÁx¼ÁÀ\ÆÁÈ¡ˆŒüÚ!× ¤¦¨«©¤ß¥§¨§¤¬€œEqq顲ŒRjAÊQéi{èQtÁv¸@~¯ ÔÜ@cuùo@ge÷_TO˜pKJJJ¿KLORSUœ^›diq`y¹ÐÈPlϡᡖ”…ˆé°Î3P‡€xã`7~zŽ À~E±® »@ƒË‚~Áy;!@vsttb…=»Pgв ;€wÑpop/1¥P¯¡YPìñæ §Ù ÔÈÐRB‘šd€“xpŠ  ‡ƒc€žÀÑ'€Çà_VQSRSÁ0YâàM`Vjn&`¥Q~*0 q#`»`o©#1WPfÀ‚¾°ŽÙ°LÀFÀhA»PŠSבƒñ<1P»p#PÈœVrù žF€Fš—’‡ cm{ÀPÐN”0ó€eÀeÐðÄ€ö°‡2ÑPºÑOÀ ð†!}üQøŽpXrGуl8±Ðso°`ddÍ MlT°lmôPu°~8 ‰€Q¸B”ß°*‘€š‚£€*0Àä`+rlëPžÀqoPsràp¢À³Ò ±}w«ÑM?±âña©ðœ¡ì±Ž‘@¤Âç S€hé!žp#y’ô°ô…zol*€óhg²a.€jh`[i]rðVfÃÀqm±Âq°v¶Q³ p±{Qt{À×pPm­0m—€Èçp€±Rp¼ÖéªY«hp¤¢\ ÷`#~z ÐóÐqog€@ ApØ€äsö€‚~¾ða`ñ™ÂdÓQTƒ…Ÿ€\ñAᛀ—s"[à¡ìвpîmQ‚„„‚—ƒµÀìS‘žQ˜ÁxœoàˆP—€øÁˆ÷€up"°rpiedb]YYXWq]àVV‡ “ rñe4À!aj’ÁstSÒ÷11ƒº`P½aŽ$@ï±´ýPÊ@ˆy!‹‰ì𓽑В••ðœCàÚ°ððððæ  —ʱհŸÑhÀ-!¾€qquÁ£`‚€“Á.4 urnljéàœq*ágüŸqÇ ]^bcedUe6ÐlípwH€ès…ƒañ°ñŒ“Gà›—ð‡…‹ñȰhÐ;˜œÈП›”Çbà°t0_À.€w¤­Ã8ae°:µÀ °}zr ЈÀž 0`km$±JıوžãÒ¢›š2°ŽŠƒ{Yiðt°!µq@ƒpq40rÂñÐEÒ ":°k› -eP4À8À4¯ð×Pˆ>p–šKáÿñ/ª««¬®à­&°"°~'±ª©¨¤ ž‚R"‹P”FÀ0’Qƒd°Ÿ@ zwd€tP‚€zÀ±liš £q‘@`²€`€ÊSI|¥qp?Pø‘çqo¯0¡dcc’P# 7 H0¾P‡¤<#?À‹þàFÀ]Á¡uѵðˆAˆ?àÝQ¾sù •¦ƒ•“÷ÁÖ`€JÁÄ@…ÀãlPøp³ñÞS}Q˜–”üà‹hpt ™PD€›A¸ ÷aövyÐißb[YXYÏð[\àp!`’À#0 ±x€Í AP‹ƒÎ¡<@JmS‚À, { Åaב{0Ⲅƒ@A¢1à¡9ÀvÁ~ðz±d„ó3 x§€õ>P°|Q°²pA4"ÚÀãqqlR ‡±¿Q‰Ä£0¸ y#TÐñvH‚¯ ¸Ž‘•™¼Kà«­¯²Y!¸Ÿ¶¶¶´±h 3°œ™–’ŽÝ€ä¡jù| P÷‘qoh`\YXXXYZ[—"òÙñeB°{ƒ‡W`õ òðJpÀ‚U@ÚÐðbpàp0ð‘zvroˆakjh <!q¢ ¢¢o>0ö2= nAâ°‡1Áƒ›Ðß@ù“mk„ë àðv aAP±¡‘y•Dqk«®¯° àh Ði0›—¼î1Ú0{=@yuú¡cbÿbcc_XUVXÿZ\\WQQST·TTVÓð_`¥°m# ›Aâ2Sæ%ðÝR<Ùa±€’•–‘"á#àÜPŠA- ùÿÁÏ@7"Ï€|uìqŽ‚y|¸ v ‡òž@†ÂˆÁïuRÂ`‹’z ßA ަÀ‚ämq‚¡/„€ˆ°UеÂésô g‚Œƒø¹ç0Ùp†€wsqЬPQì¡«At£}‚Q†Â`˜Áä@“Ér‘$Pʼn|1rdâ1v‚oiÁ ‘2r‘áQ”¾`•žÃ‰–‘øòµ “ކ‚:9#Åâ¾`Ї„zÓRò/€â¡tZÐ [°¡‚SPž‚`pnia\ZZn‘!_¢p!a>0~Ë=–ê@Ÿ¡ šÏaÔaß±†§À? ¦ÀÕÐä`äa€ðX€n‚«cÙ@œ`k~qÖ ƒ¡bà"@&çBm1ò €ž\A!žž™“c‘¨¥À!yòѸø‘opkea \ q\‘a°@}¢æ`‚ñãA}Q,b@ÆÐ——€PÕ€§‘÷ðÀ‘šÂŠr ÓPŽ¡€Žà ª ô’W°¤`UPsÆÿ@lgÄ "¡¥rac¿effgfd3àe€MဳQ*pBR­b®à…˜U0I ,›œàÙ1•,êPÒ‘——t0¶(DÈqÕaÂpr ¯€ŒÃñƒ‰†)ð|pTü0#ˆÃË•”‘Û°à°àà…„€xÌ¢y‚uRÄ¡±±y^œ2~z!sñ ƒ‚¬1ï q¶P%€Ä㉃} qï„=AðC‚~ÊÁ‡¼/€y¤áàÑHÐC@!@Ãa’“’E–’Š”ÀÂ@Àƒ£0€á š#r‚0­àŰ!A‰Ç„|uæ èÐ#qpr;@‡€ØPŒƒùSÊq0õ°ý±Ú²Úˆ…t£±a_á³b¸²°3_P@‹!‘áùb2#!“`wZÐèÒa.sn̰"ÀÆq3‰·NÑ~}zaÑdAÁz˜`vx¦ð$w!öDp  ¡¤¦¦£D‘¼ ïBÖŒ‡€"xq™!ÐÔ@'‚¸q×ðAͳٱ)/’އ„à€{yBõ¡îx±vqk ab_\Y_;àr†Œt±·Qã`ëÍñq®Âê¤ð mÁ<À5BÍÒ‡!×ð¼kòlƒxrñ£pî q4 7aèòÛ ‰'’Åpî#úPÉpÏpß±D{àËч¸B N°p`0‡[‡ðoni  gf· ‘'r¦ƒ¯ ë‘ ¼a¯€ˆ‚òëáГ`>Á”àÀRdಀÃp÷'Àbü²Þ Áx㈃N± `€†‘ð/p±Áx S|gA늎’“t`&ï°ßp û€lòí`Òðü0Û᫇ð’ÀõÁ¢¸jBBj0{xtAòkihh@©°ö`£ °ŒƒyPb«ño Žßp‰…}õ[° pÑtÎÁùs(•ã@¡¥{§¨*Щ©¨§á%œô@™Õ@°ŽÞR @íšÑQ€|¡òPxz0ll b%aDas…w0nk¢¡ qð¡È!’ð“∡ˆ!¶åËÁ‚ð‡üÁòIJÅaðR{á(´¡Îç ›n¡‡s ¾áÀoYà&w!ã’•u™º€ ¼€¦¨ª9€¨Ã¦¥¢Xq‘ÑèP<½ðiñ„{uü‘ ÿfd_YTSRRQPOPQRSp€ÝUm_ac_bÖpÑnk @o]rplê ì ñ¡ýÜò€üð Â͒Бp æPÝCˆ€ªáIÀ‘2Ð}ŒQA…ªîô±TC‹£h ØðÈb…ªñ‰ ¿á ÐÅpyÑObÇrµÀòÐOÀT‘‚Àª ¶2RDÍàîU’‰jð¤P¨S€`Â-ð7PÀcâÄŒü<@ƒ„„„ƒ€}PèÁABu‘ÏRŒùð‹f…áýpÌÔ &ðP7QþÀŒ\X°kh ¡@ @x„@¡Â±Ó`ÊÀ‘!ADƒà Ûƒ×ñÇ1‘’”·£^pÂD°iðÆ#}¡o2æs6£{pÐWg „pˆ`}ý€¼ó2aÀwR ¢Q×£°BŠŽÏ‘•˜›gÁæ@ŸŸ ¡¡¡ Xq»€K€މ„±Á›Ñ|Ž@ŠqÀk'Ñq²iÓ„;âÐÄ’ù‚ïÄ“ÞbÚclBÑ‚¾°pPôÑr!¦€{±¤jpÆ‘ð‚ábAAÔàÃÑ›rqÌH’¶‘¨€ùpubùq›Q+°Í‘àa¶EÅáPÑöÓKà •DÒ™FÐKšš[á’«°€@À…q¹ÀkóaÂLPgf`ú`(Ñš1n¤©S’’áÒ°à˜`Õ…AKbÒ÷“Ä‘¢^‘ŸCq°w±¼“{ä["V:Âp `¥q‹€¾s…ÑüÒF"y`ºaA÷POS0£g&ÅÑ3S‰bf µB€ÂÒ¿ÑØáQb¤ r!†¥‘¥‚N%ƒŒHá U°m°À 0÷àcáѰ£qpºq›°B² סѴpS&2ÏO€ê€z°÷°”up˜ÒzÑÓñ=ÀˆA8ÀžqXó=R Ç‘ÜÑÒ¡cÓɱ)S¢“°RB¾ó¸S‹’~˰¡¢(AíТ—¡ñbÝÒ"Ïbºm!sCç¤AÃîRÙ ïåòk!“1©Ññq…t$‘s ô§YAþá%àpS¾‘Ö³àCã¹’8å!P1ó@ØÁÎÀ¼b…jÙ’ß‘™QÑ” ‘ ¹‚#€'`çA¥A®ÂrÐxÑ7qfyñKÞ7†3Á3åÒí@Q2;ƒ(‚Òåñ²‘òæ„„‘†¨Áb‘Ï% #¢‘'ñWœÓ™‚Tñ¡…@Œ3f2CO˜ò,BpAm"§/áiÑf‘5±¸rরw#킉†Qðñ§±ÝLás±±‘ö‡ú²ÀBzÐÓáyCûQl“t“!2½_°„ⰀšÆð°à ÀMñÒš±qnL€âÂd)“ÂàšÐ3ò€;’7²Js6ŸCU±6ˆ]Ñi”a¤•rãSAÕñ{¡›±~a7Áá-B«àձʠÀRtu5O"&€bb5Ѐ’³EƲ4s~15òrs…ý‚ý#¾¢3ö±ü ¡áÑsq˜óÀA±±¬qÂÑDZ›ÑÂá'BìѤᛤٲ求L#ì׳zQuá™Ò0raÃ_G‚kj Š)†¦Øàa¤ "±4ÓÔžô‘"üÐíñE"'‚>á«”B4Ò •ÓµD¤öàêc0áÒÈ£¾²ÖкmÒ˜’¬µO€´ÁªÓÎc¡`ëT{ÝÑŽbâð`£C“ò:AîÁ\q ²’üÅÜe1ûPãà=<X£<'¡€Ò–ÒÓR.Ð8!5ã¿ó÷¢9âqQâ'â=¶dÒ]0¿ÒBRñxð2 +>•VB€ê’»Ý\géûbr.ÒÆo3#±äVc0#¢5óét%S²QUSxqÌÃüÈÖ?ÍÂÔ²„Ô#RäQ‘¶B_¢c#•rÈB¢PLQ¡¯Ä©PÇ!´Ák2ªDADUŽA"´ CH“ðÊq?ð=ƒ6QŠ¥šbbVc‚½ñ£Ùc±F“™ñ~Ká"²OÂ@˜ [ñ¤c’L’B²‘¤ÄÛ“þ³³å±•”ÍÒÀ—£<ÍÂhC ij3Ò¢ÐRASµÅÓ“a!ŠsEs¹Q'S2qyvtsp~bpXê"Ê#œ‘„†S"’ëc]dœ?æÒ71òd"T“Eé#Á” ð‘Q¿b•T3ÐÚ€%P b2ªQ€dÒ‹"¡34â’£;Å»¨,¦œ’ºÒÐÀƒç)u±3£­íQ×FU%âü¡JµdaVS(U¿0ºÑ¤ÄÞ‚ …rÖ·Q‹€ªv¯qË ±Á¹nôNÄ7qçvÏÑ ·PäÑ ²:æpõíSY’cô‡ÒDäh2Ü#MÂ7€²GâÖ’õÂÙb>"0H!‰“1ÖhÒF ŒJ kÒØò˜ñz1žÓŽ0ŠÖVÁp4Q7RbâV0×P@UO1$ÂÂÚ£EbË"Ѳ:¤è’ï‘H„Ó]tQó:Ã<Ä¿1µäí³±aæÑÖ!ÊS-Òk▇ĂôÑa÷ĶR:0OÂ@Pó!`DB8(Ù‚ÚÔq’~}ìá‰QF1I1…ayÂpó²óLÀÔÓ$Ra‚ر1aN¡ŽJ°Å¸E1¤|ãNìñ@Æ´ÒIrûöT̳¿Ñ.á–õ™q®Ó’…jñFTÂr|HâN#\ÄUµC>2ƒ SÂQØÁJRBÅShÅ)s óÿ¾¢ÔÔ=Æ3qêÀÕQ°€%2ˆ¢3!ÓƒLPôUõOÅ’Î%—¢ë±Ú¶]RmÖ ‚À¢ËOvZt¹tööÀ²RƒsPõsÂT]Áûõ3"¶‚Ýqó•ò­Ä)¬µ¶4íá²2"¦‚b'!ûRÄtTÐh|‚Dur€ƒï„r¤“Ô…µº2€¶Ök0¢Ss›Qiò‹xwîá¢ñ¤ð¦ð±ôñ•šr£…KÆùeºáO³¨W‘ÃSc•že·”dŠ(ÃÑIJƒÔs£B4ÏuÿFšv5°¤põ0–Od td´kóÂÿäêc¥!òGÈåB¨Vi†„Ðe½”]=ñÌÈ”)ÖH7˜·_­T娦h‚éIJÕdcÓæ÷”0È…)œj×XT®„à˜Ó½Õ‚´ÿÈ÷æÈ“hd‚4¶”4´µ%H£¹h…¡Ô%æÁHõ`TÑJB¬0±2œ5—b‚ûÖò¥4äÂ$탂¡3Êé«UâætŒ†Ks•µ×I­vñE(Ä©¸›Ö'q²¥sD&pèåi§ÞE²„“÷‰5ÔB]ã.–µ4.ôŽ£Ž2¯²å³±U>ä*#nÿUˆr\„œd:Ti–‡$á¸c­3WF¨odÊS1DðE"Aï’T¼‘©f”Á³5µôÌåXç¥W”¬díä¼”¼™o•D*™÷jˆ/jö¥Vév£ÇKv²è–e„C·•Å&V烠Åzø¬%´¨’“çå´xf@¦øäŠóZ%gdÙqýÖú;q}Ð’WóøÆ~”k5­ÖÖgÔíd¨töÅÁ—¼µ®õ8ä^4«•žÄq˜¾è#)©Ö;Vó*ƒÆ³“ϳ„´Á—†æî”Ä'ÒæpÆâ4½ö…òuOc×Ïf³Ú®ÍÄßf J ;ëÖ\ö ‚{³²õ‹b‡…÷§ê7Ÿü8Æ…7\Ètb¸ÄÓeþƒ¦Õß¶ìcBÏÈîI.Å-Éb##éÙõÄÂtp“D²¡“ K4æY7Ö3$¯@¨G>&1õzù…„W€”ôÁèÕæ–/û™sݸ4z¿–•YÀ…¦üH0 ¥b/ÇƒŽæƒ¸ÕÚ”¸”Þ8mv¥÷ôTù*}âòxç3iõÞ6f8l7¦)ˆýr‰På¤Ã€¤Œc3¤mÆÀ˜¤HE&O%2ö×ÃÁÅ×»š9ÝhiÃ+7ZlÓx:ü}ñU­Ù¾™¼—áJ˜º…Â6[hz½Ô9*˜tNð#¥y l\œºW¤J»?ˆ«¥ˆ_™-j¡åKx=ø=ù©xäÅ%Î*–†}ÞœYI_\Dõ¡ŽÒšËæ08p÷¾áV(…@I ¼îw9ÿ‰Œ½c×ÿÊ„65ùF§£Ò–0_“Ãh5F¨Å("(J½6UšhzM¦™¨*W¢ÎWKgTg7Æ…Ÿm …;öéMòTø²G~+&{&k™)zÊì¿Øó¬€c½é§:úí|î4§7ü[VÛjp½ÈcK¸a€'âRéxUŸ]öö¿œ‡¹FªéŸÈà¯Þ„ŽÚ¥4Ål¼ëšîA(²Î¢åBSÓè‹Ý8˜²TΈƒ¬êy°W‘¥tˆ”þ¥ª—u…‚É˨Ôù^§I|ƒðŸâ7Ä&v×ï"Zóf|œ™ZVtHèêÖœ×D¿íŒ)&&†ŒøÂ£ƒŽ˜ØÁêØÛJÉW´¤|/·mûÙwØ“^Xzx#˜þ\–ºuO=ïñ †#B)ÿoÍO¬«Å “]UW9´ç¿«¹Pý^¥Ez¾dÖ©ˆßþ$«&+,­äeïX›Ø¡³ÌŒ?éé¥ÏF8•óDöTÿCWÈO=N-¹J­ÚtŸÕ—»’Y›ý—ÿʇ\”O¯w×µ…‡&/ÈéÆB/°ºÌ;§Oë¿Lu?âv9¯ùr?ïqåï7ŸND“¥?s,ß÷_L圥š½Î?pÎ}ÇzëYC?€¡ÈgW/U_û[ÖªåðzܳÝoJ¸‰9–©¼úKÏpÛa§ˆ+Rio¨ÖæJ‘P‘wfKè)O™ëRn–9O?Ro üVŠ~„>MY‰fTä­z£mv?MkWL½*(ŽÏ»˜üð_ðuŒž“gº:ÇÑ=}ž$ÿPoÌ/F;ãœ3ïZçºJªá“iOa׎ÜäjÖ~yy(–›©)ɨŸco†šÁÊo®F-ñ§D_þ©Åž?có%?Õ>Š}>ýÁz¬¿_\;‹–ãoçÓ“[í:$os áìêiºm¿ m¡Ënm´ýð…ÿñð*ì_«{¾¬ýÑßãß­«/جg'¿ú†Iމˆ/LÞü«‡èß:íMËïöjÑïàïñ9™ÊÆ¿½§mïLßFe¾Eß ïÙ]‹—߇ªÒšÍï!½ïýÞ'›ÿÿjßEO Ïhs>_M¶›Æ‹š+¸íímðLìïäD¯!üí¿üœ¯íÿ|Smhho铟%/E/ø_MA/R/Ï7¯‡~¿vBä“ì&?/ŠÿÙÊá¹åª ˆ˜þ/Õ^öûŽˆó•9¸M(ÿvF{Ipÿwç¬>Øóïïÿ?w¿Î7Z­ ?…NÁïÐOMìAÈ¡ðÿDëAO±OOvKZO@_EuK_>>ü?ƒ_Í_6_"Ÿ$_&o&€ÆSo¯ZöZÉŠq888qÿ8UxŒ¨¹ÐÔÿÐÕÄÁºŸ…jïN- Cp-1ÿNNjjooo^ãG/éoˉX8C_ýhìzUCCUd{ÿ›¨´ËÚÝßÝÿÙÒɵ£…n?ÿ- %1LÿXss……ƒ~{^G)Ó5Zd3>Jdy‰›V…ÿœ––‰{x{ÿž¨¾ËÔßßäþ÷£„X?1ÿ16EMauÿŠŠ£——•{c†¸p»p¾a• {)ÿ8C^x›±´ß¹¾¾¾ÈÀ¾¹ÿ´´¨žž¡´Ä÷ÐÛßl€áÑÌÃÿÉ¿°£aE6ÿ6EBBZuuÿŠ“££¨—Œoÿ^;))(xº`¢ ™/;¹ÿ¹¹¾ÔÚÚÚàþ+ÔÐÄ嬬Ÿ¬ºÁÍÙÕ€×€ÆÿÆÂ¿°¢’uZÿMBBHPZktÿˆ’’§£¬¨¡oŒ{^^ˆp87÷€¼ü&QŽÿ7Gh‰ž´¾ÿÐÔÚàèêîêÿèääÝÙÍĬÿ¬µÃÉÍÙØÌü?‘A²©Ž€tÿZPPPR\ktÿ€Ž˜¢°¬µµÿ¨ž‰{hh_Q+J>bgž)Pqþ€);^{Œ´§¹ÐБ“߀¿ÿ·°·¿·ÃÆÂú ¡²¡­™”€tÿ\\RRR\\tÿ€€’©°·µºÿÁ®¨››‰‰hhTJ>8(gœûq773/)ÿ##3Gdž´ÿËÐÚÚäèêêûñîýßÍ¿·©Ú% ·¡²­v¢™ï‚‚}i¡\Rfßiq‚Ž¢ ÉÄÿÄĹ´ª›ÅyÇ>7 gš)P8>ÿ;CGG;;4;ýG塀ËÔÚßÿèèèîîèåÞ÷ÞÑÊ °©­­éz Ü ”à ‚}qÿmiSSOOFIÿSSfm‚‚”©ÿ·ÃÃÉÒÐË»“¹À]€š TŸ Ï™?8>J_üT¾¡ÞÏ€Ôßää_ ëåûáØ?²­©­¢™”™™} þ~ ‚ifSSDDÿI:@:DS`iÿ}‚”·¿ÍÙßÙÍËËÁ• ±›ç–xhž¢Y7>_9dc`´poo~'´m€®Ç ååÞ?Âu¡W””| }~ qæ Ÿ`IDD:¹³X°qï}©ŸÉÉÉߺµµ´¨, ïhG8/8¨(>ÿQhxŒŒ~~ÿ~ƒƒ—¨´ÁÐ_ÔÝßßÝ/°å4³¸¡²ß F³}mqM±:ÿ:22++5+5ÿ:@Sfq}‚™ÿ­²ÆÃ¿¿·¸ï¬¬Ÿ—…€žŒ{úرw¸Jhy‰›ùž:À:À¨µÁÔÛÙÝf .°åá=ÑÊ4¡Ú¡”E±}} N±ÿ:+'+!!ÿ+25:Ofq‚Â3À°©“ÿŠ„………—•¿~{dG7(f•ÿ8Ty›¡—ÿ—ŸŸŸ£¬µÄãÄÙýÊÀhÂÞØØ‡ÌÊʡۡÄM°Oÿ@5+''ÿ!'5:Smû}™Ù °©©˜Žßuurr¢À—•õŒ©ÁEÄ>_¿yž¡Ÿ£'Ѭ§ÁÇÙÆ .°ßjÀáGÞÞÞ6°oÀ ¥±¾I±}q`SO†Àß ôÀ'5ÿISq­²©ÿ¢˜€teeZZÿeuŠ“Ÿ—¡›ò×±(Ï“ÑxŒ—Ÿÿ£“““š£¬¿Íß0ÑÀÑĤnÀ  ç²²™?°F±qi`þTÒ g '‘À\°˜¯o\]ZPrГV-´zÐJ8ΓÐ#Ðߣ£š˜’¼·Í Ý1ÑiÀÞ5±×À§‘¨ÒèrÁ?°Àq»Ð2!²ÂÐ+àÇÐ2@dД_™‚‚€k PÙÐÿ£µº¹´›ñ‰åÑÂ`° >h›¡ï¬¬§¢øÐ©©·ÉÿÑèáØoÀªuá`§‘AÒ¥±ã ´°:'YÐû”à '5/Om‚KÐt=á ÿk€Ž§ºÄоﱖy_q²3ÿQy›´¬£¢’ÿ˜Ž’˜˜·Éß”kàoârÁ­ yàzàø ¡ààqfS@5û'’ã!2wIi}E°}mk§âþ«à˜°ÃÔÚԾ߯hJ78¡8ÿ_ª®¬«˜˜wŽŽˆŒ ¿ÒäiáCÞÞŸ³Ü¡v¡u㲠þ«°iI:2'‘ä ÜóG±‚`S§ä’·ÿÍÚàÚÈÀœyûQ>Ñ>h´ïµµ©¢0ðˆˆ’©¿ÒÝ0Ñoà‚áF±Æ7à­s Rñ¡­O”}m„Àà -ãÏ'+Dfoò¹ÐSSþ¡t˜¿Òèíà?ÜȤyT>dñÿ›´Áµ·©’ˆÿ€ˆˆŠ§¬ÍÝ¿ßäèßÙÑ ™=°°q}}þÁßá v¡ƒà™ Àá˜àÏ+5mõM±S`þ¸©ÉÝãíàæ°íðˆðeöñ¹Áj ˜ý’1ðŠ£¬ÇÒÙî–’ÆÂifi‘i}ÀfвðãqßiSO5+XÐ!+@SZ±ã¡M°ïiiqˆ~ðßìí×íÜÅVÑh›ÿ¾ËÉ¿©¢’’ûŽlºÄÒÙßÏÙÍÍÉxç ``r*À@±¦°™Ù Ø) ñ#â!Òð::ã`iŸà⤉ ˜¢ÃÿÒäííæÓ½‘ìóÅÔÒj ¢˜˜ý¢ÃÀºÁÄÐÒÍÿÒÉ÷™”}iNè SSiò¡ò7à­.À­™«ñ}RÐ@5m:V±‚ïáÀ~Ÿ‚˜·ÍÙ*¼|Ì·ãõò¾Úqа·õº?ËœpÇÉÉ·¢ñâPimoòE°¨°Ø_à} mfÞðDI ×X²Gð|¢®ð™ö ÍÿÚÚÜȯ‘hQ¼Pâ•àÝÙÉ2ÀÃïÃÇËÐ ÚÐÐ?Á¿°©’K~ïmiqqMÑm}}ŒÄ÷qiÝñG“À‚ñøKÐé°·ÃËŸÚÖȯœïðÓ¿8h¹Îàn€ÍÛÒÙr ÕÔ'‘ÚÐ?ĵ¸©˜˜¯²: mqã}ó Hñ)À ãfÝðfº˜"Ü ŠŽn ÃÐЄñ¼âDZÈÚl ×!–°ää-ã+ÚÔ"pò–A!°wÊò! ¡}E ÏЊö© ÃÿÄľ±œxh>ù38£Uâ–¾ÎàíØ2ÑÈ¡E0ìíâ!ÕÉÛÉ¿ ­ämf1Sî æ””îààÃÈÁŒ oñÅÙ ²¿ÿ··¸ÁűùxôôR>Ty›ÿ¾Öííãîîñ?ôññôôô¹¦0oèßÝݲîàýòáDOI@IIOP•"À­ó…1=· ÁÁ´ž‘0·àüÏ•NÁ_†¯ÈÜíïòïööôö@ïòííï®1îêåãØÑá*ç IO:€T±Î0¹pòÂá4­°™ù”gЙÁµº¨žçhdU_ ¸>Jhѳ BzDy@@ùù¿ùôðëëå²·”‚mé @:p::Ï0Á±}Á¬I— .ÀÂÈò0\@€;ÚºUáJhÿ¯ÅÓÜÜéíõïåCò†@úúûûßû÷óðð@²™1‚QÒnp@DP* ¨ã3MÑâ2¼D»ÅB/òr»° @¤³½ÈýÈà@æéíæíò·öúüWQÿÿó@ð?åÌÆ­™‚/@PE:$À23@9A2‚zÂü°±ç²ÆÍÍÄǨŒo/R»zá8ÿQh|‘¤¤¯¯w³ÅÅKPéòøVR-ÿÃQû÷ŽA­ „ÀÂnO`S$ ~Rï"ùm‹!-ÀÂÒÒĨŸ~cG3)º}H 7>Thy†‘`œ¤¯½ÜíòVU>ÅQóëáØ²yÑRv!À25ÀD`fñQÔyÂm!q\°ÂÍÙÄ´Œ‰»}Uá>ÿQ_y|†||y}h`¤ÅÜïøÁT-dåÆÂ­gÁn}I©!Ž”’ÀòÃðf© ‰ ™²É͟дŒh;gnnA>ýTa†|y_TTŸ_h|¯È$b’f÷À2`§ð,@™AœBW±m€€Éà’˜|¡!û }ÿ­·ÍйŒxãG3dGy·~`†–œgœ†› å`œ½ŒjðóA3`ûA-ID@@ýDÚfm}€’’c¢©†p+ÂSieÐའË`«À9|îÐJ_y½‘²P¯¯¤œê`yg|–³#cbwóðœ°ðw,NIb™’¢¢å©ïqˆçÂX²˜°¿Ÿº¨hC¬ÀÓnQÿ_|œ¯³½ÅÅÿ½³¤œ‘–‘¤³ÓéòùÀUÿdŽ@ÊÂ­ã  2+ÀÅ`ïp°k ©Žˆå û iß}€˜©¬ÄA;3ˆé°FQÅÀ#€ºp¤ru@ï%búhðåå?ЪñD±Å˜À·3À··ª®€: k¸ˆvÐ{Ñ^€8­°r|†‚ÓÓ;ÈÅ"³½Ó#`½Rþ‘cüÿüù÷ëëÇÞÙÙàv£º€ÊÊrø Í Àˆ€k0?ttz„…üQ7®‚~²TµpHRŠ€‹€·Qæ·ïòù¾WÿüñèäÝÒÍÆ¿táûÊÊ§ÐØØÝÙÒßÍÍ÷§þðttÿkkeeuanoŸ^G/(Ïžƒ|㜤µQÄ•LQïòøüj“XRüüúöñêþm"ÍÍÑÑÞáåöð‘äßb°ÄÁ¬¬ý“ÐeZgaXLN9,#¦¨SãT/h|¤€½!€É’¡Óà@xA½SÖ“ùâêx¹0Ÿð0±ëêëê.°ÿÝÔ˺®¡……ûsa ??-,im:Uè°`°P)¥˜Ã’MP@øùï@«¢ù×öôô\ ß ðññßîêîêêÀ äÚÿŨ•~~jjÿjN?9-$Ãw¯£W}``‘–±Q¯³°°ð@yGÿííàÚÚÔÔàçèêê«1½¡äÔ¾ÿž‰ocKKK990,گΟZ7>Jï`€`‘‘w‘œ¤&‚––– `èKQ{´\¾‡°Ôààýêª2ñèêྞÿdKG,,,))#Ù¯N¿{aîa…yÒµhÛ°€`þ ã·–¯–œ›ÀÓ íŽ°ñßîãàΪl€/#ÆÂt¯µ¿?Q78o>>JQ:ÄJ>CÂËJTJÂ_í`LÃhxùœÒ ³1àÚ¾±‰ƒ^;`mÃÏ…Ï¥T¿(37873¡Â(lÀ¬Á(7´À((«Áú³À8q@†›¾ÈÎÚÚȾª‰dÎ`‰ÏçÏ%Í×   ð0ÂÒÐ@P(3>_h›±¹¹±LàG7nJß\ß§PmÚjØöD *ÐUhy‰ydG8:ß°²ßÄßÖß_ß(ÁÀ_~Û°d_C7)£ßàï-ï?ïéßûÑCJJC;>7~~ïï¢ï´ï…¥788¨Â ïèïúï ÿÿõ8ñ ïNÿ`ÿrÿ„ÿ)Ç ð¯µÿÇÿÙÿëÿðeÝ ApropÿDATEÿ7-08-200Ÿ5, 17P5N{AM<doo6{en5ORIG=Ý ].bm8A÷¤BM¤T==~=(=4=Ý7=¢-&Œë ­=·Þ ð0ÿ003336ÿ66LLLPÿPPYYYfïffÿæsssÿƒƒƒým0²²²Ì÷ÌÌÃP¿  Ÿ =ÿÿ  Ó)=+ý   ó O=þÕÀ w= SS\æJ—¡§z\º´ÁmÁ [c –Ýcÿøèý§  !##¹"m › ÿ =& 6!9!Ý›(G!ä]&T#; . D .R$Z$4D$Ÿ&T#[  ·…#¿$R#'1 F +/=/O/a/s/…/—/©/»/Í/ß/ñ/??'?9?K?]?o??“?¥?·?É?Û?í?ÿ?O#O5OGOYI$!Œ@S0—E¡B/±ÊAïGÚE ÁA1 Ÿ‰AÈ£BDR˜C Â@¥AÊAé¡ ™ÉA‚Q‚RSÃŽT!‡BžT÷(R Z@ ­PžTZ@èD0ÏP0P#!ŸQ A[ˆ@¸@åBéCøúSÜeP Ž@RbûR=Pãƒ@(`#  Ž@ åFBaBaì[4PËAnÇFa‡Bca Çn`[s`À1P{`pbÝÊ@` 3a–c(˜@Ê Q c­P³`— ƒD ÄbE` ƒ NZAàdt`Û`? YaK­`¡ P bƒb°š@©a`qb=p¬aæ¨aR p°Wpƒ@€d cQ»QbeRr °}p§a†3 b‰@¤AÒ`™_P^Q R ±‡QšRCR ’°þPŽppRï,° ÒGb9q¿°\Ç`ÒpÓA$ m‚“P¤œP€5G6Q sÇhute Yy Ö^yBMÖ ª§,— , ­]5€¯¾¿Z@þ,p» Ѐ Æ ÿ" 2ß9!å€"5ÿ#5';ÿ%I&LþÊ(O.Eï.HÒ2Kÿ4N!2Vÿ6Q6Tÿ8T3e¯:Wh"kÿ8n@dÿ!Aa*ÿFKDF5DSKÿ5VKFWKFEWS6KFǪÑ[• •¡› Ó£75·FDKÞ TSã¡K?6NK$KFûªÇ ¸È È œ¡>> °FÿF7KFFVS[F7°#R@°K/ºÍ\4±UL› 9³KFk$F±KH°K$å ç7NSS±d¹\\\][˜±[[[:±+B°9F†°z²S$R‚¶˜¹óBB8ñ–/PS& °$K«±G°K³°J°­R¨±KKͶBý°[þa¡AU(/PÎ °5$Rܰz°TKgK7N‚°í²EKÆøý±c°a¡;):wK$FÁ7K5ÂýÀDWK5Ká6‰±8Ãý²b£('—,Gu±NGÊL°$ XÁiÆ1Åg pÂ:S°À•DIÁV«ÂFè°A°EáFÆ1œ³pÁGD°®ÁⲬÁ5À°ÂÀˆÒÅý±Í·ÜÀâ âÂK‹XÁKïÆô¿ÂðÒEÂF°ÑNK5Dâí°SÁ)Ïi /H:+⢬²QÓSÀC±ZÏölÃ/xÐNFZZCZñ°±ÑÀR‘ÐüÏ¢Á9H:NõZáÀ\´ÐTFF Zµ°\Á’ÓÈÏÞÒ»ZPÀDZG°5Œ¿Ð‚°Z÷ÓùÏ5€9)&:+Z$…°váXF¿ÐSF$)áøê ,ßÁ9)H&+Ñ\*á(àÑ\XàK¸]ä`ßh¡9:­Ð\5€…àOÑŠà¶âMàÂØß=/¯âK\ZZÁìÐ3K$éà€°$NõÀÈß ¢ÁââÁÒ´±|²NêÀЧNF6ÃÏÕÂßÐ8ÍRàÁ7Wz´ÄN52ð1ï5€Kó°L±à¡cð_õcïÂ~ò‚à«Á¶Ò ë±HÒ˜ñ˜ïrÒ ¬Òu±RÂSì°¬Á—òÌï¦ÒG HG®Ð©°ÀSìÐà÷ò/ðì°ÆßöG+C NêÐVV.0ðûß ã),:SÀZ˜ÂXÐyÀEShþœò/'):¦²¬ÀSG°ºÀC–DÁESû Óûd ÜѸ«±Àâ ÂÎÃä–Ä_ A°À+?Q ª±²´À5„ÂNïÁÁE5Ä.ÄhÀ`¡oÀ!,ª°GÑ*‡ÒA±Èà˜û¢•Å3ÁUY°ÜÐ!,@Às°NF±B°ùñ‚’E˜±Ôöwƒœò2 ::D°PÀ¿õ°K6WSœñ‚xüœñô ?:+GôàÁïá5TðS$SG'MÏð@ñxÀ›¡þÀ?,:ó: ñòþ5$GPc;MÂp™ÆYUµÿ.,?:ùK¶Ñ’ðWFFGPG(”¡"F&ÁT"þW />,?:þc€QGG$M:PŸG;Al I'\ù(¡ÁÀ3ÿ0"@=?Hÿ?P';-U(ÈÁw*3Á\éÀ( ŸÊ!Ê <1;;½"c°uH%¼p!ò#!µƒ"<1œð#ýÅâ(ÄýAœò([AOOæY5G=w1±„Ø!­[²çÙ!Ü"A@{>3ÂA1¾" °æ(å"c³(¯?ý´Ù$LÀ…A"\Ü?®)0f La\"À6ÁC0U[O:|&\AYL[JnÁ ?[\NOâ)À3@Hq"¢ÁZ°\xO|>\3AY±)2\EOíO”Ab¡>_¼O›³ž° _ý±-?†ý7I‰exitsicgn]‰Uq‡ˆ£Q'BMˆŒ€µf_Pr `/`š€41ðŒ€§…„„„33ü¾’Ï‘f™3(nÿµ7}Ä@‹ßÖ] ã f÷™ÅðçPÿ"ß)A‘` ÜÙ``”Ah!¦æi)¦›€b "'¦CoUl§eowoöYea¥UÏS`|ð*6ÿfUVVfUûªb*f»ÿ¶ »¶keûP0ºQ£fµUµîÌ`[UP«a#fÿ»·kwkg{uý3àb(6µfµ·×{w{Þd§æ`¶¶ß»·»µSÐbŠwŸvWwvfpßc8ÿ§Šwz‡Š‡xsªs™€WY6-2<†÷4:3rYgraËss]ˆ [rq‡Î¦yqBM|qµN¶TtÅQµ€_P§…&€®r¿ (@WãP™þçS º…àWÿ131332ÿ21#22ÿ!!B$!"BD$$$"êpûDTçpBDRBBýEépB$%DEUßBETEEøpDTo$TDE€TD€ÓDT €õpEóq$Tï$%BB*€R%$ÿRRR%!!Rÿ2R"%!ÿ#!"!#3Ï3333Eu44^Oxice`xw€ú›WAµPAfBMfZ¢³P®PÒ±£q£qA`„så@ÏWL_PÇÿÿ±ª& ²& ´& µ& ¶ª& ·& ¸& ¹& ºª& »& ¼& ½& ¾ª& ¿& À& Á& Âª& Ã& Ä& Å& Æª& Ç& È& É& ÊR& Ë& %¡Í& Î& UÏ& Ð& Ñ& Ò& UÓ& Ô& Õ& Ö& U×& Ø& Ù& Ú& UÛ& Ü& Ý& Þ& Uß& à& á& â& Uã& ä& å& æ& Uç& è& é& ê& Uë& ì& í& î& Uï& ð& ñ& ò& Uó& ô& õ& ö& U÷& ø& ù& ú& õû& ü& ý ?"'(&ëp6€ÿ"&))**.2ÿ0-+,-,*(ý) .15790ÿ%"(&!ÿ ()(&&%%ÿ"%*)%%%$þ< *+)'ÿ&)'&#!ÿ$'$"##%,ÿ23400343ÿ-,/*%""ÿ#%(+.0,'û"  % ÿ'# ÿ*'!$ÿ"%((),ÿ153-/124ÿ1.+()+.3ÿ9>@9/)&/ÿ451($!%+'"",C ÿ$#"#&,+'ÿ&   )ÿ&"(%#ÿ%%&+0/,)ÿ+-*&!*$¿ #*-.¢(ÿ#ÿ &+'!ÿ $ ß!#½ $)/21-+(,› ÿ)).258<=ÿ>:5/,.03ÿ1*'%*3-'ÿ&*+(ÿ&#$$(-+&ÿ# #› ° !ìqj *ÿ)++)"(ï&%$$4 &(*ï+*("† ÿ#%&'#ÿ"#ÿ"$ ÿ"'-/,( û» ',6?Aÿ@=:7772-ÿ&#&'')-4ÿ<70$ý* +*')/-})ä ""°ÿ!" ÿ!'&&)*)"'+,(L±û"º°'" ÿ!%()%!"%)'C€o""! r  !i¡þB°'''(û,2¥°8:::8÷3.)­°+057ÿ:61)!'»+/°)'(À Ù"; Á!!ްù R±Ü 11,#ß*+,%D€!ÿ'*,)&"ç!%>À´ "'+-,()*½°_)!FÀ& ¿$$) *ÿ(%(07@=7ÿ3//0-/38o<:73ê +,Ù þv %"$+./1/*ÌÁ÷('!sÁ&(-0ÿ387-$ ,+*" &&$vÀòd°"ÓÀšÀ*&!ÿ$''÷%&)=±" ó#)ê ºÀ%ÿ'*'&,.,.þ# 8641012ÿ6:<=962-û13¥°1.$ý +¡ #'*û-,…À'###!_ %À.6Ðÿ0%(134+%¿%#"&ÏÁ$ï! "#Õ° ß D)$üsÀL° (0/.í1& À$$/û42ÜÀ334551075,¿"$,-ÐÀ"g# À&tÐÿ $+-(ÿ+28=;013÷9=4ÎÐ&ý.¹¢"   õ ÿ %$#$%&ß% …À-.ÿ,'#,/2-ÿ)-.'(.49ÿ;;;85344û22n  #,5ÿ960'%+{21;°&)+(=¡¿'*)&&'xÀ¿%*+/¢ >ÿ7417=<6'¯)m¡'Ò !w ! õÐûÀé° °%Ð ½x°)-1/ 4û:50á"*4??ÿ?><852/+ÿ*+&"&ý.,° "-47ÿ3+'$*//&ùÕ *-*'"û  -16;<ÿ9527;<8&%020+k°÷'%# °!##ÿ |Và†á$$#R°ï',00¶À3:<ÿ9+#")5=B÷>9<°À4113Ï544.°/à$÷#+ê¡)*10ÿ&'&!©$Íáñà"ް!€À1ÿ5467532.o!")Ù +*Ðüа! ? u°Éà÷#&&hÀ!&û*-—ð18<9(ÿ!$.<@A<7ÿ;=:95566×7:=«ð3Óà#$**''*pð*"¸ KàÕ õ&ŸÀ#‘ð#(*,÷,*0§À*& o$(+)Eà-/:¡þÕà ï"LÁý!Ïð ö”ð,1/#'ÿ1<==<;?Aÿ?<:973-2¿;96-$Øà&Ñ À¢ #œ°22rrð#ÿ°uð#$"ذÿ*($&40,3% EÀrÐ% ¼Ðÿ#*)#"!Ÿu°ôÐú$vðß!!(1°&!ÿ '.4548;þ¤ 677:7/3Þ&°&ÆÀ&$}(–ð.1/&#GÐþà/2.*# %Ý)º¡ „à!Îa°-.)rÐ ò(/¿.+!#>À%ÿ# ÿ!"à#"×°E°Ýrð$ !½)*ÿ,3<>ð.¯.061= +Âà#÷)1,V,12.¿+'~Ðÿ(41-"ükР/3.+% ý$¬°((' {ùÐam$c°#‡°þ Ï#(,® ”ñ.1ÿ8@>:.(.5k=@¥à/tÀ.3/ðf2/oC€)*´ ¿&" $ð.ÿ,(#%*0:Ð^ù 1.((?* ÿ#!ÿ  ß &n°$ÿ  ×$°"¾Ð69ÿ81/4Þ°ðACE1Ð25_/-,02ZÐ& !ÿ" ''ÏÒ9 ) ÷Z $+00ÿ-*./'&*/—5."—.ê èÐÿÿ þtÐ!!#ßÌ/0c.$˜'à#Â68)à¿27=2&&bÐ+þ¼+$ %!ç'-( ñ°/ )%"iLÀñÁÿ&.242/-ß-024/ð ÿ$&#þŸSÐ Ðþ /(&-6@:ÿ0..6;>?=ÿ81( (53/¯)'01f%Ò 'ÿ &.*&(þÐð("$,³'!VàÇÐ"!jÿ,4<512û3620+$ÿ w!_çq°Û¡ü \á<81+**ÿ041+#-370ä®à‡Á+²4&¼°å°"'Š ù'1à‘ðÿ!%*%(6{A=$À:71,CÀ¿… ÿ!ÿ"ý’ÿ %1=ß62359$<2üX Þ0 'ÿ4>5/00//T› Z°%h +À*íîOÑ),%ò°ÿ &0,ÿ!(7C?<<;ï<6.)PÐÿÑ‹Ñt°xà NÀþx@ "2B=&àÿ>>;861-&ý! 'ÿ5?:552,-1.- 'f° ¹1þJÒ,+!w—0&11À·8<630² %›'@ñS°õA0" Ð#!ÿÿ #ÿ3C@==>>=þªà11+%# ýP )-7?<8¿62++11‘Ð.÷)%$’°/0/3ß20*%(¹ ö@ô0)+Ë'.­ð/Þñ  #C& u°NÀtÐ>° õàÿ&%!ÿ ¿"#à3;622466œ0¯36,%x*Üà8*';dð0GP+ : ÿ'.369:;7ÿ/%'('ýõ0 ÿ'22/}(½ð! Ðÿ##""ù‰Ð«°&$!ÿ " ¾ŒP °$º*°-¿./.Üà/û*-6A16:>A÷A<8¥°4/)!}â !#'06­Ðë82R@#†Àÿ  ÿ!/23ý-:Àï#'%q°ý`#')&ûŽÀ'% ÿ  ÿ )+*%Ÿ#*,%$1 ; 4ò©`/BQ¬Ð@@ABßA:3*!ŽÐ$#þÑ5?C?.'&þk 132! ß }ß-4;%Ð.íu`Þ0 nQ Ç$ë”… ÿ >9°)(.-"Ù°î­6(à/)LÀ&šP@ßEGF?9K`"ý)_P)0:CE>{)"j°&"(+«@{P t°½%’ 894,ŒÐý0&$úpVÐ**"ÿÿ  ÿ "+ÞY 61# qÐ'.¯9@;2s#0(¿4?GJE5!`,ÿ&'.0215<ÿBFF<&##ë ˆ $pÑ ïØÐ/,,ÿ+48/'!ýp % ð"/Prpô N ïPO ~ Ý0//àüq µ !/982%÷!),°2;CI÷KC/Y±$#+0;1/cà@<6¿°Npú÷ #^0ç  ¹ (/3ì9 Tà}k0õ°"ö¡îwá÷P ßÞã(@PtaØP"04ÿ2'%/6<;:ÿ@DHJK@)#í(s`)Z 127ß92/./9 ++8fÁ @ƒ êPYàû)'à342-(ÿ% ûð ï ¢ ˆpÌV0þ0#SðNà"m{p),A`*4âàÿ:BEA:.+-Ý)054ŸP4/W!#?à, (ó°é e€-ñ5º+#Ÿs‘0>ó° È >°ÿ# ÿ ô„°ôÁ1 ,#û ÀÀ ..+¿/2:>73æ *÷*/0œ )"|@õŒ°õ MÐ& Б ~ °&Ð,-~V'.Oàÿ()-32257ÿ1($%û(ñ*.+$'Ó*"ueð.œ #ªn i"À$á+y%ÙáC  E Á% ƒ0ï«°þ)P ƒòBàÿ°èY°%æq@"kP€P+1-îÐá, R€%,¥Ñ/"#Ðpò?ÀºCÀ #&!ذ,õ%û€{ !&+Оà¡pÅ0oÀ"ŽËZð'ïÀq@åõ0°Îw€9ƒP½‡ $$$(à"™"Q@S)!ò ²/*"$(),1© È¼€rÀŒÀG ÅÑ)#Û\ #ûp*-Í)BA0,kPwàÿ()+.+îtà}Ý{±!uB.Õ@#'#TÐ!@ÀñÐ8q°É Œð(-/H@ôÐ](¶°#)/að1žËTPVÐMá$y""Üð@+ï%¶à%û@ !ÿ"'--(#÷ ” =î0Ž0Jö‘á°#þp Ð$×ñû%[Ð62,)%Úý0#éÀ''Ȱ62ï*#@hRj×!{(-Õÿ%)-/ù øP‡€÷À%ås~ ˆPF‰€á àõ!Xàõ ÿ  !-=7)07+'%œ°ÈÒý Ì152&³ òp@"‡@$ÿ(-+'ÿ%.2/'_$*)(…P‹ êõГ0[ð'³ ùU°0ÒTû€Ç)sp¾Ü0'÷"ê8?;1Ö°àx'Þ %,ÿ03*"ù%sáÐ$!%)-?) i°1Àþ„á&! ÿ%%!uŒ0Ù°}a×'#™Ñ ¬Àû)*!N{@$!— "ðÿ)8@=1êò""#ªP&&'·*1.…Ð%¾ +­)0&#Rà$ âu #MqÇð"Àvêp“Tqvp@#êÝÐ,½Ðð%"÷w€%&!¢@`€ ¨°"žÁÿ '0:@6*— $#À •𢠿#" fÀ/ñ.Ÿ c w!e‹Òð"—þŽ0ÿ 'ÑТ)ô yðË$‚@Ûþýà&=)v %ÂÀ¡ o:3'° #€ÿ,$Và+,¿1é€.ŒAŽ@„àû°Þà/@ö_ƒ0¾Ž 3ñ(ü»Á "ãy@Lðòp! Зq`#õw÷(,,Ȳ~Ìà!"*0--¨`5353ò²÷cÀ!à¶…ð%°Vp þÑ  õÕ@"› -331¿-*&" —À» PcÀ/ ŽQÌ ƒzÕÐÐ" +Áp/35+ ‡à"wNPý1: 456443†;@)(Ò!‡Ï°ìPþL  ýð øË0ö@{&,131/-cy€{ÐÔ „`®u`  ÷0v à')B‘9;-z€'.1-¹°îÊÐg²® 1#`j€òñ?ŠpØ–0`Øp Š !¾TÐ#*.0b!(’, $o@™‹Sßçá'#ß"Fð-18258;:/ÅÀ 0¸))À`j°XðÙý3JP0.*#üó0ûÀc“çà‡A“0/ %À|qGPnÍ€)(' áø0Ë‹ wð PýwP%%(298è ë"Z|Wá•'*,-3cP\® ^0/,I0"% ÿ  ´ð  À#w`V0‡!(,¼@Ð@N°¡à » øñ 0îäà ëà' ¾²Ð19>;0Ð@0«20s .ê@#èà(ÞgP+(&*¯P97ÜÚ;P0-+À@!ÿ  îa}°Ë su‘æ°!&„Î@È@*N¼€þ w`ÿ  í0%»0$ÿ)4740,æ!%N0°Y( hÀ.2X 8¡P¼a Ý,+'$²ü wÀZq ÿ   ÔÀ!=À‡©R•^åY€Y`ûp€ !Æb˜À¯½@,.úÿPÔ  ÿ  "',1¿8:=;97è28FP:0»À ÐVÀÿ% í ‘` Zp ©U†A!Õ°ûp(øþpÌài0¼AU` ® [GàÎ`7Ÿ&+* °Ö‘û$Ià,,,29C;<å`e`½=P-RþõA"(,-'ù€ 0   Ö@°% ®éð%()ƒ± š÷å°%ÿ » À1 .ï24:*³ 5!p(WÀ,-‚Àšp8<==71'- K*(0P)r  2%£pöÈðaàÿ "ç°ôWà W€Ï$','íðbÀíÀ¬%(ö?58—à!µÀ,)!p-©` `®°ó66뀋 !3($ÎðOQ$aÀíS  äÐm€ ;50ëçà™!¬À÷ ‰€±&¡'š0¯†ƒxÀó#Ÿù2hP'"*úD-ðÐ &130ì€ÓÐ_PmA‹  "#Îà%0KðŠÐœ1ó °¯@úøà›À½ú€!$&*°–‘Ð{ài*°&$'hоP$é°b€¹&ÒМ@+,L€'ìGàÊ€/*ÖP% ½Ý (#7@")'Ã@íÐùÑéða"ßðÓ°i00 øà€Ó°Ã!"Íð0£à÷p&(êy°Æ )jÀ##*Jg 5Ü0(“0£°vàè› ]ðA`0Ê`$$kîÐ#Ò!ø‘oéà$$³ñÅPÌ‘Þðàúà T±õ`?áŒêP1%*JPcÀÃÀ.õ., #§Ð-3:>ÿ:41,/11/å(ÛÐ+ÅÐ8°*+.»0/–1¡ðú9@"}€ yîPÕ@! {q6P°),ÞA¶ š€¿ V0+" pá¢--ðÇ@³/2EΠ.*ÈÀ9<;84002ꀿ*&+3.(t‹áå #¥ð!¢°Û# zð"&–#y@©Q #A¢‹ð(…€×’ 0ìp†°œ`ËqZн€$ï)..,æ '/Ý6V0779)€57¿776752ß-û.-C€>81%›`&'ëàÆ1$}+#Tá6½Ð†ðV°ЮíÐ(.,0$r Žæaª@`ðjðÂÐÞð©°%$ ¿$,2Û 6795/g 24i‘¾ zB€5×060*'RàÇ./*&ƒap´°,!ˆ0PÈAÃÐ$(Pb_ V!"'!'A0#é1¸³ Àµ° ‚à#ÊN‘,,À#`€ {%Ê`0392Ã0¿$*2630Pp/026:>=7MàT:0V€0à™1$(½à Z€,¬ æÒ°úîÐ&lÀ #æ ÂÐ&Ï%>Àá?`.ÆðdP-ʰë°+ à1`Q°ç€`Aq41(™%æÀÌ`+&EðDp=÷;3(´Ð43//.+&vp 1máöà "P  ,Ï`²ÀXpkp^ &&²#ÄÀð>`e€0Åà0,K! .ǰ©Á'Á îc!(# 5q122q/=¾]P)/3Oÿ=81' $+5W40/‘d°ù¢ð@!ÍðY`h€,€< fp"áN ÄПÀ‹ x 3"IA'.Ið&0[*„a+€ý%€.,$ ++'*.İ¿*066.(­p1y2¾¦A!(00ò‘»* ¥0±!ø€R`è +(Í#æ@#'h2‘0$#P>`—aÁ† i% à”Žqp°/ +e#á'µú Êðå0*-&ÿ&0884/#+-ß =0þºðV€`pž0 µà#P´ÂP;P-C0#&P%)ûê#ð'`@×ÐDÛp'Àr@g # &°`*ç $`0 Àû&+Ý//# %[06Gp30Ì€3Áy3H€R $"ñðµÀ@"x#m!:Q2-&P!)]3,+аíУ1Wp4…pŠð'îá•“ð~®‘*+-)$†lÇÐÚÁ$$qp(*ð÷."&5Ð<73293VñÂp:;7Mpç ¿¬ð"ïÐf¡ŠðhÀ,J`1[!-bîP!p©m`Ï0$öàà÷Ñ #+¢P±. ¡Íà±@Ñ(_#!!'/jÀ+Ö0ß96425Ñ@45ÿ2-2962.+Z=Кàv!ºðNP*')Ûq(:V@5\6)€Ð.€Ò@%Š`já#Ihà`'A`%°:š ø0ÚÀ¾Ðÿ&.78@>;:ÂFp5IÀÅð§`¨P%+,% êñÌ0Êá#€ÊÐ69ß71*#°`!ß%+:.+` ÿ$&!%-*%[ýà¡Ð PC$%ÓP»0(°‘ñ!­ã "’a”ÐŽ@ '/¹,Û×751Ü1å-xà´ÜÐ&#$”°iDà'í%å°.4Ø 5.(îÄà*+"UÐ8/"ß ð!öèp0±()"‘²àÁP#Ýà•#òì0" ×Àü&à_@-+/,+-?2233/+RðP@hÛ`àaà"'’ðþéÀ/1.#"÷.9:SÀ+''+üâ0 2+ Ï ·ð% =(=@30(¡ðz` `p#‰+ õ€†0"°N§q! (ð€½*_ òW3Õর/033VÆp3&f !ÖÑ!`Qü!°Üp &-5é8Æ€“*;1-&ÿ/' &™À%!¢pŽ@$Æàôpµ"·°(%)-‘)ü°$% #³()ÃPd0)+=@58:861½ß ].Qà7.%0°#â@  Y°:POàã0zÒP)%°/-'+•š ` €'!c°Ê0"µð&jКÀà%°7%©À"pºÀù!ôH@-.014=3Áp63./¿Öð}4W40-,/ÉЩ*œ ƒ!«°*ð½ÛPd0&P&+-,µ%€°&)ÜP%ð‡€Ša`Žà!%,ù,S`€  Œ08°pb"± .õ1Öð5E,'+-o.167ïÑ3/Mà†$ --Iབྷ‘P] @)(,Ú0 :”$ë@$‚ ŽÏ,22.pÀ '%Ç #)Pi°…p& »À«@ Am0Ñ” 1  2Íõ*%*.Ë`ÉðÛñŒÓ0²*)Š1€ð)O,*&$B :0$N•0° Ž P [î*Ð!!#C *%!*(³@@N,°%'&Í ’.IÐH_ ÎpŠð)>ðÝP$«p *G*)×ÔPsp‹p!$-.,‘Ö@[$Š (àP(ûP7°¶`)Ø!(Ñð&)§°%û¸Ð(% 0 Å!òšã‹&,¾ð1“ȉp&=p+@®Ñï¿Q0,˜e€›ü°+,â0Í *(n@/€!&@üQ…€*¦À&0"‡€@ñY°à¨@0G1ƒ dðí[¡‡`Ûð+ÿ(10.34-% $IP&µá_Ñà³ðó%)0šA").4684<€7Ù𤰘@Ý +ÐUPZá@àPà€ÃPÑP&èÀn@ X°è`¯áàð °µpZ´‘0&"[07_94,"&‰)`pàdp#P/ Y!â€ù'ð¼04872¸»á¥°{á##“ññ€ ³ªáÙî0º€/0>À)(ß"o )/2@€Êp‰€¼¦ Ó°8;:4(€-– ¡ SaüPüà $öÈð2:HÐ6873žJð61'#‘àA@# ƒPpq÷ñ"à@›Põd $ñ*,.*ô‚€x &Ã"/Çм±ÁÜ`0@>=?@>7-X`‡/0-ˆ@© ]ðáä_ ©ðæ(/7ï7344Æ 0('Xô°Ë $Û°nÀtÞ¡ð‰°ä Œoq $£0«Pß$0 .2÷533F,',CÿBBB?<5/(þq 0-(*+'žÑ¥q™áŒj¿&,04¹06äzÀ‰À(]ð@..*?#*©à|!$‹qà€c0è`@L`ýør¹ðp±350Hð3/(,=?>8ï4(0ÀÛ@%ððþ@gðàÛ`"&-+ˆ3— m,æ €&$ ß°ý°!$+.*(ü0W%W p#»p† ®b¡d`€ ÷'.-14/']zP*@B`õ,p Ç&,'†ðÐÒç -*Ÿ,475.{…)FÎ õ § 5à'1ÐnØP!*³p-. ‘•šP#Æa0Ñ.}/^/)( @-˜ÛòY)`+N Ú$‰qõ)p,s+378w3.+ó#0 ô– °@&5,-) ß'4lá+#— ]Ñ ¸Ð&’ºð-i ° ÓP"û#(@,.,(ß&25Q€+)ÿy°Ð%,‰0?++..)/ñkPq+ €ˆ¡œ°â€ò¯Â&Ð^`$ï'33.r'‡æp­‘Ùñ270,$Ûà',¾`…€û31Ê,$ß)98)&É × ›Pæ ,+[@*O/.¶0àÌÃ*">p¶pýcóÙ‰ '-)"ÿ#% 'üEÂQþ“0&-()%û$)sQ'!%¼v@Aà/3.'S`*¿#-<;þð+».ö° ¢ W"*'.Áð)g_3,$|0+š>’0$z0îÀ€,*'@ð("¡] Ü[A&0À ü°c°!% $)pò»°8 ï@.3. þÍÀ$)1;:30ï'$%‘ü'à)p&05ÿ) !'/3/$?$ôp÷;}€#%!v ¾ÐÀδ` ÑAî@Ù îÀP%'"yªçP$*06L€«'.î02Að3ÉÑ%Ç((+¶@¾€€÷.15³`+273±/ÌàÃP#0(/´P5ý+}á!w IÀ&Ó Œé ·p)0àî`^0"öŒ !"4@.(" '+!è0G(& O`Ñš .xP ô ÛéPûþ]P*02573,ÿ# +49+!ÿ '$ÿ&1>5i)aP š0,- áÿ&$/ÿ1  <°mA>ð"Ï#2`ð (ÿ20)*&èØðí@ÄP!C`Gà3+$<€JPŸ'!‘@‘0¿"'/1-"â(ß29:6-ø*.*$#*1†þNà'$(.7=@¯6& apä`üpqP220(æ}+,‚ÀiP2/)(#[PÚ äNÐì"+.‹`9püö€p##í$°"É %}à0594.¼0^˜€ +2'ðû02óP5=8. ¡f`ÌÐA ñ.:p!¾5@$&*+)ÃP(n Þ[P±`Íà" $**>€ý%Cp..&ŸΠä ÜáÐ|°ÕA1ÂÁ°$-J ÄP9ï50('PÑ"ë°êÒ+ë #a)Á‹`p"![@ PÕ`**B±®î@ Pîì°(#-P—%ºp €7@õz€#`à$+03ž³1)oðžA+39=6. `@0*‡p• d ` Å %"µ/8ðsR)–ÌÀë1.= )=@)#hø m .½P/.ÕÑï$"g+( ï#OÐ%»T`/--̰)ìÈð^a,-­€/-2840# –4 þ$Ô|àŸ`#B€-M°,1\Tpà%(-Ù°怅@%°CàÙP 4ÿ451$Ó&(TP=°¢p"=$Û` "(0í°à//+"k`1ìÐLÀÿ3447:1'Ÿ'0/ÏІ/3+%º€“ ,(U0} õ€d°.%j`Hð9p$À=€MÐYpü` 88763&žÔ $)'øàÀ/  t€$– º€´Î0ÓÐ;€)1²00ý1 8;=/%!Tå°‡*¬€,ˆ.zEÀ#g */(!p#&((U àá”PžÓÐ!$ˆ 00%|‹^P4:865¶`ü‚ óÖ°Ub$#x±‰€ö!&*/2 ÿ379:;<1*+0444/(… |Y°ñP !œPæ°073†Â "®×°.*&…€0Óp îà"#+$,2111694˜ðLÙ o¨0„p(#pn=à--' P„ ÷( b°% %þ:19:8886_6563/2€*œàä–Ä þœà&'.û57š@*$!ÿ -44,$ÎSp*(#ò`yà&-ÿ2645:=97w788¿P‘ÀŸ '€Ññ!ÔÐ>"ÛÀ?€$Þü '#ßà*,_0752.­€0Q†=@'бm ± @@,÷-' ´;95/&#,É`_"&b ‹€õ=`2•`>@<9o7661¥#°Ç lpb°ª  ÿ'232,# î€'=pÈðWaÿP°û/*nÐ'-.)Íœ äÀ€)$$(-235-~°Y$jà¹0*:ƳÐ&'»Ð°ÌÀ/3ÿ7:>@B@;4ög0+ëëD°|Ps¾°ÔPN á$°¬€;€’1/,ý'q+-(gâлà' È w776»€™à`ðÜñNÓö`æ'(¬€þ€-48?B=9p8 F ëM€ %‚ÀÔü »ÐûД @à¹áj¢`*Í/¯@*'MÐÒL0&=àq!0#6Jp)%c #+hÑåÐþ.0(#&äÝÐà&â 09>9ÊÞp:%`*‰B.1~™ "')%°ÿ%!propÿDATEï7-06„P05,ß 9:13ÿ‘NAýM¡icecr÷eamÿ‘ORIGº  &¥.bm¡AïbJ¡BMb©  r ( º  V¢ð– ë v£¡V£ß+€ÿ 3fÿ™fÌ3òÿ0Ä3™ÿÿ;ÿLÌÿÿèàÇÿÿràü.ÿøÿÿÿÍžÍ çĥ͠ã;sǦ.Ã3Þ£å¢óssĢ͠"çsÇy7Þ¡ý¡ì—ss±þý¡.|ÇÃÃ3ý²Ì||s5TýQý¡"ìÌÌ5ˆ÷…E.²|sxîûˆ„9².Ì7¸äû„…E³Ã¾tƒ3ý49²";~·ª¦ý£-²"»îzÝÚûj0^²¾î½ÚÝý¦u³+î½îÚÚ~u³"»½ÞíÝ´Ÿ""ÝîÚi³Í€-SÝÒÍ ÿ˜ 8¤ÖÞ`37¨& ti¥p.¨ ܳB¨¢ü±BƒM¢U¤ÿ°_¢9°Â#V£U x¥ 2Áþ¡ÿç…ÿðœÿòòÄýöÏ7ÿúLÀþο TÁVLÀÿп Ò¿ Ó¿ UÔ¿ Õ¿ Ö¿ ×¿ õÚ¿ ÞQÀáÿýÿåÿüéþûUî¿ æ¿ ë¿ ð¿ ½÷¿£¦À §Âk ¶Â¶À¸ÁÇU ÈÂÈÁ=ÐÀ[áÕÁþð  çMa÷Å¿ Ðÿ  ß÷Æ ÿ ùîÀ0Ò  ï ÷Á M ÷Ä €!Ñ Ð~/Ò ×oßß°À–Û´¹  Ã¶ï1:41©menŸu.dat.¨ÍÖFILEŽ’îÒW ´¹8³Ú1Ϲÿ DEMO_BM¿P_BACKÖÙback.tgaÿ‘oXPOS -ÁÒ¯XSIZKçYHêYÔVæ'à ¥Àâ~k ÓìïÎçïà6“éÅä¡á½Ù§ä¢àãÛóóºà“ì“æºæàáæ¢ãðï±ãêæáéáãÆï5ÿGÿYÿkÿ}ÿ“ãÿéÿÅüöïÿìÔÿãÿøÿïÿL ¨é¨æp‚«æ¥ãU :#üºãÙ½æL*7´æÍi½ïÊ ã¥ï·ïî9ÿïÆ2/D/V/h/z/ÿ/•/Â/êêýþ/é/"?ø)1?Ugv?ˆ?L?  ˜/ZÜ?­,áO!O3OHÐ?iOºã¨{OOÛ9O?Lµ?¤//_A_S_Tt_§/_’_¼_Î_à_çOoé_(oì_LoU?pod?Xo¦oÿ\_Öoë?ÞO 0»ÊofèorØé ´IºOÒOó<K)„À_qƒ¤³ÝŸøŸ.ŸäRŸao‹oˆŸšŸÿO´ÊŸÜŸñoCŸ¯$¯ŸÑÄŸl¯~¯¯ŸX0T¯·¯Û ¯ü¯EO ¿2¿5¿h¿z¿¿H¬H¯¿¿Ñ¿–O¿¿Ï+Ïä¯OÏaŸyŸ…Ϧ?©Ï¾ŸV³“¯Õ¯÷ÏIÏß-ß§¿¹¹ßÏoßßåÏ¢KL~ëÏ,\ﹿ)ïã¿P¿_ïqïƒïñÏý¯“Ÿb¯t¯Û™ÛŸ¤¯¹ȯگ˜¯¦¿§¯4¿þ¯X¿jj¿Ž¿ ¿µQŸ¿¯è¿›¯ Ï­¯Ç¿GïTÏfÏxÏ9ÏŸŸ¿¹¯ÒÏ$Ï/¤|ÕÏ)ß;ßMß_ßqßÛÏú¿ÏÆÏËßÝßò¯ï®Ï%ï7ïïm/Uïï‘ïïß¼Ù“Ïåïìß ÿßNÏ?ÿQÿcÿuÿ‡ÿñïv¿¶ß'ÿÒÿöÌÿ&8JôïŒßÿ¤M¯ÈÚ’Iï¦ï"4^ïjï|Žt-ÿ¿Çߪâ'/9/Íï]/o//ߨÉjT9™/EÏóü /?#?5?G?ù/?Y??¡?ÀÿÅ?×?z?C O§?1Os¿XjyO‹OOq?Ò//ÍOÙO _ëOýO?__c_u_*_™_®/½ÿœ_Z_ªio#o5oGoüühoò?Œožo³?Ï_ÔoPo=O biI±_[OO|ŽoÛ_ç_ÍúQ/Åo0BëfxæoIn?Ò¹oöŸŸ,Ÿ>ŸïobŸøoqŸ˜Ÿ­oÆ_ΟàŸwŸ¯¦|¯7¯d|X¯j¯|¯jެ³ŸÞӯͯ÷¯ ¿Á¯-¿?¿è¯c¿¿™¿F}œœ¿Þ¿“¿ÏÏ&Ï8ÏVlƒŸøŸYÏϡσ ¿ÔÏGÏnÏ ßß.ß=¯Rßdßv߈ߚ߯¯¾ß„¿x¿Š¿í¿ËÏ*ïÇßôßHïåýߖ﮽¿çÞïðïŸÿ&ÿìÏûφÏßYÿ’ÿ¤ÿ°ŸÈÿÚÿ>ÿqÿ"4IßXpv^…—¬ß»cïÇÖ'ÄKBWÿïöS‘¯øüÃ_Þð“/ïÿf@}ÿøÿw/°ÿ›/­///¹É°/z/?%?"¯I IC?[?Ž?£¿/{rÍ?ß?Ñ/OIåß]ìè?HOOIóVa?½¹/ÞOðO__ø/8_?j?n_.?’_¤_ÏOŠOÝ/ì_€_o"o7?A_LojoIoŽo£?¿_Äo{OèoÙoño×_cO'fxŠ¢ï«vŒ_ÆL–êüæ_yo…oY_hz7o&›‰WÑ_§ŸŸûG\pŸ‚ŸIŸ´ïØTÜŸ?Lίٟ ¯ã»Ÿi¯{¯¯>/±yì¶á¯ó¯¿–¯øŸM¿;¿a–P¿˜ž¿•¼*¯<¯¡¿,¿ÏÏ+Ï=Ïz¿dŸsÏ…ÏIÏ·¯¿ÔȿԿåÏÙÏ'ß9ßÃé¿¿ißà¼xßø¿±¯À߇ßäßößïߥߣÏPï;ït˜ïªïØßÑã¿)ïÿÿ(ÿ:ÿhïGï†_‚ÿïï´ß¿é¶ìZOåÿß Áÿµÿ °]o­¿šÿFÿ¬ÿ*ÛíÿB¯™Oÿ,YUÿ}sÿÒÅx¤û //1/_†g/›¶ò¦Ï§Ðöè/¹K0?õTÔl? Š?œ?±9?¶ä?ö?O~?¨?·?POB?tO±?GL}OŠßËOÂOªO__%_7_8O[_­OÝLO£/4Ÿy_Ö_ÓŸ¿O oïOp_0o¦Sˆ_loOo¢o’OÆouoêoüo]o‡oU/ÊYÉoot,9oª_Îà¤(:^°O‚;¸ÜîòŸ$ŸC5ÇlŸýŸ¢Ÿ¾ÆŸuŸêŸxŸNÜï©]ŸÉŸJ¯´Ÿ)¯†¯­¯Y¯‘/㯰¯¿¿+¿=¿8¯õ¯A¯…¿ÿŸ•¯›£Ab¯Ú¯ì¯ ÏÏ-Ï/¯R¿Ü¿â¿ϙϫϽÏÇ_áÏuÏMvÉÏ&¯>ίAßk¯zß)ß›¯ßÂßPß„Ïøß ïï.ïŒß5ßïßÕÏ ?¿CïRïÐïæßôïKϾïúï²¼KÿÄï×ßèï“ÿ¥ÿ·ÿÉÿ{ÿ”ï~ÿ¸¼$óáÿoÿDq߀Eÿ®ovï|\‰û 1•cÿ:_‹ï ï@!ÿÓdTÿ /Á-/?/÷°u/—W/$/®/À/Ùä/ö/èQ/ª ÿ/J?|× ??¡?¹‹q?é?­ Oã?1O•?X¼¯vOÔ<Â?:OOOÍOßO¤?ÄFúOÇO0_6o _/ßx__)¯ŸelD¯•¯Ð/¹˯àﯿ¿%¿P¯Ñ¯“Ÿm¿.¿‘¿0o£¿Ç¿Ù¿ë¿ /Ïs¿3Ï€¯¬¿ZÌHÏp¿=_®ÏÀÏÒÏäÏöÏßß0Ï>ßY¯[¿A߆ߘߪ¯¿¯Îßtßòßïï(ïSßLïa¿pïãß”ïfϦïÊïÜïîï‚ïÊÿaïÿHÿZÿoýïÿÂß´ÿCïØÿêÿüÿ×ß2ÿÉÿk܇ÿ‰›­ßÿÑ}õ+¢ÏOj_-ÿ…1iÿµïÍßñ/Åa‘¯ï]/uÿw“/&3/SÒ/ä/ö/??Š/Q,À/?6/ƒ?•?œ/™ÏÆÿ)?ï?OO%OŸ/IOn?t?¼?}?£OµOÇOÙOëOýO=OUO3_‘LW/8?{ÏŠ_¢ü`?_½_!_á_êS½Ùé_ûQü_Ý?i_ˆOÿd}oo¡oJf­?Ylf¶oøo .Ì_ odwoÅ?1/¾Ðâô©RX¿t¿†¿A¿ª¿J¿Î¿³¿Õ¯ÏÏ(Ï:ÏLÏÚ¿Ë¿…™~¯°,OÏÁÏÓÏXÏ÷Ï ßß__¯ÏèÏNélï­¿jϧ¿·ß–ÙKßçßùß¿,!ߥßé¿5ïtï†ï˜ïGïÝŒ›ïgÏ<ßÿÿ%ÿ7ÿIÿ^Ïéï‚ϗϦϵÿÇÿÙÿbïîÿ!3ßÿZߋϋÿaÿ±ÃKçùï,6¢o8t†˜D¿¿ÎªB//(/:/L/õ/È…Ÿ”ÿ©ÿ¸/Ê/Ü/ìî/?$?6?ß/a/‹/Ž/m/g/´??Q?ê?ù?æÝ–?bOtO†O;_ã¿ÎO­OòOB?_(_:_L_[ÿMO…/”_Ò?¸_Ê_?î_oo$o6o¯_d_~Ž_v_g_´o“oNoêoüo O#ï¢oDœohzŒ>2O°æøÕo.@R¹¤O‹_š ¾Ð÷ÿŸŸ*ŸÖfo„ŸAF¶±ŸÃŸHŸçŸùŸ ¯ •A¯£e¯w¯2¯›¯Y¯˜¯Ñ¯œŸõ¯¿EŸTŸ(¿O¿d³¯ˆ—¿©»¿Í¿,¯ôâ¿Ï'Ï¿KÏ`Ÿ ¿Ïv¿g¿·ÏÌŸÛÏíÏÿϯ#¯¨ÏGß–Ïkß}ß5ß¡ß_ߘߪßéßÝO ïØÏ"ïCïUï¿O|¿oÏﯿÁï[ïåïµï1ìîï*ÿúï1é|ï‹ï~ÿpïÂß´ÿÿÓïêÿüÿ ߥÿDã¯hz¢ÿž–ÿÂjï¶×Y³4¿:LÙïpfÏ”ªÌ[dëÓÜ!/ñ/¸{ox/©T/Š//ýä/ö/?aï>?b?t?†?J?Æ/K/Î?à??O“/_P__qc•§ÿ,üÎŒªŸ"ŸYãXŸjŸyŽŸ Ÿ²ŸÄŸ„ïÄ?П ¯¯…ŸýŸQ¬c¯¯‡¯FŸï‰s–½Ù¡sŸì/_¢¯¿Õ¯*¯D¿¯í¯8¿Œ¿ž¿ƒ¶ÿ¯Ë¿Ý¿âoÏÏ%Ïe¿¼¿[ÏmÏì¿z¿£ÏµÏÇÏÙÏî“›/ñŸ—Ï'ß9ßKß]ßßß“ßyϺ¯Éß…Ïí߯OïÛß5ißxßkïßýÏDï4?Åï×ïvwïÿÿ­ïïï¼ï^ÿpÿ#ï”ÿG¸ÿÊÿÜÿ•长 âÿD˜ïôÿi¶«Ÿ±Ã…ÿCÿÕ®¯ü/r{e;¬ÿ›~¿Ñæïw//ªò¼·Ü^/‚/&&•Á/ÜŸå/<Z<?ƒO’ro Èò¿"7/Xj|½ß:Œ(Á7_Ç÷ ŸŸz?Ÿ!lco°ï¨o–Ÿ¨ŸºoÌŸÞŸðŸ¯I ¯ß3Ÿf™>¯QŸŒ¯}³¯)¯æ¯×¯A¯¿xŸì¯±?d¿v¿ˆˆ¿8¯¾¿+¿Ð¿†¯ÏÏ*ÏKŸ}¯cŸ.¿ŠŸ–ϨϺÏÀߣ¿:¿¹¯üÏ—¹¯¿DßY¯;ßVŒßPß¹ï ßßæßø¯nßï{Ÿï߇ɿßpï‚ï”ïÂ߸ï ïÜï9Ïåïÿ$ÿñïHÿVßÊïŸÿ¢ÿ´ÿÆÿ¦ïíÏCïüÿ#ß¿ÿcÿoÿzŒ6ÿ³ß/Ôæn³¯øUïdvˆš¬ò"Ù¿<ÿNÿ/*//Tÿª rÿO“/^‹œ/Û/í/¸õ#?é/Vo/w?‰?뿳?Ñ?ã??ìò?õ?:O½/FOpO‚O”O¦O¸O5ßÖOH/G?$_ôïH_¡?ÐLOï^OŸ_±___ç_ÁO où_ODA?ñOwo‰oDoooÑoãoõo¿oþo=„_as…—©»2ßeoi_’o'Kî@U“ 1É_ÃÿŸœ8*ñ}ŸJŸ`‰ä‰)ŸËŸo¯ÚŸ7É@¯m¯¯‘¯£¯µ¯&ŸL_ŸhŸ ¿ëO0¿B¿T¿:¯I¯[¯Í¯®¿I„¿çö¿ÏϨ¿›ŸV?÷tφϘÏ~Y&ÏÈÏÚÏìÏþÏ5Ï\Ÿ7¯á¿@ßjß|ߎߠ߲ßÄßÂÏèß+ßßß'ïTï:ßIßXßÐß®ï4ÜÉ/Oßóïÿÿ¥ï>ÏPÏbŸqÿƒÿZïxì&ÿÈÿÚÿìÿþÿ2ÿ ï7ß{ï@j|Ž ²Ìï»Âöܼÿþ?nÿhÿKžÿ¾Ð“ ·xŠíÿ/¢?G–?__/q/ƒ/c§/)/Ë/ÀÚ/?ï/%?³/°ÿ[?m?¼/4?£?µ?Ïï»?ë?ý?ë…?OPObOtOÀ?î//OIŒOÚO­OþO_ÑO4_F_X_j__%_‹_|_¦_»_Á_Ð_Vm_÷_Bo?Öou?o<0o´oÆoØoêoioO/ 6oDo;z\ž<ÜN?]?¤k× _+=Oa…/…—ò ¬ßÊÙë'Ÿ9ŸKŸ]Ÿ‡oï9`Ÿ±ŸÃŸÕŸçŸùŸ¯úA¯S¯8¯w¯ i/¯°¹¯Ë¯Ñyž¯’¯ã¿æ¯1¿C¿U¿g¿y¿‹¿¿n¯\¯Ó¿¦¿å¿²¿Ê¿-Ï?ÏQÏlŸ ¯™Ï«Ï½ÏÏÏáÏóÏF/ßÏ;ßMßb¯àqß\ߕ߭¯¹ßÛóóÎÐËÖÎÖà¯õßß+ï=ïOï€ß%ï^ïyïˆï»ï†¯¦ïñïèïúï§O9ÿKÿ‡ÏuÏÿ“ÿÿÿ¶±ÿšïöÿ o>P otáÿ#°ÙÚÙ×ÙÎàÙéßeߌ"F§Ü‹b¯ÁÓå÷ /:-/?/Q/cÿxÿ‡/™//|Ï//ó/??¢/;?M?_?q?á/)?°ßËÓÂÑ?ãø5?€?OOOO=OFOmO—O©O»O§?ÄOÈ_sOß9_K_`/r/_“_‚O_±_º_í_Ã_ù_#oÕ_GoYokoØ_o2f­?¿?Îoæ<ï À_‰oÉÿ%[Ž aîOæoÍ»|…_~_?Qf_x_‡™y´áóûoŸÃ;ŸMŸ½_qŸï,Ÿî°o¶oãoò? ¯ŒŸ˜Ÿ(¯¯¯[¯‘¯£¯ªŸÇ¯ô²¯©¯m¯$ÿ3¿E¿W¿o-¿¿¯¿¢¿º¿ç¿ù¿ ÏÏÉ¿AÏ/Ï:ë¯Þ¿wϭ϶ÈŸÙ¯ÿßGÏ+ßøŸ:߸IßjߗߡϻßÍßú¯ô¯ïpß'ï9ï]¿`¿r¿ï“ï…ßï±ï!ïíïÿïÿ#ÿÉïÕï@ßDÿJÿXßëß¹ÏÚlÚoÙß)ÿzÿ€ÿ.Cß:d½ïp…§ÿ¾ÐýßâI*<Nï`uïWï–yßÌð//&/ÒÛD/ÞF¡?²¹ÿÈ/Úÿïÿþ/?ø/4?%?/j?a?v? ?§/Ä?Ö?²?ú OU?0OBOWfO{x–O?S/ÌOœOðO__&_ºOØOÏOM_8_¡oë?¶/È_Ý/ï/þ_o"o4oFoz_k_aoŽo oª_ÄoÖo¤_ý? Uo0BoO‡I`ŠO–€_¥ÞðYÏ&_ÌYÒz¯o³ÂÏÈŒÝ̉8Ÿ+Ÿ=ŸOŸ˜”?…Ÿ­èo»ŸÍŸßŸ¦Ÿ¯ƒ'¯9¯NŠQ¯W¯“¯¥¯·¯É¯Û¯í¯ÿ¯¿#¿bü)¿Ÿ¯«M¿ž¿¸ŸÂ¿¿ŒÑ¿†¿ÏÏ+Ï=Ïo¬Ÿ¿‚Ïæ¿ôŸ”ÏÊϦϩÏßn¿$ß6ßOϯKß~ßiߢߴ߯ߨßêßüßï ï|Ïß8ï;ïzïMï÷ÏÜÏÂïÔïßÏŒïøï€¿.ÿ@ÿRÿdÿSï§ïšÿåϾÿÐÿ¯ÿ¡ï"ÿ*<Tß`E‡ß–¨ºÌÞðyÿ#\>M’‘ÿ¶ÈÚïïÿ‰ø4/F/X/j/§ªâÿ¾/Ð/â/÷ÿ,"/'?9?RÏ]?o?Š“?Š?·?É?Û?í?Q?Os/5O,8OhO#O§kOë/¿_Ú_¿O÷)PIVOqO _vŸ}Oa_ƒO›O—_©_»_Í_ß_ô/:_ /'o9oÿ?]ooo„?“o¥o·oÉoÛoíoÿo#5GooS’Lë_°ÂìIãOú_kƒL^z‚µ/¦¸ÊÜô\/Ÿ!Ÿ3ŸuoŠoiŸ~oŸŸŸ±ŸÃŸÕŸçŸùŸ ¯¯/¯ÿ|Ÿ>¯‰¯è­¯¿¯àyàò¿¿ /¿I¿om¿¿’Fů¬¿¾¿Ð¿•@_a¿Ï*Ï<ÏQŸ`ÏHÏWϖϨϺÏÌÏÞÏðÏßß&ß8ß:¿AßX¿Gß•¯¤ß¶ß˯Èßß¿úïSßïYßXïjï4ï’ß ï²ïÄïÙ¿èïpïyïôï0ÿBÿ‡ÏfÿKÿuÿœÿ®ÿÀÿÒÿäÿöÿ, ÿ!ÿJtïšìšï¹ãßÎâïY†;[>•£µÇìëmvú3/E/W/i/{ÿ„ÏŸ/±/Ã/Õ/ç/ù/ ??hßA?&?e?/_?ßÖ¼?×ßË?åOOY?@LO^OV?‚O•?¦O¸OÊOï?îOpO_$_6_H_Z_„/)/œ_®_À_Ò_ä_ö_oo1>o&oboto\o›ÖO¼oé¬à¯âOŒ8o/?Itßm4 y¿o¯ÁÓ % -?Qc{_Š_™«½ÏáóŸŸy&ŸMŸñqŸ†oš§Ÿ¹ŸãlÚŸïoþŸ¯}Ÿ4¯F¯X¯j¯|¯Ÿ ¯²¯Ä¯Ö¯¯(¯ ¿¿0¿B¿T¿f¿Š¿œ¿®¿À¿Ò¿ä¿ö¿ÏÏX>Ï,ÏbÏtφϯªÏ¿ŸÎÏãŸè¯ßßý¯:ßLß^ßpßSÏ•ÏܯßÊßâ¯îß1ßï$ï6ïHïZïlï~ïï¢ï´ïÆïØïêïüïÿ ÿ2ÿDÿ‹ßhÿzÿϤo°ÿÂÏÔÿé?øÿ ï@Rd¿Yÿ˜ÿ¬¿ÿÜß©+…*<N`r„–5ŸºÌÞð//&/8/‘ žÿåŒ/})ÍÂÿÎ/àÿ}/??ô±L?^?x¿‚?Y/¦?§/ÐÜ?÷O÷?$O6OHOZOlO~OOJ/OP/ØOêOüO_ _2_ÃOÒI¸?Ó?†_˜_k_¼_æ,æ/}_oo%oP_Io[omo|?A_£oµoÇoˆ|èo‘o O0BTsofŠœÆOëoäöu,Õ§_ì_†˜kÅ\Ë/à_}ŒìŸ›/Ÿ5XŸjŸ|ŸŽŸo²ŸÄŸŸèŸ—ŸM¯0¯B¯T¯f¯x¯Š¯œ¯¨ߟ¥¯ä¯ÿy?¿,¿>¿âŸøŸ†¿˜¿h¿¼ãÑ¿¤¿ò¿ø¿(Ïì¿D¿^ÏpςϔÏϸÏɯÜÏîÏßß$ß6ßHßZßlß~ßߢßÓÏÉOØßêßÿ¬ößï/ï½ß4Ÿ.œ=φï˜ïÏ¿é¹ÅïzïSïÿ¹ï4ÿÌßXÿjÿ|ÿŽÿûï²ÿÄÿÍÏèÿ ¯0±ßTf¹ï–?Y_KÞðï&8ÿÓÿn€’ÿ¶Ñ_οYþ/¹4/ò;a/s/>D©/»/Í/L/uë/?ˆ/Aå/]?ô/ý/“?*?·?H?Û?í?ÿ?O#O¨?/=/kO}OO¡OMO×ÝbO°OõO¹O1_F/U_g_y_0?´?¯_Á_Ó_…_ ooŽ_E?Qocox?o™o¯Až¯L¿ß¿„ŸÏÏ'Ï9ÏKÏ]ÏoÏô¿“ϥϷÏÉÏÄ¿ÛÏÌÏß#ßÕÏû¯ ¼DßöÏŒßzß›ß7¿=¿Ôßøß¼ßà¯.ïC¿Rïdï÷/ˆï ¿¶¬ïIïßïyïÿÿ'ÿ9ÿKÿ]ÿúÿÿšï¥ÿ·ÿÉÿžßÞÿÏÿ–ÿØÿ ïïDС³7ïePû¿Å1CïUgúï‹, ¾Lây//-o-/N/`/r/„/–/¨/º/Ì/ÓðŸ??Û/¬=n?2?’??•?G?k?äÿþ?P?"O4O›?XOëmOjO­?²OÄOROñý __,<ÓOQ_åOc_‡_H/«_½__E_á_oo©O;oO=Oqo9_ÐO#oŒoËo†?Ýo\o%božo[m‘øoµÇšôLu_ ©ÙTfxŠB®À“ç_䟟,Ÿ6PŸ¸ïtŸ;ŸöªŸŒŸ•ŸàŸ¼Ÿbœ4%¯=ÝŸ[¯m¯¯‘¯õŸµ¯F¯åë¯Ó¯¿!¿œ_E¿W¿l_{¿ ¯9¿±¿Ã¿“¿†oŸ¿ Ï÷¯Ò¿AÏSÏeÏù¿2ωϭÏ>Ï}϶ÏõÏS ï"Ù=¯ÔÏUßgßyß‹ßìϯßCßÏñ¯šßÇßï-ï?ïQïcïuïl¿ ï«ï½ïýßáïÁßÿÏ)ÿÛì7ßöïó/€ÿ’ÿ¤ÿ¶ÿÈÿÚÿkÿ߯ûÿ\ÿÿ&ÿj|Žìÿ²LÖëߦ 0BTÄñu®Àúä/,/AÿP/ÿe/†/˜/#/¼/Î/à/ò/Þ?ø/:?Ð/r¿™”?¦?¸?O?Ü?­/G/Ohü¾?EO|?Ä?v?ª/ŸO±OÃO÷?çO3O _è?ÕOS_üOw_‰_›_å?&\,_à_ò_oo(o:o­_^o@o‚o”o¦o¸oaoÜo»oOño6HZÁoåo¢´ÆØêül÷o $zŒ°#Ôæø ŸŸ.Ÿ¡RŸÈvŸˆŸfO¬Ÿ¾ŸuLaŸ‘Ÿ¯_'¯9¯K¯]¯ÊŸèŸx¯Š¯·¯É¯Û¯í¯ÿ¯“¯¢¯÷ŸG¿Y¿!¯}¿¿¿³¿)¿×¿é¿û¿ ÏÏ1ϧ¿UÏÅ\Ë¿ˆÏˆ?¬Ï¾ÏsÏdÏ”Ïßh¿*ßúÏ6ß`ßÜÏëϖߨßuO±ßjÏÙ™ÌßÒß ï2ïßVïßzïŒïÕß°ï˜ïÔïæïøï ÿÿ.ÿ¤ïRÿáßÂïtïqï¬ÿ¾ÿÐÿpÿ‘ÿkï*ýÿ`ßÿëÿ–¨åÿ±Þ~ï&9J\Z€Ø¤ó ÚìDò/1/¶È:/õ )/©/»/X/º|/??ñ/ú/K?3?Ü/è/“?¥?·?É?x?„?ÿ?O#O6?GOYOW?}OÛ?¡O³Oó?™eOõOnO_+_˜O1_a_s_ãO—_y_»_Í_êß|_ooô_ú_Ko'c$oß_î_™o«o½oÏom/óo)ic__oqoƒo(§o¹oËoB_ïo_%âOžo[mÔo‘ œ_Ç4C‹£¯EWl_L»'±rxçù_ o/ŸAŸŸeŸwŸ‰Ÿ›Ÿ­Ÿ¿ŸŸãŸõŸYŸ¯½ëO¯a¯s¯…¯ÚŸ‘¯»¯Æ=¯F¯þŸ¿©¯—¯*¿‹ï7¯ô¬N¿“¿´¿·ÏØ¿ê¿ü¿œ¹DŸ>ÏMŸ5?φÏϪϼÏÎÏ¿òÏžÏß•o:ßLß^ßp߂ߔߢ¿¸ßo¿ÐßÉ¿ÝÏïß ßHïïÍß¿ïWïEïÆïØïêïüïBïéJÏ>ÿPÿPÏÿï$ïwÿ¼ÿÎÿ•ÿòÿ­ÿ(:L^p‚”¦¸ßßrïÁÚÿú6lïåZ´€ŸØêü¡ÿ#ÿ_öÛóó>&;#;)_ÿVÉ/,)Œ,º¶/È/ÿ}/­/?"?4?F?X?j?|?Ž? ?²?Ä?Ä÷¯o Oû/|?Oú?NOè?‡O6O«OQOÏOáOóOñ?–O,/8&5_V/kÿ€/Œ_¡/ÆOÂ_Ô_æ_ø_ oo.o@o+ßdovoˆoæ/¬o¾oÐoôß_œO§_<!cïuO‘o–q/fÌÞðŠ) ’_DV¡_}_ŒkÃÂÔæø ŸŸ.Ÿ@ŸUodŸvŸˆŸ÷o¬Ÿ¾ŸÐŸâŸôŸª¯<¯¯uZ¯eÌk/·¯É¯Û¯í¯„¯zŒ›’D¿•h¿&Œ¿b¿±¯ ¿Ô¿æ¿ø¿ ÏÏ.Ï@ÏRÏdÏvψϚϬϾÏÐÏâÏôϹ§¿z6ßß”oßoZ߉¼‰¿TßÃßÕß*ß´ßc¬ßï\_Pïž¿tï\ï˜ï®ßíßÿßàïòïÿÿ(ÿ:ÿLÿ^ÿpÿ‚ÿ”ÿ[Ÿ¸ÿÊÿÜÿîÿ¿¤ï'ß6ÅïZ£ÿúÿ¢HWØżÀï>,M\¥º€ï_Éü×éû //1/C/U/g/y/‹/oßxÁ/Ó/¹è/¡­ú/??$?ô/²/?™?«?hT??6?€)O>GOV¢OO·?Ò?c¯×OéOûO __1_C_U_g_y_‹_ÎIx?»_Í_ß_ÎOƒO§Oâ_OOê?¦_„?“o¥o·o­OÛooÒozO#5;OYO“¯Ãoñ_×éû 1CUgy‹Î¯ÁÓå™ßoß?Ÿ$ŸcŸuŸŠo™Ÿ8ï;œ~ŸÈQŸ¶ƒ)¯;¯M¯ªt£ÆŸ›¯w¯ OÞŸã¯xÓxo ¿¿1¿C¿U¿g¿y¿‹¿¿¯¿Á¿Ó¿9ŸŠŸ ϰ¯ß¿$Ì'Ï`ÏrχŸ–ÏGºÏGTÏçÏíŸiHŸÏŸŸ_ßS߆©¯¡ßeßùÏroò¬û¯ ïï.ï@ïRïdïvïˆïšï¬ï¾ïÐï¶ß‡Ïÿ­ßÛÏNÏËß`ÿrÿ÷ï߫όßÉŸ~ÿ6ÿ¯³ß;ßÿJöo5ߺü•œÿP æß¬&ìíÿ"4FXj|ßïÞÿ²Ä‘n /!ÿ0/EÏ-/f/x/ÿ¤·ÿÀ/Õÿä/Ù  ,?/T/ôt?‰±/D?M?Î?ïõOOö/Â?LO^O%O‚O7O¦O¸OvOÜOe_qOÍOH_3_Ú?6_†?•Ÿ_Æ_!_ê_K_úO o2oÌoVo ozo?¡?JÜëOi_ão{_bo+Þ_Oae?:=©»š÷OªoåÍKÄr_ÚكߛoÀ_Ã]?koŸ/ŸÕŒðüŸ‰oŒŸÕ¿oiàŸÚ߯\Ÿ(¯ÞÔŸ¯¯Ø”¯m¯¸¯¯Ä¯y¯¿§Ÿš¯ë¯H¿0¿×Ÿ9¿†ß•o¥¼€Ÿ¿ç¿„¿nŸtܳŸ¿f¿ü¿÷¯‰?¥Ø¿¿Ÿi¿æŸòÏßß Ï:ß×Ïß߂ߔßm߸ßsßÇßñ¯ï§ÏšßëßHï-ïR¯ë“¿Ÿ†Ï¤ÏzWïBïnÏêïÿGÏVÿ‡ï}Ï®ïÆï2ÿMÿOßXßøÿ üï.¼ÿRßdˆC¬¾Ëoy5ÿªÿ¦åN0uïú¥ï½ï¨Þ!/í8/?D//•ÿ’/Õ¿//cÝÿÎ/Œ??1?Â/U6y?‹?C?¯?Á?Öq// O¹/Ç?v?!OcOÿ\ÿŸ´ï²ßÈÏï^ßõÿ°ÿ+=Ogßs…Aÿ§ÿ»Íßñwÿeÿ*ï;ÿK]uïô–¼’ÿtÿÿêÿã¸/‡½qÏ\/M/€/’/¯¶/x[Bf?"?4?F?Ý/j?|?t/q/ï)R?Ð?â?U?”?¯?*O!Oˆ??O¾3Ñ/kÿÒOœïù__ý?cOÉOb_t_†_ºO_¼_Î_5ÿ3O?o(o:oLoa6a?yoY_o¤/ÁoΟåoÝ_ ì_‚o!6WOËÿŠçO®OB™öO[9ñoÙoÒJ/Yk}]»o³Å[?éþ_¤Ÿ1ŸCŸ×ò>‹ŸŸ²oÁŸËÏåŸýo ¯pŸ‚Ÿ3¯9¯Èÿ,ç«'¯W¯«¯®¬¿Ü™Ò¯D¿V¿h¿z¿º¯»Ÿ ¿„¯[ŸõH¯ ÏϤ¿@ÏÑ¿æ¿vÏ…ŸšÏi¯¾Ï¶¿È¿,_߬ÏgÏ<ßNß`ßu¯åÆèÆá¯¥Ö±¯-ߨ¯ê¯±s»Ï&ŒÒßDïVïhïzïºßïÐÏßÏ[ÏÉߌïéïÿ¤ï@ÿÑï ÿvÿˆÿšÿiß¾ÿ¶ïËï÷ÏÃOðßN`ðÖÿŠßK?*äßöÜXÿñÿ÷ÿ8J\n€õ¼¿ïâÿ[ÿÉŒé/@/R/÷ŸAõš/¯ÿ¾/ªÂ)??Þ$?`?r‡ –©f?± /¨ß¢ÙöOú/;OMO_OqOƒO*?ußå/ËOì¿5OàO_(/7_­L@_j/éO?9’OõO(_I_â_,Oo??—_o*o`ou?ñ_‘_¿ÙŸb¿èŸ¿G¿S¿ÂW¯à¿ó¯Ý¿Ï(o:ÏLÏpÏ…Ÿ”ÏØ¯½¯z¿ÄÏu¯RÏjÏ$ß6ßµÏdÌ7Æ€¿•¿ÜÃHß®ßcL¦ÏáߺßßxߊßïÜÏ_ïëσïŠV_¹ïðßËïïïÈïÿö¯7ÿIÿ›ï"ÿ‚Ï‘ÿ£Ïøïtï­ïÊÿ,ã)ïmÿ'9¸ÿëÿrÜ¿ ߢKɯ²ÿê.ÿ#ïÖÿD;zïzY°Æ×ïæûï /õn@/R/–Ú‹ÿÕ ¬ÿW +/¼ñÿ&d/¦?6?/Z?}?Ö//K?É*?ê?ÿO O?`?;OOu?tO\O°O¿v/×OþW?_’O@_R_?ïO‹/¬/Û?ÈSOVu[_*oÿ@¯bÿtÿŒÏ˜ÿªÿ¼ÿŽßàÿòÿ ÿ(Oß=ŒÿØï…ߦ^Üîué0rïQH‡™-&pÆØê / /2/c{h/z/Áž/°/Â/Ô/æ/ø//?.?UR?’/v¯š?¬?¾?Ð?â?ô?OO:?'ONOM/u„O–Od?ºOÌOÞO ß®FŸO_/_A_Vÿe_w_¨O›_­_¿_Ñ_ã_õ_‘?oJ_Y_Oo²¯|?ˆ?Xo©o»oÍoßoño'9cO]rOS_“¥oÉÛ”o´yö/ASew±y·§¹ËÝïÿŸ%ŸxIŸü‚l‚oœ@Ÿ¯ŸÁŸÓŸåŸ÷Ÿ ¯¯˜ŽŸQ:Ÿ9‡¯ Ÿ$¯½¯<¯Ì¯«¯ð¯¿)¿;¿N¯œ¯q¿ü¯Þ¯§¿¹¿üOݿ￀¿ÏS¿7Ïσ¿moû¿(ÏIϵÏÇÏÙÏëÏýÏßaÏÑ¿ß:ÏNß{ßß”Ÿ±ß$ß’¿çßáßÀßï/ïAïV¿eïwïÞß›ï­ï¿ïùßãïÈïÿMï+ÿ–ßOÿƒïÿ…ÿ—ÿjÿpÿÍÿßÿñÿ¾ÿŒ¿ÿCÿT“`·6vløïÒÆ 2DYïhzÌž°Â˜æ /Ÿ./\/F/v/ˆ/š/×õÐ/â/ô/?¦/*?Ä/U/`?r?„?–?g/º??áB?9?Oó?8OQ?«?nO€Oÿ?¤O¶OËÚOìO/OSO"_4__O_[_YO•O _ç?‚™U_â_ô_‘_»_‚ŸˆŸNo=_ro…Y{o¢o~oÆooõOáo ØoDºohz’†ÿo§¹ÕßÈÝ€S%Šo~¯[L‰ ˜o-o…åŽ Ÿ²-ŸµYñOoŸ\~ŸŸj¢ßy?ú¯õ5¯WŸÆŸk¯}¯2¯ÿŸ`ÿDMnÝß»ï ÎæÝS À ·Ÿ(ùÿÎÅÛóóšBÿÅ‚Óås¬!ÿ-/?/Íz„ÿñđ澮/ê/Õ/?é í/A?‡/e?S?k?›?¿³?´/Î?íŸO}?+Oa¿4.Oà? S¿›¿q¿¿¿Ñ¿ã¿M¿ÏÏ+Ï,¿õ¿ª¿¯¥¯—Ï©Ïê¯úoo¯gÏ‹ÏßÄÏ ß$ß™¯XÏ^Ï–¯<ß·ßÉßÛßNßDï#ïRÏJ¿Dïkï\ïqïYï³ïÅï×ïéïžï ÿÿ¡ïCÿzïgÿœ£‚Ï‘ÿ£ÿµÿÊÏÜÏ^ÿß8Žÿ¾ÿˆüÛóóE!Zßåÿ4ÿpÿˆÿ´ÆBHÞH èÿ#RÿGkFÏM’Å×é­¤/+/°žC/vÿ¨B©/Qð|I/ÿ»/‚/?6!?ðyix?d/|&?Ž/Æ?Û?/ÿÙ‡?O/O~?OeOwO‰O;OSO¿OÑOãOõO§Oþ+_Gï7_a_úÿš,H?¸_íûO[S¨?o÷_*?fð?-oâ_R_oo±oê?Ø”_ü? o/ew°;P¿Ñã5­€§7Iõ†6?‘£µ]oÙX†‹Ÿ0o*Ÿ9ŸÐ%Xy_¨ŸÃß=ï°ßaï€ßäϜϩï‹ï•ß+ïô¿ÿÄï'ÿšïáÏÊÿßïRï|¿¥ÿºŸÛÏÏÌüÓïuÿ 2‡ÿ†ß<üfüeiÏA¼Îàò§:­^P±ÿÿŸÿ¸•(ô)»HÿÁ0/ú/ÍIXïPïbïtïï˜ï²Ï„ß–ßd?òïÿÿ(ÿ:ÿLÿ^ÿ3ßãé¤ïªï²ÿã/ßÏ«ß yT߯¸ÿ?ßN¯HG/¿ïÔ㦟îÿ½ÜßÿfßóƒïÜÿ;`JqŒï ÿ„ÑïÝ6ªì/7/I/[//4/%//µ/“ Pè/Ü/ /…/& ?f?r¯Š???½ßo?Q?ö?OY,Oç Éßí?nOr??¤O'?ÈOÚO“?þO?"_éOF_X_ìOü‹_y_¯_Ý\K?â_ô_ ß‘_©_…_Ù_Õß<3o9o _Ö_l«oêoüo·o_O2V;OzožoÂÔæ¨o °¹ï.d _v/š¬…D\Ó ?U*Ÿs¨¯qxo„ŸÇ\¥oôÌo®ŸíŸÿŸ´ŸWŸ5¯ÆŸY¯&¯}¯Ÿ¡¯³¯!Ÿ×¯9ŸÞŸ‰¯¿È¯ò¯4¿g¿U¿y¿*o¯¿Óÿh¯ZŸÓ¿¿¸¿-ÏI¿ú¿fŸxŸ‡ÏÎÓ/A¯Ïû¬ÞÏßß&ß8ßß¿\ßcŸ€ßðϤ߶ßÏÚß<ÏþßÜøßÎßòß4ïÇYIï©ï¨ÏJßeßÐïÕϵï'ÿpïÊ¿wߌß?ÿóËŸÆOñï ŸäÿHÿk,ÃÿPÉÿoÿ˜Øœ°|ïÝ„ÿžï%éïÏœŸF£I>ºÿÐÿ‘!/3/úîxÌêÌd®ÿ8º/‚ó/Ã/½/)?À/M?r/`/;?ö/¹?Ë?6/?/ž?%OÔ?ï?CI¢,ŠÿUšO¬O?b?ÍO_?XO_*_<_Nÿh?u/ÁO™/ÁÖO??ê_OZ_ Ã_DoVok)oÞ_¡?°oÂo|OæoÑo†oO.Úo‹OŸ_¿ˆš¬ oboeoX*<oklÓi_¢_Ì_zo E~ÿÁŸÀAŸSŸrwŸoþo›Ÿ¿Ÿ=ãŸÑŸ+¯ÚŸO¯œs¯…¯—¯©¯¾vQÙeŸ†Ÿ¯¯¿0¿²¯ß¯iÕÿ¯g¯É_ÃÒ¿ ¿ö¿EÿÏ,Ïè¯PÏo¿tÏ~¿¯ŒÏ¼Ï:¯àÏ"¯ß‚O(ß×ÏLßa¯X߂ߔߦßß;Ïi¿€Ï_ï$ï6ïK¿bÏÓßþ°ÉpropDATÿE2-2ÿ7-2005, ï7:35áNAMþ”á DEMO_F÷ONTáORIGþ•ácancunsÿmall.pcxÞ¹á +Üãõ•à •à©•àöíóãpð`¿``ÀàÀöáÒóãØ%ñöç óåÕ6>òÿDð4DòdñlPðöäòã88<|ÿðø<üøø8úöáóî|pî`ÿîÀïÀ}ÿ€~çÿç æ<úöè óç?€sÿ€w€>~àÿÿàçÀãÀsÀ?Åàý`óöãô8wppàõð`p0X÷ß p08 88¹pÌò4ö.Pðýû?Dð}L(öë4ööåNÿNöäÉóëÝð@÷öâðøè^öâô óçÀë€ð .0gpÌõ©ÿqÀõñ~áÀqÀ€þððÌó>8üßþŽº9é~*öäóã8~ÿ<<Žþ|ºöá óåVû7\g€€ÿò¶öçòä|xx@[x< øð: ¾Ý8Â~çž~ü ö6~þü ß00p`: >‘wÔ¿ðžf¨>œÒ!Šòè˜øqÂ``w.&?pÀàp]|çøø‰.&€€àß0pÀ€€oøŸüœ8p8"¥ ÿÀ€@©-ÿßõLùºÏ!>ÒvgDòÃó€öåÄ(>ÿ€­óºñ¼ðsºðAG: ·ðÂ%5p&嘆ø sêO2ºð©ÿ ?pÂ|äs1pn2/þþü—ààü•0ÀòÄ(ú&q$2ç€ç€óïà¬0å/v!10dÙ3c€#dáÌóêöBç0pðÌò¨sÀwT0+~ïàgè0Áß÷&60ñðþƒ2¬øÿ0À9ÀyÀ{ÀÿàþàîàÌàçÈàÀÃ9 #ã«ó’@ûDòïœ@çc‚4?¬1ºðáÀ½EH1Á?õ"û!1~°; î@ÉÛ áàÉðÀQßõ¬JáEw*fÚ çc€Ãßõòä8|äàfñœ„Ä(cÎ$qUä&< žŸæîzxÌO€ãº0sÔ~Ô"<.]¬øÿÎ`î`æ`×ïÀîP{ºð1€½!.æî||cð~SîÆ9 ¡Q~ 0<-cûò@Kþþ ¹î9¥€^hà§ -10¾ú«ðñà€SÀßóò5 œhàñå0xÌöéÚZÌoÿíP ÖiÄ/Ö/ÐOú/‚_?0?B?T?f?x?Š?œ?®?ÊOÒ?ä?ö?OO,O>OPObOtO†O˜OªO¼O àOòO__(_:_L_^_p_¶”_¦_¸_Ê_Ü_î_oo$o6oHkÁd^b–¦À¤^i «µ¤õHøÁ°Öiœ/®/ ñŽç7÷-08ä11:2õ7¨è´æ_LOGýO½è logofwontÔæ#ma²Séæ,—¿“¿¥¿·¿É¿Û¿í¿ÿ¿Ï#Ï5ÏGÏYÏkÏ}ÏϡϳÏÅÏ×ÏéÏûÏ ßß1ßCßUßgßyß‹ß߯ßÁßÓßåß÷ß ïï-ï?ïQïcïuï‡ï™ï«ï½ïÏïáïóïÿÿ)ÿ;ÿMÿ_ÿqÿƒÿ•ÿ§ÿ¹ÿËÿÝÿïÿ%7I[m‘£µÇÙëý!3EWi{Ÿ±ÃÕçù ////A/S/e/w/‰/›/­/¿/Ñ/ã/õ/??+?=?O?a?s?…?—?©?»?Í?ß?ñ?OO'O9OKO]OoOO“O¥O·OÉOÛOíOÿO_#_5_G_Y_k_}_‰Xx¿­_¿_Ñ_ã_’_oo+o=oOoþ_so…o—o©oXoÍoßoñoÄo9K]o“¥·ÉÛŠÿ#5äEk}¡PÅ×éûª¼1ŸCŸUŸgŸŸ‹ŸŸ¯ŸÁŸÓŸ‚Ÿ÷Ÿ ¯¯-¯ÜŸ@Q¯c¯u¯‡¯™¯3°L¯Á¯Ó¯å¯÷¯ ¿¿-¿?¿Q¿c¿u¿‡¿™¿«¿½¿Ï¿á¿ó¿ÏÏ)Ï;ÏMÏ_ÏqσϕϧϹÏËÏÝÏïÏßß%ß7ßIß[ßmßߑߣߵßÇßÙßëßýßïp!ï3ïEïWîHD;WæÿKKJJE@80þWãLLGDB@>÷<5(ãEB>=¿;;;8+€áFýA–á;;91ÿJHC>;;:þ—á2 DE@þ¤â;98-ó;@±à³á95#æH 7<§à§à7-ýH 157;88ï75-çá(ÿ+12/* þõãôWá ø'ÿ9ÿKÿ]ÿoÿÿ“ÿ¥ÿ·ÿÉÿÛÿíÿÿÿ#5@¯Yk}¡PÅ×éûª@1CUgm5‘£µÇÙëý/!/3/E/W/i/{//Ÿ/±/Ã/Õ/ç/ù/ ??/?A?S?e?w?‰?›?­?¿?Ñ?ã?õ?OO+O=OOOaOsO…O—O©O»OÍOßOÀñO__'_9_YîFBøkçh_z^JGEGJÿKEC@@BCCÓB8z_¬^KuàFDÞ—P@>=A—PB>ó85¬_ßZLKHBÿ>52--/58ú—à=•à=>;71üß_èWLF;%ÿ -8<àà¤â=;5*oêUïJ;# ö#08äßá¤ã3ŒâxoLG›+ ù(1hd´à8³1$zo‰b%®k(I24d³à7›â°o%þs-8£â´á91âo7LF&ÿ>¿ä´àÇ7%äoöoBB4£ãÛa*K~H+Ãl–s³DCÝà²ä-–|G35–EC£ãÒá 1Ë|7K~×y´áÔáñ ‹ê}Õ;;58Çf‹81_›Ú{8+ ŸÐÂq†97(UŸˆRÞtÓᣠ Ÿ:ŸsáBAv.Éà^ŸpŸŸá uÖ㔟>ŸÁK°áUŸÏŸj¿æ5!h“ ¯µ—:Åà4(j<:¯äž87.#.¯s¯8íSÞrö*c¯¨¯~€–9;75(—¯Û¯…¨75/a¯ ¿fÿE?;96/#–¯B¿!¶@;’¯q¿P¼86/!ý¯¨¿¸=q7.¿Ù¿jD;0É¿ ÏjC5%ý¿AÏjÇB/1ÏuÏiJ@ã)eϩπª18˜ÏÝÏçY;ÌÏß"Mj5‰Bßë¼*\gn߀ßVbfߪ߀oÎßaCÒß"v(Ÿ}ä=ï†âE#úŸnåtoíSA“Rï+åo+d†ïêV4¾%²;-ˆR¯FEEDØàCØçGçKJ@˜ßY´79BsEJÁR ý@/ ïïÛLK]°;<•RA>™=``=;AðCñ=û;7ùŸLLGC? rIð:`vþ9ˆ[±`¸v÷‚¬ù7*Œÿ@ vƒÛö… Ãl›òÛõ ¤b01Ü[²  ½ý~4ð=;8887qî}73ëHB4++***¤§¨÷*'eÛA9#‡  ÙÙÙ áíì4ï.@Rdvˆš¬¾Ðâô//*/óÔöÄíïŸ"öÄï,ŸöÄŸXŸŸ|ŸcŸ Ÿ²ŸAŸÖŸ‘ŸúŸ ¯ÇŸ0¯ëŸT¯;¯!¯Š¯E¯®¯i¯§¯ä¯Ÿ¯¿€ï¯,¿>¿Í¯b¿¿m¹DøÐ☿S¾JGGH@ù™¿|¾KGHJKŸFDB1Å¿@ÙÇ3ðGD>ð=7ô3ï-ãÇLJC@Ñ>ŸðˆÿøÔ$Û¸KChŸó½ÿÅÓ%ÇJGÒóÀñÿ„Ï’€Óó&°ÏJCJBuórϲÎÔàA€žÏ ßÂÁlòËÏ7ßïÅ9øÏ8ÞHG:$ßßHEÈÁFÍýÐÎÎ#JCx߸߶´KwÔ«Ü`ï×PÝèß¿È98\ ÏLH*pï(ç#Æa 8œïä°::;74! *øC5Éï1ðîkÄ95+RÉA:;ÿ@CCDECED\(ð'óHKHñÄ;{Î"ð?/&áýÐ?BÅCPþBÑÓ†ðMðBBý5FðGE>9;Á8¨ùìò öìñyð7( ÿðB6-©¦ú+³/5{ògò71¥ñ%žV±6& ÙÔù÷-7ô980Ë ÷oïB?pÞã¶àÃ. EEB~ó×ÞYGFï…œtñKÓ95!¡ÏžîDòÅÃ;JáHKB>Ž€ò8- áŸí£Ô:€Šë6¿È<ð*žîðÄ:U“Uå'ŸñµB–ðÃ8+þ±ŒðÅ.à-0íìÝä.à4/´‰0ÿÑЀòt.(E/“äÿFGKJFB=8ù9>ðŠ!87542½1m/HHEbñ5§1-+²ó³ñ)¾ +÷-(˜.( Ôõå!ôð  ??'?9?K?]?o??“?¥?·?É?Û?í?ÿ?O#O5OGOYOkO}OO¡O³OÅO×OéOûO __1_C_U_g_y_‹__¯_Á_Ó_å_÷_ oo€-o?oQocouo‡o™n`™o¿oÑoãoõo¤o+=Oþo…—©»jßñ'ÖK]o0¥·ÉÛ휟#Ÿ5ŸGŸökŸ}ŸŸ¡Ÿ³ŸbŸ×ŸéŸûŸ ¯¼Ÿ¯C¯U¯g¯y¯(¯¯¯¯Á¯Ó¯‚¯”¯ ¿¿-¿?¿I¶=ø¯m¿¿‘¿£¿µ¿Ç¿Ù¿ë¿ý¿Ï!Ï3ÏEÏWÏiÏ{ÏϟϱÏÃÏÕÏçÏùÏ ßß/ßAßSßeßw߉ߛ߭߿ßÑßãßõßïï+ï=ïOïaïsï…ï—ï©ï»ïÍïßïñïÿÿ'ÿ9ÿKÿ]ÿÀoÿÿ“ÿ¥ÿ·ÿÇGEÃC;g/ìÿþÿV FCÇB7*LEA=;5<g>;E@ 7%x¥|!7) ´âñÁFQ­ßñKC#ƒY·."®”kpÈEЦG@>]#„/1[ \#ÂM/o4$ÿŠ/ D~¾Ã/ÇýD<¼7${/?ìE217»v"¸/C?>íJ/;3!ùøò/}?ê;@BBù7+2?½?5?CCç!±/ ó?èH*Ù0Û0&6m?t5O95ÐDC>g3Ç;:7è?sOï?@AU@Bï/«O8ŽBEA-?éOV6BÍF€â4 O+_MFÍOX_._@C _•_ä#UI_Ô_2]”W“D6!7“_ã_KC;»V†[Ñ_l_4gÃ[oå$ph=oÈoê_so…oÕo>¬iÃV!B$Åo<-œ0LxH”G o1B1æC'?¿Jÿ=88@CCED<ßpÞpHLHB­(|þž*?;9>ABCƒA3 g3þ¹9ÿ7-+++-,-~Vƒ+--/59ê/|v[15  †  (7è&1&j~V̈8~j ‰@Ø1 žB 6«8*!.ŸIª?ƒˆŸ„ZèÀ†ŸŸž}ŸŸÞŸ†C/¯Íž¡Ÿ-c0øŸ ¯¯Bq¯E¯„”¯ñ4“¯V¯—s-0 ù_ L>+L¿¾¬ù9-N¿}ˆ¿¨¶GÅV94Ö¯~3ñ¨¿ÏõE;97-õ# H2 :7/*xå¿•u¬&981-Í÷ßJKKGB3!98Ÿ7=AA7ÆþMÀEý?é'998;;5nKGCQÀ98Á;>@@6-&4üNÀ‹À:89788ü²ÃÀ7+D/E@71R*ÌÂÉÁ÷# 4§DEB>Ã52R€ÏÁÎÂÌÂ)!=A  ™‚‚z Ñ%z! Ð Ô*ÕÜEßWßiß{ßߟ߱ßÃßÕßçßùß ïï/ïAïSïeïwï‰ï›ï­ï¿ïÑïãïõïÿÿ+ÿ=ÿOÿaÿsÿ…ÿ—ÿ©ÿ»ÿÍÿßÿñÿ'9K]o“¥·ÉÛíÿ#5GYk}¡³Å×éû //-*`-/S/e/w/‰/8/­/¿/Ñ/ã/õ.I¤/?+?=?O?a?s?…?—?©?»?Í?ß?ñ?OO'O9OKO]OoOO“O¥O·OÉOÛOíOÿO_#_5_G_Y_k_}__¡_³_Å_×_é_û_ oo1oCoUogoyo‹oo¯oÁoÓoåo÷o -?Qcu‡™«½Ïáó);M_qƒ°•§¹z‘FEÑ€DÒÔ€CÔƒÝCÒ‚EDÇCB=¼ŸàÂC@—BDCšBŒÁC³=7?ABÙ€B;ŸNÿ!&5>>=o=>=;f‘;=½Àß  wï!-8B(@@B3A9NŸ›+8ùµzÁ÷6*9Ø&4o;>?@*71›Ÿbåœ>Ù°£‘ 29Üû$2À=;=<7¹.åŸ.«BC´n¿¿ü°7) ußpÍǎ¹¿6ß;8*”߆ñ°HG@ÆÏ}ßH¡-ïðЈÆHÏÅß¶’4ÀÜ¿ª¸³À’ÏïH¡6$@Kßô±¯µÚÏWïc£'%ßpñÕßåïC¦5!+ÿ ‡ÄŽÒmß©¶9þßÍÆÐDÒµß2ÿü²-"ÿH$?Å 0“ÿGÓ¨Gï‚9é9#xïDÏ|ïŽàoêÖö·kßÉï—ó×±ðŽß#6èÖÓÕ_ÒÒ¶¶vÙ¢¨ß³ïº aëßúÿ¬ô±‡Ç¸kTßÃ8-úHÈÐÇŽï)*K+ý“95#ÛøGÉóÔÑ.Ô/HDѶ›*C=± Kÿ¬µ<"Ùå/×±û/Ç :®,?>?í¶€Ç/û?}?ÿ?[?ĈKe¶8IÿÌé&c?ObA( OªRG=O85*°OY;’ÿ&ƆLD@Äô@_ó°yHÐÿg_LLE@f³ôOâ;n_£>_Ä3ÖÔ«_vZ9„_ÇÏØÒb_~wX9884(oˆ‚Ã÷"áeoyUZ`5ã0!o€Ç1g94ø®ozQ@75.$a¨oSE¨öÖ²-#±móLKä`é`1*!ÉðosW?VŒ±71½,›*KKGB`p+Ï(!6UCGFÙHÈ1g 87žw75û;CäƒDEGFBÿ;51+*  ¼|9¥BBA=‡ .ã+*åräqäq)*+û27ü“72&Ï ÂŠ -ƒö2† y   Zl~¢´ÆØêüŸ Ÿ2ŸDŸVŸhŸzŸŒŸžŸ°ŸÂŸÔŸæŸøŸ ¯¯.¯@¯R¯d¯v¯ˆ¯š¯¬¯¾¯Ð¯â¯ô¯¿¿*¿<¿N¿`¿r¿„¿–¿¨¿º¿Ì¿Þ¿ð¿ÏÏ&Ï8ÏJÏ\ÏnπϒϤ϶ÏÈÏÚÏìÏþÏß"ß4ßFßXßjß|ߎߠ߲ßÄßÖßèßúß ïï0ïBïTïvA`Yïï‘ï£ïµïdïÙïëïýïÿ!þ>ÐïEÿWÿiÿ{ÿÿŸÿ±ÿÃÿÕÿçÿùÿ /ASew‰›­¿Ñãõ+=Oas…—©»Íßñ//'/9/K/]/o//“/¥/·/É/Û/í/ÿ/?#?5?G?Y?k?}??@¡?³?Å?×?é? QH°pްpCB;í?O½EEþÛpCGHGB>=ÿ>BDCCB@<ó5%"O#OGGHHÿC;1%&5?@Ï=;0\O\HHJD@8-H‰;*8ÆP5#–OxÿJKHGCB8*{ ïm>@;9_ÞzJGDBt@æ_BBñ_{GC?Ï81$ïo*`ECÏ;5!h_VW@;g6*e_uU1¢_œc™Q<85^oäUDOC8* ä_ObF×PŸ;7/# Þ_ïV7Ó "oÒQEÞp;53*¡_`fCB»_ eÎË`5*vožg@;É#_Le8‘oÜk2(ÑnLLÖQŽo=ñoLE@>úpÍoðX´o@pÊ`;96*ððo˜nCp:;70ÁˆÖoDpFp!äêsoP&8‚Ã8/_cûq:9¨ÄOɶmGBp:v‚-˜uoŸÆ[KCúrq#ÈFŸ›E`³;7.÷ƒŸÞ+Ÿ·ŸÉŸßCCCqð82|þŸ ª}H¤•:;8+ ¯ô=¯ZEã•97(ØJ¯{¯IJB!¥951 ³o¸¯Å©FGh’ð‚H_ô¯l\DCq$£-+¯;L@DEC8°9¸?CECC@.wR±ƒTDq@_ä@Cu¿BE@‹2i G*”ð€^¿ÿ=8425;;==<>==>¶°}>p84-+!-rñJ*•Àpù_Ï 09§“§•*7 ˲HB”µ›¿·J哵€6*-vפ—´ Ü¿ª´LÇÁpä§BT·Ï"3WCp7÷Š;BrÅXÏðUMÇãª@ ¦“ÏqX€Ñ¸Ù851-*( Ãü×á%*ß*+2;BD@A>þ p.*(! ãÔ ñ ÿ*,-*# Wä  GŽ ²ÄÖèú //0/B/T/f/x/Š/œ/®/À/Ò/ä/ö/??,?>?P?b?t?†?˜?ª?¼?Î?à?ò?OO(O:OLO^OpO‚O”O¦O¸OÊOÜOîO__$_6_H_Z_l_~__¢_´_Æ_Ø_ê_ü_o o2oDoVoek`eo‹oo¯oÁopoåo÷o ÊoÜoQcu‡6«½Ïáó¢);Müqƒ•§¹hÝÂ7ŸIŸ[ŸmŸŸ.Ÿ£ŸµŸÇŸÙŸˆŸéŸ¯!¯3¯E¯ôŸi¯{¯¯Ÿ¯N¯`¯Õ¯ç¯ù¯ ¿º¯/¿A¿S¿e¿w¿&¿›¿­¿¿¿Ñ¿€¿õ¿ÏÏ+Ï=Ïì¿aÏsÏ…Ï—ÏFÏ»ÏÍÏßÏñÏß²Ï'ß9ßKß]ß ßmߓߥ߷ßÉßxßíßÿßï#ïÒßäßYïkï}ïï>ï³ïÅï×ïéïûïªïÿ1ÿCÿUÿÿyÿ‹ÿÿ¯ÿÁÿpÿåÿ÷ÿ ) 4ØÿM_qƒ•§¹ËÝï%7I[m‘£µÇÙëý/!/3/E/W/i/{//Ÿ/±/Ã/Õ/ç/ù/ ??/?A?S?e?w?‰?›?­?¿?Ñ?ã?õ?OO+O=OOOaOsO…O—O©O»OÍOßOñO__'_9_K_]_o__“_¥_·_É_Û_í_ÿ_o#o5oGoYoko}oo¡o³oÅo×oÀéoûo 1;;- ”þHtJKJD>2%ÿ (;FJ¿KKE@=;ìp7ù)‹|sKKGC@ï0÷s7DE{C?ër95 ÷~~rGC?8*„îÓðBB>ër:80¡D‡2‰èpïpZˆC•Bºp:íq*òrCß?;5*Z‰DCÉ<ìq"€!ZnA=î¦ECëq:;8Á2Y<‚Øv‰ç†;;·8+ öE@ºp8u/ôGë„7(*Ÿ.êq95#&J“#€ý^Ÿ>;:96* ÁŒKKB!“Xl•WLFAU“ŒŒl”r‘?}KCºp!¦78-ÝžG@R§ ¯¨8Œ‹T £>¯P¨½&‰L!¤s¯Ð¢Q„óŠo‚U“.ª¯¼¤%œT  “0ۯѥ‡€ZšKJ"£ð€11ôµ‹JF×€£¢r‹JÖíKE “Ì­KqDB$´%›JJõB¿´;w½KA@’¾²:¨°[™Gî’X¢-J(›LypB»“ŒœEÕ³œ‡€¬B˜óŠGcC>‡#‘Œ‹F ƒ’Dp´'—=Lp𤉠±Éå!ÓðHÄ-ÈJ*cJHZÄU€Œ‰G#7Çú+À6Å¥L7 FÄU¤#œGðÁPÕµ4–&ƒL:(B”*Á-±MÜvp¿´5$|s;r(‘;<‘…ƒ94Ú2upHÂÂב1(jÕÓð™@$´\±.*僉ÔýH?Ö987;BCá4(”YæÂà=AB—A7…HÕµ¤¢2åw¥A Ãä>=4¸Šx†”‡‚5*D†;=aæØ5+¸ôÅØ—60!©™7%¡=¢8å5žëD³´á*ÞÁ‰1578´à87O5-$ÓêPà;ãàç75.ŸêÓñ(*,ÿ020+( þÁŒ35551+(óÓê‚÷ ý&#% Pÿoó…‡ý‚ÿ¬ÿ¾ÿÐÿâÿôÿ*<N`r„–¨ºÌÞð&8J\n€’¤¶ÈÚìþ/"/4/F/X/j/|/Ž/ /²/Ä/Ö/è/ú/ ??0?B?T?àf?x?Š?œ?­=`­?Ó?å?÷? O¸?-O?OQOcOO$O™O«O½OÏOÙF,ˆOýO_!_3_E_W_i_{__Ÿ_±_Ã_Õ_ç_ù_ oo/oAoSoeowo‰o›o­o¿oÑoãoõo+=Oas…—©»Íßñ'9K]o“¥·ÉÛíÿŸ#Ÿ5ŸGŸYŸkŸ}ŸŸ¡Ÿ³ŸÅŸ×ŸéŸûŸ ¯¯1¯C¯U¯€g¯y¯‹¯¯¯¯Á¯Ñ¬Kø Ðѯ÷­HECCH}JÃÐA@BA9÷¯þVçHGB/!!ÿ*19@?ABBç>71 ¿Ï³LH?K(à³-wáxà5èÓ^M¾KC5næ>§Ó÷91%t¾LLKGãA/‡è@°¦Â7)ž¡¾FC=1‹·‹Á<ú@Ä£½EA;5#¸3ÔÁãŽÄ92¤»G?C?:7*›ùÅo95# ¦¹E@üàa/—É¡Á÷Á.Ð5 ÿÅÊYÃ>LÁ%»sÔ80dcÇ[Ã;õ°›úKK Ó97* ©ÌMÀ;å4Ôî)Õ5 ªË;81cˇ°^Ó7.‡åÕÐÀxUçœÒøÓ;85!;å€ôÀyâyÀ ÉѨуà(ŠõKwÓ:¤ÊXIJâ43)nåKÕ98<Ú¡ÕÀ·é‰ÖMÀ ȡ҃à-#<7øKÕ;;4|ư°¿C>851*úJøŠÕLÁþ¹5-)!òiûG_Ô~à5-(ÿFECEHEA7ß/# ýEEüGÃ=à5+(7A9?) iÿnÂ|óš± ¨ï}·FÃ>á- Õï&»ÊâÁ<Ü,þFLÓıÿXü!BFÄÑJÿ„û;–³Eó) „ÿ±=¨õ@äÐ#+ ¨ÿ/±q¶BÊÂı§9-Óÿ®°7ÏöA½B‘ä;94þÿcL;Ï÷l±;ä7-Cåʦ¸:Ïù7GÃ>á80í(¢¼J5Ïú159tCó¥Ñ1 LG+|Çβ*28Àã73å-¿É#ÿÅ)(17y8Ñ{>BDCsàßFGC/Ìï%û+2ü9;=@BÿCCBBA;/iÚB*ûY¹Ó?74+$pÿ&)*-26ÿ751+(  ùiž &(! ¦ï˰ »ô//*/=8û0ä9A?=>Ø4673rïLLwKEA95#>û7=˜ð>;=;8?5.--+*=ƒã<÷ð6* äÃõ3?! ’ºŽ70úà!0t©ïEåCIó5#VúÍCjô4 VÿáLE¶Äó819ûEjò:Ï;7-ÿàHG@Ió7*Éû»ó0'5)ÉÿÙðEÔà£ó5!üõô;:8+ÚÐ09«ýºöMðÝ=HJHó:8ó- v /;82´æüàD£ô;8åýeGj88üê=A8ãÌO;7+“ âÙ?ÄÖÔKB;7é(¯à>Ýó:8*¹ Íþ¦4_g8>1KE‹‡5(éÎã¾ózKkKBÔà:Ãà*Юâ158úñ8!L΋85*ÏI%*1[79úð-\ü>Àñü/„)%+489;Û4yêE?úð84ó({/¿($18êÂð! )@âð5.!üA/-8974-(þ}æC>851*!óí/a1+(%ï&3BCOKG=ÎI0!ÿn?K7ÿ  .;ÿBC@4! Ñ%?¥?ƒàDŠõÇ•?Ú?¤%7xà?Oâ?E@0OBO‘þ‹œ*uO‡OùjðC7/5¬O¾OÕÖA§ñG754ÆOóOÐÚDs!a;Øâ_/_ÔGCúà~m=>=?BA(ïl_ôBÝó3ñœàaàY_„¨_â;¬ lQ›áAÀ•_ä_ÏåÄUŽQÍRB?>?7è_w\ôÇRc b@0#o— R^ f–e==¡@1]o—gFÏ;478rcwn;5ù*—oØÓCEE2ç(2¬oó91%þÌoKHKHB4%)çoöøó7+t KLJGoC;! É4[ 78™ *}1Åû¼à†àó8&pu&*Ÿ,4589" wh9³7&c)„â=;«ü%-26ŸzÀÂð:¡ðÀâ’Òps&-#vQ91ÒØxÜó „(47&t‹;:Äà Z5zˆw!08¡u95 v0KP½òr¶‡$17eæ aAÁqo‚ñ†-8Q‚¬Š@ÚA\€b+bR5™ –>•4,Ÿf–B^Hò98-É85$s97-#fŸ³ú¯ Æé¿+27;" :71¥OÕ­#ú”!#qh5ðÑŸ æCâð.#ôœ¿*1Ûp;§72-¯GãB éÉ?[p(Ùq776LPofò80,¯¤¤€á,S€Pl„à=/!ùf¯Êx%+-Ï1019çÐ'áHEÿCDGHE9$ù”? ÿ2?>62;CÿB0! ø¿W¿v 9sû…½`…¿«¿½¿Ï¿á¿¿ÏÏ)Ï;Ïê¿ü¿qσϕϧÏVÏËÏ0ÝÏïÏßßÄÏ9ßKß]ßoßߓߥ߷ßÉßÛßíßÿßï#ï5ïGïYïkï}ïï¡ï³ïÅï×ïx[Låï¶vF1"Ÿi&8ö?¾ÙcHKJAF¹LûHE\ðDEDGJ¿KGDB1 ÑøH_GCDEC{óBM`ý*x( /;g@>=UP15!»šÀ½Q6däXwNT97­C¤˜€¤ýhæ¡BÚð ˜o)øÿ:@N œÖÙBK…E"†M×¢ÿÖE¾!2ÂÃ(,†JÿQ7(‡ù„E›±dYJÞ𥠈'¥DÂaß~Üšù î 4)9PÜ`J¼od:¾ÿµù\ ]€/‚'6/ Úÿ¹)€8?FñMSþ/ap?F)5!­?‹/a„%©//‚À/ vlƒE˜KáFÙ$:ÆÄxH \ÿvL4v¸ç…L9GbýpŹs;GGƒ94n ¡KH5HDEµõ?858BGC†ú—ð¾…;870K7üNPV985*öL15Ê8875÷-!O(+12Ÿ0+( ¿;¡ ¿œUTuµ_Ç_Ù_ë_ý_o!o3oEoWoio{ooŸo±oÃoÕoçoùo /ASew‰›­¿ÑãõêA(ß/ASew‰›­¿ÑãõŸŸ+Ÿ=ŸOŸaŸsŸ…Ÿ—Ÿ©Ÿ»ŸÍŸßŸñŸ¯¯'¯9¯K¯]¯o¯¯“¯¥¯·¯É¯Û¯í¯ÿ¯¿#¿5¿G¿Y¿k¿}¿¿¡¿³¿Å¿×¿é¿û¿ ÏÏ1ÏCÏUÏgÏyÏ‹ÏϯÏÁÏÓÏåÏ÷Ï ßß-ß?ßQßcßu߇ߙ߽߫ßÏßáßóßïï)ï;ïMï_ïqïƒï•ï§ï¹ïËïÝïïïÿÿ%ÿ7ÿIÿ[ÿmÿÿ‘ÿ£ÿµÿÇÿÙÿëÿýÿ!3EWi{Ÿ±ÃÕçù /ASew‰€›­¿Ñãõ*F=@/HD</›$óB;2/0AHJGBó9.y;] JE@>›=3úJKD w 2þ~.KFECBA=û0J'LLKGD¾ª @?>/J+LÙK¼ ‘ >@Ä,LLnØ A=>n@3±'gHECÛ n@=;ËDh³(1Ã0<;LLv!îþC5#b58-2;<492Ê)0AÅ=¥2:©0Æ'» B@4¥2SBœDH&Ro3÷96&F5KE5¸P1o37@1“EBÏ+(09VtEG#vJABB†397'’FÑ=ÌA3q20uEL;hF1EFHã2CÃBnª@5![D; ä3®5D;7,¯E@F2BmB¸48*Ã2J%J#¹EÃEÚ5ByJ:w97( SLDöC–E7(Ã1L•%~D:Ö$EF\4G4E95› ¶"G#Ü4E5M ‘1CJ$üE7pCæuFJD FG+Ü'UC80î@H-X"&HUpCL1G5KgEÆT@/‘4wPËB97a+F1`CŽZ»BBF6éFDëEF5GFAÖ 35#‘@C¯&GG4CTHú&KE·4 Gx#%c¿0BVVT&d£01QQK•&K’T£;9oDR(4E1ú 5‘C)Y8-å1 Uò@ðž5ÌUT&Xf5+8µ!³o8+1H)„'Cä)coJÝR}R53&ücgv9.C5°ó5tèAanKE=4:ç95(.vPx94*31€gjw5 @T#%gJB>»2ôlJJ“SÆ~QI(,7W`Ÿs98-lõTâR>Dãyk@7-gLsŒ1óyÀ#c=4t0i'dèB#ƒ(îa¼1<‹)X~W&\s0×ypËC9‡‹¹iŠ|wTŽ‚y®ky.ØyŸ¯|ny"ŠRpþEóyt>²yœµuÕ|Rt©oŠ™!‹ÿv~œµtôoÕ˜kŒJ†ž45Cµ€ J$C$—{µ¨-UfŸˆ5!®dLc$J#G@þFŽyß…:<‹´x.Ú5L@ ž$DW¯ˆ™µŒÜSÍJe!¦ u•«lãED<2lBó3L3€áz$¿µulüEî0+3Lƒ9 m!Œ5¶–œ}‡9-4wAL;.vH4DkðRu«lœpE;731'=C2õµ»a>Œ¯²wÍ9lDEž4Á5+£ ®gçtÍÀŽzGfÃS98²TJ%;@d„Í9p)Ö»”87ï74( jCC;½8üÀ75-k7ß:89;8,Ð5.}!2ÚA=2+*vл'2Û;5uÑ)ï(k---ÿ2551+(ýk ÷nŒ& üÁÐÅÞ# Þß ïï,í ùßQïcïuï‡ï™ï«ï½ïÏïáïóïÿÿ)ÿ;ÿMÿ_ÿqÿƒÿ•ÿ§ÿ¹ÿËÿÝÿïÿ%7I[m‘£µÇÙëý!3EWi{Ÿ±ÃÕçù ////A/S/e/w/‰/›/­/¿/Ñ/ã/õ/??+?=?O?a?s?…?—?©?€»?Í?ß?ñ?OOD`OCOUOgOyOD30O¥O·OÉOÛOíOÿO_#_5_G_Y_k_}__¡_³_Å_×_é_û_ oo1oCoUogoyo‹oo¯oÁoÓoåo÷o -?Qcu‡™«½Ïáó);M_qƒ•§¹ËÝ%Ÿ7ŸIŸ[ŸmŸŸ‘Ÿ£ŸµŸÇŸÙŸëŸýŸ¯!¯3¯E¯W¯i¯{¯¯Ÿ¯±¯Ã¯Õ¯ç¯ù¯ ¿¿/¿øA¿S¿d½KGC?8ød¿Œ¿ÃEDEGE@5*-=§±‘¿h¼ÿHKJFC@5(ÿ*;ÏCEB@z¿VÈLJ¿GDB;3&×/?>CC?71ò¿¥ÂûLLv°@>7+þ¯Ù2>@>=50ø#Ï2Â×°=;80Ê}Û?ÄÁ7PÏ4ÁEAM=Ð5#ÓÇ;ÓBÀO;;5*‰Î8À<ÐÓ6*|Ü?Ð>Ñ91Ý%(ÌE@>µÁ7/íßÝEC´Â98*yñÌ´Â85!UÍÔ:91$ßÑÏØ‚À(Xß8ßÕéÀ÷82'Ý:;5#ùUÏ~Õ9;7&2/ÄG1ÓÐ-Ÿß°×7;7*ðÓKKæÀµÒø À:Þ{Ø:;8-œòÕÓ;81žßê9¡4"Ò)àÈÔ àkï{GKæ;5% YêÇ95!iï ±Õ:97( ¡°*æ¹Ðhï ±cKB’ä·À9ÑGFœÁBµÓ+ðà5ÿ&ð³å9gâÓEEåå†Ð6ÿÃHEÐòSà3ñGC>€óŸÀ iÿáç·ÑšâçSóÿK³ÃêãfðƒJHò‚÷ÏÿIòò9 5£ÀF]ãúâšïϲZø.qÀBäæ.$äBçÂÈâÐÒ;ÿÂòb”Xé–á.ã@^ä` ™)ç6×Bö•2ÁIö85(ÕÄAâöÈ'å6ä*qÄ;=)öüÔ[çLqÆ7Lå7+âcLåLž°159èõþþ\ä9°*;28´Ò9-˜çÁß984(qË(1½8ëÐ;92'ÍE €Àá0!å""óíà}Í960#?ɺ&7( 82!›<Ÿ975*{/ž±%ÿ+27887.#~,ÉC=51*lßþä$&-255û-(õÇA5+!óÞ/6$ÿ('*4@HGÿFHE;/$ ü?O= &7ÿBB9) x¬/€?‡3 p?®?À?Ò?ä?ö?OO,O>OPObOtO†O˜OªO¼OÎOàOòO__(_:_L_^_p_‚_”_¦_¸_Ê_Ü_î_oo$o6oHoZolo~oo¢o´oÆoØoêoüo 2DVhzŒž¥s`¥ËÝï°%7I[mŽ.‘£µÇÙëýŸ!Ÿ3ŸEŸWŸiŸ{ŸŸŸŸ±ŸÃŸÕŸçŸùŸ ¯¯/¯A¯S¯e¯w¯‰¯›¯­¯¿¯Ñ¯ã¯õ¯¿¿+¿=¿O¿a¿s¿…¿—¿©¿»¿Í¿ß¿ñ¿ÏÏ'Ï9ÏKÏ]ÏoÏϓϥϷÏÉÏÛÏíÏÿÏß#ß5ßGßYßkß}ßߡ߳ßÅß×ßéßûß ïï1ïCïUïgïyï‹ïöœíF@œïHD;þ±ïJHGJGB9ý.8 JKJE@7ý18 LJFECBïA=0œKGDŸB@><5þ%Ð$G7C@>X34)3ñ®Œ8+Ë(F4ð<ޱò5#6)Œèñ1eÌ&H5îðºÏ$C­820Kï>#+‹;91½$LJ@4¿;»8/ÆôJ/ 9õ?Â-ÉLG+·(7J* ¾ã&tìŒ7bLG%ëY7ëò‚ àò%Æã¹C©`J*S@¾ª997-!LÅ/ÆäE©` ™òL5²™ó7cðD -!Gu8ÉGu5 Úm;É35û #?2±-æñ¾ã©82ÆòC½Æå&#%z.JkKB«+kñK*V9µ>Hv7)æðKÓ> ÆïâêExò95C&¬à<øqâðJÿ:;4#F7è"šÑåF¤ó96+àöÊT878Ç>+Ðz©ñ9;7+Ç%/¯ŒöÛöP/Qv!5#¬{/.Æx8-J/./%5#+Ö/`/ "¦/Š/¦óÐ/Õòý/Ä?CJ,…?ñ?i(8ÅöO¢>DOÎ:m#6X€qOû?²?§O–(á?ÖOIG>#.šOÙOD­3§75!ÈOïBŽ7Ÿ874( öOa]@ÿ>1+***)(ó Q__ ~_¼_Î_à_ò_oo(o:oLo^opo‚o”o¦o¸oÊoÜoîo$6HZl~¢´ÆØêü 2DVhzŒž°ÂÔæø ŸŸ.Ÿ@ŸRŸdŸvŸˆŸšŸ¬Ÿßñ`±Ÿ×ŸéŸûŸ ¯¼Ÿ1¯C¯U¯g¯¯(¯¯¯¯Á¯Ó¯‚¯÷¯ ¿¿-¿?¿î¯c¿u¿‡¿™¿H¿½¿Ï¿á¿ó¿Ï´¿)Ï;ÏMÏ_ÏσϕϧϹÏËÏzÏïÏßß%ßÔÏ5ß[ßmßß‘ß@ßµßÇßÙßëߚ߬ß!ï3ïEïWïï{ïïøŸï±ïÃïpropD÷ATEßð6-1ÿ8-2005, ß19:11ÖáNAýMÝáDEMO_ýG÷à_PALET{TEÖáORIGßðÿ paletteï.bmpð þ+{þ+ ÿa &Á ÿÓ?Ó 3ÿÓ ÿá Ñ ß ÓÓÿ Ó A¿ AmðÿÓ 1 ÿÓ Ó ÿ 1 ÿ,ñÿQ Ñ ÿ‘Ó ÿÓÓ ÿÓ Óî­ðÓ7gðÿÓÓÿá ÓÿÓ ÓÿA;áÿ!áÿÑqÿ "!!ÿ1 áûÓ?gðÑÿ‘!á¯ÓÛðÿ$ÓÓÿ"!!,ÿÓ!ÓÿÓ"Óÿ± Óý$Q%ÿÓ%Ó#ÿÓ#$¾a!Ó M#ÿÓ!%ÿ!2 !+ÿÓ)Ó!ÿÓ"Ó&ÿÓ'Ó$ÿ±&& ÿÑ#A&ÿá",$ÿÁ#Ó$ÿÓ*ñ)¿Ó'Ó“$ÿÓ)ÿ(3 ÿ-Ñ&(¿Ñ#Ý/ÿ‘(%ÿ*(ÿ%&ÿ',û )ï+#ÿ+'ï()&ÿ))ý.ûà/-ï(A.ï,/1ÿ& +ÿ 1,¿)ûÿ..þk+)ÿ&*¿/‡Ë1‰+.ï*¥/ÿ))þ§,+ã¯w+ÿ 4+ÿ+ 1þá3-û1í0.ûã.ó0 Ð-6ÿ -ï-ÿ,þ /14ÿ +û!0- .$7ÿ3"4ÿ?"1ÿ 3(5ÿ)83?ÿ):2(ÿ1 > ÿ?& 8"?#$,,„ÿ5?6? ÿ6??3?ÿ1 #7?%ÿ8??1#?ï00(— *9?ÿ'8;>ÿ/:?Ð3:=ÿ??@1;?ÿd3;?9:9¿7;=- 5¯Â :>?7÷! ÿ====>?Óß:??Ó<0>>÷=Ó>0??>îÖé7-0åæ1:2½7òîMENUÿÿ logofonŸt.pcx&ùˆ {Ûm@—0ÓÿÁ!ßÓ¨1®®0 Ó´1¹1 ÿ¡ Ó ÿÁ A ämðÑ1‰ðÙ1Ó ÿA !ÿáÓÿ‘QÿÓÿÓQÿÓ!Ó¥A#Å@A%óÓ$BÈ'ñÿ)Ó)ÿ+Ó!-áÿ!-Ó!/Ñÿ#/a#/Áÿ#1%1!ÿ%31%3Ó{'5b@7Ó!)iAÿ9Ó!+9!+ÿ;á#+;‘#+ÿ=á#-=á%-ÿ=%-?%/÷?'A1?Ó)ý3™@5?Ó+5?¿Á+7?Ó-¨A9î,1?!/°@/;?_Q1=?Ñî ö Q,³@²A²AËD!³@UQËH³@Á³@AßD%³@ÑËH²AáóDÎEâMî ±BQaÓDQUÊAÖAÁ UVSXn_T[s_‰ZfQZUºU–U—_Ý_X’UVYoä_ odS’Q’QoXooloŠ_8oŽ_d_ÎY woÁf’_.??ÿCunàNqPUgx}Fp1=4æä_21:48òèZ3?IDI_INñøÿ skate2.÷mid¼qV²úárÀnàÿýSÔq!ÿBÿy Nick DÿaviesÿÿCopyrigßht © çá b~þ}All Rÿs Reservûedùp GeneõrÕpd‚oteWÿorthy Co÷mpo?€ÿQÿ¡ ÿX¿ÿ/nàß©ÿ!Pp ÿPercussiûonã¹¹û @•†™E?.™?E™E-©³‚¨Òä¾ðŸ,Ÿ&ŸPŸbŸ<ŸvŸ˜ŸªŸ„ŸÎŸàŸºŸôŸþŸ¯"¯L¯^¯8¯r¯”¯¦¯€¯Ê¯Ü¯î¯È¯ú¯¿¿0¿Z¿l¿F¿¿¢¿|¿¶¿Ø¿ê¿Ä¿ÏÏÏ4ÏVÏhÏBόϞÏxϲÏÔÏæÏÀÏ ßß.ß(ßRßdß>ßpߚ߬߆ßÐßâß¼ßößï*ï$ïNï`ï:ïtï–ï¨ï‚ïÌïÞï¸ïòïüïÿ ÿJÿ\ÿnÿHÿ’ÿ¤ÿ~ÿ°ÿÚÿìÿÆÿøÿ6XjDŽ z´Öè 2Tf@Šœ®ˆÒä¾ð/,/&/P/b/opošo¬o†oÐoâo¼oöo*$N`:t–¨‚ÌÞ¸òü J\nH’¤~°ÚìÆøŸŸ6ŸXŸjŸDŸŽŸ ŸzŸ´ŸÖŸèŸÂŸ ¯¯¯2¯T¯f¯@¯Š¯œ¯®¯ˆ¯Ò¯ä¯¾¯ð¯¿,¿&¿P¿b¿<¿v¿˜¿ª¿„¿Î¿à¿º¿ô¿þ¿Ï"ÏLÏ^Ï8ÏrϔϦπÏÊÏÜÏîÏÈÏúÏßß0ßZßlßFßߢß|߶ߨßêßÄßïïï4ïVïhïBïŒïžïxï²ïÔïæïÀï ÿÿ.ÿ(ÿRÿdÿ>ÿpÿšÿ¬ÿ†ÿÐÿâÿ¼ÿöÿ*$N`:t–¨‚ÌÞ¸òü J\nH’¤~°ÚìÆø//6/X/j/D/Ž/ /z/´/Ö/è/Â/ ???2?T?f?@?Š?œ?®?ˆ?Ò?ä?¾?ð?O,O&OPObOïPïÒïäïÿ˜ïJÁ®ãHÁ@ñ¼áhÏ*ÿ<ÿNÿÿºÿœÿ®ÿèÿÒÿ¬ï¾ï˜ÿ&àÿbt®`ÿâßôß^ÈÚ”¦X:tî8J$Ž Zl//:/´nÿ€ÿêT/f/H/2/ä/Æ/Ø/ê/4Ö°/?,?>?ø/ª?Œ?ž?x/ú v?à?ò?O¾?pOROdOOÀb?Ï Ï2ÏlÏŽŸ0¿ ÏtφϘϪÏßæÏøÏ2ßT¯f¯x¯:ßLß^ßßÊ߬߾߸ßrß¼ÏÎϨßï$ïÞßðßrï„ï¾ï8ïò¿ÏnïØïêï¤ï¶ïhÿJÿ„ÿnÿHïZï4ÿžÿ°ÿÂÿ|ÿ.Jüï~ßßúÿdvX€BôÖèŠDïæÿ1÷K…PÃÿ/ÿÕÿ!þ’ Acousÿtic bassÿÁ ±÷± @±†‘'{‚È ‘3Ëý3Ð,.‘,‘.‘(ÉãýÐíÜ ' Jû^è,> !+> €(ð//U/ÿ^/p.0ª¦ 0ª 3¦ 3ª 0> Ã!=/O/Ÿ/s/…/ó/?0/Ü/,?>?z?$?ƒ?È•7±0½3^Ê/g?‘)õ0)š?Ç?O­?O-OPX?j?TOfL" A"¥@) A)®OOÒOµ/Ç/‰COçOùO:OLOM_pO‚O”O†_˜_l_î_Ý_Û?í?ÿ?ì_odoÿ_mooª_¼_¦o³OÅO¹oõo*Ø _§ Aù¡>¼ A¼ è¡®£Ñ¤»¡µF寵¯Ç¯Ù¯>¿P¿b¿t¿†¿˜¿ª¿¼¿÷¯ ¿¿-¹°ÿ¿Ï¿á¿ó¿ÏÏ)ψ;Ï4¿`Ä…ÔÏrÀ” ýV› Rhodeÿs piano/Ä´¶´º/×ÿž”3l”:ïl ”ƒÀ”:NÐHÒ^OÔFßXßjÚ+`gÒ7~Ô7†ßwß”«ßÍÐ8°Õ8ÚÖÂÓ8ÉÔáßóßå˜ßýßïCïÏßÀßyï‹ï’ߤߟï±ïÚßPï ÿÿ"ï4ï/ÿAÿjïàïòï«ÿ½ÿZÿ¿ÿÑÿ‘ÿ‚ÿ;MTÿfÿasœÿËÝäÿöÿñ,¢´m€“ÇSDý/!%2*%2C*^R$I/[/m,/*/ /²/%Æ/Ø/—/ ??B?ß/ñ/V?h?UËÝÒ?ä?¯Áø?,O¸?©?bOtO{??ˆOšOÃ?9OKO_ O³O_*_SOÉOÛO”_¦_­O¿Oº_î_z_k_$o6o=_O_Jo\o…_û_ oÆo9/l/~/ “/àoòoh zqo|ŽÂ{°[Ñõ£µ-oo¡o—aoF«½ñ\n'Ÿ9Ÿ6HŸ“ŸAŸSŸÉŸÛŸô Dˆ±ÁÀHr°°±¾±^ú¢s±A½µÅÀȲݳã¡×³Í³´²Ç·¹Ha ú¢H0ž —³nÀœ² ÃÛ¡+ÁÛ³˜²æ±±AÃô³Õ¡ó¡˜²û¡NÅDl‚å¿ÖºŠÏÀö»Ó·ó£Ó³)ÀÒe¾Õ Xylo£Ã— ³3г7ÐíÇ•ÿ`“R\“RW“TÐT ÐVÐ}V ÐW\^“WÚ+@ ÐØ Ò6ß¶Õ‚p ЊÐ^xÒFßÙ¡b“PÐáP ØxÕ™×уb“_^\“cÐ^3ÐUc Ð[»Ð^Ð[3Ð…^ÒÉÐÑÜÐ ÐRä»Ð^ÐÐìЇ`K“`»Ô`ÃÔüÝ\»ÐU`Ð\3Ð`×Ô\ïÑ2Ñ$àl¢@ïRïdïvïˆïÿpropDATEþn 5-19-2ÿ005, 19:»02›áNAM¢áÿDEMO_MIDI_INTRO›áïORIG¿áintÿro_musicï.midÈáõñâxn ÿXÿÿYýn ÿQûú;ä:s¥TubaóÀïp‹¢<$ÿd$‚K+þ7ð+S*dYÿ*+d‚g+ü:å÷BassÁ÷ ±üÀ± Pé‘6ÿHþ?öHor¿nÂ<²üÀ²ÿ x’Dd`ÿDCdhCÿBdBj½?Àð?jdïKd;\Md;ïM> Odÿ;OQd;Qþ•ñAdRd;ÿRTd;TûA¦\V\‚ÓgVØñ;䣶 2¯Ç0·üÀ·pð—DÔÆðoÀV^J¦ô4mB;oBÿDdDFÿdFHdü\JdMd’FJWNc@PdPM]ò`óÐRPdTëdjP]]Vé]uc÷impßÈ/¸üÀ¸ ÿ2˜0hw0¯0B;H!LM"aêG"PM"bM!7j;Õ7g e;Ye°@;8ÿ C`Bmÿ>m9m°@ÿX@QBÿ> 9ÿ@rYþ¹@x9>÷B$¡@ ;e·CYš@i‰@lþŽ@C>ÜA˜@9e¡@‚§@5©@‘@°@[@mÒBm¡AmÂ@ß9Ñð@u7Ó@@æ@SQ.0í@¡@>3_Eí@]‰O›O­O¿OÑOãOõO__+_=_OQ3TV3^_p_‚_”_¦_¸_Ê_Ü_î_ooD$oLT›`Ÿ„`_HoZolo~oo¢o´oÆoØoàêoüo 2r95ÿ47<59Y_9‡8.04ÿ¸,ðj jO6 ’àÂi¦ËUhµÎgÇËfÖËeåÎUd÷ËcÛbÛa$Þ­`6Ók°°7Ô_ŽJÑ<9,ðLÒKÑ^ú^Þ]pÓC¯°]zÀ~Ð »\‰Ð 5tÁ\%@ДЉÒ[ƒpb´R,ð[¢Ñ±ÔZ¼ÞYÎÛUXÝÛWìÞVþÛU ëUTëS+îR=ëQLëUP[îOmëN|ëM‹æÙ@Ð}ÐMþp °L ¥àq²,ð¦âª³äK¾ëJÍëIÜîHªîëGýëF þEûDª-ûC<ûBKþA]û@zlû?{ü> zÀŸ°> Žñ"²/°= ¤ð»¥òª¤ñ<Àû;Ïþ:áû9ªðû8ÿþ7 6 5ª/ 4>3P 2_ 1ªn0€ / .qÄ.ÊyÇ.„Í.ž˜Ä- ªÎ ,ß +î *ý)ª('-&<%*N$]#?Ô#llýQÐ<°" U!… yÔ Ô ”4”Ô—Ô »¦Ùª¼Ôãòª++"+1.ªC+R+a $e!U k'v#w!‚.U”+—äŸä£ Tªçµ Ä+Ó. å+U ô+ > ; $;½30` :1z?;N30 X:ýf9 ±[ÿ± I±]ý[@‘+}ƒ`+ÿ&rƒ`&ÿ-}‡@-Ë?Ý?ï?OO%O7OIOÏ-„¹0™4@_þ¢5DrumsÿÉ ¹¹ÿ 8¹]([ÿZ¥@™$l<$ÿ4,R<,wx$R¥@$y¥Cíy¬@4¶I<$J*²B²Br¥Cj¬B·AÇ$W¥O·OÉM(2s\\P2<\ÿ0<0/¾Ä(n<(ÕW¯,ç‘WMQ,ºÕRMQ0y9P0õObRLbQ$y(ùyDQP1*—$]ÿA*|PˆP4ùÑCŠP*]$D²•U2tT™Qy<™Q6g$L•X…U*7¶R*µS-ÈXj¶R7ïCæSg(­UÓX$]ÑTê‡QjÈX9¶Q.Dë$jÿA.ˆP0$ñOõ_P¶R](2=t)Q™Q=/P$R)Põ(‡S.x°O(0jIoQ9c45P‚`(/a W<;a:tP@d®UªX=¼X±ha=e‚X_¢_´_Æ_Ø_ê_ü_o oà2oRVer½`R(›]EP(yÆqtf(à‚P¥e‰cêC•b2jm(ç‘y›c$O)QÄ÷sÂf2YpvRbf0yÀ8Q„‚P’rbcpp/cga9yRÐ,Qœ0ŠQRÙq…RQ¨cíoÿo#5GYk}ß³}íu{a•Wb˜f)—±jò‹Øovˆš¬¾Ðâ€ôŸŸ*Ÿ<ŸNŸ`ŸO—(<ÆrNÌw°l(jÇ–Ö—. ¡`•“x[`y<`m…‡Q«Ÿ½ŸÏŸáŸóŸ¯¯)¯;¯M¯m¿Woio{ooŸo±oÃo“Ÿ¥Ÿ¿%¿7¿I¿[¿»¿@¿‘¿£¿µ¿k¯¿sFÆrrÌÞð&8J\njÏ|ώϠϲÏÄÏÖÏèÏúÏ ßßx¯Š¯jŸ|ŸŽŸXÏößïï,ï€>ïPïbïtï†ï˜ïªï (7ÆrjÆqÁ¤â±Ç‘.‚PØBËñ¾ò XrÐ2QŠP0j¥Ò.Äô2)ñCŽ÷OÐ*Wä¤Ößèß,ÿ>ÿPÿbÿtÿÔÿ˜ÿªÿ¼ÿÎÿ®ïÀïÒïäïöïÿÿˆš¬¾Ð0ô*àÿòÿ(Ô9sP"ÊÐ@ÀT"‡TPMPXj®ÀÒäö//,/>/P/|?BTfxŠœ?(?:?L?^?p?‚?”?p¦?¸?®O(Þ(2j×±ê¶á±}Ñé±ý8_Pø±ÂuÑ9ÿ zÐPÕË!ÓC'Èá1ࡲ$ì#&Ár$rÇ\PÄÑÉÑ6OHOZOlO~OO¢O´OÆOØOêO"oÜ?î?OO$Oª_¼_Î_à_ò_oo(o:oHâiñcýbxs?rx?r-OhzŒž°ÂÔ¤O¶OÈOÚO*<N`r’¾/Ð/â/ô/??*?·Å>°‹Â(´r¢bMѲ±N´¢Q”PO}*B|´gG–±ó(S¡b S&K“<&7Æ °N´Ã—I!´é¨$Yͨ>°¦ÀA²·¦•OµäÄ‚C$Nµb¿t¿†¿˜¿ª¿¼¿Î¿„¯–¯¨¯º¯Ì¯Þ¯ð¯·ÿ¹ Ê#ò$#ó™ ¸!ö~ƒ~Hÿ4ö ±!ðJó}}tÿ4ö,±!ðvóo|| ÿ ™ææ½¹§ô{{Éÿ ñ™:µ!ðËózzðòÿ`ù ñôóyyä4ö7!ð xáxGáó˜ñIwÁwmáóá!ðov“v–4öj!ð˜uu¿áó-á!ðÁttè®q0¹ïss¸ö?rr=_?qqcáòPâ!ðeppŒ{ZäÃ>~¤aü€¨¤=Ã=ª¤ü¬¨«¤<Ã<Ö¤¹ùبפ;Ã;ÿ¤âù¸´:Ã:(´ *¸)´9Ã9T´7 V¸U´8Ã8}´`¸~´7Ã7£´† ¥¸¤´6Ã6Ì´¯ θʹ5Ã5õ´Ø ÷¸ö´4Ã4Ä ÈÄ3Ã3JÄ-LÈKÄ2Ã2sÄ`uÈtÄ1Ã1™Ä|›È·Ê0ã0¤ÊÂÝÏ/ã/ÐöÂß.ã.ùÒ/ß-ã-"-HÒ[ß,ã,tÒ‡ß+ã+z* Ò°ß*ã*£'ÉÒÖß))É*ïÒîÒà$çñ'((ÿ/.!%â>ï''1?Vãmï&&`=†â™î†7%%”:ºâ¹âÔ«7ËçÆ?<ù>#÷# ÿ"ñ"&O%ó<ÿ!á!UOgDUòqÿ  ŠOœGŠñªDŠò´úÇOÙGÇòæÿÿOQÿò>1_CQ|1Jc_øuQc|ð•_§Q•®áÇ_°Çàãù_øã(m(;ãTmTgS€j€$ªf>®@ §O,_ ÍÍ>ÿi ðü>(v /"#>Ny ?/K#>w| k/w#>£y ”/ #>Ìy ½/É#>õ|  é/õ#>Ól  ?!3>M‰  >?J3>v†  d>•„|e2¡  ˜2𽄙7®4Õ‰(0jø›Ê0Á€ |Þ9:– ø?|C`œ $B}0ŒŸ AO|MC»œ mOøyCç™®@ ò™B™C ¬ù ¹Owt¹dÿþ–ðÿ!ÿÿIceÿ RainÃ[ÿ³³ ÿ³[Z]ÿ9 ÿ@“ÿLr†9LJÿr9JHe†ÿ-HHr;HÿG_3G ÿCr†CpLÿrrLJr‡@J_!_3\–B_T_2_z_Œ_h\ÿì÷@ÚDµãE Syÿnth Bass 1Ä&´ù@ß´ L´R[ÿ]ÿ@”!ÿo a?<(`Pþ8a&U<&<$cU<“ðÀb¹d+F,a[&aÎa$PÈhKÚb¼ÍbÆcP<Ê`o’ÂboÈ`AcrËcG>CEœPÿLNH_E¿_EH«PÿLYHrûEYêÖZGeCŸ_JeªPßÐG«ZåÐLæÕLìу÷>-ØÑ@>@ºÚÐNÞÒYEãÑüîÐ"âGIJmOCOªPýGNàYJ_O5SXçEâHmFá%à­EòÐGSRâNjèS÷LmyéONöàJmáGOV)à<6ÒÒ7.â84á¯GmCˆàYçCô¬à à_³äCZEILIHY¡ç°Óà®áâîâñm¾çéƒBG8·àEÛ9ëÐC8ÞÑ9eBS>YÙÐõBQZ>ð>_BãNJðÙÐMð;YÍ>àNßÐÙÐ;wBNRñ9_ðÂGòZ™áxàEâ€âƒBÐßâßôßïï*ï<ïNï`ïrï„ï–ï¨ïºïÌïÞïðïÿÿ&ÿ8ÿJÿ\ÿnÿþ;242§9.|ñt€;»ð9ÿ(;,4/ü\";+4ý-k47;4“90|ño4)‹-îZ49k95ö‰47k1;1Ýo45§@:ÿ;8974á8kþðoN.@0Œ4.kþð(-@Q-Œþð–:ï5’94ÝïZ@>- 4(ã9,wÂ[@E~¿4;96|ñlÞ–@@2 9QâÐ3Ât€ÆEFÿ@Q;/43øŒ´ð"4@¿@K;@½9ùI#)ZEK@S2 ±!@NÃô-!©eÆ$— 9Ð9>(Kذô- ½@Cº#9õ3­@k4G½;¶ eE}Õðã9Y )$L4IûEm· ;BJN9S|ñ%$¢ÿ;E4E9N{J¶ GES³ñtr"öJ»r@æN`1^0$3|2“Iã4G00æ@_ˆº!s632Z…0¯3:0;àG0{ò´ðªPW%Ee~„2m4_;"0]y“?ZHm;Ñ0…S<2mº!–-ÿ8µ@)•-_q46%“ f ÿ@9;5 9ÿ @;‚ÿ,46(4P-ÿ8D-p44ú“ «@4;0ÿ';@OAÿ8; ;=ÿAk@81@ÿ/9T<8o<ÿ -?H-l×45-“ oA6ÿ;2‚:9;ÿ@4.þæ-4P-d4»5+“ 9.«@×@5CxB3~A87ÿ; AG9ÿ+@8g@M>ÿ9Oµ@•>ß)<"9@ý•©€9/53 ÿ)<9ß 5Õ<7ß@7mä'@ÿ&<&93&ÿ9R)945ÿ84@792ÿ6@9:AîO 9\AQ)ÿ(5-@9+¿@ <7_ô@ï•(>*9@x•<»i 98Z(>@B‚(CA¿*96&;ýð,ÿ9(:44ÿ749I39÷E@B0R@ÿ;`9E4ï( ä@Aÿ(=;C8ßA49(ô@ •ÿ;@(84$6OHOZOlO~OO¢O´OÆOØOêOüO_ _2_D_V_€h_z_Œ_ž_°_Â_ÔZƒH™ÿ«ÿ½ÿÏÿáÿóÿ);M_qƒ•§¹ËÝï%7€ÿ’ÿš¬¾Ðâô*çFK7SpF°>Ö ä%°"±[úƒ2ݱ4+\76L±$°969´<<Œ .>Lk$a‘Œ :k>Sp>—·>¥7ÐLN·¤±Bv°L°˜²Z<+p‚ 3à¸mFì±7:)Ƥ±}LJɃB;'oÛ'<7'±2>6:-F¡Àý6°Z662yB‚İ6Z7ÀŸF/>¡Ð±w-B‘Á66‰Â- ¿¿0¿B¿T¿f¿x¿Š¿œ¿®¿À¿Ò¿ä¿ö¿ÏÏ,Ï>ÏPÏbÏtÏ†Ïø˜ÏªÏ¼Åĵ÷dÿaà6ÿÿ!ÿÿKalimbaÿÆl¶¶ï d¶t ÿ[]Ù@÷–>dêÐ@aX·âU½âRÃâOªÉâL·âI½âFÃâBªÉâ?·â<½â9Ãâ6ªÉâ3·â0½â-Ãâ*ªÉâ'·â#½â ÃâªÉâ·â½âÃâªÉâ·â ½âÃâÉâ¶ïÈïÚïìïþïÿ"ÿp4ÿFÿXÿjø¡;'÷nôôJ fLr3;÷ JäLjÐpuÿ‡ÿ™ÿ«ÿ½ÿÏÿáÿóÿiÿ¼Îàò//(/:/L/^//ASew‰›­¿Ñãõ+=Oas…—©o‚¼p¶åU‰åÿOrch Hi¿tÇ7·žà·ï @·¦é×—ë>x"~ (áQB(QÿS9(SXÿJ(X];(ÿ]_?(_ÿdB(di×N(itPGxQbNk(bnPHrQ]GlQ{XKfQVO(VVPíPZQLSNQJU(v¬EKHQ@Y(ÑÿY(9ÃÈKÿ‡@˜Eo†=Eÿ C>qCÿ@P†HK <]à%`ÿH†D@GIÿxCaG†BÿEPCKEÿAa†HCGÿAiEPCÿ†DH[EMÿHGh‡@L¿HG‡#³@»Û ¸å{‰å GÿlockenspÿeilÊ º>žàº &ºmP¬à¦âBPšF_X_j_|_Ž_Ü _²Y>@(aE9ÿQ@Ê0(šþ…`E; 4ó+Ðù ; 4}t4;ÎÑõ4s u ; Þu&4!u{4u!;(uï4 u4ýu34#@ù'àÁt@ã4q½q@ù t”s4;g@àÁs4/]Ð÷@2´x-;<Þu4u{4u?;Cu¯4xuQ÷4Gu4ôuÐPu4Þu"4 u^Ÿ4A@H~xzpw4x@=€tbr¦t)Tp@%´xP;i@V´wOÊ ƒ³W`ºEö‰åÿOboeËDÿ»t» û»¦ë›He†=ÿH G9qGÿCI†HG=ÿC!HE Gÿ/HLB†DÿLJCxGYûJþPHIG¿KHEYö€AEiHIýPÿDJSHMJÿL_‡@SB;L,`S çù  ŸŸ/ŸA”1`»åýH‰å More ÿDrumsÉ ÿ¹v¹[nþ®á»@™(-<(ï<(.ß’1(¯(ë’ ë’ªë’3ë’ë’ ¨5:ß’+ß('ë’&£®Þ‘(%ë’"ë’/ª!®>ß’?ß’Bë’ªë’+ë˜Dë’ë’!*¨Fß’8!¢2ë’ž£U:!¢0ë’,ë’<™®•Oß’Pß’Së’8£6ªë’ë’U9¨)ù¨W ß’’¡T Q£ë’H!¢;Já¨I!¢=ë’:³`ß’Ubß’d±¨@¨fù¨$ž£ê“hÕ£!¢Jë’Ž³U!¢FY¸ ± °³ëÿ´LÉ‚ ™*<**&Ųÿ@&4&ó&5ԱƱY&eý<Û³.e<.JÿQ9HCQû?…`H)QrçHyL‡à9HJÿH&HRQýL–JjQÿ HZJ8Gïr H‰@ÿ9Hj G¿2GcH€ßEy8EõP<ÿ7] ¼@+@ÿœC]Gÿ$Gy0G Jÿ"JGyÿOj?OGÿ4OGy)Cÿ6GOÿC>jENÿ'ErN"2ÿ>SNÿEjEj*Í8Pð>ròAs JÆgAOj aàs 2WÇEJ1ÀüNÛ>ÿCCïHeƒ`IáNGµE›…!Y(s GóYŸ @CeJ»S…PCeD2rO4JsaàY„!ËErBr®=ðLß}ON†¿/P/€b/t/†/˜/ª/¼/Î-ËÛ,½®• %ÃFClÿavinetÎW¾Ù@¾‚¾$éÿç@ž-N-ÿ9}>9:ÿ9}697Yÿ-74Y,4ÿL2e52ÿ4e:42eÿ12 7r`7ÿ9Y:9ÿ7e17 -eÿ-!9rCÿ959r39ÿ 7Y*74ÿe-4K2I*ý2@I<2Y4ÿ-2 7rYß79eµ347ÿ-Y-ÿ9r79A9ýrµ327 4eÿ44D2N82ÿ4r84÷2Y/BT7$ÿ9N.97eÿ<-r7ÿ-9}89W@9N"BeABrAý- Àr-90ÿ-e6-ÿ2}S2%4}ÿ<+r 42+F§?¹?Ë?Ý?ï?OO%O7OIO[OmOO‘O£OµOÇOÙOëOýO_!_3_E_W_i_{__Ÿ_±_Ã_Õ_ç_ù_ oo/oAoSo˜eowl1ž pŽ0 êœw~§x}³v ž-÷¾´q| ž9¥}0|ÇqÐq{ØpŸž9¾ÙrØrzÎìqž9N0îryBýsßp™`0ÿpx†¡—pŸ`0€w(ƒ Sž4Âq*€v9Šžr{u N‡t ž0‘qÓtÀpšptYs†o€ ž¯b0qo‚r†€Àp·`0ˆ ýqš‰ ž2¾7p ¯ƒž4Íq°€mo¿‡ž+‘qn 2€•Ѐ Ù†žÇb0mÕ í‡lø‹k˜j^Àp ¾jÊtj× i)–ßp ¾"*‘h=”Ës?gN–ƒ)Y0Pfe“ —pÃpYf·€`‘e |•2€ôâp}d˜c ž2R c›‘¤‘b¬ª€î`0®‘¬’aÃÓ‚ ’.Å‘ `דª€ú`0Ù“_î˜^ú‘—p0Zü“9`‘] ¨ ßp,p0\ (§[–rz‚©[3 A¥ZJ¨YV¨X”Xb Êp‘ql¢Wú{¦ßp¾V (¦q£Ž U ¦ßppÖ0T µ¥—p¾3S·€ S Î¥1„ëR ß§Qꡞ2I˜0ì¢ë¡Pª€Ä Pt·€ó¡Pþ  O´›ž2`‘O2€9N‰ +²©„N ‘q,°MjC¸LO³—p¾P³Ûž9 K i²}JZ” ¾J }´#I—pOp0I…°“²•H™¸G¥»F´°d„FDp¤¶°Eʶ‡¤Ì°DÞ·Vq£C ð·BZ—Bû°’ ÅAƒ AÀ Â@š&À2€¾'Â&Â?j:Ážnð¾;Ã>KÃ!ª€tp0MÀ=_Ƈ’¤²aÀÿ-"ÙÒ!ÿ.­@ÃVom'ÿƒ^—©¶€ÿ»Ã·Ê«šÿ‡yso`}Nàÿ>x3õ-5/Fÿ7²E„Yïp.ÿ‰Ÿ"°'»>ÿÀê¿hº­¯üÿŸbŒ°vö`ÿM©<ù0+}ÿ+ö1Œ=íL¸ÿ^œq2„ô”fÿ¢r«¥¯¯ ÿªð =”ЄÿtècV/LÙÿF%FŠI:PiÿY|düpO~pÿ‹ó–dŸã£qÿ¤Â¡¦œ“•§ÿŒ‚¤v–k]ÿb\çXèX—ÿ[n`×f'n©ÿu²|°‚2‡õÿ‰òŠ]ŠuˆOÿ…Ö€{¾tñÿn k°iˆjƒÿl·nqÿsÿx}ÙH…Ýÿ†î†7†/…¼ÿƒv4~]zÊÿvLtEs‘sÇÿtŒvÊx—{öÿ~œ‚ë…3ˆÿ‰gˆÎ†Ï„Üÿ‚!œ7~æÿ|¥{~z¡ypÿydzÅ|[€`ÿ„ǯ‰ê‰Úˆ3‡ˆ… „€ÿ€Í~Z|znÿx/xvyæ{Çÿ~öƒ”†Áÿ‰_¥™’Åÿ’ƒ‘¢·±ÿ‹!‰Ò…)‚ëÿ~¡|N{¥z™ÿz{<~v‚nÿ‡Ï‹¦Žò~ÿ"‘’º’>ÿ’&ÁŒ÷ˆ¼ÿ…‰ƒ/‚ ýÿ÷~Á~ €õÿ‚¾†CŠ Œ»ÿ(Ž—ŽAÐÿ±–ަŒXÿŠˆ,†—„Xÿƒn‚çæžÿ‚7„—†M‰²ÿ‹R?ŽúŽøÿ!‘Á‘ ‘ÒÿŽ©‹ˆ%†Rÿ„‚—€Î~ÿ~ý~|Ë„ÿˆ‹Ž‹‘tÿ•g™·œòžÿ % lŸÄüÿš —D’FÃÿˆ&…i‚3€:ÿ~¢||b}Éÿ€µ…èŠ>Yÿ’¨”Ø–™þÿš¶›Öš„˜7ÿ•N‘ñŒFˆ»ÿƒìR}|Èÿ{z|2~ÿ…š‰ê‹‘yÿ”ø–1™óšÊÿ›L›a™\–Ùÿ’¼Œ†Š“ÿˆ¦†ò„„·ÿ„¿†k‰¸‹7ÿSŽÙ’Xÿ”„•ß”®’ßÿ@õŠ©ˆ.ÿ†ÛƒP‚õ´ÿ‚/„&†—ˆŽÿ‹ÝŽ"’•pÿ—W™™šàšàÿ™ª—³”‘‘ÿŽá‹I‰à†Üÿ„ƒï‚9ƒ^ÿ„X†þˆû‹åÿŽm‘r“ð”Ñÿ•î•1•Óøÿ‘7Ž,Œñÿ‰Ï‡P†ð…Áÿ†fˆJŠŒÿöŽ¢‚’Hÿ”•Ù•@•éÿ“’ænÌÿŠRˆl†S…çÿ„τԄ$…0ÿ†:ˆ‹åPÿ’”“â”Úÿ•ò•¿”P’1ÿŒx‰ƒ‡*û†VA ¾„Є=ÿ…F†ˆvŠüÿŒ7‘†’Åÿ“q””m’ùÿ}†‹ø‰OÿˆA†1„ì‚þÿ‚2„Ô…f‡ ÿ‰C‹5ŽO‘¨¿“Ì”•d "ÿ–•(’>Ž•ÿŠˆ±†‡…öÿƒ‚©€.€¡ÿ€Œ—‚Óƒyï…‚‡‘¥ ‘ŒÄÿ .·`ÿ[&ŽGÿŒ‡‹ÛŠbŠÿŠ·‰âˆª‡žÿ†e†‡"ˆ«ÿˆ`ˆ§‡*‡9ÿ‡“‡Ö‡ü‡^ÿˆ4‰0НŠVÿЉ)‰’‰jÿŠÐŠ9ŠñˆÓÿ‡€‡Ú‡4ˆÿˆB‡o†è…Ÿÿ…C…¦„„·ÿƒ„¨„F…—ÿ…£…¥…Â…ÿ†U†Ó†”‡ˆÿˆd‰Ï‰­‰Mÿ‰&‰z‰ŠxÿŠHŠ‰ìˆ™ÿˆŸˆ›ˆ.ˆSÿ‡l†ñ… †sÿ†Ä†¼†p†#ÿ††ø…Û…•þA°…=…„…­ÿ……9…é„Éÿ„Ì„¼„v„ÿ„óƒ?„ß„qîO°M…è©°…HþA°í„¤„à„¼ÿ…Ô†‡›‡&ÿ‡º†Å†F‡âî5° ˆÏ1°I‡ÿ‡¶†2†¢…&ÿ…Ç„y„5„ ÿ„„_„Û„WþQ°°…’…o…dÿ…s…‚…z…Pÿ……Õ„œ„Yÿ„úƒŒƒFƒbÿƒíƒ „…ï…­„¡M°‚†¹ÿ‡Gˆ ˆƒ‡Rÿ‡­‡%ˆˆ,ÿ‡Õ…º„;„!ÿ„èƒDƒs‚øÿ#‚Ï‚”ƒ&ÿ„“„…Ì…—ÿ†@‡®‡ñ‡ÿˆ3ˆˆÈ‡Vÿ‡á†m†ß…(ÿ…_„¾ƒqƒuÿƒ¡ƒÕƒ„nÿ„í„p…Ð…þÿ…†'†J†aÿ†L††š….ÿ…Ñ„‰„W„@ï„I„s™ …]ÿ… …È…Ò…Ëï…Ã…ÅÁÀÁ…‘ÿ…0…›„؃ÿÿ‚=‚ËÆÿ‚z‚·‚Í‚ôÿ‚`ƒ„Ÿ„îÿ„ø„ù„&…eÿ…f…ï„"„dÿƒ ƒ ƒƒëÿ‚‚K‚X‚®ï‚ƒT‡À‘ƒ»ÿƒáƒéƒÐƒ­ÿƒ–ƒ…ƒdƒ.ÿƒö‚؂݂ò 1Ѓñÿ‚Ë‚£‚˜‚°þ9и‚f‚ý¾ÿÊ ‚@‚Iÿ‚1‚‚‚ï‚‚]Ð(‚^ÿ‚q‚B‚æŽÿ]E Øÿ€ƒ€R€_€šÿ€Ø€÷€ú€ûÿ€?s›ÿ«£‹qï_[—ÐK!ÿ䀭€•€ÿ€±€¶€¤€Œÿ€…€—€²€Â¿€¿€´€°³Ð¯þ¥Ð€k€g€oÿ€q€a€G€4¿€2€:€<ÓÐ%ÿ€&€6€H€Lï€>€,ÝÐ0€@ï€F€=Ë "€Ï€ €!ùÐúÑ!€ÿ€€€ €Ï €€ÈOÚE02ú (ðIWELCO{ME(( welíeW^hâV"îhà}zyé{{} ˆá~à€‘èáãœæ‘é•ï¡é‹ãäˆâçæ†âP†äÛä²ï¸æ#ð‚'øF#ñ¼êçé×â{WóúyãxdúwwvvtWsstvðq}ós„ðÿttvwxxz{©}à%ô„›ñ… ñ‡ÿˆ‰‹ŒŽŽ’ÿ“–—šœ ¡÷££¤¸ð£¡ ÿœ™–“Œˆ„ÿ~{wtqmj¿ifecbaÕðbÿcefhilmp·svxð‚Ÿò„ý„0ñ~}{xwtûspÎðheba_ÿ^[ZXWUUWÿXZ[\^abeÿhjloqtwzç}€õ¢óŒ’ÿ–šž¤ª¯µ»ÿÀÃÇÊËÍÎÎÿÍÉÿ¹²­¥ÿž—ˆzsmÿhb^[XWTRÏQQPPZ[QRÿTUWZ\aciÿmsz€‡Œ“œÿ¤«¯´¶¹»¼ÿ»¹µ®§ —ÿˆ€vlb[TPÿJFC@???@ÿBCDFJMNPÿQRUX[^aeÿfimqvz~‚ÿ…ˆ‹ŽŽŒßŒ‹‰…Êñojîbbc¥s{…ÿ™¤®¹ÃÍ×ÿáèêìììêéÿæâÛÑÆ¼²ªÿ –Ž‚wme^ÿWPJC=82.ÿ+*(((+.4ÿ9?GPZep}ÿ‡’𤭵¼ÀÿÄÇÊÍËÊÆÀý»ž“…xmeÿ\UKC;41.ÿ../259=CÿJPU^emswý{«‰ŒŒŒ‰‡y…ÇòOca_\Tü ehlpsxÿ~„‹“—ž¨ÿ´ÂÍØáéñ÷ýûnúöðéáÒÿÀ­š‰}obUïJ@<9ƒ;@ÿ™«¿ÑÞæìñÿöøúöíßÐÀµ«¡“…zq ÿqplhffijþc@^^ahpx€ÿ‡Ž– ª¯²²ÿ¯ª£š’‰€tÿib\ZZ[_fûq}ò Œ“——u‡ oë eeh¦0»wsä@b\U¦@9ÿ8;=?BFKTŸZ^beeÒð,A[ýZhhqz‚Ž ¹ÔèñóóôŸ ÿðØÀ¯¨£šŒÿ{oijpwzxítÓ0pp& ^\_¿fov}„ŽT0¯ÿ´´¯ª —…ûxlù KMR[bÿjqz„—š™ß•‰…€Nihéh/ ‹ðwÑ0jbWÿMD?;9989¿=FPX_eÞðmßlhc^ZVTWÿ\cmzŒ£¸ÊÿØâéïóöôïÿã×ÊÀ¸¯§œ³’‹¦ð¶~zEbu^* cî }…Ž"ÿ¡ž™’Œ…~våoPiE1I ŽŽˆ]‚öðvqldAe]Aøàð(AÓQNKIFçFIKá[@lopÝoå@eefO`hpÿ~’¥¶¿ÆÑßÿíööðæÞØÔ¿ÍÀ±žˆîð|ôá"ð~xsolÏðÃcb`ýQ0·ð¡œÿ“މ‰‰…}tqtz}Ÿ@²@(P5`…T°TX (aA0ÿð_ù[VdWZ^ejøê Ü !lmv…—¥®²¹ÉÞíÛPÿéææåÞн­ÿ•‹„xpj´ÞðPhMbec×ðfólsªõA§¨¨¨ü~Pâ’Ž…xja[XUQIB’CFGIJNRÄ`¡_ÃÂÂí@_ÙðeGcchF`’@ßðp¡Pÿjq}ˆ“ž¨²ÿ½ÍÛåêêêéÿéèåÞÔÆ¹®¥ š’ˆ€xuðtPpd@_WUW¡ýc¤Q{‚‹•—ÿ¤«®­¨¥¤ÿ¡–Œvmf¿_XPICB•DDGKPU * ×ðsbcÚñ_Amostñø‰òuóˆðzŒ– ÿ¥­¶ÂÐØÜÞÿÞßßÞÚÒÊÀ­¶€‹‡ÇñzøðqÝm|`a\Z X[ù_Ep“Q–š £ÿ§ª¨¡—އûzqØ0PMJIIGGGG,p ¿@_zpH…q–0è~šð™ò{ ùt|ðmPqsw~‰ÿ•¤ª±»ÆÑïØØ×Õl€ÑËÃÿ½¸´¯­¨£ÿ—•’‹‡}´e!€W¾`UX0@hÿq~ˆ“•™žß££•Œ€pf?^UPMMKµ¯tÌT ^\HP¦Q{€?„ˆ‹‹ˆ‡Î€@Pœâ"ò%ðïò„q—‰`ÿ¨¯¶½ÀÀ¿¿ýÀÊ »´®ª§¥ÿ£™•Ž‹ˆŽ¸vplÿñhf{lp`}…‡P#vs½¹`P\1‘>qÏb_^\-’8€bf^3€‚…Ђ8ñä݃¥ð‰éPêPˆˆ‡…2ò€€8†`뀤ߨ­­«ªƒ‘¨¥ÿ£žœšš™–•O“މj`ÈðxU€ xñ‚ðÕp/` lÐðƒ¨ šóUד¤ñˆaf’΃ù“£ðÏìòïð¤ñ§ðîÉ“•“ •“’ŽŽµÍ€j‘Ú“š»’@iæ@Q`é@^BK£L´@D€vxÔ”1ñ€æâ Ù‚O‘ˆv R‘g úq „ v„¡xƒâYø‡âØ‚*þæãäîØ„™ô0÷õÛ†Ú¤—ò1ð›áóàbû™¦WñÎ¥ö¤û¤µ§ðäWòi£ ñ—ó¢ø•˜õ÷©6ó3ó´g¡\õyëˆã.¹?³æécòaóš¥Ù†)ÿ!ò—åðãÀïåbòsð*‹  †âׇ$÷´§[ö©½¡¢ŒµœáXÌSµéåâ[ñpñ²Äⶉæí¶µ¥Ÿ¼U´ò¨Â»­ÂŒËX²BÅ7ôåãYöRµ;‹» ³[òCÖè¸%òٓó~ÅçìÄæékÖØàWôCÙ¦àK´êêßÚ¢£’ôû£‘·CµææiØDüJ¹mÆ!ðõ-Õ»§äèô}Ø.ôs·n”ÂÀœÅâêÔÓoæžÆ$ñˆ•ÿ¡§¡qbTÿKMUajv‚Œÿ•™™“‰{ocÿ^ap…– ¡÷—Œ~“ mqw€Ù‰Žpã pa<0ajÿ{•²ÆÇ¹¤Œ¯ve_cC0tÅŒÿމ‚tf\X[ûft_Žˆ}m_ÿ[_it€Œ–œœ™“Ž…}sž`Ûowô@’• 0}xÿx€¥¶»²¥ÿ•€hUJFGKÿT^ivˆ‰‡þ_0a\^blw…’—–‡~x§0ÿ„‹’••’މý‡¹wz‚‹–£ÿ«®¨œ‹zlbç\[_€4Àwtpjfccfmxÿž—Žtop¼xP1—¡ž›qjób_Á@x‰ÿŒ‰‚{tt{þ ‡…~smp{?‰Œ‡€{ é·xtqØòŽ‹ph÷fip „ztãsvû0{ spv}‚¡eÜ1:p}p[ZÏXXWW\1¾fRTú €^Fw‹’—ÿšœž¡§®µ¿ÿÇÍÎÍËÎÒØÿÜßáÞÚÕÑÍÿÊÉÇÄÿ¹´ÿ­§¡š—“Žcˆ‚õð°‘`\Z?~¬ ZWRPNN_ 0e €e!$pWW2€ r<‘'q7r$qZ€¾qRðù‹ê€×`¥­´½Ç{ÍÐàaÔÛßáèbÿÎÍÊÇÆÂ½¸o²«¥¡ˆ À„€:<‘º`d!ºbPPŸQTWZ\3q»€a°an!_­d‚q.’pêEhíjQ—™ÿ™—™ž§±¼ÄïËÍËËâdßÛ×çÒÐÎipmp¹µ¯íªsq’‹#tojQfÜ1@«PNâ Q&‚/JMQUºaR–p´m!c0Q.€a³qB‘³qì6‘µeeÏ`‚•v–ÔpÆÍÑhpoÐÕÜâ— ßÜe`ÿÕÒÎÊÄÀ¼¸?´®¨£–ŸP?þ*“XWTPJFC_BCFJK†€CCPMQT¼aRÊaªpc1C¡? 9‘C_®c4c0þ.€cfjq}‰“——–—§²ÖpÿÑÔÔÒÔ×ÛáÿãåãáÞÜÛØïÕÒÍÉlƒ§ š>üa}xslc)`c b@BU °Q®PDF”‚.X\aB‚hJ¡> ð¿—­fFaµ‘eipz÷‡“œ*@¤­¸ÿÂÊÑÔÕÔÒÕgÚÞâàå€ÔÑjÿ½»¶±ª£œ–ÿ‹…~xsmeý‚-`J@;P:`6a’ #qCqX@õëj«iÙhp¢‚cc2€\_ø¡õosz„Žï–œØ`¯¹Â¿ÉÎÑÒÑÑÚ€Ú÷ÛÛÚg`ÐÎËÇÄÂÀ½ô`ob Qswle^¶bTPK‡ƒ=`.`JX»p½€Erª@¡,“:€ €H`°‚Fpø£‘å ð‹•šœÿœž¥®¶½ÄÊ?ÎÎËÊÊÍWY;ÐËîa¿¼ïqrîö”mhb³`[ZUR›0FGIÀP ‚;`€œ€ pE`¤ƒRP« ¨¢c 1‘(²¡¥ôl¢`w ïx‹•M‘ž¤«ÿ±¸¿ÄÇÇÆÆ_ÆÇÊÍÎ[pÊð`ýÃí»¸µ±«¥ÿ œ—’Œ‡}Gwsm®@LPˆ@P0aM „—¡€5‚W@ÎP+‘Äq*D*€§©¤ŠbG¤}~Ìpœššœ Ú`¼V`á¡ÉËÎÐÚÎÿÊÉÉÊËÉÆÃm€qqú ýb¯ð°ˆA P9`MPP¡±—“Eae-‘Ja%”§¡$¡­íÔöçoùw‰ñ—œÿœš¡¨¯µ¹¿¿ÂÆÇÇÇq°Í¿ÐÑÑÐËÉè°ÆYÄípXð„Ï—ifcгN• •±Q?PNMKKMÁPAb€ž¢ª°¯±¶SP£)’iùjβøtw{€‡ÿŒ“™œœ ¥­²¶¼ÀÄÇì°ÍÍ^ ËÍ\ ð`ÂÀÄo ñ ™Pý`y`piQbÿ’‡¡‚RpM]"!tC`_'±®±Dê¢D´Ôíh0sŠtm~…™Ö`£¨®¿´¸¼½¿ÂiÁ˨i ô°ø°¿ò¥šÀŽˆÀ¯ñA+b]!‹@qÇa)Ðd ›“C³;Õ?±¼³°J±Ë¢×Áb…‰P™šäÀâ°êÈÊkpxÀüÂE²q€žÑv’ýq^ˆ@½`ŸÃN Á°b!d"¤‚,¶ÅµãpÿWÒÄï…ˆŒ30™œ ÿ¥ª®²µ¸»½·ÀÃÄá ÆÄùÐÃßÀ½¼¼»,!«¤9 ùaŸQzvq A‹°ˆp½jT9t.r@:Ô‹a0«È¡ÎÓNwzšCí„_ГæÐž ¤ïª®±²jпÀÂñÃyäûÀึ²®0òp‡ÑŸPúpplâ@r œÀ(Òf!5£¦¢@ťʡвW_]á~¹É…˜ ’hàeÐ¥¨ÿ«­®±´¶¸¸ý¹þ㸶µ´²±i¯3 ŒàƒÁ‰…‘? iˆ²a+aÃc2ñ²å¢6£Ã¡ÉÓα\@×À`ñzò"†±‰‰‹Œ¿“•–—áÁ¡_£¤¥¨ªöà¯/"þ2 «ª¨§¥¤£ œš–“Þð>#xvsol¯’:€7qˆr€U@q4㣃ţWòÙÒï Çããoð3cŒŽœP üò“•K––0—xñ_ÀR eš™ N€“’Ùt`ˆ§~}Ø{aé¿Â-‚E®`Ý0(‚Å€A䍨÷bûòôûô’!Ž' —6ž}”±‰ «o­”`xxvÕÁMüßï ÓÑ×BYÚÑ ±Ìpȉmñ$ˆˆ ¤~að {`–cÙÀï"¯q¯¢È 0“c`sÞppsœa”ØâNàÙ{{d°v€@É:Ó€p…EâØ€Ùïê_/ØD~×} æïLùâ} ˆûá"l®ÅB¯ ±‚&"×I!($â(!A%,,Ì/ï¬%çòf$Åìð =ÈÊ%èL;" ü & $ "×%"ÙÔô"–"S7™!#—2)™2¢#¤(úíaÙ%°4…Af#f#©9_#&•#Ÿ%¤*¸$Ë5ø_ë'bK~‚‰‰ÿwfcs‰…sÿls€‡vqvÿ~„ztv}„Þ¡Px~„„0€‚þ-…—š}o¿oz„‡z”@‚}vv{€€zX£Ps]ðàšXÚÑ©ÿw~‚€vqx…Ÿˆz{./~Ç‚……Ó’#ÞÑ„>s@‚~{{ê@¼0ó€~mÙ~wsz‡‹€ts{…wa÷}‚‰ÝA„‹‹…ï}{‚‰øp}ˆý‹À{‰Œˆ/~€„‡P€æ@òáà~ÜÐ" „ˆtÿmt‚ˆ‚wooÿv~{spt~ã€{@ýAa‚€}ê`×~á@‚„‡Ë‡‚aà„{P]wt{w}lPpsz€zpÛtv\zw¡P€{þ P…}z~„‹ÿŽˆ}‡ˆ…†2}×°À Pª}ÞÜЂ€x¬Q{w xH zw\ð  `}z{•@€ØR¯zP~„…‚}\ÐÖ`à¿{xz€–B}ƒ€„ÈQáA2¢ð`…/…}vwpP€×P•@û}xõP{{€‚úL`~Ea€€{wwžõQzwvx2]`zÿqt€…€qltûˆvb‡xvzô~Qß@‚âPv{„‰ÿ‰‚tlmz‰âPpR°œ@‹@t{‡ç‹ˆ€Ü×°Ž…ÿxpp}Œ—•…ÿtmv„ˆ{ûvv·…‹‡~sÿopv~‰Œ}ÿlep‚ŽŽ‚vópt‹`HQwljtÿ„’‰{qqwÞ¹‚ˆ‰…QP€‡¿ˆwv~ˆ)„{ss{BP`ÞPP¿~toq{‚îðÿtiivˆ’…çzvxÙü@}wx¿~‡‰‡~vbP‚ÿ–’„voq}º@p„Ö‚…ˆ`s¿s~‹’‡gQ}Ï…Œ‹‚Œ@a€~­zÆ@}…qoÉ‚‡ùpv™P…#P¸Zp÷‹ˆ‚‹px€‡‹?‰‚{tqt¡PQP¼\Ð5awssv†pˆBùpw„cýPø@ÖzM`vé@‚~ßvx~¯Pà¥PÚÑRlèPx{€…ˆÂPFaœAô@P^88aaE`vvx!a3SPœ"gbp~Ü‚\1$aAR^FR a_à£6k~~Òq~b{zaaAL"'E"Ò†7p2Ýßâ(5÷8z2y2èåG6&§ôŒÍ@^õÔe„vžˆðð—“%“Ž0øóŽ÷ñŠ’“#7‘A&šSrÖ5m<À€D­ó&ñ®Ñ=ð4á5¢ehǡӰiaáÆ/~|‚A–𠍮 ñÍ­÷â¼ÀûÂò­§G£ ž˜ð‹ÐµqoRò²·°eѱÓ^^¡^xÛ‘°â\[XT%㈨Á·á^!¡ÐÀVâxæßá…‰rðíàš¡«¿¶½ÂÃÄÄê±ÎÿÒØÜÞÞÞÜÛÿÛÚ×ÒÎÇ¿¸ÿ±­¨¤ œ•Žÿ…}tlfa\XßTNJFDX¢FIMT\bE³P°ìPãò瀀}Ò±XURÿPKGC?<;;ÿ<<<=?@DJwNRU  aehÑÀ¾´@„ˆŒ•xðšÞÞ°ª´½Æg±ÒÔÞ¸¡ÕÕÔÒÀ¡ÔÒÐÊü´«£I í‡âPql“Ð[UPýI‡¤=?BFJN_T\emt`ò‚Û‹Œ‘‰‡ÙpzsõlÙW•ÀGDC@ç=;9°Š ?BGÿMQUZ^bflšl¡}àЉŒgáY°žÿ£«µ½ÄÆÇÊþî±ÑÒÒÑÐÎÍýÍsÀÍËÉû´î„М“‹^poicvêTQ…¡=<<°ÿ;=BINRX_¿is}…‹íà—è$‹ÿ`vmfÿaZRKF@<9ÿ86544456û9;Ž CIMPTX^ejoÀ@+°ú¡þ!¦ÀÉÍÎÑ×ÛßÜÛÚØ×Å ÐÎõÎB±ÎÈ ¶±ª ÿ•‰€voha[¶ÂMK²?<°FÿJPU[cmw„§ñ«¨¤ðàð) ðxpf^ÿUNF=5.*'ý%+À'*/269ÿ=@CGKNQTÿW[ahmsw{ó‡êâKÁ— ªµÿ¿ÇÍÑÕÛáåååãâÞÚÕG±öfÀÍÉ౨ž•‰ÿ~siaXQMIÿFCCCDCB@îƒÂCFJ°\cl?t~ˆ“§çÀðæÐ¤žÈQtpjÿe_XQJB92ÿ+%!!ÿ$(-28?FKÿPTWZ\achð&°*±¢ÿñ— «¹ûÄË˰ÞåéêéÿèåâÞÛØ×ÕÞÕ±ÍÇÀ¸ã°–Œÿvj_UMD?xœ°¦°n²@BDGÄÀÿZ_hpz„Ž–ÿž¤ª±¶¿ÃÄÿ½¸´®§ž–ÿŽ…~wqje^ýWyÀD?6/+(ï%#!!¼Á16<ÿ@FMT[_beà ™láàÅ‹Œÿ™§µÃÍÑÔÚÿßæêìêéæãßáÞÜÜÛÓ°ÒÑÿʶ­¤œÿsf[PF?95;2/1À;==©°Ñþ°°ls}‡’œ£ûª¯îÑÂÆÆÀ¹ÿ±ª¤œ•Œ„zÿoe^XRMGBþÐ62.++-.?/1258;‘ ­°±Zš MôOàjiWÑqýq™Pˆš±ÆÔÚÿÜâêñö÷öóÿðíêèææåáþ: ØÑõ¥šÿ‚sbRD8.'þ.À*-19?CDÿGMRX^cioÿt{„œ¨²¶?¹½ÀÀ¿¼†àûÁûˆ;pqiaWPÿJGC=8545½5¤°=@DI9ÀQ«QTÅðZß^N_øã‘Ûß’afo}’ÿ­Éáìðóøý~àþþøóìæ àÿßÛÕÑÇ»ªšÿŽ‚tcP=- ÿ#(.5ÿ=IT^fovzú…Pˆ Ш¯¸¼½Í¼Ä๱à>`plâ_awâk„ FGKSQWSÑœ pz a9Ð×NKK9ÀRð°KMþbàNKIJMRZûbjp§Äã÷íþàÿþàûôé{ÜÒP³«¡“‚ÑÿD6('ÿ6CMU^jw…ÿ’šž¡¡ žžï ¤¨«…𭥡ÿ™“‰}m^QÿIGJQX_cf=jåa„‚{s{ ÌÀúVtsofZMñBn± Ðq°GMPQûRRû‘W\biq÷z‚‰•ÀµÇßóçûþû§ðàôåÒÿÀ¶´´´¯¥šß‡}qf9ÐI=ÿ2*(.9FUbjpwŽœ¥Àÿ¥ š™œž  ßœ—“‹ÀzoÿaTJFFMWaiosx‹“ˆ°qŒopý¬qom?jc[NC<°Ž Î]àKRZä [_ÿeimpsw}„ÿŒ•¡££¨¶ÿÐèøûöíêíÿôøôéÕô­ªª§ —ˆÀÿiea[RI@;¿9?KXcl¡`‰w—£«Àž™—3°ß™–‰…šxo7bWMðT[À´a×–—–¹ðvýñspûmlf_UKCù=°Ž¢IMRW[~öTU[bhmø`ÿ…‹“••“ÿ’’–¤¼Õêôÿóïìïöúöè÷Ò»¨Iðžš•ù‰1P5ÐaTI?;ÿ ’3° ¯ÿÄ×ߨËÄÇÑÿØÕʽ´±µ¼ÿ»¯¤š’‹ý‚D XPJJNWÿaec_\_fpovvql¿ ‡BÖ!•¤pwts6Zptj`wqÕ`êpYs¿A]0mi} ^h`;=:ñ° °[[  Çhotˆ’¢¡Àˆ‰ýŽÕ–•—£µÇÿÒÐÆ¿ÂËÔÒ+ËÂ?à¹ÄൈÐÏ ¿€wmcZW–ðbû^XÍaa\Z[aiqx³P™<0û.°ÿ o Œ² wðìÑijjheb^i‘Üþ0­_bal0Z\_qàbcf$sñyƒôUP,±‰”Ž• ­õµ²ð¶± Ç¼»ÿ¼¿Âý¹µë±®òvqj¼a°iàUPKK+à\____bf£w8pý‡$‘Ž’—œš–KÁ’Žˆ‘Pw€qf²TPzÀ\¡KNÿà=K”¡WW[bïð(²h‘”0ˆp…„ ûž£Ç@¨¯µµ´¿®«­±¶¹›À¶ýµÍ@¯«¥¡š•Þ‰‰„}tÐlh÷aXR;ÀWUQNPR  €1› R0SP|°~H—šœœš—Ø0(à0y h.0WÅù‘1Pñr0• \aVÑl Âú`%pû¡NRJŒþ_­«§¨­±²?¯­¨§ª­²¼æ¾®ªÕðKŽ‹ÀÈPX_²àÛ•â‘^a cðmñÐvpù SPø;Œ*@ˆ‰ˆÈPéPQq#Qsâí°RmRÍP„:P{cVÔDP¯Dù£g— ¨ÀgP¯®ôPº`PµšÀ¶´±Pð¨Ï¡œ—•`‚@{½ví0ib\[ÓP_„~1Xs#°õ0 x®Êq„…ˆ  LŒH‘Ý\€Î‘íÐ× »098dàÇÀabfjÒR1øW‚ä1TQ“¥«gª¤ ­ÐdP¨ª±‘»»¶²¯¯±Àÿ¡œš™—•S‹„7€e0fAcÈ0`,aì‘  TÐÊ`fjÎ0Â^…ù ,’@‘MˆˆA‡pì2h0û3øR<À g1€AUE€„ø ‰‹—¡¨¨£aý±B­¯²´¸¼ï¿¼µ±,p¯¨¡šõТ¬ÀF™Pc^ján0ÌT<À_aa_afmªB¯#‘e •—À#Êpí0Óàb_WBÌPÆÀ0ÓP@“ARÞq€çPÿŒ•ž§ª¥¡¡W§­®(r±.s¯OòûžœP™•’ˆ}‚pvtohccðie^ZuÜ‘ -à>-0_bipt¬plº°M‹Ž“ްQé`x€wðÒàe×àæ^_e^_@g£†“þàP‚…ˆŽ•£ÿ¤¡ £¨®®ª¿§ª®²´µÃà¹ý´ž`²®¥ž o£¡œ–­P‡€ë€Ñájmm`°ò‘%dA‡_^_²°`1rÐ ‡€gÐK’…Aˆ@aÓáccrà¿…ÕQ2`Q¢m@þkqŽ—ž¡ ÿ£¨ª¥£¤¨®¾Êp´¸»µ­”`¯Ûª£f€ P‹»„}xsm5`mjebapå-2¼€`UРA PŽ‚‚°B,op€}!wì0Òà-hPfeº€cÊ`W‘À åÐÐkA‹0‰’ÿ™œœ™™£¥ß¤££¥ª¯‘¶¸ µ®)p®ú€Úð‘æ@x®`PAÑ€qmheY#‘öpÊ€TUÐP@?€p­pPo@¿A~{€ÿqpptz{xqejQ‘cÖPªfhø0€» æÐ¾‘ÀÿñÓ€]Ђÿžª«¥žž§¿²¶²­«±šÀ¼ÿÂÄ¿´¨¤§«Ãª „bàp» ieÿ__epxzsjÁhÏ`p 4‘-°Ïàtz—‚Œ«`{M0‹A_;ci^WT!°sàÂo¬Àa¡ž wv/qmjiPvO1Ó€þoq{«ÆÔÿÑù¿ÍØÕÇÿ½¼ÄËÐÐÐÍï®–‡Ð }maï_fmo TQR·Xaj'°}„߀ž™’–š£š‘$XW[cjps"Pþ8mllpw{}?{vpib^™p AŠPWRBW›q0àvòëz€r‰À{xÿwz„»ÔÜÒÿÀ¹½ÊÐÉ»±ÿ±¸ÀÆÇƽ­û“~ zsiceÿjswvmc[Xï^iv€Ÿ–œÿœ“‡}}…•ÿ’‡zsppolëfa`c‰ˆ‚¥~kp‚Û ÏÀ}¸1QúðKó°JNTWUóRQ®² qmosw4P@¡P„<~}ÎÓþ¶°Œ¥ÆâêÞýÍ0ÕÐÆ»´´ÿµ¹½¼±šlÓba[Ž€cÅ sm¿hflxˆ•x‘œÞ£…{w¢P…}ûoaép_a^Z[ÿbo}‹—ž•ãˆ&@sh[M?@9;BJNÀ;ÀöÛáX_„0vtplkjl‘ t<€z~2ün!) ‰„…—´ÿÕìóêÛÐÎÑÿÒ͵­ª«±´¯ ‡m\U^róbfêrttz‡?•¡§¥ œ¨`ÿÀomsx{xoº0þ+abhq’¡ÿ¨¥šŽ…‚‚‚÷€{vî1f_TG¿=89?IQ8UªÂbZ¥Ðqloñpà+’C ™=`à…„…¶×çáÑËÿËËÊûµ²±ÿ²²­žˆmWKÇKR\œ±&\0vw÷€Œš‰a—’Œö3ÐttC xpc[úÍ\» o{Œ§ï§‚«p€~zýsï je\PF==DNX'€±ÁñpWýZ+Àqpjc_aáeå m’ÍÁÎ ˆ•ù—õÁØñúðÜ¿ÍÄÄÄ»E@«ÿ§¤ •…p\QŸPU_jts€m@{îŠ0‡—Æ@ ™[‡~W0qwõ oh2þe@ls}‹šª®÷¥—ˆ­~woþr`mf\QF@?CJT[ÅQ•qÀ`KÐ>z€b\\bjÝ‘8ÀÏw€ˆŽûëP‹ÿ‚{}Ž®Ñðÿÿúåʹ¶½ÃÃû¿¹É°µ²¨“xÿ^MIPas~ûzpˆ moopx…•£ª«¤™ ü‘Ð}}~{scßTMPZfÎ0ˆÿ’ž¥¥š‹}vóv{½ÐKa[UQôå (!U@KJMPÅTl bí‘7€@Pw}>Èztt{…„€þm ‹ž½ÞöûðóÛÆ<@•à»»»¸ÿ¶¯ž‡mXPPZhv~€zqnðÿcflv€‹•žŸ¤¥¡•…¥ ER„ÿ„€tcTKMUûcpЉ“šœÿ–‹€z}‚‰Œ¯ˆ€tiºaT‰°G÷JNRçàFCCIÿQZ_b_\XXÑ\Y[ 'p€ò0n€µ°‡š¹Üÿ÷ÿöÞĵ±¶ÿ¼ÃÇÉÇÄÀ¼ý´`Ã^jw„{·obX1ðiv¨ —{ž!x}…Ž©òmiª’iÁx„Žs‹€P Mñ‰€vëAéj[bÊQPV FJN/UZZU<UþáÝpÐn@Ï! ‹ð€‚ÿ‹¸ØñøêÐÿµ¨­¼ÍÛáÞÿѶ±«¡~ophhl„ÀwmçñKXiz‚„‚HPø±p•0š—‚s?e\[blt¥±íòjì0sAàÜlhËßllic\[AKMÞÈPNMJŒ°NQçXai“€[ oloÿw„™œ™’‰ÿ„‚„ˆ¡»×ÿíöìÔ¹£œ¥ÿ»ÑãéâÒÀ±w£—Û0„€{ÿvl^PFDM\ßo}‚€xás€_Œ•—•¦ƒ…Ñð/Т‘ÞP}{e1pàfp‚Pjæac4 !€ÆQ 5P6Qga˜Ro°œÀòn ‹Ñ Ôp“™¨ÂÿÚêìÜÆ±¥¥ÿ±ÃÕãæÞÍ¸ï¤–ŽŒv–Ž|W0JpZUTW\z¡k°bahtS ®R¹AzØòŒ¨ˆ}piÁð?wxtlc\ @=Pþö0b^\_cff€×°"`p]p¹ A[ÚãÐqó ~~Óa‡Žÿ“™šššž«½ÿÍ×ÕÊ¿¹»À¿ÇÎÕÚÛ×WÀ«î"p¥§¡×àxtp ‘#`CÒý ¸ ezøCarq“—œžœ÷“ˆ}@€‚}cvlU@˜PYð[UÏQP’P×Ñ+€@bè‘hÚPp!àtxÎpºŽó’à —š£«ÿ´¶´­¤  ¤Ýªð€¸µ¯H@œšg–‰N]0#P6Ufhy€lj üÀR qÒ€nxnwÕ€ w9 \Ò¸PÖ,!•¡O ¤‘ï3@P¡l‘‹3‘{a„ž€ ±½@p"0Òð€#@4“~#v LR0Ô1ý–—1’#’™qA‘{¯`ññK2Í"qP0 Îü’å%Çà !1ärpz`t 2Ò`r€, ô"8!ó#/áF0š°@+@¸AŽß® QS€{!Ö<` 62F1Å%íôð$33á‘2¨q”3&764!3Ô`@‘l"²m²B“">“Œ Š ‘5ï7þ&n$°@¿@¿@æQmÀ@t4áHÃ##21"îõ!M@j‘7A1ÎÁ Dt 9’$AœÀ2í6¯€2Š4…B‘Ñ37–#×6A"sCŠ"ÈC 4“B,#p2åBCô ü!Š#3÷Cë44–4“Cõ#2þ$·´F»Aå3ý2RWFÿEÊDõ:NSì1š5FTsUY%72á@YT¢ED;`uD{F{íBøXô(³ xmhi­ohq„ŒOð…Q`vïojms<À…‹O‰Á T`o aàAÁ#°ÀÑîЋ…vÛ¡hb` lv~Mü@p€ptpmmpt×{„‹§ –« ˆ}}ß±ilqxïÐ=’ã`…{sjªÁðgz‚ˆ£Àvpï . p}‚ˆ€‡É‘Z Ãtwp«‚1{~{…Žwpˆw¨Ð÷cfm°‡•£­ß®£}oPpUWÿ_p…šª´¹¶ÿ®‰q^NGGÿMWcs…–¤ª¿ª£™Ž€qß Zÿbmx‚‰•–û–)a{xslh½fŸppv}‡ø‹õ…Pàt pw}…ƒ‰Œ´ Ha5CC€á2€ CÐz~ýE0k! BÀ¼DEr‘ñ>ƒ«2Bà—Ý ·àš‡`he‚'tKpÐð]`¶€8€sÓq*a—D340à=pFw ˆ…ªs½tE’ve!š@o! 3 ð…Ž`;`0ìQŒÑš@À$w{ ÀÑ2ÌpxGB•ðÎÀA!Ù€¡8q41qA„ˆ‹N0¸"@Àd"Ýq# qÙòpp34Éq‚ís6'B`°”ñ°@w~z  }Æs„~óY=CÌ"½àÁ€B‘4°Wð˜†ÓÒ°v}RÓ#À€üÑ42‰– ª±ÿ¶¹¸´®§ž—ÿ“’•œ¥±¹½ÿ½¸®¡“‡zqùlžrúñpib^[ Z€Ðej_!aLpí1€.0 ðæ€’±û b`Ð`Œ?““‰‚â! ½á+‘plÁ«°¬ ±`åÀ°PÀ¨ÀÆp…… ñøË0,pè‚„‹•ï ­¸½!Òš•“ÿ•š¡ª²µ´®¥œ„ŽÀQBŒ®à¤×`£o p?€‹Ñx"ñ‚…@š€yp.ÐÅÂó ‚§`—àBÐLp~woha[X<б±d°b_¬ " b€°`!à„áü òprvww{û…’L༼µ®¤ÿ™™œ¡§­±?²®§’‡4pÓ Lh ßÀbeËá-¡j’Ѐˆp“"ÁÒð1ðIÒG!_²å’„Œ“—á—ñ°›;q­Àzsle_\]õ¬…Ò4¡waY‰Ûƒ•…°ˆ‚ððb’‹Ó c`ˆ–£®ûµ¸°Ñ¨£ žnG°§£œJñxqZòȤÁ?¡Æ"we`dЖ“~ðˆåá€3ÐØ|ù¢ýlq°{„Œ•££“ˆ[ hâX‚i©ZXXZÖÐo°7‘$‘ႉi`&ð£b(Ç€®`Ú€}Óñt à`Ð;Œ™»Ò»µ­÷ઠ–¬ W±ÏÐjà°°a@6QI¡£pS o¦€x ái3‘(!'6Á–š¿ž—Žts`hä:¡8 hpàßÂbch;ow+{vN ¾²0f¨p4>à‹sT¾‹•ž¥«¦ œ÷–•–x𜖋β{to™°p¶%°âã)À¤ szÀNBÓ Ãqt‘C.0à‹‚ÅÐb Dv¢Î‘4 j}à-AC"6A^À› ù€;cáx^Á¹"À#:p‡Œ¿’–œ¡£¤ ð𠆑o’Êq·ÍiWV‘4ajD80„ñ›€5â‘D‘È’ÁòbD„àˆ~qs›pÙ4ÀfimU!$ÐÁoÐv¯pÇ‚{FpÁ•ÑnqAçÒ-0âáa¢3}}p–šœœ™« “’p’þ‘˜ã ±’€Ð²ærº!{¨`à!@ºA¡+3îÑ-Áóp‹X  jг°ã1 @ÐvÞp—á@à€ç@-0•î {Ÿa‘à·`&‚Á€í  ‘®`è80ÖP™; •ha•Œ‡Œ$4q ‚<`ô‘±` }€`–pßpx>a¹tˆ ”CåqÏ1 Àë€wu" ñp"°N3tÀ±Á2-a`€{Ê"!~#ÅPÎ01öJQ„ã’ºÀC æ¢ð‡RN€œáÅ"¡@Stb¨€‹òÁˆ¢•‘ò’zAë’Fpù°lázápN3ÝЈ Ç@p½‘[2:p‚;qiPoƒ¯BeCGÑät<ö˜1瀙0颂=C Š@S QÒGA É${€2T……AS…†PR…ƒ’‡"…… #$„_ ÷Q3¡_ R1û5ÈÈÀ!‘'BMÀŒ/eú.ú_ oào0oBoToff ÄgrlZP¿0„h ß B4 ‡¯0í˜lÁ`ÿip1`4 Ö` , Ëg ‡p³pÁYÐs3{€­rp s à2öÉ2ò2k  o£(rßk Hp`…£ø“©\p|£ Z¢PKuÅp)PGpµq Ák¡À!™p|£Âq[ àÀ{¤¿o P Œ¶€-à‚p{¤ Nó¡uµB<¶Pr@—{£ >‚ÂÓ Š@à/0úɉ°ÜpìÁ@“´Ë á“¶PR“³®¶@#“µ #_ ú4óÔò‚1û6ÈÈÆ3ÁBM Æ,Ÿeú4LŸ^ŸpŸ‚Ÿˆ”Ÿ¦ŸffÂw@rl(ZPà„h ê’ B4æ°ú” ˜l·` ¥Ã¨š{Ж£3©{Ђ–¢ë‘q5ÈGqÑ(­0c¥{€–¤u¯‡¯™¯«¯½¯Ï¯á¯ó¯¿¿)¿;¿M¿_¿q¿ƒ¿•¿§¿ ¹¿Ë¿Ý¿ï¿P5ÏÂêj+7+ÈÂKñBMÂ>ÏPÊ0^ÏpςϔϦÏÀ¸Ïfoxf(z„hgó@C3 /¡µJ3Ÿd& ØŠÑn3`4ÑP G ¡pHÚ|0@— pI©ú Wq êÐu߇ߙ߽߫ßÏßáßóßïï)çd6ê¿1U@JêW]éWpæW$ã¿1Šâó1”æ)AÉ=Aµ²ä¿Àä¿PR¿Ú#¿ #=AÔýïD*8R( ÿ‚sl«ow0ÿ1ÇXa!BMÌqYÿïW€vÿˆÿšÿ¬ÿ¾ÿÐÿâÿxoŠoN?`?r?„?–?¨?º?Ì?Þ4)q œt)AqC¡pÊ67wur^pIwit‡wzr¡ v1œt{€X@D@k XPÇu7C™á#ˆ€~pyD½@‚B0 NàràQ“E 04· f€Ÿ0´@204 P;B;€0ü@¡C›BåAd_0`áqá" •@Ÿ3 D‚ Pî‘Aoà$TÓ1W@§@Pƒ=€è‰›­¿Ñ‚î.6-2$&4:4}0øsoilF(Ù£Q+ÇD6¿QBMK6D#63w!€ÖT„UÁ"@'XÂYÁY1ù a€´à  Ö€ cP›f ö#`ÿ!ß"#E€'ÿ$*ÿ'%ÿ+,ÿ)-ëc`K`/ÿ0.ý n`1ÿ22ÿ3 4 ÿ6 5!ÿ7 !6"÷8¢`#9ÿ $:#?ÿ #> %;ÿ&=&>ÿ &< %@ÿ'? '=ÿ&B '>ÿ&C)@ÿ 'D (Eÿ +B )Fÿ*H *Gÿ ,D+Iß +Hp,ÿJ,I -ÿK,P-ÿJ .L /ÿM 0N 0ÿO1P2÷Q6p 3Rý>p 4S 2÷WFp 5Tÿ 6U 4ZýVq6W5[ÿ7X6\ÿ 7]8Yþó°]9Zÿ8^:[ ÿ9`9_ß;\:‹p<]ÿ ;b;aÿ;c>`ÿfÿ?g@hÿAi BkÿBjClÿCmCkûÚpDnÿDmCrÿEoEnÿFpDtÿFoGqÿEuHrÿFvIsÿGwJtÿHxIyïKu*€JzÿJ|Lvû6€K}ÿMwK{ÿMxK|ÿNzL~ïL}Z€O{¿Mj€ÿP|N€þv€OR~ÿP‚SÿQƒR…ÿR„S†ÿS…T‡û¦€Uˆþ®€V‰VŠû¶€W‹ÿUWŠÿVXÿX‹YŽÿZY“ÿ[\’ÿ\‘Z•ÿ[–]’þö€^”\˜ÿ^“\—ÿ_•]™ÿ _”`–ÿ^š!`•ÿa—_›û"*b˜ï`œ#6c™ÿab ÿbžd›ÿc¡c ÿd¢ d¡û!^e£ ïgž"jf¥ÿ#f¤g¦ÿeª$g¥ÿh§i¨ÿg¬%i§ÿj©h­¿i®!¢ ÿk«l¬ÿj°k±"ÿm­n®#þ¾m´$m³ÿp±%p°ÿp·o¶ÿ!q¸rºÿp¿s¼ÿsÂ%u½ÿuÅyÑÿ……£´¢¬ÿ°¤ˆF8T€ŸÿŸ±£s««¤·ÿ¡~…~e`—Œÿ—|ž¸Ÿ«Èÿ·¯°µÅÑßöÿòÄ‚…Ä䱯ÿµ¤˜™««­°ÿª—ƒŠž£›—ÿŒkƒ–€ˆÿ­´½·º°Ÿ¤ÿ¤zn zÿ 7|‰E8uÿ‚sk‚ž|oxÿŸŠsFJkƒxÿsz…˜|^nsÿs¢™‚£¢œ«ÿ±œUOzª··ÿ¬°g¯¤’«ÿž…{bES‚ƒÿ™ˆr§Ù¶¯¸ÿ­Ÿ­°Ãÿ×ÿÚÉœ¬¯‘£ÿº²§µ°¡ªÿ£‘|‰™–™ÿœ˜€bg€z{ÿ¤¯¶Ã¶±¶«ÿ­|e£¼eÿ@¶§sTÿ€g\s„qsŠÿ ž€EEz||ÿ…‰˜œŒz[kÿ‘§’~œoruÿŒ[8v§·¼Àÿ¼«žc|£¯§ÿ—‘ƒbAUs{ÿ™€R¡Úµ—«ÿ¸¬¤¤­­¯¾ÿ¸µ¤•£§…—ÿ«™¤º­Œˆ…ÿ–Œg€‘€€…ÿ¡«z|ЉrÿsŸ¶¿º·º¤ÿ•°¯¸Ð–ÿ n°°Œn`rÿq^bksoqzÿ‰£…:N€}}ÿ£«‚Šp{ÿ£—…¢†|vÿbBb™ª•·ÿ«±±‰j•·™ÿŠ—s=!Tv‘ÿžg3oº±Š—ÿ­­­·´££ºÿħ‚¶«š™ÿž£ŠŒ—‹‰sÿ‰–uŒ¡•ŠŒÿ£§—…ƒ‘ŠrÿYs¡¡«² Šÿ•¤­°¬g(ÿX««yPkjÿjjQaxnTrÿ–—\3f…Œ‰ÿ—™‰—{—ssÿ‘•£™—ЉŠÿnOuŸŸ¶«ÿœ¬¶«s…¯«ÿ¬…Z,'-<ÿ8ÿ=.8OoŒaÿLgs{so„ÿjnx`E~~žÿ–€~€gOŠÿ…œ½×µ¡µÿȰ~|‰ª««ÿ‚sgbJB+ÿY…jXg_iÿY`nz’c.Eÿа¡˜ž£¤–ÿss„…˜™…xÿ‹—œ¯«Œ›£ÿƒgrzsrowÿx’{s˜¤ª·ÿ­¯œ™¤¤¶qÿ.;aYMÿg€ojsŒŸ`ÿJrssYYj|ÿ…¤sMu™€ÿ‘~……zFMšÿ¯—•µ·«¤âÿݽ|{•£’ÿ‹„xx‚žTÿ2ˆ­œ€XUÿEObn‚YDÿƒ‘‚¤´·£…ÿ{v‚Œ˜——ÿž£«—˜£¡ÿ—œ¡ž‘€|sÿz…bz™«­ÿž™«¸¼˜ Œÿ( !YYg{kÿmzsTOmšbÿLf\TQbz—ÿ§¯¡|sM{Mÿ‚Ÿ~zDrÉûÖµ ±×êÕ¸ÿoƒ¶°«š•ŒÿkUa…°‚Joÿ²¶ž™rS`eÿjqY%$q¡ÿo¤·§…pvŠÿ›ž£˜•£«§ÿªœ‰«·£§Äÿº·²•…‘«ÿ¯ysš§«›œÿ§Ã׫grgFÿK‚gYu‚nTÿka9)+8M~ÿ~p{ˆ–™’ÿ–‰›)@@}µÿ«Q!gÍÍÄÿ¿¬²·ÞÙµŸÿuŸ±µ£Ÿ‚ÿf_z†£§‚°ÿ¤…‚—gQm…ÿvY%7€¤žÿ£­£—ses‰ÿŠƒ••œ§«£ÿ£›¡¬¸µ¾ÈÿÈÈ¶Š–g{ÿ zqq{™¡¶ÿ¯­ŒrJL|ÿn€†‚†…œÿ™kD( >mÿsg……—£—žÿƒ†–\Fsr¤ÿ o%)±»Öÿº±ÍÈÀ­›†ÿq™«±­¯¸«ÿ‰š¤º«ÿrn’`LkŒÿf&7\jsŠ£­’r_rsoÐû‚¼àœŒ£°«ý¶¨¡×¸¤ª…[ÿešmrse‚¤ÿÍϺžz@3g†‰‰…••u6àÿ^ELA1LXLÿ9q‘–«¬£‚ÿ…¤±‚¬e\€ÿ…nxŒ¡¶ÛÏÿ¶ÉÄΜ§¯§ÿÁÕׯÃη‚ÿxœµ´¤¤•vÿm†…`_qnDÿ 9k|b@Tÿž`3Lo„zzÿvu|§¯««ÿ§¯»ÂÈ×Õßÿì᮫«€z…ÿgq‰~§Æ¶¿ÿ°¡›zsxŒ‰ÿ’‘¡ŸŸ‹~ÿkm|sisЉïnkrz ¯«°¿Ü·×•?@.ð™ÿ£µ××ÃɾÈÿ¼ÎíÞØíòíÿëâ­g[–¿¸ÿ¤«˜sTL@BÿF1E^XbqaÿYBFzƒ@1ÿs™‰x{‰……ÿ’«¶¯§¶ÃºÿÃÝìåçê×´ÿ««|ynOg™ÿ«¯ ªž~rrÿ†…–’ª°¯¶ÿ•YLq™•sÿg€«¯£€„ÿ—Œ¤°«ž±ÄÿÚ¶T"7X £ÿ¬¶¬¸ÉÛÍÅÿ´ÛïÕÐ×îëÿϵ‹cjž¶µþËðs[kpƒˆjÿ{¡«µƒ[rYÿ.JO-'Bo…ÿ‰~zz|‘™¢ÿ¬§¯º·¶¿×ÿëìà×ݤ—±ÿŸ~k3OŒŒÿ…­¶°sWoŸÿ§¤¼Å«…sXÿTv—ž†cj€ÿ™¤ Š¶¤™€ÿ}„ž™™Õ¸¼ÿ…@€ª°«ÿ·ÍÍÍÓÄÑÿÝÉÄÉí×§£ÿ¯…r’°«™™ÿžkzªÄ¸sÿ‚‚£Õ«{™ÿB,,FeSUaÿjaL;Jp•¤ÿ§¤§™¡«±¿ÿÏÙͲ±¤–§ÿž£n%N¡£„ÿ•²±²k[‰´ÿ¤›µ´–bWxÿЧ––}ko ÿ¶¬£ž¬¬žžÿ¤–ƒ¤ ¤ÿ™$M§º£ÿ•¸ÓØáÕÞ×ÿÓ×áẻ»Îÿê½vvŸž¢¸ÿ°|ƒ°¿²˜ÿup•ì–ª›ÿb,%EgXMfÿrkE2Enu{ÿ|‚‰…—µÄÄÿÎÛ×°ŒŠ›ÿ™•_.Oš·­ÿ¬¤•‰W`~‰ÿ†z™mLLvÿªÃ¤zYnŸÿ¸¼«ŠŒ­™­þ‹Àš|Ÿ®£žƒÿ=q­¯«­ÿÄÕäÕÝÄÙÞÿ×ÎÓá÷îã¼ÿ‰ƒž ££‘^ÿaŠ­«¤—~‚ÿ¢µ´™§ €^ÿRWLLQWÿB8^{||ÿ„‚ƒ§ÄûÙÿäÙªŸ¯«ˆkÿ[MTs˜ª­Ÿþž2I`i[aNÿPQ[—«¼¸¦ÿ{[a…—Ÿƒkÿ…½¤’­¤»Ãÿ±¯Ä¿™nJ<ÿFœ¤›±Å´ÿ­«··ÈÙÑíÿîÜíº–{igÿzrgzoW[g¿…žzOr —ÿs™€@&>ÿDSNTOTq‰ï€ƒœŒòà§¶µÿ¿¿ÙÈž…‰sïkiso¨Ð¤•ÿ­Ùš..zži9_qkq ¯ïÿˆ[sœ–sEEÿk¶±‰ªÄ¿ÚÿÚͬ¸žij¢ÿ3+‰Œz£¿Ãÿ«¦¬²ÈêáÓÿ眃vpL8ÿSYa{xsokÿx‰™•^p¤ÿr\_‚¤Ãy ÿUÿebgiL79Xÿ™§oggo‰ÿ¡• ‚°Ã¼ÿȰ…oT2Lxû‚€!À ª­¤…ÿjj«§£¤¢œÿ¶º·«†—ª£ÿˆ«€€jbu—ÿv+ J7,‚ÿ’xoŠŸª¬¸÷£xu$0‚zƒÿ–ÂÈ£¡—ÿ…œ«¡‰€­Ãÿ¸™op`'(Zÿj}™¤žŠ§ÿ‰]LTag…„ÿb@.FŸÍ‘nÿnxngg‚€ÿ{£¿Õ× —vï[1I @ƒ‰ˆï’«±Ÿß¦²ºÿ£±Ïñ«¶ÿ´­œ|°s3Nÿ‚™—7$AJÿ´°‘ž£«ÿ¡¶ška‚ž§ÿ¯ÎΛx‹Ñ×ÿ¾ºº£œ¤§£ÿŠ‚º¸‘rO`ÿi.!Ygs¢ªÿ–…¡˜vjYÿTs•‰[B1Bÿ¯…qknmZÿcŒ…z|•«¿ÿÍŠz[MMT‰ÿŸ……Š£Œ–—ÿ¡¦¶µ±¤ÃÅÿ¡ª××´µªºÿ°–¤¯âœ1,ÿ\pkE.M{vÿz•¤ž‰on‰ÿ¡¤j:MoŸ¡ÿ·ìç´—¿ÄÿÏÚÓµ«§«¬ÿ ‰ªroXaÿ^.(ppr¤Ÿÿz‰˜žsgOÿFUps`TF3ÿ7UXL@Q[Tûg8ð–sby‚ÿobQz…£žsÿ~Ч«¢«¬ÿ¶º¦‹´ÏÀÉÿêëÈÈĵž¤ÿÈÚäÐv%ÿA^Œ€ssÿ™™¶£ž™ž–ÿg^p_k°¸×ÿá㼫¬Éíìÿ×¼¢§œ‰~sÿgkˆpsQ$ÿ1gnWr{s}ÿ‰ˆrpk\Jÿ@TnsvM)(ÿ1!7g`TXÿb–«‰D#gÿ€‚‰œ• «ƒÿ|‚˜¯Ãµ¸¸ÿŸ{}–ºÈãÛÿÞÏ××È««Äÿ×޿ܬIÿ)@Yc}~—ÿמ£ÏÜ—«ÿ±µª`QŸÅÄÿÜîÞ²œ´Üàÿͯ¡Ÿž‚`WÿkLO…ve@ÿ,gmUf~‹ÿ…zz{sx‚qÿT[gm…~b^ÿU3#IBE_ÿ[‰g3 ÿ-Oz™• ´šÿ‚mkŒ­±«¡ÿqN†°ÈÓîÓÿÉ­¾ÝÙ¯«Éÿż¸¡n3ÿ  3Jgs§ϰ›­Ÿ…–ÖÐÿ°«k`£ÛåÛÿÙ¿£°íþÓ…ßs…­¢zb°myÿxg?I\pÿ~ŠŒ œ€zÿrz’ zjc^ÿzš{gn[vÿD'o_B^ÿ€bA7Xÿ••¤°¶ŒLnÿª­ƒYFc¯·ÿ´ÝòÚÜÕÜäÿìͪº¶º—nÿgz4Wu™ÿ{jq«´¤›ÿ•œª™¢ª±ÿžciÃãÂëöÿ¯Ÿ»×º„}˜ÿ§¡yr‰Šzvÿ‚o\+&Laqÿ‘˜—Ÿ¡œƒcÿYks…{psnÿgqqfF(T€ÿsB(gs[@oÿk™Ð‚( ÿ (g ×­z‘ÿœ‚]8>Fjœÿ¬¯µÃØÙÉÄÿÕͪ«§—™ƒÿ¶Üs=›×Èÿ¯vj£¸«•™ÿŸ§ª«›¡½Çÿº‚Z›ÛÑ×åÿ²¦­µ°«­¤–‚us}•ŸýÀÿRNu—¤¤ÿ£—€~~z}zÿssv€‚ockÿgO3 Q ÿk`@aˆ|onÿs¶ë¶g#ÿL|o€¤‘kÿJ.E8@[r…ÿx·×мºÙäÿÚÜÍ«¤‰ÐäÿWOžµÃº…ÿ}Ÿ¯žœŸœžÿ¤–‰†ž¤´–ÿ—xŠ×åÓ¿¢ªª’§¤òðÿs~œ•‚|< ÿ 8n…£¡„‚ÿˆŸ¶«—Œ£ªÿ™ƒqk‚y@ÿ,.Xpqr†ÿa~­¢ˆjD‰ÿÕæÎ°q"ÿ(n°ˆN>:ÿemiSz¦Ÿ½ÿÞïà·ÜñâõÿЧn€Ï¶T>ÿr™£±Ó«s‹ÿ««žŒ™£«ÿŸ—˜¸¶£ºŒÿNr¿íÓˆqŸÿ²€—ˆqs…}ÿ€‰€rciI ÿ.Yj‰£›¦ÿ·º·ª ˜¬§ÿŒniz…™™Kÿ9Eor9.4…ÿ«‚…Š…nT•ÿ·ÕÍÐÑ•9ÿ@ooE:2ÿ`zciˆ­±¤ÿÄòôÍÐÞ×ãÿ¯v£ç¤?bý|Œ°ëº{{•›÷™™™Âౕ–°ÿ¯ž±½q.[¾ÿ×u{vYnrÿYp–…z‰Š‚ÿ€‚k"1Uaÿz–£«·¶—’ÿ°µ«™•ƒ~|ÿv…ƒOOnŠyÿB(3eosMÿMjs§­°™­ÿÕß¶gQ,TuÿaLYXxˆuÿ…¯ ®ÜÜÄÿÄÉÃͳ‚µÃÿæ‚!_—ÈÞ¿ÿá·vuz‘‘ÿ¡ª¸À­˜žÿ«˜Ñ,'sÿ·¡ssxeus÷Xz-€•¯¼ªÿzE4Okkq€ÿ…Š–œ‚…§´ÿ¯ª£•„vnrÿkJ`o™‚sÿ,?[@1`ÿ€¯¬•ž§º¶ÿ‚ ¶§¤«F:ÿuuv€|~mrߌ®«ÄÃÜúÿ®·«­±{&^ÿ¢¿Ä¶½¤£¿sz¤¢¢Œ…ÿ•˜–‰±­jÿLFYQNgjTzziŒr{ãPÿ°™vDBiŠzÿsz…›‹~ˆÿ˜ž¤¢‚ƒoÿsoOBXg™¸ÿŸq\_T7(=ÿ+@n[Xi„Šÿz‚ ¼Ãжpÿ&9‰zs„{uÿjzƒ­™«¤Äß¼º¯³º$ ‚–ÿAMаª˜ž´ÿ­Œ~…𬝰ÿ¤™™›£ž—Šÿƒž¡§µn ÿ 2?yŒzÿ…z~…{skeÿL&2;DUÿs‚†‚z…–ÿ–™–€|†›sÿXbYa›Í‰Nýÿà@  ÿTeY€¬Íÿ··‚;8Z}~¿ƒv[X¢Á ™ÿœ¼µ§«·®«ÿ—¡–r[sˆ°ÿ§¤¬¢€kŠß¡£­­£•°ˆƒÿ£­›Š‚nzMÿ2$€±ÿ~r‚‘ŠqLÿ7E`gmL9,ÿ9`najosxÿ‹Šƒˆ•ƒzŠÿ‰\j’Šrƒµÿ…Ogn‚ž™bÿ ,,ÿ%g•–~•g,ÿTzsznY\ÿ€›Š{ŸŸª±ÿµ«ªµ˜–ƒ•÷‰kmßp¡ª£ŠÿƒaQ‚ Ÿÿ•™§œ•š­£ÿ§¢m)(?r­ÿºs e™nXÿoƒoF'4^Œÿ¸º¤¤º°|nïk^es@€—{‰¿˜…€žšUQPžÿ²«€R^kk•ÿ¤‚@)WK8ÿIkgE#,(3ÿ'9bgkruÿ•Šqg–° ÿ§«±·°¸gsÿ…™{qn|ˆ£ÿ’·´ƒsanŠÿ¤­£•Šž¤£ÿ§§¡fabILÿ€±ÜççÃgÿXkbYFBIÿY|­½ºª¡«ÿ½™aKk‚€}÷sz|)À—…‚žï‰WnŠ{@ŒsYÿj‚–™™nMFÿX^XWXynÿ@((,FTÿMYv ¯œcûX¸@ µÃ·—ÿi{Z…rv~sÿž¶ž¼Ã£—‰þ·€ž™•«²ŒÿiL91Nz¶ÐÿÐÐÍÃÃÙ?ÿ (HBBR}ÿ§§¬ªŸ––§ÿ¤žss•£Šoÿ{~~{}–‚ÿŠ™sTp‰¯´ÿŸzfaz£¶¤ÿ‰kZijseT÷r…po XOk|ÿsS,8Wgr„ÿ¡cz££ŸŸÿ­Ã™agZ,kÿsn…›¬§£½ÿͰšnyrPbþúÐjcM:Am£ÿ¸¼ëãÿÈÅÿÐÃÄ—) #IÿO^z–¤§¯­ÿ‰x~—«œ|Œÿ–‰oqrsÿˆ‰™ž‰fOÿr¤¯¤¤žuUÿm–•…sz€ÿ{g<8eŒavÿ™¤zsˆ|ˆzÿT-BJOc‚ÿUg€‘«¸¸ÿœ~z8%M€kÿpŠgo¶¸~ÿ>(Mnebÿ@2@Lp‚µ×¿ÍÍè߸·v ÍÿÑÍ\&y™keÝx=§ƒz¸žÿ~v{€znbÿqƒŒ€‰§ŸmÿRDk™ –™°ÿ‘f‚ª}jo|ÿ–›z^JQaeÿQn‘vrvqÿš—x`YB$ÿTÿbYL1@DAÿ 7LaPI•ÿ¤q†¯«¶ãÿáäáÕÙÚÙÞßÝÐȰ¤ãð—‚ÿ…¡‘Šž€gnÿ™‚|usTJ~ÿ¯¶Ð×ȧ«ÎÿãÛ¿˜fsŸ£ÿ‰{€€s{~ÿ€zpX`sƒ|ÿgJ=FUQp{ÿM4M€z)ÿJksospeÿnoŒ‚—ve{ÿ‚zWPv‚—ŠÿT$1,ÿ(7BX…´ÿ‰‚¶­£¶ÎÚÿÑ´½×áÙãÛÿÄÀ½¸¯°Ÿuÿw‚…Œzrmaÿg{xs‚ufÿ‚‹ÉÞħ¤Úÿݺªsj€žÿ«­­ai}Šÿ‚g\PB?LEßSg@,(L[aÿygT Ipÿ–˜~orgrÿ……™mzuY÷@r€_^\sÿe,…q"Jÿ8(Šr…¡ÿ~—¯¶¯·ÃÜßÕÎàÕĘð¸·ÿ¢sar{ƒsjÿ`boŠ‚r‰{ÿ£ª‹­ßä¿ÿµÃø­–uÿ£™¶¶psï—Œn^D 49Hÿc‰™„zE ÿj§•H1Qÿk£ª¡ œ™sÿeWz‚oMSÿbXMr€ƒž÷£§¦¹ ¸¢M<ÿLT77(ÿN…ˆ £š«ýµw ÃÄ¿µ¿¯ÿµµŸk^TLMÿbb`rƒ¤Œnÿ|ƒ~›£zr¢ýÄù ¸¯‰[ÙÿäĤž£œŠž¿««¢•zpº°oÿTYŒ¤¶¤,ÿ7•e!#nÿŸ¼Ã·¸£kMýSè0sWNTfxþª°ˆ…µÙ±«…ÿ‰µ¼™¶¡ZXÿok9%nÿž£­®ž˜Ÿ¯ÿ±«­µ··°«ÿ«­šuaDÿILF\s™~Zÿs{X[snk‰ÿ­¤¬ ™–kYÿ™Ä±¼Á«Ÿû‰¤‹ºŸvŒœÿ‰pSLŠºº¸ÿn9,4 Pÿ™£žµ×Û¸uÿ,:s•oiSDÿYfo€ŠœŠ|ÿŒ¿Ý­£µ·ÿäêÝkfŸ¿ÿ™xk'&T–£ÿ°ÄÄ­ž£›ÿ£­¬·¬ªªžÿœ…rO327%ÿ&Legi`eEÿ!7ORn—ªŸÿ‰~cYnŠª¬ÿ£ºº¬š‚ˆ™ÿ —«½¶—ž«ÿ……¢—¶×¼ ÿ ‚BJgÿv«¯£ª´ªsÿD[x‚nkXMßggafzÕ v–ÿ¯ªª¸ä×ĸÿÉôÃT{úµÿ̓`[Nk•µÿȶ§™ˆ’žÿ’𣣛•˜|ÿrrpY+&^ÿgTWbP8Fqÿsk…œŠb@;.L€¯¶¶¶A ÿn`jv…˜ ¤¿¤‹«·££ 0Åÿ¶£¡±Ùÿn‚‚¸Î­¡°ÿž™œ¡z€ÿns‰s_^ozûqq§µºÙßÝ»´¸ùðWeðÿý…Y.Bm—ý§•°–ŒŠv}¿Œ•Š˜•…¿ðAÿ!=~‘‚o~ÿz~«§~zŠ~ÿ^3$7k¤ÐÍŸ±§£‚oVÐËgþ²§°¶«£°ÿ´Ã± ºÄÿ([…§ºÉåÿÁÏÀ»Ã¼Œzÿ€~‰¯†knÿ}xik—ª·ÿ·ÝÞÛÄÃÑïÿë™m ™­§ºÿ¤nBHs–—ÿ—––—Šˆrkÿo… š–…qÿJ$Ynž¶¸ÿ±­¶±«{ggÿT<,2@…Íêÿê×·¤µ§oTÿN`g{zu…¢ÿ•‚™¶½ª«ÐÿÉζŒ°ÞžOÿJBzŸª»ëÿÈ×ÝÈÄ¿›sÿkˆŠ•˜‚~}ÿ‰Œ…ƒ«¿Ã´ÿ±ÃàìÞÚ×Èÿ×΢…orzªÿ°ukuš£š–ÿЉ‰Š—‰s\ÿaz•ŠŠƒ†rÿ42ss‚¶¶ÿ¸µ´™[2LOÿ#(L{¸ÏÍÿÐÕ¿¸Í¤_Kÿb€˜ žš¡™÷˜ˆ¢Qp·ÄͶÿ¯¶ÃÍNv%ÿ,x§²­Â×ÍÿÅ×Ƚ°•sŒÿž˜iu•ˆ¡ÿ£—·ÄÏÍ´ÆÿÓåÓÕÈÄÄ×½c^s‰)ðÿ ¡–’‰xÿ‰ŠqY[kmsÿukaY97Rzûivçðs`?@ÿe@,g‚Ÿ°ÿºÃÏ×¶¸¶nÿLg„–™ §­ÿ«™¡——±ÍÍÿ¿ÈѼÄÙ¸„ÿqŠ•!$…·Ãÿ¢ªÚÖÆ¼Á¶ÿªž…¶½})Mÿnjjƒ •½Ä÷ÏÕ¾”@Ä××ÎÿÉÑ¿ÕÂkPÿn‘ƒ~…‰—žÿŠ{z{ˆŒzmÿa_Y\`OUJÿ,;nƒkooXÿX1&'!:Mk~sÿ€vWUek–ÿŸ•œ–…ƒs~ÿzƒzYpsy…ÿz‰–šŸ’ý‰‹€‹‰…{vkÿnrs_YmsXÿLg‘Ÿ¡¡µºÿ¬¤™n@LnaÿY_~™‰—–‹ß†¦×Äà â×ÿµ¤¤§£zYÿk™¡n^puxÿzƒœ¤Ÿ–—{ûss‡ „zgmkÿgD'F$@Ocÿy€–…sk[eÿs™¤›§•ž—ïvsvgž@bƒ ÿ˜ˆ˜™£Ÿž•û…‚×zsnjqývë@Yr„pgx£§<`¶§YÿFzoRJ`{‹ÿœ–¦¤˜¯×Éÿ´ÃÈÙÈ«°«ÿ£ž…qmnn…¿™kgrz|ð@œÿ£¤–†{scfÿuuaWYK)ÿ&ULFxˆŠ…ÿ‰nsvqn——ÿ™­£¡™–`XÿeY[H?Yx™÷Ÿ•›þ˜Šˆƒÿ{ukmj\crÿoRUfr‚ÿap‚— ¢°·ÿž«Å•a‘€Wÿb‚Ÿ•zo—–ÿˆ¡°¬£°Â×ÿ¸£¦Ÿ¡£’~þŠ ˜—xsqx…ÿ‰|x™£¡—ÿzs`Y`\TRÿM7.nnJÿzš~|€‰Œÿss—–Ÿ«™¤}g?qf[:@i>÷Šˆ–À€Œ…zzûzu#@irrcYÿak{–oPj„ÿ–’«µ±’œÝÿ°k—†ks’¸ß·—ˆ§·3PŠ—ÿªº¾¯°¶¤¤ÿ«§–ƒ‘–‰|ÿ…†s‚–ƒv…÷¤««Y°rWOWÿXYO97Ho›ÿšpOk{mbzÿ‚u{vs‰÷—¤œ.P\vŠqÿ\o|k—¤šƒÿ•Ÿ™–Š~}ïxzse»nNTÿr–|LBg•ýžŒPº««Ñ§kŠ‚ns‘¸ÕÿÄȾ²{—¯Ãÿ»¯½Â·¼µªÿ‘€‘›~|‘ÿƒ…’…{uŠŸþ´Ð•|_UZbYÿF@aƒ…–Š`ÿNSnn^r}kýi¼ƒ‘Œ¡ƒYÿpfXngTgnßjp«Í£Ê`¤—û‰…:ðqnfm|ÿxaLj–£—\ÿ9Y}§­¤¶ÎÿÙȷаngwÿ…–¡¶ØÞĵÿÍÚ¼‰p£½Â¿½¶¸¼º´)Њÿ—ˆ|ƒš—Šÿ¤£Šz…ž§ªÿ–…~jYYb>ÿ7W‰£šŒsWÿTmx€‚†­œß‰‚z–@r?ÿOOUH)=@$ÿ+f£–žª­ÿ¤¡ˆ‚ƒ{zqÿkmm|uMNzÿ¤¤~EFu’±ÿ¼µ°Å×οÐÿ®kFY–°«¤ÿ·¿¿ÈÄÉ´}ÿm­¾¾ºÃ¼·ÿ·´ÍÕäus÷‰Ÿ§ à¶°•‰ÿŸ¶°¢–›ˆnÿMOW;Lv™ÿ…mDM…—¤—÷•¡¶G°œ——«ÿµ—_!:^|[ÿ7B#T›ˆ|ÿ…­«’£žˆÿ…€og|umrÿ`@Xˆ™sFDÿj– ¤À°±¼ÿ¼·ÄÉ£i1#ÿjª§’§²±ÙÿȬ¼§ƒª¶¶û¾´{PÑÅÄÙ¯ïs›¤ «ºµû˜„¥°¯§œ‰rÿMD7Qz‚‚ƒÿbJ73an™«ÿ’ž¡¡§£•nþ†°Y`š|ÿkF>¯´Š~ÿ««š‰ˆ––ÿ‹pjƒŠpTÿFLu˜p1)Xÿƒ«§ªµ¤›«ÿ·«½¼•g?(ÿO…|{šœ¤½ÿȴͱ£­µÿ±¢—¯×ãÉÃÿѤ‚€–™¦±ÿ¶¸Éȱ——˜ÿª¯™…|ujU÷8W~Epk^O,ÿ Js‚•ˆ—þôÐmkngs_ÿIsƒzF Jÿ¼ªor‹§±ªÿ•……‰ŒŒzfþp U>YŠ‚TM÷pœš–PÃÇ–›ÿ½¼°›mTTiÿzzPTxš–—ÿ¶Ð¸›¦«´ý¸AÆÚÍ×Å’ísÓЭœ@Úħ÷§«¶ ŒŠ‰rïLk€{tÐsbKÿ$&DTpjgvýssЊkWp[ÿ+#O€‚A`ÿ¶zqz€€•…I=fsqgÒÀÿ£¡Œ˜Ñùùàÿïíݸ––¦¯ÿ¯ŠaL;((Mÿ}…vn¡Ãÿÿж§¯zksxÿƒkF73@e?'.3E!)`0ï–ÄÍ£Ë ­¯ºÿ¯¡ˆ–_,Qÿg‚‘¶¬€˜ÿµ×Ù¿ÈÚç±ÿ†¡£•¡«±±û«¡VଉxrYÿ1)Mc`zˆÿg:D^gqjbÿs…‘mSq´òÿ÷×ãøãµ›~ÿz…•kLY[>ÿ:`†`\ÃÿºÃÞµ¼¿ƒÿ}qsn_SaIÿL .o€ÿ$@n­¸äðøÿâÕ¿´ÃÍ´‰ÿv—v Yˆª‰~ŠnYs«@¿œ™«§…wÀ¤ÿ¸·ª£«¡™­û™–àsiTMgÿp[9$RjsÿMBs…v`Lbÿ‰··ž¿óè·ÿ™†aXO@Akÿ\FOpˆxkzÿ¢¿ÃÄ×™« ÿ@|JM_k…ÿ•oLf7^ÿz;kx’°­ÃÿêàçòѤ·Àÿ¸Š€–jmÿxn:2Ys^fÿkYU`L@Yuÿz{€…£µºÿ°¯¸±£¤¯¯ÿ–…º¿ƒcg\ÿNEB,$.,,ÿ;Nm{u{—Šÿnz––½Ïªsÿj…Œc8!LrÿPFOk|||žÿ­ºÃö¢«sÿMk7Mks ÿ –so:ÿ(R…°´·µÕÿçÑã÷Й£°ÿ¯§¢}`&"sÿ[3 %_ƒujÿMET^=.I[ÿ|£Š`Ri±ÿÄϺ°±·´¸ÿ¤ºÈ£ƒ‘vÿLOmsY $ÿI@&Lns•ŒÿOFg|«¬Q@ÿj‚–u@9WYÿe^.4nx~£ÿ«¬½²ž‰z3ÿ+LZ~ž–£ÿŠ€k|Xÿ:|¯¸·ÄÄÿÄ¿ÄÞÆ¸­¬ý«Jp%$|mNÿLY‰‘|usÿ–okss£ºÿ‹cWWs–¾Õÿ´·¿·µ·­¡ÿ£µ¤‰…kgÿg‰|)3:!ÿ!.7Wm`MÿA1Yg%!ToÿsT8Qkisÿ1%Orz…¡ ÿ¶¤ŠjL29Bÿm•š° ™š‰ÿvmjp4ÿO­–ž—¤ªû£¤¨À¬„kkxÿ~.,†kigrÿ‰‹œ«£ —›ÿž–œ¡ªzÿŒ‘—…¯ÍÀÐ璘±``µ«‚ÿs{„{x’aÿLYFQU9 ÿ@zsF+IMÿ.4IISN+2ÿcƒxgE;O_ÿ|¤«€M9ÿHv~Z€¤•¯ÿ·¡¤–rzz‚ÿn)`–‰ÿnzœ­‚}|zÿ ™oWr•—!ÿ>‚pgpk|•ÿ¶¤—’‚•~ÿx˜ž£—­±ÿ°«»»¾ÖÑ«û£¶¿¶­’nsÿƒ––¢¬žeÿY~¡~T% %ÿgsYO‚Œ~zÿiLTgW-@nÿpZ[^LNxoÿq–{HMk—û‰k„§«­«oÿv„…¢[ÿ.`™¤•¦°¸ý¤§¬‰sqˆÿ‹$9|€nskÿsœ²—}…‰ŸŠsg‚Œ–¿Ðÿ¼ÏØ¿´ÛäÄÿ·¸º¯¯µµ¡ÿ…ˆ‘›¤•ƒ¼ÿÍza€­««Šÿ[OnrY`šµÿ¡‰€rs—‹gLau|‰}O¦PÿrŒŒr4Nzƒÿnrzr~›±ÿ—i{ gniïMv2 Ü¿×ýâ)б¶µƒLbÿ…B>psk|}ÿzŠ¢™™¯£ÿ—‚s~•ˆƒ˜ÿÃÍ×àíÄÃÙÿîìÏú¸ÃÄÿ½¤™žš–¡Šÿ}ŸÃ¡g‚··ÿ§žŸ™raJ7ÿp£œŠ…€…™ÿ•u[^…œ˜ß\M_ané0TBÿzve…|‚™ÿ¡¢sp–Œ«ÿp…X;RŠˆÏÄ×ݵ—%Àï†T:Mkkÿs…z—ž£ž¬ÿµ™—…sjimÿ~}ºÄÆÓíãÿÈÈìôÙ¸´¼ÿº¿·¤£ž‘—ÿ……¤Í¬orÿŸ¯§ž« osÿX3Z•˜£ýž  e~z|•ÿfOc^Jv‚™ÿwY‚ksŠ¡•ÿ¢±·žnz‰…ÿµ«…€YT)ÿPi{ž«¤¤ÿzrnmkWbgÿ\j……incrÿ—£§«Š™¡ƒß…|jnU`PÃÑÿÃÜãÛ´¯ÍÝÿɵ¶¯°·°Ÿÿœ–—™£Šœ¸ÿÈ´™~sv…«ÿº¡Ÿ¤€kk~ÿ‰—’™Šƒr~ÿznnpk€mpÿ|s(bzo|nÿ~q‘—‰\Q…»°‘`|¡§€sÿygE,`szoÿƒ…nz`N‚ˆÿ—–moš€u…ÿcg¬™ps…¡ÿ§ƒ{ƒ‰€jÿNYºÙÈ÷ê²ÿ–­×ãֿüÿº·§—•š—Ÿÿ£ž¤¶À¼¶§ÿ•sfnsЏ¸û™ŸLð…‚ŒzÿTWUp{…naÿn~¤~:`~jÿ|ˆu|oe,ÿ2a‚vrz{aÿs…s`J7Q~ÿN @‰•znïpgYnŒ`€ŠŸÿ¯–z‚qŠ€ÿLNˆÈÉœzˆÿ–—–qk°ÕÿâìÁ~ƒªÚöÿë×ÄÕã¿–™ÿ£–ˆ•ž™«­ÿ¶Ä·º½¡^4ÿ$R½Ýº¤Ÿ™ÿ§™€‰ƒsmbÿL{£œqMc|ÿ™sT…€iq`ÿLP,$:n`ÿTo|re^gŒÿŠgkJ)KBÿ#y§ŠcE4@ÿ[™§}`egvÿ{pUzœuZsÿ~½ÞÙ°…’ÿ«¡‰–Ÿ¶½ÈÿŲ¶–sqŸÉÿÄ´·È°zfrÿsgmŠ–—£ÿºÎïž…oYÿ$1šâµ¤¸ºÿ·¬›–€…žƒÿY|¶Ÿ`DkŒý˜ép}aU4-3ÿ3..+Q1'cÿsoaŒ~ƒg\ÿnrEFLSÿ|šg) "7oÿ…zc;SbTXÿQpƒrN`£Îÿç×»¯«¶°°ÿª§¤ÉÍ··¶ÿÛµb,Yžÿ–…S.1NPJÿgz…–žºÃÿ sg™¡S3ÿ\‰Š™µµ«ÿœ‰ƒ}™™}„ÿŸ‚LMsž¤‹ÿ]qzivwbYÿoŒQ)@ÿz‚‰¯…fEW¾ s3(êp?ÿ 3=ngLÿJe[mmj[kÿkn¦ÉÄ»¼Äÿ×ɯ¤±­¯×ÿ¿±«°Û«YSÿpv}Š…kB2ÿXfgg†‰~ÿƒ™³º™}ƒœÿ¸·g@N[x™ßƒ…—ú  ªÿž‚ovUauœÿ­«vgqk~£ÿ™|zj‰|: ÿ)[y¡­°ŠnÿXv›nookWÿ$N€˜XT¿XYp]N$Ï0€ÿsULr–—¡µÿ±½ÉëöÕ¶´ÿ¯««Ã×ë£ÿ¤sW¯†€…ßyWTz¡Äp«•ÿƒ€Š¤¸¼¬ÿ~‰f[en{ÿ Î¯€zs–Ÿ­¸ª«œÛçð~˜~wƒz‰A ÿ€@a‘eLzÿœ¤¯ ‰zo‘ÿ¤‚zn™­kFÿa‚XOorþ]°E)Xsb!ïLƒˆ˜?ðÈììÿÉ×ÝΤ•£¸ÿ׿°¶ |u…ÿ’€{zYFsžÿª±¸ª˜{p~ÿ£¤’sb\BJÿEHs}w£°ºÿ°™™ygбÈÿ¬­¤‚xŠž—ÿov—­­Äºû¦´× 9nšk4ëa‚¾„– ž½¡ÿ—¤·­–vrÿs`FkeYÿ\9%F^`7ÿeŠzžÆÓÙ×ÿã¿±ÍÆ¯œœÿªº¸£…¬§uý\§0|oEZ•£ÿ¤™|Œž‚…ÿ‚_E7L^Rauu‰z| ¤¦°ÿ¤Š`^…º°µÿ™£‰~ˆ¡€ÿ˜£»×ÈϰÑÿÅ­xaž¯|aÿœ‘ƒ‚›«þÙàr€­±¶³ÿ‚fŒ€,(ÿ#.((HRTMÿLHjƒŒ¦ÉÙýÚm í×£•££ÿµÃ°ž‚£«pÿFs–zYE‰ÿ°Ÿžµº~Œ¶ÿ­—a)7o†‘ÿ•ž••˜‰£ÿ´¬•«´€:ÿb°°±•›zZÿr—•ž½ºÍÙÿÈÀª·´«˜ÿ¶Ä …•ž¤‘ÿ‚{‰¤¶°Ÿÿ‚°ÃºŸooÿ™ B #EÿTkua) ÿ7q…«Í¾£˜Š£Í㸫£?Ðÿ¼«€ƒ˜gE[ÿrZEBe®Ñºÿµ¼Ä–y¯­†ÿ^`uŠŒ—Š™¿œ‚™¶¿PŠþP[:{œ­}jÿF7R¬µ¬°ÿ·ºÉÁ£¡·¯ÿŒy§Ã£™Œzÿ‚…€|•«¸¤ÿ±š ¢«¸«|ÿvˆzM#,LJÿk€ŠyQÿ%EsspßgœÄ›—*¬‰ÿ«½§ˆagzQÿD>$ 9bžÆÿÄÍø±žŒ£ÿ ~g‘|ku¿€~guŒM£ÿž™žºÜ…)Nÿsz[MBRq–ÿ¾«–ž¯´´·ÿ£´§‚z™¯ÿž—ƒmsƒ{’ÿ„–ºµ«›£ÿ¯«[|ŒHÿK ¶sanjoÿ‚g2%$3@.¿2A8:FsÕpŠÿ—¶º—¯«soïka^,Ì0Y€¦ÿÄÃ×àÞÚëÿ§ž€ƒxjuÿrzˆ}s}– ¿¢Ÿ«·ŸžFЙÿnib1>Ok‚ÿ«µ°œ…™·ÏÿϯŸ•¢¯gï€{zPz•–ÿ|‰¤«¡|ÿ ‚ogwp7Aÿ…¼£gnXToÿyjpƒ•¿Ãˆÿ‚’{€€œu}ÿ­›…«…z·­ÿsu~rR 4û£Ñ¼¼ÜäÍÿм­Œ‚‚s¿n~Œ–¡¤ŽÐ¡ÿ˜™º«€¤¸«ÿ‘˜—‹eEeÿs™·¬•—{ÿ±áů¯—˜±ÿ§oxsengZÿku—ž™£™ÿ ž¡•…~™…ÿnQLv™‚vgÿosx™pTg«ÿ ÐФÕñ½±ÿª«‚oŸ£ «ÿwZ™¬Œ‰Š|ÿkB9ržŒ€œÿµµ™¸Ã·Ï­ÿojƒjm{ÿ™—¶¸«zr ÿ•›·ª†£µ¯÷—£dPr‚—žÿ¯£‘ziŠÅÝ¿Ùð·À«Ðsƒÿ|kLe–…zŠÿ¤™—™¡·saÊP­…uÐÿš‚g‚¢ª®ÿ®…âõȼŠÿ›—£vTK7;ÿjqHJQTcaÿ`‚•{…›£§ÿ ¤´´Ã™Zmÿˆrazœ§™Ÿÿ«›Švs•£¯ÿ¯™«•«°«ÿª¡™›ž¯œŠÿ«­••i?jŸÿÄɸ´´¸vÿq‚Ÿ«|WEOÿ‚Hnƒ•ž­°ÿƒ^[rOev–ÿ¤¶¤šgXo‚ÿƒqr£³°¿¿ÿ³zµÉ™ÃÀÿzŠ`@K@ÿ@gjHIRXOÿMx–zu|›¡ÿ’¯º§«oX…ï‰k`vZ`¢œzÿ[Yr›«™›ÿŸ°¡¯Ã±­¸ÿºÀÿ’|…¡ÿª£q-`Œ¾×ûŸ½`ƒƒ¡°§ÿxbR.F1qÿ Š ŒgXTST}–Œž¯¡p`ß…‚o‚¤<นÿ‚s—°¯¶¼ÿ£—…™·¶WÿY¸ã¶£™Uÿ@rœž•‘¸¸ÿ¤¸Äµ¢ja‰ÿŠsir… ­¬ÿ™XDg|sŒ–ÿž§«¤«½µý«:pÜ®…‰{ƒÿœ­€kj{œ°û¸°!ÿ%Uk~„…xnÿsxvŒ¤¤•Šÿ¤×·°ÍÃÐñÿøñÜõôä¯xÿkƒª«‘£¤·ÿÄ·¢§«»ÞúÿüíÄ}EmZTÿTTqsWWkŒÿ·¸§¡«°%ÿ8§Ýîªf…µÿ½ìè¦cz’vm[WkzŠœ+ ß¤sp˜Ÿíе¶ÿ¶±¡}TQ€™ÿžŒiRg…­¤ÿŸŒgE7B_xÿ—†p\[rŒÿ£–€•´¿½¼ÿÉÐÕÄÜÝÛßÿä·|_Ff‘°ÿ¤§¦ÉÖׯÁÿªÀìäù׋Rÿ>fUF[ksxÿgew£·µŸ™ÿ«ÃÁS.]ƒòÿìs}¦Äòì¿ÿ{{ª…jMMbÿ™µ‚z|¡…MÿFbg…›ž²§¿¡’–ŒŒŠžðWÿ-k«¸·µ½Íÿ±§zONg|zÿ…€eL`npr·¤¼ðÐëæÿëâãÝÕBLÿTrr~ž´É×ÿ×¼¬£…‹£ÿ×Ï¡znS+ÿ:m|s|xˆ£ý«÷PªÉÍ—xjÿWØþº§¶Ñìÿ辊s« rUÿ_a€£…rpoÿn>@MWq€’üuð«À£¯_9ÿ@…Õį«ªÃÿ×°…_Tmkvÿ‚‚mRWUgsÿ…£™£¶¤«¿ÿÐëõïÜëÄ`ÿ:`x‚zv£¤ï°´¾×äÐmZ{ÿ»×ª€qX1ÿ1_€—sˆ•‘ÿŠžª°¯º«£ÿ§–i‹ò屯±´«xFM…z ÿzkYYXNgsÿWLrrusj}ÿŸ¢£«Ä¼§£ÿšjFNƒ·Ã¸ÿ¿ÍÏ×ɰž{ÿxsuskfÿ`iqmvœ«ªÿ§—¯¯¸×ëÚÿ¿¼‰9S‰„qßuo|…˜“çá¿Áœª¯†öÀUßRMJTkÅð‚sÿŸ¡¶¸¯«¤§ÿ­µžz¤ÑŸšÿ…X=j‰ÿxzqT1)F\ÿps`k~u‘±ÿ¢‚…™§¯µÀÿ±«˜`.?–¸ÿ°¶¸ÄÜÜÑÎÿ´s‰’‚€ÿ†{\Uirv‰ÿ¢£‚‚™™Ãÿ¶Œ§«LLfÿYOq„ƒ£«ÿu§Éòدª«ÿ¡`j~]Darÿp`T_rƒ{ÿµ°¯¸È¸¯·ÿ¬×Õk™¶‚ÿ,  7Es‚ÿ’}}z\=BMÿOe`MTaq˜žˆ{‘ª¬¯€Àÿ‰Q(JŒª´¿ÿµ¼ÃÄÀ¿¸ÿs€£ –™—ÿrXs— •‘’ûsjÝ¢…Kkvÿ!3uukbq•ÿ•¡sk–¯Ãÿµ™«z—…zkÿJJs€•–aÿ^f~—°¤±ÿݽ´£¬·‘ÿLJ¶g,kÿ˜‚n{ƒs‚…ÿa$!@|Œàûo˜ÿÀšˆ¡«{ÿ\pˆ•—ƒ¤£ß{£Í×Ýæ@ÑãÿçוRe¯Ñ°ÿª¬£•–™¡¸ÿø¢€‚š ÿ¤±´¶™¤«‰ÿŒºÙÄÀ¸«¡ÿ¤Œ{  L ÿ, @xH+ÿs‰s€¢…zÿv…rJBr€ÿsju˜‰zx‘ÿof€~r…ŸŠÿŸ§ŸpLU{£ý¯Šp««ŸµŸÿ~€jOY‰‰œÿ–s¡È«±É¸ÿ¯¸ÃÙ×ÉÙ×߯sr«ºÓÀ«¡ß§¬«­µˆ ~œÿœœŸ­º¬~¡ÿ±~x¯¿º¸µÿ±§«¯z_¡¤ÿ9!g¡ÿYD{€maz–ÿsr€Ÿ’xFFÿv€xzzŒœ€ÿi`p~propÿDATEÿ7-06-2005, 9:13ý‘÷NAM¡swe{etý‘ORIG Ý $¢.bm¡A÷NB¡BMNT  ^ ( Y¤×N¢ð ë Ðn£q w¢N¡ÿ ™Ç3̉ †¡‚¢3Ìþƒ ÿ²²²ÿÿÿwww«£ïwrª¨Qþª£q"@0>­¤!4Cª¢² ßqFR @®¤eçB$ª¡² VCy&Ï¢ú¡˜FcÜ¡>â¡YVB0é ² ?wU˜eC$Ü ±u…FÏ ±°ï1fC5³qYƒgVBP5³!±3'M´î.°3 N³w•÷f´qUr=Wf´wwpM´„±Ô(±ý˜  8 ¤19÷:59©wateqr)©À²:¦€6Þ±¯BM6€M£6U¤€œN¡M N£é° ÂÏ%Ï7ÏIÏû²ÿ ÿÿ  ÿ# ( +ÿ - 47ÿ<CÿGM!Q$ÿR$S%OÿO!OÿNU#S!ÿX&V%Wß&Q »ÀLÿFKCÿ JGÿB C < ÿ<> @ÿ BFÿBE=ÿ9 3 .ÿ + , ÿ+ * *ÿ % $ ÿ   d `ÁM¤0ßBßTßfßxßþŠÞÂJ9¸@/µÿ>-°8'»C2ÿÅL;ÏWF×^ïMÔZI±ÐÎUDÿÃI8¿D3ÁGÿ6ÌRAÉP?ÐÿWFÄK:½D3þ«ÐÅM<ÈO?ÄßK;ÇN=ÏÐÊRÿAÈP?ÄM;ÀÿI7ÁJ9¿H7ÿ½F5¿H6»Dÿ3ÃL:ÅN=ÈÿP>ÈQ?ÃL9ÿÃK9ÀI5ÌUÿBÍVDÊTAÇÿQ>¸B.±;(ÿµ>+´?+µ@ÿ,¼G4½G5´ÿ?,±>+­:&ÿ­9(¬8'²?ÿ/³@0±?/¹ÿH7±A1¬;+ÿ¨7(y)Š2ÿ#˜9,«?.ªÿ>.¤9(ž3#ÿ2"›0 ¦;ÿ+©=,·I9¾ÿP?¿P?¼K:ÿ³A0´C1®;*¼I8½K;Œàÿ±>-«9(³@ÿ.³@/¿L;ÁÿM<ÂO?ÍYJÿÇSDÀL<³?ÿ/·C3°<,¶ßB2¼H8¹à½Iû9´NàE5»F6ÿ¶A1½G7¸Cý2Ýà³>-½G6ÿÂL;ÇQ@ÍWùFæàÚà²<+¼Fÿ5ÈR@¶@.ÀÿI8®8'¢+ÿ¬4#²:)½Eÿ4ÇO>ÐXG·ûA0ð°:)¸Bÿ1¸A0ºC2ßL;ÀH7¨Ð1ð¾þüàP?ËSB¿Gÿ6ºB1®7&¬ÿ6%«5$»E4ßµ?.¶?ñµ?û-Ç>ðTCÍVEÿÒ\KÑ\JÈSûAÂîÐL:¾J8ÿÃO<ÅQ>ÁMþxð7ºG4¿L:ÿÄQ?ËWDÀMÿ:¼I6¸E2±ÿ@-·F3ºJ6ÿµF2´D2¶Fÿ5®>,¯?.±ÿC1­A/ª=,ÿ®C2¬A0§=ÿ-©?/4#œÿ3"š2!¡:)ÿ¦?/¦>.1ÿ$‹4&6)«ÿE5¶P@¯H9ÿ®H8­G76ÿ'¨A2¬E5­¿C4·M=´ÆàGÿ6¶H7¯@/­_<+µF4¬ð¾«àûQ@†à½L:ÀNÿ>¿M<µC3¸ÿE5«8(«7(ÿ¶B3½I:ÌXÿI¿K<¿L<°ÿ=-´A1ÅRBÿºG7ÀM=·DÏ4©5%Âà¹ãÊVýFËà¿K;µB2÷²?.Ñàª7&¯ÿ<+¥2"§4#þ¹à¨4#°<+±ÿ<,«6%´?.ÿ°;*¬7&ª5ÿ$¬>.ª<,¦ÿ7'¢4#µF5ÿ¸I9²C2¼M<¬<+«;*·÷­=,½´D3µ÷E4±ðG6³Dÿ3¶G6­>-¬ÿ=,§8'¤5$ϯ@0°ð“àN=÷ºJ9ä°A/±¿B0±B/³¶ð>ÿ+¨8%¨8&©ÿ:(¦7$ª;(ÿ¬>+§9&¦9ÿ&¥8$¢6"¨ÿ<)¬A-±E2ï©?,¢<)Ÿÿ5$¢:(­E3ÿ¬E4¦@.¢<ÿ+›8&“/šû7%GŽ+”2ÿ!Ž+™7&rÿ$})•=/ÿ©I9¨H7§Fÿ6™6'“1!›ÿ9*œ9)Ÿ;,ïœ7&Ÿx7%šÿ1! 6%£8'ý¬ ÐI7µH8´ßF5±B1ð0³ÿE4´G5ÁRAÿ¸I7£4$®?÷0¯?Ë8ÈXIÿ»K<ª:+²BþÅ5¹I:¹I9ÿ©9)¤4%£3ÿ#¥5%®>-®÷=-° =-«;÷+°Aþ-³D4ÿ´F6¥7'±Dÿ4»N>ÁTDÄÿWG¿RB·J:ÿ©<,ª=-¤6ÿ&¨;+­?/˜ß3$, ™4ÿ%š6'Ÿ9*¦ÿ@1¢<,­F7ï£<,ž @0ÿ'–-¢9*§>/°H8±ÏÿA1Ÿ7'ž5%œ4%›3# 1÷D3ªTàB2®Eÿ4¥;*©>.¢ÿ7&¡7%¢6$ÿ¦:(³H6³Gÿ5¶K8·N:±þƒ I7®E2¦>ÿ,£;(ž6$ÿ6$œ5#¡;'ÿ¢<)ªE0¯Jÿ7°J8¹TA±ÿL9®I7§C1ÿ¦@/¥B/˜4ÿ&š6(’0 •ÿ3%˜4$Ž,ÿ-z(ƒ-ÿ‰0 0“û2"Í ’/”1!š6&–1$Ê ÿŸ9,•-£;ý*Äð¥;)«@-¿¬A/²F50¿ÿRA¾P@ºL;¿¹M:²E3… ­ÿB1¿SC¾RCÿ¼PA¸L=«@ÿ0§;,¢6'ªÿ?0¨<-¯C4îH0¤8)H0¶J:ÿ·K;¸L<±Eï5©=-hà¦:*ÿ§<,¤:*¨?í/R!8(u0(ÿ‰#‡"Ž)ÿ*+ÿ(‡"’-þ •0!’9.›ÿB7©QC•0²M?·RDÿ´OA«F8©Eÿ7œ8*©E6£û?0( 9*›7ÿ(¦B3³O@³ÿOA¬H9¦B4ÿ—4& >0™8ÿ*¨H:»\N­ÿOA®PBž@2w†*P„(½0ÿ˜>0˜=/Ž4ÿ(–=1‚.!ÿ- ‰7*1ÿ1™C6:,˜ÿA3’:+Œ3$ÿ3%3$Œ1ÿ"ˆ-Š/Šÿ-‘4$—9(ÿ›<+¤E5¢Cÿ2>.?.›ÿ=,?/¡D3ÿš=-3#1ï •:)£P–:*¿—<+Œ1!¯Pÿ5%ˆ.†,÷5#¾P3"ˆÿ.%‰/¿‡-2"¾P†ß+ˆ2#â 4ÿ$–7%,‘ÿ/!“1"”1$ÿŸ<*˜4"—1ÿ )(û4"2Ÿ4#Ÿ5ÿ#—,›1 ¢÷8'©–@B1§=,¦>-= L îð¨ÿB3Ÿ:+‘-ÿŸ=.¥C5©Hÿ:©J<˜9+ÿ0#€!„&ÿ…'•7)›=ÿ/Š,!1&ˆÿ*Š,"?1÷¢D6P©K=¥ÿG9žA3£G9÷—<.jPŒ3%‰ÿ0"ˆ/"Ž6)ý”¦0D6“=/–ßA49,P¤Eÿ7ž@3œ?1›ÿ?1•9+4'ÿ‹1$woÿ w‚)™ÿ?1—=/‰/!¿‰/"&Æ`Œ÷1$¬`0#2ÿ%’6)‹0!“öÄ1,Š…`3&‰.ÿ!ˆ-Ž3$ŠÓ0 mP´0‡<@1#ÿŒ2$’8)•;ÿ+•<,6'ÿ7)Ž6(…. ÿ†0,})ÿx%z'wÿ$r}+ÿ|)+ƒ2ï"-2pz(ÿv"z(~*ÿ‚.)|ÿ&|%})ÿ‘9(œC2¤Fÿ4ŸA/˜8&˜ï6%›9p$:ÿ,¡>/:+ªûC1;¢:)°Iï7±H7`°F4÷£9&Œª?-°óD2*00´H7²ÿI8¶L=¨?1ÿ¤<.™2$Š%Û‘;P+ëP”3ÿ&—7)‘1#Žÿ. Œ,‰)ÿ-/!œ<ÿ.Ÿ>0š8*£óA3ì@ì@œ:+–ÿ3%š8)“1#ï—5'˜R`:+ö´p9*€¤D5¯ÿO@¸XI®OAç§H:ì@tš9*ÿ¢A3›;,–7ÿ(”5&.†ß'“4&7€>ù0?`œ`£D6 A3‘2$0#7€¿Š+=.ÈpŒÿ-0"~ÿ}zzÿ|!‚'‰ÿ-†+‰/ÿƒ*„+†.ÿ‰4$9*“ÿ?/”@1;+ÿ†4%‚1"~.ÿ~/ 3$yÿ-}1#z/!ÿs)v,z0ÿ!x. w-ÿ8)x.t*ÿ4&s)s(ÿw+glÿ feÿx+u&‡5ÿ%‹8(…1!…ÿ0 ˆ2!*¿Ž5$‘8'ÄP”ÿ8(Ž2!“5$œ<,œ;* î0ã7&}00¦=,}¯<;*¥9(›pŸ3"¥:*¡Õ@ý2 `'5%¦?ÿ0£<.¥@1©ÿD6£>0 <-ÿ¤@1‘. +ÿ”0#‘.!¤sA2Î@0`–1"iÿ)›6'›5ÿ&”.œ7(œ¼±@{8)œ9.9+ <.– ÿ-‘/ ™7)þûp–4&’é04@5`/æpŸ<.ÿ£@2›8*š7ÿ(-•1"þ`0"›6(˜3ÿ%8*—2$šöíp7)Òž:+“×0"“Ãp0ê !˜ÿ6'’2#“2#ë’3äP(©P”9)ÿ7'Ž5'‡1ÿ!†1!‚.ˆÿ4%‰6(ƒ1!ÿ„3$v&v'ï}0!¦€~4%ÿ5'}5&}3ÿ%8)|4&kÿ%n)f"ÿg"h"j"ÿl$q)ÿ5(‚8*‚<-÷:+8 ƒ8)~ß3$z/ ¦€v(ÿ{-x){ÿ*/x%ÿx"~'|%ï†- pœ?/ÿ£D5¥D4¡=Ÿ-¢>-ž£”Cþ(.ª@/ž2#ÿš-œ0!ª=ÿ.±D5´G8·ÿK<Ÿ4)–,!ÿ—.#“+¢:ß+³L=£ë05'þ³@˜1#§@2¯ÿH:¤=/¡:,üé + ©C4±J<î. ¤>/Ø‘,ÿ”0!*’. ,*«þï@Ÿ;-«G9§C5£?1N×@{þ+ ¢<-’+˜ÿ1"˜0!•,þª@&˜/#šÿ2&¥>1µM>ÿ¬D6­G9¥?ÿ0¡<.ž8*¡û;-Õ’-“0 Ž+š8(ó0ÿœ9+š;+Š-ý y€‡,†-w’7' p‘9*dP’;,‰3%Žöpÿ?/ˆ5$‚/þ5p|*z&yþ‡ *mv&ÿu%u#|ÿ,v&t$÷s%ʰz,zÿ-p#dÿddy+ÿ2#{/ Šÿ=.Ž?1†7(ÿŠ<,€/y)½} ƒ0"‚Ïp6ç)’<­4ð`$ÿƒ$‡%ˆ&ÿ“-›3$›ÿ1"3$š. û£6Ý&©9*¬»;,¬=.6À¡÷4%¢FÀ5& 5ï&š/!*À˜/ ï¥<.§Ò@2$™¿2#‹%‘q°4ÿ&§A3¦A3¥ûA2z(š5'žÿ9+¬G9 ;-œ‡ÀxÀ›7)%°° ÿ9+¢;-¥>/ÿŸ7(¥=-œ3û#ž& 0 ¡7(ÿ¢7(¡6&¬@ÿ1«?0¸M>Çÿ\MÆ\N½TE÷²I:°@”,Žß&)‡0•/ý!Ó0!9,Ý •P>0žï°. ûŽ/Ùr>/¤F7ÿžA1¡D4“7û&”Œ°9(‘7&ÿ“9(•:*œAÿ1£H8§M<žÿC3 G5™@/5$6%ˆÎPû.ú€—>,™?ÿ.£K9—?-”ÿ=+‹4"w!ÿ{#s sŸƒ0…žP ?ÿ.Š5%;+ß8)‰5&8p‚,ÿŠ4&‰5%Žÿ9*ƒ.*ÿ~)*z'ÿz&€+ƒï,„)¼1‰+Ž/ ›8'˜_ ÿ9) 7'Ÿ5%r·À¥ó šÀ3%£/°ÿ4%¥:+­B4¿¨?0¤;,ÑЪÿB3«B3±J;¿²K<¬E6¶@¥Ã?1% ×@NxÀ®Jý<Î@°K=©D5Ý/°8* , ?0­E7ãУ Á;4HÀǪ>/ºÀNÀN0Ÿ3ÿ$­A2¶K;¾ÿSC¼QA°F7ÿ·N?¬D4³Kù/I «C4©óA2`À°@–.‘÷)š4ò³M=¹ÿSC°J;°K<ÿ¨C4£>/›5ý'ØŸ8)¦>/ÿ´K=¾TF³Iÿ:°E6±E6©û=.“óÈUE¹Gý7l®<,²A2ï´D5©~p<,§ë:+0’&-ÀŸ6&kš2Æà!~ð™4ù Ã'¨d)°ÒÐsðC4í¬®pI:ÿÀ’5%ÿƒ%Š,2ý#Ñ7&’4"•û6% ¦D4¢?þŒ'’.)ÿ–0›4#©Aÿ/¨@-«B.¨ÿ?,£9'ª@-ª?,§<(§ 0ÿ?+µH5»P;þ8µH4±E0¬ÿ?+¸J7´H2ÿ°B-ºN8±C.³D0´H4ÿ®C.¯C/±E¿1ÁTAÃW/0=ÿ½Q=±G2­D1¬D3§@.@  @DkA*@7A”ý1›&ž<, >ã.žƒPЫ F6¦ûB1¬à¥@0£=ù-7 ¤ £<+¨A¿0²K:«C– -þ¤C¹O>ÄYH½ïSB¸Nv7¢8ñ)ÑЮÀ9¥;,¥ß:,©>/ ¶Iÿ:¼N?ÃTE³ÿD5¶F6·G7ÿ½K;ÊWGÒ_ÿOÅQ@ÄP?ÃÿO>ÀM<ÅRAÏ¿M=±@8 /¿›. 5$‰ ß7&§@/¤ ž8ß'8(•³P,ý‹WA”4$›=ï- B1…P™;,ÿ•7'”6&‘3úõð%P–8&•6þäP&=+¢@/ÿ¤B1­I7¤?ý.Á  9'š3!ÿ•.™1¤<ÿ*©@-¸P<¸ÿP=ÀWDÀVDÿ²H4´J6¨=ï+Ÿ4 ›p¦9'ߥ:%®A³ð%¦ÿ7#§9%£6"ÿ°C-³G3®DÝ/w¡8#»¤;þô'°F2²H5ÿ°H5´L9²Jû7¦¨@8'“/íŽþP,n@™5%Üî “’.qp¦Cÿ1¨D3­I8¨ÿC3¥>-§?.ÿ¤<+´L:¿VÿDÍcQÇ[IÃûXE!0¯A.·Iÿ5´F2»L9½ÿN:ÈYEÄT@ÿÀP<¿N;«9ÿ&°?,±?-¹ÿG5ºH7»I9ÿ´B2©7'¤2ÿ! .«8'®ÿ<+ºG7ÃP@ï¼J9¹D3²ß?.½J9#ÿ˜+¡4$²E5½PA½QmÿH®C3³J9°ÿH7¯G6°I8¿§A0•0#–•ÿ2%Ž,š9(÷—6& ¤D3¤÷C2§çB2š9ß)¢B0›G=+ÿ©H6 ?-¢Aÿ/¥A/8'¡æƒ=+I2&¢;ÿ(¦?,Ÿ7$£ÿ:'Ÿ6#›3œ4!¢:'¤0ÿ>+¯G2¯F2÷¬C/Ô>, 7ý$)1E1«A.°ÿE0©=(­@+þÊ9$©<'«>ÿ+£8%¨=)¥û;( µK7³Iÿ4¾UAµL9±þòG3¢9&ž6ý$¾à¢;)¥>+ÿ¤=*”-—/”-6$ƒ0÷£;(ô­F3¯ûF3w§<)¨;ÿ(²E3³E3½ÿN<ÇXEÆVBÿÐ_KÔbNÑ^ÿJÆS?ÄP=´ÿ@,°;'´>*ÿ®8%ÃM9Ô]ÿI×`MÖ^KÇÿP=¹B/®8&ÿ¥0§2!¦3ï"¨5$Š µD3ÿ¸G7ºK:´Eÿ5·H8³E4»ÿM=®A1¥8(ÿž1!ªD5ž9þÔ#‹&…ÿ„Š$”.œ5%§@0Èÿ³L;³M;±L·:©Dx°(¹P$ÛŠ]p0­J9«I9«H7ú§Ð¡’P8' :)þÀ œ5$¥=+¥=,¢:(¦=@ý/D0³I6·K7ÿ©?,¨>)œ3ÿž6!œ4 û4!¾à£;)¬Eü- ¨B/ :'þ¸ã§A.­H4§ó?-¦@ @œ2ž4"§?*©?@1î)¢8$;0¢7$¿ª?+­D0B.…@ªB.£ªßA.ªC0P§>ú `+¾à¨A/¦>ý,€p­F2©A-þ…@­E0°E2­ÿA-´G2¶G3ÿ­=(¸G3²Bÿ-·F1ÃR=ÃÿP:ÌYEÓ_JÿÑ]HÔ`KÆQÿ<ÊVAÂN9¾ûJ5QPÄP<Ð\ÿHÌYDÎ[GÁ{O;Z ·H5©®0¿D2œ/¨¨7»'™%À0 jÀ(ß–-™Çñ(¨îÐ<-‘°.Šƒ)œPõpzpõÐrð¢ÿ;+ž6%ªB0~@®G5´M;Pw¨B0p@–1ü!ÿ<*£>,²M=Ÿ¤>- :Ĥñ=qP P©?-§ï=*¥:íG3³¿G4´H6­øà9.¼ð ¡8¿ð# 0ÿ¡;(¤>+8ÿ%›7$œ8%˜ÿ4"˜3"š9&ÿ•3 ,Ž,ÿ/“0™ÿ5#É”‰ ;(û£=Ç/®F4¨ß@.¢:�£;¹'ùP£¨>+,>ï+µK8¤0ž5#ÿš1‘(&Œ&$À°{PþP¬D1­E2±ÿH4ª@,©@+ÿ3¡4 °Cÿ.µG3ÂT?ÂÿS=¾P:·H2÷²B,¿`ÄT>ÊÿZEÒbMÄU?ÿ±B,«='¬=ÿ'µG1µF1½¿O:ÙŸ”¨c`<æÄÐ!£ 0™pA0®ßE4ªB1=@¨Có2žÐ q0 –3ù#Õðq=.œ;+ó”9qy€žC5¤ÿI:¤H9®QBÿœ=.•4%–4U$O™DèÐ-CÎý˜1 * · ¸Pÿ?¹RA¯H6±ãJ8Ä@Y`0 ¡8&ÿ«C1¯E3­Cù0D0¡a?*«@-÷¯D0_0¦;'£þÑ9&Ÿ7%Ÿ8}%0£>*¥@ôÐþ¶-˜7#™8%÷–3 ˜•4"“ÿ10‘1 û’1 p$ =*¡ÿ>+¨D1®I5ÿ±L8¹T?¶Oÿ:·O;´L8³ÿJ5»Q<¸M8ÿµI5¬A-ª@¯+¦;(ë@¬þàEï1°I5P­E3ï¢<) ›à7%™3!¨C0Cp²@›`Üúp,0±H3$€¬CÞü@+¤:%â£:ß%¯E0¸UPT>^$€­D.°à90·'©B/ð#¥×@I¯5¦@,€§ñPCÿ1¤B0ªJ9§ÿH7š<+™;+ÿ‰+Š-†*ÿ“7'—<-–?;,˜<.”ž°…þçÐJ;”9*‰0ÿ!‚)ƒ*†ÿ-‡-€&ƒ(†)„Àæ`.›ÿ ©C1Àƒ3ƒ0z`y@›0b0¬B<„p/€(¦<)‘@‘@ç°F3Û€ª1=* ;5"ß@¤8%ˆpö€øD0÷p”¡;)™5ÿ!—4!:'™ÿ7#Ÿ=*™8&ÿš9'<*‘0 —5$“3" pï”3 ‘9Ð.†ÿ"•2 ž:)ü‰¡0¤?+›5 ÿš2Ÿ7#¦=í)Ó@§>ø€!š0oŸ6"è¨@PÛ*¬B0D1Cp£=,›7%,`ôà—à›Û7&©à¡=×P*®—I4©Ò`D”`¡À(üßp,0ªA,¬C.úN€ž9%¤?*ö¿9Ãp'—4ÿ–4›:%œ:ÿ&”4 0—ÿ8%0–8%ÿœ>,–:'”8ý'/Ð6%ƒ)ÿŒ3"‚)z"û„Ô°"…-€')—vðÿC4žF7šB3÷Œ/p–8'‹ï-!/1'†$ÿ™6&Ÿ:*¢ÿ=,°I7°I6ÿ±I5®E1¹Oÿ;¿S?ÁS?Íû^I¼0Ì\HÉYÿDÃR>¼L8¸ëI5a ´¥0D1ª¿=*­?-®PC/°D1k`‹p\¥ÿ<)¬C1±I6P¤?,¡0Å@i`þ00J5©G4¦Dÿ1<)›:( û>,«H4¤Bÿ- <)—2–ï1š51`œ6ÞWà™2 »à¦?¯+®G3P`ž-`1ÿ (—1–ç0›Ë@Ë 1šû6#†“2"Š+#{ðê²p’á3‘‘-ð° 02`µ@¡<&¡ý:0(¨C/©Cÿ/¦A+§E0¢þÈE1Ÿ?+‘2Ž/‰+K°ÿ1“6"–9û%¥.PP<²TAÿ¿aN°R?©Lß:œ@.—=+ÿˆ,Š.!…*ÿ‹0$‘6%‰û/„°†+ˆ-ÿ†+}"ƒ½'°€š:(&‘;ÿ)•3"-Šÿ%€ ‘+΢:)ë@Žp™/ÿ›/¡5!©û;'YµF2ºJý6Q ·H4ºK6ÿ²D/¬?*²Eï0­@,D°F0DzF4Ü‚@#0¡9%œ7"&0 Pµ@‰0ŽP`¥@+0°” £p£þ¿A.©F2£?·+¢>Ä&žp;(™6%Ÿ<*! w¥B0Á@¯J7” í©ñP@,¼©B.} Æ8$6"0ÿš35 ˜1½hÂ7$0°¨þõpH5¨E2ž;“)¢90ƒ->ÀÇp¥@.©E1§C¯ÿ1©D/«F2ªÿE0ªE/¦@+|†0¤À¢=)Ÿ<4À"—5 ”3×ÿ“4!Ž0Ž1ß‹-’ÃÀ5"ÿ‘3 ”7#†)ÿ0„'ƒÿ&$"ÿˆ,4$’5ÿ$ˆ+…){ÿ| ‚%ÿ…($—:û(Å@D2ªJ8ÿ›;)Œ,,ïœ;(8`“0ÿŠ&‰$•0Ý—œ4"î ’)œ3ç()A0\0îñp¡5"ÿ€¤8$ߪ>+¬@÷& ÿ5#”*–,÷˜/jp¡9'¤F„0<(yÐöPz0¤ Pøô c`rA-¡=)®M`œ9'Œ–°s4÷!–7 ñ/’¿3"‰*˜;ÿ)“4"™;(’ÿ5"•7$ŸA/ÿ¡B/¢C0=ï*œ;'©p™7$ýž­ <(9%Ÿó9&šp» ªE2©ÿE2Í˜Ž˜7$ÚúБá4""Ж5ý#œ<)œ;)_ @,ž>à(ÖÐïœ;&¡_ÐD/¥»D0'à¢?+—à­ú•àDk€7¥F4£÷E3¨Ð>,’6$Œ1”:(Qàÿ—=+š@.‘7ï&”:)`à‹2!÷‡.ø4"‰ÿ0…,~%?ˆ/ˆ/ï“„°ÿ’7&Ž2 ‘4ÿ#‘4"„&‰ß*‘3!œàˆ*ÿ“4'˜9+—¿8*¢@.£Á 2ñ!÷Ðù •°J8¦å@, -}0Ð@–.ÿ™0 6$¦=+Øà#ØàSÐúP–;'¦?*¡<a¸@šp¢=(”  €¬pî5À–5"œ°›<+Ï—:&—ê‘_à(“ÿ9'‘8&8%ÿ6$8&Š4ý#2ð„/‚.ÿ„0}({&ÿ|'})~ÿ)†1Œ5$¿Ž6%“;)ïþ à,‰,“6#ÇÐy»Ðœàüð“àŽÿ0Œ0 ‘6&ÿ•8(š?.ŸEu3Wà“úð7$—´ÀÿC0¢F2@-ÿ•9$—;'•9ý&§ðœA.š?-ÿ˜;)–;)’9ÿ'…,ˆ/‡ÿ0 ~'…0ÿƒ/|)u#ÿy'v$qÿ~,{)}}ùÀ3"/ìðþàðu"{(|þÐ,+}&ÿ€)„,•ÿ=+ F5¢G5ÿœA/“6${+ÿ|+v$…¿2"‹8(†þ 6ÿ&-…0 ”ÿ>.•>.œD4§’9)òƒð39ÿ)—8'1 g.•{` D2 ~8À™7%”2 œ$„‘$èÐM`2À© ê)˜$;l#15"5#øw‰2!>ð~*8ñ¿//ŒZð=ÿ-‹:)‰9'}÷-yüÀ-}.ÿ{,}-‚ÿ2#{+~. ¿x(u$×ð~ß+|)8ð‰3"„.ˆ1!Aðÿ}&€)†/ÿŒ4#”>,—ÿ@/‘:*˜A0ÿ‘9)8(;ÿ)….ˆ1ƒû,ËðŒ6%ˆ3ÿ!Œ7$Œ6#‹ÿ5#‹6$‡3"ÿŽ<+’@/–Gÿ6™J:B1„ÿ7'}1!y.ÿz0 ƒ:*{3ÿ#9*|5%oÿ)r,v0!~`s,~7(iÿq*}5&q)ÿp't+bÿ gb ÿhw+s&ÿ‚5%†8(~ÿ/s,m%þxl#m$sÿ(hg ÿif jÿy,‚4%„ÿ5&Œ<-…2#öß+‡/þòŒ1!‰,ÿ0‹-0ÿ’1!‡%.ÿ—4#“0¤@,œ9$š8úà+àž?+ŸAþ£ð%™>*6#ÿˆ/6$Ž7$9&’;(!ÿŒ7&‹7'9ÿ)‡4$Š7'Œ¾š€8'ˆ8'Ä+Þ½z+m#ÿv+u*tÿ&3$~/ ÿ€1"‹;+‹=ÿ,„5%…5&…ÿ6'z*€/!ÿ/ z(~-ÿ~.„2"ƒÿ2#„3"~,û€/ˆ!…3#Œ:ï)†6%éð…5$ÿ01 2û!}¡1!v,ÿ|2"x/6ÿ'€7(v.yÿ1"j#k%ÿt/ n*v3ÿ$w5't3$tÿ2$y7)v4&ÿe%j* a"ÿ`!b!cÿ!e"l)ÿz6(~:+„@ÿ1ƒ>/~9*~¿8)y3$s¦€?ÿ0ŒC5‚9*„ÿ;,u+k!ÿp&r'n#ÿt){0$pû%=0c X ÿbj lÿy&x$ÿt}'vÿ~&†,{3#ð›=*§[€÷G3¥~À=*—8ÿ$˜8%É•Š˜ß9#š:% ž?ý*‹1>*š<(•ÿ6"’3•7!ÿ0/“4ß ”5!œúPG4ú ¡ÑÐ@.š=*ïŸC1”J@5#ÿ3"Œ2!5%ý- 3!‚+{ÿ%(„.÷…/ / …1!~ÿ+„1!-ÿ{*|,~.þÒƒ2"‡6'ýï-y(vÿ&w'w&ÿz+w)€1ÿ ƒ4$|,xÿ*b b ÿhk"|1ÿ ‹>.€5&„ÿ8)„8*w,ÿ4$‚8(x/ÿq(m#nû%+0m#o&ï` ¥k"ÿj!q)k#ÿh i jÿ!r*s+ÿh"c_Ï^xË w/ÿ ‰8)†5&{ÿ+.‡6(Þq Š:+yZ %ÿr$s%j"ÿak#iÿ m }/#ÿy*‚2&–Cÿ3‘>/’>.–ÿ@1“=-ˆ1#ÿ„,y |!ÿˆ.‰/Žï4 Œ/z€–:ó&™à•0=)˜9õ%ˆ0ŸO€G3¨Dÿ/®K4¬G1£û>(§ÀªC.®G½2Öp¹R=²Ü°Kï7¨B.]€«E3âc€¬³0€Xà7%?;(ž>+šoðhü¿Ð°;*”7%‘ß4!‡,kP‰/¯‡.Vðí8ï'Ž7'2ð‹5%ÿŽ:)9)Œ8ó(ˆó"@1!ˆ7ÿ&Œ9)ˆ6&…K4#ïòµž ‰œQß(‚0‰Tð;)ÝŠ‹à:)aàA0ÿžJ9¡N=–Cÿ2šH6‘>-„ÿ1 ‡5#-ÿ~,Œ9'>,“@.¡N<ìPÿ=+…4"pÿt"k l ƒ2!ƒ3g [*ŽÛP4$h c`¿E2£A.¥€Dÿ1¢B/¬L:Ÿ¿@/•7&`.îf1•9(ìŒ1 ß‚&%­€‡Ÿ+“8(°`à™ÿ>-’7'‘7%×2 qP‰1ÿ•;* G4¤Kÿ7žE0›B-‘ÿ8#–;'š?*ÿ—9&–8#™;½'¾Ð=)£ÎÐ?ß+«G3¢Ã‘%¡õ=áÐ'P§C/ª÷D2¬BÀK7¦Bû0ž3Á#•1˜þí`?-›6&“/ÿ”1!Ž+–·6$œ%°?,£p Öã`B.+` æ`B.þÍПB0¢D2›ß>-4"ð@'Ÿ‚+Šgà~ð5ÿ$Š3!‰2•ó=*¼ð&ð’:&‚ÿ(‡-Š.ç‚&Q°‹`¡A.¿®M:¯O;*à›üðºÀ6#,û/£Ð˜7%«Iú¢ 3<° >*ž<û' ð>)™6!ÿ’/š7"¨E0³O:°L7›À¿š6!”1Ë‘ß.Ž+“p‘.ÿÉ\GÃWBÁÿUA´J6±G4÷±H6z®G4ë7%š à7%Ÿß;)›6$1Ð’.ñ’ÐVP˜6$Š)Œ,’2Ùÿš<)˜:(˜þ˜Ð?,™=*¤Hÿ4B-B.—?<(’6#‘Op¿ ÿ:&–<&œ@+ÿš=(•7#3ÿ1‘1™ÿ9$Ÿ>+¤C/ç«H5#À  ¨D1ÿ¤A.¤@-›7é$‘à9kp*:ÿ(‘-’. ,¥°˜ið§ÐeÐØÀ÷3!–U°7#›;(˜9&˜9'nðw“7%o°–;(Ä0í–*7&_ðŒ2¿‰/Œ2 àÏ3!˜<À0ñŸA¿.˜:%•5à'ç¤B/†qÀ)ÿ&—0œ4ÿ!²J6¯F2±ÿH3«B-¤:&¿­B.¯D0×€¬ÿA-°E0¸L7¾S>´H3²î±ÿ1«>)»N8·ÿI3±C-ÁS=þû€ºL6¾O:©¿;%´G1´*PIÿ4ÆYEÖ’³ÿJ6³J7¸P=ÿµN;©C1 ;Þ½  ’-4¡<ÿ*—2#Œ(’ÿ. ‡"”1 d,À8€­{ÀÐD2ÀàþJÀ®I5»UA²ÿL8·P<·Q=ÿµO;­H3°Lÿ6§E-ž:$­ÿI3¨E.­J4ÿ®K5£@+ >¿(§D.§DvÀ/ÿ±M8®I4¨Dû.¤gp8#8#÷ ;&¯` ;'£ü$€ã`?,¢>+¢Î¹’ <*¾€Àž<Í*¬¡?-ñ`…=S,•iðiô%ÁЛXàw=*•êP4"‹naû Ž`1 ‰.ÿ‡-Š04{#°4!“5¨ÐÏ$™:% P¬0•5ÿ!‘2¢@,§¾k F3¶Q>JÀªçD1ž<€k+›û2FÑF2ÂYDÿÀWCËbMÊaÿL¹O:¿U?²ÿG2¦:%¸K6ÿ¯A,«='´E/§8"¤6 { ÿ 2°C-·Kû5¶N8¨='ÿ¢6"§=(¥;'ÀXD·O<5PϲJ7¢QPVÐ>+ü·p¸¤>,‘+ÿ’,)–1ܱ/À¥@-« ›6#œ6"š3Àÿ¬D0±I4³Kÿ6«C-¬C.¢ÿ:#˜/œ3ÿ¥<%§>'³Kÿ4¯F/©A*¯ÿG0°G1·M6ÿ¶N8²I2²Jÿ5®F1¯H2®÷G0©p B-¥=3)¨Ð_Ð?+MÀgÿ¬F48'š4ÿ$+Œ'…÷$‰P`'‘0tZž°)S±;)¡¿`þÍ ?,“4#/õ‘h1(–9'é’Y`%p5€!1÷/ñÀ"1 ó‘3ÆÑ <(£×A,¦õ`@íÐ'¡{;'²¢<)ŸqÐû:'nÁ5"ž6#ÿ—. 7#ž5û!›cÀ4 ¢:%ÿ¥<'ª@+µLÿ6ºP:¶L6­ÿC/±F2¢7#ÿ©>*³H1®Bÿ,¸L5°C,¯ÿB+¨;%¢5ÿ¤7!«?*¥8Ý$^Ы@,IкPÿ<µL8°H4©A-«C0¨A:Pÿ-§A.§B/©ßD1¥?-4À¢=Á+Í`ßÐaP,€®Jù7”¯`¢>*¦Bw-£?³ )¥A<Àÿ)©C-ªD/°ßJ4«E.pÀ¨Bû+Ÿy ='¥@(ÿ«F.«F/«Dç.¥@fÁˆÀ³M7ÿ²L6¬G0§Aï,£=&jÀ§A-w¦?+¶° :%Õ öRÁ=+5€ªG5¤ÿB0ªH6¡?-þ à™9(‘2 žþÎ`<+È•˜:)“5"\Pð‚™Ó:'‹ПÐC1÷¡A/b°›<)–ß6#™9&â™8ß&—5#“È`5#ÜÒ ¹€©C.&P¦>ï)±H2 °¥=(ï¨@*­kÀF2¸¿O:»P;­"Ð<ÿ&—.š1—o.š1õ (¡ ÀãC/ê ê Î„;&¿4§>(¬è Bû-ª 4 ž4÷Ÿ6!Ô°©@+Öçž’®¤À 6"öÙ ;'À¦>+¥û>+(®G5™3ÿ#”-‰#‡ÿ!‡&ß„$/ áž=öep-¥¶`K8¨Fu2P—‚à.™ÄpÛ3!£`¤ATÁК³¦§ÀžÀ>)óЬÿF0¯I5«G1²N7ªE0¨"зB-Ÿ"à<&¬a@ý*ðЧC.¡=)ÿ›7#”0Ž*–2ž:'3 ÿ¤B.©F4£A³/™<°„€5$t€›¿=,?.”G0½!çp—9'˜·°8Î& #—7s€U°'ž8HRÁ`GPŸ=*tá!à q/à <³ ° ðøàë)¤'±+$У;&ÿ 7!¡8#ªAÿ,°G2µK7³ÃH5ÀÔ€“Ò¦à#§Í>éà)¥ÉàP4 ÿ•/˜2›5ù!¬XÀœ8"Ž+ÿ•1˜5 ›ó7"²`íЫF2­H4¬F3±K7°Û2¢±€<(œÐ¦=ß*ªB/§¼;'ÎB «E1? DP°L9§D2­J8ÇÀï<+›cP5$¦ÿG6¢C2 A0?¢B0>* +š`Ÿ¨E3¡>{ðŠÀ-ç¤?-++À¦?.û­EoÀ2­G5¨ÿ@/£=+›5%ÿ™3$5%˜2ï!Ÿ7$œÐ©@,÷Й­à®G1°ÿH2°G3²I5ÿŸ7#œ3 œ4Ý ¼°š4!? :úà,¸`¬I5­Ký7ž°¡@+›:%ÿ™8$•5 Œ,ÿ‘3’4ÿ1£D0¥F1ÿ¡B-­L8­Lÿ7²P<Á`K¼ÿZE¶S>¯J6ÿ¬F1³L8±J5«C/¡9&Ò Ž»“ªF48àÆÐ7ð•ý5—°&ž@/¡Dû3”0 0 •8'Ðw°ípëäpTP;(üo—` ?+©H4üUðë`ž;'<'dÿ]™ ª?*]p¿¦F1¨G3#€”ÿ2 “0Š(ß—3 ›8ž+¨ëD0É °À9%—Ò­ñ# ÕПéðC1¿ªJ8¤E3:ð›ï:)˜8ðÀ* ?}/S°Ÿ<+¢@fð0¨F4¨F33 üL³°•0™2 ÷Ÿ8'ŸÐ¯G4©çB0¦ã`T;*©ÿB2¯I8¯I6_«E4§A*¶°Ö’àŸ9š¤–;'ï­G2¨PE2¯ÿG5³L:·Q?û¦A–2™7$—s5"#€”0¡A-bàï’4" `%÷2"Š  -3ï0ë‰+üçp_°Ÿ@.«L8¿¥E1œ<'©ðœß:&¤A-A€Ÿ;ÿ',‡#”ß/’0b€.ùлðŽ2$)ÿwl xÿŠ.‚&}‹Îð-†)òßC0œ>,ÓÀ0×-Òð—`±Pÿ<¯N:©H7 î¸ 0“ÑÀ>+›~ A-œ=)0°þPI6±Q>§G‚ã2%`ÇÀ%`Á`§ƒE0,€‘ð¥5€èñBÏ0¡@.Ü\P–67%“3œ0"œ;Ç û>-1`œ=,Ÿ?.—7%´Zp_€èðg¦C0è åð¥BQÀÿ-¥A/š5$šÿ5%—3#–2!ÿ›6%œ7$˜2ÿ"—1"œ7'žý9õÐ,¨C0§Bÿ0©D2¥A.¯vSB/B ¨A-•ÿ¯H6½WD­GÝ4Ì Ÿ;(ÁªGÿ4³R>¿^J»ÿ[G¸WC±Q<ÿ¬L7³S>¸XÿC¼\F·WA±ŸP:¨F0aðW–ë5 í“. A,¨þg E0²P;˜7ý'Š0Œ*€÷,–1*•3ý _«J7®N<÷©J8bPž>.›‹;+Ó"/eà7ðÉЩI6°N;°OË1ç¦D0 )”0ŽÄ`›9&å`èð%`«³I6¢1I5Vžn–A.Ÿžð=+ÖÙ [ “3 ¸ñ“à­ A.²ñ4" Ð_PàÇ O ÔßÀ7`0¿1"”9)ƒ€šÿ@0žC2–;*úU`‹p0 2"û4p°"Œ.‹÷-Ž 5% @ÿ/¥E3¦E5¤¿C2Ÿ=,™¾08ÿ(š6&™4$¢->Æ‘¥>ŸÀ,±¡–ðñð¿°Ô°¢9& ¯6#¦;˜ (³@«A-®D0¥pã°9Э¸Í0G3°Ÿ³À<Ý'$ЫD/2P¯GþÍÂYC¼T>À¿XBÂZEµù€Pÿ;§@+œ5žÿ8"—0—0ÿ7"™3œ7ï"8$ *DHô16µ Ü`GŽŠ°û1 ÖÀ‘2!š;ù+JàÜÀ¡C1>O,›=*@Ц£0;K8UPªJ7@Éе"Ý-e5R±n€ß¡¢,³ #ÀÏPD¦€/÷œ?.÷œA.¢ÿG5 F4›A/•;(‹ßpé_`9ÿ)6(ƒ,ÿ)€+‡1"ÿŽ8(“>.•?ÿ0Ž8)–@1ÿ:,‘;-–@0ÿ7(‘:*ˆ3ÿ%Ž9+8+Šÿ2#”<-’8)Þ¬P”;+`1"û’7‚€+—;,žï@0™9Ð&–4?$“1!˜3е°(¥=+ª@.æ°ÿ¸J8¾O<ÀPÿ<¿M9½I5¶ÿB-¶A,¯:%ÿ¹D.ÁM7ÉUÿ?ÊV?ÈT=¿ÿL5¯<%´B+ÿ§5®=&¥4ÿ ¤3±A-¢ÿ3 ¶H1±D-Ý©O`G/³pbµJÿ3¸M6¯D.²ÿH1¯E.¦=&ï§='§eÀB,¨ËA,jÀªÿ¥@C0þýŽ4"3"‡ÿ.Š1"8)ÿ‘9)›D4¤Mÿ=˜A1’:+‰ÿ1!ˆ0 6&ûš@ŸP)ˆ-‰ß.†,-p•:ÿ(™>,“8'™þ>P<+š>,¢Dÿ3¥I6œA/˜¿>+—<+¤ð3ÿ"Š0 Œ4#‹÷4#Q@?.‹8ÿ':)†3#†ÿ4$†4#„3!ÿ€/~/†7ÿ&3#‰;+‡ÿ9*1"…7(ÿ‚6&€2#4ÿ%2#}/!ÿ3&2$}.ÿ€3#~-y,õSp{³P1"„4ÿ&„3%…4&~ÿ-{+}+ÿ|*„2"‰5ÿ&Š4&Š5%Š4$Š1!‘6[àù*:PÇ ›8(˜4ß#š4"£·@=*ù«[ÒÀ©<)ª<ÿ(´F2¶H4»¿N9·J5¦!€2ÿ 3§:$¯÷C,°’ÀH1¸Mÿ7½S=ÀW@º¿Q;³K5¬°Døúà–2 ,°M5§ïE.¡?çÀ&ž=ÿ'Ÿ>)ž>)Ÿÿ@*-Œ-þ ™;';+}ÿ,u$t$ÿy*€0!‹;ÿ,ʇ6'•ÿD5Ž=.Ž=/ÿ’A2},|)ÿnt"ÿ-"~*•?/ß”=,‹3 q)ÿƒ-†/ ‘ÿ:+–=/•>.í—V€>-X€“<,ÿ‹5%„1 †1{!~up,ƒ2Xpû|rp,v(ÿt's'w,ÿx-{/!û3%¦€|1#z/ÿ s+v.tÿ,l$p'ÿq(p(r)ït+Ä€r*ÿu,m'q*ÿs- y1#uû/!߀o(n&ýñ€r*r)þÙ€y/ y. ‚5'2%‚1pï%…1!‰p6'ÿ‘9*šA2šA1š>-—9)C ÿ„%‚%‡(oŽ/ Ç ¤EEðá/Ið<‹ Æ0ªK8üe°è/Ž1¿—;'˜>)`ÿ3…-’:&ÿ•>*–@,™Cÿ/Ž9$Œ7"‘ç;'™÷0N:™ÿE1”@-Š7#ÿ‹9$•C0Ž<ÿ*r,s. vÿ1$g!v0"ÿz3&q*t-ÿ r+x0#zÿ1$}3&u+ýrË€'s(yþ’€.~/ ~/ÿ!†6(}-ÿ.x&w%ÿ€/ €/…3ß$€-‚è.þêˆ6'z+yÿ+v%v&ÿƒ2"ˆ7'Ž>ÿ.‡8'1!±.Γepƒ4Rq~½1Ô}/Gp~ÿ2"4&|0!ý}Hp2#z0!~ÿ5%~4%{2#ÿ{4&w."q*ÿi&h%iÿ%m)p-!ÿk)i'h&ý\ k(m*ÿl'j&k&ÿq)r){ÿ1#{.y*þ+€ƒ3#„2#ˆÿ7&‰6&‡5$¾p‡5#‡4¬¡‰ÿ6%‰5%”@/ÿ¤Q@¦SA­ZÿH¤Q>’?,Œÿ8&9'†2 ÿ‰5":'€.ÿˆ7%•E3šþ2ðR>—J5‘Dÿ/ƒ7"‰=)‹ÿ?+‰>+ˆ>*ÿD1ƒ9)†<ÿ+‰?/{1"†ÿ<*€8&w/ÿy3";*g!ÿl'f"bÿf"l(ÿj%o*v0ÿ#n(k$lÿ%fj#þC°a] _ÿ o&p'ÿv,z0"p%ÿs&v)|ÿ/ ‡:+?0ÿ‰;,Œ=-ˆ7ÿ(„3#ˆ6&ƒï1 „0Ó %‹5ÿ&9(Ž7'‰ÿ4#ˆ2 ƒ,Ï….Ž¿ ¹ =,ÿ—@-:'8û%–Ê@,˜C1ï‘<+ŒŸ 5$ÿ+|*~,÷}+ç‘1"{-ÿs%v(wþ“ 6'„9*‚7Ý(G s)ë°p&ÿm%j"oÿ&o$v+÷z. >¡0"3ý%Aq2#0 }ÿ-ƒ1"/÷„2 Á°z'yÿ&|(z&ÿw#ƒ/Š6ÿ#Œ8%’>+Žÿ:'…2‚/ÿ€,ˆ5!‘?ÿ+•B/›I5™ÿG3šH4¨VBÿŸN:žN:Œ<ÿ+„5#}.q$15ñ ÿ*‹?,7$sÿ*hh ¿r*‚;*Â+ûy3À°-‚ß1 ‹9)€…4ÿ$0!{*}þ¬Ð9*Š;,‡:ù*j° m!eÿca pÿ%y-x+ï~1"}H 1"w*w)ٰٰ”€ÿy)|*€,½¾°’=-•P>û-“Wà<*˜;)~Ж:&˜;'T›ôÐF1§^ÀGo3§H5\á:%8@úéšà>*žB/ï¡E1ŸÙB/ŸÿE2™?-•=)ÿ˜@,”=+‘:¿)‘8%‹3Å`φ-†Û 7À4"Ž7%Ä•ŽŸ ÷2"‡Ä`1!Œ5ï%6%†ÐŽ6&÷Œ2!É`‘7&“>¾0?.™<(Ëü½£îÐC.£?¦(þ P˜3ž8#©ßD.§D-à²N÷8£@þ2½ZCÿ°M6×¢•­Jîò02ž=QP.>ÿ&–7¬M7¨ÿJ3±T=²V?ï¥I3‘`M7¤ÿJ4¢H2±WBÿ¬S>§O;¤Mÿ8“=(…0ë-rªyQ=§ÿL9¨M:«Q>÷œB0’Ѐ(tÿ z$}(ÿz&x%v#=FàŠ7(а}°ß0!y&ð¹Œû……9p2"ƒ1!ºdà‚3 -˰,ÿ„/€*„ÿ,‚*„*ÿ‡,1–9ß&3 —ôœ;ÿ'¢@-£C.ŸŸ=*›;&ù©ð›_:$Î™Ž ©bðþü@:$¢?)¡={)¢}ñ+œ8$B0× =(dðªs?+ÿ¥B-;'£=¿)§B.£@{ð,y¨!Ñò05®N:t@ü,@5@-1ï“5!—­°7#˜{8&)›7%¥ß¿A,¬C-°Þ@Dÿ.±C-µG1±ÿB,®?(­>(ÿ²D,³F.©<þÐp+°D,±F.ÿÁV>ÅZB¿Tÿ<ºO7­C*¡ÿ6§=$³I1ÿ²I0ÂY@»Rï9³J1lð¸O7ÿÃZBÃ[C¹Qÿ9¹R;­G/±ÿL4¸T<®J3þÔС?)¤B,©ßI3¢A-v ˜:ß&’5"’)P=*þPСH6¢I7š¿A0“;*… À+þ™°y"x!ÿx }$Š1ý ’Є*†,üÛðG@£H8š?.ÿŸE5”;*Š/ÿ5#Š/‘¿4#‘3!‰¹P(ÿˆ(0—ÿ5#œ;(˜6$çœ9& ¦D.ù¦”`!ÐD/§C- ;' <&¡w û:&/¢>(§B-£>*©C,¼Ð?¡9$¢:%ª@!ðÿ¥='¤>(œ9"¡<& 9$û@Z“`§Ýà?+§Ÿ«@{>*ëà¢@,§`óF3¬ ç›:&ŸÞÅá,™6$•˜1ÿ˜1£<&¥¿:$£8!¨ˆ`<ÿ$©=&¬@(­çA*°.ððÐG0°ÿF/²I1©A)ÿ°G.­E,¯G.ºR9µM4Ôß±I0«C©p+¦ÿ>&§@(¬E-ÿ³L4®G/°H0£<$¨@(û÷¯H0„ð¥@( ý<(ž<&™7û"£TE0¦H5ÿ²TA¯R?ªM¯:–8&F Œ÷ñ"–:(1!Ž]Aß%Ž1#› @:)ÿ2 •6$ƒ'ÿˆ+2$Œû/!¸ ž<)™8ÿ%=*¤D2£÷B0¢E™7% k=+$0¦}B/0Ý¡:?,› 03!î –1Äà¨B-×§A-ªp 8$ÿž9%˜2 9ß&¨@+¬¡ C-ÿ­G2«D.¥>ÿ)ªC,£:%¦û='$ð±I4²Jï5­E0ëàš4 ÿ™5›47½!™`³M9² àI6¤>*š5!¬}Ÿ›à>,š6$ðÿ9(ž:(©DÞº/¥?,×@›4û!œv04¡8#ÿ§=&®C-¶Lÿ5¿T?¼S<µÿK6µL6¢9#þ'  7!ž6¬ßD-­E.K ´Lÿ5«C,ªB,¤ï=&6 %®Gï0³L6ép³N7ý«…`A*¨C,™ý4P!£>(®J4°L7ªG2ÿ”2“3‘1þm@ £E2¬O=ù¦\PDP@.¡D3ÿ˜:(š;)Œ,ÿ…%/—×6$ †@¢à+¤óA/ ôµP>¶ÿQ?¼WEµO>ÿ«D3¦>-¦?ÿ-©A0·O>·þÓ P>¬E4¦@û. tP4$›3"ß”.—0 *¨ïA.²Lð±L8¿ªD0§B/0¤û?+P—2™6÷!š5 (¢=)?£>)¢<(q÷þ÷¡;&¨A-ªýCô5¶O:±K6°I4ªE0Œ©<ÐC =•ð-&­ÿK7«I4¦D/ÿ¤B/©E2Ÿ<úÃà*—‘+–2™3 £<) ÿ¨B.³K7­Fß1®F0±ðÐJ5ÿ´N9¸Q<³Lÿ7±I5¥>*˜ÿ2¤=)°I5ÿÄ^IÈbMÆaŸKµO:«!Ð??ÿ)œ8#“0˜_5™5 §—ðÿE/¥A,¡=(Þßà£@+¡ÅG2ÿ©F2±N;·TÿA´Q=°M9¨ïG2Ÿ>KP+˜8ÿ$›=)ŸA.¤ÿE4 B1˜;*þ@ªM<£E4¡ÿB1’3"“4#–6%¡A0ž–@ÿ?. ?.ž<+÷£A0À :)þßð/Ž)˜2÷ ¢-¥J@=ÿ-¥B2¨F5«ÿJ8²N=§E3?¥D1;)OPaïš:'”¤P/‘ÿ/0˜9&í¥}P>+w0š9'ýމà,‡$™¿4!¡>+¬Oÿ;Ÿ?-ž=+›ÿ:'¡@,ªI6÷¢@/jPš9)¡ÿA.©I7¤D1ÿ¡@/—5$˜7ù%vï@8'›9'æÄ@œ:Q @œ;*ÿŽ-–5"-.pPPC@Bÿ¥G4¡C1¨Jÿ8­O=µWD½ÿ^K²S@¯Q=ÿ¡C/—:%’4ÿ –9%Œ.Œÿ/4 3ÿš>*§J7žBÿ.¢E1•8&‡ÿ*‡)!ÿ“4!>+®N¿<³S@£Cü@.þ9¡B0­O<šøÐ¦Àp5%‰-þ7˜=-5%–ÿ;+B2œA1ûžCúÐ2•9*‹ÿ/3#Ž0 ÿ”5%›;+¤C]3I@§E4ÛPŸG@ÿ@0•1!—3#_™4%›8v.óPß›7)™5s. ÿ>0Ÿ<,=,ÿ›<,ž?/ Cý3"@2"Œ/ÿ’6%‘5$”8]'#`1 ùð—pë9&áð–=+ŸÿD3§I9°TCÿ¢D5£E5 Aÿ1™<+¥F6¢ÿA2¡A1 F5wŸE3`¨I9"@ÿš:*“6&‹.ߎ2!ˆ©P2!ß—=,‘6³Qš=Ï.—<,}`®P–<Ï*4#Þ`:2Í"ä`33ó`š>~¶P1–=,‚)kÿ)“<+™A0œÿF5Œ6%†/ÿ„/‹4"Š3ÿ!9'7%…ß-‹3"\ÐŽ8½& °’;)—A@Iÿ8¥M=³[K ÿH8ŸF6žD4÷•;+äð D4ÿA1¨L;¤H7ÿ¤G7©L<˜;ÿ+˜<,–:*”ÿ8)3#‡,ÿ‡+…*6ÿ&Ž5&”;,Ž¿6(Š2#Œip,ÿ…-‚)ÿ&„*‡-÷†+ž`™<-¡ÿD5§J;©K=þG`œ=.0"’ÿ1#Ž. ‘0"ÿ¡A2Ÿ@1£Aÿ2›;,œ;,—ÿ6(›=-œ=-’4%”6'a¿ ’5&“6“p&½š a0Ÿ?0S`¥ÿG7£D5—:+ç™=-œP¸pžB2ÿ4%†+†+‘4$•8'žÐÿ B2‰0"‘5ò£`#`¡`•:)•þl`8)4$‰.ûˆDp+Ž4%ù5pk°4%Š1"¿‰/!‚)Êp‰{/ððŠ0 ’Pàs/ `/`™>-pÿ’8(5&‹2÷#Š2ßa5$Šöu`/ ‚àˆ/Œÿ3"Š1!’9)÷™?/Z€£I9¥ÿK;¢H8“9)ÿ•<,”<+‘8ß(™A1‰ '÷'Q€’8'œ_B1¡E5¥P— pû7'Ðp–:)…2ÿ'}){'~ÿ+ 9*—C5ÿ˜D7šG9Ž;ÿ/‹9-†4)ˆÿ7+”C6›J>ÿ¥UH¡PD£RÿE“B5…4'Šÿ9,†5(ˆ7*ÿŠ8,."~,ÿ Š8+Œ8-ÿ=1•?37*ÿƒ,~&tÿo x}ÿ"‹/!’6)ÿ•8+—9,–7ÿ*“4'“6(—ÿ:,˜:+•7'×”7(ÐpÞ`5'ý“4%–<-”;ÿ-’9*œB5—ÿ@1šB3šB4o’:-•EC4Dÿ•>/ƒ1#}+ýÀ’>/:+ÿ†2'~*}(ÿ€, Œ7(”þåP?0—B28ÿ*Š6)‡2&‡ß3%9*}œE5˜?1˜?07p×5%¹`Œ® -~Up%„)qaû3$îpœ?1š=ï/›>0¸r.ŸD4—;+4#7ÿ‡-‹1!7Ý(>Ž6'Y’;ý-›E7™D5ÿ›F7›F8<ÿ-“@1˜E6–ÿB3”@1Š6'?.‡4% þÿu-ŒC5ŠAï3†>0% {3%ÿ~6)†>17ÿ*t,‚:-xÿ1$w1$:-ÿu/#o*v1ÿ&t/$s.#yÿ5*n)r-"ÿi$f!j$ÿh"s-!wÿ/#y.$r(ÿo#p!{+ý瀓?2’=0ÿŒ5(‡-"‚)÷ƒ*üp‰0!÷Š0"Çp”9+˜ÿ=0šA2•=.ÿ–>0•<.•?Ý1õ:,Œ€-ÿu${+vÿ'1$„8+ý€Ap9+x,}ÿ3%s,v- ÿt*q&w+ÿx-@2‹ÿ?1ˆ<-Š=/ÿ€4%ƒ5(Š<ÿ/†8)1#Š¿:-…5'†Mà9ý+\/!„1"î°‡2$  Š4%ÿ6(6'’7(›?0™<,‘p¿/$?°‰ó-!€ÃP˜=.÷C3™EA2–=žÐ/–@1  Œÿ:+1"z+ÿo!v)r&ÿ~3&„:,~ÿ5'ƒ:,t,î+ v. ß r)ÿk#r*v6ÿ+{;0„E9}ÿ>3y:.i*¿T W±°`ÿ#f)e)ÿ\ Zd)ÿf,"t:/wÿ=3m5*g.$ÿY Yb'ÿe(j-$eÿ)_!f'ÿi(q."t.ÿ#r*r'yû+ Ê …5)ƒ1÷&†4Qà)ˆ5)_‘=0Ž9î-†þÀ{(t"uÿ#s"}, ÿz,u(r&ÿifm¿%d_ÊÀ ÿ`d"gß%aVÀVÿ ]e#iÿ$s0#{6*ÿ;-ˆC5„=ÿ08+r,c¿g i*À)÷u+°p&ÿn%v*w*ÿ€3%†9*‰ß;+Š9*\ƒ/ ˆ2"‹2"!€î3€Š- —;-ÿ”7+›@2˜>ï/›A3¬ ”>/z%lkØÀÿw(|/!ûy-ˆÀh bÿj$_ÿYb"^ûaQÀ&_ý^ZÂZb"þÐn/#l+dÿ$c#\þ«°i, r5*wÿ:/o3(r6+ýi\ .#f+ dÿ*g.#Y!ÿ^%d-$a*ÿ!a)!^&UÿT^#ÿY_"]ÿZX^ÿap)ýw3Á|-!1ý%á€/$~,"ÿx%‚/%‡3_)‰5(‰Á$ ÐÞ °‚2$€iÀ, þu°w+t*iÿ"e^ f t, q,Ðÿ."e"^ÿ]`aÿm)y5)}ß5(~7+7 m'¿o'j"ÆÑuÿ.!|4'~8,ÿz2%|5'x0ÿ"|4%~5&{_3$}2$Ö | àÿ0!0!~. ×~.màˆ(°8(Ç“8*½P"pp•8ÿ)Œ0"™>0˜¼­ ª ?0‹6œÐ'ù‡ApªÑ!~/!wÿ+x-t+}c¿ÐTMÀþj s/#w4(gÿ%\Y ×Z ÐjzÐ6*v5)x7+|®ÿ0!‰8*…5&ÿz*mcïd æÀƒ8*ÿˆ=/’G9ˆ>ÿ0x/"„;-„ÿ;.9+‰@2÷„<.à€6(x÷/#xk .!n$ý˜Àt'}. ý|µà2$†3%‡¿4$Ž:*‰úà8ý)æ”:,”9*üßp±PŒ. Ž1"ŒÞ4%ppÈÀ—þ¤ @0œD4žEï7›B3]±?/Œÿ5&’;.‘:,ÿŠ3'Ž7(…/ÿ!,y%x÷%}Pp5'Š7ÿ)ʆ-zÿ%….‰2!üð­À~)v"ÿp p€+o‚0"¾ †4¢Ðÿ"/‹9)‹}8œÐ&Œ7'„“ðß5%‘;*¹`˜?m-€`‘36@&ž.€û@/Ü@œ;)”3ÿ"0!/Œÿ/–:+ E5ÿ¥I:©O?ªOÿ?¨N>¦M=›ÿB2“;+”;+ÿƒ*7)8ÿ+Š3&‘:+ˆÿ3$€,w$v#},ŒŸÿ<-’A2.wq p2!,`~Ëðœ>,ŸB0+¿¨K:³VC"«ÿN<¡E2“7%ø˜`CuP’6$Ž3ÿ ‰-0‘ý6»(‘7%”:Û)”_6$€`3ÿ!…*ƒ)†÷+Š ‘&@0þ‚ŸC2£F6œAÇ‘‘5&ðÇpÃP÷Œ1#s(ƒ(‹0!3$Bà¼`p›>.ŸJ@BŸ0œ>-›.€;@@¿/œ?-˜< ð%þP`›@/¤H6ªÿN<¨L9ªK9ÿ˜:)’5#“5ÿ$3!™<*—õ<¢ *˜`š?.¡ÿG5šA/šB0ÿ–>,‘9'”<¹*­ð×`Š3 Î`ˆ0‹1 78€s"†«)p.`ÿ<,ŸF5™@.ÿŒ3#†-‡.ýRp„*~%?~$‚&ôpÄþÍ A/£E3©ÿJ9¨I7¦G5¿ @.ž?-QBû1Ÿ =+’5$ÿš>,£G5­Qÿ?³WE­R@®ÿQ@’5"‹,ç“3!$PP£@-ï¦C/¢þ/™ÿ4 Ž)”/ç¦A+Î0S0©D/þɦ@+Ÿ;& þ 7#’0Ÿ>ÿ)©H2¬L8­çL:ª£ ‘P>,™vP1 ,Œ0›`Þ ð4$‡Ìð3%ÿ‹4$“=.“<Ï,Ä•>ðÿàŠ5ÿ&†/ ƒ,ÿ,„-ƒ-ÿƒ,)„,ïŠ1 E€†,÷„*Ý‘5$‘7&[Œ2œpl*’öÕ`5#O’7%û5!X5#4­!C6Þp#a‰ÿ.4"Œ3!÷6$g“9'•ß<)‰2 ˜ ˆ2ÿ!„/†1!…ÿ0.Š6&¿9(’@/³ ŒþŸÀ7'†5$‡8ß)„4$„ÿð/!ýQð'v#sÿw"‚+Àkð§r€1p„€b &Ï$ü¡`—,š7Ô+­H5¤>+Ïÿ§?*¯G1§=ÿ'«A)§=&¦ÿ=%µK3±G0ÿ¹P8´K4°Gÿ/«C+¤=& 9#Ÿ9#¨AÐ0ÿ+ªH3ªH5¢µA5P.u™;'üuP'=+™?.ßD3œC2à`Œ5ï$†0 ¡ð‰3#ÿ-„.!†3ÿ$‡3$‹8)‚ÿ-|'{&?„/ ‡0!²0Cp®{€ƒ*3R€0Œ0Tp€t`€`•;)ˆ1‹Ý1{ %P4#”9/°[&•6a)”×0:•€í!V!4 WP2ó‘3Ðð;°“7"¾fP2“8s!ÿ7"Œ4 Š3¿‡2‚.Yðy?(w'z`¨~°;+„3%‡ðÿ. ƒ2#-ýz:@&w!†Ü“ðä 9(‹Ÿ +ÿ|#~$Œ2}!ß0“8&5²Àþ"`%@-¢E3ý˜09'™:'–ÿ6"/,ÿ¤@+®H3¸Qÿ<¸P:´J4¼ÿQ:³I1½T;ÿÂW?ÀW?ÃZÿAµL3²H1«ÿB*ªB*¥=&ÿž7¡<% ;ÿ&ž;&¤A,ÿ;'™7#¡A-ÿŸ?+ ?,œ?û*—ì04!”6#ìs0„œBÊÀ.›Bÿ1•;*—?/“y:©ð P.Ž7'wè# '°¤ð…(à-{ß$|%K5¿#‰1…+xöò 1É0‡+ÿ‡-†*ƒ(ÿƒ&†*„*ˆ.…,@Pÿ…)Œ.–¯8$š;Šp+ПÿA-§H4£C/ùªÇ~PB.§F0ÿž='Ÿ?)Ï›ÿ§H1§G1¦ÿG1@+š<(ÿ˜<'Š/Š0ÿ„,ƒ+û8&ã`’<+9û)‘:*†1#o„0"w-P& Qÿ4$…/~&?&}$b [ûŠ/{€&ˆ÷-ˆB (‡+ïŠ.VP„'ÿ‰+ˆ)0ÿŠ*ƒ"…ÿ#™6!•1ÿ–0˜1œ4ÿ¡7!¦<&¨ÿ>&®B+µJ3ÿ±F.²J2¨@ÿ(¨@)Ñš£þS0:$™5—5ÿš7"›:$œÿ:&›;'š;&üqP¤P?,›<+þ0—9&“5#”ÿ7%œ@-A/ü1ó”8&”8'xˆ`Óôp.Éòý–:7%Ž/‹?,Š+’Ô0y@ß3!Œ,¸`’0ÿ•2 •3!û/Ç`’0—8%š:'Ÿ>*ê@ÿ˜:'’2-ÿ‘/˜6"£ÿ@,Ÿ<(š6"o”1”#`4 `ÿ˜3›6!Ÿ9ÿ%¨@*©B,¦ï?(¨AÈ@,§?ÿ)§A+ 9"Ÿ7!¢<&ÀÉ¥ÿ@+ =&œ7#—4—4!–T ÿ0—3 —5"÷“2¥“3 ™ç9&š”@4"’û2 Hp.,ÿ‚!Šÿ)˜7%ž>*÷¥E1^`—6#œþh`<(©G4°Nï:¨F2¥‰'ÿ‚ Š' ÿˆ'”3#˜ÿ6&­H2²L5þp¯H0ªB+®ßF.©@(ºp®Eý.p´M6·Q;ÿ³M6§B+£@*š7!è`ê@up™;:&nP“6#ô‹`~Ó–<+–=+gÿ7$‰0Š2߈0…±P(?€&‡,õPFþˆ`03!‰ï+“6pP*”5{#–í 0/™`O‰*;€²`Ïðþ÷@8%˜8& ?ÿ+ž?,>){=)g`¡@,œ_`ÿ7#“/‹(ÿ“-—3£>)¦@,£<)pÿ¡:%¤<)­D-.†€©?…€-Àp«@ÿ®D-­C,®Dï.¨?(Ã@°G1ÿ¬B,¬C-¦>µ(°€©x€;'.0¡þ~€9%£=)«Dÿ0¬F3¨C0§¿C/9'ž7ß%“0‘Ëb‹)ß.ŽÛ*ÿ›:&¡B/¥Gÿ4§I6¬N;©ÿK7¢C0›<(¿–7"‘1ò€™üåpõ`3€"Šý)½`•1™6ÿ¤@*£>(™ÿ4–1˜1ÿ£=%®G/³Mÿ4ºS;´N6¯ÿH1¡;$7 ÿ›5 ›7"¢?ý+Þ>*?+í“ýp._P'÷(Ž0-~ÿ*€,})ß~*|)Uð|ÿ)‚.‰6&ýêð?/‹6'…÷0"‡°+Œ6ù&>ð¤!/€)7…-à!3"æSÿ‹01‘5û"û`9%œ=*ÿš;'›=*=ý* `œ;(œ8'ï›6&™ëp/ÿ(•07%ÿ :'§@,§@ÿ+¬E/±K5­ýEN0,¥=' 7ÿ «B+¬A+¬»C+ÃAA*¨ 6ß!4¤/`A-ªC.ªD0ŸRpú¦7N`$£?-¡¿?-;*ž05ý$¯`1!’3!÷•6$ñ’4#ˆöÎ0-`Š/–þ“ 9&–:' Eù1|`PªN;¤Hù40Ü`{nÿ "‡,„ÿ)$ƒ(ÿ‘6"1‡*ñ@8€Y€±P:¦þÁpF0£A+—5ëÓ=Ù™9%üG€ó@š=(™=)o•;( 0ÚPýˆú6%‹7&Œÿ9'‚0€.ÿ},}+1ÿ †4%ˆ8'Žÿ>-‰8(…5$þ°|-‚3"ƒÿ5%„6&ˆ9*ý~|à(t%lÿls#÷o{)uÿ!|(z$çƒ* l@‹0ÿŠ.Œ/‘2ÿ•4 ”1–þCp3’.–2ÿ—2—3–ü `x°3˜4¢û@+Ÿ@Ÿ;'¢>ÿ*Ÿ:&Ÿ:%«ßF1ªD- pªDý.L¥>)¤='ÿž8#¡;&¢=Ï)ž9%±î`¢@ï-§D1g0§E3ÿ>-—7'•7ÿ'‰,‡,í1@ ˆh/}ÿ%){#ü8 Ž0{&|'ÿsu ~(„.“Š!ÿ‹4!Œ3 Š0¿Œ2‹0žàÿ€/‚/=ÿ+J8‘=.†ÿ1"x"sý€ €'–;'˜ÿ=)˜='¡F1?–9$˜;&Üy`¿A.£F4`¡D0™<)ý0ý00öñ0“8ó1‘8&ˆß0ƒ-Ý ‚-ÿ‰3!Š6$„û1"$à}-y*ïƒ2"°€1"ÿv)s&r&ÿr&r'tÿ)q&p%ñ{ÌPQðgà&u'ïv% †3"ý…€4 ‚*ƒß)†-•7ý$pš9&•3 ý” @0™8#—¿6!“3•Ö 3ý qP¡B.œ<*öTp‘2·`/ÿ‘1ž=(Ÿ=ÿ(ž<'ž<(™¿7"œ9$žæ:õ&ë`¢ìa)œ9%˜5!”3”Ћ8& `—nÀN •2Ý#*‰4## €+݉ð€-Ë ˆ7ÿ'‚1!€0p_"n {Ðt:@ÿ,oh ¿j q “ÿB0‰7$v+ÿs(jt(t'q#;°çw'œà‹À9'ù‹År 8%Ž5#ŽÀ‡,ÇS ë0ŸÿD1žB0 C1kŸBhž}`>*Ð`?–8#™;'j`j`¸@Àú0k Ž4"• “ô_ á)ÚP„/{ÿ(t"t#ïu%zB°&uß&n!/àq$ßm"j” "ûr%+á},~,Ÿy'„< ÁÒšÇA.”q0q0“ 8$þý”5 “4 îär"’6@ †+o‡-õQ.g† 0zàÍwàöp19&óИ8%›ÿ:'ž>+Ÿ?,y _.Ñ)˜5#Epí•ô@3!]p—9%ÿ2!‰-Š/o*¬0y%Ó ÿw%~+uÿ$n|-þ#°B2›N=‡ÿ<+4$z0 ¿t)€5$ ð|ÿ2 €6$5#ÿw-i#l&ÿ|5%{2#†ÿ<-~3$w,ÿl!^]ÿ_ n{ß*„2#]Њ4s"Šä tÀ:+‹ž0ÿ/!ƒ+3%÷‘8'{A7$ƒ'O‚%® î•K€Ó:(Ó}àÀ0=ˆ„áŒ1_Pã°÷‰/vÀ•=*™ßA/8'IðŒ5ý%ð <,ˆ4$ÿ}*~++û~t/*ç,‚Á À3"‰÷1 [p7%–:9){ Ü`”7$vðåðÈwàs0ë0•ì` 8&žÃÐŒ5"ަ ÿ}(x#x"â²0\ à™=+¿š>*›>+Š ¤ÇF4Ÿ‚ N€>+ÿ¢?,¡>*˜4þó`’1š9's¡@½ï.“7a Ï%Š0 ;  †0þ™0‰5$…2"ý|m@+{,~þH D2–J9ŽBÿ1‘F4F4ˆÿ>-‡=,u-!ÿk$d­†ÿi p'qÿ's(y.ÿx-w*3ÿ#}/2!‚ÿ2"z(„1!ï‚/ ˆ 6(„s.Uð©ðŠ3#‹1ÿ-…+…*ü;PÇ114"ŽøB€@@Ð7#˜;'_”6"–8MÐ&ü €f ‘3!‘3"ל@,u –âp;'ý‹a0!ˆ/ ?(‹3!ˆÐÐëp;;)üp‹2 ‰ A ª²„3!; ^p5!&€—:&ðf c ¸Ê`k!3 Ž@@/õê †ú *„.y§ ¡ „.‡™ »3! 6%Ä0’æIÐ;)002 è£`Ùrp™éð2Ÿ.—5!<Ð6œ·;*ŸÌ°8(c s4#V°Ö0–<*Öðß7&‡0V@€ÿ.y(x(¾éàx&v'!}ÿ/t'r$ýr-à"o%eÿ |2!}3#ÿz0!r){0ü!®~2#q%p$x+y `ß8)Œ:*iЃ/ÿ })(ƒÿ-*†.Ç…,5Óðä„+O…(Ôà‚ðapÿ10‡)w…(#€/@ÿ‹.†(‹,ÿŠ+›=) ÷A.˜Ô>*3¦X°Žx7`ñ”ÿ<)—?-™@/ÿŸG5š@.—>ú~0,„ ˜>,—=*@À’7#ö@ÿðÐÜåj0¢C.up=úsP)a D/¡Eÿ1ŸE1™@-‘ît`<)–?-›ÿC0‘:'6#?Ž7#Ž6# á¤`öà2 Ú“6%”ç8$™Pð¢3#1‡(Œ,`3˜ðeÀ3!DPÚÿŒ2"‹2#Š1ÿ"‘8)“;*–ÿ?.œD4•?-ÿ:*8&‰5ÿ#†1 ˆ6$}/À}-{Î0ÿ:(‚3!‚4!ÿ1z-~2ÿ!u*g lî?à'tM 4&}þR@4%5'~2ÿ"„8)ŽB3ÿB3A2…6&ï|,Yð3%‡ÿ5'."~)ÿ*€*„+‹0!4%$u˜%,çp‘2 — ßž?+¤EšP3£¿C.š:&——Aþ •4Ž.”vrà7#a`œ=)ö@w‡+PP$çÿ“9)Š2$59&UðS†-¬ wá:pãñ.€gà"”4ÿ“2’2•ý38p œ:% =õ)’P¥¢°A-™;—&‘3pà`ô@:ï(–>+µ •<*ÿ™?-˜@- G5¢I7D20 $1W5#óßÀsðÑàâdÂ"‚ðM@6$Û‘7=@#Œ•`7'ÿˆ3#Ž9)Œ6()Pˆ1"s¬‹z!P6«ð&‰3#Ú@ç‡3#|"Àƒ0îMà.À…5#ÿƒ5#{.s"v&|. "Pÿ{. y-s'ÿy/!z1#xÿ. z0"{1#÷r(7Pw-wß,z,´v)ûwÙ02$0"÷ƒ0"Æ-„,Ï’8'’@ã›@O-™>,'))z@ù˜õÀ× 4•5 íšÓ 5"Kp˜7$8šPw@xp¢C/d`‚ð?‡*ˆ+ûPª@gš>-ðpê1<)q:Ü`›<)_€÷¢>)Òp¨B.«ÿF0Ôž’±K6ß­G2¤?-‘˜5níÀ–5±`“Æ@'2 Ž(1‘à"úñŸîÂ9&Î8%ß9&’:'Î@’9Ðfð#1¤Ä”Ý`8%þ?`‘9'’:(ß8(Š6&r{)ÿ€/ƒ1"…öü@4$]`ˆ5&„ÿ/ Š6'‡2"ÿˆ2#‡2!ƒ.Ú졇Ôð8'o0šDÿ3™E4žJ9˜ÿE4Ž;*†3#ÿt#‘=-†3ÿ$u(q$jÿn#x+ÿn"o$o%ÿq'r)hÿ g` ÿdj"l"ý½`w-!}2%ÿ„7*€3'}0ÿ!{,t#zß)ƒ.i6=$Œ@“:&”ó€û {B. A-ކð)Œ-D€HpBÒÿ†&ˆ(Œ,‰+Ð``š“@;(™qPÝL ?,œ?,¤às V@ðÙ#@áp‘R!–4 ]žÚ8$Ÿ«°*#“ÿ6!11í…!p)”€„&ÿŒ-0.ýˆ Œ-‡*ÿŠ,/‘4a ›àåñ¥àî0=+jÀ4#î €QàBÛ‹/„ð-p7"ß–:%‘6Ì€ Œ©0ÀÀñ€„} ,{…ð°.Œ5Hðù!ÀнÑ7%‹8&÷Š7&Èpƒ1 í/À…Û:(ÿ;+;*;)ï:)‡ À9&‹ÿ8%†2!…3!ÚJà|Õp+Z`‡5÷%ˆ5D#½ˆþÚC’<+’;+—?/Ž6&‹4Wð߆/Žöp7&Òo2'ø@€{‚Ð%þÝà€+—B1•û@1œ`Ž:+”?0:+†1#Þ0ÿw!sv ïo ½v"ÿ*€,†3ÿ%|)x&øØpgÐJ -v&2PzÒp8À/´ÐfÐüP€…0‚+×~'æ°‰]°6#¿œA. E/— ™Ã<'V@z@ô ÿ2ÿ‰+‚&‰Û,n“7a'’ß5"‰-,@‡+½m Œ1‹ñÿ‰/Ž5"Š1ß‹2“»Ð1ý5#ˆ/ÿ8$3!‹3ñ$ .`.`:'“-Š5í$ÂpŒ8Ù@";¿(Œ9&Š6Hñ÷;(Kp9&”>ÿ,•=,–>-›£B00’@Ë@ŠÑÀ.÷‹/o /Í‹ð .ÊP*04Ï$6%êà°(ÿz"w yÿ"….’<,¿}#}$Óð’ÿ9)›A1¡H7ÿ›A0–;*5ù$QоP˜<+›=ÿ+–9(—:)œþ¼ D3 E4œCû1íp-ƒ+*7À…¨p.½ð{`9—Ø G4€ÀЕ…÷/Œ{à9$“<ÿ'™B-œC.˜ó<(ùÿ3Žÿ1Ž0‹-×0ÖR-åÀ*‘:%‡ÿ0„-‡0!‹eÀ.`Ca/`#gðe¡¶ 1 `’6çð'ÿ›?-ŸA0š<ÿ+•7%0«/h%]ÀÑð+Ýjð†*‹ Š.õ×àŠP*$ï‚(åðŒ/Š-…)‡h°ñ,Õ±ö‹ Œ.“}5U@&Ÿ@.RB0Ä8&×ZÀì 7‡,Q0‰-‚Ae Ý“05"…óà-í‚è.€ •@,ÿ‘<(–@+™Cÿ/˜A.ŸH4’ó:*Ðð5‡.Ç?—Œ˜=(–†°àï01üP š:ÿ$ ?+Ÿ>)›÷9$šfà3–4»™æ€4 ˜Ãà2½bp•3‘*Ò›û9&2Р>)š9ó$˜ŸàfÐ9#œ<ß'Ÿ=)˜Qp:&Ê­à–iÑ%€ÐnàŽ/Í\A4\@2Ñ?+ÿ¦F2¤E0¡Aï,œ=(§Ñ<(œÖÝPE0¦P¡Œ°>)|‰Ñ¡€02Pÿ¥G4¦H5£F½2vðŠ,Žl 2å µ€”:`Úð;*’s5%dñ§ð1•~Ðÿ;)œ?.¡C1ÿœ?-Œ/„'‚&)@y ; @÷‘2`ˆ)‡&ã(Š+ŸE0`þ,p˜9&¡A.›ðºàë0C`c /˜8ü„P|Ð) @,™9Ï&–7$'1z°.þíÀ†,*ƒó,³~`Š5#7$ˆ4:îpÜoàC@‡.ìï33ù€‘4ï—8"nП>(ÿ;&ž<&£@ù+ÜR>)›6! ÿ<%7"›7!¢='Ÿ:%£ÌÐ÷A, ƒP3“.ÿ“.š6 ÿ9#¤>)©E/ÿ¨C.©E0§Dù/Üá®Ð8#–3·—4ëá:$ßP¡û=(ßà¤@*§B÷.¨DäP1¦A,ÿ¦B-¤@,¨E/«G2§C-Üà—Ÿ<'ðŸð¼àBÿ.©J6¥F1 »B/ü0ž?,8q; ÖÁAßçöÑ à9`?‘5#˜=*¿@·À/‘3 НÀ/¹Àü.p?á†#+þh@‘0<(’ÿ1 Œ+‹*„#‰)ŠB ÿ(‰),wŠ)@Ž,Ãðÿ‘1—6$¢Bû/£ÙðC0¤C0- ™@B.çð›Hp@o=)6î@ †z ß1:&Žà‘<ÿ'’<'”>*—ÿA-˜C.™B.Ý’6 ŒŒ€4ÿ˜>) C/§Iÿ3£F0£D.˜¿8"–6!’žà*ÿ’/“.•û/G0œ5 ÿ¡:%¥?*©Bû-¨+ð>(¤<'ÿ 8"¢9#§>ÿ)¦=&¤;%Ÿ÷6 ŸÎà24ÿ 7"š3 ü9Ði@5 Ÿ9$¿8# <&¡Ôà*•<(ï7$‘@`9%Ž}6ˆp 8#‰€ç7"‰€÷ð1÷5 ˜@ðA+¤Gÿ1£E/ A*Ÿý@vÐ"—6 ›:þœP!š8" >(ÿ¢@*©G1°Lÿ7­I4«F2Ÿý:š4"6$ÿ 9'¡9'¨@ÿ+¥=)ªB,«ÿA,°F1µK5þî®D-§<'¢ÿ8"¥;$£:$÷¥<% ¢;%§Üð¡@)¡c=&w£?*Üà§E/k@mšó8$}ТAê!¾â =*Ÿ>> +ÿ¥B0Ÿ>,¢A/ž>,ààRà“ƒ3 ÓPYpN ך £ßE2¡B.aà—7:%¯°¢@-Eðñÿ2Ÿ<$©E-ÿ¬H/°K3¥@ÿ(—1¯H-©ÿC(¡;!•/ÿ‘-‹(ž<ý%®  @*£C-™:$’Ð}@ Ù µ°É•o ÞÑæ ¸P’5üèÐcà%˜:(’41"ä 8 ¾?+!Àü`·“9%s™=H°,A,‘°‘±øPT@Ôß=(ŸA+PžAÿ+œ<&ŸA*¶6Ð<%¬à1+p÷–8"q@Ÿ?*¡ã?+¤ÐwpÙPž<)—5! 0ª°o@fp¿6"ž8$ ´Aû-¬ûà@,¥=(ï¦?)¢ ;%¥þû;%¢<%¡;ß$¦A*¥r@@*o¢?*žxp:%8Ðê8МZp8$—7}$ÖPœ<)>šÐó-™Yà¿€9'™7q$³0ÔZð=+aà~Z ’2‘0á ë•7‡P$Òð‘2Ù—%À«06"¥ð“1ÿ-œ9#¦ÿC,¦A)¨C,ÿ¥@'¥?&©B)­G-´N4Ÿ ?ºS7¥?( úPÿ‰'–5’2ÿŒ-˜:$…2ô Ì «ÀÀ²P}"%‰.ó€"3#‼@ããð{ðÛ ìõš>+›¿@,˜=+”s <Ï(”9$‚@”:ÿ$—;'˜<&•»:##‰/ Šï0Ž3´€1þ¨à 2—:$õž8A·@,›>(wš<'°Ð?*}p§š;&ÖP¨ð˜[À3o™8$_p; ÿ)–3!˜4!•í1OÑ:ºà,¨Då0'ð¤8( 6!—û3Pš7!™61 +‘PÜ@›;Ðÿ!“3!0 ‘û3"C°œA0AË/˜íÑ#ì °œAÿ/š?,“8)ÿ2#‹0!3#ÿ—<*žB/ŸC³1ŸÛ ¼°<)»P›ÿ@-¤I5¦J7ïŸD1›0;'”û5!/0¡A)ž=ÿ%œ;"›9 ©ÿF,§C*±L2þ–PµR6¬I-­¿L0­L2¥‘PIÿ0žA)£F/žïB+–:½€"‹0¾ä°‘6"Š p.~ràˆ/Œ3„—‹2 ã¡1AP/`&o‰1!‹p`0°þ`‹4"Ž7$’ß<)8$w ˆ/І.ú°—0ýŽÐ9#š?*›ó?)0¦€’5 —>Î@>*¢C.#0ò0½–æ€7!1ß0!¯Ž.Žæà3QàÙ”[ Ñ;'M0¤C×/Ÿ=%0(à.ÿˆ'‡&Ã-UàM07«Ñ&œ:„0AÄ/¢DÝðqªYp•"P5/P&Í€ï1!5%8ÿ(:)†2 ‹ÿ8'†3#‰5$øW¡pªp†4"“@ÿ.”@.“?,’û?-B8&’<†/À(Ž0.À{¡aŒÐ¶€†°Œ@œB=p'ï@)@¯Ð%¨Iÿ/«L2²R7±ÿP5«O5š?(ÿ—<%68ÿ!¥N6§Q9¤ÿN7žJ2Ž9#ÿ“?(•?)-ÿ}+t"v·$…Ô€7%Lp~ÿ*y%y$Þ¡pˆ5$…Ûp.¿w$t!€yÿ&+ƒ1!ç|)­p› }&Ï}'~G@3 :(Ý–³°@+˜2¡C.°Ðœ='¦p=þ³à<&›;%•5 •'`2M`¸põ0¿›<'¡A-9 œ;'š9'’2.Ðó'•KП`7%‘2r`@"iÀ‡ð–8'ðÜoðéŽ2éЗ;(€š?+0@‘/7#•9ñÑŒ|Àepû)Xp~)},ÿ~- }. wÿ(r%lÿn#t(w*ÿ€4%‡:+‹ÿ?.B2Š>,ÿ‰<+~0w(ÿ|--‚¯2!ˆ6¯¡† 8þ² $9%‹6"ÿ’<(•=(”;ÿ&“:#”;$’ÿ9"’:"œC*ÿ˜?&C*…0ÿ„/‚-“ÿ>&¢N5¥R9ÿ¦T;Σ•™Hÿ0’B*Ž<&†ÿ6†5ˆ7"þr€‡5"ˆ6%‡û6$!ƒ1},ÿx&z(wÿ%v$v#ýuè€$t"{ç)a€R/€ÿ-€*€+ÿƒ+„+…-´ó±øÐì°6"  £7C/¦(ðF17ÓAØ6Ð5à-Çq;(ÿ§G2¬K7¨Hq5Càä µ°—8&iÁæƒà.5 õC0×™?.4°‹ú*]†_p/„°/`«Œ=Á%“ýQ%Ù‹V± 4!9Àˆ1ÿƒ.„/‡ÿ2"…1"„5%ÿ|,s&n!ÿn p%{¿- †8)…Ã9ÿ)€3#y-yÿ,t&|.ï~1„á <)‰þ€;)‰7%ˆ6ÿ#…2ƒ/ƒ».ò…2{€‰ÿ3Ž7 9!ÿ9"šD-—Bÿ*—D,˜D-Šÿ6”>$Š4ÿ’;"—A'Š4ÿŠ4Š5ˆÿ3‘<#“>%ý•— B*•A)•ßA*;&F 8×%‡4¾`%apŠ6ü²`(‘;*Œ4ß$‡/†e°%ÿ„+‰/ 3[%•n°<*éЉ¬Á¯Š-^@”|ð9ÿ'˜7$•4"•ó3!Ý1ûp6#œ:ë'ž@6±!”2ݤ0¦C0K ¨G 4N š9…`´±$PoÀÿ„%…&3ÿ!—;+¤I8›ÿA/‘7(6&ÿƒ+7&:ÿ*‡1!‰4#†?0 …0†þ xöÚ°4!ˆà‘<)”|ô °>+’;(çPÿ†0…-….ý!€‰4"‡0 ÿ*€',ÿ‰2#ˆ2"ÿ8(…/(ù‰·`e@:)Œ7$þK°….|&€ü&à6#•=*—ã@,Œ‘ça–q›C-õ˜­@òð%–>'ÿŸG0™B*Eÿ/¦O8˜A*ÿ9!±R7¯P5ÿ¬M2«L0§Iÿ-¢F)–:–ý:úÐ’6—<¿"–<$˜>À"×4õ`RÀ4ü±a€(ƒ,‰Äƒàsñ#ÀûÐð —9q&œÀï0‘ –7#Ô2ï”3=ž=)·£A-¹-¡05³#•€8à0Å0“ù1”Ð&P 0“¬XÀh5"Ià¢F A/™;)•6%½Àõ—ë ;€&2!¿‘8(Š2!E±*ÿ}'ƒ.Ší6»a‚0Ô€!~-|*x&ó€ÿ{).…2Iü€c°‰ÐÜÀ2„õ"€Žhâ“6%”¨Tè°'À6@(ZP¦ÿI6¨K9§J7^¿À—:)“á7ZAµ˜ç9ã &˜-bŸ¿A-š>*š€;ý%àÀœ?)¡D/î0›=) `‘5!ÿ˜<$–:!Œ0ÿ–9¢D*«ÿM3®P6¥>ÿ¡:´L.¯H)¶O1¼U7(Ðû²MÆ/®K.¥ïC'¡Bp% Cÿ*ŸB)œA*›ûA)‹@Ž4!‰1ÿ‰25"Žÿ6$9%8%wŽ4"€5"\‹/’6#”ð0Üs"À˜7#,Á4 M–Œ 2ÀÀ“ibù•;à*”2"•4Û#šê5"ó°‘4îÐÀ&™>JP'4ÿ$(€(…ß,‚*E°v$ÿx%z*ƒÿ4&Š7(/}+osñ€ÿ,y*3$ÿ2"z+€/ÿ†4#…4"‹¼åPÀ`4!Š5 "þ_ÀŠ2‰.‡Æ:°-gà¶À­À—99'yÐ~ð–:(cP°Àp0Ž@]!TÀ2 •|€2ß@º Ëp8žç='™Ÿ2ià¡A*ÿ ?(š;#œ;ÿ$™8ž=$¥ÿD+¬J0´Q7ÿµR7ºW;µQÿ4¥A$«E(£ÿ:§>"°H+ÿ­E)¿W;±Jÿ-¨B%±K.¡û;–àªF+¥Cÿ(¤C) ?%œß=%’4©@Š.ÿ†+†,„w,†%à3 ޳Ð}:0#Œ3 ‰Yƒ-ö °À_ð”37"È0Hðœ=—aQ ˆ*  ÐÄ •Ü ˜ úP5½#ó°Ž3!‰`-õÏP‡¬ð6&‡2ï#z&Aðrÿy&,y&ÿ‡4&|*}ß-‚1"Vð{*·.Ô€"~Zñ!ÿz(v%x'Ýwð…3$¼`„0õ È`„À0 ‹3]!ƒ‰0gÐlþ–ð1 3"Œ1¼)àf@"“6"yКs=*6PPÁ:'–Q‹9%Æ ˜î v ÝA¯-£E0’` N0=ÿ+˜7"Ç“‰•ÿ5—6š9#þuà >'›:"™ß8 ’1.@š8¡?$¤A&ºà¿±M1²L2Ÿ ¥ÿ>#ž7¢; ÿ©B&²K0¸Qÿ5µN1£<$Ÿÿ9 £=&¨A*ÿºU9µQ7°L¿3±N5£C1`+ß›=&“6(a3'‹/Îà#቉ «ñ÷!4iŠ-Žû0XŠ-0ÿŽ1Š,‹3,=@^40%ðí"µUï<¬K2P‹'ÿ•1™5¤?ÿ#©B'«H.œÿ9Ÿ<"™6ï’.¢‚à@%£ï=#ªC &¢<ÿ"¦B'¨D)«ÿG.¨D+¨C+¯¢@(¤ AC0)îcà™8# Ð“2ý+,‘³/” r œ=ð"ß@—07#Ð@Ýð@ØvÐ@a3u !Œû5#Þ°+…2ÿ!{*x'wÿ)y+{,ûv(.!n"r%ÿs&m pÿ$q$t'ÿ2$€2$…7ÿ)‰:,€0!†ó5'åÐgp…1!¿)….†ò.‰0‡-€¹‘ïp«À7&’×@9Û(•õp5$à†)oŠ-K5#ÚÀ?2 Œ/РKc6%»ÐvÐÉP…*Q@±íàÞà‰0 ü\–;)›A-ÿ G2›A.“;'‹2‰/H÷ƒ)Ô#Ž2•ÿ8"—9"=%ßš:"¡?Î(§ßD,¬I0Â$ÿ/•6®ÿO7­M5¬K3ÿ±P8²O7±Oÿ6®J1­G.¤ïA'¥BÎ&£?÷%¢?g0#¡;#ÿ¢?&¢>'¢?õ(›0™<`4-]šÐ“2Ý0 ÀþäÀ@+Ÿ@, @-ŸA+¬pÚÀ˜`‡™<(ð°ŽÞPŒ}2éP Š3!ˆX°ÿ0€+x$Þ|p{*‚OP:+ÿ†6'ƒ3%{+o!w*¿ÿ|-!z, jûk×0~+û„/ˆð Š4%Œ¿5&8'ïp7Ñ%§ðg@­À–×p6$—Å“‰ßP °/¶!–ð2@”ƒ6$@ýpPÀÝ  Œÿ2Ž3"4"ø'áäá…+£(£n”Ë@@q-äà”p0}%ÊÐÿ&~'ˆ0¿6"5[À#6!6V@¸À‹ ÷!2D†*ÿ†(} –=ÿ(ŸG1“:%”ý;€"%‰,ÿŽ1™:"§ÿG.«J1¤C*ÿ£A(ž<$ =%¡=&ž:#É@ÿ;$;%,•0À.“1Ï‹*š ;À—6$Ä  QTg°'ðÚ 7Æ·p#“˜ «ðU@6$§›<*Måp“–À(ÿ€"‚'ˆ»)s‘1Ê¢ ps°ÀÙ Œ “7%§Àô,ò‘Š„P1œAó-“Àí`6#†,Ÿ•<%’8pŽ#ÿ5’:$ƒ,ÿ‡0Œ4™ÿA,£J4›A*ÿœ@* C,—:þÊð#”5.ÿ•4œ<%Ÿ?ã(ž÷ï@ã‘1Ý"0’3|0ÿ‹-Œ0K/ B"\P€ˆ:°Ã,ÔÀÿ°ñ8#ý—_1 —5!›7ß#Ÿ<(¡@;'ÿž:%¢>)Ï™ÿލC.«F2¦ßA-¤?+²`¦BŸ.¥?,¢·PáP-ÿ‘-˜2!œÿ5$¡:(¢:(ÿ˜2 £;(¥=ÿ+©@.¬D1§ÿ>,£;)¤<)ߣ:(ªAäaªB-­D1¨@-prÜ` †0P1šP{4"À”1•Á; É 0ŽØ 3ÀÒÂq!ßp£ šjâž<ÿ(›9%›8$Ÿ==±p(Ÿ>*]à ð‘0Š(„WPÿ(†%‡(w.Ž/ó°á”†ÐÒÀørŠ/ç—=(ư¥@•>)ÿŽ7"ˆ2’4ï @+&P‘4ÿ‰)‰+’3ÝZà©I3´p£BÏ,?(:`O`•3oœ<&rà›<âÀç(˜9(ð @"“7Nƒq‘‡žð€!8QÐ 5 ‡-öqW+Š j`‹:ꊰPFà7!œÿ8#ž:$œ7"ùŸpà›`;&¡;'ÿ7$ž7#œ5ÿ Ÿ7"¡9%§û=*ýa>,°G5ÿªA/¦<*©?û,¤Òð7%¥;(ÿŸ4!¤8%«>ÿ,«>+´G4±÷E2²l‚®B/©ÿ<*¢6# 5!ÿ¡6"¤8$¦<ÿ(¨>+¨=*¢¸FàXà’Ð1—ú@8«#š:q%5Ó’Ð5í"/—5„Ð"ž:þ€$¢>*¡<&¿š6 ¤?*`¤¿@+¡=)œ­ 1ó’ 0!À.œ8ï$¢=*Bpš8$Í‘Ø .¯ ,ž>õ)P›-€>)œ>)` B-2Q’­ÿI4°L7¬H3ÿ¤@*¥A*Ÿ;÷"§B5¥A)ÿ¦B+¥B+<¾ À'œ:%“!À1û’ÏQ™8$œÿ<'›=(˜:%ý•bÐ5!Œ1Šÿ0†+„)úRГ´ð@,ŸD0 <à?@’74Q¤ ²Ð~ð™7#:&æ€í›Ÿ€4  ˜3ÿ8#Ÿ8$¤>ÿ)¬D0«C.ªûB.;€œ3 œ1ý}€¤:'§>+û§=Ì‘¢8&ž4ÿ! 6#2 žÿ3!§;)£7%þz€¦9'2ï1Ÿ5ÀŸ4ý }€£8%¨<)öŒ€©@ê`'¢9%ïŸ8%›¤ 6#›öú3© ¡=*£n  A,šáÀ:%Bp¿ >)£?*© ?;%¦=(§&ï`ê ¡&¾£ØÀ/‹ÿ%’*‘)ï‘*žS5"šß5!¨B-²`«Hÿ3­I5¡>)–ÿ3Œ()üÈ€[0©E/µQ<÷²M8 ±M8 ÿ3š.Ÿ2ÿœ0¨;$¸Lÿ4ÃYAÎdLÌÿbJ¾U=¹Q9ÿ¯J3§B*§BŽÀ`% <È@yPÂ@'Îp0›:&Àê@—8hòµð(Qš}7#PüA¡Ð6$œ?,›s?+Ž0×À”8$‹Ðr¦Ð’Û€V`2š˜`¿;'£?+¨¼`@ÿ,©C.§@-¢ÿ:&§@,¤=*«C0¯G4©u€ÿA/¤<*¡8'מ7%p™(à,ÿ”.–0™4ÿ$¦?-ªC0­ÿE3²K8²J7úh°©À8%œ5!¿ 8%¤;)5°§&Q€=)Ö`/€›Q°¡ÎQ°5" ú2ØHp0 0 ¦EÅ1©_F2§D0¬œ˜`ÿ:$ 8#Í•Šÿ¥=(©A.œ4ÿ#–/!Œ%ÿ ˆ‹"ÿ‘)–-œ4¿"¨?+¥<Þ`(÷«B-õ°®D/«ÿA,¤:$¥:%ÿ¬A,¬A+«?û*¦®°:$¡5ÿ¢5°B+®@ÿ)¶H0²D,¯ÿB)´G/±F-ï¨>%¦Ç 7¤ý;³,³L5µOÿ8´O8¦A+™ìý¤4 Ï ¤B,o¥D.¢w?)Ûÿ–6!“3 ‘2’5âP–uÁ@v=‹mp1/^P/pÑ OŽÐp—Î`7%Ï9%¢ï`äÀ:'zé8 $¥>+¯Àwœ7$Ù`—2 ¿‚ÿ, <+—3"˜ú¹Ð0“Ð!š8&™ß7&Ÿ<,zPŸ;ÿ, =+Ÿ;*žû;(¼€ <*9&8%¡<)ýÀþúÀž9'š4!™{3!¡€Ÿ9'œôX@ PÁNÁa0ø€O`0rœ"ð!–7£P²€#Ÿ?Ñ-˜œP Ðñ½#ŒPœ:(Ÿx€>ÿ,¬H6¨C1¡ï=+7ºÀ#”.ÿ˜1!4$›ÿ3#«A-ªA-ÿ¯E0°F0ºNÿ9ÁU?ÀS>¾ßP:²D.À®Cÿ.²H2·L6»O8·L4²H†Ðÿ.¬B+ªA*¨ÿ?'¦>' :$ž8"œ6! ¤`»<&8°£>)£`›ƒ9#làEp¼€BpNp »>*s0<*š ð†7$ PŒPö@‘’ò‘P%p0]Ñ?,¨C0©D2«E2£Àh¯À/€ p£ÍÑ*¦„°ÿA-§A. ;(Æ¡7&pèÀèÀš7ÿ%”2!+Œ)-˜6Apß*¡>-£gÐ?-Ëž><)ÙÀÙÁ6$ç™7%q à8%™ „ãžÀ:&! Npð=˜pÐ4 2 ðW`©#a8ëP g`ˆÿ,‹0†,ÿŽ6"8%Œ3ÿ$ˆ0!…,(‚(4ëPý$† ŸC3–9(ÿœ=-š;).iíÐ_à£9à=*¡€úúÂ(e°°H4§?ý+T ¤;'Ÿ6"ÿ¥;'©C/£<ÿ'£<&§?)¦¿>(©@+ª8=¿&£;$«Cü`.ÿ¬F0²K6©Bã-¥Ì€ü€ 7#˜ Pq!”îAÁ€POØWp›Pó*™Ð:(zyð— á':(QЩ˜Œ03€9Ë@'ûà û=)pŸ;(¢>ß+£>+ ìÀ9'ÿž9&›6$ :!'Ð;à£À£Àœ³ðpÝ:Kñ¥?-¦ð¤>{-¡Þ 5$–1™Áä_°ôÀœ¼¹Á%™5œ$ÐРаðòðŽ 5 š àô@’`4°TñùWÛp.&t*E}À4 ŽzÀÿ7$‹4"‚+ÿ€)|%x"ÿz$~)ÿ,‚+„.¿‡/ ‡.`†í+i±Q&1¶—8¾P"œþÀ@Û-–«P4!d0‘/ý}PÌ—ŒªF3Ï«G3ŸÕ€1 ;&ÿ©E0·R=¸Sï>¼VA@ð­F0·§>)8€¦?ŽŸu9¹(»À¢@-BpNs0š:'[óšïÀ;>,sðœ=+#PPí’áP4"ð–6%8öЛPù—6%‘éÀÿ?-¢B-¢A.£@/¤fâzP à¼UðMà:'šý 7ÿ&–0 “.˜¿0–/³ð8ø!ð‹± Ÿ8&ΕE‹‰° дPƒ`3ÃÁ6—`ž8üñœ8ùÀ±ð1# ¡€?pš6»€T0ý)Ñ€¥C/¦C/>šð¢@+ ?0B='ŒP”5 ’k0âó1lpÛp2‘þÏ ,Š/–:ÿ+•9*•:)“ÿ7'Œ1!Œ0!ß‘5&ˆ+Àƒÿ&‚%Œ.“Š,``„`( eà§ÿG5¢B0=*ÿ/-!ÿ€‡'–ÿ6&¤D0§F2º@™ê€A.–x°?÷+š;gP&Ê—Œþœ¤B.«I5§ûE1 :'/Ù’°ÕP2xq8%‹0^3!‡p¿à+š>q+É0>P”9'^ v@‰-{a1l'‘5$y"à0&s…Â8P’Á0 Aœ!àP1A+/~p^ p ˜€?Pz 2€à‚à½&é€8'¥öà;_)ž6$¤Z€5Ø ="\€3 Ô#æ…9Õ!ž‡œ°]@€;w&¥>'ñ¨@+(ð¿£:%¤<%1ñ=í'¯ <ùÀ$Ê”Š™]@8$ž°©i ÷œ4!N ±H5µ;M9¹@´L9Œ°Á`ùŸ}ðô0,ˆ$ÿ’.—5&®Mÿ=´SB¯N>¨ÿH8›<,œ>.û˜: P'0 †÷+”óB2¢Hÿ7œC26%Šÿ1 &)÷…-P‡/|ÿ)z(z)ÿƒ3"Š9'•Eÿ3—G5“B0›ÿJ9”B1Ž<,ÿ}- x(z(ÿu#‹4&Œÿ4$3#•:(='A ’5#ÝPÝP¸³PªPŽ‘3˜P›s;(’P0—9%x”\P77@£QöЂPØ á á ð ‹À‹X  ©PÛ€O06†1‚PrmÐ9¾€&Ÿ7н&Dœ3!ŸXÐ3ŒµA ð§,ÁÀ“.•1ï9(cЪG6ÿ¯L< >.›9¿)œ;+š:t1‰ÿ+}|þ×–;-§N>œÿD4’:+9)ÿ+<,“?ÿ0ƒ0!„2"|ÿ*z(jÿm"l!x,ÿ4#z-€ÿ1"„5&0!ý€µ`/ /†ÿ2"‰4$‡1!?‹2"Œ2!lj —9'ùЛæ ñÐmÐÌtP$à:'' ³°«Gï4«H5'0£@-`' šðôÀ °ëð™7k  ¶€™7 Ò ï€RÚÛ “.08&ð—7s&˜RÔyà&“2–Àÿ#Ž--”ÿ1“/–2 ÎÁ ¡:'Ðð;°©?r.°,Ö ¬˜0S°{š3¦@%¤>*`Ú˰¥VÀ<'P€°Hÿ2±I2´M6°¿G2ªB,¦ 9¥#B ¦FÐõQ.D°°÷H5±o°F4¢<ý+¾ ‘-‘/ õ™p.ið#-ÿ‡(-Š+þ®P!›=.¢D5¿ C3—;+Ú’ÿ8(“9)“:*÷Ž6'Îà9*‡ÿ2#.y'ïu#|g6(ÿ1"|/ |1!ÿu*p%w.ï €7(€†<-ÿƒ8)~3#„6ÿ&†7'…4%„ÿ1!€+|&ï†/‰ô06&ž÷B1šKà:)Ÿ=C+žN@Ëð¶ðT@9”@ï)¥?,¦À 9%Ø 1lZ@9$0¤=ó'¨*°6à@*¤=³(¡z1©Aà-«­Fà0¯¡¢6õ#Î@š1’-ùK0W0”0 ”0¯“0¾ Ÿ·q(…ðÇP—3#X€G@X™9Ò€ÝÒ:'»ÀE0›¦°ð8%•¤¢ðA-/$  =ðÀ™‘ ñ›=)³°¥@D0Û€&Ç•0hG@ÐÀ’/ÿ‹(Œ,‘ÿ2!‰+‹- ÿ‡*Œ0"˜=ÿ-6'’9)ÿ4%8(–?0ÿŠ4'ƒ.!qÿoz'xÿ&-l ÿl o$z0ÿ%ƒ5'y+tÿ(b hÿs*o&{3ÿ%x0"n&}¿2$x-y +û~ö@5%ˆ7'ý~Ò@4$Œ7'ˆÿ1!’:*‘8'ÿ–;*£F4ž@_.¤D2œÚð8”àîðÁ¨B0ðªC/ð`m€` `¨>)¬³C/E (ð§?|p) ˰‰°©A£p!ñŰºÿ¢:%®E0²Hÿ4°F3³J5§ñ>.áµð²€*‹ÿ&“/˜5#ÿ©E4®J9©Hï6¥A1l0š:*ç˜6&ˆP0?—9(Ÿ@/eàkàn‚P“2 ¯ /¯O"Œ/¦! A#ÿ0‡—;(Ò0U!Pq 6ù$Û0É0‘5%3ý#Ã0˜;+A0ÿ¤H8§L;ŸDÿ3D5“:+Šÿ3$‰2#…0!ÿƒ/"€,w%ÿv$x'vÿ'~0"{- wj¢`d Ÿ`ÿu)m"3ÿ's'u*{ÿ0#s(q&ÿv+z.!s(ÿx. n#hÿk!l"¿}3%{)“`‰ÿ7'‰6&€,ÿw$v (ÿ†.†-ˆÿ.$€$ú5@•ú6$˜7%í(+†àŸ;)_¥@.«D”p0—€ë¥=ø*÷P°F2¯®E1¨˜€?ˆ@*î·«B.ü¤<({¡86À$6! 0îVp5#E`£<*ÿΗŒ¢:&”.’,‘,²ð¿§A/¦A0A ¥A/Ÿ<)Ê€\à8 ÿ.‡%‡&ÿ/ —7'¤»F6éà•8'’ Šÿ.–:*™=-ÿŒ1"Œ3#†/}4²„-„ë0÷3"Ž*pA/—Bÿ0’>-–D4{=-%°z+uÿ ÿ(o#0$ÿ‚2%ƒ3&†6ÿ)u%keûœ`in$ÿhj"nÿ&k#v/$ÿo(k%e ÿ`f!rÿ-!}7+~7+ÿq,#k%o)ß t.$wyÀ-#ÿgY lÿt&z+ÿ1"y(t#÷w&@€‘:)ß7&’:)œ0–=ï,›@/ÃŽ2#ÿ‚&…'ˆ)ÿ’2 ”4!‘þlp9&¡?,¥Aÿ0£?.«G6ª{F4à®E3®—ÿD1±I5°I5ÿ©@-ªB.¨>!*‚€`‘€ùÁ8í ä {&¢Ù‘.­F3àlD@þà’.Fp–YPxNp› bñ•3"ͰþTЛ:) @0 Ó@/é@Ù°—X8'ß“6%‘4Š "”û9*œ0Š2"„+ÿ‚*‡/Šÿ4&†1"‚/ÿ-|*y'úEPÑ w&€-ƒ2"€.º`¿„3$/ •Ð}ÿ.{-}. ÷~/!Ú x*vüDPAP-!z/"~ÿ4(ƒ9-|2&ÿ7+r,"j$ÿe!h$lÿ&d h$ÿ^ad!^bÔÐÿg!w1%x1ÿ$€7+…-} ”7&‘ß4#4#ãp’7ÿ(2#~%ÿ&…, „,ÿ‰1#z'{(ÿ}*†5(Šû5'tÐ}*oûtí - {)ÿ„4%‚1#y)0!‡7'1€?‹;+‰8(%P«ß‡5%†4ð$€>œÐ',tРÿ:+ˆ4%}+󀀯 0#~.ÿ!{,w'sÿ$s%i÷m €y/$…ÿ;.}5(y1%ÿn'_n(ÿs,"s+!rÿ+!] ^ ÿ]w(€/ÿ!ƒ1"‹8)ÿ8):*8'o8'‰x 5#É0÷—/w@Œ#ÜÎ W@5"­øP=*Þ®ðª?,«îÀA.ÿ³K8³L9¬Eý2Eb :(¤?¦™€2¤¯À@,–àÙ•…÷4#ÆÀ’0ÑǰÁ°¢ÍÀB/Þˆà¡=+¤A.ÿ¨G4ªI6<ÿ+ @1˜9(ÿ2"•7%Œ1{Ž3ø0$‹/“ðÿŠ1!‡0 7ÿ'Š4$~)|ÿ'v!}(ÿ€+})Š6ÿ(€-/!†ÿ3$}*|)ÿ. ƒ/!}+ÿ/ x&tÿ"v$x&î’Ð…3$½`ƒ0 ¯ƒ.†Í`6­0'¿….‹4$•†Ç.ŽçpHÐöG5ÿœ@/¢D4œ>->. A1ï@?¢C3>-¬àO€×”4"ò—¸0;*îâ°3#F€–<-ÿ•<-›B3¢Iÿ:6(3%…ÿ){‚$çˆ*t Ù°›;*þi0¡@.œ:(¦vùC2[°°I6â ÿÀM9ÆR>ÂMÿ9»E0³=(©ÿ3¸A,¸A-ÿ·A-±;'«7ÿ#©7#£2®þ`9&«>+·JŸ8´H7®ÖðY°=9,Á G@¢?.Oà¾!ØóÈ Ñ€9'Í€ <,¤B/¨D3A¡ÿG5¥E2¦D1™žpÓ09(ÀÀéˆï+‹/ 3û$‡‡/ Œ4%ÿ‹6&•@1<-ˆ5'‚0!_ÿ~,ƒ2$‡6û(ˆQ1%|,"ÿ~/$0$~.ÿ".#sjÿ y$*….Š3#ƒKÿ&)ƒ+݈65$Ä`-)'‰¤i!@0‰3 +;@¸C ùðÄ š5"P@¬ûD2Æð«B0¬Bÿ/°E3±E1µÿJ7¸M9²F3ý²C!2²G4°Cÿ1¯C1¡6%˜ÿ-š/ž3"ÿ£8&«@.ª>ÿ,ž2 ­A/±ÿD2¶I7¼N<ýµX B0±C0±ÿB0»L8¿O;ÿ¿N9ÆT@«4ÿ ±8$¼B.ÃÿH4ÇL8ÊN9ÿ¿C.»?+µ9ï$º>*¢ ÁF3ÿÍS@ÉQ>ÊSÿA¿I7µ@.®ÿ;)¡/ /ÿ 1 ¡1"¦8ÿ)Ÿ4$™.–ß,•,f œ3+ Ÿôð7Ž@)ˆ°hp¸‹°‘°0`¡;)‚à¨ÿC/¬I6Ÿ>-ÿ˜8(›<-–7ï(ŸA0®À˜?0õ‘‹ñ)IP~*~ÿ*x'z)¿. z)>0zŸ*y(ôà4€‡ÿ5(‹9,0"껃»`,ÿ°|%Ç…-ù±:°Ì`ˆ-Ï`•:)Ò`Û0ö0úàœšð8'’2#ÿ‰*Ž-‘.Ï—4!H`'‘5#¿¥>,°G4 ¶ÿL8°D1©=)ÿ­@-®@-¯Aÿ.´F2­?+«ÿ;(¤4 ©8$ÿ«:&µB.¿Mÿ:·E2ÄS@¼ÿJ8³B0·G4®>+¨7%­æPÿ3!«9'·D2ÿ¹F3ÇS@ÄQÿ>ÄP=ÂM:¹ÿE1¯:'¦0ÿ§1®;(¹Eÿ2³?,¼H4·ÿB.¶@,ÃL8ÿÀI5ÈQ=ÉQÿ=¿G3ÃK7¿ÿH4¾F4ÃL:ÿ¿I6ºD3³>Ÿ,­8&¬S@ü2ÁÿN<ÀM<¿L;÷¶D3õ0¬=*³ŸD2µF4s@È0ªÿ=)ª;'§:&«?*¨=)¦úÀ¿9&š2+‘%§¡>, Ap—i 3ë#”*è°ƒ*ÿ5%˜@0Ž8ß(Ž:+…‘À&÷„3&Ç@ƒ1%ÿ0#mpom|°/ àï6'‘íp9)’îÕ5#ŠEp3 –û8&0š;)š:¯'•5"$  ’8q% ùð[€¤@-‚àª^°®ÙÀ@©p-& ¦ÿ;(¨=+¥9%ò0P¤èŒ°3 «?ÿ+­?,¶H3¿ÿQ<ºK6·G3ÿª9&¤2£1ÿ©7$²A.·_F4²A/p@ª_àÿ2 £5#ž0ÿ 1­>,§7ß%£2 ªÅP*ï,¢’@,¦ÿ4!©6#¦;)ÿ³H6·L:ºNÿ<·K9³F5®ÿA/©<*«=+ï®?.´h@=+¯ÿ>,´B1ª8'ÿ¬;)°?.®<ÿ+¸G5ÁO>ÇÿSBÆRBÃO>ý½ H7»G6ÂÿN=¼I8µD2ÿ´B/®=*¸Gÿ4Úž“ºI4´ýCë03¹J6¶Gï2ºM9®P§<)ç£9(3 ö œ5#÷6%²°ž9&Ÿîž@2—ëð/”÷3"™‡ ;*œ?ÿ. B2¦I9š÷>-—R/„%{† *Ž/'àý#ú@›;)<){™7 P,¡?.U€÷¦A/¯€•.šŸ2Ž&ð!©ð6ã#ª.PÙk°>+¬öÀ0B/¶0³I5¯þº0?+3§<(§;(«>,T Î`¨>+W N ºNû;¹L D1½O;ï¸I5À@UB¹ÿJ8¸J8«>-ï¢5% Š0.˜ÿ/%&ÿ‘*“,©AþæÀ9»SCÉaPÿÇ^N¼SC°F6›0 —,i ïŸ<-—¥ 5&û.Åp¡@0ªIÿ9±O?®K<¦ÿB3£>/£=.ÿ¥>/±H9£;÷+ªA©`/ž3#ÿ®B3²D4·Iÿ:ºL<°A1¬û=-^p®=,´Cÿ2´E4¯B/¼ÿM:ÂTBÀS@ÿÅVB¼L9¶Hÿ4³C0¬=)¯ÿ?,ª<(©:'÷¬>,RµK:´ÿJ8¶N:²I7~áÀ¨@.¨@-'Q«@.6 ¦ž°;û )Àcö ÇqÐwàc`2 ¿¥=+©B/ЯÿG5«C0¨?-÷¦=*èp¯D0±óF2E!èÀB/³E1³C/¯=)×0ÿ¦4±>)±>ÿ*°?*®<(«ÿ9%©9$¥5!ÿ¬=(«<'µEÿ2ºK7»N:µÿH4­@,²E2ÿ©>,ª?-®D‰1¨ðœP£ø€Ro ¦ÿ<*ž4#¦=,ÿ«C3³L<¯Iÿ:™5%š6'•ï2#˜6,•5¿&Ÿ?1Ÿ@}€2ÿ¢C5=/š;ÿ,‘2#”4&ÿ0"”3$ž<-ÿ˜>0›A3ŸEÿ6§M>žC5œÿA3•:,‹0!ÿ‹/!Š-˜:ÿ+¢C4¤D5Ÿÿ>/š7(‰$ÿ)—0"–.ý!Fp£:)ª?/ý±? A1¤8&§ÿ:)£6'¨=,ÿ³G5§=+«B­1èp¥+úp³Gù4‚p„ ¯B-¤7ý%xPœ.ž/ÿ©7"°=)¶Bÿ/ºF2¹D0³ÿ>)²<)®9$ÿ³>*¶A-»Eÿ1ÃM:ÄO;Æ}RìP5½J7·€þþpB0³C1©:ß*¥7&¥h0ú?€­‹ G5³J8ÿµM;ªB1ž8ï'¡<,i€ªG8ÿ¬I:œ:+Œ+ÿy z¿Š,˜á@ÿ1¤J<ŸE7”ÿ;-6(‘8*ç4&   Œ2$ü 0•0/ -û‡'š0.‹÷)“”€1"›6û'¦ÿ=.¯F7ÿ¶M=¸M=¼Qÿ@©<,š-“ÿ%Œ •%ÿ¢2"«:)´Dÿ5²C2­@/¤8Š@+ $Ö€±9(œ:)š8&Ëî+pš:+ 0™9+ïž?0¢ÖðF5¦ûF5¢A0¥E÷4 ?À°+£@-ÿš6$¡<*™4"–/œ4!Ÿð‡¤;(½ðª`˪`¤ÿ:&¥:& 6"ÿ 7#ª@,¨=ý*³a?+ 4 ž÷1Ÿì 2£6ÿ"¨;'¬?+±ÿC/°A-µG2°A,¬<(³Æ0ÿC/¸I4¼J7ï¹G4¸Æ`H4º«G3°µ0‹p°û@-m@ª<)±C1·I7¶AàPè€ÿ7&¤9'«A/ï¯F4±¤pG6¬ëE4&¢Ö€<,Ÿÿ8(®G8¯I9¯H9­G8œ¤à»-7 “2#‹£‘÷2$•  3$—8ï*—9*°*ÿ™7'œ9*›8¿(¢=.—1º  ÿ—/ '”,îî` œ3U,¯Eß5¯C3¬ª 1!ïž/¬hpD3ÄûSCذ¿M=»I6´C3°@0̰ÿ˜+”)•-¿ :*¨D9}§ÖÀM=žD4àÿ…0$+,¿!w%‹510(ÿ‡."3#…*ÿ$‡*2#1 ”óðXàÇž:(,`Ïð 0 9ÿ(Ÿ9&¢<)žÿ7$™2 ›3"g›5$[|à­GV°6³M8¯H5èpîÓp–.» ™2·Ÿ8#ðÀªBS°3¿®E2¬A.?€§Úã <ä *©­ 6$ª=*I|@EPú Â0ÿ³F4·J7½Oß=½P=­³p@-÷«?,±PµI8®ûC1°0¦=+6}$GÀš2"¡9Wî¼ð1¦=û€,¡7' 5%¨>-ïÀø]€×GÀ¡;*7ý'¨°°L<ªF7ÿ¢?/‘.ˆ%ÿ´P@9)¦÷B2’, *•/ß Ž(Ý@ÿ‰#€‡!ûŽN0)ÿ(‘+œ5ÿ& 8(§>.©ÿ>/¢6'š-ÿ™,–+™-ÿ«A2­E7­þs°J:£A1œ=ÿ-›=.œ?0–ÿ<+‘7)‰2#î'ð‰2$ßà…1#õ†þà/Ìà7(¾¢'š?/›ªÐ>ÿ/¥F7 @0›ÿ:*š9);*¿¡>.§D2ÄОÿ;*¢>-£>,úªÒÀB0¤C0œ| P¦C/¯ ÐМç:&š„0¥02˜w6#™Š04"˜¹àS4"2`aà¦÷€D×ñÇ¢<+à 0ªB÷0¥>íp,ª@.î¶`­A0W!D1ª‡?.¬eà]ÀÎÐÌ.ÿ•-‹#ÿ)•.š4$w›4%Tà˜0 ó°û(4•+›Ý1§ð$¢7„@.¨w<+¤`4$’jàþŸ00 Ÿ9)­Hï8¤?0 Ð’*þà¥>.µN>¶ÿP@µP@¨B3¿›6&”/ l€¡==ÃÐ5¥B3r€%pߌ*”2¢@& ÿ=/¡>/›7(­˜‘°2#+Ж°.ÿ,‘. ’þ¬°8(’5&Œ1÷!‘6ð@&‘8)÷‘7( ˆ0!ˆû1" ðŠ1$–;ï-’8(±€3%þ°“4%—8)›;+›9*ž;àý3y—3"š7&ù™Åp 0B/¥>+ú ˜~0/’,çŸ:' ÜЧE3^åП=*žý =ºÐï&›:(‚ –3"÷ž<+œ<+¦cD3}ð •5q€5%‚  w¡.¢¹pàU;Àp&»p ØÀ5Uõ)<€¥'=,›2•!Âð©ÿÀ8þ IÀ)p«°Ýv ö°˜1!œàÿdž˜. 6¾n /¨<,©üÀ=,©;*°B1´Pÿ²D3¶H7ºMÿ<¼P@¹N>®ïE5¡8JàºRÿB±K;ªD4˜û3#äá/.ÿ—6&‰(¾Šï‚ƒ$:Ž0!ÿ•8*¦J<£Gÿ9”8-–:/…ÿ)Š.#œ@2ÿ‘4'‘4&•8Ý)–°£E7gœ>ÿ0“6(‡+ƒß(†+#À…+Óm€ñ)®€“8ÿ)5&›@0—ß:+œ>.’0™8þg`,;,ªG7?§B2¥?/ÐNà›4$¢:)¤=€÷B1¤à<*¤=ß*¬D1®¬PF4÷®G3ü š7#››7"—@ ;LÀ=Á¤_?,¦B-0¡þž5",”/ß•1“í`4!˜3";ðý¸ #`Ð8]€îp®D2²p¼ðšé`—bÐ,ìðVÀžja 2­±ª¾àA2毮L< YÐ@-¿«H9§C4ù°©+D4Ñ;Æ,ìÀ¿ðî<à©=-Þ€¥9(ï³G6£!04%§ÿ=.¢9)°H7¿·O?¢:+i°™ý2&•0 8¿)¢>/Ÿ;¥”ÿ2$,“3%¿1#2$^‡ÿ*†)‡+ÿ%z‡,ÿƒ(3&ÿC5’8+š>0ÿŸD7”9,4ï'‡,ÕyþÛˆ.Ž3$‹ÿ0 †+€#ï}!`a)š;ù+‹ (p‹*“1ÿ"˜5%Ÿ:+¬^»PF7«DØ,ļîp]°­G5¨;ý+Ú‘;(ΖŒ§üÃÀ?A-¡>*žÿ:&Ÿ<(¦A,ý¤Ì0G3©D1£ý>·  Œ'‹&ïˆ#š5#º¸ §ÚÐ?-žHÁ(g‘,`áÃð5$,NÑ9(Ÿ!Ìp'f°Þ¥¡<-¥[:,ç©E6p/ðœ<.þŠ€¦H:ŸB3œ÷?1ž¬€8*‘3ó&– µ€*Œ,}°’0!‘.'ÐOŠ$àðó°ž=ß2"œ3#0ž5ß%4$œ¹9*Ü= «‘-êà†"߸°4%îØà–2#"0’.·“0!r€‘/ïá“ë3$‹ €<.‘ÿ3%ˆ+‰,ÿ¼Šƒ5'‰.!Œ1%˜=0j1{<.‘Š- ÷0#Œµ‚†(ˆ*1’4¥Aµœº Fû°7¨[°Iï9©E57p¬D5ÿ­G6¨A1­F»5¨Ø6%=4í#àÀœ7%a›6%—1 ˜3!—õП1–5!îÐ@ÿ9%”1•3ÿ‘/”3:ý'ô0¡?+¥B.í ~ð7%P“0výÒ#›xñ!”0ïàÿ “1 œ9)›þÅ0:)–5%,ï•4%0@š9+ÿ§H8£C5 Bï3“5(·€u ÿ{ˆ- ‹1ÿ$š@2Œ2'…ÿ+ ‚(ƒ)ÿŠ0"†,Ž3ÿ%4%’5' ÿC4œ>/’2$÷›:+ò ›8)©ÿF6¦A2®I9Ù¡²ùÀ?0“@Ÿ9ÿ*µO@²M>´ÿO?¶PA¥?0ýžb1!Š$ˆÿ!‹$•.wš3#¢à¤<-v ¿§A1›5&«Û9*10:p`1•ß4&˜8*“€‹,ÿ–7*“5'–þ—°7(“5&—7›)˜"@;+L0ü@{<-£¦F6¥jë;-¸Ð“áð1 —ÿ5%•3#ž:+žÊР=-ŸpMp:‰)Ыš$a½1x°Ÿs;*>ÀÙП>,}ðþ‚ Ž//Žû,JÀ¨D0ªEÿ3¯I8©F2¢û>+Dð¡<)˜3 •3 ˜5#@—5"͘uñß'¡@. ¡¢Ÿ?ÿ-—7&Ž.Šÿ,„&}÷ˆ+æ “7(ÿ4(ˆ-!ƒ(߃)“:„Ñ‘6¾ð"Œ0#”å1?™>0 E7¨€ðט=/v{÷~"‚&‰»¿6'Œ.’‘°7ÿ(Š)…#‡ÿ$“/"û ;Ùð,™4%œöÙá#‘¸°3#Š%ÿ*‘+’ß, 5%“ 7Y'3G ®F±1¯:@¿=-©C3±\pKÿ<¹UF¦C3žnv€3$–`;,m`w£B3™€:+ºàç¡=-8ðÌ@™4$Ð%`àÉ@¦¶Ð6%ü¬i«F7¬F6pýÐ{°äàg`•0@+%`;ðàYÀµ þkP ;*£?.¤ÿ@.œ9'—:(Ïœ<*—¹Ñ`;)ÿœ4#¢:'œ5ý!zP¨D.ªE1ó©D‹ È@/¢;(~µ ¦?-œ6#ÐÐ~µ š6&¢?-ÓaßB1¢B0ƒð”5$0!Ž0 À’^à3$’D0w0 û1"Ep”6'™:ý+Np @1§G8w¥E6À€£C4~€ÿ¨I:¨J;§I:ž@1”6(mç2#ø@„&݆µ°4%Ž>02"?š8)’0 70ÐÚØàœ¡8)ˆ`’,ù¥²0£;,©@ÿ1—.† “¿)š/Æð=ï,¶J9{à¯C2ú‡±8¸J:±ÿD4Ÿ2"¥8(þO ¡3#©;+³ÿD5ª<,±D2ïµE5«™À:)¯ö=à;*€­;+¨ÿ7&¯?-ª9(ÿ²B1³D3²Cÿ3µF6¬=-µßH8¯B23à³Gÿ7¦;+¥:*¤9*¢8'[Ð5€Šù¥‘à-€F5¼O=ÿ¼O<¸L;¶Jû8šà?,¡9$÷®A,e€¬>(¯ÿB.¯A,´E1ÿ²E/±D0´Iÿ4¸K7»N:»ÿP;¸N;»P=µJ7°F3£Ý`ß4#š3!á<*¢=+£?-•6&š8(ÌàÆàÆàü + ’/!’/ ÿ‰&Ž+œ8Ï* ;- &P—35$7 ™?€B3¦0@~+ ”3$¢B3ò€ÿ£D5œ=.Œ-ÿ›<-˜9*”Ó5&O0 –9)pà€­€ÕàÀà§D4`ÜÞà2P¤>/U`¦?/—/‘)ÿ¬B2ª@/´Iõ8ïò+Øp¬>-¶÷G6¸—G6ÄSÿB´B1µC2¾ÿL;²?-¶B1ÿ´@/ª5#¿J9ÈQ@ÍVD|ÿÂJ8ºB0¹@ÿ.·<+ÄI9ÌÿQ@ÑWFËRAùÀVÍp6&¶=-ÿ·?0ºC3¼Dÿ3´=-°9*ª¿6%®8(±Á°;ÿ)±=+µ?.¸¿E2¶C1´°@ÿ.°=*³A-»ÿI5¡B0­H5÷µM9t€©:(­ÿ>+¬>+»J5ÿÀP;ÃT@ÁSÿ>¾Q<´H4©ÿ<'¥8#¦:&¨:'°C0¬.úõ`>á ,©?.±ÿH7²J9¯G6øµ0§ àðš4%¢<ù-0o°©D5¨Ca4K@.) ,Ø0ÿ%—3(’.#£¿@1£A2œOp8Ï)ž=.°›;ë,Š€1æ@‘2¹#opû€£E6²Ð¤{E5ZpŸ?0šÓ@Ë6'r âà'ð5%u ^8ÁЪE6£`þ“à²M=¯J:«ƒE5¢àãÀ:Œ÷#œÂ`5$°Eÿ5ÂVE¾Q@Ä¿WF¹K:¹ÜpAÿ1±@0¾L<¼ÿI9¼I8µA0ÿµA1ºD3½F»6¸ý >-ºñ Fï6ÉQ?|ÈO>ÿÃJ9¿E5·=ÿ,µ<+·=-½ÿB2ÀE4¼B1ÿ½C2º@/»Cÿ2ÁI8ÁI9¿ÿF6·A.±<)ÿ¯9'­8&´?ý-S°¶@.3#ÿ”05#¯>ÿ)³C/µE1±?A-´D0³{€r°ÿE/«=( 2¿§8$¨:&îµÿG4¯A/±C1ý²“°E2±D1¯ÿB/®@.±C2U®°D+€/øðªzÐû.gО1"Ÿ3ý#òðž3#š/ÿ“)™/¨?/¢:*§@0O`þ¦`¹SD¶QA¬ÓG8¨ Ú€šô@1"ì£ma<-½š;-§ž@2ã op‘ˆp19!u@op>.À¡C>/À ÀopÂ2À½—0m`£# ï°Ú€¨ æ°ã°à°¦`O`װ԰Ѱΰ˰ȰŰòð¿°¼°gЀ¶°³°øð­°öp§±¥°@.ž°›°˜°•°’°°Œ°î†°ƒ°€°}°z°q¶n°k°h°e°b°_°\°Y°S³P°M°J°G°D°A°>°;°€8°5°2°/°,°)°&², °°°|°°° °°°°ÿ ü ù ö ó ð í ê ç ä á Þ Û Ø Õ Ò :Ì ¢àãÀ ½ º · £`± ÁЫ é±5%j`Ÿ r C0– “ ”ZqŽ Fi6û€ Á2#{ x u r ï i  c ` ] Z W T Q ) .@KB ? < 06 3 àð§ µ0' $ !              ýú÷ôñîëèt€âßÜÙÖÓÐÍÊÇÄÁ¾‘<,¸µ²¯¬©¦£ š—”‘Ž‹ˆ…‚|“yvspmjgda`^[XUR‘H8LïðFC@:74U`.2P(`"〭€à€ O0þ€„¡D5òƒï€¿€0@¦ã€à€Ý€Ú€&P р΀ˀȀŀ€¿€ ¶ƒ³€°€­€ª€§€¤€¡WP3!ë`•€’€€Œ€‰‚;ƒ€€€}€z€w€t€q€n€k€eƒb€î\€Y€€V€S€P€M€,€G€D:*>€;€8€5€2€/€,€˜)€&€#F6€B1€€€ €ƒ€ÿpüpùpöpópðpípêqs8(ápÞpÛpØpÕp‡ÏpÌpÉpÆpÃpÀp½pºp·p´p±p²0¥¨pˆ`«Ÿp40™p70“pppŠp‡p„pp~p{pxpuprpoplpipfpcp`p]pZpWpTpNsKpEsBp?pPÏA>`:^€//P,P )P^ð#P¥ B!PPPPõ°PPL0ÿ@P`ù@ö@ó@ð@íA7*ç@Àä@á@Þ@Û@Ø@ÕA9*Ï@Ì@”`Æ@Ã@lн@º@·@´@±@®@«@¨@¥@¢@Ÿ@œ@™@“C@@Š@‡@„@@~A ‘$u@r@o@l@i@f@c@`@]@Z@W@T@Q@N@K@H@E@B@?@<@9@6@0C-@*@'@$AÆ101 P}†P›8ï&˜4#©`“0ßš7$›7§ +¥B.¡?+:¥ ÿ'”3‘/•3”19 @ÿ(œ:&–5!•ï1—2· !—1ý š`›6$œ7%í¡šp4#DPž6%§¨B1 àL`­áàDÿ5¦B3©E5¬ÿI9¨G6ªI7ç¥F4û²5p#1ˆ*†(ð0ÿŒ/!0#4ß&Š-/ð<.¿Œ1%˜=0Å@‰ÿ.!5'¼Šƒÿ‰,ˆ+‘3—%›<À0+ðP’ö‡/ ™ “0!’Æô-–p™`0,ÿ†"ã,û@ú üÑ9*œü‘ó›2"œ3#Ú(Pž‰ð-àŠ$*‘.·0~o Œ,Š*‚ ÞÀ‘3&•ÀA3ÿœ?1ŸB3¦H[:šù±.› Ð<Óƒß,¥@1¡;À6&ý£tÀ8'ž7%þÈ`9( 9(ž7ý&Ç`˜2!)ï‘,Ÿ’P9(¤ÿ?-§B0™4"ùš³ ¨@#‹&ÿŒ'™4 £>*©D1«G35ÿ¦A,Ÿ<(ž:þ*¨A-«D1ÿ§@-ΖŒ¡;ó(žûð €A/­Gÿ5¬E4¨?-¤}0’8+¿C53&9`‡û,?`%‡+ÿ†)‡*‘Ÿ4&2$7Àß,”2$OðŸ;ï,¢>/ú •0 þŠ™2#Ÿ8(¢ÿ:+·O?°H7~û§=.Ÿ4%D€þÒp¥9(±E4©^ƒÀ?.§=à,`­¢ð7'•¨–Cï4«H9¿¢@1ÿ >/®L<¬I/:¥A2E –ð@/Qÿ%›3" 6&–ÿ,—, 5$ÿ¥:)©@.®Dý2úP¦=,¤=+n‘P6%¯P™5Zðû"˜$p4!“.~\@”/, pÿœ8'¡=+¨CÏ/¦B-_€è ¢<ÿ( ;&8%›ý7EÀ#¤<(®Gÿ3®F4®F5¬D1¤=*¤,¢¾@4$•-¥0¥;?/˜ªG7Oðõ°þÏЗ8'œ>.—_:+›@0¿@“‹`÷:,’‹`;-6_'…+…«@+u ‡+“6(Àû£E­Ð7—9*•û8)o`‘4'œ@ÿ2Š.#…)–ÿ:/”8-£G9ç¦J¼P@ºMû<¶" D3«=+°B1©f à`û@/ù`˜.Ç*à :*Þo0¡<,—½°9)þ–` 8(©B1›Ã2!p€½apã <)îp 6$MŸ7&ï¢;)£>,£õ>d+Ü ˜6%•ó5#@ß <+¦ëD3› 0<+–û3"Ü ›:(š9×&Ÿ=·€(Ç€¦Cÿ/§E3¤C0£ÿA.Ÿ:'’,ß•/˜1`$¥ï>+§B0)™5#š7&t³Œ@žÓ;+mP60—¦4%‘3$3%‹ö@ë8(R Šå00!ˆë1"$Øp7(‘ÿ8)5&‘6'ÿŒ1!’5&–8m(ìA. P“. ו/ ð˜407(~ð =/—5&‚ðÑŒzò™ ð§F =.ùšVð—Ð6&¨B3ÿµP@¶P@µNÝ>lЗ0 R€°L—<¤?Þ8q@.ÿ’(ž4$¤³9(éá7&p›ÿ1 •+–-ç(4Q)›·4%š~p.P‹{#€p—.£µ¾ž 7&¬B0º`°ö›ÀG4 «>,ªÿ@.¨?,¥>*Áª’ð¿ þP@/ÿ¨D2¦B1 =¿+—4#—4(p#ý˜q$˜6#•2¿•2 š7 @&î#£@-Ѐ >+ç¤B/Ö€å ªG4é¥`xp> 1§D2œn ‡Ð;*"ð0 û@0«Ð›>/›?ß/š?/Vð;-ÿ7(„,‡/ÿ †0!…1#Šÿ5'‰2$…0!÷‰2#m –<+œÿ?0›=.œ=-ý£„@J:­H9­ßE7«A2¹°–+™,š-÷ðï©>/§˜€8(œþ7+()ß„Ž[`!ÿ€‰#„)Ž(Tÿ*’-¦Bý2œ´P@ˆ%ÿ‘.¢?/ªF%7œ¢º¦1*‘Ptpîp¡7'ð 5%4=°À`¦ƒÀA1iÐq@·š2"r$¦5€Gÿ4®C1µI8©ÿ<*«?,¬@-ÿ­@.½P=½Oß=·J7³cp@-ÿ¨;'«?+ª=÷)«>°*£6$ï©<+§l <*§ÿ=*ª?-¬A.ÿ®E2¯F3ªBÿ/ªB.Ÿ8#™ÿ2–/–.÷ 8&úP¯H5³ÿM8±I6­G4ã¨A-°–Qö`™2 ož7$¢¼ 9&‘Pê  é :ÕP(›8ÿ'˜6$š9(ÿ1 2#‡*÷$¹p3#‡ÿ."‹4(‹5)ÿw%,!+ÿ…0$•<-ž¿D4ªM=§–A9øÏ`X€4P”)˜+ÿŸ1!°@0´ÿC3»I6¿M=÷ÄSCZÀ´D3¬ß=,ž/KÀ¬?ÿ/¯C3¯E5¦ÿ<,œ3$˜/ ”x'ýà í`a€+°ý›ä 9*™7'_*•6(Ñp—SQý$œÀ‘2$–7(ÆæA2#Xð‰î ­Gï8¯H9ùЮG8¸–`‚PÆ`¡:)÷P®ÿG6±I7¯F4ý«39'£7&§þÖÀ>,¶H6·Iß7±C1ª!à=*ÿ°@-¯?,³Cÿ0µE1·E1ºÿG3ºH4¸F3ÿ¹G4¼J7¸Iÿ4´C/³A.¬ÿ<(°A,µG2ÿ°A-±C/¬?ý+ˆ°£6"ž2ÿŸ4 ž1 4½ ‹°§;(¨¤°@ÿ, 7# 6"¥ÿ:&¤:&©?+÷­C0eЪA.¤/;(4œð!¾°¯Pú š†€@-Ÿ<+¿ ?/¥E4š žÿ>-¦F5¤F5ÿ¢C2ž?0™9-+®Ã¡@£Ð(Ü ¦€Ï9(£ž 09'ý¦þP8)­@/²þÒàD5«:)¢2ÿ"•%Œ “ß%š-N¼Qÿ@¸M=¶M=¯_F7¤=.P›Vòÿ“0"‹).ýIð‡'-íqð2#®ÀŒ2$g6(--‘8*àþ’ ŸE7¤J<›ß@1˜<-ºzÿy Œß+œ:+ä`ªG›8™D°<,ëPtpµÿM;³J8±G5ühЦ°0¥8'ÿ¥7&©:*³C1³B0³B/Ðÿ½J7¼I5ÆRÿ=ÄO;ÃM:»ÿE1¶A-³>*ÿ®9$²<)³>ÿ)¹D0ºF2¶ÿB/°=)©7"ÿž/œ.ž0ÿ¤7%¯B-µÿG4¶H4³G4µI5ª>+¨’ðÿ6#Ÿ3 ¦<(ÿ¢7$¨>)®Dÿ/§;)­B/±¬Ô°žàD1  ž­ -’*•.”PÜ2ÕÀŸ9'耜59#pˆPœ4"p2ÿ³I7·O;±Hÿ5®E3©A/¥û<*ǰ«B1§=þ5¨=,£6'~íÀ¤8&®A1´`ª?/£:)£`ÿ.!—0")ÿ‰$š7(Ÿ>ý/Ø¢C4˜:+Îð0‹/!ªpœAý3U §M>ŸE6¿›A3˜>0¿”n0"”Øp2#gPÿ=/¢C5Ÿ@ý2ÒŸ?1•5&×›;,ò@•©ð6'þUà¯I:³L<«{C3pž4#¦n°¿@.³H6¦€8%çð 5#÷র|€ÿ²E2­@,µHÿ4»N:ºK7µÿE2«<'¬=(ÿ¥5!©9$«9{%®*Ð?*±>"ÿ)¦4«:&¯÷=)³$ÐE1°B½/Ðà±E1±Å D¹0r;òC0¯hàFÿ3©B/¥=+›û2 İ¡:'Ÿ8$Ÿ7%kðk¤ý<_ð)¦>,¬DÉ2pp¨†° pF3ÿ²I7¶N:´J8µK:®C2ðÀ¿©:'ª<(Ьú00Êà¼L9ÅVÿBÀS@ÂTB¼M:¯B/´E"Ðÿ2®=,°A1¬û=-ѺL<·Iß:²D4®3#í©#°A1`ð±H9Ÿ¥>/£=d Cp3 ®ÛO?9À­Ð`o‘ß5&—4%pPž3ÿ"—,›0 °ÿF6¼SCÇ^NÿÉaP»SC±Iÿ9©A1“,‘þMP&%˜/ï˜.p¢5%ÿ«>-¸J8¹Jÿ8ÄUBÀQ>¸ÿI5½O;²D1¹M9ºN;²¾òá+§<)± >ý,PЧ<(3þeЯD1³I5¶_L8®B/s°©Ôàw>*¦¥>* Úà~¤€3 Ž&š? ÿ.š4"¦A/ÿž;)¡?. >û,™‰P<)›;)ÿ–8&“4#Ž/ÿ‰*†'„?%/—V°–ÐÿI9 B2œ?.ÿ™;*™;(”3¢î@, > ÷±9ó $Ôpqž†€9„)®ÿA/ºM9¶G2ÿ¹J6·G3´Cÿ0ºI4Úž“¸îe°=*´9D2¼ÿI8ÂN=»G6ÿ¼H7½I7ÃOÿ>ÆRBÇSBÁÿO>¸G5®<+ÿ°?.¬;)ª8ÿ'´B1¯>,­;=+`À®?.4€m°¾$ ³F5·Kl<÷·L:äó©6#¦ÿ4!,¢2,›*ªèÀÿ2 §7%­>,÷ 1¾à£5# ÿ2 ª;)³D2ÿ²A/·F4²Aÿ.©7$£1¤ß2ª9&0 ºK÷6¿Q-€3­?,þ‹° 3 ¤8%¤=9ìð(¥9%Öàü §ÅPA-qâÀo oП@-ž:'/@Ù€šÛ8%S ™8¢€"šÞ0;)œ= `&ÿ3 Š-5#ÿ’8'“9)‘9û)´p/„/ ÿ|)mpÿm0#ƒß1%„3&k0y&ÿ…1"Ž:+Žÿ8(˜@05%߃*Š.€ð”.*@3#—³P3¥€_ý,Sp7$š2¡9&¦<'¨°ÿ?*§:&ª;'~ް´F2µF4¿0üÉ ÿÀ­<*¶D3¿L;ÀM<Á‘ þÆ09'¬8&­8ß&³>,ºÏ0I6ÿÃL:¾F4¿Hÿ4ÃK7¿G3ÉÿQ=ÈQ=ÀI5ÿÃL8¶@,·Bû.¼Ëà?,¹E2ý®ƒ1¦0¯ÿ:'¹E1ÂM:ÿÄP=ÄQ>ÇSï@¹F3Ú0«9'÷¥3!Ë0¨7%®_>+·G4à¼YÿS@·E2¿M:÷µB.,©8$¤¾KÐ;(­?+¼0¯<ª°t±-©=)ü”÷²H4d°¥>,›þ³P0—2 —4ÿ!‘.Ž-‰ó*à˜q=+˜;ÿ)‘5$•9'“ÿ7%•:)1 ÿˆ-Œ2!ˆ.ÿ†.…-|ÿ%„-,ƒ/ ˆ5'àÿ9,‡5(…4%ÿ„4%y(z*ÿz)z)û. î@x'~*ÿ~*‹4&îÕp:*˜· @/ŸûA0§Ð›<-˜8qð-¬I6Ap0 ÿ›4 6!¡8Á%h\pwkð3 ¿š/•,ü`™ÿ.Ÿ4$¦8)ÿ¡1" 1  /ÿ¡/®;)µÿ@.¿I7ÊSAÿÉQ>ÍS@ÁFÿ3¼B.º>*µÿ9$»?+¿C.ÊN9ÇL8ôÿB.±8$«4 ÿÆT@¿N9¿Oÿ;»L8±B0±ßC0°B0Çà¼N;<¶÷ÀD2­¿Ä =>E€.£8&HPÿ˜-¡6%¯Cç1°Cþ‘|²E3~p¸M9µJ7>ÿ°E3¬B/«BO0¬E2€ š9p»7% 0›:',0‹ÿ+‰*‘3!ÿ3!3!‰.ÿ')‡-4$5#ÿ ƒ+)}ÿ&ƒ+Š3#ÿ….*y$ÿj sÿ.#~."0$ÿ~/$|,"€1ÿ%ˆ6(‡6(ƒÿ2$~,|)ý‚%5'<-•ÿ@1‹6&Œ4%ÿ†/ ‡.3ß$Š.‹Ô@+錬B 9qð+ž<ÿ*¦D1¥E2©Êd J;À3V ý€œ8ÿ(›9':(ã:'¹Ð;p/ ¢?.×8'Ù°¥p;)~ž´H7·J8‘°ÿ§9&®>*£2ÿ©7#«7#±¿;'·A-¸q,ÿ©3³=(»Eÿ0ÂM9ÆR>ÀÿM9 8%°I6~b §C2¦C1˜1ß@. ?.µ€—7ÿ'‘2"ˆ*‚ÿ${…)ÿ3%6(¢Iï:›B3-À–<-;‘6=0#•840¡À­&°Ð”410)•п>-¢C3˜~ Aß1>.œwpD4ÿœ@/£G5—=ÿ+’7'Ž5&†ö‡04$p….þ—À6&†2!ƒ.ÿƒ0 /…ÿ3$„3$x&ÿv$t"x&ÿ/ }+ƒï/!.X0}*ÿ†3$/!€ÿ-Š6(})ÿ€+}(v!ÿ|'~)Šþ0`7'‡0 Š1×!‰/€ð¬@Ž3ÿ$Œ1•7%ÿ2"˜9( @1Z¬€ª"PG4Ù€¤(Pÿ=+9&¥B/w¢?, 0Ÿ<)À’0‘0– o3!•4àLPû3! ¡C2¤?,Þô°—2¤~E2¿³L9³K8nЫ?@-ª?,­ 0É0õAB°"ðð3 Œë#tЗ{Ð=+û5#€8'8ÿ':*8)‹ÿ8)ƒ1"€/!ÿw(]^ÿ ] r+!sþÇ€,"n(_ÿn'y1%}þà@;.y/$p%ÿm isÿ%s$w'ÿ{,~.!€0¿#€/"€.Ìp¿ˆ4%:+ª ÿ-,{'ÿ€.†4$†4ß%‡5%†03"‰8(‹;+†þpý7Ø@!y)‚1õ#å@{ò@- t"o}*þ¤ †5(}*{¿(z'‰?,ÿ…, &~ÿ%2#’7(ÿ—;+4#‘4#”7&”6%•Ðÿ•5$‘2!˜7ï'˜8'`˜7%ÿ“0‘-”1Ï™5!03€£>Ý*0¥A.Ö° ;' :'‹@ð¿¡;<)˧B0) ÁùŸ+Pþ°4"ž:)ü/ Î`Ÿ<*¡=,ÿ¬I8ªH6¨E4§F2›;(›ï¢B/”`=*“ÿ4!1—9'~©@@.€*S0ÿ€+€,,ÿt#}-wÿ)w+€5'ÿx.!…-—B0—ÿA/Ž8&‰3"ÿ„-„-†-þÃA†/Œ3#Œ·1"™À:*†0”û8&apœ=-¤Fõ67pŠ`&‡%°“/B€‰Ð?€w¥A/³`¦A0'ðþ ‘,’,”û.-°Î—Œ£<Ý*l€5#e¡;&0P 7$3P9P§¿?*«B.§'>¾L+¨A,®6FÙ2 0¹À¥= 0,ªãB00"pÚ™6#ëŽ+à›–6$ÿ•6%“5#€$Ï$ÁA6À.ÿ(v w$ï€,À‰7'ÿ„2"{)}3ÿ%l"k!hÿn#x. ÿs(z.!v+ÿq&s({ÿ0#u*s'ÿ3'm"u)ÿm"d lß!jŽ¡0"ûv'ù@v$wÿ%€,ƒ/"þ‰2#Š3$“ÿ:+D5ŸD3ÿ§L;¤H8Aÿ0˜;+’4%Ÿ3#‘5%œ€¯A6í$PÀ’7¢Ð%™>û+—û9&’5#\†`Œ/:p€ÿ,“2 ”5#ÿž>+£C1Ÿ@ÿ/—9(0’ÿ2!—6%˜6&ÿš:*›:*¥Aï1©H6³`©E4÷˜5#kÀ‹&Ÿ*—1¿°‘>ß*³J5°H4ß®E0¢:m" ß8#£<&6°©Aß+¤=)¥=)þ°À¦>(§@*¬ãC/åà6à6° 9%Ý¥C°C/©CàB0þªž;(›8&œg;)¤`ÇPF4„°ÿ‘8'’:*ˆ1¿!Œ7'ˆ4p`ûˆ7X%~0 y¿+y-x˜ 2ÿ$n&x0"{ÿ3%o&s*ÿhb t(ÿy+ƒ5'zÿ0%o$l ÿl -x&ÿz'oqÿƒ.!Š4'ÿ–?08(4ÿ%’9)6'˜ÿ=-Œ0"‡*¿‹- ‰+Œ¿,‹(’lÀ4Ý#×`›7$Ž@8ó& ý ŠD1¢=üÙÍ`$ž:& =ï(¡=*È`£A-ÿ¢?+œ:'¦C¿/›8%›9ð)«œ7%ð'ª› 9ë(žÆ`8Lð(—3#›7&Å`¿`qÀÎ`ý“p°0”0 ¿-—3!’{ð1ý»—1 œ6#ÿ¡;'¤>)«E^#°2¨C-ÑÀ¡.°:%¡9$¤=>áì 0?°¤=8°&Ÿ9¿$ž6"Ÿ7Žð&¼Nà°¥?,£ð9i& ðJò(ב=+ppíšÕB1[p‰1 þ™°|&€+„ó1!â@2„6&~ÿ3#ƒ8)†<-w€7(w. ä€u*|1!|ž ÿ1"†6(|+ÿu#y'.ÿ‡2#9*ˆÿ0!Ž6'“:*ÞJ0’8(‘;+ÿ C3¢D5›=ÿ.1!Š+ÿ-‡(-÷”4# ™6&‘ß/ ‘-Î`¢<ÿ+­F4±J7°¿H5©A/©0<ß)¦?+¦*ð9#ÿ¦>)ªB,°Gÿ2´M6±I2°ßH2©?,6°¥>º5à(Qà¤>*ž0šÿ3!™2 ˜0þ6PŸ6#§@,©> C0¥?-žÀÚ`ï–2 “Š01ß-Ž-•0“2ó!™ã­@4#˜8ÿ%—7&—7$˜þÔ!”3™8$ýš$ð<'™7 —ÿ5š5 ™7"ïœ9%Ÿ½<* ÿ=)£@,£@-Ý¥\@H5«tD1ø6È`&0œ;(š7–;ìà!ÿ|}‰+ï0 ppœ;+ÿ›9) >.¯L<ªG6¬H6Ë`?•1“.‘@l€ý¢áð8)6&•¯.›3 $-P›ªFP2/P#Qà®ÆÀB¯-§@+Qà ¨ð<ï'§='6à£;&ÿ¢;%¢:$£:%§?+ 004"•ç:(BÀžq&u#ûz‰ (}- ÿŽ<,”B1›Jû9“'ÀG5•E3·Š9')z)ñ ÿ|)‡/)÷…-1&Šÿ1 6%œC2ÿ¢H7B2”9»(†b0 ”“:ï*œ>.ñ ¨H8ÿ¯N>´SB®Mÿ=—5&’.ˆï$‘,‚ð Ÿ:ÿ(¢<*¢:(´L9±H5µMu1þV!4!œ5"8÷#7ð$™4!×Ê”ŠŽ0 (à>)É£'!)à%5 <à¨@½+<à¥>)¤¢Á"Ζ€ž5"¿ñ°9$ý @Q# 5$3vSP! Àð5#¤Øð6$£;)¥<Àý'°š8&˜7$ö`’2Ê #“5$ߘ9'•8]p!ÿ4"‹/2ø  `“7$’6»"’ °6%‘ °7O$“8%²Ñ„À5–Ðý$¸@1‰,ï‰-Ž@3!”ç9'­Bœ€š>+Z¬ÐŸ)p@.šÒ)‘Ðù‘ðÀbp?-’8&ý•@9'7$ÿ8&–@-’=)?:'Œ5#2`f@\@c™<*`˜[2y $¼ }!4#¼ Ì?™9)œ<+ëÐ1pÿ™8(.-Ýp‰'zð*O”0à}ðšÆÿ;)¦A-®J6?±K8§C.ó@°ÿ˜5!˜4!;ý'<¦B.£?*»ž9 `"˜4‹ð!·7!¹ñ;%¡À¥Ÿ?*¢<(Ñð2Pž~˜0;(¢;( .±'ž7$Œðp0p¢x+ðoÀ6#ž5Ì09$ b Ÿ:'`Ú`þÎ`™6$–3"’ß1’3 ÇÐŽ/ù±@`‘4 “6é#!@-@„P/ˆ¿,Š.Žæ6²ä #$@c’6–Ð#u“ 7Ö &•9ÁQ2 ‹0Š@êO€9¸P"©Ð”7#îý0š:'ý0/þ`¡>,§E1«ÿI5¤B.Ÿ=)ÿÊ—Œ™:&š;ÿ'œ?+–8%ž½Ak@*4!û¤ÿD0–6&‡'ÿ€!-ÿ/=*¢ßB0§G5ÓÐ=µ+jp€,›`‚ÿ%ƒ&‹.gˆ+OÀŒ1 @û'•û 9*–:+÷Š/H@‘3 ÿ2”6".ß1‘2`”“5 °8ð›½T @ù+3;ð¥C/¤@ï+¢>)&ðš6"÷›9$°–3›q6ðvPp &ž8m Îað$™3!Å‘9'®0àΕ‹YPŸTP:(£<) 8'b ß–/˜0é–¯0 œ7®`$K7ß%—5"™ <(¾õP¡?-¤CG/ÿ¢A.¢B-Ÿ?¡-@`”`âÐw •¶`7µ$w ’~ð4"?p“ìW =+  ž>,wš;(l°˜:%éPÿž>*ž<(¢@ñ-Gð2PÔð¢;'¦ó?*!à¶À­F0²ÿK6¼VA¸S>ÿ·R=©E0ž;û&œà=)«G3ÿªF3Ì—Œ•3ÿ ‘/-•¿4!–4"¡jp<¯)“3"¶ ©p1ï ”6&f†+†+‡88¡ .ÿ‚+,~ÿ)z$x"ÿ|%€)‚+ÿ‹4"Ž7$Žÿ5"Œ4 2z¤P‹¨Q.|`?•8#–6" pæ¿•4 š7#<€–t%að%­ <)Ä`oœ:&›05$qPíœO9%0™4$ÿ—2!–1›5û$¡gà>-£>+žÜž8% QP!ð64np7P)ðŸ9¾’c"-ž~€;*b€¢d@XpË5#3 RpoP9&N,€˜6"ú0eðšr!K$š½ :YpUÀ*l°Þ6p”4"‘@.þ΀“3 ”4—;4! p˜5"Ê`h€Ç¡<(/P „p¬F÷0­DØ-£;$Þ£0ªB+©°2§?å)'à£+à¡`;'Ÿÿ6"¤;'£:&~8 °H4ªC0ì€üÁÑ0=*£A.ž–ì0<*Ò@šEðÀ9ï(ŸC3u@Ž3$ï4#‚£°(…ô…à_`3‰@%Ž6"ý†€0ˆ,Œ÷0ŽØ€8#4y @6pŽ1‰`Ç4 ˜$€®€9P;'<€£@6#>ðàÀN¤pæ™§‘&ô0ã<)ÐÐpÓС>-ø@nÀÕ@Œ)+o”2!T =œ`á+¸p»`ð§A.9§ÉÀ7>*£Ã€iP”HðTP<”ð2Z°!°¢w?,Ÿì0;&šº :q#•5" °t!:p$·Á 'Ccp ¿9Pô9PNð9@ð$›9#Ûž:Êð)¤5`<&÷ :% Pž8" ÿ:$¦>'¨?'ÿªA*¬B+°Fÿ.²H0·L4»ÿO8·L6²H2ÿ®C.®@)²Dÿ.¾P:ÀS>ÁÿU?ºN9°F0ÿ¯E0ªA-«Aý-ÿ4$˜1!ï”.œŒ07%¡ß=+¨C1á¢>*#¡œ¬@5€#ú0®pߘ6#¤A&p+˜ÿ8#—7"–7!k–6¯ "3 “3Ö€§—6°pÜ€ P– !‚;€Ä`}€7™ë@¿0;9'Á¡<)5°Á˜2‚ `àŸ;2”€,ÎõPŸ<,úô0•2÷!“0ñ—3" e<¨`, ðí˜2ÿ`b¡¥d@$ðTP=*nPœ àt€9%qPS€•G3–‚@Õ‚• @?1‹.Œ ‚'Al(A&@!‘þ03 ü ÿ™8#Ÿ?)¢@¿,¥D.¤BR°(üP°™5!¦A+ÿ´O8µO8³Lÿ5ªC,¤;# ÿ7¦<%¨>%ÿ±F-´G/¯BÞž ,¶H0œ °Bÿ+¢5¡5¦þy :%«?*¬Aÿ+¬A,¥:%¤÷:$«ÀÀD/«BÙ-=À3á<(¼Àœ4ÿ"–-‘)‹ÿ"ˆ ÿŒ%–/!œ4¹#Ž3àÍ•Š$àŸõ:C€#ͧD0©þ™ðD1¦E.›:ý%ˆÁ8$–2›~¼07#™5"š pØ †0mp:(0à§?í,Ó¤;í`%œ5ÿ!¡8%©@-­ÿE3²J7²K8\ÄÀ.¦?-P€–uðŸ.“,ÇÀžÞÊ 8'¤<¯ð/©B/¯G4Ùi Óý¢&@-©C.¥Ç@,¨QO°p#•º°1’1“Gpÿ$˜:&™<(›v6ð?,9@4!N@ûŽ0—!š<(œ>*š=Yp%› ”0¡ ' à°¡=/ ÿ%§B,§B*¯ÿJ3¹Q9¾U=ÿÌbJÎdLÃYÿA¸L4¨;$œÿ0Ÿ2š.ÿ 3±M8µQ{<²Ò©E/^pÿ6 )Œ(ï–3¡pI5«ûH3ó@¨B-š5ü„1;P‘*‘)ÿ’*‹%—/]%œ3 V £ PvN @*— ;%ˆ0âP ª`1Ð^p;&£EA8,,ð ¸b"Œð¸÷åaÉð;'© Ð=ß*¨<)£i€5!ýŸP1Ÿ5 ÿ12¦9'ÿ¢6#£7%§;»)ž` 2  `P4!¢8&§=+eáß>+¤:'8àœ1éäÐJ ª=C.¬cD0’ð͈0˜3…ð ’à›8##ð£,€À0 Ë!{ 7@1AÇP'—¾ppD0š@,3@Žÿ4!„)†+ÿŠ0Œ15<ÙQ]p›=(œÐÐÿ1’0“1·“0–pž=G &ÿ¥B+¦B+¥A¿)±M5§BO°"ÿ¥A*¤@*¬Hÿ3°L7­I4–úÀ8Ó $ B-¡ÿC.œ>)>)²”`˜½ð,ð<( °_.‘.(ñ0þ›à“.•0’÷/—uà6"¡=ý)¦`¡=(¤?*~®Ð¡<&¢>*Í`v¡€˜7€˜8²º°3 “ãÀP'°ô 3•1™2X€ù!up/á>+¦<(?¤8$¡6"8àMàÿ©<*®B/²E½2Äð±E2´øÀ>+«>,¤8%Ù0ÿ¥;(¡7%¤9ý'¯¦<*ªA/ÿ°G5¨>,­DÏ1§=*J {pœ5“ žÇ¡[€',P쀟-9C€"žtÀ8.€ Q¿‘1 ‹-!,ýÀq4 Š0‡ß+‡-<5ÿ Ž4 ‘8$‹ÿ1‹0‘‡ßŒ0“7Ð "”ÿ7!˜9#›>(ÿ›<&¡A*œ<ï&•3°”5ÿ?(£B,©Iý3~™:$’3ÿ‰+‰)‘4ýNÐ@+’4 ïˆ2ް>)”ÿ;%4—=(@ÔPTŸ@Ÿ@ãPº$‰Pü@`‡(†%ÿˆ(„$Š(÷‘0“"<'ŸO¢Ÿ=(>€Z áî³`9$—1¢•5!þ°0Ž.½0×@”3 ž°”ƒ1˜€¸À[ðÐ` ä'á®0-2ôðªB-¬9A.£ªÀ3à;o)§>,>©@iÀñ+/w°p0¡:(œþ@2!‘-’-/˜3!m0¥æðPÖ? ?+ó@«€ÀC.—Ï™Ž©b%ÐgðŸ¤1Й 5±ö¡8¼@&pZpžP@H@ˆ,K;.Ÿ@1Àp|ý‹@00’¿3•6‘0ý°–6ž=&óŸ?ßàæ .þu˜:#—:# ÿC,œ@*›A*ÿ£J4™A,Œ4ÿ‡0ƒ,’ÿ:$5’:#ÿ“9"’9#•<%†,–PÉPW ÿA-‹1Š15ŒF@/~!½P·QôŽQÔ ŽVð3 ™:ì#AЈñp'€ÿ"‡(“3!®@«@›<*Ñ $6pbÎ •´ ¯@ØP5#6pÈÅ 9 ¿ —{Pß 3!‹*“Ï‚¥põP³€Çœ:)Á Ž ´@™:ï)—8'@‘2"^ˆ)‚Ö-³þt@&C2˜=.¿”:)“9)W@%3>@"­à"ð—¥€IÕ8Kp9 ƒP•5$HpBеc°9âP"ž0PB].4ð—9$Zp‘›ðš7¡#±4”H0–ß7"š:$‚ð™9ß#<%÷Ð;$¿¡=&ž:#f0 ý=ò$£A(¤Cÿ*«J1§G.™ÿ:"Ž1‰,¿%“8"¥“þ—pG1–=(}û †Í*ˆ,ý†`6!—;&”ÿ:$6 6!û‘8˜@!6"ˆÿ0~'&€(}%ŒT€÷<)”º€@-”:ÿ&‹1 …-‚ÿ)(…+ω.ŒÉ°@2 ­÷p3"ó0”: ;ÿ)—:(—;)–[9'‚ 2>Ñ"0¯2!/³!ÈŽŸ1Å“‰R A8ý&¼PŒ1 ‘7%õB@8•@&Š4%ý„Ùp/ ~+kÿkjÿz, |-!{-ÿ w*o!{ÿ+ƒ3%†6'ÿ‹:+‚2#{*ÿ|)x$€ÿ+…0ˆ2 ­Š­ 2 Ò0ŠÒà4¡ °3°`—[ ;ÿ&ŸA+ @-ŸŸ@,Ÿ@+cp' ‘Æêà2ìà«p°™7ý"«Ð¢?(¢>'ï¢?&¡ü°<#¢?$£?%¤Aúàÿ(¤A'­G.®ÿJ1±O6²O7ÿ±P8¬K3­Mï5®O7Ý/ÿ‚$«G.¬Iÿ0§D,¤A(¡ý?»€"=%—9¾€"Ž2Š+1ƒ)‡-F ý‹Ì@;'›A. G2›A-@<Ð:So‰0´4!ð0~ð0…*ˆ.¹Pï“7&“V1 >¯/2 °@ªàþ‚PŠ-†)‰ï.‘5!ð'•9©@$”7&UA@K߇-‰0Ôp†ÿ-….)ÿ…1!€./ÿ†5'€0!‰ÿ:,…7)€2$ÿ2$t'q$ÿp$m sÿ&r%n"ÿw)v({,ïy+úPx'ÿ{*…2!+ÿ‰1 Œ5#ÿ3!3 ‰-ëŒ1ª0#¹à @,Bp–Ÿ¢à¢à=¯ÿ˜7$‘/,ÿŒ+0“ã2ç Ñ°cÑ?)¤úðA™`(¨C+¨ûD+P¨D)¦Bÿ'¢<"§A&ªÝC #¥@ˆ°$’ÿ.™6Ÿ<"ÿœ9«H.©B÷'¤?™À•1ÿ‹'›9 ¬Kÿ2µU<·X>±ÿR:¦H1ž?(¿™;$’4]<þ9 * C.£H2š(ðž.`='€-Е:&“7“QCP‰Pÿ5!‹.‡,ÿ„)ƒ'‰-ù€‚‹/‡Ç*Ž*AiQT„)ÿƒ*‡-ÿ3#6$Š3"ÿ†.ƒ-*ÿ„.‡2"‚ÿ-})w$ÿg r!~.ÿ"}."|/#xÿ+ u(z-"ÿ„6(ƒ7'}/ÿ!v't%x¿)|+Ùp3ÿ%},0 ÿ/ ,ƒ/wƒ-ç0„*P‹‹0»°#¿°À…‹¹-€,Š,pî׊-¶±0ŠÓ-&@&@‘ư6#x!`p^Q/3»°ÿ “6 ›=&¢ÿC+£C*±N5ÿ°L3µQ7ºUó9¨ í9 £<ÿ$µN1¸Q5²K0©B&¢;ÿ¥>#©C(²ÿL2±M1ªF+vò@¡?À–5 Ðÿ™8 ›:" ÷>' )P9#—6^>0Ç“‰|ðžìü Ð`E0¡A-˜§9'•z!@#°@–÷:'—t(A/ÿš=*”8%“6m"ý “6=A3ƒ0ý N5$Ž4"ÿ‰0Œ4!‹3÷!‡0R@„1 ÿ„0 †3#…3ï$x'»€v%ÿz(‚1!~-ÿƒ1". {ÿ*|*‚1"÷}-Ö€‡4&yû&‰py&rïz&ñ€‡2#ÿŒ6&‡1 ˆ/)p‰/I Àžp#•7Vаø&ç ²t0 ­œôÐ@+œÖ0ý7©à!“7$˜,|P‘4Ü¿§àš;)á ”2Ý"$Ð’1ç .1ìàÐД2 ±'Ñè C1‘ 0‚€yPpž^P5"‘è`µ8ß%9%Ž  5"?‰2‰1Åà±0÷›A)Ì`ŸB) ÿC*@%¡B'ÿ¥C'®K.°Lÿ/²M1¶O1¼ûU7°¯H)´L÷.¡:€®P6ÿ«M3¢D*–9¿Œ0–:È`$þÎp›?)›=)ÿA,¡D/œ?)ÿ˜;&—;%š=ÿ)š>*ŸA-›>*C°-а@-гç`þ‹€—:)¦I6§ßJ7¨K9m°žB/—;(  X ¢u%L Ž–@3"ž€¿2!‡1‰§€1ÿƒ/…2ÿ.{){)ÿx&|*~-߃1!‚³‚Š6ÿ'ƒ.}'¸ `Q i8(i7êE°( @–´à6%™ÿ;)ŸA/¢B0§œ=+© ‹óU3"¬¡“±àÜ0¡ÿ¡>*£@-¥C¿/£A-ž=0ð& Zг B`3`d€—†°7º1•0:'’@6ï#Š1 `ƒ,ÿ(„-†/ß‹4p4 þ¨’8"˜>&–ÿ<$—<"’6ï•:–‚Á¢Fÿ)§I-«L0¬ÿM2¯P5±R7ÿ9!˜A*¦Oÿ8E/™B*ŸÿG0–>'•=%÷˜@)´À›C-™?@+–>)C0îÿ@,•=*Œ6#þ°€)|&…ç.‰–@F`:)‹Û5#ÞÀ(a¡8÷(ˆ2Ü #,ï€''p0 ‰þ˜±"….…-ÿ†0‰1!’;_(”>+‘Ö0?ѯ7$ˆÆà.bÁ†Ë0Œ@†ÑÑÀ!ÿ:*7&ƒ+ÿ6&‘7(›A/¤I8—;+U ¿…&„%…P’»3!a œ;)£ žÿ>,¨G4¢A/?¦C0œ:&¤ =ðט6"àœt€6#ç–4"È@¬ •4"¼E`d€”5#‘\P-‡+‰,@ÿ—<*•:)3û%‰Q@+~%ù†?p¯4$‘;*÷:(×Њ6&ˆÿ5$‰5%‡4#¿8%;&ìЕÿA*•A)—B*ÿ•@(“>%‘<ÿ#ˆ3Š5Šÿ4Š4—A'ÿ’;"Š4”>ÿ$Š6˜D-—ûD,øÐšD-9ÿ"9!Ž7 ‰3‹6"…2‹pïƒ.=à…2ýˆÒp7%Œ;)‰ÿ8&Š<)„6$ÿ~1|.t&ÿy,y-€þ¶€9)…8)†8ý)h@p%n ÿn!s&|,„5%…1"ApÑ„pÚ ¶P0ÐÐ!Œ¿6$‹5"ƒ€<)’:&‘9%£ÿ1ˆ/„+–†-rPá0÷ ™¿?.C0šx¡$˜Å¡† · 8&a | ¡ÿA.¨H5¬K7ù§SPã°6"-‡“0Ô@W0çÕ¦ûF1ð£C/?q+ª@ÆC Š0ä0„+ƒ+€.ðß*€-¦°+ï-²°t"u$u#vLð÷$wÂx&ò€pƒ¤°ë`6$ˆ6ÿ%‡5"Š8$ˆÿ7"†5†6ÿŽ<&’B*™Hÿ0Σ•¦T;¥ÿR9¢N5“>&ÿ‚-„/…0ÿC*˜?&œÏC*’:' 0$“÷:#”ðÐ=(’<µ(7à°à8$oð†üèÀgñ$‚2!-ÿ|-w(~þÐ<+Š>,Bÿ2‹?.‡:+€ÿ4%w*t(ÿn#lr%ûwÍ0. ~- ÿ},~)y%€) Д°ö0•i9±P)a™J°?+â±ÆÐ7%@@´‘4©'‘07Pæx!<ÿS0'’2 ¾!Ð;Â-›<‘Ð ²’Ua0 ›a0<ï&>(³@œ='æŒ>)Õ`&˜>*þ½Á<)“:(ˆ1ÿ~'}'}ÿ&+„0üƒ@¾°+y&ÿ~*t!w$ÝÍP…2"àЀ-/y$~ `•Pý7Šà v$t"ÿ}+-•ÿ?)“?(Ž9#ÿžJ2¤N7§Qÿ9¥N68!ÿ6—<%š?(ÿ«O5±P5²Rÿ7«L2¨I/œ¿>%@(¸À=ÿ'B*—<&“Ÿ:$‘9$lÀÃÀý9<&–>*Ž7÷#‘:¶ð*8&ý‹½ ?-“?,”ÿ@.“@.†4"œ¯€×‡5%) µ€‹÷8'†ú0:)8ÿ(Ž6%5%1`ÿ!¡pš ­@0`[€ÿ¢D/¥D/¢Aÿ,œ;%œ<&ž]= ñ¡@,  ß&ˆ'˜ ‘1ÿœ<(Ÿ=+¤‹C/»MPÐhP/ýE0Ž.Ž.?–7!1ñQ0o—8$žg`C.R°œ®0ãp’4 04°šï?*“9Í 5÷ ‹1ºP†.ç‡.¸àÃÀ8$ÿ’<)Ž7$‹4ß"5#…¼à0ù‹÷ÀBÐ7&6&¢›@ŠI!nÀ“°!¾á,}vPŠ0‘6@þšp•9"–:$ÿžB+£F/žAþŒÀ0¥F,­L2ý­‘ÀI-µR6±þ#€L2§C*©Fí,«`œ;T€%¡Aÿ)›<%”5!™üMPM°D1¦J7¤ÿI5›@-š>-÷—<)ùŸC0ŸãC1y±Vz0!ï2#“8(,œAß/6%œr˜;ý*|€œA0–9(_‘3"0s!hо$›;'™8%ÿœ:$™6 š7Û!š¬03)0ž:ÿ%¤@+«F1¨wD0£Ú:&–{ÿ1˜4!–3!ñ 8°ñ¸ 8$•3Ϙ6$ ð0`š;&š:&?*’{š<¼ (žA, ßž@+—:@‘þmÀ1‘4Ž3üY #a‰/4‡•:#É`ðæ <”Ó9$°0*`”C`=+¿›@,š>+Óâ% ’50°#‘P‘PªÐa°ýâ!"‰.%}"ˆ+pîð`•8$­p2ÿ˜:$Œ-’2ý4€‰'”2ÿ =&¥?(ºSý7€´N4­G-ÿ©B)¥?&¥@ÿ'¨C,¦A)¦ÿC,œ9#-?“1‘0ný>?À‘2‘1µ °Y#P˜Ð’22À B`=+ž?,Ÿî {<)À™9'›¥@8&Ÿ?->/‘T0`O@˜080&ÉøÉÚ@20¢?*¥@ÿ*¥?)¦A*¡ÿ;$¢<%¢;%ߥ<'£;±@$¦ÿ?)¥=(§@,ÿ¬E0§A- <ÿ'ž8$›6"Ÿ¿;'¡=)Ÿ+`=(—5!ž<)»û›:° ,¡?+Ÿ?*Ÿ?)–8ü°1—8"´ ë>ð°*²A+›Ò Q+ ó”D5 ç˜<('P:°œ@,6&™> %”­àq@#?+HÀv€èà’ŸÐæ°Ù7AÀ–$•P.?2/õ0kÐþm€™;&‘3“û4Û£C- @ï*ž<%„P‹(ÿ‘-•/¡;ý!€¯H-—1ÿ¥@(°K3¬Hÿ/©E-Ÿ<$–ÿ2œ8#Ÿ=(×¢@-И 7%vB`¡B]€2 A¥é1tÐ)À/ð$$tÐzП>,¥ÿB0Ÿ>+Ÿ>*÷=*ež>*¢¿A.›:'šŒD%ÿ§E/¥A,£?ý*@¡<'¤@)¿§A+§@*²@£Ï:$¥<+b­@8"ÿ§<'®D-°Fï1µK5A`«A,ªB,¥=)¨¹ÿ9' 9'6$ÿš4"9%Ÿ:ÿ&«F2­I4°ÿL7©G1¢@*ï >(šsÀ7!›ß:$—6 ðŸ@û) ÿpE/¤G1×A+<""6Þ!7"¡a8#` Ž6!’êЃ°ü$!)È—–8ý$a°1Ž/Nªp‰*¿pƒ ™p_,- ž¡@_D1£B.‰ž“ý@Õ-§F0¢?õ) 0›'1–1ÿ+–0Œ+ï.á˜8#wš:%æ`Š+ý±ÿ5#¢F2¤H61ž}€x "9'È08ç–:&Ñ01<)Ã?,ÏPj@í-£B¿/©H4¥Dp,ç¢?+>0$À§D/9ŸÎ@Y°4 ˜-1Špù…pba<&¡='ù „²P9$œ5 ÿš4  9$š3ÿ 7"4›ÿ2Ÿ7"Ÿ6 ÿ¤;%¦=&§>ÿ)¢9# 8"¤ÿ<'¦>(¨A,ÿ©B-¥?*¡:U%©p•y /êq“ pÿ/*’0ý–‡Ð8"£D.£ÿF0§I3 C/õ˜ÁÀ4 ð6 þ¬à™B.˜C.—ÿA-”>*’<'½‘™`:%:ü€ï†0‹mÀ6!•û=)Ï ›?, Bý.K@-¤C0£zU€Bó°/—6$L@¿,Ž,ÍŠû)f€‰)‡(ÿŠ*‰)„÷#‹Û`+’1ñ ð=AmÀ+†#˜9&ª  6Ô`Š+DÝ`>ÿÎ0‘a€6%ŒÈàÏ 4"Œ00ƒ øêêg@ž?+ Bÿ/¥F1©J6¢:O+´P:$‚p`§C-«G2¨`ÿ@,¦B-¦A,¾82.§B.¤u`;žœp(£@*ó€Žp—ß4–3±P <úž,p©E0¨Cû.©`>)9#~Žp“.“.‘p°a Pž@=' pÿ7" <%›6!¾p£@+¢>s‘žþ„;&Ÿ>(˜9ý#P‘4Œ0ÿ33Š0¾, †-…Ÿ0¥0€ˆgÀ×à5ÑÀ ùŒ8à>à,*‹†, - ް –qA& éA)¾¾ÞP!‘H0@½0f.œ€ý±4!00ª€vw‡) ¡ˆ)ûç‘2Í—0ÿ‡+‚&„'ÿŒ/œ?-¡¿C1œ?.–‡ :ñ'!ð;’5%–ë;*¶Ð”a€4 Û2 ¨,…°£F2¦H5¥G4Pÿ20Ž0ï”5 ’B-¢f%ÀE0’М=Š¡þî@¤E0¦F2Ÿ>߀?+”4xP  ÷Ž/v –6"™Ó9%¯ a:ß$Ÿu=‡ '†™9$‰Ð?š9$ >) v@ÿ–5 ‘1•3ÙD1ü05"D0™7¢í \0`”@ŸÔ¢šû:$Ü 1Ž0õ¥€–Ë =(Ç—ýŒ- ‹3!‹3"ÿ’:*ŸH4˜A¿.™C/–@Ð(ÿ•@,:'….ׂ*_ÀÅ5÷"“:š`"2o‰-˜à,ö!ï6$“5„°&š=ÿ+ŸB0@.Ÿã@.è°4pÝ`‹.페à+ò0‡*ÿ…)Š-Œ/ýBÀ‚($ÿ…*Š/Š/ÓŠä`0Ð*î1‰+ÿ3"•8'“g5%’çÐ1 0ßàÿš<+ŸA0›?Ù-½°c°Ž2# Ž~ü5"7$P÷9&OÀ9&‹4ù!šàE°‡0‘:ý%L™@-—=*ÜCp?P5"NÀ“9ã&”=À4PI€F3ÿD2—>+“;'¿Œ5"‰0' Šþ"òŠ/’8#Œß2‹1JÀ‰.†+ˆ-`Pü‡±ZÀ,„'ƒ%Œ-†(@ï!—7&s@œ<*¶kÐ<‡¡¡@j(¿0‹-s Ž†€3!Q‰p‰ –B£-“™`>·’‡ß°5ÿ#Ž:(›G4—ÿB0:)ˆ3"ÿ~*„.….ÿ€(ƒ+…ÿ-5%œC1ÿ E4ŸD3œ@o/—:)0›=—`¶—`*“R 5$I ›ÿA0¡H7›A1ÿ’9)‰1 }$ÿ}#’<,…ÿ.y"w z"(ˆÒÀû+ó 4$4s#"°°/DÐç0‹Y m!6þ¾`*›C0›B0–>-•=,”âðû9&jÐ;(Š4ß"Š6#ŒkÐ;(îËÀŒ8'ÉðŠ5$ÿ“>-Œ7%‹5$‡1‚-³ÿ¿‘‡„/ˆ0û ˆ´‘$Ž7&–y°<*<°ñ°kÐ7¿#‹33¬`$?ˆ/Ž5#Q°MÀ¿“9'‹2>ÀŽ6À¡Ð°NÀ1V°^Á†Ì|€ê`5"HPÖà1ÿ‰,‚&‰ƒ+cP!PðrPË`™Þu0=) E0.‘þJà/}%~'ï‚+¤†1 ÿƒ0€-|+ÿ€/x(zÿ*v&v&ÿ}-€/ -ý]àx&|)ÿ†3%€,*v"o uàÿv sw!÷€*;à#:+ÿ”?0Ž:+‘=ÿ-•@1—B1€ÿ+{&z%÷{'ʼn3#ÿ8':*7&ÿŽ6'†/‡/ÿ‹4$Ž6&—ÿ?/’;+’<+ûŽ9ÊÀ#½ˆ†ï2#ˆ5kð%ƒ1ÿ"|+|*~ÿ,…3!†2!Þ[‹9&‡@ :)û;þà*;+‹ÿ:(…4#€/÷/cð…3"Šm7Z&‹Ð6$¼ÀÿŠ4!Œ5#†.ó…ëàfÀ)Œ0¿Œ2‹0Ž÷3 *à–:%“s7"Ú0Ì€‹/T°oŠ.Ž´1 ‘g4#Ò l°™=DQò™°‘KŠ0/Š,‡*Œ- ÷. Œ-„ß&ˆ)žð…&ûŸ`1“6!ÚOp— >+K°ˆ2ÿ|(z&ÿ/!}-‚2$ÿz+r$q%ÿjp$mÿ#q'x."ÿy/"v- m%ÿk!jqÿ&z/!4%ÿ†:,3%}.ï y*)zÿ({)v"–Å•Aà(<à³¾ëà/:)#ðŽü¯àð4%8(‹ÿ6'„. …0!ÿ‰5%†3$†4ÿ%‡6'‚2"€¿2#2"|aà*ÿy*|,~¾Ï3"‡3"…Єÿ0+ˆ4!o…2 †îà3!¶~m‚.‚/pß‚.‰3»ð"‰~ß°3"4#‘¿ý4IÀ!Ž3 ’6¶'p&u0:%}`š?7#ž<'ŸcþÆT04 V00ÕPœ=ë)šT08…0—9ï&œ?,[p?-ï›=*™~À;(šæüÀ4!û1p‰+ÿŒ,ˆ(†&ÿ”3”3“ß2/nÀˆ)¿Ž0 A‹ÁŸ_B.¡E1P&’¶Ó8%K°ð°B 6 '3ÈÞ°U æ¡1V0 @˜5 ÿ£>(¤?*­Gÿ2±K6Ôž’«F0¨ÇP'`üacpd0«)˜ú3Fð!_ð˜än@öÁ*Ì ]P„(îì0‡*Ï€š;(þ ¥E1¡A-˜Ê‰@7°"ž 0•5   —7#%prPPû›>y *™>,›ß@-–<*XÐ’8ÿ'„,‚-„¿1!ƒ0"Ø 2ÿ$w)v)wÿ*z,w,Ýwaà. r1#÷z0"ò z1#yÿ/!s'y-Ï{. |2Qàs"ÿ{.ƒ5#…}5 ð.yiÀû0‘,‡3#üÒà«àŒ6&‹6%Þ:†1!†¤Ñ"‚ß-Œ6(Ïã7'Œ4$‹3# UÐÅÐ4!Ï€´€×1×2!’ÎÐ2o0"ÆÌ1  À,À¢Iÿ7 G5˜@-™¾Ö°<*”<)?”:(q0]òuPrP• ×¥D.÷@ Â :%üˆp÷ ’2“2N  •6"Ë`!P–¶Ðîq03 Žƒ-ÿ)‹3$5&¿Š2$“9)¢°Ã$ôÐ" oPß&–÷7#”±`.•4žK@/@@¸£ÿC.§G3¤E1äÞ€!à‘0 ¶>,˜þrò4%‹0!„þFà**~)ÿ."‡5'ƒû3%Åð|,…6ÿ&A2B3ŽÿB3„8)~2"×5'ûð}Y4&ÿt)r'l"ÿg u*~¿2!z-•Ð4ÿ!‚3!‰:({‡+}ò0w¡ÐC1Û ‰Ì8&±à•?ÿ-œD4–?.“ÿ;*‘8)Š1"ã‹2IÀÈ€Š0‘3õ!y0DZŒ,‡(1’e0}3Ô€)”8$“5ÑüÍ‘ ‘7%“:(ÿŽ6#Ž7#6ï#‘:'[Ж?-?–@,“<)ð° À}Ÿ“ E1 D/à6!à=þRC.ê€üP'–8#žÀoP’® C€g=*˜À .°?,/ÀÝšs°G5™íÀ?-ަ0‘8'Pî0²Šÿ.3œ>*ç˜9%ÌP!àŠ+Ç‹,qÀ°ñ/‰7à(‡p€¥1ñèÏ€îÐ…(„Ÿ+…+Ð!°…ÿ,†.*ÿƒ-(})ÿƒ/ €-Œÿ:*ˆ8)y+¿x+p$Ôð~ÿ2#y.}3#{{0bz0! `ÿ|2!e o%n"r&Ñðÿt'}/v'ý1`x&~+x(y(€I'‡07«i"Å À€‹J`4#f°—8(Ÿ>-œÐÿ:(œ9%—5!ÿ.”2™8šÀ%â7%U nð˜ÆMp;)ÿ& ‡/ï‰3!¹À„.Ï„/…‰ÕÀ*§†0+š`ŽÄ°3‡ 5m!àf°Ã°œç>,—:d±!2û Š&)„,€)†,Œ"°ÿ2 7$”;)úî`ˆWð3!(ÿˆ/ Š0!‹0c –ã={À@,ÿ@¸ç@ðm0˜;'ë–&÷6"'pžÀ’q`@u1Z`"= Š01Ðt¢°ÑP†S05$Š>0û5%÷0„.‹6Þ~Ð%‚/ Ô z(ýU2!}/w3#æ x-`ÿs(q'p'ÿi ­†dÿk$u-!ÿ‡=,ˆ>-Fÿ4‘F4ŽB1–ÿJ9D2~1!{{,Dà|+䣉5bp8€¼àß`Šù0À`Oð'œ>.Ÿ¿A.¡@.šñ1;”ç4"¡KP'ÀÖrP8&j`ŸR€F4k¤Hi +¼!=+Pÿ7&‡0!x"ÿx"x#}g(…<ÀŠP7%5Àç8%¯Ð# •:) ÁþÐ6"zð^ zðe ~å0–:)’7%O`®ÔR"‰4Q0(þ²°/~*+ÿ~+}*ˆn8Ð<,ŒÁ€5%sÐ8'™A/•¸€¿8&‰/ˆŸ€.1= YÀYÀŒ0o šÀž‡`%˜:(^ 0‡*‚%´°ê°C þƒP3%ƒ+‡í/#°$‘‘à;)Šù4(ðg€#„2#{ÿ*n_ ÿ]^l!ówhM<-{2ÿ#|5%l&iç#w @#06$|_2 €5$(taÿ 4$‡<+›ÿN=B2„6&ÿ|-nu$ý:`w%v#wy%Ÿà*¨°üîÐ|0—9%’2 ÿ”3!•4!—5ÿ"˜5#œ:)ÿ;( >*Ÿ?,'ž>+¸ é™(rýG€}ð’6"Að¾a`€ù.£€¬€‡-†Ã+GðG€å“4í v ’3Û0#•8»$—!À;(”þA.5€Š5#‹+0êàï},u&`%nÿ"jm"?q$n! ñÿu&z)u%ßt#t0(÷„/+‘:)‘;:(P•<) Á`Á•‰EPïŽVP—8ÿ%>*ž@-£ÿE3ŸB/ C1¿žB0ŸD1 ÀŒ.ºÀ0‡ìa ÍÑôà{5##ð9'„âáÿw'oq#t't(Œÿs(v+‰þÏ€B0.q ÿj h oÿz,t'÷n · p"€þ/01!ˆ7'€/ù!ïPBà€+†/ù Ž2#‘5ý&þÀ—9(–6%öüp”3l˜5!þm`Ÿ<)¢@,£@,œ:&ž;l`$™7"ž<(Çÿ(ž=(‘1ÿ/Œ,‘2!}šk`<*¡B.Œ ü Í“3—6!ß™8#‘0u`•÷3 šì<(•7|çð0ƒ)‚\ý4E†3"},ÿv%u'tÿ&y-w,ÿ{0"p%q&ÿt)r'rÿ&r&s&Ïv)€P0»2"7y*Wà~.npuÐy$`k€‚+ƒ%ó0©Ž`“8(•å9ǰ'y0y0™<)ÿ¡D0A/£F4A.”7%÷ý˜à9$¡F1˜¹=8¡p€'×Àsÿx"†1"ÿ‘=.J8=+‘/À–ðÚÐþBð3 ‹4!‹4ÿ"Â“Š„.~w(u|á|'žàýL0„,{#ç)0à¡‚†,þÆ`!‡,‰,ÿ•7'—7'>ÿ-§E3¢A.§÷D1¢6P<(¢=ÿ*ž9%¢=)¡ÿ;&ž8#¤='ý¥Z ;$ªD.©ÿB,ªD-«F1Ÿ:%Ÿ:&¢€ÿ;'¤@+¢@+ߘ4–3´À–ÿ1—3—2–2’.—¶Áÿ ”1•4 ‘×2ŒÐp.À„û+š`ƒ*z$|(u!û#‡ s#lÿlt%wÿ(~/#ˆ9*î@ƒ5%›°|-ýð5$‰8(ŽŸ>-ˆ8'OÐ}ý+í€.‚0Œ×Ð7&‰€Ð+}‰Ja%•;(™àÿ=(’4!–6#ÿ™9%š7% =ÿ(;&—5£ÿA+¨F0¦E.ÿ±P:=)0ù¼€Å€1‘6ÿ"ƒ($„ÿ)‡,"¿n {e —»:(€ªN;kPœ@- E1å0wðp׊/n ‰%+äÍ`Ê`•ýn01!’ÿ2!–5$ž=+ÿ;*¡?-£?ÿ-™5$œ7$šÿ5"Ÿ9&ªD0ÿªC.¨A-¤<ÿ&4 6!¨ÿ='«A*²H1ÿ¬C+¬A+«Bß+ 7 ¥àC,ÿ­E/±K5¬Eÿ/§@+§@, ÷:'RÐ0(ÿ”/™3!›ß6&œ8'SQ6%ç=*÷âœ=*€¹€)¢BP7"›5ï 7 ‘À¯H1ÿ´N6ºS;³Mÿ4®G/£=%˜ÿ1–1™4þA!@*™6•1ß’0Š–°"þ“1™8$›ã:&5!áàzÀC0©ÿK7¬N;§I6¿¥G4¡B/%ð‹¿*Ž-ÝÀ)û’oà/“0þfО:(9'§ÿC/¨C0¬F3o«D0£ƒÀ9%sðÿ§?*£;'©@ï,¦>(‚ð¬C-¿¬B,°G1à¨ÿ?(®D.­C,ÿ®D-´J4®Eÿ.­D-©?)­Î˜ðD.¤Õ°¡À9%o£<)¦°>)ÊÀÿ“-‹(“/ÝÄœ;'\ š<½(~Ð>)ž÷p?+˜8&H `Ð!‘Ÿ1‰*÷ðÐÿ/0–8'?”5#š;*Ö`³Pþ$p0”8&•û:(¯‘,€&݃'€,ˆð2ù‰?àõ`:(–=+;–&¦<&¡7!oœ4˜6 08ÿ™6!…#ƒ"ûŠûñˆ)‰ÿ+„'ƒ&®n ‡+€!,®‘€Ÿ&Š/F qã}ÿ$&~&þ! ‹4$Š4%|ÿ&w$„0"ÿ†1#:*‘;ÿ+9)’<+ŽÞÄ@8&ƒ+ä`оð/˜<'Ùñ@ß+¦G1§˜ H1÷Ï›Ä0ž='§¿F0£B.©¬ÐKÿ6£C/§H4ŸÿA-œ?-›=+üÑß0Œ.…)ï&…> .„÷*†r€&ƒ(Ù A°+°1Ï&†Lpš 1ÝÀ.|V$ÒR0…dp%Õ Œ7û(ŽeÀ?.’:*“:*—?/•h`ûB1±ÑB/š=+ÐD€\Qqp?YŸ?½+¾0™7#ªÀAß,ž;& ¼0<%ÿž7¥=&ªB÷*«BáµL3ÃÿZAÀW?ÂW?ÿ½T;³I1¼Qý: ð¸P:¸Q<÷®H3¬À,Î6"™7 ‰`:(Ï¢E3ºÀ€7$ýë8&‹1Œ·2!~ìÀ#âÀ‹ÿ2!‘9(‹4#ÿ†/w!z&ûz—-ƒ2#ÿ€. 0"„3ÿ%Š;+‡7(ƒÿ4#z+w'ÿy(}*‚.{‡ À3Œ4ó`¿"4!“8 PýÅð7"/–?:%‘3ÖÔÀŸ4 ’5$ê@6 ”s6%°Ȱ’7&A€ÝÙ 5"‹c€1íˆÑÀ;)U`Ž2!ʼn‡à+¯€Gq”`†,ÿƒ*'„s,€€„/ X÷|' 0‹8)‡ü aq!-‰3#„/CÀWp$ œÿC2D3™?.Ï—=+‘ÓÐéð:'æ” @OQpÀªH5¿ªH3£?+àŸï9# 9ŠÀ&«Cÿ+°G/´K4¹ÿP8±G0µK3ï¦=%§ä@A)§÷='¯˜ ?*¦@ÿ+¤>+­H5 ¿<+š7&ŸÑa(|‹`ˆa<*—<*°ט=+›·@<*ÿ“8'Œ0$ùô O ’8'6žÓ€(Œ4#}à¶°wÿ"sv#¿y',É „Üap58)†"Ð7'¿Œ9*’@/P79(Šà.©`‰àš¦`ˆc@2 šP- “;9'<6$î`¦’ÿ‘7%‘5#ö¼7%@5#03 \€’râ;€€ðU`5@c qà‘7&·5$‹’P*ë`Šz‡1EÁ)ƒu@¿-„-u@,ýÕ Š5&‰4$þŒàÄ•“<,“Û=.^ Œ3™a4$”9*Ž2"=P?3"Ž1 °Ð`ÿŸ@.ªJ7­L:¬L8©H2ÚàÏ’0›°;&ø P  ±K6§Bý-”/Ž)¿™4 •/|À¦?C/£@-œT€ëþï`,’5"®Qÿ@­R@³WE­ÿQ?£G5š>,ü5@90ŸA/¡B1í£X ?-È@¦G5¿¨I7©J9Q  ¿A/ž@/œ¦p4ÿ$‚&~$~ÿ%„*‡-ö0†-$À#™@.ÿŸF5–<,6ï%‡.t@†-g‹2"€S@ˆ0] û"Ф7%˜?-ÿ”<*‘9'–>Ÿ,šB0šµ`©`?í.˜='P+™<í*K5$€˜:)ÿªK9¨L9ªNÿ<¤H6›@/™Å<»@%E¾ Ò` A/0›>-Õ` [ lqß.’5&7a"ÿ3$‹0!ƒ(ÿƒ(…*Œ1ÿ#•9*4%ŽúÀ5Ä+œA0£·F6Ÿ±@@0°p’ÿ6&Š/!†+׃)’p6%dåP<”% RÐ:(åPäÇPÉÐŽ¹‘¾A›?-ü¾P¡E2«N<ÿ¯R?³VC¨K¡:³ƒE`˜‘Ù 2!˜;+q ¢ ÿ’A2<-Œ;ý,k±#w$€·,ˆá‚Š3~ +ÿ7)ƒ*”;ÿ+“;+›B2¦ÿM=¨N>ªO?ÿ©O?¥I: E5–:+Œ/˜ÿ0!”3"œ;û)Ÿ¾a/ž>-–¦MP3#_@p’% ;ù*0¤@Œ7'‰5ÿ&‹8(‹9)ÿ/ƒ1"†4$þÏ ‚0"€+pÿp v"ÿ~)ˆ2"Ž8ï)‰2!}àz%ÿ†-ĘŠ7ï)‡5'@x%ÿy%,…/ÿ!Ž7(Š3'‘_:,’;.Œà–+0ÿ>/›B3žE7ÿœD4š@0—=ÿ0˜>/˜<,•ÿ;+4%Œ1!¾žpŒ. 5·P'~3`”:,Ž6'Ä4$Ž:*‡4—@ÿ%ƒ2$|-}ÿ. t'w*ÿn$w.!x-ÿ!x/#€6(zÿ2%„<.‰@2ÿ9+„;.„;ÿ-x/"ˆ>0’ÿG9ˆ=/ƒ8*ÿy-d cÿmz*…¾`8*0! xÿ7+v5)w6*ÿj)_Zÿ Y \gÿ%w4(s/#ÿs-!`Tÿ^ctœšx°+~Ê „@2ÿ$‡4&‰5'‹ÿ6(–?0•=.¿˜>0™>0ƒp•ï8)–:G)žCÿ3“8*8(ˆ4%‚/~.  ó —¡"x,ÿ}2${3$~5ÿ&|4%x0"|û5'`~8,|4ÿ'u.!t, j¿"o'mr°,ÿ~7+}5(yÿ5)m)aÿ`]^ÿe"r."qû, > f ^ÿ ei"tÿ*w+v)ÿ{, €0#‚2$…5'ƒ1$’ ÿ‰5)‰5(‡3ÿ)‚/%x%~ÿ,"/$."ÿ1%|-!u(ÿw,p)aÿ^XÿZ]_"ÿY^#TÿU^&ÿa)!a*!d-ÿ$^%Y!gÿ.#d*f+ ÿi.#i-"r6ÿ+o3(w:/rÿ5*i, i*ÿ\c#d$ÿl+n/#bû"°ZVï ^¨g&ÿa"^b"ÿY_jÿ$bh wu+|/! Ðÿkklÿz%”>/–ß>0›A3›@ÿ2”7+—;-—:,Š- ’8F@ù'pÁ€ƒ/ ƒ1ÿ#Š9*‰;+†_9*€3%NvOÿ%p&v-ÿu+ s)i#ÿg crÿ,8+„=0ÿˆC5;-{6ÿ*s0#i$eï#]'±a~ܰg%d"Àÿc _dÿm%fiÿr&u(ÿz,}, s"ÿu#t"{ÿ(‰6)Š6)9-Ž9-‘°ޙ 6)†4‘ &…ÿ5)1$y+ ÿr'r*t.ÿ#q."i(fÿ'_!e)ÿj-$e(b'ÿYY gÿ.$m5*w=3ÿt:/f,"d)¿Z\ MÀÿf)`#WÝÀT °y:ÿ.}>3„E9{ÿ;0v6+r*ÿk#r)v-ÿ v. {3%tÿ,ƒ:,~5'Ý„²À3&r§°)o!z+ÿ:+˜E6–B3÷–@1ý€–=.šÿA2™@1C3§˜=.˜p‚°‰ `$íóÀ/.@%™<¿,›?0’7¨P'÷6(0Š6'‡ß2$„1"Ð/½!޲+†7( Šÿ:-1#†8)Š1~»6)«À†>0 àŠÿA3ŒC5u-ÿ<-“@1‡4ï%.Д@1ðÒÀÏÀàà›F8›{F7€Ð›E7}Pó;-ý€0’9*Û7(îP‡-ð !ÿ4#—;+ŸD4÷™=.¤p›>0šw=/œ„Ð:*އp§.„Π΀+©ÐüRP‹€5%”;,ÿ˜?0˜?1œEr‚Ð0FàzЇ2&À¿8*—B2£à”û@00€, }(ÿ~*†2'_:+’>/¦€}½pþ–p>/—@1šCÿ4•@1’:-šßB4šB3ßàœBý5Rà”;-–<-?5%“8('<`=‘1`7(•7§0;0ÿ,“6(“4'–ÿ7*—9,•8+ÿ’6)‹/!}"ÿxo tï~&`7ÿ*•?3=1Œ»8-¶Ð~, ­ Š÷8,ˆà5(Š9ÿ,…4'“B5£ÿRE¡PD¥UHÿ›J>”C6ˆ7ß+†4)‹À;/ÿšG9˜D7—Cÿ59*~+ {ÿ'})…2'Y–Òp ñ'—q 5ôpï5œB1IPŒ3"÷'z@‰1!™{A1OP”<+•"`ÿ9)¢H8¥K;¿£I9™?/Øð’ß9)Š1!´ðˆ/ß‚*ˆ`2!}«BŠ2"‹2O@õ&° hà>-—;ö§ð$‰úÀ7'Š0o Š/eB‚) ý/ùP"4%”:ÿ+5&Ž4%…ÿ+ˆ,‰.î¡“8)yà•:)ô:P€pƒ€5'‰0ß" B23p8'p ð÷ ›pžB2¤pßš=-™=x°+£¿D5¥G7¥«p?ÿ0ž?0š<,”÷6&“ÝQ&Œ/ ï2"”Pà4%œý=À -—6(œ;ÿ,›;,£A2Ÿÿ@1¡A2‘0"ïŽ. ’n 0"œÿ=.¢D5©K=ÿ§J;¡D5™<ï-2"ˆâ„*ÿ&‚)…þä,Œ4&Š2ï#Ž6(—àŽ5&öLP…*ê ‡,àSüù€©L<ÿ¤G7¤H7¨Lï;A1£H8þžD4ŸF6 ÿH8³[K¥M=÷ I8!1;)“<ù*| ­@‹3"…-½p9'Š”`4÷"„/`Œ6%ÿœF5™A0“<ý+‹€‚)–=,ÿB1š>+¥I+6–§P3¹0'Ý6`¼1PM@–<*˜{=ÿ,—<,š=.–ó;+_@©2!ˆó-b@à“6&šþ;*¨I9 Cû3ŸÍ`F5¡A1ç¢A2†\p A1÷£E5ΰTC§ïI9ŸDæÀ+–;(”9(“9& ÿ4#1 ”8'¼ ¼@’6%Œ.`2ù"ÍÓž?/›<ÿ,=,Ÿ<, ÿ>0Ÿ<.™5'¿›7)¢>.? ›ÿ8'™4%—3#ß•1!£@5 +§ûE4W £A0¤Cÿ3›;+”5%Žÿ0 3#‹/î˜pB2ÿœA1àu ²$¦^à‰-Ü_p^à•9)w­Oû<¡ €<*¡@.þº`³S@®N<ÿ>+“4!!¿‡)‡*¿@¢ÿE1žB.§J7óš>@p@ Œ/¿Œ.–9%/@—ÿ:%¡C/¯Q=ÿ²S@½^KµWÿD­O=¨J8¡ÿC1¥G4¢B0ÿ ?.˜7%–5#.-`ÿŽ-œ;*;û)›F0:'š9'¾0š8' ?S0%þ0—5$¡@/¤ÿD1©I7¡A.÷š9),0¢@/ªÿI6¡@,›:'ýž²`?-²O;¬ÿH5¡>+™4!ÿ‡$,Ž,½#0¤B/ ‰Cÿ1˜9&0‘ÿ//”2 }šÃ@8%™9&0ÿ¥D1§E3²Nÿ=«J8¨F5¥¿B2 =-¥^ >û-¥Á`A0«E4ÿ±L:¸R@±Kß;§@/¨Æ0A.ÿ¬F3µM<¨Aÿ0¢<+˜2 Ž÷)”k€,:·) >µ0žæ?ÿ.¡?.ž=,¡¿A0–6%“à3ý"·aE4ªM< ûB1!!B1¤E4ÿŸA.›=)˜8ÿ$Ÿ?+Ÿ>*¨ÿG2°M9´Q=ÿ·TA±N;©Fÿ2ªG2¡>)£ÿ@+¥B-¡=(ÿ¥A,©E/§Bÿ,£>(™5˜ÿ5“0œ8#÷£?)r`«F1µÿO:ÆaKÈbMÄ^I°I5¤ @ÿ2¥>*±I5ÿ³L7¸Q<´Nÿ9±J5±J3®ÿF0­F1³K7ý¨Ç A-£<)™ÿ3 –2‘+ÿ–1¡=*Ÿ<ï)©E2t0¦D/ÿ«I4­K7§Dÿ/¤B- =)›÷8#Ñ@:&ªEï0°I4o`¶O:ß°H5ªCÊ0-¡ß;&¤>*ô@¡;ÿ'¢<(£>)¢ÿ=)£<(š5ÿ™6!—28¿$¤?+§BQ@/ªD0±L8²"Qý9Ë0£<*—0ÿ”.›3"›4ÿ$ 9(¦@.¬¿E4¶P>·FPOÿ>©A0¦?-¦ÿ>-«D3µO>ÿ¼WE¶Q?µPÿ>­I6ž:(¤ŸA/Ÿ=+¥ é0—ÿ6$/…%ÿŒ,š;)˜:ß(¡D3ô`C1ÿ¦J7¬O=£Eÿ2”5 ‘1“ÿ3”2£A,~=@°L7®J4U@ÿœ7!™4¨Cÿ,¦A*«E.³ÿN7¬F/³L6ÿ®G0£<%6ÿ¤=&ªB,«ÿC,´L5¬D-÷­E.äPž6 ÿ7!¡8#¢9#ÿµL6µK6¼Sÿ<¿T?¶L5®ßC-§=&óP4ÿœ5 ›4!¤<'¥?,©Ck`ý0iP9(›7%ïš6$¢F`;'ž9%š5!ô@fP$Pÿ³M9ªE17ÿ!›4™5šÿ4 £@,­E0ý²’@I4¬C-¦ÿ='£:%ªC,ÿ¥>)«D.­Gÿ2©C-¬E0¨ÿ@+ 9&˜2þ8`Ÿ8$ :&«ÕC¢A¨GA)²@”/¿˜3!›7P,¡<*£>,¦¿@ÿA.¥A. =+þ/0–4"›:(¢þ+PB0¤D2=ý*0ž<)<*Œ/!2$ˆ½p'•6$2à )ìpŽ1#š“ ÞŽ‘4"Œk)¿–8&ªM:ûp²ÿTA¦H5¥E0þ¨P™7"ž<&—ÿ4 <%¥@(_­G/¯H`(7pÿ£<$°H0®GþËP4¬E-§@(»¦>‘`+«C„@0¿ºR9µM4[p¯ÿG.­E,°G.ÿ©A)²I1°Fÿ/±G0µJ3°ÿC-­A*¬@(ÿ©=&§<$¨=ÿ&£8!¥:$£ÿ<&˜1˜1÷™6$p¢@,Ÿþ×B£B.¤A.§cF3²p£pY`¢>·@õ'ú@¥P?+¨Aû,§a$¡<&œÿ9"¤>(¥='©A,¥<'¢â 9$ž8#©CT@ý*g@¢>( <&ߟ:&¡<üq ;û'§ `D/ªF1ÿ¦A,¦D.Ÿ<÷(œ9Øp&˜6$ÿœ;(—5#0ÿˆ(‡(‰ß+‘3! Š/÷5>€”;*?ŸE5š?.1 ÷†,W€„*Œý2( }$x ÿx!y"…ÿ.‚+…-Ï“;*šÕ0?0H6ÿ™?-˜=*’6ÿ$’5"˜:&›ý<Ç`-©I3¤Bÿ,¡?)°M6®ÿJ3¸T<±L4þ1p¹R;¹Q9Ãÿ[CÃZB¸O7¿»R9³J1ÀÂÿY@²I0³I1ÿ§=$¡6­Cÿ*ºO7¿T<ÅÿZBÁV>±F.ÿ°D,¯C+©<ÿ$³F.²D,­ÿ>(®?(±B,ÿµG1±C-²D²ì€/e`âq?+,`—ÿ4!˜8&–7#ÿ—8%“5!1ÿ-’4"™ÿ:(¥E3®N:ÿ«I5§H3¨Fû1¤¹r§B.£=³)ÅpG@?+€¤ýC»`(Ÿ;(œ8$£?+¢@+›`ÿ¢?)œ:$¤@ÿ+©G1¤A-Îÿ™Ž›:$–4 ÿ™8#›;&Ÿ=ÿ*£C.¢@-œÿ;'™9%—8$ùª@~01‡,÷„*êð„,€ÿ*„/€,¿+-  …ö‰°1!Ë…1"¹ÿŒ…€-y&ƒ0!‰6&Šß7(v#ìx%ÿz&}(zÿ$t €(þ`€œB0«Q>¨ÿM:§L9­Q=ÿªL8¥F1-ÿ…0“=(¤÷M8§]0S>±WÿB¢H2¤J4¨ÿM7B,¥I3ß²V?±Tõ 3¬ÿM7–7>&û¦F÷0&«I2­ßJ3×¢•¥€½ZýCX £@*²N8ÿ¤@*§D-©Dý.îp˜3™3ÿ¡;(£?*¦Cÿ.£A- ?*žß>*™<(_“7&‘7&6&`€qŽ¡ ‘  5%ˆYàü‹ ˜7&Ä•Žï7%Š4æð†.ÿ†-ˆ0‹ö:€8%U”=+˜ß@,•=)‡€ŸEÿ2B/ŸD0¡þÄ!/›>*š=)ï0“‘%˜:ÿ'§H5¦G3¨þ?‘4£F1›>)ß•7$˜;›ð&˜þ…P;)—<*“:ß(•>-•J=-ÿ‰5$€,|*ÿy)|-vû(H°w)w*Û~Ôà0!T°x+ÿy-p%aÿ ceÿm!{.‡:ÿ+‡:*Š;,‰ÿ9*}-{*ýŸÐ4$;+‹ÿ9)‚1 -ÿ+y3$‚;ï+‚;*¢°r*ÿh hs*ÿ7$‹?,‰ÿ=*5"1ÿq$}.„5ÿ#Œ<+žN:ŸÿN:¨VBšH4ÿ™G3›I5•Bÿ/‘?+ˆ5!€ÿ,‚/…2ÿŽ:'’>+Œ8þÐ#ƒ/w#ÿz&|(y&ÿz'+„ß2 /Óá-ÿ0 2#€2ÿ#3%}0"|ÿ0!z. v+ÿo$o&j"ÿm%p&sû)GÀz0!‚7ÿ(„9*€6'wû*H°s%{-ÿ€1"€/ }ÿ+~,|*äÀ9°Œ› Ø0C1–ÿ@,–?,8%ÿ:'—@-”=ý,O6%….ƒÿ,ˆ2 ‰4#ÿŽ7'9(‹5ÿ&‰5%„0 ƒÿ1 ˆ6&„3#ïˆ7(Œ7°;,{?0u°|/ vHÀÿ&p%z0"ÿv,p'o&ÿ_ ] aßj#ïÀfÿl%k$nþI°0#o*j%ÿl(f"bÿf"l'ÿg!;*y3ÿ"w/€8&†ÿ<*{1"‰?/ÿ†<+ƒ9)Dÿ1ˆ>*‰>+‹ÿ?+‰=)ƒ7"ÿ‘D/—J5¡Rÿ>šJ8•E3ˆÿ7%€.:'ÿ‰5"†2 9ÿ'Œ8&’?,¤ÿQ>­ZH¦SA¿¤Q@”@/°À‰ß6%‡4#…Ñ5#ï:)‡6&ˆÿ7&„2#ƒ3#¿€0!y*r°{ÿ1#r)q)ÿk&j&l'ÿm*k(iÿ&h&i'ÿk)p-!m)i%h%ÁÐÿq*w."{4ÿ&{2#~4%~;5%MÀ}2#ñÐ/À4&~2"òÐç/~àd€.ƒß4$1"E°|.ß.Yà8'ÿŽ>.ˆ7'ƒ2ÿ"v&v%yw+z96'€½ß.‚/ Ú…3ý$<á/ w%xÿ&.}-ÿ†6(~/!~/ÿ |.y-sÿ(r'r(ÿu+}3&z1ÿ$x0#r+tÿ- q*z3&ÿv0"g!v1ÿ$s. r,Žÿ<*•C0‹9$ÿŠ7#”@-™Eÿ1¢N:žI5™ÿD0‘;'Œ7"¿Ž9$™C/ƒÀ•ÿ>*’:&…-¿3˜>)Òà—ÿ;'Ž1/þ°ž?,ªK8©ÿI6§G4¤E2æÿ!A/ðࢠŽ/ þ3€‚%„%Š÷-—— >-šAû1š½9*6'ÿŠ4$…1!†4ÿ%‚1$2%‚ÿ5'y. y/ ÿu,r)r*ïn&Aðo(ÿq*u/!y1{#s…ám'8ñÿ*p't+¯r)pHð(añlÿ$t,v.ïs+zdà1#xÿ-3%{/!þ†ðw,s'tÿ'v({,ÞE°~-ƒòÐ,ÿ~+†1!„1ß ‹5%“=,ý” ?/•>.–ÿ=/‘:+†/ ÿƒ-)‹4û#‹=,•?/ÿ~*-"t"ÿn|)}ÿ,’A2Ž=/ÿŽ=.•D5‡6'Ę‹;, Òÿt$u$}û,°™;'?{+ŒÍà-Ÿ@ ÿ)Ÿ>)ž='ÿ<&¡?(§E.ÿ°M5§D,¨D×,«F"`-ÉQK5ÿºQ;ÀW@½Sÿ=¸M7³H1°ÿD.¯C,§:$ÿ 3Ÿ2¦9ÿ$·J5»N9¶÷H4´;@<(©<)«@,¬C.’`ý¦“;(š4"˜ß4#›8(¢ š;ß+˜:*‘ð1!Æ ðŠ5à¯À™Ð"|ÿ*}+{+ö¤ð…4»À%„4&îà{, ày,¿~-€3# àÿ2$3&}/!îà4%&À‚6&ÿ…7(1"‡9ÿ*‰;+3#†÷7&~#Ð/„3~%ð#†4$†3Ñÿ‹8'“?.;õ*×ðŒ=€0 Ž3ß"5#—Ø0>+÷œA/‹¢D3š?>,˜<+™“ÀF Û>,‡-Y€‰ÿ.ˆ-•;)÷š@/  ˆ0 ‰ÿ1!’:+˜A1ÿ¤M=›D4‘9ß)8)Šþ.ÿ3"Ž4"‹0ßžC0œåàE1ûªDÊ0,©B,§þe@='¦=&¯Eÿ.²H1¯D.¸ëM6yp³DpG/´ÿG/©<%±D-ÿ¶H1¢3 ±Aÿ-¤3¥4 ®þ†p5´B+¯<ÿ%¿L5ÈT=ÊÿV?ÉU?ÁM7ý¹b:%¶A,¶ÿB-½I5¿M9ÿÀP<¾O<¸J;8±;@@.¥pP'`¿7&˜3#“ÿ`4ÿ$–6&™9)žÿ@0—;,”9+ÿ’7(‹1"4ÿ$”;+’9)’ÿ8)”<-Š2#ÿ8+Ž9+ˆ3~Ø *7(–@¶àÿ-:,–@1Žÿ8)•?0“>.ïŽ8(‡fÀ+ÿ)ƒ,6(ÞG –>-µ°2 ÿ•;(›A/ Fÿ4¢G5œA.•þ0?.ŸA/¡Dÿ2¨J9¡C0 ÿB0¢C1=,í›’9(0”3!î,0<)rP¥D2}ŸåàJ7«K8Ý ç¦F3’0× ›=*Ï>,¡{0ð`=,þ ‘2!›<+ÿ1 Ž/˜8'û–670.«I6¬ûI6G*,ÝPœ7" 7ÿ"—0—0žß8"œ5Ðp·Pÿ;µN8ÂZEÀÿXB¼T>ÂYCÿ±H3¯G2²K6«D/¦>)`ÿŸ6"®F1°Gÿ3¸O;¸O:­ÿC/´J6®D0ÿ«A-¦;(¥;­(|0 6õP&åpž6#§?,¦>!»¤=ù@)£=p`,÷ <*2`™4$š6&8(™7‘¿,¤C2¦Ep3ÿ @/”5%Ž0ÿ‹-Œ.‘÷3"‹°2"Œ0ÿ ‹0“8(–ÿ;*žC2š@0ÞT€”9)? 0ç3"°2œ>,¸5æ ”2 Âc¡ÛA.@; A“3 ’2—7%Ë!ó=+× @ž=*¢º150¨F30¥ïC0¡>I-›9&™6#”0~€¦D0°O;fAóN;êàÔ <+—î¶0?/œ½!+ž>ÿ.š;*©J8®ßN<«J7E@•3 *,œ@ÿ€Œ*˜7½'¨@²P;¦~`Gß2¢A,“P<'ÿ–5 ¡@+¨Gÿ1¨F0±P:·ÿWA¼\F¸XCÿ³S>¬L7±Qÿ<¸WC»[G¿ÿ^J³R>ªG4û¢?4`(¥@-­ÿG4½WD¯H6ÿ£=*¨A-ž7×$¨B3p5¹`©D2§B0¨C0°`ÿž9)œ7'—1ÿ"˜2"œ7$›ÿ6%–2!—3#Ûš5:`$¥÷à?-ÿ¥B/¨E3¦CÑ0JPN@Å ˜À`7&î*@Ÿ?.~@Ÿ@/­žÀð8&’û03"–6%”4"Ú`æ0¤BMA¯pªF4ÿ¨E1©F2§E0¢l?,KABPKPkE2íà±  I6 °~œ=)ŸA-–€ÿž>+“2 ‘0ÿ >,©H7¯ÿN:±P<=)Þ'@-”?-œ@³ ˜:( p ð‹þ@à&Š.xÿl wß)Ž2$0@–6ß#.”%@0î¡`‡#0Ÿ;'Ü€€œ:&‰œ<ÿ'¥E1«L8Ÿï@.¡BëQ‰+÷–8%ý 3Šë-R`Ì%{2!2”5#¡P~¿p>+—5"™ PÿD2¦A/·Q?ÿ³L:¯G5­EË2¨÷A2Äpš2(Ÿ½9Ãp(¡:'P§ÿA/«E4¯I6ÿ¯I8©B2¢;¿*£<+¦?¤0¯G4¥>+ŸRþ“ 0Ÿ8&9'&§DÈ@C4ƒP<@÷Ÿ<+  ?/›ë;* 0›ö ;*¤ÿE3ªJ8¤C1¿Ÿ>,—5$@˜þ$4!œ9%:%ž9&¨D0kÿ›8#—3 Š(Ï“0@m`¨G3¦F1>Ž Œž¿™8$š8#½@žë;'¬p¦PH4 û?+×P£D0š;(>+š<)I`þ™–9'•8'ÿ0 ”7'¡D3wž@/YP•5$u@¿ >-©F4ŒP¢÷>+£ê 6#¡9ÿ&«C/±J5³ÿL8¬F1¯J6ÿ¶S>¼ZEÁ`ÿK²P<­L7­ŸL8¡B- ]pÿ1’4‘3ߌ,•5‹$›û:%Ã@£A,­K7¬I5¬H4G¿ :'š4!óp÷5"œ2`3 Ÿ7ï#²I5g0°H2ÿ®G1ªA,ЙW©@“1Ÿ°2øpÿ%™3$›5%£ÿ=+¨@/­G5ÿ«E2­E4¦?Û.§PC1AQ@-í¤>`>,GP£B/ÿ >+›;)0û’_`2"Š+ÿ.~#xÿ‚'ˆ-!”Ã6'0@æ 0@˜7÷$•4( Ž,û—5Gp)¡?,®ÿJ5ªG2­I5úP¡)a,ž;%¡ÿ=(¥B,£?)êz¦; Aò@& <÷'9ˆ¤B.„_Æ@ª?¬àOr@œŸ<)>*ó⸠2?¦G6”5$ë`u@þ¡P­J8§D2°ÿL9¬G4ªD1}«ò 7$¢;'‘0çªB/Ž”0¤<(¾¬F2±K§p3ß­H4«Fx`-§ÿC/›7"˜5 ÿ•1Ž+œ8ÿ"¦B- ;&›ÿ5!˜2•/¿š4 ¥>*d‘=ÿ)§>* 7#¤;&3¤:°ÿ1³H5µK7°ûG2€¡8# 7ï!£;&[0¨@+ͤ[p=)§€‚ ¤?ß+ <)žñp7%Û›8·0)ž•`=*ùŸªƒ0=+ž<)?š9'˜9(x@d`ë˜8±—Ë:(e0v€&— ø ˜9¿@ý$ ™8'£A/Ðp΀Ó`¬–ñ°*”0›7#¡kæŒA,p Å€¡<&ü€R¨C.ªE0²N7«G1¯èpÅFP)?  =К¿¢>*¤AšP*ÿ•3!™6$.õp© °F2¬Kù8Ô Špž=,œ;ÿ*/#„$‡ÿ&‡!ÿ‰#”-™3#®G5µN;Á`ò”0©Ö3 6ÿ"§=)®D/Ößž’©@+‹0Ÿ6ÿ!ž4Ÿ4 ªÿ?+¬B-¬C-¿§>(4s«ãB-O0ˆØ¢/¡8ÿ$¥<(š1—ÿ.š1—.ÿ¦<&­C.»P^l1°F2­ @i(©A,±H2[0ÛªC@€.-Q#˜õ5% ’€™8&•Ù6>p€#›ª@-o¡A/£þ`?-Y€ßš;'™:3)šã:(zPý0õ È•ü0ãP‘2 ™9(Üu ¡PªH6Ü`ªGÝ5‰P¢=+¦œ6û" Üp:'¦?+×§A-Ÿ£ßA,ÿ¬G0²L6³M'7«D@€F€)¤°Fß«F.¥@™0'Ÿÿ8"¨B+«E.–°°J/§°¶€¥…A°)¶€* N¡°DÏ/®J7’Pc ¦C^ (£?-}°¥BPÿ?-©D1§B/¾>€¦@-¨AŠ0þœ °H4µL8ºóP<|…@,¥8ÿ$«?*¤7!¢ÿ5¨;%¯B+ÿ°C,¸L5®B5,^©ê€7# p0ÿ¶L6ºP:µLû6ª²¢¢:%4 ›3ž5!pç—.Ž0ùp˜1|`Í`¢<) ;™`}'!¡@*¦B.ápo<(–‡€7$Ó0ÿ1 4"/ÿ13!’øÆ kÐ0P9'—:(ý‘$ 6$/“4#äà8±B_pÉÁ þÛÁ‘0#‡'‰ÿ(…$Œ'ÿ+š4$8¾-4²L8¦)À?5+Ш)À=)Ò  °ï®G0¯ €F1²ÿJ5²I2¶N8¯·M6°7 GÀ*ý¯M4§>'¥<ÿ%œ3˜/¢û:#ˆ-³K6±ßI4¬D0(š39ƒ°™pž8%ö@pÿž8&–1!)ÿ’,‘+¤|‡P4@;)¤>+fÐÿ¢;(²J7²Kÿ7·O<ÀXD¥þ=(¢6"¨=ÿ'ºN8¶I3·ÿK5°C- 2÷¤6 ·Ð§8"´ÿE/«='¯A,ÿ¸K6¦:%²Gÿ2¿U?¹O:ÊÿaLËbMÀWCïÂYD¯!-›2“+™2Pþ©C0¶Q>ªûF3Ó`¢@,‘2Ÿ•5!”Y@p:þXP$“5!‘4!ùá/‡-‰w.‹03"Œ´ðó0©À¤ š=*›{€;(I`áà,°,°¼ Î}P @-Ë @ž<*ž;)“p¦0–p›P„“sУlà`§t8þeÐ#¤>*¨D.ÿ®I4±M8¨Dý/æ°§D. >(ÿ£@+®K5­JþŽP.­I3ž:$ÿ§E-°L6­Hÿ3µO;·Q=·ûP<лUA®I½5ùаJ8ª® D2­H5¤@-Ð`ÿ”1 ‡"’.ÿ Œ(—2#¡öoP-þà—2  ó;)A€“ ¸P=³ÿJ7³J6Ö’ÿÆYE¶I4´Gÿ2´G1©;%¾ÿO:ºL6·I3¿ÁS=±C-1ð»¿N8«>)²ÐFÿ0´H3¾S>¸ÿL7°E0¬A-?­B.¯D0XðyüÒ£äвJ6œ4!ÿ—0&)ý°œ8%¤B/oœ;'•W±%Ÿ{°÷F2ŸêP<*3ÿ!Ž2 Œ2 ‰÷/ŒÛP3!‘7ï&–<*î0–;(o—;)“WP8&î÷˜9&¿ –7#–C6"È `Å ‰€˜QàþÔ0,’.‘-w:Ã*œ9'a?™7#›7$æà‰P¿¨D1¬J5’P«öäàC/m`™9$‘ï11N`•7ÿ#š=(œ@+–ÿ<&–:&2ß‘6#’68(ÿB.B-¤H4}™ïð?,˜;(ìPÞfp0’žð,_Š)˜6Dp&²ÿš6$’.•0?›6$Ÿ;"P:Pý#07%®G4ÿ«D1±H6±Gý4s0ÁUAÃWBÿÉ\G‘.Ž+ýŸ‘.—4”1š6!ªe0ÿL7³O:¨E0ÿš7"’/™6¿!¡>) =dà'© ê€£GG@5VP•w4"­À,—7þaÐ:&¥D0¯Oï;®M:@—9&{1÷PŠ.Z‚(’:&‘¹Àþpp=*‰2Š3ÿ!Œ5$‡0Šÿ2!‚+'ïˆ.@>-¢ØÕ „PT€B.\à¢Bå/Np ~à9°?,œþ 6$Ž+”1!“/›6&ø°?˜4!•1W@¸)¦¼`åpH2@¦’Ý'°€9%T «Gñ3˜PS€×P“4"™÷;'–p9&š?ÿ*–;'‘8#›ÿB-žE0¤K7ÿ G4•;*Œ1Ÿ‰0‰­ÀÆP7ÿ%’7'™>-”ß:)‘6%â0‡+ÿƒ(%‚û&5à”8'•9(3#‹.ú0}•y@@/¬L:G÷¥D1K@£A.§ÿE2;'‹;+ÿ„4$Ž>-‹;ÿ*ƒ3"ƒ2!lÿ k t"ÿp…4"=û+ð N<“@.þ@ Œ9'~,ÿ-‡5#„1 ÿ‘>-šH6–Cÿ2¡N=žJ9”ÿA0:)Ž:)ÿŠ7&Ž;)‰5ÿ$‚0Œ9(‰ÿ7&Œ:)‹:)ÿ~,/…4ÿ#ˆ6&Œ9)ˆÿ7&ƒ1!ƒ1 ÿˆ6%Œ8(9þo!‹5%Š4#Žï7'8·!Ž6%w‡.ˇ,Ç Jà”y;AzP™y8&ÂP@¯Ä¾ ϧC0«HP ÐB.ü“ÐU0¹R=¶O:ù®†.¡/£>(¬ŸG1®K4žàc Ÿß<'š:%àš=ß)œ>*™›À:&ÿŠ-Œ/Ž4ú¢ð/|!y ÿ„,ˆ1#“ÿ=-–@1’>.ÿ‘>/–C3‚2ÿ&y*}/#mÿ i k#ÿaj"s%ÿr$t%yÿ*Š:+…5&ÿ‡6(.{+ÿ†5&‰8)wÿ/ y1"q)ÿ^_cûhy0+r*ÿj!i h ÿk#q)jÿ!k"l#ÿ` o&m#ÿk!n%mþÁ0(x/‚8ÿ(4$w,„ÿ8*„8)€5&ÿ‹>.|1 k"ÿhb bÿ x*|,ÿƒ4$€1 w)ÿz+w&wÿ'v&y(ÿ}-1!‡6ß'ƒ2"~i€.ÿ|,{*-ÿ„1!~+…ÿ1!‹7'…/ ÿ„.({%ÿ‚+‹3!ÿ7&5%Œ2!ùàð¶À9(ŸC1ÚAà>`C0¼P¥Gï4œ=*à“4 ÿ/0•7ÿ!’3•6"šàÀQ[àa°£A'2#É•ýŠÖ—8$ž=*û¥Eô€3§I5›ß=*—:'ø†,ÿ~&v}ÿ'tx$ÿy&ljÿ bX cß p%õ@{0ÿ$t)n#rß'p&Ø0u+ÿ„;,‚9*ŒÿC5‡?0s-ÿy3$~8)~9ÿ*ƒ>/„@1~ÿ:+z6(l)ÿe"c!b!ÿ`!a"jÿ* e%v4&ÿy7)t2$t3ÿ$w5'v3$nÿ*t/ k%÷j#Ÿ0v.€ÿ7(6'x/ÿ|2"v,~1ÿ!}02!ÿ1 0…5$ï…3"†¤ :)…ÿ3#„2"€/~,„)!œQ5A-ÿz(/ €ÿ/!z*…6'~Š0„5%‹=, ÿ€1"~/ 3ÿ$t&u*vÿ+m#w+ÿz+y){+ÿ}.ˆ8'‰ÿ8'Œ9*Š7'¿‡4$9)M@Œþƒ 6%’;(9ÿ&Ž7$6$ˆ÷/-°>*•9fð-ž°†À@+µöEpœ9üð,“0ÿ—4#.‡%û’sÐ0‹-ÿ0‰,Œ1û!¿ /+þc`~+…2#Œÿ<-„5&‚4%ÿy,jfÿ ig hÿs(m$üÌ0¢0m%s,ÿ~/†8(‚5ï%s&åPhÿb gb t+p'¢0}5&q*sÒ@û7(Æ`r,v0ý!Ï`o)|5%ÿ9*{3#ƒ:ÿ*z0 y.}÷1!„¶ B1™Jÿ:–G6’@/Žÿ<+‡3"‹6$ÿ‹5#Œ6#Œ7û$ˆ6%…0ƒ,ˆ1…üÿ;)8(‘9)ÿ˜A0‘:*—@û/”J 4#†/ÿ€)}&}(ûˆî`.‰3"¿„/|)i`yÿ'u$x(ÿ~. {+‚2#}-{,ñPû{-êP}-‰û9'ˆ =-Œ;)/‚/Ppï~*„U`2!ŒÞ¤À5#5¥À”;6#G°˜8&Yà•€ùŸÂ¹9&œ8$þ¯œ8&“/”»2Ü Ÿ<*ò°¦{D2Ê•5#üÿ1 —8'–9)¿3"‘6&]`’ÿ9)œD4•>.ÿ”>.…0 -ÿŠ6&†2"‹÷8(…zP$|+üíQÇÀœA/¢G5ÿ F5•=+„,ÿ€)}&ÿ+,|(ÿ{(u"~,ùŽ Ž!3"}+ý{Tp,qvû$Yq#|)÷ƒ/p~'‡?0 ˆ/…ãðïw;)˜E°?-œú6†ð9&ˆ‚$E’òï—=)’à7&—~ì E3š?.•'pþ• 0 Ž0‘4ß"’4"‘X ;)ü¾ðMà“6#‰,÷ˆ,©ð5$“ó;)¾ †1~þ/€)|'{&Dp•p‚.Žq² ² o8&[ 8%o“9'”Q°8&Ë@ç—:&_°P°–5"홼À3 x¡<)ÿ¢=(£>*£=ù*£ ¦?*£;ß'¥=*¤x@5"?¦=+¨?,TT 6$™0–tÀÿ4"ž6$§?-ô ÀÚࡽ@A/͘ÿŽ•2!£A0¢ÿ@.—8*˜9+?“4'ˆ*Á€Á€¿‰*„&»€‘þ³ 2 ’7&‰/y]`Ù€ˆ/ˆ¡Pÿ%…,‰0÷4"›p‡.‹s2!ÚÚ7&šˆÛ=+‘:(Å’6ÿ$›>,¨J8£ÿE3¥F4ªJ7~ð­I6¥B/˜k¥D 0 ¡@t %&…ðœŸDt )-`k°òÖðœHà¿€0˜7ù$8 ~©E2ªE2 <)9¼p zŸ@:öð$™8%…ðß=*¢C=ŸAµ/Mà’(;(¡)ÿ˜:'‰*’3^«À0Êð“lÃ4"2 fñð¹p¡=ÿ)¦A-§@,¢¿;'¨?-¤49Û&©ÿ°<(ä ¤;ß)¡9'¡¿ð/ÿ–,”* 5ï#¥:&(Àª>+¤8$¤8%¡RŸ;(£8%"ÀçФÿ;(œ3 ’)ÿ›4!œ4"š3ý!o‰$Š&ï“0•.;(_,Œ,D°ªñßD2?-ÁÀ$ÿ…(‚%|ÿ {…)ÿˆ+’5$4ÿ$ˆ,"ÿ$ƒ&„'ÿ0†)”7¿#‘3 “5½€ ÿ‹-Ž1Ž0ý ”4 ”3¿—5 ™6"ôð¢=)ªE0¥>Ði+0…°«í°D/±§C.©E1¥{@¯>+¥B†-ë ¢û>,hà¨E2¬H5¨D0¨C/|ðî|À˜1ʰ5 ÿš3›36ÿ" 8$ 9$©B.Ÿ9%ÐùÐ3¿¯J7­H4©°¨…D#0**¶plÐéà¢v:?+ ¦A.höP<)Á°¥@+£{=+N :'¦Û ?<(œ7"¡.Àÿ=*®D/²F4ÿ°F0±E0­@û,²Sð?*²D/ÿºK6·H4½Nÿ:ºJ6µF2³÷D0©‰À5!›/ÿ™/£9&­ÿD0¢:)›4#ÿ‘+€ Š%/-ßðÚÁ&0üæÊƒ)‹2ÿŽ5Œ3û6!®À–=(‘7Ÿ'‹2ZjDÿ.œB,¡G1­ÿR<´XAÂfOÿ¶ZC±V>©Mÿ5›@(˜=%”ß8!3çÀ“6ÿ–9"¤F.«ÿL4§H/«K2ÿªH.­J2¬Jÿ2§B+¦A'¥ÿB)¥A*:%ÿ£?)›:$–5ïœ;$З7 wš;%U°%ã÷2"à¢@*Ÿ}=¾p"¡=& !Ðÿ7œ8 •0îŒà¢>(¤à²M5ÿªF.§C+ž9ü8`CÑ:"ž<%÷›8 hÐ¥C,¨¿I0¯N6¦†°Eÿ/ A+¡B,ªÿK4­M6°P7ÿ¬L5§G0§F{0¦{ÐF/®JÄàÿ8°J4©C,ªÿD,§?(¬E.ÿ´K4±I1²Hÿ1±E/®D-µÿK4·L5¼O7þÑпR:ÆX@Ìÿ_FÏbJÉ\DÿÐcKÄYAÂYÿA½U=²L4µÿO7´O8´O9ù¦„(`=)‹+¿˜:*”6'C°›û>*-‘6"¤Pÿ8§S<¤P9¡ÿK49!Œ7‘<#‡2/âÿŽ9!—B)9ÿ!›E,šD+žÿF- H-¥L2ÿ F+š?$¡Fÿ+™?#žC'¥ûH,aà C&¡Cÿ&©K-¦G+­ûM0sà¨G,§Eÿ)¬J-´P4²ÿO2¶T7ºW:ÿ­K.²P3³Qÿ5±P2¶U9¬ÿL0ªJ0¤E+ÿ¤E,­O4«Mï2¥F,¯à«J2û®M“à6´R6¯ÿL0°N2­I-ÿ¨D)¤?#©Dù(ÁàÓáK/¨E)ÿ¤A$¥D'­M1µS8ªJ1ùÀÿŸ@'‘2›=ý#÷àžB' B*ÿA)¡D+›?ÿ'¦I0¤G-£ýFï0£F*¦Hÿ-¡C(£D(ªùI 0à5³O4°ÿK0¯I-¬F+ÿ«F+©D)°Jþ2ð/´O5¸S8ÿ±M2±L2¯Jÿ/­H.°K1´ÿP6®I.¬I.ÿ®K1§D*«Iï/®L1ið±P6ÿªK1ž?'›=þ¢€5‘8 ÿŽ7Œ5’<ÿ&‘<%Ž9#Žÿ9"”?(£O3ÿ²]BªU:¢Nÿ2£N2§Q7¥ÿP5¦Q6¢M1ÿ—B&šD(šCÿ&¨P4¨Q4´ÿ\?¶]@±V8¿³W9´W8Òð³ÿU5º\=²T4ÿ¬N-µV6°Qÿ0®O.»[:¹ÿX7¼\;ÇfEÿÂa@ºX8°Pÿ/®N-±P/¶ÿV4¸W6¼[;þóðºZ:¸X9¹ÿY:´V8²S6þÒð¨J,ªL/®ÿP2¯Q2¹Y;þ»\=¹Y9¸¿W8¹X8³˜á4ÿ¸U6À\=Â`ÿ?ÅcC¾]=¿ÿ_?ÁaBÁbA¿ÃeE¼_?Ûð´ÿX9®S4­R3ÿ¥J.¡G*¡Hÿ+ G*¢H)¤ÿJ,¦J,¥J+ÿ¨N/§M-°Uû6²“°S3¯Pÿ2­N/­M/°ýOÃà/³P1´Rÿ2»X8·U6µßT3¶U5¶¹Wÿ8ºX;·W9®·M0±ÄðT6Ѽÿ]?º[=ÃdG¿ÂcE»\? §ßH+³T7ì²Tÿ6µX:§J-¤þbàJ.¤J/ªRÿ7¹cH±[@±\A¬W=—B›ðý4¯X7±Y:÷±X9"ªQ1¨ÿO.«Q1°V5ÿ¹^=ÂeDº]ÿ<½`?º];´ÿU4µU3±R/ÿ·X5¹X4à©ÿÊhDÃ`<Ãÿa<¼Y4»Y4ÿÀ]8ÏmHÛwÿSÔqMÏlGÁû]8sÅb=ÊhÿCÎkFÎlHÃÿa>¿^:³R.ÿ¯P,¹\7º\ÿ8Àb?¼_=¼ÿ_<º^;¹];ÿ®T5¥K,§Lÿ-¢G(¥G&¥ÿG'­O.°S1ÿ¾a>ÃeB¸Zÿ7º[8¸Y7¹û\9ʵX4³Vÿ4´W3¸[:½ûa?£µY7²Wÿ5Ó „¬S1§ÿN,¥M+£K)þ÷©Q.­V3«ÿP0¬R0¯U2ÿ®T1°U2µZÿ7³W5´X5µþT1³U2°Qÿ.¶V3¼]:Âïb@Âa[>¿`ï=¶W4ÊZ9·»Y7 º^<å®ûQ1 ²W7µZÿ9ÁfFµZ8³ÿX7°U4ªO.ç²W6££ÂfDîß³V5@°S2ÿ´X7¸^>¶\ÿ=³Y:­U5¥ÿN/ H*¤M.þ ¹`<¼c?µÿ\8±V3¯T0ÿ«P,ªN*³Vý2 º\7¼_:ÿ³V1Äf@½_ÿ8ÈiBÏoHÐÿnGÚwPØvNÿÛxQÒoH×tKÎjBÑmEÛ ÿÔoGÞ{SÜyïQÞ{RÒ ÑoFÿÑqHÈg?Ädÿ<ÉhAÁ`8ÇÿhAÆh@Àc<ÿÃg@Ág>Àdÿ>½c<Ág@¾ÿd?»a;½c>ÿ¹`9»a:¼ao;¾e>21c=0w¾d=0Àd=0ýÀ30a:¸\5·ÿ\5¸]5¾c<ÿÂf?½b:¼bÿ:µY4³X1´ÿY3¹_9¼b<ÿÁiA¼c=¸`ÿ8¹`:¶]7½ßd>¼b=w0Àg1An0)0k0³Y —0ÿ1½a9½b;ÈÿkDÅiC¿c=ÿ¿d=»`:¸^ÿ8º`;º`:³ÿZ5¼c>·^9ÿ´]7·`;³]ÿ7¸a=¿iD¿ÿjEÁjE¸b=ÿ«V1¥P,¢Mÿ(ªT/³]8½ÿfAÃkFÅmG÷ÅlG&0¼b>³ßZ6­U1ô¡Hÿ&¢I(¦O-¯ÿW4µ]9¾fBÿº_6¿d;ÅjÿBÏsKÉmDÌÿoGÉmEÎrHÿÌoFÊmCÏpÿHÁb9¿`7Àÿ`6¿^4Åc:ÿÍkA×uKâÿUãVáSÔÿsHÅd9Éh=ÿÇf;Éi>ÕuÿKÖwLÞTáÿ‚WÞ€UÖzNÿ×{PÐtJÉmÿCÈmCÁf;Àÿg<ÇnBÆnCÿÄmCÆoE½fÿ;¼f<¹b8²ÿ\2µ]4²[3¿¾h=¿h>@½ÿg<ºb9¼e:ÿÇoCÇoEÊrÿHÑyNÈpDÊÿrFÃk@¾e;ÿÁh<½d9Ãhÿ=Âg;¿d8Àÿe9Äj>Âh;ÿÇmAÃj@ÆmÿBÀh=»c9Áÿh>½e<ÄlAþ‘@ÆoCÀh>¾ÿg;¼e;¸`6ÿ·`5ºb8½e¿;ºc9¿i±@;ÿ¹c:¼h>ºdù;-P-P¹d;¿jÿA¼j@»i?ÁÿoEºh>·e=ÿ¼kA¶d<¼kÿCÀoF¾kB¾ÿmC¸f=µb:ÿ·e;®[5³`û9¯jP^8ÀjAÿÆpGÆoFÇoÿFÉqHÅlCÔÿzRÐuMÐuNÿÈmE»`8µ[ÿ2°U,Ù}OÓÿxJÌpCÏtF÷ÐuHŸP×{OÑÿvIÉoAÇl>ÿÀe8Ãh:Ækÿ>ÍsFÒwJÑÿwIÑvHËqBûÊp¶P=Õ{LÕÿ|LØOÛ‚RÿÓzKÒyJÍuÿFÏwHÊrCÑÿzK×RÚƒUÿÞˆZÕ€RÍyÿKÃoAÅqCÃÿpBÅsFÉwJÿÅtFÄsE½mþJP9¹h<¶e9ÿ»j=¾m?µdÿ6´b4·e7¿ÿl>ÄqCÌxIÍyJËwHÌîPÿuFÃm>Ãn>ÿ¿i:Ál<ËvÿFÉtDÌuFËÿsBÂk;Åm=÷ÄkÇqBP`ůoAÍxC`GÿPÕÿRÐ|MÐ|LÿÆqBÃo@»gÿ9¹e7¼i:Àým7`DÃqCÈwÿIÃsEÁqD¾ÿoA¹k>¹k<ÿ¹l>ºm?¸kß=¶i<¸·a>»¿nBÃuHÀ`oÿB¸i<³d7²ÿb5´c7¸g:÷¾l?5`Án@ÅÿqDÀk>Àk=ÿÀi<½e8¿fÿ9ÇoBËqDÔÿyMÙ}PÕzL¿×{NØ|NœPäÿŒ[Þ†VÖNÿÓ}LÒ|KÐ{ÿJÚ…TÖQÒÿ~NÓOÊwG×ÈuE=pÄ“`p@ÿÇuEÅsCÏ}ÿLÓ€OÖ„SÛÿ‡VÔ‚PÉxFÿÆuCÈvEËzÿHÐNÉyGÆÿvDÆuDÆvEþvpÇxGÃtCÈÿzHË|KÅxFÿÇxHÃuDÄwÿFÃvEÀsA½ÿn=¿q?ÀrAÿÃuCÂtBÁsÿAÅvDÃtBÊûzH^pÌ{IÌ{ÿHÏ}IÖƒO×ÿƒOÚ‡SÙ„RÿÏ{HÎzGÍzÿFÆr?Ñ}JÐÿzGÏzFÕLÿÎzEÑ}HÓ~LÌxDÏ{GÙpîÙpÕ‚NÙpËxDÿÉuCÉvBËx½E €ÆtBÉ €zýF€ÊxFÁq?ÿ¾n<¹i7¼mÿ;ÂsAÆxFÈÿ{JÂuD½q@ù¼€˜psBºp?ÿ·l;²g7¼qûAÂW`~NÌ€OÆzJÇzJÃApÿvEÉ{KÁrBÿÀp@ÄsC¾nß>Áp?Ä¡pp@ßÅrAÈu€DÊÿuEÊtDÑzJÿÐyIÍvEÑyÿHÔ|LÝ…TÎû~Iœ}IÓ‚NÿÒ‚NÔ„PÚ‹ÿWÔ†RÌ~JÈ÷{FÅ €yEË~ÿJÍMÒ†QÒÿ…Q׊UÔ‡RûÈz¹€CÀq=Ãÿt@É{FÍJ΀KÏMÍÁ€ÿ~JË|GÅwBÿÈzEÂs?ÇxùDÒƒ·€Ê~IÈ}ýH ÃyD»q=þ‘r>ÀwBÄ{ÿFÃ{FÁxC¿ûu@&Å|FÉ€ÿJІQËJÌÿJË€JÊHþ;È{EÁu>¿ÿs<Àt<Àu=ÿÃx@Áu?ÆyÿBÏ‚JÒƒLÓÿ…MÍ€IÇzB÷Äv?kË~FÊï|FÊ}yGÌIσLÑ„N·ÿyCÃwBÁu@¿ÆzDÇ{E˜Ìÿ€JÏ„NЄNÿÉ~IÄyDÂxïB½s>ÂyDÏ¿uAÁ·’¹Ä{ÏGÂxD ȹoÿ;ºp;¸m8ÁöÃwCՀуOÉÿ{GÔ…QÔ†QÿЂMÖ‡SÒƒÿNÙ‰TÚŠUÖ¾í€KÈxC‚D¿ÉzEÏ~J  ÊÿzEÍ|HÐ…MÿσKÓˆPÔˆÿQцM̓JÍÿ‚JÌ‚IÒˆPÿÖŒTÒ‰PÕŒÿTЇNÍ„LÌÿƒJÊ€GÐ…NÿцNÔ‰P׌TÖŒSÓ‡O[ ÷Ï„Ka Ò†MÔÿ‡OЃKÍ€GÿÏ‚IÍGÒ„ßLЂJÎt €G÷Í‚H+ ÉFÊÿHÄ}EÁ{CÿÂ}E¿zC¾{ÿC¼{D¹yA¹ÿyB½{C»zBÿ¼{C¾}DăÿJÁ€G€H¾ý|Ÿ BÁ€HÂýJµ£Ç†LÃJÿ¿F¾~Dµsÿ;¶t;¹v>¸ÿv<€FÇ„JÿɆLÏŒRʆÿLÉ…KÅ‚HÀ÷}CÁ³ GÄ€ûGÊ) ‰P̈OÿÑTÏŠQˆNÇ‚JǃIú ÿȃIÇ‚HÆÿHΈȮNÏ_‰QË…M‘ Ä³ ¿}EÌ…LÎf†ÿM̃KÇ~EÇ÷~FÈ:°{BÅyBÄyAÇ|C. ÿ׋RÜXá•ÿ]â•]ÚUÓnh †NÎ+°‚I ÿÊ~EÌGËÿFЄKÍ‚IÐüC°n ‚JÑ‹OÓÿŒPψMÔŽQ¿Ø‘TÒ‹O¨°Ñÿ‰MψLЉLwÑ‹N¥°ÕŽRÀ°ÿχK˃GÈ€ÿDχJφJÕÿPÔ‹O΄HwÏ…IÞ°ÒˆKä°ýÓå°‡KÔˆK×ÿ‹O׊NØ‹N÷Ö‰Mð°ÓˆLÏ×…HÐбIÒ°Ì„þ)°DÆ€CÄ€DÿÀDƃHˉÿNɈLË‹OÈÿˆMÃ…HĆIî/À¿‚E/ÀÇ‹NÿʼnLÉQÇ‹ÿOÀ„H‡J¿ÿƒFµ{@µ|@ÿµ}BºDÀ„ýG_À½€C¼€CþeÀ¾DÁ„F½ýjÃE¹|@ÁƒßF¿EÀoÀƒFýÁ9ÂÆˆJÌPïɉMÇǰ‹NË튠ÀMÍŸÀˆLÅ~À„HŃGÇܰÿ‹NЊNÔRýÏBÀ‚F̆HË„H·J«°±°«°÷ÔP¨°ØSÜ÷“WÔ °‡KÎ…ÿJÊEшKÍŸ„GΆIøÀɰÓÎÒÀŠMе±ÖÁÓ×Tœ°Ö“SÿÏ‹KΊJÏŒÿKÐŒLÏ‹JÑÿMÐŒKÔOÿØ“SÙ”TÞ™XÚ–UÖ‘P7Ðw×’Q7ÐÝ—W:ÐçÓŽMCÐ4ÒRß™ýYIÐÑ‹LÒŒMþjÐÖPà™Xßÿ—WÞ–UÚ’RÿÕMÔŒKÕŽÿMÛ”SÚ”RÛÿ•T×’PÕO÷דR—ÐØ•U×ÿ•UÕ”SÒ’QÿË‹JƈGȉÿIŇGňGÉÿLÆ‹JÅŠJÿÆŒKÄŠJÅŒÿKÅŒLÈNÊÿ‘PÈ‘PÉ’QÿÉ“RÉPÈÿPŠLÀˆI¿÷‡H¾éÒ½‡HÁÿŠL¿ˆJÆŽNþÓÐÇŽNÇNÈûOÍÐÅ‹KÇÿMĉIĈHÊÿŽNÊŽMÌPÿÌNÉŒLËŽÿMËLÏOÏÿOÑ‘PÒ’PÿÒOÐNÑŽÿMÐŽMÒOÐóM.Ð.ÑMÕ’çQÕ‘“ÐZÑÒŽNüWà`àÔPÒMN"ÐÒŽM%ÐiàÔDÐ÷”TÖ›ÑTÖ’RœÐHàɆF`àEàÓÿPÕ•PÕ”Oÿ×–QÛšUÚ™ýT¥àÙ™TÙ˜Sø¨à±à±àÖ”OÙ—ÿRÙ—SÔ’N×ß•QוP¨àÞÿXÜ›WÕ”PÖß•QÔ“OØàÜ›VÚ™UÜšVÒâßVÜ™UÝåà—RûÚ–ûàQÛ—RÝû™Tÿàß›UܘýSðáXÝšTÓÜ™ñÀâR«ä™TÿÖ—QÓ•PÖ˜ÿSÔ–QÕ˜SÓÿ–QÏ“NÒ–PûЕFñÓ˜SÑ–ÿQÊ‘NË“OÄÿKÄ‹IÇKÿÅIË“NÉ’þgñΗRÊ“NËÿ”OϘSÊ“O¿Ë”PÌ”PtðÉÿ’MÌ•PÍ•QýÌuð–QΕPÎ~uð•QЖQÔ-ðû›V¤ðÔ˜SÒ—QÑ”OГN³ðÒ•OÑ“OÒuðÿ’NÍLÌŽKÿÌJÍŽJÍŸJÕ•QÓ à²àšUÒ“OÖ—RÔðÝÕ£àœWÜÓàY¿ÞŸ[ÚšVãñ–ÿRÑ’MÔ”OÖß–R×—S®àÜœûWظà™T×–Rÿâ¥\ä§_çªÿaä§^á¤[ÝûŸW+Þ¡XÞ þ-ÜžVÛUÝÅ 9U4::à£ÝZ@ß¡Y1ÚœÿTØ›SØšRÙÿ›SÙœTÚU?ÜŸWÛžV[dþ[טPÝUáÿ¡Xâ¢Yç¦]ÿå¥\æ¤[å¤ÿ[ä£Yå¤Zãÿ¢Xà VàŸUÿä¤Zâ¢X好[©à W㘣­Y4ࢷX=Þù KlUߣYáÿ¤ZÞ£YÚ VÿÓšQÓ˜OÓ™ÿPÔšQÕœSÔÿ›QÒšPјOýÒÚ›RÔœRÖßTÔ›RÙ›RÿЗOÑ™PÒ™ïQÒ™PÙÕ›RïÖœSÖtŸVÚÿŸWÚŸVÜ¡X÷Û W*ÙUØ¿UלS×ežÒ2T<6ØtžVHÜ¿ŸW?T0üK0œTÕ™Q×ü\O¡YÝ¡YÕýšOðOÏ”MÑ—=P`Ü WÞ¼Vû¢Z(Û¤Xߨÿ[áª]à¨\ãÿ«^á©\ߦZïÝ¥XÞ²¦YÞÿ¥Yá¨[å¬_ÿäª]æ¬_ç­`ã©\å«^ÌÿÝ£XÝ£WߥùYØÌá§ZÜ£ÿVÜ¢UÛ¡TßߥXâ¨[Ƭ_ÿåª]ä©\à¤ûWäôª]è¬^~ æª\æ©[ ÷çª\ ä§Yâÿ¥Wâ¤Vä¦Xþ)!§Yã¦Xà£åU5 âñ* ©Z໥XD ߤWJ á÷§Y߸XݦXÿÜ£Uß§XߦÿXݤWÞ¥WÛŸ¢UÝ¥Vb _&ÝÏ¥Wß§U!´â©o[á¨ZŒ!§Zðûঈ!ä«]ãªï\ã©[¡#å«]>Ï[â¨Zà¸f"ìe"³¥Y·à¨[ýâ£[â«^à©ÿ\Þ§ZÞ¦ZÚߣVÚ¢Vœߨñ\Ý ŸœØ¢VÕÿŸSÓQÔR×Ú£Wà ßÓ§ZþœÜ¥Xæ°_ä?­]æ¯_ç1Ù ÷Zâ¬-1è±`ìÿµcì´cï¸fÿë³aç¯^è°ß_ç®]ê50³açí´cR0L0ç¯]÷è¯^I0é°_ë;±`^0ë²am0R0‡îµdR0d0L0^0éÿ¯]ë±_è®\óê°„1…0ì±_êþ†2ë°^ì²`îÿ³aðµcí³aÞˆ0é®]å20®\ïç®\è’0°^çñ¯½1I0m2`ç°^ÿæ¯]àªXä«ÛZã,0ªXâ0ã«ÿYä¬Zæ­\åœï1 Z䬿¿Z§æ®\ë0[1°]0]üÄ0»0æ®[æ­[†D­[¾0¾3Ð0Ð0êe04@°0}0Ñ0D1GAú0¿æ¯^æ®^+0ão¬[ਫ਼Wáø0_­\áªZQCå_0üL@)0¬ZáªYâÎû0®^ä³0_0²`þ0ë´cç±aåï¯_ëµ›Aê³^7è²\¢@ê´ªB£Bwé²]·@í¶`½@÷ï¸bÃ@î·aïó·aÉCÌ@ð¹còûºdÛ@ñºdð¸cî¶aä@ä@ÒAÇ@ôÁ@ÊAbÛ@ó»eóû»fPð¸bñ¹cPÛCReä@PÃBüÎDÉ@ë´_í¶aŸì¶`ëµ60=P_ü«BžBµ_éµ_è?´^æ³^é©BAR‘`PP;PAPîÇ@ÄBð7ºcðÜ@¼e}PzP3ï¹ÈA½@ì¶7P¿A3î·šP×@bñ{PPßBS›Q–S÷AÈAØ@ÃAŸ·bï¹cQiPµô¿AÀA·yPdð¹dÂQ¶4P°@]Ã@˜R×AÉ@î·úP:QAP¨CAPÿô¿eó¾dò½ùc``õÀföÁßh÷Âhö2`Ágæ`ò½*a`ô¾dcFcF`c[c(cgccÿöÀg÷Âiõ¿dBb;ac+b9aôÀaHc@biaóƒb"`ñ\c£¾d¯a¶`¼bð­ad÷ò¿fÊ`óÀfðÿ¾eí»bë»anÄ`ï¼bÜd¼b¯`rèa¾´aµ`óÀe¦a0Ycõa$a‘`ó¿öa^e@sWd%bqOd:v¾œa7`@a¾d%cF`@c|cõÀhpEb&b%c7cgcþ^fó¾e÷Åg÷;ÄgœpøÆh¢q©rÇ÷Äf¥s±qrùÆýh¥pøÅhùÆi?ùÇiúÇjÆqÄr8¢sÏp¥púÈjÉpÉqMÇÎrÈjÌp´tÅÂt ósóqÍräsÛvøƒåp'Çi÷¦p9‚öpýpü64„õÅgôÅgçóÄgA‚@öÄfŒe]‚÷Å:´tÖuøAÆ(‚ „‹…‚ösúƒ` …§€§…êpûÉÇ‚¥¦áv˜ƒƒ«p›èrȧ‚òrü„iít$†ÆhÿýÎlüÍküÌkûÌj%–‘2ž8”MŸ_ŸÍkûq“/’F”J˜+–ûÌo–0˜†•vvúÌjÁ%Ä“¾’À‘ùË•—ž’(Ÿ‹™½ü§’ýÎkýDÍH£úŸ@œ0¦¢V¦H‘¨I™F“{¤Íšüø’ÿÔnþÓmŸ£œ ¨¯@º¯Ã£¥£¥¯Ï©Ø¯ÿܡݯ¿1¿C¿U¿g¿y¿‹¿¿¯¿Á¿æ¯Ð¿ÑªÏŸ ÿpropBACKßnÁDI{TH$ÆNAME$Àÿ Grabber¯InfoÁP!Ä2^ÁRELF$ÁyÁïSORTbÆTRA½N$ÆXGRD$À+16ÁY†ÆiJÀ$Àý ¡ÁFor inÿternal uÿse by the gCÃallegro4.4-4.4.2/demos/skater/include/000077500000000000000000000000001173507505700174315ustar00rootroot00000000000000allegro4.4-4.4.2/demos/skater/include/anim.h000066400000000000000000000010651173507505700205300ustar00rootroot00000000000000#ifndef __DEMO_ANIM_H__ #define __DEMO_ANIM_H__ #include struct Animation { BITMAP *Animation[3], *Still, *Slow, *Medium, *Fast, *CBitmap; int SkateVoice; float TimeCount; }; extern BITMAP *GetCurrentBitmap(struct Animation *); extern void AdvanceAnimation(struct Animation *, float Distance, int OnPlatform); extern struct Animation *SeedPlayerAnimation(void); extern void FreePlayerAnimation(struct Animation *Anim); extern void PauseAnimation(struct Animation *Anim); extern void UnpauseAnimation(struct Animation *Anim); #endif allegro4.4-4.4.2/demos/skater/include/backscrl.h000066400000000000000000000003401173507505700213630ustar00rootroot00000000000000#ifndef __DEMO_BACK_SCROLLER__ #define __DEMO_BACK_SCROLLER__ #include void init_background(void); void update_background(void); void draw_background(BITMAP * canvas); #endif /* __DEMO_BACK_SCROLLER__ */ allegro4.4-4.4.2/demos/skater/include/credits.h000066400000000000000000000003501173507505700212350ustar00rootroot00000000000000#ifndef __DEMO_CREDITS_H__ #define __DEMO_CREDITS_H__ #include void init_credits(void); void update_credits(void); void draw_credits(BITMAP * canvas); void destroy_credits(void); #endif /* __DEMO_CREDITS_H__ */ allegro4.4-4.4.2/demos/skater/include/dblbuf.h000066400000000000000000000003131173507505700210350ustar00rootroot00000000000000#ifndef __DEMO_DOUBLE_BUFFER_H__ #define __DEMO_DOUBLE_BUFFER_H__ #include "updtedvr.h" extern void select_double_buffer(DEMO_SCREEN_UPDATE_DRIVER *driver); #endif /* __DEMO_DOUBLE_BUFFER_H__ */ allegro4.4-4.4.2/demos/skater/include/defines.h000066400000000000000000000042111173507505700212150ustar00rootroot00000000000000#ifndef __DEMO_DEFINES_H__ #define __DEMO_DEFINES_H__ #include "demodata.h" /* Error codes. */ #define DEMO_OK 0 #define DEMO_ERROR_ALLEGRO 1 #define DEMO_ERROR_GFX 2 #define DEMO_ERROR_MEMORY 3 #define DEMO_ERROR_VIDEOMEMORY 4 #define DEMO_ERROR_TRIPLEBUFFER 5 #define DEMO_ERROR_DATA 6 #define DEMO_ERROR_GAMEDATA 7 /* Screen update driver IDs */ #define DEMO_UPDATE_DIRECT 0 #define DEMO_DOUBLE_BUFFER 1 #define DEMO_PAGE_FLIPPING 2 #define DEMO_TRIPLE_BUFFER 3 #define DEMO_OGL_FLIPPING 4 /* Input controller IDs */ #define DEMO_CONTROLLER_KEYBOARD 0 #define DEMO_CONTROLLER_GAMEPAD 1 /* Virtual controller button IDs */ #define DEMO_BUTTON_LEFT 0 #define DEMO_BUTTON_RIGHT 1 #define DEMO_BUTTON_JUMP 2 /* Game state/screen IDs. Each game state must have a unique ID. DEMO_STATE_EXIT is a special state that doesn't relate to any actual gamestate but represents the final state of the game framework state machine. */ #define DEMO_STATE_MAIN_MENU 0 #define DEMO_STATE_NEW_GAME 1 #define DEMO_STATE_OPTIONS 2 #define DEMO_STATE_GFX 3 #define DEMO_STATE_SOUND 4 #define DEMO_STATE_CONTROLS 5 #define DEMO_STATE_MISC 6 #define DEMO_STATE_ABOUT 7 #define DEMO_STATE_HELP 8 #define DEMO_STATE_INTRO 9 #define DEMO_STATE_CONTINUE_GAME 10 #define DEMO_STATE_SUCCESS 11 #define DEMO_STATE_EXIT -1 /* Size of the buffers containing absolute paths to various game files. */ #define DEMO_PATH_LENGTH 1024 /* Size of the static array that holds the game states. */ #define DEMO_MAX_GAMESTATES 64 /* Skater can use both AllegroGL and plain Allegro fonts. AllegroGL fonts require somewhat more code but are much faster that Allegro fonts. */ /* By defualt, use AllegroGL fonts if building in AllegroGL mode. */ #ifdef DEMO_USE_ALLEGRO_GL #define DEMO_USE_ALLEGRO_GL_FONT #endif #endif /* __DEMO_DEFINES_H__ */ allegro4.4-4.4.2/demos/skater/include/demodata.h000066400000000000000000000014641173507505700213650ustar00rootroot00000000000000/* Allegro datafile object indexes, produced by grabber v4.2.0 (beta4), MacOS X */ /* Datafile: /Users/thomasharte/Allegro Demo Game/build/Development/demo.dat */ /* Date: Fri Jul 8 12:41:18 2005 */ /* Do not hand edit! */ #define DEMO_BMP_BACK 0 /* BMP */ #define DEMO_FONT 1 /* FONT */ #define DEMO_FONT_LOGO 2 /* FONT */ #define DEMO_GAME_PALETTE 3 /* PAL */ #define DEMO_MENU_PALETTE 4 /* PAL */ #define DEMO_MIDI_INGAME 5 /* MIDI */ #define DEMO_MIDI_INTRO 6 /* MIDI */ #define DEMO_MIDI_MENU 7 /* MIDI */ #define DEMO_MIDI_SUCCESS 8 /* MIDI */ #define DEMO_SAMPLE_BUTTON 9 /* SAMP */ #define DEMO_SAMPLE_WELCOME 10 /* SAMP */ allegro4.4-4.4.2/demos/skater/include/fps.h000066400000000000000000000057671173507505700204110ustar00rootroot00000000000000/* Module for measuring FPS for Allegro games. Written by Miran Amon. version: 1.02 date: 27. June 2003 */ #ifndef __DEMO_FPS_H__ #define __DEMO_FPS_H__ #include #ifdef __cplusplus extern "C" { #endif /* Underlaying structure for measuring FPS. The user should create an instance of this structure with create_fps() and destroy it with destroy_fps(). The user should not use the contents of the structure directly, functions for manipulating with the FPS structure should be used instead. */ typedef struct FPS { int *samples; int nSamples; int curSample; int frameCounter; int framesPerSecond; } FPS; /* Creates an instance of the FPS structure and initializes it. The user should call this function somewhere at the beginning of the program and use the value it returns to access the current FPS. Parameters: int fps - the frequency of the timer used to control the speed of the program Returns: FPS *fps - an instance of the FPS structure */ FPS *create_fps(int fps); /* Destroys an FPS object. The user should call this function when he's done measuring the FPS, i.e. at the end of the program. Parameters: FPS *fps - a pointer to an FPS object Returns: nothing */ void destroy_fps(FPS * fps); /* Updates the FPS measuring logic. The user should call this function exactly fps times per second where fps is the speed of their timer. Usually this is implemented in the logic code, i.e. in the while(timer_counter) loop or an equivalent. Parameters: FPS *fps - a pointer to an FPS object Returns: nothing */ void fps_tick(FPS * fps); /* Counts the number of drawn frames. The user should call this function every time they draw their frame. Parameters: FPS *fps - a pointer to an FPS object Returns: nothing */ void fps_frame(FPS * fps); /* Retreives the current frame rate in frames per second. This will actually be the average frame rate over the last second. Parameters: FPS *fps - a pointer to an FPS object Returns: int fps - the average frame rate over the last second */ int get_fps(FPS * fps); /* Draws the current frame rate on the specified bitmap with the specified parameters. Parameters: FPS *fps - a pointer to an FPS object BITMAP *bmp - destination bitmap FONT *font - the font used for printing the fps int x, y - position of the fps text on the destination bitmap int color - the color of the fps text char *format - the format of the text as you would pass to printf(); the format should contain whatever text you wish to print and a format sequence for outputting an integer; Returns: nothing Example: draw_fps(fps, screen, font, 100, 50, makecol(123,234,213), "FPS = %d"); */ void draw_fps(FPS * fps, BITMAP * bmp, FONT * font, int x, int y, int color, char *format); #ifdef __cplusplus } #endif #endif allegro4.4-4.4.2/demos/skater/include/framewk.h000066400000000000000000000025001173507505700212330ustar00rootroot00000000000000#ifndef __DEMO_FRAMEWORK_H__ #define __DEMO_FRAMEWORK_H__ #include #include "defines.h" /* Initializes Allegro, loads configuration settings, installs all required Allegro submodules, creates all game state objects, loads all data and does all other framework initialization tasks. Each successfull call to this function must be paired with a call to shutdown_framework()! Parameters: none Returns: Error code: DEMO_OK if initialization was successfull, otherwise the code of the error that caused the function to fail. See defines.h for a list of possible error codes. */ extern int init_framework(void); /* Runs the framework main loop. The framework consists of user definable game state objects, each representing one screen or page. The main loop simply switches between these states according to internal and user specified inputs. Note: init_framework() must have been successfully called before this function may be used. Parameters: none Returns: nothing */ extern void run_framework(void); /* Destroys all game state object and other framework modules that were initialized in init_framework(). Parameters: none Returns: nothing */ extern void shutdown_framework(void); #endif /* __DEMO_FRAMEWORK_H__ */ allegro4.4-4.4.2/demos/skater/include/game.h000066400000000000000000000011731173507505700205150ustar00rootroot00000000000000#ifndef __GAME_H__ #define __GAME_H__ /* functions for Miran's framework */ #include "gmestate.h" /* gamestate.h */ extern void create_new_game(GAMESTATE * state); extern void create_continue_game(GAMESTATE * game); extern void destroy_game(void); extern char *load_game_resources(void); extern void unload_game_resources(void); extern DATAFILE *game_audio; /* global game state defines and variables */ #define KEYFLAG_LEFT 0x01 #define KEYFLAG_RIGHT 0x02 #define KEYFLAG_JUMP 0x04 #define KEYFLAG_JUMP_ISSUED 0x08 #define KEYFLAG_JUMPING 0x10 #define KEYFLAG_FLIP 0x20 extern int KeyFlags; extern float Pusher; #endif allegro4.4-4.4.2/demos/skater/include/gamepad.h000066400000000000000000000003111173507505700211730ustar00rootroot00000000000000#ifndef __DEMO_GAMEPAD_H__ #define __DEMO_GAMEPAD_H__ #include #include "virtctl.h" VCONTROLLER *create_gamepad_controller(const char *config_path); #endif /* __DEMO_GAMEPAD_H__ */ allegro4.4-4.4.2/demos/skater/include/global.h000066400000000000000000000143401173507505700210440ustar00rootroot00000000000000#ifndef __DEMO_GLOBAL_H__ #define __DEMO_GLOBAL_H__ #include "defines.h" #include "keyboard.h" #include "updtedvr.h" #include /* Some configuration settings. All of these variables are recorded in the configuration file. */ extern int fullscreen; /* selects fullscreen or windowed mode */ extern int bit_depth; /* screen colour depth (15/16/24/32) Note that this is ignored when in windowed mode and the desktop colour depth can be retreived. */ extern int screen_width; /* horizontal screen resolution */ extern int screen_height; /* vertical screen resolution */ extern int update_driver_id; /* selected screen update driver */ extern int use_vsync; /* enables/disables vsync-ing */ extern int logic_framerate; /* target logic framerate */ extern int max_frame_skip; /* max number of skipped logic frames if the CPU isn't fast enough */ extern int limit_framerate; /* enables/disables unlimited framerate */ extern int display_framerate; /* enables/disables FPS counter */ extern int reduce_cpu_usage; /* enables/disables power saving by giving up the CPU when not needed */ extern int sound_volume; /* sound volume in range [0,10] */ extern int music_volume; /* music volume in range [0,10] */ extern int controller_id; /* ID of the selected input controller */ /* Offset of the text shadow in game menus as number of pixels. */ extern int shadow_offset; /* Array of available input controllers. New controllers may be added here in the future. */ extern VCONTROLLER *controller[2]; /* Absolute path of the config file. */ extern char config_path[DEMO_PATH_LENGTH]; /* Absolute path of the datafile. */ extern char data_path[DEMO_PATH_LENGTH]; /* The datafile that contains all game data. */ extern DATAFILE *demo_data; /* The main menu font (monochrome). */ extern FONT *demo_font; /* The big title font (coloured). */ extern FONT *demo_font_logo; /* The big title font (monocrome in AllegroGL mode, same as demo_font_logo in normal mode). Needed because of limitation in AllegroGL text output.*/ extern FONT *demo_font_logo_m; /* Font made of default allegro font (monochrome). */ extern FONT *plain_font; /* The update driver object that is used by the framework. */ extern DEMO_SCREEN_UPDATE_DRIVER update_driver; /* Converts an error code to an error description. Parameters: int id - error code (see defines.h) Returns: String containing the description of the error code. */ extern const char *demo_error(int id); /* Switches the gfx mode to settings defined by the global variables declared in this file and reloads all data if necessary. Parameters: none Returns: Error code: DEMO_OK on succes, otherwise the code of the error that caused the function to fail. See defines.h for a list of possible error codes. */ extern int change_gfx_mode(void); /* Reads global configuration settings from a config file. Parameters: char *config - Path to the config file. Returns: nothing */ extern void read_config(const char *config); /* Writes global configuration settings to a config file. Parameters: char *config - Path to the config file. Returns: nothing */ extern void write_config(const char *config); /* Unloads all game data. Required before changing gfx mode and before shutting down the framework. Parameters: none Returns: nothing */ extern void unload_data(void); /* Facade for text output functions. Implements a common interface for text output using Allegro's or AllegroGL's text output functions. Text alignment is selected with a parameter. Parameters: BITMAP *canvas, int x, int y, int col and char *format have exactly the same meaning as in the equivalent Allegro built-in text output functions. FONT *font can be either plain Allegro font or a font converted with AllegroGL's allegro_gl_convert_allegro_font_ex(). int align - defines alignemnt: 0 = left, 1 = right, 2 = centre Returns: nothing */ extern void demo_textprintf_ex(BITMAP * canvas, const FONT * font, int x, int y, int col, int bg, int align, const char *format, ...); extern void demo_textprintf(BITMAP * canvas, const FONT * font, int x, int y, int col, int bg, const char *format, ...); extern void demo_textprintf_right(BITMAP * canvas, const FONT * font, int x, int y, int col, int bg, const char *format, ...); extern void demo_textprintf_centre(BITMAP * canvas, const FONT * font, int x, int y, int col, int bg, const char *format, ...); extern void demo_textout(BITMAP *bmp, const FONT *f, const char *s, int x, int y, int color, int bg); extern void demo_textout_right(BITMAP *bmp, const FONT *f, const char *s, int x, int y, int color, int bg); extern void demo_textout_centre(BITMAP *bmp, const FONT *f, const char *s, int x, int y, int color, int bg); /* Custom text output function. Similar to the Allegro's built-in functions except that text alignment is selected with a parameter and the text is printed with a black shadow. Offset of the shadow is defined with the shadow_offset variable. Parameters: BITMAP *canvas, FONT *font, int x, int y, int col and char *text have exactly the same meaning as in the equivalent Allegro built-in text output functions. int align - defines alignemnt: 0 = left, 1 = right, 2 = centre Returns: nothing */ extern void shadow_textprintf(BITMAP * canvas, FONT * font, int x, int y, int col, int align, const char *text, ...); /* Selects the specified update driver by filling in the update_driver object with pointers to appropriate functions. Parameters: int id - ID of the driver as defined in defines.h Returns: Error code: DEMO_OK if initialization was successfull, otherwise the code of the error that caused the function to fail. See defines.h for a list of possible error codes. */ extern int select_update_driver(int id); #endif /* __DEMO_GLOBAL_H__ */ allegro4.4-4.4.2/demos/skater/include/gmestate.h000066400000000000000000000031261173507505700214150ustar00rootroot00000000000000#ifndef __DEMO_GAMESTATE_H__ #define __DEMO_GAMESTATE_H__ #include /* Structure that defines one game state/screen/page. Each screen is basically just a bunch of functions that initialize the state, run a frame of logic and draw it to the screen. Each actual state must fill in the struct by setting the function pointers to point to the functions that implement that particular state. Note that not all functions are mandatory, but most are. */ typedef struct GAMESTATE GAMESTATE; struct GAMESTATE { /* Supposed to return the ID of the state. Each stat must have a unique ID. Not: all actual IDs are defined in defines.h. */ int (*id) (void); /* Initializes the gamestate. This may be setting some static variables to their default values, generating game data, randomizing the playing field, etc. */ void (*init) (void); /* Destroys the gamestate. Note that a particular gamestate may set this pointr to NULL if there's nothing to destroy. */ void (*deinit) (void); /* Runs one frame of logic, for example gather input, update game physics, enemy AI, do collision detection, etc. Must return ID of the next state. Most of the time this should be the ID of the state itself, but for example when ESC is pressed this should be the ID of the main menu or something along those lines. */ int (*update) (void); /* Draws the state to the given bitmap. Note that the state should assume that the target bitmap is acquired and cleared. */ void (*draw) (BITMAP *); }; #endif /* __DEMO_GAMESTATE_H__ */ allegro4.4-4.4.2/demos/skater/include/keyboard.h000066400000000000000000000003151173507505700214010ustar00rootroot00000000000000#ifndef __DEMO_KEYBOARD_H__ #define __DEMO_KEYBOARD_H__ #include #include "virtctl.h" VCONTROLLER *create_keyboard_controller(const char *config_path); #endif /* __DEMO_KEYBOARD_H__ */ allegro4.4-4.4.2/demos/skater/include/level.h000066400000000000000000000016521173507505700207150ustar00rootroot00000000000000#ifndef __LEVEL_H #define __LEVEL_H #include #include "quadtree.h" extern struct Level *LoadLevel(char *name, int collradius); extern void FreeLevel(struct Level *lvl); extern char *GetLevelError(void); extern void SetInitialState(struct Level *lvl); extern void DrawLevelBackground(BITMAP * target, struct Level *lev, float *pos); extern void DrawLevelForeground(BITMAP * target, struct Level *lev); /* level state struct, which stores the current state of the level - perfect for any future implementation of loading/saving games */ struct LevelState { int Length; uint32_t *Data; int DoorOpen; }; extern void SetDoorOpen(struct Level *Lvl); extern struct LevelState *BorrowState(struct Level *); extern void ReturnState(struct Level *, struct LevelState *); extern void FreeState(struct LevelState *); extern BITMAP *ObtainBitmap(const char *name); extern SAMPLE *ObtainSample(const char *name); #endif allegro4.4-4.4.2/demos/skater/include/lvlalloc.h000066400000000000000000000005421173507505700214130ustar00rootroot00000000000000#ifndef __LVLALLOC_H #define __LVLALLOC_H #include "level.h" extern struct Level *NewLevel(void); extern struct Material *NewMaterial(void); extern struct ObjectType *NewObjectType(void); extern struct Triangle *NewTriangle(void); extern struct Object *NewObject(void); extern struct Edge *NewEdge(void); extern struct Vertex *NewVertex(void); #endif allegro4.4-4.4.2/demos/skater/include/lvlfile.h000066400000000000000000000006211173507505700212360ustar00rootroot00000000000000#ifndef __LVLFILE_H #define __LVLFILE_H #include "level.h" void LoadMaterials(struct Level *NewLev); void LoadVertices(struct Level *NewLev); void LoadTriangles(struct Level *NewLev, int radius); void LoadObjectTypes(struct Level *NewLev, int radius); void LoadObjects(struct Level *NewLev); void LoadStats(struct Level *NewLev); extern int GetNormal(struct Edge *e, float *v1, float *v2); #endif allegro4.4-4.4.2/demos/skater/include/menu.h000066400000000000000000000024471173507505700205550ustar00rootroot00000000000000#ifndef __DEMO_MENU_H__ #define __DEMO_MENU_H__ #include #include "global.h" #define DEMO_MENU_CONTINUE 1000 #define DEMO_MENU_BACK 1001 #define DEMO_MENU_LOCK 1002 #define DEMO_MENU_SELECTABLE 1 #define DEMO_MENU_SELECTED 2 #define DEMO_MENU_EXIT 4 #define DEMO_MENU_EXTRA 8 #define DEMO_MENU_MSG_INIT 0 #define DEMO_MENU_MSG_DRAW 1 #define DEMO_MENU_MSG_KEY 2 #define DEMO_MENU_MSG_WIDTH 3 #define DEMO_MENU_MSG_HEIGHT 4 #define DEMO_MENU_MSG_TICK 5 extern BITMAP *demo_menu_canvas; typedef struct DEMO_MENU DEMO_MENU; struct DEMO_MENU { int (*proc) (DEMO_MENU *, int, int); char *name; int flags; int extra; void **data; void (*on_activate) (DEMO_MENU *); }; void init_demo_menu(DEMO_MENU * menu, int PlayMusic); int update_demo_menu(DEMO_MENU * menu); void draw_demo_menu(BITMAP * canvas, DEMO_MENU * menu); int demo_text_proc(DEMO_MENU * item, int msg, int key); int demo_edit_proc(DEMO_MENU * item, int msg, int key); int demo_button_proc(DEMO_MENU * item, int msg, int key); int demo_choice_proc(DEMO_MENU * item, int msg, int key); int demo_key_proc(DEMO_MENU * item, int msg, int key); int demo_color_proc(DEMO_MENU * item, int msg, int extra); int demo_separator_proc(DEMO_MENU * item, int msg, int extra); #endif /* __DEMO_MENU_H__ */ allegro4.4-4.4.2/demos/skater/include/menus.h000066400000000000000000000011271173507505700207320ustar00rootroot00000000000000#ifndef __DEMO_GAME_MENUS_H__ #define __DEMO_GAME_MENUS_H__ #include "gmestate.h" /* gamestate.h */ void create_main_menu(GAMESTATE * state); void create_options_menu(GAMESTATE * state); void create_gfx_menu(GAMESTATE * state); void create_sound_menu(GAMESTATE * state); void create_controls_menu(GAMESTATE * state); void create_misc_menu(GAMESTATE * state); void create_about_menu(GAMESTATE * state); void create_success_menu(GAMESTATE * state); void create_intro(GAMESTATE * state); void enable_continue_game(void); void disable_continue_game(void); #endif /* __DEMO_GAME_MENUS_H__ */ allegro4.4-4.4.2/demos/skater/include/music.h000066400000000000000000000003451173507505700207240ustar00rootroot00000000000000#ifndef __DEMO_MUSIC_PLAYER_H__ #define __DEMO_MUSIC_PLAYER_H__ void play_music(int id, int loop); void stop_music(void); void play_sound(int id, int vol, int pan, int freq, int loop); #endif /* __DEMO_MUSIC_PLAYER_H__ */ allegro4.4-4.4.2/demos/skater/include/oglflip.h000066400000000000000000000003071173507505700212360ustar00rootroot00000000000000#ifndef __DEMO_OGL_FLIPPING_H__ #define __DEMO_OGL_FLIPPING_H__ #include "updtedvr.h" extern void select_ogl_flipping(DEMO_SCREEN_UPDATE_DRIVER *driver); #endif /* __DEMO_OGL_FLIPPING_H__ */ allegro4.4-4.4.2/demos/skater/include/pageflip.h000066400000000000000000000003131173507505700213660ustar00rootroot00000000000000#ifndef __DEMO_PAGE_FLIPPING_H__ #define __DEMO_PAGE_FLIPPING_H__ #include "updtedvr.h" extern void select_page_flipping(DEMO_SCREEN_UPDATE_DRIVER *driver); #endif /* __DEMO_PAGE_FLIPPING_H__ */ allegro4.4-4.4.2/demos/skater/include/physics.h000066400000000000000000000003511173507505700212630ustar00rootroot00000000000000#ifndef __PHYSICS_H #define __PHYSICS_H #include "anim.h" #include "level.h" extern struct QuadTreeNode *RunPhysics(struct Level *lvl, float *pos, float *vec, float TimeToGo, struct Animation *PAnim); #endif allegro4.4-4.4.2/demos/skater/include/quadtree.h000066400000000000000000000062061173507505700214200ustar00rootroot00000000000000#ifndef __QUADTREES_H #define __QUADTREES_H #include #define TRIFLAGS_WIDTH 0x07f #define TRIFLAGS_EDGE 0x080 #define OBJFLAGS_VISIBLE 0x001 #define OBJFLAGS_DOOR 0x002 #define FLAGS_COLLIDABLE 0x100 #define FLAGS_FOREGROUND 0x200 struct Material { BITMAP *Edge, *Fill; float Friction; struct Material *Next; }; struct Vertex { float Pos[2]; float Normal[2]; struct Edge *Edges[2]; struct Vertex *Next; }; struct SmallVertex { float Pos[2]; }; struct BoundingBox { struct SmallVertex TL, BR; }; struct Triangle { struct BoundingBox Bounder; struct Material *Material; struct Triangle *Next; struct Vertex *Edges[3]; unsigned int EdgeFlags[3]; unsigned int LastFrame; }; struct ObjectType { BITMAP *Image; SAMPLE *CollectNoise; int Radius; struct ObjectType *Next; }; struct Object { struct BoundingBox Bounder; struct ObjectType *ObjType; float Pos[2]; unsigned int Flags; fixed Angle; unsigned int LastFrame; struct Object *Next; }; struct Edge { struct BoundingBox Bounder; struct Material *Material; struct Edge *Next; /* equation of the edge, as in a*x + b*y + c = 0 */ float a, b, c; /* pointers to the vertices that create this edge */ struct Vertex *EndPoints[2]; }; /* containers for the two previous elements, used to build lists at tree nodes */ struct Container { struct Container *Next; enum { TRIANGLE, OBJECT, EDGE } Type; union { struct Edge *E; struct Triangle *T; struct Object *O; } Content; }; /* quadtrees of containers */ struct QuadTreeNode { struct BoundingBox Bounder; int NumContents; struct Container *Contents; struct Container *PostContents; struct QuadTreeNode *Children; struct QuadTreeNode *Next; }; /* level structure, connecting it all */ struct Level { struct QuadTreeNode DisplayTree, *VisibleList; struct QuadTreeNode CollisionTree; float PlayerStartPos[2]; int TotalObjects, ObjectsRequired; struct LevelState *InitialState; struct ObjectType *AllObjectTypes, Door; struct Material *AllMats; struct Vertex *AllVerts; struct Edge *AllEdges; struct Triangle *AllTris; struct Object *AllObjects; BITMAP *DoorOpen, *DoorShut; }; extern void SetupQuadTree(struct QuadTreeNode *Tree, int x1, int y1, int x2, int y2); extern void FreeQuadTree(struct QuadTreeNode *Tree); extern void BeginQuadTreeDraw(BITMAP * target, struct Level *Lvl, struct QuadTreeNode *TriTree, struct BoundingBox *ScrBounder, unsigned int framec); extern void EndQuadTreeDraw(BITMAP * target, struct Level *Lvl, struct BoundingBox *ScrBounder, unsigned int framec); extern struct QuadTreeNode *GetCollisionNode(struct Level *lev, float *pos, float *vec); extern void AddTriangle(struct Level *Level, struct Triangle *NewTri); extern void AddEdge(struct Level *level, struct Edge *NewEdge); extern void AddObject(struct Level *level, struct Object *NewObject, int DisplayTree); extern void SplitTree(struct QuadTreeNode *Tree); extern void OrderTree(struct QuadTreeNode *Tree, int PostTree); #endif allegro4.4-4.4.2/demos/skater/include/scrshot.h000066400000000000000000000046601173507505700212750ustar00rootroot00000000000000/* Module for taking screenshots for Allegro games. Written by Miran Amon. version: 1.01 date: 27. June 2003 */ #ifndef SCREENSHOT_H #define SCREENSHOT_H #include #ifdef __cplusplus extern "C" { #endif /* The structure that actually takes screenshots and counts them. The user should create an instance of this structure with create_screenshot() and destroy it with destroy_screenshot(). The user should not use the contents of the structure directly, the functions for manipulating with the screenshot structure should be used instead. */ typedef struct SCREENSHOT { int counter; char *name; char *ext; } SCREENSHOT; /* Creates an instance of the screenshot structure and initializes it. The user should call this function somewhere at the beginning of the program and use the value it returns to take screenshots. This function makes sure previously made screenshots will not be overwritten. Parameters: char *name - the base of the name for the screenshots; actual names will have their number appended to them; typically the name should have no more than 4 characters (for compatibility) char *ext - extension of the screenshot bitmaps; typically this should be either bmp, pcx, tga or lbm, anything else will fail to produce screenshots unless you have and addon library that integrates itself with save_bitmap() Returns: SCREENSHOT *ss - an instance of the SCREENSHOT structure */ SCREENSHOT *create_screenshot(char *name, char *ext); /* Destroys an SCREENSHOT object. The user should call this function when he's done taking screenshots, i.e. at the end of the program. Parameters: SCREENSHOT *ss - a pointer to an SCREENSHOT object Returns: nothing */ void destroy_screenshot(SCREENSHOT * ss); /* Takes a screenshot and saves it to a file. Parameters: SCREENSHOT *ss - a pointer to an SCREENSHOT object BITMAP *buffer - the bitmap from which we take a screenshot; this can be the screen bitmap but taking screenshots from video bitmaps like the screen is a bit slower so if you use a memory double buferring system you should pass your buffer to this function instead Returns: nothing */ void take_screenshot(SCREENSHOT * ss, BITMAP * buffer); #ifdef __cplusplus } #endif #endif allegro4.4-4.4.2/demos/skater/include/token.h000066400000000000000000000041141173507505700207220ustar00rootroot00000000000000/* * tkeniser.h * Allegro Demo Game * * Created by Thomas Harte on 18/07/2005. * Copyright 2005 __MyCompanyName__. All rights reserved. * */ #ifndef __TOKENISER_H #define __TOKENISER_H #include /* Level loading related variables - Lines is a count of the number of lines of text that have been parsed from the source level file. It is used for error reporting where necessary. Error is an error flag. If it is set to non-zero then some error occurred. ErrorText is a textual description of the error that has occurred in level loading. It is set initially to be an empty string, and if an error is flagged but an error string not provided then the user gets an "Unspecified error" */ extern int Error, Lines; extern char ErrorText[1024]; /* TokenTypes gives a complete list of all the tokens that the parser can understand from a file. Most are self explanatory but nevertheless: TK_OPENBRACE - the { character TK_CLOSEBRACE - the } character TK_COMMA - the , character TK_STRING - a section of text enclosed in quotes, e.g. "hello" TK_NUMBER - a number in any C standard format, integer or floating point (e.g. 97, 012, 0x8 or 23.6f) TK_COMMENT - a comment, which begins with a hash and then runs to the end of line TK_UNKNOWN - something the parser didn't really understand */ enum TokenTypes { TK_OPENBRACE, TK_CLOSEBRACE, TK_COMMA, TK_STRING, TK_NUMBER, TK_COMMENT, TK_UNKNOWN }; /* struct Tok holds a Token. It is straightforward. 'Type' holds the token type. 'Text' holds the characters read from the file and taken to be the token unless the token is taken to be a string, in which case the surrounding quotes are removed In the case that a number is found, FQuantity holds a floating point value and IQuantity holds an integer value */ struct Tok { enum TokenTypes Type; char Text[256]; float FQuantity; int IQuantity; }; extern struct Tok Token; extern PACKFILE *input; /* the file from which level input is read */ extern void GetToken(void); extern void ExpectToken(enum TokenTypes Type); #endif allegro4.4-4.4.2/demos/skater/include/transitn.h000066400000000000000000000010471173507505700214460ustar00rootroot00000000000000#ifndef __DEMO_TRANSITION_H__ #define __DEMO_TRANSITION_H__ #include #include "gmestate.h" /* gamestate.h */ typedef struct TRANSITION { GAMESTATE *from; GAMESTATE *to; float duration; float progress; BITMAP *from_bmp; BITMAP *to_bmp; } TRANSITION; TRANSITION *create_transition(GAMESTATE * from, GAMESTATE * to, float duration); void destroy_transition(TRANSITION * t); int update_transition(TRANSITION * t); void draw_transition(BITMAP * canvas, TRANSITION * t); #endif /* __DEMO_TRANSITION_H__ */ allegro4.4-4.4.2/demos/skater/include/tribuf.h000066400000000000000000000003131173507505700210720ustar00rootroot00000000000000#ifndef __DEMO_TRIPLE_BUFFER_H__ #define __DEMO_TRIPLE_BUFFER_H__ #include "updtedvr.h" extern void select_triple_buffer(DEMO_SCREEN_UPDATE_DRIVER *driver); #endif /* __DEMO_TRIPLE_BUFFER_H__ */ allegro4.4-4.4.2/demos/skater/include/updtedvr.h000066400000000000000000000016501173507505700214410ustar00rootroot00000000000000#ifndef __DEMO_UPDATE_DRIVER_H__ #define __DEMO_UPDATE_DRIVER_H__ #include /* Structure that defines a screen update driver. Each actual driver consists of a number of functions that expose it to the user programmer and any number of internal static variables. */ typedef struct DEMO_SCREEN_UPDATE_DRIVER { /* Creates all the necessary internal variables such as video pages, memory buffers, etc. Must return an error code as defined in defines.h */ int (*create) (void); /* Destroys all internal variables. */ void (*destroy) (void); /* Flips the page, blits the backbuffer to the screen, etc. Whatever it takes to put the backbuffer to the screen. */ void (*draw) (void); /* Returns a pointer to the backbuffer the user programmer can safely draw to. */ BITMAP *(*get_canvas) (void); } DEMO_SCREEN_UPDATE_DRIVER; #endif /* __DEMO_UPDATE_DRIVER_H__ */ allegro4.4-4.4.2/demos/skater/include/virtctl.h000066400000000000000000000046241173507505700212770ustar00rootroot00000000000000#ifndef __DEMO_VCONTROLLER_H__ #define __DEMO_VCONTROLLER_H__ /* Structure that defines a virtual controller. A virtual controller is an abstraction of physical controllers such as kyboards, mice, gamepads, joysticks, etc. to make them more easily manageable. This particular implementation supports up to 8 digital buttons, but can easily be expanded to support analogue axes as well. Each implementation of an actual controller should implement all the functions in this struct. Each function is passed a pointer to the associated object, a bit like the implicit this pointer in C++ classes. */ typedef struct VCONTROLLER VCONTROLLER; struct VCONTROLLER { /* Status of each of the 8 virtual buttons. Virtual controllers should update this array in the poll function and the user programmer should read them in order to gather input. */ int button[8]; /* Pointer to some private internal data that each controller may use. Note: perhaps a cleaner implementation would be to let each controller use static variables instead. */ void *private_data; /* Polls the underlying physical controller and updates the buttons array. */ void (*poll) (VCONTROLLER *); /* Reads button assignments (and any other settings) from a config file. */ void (*read_config) (VCONTROLLER *, const char *); /* Writes button assignments (and any other settings) to a config file. */ void (*write_config) (VCONTROLLER *, const char *); /* Supposed to calibrate the specified button. Returns 0 if the button has not been calibrated and non-zero as soon as it is. The user programmer should call this function in a loop until it returns non zero or button calibration has been canceled in some way. */ int (*calibrate_button) (VCONTROLLER *, int); /* Returns a short description of the specified button that may be used in the user interface (for example). */ const char *(*get_button_description) (VCONTROLLER *, int); }; /* Destroys the given controller, frees memory and writes button assignments to the config file. Parameters: VCONTROLLER *controller - The pointer to be destroyed. char *config_path - Path to the config file where settings should be written. Returns: nothing */ void destroy_vcontroller(VCONTROLLER * controller, const char *config_path); #endif /* __DEMO_VCONTROLLER_H__ */ allegro4.4-4.4.2/demos/skater/level.dat000066400000000000000000001301341173507505700176110ustar00rootroot00000000000000slh!ïALL.ëðpr¿opDATEëðÿ1-02-200ÿ6, 20:00îöñNAMýñ LEVEL_TXTöñïORIGlev¿el.txtúðAïòÝ@# Eÿxported ÿfrom Bleÿnder 237 # on MfÿJul 11 19:28:51 ÿ05 (CET)þcdo not ßedit, /ÿhome/elißas/.bY/mÿyown/hilûly¨ instïead cMatÿerials {ÿ {"soilÿ", "grasÝsá1.0ï} ¿# 0 "H¸"ÎÙiceátiÝpá0.2õ1 ã"IÙ 400×275õ2yGðæÙ î3 "Pÿlatform"{ }ÊVertüÖÌesh "C¯urveî1-ÿ9671, -4ë20?0 804Ψ116P78;68¨869@ w920¨028lÞP6579¨10Õ9Ô4Ú8 -3ë96?5 817­7 !376 1¼ï»3934õ7¬)%Î39Á8)%3Ê "09$"88ºè1³382§1Ë48ô1ÇÝ42æp"77Ù7135õ28Ÿ#í·5Î"873"52=7!2731"w793ô352œ(!–#179Â=!8Í2—"25R"96Í1F"88Ý#g!54]2Î122Ý"2³W515[!932Ç]8ô212ô2Ùƒ51o$f3íð `23Lf3#44Á$8"2";96Í381A3("·9381"86È"2n="226¬"53?V333˜#4Â2g!w662!107èV³29˜#2È"3Ç£58^2 3Ù2­6ë"80Ý"3¹#2]5§377Â3!7748ƒ"56è©3Ô`XB3Ÿ"3(!694B17#azC˜"‘@\lR!911§5›C¶g#23"62Â4³24E"1© üÇ7421ô68ëCÙ+83:25#4OE¬!Ôï Ÿ"4Î#5¼B27u28"4!682¬!µ9Ç#4(!84IR1T=S¡D9!R3qC4R!;32†2139S32»86»165ô5R|"4 —@4Ý"5Ç·379B35è5¶Ù31"26Â5î¹"857»299 ³S!57Z"ü@ÜS"«10§D8†C5¾42ª1"1"#5="4HS3µ0á35}R37á1u2qC5g"575á 28žS6³-`*bêCQ6#¿ÖR1Ÿ"6ÍT0"0]C6¹"aÆ3j¢36#2#03­c–!96E#0˜c(!5«56Rb5­6¡D5¦c0ÃcR!5±Põ#96ÈD922988#G2Í9C768##19Ö[!29qC7Ù52´jCCd7¹#15êS5jŸ"7"8Ì27wp"&p !4V"¢`Ýc5äüƒu02îpßè‘Ç@B.¡5j´(’ò‘žS5[£Þ=’-984Åq41!8©³R’õ1´c5ò°Á$€Eq5äÄ}’4v()3“’¡P2tB4³(#52EsC±€×bb÷°õT!9°ò3ÐÄç’’±C(»CWð<133I£¢ ¸Pp‘‡@µ25óÍdT„0B1í1]$4O¢x€°sä2T€úëóðÀ‹#B’â0íâCß°b6Yò­‹#(‚Ï€ Ò‹#>3¡ÂÜ$~q1ºà,hRoÐBa8róž$‘7òb ßp´$°Ág IB4gíлòó€Z3˜CÔ#Ú`Z3ÿqÍPÚ“´ã4\²¨vÂH¦Àƒ4d0c³š¤4‡²ñ@žb8ûCìà¼"/‘-4¯²ÿò¶ n4.QÀZs@Û$Ú²ðZã³$ï²8³pPƒ,C|ä£53£4Â}  RŠã41Â`ôY±P¥‚5S°ð,CQUØ4n †`ÅqJÀ,CÂb7Y‘8$+D.Q6€œ’5+DÏ22År75˜3ÃÂ2`BÒ4øD$VƒåS4ëÀ#»CÒÂÐos‘EÒ9`ZsD*Ò1ÿò Ü#@Òˆ0óÂÔùC{¼Ð…â©1JTõ¢5GÓ4í£4P~Ò@ÇÒ4“Ò54ÀÈSQó8LÂ=ÀS½Ó Ý.¢12Ç#ÓÒ‹ ÇÒ ùc4èÒ4Šp/ó3ýÒ±ÃË“'`‰±%³9 ÈSÂc޲É0ÈSf":²`d`°Âœ ñÓï#gâ89ÚAX4{â4òbï@Š#‘âþ(ËÞ#¥â5‚2àE»âC88ÀñáÓrÒ7"0‹s4æãG ­óådüâØƒ©˜c‘+TÀ@˜cK2Ñp:Bà“àýR32ƒuÀ T“0è€<¢­â1ïpasç‚7Pú±î°asdˆà(‡Ó‰tè’2¯“5´tü’(qP.ówÓ4Îò7_`oó‰t=âµÐ×ò0Ðas°ÃpÒ}ï# 96óÂW 4ƒ`ØÁ€¤²d870ƒ1—4Mk O´Ü#c°ðP"Ø4ƒˆ²0šÓ6J#A4Žþô—ð4ƒ…Â8Bó„ÚU¹1F YSSÎ5ïC9Tä% S®4ø 1n“16¼d{À'²4”]²¦„0•’òÅ…âï#PðO³–ddÝÁÇ#z1÷PÖ#˜3ŠÀñC™„¦°nò+ð‹"º Qú3ÛTÏì¬ó‰W0%6«ó5””ûh¢°ë”"pWS%$€1€¨4¤ 2¢³§ÂB8N²C4e"1b´k Ö“ºRA2ÅÒ2ðV²²@‰±2{3@?Ъ£ØÁÅP“ƒ#Ó5º"C19#C­„MQ5—€õ@-²_àð¢Z@'²“5@õ"Òз²Ûðª£q2ä€ÜÓ¾¤üâ6ÚÒ TPS" 2¬ñÞä5J3º€ÂrS@©ðœ¢ã’…P{´ØÁ8_à£, _sð€Ñ7?1“ÂþðýLÂ1y |³QR$P”ƒÓ£Ê29,sà|³ sRnÐ|³üâ0s0¡5BÓ Â"Û#5B255¡C-351BÛƒ#ý¤EBhs9©Âù€VÒp2ØÐHþ±265Ø^°HÃÒ7"Оã±>â2-òX`\Ä 2q n#)³ÁBl0D"9C3‰à&Ãfú183f³èB27-#59>C5þB-6úºc5R281ðÒ9wәЦñ7ij]TõÐ7Ò’ÄÔPR“#ç¤eR€¬8ÓzR9XóApÓâ¶YR¼c5¤RUP“ƒ Ë´¹RÁ/☄5ÍRð4‘3Kã5âS77«ˆàþ£øRèÚ´ä¾±—à¬Ã07¾£"bÅ $’31„ƒ57bÿ×òf`îÓMbƒ05SÜ`$‡pÀ÷³1¢ƒQ2¸Ð>$Ë23ž@çÙ]£³@NC'%œ’C03:“#530–à€€ÃÓ£š¢£0ËÀ€Âå6¯¢Ðd¢x.2dàø#zâøÉð4b€# Mesÿh "CurveCircle"ÃB êRmÓµð:3{a6n2º0€:3=ÑAã  íbböc6ˆ/²v0=Ò0Ä2Àíb1¦ÓB6X²w Ëó¦4†ó#¢Š@ñ"²úð-Sð#–³eÔ S6¨²ð`Ysâ4ò@úðÃÏ3ìc–s6ç²89%ãE³3 E- õ5B?Ãá5µâ´ðÉ8M¢`"³¦3b¢`=Ò¥4wÂÐâ‘4‹ÂÕÐha}4 ÂÕÐÞaj4¶ÂÕÐ=ÑW4Ì“90H–c6áÁ&5Font.00191(èPÀS¯Ã6öÂ2hÃCPð# ҿмâéàñ"ÒÐhc‘45Ó6µc17X3HJÒÐð‚s03_Ó1¶¢Úp…TÓ²8ÏÒCPk3‰Ó2-t4šT"«säPö3³Ò;±©S1b6ÈÓ}ư E3ÝÒ†pÖsÃ6óÓ-@ýS’3âU`©Âþ”6âU`fã÷63âQV‘4Hâ»P©Â#CcŠÒˆÐèR}4Ðsâ ¤cã6ˆâ23QÒ—Vžâ13x#=ÀCc Ò®À/s’3Èâ? YUÝâMPbK s¡R.°S)t`Ób#sËR 'b€¬ÓCÛ¢:âjàcFò27’CV[ò'°Š s€MS´u’tbRG`'by6šò9¤c7Î3¯òIp¹cXÓ6Ãò­ÀôtcØò  7t¦3íò‘ð~SAd€Ð µsÔ“*À1²'Ó0Ø#6€,#~RºuAØÀ333VS4Vc7À3KscµÔ3§SOÐò³ÞâåÓÓò³ý2:c4íS7Cž°ñ´òȆò³ú“„‘3!7LBU` „°Â7`BÆéc7tBIY”ÄWŃ@òp*²œB0 ecmÓ7°BÓ`ôtXâ7ÄBºVŒ´ØC8"³ÄëB`¹clã7þB½`/“ëã7R0s³¨½ÄÿÑS567LR9:c²Ð¾ÃbRj„“y³vR@Ý7t‹Ôx£Ÿs¼D7 R¡9…³‡àŒÓÐ’3£0T~ÄÊR8½£5C7ßT¨¤•C7ôS7X“úÅ b86Ò£|s7båÀU£©7‹Ôµâ6üR4÷C7Hc‹Ås7]b»PIºPZã¡SÃhŇbš7³çà œb°]„¬ä²b4T£ÁP„Zã"4{ã¹ Zã®s0¨asd´ðb9º#4û7 s¦°ÜƒçÃs3¡ò~`$y³/s8C”5“7Drc0*ãÃYs3ï2­ Sô³é…*ó²b_J¨Ä˜r¡@pÓɳ­s35µt)ô•‚5{ä0Sôó "€æìr9T£5P´‚#€‡ƒ´´‚1Cp܃ l±«Ð‡0Ϭ°®³Nƒžp´"!sª$7j‚9—“s³"@0‚ MSûT#7©ƒÐÁP-þ‚9*£52„ÃÓ‚2wsÜ)5@9Ã"€ÉÐÓŽ#E¤7’œ‘ØÙ'’9¤"+`³<“ŠÄ2 S7Q“À ˆ7f“û0èSɳ{”Ç“A5Úƒ9`™Ôƒù£1 ´‚º’9ÍcÌ`™ÐÓ*£037ä“ yÉù’ƱjS ë"Öp¯Ù#¤3?SÁ ›ÃMÃü™ª‚5ÎäÛˆb¢;(s7w¢*`çS1³Œ¢142arj#’>5{¶„7¶¤5³1€ŠÔË¢CQåߢk;c84ɳó¢9“45ò 6³ãô²0@ÿ¦2À(h’ä|s8C²9ù£ï´!8W²p½S8k²ü@äãNƒÉÀ#×ÔåB8“²‚Ó4‘#è°áRqƒI”8»²–Õ1 Sªh¤äc8ã²ànÆð:2÷² Cv4 ÂsÑõx8Â10%c4‚ã83Â4u}Ä!8GÂkr³K8[Â-ásµ3pÃ5uécü°;Iƒ 8šÂ14>TqE}Ó£ p:2ÃÂåPiTŒ3ØÂаHÎd3CíÂ9Ô(s8ÒYPPcUc7¨St8+Ó56óÔä8@Ò*`r„€93TÒÀ“SÚEò6ó4@6ÈpÞ½SBT‘Ò2‚ ýS¡3¦Ó02J³ÚD»Ò&pVDN3ÏÓ0£Ë„8(äÒ–ÐM)8øÓ5›D ãöT^8"âý`U£s86âa€#$êTû3ÍS3 p£8_ã5·~cx£DX«8‰ã4Ód8žâ| aÓ8²âËPëÓØ£¡8Çâk®³8Üã9„wÄfó8ñâIƒ“ú#8ò2ÝuDòê0Rã†D/ô(ã1óW§“±ƒådYòùp5“8mòUŸÓ8‚ò…@E1£Õ%¢8@£d¬òÝÀ˜’œ8Àò 9“.ä8ÕóS¤a€Psª‚4(ãM„CB×4TˆTë¤8(›{S2 93=Ã…2†dC0`ó2Àµ3fèàV„Ê3{155‹dN3zaÙ9¤ËPÃ1H„SŠ$|dÎËP(^´3Câ3(6N3÷0W"d”>01r³G„!33ã†D6» ™Ô˜ð„ãQã09¡3_97Rㆄt‘¦Þ4‰.°áÃb3žÎ–Гks ³1 „È4ªTÜå”Vñ14…³39Ó8"H`Æ¿T"9Õ´¨Ã80#•TÃ8E#ÆàºYZ#Ô­8o"–à:ÄŒ3ƒ"™Óúd˜#¦0’㑤 S†t !8Â"1š@pÓ3C×"‹10Z4493ì#ñ¤4¿T2Ï ê³9»¤Öó“op’£û3ãàz±E0Ä#„™Óð³9T2p‚²9Ph2¾‘ óYâ9}33¯s®°d³"Ô4‹Ò£à¦ÿ2´Ýâ8@¡cÌ´†ÃÔ„3lä9å31X49¢´[#/ªS9Cp‡¹$B³ÐA„”Â99BNPÈó 6´À•³ãÅC9cB_1(CJÄg6C2Àãn0…#2NÒ9¢C±ôËP6ÃÆsF„9ÌBQvó ÃáCpu»c9öCh€r³Ì³ RÏ ³ó0Ôdƒ8@{SŠÓWh¾Cùd9IR1Æ 3³³^Ryàuóã!9sRÍðE.“9ˆRbpBgé9œRL0=(c9±R —Äx³ÆS92sÏdò @áÓÈóoÔðRi€Ÿ£3Öâ%9c6¾C$9b H®4 Ã/c5!£Êt9Dc„Ý$È49Ybé®3ãó9Ând9‹"@d²ƒc33|“sĘc@‘“³­bY°,B33_ÃÂbJ "ófó9×b5 QT¢³ìc4X9s7{gЬãtŸ£$IÄ+s4 dÚC9@s(ÓÓÈÃUs1æÓ0käjr@ QSoÔr*…ýT9”rÐ[3¶´¨rr¡úyBüTr¹Òs2Q4h#9çr`!0‡t‰Ãûs·ä41̳‚ô°îr¥$9%ƒô°Ê¨9:‚1Ý0‘“¢³NƒòõZÕ“9c‚15S2¡s9x‚Ü0Ê$x³‚ ø”¸_TmÃ¥£¬0lTO n£ã“27-ãá‚§€QSÄö‚eð›r0³t -r@ž£rÅ ’pSÞ395“ç„õJ’12GÔ_’a1¡wc Ãt“67‹#7!Kó1f£Ž¯i4䲓6+C28x³Ç‘ÿ# Mesh "¾ÿ.001"Ô°5°þÄàô™ñ44[²3 0³ñ’6îGCìp8! °­Ã³¢ž )"Jðô†yA43ÄrÈ $¼15æê54c³X¢407°›q{`0$n¡41uò3!5ÇÄ‚¢F@Ô3MtI  !7}Ó5x¬¢8)"#40 ÃÁ¢P%3 Ö¢€T€Ñ"¨Ù#a"èà~"6 í$yA37eR®°³²¡3ŽÀ¨"n$*²3…s3’ø¤9?²¤%5ˆÄT²33Â23€Ë1ê0²Q{ :2{ôê0"#Éò@HBÅ0®av56óÅ09l «4K‘63<“3GCÅ0H2D *!7IÃÅ0‹"3¬a8VãÅ0 "ªÃ30ÃEqw"0:3ÅC}!Tp3¸œ ²27ŠbÕ ±B:‘"!H6é㜠®a5ÀÛq6YEzÂ$3Fp‡DK‘`ä`›rà€‡D`‘56¤“A6¡³œ Ô+à†±3™8‡Dr2žc355†EbI3ÝFÊ"T¯„Ñ87(£ÛÀô#»#4˳ÛÀÞ2…3!¢3pcT2“D5€óEaÒã%ÏôÛÀH2b45ïƒÜa2Ú#p6T ÒŒPd2kcTn¡5GàÛr›E6ÊÒ57ýƒ55æTßÒ`:2ç?d¤B›T6Ð?dÞ2-T4$sC`2ÏðöSjeæB¥#2?düB'в"7ª4]â32Oâ3Xõ€?d»53‘#80ÓÝ`bT5×fxBëDð«3±âŒe7€ãà""‡ €i"›EÛâPFàÐB56S•eò0%2Ýðtv"5§Ò›PFuR¢P"¢ààb¿D7NàbE4î³85Unòe0UƒòÓ0å2;÷t¤BÏd.ð÷tºB`@˜sª4Âò_ðd3/u×ò¶55ÏUìòWs€gó±I9Ȱàb«5þã°n¡p…6M³°Ê"isg@ÐTU;%ÿ Ó„™ñ6/ÐB@3º Nr›à"y…”@ƒÜú æBådŽÀÓ„`‘F$º ‹"iuEèäPTÒ¦ÐÓ„>S93a1=óº ès(#15pD '~u46>d<¢dg@®•Nrüpz36Tfªt- bT{ ”3¯”üB×t7e¥z%€¯”˜‚}E€ñÃð >RÍ5b³ð 0i48ÐTùó†Ì0‹¤""ç”XP@‹¤Þ266)"6oEK"46G3¢@‹¤a"Ï%1ª4u":Fò/±Œ(6Aã<Ñ‘xŒà‹¤iØ ‹¤Ê"Ù¥ µÞ"ø&JfÐ8sg#& g´NrÉ„€g´ÐBy”7‘¶æB……G3óUU•\3ähpg´r2©À䳪4†3E„5•e›2¸fÝèÀ¶’=u9èÀÌ“0‚¿`œCÛÀ“MdDCÝ`1@À$“„ÅV‚À&23ª3t€û2 !-89`ò£41¿4º ÌÂ74¸ ðCÄ»-85æÒ4(æ…<ÐÌÂ40‚4 €CÄ`åÏÆ2ÀCÃB-8"ÔÁ4!„;ÐÌÂ1’ÒŒPLXĹB-8ä@ÔÁ5íd#àÌÁ- ÓÂ5YDÏÐÌÁ vP&á45 ´MàúÉPl7ÔâÂ76›46id 1'RíÀ2ÆÀÔ=R-755ÐÓåTŒà›Ò4N24º…sð›Òl ÑÒ mÅR-7ÑÒ‰¤ð–›Ò15ã8åƒÒ7ЉÔ6Ád1ÁRmàÓ6"Ét1×RÆp\Ó65ÕíR-6Cðã3åùÂjãT€Æã0O‘ÔÐ3å'ÒÉ6ÐGÒ7XÄEb-6HøàuÒ „1[b„æ5ÕDqb÷æ5‘ó{ÀƒÒ6Í34šE`„Ò˜ÐÑҙųb÷à>r4ÿÀô®ã#ÑÒ‚±D1ßbæx…Eôã0ÒŠ÷óãÂAú!rSö¸U117r2Б"47¿ÕMr-636Êóé´àê—4.u1yr-57 ÚAXÄr"1¶ã]¤I1¥ríÀ8¶ã{´1»r¨úÖý÷Üã2%6=d1çr-4˜ÀU ýr˜ñêÂ7¥„1‚˜ð¡ÓàÏ8óè Õ4Xà„ÒpÔÁQ8¹õU‚2Ò8)”%1k‚-ÿÀˆã6åâÂ.ð#”1—‚BÖ+@ϘÒ+êÂ826ÔÂ-x€:3šÄÙ‚Y×+Ä À ¦0¢Ò8ì#ÆÐ8ó´ä0§Ö’ÃÄ¢47áL E8?”1G’Vçë41]’ -5ÎÔ7Õs’©ûÐLµŽ59TO´1Ÿ’ ÎäâÖµ’è05çÒ8(íÕË’x 4Ç5šÄá’Æö ›$iâNB ¢M †R ä#¢×7c„Ô0MS0 #ñÄO¢00x2 8Òæ€çÒ7ÙÅ{¢IÐ396ÙÅ‘¢-52ö‚A ä§¢-5ØÀöä½¢BÄ@3Þ)Ó¢£01b3ÀWé¢^Px4¢õÿ¢-5”P¿;,:6Ðõ+²6&A²mç0ó5¿#?m² Ã%&ƒ²&À#8q™²Á1FÒ8ÖÕ¯²¸€<¯&Ų !tÒ8WÅÛ²á:06Ôñ²wÐ"69äÂ@ÓÐN’R UŽ¥46Ÿ”3ÂüF7ô2IÂIÐ6D õt2_Âu6"52u„J']¤2‹ÂÑÐô2È¡ÂÝöõ2·Á}75((cê0àÙ7ý„2øÃBHJ2Óî Ç”2&Ó:”e2=Ó Ð3dUÒ€‹Ò µ2kÓë`,ãWm2‚Ô88–91íT–™Ó38j9Hf±Ò3+75,â9ßt2ÇÓqÕÔÐ3dù¸E9ìUõÓ§%%9Ô2 ã 9Òe#ãw€žcFô9À!s„ó£fQãçÅ PtƒÓ4âd#´2ã/tNóFH564ø£å€å97ïD2|ó ÀCäZ…`EæuªóæE)àÿtZ3lõˆSÔVïôß AóíTˆÕå[ ‰96»e4%—L¿$6ýubúVwäM°„Z9´2žU—Ò2A9$£à•'Ò …71e@ÕŸÖÉ–UÒmeB2œåüv:„=ðË”2ó ç@Ë”­cWeá¤2_»58ƒÄ2v tôѰ e¤Z YcÄ2»ôu(¤å!°ÉÙ5LÔ2é:€s2/t#áåƒð±¤šÒ]?tÖT.#‚õⱤ\£öô9³® ù¹`±¤t*±–Š#e¼µ2¡#ë¥8 µ¸#ju Ð—´lÓÕUæ#„eGfý+Çð—´y‹&$Dœà!y8¾UB3@æ0 Å"¤›1¨Tp4¢D7Ý¥‡3Fµ86¨Tž3²e8`ä„DÐÎ96¡uÌ3)å.õ2ã3YU_å2ú3ŠE”¶CÊå5•(C¦¦êäÀ”z0cTVCAàª#¾UmA# Mesh "oÑ.003"Op«ÚàcÔÏ¢ƒ@ÐÓ0¨T›B:€²Ìa3LƲB29<319…ÉD#43zTàC„ðÕ²8LT÷BI€°Ò50æuRŽ€ºÁ35úPªÑˆ ±Ñƒ–@¹ãÀ|ä²õb´²ˆå83@ ˳xPÕ²ˆ%â²1p ©äù²òQ”ó6ÂùæJS¤3'Â7gôp„3>Âi%ʰVDŠ¢i t-õlÂE7r0-õƒÄ)d7$ä›`ªÑ¨£`ð0Tbò@#„”~@_4Ƥ3ßà úb½ð0TÇã5&ô 5 Ò6F9 $Ò82úb2à0T{)0²V¶!!`RãiÑKE0)E‘ÒŽn° dNs 3³¾Ó¬±Ò9|äÔÒ¤ç6êÒ‘õÒ5ääÅõâèðc¢ÆP e-âZyBâ¼õE%ºåó¢ÂÆPFs@êàŵ üßãc0Y„,POpQ€ó º0#WìEÇpªÑ5u ´Àüó”Rðð(¶ƒ`â9oc7€uäóÐÃSäe‡³U$dÄë@·9×S6CƒÛPOWŽ€Ät ÷?#Äõ+ðªØ5‰ÔlðÂÈã9øÂv¢ò74@Ùu˜¶äGàÄtÎò7 s1ØD—ðÓ’Ôó§ÐÄtmÃ@ӳذåcžàÎã9@4'ÏuŒp „棾¤995€tT-16SUã…D³149F…693ÔE yV”Pf‰ôfð? ˆ…Ú;V8¾äáжH°ƒ”Lò¤D2d䨰8S5£8§4”@xùîÄbà·™72Ãt]qæzÅüóÓ²ðð‚•©c˜ÕuŸ‘WÂDA4µØ$SE¹05lPìŠ=uöà©ò‘Ų l ¬u""´4éðe¤ëÑåD€-UåÀ¥YŸàe¤©cÊ1•uz"²$äe°y åc¦$Ú"åÀC´m㥠Í>tÒ"âà2Sô€tè"¢u`„þ"ÿõÀ…µ‚ÓôU4*3vtYp(tA3¤YpÀnµäùopûdn2%ô05Ãt„2ðeopäd™2­e`>”¯2&‡9€tÄ26 s€O4æÀÈé©°$Ä¢òt4mµDH3«Eyà†7‡@$Ä@{"Ê4@à$ĵr D2Ê$4\BUðÔNT§‘äï\x&–žBÙÕ% ÒW04ÕëÒ€„0@Ô˜$2{äCPÀÒk"ÊÐ.Õ{ƒCopÔµryöÐåc6T´1>”MRN´[@ÞÔ¢‰B6U$"ÅvS9ûã9ÀnÕŒRkàôcy ÿ# Mesh "?Plane"ò1 Prm 1¤¦ºR824`1‰1€–ÐT3ãoæX18!3’òƒàåµq8\€ãl„b82cB18­•&b¾àAƒçò¾ ÜSÐôŒÒÆà×âöWŽâ5)‚õXÔSóB0ùTêSR´VäÒ`¯Sg5úÒgp3cã%â°à€ÅSÓfòJаSüô;â8a6¢Ù1Õd~_09bâ ¼Pjá60wãКRÝ㥀f{¤âð|sêe€êSø3€vÏãWÀšR„´5åã`|sÚu,cL’—aÅttoR¬v'ó ¾{>òvàÔsÈSó›À¾{šc®‚Áx€ÔS½’ßqÅtêS#€u6 «óŒÔs …òc3‹c„´6×óÀš‹sS¦€¡„ÐbÒ$P|sT“601©0^s$C6È´6C3¨C6"Äjpcâ36— s-5ù265B³6…Pà Hš›û fr+t6±÷d6ö´6Ç “ „Ý@)„x–ó¢Ã˜:ƒ41“c¤642ᔕšcsŽ—ÔS0µ”•‚“BSL–wà “l¥æã:²Ï ¼”£uk¦ò3óà˜m¤“Ü#66 „å0…1-7.ó±Àm¤xâ743]°m¤Žâ¬³Ú¥¤â¦€þ«ôÀ2ö£¹Â1Õ4-Ô6g#72c39 ¦”}#Ø €»üâ6În·„pÀ3bâ`€²mD6 ¿#¬P€²—¥Õ#7èsð·  ³cÚ·ÉÀ4bâ9ªÀ3òÔ639"£3`÷…-3g´\ÆC378%BhFÆY15bá90ªãƒ26´o3þ0®ÂAt6…3šàÄÔ›3®Ëâ¯1ù9EÀú1W uÄÑ!9Û$-°uÄŽâ9v34×ÐPÃä×N¿1Å292B²ó1kt ÒÜ#0Ÿ…bIB9u4 ×á90ZÔD‹Öº¿1‘Rf0ù20­¥`‹BP0±ÓÑ•¡B91`3 ç(ÓJ3ö×&Ï1]rH 23ã1´ãB93ÄS+Ôºá  ÕBxæR‚Љãhcå%Q 2)’94ò@EØ ÃâÈò9ç•QRt ˆQâçâ3RÍçþÏ2J9Ã4Þó7oµ§S3ă 7÷…½S3PC6÷€ó¢3369¼”éS429£›µªÿS3nS6‰„6c4¨Ü#Lö+c4lƒ6G„6"Ac3š#xöWc3‚ƒº÷J 32c6·Õƒc3`3º÷¾SRº÷ sþsŽ÷‚“Ñ0oRLöÛc4ø368D¦”ñc3à”¥õs3Òs”Ts3$C7ÍÕ3s4 6ù270p´IP*óE5#6‚@“®ƒ73$…6‰s3(³ló^c7Œ/µµs41eËs3PÈâ0z”ás4°#7ç•T÷sÄ7}46 ƒ3:CD#ƒ3ˆóZ\ãû ]@“,#Z¾Sà“Z szsZR"3¦sLðO”µó©47½ƒ3ø3p7Óƒ3ÔC6'¶£òâ-ä#¨ØÕƒµó5Î#7Ÿ02Ò  ù209$@“sd@9$22CÎ'ló0ó°"@9$^Í280nC7—“3³79d$­“qôä&Ó4èsÀ)4¶£ª³6cR7BS8@)4@“þsR7Št»< sˆ#&70*#|C&6s£3974EŠ£€=5Ÿ£G¶£˜ƒ«81°C7Ë£4,S8Y0Ð$á¯02éÓ0“Ù25 ²90ª³18ls7!³†à¬CrEPØS”šGjß2Uã0N£"e7Bw²9çÐþ¢=5³9C50ÿd7£³97_dU Öß3)“8øc¸@ Tðò,Р“Unb8\âØ€ T P‚h˜UBï3õ¤cC92\DOÃÎ@ö"7(4eÄ:s4[E{ôÙS8$¶‘Ï039Â92:s3i3!eÀÒ2"£28¬4HÑÂA`M18 fâ1z£³33²DýÏ03õ7ÆîÃ82ae ³ƒ77Ð$=Ó†BÃaeçSÓò ” dæO3Á#8€c”7“Ò«PŸ#cô7©ÒkP72€GP#tørÊ`Æcd$Õß0 3}Ò89ü£Âu;Â@V„c%â„p±Óµ„7+âTÀ”du½_3DjÑ,#tlâ07)³1²DãK05!197%—ã0Â346²D­ï03UãóÀP€¹Ž ÒÈ#3´7ëãÝÀšQi5óàR5ÿ“04)““´5'5?ó5ðƒ4†2£T·H£‚ÃA4`eó\ àŠ—ó5îÃ47¦$­óîàƒ>•¤³jC4ôUÙó50ó–ïóÑ5Ó&—¢5z£48 \D56y”(•"³ˆãD&—8³3M”(•^¢5ô#”ä†s6ˆ#4Ëe‰5˜¼<–Ÿ55盵5¦£4«5Ë*àS(4á /FontêÑ-°°!14UÀ¤,á ª²• d$! ”B• \D7»¡ý1A40ंñ Äb4€9#cé¡Ö¢XÐõ¤ªÑ  lRä€ µÄñ·7ô¥Úñ é¦`õ¤ðñÒ¦8Ô<0b¸©87%礦85gµ·¤£8ñ´7" žâ ’¸å¤T¢{°Ã8?" F"{°ó8U" òàÃ0ú´Ž³8´D@ú´w³i4Ö0Êyô8­!ü·ÄÐÛ´ ¤é³Û¥8í"϶ÝUHp@µ¹­¥82§1Ú´/2¸±É!Ú ¢ÓZ@Ì´71€ñ ñ´[2ϱ1ñ dã8q2æ±Ö£ä8‡2æ±õ!R{Ä2æ±Ã5ų2(×e8Ïã8É2Ö878óú ÷É8/8õ2ãÆh Û³ BÌÆ`§Ô´¤´$87B¡ŸÔ½ÕA´>¢£ØX´üŒ×yAº¢ÄxÔ£B»¡¶Ó«”8¹B»¡I³5ÅÏB<ç2ÕåA$çÖRæÖ%R÷ÖìÆ;RàÖÕÆQQŒ ÝƒZ xÔ{RÝàjBåèo³58I³”´œðÚã_´ö·£5Úbä€Ú´æRÝàÞ"Aøå£Ú úbgðH´qö³“p ñ´RbÝàŽ2JÇhbÝàãÔ¶öX³7Z Ú´“afñ?ãã÷ £óôp÷·£Üôp÷Σ¹°ßûcôæÄ¼Õ)rMö?r6m*³3»´!tŒ¶Ôñ´•r’ŸÔÄ«r’º2£×Ár×,Óçå×q‘‚º×‚ÄXå£3(ä¼Õ,‚3ŸÛB‘7ˆÔ6Äl‚aÃi”`^2´l¼8/ÄUÓžÔ°ê2ºÀ…äl÷äádÐÔþÑÅ/’§ÆE’3‘ªëP^¢Ëq’"'¢]ÃzÅ’’jóbƳ’£!näñ´É’£!Wëß’º'™õ’£&Ö ¢Œ& 4]&ôxÔ7¢^&öM¢D³«´8c¢ˆÓ4 5ÓŸÓ|6ê!5çhˆ×Äͤ«5{Ä䤔5„Äû¤3´2Õ´w%0aÔ)´3˜Rñ E‹³ä6ÄW´`% d1Ð0í£¿Å…´3º’wHsL¹ÄcE%çÄÌcþ@Ôí¤S€PÔ³äg³1€:Ït9Ò&Ä2u3e9=Ä28ÐÃ1Vó29+\ê.ÃÅ€iT$ÖEsÅ"sìÀ—Tí¤acœ€—TÃd„½@Å[¼UŽËU2T Ô³T @½T¼L’ä€ÓUÓ¯ô¡8Œc —Y¯9hÔ31/ÄЃŒPiT³Fä9`–Ô…Tù ×C­Ô30I³P¤uPiTÊ9ÛÔ3ž‚ 6°íDòÔÞn¼0ˆÓ/ä@­ iT|– iTŸÓ7wT&Nä31³ä9eäkeÄ9|ähv2T“ähvtdªähvwTÁäQvTØä:u‘5ÖDïä#u5¼Tô3E0Ò:9ôQuÙ´94ô4ez„9Kô314äub/2¥´2Tyô32޳*Ÿô9ô3‡Ô3n…Ž"}„2ÖD¾ôN…2tdÕô =eUìô#uܤ92i9ŸÓ¿Ä928”L¥T127œcó2_´Ì÷…_26Ú‹v25(,ÓÉ…2úÔ2ÓT¤ )TðU”:TúÔ4TÒ2<ôm…é2äV…)2(äÁ492M}´Å9.2õ¼TE28˜Ž´ÖD\28,Óð´9Fs29ÛwTŠ2Ô$ÓÔýàRTò 9¸•6:¥•Äh¥”w¤Buý)24œ9$2ÿ4uÊ+$2d7¼TB$26ZÚ9Y$26CÔ¥Tp$2?å µ:Tc”Eež$2J#ö0!´”¢µ µý•D“µ¥§$NµE•§$¥T4¤ëF(4s´ÔF?4\´ÂPÄmµÊätdm4)UaÆQTDCÑV›4‡ÆÅ”2¤eÉ44•.eà42©¼T÷4@T[fD•Öp«Ö‡¥^´ìÅž¥„dÖDjEoSf@EÈde˜E tÞ9¯E`ÈcÆÆEoTÃ20ÝDVÔô×Ðs”Ó£IÄ×Ðpª½D×Ð#T“Ïä×Ð:[æQT©þטÅÏI×ЯÅ#€ÑÖ.•³ä.åE•Ýs›ƒ2!0ÃT¯æäÚT2G4˜“€½àŠ”dQ#½à#T-C8:#½à:U¬„¸åMåĸ啒”¸å㥄cö|eöì“e åå©f±ä.äÀf„c3ÒÔ×f±äéÔîfG³4@ävÀ”A£ðgÛ4Ìõ•óôýäJtv¥>ú¥8 µOÒÔtäÜ”‰×å€O.ä½tK•„ƒ‰#T4€b$›:TØM4‰QT2€ôt÷”.c‰”2€d„.””ƒó@…E”2ŠCÑÕu„21.DæäŒ„2U䣄2;s,溄2$s­:T s–QToTÿÕÿ„Ðmꔲ ¶Sð2 oä#s€dû#1%"$[”õ0ZSär”§`ZS.䉔‡Ú  ”~ÀZSÒÔ·•oUýäΕ ƒÁ'”†T«&”lc“'.”'c|'E”OƒŒT½\”}ƒxD½s”4 &o¥b7#Ts4*õ¡ÿ# Mesh "Circle"â0Ã77 rè d5kA77F²[74‚A7ÊðÉ3ä‚â¢7°³2S½°A7,`³3’5ÇA7xÿ '²67ßb2‡À(DõAÃ70ARx'E Q76a3žQ%±(D»75Ý5ÒÔƒ²743¿Ôá(D Á2‚cšA(D×21 Džs@¶1rBåBÿ .äß²6¢€!BÒSè _6³ð7BÆ“¦v7( 7B¯“¦‡665¤BKT[B4°z’ß!T»64Ó¢23ªEiÂÅ0÷a¯±TÁ21D0U×2×ÐçCéÔv®Â74Ø213"$‚ÅÂ6ã@!B{³¦õB9p$r3¸äóÂ733È3 ìE Ò77Ž¢3áàT[B°Õ“ê@ÒÔ8Ò73²21‡säP‡CÁT·åfÒ7ƒ59–SÑÕ}Ò`æC3”Ò7K`!Bg£äPB±6d´õÂÒ66íS3 *ô1ÙÒ7pcBÀ³``¢EB3õâ``1â7!7}‚-¼dqB6]²èñ ¼d‡B64È3ÈTa`öB&qc28çe6&°)SŠã1zâ6_@URR1R‘â7|ƒPF1¨â6QÀJi1¿â6ŽÀ!B2"#1ÖâapüC•£ÔArB_"Àù˜tqC'S×wÒ674T²T12ò66CÃð ˜t×2+!BT1`òQWüçdwð} # Tÿrianglesû {›8urve.|ïЫ1 {4±—2},x‚4¿w ÿ"edge" "ÿcollidab ©0‚ƒ£"ƒ¦ð}u„3“„3&á„í¯Íˆ~Ž ˆÙ{E²…¡ˆÅ…5ÛŽ1qa…–{ 5bÛ2f—ÀŠsŸ¿Š‘ü ‡žŸn….—.²¡ž4åA…‡aÅ…QŸTáÅ…‡˜EŸ„œ¿ŸŠe¯*4¥N¨¥¯)¡XÐ¥2-¡‰¯ ‡¥Ò¯PP註§.–®¯Ì¦÷¯ ‡@¿¨€»q„)¸9¯'º.‘d¿ ‡«¿n´˜•¸ç¦‰¿å¶Î¿ ‡Ϩ€8§ýº¿üºç¡9Ï ˆÏSÀf—iÉÀÏé ¦{[‘¤Ï›¨ÄñÔ¯1ÅÖÈ[–ÊÏèÆß ˆ[ߨ€H!хƢߠˆÏA0h¯ìi•ó˜36àßz€!^–-§D×8ß–×ÂßÔÙ<ïšÐô™×1 ¯¨*¸ˆ|_2KAC¿•¸4ûAÏï¹A>ï'Q¥©ç{45AãßiQÅ ÏМ_ÿ)’ˆ˜ÿМþ—N™1¥#âÈÿ ˆ5£ÿð‘~‡ã30ÿÞì+{54ç§"é1/ߊ 󯜚"ä«4*¹îïµû4y¼ù ®.×Ë€`¿Ðœ8æÿ*ˆuÊ5Ï—¬3ªïùÇ3"5 è°‚2T÷y)’g— 'uÕ âèXC/SÀ.—52.˜9…/º:—2'»6„‘ç¨Â‡º§ /€&h/âè ?è° ~‡2™(4L?"Έ¹ÝíKdÿ-¨õ)/ò,X€Þìë?Áñ.˜K-Oz‹1ÕȈƒD¿L)¹à/§LÊ¿Þì¶OSÀˆêÛOÔ˜•·^Ê0èÞ_›¨øOÛç©LŸ›Kõ"a_Ô˜«_rû €wû?_T÷3+?Ï,OA’ˆ樽{m]_М‹oòÑ-¨siëpm­o×üûo»0È( ¨1¹2ˆüø8¯ˆ˜âi‰Oßl_+]@Å7+ ÂéÔ˜7í_W‘È)åÞíPñÿ˜¬y@—©|j¼Qú3½¢ÿ% Ç5²#Ÿ›¨i(¢È(*4AŸ ‹Ç" gŸ5™³ŸëÀn86Ÿ¼I[Œ¾ë…Ÿ¢-cŸ(¬±/ø8Ø3û÷3 @—ÿÐ ¬oÜg”jÔ'9^xóŸ‹xÇ(üŽŸî—þ¯,¨v¿'÷Ø OuI¿Q ©g21ŽòÑ‚''­¢ñ^(ÇÜØŠwAªŸèÂOÏ—ø|GD_x\¸¿ {ø]ºý[¼l(¬8ß k7¢]ßÐoOòç!7š)¼ßDñß1Ó2Ÿß5™ª¯:¼Ù¿Ì H¿÷(€ùmÏ«=Ëïñ‚0°}I^oò!!×37qH7zߊõÇ Ø°ÇßuÖRï ²Tÿ˜gÆ)5šÏ†}€<²wÿíHyß b‘è ©8ÎÛçÓèÿ¹Ëïý— 4˜5249ñßY¨Ç0ÿŽ÷ZsXÒmA͸/b÷sXøï†rørÿ,}@ ß(",'¹ xL2» ;_y@e§’ð½ÏkÝœT@8/jÉb¡È±6Âÿ ®¼Ï_ì”/Y|3Wº/d脟èí°È4·¿VBÈŒ6”ÿg<›ßÈ,v?$ ¯kÝ¥‚á W1ÛèMÌoSw]9ÇR?²7"O Ì(mOwÐ!Øš™0ö•§™ŽOÏÍÝO$ð€wšß'®¯O‡{7Èõâ¶ùw¤WIO©GD_Ì(¼_b¡ ¨È˜7¯ÑaWà`ÿØ>ǘZH¤X÷˜_øWá_dç…oˆ#áéø8b_.±k·3@òíŽ+oŸx¡Í¸þÒcŸg2Êk¸ž‡–í1²&˜&ÿ­O¹l¯4=aõÇ1í¨49ÄŸ€¨Ë1Mh¶ÂO}¸†ÿÓq?ƒX*gö€y/èñÄ'Òðôö¿Äah`"–?O¹'aÄÚØøˆ5ýBöž˜53(ß\1®µˆ¶Ï]@h…Oh²ëO׈1â?„±ÄÉâ/_é _‹-Þg™#Q_ûÈ[rs_SOe q¸-¸—˜ªG1§òå_P.ÈOa1ÎØ4§3ñŸÒ†91O*ÌÄO´Ñø9§W2Õÿ ‚§W3ßâÆo>Ù ‘_ÖœŸb7׈6“Aì÷3¼'^ M_Òñ_ؘÃO_=4$ðôá?ìø|· `2†88"?:Ý/o6Áø÷Ó¨qo°ŒçOÔm¿m¢ŸµM oÀ‘þÿ'Çð“ kZ²'ŸœùsŸî§W±â˜ŸýI·ŸfJCÛŸœø`'{iîÉdˆ5L_™²Úبˆ1ßçœúˆ¯Øi˜¯6Á|·ÚøŸW±¨»¯ò+à{i³ˆhIÛ¯¯2ìøKè2ñÆ*LèÞé]ÜwÐzÚØ³ˆT¿r·Ì¿ghCϹò²çlê›ïÑuI)¿cm‡Ïú^§+Ê2ŸÝÖÏwÍ&ßèñEie8s jþ5ôrLßõ(a0µÏÆá†8…812Ï@úݺ¯wÍ ïÒñ²è2ÊøDz îg4ò0ï¨8\{iCˆðÙ1oçåßGè¢ï{Éîï'QdèQo,­øÏi-@+_4=j¯ÞÝxCˆ1ROÖþeÏwÍçÿ\G)S3oùhÛ AYNïæ±ˆhÎúH+G±Ø7”Ÿ¤<2˜ßÒ1ùg4ü¢ð‡‰ÊÀ”g5X24ª˜cçÐzþ“h1¢B 8ÉSÿcmÄÁ§W:£êª˜d74 Œ©”iRDü'Qó'Ž·N‚./¹I/_[2t÷lTyÿ€È¢OøN|ïÈ‘ùh­Ø1f—Ÿ(>?giŠ?îÑŽ¸¸ò°?2’õ`DirPô?IXlë1øh4øg¿š©Ç"‡XUO»Pw}  È/clºw°* È1kx[?2V‘8éwp914L/@\ÁobmO_¤ÂÕXøj°O‹4 Ê"_W‘ 8r_cm§/$J47X1C¹Îظ÷•Ð(œ‘€×3@3Ö’ô_€L2g$pð_ ¡pèÐh5÷Ÿ’¯xSi—+_XoˆYEj^¨¢i¸ÿ‚g˜@ i¯Ó\îSkIåÊ1‹ø0ð?Ú½»o±Á€× Ø4rŸç¨©È©Wv“ˆ O—߆ò¯h3R¨ÅGó*Öè,x1•V±íèIgŸG±n `¸ÛßÉ2Tg25h/ß\¿™W)@¯h©RŸP8m×88ä9hw¯G±¯hè;-Í?{Ò¼¸N˜1ϾU¯äM¿a9yæ ë므×ÉÈöÏ'sh83OM¿ªÑpèëK=–òÒ>W¦À¬?L<6Y¿v!)‰Ÿ„]3oj!~8-81­×ð¯R¸¼ÏèIßDñ(Öè›ë2$Ç 2Šø53)ìÌ«.ßgÀzœ(50Ïþ ¯O(’œ( ïHlØ!6ÝhÙÏ528X7Éß©ý/ï\aTg3ÚòÇïæ¯2uhúè'ÿn¯hK=@ø2ØŸ[bØn¹Ââþ/9”/½™?gKC¿?ª)š ÁÌ(j7eÀ€!O‰ª¡£Ok©r/3L9¶W51KÉ‘•çÿÚ.ï[bQ?úŽ>?‰ ßøÌy8ú/O\ÂïH½^_nâD(@þb…_ÈÀ—8êuh0 x(ÕG’yŽØ3ûÈ3‚SN€Á—7“É_Èq/¶‚ˆ(4»?׫8//É‘¨•¬oM¸o⢧FYŽ×;_W€ïo—Y:Å_b-ˆ(3ç_Ÿ¡ÖH8•èNOéB²øpO׬‡bº›×‰1¯LÅ2FX4êßJ’âG36 “ ŽNà¬Ç2Gˆ31}î‹ s³ª)þmØ"x1Rd˜ŽÒ$ŸM¸oŸü^‡Ç°“Ÿ ìï ß{È™õŸLÃu‡3€83âwhŠG©’ŸBÍS¯ãQd—2xשÀ£_ ÁÖHÖx4¼÷øzðÈW˜1=?¾_ ¤!¿ŸQ;¨åˆ5Vÿ¢Ò@‡¹ ŸrïcÂâG1«Â¹¿y׿=¬Èì¹ϼ{ ²tý¿Ë¹Á}‹1FRoÏ #éIÏ&ÑD(”è2l×ü¯€^¸³ÏzhþÏLâˆ(”è6 e¿aÛ14moß* Šçu±øHÏžŒ)­ƒ›¯ ½ø7CH0ï‘íu¯"]0—¯³áýXæÈ20Ïží ’ß3Ý®ï­ñç§5S829ó¯>‘1É h³ßNáâG”é2Lÿjþ3Ý{ÿ>ú2æÈKÿÚþµ¿ëÿ<£‰d˜´²Hˆòx16òïlA753ëo“] ÿ}‹µ ãã_8bùî^ý›bÇzh@¨¬Ã£g&ˆ/-Á8 eàßÔ!8‡"«ň.>BT8cB/y´Ÿ3k2ù¢‡hYh]âÂdø1] {Öy(¿Oõ.Ðïu?>‘–çQâ,?†H0È!›(?‚L²ßøR£ˆ©æ_îÂdI§uÑ?a8hòˆ~/`LI2%OÅ8oO°ÐÞÖy5÷â/D7•OyÞOa0èüR`_&ˆÀøRd—45C_¥}e_òÑè¢9Ð?á‚ÒI¿Y!_ס '4/À2??ÑöØt¯1žöq¡(d‘ooXé–oÊlÇoÒ‘`8Þ22¬/{ø¿])‚²à÷|#OÙ nÑÐí¸†RW…©_>ñh (d]Èn¹9X˜–ç32…ÐÑ ¸hñ‡fø4©·}%_ƒxnù2<ï²!O]}ÂUK 7oõ±s WHFŸî£ÈO(8sŸþñÂ(I”!çÉ®o I?ÄÑP(4-ˆ¨_žk¨‰¬c Ÿ¢è’óŸÄik¯|á¢hB‘¯r(3×_œ+éñ¯Ñ³ñhgø!¿?Ñ&Ÿn,5m8áñoÊoø÷øç{ ÍŸ3[2Ñy±O7ây6ù¯¯ñcøçÈo"cø8¯?\8Ïß±"ˆ¨¸2\ÙÎѯÀmêÏÅÐE!ˆ3Hoa‚-ˆN²ßÄi>¯üÌ"ß9“¿[k ùáßé" 'BÙ0Ÿ#a6ø!‚ÅßXâ—·êØ¸x4ïžì-ÒcïX­ïŒB×¹ïŸn,KÏ*‹ø4ÿXà÷3Ø"ÿ§Iòï¾!Æxvù¤ÿ?ÜZÒ‡ÿ9=ï¨!û1¨1¯Ž²Vø–é“ìäâíqX!ˆWB–*ùxÏÕ!C×È öÈ,jo®.ßÚqó8!‡µ/aJÅ8’¿R”(¡b¼XGz ™Â;µ×¸ÊWM­ /XK/3wø9ÿâí/Úq ¸Rèï¹Sä—î²¶/X_7ûéî’Å•IF?€Î Ê $?š[†·z ^i1 x¶?4(3(2{‡'/‰(—?„)O[a‰˜Ýr5O¥y/ÓQ8‚yOYYSOb‰™1OÊÑÇçz,hH4¬G(_FX_Y_K±ç4rs_99‘_4ð ö8QOCc­I ·6O¿ç\ {‚·_)Õ_7;_¨wÏœ3‰h3Ó/2Ɉ»ÏVÒˆˆðH_«s׸hI–OàlûcVoÎÀ—óÉ, ð6?º}³_-Ê=qè3OØ+,‹uO <>pÁ—45§X^§Gªž‰ì\©xÒwøÀßÉ9ýoA1‡·4' 0M_«¡ ·B¹6¡o~œ[-ŸOìÄ©•ëxøqØÝÇ j[7%²Ÿ\_ý"g75žÒP¯ÏI0oIQ%ˆlÇ5¥'>úCØXr”¯‘y²¯IP8t™2p×iŸÉ˜¿`“ØP¿òñHâ¸37n¯:ŠhGv‡w¿‹I•¿€k/bÏÎÉûé¶h2!9§Xœ;!ƒ¨4–ÂXÏ \_Ÿ°ÒH˜8¹7#¿Ý{…½ß±10ˆÿ€]Zß@«ähŽ£P.X×úÊ2ðG€ðÏRØ߉¹÷ß,½Ø0ÅÏ€-çÏ1„¨zßWñï-’ظÞÙ3'Òß4è¥ï‰¸ðï§½Ø67ß^­£ÏGü!1ïËLVòQ^5¯­ý„¨ÏŸüûTð¬ÒòRo^­¬6ho  yÿSño_^­v˜Â¿à â[7µÁÿ·­ýË8î ”· &¥Ï^­æ˜7…ÅâÓ¨soi¢Wÿ­ýû /çf8 #û]ï^­ëuÏ ÞØ}#m/ÿ^­‰XßÊ-Þ otöõ/±ùmM?:â# ¡5g?b©Ki/u¦9„7Æú›ÿ­ýQ)Û/qJø Ø Óÿ^­I¿?Y,ŠI RòGO³í+_×Ì4ÿj[°p£OcQ_±ùv™1O]‰ðgî H—Iú¾?á9Õ?_]Oñ¡ÕX1’cocYÉIq‰Øâ§ocY_×m¹O_]=o×m c?_]_ùÁK9M__]o£{3æÂ·ÛȲrÙÀ‰’û ‰M×k29ñ/ +o Åo“k2*Žoâ›ü“ Ÿ ‰á_✀bOŸ ‰o_+³_]uO“lÄbןcY‘?³°Ô?"ÍJ11õŸK¡Ç1P(1¬"S¯)öBª¯a­ýG{¯¥§—¯÷£Û¯Á¯õ¬ž©¿Œ]nR7¿ ‰Õ·µ¿ ‰ƒ™mŸ[a/Û8oØ8¯<Ë{60™¿ã½$w¿Gð03¿é¬1…W_ÁO¯é¬šÂÁÏÓËÜ`À)Ÿ {~$üÚ4ß¾âøìvò¸vÞ# Mesÿh "CurveOCirc*ðÔÅ1š[Ä1›ÊÝÕ ßÌÑתÝÕiGøß ç)éÔÞ»¿ÌÑšÝÕGéhïzå—éÔÞAÏÌÑÝÊÝÕµéÖïèåùÔÞ…ÏÌÑcÊÝÕ#ùDÿVõsùÔÝ2±Ÿ_ÁÿŽû±ÿÃöáù¡þÿ¿_Á/ÿüü 2O ¡þxß_ÁÁïj Ž ½ ¡þå_ÁSïØ ü+¡þ¡_ÁåßFj|™¡þ]_ÁôØê)¡þ1ï_ÁU",F/X%u)ø¡þŸì³ÕFont.001ÆÕ7}ëWßÚ (ÝÏï-¡3»—7ë ?Ú$9;?í¦*95 r?Ž0Ñ¿ï-éö„:Ï£=?—Ó3ï?{?_Àп[ݲ¢>ëv8J‘?WM·7$'„:%èÀJ‰O›EÅI£O§9û†„:›Ï£=×ùO9WY_§9ÿÇ7ׄ:÷W¹[ƒ_;ZÄT_§9Õ?1Ý/£=ÝY7?+O _ k9o ]OWMë?8oCÔžç{93ŸOï,$(—*93U_ï,3}oï,É2s†*94oé«86%è4ÁoGÐ7EO©}»X3¹GÐðr‹y½È˜²4E·8@‡{9 8II4—é«9Îà}7_‚Ù 5ÁHtr±Ÿ5œ{7N¯BÕ\™RëvŸrp`Ç_e‘WWMµç84³hípâoî-7“'75;Ÿ9q“'80+*¯°€Ÿæ©9a¨4Oo­ öhz=€‡}5ˆ"—Ü®¹í¯ó(5õ_ ‘§‡86é¯á|V*:-¸ê‚õÍ™ÝX:’¿­yÓ¯e‘m¯ï,âºÏ[q49¿\Ü5•85ÿÆJŽ}‰oÏ߈0çDšÉ9Í/™UÏ-q}¿á|4kÏÛŒ3 ŸWºÔ]ß­y¿Ëq»Ï‡}-¹[¿ÑÕûÞ¼ßï³"Ùß­y¯i¡µèhŸVMXÒ%ßa¨>¢›ï[IÍ¿¡ÝXÁ4ßÛŒ ŸØ65û˜0wúwW8oÌÎ!ßi¥÷$8û˜8¡Ÿ{ŸŸ@Á“åÿ߉SïóÿÓ5Õß©í%(|²£¾2gï-'Ïï,4K¯CíÙŸ©}ýïíqá|d?|ÎAÿÿ8Î ï¿K½9u5t6#™áÿ Mi¿85£á}•Cíèîìry‡8üâQ/5ùo/¡ÁH0rÃ/[H‚£¾%8-·68¿à}8/Ëqkß ‘-ƒ?+/i¡èx‚±?5ù3Õ•ÿž°ÿ:/ȼ%?ÑñG?kÝa¨Ô÷ÌšO9Í/IÝÝÏ-qå?½ ­?ß 5O‘•S_ï˜,¹ÜÏ &‹_åx–Ú0™Ï;¡M/9Í1w84oOjDlõO¿?iKnîpSoÁjPd€…oáYyO aÿÛŒšˆ9&Ï’o@Õ÷«jL^à¦?/¬8…øx‡>JË_ÿ]IݽO¿‘#9ͱ¯™]ëqøþ^µ_±…ÅM،ȿƒ}O}Ï}-_Ý]Åo»%Íô–˜6òÏ¢@‡__-¹h€~=Ÿ q_€Ëå/¯“¹Ç?ÿeÃ×9p²g¯MØ7Ÿ­AùíìÙDÚvï¯ñéؘόòc¯µj‘ϋ˜ŒÂw¿É÷(&Ÿ¬B‘Y=˜´_Ú|€[³ÿ¿áYŸ‡áÁíì8§¨xOœ²A)yx¿Üò÷Ù÷O³‡ÏÅŸuq·¿Å­éuï… 7/¿=mÏ=qs¿ý­?È„§ÂêƒÏ1}÷'û¯F¨ ï™gßq9ßµHêwï±_Ÿ_-A(¯Ìæ÷éÕïáYßÏuq!ÿu­£˜Ô¯Yÿ#™«ßyѱH¢¡ÿ¹¼rÏÿywÓ£ñÿÉ©ïß! ï×Öð±G9‚ÏX>Cÿ!1…¨4G¬ußï%‰ß ¹•ÍËÿ¥QA'6.¿>3ï=uŸ¥H(8ŽjÑï\b/£é‡ÿ‰å³é=/™ym-õÛûáUïɽ¹hîßtq°Ç¬yx4Bç/¥Qig62ýÞwpÞC?™ÈA4؈ҋÿíÿ\1Ý?Ï}/‹AÁߟíq(Ì/üv™´97Oÿýÿïyßwû R¶6‹OY¼8–Åq(ÇN‰2ÿ?å^Ÿ6náö*N]I…_y©!OÛq ›Ýáø9Ç?ũΤ eO1qX€Ÿ/«9¯³^æRoy©£_£¡íOÏ}Ëiùos1×o•Ìv9ú¿P?øv_5Ëi—wõ±-)?Ȇoæ¦×Éõ¯9[/±aÙ¸Ž8€_’è‡OqõÇ8v7RZgí½ÿýç_¯¥Iµ#Ÿ…½c:t4kŸE¹£¹ÔÒÑŸéá÷7< v5yýŸó9ëwû9¬šÞ‰Ÿµ߈˜?®þÛ…‘«Ÿ…½Ièj¯6 ¿Ãy׳oŸÇQ¿Yý_å°Ïm8Iè*ov¶·¿ù) ¿KÝ'¯w°0ùŸ‡ YI¯ßŸ¹/¾FPÕ¿=kWc¥Ï}™³¿³Ï½¥‡ÿ-ߣé5!ßyÙÏkLÌŸÊ{H6¿Ð²­z·ZϾ¨áß ™ß¿}ÏÙÕéuïó9¯¯•Õ¿Ù¹ïÏ 9ïc‘k7•ýï‹ ×ïSqïi6¡Ï“\h('8zB›ÿÛX¢_ô’)ßå–h0“ïg1µï!}yˆ1I_ÃO9dO4â=ÿ×\*º_ÿý€h¾HßÉ~Z˜Ùs 80RÍéj7nOÈt-èf’½ÿíéI¯MÍ ï­ã­Å1ç!}-è’ɹXL¿ž®aß;ßÁ ï Ù/ó9M/5áѯMÍ+¹/?Ù1yˆ$"‘/+/-é /W©ýhÿDRÕ/Ïo¸¶2é>b‚CO%y»ÙEŸ…‘ˆ5?O‡ý·?ç/%Ah0ƒOaímO³5Ý91_QÉAu_ɸTØ#__UØr?v²q_[­hGà_þXo‰ÓO_“Ïø47x‡2JÉŽ1xÏü‚-ètò•±OñoS-ç;ó—ïõOÛ -_»]¡?™uÙyÿYoë¸Ô²Ó‰©_Ÿo¥ÞŠ[¬êÒR'­£¥‰ÉCeAi`é‹ù‡¿¹66{x°OÈ’(5iżF@9 ŸŸÉ¸¦'0©:8ߟ £½ko{“(9—ÿk}IoѱoŽuŽKŸ!…ۯɹG9ìçfʹ/º ø¯~B#¯% 1÷9tÿV¯@Њ³¿ñùÏùá'{7üòß¿1h6wvN#Å}¯5­k¿'}µ¯Û ³ÏÁ¿K¿i³ÙÏõ™ÕÏçÏ¥/ßOýY=Í`‘Ï¥ßSøøX64Ã!Š:´¹ßß ãß¡E ïéH€4 ¸gê$ïP؈8NRAïùŸßñI»ïOü„JRÏø3oÏW=kïó{—ãGÿß GAß3‰­ÿñ¹_éMÏá ßý™Cÿ»ÿ“<ïømbÉ®¿XZ&G»]ÿï… !ÿÿõóIÅh: ¨_”Nå­×_ù±€Õÿí½{÷™“çß-l4[ßÇÝù±•8|¢ u¯ý!o(/öŽóE¡/ýiåL(O\œw“û/™I/³i¤zra?H¾rÝ5 Ï9e?SéÙˆ21¸™JŸž²k“½c'­áØ ¤-OùWkCCO‰ M/¥Qˆ÷/=Í1·7ÞO8âý·9!3cÈ ÿÈt6sùlDæd©3;?5­£·6šOªí‚¯_]‰•_É?OùlfZo9á{ù3oÇÝû_o?3…©ÿ“½±I#_/eYiÕo‰Yÿom¡1·6r_:žÅ ·oÑ…‰?³×Ø3Cý•·?™9X.7|:ר"û€?™UÉ1Yx6òK·ˆ0{/ Eñ¹aH—À !Emy%£Á]?ÅÍùØúR€¿oè§î€)O©G7ª_>ao•-™ÍŸ—¹eÿ‹7¶2¯ã 5Ÿûj,©þ™Î¹‚oÄ}0¸«ûžˆ?DnÉŸ™Ó´jÅŸÅÍ¿;¿Óµ·¯9Q¯ŸyŸAѿܮ¿Î?ÅEÉ/ÏçiFìÙ1c(ŽIHìÚGß<¶¯ n‘Ï­AI@øÒûÏÁYÙ__ÌY9ß¹•?ßÑéc(ßP²o(I0a¿•¿¯¥HRï‰ ó¿ë1¨àr9ï Y·?»!ýߟïW7\ßz†µïIi‹½]/¯'!Õx‚¿œŽ¿Ï%ìŽH9ä¢_ÿï+5¯ÿ 9Yy}ÿ…1I6¤oÞ=*Âaß•ŠÒ+ͩ寭A«8Hoçis¯§õO鳉Y'!óc¬æ Ц’/ë)÷Ͻÿ› ¡ë)o(¾Ï„¢«ÿ³ÝÉ›=MÏeï%ƒH9 /¯«uk Emв·T¸9Ì?8×ÿ‘/)I)!?Í©÷óq]œžùXÜv‘?g©/Ø2ŸïwgÝè`»?U|`Hg‡7³9Õ?ÓIQ/oQ9ÔrO‰YÙ/s5ÅOŹÿw}ÏßÑu_E(NBW_-ùÿ?ÓõÑ%_w}—_íû/Í£ŒìViõ_£9oUuEoç¸òb}oico…¡)é³Ç68U?/?¥ £6Ì(7ÐTrùOÓM¤yoA,79ÿ«°8‰§83xêŸ^fkA)˜žOî¶ÑÅ ŸøÒgìN5Yç¹?§%Ñ)eß™Ñ?ýo-oahø ˆ7‰Ë·ÙI0᡹_s¼˜ˆ71‰§uiŸqùßi·wEÓçq£­ŸÝ³¥Ý®®àƒQ±Íû©ëo¯#|O¶ŽEA-½oE;SŠ‚Ò’eŸGíOH,Ÿž¯&Ö¹¯ÓMŸø,OÄ»F0mè¼oàÜyïØXžï6s)¯¿±¥ÓèšbüKɉ¸# Meshû "¨Á.001"†&Ô10."E~/Âì1 090eHZÿÞÎÀÈ íϹÄÚR ßãÉ2)ç¾À6ßkßo¿Þ}ß¼Á®^߆10ÞçùÉ@¿ÞÎ3HpÚ“–?Ú0¡ßßÌ1|÷½ÀôâUî‰ë4MßßÍ—ïÙãÛßã<95gmÐ ï¼Áª/ÞΈwdá/v?ÚCêú/²ßQï¼ÂŸw9ðSÏýßï€á_¯ÞŸw÷ÿ/ÔË—10Dþ%ÿcâ›oßί8ƒŽÓGÇà¼ïßÎ×–†Û!ï_Þá Y÷,Òê;Ç9Ö—?ÛbßÍÚWàGÆ?Û×ÿß͸RVöãFÍÛ* ›Nþ+/]U 9©Ÿ3î÷¶¼ûÍÏß͈*¸/6ó¯ê–/Nþäcâ_ùÖ’(?*>á$?ýÊùÅ7ùÎ-Ú ¨?ãÊÓ?âá 1â.r/câö?3îá _OŽÓ¤?Þ߸5ßÛMý$ÂO ùíOõ_ ùU ³ÿg]ø’M_æ*x_†â_ß|Ã×ážÚâïxÚ¯ˆO§OHÒÕ_ .ù–džۯéÔ_8oÊ6@¹o ù_ùÇùÊ_ù2I_ .HÒïwÕ`ïoâ.3_ÖÒO/Îîá 6¾_ÖÆ RúU $Ç.ûU 1µoÞ9 uaãÉŠê@r=Šê¦BšcÚÆcæÖêî ùdHÒ‡—Q“5ŸcÚ?åªúzŸãÊSŸEk8ñîÎîØoᨎÁÉ›_eÊ›)Ù6Aý‘oEf©¯~êÊúOÅöâ¯Rú݉F?\]ç]Æ92‰&4/p¿Ú{yN"Ÿ¿ÔºÌÏ6¿â¿ý½R ÏcÚ)ÏPPÏËù¹ ª\¥¯ÎîÆ95€ëÎ0ÍÏâ.ýÏf%ßæ*YHß}Úš²_ßsŠ‹ß+F³ßÒê‹êÒßînÂíßÒê ïñ2=ïNþù6`ï•î2{ï˧ïÜÏï=j¯™íòï'ú5%¿9n5ÿÐV ûZ]ÿ*™ŸŠ½7ÏüŽîïe–êÿ¬Šj ƒjÑÒ$± U¿#Ow¬ŠÃÿ£f¾š¯™Ü¸G+Yø…$'†Kšö™iþ\ô\b…¯„&åëY­ O\bÆ9&oæ^– 5J e/wj|ÿ­²åy0/Ξ±ô¶ñ/wjåy?+“Þ¯ð®YÂÿû£'?ð®n?ð®ƒ/°6ò:Ü?=j¶Ï=Kwu#OôªoÏëÆjOwj¨j Ÿ¾N×b¤O¬ŠÐO'‚$™²øOêž?yÒùº C^_ÒLÏ9n,Š_ô²Ø?3ÞG¢_×_06ooŽë_€ÕõYoê$™]_ª’,‡9_.Dß‚Žo -ÔhQ3¯šO¨Žû?’í/ΞŽ,’»_˜Î$™˜Ÿw?yïÒšGpVBšT)`Y§|œÊYJxoÝŒ# ÜÊï­²ù¹6ë®5ŸGò>9>ù¹{Ÿ¸ç—Ÿ Ð ^yÊâÿ?º5Ÿ‰î€É/Gö2¯Ð ©ÊQ¯†¬9 vïo˜¯|^w9wb¿¯Ð Þ¯E6¿œÊ¢Ùì"(¿]º•?¿Ð k¿ÙV“¿Sê(¤Tb¶¿6J97¿3ÞÔ¦!ÏœÊJ9?Ïæ¿2[ÏmÊù¿¢a/ -žÊ$¿€ævŠéÏ$)ß[âJ94É¿iÎ^vc߂߉ L™}Ò¥ßÚÚíâ¼ß=:èßYvïjf ‡Ïdî5“Ÿgnvìÿ# Mesh "*Îá.9P"Tu2ÿwN°¡^v1†ù°ëï„:¿€>ÿòQÿ… åãˆ6€ÞV ù¬üFï€>»ÿâá7çïùîf[p8 ï€>I¡ /œþöçF ‡ «ýêסá‚ÿ„9¦öÖ™9ýêeâáê~á‰1p×'£Çýêóâá5‰¹ *Ù¤;/p.ùî/^x22Q/þ¬ââϹß*?âá6/¹ P"ötÿ‹?&?ùî?‹ÿxMÙ23ZÖ úKÁ?¹ *OáâÓhj0.ÿ¹ Ç ú}ß§O!¨11îOÃùî_¡È¿~.ç ‡€ÂO>Zb_ýé_ÊC!¨2ˆb/V?„B»¯ùí]RÌVQo–OÄ^co^_¹ 2bÌVoßoù_Ä^ño0û?¹Z¹Omm?Ä^„Bâˆ2ͧ¬Jä?„A9‡oÓnÝz$_JÚ4K²_Õ< 2ÿÖA½z…ÈZ ±„B¹ìY2rO-Ÿ3oþ?ŸYR£ NGVÑQÈ/»ŸcŸÄ^ÍŸ0ÕEnóI2 I¯êÄ^[¯Ýz+¯¨N¯B†Ê¯½ Ý~_¯Ò¿ƒ:ÿØMCí¯i»€Æ¯aNw¿„BTÕÊ 2@ó¿Õ¿Ä^ÏàÁ7ŸÓnÀ˜2Kπυ’gÏ¡ú “Ïh2ñŸÓnt)2G_ßÁoÄ^!ßL"<cIßg*€øñÏ>Ú¯ßñ9j¹1Eßc.hß^¿ùí@ ë=ïh2ï¨Näi3ªo¹îgÒŸïIjËïYR$¨NXš²ÏïKûTïEnYÿ^Â$ÕV €4ÆßuÍ4†Ÿl~¶ûçÿh2·ÏEn·ø1qObš¿Vu^™¨N¤‰3„ïñEEnùòG¿ø¹4Õ_IetZ‘Q–¹:I÷ /¢//mB}ÿ!ž†É 5Ø›.4µ>­/YRÄÿuÍ`xVÿ)?)ÿp^`;?„BC/užØ21¼ï"Ñ/Enäi4 ÿþ?}/p^O)4Oã.À™-‹OVBrOtZžOiFÜJÆOtZJYR)ÏÖþüJ,_>VjZG_ØI5‚?Û2aEnÙ58ï_nO©^oàAõ×*™?Öþf/Á¢%os†É g§Kþÿã..95WO lo©^B²íoã.Lùwßo[z­Z«ræÓ:Š2™â¯+‹ _,î9Oæ{êayšÖoµR s#¹ÆP“_?¯žžz¢¯CŸÑ_©^UŸ)%Ÿ¾h GŸ“š·Ÿ­ZãŸÂ{Öþh 6Ÿ_®ß?æ¿q¯^Â]ç¾Lù6Hoí¯³Ÿç¾ÿ¯àByŸsö 6ò{¿A羿ÄnDßÄžÕoøóÏÔN.96œŸPÏ]¿5¾bÏ¡b•¯>„¿Â­Ïâ˯5¾ðÏ)†Ïå‘Iî;ßpÚ¿Ïn¿~ß›&¦ß!:LøÏ#ÉßþÛϯÖþ ïµR0ïÖþ.97oˆï±¿sšï(vr2ÏÔM2€¸2›ŸÿÎŒ(ÿêNß©^€¹…ò,ÿ¨ûÞs¶ÿvrßÅžêoÿ2†ÿsDx"Úÿ7žŠY7€ÀsÒZfúçZ)kbR´@{ï`+âLÿ ÎI8º_ÜÂ;šî‚„|îãÉ+‡°,*P/;š|/K‚¾ÔMK"?–áïø/¾ï7ž ?ÂöŽo*åO†?0@7ž˜?½r¼?`Þ™3dO#¿ Î&OóæfúNOdÚÏK‚/7ž„I³O@³ö? ÎÅ 9ûO0^Þ2_ð*B_Ÿ‚„J.?~mO:ö±_€sŠ„JÐ_CbJO5¾á95/Lo.oì.^oK‚ç_S~d©9Ã/Úo /ì.ìoK‚‚oŽ€¹9oh­_ì.zžŽßjýÿöÚ/ì.ÂËO Î3v½qß?„hì.–+â‘O ÎH™9Ÿ¼oì.$Ÿó²ô ÅžQh21O Ÿ_ù^²Ÿæ²JDÍÕ’JæQ?¼r‚ŸBîÅ20‰_u­i“[¯Öʇ¯‚ºì.zª¥o¿¯Òο×Òê~ÿÙA6Áä9¿ê~S03Ø¿s¿ÒÎê¿EBI-o¾_1ÏfYÏ šHÊxÏ+⫯ ´ßh20@¯ôÏØ ÎßN.ß* ùƒÃφۀHŸž”ßNóh¯–¹0ÝïÖŸ Î"ï+ÖÏBy«‹žï¸ß ΰïjòÔï ’î‰ˆ21¿Ï}’L/"®êÛßsÿòß Î…ÿ}–ðš­ÿýZiïíÒFïê}TòfίHËò.ýZZþb3©2UÏ<\¿¦Ò©ÿÎn¸ è,ö–꥚/dÅüù^v# Meshû "Î.003"²…4™uÝ32˜32y§08*44~ù˜/#ßh45ðÿê|4Bb.4¨ÿøu*¥/!5.)6¼/”-¢ð/? Í.:2?áݸ4¢²N?˜)6ù– *Óï“.;Á?âM4†ÒÜ?&:Ìö *7ž?ê>JOOâ4Y42jO˜*–O6",Où¢·bAì/¹ËNͧv1MÖ ®+ßh31J?">k_!M8HÈ43ç”-3£¶®+ÏùJ6v *JÜBo´:@oâ*ù†Ú€Àw *ºª¯L_k–®*6ÀôOù¹ 4‰H36€žoê>$_Ó2€\>‰I2ÎoØv¾˜).ŠêY"3¨4þËOæKX48ºvÝ9²_·"²€”-¤‹;_vÚÊ;$”-81ø38Gu2F>~ݸ3Ôßg”ŸÈŠånÄŸ5HÈ3¤‚ÛŸî:yŸY",\>ÉYM¯ÃSsy:/¯o‡oþ&½¯ýhç 5௻Ÿ°>#¿!GÉÚ£K¿ýŽE2ó¯ù€º°¿ÃWÌ¿ý¥‰ÕR}ŸbÅjÏÞºÝO®–gÏî:"„ψTm9 ÿʯ¯·"1ø4âòõÏBz•¯E2ÉYÇ¿ Îk—ƒ;Ÿ^©¡ß`CÏ\>^‰€·Ë^Y0ï‘Þß6R¹x’XïšÍÏÄRì°>Áh33ø¿Ó2­J›ï”.ÀŸ·"¹¯¾­JLÿàb:¹ß°>[ßö6»ÿBz:ÚÿŠRl™7ßL/¾ï§¦I&jl™ g#‘Þ¹4wï –`Ê´j+Ùß*30 ">=E2Ájϰn?Ϧ¬Š‚Y¤‡®*+âW/|²m839·ÿ\>Oñ©3}/"nËmÖÈ/ ºrÞë/ 9w“?]º.?î¢E¾^‰2 /ª?R?޼?g–ä?[ +Ù‡§P‹l™bÏ:ÿJO´ÖàÚrOyÊO.bnO¯Îl™×O?Ö_~Wj_­Rñÿ‘Þ)vï†7ú:_ö:ÿ^òñÏËÞ2Wi7Y/)m38Œ?s;ocozrÚéß·oþ/Y¾Éo|²_ošç/E~7Æ[žWíoËÞøéÊëórÙ2µO.‚o@Ñ_ò>#é4“ÿ|²Õï.@ÄZô_–ïOY¾Gé4f_æÕ#ÀÉó‡ãû{.jº}ŸµsŸ`¢6_uÎp)e_]óÑ ¾YZHŸR®õ8¯?úd¯+âC‘ÞrÙ3,½¦éªÆ¯?ùÿÍ3 (¾ º9¿xV¤ZT¿0%Ȧ„¿÷é40¤¿uÎ €¿–ⳟWé 6sC΀îOâUÏ o‘Jx3ðò ÏÕÊÁ¯ÄÏãÏ+â'«nú­__ßAß;þqß²P¿ž>0o'9ëé •ß­îÿßï†'ï±ê·)æ/7Gaï¯jaNJïŒçU!#ï‘­†Òk]ï^)ÿ?JyÅa¿ïk"ÖÉ92ÿò>FïtÂp(îóÑÿJªbÿZp)6—?šR,ºÇ¿Â² ¹:’¦;ÊÅ$&íºº—¹ Ç“Ê'ö:~Âæ{‘züzšÑ’aJwF®Sï‹ã /9ê*ßêBÀ/ÿžô‰‰‚s/¨)31³Ï(¾¶/àr±ž>Ri3¢?6:n"?¢:D?Î2dÚ€?€N‹?²†ÿ«nØy5ÏM€cí?ŠOT_†/š®o/6ˆO¯jJy®2dOàKL/š®îOtÂÚ/qnÇé'/¯wÜzP_!jý/—Âé? z=’ZÂ_ÎòÙ5%ÏÔ® Ò?643¯?Ç~©ÿíßL_(¾ðÿa†Àoت ¹£âœoz3Ú_5î&GVsZN;ʧO26•Hú I³@ã I7¾OSÞûÌ‚¼oÅž ¸Å¿j]ªyúßo“bq YÔ®á“b˲^©Ÿ’cdÙŸ_j‰›R.Ÿ²^uš¥Ÿä6WJÀŸÉÊ`O¤&¯9[92¯­Ã—¹Ië_ o梯* z^Ÿö¯öo5î¿®Â[9õo!¯ìŸ„‚ì^mª–¿ ÂhióˆwFkÿ϶Šôº$Ï@„‚ϲŽdÙPoŸÏ8J¯Ã²Ïtò 5êkÏÊÖÖjßð*@ßvhß9òڇߓboZuoz>Ш¶Ôºöß9ïYÂ9ï@n[9럀Oósï£~©)ñÒ§ïÜé3Ñ2¾ïðZ˜o»öÿBºÍ)0ÿ€'ô*LÿSJxÿ“bžß…¾• ¾ÿÊ·Úÿ~:Í)r² ? ®?é¯M‘âùù»o‚êïàÖ¼DjùùÚMdß…¾ç‰7\ïYÂ9£~ç‰À×Zk¸@žåÙïšS=zºïkŽO¿†2Öÿk-’åv>/üæY/áz“YÑ?Ð÷ýú /SJ°;ô/Dšã*?Øâœÿ/ *=/ã*?>¾0IAI³/ì^‰tb¥?!J1U/²Ž/OñfdzWOBº”P&|*žOzÚvOcfåO3 =z_Âî_´ÚÌ/Øí35SOÎK_زvÞu™5Îßžhô_$úÙ_WHo§z^É¢ko6Éúr‚o‡:¡?J²‚È2À¢ÖoìÊè?}4øCo*½L# Mesÿh "Plane-"–…50^É8`èÎ"®f2ÇH¨|3Ø5ç7ãy4]—¦| :ˆä0À×EŠÀÙ^Œ÷Ed¦qã{¿(‚Š4w÷v‹Ýéò‹žŸ\4§v‹x)T›’Vã{ÁÙ´‹<¿›±ŽS†v‹¥ÊSŠŸìrSyÚšôŸ7¯ ª9£æv‹^É+é$¯˜¯·¨ÒÁbŸh‚3Ùžªé­ž’z.001ŸwŒI5Œn_É 50ÚA¿þy2ÄŸìrS‰Eº¦¿¸¿×·¦p1mËø¾1Ÿê¾˹¯ˆ²¿(Ë1kÏ—Ë‹Î:Ï®Ï\5ïRÑÏýÇíΓŸˆ²„ŠQÊØ¿[ÛMÎW¯ŒÛº¾œÏˆ² xuÛßÓß§Ú¾'Ë/‰§ÚÁß5ïTç¦q@þÏÂþy:ê…í*½6Ÿw& i52S¿e½2v¿ÝïþyÑbÿ2S‰áêBÿTÿs÷¦pJWãzJW”þÍφþ »ûUï$ò‚É»ú33 'ÖÿJñÉ3†ï• ‰/ß$ò Êíútÿ÷ éþóß(Vþ8$òÙÙ,oC"“3/‰C]ѨY52š ò6ùÖ!- *½7Ÿw6gúïïe½Ú7ãz}+6ùL7ûS‰}*Þ/ð/L95Y7ãz@70>i@">W;ñÀ"‚ÉW:5£?Ï;Ã>r?æ? gJ;Ù(KËÀ"¼ú‰:?“K…>ÄKò.Ô?À"ÙÙ®JÈO _ßJ5À<2~)ßJùOm_ŒWÞá6O<26ùrZ½]‚*½8Ÿw‚wz!‹/-6®/o6ù;w·+S‰jzoŒo;w¦p7A?ØkÌnO@¾nók_\b‚Éój7? k{_~‚ 7¾_Í{Á~gO\bX:%z¬o/‹!~+_`‹Žnp\bÙÙJŠd§{Š7\_Øb~){Š• Ÿ(—z!ÒØb6ùšY*½9;¶60Ÿj'o-18Jo±Ÿ6ø604\b@¬¨´š¯'¯F¨Ù 9Ýot«h®¡Z­Ž¬)Ÿø’‚É©59Û¯»û®ª¯¿ 9ZŸi»]¾ø’ôjÁªH¯Ë»½®Çü»*® ¿@ø’ÙÙæºÏCÏÊ9øt¢~)É0ϤÏÃÈan¿`t¢6ùªÊõÍÆì10«—12;ªÃŸ,60æŸMß ©2пø’.©QÚ²ßÄßãײ1y¯ëî=¿öÞ +ëÅÏ”Òò¨*ë1wï£ë0—îFïºï61öÏûù”Òª]êäßgûYîcϘûÆÞ¨ï”Òuûœÿßÿ³ú1”Ïâ;©³úÍÿA`²‘ ÿâ ©F ‘ ‚6Ý1GØýé!"cßuÙ2‚Ö3ŒÚ¦ÚÊÚÙæ'6Ý2«—3,é3;ñÿuÙ3a'©vŽéyXBÑ3o ©3ÿñ‹×Ö³×Ù3é'äBÑ4«—4¿é4ò¡/Oþýé3!ù‘'p/Bщ5‡(×Ù4lñ£/uÙ4ÛŠ%,é4 7ü/BÑ6‡(ýé½R/?A:Õ; Ž!.©©7ˆ?BÑ7«—5,éfB»?uÙ5ªaK2A Žé5GOBÑg6ÔY6*RGOYJ6/íK2AZ)ÔW0 OBѪ˜°Y66Ÿ/UN€Â/y[2A!ùMW,_ `2JFØ6×Ù6+?qÝ6N?kJQ ÙW¸_ÊQ†(ži66_ßù^‚ßaoÂIw‰dkÆoØo÷g²“wïš“y|Ùï ~?{a¨bŽé?z7‹·{«~ZÎýé7’‹ Ž;ÿ¨b!jqzøo{‹m~ÿÿ¬‹Ún¼@¨b –аóÇŠ70$r×ÙÇŠáUŸt—JQ@$rÂIZš¥¾]77:ª‰8soqÝ8–oýŸÂH7œ§Ÿkxªa¯s¯’¨vÀ/·lÊ/¹¶¬í¦­Ú¬uŸD¢ŽéÛ©69'¿S»G¾ö¯j¿ýé9¦Ÿµ»©¾OD¢@z º”¯Ë ¾ŸHËv®X¿D¢ 2ÊLÏÏcÊ9DŸÀ¢×ÙcÉ|ÏðÏØbaº¿À¢ÂIöÊAݾ]ž7Í7ÖÙ70¯%,702¯™ßV©8ç;«z©Úþßï/çþËç;ªËéR쉿@BîwëßàÒ>¸vë1Ãï`ïëãî’ïÿî71BßQûEþë¿àÒܪ©ê0ï³û¥î¯ÏäûîôïàÒr8Íûèÿ+ÿú1àÏ\⇩ÿú¬þ‘Vÿ\âV©’ Ý ¾]¶G7NšÑ·?½Ý2Ú?ešÑê OÁZBWù7ÚKforeg_roundÄÖ3CLFÕ73­Kø1<© &ñà[\A/Ä/¦03ÎW73ÎÑY/Ü ÏLÁ/73òA|/"-ø%€Ý/àç\-?°'?’/0K31÷—42/Ø4U/ÀØ«Õl?&)«ÜÐ?73`GOœ7ì?~?03Zg74?°>A?°>x/ö?ÎGµO¸6é°>ø/bOœ'ö˜4 O°>-O°>d?âOºW¡_¸6Õ/°>ä?N_œ'’Ø5öOØ5_tnPOÎ_¦go|fÁ?tnÐO:oœ'7Whâ_tnotn<_ºo’wy|f­Otn¼_&$œ'.6ÎoØ6ñotn(o¦~‡e|f™_Lލoœ'º6ºLŽÝLŽ’j—QŸT†…oLŽ”TþˆÖ4¦(8#é6«ß"½Ý6Îß ¯8¸ÿ5‚@Žªr¯„¯£§ÂÀ7aïЫĮ%ÿ¶®ë«­T¢Úéëª77¿c»W¾¿z¿:7ÞÅ»¹¾‡ÿT¢x黤¯'˾KXˆ®h¿T¢ b BÊ\ÏŸÏsÊ7|Т#ésÊÏß ×6ʿТðÚQÝFont’/8±-.¯8@=¸ß8÷"ž§Óæß¥ÐÏBóßçëÕÐß¿ÙÀ2$ïêõMSï8‰Bkï]šï5ëfïxï­ç¥Ñ™¶þë:¬ãÉïZêb/ÿdÿ¥ÑGYþëḠûôïÿ MYÿ8Ô-­ÿ+é:ŒÉü]Œ;+é,Vî©ßVî,ƨó ÝZê ›­ðm/8Ím8˜R]ðb­—†‹ïU­ú²/¿Ùë¢./@*åÿ%&g*Q/@*!Öy+Jÿ<.‡*·/É&õ*Ò/¿ÙQ×y+ <.éD?V7ƒ?¥Ð9¿Æ•:¼7¬>C/Ë6=ùQÒò?8:&ÿ%"Ù<.£99B¦Æ;é„K¶OYJ‰JÇO¿Ù9ü¸2(O^JKOëO\?^®ï`90"?^Ëùf_x_­RÉ_ZmÿÀR”/1¬ÃSì_•;ÃO<.ðJŸ¤Ñ Ò0¯@*èZO¯a¦ªj¯8:Xk,¯‚º¯^þ/k埂é9¿`£ß»Ý¬«Ý¯“¶¿ºœ¿8:tk«Ÿ‚…J¿Ú¿˜¿4>VÏk˜‚ðJÏkD‚(zäÏhÏf¯‚Œ?mÖS߆ÒŠ+ß=Þq×µß]¦ì¿ª¾áiéßû×(ê﮺rßCîwâY﮺ƒoa¢¿ª¾ê¿ïÑæýêÚ﮺-ÿ´Ïª¾3Ÿa¢ô¯ª¾ú”ÿ¦öÒú¯ÿ®ºQ¿½Ÿ¼Vÿÿen"en¯JŒ vii!™0qÿen¬ Û “*ÿenÔ8!”œïen™ñ÷·Zñù¢r4x¨{20”#,­æÏ –¯!‘1Uïen°7& p/²+¦.M/ô7&â:K=-·/$"O'>¶HC?€(®*`?+:È¿W6ƒ:´?Ï Ó?$"ó'>Ož?ï'>Ï$":'>]aOsOzÏ'>1ïºFæJ_Ï ¨O‚"_em¢;6_$"'>¤}_ÖVjß_Ï Ä_V»Z3o…y9xïovo}×—º\?'>)ßocm–dûoŒjÿòfzOÓjn‚"Z_¦^>zµe1OË…züÇvózŒjMÿ†:ŠkÓjŠ‚"÷?¦^ZŠÑe®Ë¡ŠŸã†š3ŸŒjÛÿ*–Vš‡ŸÓj¦Ÿ‚"è/¦^všíŸe’˽š4¯‚"?¦^È3¯Œ§¹ª–¯ŒjjF¦rªê¯Ój ¿‚"-¿¦^ÙªP¿”b½oËz—¿b¶Žº²¿Œj)/©¶ÕºÏÓj%Ï‚"ÊŸ¦^õºlÏ”b/oˆn<ʳÏ~ƪÊÎÏŒjŒ?”b̈n>yùÏ ß@Ò\ߌjïO‚"/Ÿ¦^ÚÏßáÖ ï„ß$ïCåêßÓjAß‚"K¯¦^½š€Žï æÌê©ïÓjïJ2®¿¦^zÿ.öZú7ÿÓj o.òÊÏa yûªÿ.ò‡ÿÓþ{Úñÿ.òùïÓþ:ê8Jv SÓjRo.òkïÓþ– Æ.òIÏÓþÈ -óg¿ÓþÙ©Se’oc)6'.òƒÏÓþê9áó *ýÕC;/æßÑ_Ÿ.ò”/Óþ@*·/É&õ*Ò/Õ¯.òM/Óþ:E?ò13¿Óþ"i‹?7Ê:§?ÕÞ¿ž2£l]é;O,FXJ5OÕGïž2CNxJ¨OºFæJÃOÕÕïž2OCNZ6_HVtZQ_Õcÿž2_CN”ZÄ_ÖVjß_Õž2…OCN"jRodfjmoÕ›ž2÷?CN°j àoòfzûo¨y5)/ž2"?CN6‰mw¬z‰azp/ž2Î/CNÌzü†:Šazþ/ž2ÙCNZŠŠœ†È{207¤ÿ‰ñŽ¡•š ›èŽ7ŸazÓ?Å‘4KCN ·ÿ€ÑқƞgEŸW•¢?¿¼]Ÿ¢–Κ9¯Kªe¯0¢½oG­é:d¯v¯jš¯aO¾¦êª¿az:¿0¢/oÕ®Qº¿¢’ïÍ{«È¿Ú¶Êã¿KªïO0¢¡_Õ®:éÇ¿ ÏÜDÏ}_hÆ”ÊÅÏazVÏ@¢’˜¿ñ¾&ÊäÏ.‘15¯Õ®ûÊ+ß=ÖiÚßKª o„Ö°ÚáßazrßËßBßG®™o¢’Ýßñ¾ÐÚŽï„Òß¿G­ëGï æÌêðïKª'„ÒkïþîQºÿ.ÿ‰ßþîµuö¡úÒÿazï„ÒþîÊ8¢’$ïñ¾3ùðÿ½ šúŸ„Ò–þîûÊØ¯þîן„Òßþî"iSeš¶úó¯$& /ú°iáó('l/~/%D/azÕ²ñ¾Õè/¢’@/ñ¾c*/?A6m:J?azcÿ¢’/ñ¾¨z½?Ï6û:Ø?õºÆ¢’xñ¾ÌyJBfO¯§ÑlŸQþ]¿ÐOϺFüJæOÕJ¹ßºBbOÑNZL_^VŠZg_€ÕJªÿ§Ò)_Õ®·_G­6“_ìV.jo*jÚ_ºB’OÑNªZ~of¼j™oÕJ¡/×oÅ/ÑNv?2b(OÑNÜjSev‘znÕJO2b¾&n±záóvþ€2÷ š2úK‹[o¤Og†Ý K‹ñ_œg†NiK‹âOãg†”'I¿O*Ÿg†ZLŠc_qŸg†ªZjG­‘O·Ÿ§w0&n&ÉÏ×b‹ÐÙR«éo¯'ªWª•¯öšš¹¯øòž€(Io‘¯&n`¯G¿ÐÙ3KO¨»º®àŸ£¯Š¿©µâ¿ƒÊ ϦŸ›Þ›MÏ_Ÿ0›ÞŸð¿9Ô78¦ÏÜ378ÉÏ6ì80­¿ñÆ3Úß/Ú;ÏñÂ_ÏÞSڃߕÖÁÚžß/Ú‚ÏñÂ`ßÞáÚï#æOï8Ð÷aé‡èxî¿ÛÏ—æøVã¾ïˆ/Ú)/ñÁ9Þ¿Þoé3YYûkíŸâ2ÿÐï)öUú“ÿ/Ù3|¿›â˯+Ýæëÿ·ÿÛþâÉÿw§0‰ ¸ •/Ú_)òºïÝ»ûzF#ßú‰ï›âŠØ aÿ+Ý2<ß›âѸ(Û4(b*?//Ú7o)òW1çé#/Ã'ð*Í/*Êß›âå‚*²/)ò‘1:@?™6Å:¢?*XïR6~:ö?/Ú^ÿ›âôï,J\Oà?sO.Á›âò?SÚ£O)ò9O1å:êOüF(ZL_/ÚìÿCVoZ _*k/›â?áÚ¿_Ñ_/.‡?ô"/oêMo)òqo1ÖZ”o¦fÒjöo/ÚOífzJ*1_ô"s. êi{œ_.Ûo9†*çê÷ ´ …)òã_1‚*¶È†ôŠÑ/Ú–)òÇO1,JDŸV–‚š_Ÿ5ù/)ò_1­èГíŸþ¥ü# Mesh Ÿ"Circàðm¥1X0W€¡­ç2072·¸ 1Ÿè20õÏ·Îä7z©08òo$¼U«È/„ÁªÑ—„¡WªxVz¯¯ª¿åªÒ–Áª7ĹRØ…¤n¿¿Ÿ²•¯§®áס°¾¿Ð¿›¶Ï¯á®7’ j¿-Ï›¶kÈ †ª‹¿«Ä韧­8á®D‹–Áª6,¹Ž/ü¾6f€O»òª¯á®"v»kÉ6ÖÏá®!ŸŠÏ#¶ÉG_çÏÎ6³ß[ª/ïVÚNïl¢dª@ß§­7•ïfÎÛâ½ï«ªF¿ƒ¢,GÔÿÏêý†O»^'0Üïŧÿ¯á­9ùhÿìï>Ó…ÿlß B¿ïJê¨ê–»ñßá®ÿá®Z ÆÉÏê )fΫêÛïkZŸßóû䈫ª§H¹ïRÞèÃöïÿêC/b*„¡q¯ Í-/«ªªßŸ²›ÿÚþW¨¨Óù/±ÿƒ¢„Úþˆ©¤ÂV?;?fÎ2Ò†?ìʸ¯AËá®cßR¦O«ªMk/¥Ê‚?Úþ&Oa&•OåªR?èÎøÿ’+†,_ޤËOÚþkÊB_Ÿ²%?RÞ,º _”?#¶Y*±¹Eá_¢ïIæo«ª´OTV€ZUoìÊmOR¯ORÞ‹¢¼?è΄J/)oÍÆ˜oèÎu:[›¿‡n»oÎrßo§®dªv¸Êéu8€ìÊÛ6õrÞú`}ÿ # Objeÿct typesý á{ "banþÿ€s", "diÿng" } # ý0ù‚cherriñeœ8 û€icecïream‘popx “O°û€oran¿€ú>™3ù‚sweetò=š4å‰ö„-862¸€-434ÒYPYPLÉ’"Bÿ„‹“3MáÇ-32e!Ÿ¯š.001¼›33ÐPÏŸá¡2òœ_¯á3¼“6;75µ€-29–!;¯Šá4^«8ÍÑq¯á5¢”¬2=@§¯á6¼“5C54Ipj¯è¯ì’7¼hf¡¿á8º30FñtI¿á9¼“399=@° °üQ¿áœ10¢¼4î@µ¿Ç½ñ”¨¶P{ñ”@qŒba@p‚BÅ8Oa-‘`€_¸wÆ78ïÁC17›4âP{“¤7sA‡-18DP{ɤ7ÆÔs82ZÖ66`%Ñ{Yr5´64“‘180{ºÌ‹k³žàF­‚79I_ü»Õ2× BƒŽ#&Ÿ8šòÔàmòTŸ0fŸ%ç)ÐA‚79ꞟn[å215¹Á17¿ÄØÈŸn›]£21„“71`´ ¯ÃåîA‚59H,@¯øå38 ƒ6¶_u¯,ö39-¡”Ðkä ¯n›5³­A‚68_⯗õA4i°¿¿t•¡³4ž06³ÂŸN¿ÿö77Õs´u¿‡¾67ÍÑæ¦º¿Ài&4Û¿í¿“²ÝS56`†"¥°š¯&ÏÓ56&¤Ñ5Ü\Ï5@S170E†ÏŠ»/ó72Áð¬¹Ï‡¾dô2’aàµÏ0ýϨÚpÙA15â%ß4‡¾Íô3äÃ55jßÀ%4@ÕrŒßžßE'74a4]£Õßz&10xR424r¿ ï±%N•22ä6ï¦ÛcqðÞdïìvï798­425(¨¿®ïS59P#2-¯â6j@J^á ÿ£Þðd9 ”3¦<ÿNÿö58Á‘P4œïƒÿ+F8ØBí"ß ¹ÿaF82½"2°Þÿðÿ˜E7Ï¡!Çó…ÃÑ0ì;ÿ[V24;±›p4úß‘05KdãÀQ"pŒ%¼¿û‚d255ó#°ìþ*@¹d256C9@Ï5*@ðd¡@•29æQ^¼þ÷426Ðá,0›ïn£.06-D62г73¶Û06oU24²47~/ì¦U}À²*21ÉI/06ÝU1A3)37/ìe0 ‚¢/´/êKe0ÕóŠŸì/LëÀ£88¼ÒÈ-<ÿ"foregro÷undP´ExitÍt79•ã7C@?ÿIcecream dEf"30 ±†?˜;lW92=A¢p30ã¼?Î;‚92ÿé?û?Ö3…2`A³?3O×2d37pñ`‡ÜôaOÎ;Kd36c6¦ô˜OÎ;¿ ƒ7#ÏOÎ;Joòæ‡_Î;ðc111QÒ9Á”=_Î;~Ó1UÐgRþ¡p_Ë=]t÷`ñ’4‚?´_’vƇÓa1[ß_»[è“64Ôsã42m_!o…644€…’Æ FoXo7„ Ãb5[Ool…l B”¶o»[n912A29Þaèo¸^J91‘ApSظ^71Š28ÀIÄY»[—ôu€ž!28ÀùÔÎ:{”pN’29¡2SÓ°•@2Êá2a9ÕñûÖ~936ŠD0pô5Ù{”$35ÁC”‚iÖ~E45–ƒ‘£Ù{¸E51â3ñ×Ö~197CÂÂÕŸÙ{J¹×²54 ŸTŸ*µ-2`°^£Š‹Ÿ`µ¥A6É£&¡³ŸË=—´7KsÐB`èŸúŸÍ´8”â21Q0yŸ.¯Å9j²2R¯d¯9Ä8f"ÝÔ˜¯ˆnÅéÀùB6#O̯£Æ1Ä ’ã2°Ÿ¿ÚÅ14`‘n±o9¿Õ13f"9ðøo¿FÕ3æÂ38“¿¥¿|Õ329åÃHÏ¿Î:³Ô3Gw`þáÏlÎ!òÓ35ñ¯$GÏå5í@1Q2À|ÏSæ50›Â#§ÏËË#XœR3ôÝÏË3Bà’3ÌßÎ s6´q3þ¿Tß)ö656²a2§Ñ|ßÎ66¹r!1N °ßÂß–ô6› ›ÂiñèßË=Ìô8CbiPCß-ï8­1Ô!Sï0î983:’Bˆï0À+ÀŒAA½ï0îË#56…0ÂB7qòï0î35Ã64‹DÉ¿7ÿ57àÁˆPïmÿH569b’64Ï¢ÿ~44Kr£32eØÿµ4w’-a3oþÿî44~¢#32xŸD#&4ãbùð06$oK C36’±‡D¢H”#3¥ÐUAÀBØ HË#37 2˯ß5ˆ@æ26 ŸR66-P€ÿOˆì&S@ªb6°jϾ# Ÿ“22›R37@ôVï³àB7Y5åß+/07çt9Qð€UAÐRR/d.Ü5Ðàb0 ­˜/¸p­%Í8÷±À/4d.Œ„9Ú88Õ?»07D930ñq3!8  #include #include "../include/anim.h" #include "../include/game.h" #include "../include/level.h" float LastSpeedStore = 0, LastSpeed; int OnLand; BITMAP *GetCurrentBitmap(struct Animation *Anim) { LastSpeedStore = LastSpeed; if (Anim->SkateVoice >= 0) { if (LastSpeed >= 1.0f && OnLand) voice_set_volume(Anim->SkateVoice, 256 - (256 / LastSpeed)); else voice_set_volume(Anim->SkateVoice, 0); } return Anim->CBitmap; } void AdvanceAnimation(struct Animation *Anim, float Distance, int OnPlatform) { Anim->TimeCount += Distance; OnLand = OnPlatform; if (!OnPlatform) { Anim->CBitmap = Anim->Fast; } else { /* obtain speed */ LastSpeed = Distance = fabs(Distance); Anim->CBitmap = Anim->Fast; if ((Distance < 12.0f) && (LastSpeedStore < 12.0f)) Anim->CBitmap = Anim->Medium; if ((Distance < 5.0f) && (LastSpeedStore < 5.0f)) Anim->CBitmap = (KeyFlags & (KEYFLAG_LEFT | KEYFLAG_RIGHT)) ? Anim-> Animation[((unsigned int)Anim->TimeCount) % 3] : Anim->Slow; } } struct Animation *SeedPlayerAnimation(void) { struct Animation *Anim = (struct Animation *)malloc(sizeof(struct Animation)); SAMPLE *Sound; Anim->Animation[0] = ObtainBitmap("skater2"); Anim->Animation[1] = ObtainBitmap("skater3"); Anim->Animation[2] = ObtainBitmap("skater4"); Anim->CBitmap = Anim->Still = ObtainBitmap("skater1"); Anim->Slow = ObtainBitmap("skateslow"); Anim->Medium = ObtainBitmap("skatemed"); Anim->Fast = ObtainBitmap("skatefast"); if ((Sound = ObtainSample("skating"))) { Anim->SkateVoice = allocate_voice(Sound); voice_set_playmode(Anim->SkateVoice, PLAYMODE_BIDIR | PLAYMODE_LOOP); } else Anim->SkateVoice = -1; return Anim; } void FreePlayerAnimation(struct Animation *Anim) { int c; if (Anim) { c = 3; while (c--) destroy_bitmap(Anim->Animation[c]); destroy_bitmap(Anim->Still); destroy_bitmap(Anim->Slow); destroy_bitmap(Anim->Medium); destroy_bitmap(Anim->Fast); if (Anim->SkateVoice >= 0) { voice_stop(Anim->SkateVoice); release_voice(Anim->SkateVoice); } free(Anim); } } void PauseAnimation(struct Animation *Anim) { if (Anim->SkateVoice >= 0) voice_stop(Anim->SkateVoice); } void UnpauseAnimation(struct Animation *Anim) { if (Anim->SkateVoice >= 0) voice_start(Anim->SkateVoice); } /* BITMAP *GetCurrentBitmap(struct Animation *Anim) { return Anim->bmps[((int)Anim->TimeCount)&3]; } void AdvanceAnimation(struct Animation *Anim, float Distance, int OnPlatform, int Forward) { Anim->TimeCount += Distance*0.125f; } struct Animation *SeedPlayerAnimation(void) { struct Animation *Anim = (struct Animation *)malloc(sizeof(struct Animation)); Anim->bmps = (BITMAP **)malloc(sizeof(BITMAP *)*4); Anim->bmps[0] = load_bitmap("man-frame1.bmp", NULL); Anim->bmps[1] = load_bitmap("man-frame2.bmp", NULL); Anim->bmps[2] = load_bitmap("man-frame3.bmp", NULL); Anim->bmps[3] = load_bitmap("man-frame4.bmp", NULL); return Anim; } void FreePlayerAnimation(struct Animation *Anim) { if(Anim) { if(Anim->bmps) { destroy_bitmap(Anim->bmps[0]); destroy_bitmap(Anim->bmps[1]); destroy_bitmap(Anim->bmps[2]); destroy_bitmap(Anim->bmps[3]); free((void *)Anim->bmps); } free(Anim); } } */ allegro4.4-4.4.2/demos/skater/source/backscrl.c000066400000000000000000000023341173507505700212400ustar00rootroot00000000000000#include #include #include "../include/demodata.h" #include "../include/global.h" static int offx; static int offy; static float current_time; static float dt; static BITMAP *tile; void draw_background(BITMAP *canvas) { int dx = tile->w; int dy = tile->h; int x, y; while (offx > 0) offx -= dx; while (offy > 0) offy -= dy; for (y = offy; y < canvas->h; y += dy) { for (x = offx; x < canvas->w; x += dx) { blit(tile, canvas, 0, 0, x, y, dx, dy); } } } void init_background(void) { offx = 0; offy = 0; current_time = 0.0f; dt = 1.0f / (float)logic_framerate; tile = demo_data[DEMO_BMP_BACK].dat; } void update_background(void) { /* increase time */ current_time += dt; /* calculate new offset from current current_time with some weird trig functions change the constants arbitrarily and/or add sin/cos components to get more complex animations */ offx = (int)(1.4f * tile->w * sin(0.9f * current_time + 0.2f) + 0.3f * tile->w * cos(1.5f * current_time - 0.4f)); offy = (int)(0.6f * tile->h * sin(1.2f * current_time - 0.7f) - 1.2f * tile->h * cos(0.2f * current_time + 1.1f)); } allegro4.4-4.4.2/demos/skater/source/credits.c000066400000000000000000000277041173507505700211210ustar00rootroot00000000000000#include #include #include #include #include "../include/credits.h" #include "../include/global.h" /* for parsing readme.txt */ typedef struct TEXT_LIST { char *text; struct TEXT_LIST *next; } TEXT_LIST; typedef struct README_SECTION { TEXT_LIST *head; TEXT_LIST *tail; char *flat; char *desc; } README_SECTION; /* for parsing thanks._tx and the various source files */ typedef struct CREDIT_NAME { char *name; char *text; struct CREDIT_NAME *next; } CREDIT_NAME; static CREDIT_NAME *credits = NULL; /* text messages (loaded from readme.txt) */ static char *title_text; static int title_size; static int title_alloced; static char *end_text; /* for the text scroller */ static int text_char; static int text_width; static int text_pix; static int text_scroll; /* for the credits display */ static CREDIT_NAME *cred; static int credit_width; static int credit_scroll; static int credit_age; static int credit_speed; static int credit_skip; /* helper to find a file or directory in the Allegro tree */ static int find_relative_path(char buf[], size_t bufsize, const char *name) { static const char *locations[] = { "", "../", "../../", /* Allegro root, no build directory */ "../../../", /* Allegro root, with build directory */ "../../../../", /* Allegro root, MSVC build configuration directory */ NULL }; char exe[256]; char dir[256]; int i; get_executable_name(exe, sizeof(exe)); for (i = 0; locations[i] != NULL; i++) { replace_filename(dir, exe, locations[i], sizeof(dir)); append_filename(buf, dir, name, bufsize); if (file_exists(buf, FA_ALL, NULL)) { return 1; } } return 0; } /* helper to open readme.txt and thanks._tx */ static PACKFILE *open_relative_file(char buf[], size_t size, const char *name) { if (find_relative_path(buf, size, name)) return pack_fopen(buf, F_READ); return NULL; } /* formats a list of TEXT_LIST structure into a single string */ char *format_text(TEXT_LIST * head, char *eol, char *gap) { TEXT_LIST *l; int size = 0; char *s; l = head; while (l) { if (l->text[0]) size += strlen(l->text) + strlen(eol); else size += strlen(gap) + strlen(eol); l = l->next; } s = malloc(size + 1); s[0] = 0; l = head; while (l) { if (l->text[0]) strcat(s, l->text); else strcat(s, gap); strcat(s, eol); l = l->next; } return s; } /* loads the scroller message from readme.txt */ void load_text(void) { README_SECTION sect[] = { {NULL, NULL, NULL, "Introduction"}, {NULL, NULL, NULL, "Features"}, {NULL, NULL, NULL, "Copyright"}, {NULL, NULL, NULL, "Contact info"} }; #define SPLITTER " " static char intro_msg[] = "Welcome to the Allegro demonstration game, by Miran Amon, Nick Davies, Elias, Thomas Harte & Jakub Wasilewski." SPLITTER "Help skateboarding Ted collect various shop items - see \"About\" for more information!" SPLITTER; static char splitter[] = SPLITTER; static char marker[] = "--------"; char buf[256]; README_SECTION *sec = NULL; TEXT_LIST *l, *p; PACKFILE *f; int inblank = TRUE; char *s; int i; f = open_relative_file(buf, sizeof(buf), "docs/txt/readme.txt"); if (!f) { title_text = "Can't find readme.txt, so this scroller is empty. "; title_size = strlen(title_text); title_alloced = FALSE; end_text = NULL; return; } while (pack_fgets(buf, sizeof(buf) - 1, f) != 0) { if (buf[0] == '=') { s = strchr(buf, ' '); if (s) { for (i = strlen(s) - 1; (uisspace(s[i])) || (s[i] == '='); i--) s[i] = 0; s++; sec = NULL; inblank = TRUE; for (i = 0; i < (int)(sizeof(sect) / sizeof(sect[0])); i++) { if (stricmp(s, sect[i].desc) == 0) { sec = §[i]; break; } } } } else if (sec) { s = buf; while ((*s) && (uisspace(*s))) s++; for (i = strlen(s) - 1; (i >= 0) && (uisspace(s[i])); i--) s[i] = 0; if ((s[0]) || (!inblank)) { l = malloc(sizeof(TEXT_LIST)); l->next = NULL; l->text = malloc(strlen(s) + 1); strcpy(l->text, s); if (sec->tail) sec->tail->next = l; else sec->head = l; sec->tail = l; } inblank = (s[0] == 0); } } pack_fclose(f); if (sect[2].head) end_text = format_text(sect[2].head, "\n", ""); else end_text = NULL; title_size = strlen(intro_msg); for (i = 0; i < (int)(sizeof(sect) / sizeof(sect[0])); i++) { if (sect[i].head) { sect[i].flat = format_text(sect[i].head, " ", splitter); title_size += strlen(sect[i].flat) + strlen(sect[i].desc) + strlen(splitter) + strlen(marker) * 2 + 2; } } title_text = malloc(title_size + 1); title_alloced = TRUE; strcpy(title_text, intro_msg); for (i = 0; i < (int)(sizeof(sect) / sizeof(sect[0])); i++) { if (sect[i].flat) { strcat(title_text, marker); strcat(title_text, " "); strcat(title_text, sect[i].desc); strcat(title_text, " "); strcat(title_text, marker); strcat(title_text, splitter); strcat(title_text, sect[i].flat); } } for (i = 0; i < (int)(sizeof(sect) / sizeof(sect[0])); i++) { l = sect[i].head; while (l) { free(l->text); p = l; l = l->next; free(p); } if (sect[i].flat) free(sect[i].flat); } } /* sorts a list of credit strings */ void sort_credit_list(void) { CREDIT_NAME **prev, *p; int n, done; do { done = TRUE; prev = &credits; p = credits; while ((p) && (p->next)) { n = 0; if (n == 0) { n = stricmp(p->name, p->next->name); } if (n > 0) { *prev = p->next; p->next = p->next->next; (*prev)->next = p; p = *prev; done = FALSE; } prev = &p->next; p = p->next; } } while (!done); } /* reads credit info from various places */ void load_credits(void) { char buf[256], *p, *p2; CREDIT_NAME *c = NULL; PACKFILE *f; /* parse thanks._tx */ f = open_relative_file(buf, sizeof(buf), "docs/src/thanks._tx"); if (!f) return; while (pack_fgets(buf, sizeof(buf) - 1, f) != 0) { if (stricmp(buf, "Thanks!") == 0) break; while ((p = strstr(buf, "<")) != NULL) { *p = '<'; memmove(p + 1, p + 3, strlen(p + 2)); } while ((p = strstr(buf, ">")) != NULL) { *p = '>'; memmove(p + 1, p + 3, strlen(p + 2)); } p = buf; while ((*p) && (uisspace(*p))) p++; p2 = p; while ((*p2) && ((!uisspace(*p2)) || (*(p2 + 1) != '('))) p2++; if ((strncmp(p2, " (", 9) == 0) || (strncmp(p2, " (email", 7) == 0)) { *p2 = 0; c = malloc(sizeof(CREDIT_NAME)); c->name = malloc(strlen(p) + 1); strcpy(c->name, p); c->text = NULL; c->next = credits; credits = c; } else if (*p) { if (c) { p2 = p + strlen(p) - 1; while ((p2 > p) && (uisspace(*p2))) *(p2--) = 0; if (c->text) { c->text = realloc(c->text, strlen(c->text) + strlen(p) + 2); strcat(c->text, " "); strcat(c->text, p); } else { c->text = malloc(strlen(p) + 1); strcpy(c->text, p); } } } else c = NULL; } pack_fclose(f); /* sort the lists */ sort_credit_list(); } CREDIT_NAME *next_credit(CREDIT_NAME * cred) { int max, i; if (!cred) { cred = credits; if (!cred) return NULL; } max = rand() % 1000; for (i = 0; i < max; i++) { if (cred->next) { cred = cred->next; } else { cred = credits; } } return cred; } void init_credits(void) { /* for the text scroller */ text_char = 0xFFFF; text_width = 0; text_pix = 0; text_scroll = 0; /* for the credits display */ cred = NULL; credit_width = 0; credit_scroll = 0; credit_age = 0; credit_speed = 32; credit_skip = 1; load_text(); load_credits(); } void update_credits(void) { /* move the scroller */ text_scroll++; /* update the credits position */ if (credit_scroll <= 0) { cred = next_credit(cred); if (cred) { credit_width = text_length(demo_font, cred->name) + 24; if (cred->text) { credit_scroll = text_length(plain_font, cred->text) + SCREEN_W - credit_width; } else { credit_scroll = 256; } credit_age = 0; } } else { credit_scroll--; credit_age++; } } void draw_credits(BITMAP *canvas) { int c, c2; int y2; int col_back, col_font; /* for the text scroller */ char buf[2] = " "; /* for the credits display */ char cbuf[2] = " "; char *p; col_back = makecol(222, 222, 222); col_font = makecol(96, 96, 96); /* draw the text scroller */ y2 = SCREEN_H - text_height(demo_font); text_pix = -(text_scroll / 1); hline(canvas, 0, y2 - 2, SCREEN_W - 1, col_font); hline(canvas, 0, y2 - 1, SCREEN_W - 1, col_font); rectfill(canvas, 0, y2, SCREEN_W - 1, SCREEN_H - 1, col_back); for (text_char = 0; text_char < title_size; text_char++) { buf[0] = title_text[text_char]; c = text_length(demo_font, buf); if (text_pix + c > 0) { demo_textout(canvas, demo_font, buf, text_pix, y2, col_font, -1); } text_pix += c; if (text_pix >= SCREEN_W) { break; } } /* draw author name/desc credits */ y2 = text_height(demo_font); rectfill(canvas, 0, 0, SCREEN_W - 1, y2, col_back); hline(canvas, 0, y2 + 1, SCREEN_W - 1, col_font); hline(canvas, 0, y2 + 2, SCREEN_W - 1, col_font); y2 = (text_height(demo_font) - 8) / 2; if (cred && cred->text) { c = credit_scroll; p = cred->text; c2 = strlen(p); if (c > 0) { if (c2 > c / 8) { p += c2 - c / 8; c &= 7; } else { c -= c2 * 8; } c += credit_width; while ((*p) && (c < SCREEN_W - 32)) { if (c < credit_width + 96) { c2 = 128 + (c - credit_width - 32) * 127 / 64; } else if (c > SCREEN_W - 96) { c2 = 128 + (SCREEN_W - 32 - c) * 127 / 64; } else { c2 = 255; } if ((c2 > 128) && (c2 <= 255)) { c2 = 255 - c2 + 64; cbuf[0] = *p; demo_textout(canvas, plain_font, cbuf, c, y2, makecol(c2, c2, c2), -1); } p++; c += 8; } } } c = 4; if (credit_age < 100) { c -= (100 - credit_age) * (100 - credit_age) * credit_width / 10000; } if (credit_scroll < 150) { c += (150 - credit_scroll) * (150 - credit_scroll) * SCREEN_W / 22500; } if (cred) demo_textprintf(canvas, demo_font, c, 0, col_font, -1, "%s:", cred->name); else demo_textprintf(canvas, demo_font, 0, 0, col_font, -1, "thanks._tx not found!"); } void destroy_credits(void) { if ((title_text) && (title_alloced)) { free(title_text); } while (credits) { cred = credits; credits = cred->next; if (cred->name) { free(cred->name); } if (cred->text) { free(cred->text); } free(cred); } } allegro4.4-4.4.2/demos/skater/source/dblbuf.c000066400000000000000000000022361173507505700207130ustar00rootroot00000000000000#include #include "../include/dblbuf.h" /* double_buffer.h */ #include "../include/defines.h" #include "../include/global.h" /***************************************************************************** * Double buffering module * *****************************************************************************/ static BITMAP *double_buffer = NULL; static void destroy(void) { if (double_buffer) { destroy_bitmap(double_buffer); double_buffer = NULL; } } static int create(void) { destroy(); double_buffer = create_bitmap(SCREEN_W, SCREEN_H); if (!double_buffer) { return DEMO_ERROR_MEMORY; } else { clear_to_color(double_buffer, makecol(0, 0, 0)); } return DEMO_OK; } static void draw(void) { if (use_vsync) { vsync(); } blit(double_buffer, screen, 0, 0, 0, 0, SCREEN_W, SCREEN_H); } static BITMAP *get_canvas(void) { return double_buffer; } void select_double_buffer(DEMO_SCREEN_UPDATE_DRIVER * driver) { driver->create = create; driver->destroy = destroy; driver->draw = draw; driver->get_canvas = get_canvas; } allegro4.4-4.4.2/demos/skater/source/fps.c000066400000000000000000000023251173507505700202440ustar00rootroot00000000000000/* Module for measuring FPS for Allegro games - implementation. Written by Miran Amon. */ #include #include "../include/fps.h" #include "../include/global.h" FPS *create_fps(int fps) { int i; FPS *ret = malloc(sizeof(FPS)); ret->nSamples = fps; ret->samples = malloc(fps * sizeof(int)); for (i = 0; i < fps; i++) { ret->samples[i] = 1; } ret->curSample = 0; ret->frameCounter = 0; ret->framesPerSecond = fps; return ret; } void destroy_fps(FPS * fps) { free(fps->samples); fps->samples = NULL; fps->nSamples = 0; fps->frameCounter = 0; free(fps); fps = NULL; } void fps_tick(FPS * fps) { fps->curSample++; fps->curSample %= fps->nSamples; fps->framesPerSecond -= fps->samples[fps->curSample]; fps->framesPerSecond += fps->frameCounter; fps->samples[fps->curSample] = fps->frameCounter; fps->frameCounter = 0; } void fps_frame(FPS * fps) { ++(fps->frameCounter); } int get_fps(FPS * fps) { return fps->framesPerSecond; } void draw_fps(FPS * fps, BITMAP *bmp, FONT *font, int x, int y, int fg, char *format) { demo_textprintf(bmp, plain_font, x, y, fg, makecol(0, 0, 0), format, get_fps(fps)); } allegro4.4-4.4.2/demos/skater/source/framewk.c000066400000000000000000000320021173507505700211030ustar00rootroot00000000000000#include #ifdef DEMO_USE_ALLEGRO_GL #include #endif #include "../include/credits.h" #include "../include/fps.h" #include "../include/framewk.h" #include "../include/game.h" #include "../include/gamepad.h" #include "../include/global.h" #include "../include/gmestate.h" #include "../include/keyboard.h" #include "../include/menus.h" #include "../include/scrshot.h" #include "../include/transitn.h" #include "../include/updtedvr.h" /* The callback function for the close icon on platforms that support it. The value of the close variable is regularly tested in the main loop to determine if the user clicked the close icon. */ static int closed = FALSE; static void closehook(void) { closed = TRUE; } /* name of the configuration file for storing demo-specific settings. */ #define DEMO_CFG "demo.cfg" /* Timer callback. Installed with the frequency defined in the framework configuration file. The value of the timer variable is regularly tested in the main loop to determine when to run a frame of game logic. */ static volatile int timer = 0; static void timer_f(void) { timer++; } END_OF_STATIC_FUNCTION(timer_f); /* Screenshot module; for taking screenshots. */ static SCREENSHOT *screenshot = NULL; /* Status of the F12 key; used for taking screenshots. */ static int F12 = 0; /* Framerate counter module. */ static FPS *fps = NULL; /* Static array of gamestates. Only state_count states are actually initialized. The current_state variable points to the currently active state and last_state points to the previous state. This required to do smooth transitions between states. */ static GAMESTATE state[DEMO_MAX_GAMESTATES]; static int current_state = 0, last_state; static int state_count = 0; /* Module for performing smooth state transition animations. */ static TRANSITION *transition = NULL; int init_framework(void) { int error = DEMO_OK; int c; /* Attempt to initialize Allegro. */ if (allegro_init() != 0) { return DEMO_ERROR_ALLEGRO; } #ifdef DEMO_USE_ALLEGRO_GL /* Attempt to initialize AllegroGL. */ if (install_allegro_gl() != 0) { return DEMO_ERROR_ALLEGRO; } #endif /* Construct aboslute path for the configuration file. */ get_executable_name(config_path, DEMO_PATH_LENGTH); replace_filename(config_path, config_path, DEMO_CFG, DEMO_PATH_LENGTH); /* Construct aboslute path for the datafile containing game menu data. */ get_executable_name(data_path, DEMO_PATH_LENGTH); replace_filename(data_path, data_path, "demo.dat#menu.dat", DEMO_PATH_LENGTH); /* Read configuration file. */ read_config(config_path); /* Set window title and install close icon callback on platforms that support this. */ set_window_title("Allegro Demo Game"); set_close_button_callback(&closehook); /* Make sure the game will continue to run in the background when the user tabs away. Note: this should be made configurable! */ set_display_switch_mode(SWITCH_BACKGROUND); /* Install the Allegro sound and music submodule. Note that this function failing is not considered a fatal error so no error checking is required. If this call fails, the game will still run, but with no sound or music (or both). */ install_sound(DIGI_AUTODETECT, MIDI_AUTODETECT, NULL); set_volume(sound_volume * 25, music_volume * 25); /* Attempt to set the gfx mode. */ if ((error = change_gfx_mode()) != DEMO_OK) { set_gfx_mode(GFX_TEXT, 0, 0, 0, 0); allegro_message("Error: %s\n", demo_error(error)); return error; } /* Attempt to install the Allegro keyboard submodule. */ if (install_keyboard() != 0) { set_gfx_mode(GFX_TEXT, 0, 0, 0, 0); allegro_message("Error installing keyboard: %s\n", demo_error(DEMO_ERROR_ALLEGRO)); return DEMO_ERROR_ALLEGRO; } /* Attempt to install the joystick submodule. Note: no need to check the return value as joystick isn't really required! */ install_joystick(JOY_TYPE_AUTODETECT); /* Install the timer submodule and install the timer interrupt callback. */ install_timer(); LOCK_VARIABLE(timer); LOCK_FUNCTION(timer_f); install_int_ex(timer_f, BPS_TO_TIMER(logic_framerate)); /* Seed the random number generator. */ srand((unsigned)time(NULL)); /* Create the screenshot module. Screenshots will be saved in TGA format and named SHOTxxxx.TGA. */ screenshot = create_screenshot("SHOT", "TGA"); /* Create the frame rate counter module. */ fps = create_fps(logic_framerate); /* Initialize the game state array. */ c = DEMO_MAX_GAMESTATES; while (c--) { state[c].deinit = state[c].init = NULL; state[c].id = state[c].update = NULL; state[c].draw = NULL; } /* Create all the game states/screens/pages. New screens may be added here as required. */ create_main_menu(&state[0]); create_options_menu(&state[1]); create_gfx_menu(&state[2]); create_sound_menu(&state[3]); create_misc_menu(&state[4]); create_controls_menu(&state[5]); create_intro(&state[6]); create_about_menu(&state[7]); create_new_game(&state[8]); create_continue_game(&state[9]); create_success_menu(&state[10]); state_count = 11; /* demo game has 11 screens */ current_state = 6; /* the game will start with screen #7 - the intro */ /* Create the keyboard and gamepad controller modules. */ controller[DEMO_CONTROLLER_KEYBOARD] = create_keyboard_controller(config_path); controller[DEMO_CONTROLLER_GAMEPAD] = create_gamepad_controller(config_path); /* Initialize the module for displaying credits. */ init_credits(); return error; } /* Draws the current state or transition animation to the backbuffer and flips the page. Parameters: none Returns: none */ void draw_framework(void) { /* Before drawing to the backbuffer we must acquire it - just in case. */ acquire_bitmap(update_driver.get_canvas()); /* Draw either the current state or the transition animation if we're in between states. */ if (transition) { draw_transition(update_driver.get_canvas(), transition); } else { /* DEMO_STATE_EXIT is a special case and doesn't eqate to and actual state that can be drawn. */ if (current_state != DEMO_STATE_EXIT) { state[current_state].draw(update_driver.get_canvas()); } } /* Draw the current framerate if required. */ if (display_framerate) { draw_fps(fps, update_driver.get_canvas(), font, 0, 0, makecol(255, 255, 255), "%d FPS"); } /* Release the previously acquired canvas bitmap (backbuffer). */ release_bitmap(update_driver.get_canvas()); /* Finally make the update driver flip the page so it becomes visible on the screen, however it may go about actually doing it. */ update_driver.draw(); } void run_framework(void) { int done = FALSE; /* will become TRUE when we're ready to close */ int need_to_redraw = 1; /* do we need to draw the next frame? */ int next_state = current_state; int i; /* Initialize the first game screen. */ state[current_state].init(); /* Create a transition animation so that the first screen doesn't just pop up but comes in a nice animation that lasts 0.3 seconds. */ transition = create_transition(NULL, &state[current_state], 0.3f); /* Initialize the timer variable - just in case. */ timer = 0; /* Do the main loop; until we're not done. */ while (!done) { /* Check if the timer has ticked. */ while (timer > 0) { --timer; /* See if the user pressed F12 to see if the user wants to take a screenshot. */ if (key[KEY_F12]) { /* See if the F12 key was already pressed before. */ if (F12 == 0) { /* The user just pressed F12 (it wasn't pressed before), so remember this and take a screenshot! */ F12 = 1; take_screenshot(screenshot, update_driver.get_canvas()); } } else { /* Remember for later that F12 is not pressed. */ F12 = 0; } /* Do one frame of logic. If we're in between states, then update the transition animation module, otherwise update the current game state. */ if (transition) { /* Advance the transition animation. If it returns non-zero, it means the animation finished playing. */ if (update_transition(transition) == 0) { /* Destroy the animation, we're done with it. */ destroy_transition(transition); transition = NULL; /* Complete the transition to the new state by deiniting the previous one. */ if (state[last_state].deinit) { state[last_state].deinit(); } /* Stop the main loop if there is no more game screens. */ if (current_state == DEMO_STATE_EXIT) { done = TRUE; break; } } } /* We're not in between states, so update the current one. */ else { /* Update the current state. It returns the ID of the next state. */ next_state = state[current_state].update(); /* Did the current state just close the game? */ if (next_state == DEMO_STATE_EXIT) { /* Create a transition so the game doesn't just close but instead goes out in a nice animation. */ transition = create_transition(&state[current_state], NULL, 0.3f); last_state = current_state; current_state = next_state; break; } /* If the next state is different then the current one, then start a transition. */ else if (next_state != state[current_state].id()) { last_state = current_state; /* Find the index of the next state in the state array. Note that ID of a state is not the same as its index in the array! */ for (i = 0; i < state_count; i++) { /* Did we find it? */ if (state[i].id() == next_state) { /* We found the new state. Initialize it and start the transition animation. */ state[i].init(); transition = create_transition(&state[current_state], &state[i], 0.3f); current_state = i; break; } } } } /* We just did one logic frame so we assume we will need to update the visuals to reflect the changes this logic frame made. */ need_to_redraw = 1; /* Let the framerate counter know that one logic frame was run. */ fps_tick(fps); } /* Make sure the game doesn't freeze in case the computer isn't fast enough to run the logic as fast as we want it to. Note that this will skip logic frames so all time in the game will be stretched. Note also that this is very unlikely to happen. */ while (timer > max_frame_skip) { fps_tick(fps); --timer; } /* In case a frame of logic has just been run or the user wants unlimited framerate, we must redraw the screen. */ if (need_to_redraw == 1 || limit_framerate == 0) { /* Actually do the drawing. */ draw_framework(); /* Make sure we don't draw too many times. */ need_to_redraw = 0; /* Let the framerate counter know that we just drew a frame. */ fps_frame(fps); } /* Check if the user pressed the close icon. */ done = done || closed; /* If power saving is enabled, let go of the CPU until we need it again. This is done by calling rest() and passing it 1. */ if (reduce_cpu_usage) { while (timer == 0) { rest(1); } } } } void shutdown_framework(void) { /* Uninstall the time callback function. */ remove_int(timer_f); /* Save the configuration settings. */ write_config(config_path); /* Destroy the screenshot module. */ destroy_screenshot(screenshot); /* Destroy the framerate counter module. */ destroy_fps(fps); /* Destroy controller modules. */ destroy_vcontroller(controller[DEMO_CONTROLLER_KEYBOARD], config_path); destroy_vcontroller(controller[DEMO_CONTROLLER_GAMEPAD], config_path); /* Destroy the game states/screens. */ destroy_game(); /* Get rid of all the game data. */ unload_data(); /* Destroy the credits module. */ destroy_credits(); /* Destroy the transition module. */ if (transition) { destroy_transition(transition); } /* Destroy the screen update driver. */ update_driver.destroy(); } allegro4.4-4.4.2/demos/skater/source/game_sk.c000066400000000000000000000341321173507505700210630ustar00rootroot00000000000000#include #include #include "../include/defines.h" #include "../include/game.h" #include "../include/global.h" #include "../include/menus.h" #include "../include/music.h" #include "../include/physics.h" #include "../include/virtctl.h" /* All variables relevant to player position and level / level status. Only thing of note is that PlayerPos is a 3 element array - it contains player position (in elements 0 and 1) and rotation (in element 2) */ int KeyFlags; int RequiredObjectsLeft, TotalObjectsLeft; float PlayerPos[3], PlayerVec[2]; float ScrollPos[2]; struct Animation *PlayerAnim = NULL; struct Level *Lvl = NULL; struct LevelState *LvlState = NULL; float LeftWindow = -120, RightWindow = 120; float Pusher = 0; #define PLAYER_STRENGTH 0.14f /* ID things, for GAMESTATE purposes. Note that two menu entries head this way - "new game" and "continue game", so we have to IDs */ static int _newid = DEMO_STATE_NEW_GAME; static int newid(void) { return _newid; } static int _continueid = DEMO_STATE_CONTINUE_GAME; static int continueid(void) { return _continueid; } int CurrentID; /* background stuff */ BITMAP *water; int WaterVoice = -1, WaterVoice2 = -1; SAMPLE *WaveNoise = NULL; BITMAP *cloud; fixed *TanTable = NULL; int CalibRes = 0; fixed TexX; float WaveY; DATAFILE *game_audio; struct { fixed x, y; } Clouds[8]; int CloudX; fixed Scale; char *load_game_resources(void) { int c; char AudioPath[DEMO_PATH_LENGTH]; get_executable_name(AudioPath, DEMO_PATH_LENGTH); replace_filename(AudioPath, AudioPath, "demo.dat#audio.dat", DEMO_PATH_LENGTH); game_audio = load_datafile(AudioPath); Scale = itofix(SCREEN_H) / 480; Lvl = LoadLevel("level.dat", 15); if (!Lvl) return GetLevelError(); ReturnState(Lvl, LvlState); PlayerAnim = SeedPlayerAnimation(); cloud = ObtainBitmap("cloud"); water = ObtainBitmap("water"); c = SCREEN_H << 2; TanTable = (fixed *) malloc(sizeof(fixed) * c); while (c--) TanTable[c] = ftofix(tan ((3.141592654f / 2.0f - atan2(0.75f * (((float)(c * 2) / (float)(SCREEN_H << 2)) - 1), 1) ))); WaveNoise = ObtainSample("wave"); return NULL; } void unload_game_resources(void) { if (game_audio) { unload_datafile(game_audio); game_audio = NULL; } FreePlayerAnimation(PlayerAnim); PlayerAnim = NULL; if (cloud) { destroy_bitmap(cloud); cloud = NULL; } if (water) { destroy_bitmap(water); water = NULL; } FreeState(LvlState); LvlState = BorrowState(Lvl); FreeLevel(Lvl); Lvl = NULL; if (TanTable) { free(TanTable); TanTable = NULL; } } void DeInit(void) { if (WaterVoice >= 0) { voice_stop(WaterVoice); deallocate_voice(WaterVoice); WaterVoice = -1; } if (WaterVoice2 >= 0) { voice_stop(WaterVoice2); deallocate_voice(WaterVoice2); WaterVoice2 = -1; } PauseAnimation(PlayerAnim); } void GenericInit(void) { int c; set_palette(demo_data[DEMO_GAME_PALETTE].dat); CloudX = 0; Clouds[0].x = Clouds[0].y = 0; for (c = 1; c < 8; c++) { Clouds[c].x = Clouds[c - 1].x + itofix(cloud->w + 8) + itofix(rand() / (RAND_MAX / 32)); Clouds[c].y = rand() / (RAND_MAX / (SCREEN_H >> 1)); } WaterVoice = allocate_voice(WaveNoise); voice_set_playmode(WaterVoice, PLAYMODE_BIDIR | PLAYMODE_LOOP); voice_set_volume(WaterVoice, 48); voice_start(WaterVoice); WaterVoice2 = allocate_voice(WaveNoise); voice_set_playmode(WaterVoice2, PLAYMODE_BIDIR | PLAYMODE_LOOP | PLAYMODE_BACKWARD); voice_set_volume(WaterVoice2, 64); voice_start(WaterVoice2); play_music(DEMO_MIDI_INGAME, TRUE); UnpauseAnimation(PlayerAnim); } void ContinueInit(void) { GenericInit(); CurrentID = continueid(); } void GameInit(void) { KeyFlags = 0; enable_continue_game(); SetInitialState(Lvl); ScrollPos[0] = PlayerPos[0] = Lvl->PlayerStartPos[0]; ScrollPos[1] = PlayerPos[1] = Lvl->PlayerStartPos[1]; PlayerVec[0] = PlayerVec[1] = 0; RequiredObjectsLeft = Lvl->ObjectsRequired; TotalObjectsLeft = Lvl->TotalObjects; GenericInit(); CurrentID = newid(); } void DrawClouds(BITMAP *buffer) { int c = 8; fixed x1, y1, x2, y2, x; while (c--) { x = Clouds[c].x + CloudX; x1 = fixmul(x - (fixsin(x) << 2), Scale); x2 = fixmul(x + itofix(cloud->w) + (fixsin(x) << 2), Scale); y1 = itofix(Clouds[c].y) - fixmul(fixcos(x) << 2, Scale); y2 = itofix(Clouds[c].y) + fixmul(itofix(cloud->h), Scale) + fixmul(fixcos(x) << 2, Scale); if (x2 < 0) { Clouds[c].x = Clouds[(c - 1) & 7].x + itofix(cloud->w + 8) + itofix(rand() / (RAND_MAX / 32)); Clouds[c].y = rand() / (RAND_MAX / (SCREEN_H >> 1)); } else stretch_blit(cloud, buffer, 0, 0, cloud->w, cloud->h, fixtoi(x1), fixtoi(y1), fixtoi(x2 - x1), fixtoi(y2 - y1)); } } void GameDraw(BITMAP *buffer) { BITMAP *ch; fixed depth; V3D Points[4]; /* draw background */ { int c = (SCREEN_H << 2) - 1; fixed y2, lowy = itofix(SCREEN_H), y1; float index; Points[0].x = Points[3].x = 0; Points[1].x = Points[2].x = itofix(SCREEN_W); while (c > (SCREEN_H << 1) + 15) { depth = fixmul(TanTable[c], (int)((ScrollPos[1] - 240) * 4096.0f)); if (depth > itofix(-261) && depth < ftofix(-5.0f)) { y1 = lowy; index = (fixtof((depth) & (itofix(256) - 1)) - 1.0f) * AL_PI * 2 * 8 / 128.0f; y2 = itofix(c >> 2) - fixdiv(ftofix(125.0f * sin(index + WaveY)), depth); if (y2 < lowy) { lowy = y2; Points[2].y = Points[3].y = y1; Points[0].y = Points[1].y = y2; Points[0].v = Points[1].v = Points[2].v = Points[3].v = depth + itofix(5); Points[0].u = Points[3].u = itofix(64) + (depth << 2) + (int)(ScrollPos[0] * 8192.0f) + TexX; Points[1].u = Points[2].u = itofix(64) - (depth << 2) + (int)(ScrollPos[0] * 8192.0f) + TexX; quad3d(buffer, POLYTYPE_ATEX, water, &Points[0], &Points[1], &Points[2], &Points[3]); } } c--; } set_clip_rect(buffer, 0, 0, buffer->w, fixtoi(lowy)); clear_to_color(buffer, getpixel(cloud, 0, 0)); DrawClouds(buffer); set_clip_rect(buffer, 0, 0, buffer->w, buffer->h); } /* draw interactable parts of level */ DrawLevelBackground(buffer, Lvl, ScrollPos); #ifdef DEBUG_EDGES solid_mode(); struct Edge *E = Lvl->AllEdges; while (E) { line(buffer, E->EndPoints[0]->Normal[0] - x + (SCREEN_W >> 1), E->EndPoints[0]->Normal[1] - y + (SCREEN_H >> 1), E->EndPoints[1]->Normal[0] - x + (SCREEN_W >> 1), E->EndPoints[1]->Normal[1] - y + (SCREEN_H >> 1), makecol(0, 0, 0)); E = E->Next; } #endif #ifdef DEBUG_OBJECTS struct Object *O = Lvl->AllObjects; while (O) { rect(buffer, O->Bounder.TL.Pos[0] - x + (SCREEN_W >> 1), O->Bounder.TL.Pos[1] - y + (SCREEN_H >> 1), O->Bounder.BR.Pos[0] - x + (SCREEN_W >> 1), O->Bounder.BR.Pos[1] - y + (SCREEN_H >> 1), makecol(0, 0, 0)); circle(buffer, O->Pos[0] - x + (SCREEN_W >> 1), O->Pos[1] - y + (SCREEN_H >> 1), O->ObjType->Radius, makecol(0, 0, 0)); O = O->Next; } #endif /* add player sprite */ ch = GetCurrentBitmap(PlayerAnim); if (KeyFlags & KEYFLAG_FLIP) rotate_scaled_sprite_v_flip(buffer, ch, fixtoi(fixmul (ftofix (PlayerPos[0] - (ch->w >> 1) - ScrollPos[0]), Scale)) + (SCREEN_W >> 1), fixtoi(fixmul (ftofix (PlayerPos[1] - (ch->h >> 1) - ScrollPos[1]), Scale)) + (SCREEN_H >> 1), ftofix(PlayerPos[2] * 128.0f / AL_PI) + itofix(128), Scale); else rotate_scaled_sprite(buffer, ch, fixtoi(fixmul (ftofix (PlayerPos[0] - (ch->w >> 1) - ScrollPos[0]), Scale)) + (SCREEN_W >> 1), fixtoi(fixmul (ftofix (PlayerPos[1] - (ch->h >> 1) - ScrollPos[1]), Scale)) + (SCREEN_H >> 1), ftofix(PlayerPos[2] * 128.0f / AL_PI), Scale); DrawLevelForeground(buffer, Lvl); /* add status */ demo_textprintf(buffer, demo_font, SCREEN_W - text_length(demo_font, "Items Required: 1000"), 8, makecol(255, 255, 255), -1, "Items Required: %d", RequiredObjectsLeft); demo_textprintf(buffer, demo_font, SCREEN_W - text_length(demo_font, "Items Remaining: 1000"), 8 + text_height(demo_font), makecol(255, 255, 255), -1, "Items Remaining: %d", TotalObjectsLeft); } int GameUpdate(void) { struct QuadTreeNode *CollTree; struct Container *EPtr; if (RequiredObjectsLeft < 0) return DEMO_STATE_SUCCESS; TexX += ftofix(0.3f); WaveY -= 0.02f; CloudX -= ftofix(0.125f); /* scrolling */ if ((PlayerPos[0] - ScrollPos[0]) < LeftWindow) ScrollPos[0] = PlayerPos[0] - LeftWindow; if ((PlayerPos[0] - ScrollPos[0]) > RightWindow) ScrollPos[0] = PlayerPos[0] - RightWindow; if ((PlayerPos[1] - ScrollPos[1]) < -80) ScrollPos[1] = PlayerPos[1] + 80; if ((PlayerPos[1] - ScrollPos[1]) > 80) ScrollPos[1] = PlayerPos[1] - 80; if ((KeyFlags & KEYFLAG_FLIP) ^ (((PlayerPos[2] < AL_PI * 0.5f) && (PlayerPos[2] > -AL_PI * 0.5f)) ? 0 : KEYFLAG_FLIP) ) { if (LeftWindow < 0) LeftWindow++; if (RightWindow < 120) RightWindow++; } else { if (LeftWindow > -120) LeftWindow--; if (RightWindow > 0) RightWindow--; } /* update controls */ controller[controller_id]->poll(controller[controller_id]); if (controller[controller_id]->button[0]) { if (KeyFlags & KEYFLAG_LEFT) { Pusher += 0.005f; if (Pusher >= PLAYER_STRENGTH) Pusher = PLAYER_STRENGTH; } else { KeyFlags |= KEYFLAG_LEFT; Pusher = 0; } } else KeyFlags &= ~KEYFLAG_LEFT; if (controller[controller_id]->button[1]) { if (KeyFlags & KEYFLAG_RIGHT) { Pusher += 0.005f; if (Pusher >= PLAYER_STRENGTH) Pusher = PLAYER_STRENGTH; } else { KeyFlags |= KEYFLAG_RIGHT; Pusher = 0; } } else KeyFlags &= ~KEYFLAG_RIGHT; if (controller[controller_id]->button[2]) KeyFlags |= KEYFLAG_JUMP; else { if ((KeyFlags & KEYFLAG_JUMPING) && PlayerVec[1] < -2.0f) PlayerVec[1] = -2.0f; KeyFlags &= ~(KEYFLAG_JUMP | KEYFLAG_JUMP_ISSUED); } /* run physics */ CollTree = RunPhysics(Lvl, PlayerPos, PlayerVec, 0.6f, PlayerAnim); /* check whether any objects are collected */ EPtr = CollTree->Contents; while (EPtr && EPtr->Type == OBJECT) { if (EPtr->Content.O->Flags & OBJFLAGS_VISIBLE) { float SqDistance, XDiff, YDiff; XDiff = PlayerPos[0] - EPtr->Content.O->Pos[0]; YDiff = PlayerPos[1] - EPtr->Content.O->Pos[1]; SqDistance = XDiff * XDiff + YDiff * YDiff; if (SqDistance <= EPtr->Content.O->ObjType->Radius * EPtr->Content.O->ObjType->Radius) { /* collision! */ if (EPtr->Content.O->Flags & OBJFLAGS_DOOR) { if (!RequiredObjectsLeft) { if (EPtr->Content.O->ObjType->CollectNoise) play_sample(EPtr->Content.O->ObjType-> CollectNoise, 255, 128, 1000, 0); RequiredObjectsLeft = -1; } } else { EPtr->Content.O->Flags &= ~OBJFLAGS_VISIBLE; if (EPtr->Content.O->ObjType->CollectNoise) play_sample(EPtr->Content.O->ObjType->CollectNoise, 255, 128, 1000, 0); if (RequiredObjectsLeft > 0) { RequiredObjectsLeft--; if (!RequiredObjectsLeft) SetDoorOpen(Lvl); } TotalObjectsLeft--; } } } EPtr = EPtr->Next; } return key[KEY_ESC] ? DEMO_STATE_MAIN_MENU : CurrentID; } void destroy_game() { FreeState(LvlState); LvlState = NULL; } /* GAMESTATE generation things - see comments in gmestate.h for more information */ void create_new_game(GAMESTATE * game) { game->id = newid; game->init = GameInit; game->update = GameUpdate; game->draw = GameDraw; game->deinit = DeInit; } void create_continue_game(GAMESTATE * game) { game->id = continueid; game->init = ContinueInit; game->update = GameUpdate; game->draw = GameDraw; game->deinit = DeInit; } allegro4.4-4.4.2/demos/skater/source/gamepad.c000066400000000000000000000075371173507505700210640ustar00rootroot00000000000000#include #include #include "../include/gamepad.h" static void read_config(VCONTROLLER * this, const char *config_path) { int i; char tmp[64]; push_config_state(); set_config_file(config_path); for (i = 0; i < 3; i++) { uszprintf(tmp, sizeof(tmp), "button%d", i); ((int *)(this->private_data))[i] = get_config_int("GAMEPAD", tmp, 0); if (((((int *)(this->private_data))[i] >> 8) & 255) >= num_joysticks) ((int *)(this->private_data))[i] = 0; } pop_config_state(); } static void write_config(VCONTROLLER * this, const char *config_path) { int i; char tmp[64]; push_config_state(); set_config_file(config_path); for (i = 0; i < 3; i++) { uszprintf(tmp, sizeof(tmp), "button%d", i); set_config_int("GAMEPAD", tmp, ((int *)(this->private_data))[i]); } pop_config_state(); } static void poll(VCONTROLLER * this) { int i; int *private_data = (int *)(this->private_data); poll_joystick(); for (i = 0; i < 3; i++) { if (private_data[i] & 1) { /* read a button */ this->button[i] = joy[(private_data[i] >> 8) & 255].button[private_data[i] >> 16].b; } else { /* read an axis */ this->button[i] = (private_data[i] & 2) ? joy[(private_data[i] >> 8) & 255]. stick[(private_data[i] >> 16) & 255]. axis[(private_data[i] >> 24)]. d1 : joy[(private_data[i] >> 8) & 255]. stick[(private_data[i] >> 16) & 255]. axis[(private_data[i] >> 24)].d2; } } } static int calibrate_button(VCONTROLLER * this, int i) { int stickc, axisc, joyc, buttonc; poll_joystick(); joyc = num_joysticks; while (joyc--) { /* check axes */ stickc = joy[joyc].num_sticks; while (stickc--) { axisc = joy[joyc].stick[stickc].num_axis; while (axisc--) { if (joy[joyc].stick[stickc].axis[axisc].d1) { ((int *)(this->private_data))[i] = 4 | 2 | (joyc << 8) | (stickc << 16) | (axisc << 24); return 1; } if (joy[joyc].stick[stickc].axis[axisc].d2) { ((int *)(this->private_data))[i] = 4 | (joyc << 8) | (stickc << 16) | (axisc << 24); return 1; } } } /* check buttons */ buttonc = joy[joyc].num_buttons; while (buttonc--) { if (joy[joyc].button[buttonc].b) { ((int *)(this->private_data))[i] = 4 | 1 | (joyc << 8) | (buttonc << 16); return 1; } } } return 0; } static const char *get_button_description(VCONTROLLER * this, int i) { int *private_data = (int *)(this->private_data); static char RetMessage[1024]; if (!private_data[i]) return "Unassigned"; if (private_data[i] & 1) { uszprintf(RetMessage, sizeof(RetMessage), "Pad %d Button %d", (private_data[i] >> 8) & 255, private_data[i] >> 16); return RetMessage; } else { uszprintf(RetMessage, sizeof(RetMessage), "Pad %d Stick %d Axis %d (%s)", (private_data[i] >> 8) & 255, (private_data[i] >> 16) & 255, private_data[i] >> 24, (private_data[i] & 2) ? "-" : "+"); return RetMessage; } } VCONTROLLER *create_gamepad_controller(const char *config_path) { int i; VCONTROLLER *ret = malloc(sizeof(VCONTROLLER)); ret->private_data = malloc(3 * sizeof(int)); for (i = 0; i < 3; i++) { ret->button[i] = 0; ((int *)(ret->private_data))[i] = 0; } ret->poll = poll; ret->calibrate_button = calibrate_button; ret->get_button_description = get_button_description; ret->read_config = read_config; ret->write_config = write_config; read_config(ret, config_path); return ret; } allegro4.4-4.4.2/demos/skater/source/global.c000066400000000000000000000337431173507505700207240ustar00rootroot00000000000000#include #ifdef DEMO_USE_ALLEGRO_GL #include #include "../include/oglflip.h" #endif #include "../include/backscrl.h" #include "../include/dblbuf.h" #include "../include/demodata.h" #include "../include/game.h" #include "../include/global.h" #include "../include/pageflip.h" #include "../include/tribuf.h" #include "../include/updtedvr.h" /* Default values of some config varables */ int fullscreen = 0; int bit_depth = 32; int screen_width = 640; int screen_height = 480; int update_driver_id = DEMO_DOUBLE_BUFFER; int use_vsync = 0; int logic_framerate = 100; int max_frame_skip = 5; int limit_framerate = 1; int display_framerate = 1; int reduce_cpu_usage = 1; int sound_volume = 5; int music_volume = 5; int controller_id = 0; int shadow_offset = 2; VCONTROLLER *controller[2]; char config_path[DEMO_PATH_LENGTH]; char data_path[DEMO_PATH_LENGTH]; FONT *demo_font; FONT *demo_font_logo; FONT *demo_font_logo_m; FONT *plain_font; DATAFILE *demo_data = 0; DEMO_SCREEN_UPDATE_DRIVER update_driver = { 0, 0, 0, 0 }; char *GameError; int load_data(void); const char *demo_error(int id) { switch (id) { case DEMO_ERROR_ALLEGRO: return allegro_error; case DEMO_ERROR_GFX: return "can't find suitable screen update driver"; case DEMO_ERROR_MEMORY: return "ran out of memory"; case DEMO_ERROR_VIDEOMEMORY: return "not enough VRAM"; case DEMO_ERROR_TRIPLEBUFFER: return "triple buffering not supported"; case DEMO_ERROR_DATA: return "can't load menu data"; case DEMO_ERROR_GAMEDATA: return GameError; case DEMO_OK: return "OK"; default: return "unknown"; }; } /* read_config: * Load settings from the configuration file, providing default values */ void read_config(const char *config) { push_config_state(); set_config_file(config); fullscreen = get_config_int("GFX", "fullscreen", fullscreen); bit_depth = get_config_int("GFX", "bit_depth", bit_depth); screen_width = get_config_int("GFX", "screen_width", screen_width); screen_height = get_config_int("GFX", "screen_height", screen_height); update_driver_id = get_config_int("GFX", "update_driver_id", update_driver_id); use_vsync = get_config_int("GFX", "vsync", use_vsync); logic_framerate = get_config_int("TIMING", "logic_framerate", logic_framerate); limit_framerate = get_config_int("TIMING", "limit_framerate", limit_framerate); max_frame_skip = get_config_int("TIMING", "max_frame_skip", max_frame_skip); display_framerate = get_config_int("TIMING", "display_framerate", display_framerate); reduce_cpu_usage = get_config_int("TIMING", "reduce_cpu_usage", reduce_cpu_usage); sound_volume = get_config_int("SOUND", "sound_volume", sound_volume); music_volume = get_config_int("SOUND", "music_volume", music_volume); controller_id = get_config_int("CONTROLS", "controller_id", controller_id); pop_config_state(); } void write_config(const char *config) { push_config_state(); set_config_file(config); set_config_int("GFX", "fullscreen", fullscreen); set_config_int("GFX", "bit_depth", bit_depth); set_config_int("GFX", "screen_width", screen_width); set_config_int("GFX", "screen_height", screen_height); set_config_int("GFX", "update_driver_id", update_driver_id); set_config_int("GFX", "vsync", use_vsync); set_config_int("TIMING", "logic_framerate", logic_framerate); set_config_int("TIMING", "max_frame_skip", max_frame_skip); set_config_int("TIMING", "limit_framerate", limit_framerate); set_config_int("TIMING", "display_framerate", display_framerate); set_config_int("TIMING", "reduce_cpu_usage", reduce_cpu_usage); set_config_int("SOUND", "sound_volume", sound_volume); set_config_int("SOUND", "music_volume", music_volume); set_config_int("CONTROLS", "controller_id", controller_id); pop_config_state(); } int change_gfx_mode(void) { int gfx_mode; int alternative; int ret = DEMO_OK; /* First unload all previously loaded data, select the direct screen update driver and go to text mode just in case. */ unload_data(); select_update_driver(DEMO_UPDATE_DIRECT); set_gfx_mode(GFX_TEXT, 0, 0, 0, 0); /* In windowed mode the desktop color depth takes preference to the user specified colour depth for performance reasons. */ if (fullscreen == 0) { bit_depth = desktop_color_depth(); } /* Select appropriate (fullscreen or windowed) gfx mode driver. */ #ifdef DEMO_USE_ALLEGRO_GL gfx_mode = GFX_OPENGL; #else if (fullscreen == 1) { gfx_mode = GFX_AUTODETECT_FULLSCREEN; } else { gfx_mode = GFX_AUTODETECT_WINDOWED; } #endif #ifdef DEMO_USE_ALLEGRO_GL /* AllegroGL has its own way to set GFX options. */ allegro_gl_set(AGL_COLOR_DEPTH, bit_depth); allegro_gl_set(AGL_DOUBLEBUFFER, 1); allegro_gl_set(AGL_RENDERMETHOD, 1); allegro_gl_set(AGL_WINDOWED, !fullscreen); allegro_gl_set(AGL_SUGGEST, AGL_COLOR_DEPTH | AGL_DOUBLEBUFFER | AGL_RENDERMETHOD | AGL_WINDOWED); #else set_color_depth(bit_depth); #endif /* Attempt to set the selected colour depth and gfx mode. */ if (set_gfx_mode(gfx_mode, screen_width, screen_height, 0, 0) != 0) { /* If setting gfx mode failed, try an alternative colour depth. 8bpp doesn't have an alternative, but 15 and 16 can be exchanged as well as 24 and 32. */ switch (bit_depth) { case 8: alternative = 0; break; case 15: alternative = 16; break; case 16: alternative = 15; break; case 24: alternative = 32; break; case 32: alternative = 24; break; default: alternative = 16; break; } if (alternative != 0) { /* Try to set the alternative colour depth and gfx mode. */ set_color_depth(alternative); if (set_gfx_mode(gfx_mode, screen_width, screen_height, 0, 0) != 0) { /* Won't go. Give up! */ return DEMO_ERROR_ALLEGRO; } /* Alternative worked, so remember it for next time. */ bit_depth = alternative; } else { /* Give up is there is no alternative color depth. */ return DEMO_ERROR_ALLEGRO; } } #ifdef DEMO_USE_ALLEGRO_GL /* Needed for Allegro drawnig functions to behave. Also sets the Allegro coordinate system. */ allegro_gl_set_allegro_mode(); #endif /* blank display now, before doing any more complicated stuff */ clear_to_color(screen, makecol(0, 0, 0)); if (fullscreen) { show_os_cursor(MOUSE_CURSOR_NONE); } #ifdef DEMO_USE_ALLEGRO_GL /* OpenGL doesn't let us choose the update mode. */ select_update_driver(DEMO_OGL_FLIPPING); #else /* select update driver */ switch (update_driver_id) { case DEMO_TRIPLE_BUFFER: ret = select_update_driver(DEMO_TRIPLE_BUFFER); if (ret == DEMO_OK) break; /* fall through */ case DEMO_PAGE_FLIPPING: ret = select_update_driver(DEMO_PAGE_FLIPPING); if (ret == DEMO_OK) break; /* fall through */ case DEMO_DOUBLE_BUFFER: ret = select_update_driver(DEMO_DOUBLE_BUFFER); break; default: ret = DEMO_ERROR_GFX; }; #endif /* Attempt to load game data. */ ret = load_data(); /* If loading was successful, initialize the background scroller module. */ if (ret == DEMO_OK) { init_background(); } return ret; } int load_data(void) { /* First unload any data that was previously loaded. We don't want any nasty memory leaks. */ unload_data(); /* Load the data for the game menus. */ demo_data = load_datafile(data_path); if (demo_data == 0) { return DEMO_ERROR_DATA; } #ifdef DEMO_USE_ALLEGRO_GL_FONT /* Convert Allegro FONT to AllegroGL FONT. */ /* Note that we could use Allegro's FONT and text output routines in AllegroGL mode but it is proven to be very slow. */ demo_font = allegro_gl_convert_allegro_font_ex(demo_data[DEMO_FONT].dat, AGL_FONT_TYPE_TEXTURED, -1.0, GL_ALPHA8); set_palette(demo_data[DEMO_MENU_PALETTE].dat); demo_font_logo = allegro_gl_convert_allegro_font_ex( demo_data[DEMO_FONT_LOGO].dat, AGL_FONT_TYPE_TEXTURED, -1.0, GL_RGBA8); /* Due to lack of the flexibility in AllegroGL text output routines we need an additional FONT that is equivalent to demo_font_logo - but monocrome. This allows tinting it to any color, which cannot be done with true color fonts (and paletted fonts are not supported by AllegroGL). */ demo_font_logo_m = allegro_gl_convert_allegro_font_ex( demo_data[DEMO_FONT_LOGO].dat, AGL_FONT_TYPE_TEXTURED, -1.0, GL_ALPHA8); plain_font = allegro_gl_convert_allegro_font_ex(font, AGL_FONT_TYPE_TEXTURED, -1.0, GL_ALPHA8); #else demo_font = demo_data[DEMO_FONT].dat; demo_font_logo = demo_data[DEMO_FONT_LOGO].dat; demo_font_logo_m = demo_font_logo; plain_font = font; #endif /* Load other game resources. */ if ((GameError = load_game_resources())) return DEMO_ERROR_GAMEDATA; return DEMO_OK; } void unload_data(void) { if (demo_data != 0) { unload_datafile(demo_data); unload_game_resources(); demo_data = 0; } #ifdef DEMO_USE_ALLEGRO_GL_FONT if (demo_font) allegro_gl_destroy_font(demo_font); if (demo_font_logo) allegro_gl_destroy_font(demo_font_logo); if (demo_font_logo_m) allegro_gl_destroy_font(demo_font_logo_m); if (plain_font) allegro_gl_destroy_font(plain_font); demo_font = NULL; demo_font_logo = NULL; demo_font_logo_m = NULL; plain_font = NULL; #endif } void demo_textout(BITMAP *bmp, const FONT *f, const char *s, int x, int y, int color, int bg) { demo_textprintf(bmp, f, x, y, color, bg, "%s", s); } void demo_textout_right(BITMAP *bmp, const FONT *f, const char *s, int x, int y, int color, int bg) { demo_textprintf_right(bmp, f, x, y, color, bg, "%s", s); } void demo_textout_centre(BITMAP *bmp, const FONT *f, const char *s, int x, int y, int color, int bg) { demo_textprintf_centre(bmp, f, x, y, color, bg, "%s", s); } void demo_textprintf_centre(BITMAP *canvas, const FONT *font, int x, int y, int col, int bg, const char *format, ...) { char buf[512]; va_list ap; va_start(ap, format); uvszprintf(buf, sizeof(buf), format, ap); va_end(ap); demo_textprintf_ex(canvas, font, x, y, col, bg, 2, "%s", buf); } void demo_textprintf_right(BITMAP *canvas, const FONT *font, int x, int y, int col, int bg, const char *format, ...) { char buf[512]; va_list ap; va_start(ap, format); uvszprintf(buf, sizeof(buf), format, ap); va_end(ap); demo_textprintf_ex(canvas, font, x, y, col, bg, 1, "%s", buf); } void demo_textprintf(BITMAP *canvas, const FONT *font, int x, int y, int col, int bg, const char *format, ...) { char buf[512]; va_list ap; va_start(ap, format); uvszprintf(buf, sizeof(buf), format, ap); va_end(ap); demo_textprintf_ex(canvas, font, x, y, col, bg, 0, "%s", buf); } void demo_textprintf_ex(BITMAP *canvas, const FONT *font, int x, int y, int col, int bg, int align, const char *format, ...) { char buf[512]; va_list ap; va_start(ap, format); uvszprintf(buf, sizeof(buf), format, ap); va_end(ap); #ifdef DEMO_USE_ALLEGRO_GL_FONT if (bg != -1) { rectfill(canvas, x, y, x + text_length(font, buf), y + text_height(font), bg); } switch (align) { case 1: x = x - text_length(font, buf); break; case 2: x = x - text_length(font, buf) / 2; break; }; glEnable(GL_TEXTURE_2D); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); allegro_gl_printf(font, x, y, 0, col, "%s", buf); glDisable(GL_BLEND); glDisable(GL_TEXTURE_2D); #else switch (align) { case 0: textprintf_ex(canvas, font, x, y, col, bg, "%s", buf); break; case 1: textprintf_right_ex(canvas, font, x, y, col, bg, "%s", buf); break; case 2: textprintf_centre_ex(canvas, font, x, y, col, bg, "%s", buf); break; }; #endif } void shadow_textprintf(BITMAP *canvas, FONT *font, int x, int y, int col, int align, const char *format, ...) { char buf[512]; va_list ap; va_start(ap, format); uvszprintf(buf, sizeof(buf), format, ap); va_end(ap); demo_textprintf_ex(canvas, font, x + shadow_offset, y + shadow_offset, 0, -1, align, "%s", buf); demo_textprintf_ex(canvas, font, x, y, col, -1, align, "%s", buf); } int select_update_driver(int id) { int error; DEMO_SCREEN_UPDATE_DRIVER new_driver = { 0, 0, 0, 0 }; /* destroy the previous driver if any */ if (update_driver.destroy) { update_driver.destroy(); } /* select the create function */ switch (id) { case DEMO_DOUBLE_BUFFER: select_double_buffer(&new_driver); break; case DEMO_PAGE_FLIPPING: select_page_flipping(&new_driver); break; case DEMO_TRIPLE_BUFFER: select_triple_buffer(&new_driver); break; #ifdef DEMO_USE_ALLEGRO_GL case DEMO_OGL_FLIPPING: select_ogl_flipping(&new_driver); break; #endif }; if (!new_driver.create) { return DEMO_ERROR_GFX; } /* create the backbuffers, video pages, etc. */ error = new_driver.create(); if (error != DEMO_OK) { /* If it didn't work, fall back to the old driver, if any. */ if (update_driver.create) { update_driver.create(); } return error; } /* copy the object over */ update_driver = new_driver; return DEMO_OK; } allegro4.4-4.4.2/demos/skater/source/intro.c000066400000000000000000000050651173507505700206130ustar00rootroot00000000000000#include #include "../include/menus.h" #include "../include/global.h" #include "../include/defines.h" #include "../include/music.h" static int _id = DEMO_STATE_INTRO; static float duration; static float progress; static int already_played_midi; static int id(void) { return _id; } static void init(void) { duration = 4.0f; progress = 0.0f; already_played_midi = 0; set_palette(demo_data[DEMO_MENU_PALETTE].dat); } static int update(void) { int c; progress += 1.0f / logic_framerate; if (progress >= duration) { return DEMO_STATE_MAIN_MENU; } if (keypressed()) { c = readkey() >> 8; clear_keybuf(); if (c == KEY_ESC) { return DEMO_STATE_EXIT; } return DEMO_STATE_MAIN_MENU; } return id(); } static void draw(BITMAP *canvas) { int c, x, y, offx, offy; static char logo_text1[] = "Allegro"; static char logo_text2[] = ""; /* XXX commented out because the font doesn't contain the characters for * anything other than "Allegro 4.2" */ /* static char logo_text2[] = "4.2"; */ if (progress < 0.5f) { c = (int)(255 * progress / 0.5f); clear_to_color(canvas, makecol(c, c, c)); } else { if (!already_played_midi) { play_music(DEMO_MIDI_INTRO, 0); already_played_midi = 1; } c = 255; clear_to_color(canvas, makecol(c, c, c)); x = SCREEN_W / 2; y = SCREEN_H / 2 - 3 * text_height(demo_font_logo) / 2; offx = 0; if (progress < 1.0f) { offx = (int)(text_length(demo_font_logo, logo_text1) * (1.0f - 2.0f * (progress - 0.5f))); } demo_textprintf_centre(canvas, demo_font_logo_m, x + 6 - offx, y + 5, makecol(128, 128, 128), -1, logo_text1); demo_textprintf_centre(canvas, demo_font_logo, x - offx, y, -1, -1, logo_text1); if (progress >= 1.5f) { y += 3 * text_height(demo_font_logo) / 2; offy = 0; if (progress < 2.0f) { offy = (int)((SCREEN_H - y) * (1.0f - 2.0f * (progress - 1.5f))); } demo_textprintf_centre(canvas, demo_font_logo_m, x + 6, y + 5 + offy, makecol(128, 128, 128), -1, logo_text2); demo_textprintf_centre(canvas, demo_font_logo, x, y + offy, -1, -1, logo_text2); } } } void create_intro(GAMESTATE * state) { state->id = id; state->init = init; state->update = update; state->draw = draw; } allegro4.4-4.4.2/demos/skater/source/kbd_sk.c000066400000000000000000000047621173507505700207200ustar00rootroot00000000000000#include #include "../include/keyboard.h" static void read_config(VCONTROLLER * this, const char *config_path) { int i; char tmp[64]; int def[] = { KEY_LEFT << 8, KEY_RIGHT << 8, KEY_SPACE << 8 }; push_config_state(); set_config_file(config_path); for (i = 0; i < 3; i++) { uszprintf(tmp, sizeof(tmp), "button%d", i); ((int *)(this->private_data))[i] = get_config_int("KEYBOARD", tmp, def[i]); } pop_config_state(); } static void write_config(VCONTROLLER * this, const char *config_path) { int i; char tmp[64]; push_config_state(); set_config_file(config_path); for (i = 0; i < 3; i++) { uszprintf(tmp, sizeof(tmp), "button%d", i); set_config_int("KEYBOARD", tmp, ((int *)(this->private_data))[i]); } pop_config_state(); } static void poll(VCONTROLLER * this) { int i; int *private_data = (int *)(this->private_data); for (i = 0; i < 3; i++) { if (key[private_data[i] >> 8]) { this->button[i] = 1; } else { this->button[i] = 0; } } } static int calibrate_button(VCONTROLLER * this, int i) { int c = 0; static int special[] = { KEY_TILDE, KEY_LSHIFT, KEY_RSHIFT, KEY_LCONTROL, KEY_RCONTROL, KEY_ALT, KEY_ALTGR, KEY_LWIN, KEY_RWIN, KEY_MENU, KEY_SCRLOCK, KEY_NUMLOCK, KEY_CAPSLOCK, -1 }; if (keypressed()) { c = readkey(); if (c >> 8 != KEY_ESC) { ((int *)(this->private_data))[i] = c; return 1; } else { return 0; } } c = 0; while (special[c] != -1) { if (key[special[c]]) { ((int *)(this->private_data))[i] = special[c] << 8; return 1; } c++; } return 0; } static const char *get_button_description(VCONTROLLER * this, int i) { int *private_data = (int *)(this->private_data); return scancode_to_name(private_data[i] >> 8); } VCONTROLLER *create_keyboard_controller(const char *config_path) { int i; VCONTROLLER *ret = malloc(sizeof(VCONTROLLER)); ret->private_data = malloc(3 * sizeof(int)); for (i = 0; i < 3; i++) { ret->button[i] = 0; ((int *)(ret->private_data))[i] = 0; } ret->poll = poll; ret->calibrate_button = calibrate_button; ret->get_button_description = get_button_description; ret->read_config = read_config; ret->write_config = write_config; read_config(ret, config_path); return ret; } allegro4.4-4.4.2/demos/skater/source/level.c000066400000000000000000000413771173507505700205750ustar00rootroot00000000000000/* Level.c contains the code for loading levels (which are in an ASCII format and parsed with a 'reasonable' degree of intelligence) and preprocessing them for game use. It can also produce a condensed version of the current level state (suitable for saving and loading of games, used elsewhere to retain state when display resolution is changed) and includes the main hook for level drawing - although this is passed on to quadtree.c as determining visibility is really a quadtree function. Note that the graphical parts of the level are scaled for the current display resolution but the collision / physics parts are never scaled. This is so that game behaviour is identical regardless of the display resolution and so that if the user changes resolution during a game they don't break their game state. The rounding error adjustment algorithms (see Physics.c) would not be very likely to survive a scaling of velocity and position and the player would likely fall through any platform they may be resting on. */ #include #include #include #include "../include/defines.h" #include "../include/game.h" #include "../include/level.h" #include "../include/lvlalloc.h" #include "../include/lvlfile.h" #include "../include/token.h" /* Drawing stuff first. Framec is a count of the current frame number, which is a required parameter to the drawing stuff in QuadTree.c - see that file for comments on that. DispBox is the rectangle that the user expects to be displayed. Note that (x, y) are parsed in the same units as the player moves so are scaled here into screen co-ordinates. */ int framec = 0; struct BoundingBox DispBox; void DrawLevelBackground(BITMAP *target, struct Level *lev, float *pos) { if (!lev) return; framec++; DispBox.TL.Pos[0] = ((pos[0] * SCREEN_H) / 480.0f) - (SCREEN_W >> 1); DispBox.TL.Pos[1] = ((pos[1] * SCREEN_H) / 480.0f) - (SCREEN_H >> 1); DispBox.BR.Pos[0] = DispBox.TL.Pos[0] + SCREEN_W; DispBox.BR.Pos[1] = DispBox.TL.Pos[1] + SCREEN_H; BeginQuadTreeDraw(target, lev, &lev->DisplayTree, &DispBox, framec); } void DrawLevelForeground(BITMAP *target, struct Level *lev) { if (!lev) return; EndQuadTreeDraw(target, lev, &DispBox, framec); } BITMAP *ObtainBitmap(const char *name) { #ifdef DEMO_USE_ALLEGRO_GL BITMAP *ret, *bmp; #endif char LocName[DEMO_PATH_LENGTH], TString[DEMO_PATH_LENGTH]; uszprintf(TString, sizeof(TString), "demo.dat#%s", name); get_executable_name(LocName, DEMO_PATH_LENGTH); replace_filename(LocName, LocName, TString, DEMO_PATH_LENGTH); #ifdef DEMO_USE_ALLEGRO_GL /* If AllegroGL is used, it is desireable to use use video bitmaps instead of memory bitmaps because they tend to be much faster. */ bmp = load_bmp(LocName, NULL); ret = create_video_bitmap(bmp->w, bmp->h); blit(bmp, ret, 0, 0, 0, 0, bmp->w, bmp->h); destroy_bitmap(bmp); return ret; #else return load_bmp(LocName, NULL); #endif } SAMPLE *ObtainSample(const char *name) { DATAFILE *Object; if (!game_audio) return NULL; Object = find_datafile_object(game_audio, name); if (!Object) return NULL; return (SAMPLE *)Object->dat; } /* A couple of very standard functions - min(a,b) returns the minimum of a and b, max(a,b) returns the maximum of a and b. Both have all the usual disadvantages of preprocessor macros (e.g. consider what will happen with min(a, b++)), but for this code it doesn't matter in the slightest. */ #define min(a, b) (((a) < (b)) ? (a) : (b)) #define max(a, b) (((a) > (b)) ? (a) : (b)) /* The FreeLevel function and associated macros. Just runs through all the data structures freeing anything that may have been allocated. Not really worthy of extensive comment. This function does the freeing for all level related struct types - there is no set of C++ equivalent deconstructors */ #define FreeList(name, type, sp) \ while(lvl->name)\ {\ Next = (void *)lvl->name->Next;\ sp(lvl->name);\ free(lvl->name);\ lvl->name = (struct type *)Next;\ } #define FreeMaterial(v) \ destroy_bitmap(v->Fill);\ destroy_bitmap(v->Edge); #define FreeObjectType(v) \ destroy_bitmap(v->Image); #define NoAction(v) void FreeLevel(struct Level *lvl) { void *Next; if (!lvl) return; /* easy things first */ FreeQuadTree(&lvl->DisplayTree); FreeQuadTree(&lvl->CollisionTree); /* free the resource lists */ FreeList(AllTris, Triangle, NoAction); FreeList(AllEdges, Edge, NoAction); FreeList(AllMats, Material, FreeMaterial); FreeList(AllObjectTypes, ObjectType, FreeObjectType); FreeList(AllVerts, Vertex, NoAction); FreeList(AllObjects, Object, NoAction); /* free door */ if (lvl->DoorOpen) destroy_bitmap(lvl->DoorOpen); if (lvl->DoorShut) destroy_bitmap(lvl->DoorShut); /* finally, free the level structure itself */ FreeState(lvl->InitialState); free(lvl); } /* 01234567890123456789012345678901234567890123456789012345678901234567890123456789 */ int CalcIntersection(struct Edge *e1, struct Edge *e2, float *Inter, int radius) { float d1, d2; d1 = (e1->EndPoints[0]->Pos[0] + radius * e1->a) * e2->a + (e1->EndPoints[0]->Pos[1] + radius * e1->b) * e2->b + e2->c; d2 = (e1->EndPoints[1]->Pos[0] + radius * e1->a) * e2->a + (e1->EndPoints[1]->Pos[1] + radius * e1->b) * e2->b + e2->c; if (!(d1 - d2)) return FALSE; d1 /= (d1 - d2); Inter[0] = e1->EndPoints[0]->Pos[0] + radius * e1->a + d1 * (e1->EndPoints[1]->Pos[0] - e1->EndPoints[0]->Pos[0]); Inter[1] = e1->EndPoints[0]->Pos[1] + radius * e1->b + d1 * (e1->EndPoints[1]->Pos[1] - e1->EndPoints[0]->Pos[1]); return TRUE; } void ScaleVerts(struct Level *Lvl) { struct Vertex *v = Lvl->AllVerts; float Scaler = (float)SCREEN_H / 480.0f; while (v) { v->Pos[0] *= Scaler; v->Pos[1] *= Scaler; v = v->Next; } } void FixVerts(struct Level *NewLev, int radius) { struct Vertex *v = NewLev->AllVerts; while (v) { if (v->Edges[1]) { /* position normal at intersection of two connected edges */ if (!CalcIntersection(v->Edges[0], v->Edges[1], v->Normal, radius)) { v->Normal[0] = v->Pos[0] + v->Edges[0]->a * radius; v->Normal[1] = v->Pos[1] + v->Edges[0]->b * radius; } } else if (v->Edges[0]) { /* position normal as a straight projection from v->Edges[0] */ float Direction = -1.0f; if (v->Edges[0]->EndPoints[0] == v) Direction = 1.0f; v->Normal[0] = v->Pos[0] + v->Edges[0]->a * radius + radius * Direction * v->Edges[0]->b; v->Normal[1] = v->Pos[1] + v->Edges[0]->b * radius - radius * Direction * v->Edges[0]->a; } v = v->Next; } } int FixEdges(struct Level *NewLev, int radius) { struct Edge **e = &NewLev->AllEdges; int NotFinished = FALSE, Failed; struct Edge OldEdge, *EdgePtr; while (*e) { /* check whether edge is now the wrong way around, and if so set NotFinished */ OldEdge = **e; Failed = GetNormal(*e, (*e)->EndPoints[0]->Normal, (*e)->EndPoints[1]->Normal); if (Failed || (((*e)->a * OldEdge.a + (*e)->b * OldEdge.b) < 0)) { NotFinished = TRUE; /* fix edge pointers */ EdgePtr = ((*e)->EndPoints[1]->Edges[0] == (*e)) ? (*e)->EndPoints[1]->Edges[1] : (*e)->EndPoints[1]-> Edges[0]; if ((*e)->EndPoints[0]->Edges[0] == (*e)) { if (!EdgePtr) { (*e)->EndPoints[0]->Edges[0] = (*e)->EndPoints[0]->Edges[1]; (*e)->EndPoints[0]->Edges[1] = NULL; } else (*e)->EndPoints[0]->Edges[0] = EdgePtr; } else (*e)->EndPoints[0]->Edges[1] = EdgePtr; if (EdgePtr->EndPoints[0] == (*e)->EndPoints[1]) EdgePtr->EndPoints[0] = (*e)->EndPoints[0]; else EdgePtr->EndPoints[1] = (*e)->EndPoints[0]; (*e)->EndPoints[1]->Edges[0] = (*e)->EndPoints[1]->Edges[1] = NULL; /* unlink & free */ EdgePtr = *e; (*e) = (*e)->Next; free((void *)EdgePtr); if (!(*e)) break; } e = &((*e)->Next); } return NotFinished; } /* AddEdges calculates the axis aligned bounding boxes of all edges and inserts them into the collision tree */ void AddEdges(struct Level *NewLev) { struct Edge *e = NewLev->AllEdges; while (e) { /* calculate AABB for this edge */ e->Bounder.TL.Pos[0] = min(e->EndPoints[0]->Normal[0], e->EndPoints[1]->Normal[0]) - 0.05f; e->Bounder.TL.Pos[1] = min(e->EndPoints[0]->Normal[1], e->EndPoints[1]->Normal[1]) - 0.05f; e->Bounder.BR.Pos[0] = max(e->EndPoints[0]->Normal[0], e->EndPoints[1]->Normal[0]) + 0.05f; e->Bounder.BR.Pos[1] = max(e->EndPoints[0]->Normal[1], e->EndPoints[1]->Normal[1]) + 0.05f; /* insert into quadtree */ AddEdge(NewLev, e); e = e->Next; } } /* ScaleAndAddObjects calculates a collision box for the object, adds it to the collision tree then scales the box for the current display resolution before adding to the display tree */ void ScaleAndAddObjects(struct Level *Lvl) { struct Object *O = Lvl->AllObjects; float Scaler = (float)SCREEN_H / 480.0f; while (O) { /* generate bounding box for collisions (i.e. no scaling yet) */ O->Bounder.BR.Pos[0] = O->Pos[0] + O->ObjType->Radius; O->Bounder.BR.Pos[1] = O->Pos[1] + O->ObjType->Radius; O->Bounder.TL.Pos[0] = O->Pos[0] - O->ObjType->Radius; O->Bounder.TL.Pos[1] = O->Pos[1] - O->ObjType->Radius; /* insert into collisions tree */ AddObject(Lvl, O, FALSE); /* scale bounding box to get visual position */ O->Bounder.BR.Pos[0] *= Scaler; O->Bounder.BR.Pos[1] *= Scaler; O->Bounder.TL.Pos[0] *= Scaler; O->Bounder.TL.Pos[1] *= Scaler; /* insert into display tree */ AddObject(Lvl, O, TRUE); /* move along linked lists */ O = O->Next; } } /* AddTriangles takes the now fully processed list of world triangles, calculates their bounding boxes (allowing for any edge trim) and inserts them into the display tree */ void AddTriangles(struct Level *Lvl) { struct Triangle *Tri = Lvl->AllTris; while (Tri) { int c = 3; /* determine axis aligned bounding box */ Tri->Bounder.TL.Pos[0] = Tri->Bounder.BR.Pos[0] = Tri->Edges[0]->Pos[0]; Tri->Bounder.TL.Pos[1] = Tri->Bounder.BR.Pos[1] = Tri->Edges[0]->Pos[1]; while (c--) { int lc = c - 1; if (lc < 0) lc = 2; /* check if this x expands the bounding box either leftward or rightward */ if (Tri->Edges[c]->Pos[0] < Tri->Bounder.TL.Pos[0]) Tri->Bounder.TL.Pos[0] = Tri->Edges[c]->Pos[0]; if (Tri->Edges[c]->Pos[0] > Tri->Bounder.BR.Pos[0]) Tri->Bounder.BR.Pos[0] = Tri->Edges[c]->Pos[0]; /* check y */ if ((Tri->EdgeFlags[c] & TRIFLAGS_EDGE) || (Tri->EdgeFlags[lc] & TRIFLAGS_EDGE)) { if (Tri->Edges[c]->Pos[1] - (Tri->EdgeFlags[c] & TRIFLAGS_WIDTH) < Tri->Bounder.TL.Pos[1]) Tri->Bounder.TL.Pos[1] = Tri->Edges[c]->Pos[1] - (Tri->EdgeFlags[c] & TRIFLAGS_WIDTH); if (Tri->Edges[c]->Pos[1] + (Tri->EdgeFlags[c] & TRIFLAGS_WIDTH) > Tri->Bounder.BR.Pos[1]) Tri->Bounder.BR.Pos[1] = Tri->Edges[c]->Pos[1] + (Tri->EdgeFlags[c] & TRIFLAGS_WIDTH); } else { if (Tri->Edges[c]->Pos[1] < Tri->Bounder.TL.Pos[1]) Tri->Bounder.TL.Pos[1] = Tri->Edges[c]->Pos[1]; if (Tri->Edges[c]->Pos[1] > Tri->Bounder.BR.Pos[1]) Tri->Bounder.BR.Pos[1] = Tri->Edges[c]->Pos[1]; } } /* insert into tree */ AddTriangle(Lvl, Tri); /* move along linked list */ Tri = Tri->Next; } } /* GetLevelError returns a textual description of any error that has occurred. If no error has occurred it will slightly confusingly return "Unspecified error at line " Appends "Level load - " to the start of whatever text may already have been provided */ char *GetLevelError(void) { char *LocTemp; if (!strlen(ErrorText)) uszprintf(ErrorText, sizeof(ErrorText), "Unspecified error at line %d", Lines); LocTemp = ustrdup(ErrorText); uszprintf(ErrorText, sizeof(ErrorText), "Level load - %s", LocTemp); free((void *)LocTemp); return ErrorText; } /* LoadLevel is called by other parts of the program and returns either a complete level structure or NULL indicating error, in which case GetLevelError will return a textual description of the error. Parameters are 'name' - the file name of the level and 'radius' - the collision size of the player for collision tree building */ struct Level *LoadLevel(char *name, int radius) { PACKFILE *file; struct Level *NewLev = NULL; ErrorText[0] = '\0'; /* set ErrorText to be a zero length string so that it will be obvious later if anything has set the error flag but not produced a verbose explanation of the error */ Error = 0; /* reset error flag as no error has occurred yet */ Lines = 1; /* first line is line 1 */ /* attempt to open named level file */ file = pack_fopen(name, "rp"); /* Find the data of the first object in the datafile. */ input = NULL; if (file) { /* is it a datafile? */ long magic = pack_mgetl(file); if (magic == DAT_MAGIC) { long i, n = pack_mgetl(file); /* check all objects in it */ for (i = 0; i < n; ) { long type = pack_mgetl(file); /* skip properties of this object */ if (type == DAT_PROPERTY) { long size; pack_mgetl(file); /* type */ size = pack_mgetl(file); pack_fseek(file, size); continue; } i++; file = pack_fopen_chunk(file, FALSE); /* use the very first DATA object found */ if (type == DAT_DATA) { input = file; break; } file = pack_fclose_chunk(file); } } } if (!input) { uszprintf(ErrorText, sizeof(ErrorText), "Unable to load level.txt"); goto error; } /* allocate and initially set up new level structure */ NewLev = NewLevel(); /* load materials, vertices & triangles in that order */ LoadMaterials(NewLev); if (Error) { goto error; } LoadVertices(NewLev); if (Error) { goto error; } LoadTriangles(NewLev, radius); if (Error) { goto error; } /* do a repeat 'fix' of vertices and fix of edges until we have no edge errors - see algorithm descriptions elsewhere in this file */ do FixVerts(NewLev, radius); while (FixEdges(NewLev, radius)); /* now that edges are fixed, add them to the collision tree */ AddEdges(NewLev); /* load ordinary object types */ LoadObjectTypes(NewLev, radius); if (Error) { goto error; } /* load special case object: door */ if (!(NewLev->DoorOpen = ObtainBitmap("dooropen"))) { uszprintf(ErrorText, sizeof(ErrorText), "Unable to obtain dooropen sprite"); goto error; } if (!(NewLev->DoorShut = ObtainBitmap("doorshut"))) { uszprintf(ErrorText, sizeof(ErrorText), "Unable to obtain doorshut sprite"); goto error; } NewLev->Door.Image = NewLev->DoorShut; NewLev->Door.CollectNoise = NULL; NewLev->Door.Radius = 14 + radius; /* load objects */ NewLev->TotalObjects = 0; LoadObjects(NewLev); if (Error) { goto error; } /* scale graphics according to current screen resolution. Note that collision edges are already computed and added to the collision tree */ ScaleVerts(NewLev); /* complete display tree additions */ AddTriangles(NewLev); ScaleAndAddObjects(NewLev); /* order things for drawing */ SplitTree(&NewLev->DisplayTree); OrderTree(&NewLev->DisplayTree, FALSE); OrderTree(&NewLev->DisplayTree, TRUE); OrderTree(&NewLev->CollisionTree, FALSE); /* load static level stuff - player start pos, etc */ LoadStats(NewLev); if (Error) { goto error; } /* make a copy of the initial state */ NewLev->InitialState = BorrowState(NewLev); /* return level */ return NewLev; error: /* close input file */ if (input) file = pack_fclose_chunk(input); if (file) pack_fclose(file); if (NewLev) FreeLevel(NewLev); return NULL; } allegro4.4-4.4.2/demos/skater/source/lvlalloc.c000066400000000000000000000043171173507505700212670ustar00rootroot00000000000000#include #include "../include/lvlalloc.h" /* A whole bunch of functions for creating new instances of the various game structs. For simplicity these are allocated one at a time by this code, although this is likely to lead to very suboptimal memory usage on modern operating systems. If this were a C++ program, these would be the struct constructors. The pattern is quite generic and not really worth too much attention. All pointers that may later be the target of memory deallocation are set to NULL and in some cases other members of interest are initiated. */ struct Level *NewLevel() { struct Level *l = (struct Level *)malloc(sizeof(struct Level)); if (l) { l->AllTris = NULL; l->AllEdges = NULL; l->AllMats = NULL; l->AllVerts = NULL; l->AllObjects = NULL; l->AllObjectTypes = NULL; l->InitialState = NULL; l->DoorOpen = l->DoorShut = NULL; l->Door.CollectNoise = NULL; SetupQuadTree(&l->DisplayTree, -65536, -65536, 65536, 65536); SetupQuadTree(&l->CollisionTree, -65536, -65536, 65536, 65536); } return l; } struct Material *NewMaterial() { struct Material *r = (struct Material *)malloc(sizeof(struct Material)); r->Next = NULL; r->Edge = r->Fill = NULL; r->Friction = 0; return r; } struct ObjectType *NewObjectType() { struct ObjectType *r = (struct ObjectType *)malloc(sizeof(struct ObjectType)); r->Next = NULL; r->Image = NULL; r->CollectNoise = NULL; return r; } struct Triangle *NewTriangle() { struct Triangle *r = (struct Triangle *)malloc(sizeof(struct Triangle)); r->Next = NULL; r->Material = NULL; r->LastFrame = 0; return r; } struct Object *NewObject() { struct Object *r = (struct Object *)malloc(sizeof(struct Object)); r->Next = NULL; r->Flags = OBJFLAGS_VISIBLE; r->ObjType = NULL; return r; } struct Edge *NewEdge() { struct Edge *r = (struct Edge *)malloc(sizeof(struct Edge)); r->Next = NULL; r->Material = NULL; return r; } struct Vertex *NewVertex() { struct Vertex *v = (struct Vertex *)malloc(sizeof(struct Vertex)); v->Next = NULL; v->Pos[0] = v->Pos[1] = 0; v->Edges[0] = v->Edges[1] = NULL; return v; } allegro4.4-4.4.2/demos/skater/source/lvlfile.c000066400000000000000000000371071173507505700211170ustar00rootroot00000000000000#include #ifdef DEMO_USE_ALLEGRO_GL #include #endif #include #include #include "../include/lvlalloc.h" #include "../include/lvlfile.h" #include "../include/token.h" /* Routines related to the initial reading of level data - heavily connected to tkeniser.c. Defines the grammar that level files should use. Also includes a simple function for obtaining the equation of a line and some other bits to do with data initialisation that flows straight from level data */ /* Converts a bitmap using bright pink for transparency to a bitmap using alpha channel. */ #ifdef DEMO_USE_ALLEGRO_GL void ConvertFromMaskedToTrans(BITMAP *From, BITMAP *To) { int x, y; for (y = 0; y < From->h; y++) { for (x = 0; x < From->w; x++) { int col = getpixel(From, x, y); /* If the pixel matches mask color (bright pink) write it with alpha value 0 (fully transparent), otherwise write at with alpha value 255 (fully opaque). */ if (col == bitmap_mask_color(From)) putpixel(To, x, y, makeacol32(getr(col), getg(col), getb(col), 0)); else putpixel(To, x, y, makeacol32(getr(col), getg(col), getb(col), 255)); } } } #endif /* LoadMaterials loads the list of materials according to the following grammar: fillname -> string edgename -> string materal -> { fillname, edgename } material list -> { material* } */ void LoadMaterials(struct Level *NewLev) { struct Material **NewMatPtr = &NewLev->AllMats; #ifdef DEMO_USE_ALLEGRO_GL BITMAP *TmpEdge; #endif ExpectToken(TK_OPENBRACE); while (1) { GetToken(); switch (Token.Type) { case TK_CLOSEBRACE: return; case TK_OPENBRACE: { *NewMatPtr = NewMaterial(); ExpectToken(TK_STRING); if (!((*NewMatPtr)->Fill = ObtainBitmap(Token.Text))) { Error = 1; uszprintf(ErrorText, sizeof(ErrorText), "Could not load material fill %s at line %d", Token.Text, Lines); return; } ExpectToken(TK_COMMA); ExpectToken(TK_STRING); #ifdef DEMO_USE_ALLEGRO_GL if (!(TmpEdge = ObtainBitmap(Token.Text))) { #else if (!((*NewMatPtr)->Edge = ObtainBitmap(Token.Text))) { #endif Error = 1; uszprintf(ErrorText, sizeof(ErrorText), "Could not load material edge %s at line %d", Token.Text, Lines); return; } #ifdef DEMO_USE_ALLEGRO_GL /* The "Edge" texture uses bright pink (also known as magic pink, makecol(255, 0, 255)) for transparency. Since AllegroGL doesn't support rendering of masked 3D polygons we have to convert the texture to a RGBA8 format which will use alpha channel for transparency.*/ /* Tell AllegroGL to create 32-bit video bitmaps (RGBA8). */ allegro_gl_set_video_bitmap_color_depth(32); (*NewMatPtr)->Edge = create_video_bitmap(TmpEdge->w, TmpEdge->h); /* Switch back to defualt video bitmaps color depth (screen color depth). */ allegro_gl_set_video_bitmap_color_depth(-1); ConvertFromMaskedToTrans(TmpEdge, (*NewMatPtr)->Edge); destroy_bitmap(TmpEdge); #endif ExpectToken(TK_COMMA); ExpectToken(TK_NUMBER); (*NewMatPtr)->Friction = Token.FQuantity; ExpectToken(TK_CLOSEBRACE); NewMatPtr = &(*NewMatPtr)->Next; } break; default: Error = 1; return; } } } /* LoadVertices loads the list of vertices according to the following grammar: xpos -> number ypos -> number vertex -> { xpos, ypos } vertex list -> { vertex* } */ void LoadVertices(struct Level *NewLev) { struct Vertex **NewVertPtr = &NewLev->AllVerts; ExpectToken(TK_OPENBRACE); while (1) { GetToken(); switch (Token.Type) { case TK_CLOSEBRACE: return; case TK_OPENBRACE: { *NewVertPtr = NewVertex(); ExpectToken(TK_NUMBER); (*NewVertPtr)->Pos[0] = Token.FQuantity; ExpectToken(TK_COMMA); ExpectToken(TK_NUMBER); (*NewVertPtr)->Pos[1] = Token.FQuantity; ExpectToken(TK_CLOSEBRACE); NewVertPtr = &(*NewVertPtr)->Next; } break; default: Error = 1; return; } } } /* GetVert loads a single vertex reference as part of the LoadTriangles routine. Grammar is: edge height -> number reference -> number flags -> "edge" | "collidable" | "foreground" vertex reference -> { reference, edge height [, flags] } */ void GetVert(struct Level *NewLev, struct Triangle *t, int c) { ExpectToken(TK_OPENBRACE); ExpectToken(TK_NUMBER); t->Edges[c] = NewLev->AllVerts; while (t->Edges[c] && Token.IQuantity--) t->Edges[c] = t->Edges[c]->Next; if (Token.IQuantity != -1) { Error = 1; uszprintf(ErrorText, sizeof(ErrorText), "Unknown vertex referenced at line %d", Lines); return; } ExpectToken(TK_COMMA); ExpectToken(TK_NUMBER); t->EdgeFlags[c] = (Token.IQuantity * SCREEN_H) / 480; GetToken(); switch (Token.Type) { case TK_COMMA: { int Finished = FALSE; while (!Finished) { GetToken(); switch (Token.Type) { case TK_CLOSEBRACE: Finished = TRUE; break; case TK_STRING: if (!strcmp(Token.Text, "edge")) t->EdgeFlags[c] |= TRIFLAGS_EDGE; if (!strcmp(Token.Text, "collidable")) t->EdgeFlags[c] |= FLAGS_COLLIDABLE; if (!strcmp(Token.Text, "foreground")) t->EdgeFlags[c] |= FLAGS_FOREGROUND; break; default: Error = 1; return; } } } break; case TK_CLOSEBRACE: break; default: Error = 1; return; } } /* GetNormal is a function that doesn't read anything from a file but calculates an edge normal for 'e' based on end points 'v1' and 'v2' */ int GetNormal(struct Edge *e, float *v1, float *v2) { /* get line normal */ float length; e->a = v2[1] - v1[1]; e->b = -(v2[0] - v1[0]); /* make line normal unit length */ length = sqrt(e->a * e->a + e->b * e->b); if (length < 1.0f) return TRUE; e->a /= length; e->b /= length; /* calculate distance of line from origin */ e->c = -(v1[0] * e->a + v1[1] * e->b); return FALSE; } /* InitEdge intialises edges, which means calculating the 'expanded' edge equation (i.e. one moved away from the real edge by 'radius' units) and making a note at both end vertices of the edge they meet */ void InitEdge(struct Edge *e, int radius) { /* get edge normal */ GetNormal(e, e->EndPoints[0]->Pos, e->EndPoints[1]->Pos); /* calculate distance to line from origin */ e->c -= radius * (e->a * e->a + e->b * e->b); /* link edge as necessary */ if (!e->EndPoints[0]->Edges[0]) e->EndPoints[0]->Edges[0] = e; else e->EndPoints[0]->Edges[1] = e; if (!e->EndPoints[1]->Edges[0]) e->EndPoints[1]->Edges[0] = e; else e->EndPoints[1]->Edges[1] = e; } /* LoadTriangles loads a triangle list, using GetVert as required. Grammar is: vertex reference -> (see GetVert commentary) material reference -> number triangle -> { vertex reference, vertex reference, vertex reference, material reference } triangle list -> { triangle* } */ void LoadTriangles(struct Level *NewLev, int radius) { struct Triangle *Tri; struct Edge *NextEdge; int c; ExpectToken(TK_OPENBRACE); while (1) { GetToken(); switch (Token.Type) { case TK_CLOSEBRACE: return; case TK_OPENBRACE: { Tri = NewTriangle(); /* read vertex pointers & edge flags */ GetVert(NewLev, Tri, 0); ExpectToken(TK_COMMA); GetVert(NewLev, Tri, 1); ExpectToken(TK_COMMA); GetVert(NewLev, Tri, 2); ExpectToken(TK_COMMA); /* read material reference and store correct pointer */ ExpectToken(TK_NUMBER); Tri->Material = NewLev->AllMats; while (Tri->Material && Token.IQuantity--) Tri->Material = Tri->Material->Next; if (Token.IQuantity != -1) { Error = 1; uszprintf(ErrorText, sizeof(ErrorText), "Unknown material referenced at line %d", Lines); return; } /* expect end of this triangle */ ExpectToken(TK_CLOSEBRACE); /* insert new triangle into total level list */ Tri->Next = NewLev->AllTris; NewLev->AllTris = Tri; /* generate edges */ c = 3; while (c--) { if (Tri->EdgeFlags[c] & FLAGS_COLLIDABLE) { NextEdge = NewLev->AllEdges; NewLev->AllEdges = NewEdge(); NewLev->AllEdges->Material = Tri->Material; NewLev->AllEdges->Next = NextEdge; NewLev->AllEdges->EndPoints[0] = Tri->Edges[c]; NewLev->AllEdges->EndPoints[1] = Tri->Edges[(c + 1) % 3]; InitEdge(NewLev->AllEdges, radius); } } } break; default: Error = 1; return; } } } /* LoadObjectTypes loads a list of object types. Grammar is: image name -> string collection noise -> string object type -> { image name, collection noise } object type list -> { object type* } */ void LoadObjectTypes(struct Level *NewLev, int radius) { struct ObjectType **NewObjectPtr = &NewLev->AllObjectTypes; ExpectToken(TK_OPENBRACE); while (1) { GetToken(); switch (Token.Type) { case TK_CLOSEBRACE: return; case TK_OPENBRACE: { *NewObjectPtr = NewObjectType(); ExpectToken(TK_STRING); if (!((*NewObjectPtr)->Image = ObtainBitmap(Token.Text))) { Error = 1; uszprintf(ErrorText, sizeof(ErrorText), "Could not load object image %s at line %d", Token.Text, Lines); return; } (*NewObjectPtr)->Radius = ((*NewObjectPtr)->Image->w > (*NewObjectPtr)->Image->h) ? (*NewObjectPtr)-> Image->w : (*NewObjectPtr)->Image->h; (*NewObjectPtr)->Radius += radius; ExpectToken(TK_COMMA); ExpectToken(TK_STRING); /* this doesn't generate an error as it is permissible to have objects that don't make a noise when collected */ (*NewObjectPtr)->CollectNoise = ObtainSample(Token.Text); ExpectToken(TK_CLOSEBRACE); NewObjectPtr = &(*NewObjectPtr)->Next; } break; default: Error = 1; return; } } } /* LoadObjects loads a list of objects. Grammar is: object pos x -> number object pos y -> number object type -> number flags -> "collidable" | "foreground" object -> { object pos x, object pos y, object type [, flags] } object list -> { object* } */ void LoadObjects(struct Level *NewLev) { struct Object *Obj; int Finished; ExpectToken(TK_OPENBRACE); while (1) { GetToken(); switch (Token.Type) { case TK_CLOSEBRACE: return; case TK_OPENBRACE: { Obj = NewObject(); NewLev->TotalObjects++; /* read location */ ExpectToken(TK_NUMBER); Obj->Pos[0] = Token.FQuantity; ExpectToken(TK_COMMA); ExpectToken(TK_NUMBER); Obj->Pos[1] = Token.FQuantity; ExpectToken(TK_COMMA); /* read angle, convert into Allegro format */ ExpectToken(TK_NUMBER); Obj->Angle = (Token.FQuantity * 128.0f) / AL_PI; ExpectToken(TK_COMMA); /* read object type, manipulate pointer */ ExpectToken(TK_NUMBER); if (Token.IQuantity >= 0) { Obj->ObjType = NewLev->AllObjectTypes; while (Obj->ObjType && Token.IQuantity--) Obj->ObjType = Obj->ObjType->Next; if (Token.IQuantity != -1) { Error = 1; uszprintf(ErrorText, sizeof(ErrorText), "Unknown object referenced at line %d", Lines); return; } } else { /* this is the door - a hard coded type */ Obj->ObjType = &NewLev->Door; Obj->Flags |= OBJFLAGS_DOOR; NewLev->TotalObjects--; } /* parse any flags that may exist */ GetToken(); switch (Token.Type) { case TK_COMMA: { Finished = FALSE; while (!Finished) { GetToken(); switch (Token.Type) { case TK_CLOSEBRACE: Finished = TRUE; break; case TK_STRING: if (!strcmp(Token.Text, "collidable")) Obj->Flags |= FLAGS_COLLIDABLE; if (!strcmp(Token.Text, "foreground")) Obj->Flags |= FLAGS_FOREGROUND; break; default: Error = 1; return; } } } break; case TK_CLOSEBRACE: break; default: Error = 1; return; } /* thread into list */ Obj->Next = NewLev->AllObjects; NewLev->AllObjects = Obj; } break; default: Error = 1; return; } } } /* LoadStats loads some special variables. Grammar is: player start x -> number player start y -> number required number of objects -> number stats -> { player start x, player start y, required number of objects } */ void LoadStats(struct Level *NewLev) { ExpectToken(TK_OPENBRACE); ExpectToken(TK_NUMBER); NewLev->PlayerStartPos[0] = Token.FQuantity; ExpectToken(TK_COMMA); ExpectToken(TK_NUMBER); NewLev->PlayerStartPos[1] = Token.FQuantity; ExpectToken(TK_COMMA); ExpectToken(TK_NUMBER); NewLev->ObjectsRequired = Token.IQuantity; ExpectToken(TK_CLOSEBRACE); } allegro4.4-4.4.2/demos/skater/source/lvlstate.c000066400000000000000000000027071173507505700213160ustar00rootroot00000000000000#include #include #include "../include/level.h" struct LevelState *BorrowState(struct Level *NewLev) { struct LevelState *St = (struct LevelState *)malloc(sizeof(struct LevelState)); struct Object *O; int ObjCount; if (!NewLev) return NULL; St->Length = (NewLev->TotalObjects + 31) >> 5; St->Data = (uint32_t *) malloc(sizeof(uint32_t) * St->Length); memset(St->Data, 0, sizeof(uint32_t) * St->Length); ObjCount = 0; O = NewLev->AllObjects; while (O) { if (O->Flags & OBJFLAGS_VISIBLE) St->Data[ObjCount >> 5] |= 1 << (ObjCount & 31); O = O->Next; ObjCount++; } St->DoorOpen = (NewLev->Door.Image == NewLev->DoorOpen); return St; } void ReturnState(struct Level *NewLev, struct LevelState *State) { struct Object *O; int ObjCount; if (!State || !NewLev) return; ObjCount = 0; O = NewLev->AllObjects; while (O) { if (State->Data[ObjCount >> 5] & (1 << (ObjCount & 31))) O->Flags |= OBJFLAGS_VISIBLE; else O->Flags &= ~OBJFLAGS_VISIBLE; O = O->Next; ObjCount++; } if (State->DoorOpen) SetDoorOpen(NewLev); } void FreeState(struct LevelState *State) { if (!State) return; free((void *)State->Data); free(State); } void SetInitialState(struct Level *lvl) { ReturnState(lvl, lvl->InitialState); } void SetDoorOpen(struct Level *Lvl) { Lvl->Door.Image = Lvl->DoorOpen; } allegro4.4-4.4.2/demos/skater/source/menu.c000066400000000000000000000435401173507505700204240ustar00rootroot00000000000000#include #include "../include/backscrl.h" #include "../include/credits.h" #include "../include/global.h" #include "../include/menu.h" #include "../include/music.h" #include "../include/virtctl.h" static int selected_item; static int item_count; BITMAP *demo_menu_canvas; static int locked; static int freq_variation = 100; void init_demo_menu(DEMO_MENU * menu, int PlayMusic) { int i; set_palette(demo_data[DEMO_MENU_PALETTE].dat); set_keyboard_rate(0, 0); clear_keybuf(); selected_item = -1; item_count = 0; locked = 0; for (i = 0; menu[i].proc != NULL; i++) { menu[i].proc(&menu[i], DEMO_MENU_MSG_INIT, 0); } item_count = i; for (i = 0; menu[i].proc != NULL; i++) { if ((menu[i].flags & DEMO_MENU_SELECTED)) { selected_item = i; break; } } if (selected_item == -1) { for (i = 0; menu[i].proc != NULL; i++) { if ((menu[i].flags & DEMO_MENU_SELECTABLE)) { selected_item = i; menu[i].flags |= DEMO_MENU_SELECTED; break; } } } if (PlayMusic) play_music(DEMO_MIDI_MENU, 1); } int update_demo_menu(DEMO_MENU * menu) { int tmp; update_background(); update_credits(); for (tmp = 0; menu[tmp].proc != 0; tmp++) { if (menu[tmp].proc(&menu[tmp], DEMO_MENU_MSG_TICK, 0) == DEMO_MENU_LOCK) { locked = 0; return DEMO_MENU_CONTINUE; } } if (locked == 1) { return DEMO_MENU_CONTINUE; } if (keypressed()) { int c = readkey(); clear_keybuf(); switch (c >> 8) { case KEY_ESC: return DEMO_MENU_BACK; break; case KEY_UP:{ if (selected_item != -1) { tmp = selected_item; while (1) { --selected_item; if (selected_item < 0) { selected_item = item_count - 1; } if (menu[selected_item].flags & DEMO_MENU_SELECTABLE) { break; } } if (tmp != selected_item) { menu[tmp].flags &= ~DEMO_MENU_SELECTED; menu[selected_item].flags |= DEMO_MENU_SELECTED; play_sound(DEMO_SAMPLE_BUTTON, 255, 128, -freq_variation, 0); } } } break; case KEY_DOWN:{ if (selected_item != -1) { tmp = selected_item; while (1) { ++selected_item; if (selected_item >= item_count) { selected_item = 0; } if (menu[selected_item].flags & DEMO_MENU_SELECTABLE) { break; } } if (tmp != selected_item) { menu[tmp].flags &= ~DEMO_MENU_SELECTED; menu[selected_item].flags |= DEMO_MENU_SELECTED; play_sound(DEMO_SAMPLE_BUTTON, 255, 128, -freq_variation, 0); } } } break; default: if (selected_item != -1) { tmp = menu[selected_item].proc(&menu[selected_item], DEMO_MENU_MSG_KEY, c); if (tmp == DEMO_MENU_LOCK) { locked = 1; return DEMO_MENU_CONTINUE; } else { locked = 0; return tmp; } } }; } return DEMO_MENU_CONTINUE; } void draw_demo_menu(BITMAP *canvas, DEMO_MENU * menu) { int i, x, y, h, w; int tmp; static char logo_text[] = "Demo Game"; /* make sure the procs know where to draw themselves */ demo_menu_canvas = canvas; draw_background(canvas); draw_credits(canvas); x = SCREEN_W / 2; y = 1 * SCREEN_H / 6 - text_height(demo_font_logo) / 2; demo_textprintf_centre(canvas, demo_font_logo_m, x + 6, y + 5, makecol(128, 128, 128), -1, logo_text); demo_textprintf_centre(canvas, demo_font_logo, x, y, -1, -1, logo_text); /* calculate height of the whole menu and the starting y coordinate */ h = 0; for (i = 0, h = 0; menu[i].proc != NULL; i++) { h += menu[i].proc(&menu[i], DEMO_MENU_MSG_HEIGHT, 0); } h += 2 * 8; y = 3 * SCREEN_H / 5 - h / 2; /* calculate the width of the whole menu */ w = 0; for (i = 0; menu[i].proc != NULL; i++) { tmp = menu[i].proc(&menu[i], DEMO_MENU_MSG_WIDTH, 0); if (tmp > w) { w = tmp; } } w += 2 * 8; w = MID(SCREEN_W / 3, w, SCREEN_W); x = (SCREEN_W - w) / 2; /* draw menu background */ if (update_driver_id == DEMO_DOUBLE_BUFFER) { drawing_mode(DRAW_MODE_TRANS, 0, 0, 0); set_trans_blender(0, 0, 0, 144); rectfill(canvas, x, y, x + w, y + h, makecol(96, 108, 116)); drawing_mode(DRAW_MODE_SOLID, 0, 0, 0); } else { rectfill(canvas, x, y, x + w, y + h, makecol(96, 108, 116)); } rect(canvas, x, y, x + w, y + h, makecol(0, 0, 0)); /* draw menu items */ y += 8; for (i = 0; menu[i].proc != NULL; i++) { menu[i].proc(&menu[i], DEMO_MENU_MSG_DRAW, y); y += menu[i].proc(&menu[i], DEMO_MENU_MSG_HEIGHT, 0); } } int demo_text_proc(DEMO_MENU * item, int msg, int extra) { if (msg == DEMO_MENU_MSG_DRAW) { shadow_textprintf(demo_menu_canvas, demo_font, SCREEN_W / 2, extra, makecol(210, 230, 255), 2, item->name); } else if (msg == DEMO_MENU_MSG_WIDTH) { return text_length(demo_font, item->name); } else if (msg == DEMO_MENU_MSG_HEIGHT) { return text_height(demo_font) + 8; } return DEMO_MENU_CONTINUE; } int demo_edit_proc(DEMO_MENU * item, int msg, int extra) { int col, w, h, x; int l, c; if (msg == DEMO_MENU_MSG_DRAW) { if (item->flags & DEMO_MENU_SELECTED) { col = makecol(255, 255, 0); } else { col = makecol(255, 255, 255); } w = demo_edit_proc(item, DEMO_MENU_MSG_WIDTH, 0); h = text_height(demo_font); rectfill(demo_menu_canvas, (SCREEN_W - w) / 2 - 2, extra - 2, (SCREEN_W + w) / 2 + 2, extra + h + 2, 0); rect(demo_menu_canvas, (SCREEN_W - w) / 2 - 2, extra - 2, (SCREEN_W + w) / 2 + 2, extra + h + 2, col); shadow_textprintf(demo_menu_canvas, demo_font, SCREEN_W / 2, extra, col, 2, item->name); if (item->flags & DEMO_MENU_SELECTED) { x = (SCREEN_W + text_length(demo_font, item->name)) / 2 + 2; vline(demo_menu_canvas, x, extra + 2, extra + h - 2, col); vline(demo_menu_canvas, x + 1, extra + 2, extra + h - 2, col); } } else if (msg == DEMO_MENU_MSG_KEY) { switch (extra >> 8) { case KEY_BACKSPACE: l = ustrlen(item->name); if (l > 0) { item->name[l - 1] = 0; if (item->on_activate) { item->on_activate(item); } play_sound(DEMO_SAMPLE_BUTTON, 255, 128, -freq_variation, 0); } break; default: l = ustrlen(item->name); c = extra & 0xff; if (l < item->extra && c >= 0x20 && c < 0x7f) { item->name[l] = c; if (item->on_activate) { item->on_activate(item); } play_sound(DEMO_SAMPLE_BUTTON, 255, 128, -freq_variation, 0); } break; } } else if (msg == DEMO_MENU_MSG_WIDTH) { return MAX(text_length(demo_font, item->name), item->extra * text_length(demo_font, " ")); } else if (msg == DEMO_MENU_MSG_HEIGHT) { return text_height(demo_font) + 8; } return DEMO_MENU_CONTINUE; } int demo_button_proc(DEMO_MENU * item, int msg, int extra) { int col; if (msg == DEMO_MENU_MSG_DRAW) { if (item->flags & DEMO_MENU_SELECTED) { col = makecol(255, 255, 0); } else { col = makecol(255, 255, 255); } shadow_textprintf(demo_menu_canvas, demo_font, SCREEN_W / 2, extra, col, 2, item->name); } else if (msg == DEMO_MENU_MSG_KEY) { switch (extra >> 8) { case KEY_ENTER: case KEY_SPACE: if (item->on_activate) { item->on_activate(item); } play_sound(DEMO_SAMPLE_BUTTON, 255, 128, -freq_variation, 0); return item->extra; break; } } else if (msg == DEMO_MENU_MSG_WIDTH || msg == DEMO_MENU_MSG_HEIGHT) { return demo_text_proc(item, msg, extra); } return DEMO_MENU_CONTINUE; } int demo_choice_proc(DEMO_MENU * item, int msg, int extra) { int col, x, cw, ch, dy, cx; int choice_count = 0; int slider_width = SCREEN_W / 6; int i, tmp; /* count number of choices */ for (; item->data[choice_count] != 0; choice_count++); if (msg == DEMO_MENU_MSG_DRAW) { if (item->flags & DEMO_MENU_SELECTED) { col = makecol(255, 255, 0); } else { col = makecol(255, 255, 255); } /* starting position */ x = (SCREEN_W - slider_width) / 2; /* print name of the item */ shadow_textprintf(demo_menu_canvas, demo_font, x - 8, extra, col, 1, item->name); /* draw slider thingy */ ch = text_height(demo_font) / 2; ch = MAX(8, ch); dy = (text_height(demo_font) - ch) / 2; /* shadow */ rect(demo_menu_canvas, x + shadow_offset, extra + dy + shadow_offset, x + slider_width + shadow_offset, extra + dy + ch + shadow_offset, 0); cw = (slider_width - 4) / choice_count; cw = MAX(cw, 8); cx = (slider_width - 4) * item->extra / choice_count; if (cx + cw > slider_width - 4) { cx = slider_width - 4 - cw; } if (item->extra == choice_count - 1) { cw = slider_width - 4 - cx; } rectfill(demo_menu_canvas, x + 3 + cx, extra + dy + 3, x + 3 + cx + cw, extra + dy + ch - 1, 0); /* slider */ rect(demo_menu_canvas, x, extra + dy, x + slider_width, extra + dy + ch, col); rectfill(demo_menu_canvas, x + 2 + cx, extra + dy + 2, x + 2 + cx + cw, extra + dy + ch - 2, col); x += slider_width; /* print selected choice */ shadow_textprintf(demo_menu_canvas, demo_font, x + 8, extra, col, 0, (char *)(item->data)[item->extra]); } else if (msg == DEMO_MENU_MSG_KEY) { switch (extra >> 8) { case KEY_LEFT: if (item->extra > 0) { --item->extra; play_sound(DEMO_SAMPLE_BUTTON, 255, 128, -freq_variation, 0); if (item->on_activate) { item->on_activate(item); } } break; case KEY_RIGHT: if (item->extra < choice_count - 1) { ++item->extra; play_sound(DEMO_SAMPLE_BUTTON, 255, 128, -freq_variation, 0); if (item->on_activate) { item->on_activate(item); } } break; } } else if (msg == DEMO_MENU_MSG_WIDTH) { cw = text_length(demo_font, item->name); for (i = 0; item->data[i] != 0; i++) { tmp = text_length(demo_font, (char *)(item->data)[i]); if (tmp > cw) { cw = tmp; } } return MAX(text_length(demo_font, item->name), cw) * 2 + slider_width + 2 * 8; } else if (msg == DEMO_MENU_MSG_HEIGHT) { return demo_text_proc(item, msg, extra); } return DEMO_MENU_CONTINUE; } int demo_key_proc(DEMO_MENU * item, int msg, int extra) { int col; if (msg == DEMO_MENU_MSG_DRAW) { if (item->flags & DEMO_MENU_SELECTED) { col = makecol(255, 255, 0); } else { col = makecol(255, 255, 255); } shadow_textprintf(demo_menu_canvas, demo_font, SCREEN_W / 2 - 16, extra, col, 1, item->name); if (item->flags & DEMO_MENU_EXTRA) { shadow_textprintf(demo_menu_canvas, demo_font, SCREEN_W / 2 + 16, extra, col, 0, "..."); } else { shadow_textprintf(demo_menu_canvas, demo_font, SCREEN_W / 2 + 16, extra, col, 0, controller[controller_id]-> get_button_description(controller [controller_id], item->extra)); } } else if (msg == DEMO_MENU_MSG_KEY) { switch (extra >> 8) { case KEY_ENTER: case KEY_SPACE: item->flags |= DEMO_MENU_EXTRA; play_sound(DEMO_SAMPLE_BUTTON, 255, 128, -freq_variation, 0); return DEMO_MENU_LOCK; break; } } else if (msg == DEMO_MENU_MSG_TICK) { if (item->flags & DEMO_MENU_EXTRA) { if (controller[controller_id]-> calibrate_button(controller[controller_id], item->extra) == 1) { item->flags &= ~DEMO_MENU_EXTRA; play_sound(DEMO_SAMPLE_BUTTON, 255, 128, -freq_variation, 0); if (item->on_activate) { item->on_activate(item); } return DEMO_MENU_LOCK; } else if (key[KEY_ESC]) { item->flags &= ~DEMO_MENU_EXTRA; return DEMO_MENU_LOCK; } } } else if (msg == DEMO_MENU_MSG_WIDTH) { int w1 = text_length(demo_font, item->name); int w2 = text_length(demo_font, (item-> flags & DEMO_MENU_EXTRA) ? "..." : controller[controller_id]-> get_button_description(controller[controller_id], item->extra)); return 2 * (16 + ((w2 > w1) ? w2 : w1)); } else if (msg == DEMO_MENU_MSG_HEIGHT) { return demo_text_proc(item, msg, extra); } return DEMO_MENU_CONTINUE; } int demo_color_proc(DEMO_MENU * item, int msg, int extra) { int col1, col2, x, h, cw, cx, i, c; int rgb[3]; static char buf[64]; int changed = 0; int slider_width = SCREEN_W / 6; slider_width /= 3; slider_width -= 4; if (msg == DEMO_MENU_MSG_DRAW) { if (item->flags & DEMO_MENU_SELECTED) { col1 = makecol(255, 255, 0); col2 = makecol(255, 255, 255); } else { col1 = makecol(255, 255, 255); col2 = makecol(255, 255, 255); } x = SCREEN_W / 2 - (slider_width + 4) * 3 / 2; h = text_height(demo_font); shadow_textprintf(demo_menu_canvas, demo_font, x - 8, extra, col1, 1, item->name); c = *(int *)(item->data); rgb[0] = getr(c); rgb[1] = getg(c); rgb[2] = getb(c); for (i = 0; i < 3; i++) { cw = 4; cx = (slider_width - 4 - cw) * rgb[i] / 255; rect(demo_menu_canvas, x + 2, extra + 5, x + slider_width + 2, extra + h - 1, 0); rectfill(demo_menu_canvas, x + 3 + cx, extra + 6, x + 3 + cx + cw, extra + h - 4, 0); rect(demo_menu_canvas, x, extra + 3, x + slider_width, extra + h - 3, item->extra == i ? col1 : col2); rectfill(demo_menu_canvas, x + 2 + cx, extra + 5, x + 2 + cx + cw, extra + h - 5, item->extra == i ? col1 : col2); x += slider_width + 4; } uszprintf(buf, sizeof(buf), "%d,%d,%d", rgb[0], rgb[1], rgb[2]); shadow_textprintf(demo_menu_canvas, demo_font, x + 8, extra, c, 0, buf); } else if (msg == DEMO_MENU_MSG_KEY) { c = *(int *)(item->data); rgb[0] = getr(c); rgb[1] = getg(c); rgb[2] = getb(c); switch (extra >> 8) { case KEY_LEFT: if (rgb[item->extra] > 0) { if (key_shifts & KB_SHIFT_FLAG) { --rgb[item->extra]; } else { rgb[item->extra] -= 16; rgb[item->extra] = MAX(0, rgb[item->extra]); } changed = 1; } break; case KEY_RIGHT: if (rgb[item->extra] < 255) { if (key_shifts & KB_SHIFT_FLAG) { ++rgb[item->extra]; } else { rgb[item->extra] += 16; rgb[item->extra] = MIN(255, rgb[item->extra]); } changed = 1; } break; case KEY_TAB: if (key_shifts & KB_SHIFT_FLAG) { --item->extra; if (item->extra < 0) { item->extra += 3; } } else { ++item->extra; item->extra %= 3; } play_sound(DEMO_SAMPLE_BUTTON, 255, 128, -freq_variation, 0); if (item->on_activate) { item->on_activate(item); } break; } if (changed) { *(int *)(item->data) = makecol(rgb[0], rgb[1], rgb[2]); play_sound(DEMO_SAMPLE_BUTTON, 255, 128, -freq_variation, 0); if (item->on_activate) { item->on_activate(item); } } } else if (msg == DEMO_MENU_MSG_WIDTH) { return MAX(text_length(demo_font, item->name) * 2 + 8 * 2 + 3 * (slider_width + 4), 8 * 2 + 3 * (slider_width + 4) + 2 * text_length(demo_font, "255,255,255")); } else if (msg == DEMO_MENU_MSG_HEIGHT) { return text_height(demo_font); } return DEMO_MENU_CONTINUE; } int demo_separator_proc(DEMO_MENU * item, int msg, int extra) { if (msg == DEMO_MENU_MSG_WIDTH) { return extra - extra; } else if (msg == DEMO_MENU_MSG_HEIGHT) { return item->extra; } return DEMO_MENU_CONTINUE; } allegro4.4-4.4.2/demos/skater/source/menuabt.c000066400000000000000000000033161173507505700211100ustar00rootroot00000000000000#include #include "../include/defines.h" #include "../include/global.h" #include "../include/menu.h" #include "../include/menus.h" static int _id = DEMO_STATE_ABOUT; static int id(void) { return _id; } static DEMO_MENU menu[] = { {demo_text_proc, "Looks like rain. And soon!", 0, 0, 0, 0}, {demo_text_proc, " ", 0, 0, 0, 0}, {demo_text_proc, "Help coastal outdoor confectioner Ted collect the cherries,", 0, 0, 0, 0}, {demo_text_proc, "bananas, sliced oranges, sweets and ice creams he has on display", 0, 0, 0, 0}, {demo_text_proc, "before the rain begins!", 0, 0, 0, 0}, {demo_text_proc, "Luckily he has a skateboard so it should be a breeze!", 0, 0, 0, 0}, {demo_text_proc, " ", 0, 0, 0, 0}, {demo_text_proc, NULL, 0, 0, 0, 0}, {demo_text_proc, "by Shawn Hargreaves and many others", 0, 0, 0, 0}, {demo_text_proc, " ", 0, 0, 0, 0}, {demo_text_proc, "Allegro Demo Game", 0, 0, 0, 0}, {demo_text_proc, "By Miran Amon, Nick Davies, Elias, Thomas Harte & Jakub Wasilewski", 0, 0, 0, 0}, {demo_text_proc, " ", 0, 0, 0, 0}, {demo_button_proc, "Back", DEMO_MENU_SELECTABLE, DEMO_STATE_MAIN_MENU, 0, 0}, {NULL, NULL, 0, 0, 0, 0} }; static void init(void) { menu[7].name = allegro_id; init_demo_menu(menu, TRUE); } static int update(void) { int ret = update_demo_menu(menu); switch (ret) { case DEMO_MENU_CONTINUE: return id(); case DEMO_MENU_BACK: return DEMO_STATE_MAIN_MENU; default: return ret; }; } static void draw(BITMAP *canvas) { draw_demo_menu(canvas, menu); } void create_about_menu(GAMESTATE *state) { state->id = id; state->init = init; state->update = update; state->draw = draw; } allegro4.4-4.4.2/demos/skater/source/menuctl.c000066400000000000000000000027441173507505700211300ustar00rootroot00000000000000#include #include "../include/defines.h" #include "../include/global.h" #include "../include/menu.h" #include "../include/menus.h" static int _id = DEMO_STATE_CONTROLS; static int id(void) { return _id; } static char *choice_controls[] = { "keyboard", "gamepad", 0 }; static void on_controller(DEMO_MENU * item); static DEMO_MENU menu[] = { {demo_text_proc, "SETUP CONTROLS", 0, 0, 0, 0}, {demo_choice_proc, "Controller", DEMO_MENU_SELECTABLE, 0, (void *)choice_controls, on_controller}, {demo_key_proc, "Left", DEMO_MENU_SELECTABLE, DEMO_BUTTON_LEFT, 0, 0}, {demo_key_proc, "Right", DEMO_MENU_SELECTABLE, DEMO_BUTTON_RIGHT, 0, 0}, {demo_key_proc, "Jump", DEMO_MENU_SELECTABLE, DEMO_BUTTON_JUMP, 0, 0}, {demo_button_proc, "Back", DEMO_MENU_SELECTABLE, DEMO_STATE_OPTIONS, 0, 0}, {0, 0, 0, 0, 0, 0} }; static void init(void) { init_demo_menu(menu, TRUE); menu[1].extra = controller_id; } static int update(void) { int ret = update_demo_menu(menu); switch (ret) { case DEMO_MENU_CONTINUE: return id(); case DEMO_MENU_BACK: return DEMO_STATE_OPTIONS; default: return ret; }; } static void draw(BITMAP *canvas) { draw_demo_menu(canvas, menu); } void create_controls_menu(GAMESTATE * state) { state->id = id; state->init = init; state->update = update; state->draw = draw; } static void on_controller(DEMO_MENU * item) { controller_id = item->extra; } allegro4.4-4.4.2/demos/skater/source/menugfx.c000066400000000000000000000117221173507505700211260ustar00rootroot00000000000000#include #include "../include/defines.h" #include "../include/global.h" #include "../include/menu.h" #include "../include/menus.h" static int _id = DEMO_STATE_GFX; static int id(void) { return _id; } static char *choice_yes_no[] = { "no", "yes", 0 }; static char *choice_on_off[] = { "off", "on", 0 }; static char *choice_bpp[] = { "15 bpp", "16 bpp", "24 bpp", "32 bpp", 0 }; static char *choice_res[] = { "640x480", "720x480", "800x600", "896x600", "1024x768", "1152x768", "1280x960", "1440x960", "1600x1200", "1800x1200", 0 }; static char *choice_update[] = { "double buffer", "page flipping", "triple buffer", 0 }; static void apply(DEMO_MENU * item); static void on_vsync(DEMO_MENU * item) { use_vsync = item->extra; } static DEMO_MENU menu[] = { {demo_text_proc, "GFX SETTINGS", 0, 0, 0, 0}, {demo_choice_proc, "Fullscreen", DEMO_MENU_SELECTABLE, 0, (void *)choice_yes_no, 0}, {demo_choice_proc, "Bit Depth", DEMO_MENU_SELECTABLE, 0, (void *)choice_bpp, 0}, {demo_choice_proc, "Screen Size", DEMO_MENU_SELECTABLE, 0, (void *)choice_res, 0}, #ifdef DEMO_USE_ALLEGRO_GL {demo_choice_proc, "Update Method", 0, 0, (void *)choice_update, 0}, #else {demo_choice_proc, "Update Method", DEMO_MENU_SELECTABLE, 0, (void *)choice_update, 0}, #endif {demo_choice_proc, "Vsync", DEMO_MENU_SELECTABLE, 0, (void *)choice_on_off, on_vsync}, {demo_button_proc, "Apply", DEMO_MENU_SELECTABLE, DEMO_STATE_GFX, 0, apply}, {demo_button_proc, "Back", DEMO_MENU_SELECTABLE, DEMO_STATE_OPTIONS, 0, 0}, {0, 0, 0, 0, 0, 0} }; static void init(void) { init_demo_menu(menu, TRUE); menu[1].extra = fullscreen; switch (bit_depth) { case 15: menu[2].extra = 0; break; case 16: menu[2].extra = 1; break; case 24: menu[2].extra = 2; break; case 32: menu[2].extra = 3; break; }; switch (screen_height) { case 480: menu[3].extra = 0; break; case 600: menu[3].extra = 2; break; case 768: menu[3].extra = 4; break; case 960: menu[3].extra = 6; break; case 1200: menu[3].extra = 8; break; }; if (((screen_width * 3) / 4) != screen_height) menu[3].extra |= 1; switch (update_driver_id) { case DEMO_DOUBLE_BUFFER: menu[4].extra = 0; break; case DEMO_PAGE_FLIPPING: menu[4].extra = 1; break; case DEMO_TRIPLE_BUFFER: menu[4].extra = 2; break; }; menu[5].extra = use_vsync; } static int update(void) { int ret = update_demo_menu(menu); switch (ret) { case DEMO_MENU_CONTINUE: return id(); case DEMO_MENU_BACK: return DEMO_STATE_OPTIONS; default: return ret; }; } static void draw(BITMAP *canvas) { draw_demo_menu(canvas, menu); } void create_gfx_menu(GAMESTATE * state) { state->id = id; state->init = init; state->update = update; state->draw = draw; } static void apply(DEMO_MENU * item) { int old_fullscreen = fullscreen; int old_bit_depth = bit_depth; int old_screen_width = screen_width; int old_screen_height = screen_height; int old_update_driver_id = update_driver_id; int old_use_vsync = use_vsync; ++item->extra; --item->extra; fullscreen = menu[1].extra; switch (menu[2].extra) { case 0: bit_depth = 15; break; case 1: bit_depth = 16; break; case 2: bit_depth = 24; break; case 3: bit_depth = 32; break; }; switch (menu[3].extra >> 1) { case 0: screen_height = 480; break; case 1: screen_height = 600; break; case 2: screen_height = 768; break; case 3: screen_height = 960; break; case 4: screen_height = 1200; break; }; if (menu[3].extra & 1) screen_width = (screen_height == 600) ? 896 : (screen_height * 3) / 2; else screen_width = (screen_height * 4) / 3; switch (menu[4].extra) { case 0: update_driver_id = DEMO_DOUBLE_BUFFER; break; case 1: update_driver_id = DEMO_PAGE_FLIPPING; break; case 2: update_driver_id = DEMO_TRIPLE_BUFFER; break; }; use_vsync = menu[5].extra; if (fullscreen == old_fullscreen && bit_depth == old_bit_depth && screen_width == old_screen_width && screen_height == old_screen_height && update_driver_id == old_update_driver_id) { return; } if (change_gfx_mode() != DEMO_OK) { fullscreen = old_fullscreen; bit_depth = old_bit_depth; screen_width = old_screen_width; screen_height = old_screen_height; update_driver_id = old_update_driver_id; use_vsync = old_use_vsync; change_gfx_mode(); } init(); } allegro4.4-4.4.2/demos/skater/source/menumain.c000066400000000000000000000034361173507505700212710ustar00rootroot00000000000000#include #include "../include/defines.h" #include "../include/global.h" #include "../include/menu.h" #include "../include/menus.h" static int _id = DEMO_STATE_MAIN_MENU; static int already_said_welcome = 0; static int id(void) { return _id; } static DEMO_MENU menu[] = { {demo_button_proc, "New Game", DEMO_MENU_SELECTABLE, DEMO_STATE_NEW_GAME, 0, 0}, {demo_text_proc, "Continue Game", 0, DEMO_STATE_CONTINUE_GAME, 0, 0}, {demo_button_proc, "Options", DEMO_MENU_SELECTABLE, DEMO_STATE_OPTIONS, 0, 0}, {demo_button_proc, "About", DEMO_MENU_SELECTABLE, DEMO_STATE_ABOUT, 0, 0}, {demo_button_proc, "Exit", DEMO_MENU_SELECTABLE, DEMO_STATE_EXIT, 0, 0}, {0, 0, 0, 0, 0, 0} }; void enable_continue_game(void) { menu[1].proc = demo_button_proc; menu[1].flags |= DEMO_MENU_SELECTABLE; } void disable_continue_game(void) { menu[1].proc = demo_text_proc; menu[1].flags &= ~DEMO_MENU_SELECTABLE; /* need to move 'cursor' if it was on continue game */ if (menu[1].flags & DEMO_MENU_SELECTED) { menu[1].flags &= ~DEMO_MENU_SELECTED; menu[0].flags |= DEMO_MENU_SELECTED; } } static void init(void) { init_demo_menu(menu, TRUE); if (!already_said_welcome) { play_sample(demo_data[DEMO_SAMPLE_WELCOME].dat, 255, 128, 1000, 0); already_said_welcome = 1; } } static int update(void) { int ret = update_demo_menu(menu); switch (ret) { case DEMO_MENU_CONTINUE: return id(); case DEMO_MENU_BACK: return DEMO_STATE_EXIT; default: return ret; }; } static void draw(BITMAP *canvas) { draw_demo_menu(canvas, menu); } void create_main_menu(GAMESTATE * state) { state->id = id; state->init = init; state->update = update; state->draw = draw; } allegro4.4-4.4.2/demos/skater/source/menumisc.c000066400000000000000000000031471173507505700212770ustar00rootroot00000000000000#include #include "../include/defines.h" #include "../include/global.h" #include "../include/menu.h" #include "../include/menus.h" static int _id = DEMO_STATE_MISC; static int id(void) { return _id; } static char *choice_yes_no[] = { "no", "yes", 0 }; static void on_fps(DEMO_MENU * item) { display_framerate = item->extra; } static void on_limit(DEMO_MENU * item) { limit_framerate = item->extra; } static void on_yield(DEMO_MENU * item) { reduce_cpu_usage = item->extra; } static DEMO_MENU menu[] = { {demo_text_proc, "SYSTEM SETTINGS", 0, 0, 0, 0}, {demo_choice_proc, "Show Framerate", DEMO_MENU_SELECTABLE, 0, (void *)choice_yes_no, on_fps}, {demo_choice_proc, "Cap Framerate", DEMO_MENU_SELECTABLE, 0, (void *)choice_yes_no, on_limit}, {demo_choice_proc, "Conserve Power", DEMO_MENU_SELECTABLE, 0, (void *)choice_yes_no, on_yield}, {demo_button_proc, "Back", DEMO_MENU_SELECTABLE, DEMO_STATE_OPTIONS, 0, 0}, {0, 0, 0, 0, 0, 0} }; static void init(void) { init_demo_menu(menu, TRUE); menu[1].extra = display_framerate; menu[2].extra = limit_framerate; menu[3].extra = reduce_cpu_usage; } static int update(void) { int ret = update_demo_menu(menu); switch (ret) { case DEMO_MENU_CONTINUE: return id(); case DEMO_MENU_BACK: return DEMO_STATE_OPTIONS; default: return ret; }; } static void draw(BITMAP *canvas) { draw_demo_menu(canvas, menu); } void create_misc_menu(GAMESTATE * state) { state->id = id; state->init = init; state->update = update; state->draw = draw; } allegro4.4-4.4.2/demos/skater/source/menuopts.c000066400000000000000000000023401173507505700213230ustar00rootroot00000000000000#include #include "../include/defines.h" #include "../include/menu.h" #include "../include/menus.h" static int _id = DEMO_STATE_OPTIONS; static int id(void) { return _id; } static DEMO_MENU menu[] = { {demo_text_proc, "OPTIONS", 0, 0, 0, 0}, {demo_button_proc, "Graphics", DEMO_MENU_SELECTABLE, DEMO_STATE_GFX, 0, 0}, {demo_button_proc, "Sound", DEMO_MENU_SELECTABLE, DEMO_STATE_SOUND, 0, 0}, {demo_button_proc, "Controls", DEMO_MENU_SELECTABLE, DEMO_STATE_CONTROLS, 0, 0}, {demo_button_proc, "System", DEMO_MENU_SELECTABLE, DEMO_STATE_MISC, 0, 0}, {demo_button_proc, "Back", DEMO_MENU_SELECTABLE, DEMO_STATE_MAIN_MENU, 0, 0}, {0, 0, 0, 0, 0, 0} }; static void init(void) { init_demo_menu(menu, TRUE); } static int update(void) { int ret = update_demo_menu(menu); switch (ret) { case DEMO_MENU_CONTINUE: return id(); case DEMO_MENU_BACK: return DEMO_STATE_MAIN_MENU; default: return ret; }; } static void draw(BITMAP *canvas) { draw_demo_menu(canvas, menu); } void create_options_menu(GAMESTATE * state) { state->id = id; state->init = init; state->update = update; state->draw = draw; } allegro4.4-4.4.2/demos/skater/source/menusnd.c000066400000000000000000000030471173507505700211270ustar00rootroot00000000000000#include #include "../include/defines.h" #include "../include/global.h" #include "../include/menu.h" #include "../include/menus.h" static int _id = DEMO_STATE_SOUND; static int id(void) { return _id; } static char *choice_volume[] = { "0%%", "10%%", "20%%", "30%%", "40%%", "50%%", "60%%", "70%%", "80%%", "90%%", "100%%", 0 }; static void on_sound(DEMO_MENU * item) { sound_volume = item->extra; set_volume(sound_volume * 25, music_volume * 25); } static void on_music(DEMO_MENU * item) { music_volume = item->extra; set_volume(sound_volume * 25, music_volume * 25); } static DEMO_MENU menu[] = { {demo_text_proc, "SOUND LEVELS", 0, 0, 0, 0}, {demo_choice_proc, "Sound", DEMO_MENU_SELECTABLE, 0, (void *)choice_volume, on_sound}, {demo_choice_proc, "Music", DEMO_MENU_SELECTABLE, 0, (void *)choice_volume, on_music}, {demo_button_proc, "Back", DEMO_MENU_SELECTABLE, DEMO_STATE_OPTIONS, 0, 0}, {0, 0, 0, 0, 0, 0} }; static void init(void) { init_demo_menu(menu, TRUE); menu[1].extra = sound_volume; menu[2].extra = music_volume; } static int update(void) { int ret = update_demo_menu(menu); switch (ret) { case DEMO_MENU_CONTINUE: return id(); case DEMO_MENU_BACK: return DEMO_STATE_OPTIONS; default: return ret; } } static void draw(BITMAP *canvas) { draw_demo_menu(canvas, menu); } void create_sound_menu(GAMESTATE * state) { state->id = id; state->init = init; state->update = update; state->draw = draw; } allegro4.4-4.4.2/demos/skater/source/menusucc.c000066400000000000000000000026501173507505700212770ustar00rootroot00000000000000#include #include "../include/defines.h" #include "../include/global.h" #include "../include/menu.h" #include "../include/menus.h" #include "../include/music.h" static int _id = DEMO_STATE_SUCCESS; static int id(void) { return _id; } static DEMO_MENU menu[] = { {demo_text_proc, "Well done! Ted's stock is saved!", 0, 0, 0, 0}, {demo_text_proc, " ", 0, 0, 0, 0}, {demo_text_proc, "This demo has shown only a fraction", 0, 0, 0, 0}, {demo_text_proc, "of Allegro's capabilities.", 0, 0, 0, 0}, {demo_text_proc, " ", 0, 0, 0, 0}, {demo_text_proc, "Now it's up to you to show the world the rest!", 0, 0, 0, 0}, {demo_text_proc, "Get coding!", 0, 0, 0, 0}, {demo_text_proc, " ", 0, 0, 0, 0}, {demo_button_proc, "Back", DEMO_MENU_SELECTABLE, DEMO_STATE_MAIN_MENU, 0, 0}, {0, 0, 0, 0, 0, 0} }; static void init(void) { init_demo_menu(menu, FALSE); disable_continue_game(); play_music(DEMO_MIDI_SUCCESS, FALSE); } static int update(void) { int ret = update_demo_menu(menu); switch (ret) { case DEMO_MENU_CONTINUE: return id(); case DEMO_MENU_BACK: return DEMO_STATE_MAIN_MENU; default: return ret; }; } static void draw(BITMAP *canvas) { draw_demo_menu(canvas, menu); } void create_success_menu(GAMESTATE * state) { state->id = id; state->init = init; state->update = update; state->draw = draw; } allegro4.4-4.4.2/demos/skater/source/music.c000066400000000000000000000011631173507505700205730ustar00rootroot00000000000000#include #include "../include/defines.h" #include "../include/global.h" static int currently_playing = -1; void play_music(int id, int loop) { if (id == currently_playing && midi_pos >= 0) { return; } if (play_midi(demo_data[id].dat, loop) == 0) { currently_playing = id; } else { currently_playing = -1; } } void stop_music(void) { stop_midi(); currently_playing = -1; } void play_sound(int id, int vol, int pan, int freq, int loop) { if (freq < 0) { freq = 1000 + rand() % (-freq) + freq / 2; } play_sample(demo_data[id].dat, vol, pan, freq, loop); } allegro4.4-4.4.2/demos/skater/source/oglflip.c000066400000000000000000000014071173507505700211100ustar00rootroot00000000000000#ifdef DEMO_USE_ALLEGRO_GL #include #include #include "../include/defines.h" #include "../include/oglflip.h" /***************************************************************************** * OpenGL screen update module * *****************************************************************************/ static void destroy(void) { } static int create(void) { return DEMO_OK; } static void draw(void) { allegro_gl_flip(); } static BITMAP *get_canvas(void) { return screen; } void select_ogl_flipping(DEMO_SCREEN_UPDATE_DRIVER * driver) { driver->create = create; driver->destroy = destroy; driver->draw = draw; driver->get_canvas = get_canvas; } #endif //DEMO_USE_ALLEGRO_GL allegro4.4-4.4.2/demos/skater/source/pageflip.c000066400000000000000000000025511173507505700212440ustar00rootroot00000000000000#include #include "../include/defines.h" #include "../include/pageflip.h" /***************************************************************************** * Page flipping module * *****************************************************************************/ static BITMAP *pf_page1 = NULL; static BITMAP *pf_page2 = NULL; static BITMAP *pf_active_page = NULL; static void destroy(void) { if (pf_page1) { destroy_bitmap(pf_page1); pf_page1 = NULL; } if (pf_page2) { destroy_bitmap(pf_page2); pf_page2 = NULL; } pf_active_page = NULL; } static int create(void) { destroy(); pf_page1 = create_video_bitmap(SCREEN_W, SCREEN_H); pf_page2 = create_video_bitmap(SCREEN_W, SCREEN_H); if ((!pf_page1) || (!pf_page2)) { destroy(); return DEMO_ERROR_VIDEOMEMORY; } pf_active_page = pf_page1; return DEMO_OK; } static void draw(void) { show_video_bitmap(pf_active_page); if (pf_active_page == pf_page1) { pf_active_page = pf_page2; } else { pf_active_page = pf_page1; } } static BITMAP *get_canvas(void) { return pf_active_page; } void select_page_flipping(DEMO_SCREEN_UPDATE_DRIVER * driver) { driver->create = create; driver->destroy = destroy; driver->draw = draw; driver->get_canvas = get_canvas; } allegro4.4-4.4.2/demos/skater/source/physics.c000066400000000000000000000403321173507505700211360ustar00rootroot00000000000000#include #include #include "../include/game.h" #include "../include/physics.h" /* FixUp is called when the player has collided with 'something' and takes the current player's velocity and the vector normal of whatever has been hit as arguments. It's job is primarily to remove whatever proportion of the velocity is running into the surface. This means that the player's velocity ends up running at a right angle to the normal. Think of a perfectly unbouncy ball falling onto a horizontal floor. It's vertical velocity is instantly zero'd, but its horizontal velocity is unaffected. FixUp does this same thing for surfaces that aren't horizontal using the dot product. As a secondary function it returns the magnitude of force it has away, which can be used to pick a 'thud' sound effect and also for friction calculations */ float FixUp(float *vec, float normalx, float normaly) { float mul; if (KeyFlags & KEYFLAG_JUMPING) KeyFlags &= ~(KEYFLAG_JUMPING | KEYFLAG_JUMP | KEYFLAG_JUMP_ISSUED); mul = vec[0] * normalx + vec[1] * normaly; vec[0] -= mul * normalx; vec[1] -= mul * normaly; return mul; } /* SetAngle takes a surface normal, player angle and JustDoIt flag and decides how the player's interaction with that surface affects his angle. If JustDoIt is set then the function just sets the player to be at the angle of the normal, no questions asked. Otherwise the players angle is set if either: - the angle of the normal is close to vertical - the angle of the normal is close to the player angle Note that the arguments to atan2 are adjusted so that we're thinking in Allegro style angle measurements (i.e. 0 degrees = straight up, increases go clockwise) rather than the usual mathematics meaning (i.e. 0 degrees = right, increases go anticlockwise) */ void SetAngle(float normalx, float normaly, float *a, int JustDoIt) { float NewAng = atan2(normalx, -normaly); if (JustDoIt || ((NewAng < (AL_PI * 0.25f)) && (NewAng >= 0)) || ((NewAng > (-AL_PI * 0.25f)) && (NewAng <= 0)) || fabs(NewAng - *a) < (AL_PI * 0.25f) ) *a = NewAng; } /* DoFriction applies surface friction along an edge, taking the player's intended direction of travel into account First of all it breaks movement into 'ForwardSpeed' and 'UpSpeed', both relative to the edge - i.e. forward speed is motion parallel to the edge, upward speed is motion perpendicular Then the two are adjusted according to surface friction and player input, and finally put back together to reform the complete player velocity */ void DoFriction(float r, struct Edge *E, float *vec) { /* calculate how quickly we're currently moving parallel and perpendicular to this edge */ float ForwardSpeed = (vec[0] * E->b - vec[1] * E->a) / E->Material->Friction, UpSpeed = vec[0] * E->a + vec[1] * E->b; float FricLevel; /* apply adjustments based on user controls */ if (KeyFlags & KEYFLAG_LEFT) { ForwardSpeed += Pusher; KeyFlags |= KEYFLAG_FLIP; } if (KeyFlags & KEYFLAG_RIGHT) { ForwardSpeed -= Pusher; KeyFlags &= ~KEYFLAG_FLIP; } /* apply friction as necessary */ FricLevel = 0.05f * E->Material->Friction; if (ForwardSpeed > 0) { if (ForwardSpeed < FricLevel) ForwardSpeed = 0; else ForwardSpeed -= FricLevel; } else { if (ForwardSpeed > -FricLevel) ForwardSpeed = 0; else ForwardSpeed += FricLevel; } /* add jump if requested */ if ((KeyFlags & (KEYFLAG_JUMP | KEYFLAG_JUMP_ISSUED)) == KEYFLAG_JUMP) { UpSpeed += 5.0f; KeyFlags |= KEYFLAG_JUMP_ISSUED | KEYFLAG_JUMPING; } /* put velocity back together */ vec[0] = UpSpeed * E->a + ForwardSpeed * E->Material->Friction * E->b; vec[1] = UpSpeed * E->b - ForwardSpeed * E->Material->Friction * E->a; } /* RunPhysics is the centrepiece of the game simulation and is perhaps misnamed in that it runs physics and game logic generally. The basic structure is: apply gravity and air resistance; while(some simulation time remains) { find first thing the player hits during the simulation time run time forward until that hit occurs adjust player velocity according to whatever he has hit } Although some additional work needs to be done */ struct QuadTreeNode *DoContinuousPhysics(struct Level *lvl, struct QuadTreeNode *CollTree, float *pos, float *vec, float TimeToGo, struct Animation *PAnim) { float MoveVec[2]; float CollTime, NCollTime; float End[2], ColPoint[2]; void *CollPtr; float d1, d2; struct Edge *E; float r; int Contact; struct Container *EPtr, *FirstEdge; /* save a small amount of time by finding the first edge here */ CollTree = GetCollisionNode(lvl, pos, vec); EPtr = CollTree->Contents; while (EPtr && EPtr->Type != EDGE) EPtr = EPtr->Next; FirstEdge = EPtr; /* do collisions and reactions */ do { Contact = FALSE; /* rounding error fixup */ EPtr = FirstEdge; while (EPtr) { /* simple line test */ d1 = EPtr->Content.E->a * pos[0] + EPtr->Content.E->b * pos[1] + EPtr->Content.E->c; if (d1 >= (-0.5f) && d1 <= 0.05f && pos[0] >= EPtr->Content.E->Bounder.TL.Pos[0] && pos[0] <= EPtr->Content.E->Bounder.BR.Pos[0] && pos[1] >= EPtr->Content.E->Bounder.TL.Pos[1] && pos[1] <= EPtr->Content.E->Bounder.BR.Pos[1] ) { pos[0] += EPtr->Content.E->a * (0.05f - d1); pos[1] += EPtr->Content.E->b * (0.05f - d1); Contact = TRUE; } EPtr = EPtr->Next; } MoveVec[0] = TimeToGo * vec[0]; MoveVec[1] = TimeToGo * vec[1]; CollTime = TimeToGo + 1.0f; End[0] = pos[0] + MoveVec[0]; End[1] = pos[1] + MoveVec[1]; CollPtr = NULL; /* search for collisions */ /* test 1: do we hit the edge of this collision tree node? */ if (End[0] > CollTree->Bounder.BR.Pos[0]) { NCollTime = (End[0] - CollTree->Bounder.BR.Pos[0]) / MoveVec[0]; if (NCollTime < CollTime) { CollTime = NCollTime; CollPtr = (void *)CollTree; } } if (End[0] < CollTree->Bounder.TL.Pos[0]) { NCollTime = (End[0] - CollTree->Bounder.TL.Pos[0]) / MoveVec[0]; if (NCollTime < CollTime) { CollTime = NCollTime; CollPtr = (void *)CollTree; } } if (End[1] > CollTree->Bounder.BR.Pos[1]) { NCollTime = (End[1] - CollTree->Bounder.BR.Pos[1]) / MoveVec[1]; if (NCollTime < CollTime) { CollTime = NCollTime; CollPtr = (void *)CollTree; } } if (End[1] < CollTree->Bounder.TL.Pos[1]) { NCollTime = (End[1] - CollTree->Bounder.TL.Pos[1]) / MoveVec[1]; if (NCollTime < CollTime) { CollTime = NCollTime; CollPtr = (void *)CollTree; } } /* test 2: do we hit any of the edges contained in the tree? */ EPtr = FirstEdge; while (EPtr) { /* simple line test */ d1 = EPtr->Content.E->a * pos[0] + EPtr->Content.E->b * pos[1] + EPtr->Content.E->c; d2 = EPtr->Content.E->a * End[0] + EPtr->Content.E->b * End[1] + EPtr->Content.E->c; if ((d1 >= (-0.05f)) && (d2 < 0)) { NCollTime = d1 / (d1 - d2); ColPoint[0] = pos[0] + NCollTime * MoveVec[0]; ColPoint[1] = pos[1] + NCollTime * MoveVec[1]; if (ColPoint[0] >= EPtr->Content.E->Bounder.TL.Pos[0] && ColPoint[0] <= EPtr->Content.E->Bounder.BR.Pos[0] && ColPoint[1] >= EPtr->Content.E->Bounder.TL.Pos[1] && ColPoint[1] <= EPtr->Content.E->Bounder.BR.Pos[1] ) { CollTime = NCollTime; CollPtr = (void *)EPtr; } } /* move to next edge */ EPtr = EPtr->Next; } /* advance - apply motion and resulting friction here! */ pos[0] += MoveVec[0] * CollTime; pos[1] += MoveVec[1] * CollTime; if (!Contact) AdvanceAnimation(PAnim, 0, FALSE); /* fix up */ if (CollPtr) { if (CollPtr == (void *)CollTree) { CollTree = GetCollisionNode(lvl, pos, vec); /* find new first edge */ EPtr = CollTree->Contents; while (EPtr && EPtr->Type != EDGE) EPtr = EPtr->Next; FirstEdge = EPtr; } else { /* edge collision */ E = ((struct Container *)CollPtr)->Content.E; r = FixUp(vec, E->a, E->b); SetAngle(E->a, E->b, &pos[2], (fabs(vec[0] * E->b - vec[1] * E->a) > 0.5f)); AdvanceAnimation(PAnim, (vec[0] * E->b - vec[1] * E->a) * ((KeyFlags & KEYFLAG_FLIP) ? 1.0f : -1.0f), TRUE); /* apply friction */ DoFriction(r, E, vec); } } else if (!Contact) { /* check if currently in contact with any surface. If not then do empty space movement */ if (KeyFlags & KEYFLAG_LEFT) { vec[0] -= 0.05f; KeyFlags |= KEYFLAG_FLIP; } if (KeyFlags & KEYFLAG_RIGHT) { vec[0] += 0.05f; KeyFlags &= ~KEYFLAG_FLIP; } if (pos[2] > 0) { pos[2] -= TimeToGo * CollTime * 0.03f; if (pos[2] < 0) pos[2] = 0; } if (pos[2] < 0) { pos[2] += TimeToGo * CollTime * 0.03f; if (pos[2] > 0) pos[2] = 0; } } /* reduce time & continue */ TimeToGo -= TimeToGo * CollTime; } while (TimeToGo > 0.01f); return CollTree; } /*#define TIME_STEP 0.6f struct QuadTreeNode *RunPhysics(struct Level *lvl, float *pos, float *vec, float TimeToGo, struct Animation *PAnim) { struct QuadTreeNode *CollTree = GetCollisionNode(lvl, pos, vec); static float TimeAccumulator = 0; float Step; TimeAccumulator += TimeToGo; Step = fmod(TimeAccumulator, TIME_STEP); if(Step >= 0.01f) { TimeAccumulator -= Step; CollTree = DoContinuousPhysics(lvl, CollTree, pos, vec, Step, PAnim); } while(TimeAccumulator > 0) { vec[1] += 0.1f; vec[0] *= 0.997f; vec[1] *= 0.997f; CollTree = DoContinuousPhysics(lvl, CollTree, pos, vec, TimeToGo, PAnim); TimeAccumulator -= TIME_STEP; } return CollTree; }*/ struct QuadTreeNode *RunPhysics(struct Level *lvl, float *pos, float *vec, float TimeToGo, struct Animation *PAnim) { float MoveVec[2]; struct QuadTreeNode *CollTree = GetCollisionNode(lvl, pos, vec); float CollTime, NCollTime; float End[2], ColPoint[2]; void *CollPtr; float d1, d2; struct Edge *E; float r; int Contact; struct Container *EPtr, *FirstEdge; /* Step 1: apply gravity */ vec[1] += 0.1f; /* Step 2: apply atmoshperic resistance */ vec[0] *= 0.997f; vec[1] *= 0.997f; EPtr = CollTree->Contents; while (EPtr && EPtr->Type != EDGE) EPtr = EPtr->Next; FirstEdge = EPtr; /* Step 2: do collisions and reactions */ do { Contact = FALSE; /* rounding error fixup */ EPtr = FirstEdge; while (EPtr) { /* simple line test */ d1 = EPtr->Content.E->a * pos[0] + EPtr->Content.E->b * pos[1] + EPtr->Content.E->c; if (d1 >= (-0.5f) && d1 <= 0.05f && pos[0] >= EPtr->Content.E->Bounder.TL.Pos[0] && pos[0] <= EPtr->Content.E->Bounder.BR.Pos[0] && pos[1] >= EPtr->Content.E->Bounder.TL.Pos[1] && pos[1] <= EPtr->Content.E->Bounder.BR.Pos[1] ) { pos[0] += EPtr->Content.E->a * (0.05f - d1); pos[1] += EPtr->Content.E->b * (0.05f - d1); Contact = TRUE; } EPtr = EPtr->Next; } MoveVec[0] = TimeToGo * vec[0]; MoveVec[1] = TimeToGo * vec[1]; CollTime = 1.0f; End[0] = pos[0] + MoveVec[0]; End[1] = pos[1] + MoveVec[1]; CollPtr = NULL; /* search for collisions here */ /* test 1: do we hit the edge of this collision tree node? */ if (End[0] > CollTree->Bounder.BR.Pos[0]) { NCollTime = (End[0] - CollTree->Bounder.BR.Pos[0]) / MoveVec[0]; if (NCollTime < CollTime) { CollTime = NCollTime; CollPtr = (void *)CollTree; } } if (End[0] < CollTree->Bounder.TL.Pos[0]) { NCollTime = (End[0] - CollTree->Bounder.TL.Pos[0]) / MoveVec[0]; if (NCollTime < CollTime) { CollTime = NCollTime; CollPtr = (void *)CollTree; } } if (End[1] > CollTree->Bounder.BR.Pos[1]) { NCollTime = (End[1] - CollTree->Bounder.BR.Pos[1]) / MoveVec[1]; if (NCollTime < CollTime) { CollTime = NCollTime; CollPtr = (void *)CollTree; } } if (End[1] < CollTree->Bounder.TL.Pos[1]) { NCollTime = (End[1] - CollTree->Bounder.TL.Pos[1]) / MoveVec[1]; if (NCollTime < CollTime) { CollTime = NCollTime; CollPtr = (void *)CollTree; } } /* test 3: do we hit any of the edges contained in the tree? */ EPtr = FirstEdge; while (EPtr) { /* simple line test */ d1 = EPtr->Content.E->a * pos[0] + EPtr->Content.E->b * pos[1] + EPtr->Content.E->c; d2 = EPtr->Content.E->a * End[0] + EPtr->Content.E->b * End[1] + EPtr->Content.E->c; if ((d1 >= (-0.05f)) && (d2 < 0)) { NCollTime = d1 / (d1 - d2); ColPoint[0] = pos[0] + NCollTime * MoveVec[0]; ColPoint[1] = pos[1] + NCollTime * MoveVec[1]; if (ColPoint[0] >= EPtr->Content.E->Bounder.TL.Pos[0] && ColPoint[0] <= EPtr->Content.E->Bounder.BR.Pos[0] && ColPoint[1] >= EPtr->Content.E->Bounder.TL.Pos[1] && ColPoint[1] <= EPtr->Content.E->Bounder.BR.Pos[1] ) { CollTime = NCollTime; CollPtr = (void *)EPtr; } } /* move to next edge */ EPtr = EPtr->Next; } /* advance - apply motion and resulting friction here! */ pos[0] += MoveVec[0] * CollTime; pos[1] += MoveVec[1] * CollTime; if (!Contact) AdvanceAnimation(PAnim, 0, FALSE); /* fix up */ if (CollPtr) { if (CollPtr == (void *)CollTree) { CollTree = GetCollisionNode(lvl, pos, vec); EPtr = CollTree->Contents; while (EPtr && EPtr->Type != EDGE) EPtr = EPtr->Next; FirstEdge = EPtr; } else { /* edge collision */ E = ((struct Container *)CollPtr)->Content.E; r = FixUp(vec, E->a, E->b); SetAngle(E->a, E->b, &pos[2], (fabs(vec[0] * E->b - vec[1] * E->a) > 0.5f)); AdvanceAnimation(PAnim, (vec[0] * E->b - vec[1] * E->a) * ((KeyFlags & KEYFLAG_FLIP) ? 1.0f : -1.0f), TRUE); /* apply friction */ DoFriction(r, E, vec); } } else if (!Contact) { /* check if currently in contact with any surface. If not then do empty space movement */ if (KeyFlags & KEYFLAG_LEFT) { vec[0] -= 0.05f; KeyFlags |= KEYFLAG_FLIP; } if (KeyFlags & KEYFLAG_RIGHT) { vec[0] += 0.05f; KeyFlags &= ~KEYFLAG_FLIP; } if (pos[2] > 0) { pos[2] -= TimeToGo * CollTime * 0.03f; if (pos[2] < 0) pos[2] = 0; } if (pos[2] < 0) { pos[2] += TimeToGo * CollTime * 0.03f; if (pos[2] > 0) pos[2] = 0; } } /* reduce time & continue */ TimeToGo -= TimeToGo * CollTime; } while (TimeToGo > 0.01f); return CollTree; } allegro4.4-4.4.2/demos/skater/source/quadtree.c000066400000000000000000000526641173507505700213010ustar00rootroot00000000000000/* QuadTree.c ========== A quad tree is a hierarchical tree based structure. For further information on quad trees see http://en.wikipedia.org/wiki/Quadtree In this code, every node has a pointer named 'Children' which is either NULL or points to an array of four children. The children are indexed as follows: 0 - top left 1 - top right 2 - bottom left 3 - bottom right This allows indexing according to a simple bitwise calculation: childnum = 0; if(x > midpoint) childnum |= 1; if(y > midpoint) childnum |= 2; The QuadTreeNode structs look like this: struct QuadTreeNode { struct BoundingBox Bounder; int NumContents; struct Container *Contents; struct QuadTreeNode *Children; }; BoundingBox is the axis aligned bounding box for the region of space covered, NumContents is a count of the number of items contained in the linked list 'Contents'. It is redundant but convenient. 'Children' is as explained above - NULL if this is a leaf node, otherwise a pointer to an array of four QuadTreeNode structs that subdivide the area of this node. */ #include "../include/level.h" /* CentreX and CentreY are macros that evaluate to the centre point of the bounding box b */ #define CentreX(b) (((b)->TL.Pos[0]+(b)->BR.Pos[0]) * 0.5f) #define CentreY(b) (((b)->TL.Pos[1]+(b)->BR.Pos[1]) * 0.5f) #define ERROR_BOUNDARY 2 /* GetChild. Returns the child index for a point (qx, qy) in the bounding box b. Uses the logic expressed in the comments at the top of this file */ int GetChild(struct BoundingBox *b, float qx, float qy) { int ret = 0; if (qx > CentreX(b)) ret |= 1; if (qy > CentreY(b)) ret |= 2; return ret; } /* Get[X1/2]/[Y1/2] - if passed a child id and the bounding box of the parent, these return the corresponding co-ordinate of the child */ float GetX1(int child, struct BoundingBox *b) { return (child & 1) ? CentreX(b) : b->TL.Pos[0]; } float GetX2(int child, struct BoundingBox *b) { return (child & 1) ? b->BR.Pos[0] : CentreX(b); } float GetY1(int child, struct BoundingBox *b) { return (child & 2) ? CentreY(b) : b->TL.Pos[1]; } float GetY2(int child, struct BoundingBox *b) { return (child & 2) ? b->BR.Pos[1] : CentreY(b); } /* ToggleChildPtr[X/Y] relate to the way movement is handled by the physics code. They use a continuous time method (see Physics.c for more details), which means that they need to be able to calculate when a travelling point will leave a quad tree node. Because there may be rounding errors close to the border, the function for obtaining collision edges inspects velocity to determine which child a point near the boundary is actually interested in. For that purpose, ToggleChildPtr[X/Y] affect which child is looked at according to velocity. If the point is heading right it wants the right hand side child, if it is heading down it wants the lower child, etc. */ int ToggleChildPtrY(float yvec, int oldchild) { if (((yvec > 0) && (oldchild & 2)) || ((yvec < 0) && !(oldchild & 2)) ) oldchild ^= 2; return oldchild; } int ToggleChildPtrX(float xvec, int oldchild) { if (((xvec > 0) && (oldchild & 1)) || ((xvec < 0) && !(oldchild & 1)) ) oldchild ^= 1; return oldchild; } /* Separated does a test on two bounding boxes to determine whether they overlap - returning TRUE if they don't and FALSE if they do. It achieves this using the 'separating planes' algorithm, which is a general case test that can be expressed very simply for boxes. If the leftmost point of one box is to the right of the rightmost point of the other then they must not overlap. Ditto for the topmost point of one versus the bottommost of the other and all variations on those tests. These tests will catch all possible ways in which two boxes DO NOT overlap. Therefore the only possible conclusion if they all fail is that the boxes DO overlap. A small error boundary in which non-overlapping objects are returned as overlapping anyway is coded here so that we don't get rounding problems when doing collisions near the edge of a node */ int Separated(struct BoundingBox *a, struct BoundingBox *b) { if (a->TL.Pos[0] - ERROR_BOUNDARY > b->BR.Pos[0]) return TRUE; if (a->TL.Pos[1] - ERROR_BOUNDARY > b->BR.Pos[1]) return TRUE; if (b->TL.Pos[0] - ERROR_BOUNDARY > a->BR.Pos[0]) return TRUE; if (b->TL.Pos[1] - ERROR_BOUNDARY > a->BR.Pos[1]) return TRUE; return FALSE; } /* GENERIC QUAD TREE FUNCTIONS */ /* SetupQuadTree just initiates a QuadTreeNode struct, filling its bounding box appropriately and setting it up to have no contents and no children */ void SetupQuadTree(struct QuadTreeNode *Tree, int x1, int y1, int x2, int y2) { Tree->Bounder.TL.Pos[0] = x1; Tree->Bounder.TL.Pos[1] = y1; Tree->Bounder.BR.Pos[0] = x2; Tree->Bounder.BR.Pos[1] = y2; Tree->NumContents = 0; Tree->Contents = Tree->PostContents = NULL; Tree->Children = NULL; } /* FreeQuadTree frees all the memory malloc'd to a QuadTree. It calls itself recursively for any children */ void FreeQuadTree(struct QuadTreeNode *Tree) { int c; struct Container *CNext; /* if this node has children then free them */ if (Tree->Children) { c = 4; while (c--) FreeQuadTree(&Tree->Children[c]); free((void *)Tree->Children); Tree->Children = NULL; } /* free all edge containers stored here */ while (Tree->Contents) { CNext = Tree->Contents->Next; free((void *)Tree->Contents); Tree->Contents = CNext; } } /* AddContent adds new content to a QuadTreeNode. The basic steps are these: 1. does the new content fit into the space covered by this node? If not, reject it 2. is this node subdivided? If so then pass the new content to the children to deal with. If not then insert at this node 3. if inserted at this node, have we now hit the limit for items storable at any node? If so, subdivide and pass all contents that were stored here to the children */ void AddContent(struct QuadTreeNode *Tree, struct Container *NewContent, int divider) { int c; struct Container *CPtr, *Next; /* First check: does the refered new content actually overlap with this node? If not, do nothing NB: this code explicitly checks the bounding box of an 'edge' held in NewContent, even though it may hold an edge, triangle or object. This is fine because we've set up our structs so that the bounding box information is at the same location regardless */ if (Separated(&NewContent->Content.E->Bounder, &Tree->Bounder)) return; /* Second check: has this node been subdivided? If so, pass on for children to deal with */ if (Tree->Children) { c = 4; while (c--) AddContent(&Tree->Children[c], NewContent, divider); } else { /* If we're here, then the edge really does need to be added to the current node, so do that */ Tree->NumContents++; CPtr = Tree->Contents; Tree->Contents = (struct Container *)malloc(sizeof(struct Container)); Tree->Contents->Content = NewContent->Content; Tree->Contents->Type = NewContent->Type; Tree->Contents->Next = CPtr; /* Now check if we've hit the maximum content count for this node. If so, subdivide */ if ((Tree->NumContents == divider) && ((Tree->Bounder.BR.Pos[0] - Tree->Bounder.TL.Pos[0]) > SCREEN_W) && ((Tree->Bounder.BR.Pos[1] - Tree->Bounder.TL.Pos[1]) > SCREEN_H)) { /* allocate new memory and set up structures */ Tree->Children = (struct QuadTreeNode *)malloc(sizeof(struct QuadTreeNode) * 4); c = 4; while (c--) SetupQuadTree(&Tree->Children[c], GetX1(c, &Tree->Bounder), GetY1(c, &Tree-> Bounder), GetX2(c, &Tree->Bounder), GetY2(c, &Tree->Bounder)); /* redistribute contents currently stored here */ CPtr = Tree->Contents; while (CPtr) { Next = CPtr->Next; c = 4; while (c--) AddContent(&Tree->Children[c], CPtr, divider); free(CPtr); CPtr = Next; } Tree->Contents = NULL; } } } /* STUFF FOR DEALING WITH 'EDGES' */ /* GetNode returns the leaf node that a point is currently in from the edge tree, for collisions & physics */ struct QuadTreeNode *GetNode(struct QuadTreeNode *Ptr, float *pos, float *vec) { int Child; int MidX, MidY; /* continue moving down the tree if we aren't at a leaf */ while (Ptr->Children) { /* figure out which child we should prima facie be considering */ Child = GetChild(&Ptr->Bounder, pos[0], pos[1]); /* toggle child according to velocity if sufficiently near the boundary */ MidX = CentreX(&Ptr->Bounder); MidY = CentreY(&Ptr->Bounder); if (abs((int)pos[0] - MidX) < ERROR_BOUNDARY) Child = ToggleChildPtrX(vec[0], Child); if (abs((int)pos[1] - MidY) < ERROR_BOUNDARY) Child = ToggleChildPtrY(vec[1], Child); /* and now move ourselves so that we are now looking at that child */ Ptr = &Ptr->Children[Child]; } /* return the leaf node found */ return Ptr; } struct QuadTreeNode *GetCollisionNode(struct Level *lvl, float *pos, float *vec) { return GetNode(&lvl->CollisionTree, pos, vec); } struct QuadTreeNode *GetObjectNode(struct Level *lvl, float *pos, float *vec) { return GetNode(&lvl->DisplayTree, pos, vec); } /* STUFF FOR DEALING WITH 'TRIANGLES' */ /* DrawEdge is a drawing function that adds a textured edge to a triangle */ void DrawEdge(BITMAP *target, struct Triangle *tri, struct BoundingBox *ScrBounder) { V3D PolyEdges[4]; int c, c2; /* quick bounding box check - if the triangle isn't on screen then we can forget about it */ if (Separated(&tri->Bounder, ScrBounder)) return; c = 3; while (c--) { c2 = (c + 1) % 3; if (tri->EdgeFlags[c] & TRIFLAGS_EDGE) { /* We're going to use quad3d with an affine texuring mode to paint our polygon edge. In order to do that with Allegro we must fill some V3D structs. Texture u is determined according to world position so that edges that should appear to meet up do. */ PolyEdges[0].x = PolyEdges[3].x = ftofix(tri->Edges[c]->Pos[0] - ScrBounder->TL.Pos[0]); PolyEdges[0].u = PolyEdges[3].u = ftofix(tri->Edges[c]->Pos[0]); PolyEdges[0].y = ftofix(tri->Edges[c]->Pos[1] - ScrBounder->TL.Pos[1]) - itofix(tri->EdgeFlags[c] & TRIFLAGS_WIDTH); PolyEdges[3].y = ftofix(tri->Edges[c]->Pos[1] - ScrBounder->TL.Pos[1]) + itofix(tri->EdgeFlags[c] & TRIFLAGS_WIDTH); PolyEdges[1].x = PolyEdges[2].x = itofix(tri->Edges[c2]->Pos[0] - ScrBounder->TL.Pos[0]) + itofix(1); PolyEdges[1].u = PolyEdges[2].u = ftofix(tri->Edges[c2]->Pos[0]); PolyEdges[2].y = ftofix(tri->Edges[c2]->Pos[1] - ScrBounder->TL.Pos[1]) + itofix(tri->EdgeFlags[c2] & TRIFLAGS_WIDTH); PolyEdges[1].y = ftofix(tri->Edges[c2]->Pos[1] - ScrBounder->TL.Pos[1]) - itofix(tri->EdgeFlags[c2] & TRIFLAGS_WIDTH); PolyEdges[0].v = PolyEdges[1].v = 0; PolyEdges[2].v = PolyEdges[3].v = itofix(tri->Material->Edge->h); #ifdef DEMO_USE_ALLEGRO_GL /* AllegroGL doesn't support POLYTYPE_ATEX_MASK so we use transparent * drawing here. */ set_alpha_blender(); quad3d(target, POLYTYPE_ATEX_TRANS, tri->Material->Edge, &PolyEdges[0], &PolyEdges[1], &PolyEdges[2], &PolyEdges[3]); #else quad3d(target, POLYTYPE_ATEX_MASK, tri->Material->Edge, &PolyEdges[0], &PolyEdges[1], &PolyEdges[2], &PolyEdges[3]); #endif } } } /* DrawTriangle is a drawing function that draws a triangle with a textured fill */ void DrawTriangle(BITMAP *target, struct Triangle *tri, struct BoundingBox *ScrBounder) { /* quick bounding box check - if the triangle isn't on screen then we can forget about it */ if (Separated(&tri->Bounder, ScrBounder)) return; /* drawing is quickly and easily done using a patterned fill of an ordinary triangle. Notice that the pattern offset is set according to the offset of our view into the world so that it moves correctly with the triangle */ drawing_mode(DRAW_MODE_COPY_PATTERN, tri->Material->Fill, -ScrBounder->TL.Pos[0], -ScrBounder->TL.Pos[1]); triangle(target, tri->Edges[0]->Pos[0] - ScrBounder->TL.Pos[0], tri->Edges[0]->Pos[1] - ScrBounder->TL.Pos[1], tri->Edges[1]->Pos[0] - ScrBounder->TL.Pos[0], tri->Edges[1]->Pos[1] - ScrBounder->TL.Pos[1], tri->Edges[2]->Pos[0] - ScrBounder->TL.Pos[0], tri->Edges[2]->Pos[1] - ScrBounder->TL.Pos[1], 0); solid_mode(); } /* DrawObject is a drawing function that draws an object (!) */ void DrawObject(BITMAP *target, struct Object *obj, struct BoundingBox *ScrBounder) { /* quick bounding box check - if the triangle isn't on screen then we can forget about it */ if (Separated(&obj->Bounder, ScrBounder)) return; if (obj->Flags & OBJFLAGS_VISIBLE) rotate_scaled_sprite(target, obj->ObjType->Image, (int)(0.5f * (obj->Bounder.TL.Pos[0] + obj->Bounder.BR.Pos[0]) - ScrBounder->TL.Pos[0]) - (obj->ObjType->Image->w >> 1), (int)(0.5f * (obj->Bounder.TL.Pos[1] + obj->Bounder.BR.Pos[1]) - ScrBounder->TL.Pos[1]) - (obj->ObjType->Image->h >> 1), obj->Angle, ftofix((float)SCREEN_H / 480.0f)); } /* DrawTriangleTree does the 'hard' work of actually drawing the contents of a quad tree. If you've understood how the quad tree is made up and works from all the other comments in this file then it is very straightforward and easy to follow. The only point of interest here is 'framec' - an integer that identifies the current frame. The problem that necessitates it is that a single screen may cover multiple leaf nodes, and that some triangles may be present in more than one of those nodes. We don't want to expend energy drawing those triangles twice. To resolve this, every triangle keeps a note of the frame in which it was last drawn. If that frame is not this frame then it is drawn and that note is updated. The 'clever' thing about this is that it kills the overdraw without any per frame seeding of triangles. The disadvantage is that any triangle which doesn't appear on screen for exactly as long as it takes the framec integer to overflow then does will not be drawn for one frame. Assuming 100 fps and a 32bit CPU, this bug can in the unlikely situation that it does occur, only happen after approximately 1.36 years of continuous gameplay. It is therefore submitted that it shouldn't be of high concern! Calculations: 2^32 = 4,294,967,296 /100 = 4,294,967.296 seconds /60 = 715,827.883 minutes /60 = 11,930.465 hours /24 = 497.103 days /365.25 = 1.36 years */ void GetQuadTreeVisibilityList(struct QuadTreeNode *TriTree, struct Level *Lvl, struct BoundingBox *ScrBounder) { int c; /* if the view window doesn't overlap this node then do nothing */ if (Separated(&TriTree->Bounder, ScrBounder)) return; /* if this node has children, consider them instead */ if (TriTree->Children) { c = 4; while (c--) GetQuadTreeVisibilityList(&TriTree->Children[c], Lvl, ScrBounder); } else { /* otherwise, add to draw list */ TriTree->Next = Lvl->VisibleList; Lvl->VisibleList = TriTree; } } void DrawQuadTreePart(BITMAP *target, struct Level *Lvl, struct BoundingBox *ScrBounder, unsigned int framec, int PostContents) { struct Container *Thing, *TriStart; struct QuadTreeNode *Visible; /* go through each node drawing background details - objects first, then polygons, finally edges */ Visible = Lvl->VisibleList; while (Visible) { /* objects */ Thing = PostContents ? Visible->PostContents : Visible->Contents; while (Thing && Thing->Type == OBJECT) { if (Thing->Content.O->LastFrame != framec) { DrawObject(target, Thing->Content.O, ScrBounder); Thing->Content.O->LastFrame = framec; } Thing = Thing->Next; } TriStart = Thing; while (Thing) { if (Thing->Content.T->LastFrame != framec) DrawTriangle(target, Thing->Content.T, ScrBounder); Thing = Thing->Next; } /* and add edges that haven't already been drawn this frame, this time updating the note of the last frame in which this triangle was drawn */ Thing = TriStart; while (Thing) { if (Thing->Content.T->LastFrame != framec) { DrawEdge(target, Thing->Content.T, ScrBounder); Thing->Content.T->LastFrame = framec; } Thing = Thing->Next; } Visible = Visible->Next; } } void BeginQuadTreeDraw(BITMAP *target, struct Level *Lvl, struct QuadTreeNode *TriTree, struct BoundingBox *ScrBounder, unsigned int framec) { /* compile list of visible nodes */ Lvl->VisibleList = NULL; GetQuadTreeVisibilityList(TriTree, Lvl, ScrBounder); DrawQuadTreePart(target, Lvl, ScrBounder, framec, FALSE); } void EndQuadTreeDraw(BITMAP *target, struct Level *Lvl, struct BoundingBox *ScrBounder, unsigned int framec) { DrawQuadTreePart(target, Lvl, ScrBounder, framec, TRUE); } /* FUNCTIONS FOR ADDING CONTENT */ #define MAX_COLL 200 #define MAX_DISP 50 /* AddTriangle and AddEdge are both very similar indeed and just package the new triangle or edge into a 'Container' so that the AddContent function knows how to deal with them in a unified manner. */ void AddTriangle(struct Level *level, struct Triangle *NewTri) { struct Container Cont; Cont.Content.T = NewTri; Cont.Type = TRIANGLE; AddContent(&level->DisplayTree, &Cont, MAX_DISP); } void AddEdge(struct Level *level, struct Edge *NewEdge) { struct Container Cont; Cont.Content.E = NewEdge; Cont.Type = EDGE; AddContent(&level->CollisionTree, &Cont, MAX_COLL); } void AddObject(struct Level *level, struct Object *NewObject, int DisplayTree) { struct Container Cont; Cont.Content.O = NewObject; Cont.Type = OBJECT; if (DisplayTree) { if (NewObject->Flags & OBJFLAGS_VISIBLE) AddContent(&level->DisplayTree, &Cont, MAX_DISP); } else { if (NewObject->Flags & FLAGS_COLLIDABLE) AddContent(&level->CollisionTree, &Cont, MAX_COLL); } } /* OrderTree sorts the items stored within Tree so that their lists consist of all their non-objects (i.e. triangles or edges) first followed by all of their objects. */ void SplitTree(struct QuadTreeNode *Tree) { struct Container *P, *PNext; int c = 4; if (Tree->Children) { while (c--) SplitTree(&Tree->Children[c]); } else if (Tree->Contents) { P = Tree->Contents; Tree->Contents = Tree->PostContents = NULL; while (P) { PNext = P->Next; if (P->Type == OBJECT) { if (P->Content.O->Flags & FLAGS_FOREGROUND) { P->Next = Tree->PostContents; Tree->PostContents = P; } else { P->Next = Tree->Contents; Tree->Contents = P; } } else { if ((P->Content.T->EdgeFlags[0] | P->Content.T-> EdgeFlags[1] | P->Content.T->EdgeFlags[2]) & FLAGS_FOREGROUND) { P->Next = Tree->PostContents; Tree->PostContents = P; } else { P->Next = Tree->Contents; Tree->Contents = P; } } P = PNext; } } } void OrderTree(struct QuadTreeNode *Tree, int PostTree) { struct Container *Objects, *NonObjects, *P, *PNext, **ITree; int c = 4; if (Tree->Children) { while (c--) OrderTree(&Tree->Children[c], PostTree); } else { ITree = PostTree ? &Tree->PostContents : &Tree->Contents; if (*ITree) { /* separate object and non-oject lists */ Objects = NonObjects = NULL; P = *ITree; while (P) { PNext = P->Next; if (P->Type == OBJECT) { P->Next = Objects; Objects = P; } else { P->Next = NonObjects; NonObjects = P; } P = PNext; } /* now reintegrate lists - objects then non-objects */ *ITree = Objects; while (*ITree) ITree = &(*ITree)->Next; *ITree = NonObjects; } } } allegro4.4-4.4.2/demos/skater/source/scrshot.c000066400000000000000000000026001173507505700211350ustar00rootroot00000000000000/* Module for taking screenshots for Allegro games - implementation. Written by Miran Amon. */ #include #include "../include/scrshot.h" void next_screenshot(SCREENSHOT * ss) { char buf[64]; ss->counter++; if (ss->counter >= 10000) { ss->counter = 0; return; } uszprintf(buf, sizeof(buf), "%s%04d.%s", ss->name, ss->counter, ss->ext); if (exists(buf)) { next_screenshot(ss); } } SCREENSHOT *create_screenshot(char *name, char *ext) { SCREENSHOT *ret = (SCREENSHOT *) malloc(sizeof(SCREENSHOT)); ret->name = (char *)malloc(ustrsizez(name)); ustrcpy(ret->name, name); ret->ext = (char *)malloc(ustrsizez(ext)); ustrcpy(ret->ext, ext); ret->counter = -1; next_screenshot(ret); return ret; } void destroy_screenshot(SCREENSHOT * ss) { free(ss->name); ss->name = NULL; free(ss->ext); ss->ext = NULL; free(ss); ss = NULL; } void take_screenshot(SCREENSHOT * ss, BITMAP *bmp) { char buf[64]; BITMAP *bmp2 = NULL; PALETTE pal; uszprintf(buf, sizeof(buf), "%s%04d.%s", ss->name, ss->counter, ss->ext); get_palette(pal); if (is_video_bitmap(bmp)) { bmp2 = create_bitmap(SCREEN_W, SCREEN_H); blit(bmp, bmp2, 0, 0, 0, 0, SCREEN_W, SCREEN_H); save_bitmap(buf, bmp2, pal); destroy_bitmap(bmp2); } else { save_bitmap(buf, bmp, pal); } next_screenshot(ss); } allegro4.4-4.4.2/demos/skater/source/skater.c000066400000000000000000000015461173507505700207510ustar00rootroot00000000000000/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Demo game. * * By Miran Amon, Nick Davies, Elias Pschernig, Thomas Harte, * Jakub Wasilewski. * * See readme.txt for copyright information. */ #include #include "../include/framewk.h" int main(void) { if (init_framework() != DEMO_OK) { return 1; } run_framework(); shutdown_framework(); return 0; } END_OF_MAIN() allegro4.4-4.4.2/demos/skater/source/token.c000066400000000000000000000142371173507505700206010ustar00rootroot00000000000000#include #include #include #include "../include/token.h" /* declarations of these variables - see token.h for comments on their meaning */ int Error, Lines; char ErrorText[1024]; struct Tok Token; PACKFILE *input = NULL; static int my_ungetc_c = -1; /* OVERARCHING NOTES ON THE LEVEL PARSER ------------------------------------- We're using something a lot like a recursive descent parser here except that it never actually needs to recurse. It is typified by knowing a bunch of tokens (which are not necessarily individual characters but may be lumps of characters that make sense together - e.g. 'a number' might be a recognised token and 2345 is a number) and two functions: GetToken - reads a new token from the input. ExpectToken - calls GetToken, checks if the token is the one expected and if not flags up an error. A bunch of other functions call these two to read the file input, according to what it was decided it should look like. Suppose we want a C-style list of numbers that looks like this: { 1, 2, 3, ... } Then we might write the function: ExpectToken( '{' ); while(1) { ExpectToken( number ); GetToken(); switch(token) { default: flag an error; return; case '}': return; case ',': break; } } */ /* Two macros - whitespace(v) evaluates to non-zero if 'v' is a character considered to be whitespace (i.e. a space, newline, carriage return or tab) breaker(v) evaluates to non-zero if 'v' is a character that indicates one of the longer tokens (e.g. a number) is over */ #define whitespace(v) ((v == ' ') || (v == '\r') || (v == '\n') || (v == '\t')) #define breaker(v) (whitespace(v) || (v == '{') || (v == '}') || (v == ',')) /* my_fgetc is a direct replacement for fgetc that takes the same parameters and returns the same result but counts lines while it goes. There is a slight complication here because of the different line endings used by different operating systems. The code will accept a newline or a carriage return or both in either order. But if a series of alternating new lines and carriage returns is found then they are bundled together in pairs for line counting. E.g. \r - 1 line ending \n - 1 line ending \n\r - 1 line ending \r\n\r\n - 2 line endings \r\r - 2 line endings */ int my_fgetc(PACKFILE * f) { static int LastChar = '\0'; int r; char TestChar; if (my_ungetc_c != -1) { r = my_ungetc_c; my_ungetc_c = -1; } else r = pack_getc(f); if (r == '\n' || r == '\r') { TestChar = (r == '\n') ? '\r' : '\n'; if (LastChar != TestChar) { Lines++; LastChar = r; } else LastChar = '\0'; } else LastChar = r; return r; } /* Hackish way to ungetc a single character. */ void my_ungetc(int c) { my_ungetc_c = c; } /* GetTokenInner is the guts of GetToken - it reads characters from the input file and tokenises them */ void GetTokenInner(void) { char *Ptr = Token.Text; /* filter leading whitespace */ do { *Ptr = my_fgetc(input); } while (whitespace(*Ptr)); /* check whether the token can be recognised from the first character alone. This is possible if the token is any of the single character tokens (i.e. { } and ,) a comment or a string (i.e. begins with a quote) */ if (*Ptr == '{') { Token.Type = TK_OPENBRACE; return; } if (*Ptr == '}') { Token.Type = TK_CLOSEBRACE; return; } if (*Ptr == ',') { Token.Type = TK_COMMA; return; } if (*Ptr == '\"') { Token.Type = TK_STRING; /* if this is a string then read until EOF or the next quote. In ensuring that we don't overrun the available string storage in the Tok struct an extra potential error condition is invoked */ do { *Ptr++ = my_fgetc(input); } while (Ptr[-1] != '\"' && !pack_feof(input) && (Ptr - Token.Text) < 256); Ptr[-1] = '\0'; if (pack_feof(input) || (strlen(Token.Text) == 255)) Error = 1; return; } if (*Ptr == '#') { Token.Type = TK_COMMENT; /* comments run to end of line, so find the next \r or \n */ do { *Ptr++ = my_fgetc(input); } while (Ptr[-1] != '\r' && Ptr[-1] != '\n'); Ptr[-1] = '\0'; return; } Ptr++; *Ptr = '\0'; /* if we're here, the token was not recognisable from the first character alone, meaning it is either a number or ill formed */ while (1) { char newc = my_fgetc(input); /* read new character */ /* check if this is a terminator or we have hit end of file as in either circumstance we should check if what we have makes a valid number */ if (breaker(newc) || pack_feof(input)) { /* check first if we have a valid integer quantity. If so fill IQuantity with that and cast to float for FQuantity */ char *eptr; my_ungetc(newc); Token.IQuantity = strtol(Token.Text, &eptr, 0); if (!*eptr) { Token.Type = TK_NUMBER; Token.FQuantity = (float)Token.IQuantity; return; } /* if not, check if we have a valid floating point quantity. If so, fill FQuantity with that and cast to int for IQuantity */ Token.FQuantity = (float)strtod(Token.Text, &eptr); if (!*eptr) { Token.Type = TK_NUMBER; Token.IQuantity = (int)Token.FQuantity; return; } /* if what we have doesn't make integer or floating point sense then this section of the file appears not to be a valid token */ Token.Type = TK_UNKNOWN; return; } *Ptr++ = newc; *Ptr = '\0'; } } /* GetToken is a wrapper for GetTokenInner that discards comments */ void GetToken(void) { while (1) { GetTokenInner(); if (Token.Type != TK_COMMENT) return; } } /* ExpectToken calls GetToken and then compares to the specified type, setting an error if the found token does not match the expected type */ void ExpectToken(enum TokenTypes Type) { GetToken(); if (Token.Type != Type) Error = 1; } allegro4.4-4.4.2/demos/skater/source/transitn.c000066400000000000000000000027751173507505700213270ustar00rootroot00000000000000#include #include "../include/global.h" #include "../include/transitn.h" TRANSITION *create_transition(GAMESTATE * from, GAMESTATE * to, float duration) { TRANSITION *t = malloc(sizeof(TRANSITION)); t->from = from; t->to = to; t->duration = duration; t->progress = 0.0f; #ifdef DEMO_USE_ALLEGRO_GL t->from_bmp = create_video_bitmap(SCREEN_W, SCREEN_H); #else t->from_bmp = create_bitmap(SCREEN_W, SCREEN_H); #endif if (from) { from->draw(t->from_bmp); } else { clear_to_color(t->from_bmp, makecol(0, 0, 0)); } #ifdef DEMO_USE_ALLEGRO_GL t->to_bmp = create_video_bitmap(SCREEN_W, SCREEN_H); #else t->to_bmp = create_bitmap(SCREEN_W, SCREEN_H); #endif if (to) { to->draw(t->to_bmp); } else { clear_to_color(t->to_bmp, makecol(0, 0, 0)); } return t; } void destroy_transition(TRANSITION * t) { if (t->from_bmp) { destroy_bitmap(t->from_bmp); t->from_bmp = NULL; } if (t->to_bmp) { destroy_bitmap(t->to_bmp); t->from_bmp = NULL; } free(t); t = NULL; } int update_transition(TRANSITION * t) { t->progress += 1.0f / logic_framerate; if (t->progress >= t->duration) { return 0; } else { return 1; } } void draw_transition(BITMAP *canvas, TRANSITION * t) { int y = (int)(t->progress * SCREEN_H / t->duration); blit(t->to_bmp, canvas, 0, SCREEN_H - y, 0, 0, SCREEN_W, y); blit(t->from_bmp, canvas, 0, 0, 0, y, SCREEN_W, SCREEN_H - y); } allegro4.4-4.4.2/demos/skater/source/tribuf.c000066400000000000000000000037301173507505700207500ustar00rootroot00000000000000#include #include "../include/defines.h" #include "../include/tribuf.h" /***************************************************************************** * Triple buffering module * *****************************************************************************/ static BITMAP *tb_page1 = NULL; static BITMAP *tb_page2 = NULL; static BITMAP *tb_page3 = NULL; static BITMAP *tb_active_page = NULL; static int tb_page = 0; static void destroy(void) { if (tb_page1) { destroy_bitmap(tb_page1); tb_page1 = NULL; } if (tb_page2) { destroy_bitmap(tb_page2); tb_page2 = NULL; } if (tb_page3) { destroy_bitmap(tb_page3); tb_page3 = NULL; } tb_active_page = NULL; tb_page = 0; } static int create(void) { destroy(); if (!(gfx_capabilities & GFX_CAN_TRIPLE_BUFFER)) { enable_triple_buffer(); } if (!(gfx_capabilities & GFX_CAN_TRIPLE_BUFFER)) { return DEMO_ERROR_TRIPLEBUFFER; } tb_page1 = create_video_bitmap(SCREEN_W, SCREEN_H); tb_page2 = create_video_bitmap(SCREEN_W, SCREEN_H); tb_page3 = create_video_bitmap(SCREEN_W, SCREEN_H); if ((!tb_page1) || (!tb_page2) || (!tb_page3)) { destroy(); return DEMO_ERROR_VIDEOMEMORY; } tb_active_page = tb_page1; return DEMO_OK; } static void draw(void) { do { } while (poll_scroll()); request_video_bitmap(tb_active_page); switch (tb_page) { case 0: tb_page = 1; tb_active_page = tb_page2; break; case 1: tb_page = 2; tb_active_page = tb_page3; break; case 2: tb_page = 0; tb_active_page = tb_page1; break; } } static BITMAP *get_canvas(void) { return tb_active_page; } void select_triple_buffer(DEMO_SCREEN_UPDATE_DRIVER * driver) { driver->create = create; driver->destroy = destroy; driver->draw = draw; driver->get_canvas = get_canvas; } allegro4.4-4.4.2/demos/skater/source/virtctl.c000066400000000000000000000010461173507505700211420ustar00rootroot00000000000000#include #include #include "../include/virtctl.h" void destroy_vcontroller(VCONTROLLER * controller, const char *config_path) { if (controller == 0) { return; } /* save assignments */ if (controller->write_config != 0) { controller->write_config(controller, config_path); } /* free private data */ if (controller->private_data != 0) { free(controller->private_data); controller->private_data = 0; } /* free the actual pointer */ free(controller); controller = 0; } allegro4.4-4.4.2/docs/000077500000000000000000000000001173507505700143365ustar00rootroot00000000000000allegro4.4-4.4.2/docs/CMakeLists.txt000066400000000000000000000154741173507505700171110ustar00rootroot00000000000000#-----------------------------------------------------------------------------# # # Documentation # option(WANT_DOCS "Generate documentation" on) if(NOT WANT_DOCS OR CMAKE_CROSSCOMPILING) return() endif() set(DOCDIR "doc" CACHE STRING "Install docs into $DOCDIR/allegro-$VERSION") set(ACTUAL_DOC_DIR "${DOCDIR}/allegro-${ALLEGRO_VERSION}") add_executable(makedoc src/makedoc/makedoc.c src/makedoc/makehtml.c src/makedoc/makemisc.c src/makedoc/maketxt.c src/makedoc/makertf.c src/makedoc/maketexi.c src/makedoc/makeman.c src/makedoc/makechm.c src/makedoc/makedevh.c src/makedoc/makesci.c ) file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/build ${CMAKE_CURRENT_BINARY_DIR}/txt ${CMAKE_CURRENT_BINARY_DIR}/html ${CMAKE_CURRENT_BINARY_DIR}/rtf ${CMAKE_CURRENT_BINARY_DIR}/scite ${CMAKE_CURRENT_BINARY_DIR}/texi ${CMAKE_CURRENT_BINARY_DIR}/info ${CMAKE_CURRENT_BINARY_DIR}/man ) set(DOC_SRCS src/abi._tx src/addons._tx src/ahack._tx src/allegro._tx src/api._tx src/changes._tx src/const._tx src/dat2c._tx src/dat2s._tx src/datafile._tx src/dat._tx src/faq._tx src/grabber._tx src/help._tx src/index._tx src/license._tx src/makedoc._tx src/mistakes._tx src/packfile._tx src/readme._tx src/thanks._tx src/build/cmake._tx src/build/linux._tx src/build/macosx._tx src/build/mingw32._tx src/build/msvc._tx src/build/unix._tx ) set(all_docs) foreach(page ${DOC_SRCS}) string(REGEX MATCH "[^/]*._tx" basename ${page}) string(REPLACE "._tx" "" basename ${basename}) set(page ${CMAKE_CURRENT_SOURCE_DIR}/${page}) if(${page} MATCHES "/build/") set(txt_out ${CMAKE_CURRENT_BINARY_DIR}/build/${basename}.txt) set(html_out ${CMAKE_CURRENT_BINARY_DIR}/build/${basename}.html) else() set(txt_out ${CMAKE_CURRENT_BINARY_DIR}/txt/${basename}.txt) set(html_out ${CMAKE_CURRENT_BINARY_DIR}/html/${basename}.html) endif() add_custom_command( OUTPUT ${txt_out} DEPENDS makedoc ${page} COMMAND makedoc -ascii ${txt_out} ${page} ) add_custom_command( OUTPUT ${html_out} DEPENDS makedoc ${page} COMMAND makedoc -html ${html_out} ${page} ) list(APPEND all_docs ${txt_out} ${html_out}) endforeach() macro(ascii_file out src) # You'll have to ask Shawn why it was like this... add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${out} DEPENDS makedoc ${CMAKE_CURRENT_SOURCE_DIR}/${src} COMMAND makedoc ${ARGN} -ascii ${CMAKE_CURRENT_BINARY_DIR}/${out} ${CMAKE_CURRENT_SOURCE_DIR}/${src} ) list(APPEND all_docs ${CMAKE_CURRENT_BINARY_DIR}/${out}) endmacro() # Files in the root directory. ascii_file(AUTHORS src/thanks._tx -part) ascii_file(THANKS src/thanks._tx -part) ascii_file(CHANGES src/changes._tx) ascii_file(readme.txt src/readme._tx) if(UNIX) set(TEXT_FILES_TO_INSTALL ${CMAKE_CURRENT_BINARY_DIR}/AUTHORS ${CMAKE_CURRENT_BINARY_DIR}/THANKS ${CMAKE_CURRENT_BINARY_DIR}/CHANGES ${CMAKE_CURRENT_BINARY_DIR}/readme.txt ${CMAKE_CURRENT_BINARY_DIR}/txt/abi.txt ${CMAKE_CURRENT_BINARY_DIR}/txt/addons.txt ${CMAKE_CURRENT_BINARY_DIR}/txt/ahack.txt ${CMAKE_CURRENT_BINARY_DIR}/txt/allegro.txt ${CMAKE_CURRENT_BINARY_DIR}/txt/api.txt ${CMAKE_CURRENT_BINARY_DIR}/txt/const.txt ${CMAKE_CURRENT_BINARY_DIR}/txt/dat.txt ${CMAKE_CURRENT_BINARY_DIR}/txt/dat2c.txt ${CMAKE_CURRENT_BINARY_DIR}/txt/dat2s.txt ${CMAKE_CURRENT_BINARY_DIR}/txt/datafile.txt ${CMAKE_CURRENT_BINARY_DIR}/txt/faq.txt ${CMAKE_CURRENT_BINARY_DIR}/txt/grabber.txt ${CMAKE_CURRENT_BINARY_DIR}/txt/help.txt ${CMAKE_CURRENT_BINARY_DIR}/txt/license.txt ${CMAKE_CURRENT_BINARY_DIR}/txt/makedoc.txt ${CMAKE_CURRENT_BINARY_DIR}/txt/mistakes.txt ${CMAKE_CURRENT_BINARY_DIR}/txt/packfile.txt ) install(FILES ${TEXT_FILES_TO_INSTALL} DESTINATION ${ACTUAL_DOC_DIR} ) file(GLOB HTML_DOCS ${CMAKE_CURRENT_BINARY_DIR}/html/*.html ${CMAKE_CURRENT_BINARY_DIR}/html/*.css ) install(FILES ${HTML_DOCS} DESTINATION ${ACTUAL_DOC_DIR}/html ) endif(UNIX) #-----------------------------------------------------------------------------# # # Man pages # option(WANT_DOCS_MAN "Generate man pages" on) set(MANDIR "man" CACHE STRING "Install man pages into this directory") if(WANT_DOCS_MAN) set(man_out ${CMAKE_CURRENT_BINARY_DIR}/man/allegro_init.3) set(man_src ${CMAKE_CURRENT_SOURCE_DIR}/src/allegro._tx) add_custom_command( OUTPUT ${man_out} DEPENDS makedoc ${man_src} COMMAND makedoc -man ${man_out} ${man_src} ) list(APPEND all_docs ${man_out}) # I'm assuming only Unix users want man pages installed, but djgpp supports # man pages to so this might need to change. if(UNIX) file(GLOB MAN_PAGES ${CMAKE_CURRENT_BINARY_DIR}/man/*.3) install(FILES ${MAN_PAGES} DESTINATION ${MANDIR}/man3 ) endif(UNIX) endif(WANT_DOCS_MAN) #-----------------------------------------------------------------------------# # # Info # option(WANT_DOCS_INFO "Generate Info document" on) find_program(MAKEINFO NAMES makeinfo) mark_as_advanced(MAKEINFO) set(INFODIR "info" CACHE STRING "Install Info docs into this directory") if(WANT_DOCS_INFO AND MAKEINFO) set(texi_out ${CMAKE_CURRENT_BINARY_DIR}/texi/allegro.texi) set(info_out ${CMAKE_CURRENT_BINARY_DIR}/info/allegro.info) set(info_src ${CMAKE_CURRENT_SOURCE_DIR}/src/allegro._tx) add_custom_command( OUTPUT ${texi_out} DEPENDS makedoc ${info_src} COMMAND makedoc -texi ${texi_out} ${info_src} ) add_custom_command( OUTPUT ${info_out} DEPENDS ${texi_out} COMMAND ${MAKEINFO} --no-split -o ${info_out} ${texi_out} ) list(APPEND all_docs ${info_out}) if(UNIX) install(FILES ${info_out} DESTINATION ${INFODIR} ) endif(UNIX) endif(WANT_DOCS_INFO AND MAKEINFO) #-----------------------------------------------------------------------------# # # Scite # set(scite_out ${CMAKE_CURRENT_BINARY_DIR}/scite/allegro.api) set(scite_src ${CMAKE_CURRENT_SOURCE_DIR}/src/allegro._tx) add_custom_command( OUTPUT ${scite_out} DEPENDS makedoc ${page} COMMAND makedoc -scite ${scite_out} ${scite_src} ) list(APPEND all_docs ${scite_out}) #-----------------------------------------------------------------------------# add_custom_target(docs ALL DEPENDS ${all_docs}) #-----------------------------------------------------------------------------# # vim: set sts=4 sw=4 et: allegro4.4-4.4.2/docs/build/000077500000000000000000000000001173507505700154355ustar00rootroot00000000000000allegro4.4-4.4.2/docs/build/cmake.html000066400000000000000000000150661173507505700174130ustar00rootroot00000000000000 Building Allegro with CMake


Building Allegro 4.4 with CMake

CMake is a cross-platform tool that can generate native makefiles and workspaces that can be used in the compiler environment of your choice. Allegro 4.4 uses CMake as its build system. The process is essentially the same for all compilers. You will need CMake 2.6 or later. The CMake web site is http://www.cmake.org/.

  1. Create a temporary directory to build in. This is optional but recommended. If something goes wrong you can delete the build directory and try again.

    $ mkdir Build

    $ cd Build

  2. Run CMake in the build directory. This will detect your compiler environment and generate makefiles or workspaces for you. You may pass some options to customise the build (see later), but the defaults should be fine. You may need to tell CMake which type of files it should generate, using the -G option. You can call CMake using the --help option to see a list of available generators.

    Examples (you only need one):

    $ cmake ..

    $ cmake -G "MinGW Makefiles" ..

    On Unix/Mac you can use `ccmake` which will present you with a console program to adjust the options. On Windows you can use `cmake-gui` instead (it should be listed in the Start menu or on the desktop).

    If you are missing any dependencies, CMake will tell you at this point. You can continue without building all of the addons, or install the dependencies and retry. You may need to delete the `CMakeCache.txt` file first.

  3. Use the generated makefiles or workspaces to build Allegro. If using makefiles, type `make` or `mingw32-make`. If using workspaces, open them in your IDE. If using Xcode, you can use `xcodebuild` from the command-line or the IDE.

  4. Optionally install the libraries and header files to your system.

    $ make install

    DESTDIR is supported, e.g.

    $ make install DESTDIR=/tmp/package-allegro


Build options

Here are some build options you may be interested in. You can set them on the command line like so, or using one of the front ends:

$ cmake -DCMAKE_BUILD_TYPE=Debug ..

CMAKE_BUILD_TYPE (default: RelWithDebInfo)
Selects release, debug or profiling configurations. Valid values are: Release, Debug, RelWithDebInfo, MinSizeRel, Profile.

If you are installing multiple configurations in a row, we recommend installing the Release or RelWithDebInfo configuration last, so that the installed allegro-config script will default to that configuration.

SHARED (default: on)
Whether to build the main Allegro library as a shared library (DLL) or as a static library. Addon libraries are always built as static libraries, for simplicity.

CMAKE_INSTALL_PREFIX (e.g. /usr/local)
Where to install the library and header files.

WANT_<addon> (default: on)
Whether you want to build/install each particular addon.

WANT_EXAMPLES (default: off)
Whether you want the specified addon's example programs to be built.

WANT_FRAMEWORKS (default: off)
On Mac OS X, whether to build and install frameworks instead of Unix-style shared libraries.

If you want both kinds, you will need to run cmake twice and install twice.

WANT_EMBED (default: on)
If building frameworks, whether to build embedded or non-embedded frameworks. An application bundle that links against an embedded framework will first search for the framework within the application bundle, then fall back to system paths.

FRAMEWORK_INSTALL_PREFIX
Where to install frameworks.

CMAKE_OSX_ARCHITECTURES
You may set this to a semicolon-separated list of the architectures to compile for, to produce universal binaries, e.g. "i386;ppc".


Dependencies

Many of the addons make use of additional libraries. They are not required to build Allegro, but functionality may be disabled if they are not present.

Windows users may find some precompiled binaries from http://gnuwin32.sourceforge.net/. You need to get the bin and lib packages. The bin packages contain DLLs, and the lib packages contain the headers and import libraries.

Mac users may find some dependencies in Fink or MacPorts. http://www.finkproject.org/ and http://www.macports.org/

Linux users likely have all the dependencies already. If your distribution uses separate development packages, they will need to be installed. The packages are probably named *-dev or *-devel.


Platform-specific information

Please see the other files in the docs/build directory for additional information specific to each platform. allegro4.4-4.4.2/docs/build/cmake.txt000066400000000000000000000131131173507505700172550ustar00rootroot00000000000000 ========================================================= ============ Building Allegro 4.4 with CMake ============ ========================================================= CMake is a cross-platform tool that can generate native makefiles and workspaces that can be used in the compiler environment of your choice. Allegro 4.4 uses CMake as its build system. The process is essentially the same for all compilers. You will need CMake 2.6 or later. The CMake web site is http://www.cmake.org/. Create a temporary directory to build in. This is optional but recommended. If something goes wrong you can delete the build directory and try again. $ mkdir Build $ cd Build Run CMake in the build directory. This will detect your compiler environment and generate makefiles or workspaces for you. You may pass some options to customise the build (see later), but the defaults should be fine. You may need to tell CMake which type of files it should generate, using the -G option. You can call CMake using the --help option to see a list of available generators. Examples (you only need one): $ cmake .. $ cmake -G "MinGW Makefiles" .. On Unix/Mac you can use `ccmake` which will present you with a console program to adjust the options. On Windows you can use `cmake-gui` instead (it should be listed in the Start menu or on the desktop). If you are missing any dependencies, CMake will tell you at this point. You can continue without building all of the addons, or install the dependencies and retry. You may need to delete the `CMakeCache.txt` file first. Use the generated makefiles or workspaces to build Allegro. If using makefiles, type `make` or `mingw32-make`. If using workspaces, open them in your IDE. If using Xcode, you can use `xcodebuild` from the command-line or the IDE. Optionally install the libraries and header files to your system. $ make install DESTDIR is supported, e.g. $ make install DESTDIR=/tmp/package-allegro ======================================= ============ Build options ============ ======================================= Here are some build options you may be interested in. You can set them on the command line like so, or using one of the front ends: $ cmake -DCMAKE_BUILD_TYPE=Debug .. CMAKE_BUILD_TYPE (default: RelWithDebInfo) Selects release, debug or profiling configurations. Valid values are: Release, Debug, RelWithDebInfo, MinSizeRel, Profile. If you are installing multiple configurations in a row, we recommend installing the Release or RelWithDebInfo configuration last, so that the installed allegro-config script will default to that configuration. SHARED (default: on) Whether to build the main Allegro library as a shared library (DLL) or as a static library. Addon libraries are always built as static libraries, for simplicity. CMAKE_INSTALL_PREFIX (e.g. /usr/local) Where to install the library and header files. WANT_ (default: on) Whether you want to build/install each particular addon. WANT_EXAMPLES (default: off) Whether you want the specified addon's example programs to be built. WANT_FRAMEWORKS (default: off) On Mac OS X, whether to build and install frameworks instead of Unix-style shared libraries. If you want both kinds, you will need to run cmake twice and install twice. WANT_EMBED (default: on) If building frameworks, whether to build embedded or non-embedded frameworks. An application bundle that links against an embedded framework will first search for the framework within the application bundle, then fall back to system paths. FRAMEWORK_INSTALL_PREFIX Where to install frameworks. CMAKE_OSX_ARCHITECTURES You may set this to a semicolon-separated list of the architectures to compile for, to produce universal binaries, e.g. "i386;ppc". ====================================== ============ Dependencies ============ ====================================== Many of the addons make use of additional libraries. They are not required to build Allegro, but functionality may be disabled if they are not present. Windows users may find some precompiled binaries from http://gnuwin32.sourceforge.net/. You need to get the bin and lib packages. The bin packages contain DLLs, and the lib packages contain the headers and import libraries. Mac users may find some dependencies in Fink or MacPorts. http://www.finkproject.org/ and http://www.macports.org/ Linux users likely have all the dependencies already. If your distribution uses separate development packages, they will need to be installed. The packages are probably named *-dev or *-devel. OpenGL is required for AllegroGL. libpng and zlib, for PNG image support. These are used by loadpng. Home page: http://www.libpng.org/pub/png/ Windows binaries: http://gnuwin32.sourceforge.net/packages/libpng.htm Ogg Vorbis, a free lossy audio format. (libogg, libvorbis, libvorbisfile) This is used by logg. Home page: http://www.vorbis.com/ jpgalleg does not require any additional libraries. ======================================================= ============ Platform-specific information ============ ======================================================= Please see the other files in the docs/build directory for additional information specific to each platform. allegro4.4-4.4.2/docs/build/linux.html000066400000000000000000000170551173507505700174720ustar00rootroot00000000000000 Allegro Linux-specific information

     ______   ___    ___
    /\  _  \ /\_ \  /\_ \
    \ \ \L\ \\//\ \ \//\ \      __     __   _ __   ___ 
     \ \  __ \ \ \ \  \ \ \   /'__`\ /'_ `\/\`'__\/ __`\
      \ \ \/\ \ \_\ \_ \_\ \_/\  __//\ \L\ \ \ \//\ \L\ \
       \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
        \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
                                       /\____/
                                       \_/__/


                 Linux-specific information.

         See readme.txt for a more general overview.

   Also see docs/build/unix.txt for general Unix information.


General notes

On Linux you have two different system drivers -- one for running using X, and one for running without X. For information on the X version, and instructions telling how to install Allegro and compile your programs on a Unix system, see docs/build/unix.txt. This file only describes the Linux console routines.

Normally the X version is used in preference to the console version, if an X server is contactable (this means that your programs will use X if you launch them from inside X, and otherwise use the console).

Unless you have specific needs, we recommend using the X version. The Linux console port is not enabled by default. It never worked that well and there is no real interest in it any more. We may remove it in a future release.


Installing Allegro

See docs/build/unix.txt: this process is identical for the console and X versions.

You must set the CMake option WANT_LINUX_CONSOLE to enable the console version, as it is not built by default.


Using Allegro

Some parts of Linux console Allegro need root privileges. Others don't. Specifically, the VGA and mode-X graphics drivers do. The fbcon driver doesn't. Also, if you intend to run a program from something which isn't a VT (e.g. an xterm (but not using the X version), a remote login, a screen session) then you need to either own a (free) console numbered from 1 to 15 or to have root privileges.

If you want a program to run with privileges even though the user running it is not root, make root own the binary and set the suid bit:

      # chown root.allegro exhello
      # chmod 4770 exhello
That makes the executable be owned by root and group `allegro'. It's readable, writable and executable by root and people in that group. Also, when it runs, it has root privileges. For that reason, it's not executable by the general public. Put trusted users into group `allegro'.

You might prefer to use `4750' instead of `4770' -- then people in the group cannot write to the binary.

Allegro will drop the privileges almost immediately after initialisation, using `seteuid'. This means that you can still get the permissions back later on. Allegro needs to be able to regain the privileges if you intend to call `allegro_init' again in the future. If this isn't the case, you can completely give up the privileges using `setuid(getuid());' -- then they are lost for good.

Security note: If you don't do this, any buffer overflows are a severe security problem. In any case, you should take great care when allowing random people to execute third-party programs suid root.

If, as root, you run `make suid', it will do this to all of the programs generated -- the demo game, the examples, the tests, etc.


Notes on drivers

This section contains Linux-specific notes on the drivers available.

System:
On initialisation, Allegro will try to get a certain amount of control over the console. This doesn't generally require root privileges, but if the program isn't being run from a plain VC (e.g. it's running from within X or screen), Allegro must try to allocate a spare VC and move the program to it. This requires a free console we can read from and write to; unless the user has allocated some, we need to be root here.

Display switching is possible; all of Allegro's modes are supported. The default is SWITCH_PAUSE. SWITCH_BACKGROUND will only work if the application takes special precautions.

Graphics:
Linux Allegro supports standard VGA by direct writes to the video card. You need root privileges for this to work.

It also supports fbcon, for which you do not need privileges, but you do need a recent kernel, correctly configured.

The SVGAlib driver should be fairly stable and fast now, and can use most of the video modes that SVGAlib provides. It requires root privileges if your version of SVGAlib requires them.

Note: Allegro used to have a mode-X driver, but it does not work as of 4.4.0. Someone may restore it in the future, but it's likely.

Keyboard:
The keyboard driver uses the kernel mapping tables to map scancodes to character codes and key functions, so your keyboard mapping should be fine without special configuration in the setup program.

Joystick:
To compile Allegro with joystick support you must have a 2.2.* or newer kernel, i.e. with kernel-based joystick support. Look for /usr/src/linux/include/linux/joystick.h. You shouldn't have to actually configure the kernel with joystick support though, you just need that header file.

Similarly, to run Allegro programs with joystick support you must have configured joystick support into the kernel. You also need to create the device file /dev/input/js0, if it's not already there.

See /usr/src/linux/Documentation/joystick.txt for details.

Mouse:
Currently Linux Allegro supports PS/2 and Microsoft mice directly, and other mouse types via GPM. To use GPM you must turn on its `repeater' feature, where it copies all mouse activity to the FIFO /dev/gpmdata. Edit your init scripts and add the `-R' option. The GPM driver can also be used with native Mouse Systems mice by changing the `mouse_device' variable in the config file.

When using the PS/2 Intellimouse protocol, it is necessary to explicitly put the mouse into wheel mode, which requires Allegro to have write permissions to the device.

There is an input events-based driver which reads events from /dev/input/eventN.

allegro4.4-4.4.2/docs/build/linux.txt000066400000000000000000000153121173507505700173370ustar00rootroot00000000000000 ______ ___ ___ /\ _ \ /\_ \ /\_ \ \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ /\____/ \_/__/ Linux-specific information. See readme.txt for a more general overview. Also see docs/build/unix.txt for general Unix information. ======================================= ============ General notes ============ ======================================= On Linux you have two different system drivers -- one for running using X, and one for running without X. For information on the X version, and instructions telling how to install Allegro and compile your programs on a Unix system, see docs/build/unix.txt. This file only describes the Linux console routines. Normally the X version is used in preference to the console version, if an X server is contactable (this means that your programs will use X if you launch them from inside X, and otherwise use the console). Unless you have specific needs, we recommend using the X version. The Linux console port is not enabled by default. It never worked that well and there is no real interest in it any more. We may remove it in a future release. ============================================ ============ Installing Allegro ============ ============================================ See docs/build/unix.txt: this process is identical for the console and X versions. You must set the CMake option WANT_LINUX_CONSOLE to enable the console version, as it is not built by default. ======================================= ============ Using Allegro ============ ======================================= Some parts of Linux console Allegro need root privileges. Others don't. Specifically, the VGA and mode-X graphics drivers do. The fbcon driver doesn't. Also, if you intend to run a program from something which isn't a VT (e.g. an xterm (but not using the X version), a remote login, a screen session) then you need to either own a (free) console numbered from 1 to 15 or to have root privileges. If you want a program to run with privileges even though the user running it is not root, make root own the binary and set the suid bit: # chown root.allegro exhello # chmod 4770 exhello That makes the executable be owned by root and group `allegro'. It's readable, writable and executable by root and people in that group. Also, when it runs, it has root privileges. For that reason, it's not executable by the general public. Put trusted users into group `allegro'. You might prefer to use `4750' instead of `4770' -- then people in the group cannot write to the binary. Allegro will drop the privileges almost immediately after initialisation, using `seteuid'. This means that you can still get the permissions back later on. Allegro needs to be able to regain the privileges if you intend to call `allegro_init' again in the future. If this isn't the case, you can completely give up the privileges using `setuid(getuid());' -- then they are lost for good. Security note: If you don't do this, any buffer overflows are a severe security problem. In any case, you should take great care when allowing random people to execute third-party programs suid root. If, as root, you run `make suid', it will do this to all of the programs generated -- the demo game, the examples, the tests, etc. ========================================== ============ Notes on drivers ============ ========================================== This section contains Linux-specific notes on the drivers available. System: On initialisation, Allegro will try to get a certain amount of control over the console. This doesn't generally require root privileges, but if the program isn't being run from a plain VC (e.g. it's running from within X or screen), Allegro must try to allocate a spare VC and move the program to it. This requires a free console we can read from and write to; unless the user has allocated some, we need to be root here. Display switching is possible; all of Allegro's modes are supported. The default is SWITCH_PAUSE. SWITCH_BACKGROUND will only work if the application takes special precautions. Graphics: Linux Allegro supports standard VGA by direct writes to the video card. You need root privileges for this to work. It also supports fbcon, for which you do not need privileges, but you do need a recent kernel, correctly configured. The SVGAlib driver should be fairly stable and fast now, and can use most of the video modes that SVGAlib provides. It requires root privileges if your version of SVGAlib requires them. Note: Allegro used to have a mode-X driver, but it does not work as of 4.4.0. Someone may restore it in the future, but it's likely. Keyboard: The keyboard driver uses the kernel mapping tables to map scancodes to character codes and key functions, so your keyboard mapping should be fine without special configuration in the setup program. Joystick: To compile Allegro with joystick support you must have a 2.2.* or newer kernel, i.e. with kernel-based joystick support. Look for /usr/src/linux/include/linux/joystick.h. You shouldn't have to actually configure the kernel with joystick support though, you just need that header file. Similarly, to run Allegro programs with joystick support you must have configured joystick support into the kernel. You also need to create the device file /dev/input/js0, if it's not already there. See /usr/src/linux/Documentation/joystick.txt for details. Mouse: Currently Linux Allegro supports PS/2 and Microsoft mice directly, and other mouse types via GPM. To use GPM you must turn on its `repeater' feature, where it copies all mouse activity to the FIFO /dev/gpmdata. Edit your init scripts and add the `-R' option. The GPM driver can also be used with native Mouse Systems mice by changing the `mouse_device' variable in the config file. When using the PS/2 Intellimouse protocol, it is necessary to explicitly put the mouse into wheel mode, which requires Allegro to have write permissions to the device. There is an input events-based driver which reads events from /dev/input/eventN. allegro4.4-4.4.2/docs/build/macosx.html000066400000000000000000000300121173507505700176110ustar00rootroot00000000000000 Allegro MacOS X-specific information
     ______   ___    ___
    /\  _  \ /\_ \  /\_ \
    \ \ \L\ \\//\ \ \//\ \      __     __   _ __   ___ 
     \ \  __ \ \ \ \  \ \ \   /'__`\ /'_ `\/\`'__\/ __`\
      \ \ \/\ \ \_\ \_ \_\ \_/\  __//\ \L\ \ \ \//\ \L\ \
       \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
        \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
                                       /\____/
                                       \_/__/


                MacOS X-specific information.

         See readme.txt for a more general overview.


MacOS X notes

This is a full featured native MacOS X port.


Required software

To build Allegro under MacOS X, you need:

  • MacOS X 10.2.x or newer
  • Apple Developer Tools (December 2002 or newer edition)

If you don't have the Developer Tools installed, you can get the latest release at:

http://developer.apple.com/tools/download

On the same page you will also find instructions on how to install them. Note that system version 10.2.x is required to compile Allegro, but the library will still work on 10.1.x. (At least that was true once; we haven't gone back and checked it!)


Installing Allegro

Allegro ships in source code form; this means you need to compile it before you can use it. You do this easily from a terminal window. See the generic documentation in docs/build/cmake.txt.

You may build either Unix-style shared library, or Mac OS X frameworks, or both.

XXX information about universal binaries


Using Allegro from the command line

The options for linking with Allegro are quite long, expecially for static versions of the library as you need to pull in several different frameworks (Cocoa, QuickTime, etc.) other than Allegro itself. When linking against the shared library version, things are also different. To avoid you having to work out the right linker commands for yourself, the installation creates a script, allegro-config, that will print out a suitable commandline. You can use this inside a backtick command substitution, for example:

      gcc myfile.c -o myprogram `allegro-config --libs`
Or if you want to build a debug version of your program, assuming that you have installed the debug version of Allegro:
      gcc myfile.c -o myprogram `allegro-config --libs debug`
You can also link against the Allegro framework, providing you previously installed it:
      gcc myfile.c -o myprogram `allegro-config --frameworks`
Unix newbies, take note that these are ` backticks, not normal ' quotes!

There are also switches for printing out the Allegro version number, overriding the install paths, and selecting between shared and static libraries, in case you installed both. Run allegro-config without any arguments for a full list of options.

If you get an error like 'allegro-config: program not found', and you're sure you have built and installed the library as described above, it probably means that /usr/local/bin is not on your path. The method to add it depends on the shell you're using. If you have tcsh, add the following line to the end of the .cshrc in your home directory.

     set path=($path /usr/local/bin)
If you have bash, add the following line to the end of the .bash_profile file in your home directory:
     PATH=${PATH}:/usr/local/bin
If you don't know which, just type echo $SHELL on the command line, which will print either /bin/bash or /bin/tcsh. Newer versions of OSX use bash, older ones use tcsh. You will have to close the Terminal window and open a new one once you have made the changes, so it will have an effect.


Allegro and application bundles

When you build applications from the command line, you're actually just creating the executable, so you can run it from the command line only, and not also from the finder like a common MacOS X application. In other words, compiling from the command line does not create application bundles.

Allegro ships with a little tool, named fixbundle, which allows to build an application bundle out of an executable. The utility works from the command line and it accepts a variety of options to customize your bundle; the easiest way to use it is:

      fixbundle executable_name
This will create an application bundle named "executable_name.app" that contains your program executable and will appear in the finder with the default application icon. A more complex usage example follows:
      fixbundle executable_name -m -o bundle_name -v "1.2" icon.bmp
This creates a bundle named "bundle_name.app". The executable will be moved instead of copied into the bundle; the application will be marked as version "1.2" and icon.bmp will be converted to an icon for the bundle. You can specify more options and up to 4 differently sized icons (16x16, 32x32, 48x48 and 128x128) to be read from any Allegro supported image files or from datafile objects. Run fixbundle without arguments for the full list of known options.

A special note is required for the "-e" switch; this lets you embed the Allegro framework inside the built application bundle, so your app will not require Allegro to be installed into the target machine in order to work. This flag assumes you previously installed the embeddable version of the Allegro framework, and that your executable has been linked to it, either via Project Builder or XCode, either via the allegro-config script. If one of these conditions is not met, the created app may not work on target machines.

Bundles created by fixbundle have this default layout:

      bundle.app --- Contents --+--- MacOS --- executable
                                |
                                +--- Resources --+--- (bundle.icns)
                                |                |
                                |                +--- (executable/...)
                                |
                                |
                                +--- (Frameworks) --- (Allegro.framework/...)
                                |
                                +--- Info.plist
                                |
                                +--- PkgInfo
If you are using Project Builder to compile your programs, there is no need to use fixbundle, as the IDE will do the work of generating an application bundle for you.

When an Allegro program starts, it automatically detects if the executable lives inside a bundle or not. The working directory is always set up to be the directory where the standalone executable or application bundle is located, but there is an exception: if the application is a bundle and Allegro finds a directory under the bundle Contents/Resources path with the same name of the executable (note that here we mean the real executable name, not the bundle name), that directory is set to be the working one. This allows to easily package all the application data inside the bundle, and still have a working program without the need to tell your code about the changed location of your files.


Notes on drivers

This section contains MacOS X-specific notes on the drivers available.

System:
When the system driver is about to be initialized, we already have a working NSApplication object connected to the Window Server. At driver startup, the working directory is changed if inside a bundle with a proper data directory under the Contents/Resources path (see above).

Display switching is possible, but only the SWITCH_BACKGROUND mode is supported, so your application will have to deal with it.

Graphics:
The MacOS X windowed graphics mode uses a Cocoa window with a Quartz QuickDraw view as its content view. All combinations of window/desktop color depths are supported; if needed, color conversion will automatically be done transparently to the user.

Fullscreen mode uses the CoreGraphics DirectDisplay API; only 8, 15 and 32 bit color depths are supported.

Sound:
The CoreAudio digital/MIDI drivers use V2 AudioUnits, and thus they require MacOS X 10.2.x (Jaguar) or newer to work. If this is not the case, you can fall back to the Carbon Sound Manager and Quicktime MIDI drivers.

Keyboard:
MacOS X Allegro uses the current system keyboard mapping table to map scancodes to characters: the keyboard user settings in allegro.cfg have no effect.

Mouse:
On MacOS X 10.2.x (Jaguar) or newer, Allegro will automatically detect the number of buttons of your mouse at driver initialization. If the 1-button Apple mouse is found, the library will activate an emulation mode that mimics the way MacOS X itself deals with 1-button mice: depending on which key is pressed when the button is clicked, Allegro will report a different mouse button click. (Control + button) emulates a right click and (Option + button) emulates a middle click.

On MacOS X 10.1.x, mouse autodetection is not possible, and Allegro will assume an 1-button mouse to always be present, activating buttons emulation accordingly.


Notes on Threading and Cocoa GUIs

It is possible to include a Cocoa GUI in an Allegro application. If you do this you should be aware that Allegro will run your application's main() function in a different thread from the thread that the main OS X event loop runs in. See http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/Multithreading/Introduction/Introduction.html for more information about threading on Mac OS X.


Final notes

There is a known compatibility problem when using gcc 4 on MacOS X 10.4 that prevents binaries from working on older versions of MacOS X. While it is anticipated that a future update from Apple will fix this problem, you can use gcc 3 to work around it.

As a final note, when coding Allegro programs don't forget that you need to use the END_OF_MAIN() macro right after your main() function! allegro4.4-4.4.2/docs/build/macosx.txt000066400000000000000000000260051173507505700174730ustar00rootroot00000000000000 ______ ___ ___ /\ _ \ /\_ \ /\_ \ \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ /\____/ \_/__/ MacOS X-specific information. See readme.txt for a more general overview. ======================================= ============ MacOS X notes ============ ======================================= This is a full featured native MacOS X port. =========================================== ============ Required software ============ =========================================== To build Allegro under MacOS X, you need: MacOS X 10.2.x or newer Apple Developer Tools (December 2002 or newer edition) If you don't have the Developer Tools installed, you can get the latest release at: http://developer.apple.com/tools/download On the same page you will also find instructions on how to install them. Note that system version 10.2.x is required to compile Allegro, but the library will still work on 10.1.x. (At least that was true once; we haven't gone back and checked it!) ============================================ ============ Installing Allegro ============ ============================================ Allegro ships in source code form; this means you need to compile it before you can use it. You do this easily from a terminal window. See the generic documentation in docs/build/cmake.txt. You may build either Unix-style shared library, or Mac OS X frameworks, or both. XXX information about universal binaries ============================================================= ============ Using Allegro from the command line ============ ============================================================= The options for linking with Allegro are quite long, expecially for static versions of the library as you need to pull in several different frameworks (Cocoa, QuickTime, etc.) other than Allegro itself. When linking against the shared library version, things are also different. To avoid you having to work out the right linker commands for yourself, the installation creates a script, allegro-config, that will print out a suitable commandline. You can use this inside a backtick command substitution, for example: gcc myfile.c -o myprogram `allegro-config --libs` Or if you want to build a debug version of your program, assuming that you have installed the debug version of Allegro: gcc myfile.c -o myprogram `allegro-config --libs debug` You can also link against the Allegro framework, providing you previously installed it: gcc myfile.c -o myprogram `allegro-config --frameworks` Unix newbies, take note that these are ` backticks, not normal ' quotes! There are also switches for printing out the Allegro version number, overriding the install paths, and selecting between shared and static libraries, in case you installed both. Run allegro-config without any arguments for a full list of options. If you get an error like 'allegro-config: program not found', and you're sure you have built and installed the library as described above, it probably means that /usr/local/bin is not on your path. The method to add it depends on the shell you're using. If you have tcsh, add the following line to the end of the .cshrc in your home directory. set path=($path /usr/local/bin) If you have bash, add the following line to the end of the .bash_profile file in your home directory: PATH=${PATH}:/usr/local/bin If you don't know which, just type echo $SHELL on the command line, which will print either /bin/bash or /bin/tcsh. Newer versions of OSX use bash, older ones use tcsh. You will have to close the Terminal window and open a new one once you have made the changes, so it will have an effect. ========================================================= ============ Allegro and application bundles ============ ========================================================= When you build applications from the command line, you're actually just creating the executable, so you can run it from the command line only, and not also from the finder like a common MacOS X application. In other words, compiling from the command line does not create application bundles. Allegro ships with a little tool, named fixbundle, which allows to build an application bundle out of an executable. The utility works from the command line and it accepts a variety of options to customize your bundle; the easiest way to use it is: fixbundle executable_name This will create an application bundle named "executable_name.app" that contains your program executable and will appear in the finder with the default application icon. A more complex usage example follows: fixbundle executable_name -m -o bundle_name -v "1.2" icon.bmp This creates a bundle named "bundle_name.app". The executable will be moved instead of copied into the bundle; the application will be marked as version "1.2" and icon.bmp will be converted to an icon for the bundle. You can specify more options and up to 4 differently sized icons (16x16, 32x32, 48x48 and 128x128) to be read from any Allegro supported image files or from datafile objects. Run fixbundle without arguments for the full list of known options. A special note is required for the "-e" switch; this lets you embed the Allegro framework inside the built application bundle, so your app will not require Allegro to be installed into the target machine in order to work. This flag assumes you previously installed the embeddable version of the Allegro framework, and that your executable has been linked to it, either via Project Builder or XCode, either via the allegro-config script. If one of these conditions is not met, the created app may not work on target machines. Bundles created by fixbundle have this default layout: bundle.app --- Contents --+--- MacOS --- executable | +--- Resources --+--- (bundle.icns) | | | +--- (executable/...) | | +--- (Frameworks) --- (Allegro.framework/...) | +--- Info.plist | +--- PkgInfo If you are using Project Builder to compile your programs, there is no need to use fixbundle, as the IDE will do the work of generating an application bundle for you. When an Allegro program starts, it automatically detects if the executable lives inside a bundle or not. The working directory is always set up to be the directory where the standalone executable or application bundle is located, but there is an exception: if the application is a bundle and Allegro finds a directory under the bundle Contents/Resources path with the same name of the executable (note that here we mean the real executable name, not the bundle name), that directory is set to be the working one. This allows to easily package all the application data inside the bundle, and still have a working program without the need to tell your code about the changed location of your files. ========================================== ============ Notes on drivers ============ ========================================== This section contains MacOS X-specific notes on the drivers available. System: When the system driver is about to be initialized, we already have a working NSApplication object connected to the Window Server. At driver startup, the working directory is changed if inside a bundle with a proper data directory under the Contents/Resources path (see above). Display switching is possible, but only the SWITCH_BACKGROUND mode is supported, so your application will have to deal with it. Graphics: The MacOS X windowed graphics mode uses a Cocoa window with a Quartz QuickDraw view as its content view. All combinations of window/desktop color depths are supported; if needed, color conversion will automatically be done transparently to the user. Fullscreen mode uses the CoreGraphics DirectDisplay API; only 8, 15 and 32 bit color depths are supported. Sound: The CoreAudio digital/MIDI drivers use V2 AudioUnits, and thus they require MacOS X 10.2.x (Jaguar) or newer to work. If this is not the case, you can fall back to the Carbon Sound Manager and Quicktime MIDI drivers. Keyboard: MacOS X Allegro uses the current system keyboard mapping table to map scancodes to characters: the keyboard user settings in allegro.cfg have no effect. Mouse: On MacOS X 10.2.x (Jaguar) or newer, Allegro will automatically detect the number of buttons of your mouse at driver initialization. If the 1-button Apple mouse is found, the library will activate an emulation mode that mimics the way MacOS X itself deals with 1-button mice: depending on which key is pressed when the button is clicked, Allegro will report a different mouse button click. (Control + button) emulates a right click and (Option + button) emulates a middle click. On MacOS X 10.1.x, mouse autodetection is not possible, and Allegro will assume an 1-button mouse to always be present, activating buttons emulation accordingly. =========================================================== ============ Notes on Threading and Cocoa GUIs ============ =========================================================== It is possible to include a Cocoa GUI in an Allegro application. If you do this you should be aware that Allegro will run your application's main() function in a different thread from the thread that the main OS X event loop runs in. See http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/Multithreading/Introduction/Introduction.html for more information about threading on Mac OS X. ===================================== ============ Final notes ============ ===================================== There is a known compatibility problem when using gcc 4 on MacOS X 10.4 that prevents binaries from working on older versions of MacOS X. While it is anticipated that a future update from Apple will fix this problem, you can use gcc 3 to work around it. As a final note, when coding Allegro programs don't forget that you need to use the END_OF_MAIN() macro right after your main() function! allegro4.4-4.4.2/docs/build/mingw32.html000066400000000000000000000364241173507505700176220ustar00rootroot00000000000000 Notes on building the MinGW/Cygwin version of Allegro.

     ______   ___    ___
    /\  _  \ /\_ \  /\_ \
    \ \ \L\ \\//\ \ \//\ \      __     __   _ __   ___ 
     \ \  __ \ \ \ \  \ \ \   /'__`\ /'_ `\/\`'__\/ __`\
      \ \ \/\ \ \_\ \_ \_\ \_/\  __//\ \L\ \ \ \//\ \L\ \
       \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
        \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
                                       /\____/
                                       \_/__/


   Notes on building the MinGW/Cygwin version of Allegro.

   See readme.txt for a more general overview.


MinGW notes

This is a complete MinGW port of Allegro.

The screensaver example is built, but you must copy scrsave.scr to your windows/system directory (or winnt/system32 directory under Windows NT/2k/XP) if you want to test it.


Obtaining and installing the compiler & tools

You have four choices when it comes to installing MinGW and Allegro on your computer:

  • The section 'Setting up MinGW to build Allegro' describes how to set up the MinGW command line tools which is the preferred choice for those who like to work on the command line.
  • The section 'Setting up Dev-C++ to build Allegro' describes how to set up the Dev-C++ environment to work with Allegro. This is the preferred choice for those who like to work in a graphical development environment.
  • The section 'Setting up Cygwin to build Allegro' describes how to set up your Cygwin compiler to build Allegro. Cygwin offers a mature Unix-like environment for you to work in.
  • The last section 'Cross compilation' describes how to set up the MinGW command line tools to compile Win32 programs from your Linux box.
Note: You will need a program to decompress .zip, .tar.gz and optionally .tar.bz2 files. I recommend PowerArchiver (shareware) which can be downloaded from: 'http://www.powerarchiver.com'.


Setting up MinGW to build Allegro

The procedure is as follows:

1. Make sure you have a working MinGW installation. You can download the complete distribution or individual packages from 'http://www.mingw.org' or 'http://sourceforge.net/projects/mingw/'. You can also use the Minimal SYStem (MSYS) environment with Allegro.

2. Get the minimal DirectX 7 SDK for MinGW (dx70_mgw.zip). You download it from 'http://alleg.sourceforge.net/wip.html'. Note that this is *not* the same package as 'dx70_min.zip'. Unzip it to the compiler directory, overwriting any existing files.

3. Optionally, set the environment variable MINGDIR to the compiler directory. If you use Windows 9x, you can add the line

         set MINGDIR=c:\MinGW
to your 'c:\autoexec.bat' file, assuming 'c:\MinGW' is the compiler directory, and reboot. If you use Windows ME, you can run 'msconfig', select the 'Environment' tab and then add MINGDIR. If you use Windows NT/2k/XP, you can open the Control Panel, click the 'System' applet, the 'Advanced' tab and finally the 'Environment' button, and then add MINGDIR. If you use MSYS, add instead the line
         export MINGDIR=/mingw
to your 'c:\msys\etc\profile' file.

Test the installation by typing the following on the command line: 'gcc -v'. The answer should be similar to:

      Reading specs from ../lib/gcc-lib/mingw32/3.2/specs
      Configured with: ../gcc/configure --with-gcc --with-gnu-ld
      --with-gnu-as --host=mingw32 --target=mingw32 --prefix=/mingw
      --enable-threads --disable-nls --enable-languages=f77,c++,objc,ada
      --disable-win32-registry --disable-shared
      Thread model: win32
      gcc version 3.2 (mingw special 20020817-1)
If you don't know how to open a terminal, you can click on 'Start -> Run' then type "command". Under Windows 2k/XP, you should type "cmd" instead.


Setting up Dev-C++ to build Allegro

Note: we assume that the complete version of the Dev-C++ environment (i.e with the bundled MinGW compiler) is used. If you use instead Dev-C++ as a mere IDE on top of an already installed MinGW compiler, follow the instructions given in the previous section.

The procedure is as follows:

1. Make sure you have a working Dev-C++ installation. You can download the complete version from 'http://bloodshed.net/dev/devcpp.html'.

2. Get the DirectX SDK: go to Tools\Check for Updates/Packages... and install the DirectX package. Close Dev-C++.

3. Add 'c:\DevCpp\bin' to the beginning of your PATH environment variable. Optionally, set the environment variable MINGDIR to 'c:\DevCpp'. If you use Windows 9x, you can add the lines

         PATH=c:\DevCpp\bin;%PATH%
         set MINGDIR=c:\DevCpp
to your 'c:\autoexec.bat' file and reboot. If you use Windows ME, you can run 'msconfig', select the 'Environment' tab, then modify PATH and add MINGDIR. If you use Windows NT/2k/XP, you can open the Control Panel, click the 'System' applet, the 'Advanced' tab and finally the 'Environment' button, then modify PATH and add MINGDIR.


Test the installation by typing the following on the command line: 'gcc -v'. The answer should be similar to:

      Reading specs from ../lib/gcc-lib/mingw32/3.2/specs
      Configured with: ../gcc/configure --with-gcc --with-gnu-ld
      --with-gnu-as --host=mingw32 --target=mingw32 --prefix=/mingw
      --enable-threads --disable-nls --enable-languages=f77,c++,objc,ada
      --disable-win32-registry --disable-shared
      Thread model: win32
      gcc version 3.2 (mingw special 20020817-1)
If you don't know how to open a terminal, you can click on 'Start -> Run' then type "command". Under Windows 2k/XP, you should type "cmd" instead.


Setting up Cygwin to build Allegro

Note: Allegro 4.4 has not been tested with Cygwin yet!

The procedure is as follows:

1. Make sure you have a working Cygwin installation. You can download the setup.exe program from 'http://sources.redhat.com/cygwin/'. You will need the following packages: bash, binutils, coreutils, cygwin, cygutils, fileutils, gcc, gdb, login, make, man, mingw-runtime, sed, texinfo and w32api.

2. Get the minimal DirectX 7 SDK for MinGW. (dx70_mgw.zip) Download it from 'http://alleg.sourceforge.net/wip.html' and unzip it to a temporary directory, for instance 'C:\Temp'. Then move the contents of 'C:\Temp\lib' to 'C:\cygwin\lib\w32api', and the contents of 'C:\Temp\include' to 'c:\cygwin\usr\include\w32api'. If you are asked if you want to overwrite any existing files, choose to overwrite them.

3. Put the following text in '/etc/profile' (c:\cygwin\etc\profile)

         export ALLEGRO_USE_CYGWIN=1
         export MINGDIR=/usr/local
         export CPATH=/usr/local/include
         export LIBRARY_PATH=/usr/local/lib
Note: if the CPATH or LIBRARY_PATH variables are already set, you will have to append the new path to the existing one by using a colon (":") as the separator.


Test the installation by typing the following in the Bash shell: 'gcc -v'. The answer should be similar to:

      Reading specs from /usr/lib/gcc-lib/i686-pc-cygwin/3.2/specs
      gcc version 3.2 20020927 (prerelease)
Note: if you have problems installing the profiling version of the Allegro library, you will probably need to copy a file called libgmon.a from the MinGW distribution to your /lib/mingw directory (c:\cygwin\lib\mingw) in Cygwin. This is expected to be fixed in a later release of the mingw-runtime package (I'm currently using mingw-runtime-1.2-1).


Cross compilation

The procedure is as follows:

1. Download and install the MinGW cross-compiler. You can get the software:

  • directly from the MingW site: http://sourceforge.net/projects/mingw/. You need the following packages (as of February 2003):
    • gcc (gcc-3.2.2-20030208-1-src.tar.gz)
    • binutils (binutils-2.13.90-20030111-1-src.tar.gz)
    • mingw runtime (mingw-runtime-2.4.tar.gz)
    • w32api (w32api-2.2.tar.gz)
    Optionally, you can get from the SDL site, http://www.libsdl.org/extras/win32/common: opengl-devel (opengl-devel.tar.gz)
  • using a more convenient script with instructions for downloading: http://www.libsdl.org/extras/win32/cross/README.txt. Follow the instructions, and make sure to edit the build-crosh.sh script so it downloads the most recent version of gcc and binutils.
  • as a premade Debian package called 'mingw32', which you can install with 'apt-get install mingw32'.
2. Get the minimal DirectX 7 SDK for MinGW (dx70_mgw.zip). Download it from 'http://alleg.sourceforge.net/wip.html' and unzip it in the cross-compiler base directory. Make sure you convert all text files to unix style (unzip -a) or the preprocessor will croak. The DirectX package downloaded and installed by the SDL script is not up to date: replace it with the package from the Allegro site.

3. Use the cmake/Toolchain-mingw.cmake file. Remember to set MINGDIR if your MinGW binaries live alongside your native binaries, otherwise the 'make install' step may make a mess in your normal directories.


Installing Allegro

Once your compiler is set up, follow the generic build instructions in docs/build/cmake.txt.


Using Allegro

All the Allegro functions, variables, and data structures are defined in allegro.h. You should include this in your programs, and link with either the optimised library liballeg.a, the debugging library liballeg-debug.a, or the profiling library liballeg-profile.a. You should include the Allegro DLLs in any software you release to the public.

When using a statically linked library, you must define the preprocessor symbol ALLEGRO_STATICLINK before including any of the Allegro headers and link your program against Allegro and the main Win32/DirectX libraries in that order. The names of the statically linked Allegro libraries are post-fixed with '-static' so that you will link with either liballeg-static.a, liballeg-debug-static.a or liballeg-profile-static.a.

Don't forget that you need to use the END_OF_MAIN() macro right after your main() function.


Compiling manually with MinGW

A simple example of a command line to compile an Allegro program with MinGW looks like:

      gcc foo.c -Wl,--subsystem,windows -O2 -Wall -o foo.exe -lalleg
If you are compiling with Cygwin, the compiler option '-mno-cygwin' must be added, both at compile-time and at link-time:
      gcc foo.c -Wl,--subsystem,windows -mno-cygwin -O2 -Wall -o foo.exe -lalleg
Note that, if you want to make a console application, you must use '-Wl,--subsystem,console' instead of '-Wl,--subsystem,windows'.


Creating a program with Dev-C++

A simple example on how to create a little program with Dev-C++:

Launch Dev-C++ and create a new project (File/New Project). Select "Windows Application", then click on the "Ok" button. Name your project and give associate it to a new file. You should now see a sample code in a window. Close that window since you won't be needing it (Allegro is much simpler to use than this). Create a new file (File/New Source File), then write a small Allegro program. You can inspire yourself by the Allegro examples if you wish. Here's a small program you can type to see if everything worked until now:

      #include <allegro.h>

      int main() {
         allegro_init();
         allegro_message("Hello World!");
         return 0;
      }
      END_OF_MAIN()
You now need to tell Dev-C++ that you'd like to make a program that uses Allegro. For that, go in the Project Options screen (Project/Project Options menu), then enter -lalleg (or -lalld for the debug mode) in the box under 'Further object file or linker options' or select 'Parameters tab' and enter -lalleg (or -lalld for the debug mode) in the box under 'Linker'.

Compile your project! Simply click on the green check mark on your Dev-C++ toolbar. Correct any syntax errors in your code, then click on "Execute" to run the program. If all worked you will see a message box pop up with "Hello World" inside of it.

Happy coding! allegro4.4-4.4.2/docs/build/mingw32.txt000066400000000000000000000327721173507505700174770ustar00rootroot00000000000000 ______ ___ ___ /\ _ \ /\_ \ /\_ \ \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ /\____/ \_/__/ Notes on building the MinGW/Cygwin version of Allegro. See readme.txt for a more general overview. ===================================== ============ MinGW notes ============ ===================================== This is a complete MinGW port of Allegro. The screensaver example is built, but you must copy scrsave.scr to your windows/system directory (or winnt/system32 directory under Windows NT/2k/XP) if you want to test it. ======================================================================= ============ Obtaining and installing the compiler & tools ============ ======================================================================= You have four choices when it comes to installing MinGW and Allegro on your computer: The section 'Setting up MinGW to build Allegro' describes how to set up the MinGW command line tools which is the preferred choice for those who like to work on the command line. The section 'Setting up Dev-C++ to build Allegro' describes how to set up the Dev-C++ environment to work with Allegro. This is the preferred choice for those who like to work in a graphical development environment. The section 'Setting up Cygwin to build Allegro' describes how to set up your Cygwin compiler to build Allegro. Cygwin offers a mature Unix-like environment for you to work in. The last section 'Cross compilation' describes how to set up the MinGW command line tools to compile Win32 programs from your Linux box. Note: You will need a program to decompress .zip, .tar.gz and optionally .tar.bz2 files. I recommend PowerArchiver (shareware) which can be downloaded from: 'http://www.powerarchiver.com'. =========================================================== ============ Setting up MinGW to build Allegro ============ =========================================================== The procedure is as follows: 1. Make sure you have a working MinGW installation. You can download the complete distribution or individual packages from 'http://www.mingw.org' or 'http://sourceforge.net/projects/mingw/'. You can also use the Minimal SYStem (MSYS) environment with Allegro. 2. Get the minimal DirectX 7 SDK for MinGW (dx70_mgw.zip). You download it from 'http://alleg.sourceforge.net/wip.html'. Note that this is *not* the same package as 'dx70_min.zip'. Unzip it to the compiler directory, overwriting any existing files. 3. Optionally, set the environment variable MINGDIR to the compiler directory. If you use Windows 9x, you can add the line set MINGDIR=c:\MinGW to your 'c:\autoexec.bat' file, assuming 'c:\MinGW' is the compiler directory, and reboot. If you use Windows ME, you can run 'msconfig', select the 'Environment' tab and then add MINGDIR. If you use Windows NT/2k/XP, you can open the Control Panel, click the 'System' applet, the 'Advanced' tab and finally the 'Environment' button, and then add MINGDIR. If you use MSYS, add instead the line export MINGDIR=/mingw to your 'c:\msys\etc\profile' file. Test the installation by typing the following on the command line: 'gcc -v'. The answer should be similar to: Reading specs from ../lib/gcc-lib/mingw32/3.2/specs Configured with: ../gcc/configure --with-gcc --with-gnu-ld --with-gnu-as --host=mingw32 --target=mingw32 --prefix=/mingw --enable-threads --disable-nls --enable-languages=f77,c++,objc,ada --disable-win32-registry --disable-shared Thread model: win32 gcc version 3.2 (mingw special 20020817-1) If you don't know how to open a terminal, you can click on 'Start -> Run' then type "command". Under Windows 2k/XP, you should type "cmd" instead. ============================================================= ============ Setting up Dev-C++ to build Allegro ============ ============================================================= Note: we assume that the complete version of the Dev-C++ environment (i.e with the bundled MinGW compiler) is used. If you use instead Dev-C++ as a mere IDE on top of an already installed MinGW compiler, follow the instructions given in the previous section. The procedure is as follows: 1. Make sure you have a working Dev-C++ installation. You can download the complete version from 'http://bloodshed.net/dev/devcpp.html'. 2. Get the DirectX SDK: go to Tools\Check for Updates/Packages... and install the DirectX package. Close Dev-C++. 3. Add 'c:\DevCpp\bin' to the beginning of your PATH environment variable. Optionally, set the environment variable MINGDIR to 'c:\DevCpp'. If you use Windows 9x, you can add the lines PATH=c:\DevCpp\bin;%PATH% set MINGDIR=c:\DevCpp to your 'c:\autoexec.bat' file and reboot. If you use Windows ME, you can run 'msconfig', select the 'Environment' tab, then modify PATH and add MINGDIR. If you use Windows NT/2k/XP, you can open the Control Panel, click the 'System' applet, the 'Advanced' tab and finally the 'Environment' button, then modify PATH and add MINGDIR. Test the installation by typing the following on the command line: 'gcc -v'. The answer should be similar to: Reading specs from ../lib/gcc-lib/mingw32/3.2/specs Configured with: ../gcc/configure --with-gcc --with-gnu-ld --with-gnu-as --host=mingw32 --target=mingw32 --prefix=/mingw --enable-threads --disable-nls --enable-languages=f77,c++,objc,ada --disable-win32-registry --disable-shared Thread model: win32 gcc version 3.2 (mingw special 20020817-1) If you don't know how to open a terminal, you can click on 'Start -> Run' then type "command". Under Windows 2k/XP, you should type "cmd" instead. ============================================================ ============ Setting up Cygwin to build Allegro ============ ============================================================ Note: Allegro 4.4 has not been tested with Cygwin yet! The procedure is as follows: 1. Make sure you have a working Cygwin installation. You can download the setup.exe program from 'http://sources.redhat.com/cygwin/'. You will need the following packages: bash, binutils, coreutils, cygwin, cygutils, fileutils, gcc, gdb, login, make, man, mingw-runtime, sed, texinfo and w32api. 2. Get the minimal DirectX 7 SDK for MinGW. (dx70_mgw.zip) Download it from 'http://alleg.sourceforge.net/wip.html' and unzip it to a temporary directory, for instance 'C:\Temp'. Then move the contents of 'C:\Temp\lib' to 'C:\cygwin\lib\w32api', and the contents of 'C:\Temp\include' to 'c:\cygwin\usr\include\w32api'. If you are asked if you want to overwrite any existing files, choose to overwrite them. 3. Put the following text in '/etc/profile' (c:\cygwin\etc\profile) export ALLEGRO_USE_CYGWIN=1 export MINGDIR=/usr/local export CPATH=/usr/local/include export LIBRARY_PATH=/usr/local/lib Note: if the CPATH or LIBRARY_PATH variables are already set, you will have to append the new path to the existing one by using a colon (":") as the separator. Test the installation by typing the following in the Bash shell: 'gcc -v'. The answer should be similar to: Reading specs from /usr/lib/gcc-lib/i686-pc-cygwin/3.2/specs gcc version 3.2 20020927 (prerelease) Note: if you have problems installing the profiling version of the Allegro library, you will probably need to copy a file called libgmon.a from the MinGW distribution to your /lib/mingw directory (c:\cygwin\lib\mingw) in Cygwin. This is expected to be fixed in a later release of the mingw-runtime package (I'm currently using mingw-runtime-1.2-1). =========================================== ============ Cross compilation ============ =========================================== The procedure is as follows: 1. Download and install the MinGW cross-compiler. You can get the software: directly from the MingW site: http://sourceforge.net/projects/mingw/. You need the following packages (as of February 2003): gcc (gcc-3.2.2-20030208-1-src.tar.gz) binutils (binutils-2.13.90-20030111-1-src.tar.gz) mingw runtime (mingw-runtime-2.4.tar.gz) w32api (w32api-2.2.tar.gz) Optionally, you can get from the SDL site, http://www.libsdl.org/extras/win32/common: opengl-devel (opengl-devel.tar.gz) using a more convenient script with instructions for downloading: http://www.libsdl.org/extras/win32/cross/README.txt. Follow the instructions, and make sure to edit the build-crosh.sh script so it downloads the most recent version of gcc and binutils. as a premade Debian package called 'mingw32', which you can install with 'apt-get install mingw32'. 2. Get the minimal DirectX 7 SDK for MinGW (dx70_mgw.zip). Download it from 'http://alleg.sourceforge.net/wip.html' and unzip it in the cross-compiler base directory. Make sure you convert all text files to unix style (unzip -a) or the preprocessor will croak. The DirectX package downloaded and installed by the SDL script is not up to date: replace it with the package from the Allegro site. 3. Use the cmake/Toolchain-mingw.cmake file. Remember to set MINGDIR if your MinGW binaries live alongside your native binaries, otherwise the 'make install' step may make a mess in your normal directories. ============================================ ============ Installing Allegro ============ ============================================ Once your compiler is set up, follow the generic build instructions in docs/build/cmake.txt. ======================================= ============ Using Allegro ============ ======================================= All the Allegro functions, variables, and data structures are defined in allegro.h. You should include this in your programs, and link with either the optimised library liballeg.a, the debugging library liballeg-debug.a, or the profiling library liballeg-profile.a. You should include the Allegro DLLs in any software you release to the public. When using a statically linked library, you must define the preprocessor symbol ALLEGRO_STATICLINK before including any of the Allegro headers and link your program against Allegro and the main Win32/DirectX libraries in that order. The names of the statically linked Allegro libraries are post-fixed with '-static' so that you will link with either liballeg-static.a, liballeg-debug-static.a or liballeg-profile-static.a. Don't forget that you need to use the END_OF_MAIN() macro right after your main() function. ======================================================= ============ Compiling manually with MinGW ============ ======================================================= A simple example of a command line to compile an Allegro program with MinGW looks like: gcc foo.c -Wl,--subsystem,windows -O2 -Wall -o foo.exe -lalleg If you are compiling with Cygwin, the compiler option '-mno-cygwin' must be added, both at compile-time and at link-time: gcc foo.c -Wl,--subsystem,windows -mno-cygwin -O2 -Wall -o foo.exe -lalleg Note that, if you want to make a console application, you must use '-Wl,--subsystem,console' instead of '-Wl,--subsystem,windows'. ========================================================= ============ Creating a program with Dev-C++ ============ ========================================================= A simple example on how to create a little program with Dev-C++: Launch Dev-C++ and create a new project (File/New Project). Select "Windows Application", then click on the "Ok" button. Name your project and give associate it to a new file. You should now see a sample code in a window. Close that window since you won't be needing it (Allegro is much simpler to use than this). Create a new file (File/New Source File), then write a small Allegro program. You can inspire yourself by the Allegro examples if you wish. Here's a small program you can type to see if everything worked until now: #include int main() { allegro_init(); allegro_message("Hello World!"); return 0; } END_OF_MAIN() You now need to tell Dev-C++ that you'd like to make a program that uses Allegro. For that, go in the Project Options screen (Project/Project Options menu), then enter -lalleg (or -lalld for the debug mode) in the box under 'Further object file or linker options' or select 'Parameters tab' and enter -lalleg (or -lalld for the debug mode) in the box under 'Linker'. Compile your project! Simply click on the green check mark on your Dev-C++ toolbar. Correct any syntax errors in your code, then click on "Execute" to run the program. If all worked you will see a message box pop up with "Hello World" inside of it. Happy coding! allegro4.4-4.4.2/docs/build/msvc.html000066400000000000000000000136711173507505700173030ustar00rootroot00000000000000 Allegro MSVC-specific information

     ______   ___    ___
    /\  _  \ /\_ \  /\_ \
    \ \ \L\ \\//\ \ \//\ \      __     __   _ __   ___ 
     \ \  __ \ \ \ \  \ \ \   /'__`\ /'_ `\/\`'__\/ __`\
      \ \ \/\ \ \_\ \_ \_\ \_/\  __//\ \L\ \ \ \//\ \L\ \
       \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
        \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
                                       /\____/
                                       \_/__/


                 MSVC-specific information.

         See readme.txt for a more general overview.


MSVC notes

Status: complete.

The screensaver example is built, but you must copy scrsave.scr to your windows/system directory (or winnt/system32 directory under Windows NT/2k/XP) if you want to test it.

You may also want to refer to one of the following, as they may include more up to date information:


Project Files

The CMake tool can generate workspaces for MSVC.

If everything builds successfully, you'll need to copy some files to finish the installation:

  • Copy the contents of C:\allegro\include to "Visual Studio\VC\include"
  • Copy the .lib files from C:\allegro\lib\msvc to "Visual Studio\VC\lib"
  • Copy the .dll files from C:\allegro\lib\msvc to C:\Windows\System32

The most common location of Visual Studio is "C:\Program Files\Microsoft Visual Studio."

Then you can build the rest of the examples, demos, tests, and tools by opening up their respective project files and selectiong Batch Build from the menu.


Required software

  • Microsoft Visual C++.
  • Recent set of DirectX and other Windows SDK headers.
Allegro should work with MSVC versions 6 and above. Lower versions may work but haven't been tested in a long time.

The DirectX SDK can be obtained directly from Microsoft. An old version of the headers is included with MSVC 6, but Allegro requires more recent files. You should either copy the current headers into your MSVC include and lib directories, or alter your INCLUDE and LIB environment variables to put the DirectX SDK files in front of the standard MSVC locations.

Microsoft Visual Studio Express Editions (free): You will need to separately download and install the "Platform SDK" or "Windows SDK". In the IDE, go to Tools > Options > Projects and Solutions > VC++ Directories and add the Platform SDK and DirectX Include and Lib/x86 (or whatever) directories to the relevant lists.


Installing Allegro

This is a source-only distribution, so you will have to compile Allegro before you can use it. Please follow the generic instructions in docs/build/cmake.txt.

If you need to call MSVC from the command line, you may need to set up your environment. You probably have a vcvars32.bat file that will do this for you (the exact location of this file depends on your MSVC version and folder where you have MSVC installed, e.g. for MSVC 6 it is usually C:\Program Files\Microsoft Visual Studio\VC98\Bin, for MSVC 8 C:\Program Files\Microsoft Visual Studio 8\VC\Bin etc.). You will have to run this file every time you open a DOS box or configure the environment variables in Control Panel/System/Environment (autoexec.bat for Win 9x/ME).


Using Allegro

All the Allegro functions, variables, and data structures are defined in allegro.h. You should include this in your programs, and link with one of the libraries:

      alleg.lib                  - optimised DLL import library
      alleg-debug.lib            - debugging DLL import library
      alleg-profile.lib          - profiling DLL import library
      alleg-static.lib           - statically linked optimised library
      alleg-debug-static.lib     - statically linked debugging library
      alleg-profile-static.lib   - statically linked profiling library
When using a statically linked library, you must define the preprocessor symbol ALLEGRO_STATICLINK before including any of the Allegro headers and link your program against Allegro and the main Win32/DirectX libraries in that order (see the variable LIBRARIES in makefile.vc). You have also to make sure that your program is linked against the right C run-time library, ie. the multi-threaded DLL version of MSVCRT (or the debug version if you are using the debug library). You can change this option at Project - Settings - C/C++ - Category: Code Generation - Use run-time library.

Don't forget that you need to use the END_OF_MAIN() macro right after your main() function!

If you use one of the DLL versions, you will obviously need to distribute the appropriate DLL along with your program. allegro4.4-4.4.2/docs/build/msvc.txt000066400000000000000000000124201173507505700171450ustar00rootroot00000000000000 ______ ___ ___ /\ _ \ /\_ \ /\_ \ \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ /\____/ \_/__/ MSVC-specific information. See readme.txt for a more general overview. ==================================== ============ MSVC notes ============ ==================================== Status: complete. The screensaver example is built, but you must copy scrsave.scr to your windows/system directory (or winnt/system32 directory under Windows NT/2k/XP) if you want to test it. You may also want to refer to one of the following, as they may include more up to date information: http://wiki.allegro.cc/Build/MSVC_6 http://wiki.allegro.cc/Build/MSVC_7 http://wiki.allegro.cc/Build/MSVC_8 ======================================= ============ Project Files ============ ======================================= The CMake tool can generate workspaces for MSVC. If everything builds successfully, you'll need to copy some files to finish the installation: Copy the contents of C:\allegro\include to "Visual Studio\VC\include" Copy the .lib files from C:\allegro\lib\msvc to "Visual Studio\VC\lib" Copy the .dll files from C:\allegro\lib\msvc to C:\Windows\System32 The most common location of Visual Studio is "C:\Program Files\Microsoft Visual Studio." Then you can build the rest of the examples, demos, tests, and tools by opening up their respective project files and selectiong Batch Build from the menu. =========================================== ============ Required software ============ =========================================== Microsoft Visual C++. Recent set of DirectX and other Windows SDK headers. Allegro should work with MSVC versions 6 and above. Lower versions may work but haven't been tested in a long time. The DirectX SDK can be obtained directly from Microsoft. An old version of the headers is included with MSVC 6, but Allegro requires more recent files. You should either copy the current headers into your MSVC include and lib directories, or alter your INCLUDE and LIB environment variables to put the DirectX SDK files in front of the standard MSVC locations. Microsoft Visual Studio Express Editions (free): You will need to separately download and install the "Platform SDK" or "Windows SDK". In the IDE, go to Tools > Options > Projects and Solutions > VC++ Directories and add the Platform SDK and DirectX Include and Lib/x86 (or whatever) directories to the relevant lists. ============================================ ============ Installing Allegro ============ ============================================ This is a source-only distribution, so you will have to compile Allegro before you can use it. Please follow the generic instructions in docs/build/cmake.txt. If you need to call MSVC from the command line, you may need to set up your environment. You probably have a vcvars32.bat file that will do this for you (the exact location of this file depends on your MSVC version and folder where you have MSVC installed, e.g. for MSVC 6 it is usually C:\Program Files\Microsoft Visual Studio\VC98\Bin, for MSVC 8 C:\Program Files\Microsoft Visual Studio 8\VC\Bin etc.). You will have to run this file every time you open a DOS box or configure the environment variables in Control Panel/System/Environment (autoexec.bat for Win 9x/ME). ======================================= ============ Using Allegro ============ ======================================= All the Allegro functions, variables, and data structures are defined in allegro.h. You should include this in your programs, and link with one of the libraries: alleg.lib - optimised DLL import library alleg-debug.lib - debugging DLL import library alleg-profile.lib - profiling DLL import library alleg-static.lib - statically linked optimised library alleg-debug-static.lib - statically linked debugging library alleg-profile-static.lib - statically linked profiling library When using a statically linked library, you must define the preprocessor symbol ALLEGRO_STATICLINK before including any of the Allegro headers and link your program against Allegro and the main Win32/DirectX libraries in that order (see the variable LIBRARIES in makefile.vc). You have also to make sure that your program is linked against the right C run-time library, ie. the multi-threaded DLL version of MSVCRT (or the debug version if you are using the debug library). You can change this option at Project - Settings - C/C++ - Category: Code Generation - Use run-time library. Don't forget that you need to use the END_OF_MAIN() macro right after your main() function! If you use one of the DLL versions, you will obviously need to distribute the appropriate DLL along with your program. allegro4.4-4.4.2/docs/build/unix.html000066400000000000000000000263541173507505700173200ustar00rootroot00000000000000 Allegro Unix-specific information

     ______   ___    ___
    /\  _  \ /\_ \  /\_ \
    \ \ \L\ \\//\ \ \//\ \      __     __   _ __   ___ 
     \ \  __ \ \ \ \  \ \ \   /'__`\ /'_ `\/\`'__\/ __`\
      \ \ \/\ \ \_\ \_ \_\ \_/\  __//\ \L\ \ \ \//\ \L\ \
       \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
        \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
                                       /\____/
                                       \_/__/


                 Unix-specific information.

         See readme.txt for a more general overview.

   Also see docs/build/linux.txt for Linux-specific information.


Unix notes

On Linux you have two different system drivers -- one for running using X, and one for running without X. This file describes the X version, which should be portable to any Unix variant. For information about the Linux-specific console routines, see docs/build/linux.txt.

Only the X version is installed by default.


Required software

Chances are that you already have all the necessary development tools, at least for compiling and installing the library. You will need CMake 2.6 or above. Most distributions should include it now, otherwise you will need to install it yourself.


Installing Allegro

Please follow the generic instructions in docs/build/cmake.txt.


Shared files

Installing Allegro will copy the library and header files plus other support files. These are:

  • allegro-config: Script that outputs the correct compiler and linker flags for your system in order to compile Allegro. This is copied into a `.../bin' path.
  • pkg-config files. These are alternatives to the allegro-config script.
On the other hand, there are files which you, as system administrator, are required to installed manually. These are:
  • language.dat: Contains translations for text strings used by Allegro. If this file is not available, Allegro runtime messages will only speak English. Recommended location is `/usr[/local]/share/allegro'.
  • allegro.info: Allegro documentation in Info format, viewable with GNU's info viewer. This is copied into the `info' path of your system.
  • allegro.cfg: Contains configuration settings for your system when the hardware autodetection fails. You can either copy this file and edit the contents manually or you can use Allegro's setup configuration program (in the `setup' directory) to create this file. Recommended location is `[/usr/local]/etc/allegro.cfg'.
You can find more information about some of these files and other suggestions in the chapter "Unix specifics" of the main Allegro manual.


Using Allegro

The options for linking with Allegro are quite complicated, since for static versions of the library, depending on how it was configured, it may need to pull in other libraries (X, SVGAlib), as well as just Allegro itself.

To avoid you having to work out the right linker commands for yourself, the installation creates a script, allegro-config, that will print out a suitable command line. You can use this inside a backtick command substitution, for example:

      gcc myfile.c -o myprogram `allegro-config --libs`
Or if you want to build a debug version of your program, assuming that you have installed the debug version of Allegro:
      gcc myfile.c -o myprogram `allegro-config --libs debug`
Unix newbies, take note that these are ` backticks, not normal ' quotes!

There are also switches for printing out the Allegro version number, overriding the install paths, and selecting between shared and static libraries, in case you installed both. Run allegro-config without any arguments for a full list of options.

You can also use pkg-config instead, for example:

      gcc myfile.c -o myprogram `pkg-config --libs allegro loadpng`
As shown, there are pkg-config files for the bundled addons as well.

Don't forget that you need to use the END_OF_MAIN() macro right after your main() function!


Setting an X11 icon

You can set the X11 icon for your application to use. To do this, you need to include the icon in .xpm format and then point the symbol allegro_icon to the .xpm data before calling set_gfx_mode(). Alternatively, you can use the xfixicon.sh shellscript to produce a C file that will do this for you automatically when you link it with your project. No other steps are required. The xfixicon.sh utility will also accept bitmaps that are not in .xpm format, interpreting magic pink as transparent. You will need to have the ImageMagick tools installed for this to work.


What if you're not root?

Allegro can be installed on a system where you don't have root privileges. Using the standard configure script option `--prefix' you can change the target directories for installation -- for example, you can write:

      cmake -DCMAKE_INSTALL_PREFIX=$HOME ..
Then binaries will be installed to the `bin' subdirectory of your home directory, libraries to `lib', etc. Now you need to set up your system so that it knows where to find a few things, if this has not been done already. You might want to add these commands to your .bash_profile or similar startup script. If you use a csh-style shell, you want to use `setenv', not `export'.

Your PATH must include the `bin' directory:

      export PATH=$PATH:$HOME/bin
If you are using Allegro as a shared library, you need to tell the dynamic loader where to find the Allegro libraries:
      export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$HOME/lib
GCC needs to know where to find header and library files:
      export C_INCLUDE_PATH=$C_INCLUDE_PATH:$HOME/include
      export CPLUS_INCLUDE_PATH=$CPLUS_INCLUDE_PATH:$HOME/include
      export LIBRARY_PATH=$LIBRARY_PATH:$HOME/lib
Note: in fact `allegro-config' can handle the last step for you, if you use it for compilation as well as linking:
      gcc -c mygame.c `allegro-config --cflags`
      gcc -o mygame mygame.o `allegro-config --libs`
But, it's better to set the environment variables too. Most people don't tend to bother with `allegro-config' when compiling.

Alternatively, you can get the required environment changes from allegro-config, by typing at a shell prompt:

      allegro-config --env
You can catenate the output to your .bash_profile, which is pretty much like adding all of the above commands. Note that `allegro-config' itself is in the `bin' directory of the installation, so either make sure that directory is in your path before running `allegro-config' or specify the path exactly, for example:
      ~/bin/allegro-config --env >> ~/.bash_profile


Notes on drivers

System:
On initialisation, Allegro will try to connect to an X server. If it can't find one, it will give up and try to use some different system driver instead (such as the Linux console driver, if it is enabled). This means that to run it in X mode, you must either launch your programs from inside an X session, or have set the DISPLAY environment variable to indicate what server you would like to use.

Graphics:
There are two different X graphics drivers: GFX_XWINDOWS uses only standard X calls, while GFX_XDGA2 uses the XFree86 DGA 2.0 extension (shipped with XFree86 4.0.x) which allows it to write directly to the screen surface, and use hardware acceleration if available. It is normally much faster than the standard X mode, but requires root permissions and will not work remotely. Note that DGA2 is deprecated now.

If your program requests a different color depth to the current X display, Allegro will emulate the depth you asked for, so that your program will still work, albeit more slowly than if the color depths were identical. To find out whether this emulation is taking place, look at the gfx_driver->desc field (which is displayed in the middle of the screen by the tests/test program). If this says "matching", the color formats are identical, so no conversions are required. If it says "fast", some simple conversions are taking place, but nothing too painful. If it says "slow", you are in trouble :-) This is not valid for the DGA 2.0 driver, as it'll always change the video mode to the specified resolution and color depth.


Irix Notes

If the Irix compiler spits strange lines such as the following when compiling your Allegro program:

      include/allegro/alcompat.h:59: conflicting types for `ceilf'
      /usr/include/math.h:311: previous declaration of `ceilf'
      include/allegro/alcompat.h:60: conflicting types for `floorf'
      /usr/include/math.h:333: previous declaration of `floorf'
      include/allegro/alcompat.h:63: conflicting types for `tanf'
      /usr/include/math.h:176: previous declaration of `tanf'
      include/allegro/alcompat.h:64: conflicting types for `acosf'
      /usr/include/math.h:106: previous declaration of `acosf'
      include/allegro/alcompat.h:65: conflicting types for `asinf'
      /usr/include/math.h:116: previous declaration of `asinf'
then you should #define ALLEGRO_NO_FIX_ALIASES prior to the #include <allegro.h> line. allegro4.4-4.4.2/docs/build/unix.txt000066400000000000000000000241511173507505700171640ustar00rootroot00000000000000 ______ ___ ___ /\ _ \ /\_ \ /\_ \ \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ /\____/ \_/__/ Unix-specific information. See readme.txt for a more general overview. Also see docs/build/linux.txt for Linux-specific information. ==================================== ============ Unix notes ============ ==================================== On Linux you have two different system drivers -- one for running using X, and one for running without X. This file describes the X version, which should be portable to any Unix variant. For information about the Linux-specific console routines, see docs/build/linux.txt. Only the X version is installed by default. =========================================== ============ Required software ============ =========================================== Chances are that you already have all the necessary development tools, at least for compiling and installing the library. You will need CMake 2.6 or above. Most distributions should include it now, otherwise you will need to install it yourself. ============================================ ============ Installing Allegro ============ ============================================ Please follow the generic instructions in docs/build/cmake.txt. ====================================== ============ Shared files ============ ====================================== Installing Allegro will copy the library and header files plus other support files. These are: allegro-config: Script that outputs the correct compiler and linker flags for your system in order to compile Allegro. This is copied into a `.../bin' path. pkg-config files. These are alternatives to the allegro-config script. On the other hand, there are files which you, as system administrator, are required to installed manually. These are: language.dat: Contains translations for text strings used by Allegro. If this file is not available, Allegro runtime messages will only speak English. Recommended location is `/usr[/local]/share/allegro'. allegro.info: Allegro documentation in Info format, viewable with GNU's info viewer. This is copied into the `info' path of your system. allegro.cfg: Contains configuration settings for your system when the hardware autodetection fails. You can either copy this file and edit the contents manually or you can use Allegro's setup configuration program (in the `setup' directory) to create this file. Recommended location is `[/usr/local]/etc/allegro.cfg'. You can find more information about some of these files and other suggestions in the chapter "Unix specifics" of the main Allegro manual. ======================================= ============ Using Allegro ============ ======================================= The options for linking with Allegro are quite complicated, since for static versions of the library, depending on how it was configured, it may need to pull in other libraries (X, SVGAlib), as well as just Allegro itself. To avoid you having to work out the right linker commands for yourself, the installation creates a script, allegro-config, that will print out a suitable command line. You can use this inside a backtick command substitution, for example: gcc myfile.c -o myprogram `allegro-config --libs` Or if you want to build a debug version of your program, assuming that you have installed the debug version of Allegro: gcc myfile.c -o myprogram `allegro-config --libs debug` Unix newbies, take note that these are ` backticks, not normal ' quotes! There are also switches for printing out the Allegro version number, overriding the install paths, and selecting between shared and static libraries, in case you installed both. Run allegro-config without any arguments for a full list of options. You can also use pkg-config instead, for example: gcc myfile.c -o myprogram `pkg-config --libs allegro loadpng` As shown, there are pkg-config files for the bundled addons as well. Don't forget that you need to use the END_OF_MAIN() macro right after your main() function! ============================================= ============ Setting an X11 icon ============ ============================================= You can set the X11 icon for your application to use. To do this, you need to include the icon in .xpm format and then point the symbol allegro_icon to the .xpm data before calling set_gfx_mode(). Alternatively, you can use the xfixicon.sh shellscript to produce a C file that will do this for you automatically when you link it with your project. No other steps are required. The xfixicon.sh utility will also accept bitmaps that are not in .xpm format, interpreting magic pink as transparent. You will need to have the ImageMagick tools installed for this to work. ================================================== ============ What if you're not root? ============ ================================================== Allegro can be installed on a system where you don't have root privileges. Using the standard configure script option `--prefix' you can change the target directories for installation -- for example, you can write: cmake -DCMAKE_INSTALL_PREFIX=$HOME .. Then binaries will be installed to the `bin' subdirectory of your home directory, libraries to `lib', etc. Now you need to set up your system so that it knows where to find a few things, if this has not been done already. You might want to add these commands to your .bash_profile or similar startup script. If you use a csh-style shell, you want to use `setenv', not `export'. Your PATH must include the `bin' directory: export PATH=$PATH:$HOME/bin If you are using Allegro as a shared library, you need to tell the dynamic loader where to find the Allegro libraries: export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$HOME/lib GCC needs to know where to find header and library files: export C_INCLUDE_PATH=$C_INCLUDE_PATH:$HOME/include export CPLUS_INCLUDE_PATH=$CPLUS_INCLUDE_PATH:$HOME/include export LIBRARY_PATH=$LIBRARY_PATH:$HOME/lib Note: in fact `allegro-config' can handle the last step for you, if you use it for compilation as well as linking: gcc -c mygame.c `allegro-config --cflags` gcc -o mygame mygame.o `allegro-config --libs` But, it's better to set the environment variables too. Most people don't tend to bother with `allegro-config' when compiling. Alternatively, you can get the required environment changes from allegro-config, by typing at a shell prompt: allegro-config --env You can catenate the output to your .bash_profile, which is pretty much like adding all of the above commands. Note that `allegro-config' itself is in the `bin' directory of the installation, so either make sure that directory is in your path before running `allegro-config' or specify the path exactly, for example: ~/bin/allegro-config --env >> ~/.bash_profile ========================================== ============ Notes on drivers ============ ========================================== System: On initialisation, Allegro will try to connect to an X server. If it can't find one, it will give up and try to use some different system driver instead (such as the Linux console driver, if it is enabled). This means that to run it in X mode, you must either launch your programs from inside an X session, or have set the DISPLAY environment variable to indicate what server you would like to use. Graphics: There are two different X graphics drivers: GFX_XWINDOWS uses only standard X calls, while GFX_XDGA2 uses the XFree86 DGA 2.0 extension (shipped with XFree86 4.0.x) which allows it to write directly to the screen surface, and use hardware acceleration if available. It is normally much faster than the standard X mode, but requires root permissions and will not work remotely. Note that DGA2 is deprecated now. If your program requests a different color depth to the current X display, Allegro will emulate the depth you asked for, so that your program will still work, albeit more slowly than if the color depths were identical. To find out whether this emulation is taking place, look at the gfx_driver->desc field (which is displayed in the middle of the screen by the tests/test program). If this says "matching", the color formats are identical, so no conversions are required. If it says "fast", some simple conversions are taking place, but nothing too painful. If it says "slow", you are in trouble :-) This is not valid for the DGA 2.0 driver, as it'll always change the video mode to the specified resolution and color depth. ==================================== ============ Irix Notes ============ ==================================== If the Irix compiler spits strange lines such as the following when compiling your Allegro program: include/allegro/alcompat.h:59: conflicting types for `ceilf' /usr/include/math.h:311: previous declaration of `ceilf' include/allegro/alcompat.h:60: conflicting types for `floorf' /usr/include/math.h:333: previous declaration of `floorf' include/allegro/alcompat.h:63: conflicting types for `tanf' /usr/include/math.h:176: previous declaration of `tanf' include/allegro/alcompat.h:64: conflicting types for `acosf' /usr/include/math.h:106: previous declaration of `acosf' include/allegro/alcompat.h:65: conflicting types for `asinf' /usr/include/math.h:116: previous declaration of `asinf' then you should #define ALLEGRO_NO_FIX_ALIASES prior to the #include line. allegro4.4-4.4.2/docs/chm/000077500000000000000000000000001173507505700151055ustar00rootroot00000000000000allegro4.4-4.4.2/docs/chm/build/000077500000000000000000000000001173507505700162045ustar00rootroot00000000000000allegro4.4-4.4.2/docs/chm/build/tmpfile.txt000066400000000000000000000001101173507505700203750ustar00rootroot00000000000000This file is needed because some unzip programs skip empty directories. allegro4.4-4.4.2/docs/chm/tmpfile.txt000066400000000000000000000001101173507505700172760ustar00rootroot00000000000000This file is needed because some unzip programs skip empty directories. allegro4.4-4.4.2/docs/devhelp/000077500000000000000000000000001173507505700157655ustar00rootroot00000000000000allegro4.4-4.4.2/docs/devhelp/build/000077500000000000000000000000001173507505700170645ustar00rootroot00000000000000allegro4.4-4.4.2/docs/devhelp/build/tmpfile.txt000066400000000000000000000001101173507505700212550ustar00rootroot00000000000000This file is needed because some unzip programs skip empty directories. allegro4.4-4.4.2/docs/devhelp/tmpfile.txt000066400000000000000000000001101173507505700201560ustar00rootroot00000000000000This file is needed because some unzip programs skip empty directories. allegro4.4-4.4.2/docs/html/000077500000000000000000000000001173507505700153025ustar00rootroot00000000000000allegro4.4-4.4.2/docs/html/build/000077500000000000000000000000001173507505700164015ustar00rootroot00000000000000allegro4.4-4.4.2/docs/html/build/tmpfile.txt000066400000000000000000000001101173507505700205720ustar00rootroot00000000000000This file is needed because some unzip programs skip empty directories. allegro4.4-4.4.2/docs/html/tmpfile.txt000066400000000000000000000001101173507505700174730ustar00rootroot00000000000000This file is needed because some unzip programs skip empty directories. allegro4.4-4.4.2/docs/info/000077500000000000000000000000001173507505700152715ustar00rootroot00000000000000allegro4.4-4.4.2/docs/info/tmpfile.txt000066400000000000000000000001101173507505700174620ustar00rootroot00000000000000This file is needed because some unzip programs skip empty directories. allegro4.4-4.4.2/docs/man/000077500000000000000000000000001173507505700151115ustar00rootroot00000000000000allegro4.4-4.4.2/docs/man/tmpfile.txt000066400000000000000000000001101173507505700173020ustar00rootroot00000000000000This file is needed because some unzip programs skip empty directories. allegro4.4-4.4.2/docs/rtf/000077500000000000000000000000001173507505700151315ustar00rootroot00000000000000allegro4.4-4.4.2/docs/rtf/tmpfile.txt000066400000000000000000000001101173507505700173220ustar00rootroot00000000000000This file is needed because some unzip programs skip empty directories. allegro4.4-4.4.2/docs/scite/000077500000000000000000000000001173507505700154455ustar00rootroot00000000000000allegro4.4-4.4.2/docs/scite/tmpfile.txt000066400000000000000000000001101173507505700176360ustar00rootroot00000000000000This file is needed because some unzip programs skip empty directories. allegro4.4-4.4.2/docs/src/000077500000000000000000000000001173507505700151255ustar00rootroot00000000000000allegro4.4-4.4.2/docs/src/abi._tx000066400000000000000000000104651173507505700164020ustar00rootroot00000000000000@html_text_substitution=readme.txt|readme.txt @external-css=allegro.css @document_title=ABI compatibility information @
@!indent
     ______   ___    ___
    /\  _  \ /\_ \  /\_ \
    \ \ \L\ \\//\ \ \//\ \      __     __   _ __   ___ 
     \ \  __ \ \ \ \  \ \ \   /'__`\ /'_ `\/\`'__\/ __`\
      \ \ \/\ \ \_\ \_ \_\ \_/\  __//\ \L\ \ \ \//\ \L\ \
       \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
        \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
                                       /\____/
                                       \_/__/


                ABI compatibility information.

         See readme.txt for a more general overview.
@indent
@
@heading Introduction We plan to maintain backward compatibility at the Application Binary Interface level for the subsequent releases of the 4.4.x series. For example, that means you will be able to use an executable compiled using version 4.4.0 with version 4.4.5 or 4.4.41 of the dynamically linked library. However, there are some guidelines you should follow. Note: ABI compatibility will only be _actively_ maintained for:
  • Windows on x86 / x86-64
  • Linux on x86 / x86-64
  • MacOS X on PowerPC / x86
We will not be maintaining "forwards compatibility", meaning that programs compiled with a newer release of Allegro may not necessarily run on a target system which has an older release of Allegro installed. You would have to upgrade the Allegro DLL on the target system. While we will try to minimise these kinds of forced upgrades, it should give us more flexibility within the stable series. @heading Windows notes If you don't need a modified version of Allegro then just link your program against an official stable version. Don't disable any features in the DLL. If you require a modified version of Allegro, then please either statically link, or pick a non-standard name for the Allegro DLL. For example, don't distribute a modified version of Allegro under a name such as all44.dll or alleg44.dll. For the people who use vanilla Allegro, we will provide a set of "reference" DLLs. If your binary works with those then everything is fine. If you want to distribute Allegro DLLs with your program (usually a good idea), we recommend you distribute our DLLs instead of ones you compiled yourself. @heading Linux notes When you are ready to distribute your binary, run "ldd <mybinary>". It should say something like: liballeg.so.4.4 => /usr/local/lib/liballeg.so.4.4 (0xdeadbeaf) It should NOT say: liballeg.so.4.4.0 => /usr/local/lib/liballeg.so.4.4.0 (0xdeadbeaf) If you see the latter, that would mean users with later versions of Allegro would not be able to run your binary. See also the Windows section if you need to use a modified version of Allegro. For people packaging Allegro for redistribution: you should try to ensure that a program built against a copy of Allegro with the default configuration will work with your version of the library. @heading MacOS X notes On OSX there are two 'styles' of linking - Unix style and Mac style. For the Unix style linking, you would use `allegro-config --libs` on the link line. For versioning, follow the advice given in the Linux section above, using the command `otool -L' instead of `ldd'. For example, otool -L <mybinary> should give liballeg.4.4.dylib (compatibility version 4.4.0, current version 4.4.0) For the Mac style, use `allegro-config --frameworks` on the link line, or add `Allegro.framework' to your project if you are using XCode. In this case, the versioning is done inside the framework itself. Apple recommends that an application should be entirely self- contained. To achieve this in Allegro, static-link the executable and use `fixbundle' to bind all its resources together. In this way, you will not need to worry about incompatible versions of the library. This is useful if you are distributing an application. There is a known compatibility problem when using gcc 4 on MacOS X 10.4 that prevents binaries from working on older versions of MacOS X. While it is anticipated that a future update from Apple will fix this problem, you can use gcc 3 to work around it. allegro4.4-4.4.2/docs/src/addons._tx000066400000000000000000000110211173507505700171040ustar00rootroot00000000000000@# @# This is the source for the Addon libraries, in a weird custom @# format. Read makedoc.c for a description of what is going on... @# @html_text_substitution=docs/txt/targets.txt|docs/txt/targets.txt @external-css=allegro.css @document_title=Addon libraries

Addon libraries


This document contains general information about addon libraries that are distributed with Allegro. For more detailed info on API, usage and updates, refer to the documentation and web site of the specific addon library. @!text @heading Contents @shortcontents @text @heading Building addons All available addons are built automatically if all the required dependencies are found. To disable building of the specific addon, set the appropriate CMake variables to off. You can use ccmake to browse the list of options. @heading Available addons Since Allegro 4.4, several addon libraries are bundled in the Allegro package. These are some of the most commonly used addons because they contain some handy features that Allegro lacks. Hopefully, with these addons you will need less additional libraries for your game. One advantage of bundled addons is that their build system is integrated with Allegro's build system. Addons are automatically configured, built, installed and uninstalled with Allegro. However, you can perform these operations separately for each addon, if that will better suit your needs. Finally, if you think that some addons, in your opinion, should be included, feel free to contact Allegro developers and we will consider your proposal. @@ AllegroGL AllegroGL is an Allegro add-on that allows you to use OpenGL alongside Allegro -- you use OpenGL for your rendering to the screen, and Allegro for miscellaneous tasks like gathering input, doing timers, getting cross-platform portability, loading data, and drawing your textures. So this library fills the same hole that things like GLUT do. AllegroGL also automatically exposes most, if not all, OpenGL extensions available to user programs. This means you no longer have to manually load them; extension management is already done for you. License: dual-licensed under GPL and zlib. More info: @@ loadpng PNG (Portable Network Graphics) is a cool raster image file format. libpng is the reference library for working with PNG files. loadpng is some glue that makes it easy to use libpng to load and save bitmaps from Allegro programs. loadpng depends on zlib and libpng libraries. Instructions for getting and installing these can be found on loadpng webiste. License: public domain More info: @@ logg LOGG is an Allegro add-on library for playing OGG/Vorbis audio files. It can load OGG/Vorbis files as Allegro SAMPLE's, or it can stream them from disk to save memory. It depends on libogg and libvorbis, available from vorbis.com. License: MIT License. See addons/logg/LICENSE.TXT More info: @@ jpgalleg This addon library lets you load baseline and progressive encoded JPG images, and to save baseline JPGs. It is standalone (no dependencies except for Allegro), compact (compiled lib weights 40K!) fast and standard compliant (it'll load almost any JPG you'll throw at it!). Ships with sources, documentation, examples and a Grabber plugin, and supports any platform supported by Allegro. License: zlib/libpng. See addons/jpgalleg/license.txt. More info: allegro4.4-4.4.2/docs/src/ahack._tx000066400000000000000000000676151173507505700167270ustar00rootroot00000000000000@# @# This is the source for the Allegro Hacker's Guide, in a weird custom @# format. Read makedoc.c for a description of what is going on... @# @html_text_substitution=readme.txt|readme.txt @external-css=allegro.css @document_title=Allegro Hacker's Guide

The Allegro Hacker's Guide


This is a guide to some of the internal workings of Allegro, for people who are interested in hacking on it. This document is far from complete, and may not always be 100% accurate. Remember that when in doubt, the sources are always the definitive reference. Suggestions for what to include in this document will be very welcome: there is far too much code for me to go over it all in any kind of detail, so I want to concentrate on the things that people find most confusing... @!text @heading Contents @shortcontents @text @heading Coding Style I'm not going to be a fascist about this, but it does make life easier if all the code uses a consistent layout. If you are going to write and maintain more than one complete source file of your own, I think you are entitled to do that however you like, but for smaller contributions, I will probably reformat your code to fit in with my existing style. It will obviously save me time if you write it this way in the first place, hence this description: Basic Allegro style: K&R, with 3 space indentation. On disk, though, tab stops are 8 spaces, so if for example a line was indented by 12 spaces, this would be saved out as either 12 space characters or 1 tab and 4 spaces, not as 4 tabs. Because this format always will lead to code display looking broken in place or another, new patches should now always use spaces only and no longer contain tabs. The indent.pro file included with the Allegro distribution comes close to getting this layout right, but doesn't quite manage it, so some things still need to be cleaned up by hand. Preprocessor defines and structure names are UPPER_CASE. Function and variable names are lower_case. MixedCaseNames are evil and should not be used. That silly m_pHungarian notation is _really_ evil and should not even be thought about. All symbols should be declared as static unless that is absolutely not possible, in which case they should be prefixed with an underscore. Functions look like this: /* foobar: * Description of what it does. */ void foobar(int foo, int bar) { /* do some stuff */ } Three blank lines between functions. Conditionals look like: if (foo) { /* stuff */ } else { /* stuff */ } The only time when something comes on the same line after a closing brace is at the end of a do/while loop, eg: do { /* stuff */ } while (foo); Case statements look like this: switch (foo) { case bar: /* stuff */ break; default: /* stuff */ break; } Examples of where to put spaces: char *p; if (condition) { } for (x=0; x<10; x++) { } function(foo, bar); (BITMAP *)data[id].dat; All sources should begin with the standard header: /* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Brief description of what this file does. * * By Author. * * Cool stuff added by Someone Else. * * Stupid bug fixed by a Third Person. * * See readme.txt for copyright information. */ Author credits should be added in chronological order, and email addresses should not be included: those can be found in the main credits file, and if they only exist in one place, it is easier to update them when people change address. People only need to be listed in the source file header if they've made a significant contribution to it (one-line fixes don't count), but no matter how small their addition, they must be added to the docs/thanks._tx file. This is sorted alphabetically by name. If they are already in it, update the text to describe the new addition, otherwise make a new entry for the new contributor. Also, anything more than very tiny modifications should be added to the docs/changes._tx file, which grows from the top in reverse chronological order. This file should briefly describe both the nature of the modification and who did it. @heading Build Process [This is outdated. Now we use CMake.] This is very different depending on whether you are using autoconf or a fixed makefile. For most platforms, though, the fixup script (eg. fixdjgpp.bat), will create a small makefile, which defines MAKEFILE_INC to the make of another file (eg. makefile.dj), and then includes makefile.all. This contains a lot of generic rules, and includes the file named in MAKEFILE_INC to provide additional platform-specific information. The actual source files are listed in makefile.lst. There are three library targets: alleg (release), alld (debugging), and allp (profiling). Objects go in obj/compiler/version/, where version is one of alleg, alld, or allp. Libraries go in lib/compiler/. A few generated things (asmdefs.inc, mmxtest.s, etc), go in the root of obj/compiler/. Dependencies are generated by "make depend", and go in obj/compiler/version/makefile.dep, which is included by makefile.all. When you run "make clean", this only deletes harmless generated files like the objects. "make distclean" strips you right back to the original distribution, including getting rid of the test executables and the library itself. For the ultimate in personal hygene, run "make veryclean", which will wipe absolutely all generated files. After doing this, you will have to run "make depend" before you can build the library, and also "fixdll.bat" if you are working on a Windows platform. To pass long commandlines to the MSVC and Watcom linkers, the program runner.exe is compiled using gcc, so make can pass it a decent number of arguments. This just saves the parameters into a temporary file, and then invokes the real command using that as an argument file. All the makefiles currently use gcc for dependency generation, because this is easier than trying to get MSVC or Watcom to output the right info. The symbol LIBRARY_VERSION, defined at the top of the makefile.ver, is used for including a version number in things like the DLL filename. @heading Header Files allegro.h lives in the include/ directory. It is only a placeholder which includes other headers which live in the include/allegro/ tree. The reason for this slightly odd approach is that allegro.h can include things like "allegro/keyboard.h", which will work both in-situ within the build directory, and if we copy allegro.h to the system include directory and the other headers into system_include/allegro/. This avoids cluttering the system directories with lots of our headers, while still allowing programs to just #include <allegro.h>, and also makes it possible for people to access keyboard stuff with #include <allegro/keyboard.h>. base.h includes alconfig.h, which checks the current platform and includes a helper header for this compiler (aldjgpp.h, almsvc.h, alwatcom.h, etc). That helper header defines a bunch of macros describing the system, emulates whatever things are needed to make the code compile properly, and optionally defines ALLEGRO_EXTRA_HEADER and ALLEGRO_INTERNAL_HEADER if it is going to need any other platform-specific includes. After including the platform header, the rest of alconfig.h defines a lot of generic helper macros to their default values, but only if the platform header hasn't already overridden these to something specific. Every module-specific header contains structure definitions and function prototypes. At the end of the file, it may include a header from the include/allegro/inline/ directory which defines related inline routines. If inline asm is supported, this can include in turn asm.inl which imports routines from one of the compiler-specific files al386gcc.h, al386vc.h and al386wat.h; otherwise C versions are used instead. The header alinline.h is a placeholder which includes all the headers defining inline functions. If ALLEGRO_EXTRA_HEADER is defined, allegro.h includes this at the very end. This is used to include one of the files aldos.h, alwin.h, etc, which define platform-specific things like ID values for the hardware drivers. Unlike the platform files included from the top of allegro.h, these are specific per-OS rather than per-compiler, so the same alwin.h can be used by both MSVC and MinGW. They describe library functions that relate to this platform, while the earlier header described the basic language syntax. aintern.h is like the internal.h in earlier Allegro versions, defining routines that are shared between multiple sources, but that we don't generally want user programs to see. On platforms which have specific, non-portable API routines of their own, these should go in a special header in the root of the include directory, eg. winalleg.h. This can be included by user programs that want to access these routines, while making it very clear to them that by including this header, they are writing non-portable code. @heading Definitions All header function prototypes should use the macro AL_FUNC(). Inline routines use the macro AL_INLINE(). Global variables use AL_VAR() or AL_ARRAY(). Global pointers to functions use AL_FUNCPTR(). Pointers to functions which are passed as parameters to other routines or stored in a structure typedef use AL_METHOD(). This may seem like something of an overkill, but it gives us a lot of flexibility to add DLL import/export specifiers, calling convention markers like __cdecl, and even to mangle symbol names on some compilers. If you forget to use these macros, your code won't work on some platforms. This only applies to header files, though: you can write normal code in the C sources. The symbol ALLEGRO_SRC is defined while compiling library source files. If you want to inline a function in one of your sources, use the INLINE macro. To declare a zero-sized array in terminal position inside a structure, use the ZERO_SIZE_ARRAY(type, name) macro. To use 64 bit integers, declare a LONG_LONG variable (this won't be defined on all platforms). To do things with filenames, check the macros ALLEGRO_LFN, OTHER_PATH_SEPARATOR, and DEVICE_SEPARATOR. See the headers for details. @heading Unicode Support Do not assume that strings are ASCII. They aren't. If you assume they are, your code might work for a while as long as people are only using it with UTF-8 data, but it will die horribly as soon as someone tries to run it with 16 bit Unicode strings, or Chinese GB-code, or some strange MIME format, etc. Whenever you see a char * being passed around, you must be aware that this will actually contain text in whatever format is currently selected, so you have to be damn careful when manipulating strings. Don't ever forget and call a regular libc routine on them! Use the Unicode functions for all your text manipulation: see the docs for details. When allocating a scratch string on the stack, assume that each character will occupy at most four bytes: this will give you more than enough space for any of the current encoding schemes. If you want to specify a constant string, use the function uconvert_ascii("my string", buf) to obtain a copy of "my string" in the current encoding format. If buf is NULL, this will use an internal static buffer, but the converted string will be overwritten by the next call to any format conversion routines, so you shouldn't pass it down into other library functions. Normally you should provide the conversion space yourself, allocating buf as a temporary object on the stack. To convert the other way (eg. before passing an Allegro string to an OS routine that expects ASCII data), call uconvert_toascii(mystring, buf). For any messages that may be seen by the user, you can call get_config_text("my ascii string") instead of uconvert_ascii(). This will return a pointer to persistent memory (so it is ok to keep the string around indefinitely), after converting into the current text encoding format. This function is cool because it saves you having to bother allocating space for the converted data, and because it allows the string to be replaced by the translations in language.dat. You should be sure to always pass a constant string to get_config_text(), rather than any generated text or data from other string variables: this is so that the findtext.sh script can easily locate all the strings that need to be translated. Hardware drivers should initialise their name and desc fields to the global empty_string, and store an ASCII driver name in their ascii_name field. The framework code will automatically translate and convert this value, storing the result in both the name and desc fields. For most drivers this will be enough, but if you want to provide a more detailed description, it is up to your driver to set this up from their init routine, and take care of all the required conversions. @heading Asm Routines [We don't use hand written asm any more.] Structure offsets are defined in asmdef.inc, which is generated by asmdef.c. This allows the asm code to use human readable names for the structure members, and to automatically adjust whenever new fields are added, so it will always exactly match the layout of the C structures. Asm code should use the macro FUNC(name) to declare the start of a routine, and GLOBL(name) whenever it wants to refer to an external symbol (eg. a C variable or function). This is to handle name mangling in a portable way (COFF requires an underscore prefix, ELF does not). You can modify %ds and %es from asm, as long as you put them back. If USE_FS and FSEG are defined, you can also change %fs, otherwise this is not required and you can safely use nearptr access for everything. Don't assume that the MMX opcodes will be supported: not every assembler version knows about these. Check the ALLEGRO_MMX macro, and be sure to give up gracefully if these instructions are not available. @heading Documentation One of the nicest features of Allegro is its excellent manual, that you can read in several formats, ranging from plain text to compiled HTML. All API functions of the library have to be documented in docs/src/allegro._tx in the appropriate section. Note that, whatever you write in the file, you shouldn't exceed a line width of 78 characters, except for lines which contain tags. This rule is needed in order to produce correct plain text documentation that doesn't extend beyond the standard 80 column screen/terminal. All the other formats are less strict about line width and will probably reformat the text anyway. If the function you are documenting returns a value, use the @retval command to start the chunk of text that describes the return value or how it is used. If the function takes parameters, document if they are required to follow a specific format (e.g. string encoding), what they are for, and their range of values (if any). The latter is particularly important for boolean parameters, because there's no way to tell the user that an integer must be either `true' or `false' in the C programming language. Parameters are always referred to between single quotes, left and right. These are tt-ized in the HTML version, but only if there are no space characters between the left and right quote. If it is possible to include a little fragment of code which demonstrates the usage of the function, do it just before the @retval command if there is one, or at the end of the block. This is very welcome for functions that don't have example references (@eref). You don't need to include the declaration of the variables unless you really think it can help newbies. Usually a single line will be enough, but don't hesitate to add whatever comments you might think of as useful for newbies. Also, if you are writing such a one liner, try to use verbose variable names to indicate where they come from or what they should contain. Compare the following lines, where the second is more likely to be found in `real life' code, but should be avoided in these little code fragments taken out of context: blit(source_bitmap, destination_bitmap, source_x, source_y, destination_x, destination_y, bitmap_width, bitmap_height); ... blit(spr[3]->bmp, screen, x, y, s_x, s_y, spr[3]->bmp->w, spr[3]->bmp->h); Whatever coding style applies to Allegro's code also applies to these examples (e.g. 8 characters tab, 3 spaces indentation). If you are having trouble documenting a particular function because you don't know how to approach the task (this tends to happen when you have used the function so much that you have learnt it by heart), here is a checklist you can follow:
  • What is the purpose of the function? Why would the user want to call it?
  • Can you call it at any time or is any other function required to have been called before (excluding install_allegro/allegro_init)?
  • What do the parameters mean? Do they have a precisely defined type? Do they have a range (like boolean integers)?
  • If the function returns a value, what is it? What can it be used for? Is it likely to be the input of another Allegro function? Does the return value have a range (e.g. positive numbers mean success, negative ones failure)?
  • Is this function supported across all platforms that Allegro runs on? What does it do if it is not supported? Does it require a more thorough explanation in the platform-specific section of the documentation?
  • Should the description say whether the function is reentrant or not? Do you think users would like to use it concurrently in multithreaded environments?
Don't bother about existing example references (@eref). These are generated automatically by a script. The person in charge of releasing Allegro will most surely do this for you. If you know how to run it, you are very welcome to update these tags though, to avoid piling extra work on the maintainer's shoulders. Of course, all said about documenting functions applies to macros and variables too. @heading Debugging helpers As a developer you are encouraged to spill as many ASSERT and TRACE macros as you consider necessary. ASSERT macros are a very good way of enforcing documented limitations in input parameters which should never happen during a perfect (ie. bugless) version of your game. They are good for things like verifying some Allegro subsystem was initialised at the entry point of a function which depends on it, or passing NULL pointers where the documentation explicitly says the user is not allowed to do so. The TRACE macro is very good for things which are not very repetitive, mainly initialisation functions. The problem with C code is that usually error reporting to the user programmer layer is done through a simple integer or NULL pointer, and the error description (if any) stored in allegro_error. This is clearly insufficient for functions like set_gfx_mode() which test many graphic drivers before bailing out. What should be the error code in such case? How could you preserve a coherent error message to the user in driver A when driver B later overwrites it with some other error which may not interest the user trying to run driver A? Developers have made plans to include better logging facilities in future Allegro releases. In the meantime, it is good if opaque systems like drivers use TRACE both to indicate success and failure. For this reason there is a TRACE convention for Allegro code using this macro. At the top of the source file you want to use TRACE define three macros: PREFIX_I, PREFIX_W, PREFIX_E. Each of this should be a string in the format "al-SYSTEM LEVEL: " where SYSTEM is usually the filename creating the TRACE (but doesn't have to) and LEVEL is either INFO, WARNING or ERROR respectively. Later you can use them like this: if (some_error_in_a_deep_obscure_function) { TRACE(PREFIX_E "Couldn't init obscure driver because %s", something); return -1; } TRACE(PREFIX_I "Obscure system initialised with option %s", switch); Thanks to this prefix convention a user can use the TRACE macro too and grep Allegro's messages if there is no interest in them. @heading Other Stuff Any portable routines that run inside a timer handler or input callback must be sure to lock all the code and data that they touch. This is done by placing an END_OF_FUNCTION(x) or END_OF_STATIC_FUNCTION(x) after each function definition (this is not required if you declare the function as INLINE, though), and then calling LOCK_FUNCTION() somewhere in your init code. Use LOCK_VARIABLE() to lock global variables, and LOCK_DATA() to lock allocated memory. Any modules that have cleanup code should register their exit function by calling _add_exit_func(). This will ensure that they are closed down gracefully no matter whether the user calls allegro_exit(), falls off the bottom of main(), or the program dies suddenly due to a runtime error. You must call _remove_exit_func() from inside your shutdown routine, or you will find yourself stuck in an endless loop. @heading How to contribute patches Once you are willing to contribute that beautiful hack which does what everybody has been waiting for, the fix for that hideous bug which has been driving you mad for several nights, the nice improved documentation you would have liked to read in the manual for the first time, etc, you have already done the hardest part. Now you only need a way to let the Allegro developers merge your changes in the main distribution. You could probably send your patch to one of the people working on Allegro, but this is not very safe, it depends on the person you chose being available and willing to do the work for you. The best you can do is to send your patch to the Allegro Developers mailing list. Read the readme.txt file for information on how to subscribe to this list. Alternatively, updated subscription instructions should always be available at http://alleg.sourceforge.net/maillist.html. Sending your patches to the mailing list instead of a single person is good, because all the subscribed developers can take a look at your modifications, suggest improvements, or find problems, which you can discuss on the same mailing list, letting other developers join the conversation when they consider appropriate. If the modifications are good, they will probably be accepted and merged in the WIP version for the next release. If you aren't lucky, or your patch still needs some work, you will be told why it's not accepted, or what you have to do to improve it. If you aren't subscribed to the list, remember to say this in your message as, by default, replies are irected to the list. You can also use SourceForge's issue web trackers, which you can find at http://sourceforge.net/tracker/?group_id=5665. This doesn't require you to subscribe to any mailing list and you can verify every now and then the status of your contribution. @hnode Building your patch against an existent release If you have obtained Allegro from an existent release, stable or unstable, you will have all the source code contained in some archive format. You will need it, because to create a patch you need two versions of each modified file, the original version, and your modified version. You will also need the diff tool, which is used to create the patches. This tool is usually packaged as a standalone package in most GNU/Linux distributions with the same name. For DOS, you can get a port from http://www.delorie.com/djgpp/. Just choose a mirror from http://www.delorie.com/djgpp/getting.html, enter the v2gnu directory and download the difxxb.zip package. While you are at it, you can also get a tool named patch (patxxb.zip), which is used to apply patches generated by diff, in case you have to apply the patches somebody else sends to you. Install the binaries in some directory of your path, so that you can use them from anywhere. If you are planing to modify only one file, you will usually copy this file to the same name in the same directory with the appended extension '.old' before starting to work on it. After you have made your modifications to the file, and verified that they please you, go to the directory containing the modified and original files and type at the prompt: diff -u file.c.old file.c > patch This command will generate a text file which contains the differences between both files in unified output format. Open it with your prefered editor and verify that it contains the modifications you wanted to do: lines you have added will be marked with a plus sign '+', lines you have removed will be marked with a minus sign '-'. If the file is bigger than a few kilobytes, compress it before sending to the developers mailing list, and of course remember to add an explanation of what the patch is meant to do, why it's needed, and any other information you consider relevant. If the modifications you want to do are scattered through several files and/or directories, this form of patch generation is very tiresome for both ends (you, and the developers). So unpack a fresh copy of the Allegro source somewhere and move it to the parent directory where your current version is, after giving it another name of course, so as to obtain two complete sources trees side by side. Modify the files you wish in your working directory. Once you are finished, go back to the parent directory housing the two source trees and type: diff -ur fresh_original_directory working_directory > patch The '-r' switch makes diff compare directories recursively. Again, do the previous steps of verifying your patch, compressing and sending with correct instructions. If your patch adds or removes files, you will have to add the '-N' switch, because by default diff will ignore files which are only in one of the trees. Of course, you might want to run a 'make clean' in your working directory before running this command, or you will include lots of generated files which have nothing to do with your patch. Or you could edit the resulting patch, but that can be error prone. @hnode Building your patch against a SVN version If you are working with the SVN version of Allegro which you can get from Sourceforge (http://sourceforge.net/projects/alleg/), you won't need to copy any files at all. Just modify the files you want, go to the root directory of the SVN copy and type: svn diff > patch Unlike the standalone diff, the svn diff command will work recursively through the Allegro source tree, comparing each file against the Sourceforge repository. The patch will have slightly different headers, but that's ok, once you have it follow the previous process to send it to the developers mailing list. Of course, check the Subversion manual for more information and options. @hnode Online patch creation Sometimes you don't have the diff tool around, or don't have the SVN tool to check out the bleeding edge version of Allegro, or you are too lazy to care how to actually make the patch yourself. For any of those cases, you can use the online Allegro patcher at http://www.allegro.cc/dev/make-diff.php. To use it, first you have to get one of the source files of Allegro and make your changes to it. Then, go to that URL and supply the local path on your computer to the modified file. Then, you write the path of this file relative to Allegro's root. If everything goes well, you will end up with a patch you can send to the Allegro developers mailing list or post on SourceForge's patch submission page. allegro4.4-4.4.2/docs/src/allegro._tx000066400000000000000000027101671173507505700173040ustar00rootroot00000000000000@# @# 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.4.2" "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.4.2


		A game programming library.

	     By Shawn Hargreaves, May 19, 2011.

		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.2.1 (SVN)' for an Allegro version obtained straight from the SVN 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_WIN2003 - Windows 2003 OSTYPE_WINVISTA - Windows Vista OSTYPE_OS2 - OS/2 OSTYPE_WARP - OS/2 Warp 3 OSTYPE_DOSEMU - Linux DOSEMU OSTYPE_OPENDOS - Caldera OpenDOS OSTYPE_LINUX - Linux OSTYPE_SUNOS - SunOS/Solaris OSTYPE_FREEBSD - FreeBSD OSTYPE_NETBSD - NetBSD OSTYPE_IRIX - IRIX OSTYPE_DARWIN - Darwin OSTYPE_QNX - QNX OSTYPE_UNIX - Unknown Unix variant OSTYPE_BEOS - BeOS OSTYPE_MACOS - MacOS OSTYPE_MACOSX - MacOS X @@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 independent way when some Allegro subsystem cannot be initialised. But you must not use this function if you are in a graphic mode, only before calling set_gfx_mode(), or after a set_gfx_mode(GFX_TEXT). Also, this function depends on a system driver being installed, which means that it won't display the message at all on some platforms if Allegro has not been initialised correctly. On platforms featuring a windowing system, it will bring up a blocking GUI message box. If there is no windowing system, it will try to print the string to a text console, attempting to work around codepage differences by reducing any accented characters to 7-bit ASCII approximations. Example: 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 appropriate section when it's already described there. Note that unless stated otherwise, the contents shown here are just for read only purposes, there might be other internal flags, but you shouldn't depend on them being available in past/future versions of Allegro. @@typedef long @fixed @xref Fixed point math routines @eref ex12bit, ex3buf, ex3d, excustom, exfixed, exrotscl, exspline @eref exsprite, 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, al_ffblk_get_size @shortdesc Cross platform structure storing file information. int attrib; - actual attributes of the file found time_t time; - modification time 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 compression. 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 decompression. 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 High 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' whose length in bytes is specified by `size' and which is guaranteed to be null-terminated even if `src' is bigger than `size'. 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 occurrence 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 for 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 occurrence of a string in another one. This function finds the first occurrence 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 re-entrant (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. Note that variable and section names cannot contain spaces. By default the configuration data is read from a file called `allegro.cfg', which can be located either in the same directory as the program executable, or the directory pointed to by the ALLEGRO environment variable. Under Unix, it also checks for `~/allegro.cfg', `~/.allegrorc', `/etc/allegro.cfg', and `/etc/allegrorc', in that order; under BeOS only the last two are also checked. MacOS X also checks in the Contents/Resources directory of the application bundle, if any, before doing the checks above. If you don't like this approach, you can specify any filename you like, or use a block of binary configuration data provided by your program (which could for example be loaded from a datafile). You can also extend the paths searched for allegro resources with set_allegro_resource_path(). You can store whatever custom information you like in the config file, along with the standard variables that are used by Allegro (see below). Allegro comes with a setup directory where you can find configuration programs. The standalone setup program is likely to be of interest to final users. It allows any user to create an `allegro.cfg' file without the need to touch a text editor and enter values by hand. It also provides a few basic tests like sound playing for sound card testing. You are welcome to include the setup program with your game, either as is or with modified graphics to fit better your game. @@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. (Allegro will not search for this file in other locations as it does with allegro.cfg at the time of initialization.) 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(). @@int @list_config_entries(const char *section, const char ***names); @xref set_config_file, get_config_string, list_config_sections @xref free_config_entries @shortdesc Lists the names of all entries in a config section This function can be used to get a list of all entries in the given config section. The names parameter is a pointer to an array of strings. If it points to a NULL pointer, the list will be allocated, else it will be re-allocated. You should free the list again with free_config_entries if you don't need it anymore, or you can pass it again to list_config_entries and the memory will be re-used. See the following example for how you can use it, it will print out the complete contents of the current configuration: int i, n; char const **sections = NULL; char const **entries = NULL; /* List all entries not in any section. */ n = list_config_entries(NULL, &entries); for (i = 0; i < n; i++) printf(" %s=\"%s\"\n", entries[i], get_config_string( NULL, entries[i], "-")); /* List all sections (and entries in them). */ n = list_config_sections(§ions); /* loop through all section names */ for (i = 0; i < n; i++) { int j, m; printf("%s\n", sections[i]); m = list_config_entries(sections[i], &entries); /* loop through all entries in the section */ for (j = 0; j < m; j++) { printf(" %s=\"%s\"\n", entries[j], get_config_string( sections[i], entries[j], "-")); } } /* It is enough to free the arrays once at the end. */ free_config_entries(§ions); free_config_entries(&entries); @retval Returns the number of valid strings in the names array. @@int @list_config_sections(const char ***names); @xref list_config_entries, set_config_file, get_config_string @xref free_config_entries @shortdesc Lists the names of all sections available in the current configuration. The names parameter is a pointer to an array of strings. If it points to a NULL pointer, the list will be allocated, else it will be re-allocated. After the function returns, it will contain the names of all sections in the current configuration. Use free_config_entries to free the allocated memory again. See list_config_entries for more information and an example how to use it. @retval Returns the number of valid strings in the names array. @@int @free_config_entries(const char ***names); @xref list_config_entries, list_config_sections @shortdesc Frees memory allocated for config entry lists. Once you are done with the string arrays filled in by list_config_entries and list_config_sections, you can free them again with this function. The passed array pointer will be set to NULL, and you directly can pass the same pointer again to list_config_entries or list_config_sections later - but you also could pass them again without freeing first, since the memory is re-allocated when the pointer is not NULL. See list_config_entries for an example of how to use it. @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 X-Windows ("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 base name like `us' or `uk'. If the latter, Allegro will look first for a separate config file with that name (eg. `uk.cfg') and then for an object with that name in the `keyboard.dat' file (eg. `UK_CFG'). The config file or `keyboard.dat' file can be stored in the same directory as the program, or in the location pointed to by the ALLEGRO environment variable. Look in the `keyboard.dat' file to see what mappings are currently available.
    • language = x
      Specifies which language file to use for error messages and other bits of system text. The parameter is the name of a translation file, and can either be a fully qualified file path or a base name like `en' or `es'. If the latter, Allegro will look first for a separate config file with a name in the form `entext.cfg', and then for an object with that name in the `language.dat' file (eg. `ENTEXT_CFG'). The config file or `language.dat' file can be stored in the same directory as the program, or in the location pointed to by the ALLEGRO environment variable. Look in the `language.dat' file to see which mappings are currently available. If there is none for your language, you can create it using the English one as model, and even send it to the Allegro development team to include it in future releases.
    • 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.
    • XInitThreads = x
      If this is set to 0, the X11 port will not call XInitThreads. This can have slight performance advantages and was required on some broken X11 servers, but it makes Allegro incompatible with other X11 libraries like Mesa.
  • [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 additional 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. If you want to use only part of a tablet, you need to set the entries for X and Y axis by hand.
    • ev_abs_to_rel_x = x
      ev_abs_to_rel_y = x
      ev_abs_to_rel_z = x
      Linux only: scaling factor for tablet mouse speed. Defaults to 1. This is used only when the input sends absolute events (tablet, joystick, etc.) and the cursor should behave like a mouse. If you are using a mouse on a tablet, you need to set these entries for X and Y axis (try numbers between 1 and 40).
    • 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 sound card) 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 sound card port address (this is usually 220).
    • sound_dma = x
      DOS only: sets the sound card DMA channel (this is usually 1).
    • sound_irq = x
      DOS only: sets the sound card 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 up to a certain size. Allegro will fall back on its own cursor drawing if it cannot let the OS handle this. On some platforms, the hardware cursor is incompatible with get_mouse_mickeys() and it is therefor disabled by default. In such cases you need to call enable_hardware_cursor() to enable it explicitly.
  • 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 overridden 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 substitution (should the operating system's native cursor be unavailable). The bitmap must remain available for the duration in which it could be used. Passing NULL lets Allegro revert to its default substitutions. The effect of this function will not be apparent until show_mouse() is called. @@extern volatile int @mouse_x; @@extern volatile int @mouse_y; @@extern volatile int @mouse_z; @@extern volatile int @mouse_w; @@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' and `mouse_w' variables hold the current vertical and horizontal wheel position, when using an input driver that supports wheel mice. The `mouse_b' variable is a bitfield indicating the state of each button: bit 0 is the left button, bit 1 the right, and bit 2 the middle button. Additional non standard mouse buttons might be available as higher bits in this variable. Usage example: 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. Note: you must not be showing a mouse pointer on a bitmap at the time that the bitmap is destroyed with destroy_bitmap(), e.g. call show_mouse(NULL); before destroying the bitmap. This does not apply to `screen' since you never destroy `screen' with destroy_bitmap(). @@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 succeeded or not. On some systems (e.g. DirectX fullscreen) this is not supported and the function will always fail, and in other cases only some of the cursors will work, or in the case of MOUSE_CURSOR_ALLEGRO, only certain bitmap sizes may be supported. You never should use show_os_cursor together with the function show_mouse and other functions affecting it (select_mouse_cursor, enable_hardware_cursor, disable_hardware_cursor, scare_mouse, unscare_mouse). They implement the standard high level mouse API, and don't work together with this low level function. @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 @xref position_mouse_w @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, position_mouse_w @shortdesc Sets the mouse wheel position global variable. Sets the mouse wheel position variable to the specified value. @@void @position_mouse_w(int w); @xref install_mouse, position_mouse @shortdesc Sets the horizontal mouse wheel position. Sets the horizontal mouse wheel position 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. @@int @mouse_on_screen(); @shortdesc Tells you whether the mouse pointer is currently on screen. This function can be useful to prevent having two mouse pointers on the screen at the same time when running your program in windowed mode and drawing the mouse pointer yourself. Other possible uses include the ability to pause your game when the mouse goes off of the window, or only scrolling the view when the pointer is near the edge of the window, but not while off of the window. Example : if (mouse_on_screen()) {draw_sprite(buffer , mouse_sprite , mouse_x , mouse_y);} @retval Returns 0 if the mouse pointer is off of the screen, or non-zero otherwise. @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 occurred precisely at the last tick). The speed is given in hardware clock ticks, of which there are 1193181 a second. You can convert from other time formats to hardware clock ticks with the macros: 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 Available Allegro examples @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 accomplished through the keyboard variable of the system section in a standard `allegro.cfg' configuration file. Read chapter "Configuration routines" for more information about this. @@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_mode 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 deactivate 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. Installs Allegro's joystick handler, and calibrates the centre position values. The type parameter should usually be JOY_TYPE_AUTODETECT, or see the platform specific documentation for a list of the available drivers. You must call this routine before using any other joystick functions, and you should make sure that all joysticks are in the middle position at the time. Example: 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 handler 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 eight 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. Pass the number of the joystick you want to calibrate as the parameter. @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 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:
  • 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 whether 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. @@int @get_gfx_mode_type(int graphics_card); @xref gfx_mode_select_filter, get_gfx_mode, set_gfx_mode, is_windowed_mode @shortdesc Retrieves type information for a specific graphics card. This function lets you determine the types of operating modes that a specific graphics card driver operates in. It will tell you whether it is a windowed, fullscreen, definitely windowed or fullscreen, and/or a magic driver. The value returned is a bitfield consisting of these fields:
GFX_TYPE_UNKNOWN
GFX_TYPE_WINDOWED
GFX_TYPE_FULLSCREEN
GFX_TYPE_DEFINITE
GFX_TYPE_MAGIC

The return value will only be equivalent to GFX_TYPE_UNKNOWN when it is a driver unrecognized on that platform, or it is a bogus value. Test for the other types by using a bitwise AND. If the driver is windowed or fullscreen, it will also have the definite flag set. For example, int gfx_type = get_gfx_mode_type(GFX_AUTODETECT_WINDOWED); gfx_type would have the GFX_TYPE_WINDOWED, GFX_TYPE_DEFINITE, and GFX_TYPE_MAGIC flags set. Allegro needs to be initialized first. Example: /* Accept the use of only windowed drivers in our selection dialog */ int accept_windowed(int card , int w , int h , int color_depth) { if (get_gfx_mode_type(card) & GFX_TYPE_WINDOWED) return 0; return 1; } /* In main: */ gfx_mode_select_filter(&card, &w, &h, &color_depth, accept_windowed); @retval Returns a bitfield describing the graphics mode type. @@int @get_gfx_mode(); @xref set_gfx_mode, is_windowed_mode @shortdesc Returns the id of the current graphics driver. This function will let you determine which graphics driver is currently set by allegro. If no graphics driver is set, it will return GFX_NONE. @retval Returns the id of the current graphics driver if there is one, or GFX_NONE if none is set. @@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. GFX_HW_VRAM_STRETCH_BLIT:
Indicates that stretched blitting of video bitmaps onto the screen is implemented using hardware acceleration. GFX_HW_SYS_STRETCH_BLIT:
Indicates that stretched blitting of system bitmaps onto the screen is implemented using hardware acceleration. GFX_HW_VRAM_STRETCH_BLIT_MASKED:
Indicates that masked stretched blitting (including stretch_sprite) of video bitmaps onto the screen is implemented using hardware acceleration. NOTE: some display drivers may show artifacts when this function is used. If the image does not look correct try updating your video drivers. GFX_HW_SYS_STRETCH_BLIT_MASKED:
Indicates that masked stretched blitting (including stretch_sprite) of system bitmaps onto the screen is implemented using hardware acceleration. NOTE: some display drivers may show artefact's when this function is used. If the image does not look correct try updating your video drivers. Note: even if the capabilities information says that patterned drawing is supported by the hardware, it will not be possible for every size of pattern. VBE/AF only supports patterns up to 8x8 in size, so Allegro will fall back on the original non-accelerated drawing routines whenever you use a pattern larger than this. Note2: these hardware acceleration features will only take effect when you are drawing directly onto the screen bitmap, a video memory bitmap, or a sub-bitmap thereof. Accelerated hardware is most useful in a page flipping or triple buffering setup, and is unlikely to make any difference to the classic "draw onto a memory bitmap, then blit to the screen" system. @@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, show_mouse @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. The bitmap must not have a mouse cursor shown on it at the time it is destroyed. @@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. Acquires the specified video bitmap prior to drawing onto it. You never need to call the function explicitly as it is low level, and will only give you a speed up if you know what you are doing. Using it wrongly may cause slowdown, or even lock up your program. Note: You do never need to use acquire_bitmap on a memory bitmap, i.e. a normal bitmap created with create_bitmap. It will simply do nothing in that case. It still can be useful, because e.g. under the current DirectDraw driver of Allegro, most drawing functions need to lock a video bitmap before drawing to it. But doing this is very slow, so you will get much better performance if you acquire the screen just once at the start of your main redraw function, then call multiple drawing operations which need the bitmap locked, and only release it when done. Multiple acquire calls may be nested, but you must make sure to match up the acquire_bitmap and release_bitmap calls. Be warned that DirectX and X11 programs activate a mutex lock whenever a surface is locked, which prevents them from getting any input messages, so you must be sure to release all your bitmaps before using any timer, keyboard, or other non-graphics routines! Note that if you are using hardware accelerated VRAM->VRAM functions, you should not call acquire_bitmap(). Such functions need an unlocked target bitmap under DirectX, so there is now just the opposite case from before - if the bitmap is already locked with acquire_bitmap, the drawing operation has to unlock it. Note: For backwards compatibility, the unlocking behavior of such functions is permanent. That is, if you call acquire_bitmap first, then call e.g. an accelerated blit, the DirectX bitmap will be unlocked internally (it won't affect the nesting counter of acquire/release calls). There is no clear cross-platform way in this Allegro version to know which drawing operations need a locked/unlocked state. For example a normal rectfill most probably is accelerated under DirectX, and therefore needs the screen unlocked, but an XOR rectfill, or one with blending activated, most probably is not, and therefore locks the screen. And while the DirectX driver will do automatic unlocking, there is no such thing under X11, where the function is used to synchronize X11 calls from different threads. Your best bet is to never use acquire_bitmap - changes are you are doing something in the wrong way if you think you need it. Warning: This function can be very dangerous to use, since the whole program may get locked while the bitmap is locked. So the lock should only be held for a short time, and you should not call anything but drawing operations onto the locked video bitmap while a lock is in place. Especially don't call things like show_mouse (or scare_mouse which calls that) or readkey, since it will most likely deadlock your entire program. @@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 Intersects a bitmap's clipping rectangle with the given 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 Available Allegro examples @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, BITMAP *bmp, 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, BITMAP *bmp, 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, BITMAP *bmp, 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, exrotscl, 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 @eref exzbuf @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 @eref exrotscl @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, getr, getg, getb, geta @xref Truecolor pixel formats, Palette routines @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(). To extract the individual color components, use the getr() / getg() / getb() / geta() family of functions. @@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) { ... } do_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. 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. @\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, extrans2 @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_ex(BITMAP *bmp, BITMAP *sprite, int x, int y, @@ int mode, int flip); @xref draw_sprite, draw_sprite_v_flip, draw_sprite_h_flip, draw_trans_sprite, @xref draw_lit_sprite @eref extrans2 @shortdesc Draws a optionally flipped/blended/tinted sprite on the bitmap. Draws the sprite image onto the destination bitmap using the specified mode argument, optionally flipping the sprite in the orientation specified by flip argument. The mode argument defines how is sprite going to be drawn on the destination bitmap: DRAW_SPRITE_NORMAL - draws a masked sprite, like draw_sprite() DRAW_SPRITE_LIT - draws a tinted sprite, like draw_lit_sprite() DRAW_SPRITE_TRANS - draws a blended sprite, like draw_trans_sprite() The flip argument defines the flipping orientation: DRAW_SPRITE_NO_FLIP = 0 - do not perform flipping DRAW_SPRITE_H_FLIP - flip horizontally DRAW_SPRITE_V_FLIP - flip vertically DRAW_SPRITE_VH_FLIP - flip both vertically and horizontally @@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 / step; int height = SCREEN_H / step; 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_sprite_h_flip(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, exrotscl, 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, 64); @\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 @eref exrotscl @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. @@void @rotate_sprite_trans(BITMAP *bmp, BITMAP *sprite, @@ int x, int y, fixed angle); @xref draw_trans_sprite, rotate_scaled_sprite_trans, rotate_sprite_v_flip_trans @xref rotate_scaled_sprite_v_flip_trans @xref pivot_sprite_trans, pivot_sprite_v_flip_trans, @xref pivot_scaled_sprite_trans, pivot_scaled_sprite_v_flip_trans, @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_trans(BITMAP *bmp, BITMAP *sprite, int x, int y, fixed angle); @xref rotate_sprite_trans, rotate_scaled_sprite_v_flip_trans @xref pivot_sprite_v_flip_trans, pivot_scaled_sprite_v_flip_trans @eref exsprite @shortdesc Rotates and flips a sprite. Like rotate_sprite_trans, 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_trans(BITMAP *bmp, BITMAP *sprite, int x, int y, @@ fixed angle, fixed scale); @xref rotate_sprite_trans, rotate_scaled_sprite_v_flip_trans @xref pivot_scaled_sprite_trans, pivot_scaled_sprite_v_flip_trans @eref exrotscl @shortdesc Rotates and stretches a sprite. Like rotate_sprite_trans(), but stretches or shrinks the image at the same time as rotating it. @\void @rotate_scaled_sprite_v_flip_trans(BITMAP *bmp, BITMAP *sprite, @@ int x, int y, @@ fixed angle, fixed scale); @xref rotate_sprite_trans, rotate_scaled_sprite_trans @xref rotate_sprite_v_flip_trans @shortdesc Rotates, stretches and flips a sprite. Draws the sprite, similar to rotate_scaled_sprite_trans() except that it flips the sprite vertically first. @\void @pivot_sprite_trans(BITMAP *bmp, BITMAP *sprite, int x, int y, @@ int cx, int cy, fixed angle); @xref rotate_sprite_trans, pivot_scaled_sprite_trans, pivot_sprite_v_flip_trans @eref exsprite @shortdesc Rotates a sprite around a specified point. Like rotate_sprite_trans(), 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_trans(BITMAP *bmp, BITMAP *sprite, int x, int y, @@ int cx, int cy, fixed angle); @xref rotate_sprite_trans, rotate_sprite_v_flip_trans, pivot_sprite_trans @eref exsprite @shortdesc Rotates and flips a sprite around a specified point. Like rotate_sprite_v_flip_trans(), 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_trans(BITMAP *bmp, BITMAP *sprite, int x, int y, @@ int cx, int cy, fixed angle, fixed scale); @xref rotate_sprite_trans, rotate_scaled_sprite_trans @xref pivot_sprite_trans, pivot_scaled_sprite_v_flip_trans @shortdesc Rotates and stretches a sprite around a specified point. Like rotate_scaled_sprite_trans(), 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_trans(BITMAP *bmp, BITMAP *sprite, @@ int x, int y, @@ int cx, int cy, fixed angle, fixed scale); @xref rotate_sprite_trans, rotate_scaled_sprite_v_flip_trans @xref rotate_sprite_v_flip_trans, pivot_sprite_trans, pivot_scaled_sprite_trans @shortdesc Rotates, stretches and flips a sprite around a specified point. Like rotate_scaled_sprite_v_flip_trans(), 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 @rotate_sprite_lit(BITMAP *bmp, BITMAP *sprite, @@ int x, int y, fixed angle); @xref draw_lit_sprite, rotate_scaled_sprite_lit, rotate_sprite_v_flip_lit @xref rotate_scaled_sprite_v_flip_lit @xref pivot_sprite_lit, pivot_sprite_v_flip_lit, @xref pivot_scaled_sprite_lit, pivot_scaled_sprite_v_flip_lit, @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_lit(BITMAP *bmp, BITMAP *sprite, int x, int y, fixed angle); @xref rotate_sprite_lit, rotate_scaled_sprite_v_flip_lit @xref pivot_sprite_v_flip_lit, pivot_scaled_sprite_v_flip_lit @eref exsprite @shortdesc Rotates and flips a sprite. Like rotate_sprite_lit, 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_lit(BITMAP *bmp, BITMAP *sprite, int x, int y, @@ fixed angle, fixed scale); @xref rotate_sprite_lit, rotate_scaled_sprite_v_flip_lit @xref pivot_scaled_sprite_lit, pivot_scaled_sprite_v_flip_lit @eref exrotscl @shortdesc Rotates and stretches a sprite. Like rotate_sprite_lit(), but stretches or shrinks the image at the same time as rotating it. @\void @rotate_scaled_sprite_v_flip_lit(BITMAP *bmp, BITMAP *sprite, @@ int x, int y, @@ fixed angle, fixed scale); @xref rotate_sprite_lit, rotate_scaled_sprite_lit @xref rotate_sprite_v_flip_lit @shortdesc Rotates, stretches and flips a sprite. Draws the sprite, similar to rotate_scaled_sprite_lit() except that it flips the sprite vertically first. @\void @pivot_sprite_lit(BITMAP *bmp, BITMAP *sprite, int x, int y, @@ int cx, int cy, fixed angle); @xref rotate_sprite_lit, pivot_scaled_sprite_lit, pivot_sprite_v_flip_lit @eref exsprite @shortdesc Rotates a sprite around a specified point. Like rotate_sprite_lit(), 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_lit(BITMAP *bmp, BITMAP *sprite, int x, int y, @@ int cx, int cy, fixed angle); @xref rotate_sprite_lit, rotate_sprite_v_flip_lit, pivot_sprite_lit @eref exsprite @shortdesc Rotates and flips a sprite around a specified point. Like rotate_sprite_v_flip_lit(), 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_lit(BITMAP *bmp, BITMAP *sprite, int x, int y, @@ int cx, int cy, fixed angle, fixed scale); @xref rotate_sprite_lit, rotate_scaled_sprite_lit @xref pivot_sprite_lit, pivot_scaled_sprite_v_flip_lit @shortdesc Rotates and stretches a sprite around a specified point. Like rotate_scaled_sprite_lit(), 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_lit(BITMAP *bmp, BITMAP *sprite, @@ int x, int y, @@ int cx, int cy, fixed angle, fixed scale); @xref rotate_sprite_lit, rotate_scaled_sprite_v_flip_lit @xref rotate_sprite_v_flip_lit, pivot_sprite_lit, pivot_scaled_sprite_lit @shortdesc Rotates, stretches and flips a sprite around a specified point. Like rotate_scaled_sprite_v_flip_lit(), 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, 64); @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(myfont); @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. @@void @make_trans_font(FONT *f); @xref is_trans_font, set_alpha_blender, load_font, draw_trans_sprite @shortdesc Makes a font use transparency. This function converts a font to use transparency for drawing. That is, each glyph in the font will be drawn with draw_trans_sprite, so you can use the same blenders as with draw_trans_sprite to draw the font. One common use of this is to load a bitmap font with an alpha channel, and therefore get anti-aliased text output by using Allegro's alpha blender. Here's an example how to do that: FONT *f = load_font("alphafont.tga", NULL, NULL); make_trans_font(f); set_alpha_blender(); textprintf_centre_ex(screen, f, 320, 240, -1, -1, "Anti-aliased Font!"); @@int @is_trans_font(FONT *f) @xref make_trans_font, is_color_font, is_mono_font @shortdesc Returns TRUE if a font uses transparency. This function checks if the given font is a color font using draw_trans_sprite to render glyphs. @retval Returns TRUE if the font uses transparency, FALSE if it does not. @@int @is_color_font(FONT *f) @xref is_trans_font, 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_trans_font, 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. @@int @font_has_alpha(FONT *f) @xref is_trans_font @shortdesc Search all pixels of a font for alpha values. This function goes through all pixels of all glyphs in the font and looks for alpha values. @retval Returns TRUE if any alpha pixels are found, else FALSE. @@int *@is_compatible_font(FONT *f1, FONT *f2) @xref merge_fonts, is_trans_font, 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_trans_font, 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 capitals from */ /* the fancy font but other characters from myfont */ lower_range = extract_font_range(myfont, -1, 'A'-1); upper_range = extract_font_range(myfont, 'Z'+1, -1); capitals = extract_font_range(myfancy_font, 'A', 'Z'); tempfont = merge_fonts(lower_range, capitals); combined_font = merge_fonts(tempfont, upper_range); /* Clean up temporary fonts */ destroy_font(lower_range); destroy_font(upper_range); destroy_font(capitals); destroy_font(tempfont); @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 color depth 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 color depth when you load the font. If you try to use a font on a bitmap with a different color depth Allegro will do color conversions on the fly, which will be rather slow. For optimal performance you should set the color depth to the color depth you want to use before loading any fonts. @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 @eref exmouse @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 algorithm. Same as before: just OR the POLYTYPE with POLYTYPE_ZBUF. Also, you have to clear the z-buffer at the start of the frame. Example: 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 successive 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() function, the FLAT style is subject to DRAW_MODEs. All these modes are valid. Along with the polygon, this mode will be stored for the rendering moment, and also all the other related variables (color_map pointer, pattern pointer, anchor, blender values). The settings of the CPU_MMX and CPU_3DNOW flags of the cpu_capabilities global variable on entry in this routine affect the choice of low-level asm routine that will be used by render_scene() for this polygon. @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 paletted 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, exrotscl, exshade, extrans, extrans2, 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, exrotscl, 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 color spaces. Convert color values between the HSV and RGB color spaces. The RGB values range from 0 to 255, hue is from 0 to 360, and saturation and value are from 0 to 1. Example: 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 allocating a block of memory and reading an FLI file into it, or by importing an FLI into a grabber datafile. If `loop' is not zero, the player will cycle when it reaches the end of the file, otherwise it will play through the animation once and then return. Read the beginning of chapter "FLIC routines" for a description of the callback parameter. Playing animations from memory is obviously faster than cuing them directly from disk, and is particularly useful with short, looped FLI's. Animations can easily get very large, though, so in most cases you will probably be better just using play_fli(). You can think of this function as a wrapper on top of open_memory_fli(), next_fli_frame() and close_fli(). Example: 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 scenery) you will want to specify more carefully how hardware voices are reserved and which samples have priority over others. The hardware voice reservation phase has to be done before the call to install_sound(), since it directly affects how Allegro talks to the sound drivers. @@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. @@void @get_volume(int *digi_volume, int *midi_volume); @xref set_volume, get_hardware_volume @shortdesc Retrieves the global sound output volume. Retrieves the global sound output volume, both for digital samples and MIDI playback, as integers from 0 to 255. Parameters digi_volume and midi_volume must be valid pointers to int, or NULL if not interested in specific value. @@void @get_hardware_volume(int *digi_volume, int *midi_volume); @xref set_hardware_volume, get_volume @shortdesc Retrieves the hardware sound output volume. Retrieves the hardware sound output volume, both for digital samples and MIDI playback, as integers from 0 to 255, or -1 if the information is not available. Parameters digi_volume and midi_volume must be valid pointers to int, or NULL if not interested in specific value. @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 bit depth (8 or 16). Returns the mixer bit depth (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_voc("alarm.voc"); 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, destroy_sample @shortdesc Stops a sample from playing. Stop a sample from playing, which is required if you have set a sample going in looped mode. If there are several copies of the sample playing, it will stop them all. You must still destroy the sample using destroy_sample(). @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 sound card voice for a sample. Allocates a sound card voice and prepares it for playing the specified sample, setting up sensible default parameters (maximum volume, centre pan, no change of pitch, no looping). When you are finished with the voice you must free it by calling deallocate_voice() or release_voice(). Allegro can manage up to 256 simultaneous voices, but that limit may be lower due to hardware reasons. @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 sound card voice. Frees a sound card 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 sound card voice. Releases a sound card voice, indicating that you are no longer interested in manipulating it. The sound will continue to play, and any resources that it is using will automatically be freed when it finishes. This is essentially the same as deallocate_voice(), but it waits for the sound to stop playing before taking effect. @@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 sound card 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 sound card of the end user to play the notes, and sound cards have been historically known to have poor MIDI performance (at least those oriented to the consumer market). Few consumer cards feature decent MIDI playback. Still, as a game creator you can never be sure if the music of your game will be played as you meant it, because it totally depends on the hardware of the user. For this reason Allegro also provides a DIGMID driver. This is a software implementation of the so called Wavetable synthesis. Sound cards featuring this store digital samples of real instruments at different pitches, interpolating those that are not recorded, thus achieving a high sound quality. Implementing this in software makes you sure that the quality you hear on your computer is that which will be heard by end users using the same driver. The disadvantage of the DIGMID driver is that it uses more CPU than simple MIDI playback, and it steals some hardware voices from the sound card, which might be more critical for the end user experience than the background music. At the Allegro homepage (http://alleg.sourceforge.net/) you can find more information about DIGMID and where to download digital samples for your MIDI files. @@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 real-time, 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 sound card, be it digital samples or MIDI notes. Ideally this would allow you to create games where basic speech recognition could be implemented, or voice messages in multiplayer games over a network. However, many old sound cards are not full duplex. This means, that the sound device can only be playing or recording, but not both at the same time. Any Windows 2000 or better machine comes with a full duplex sound card and updated drivers. All MacOS X machines allow full duplex recording. Under Unix your mileage may vary: you can have the right hardware for the task, but the drivers might not support this feature. Under DOS you should forget about full duplex altogether. To find out if your system allows this feature, use the akaitest program, distributed along with Allegro, in the `tests' directory. @@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 sound card). -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_NONE - Exclude files that have any attribute set FA_RDONLY - Directory entries that are unwritable for current user FA_HIDDEN - Hidden flag FA_DIREC - Directories FA_SYSTEM - Files with system flag set (DOS/Windows only) FA_LABEL - Files with volume label flag set (DOS/Windows only) FA_ARCH - Files with archive flag set (DOS/Windows only) FA_ALL - Match all attributes Do not use any other flags from DOS/Windows or your code will not compile on another platform. FA_RDONLY is for directory entries with read-only flag on DOS-like systems or unwritable by current user on Unix-like systems. Hidden files are directory entries that have the hidden flag set (DOS/Windows) or have names starting with '.' (UNIX, excluding '.' and '..'). Flags can be combined using '|' (binary OR operator). When passed to the functions as the 'attrib' parameter, these flags represent an upper set in which the actual flag set of a matching file must be included. That is, in order for a file to be matching, its attributes may contain any of the specified flags but must not contain any of the unspecified flags. In other words, you explicitly exclude the flags that you do not specify. Thus if you pass 'FA_DIREC | FA_RDONLY', normal files and directories will be included as well as read-only files and directories, but not hidden files and directories. Similarly, if you pass 'FA_ARCH' then both archived and non-archived files will be included. If FA_NONE is passed all attributes are excluded and only files with no attributes are returned. Conversely, if you pass FA_ALL, no attributes are excluded so all files are returned (which is what you would usually want). Functions which accept wildcards as file names support the meta characters `*' (which means, zero or any quantity of characters) and `?' (which means any character, but only one). @@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. @@void @set_filename_encoding(int encoding) @xref get_filename_encoding @shortdesc Sets the encoding to use for filenames. Sets the encoding to use for filenames. By default, UTF-8 is assumed. @@int @get_filename_encoding(void) @xref set_filename_encoding @shortdesc Returns the encoding currently assumed for filenames. Returns the encoding currently assumed for filenames. @@int @file_exists(const char *filename, int attrib, int *aret); @xref exists, file_size_ex, 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_ex, 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. @@uint64_t @file_size_ex(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_ex @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, al_ffblk_get_size @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 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, FA_ALL) != 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. @@uint64_t @al_ffblk_get_size(struct al_ffblk *info); @xref al_findfirst, al_findnext, al_ffblk @shortdesc Get size of file returned by al_findfirst/al_findnext. This returns the size of the file returned by al_findfirst or al_findnext. @\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_ungetc(int c, PACKFILE *f); @xref pack_getc, pack_fgets @shortdesc Moves one single character back to the input buffer. Puts a character back to the file's input buffer. Like with ungetc from libc, only a single push back is guaranteed. Note: pack_fgets internally uses pack_ungetc, so never use pack_ungetc directly after using pack_fgets on a PACKFILE. @retval Returns c on success, or EOF on error. @@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, pack_ungetc @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. Note: This function internally may make calls to pack_ungetc, so you cannot use pack_ungetc directly afterwards. 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. @@DATAFILE_INDEX *@create_datafile_index(const char *filename); @xref destroy_datafile_index, load_datafile_object_indexed @xref Using datafiles @shortdesc Creates an index for a datafile. Creates an index for a datafile, to speed up loading single objects out of it. This is mostly useful for big datafiles, which you don't want to load as a whole. The index will store the offset of all objects inside the datafile, and then you can load it quickly with "load_datafile_object_indexed" later. Use destroy_datafile_index to free the memory used by it again. Note: If the datafile uses global compression, there is no performance gain from using an index, because seeking to the offset still requires to uncompress the whole datafile up to that offset. Example: DATAFILE_INDEX *index = create_datafile_index("huge.dat"); DATAFILE *object = load_datafile_object_indexed(index, 1234); ... unload_datafile_object(object); destroy_datafile_index(index); @retval A pointer value which you can pass to load_datafile_object_indexed. @@DATAFILE *@load_datafile_object_indexed(const DATAFILE_INDEX *index, int item) @xref create_datafile_index, load_datafile_object, unload_datafile_object @shortdesc Loads a single object from a datafile index. This loads a single object, using the index created previously with create_datafile_index. See create_datafile_index for an example. @retval Returns a pointer to a single DATAFILE element whose "dat" member points to the object, or NULL if the object could not be loaded. @@void @destroy_datafile_index(DATAFILE_INDEX *index) @xref create_datafile_index @shortdesc Destroys a datafile index. This function frees the memory used by a datafile index created with create_datafile_index earlier. @@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, exrotscl, 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 cycles for a floating point sine result rather than wait for the CPU to fetch the precalculated table from main memory. Always profile your code. Angles are represented in a binary format with 256 equal to a full circle, 64 being a right angle and so on. This has the advantage that a simple bitwise 'and' can be used to keep the angle within the range zero to a full circle, eliminating all those tiresome 'if (angle >= 360)' checks. @@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 time slices. An invisible helper object that yields time slices for the scheduler (if the system supports it) when the GUI has nothing to do but waiting for user actions. You should put one instance of this object in each dialog array because it may be needed on systems with an unusual scheduling algorithm (for instance QNX) in order to make the GUI fully responsive. @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); Note that you are responsible for showing and hiding the mouse cursor, which do_dialog would otherwise do for you, or saving and restoring the screen contents, as popup_dialog would do for you. @@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. The initial values at the addresses provided by card, w, and h are used as the default selections in the dialog if they are found in the driver and mode lists. If they are not found then the initial selections will be the first in each list. If you wish to ensure that the initial selection is always the first entry, then initialize the data at the addresses passed to the function to the value of 0 or -1. If the dialog is OK'd, it stores the selections at the addresses passed to the function. @retval See the gfx_mode_select_filter function for the return values. @@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 also allows the user to select the color depth. As with gfx_mode_select, the values stored at the addresses passed to the function will be used as suggestions for the initial selections in the dialog, defaulting to the first entry in each list if the values are not found. Initialize the data stored at the addresses passed to the function to the value of 0 or -1 if you want to ensure that the initial selection for each list will be the first entry. If the dialog is OK'd, it stores the selections at the addresses passed to the function. @retval See the gfx_mode_select_filter function for the return 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 @xref 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. As with gfx_mode_select, the values stored at the addresses passed to the function will be used as suggestions for the initial selections in the dialog, defaulting to the first entry in each list if the values are not found. Initialize the data stored at the addresses passed to the function to the value of 0 or -1 if you want to ensure that the initial selection for each list will be the first entry. If the dialog is OK'd, it stores the selections at the addresses passed to the function. Example usage : ret = gfx_mode_select_filter(&card, &w, &h, &color_depth, user_filter); if (ret) {/* User okayed dialog or user_filter removed all modes */ if (card == GFX_NONE) { // No modes available *card = 0;/* Make sure not to leave *card == GFX_NONE */ return -1; } /* Handle changing to new mode here... */ } else {/* User cancelled dialog or there was an error (unlikely) */ if (card == GFX_NONE) { /* Error, probably out of memory */ *card = 0;/* Make sure not to leave *card == GFX_NONE */ return -2; } /* Carry on in current graphics mode if that is acceptable */ } @retval Returns zero if the user cancelled the dialog or an error occurred. In the case of an error then *card is assigned the value GFX_NONE. The functions return non-zero if the user made a selection OR if all the modes were filtered out. In the case that all of the modes were filtered out, then *card is assigned the value GFX_NONE. This means you should NOT initialize the *card to the value of GFX_NONE, as it could interfere with determining the proper return value. @@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 adapter. It supports up to four controllers on a single parallel port. There is no need to calibrate the analog stick, as this is done by the controller itself when powered up. This means that the stick has to be centred when the controller is initialised. One possible issue people may have with this driver is that it is physically impossible to move the analog stick fully diagonal, but I can't see this causing any major problems. This is because of the shape of the rim that the analog stick rests against. Like the Gravis Game Pad Pro, this driver briefly needs to disable hardware interrupts while polling. This causes a noticeable performance hit on my machine in both drivers, but there is no way around it. At a (very) rough guess I'd say it slows down Mame 5% - 10%.
  • 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 sound cards: 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 sound cards: 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 sound cards: 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 sound cards: 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(). @@void @win_set_msg_pre_proc(int (*proc)(HWND, UINT, WPARAM, LPARAM, int *retval)); @shortdesc Sets a user callback to be called on window events. Set a user callback to be called on window events. This callback function takes the same parameters as a normal window callback procedure plus an additional pointer to an integer. This pointer should be filled with a return value that must be set if the callback has completely processed the window event. If the callback has completely processed the window event, it should return 0 and fill retval with a proper value (the default is zero), otherwise it should return a non-zero value, and event processing will continue in Allegro's default window callback procedure. @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() because 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() because 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 sound cards: 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 sound cards: 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 sound cards: 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 sound cards: 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 sound cards: 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 sound cards: 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 end-user, you need to add the END_OF_MAIN() macro right after your main() function. This is a necessary step: if you omit it, your program will not compile. The END_OF_MAIN() macro simply does some magic to make sure your program executes another function before your main(); this function is defined into the liballeg-main.a static library, which is automatically linked if you use the allegro-config script when linking. Otherwise be sure you link against it unless you want to get undefined symbol errors. To behave nicely with the MacOS X user interface, Allegro apps will provide a standard application menu with the "Quit" menu item in it. The default behaviour when the user hits Command-Q or selects "Quit" is to do nothing. To override this behaviour you must call the set_close_button_callback() function; under MacOS X the supplied callback will be used either if the user clicks the window close button either on Command-Q or "Quit" selection. In this last case the application will not shutdown, but you are supposed to set some quit flag in your callback and check for it on a regular basis in your main program loop. If you would like to use InterfaceBuilder to design a more fully-featured menu, Allegro will automatically load it if you create a bundle for your application. The use of InterfaceBuilder is beyond the scope of this document. Briefly, you need to create a Nib, called MainMenu.nib, containing a main menu and a controller. Then, when you create the bundle, install MainMenu.nib into the Contents/Resources subdirectory. Note that the actions attached to the menu items will be called from a different thread than the one in which your Allegro code is running. Therefore you should not do any work there (especially, don't call Allegro functions.) Instead, set a variable, and test it in your main loop. @@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 sound cards: 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 sound cards: 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. Note that ALLEGRO_LINUX is a misnomer. It will only be defined if Linux console support is enabled. It is not a reliable way to check if the program is being built on a Linux system. ALLEGRO_AMD64
ALLEGRO_I386
ALLEGRO_BIG_ENDIAN
ALLEGRO_LITTLE_ENDIAN
Defined if you are building for a processor of the relevant type. ALLEGRO_MULTITHREADED
Defined if the library is internally multi-threaded on this system. ALLEGRO_USE_CONSTRUCTOR
Defined if the compiler supports constructor/destructor functions. ALLEGRO_VRAM_SINGLE_SURFACE
Defined if the screen is a single large surface that is then partitioned into multiple video sub-bitmaps (eg. DOS), rather than each video bitmap being a totally unique entity (eg. Windows). ALLEGRO_CONSOLE_OK
Defined if when you are not in a graphics mode, there is a text mode console that you can printf() to, and from which the user could potentially redirect stdout to capture it even while you are in a graphics mode. If this define is absent, you are running in an environment like Windows that has no stdout at all. ALLEGRO_MAGIC_MAIN
Defined if Allegro uses a magic main, i.e takes over the main() entry point and turns it into a secondary entry point suited to its needs. ALLEGRO_LFN
Non-zero if long filenames are supported, or zero if you are limited to 8.3 format (in the DJGPP version, this is a variable depending on the runtime environment). LONG_LONG
Defined to whatever represents a 64-bit "long long" integer for the current compiler, or not defined if that isn't supported. OTHER_PATH_SEPARATOR
Defined to a path separator character other than a forward slash for platforms that use one (eg. a backslash under DOS and Windows), or defined to a forward slash if there is no other separator character. DEVICE_SEPARATOR
Defined to the filename device separator character (a colon for DOS and Windows), or to zero if there are no explicit devices in paths (Unix). Allegro can be customized at compile time to a certain extent with the following macros: ALLEGRO_NO_MAGIC_MAIN
If you define this prior to including Allegro headers, Allegro won't touch the main() entry point. This effectively removes the requirement on a program to be linked against the Allegro library when it includes the allegro.h header file. Note that the configuration and file routines are not guaranteed to work on Unix systems when this symbol is defined. Moreover, on Darwin/MacOS X systems, this symbol simply prevents the program from being linked against the Allegro library! This highly non portable feature is primarily intended to be used under Windows. ALLEGRO_USE_CONSOLE
If you define this prior to including Allegro headers, Allegro will be set up for building a console application rather than the default GUI program on some platforms (especially Windows). ALLEGRO_NO_STD_HEADER
If you define this prior to including Allegro headers, Allegro will not automatically include some standard headers (eg <stddef.h>) its own headers depend upon. ALLEGRO_NO_KEY_DEFINES
If you define this prior to including Allegro headers, Allegro will omit the definition of the KEY_* constants, which may clash with other headers. ALLEGRO_NO_FIX_ALIASES
The fixed point functions used to be named with an "f" prefix instead of "fix", eg. fixsqrt() used to be fsqrt(), but were renamed due to conflicts with some libc implementations. So backwards compatibility aliases are provided as static inline functions which map the old names to the new names, eg. fsqrt() calls fixsqrt(). If you define this symbol prior to including Allegro headers, the aliases will be turned off. ALLEGRO_NO_FIX_CLASS
If you define this symbol prior to including Allegro headers in a C++ source file, the 'fix' class will not be made available. This mitigates problems with the 'fix' class's overloading getting in the way. ALLEGRO_NO_VHLINE_ALIAS
The `curses' API also defines functions called vline() and hline(). To avoid a linker conflict when both libraries are used, we have internally renamed our functions and added inline function aliases which remap vline() and hline(). This should not be noticeable to most users. If you define ALLEGRO_NO_VHLINE_ALIAS prior to including Allegro headers, Allegro will not define the vline() and hline() aliases, e.g. so you can include curses.h and allegro.h in the same module. ALLEGRO_NO_CLEAR_BITMAP_ALIAS
If you define this prior to including Allegro headers, Allegro will not define the clear() backwards compatibility alias to clear_bitmap(). ALLEGRO_NO_COMPATIBILITY
If you define this prior to including Allegro headers, Allegro will not include the backward compatibility layer. It is undefined by default so old programs can still be compiled with the minimum amount of issues, but you should define this symbol if you intend to maintain your code up to date with the latest versions of Allegro. It automatically turns off all backwards compatibility aliases. Allegro also defines a number of standard macros that can be used to insulate you from some of the differences between systems: INLINE
Use this in place of the regular "inline" function modifier keyword, and your code will work correctly on any of the supported compilers. RET_VOLATILE
Use this to declare a function with a volatile return value. ZERO_SIZE_ARRAY(type, name)
Use this to declare zero-sized arrays in terminal position inside structures, like in the BITMAP structure. These arrays are effectively equivalent to the flexible array members of ISO C99. AL_CONST
Use this in place of the regular "const" object modifier keyword, and your code will work correctly on any of the supported compilers. AL_RAND()
On platforms that require it, this macro does a simple shift transformation of the libc rand() function, in order to improve the perceived randomness of the output series in the lower 16 bits. Where not required, it directly translates into a rand() call. @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. You can call this function even when Allegro has not been initialised. 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. You can call this function even when Allegro has not been initialised. 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. @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, key, makecol, readkey, release_screen @xref screen, 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, rest, 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_keybuf, clear_to_color, create_bitmap, desktop_palette @xref destroy_bitmap, font, install_keyboard, install_timer, keypressed @xref makecol, release_screen, retrace_count, screen, set_gfx_mode @xref 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_keybuf @xref clear_to_color, create_bitmap, create_video_bitmap, desktop_palette @xref destroy_bitmap, font, install_keyboard, install_timer, keypressed @xref makecol, retrace_count, screen, set_gfx_mode, set_palette @xref 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, key, load_font, makecol, merge_fonts, readkey @xref release_screen, screen, set_gfx_mode, set_palette @xref textout_centre_ex @shortdesc Loading and manipulating fonts. 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_w, 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 textprintf_right_ex, 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 key press modifies the cursor to be several concentric colored circles. They are not joined together, so you can still see bits of what's behind when you move the cursor over the printed text message. @@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, install_timer, key, key_shifts @xref keyboard_lowlevel_callback, keypressed, makecol, readkey, rectfill @xref release_screen, rest, scancode_to_name, screen, set_gfx_mode @xref set_palette, textprintf_centre_ex, textprintf_ex, ureadkey @xref 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 scan codes. The fourth test detects modifier keys like alt or shift. The fifth test requires some focus to be passed. The final step shows how to use the global key array to read simultaneous key presses. The last method to detect key presses are keyboard callbacks. This is demonstrated by 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 command line to specify as first parameter a WAV or VOC sound file to play. If the file is loaded successfully, the sound will be played in an infinite loop. While it is being played, you can use the left and right arrow keys to modify the panning of the sound. You can also use the up and down arrow keys to modify the pitch. @@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, destroy_bitmap, font, install_int_ex @xref install_keyboard, install_timer, keypressed, load_datafile @xref replace_filename, rest, screen, set_gfx_mode, set_uformat @xref set_window_title, text_height, text_length, textout_ex @xref uconvert_ascii, unload_datafile, ustrcat, ustrcpy, ustrsize @xref 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 command line to specify as first parameter a graphic file in one of Allegro's supported formats. If the file is loaded successfully, it will be displayed until you press a key. @@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, destroy_bitmap, font @xref get_config_argv, get_config_int, get_config_string @xref install_keyboard, line, load_bitmap, makecol, pop_config_state @xref push_config_state, readkey, screen, set_color_depth @xref set_config_file, set_gfx_mode, set_palette, stretch_blit @xref textout_centre_ex, textprintf_centre_ex, ustrdup, ustricmp @shortdesc Using the configuration routines. This is a very simple program showing how to use the Allegro configuration (ini file) routines. A first look at the example shows nothing more than a static graphic and the wait for a key press. However, the way this graphic is displayed is configured through a custom exconfig.ini file which is loaded manually. From this file the example obtains parameters like fullscreen/windowed mode, a specific graphic resolution to set up, which graphic to show, how to blit it on the screen, etc. @@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 @exrotscl @xref BITMAP, END_OF_MAIN, SCREEN_H, SCREEN_W, acquire_screen @xref allegro_init, allegro_message, clear_to_color, create_bitmap @xref destroy_bitmap, draw_trans_sprite, fixed, font, ftofix @xref install_keyboard, key, keypressed, load_bitmap, makeacol, makecol @xref readkey, release_screen, rest, rotate_scaled_sprite @xref rotate_scaled_sprite_lit, rotate_scaled_sprite_trans, screen @xref set_alpha_blender, set_color_conversion, set_color_depth @xref set_gfx_mode, set_trans_blender, textout_centre_ex @shortdesc Demonstrates rotate_scaled_sprite functions. This example demonstrates rotate_scaled_sprite functions. @@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 executable by the exedat tool. It is basically the exdata example with minor modifications. You may ask: how do you compile, append and exec your program? Answer: like this... 1) Compile your program like normal. Use the magic filenames with '#' to load your data where needed. 2) Once you compressed your program, run "exedat foo.exe data.dat" 3) Finally run your program. Note that appending data to the end of binaries may not be portable across all platforms supported by Allegro. @@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, rest, 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 illuminated by a spotlight you can move with your mouse. After a key press the example shows the full bitmap and the spotlight changes to be a reduced version of the background with 50% of translucency. The translucency effect is easy to do in all color depths. However, the lighting effect has to be performed in a different way depending on whether the screen is in 8bit mode or another color depth. This is because additive drawing mode uses a different set of routines for truecolor modes. @@Example @extrans2 @xref BITMAP, END_OF_MAIN, allegro_error, allegro_init, allegro_message @xref blit, clear_bitmap, create_bitmap, destroy_bitmap, draw_sprite_ex @xref font, install_keyboard, install_timer, key, load_bitmap, makecol @xref replace_filename, rest, screen, set_color_depth, set_gfx_mode @xref set_trans_blender, stretch_blit, textprintf_ex @shortdesc Drawing flipped, translucent and tinted sprites. This program demonstrates how to draw trans and lit sprites and flip them at the same time, using draw_sprite_ex() function. It displays several images moving around using different drawing modes while you can press space key to change the flipping orientation. @@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 color space 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 Gouraud 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 command line to specify as parameters a number of graphic files. Use at least two files to see the graphical effect. The example will crossfade from one image to another with each key press until you press the ESC key. @@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 star field (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 algorithm in Allegro (create_scene, clear_scene, ... functions). It also provides an example of how to use the 3D clipping function. The example consists of a flyby through a lot of rotating 3d cubes. @@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_palette_range @xref set_projection_viewport, set_zbuffer, 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 polygons 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 noticeable 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 @shortdesc Hardware accelerated mouse cursors. 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 command line to specify as first parameter a number which represents the type of video update you want: 1 for double buffering with memory bitmaps, 2 for page flipping, 3 for triple buffering and 4 for double buffering with system bitmaps. After this, a dialog allows you to select a screen resolution and finally you will see a kaleidoscopic animation, along with a frames per second counter on the top left of the screen. @@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 sound card. In this case, the sample data is generated during runtime, and the resulting sound reminds of a car engine when you are accelerating. @@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_ex, 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 file stream functions. The third test demonstrates seeking with a custom vtable. The fourth test reads two bitmaps, and dumps them back into a single file, using a custom vtable again. @# end genexamp.py chunk @externalfile targets Makefile targetes @externalfile addons Addon libraries @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 command line @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 SVN repository, from which releases are built every now and then. But, who decides when a build is stable enough? Who decides when somebody is granted write access to the SVN? Who chooses the lesser of two evils patching some obscure bug? And more importantly, who decides what's Allegro's mascot? For all these reasons, the community decided to replace Shawn's position with the Allegro Dictator. In republican Rome, political power was with the Senate and the Consuls. However, if it was necessary that decisions were made very quickly then the senate could appoint a Dictator. The Dictator was appointed for a specified duration or charged with a specific task, after which he was expected to surrender his authority back to the Senate. Nowadays, the Allegro Dictator is a benevolent figure and rarely has to use his overwhelming fist of iron to put order into chaos. The truth is that the Allegro Dictator is usually the person in charge of doing releases and all that unsexy work inside the community, like pestering users to test some obscure bugfix or rejecting incomplete patches. Past Allegro dictators have been: Shawn Hargreaves, George Foot, Peter Wang and Eric Botcazou. At the moment of writing this, Evert Glebbeek is the active Allegro Dictator. Should you want to change Allegro in some illogical way, he's the guy you have to send your bribes too :-) @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 allegro4.4-4.4.2/docs/src/api._tx000066400000000000000000000256161173507505700164240ustar00rootroot00000000000000@html_text_substitution=readme.txt|readme.txt @external-css=allegro.css @document_title=API compatibility information @
@!indent
     ______   ___    ___
    /\  _  \ /\_ \  /\_ \
    \ \ \L\ \\//\ \ \//\ \      __     __   _ __   ___ 
     \ \  __ \ \ \ \  \ \ \   /'__`\ /'_ `\/\`'__\/ __`\
      \ \ \/\ \ \_\ \_ \_\ \_/\  __//\ \L\ \ \ \//\ \L\ \
       \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
        \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
                                       /\____/
                                       \_/__/


                API compatibility information.

         See readme.txt for a more general overview.
@indent
@
@heading Introduction Once Allegro 4.0 is released, we plan to maintain backward compatibility at the Application Programming Interface level for the subsequent stable releases of the 4.x series, that is for the releases with an even minor version number. For example, that means you will be able to compile your program written for version 4.0.0 with version 4.0.23 or version 4.2.1 of the library. However, in order to fix some minor inconsistencies of the original 4.0 API, we may make exceptions to the rule and break strict backward compatibility in a few cases. But this is guaranteed to never happen in a stable series for which major and minor version numbers are fixed; in other words, two stable versions that differ from each other only by the revision (3rd) number will be strictly backward compatible. @heading Changes between 4.2.x and 4.4.x series
  • The output parameters to gfx_mode_select should be initialized in 4.4.x as they are used for the initial selection now.
@heading Changes between 4.0.x and 4.2.x series
  • The 'aspect' parameter of get_camera_matrix() and get_camera_matrix_f() strictly conforms to the documentation; in particular, setting it to 1 instructs the functions to do no scaling. This was not the case before, because the functions multiplied this aspect ratio by 4/3.
  • Menus created from a DIALOG array (by using d_menu_proc for the proc pointer) now correctly use the w and h fields as a minimum for their inclusive dimensions (in the same way as all other GUI elements). Before, they would draw the border outside of this dimension (1 pixel overdraw with other GUI elements), and also add an additional 'shadow' to the right and the bottom (2 pixels overdraw with other GUI elements).
  • The 'retrace_count' variable and the 'retrace_proc' callback function take into account the refresh rate (if it is known) when the retrace simulator is not installed. This was not the case before, except under Windows.
  • The default value for the mouse configuration variable 'emulate_three' has been changed to 'no' in all cases (even if you have a 2-button mouse).
  • The COLORCONV_KEEP_TRANS flag strictly conforms to the documentation now. This was not the case before, because it was ignored when loading bitmaps from datafiles. fixup_datafile() was modified to preserve transparency when this flag is set, which was not guaranteed before in rare cases.
  • create_sub_bitmap() is now less tolerant about receiving bad arguments. For example, it used to compensate for negative values for the origin and return NULL if the parent bitmap was NULL. These cases are now ASSERTed in the debug version, but unchecked in the release version.
  • install_allegro() and allegro_init() now return an error code if unable to initialise a system driver. Previously they would have aborted the program in such cases. Consequently you should check their return values.
  • The preprocessor symbol USE_CONSOLE is deprecated. Define instead the symbol ALLEGRO_USE_CONSOLE prior to including Allegro headers in order to set up Allegro for building a console application.
  • The constructors of the fix class from integer and floating point values are now explicit.
  • All BeOS gfx driver IDs and constants have been replaced by more meaningful ones. You may have to modify your allegro.cfg to reflect the change, or update and recompile your programs if you used BeOS specific gfx drivers.
  • The behaviour of the GFX_SAFE driver has changed: it doesn't try to first set up GFX_AUTODETECTed drivers anymore and is now guaranteed to be a windowed driver when the platform has got a windowing system.
  • A datafile object returned by load_datafile_object() used not to contain the properties attached to the object. This has been fixed.
  • object_message() now takes care of scaring and unscaring the mouse if the message to be sent is MSG_DRAW.
  • file_select_ex() now treats '(+)d' as it does for any other attributes in the extension string which is passed to it: only directories are included and, among them, only those with the correct set of attributes.
  • d_ctext_proc() now behaves like d_text_proc() and d_rtext_proc(), that is it takes into account the bounding box to calculate the position which the string is centered around. It previously used only the x field. And, as a consequence, gui_ctext_proc is now expected to behave the same.
  • dialog_message() now passes user messages to hidden objects.
  • set_volume() doesn't use the hardware mixer anymore to alter the global volume. Use set_hardware_volume() instead to get the old behaviour.
  • The default sound volume of Allegro was raised, since there no longer is the risk of wrapping with the new mixer. To restore the volume level to that of previous versions, look at the set_volume_per_voice function. Programs already using set_volume_per_voice are not affected.
  • The semantics of rest are clarified so rest(0) does yielding when possible.
  • The get_align_matrix[_f] functions would return mirrored matrices in some cases, this was fixed.
  • In many places 'unsigned long' variables were used to hold memory addresses. These have been changed to use the 'uintptr_t' type instead.
  • 15-bit and 16-bit bitmaps used to be arrays of unsigned shorts, and 32-bit bitmaps used to be arrays of unsigned longs. They have been changed to be arrays of 16-bit and 32-bit integers respectively. This makes a difference on platforms where an unsigned long is not 32-bits wide (e.g. some 64-bit platforms).
@heading Deprecated materials The following items have been deprecated and the main documentation was purged of any references to them. If you are still using any of those, now might be a good time to get rid of them (within parentheses is the symbol most likely to be a replacement for the obsolete one, if any). However they are still supported for the sake of backwards compatibility, unless you define the symbol ALLEGRO_NO_COMPATIBILITY prior to including Allegro headers.
  • clear (clear_bitmap).
  • cpu_fpu (cpu_capabilities, in combination with CPU_FPU).
  • cpu_mmx (cpu_capabilities, in combination with CPU_MMX).
  • cpu_3dnow (cpu_capabilities, in combination with CPU_3DNOW).
  • cpu_cpuid (cpu_capabilities, in combination with CPU_ID).
  • draw_character (draw_character_ex, passing the mode you would have passed to text_mode() as the 'bg' parameter).
  • fadd (fixadd).
  • fsub (fixsub).
  • fmul (fixmul).
  • fdiv (fixdiv).
  • fceil (fixceil).
  • ffloor (fixfloor).
  • fcos (fixcos).
  • fsin (fixsin).
  • ftan (fixtan).
  • facos (fixacos).
  • fasin (fixasin).
  • fatan (fixatan).
  • fatan2 (fixatan2).
  • fsqrt (fixsqrt).
  • fhypot (fixhypot).
  • file_size (file_size_ex)
  • file_select (file_select_ex, passing the two constants OLD_FILESEL_WIDTH and OLD_FILESEL_HEIGHT if you want the file selector to be displayed with the dimensions of the old file selector).
  • fix_filename_path (canonicalize_filename).
  • for_each_file (for_each_file_ex).
  • gui_textout (gui_textout_ex, passing the mode you would have passed to text_mode() as the 'bg' parameter).
  • initialise_joystick (install_joystick).
  • joy_x (joy).
  • joy_y (joy).
  • joy_left (joy).
  • joy_right (joy).
  • joy_up (joy).
  • joy_down (joy).
  • joy_b1 (joy).
  • joy_b2 (joy).
  • joy_b3 (joy).
  • joy_b4 (joy).
  • joy_b5 (joy).
  • joy_b6 (joy).
  • joy_b7 (joy).
  • joy_b8 (joy).
  • joy2_x (joy).
  • joy2_y (joy).
  • joy2_left (joy).
  • joy2_right (joy).
  • joy2_up (joy).
  • joy2_down (joy).
  • joy2_b1 (joy).
  • joy2_b2 (joy).
  • joy_throttle (joy).
  • joy_hat (joy).
  • JOY_HAT_CENTER.
  • JOY_HAT_CENTRE.
  • JOY_HAT_LEFT.
  • JOY_HAT_RIGHT.
  • JOY_HAT_DOWN.
  • JOY_HAT_UP.
  • KB_EXTENDED.
  • KB_NORMAL.
  • SEND_MESSAGE (object_message).
  • set_window_close_button.
  • set_window_close_hook (set_close_button_callback).
  • text_mode.
  • textout (textout_ex, passing the mode you would have passed to text_mode() as the 'bg' parameter).
  • textout_centre (textout_centre_ex, passing the mode you would have passed to text_mode() as the 'bg' parameter).
  • textout_right (textout_right_ex, passing the mode you would have passed to text_mode() as the 'bg' parameter).
  • textout_justify (textout_justify_ex, passing the mode you would have passed to text_mode() as the 'bg' parameter).
  • textprintf (textprintf_ex, passing the mode you would have passed to text_mode() as the 'bg' parameter).
  • textprintf_centre (textprintf_centre_ex, passing the mode you would have passed to text_mode() as the 'bg' parameter).
  • textprintf_right (textprintf_right_ex, passing the mode you would have passed to text_mode() as the 'bg' parameter).
  • textprintf_justify (textprintf_justify_ex, passing the mode you would have passed to text_mode() as the 'bg' parameter).
  • PALLETE (PALETTE).
  • DAT_PALLETE (DAT_PALETTE).
  • black_pallete (black_palette).
  • desktop_pallete (desktop_palette)
  • get_pallete (get_palette).
  • set_pallete (set_palette).
  • get_pallete_range (get_palette_range)
  • set_pallete_range (set_palette_range).
  • fli_pallete (fli_palette).
  • pallete_color (palette_color).
  • select_pallete (select_palette).
  • set_clip (set_clip_rect).
  • unselect_pallete (unselect_palette).
  • generate_332_pallete (generate_332_palette).
  • generate_optimized_pallete (generate_optimized_palette).
  • yield_timeslice (rest, passing 0 as parameter)
  • retrace_proc (retrace_count or install_int).
  • timer_can_simulate_retrace.
  • timer_is_using_retrace.
  • timer_simulate_retrace (when enable_triple_buffer is called, the mode-X driver still enables retrace simulation automatically where possible).
  • split_modex_screen.
allegro4.4-4.4.2/docs/src/build/000077500000000000000000000000001173507505700162245ustar00rootroot00000000000000allegro4.4-4.4.2/docs/src/build/cmake._tx000066400000000000000000000131511173507505700200210ustar00rootroot00000000000000@external-css=../allegro.css @document_title=Building Allegro with CMake @heading Building Allegro 4.4 with CMake CMake is a cross-platform tool that can generate native makefiles and workspaces that can be used in the compiler environment of your choice. Allegro 4.4 uses CMake as its build system. The process is essentially the same for all compilers. You will need CMake 2.6 or later. The CMake web site is http://www.cmake.org/.
  1. Create a temporary directory to build in. This is optional but recommended. If something goes wrong you can delete the build directory and try again. $ mkdir Build $ cd Build
  2. Run CMake in the build directory. This will detect your compiler environment and generate makefiles or workspaces for you. You may pass some options to customise the build (see later), but the defaults should be fine. You may need to tell CMake which type of files it should generate, using the -G option. You can call CMake using the --help option to see a list of available generators. Examples (you only need one): $ cmake .. $ cmake -G "MinGW Makefiles" .. On Unix/Mac you can use `ccmake` which will present you with a console program to adjust the options. On Windows you can use `cmake-gui` instead (it should be listed in the Start menu or on the desktop). If you are missing any dependencies, CMake will tell you at this point. You can continue without building all of the addons, or install the dependencies and retry. You may need to delete the `CMakeCache.txt` file first.
  3. Use the generated makefiles or workspaces to build Allegro. If using makefiles, type `make` or `mingw32-make`. If using workspaces, open them in your IDE. If using Xcode, you can use `xcodebuild` from the command-line or the IDE.
  4. Optionally install the libraries and header files to your system. $ make install DESTDIR is supported, e.g. $ make install DESTDIR=/tmp/package-allegro
@heading Build options Here are some build options you may be interested in. You can set them on the command line like so, or using one of the front ends: $ cmake -DCMAKE_BUILD_TYPE=Debug ..
CMAKE_BUILD_TYPE (default: RelWithDebInfo)
Selects release, debug or profiling configurations. Valid values are: Release, Debug, RelWithDebInfo, MinSizeRel, Profile.

If you are installing multiple configurations in a row, we recommend installing the Release or RelWithDebInfo configuration last, so that the installed allegro-config script will default to that configuration.

SHARED (default: on)
Whether to build the main Allegro library as a shared library (DLL) or as a static library. Addon libraries are always built as static libraries, for simplicity.
CMAKE_INSTALL_PREFIX (e.g. /usr/local)
Where to install the library and header files.
WANT_<addon> (default: on)
Whether you want to build/install each particular addon.
WANT_EXAMPLES (default: off)
Whether you want the specified addon's example programs to be built.
WANT_FRAMEWORKS (default: off)
On Mac OS X, whether to build and install frameworks instead of Unix-style shared libraries.

If you want both kinds, you will need to run cmake twice and install twice.

WANT_EMBED (default: on)
If building frameworks, whether to build embedded or non-embedded frameworks. An application bundle that links against an embedded framework will first search for the framework within the application bundle, then fall back to system paths.
FRAMEWORK_INSTALL_PREFIX
Where to install frameworks.
CMAKE_OSX_ARCHITECTURES
You may set this to a semicolon-separated list of the architectures to compile for, to produce universal binaries, e.g. "i386;ppc".
@heading Dependencies Many of the addons make use of additional libraries. They are not required to build Allegro, but functionality may be disabled if they are not present. Windows users may find some precompiled binaries from http://gnuwin32.sourceforge.net/. You need to get the bin and lib packages. The bin packages contain DLLs, and the lib packages contain the headers and import libraries. Mac users may find some dependencies in Fink or MacPorts. http://www.finkproject.org/ and http://www.macports.org/ Linux users likely have all the dependencies already. If your distribution uses separate development packages, they will need to be installed. The packages are probably named *-dev or *-devel.
  • OpenGL is required for AllegroGL.
  • libpng and zlib, for PNG image support.
    These are used by loadpng.
    Home page: http://www.libpng.org/pub/png/
    Windows binaries: http://gnuwin32.sourceforge.net/packages/libpng.htm
  • Ogg Vorbis, a free lossy audio format. (libogg, libvorbis, libvorbisfile)
    This is used by logg.
    Home page: http://www.vorbis.com/
  • jpgalleg does not require any additional libraries.
@heading Platform-specific information Please see the other files in the docs/build directory for additional information specific to each platform. allegro4.4-4.4.2/docs/src/build/linux._tx000066400000000000000000000154351173507505700201070ustar00rootroot00000000000000@html_text_substitution=readme.txt|readme.txt @html_text_substitution=docs/build/unix.txt|docs/build/unix.txt @external-css=../allegro.css @document_title=Allegro Linux-specific information @
     ______   ___    ___
    /\  _  \ /\_ \  /\_ \
    \ \ \L\ \\//\ \ \//\ \      __     __   _ __   ___ 
     \ \  __ \ \ \ \  \ \ \   /'__`\ /'_ `\/\`'__\/ __`\
      \ \ \/\ \ \_\ \_ \_\ \_/\  __//\ \L\ \ \ \//\ \L\ \
       \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
	\/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
				       /\____/
				       \_/__/


		 Linux-specific information.

	 See readme.txt for a more general overview.

   Also see docs/build/unix.txt for general Unix information.
@
@heading General notes On Linux you have two different system drivers -- one for running using X, and one for running without X. For information on the X version, and instructions telling how to install Allegro and compile your programs on a Unix system, see docs/build/unix.txt. This file only describes the Linux console routines. Normally the X version is used in preference to the console version, if an X server is contactable (this means that your programs will use X if you launch them from inside X, and otherwise use the console). Unless you have specific needs, we recommend using the X version. The Linux console port is not enabled by default. It never worked that well and there is no real interest in it any more. We may remove it in a future release. @heading Installing Allegro See docs/build/unix.txt: this process is identical for the console and X versions. You must set the CMake option WANT_LINUX_CONSOLE to enable the console version, as it is not built by default. @heading Using Allegro Some parts of Linux console Allegro need root privileges. Others don't. Specifically, the VGA and mode-X graphics drivers do. The fbcon driver doesn't. Also, if you intend to run a program from something which isn't a VT (e.g. an xterm (but not using the X version), a remote login, a screen session) then you need to either own a (free) console numbered from 1 to 15 or to have root privileges. If you want a program to run with privileges even though the user running it is not root, make root own the binary and set the suid bit: # chown root.allegro exhello # chmod 4770 exhello That makes the executable be owned by root and group `allegro'. It's readable, writable and executable by root and people in that group. Also, when it runs, it has root privileges. For that reason, it's not executable by the general public. Put trusted users into group `allegro'. You might prefer to use `4750' instead of `4770' -- then people in the group cannot write to the binary. Allegro will drop the privileges almost immediately after initialisation, using `seteuid'. This means that you can still get the permissions back later on. Allegro needs to be able to regain the privileges if you intend to call `allegro_init' again in the future. If this isn't the case, you can completely give up the privileges using `setuid(getuid());' -- then they are lost for good. Security note: If you don't do this, any buffer overflows are a severe security problem. In any case, you should take great care when allowing random people to execute third-party programs suid root. If, as root, you run `make suid', it will do this to all of the programs generated -- the demo game, the examples, the tests, etc. @heading Notes on drivers This section contains Linux-specific notes on the drivers available.
System:
On initialisation, Allegro will try to get a certain amount of control over the console. This doesn't generally require root privileges, but if the program isn't being run from a plain VC (e.g. it's running from within X or screen), Allegro must try to allocate a spare VC and move the program to it. This requires a free console we can read from and write to; unless the user has allocated some, we need to be root here. Display switching is possible; all of Allegro's modes are supported. The default is SWITCH_PAUSE. SWITCH_BACKGROUND will only work if the application takes special precautions.
Graphics:
Linux Allegro supports standard VGA by direct writes to the video card. You need root privileges for this to work. It also supports fbcon, for which you do not need privileges, but you do need a recent kernel, correctly configured. The SVGAlib driver should be fairly stable and fast now, and can use most of the video modes that SVGAlib provides. It requires root privileges if your version of SVGAlib requires them.
Note: Allegro used to have a mode-X driver, but it does not work as of 4.4.0. Someone may restore it in the future, but it's likely.
Keyboard:
The keyboard driver uses the kernel mapping tables to map scancodes to character codes and key functions, so your keyboard mapping should be fine without special configuration in the setup program.
Joystick:
To compile Allegro with joystick support you must have a 2.2.* or newer kernel, i.e. with kernel-based joystick support. Look for /usr/src/linux/include/linux/joystick.h. You shouldn't have to actually configure the kernel with joystick support though, you just need that header file. Similarly, to run Allegro programs with joystick support you must have configured joystick support into the kernel. You also need to create the device file /dev/input/js0, if it's not already there. See /usr/src/linux/Documentation/joystick.txt for details.
Mouse:
Currently Linux Allegro supports PS/2 and Microsoft mice directly, and other mouse types via GPM. To use GPM you must turn on its `repeater' feature, where it copies all mouse activity to the FIFO /dev/gpmdata. Edit your init scripts and add the `-R' option. The GPM driver can also be used with native Mouse Systems mice by changing the `mouse_device' variable in the config file. When using the PS/2 Intellimouse protocol, it is necessary to explicitly put the mouse into wheel mode, which requires Allegro to have write permissions to the device. There is an input events-based driver which reads events from /dev/input/eventN.
allegro4.4-4.4.2/docs/src/build/macosx._tx000066400000000000000000000253521173507505700202410ustar00rootroot00000000000000@html_text_substitution=readme.txt|readme.txt @external-css=../allegro.css @document_title=Allegro MacOS X-specific information @
     ______   ___    ___
    /\  _  \ /\_ \  /\_ \
    \ \ \L\ \\//\ \ \//\ \      __     __   _ __   ___ 
     \ \  __ \ \ \ \  \ \ \   /'__`\ /'_ `\/\`'__\/ __`\
      \ \ \/\ \ \_\ \_ \_\ \_/\  __//\ \L\ \ \ \//\ \L\ \
       \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
	\/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
				       /\____/
				       \_/__/


		MacOS X-specific information.

	 See readme.txt for a more general overview.
@
@heading MacOS X notes This is a full featured native MacOS X port. @heading Required software To build Allegro under MacOS X, you need:
  • MacOS X 10.2.x or newer
  • Apple Developer Tools (December 2002 or newer edition)
If you don't have the Developer Tools installed, you can get the latest release at:
http://developer.apple.com/tools/download
On the same page you will also find instructions on how to install them. Note that system version 10.2.x is required to compile Allegro, but the library will still work on 10.1.x. (At least that was true once; we haven't gone back and checked it!) @heading Installing Allegro Allegro ships in source code form; this means you need to compile it before you can use it. You do this easily from a terminal window. See the generic documentation in docs/build/cmake.txt. You may build either Unix-style shared library, or Mac OS X frameworks, or both. XXX information about universal binaries @heading Using Allegro from the command line The options for linking with Allegro are quite long, expecially for static versions of the library as you need to pull in several different frameworks (Cocoa, QuickTime, etc.) other than Allegro itself. When linking against the shared library version, things are also different. To avoid you having to work out the right linker commands for yourself, the installation creates a script, allegro-config, that will print out a suitable commandline. You can use this inside a backtick command substitution, for example: gcc myfile.c -o myprogram `allegro-config --libs` Or if you want to build a debug version of your program, assuming that you have installed the debug version of Allegro: gcc myfile.c -o myprogram `allegro-config --libs debug` You can also link against the Allegro framework, providing you previously installed it: gcc myfile.c -o myprogram `allegro-config --frameworks` Unix newbies, take note that these are ` backticks, not normal ' quotes! There are also switches for printing out the Allegro version number, overriding the install paths, and selecting between shared and static libraries, in case you installed both. Run allegro-config without any arguments for a full list of options. If you get an error like 'allegro-config: program not found', and you're sure you have built and installed the library as described above, it probably means that /usr/local/bin is not on your path. The method to add it depends on the shell you're using. If you have tcsh, add the following line to the end of the .cshrc in your home directory. set path=($path /usr/local/bin) If you have bash, add the following line to the end of the .bash_profile file in your home directory: PATH=${PATH}:/usr/local/bin If you don't know which, just type echo $SHELL on the command line, which will print either /bin/bash or /bin/tcsh. Newer versions of OSX use bash, older ones use tcsh. You will have to close the Terminal window and open a new one once you have made the changes, so it will have an effect. @heading Allegro and application bundles When you build applications from the command line, you're actually just creating the executable, so you can run it from the command line only, and not also from the finder like a common MacOS X application. In other words, compiling from the command line does not create application bundles. Allegro ships with a little tool, named fixbundle, which allows to build an application bundle out of an executable. The utility works from the command line and it accepts a variety of options to customize your bundle; the easiest way to use it is: fixbundle executable_name This will create an application bundle named "executable_name.app" that contains your program executable and will appear in the finder with the default application icon. A more complex usage example follows: fixbundle executable_name -m -o bundle_name -v "1.2" icon.bmp This creates a bundle named "bundle_name.app". The executable will be moved instead of copied into the bundle; the application will be marked as version "1.2" and icon.bmp will be converted to an icon for the bundle. You can specify more options and up to 4 differently sized icons (16x16, 32x32, 48x48 and 128x128) to be read from any Allegro supported image files or from datafile objects. Run fixbundle without arguments for the full list of known options. A special note is required for the "-e" switch; this lets you embed the Allegro framework inside the built application bundle, so your app will not require Allegro to be installed into the target machine in order to work. This flag assumes you previously installed the embeddable version of the Allegro framework, and that your executable has been linked to it, either via Project Builder or XCode, either via the allegro-config script. If one of these conditions is not met, the created app may not work on target machines. Bundles created by fixbundle have this default layout: bundle.app --- Contents --+--- MacOS --- executable | +--- Resources --+--- (bundle.icns) | | | +--- (executable/...) | | +--- (Frameworks) --- (Allegro.framework/...) | +--- Info.plist | +--- PkgInfo If you are using Project Builder to compile your programs, there is no need to use fixbundle, as the IDE will do the work of generating an application bundle for you. When an Allegro program starts, it automatically detects if the executable lives inside a bundle or not. The working directory is always set up to be the directory where the standalone executable or application bundle is located, but there is an exception: if the application is a bundle and Allegro finds a directory under the bundle Contents/Resources path with the same name of the executable (note that here we mean the real executable name, not the bundle name), that directory is set to be the working one. This allows to easily package all the application data inside the bundle, and still have a working program without the need to tell your code about the changed location of your files. @heading Notes on drivers This section contains MacOS X-specific notes on the drivers available.
System:
When the system driver is about to be initialized, we already have a working NSApplication object connected to the Window Server. At driver startup, the working directory is changed if inside a bundle with a proper data directory under the Contents/Resources path (see above). Display switching is possible, but only the SWITCH_BACKGROUND mode is supported, so your application will have to deal with it.
Graphics:
The MacOS X windowed graphics mode uses a Cocoa window with a Quartz QuickDraw view as its content view. All combinations of window/desktop color depths are supported; if needed, color conversion will automatically be done transparently to the user. Fullscreen mode uses the CoreGraphics DirectDisplay API; only 8, 15 and 32 bit color depths are supported.
Sound:
The CoreAudio digital/MIDI drivers use V2 AudioUnits, and thus they require MacOS X 10.2.x (Jaguar) or newer to work. If this is not the case, you can fall back to the Carbon Sound Manager and Quicktime MIDI drivers.
Keyboard:
MacOS X Allegro uses the current system keyboard mapping table to map scancodes to characters: the keyboard user settings in allegro.cfg have no effect.
Mouse:
On MacOS X 10.2.x (Jaguar) or newer, Allegro will automatically detect the number of buttons of your mouse at driver initialization. If the 1-button Apple mouse is found, the library will activate an emulation mode that mimics the way MacOS X itself deals with 1-button mice: depending on which key is pressed when the button is clicked, Allegro will report a different mouse button click. (Control + button) emulates a right click and (Option + button) emulates a middle click. On MacOS X 10.1.x, mouse autodetection is not possible, and Allegro will assume an 1-button mouse to always be present, activating buttons emulation accordingly.
@heading Notes on Threading and Cocoa GUIs It is possible to include a Cocoa GUI in an Allegro application. If you do this you should be aware that Allegro will run your application's main() function in a different thread from the thread that the main OS X event loop runs in. See http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/Multithreading/Introduction/Introduction.html for more information about threading on Mac OS X. @heading Final notes There is a known compatibility problem when using gcc 4 on MacOS X 10.4 that prevents binaries from working on older versions of MacOS X. While it is anticipated that a future update from Apple will fix this problem, you can use gcc 3 to work around it. As a final note, when coding Allegro programs don't forget that you need to use the END_OF_MAIN() macro right after your main() function! allegro4.4-4.4.2/docs/src/build/mingw32._tx000066400000000000000000000327161173507505700202370ustar00rootroot00000000000000@html_text_substitution=readme.txt|readme.txt @external-css=../allegro.css @document_title=Notes on building the MinGW/Cygwin version of Allegro. @
     ______   ___    ___
    /\  _  \ /\_ \  /\_ \
    \ \ \L\ \\//\ \ \//\ \      __     __   _ __   ___ 
     \ \  __ \ \ \ \  \ \ \   /'__`\ /'_ `\/\`'__\/ __`\
      \ \ \/\ \ \_\ \_ \_\ \_/\  __//\ \L\ \ \ \//\ \L\ \
       \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
	\/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
				       /\____/
				       \_/__/


   Notes on building the MinGW/Cygwin version of Allegro.

   See readme.txt for a more general overview.
@
@heading MinGW notes This is a complete MinGW port of Allegro. The screensaver example is built, but you must copy scrsave.scr to your windows/system directory (or winnt/system32 directory under Windows NT/2k/XP) if you want to test it. @heading Obtaining and installing the compiler & tools You have four choices when it comes to installing MinGW and Allegro on your computer:
  • The section 'Setting up MinGW to build Allegro' describes how to set up the MinGW command line tools which is the preferred choice for those who like to work on the command line.
  • The section 'Setting up Dev-C++ to build Allegro' describes how to set up the Dev-C++ environment to work with Allegro. This is the preferred choice for those who like to work in a graphical development environment.
  • The section 'Setting up Cygwin to build Allegro' describes how to set up your Cygwin compiler to build Allegro. Cygwin offers a mature Unix-like environment for you to work in.
  • The last section 'Cross compilation' describes how to set up the MinGW command line tools to compile Win32 programs from your Linux box.
Note: You will need a program to decompress .zip, .tar.gz and optionally .tar.bz2 files. I recommend PowerArchiver (shareware) which can be downloaded from: 'http://www.powerarchiver.com'. @heading Setting up MinGW to build Allegro The procedure is as follows:
1. Make sure you have a working MinGW installation. You can download the complete distribution or individual packages from 'http://www.mingw.org' or 'http://sourceforge.net/projects/mingw/'. You can also use the Minimal SYStem (MSYS) environment with Allegro. 2. Get the minimal DirectX 7 SDK for MinGW (dx70_mgw.zip). You download it from 'http://alleg.sourceforge.net/wip.html'. Note that this is *not* the same package as 'dx70_min.zip'. Unzip it to the compiler directory, overwriting any existing files. 3. Optionally, set the environment variable MINGDIR to the compiler directory. If you use Windows 9x, you can add the line set MINGDIR=c:\MinGW to your 'c:\autoexec.bat' file, assuming 'c:\MinGW' is the compiler directory, and reboot. If you use Windows ME, you can run 'msconfig', select the 'Environment' tab and then add MINGDIR. If you use Windows NT/2k/XP, you can open the Control Panel, click the 'System' applet, the 'Advanced' tab and finally the 'Environment' button, and then add MINGDIR. If you use MSYS, add instead the line export MINGDIR=/mingw to your 'c:\msys\etc\profile' file.
Test the installation by typing the following on the command line: 'gcc -v'. The answer should be similar to: Reading specs from ../lib/gcc-lib/mingw32/3.2/specs Configured with: ../gcc/configure --with-gcc --with-gnu-ld --with-gnu-as --host=mingw32 --target=mingw32 --prefix=/mingw --enable-threads --disable-nls --enable-languages=f77,c++,objc,ada --disable-win32-registry --disable-shared Thread model: win32 gcc version 3.2 (mingw special 20020817-1) If you don't know how to open a terminal, you can click on 'Start -> Run' then type "command". Under Windows 2k/XP, you should type "cmd" instead. @heading Setting up Dev-C++ to build Allegro Note: we assume that the complete version of the Dev-C++ environment (i.e with the bundled MinGW compiler) is used. If you use instead Dev-C++ as a mere IDE on top of an already installed MinGW compiler, follow the instructions given in the previous section. The procedure is as follows:
1. Make sure you have a working Dev-C++ installation. You can download the complete version from 'http://bloodshed.net/dev/devcpp.html'. 2. Get the DirectX SDK: go to Tools\Check for Updates/Packages... and install the DirectX package. Close Dev-C++. 3. Add 'c:\DevCpp\bin' to the beginning of your PATH environment variable. Optionally, set the environment variable MINGDIR to 'c:\DevCpp'. If you use Windows 9x, you can add the lines PATH=c:\DevCpp\bin;%PATH% set MINGDIR=c:\DevCpp to your 'c:\autoexec.bat' file and reboot. If you use Windows ME, you can run 'msconfig', select the 'Environment' tab, then modify PATH and add MINGDIR. If you use Windows NT/2k/XP, you can open the Control Panel, click the 'System' applet, the 'Advanced' tab and finally the 'Environment' button, then modify PATH and add MINGDIR.
Test the installation by typing the following on the command line: 'gcc -v'. The answer should be similar to: Reading specs from ../lib/gcc-lib/mingw32/3.2/specs Configured with: ../gcc/configure --with-gcc --with-gnu-ld --with-gnu-as --host=mingw32 --target=mingw32 --prefix=/mingw --enable-threads --disable-nls --enable-languages=f77,c++,objc,ada --disable-win32-registry --disable-shared Thread model: win32 gcc version 3.2 (mingw special 20020817-1) If you don't know how to open a terminal, you can click on 'Start -> Run' then type "command". Under Windows 2k/XP, you should type "cmd" instead. @heading Setting up Cygwin to build Allegro Note: Allegro 4.4 has not been tested with Cygwin yet! The procedure is as follows:
1. Make sure you have a working Cygwin installation. You can download the setup.exe program from 'http://sources.redhat.com/cygwin/'. You will need the following packages: bash, binutils, coreutils, cygwin, cygutils, fileutils, gcc, gdb, login, make, man, mingw-runtime, sed, texinfo and w32api. 2. Get the minimal DirectX 7 SDK for MinGW. (dx70_mgw.zip) Download it from 'http://alleg.sourceforge.net/wip.html' and unzip it to a temporary directory, for instance 'C:\Temp'. Then move the contents of 'C:\Temp\lib' to 'C:\cygwin\lib\w32api', and the contents of 'C:\Temp\include' to 'c:\cygwin\usr\include\w32api'. If you are asked if you want to overwrite any existing files, choose to overwrite them. 3. Put the following text in '/etc/profile' (c:\cygwin\etc\profile) export ALLEGRO_USE_CYGWIN=1 export MINGDIR=/usr/local export CPATH=/usr/local/include export LIBRARY_PATH=/usr/local/lib Note: if the CPATH or LIBRARY_PATH variables are already set, you will have to append the new path to the existing one by using a colon (":") as the separator.
Test the installation by typing the following in the Bash shell: 'gcc -v'. The answer should be similar to: Reading specs from /usr/lib/gcc-lib/i686-pc-cygwin/3.2/specs gcc version 3.2 20020927 (prerelease) Note: if you have problems installing the profiling version of the Allegro library, you will probably need to copy a file called libgmon.a from the MinGW distribution to your /lib/mingw directory (c:\cygwin\lib\mingw) in Cygwin. This is expected to be fixed in a later release of the mingw-runtime package (I'm currently using mingw-runtime-1.2-1). @heading Cross compilation The procedure is as follows:
1. Download and install the MinGW cross-compiler. You can get the software:
  • directly from the MingW site: http://sourceforge.net/projects/mingw/. You need the following packages (as of February 2003):
    • gcc (gcc-3.2.2-20030208-1-src.tar.gz)
    • binutils (binutils-2.13.90-20030111-1-src.tar.gz)
    • mingw runtime (mingw-runtime-2.4.tar.gz)
    • w32api (w32api-2.2.tar.gz)
    Optionally, you can get from the SDL site, http://www.libsdl.org/extras/win32/common: opengl-devel (opengl-devel.tar.gz)
  • using a more convenient script with instructions for downloading: http://www.libsdl.org/extras/win32/cross/README.txt. Follow the instructions, and make sure to edit the build-crosh.sh script so it downloads the most recent version of gcc and binutils.
  • as a premade Debian package called 'mingw32', which you can install with 'apt-get install mingw32'.
2. Get the minimal DirectX 7 SDK for MinGW (dx70_mgw.zip). Download it from 'http://alleg.sourceforge.net/wip.html' and unzip it in the cross-compiler base directory. Make sure you convert all text files to unix style (unzip -a) or the preprocessor will croak. The DirectX package downloaded and installed by the SDL script is not up to date: replace it with the package from the Allegro site. 3. Use the cmake/Toolchain-mingw.cmake file. Remember to set MINGDIR if your MinGW binaries live alongside your native binaries, otherwise the 'make install' step may make a mess in your normal directories.
@heading Installing Allegro Once your compiler is set up, follow the generic build instructions in docs/build/cmake.txt. @heading Using Allegro All the Allegro functions, variables, and data structures are defined in allegro.h. You should include this in your programs, and link with either the optimised library liballeg.a, the debugging library liballeg-debug.a, or the profiling library liballeg-profile.a. You should include the Allegro DLLs in any software you release to the public. When using a statically linked library, you must define the preprocessor symbol ALLEGRO_STATICLINK before including any of the Allegro headers and link your program against Allegro and the main Win32/DirectX libraries in that order. The names of the statically linked Allegro libraries are post-fixed with '-static' so that you will link with either liballeg-static.a, liballeg-debug-static.a or liballeg-profile-static.a. Don't forget that you need to use the END_OF_MAIN() macro right after your main() function. @heading Compiling manually with MinGW A simple example of a command line to compile an Allegro program with MinGW looks like: gcc foo.c -Wl,--subsystem,windows -O2 -Wall -o foo.exe -lalleg If you are compiling with Cygwin, the compiler option '-mno-cygwin' must be added, both at compile-time and at link-time: gcc foo.c -Wl,--subsystem,windows -mno-cygwin -O2 -Wall -o foo.exe -lalleg Note that, if you want to make a console application, you must use '-Wl,--subsystem,console' instead of '-Wl,--subsystem,windows'. @heading Creating a program with Dev-C++ A simple example on how to create a little program with Dev-C++: Launch Dev-C++ and create a new project (File/New Project). Select "Windows Application", then click on the "Ok" button. Name your project and give associate it to a new file. You should now see a sample code in a window. Close that window since you won't be needing it (Allegro is much simpler to use than this). Create a new file (File/New Source File), then write a small Allegro program. You can inspire yourself by the Allegro examples if you wish. Here's a small program you can type to see if everything worked until now: #include <allegro.h> int main() { allegro_init(); allegro_message("Hello World!"); return 0; } END_OF_MAIN() You now need to tell Dev-C++ that you'd like to make a program that uses Allegro. For that, go in the Project Options screen (Project/Project Options menu), then enter -lalleg (or -lalld for the debug mode) in the box under 'Further object file or linker options' or select 'Parameters tab' and enter -lalleg (or -lalld for the debug mode) in the box under 'Linker'. Compile your project! Simply click on the green check mark on your Dev-C++ toolbar. Correct any syntax errors in your code, then click on "Execute" to run the program. If all worked you will see a message box pop up with "Hello World" inside of it. Happy coding! allegro4.4-4.4.2/docs/src/build/msvc._tx000066400000000000000000000121471173507505700177150ustar00rootroot00000000000000@html_text_substitution=readme.txt|readme.txt @external-css=../allegro.css @document_title=Allegro MSVC-specific information @
     ______   ___    ___
    /\  _  \ /\_ \  /\_ \
    \ \ \L\ \\//\ \ \//\ \      __     __   _ __   ___ 
     \ \  __ \ \ \ \  \ \ \   /'__`\ /'_ `\/\`'__\/ __`\
      \ \ \/\ \ \_\ \_ \_\ \_/\  __//\ \L\ \ \ \//\ \L\ \
       \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
	\/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
				       /\____/
				       \_/__/


		 MSVC-specific information.

	 See readme.txt for a more general overview.
@
@heading MSVC notes Status: complete. The screensaver example is built, but you must copy scrsave.scr to your windows/system directory (or winnt/system32 directory under Windows NT/2k/XP) if you want to test it. You may also want to refer to one of the following, as they may include more up to date information:
  • http://wiki.allegro.cc/Build/MSVC_6
  • http://wiki.allegro.cc/Build/MSVC_7
  • http://wiki.allegro.cc/Build/MSVC_8
@heading Project Files The CMake tool can generate workspaces for MSVC. If everything builds successfully, you'll need to copy some files to finish the installation:
  • Copy the contents of C:\allegro\include to "Visual Studio\VC\include"
  • Copy the .lib files from C:\allegro\lib\msvc to "Visual Studio\VC\lib"
  • Copy the .dll files from C:\allegro\lib\msvc to C:\Windows\System32
The most common location of Visual Studio is "C:\Program Files\Microsoft Visual Studio." Then you can build the rest of the examples, demos, tests, and tools by opening up their respective project files and selectiong Batch Build from the menu. @heading Required software
  • Microsoft Visual C++.
  • Recent set of DirectX and other Windows SDK headers.
Allegro should work with MSVC versions 6 and above. Lower versions may work but haven't been tested in a long time. The DirectX SDK can be obtained directly from Microsoft. An old version of the headers is included with MSVC 6, but Allegro requires more recent files. You should either copy the current headers into your MSVC include and lib directories, or alter your INCLUDE and LIB environment variables to put the DirectX SDK files in front of the standard MSVC locations. Microsoft Visual Studio Express Editions (free): You will need to separately download and install the "Platform SDK" or "Windows SDK". In the IDE, go to Tools > Options > Projects and Solutions > VC++ Directories and add the Platform SDK and DirectX Include and Lib/x86 (or whatever) directories to the relevant lists. @heading Installing Allegro This is a source-only distribution, so you will have to compile Allegro before you can use it. Please follow the generic instructions in docs/build/cmake.txt. If you need to call MSVC from the command line, you may need to set up your environment. You probably have a vcvars32.bat file that will do this for you (the exact location of this file depends on your MSVC version and folder where you have MSVC installed, e.g. for MSVC 6 it is usually C:\Program Files\Microsoft Visual Studio\VC98\Bin, for MSVC 8 C:\Program Files\Microsoft Visual Studio 8\VC\Bin etc.). You will have to run this file every time you open a DOS box or configure the environment variables in Control Panel/System/Environment (autoexec.bat for Win 9x/ME). @heading Using Allegro All the Allegro functions, variables, and data structures are defined in allegro.h. You should include this in your programs, and link with one of the libraries: alleg.lib - optimised DLL import library alleg-debug.lib - debugging DLL import library alleg-profile.lib - profiling DLL import library alleg-static.lib - statically linked optimised library alleg-debug-static.lib - statically linked debugging library alleg-profile-static.lib - statically linked profiling library When using a statically linked library, you must define the preprocessor symbol ALLEGRO_STATICLINK before including any of the Allegro headers and link your program against Allegro and the main Win32/DirectX libraries in that order (see the variable LIBRARIES in makefile.vc). You have also to make sure that your program is linked against the right C run-time library, ie. the multi-threaded DLL version of MSVCRT (or the debug version if you are using the debug library). You can change this option at Project - Settings - C/C++ - Category: Code Generation - Use run-time library. Don't forget that you need to use the END_OF_MAIN() macro right after your main() function! If you use one of the DLL versions, you will obviously need to distribute the appropriate DLL along with your program. allegro4.4-4.4.2/docs/src/build/obsolete/000077500000000000000000000000001173507505700200405ustar00rootroot00000000000000allegro4.4-4.4.2/docs/src/build/obsolete/bcc32._tx000066400000000000000000000077231173507505700214610ustar00rootroot00000000000000@html_text_substitution=readme.txt|readme.txt @html_text_substitution=docs/build/mingw32.txt|docs/build/mingw32.txt @html_text_substitution=docs/build/djgpp.txt|docs/build/djgpp.txt @external-css=../allegro.css @document_title=Allegro Borland C++Builder-specific information @
     ______   ___    ___
    /\  _  \ /\_ \  /\_ \
    \ \ \L\ \\//\ \ \//\ \      __     __   _ __   ___ 
     \ \  __ \ \ \ \  \ \ \   /'__`\ /'_ `\/\`'__\/ __`\
      \ \ \/\ \ \_\ \_ \_\ \_/\  __//\ \L\ \ \ \//\ \L\ \
       \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
	\/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
				       /\____/
				       \_/__/


	  Borland C++Builder-specific information.

	 See readme.txt for a more general overview.
@
@heading BCC32 notes Status: it works. It currently doesn't build the Allegro library from the sources, but it does let you compile your own Allegro-based programs and run them with the Allegro DLLs. Thanks to Inprise for creating the very useful IMPLIB program. The screensaver example is built, but you must copy scrsave.scr to your windows/system directory (or winnt/system32 directory under Windows NT/2k/XP) if you want to test it. @heading Required software
  • Borland C++Builder (or Borland C++ command line tools)
  • Recent set of DirectX and other Windows SDK headers.
  • GNU make 3.77 or higher.
  • Optional: GNU sed. Used by "make depend" and "fixdll.bat".
  • Optional: GNU sort (not DOS sort). Used by "fixdll.bat".
In order to run your programs, you need to obtain the Allegro DLLs and install them in the Windows system directory. This is known to work with the Borland C++ 5.5 command line compiler. Earlier versions may cause problems (for example v5.02). You need to use GNU make, since Borland make is really ugly about its makefiles. You can grab it from either the MinGW or DJGPP distributions; more info on this in available in the following files: docs/build/mingw32.txt and docs/build/djgpp.txt. @heading Installing Allegro Set up your environment so that Borland C++ can be used from the commandline. Then set the variable BCC32DIR to the directory where Borland C++ is located, for example 'set BCC32DIR=c:\bcc32'. Type "cd allegro" and then "fix.bat bcc32". Then, run "make". Find something fun to do while it's compiling. It will eventually finish; then just type "make install" to set the library up for use. If you also want to install a debugging version of the library (highly recommended), type "make install DEBUGMODE=1". Case is important, so it must be DEBUGMODE, not debugmode! If you also want to install a profiling version of the library, now type "make install PROFILEMODE=1". If your copy of Allegro doesn't include the makefile.dep dependency files (unlikely, unless you have run "make veryclean" at some point), you can regenerate them by running "make depend". If your copy of Allegro doesn't include the linker .def file (unlikely, unless you have run "make veryclean" at some point), you can regenerate it by running "misc\fixdll.bat". @heading Using Allegro All the Allegro functions, variables, and data structures are defined in allegro.h. You should include this in your programs, and link with one of the libraries: alleg.lib - optimised DLL import library alld.lib - debugging DLL import library allp.lib - profiling DLL import library Don't forget that you need to use the END_OF_MAIN() macro right after your main() function! You will need to distribute the appropriate DLL along with your program. allegro4.4-4.4.2/docs/src/build/obsolete/beos._tx000066400000000000000000000107151173507505700215100ustar00rootroot00000000000000@html_text_substitution=readme.txt|readme.txt @external-css=../allegro.css @document_title=Allegro BeOS-specific information @
     ______   ___    ___
    /\  _  \ /\_ \  /\_ \
    \ \ \L\ \\//\ \ \//\ \      __     __   _ __   ___ 
     \ \  __ \ \ \ \  \ \ \   /'__`\ /'_ `\/\`'__\/ __`\
      \ \ \/\ \ \_\ \_ \_\ \_/\  __//\ \L\ \ \ \//\ \L\ \
       \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
	\/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
				       /\____/
				       \_/__/


		 BeOS-specific information.

	 See readme.txt for a more general overview.
@
@heading BeOS notes Status: It compiles for Intel R4 & R5. Port is complete. @heading Required software BeOS Intel R4 and R5 Pro Edition come with everything you need. If you have BeOS Intel R5 Personal Edition, you require the development tools; these can be found on the Be homepage at http://www.be.com. You also need updated binutils, which can be found at http://bebits.com. It might not be a bad idea to update gcc as well, but is not required. @heading Installing Allegro Allegro comes as a source distribuition: you'll have to compile it to get it to work. Unzip the library archive wherever you want, and cd into that directory with a Terminal. Due to the multi-platform nature of Allegro, you need to run: fix.sh beos This will set the library ready to be compiled on the Be platform. Now you must build it: make And then install it: make install With this last command the Allegro library will be installed into /boot/home/config/lib (the default location for BeOS shared libraries), while the headers will go into /boot/develop/headers (the default locations where Be looks for them). You have now installed Allegro! See the rest of the documentation and examples to learn more about it. A simple example of a command line to compile an allegro program: gcc foo.c -O2 -Wall -o foo `allegro-config --shared` The `allegro-config --shared` is explained in the next section. The dynamically linked version of Allegro gets built by default but if you want to build the statically linked version of Allegro write the following on the command line: export STATICLINK=1 In the same manner we can also enter one of the following lines to build either the debug or the profiling version of the library: export DEBUGMODE=1 export PROFILEMODE=1 Then we can start to actually make and install the Allegro library. make make install If you have compiled a static version of the library, it will be copied to /boot/develop/lib/x86. @heading Using Allegro Linking Allegro to a program also requires you to link several other BeOS libraries and set the correct library search pathes. To simplify the linking process, the installation sets up a script, allegro-config, that will print out a suitable commandline. You can use this inside backtick command substitution, for example: gcc myfile.c -o myprogram `allegro-config --static` This will enable you to link against the static library. The `allegro-config --shared` option mentioned above will output all the options and libraries needed to link dynamically against the shared version of the Allegro library. If you use --libs instead of --shared or --static, the script will generate the linking arguments according to the latest installed library version. You can also run these allegro-config commands on the commandline to see what exactly they do. If you want to build a debug version of your program, assuming that you have installed the debug version of Allegro, use: gcc myfile.c -o myprogram `allegro-config --libs debug` Terminal newbies, take note that these are ` backticks, not normal ' quotes! There are also other switches for printing out the Allegro version number, or to override the install paths. Run allegro-config without any arguments for a full list of options. Don't forget that you need to use the END_OF_MAIN() macro right after your main() function! allegro4.4-4.4.2/docs/src/build/obsolete/darwin._tx000066400000000000000000000076771173507505700220610ustar00rootroot00000000000000@html_text_substitution=readme.txt|readme.txt @html_text_substitution=docs/build/unix.txt|docs/build/unix.txt @html_text_substitution=docs/build/macosx.txt|docs/build/macosx.txt @external-css=../allegro.css @document_title=Notes on building the Darwin/X11 version of Allegro @
     ______   ___    ___
    /\  _  \ /\_ \  /\_ \
    \ \ \L\ \\//\ \ \//\ \      __     __   _ __   ___ 
     \ \  __ \ \ \ \  \ \ \   /'__`\ /'_ `\/\`'__\/ __`\
      \ \ \/\ \ \_\ \_ \_\ \_/\  __//\ \L\ \ \ \//\ \L\ \
       \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
	\/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
				       /\____/
				       \_/__/

   Notes on building the Darwin/X11 version of Allegro.

   See docs/build/unix.txt for general Unix information.

   See readme.txt for a more general overview.
@
@heading Darwin Notes This file explains how to build the X Window port of Allegro on a Darwin system. If you are running MacOS X, you are strongly encouraged to use the MacOS X native port; read docs/build/macosx.txt for more info. It is important to note that there is no sound because the sound drivers have not yet been ported. This library cannot yet be compiled as a shared library, only static. @heading Required software If you are running MacOS X, you must download the developer tools. This requires free registration with Apple. You can register and download the tools at:
http://connect.apple.com
Recently, GCC 3.1 has been released which supports the Mach-O binary format, and you may be able to use it directly (if you compile it yourself or find a binary distribution.) You will also need X Window. You can use either the Darwin/MacOS X port of XFree86 from the XonX project or Xtools, a proprietary version. The XonX project is located at:
http://sourceforge.net/projects/xonx
@heading Installing Allegro First, decompress the .tar or .zip file into some directory. Next, open up a terminal (in MacOS X, this can be found in Applications/Utilities). From here, enter the directory into which Allegro has been decompressed. If you are using the .zip file, type the following: chmod +x fix.sh ./fix.sh unix From here on everything is a pretty standard Unix-style install process. First you configure it with at least the following options: ./configure --enable-static --disable-shared --disable-pthreads It should automatically build dependencies. Then you build it: make If you are using an older version of Apple's tools, you will probably see lots of preprocessing errors. Just ignore them (they are due to Apple's modifications to GCC and do not affect the resulting object code). To install Allegro, you will need root permissions. If you don't have root permissions set up on your system (in MacOS X, for example), you will first need to activate the root account. This can be done by running the program "NetInfo Manager" in Applications/Utilites. From within the program, go to the "Domain" menu, select "Security" and "Authenticate". Type in your password and go to "Domain", "Security", "Root User Enable". I strongly urge you to set your root password in the same menu. Now, type the following in the terminal: su -c "make install" To install the man pages, type: su -c "make install-man" If prompted for a password, type in your root password. @heading Using Allegro When compiling a program using Allegro, you will have to link to the following libraries: -lalleg -lX11 -lXext If you are using the XFree86 port, you will also have to add: -lXxf86vm allegro4.4-4.4.2/docs/src/build/obsolete/djgpp._tx000066400000000000000000000327361173507505700216730ustar00rootroot00000000000000@html_text_substitution=readme.txt|readme.txt @html_text_substitution=docs/txt/faq.txt|docs/txt/faq.txt @external-css=../allegro.css @document_title=Allegro DJGPP-specific information @
     ______   ___    ___
    /\  _  \ /\_ \  /\_ \
    \ \ \L\ \\//\ \ \//\ \      __     __   _ __   ___ 
     \ \  __ \ \ \ \  \ \ \   /'__`\ /'_ `\/\`'__\/ __`\
      \ \ \/\ \ \_\ \_ \_\ \_/\  __//\ \L\ \ \ \//\ \L\ \
       \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
	\/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
				       /\____/
				       \_/__/


		DJGPP-specific information.

	 See readme.txt for a more general overview.
@
@heading djgpp notes Status: complete. This is the original Allegro version, and has had plenty of time to become nice and stable. However, under Windows NT, 2000, or XP you will very likely experience problems and should consider using the native Windows version of Allegro instead, less likely to give you problems under such environments. @heading Required software
  • DJGPP 2.01 or later (djdev*.zip).
  • GCC compiler 2.91.x or later (gcc*b.zip). Note: gcc 3.0.x (0 <= x <= 1) doesn't properly compile Allegro.
  • Binutils 2.9.x or later (bnu*b.zip).
  • GNU make (mak*b.zip).
  • Texinfo (txi*b.zip).
  • Optional: sed (sed*b.zip). Used by "make depend".
All of the above can be downloaded from your nearest SimTel mirror site, in the /pub/simtelnet/gnu/djgpp/ directory, or you can use the zip picker on http://www.delorie.com/djgpp/. Please make sure that you have installed djgpp according to the instructions in readme.1st, and that you aren't mixing it with any files from different compilers (eg. the Borland version of make). @heading Allegro SVN Notes If you are using a SVN version of Allegro, then you will need to do some extra things to ensure that your copy of Allegro will compile correctly. These are covered in detail below, but briefly:
1. You must run the `fix' script (either the batch file, under command.com, or the .sh file under bash). You must supply the argument `djgpp'. 2. You must regenerate the dependency files: a simple `make depend' will do this. However, please note that you must have sed installed to do this.
@heading Installing Allegro This is a source-only distribution, so you will have to compile Allegro before you can use it. To do this you should: Go to wherever you want to put your copy of Allegro (your main djgpp directory would be fine, but you can put it somewhere else if you prefer), and unzip everything. Allegro contains several subdirectories, so you must specify the -d flag if you are using pkunzip. If you are running under Linux, and want to cross-compile the djgpp version of Allegro, set the environment variable "CROSSCOMPILE=1", set DJDIR to the directory where your djgpp cross-compiler is installed, set PATH to access to the cross-compiler, and set NATIVEPATH to a path that will use your native version of gcc instead (_not_ the djgpp cross-compiler!) so that this can be invoked when converting the documentation. You might like to edit and use `xmake.sh'; there are further instructions in comments in the file. You must also run 'fix.sh djgpp' as detailed above - it is required to properly configure Allegro for building with djgpp. Type "cd allegro", followed by "make". Then go do something interesting while everything compiles. When it finishes compiling, type "make install" to set the library up ready for use. If you have any trouble with the build, look at docs/txt/faq.txt for the solutions to some of the more common problems. If you also want to install a debugging version of the library (highly recommended), now type "make install DEBUGMODE=1". Case is important, so it must be DEBUGMODE, not debugmode! If you also want to install a profiling version of the library, now type "make install PROFILEMODE=1". If you want to read the Allegro documentation with the Rhide online help system, go to the "Help / Syntax help / Files to search" menu, and add "allegro" after the existing "libc" entry (separated by a space). If you want to create the HTML documentation as one large allegro.html file rather than splitting it into sections, edit docs/allegro._tx, remove the @multiplefiles statement from line 8, and run make again. Once the build is finished you can recover some disk space by running "make compress" (which uses the DJP or UPX programs to compress the executable files), and/or "make clean" (to get rid of all the temporary files and HTML format documentation). If your copy of Allegro is set up for use with some different compiler (if you downloaded a tar.gz archive or a SVN version), you will have to run 'fix.bat djgpp' before compiling it. If you are using bash you can run 'fix.sh djgpp' instead. If your copy of Allegro doesn't include the makefile.dep dependency files (if you have run "make veryclean" or you have the SVN version), you can regenerate them by running "make depend". If `make' tells you that you need to download a new package, or if you need the `sed' package to generate dependencies, you can find these at ftp://ftp.demon.co.uk/pub/mirrors/simtelnet/gnu/djgpp/. A list of all the available options:
CROSSCOMPILE
Set this if you are crosscompiling; it implies UNIX_TOOLS.
WARNMODE
Set this if you want Allegro to display and stop on nearly all warnings issued by the compiler. Allegro should compile fine with this set.
TARGET_ARCH_COMPAT or TARGET_ARCH_EXCL
These affect the level of processor dependant optimisation that Allegro uses. You can set either of these to the processor type you want to optimize for. The difference between these two is that TARGET_ARCH_COMPAT optimise for the given processor so that the code will still run on older processors, while TARGET_ARCH_EXCL will generate code that will run exclusively on the given processor and of course newer ones. Example: set TARGET_ARCH_COMPAT=i686
TARGET_OPTS
Affects the general optimisations that Allegro uses.
UNIX_TOOLS
If your system does not have the usual DOS tools available (`md', `rd', `copy', etc., and commands which understand the \ character), then set this to 1 to use the Unix equivalents. This is set implicitly when you set CROSSCOMPILE, and is also set automatically when you are running under bash.
To activate any of these, type (for example) "make WARNMODE=1". @heading Using Allegro All the Allegro functions, variables, and data structures are defined in allegro.h. You should include this in your programs, and link with either the optimised library liballeg.a, the debugging library liballd.a, or the profiling library liballp.a. To do this you should: Put the following line at the beginning of all C or C++ files that use Allegro: #include <allegro.h> If you compile from the command line or with a makefile, add either '-lalleg' (for the optimised version), '-lalld' (debugging version), or '-lallp' (profiling version) to the end of the gcc command, eg: gcc foo.c -o foo.exe -lalleg If you are using Rhide, go to the Options/Libraries menu, type either 'alleg' (for the optimised version), 'alld' (debugging version), or 'allp' (profiling version) into the first empty space, and make sure the box next to it is checked. @heading Supported hardware The bare minimum you need to use Allegro is a 386 with a VGA graphics card, but a 486 is strongly recommended. To get into SVGA modes you will need a compatible SVGA card, which means something that has a working VESA or VBE/AF driver. Ideally you should use VBE/AF, because it allows Allegro to use hardware acceleration functions to speed up the drawing. The FreeBE/AF project (http://www.talula.demon.co.uk/freebe/) provides a number of free VBE/AF drivers (volunteers to write more are always welcome!), and accelerated drivers for a large number of cards are available commercially as part of the SciTech Display Doctor package (http://www.scitechsoft.com/). If you have a VBE 2.0 or VBE 3.0 driver you are probably fine just using that, although unlike VBE/AF it won't provide any hardware acceleration. If you have an older VESA BIOS implementation (eg. VESA 1.2), beware. For one thing, everything will be much slower if Allegro can't use the sexy VBE 2.0 features. For another, I could go on all day telling horror stories about the buggy and generally just pathetic VESA implementations that I've come across. If you are having trouble with the SVGA modes, try getting a copy of the SciTech Display Doctor and see if that clears things up (it probably will: SciTech usually get these things right). Note that the native SVGA chipset drivers from Allegro 3.0 and earlier have been removed. These are still available as an optional add-on package from the same sites as Allegro, but are not needed any more because you can get the same code in a more flexible format as part of the FreeBE/AF project. On the sound front, Allegro supports sample playback on the SB (mono), the SB Pro (stereo), the SB16, the ESS AudioDrive, the Ensoniq Soundscape, and the Windows Sound System. It has MIDI drivers for the OPL2 FM synth (Adlib and SB cards), the OPL3 (Adlib Gold, SB Pro-II and above), the pair of OPL2 chips found in the SB Pro-I, the AWE32 EMU8000 chip, the raw SB MIDI output, and the MPU-401 interface, plus it can emulate a wavetable MIDI synth in software, running on top of any of the supported digital soundcards. The Creative Labs SB PCI-64 and PCI-128 cards are actually based on the Ensoniq chipset, so they can be used with the Soundscape and MPU-401 drivers. You'll have to manually select the MPU, though, because it won't be autodetected. Actually, quite a lot of wavetable boards emulate the MPU, so give this a try and see if it works on your card. If you feel like coming up with drivers for any other hardware, they would be much appreciated. Audio recording is supported for all SB cards, but only in unidirectional mode, ie. you cannot simultaneously record and playback samples. MIDI input is provided by the MPU-401 and SB MIDI drivers, but there are some restrictions on this. The SB MIDI interface cannot be used at the same time as the digital sound system, and the MPU will only work when there is an IRQ free for it to use (this will be true if you have an SB16 or greater, or if no SB-type digital driver is installed, or if your MIDI interface uses a different IRQ to the SB). @heading Notes for the musician The OPL2 synth chip can provide either nine voice polyphony or six voices plus five drum channels. How to make music sound good on the OPL2 is left as an exercise for the reader :-) On an SB Pro or above you will have eighteen voices, or fifteen plus drums. Allegro decides whether to use drum mode individually for each MIDI file you play, based on whether it contains any drum sounds or not. If you have an orchestral piece with just the odd cymbal crash, you might be better removing the drums altogether as that will let Allegro use the non-drum mode and give you an extra three notes polyphony. When Allegro is playing a MIDI file in looped mode, it jumps back to the start of the file when it reaches the end of the piece. To control the exact loop point, you may need to insert a dummy marker event such as a controller message on an unused channel. All the OPL chips have very limited stereo capabilities. On an OPL2, everything is of course played in mono. On the SB Pro-I, sounds can only be panned hard left or right. With the OPL3 chip in the SB Pro-II and above, they can be panned left, right, or centre. I could use two voices per note to provide more flexible panning, but that would reduce the available polyphony and I don't want to do that. So don't try to move sounds around the stereo image with streams of pan controller messages, because they will jerk horribly. It is also worth thinking out the panning of each channel so that the music will sound ok on both SB Pro-I and OPL3 cards. If you want a sound panned left or right, use a pan value less than 48 or greater than 80. If you want it centred, use a pan value between 48 and 80, but put it slightly to one side of the exactly central 64 to control which speaker will be used if the central panning isn't possible. allegro4.4-4.4.2/docs/src/build/obsolete/dmc._tx000066400000000000000000000126761173507505700213330ustar00rootroot00000000000000@html_text_substitution=readme.txt|readme.txt @external-css=../allegro.css @document_title=Allegro DMC-specific information @
     ______   ___    ___
    /\  _  \ /\_ \  /\_ \
    \ \ \L\ \\//\ \ \//\ \      __     __   _ __   ___ 
     \ \  __ \ \ \ \  \ \ \   /'__`\ /'_ `\/\`'__\/ __`\
      \ \ \/\ \ \_\ \_ \_\ \_/\  __//\ \L\ \ \ \//\ \L\ \
       \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
	\/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
				       /\____/
				       \_/__/


		 DMC-specific information.

	 See readme.txt for a more general overview.
@
@heading DMC notes Status: complete. Caveats: The DMC runtime library does not support unicode paths. DMC is the only Windows compiler that can build a static library that can be used with DAllegro. The instructions at http://wiki.allegro.cc/Build/DMC might be more up to date. @heading Required software
  • Digital Mars C/C++ Compiler - http://www.digitalmars.com/d/1.0/download.html
  • Digital Mars Basic Utilities - http://ftp.digitalmars.com/bup.zip
  • GNU Make - http://sourceforge.net/project/showfiles.php?group_id=9328
  • Recent set of DirectX and other Windows SDK headers. - http://alleg.sourceforge.net/files/dx70_dmc.zip
@heading Setting up DMC
  1. Unzip the Digital Mars compiler (dmc.zip) and place the files in c:\dmc.
  2. Unzip the Basic Utilities (bup.zip) and place them in the same folder. (The exe files should all be in the c:\dmc\bin folder.)
  3. Unzip the DirectX 7 package (dx70_dmc.zip) and place the include files in c:\dmc\include and the library files in c:\dmc\lib. (This will overwrite some of DMC's default DX files.)
  4. Extract only the usr/local/wbin/make.exe file from UnxUtils.zip to your desktop, rename it to gmake.exe, and copy it to c:\dmc\bin.
  5. Add c:\dmc\bin to your PATH environment variable.
  6. Create the DMCDIR environment variable and set it to c:\dmc
@heading Building Allegro @hnode Step by Step Instructions
  • Extract the Allegro source zip file to c:\allegro
  • Open up a MS-DOS prompt and type the following commands.
cd\allegro fix dmc gmake obj\dmc\plugins.h gmake all STATICLINK=1 gmake installall STATICLINK=1 gmake all gmake installall @hnode Advanced Build Options The above instructions build six versions of Allegro, the Demo, tools, examples, and the documentation. If you don't need all of that, you can customize what gets built. Obviously, if you don't need both the static or dynamic libraries, simply don't run the associated commands. If you don't care about the Debugging or Profiling versions, you can remove the word all from the command line. For example: gmake gmake install builds and installs the optimized, dynamic Allegro library along with all of the examples, documents, etc. Or if you want to specifically build and install the debug and profiling versions: gmake DEBUGMODE=1 gmake install DEBUGMODE=1 gmake PROFILEMODE=1 gmake install PROFILEMODE=1 If you only want to build the library (without the extra stuff), specifically request to make the lib target: gmake lib That would only build the optimized, dynamic Allegro library. Other targets besides lib exist; refer to Makefile.all and Makefile.dmc for more information. All of the options can be mixed and matched where it makes sense. @heading Using Allegro @hnode Hello World For a simple example, consider hello.c: #include <allegro.h> int main(void) { allegro_init(); set_gfx_mode(GFX_AUTODETECT_WINDOWED, 640, 480, 0,0); allegro_message("Hello, World!"); return 0; } END_OF_MAIN() First, you must include the Allegro header file. Inside the main function, you should call allegro_init() to set up Allegro. You must do that before calling (almost) any of the other Allegro functions. (This program will create a 640x480 window and then pop-up the message "Hello, World!".) At the end of the main function, you must include the END_OF_MAIN() macro (no semicolon is needed). @hnode Dynamic Version (DLL) To compile this program, type: dmc -c test.c This will create the object file. It will then need to be linked to Allegro when you create the executable: dmc test.obj alleg.lib -otest.exe That will build test.exe, which will require the Allegro DLL (eg: alleg42.dll) to run. Alternatively you could use allp.lib for profiling or alld.lib for debugging. @hnode Static Version If you wanted to statically link this program so that the Allegro DLL is not required, you must first compile it like: dmc -c test.c -DALLEGRO_STATICLINK=1 Then you can link it against any of the static versions of Allegro: dmc test.obj alleg_s.lib kernel32.lib user32.lib gdi32.lib comdlg32.lib ole32.lib dinput.lib ddraw.lib winmm.lib dsound.lib dxguid.lib (All of that should be entered on one line.) Note that you have to include a bunch of Windows libraries when you statically link! As before, you can also use allp_s.lib for profiling and alld_s.lib for debugging. allegro4.4-4.4.2/docs/src/build/obsolete/haiku._tx000066400000000000000000000045051173507505700216610ustar00rootroot00000000000000@html_text_substitution=readme.txt|readme.txt @external-css=../allegro.css @document_title=Allegro Haiku-specific information @
     ______   ___    ___
    /\  _  \ /\_ \  /\_ \
    \ \ \L\ \\//\ \ \//\ \      __     __   _ __   ___
     \ \  __ \ \ \ \  \ \ \   /'__`\ /'_ `\/\`'__\/ __`\
      \ \ \/\ \ \_\ \_ \_\ \_/\  __//\ \L\ \ \ \//\ \L\ \
       \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
	\/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
				       /\____/
				       \_/__/


		 Haiku-specific information.

	 See readme.txt for a more general overview.
@
@heading Haiku notes Status: don't know. @heading Required software Don't know. @heading Installing Allegro Don't know. @heading Using Allegro Linking Allegro to a program also requires you to link several other Haiku libraries and set the correct library search pathes. To simplify the linking process, the installation sets up a script, allegro-config, that will print out a suitable commandline. You can use this inside backtick command substitution, for example: gcc myfile.c -o myprogram `allegro-config --static` This will enable you to link against the static library. The `allegro-config --shared` option mentioned above will output all the options and libraries needed to link dynamically against the shared version of the Allegro library. If you use --libs instead of --shared or --static, the script will generate the linking arguments according to the latest installed library version. You can also run these allegro-config commands on the commandline to see what exactly they do. If you want to build a debug version of your program, assuming that you have installed the debug version of Allegro, use: gcc myfile.c -o myprogram `allegro-config --libs debug` Terminal newbies, take note that these are ` backticks, not normal ' quotes! There are also other switches for printing out the Allegro version number, or to override the install paths. Run allegro-config without any arguments for a full list of options. Don't forget that you need to use the END_OF_MAIN() macro right after your main() function! allegro4.4-4.4.2/docs/src/build/obsolete/qnx._tx000066400000000000000000000062541173507505700213710ustar00rootroot00000000000000@html_text_substitution=readme.txt|readme.txt @external-css=../allegro.css @document_title=Allegro QNX-specific information @
     ______   ___    ___
    /\  _  \ /\_ \  /\_ \
    \ \ \L\ \\//\ \ \//\ \      __     __   _ __   ___ 
     \ \  __ \ \ \ \  \ \ \   /'__`\ /'_ `\/\`'__\/ __`\
      \ \ \/\ \ \_\ \_ \_\ \_/\  __//\ \L\ \ \ \//\ \L\ \
       \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
	\/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
				       /\____/
				       \_/__/


		 QNX-specific information.

	 See readme.txt for a more general overview.
@
@heading QNX notes Status: it works. Only annoying bug left seems to be the display switching in fullscreen mode; just don't try to change workspace while in fullscreen or your program will crash... Also, video bitmaps and hardware acceleration are still not yet implemented. @heading Required software The library works with QNX 6.0 RTP. You need the development tools installed on your system; if you don't have them, you can get them from the QNX online repository using the Package Manager. @heading Installing Allegro As Allegro is a multiplatform library, you first need to set it up for use on QNX RTP, by running: chmod +x fix.sh ./fix.sh qnx Now you may want to generate the dependencies; this step is optional if you are using an official release, but it is required if you got a SVN snapshot of the library. make depend Then you need to build Allegro: make And finally install it (you need to be root for this): su -c "make install" Installing the library will copy the header files to /usr/include, the library file to /usr/lib and the allegro-config script into /usr/bin. @heading Using Allegro Linking with Allegro requires you to link also other libraries to your executables. To avoid you having to work out the right linker commands for yourself, the installation creates a script, allegro-config, that will print out a suitable commandline. You can use this inside a backtick command substitution, for example: gcc myfile.c -o myprogram `allegro-config --libs` Or if you want to build a debug version of your program, assuming that you have installed the debug version of Allegro: gcc myfile.c -o myprogram `allegro-config --libs debug` Unix newbies, take note that these are ` backticks, not normal ' quotes! There are also switches for printing out the Allegro version number and overriding the install paths. Run allegro-config without any arguments for a full list of options. Don't forget that you need to use the END_OF_MAIN() macro right after your main() function! @heading Final notes Allegro for QNX requires you to be running the Photon MicroGUI environment; if Photon cannot be found, the library will fail to initialize. If this happens, you're probably in a text console; just run "ph" to start Photon. allegro4.4-4.4.2/docs/src/build/obsolete/targets._tx000066400000000000000000000233561173507505700222360ustar00rootroot00000000000000@# @# This is the source for the Makefile targets, in a weird custom @# format. Read makedoc.c for a description of what is going on... @# @external-css=allegro.css @document_title=Makefile targets

Makefile targets


@text 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.
  • UNIX_TOOLS=1
    Instructs the build process to use Unix-like tools instead of DOS tools. Note that you usually don't need to set it because the build process will try to autodetect this configuration.
  • COMPILER_MSVC7=1 (MSVC only)
    Enables special optimizations for MSVC 7 (the default is MSVC 6). You don't normally need to set this flag since fix.bat msvc7 should do the same thing and is the preferred way of doing this.
  • COMPILER_ICL=1 (MSVC only)
    Instructs the build process to use the Intel command line compiler icl rather than Microsoft's command line compiler cl. You don't normally need to pass this flag since fix.bat icl should do the same thing and is the preferred way of doing this. Do not try COMPILER_MSVC7=1 and COMPILER_ICL=1 at the same time.
Here is the list of options which enable building of the specific addon library:
  • WITH_ALLEGRO_GL=1 (MSVC, DJGPP, MinGW, DMC, MacOS X)
    Enables building of AllegroGL addon library.
  • WITH_LOADPNG=1 (DJGPP, MinGW, MSVC, MacOS X)
    Enables building of loadpng addon library.
  • WITH_JPGALLEG=1 (BeOS, MSVC, DJGPP, MinGW, MacOS X)
    Enables building of JPGalleg addon library.
  • WITH_LOGG=1 (MinGW, MSVC, MacOS X)
    Enables building of logg addon library.
  • WITH_ALL_ADDONS=1 Shortcut to enable all above addons.
If you only want to recompile a specific test program or utility, you can specify it as an argument to make, eg. "make shooter" 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 PostScript file from the previously generated DVI file. This is not a default target, since you need the texi2dvi and dvips tools to create it. The second and third targets compress the generated Postscript file. The generated file is especially prepared to be printed on paper.
  • '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.
allegro4.4-4.4.2/docs/src/build/obsolete/watcom._tx000066400000000000000000000077221173507505700220560ustar00rootroot00000000000000@html_text_substitution=readme.txt|readme.txt @html_text_substitution=docs/build/djgpp.txt|docs/build/djgpp.txt @external-css=../allegro.css @document_title=Allegro Watcom-specific information @
     ______   ___    ___
    /\  _  \ /\_ \  /\_ \
    \ \ \L\ \\//\ \ \//\ \      __     __   _ __   ___ 
     \ \  __ \ \ \ \  \ \ \   /'__`\ /'_ `\/\`'__\/ __`\
      \ \ \/\ \ \_\ \_ \_\ \_/\  __//\ \L\ \ \ \//\ \L\ \
       \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
	\/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
				       /\____/
				       \_/__/


		Watcom-specific information.

	 See readme.txt for a more general overview.
@
@heading Watcom notes Status: complete and fully functional, but not so widely used and tested as the djgpp code. This version is heavily based on the djgpp version, basically just emulating whatever parts of the djgpp libc aren't provided by Watcom. See docs/build/djgpp.txt for information about the available hardware drivers: the djgpp and Watcom versions are 100% identical in this respect. This library works with version 10.6 and the various 11.0 versions of the Watcom C compiler, as well as with Open Watcom 1.0 or later. @heading Required software
  • Watcom C version 10.6 or 11.0x, or Open Watcom 1.0 or later.
  • djgpp compiler (djdev*.zip, gcc*b.zip, and bnu*b.zip).
  • GNU make (mak*b.zip).
  • GNU sed (sed*b.zip): Required for 10.6: Used to build asm sources. Optional for other versions: Used by "make depend".
Except for the Watcom compiler itself, all of the above packages can be downloaded from your nearest SimTel mirror site, in the /pub/simtelnet/gnu/djgpp/ directory, or you can use the zip picker on http://www.delorie.com/djgpp/. See the djgpp readme.1st file for information about how to install djgpp. @heading Installing Allegro This is a source-only distribution, so you will have to compile Allegro before you can use it. To do this you should: Type "cd allegro", followed by "fix.bat watcom", followed by "make". Then go do something interesting while everything compiles. When it finishes compiling, type "make install" to set the library up ready for use. The makefile will try to guess whether you are using Watcom 10.6 or 11.0 by checking for the presence of wdisasm.exe. If it gets this wrong, you may need to override it by passing WATCOM_VERSION=10.6 or WATCOM_VERSION=11 as arguments to make, or setting the WATCOM_VERSION environment variable. If you also want to install a debugging version of the library (highly recommended), now type "make install DEBUGMODE=1". Case is important, so it must be DEBUGMODE, not debugmode! If you also want to install a profiling version of the library, now type "make install PROFILEMODE=1". If your copy of Allegro doesn't include the makefile.dep dependency files (unlikely, unless you have run "make veryclean" at some point), you can regenerate them by running "make depend". @heading Using Allegro All the Allegro functions, variables, and data structures are defined in allegro.h. You should include this in your programs, and link with either the optimised library alleg.lib, the debugging library alld.lib, or the profiling library allp.lib. Programs that use Allegro must be compiled to use the stack based calling convention (wcl386 option '-5s'), and with stack overflow checks disabled (wcl386 option '-s'). You will also have to increase the stack size from the miserly Watcom default, using a wcl386 option like '-k128k', or a linker command like 'option stack=128k'. allegro4.4-4.4.2/docs/src/build/unix._tx000066400000000000000000000240711173507505700177270ustar00rootroot00000000000000@html_text_substitution=readme.txt|readme.txt @html_text_substitution=docs/build/linux.txt|docs/build/linux.txt @html_text_substitution=abi.txt|abi.txt @html_text_substitution=Allegro manual|Allegro manual @external-css=../allegro.css @document_title=Allegro Unix-specific information @
     ______   ___    ___
    /\  _  \ /\_ \  /\_ \
    \ \ \L\ \\//\ \ \//\ \      __     __   _ __   ___ 
     \ \  __ \ \ \ \  \ \ \   /'__`\ /'_ `\/\`'__\/ __`\
      \ \ \/\ \ \_\ \_ \_\ \_/\  __//\ \L\ \ \ \//\ \L\ \
       \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
	\/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
				       /\____/
				       \_/__/


		 Unix-specific information.

	 See readme.txt for a more general overview.

   Also see docs/build/linux.txt for Linux-specific information.
@
@heading Unix notes On Linux you have two different system drivers -- one for running using X, and one for running without X. This file describes the X version, which should be portable to any Unix variant. For information about the Linux-specific console routines, see docs/build/linux.txt. Only the X version is installed by default. @heading Required software Chances are that you already have all the necessary development tools, at least for compiling and installing the library. You will need CMake 2.6 or above. Most distributions should include it now, otherwise you will need to install it yourself. @heading Installing Allegro Please follow the generic instructions in docs/build/cmake.txt. @heading Shared files Installing Allegro will copy the library and header files plus other support files. These are:
  • allegro-config: Script that outputs the correct compiler and linker flags for your system in order to compile Allegro. This is copied into a `.../bin' path.
  • pkg-config files. These are alternatives to the allegro-config script.
On the other hand, there are files which you, as system administrator, are required to installed manually. These are:
  • language.dat: Contains translations for text strings used by Allegro. If this file is not available, Allegro runtime messages will only speak English. Recommended location is `/usr[/local]/share/allegro'.
  • allegro.info: Allegro documentation in Info format, viewable with GNU's info viewer. This is copied into the `info' path of your system.
  • allegro.cfg: Contains configuration settings for your system when the hardware autodetection fails. You can either copy this file and edit the contents manually or you can use Allegro's setup configuration program (in the `setup' directory) to create this file. Recommended location is `[/usr/local]/etc/allegro.cfg'.
You can find more information about some of these files and other suggestions in the chapter "Unix specifics" of the main Allegro manual. @heading Using Allegro The options for linking with Allegro are quite complicated, since for static versions of the library, depending on how it was configured, it may need to pull in other libraries (X, SVGAlib), as well as just Allegro itself. To avoid you having to work out the right linker commands for yourself, the installation creates a script, allegro-config, that will print out a suitable command line. You can use this inside a backtick command substitution, for example: gcc myfile.c -o myprogram `allegro-config --libs` Or if you want to build a debug version of your program, assuming that you have installed the debug version of Allegro: gcc myfile.c -o myprogram `allegro-config --libs debug` Unix newbies, take note that these are ` backticks, not normal ' quotes! There are also switches for printing out the Allegro version number, overriding the install paths, and selecting between shared and static libraries, in case you installed both. Run allegro-config without any arguments for a full list of options. You can also use pkg-config instead, for example: gcc myfile.c -o myprogram `pkg-config --libs allegro loadpng` As shown, there are pkg-config files for the bundled addons as well. Don't forget that you need to use the END_OF_MAIN() macro right after your main() function! @heading Setting an X11 icon You can set the X11 icon for your application to use. To do this, you need to include the icon in .xpm format and then point the symbol allegro_icon to the .xpm data before calling set_gfx_mode(). Alternatively, you can use the xfixicon.sh shellscript to produce a C file that will do this for you automatically when you link it with your project. No other steps are required. The xfixicon.sh utility will also accept bitmaps that are not in .xpm format, interpreting magic pink as transparent. You will need to have the ImageMagick tools installed for this to work. @heading What if you're not root? Allegro can be installed on a system where you don't have root privileges. Using the standard configure script option `--prefix' you can change the target directories for installation -- for example, you can write: cmake -DCMAKE_INSTALL_PREFIX=$HOME .. Then binaries will be installed to the `bin' subdirectory of your home directory, libraries to `lib', etc. Now you need to set up your system so that it knows where to find a few things, if this has not been done already. You might want to add these commands to your .bash_profile or similar startup script. If you use a csh-style shell, you want to use `setenv', not `export'. Your PATH must include the `bin' directory: export PATH=$PATH:$HOME/bin If you are using Allegro as a shared library, you need to tell the dynamic loader where to find the Allegro libraries: export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$HOME/lib GCC needs to know where to find header and library files: export C_INCLUDE_PATH=$C_INCLUDE_PATH:$HOME/include export CPLUS_INCLUDE_PATH=$CPLUS_INCLUDE_PATH:$HOME/include export LIBRARY_PATH=$LIBRARY_PATH:$HOME/lib Note: in fact `allegro-config' can handle the last step for you, if you use it for compilation as well as linking: gcc -c mygame.c `allegro-config --cflags` gcc -o mygame mygame.o `allegro-config --libs` But, it's better to set the environment variables too. Most people don't tend to bother with `allegro-config' when compiling. Alternatively, you can get the required environment changes from allegro-config, by typing at a shell prompt: allegro-config --env You can catenate the output to your .bash_profile, which is pretty much like adding all of the above commands. Note that `allegro-config' itself is in the `bin' directory of the installation, so either make sure that directory is in your path before running `allegro-config' or specify the path exactly, for example: ~/bin/allegro-config --env >> ~/.bash_profile @heading Notes on drivers
System:
On initialisation, Allegro will try to connect to an X server. If it can't find one, it will give up and try to use some different system driver instead (such as the Linux console driver, if it is enabled). This means that to run it in X mode, you must either launch your programs from inside an X session, or have set the DISPLAY environment variable to indicate what server you would like to use.
Graphics:
There are two different X graphics drivers: GFX_XWINDOWS uses only standard X calls, while GFX_XDGA2 uses the XFree86 DGA 2.0 extension (shipped with XFree86 4.0.x) which allows it to write directly to the screen surface, and use hardware acceleration if available. It is normally much faster than the standard X mode, but requires root permissions and will not work remotely. Note that DGA2 is deprecated now. If your program requests a different color depth to the current X display, Allegro will emulate the depth you asked for, so that your program will still work, albeit more slowly than if the color depths were identical. To find out whether this emulation is taking place, look at the gfx_driver->desc field (which is displayed in the middle of the screen by the tests/test program). If this says "matching", the color formats are identical, so no conversions are required. If it says "fast", some simple conversions are taking place, but nothing too painful. If it says "slow", you are in trouble :-) This is not valid for the DGA 2.0 driver, as it'll always change the video mode to the specified resolution and color depth.
@heading Irix Notes If the Irix compiler spits strange lines such as the following when compiling your Allegro program: include/allegro/alcompat.h:59: conflicting types for `ceilf' /usr/include/math.h:311: previous declaration of `ceilf' include/allegro/alcompat.h:60: conflicting types for `floorf' /usr/include/math.h:333: previous declaration of `floorf' include/allegro/alcompat.h:63: conflicting types for `tanf' /usr/include/math.h:176: previous declaration of `tanf' include/allegro/alcompat.h:64: conflicting types for `acosf' /usr/include/math.h:106: previous declaration of `acosf' include/allegro/alcompat.h:65: conflicting types for `asinf' /usr/include/math.h:116: previous declaration of `asinf' then you should #define ALLEGRO_NO_FIX_ALIASES prior to the #include <allegro.h> line. allegro4.4-4.4.2/docs/src/changes._tx000066400000000000000000006564431173507505700172730ustar00rootroot00000000000000@# @# This is the source for the recent changes list, in a weird custom format. @# Read makedoc.c for a description of what is going on... @# @html_text_substitution=readme.txt|readme.txt @external-css=allegro.css @document_title=Allegro Changes @html_spaced_list_bullet @heading Changes from 4.4.1.1 to 4.4.2 (May 2011)
  • Make rest(0) call select() with non-zero timeout on Unix. The old implementation was no longer enough to make input responsive on X11, on programs which try to draw as fast as possible. (Peter Wang)
  • Fix module loading on Unix (Bernhard Rosenkraenzer).
  • Made memory bitmaps returned by create_system_bitmap not marked as system bitmaps (Edgar Reynaldo).
  • Add detection of Windows 7 (Andrei Ellman).
  • Fail instead of crashing if gfx_directx_make_bitmap_from_surface() fails (Andrei Ellman).
  • Fix crash in GDI driver if setting a second mode fails, after having successfully set a mode previously (Andrei Ellman).
  • Add missing frameworks required for static linking on OS X (Peter Johansson).
  • Fixed a problem with keyboard focus being lost on OS X when switching from windowed mode to fullscreen mode (Peter Johansson).
  • alsa_rawmidi_init could return success on failure (Nicolas Kaiser).
  • Updated PSP port from diedel. "The graphics, system, digi, keyboard, mouse, joystick and timer drivers are implemented and are fully functional. It supports 8, 15, 16 and 32 bpp color depths and a max. resolution of 480x272 pixels."
  • Eliminated the need for old DirectX headers for the Windows port (David Capello).
  • Fix problems in Windows when you use Alt-Tab. Sometimes the Alt modifier is kept pressed when you focus the Allegro window. (David Capello)
  • Make the submenu appear to the right of its parent menu if it does not fit in the screen (Paul Suntsov).
  • Made timers on Unix cope with system time being set backwards (Hardi Stengelin).
  • Fix various compilation and build problems (scottmc, Cristian Morales Vega, Tony Ylisirniö, Edgar Reynaldo).
  • Added WANT_OSS, WANT_ALSA, WANT_JACK, WANT_SGIAUDIO options (Samuli Suominen).
  • Also pass -pg when building shared library in PROFILE mode.
  • Let demos find readme.txt and source files correctly even if running from a build directory (Peter Wang).
@heading Changes from 4.4.1 to 4.4.1.1 (March 2010)
  • Fix a silly build system problem with MinGW on Windows.
  • Update loadpng code to not use a deprecated interface (as of libpng 1.4).
@heading Changes from 4.4.0.1 to 4.4.1 (March 2010)
  • Allow Linux joystick driver to be used with the X11 port without enabling the Linux console port.
  • Avoid problem compiling joystick driver on some Linux systems.
  • Install DLLs into bin directories on Windows.
  • A few build improvements for MinGW cross-compiler.
@heading Changes from 4.4.0 to 4.4.0.1 (December 2009)
  • Chris Roberts updated CMake build for BeOS/Haiku.
  • Some AllegroGL header files were not being installed.
  • Fix a build problem with CMake 2.6.2+ on Mac OS X.
@heading Changes from 4.4.0 RC2 to 4.4.0 (December 2009)
  • Fix an integer overflow problem with polygon3d().
  • Work around DSCAPS_PRIMARY16BIT capability flag not being set in DirectAudio driver.
  • Avoid a potential divide-by-zero in non-FM synth case in OSS MIDI driver.
  • Name DLL as alleg44.dll not alleg.dll.
  • Various minor changes to build system and example programs.
@heading Changes from 4.4.0 RC1 to 4.4.0 RC2 (November 2009)
  • Peter Wang replaced the old build system with a new one using CMake. Please see docs/build/cmake.txt.
  • Peter Wang disabled the Linux console port by default. Most people use X11 exclusively now.
  • Peter Wang made the build system install pkg-config .pc files on Unix-like systems.
  • Trent Gamblin added _trans and _lit versions of all rotate_* and pivot_* functions. New example: exrotscl.
  • Francis Devereux made it possible for keyboard events to go to other windows when the Allegro window does not have focus, on Mac OS X.
  • Fixed various compilation issues.
@heading Changes from 4.3.10 to 4.4.0 RC1 (April 2009)
  • Christer Sandberg fixed a crash when omitting the end of the glyph interval in the text file for load_txt_font().
  • Peter De Wachter made the ALSA driver work for hardware which does not support unsigned samples.
  • Milan Mimica fixed display switching on linux console driver.
  • Milan Mimica fixed various glitches related to the build system in the core library and addons.
  • Milan Mimica added support for MSVC6/7/8/9 to logg and loadpng.
  • David Capello fixed the BMP loader to handle (valid) .bmp files with negative heights and other uncommon features.
  • Peter Hull added Mac OS X (non-universal) build support for loadpng and logg.
  • Peter Wang made configure and fix.sh scripts more robust.
  • Paul Suntsov made a replacement function for do_ellipse() which produces accurate ellipses and much more rapidly.
  • Milan Mimica added supprot for macosx-universal binary to addons.
  • Elias Zacarias added a function that allows users to intercept window events on Windows.
  • Scott McCreary and Grzegorz Dabrowski made the BeOS port compile on Haiku.
  • diedel started a Playstation Portable port. (Alpha status)
  • Edgar Reynaldo provided mouse_on_screen() function.
  • Edgar Reynaldo added functions that can be used to determine the graphics mode type of arbitrary graphics drivers at runtime.
  • Edgar Reynaldo improved the behavior of the file_select_ex* functions.
  • Various minor improvements and fixes.
@heading Changes from 4.2.2 to 4.3.10 (January 2008)
  • Milan Mimica integrated the following addons into the Allegro build system: AllegroGL, loadpng, JPGalleg, logg. Not all addons currently build on all platforms, but Unix and MinGW are supported by all.
  • Milan Mimica disabled support for asm mode on all platforms. This was previously the default for non-x86 architectures.
  • Jon Rafkind and Milan Mimica implemented draw_sprite_ex() function and added an extrans2 example.
  • Milan Mimica integrated the "skater" demo game and renamed the classic demo to "shooter". The skater demo was written by Miran Amon, Nick Davies, Elias Pschernig, Thomas Harte & Jakub Wasilewski.
  • AJ added detection for SSE3, SSE4.1 and SSE4.2
  • Matthew Leverton fixed a problem with filename encoding and the SYSTEM_NONE driver on Windows.
  • 8L45T3R fixed a bug in arc() function, where small arcs would be drawn as circles.
  • David A. Capello fixed a problem on Windows where the NumLock, ScrollLock and CapsLock flags are not registered in the key_shifts flag until at least one key is pressed.
  • Christer Sandberg fixed a memory leak where datedit_exit would not free datafile properties. (bug #1808894)
  • Robert Riebisch fixed warnings from gcc 4.x about unnecessary 'packed' attributes being ignored on some data structures in the VESA and VBE/AF drivers. (bug #1729552)
  • Matthew Leverton renamed MID() to CLAMP() and introduced a new MID() that returns the median of x,y,z for all cases.
  • Various minor improvements.
@heading Changes from 4.2.3 to 4.2.3.1 (October 2009)
  • Francis Devereux made the OS X port compile on Mac OS X 10.6.
@heading Changes from 4.2.2 to 4.2.3 (October 2009)
  • Fix fnstsw compile bug with newer binutils.
  • Trent Gamblin made a small change to the Windows mouse driver to add support for touchscreens (at least 1 of them).
  • Peter De Wachter made the ALSA driver work for hardware which does not support unsigned samples.
  • Matthew Leverton fixed a problem with filename encoding and the SYSTEM_NONE driver. Added set_filename_encoding(), get_filename_encoding().
  • Milan Mimica made the MinGW and MSVC makefiles add the suffix "_c" onto non-asm builds, and clarified that user programs linking against the non-asm libraries must also defined ALLEGRO_USE_C. Mixing calling conventions causes segfaults when functions are inlined.
  • AJ added detection for SSSE3, SSE4.1 and SSE4.2
  • David A. Capello made key_shifts work properly on Windows for Control, Alt, and Shift.
  • Clarified that set_config_file() does not search for the given config file in other locations, as Allegro does with allegro.cfg at initialization.
  • Fixed buffer overflow in exgui.
  • Fixed problems with newer versions of autoconf.
@heading Changes from 4.2.2 RC1 to 4.2.2 (July 2007)
  • Matthew Leverton added build instructions for DMC and updated the MSVC project files and instructions.
  • Matthew Leverton added a shell script wrapper around gcc to build universal binaries (i386 + PPC) on Mac OS X and made the Allegro makefile use it.
  • Peter Hull reenabled the Quit menu option on Mac OS X when set_close_button_callback is used.
  • Rikard Peterson fixed the Mac OS X joystick driver so that HID_ELEMENT_STANDALONE_AXIS axes correctly got the flag JOYFLAG_UNSIGNED and not JOYFLAG_DIGITAL.
  • Matthew Leverton fixed a problem with the GDI driver blitting a rectangle smaller than the bitmap's height that touches the bottom left corner of a bitmap.
  • Some minor changes.
@heading Changes from 4.2.1 to 4.2.2 RC1 (July 2007)
  • Matthew Leverton added project files for MSVC 6/7/8 (see the build directory and Allegro Wiki for instructions).
  • Matthew Leverton added initial support for the Digital Mars C compiler (for the Windows port). It only works with the C-only port and obj\dmc\plugins.h needs to be built by hand.
  • Peter Wang cleaned up most of the autoconf namespace pollution.
  • Matthew Smith made a fix for C locking code in GDI.
  • Trent Gamblin made the fullscreen DirectX driver save and restore the palette when switching away and back in 8-bit video modes.
  • Elias Pschernig added missing documentation for pack_ungetc().
  • Trent Gamblin fixed the C version of stretch_blit so it now draws correctly. He also made it about 20% faster along the way.
  • orz and Matthew Leverton made the ALLEGRO_USE_C=1 option to work under MinGW and MSVC.
  • Erno Schwetter fixed a long-standing bug in polygon() where the bottom-most pixels would not be drawn.
  • Anthony 'Timorg' Cassidy made d_menu_proc fill up its assigned area with the gui_bg_color.
  • Phil Krylov fixed a bug that prevented load_bios_font() from loading 8x16 fonts.
  • Etienne Vouga fixed a bug with the reset_controllers MIDI command.
  • Milan Mimica fixed a double SWITCH_IN event callback bug when de-minimizing an Allegro program in Windows.
  • Erno Schwetter fixed a bug where __al_linux_console_fd was used in display_switch_lock() without the console being initialized first.
  • Erno Schwetter fixed an unbalanced __al_linux_console_graphics() call.
  • Ryan Patterson fixed a crash in free_config_entries.
  • Elias Pschernig added support for horizontal wheel mice (so far, only the X11 driver reports any horizontal wheel movement though). Also increased the number of supported mouse buttons from 3 to 5 for the X11 driver.
  • Jon Rafkind and Karthik Kumar fixed a problem where allegro-config would respect neither --libdir nor --includedir.
  • Peter Wang fixed some problems with the ALSA MIDI driver in the case of failure.
  • torhu fixed a bug in akaitest where an array was indexed with -1.
  • Trent Gamblin implemented set_mouse_speed under X11. Peter Wang made setting stick only while the cursor is in the Allegro window.
  • Evert Glebbeek added desktop_color_depth and get_desktop_resolution to the Linux fbcon driver.
  • Matthew Leverton fixed building of universal binaries on MacOS X. This currently requires OS X 10.4 on both PPC and Intel.
  • Milan Miminca made the fbcon driver initialization fail if an unsupported color depth was set.
  • Michal Molhanec and Milan Mimica simplified the MSVC build process and updated the documentation.
  • Andrei Ellman made the MSVC makefile compatible with cygwin port of make-3.81 (and newer?). makefile.vc now uses cygpath tool to convert DOS 8.3 paths to unix-style paths.
  • Daniel Schlyder added a functions is_trans_font, font_has_alpha.
  • Daniel Schlyder made load_txt_font() additionally search for files referenced in the font script in the same directory as the script itself. It still searches in the current working directory first (for relative paths).
  • Daniel Schlyder documented that register_assert_handler() and register_trace_handler() can be called before initialising Allegro.
  • Daniel Schlyder prevented the Windows port from registering its default trace handler on initialisation if the user had previously registered a custom trace handler.
  • Andrei Ellman modified the 6-to-8 bit value scaling tables to be more evenly distributed, and changed the implementation of create_blender_table() to create a more evenly distributed distribution of the lower 2 bits. It should be faster as well.
  • Other minor bug fixes and documentation updates.
@heading Changes from 4.2.1 RC1 to 4.2.1 (November 2006)
  • Peter Wang made the Unix ports query the memory page size with sysconf() when necessary, instead of using the PAGE_SIZE constant, which seems to be Linux-specific.
  • Matthew Leverton gave the STATICRUNTIME builds of MSVC new names by appending _crt (c run time) to the libraries. He also fixed the problem of incorrectly setting the EMBED_MANIFEST variable when using the STATICRUNTIME.
  • Andrei Ellman fixed an inverted test in pack_fopen_chunk on Windows.
  • Peter Hull made 32-bit icon generation by fixbundle endian-independent (colours were incorrect on Intel Macs).
  • Peter Wang fixed a long standing bug where some compressed packfiles would not be read back properly (premature EOF). Reported by jman2050.
  • Andrei Ellman spotted a free() of an internal buffer returned by tmpnam().
  • Peter Hull fixed a problem with mouse-related deadlock on MacOS X as reported by Mike Farrell.
  • Peter Hull implemented simulation of video bitmaps on MacOS X, so that page flipping will work.
  • Peter Hull fixed an endian problem in the digital sound driver on MacOS X.
  • Elias Pschernig and Chris Robinson fixed problems with UTF-8 filenames under Unix, as reported by Grzegorz. Non-ASCII non-UTF-8 filenames remain broken.
  • Chris Robinson fixed some problems with non-ASCII filenames under Windows.
  • Elias Pschernig made the X11 driver call XInitThreads, to make Mesa-OpenGL work together with Allegro. It can be disabled at runtime through a config variable.
  • Andrei Ellman fixed a bug in datedit.c that could crash the grabber.
  • Elias Pschernig added file_size_ex(), which returns a 64 bit integer to handle large files.
  • Ron Novy made improvements to the test program.
  • Peter Hull fixed problems with set_mouse_sprite() on Intel Macs.
  • Peter Hull added universal binary support to the MacOS X port.
  • Peter Wang and Evert Glebbeek independently fixed a problem with dependency generation for MacOS X on non-Mac systems.
  • Many smaller fixes and updates by Peter Hull, Elias Pschernig, Peter Wang and Milan Mimica.
@heading Changes from 4.2.0 to 4.2.1 RC1 (May 2006)
  • Michal Molhanec made msvchelp.exe work on Cygwin, where there was a problem with the case-insensitivity of environment variables. Reported by Milan Mimica.
  • Peter Hull fixed a bug where Allegro detected keypresses on KEY_MINUS_PAD as KEY_PLUS_PAD.
  • Peter Hull made OSX work correctly with Logitech sticks, as discussed with Ultio.
  • Milan Mimica fixed some spin loops in the test program.
  • Chris Robinson added UTF8/Unicode support for filenames in Windows.
  • Milan Mimica made the Linux console driver more robust: set_gfx_mode used to get stuck in a infinite loop when there wasn't a console available.
  • Evert Glebbeek made the C blitter use memmove for normal blits, with a bugfix by Milan Mimica. This can be disabled by removing a #define USE_MEMMOVE at the top of cblit.h so that it can easliy be tested against the older versions of the code.
  • Christer Sandberg worked around a problem where one-line high bitmaps would crash with Electric Fence.
  • Chris Robinson fixed a crash that occurred if the sound mixer quality level was set to 0 after the mixer was already initialised.
  • Evert Glebbeek fixed the window title under X11, which was broken by a previous change.
  • Peter Hull updated the endian detection under OSX as recommended by Apple.
  • Miguel A. Gavidia and Jay Bernardo made qtmidi.m work on both PPC and Intel.
  • Milan Mimica fixed a crash when vsync() on certain drivers.
  • Elias Pschernig replaced the ALLEGRO_USE_C define with ALLEGRO_NO_ASM.
  • Peter Wang restored the JACK driver to compiling state.
  • Milan Mimica made the new transparent fonts be recognized as color fonts with is_color_font.
  • Elias Pschernig made the modules path WIP version specific, for enhanced binary compatibility.
  • Stijn Wolters clarified the documentation of init_dialog.
  • Hans de Goede fixed a problem with dynamically generated stretcher code not being properly marked as executable on Linux (esp. SELinux).
  • Hans de Goede fixed a busy wait in the X11 vsync simulation.
  • Elias Pschernig makde it so modules under Unix are now searched in libdir as passed by the build machinery. Closes bug #1401840 from SF, reported by Paul Eipper.
  • Milan Mimica added a get_volume and a get_hardware_volume function, to work as pendants to set_volume and set_hardware_volume.
  • Milan Mimica corrected a case where a wrong structure on the stack was being cleared in the DirectSound input driver.
  • Hans de Goede added a fullscreen driver for X11 which does not need XVidMode extension, and instead simply centers the window on the desktop and draws a black border around.
  • Hans de Goede fixed a problem where switching to fullscreen mode under X11.
  • Serge Semashko added Enter as a fire key in the demo game.
  • Serge Semashko added fixed problems with Allegro working on Nokia 770.
  • Peter Wang fixed some problems with binary compatibility checking in the 4.2 branch.
  • Catatonic Porpoise added OpenBSD detection (in addition to FreeBSD and NetBSD) and fixed an issue with executable rights not set on the memory for the i386 stretcher on UNIX systems.
  • Hans de Goede fixed a bug preventing the ALSA driver to work on big endian systems.
  • Elias Pschernig and Chris Robinson fixed binary compatibility checking in allegro_init and install_allegro.
  • Catatonic Porpoise fixed the example in the documentation of stretch_sprite.
  • Hans de Goede made DIGMID work with absolute paths in the patches.cfg file.
  • Peter Hull added code to make Allegro work better with user-supplied Nibs under OSX, as discussed with Thomas Harte.
  • Matthew Leverton added embedding of manifests to the MSVC 8 build process.
  • Neil Walker and Thomas Harte implemented a hardware accelerated stretch_blit() for the Windows DX port.
  • Evert Glebbeek corrected a bug when destroying sub-bitmaps under Windows.
  • Evert Glebbeek fixed a bug in pack_fopen_chunk() where a temporary file would be created in a non-writable location.
  • Peter Wang changed a "/lib" option to MSVC's link utility to "-lib" as reported to be problematic by Karthik Kumar.
  • Peter Wang fixed a crash in dat and grabber due to the return value of pack_fopen_chunk() not being checked.
  • Elias Pschernig added support for anti-aliased bitmap fonts.
  • Dennis Busch fixed the short description of add_clip_rect.
  • Thomas Harte and Neil Walker fixed a problem with draw_sprite() and sub-bitmaps.
  • Peter Wang fixed scancode_to_name(KEY_NUMLOCK) returning "PAUSE" in Windows.
  • Peter Wang fixed page flipping and triple buffering in the demo game.
  • Elias Pschernig added list_config_sections and list_config_entries functions.
  • Hrvoje Ban added create_datafile_index and load_datafile_object_indexed functions.
  • Peter Hull allowed use of "mingw" instead of "mingw32" in fix.bat and fix.sh.
  • Peter Wang fixed a bug with SWITCH_BACKAMNESIA mode with the fbcon graphics driver.
  • Peter Wang made the svgalib driver save and restore the palette on VT switches.
  • Peter Wang fixed a problem with the fbcon driver and VT switching.
  • Milan Mimica delayed Linux console initialisation until it is required. This way the user can write command-line programs using timers without needing a real console.
  • Chris Jones fixed behavior of numeric keys when NumLock is on.
  • Vincent Penecherc'h worked around a problem with 24-bit bitmaps in the assembler code.
  • Tobias Dammers fixed a problem with the DirectSound input driver.
  • Matthew Leverton fixed Ctrl-Alt-Del mistakenly being captured by Allegro under Windows
  • Vincent Penecherc'h improved the implementation of set_ramp_cmap in the fbcon driver.
  • Vincent Penecherc'h implemented get_refresh_rate for the fbcon driver.
  • Vincent Penecherc'h fixed problems with the fbcon driver not restoring the original video mode when the driver exits.
  • Victor Williams Stafusa da Silva made OS type detection handle Windows 2003 and Windows Vista.
  • Chris Jones and Vincent Penecherc'h fixed load_wav to handle degenerate stereo wave files with an odd length.
  • Annie Testes fixed all sorts of problems with the linux evdev mouse driver when using a tablet as the mouse.
  • Annie Testes made the linux evdev mouse driver use the correct device files.
  • Vincent Penecherc'h made the linux fbcon driver set a ramp colourmap for directcolor modes, otherwise colours in those modes were all wrong.
  • Vincent Penecherc'h fixed a problem with the linux fbcon driver, where it would keep using the old pitch after changing resolutions.
  • Serge Semashko fixed a typo causing crashs in _linear_draw_trans_rgba_rle_sprite24.
  • Annie Testes fixed cursor speed and incorrect mickey computation bugs in the Linux evdev mouse driver.
  • Vincent Penecherc'h made the Linux PS/2 mouse driver try /dev/input/mice by default, in addition to /dev/mouse.
  • Warnings, code formatting and minor changes to code and build system by Milan Mimica, Evert Glebbeek, Elias Pschernig, Peter Wang, Peter Hull, Thomas Harte, Vincent Penecherc'h and Chris Robinson.
  • Documentation updates by Tore Halse, Elias Pschernig, Milan Mimica, Peter Wang, Physics Dave, Ryan Patterson, Grzegorz Adam Hankiewicz, Andrei Ellman and Evert Glebbeek.
@heading Changes from 4.2.0 RC2 to 4.2.0 (November 2005)
  • Peter Wang made fixmul() detect overflows as it used to do in the 4.0.x branch.
  • Peter Hull fixed a bug in the fixbundle utility.
  • Dennis Busch found a bug where d_clear_proc would not work properly if the GUI target bitmap is different from screen.
  • Grzegorz Adam Hankiewicz made Allegro log all TRACE output with a prefix in the format "al-system level: ". This makes it easier to grep debug logs.
  • Grzegorz Adam Hankiewicz made dialogs with MSG_CHAR/MSG_UCHAR handlers honor a D_CLOSE return flag without a D_USED_CHAR.
  • Peter Hull fixed problems with the mouse position as reported by Allegro and the mouse position as known to OS X.
  • Peter Hull made Command-Q not close the application if no exit-button callback is registered.
  • Peter Hull fixed problems with joysticks under MacOS X as reported by Thomas Harte.
  • Peter Hull fixed a bug preventing more than one Allegro application from being run at a time on Mac OS X. Reported by Thomas Harte.
  • Peter Hull did a lot of other things for the MacOS X port too.
  • Jiri Gabriel fixed loading of multiple ranges in a single bitmap with txt fonts.
  • Milan Mimica and Jiri Gabriel fixed several bugs in extract_font_range.
  • Dennis Busch fixed a Unicode bug in the mode selector.
  • Evert Glebbeek added FA_ALL and FA_NONE file attribute flags.
  • Peter Hull fixed a deadlock in OS X when calling vsync() while the screen was acquired.
  • Robert Alfonso fixed a grabber crash when importing a new font range into an existing font. Reported by Milan Mimica.
  • Chris Robinson fixed the fileselector in UNIXnot properly recognising filenames containing UTF-8 characters.
  • Hrvoje Ban and Peter Wang wrote a documentation section that explains several common mistakes.
  • Elias Pschernig disabled DGA auto-detection under X11
  • i_am_drv added support for .rmi midis to the midi reader
  • Elias Pschernig fixed a fix-point overflow in pivot_sprite.
  • Michal Molhanec fixed several problems with the Watcom compiler.
  • Peter Hull fixed an error with 'make uninstall' on MacOS X.
  • Matthew Leverton added a programs: makefile target.
  • Many small fixes and improvements by Michal Molhanec, Peter Hull, Chris Robinson, Peter Wang and Elias Pschernig.
  • Documentation improvements by Grzegorz Adam Hankiewicz, Tore Halse and Peter Hull.
@heading Changes from 4.2.0 RC1 to 4.2.0 RC2 (August 2005)
  • Grady Martin made the grabber consider deleting object properties as a change to the datafile.
  • Milan Mimica fixed numerous bugs in extract_font_range().
  • Peter Hull moved the 'magic chdir' in the MacOS X port to earlier in the startup process, so that the config file will be looked for in the resource directory if is present.
  • Chris Robinson made create_bitmap(0,0) not return a bitmap that would later crash destroy_bitmap(). Zero-sized bitmaps are still not allowed so the assertions for debug mode have not changed.
  • Elias Pschernig patched the Windows keyboard driver to get key_shifts working again with KB_SHIFT_FLAG, KB_CTRL_FLAG, KB_ALT_FLAG on Win98.
  • Peter Wang changed hline and vline into aliases for internal symbols to avoid a conflict with the curses API. This change should be transparent for users.
  • Matthew Leverton and Michal Molhanec updated the build system for MSVC 8.
  • Grzegorz Adam Hankiewicz prevented make_relative_filename() from crashing with malformed parameters.
  • Hrvoje Ban made ASSERT() actually abort in Windows.
  • Chris Robinson made GUI menus work with gui_screen.
  • Evert Glebbeek fixed reading of 32 bit Windows .bmp files, which was not supported. These files seem to be not very standard though, so it's unclear if it will always do the right thing. Alpha channels also seem not to be standard in 32 bit BMP files, so it's possible they're not read in correctly.
  • Peter Wang and Peter Hull updated the ABI compatibility document. This documents our policy for the 4.2.x series.
  • Extensive documentation updates from Grzegorz Adam Hankiewicz and minor updates due to Michael Faerber, Robert Ohannessian and Milan Mimica.
@heading Changes from 4.2.0 beta 4 to 4.2.0 RC1 (August 2005)
  • Peter Hull fixed the MacOS X port to avoid an issue with the dead bootstrap context and cleaned up the dock notification. This means command line apps (with SYSTEM_NONE) run without the dock being notified.
  • Peter Wang Added a COLORCONV_KEEP_ALPHA flag, as suggested by Gideon Weems.
  • Peter Wang fixed issues with OSS in OpenBSD and made the configure script print a warning if Allegro is compiled without X11 support.
  • Peter Hull set the compatibility version to 4.2.0 for MacOS X and added a MacOS X help file.
  • Peter Wang made the Mode-X and VBE/AF drivers fail if Allegro is compiled as a C-only library in Linux and made the Unix port install liballeg*.so and the alleg-*.so modules with the execute permission enabled.
  • Grady Martin standardised some of the grabber dialog boxes and added a `move' command to the grabber.
  • Evert Glebbeek fixed a bug when loading some old datafiles containing monochrome fonts.
  • Evert Glebbeek fixed a bug that prevented system cursors from working correctly in Windows.
  • Olivier Blin fixed compilation problems for the ModeX driver with newer binutils.
  • Shawn Walker fixed a bug in get_executable_name under some UNIX systems.
  • Shawn Walker worked around a problem with some versions of GNU AS and fixed some errors in the configure script when not using GCC.
  • Elias Pschernig made create_sample not unnecessarily clear the sample to 0.
  • Bobby Ferris fixed the makedoc SciTE API output.
  • Elias Pschernig fixed a too strict assert that prevented set_volume from working in debug mode.
  • Paavo Ahola helped fix a problem with BCC and the C implementations of fixmul.
  • Elias Pschernig fixed a cosmetic bug where the listbox was drawing a too big selection rectangle, reported by dthompson.
  • Documentation and example updates by Grzegorz Adam Hankiewicz, Peter Wang, Elias Pschernig Michal Molhanec and Evert Glebbeek.
@heading Changes from 4.2.0 beta 3 to 4.2.0 beta 4 (June 2005)
  • Matthew Leverton changed the default behavior of the grabber: default color depth is now the desktop, default mode is windowed and if fullscreen is specified, then desktop resolution is used by default.
  • Peter Wang fixed compilation problems related to get_modex_screen() on UNIX and deprecated it.
  • Robert Ohannessian fixed compilation problems for the assembler code with newer binutils.
  • Peter Wang, Thomas Harte and Evert Glebbeek optimised fixmul() for different platforms.
  • Robert Alfonso fixed a couple of warnings that with DJGPP.
  • Grzegorz Adam Hankiewicz made the FLIC player yield.
  • Miran Amon fixed an arbitrary limit in get_config_argv(). Evert Glebbeek fixed a memory leak in same.
  • Thomas Klausner fixed a problem in allegro.m4 and automake 1.8+.
  • Charles Wardlaw fixed some warnings with gcc 4 on MacOS X.
  • Elias Pschernig removed the `256 items' limit from the dat utility.
  • Julien Cugniere fixed a crash in the GUI if a new dialog was opened while a menu was still open.
  • Shawn Walker fixed crashes with the keyboard driver under Solaris.
  • Elias Pschernig split the demo game into multiple files and made the makefile handle a multi-file demo game.
  • Evert Glebbeek fixed a bug where the hardware mouse wasn't displayed in Windows until the mouse was moved.
  • J.P. Morris fixed rest_callback() under UNIX.
  • Shawn Walker and Evert Glebbeek fixed get_executable_name() under Solaris and OpenBSD.
  • Peter Hull fixed compilation problems with setAppleMenu under Tiger.
  • Peter Hull fixed a deadlock on MacOS X related to mouse updating.
  • Peter Wang fixed a problem with compiling the VBE/AF driver using newer binutils.
  • Evert Glebbeek fixed a bug with colour conversions when loading a font from a datafile.
  • Many code, example and documentation updates by Grzegorz Adam Hankiewicz, Elias Pschernig, Peter Wang, Evert Glebbeek, Andrei Ellman, Victor Williams Stafusa da Silva, Matthew Leverton, AJ, Michal Molhanec and Hrvoje Ban.
@heading Changes from 4.2.0 beta 2 to 4.2.0 beta 3 (May 2005)
  • Grzegorz Adam Hankiewicz did several documentation updates.
  • Evert Glebbeek cleaned up some of the global namespace pollution in the Windows port.
  • Chris Robinson made improvements to the Windows sound driver.
  • Chris Robinson made the GUI multi-selection box behave a bit nicer.
  • Grzegorz Adam Hankiewicz added a bunch of ASSERTs to the code to check for out-of-range arguments.
  • Jakub Wasilewski fixed a bug when loading greyscale TGA images.
  • Evert Glebbeek fixed a bug where the bottom and right line of pixels was not updated on show_video_bitmap, as pointed out by Thomas Harte.
  • Evert Glebbeek documented JOY_TYPE_* defines for Windows and Linux.
  • Dark Nation restored the ability to read old-style encrypted packfiles, i.e. those produced before Allegro 3.9.30. This was silently removed from 4.1.18 when custom packfile support / decoupled compression routines were added.
  • Evert Glebbeek made the grabber and dat utilities now use Allegro's builtin load_font() function and made datafiles properly store truecolour fonts and added a datedit_select() callback to datedit.
  • Evert Glebbeek fixed some unsafe assumptions on the size of integer data types.
  • Arthur Huillet fixed a typo in the docs.
  • Elias Pschernig restored Alt+key = ASCII code 0 behavior for the Windows keyboard driver
  • Evert Glebbeek fixed a bug that caused a crash when loading Allegro 1.x datafiles containing 4 bit bitmaps.
  • Peter Wang clarified the mode select documentation and made the mode selector clear the input variables before passing them on to the filter.
  • Peter Wang fixed a bug in the mode selector where disabled drivers were still shown with empty resolution lists. Pointed out by Hrvoje Ban.
  • Elias Pschernig fixed Allegro's internal multithreading in Windows. This fixes a deadlock on exit.
  • Robert Alfonso made the MSVC makefile call `link /lib' rather than `lib', which doesn't work for the free toolkit.
  • Peter Hull fixed a problem with hardware cursors not working properly in MacOS X.
  • Peter Hull added a missing enable_hardware_cursor vtable entry and added OS native cursors for the MacOS X port.
  • Grzegorz Adam Hankiewicz documented the online Allegro patch generator.
  • Evert Glebbeek renamed datafiles._tx -> datafile._tx
  • StApostol updated the FAQ to use rest(0) instead of the deprecated yield_timeslice().
  • Evert Glebbeek silenced some GCC4 warnings in MacOS X.
  • Peter Wang fixed warnings and errors with gcc 4.0.0 on the Unix port; reported by Milan Mimica.
  • Peter Wang added the preprocessor symbol ALLEGRO_NO_FIX_CLASS that the user can define to not pull in the `fix' class in C++ programs.
  • Peter Wang removed the exdodgy example.
  • Elias Pschernig fixed another X11 async reply bug.
  • Elias Pschernig made the seek in expackf test work with CR/LF line endings.
  • Evert Glebbeek fixed a small bug that prevented the Allegro template for Project Builder from installing correctly on MacOSX.
  • Elias Pschernig enabled warnings about unused variables with --enable-strictwarn in unix.
  • Peter Wang fixed a warning with Watcom 1.3.
@heading Changes from 4.2.0 beta 1 to 4.2.0 beta 2 (April 2005)
  • Daniel Schlyder fixed a problem with the makefile in Windows.
  • Evert Glebbeek fixed a bug that prevented true colour fonts from working.
  • Peter Wang fixed a possible deadlock in dialog_message.
  • Elias Pschernig fixed a bug where the DJGPP version would choke on a missing variable.
  • Peter Hull made makedoc return an error code if it failed to build the SciTE documentation.
  • Evert Glebbeek fixed a problem with incorrect dependencies being generated for MacOS X.
  • Tobi Vollebregt fixed a problem in X11 if the XRGBACursor extension was missing.
  • Evert Glebbeek made configure use k8 rather than athlon64 as a compiler switch on AMD64.
  • Peter Wang and Elias Pschernig added a packfile example.
  • Michal Molhanec fixed a problem in the MSVC makefile.
  • Evert Glebbeek removed void*-arithmetic from the colour converter.
  • Evert Glebbeek fixed a bug where hardware cursors would stop working.
  • Elias Pschernig, Andrew Chew fixed and Tobi Vollebregt fixed several problems with the Windows keyboard driver.
  • Elias Pschernig fixed bug in unix dependency generation.
  • Elias Pschernig made the GUI not mess up the hardware cursor.
  • Elias Pschernig removed pckeys.c and keyconf from the windows port, since the dinput driver no longer needs pckeys.c nor uses keyboard.dat.
  • Daniel Schlyder fixed a problem with the -mtune switch on older gcc based compilers.
  • Matthew Leverton figured out which versions of Watcom have inttypes.h and stdint.h.
  • V Karthik Kumar added a password to the Windows screensaver example.
  • Cosmetic fixes, example bugfixes and spelling corrections by Jon Rafkind, Evert Glebbeek, Peter Wang, StApostol and Elias Pschernig.
@heading Changes from 4.1.18 to 4.2.0 beta (March 2005)
  • Peter Wang fixed many problems on AMD64 in Linux - it should now work fine.
  • Peter Hull added CPU detection to the MacOS X port.
  • Peter Hull fixed some problems related to /usr/local/bin not existing in recent versions of MacOS X.
  • Elias Pschernig and Peter Wang rewrote the Windows keyboard driver so it no longer needs keyboard.dat.
  • Elias Pschernig added a show_os_cursor function as an alternative to show_mouse() for system cursors.
  • Evert Glebbeek and Peter Wang added an example programme for system cursors.
  • Elias Pschernig fixed a deadlocks in X11 related to scare_mouse() and keyboard repeats and fixed async replies.
  • Daniel Schlyder fixed the gcc -mcpu is deprecated warnings.
  • Peter Wang added an astdint.h, which provides C99 typedefs for pre-C99 compilers.
  • AJ added detection for DirectX 8 and 9 to the Windows port.
  • Evert Glebbeek added detection for AMD64 to the UNIX port and test programme.
  • Elias Pschernig added a get_midi_length function and a midi_time variable.
  • Elias Pschernig fixed a problem where Allegro would ignore a user-specified configuration file if set_config_file() was called before allegro_init().
  • Evert Glebbeek added a transpose_font function.
  • Evert Glebbeek added support for true colour fonts and a font example.
  • Elias Pschernig fixed a problem in shutdown_dialog() reported by Tobi Vollebregt.
  • Marcio Fialho fixed some issues with displaying author names in the demo game.
  • Andrei Ellman fixed a problem in the MSVC makefile when building Allegro with Cygwin.
  • Daniel Schlyder fixed (again) problems with creating directories in different setups in Windows.
  • Elias Pschernig added documentation for the custom packfile functions.
  • Jeff Mitchell fixed the location of grabber.txt in the spec file.
  • Harshavardhana Reddy added a Kannada greeting to exunicod.
  • Elias Pschernig cleaned up the example programmes.
  • Peter Wang made it possible to disable the hardware cursor in X by passing an option to the configure script.
  • AJ and Michal Molhanec added an MSVC 7 configure option and added an msvc7 switch to fix.bat. Karthik Kumar did the same for the Intel compiler icl.
  • Mr_Bones fixed compilation of setup.c when --disable-ossdigi is used
  • AJ fixed a beep being generated in Windows when alt+character was pressed in Windowed mode.
  • Peter Wang fixed many oversights and problems in the library and examples and allowed the code to be build with stricter warnings.
  • Peter Wang fixed problems compiling the Windows port with WARNMODE=1
  • Tore Halse fixed compilation problems in Windows related to TITLEBARINFO.
  • Daniel Schlyder made the Windows port use TITLEBARINFO if it is available.
  • Grzegorz Adam Hankiewicz made many improvements to the documentation.
@heading Changes from 4.1.17 to 4.1.18 (January 2005)
  • Peter Hull fixed a bug that caused rest() to wait too long on MacOS X.
  • Tore Halse made the Allegro window always appear centred in Windows.
  • Peter Wang fixed a lot of warnings in the code and did a lot of cosmetic fixes as well.
  • Grzegorz Adam Hankiewicz added short description support to the MAN and HTML documentation.
  • Milan Mimica fixed a bug in the keyconf utility.
  • Peter Hull fixed some issues compiling Allegro for MacOS X.
  • Marcio Fialho fixed a warning when compiling Allegro with DJGPP.
  • Evert Glebbeek fixed a bug that prevented system cursors from working in Windows, as pointed out by Peter Johansson.
  • Evert Glebbeek added a font loading routine and various other font functions to the library.
  • Peter Wang added custom packfile functions and packfile vtables.
  • Peter Wang decoupled the packfile compression code from the packfile routines.
  • Daniel Schlyder fixed some problems with the font loading code.
  • AJ added IA64, SSE3 and AMD64 detection code.
  • Daniel Schlyder fixed some warnings with MinGW gcc 3.4.2
  • Peter Hull made the file selector work properly with directories that have more than 2048 entries.
  • Marcio Afonso Arimura Fialho fixed some problems with the DJGPP version and the VBE/AF driver.
  • Phil Shenk clarified the MSVC build docs.
  • Michal Molhanec fixed a problem with long filenames in the MSVC build process and added a --msvcpaths flag to the fix.bat script.
  • Grzegorz Adam Hankiewicz made a lot of improvements to the documentation.
  • Peter Wang made some modifications to allegro_message() in X11.
  • Evert Glebbeek added blender mode defines and activated the gfx_vtable set_blender_mode() function in the source.
  • Evert Glebbeek added gui_set_screen and gui_get_screen functions and a set_mouse_cursor_bitmap function.
  • Peter Wang made scancode_to_name never return NULL.
  • Peter Wang fixed some problems in the Linux joystick driver.
  • Grzegorz Adam Hankiewicz added a lot of ASSERTions to the code.
  • Elias Pschernig added special Ctrl-Alt-End and Pause key handlers to the X11 keyboard driver.
  • Elias Pschernig fixed a problem with the mouse acceleration in Windows.
@heading Changes from 4.1.16 to 4.1.17 (December 2004)
  • Sven Sandberg fixed a few problems with the sprite rotation code.
  • Sven Sandberg optimized blitting between different colour depths.
  • Evert Glebbeek added support for the use of native window manager cursors.
  • Chris Robinson made install_allegro() check if the library version matches the version of the header files installed.
  • Peter Wang fixed some problems with rest() on UNIX systems.
  • Evert Glebbeek added an is_windowed_mode() function.
  • Elias Pschernig added the scancode_to_name function.
  • Elias Pschernig made rest use usleep() on MacOSX.
  • Chris Robinson fixed the incorrect use of -export-dynamic on UNIX
  • Elias Pschernig, Chris Robinson and Peter Wang fixed XOR mode leaving droppings in X11.
  • Elias Pschernig fixed several dependency issues.
  • James Lohr fixed a problem with mouse acceleration in fullscreen modes under Windows.
  • Peter Wang fixed a problem in the TGA loader.
  • Lennart Steinke contributed keyboard layout detection code for Windows.
  • Peter Wang fixed a bug that caused Allegro to crash if it failed to initialize.
  • Peter Wang fixed a deadlock related to X vsync emulation.
  • Daniel Schlyder fixed make uninstall with mingw make.
  • Elias Pschernig fixed QNX issue of not including utimer.c
  • Angelo Mottola fixed compilation problems on BeOS and fixed the detection of VRAM.
  • Evert Glebbeek fixed compilation problems on *BSD.
  • Elias Pschernig made the X11 window hidden in GFX_TEXT mode.
  • Peter Wang removed remapping of numpad keys when NumLock was off in Linux
  • David A. Capello made override_config_file also be used for writing to the config file.
  • Julien Cugniere added an X11 message box for allegro_message under X11.
  • Vitaliy Chetverikov a small bug in the GUI where the return value of MSG_IDLE was ignored.
  • Peter Wang made several improvements to the examples.
  • Grzegorz Adam Hankiewicz made a lot of improvements to the documentation.
  • Elias Pschernig made make-install not build examples.
  • Peter Wang fixed several instances of symbols not declared static that should have been.
  • Elias Pschernig replaced the X11 keyboard driver with a new XIM driver.
  • Peter Wang fixed a problem with Linux headers and Allegro headers both declaring KEY_ constants, as pointed out by David A. Capello.
  • Elias Pschernig fixed X11 async reply in DGA2 mode detection due to missing XLOCK/XUNLOCK
  • Peter Wang fixed problems in ex3buf, which was trying to lock symbols which had been removed.
  • Elias Pschernig cleaned up grabber/dat documentation.
  • Daniel Schlyder added ALLEGRO_LIB_BUILD flag for gcc variants not using configure.
  • Elias Pschernig fixed bugs in matrix_to_quat and get_align_matrix.
  • Evert Glebbeek fixed a problem with the X11 port when ALLEGRO_MULTITHREADED was not defined.
  • Matthew Leverton added support for a fourth mouse button to the Windows port.
  • Michal Molhanec added a FAQ section about the giftware license.
  • Elias Pschernig added the license disclaimer to the docs.
  • Evert Glebbeek added missing vtable entries for AllegroGL, as requested by Robert Ohannessian.
  • Dustin Dettmer spotted a typo in save_bitmap.
  • Sam Hocevar removed deprecated use of init_read_test, test_byte_read, etc.
  • Peter Wang fixed a bug in the Windows keyboard driver.
@heading Changes from 4.1.15 to 4.1.16 (October 2004)
  • Peter Wang fixed two problems with the keyboard driver on Windows.
  • Chris Robinson fixed a problem causing some components to wrongly initialized in Windows when the window is set.
  • Elias Pschernig added chapters to the documentation.
  • Chris Robinson fixed a bug where the X11 fullscreen driver would fail if no virtual screen was reported.
  • Daniel Schlyder added a set_allegro_resource_path() function .
  • Elias Pschernig fixed an issue with xf2pcx.
  • David A. Capello made makedoc write sub-section headings for .txt output.
  • Evert Glebbeek added hardware cursor support to the X11 and DirectX window drivers.
  • Peter Wang made the Linux joystick driver read more than one joystick event at a time, as pointed out by Greg Lee.
  • Evert Glebbeek removed the need for magic main under UNIX and added a --enable-magicmain option to the configure script.
  • Evert Glebbeek fixed a crash when initializing, deinitializing and reinitializing Allegro on Windows.
  • Evert Glebbeek fixed a possible memory protection problem in stretch_blit on Windows XP SP2, as suggested by Chris Robinson.
  • Chris Robinson fixed set_palette() not waiting for vsync in X11.
  • Peter Wang deprecated the retrace simulator.
  • Daniel Verkamp contributed a MIDI input driver for the Windows port.
  • Chris Robinson improved the speed of drawing primitives on X11 and implemented locking/unlocking for video bitmaps.
  • Evert Glebbeek fixed a problem with the build process on non-intel UNIX systems.
  • Peter Wang fixed a problem with programs aborting on exit under X11.
  • Peter Wang disabled VBE/AF by default on Linux.
  • Sam Hocevar fixed a bug where makedoc would crash for missing @erefs.
  • Peter Wang made the mouse movement appear smoother.
  • Chris Robinson made the file routines work with files containing a # in the filename.
  • Peter Wang fixed a bug in remove_int().
  • Bobby Ferris added SciTE .api file generation to makedoc.
  • Sam Hocevar made is possible to put functions defined in assembler source files in a shared library in UNIX.
  • Evert Glebbeek removed the weak declaration of allegro_icon and changed xfixicon.sh accordingly.
  • Evert Glebbeek made get_executable_name() use procfs on UNIX.
  • Grzegorz Adam Hankiewicz made many improvements to the documentation and to the makedoc tool.
  • Many fixes to source, examples and documentation.
@heading Changes from 4.1.14 to 4.1.15 (July 2004)
  • Chris Robinson tweaked tests/play.c slightly.
  • Elias Pschernig deprecated yield_timeslice in favour of rest(0) and adjusted yield_timeslice on BeOS, QNX and MacOS X to behave the same as on other platforms.
  • Eric Botcazou fixed a problem with the asm colour converter.
  • Elias Pschernig fixed some gcc warnings.
  • Vincent Penquerc'h added the ability to pass extra CFLAGS and LDFLAGS on the make command line.
  • Elias Pschernig made ex3buf work outside of DOS.
  • Chris Robinson made the alleg mixer default instead of the DirectX one in windows.
  • Angelo Mottola fixed a bug where vsync() was blocking on a mutex if called when the screen was already acquired in windowed mode.
  • Evert Glebbeek made triple buffering work in the demo if VRAM is a single surface.
  • Jon Rafkind provided an m4 macro for Allegro.
  • Eric Botcazou and Henrik Stokseth made some improvements to the build process.
  • Grzegorz Adam Hankiewicz added various fixes to the documentation and to the documentation generation system.
  • V Karthik Kumar added a Tamil language greeting to exunicode.
  • Chris Robinson and Elias Pschernig reduced lag under X11 when X11 locks are held for too long.
  • Vincent Penquerc'h fixed a problem with dependency generation under bash.
  • Evert Glebbeek added an icon to the X11 port and contributed the xfixicon script.
  • Angelo Mottola fixed an endianess issue when loading/saving 24 bit images from datafiles.
  • Angelo Mottola made datafile plugins return FALSE on error.
  • Angelo Mottola fixed the docs for pack_putc.
  • Vincent Penquerc'h made the grabber choose better default menu shortcuts.
  • Henrik Stokseth enabled the asm color converters for the X11 port.
  • Henrik Stokseth improved buffer security in various parts of the library.
  • Evert Glebbeek made strncpy use sizeof() for fixed length strings.
  • Eric Botcazou made KEY_PAUSE work properly in windows.
  • Chris Robinson improved the threaded UNIX timer code.
  • Elias Pschernig fixed some problems with the ALSA driver.
  • Angelo Mottola made Command-Q and Quit trigger the close_button_callback in OSX.
  • Grady Martin fixed a bug in the handling of %n in the printf style text functions.
  • Chris Robinson rewrote parts of Allegro's mixer.
  • Chris Robinson increased the default volume, which was set very quiet previously.
  • Grzegorz Adam Hankiewicz clarified the behavior of install_mouse.
  • Elias Pschernig improved the pause key behavior.
  • Vincent Penquerc'h added MSG_WANTMOUSE to the GUI.
  • Vincent Penquerc'h sped up get_filename.
  • Chris Robinson implemented the digmid_set_pan function
  • Chris Robinson improved the performance of the DIGMID driver.
@heading Changes from 4.1.13 to 4.1.14 (April 2004)
  • Elias Pschernig added a missing install dependency on Linux.
  • Elias Pschernig fixed a couple of problems in dat2c.
  • Angelo Mottola polished the MacOS X package builder script.
  • Elias Pschernig added a Jack sound driver to the Unix port.
  • Henrik Stokseth added support for debugging with DMalloc under Unix.
  • Eric Botcazou fixed detection of the ALSA 1.0 MIDI driver.
  • Eric Botcazou fixed compilation with --enable-color8=no under Unix.
  • Angelo Mottola made it possible to link against the Allegro framework with the allegro-config script under MacOS X.
  • Angelo Mottola changed the dynamic lib install name to major.minor to preserve binary compatibility under MacOS X.
  • Angelo Mottola fixed a bug in fixbundle with 32bpp icons and alpha channel under MacOS X.
  • Eric Botcazou improved the cross-compilation support on Linux.
  • Eric Botcazou restored the compensation code for end-of-frame in the FLI player.
  • Daniel Schlyder fixed potentially unsafe constructs in the Windows code.
@heading Changes from 4.1.12 to 4.1.13 (March 2004)
  • Minor changes and clarifications in the docs by Sven Sandberg, Andy Goth, Jon Rafkind, Nathan Smith and Daniel Schlyder.
  • Elias Pschernig extensively modified the ALSA 0.9/1.0 sound driver to make it work more nicely.
  • Julien Cugniere and Eric Botcazou fixed the crash on exit with the aRts sound driver.
  • Nathan Smith implemented the recursive handling of directories for the dat utility.
  • Eric Botcazou renamed the new '-r' option of the dat utility into '-f'.
  • Omar Cornut improved the handling of KEY_COLON2 on Japanese keyboards.
  • Omar Cornut fixed the Windows joystick driver to handle a weird peculiarity of the DirectInput API.
  • Elias Pschernig corrected the value of the alpha-channel depth field in the header when saving TGA image files.
  • Eric Botcazou fixed again the formula giving the stride value in the Linux framebuffer console.
  • Eric Botcazou restored the pixel-correct version of line() and added fastline() after Doug Eleveld had reported the problem.
  • Andy Goth and Eric Botcazou fixed the constructor support in dat2s on Unix.
  • Angelo Mottola revamped the MacOS X package creation process to make it work under 10.3 and create an enduser package that holds just the shared framework.
  • Angelo Mottola changed the MacOS X shared library building process to have a prebound shared library separated from a small static libray holding just the magic main stuff.
  • Angelo Mottola removed window shadow flickering when moving the program window around on MacOS X.
  • Elias Pschernig changed the behavior of yield_timeslice() to sleeping instead of just yielding.
  • Angelo Mottola made the MacOS X port reuse the screen on the first video bitmap creation and made the screen fade on mode switches faster.
  • Elias Pschernig made d_menu_proc() automatically yield when the dialog is driven by do_dialog().
  • Elias Pschernig added missing d_yield_proc()s to the grabber.
  • Eric Botcazou fixed a bug which caused too many sliders to be reported in the presence of a POV device on Windows.
  • Chris Jones added support for the bitfield compressed BMP image format.
  • Eric Botcazou removed all uses of GCC's cast-expression-as-lvalue extension in preparation for GCC 3.4.
  • Michal Molhanec replaced all occurences of MingW32 by MinGW in the docs.
  • Omar Cornut bumped the maximum number of buttons per joystick to 32.
  • Eric Botcazou implemented automatic screensaver disabling (only on Windows for the time being).
  • Elias Pschernig added mode 1280x960 to the gfx mode selector.
  • Elias Pschernig fixed the video mode error display in the test program.
  • Eric Botcazou fixed the final animation of the demo game.
  • Elias Pschernig made the X11 gfx driver ignore repeated key-events.
  • Eric Botcazou added set_hardware_volume().
  • Francisco Pires added an FPS counter and an option to disable vsync to the excamera example.
  • Eric Botcazou and Sven Sandberg documented the limitations of getpixel() and added is_inside_bitmap().
  • Eric Botcazou added i386 sincos optimization to GCC-based ports.
  • David Capello fixed a bug with FLI frames containing odd-sized chunks.
  • Elias Pschernig and Sven Sandberg improved the GUI focus algorithm.
  • Eric Botcazou modified the dat/grabber plugins interface to expose datafile properties to plugins.
  • Eric Botcazou added a new clipping API and deprecated the old one.
  • Grzegorz Adam Hankiewicz updated the MSVC build instructions.
@heading Changes from 4.1.11 to 4.1.12 (Nov 2003)
  • Many minor changes and clarifications in the docs, some of them based on suggestions by Neil Roy, Jon Rafkind, aj, Andrei Ellman and Michal Molhanec.
  • Angelo Mottola made little fixes all over the place in the MacOS X port.
  • Angelo Mottola removed MacOS X 10.1.x source compatibility.
  • Eric Botcazou disabled keyconf on platforms that don't need it.
  • Elias Pschernig shifted key name display so that all keys are visible in the keyconf utility.
  • Stephan Brauss added new keysyms to the X11-to-BIOS conversion table in order to catch missing keycodes for the keypad when NumLock is on.
  • Stephan Brauss corrected a few nits in the Swiss keyboard configuration file.
  • Eric Botcazou disabled the close button support when a user window is registered under Windows.
  • Eric Botcazou changed the default switch mode to SWITCH_BACKGROUND for the Windows port to cure the problems on exit under WinXP.
  • Sven Sandberg improved the previous fix to _parallelogram_map().
  • Sven Sandberg fixed an overflow in floodfill().
  • Sven Sandberg fixed the dither blit mode for the Mode-X driver.
  • Angelo Mottola added quality and reverberation settings support to the CoreAudio MIDI driver under MacOS X.
  • Angelo Mottola added high performance CoreAudio digi/midi drivers (default on autodetect) and made little fixes to the old QT Note Allocator and Carbon Sound Manager drivers under MacOS X.
  • KronomanX added a FAQ entry about the conflict between Allegro headers and the C++ 'using' directive.
  • Vincent Penquerc'h let dialog_message() pass user messages to hidden objects.
  • Michal Molhanec simplified the build instructions for Dev-C++.
  • Annie Testes fixed a redrawing problem in the grabber.
  • Vincent Penquerc'h added support for the joystick_device* config variables under Linux.
  • Vincent Penquerc'h added gfx_mode_select_filter().
  • Peter Wang removed the old Linux async I/O stuff, which had been out of service for a long, long time. Also simplified the Linux standard drivers stuff.
  • Thomas Fjellstrom added (experimental) support for ALSA 0.9.x.
  • John Utz corrected a wrong assumption about the VRAM layout in the Linux framebuffer console driver.
  • Grzegorz Adam Hankiewicz tt-ized text quotes in the HTML version of the docs.
  • Eric Botcazou made the Linux port compile on non-x86 platforms.
  • Stephan Brauss made a few fixes to let the Linux port compile again on Linux 2.2.x systems.
  • Kalle Toivonen fixed a bug in _parallelogram_map().
  • Eric Botcazou cleaned up the ALSA config variables under Unix.
  • David Cullen added multiple bullets and extra lives to the demo game.
  • Sam Hocevar fixed a race condition in the mixer under Unix w/ threads, Windows, BeOS and MacOS X.
  • Andrei Ellman improved the Windows screensaver.
  • Jon Rafkind implemented the Cohen-Sutherland clipping algorithm for the line() function.
  • Angelo Mottola added an application menu with a Quit item acting like the three fingers salute, in order to better integrate Allegro apps with the Aqua UI guidelines under MacOS X.
  • Jon Rafkind and Vincent Penquerc'h added more ASSERTs to the code.
  • Eric Botcazou added an option to disable vsync when page-flipping.
  • Eric Botcazou added the detection of spaces to the MSVCDir variable for the MSVC port.
  • Grzegorz Adam Hankiewicz integrated the build instructions in the HTML version of the documentation.
  • Angelo Mottola fixed some nits in fixbundle for alpha channel on 32-bit icons under MacOS X.
  • Lisa Parratt improved the performances of the SGI audio driver.
  • Grzegorz Adam Hankiewicz updated and improved the documentation in many places.
  • Grzegorz Adam Hankiewicz added HTML text substitution to the doc processor.
  • Tobi Vollebregt spotted a bug in ustrerror(), which was not returning a pointer to a static buffer.
  • Grzegorz Adam Hankiewicz added more documentation about return values of functions.
  • Grzegorz Adam Hankiewicz added a new section about documentation to ahack._tx.
  • Grzegorz Adam Hankiewicz fixed rare buffer overflows in do_uconvert with very tiny buffer sizes.
  • Serge Semashko fixed a bug with the letter P in the Russian keyboard configuration file.
  • Angelo Mottola let application bundles accept files dragged onto the application icon under MacOS X.
  • Peter Wang fixed save_bmp for better conformance (a couple of header fields were wrong, and dots-per-metre fields were being filled with zero).
  • Julien Cugniere fixed a bug related to the retrieval of the inital volume when no primary buffer was present under Windows.
  • Henrik Stokseth simplified the asm detection test, removed many GNUish preprocessor constructs in the asm files and, as a consequence, let the Watcom port use its own preprocessor on assembly files.
  • Peter Wang prevented non-mmapped memory from being munmapped under Linux.
  • Annie Testes prevented __al_linux_shutdown_vga_helpers from being called unless the corresponding init function was first called under Linux.
  • Sven Sandberg improved the misc/findtext.sh script.
  • Sven Sandberg added support to produce a PDF version of the manual under Unix and to compress the various formats with bzip2.
  • Sven Sandberg made some correction to the Swedish translation file.
  • Eric Botcazou pluginized the new 'Change filename' menu option in the grabber.
  • Eric Botcazou fixed the X11 mouse scrolling bug.
  • Vincent Penquerc'h made it so that modifications to the type or color depth of an image are detected as such by the grabber.
  • Henrik Stokseth added a C++ test, Eric Botcazou integrated it in the build process.
  • Angelo Mottola made several fixes to let Allegro play nice with AllegroGL under MacOS X.
  • Angelo Mottola added proper embeddable framework support to the MacOS X port, modified fixbundle and updated the docs accordingly.
  • Angelo Mottola made external plugins scripts work under MacOS X.
@heading Changes from 4.1.10 to 4.1.11 (Jun 2003)
  • Eric Botcazou temporarily reverted the fix for the mouse bug when scrolling with the X11 driver under Unix.
  • Eric Botcazou fixed the invocation of non-GNU make in the configure script, a few compilation warnings in tools/dat2c.c and made it possible to pass libraries to the misc/deplexe.sh script, so as to let Allegro build again under Solaris.
  • Grzegorz Adam Hankiewicz removed all direct references to Canvaslink and credited SourceForge for current services.
  • Eric Botcazou reworked the configure check for sched_yield() under Unix.
  • Sam Hocevar fixed a Bashism in fix.sh that makes Solaris' sh choke.
  • Angelo Mottola made sure mouse buttons are initialized to 0 at startup under MacOS X.
  • Eric Botcazou added a blurb about the new behaviour of d_ctext_proc().
  • Eric Botcazou corrected several inadequacies in the documentation of makefile targets.
  • Grzegorz Adam Hankiewicz did some housekeeping work in the docs.
  • Angelo Mottola added a missing item to the list of installed files under MacOS X.
  • Angelo Mottola added a script to automate the enduser MacOS X package creation.
  • Angelo Mottola made it possible to compile apps if just the Allegro framework is installed under MacOS X.
  • Vincent Penquerc'h corrected an inefficiency in select_palette() and unselect_palette().
  • Eric Botcazou fixed the build failure with MSVC.
  • Andrei Ellman added a few missing items to the list of uninstalled files for the MinGW and MSVC ports.
  • Vincent Penquerc'h fixed a bug in _fill_3d_edge_structure().
@heading Changes from 4.1.9 to 4.1.10 (Jun 2003)
  • Many minor changes and clarifications in the docs.
  • Hein Zelle reworked the paragraph on the location of shared libraries under Unix in the docs and added a FAQ entry on the same subject.
  • Martijn Van Lersel fixed an overflow in create_light_table().
  • Chris Jones and Eric Botcazou made the MIDI player handle the 'All Sound Off' controller message.
  • Angelo Mottola made the MacOS X port play nice with 10.1.x.
  • Eric Botcazou made the menus not block on exit when mouse buttons are still being held down.
  • Grzegorz Adam Hankiewicz improved the description of set_gfx_mode about virtual screen sizes and hardware scrolling by suggestion of Lothar May.
  • Chris Jones let the MIDI player pass controller events to the raw player by default.
  • Angelo Mottola added the platform-dependent AL_RAND() macro.
  • Angelo Mottola added a HID joystick driver to the MacOS X port.
  • Henrik Stokseth spotted non-standard constructs in the Windows port.
  • Henrik Stokseth spotted unused variables throughout the library.
  • Jim Grainger spotted a broken link in the docs and updated it.
  • Javier Gonzalez fixed some problems in the DirectSound streaming.
  • Andrei Ellman improved the exrgbhsv example.
  • Andrei Ellman corrected a rounding issue in hsv_to_rgb().
  • Angelo Mottola added _al_rand() and replaced rand() with it throughout the library.
  • Elias Pschernig moved the big font example from exgui to excustom and fixed d_edit_box string length.
  • Angelo Mottola added the 'fixbundle' utility to the MacOS X port.
  • Eric Botcazou added the possibility to fold/unfold nested datafiles in the grabber.
  • Angelo Mottola fixed a couple of color conversion bugs.
  • Elias Pschernig replaced exgui with a more thorough version.
  • Vincent Penquerc'h added support for debugging with Fortify under Unix.
  • Vincent Penquerc'h added the 'Replace' option to the grabber.
  • Vincent Penquerc'h added the 'Force Update Selection' command to the grabber and refactored a fair amount of duplicated code.
  • Eric Botcazou made exunicod endian-safe.
  • Eric Botcazou fixed the behaviour of the C version of draw_trans_sprite() with 32-bit RGBA sprites.
  • Angelo Mottola fixed the behaviour of the C version of draw_trans_sprite() in 8bpp mode.
  • Angelo Mottola added system bitmaps support to the MacOS X port.
  • Eric Botcazou enabled full support of relative filenames in the dat/grabber utilities.
  • Angelo Mottola made exlights endian-safe.
  • Christer Sandberg fixed a bug in the 24-bit graphics code of fixup_datafile().
  • Angelo Mottola added hw-accelerated VRAM->VRAM blit support under MacOS X.
  • Angelo Mottola added an install-template makefile target to install an Allegro application Project Builder template under MacOS X.
  • Angelo Mottola added a digital sound driver to the MacOS X port.
  • John Holden fixed a bug in load_wav().
  • Angelo Mottola added a MIDI driver to the MacOS X port.
  • Angelo Mottola added proper mouse buttons detection via HID Manager and buttons emulation if needed under MacOS X.
  • Eric Botcazou added canonicalize_filename() and deprecated fix_filename_path().
  • Evert Glebbeek added the support for relative filenames to the grabber.
  • Eric Botcazou made it possible to pass CC on the command line to make on non-Unix systems.
  • Angelo Mottola added support for bundled applications under MacOS X.
  • Javier Gonzalez devised a simpler fix for the WinXP black screen bug.
  • Javier Gonzalez prevented some artifacts from being left on the screen when moving fast the window under Windows.
  • Angelo Mottola contributed the MacOS X port.
  • Angelo Mottola fixed various things in preparation for the MacOS X port.
  • Eric Botcazou uncoupled link options for libraries and programs.
  • Evert Glebbeek added the support for relative filenames by means of three new API functions.
  • Elias Pschernig made the allegro.devhelp work with devhelp 0.6.0.
  • Eric Botcazou made file_select_ex() honor the '(+)d' attribute character in the extension string.
  • Eric Botcazou removed the remaining occurences of ustrcpy() from the library code.
  • Christer Sandberg fixed a problem with the include guard generated by dat2c.
  • Eric Botcazou removed the remaining calls to deprecated functions from the distribution.
  • Eric Botcazou optimized the handling of the extension string in the file selector.
  • Eric Botcazou implemented the AL_*_DEPRECATED macros and enabled them for GCC 3.1 or later.
  • Sven Sandberg improved the performance of the rgb_to_hsv() function.
  • Christer Sandberg and Eric Botcazou made dat2c correctly detect the native line ending.
  • Christer Sandberg and Eric Botcazou made dat2c work better with ISO C90 compilers.
  • Henrik Stokseth updated the installation and configuration instructions of both MinGW and Dev-C++ and documented the support of MSYS.
  • Andrei Ellman improved the performance of the hsv_to_rgb() function.
  • Peter Wang made the makefile not pass the -s switch to ld on Unix for non-optimized builds.
  • Evert Glebbeek added the 'New' command to the grabber.
  • Eric Botcazou made the grabber save previous modified data when loading new data.
  • Eric Botcazou unified and fixed the support for ALLEGRO_USE_C on all GCC-based ports.
  • Eric Botcazou unified the autodetection and handling of Unix-like tools on non-Unix systems.
  • Andrei Ellman got Allegro for MSVC to build with Cygwin.
  • Elias Pschernig made the programs be linked with -pg in profile mode under Unix.
  • Andrei Ellman updated the Cygwin section in docs/build/mingw32.txt.
  • Magnus Henoch fixed a problem when compiling without 8bpp support.
  • James Ponder and Hein Zelle clarified a requirement when cross-compiling from Linux.
  • James Ponder suggested to remove the DJGPP makefile from the Unix tar archive.
  • Grzegorz Adam Hankiewicz improved the docs on allegro_exit().
  • Grzegorz Adam Hankiewicz documented the bunch of packfile functions.
  • Eric Botcazou fixed the profile build on BeOS.
  • Eric Botcazou updated the FAQ about DJGPP's va_list problem (thanks to aj for spotting this).
  • Andrei Ellman suggested some additions to the docs.
  • Grzegorz Adam Hankiewicz added a chapter on available examples to the docs, the ability to cross-reference them and display the references with a specific layout in the HTML docs, and a Python script to automate the updating process when new examples are added.
  • Eric Botcazou fixed an asm locking bug under Windows spotted by Omar Cornut.
  • EvilTypeGuy cleaned up and fixed the RPM spec file for RedHat 9.
  • Ville Skyttä fixed a problem with make install libdir= and modules on Unix systems.
  • Peter Wang added a hack to not unload the SVGAlib module if SVGAlib installs an atexit() handler.
  • Elias Pschernig updated xf2pcx and integrated it in the build process under Unix/X11.
  • Grzegorz Adam Hankiewicz added support for dumping the configure settings under Unix.
  • Javier Gonzalez added get_color_depth() to the API.
  • Julien Cugniere and Eric Botcazou improved the support for non-blocking menus.
  • Grzegorz Adam Hankiewicz corrected several nits in the documentation.
  • Grzegorz Adam Hankiewicz documented the END_OF_MAIN macro.
  • Javier Gonzalez added get_color_conversion() to the API.
  • Lennart Steinke added the exconfig example.
  • Eric Botcazou added big-endian support to the BMP, PCX and TGA loaders as well as to the X11 driver.
  • Eric Botcazou fixed the 'uninstall' target and a problem with Mingw32's make for the Watcom port.
  • Charles Bilyue suggested to not force yielding timeslice with non-blocking menus.
  • Annie Testes fixed a bug with asynchronous I/O mode restoring under Linux.
  • Annie Testes made the screen be cleared before setting the default palette when calling set_gfx_mode().
  • Annie Testes fixed a bug with patterned drawing in the C version.
  • Vincent Penquerc'h spotted an off-by-one problem when building the list of color depths in the gfx mode selector.
  • Peter Wang made the Intellimouse PS/2 driver work for USB mice in Linux.
  • Elias Pschernig integrated xkeymap in the build process under Unix/X11.
  • Oscar Giner fixed a conflict between the magic main and the MFC.
  • Matthew Leverton fixed a bug with pack_fgets().
  • Eric Botcazou fixed broken and missing dependencies for make -j2 builds.
  • Hein Zelle revamped the cross-compilation section of docs/build/mingw32.txt.
  • Marcel Smit and Eric Botcazou made the show_video_bitmap() method of the Windows windowed driver wait for a vsync.
  • Eric Botcazou made the test program really time the fixed math functions.
  • Eric Botcazou clarified the limitations of Allegro's interrupts regarding the FPU state under DOS.
  • Peter Wang fixed a bug in stretch_blit() where the first column or row can get an extra pixel, reported by David Gowers and AJ.
  • Eric Botcazou made the linux mouse detection code really empty the buffer before proceeding in the setup program.
  • Eric Botcazou made the Watcom port compile in warnmode with Open Watcom.
  • Elias Pschernig fixed the build with the Unix->MinGW cross-compiler.
  • Magnus Henoch made the gfx mode selector keep the current selection as much as possible.
  • Eric Botcazou fixed the mouse not being scared over alert boxes.
  • Eric Botcazou added -Wstrict-prototypes to the build warnmode under DOS, Windows and BeOS.
  • Annie Testes updated the mouse autodetection code under Linux to take into account her EVDEV driver.
  • Philipp Thomas added multi-arch support, DESTDIR support and the German translation to the RPM spec file.
  • Philipp Thomas converted the configure machinery to autoconf 2.53 or later.
  • Philipp Thomas fixed all function prototypes, thus allowing to build with -Wstrict-prototypes on Unix systems.
  • Philipp Thomas fixed the compilation on x86-64.
  • Philipp Thomas fixed all comparisons between signed and unsigned types, thus allowing to build with -W -Wno-unused on Unix systems.
  • Eric Botcazou reworked the truecolor subsection of the 'Transparency and patterned drawing' section.
  • Eric Botcazou clarified the return value on failure of file_time(), following AJ's suggestion.
  • Eric Botcazou fixed the build in strictwarn mode on Unix systems.
  • Eric Botcazou fixed a mouse bug when the screen is scrolled with the X11 fullscreen driver.
  • Eric Botcazou fixed a bug with resolution and color depth not being taken into account by gfx_mode_select_ex().
  • Vincent Penquerc'h fixed the compilation breakage on Linux kernels 2.2.x.
  • Eric Botcazou defined ALLEGRO_LIB_BUILD for debug and profile releases as well on Unix systems.
  • Eric Botcazou forced the exstream example to abort if no real sound driver is found.
  • Eric Botcazou clarified the limitations of the stretching functions.
  • Acho A. Tang added a Sidewinder Precision Pro joystick driver to the DOS port.
  • Eric Botcazou re-enabled the autodetection of joysticks in the setup program.
@heading Changes from 4.1.8 to 4.1.9 (Jan 2003)
  • Many minor changes and clarifications in the docs.
  • Annie Testes fixed some device name strings in the setup program.
  • Annie Testes added a mouse driver based on the event interface (EVDEV) to the Linux port.
  • Eric Botcazou added for_each_file_ex() and deprecated for_each_file().
  • Eric Botcazou disabled hackish centering code in fullscreen mode under X11 which caused some artifacts to appear on KDE desktops.
  • Elias Pschernig fixed a pasto in the sample reading code.
  • Eric Botcazou fixed a bug with Alt+TAB under X11.
  • Eric Botcazou added a configure check for the include prefix problem with gcc 3.1 or later on Unix systems.
  • Eric Botcazou reverted the latest patch applied to the joystick code.
  • Matt Witherspoon and Eric Botcazou fixed a bug in the scroll() method of the Linux SVGAlib driver so as to make it wait for the vertical retrace.
  • Eric Botcazou added a stop/resume option to the exstream.c example.
  • Ben Davis documented the non-standard behaviour of pack_feof().
  • Eric Botcazou worked around a weird problem with some X11 window managers that prevented the fullscreen driver from setting up.
  • Eric Botcazou disabled the new timer synchronization code.
  • Grzegorz Adam Hankiewicz added a warning about DJGPP stability under some Windows versions.
  • Eric Botcazou made it so that the window is centered at startup under Windows.
  • Chris Jones and Eric Botcazou worked around a problem with DOS file attributes under Win2k.
  • Eric Botcazou made the filetest work better with the keyboard.
  • Eric Botcazou fixed shifted help sections in the grabber.
  • Eric Botcazou fixed the mishandling of TAB characters in menu bar entries.
  • Eric Botcazou added a new DEBUGMODE level so that debuggers will not be flooded by internal debug messages any more under Windows.
  • Eric Botcazou fixed a weird compilation bug under MacOS X.
@heading Changes from 4.1.7 to 4.1.8 (Dec 2002)
  • Eric Botcazou fixed a bug with nested datafiles in the dat/grabber code spotted by Thomas Klausner.
  • Eric Botcazou clarified the wording about ABI/API compatibility.
  • Thomas Klausner added NetBSD detection.
  • Ben Davis constified the parameter of set_window_title.
  • Lisa Parratt added IRIX detection.
  • Robert J. Ohannessian clarified the docs for play_audio_stream.
  • Sven Sandberg fixed the makedoc linking problem with Watcom spotted by Glenn Jarvis.
  • Ben Davis fixed a compilation warning for set_window_close_button.
  • Eric Botcazou fixed a buffer overflow in the Windows debug version spotted by aj.
@heading Changes from 4.1.6 to 4.1.7 (Dec 2002)
  • Eric Botcazou made the joystick initialization routine correctly handle zero as the joytype.
  • Eric Botcazou fixed the compile-time check for the MMX asm support.
  • Eric Botcazou fixed the non-MMX asm color copy routine.
  • Eric Botcazou implemented the synchronization routines for the BeOS port.
  • Eric Botcazou turned the set_window_close_* macros into inline functions.
  • Eric Botcazou fixed an oversight that caused the SGI AL audio driver not to be built as a module on Unix.
  • Stepan Roh fixed a glitch with autoconf 2.53 on Unix.
  • Eric Botcazou fixed the compilation bug with MinGW.
@heading Changes from 4.1.5 to 4.1.6 (Nov 2002)
  • Grzegorz Adam Hankiewicz added informations on the FLI format provided by Kronoman X to the FAQ.
  • Eric Botcazou revived the two former set_window_close_* functions as deprecated functions.
  • Elias Pschernig contributed an improved xkeymap utility, based on the original code by Michael Bukin.
  • Eric Botcazou added synchronization to the timer code on multi-threaded platforms (except BeOS for the time being).
  • Eric Botcazou made the new 'save' method of plugins use the same return value convention as the 'export' method (see tools/plugins/plugins.txt).
  • Eric Botcazou added the support for plugin scripts to the MinGW port.
  • Peter Wang changed the default sound mixing quality to 2 (highest).
  • Matthew Leverton added the detection of left-hand mouse configuration under Windows.
  • Oscar Giner fixed a bug with binary data exporting in the grabber, introduced in the 4.1.4 release.
  • Eric Botcazou fixed a crash when Alt+Tabbing under WinXP.
  • Eric Botcazou reverted his patch changing the behaviour at startup under Windows.
  • Grzegorz Adam Hankiewicz added infrastructure for properly documenting the return value of the API calls.
@heading Changes from 4.1.4 to 4.1.5 (Nov 2002)
  • Grzegorz Adam Hankiewicz updated the docs about mailing lists/contacts.
  • Grzegorz Adam Hankiewicz added instructions on how to create and submit patches to the Allegro developers.
  • Eric Botcazou implemented the support for non-blocking menus.
  • Lisa Parratt spotted a BSDism that IRIX doesn't like at all.
  • Daniel Schlyder fixed a problem with set_window_title() under BeOS.
  • Lisa Parratt contributed the SGI Audio Library sound driver.
  • Eric Botcazou completely revamped the close button support.
  • Eric Botcazou simplified fullscreen mode initialization under Windows.
  • Elias Pschernig and Eric Botcazou made the GUI code scare the mouse, when drawing, only if it is necessary to do so, thus reducing cursor flicker.
  • Eric Botcazou fixed a bug in scare_mouse_area().
  • Elias Pschernig optimized the load_bitmap() function family when no palette is specified and documented the feature.
  • Grzegorz Adam Hankiewicz aliased the stylesheet to the default CSS style, allowing The Big Lizard(tm) and other web browsers to disable CSS.
  • Eric Botcazou fixed an ill-behaviour at startup under Windows.
  • Elias Pschernig added the Euro character to the default font and to the German and French keyboard configuration files.
  • Eric Botcazou made _ustrdup() set *allegro_errno to ENOMEM on failures.
  • Annie Testes lifted several hardcoded length limitations in the configuration routines.
  • Eric Botcazou prevented set_gfx_mode() from resetting the layout of all color depths.
  • Eric Botcazou moved #include directives out of the range of extern "C" directives (fixing the C++ compilation bug with Borland C++).
  • Vincent Penquerc'h added the ALLEGRO_NO_COMPATIBILITY symbol and moved all the deprecated stuff from allegro._tx to api._tx .
  • Grzegorz Adam Hankiewicz reformatted monospaced text blocks to fit page in Postscript output.
  • Oscar Giner added the Catalan translation.
  • Oscar Giner corrected the Spanish translation.
  • Grzegorz Adam Hankiewicz added a new command to the doc processor for email mangling: me@serv.com -> me at serv dot com. It is applied to all documentation output formats.
  • Grzegorz Adam Hankiewicz made all source files use the external CSS.
  • Chris Jones fixed a bug with 16-bit samples loading introduced in the previous release.
@heading Changes from 4.1.3 to 4.1.4 (Oct 2002)
  • Eric Botcazou prevented the linker from choking on Solaris because of a static library with no symbols.
  • Eric Botcazou removed joystick control from main part of the setup program.
  • Eric Botcazou documented the workaround needed for C++ programs compiled with Borland C++ (in docs/build/bcc32.txt).
  • Eric Botcazou unified the magic main for the 3 Windows compilers and fixed the WinMain() linkage for Borland C++.
  • Henrik Schmidt made gcc pass '-h' instead of '-soname' to the linker and replaced '-L' by '-h' in shell comparisons so as not to break on Solaris.
  • Eric Botcazou fixed the bogus check for GNU ar on Unix systems.
  • Elias Pschernig made load_datafile_object() load the properties attached to the object.
  • Javier Gonzalez and Eric Botcazou fixed the infamous blank screen problem under Win2k/WinXP.
  • Eric Botcazou cleaned up the use of errno/allegro_errno throughout the library and removed all occurences of errno in the grabber/plugins code.
  • Grzegorz Adam Hankiewicz embedded readme.txt into the Allegro manual.
  • Eric Botcazou made the Windows port set the NULL mouse cursor in fullscreen mode instead of hiding it.
  • Vincent Penquerc'h ASSERTed a bunch of C drawing routines.
  • Robert J. Ohannessian did some cosmetic improvements to the HTML output and separated the CSS file.
  • Evert Glebbeek added configure options for x86 processor optimizations on Unix systems.
  • Benny Colyn added a Dutch translation.
  • Evert Glebbeek added the detection of SunOS/Solaris.
  • Javier Gonzalez fixed a graphics bug with always-on-top applications.
  • Igor Gnip added the detection of MSYS via the SHELL variable to the MingW32 port.
  • Eric Botcazou made the mouse use the exclusive foreground cooperative level in fullscreen mode under Windows.
  • Eric Botcazou fixed a bug than had prevented ALT+F4 from being properly handled under Windows and cleaned up the low-level scancode handler.
  • Eric Botcazou updated the description of the layout of header files in the aHack file.
  • Grzegorz Adam Hankiewicz corrected the docs about 'ulimit' in the Help file.
  • Laurence Withers converted the core library and the whole distribution to use the new text API.
  • Laurence Withers added a new text API and deprecated the old one.
  • Eric Botcazou made the Windows port stop triggering SWITCH_IN events when restoring the DirectDraw surfaces.
  • Eric Botcazou re-enabled screensavers and powerdowns under Windows.
  • Eric Botcazou made the deprecated file_select() an inline function.
  • Eric Botcazou cleaned up set_gfx_mode() and made it so that GFX_SAFE selects a windowed mode in windowed environments.
  • Vincent Penquerc'h added a container header file graphics.h for all the graphics stuff.
  • Vincent Penquerc'h added an indexing option to the grabber.
  • Evert Glebbeek added an option menu to the grabber.
  • Evert Glebbeek and Eric Botcazou cleaned up the grabber/plugins code; in particular, the 'save' method of plugins got a new prototype.
  • Peter Wang made fix.sh and zipup.sh not destroy timestamps when just changing EOL markers.
  • Peter Wang fixed a misuse of the -I option with gcc 3.0 and later.
  • Robert J. Ohannessian added more caveats to docs/build/mingw32.txt.
@heading Changes from 4.1.2 to 4.1.3 (Sep 2002)
  • Grzegorz Adam Hankiewicz fixed a bug in the HTML rendering code.
  • Eric Botcazou modified the querying of DirectSound devices under Windows.
  • Evert Glebbeek added a '-fullscreen' switch to the grabber, Laurence Withers a '-windowed' switch.
  • Eric Botcazou temporarily disabled screensavers and power downs under Windows.
  • Daniel Schlydler fixed problems with get_executable_name() under Windows.
  • Eric Botcazou added a FAQ entry on the C++ headers problem with gcc 3.x and Mingw32, summarizing findings by Robert J. Ohannessian.
  • Robert J. Ohannessian fixed the compilation problem with MSVC.
@heading Changes from 4.1.1 to 4.1.2 (Sep 2002)
  • Many minor changes in the code and the docs.
  • Grzegorz Adam Hankiewicz fixed a crash in the exmouse example when no mouse is present.
  • Angelo Mottola made the exunicod example welcome Italian programmers too.
  • Grzegorz Adam Hankiewicz documented new structures.
  • Eric Botcazou added a native DirectX window test.
  • Eric Botcazou re-enabled the 1 ms accuracy limitation for timers under Windows.
  • Elias Pschernig added support for the Devhelp documentation format.
  • Marcel Smit corrected an error in the packfile format write-up.
  • Eric Botcazou fixed a conflict between Allegro headers and standard C++ headers of gcc 3.x under Mingw32.
  • Matthew Leverton made the DOS/Windows makefiles use 'copy /B' instead of 'copy' for file concatenation.
  • Eric Botcazou wrote another new page flipping/triple buffering code for the Windows port.
  • Eric Botcazou made it so that win_set_window() restores the state of the joystick module as well.
  • Grzegorz Adam Hankiewicz ASSERTed a bunch of public functions.
  • Eric Botcazou made it so that restoring the DirectDraw surfaces always triggers a SWITCH_IN event under Windows.
  • Peter Wang fixed a problem linking with the debug version under linux, due to missing "inline" functions.
  • Robert J. Ohannessian fixed the docs for pivot_scaled_sprite_v_flip().
  • Eric Botcazou fixed a race condition when registering input events at startup under Windows.
  • Roberto Alfonso added an srand() call in the demo game.
  • Elias Pschernig removed (seemingly) arbitrary window size checks in the Unix X11 driver.
  • Roberto Alfonso fixed a couple of memory problems in the dat2c utility.
  • Matthew Leverton pointed out a C99 idiom in the dat2c utility that Borland C++ doesn't like.
  • Angelo Mottola changed the BeOS gfx driver IDs/constants to more pertinent ones.
  • Angelo Mottola added a safe BWindow-based windowed driver and a fullscreen overlay driver to the BeOS port.
  • Angelo Mottola reorganized and commented all the BeOS gfx subsystem.
  • Sven Sandberg fixed a bug in create_trans_table().
  • Javier Gonzaled fixed a bug with volume and pan not properly set in loop mode by the DirectSound driver.
  • Laurence Withers added two fixed point ratios for converting to and from radians.
  • Eric Botcazou fixed the documented prototype of fixtof() and ftofix().
  • Laurence Withers fixed the 'inline' compilation bug in the dat2c utility.
  • Eric Botcazou fixed a bug that causes timers to restart permanently when Allegro is switched out under Windows.
  • Eric Botcazou fixed a bug with switch mode setting under Windows he had introduced in the 4.1.1 release.
  • Grzegorz Adam Hankiewicz improved the legibility of the HTML code generated by the doc processor and reduced its size in the process.
@heading Changes from 4.1.0 to 4.1.1 (Aug 2002)
  • Many minor changes and clarifications in the docs and the FAQ.
  • Eric Botcazou fixed a bug with graphics mode switching using a ALT+key combination under Windows.
  • Laurence Withers contributed the dat2c utility.
  • Grzegorz Adam Hankiewicz made it so that chapters can be referenced in the documentation and added a new one on the types and structures defined by the library.
  • Eric Botcazou improved win_set_window() so that it can be called after the library has been initialized.
  • Elias Pschernig fixed a bug in midi_seek().
  • Eric Botcazou wrote a new page flipping/triple buffering code for the Windows port.
  • Grzegorz Adam Hankiewicz added a linux specific debug help section.
  • Eric Botcazou made the constructors of the fix class from integer and floating point values explicit.
  • Eric Botcazou fixed a dat2s bug with dynamically linked programs under Windows.
  • Jan Bruun Andersen fixed a compilation problem with Cygwin.
  • Jeremiah Blanchard updated the build instructions for Darwin.
  • Vincent Penquerc'h added sample loader/saver registration and a save_sample() function. Peter Wang documented it.
  • George Foot added (preliminary) non-FM support to the OSS MIDI driver.
  • Ben Davis and Robert J. Ohannessian put in (void *) casts for the LOCK_* macros on DJGPP and Mac.
  • Nicholas Davies made the fix class not trigger warnings with gcc -Weffc++.
  • Angelo Mottola fixed a keyboard focus problem under BeOS.
  • Peter Wang fixed the detection of ESD and aRts on Unix systems.
  • Peter Wang made files be opened with as permissive as possible permissions on Unix systems.
  • Stepan Roh added support for a automake-style DESTDIR variable in the Unix makefile.
  • Grzegorz Adam Hankiewicz made the doc processor output valid HMTL 4.0 in some corner cases for which it previously didn't.
  • Grzegorz Adam Hankiewicz fixed a crash of the doc processor with very long lines.
  • Peter Wang did some housekeeping work throughout the code and the documentation.
@heading Changes from 4.0.2 to 4.1.0 (Jul 2002)
  • Charles Bilyue optimized the i386 blitters.
  • Peter Wang fixed the mis-treatment of empty files by the library and the 'pack' utility.
  • Eric Botcazou simplified pack_f{read,write} and cleaned up several uses of pack_feof().
  • Eric Botcazou split USE_CONSOLE into ALLEGRO_USE_CONSOLE and ALLEGRO_NO_MAGIC_MAIN.
  • Eric Botcazou simplified and cleaned up the asm bank switchers.
  • Peter Wang added support for the environment variable ALLEGRO_MODULES under Unix.
  • Peter Wang made 'configure --disable-vga' remove more stuff out of the core under Unix.
  • Eric Botcazou made the DirectDraw code try to restore its surfaces as soon as it detects they have been lost.
  • Peter Wang added a description of the packfile format.
  • Peter Wang added an aRts sound driver to the Unix port.
  • Sven Sandberg optimized create_video_bitmap() for systems with a single video memory surface.
  • Grzegorz Adam Hankiewicz reindented the documentation sources, improving the text/info/html output in the process.
  • Grzegorz Adam Hankiewicz improved chm output for the documentation.
  • Sven Sandberg optimized and reduced numeric errors in create_trans_table().
  • Lorenzo Petrone added a xwin_set_window_name() function to the X11 port.
  • Peter Wang made install_allegro()/allegro_init() not abort the program on failure.
  • Sven Sandberg and Grzegorz Adam Hankiewicz added backward compatibility to the new doc processor.
  • Sven Sandberg fixed various problem in the makefiles.
  • Elias Pschernig made it so that the COLORCONV_KEEP_TRANS flag is checked when converting bitmaps out of datafiles.
  • Eric Botcazou added preliminary support for hardware acceleration and video bitmaps to the QNX port.
  • Elias Pschernig added a window position saving feature to the Windows port.
  • Vincent Penquerc'h added a -s-PROP option to the dat utility in order to preserve properties when stripping.
  • Henrik Stokseth made the zipwin.sh script for packaging the Windows binary distribution work with Cygwin.
  • Peter Wang and Eric Botcazou made it so that Allegro C programs can compile with gcc -ansi -pedantic.
  • Vincent Penquerc'h added a 'sort' option to the grabber and the dat utility.
  • Eric Botcazou added preliminary support for native windows under Windows.
  • Vincent Penquerc'h made gcc use pipes on Unix when building the library.
  • Lorenzo Petrone added support for switch callbacks under X11 and refactored the display switching code.
  • Javier Gonzalez changed the default value of emulate_three to no in all cases.
  • Eric Botcazou modified the behaviour of the retrace_* objects to take into account the refresh rate if known.
  • Eric Botcazou fixed the 'configure --disable-constructor' problem.
  • Elias Pschernig fixed menu dimensions in the GUI engine.
  • Eric Botcazou added documentation on API compatibility.
  • Elias Pschernig and Eric Botcazou fixed the get_camera_matrix*() functions.
  • Igor Gnip removed the requirements for fileutils on DOS/Windows platforms.
  • Jeremiah Blanchard contributed modifications in order for Allegro to compile on Darwin/MacOS X.
  • Henrik Stokseth merged standard and extended mode-selectors.
  • Elias Pschernig added chm ouput support for the documentation.
  • Eric Botcazou merged the three input threads into a single one under Windows.
  • Mike Pichagin contributed the ustrnicmp() function.
  • Grzegorz Adam Hankiewicz contributed a new documentation format for better html output.
  • Eric Botcazou added a DirectInput joystick driver to the Windows port.
@heading Changes from 4.0.1 to 4.0.2 (Jun 2002)
  • Many clarifications in the docs.
  • Sven Sandberg improved accuracy and fixed bugs in do_arc().
  • Matthew Leverton added missing header files to be installed by the Windows binary distribution.
  • Grzegorz Adam Hankiewicz fixed a problem with the TOC of the FAQ.
  • Eric Botcazou fixed a bug with stretch_blit() under Windows XP.
  • Peter Wang fixed various configure machinery problems under Unix.
  • Sven Sandberg updated the Swedish translation file.
  • Sven Sandberg fixed a crash in the exswitch example when compiled by Watcom C/C++ and also made if faster.
  • Maxime Carey added a Canada (French) keyboard mapping file.
  • Henrik Stokseth updated instructions and fixed installation for Cygwin.
  • Eric Botcazou added an option to disable direct updating in color conversion mode under Windows.
  • Eric Botcazou (presumably) fixed the bug in the emergency exit mechanism under Windows when called from the DLL.
  • Angelo Mottola made it so that the sound doesn't block the main thread anymore under BeOS.
  • Deepak T and Eric Botcazou fixed clipping in three C sprite drawing routines.
  • Peter Wang fixed a deadlock that occurred under Unix when Allegro received an X11 close event.
  • Eric Botcazou added a --cppflags option to allegro-config and fixed C++ compilation under QNX.
  • Vincent Penquerc'h added a --version= option to allegro-config.
  • Robert J. Ohannessian made the 32->24 color convertors more robust and improved the MMX one in the process.
  • Robert J. Ohannessian, Eric Botcazou and Sven Sandberg fixed a bug in the hue blender and the hsv_to_rgb() routine.
  • Matthew Leverton fixed another problem with al_find*() and NTFS partitions under Windows.
  • Peter Wang fixed a bug in ALSA device detection.
  • Peter Wang fixed a bug in al_find* under Unix when running as root.
  • Matthew Leverton and Eric Botcazou fixed a bug with mouse mickeys in windowed mode under Windows.
@heading Changes from 4.0.0 to 4.0.1 (Mar 2002)
  • Many minor changes, many clarifications in the docs.
  • Peter Wang fixed the installation of shared libs under FreeBSD.
  • Peter Wang and Eric Botcazou fixed autodetection glitches for VGA and SVGAlib.
  • Eric Botcazou fixed a problem under X11 when the MIT X-SHM extension is used.
  • Eric Botcazou fixed a deadlock on exit when an user window is used in conjunction with timers under Windows.
  • Eric Botcazou disabled useless backbuffers for the DirectX safe driver.
  • Peter Wang made the Alsa sound driver use non-blocking mode when detecting if ALSA PCM available.
  • Sven Sandberg added support for long long integers to usprintf() and al.
  • Robert J. Ohannessian fixed the difference blender.
  • Peter Wang fixed a race condition when closing the X display.
  • Elias Pschernig made all active dialogs redraw themselves after a switch.
  • Peter Wang made fbcon a priority driver, so that it can appear above VGA.
  • Javier Gonzalez fixed a glitch in the DirectSound input code.
  • Eric Botcazou fixed the SIGSEGV on exit with the three-finger salute under QNX.
  • Eric Botcazou fixed the C-to-asm calling problem for Borland C++ compiled programs.
  • Eric Botcazou cleaned up the messy (and somewhat incorrect) DirectDraw bitmap management code.
  • Sven Sandberg improved the video bitmap subdivision algorithm.
  • Sven Sandberg fixed problems in the Windows makefiles (especially Borland) when building Allegro under Win98.
  • Peter Wang removed the hack which switched off fix aliases under IRIX.
  • Vincent Penquerc'h fixed a problem with the SIGALRM timer and SWITCH_PAUSE.
  • Javier Gonzalez fixed a latency problem with audiostreams.
  • Laurence Withers made the font exporter use the current palette for the output.
  • Elias Pschernig made some changes to grabber: added a close hook; keeps track if anything has been modified; when you exit the grabber and the file was modified, the popup now has a 3rd option for save+exit; window title displays the current filename, and if the file has been modified; fixed multicolour font exports.
  • Sven Sandberg optimized again the create_light_table() function.
  • Attila Szilagyi fixed SVGAlib horizontal scrolling.
  • Eric Botcazou fixed synchronization problems under QNX.
  • Grzegorz Adam Hankiewicz made the TOC at the top of sections alphabetically sorted.
  • Eric Botcazou fixed the screen not restored after a wake-up in the Windows windowed and overlay drivers.
  • Richard Reeve fixed a silly mistake with gcc 3.0.x detection.
  • Angelo Mottola fixed static keyconf compilation problem on BeOS due to pckeys keyboard driver.
  • Eric Botcazou fixed the not-returning-focus-on-exit bug under Windows.
  • Michael Bukin fixed a bug with C-version textprintf on 24-bpp bitmaps, reported by Bertrand Coconnier.
  • Eric Botcazou fixed a bug in the 32->15 MMX color conversion routine.
  • Eric Botcazou fixed the DLL linking problem with Borland C++ Builder 4.
  • Sven Sandberg made exaccel more responsive.
  • Sven Sandberg fixed a glitch with short filenames under DOS.
@heading Changes from 3.9.40 to 4.0.0 (Dec 2001)
  • Many minor changes.
  • Eric Botcazou modularised the VGA/Mode-X drivers under Linux.
  • Peter Wang fixed the segfault bug in Mode-X under Linux with threads.
  • Peter Wang made the X11 port use SIGTERM signal instead of exit() when invoking the three finger salute. This solves a problem where programs with sound hang when they are killed.
  • Eric Botcazou added os_version and os_revision support to the QNX port and added a QNX specific section to the docs.
  • Peter Wang added a deadzone for digital readings of joystick axes under Linux, as suggested by George Foot and made the driver look for /dev/input/js# before /dev/js#.
  • Peter Wang renamed fixed point functions to be prefixed with "fix" instead of "f", to avoid clashes with some libcs. Backwards compatibility is provided using static inline functions.
  • Peter Wang fixed two problems with emergency exits under Linux/Unix.
  • Eric Botcazou changed the updating logic of the QNX Photon graphics driver.
  • Eric Botcazou added a doc for the wfixicon utility, with the help of Laurence Withers.
  • Angelo Mottola unicodified allegro_message on BeOS and wrote a new BeOS keyboard driver (using the shared pckeys system).
  • Eric Botcazou fixed a problem with David Capello's d_menu_proc steal/return mouse focus patch.
  • Peter Wang made passing NULL to install_allegro() as the atexit_ptr parameter mean allegro_exit() won't be installed as an atexit() callback, as suggested by Javier Gonzalez.
  • Lorenzo Petrone added a gfxinfo utility.
  • Eric Botcazou added fetch_mode_list() to the QNX Photon Direct driver.
  • Peter Wang made X desktop_color_depth() able to return 15 bpp.
  • Grzegorz Adam Hankiewicz updated Spanish translation strings.
  • Peter Wang fixed a problem with X shutdown sequence.
  • Eric Botcazou repaired the QNX build process, revamped the layout of the QNX port sources and made some fixes.
  • Peter Wang disabled the SVGAlib mode fetching code as it was causing problems with other drivers.
  • Angelo Mottola added BeOS notes to the ABI compatibility doc.
  • Eric Botcazou fixed a bug in the Windows locking code that caused the grabber to crash on switch out.
  • Eric Botcazou fixed a bug in the handling of recursive sub-bitmaps under Windows.
  • Eric Botcazou fixed a bug preventing old style password-protected packfiles from loading in the grabber.
  • Lorenzo Petrone added two FAQ entries on DGA2 problems.
  • Grzegorz Adam Hankiewicz revamped the structure of the docs directory.
  • Stepan Roh updated the Czech translation.
  • Javier Gonzalez fixed a bug in the DirectSound driver related to the loop playing modes.
  • David Capello fixed a problem with submenus which overlapped their parents, where focus would pop back to the parent instead of the child.
@heading Changes from 3.11 to 3.9.40 (Nov 2001)
  • 3.9.40: Eric Botcazou enabled SSE support under Linux. Also reduced the delay in the DOS Sidewinder init code. Made the definition of _AL_DLL for MinGW32 consistent with other Windows ports.
  • 3.9.40: Henrik Stokseth improved make install to install only the needed headers from the include/allegro/platform directory.
  • 3.9.40: Vincent Penquerc'h updated 7 makefiles after his header splitting patch.
  • 3.9.40: Robert J. Ohannessian added two new entries to the GFX_VTABLE structure.
  • 3.9.40: Eric Botcazou replaced sprintf() by snprintf() in the Linux/Unix code. Increased the delay in the Windows switch handling code. Unicodified the GFX mode selector and fixed some glitches. Added a new test dubbed filetest. Fixed more unicode string problems. Unified the handling of system directory variables in the Windows makefiles. Made two strings translatable in the GFX mode selector.
  • 3.9.40: Ben Davis added support for timers with parameters under Windows.
  • 3.9.40: Eric Botcazou fixed the bug in the asm sprite functions when used with sub-bitmaps. Fixed a problem of the new header layout for platforms not supporting asm.
  • 3.9.40: George Foot and Eric Botcazou fixed the C fceil() function and added the ffloor() function.
  • 3.9.40: Chris Graham suggested to add a new flag for Windows NTFS compressed files.
  • 3.9.40: Henrik Schmidt and Eric Botcazou found a workaround for the switching problem under Windows.
  • 3.9.40: Eric Botcazou revamped the Borland C++ build process. Now it targets BC++ 5.5. Made pack_fdopen() an exported internal function. Reverted to the 3.9.38 code for 16-bit audio streaming with DirectSound.
  • 3.9.40: Vincent Penquerc'h contributed a rather large split-up/ reorganization of the Allegro header files. Henrik and Eric did some related clean-up and fixing.
  • 3.9.40: Peter Wang updated put_backslash() docs.
  • 3.9.40: Eric Botcazou modified the way DirectDraw surfaces are enumerated. Fixed compilation errors/warnings with BC++. Made generate_optimized_palette_ex() a static function. Worked around the DOS limitations for al_findfirst() and for_each_file(). Moved platform-dependent stuff out of src/fsel.c.
  • 3.9.40: Peter Wang updated timer docs for non-DOS. Added ABI compatibility readme.
  • 3.9.40: Javier Gonzalez removed all references to the RSXNT build.
  • 3.9.40: Vincent Penquerc'h made it so that users can provide their own ustrdup().
  • 3.9.40: Robin Burrows fixed two glitches in the DirectDraw code.
  • 3.9.40: Peter Wang fixed a problem where XUnlockDisplay was called after XCloseDisplay.
  • 3.9.40: Eric Botcazou removed old Sidewinder asm driver. Cleaned up buffer usage in DIGMID. Fixed unicode support in the DIGMID driver. Replaced all occurrences of SEND_MESSAGE() by object_message().
  • 3.9.40: Annie Testes caught a misordering in the X system shutdown.
  • 3.9.40: Eric Botcazou increased the size of filename buffers to 1024 bytes.
  • 3.9.40: Sven Sandberg improved fix.bat script.
  • 3.9.40: David Capello fixed a problem with lost GUI mouse clicks.
  • 3.9.40: Vincent Penquerc'h removed two hard-coded list sizes in grabber.
  • 3.9.40: Peter Wang added a little clarification regarding mouse_accel_factor.
  • 3.9.40: Eric Botcazou made debugging functions revert to ASCII strings. Added some defines for backwards compatibility with former cpu_* flags. Fixed a compilation problem under DJGPP.
  • 3.9.40: Henrik Stokseth added VBE/AF fetch_mode_list().
  • 3.9.40: Robert J. Ohannessian revamped the retrieval mechanism of CPU capabilities and added some new flags.
  • 3.9.40: Eric Botcazou fixed various mouse cursor problems under Windows. Updated docs about the DIGI_DIRECTX drivers.
  • 3.9.40: Javier Gonzalez fixed audio streams in Windows.
  • 3.9.40: Peter Wang improved the XDGA2 driver by removing unneccessary scrolling, which also resulted in speed-ups due to less locking/unlocking. The original fix was by Michael Bukin.
  • 3.9.40: Eric Botcazou and Javier Gonzalez added some documentation on static linking with MSVC/MinGW32.
  • 3.9.40: Peter Wang fixed sonames for debug and profile libs. Also added a 'configure' check that ld supports -export-modules before enabling modules.
  • 3.9.40: Annie Testes found ASCII strings that needed to be converted. Also added a pack_fdopen() function.
  • 3.9.40: Robert J. Ohannessian clarified some Dev-C++ instructions. Fixed fix.bat script under MinGW32/Win2k.
  • 3.9.40: Marcel Smit corrected a bug that caused errors when drawing perspective-correct polygons facing the screen. (dz=0)
  • 3.9.40: Peter Wang made install_timer_int static. Also moved allegro_404_char into public API.
  • 3.9.40: Laurence Withers added docs for allegro_404_char.
  • 3.9.40: Eric Botcazou fixed a little glitch with menu auto-opening. Also fixed a color glitch in the Windows windowed driver on 8-bit desktops.
  • 3.9.40: Salvador Eduardos Tropea fixed inline friend declarations with bodies. (gcc 3.0.x problem)
  • 3.9.40: Peter Wang improved behaviour between mouse auto-opening menus and navigating with keyboard. Also unspartanised the ustrtok_r() docs.
  • 3.9.40: Henrik Stokseth replaced the mmxtest with a more advanced assembler capabilities testing.
  • 3.9.40: Eric Botcazou re-enabled full pairing on Pentium for five color conversion routines. Applied xor vs. mov instruction-length optimization to the non-MMX code. Applied %ecx vs. %edx instruction-length optimization to the non-MMX code. Updated the mouse_accel_factor docs.
  • 3.9.40: Peter Wang eliminated use of static buffers by uconvert() in several places.
  • 3.9.40: David A. Capello made d_menu_proc steal/return focus when activated/deactivated.
  • 3.9.40: Henrik Stokseth added Out of Environment space detection on the fix.bat script.
  • 3.9.40: Eric Botcazou fixed a non ANSI C compliant behaviour in usprintf().
  • 3.9.40: Seunghwan Ji made makedoc output correct html and rtf files for Korean.
  • 3.9.39: Robert J. Ohannessian added -? and --help options to dat.
  • 3.9.39: Sven Sandberg and Grzegorz Adam Hankiewicz fixed some errors in the documentation.
  • 3.9.39: Annie Testes fixed several glitches related to unicode support.
  • 3.9.39: Henrik Stokseth added an internal _al_sane_realloc() function with guaranteed behaviour. Used this to fix a memory leak and updated the FAQ.
  • 3.9.39: Eric Botcazou and Peter Wang updated the documentation on: file attribute flags, request_scroll and request_video_bitmap.
  • 3.9.39: Eric Botcazou unified the use of internal timers in Windows drivers. Also let digitest use max volume of Allegro mixer.
  • 3.9.39: Paul Hampson improved again the DOS SNESpad joystick driver.
  • 3.9.39: Eric Botcazou revamped the locking mechanism of the DGA2 driver. Also fixed some memory leaks.
  • 3.9.39: Peter Wang added mode fetching for X11 fullscreen and DGA fullscreen drivers.
  • 3.9.39: Robert J. Ohannessian fixed 16bit masked blit SSE code and removed unused instruction in the other blitters.
  • 3.9.39: Salvador Eduardos Tropea added some GCC 3.x fixes.
  • 3.9.39: Peter Wang added a check if a module listed in modules.lst exist before trying to load it.
  • 3.9.39: Charles Wardlaw made alert/alert3 use transparent background for text label.
  • 3.9.39: Eric Botcazou added a flush_config_file() API function. Also added a hfill() method to the GFX_VTABLE structure.
  • 3.9.39: Peter Wang fixed some memory leaks.
  • 3.9.39: Eric Botcazou fixed two compilation warnings with gcc > 2.95.
  • 3.9.39: Johan Peitz contributed 'Alex the Allegator' icon.
  • 3.9.39: Angelo Mottola fixed safe fullscreen bug and fetch_mode_list() for BeOS.
  • 3.9.39: Peter Wang updated XDGA2 and SVGAlib driver's fetch_mode_list() function.
  • 3.9.39: Henrik Stokseth rewrote the mode-list API, updated the code and updated the documentation.
  • 3.9.39: Grzegorz Adam Hankiewicz updated all URLs in the Allegro sources and documentation.
  • 3.9.39: Eric Botcazou fixed cmplog script for perl 5.6.1.
  • 3.9.39: Peter Wang added a FAQ entry.
  • 3.9.39: Peter Wang fixed up the sound subsystem which he accidentally broke when he introduced the dynamic modules.
  • 3.9.39: Eric Botcazou fixed a compilation warning. Also added support for 8-bit desktops to the windows windowed driver. Fixed color shifts in the color convertors from 8-bit. Fixed a bug in the 8->8 color conversion routine.
  • 3.9.39: Javier Gonzalez contributed bidirectional looping support for the directsound driver.
  • 3.9.39: Robert J. Ohannessian and Henrik Stokseth did a large update on the installation instructions for Mingw32.
  • 3.9.39: Eric Botcazou cleaned up windows dll version info sheet and let the windows makefiles use implicit rules on some file targets. Fixed a compilation glitch with MSVC.
  • 3.9.39: Henrik Stokseth added support for building RPMs with SuSE Linux.
  • 3.9.39: Peter Wang fixed some off-by-one errors. Fixed unix makefile. Fixed disabling of dynamic modules.
  • 3.9.39: Eric Botcazou and Grzegorz Adam Hankiewicz finished translation of the allegro.spec file.
  • 3.9.39: Eric Botcazou re-added a faq entry on DirectX version problem.
  • 3.9.39: Grzegorz made fbcon a module.
  • 3.9.39: Peter Wang removed allegro-enduser.spec as it is no longer needed. Also contributed a rewrite of the allegro.spec file, and updated the scripts to make the rpm. The new allegro.spec file was based on one contributed by Osvaldo Santana Neto. Peter also allowed configure to give linker flags to allegro-config (for modules). Also let _unix_find_resource search in /usr/[local/]share/allegro for .dat files.
  • 3.9.39: Javier Gonzalez contributed backward playing support for the directsound driver.
  • 3.9.39: Eric Botcazou fixed a glitch with backward playing in the digitest test.
  • 3.9.39: Salvador Eduardos Tropea made a small update on the cygwin section of readme.mgw.
  • 3.9.39: Peter Wang fixed a problem with BSD make and Mac directory separators ':'. Documented gfx_cardw variable.
  • 3.9.39: Sven Sandberg fixed a nasty side-effect of clear() inlining on Watcom.
  • 3.9.39: Laurence Withers fixed a crash bug in the mode-selector.
  • 3.9.39: Peter Wang removed SIGIO asynch stuff since it's not needed when we have pthreads. Updated documentation to mention dynamic modules. Added configure option to disable threads.
  • 3.9.39: Burton Radons fixed a bug in his dissolve blender.
  • 3.9.39: Eric Botcazou fixed a bug in the menus caused by auto-opening.
  • 3.9.39: Henrik Stokseth updated the makefiles to use -mcpu=pentium instead of the depreciated -mpentium gcc option. Also let the packaging scripts run autoconf and remove hidden or leftover files.
  • 3.9.39: Eric Botcazou cleaned up the windows sound code. Also clarified the code in the core menu function. Corrected a unicode glitch. Removed remaining references to ALLEGRO_NO_FINDFIRST. Added a unified al_find*() interface. Made the Portuguese translation file of the former Portuguese (Br) file. Fixed a few keyboard configuration files. Changed pl.cfg EOLN delimiter to \r\n.
  • 3.9.39: Grzegorz Godlewski contributed a Polish localization patch. Also added support for lower and upper altgr tables.
  • 3.9.39: Eric Botcazou fixed a bug in the keyconf utility caused by the sectionification.
  • 3.9.38: Robert J. Ohannessian added the following to the color convertor: color copy routines needed by the BeOS port, support for cross-conversion between 15-bit and 16-bit colors, support for conversion to 8-bit color, support for rectangles of any width and added two new MMX routines.
  • 3.9.38: Henrik Stokseth rewrote get_gfx_mode_list() likewise rewrote the mode-selector to use get_gfx_mode_list(). Also added fetch_mode_list() functions on the DirectX, VGA, Mode-X and Xtended GFX drivers.
  • 3.9.38: Angelo Mottola fixed problems with SMP on the BeOS port.
  • 3.9.38: Eric Botcazou fixed some problems with the non-MMX code in the color convertor.
  • 3.9.38: Sven Sandberg improved spline() for DRAW_MODE_TRANS
  • 3.9.38: Peter Wang renamed clear() to clear_bitmap(). clear() is still provided for backwards compatibility.
  • 3.9.38: Stepan Roh made fractal generator work under non-Intel processors.
  • 3.9.38: Eric Botcazou made a valid display switch mode of SWITCH_NONE under DOS.
  • 3.9.38: Angelo Mottola made the BeOS port use the new unified color conversion routines.
  • 3.9.38: Peter Wang added check to see if display is local under X11.
  • 3.9.38: Eric Botcazou and Sven Sandberg fixed compilation under Watcom 10.6.
  • 3.9.38: Elias Pschernig contributed an icon resource fixer for the Windows port and added support for shared library under BeOS.
  • 3.9.38: Angelo Mottola added a bfixicon utility.
  • 3.9.38: Stepan Roh made the native Allegro time format of ANSI time_t.
  • 3.9.38: Peter Wang added an ustrtok_r() function.
  • 3.9.38: Robert J. Ohannessian optimized some masked_blits with SSE instructions.
  • 3.9.38: Angelo Mottola did a sound fix for audiostream output and SMP machines and added triple buffering support on the BeOS port.
  • 3.9.38: Angelo Mottola added fetch_mode_list() support to the BeOS fullscreen driver.
  • 3.9.38: Eric Botcazou changed the acceleration scheme for the mouse under Windows.
  • 3.9.38: Peter Wang added fetch_mode_list() support to the svgalib driver.
  • 3.9.38: Peter Wang added pthread timer and removed dependancy to SIGALRM.
  • 3.9.38: Henrik Stokseth added Windows XP detection.
  • 3.9.38: Andreas Kluge fixed a bug with volume setting in the DOS Soundscape driver.
  • 3.9.38: Angelo Mottola rewrote the BeOS sound driver to use the BSoundPlayer class.
  • 3.9.38: Robert J. Ohannessian added SSE and SSE2 detection.
  • 3.9.38: Connelly Barnes fixed a bug with the DirectSound pan.
  • 3.9.38: Eric Botcazou added support of switch modes to the test program.
  • 3.9.38: Eric Botcazou modified the Windows switch mechanism.
  • 3.9.38: Angelo Mottola added fullscreen display switching support and did many fixes and cleanups on the BeOS port.
  • 3.9.38: Henrik Stokseth added code to get more os info under unix.
  • 3.9.38: Nimrod Abing fixed a bug in the config routines related to the NULL section.
  • 3.9.38: Eric Botcazou fixed a crash in the Windows windowed driver on fast machines.
  • 3.9.38: Ronaldo Hideki Yamada did a large update on the PowerMac port and added a midi driver.
  • 3.9.38: Henrik Stokseth generalised the support for processor specific optimisations in some makefiles.
  • 3.9.38: Evert Glebbeek put set_gfx_mode on a diet and added config entry for specifying the card to use for GFX_AUTODETECT_WINDOWED.
  • 3.9.38: Robert J. Ohannessian made blit not convert between colordepths for video bitmaps. (for AllegroGL)
  • 3.9.38: Peter Wang made fix_filename_slashes() handle both types of slashes.
  • 3.9.38: Grzegorz Adam Hankiewicz implemented a switch in makedoc to check for long (>77) doc lines.
  • 3.9.38: Owen Rudge contributed a DLL version resource script.
  • 3.9.38: Sven Sandberg made the rotation functions faster, more accurate and working with any type of bitmap. Also removed rotate_scaled_sprite_flip().
  • 3.9.38: Angelo Mottola added fetch_mode_list() support to DGA2.
  • 3.9.38: David A. Capello made test program use transparent polygon types.
  • 3.9.38: Owen Rudge contributed a mkdata.bat script.
  • 3.9.38: Grzegorz Adam Hankiewicz added reload_config_texts().
  • 3.9.38: Eric Botcazou added an enhanced building mechanism for DLL export definition files.
  • 3.9.38: Eric Botcazou added a new unicode example program and did a ton of small fixes.
  • 3.9.37: Johan Peitz fixed and enhanced the Win32 joystick driver.
  • 3.9.37: Sven Sandberg added Ctrl + arrow keys to d_edit_proc().
  • 3.9.37: Eric Botcazou changed the color key for the Windows overlay driver to bright pink.
  • 3.9.37: Eric Botcazou reverted some changes he made to the timer core last release which were causing problems with the MIDI player, and removed the Windows multithreaded timer driver.
  • 3.9.37: Henrik Stokseth made some updates to the OS detection code, and added a os_multitasking variable.
  • 3.9.37: Eric Botcazou fixed a problem in the config routines, where entries in the NULL section were hiding duplicate entries in other sections.
  • 3.9.37: Eric Botcazou made the setup program use Unicode functions.
  • 3.9.37: Henrik Stokseth unified the fix* scripts, and gave them new options.
  • 3.9.37: Peter Wang added support for dynamically loaded modules under Unix. The SVGAlib, ALSA digital, ALSA MIDI, ESD and DGA2 drivers will be built as modules when possible. This removes external dependencies on the main library and improves binary transportability under Linux.
  • 3.9.37: Eric Botcazou made many changes and bug fixes to the Unicode string functions, and their use in the library. The old functions now behave exactly like the libc equivalents, while the new functions (the 'z' functions) behave more sanely. This change affects most code which uses the Unicode functions.
  • 3.9.37: Bertrand Coconnier changed the recently merged scene rendering API, fixed a bug, and provided a new example program. The API change will affect all code which uses the scene functions.
  • 3.9.37: Laurence Withers wrapped registration of the bitmap file types in a constructor. Where constructors are supported, this should reduce the executable size when statically linking (unless you use the bitmap loaders, of course).
  • 3.9.37: Ben Davis modified the set_volume_per_voice scale. Please see the docs for this function if you have used it in the past.
  • 3.9.37: Eric Botcazou worked around a DOS mouse bug under Win2k.
  • 3.9.37: Eric Botcazou added VGA Mode 13h support under DirectX 5 or greater.
  • 3.9.37: Henrik Stokseth added a get_gfx_mode_list() function, and the implementation of it for the VESA driver.
  • 3.9.37: Eric Botcazou and Annie Testes toiled hard to avoid buffer overflows (particularly with regards to the Unicode functions).
  • 3.9.37: Eric Botcazou fixed a mouse mickeys bug and cleaned up the input subsystem under Windows.
  • 3.9.37: Eric Botcazou made two minor changes in the handling of index 0 in paletted modes.
  • 3.9.37: Eric Botcazou added a transparency preserving feature to the grabber and dat utility.
  • 3.9.37: Eric Botcazou fixed a crash when alt-tabbing in page flipping under Windows.
  • 3.9.37: Peter Wang added gui_menu_draw_menu and gui_menu_draw_menu_item to allow customising the look of the GUI menus (to a certain extent).
  • 3.9.37: Angelo Mottola added support for the new GFX_AUTODETECT_FULLSCREEN and GFX_AUTODETECT_WINDOWED constants, which we _all_ wholeheartedly agreed upon :-)
  • 3.9.37: Eduard Bloch made config vars which exist but are empty return defaults.
  • 3.9.37: Elias Pschernig added a COLORCONV_KEEP_TRANS mode.
  • 3.9.37: Henrik Stokseth added support for compiling with Cygwin. It works in Mingw compatibility mode.
  • 3.9.37: Angelo Mottola made GUI submenus automatically open when the mouse hovers for long enough. (This was an old patch that finally got merged.) Eric made some related modifications to it later.
  • 3.9.37: Eric Botcazou made clear_keybuf() not clear the key[] array.
  • 3.9.37: Sven Sandberg added a --quick option to fix scripts.
  • 3.9.37: Angelo Mottola did _loads_ of work on the QNX port (much too much to document here).
  • 3.9.37: Eric Botcazou made the Win32 asm color conversion code for windowed drivers available for other ports, and added a few other converters. Isaac Cruz added one too.
  • 3.9.37: Eric Botcazou restructured the config file format. Some previously unsectioned variables are now in sections.
  • 3.9.37: George Foot added a threading system to handle asynchronous events, instead of using SIGALRM (under Unix).
  • 3.9.37: George Foot fixed some problems with pack_fgets().
  • 3.9.36: Eric Botcazou made it so that set_keyboard_rate(0, 0) will disable keyboard repeat, as in the documentation.
  • 3.9.36: Annie Testes added font_height, render_char, char_length hooks to FONT_VTABLE.
  • 3.9.36: Eric Botcazou made some minor changes related to AllegroGL in the window management code, and fixed two little mouse bugs Javier Gonzalez had found (both under Windows).
  • 3.9.36: Eric Botcazou added a get_desktop_resolution() function for Windows and X. Joshua Haberman added a BeOS version.
  • 3.9.36: Angelo Mottola comprehensively started a QNX port.
  • 3.9.36: Robert Ohannessian corrected src/dest ordering in additive blenders.
  • 3.9.36: Eric Botcazou improved support of external windows in Windows.
  • 3.9.36: Peter Wang updated the SVGAlib driver for version 2.
  • 3.9.36: Peter Wang added a fullscreen version of the X-Windows graphics driver. The original was by Benjamin Joel Stover.
  • 3.9.36: Peter Wang made grabber use file_select_ex(). This is just here so you don't get a shock :-)
  • 3.9.36: Eric Botcazou fixed some small bugs in the DirectSound input code.
  • 3.9.36: Eric Botcazou fixed the NumLock state in X not matching keyboard LEDs.
  • 3.9.36: Eric Botcazou reenabled the multi-threaded timer under Windows.
  • 3.9.36: Eric Botcazou and Javier Gonzalez made the keyboard repeat system more efficient.
  • 3.9.36: Eric Botcazou fixed some asm blitters, and also a bug with changing timer speeds.
  • 3.9.36: Peter Wang made the keypad return / * - + ASCII values even if NumLock is off, under Linux console.
  • 3.9.36: Ronaldo Hideki Yamada made a big update of the Mac port, including some new PPC files.
  • 3.9.36: The GGI driver was removed, due to its inability to actually work. It is no longer supported, unless someone rewrites it.
  • 3.9.36: Eric Botcazou fixed a problem with the GDI driver when compiled with MSVC.
  • 3.9.36: Some MIDI fixes by Javier Gonzalez and Eric Botcazou.
  • 3.9.36: Grzegorz Adam Hankiewicz improved the fb.modes line parsing function in the fbcon driver.
  • 3.9.36: Grzegorz Adam Hankiewicz changed the behaviour of GFX_SAFE. This means that "set_gfx_mode(GFX_SAFE, ...)" now returns an error if it is unable to set a video mode, just like any other video driver.
  • 3.9.36: Eric Botcazou fixed volume setting in Windows.
  • 3.9.36: Eric Botcazou added DirectX 3 compatibility.
  • 3.9.36: Nick Kochakian added input routines to the DirectSound driver. It was also modified by Javier Gonzalez.
  • 3.9.35: Eric Botcazou made Windows restore the original sound volume after an Allegro program quits.
  • 3.9.35: Eric Botcazou fixed sample looping in DirectSound driver.
  • 3.9.35: Grzegorz Adam Hankiewicz solved some color problems in the demo game.
  • 3.9.35: Angelo Mottola implemented a close button hook for X11.
  • 3.9.35: Eric Botcazou fixed _the_ Windows 2000 keyboard bug.
  • 3.9.35: Eric Botcazou made some changes to the locking/unlocking mechanism in the Windows port.
  • 3.9.35: Laurence Withers made some modules avoid linking dependencies.
  • 3.9.35: Javier Gonzalez added close button support for Windows.
  • 3.9.35: Eric Botcazou improved mouse handling in the GFX_GDI driver and fixed some other mouse glitches.
  • 3.9.35: Peter Wang made set_mouse_sprite(NULL) regenerate the default arrow bitmap (using the current palette).
  • 3.9.35: Eric Botcazou made hardware accelerated primitives stop when the user switches out in Windows.
  • 3.9.35: Tom St Denis fixed clipping of transparent objects.
  • 3.9.35: Eric Botcazou and Javier Gonzalez improved switching in Windows and other things.
  • 3.9.35: Peter Wang made the Linux joystick driver use standard constants.
  • 3.9.35: Sven Sandberg changed the Z-buffer API.
  • 3.9.35: Peter Wang made the default mouse sprite independent of the palette in 8 bpp modes.
  • 3.9.35: Bertrand Coconnier added documentation for the P3D merge.
  • 3.9.35: Angelo Mottola fixed desktop_color_depth() and added window close button support for the BeOS port.
  • 3.9.35: Ben Davis added the set_window_close_button() and set_window_close_hook() framework.
  • 3.9.35: Peter Wang exposed the mouse_sprite, mouse_x_focus and mouse_y_focus variables.
  • 3.9.35: Robert Ohannessian and Javier Gonzalez fixed bad clearing of subbitmaps.
  • 3.9.35: Peter Wang renamed GFX_XDFS to GFX_XDGA_FULLSCREEN.
  • 3.9.35: Henrik Stokseth updated the cross-compilation system.
  • 3.9.35: Tomohiko Sugiura added some keys and renamed some JP keys.
  • 3.9.35: Eric Botcazou added a DirectDraw2 interface, with support for refresh rates.
  • 3.9.35: Bertrand Coconnier merged in Calin Andrian's P3D library.
  • 3.9.35: Javier Gonzalez made allegro_message() use the title from set_window_title() in Windows.
  • 3.9.35: Andreas Kluge fixed division bugs in the fix class.
  • 3.9.35: Stepan Roh documented the FA_* flags.
  • 3.9.35: Peter Wang added hooks to allow overriding the look of standard dialogs.
  • 3.9.35: Peter Wang changed X window placement and mapping behaviour.
  • 3.9.35: David A. Capello made dotted_rect() avoid bank switches.
  • 3.9.35: Eric Botcazou fixed a freezing problem under Window with locking/unlocking bitmaps under heavy load. He received help tracking down the bug from Javier Gonzalez.
  • 3.9.35: Stepan Roh fixed a bug with FA_RDONLY constant under Unix.
  • 3.9.35: Eric Botcazou cleaned up the Windows graphics subsystem.
  • 3.9.35: "Sask Allegro" added support for more than two joysticks in the Windows port.
  • 3.9.34: Ben Davis made close button in Windows windowed modes not simulate Escape key, in preparation for new behaviour (in next WIP).
  • 3.9.34: Laurence Withers fixed a problem with accents in keyconf.
  • 3.9.34: Javier Gonzalez added DIGMID to the Windows MIDI drivers list.
  • 3.9.34: Eric Botcazou cleaned up the DirectDraw subsystem.
  • 3.9.34: Eric Botcazou made the DirectDraw overlay driver comply with page flipping and triple buffering code, amongst other things.
  • 3.9.34: Bertrand Coconnier improved subtexel accuracy for texture mapping.
  • 3.9.34: Javier Gonzalez corrected mouse movement speed in Windows.
  • 3.9.34: Ben Davis adapted polygon functions to handle two coincident vertices, and changed and clarified texture coordinate alignment in code and documentation.
  • 3.9.34: Grzegorz Adam Hankiewicz fleshed out the docs for Unicode functions, adapting from djgpp and gcc docs.
  • 3.9.34: Eric Botcazou fixed a triple buffering problem in the DirectDraw accelerated driver.
  • 3.9.34: Henrik Stokseth added support for cross-compilation in the mingw32 build.
  • 3.9.34: Grzegorz Adam Hankiewicz updated more examples for GFX_SAFE.
  • 3.9.34: Ben Davis added set_volume_per_voice(), made silent voices continue playing and fixed other minor bugs.
  • 3.9.34: Ben Davis fixed a bug in create_rgb_table().
  • 3.9.34: Angelo Mottola added display switching routines for BeOS and fixed some bugs.
  • 3.9.34: Laurence Withers updated documentation about `const'.
  • 3.9.34: Ronaldo Hideki Yamada contributed a macintosh port of Allegro.
  • 3.9.34: Grzegorz Adam Hankiewicz changed and documented new GFX_SAFE behaviour (that color depth is undefined), updated the fbcon driver to take advantage of this and updated example programs.
  • 3.9.34: Peter Pavlovic fixed a bug caused by file selector stretching.
  • 3.9.34: Bertrand Coconnier fixed bugs related to poly3d(); removed never-called C versions of scanline functions for POLYTYPE_FLAT and non-8bpp POLYTYPE_GCOL; and made clip3d() and clip3d_f() functions compliant with Z-buffered polygons.
  • 3.9.34: Stepan Roh added C version of masked_stretch_blit().
  • 3.9.34: Angelo Mottola did more work on BeOS: hardware acceleration (rect, hline, vline, clear_to_color, blit); mouse fix in windowed mode; desktop_color_depth(); yield_timeslice();
  • 3.9.34: Peter Wang retroactively updated CHANGES and AUTHORS from late 3.9.33 to present using CVS logs and email archives, and possibly messed up.
  • 3.9.34: Angelo Mottola added a BeOS windowed driver (originally by Peter Wang), a BeOS MIDI driver, mouse wheel support under BeOS and made many bug fixes and changes to other BeOS code and documentation.
  • 3.9.34: Laurence Withers fixed dat2s output of fonts for new font subsystem.
  • 3.9.34: Peter Wang made the SVGAlib driver more robust.
  • 3.9.34: Peter Wang changed the way Intellimouse protocols are selected under Linux console.
  • 3.9.34: Eric Botcazou added file_select_ex and reverted file_select to old behaviour.
  • 3.9.34: Laurence Withers added ugetcx() function.
  • 3.9.34: Laurence Withers designed and implemented a new FONT structure, which should provide many advantages over the old one.
  • 3.9.34: Eric Botcazou made more fixes to Windows code.
  • 3.9.34: Bertrand Coconnier added a z-buffer rendering mode for 3D polygons (derived from Calin Andrian's P3D library) and an example program for it.
  • 3.9.34: Michael Bukin added customization for keycode to scancode mapping in X.
  • 3.9.34: Peter Wang added mouse wheel support to d_textbox_proc and d_slider_proc, and made file selector dialog stretch.
  • 3.9.34: Tom Fjellstrom added an ALSA MIDI driver.
  • 3.9.34: Eric Botcazou made some changes to the Windows windowed driver.
  • 3.9.34: Grzegorz Adam Hankiewicz updated the documentation and the makedoc program to produce better .texi output. The new version works very well with the texi2dvi program, which produces fine ready to print device independent output. Also documented the new unix makefile targets.
  • 3.9.34: George Foot added --env option to allegro-config script.
  • 3.9.34: Benjamin Stover made some vararg fixes in unicode.c and added a workaround for missing defines in fbcon.c.
  • 3.9.34: Robin Burrows added a Windows waveOut sound driver.
  • 3.9.34: Eric Botcazou changed desktop_color_depth() for Windows.
  • 3.9.34: Angelo Mottola added line switching and refresh rate support to DGA2 driver.
  • 3.9.34: Bertrand Coconnier added scanline subdivisions and fixed 3D polygon drawing.
  • 3.9.34: Angelo Mottola added BeOS joystick driver.
  • 3.9.34: Angelo Mottola added DGA2 driver.
  • 3.9.34: Robin Burrows added Windows sound driver using Allegro mixer.
  • 3.9.34: Stepan Roh added workaround for fceil defined in Irix headers.
  • 3.9.34: Michael Bukin changed DGA screen clearing.
  • 3.9.34: Tomohiko Sugiura added a more aggressive Sidewinder driver.
  • 3.9.34: Tomohiko Sugiura added three Japanese keys.
  • 3.9.34: Stepan Roh made C functions const-correct.
  • 3.9.34: Bertrand Coconnier fixed blending in atex_lit scanline functions.
  • 3.9.34: Michael Bukin modified text_mode to return previous mode.
  • 3.9.34: Peter Pavlovic fixed scrollbar display in grabber and improved scrolling in GUI objects.
  • 3.9.34: anarko made GUI objects restore textmode.
  • 3.9.34: Laurence Withers added font destroy hook.
  • 3.9.34: Vincent Penquerc'h modified the mouse button press/release events so they have higher priority than double-click events.
  • 3.9.34: Eric Botcazou improved colormap handling in XDGA.
  • 3.9.34: Robin Burrows provided a new page flipping code for the DirectDraw subsytem, which now works on every graphic card.
  • 3.9.33: Henrik Stokseth updated the mingw32 makefile, the documentation and sent in some other related fixes and updates. You will never again need MSVC to compile the Allegro DLLs. ;o)
  • 3.9.33: Peter Puck contributed some updates to Allegro's win32 code which got the native mingw32 build fully working.
  • 3.9.33: Michael Bukin changed the auto-repeat handling in X, sched_yield handling for Unix, fixed _add_exit_func, and added list of active dialogs to the GUI.
  • 3.9.33: Vincent Penquerc'h sped up the C versions of the RLE sprite drawing routines by quite a bit.
  • 3.9.33: Peter Wang improved TGA palette loading.
  • 3.9.33: Laurence Withers made more functions const-correct.
  • 3.9.33: Isaac Cruz moved Windows bitmap locking to a separate .S file, changed the update logic for the windowed driver, and added an accelerated vline implementation.
  • 3.9.33: Stephen Kittelson fixed a bug in pckeys.c, and changed the ASCII values returned for a few weird key combinations.
  • 3.9.33: Peter Wang made various functions const-correct.
  • 3.9.33: Peter Pavlovic made aesthetic modifications to the GUI menu system.
  • 3.9.33: Javier Gonzalez suggested that the file and mode selector dialogs should use popup_dialog.
  • 3.9.33: Vincent Penquerc'h added the install-gzipped-man makefile target, patched some of the EINTR handling, and made the OSS driver detect whether the device is 16 bit or not.
  • 3.9.33: Peter Pavlovic modified the Slovak keyboard mapping and made the file selector detect available drives in Windows.
  • 3.9.33: Peter Wang added a sound (output only) driver for BeOS.
  • 3.9.33: Sven Sandberg fixed a typo in the definition of ustrdup, added the uwidth_max function, provided the d_yield_proc function, and made various dialogs use it.
  • 3.9.33: Michael Bukin made the DGA driver clear video memory and centre the screen, if it's not fullscreen.
  • 3.9.33: Eduard Bloch suggested better ways to find the executable in Unix.
  • 3.9.33: Andrew Geers added flipped rotated sprites.
  • 3.9.33: George Foot made the Unix makefile work for non-root users.
  • 3.9.33: Grzegorz Adam Hankiewicz made language config files be forced to lower case.
  • 3.9.33: Grzegorz Adam Hankiewicz added documentation for findfirst(), findnext(), and findclose(), and corrected the documentation for get_executable_name().
  • 3.9.33: Stepan Roh made patches to allow compilation on IRIX.
  • 3.9.33: John Harger made a change to improve the stability of AllegroGL in Windows.
  • 3.9.33: Sven Sandberg fixed a bug in the plain C 16bpp stretched blitter.
  • 3.9.33: George Foot fixed a bug in the i386 8bpp masked blit routines, reported by Damian Yerrick.
  • 3.9.33: Eduard Bloch fixed a freeze caused by the ESD detection code.
  • 3.9.33: Vincent Penquerc'h added mouse button press/release events to the GUI system.
  • 3.9.33: Peter Wang solved a conflict with SVGAlib.
  • 3.9.33: Vincent Penquerc'h added the XCRP and YCRP properties to bitmap objects in datafiles.
  • 3.9.33: Vincent Penquerc'h made the GUI system not send MSG_DRAW to hidden objects.
  • 3.9.33: Chris La Mantia pointed out that his code for textprintf_right had mutated somehow.
  • 3.9.33: Peter Wang added a workaround for a mouse motion reporting bug in some X servers.
  • 3.9.33: Eric Botcazou altered the DGA code to work better in 32bpp modes.
  • 3.9.33: Daniel Nilsson tweaked exstars and exlights
  • 3.9.33: Isaac Cruz fixed a nasty bug with subbitmap locking, and added desktop_color_depth and yield_timeslice support to the Windows version.
  • 3.9.33: Peter Cech made uisspace() recognise non-ASCII space characters.
  • 3.9.32: S.Sakamaki added a function for controlling the refresh rate when using the DOS VESA 3.0 driver (this could also be supported by some other drivers if anyone wants to implement that).
  • 3.9.32: S.Suzuki added DOS drivers for the IF-SEGA /PCI, /PCI2, and /ISA joystick interface cards.
  • 3.9.32: Fabrizio Gennari added DOS drivers for multisystem joysticks with 9-pin connectors (Atari, Commodore 64, MSX).
  • 3.9.32: Peter Pavlovic improved the support for accented character maps in the keyboard driver.
  • 3.9.32: Sven Sandberg optimised the GUI listbox scrolling to skip redraws if it can't keep up with the update speed.
  • 3.9.32: Olly Betts did some work to make cross-compiling the djgpp version work on Linux.
  • 3.9.32: Isaac Cruz improved the windowed mode ddraw driver, adding support for many different color depth conversions.
  • 3.9.32: Vincent Penquerc'h added an update selection function to the grabber.
  • 3.9.32: many bugfixes from various people.
  • 3.9.32: zipup.sh now generates dependencies entirely using standard Unix tools and gcc, so it can setup all the supported platforms without needing those compilers to be available (ie. I can create Watcom, BeOS, and Mingw32 dependencies all from my Linux machine). This does require a bit of cooperation from the different targets, though: they have to set up their "make depend" target to override the standard gcc defines, and wrap any non-standard header includes with "#ifndef SCAN_DEPEND".
  • 3.9.32: fixed (I hope :-) bug with non-GMT timezones in the datafile update code.
  • 3.9.32: rewrote the Unicode usprintf() to piggyback on libc when converting floating point data (too hard to get this right ourselves :-)
  • 3.9.31: Henrik Stokseth did some work on a native Mingw32 build. This is currently incomplete, and unlikely to work right now since there have been other changes in the Windows code since the version he started from. At the moment this version is statically linked, using makefile.mgs, and makefile.mgw still exists for the MSVC-piggyback version. The ultimate goal is to get this native version building as a DLL in addition to statically linked, at which point we can merge both makefiles into makefile.mgw and remove makefile.mgs. Oh yeah, and there are currently no docs for the native version.
  • 3.9.31: Greg Hackmann contributed a Borland C++ Builder port. Like the RSXNT and Mingw32 versions, this is a client for the MSVC DLL, and not able to compile Allegro directly itself, but allows you to build Allegro programs using the Borland compiler.
  • 3.9.31: Robert Ohannessian added MMX optimisation for the 8 and 16 bit clear() functions, and Jose Antonio Luque optimised the 16 bit blit() and masked_blit() routines.
  • 3.9.31: Vincent Penquerc'h added a yield_timeslice() function (currently implemented in DOS and Unix).
  • 3.9.31: added a desktop_color_depth() function (currently only implemented in X: a Windows version will follow).
  • 3.9.31: Isaac Cruz added support for windowed modes in color depths other than the current Windows desktop, and hardware accelerated system bitmaps.
  • 3.9.31: Jose Antonio Luque improved the Windows joystick driver.
  • 3.9.31: James Hyman added support for dithering truecolor down to paletted images.
  • 3.9.31: Chris La Mantia added textout_right(), textprintf_right(), and textprintf_justify() functions.
  • 3.9.31: Sven Sandberg added a ustrrchr() function, and improved the usprintf() handling of large floating point values.
  • 3.9.31: Peter Pavlovic added a Slovak keyboard mapping and message translation.
  • 3.9.31: Manni Heumann fixed some problems with the German keyboard mapping.
  • 3.9.31: Michael Bukin improved the X keyboard and mouse handling, and fixed some problems with building on non-GNU Unix systems.
  • 3.9.31: many bugfixes and tweaks from various people (sorry, my typing patience has run out so you don't get a full list :-)
  • 3.9.31: Peter Wang added input support to the Linux OSS sound driver.
  • 3.9.31: David Kuhling optimised the i386/gcc fsqrt() code, and added an fhypot() routine.
  • 3.9.30: fixed the double XOR that was making datafile passwords so easy to reverse. The new code can still read old-style encrypted files, but data written by this version can't be accessed by older copies of Allegro.
  • 3.9.30: made load_datafile(), load_datafile_object(), and the file.dat#object syntax work correctly in all possible combinations.
  • 3.9.30: Vincent Penquerc'h added a scare_mouse_area() function.
  • 3.9.30: changed the DirectX surface locking mechanism, to improve the performance of hardware accelerated drawing.
  • 3.9.30: George Foot improved the Linux LED code, and made the internal X driver state visible via xalleg.h.
  • 3.9.30: added EINTR retry handling to read/write calls. I hope I got this right: if anyone who properly groks this stuff could check over file.c, that would be cool.
  • 3.9.30: made the Windows mouse driver work correctly in windowed mode.
  • 3.9.30: fixed various problems with Windows foreground/background switching (keys were getting stuck down, timers weren't being paused, and not all the right switching modes were being reported to the caller).
  • 3.9.30: made the X keyboard handler release all keys when it loses the input focus, to avoid stuck buttons when you alt+tab between windows.
  • 3.9.30: made the allegro-lib script arguments compatible with the standard used by GTK, ESD, etc, and renamed it to allegro-config. This changes the syntax for linking Allegro programs on Unix: see readme.uni for details of the new method.
  • 3.9.30: George Foot improved the Unix shared library system.
  • 3.9.30: Joerg Rueppel added a find_datafile_object() function.
  • 3.9.30: Peter Wang improved the SVGAlib driver.
  • 3.9.30: Peter Wang improved the Linux joystick driver.
  • 3.9.29: made the Windows code agree with other platforms about how video bitmaps are supposed to behave.
  • 3.9.29: fixed some problems with the Windows mouse wheel support.
  • 3.9.29: added set_write_alpha_blender(), set_add_blender() and create_blender_table() functions, and made the 32 bit version of draw_trans_sprite() able to use 8 bit source images in conjunction with set_write_alpha_blender(). In addition to being generally useful, using these routines makes the sources for my SpeedHack entry much smaller :-)
  • 3.9.29: added uninstall targets to the Linux makefile.
  • 3.9.29: made the X windowed mouse driver hide the Allegro cursor when the mouse moves out of our window.
  • 3.9.29: added a simple timer delay emulation of vsync() to the X code, so that eg. the demo worms game runs sensibly.
  • 3.9.29: Isaac Cruz added a GFX_DIRECTX_WIN driver.
  • 3.9.29: Keith Gerdes made some more improvements to the DirectX overlay driver.
  • 3.9.29: Andrew Geers added scrolling support to the grabber image viewer.
  • 3.9.29: Peter Wang added an alternative X DGA driver, that includes mode switching support to run in fullscreen mode.
  • 3.9.29: Peter Wang added a MSG_WHEEL event to the GUI, and made d_list_proc() use it.
  • 3.9.29: Lucas Vignoli Reis added a Portuguese (Brazil) message translation and keyboard mapping.
  • 3.9.29: Peter Wang added a Linux OSS MIDI driver for FM synth devices, and mixer support for the OSS digital driver.
  • 3.9.29: George Foot added scripts for building various Linux distribution formats.
  • 3.9.29: Michael Bukin fixed the portability problems in quantize.c.
  • 3.9.29: added a zipwin.sh script for making Windows binary distributions, including a batch file that can compile the MSVC support programs without having any GNU tools installed.
  • 3.9.29: fixed bug with color font rendering in the Windows version.
  • 3.9.29: added hardware accelerated rectfill() and hline() to the Windows version, and fixed a couple of accel related bugs (clears were being clipped wrongly, and it was claiming to support XOR drawing even though that isn't supported).
  • 3.9.29: Michael Bukin fixed bug with X drawing onto screen sub-bitmaps.
  • 3.9.28: various documentation updates.
  • 3.9.28: added parameter autodetection to the Unix OSS sound driver.
  • 3.9.28: made it possible to nest calls to the Unix for_each_file() routine.
  • 3.9.28: added a load_datafile_callback() function.
  • 3.9.28: rationalised the sound config variables, so they can be shared between drivers more easily. For instance sb_freq has been renamed to sound_freq.
  • 3.9.28: Antti Koskipaa added a DOS driver for WSS (Windows Sound System) cards.
  • 3.9.28: the audiosteam code is now able to merge multiple buffers into a single larger one, so it will still work correctly even if the user supplies a buffer smaller than the current soundcard transfer size. You can even play streams with single byte buffers now, as long as you refill them often enough!
  • 3.9.28: made the Windows timer code more robust, so it will no longer lock up when you install extremely high frequency callbacks.
  • 3.9.28: Teijo Hakala added wheel support to the Windows mouse driver.
  • 3.9.28: Peter Wang added wheel support to the X mouse driver.
  • 3.9.28: Andrew Geers added -ppassword and -nosound options to the grabber.
  • 3.9.28: Keith Gerdes fixed the DirectDraw overlay mode driver.
  • 3.9.28: Isaac Cruz fixed the bug with accelerated drawing onto sub bitmaps of DirectDraw surfaces.
  • 3.9.28: Peter Wang added banked mode support to the SVGAlib driver.
  • 3.9.28: Peter Wang fixed some problems with the ESD sound driver, and added an ALSA driver.
  • 3.9.28: palette fading speed is now timer regulated, to avoid problems with some systems (eg. DGA with non-matching color depth) where it can be excessively slow.
  • 3.9.28: fixed a couple of different overflow bugs that were causing timers to run slow on heavily loaded Unix systems.
  • 3.9.28: added a display of author credits to the demo game.
  • 3.9.28: changed the info page installation system. It now creates a dir file in the same directory as the info page, rather than messing around with symlinks, and autoconf is used to locate the install-info program.
  • 3.9.28: added an allegro-lib script to the Unix installation, which can be run by makefiles to find the right linker commandline for building Allegro programs.
  • 3.9.28: added a manpage output format to the makedoc utility. It doesn't work terribly well with apropos due to the lack of a one-line summary for each function, but the basic formatting seems to be ok: please let me know if you see any problems.
  • 3.9.28: patches from George Foot for Linux console handing, keyboard, and filename manipulations.
  • 3.9.28: many improvements by Michael Bukin, in particular enhanced performance in X, better X mouse behaviour, and DGA graphics support.
  • 3.9.27: Robert J. Ragno made some improvements to the Wingman, PSX, and throttle joystick input code.
  • 3.9.27: Peter Wang added wheel input support to the Linux mouse code (this shows up as a new mouse_z state variable).
  • 3.9.27: Patrick Hogan made Windows audiostreams work properly.
  • 3.9.27: Sven Sandberg optimised the spline routines.
  • 3.9.27: Tomohiko Sugiura added KEY_YEN and KEY_YEN2 Japanese keys to the input handler.
  • 3.9.27: Chris Robinson wrote a fixed point version of clip3d_f(), called (surprise!) clip3d().
  • 3.9.27: Sven Sandberg improved the file selector sorting algorithm.
  • 3.9.27: Henrik Stokseth improved the OS detection in the Windows lib.
  • 3.9.27: Sven Sandberg made more accurately rounded lookup tables for the fixed point trig routines.
  • 3.9.27: George Foot made the fbcon driver reset the palette on exit.
  • 3.9.27: much new X code from Michael Bukin: this stuff is working brilliantly now!
  • 3.9.27: added the X library path to the Linux liballeg.a wrapper. I think I prefer Michael's idea of having a script to return this info, though, so perhaps we should change across to doing it that way.
  • 3.9.27: fixed various bugs in both the C and i386 RLE sprite code (mostly relating to lit modes and hicolor formats).
  • 3.9.27: front-ported various fixes from the 3.12 release, to make WARNMODE=1 compile cleanly with gcc 2.95.
  • 3.9.27: Knut Pape improved the Mingw32 readme file.
  • 3.9.26: rewrote the DOS Sidewinder driver, after powerjaw sent me a pad to test it with. It still doesn't work for me in DOS mode, but it is ok under Windows, which is better than before, and as good as any of the other Sidewinder code that I've been able to locate. If anyone has or knows of code that works better than this, please let me know!
  • 3.9.26: more flexible mode flags for set_color_conversion().
  • 3.9.26: Robert J. Ragno added a driver for Gravis GrIP devices.
  • 3.9.26: Gorka Olaizola added a Redhat RPM .spec file.
  • 3.9.26: Stepan Roh updated the Czech translation and added multiple codepage support to the textconv utility, and a Unicode-aware ustrtod() function.
  • 3.9.26: added ustrdup() to the Unicode support functions.
  • 3.9.26: Sven Sandberg optimised the gcc fixed point math routines to collapse constant expressions at compile time.
  • 3.9.26: Stefan T. Boettner added a proper Linux SVGAlib driver.
  • 3.9.26: several tweaks from Vincent Penquerc'h (added a datafile merge function to the grabber, GUI bugfixes, optimised spline calculation, fix for 24 bit version of the C drawing code).
  • 3.9.26: Linux patches from Michael Bukin improve the OSS sound driver, SIGALRM handling, and X keyboard driver.
  • 3.9.26: many Linux patches from George Foot (fixes to the mouse driver, shared library and configure script, and assorted other stuff).
  • 3.9.25: fixed pckeys.c to leave sensible data in the key[] array when doing numeral vs. arrow key numlock fakery.
  • 3.9.25: fixed a bunch of problems with the SWITCH_BACKGROUND mode (I'd stupidly forgotten to disable a lot of graphics driver functions that could do bad things if called when the Allegro console isn't active).
  • 3.9.25: added pivot_sprite() and pivot_scaled_sprite() functions (thanks to Matt Jallo for the suggestion).
  • 3.9.25: added ustrerror() to the standard Unicode support functions.
  • 3.9.25: fixed the d_edit_proc() GUI object to handle shift+tab focus movement properly.
  • 3.9.25: lots of Linux patches from George Foot (proper fbcon mode setting, different mouse types and setup program support for configuring them, fixes to the shared library support, exedat no longer destroys the file permissions, and probably some other stuff that I forgot about).
  • 3.9.24: assorted bugfixes to the Linux fbcon and sound code (this is mostly an emergency release because these were broken in 3.9.23).
  • 3.9.24: James Arthur wrote some docs for the Photoshop-style truecolor blender routines.
  • 3.9.23: Michael Bukin added an OSS sound driver to the Linux code, and the beginnings of an ESD driver.
  • 3.9.23: many Linux patches from George Foot, including shared library support.
  • 3.9.23: Ole Laursen made the Unicode utolower() and utoupper() functions understand the entire 16 bit character set.
  • 3.9.23: Pavlos Touboulidis made file_select() able to include or exclude files based on their attributes.
  • 3.9.23: the d_check_proc() GUI object can now print the text to the right of the check, selected by having a non-zero d1 field.
  • 3.9.23: changed my mind about how GFX_SAFE should work, and removed the color depth emulation bodges. Now, the GFX_SAFE driver may simply change the color depth if it doesn't like what you are requesting, and it is up to the caller to deal with this.
  • 3.9.23: fixed problems with MMX polygon rendering code in the MSVC version.
  • 3.9.23: added a strictwarn option to the configure script, and fixed everything that it moaned about. The warnings still aren't all that strict: at some point I want to sit down and make it build cleanly with -W, as well as -Wall -Werror.
  • 3.9.22: fixed some potential race conditions introduced by my previous fixes to the Windows timer code.
  • 3.9.22: made set_display_switch_callback() able to install multiple hook functions, added a remove_display_switch_callback() routine, and wrote an exswitch example program.
  • 3.9.22: adjusted MSVC inline asm syntax in an attempt to work around compiler version conflicts.
  • 3.9.22: more flexible GFX_SAFE system. As well as defining fixed safe values for each platform, you can now leave out those definitions to get zeros passed through to the actual hardware drivers, and if your driver sets a color depth other than the requested one, graphics.c will hook up some emulation routines so that everything still works in a sensible way.
  • 3.9.22: George Foot added a scancode to ASCII conversion function to the keyboard driver (implemented for DOS, Windows, Linux, and X). This is needed to handle alt+key input sensibly when using unusual mappings like the Dvorak layout.
  • 3.9.22: Linux patches from George add better console switching, shared library support, and various other nice things.
  • 3.9.22: Windows patch from Stefan adds much cool new stuff, including windowed mode support.
  • 3.9.22: Peter Wang made the Linux GGI driver work properly.
  • 3.9.22: Johan Venter made some more improvements to the RSXNT and Mingw32 makefiles.
  • 3.9.22: updated the Watcom makefile to allow manual override of the 10.6 vs. 11.0 version detection, in case it guesses wrong.
  • 3.9.21: Windows patch from Stefan adds support for the new screen mode switching system.
  • 3.9.21: more BeOS patches from Jason Wilkins.
  • 3.9.21: Johan Venter fixed some problems with the RSXNT and Mingw32 makefiles.
  • 3.9.21: ran "configure --enable-asm=no", and fixed all the reasons why this didn't work. In particular there was a bug in patterned drawing modes, RLE sprites were broken, and I'd forgotten to add C versions of the RGBA sprite functions. Those of you who are interested in such things will be interested to know that the test program thinks the C drawing code is 20% slower at hline(), 10% slower at rectfill(), 50% slower at blitting, and 40% slower at draw_sprite(), which is not at all bad going. It's actually a bit faster at drawing translucent and lit sprites, so we need to have a look at that!
  • 3.9.21: many new Linux patches from George Foot.
  • 3.9.21: added VBE/AF support to the Linux code.
  • 3.9.21: finished the Linux fbcon driver.
  • 3.9.21: made Linux console switching work in a more complete manner, with a set of helper functions in dispsw.c. The background mode should work now, but is untested.
  • 3.9.21: added Linux GGI driver by Carsten Schmidt (this is somewhat out of date, and doesn't work yet, but a good start if anyone wants to hack on it).
  • 3.9.21: improved the Unix configure and build system. Moved more things into makefile.lst, so there are no file lists anywhere else now. Made it understand how to build the datafile tools, and convert the documentation (this may cause problems for systems without makeinfo: it would be good if someone who groks autoconf could try to do this better). Made the Linux VGA drivers (vga and modex) configurable.
  • 3.9.21: added ctrl+alt+end abort sequence to the Linux keyboard driver.
  • 3.9.21: directory structure changes: moved ufile.c into the misc directory, so BeOS can share it. Moved various helper scripts into the misc directory, including a cmplog.pl that compares two test.exe profile logs.
  • 3.9.21: made the Linux PS2 mouse driver understand the middle button. Added a scaling factor to make it go at a more sensible speed in SVGA modes.
  • 3.9.20: started working on a driver for the Linux fbcon device. It works, but can't change video mode yet.
  • 3.9.20: Windows patch from Stefan adds joystick input, and the beginnings of a windowed mode driver.
  • 3.9.20: moved all filename lists (even the platform specific ones) into makefile.lst, to avoid any duplication and give us a nice centralised place that mentions every single source file we use.
  • 3.9.20: removed the install_lost_bitmap_callback() function, in favour of the more generic set_display_switch_mode(). Updated the Windows code to use these new routines.
  • 3.9.20: merged X patch from Michael Bukin (adds mouse support).
  • 3.9.20: Vincent Penquerc'h optimised the 256 to truecolor graphics blitting code to avoid repeated conversions of the palette table.
  • 3.9.20: James Hyman added quoting support to get_config_argv().
  • 3.9.20: Peter Cech optimised the alpha sprite blending routines. Shawn optimised them a bit more by expanding out specialised versions for common pixel formats.
  • 3.9.20: Richard Davies made some improvements to the PSX joypad driver.
  • 3.9.20: added a system driver parameter to allegro.cfg, and hooks to make the Unix version look for config data in /etc/ and ~/.
  • 3.9.20: moved the Posix findfirst() emulation into libc.c, removing it from the autoconf and BeOS specific builds.
  • 3.9.20: more BeOS patches from Jason Wilkins. The graphics stuff be working there now!
  • 3.9.20: improved the VBE/AF driver to know that vertical lines can be implemented as a rectfill. This enables hardware acceleration for patterned vertical lines, and with drivers that don't have hardware support for the VBE/AF line draw routine.
  • 3.9.20: George Foot did some major work on the Linux console version, getting it up and running in a fairly convincing way.
  • 3.9.20: the Windows sound driver lists are now dynamically generated based on the available devices, so you can select which ones to use.
  • 3.9.19: wrote the first part of an Allegro Hacker's Guide, which is my (probably futile :-) attempt to document at least a few of the more gory parts of the Allegro code.
  • 3.9.19: finally got around to documenting the Unicode functions.
  • 3.9.19: more BeOS patches from Jason Wilkins.
  • 3.9.19: Michael Bukin made some more patches to the X code (timers are implemented now), and added a complete (?) C implementation of all the drawing code. Non-Intel machines, here we come! If you define ALLEGRO_USE_C before building the djgpp library, you can actually test out a pure C version of test.exe, the demo game, etc.
  • 3.9.19: added a findtext.sh script, which scans the source code and creates a list of all the strings that are available for translation. It can also compare this list against an existing translation file, to see if any new messages need to be added.
  • 3.9.19: Stepan Roh updated the Czech keyboard mapping for Unicode support, added support for keyconf to use a non-standard font, and added the Latin Extended-A characters (U+0100 to U+017F) to the default font.
  • 3.9.19: Grzegorz Adam Hankiewicz updated the Spanish translation with UTF-8 format (ie. properly accented) strings. Converted the setup program font into Latin-1 ordering so that this will display correctly. Fixed bug with dat2s not correctly converting the resulting multiple-range font.
  • 3.9.19: Chris La Mantia made some cosmetic fixes to the d_slider_proc() GUI object.
  • 3.9.19: Richard Davies added support for N64 joypads.
  • 3.9.19: added keyboard_ucallback() (I missed this one when I first added the Unicode support).
  • 3.9.19: made some changes to setup.c so that it can easily be embedded into other programs (thanks to Grzegorz Adam Hankiewicz for the suggestion).
  • 3.9.18: added support for 32 bit RGBA images. You can now read TGA files with an alpha channel into the grabber, or you can import a normal image and then overlay alpha data from any greyscale bitmap. You can save these alpha channels as part of a datafile, call the makeacol(r, g, b, a) function, and most importantly, call set_alpha_blender() and then draw_trans_sprite() to display them. Check out exalpha.c. There is much room to optimise the 15, 16, and 24 bit versions of _blender_alpha*(), if anyone wants to have a go at this. I think it would be profitable to write specific versions for common pixel orderings, and only keep the current generic implementation around as an emergency fallback.
  • 3.9.18: more Unix patches from Michael Bukin. It builds flawlessly now, even if it doesn't do anything very interesting yet.
  • 3.9.18: Jason Wilkins contributed the beginnings of a BeOS port (not yet functional, but it does compile).
  • 3.9.18: Revin Guillen added a position_dialog() function.
  • 3.9.18: portability improvements: changed makefile to be a generated stub, which normally just includes makefile.all, but can be completely replaced when using autoconf, and moved the emulation for missing libc functions into the shared sources.
  • 3.9.18: numerous bugfixes.
  • 3.9.17: Burton Radons changed the truecolor pixel blending functions to use a single callback function rather than the previous table. This may break some old code, but should remain largely backward compatible, and the new way is much more flexible. He also added a more complete set of blender functions, including Photoshop modes like burn, difference, lumincance, etc.
  • 3.9.17: Richard Davies added support for PSX joypads.
  • 3.9.17: fixed bug in dat2s handling of truecolor images.
  • 3.9.17: Jason Wilkins improved the quaternion math routines, and added some documentation for them.
  • 3.9.17: Neil Townsend added callback parameters to the timer handlers.
  • 3.9.17: Gunter Ladwig added three-button mouse emulation, which can be enabled using the config file (it defaults to on if you have a two button mouse).
  • 3.9.16: applied some patches from Michael Bukin, which add the basics of a Unix build system. It doesn't actually work yet, though :-)
  • 3.9.16: merged new code from Stefan. Lots more cool things are working in the Windows version now, eg. hardware acceleration, triple buffering, sound...
  • 3.9.16: added an example of how to write a Windows screensaver using Allegro. If anyone knows how to get a proper name to show up in the Windows selection dialog, please let me know! (I've made the stringtable entry that MSDN says you need, but it doesn't work).
  • 3.9.16: Andy Goth added a d_text_list_proc() dialog object, that lets you alter the selection by typing the first few characters of a list entry.
  • 3.9.16: Ole Laursen updated the Danish message translation.
  • 3.9.16: Calvin French added a -w (always update) switch to dat.exe.
  • 3.9.16: Joerg Rueppel added more flexible wildcard matching for object names in dat.exe.
  • 3.9.16: added GFX_HW_SYS_TO_VRAM_BLIT and GFX_HW_SYS_TO_VRAM_BLIT_MASKED capabilities flags, and more flexible blitting functions in the vtable.
  • 3.9.16: added lock_voice() and unlock_voice() methods to the digital sound driver, for implementing audiostreams under Windows.
  • 3.9.16: _handle_timer_tick() now returns the desired gap until the next interrupt.
  • 3.9.15: Michael Rickmann added a Mingw32 port. This currently works the same way as the RSXNT version, using MSVC to build the DLL, but will become a full gcc port after the core Windows code stabilises a bit.
  • 3.9.15: Vincent Penquerc'h added a D_DIRTY flag for GUI objects, and I extended this with a new D_REDRAWME return code for the handlers.
  • 3.9.15: changed the syntax of the create_color_table() callback. This breaks the API, but is the only way to make it work reliably with different compiler calling conventions.
  • 3.9.15: added a sub bitmap creation hooks to the vtable structure (so the parent bitmap can be told when it is being cloned).
  • 3.9.15: "make install" is now a separate target, not run automatically. This means that you now have to run "make" and "make install" as two separate operations, or if you want all three versions of the library, "make all" and then "make installall".
  • 3.9.15: added an END_OF_MAIN() macro, which makes the WinMain() magic work correctly in any combination of C and C++ code.
  • 3.9.15: Olly Betts modified the djgpp makefile to support cross-compiling on a Linux machine.
  • 3.9.15: Andy Goth added a 256x256 tweaked VGA mode.
  • 3.9.15: major documentation update (from now on I'll be adding a version number to each changelog comment).
  • Merged new code from Stefan. Windows version is getting much closer to completion, including mouse support and video bitmaps, although the mouse code isn't working quite right for me at the moment.
  • Rewrote fix_filename_path() to avoid calling _fixpath(). The new version is much more portable, although things like reading the current directory across multiple drives need some tweaking to work with different compilers.
  • Fixed oodles of things that were stopping the Watcom version from working. It now runs everything without any trouble at all, including such gems as exdodgy and the grabber shell edit! According to test.exe, gcc 2.8.1 is about 10% faster than Watcom 10.6 for most things, although for some reason textout() is about twice as fast in the Watcom version.
  • Fixed a bunch of stuff to make the RSXNT version work. All the tests and examples now build with RSXNT, and work identically to the MSVC originals.
  • Added quaternion math routines by Jason Wilkins.
  • Added more flexible gfx_card config support by Andy Goth.
  • Added a masked_stretch_blit() function (trivial change, the code could do it, but the API entry point was missing).
  • Added Windows GDI routines by Marian Dvorsky.
  • Added a DMA poll to the Soundscape driver, to make sure it can never get out of sync with the transfer.
  • Merged various bits and pieces that have been sitting around my hard drive for ages (Swedish and Norwegian translations, various patches from Michael Bukin, new palette generation code by Michal Mertl, Soundscape driver fixes by Andreas Kluge).
  • Grabber now knows about and can manipulate Unicode fonts.
  • Now passing atexit() as a parameter to install_allegro(), to avoid problems with DLL shutdown.
  • Made FLIC player set the dirty variables when clearing the bitmap at the start/loop point (this was sometimes causing the screen not to be cleared from previous contents).
  • Fixed several bugs in the grabber.
  • Changed the datafile utilities to link the datedit and plugin routines as a proper library. This will make life easier for third parties that want to use those routines (duplicating the plugin linkage isn't much fun).
  • Replaced errno references with allegro_errno pointer, to avoid problems with multiple runtimes when linking as a DLL. The MSVC version of dat now works perfectly!
  • Added a system_none driver for commandline utilities and other platform neutral situations.
  • Made new demo intro animation. My first ever Max rendering!
  • Merged Windows patches from Stefan. Whoah! This thing is cool. It works (sort of :-) on two platforms. Now I can die happy....
  • The file selector now adjusts for platforms without any directory list (eg. Unix).
  • Added a global default_palette (the normal IBM BIOS one), and made set_gfx_mode() select it.
  • Modified DIGMID driver to avoid using 64 bit ints or floating point in the interrupt handler.
  • Added ASSERT() and TRACE() debugging routines, and lots of asserts throughout the library code.
  • The default truecolor pixel format before setting a video mode is now BGR rather than RGB. This should help to shake out bugs in BGR support, and catch any errors where people load graphics before setting a video mode.
  • Fixed fmul() overflow detection bug.
  • Rewrote gpro.c and sw.c to avoid using inline asm. The SW code is currently very ugly (literal translation of the asm routine), but I'm keen to improve it given some testing feedback. If you have a Gamepad Pro or Sidewinder, and were able to use it with the Allegro 3.11 driver, I would _really_ like to hear whether this current code works for you or not...
  • Numerous changes to make the support programs more portable.
  • Added a get_executable_name() function.
  • The sound.cfg file is no longer supported. Use allegro.cfg instead.
  • Added versions of the inline _putpixel() and _getpixel() for all color depths.
  • The check_cpu() function is now called automatically by allegro_init().
  • Added system bitmap objects, which exist in system memory but are accessed in a similar way to video memory surfaces (this can enable better hardware acceleration on some platforms).
  • Added enable_triple_buffer(), timer_can_simulate_retrace(), and timer_is_using_retrace() functions. This enables programs to correctly handle the interrelationship between mode-X triple buffering, the retrace sync mode, and the current OS, without having to include any DOS specific code.
  • GUI routines now call the input polling functions and acquire/release the screen as appropriate.
  • Fixed a real show-stopping error that was causing VBE/AF crashes on some machines (calling driver functions with non-flat memory selector in %es).
  • Added an allegro_message() function.
  • Added dummy bank switch routines that can emulate linear access to a mode-X screen, albeit rather slowly. The only practical result from this is that polygon routines work in mode-X now, but it helps to make things more robust in general (if a routine doesn't know about mode-X, now it will just run more slowly than usual, rather than not working at all).
  • The SB, Adlib, and standard joystick drivers now properly have a separate instance for each variant of the hardware, rather than a single driver pretending to exist under multiple different ID codes.
  • Rewrote joystick polling to avoid inline asm.
  • Converted translation files into UTF-8 format. These can now use any Unicode characters they like, so accented vowels etc. can safely be used.
  • Keyboard scancodes have changed from the hardware format to an abstract, Allegro-specific encoding. This simplifies the code a great deal, and avoids hassles with two different keys generating the same scancode.
  • Added generic find_allegro_resource() function, which removes a lot of duplicated code from config.c, digmid.c, and pckeys.c.
  • Timer module now autoinstalls whenever someone tries to use it.
  • Keyboard functions can now alter the repeat rate.
  • Watcom port.
  • Added a special GFX_SAFE driver ID.
  • Now using VDS to detect win95 even when in stealth mode.
  • Added fixver.sh for patching version numbers and dates when releasing a new version (requires bash, fileutils, shutils, etc, to run on DOS).
  • Added zipup.sh for building a distribution zip and diffs, which automatically cleans up the tree ready for this (eg. pregenerating the dependency files for all supported compilers).
  • Added input polling functions.
  • Major code restucturing, added system drivers, new framework for input handling, timers, keyboard scancode conversion, file access, etc.
  • Added full support for Unicode text, including string manipulation functions, a new font format, the textconv utility, a new GUI MSG_UCHAR, and a ureadkey() function.
  • Added variable sized monochrome fonts, replacing the the old 8x8 fixed size format. As a result, the GFX_HW_TEXTOUT_FIXED capabilities flag has been renamed to GFX_HW_GLYPH.
  • New system for accessing video memory, using bmp_select(), bmp_write*(), and bmp_unwrite_line(). This is equivalent to the djgpp farptr functions, but portable to different platforms.
  • Drastic reorganisation of directory structure, makefile system, etc.
  • Enhanced the makedoc utility to simplify adding links and email addresses to the docs.
  • Added a bodge to make the VESA code work with broken S3 Trio64 drivers.
  • Removed the 386DX vs. 386SX processor detection code (it was sometimes crashing).
@heading Changes from 3.11 to 3.12 (Aug 1999)
  • Fixed a few incompatibilities with gcc 2.95. This release is otherwise identical to 3.11.
@heading Changes from 3.1 to 3.11 (Feb 1999)
  • Cleaned up a few places where memory wasn't getting freed during the system shutdown. A cosmetic detail since the OS will free it for us, but it is nice to get these things right.
  • Alessandro Monopoli added an Italian translation of the system messages.
  • Henrik Stokseth added code to distinguish between win95 and win98.
  • Creative Labs have been removed from the THANKS file, because of their refusal to release any specs on the SB Live soundcard.
  • Changed the name of the library. After years of thinking that Allegro was a word with no particular meaning, I realised that it is in fact a recursive acronym for "Allegro Low Level Game Routines".
  • Established a new mailing list for use by the people currently working on Allegro. Please send code contributions to this list rather than directly to me (Shawn Hargreaves), because this will allow Allegro development to continue even if I'm not around or am busy with something else at the moment.
  • Andreas Kluge wrote a driver for Ensoniq Soundscape cards.
  • More localisation: Swedish message translation by Sven Sandberg, Anton Ragnarsson, and Erik Sandberg, Finnish message translation by Antti Haapala, and Russian message translation and keyboard mapping by Dmitriy Kazimirow.
  • The midi_out() function now correctly updates the pan/volume/bend controller status.
  • Kester Maddock added a Wingman Warrior joystick driver.
  • Fixed some problems with the Sidewinder, Gamepad Pro, and SNES joypad drivers.
  • Changed the SB16 driver to use signed 16 bit output mode, rather than the previous unsigned format. Hopefully this will improve compatibility with crappy clone hardware.
  • Added a new WARNMODE environment switch to the makefile. Allegro developers should all set this to get strict warnings, but it will be left off by default so that the distributed version will be more forgiving about different compiler/libc versions.
  • Fixed problem with reading the top and left positions on digital joystick devices.
  • Fixed (I think, still waiting accurate confirmation on this one :-) problem with timers running too fast on some motherboards.
  • Fixed stupid bug where get_align_matrix() wasn't bothering to zero the translation vector.
  • Fixed stupid bug where rotated sprites were coming out upside down in mode-X and hi/truecolor modes.
  • Fixed bug where dat utility was truncating long filenames to 8.3 format.
  • Renamed the ChangeLog file to CHANGES, to avoid problems on 8.3 systems.
  • Various other minor bugfixes.
@heading Changes from 3.0 to 3.1 (Jan 1999)
  • Changes between the 3.1 beta and final releases: assorted bugfixes, Antoine Mathys added a Swiss keyboard mapping, Thomas Wolf added a German translation of the system messages.
  • Changes between the 3.1 alpha and beta releases: assorted bugfixes, FLIC routines can now read from datafiles, included rotation optimisations by Ivan Baldo.
  • Peter Cech added support for hot-swapping between a custom keyboard layout and the standard US mapping.
  • Neil Townsend improved the accuracy of the timer routines.
  • Added exlights.c example program, showing one way to do colored lighting effects in a hicolor mode (and also because it makes the total number of examples a nice round number :-)
  • Added an afinfo test program, which does the same thing as vesainfo but for VBE/AF drivers.
  • Michael Bukin made a lot more portability patches and some bug fixes, including some improvements to the FLIC player and a much more rational filename handling system.
  • Removed the chipset-specific SVGA hardware drivers from the main library distribution. Instead, these will now be available both as an optional addon package, and reformatted as part of the FreeBE/AF project.
  • Added FreeBE/AF extensions support to the Allegro VBE/AF driver (farptr access to video memory, and the libc and pmode exports needed for future compatibility with the SciTech Nucleus drivers).
  • Fixed a bug with the patterned and translucent vline() function in 15 bit color depths.
  • Fixed a NULL pointer dereference bug in the config routines.
  • Fixed an order of processing bug that was causing data to be lost when calling set_config_file() with the same filename as the current config.
  • Stepan Roh added a Czech translation of the system messages.
  • Ole Laursen added a Danish translation of the system messages.
  • Grzegorz Ludorowski made a new demo game intro animation.
  • Calin Andrian added 3d polygon timing routines to test.exe.
  • Peter Cech added grabber support for the 8x8 BIOS font format.
  • Stepan Roh added a Czech keyboard mapping.
  • Renamed the Spanish language translation file from SP to ES.
  • Calin Andrian added a complete set of truecolor polygon rendering routines, with support for MMX and 3DNow! optimisations and a new masked lit drawing mode, along with a new polygon clipping function. One minor change is that POLYTYPE_FLAT mode is now implemented by calling hline(), so it will respond to the current drawing_mode() settings.
  • Changed the graphics/sound/joystick driver ID numbers from a zero based list to a descriptive 4-character string, to make them more readable and flexible. Added config functions to read/write data in this format. The sound config data is backwardly compatible, but you will need to manually update any graphics or joystick driver numbers that are stored in your config files.
  • Michael Bukin contributed a _lot_ of patches to improve the portability and robustness of pretty much the entire library. The only externally visible change is that the macros used for declaring hardware driver lists have been redesigned to use a more portable syntax, although the old syntax is still available as a compatibility macro.
  • Burton Radons did some more optimisation of the truecolor pixel blending functions.
  • Martijn Versteegh added a hook mechanism for extending the config file system, which can be used to provide extended system status information or customisation routines for addon packages.
  • Redesigned the grabber and dat utilities to support source-code "plugin" modules, which can be used to extend the system with additional object types, import/export routines, and menu commands.
  • Ivan Baldo added a dithering option to the 15/16 bit color conversion routines.
  • Kerry High added a SNES joypad driver.
  • Added a font override to the d_text_proc() and d_ctext_proc() GUI objects, using the dp2 field to specify a custom font.
  • Michael Tanczos fixed some bugs in the FLIC player.
  • Cloud Wu optimised the truecolor pixel blending functions.
  • Paul Pinault added a French translation of the system error messages.
  • Grzegorz Adam Hankiewicz added a Spanish translation of the system error messages, and added a new (but undocumented :-) command line option to the demo game.
  • Fixed clicks in the interpolated sample mixing.
  • Fixed a bug with position_mouse() not updating the mouse_pos variable.
  • Fixed a bug in mode-X horizontal scrolling while the timer retrace simulator is active.
  • Added a language.dat file, which can be used to provide translated versions of system strings (eg. error messages), in a similar way to the existing keyboard.dat. If you want to use this mechanism from your own code, replace all your constant strings with calls to get_config_text("string"). This allows them to be translated by including a line of the form "string=foreignstring" in the relevant section of language.dat.
  • Added an ASCII name field to the keyboard mapping files, in order to make the setup program a bit more friendly.
  • Increased the maximum number of sound channels from 32 to 64.
  • Modified the DIGMID patch loader to support 16 bit samples, rather than just reducing everything to 8 bit.
  • Added an interpolation option to the sample mixer (quality=2).
  • Salvador Eduardo Tropea added support for proper 16 bit sample mixing (quality=1).
  • Lee Killough added a lower level hook routine to the keyboard handler.
  • Removed floating point code from the DIGMID driver, to avoid potential FPU stack overflows.
  • Jim Flynn removed floating point calculations from the AWE32 MIDI driver (these could sometimes cause stack overflows).
  • Salvador Eduardo Tropea improved the datafile system to avoid linking of unused code.
  • Romano Signorelli contributed a Bresenham arc plotting function.
  • Thomas Wolf corrected some errors in the German keyboard mapping file.
  • Grzegorz Adam Hankiewicz improved the excolmap example program.
  • Sven Sandberg optimised the fixed point trig routines.
  • Fixed some silly crash bugs in the joystick code.
  • Added a "compress" target to the makefile, based on a suggestion by Grzegorz Adam Hankiewicz.
  • Added dummy bitmap acquire/release functions to allegro.h, for compatibility with the Windows version.
  • Added a cross-reference facility to the Info format documentation.
  • Martin Fuller fixed an obscure bug in the reading of compressed .bmp files.
  • The emergency exit signal handler now correctly restores the previous handler, rather than resetting to the default action.
  • Sven Sandberg optimised the create_light_table() function.
  • George Foot fixed a bug when the get_mouse_mickeys() routine was called with both parameters pointing to the same value.
  • Changed the licensing terms from "swapware" to "giftware". See the Allegro website for an explanation of the reasons for this change.
  • Added yet more overloaded operators (this time for long and double types) to the fix class.
  • Marius Fodor added support for the Sidewinder and Gravis GamePad Pro. Many apologies for my taking so long to merge in this code!
  • Stefan Schimanski optimised the reverse blitting routine (for overlapping images).
  • Added a shift+tab reverse focus movement key to the GUI routines.
  • Grzegorz Adam Hankiewicz added a new example showing how to create and use a custom color mapping table.
  • Totally revamped the joystick system (better API and new driver structure).
  • Modified the fix class to work properly with gcc 2.8.0.
  • Added a help.txt "how to get tech support" file.
  • The midi_pos variable is now negated, rather than cleared to -1, at the end of a MIDI file. This can be used for measuring the length of a file.
  • Added a rendering hook to the font structure, for use by text addon packages.
  • Improved the VBE/AF text output routine.
  • Corrected an error in the way the VBE/AF driver interprets hardware cursor colors.
  • Pedro Cardoso contributed a tweaked 80x80 VGA mode.
  • The VBE/AF driver now supports dumb framebuffer drivers as well as accelerated ones.
  • Added more accelerator support to the VBE/AF driver (hardware cursors, lines, vertical lines, triangles, fixed width text output, and opaque/masked blitting from system memory to the screen).
  • Added a scare_mouse() function, based on ideas by Martijn Versteegh.
  • The grabber now stores the "grab from grid" dialog state in allegro.cfg.
  • Sven Sandberg fixed a problem with save_bitmap() widths being rounded upwards.
  • Made the _timer_installed flag globally visible.
  • Ove Kaaven added linear framebuffer support to the native mach64 driver.
  • Erik Sandberg optimised the 8 bit draw_sprite() and draw_trans_sprite() functions.
  • Michal Mertl fixed a memory leak in the generate_optimized_palette() function.
  • Added an ALLEGRO_DATE version define to allegro.h.
  • Michael Bukin optimised the line drawing routine and fixed problem with the inline asm constraints for fadd()/fsub().
  • Fixed potential problems caused by a lag between the mouse state variables changing and the pointer being redrawn.
  • Michal Mertl optimised the clipping code for lines, rectangles, and circles.
  • Maiolino Carmelo contributed an Italian keyboard mapping.
  • Fixed lockup problems caused by the keyboard LED functions on some platforms/hardware.
  • Added new create_video_bitmap() and show_video_bitmap() functions.
  • Added a profile option to the test program.
  • The keyboard handler now correctly updates the BIOS state for the right control and alt keys when it shuts down.
  • Fixed a problem that was preventing the DIGMID driver from reading patch sets stored in executable appended datafiles.
  • Changed the default sample priority from 255 to 128.
  • Fixed some problems with virtual screen sizes in the VBE/AF driver.
  • Added two new example programs.
  • The VBE/AF driver now has full support for hardware accelerated drawing.
  • Added VBE 3.0 support, including new triple buffering routines.
  • Wrote a routine to select the sound input source (microphone, line input or CD audio).
  • Added proper support for stereo samples. This requires an extra parameter to the play_audio_stream() function, so you will need to change any programs that use this. I'm very sorry for breaking your old code!
  • Fixed bugs with the SB16 autodetection and 16 bit sample recording.
  • Added input support to the raw SB MIDI interface driver.
  • Wrote a new test program to demonstrate the audio input features.
  • Ove Kaaven added support for MIDI and audio (sampled sound) input.
  • The pack_fopen() function now understands nested datafiles as directory structures, using filenames like "graphics.dat#level1/sprites/zdurgle".
  • Charles Mac Donald showed me how to set a 160x120 VGA mode, and more reliable 400x* mode-X resolutions.
  • Guilherme Silveira and Theuzifan Sumachingun both independently modified the file selector to only list valid drive letters.
  • Carsten Sorensen added a driver for the ESS AudioDrive soundcard.
  • Przemek Podsiadly added hicolor versions of the 3d polygon routines.
  • Ove Kaaven added truecolor support to the native ATI mach64 driver.
  • Patrick Hogan added a draw_gouraud_sprite() function.
  • Ben Chauveau added a driver for Tseng ET6000 cards.
  • Marco Campinoti added truecolor support to the native Tseng ET4000 driver.
  • Marco Marmulla added 16 bit support to the load_voc() routine.
  • Added Danish, Swedish, and Norwegian keyboard mappings.
  • Added GUI hook functions for scaling or offsetting the mouse position.
  • Fixed bug which was causing a lockup when calling set_leds(-1).
  • Michael Bevin optimised the create_trans_table() function.
  • It is now possible to display a mouse pointer without the mouse handler needing to be installed.
  • Added a create_sample() function.
  • Made the _blender_map pixel blending functions and the _mouse_installed, _keyboard_installed, and _sound_installed flags globally visible.
  • Added an 8-button joystick mode.
  • Chris La Mantia fixed a minor visual problem with the d_icon_proc().
  • Added a Rich Text Format (.rtf) version of the documentation.
  • Added postfix increment and decrement operators to the C++ fix class, and the unary negation operator is now const-correct.
@heading Changes from 3.0 beta to release (Dec 1997)
  • The pat2dat utility can now import instruments from AWE32 SoundFont files.
  • Optimised the DIGMID patch loader and fixed a couple of bugs.
  • Ove Kaaven fixed the ATI mach64 driver.
  • The config file can now mention several possible video drivers, using lines in the form gfx_driver=x, gfx_driver2=x, etc.
  • Improved the native SVGA driver helper functions, making it easier to add truecolor support to the register level drivers.
  • Double-clicking on a font object in the grabber now allows you to view the extended characters as well as normal ASCII.
  • Markus Oberhumer corrected a potential problem with the Video-7 initialisation code.
  • Markus Oberhumer, Bitland, and Sormuras all sent me mapping tables for the German keyboard layout. Coordination of effort: who needs it? :-)
  • Mathieu Lafon improved the French keyboard mapping.
  • Fixed some bugs in the MIDI voice allocation system.
  • Added a -k (keep names) option to the dat utility.
  • The setup program now uses the ALLEGRO environment variable to locate the keyboard.dat file.
  • Fixed a problem with < and > characters in the HTML documentation.
@heading Changes from 2.2 to 3.0 beta (Nov 1997)
  • Merged in George's improved instrument parameters for the AWE32 driver.
  • The pat2dat utility can now reduce sample data from 16 to 8 bits (saves space, and the DIGMID driver only uses 8 bits in any case).
  • Added yet another version of the mouse handler, this time in an attempt to make it work more reliably under Windows NT.
  • Frodo Baggins added a mapping table for Portuguese keyboards.
  • Added an external tool "shell" function to the grabber.
  • Added a "box grab" function to the grabber, which uses a color #255 bounding box to determine the extent of the sprite to grab.
  • Santeri Saarimaa added a Finnish keyboard mapping.
  • Finished writing the pat2dat utility, and the DIGMID driver is working a lot better now.
  • Mathieu Lafon added support for the Pause and PrtScr keys, and changed the key[] array to a bitfield indicating whether either or both of the normal and extended versions of the key are pressed. This remains compatible with the "if (key[KEY_*])" syntax, but also allows you to distinguish between, for example, the Enter key on the numeric pad and the one next to the right shift key.
  • Fixed a bug in the handling of config variables that don't belong to any section.
  • The makefile now tries to detect and warn people about some of the more common installation errors.
  • The HTML version of the documentation now uses a short .htm file extension if it is built on a system with LFN disabled.
  • Keyboard mapping files now only bother saving the entries that differ from the default US mapping. This makes the maps a great deal smaller!
  • Changed the default font and keyboard mapping tables from DOS codepage 437 to the standard ISO charset (first part of Unicode). If you have made a keyboard config using the old codepage it will need to be updated, but don't worry, I have a script that can do this very easily.
  • Fixed a bug in the detection of font formats (fixed or proportional) when grabbing from a bitmap font.
  • Added an editable loop point to the MIDI player (thanks to George for sorting out how to do this...)
  • Rewrote the mouse handler to track the position itself, using only the mickey counters from the int 0x33 driver. Hopefully this will fix the problem with buggy Logitech drivers...
  • Added a mouse_pos variable containing both the X and Y values in one 32 bit location, to allow a single instruction read during tight polling loops.
  • The grabber now supports multiple selection, and has a new "ungrab" command that copies from a bitmap object into the scratch buffer (you can use this to generate palettes from truecolor images, or to re-grab a smaller area from the image).
  • Added multiple selection abilities to the GUI listbox object.
  • Theuzifan improved the cpu detection for Cyrix chips.
  • Mathieu Lafon added a French keyboard mapping.
  • Richard Mitton wrote an example program demonstrating how to fake a 12 bit truecolor display on an 8 bit card.
  • Michal Mertl added a routine for generating optimised palettes for a specific truecolor image.
  • Optimised the getr/g/b() functions. Converting between different color depths should be much faster now...
  • Scott Harrison added code to detect OpenDOS, and use the i_love_bill mode if their version of EMM386 is in use.
  • Added some new example programs.
  • The makedoc utility now converts between the DOS and Windows extended character sets when producing HTML output files.
  • Ettore Perazzoli made a spectacular optimisation to the linear -> mode-X blitting function.
  • Added a grid option to the dat utility, to specify which region of a bitmap you want to grab.
  • Fixed a bug in blitting truecolor bitmaps onto mode-X destinations.
  • Fixed a bug that was preventing the Adlib volume from being changed when only MIDI sound drivers were installed.
  • The grabber can now be run in video modes other than 640x480 (it doesn't look very nice in lower resolutions, though :-)
  • Added a new fake scancode for the extended / key (the one on the numeric keypad) so that the two keys can be distinguished from each other.
  • Joaquin Hierro Diaz made a mapping table for Spanish keyboards.
  • The setup utility can now be used to select a keyboard layout and to calibrate the joystick, as well as for the sound hardware.
  • Moved some of the documentation to different locations, so hopefully people will now be less likely to miss the faq.txt, and to bring it closer in line with the standard GNU distribution format.
  • Better keyboard configuration system. There is now a proper utility for setting up the mapping tables, the tables can be read from external files, and it properly supports the alt-gr and accent escape keys.
  • Menu items can now be disabled, have check marks next to them, and support right aligned text eg. for displaying keyboard shortcuts, there is a new "void *dp" field in the menu structure, and the click callback routines can now use the global pointer "active_menu" to determine which option they were called by, if a single routine is shared by several menu items.
  • Peter Palotas added an input callback to the keyboard routines, and event flags to the mouse callback.
  • Added a -pal option to the dat utility.
  • Grzegorz Ludorowski made some new graphics for the demo game.
  • Moved some code to new files and added a bunch of macros so you can remove unused graphics and sound drivers at link time.
  • Fabian Nunez added support for the Logitech Wingman Extreme joystick.
  • Chris La Mantia contributed a d_slider_proc() dialog object.
  • Sean Gugler added a routine for changing the keyboard LED state.
  • George Foot added pause and seek functions to the MIDI player.
  • Added the ability to append datafiles (in fact any files at all) onto the end of your program executable.
  • Merged in the AWE32 driver. Long live George!
  • Can now read RLE compressed TGA files.
  • Added a mouse movement callback function (useful for detecting double click events).
  • Stefan Eilert added support for dual joysticks.
  • Seymour Shlien contributed a routine for drawing justified text.
  • Krzysztof Krzyzaniak contributed a loader for .VOC sample files.
  • Added a rotate_scaled_sprite() function.
  • Now supports the Dvorak keyboard layout.
  • Salvador Eduardo Tropea added a 320x100 VGA mode.
  • Implemented translucent and lit sprite and RLE sprite drawing functions for the truecolor modes.
  • Updated the sound setup utility.
  • The dat utility can now output makefile dependencies for automatically rebuilding the file when any of the source data changes.
  • Fixed some problems with the RGB <-> HSV conversion functions.
  • Truecolor image loading and grabber support.
  • Phil Frisbie provided some code to detect the CPU type.
  • Michal Mertl added 24 bit graphics modes. Hurrah!
  • Added functions for playing streams of digital audio data.
  • Chris La Mantia contributed a bitmap icon GUI object.
  • Doug Eleveld added a text box GUI object, plus an improved help system for the grabber.
  • Added support for UK and AZERTY keyboard layouts. More can easily be added if you send me the appropriate scancode -> ASCII mapping tables...
  • Added get_align_matrix(), qtranslate_matrix(), and qscale_matrix() functions.
  • Added a draw_character() function for using sprites as monochrome pixel masks.
  • It is now safe to pass the same matrix as both input and output to the matrix_mul() function.
  • Paul Bartrum contributed some ellipse drawing functions.
  • Added some callbacks to the MIDI driver, allowing you to hook your own code into MIDI notes or marker events.
  • Added a function to measure mouse movement in terms of mickeys (difference since the last call) as well as in absolute screen coordinates.
  • VolkerOth made the d_edit_proc objects able to scroll, if the string is larger than the available space.
  • Added the ability to distinguish between the left and right Control and Alt keys.
  • Fabian Nunez added support for the extra keys on a Microsoft keyboard.
  • Added void *dp2 and void *dp3 fields to the dialog structure. This ought not to break any existing code, but will let you store a lot more data when creating custom objects.
  • The packfile functions can now directly open and read from datafile member objects, using fake filenames in the form "filename.dat#obj_name". This means that all the Allegro file access routines (eg. load_pcx() and set_config_file()) can now read from datafile objects as well as separate files.
  • Added miditest and digitest programs to allow more rigorous testing of the sound routines and patch sets, and a vesainfo program to check which video modes are available on any given card.
  • Jan Hubicka wrote a faster version of create_rgb_table().
  • The grabber now scales the bitmap preview if the image is too large to fit onto the screen.
  • Jorrit Rouwe provided a new and much cooler set of FM instrument definitions for the Adlib MIDI driver.
  • Added a function to load .IBK patch sets for use by the Adlib driver.
  • Added a wrapper allegro/ directory around the contents of the zip file, so it can now be safely unzipped into the main djgpp directory.
  • Richard Mitton added support for 6-button joysticks.
  • Truecolor (15, 16, and 32 bit) graphics modes.
  • Vastly improved sound routines (more flexible API, now supports up to 32 simultaneous voices on the SB, sample-based MIDI playback driver, can reverse samples, volume/pan/pitch sweep effects, MIDI commands can be output on the fly as well as played from MIDI files, and lots of other goodies).
  • It is now possible to update the status of GUI dialogs incrementally from your own control loops, with an update_dialog() function, rather than completely transferring control to do_dialog().
  • Compressed files (including grabber datafiles) can now be encypted with a password.
  • Added a masked_blit() function, that skips zero pixels.
  • Added code to detect being run under Linux DOSEMU, and use the less demanding version of the timer code if this is the case.
  • Added a standardised configuration mechanism. The format for saved joystick calibration information has changed, so existing joystick files are no longer valid.
  • Added a textprintf() routine, which uses a printf() style format string.
  • Added a TexInfo version of the documentation (thanks for the help, Francois!)
  • Jonas Petersen added a save_bmp() function, and support for the OS/2 BMP format.
@heading Changes from 2.11 to 2.2 (Feb 1997)
  • TBD/FeR added tweaked 320x600 and 360x600 resolutions to the mode-X driver.
  • Matthew Bowie added support for 4-button joysticks.
  • Dave Thomson added RGB <-> HSV conversion functions.
  • Added a 'freeze_mouse_flag' variable, that can be used to lock the pointer to a specific position.
  • Added a 'key_led_flag' variable, that can be used to prevent the keyboard LED's updating in response to the capslock, numlock, and scroll-lock keys.
  • The midi player now resets midi_pos to -1 when the music finishes playing.
  • Adrian Oboroc wrote an LBM loader.
  • Fonts can now contain characters above ASCII 127.
  • Chris Wigman made a better intro animation for the demo game.
  • Added translucency, color blending, and lighting routines (based on code by Owen Embury and ideas by Nathan Albury).
  • Added 3d math and matrix manipulation functions.
  • Added texture mapped and gouraud shaded polygon drawers.
  • Tim Gunn contributed code for reading and writing TGA files.
  • Fixed clamping problems with rotating non-circular sprites.
  • Added scrollbars to the GUI listbox object.
  • Seymour Shlien wrote a bezier spline drawing function.
  • Added fixed point fadd() and fsub() functions, which check for overflow.
  • Added pack_fseek() and chunk manipulation functions to the file routines.
  • Improved datafile structure and grabber program.
  • Wrote a utility to convert grabber datafiles into linkable asm code.
  • Salvador Eduardo Tropea improved the keyboard routines (better handling of extended scancodes, keyboard LED support, capslock and numlock, and alt+numpad input).
  • Fixed the packfile functions and file selector to work with long filenames under win95.
  • Seymour Shlien contributed a BMP reader.
  • Added a hook function to the keyboard code, allowing you to use the GUI code without installing the keyboard handler.
  • Fixed a lockup caused by trying to access non-existent floppy drives.
  • Francois Charton wrote a driver for Paradise graphics cards.
  • Chris La Mantia contributed a radio button GUI dialog object and added a D_DISABLED object flag.
  • Markus F.X.J. Oberhumer fixed the Video-7 scrolling function.
  • Converted the docs into HTML format.
  • Added code to detect Windows NT.
  • Mark Habersack added support for newer Trident chipsets.
  • Did some more work on the VBE/AF driver (it now works, but still doesn't support accelerated hardware features).
  • Fixed bugs in the WAV sample reader and FLIC player.
  • Added special 'windows friendly' mode to the timer code. You can now even run demo.exe under Windows 3.1!
  • Reorganised directory structure, to allow for a Linux version. The output liballeg.a is now found in lib/djgpp.
  • Added support for 8x16 BIOS format fonts.
  • Fixed a problem with overflow when rotating large sprites.
  • Fixed a problem with restoring the text mode screen height after running Allegro programs.
@heading Changes from 2.1 to 2.11 (Nov 1996)
  • Fixed bug in bank.S.
  • install_mouse() now sets the range to (0,0,SCREEN_W,SCREEN_H).
  • install_sound() does not automatically set the volume to maximum.
  • Added ++ and -- operators to class fix.
  • Makefile now copies liballeg.a to lib, and allegro.h to include.
  • Made a few changes to work under LFN=y (if you use unzip or winzip instead of pkunzip).
  • Added manifest.
  • Clarified installation instructions.
@heading Changes from 2.0 to 2.1 (June 1996)
  • Mode-X support (thanks to Jonathan Tarbox and Dominique Biesmans for suggesting and then helping to implement this).
  • Compiled sprites.
  • Jonathan Tarbox contributed an FLI/FLC player.
  • Added patterned drawing modes.
  • Added a vertical retrace interrupt simulator.
  • polygon() can now handle concave and self-intersecting shapes. I also changed the parameters a bit. Sorry if this breaks your old code, but it's more efficient the new way...
  • Added stretch_sprite().
  • Wrote a floodfill() routine.
  • More flexible palette fade routines.
  • Added set_volume() to the sound code.
  • David Calvin wrote a sound setup utility.
  • Improved the GUI. Added popup/dropdown menus, joystick input, three button alert boxes, better handling of arrow key focus movement, a new keyboard shortcut object (d_keyboard_proc()), and '&' markers in strings to display keyboard shortcuts. The GUI can also now be used with fonts other than the standard 8x8 default, by altering the global 'font' pointer.
  • Fabian Nunez added support for the CH Flightstick Pro joystick (looks cool: I want one :-) and 3-button mice.
  • The keyboard handler now responds to the state of the ctrl and alt keys, and there is a new simulate_keypress() function.
  • Mark Wodrich added sub-bitmaps, which share their memory with a parent bitmap but can be positioned anywhere within it, and have their own clipping rectangles.
  • Mark also modified the mouse driver to double-buffer the pointer (so it doesn't flicker any more), and added a set_mouse_sprite_focus() function.
  • Added set_mouse_range() and set_mouse_speed() functions.
  • Thanks (again) to Mark Wodrich, the grabber can now import GRX .FNT files.
  • The grabber can now make backups when saving datafiles, and it only writes the datafile headers if their contents have changed, to prevent unnecessary recompilation.
  • Added a text_height() function.
  • The fixed point inverse sin and inverse cos functions now use lookup tables, which makes them a lot faster.
  • Reorganised the directory structure, added some example programs, and improved the documentation.
@heading Changes from 2.0 beta to release (March 1996)
  • Marcel de Kogel fixed some problems with the MPU-401 driver. It now actually works :-)
  • Marcel also provided some better drum sounds for the Adlib driver.
  • Inlined the fmul() and fdiv() functions.
  • Much faster fsqrt(), taken from Arne Steinarson's fix-float library.
  • Added inline bmp_write_line(), bmp_read_line(), and _putpixel() functions.
  • The keyboard routines now support the emergency abort sequence ctrl+alt+del, and there are signal handlers to make sure Allegro will shut down cleanly if your program crashes.
  • Wrote new irq wrappers that can deal with reentrant interrupts.
  • Added joystick routines (based on code provided by Jonathan Tarbox and Marcel de Kogel).
  • Moved some functions to different files and juggled things about so the linker can do a better job. If you don't use the sound stuff, or don't use any graphics functions, now they won't be linked into your executable.
  • Marcel de Kogel manged to locate my (embarrassingly stupid :-) mistake which was preventing the VESA 2.0 linear framebuffer driver from working.
  • Various other performance enhancements and bug fixes.
@heading Changes from 1.x to 2.0 beta (Jan/Feb 1996)
  • Dropped all the Borland code. A couple of months ago I ran out of disk space, and it was with great satisfaction the I executed the command 'deltree /y c:\bc4'. It was a horrible compiler, and I'm glad it's dead.
  • Added SVGA support. As a result it no longer makes sense for allegro_init() to put the system into mode 13h, so you will be in text mode until you call set_gfx_mode().
  • Added sound code (background MIDI music and sample mixing).
  • Added support for proportional fonts (of any size) as well as the old 8x8 fixed size ones.
  • XOR drawing mode.
  • There is no longer such a thing as a SPRITE structure. The sprite drawing code now draws bitmaps onto other bitmaps, which is a much more flexible way of doing things. The datafile reader will convert all your old sprites to bitmaps as it loads them in, so the only practical difference this is likely to make is that the sprite drawing routines can't draw opaque sprites any more (but you can use a blit instead).
  • show() and get_sprite() no longer exist: use blit() instead.
  • Added flipped and rotated sprite draw routines.
  • Added bitmap scaling.
  • Added RLE sprites.
  • drawsprite() has been renamed to draw_sprite().
  • textmode() has been renamed to text_mode(), to avoid conflicts with definitions in conio.h.
  • All the file access functions have been renamed from the stdio syntax to pack_fopen(), pack_getc(), etc, so they can now be mixed with stdio code.
  • Added pack_fgets() and pack_fputs().
  • The port_callback pointer no longer exists.
  • Removed polyline() (who ever used it?), and added a polygon(), which draws a filled convex polygon with an arbitrary number of vertices.
  • Added do_line() and do_circle() functions, which call a user-supplied function for each pixel that needs to be drawn.
  • Added a default keyboard interface to the GUI routines, allowing the selection of objects with the arrow keys and <enter>.
  • Added several new GUI messages and flags. In particular there are now messages for tracking mouse cursor movement, an idle message, a special return value for the MSG_CHAR message which allows an object to override the default keyboard handling, and a flag which hides the object.
  • There are new GUI routines to centre a dialog on the screen and to alter the colors used by the standard alert and file selector dialogs.
  • The file selector now takes a third parameter specifying which file extensions to display.
  • The timer routines now have better than millisecond accuracy, and it is possible to alter the speed of a user timer callback in realtime (by reinstalling it with a different speed value).
  • Removed the _RGB struct and paltorgb() functions. RGB's are now stored directly in the hardware format, with each value in the range 0-63.
  • Added functions to get and set single palette entries as well as entire palettes.
  • Added DPMI memory locking code.
  • Wrote a C++ 'fix' class which overloads a lot of operators, providing an easy way to use the fixed point routines.
  • There are probably lots of other things that I have forgotten about.
allegro4.4-4.4.2/docs/src/const._tx000066400000000000000000000111251173507505700167670ustar00rootroot00000000000000@html_text_substitution=readme.txt|readme.txt @external-css=allegro.css @document_title=Allegro `const'-correctness

Allegro `const'-correctness


This is a short document about the introduction of `const'-correctness to Allegro. It details what changes have occurred to internal library code, the API changes (mainly transparent) and what you will need to do to adapt code to compile without warnings (again, mainly nothing). @!text @heading Contents @shortcontents @text @heading Library changes There are very few actual changes to the library code itself; only some symbol declarations and definitions have been altered to include AL_CONST. See below for a description of the AL_CONST preprocessor define. In a few places, some string was changed that should not have been - in these cases, the string is simply duplicated and then the duplicate is erased on exiting the function. In all, there were very few changes to the library code. @heading The AL_CONST preprocessor define In order to support compilers which don't know about the `const' keyword, or perhaps use a different keyword, the preprocessor symbol AL_CONST is used wherever `const' would normally be used. Note that in the documentation, I have used `const' for readability. @heading Allegro API changes These are, generally speaking, totally transparent to the user. I did not change the behaviour of any function; only its parameter types. Basically, if you can pass it as type* ptr, then you can pass it as const type* ptr without any problem whatsoever. Note also that certain changes may remove warnings in your program as static strings, etc, are now treated as `const' by Allegro functions. There are a few places, described below, where there will be an effect on existing code. `const'-correctness is deemed important for two reasons. Firstly, it can increase code readability and comprehension of Allegro functions (for instance, you can see which parameters are altered and which are not). Secondly, it ensures that the Allegro code is not changing data which it should not be, and that client callback functions are not breaking Allegro by changing data they should not be. @heading Callback functions and Pointers to Pointers Certain callback functions now have a different type - they take `const' pointers as opposed to non-`const' pointers. As far as I know, a compiler will issue a warning about incompatible pointer types. You should update your callback function to the new format (which will be listed in the main Allegro documentation). Also, when passing a pointer to a pointer to an Allegro function which is declared as taking an AL_CONST type** ptr, you will need to cast your pointer to be `const' if it is not already. For instance: int some_allegro_function(AL_CONST char** p); void my_func(char** x) { some_allegro_function((AL_CONST char**) x); } I realise that this is a change to the Allegro API, and that we are supposed to avoid those at all costs, but this is essentially fixing a bug in Allegro and changing behaviour. It also ensures that client-supplied callback functions are functioning correctly, and not altering data that they should not. Callback functions which do not treat relevant parameters as `const' are, in a small (but potentially signficant) way, broken. Please note that for the Unicode function ugetx(), I have provided an alternative version ugetxc(), which takes a `const char**' parameter as opposed to a `char**' parameter. This is because it is valid to pass either a `char**' or a `const char**', but unfortunately there is no way to tell the compiler exactly what we mean. @heading BITMAP objects Allegro represents both a screen bitmap and a memory bitmap by a single object; a BITMAP. Unfortunately, these two things can be very different. For instance, reading a pixel from a bitmap would not seem to change it, but if it is a screen bitmap we are reading from, then it is possible that some parameter of the video card is changed to select the correct line, etc. Therefore, a const BITMAP parameter does not make sense, and is not used throughout the library. This is unfortunate, but I cannot see any way around it. @heading Finally... Allegro `const'-correctness has been tested for quite enough time to say that it is working OK. However, if you still find problems with a compiler, please contact the Allegro mailing list; see `Contact info' in the Allegro documentation (readme.txt). Email: lwithers@lwithers.demon.co.uk. Thanks for listening :-) allegro4.4-4.4.2/docs/src/dat._tx000066400000000000000000000140611173507505700164130ustar00rootroot00000000000000@external-css=allegro.css @document_title=dat

The DAT archiver


@heading Commandline options As an alternative to the graphical grabber program, you can use the command line dat utility. This accepts the following options: '-a <files>' Adds the named files to the datafile, for example: dat myfile.dat -a title.pcx scream.wav If the objects are already present in the datafile, their current contents will be replaced. Names for the new objects will be generated from the input filenames, and the object type will be detected from the file extensions. In some cases this is ambiguous, for example a PCX file can be read as a bitmap, RLE sprite, compiled sprite, or font object, so you may need to explicitly specify the object type with the '-t' flag. For example, to insert alien.pcx as an RLE sprite, use the command: dat myfile.dat -a alien.pcx -t RLE '-bpp colordepth' Specifies which color format bitmap data should be grabbed in (valid depths are 8, 15, 16, 24, and 32 bits per pixel). '-c0' - no compression '-c1' - compress objects individually '-c2' - global compression on the entire datafile Sets the compression mode (see below). These can be used on their own to convert a datafile from one format to another, or in combination with any other options. '-d <objects>' Deletes the named objects from the datafile. '-dither' Dithers graphics when reducing color depths. '-e <objects>' Extracts the named objects from the datafile. To extract everything, use the wildcard * as the object name. To set the output filename or directory, use the '-o filename' option. For example, to extract an object called TITLE_SCREEN to the file title.pcx, use the command: dat myfile.dat -e title_screen -o title.pcx To extract the entire contents of the datafile to the directory c:\output, use: dat myfile.dat -e * -o c:\output\ '-f' Stores the references to original files as relative filenames instead of absolute filenames. This greatly increases the portability of complete source trees containing the source data. '-g x y w h' Grabs bitmap data from a specific grid location. '-h outputfile.h' Sets the output header file, for exporting object index definitions. This may be used on its own to produce a header file from an existing datafile, or in combination with any other commands. You can also use the '-p prefixstring' option to set a prefix string for the object definitions. '-k' Keep original names while grabbing objects. Without this switch, a file called image.pcx will be imported as an object called IMAGE_PCX, to ensure that all the object names are valid symbols for the output header defines. '-l' Lists the contents of the datafile. This can be combined with the '-v' option to list object properties along with the names, and you can specify particular objects to produce a partial listing. '-m dependencyfile' Writes a set of makefile dependencies into the specified file, which can be used to automatically update the file whenever any of the source data changes. '-n0' - no sort: list the objects in the order they were added '-n1' - sort the objects of the datafile alphabetically by name Sets the sort mode (see below). These can be used on their own to sort the objects of the datafile, or in combination with any other options. '-o output' Sets the output file or directory when extracting data. '-p prefixstring' Sets the prefix for the output header file. '-pal objectname' Specifies which palette to use. '-r' Recursively adds directories as nested datafiles. This makes it possible to maintain the data hierarchy within the datafile. '-s0' - no strip: save everything '-s1' - strip grabber specific information from the file '-s2' - strip all object properties and names from the file '-s-PROP' do not strip object property PROP from the file Sets the strip mode (see below). These can be used on their own to strip properties from the datafile, or in combination with any other options. '-t type' Sets the object type when adding files. '-transparency' Preserves transparency when converting between color depths. '-u' Updates the contents of the datafile. See below. '-v' Selects verbose mode. This can be used in combination with any other options to produce more detailed output. '-w' Always updates the entire contents of the datafile. '-x <objects>' Alias for '-e <objects>'. '-007 password' Sets the file encryption key. '<objects> PROP=value' Sets properties for the specified objects. This works like environment variables, in that setting a property to an empty string removes it. Because object names are stored as NAME properties, you can use this command to rename objects. For example, to rename MY_OBJECT to WHAT_A_SILLY_NAME, use the command: dat myfile.dat my_object NAME=what_a_silly_name You can use the wildcard * to apply the property to everything in the file, so to remove the ORIG property from the entire datafile, you could execute: dat myfile.dat * ORIG= You can create hierarchical nested datafiles by inserting one datafile into another with the '-a' command. Objects in the nested datafile can then be referred to by as "parentname/objectname". For example if the datafile myfile.dat contains a nested datafile called nestedfile, which contains a bitmap called thepicture, you could export the bitmap with the command: dat myfile.dat -e nestedfile/thepicture -o output.pcx allegro4.4-4.4.2/docs/src/dat2c._tx000066400000000000000000000060201173507505700166340ustar00rootroot00000000000000@external-css=allegro.css @document_title=dat2c

The dat2c utility


@!text @heading Contents @shortcontents @text @heading Introduction The utility dat2c can be used in much the same way as dat2s, above, except that it writes C code rather than assembler. This has the advantage that it is portable - you can compile it anywhere you can use Allegro. @heading Commandline Options Each option may appear only once. To specify which datafile to convert, give the filename without a preceding option. --cfile, -o Arguments: filename Gives the name of the C source file to output. Won't add a .c extension, even if you don't specify one. By default, dat2c will write to stdout. --hfile, -h Arguments: filename Gives the name of the C header file to output. Won't add a .h extension, even if you don't specify one. --prefix, -p Arguments: prefix (must be a valid macro name) If you specify a prefix, then this will be used when constructing a macro name for each object in the datafile. This is the same as the grabber; if you don't specify a prefix, the macro name is simply <obj_name>, but if you do, then the macro name becomes <prefix>_<obj_name> . --crlf, -C Arguments: none Forces the file to be output in CRLF (DOS) format. This is the default on DOS/Windows platforms. --unix, -U Arguments: none Sets the output to be in Unix (LF only) text format. This is the default on non-DOS non-Mac platforms. --mac, -M Arguments: none Sets the output to be in Macintosh (CR only) text format. This is the default on Mac platforms. --global, -g Arguments: none Specifies that the objects should be globally visible (default is for objects to be local to the compilation unit). If they are globally visible, then you can refer to them in your code. --convert-compiled-sprites, -S Arguments: none (See note below for more info on compiled sprites). Tells dat2c to convert any compiled sprite objects it finds into bitmap objects. More a convenience feature for lazy people :-) --datafile-name, -n Arguments: C identifier By default, the datafile is exported as: PREFIX_data or data But with this option, you can change 'data' to be something else. @heading Notes - If your datafile contains truecolor images, be sure to call fixup_datafile() after you have set the graphics mode. You must also call fixup_datafile() if your platform does not support constructors (currently any non GCC-based platform). - Compiled sprites are *not* supported (but see the commandline option --convert-compiled-sprites , above). This is because Allegro silently switches to an RLE_SPRITE implementation on platforms which don't support compiled sprites, and to get dat2c to implement that behaviour would be more effort than it is worth (especially since you can just call get_compiled_sprite() anyway!). allegro4.4-4.4.2/docs/src/dat2s._tx000066400000000000000000000050141173507505700166560ustar00rootroot00000000000000@external-css=allegro.css @document_title=dat2s

The dat2s utility


@heading Compiling Datafiles to Assembler The utility dat2s can be used to convert a datafile into an asm (.s) source file, which can then be assembled and linked into your program. This avoids the need for a separate datafile to accompany your program, and means the data will automatically be loaded into memory at startup. You should be aware, though, that large datafiles can take a long time to compile, and that it is not possible to compress data which is compiled in this way. The simplest way to invoke dat2s is with the command: dat2s filename.dat -o output.s The resulting asm file can then be assembled with the command: gcc -c output.s This will produce an object module called output.o, which can be linked into your program, for example: gcc myprog.c -o myprog.exe output.o -lalleg Your program can then access the contents of the datafile as simple global variables. Definitions for these variables can be obtained by telling dat2s to output a header file as well as the asm file, with the '-h' option. You can also use '-p' to set a prefix string for all the object names. For example, when applied to the datafile: "BMP" - A_BITMAP "BMP" - ANOTHER_BITMAP "SAMP" - EXPLODE "PAL" - SOME_COLORS "FONT" - THE_FONT the command: dat2s filename.dat -o output.s -h output.h -p item produces the header: extern BITMAP item_a_bitmap; extern BITMAP item_another_bitmap; extern SAMPLE item_explode; extern PALETTE item_some_colors; extern FONT item_the_font; extern DATAFILE item_data[]; You can refer to these objects directly, for example: blit(&item_a_bitmap, screen, 0, 0, 0, 0, SCREEN_W, SCREEN_H); Alternatively, you can use the datafile array for compatibility with code that was originally written for separately loaded datafiles, with the standard syntax item_data[index].dat. If your datafile contains truecolor images, be sure to call fixup_datafile() after you have set the graphics mode. You must also call fixup_datafile() if your platform does not support constructors (currently any non GCC-based platform). Note that compiled sprites are not supported and will cause dat2s to abort whenever it encounters one of them. However you can use the '-S' option to instruct dat2s to convert them to regular BITMAP objects. Note that datafiles compiled by dat2s must not be appended to shared objects, only to standalone executables. Use dat2c for this purpose. allegro4.4-4.4.2/docs/src/datafile._tx000066400000000000000000000253541173507505700174230ustar00rootroot00000000000000@external-css=allegro.css @document_title=Datafile format

Datafiles format information.


@!text @heading Contents @shortcontents @text @heading Introduction An Allegro datafile is a bit like a zip file in that it consists of lots of different pieces of data stuck together one after another, and optionally compressed. This means that your game doesn't have to clutter up the disk with hundreds of tiny files, and it makes programming easier because you can load everything with a single function call at program startup. Another benefit is that the LZSS file compression algorithm works much better with one large file than with many small ones. Datafiles have the extension .dat, and can be created and edited with the graphical grabber program or the command line dat utility. They can be stored as separate files and loaded into memory by the load_datafile() function, or you can use dat2s to convert them into asm code which can then be linked directly into your executable. @heading Objects Each datafile contains a number of objects, of varying types. Object types are represented by 32 bit integer ID's, which are interpreted as four character ASCII strings. These ID's can be constructed with the DAT_ID() macro, for example a DATA object is represented by DAT_ID('D','A','T','A'), or you can use the predefined DAT_* constants for the standard data types:
  • DAT_FILE - "FILE"
    A datafile, which contains a list of other objects. Datafile objects can be nested inside other datafiles, allowing you to create hierarchical structures of any depth.
  • DAT_DATA - "DATA"
    A block of binary data. Allegro treats all unknown types as binary data objects, so you don't need to use this ID: you can create custom object formats using whatever ID's you like.
  • DAT_FONT - "FONT"
    A font.
  • DAT_SAMPLE - "SAMP"
    A digital sound sample.
  • DAT_MIDI - "MIDI"
    A MIDI file.
  • DAT_PATCH - "PAT "
    A Gravis patch (MIDI instrument).
  • DAT_FLI - "FLIC"
    An FLI or FLC animation.
  • DAT_BITMAP - "BMP "
    A bitmap.
  • DAT_RLE_SPRITE - "RLE "
    A run length encoded sprite.
  • DAT_C_SPRITE - "CMP "
    A compiled sprite.
  • DAT_XC_SPRITE - "XCMP"
    A mode-X compiled sprite.
  • DAT_PALETTE - "PAL "
    A 256 color palette.
  • DAT_PROPERTY - "prop"
    An object property (see below). You will never directly encounter this object type, but you should be aware that it is treated specially by the datafile code.
  • DAT_INFO - "info"
    The grabber utility uses this object to store information about the datafile. Like property objects, you ought never to encounter it, but you should avoid using the ID for any custom object formats you create.
  • DAT_END - -1
    Special marker used to indicate the end of a datafile.
@heading Properties Each object can have any number of properties attached to it. These are ASCII strings describing attributes of the object, such as its name and where it came from. Like the objects themselves, properties are identified by 32 bit integer ID's which are constructed from four character strings by the DAT_ID() macro. Allegro defines the standard properties:
  • "NAME"
    The name of the object.
  • "ORIG"
    The object's origin, ie. the name of the file from which it was grabbed.
  • "DATE"
    A timestamp, used by the update command in the grabber and dat utilities. This is the modification time of the file from which the object was grabbed, in "m-dd-yyyy, hh:mm" format.
  • "XPOS"
    For bitmap objects which were grabbed from part of a larger image, the x position of the origin within the parent bitmap.
  • "YPOS"
    For bitmap objects which were grabbed from part of a larger image, the y position of the origin within the parent bitmap.
  • "XSIZ"
    For bitmap objects which were grabbed from part of a larger image, the width of the selected region.
  • "YSIZ"
    For bitmap objects which were grabbed from part of a larger image, the height of the selected region.
  • "XCRP"
    For autocropped bitmap objects, the amount of cropping on the left of the image.
  • "YCRP"
    For autocropped bitmap objects, the amount of cropping at the top of the image.
You can use whatever other ID's you like to store custom information about your objects (the grabber internally use some other properties stored in a hidden DAT_INFO object, so they won't conflict with yours). @heading File format specification In case anyone wants to do some serious hackery, and for my own future reference, here are some details of the innards of the datafile format. Note that this is different to the datafile format used by Allegro versions 2.1 and earlier. Allegro can still load files from the old format, but it was much less flexible and didn't support nice things like object properties, so you should load any old files into the grabber and save them out again to convert to the new format. Nb. if all you want to do is write a utility that manipulates datafiles in some way, the easiest approach is probably to use the helper functions in datedit.c, which are currently shared by the dat, dat2s, and grabber programs. These functions handle loading, saving, inserting and deleting objects, and modifying the contents of datafiles in various ways, but life is too short for me to bother documenting them all here. Look at the source... Anyway. All numbers are stored in big-endian (Motorola) format. All text is stored in UTF-8 encoding. A datafile begins with one of the 32 bit values F_PACK_MAGIC or F_NOPACK_MAGIC, which are defined in allegro.h. If it starts with F_PACK_MAGIC the rest of the file is compressed with the LZSS algorithm, otherwise it is uncompressed. This magic number and optional decompression can be handled automatically by using the packfile functions and opening the file in F_READ_PACKED mode. After this comes the 32 bit value DAT_MAGIC, followed by the number of objects in the root datafile (not including objects nested inside child datafiles), followed by each of those objects in turn. Each object is in the format: OBJECT = var - <property list> - any properties relating to the object 32 bit - <type ID> - object type ID 32 bit - <compressed size> - size of the raw data in the file 32 bit - <uncompressed size> - see below var - <data> - the contents of the object The property list can contain zero or more object properties, in the form: PROPERTY = 32 bit - <magic> - "prop" 32 bit - <type ID> - property type ID 32 bit - <size> - size of the property string, in bytes var - <data> - property string, _not_ null-terminated If the uncompressed size field in an object is positive, the contents of the object are not compressed (ie. the raw and compressed sizes should be the same). If the uncompressed size is negative, the object is LZSS compressed, and will expand into -<uncompressed size> bytes of data. The easiest way to handle this is to use the pack_fopen_chunk() function to read both the raw and compressed sizes and the contents of the object. The contents of an object vary depending on the type. Allegro defines the standard types: DAT_FILE = 32 bit - <object count> - number of objects in the sub-file var - <object list> - objects in the same format as above DAT_FONT = 16 bit - <font size> - 8, 16, -1, or 0 if font size == 8 { - obsolete as of version 3.9.x! unsigned char[95][8] - 8x8 bit-packed font data } if font size == 16 { - obsolete as of version 3.9.x! unsigned char[95][16] - 8x16 bit-packed font data } if font size == -1 { - obsolete as of version 3.9.x! 95x { 16 bit - <width> - character width 16 bit - <height> - character height var - <data> - character data (8 bit pixels) } } if font size == 0 { - new format introduced in version 3.9.x 16 bit - <ranges> - number of character ranges for each range { 8 bit - <mono> - 1 or 8 bit format flag 32 bit - <start> - first character in range 32 bit - <end> - last character in range (inclusive) for each character { 16 bit - <width> - character width 16 bit - <height> - character height var - <data> - character data } } } DAT_SAMP = 16 bit - <bits> - sample bits (negative for stereo) 16 bit - <freq> - sample frequency 32 bit - <length> - sample length var - <data> - sample data DAT_MIDI = 16 bit - <divisions> - MIDI beat divisions 32x { 32 bit - <length> - track length, in bytes var - <data> - MIDI track data } DAT_FLI = var - <data> - FLI or FLC animation, standard format DAT_BITMAP = DAT_C_SPRITE = DAT_XC_SPRITE = 16 bit - <bits> - bitmap color depth 16 bit - <width> - bitmap width 16 bit - <height> - bitmap height var - <data> - bitmap data Valid color depths are 8, 15, 16, 24, 32, and -32. Both 15 and 16 bit images are stored in 5.6.5 RGB format, and 24 and 32 bit images as 8.8.8 RGB. The special -32 flag indicates that the data is in true 32 bit RGBA format. DAT_RLE_SPRITE = 16 bit - <bits> - sprite color depth 16 bit - <width> - sprite width 16 bit - <height> - sprite height 32 bit - <size> - data size, in bytes var - <data> - RLE compressed sprite data Valid color depths are 8, 15, 16, 24, 32. and -32. Both 15 and 16 bit images are stored in 5.6.5 RGB format with 16 bit skip counts and EOL markers, and 24 and 32 bit images as 8.8.8 RGB. with 32 bit skip counts and markers. The special -32 flag indicates that the data is in true 32 bit RGBA format. DAT_PALETTE = 256 x { 8 bit - <red> - red component, 0-63 8 bit - <green> - green component, 0-63 8 bit - <blue> - blue component, 0-63 8 bit - <pad> - alignment padding } I think that covers everything. allegro4.4-4.4.2/docs/src/faq._tx000066400000000000000000001044071173507505700164160ustar00rootroot00000000000000@# @# This is the source for the Allegro FAQ list, in a weird custom format. @# Read makedoc.c for a description of what is going on... @# @html_text_substitution=readme.txt|readme.txt @html_text_substitution=allegro.txt|allegro.txt @document_title=Allegro FAQ @html_spaced_list_bullet @!html @!rtf ___ _ _ _____ ___ ___ / _ \| | | ___ __ _ _ __ ___ | ___/ _ \ / _ \ | |_| | | |/ _ \/ _` | '__/ _ \ | |_ | |_| | | | | | _ | | | __/ (_| | | | (_) | | _|| _ | |_| | |_| |_|_|_|\___|\__, |_| \___/ |_| |_| |_|\__\_\ |___/ @html @external-css=allegro.css @rtf @!text

The Allegro FAQ
If the answer isn't here, ask and it will be added...


@!text @heading Contents @shortcontents @text Note that this FAQ list is rather old, and much of it won't apply to Allegro 4.4. For example, the build system has completely changed. Still, you might find some useful hints here. @heading Trivial problems
@@ What is Allegro? See readme.txt. @@ Where can I get it? From the Allegro homepage, http://alleg.sourceforge.net/. @@ How do I use it? See allegro.txt.
@heading The giftware licence The Allegro licence is absolutely clear unless you are a lawyer. However, it's written quite informally so this mini-FAQ tries to clarify some things.
@@ Does the licence mean that Allegro is public domain? No. Every Allegro contributor holds the copyright for the code he or she wrote. This means he or she grants you the right to use it for any purpose you want. But the fact that the contributor holds the copyright means that you e.g. cannot claim that you wrote the code. @@ Can I use Allegro for commercial purposes? Yes. @@ Is Allegro compatible with licence XXX (e.g. GPL)? Because the Allegro licence has no restrictions on use you can combine it with any licence you want. @@ Is Allegro open source (OSI) compatible? See the previous question. Since Allegro is compatible with about any license, it also is OSI compatible. It clearly is compatible with all the points in the OSD (open source definition). You can search the OSI mailing list for "Allegro" to see that OSI shares this view. (OSI officials still were reluctant to consider it for approval though and suggested to use an existing license like MIT instead.) @@ How are modifications of the library licensed? You can modify Allegro and distribute the modified Allegro under any licence you want, but the original unmodified parts will still be licenced under the Allegro licence. If you offer your modifications to be included in the official Allegro distribution (e.g. by sending them to the Allegro developers mailing list) you automatically agree with licencing the modification under the Allegro licence. @\ I took your code. Will you sue me? @@ Your library destroyed my PC. Who do I sue? We are programmers not lawyers. This FAQ represents our current understanding of copyright law (or copyright laws in different countries). But given the license, which allows everything, and the disclaimer, which says we take no responsibility for anything, we really don't see how there could be any problems.
@heading DJGPP problems
@@ What is this make program that I'm supposed to run? Make is part of the standard djgpp distribution, in the file v2gnu/mak*b.zip (whatever the latest version number is). You can get this from http://www.delorie.com/djgpp/. @@ Make doesn't work properly. Are you sure that you have installed djgpp correctly? Check the instructions in the djgpp readme.1st file, and in particular confirm that you have set the DJGPP environment variable and added the djgpp\bin directory to your path. @@ My djgpp installation is fine, but make still doesn't work properly. Are you sure that you are using the GNU make program, and not some other version like the Borland one? If in doubt, run make -v and check that the GNU copyright message is displayed. @@ When I run make, it asks me for some parameters. What do I type? You shouldn't be running make from the Win95 explorer! Bring up a DOS box, change to your Allegro directory, and type make at the command prompt. @@ When I run make, it says "makefile has modification time in the future". Are you sure that your system time and date are set correctly? Alternatively you may have downloaded a fresh file made by someone in a more eastern timezone. In the latter case you can either wait a few hours, temporarily set your clock forward, or use a utility such as touch to change the timestamp of the files. @@ When I run make, it says "virtual memory exhausted". As the error message suggests, you need to provide more memory for the compiler to use. The go32-v2 program will tell you how much is currently available. If you are running under DOS, try to free up more disk space for use as a swapfile. When using win95, increase the DPMI memory limit in the properties for your DOS session to 65535 (you'll have to type this in by hand, because the pulldown list doesn't go above 16384). @@ When I run make, it says "conflicting types for va_list". As the error message suggests, there is a conflict between newer versions of gcc and older versions of the libc. You must upgrade your djdevxxx.zip package to the latest update (timestamp 11 August 2002) of DJGPP-2.03 or above. @@ When I try to compile a program using Allegro, I get lots of errors like: C:\TEMP\ccdaaaaa(.text+0x9):x.c: undefined reference to `allegro_init'
C:\TEMP\ccdaaaaa(.text+0xe):x.c: undefined reference to `install_keyboard'
You haven't read the docs, have you? :-) You need to link your program with the library file, liballeg.a. First, make sure you have installed everything properly (running make install should do this for you). Second, if you are compiling from the command prompt or with a makefile, add -lalleg to the end of your gcc command line, or if you are using Rhide, go to the Options/Libraries menu, type alleg into the first empty field, and make sure the box next to it is checked. @@ I give up: I can't compile this! Can you send me a precompiled version? No, sorry. For starters, liballeg.a is about 450k, but you'd probably also want various utilities like the grabber, sound setup, etc. And what about all the example programs? If we included compiled versions of everything, a binary distribution would be over 7 megs: way too big to be practical! More seriously though, there just isn't any reason why you can't build it yourself. A compiler is a deterministic process: given a particular input file and command line, it will always produce the same output. If this isn't working, you either have the wrong input files (ie. your copy of Allegro is broken in some way), or the wrong command line (it is hard to see how that could happen, since all you have to do is type make...) or your compiler is broken, ie. you didn't install djgpp properly. You need to find and fix the problem, not just sweep it under the carpet by getting someone else to compile Allegro for you... @@ Compile errors scroll off the screen too quickly for me to read them! GNU tools write their error messages to the error stream, stderr. Unfortunately command.com is too stupid to know how to redirect this, but fortunately DJ was smart enough to work around that, so you can use his redir program to capture the output messages, for example
         redir -eo make > logfile.txt
      
@heading DOS problems
@@ Does the DOS version of Allegro work under Windows NT? Your mileage may vary. Some people have reported problems, while others say that it works fine. Use the Windows version of Allegro if you want to make Windows programs. If you want to run DOS programs, use DOS! @@ Does Allegro work under OpenDOS? Yes, but with some caveats. If you are using the OpenDOS version of EMM386, you must disable their DPMI implementation (specify DPMI=OFF on the EMM386.EXE device line in your config.sys). You should also make sure the PIC=OFF flag is set, but this is the default so it won't be a problem unless you have specifically enabled it. @\ How can I extend the 256k limit on Mode-X video memory? @@ I have two megs in my card. You can't. The limit is imposed by the VGA hardware, not by Allegro. To access more than 256k of video memory you need to use an SVGA mode, which means either switching to a higher resolution or getting a copy of the SciTech Display Doctor, which provides several low resolution SVGA modes. @@ Does DOS Allegro work with the SB-Live soundcard? It does for some people, but not for others. The problem is that Creative Labs refuse to release any specs, so we don't know how to write a driver for it. Complain to them, or buy a different card from a more reasonable manufacturer. @@ Why does DOS Allegro play sounds so much quieter than in Windows? This might be because you have the volume set very low: try changing this in the setup program. Also, Allegro is mixing several sounds into a single output buffer, unlike the Windows sound player that only plays one sample at a time, so each individual sound can only get a smaller percentage of the total output volume. This is just the price you pay for multiple output channels. If you don't like it, use the setup program to tweak the number of channels: this can be any power of two less than or equal to 64, and the smaller you make it, the louder the sound will be. Alternatively, use set_volume_per_voice(), described in the docs. This will enable you to adjust the overall volume of Allegro's digital sound output. @@ Why doesn't it work with my video card? Try using a FreeBE/AF driver (http://www.talula.demon.co.uk/freebe/), or the commercial SciTech Display Doctor (http://www.scitechsoft.com). If it still doesn't work, post a description of your problem to the Allegro mailing list, along with a copy of the output from running the afinfo and vesainfo programs. @@ Why not use some sort of dynamic linking system? The VBE/AF interface already provides this for the video drivers: see the FreeBE/AF project on http://www.talula.demon.co.uk/freebe/. For more general things like the sound, VESA, and mode-X routines, this would be very difficult to do because the drivers depend on a lot of helper functions from the core lib. The djgpp DXE format is nowhere near flexible enough to support this, and we don't want to make Allegro dependent on any other dynamic linking packages. @\ I get an "out of environment space" error when I run fix.bat or @@ vcvars32.bat! Well duh, you need to increase the size of your environment then :-) You can do this by changing the settings for your DOS box (click the system menu and select "properties"), or at startup in your config.sys file (eg. shell=c:\command.com /e:8192 /p).
@heading Windows problems
@\ I get an "out of environment space" error when I run fix.bat or @@ vcvars32.bat! Well duh, you need to increase the size of your environment then :-) You can do this by changing the settings for your DOS box (click the system menu and select "properties"), or at startup in your config.sys file (eg. shell=c:\command.com /e:8192 /p). @@ When I run make, it says "missing separator". Make sure that you don't have a semi-colon appended to your MSVCDIR variable if you are using MSVC, to your MINGDIR variable if you are using MinGW or to your BCC32DIR variable if you are using BCC. Also run make -v from the command line and make sure you are using GNU make and not Borland make or Microsoft make. @@ I get lots of compile errors about things like "LPDIRECTDRAWSURFACE2"! You need to tell your compiler how to find the DirectX include files and libraries: put the DirectX SDK /include and /lib directories in the compiler/linker path. Alternatively, if you don't want to modify any configuration stuff, you can simply copy the files from the DirectX SDK /include and /lib directories to the corresponding ones for your compiler. @@ I get lots of compile errors about things like "DDEDM_STANDARDVGAMODES"! You need to upgrade to a more recent version of the DirectX SDK, at least version 5, which you can get from the Microsoft Developer site. @@ When I run make, it says "windres: no resources". If an anti-virus software (Norton or McAfee for example) is running in the background on your computer, try to disable it temporarily. @@ I get an error about a missing WinMain() or main() function! You need to write END_OF_MAIN() just after your main() function. Allegro uses this, along with some preprocessor magic, to turn a normal main() function into a Windows-style WinMain() entry point. @@ I get an error about an "unresolved external symbol _main"! Make sure you're building a Windows GUI Application, and not a Windows Console Application. This is a setting when you create the project in MSVC, Dev-C++ or Borland C++ Builder. Alternatively, this is specified on the command line by the -subsystem:windows option for the MSVC linker, by the -Wl,--subsystem,windows option for the MinGW compiler or the -tW option for the Borland C++ compiler. Either that, or define the preprocessor symbol ALLEGRO_USE_CONSOLE prior to including Allegro headers if you really need the console for your program. @@ I get lots of compile errors about conflicting types for "struct BITMAP"! If your program directly includes Win32 API header files, see the "Windows specifics" section of the documentation.

If your program only includes header files of the C++ standard library, you're very likely trying to compile it with gcc 3.x for MinGW; if so, define the symbol __GTHREAD_HIDE_WIN32API on the compiler command line:

         g++ -D__GTHREAD_HIDE_WIN32API program.cpp -lalleg
      
@\ In windowed mode artifacts are left on the desktop when the window @@ is moved or when another window is placed on top of it. Disable direct updating for the DirectX windowed driver by using the dedicated configuration variable. See the 'Configuration routines' section in the docs and the allegro.cfg template file for more detailed informations. @\ In windowed mode the screen stays black unless the window is placed @@ under another window on the desktop. Disable direct updating for the DirectX windowed driver by using the dedicated configuration variable. See the 'Configuration routines' section in the docs and the allegro.cfg template file for more detailed informations.
@heading Unix problems
@@ I get an error about "_mangled_main_address" being undefined! You need to write END_OF_MAIN() just after your main() function. Allegro uses this, along with some preprocessor magic, to get a copy of your argv[] parameters (it needs those for various internal things). @@ I get an error about a duplicate definition of the "_main" symbol! You are probably on a Darwin/MacOS X system. If so, make sure the symbol USE_CONSOLE is not defined in your program: it is a deprecated symbol that must be replaced by ALLEGRO_USE_CONSOLE. Also note that the magic main can't be disabled on such a system: you simply can't define the symbol ALLEGRO_NO_MAGIC_MAIN in a program linked against Allegro. @@ Compile errors scroll off the screen way too quickly for me to read them! You need to redirect stderr into a file, so you can view them later. The method for doing this depends on your shell: if you are using a Bourne-style shell like bash, try make 2> logfile.txt @\ When I try to run Allegro programs, I get "error while loading shared libraries: @@ liballeg.so.4.1: cannot open shared object file: No such file or directory". You need to teach the dynamic linker where to find the Allegro shared library. See docs/build/unix.txt, near the end of the 'Installing Allegro' section. @\ When I try to use DGA2, I get "resolution not supported", but the @@ X server does actually support that resolution ! There are two possible reasons: 1) DGA2 may support different resolutions/color depths than X, run the gfxinfo program to know what combinations you can use, 2) You may have a buggy DGA2 implementation, see next question. @\ When I try to use DGA2, the screen goes black and the PC completely @@ halts! You are probably using a XFree86 server with a very buggy DGA2 implementation, such as 4.0.3 (shipped with Red Hat 7.1 for example). Upgrading to 4.1.0 will probably solve your problem. You can obtain it from ftp://ftp.xfree86.org/pub/XFree86/4.1.0/binaries/ selecting the directory suited to your platform and following the instructions you find in the Install file.
@heading General problems
@@ I'm trying to compile the grabber, but it doesn't work! The grabber needs to be linked with the code in datedit.c. But you shouldn't have to worry about doing this by hand: just run make and that will build everything for you. @\ When I compile Allegro, make fails with something like `Error: operands @\ given don't match any known 386 instruction' or `Error: no such @@ instruction `maskmovq %mm3, %mm1''. You need to update your version of GNU binutils. See readme.txt to find out what the minimum required version you need is. @@ Can I use Allegro with my <foobar> compiler? Not unless <foobar> is mentioned in readme.txt as one of the supported platforms. You could port it, but that is usually a lot of work. If <foobar> is a 16 bit DOS compiler like Borland C, you might as well just forget the idea :-) @@ What is this "Allegro WIP" that I see people talking about? WIP stands for "work in progress", and refers to any changes that are more recent than the last official release. WIP versions of the library can be obtained as patches from the Allegro website (http://alleg.sourceforge.net/), and are usually quite stable, although obviously not so well tested as a final release version. @@ I got the WIP patch, but I can't apply it. Do you have a copy of patch.exe? If not, go and get it from the same place that you downloaded the rest of djgpp: this tool is a standard part of the compiler distribution. Similarly, you can get the Mingw compiled version from http://sourceforge.net/projects/gnuwin32/.

If you do have the patch program but it isn't working properly, make sure that you are installing the patch over the top of an unmodified copy of whatever Allegro version it is intended to update (this will usually be the most recent official release from before the WIP was made, but check the text file that comes with the WIP to be sure). @\ How can I display several different images at the same time? @@ When I show the second one it messes up the palette for the first. This is just the way that the video hardware works: there can only be one palette in use at any given moment. Either convert your images so they all use the same palette, or switch to a truecolor graphics mode. @@ How can I convert my graphics to all use the same 256 color palette? See the Allegro.cc homepage (http://www.allegro.cc/) for some utilities, for example FixPal and Smacker. @\ My colors always come out wrong. And how can I make a greyscale palette @@ with 256 different shades? The VGA hardware only uses 6 bits for each color component, which means the red, green, and blue values in the palette structure range from 0 to 63, not all the way up to 255. That gives you a potential 2^18 = 262144 different colors, or 64 shades of grey. If you need more than this you could try using VESA function 0x4F08 to select an 8 bit wide DAC, but Allegro doesn't support this directly and I don't know how reliable it will be across different hardware. @@ Why do I have a funny color border at the edges of my monitor? When you are in a 256 color mode, the VGA card displays color #0 around the border of the display area (in truecolor modes it displays black). Your funny color will go away if you change the palette so that color #0 is black. @@ How can I fade the screen in a truecolor graphics mode? With great difficulty :-) There is no such easy trick as just altering the palette, so you will have to repeatedly redraw the image in a lighter or darker form. You could draw black translucent rectangles over the screen to darken it down, or use draw_lit_sprite() to tint a bitmap while copying it to the screen, but be warned that these operations are expensive and will require a fast PC!

Also, have a look at http://www.allegro.cc/ for add-on packages (notably FBlend v0.5) that attempt to make this operation as fast as possible. @\ I tried using fade_in() and fade_out() with truecolor modes but nothing @@ happened. What am I doing wrong? fade_in() and fade_out() only work in 8-bit paletted modes. See the previous question for details. @@ How can I generate FLI or FLC format animations? See the Allegro.cc homepage (http://www.allegro.cc/) for some utilities, for example DTA and Smacker. Also, you can use ASE (Allegro Sprite Editor, http://ase.sourceforge.net/), which allows drawing/editing each frame of the animation and save it as a FLI. Or you can use The GIMP (http://www.gimp.org/) along with it's GFli plugin, using layers as frames, and saving your work as file.fli. The GIMP allows you to edit existent FLI files too. @\ How can I make parts of my sprite transparent in truecolor modes? @@ I don't understand what the docs mean by "bright pink"... In your favourite paint program, get hold of the RGB sliders and drag the red and blue ones up as far as they go (usually to 255, but this will depend on what units your software uses), and the green one right down to zero. The result is a special shade of Magic Pink, or as some people prefer to call it, magenta. @@ I can't get the 3D polygon functions to work! Remember that the vertex positions are stored in fixed point format, so you must use the itofix() macro or shift your coordinates 16 bits to the left. @@ I can't get the rotate_sprite() function to work! Remember that the angle of rotation is stored in fixed point format, so you must use the itofix() macro or shift your coordinates 16 bits to the left. For example, rotate_sprite(bmp, spr, x, y, itofix(32)) will rotate the graphic by 45 degrees. @@ I can't get the d_bitmap_proc() or d_icon_proc() GUI object to work! You are probably trying to initialise the dialog structure with a pointer to your bitmap, right? That won't work because the dialog is created at compile time, but the bitmap is only loaded at runtime, so the compiler doesn't yet know where it will be located. You need to fill in the dialog structure with a NULL pointer, and then copy the real bitmap pointer into the dp field as part of your program init code, after you've loaded the bitmap into memory. @@ Should I use regular bitmaps, RLE sprites, or compiled sprites? It depends on exactly what you are doing. If your images are totally opaque, there is no advantage to using an RLE sprite, and it will probably be faster to use a regular bitmap with the blit() function. If your graphics contain masked areas, an RLE sprite may be both smaller and faster than the draw_sprite() function, depending on your CPU and your bitmaps. Compiled sprites are in general quite a bit faster than both the others for masked images, and slightly faster for opaque graphics, but this is far more variable. They are at their best with small sprites, on older machines and in mode-X, and may actually be slower than blit() when using SVGA modes on a pentium (the large size of a compiled sprite is very bad for the cache performance). @@ How can I make my game run at the same speed on any computer? You need to make sure the game logic gets updated at a regular rate, but skip the screen refresh every now and then if the computer is too slow to keep up. This can be done by installing a timer handler that will increment a global variable at your game logic speed, eg: volatile int speed_counter = 0; void increment_speed_counter() { speed_counter++; } END_OF_FUNCTION(increment_speed_counter) void play_the_game() { LOCK_VARIABLE(speed_counter); LOCK_FUNCTION(increment_speed_counter); install_int_ex(increment_speed_counter, BPS_TO_TIMER(60)); while (!game_over) { while (speed_counter > 0) { update_game_logic(); speed_counter--; } update_display(); } } @@ How can I take a screenshot of my Allegro program? Add a call to save_bitmap() somewhere in your code. See the save_bitmap() documentation for a discussion of one common pitfall when doing this, and some example code. @@ How can I generate a random number? Call srand(time(NULL)) at the beginning of your program, and then use rand()%limit to obtain a pseudo-random number between 0 and limit-1. @\ Why not make a "lite" version of Allegro? @@ I don't need any of the sound, maths, or GUI routines... There is no need. The linker will only include the parts of the library that you actually use, so if you don't call any of, say, the texture mapping or FLIC playing functions, they will be left out of your executable. This doesn't work perfectly because a lot of the Allegro code uses tables of function pointers that cause some unnecessary routines to be linked in, so the majority of the graphics functions will be included in every executable, but I have tried to keep this to a minimum. See allegro.txt for information about more precise ways to remove some of the graphics and sound drivers. @@ Will you ever add support for 3D accelerator hardware? No. This sort of hardware support would be most useful as part of a proper 3D API, which Allegro is not, and will never be. If you want to do some work on this, the MESA library (a free implementation of OpenGL) is IMHO the place to start.

However, if you are interested in using OpenGL for graphics and Allegro for everything else, you can try the various add-ons libraries linked from http://www.allegro.cc/ such as AllegroGL. @@ Why not add a MOD playing function? Several very good ones already exist, for instance the JGMOD or DUMB packages. See the audio library extensions section on the Allegro.cc website (http://www.allegro.cc/). You are not allowed to suggest that one of these libraries be merged into Allegro, because this topic has already been done to death on the mailing list and we are tired of it. @@ Why not add networking support? There are several networking packages currently in development or floating around on the net, though, and in our opinion this sort of code is more useful as an external library than it would be as part of Allegro. @@ Why can't Allegro read GIF files? Unisys has a patent on the LZW compression algorithm that is used by the GIF format. We want everything in Allegro to be freely usable without any restrictions whatsoever, which means we can't include any code that is subject to licensing or the payment of royalties. @@ My program crashes all the time. Could this be a bug in Allegro? Perhaps. Try to isolate the smallest fragment of code that is able to reproduce the problem, and we'll have a look at it. If you can send us a 10 line program, we will fix it. 100 lines, and we can probably fix it. 1000 lines, and we don't have a chance :-) @@ Can I use Allegro in my <whatever> commercial application? Sure. See the giftware terms in readme.txt. We don't mind what you do with it, and there are no problems with commercial usage. @@ When will <foobar> be finished? I can't wait... Whenever it is done! A little encouragement is always welcome, but we don't have any completion deadlines and we're not going to make one up for you :-) As soon as it is finished, it will be released. @@ Where can I get some fonts to use with Allegro? The grabber can import directly from GRX or BIOS format .fnt files, or you can draw them onto a .pcx image using any paint program. See http://www.talula.demon.co.uk/ttf2pcx/ for a utility that will convert Windows TrueType fonts into this .pcx format. @@ Where can I find a set of instrument samples for the DIGMID driver? See the Allegro homepage (http://alleg.sourceforge.net/) for some links. You can use Gravis patches (.pat format), or SoundFont 2.0 (.sf2) files, but the latter must be converted into a patches.dat file with the pat2dat utility. @@ How can I convert the documentation into Windows Help format? You need to download the makertf conversion utility (http://www.giffer.com/public/win/pwflemgt/Files/MKRTF104.ZIP), and the Windows Help compiler (ftp://ftp.microsoft.com/Softlib/MSLFILES/HC505.EXE). Make a temporary directory, copy the allegro.txi file from the allegro/docs dir, and run the commands makertf --no-warn allegro.txi -o allegro.rtf -J allegro.hpj followed by hcp allegro.hpj. The second command will give a lot of warnings, but they can safely be ignored. @@ How can I print out the documentation? The allegro.rtf file can be read directly into Microsoft Word and printed from there, but you should right-click and update the table of contents and index fields to fill them with the correct data first. Alternatively you can install the TeX package and use the tex and dvips programs to convert allegro.txi into Postscript format. @@ Where can I find example source code, add-on packages, and tutorials? Check the Allegro.cc homepage, http://www.allegro.cc/. If you have anything to add to this, please post the URL! @\ Why is it considered good coding practice to define PI as a constant, @@ rather than just using the value 3.141592 in my code? It simplifies the maintenance of your program, in case the value of PI ever needs to be changed. Also it will make your program more portable to other compilers that use different values of PI. @@ Why doesn't vsync() seem to work? A number of graphics cards have buggy or incomplete VESA implementations, and often the vsync() function is not implemented. For examples on flicker-free drawing, look at the code for the demo game shooter, which uses a variety of methods to draw itself. @\ Why doesn't busy waiting on the key array work? For example, @@ "while (!key[KEY_ENTER]);" doesn't work. If the code works without optimisations, then it could be the compiler's fault. You can try beating the compiler into submission, for example: while (!key[KEY_ENTER]) rest(0); For this case, however, it would be better to use readkey() instead. Or consider upgrading or downgrading your compiler. @@ I get lots of errors when I try to compile my C++ Allegro program. You are probably declaring the use of a namespace before including Allegro headers. For example: #include <iostream> using namespace std; #include <allegro.h> Move the `using' declaration after the `include' directives referring to Allegro headers: #include <iostream> #include <allegro.h> using namespace std; @@ I'm still confused. Where can I get help? See http://alleg.sourceforge.net/maillist.html.

allegro4.4-4.4.2/docs/src/grabber._tx000066400000000000000000000342331173507505700172520ustar00rootroot00000000000000@external-css=allegro.css @document_title=grabber

The grabber


@!text @heading Contents @shortcontents @text @heading Commandline options The grabber accepts a few different commandline options: '-bpp' Sets the color depth, eg. -8, -16, -32. '-WxH' Sets the screen resolution, eg. -320x200, -1024x768 '-windowed' Forces the grabber to start up in a window. '-fullscreen' Forces the grabber to start up in fullscreen mode. '-nosound' Disables audio output. '-pkey' Use 'key' as the datafile password. 'filename.dat' Loads the named datafile. @heading Using the grabber Various options can be set using the buttons and text fields at the top of the screen. You can edit the name of the datafile, the name of the header file for exporting object indexes (leave this blank if you don't want to output a header), and the prefix string for the header file definitions. You can change the grid settings for grabbing bitmaps, and alter the compression mode (see below). You can enable or disable backups: if this box is checked, the old version will be renamed to a .bak extension when datafiles are saved. You can also turn dithering on (this can improve the image quality when you reduce graphics from 15, 16, 24 or 32-bit color to 8-bit color and from 24 or 32-bit color to 15 or 16-bit color) and enable transparency preserving (this will ensure that the masked areas in bitmaps stay exactly the same through color conversion). The contents of the datafile are listed in the box at the bottom left of the screen, and can be selected with the mouse or arrow keys. Multiple objects can be selected by holding down the shift or control keys while you click on the list or move the cursor. The selected object can be edited with commands from the Object menu, or using the shortcut menu produced by pressing Esc or right-clicking on an object. Double-clicking on an object performs a function which varies depending on the type of the object. Bitmaps are displayed full-screen (use the plus and minus keys to zoom in and out), samples and MIDI files are played, palettes are selected (meaning that they will be used when displaying and exporting bitmaps), and fonts can be edited by adding and removing specific character ranges. @heading Modifying objects New objects can be created using the menus or by pressing Insert while the item list has the input focus. To make nested datafiles, create a FILE object (New/Datafile), and select it before inserting other objects. To insert information into a datafile you must first create an object of the appropriate type, and then select the grab command (keyboard shortcut ctrl+G). For most objects this will bring up a file selector for you to select the file to read, but for graphic objects (bitmaps, RLE sprites, compiled sprites, and palettes) it will grab from the current contents of the image buffer, so you must previously have read a picture into this buffer with the File/Read Bitmap command (keyboard shortcut ctrl+G). You can use the mouse or arrow keys to select which portion of the image to grab. With the mouse, select the top left corner, click and hold the left mouse button, and move to the bottom right corner before releasing the button. Press the right mouse button to cancel. With the keyboard, use the arrow keys to select the top left corner, press Space or Enter, adjust the size with the arrow keys, and press Space or Enter again. By default the position will snap to a 16x16 grid, which can be adjusted by changing the values in the X-grid and Y-grid fields. Alternatively you can use the Box Grab command, in which case you should draw a bounding box in color #255 around your sprites, and can then just click once inside a box to grab the contents. Note that palette data is not stored along with bitmap and sprite objects. To store the entire contents of a PCX or BMP file, you will need to create both bitmap and palette objects, and grab data into both of them. When you reload the datafile the bitmap will probably be displayed with the wrong palette. This can be corrected by double-clicking on the palette object, which will select its contents as the current palette, meaning that it will be used when displaying and exporting bitmaps. The properties of the selected object are listed in the box to the right of the item list. These can be edited by double-clicking on one of the properties, and deleted by selecting one and pressing Del. You can insert new properties by pressing Insert while the property list has the input focus, or using the Object/Set Property command. Object names are stored as NAME properties, so the rename command is simply a shortcut for editing this property. @heading Bitmap grabbing To simplify the process of grabbing several related images from a single bitmap (for example a set of frames which form an animation), you can use the File/Grab from Grid command. Like the normal bitmap grab command, this uses data from the image buffer, so you must read in a bitmap before you use it. You will then be able to adjust the grabbing parameters, enter a name for the new objects, and choose the type of object to create (bitmap, RLE sprite, or compiled sprite). Because several objects may be created, their names will be formed by adding a number to the end of the name you supply, for example if you enter "a_picture", the grabber will create the objects "a_picture000", "a_picture001", etc. There are two grabbing modes: using cutouts of color 255, and using a regular grid. The regular grid option simply divides the bitmap up into a set of equally sized tiles, using the specified grid size, and grabs each of these as a separate object. If you set the Skip Empties flag, the grabber will ignore tiles that don't contain any data (ie. those that are a single solid color). The color 255 option is more flexible. It expects the bitmap to contain information describing the position and size of each tile, in the form of a bounding box drawn in color 255. The most reliable way to do this is to fill all the image except the parts you want with color 255, but the grabber should be able to understand more complicated layouts, even if you simply draw color 255 lines along the top and left edges of the area you want to be grabbed. For truecolor images where color 255 is not particularly meaningful, use a cyan bounding box (maximum blue and green, zero red), with a single yellow (maximum red and green, zero blue) pixel in the top left corner of the box. @heading Configuration By default, the grabber will run in a 640x480 resolution, using the highest color depth possible on your graphics card. If you want to override this, you can specify an alternative color depth or resolution on the commandline, eg. "grabber -8" for a 256 color mode, "grabber -16" for 16 bit hicolor graphics, "grabber -320x200" to use VGA mode 13h, or "grabber 1024x768". Warning: editing datafiles that contain truecolor graphics is very slow in 256 color video modes, and the grabber is not really usable in resolutions lower than 640x400. You can configure the grabber to use external tools for editing data, by setting some variables in the [grabber] section of the allegro.cfg file. These are in the form "type=command", where the type is a four letter object ID, and the command is whatever program you want to be invoked to edit this kind of data. For these variables to be seen, the allegro.cfg file must either be in the same directory as the grabber executable, or in the directory pointed to by your ALLEGRO environment variable. To invoke this feature, select the Shell Edit command or press ctrl+Z. The grabber will try to invoke the tool on the original version of the file if it knows where you grabbed the data from in the first place, or otherwise it will write the object out into a temporary file prior to editing. @heading Saving datafiles Datafiles can be saved using any of three compression types, selected from the list at the top right of the grabber screen, or with the '-c0', '-c1', and '-c2' options to dat. With type 0, the data is not compressed at all. Type 1 compresses each object individually, while type 2 uses global compression over the entire file. As a rule, global compression will give better results than per-object compression, but it should not be used if you intend to dynamically load specific objects with the load_datafile_object() function or "filename.dat#objectname" packfile syntax. There are also three strip modes for saving datafiles, selected with the File/Save Stripped command in the grabber, or using the '-s0', '-s1', and '-s2' options to dat. With zero stripping, all object properties are written to the datafile, which is normally what you will want. With strip mode 1, properties specific to the grabber (the ones describing the origins and dates of each object) are removed, which will marginally reduce the file size, but will prevent the update command from working. For the smallest possible file sizes, strip mode 2 removes all properties, including object names and any custom properties you have added. This level of stripping should obviously be used with extreme caution, although in some cases it may be possible to recover the object names even after they have been stripped out of the datafile. If the grabber and dat utilities cannot find any name properties in a datafile, they will look for a header (.h) file with the same name, and attempt to parse this to recover the names. This is far from foolproof, and will not work for nested datafiles, but in some situations it allows the names to be read back from the index definition header. In addition to those three strip modes, you can define properties to be kept, whatever the strip mode. For example, if you want to strip all properties but the NAME, this command will do the job: dat -s2 -s-NAME file.dat The objects of the datafile can be sorted alphabetically by name. This is selected by the Sort checkbox in the grabber, or by using the '-n0' and '-n1' options to dat. With zero sorting, objects are listed in the order they were added to the datafile. With sort level 1, they are listed in alphabetical order according to their NAME property, including inside nested datafiles. @heading Updating datafiles Both the grabber and the dat utility have an update command, which scans through the datafile checking if any objects have changed, and replacing those which are out of date. This depends on the origin and date properties which were set when the data was grabbed in the first place, so it won't work if these properties have been stripped out of the file. This command can be very useful if you build a datafile containing hundreds of objects grabbed from external bitmaps, and later go back and change some of these bitmaps. Rather than having to figure out which objects are out of date and then manually re-grab all the affected data, the update command will automatically refresh the modified objects. @heading Fonts Fonts can be read from GRX format .fnt files, 8x8 or 8x16 BIOS format .fnt files, and from bitmap images, or you can import a multiple-range Unicode font by writing a .txt script that specifies a number of different source files for each range of characters. The script file contains a number of lines in the format "filename start end", which specify the source file for that range of characters, the Unicode value of the first character in the range, and the end character in the range (optional, if left out, the entire input file will be grabbed). If the filename is replaced by a hyphen, more characters will be grabbed from the previous input file. For example, the script: 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. When reading a font from a bitmap file, the size of each character is determined by the layout of the image, which should be a rectangular grid containing all the ASCII characters from space (32) up to the tilde (126), unless you are using the script mechanism described above, in which case the range(s) should match the one(s) specified in the .txt file. The spaces between each letter should be filled with color 255. If each character is sized exactly 8x8 or 8x16 the grabber will create a fixed size font, otherwise it will make a proportional font. Probably the easiest way to get to grips with how this works is to load up the demo.dat file and export the TITLE_FONT into a PCX file. Have a look at the resulting picture in your paint program: that is the format a font should be in... @heading Alpha channel Bitmap and RLE sprites can store an alpha channel along with the color information, as long as they are in a 32 bit format. Alpha data can be read directly from 32 bit TGA files, or you can use the alpha channel commands (in the Object menu, or the right mouse button popup menu) to import a greyscale alpha image over the top of an existing object. This menu also contains options for viewing the alpha channel of the selected object, exporting the alpha data to a greyscale image file, and deleting the alpha data to leave only pure color information. You can also use the File menu to import an alpha channel over the top of a bitmap that you have loaded with the Read Bitmap command, after which the alpha information will be included when you next perform a Grab or Grab From Grid operation. @heading Datafile passwords Datafiles can be encrypted with a password, by typing it into the "Password:" field in the grabber, or using the '-007 password' option to the dat utility. Passwords may be up to 256 characters in length, and are case sensitive. Encrypted files _cannot_ be read without the password, so please don't forget it and then come crying to me for help :-) To read an encrypted file into your program, call the packfile_password() function before load_datafile(). It is also a good idea to call packfile_password(NULL) afterwards, to set everything back to normal. allegro4.4-4.4.2/docs/src/help._tx000066400000000000000000000424501173507505700165760ustar00rootroot00000000000000@# @# This is the source for the how-to-get-help file, in a weird custom format. @# Read makedoc.c for a description of what is going on... @# @html_text_substitution=readme.txt|readme.txt @document_title=What to do when your Allegro program doesn't work @!html @!rtf ____ _ _ _ _ _ _ / ___| ___| |_| |_(_)_ __ __ _ | | | | ___| |_ __ | | _ / _ \ __| __| | '_ \ / _` | | |_| |/ _ \ | '_ \ | |_| | __/ |_| |_| | | | | (_| | | _ | __/ | |_) | \____|\___|\__|\__|_|_| |_|\__, | |_| |_|\___|_| .__/ |___/ |_| @html @external-css=allegro.css @rtf @!text

What to do when your Allegro program doesn't work


@heading Contents @shortcontents @text @heading Introduction When things go wrong, it often seems like a good idea to ask other people for help. Fortunately for people in this situation, there are many people (both Allegro developers and users) who are happy to spend their time answering support questions of this type, but there are various things you can do to make this process work more efficiently. This document describes some steps to take whenever you have a problem with an Allegro program, suggesting ways that you can try to solve it yourself, and also giving some tips about when/how to ask for help. Following these guidelines will make life easier both for the helper (because all the relevant information will be presented to them in a concise and useful way), and for the helpee (because they are more likely to get a prompt and accurate reply). @heading Part 1 - who is the culprit? Is the problem a bug in Allegro, or in your code? To find out, try running the Allegro test programs, in particular the test.exe (for graphics related problems), the play.exe (for soundcard troubles), and the entire contents of the examples directory (for anything that is going wrong). If you can't reproduce the problem with any of these, it is probably your fault, in which case you should skip to part 3 below. If the problem is related to DOS graphics modes, you should start by getting a copy of Display Doctor from http://www.scitechsoft.com/. If this fixes the trouble, it almost certainly means that your original VESA driver was broken in some way. I'm not interested in hearing reports about problems of this type: there is nothing I can do to fix them, so I'm afraid your only option is to get a better VESA driver, for instance by downloading Display Doctor. This is now free for download from SciTech's website, but there is no longer support for it. Alternatively, you can see if there is a FreeBE/AF driver for your card (see http://www.talula.demon.co.uk/freebe/). For Windows graphics modes, you should probably check if DirectX is installed properly on your system and if new drivers have been released for your card. @heading Part 2 - when Allegro is at fault If you still think the problem lies with Allegro, post a system report containing a description of the problem, what platform and library version you are using, your hardware specs, and a list of exactly which programs you were able to reproduce the problem with (it is important to know not only what programs had trouble, but also which ones worked correctly, if any). Try running the test.exe program with various display drivers (any native drivers that you think might work with your card), and in various video modes, and report exactly what modes and color depths cause problems. If you are able to use any high resolutions at all, run test.exe with the Autodetect option and report the entire text that it displays in the middle of the screen. If the problem is related to DOS graphics modes, you should also post the output from running the afinfo and vesainfo programs (the short version is enough unless you are explicitly asked to add the -v switch: all that extra data isn't usually needed). If the problem is related to the sound system, try using the setup program to manually configure your card. You may need to manually enter the hardware parameters, and if it is an SB clone card, try selecting some earlier breed of SB card than whatever it is autodetecting (SB Pro, SB 2.0, or SB 1.0). If you are still unable to get anything working, your post should include the name and descriptions of whatever digital and MIDI sound drivers are being autodetected (this information is displayed by the play.exe program). @heading Part 3 - when your program crashes @hnode crashes under DOS When a djgpp program crashes, you will usually get a stack traceback looking something like: Exiting due to signal SIGSEGV General Protection Fault at eip=00001eca [snip] Call frame traceback EIPs: 0x00001eca 0x00001590 0x00001aea This information tells you exactly where the crash occurred. To make sense of it, you should compile your program with debugging information (using the -g switch), and then run "symify program.exe" while this traceback is displayed onscreen. That will change the traceback to something along the lines of: Call frame traceback EIPs: 0x00001eca _strcpy+14 0x00001590 _main+56, line 7 of t.c 0x00001aea ___crt1_startup+138 In this case, you can see that the crash occurred in the strcpy() function, which was called at line 7 of the main() function in the t.c source file. Now you just have to go to that line, have a look at whatever you are doing there, and change it to be correct :-) Note: if the crash happens deep inside an Allegro function, this traceback may not be so useful. When this happens you can recompile Allegro with debugging information (see the readme file), and then link your program with the debugging library version. Note 2: even when this crash traceback points to one of the Allegro functions, that does not necessarily mean the Allegro routine is at fault. Anything will crash if you pass it invalid parameters, so unless you can duplicate the problem in one of the Allegro example programs, you should start out by assuming that it is a case of operator error and double-check exactly what you are passing to the Allegro function. @hnode crashes under Linux/Unix When your Allegro compiled Linux/Unix program crashes, you will usually get a not very meaningful message along with a core dump: Shutting down Allegro due to signal #11 Segment violation (core dumped) Look at your filesystem: there should be a file named core or something similar with information telling you exactly where the crash occurred. If there is no core, check your environment settings, under bash this is done with the 'ulimit -a' command. Usually 'ulimit -c unlimited' somewhere in your login scripts should work fine. Just like with djgpp, to make sense of the core, you should compile your program with debugging information (using the -g switch), and then run the GNU debugger on it "gdb binary core". That will load the debugger, print some information about linked libraries and leave you at a prompt. Now you can get the full backtrace: (gdb) backtrace #0 0x08065237 in utf8_getx (s=0xbffffc5c) at ./src/unicode.c:347 #1 0x0806953f in ustrzcpy (dest=0x0, size=2147483646, src=0x0) at ./src/unicode.c:1770 #2 0x08057575 in _mangled_main () at t.c:9 #3 0x0806c9bf in main (argc=1, argv=0xbffffd14) at ./src/unix/umain.c:39 #4 0x4015414f in __libc_start_main () from /lib/libc.so.6 In this case, you can see that the crash occurred in the ustrzcpy() function, which was called at line 9 of the main() function in the t.c source file. Now you just have to go to that line, have a look at whatever you are doing there, and change it to be correct :-) Note that the crash happened deep inside an Allegro function, which is also revealed by the traceback. However, the binary was linked against a static debug version of Allegro, we wouldn't have had so much luck with a non debug or dynamically linked version. Since gdb is an interactive debugger, you could also select a frame and check out the values of the variables, to see better who is the culprit: (gdb) frame 2 #2 0x08057575 in _mangled_main () at t.c:9 9 ustrcpy(p1, p2); (gdb) list 4 5 int main(void) 6 { 7 char *p1 = 0, *p2 = 0; 8 allegro_init(); 9 ustrcpy(p1, p2); 10 return 0; 11 } 12 END_OF_MAIN() (gdb) print p1 $1 = 0x0 (gdb) print p2 $2 = 0x0 Yuck! Playing with NULL values doesn't really pay off. Ok, while this was a slightly out-of-the-can example, you surely get the point. Remember to check out GDB's manual to learn about more useful commands and/or how to debug your program while it's running and many other things. You might also want to check out Peter Wang's "Debugging with GDB" article, featured in the ninth number of the Pixelate online magazine (http://pixwiki.bafsoft.com/). @heading Part 4 - things people don't do (but should) One of the most common errors made by programmers is to neglect to check the return value from a function that may fail. Such an error will often lead to unexpected and downright unusual errors, making for a debugging nightmare. There are many functions in and out of Allegro that may or may not work depending on varying circumstances. They are, however, nice enough to let you know whether or not they were successful through documented return values. Whenever you call a function that might fail (most importantly set_gfx_mode(), install_sound(), and anything that loads data from the disk), it is _essential_ that you check the return code from this, and respond accordingly. Another commonly forgotten but important tool is to use whatever option enables strict warnings for your compiler (gcc uses -Wall), when compiling your code. Any warnings reported by this option will almost certainly represent errors in your program, and should be fixed before doing anything else. When using gcc, a useful trick is to compile with the -O setting as well, because this causes gcc to examine the program's actions in more detail, enabling more useful warnings. You should normally disable optimisation while debugging, though. Although it gives better compile time warnings, it is likely to upset any debugging tools that you later try to use. @heading Part 5 - asking for help Ok, so you've tried everything described above, and your program still doesn't work. You have no idea what to do next, so it is time to cast yourself unto the mercies of the net, in hopes of finding some kind of wise man, seer, or oracle that holds an answer for your question... The best places to ask are the Allegro mailing list (see readme.txt for details) and the Allegro.cc forums. Please remember that the mailing list is an Allegro-specific list. Problems relating to the C language or djgpp compiler belong in other forums (comp.lang.c and comp.os.msdos.djgpp respectively). The Allegro.cc forums can be found at http://www.allegro.cc/. You can usually ask any question related to Allegro here. Both the Allegro and djgpp mailing lists are archived, and can be searched via their respective homepages. It is very likely that you will be able to find a solution to your problem by looking through the answers to past questions, which will save you needing to post a query at all. In accordance with proper netiquette, it is assumed that when you post to any forum on the Internet you have at least consulted the relevant documentation first, if not read it in its entirety. If the problem you are having is worth asking hundreds of people the answer for, then it is certainly worth taking a few minutes to try to solve the problem yourself. Allegro is extensively and painstakingly documented and it is considered a prerequisite to posting that you have not only read the text, but examined the example programs as well. @heading Part 6 - learn from my mistakes What not to do, Part One: "My program crashes. Please tell me why." Yes, people really do sometimes send me questions like this :-) Despite years of practice I am still totally unable to read minds, so this is a very pointless thing to ask. In order to get help with a problem you must describe it in enough detail that other people will be able to understand and reproduce it: this usually means posting some of your source code. What not to do, Part Two: "I've got a problem with my program. I'm attaching a 500k zip file containing ten thousand lines of source code and all the graphics and sound data: can you please debug it and tell me what the trouble is?" After wasting the time and phone bills to download such a huge file, it is unlikely that anyone will even _want_ to help you, let alone invest the amount of time it would take to read and understand such a huge mess of information. You must try to isolate a smaller chunk of code that demonstrates the trouble: the smaller you can make it, the more chance that someone will be able to help you with it. Remember that you are asking other people to do you a favour, so it is your responsibility to make this process as easy for them as you possibly can. @heading Part 7 - wording your plea The most important thing is to include code that can be compiled and tested by the person reading your message. Don't just post your entire program: try to extract a small section that includes the specific lines causing your problem, or reproduces the trouble in a simpler way (you will often find that you can locate the error yourself in the process of making this simpler version, so it is a good exercise in itself). This code should be a small but complete program that can actually be compiled and run, because it is very hard to debug incomplete code fragments. It is best to include the code directly in the text of your email message, because it is easier for people to read this than if they have to extract it from an attachment. Ideally your example should avoid using any external graphics and data files. It is ok to include a small (max 2k) zip containing such information, or failing that a description of what other files it needs (eg. "put a 32x32 .pcx file called 'tile.pcx' into the same directory as the program). If there is no way that you can simplify things this far, you should upload the program and data to a website and then just post that URL in your message. You should say what compiler options you used to build the program. These should include extra warnings. If you use gcc, post the list of compiler switches you used. Describe what you intended this program to do (it may not be instantly obvious to other people), and also what it really does when you run it. There is usually no need to post the actual crash traceback (other people can duplicate this for themselves as long as they are able to compile and run your code), but you should say whether you do get such a traceback, or a lockup, or just incorrect results (and if so, in exactly what way they differ from what you were expecting). It is useful to mark your source with a comment to show what line the crash traceback points to. Any other information that you can include may also be useful. Most importantly a brief machine description, information about any relevant drivers, and your Allegro version (please don't just say "WIP", but give the exact date if you are using anything other than an official numbered release). @heading Part 8 - a model of perfection For reference, here is an example of what I would consider to be an ideal problem report: I'm having some trouble using the hicolor video modes in my program, although they work fine with the Allegro tests. I'm using Allegro 4.0 with MinGW 3.1.0 (gcc version 3.3.1) on a Pentium 1.2GHz, running under Windows 2000 and an ATi Radeon 7000 videocard. This program is supposed to select a 640x480 16 bit resolution, draw a blue rectangle near the top left corner of the screen, and then wait for a keypress before quitting, but I just get a General Protection Fault when I run it. I compile it using "gcc -Wall t.c -o t.exe -lalleg", and don't get any warnings. --- cut here, t.c --- #include <stdio.h> #include <allegro.h> void main() { BITMAP *bmp = screen; install_keyboard(); if (set_gfx_mode(GFX_AUTODETECT, 640, 480, 0, 0) != 0) { printf("Error setting video mode\n"); return; } set_color_depth(16); /* crashes during this rectangle call! */ rectfill(bmp, 32, 32, 64, 64, 0x001F); readkey(); } allegro4.4-4.4.2/docs/src/index._tx000066400000000000000000000016141173507505700167520ustar00rootroot00000000000000@# This file is only meant for the HTML documentation. @# All other file formats should ignore it. @external-css=allegro.css @document_title=Allegro Documentation Index @titlepage ______ ___ ___ /\ _ \ /\_ \ /\_ \ \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ /\____/ \_/__/ A game programming library. @!titlepage @contents @chapter Documentation Index @externalfile license License and Disclaimer @externalfile readme Readme (pointers to build instructions) @externalfile allegro The Allegro manual @externalfile changes Changes since previous versions @externalfile thanks Contributors: The Hall of Fame allegro4.4-4.4.2/docs/src/license._tx000066400000000000000000000026301173507505700172640ustar00rootroot00000000000000@document_title=Giftware license @external-css=allegro.css @heading The giftware license Allegro is gift-ware. It was created by a number of people working in cooperation, and is given to you freely as a gift. You may use, modify, redistribute, and generally hack it about in any way you like, and you do not have to give us anything in return. However, if you like this product you are encouraged to thank us by making a return gift to the Allegro community. This could be by writing an add-on package, providing a useful bug report, making an improvement to the library, or perhaps just releasing the sources of your program so that other people can learn from them. If you redistribute parts of this code or make a game using it, it would be nice if you mentioned Allegro somewhere in the credits, but you are not required to do this. We trust you not to abuse our generosity. Disclaimer: THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. allegro4.4-4.4.2/docs/src/makedoc._tx000066400000000000000000000156151173507505700172540ustar00rootroot00000000000000@external-css=allegro.css @document_title=makedoc

The makedoc tool


@heading Using makedoc Not only the library is built from source code but the actual documentation too. Allegro is bundled with makedoc, a convulsed C program which started small and has grown to support many different output formats. The documentation source and documentation generator can be found both under the `docs/src' directory. Running `make' in Allegro's top directory will generate the documentation along with the library, but there are more specific make targets which you can use to selectively build only the documentation or specific versions of the documentation which by default won't be generated. You can find more about these in the "Makefile targets" chapter. @hnode Output formats Makedoc output will be placed in the `docs/format' directory or directly in the `docs' directory. Usually if an output format requires an external tool which doesn't come bundled with Allegro you will have to generate it manually with the correct makefile target.
  • `.txt'
    Plain text version of the documentation. It is basically a dump of the `._tx' source file stripping the custom tags. This output is generated by default and available on all supported platforms.
  • `.rtf'
    Rich text format version of the documentation. This is a slightly improved version of the text output. Makedoc will generate a few nice things like a table of contents and will use different fonts in the output, which are nicer to read or print than the text version. This output is generated by default and available on all supported platforms.
  • `.html'
    Html version of the documentation. Depending on some tags in the `._tx' source file it can be built as multiple files or a single big page (see below). The documentation is generated in two steps: first the normal output is generated. This output doesn't contain hyperlinks between chapters since the makedoc tool doesn't know in advance in which file will be found a specific symbol. The second pass will go through all the links and make them point to the correct files. Thanks to cascade style sheets you can customize the outlook of the documentation without having to modify the makedoc tool. This output is generated by default and available on all supported platforms.
  • `.3'
    Unix man pages for the section "Library calls (functions within program libraries)". As usual these man pages will contain a synopsis, description and see also sections. Certain parts of the documentation like chapter introductions won't have man pages. This output is generated by default on Unix platforms. Note that you have to install the man pages manually with a specific makefile target.
  • `.texi'
    Intermediate format for GNU tools. This format is not readable alone and requires processing to be transformed into something else. This output can be generated on all platforms because it doesn't require external programs, but all by itself is not very useful.
  • `.info'
    GNU online info format. Generated from the `.texi' output this format can be used with the GNU `info' tool. The produced output looks similar to the plain text version but features hyperlinked navigation. This output is generated by default on platforms supporting the GNU tools like Unix or DJGPP (DOS). You need the `makeinfo' tool to generate the output and the `info' tool to view it. You have to install this manually on your system with a specific makefile target.
  • `.chm'
    Compiled HTML. Similar to the HTML output but instead of having lots of separate files you end up with a single file. You need Microsoft's HTML compiler to build this version of the documentation. Windows users can view `.chm' files by default. Non Windows users can go to http://freshmeat.net/ and search for "chm viewer". Read more in the "Makefile targets" chapter.
  • `.dvi'
    Device independent documentation file. While this format is usable, it is also used as intermediate step to other formats. In fact, this one is build from the texi output. By default not build, as it relies on the external tool texi2dvi.
  • `.ps'
    Postscript version of the documentation, ideal for printing. This is not generated by default because it needs to generate the DVI output and then use the external tool `dvips'.
  • `.pdf'
    Portable document format. Similar in output quality to the postscript output, this has the advantage of having hyperlinks. Generated from the texi output with the external tool `texi2pdf'.
  • `.devhelp'
    Devhelp HTML + XML index format. Similar to the HTML output, this also carries a separate index which can be used by external programs (usually programming editors) to look up context sensitive help. Basically it is like the info output but using the more flexible HTML format as base. This format doesn't require external tools to be built, but it is not built by default. You have to create and install it manually.
  • `.api'
    SciTE api format. This is an index of all Allegro functions of the library for the SciTE editor (http://www.scintilla.org/SciTE.html). This output is generated by default and available on all supported platforms.
@hnode Customizing the output Some of the output formats can be customized even further by modifying some of the generated files or directly the original source file. The documentation source file format is described with more detail in `docs/src/makedoc/format.txt'. Usually the interesting bits to users are:
  • The HTML output generates by default individual HTML files for each chapter. By uncommenting the `multiplefiles' command you can create a single file with the whole manual. Note that external documentation files like the FAQ or hacking guide will still be linked, but not included.
  • The HTML output also uses cascade style sheets to specify the outlook of the generated pages. You can disable CSS with the `ignore_css' command or specify a different CSS file with external-css=. The default CSS file generated by makedoc also has something to tweak.
  • When using the multiple file output, makedoc places a "Back to contents" link at the bottom of each chapter. If you follow a hyperlink you can end up pointing at one of the last descriptions of the page but your browser might not scroll to the correct height because the page ends up before. To avoid this effect, you can uncomment one of the last lines in the CSS related to a bottom margin. Making the bottom margin higher puts more space between the "Back to contents" link and the physical end of the page.
Note that all the above which applies to HTML output also applies to documentation formats which are HTML based, like Devhelp or CHM. allegro4.4-4.4.2/docs/src/makedoc/000077500000000000000000000000001173507505700165305ustar00rootroot00000000000000allegro4.4-4.4.2/docs/src/makedoc/format.txt000066400000000000000000000403561173507505700205710ustar00rootroot00000000000000 ______ ___ ___ /\ _ \ /\_ \ /\_ \ \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ /\____/ \_/__/ Allegro's _tx documentation format. By Grzegorz Adam Hankiewicz. ==================================== ============ Disclaimer ============ ==================================== During years the makedoc program has been used to output Allegro's documentation in different file formats. Nobody ever cared to document the _tx format or makedoc's source code. The result is that this late reference might be wrong or inaccurate, please take it with a grain of salt. And remember that makedoc is not a _real_ program, it's a hack, just don't tell anybody else... ================================ ============ Format ============ ================================ _tx files are simple 8 bit text files written in a specific codepage (usually latin1/iso-8859-1). The makedoc tool is codepage agnostic: if you are using makedoc to generate documents in other codepages, you are going to need to parse makedoc's output to adjust it to your needs. This is usually not a very big problem, since you could use utf8 and later convert it to your own codepage. Taking the original allegro._tx as a reference, you can see that _tx files are really a rich mixture of the supported output formats, and this richness is stripped out appropriately for each output (ie: HTML tags won't appear in plain ascii output, etc). Lines starting with $@ will go unprocessed to the texi (and later info) output. Such lines won't even appear in other outputs. Lines starting with @# are comments and will be ignored by makedoc. A few simple HTML tags like
  • ,
    or
     can be written directly where needed:
       makedoc will strip them correctly in non-HTML output. Lines starting with
       @ alone are special makedoc commands which can mean different things:
    
       @multiplefiles
          This command tells makedoc to generate multiple HTML files for a
          document containing several @heading commands. It's ignored by all
          the other output formats.
    
       @ignore_css
          By default the HTML output will use CSS to color text. Since CSS
          implementation quality varies from a browser to another, you can use
          this to avoid having unreadable documentation. Or just get a better
          browser...
       
       @external-css=filename.css
          Use this switch to tell makedoc to output a default CSS file for
          the HTML documentation. The specified file will be overwritten.
          If @ignore_css is used, this option is ignored. If this option
          is not set, then CSS will be be inlined in the HTML file.
    
       @locale=xxx
          An obsolete command. It was used by several output formats to set
          correctly the language of the document. Nowadays you should be using
          @rtf_language_header= and @charset= when apropiate.
    
       @rtf_language_header=xxx
          This can appear multiple times and is used only in rtf output. Rtf
          documents need a special header for a specific language. This header
          tells the viewer which fonts should be used with the document. By
          default makedoc will generate a language header suitable for latin1
          alike languages. Documents in other languages like Chinese or Korean
          should use this to override the default header. This command replaces
          the obsolete @locale command. Example for a Korean rtf:
    
          @rtf_language_header={\fonttbl{\f0\froman\fcharset129\fprq2 ±¼¸²;}
          @rtf_language_header={\f1\fmodern\fcharset129\fprq1 ;}
          @rtf_language_header={\f2\froman\fcharset129\fprq2 ;}}
    
       @charset=xxx
          This command is used by HTML output. Each generated HTML file needs a
          meta tag with information about the used character set. By default
          makedoc will use iso-8859-1 as character set. You can use this command
          to override that meta tag. Example for Korean HTML files:
    
          @charset=euc-kr
    
       @document_title=xxx
          Required for HTML output. Sets the title of each HTML file. For
          multifile output, to this string makedoc will append the text of the
          @heading command used to generate each individual file.
    
       @h=xxx
          An old and less flexible version of @document_title. While you can
          still use it, it will deactivate immediately CSS generation and the
          generated HTML code won't be valid (at least the header part)
    
       @html_see_also_text=xxx
          Optional command. By default, when HTML cross references for
          identifiers and sections are generated, the text "See also:" precedes
          the links. With this command you can customize it, which is necessary
          for non-english documents.
    
       @html_examples_using_this_text=xxx
          Optional command. By default, when HTML cross references are generated
          for examples, the text "Examples using this:" precedes the links. With
          this command you can customize it, which is necessary for non-english
          documents.
    
       @html_footer=xxx
          Required for multifile HTML output. This is the text that will appear
          at the footer of each individual html file which is not the index.
    
       @f=Back to contents
          Old version of @html_footer, preserved for backwards compatibility.
          @html_footer puts the apropiate link tags around the text you provide.
    
       @f1=


    Back to Contents

    Yet another ugly old version of @html_footer. Same story: don't use it. @rtfh=xxx Similar to @document_title but for rtf output. Soon to be deprecated. @manh=xxx Header of each manpage. @mans=xxx Added to each manpage, something like #include . @titlepage @!titlepage Lines enclosed between those two commands are the title page of the document. @!indent @indent Lines enclosed between those two commands won't be indented. @!html @html Lines enclosed between those two commands won't appear in HTML output. @!text @text Lines enclosed between those two commands won't appear in text output. @!texinfo @texinfo Lines enclosed between those two commands won't appear in texinfo output. @heading This command introduces a new chapter or section in the document. In HTML multifile will create a separate file. The following line has to be the title of the new section. @headingnocontent Similar to @heading, this won't generate a table of contents of the chapter. @hnode xxx Similar to @heading but doesn't create another file. xxx represents the title of the new subsection. @chapter Like @heading, but one level above. It allows to partition the documentation into multiple parts, each containing multiple @heading sections. Currently, only the devhelp output format makes use of this. @endchapter Ends the last chapter started by @chapter. Otherwise, a chapter ends at the next @chapter command or at the end of the file. @tallbullets Uses tall bullets in the output formats that support them. @html_spaced_list_bullet Prepend a '

    ' to HTML output every time a

  • tag is found. This is useful to space visually lists, used mainly for the changes log. @contents Generates an index for the info and html outputs. @shortcontents Similiar to @contents, but is always present in html files, even with formats like devhelp or chm which normally put the results of @contents into their navigation pane instead of the actual html. @htmlindex xxx Used in the main index HTML file of the document, creates a link to an external file, xxx being the name without extension. Please try to avoid this and use the next command instead. @externalfile filename title A replacement of htmlindex. The main difference is that htmlindex would name the link exactly as it's filename. This is usually not enough descriptive and tends to get in the way of translators. filename can't contain spaces, which are used to mark the beginning of title, or extension. @mangle_emails=xxx yyy From the line this command is found on, tags will be mangled. The mangling will depend on xxx and yyy, which have to be separated exactly by one space. '@' characters in email addresses will be replaced by the xxx part, dots will be replaced by the yyy part. Possible example for a spanish document: @mangle_emails=EN PUNTO This would transform 'yo@terra.es' into 'yo EN terra PUNTO es'. @retval Used to mark the section of a function description involved with the return value of this function. It has to be obviously at the end of the function description. @html_return_value_text=xxx Optional command. By default, when HTML output is generated, the text "Return value:" precedes sections marked with the @retval command. With this command you can customize it, which is necessary for non-english documents. @html_text_substitution=xxx|yyy With this command you can improve the hyperlinked nature of the HTML documentation. During the second post processing part of the HTML generation, all xxx texts will be replaced with yyy. This can be used to create links to external documents which are not links in the text version, or provide more complex HTML only features. @html_text_substitution=readme.txt|readme.txt @shortdesc xxxx A single line description of the function/define/macro whatever you are documenting. This description will appear for example in the name of man pages, which can be queried with the apropos command. @man_shortdesc_force1=xxx @man_shortdesc_force2=xxx Man pages use the short description in the title. However, one of the ways of locating a man page is usually running `apropos string', and maybe it's difficult to formulate short descriptions which always contain a specific keyword. That's why these commands exist. For every man page title, the first string is searched ignoring case. If this string is found, nothing happens. Otherwise, the second string will be appended to the short description (if any). This allows to populate all manpages with a nice title without having to specify a short description for each of them. Example: @man_shortdesc_force1=allegro @man_shortdesc_force2=Allegro game programming library. =================================== ============ Functions ============ =================================== The _tx format is about documenting functions. Functions, variables and macros are specified with several @ characters at the appropriate points. Given the function "int get_uformat(void);", you would write in a _tx source file: @@int @get_uformat(void); Returns the currently selected text encoding format. If you want to generate a cross reference for that function, you can use the @xref command followed by a sequence of tokens separated by commas. Several @xref commands can appear together for the same function: @@void @set_uformat(int type); @xref get_uformat, register_uformat, set_ucodepage, set_uformat @xref ustrsize, ugetc, ugetx, usetc, uwidth, ucwidth, uisok @xref ugetat, usetat, uinsert, uremove, allegro_init Sets the current text encoding format... If the name function is too long to fit horizontally (use a width of 80 for your document if you want it to be readable in output formats like plain ascii or info), you can split the function over several lines: @\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 Installs a set of custom handler... Remember to end the last line with @@ instead of @\. Use allegro._tx as a reference if you have any problems documenting your functions. If you want to generate a cross reference to examples using the function, you can use the @eref command, which works exactly like @xref, but will be colored differently in the HTML output. Finally, for functions which have a return value, you should use the @retval command to mark the first paragraph which talks about the return value. Output formats like HTML or man pages will highlight the beginning of this section (which should be the last of the function description) so the user can quickly see it. Possible example: @@int @set_window_close_button(int enable); @xref set_window_close_hook, set_window_title @eref exwindow, exdialog On platforms that are capable of it, this routine disables or enables the window close button for your Allegro program. @retval If the close button is successfully disabled, this function returns zero. On platforms where... =================================== ============ Meta tags ============ =================================== _tx files previously used the
     and 
    tags in source files to generate preformatted text in HTML, which was used to represent code which had to appear verbatim. Now with the use of optional CSS for HTML code, the HTML tags needed to generate the appropriate effect are longer than a simple
    . Makedoc provides some "macros" or "meta tags" which
       you can use to avoid typing long HTML commands:
    
       
       ...
       
       
       
       ...
       
    
        and  will be converted to 
     and 
     respectively.  will
       expand to 
    . The good thing is that if you disable CSS makedoc will expand them to only
     and 
    . The colors used by the text and code blocks depend on the taste of the last person who hacked makedoc, so you can't rely on them to be consistent through versions. Luckily, since 4.1.4, html output uses CSS in an external file, meaning that it's easier for you to customize those colors after the output has been generated. Note that makedoc will overwrite the .css file with each generation. Create somewhere a directory with your .css file and use a script after each generation to copy only the .html files to this new directory. Of course, compare your .css file to the one generated by makedoc after Allegro releases, the css properties/names could have changed and you may want to update your .css file to match the new version. ============================================ ============ Special characters ============ ============================================ You can't use directly '<' or '>' in your text. While makedoc is clever and won't try to convert your text, HTML browsers could misunderstand these characters. Therefore you have to use < for '<' and > for '>', which will be replaced correctly for every possible output. The '&' character also has a special meaning for HTML. However, since a _tx file doesn't use this, it will always be replaced by '&' in the HTML output and you won't have to care about this. ==================================== ============ Conclusion ============ ==================================== Hopefully this throws some light on the format. Consider this document incomplete and subject to change. After all, makedoc can be considered as a moving target, and if tomorrow the Allegro documentation needs to use whatever feature, the format will change and you will have to rewrite your _tx files. Sorry! At least makedoc will try to warn you about this. allegro4.4-4.4.2/docs/src/makedoc/makechm.c000066400000000000000000000224311173507505700203030ustar00rootroot00000000000000/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Makedoc's chm output routines. * * By Elias Pschernig, based on makehtml. * * Grzegorz Adam Hankiewicz made sorted TOCs. * * See readme.txt for copyright information. * * See allegro/docs/src/makedoc/format.txt for a brief description of * the source of _tx files. */ #include #include #include #include #include #include #include "makechm.h" #include "makehtml.h" #include "makemisc.h" #include "makedoc.h" #define ALT_TEXT(toc) ((toc->alt) ? toc->alt : toc->text) #define PREV_ROOT 1 #define PREV_SUB 2 /* Buffered tocs. Only the 'local' pointer should be freed */ typedef struct BTOC { const char *name; char *local; } BTOC; extern const char *html_extension; static int _write_toc(const char *filename, int is_index); static int _write_hhp(const char *filename); static void _write_object(FILE *file, const char *name, const char *local); static void _output_btoc(FILE *file, BTOC *btoc, int *btoc_prev, int *num_btoc); static int _qsort_btoc_helper(const void *e1, const void *e2); /* _write_toc: * Outputs a .hhc or .hhk file which are needed by the HTML Help compiler * (along with a .hhp and the standard HTML docs) to generate the CHM docs. * is_index is a boolean, and tells if the output file should be a chm * index file. The main difference is that the internal structure is * slightly different, and it doesn't need toc sorting. */ static int _write_toc(const char *filename, int is_index) { BTOC btoc[TOC_SIZE]; FILE *file = fopen(filename, "wt"); TOC *toc; int btoc_prev[TOC_SIZE]; int section_number = -1, prev = 0, num_btoc = 0; int in_chapter = 0; if (!file) return 1; fprintf(file, "\n"); fprintf(file, "\n"); fprintf(file, "\n"); if (is_index) fprintf(file, "Index\n"); else fprintf(file, "Contents\n"); fprintf(file, "\n"); fprintf(file, "\n"); fprintf(file, "\n"); fprintf(file, "
      \n"); toc = tochead; if (toc) toc = toc->next; for (; toc; toc = toc->next) { char name[256]; if (toc->htmlable) { if (toc->root) { if (is_index) { fprintf(file, "\n"); } else { _output_btoc(file, btoc, btoc_prev, &num_btoc); if (prev == PREV_SUB) fprintf(file, "
  • \n"); if (prev == PREV_ROOT) fprintf(file, "
  • \n"); } if (toc->otherfile) { sprintf(name, "%s.%s", toc->text, html_extension); } else { section_number++; get_section_filename(name, filename, section_number); } prev = PREV_ROOT; _write_object(file, ALT_TEXT(toc), mystrlwr(name)); } else { if (is_index) { fprintf(file, "\n"); } else { btoc_prev[num_btoc] = prev; } get_section_filename(name, filename, section_number); strcat(name, "#"); strcat(name, toc->text); prev = PREV_SUB; if(!is_index) { /* Buffer toc for posterior output */ btoc[num_btoc].local = m_strdup(mystrlwr(name)); btoc[num_btoc++].name = ALT_TEXT(toc); } else _write_object(file, ALT_TEXT(toc), name); } } else if ((toc->root == 2 || toc->root == 3) && !is_index) { _output_btoc(file, btoc, btoc_prev, &num_btoc); if (prev == PREV_SUB) fprintf(file, "\n"); if (prev == PREV_ROOT) fprintf(file, "\n"); if (in_chapter) { fprintf(file, "\n"); in_chapter = 0; } if (toc->root == 2) { fprintf(file, "
  • \n"); fprintf(file, "\n", ALT_TEXT(toc)); fprintf(file, "\n
  • \n"); fprintf(file, "
      \n"); in_chapter = 1; } prev = 0; } } if (in_chapter) { fprintf(file, "
    \n"); } _output_btoc(file, btoc, btoc_prev, &num_btoc); if (prev == PREV_SUB) fprintf(file, "\n"); if (prev == PREV_ROOT) fprintf(file, "\n"); fprintf(file, "\n"); fprintf(file, "\n"); fprintf(file, "\n"); fclose(file); return 0; } /* _output_btoc: * Sorts all the buffered tocs read so far and frees their memory after * writting them to the file. Can be safely called at any moment, as long * as the pointer to num_btoc is meaningfull and contains the number of * buffered tocs in the btoc table. Note that btoc_prev is NOT sorted. */ static void _output_btoc(FILE *file, BTOC *btoc, int *btoc_prev, int *num_btoc) { int num; assert(btoc); assert(num_btoc); assert(btoc_prev); qsort(btoc, *num_btoc, sizeof(BTOC), _qsort_btoc_helper); for(num = 0; num < *num_btoc; num++) { if (btoc_prev[num] == PREV_SUB) fprintf(file, "\n"); if (btoc_prev[num] == PREV_ROOT) fprintf(file, "
      \n"); _write_object(file, btoc[num].name, btoc[num].local); free(btoc[num].local); } *num_btoc = 0; } /* _qsort_btoc_helper: * qsort helper. BTOC elements are sorted through the name value. */ static int _qsort_btoc_helper(const void *e1, const void *e2) { BTOC *s1 = (BTOC *)e1; BTOC *s2 = (BTOC *)e2; return mystricmp(s1->name, s2->name); } /* _write_object: * Writes to the file a record for a new object. Note that the object * record is not closed, so other's can be nested. This forces the caller * to close the object before writting another. */ static void _write_object(FILE *file, const char *name, const char *local) { assert(file); assert(name); assert(local); fprintf(file, "
    • \n"); fprintf(file, "\n", name); fprintf(file, "\n", local); fprintf(file, "\n"); } /* _write_hhp: */ static int _write_hhp(const char *filename) { FILE *file = fopen(filename, "wt"); TOC *toc; int section_number = -1; char *stripped_filename, *p; if (!file) return 1; stripped_filename = m_strdup(get_filename(filename)); if ((p = get_extension(stripped_filename))) *(p-1) = 0; fprintf(file, "[OPTIONS]\n"); fprintf(file, "Compiled file=%s.chm\n", stripped_filename); fprintf(file, "Contents file=%s.hhc\n", stripped_filename); fprintf(file, "Default topic=%s.%s\n", stripped_filename, html_extension); fprintf(file, "Full-text search=Yes\n"); fprintf(file, "Index file=%s.hhk\n", stripped_filename); fprintf(file, "Language=0x409 English (USA)\n"); if((html_flags & HTML_DOCUMENT_TITLE_FLAG) && !(html_flags & HTML_OLD_H_TAG_FLAG)) fprintf(file, "Title=%s\n", html_document_title); else { /* Write the filename without extension and capitalized */ fputc(toupper(*stripped_filename), file); fprintf(file, "%s", stripped_filename+1); } fprintf(file, "\n"); fprintf(file, "[FILES]\n"); free(stripped_filename); toc = tochead; if (toc) toc = toc->next; for (; toc; toc = toc->next) { if (toc->htmlable && toc->root) { char name[256]; if (toc->otherfile) { sprintf(name, "%s.%s", toc->text, html_extension); } else { section_number++; get_section_filename(name, filename, section_number); } mystrlwr(name); fprintf(file, "%s\n", name); } } return 0; } /* write_chm: */ int write_chm(char *filename) { char *temp; if (!strcmp(get_extension(filename), "htm")) html_extension = "html"; if (!(flags & MULTIFILE_FLAG)) { printf("The chm version of the documentation requires that you generate \n"); printf("multifile output in the HTML version. Please delete the generated\n"); printf("HTML files and put @multiplefiles in allegro._tx.\n\n"); return 1; } temp = m_replace_extension(filename, "hhp"); printf("writing '%s'\n", temp); if (_write_hhp(temp)) return 1; free(temp); temp = m_replace_extension(filename, "hhc"); printf("writing '%s'\n", temp); _write_toc(temp, 0); free(temp); temp = m_replace_extension(filename, "hhk"); printf("writing '%s'\n", temp); _write_toc(temp, 1); free(temp); return 0; } /* get_section_filename: * Extracts the filename from path and transforms it to the format * 5+3.ext, where 5 characters are taken from path, next three represent * the section number, and ext is the html extension. buf shuold have * enough space to hold 16 characters. Returns a pointer to buf. */ char *get_section_filename(char *buf, const char *path, int section_number) { int len; assert(buf); assert(path); assert(section_number >= 0); len = strlen(strncpy(buf, get_filename(path), 5)); if (len > 5) len = 5; sprintf(buf+len, "%03d.%s", section_number, html_extension); return buf; } allegro4.4-4.4.2/docs/src/makedoc/makechm.h000066400000000000000000000002311173507505700203020ustar00rootroot00000000000000#ifndef MAKECHM_H #define MAKECHM_H int write_chm(char *filename); char *get_section_filename(char *buf, const char *path, int section_number); #endif allegro4.4-4.4.2/docs/src/makedoc/makedevh.c000066400000000000000000000160431173507505700204640ustar00rootroot00000000000000/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Makedoc's devhelp output routines. * * By Elias Pschernig, based on makechm. * * See readme.txt for copyright information. * * See allegro/docs/src/makedoc/format.txt for a brief description of * the source of _tx files. */ #include #include #include #include #include #include #include "makedevh.h" #include "makehtml.h" #include "makemisc.h" #include "makechm.h" #include "makedoc.h" #define ALT_TEXT(toc) ((toc->alt) ? toc->alt : toc->text) enum PREV { PREV_NO, PREV_ROOT, PREV_SUB, PREV_CHAP }; enum TYPE { TYPE_ROOT1, TYPE_ROOT2, TYPE_SUB1, TYPE_SUB2, TYPE_FUNC }; /* Buffered tocs. Only the 'local' pointer should be freed */ typedef struct BTOC { enum TYPE type; const char *name; char *local; } BTOC; extern const char *html_extension; static void _write_object(FILE *file, const char *name, const char *local, int open); static void _output_btoc(FILE *file, BTOC *btoc, int *num_btoc); static int _qsort_btoc_helper(const void *e1, const void *e2); /* _output_btoc: * Sorts all the buffered tocs read so far and frees their memory after * writting them to the file. Can be safely called at any moment, as long * as the pointer to num_btoc is meaningfull and contains the number of * buffered tocs in the btoc table. */ static void _output_btoc(FILE *file, BTOC *btoc, int *num_btoc) { int num; assert(btoc); assert(num_btoc); qsort(btoc, *num_btoc, sizeof(BTOC), _qsort_btoc_helper); for(num = 0; num < *num_btoc; num++) { _write_object(file, btoc[num].name, btoc[num].local, btoc->type); free(btoc[num].local); } *num_btoc = 0; } /* _qsort_btoc_helper: * qsort helper. BTOC elements are sorted through the name value. */ static int _qsort_btoc_helper(const void *e1, const void *e2) { BTOC *s1 = (BTOC *)e1; BTOC *s2 = (BTOC *)e2; return mystricmp(s1->name, s2->name); } /* _write_object: * Writes to the file a record for a new object. Note that the object * record is not closed, so other's can be nested. This forces the caller * to close the object before writting another. */ static void _write_object(FILE *file, const char *name, const char *local, int type) { assert(file); assert(name); assert(local); fprintf(file, "%s name=\"%s\" link=\"%s\"%s>\n", type == TYPE_ROOT1 ? " \n%s\n\n", name); fprintf(file, "

      %s

      ", name); fprintf(file, "

      Use the table of contents to navigate through this chapter."); fprintf(file, "\n\n"); fclose(file); } return path; } /* write_devhelp: */ int write_devhelp(const char *filename) { BTOC btoc[TOC_SIZE]; FILE *file; TOC *toc; char *dest_name; int section_number = -1, num_btoc = 0; enum PREV prev = PREV_NO; int in_chapter = 0; int chapter_num = 1; if (!strcmp(get_extension(filename), "htm")) html_extension = "html"; dest_name = m_replace_extension(filename, "devhelp"); printf("writing '%s'\n", dest_name); file = fopen(dest_name, "wt"); if (!file) return 1; free(dest_name); fprintf(file, "\n"); fprintf(file, "\n"); fprintf(file, "\n"); fprintf(file, "\n"); fprintf(file, "\n"); toc = tochead; if (toc) toc = toc->next; for (; toc; toc = toc->next) { char name[256]; if (toc->htmlable || toc->root > 1) { if (toc->root ) { /* Write previous section. */ _output_btoc(file, btoc, &num_btoc); if (prev == PREV_ROOT || prev == PREV_SUB) fprintf(file, "%s\n", in_chapter ? " " : " "); if (toc->root == 2 || toc->root == 3) { if (in_chapter) fprintf(file, " \n"); if (toc->root == 2) { char *path; path = devhelp_blank_page(ALT_TEXT(toc), filename, chapter_num++); strcpy(name, get_filename(path)); free(path); } in_chapter = 0; } else if (toc->otherfile) { sprintf(name, "%.240s.%.10s", toc->text, html_extension); } else { section_number++; get_section_filename(name, filename, section_number); } if (toc->root == 3) { prev = PREV_NO; } else { prev = toc->root == 1 ? PREV_ROOT : PREV_CHAP; _write_object(file, ALT_TEXT(toc), name, in_chapter ? TYPE_ROOT2 : TYPE_ROOT1); if (toc->root == 2) in_chapter = 1; } } else { get_section_filename(name, filename, section_number); strcat(name, "#"); strcat(name, toc->text); prev = PREV_SUB; /* Buffer toc for posterior output */ btoc[num_btoc].type = in_chapter ? TYPE_SUB2 : TYPE_SUB1; btoc[num_btoc].local = m_strdup(name); btoc[num_btoc++].name = ALT_TEXT(toc); } } } _output_btoc(file, btoc, &num_btoc); if (prev == PREV_SUB || prev == PREV_ROOT) fprintf(file, "%s\n", in_chapter ? " " : " "); if (in_chapter) fprintf(file, " \n"); fprintf(file, "\n"); fprintf(file, "\n"); fprintf(file, "\n"); toc = tochead; if (toc) toc = toc->next; section_number = -1; for (; toc; toc = toc->next) { char name[256]; if (!toc->htmlable) continue; if (toc->root) { if (!toc->otherfile) { section_number++; } } else { get_section_filename(name, filename, section_number); strcat(name, "#"); strcat(name, toc->text); btoc[num_btoc].type = TYPE_FUNC; btoc[num_btoc].local = m_strdup(name); btoc[num_btoc++].name = ALT_TEXT(toc); } } _output_btoc(file, btoc, &num_btoc); fprintf(file, "\n"); fprintf(file, "\n"); fprintf(file, "\n"); fclose(file); return 0; } allegro4.4-4.4.2/docs/src/makedoc/makedevh.h000066400000000000000000000001361173507505700204650ustar00rootroot00000000000000#ifndef MAKEDEVHELP_H #define MAKEDEVHELP_H int write_devhelp(const char *filename); #endif allegro4.4-4.4.2/docs/src/makedoc/makedoc.c000066400000000000000000000577111173507505700203120ustar00rootroot00000000000000/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * This is a little hack I wrote to simplify producing the documentation * in various formats (ASCII, HTML, TexInfo, and RTF). It converts from * a weird layout that is basically a kind of stripped down HTML with a * few extra markers (the _tx files), and automates a few things like * constructing indexes and splitting HTML files into multiple parts. * It's not pretty, elegant, or well written, and is liable to get upset * if it doesn't like the input data. If you change the _tx files, run * 'make docs' to rebuild everything. * * By Shawn Hargreaves. * * Grzegorz Adam Hankiewicz added email mangling, custom metatags for * easier CSS HTML output, and cleaned up some code. * * See readme.txt for copyright information. * * See allegro/docs/src/makedoc/format.txt for a brief description of * the source of _tx files. */ #include #include #include #include #include #include #include #include "makedoc.h" #include "makehtml.h" #include "makemisc.h" #include "maketxt.h" #include "makeman.h" #include "makertf.h" #include "maketexi.h" #include "makechm.h" #include "makedevh.h" #include "makesci.h" /* external globals */ LINE *head = NULL; TOC *tochead = NULL; int flags = TEXT_FLAG | HTML_FLAG | TEXINFO_FLAG | RTF_FLAG | MAN_FLAG; /* other globals */ static int _last_toc_line = INT_MIN; static int _warn_on_long_lines = 0; static char *_email_mangle_at, *_email_mangle_dot; static int _mangle_emails = 0; /* internal functions */ static void _transform_custom_tags(char *buf); static int _read_file(char *filename); static void _free_data(void); static void _add_line(char *buf, int flags); static void _add_toc_line(const char *buf, const char *alt, int root, int num, int texinfoable, int htmlable, int otherfile); static void _add_external_file(const char *buf, int line_number); static char *_my_fgets(char *p, int max, FILE *f); static void _add_toc(char *buf, int root, int num, int texinfoable, int htmlable); static void _activate_email_mangling(const char *txt); static void _mangle_email_links(char *buf); static char *_mangle_email(const char *email, int len); /* main: * Binary entry point. */ int main(int argc, char *argv[]) { char filename[256] = ""; char txtname[256] = ""; char htmlname[256] = ""; char texinfoname[256] = ""; char rtfname[256] = ""; char manname[256] = ""; char chmname[256] = ""; char devhelpname[256] = ""; char scitename[256] = ""; char *texinfo_extension = "txi"; int err = 0; int partial = 0; int i; for (i=1; i"))) { if (html_flags & HTML_IGNORE_CSS) { memmove(p+5, p+11, 1 + strlen(p+11)); strncpy(p, "

      ", 5);
            }
            else {
      	 memmove(p+30, p+11, 1 + strlen(p+11));
      	 strncpy(p, "
      ", 30);
            }
         }
      
         while ((p = strstr(buf, ""))) {
            if (html_flags & HTML_IGNORE_CSS) {
      	 memmove(p+5, p+11, 1 + strlen(p+11));
      	 strncpy(p, "
      ", 5);
            }
            else {
      	 memmove(p+30, p+11, 1 + strlen(p+11));
      	 strncpy(p, "
      ", 30);
            }
         }
      
         while ((p = strstr(buf, ""))) {
            if (html_flags & HTML_IGNORE_CSS) {
      	 memmove(p+6, p+10, 1 + strlen(p+10));
      	 strncpy(p, "
      ", 6); } else { memmove(p+19, p+10, 1 + strlen(p+10)); strncpy(p, "
      ", 19); } } } /* _read_file: */ static int _read_file(char *filename) { char buf[1024]; FILE *f; int line = 0; /*printf("reading %s\n", filename);*/ f = fopen(filename, "r"); if (!f) return 1; while (_my_fgets(buf, 1023, f)) { char *end = strpbrk(buf, "\r\n"); line++; /* strip EOL */ if (end) *end = 0; _transform_custom_tags(buf); if (_mangle_emails) _mangle_email_links(buf); if (buf[0] == '@') { /* a marker line */ if (mystricmp(buf+1, "text") == 0) flags |= TEXT_FLAG; else if (mystricmp(buf+1, "!text") == 0) flags &= ~TEXT_FLAG; else if (mystricmp(buf+1, "html") == 0) flags |= HTML_FLAG; else if (mystricmp(buf+1, "!html") == 0) flags &= ~HTML_FLAG; else if (mystricmp(buf+1, "texinfo") == 0) flags |= TEXINFO_FLAG; else if (mystricmp(buf+1, "!texinfo") == 0) flags &= ~TEXINFO_FLAG; else if (mystricmp(buf+1, "rtf") == 0) flags |= RTF_FLAG; else if (mystricmp(buf+1, "!rtf") == 0) flags &= ~RTF_FLAG; else if (mystricmp(buf+1, "man") == 0) flags |= MAN_FLAG; else if (mystricmp(buf+1, "!man") == 0) flags &= ~MAN_FLAG; else if (mystricmp(buf+1, "indent") == 0) flags &= ~NO_INDENT_FLAG; else if (mystricmp(buf+1, "!indent") == 0) flags |= NO_INDENT_FLAG; else if (mystricmp(buf+1, "multiplefiles") == 0) flags |= MULTIFILE_FLAG; else if (mystricmp(buf+1, "headingnocontent") == 0) flags |= (HEADING_FLAG | NOCONTENT_FLAG); else if (mystricmp(buf+1, "heading") == 0) flags |= HEADING_FLAG; else if (mystricmp(buf+1, "chapter") == 0) flags |= CHAPTER_FLAG; else if (mystricmp(buf+1, "endchapter") == 0) { _add_line(NULL, CHAPTER_END_FLAG); _add_toc_line(buf, NULL, 3, line, 0, 0, 0); } else if (mystricmp(buf+1, "retval") == 0) { _add_line("", flags | RETURN_VALUE_FLAG); flags &= ~(HEADING_FLAG | NOCONTENT_FLAG | NONODE_FLAG); } else if (strincmp(buf+1, "shortdesc ") == 0) _add_line(buf+11, SHORT_DESC_FLAG); else if (strincmp(buf+1, "titlepage") == 0) _add_line("", START_TITLE_FLAG); else if (strincmp(buf+1, "!titlepage") == 0) _add_line("", END_TITLE_FLAG); else if (mystricmp(buf+1, "contents") == 0) _add_line("", TOC_FLAG); else if (mystricmp(buf+1, "shortcontents") == 0) _add_line("", TOC_FLAG | SHORT_TOC_FLAG); else if (mystricmp(buf+1, "index") == 0) _add_line("", INDEX_FLAG); else if (strincmp(buf+1, "node ") == 0) { _add_toc_line(buf+6, NULL, 0, line, 1, 0, 0); _add_line(buf+6, NODE_FLAG | HTML_FLAG); } else if (strincmp(buf+1, "hnode ") == 0) { _add_toc_line(buf+7, NULL, 0, line, 1, 0, 0); _add_line(buf+7, NODE_FLAG | HTML_FLAG); } else if (strincmp(buf+1, "nonode") == 0) flags |= NONODE_FLAG; else if (strincmp(buf+1, "xref ") == 0) { _add_line(buf+6, XREF_FLAG); if (_last_toc_line == line-1) _last_toc_line = line; } else if (strincmp(buf+1, "eref ") == 0) { _add_line(buf+6, XREF_FLAG | EREF_FLAG); if (_last_toc_line == line-1) _last_toc_line = line; } else if (strincmp(buf+1, "header ") == 0) _add_line(buf+8, HEADER_FLAG); else if (strincmp(buf+1, "startoutput ") == 0) _add_line(buf+13, STARTOUTPUT_FLAG); else if (strincmp(buf+1, "endoutput ") == 0) _add_line(buf+11, ENDOUTPUT_FLAG); else if (strincmp(buf+1, "tallbullet") == 0) _add_line("", TALLBULLET_FLAG); else if (strincmp(buf+1, "rtf_language_header=") == 0) { rtf_language_header = m_strcat(rtf_language_header, buf+21); rtf_language_header = m_strcat(rtf_language_header, "\n"); } else if (strincmp(buf+1, "mangle_emails=") == 0) { _activate_email_mangling(buf+15); } /* html specific tags */ else if (strincmp(buf+1, "charset=") == 0) strcpy(charset, buf+9); else if ((mytolower(buf[1]=='h')) && (buf[2]=='=')) { html_document_title = m_strdup(buf+3); html_flags |= HTML_OLD_H_TAG_FLAG | HTML_DOCUMENT_TITLE_FLAG | HTML_IGNORE_CSS; } else if (strincmp(buf+1, "document_title=") == 0) { html_document_title = m_strdup(buf+16); html_flags |= HTML_DOCUMENT_TITLE_FLAG; } else if (strincmp(buf+1, "html_examples_using_this_text=") == 0) { if (html_examples_using_this_text) free(html_examples_using_this_text); html_examples_using_this_text = m_strdup(buf+20); } else if (strincmp(buf+1, "html_see_also_text=") == 0) { if (html_see_also_text) free(html_see_also_text); html_see_also_text = m_strdup(buf+20); } else if (strincmp(buf+1, "html_return_value_text=") == 0) { if (html_return_value_text) free(html_return_value_text); html_return_value_text = m_strdup(buf+24); } else if ((mytolower(buf[1]=='f')) && (buf[2]=='=')) { html_footer = m_strdup(buf+3); html_flags |= HTML_OLD_F_TAG_FLAG | HTML_FOOTER_FLAG; } else if ((mytolower(buf[1]=='f')) && (buf[2]=='1') && (buf[3]=='=')) { html_footer = m_strdup(buf+4); html_footer = m_strcat(html_footer, "%s"); html_flags |= HTML_OLD_F_TAG_FLAG | HTML_FOOTER_FLAG; } else if ((mytolower(buf[1]=='f')) && (buf[2]=='2') && (buf[3]=='=')) { html_footer = m_strcat(html_footer, buf+4); html_flags |= HTML_OLD_F_TAG_FLAG | HTML_FOOTER_FLAG; } else if (strincmp(buf+1, "html_footer=") == 0) { html_footer = m_strdup(buf+13); html_flags |= HTML_FOOTER_FLAG; } else if (strincmp(buf+1, "html_spaced_list_bullet") == 0) html_flags |= HTML_SPACED_LI; else if (strincmp(buf+1, "ignore_css") == 0) html_flags |= HTML_IGNORE_CSS; else if (strincmp(buf+1, "htmlcode") == 0) _add_line(buf+10, (flags | HTML_FLAG | HTML_CMD_FLAG | NO_EOL_FLAG ) & (~TEXT_FLAG)); else if (buf[1] == '<') _add_line(buf+1, (flags | HTML_FLAG | HTML_CMD_FLAG | NO_EOL_FLAG ) & (~TEXT_FLAG)); else if (strincmp(buf+1, "htmlindex ") == 0) _add_toc_line(buf+11, NULL, 1, line, 0, 1, 1); else if (strincmp(buf+1, "externalfile ") == 0) _add_external_file(buf+14, line); else if (strincmp(buf+1, "rtfh=") == 0) strcpy(rtfheader, buf+6); else if (strincmp(buf+1, "manh=") == 0) strcpy(manheader, buf+6); else if (strincmp(buf+1, "mans=") == 0) strcpy(mansynopsis, buf+6); else if (strincmp(buf+1, "man_shortdesc_force1=") == 0) { if (man_shortdesc_force1) free(man_shortdesc_force1); man_shortdesc_force1 = m_strdup(buf+22); } else if (strincmp(buf+1, "man_shortdesc_force2=") == 0) { if (man_shortdesc_force2) free(man_shortdesc_force2); man_shortdesc_force2 = m_strdup(buf+22); } else if (strincmp(buf+1, "locale=") == 0) { printf("'%s' tag obsolete, will be ignored.\n" "Please use @charset='' or @rtf_language_header='' instead.\n" "See makedoc.c for more information about this.\n", buf); } else if (strincmp(buf+1, "multiwordheaders") == 0) multiwordheaders = 1; else if (strincmp(buf+1, "external-css=") == 0) html_css_filename = m_strdup(buf+14); else if (buf[1] == '$') _add_line(buf+2, TEXINFO_FLAG | TEXINFO_CMD_FLAG); else if (buf[1] == '@') { char *found_struct_definition = strstr(buf+2, "struct @"); if(!found_struct_definition) found_struct_definition = strstr(buf+2, "typedef "); _add_toc(buf+2, 0, line, !(flags & NONODE_FLAG), 1); if (found_struct_definition) _add_line(buf+2, flags | DEFINITION_FLAG | STRUCT_FLAG); else _add_line(buf+2, flags | DEFINITION_FLAG); flags &= ~NONODE_FLAG; } else if (buf[1] == '\\') { _add_toc(buf+2, 0, line, !(flags & NONODE_FLAG), 1); _add_line(buf+2, flags | DEFINITION_FLAG | CONTINUE_FLAG); flags &= ~NONODE_FLAG; } else if (strincmp(buf+1, "html_text_substitution=") == 0 && strchr(buf+25, '|')) { int i = 0; while (html_text_substitution[i]) i++; assert(i < 256); html_text_substitution[i] = m_strdup(buf+24); } else if (buf[1] == '#') { /* comment */ } else printf("Ignoring unknown token '%s'\n", buf); } else { /* some actual text */ if (flags & CHAPTER_FLAG) _add_toc(buf, 2, line, !(flags & NONODE_FLAG), 0); if (flags & HEADING_FLAG) _add_toc(buf, 1, line, !(flags & NONODE_FLAG), (flags & HTML_FLAG)); _add_line(buf, flags & CHAPTER_FLAG ? (flags & ~(HTML_FLAG | TEXT_FLAG)) : flags); if (_warn_on_long_lines) { int len = strlen (buf); if (len > 77) printf("Warning: line %d exceded in %d caracters '...%s'\n", line, len - 77, buf + 77); } flags &= ~(CHAPTER_FLAG | HEADING_FLAG | NOCONTENT_FLAG | NONODE_FLAG); } } fclose(f); return 0; } /* _free_data: */ static void _free_data(void) { LINE *line = head; LINE *prev; TOC *tocline = tochead; TOC *tocprev; while (line) { prev = line; line = line->next; free(prev->text); free(prev); } while (tocline) { tocprev = tocline; tocline = tocline->next; free(tocprev->text); if (tocprev->alt) free(tocprev->alt); free(tocprev); } if (_email_mangle_at) free(_email_mangle_at); if (_email_mangle_dot) free(_email_mangle_dot); if (man_shortdesc_force1) free(man_shortdesc_force1); if (man_shortdesc_force2) free(man_shortdesc_force2); } /* _add_line: */ static void _add_line(char *buf, int flags) { static LINE *tail = NULL; LINE *line; line = m_xmalloc(sizeof(LINE)); line->text = buf ? m_strdup(buf) : NULL; line->next = NULL; line->flags = flags; if (tail) tail->next = line; else head = line; tail = line; } /* _add_toc_line: * Adds a line to the table of contents. buf is the filename to be linked, * alt can be NULL, and in such case buf will be used to represent the * link: if alt is not NULL, it will be the link's name. root indicates how * the line should be added to the TOC index - 0 is a normal entry, 1 adds * it to the root index, 2 as a chapter start, 3 as chapter end. num is the * line number. texinfoable, htmlable and otherfile are boolean values * which say if this line should appear in the toc of those file formats. */ static void _add_toc_line(const char *buf, const char *alt, int root, int num, int texinfoable, int htmlable, int otherfile) { static TOC *toctail = NULL; TOC *toc; toc = m_xmalloc(sizeof(TOC)); toc->text = m_strdup(buf); if (alt) toc->alt = m_strdup(alt); else toc->alt = NULL; toc->next = NULL; toc->root = root; toc->texinfoable = ((texinfoable) && (num > _last_toc_line+1)); toc->htmlable = htmlable; toc->otherfile = otherfile; _last_toc_line = num; if (toctail) toctail->next = toc; else tochead = toc; toctail = toc; } /* _add_external_file: * A special wrapper around _add_toc_line. buf contains both the filename * and the name which should be given to the link. Split both and call the * real funcion. */ static void _add_external_file(const char *buf, int line_number) { char *filename, *title; /* First validate buffer */ title = strpbrk(buf, "\t "); if (!title || is_empty(title)) { printf("Line %d has externalfile without title part (%s). " "Ignoring.\n", line_number, buf); return; } filename = m_strdup(buf); title = strpbrk(filename, "\t "); *title = 0; _add_toc_line(filename, title+1, 1, line_number, 0, 1, 1); free(filename); } /* _add_toc: */ static void _add_toc(char *buf, int root, int num, int texinfoable, int htmlable) { static int last_toc_line2 = INT_MIN; char b[256], b2[256]; int c, d; int done; int got; if (root) { _add_toc_line(buf, NULL, root, num, texinfoable, htmlable, 0); strcpy(b, buf); sprintf(buf, "%s", b, b); } else { got = 0; do { done = 1; for (c=0; buf[c]; c++) { if (buf[c] == '@') { for (d=0; myisalnum(buf[c+d+1]) || (buf[c+d+1] == '_') || (buf[c+d+1] == '/') || (buf[c+d+1] == '*'); d++) b[d] = buf[c+d+1]; b[d] = 0; _add_toc_line(b, NULL, 0, num, texinfoable, htmlable, 0); strcpy(b2, buf+c+d+1); sprintf(buf+c, "%s%s", b, b, b2); done = 0; got = 1; break; } } } while (!done); if ((!got) && (num > last_toc_line2+1)) { strcpy(b, buf); c = d = 0; while ((b[c]) && (myisspace(b[c]))) c++; while (b[c]) { if (myisalnum(b[c])) b2[d] = b[c]; else b2[d] = '_'; c++; d++; } b2[d] = 0; _add_toc_line(b2, b, 0, num, texinfoable, htmlable, 0); sprintf(buf, "%s", b2, b); } } last_toc_line2 = num; } /* _my_fgets: * Sometime in the future this should be replaced by the safe m_fgets * function. However, the rest of the functions in this file still rely * on the character buffer being modifiable, so cleaning this would * practically mean having to rewrite the other functions too. */ static char *_my_fgets(char *p, int max, FILE *f) { int c, ch; if (feof(f)) { p[0] = 0; return NULL; } for (c=0; c.. links and mangles them. * Modifications are made directly over buf, make sure there's enough * space in it. */ static void _mangle_email_links(char *buf) { assert(buf); while(*buf && (buf = strstr(buf, ""))) { char *temp, *end = strstr(buf, ""); assert(end); /* can't have multiline emails */ buf += 7; temp = _mangle_email(buf, end - buf); memmove(buf + strlen(temp), end, strlen(end) + 1); strncpy(buf, temp, strlen(temp)); free(temp); } } /* _mangle_email: * Given a string, len characters will be parsed. '@' will be substituted * by "' %s ', _email_mangle_at", and '.' will be substituted by "' %s ", * _email_mangle_dot". The returned string has to be freed by the caller. */ static char *_mangle_email(const char *email, int len) { char *temp, buf[2]; int pos; assert(email); assert(*email); assert(len > 0); temp = m_strdup(email); *temp = 0; buf[1] = 0; for(pos = 0; pos < len; pos++) { if(email[pos] == '@') { temp = m_strcat(temp, " "); temp = m_strcat(temp, _email_mangle_at); temp = m_strcat(temp, " "); } else if(email[pos] == '.') { temp = m_strcat(temp, " "); temp = m_strcat(temp, _email_mangle_dot); temp = m_strcat(temp, " "); } else { buf[0] = email[pos]; temp = m_strcat(temp, buf); } } return temp; } allegro4.4-4.4.2/docs/src/makedoc/makedoc.h000066400000000000000000000033061173507505700203060ustar00rootroot00000000000000#ifndef MAKEDOC_H #define MAKEDOC_H /* Some defines */ #define TEXT_FLAG 0x00000001 #define HTML_FLAG 0x00000002 #define HTML_CMD_FLAG 0x00000004 #define TEXINFO_FLAG 0x00000008 #define TEXINFO_CMD_FLAG 0x00000010 #define RTF_FLAG 0x00000020 #define MAN_FLAG 0x00000040 #define HEADING_FLAG 0x00000080 #define DEFINITION_FLAG 0x00000100 #define CONTINUE_FLAG 0x00000200 #define TOC_FLAG 0x00000400 #define INDEX_FLAG 0x00000800 #define NO_EOL_FLAG 0x00001000 #define MULTIFILE_FLAG 0x00002000 #define NOCONTENT_FLAG 0x00004000 #define NO_INDENT_FLAG 0x00008000 #define NODE_FLAG 0x00010000 #define NONODE_FLAG 0x00020000 #define STARTOUTPUT_FLAG 0x00040000 #define ENDOUTPUT_FLAG 0x00080000 #define TALLBULLET_FLAG 0x00100000 #define SHORT_TOC_FLAG 0x00200000 #define XREF_FLAG 0x00400000 #define HEADER_FLAG 0x00800000 #define START_TITLE_FLAG 0x01000000 #define END_TITLE_FLAG 0x02000000 #define STRUCT_FLAG 0x04000000 #define SHORT_DESC_FLAG 0x08000000 #define RETURN_VALUE_FLAG 0x10000000 #define EREF_FLAG 0x20000000 #define CHAPTER_FLAG 0x40000000 #define CHAPTER_END_FLAG 0x80000000 #define TOC_SIZE 8192 /* Structures */ typedef struct LINE { char *text; struct LINE *next; int flags; } LINE; typedef struct TOC { char *text; char *alt; struct TOC *next; int root; int texinfoable; int htmlable; int otherfile; } TOC; /* Visible globals */ extern LINE *head; extern TOC *tochead; extern int flags; #endif allegro4.4-4.4.2/docs/src/makedoc/makehtml.c000066400000000000000000001354471173507505700205140ustar00rootroot00000000000000/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Makedoc's html output routines. * * By Shawn Hargreaves. * * Grzegorz Adam Hankiewicz made the output valid HTML 4.0, made sorted * TOCs, added support for cross references and optional CSS to color * output, added support for auto types' cross references generation, * and a few smaller details more. * * Robert J. Ohannessian did some cosmetic improvements to the HTML * output and separated the CSS file. * * See readme.txt for copyright information. * * See allegro/docs/src/makedoc/format.txt for a brief description of * the source of _tx files. */ #include #include #include #include #include #include "makehtml.h" #include "makemisc.h" #include "makedoc.h" #include "maketexi.h" #define TOKEN_NORMAL 'n' #define TOKEN_TEXT 't' typedef struct t_post POST; struct t_post { char filename[1024]; char **token; int num; }; int html_flags; char charset[256]="iso-8859-1"; const char *html_extension = "html"; char *html_document_title; char *html_footer; char *html_see_also_text; char *html_examples_using_this_text; char *html_css_filename; char *html_return_value_text; char *html_text_substitution[256]; static POST **_post; static FILE *_file; static char _filename[1024]; static char *_xref[256], *_eref[256]; static char *_full_eref_list; static int _xrefs, _erefs; static int _empty_count; static char *_word_substitution[256]; static const char *_codeblock_start = "
      ";
      static const char *_codeblock_end = "
      "; static const int _codeblock_start_len = 30; static const int _codeblock_end_len = 19; /* MSVC doesn't like long strings. */ static const char *_css_data1 = "\ A.xref:link {\n\ \tcolor: blue;\n\ \ttext-decoration: none;\n\ \tbackground: transparent;\n\ }\n\ A.xref:visited {\n\ \tcolor: blue;\n\ \ttext-decoration: none;\n\ \tbackground: transparent;\n\ }\n\ A.xref:hover {\n\ \tcolor: blue;\n\ \ttext-decoration: underline;\n\ \tbackground: rgb(220, 220, 220);\n\ }\n\ A.xref:active {\n\ \tcolor: red;\n\ \ttext-decoration: none;\n\ \tbackground: rgb(255, 204, 50);\n\ }\n\ A.eref:link {\n\ \tcolor: blue;\n\ \ttext-decoration: none;\n\ \tbackground: transparent;\n\ }\n\ A.eref:visited {\n\ \tcolor: blue;\n\ \ttext-decoration: none;\n\ \tbackground: transparent;\n\ }\n\ A.eref:hover {\n\ \tcolor: blue;\n\ \ttext-decoration: underline;\n\ \tbackground: rgb(255, 165, 214);\n\ }\n\ A.eref:active {\n\ \tcolor: red;\n\ \ttext-decoration: none;\n\ \tbackground: rgb(255, 204, 50);\n\ }\n\ A.autotype:link {\n\ \tcolor: rgb(64, 64, 255);\n\ \ttext-decoration: none;\n\ \tbackground: transparent;\n\ }\n\ A.autotype:visited {\n\ \tcolor: rgb(64, 64, 255);\n\ \ttext-decoration: none;\n\ \tbackground: transparent;\n\ }\n\ A.autotype:hover {\n\ \tcolor: rgb(64, 64, 255);\n\ \ttext-decoration: underline;\n\ \tbackground: transparent;\n\ }\n\ "; static const char *_css_data2 = "\ A.autotype:active {\n\ \tcolor: red;\n\ \ttext-decoration: none;\n\ \tbackground: transparent;\n\ }\n\ blockquote.xref {\n\ \tfont-family: helvetica, verdana, serif;\n\ \tfont-size: smaller;\n\ \tborder: thin solid rgb(220, 220, 220);\n\ \tcolor: black;\n\ \tbackground: rgb(240, 240, 240);\n\ }\n\ blockquote.eref {\n\ \tfont-family: helvetica, verdana, serif;\n\ \tfont-size: smaller;\n\ \tborder: thin solid rgb(255, 165, 214);\n\ \tcolor: black;\n\ \tbackground: rgb(255, 201, 230);\n\ }\n\ blockquote.code {\n\ \tborder: thin solid rgb(255, 234, 190);\n\ \tcolor: black;\n\ \tbackground: rgb(255, 255, 205);\n\ }\n\ blockquote.text {\n\ \tborder: thin solid rgb(190, 234, 255);\n\ \tcolor: black;\n\ \tbackground: rgb(225, 255, 255);\n\ }\n\ div.al-api {\n\ \tpadding-left: 0.5em;\n\ \tcolor: black;\n\ \tbackground: rgb(255, 234, 100);\n\ \tfont-weight: bold;\n\ \tborder-bottom: medium solid rgb(255, 204, 51);\n\ \tborder-left: medium solid rgb(255, 204, 51);\n\ \tmargin-top: 2em;\n\ }\n\ div.al-api-cont {\n\ \tpadding-left: 0.5em;\n\ \tcolor: black;\n\ \tbackground: rgb(255, 234, 100);\n\ \tfont-weight: bold;\n\ \tborder-bottom: medium solid rgb(255, 204, 51);\n\ \tborder-left: medium solid rgb(255, 204, 51);\n\ \tmargin-top: -1em;\n\ }\n\ div.faq-shift-to-right {\n\ \tmargin-left: 2em;\n\ }\n\ div.al-back-to-contents {\n\ \ttext-align: center;\n\ \tfont-family: sans-serif;\n\ \tmargin-top: 1em;\n\ \tfont-weight: bold;\n\ \t/* Removing the comments of the next line create longer pages */\n\ \t/* margin-bottom: 100em; */\n\ }\n\ "; /* Internal functions */ static void _write_html_ref_list(char **ref, int *refs, const char *type); static void _write_html_ref(char *ref, const char *type); static void _output_html_footer(char *main_filename); static void _output_toc(char *filename, int root, int body, int part); static void _hfprintf(char *format, ...); static void _hfputs(char *string); static int _toc_scmp(const void *e1, const void *e2); static int _str_cmp(const void *s1, const void *s2); static int _output_section_heading(LINE *line, char *filename, int section_number); static void _output_custom_markers(LINE *line); static void _output_buffered_text(void); static void _output_html_header(char *section); static void _add_post_process_ref(const LINE *token, char type); static void _post_process_pending_refs(void); static POST *_search_post_section(const char *filename); static POST *_search_post_section_with_token(const char *token); static POST *_create_post_section(const char *filename); static void _destroy_post_page(POST *p); static void _post_process_filename(char *filename); static int _verify_correct_input(void); static void _close_html_file(FILE *file); static void _output_sorted_nested_toc(TOC **list, unsigned int num_items); static int _detect_non_paragraph_sections(const char *text); static char *_mark_up_auto_types(char *line, char **auto_types); static void _write_css_file(char *html_path, char *css_filename); static void _prepare_html_text_substitution(void); static void _free_html_text_substitution_memory(void); static char *_do_text_substitution(char *input); static void _output_symbol_index(void); static const char *_find_short_description(const LINE *line); static const char *_look_up_short_description(const char *token, int len); static char *_scan_line_for_code_tokens(char *line, int *code_scanning); static char *_replace_code_tokens(char *line, int column, int *end); static char *_find_potential_token(char *line, int column, int end, int *found_size); /* write_html: * Entry point to the function which translates makedoc's format * to correct html output. */ int write_html(char *filename) { int block_empty_lines = 0, section_number = 0, ret; int last_line_was_a_definition = 0; LINE *line = head; char **auto_types; if (_verify_correct_input()) return 1; /* English default text initialization */ if (!html_see_also_text) html_see_also_text = m_strdup("See also:"); if (!html_examples_using_this_text) html_examples_using_this_text = m_strdup("Examples using this:"); if (!html_return_value_text) html_return_value_text = m_strdup("Return value:"); /*printf("writing %s\n", filename);*/ _file = fopen(filename, "w"); if (!_file) return 1; /* build up a table with Allegro's structures' names (spelling?) */ auto_types = build_types_lookup_table(0); strcpy(_filename, filename); if(html_document_title) _output_html_header(0); /* write out css if specified and allowed */ if(html_css_filename && !(html_flags & HTML_IGNORE_CSS)) _write_css_file(filename, html_css_filename); while (line) { if (line->flags & HTML_FLAG) { if (line->flags & (HEADING_FLAG | NODE_FLAG | DEFINITION_FLAG)) { _write_html_ref_list(_xref, &_xrefs, "xref"); _write_html_ref_list(_eref, &_erefs, "eref"); } if (line->flags & HEADING_FLAG) { _output_buffered_text(); if (_output_section_heading(line, filename, section_number)) return 1; _add_post_process_ref(line, TOKEN_TEXT); section_number++; } else if (line->flags & RETURN_VALUE_FLAG) { assert(html_return_value_text); fputs("

      ", _file); fputs(html_return_value_text, _file); fputs("\n", _file); } else if (line->flags & NODE_FLAG) { _output_buffered_text(); /* output a node marker, which will be followed by a chunk of text inside a chapter */ fprintf(_file, "

      %s

      \n", line->text, line->text); _add_post_process_ref(line, TOKEN_TEXT); } else if (line->flags & DEFINITION_FLAG) { static int prev_continued = 0; char *temp = m_strdup(line->text); if (_empty_count && !block_empty_lines) _empty_count++; _output_buffered_text(); /* output a function definition */ _add_post_process_ref(line, TOKEN_NORMAL); temp = _mark_up_auto_types(temp, auto_types); if (!prev_continued) { if (!(html_flags & HTML_IGNORE_CSS)) { if (!last_line_was_a_definition) { fputs("

      ", _file); } else { fputs("
      ", _file); } } else { if (!last_line_was_a_definition) { fputs("
      ", _file); } else { fputs("", _file); } } } _hfprintf("%s", temp); if (!(line->flags & CONTINUE_FLAG)) { if (!(html_flags & HTML_IGNORE_CSS)) { fputs("

      ", _file); } else { fputs("

      ", _file); } prev_continued = 0; } else { prev_continued = 1; } fputs("\n", _file); free(temp); } else if ((!(line->flags & NO_EOL_FLAG)) && (is_empty(strip_html(line->text))) && (!strstr(line->text, "
    • "))) { _hfprintf("%s\n", line->text); if (!block_empty_lines) _empty_count++; } else if (strstr(line->text, "") || strstr(line->text, "")) { _output_buffered_text(); _output_custom_markers(line); } else { /* output a normal line */ _output_buffered_text(); if ((html_flags & HTML_SPACED_LI) && strstr(line->text, "
    • ")) fputs("

      ", _file); _hfputs(line->text); fputs("\n", _file); } /* mutex to control extra line output in preformated sections */ ret = _detect_non_paragraph_sections(line->text); if (ret) { if(!block_empty_lines) _empty_count = 0; block_empty_lines += ret; } } else if (line->flags & TOC_FLAG) { _write_html_ref_list(_xref, &_xrefs, "xref"); _write_html_ref_list(_eref, &_erefs, "eref"); if (flags & MULTIFILE_FLAG) { _output_buffered_text(); _output_toc(filename, 1, 0, -1); } else if (line->flags & SHORT_TOC_FLAG) { _output_buffered_text(); _output_toc(filename, 0, 1, -1); } else { _output_buffered_text(); _output_toc(filename, 1, 1, -1); } } else if (line->flags & XREF_FLAG) { if (line->flags & EREF_FLAG) _eref[_erefs++] = line->text; /* buffer example reference */ else _xref[_xrefs++] = line->text; /* buffer cross reference */ } else if (line->flags & INDEX_FLAG) { _output_buffered_text(); _output_symbol_index(); } /* Keep track of continuous definitions */ last_line_was_a_definition = (line->flags & DEFINITION_FLAG); line = line->next; } if ((flags & MULTIFILE_FLAG) && (section_number > 1)) _output_html_footer(filename); _close_html_file(_file); _post_process_pending_refs(); free(html_see_also_text); free(html_examples_using_this_text); free(html_return_value_text); free(_full_eref_list); destroy_types_lookup_table(auto_types, 0); return 0; } /* _output_custom_markers: * Converts the and custom markers to proper html code. */ static void _output_custom_markers(LINE *line) { char *s2, *s3; /* special munging for links */ char *s = line->text; do { s2 = strstr(s, ""); s3 = strstr(s, ""); if ((s2) || (s3)) { int i; char buf[256]; if ((s3) && ((!s2) || (s3 < s2))) s2 = s3; i = 0; while (s < s2) buf[i++] = *(s++); buf[i] = 0; _hfputs(buf); while (*s != '>') s++; s++; i = 0; while ((*s) && (*s != '<')) buf[i++] = *(s++); buf[i] = 0; if (s2[1] == 'e') _hfprintf("%s", buf, buf); else _hfprintf("%s", buf, buf); } } while (s2); _hfputs(s); fputs("\n", _file); } /* _write_html_ref_list: * Recieves an array of pointers and a pointer to the variable holding * the number of buffered text lines. Returns if there are none waiting * to be printed, otherwise sorts the list and writes a block of cross * references. Type should be the string "xref" or "eref". */ static void _write_html_ref_list(char **ref, int *refs, const char *type) { int i; assert(html_see_also_text); assert(html_examples_using_this_text); assert(type); assert(*type); if (!(*refs)) return; fputs("\n", type); else fputs(">", _file); /* select different wording depending on ref type */ if (*type == 'e') fputs(html_examples_using_this_text, _file); else fputs(html_see_also_text, _file); fputs("\n", _file); for (i=0; i<(*refs); i++) { if (i) _hfprintf(",\n"); _write_html_ref(ref[i], type); } *refs = 0; _hfprintf(".%s\n", (html_flags & HTML_IGNORE_CSS) ? "" : ""); _empty_count = 0; } /* _write_html_ref: * Writes a single cross reference splitting ref if needed. * Type should be the string "xref" or "eref". */ static void _write_html_ref(char *ref, const char *type) { char *tok, first = 1; tok = strtok(ref, ",;"); while (tok) { while ((*tok) && (myisspace(*tok))) tok++; if (!first) _hfprintf(",\n"); first = 0; _hfprintf("%s", tok, tok, tok); else _hfprintf("href=\"#%s\" title=\"@SHORTDESC %s@\">%s", tok, tok, tok); tok = strtok(NULL, ",;"); } } /* _write_css_file: * Writes a separate CSS file. Requires two path components: the first * one is the normal html path, the second is a relative path indicating * where to put the css file. The final path will be a composition of * both. */ static void _write_css_file(char *html_path, char *css_filename) { FILE *file; char *full_path; assert(html_path); assert(css_filename); full_path = m_replace_filename(html_path, css_filename); file = fopen(full_path, "wt"); if (!file) { free(full_path); return; } fputs(_css_data1, file); fputs(_css_data2, file); fclose(file); free(full_path); return; } /* _output_html_footer: * Writes that "Back to contets" message at the end of a file with a link. */ static void _output_html_footer(char *main_filename) { assert(html_footer); if (html_flags & HTML_OLD_F_TAG_FLAG) fprintf(_file, html_footer, get_filename(main_filename)); else fprintf(_file, "
      \n", get_filename(main_filename), html_footer); } /* _output_toc: */ static void _output_toc(char *filename, int root, int body, int part) { char name[256]; char *s; TOC *toc; int nested = 0; #define ALT_TEXT(toc) ((toc->alt) ? toc->alt : toc->text) if (root) { int section_number = 0; toc = tochead; if (toc) toc = toc->next; fprintf(_file, "
        \n"); while (toc) { if (toc->root) { if (toc->htmlable) { if (toc->otherfile) { sprintf(name, "%s.%s", toc->text, html_extension); mystrlwr(name); _hfprintf("
      • %s\n", name, ALT_TEXT(toc)); } else if (body) { _hfprintf("
      • %s\n", toc->text, ALT_TEXT(toc)); section_number++; } else { strcpy(name, filename); s = get_extension(name)-1; if (s - get_filename(name) > 5) s = get_filename(name)+5; sprintf(s, "%03d.%s", section_number, html_extension); _hfprintf("
      • %s\n", get_filename(name), ALT_TEXT(toc)); section_number++; } } else if (toc->root == 2) { _hfprintf("

      %s

        \n", ALT_TEXT(toc)); } else if (toc->root == 3) { _hfprintf("
        \n"); } } toc = toc->next; } fprintf(_file, "
      \n"); } if (body) { toc = tochead; if (toc) toc = toc->next; if (part <= 0) { TOC *ptr[TOC_SIZE]; int i = 0; if (root) fprintf(_file, "
        \n"); else fprintf(_file, "
          \n"); while (toc) { if ((toc->htmlable) && (!toc->otherfile)) { if (!toc->root) { if (!nested) { fprintf(_file, "
            \n"); nested = 1; } } else { if (nested) { _output_sorted_nested_toc(ptr, i); nested = i = 0; } } if (nested) { if (i < TOC_SIZE) ptr[i++] = toc; } else _hfprintf("
          • %s\n", toc->text, ALT_TEXT(toc)); } toc = toc->next; } if (nested) _output_sorted_nested_toc(ptr, i); if (root) fprintf(_file, "
          \n"); else fprintf(_file, "
        \n"); } else if (!(html_flags & HTML_OPTIMIZE_FOR_CHM) && !(html_flags & HTML_OPTIMIZE_FOR_DEVHELP)) { /* Outputs the function TOC for the current section. */ TOC *ptr[TOC_SIZE]; int j, i = 0; int section_number = 0; fprintf(_file, "\n
          \n"); while ((toc) && (section_number < part)) { if ((toc->htmlable) && (toc->root) && (!toc->otherfile)) section_number++; toc = toc->next; } while ((toc) && (!toc->root) && (i < TOC_SIZE)) { if (toc->htmlable) ptr[i++] = toc; toc = toc->next; } if (i > 1) qsort(ptr, i, sizeof(TOC *), _toc_scmp); for (j = 0; j < i; j++) { _hfprintf("
        • %s", ptr[j]->text, ALT_TEXT(ptr[j])); fprintf(_file, " — "); _hfprintf("@SHORTDESC %s@\n", ALT_TEXT(ptr[j])); } fprintf(_file, "
        \n"); } } } /* _hfprintf: */ static void _hfprintf(char *format, ...) { char buf[1024]; va_list ap; va_start(ap, format); vsprintf(buf, format, ap); va_end(ap); _hfputs(buf); } /* _hfputs: * Outputs string to _file. At the same time some things are substituted: * (>) for (>), (<) for (<), (&) for (&) and (`word') for * (`word'). */ static void _hfputs(char *string) { char *end = 0; while (*string) { /* Found simple text comma? */ if ((end == 0) && (string[0] == '`')) { end = strchr(string + 1, 39); /* Is there a closing comma? */ if (end) { char *p = string + 1; /* Check for a specific character range */ while ((p < end) && ((*p >= '.') && (*p <= 'z'))) p++; if ((p == end) && (p - string > 1)) { fputs("`", _file); string++; continue; } else { end = 0; } } } /* Is closing comma search active? */ if ((string[0] == 39) && end == string) { fputs("'", _file); string++; end = 0; continue; } if ((string[0] == '&') && ((string[1] == 'l') || (string[1] == 'g')) && (string[2] == 't')) { fputc('&', _file); fputc(string[1], _file); fputc('t', _file); fputc(';', _file); string += 3; } else if ((string[0] == '&') && (string[1] != 'l') && (string[1] != 'g')) { fputs("&", _file); string++; } else { fputc(*string, _file); string++; } } } /* _toc_scmp: * qsort helper which compares two TOC nodes alphabeticaly. */ static int _toc_scmp(const void *e1, const void *e2) { TOC *t1 = *((TOC **)e1); TOC *t2 = *((TOC **)e2); return mystricmp(t1->text, t2->text); } /* _str_cmp: * qsort helper which compares two tokens alphabetically. */ static int _str_cmp(const void *s1, const void *s2) { const char *t1 = *((const char **)s1); const char *t2 = *((const char **)s2); return strcmp(t1, t2); } /* _output_section_heading: * Used to mark a new section of the document. In multifile output closes * the actual file and writes a new one. */ static int _output_section_heading(LINE *line, char *filename, int section_number) { char buf[256], *s; /* output a section heading, switching file as required */ if ((flags & MULTIFILE_FLAG) && (section_number > 0)) { if (section_number > 1) _output_html_footer(filename); _close_html_file(_file); strcpy(buf, filename); s = get_extension(buf)-1; if (s - get_filename(buf) > 5) s = get_filename(buf)+5; sprintf(s, "%03d.%s", section_number-1, html_extension); /*printf("writing %s\n", buf);*/ _file = fopen(buf, "w"); if (!_file) return 1; strcpy(_filename, buf); _output_html_header(line->text); } _hfprintf("

        %s

        \n", line->text); if ((flags & MULTIFILE_FLAG) && (!(line->flags & NOCONTENT_FLAG)) && (section_number > 0)) { _output_toc(filename, 0, 1, section_number); } return 0; } /* _output_html_header: * The header of an HTML document is a little bit complex, so it deserves * it's own function. In the header you have the title of the document, * the character set definition and the style sheet specification. This * function just outputs to _file the correct tags, it presumes _file * has just been opened. The title is specified in the source document * with a @document_title= line, and section can be another text which will * be appended to the title. */ static void _output_html_header(char *section) { assert(html_document_title); if (html_flags & HTML_OLD_H_TAG_FLAG) { if (section && strlen(strip_html(section))) { int i; for (i=0; html_document_title[i]; i++) { if (html_document_title[i] == '#') fputs(strip_html(section), _file); else fputc(html_document_title[i], _file); } } } else { fputs("\n", _file); fputs("\n", _file); fputs(html_document_title, _file); if (section && strlen(strip_html(section))) { fputs(": ", _file); fputs(strip_html(section), _file); } fputs("\n\n", _file); fputs("\n", _file); /* optional style sheet output */ if (!(html_flags & HTML_IGNORE_CSS)) { fputs("\n", _file); if (html_css_filename) { fprintf(_file, "", html_css_filename); } else { fputs("\n", _file); } } /* header end and body start */ fputs("\n", _file); } } /* _output_buffered_text: * Outputs buffered text, which might be a set of cross references * followed by a number of empty lines, which will be transformed * to apropiate HTML tags. */ static void _output_buffered_text(void) { if (_empty_count) { if (_empty_count > 1) fputs("


        \n", _file); else fputs("

        \n", _file); _empty_count = 0; } } /* _post_process_pending_refs: * Reopens all the created files and scans for post process tags, which * will be replaced with correct filenames according to the post process * info in memory. Additionally, it will also look for text substitutions * placed in the html_text_substitution global array. */ static void _post_process_pending_refs(void) { int f; if (!_post) return ; _prepare_html_text_substitution(); for(f = 0; _post[f]; f++) _post_process_filename(_post[f]->filename); for(f = 0; _post[f]; f++) _destroy_post_page(_post[f]); _free_html_text_substitution_memory(); free(_post); _post = 0; } /* _add_post_process_ref: * Adds a token to a buffer with the current filename for a post process. * The type of the reference will be stored as the first character of * the clean token, and a comma will separate its short description if * there is any available. */ static void _add_post_process_ref(const LINE *line, char type) { const char *token, *short_desc; char *clean_token; POST *p; assert(line); token = line->text; clean_token = get_clean_ref_token(token); /* ignore empty tokens, or those with space at the beginning */ if (!clean_token[0] || myisspace(clean_token[0])) { free(clean_token); return ; } p = _search_post_section(_filename); if (!p) p = _create_post_section(_filename); short_desc = _find_short_description(line); /* Reserve memory for the list, and the token with type. */ p->token = m_xrealloc(p->token, sizeof(char*) * (1 + p->num)); p->token[p->num] = m_strcat(m_strdup(" "), clean_token); p->token[p->num][0] = type; /* If we found a short description, add it with a comma. */ if (short_desc) { p->token[p->num] = m_strcat(p->token[p->num], ","); p->token[p->num] = m_strcat(p->token[p->num], short_desc); } p->num++; } /* _search_post_section: * Searches the globals for an existant POST page which matches filename. * Returns the POST page or NULL if none was found. */ static POST *_search_post_section(const char *filename) { int f; if (!_post) return 0; for(f = 0; _post[f]; f++) if (!strcmp(_post[f]->filename, filename)) return _post[f]; return 0; } /* _search_post_section_with_token: * Similar to _search_post_section, but instead of matching filenames, * returns the page containing the specified token, NULL if none was found. */ static POST *_search_post_section_with_token(const char *token) { int f, g, len; if (!_post) return 0; len = strlen(token); for(f = 0; _post[f]; f++) { for(g = 0; g < _post[f]->num; g++) { if (!strncmp(_post[f]->token[g] + 1, token, len)) { /* Still, we have to verify the tokens have correct size. */ const char *desc = strchr(_post[f]->token[g], ','); if (desc && (desc - _post[f]->token[g] - 1) == len) return _post[f]; else if (!desc && strlen(_post[f]->token[g] + 1) == (size_t)len) return _post[f]; } } } return 0; } /* _look_up_short_description: * Retrieves from the cached short description the one which matches * len characters from the string token. Returns NULL if none is found. */ static const char *_look_up_short_description(const char *token, int len) { int f, g; if (!_post) return 0; for(f = 0; _post[f]; f++) { for(g = 0; g < _post[f]->num; g++) { /* First see if this entry has a short description. */ const char *desc = strchr(_post[f]->token[g], ','); if (!desc) continue; /* Does the found token have the lenght we are looking for? */ if ((desc - _post[f]->token[g] - 1) != len) continue; /* Verify that the token is the same and has correct length. */ if (!strncmp(_post[f]->token[g] + 1, token, len)) return desc + 1; /* Avoid the comma. */ } } return 0; } /* _create_post_section: * Adds one POST section matching filename to the global array of pages * after creating a new POST page, which will be returned. */ static POST *_create_post_section(const char *filename) { int num; POST *p; p = m_xmalloc(sizeof(POST)); p->token = m_xmalloc(sizeof(char*)); p->num = 0; strcpy(p->filename, filename); if (!_post) { _post = m_xmalloc(sizeof(POST*)); _post[0] = 0; } for(num = 0; _post[num]; num++) ; _post = m_xrealloc(_post, sizeof(POST*) * (2 + num)); _post[num++] = p; _post[num] = 0; return p; } /* _destroy_post_page: * Frees the memory used by a post page. */ static void _destroy_post_page(POST *p) { int f; for(f = 0; f < p->num; f++) free(p->token[f]); free(p->token); free(p); } /* _post_process_filename: * Opens the filename and replaces the post process tags. */ static void _post_process_filename(char *filename) { int code_scanning = 0; char *new_filename, *p; char *line; FILE *f1 = 0, *f2 = 0; new_filename = m_strdup(filename); if (!new_filename || strlen(new_filename) < 2) goto cancel; new_filename[strlen(filename)-1] = 'x'; f1 = fopen(filename, "rt"); f2 = fopen(new_filename, "wt"); if (!f1 || !f2) goto cancel; /*printf("post processing %s\n", filename);*/ code_scanning = 0; while ((line = m_fgets(f1))) { /* Transform read lines into hyperlinks with post process marks. */ line = _scan_line_for_code_tokens(line, &code_scanning); /* Loop over pending filename post process marks. */ while ((p = strstr(line, "\"post_process#"))) { char *clean_token = get_clean_ref_token(p + 2); POST *page = _search_post_section_with_token(clean_token); if (!page) { printf("Didn't find ref for %s (clean: %s)\n", line, clean_token); memmove(p, p + 14, strlen(p + 14) + 1); } else { char *temp = m_xmalloc(1 + strlen(line) + 13 + strlen(get_filename(page->filename))); strncpy(temp, line, p - line + 1); if (!(html_flags & HTML_OPTIMIZE_FOR_DEVHELP) && !strcmp(filename, page->filename)) strcpy(&temp[p - line + 1], p + 13); else { strcpy(&temp[p - line + 1], get_filename(page->filename)); strcat(temp, p + 13); } free(line); line = temp; } free(clean_token); } /* Loop over pending short description marks. */ while ((p = strstr(line, "@SHORTDESC "))) { const char *desc; char *end = strchr(p + 11, '@'); if (!end) { printf("Didn't find closing of @SHORTDESC!\n"); abort(); } desc = _look_up_short_description(p + 11, end - p - 11); if (desc) { /* Substitute with found test. */ char *temp = m_xmalloc(1 + strlen(line) + strlen(desc)); strncpy(temp, line, p - line); strcpy(temp + (p - line), desc); strcat(temp, end + 1); /* Don't copy the @ from end. */ free(line); line = temp; } else { /* Remove the description then. */ if (strncmp(p - 8, "— ", 8) == 0) { /* Remove the previous dash too. */ p -= 8; } memmove(p, end + 1, strlen(end)); } } line = _do_text_substitution(line); fputs(line, f2); free(line); } fclose(f1); fclose(f2); f1 = f2 = 0; if (remove(filename)) goto cancel; rename(new_filename, filename); cancel: if (f1) fclose(f1); if (f2) fclose(f2); if (new_filename) { remove(new_filename); free(new_filename); } } /* _verify_correct_input: * Goes through some bits marked during _tx read and verifies that the * input file is ok, returning non-zero with bad files. */ static int _verify_correct_input(void) { int ret = 0; if (html_flags & HTML_OLD_H_TAG_FLAG) { printf("The tag '@h=#' and its variant "); printf("is obsolete.\nPlease use '@document_title blah blah blah' instead.\n"); printf("Otherwise the output won't be valid HTML code and won't use CSS.\n"); printf("And make sure you aren't using any , or <body> tags!.\n"); } if (!(html_flags & HTML_DOCUMENT_TITLE_FLAG) && (flags & MULTIFILE_FLAG)) { printf("Missing tag for document title. You should use one of these:\n"); printf("@document_title=Allegro manual. (this is recommended)\n ...or...\n"); printf("@h=<html><head><title>#.\n...and later...\n"); printf("@\n@\n@Allegro - a game programming library\n@\n"); ret++; } if (html_flags & HTML_OLD_F_TAG_FLAG) { printf("The tags '@f=blah', '@f1=blah' and '@f2=blah' are obsolete.\n"); printf("Please use '@html_footer=Back to contents' or something similar instead.\n"); printf("And make sure you aren't using any , or <body> tags!.\n"); } if (!(html_flags & HTML_FOOTER_FLAG) && (flags & MULTIFILE_FLAG)) { printf("For multifile documents please use '@html_footer=Back to contents'.\n"); } return ret; } /* _close_html_file: * Closes the stream after writting the apropiate html close tags. */ static void _close_html_file(FILE *file) { fputs("\n</body>\n</html>\n", file); fclose(file); } /* _output_sorted_nested_toc: * Outputs the buffered TOC list, according to num_items. After the * list a </ul> is appended to the text. */ static void _output_sorted_nested_toc(TOC **list, unsigned int num_items) { unsigned int f; if (num_items > 1) qsort(list, num_items, sizeof(TOC *), _toc_scmp); for (f = 0; f < num_items; f++) { _hfprintf("<li><a href=\"#%s\">%s</a>", list[f]->text, ALT_TEXT(list[f])); fprintf(_file, " — "); _hfprintf("@SHORTDESC %s@\n", ALT_TEXT(list[f])); } fprintf(_file, "</ul>\n"); } /* _detect_non_paragraph_sections: * Used on a line of text, detects if the line contains tags after which the * paragraph tag <p> can't exist because it would break html validity. * The return value is a bit special: it * will be zero if no tags where found. For each opening tag the function * will add one to the return value. Equally, each closing tag will substract * one from the return value. Examples: * <pre>..</pre>...<pre> will return 1 * <pre>..<pre>...<pre> will return 3 (note that HTML isn't valid) * ..</pre>.. will return -1 */ static int _detect_non_paragraph_sections(const char *text) { static const char *tags[] = {"pre>", "ul>", "h1>", "h2>", "h3>", "h4>", "h5>", "h6>", "i>", "strong>", "em>", "b>", 0}; const char *p = text; int f, ret = 0; assert(text); while ((p = strchr(p, '<'))) { p++; if (*p == '/') p++; for (f = 0; tags[f]; f++) { if (strncmp(p, tags[f], strlen(tags[f])) == 0) { if (*(p-1) == '/') ret--; else ret++; } } } return ret; } /* _mark_up_auto_types: * Instead of flooding the xref section with detected autotypes, and in * order to obtain a higher coolness factor, autotypes are detected at * definition lines and turned into hyperlinks. For this to happen you * need to pass the text line you would output for a normal definition * line, but it HAS to be dynamic memory (ie: m_strdup'ed). Pass a * previously generated auto_types table. * line has to be dynamic because it will be expanded whenever auto types * are found. Since this is done reallocating, this function will return * the new line pointer you should be using after calling this. */ static char *_mark_up_auto_types(char *line, char **auto_types) { int length; char *p; assert(line); assert(auto_types); /* Did we find some auto type? */ while ((p = strstruct(line, auto_types, &length, 0))) { char *temp = m_strdup(p); *p = 0; if (flags & MULTIFILE_FLAG) { int offset = 22; char *mark = m_xmalloc(3 * length + 47 + 21); if (html_flags & HTML_IGNORE_CSS) strcpy(mark, "<a href=\"post_process#"); else { strcpy(mark, "<a class=\"autotype\" href=\"post_process#"); offset += 17; } strncpy(mark + offset, temp, length); offset += length; strcpy(mark + offset, "\" title=\"@SHORTDESC "); offset += 20; strncpy(mark + offset, temp, length); offset += length; strcpy(mark + offset, "@\">"); offset += 3; strncpy(mark + offset, temp, length); offset += length; strcpy(mark + offset, "</a>"); line = m_strcat(line, mark); free(mark); line = m_strcat(line, temp + length); } else { int offset = 10; char *mark = m_xmalloc(3 * length + 35 + 21); if (html_flags & HTML_IGNORE_CSS) strcpy(mark, "<a href=\"#"); else { strcpy(mark, "<a class=\"autotype\" href=\"#"); offset += 17; } strncpy(mark + offset, temp, length); offset += length; strcpy(mark + offset, "\" title=\"@SHORTDESC "); offset += 20; strncpy(mark + offset, temp, length); offset += length; strcpy(mark + offset, "@\">"); offset += 3; strncpy(mark + offset, temp, length); offset += length; strcpy(mark + offset, "</a>"); line = m_strcat(line, mark); free(mark); line = m_strcat(line, temp + length); } free(temp); } return line; } /* _prepare_html_text_substitution(): * The html_text_substitution array has pointers to text lines in the form * word|text. This function fills a global array with duplicates of word, * and at the same time makes html_text_substitution point directly at * text. With two arrays it is easier to search for words and replace with * the text when they are found. */ static void _prepare_html_text_substitution(void) { int f; char *p; for (f = 0; html_text_substitution[f]; f++) { assert(f < 256); p = strchr(html_text_substitution[f] + 1, '|'); assert(p); *p = 0; _word_substitution[f] = m_strdup(html_text_substitution[f]); p = m_strdup(p + 1); free(html_text_substitution[f]); html_text_substitution[f] = p; } } /* _free_html_text_substitution_memory: * Frees memory stored in the _word_substitution global array. */ static void _free_html_text_substitution_memory(void) { int f; for (f = 0; _word_substitution[f]; f++) { free(html_text_substitution[f]); free(_word_substitution[f]); } } /* _do_text_substitution: * Given a malloc'ed string, searches all _word_substitution in it and * replaces them with html_text_substition if found. Returns a new * string or the one you passed if no changes were made. */ static char *_do_text_substitution(char *input) { int start, end, middle, f; char *temp, *found, *reader; for (f = 0; _word_substitution[f]; f++) { reader = input; while ((found = strstr(reader, _word_substitution[f]))) { /* Find lengths */ start = found - input; middle = strlen(html_text_substitution[f]); end = strlen(found + strlen(_word_substitution[f])); /* Create new string and free old one */ temp = m_xmalloc(start + middle + end + 1); strncpy(temp, input, start); strcpy(temp + start, html_text_substitution[f]); strcat(temp, found + strlen(_word_substitution[f])); free(input); /* Prepare for next loop */ input = temp; reader = temp + start + middle; } } return input; } /* _output_symbol_index: * Called at the end of the first html pass, generates a list of links * to the so far found tokens in the text, which will be hyperlinked * correctly during the second pass. */ static void _output_symbol_index(void) { int f, g, num = 0; char last_letter; char **list = NULL; for(f = 0; _post[f]; f++) { for(g = 0; g < _post[f]->num; g++) { char *tok = _post[f]->token[g]; /* filter text tokens, they are not interesting */ if (tok[0] == TOKEN_TEXT) continue; tok++; /* filter normal tokens from the example list */ if (_full_eref_list && strstr(_full_eref_list, tok)) continue; list = m_xrealloc(list, sizeof(char *) * (num + 1)); list[num++] = tok; } } if (num < 1) return ; qsort(list, num, sizeof(char *), _str_cmp); /* Create minitoc scanning first letters of sorted list. */ fprintf(_file, "<div class='mini_toc' id='top'>\n\t"); for (f = 0, last_letter = -1; f < num; f++) { /* Valid range? */ if (list[f][0] >= 'A' && list[f][0] <= 'z') { /* Different letter? */ if (last_letter != list[f][0]) { last_letter = list[f][0]; fprintf(_file, "<a href='#mini_toc_%c%d'>%c</a>\n\t", last_letter, last_letter > '_', last_letter); } } } fprintf(_file, "\n</div>\n\n"); for (f = 0, last_letter = -1; f < num; f++) { char *p, *temp; /* Did we change letter section? */ if (list[f][0] >= 'A' && list[f][0] <= 'z' && list[f][0] != last_letter) { /* Is this the first section or another one? */ if (last_letter != -1) fprintf(_file, "\n</ul>\n"); last_letter = list[f][0]; fprintf(_file, "<h1 class='mini_toc' " "id='mini_toc_%c%d'><a href='#top'>%c</a></h1>\n<ul>\n", last_letter, last_letter > '_', last_letter); } /* Before writing the string, remove possible short descriptions. */ temp = m_strdup(list[f]); p = strchr(temp, ','); if (p) *p = 0; _hfprintf("<li><a href=\"post_process#%s\">%s</a>", temp, temp); fprintf(_file, " — "); _hfprintf("@SHORTDESC %s@\n", temp); } fprintf(_file, "</ul>"); } /* _find_short_description: * Given a line, looks forward enough to find a @shortdesc definition. * Returns a const pointer to the text of the line, or NULL if no * short definition was found. */ static const char *_find_short_description(const LINE *line) { assert(line); while (1) { line = line->next; if (!line) return 0; /* So, did we find a short description? */ if (line->flags & SHORT_DESC_FLAG) return line->text; /* Continue parsing through continuations or definitions. */ if (line->flags & (CONTINUE_FLAG | DEFINITION_FLAG)) continue; /* Abort on beginning of new chapters, nodes, and paragraphs. */ if (line->flags & (HEADING_FLAG | NODE_FLAG | TEXT_FLAG)) return 0; /* Safe abort on (nearl) empty lines. */ if (strlen(line->text) < 2) return 0; } return 0; } /* _scan_line_for_code_tokens: * Transforms line looking for code tokens. line has to be a dynamic * reallocable string. The code_scanning variable should point to a * state variable indicating whether the line we are processing should be * looked for code tokens or not. When looking for code tokens, anything * in the global token cache will be hyperlinked. */ static char *_scan_line_for_code_tokens(char *line, int *code_scanning) { int column = 0; assert(line); assert(code_scanning); while (1) { if (*code_scanning) { int end; /* Substituting text and looking for closing tags. */ char *p = strstr(line + column, _codeblock_end); if (!p) { end = strlen(line); return _replace_code_tokens(line, column, &end); } /* Looks like we have to change state. */ end = p - line; line = _replace_code_tokens(line, column, &end); column = end; *code_scanning = 0; } else { /* Looking for code chunks. */ char *p = strstr(line + column, _codeblock_start); if (!p) return line; /* Looks like we did find something. Change state. */ column = (p - line) + _codeblock_start_len; *code_scanning = 1; } } } /* _replace_code_tokens: * Given a dynamic line, a beginning and an end, this function replaces * all known tokens with hyperlinks to be post processed. When the new * line is returned, end will have been updated to point at the new * end character in the returned string (because it will grow). */ static char *_replace_code_tokens(char *line, int column, int *end) { int found_size; POST *page; char buf[256]; char *p, *new_line; int expanded; while ((p = _find_potential_token(line, column, *end, &found_size))) { assert(found_size < 255); /* Extract potential token into separate buffer. */ strncpy(buf, p, found_size); buf[found_size] = 0; page = _search_post_section_with_token(buf); if (!page) { column = p - line + found_size; continue; } column = p - line; /* Found a token. Resize line and replace token with hyperlink. */ new_line = m_xmalloc(strlen(line) + found_size * 3 + 69); strncpy(new_line, line, column); new_line[column] = 0; strcat(new_line, "<a href=\"post_process#"); strcat(new_line, buf); strcat(new_line, "\" class=\"autotype\" title=\"@SHORTDESC "); strcat(new_line, buf); strcat(new_line, "@\">"); strcat(new_line, buf); strcat(new_line, "</a>"); expanded = strlen(new_line) - column - found_size; strcat(new_line, line + column + found_size); free(line); line = new_line; column += expanded + found_size; *end = *end + expanded; } return line; } /* _find_potential_token: * In aline, starting at column and endign at end, tries to find potential * tokens, which is words composed of alphanumeric characters and the * underscore. If found, a pointer to the token inside the line is * returned and the length stored in found_size. */ static char *_find_potential_token(char *line, int column, int end, int *found_size) { char *p = line + column; *found_size = 0; #define VALID_CHARACTER() \ (*p == '_' || \ (*p >= 'A' && *p <= 'Z') || \ (*p >= 'a' && *p <= 'z') || \ (*p >= '0' && *p <= '9')) /* Discard bad characters. */ while (!VALID_CHARACTER()) { p++; column++; if (p - line >= end) return 0; } /* Now accept good ones. */ while (VALID_CHARACTER()) { p++; *found_size = *found_size + 1; if (column + *found_size == end) break; } #undef VALID_CHARACTER if (*found_size > 0) return line + column; else return 0; } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������allegro4.4-4.4.2/docs/src/makedoc/makehtml.h��������������������������������������������������������0000664�0000000�0000000�00000001427�11735075057�0020507�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������#ifndef MAKEHTML_H #define MAKEHTML_H #define HTML_OLD_H_TAG_FLAG 0x00000001 #define HTML_DOCUMENT_TITLE_FLAG 0x00000002 #define HTML_OLD_F_TAG_FLAG 0x00000004 #define HTML_FOOTER_FLAG 0x00000008 #define HTML_SPACED_LI 0x00000010 #define HTML_IGNORE_CSS 0x00000020 #define HTML_OPTIMIZE_FOR_CHM 0x00000040 #define HTML_OPTIMIZE_FOR_DEVHELP 0x00000080 extern int html_flags; extern char charset[256]; extern const char *html_extension; extern char *html_document_title; extern char *html_footer; extern char *html_see_also_text; extern char *html_examples_using_this_text; extern char *html_css_filename; extern char *html_return_value_text; extern char *html_text_substitution[256]; int write_html(char *filename); #endif �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������allegro4.4-4.4.2/docs/src/makedoc/makeman.c���������������������������������������������������������0000664�0000000�0000000�00000021732�11735075057�0020312�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Makedoc's man output routines. * * By Shawn Hargreaves. * * See readme.txt for copyright information. * * See allegro/docs/src/makedoc/format.txt for a brief description of * the source of _tx files. */ #include <stdio.h> #include <string.h> #include <stdlib.h> #include <assert.h> #include "makeman.h" #include "makedoc.h" #include "makemisc.h" char manheader[256] = ""; char mansynopsis[256] = ""; char *man_shortdesc_force1; char *man_shortdesc_force2; static int _mpreformat = 0; static int _mpreindent = 0; static void _write_man_xref(FILE *f, char *xref, char *ext, int notfirst); static char *_man_name(char *p); static void _mfputs(char *p, FILE *f); static void _write_short_desc(FILE *f, LINE *line); /* write_man: * Entry point of man page generation function. */ int write_man(char *filename) { char buf[256], buf2[256]; char *xref[256]; int xrefs = 0; LINE *line = head; LINE *l2; FILE *f = NULL; FILE *f2; char *p; int i; /* Free strings if not both of them where specified. */ if (!(man_shortdesc_force1 && man_shortdesc_force2)) { if (man_shortdesc_force1) free(man_shortdesc_force1); if (man_shortdesc_force2) free(man_shortdesc_force2); man_shortdesc_force1 = man_shortdesc_force2 = 0; } while (line) { if (line->flags & (HEADING_FLAG | DEFINITION_FLAG | NODE_FLAG)) { /* close off any previous manpage */ if (f) { if (xrefs > 0) { fprintf(f, ".SH SEE ALSO\n"); for (i=0; i<xrefs; i++) _write_man_xref(f, xref[i], get_extension(filename), i); fprintf(f, "\n"); xrefs = 0; } fclose(f); f = NULL; } } if (line->flags & MAN_FLAG) { if (line->flags & RETURN_VALUE_FLAG) { fprintf(f, ".SH \"RETURN VALUE\"\n"); } else if (line->flags & DEFINITION_FLAG) { /* start a manpage */ p = _man_name(line->text); if (p) { strcpy(buf, filename); strcpy(get_filename(buf), p); strcat(buf, "."); strcat(buf, get_extension(filename)); /*printf("writing %s\n", buf);*/ f = fopen(buf, "w"); if (!f) return 1; fprintf(f, ".\\\" Generated by the Allegro makedoc utility\n"); fprintf(f, ".TH %s %s %s\n", p, get_extension(filename), manheader); fprintf(f, ".SH NAME\n"); fprintf(f, "%s", p); if (!(line->flags & CONTINUE_FLAG)) { l2 = line->next; while ((l2) && (l2->flags & DEFINITION_FLAG)) { p = _man_name(l2->text); if (p) fprintf(f, ", %s", p); l2 = l2->next; } } _write_short_desc(f, line); fprintf(f, "\n.SH SYNOPSIS\n"); if (mansynopsis[0]) fprintf(f, ".B %s\n\n", mansynopsis); /* go ahead and find all the header lines */ l2 = line; while (l2 && l2->flags & CONTINUE_FLAG) l2=l2->next; if (l2) { l2 = l2->next; while (l2 && (l2->flags & HEADER_FLAG)) { fprintf(f, ".B %s\n", l2->text); l2 = l2->next; if (l2 && (l2->flags & HEADER_FLAG)) { fprintf(f, ".br\n"); } } } fprintf(f, ".sp\n"); fputs(".B ", f); _mfputs(line->text, f); i = (line->flags & CONTINUE_FLAG); while ((line->next) && (line->next->flags & DEFINITION_FLAG)) { line = line->next; if (!i) { /* multiple entries require a crosslink file */ p = _man_name(line->text); if (p) { strcpy(buf2, filename); strcpy(get_filename(buf2), p); strcat(buf2, "."); strcat(buf2, get_extension(filename)); /*printf("writing %s\n", buf2);*/ f2 = fopen(buf2, "w"); if (!f2) return 1; fprintf(f2, ".so man%s/%s\n", get_extension(filename), get_filename(buf)); fclose(f2); } fputc('\n', f); } fputs(".B ", f); _mfputs(line->text, f); } fprintf(f, ".SH DESCRIPTION\n"); _mpreformat = 0; } xrefs = 0; } else { /* normal output mode */ if (f) _mfputs(line->text, f); } } else if (line->flags & XREF_FLAG) { xref[xrefs++] = line->text; } line = line->next; } return 0; } /* _write_man_xref: */ static void _write_man_xref(FILE *f, char *xref, char *ext, int notfirst) { char *tok, *p; tok = strtok(xref, ",;"); while (tok) { while ((*tok) && (myisspace(*tok))) tok++; p = tok; while (*p) { if ((!myisalnum(*p)) && (*p != '_')) break; p++; } if (!*p) { if (notfirst) fprintf(f, ",\n"); fprintf(f, ".BR %s (%s)", tok, ext); notfirst = 1; } tok = strtok(NULL, ",;"); } } /* _man_name: */ static char *_man_name(char *p) { static char buf[256]; int i = 0; while ((*p) && (*p != '"')) p++; if (*p == '"') { p++; while ((*p) && (*p != '"')) { if ((!myisalnum(*p)) && (*p != '_')) return NULL; buf[i++] = *(p++); } if (i) { buf[i] = 0; return buf; } } return NULL; } /* _mfputs: */ static void _mfputs(char *p, FILE *f) { int state = 0; int i; if (_mpreformat) { if (_mpreindent < 0) { _mpreindent = 0; while ((*p) && (myisspace(*p))) { _mpreindent++; p++; } } else { for (i=0; i<_mpreindent; i++) { if ((!*p) || (!myisspace(*p))) break; p++; } } fputs(" ", f); } else { while ((*p) && (myisspace(*p))) p++; } while (*p) { /* less-than HTML tokens */ if ((p[0] == '&') && (mytolower(p[1]) == 'l') && (mytolower(p[2]) == 't')) { fputc('<', f); p += 3; state = 1; } /* greater-than HTML tokens */ else if ((p[0] == '&') && (mytolower(p[1]) == 'g') && (mytolower(p[2]) == 't')) { fputc('>', f); p += 3; state = 1; } /* bold HTML tokens */ else if ((p[0] == '<') && (mytolower(p[1]) == 'b') && (p[2] == '>')) { if (state) putc('\n', f); fputs(".B ", f); p += 3; } /* end bold HTML tokens */ else if ((p[0] == '<') && (mytolower(p[1]) == '/') && (mytolower(p[2]) == 'b') && (p[3] == '>')) { if (state) fputc('\n', f); state = -1; p += 4; } /* line break HTML tokens */ else if ((p[0] == '<') && (mytolower(p[1]) == 'b') && (mytolower(p[2]) == 'r') && (p[3] == '>')) { if (state >= 0) { fputc('\n', f); state = 0; } p += 4; } /* enter preformatted mode */ else if ((p[0] == '<') && (mytolower(p[1]) == 'p') && (mytolower(p[2]) == 'r') && (mytolower(p[3]) == 'e') && (p[4] == '>')) { fputs("\n.nf\n", f); state = -1; _mpreformat = 1; _mpreindent = -1; p += 5; } /* leave preformatted mode */ else if ((p[0] == '<') && (mytolower(p[1]) == '/') && (mytolower(p[2]) == 'p') && (mytolower(p[3]) == 'r') && (mytolower(p[4]) == 'e') && (p[5] == '>')) { fputs("\n.fi\n", f); state = -1; _mpreformat = 0; p += 6; } /* strip other HTML tokens */ else if (p[0] == '<') { while ((*p) && (*p != '>')) p++; if (*p) p++; } /* output other characters */ else { if (*p == '\\') fputc('\\', f); fputc(*p, f); p++; state = 1; } } if (state >= 0) fputc('\n', f); } /* _write_short_desc: * Advances the line pointer until the next man page definition * looking for a short description, which would be printed to * the currently open file. */ static void _write_short_desc(FILE *f, LINE *line) { assert(f); assert(line); assert(line->flags & (MAN_FLAG | DEFINITION_FLAG)); /* Jump current definition. */ while (line && line->flags & DEFINITION_FLAG) line = line->next; while (1) { if (!line) goto empty_title; if (line->flags & (MAN_FLAG | DEFINITION_FLAG)) goto empty_title; if (line->flags & (HEADING_FLAG | DEFINITION_FLAG | NODE_FLAG)) goto empty_title; if (line->flags & SHORT_DESC_FLAG) { /* Do we need to add the forced text to the title? */ if (man_shortdesc_force1 && !mystristr(line->text, man_shortdesc_force1)) fprintf(f, " \\- %s %s\\&", line->text, man_shortdesc_force2); else fprintf(f, " \\- %s\\&", line->text); return ; } line = line->next; } empty_title: /* If we reach here, we didn't find a short description. Force one? */ if (man_shortdesc_force1) fprintf(f, " \\- %s\\&", man_shortdesc_force2); } ��������������������������������������allegro4.4-4.4.2/docs/src/makedoc/makeman.h���������������������������������������������������������0000664�0000000�0000000�00000000315�11735075057�0020311�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������#ifndef MAKEMAN_H #define MAKEMAN_H extern char manheader[256]; extern char mansynopsis[256]; extern char *man_shortdesc_force1; extern char *man_shortdesc_force2; int write_man(char *filename); #endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������allegro4.4-4.4.2/docs/src/makedoc/makemisc.c��������������������������������������������������������0000664�0000000�0000000�00000021422�11735075057�0020466�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Makedoc's miscellaneous functions * * By Shawn Hargreaves. * * Grzegorz Adam Hankiewicz added safe memory/io functions. * * See readme.txt for copyright information. * * See allegro/docs/src/makedoc/format.txt for a brief description of * the source of _tx files. */ #include <string.h> #include <stdlib.h> #include <stdio.h> #include <assert.h> #include "makemisc.h" #define _CHUNK 100 /* myisalum: */ int myisalnum(int c) { return (((c >= '0') && (c <= '9')) || ((c >= 'A') && (c <= 'Z')) || ((c >= 'a') && (c <= 'z')) || (c >= 0x80) || (c < 0)); } /* mytolower: */ int mytolower(int c) { if ((c >= 'A') && (c <= 'Z')) c -= ('A' - 'a'); return c; } /* mystricmp: */ int mystricmp(const char *s1, const char *s2) { int c1, c2; do { c1 = mytolower(*(s1++)); c2 = mytolower(*(s2++)); } while ((c1) && (c1 == c2)); return c1 - c2; } /* mystristr: * Like strstr but ignoring case during comparisons. */ char *mystristr(const char *HAYSTACK, const char *NEEDLE) { const char *end; assert(HAYSTACK); assert(NEEDLE); assert(strlen(NEEDLE) > 0); end = strchr(HAYSTACK, 0) - strlen(NEEDLE); while (HAYSTACK <= end) { if (strincmp(HAYSTACK, NEEDLE) == 0) return (char*)HAYSTACK; HAYSTACK++; } return 0; } /* mystrlwr: */ char *mystrlwr(char *string) { char *p; for (p=string; *p; p++) *p = mytolower(*p); return string; } /* strincmp: * Compares two strings ignoring case up to s2's length. */ int strincmp(const char *s1, const char *s2) { while (*s2) { if (mytolower(*s1) != mytolower(*s2)) return 1; s1++; s2++; } return 0; } /* myisspace: */ int myisspace(int c) { return ((c == ' ') || (c == '\t') || (c == '\r') || (c == '\n') || (c == '\f') || (c == '\v')); } /* strip_html: */ char *strip_html(char *p) { static char buf[256]; int c; c = 0; while (*p) { if (*p == '<') { while ((*p) && (*p != '>')) p++; if (*p) p++; } else { buf[c] = *p; c++; p++; } } buf[c] = 0; return buf; } /* is_empty: * Returns true if the string constist of something more than space or tabs. */ int is_empty(char *s) { while (*s) { if ((*s) != ' ' && (*s) != '\t') return 0; s++; } return 1; } /* get_filename: */ char *get_filename(const char *path) { int pos; for (pos=0; path[pos]; pos++) ; /* do nothing */ while ((pos>0) && (path[pos-1] != '\\') && (path[pos-1] != '/')) pos--; return (char*)path+pos; } /* get_extension: * If filename contains a dot, this function will return a pointer to the * first character after the dot. Otherwise it returns a pointer to the * end of the string, position which holds the string terminator. */ char *get_extension(const char *filename) { int pos, end; for (end=0; filename[end]; end++) ; /* do nothing */ pos = end; while ((pos>0) && (filename[pos-1] != '.') && (filename[pos-1] != '\\') && (filename[pos-1] != '/')) pos--; if (filename[pos-1] == '.') return (char*)filename+pos; return (char*)filename+end; } /* scmp: */ int scmp(const void *e1, const void *e2) { char *s1 = *((char **)e1); char *s2 = *((char **)e2); return mystricmp(s1, s2); } /* get_clean_ref_token: * Given a text, extracts the clean ref token, which either has to be * surrounded by "ss#..", inside a <a name=".." tag, or without any * html characters around. Otherwise returns an empty string. The * returned string has to be freed always. */ char *get_clean_ref_token(const char *text) { char *buf, *t; const char *pname, *pcross; pname = strstr(text, "<a name=\""); pcross = strstr(text, "ss#"); if (pname && pcross) { /* Take the first one */ if (pname < pcross) pcross = 0; else pname = 0; } if (pname) { buf = m_strdup(pname + 9); t = strchr(buf, '"'); *t = 0; } else if (pcross) { buf = m_strdup(pcross + 3); t = strchr(buf, '"'); *t = 0; } else if (!strchr(text, '<') && !strchr(text, '>')) buf = m_strdup(text); else { /* this is mainly for debugging */ printf("'%s' was rejected as clean ref token\n", text); buf = m_strdup(""); } assert(buf); return buf; } /* m_xmalloc: * Returns the requested chunk of memory. If there's not enough * memory, the program will abort. */ void *m_xmalloc(size_t size) { void *p = malloc(size); if (!p) m_abort(1); return p; } /* m_xrealloc: * Wrapper around real realloc call. Returns the new chunk of memory or * aborts execution if it couldn't realloc it. */ void *m_xrealloc(void *ptr, size_t new_size) { if (!ptr) return m_xmalloc(new_size); ptr = realloc(ptr, new_size); if (!ptr) m_abort(1); return ptr; } /* m_abort: * Aborts execution with a hopefully meaningful message. If code is less * than 1, an undefined exit will happen. Available error codes: * 1: insufficient memory */ void m_abort(int code) { switch(code) { case 1: printf("Aborting due to insuficcient memory\n"); break; default: printf("An undefined error caused abnormal termination\n"); } abort(); } /* m_strdup: * Safe wrapper around strdup, always returns the duplicated string. */ char *m_strdup(const char *text) { char *p = m_xmalloc(strlen(text)+1); return strcpy(p, text); } /* m_fgets: * Safe function to read text lines from a file. Returns the read line * or NULL when you reach the end of the file or there's a problem. */ char *m_fgets(FILE *file) { int read, filled = 0, size = 0; char *buf = 0; while ((read = getc(file)) != EOF) { while (filled + 2 >= size) { size += _CHUNK; buf = m_xrealloc(buf, size); } if (read != '\r') buf[filled++] = read; buf[filled] = 0; if (read == '\n') break; } return buf; } /* m_strcat: * Special strcat function, which is a mixture of realloc and strcat. * The first parameter has to be a pointer to dynamic memory, since it's * space will be resized with m_xrealloc (it can be NULL). The second * pointer can be any type of string, and will be appended to the first * one. This function returns a new pointer to the memory holding both * strings. */ char *m_strcat(char *dynamic_string, const char *normal_string) { int len; if(!dynamic_string) return m_strdup(normal_string); len = strlen(dynamic_string); dynamic_string = m_xrealloc(dynamic_string, 1 + len + strlen(normal_string)); strcpy(dynamic_string + len, normal_string); return dynamic_string; } /* m_replace_extension: * Replaces the extension (any text after last dot in string and after last * path separator) in path with the new one. If there's no dot in path, path * and extension will be concatenated like '"%s.%s", path, extension'. * Returns the created string, which has to be freed. Usage example: * char *dest = m_replace_extension(argv[2], "html"); */ char *m_replace_extension(const char *path, const char *extension) { char *p; assert(path); assert(extension); p = get_extension(path); if(*p) { int len = p - path; char *temp = m_xmalloc(len + 1 + strlen(extension)); strncpy(temp, path, len); strcpy(temp+len, extension); return temp; } else { char *temp = m_xmalloc(strlen(path) + 2 + strlen(extension)); sprintf(temp, "%s.%s", path, extension); return temp; } } /* m_replace_filename: * Replaces the filename (any text after the last slash or backslash in * the string) in the path with the new one. If there's no slash or * backslash in the path, path and filename will be concatenated like * '%s/%s', path, filename'. Returns the created string, which has to be * freed. Usage example: * char *dest = m_replace_filename(argv[2], "out.html"); */ char *m_replace_filename(const char *path, const char *filename) { char *p; assert(path); assert(filename); p = get_filename(path); if(*p) { int len = p - path; char *temp = m_xmalloc(len + 1 + strlen(filename)); strncpy(temp, path, len); strcpy(temp+len, filename); return temp; } else { char *temp = m_xmalloc(strlen(path) + 2 + strlen(filename)); sprintf(temp, "%s/%s", path, filename); return temp; } } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������allegro4.4-4.4.2/docs/src/makedoc/makemisc.h��������������������������������������������������������0000664�0000000�0000000�00000001607�11735075057�0020476�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������#ifndef MAKEMISC_H #define MAKEMISC_H int myisalnum(int c); int mytolower(int c); int mystricmp(const char *s1, const char *s2); char *mystristr(const char *HAYSTACK, const char *NEEDLE); char *mystrlwr(char *string); int strincmp(const char *s1, const char *s2); int myisspace(int c); char *strip_html(char *p); int is_empty(char *s); char *get_extension(const char *filename); char *get_filename(const char *path); int scmp(const void *e1, const void *e2); char *get_clean_ref_token(const char *text); /* Safe memory functions */ void *m_xmalloc(size_t size); void *m_xrealloc(void *ptr, size_t new_size); void m_abort(int code); char *m_strdup(const char *text); char *m_strcat(char *dynamic_string, const char *normal_string); char *m_fgets(FILE *file); char *m_replace_extension(const char *path, const char *extension); char *m_replace_filename(const char *path, const char *filename); #endif �������������������������������������������������������������������������������������������������������������������������allegro4.4-4.4.2/docs/src/makedoc/makertf.c���������������������������������������������������������0000664�0000000�0000000�00000032165�11735075057�0020334�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Makedoc's rtf output routines. * * By Shawn Hargreaves. * * See readme.txt for copyright information. * * See allegro/docs/src/makedoc/format.txt for a brief description of * the source of _tx files. */ #include <stdio.h> #include <string.h> #include "makertf.h" #include "makedoc.h" #include "makemisc.h" char rtfheader[256] = ""; char *rtf_language_header; /* write_rtf: */ int write_rtf(char *filename) { LINE *line = head; LINE *l; char *p, *last = 0; FILE *f; int preformat = 0; int prevhead = 0; int prevdef = 0; int multidef = 0; int pardebt = 0; int parloan = 0; int indent = 0; int indef = 0; int weakdef = 0; int bullet = 0; int inbullet = 0; int tallbullets = 0; #define PAR() \ { \ if (pardebt > 0) \ pardebt--; \ else \ fputs("\\par ", f); \ \ while (inbullet > 0) { \ fputs("\\pard ", f); \ fprintf(f, "\\li%d ", indent*INDENT_SIZE); \ inbullet--; \ } \ } /*printf("writing %s\n", filename);*/ f = fopen(filename, "w"); if (!f) return 1; /* Fonts: * 0 - Times New Roman * 1 - Courier New * 2 - Symbol * * Colors: * 1 - Black * 2 - Red * 3 - Green * 4 - Blue * * Styles: * 0 - Normal * 1 - Quotation * 2 - Heading 1 * 3 - Heading 2 * 4 - Header * 5 - TOC 1 * 6 - Index 1 */ #define NORMAL_STYLE "\\f0\\fs20 " #define QUOTATION_STYLE "\\f1\\fs18 " #define HEADING_STYLE "\\f0\\fs48\\sa600\\pagebb\\keepn\\ul " #define DEFINITION_STYLE "\\f0\\fs24\\sb200\\keepn\\sa200\\b " #define HEADER_STYLE "\\f0\\fs20\\tqc\\tx4153\\tqr\\tx8306 " #define TOC_STYLE "\\f0\\fs24\\tqr\\tldot\\tx8640 " #define INDEX_STYLE "\\f0\\fs20\\tqr\\tldot\\tx8640 " #define INDENT_SIZE 400 #define BULLET_INDENT 250 fputs("{\\rtf\\ansi\\deff0\\widowctrl " NORMAL_STYLE "\n", f); fputs("{\\colortbl;\\red0\\green0\\blue0;\\red255\\green0\\blue0;\\red0\\green255\\blue0;\\red0\\green0\\blue255;}\n", f); if(rtf_language_header) fputs(rtf_language_header, f); else { fputs("{\\fonttbl{\\f0\\froman\\fcharset0\\fprq2 Times New Roman;}\n", f); fputs("{\\f1\\fmodern\\fcharset0\\fprq1 Courier New;}\n", f); fputs("{\\f2\\froman\\fcharset2\\fprq2 Symbol;}}\n", f); } fputs("{\\stylesheet {\\widctlpar " NORMAL_STYLE "\\snext0 Normal;}\n", f); fputs("{\\s1\\widctlpar " QUOTATION_STYLE "\\sbasedon0\\snext1 Quotation;}\n", f); fputs("{\\s2\\widctlpar " HEADING_STYLE "\\sbasedon0\\snext2 Heading 1;}\n", f); fputs("{\\s3\\widctlpar " DEFINITION_STYLE "\\sbasedon0\\snext3 Heading 2;}\n", f); fputs("{\\s4\\widctlpar " HEADER_STYLE "\\sbasedon0\\snext4 Header;}\n", f); fputs("{\\s5\\widctlpar " TOC_STYLE "\\sbasedon0\\snext0 TOC 1;}\n", f); fputs("{\\s6\\widctlpar " INDEX_STYLE "\\sbasedon0\\snext0 Index 1;}}\n", f); if (rtfheader[0]) { fputs("{\\header \\pard\\plain \\s4 " HEADER_STYLE "\\pvpara\\phmrg\\posxr\\posy0 page {\\field{\\*\\fldinst PAGE}{\\fldrslt 2}}\n", f); fputs("\\par \\pard \\s4\\ri360 " HEADER_STYLE "{\\i ", f); fputs(rtfheader, f); fputs("} \\pard}\n", f); } while (line) { if (line->flags & RTF_FLAG) { p = line->text; if (indef) { /* end the indentation from the previous definition? */ if (weakdef) { if (is_empty(strip_html(line->text))) { fputs("\\par}", f); pardebt++; indent--; indef = 0; weakdef = 0; } } else { l = line; while ((l->next) && l->text && (is_empty(strip_html(l->text)))) l = l->next; if (l->flags & (HEADING_FLAG | DEFINITION_FLAG | NODE_FLAG)) { fputs("\\par}", f); pardebt++; indent--; indef = 0; } } } if (line->flags & HEADING_FLAG) { /* start a section heading */ fputs("{\\s2 " HEADING_STYLE, f); } else if (line->flags & DEFINITION_FLAG) { /* start a function definition */ if (prevdef) { if (multidef) { /* continued from previous line */ while ((p[1]) && (myisspace(p[1]))) p++; } else { /* new definition, but flush with previous one */ fputs("{\\s3 " DEFINITION_STYLE "\\sb0 ", f); } } else { /* new function definition */ fputs("{\\s3 " DEFINITION_STYLE, f); } if (line->flags & CONTINUE_FLAG) { /* this definition continues onto the next line */ multidef = 1; } else { /* this paragraph should be flush with the next */ multidef = 0; if ((line->next) && (line->next->flags & DEFINITION_FLAG)) fputs("\\sa0 ", f); } prevdef = 1; } else { prevdef = 0; multidef = 0; if (!preformat) { /* skip leading spaces */ while ((*p) && (myisspace(*p))) p++; } } while (*p) { last = 0; if (strincmp(p, "<p>") == 0) { /* paragraph breaks */ PAR(); p += 3; } else if (strincmp(p, "<br>") == 0) { /* line breaks */ PAR(); p += 4; } else if (strincmp(p, "<pre>") == 0) { /* start preformatted text */ fputs("\\par {\\s1 " QUOTATION_STYLE, f); while (inbullet > 0) { fputs("\\pard ", f); fprintf(f, "\\li%d ", indent*INDENT_SIZE); inbullet--; } preformat = 1; p += 5; } else if (strincmp(p, "</pre>") == 0) { /* end preformatted text */ if (strincmp(line->text, "</pre>") == 0) { fputs("}", f); if (indent > (indef ? 1 : 0)) { fputs("\\pard ", f); fprintf(f, "\\li%d ", indent*INDENT_SIZE); } } else { fputs("\\par}", f); pardebt++; if (indent > (indef ? 1 : 0)) inbullet++; } preformat = 0; p += 6; } else if (strincmp(p, "<title>") == 0) { /* start document title */ fputs("{\\info{\\title ", f); p += 7; } else if (strincmp(p, "") == 0) { /* end document title */ fputs("}{\\author Allegro makedoc utility}}\n", f); p += 8; } else if (strincmp(p, "


        ") == 0) { /* section division */ if (strincmp(line->text, "
    • ")) PAR(); fputs("\\brdrb\\brdrs\\brdrw15\\brsp20 \\par \\pard \\par ", f); p += 4; } else if (strincmp(p, "") == 0) { /* start bold text */ fputs("{\\b ", f); p += 3; } else if (strincmp(p, "") == 0) { /* end bold text */ fputs("\\par}", f); pardebt++; p += 4; } else if (strincmp(p, "") == 0) { /* start italic text */ fputs("{\\i ", f); p += 3; } else if (strincmp(p, "") == 0) { /* end italic text */ fputs("\\par}", f); pardebt++; p += 4; } else if (strincmp(p, "

      ") == 0) { /* start heading text */ fputs("{\\f0\\fs48 ", f); p += 4; } else if (strincmp(p, "

      ") == 0) { /* end heading text */ fputs("\\par}", f); pardebt++; p += 5; } else if (strincmp(p, "

      ") == 0) { /* start subheading text */ fputs("{\\f0\\fs24\\b ", f); p += 4; } else if (strincmp(p, "

      ") == 0) { /* end subheading text */ fputs("\\par}", f); pardebt++; p += 5; } else if (strincmp(p, "
      ") == 0) { /* start centered text */ fputs("\\par {\\qc ", f); pardebt++; p += 8; } else if (strincmp(p, "
      ") == 0) { /* end centered text */ fputs("\\par}", f); pardebt++; p += 9; } else if (strincmp(p, "") == 0) { /* start bullet list */ indent++; fprintf(f, "\\par {\\li%d ", indent*INDENT_SIZE); pardebt++; p += 4; } else if (strincmp(p, "
    ") == 0) { /* end bullet list */ indent--; if (indent == (indef ? 1 : 0)) tallbullets = 0; else inbullet++; fputs("\\par}", f); pardebt++; p += 5; } else if (strincmp(p, "
  • ") == 0) { /* bullet item */ bullet = 1; p += 4; } else if (*p == '<') { /* skip unknown HTML tokens */ while ((*p) && (*p != '>')) p++; if (*p) p++; } else if (strincmp(p, "<") == 0) { /* less-than HTML tokens */ fputs("<", f); p += 3; } else if (strincmp(p, ">") == 0) { /* greater-than HTML tokens */ fputs(">", f); p += 3; } else if (*p == '\\') { /* backslash escape */ fputs("\\\\", f); p++; } else if (*p == '{') { /* open brace escape */ fputs("\\{", f); p++; } else if (*p == '}') { /* close brace escape */ fputs("\\}", f); p++; } else { while (pardebt > 0) { fputs("\\par ", f); pardebt--; } if (bullet) { /* precede this paragraph with a bullet symbol */ fputs("{\\pntext\\f2\\fs16 \\'b7\\tab}\n", f); fprintf(f, "{\\*\\pn \\pnlvlblt\\pnf2\\pnfs16\\pnindent%d{\\pntxtb \\'b7}}\n", BULLET_INDENT); fprintf(f, "\\fi%d\\li%d ", -BULLET_INDENT, indent*INDENT_SIZE); if (tallbullets) fputs("\\sa80 ", f); bullet = 0; inbullet++; } /* normal character */ fputc((unsigned char)*p, f); last = p++; } } if (line->flags & HEADING_FLAG) { /* end a section heading */ fputs("\\par }\n", f); } else if (prevdef) { /* end a function definition */ if (!multidef) { fputs("\\par }\n", f); if ((!indef) && (line->next) && (!(line->next->flags & DEFINITION_FLAG))) { /* indent the definition body text */ indent++; fprintf(f, "{\\li%d ", indent*INDENT_SIZE); indef = 1; if (line->flags & NONODE_FLAG) weakdef = 1; } } } else if (preformat) { /* hard CR for preformatted blocks */ fputs("\n", f); parloan++; } else if (!(line->flags & NO_EOL_FLAG)) { if ((is_empty(strip_html(line->text))) && (!strstr(line->text, "
    "))) { /* output an empty line */ if (!prevhead) { parloan++; if (!strstr(line->text, "")) parloan++; } } else { if (last && *last != 32) fputs(" ", f); /* add artificial space */ fputs("\n", f); /* normal EOL */ } } } else if (line->flags & NODE_FLAG) { /* index node */ if (line->flags & HTML_FLAG) { fputs("\\brdrb\\brdrs\\brdrw15\\brsp20 \\par \\pard \\par \\par ", f); } fputs("{\\xe\\v ", f); fputs(line->text, f); fputs("}\n", f); } else if (line->flags & TOC_FLAG) { /* table of contents */ PAR(); fputs("\n{\\field{\\*\\fldinst TOC \\\\t \"Heading 1\" }{\\fldrslt {\\b\\i\\ul\\fs24\\cf2 Update this field to generate the table of contents.}}}\n", f); } else if (line->flags & INDEX_FLAG) { /* index */ PAR(); fputs("\n{\\field{\\*\\fldinst INDEX \\\\e \"\\tab \" \\c \"1\" }{\\fldrslt {\\b\\i\\ul\\fs24\\cf2 Update this field to generate the document index.}}}\n", f); } else if (line->flags & TALLBULLET_FLAG) { /* larger spacing after bulleted paragraphs */ tallbullets = 1; } prevhead = (line->flags & HEADING_FLAG); /* advance to the next line */ l = line->next; if (l) { while ((l->next) && l->text && (is_empty(l->text)) && (l->next->flags == l->flags)) { l = l->next; } if ((l->next) && (l->next->flags & HEADING_FLAG)) { if (indef) { fputs("\\par}", f); pardebt++; indent--; indef = 0; } PAR(); line = l->next; parloan = 0; pardebt = 0; } else line = line->next; } else line = NULL; while (parloan > 0) { PAR(); parloan--; } } fputs("}\n", f); fclose(f); return 0; } allegro4.4-4.4.2/docs/src/makedoc/makertf.h000066400000000000000000000002131173507505700203260ustar00rootroot00000000000000#ifndef MAKERTF_H #define MAKERTF_H extern char rtfheader[256]; extern char *rtf_language_header; int write_rtf(char *filename); #endif allegro4.4-4.4.2/docs/src/makedoc/makesci.c000066400000000000000000000104731173507505700203150ustar00rootroot00000000000000/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Makedoc's SciTE API output routines. * * By Bobby Ferris. * * See readme.txt for copyright information. * * See allegro/docs/src/makedoc/format.txt for a brief description of * the source of _tx files. */ #include #include #include #include "makesci.h" #include "makemisc.h" /* _file_size: * Returns the size of the file specified. */ static int _file_size(const char *filename) { int ret = 0; FILE *f = fopen(filename, "r"); if(f) { if(fseek(f, 0L, SEEK_END) == 0) ret = ftell(f); fclose(f); } return ret; } /* _ignore_line: * Tells if it is supposed to ignore the line, of if it contains data for the * API file. */ static int _ignore_line(char *x) { return strincmp(x, "typedef") == 0 || strincmp(x, "extern") == 0 || strincmp(x, "struct") == 0 || strincmp(x, "example") == 0 || strincmp(x, "drivers") == 0 || strincmp(x, "#define") == 0; } /* _convert: * Converts filename into apifilename. * Returns: 0 if converted successfully * 1 if an error occurred. */ static int _convert(const char *filename, const char *apifilename) { FILE *tx_file, *api_file; int i, fs, offset; char tmp[1024]; char *buf; tx_file = fopen(filename, "r"); if(!tx_file) return 1; fs = _file_size(filename); buf = malloc(fs+1); fread(buf, sizeof(char), fs, tx_file); /* read in the file */ fclose(tx_file); api_file = fopen(apifilename, "w"); if (!api_file) { free(buf); return 1; } for(i = 0; i < fs; ++i) { if(buf[i] == '@' && buf[i+1] == '\\') { int index; memset(tmp, '\0', sizeof(tmp)); for(; buf[i] == '@' || buf[i] == '\\' || buf[i] == ' '; ++i) ; for(offset = i; buf[i] != '@'; ++i) tmp[i-offset] = buf[i]; tmp[i-offset-1] = '\0'; ++i; if(!_ignore_line(tmp)) { int done = 0; int will_be_done = 0; memset(tmp, '\0', sizeof(tmp)); for(offset = i; buf[i] != '\n'; ++i) tmp[i-offset] = buf[i]; index = i-offset; ++i; while(!done) { if(buf[i] == '@' && buf[i+1] == '@') will_be_done = 1; for(; buf[i] == '@' || buf[i] == '\\' || buf[i] == ' '; ++i) ; --i; for(offset = i; buf[i] != '\n'; ++i) tmp[(i - offset)+index] = buf[i]; index = (i - offset)+index; ++i; if(will_be_done) done=1; } fprintf(api_file, "%s\n", tmp); } else { int done = 0; int will_be_done = 0; memset(tmp, '\0', sizeof(tmp)); for(offset = i; buf[i] != '\n'; ++i) ; ++i; while(!done) { if(buf[i] == '@' && buf[i+1] == '@') will_be_done = 1; for(; buf[i] == '@' || buf[i] == '\\' || buf[i] == ' '; ++i) ; --i; for(offset = i; buf[i] != '\n'; ++i) ; ++i; if(will_be_done) done=1; } } } else if(buf[i] == '@' && buf[i+1] == '@') { memset(tmp, '\0', sizeof(tmp)); for(; buf[i] == '@'; ++i) ; for(offset = i; buf[i] != '@'; ++i) tmp[i-offset] = buf[i]; tmp[i-offset-1] = '\0'; ++i; if(!_ignore_line(tmp)) { memset(tmp, '\0', sizeof(tmp)); for(offset = i; buf[i] != '\n'; ++i) tmp[i-offset] = buf[i]; fprintf(api_file, "%s\n", tmp); ++i; } } } fclose(api_file); free(buf); return 0; } /* write_scite: * Entry point to the function which translates makedoc's format * to correct SciTE API output. */ int write_scite(char *filename, char *src) { /*printf("Writing %s (SciTE API File)\n", filename);*/ return _convert(src, filename); } allegro4.4-4.4.2/docs/src/makedoc/makesci.h000066400000000000000000000001311173507505700203100ustar00rootroot00000000000000#ifndef MAKESCI_H #define MAKESCI_H int write_scite(char *filename, char *src); #endif allegro4.4-4.4.2/docs/src/makedoc/maketexi.c000066400000000000000000000517401173507505700205120ustar00rootroot00000000000000/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Makedoc's texinfo output routines. * * By Shawn Hargreaves. * * Grzegorz Adam Hankiewicz added support for auto types' cross * references generation. * * See readme.txt for copyright information. * * See allegro/docs/src/makedoc/format.txt for a brief description of * the source of _tx files. */ #include #include #include #include #include "maketexi.h" #include "makertf.h" #include "makedoc.h" #include "makemisc.h" int multiwordheaders = 0; static int _no_strip; static int _strip_indent = -1; static char **_build_multi_identifier_nodes_table(void); static void _destroy_multi_identifier_nodes_table(char **table); static void _write_textinfo_xref(FILE *f, char *xref, char **chapter_nodes, char **secondary_nodes); static int _valid_texinfo_node(char *s, char **next, char **prev); static void _output_texinfo_toc(FILE *f, int root, int body, int part); static char *_node_name(int i); static char *_first_word(char *s); static void _html_to_texinfo(FILE *f, char *p); static void _write_auto_types_xrefs(FILE *f, char **auto_types, char *found_auto_types); static int _is_auto_type_starting_letter(char c); static int _is_auto_type_allowed_letter(char c); /* write_texinfo: */ int write_texinfo(char *filename) { char buf[256]; LINE *line = head, *title_line = 0; char *p, *str, *next, *prev; char *xref[256], *chapter_nodes[256], **auto_types; char *found_auto_types, **multi_identifier_nodes; int xrefs = 0; int in_item = 0; int section_number = 0; int toc_waiting = 0; int continue_def = 0; int title_pass = 0; int in_chapter = 0; int i = 0; char up_target[256] = "Top"; FILE *f; /*printf("writing %s\n", filename);*/ f = fopen(filename, "w"); if (!f) return 1; /* First scan all the chapters of the documents and build a lookup table * with their text lines. This lookup table will be used during the * generation of @xref texinfo commands, due to textinfo's restriction * that nodes can't contain spaces, and hence remain as a single word. */ chapter_nodes[0] = 0; while (line) { if (line->flags & TEXINFO_FLAG) { p = line->text; if (line->flags & (HEADING_FLAG | CHAPTER_FLAG)) { chapter_nodes[i++] = p; chapter_nodes[i] = 0; } } line = line->next; } /* Now scan all the definitions and see where are more than one * definition per texi node, building a lookup table for the * identifiers which don't have their own node so we can reference them * correctly from other nodes. */ multi_identifier_nodes = _build_multi_identifier_nodes_table(); /* Build up a table with Allegro's structures' names (spelling?) */ auto_types = build_types_lookup_table(&found_auto_types); /* Now reinit values and let real scanning start */ line = head; while (line) { if (line->flags & TEXINFO_FLAG) { p = line->text; /* end of an ftable? */ if (in_item) { if ((*p) && (*p != ' ') && (*p != '<')) { fputs("@end ftable\n", f); in_item = 0; } } if (!in_item) { /* start a new node? */ str = strstr(p, "
    p) { str += strlen("flags & NONODE_FLAG) && /* Output a symbol (@@void @func()). */ (_valid_texinfo_node(buf, &next, &prev))) { if (toc_waiting) { _output_texinfo_toc(f, 0, 1, section_number-1); toc_waiting = 0; } if (xrefs > 0) { fputs("See also:@*\n", f); for (i=0; iflags & NO_INDENT_FLAG)) { if (_no_strip) { if (_strip_indent >= 0) { for (i=0; (i<_strip_indent) && (*p) && (myisspace(*p)); i++) p++; } else { if (!is_empty(p)) { _strip_indent = 0; while ((*p) && (myisspace(*p))) { _strip_indent++; p++; } } } } else { while ((*p) && (myisspace(*p))) p++; } } if (line->flags & TEXINFO_CMD_FLAG) { /* raw output of texinfo commands */ fputs(p, f); fputs("\n", f); } else if (line->flags & HTML_CMD_FLAG) { /* process HTML commands */ while (*p) { if (p[0] == '<') { _html_to_texinfo(f, p+1); while ((*p) && (*p != '>')) p++; if (*p) p++; } else p++; } } else if (line->flags & (HEADING_FLAG | CHAPTER_FLAG)) { if (toc_waiting) { _output_texinfo_toc(f, toc_waiting == 2 ? 1 : 0, 1, section_number-1); toc_waiting = 0; } /* output a section heading */ if (section_number > 0) { if (line->flags & CHAPTER_FLAG) { in_chapter = 0; strcpy(up_target, "Top"); } if (in_item) { fputs("@end ftable\n", f); in_item = 0; } if (xrefs > 0) { fputs("See also:@*\n", f); for (i=0; iflags & NOCONTENT_FLAG)) toc_waiting = 1; if (line->flags & CHAPTER_FLAG) { in_chapter = 1; strcpy(up_target, _node_name(section_number)); toc_waiting = 2; } } section_number++; } else { if (line->flags & DEFINITION_FLAG) { /* This will detect all the possible auto types of the line. * The detected types will be marked in the found_auto_types * table for later delayed output. */ int length; char *temp = strstruct(line->text, auto_types, &length, found_auto_types); while(temp) temp = strstruct(temp+length, auto_types, &length, found_auto_types); } if ((line->flags & DEFINITION_FLAG) && (!continue_def)) fputs("@item @t{", f); while (*p) { /* less-than HTML tokens */ if ((p[0] == '&') && (mytolower(p[1]) == 'l') && (mytolower(p[2]) == 't')) { fputc('<', f); p += 3; } /* greater-than HTML tokens */ else if ((p[0] == '&') && (mytolower(p[1]) == 'g') && (mytolower(p[2]) == 't')) { fputc('>', f); p += 3; } /* process other HTML tokens */ else if (p[0] == '<') { _html_to_texinfo(f, p+1); while ((*p) && (*p != '>')) p++; if (*p) p++; } /* output other characters */ else { if ((*p == '{') || (*p == '}') || (*p == '@')) fputc('@', f); fputc((unsigned char)*p, f); p++; } } if (line->flags & CONTINUE_FLAG) fputs(" ", f); else { if (line->flags & DEFINITION_FLAG) fputs("}", f); fputs("\n", f); } } } else if (line->flags & CHAPTER_END_FLAG) { in_chapter = 0; strcpy(up_target, "Top"); } else if (line->flags & NODE_FLAG) { if (in_item) { fputs("@end ftable\n", f); if (toc_waiting) { _output_texinfo_toc(f, 0, 1, section_number-1); toc_waiting = 0; } } if (_valid_texinfo_node(line->text, &next, &prev)) { /* Outputs a @hnode. */ if (xrefs > 0) { fputs("See also:@*\n", f); for (i=0; itext, next, prev, _node_name(section_number-1)); fprintf(f, "%s %s\n", in_chapter ? "@subsection" : "@section", line->text); } fputs("@ftable @asis\n", f); in_item = 1; } else if (line->flags & TOC_FLAG) { _output_texinfo_toc(f, 1, 0, 0); } else if (line->flags & INDEX_FLAG) { _output_texinfo_toc(f, 0, 1, 0); } else if (line->flags & XREF_FLAG) { xref[xrefs++] = line->text; } else if (line->flags & START_TITLE_FLAG) { /* remember where the title starts */ title_line = line; if (!title_pass) fputs("@titlepage\n", f); } else if (line->flags & END_TITLE_FLAG) { if (!title_pass) { title_pass++; fputs("@end titlepage\n@ifinfo\n", f); line = title_line; } else fputs("@end ifinfo\n", f); } continue_def = (line->flags & CONTINUE_FLAG); line = line->next; } fclose(f); _destroy_multi_identifier_nodes_table(multi_identifier_nodes); destroy_types_lookup_table(auto_types, found_auto_types); return 0; } /* _write_textinfo_xref: * Writes the cross references found in the line pointed by xref. * The line will be split with strtok to find individual references. * Before a reference is written, it's compared against the table of * chapter nodes. If it's there, a special more complete xref command is * written, since nodes are internally a single word, but to the user they * look like normal complete sentences. If the word is not there, it's * compared this time agains the secondary_nodes table. If the reference * is in this pair table (see _build_multi_identifier_nodes_table), a * special xref will be written to access the primary node correctly. */ static void _write_textinfo_xref(FILE *f, char *xref, char **chapter_nodes, char **secondary_nodes) { char *tok; assert(f); assert(xref); assert(chapter_nodes); tok = strtok(xref, ",;"); while (tok) { char **p = chapter_nodes; while ((*tok) && (myisspace(*tok))) tok++; while(*p) { if(!strincmp(tok, strip_html(*p))) break; p++; } if(*p) fprintf(f, "@xref{%s, %s}.@*\n", _first_word(tok), strip_html(*p)); else { p = secondary_nodes; while (*p) { if (!strcmp(tok, *p)) break; p += 2; } if (*p) fprintf(f, "@xref{%s, %s}.@*\n", *(p + 1), tok); else fprintf(f, "@xref{%s}.@*\n", tok); } tok = strtok(NULL, ",;"); } } /* _valid_texinfo_node: */ static int _valid_texinfo_node(char *s, char **next, char **prev) { TOC *toc = tochead; *next = *prev = ""; while (toc) { if ((!toc->root) && (toc->texinfoable)) { if (strcmp(toc->text, s) == 0) { do { toc = toc->next; } while ((toc) && ((!toc->texinfoable) || (toc->root))); if (toc) *next = toc->text; return 1; } *prev = toc->text; } toc = toc->next; } return 0; } /* _output_texinfo_toc: */ static void _output_texinfo_toc(FILE *f, int root, int body, int part) { TOC *toc; int section_number; char **ptr; char *s; int i, j; int in_chapter = 0; fprintf(f, "@menu\n"); if (root == 1 && body == 0) { toc = tochead; if (toc) toc = toc->next; while (toc) { if (toc->root == 2 || toc->root == 3) in_chapter = 0; if ((toc->root) && (toc->texinfoable) && !in_chapter) { s = _first_word(toc->text); fprintf(f, "* %s::", s); for (i=strlen(s); i<24; i++) fputc(' ', f); fprintf(f, "%s\n", toc->text); } if (toc->root == 2) in_chapter = 1; toc = toc->next; } } if (body) { toc = tochead; if (toc) toc = toc->next; if (part <= 0) { ptr = m_xmalloc(TOC_SIZE * sizeof(char *)); i = 0; while (toc) { if ((!toc->root) && (toc->texinfoable) && (i < TOC_SIZE)) ptr[i++] = toc->text; toc = toc->next; } if (i > 1) qsort(ptr, i, sizeof(char *), scmp); for (j=0; jroot) && (!toc->otherfile) && (toc->texinfoable)) section_number++; toc = toc->next; } if (root) { while (toc) { if (toc->texinfoable && toc->root) { s = _first_word(toc->text); fprintf(f, "* %s::", s); for (i=strlen(s); i<24; i++) fputc(' ', f); fprintf(f, "%s\n", toc->text); } toc = toc->next; if (toc->root == 2 || toc->root == 3) break; } } else { while ((toc) && (!toc->root)) { if (toc->texinfoable) fprintf(f, "* %s::\n", toc->text); toc = toc->next; } } } } fprintf(f, "@end menu\n"); } /* _node_name: */ static char *_node_name(int i) { TOC *toc = tochead; if (toc) toc = toc->next; while (toc) { if ((toc->root) && (toc->texinfoable)) { i--; if (!i) return _first_word(toc->text); } toc = toc->next; } return ""; } /* _first_word: */ static char *_first_word(char *s) { static char buf[256]; int i; if (multiwordheaders) return strncpy(buf, s, 255); for (i=0; s[i] && s[i] != ' '; i++) buf[i] = s[i]; buf[i] = 0; return buf; } /* _html_to_texinfo: */ static void _html_to_texinfo(FILE *f, char *p) { char buf[256]; int i = 0; while ((*p) && (*p != '>')) buf[i++] = *(p++); buf[i] = 0; if (mystricmp(buf, "pre") == 0) { fputs("@example\n", f); _no_strip = 1; _strip_indent = -1; } else if (mystricmp(buf, "/pre") == 0) { fputs("@end example\n", f); _no_strip = 0; _strip_indent = -1; } else if (mystricmp(buf, "br") == 0) { fputs("@*", f); } else if (mystricmp(buf, "hr") == 0) { fputs("----------------------------------------------------------------------", f); } else if (mystricmp(buf, "p") == 0) { fputs("\n", f); } else if (mystricmp(buf, "ul") == 0) { fputs("\n@itemize @bullet\n", f); } else if (mystricmp(buf, "/ul") == 0) { fputs("@end itemize\n", f); } else if (mystricmp(buf, "li") == 0) { fputs("@item ", f); } } /* build_types_lookup_table: * Automatic function which will scan the document from the beginning in * search of structures/types, which will be returned in a NULL terminated * array. Optionally, if found_table is not NULL, it will contain a simple * array with that many entries like the returned table. This array will * later be used to mark which autotypes were found (useful for texinfo). */ char **build_types_lookup_table(char **found_table) { LINE *line = head; int i = 0; char **table; table = m_xmalloc(sizeof(char*)); table[0] = 0; /* Scan document in memory finding definition lines with upper case types */ while (line) { if ((line->flags & STRUCT_FLAG)) { char *p = strchr(line->text, '\"'); /* Find start of ... part after name */ table[++i] = 0; } line = line->next; } if (found_table) *found_table = memset(m_xmalloc(i + 1), 0, i + 1); return table; } /* _build_multi_identifier_nodes_table: * Automatic function which will scan the document from the beginning in * search of nodes which feature multiple identifiers. Since only the first * identifier of the texinfo node is indexed, all the others have to be * noted down. In the case of referencing them, a special xref has to be * written, which points to the secondary identifier through the first one. * Last lines of _write_texinfo_xref show how this is done. This function * returns a table with pairs of strings in the form (secondary, primary), * where secondary is the secondary identifier name, and primary is the * texinfo indexed identifier. The table has to be freed some time later * along with it's data. It's null terminated. */ static char **_build_multi_identifier_nodes_table(void) { LINE *line = head; int i = 0; char **table; table = m_xmalloc(sizeof(char*)*2); table[0] = 0; table[1] = 0; /* Scan document in memory finding definition lines creating multi * identifier nodes */ while (line) { if ((line->flags & DEFINITION_FLAG)) { char *first_identifier = get_clean_ref_token(line->text); line = line->next; while (line->flags & DEFINITION_FLAG) { if (strstr(line->text, "text); table[i++] = m_strdup(first_identifier); table[i] = table[i+1] = 0; } line = line->next; } free(first_identifier); } line = line->next; } return table; } /* _destroy_multi_identifier_nodes_table: * Given a null terminated table, frees it's string data and later the * table itself. */ static void _destroy_multi_identifier_nodes_table(char **table) { int f; assert(table); for (f = 0; table[f]; f++) free(table[f]); free(table); } /* destroy_types_lookup_table: * Get's rid of the previously created auto_types and found_table. * found_auto_types can be NULL. */ void destroy_types_lookup_table(char **auto_types, char *found_auto_types) { char **p = auto_types; assert(auto_types); if(found_auto_types) free(found_auto_types); while(*p) { free(*p); p++; } free(auto_types); } /* strstruct: * Complex function which replicates the logic behind the strstr function: * It will search in line, any of existant auto_types. If no auto_type is * found, it returns NULL. Otherwise will return a pointer to the beginning * of the auto_type in line, and the length of the auto_type will be stored * at the variable pointed by length. found_auto_types can be NULL, or a * table with as many entries as auto_types. In the latter case, the found * auto_type entry will be marked with a positive number. */ char *strstruct(char *line, char **auto_types, int *length, char *found_auto_types) { assert(line); assert(auto_types); assert(length); while(*line) { if(_is_auto_type_starting_letter(*line)) { char *end = line; char **compare = auto_types; int found = 0; /* Find the end of the presumably found auto_type */ while(_is_auto_type_allowed_letter(*end)) end++; *length = end - line; /* Now compare with the auto_types table */ while(*compare) { if(*length == (signed)strlen(*compare) && !strncmp(line, *compare, *length)) { /* The auto_type must be followed by a blank space */ if(*(line + *length) == ' ') { if(found_auto_types) found_auto_types[found] = 1; return line; /* Found, return it's position. */ } } compare++; found++; } line = end; } else line++; } return 0; } /* _write_auto_types_xrefs: * After normal references have been written, call this with a table of * auto_types, and a table of found_auto_types till the moment. xrefs will * be generated, and all the entries of the found_auto_types will be * zeroed for the next run. */ static void _write_auto_types_xrefs(FILE *f, char **auto_types, char *found_auto_types) { while(*auto_types) { if(*found_auto_types) { *found_auto_types = 0; fprintf(f, "@xref{%s}.@*\n", *auto_types); } auto_types++; found_auto_types++; } } /* _is_auto_type_starting_letter: * Detects if the letter could be the beginning of an auto_type. Note the * ugly hack used for Allegro's fixed and al_ffblk types, which should be * capitalized. */ static int _is_auto_type_starting_letter(char c) { if (c == 'f' || c == 'a' || (c >= 'A' && c <= 'Z')) return 1; return 0; } /* _is_auto_type_starting_letter: * Detects if the letter could be part of an auto_type. Note the ugly hack * used for Allegro's fixed and al_ffblk types, which should be capitalized. */ static int _is_auto_type_allowed_letter(char c) { if (_is_auto_type_starting_letter(c)) return 1; if (c >= '0' && c <= '9') return 1; if (c == '_' || c == 'i' || c == 'x' || c == 'e' || c == 'd' || c == 'l' || c == 'b' || c == 'k') return 1; return 0; } allegro4.4-4.4.2/docs/src/makedoc/maketexi.h000066400000000000000000000005061173507505700205110ustar00rootroot00000000000000#ifndef MAKETEXI_H #define MAKETEXI_H extern int multiwordheaders; int write_texinfo(char *filename); char **build_types_lookup_table(char **found_table); void destroy_types_lookup_table(char **auto_types, char *found_auto_types); char *strstruct(char *line, char **auto_types, int *length, char *found_auto_types); #endif allegro4.4-4.4.2/docs/src/makedoc/maketxt.c000066400000000000000000000051461173507505700203570ustar00rootroot00000000000000/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Makedoc's txt output routines. * * By Shawn Hargreaves. * * See readme.txt for copyright information. * * See allegro/docs/src/makedoc/format.txt for a brief description of * the source of _tx files. */ #include #include #include "maketxt.h" #include "makedoc.h" #include "makemisc.h" /* write_txt: */ int write_txt(char *filename, int partial) { LINE *line = head; char *p; int c, len; FILE *f; int outputting = !partial; /*printf("writing %s\n", filename);*/ f = fopen(filename, "w"); if (!f) return 1; while (line) { if (line->flags & (STARTOUTPUT_FLAG | ENDOUTPUT_FLAG)) { if (mystricmp(line->text, get_filename(filename)) == 0) { if (line->flags & STARTOUTPUT_FLAG) outputting = 1; else outputting = 0; } } else if (line->flags & NODE_FLAG) { p = line->text; len = strlen(p); fputs(p, f); fputs("\n", f); for (c=0; cflags & TEXT_FLAG) && (outputting)) { p = line->text; if (line->flags & HEADING_FLAG) { /* output a section heading */ p = strip_html(p); len = strlen(p); for (c=0; c', f); p += 3; } /* strip other HTML tokens */ else if (p[0] == '<') { while ((*p) && (*p != '>')) p++; if (*p) p++; } /* output other characters */ else { fputc(*p, f); p++; } } fputs("\n", f); } } line = line->next; } fclose(f); return 0; } allegro4.4-4.4.2/docs/src/makedoc/maketxt.h000066400000000000000000000001311173507505700203510ustar00rootroot00000000000000#ifndef MAKETXT_H #define MAKETXT_H int write_txt(char *filename, int partial); #endif allegro4.4-4.4.2/docs/src/mistakes._tx000066400000000000000000000067111173507505700174660ustar00rootroot00000000000000@# @# This is the source for the Allegro common mistakes, in a weird custom @# format. Read makedoc.c for a description of what is going on... @# @external-css=allegro.css @document_title=Common mistakes

    Common mistakes


    @!text @heading Contents @shortcontents @text @@ Ignoring this manual. Most problems are addressed in this manual. If you aren't sure about some parts of Allegro check particular section of manual. The FAQ section can also be very useful. @@ main() not returning int. On platforms that need it, Allegro uses END_OF_MAIN to mangle your main() function and supply its own that is required by the platform. Allegro assumes that main() returns an integer, as required by various C standards. If you change the return type of your main() to something else Allegro's main() will get confused and return some nonsense value which some system can recognize as an error and crash your program. @@ Semicolon at END_OF_MAIN. int main(void) { allegro_init(); /* more stuff goes here */ ... return 0; } END_OF_MAIN(); /* wrong */ The semicolon is not only unnecessary after END_OF_MAIN(), but it can also cause some compilers to issue a warning. @@ Getting bitmap's size. Many people don't know how to get the dimensions of a bitmap. This can be done by accessing the `w' and `h' fields of the BITMAP structure: BITMAP *image; ... allegro_message("Bitmap size: %d x %d\n", image->w, image->h); @@ Creating bitmaps before loading. BITMAP *image = create_bitmap(width, height); image = load_bitmap("image.bmp", pal); When loading a bitmap, Allegro will automatically create a bitmap big enough to store it. In the above code the address returned by create_bitmap() is overwritten by the second assignment statement, to the return value of the call to load_bitmap(). Since the address of the first (unnecessary) bitmap has been lost, there is no way to destroy it so there is a memory leak. @@ Loading a bitmap/font/sound inside a global object constructor. Almost all Allegro functions require Allegro to be initialized first, before they can be used. Since global object constructors are called before main() (from where allegro_init() would be called) this condition is violated. You need to postpone calls to Allegro functions to after initializing Allegro. @@ Calling set_color_depth without resetting graphic mode. set_color_depth() tells Allegro which color depth to use the next time a graphic mode is set or bitmap is created or loaded. It doesn't change the color depth of the current graphic mode or existing bitmaps. You need to be sure that all your bitmaps and/or graphic mode are in the same color depth or Allegro will be forced to do slow color conversions between them. @@ Destroying global objects like `screen'. Unlike other bitmaps `screen' is created by calling set_gfx_mode() and must not be destroyed by calling destroy_bitmap(). The proper way to destroy `screen' is calling set_gfx_mode(GFX_TEXT, 0, 0, 0, 0). allegro4.4-4.4.2/docs/src/packfile._tx000066400000000000000000000063351173507505700174260ustar00rootroot00000000000000@external-css=allegro.css @document_title=Packfile format

    Packfile format information.


    @!text @heading Contents @shortcontents @text @heading Introduction and scope This document describes the format of Allegro's packfiles from a decompression point of view. It does not describe how to do the compression (read the source, or ask Google about LZSS). file.c says "This compression algorithm is based on the ideas of Lempel and Ziv, with the modifications suggested by Storer and Szymanski.", if that means anything to you. @heading Packfile signature All compressed packfiles begin with a four byte signature "slh!" (ASCII), which in hexadecimal is 0x73, 0x6C, 0x68, 0x21 (in that order). Another form of packfiles are uncompressed packfiles, which begin with the four byte signature "slh." (ASCII), in hexadecimal 0x73, 0x6C, 0x68, 0x2B. The rest of the file is then completely raw. Uncompressed packfiles will not be discussed further. @heading Format and decompression algorithm Decompression requires a ring buffer of 4096 bytes and a ring index (which indexes into the ring buffer). The ring index starts at 4078, assuming 0-based indices. New bytes may be stored into in the position in the ring buffer that the index points to. When a byte is stored, the index is incremented by one, wrapping around to zero as necessary. Packfiles must be decompressed sequentially. The first byte following the signature in the packfile is the "flags" byte, which determines how the following "tokens" in the file are to be interpreted. Bit 1 (the least significant bit) corresponds to the first token following the flags byte. Bit 2 corresponds to the second token, etc. After every eight tokens, there is another flag byte and another eight tokens, and so on, until the end of file. If the bit I of the flags byte is set, then token I is a single byte to be sent to the output. In addition, it must put onto the ring buffer and the ring index incremented. Otherwise, if bit I of the flags byte is not set, then token I is a two byte sequence containing an index and a length. The index is the first byte OR'd together with the higher 4 bits of the second byte as the higher order bits, thus making a 12-bit unsigned number (0-4095). The length is the lower 4 bits of the second byte, plus 3. In less hand-wavy C syntax: index = byte1 | ((byte2 & 0xF0) << 4); length = (byte2 & 0x0F) + 3; Then, "length" number of bytes from the ring buffer, starting at "index", are to be sent to the output. In addition, all these bytes must be put onto the ring buffer, and the ring buffer incremented accordingly. Decompression ends at the end of the file. There is no end-of-file marker. If the number of tokens is not a multiple of eight, the unused bits in the latest flags byte are always zero. @heading Summary In brief, compressed packfiles take the form: signature -- 4 bytes flags -- 1 byte token 1 -- each token 1 or 2 bytes token 2 ... token 8 flags ... (repeat flags and tokens 1-8 until EOF) allegro4.4-4.4.2/docs/src/readme._tx000066400000000000000000000443011173507505700171000ustar00rootroot00000000000000@# @# This is the source for the Allegro thanks list, in a weird custom format. @# Read makedoc.c for a description of what is going on... @# @html_text_substitution=docs/txt/allegro.txt|
    docs/txt/allegro.txt @html_text_substitution= allegro.txt| allegro.txt @html_text_substitution=docs/txt/api.txt|docs/txt/api.txt @html_text_substitution=AUTHORS|AUTHORS @html_text_substitution=docs/build/bcc32.txt|docs/build/bcc32.txt @html_text_substitution=docs/build/beos.txt|docs/build/beos.txt @html_text_substitution=docs/build/darwin.txt|docs/build/darwin.txt @html_text_substitution=docs/build/djgpp.txt|docs/build/djgpp.txt @html_text_substitution=docs/build/linux.txt|docs/build/linux.txt @html_text_substitution=docs/build/macosx.txt|docs/build/macosx.txt @html_text_substitution=docs/build/mingw32.txt|docs/build/mingw32.txt @html_text_substitution=docs/build/msvc.txt|docs/build/msvc.txt @html_text_substitution=docs/build/qnx.txt|docs/build/qnx.txt @html_text_substitution=docs/build/unix.txt|docs/build/unix.txt @html_text_substitution=docs/build/watcom.txt|docs/build/watcom.txt @html_text_substitution=docs/txt/help.txt|docs/txt/help.txt @html_text_substitution=docs/txt/ahack.txt|docs/txt/ahack.txt @html_text_substitution=docs/txt/addons.txt|docs/txt/addons.txt @external-css=allegro.css @document_title=A general introduction to Allegro @
         ______   ___    ___
        /\  _  \ /\_ \  /\_ \
        \ \ \L\ \\//\ \ \//\ \      __     __   _ __   ___ 
         \ \  __ \ \ \ \  \ \ \   /'__`\ /'_ `\/\`'__\/ __`\
          \ \ \/\ \ \_\ \_ \_\ \_/\  __//\ \L\ \ \ \//\ \L\ \
           \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
    	\/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
    				       /\____/
    				       \_/__/     Version 4.4.2
    
    
    		A game programming library.
    
    	     By Shawn Hargreaves, May 19, 2011.
    
    		See the AUTHORS file for a
    	       complete list of contributors.
    @
    #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."
    @heading Introduction Allegro is a cross-platform library intended for use in computer games and other types of multimedia programming. It was initially conceived on the Atari ST, but that platform sadly died during childbirth. After a brief stay with Borland C, it was adopted by the fantastic djgpp compiler, where it grew to maturity. In the fullness of time it gave birth to children of its own, who went to live in such exotic locations as DirectX and the X Server, but the entire family is now back together again, living in harmony as a single portable entity. How about that for a mixture of metaphors? :-) A wide range of extension packages and add-on modules are also available, which can be found in the "Library Extensions" section of the Allegro.cc website, http://www.allegro.cc/. According to the Oxford Companion to Music, Allegro is the Italian for "quick, lively, bright". It is also a recursive acronym which stands for "Allegro Low Level Game Routines". @heading Installation and supported platforms For generic instructions on how to build and install Allegro, see docs/build/cmake.txt. For more information on specific platforms, see one of these files: Windows/MSVC - see docs/build/msvc.txt Windows/MinGW - see docs/build/mingw32.txt Windows/Cygwin - see docs/build/mingw32.txt Unix (X11) - see docs/build/unix.txt MacOS X - see docs/build/macosx.txt Linux (console) - see docs/build/linux.txt Other platforms were supported in the past, but may no longer work without effort from interest parties. Sorry. General API information can be found in the main manual, usually referred to as docs/txt/allegro.txt, allegro.txt or simply "The Allegro manual" throughout this document. The Allegro manual source is available as a set of files in the docs/src directory. During the build process of the library, these source files will be converted to HTML, TexInfo, and RTF formats (among others) and placed in their respective doc/FORMAT directory. Information about changes in the API and deprecated features can be found in docs/txt/api.txt (also available in HTML, TexInfo, and RTF format as part of the Allegro manual). @heading Included Addons
    • AllegroGL
    • loadpng
    • logg
    • jpgalleg
    See docs/txt/addons.txt. @heading Features
    • Cross-platform support for Windows, Unix, and MacOS X systems. (Formerly also DOS, BeOS and QNX - it may be possible to resurrect those platforms, with your help!)
    • Drawing functions including putpixel, getpixel, lines, rectangles, flat shaded, gouraud shaded, texture mapped, and z-buffered polygons, circles, floodfill, bezier splines, patterned fills, masked, run length encoded, and compiled sprites, blitting, bitmap scaling and rotation, translucency/lighting, and text output with proportional fonts. Supports clipping, and can draw directly to the screen or to memory bitmaps of any size.
    • Windows graphics drivers using DirectX in fullscreen and windowed modes, plus routines for drawing onto GDI device contexts.
    • Unix graphics drivers for X, DGA2, fbcon, SVGAlib, and standard VGA.
    • MacOS X native graphics drivers using CGDirectDisplay API for direct fullscreen gfx access and QuickDraw in a Cocoa window in windowed mode.
    • FLI/FLC animation player.
    • Plays background MIDI music and up to 64 simultaneous sound effects, and can record sample waveforms and MIDI input. Samples can be looped (forwards, backwards, or bidirectionally), and the volume, pan, pitch, etc, can be adjusted while they are playing. The MIDI player responds to note on, note off, main volume, pan, pitch bend, and program change messages, using the General MIDI patch set and drum mappings. DOS version currently supports Adlib, SB, SB Pro, SB16, AWE32, MPU-401, ESS AudioDrive, Ensoniq Soundscape, and Windows Sound System. Windows version supports WaveOut and DirectSound interfaces and the system MIDI drivers. Unix version supports OSS, ESD, and ALSA sound drivers. BeOS version supports BSoundPlayer and BMidiSynth interfaces. MacOS X native version supports CoreAudio, Carbon Sound Manager and QuickTime Note Allocator interfaces. All versions provide software wavetable MIDI playback.
    • Easy access to the mouse, keyboard, joystick, and high resolution timer interrupts, including a vertical retrace interrupt simulator in the DOS version.
    • Routines for reading and writing LZSS compressed files.
    • Multi-object data files and a grabber utility.
    • Math functions including fixed point arithmetic, lookup table trig, and 3d vector/matrix/quaternion manipulation.
    • GUI dialog manager and file selector.
    • Built-in support for 16-bit and UTF-8 format Unicode characters.
    Formerly also:
    • DOS graphics drivers for VGA mode 13h, mode-X (twenty three tweaked VGA resolutions plus unchained 640x400 Xtended mode), and SVGA modes with 8, 15, 16, 24, and 32 bit color depths, taking full advantage of VBE 2.0 linear framebuffers and the VBE/AF hardware accelerator API if they are available. Additional video hardware support is available from the FreeBE/AF project (http://www.talula.demon.co.uk/freebe/).
    • BeOS graphics drivers using BWindowScreen in fullscreen and BDirectWindow in windowed modes.
    • Hardware scrolling and triple buffering (where available), mode-X split screens, and palette manipulation.
    @heading Copyright Allegro is gift-ware. It was created by a number of people working in cooperation, and is given to you freely as a gift. You may use, modify, redistribute, and generally hack it about in any way you like, and you do not have to give us anything in return. However, if you like this product you are encouraged to thank us by making a return gift to the Allegro community. This could be by writing an add-on package, providing a useful bug report, making an improvement to the library, or perhaps just releasing the sources of your program so that other people can learn from them. If you redistribute parts of this code or make a game using it, it would be nice if you mentioned Allegro somewhere in the credits, but you are not required to do this. We trust you not to abuse our generosity. Disclaimer: THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @heading Configuration Allegro reads information about your hardware from a file called allegro.cfg. If this file doesn't exist it will autodetect (ie. guess :-) You can write your config file by hand with a text editor, or you can use the setup utility program (located in the setup directory). Normally the setup program and allegro.cfg will go in the same directory as the Allegro program they are controlling. This is fine for the end user, but it can be a pain for a programmer using Allegro because you may have several programs in different directories and want to use a single allegro.cfg for all of them. If this is the case you can set the environment variable ALLEGRO to the directory containing your allegro.cfg, and Allegro will look there if there is no allegro.cfg in the current directory. The mapping tables used to store different keyboard layouts are stored in a file called keyboard.dat. This must either be located in the same directory as your Allegro program, or in the directory pointed to by the ALLEGRO environment variable. If you want to support different international keyboard layouts, you must distribute a copy of keyboard.dat along with your program. Various translations of things like the system error messages are stored in a file called language.dat. This must either be located in the same directory as your Allegro program, or in the directory pointed to by the ALLEGRO environment variable. If you want to support non-English versions of these strings, you must distribute a copy of language.dat along with your program. Under Unix, BeOS and MacOS X, the config file routines also check for ~/allegro.cfg, ~/.allegrorc, /etc/allegro.cfg, and /etc/allegrorc, in that order, and the keyboard and language files can be stored in your home directory or in /etc/. If under MacOS X, the application bundle Contents/Resources directory, if any, is also scanned first. See docs/txt/allegro.txt for details of the config file format. @heading Notes about sound The DIGMID wavetable driver uses standard GUS format .pat files, and you will need a collection of such instruments before you can use it. This can either be in the standard GUS format (a set of .pat files and a default.cfg index), or a patches.dat file as produced by the pat2dat utility. You can also use pat2dat to convert AWE32 SoundFont banks into the patches.dat format, and if you list some MIDI files on the command line it will filter the sample set to only include the instruments that are actually used by those tunes, so it can be useful for getting rid of unused instruments when you are preparing to distribute a game. See the Allegro website for some links to suitable sample sets. The DIGMID driver normally only loads the patches needed for each song when the tune is first played. This reduces the memory usage, but can result in a longish delay the first time you play each MIDI file. If you prefer to load the entire patch set in one go, call the load_midi_patches() function. The CPU sample mixing code can support between 1 and 64 voices, going up in powers of two (ie. either 1, 2, 4, 8, 16, 32, or 64 channels). By default it provides 8 digital voices, or 8 digital plus 24 MIDI voices (a total of 32) if the DIGMID driver is in use. But the more voices, the lower the output volume and quality, so you may wish to change this by calling the reserve_voices() function or setting the digi_voices and midi_voices parameters in allegro.cfg. @heading Contact info The latest version of Allegro can always be found on the Allegro homepage, http://alleg.sourceforge.net/. There are three mailing lists for Allegro-related discussion, each with a slightly different purpose.
    • [AL] - Allegro main - http://lists.sourceforge.net/lists/listinfo/alleg-main/.

      This list is for any kind of discussion about Allegro, questions about Allegro, reports of problems with Allegro, suggestions for new features, announcements of programs written using Allegro, etc. General rule: if it has to do with Allegro, you can post it here. If not, go somewhere else (for example comp.os.msdos.djgpp, comp.lang.c, or the online forums at http://www.allegro.cc/).

    • [AD] - Allegro developers - http://lists.sourceforge.net/lists/listinfo/alleg-developers/.

      This list is for the people currently working on Allegro, who use it to coordinate their efforts. You can use this address if you need to contact the developers directly, for example to submit some new code that you have written or to report a bug.

      Unlike the other lists, we will be really rude to people who post inappropriate material here, so please don't do that! Do not send tech-support questions to this list. Don't post bug reports here unless you are 100% certain they aren't your fault (if you are in any doubt, use the main Allegro list instead, which is read by most of the same people who are subscribed here).

      The Allegro development is a completely open process, and everyone is welcome to drop by, have a listen, and start contributing code patches. This list is for working rather than talking, though, so please don't do anything that might get in our way.

    • [Alleg5] - Allegro 5 - http://lists.sourceforge.net/mailman/listinfo/alleg-bigfive.

      This list was once available for discussing the next major version of Allegro, when it was too noisy to do so on [AD]. This is no longer the case so the list has been shut down. However, its archives are still valuable.

    To subscribe to one of the three lists, simply go to it's web page and use the online forms to subscribe yourself. You can remove yourself from a list going to the same page above, which can be used to remind you of your password too, in case you have forgotten it. To send a message to one of the lists, write to alleg-main@lists.sourceforge.net or alleg-developers@lists.sourceforge.net. You don't need to be subscribed to these mailing lists before you can post there, but it is a good idea to subscribe in order to see the replies. Before posting tech-support questions to the Allegro list, please take a moment to read the guidelines in docs/txt/help.txt. See docs/txt/ahack.txt for information about the style of code we use, and how to create your patches. If you want to search through the archives of any of those mailing lists, you will have to check the available options at http://alleg.sourceforge.net/maillist.html. Please don't send messages in HTML format. The increased size places an unnecessary load on the server, and many subscribers have a hard time reading these posts. Please do not crosspost between these lists. Choose the most appropriate one for your message, and then send it only to that list. Please don't send large binary attachments to any of the lists, they will be rejected by the size limit filter, which is set to 100KB for the developers mailing list, and 40KB for the others. Upload your files to a website and then post the URL, or if you can't do that, post an announcement asking people to write to you privately, and then send the file by individual email to whoever responded. Please use English in your messages. You could eventually post messages in whatever language you prefer, but that would terribly limit the chances of getting a useful answer. Remember that the RFC 1855: netiquette guidelines (http://www.rfc-editor.org/rfc/rfc1855.txt) describes other general guidelines you should follow as a correct internet user (in mailing lists and other places as well), and provides more verbose descriptions and explanations about why you should follow the above guidelines. One of the important guidelines you should be aware of is how to quote correctly the message you are replying to. The previous RFC doesn't really explain how to do it, so you might want to read the document "How do I quote correctly in Usenet?" at http://www.netmeister.org/news/learn2quote.html. Quoting correctly is easier to say than to do, especially for users of Microsoft Outlook. If you are such a user, you can help yourself using the Outlook-QuoteFix extension written by Dominik Jain, which you can find at http://home.in.tum.de/~jain/software/outlook-quotefix/. allegro4.4-4.4.2/docs/src/thanks._tx000066400000000000000000001556531173507505700171500ustar00rootroot00000000000000@# @# This is the source for the Allegro thanks list, in a weird custom format. @# Read makedoc.c for a description of what is going on... @# @mangle_emails=at dot @external-css=allegro.css @document_title=Allegro Contributors @

    The Hall of Fame


    @startoutput AUTHORS We hope to have remembered everyone who ought to be mentioned here. If your name should be included, accept our apologies, and please tell us so we can correct the oversight! @heading Contributors Acho A. Tang (acho@telus.net).
    Added a Sidewinder Precision Pro joystick driver to the DOS port. Adrian Oboroc (doba@corefx.com).
    Wrote the LBM loader. aj.
    Reported many problems, suggested a lot of improvements to the documentation, added AMD64/IA64/SSE3 detection code, added DirectX 8 and 9 detection to the Windows port, added MSVC7 specific options to the makefile, cleaned up a C99-ism in makedoc, fixed a beep when alt+character was pressed in windowed mode in Windows and made TARGET_ARCH_EXCL also work with MSVC. Alex Demko (alex_demko@mbnet.mb.ca).
    Suggested lots of improvements to the datafile system and provided code for handling the 8x16 BIOS font format. Alessandro Monopoli (almonopo@tin.it).
    Added the Italian translation of the system messages. Andreas Kluge (bitland@aol.com).
    Wrote the Ensoniq Soundscape driver and fixed division bugs in the fix class. Andrei Ellman (ae-a-alleg2@wacko.wackonet.net).
    Contributed the polygon_z_normal() function, suggested some additions to the docs, updated the Cygwin section in docs/build/mingw32.txt, got Allegro for MSVC to build with Cygwin, improved the performance of the hsv_to_rgb() function, corrected a rounding issue in hsv_to_rgb(), improved the exrgbhsv example and the Windows screensaver, fixed problems in the MSVC makefile when using Cygwin and did plenty of other things too. Andrew Cottrell (andrewc@dbworld.net.au).
    Changed the grabber to use a more robust (locale-independent) date format. Andrew Ellem (krand@ican.net).
    Wrote the original version of the digital audio streaming code. Andrew Geers (andy@geerswj.clara.net).
    Added the -ppassword and -nosound options to the grabber, scrolling support in the image viewer and the flipped rotated sprite routines. Andy Goth (unununium@openverse.com).
    Made the gfx_card config variable more flexible, added the 256x256 tweaked VGA mode, wrote the d_text_list_proc() dialog object and fixed the constructor support in dat2s on Unix. Angelo Mottola (a.mottola@libero.it).
    Added the BeOS joystick, MIDI and windowed graphics drivers, added mouse wheel, display switching and close button support for BeOS, wrote the DGA2 driver and close button support for X, contributed the bfixicon utility, added triple buffering support, a BWindow-based windowed driver and a fullscreen overlay driver to the BeOS port and reorganized its gfx subsystem. And, oh, contributed the QNX and MacOS X ports too. Annie Testes (annie@kezako.net).
    Added font_height, render_char, char_length hooks to FONT_VTABLE, fixed several glitches in the unicode support, added a pack_fdopen() function, caught a misordering in the X system shutdown, fixed some device name strings, lifted several hardcoded length limitations in the configuration routines, added a mouse driver based on the event interface (EVDEV) to the Linux port, fixed numerous bugs and did plenty of other things too. Anthony 'Timorg' Cassidy.
    Made d_menu_proc fill up its assigned area with the gui_bg_color, updated required cygwin package list. Antoine Mathys (mmathys@bluewin.ch).
    Added the Swiss keyboard mapping. Anton Ragnarsson (anton.ragnarsson@swipnet.se).
    Contributed the Swedish keyboard mapping table. Antti Haapala (ztane@lyseo.edu.ouka.fi).
    Fixed the setup program to display the right frequency list for each type of soundcard and contributed the Finnish translation of the system messages. Antti Koskipaa (antti.koskipaa@nic.fi).
    Wrote the DOS driver for WSS (Windows Sound System) cards. Arne Steinarson (arst@ludd.luth.se).
    The fixed point square root routine came from his fix-float library. Arthur Huillet (email unknown).
    Fixed a typo in the docs. Attila Szilagyi (attilabox@hotmail.com).
    Fixed SVGAlib horizontal scrolling. Ben Chauveau (bendomc@worldnet.fr).
    Added support for Tseng ET6000 cards (now available as part of the FreeBE/AF project). Ben Darnell (bdarnell@vnet.net).
    Put together the 2.11 release of Allegro while I was away from the net and wrote the original version of the Allegro FAQ. Ben Davis (entheh@users.sf.net).
    Added set_volume_per_voice(), made silent voices continue playing, fixed other minor bugs in the mixer, fixed a bug in create_rgb_table(), adapted polygon functions to handle two coincident vertices, added the set_window_close_button() and set_window_close_hook() framework, added support for timers with parameters under Windows, corrected several compilation warnings and documented the behaviour of pack_feof(). Benjamin Joel Stover (stovertech@intellisys.net).
    Wrote the initial version of the fullscreen X-Windows graphics driver. Benny Colyn (email unknown).
    Added a Dutch translation. Bertrand Coconnier (bcoconni@club-internet.fr).
    Modified 3D polygones routines for subpixel and subtexel accuracy, made speed enhancements in these routines, fixed blending in C version of atex_lit scanline functions, added scanline subdivisions in C scanline functions and Z-buffer polygon functions and merged in Calin Andrian's P3D library. 8L45T3R (o8l45t3ro@users.sf.net).
    Fixed a bug in arc() where small arcs would be drawn as circles. Bobby Ferris (baf@bafsoft.com).
    Added the SciTE API output format to makedoc and temporarily hosted Allegro's SVN repository while SourceForge's SVN was in beta. Burton Radons (loth@gec.net).
    Optimised the truecolor pixel blending function, converted the blenders to the new single-handler format, and added the range of Photoshop-compatible blender functions. Calin Andrian (calin@ibd.dbio.ro).
    Wrote the truecolor, MMX, 3DNow!, masked lit mode, translucent and Z-buffered polygon rendering routines, the clip3d_f() function and also the scanline sorting functions for 3D scene rendering, and his P3D addon library was merged in. Calvin French (frenchc@home.com).
    Added the -w (always update) switch to dat.exe. Carsten Schmidt (email unknown).
    Wrote the the initial version of the Linux GGI driver. Carsten Sorensen (csorensen@ea.com).
    Wrote the the ESS AudioDrive soundcard driver. Catatonic Porpoise ().
    Added OpenBSD detection, fixed an issue with executable rights not set on the memory for the i386 stretcher on UNIX systems, and fixed the documentation for stretch_sprite. Cloud Wu (cloudwu@263.net).
    Optimised the truecolor pixel blending functions. Charles Bilyue (Esaelon@aol.com).
    Optimized the i386 blitters and suggested to not force yielding timeslice with non-blocking menus. Charles Wardlaw (kattkieru@yahoo.com).
    Fixed warnings with gcc 4 on MacOS X and helped resolve a problem with setAppleMenu under Tiger. Chris Graham (chris_graham@postmark.net).
    Suggested to add a new flag for Windows NTFS compressed files. Chris Jones (cj@jibblers.plus.com).
    Fixed a bug with 16-bit samples loading, worked around a problem with DOS file attributes under Win2k, let the MIDI player pass controller events to the raw player by default, made the MIDI player handle the 'All Sound Off' controller message, added support for the bitfield compressed BMP image format, fixed the behavior of numeric keys when NumLock is on, and fixed loading of certain .wav files. Chris La Mantia (celamantia@home.com).
    Wrote the d_radio_proc(), d_icon_proc(), and d_slider_proc() dialog objects, added the D_DISABLED flag, improved the GUI handling of different font heights, and added the right aligned text functions. Chris Roberts.
    Updated CMake build for BeOS/Haiku. Chris Robinson (crobin_99@yahoo.com).
    Wrote the fixed point clip3d() function, improved the performance of the DIGMID driver, implemented the digmid_set_pan function, rewrote part of the Allegro mixer, made the Allegro mixer the default one in Windows, improved the threaded UNIX timer code, helped improve responsiveness under X11, tweaked tests/play.c, added drawing primitives and video bitmap locking to the X11 port and did plenty of other things too. Christer Sandberg (christer.sandberg@mdh.se).
    Made dat2c work better with ISO C90 compilers, made dat2c correctly detect the native line ending, fixed a problem with the include guard generated by dat2c, fixed a bug in the 24-bit graphics code of fixup_datafile(), fixed a memory leak with datedit_exit, fixed a problem with Electric Fence. Christian Schueler (cschueler@gmx.de).
    Changed the optimisation settings for better performance. Daniel Nilsson (daniel7@algonet.se).
    Enlarged the starfield in exstars, and fixed an incorrect range in exlights. Daniel Schlyder (daniel@bitblaze.com).
    Fixed problems with get_executable_name() under Windows, another one with set_window_title() under BeOS, potentially unsafe constructs in the Windows code, the installall makefile target under Windows, added set_allegro_resource_path(), fixed make uninstall with mingw make, added ALLEGRO_LIB_BUILD flag for gcc variants not using configure, fixed a bunch of warnings in MinGW and did plenty of other things too. Daniel Verkamp (i_am_drv@users.sourceforge.net).
    Added a MIDI input driver to the Windows port and added support for .rmi MIDI files to the MIDI loader. Dark Nation (email unknown).
    Restored support for old-style encrypted packfiles, which had been removed in 4.1.18. David A. Capello (dacap@users.sourceforge.net).
    Made dotted_rect() avoid bank switches, fixed a problem with lost GUI mouse clicks, made d_menu_proc() steal/return focus when activated then deactivated, fixed a problem with submenus, fixed a bug with FLI frames containing odd-sized chunks, made makedoc write sub-section headings for .txt output, made override_config_file also be used for writing to the config file and did plenty of other things too. David Kuhling (dkuelhin@hell1og.be.schule.de).
    Optimised the fsqrt() routine, and added fhypot(). Dave Physics.
    Some documentation fixes. Dave Thomson (gameskitchen@geocities.com).
    Added the RGB <-> HSV conversion routines, the autocrop function to the grabber and wrote the 3d starfield example program (exstars.exe). David Calvin (calvid@rpi.edu).
    Wrote the original version of the sound setup utility. David Cullen (dcullen7@bellsouth.net).
    Added multiple bullets and extra lives to the demo game. Deepak T (coolbool@gmx.net).
    Fixed clipping in three C sprite drawing routines. Dennis Busch (email unknown).
    Fixed a bug in d_clear_proc, fixed a Unicode bug in the mode selector, and fixed the short description of add_clip_rect. Dmitriy Kazimirow (mariann@mail.ru).
    Provided the Russian keyboard mapping and message translation files. Dominique Biesmans (Dominique.Biesmans@ping.be).
    Wrote the mode-X version of draw_sprite() and the mode-X <-> linear blitting functions. Doug Eleveld (D.J.Eleveld@anest.azg.nl).
    Wrote the d_textbox_proc() dialog object and the new grabber help system. Dustin Dettmer (dustin@mize.org).
    Spotted a typo in save_bitmap. Edgar Reynaldo.
    Helped fixing several problems with gfx_mode_select_filter(), pointed out two warnings, fixed two warnings in a loadpng example, provided mouse_on_screen(), get_gfx_mode_type() and get_gfx_mode() functions. Eduard Bloch (edi@gmx.de).
    Fixed a freeze caused by the ESD detection code, fixed a bad behaviour of the config routines and suggested better ways to find the path to the executable on Unix. Edward Boone (Lucien.Boone@ping.be).
    Provided scancode mapping tables for the AZERTY keyboard layout. Elias Pschernig (elias@users.sf.net).
    Added a COLORCONV_KEEP_TRANS mode, contributed the wfixicon utility, contributed several enhancements to the grabber, fixed menu dimensions in the GUI engine, fixed the get_camera_matrix*() functions, added support for the CHM and Devhelp documentation formats, fixed a bug in midi_seek(), made load_datafile_object() load the object properties, made the GUI code scare the mouse more intelligently and did plenty of other things too. Eric Botcazou (ebotcazou@libertysurf.fr).
    Made the DGA driver work better in 8bpp and 32bpp modes, improved the DirectX windowed driver and Windows graphics subsystem, partially revamped the Unicode API and added uszprintf(), added file_select_ex(), the unified al_find*() interface, an Unicode example, a new filetest, rewrote the fixdll script, revamped the Borland C++ build process, fixed lots of bugs and did plenty of other things too. Erik Sandberg (eriksandberg@geocities.com).
    Optimised the 8 bit draw_sprite() and draw_trans_sprite() functions and helped with the Swedish message translation. Erno Schwetter.
    Fixed some bugs in the Linux console port and fixed a long-standing bug in the polygon() routine. Etienne Vouga.
    Fixed a bug with the reset_controllers MIDI command. Ettore Perazzoli (ettore@comm2000.it).
    Optimised the linear -> mode-X blitting function. Evert Glebbeek (eglebbk@dds.nl).
    Put set_gfx_mode on a diet, added a config entry for specifying the card to be used for GFX_AUTODETECT_WINDOWED, added a '-fullscreen' switch to the grabber, cleaned up the grabber/plugins code, added various commands to the grabber, added the detection of SunOS/Solaris, added configure options for x86 processor optimisations on Unix systems, added the support for relative filenames and did plenty of other things too. EvilTypeGuy (eviltypeguy@icculus.org).
    Cleaned up and fixed the RPM spec file for RedHat 9. Fabian Nunez (faybs@iafrica.com).
    Added support for the CH Flightstick Pro and Logitech Wingman Extreme joysticks, 3-button mice, and the extended keys on a Microsoft keyboard. Fabrizio Gennari (faybs@iafrica.com).
    Contributed the DB9 and TurboGraFXoystick drivers. Francis Devereux.
    Helped out with build issues on Mac OS X. Francisco Pires (fmlvp@hotmail.com).
    Added an FPS counter and an option to disable vsync to the excamera example. Francois Charton (deef@pobox.oleane.com).
    Wrote the Paradise graphics driver (now available as part of the FreeBE/AF project), improved the VGA palette setting code and helped with the TexInfo conversion of the docs. Frodo Baggins (l41273@alfa.ist.utl.pt).
    Made the Portuguese keyboard mapping. Garret Thomson (g@sirsonic.com).
    Wrote the music used in the demo game. George Foot (gfoot@users.sourceforge.net).
    Did a great deal of work on the Linux console version, wrote the AWE32 driver, added the MIDI pause/seek functions, provided the basis of the SoundFont reader used in the pat2dat utility, fixed the C fceil() function, added the ffloor() function and added non-FM support to the OSS MIDI driver. Gorka Olaizola (olsago@jet.es).
    Added the Redhat RPM .spec file. Grady Martin (shadygrady@budweiser.com).
    Fixed a bug in the handling of %n in the printf style text functions, added a move command to the grabber and standardised some of the grabber dialog boxes. Greg Hackmann (hacker@ididitmyway.com).
    Contributed the Borland C++ Builder port. Greg Lee (greg@ling.lll.hawaii.edu).
    Pointed out that Linux joystick driver should read all events. Grzegorz Adam Hankiewicz (gradha@users.sourceforge.net).
    Wrote several of the example programs, suggested the "compress" makefile target, translated the docs and system error messages into Spanish, suggested the idea of embedding the setup utility into other programs, wrote some documentation and corrected the .texi generation to improve texi2dvi output, improved the makedoc utility and contributed a new doc format, added reload_config_texts() and did plenty of other things too. Grzegorz Godlewski (email unknown).
    Contributed a Polish localization patch, and added support for lower and upper altgr tables. Grzegorz Ludorowski (pajonk@ajax.umcs.lublin.pl).
    Wrote several of the example programs, and made the intro animation and graphics for the demo game. Guilherme Silveira (thedarkage@geocities.com).
    Modified the file selector to only list valid drive letters. Gunter Ladwig (gladwig@iname.com).
    Wrote the OS/2 detection routines and added the three-button mouse emulation. Hans de Goede. Fixed a problem with dynamically generated stretcher code not being properly marked as executable on Linux, fixed a busy wait in the X11 vsync simulation, added a fullscreen driver for X11 which does not need XVidMode extension, fixed a problem where switching to fullscreen mode under X11, made digmid work with absolute pathes in patches.cfg, and fixed a problem with the Alsa driver on big endian systems. Harshavardhana Reddy N (nharsha@gmail.com).
    Added a Kannada greeting to exunicod. Haruhiko Okumura (email unknown).
    Wrote the original version of the LZSS compression code. 12-2-404 Green Heights, 580 Nagasawa, Yokosuka 239, JP. Hein Zelle (hein@icce.rug.nl).
    Revamped the cross-compilation section of docs/build/mingw32.txt, clarified a requirement when cross-compiling from Linux, reworked the paragraph on the location of shared libraries under Unix in the docs and added a FAQ entry on the same subject. Henrik Schmidt (hbs@ks.informatik.uni-kiel.de).
    Found a workaround for the switching problem under Windows, made gcc pass '-h' instead of '-soname' to the linker and replaced '-L' by '-h' in shell comparisons so as not to break on Solaris. Henrik Stokseth (hensto@online.no).
    Contributed a native Mingw32 port which can also be built with a cross-compiler and the Cygwin compiler, much improved OS detection, added get_gfx_mode_list() and methods for querying the VGA, Mode-X, Xtended, VESA, VBE/AF and DirectX drivers for a list of possible GFX modes, rewrote the mode-selector to use get_gfx_mode_list(), reworked the build system many times and did plenty of other things too. Hrvoje Ban (spoofer255@gmail.com).
    Pointed out a bug in the mode selector, fixed several double ;'s, fixed ASSERT() in Windows, helped write a documentation section about common pitfalls, and added the create_datafile_index function. Igor Gnip (gnipi@mindnever.org).
    Removed the requirements for fileutils on DOS/Windows platforms and added the detection of MSYS to the MingW32 port. Isaac Cruz (icruzbal@teleline.es).
    Fixed a bug with accelerated drawing onto sub bitmaps of DirectDraw surfaces, added the GFX_DIRECTX_WIN driver, fixed a Windows sub bitmap locking bug, added Windows desktop_color_depth and yield_timeslice routines, and made extensive modifications to other aspects of the Windows code. Ivan Baldo (lubaldo@adinet.com.uy).
    Wrote the 15/16 bit dithering code and optimised the sprite rotation routines. Jaime Moreno (daviangel@hotmail.com).
    Helped track down a problem with dependency generation in MacOS X. Jakub Wasilewski (krajzega@meditech.pl).
    Fixed a bug when loading greyscale TGA images and contributed to the skater demo. James Arthur (jaa@arfa.clara.net).
    Documented the Photoshop-style truecolor blender routines. James Hyman (frooge@mindless.com).
    Added support for quoted strings in the get_config_argv() function and the dithering code for paletted images. James Lohr (email unknown).
    Fixed a problem with mouse acceleration in fullscreen modes under Windows. James Ponder (james@squish.net).
    Suggested to remove the DJGPP makefile from the Unix tar archive and clarified a requirement when cross-compiling from Linux. Jan Bruun Andersen (jba-dk@users.sourceforge.net).
    Fixed a compilation problem with Cygwin. Jan Hubicka (hubicka@horac.ta.jcu.cz).
    Vastly improved the speed of the create_rgb_table() function. Jason Wilkins (fenix@io.com).
    Wrote the quaternion math routines and contributed the BeOS port. Javier Gonzalez (xaviergonz@hotmail.com).
    Corrected mouse movement speed, made allegro_message() use title from set_window_title(), added close button hook support and improved switching in Windows, fixed bad clearing of subbitmaps, made bug reports and suggestions for improvement, contributed bidirectional looping support, backward playing support and bugfixes for the DirectSound driver and did plenty of other things too. Jeff Mitchell (email unknown).
    Fixed the location of grabber.txt in the spec file. Jeremiah Blanchard (squirminworm@yahoo.com).
    Contributed modifications in order for Allegro to build on Darwin/MacOS X and updated the build instructions for this new port afterwards. Jim Flynn (jflynn@pacbell.net).
    Removed floating point calculations from the AWE32 MIDI driver. Jim Grainger (Grainger_Jim/world_europe_samuro_WYN-CTV@samsung.co.kr).
    Spotted a broken link in the docs and updated it. Jiri Gabriel (email unknown).
    fixed loading of multiple ranges in a single bitmap with txt fonts and helped fix an off-by-one mistake for the last glyph in extract_font_range. Joaquin Hierro Diaz (Joaquin.Hierro.Diaz@fresno.csic.es).
    Made the mapping table for Spanish keyboards. Joerg Rueppel (sharky-x@gmx.net).
    Added more flexible wildcard matching for object names in dat.exe and the find_datafile_object() function. Johan Peitz (d98peitz@dtek.chalmers.se).
    Fixed and enhanced the Win32 joystick driver, and contributed the 'Alex the Allegator' icon. Johan Venter (leonjventer@bigpond.com).
    Fixed some problems with the RSXNT and Mingw32 makefiles. John Holden (johnh@psych.usyd.edu.au).
    Fixed a bug in load_wav(). John Utz (Johnut01@noa.nintendo.com).
    Corrected a wrong assumption about the VRAM layout in the Linux framebuffer console driver. Jon Rafkind (workmin@ccs.neu.edu).
    Added more ASSERTs to the code, implemented the Cohen-Sutherland clipping algorithm for the line() function and supplied an m4 macro for allegro. Also fixed a problem with allegro-config. Implemented draw_sprite_ex() function. Jonas Petersen (joXonoX@berlin.snafu.de).
    Added the save_bmp() function and support for the OS/2 BMP format. Jonathan Tarbox (jonattar@rocketmail.com).
    Wrote the mode-X setup code, the FLI/FLC player and contributed parts of the joystick handler. Jorrit Rouwe (j.rouwe@cpedu.rug.nl).
    Provided a new and much cooler set of FM instrument definitions for the Adlib MIDI driver. Jose Antonio Luque (skylord@LatinMail.com).
    Improved the Windows joystick driver, and optimised the 16-bit blit() and masked_blit() functions. Joshua Heyer (joshua_heyer@yahoo.com).
    Wrote the original version of the OSS sound driver. J. P. Morris (email unknown).
    Fixed a bug rest_callback under unix. Julien Cugnière (jcugniere@free.fr).
    Improved the support for non-blocking menus, fixed a bug related to the retrieval of the inital volume when no primary buffer was present under Windows, fixed the crash on exit with the aRts sound driver, added an X11 message box for allegro_message under X11 and fixed a crash in the GUI when a dialog was opened while a menu was still open. Kalle Toivonen (allegro@korpiq.iki.fi).
    Fixed a bug in _parallelogram_map(). Keith Gerdes (kwg@softhome.net).
    Fixed the DirectDraw overlay mode driver. Kerry High (khigh01@umr.edu).
    Contributed the SNES joypad driver. Kester Maddock (dmaddock@xtra.co.nz).
    Wrote the Wingman Warrior joystick driver. Knut Pape (Knut_Pape@t-online.de).
    Improved the Mingw32 readme file. Kronoman X (kronoman_x@hotmail.com).
    Added a FAQ entry about the conflict between Allegro headers and the C++ 'using' directive. Krzysztof Krzyzaniak (eloy@arrakis.cs.put.poznan.pl).
    Wrote the load_voc() function. Laurence Withers (lwithers@users.sf.net).
    Added destroy hook to font structure, worked on const-correctness throughout the library, implemented the new FONT structure, made some modules avoid linking dependencies, contributed the dat2c utility, added two fixed point ratios for converting to and from radians, added a '-windowed' switch to the grabber, added a new text API and did plenty of other things too. Lee Killough (email unknown).
    Added the low-level hook routine to the keyboard handler and fixed a couple of bugs. Lennart Rolland (chimeni@hotmail.com).
    Contributed the Norwegian message translation. Lennart Steinke (lst@steinke.net).
    Added the exconfig example, contributed keyboard layout detection code for Windows and suggested the true colour font rendering. Lisa Parratt (lisa@thecommune.org.uk).
    Contributed the SGI Audio Library sound driver, spotted a BSDism that IRIX doesn't like at all, added IRIX detection and improved the performances of the SGI audio driver Lorenzo Petrone (looris@gmail.com).
    Contributed the gfxinfo utility, added two FAQ entries, added a xwin_set_window_name() function to the X11 port, added support for switch callbacks under X11 and refactored the display switching code. Lucas Vignoli Reis (lucasvr@bestway.com.br).
    Added the Portuguese (Brazil) message translation and keyboard mapping. Magnus Henoch (mange@freemail.hu).
    Made the gfx mode selector keep the current selection as much as possible and fixed a problem when compiling without 8bpp support. Maiolino Carmelo (cmaiolino@ctonline.it).
    Added the Italian keyboard mapping table. Manni Heumann (manfred.heumann@uni-bielefeld.de).
    Fixed some problems with the German keyboard mapping table. Marcel de Kogel (m.dekogel@student.utwente.nl).
    Not content with fixing my broken MPU-401 driver, Marcel went on to provide a set of vastly improved drum sounds for the OPL driver, to help me sort out some problems with reentrant interrupts, to supply the half of the joystick code that didn't come from Jonathan and to locate a stupid mistake in my VESA linear framebuffer code. Marcel Smit (marcel.athlon@hccnet.nl).
    Corrected a bug that caused errors when drawing persp. correct polygons facing the screen, corrected an error in the packfile format write-up and made the show_video_bitmap() method of the Windows windowed driver wait for a vsync. Márcio Fialho (maaf1980@yahoo.com.br).
    Fixed several issues with the DJGPP port and the VBE/AF driver and fixed some bugs related to author credits. Marco Campinoti (marco@etruscan.li.it).
    Added 15 and 24 bit support to the native Tseng ET4000 driver (now available as part of the FreeBE/AF project). Marco Marmulla (Viper005@usa.net).
    Added 16 bit support to the load_voc() routine. Marian Dvorsky (marian@step.sk).
    Wrote the Windows GDI interface routines. Marius Fodor (iceman@teleport.com).
    Added support for the Sidewinder and Gravis GamePad Pro. Marek Habersack (grendel@ananke.amu.edu.pl).
    Did the original Linux console port (brave man: this was the first ever work done on porting Allegro away from DOS), which is the basis of the code we are still using today and added support for the more recent Trident chipsets (now available as part of the FreeBE/AF project). Mark Keller.
    Reported two minor mistakes in the manual. Mark Wodrich (mwodric@eleceng.uct.ac.za).
    The brain behind sub-bitmaps, flicker-free mouse pointers, and the ability to import GRX .FNT files into the grabber. Markus F.X.J. Oberhumer (markus.oberhumer@jk.uni-linz.ac.at).
    Fixed the Video-7 scrolling function (now available as part of the FreeBE/AF project), optimised the color mapping routines, and made many useful suggestions like the addition of a vid_phys_base field to the graphics driver structure. Martijn Van Lersel (amarillion@yahoo.com).
    Fixed an overflow in create_light_table(). Martijn Versteegh (m.versteegh@hccnet.nl).
    Added the config hook extension mechanism. Mathieu Lafon (mlafon@ifhamy.insa-lyon.fr).
    Added the French keyboard mapping, support for the Pause/PrtScr keys and changed the key[] table to a normal/extended bitfield. Matt Witherspoon (spoon@vt.edu).
    Fixed a bug in the scroll() method of the Linux SVGAlib driver. Matthew Bowie (catcat@nmt.edu).
    Added support for 4-button joysticks. Matthew Leverton (matthew@allegro.cc).
    Fixed a bug with mouse mickeys in windowed mode under Windows, fixed a problem with al_find*() and NTFS partitions under Windows, added missing header files to be installed by the Windows binary distribution, made the DOS/Windows makefiles use 'copy /B' instead of 'copy', added the detection of left-hand mouse configuration under Windows, fixed a bug with pack_fgets(), made an online diff generator and did lots of other things too. Matthew Smith.
    Fix a bug in C locking code in GDI. Maxime Carey (werfu@users.sourceforge.net).
    Contributed the Canada (French) keyboard mapping file. Michael Bevin (michael.bevin@stonebow.otago.ac.nz).
    Optimised the create_trans_table() function. Michael Bukin (M.A.Bukin@inp.nsk.su).
    Ported the whole thing to Unix/X, and contributed a _lot_ of patches to improve the portability, robustness, and performance of pretty much the entire library. Michael Faerber.
    Pointed out a mistake in the documentation for text_height(). Michael Jensen.
    Fixed a mistake in the documentation for is_compatible_font. Michael Rickmann (mrickma@gwdg.de).
    Ported the Windows code to Mingw32. Michael Tanczos (webmaster@logic-gate.com).
    Fixed some bugs in the FLIC player. Michal Mertl (mime@eunet.cz).
    Wrote all the 24 bit graphics code, the optimised palette generation function and a fair amount of the other truecolor stuff too (bitmap scaling, image loading, etc). Michal Molhanec (molhanec@seznam.cz).
    Simplified the build instructions for Dev-C++, replaced all occurences of MingW32 by MinGW in the docs, added an faq section about the giftware license, fixed problems with long filenames when building for MSVC, corrected a problem with the Watcom port, added MSVC7 options to the makefile, fixed a linker problem with the MSVC port, fixed some const warnings in the grabber code and did plenty of other things too. Michail Pishchagin (mblsha@users.sourceforge.net).
    Contributed the ustrnicmp() function. Milan Mimica (milan.mimica1@pu.htnet.hr).
    Fixed bugs in the keyconf utility, the alsa 9 volume settings and extract_font_range(), helped fix an off-by-one mistake for the last glyph in extract_font_range, fixed a bug where a font would be converted to 8 bit, a bug with is_color_font, made the Linux console driver more robust, fixed some spin loops in the test program, and added the get_volume and get_hardware_volume functions, and did plenty of other things too. Miran Amon (miran.amon@gmail.com).
    Fixed an undocumented arbitrary limit in get_config_argv() and contributed to the skater demo. Nathan Albury, aka Rubicant (gt4558a@prism.gatech.edu).
    Improved the fire routine in examples/exflame.c (my original version didn't really look very much like flames :-) and gave me some extremely useful ideas about how to implement translucency. Nathan Smith (white_door@dread.nl).
    Implemented the recursive handling of directories for the dat utility. Neil Townsend (neil@robots.ox.ac.uk).
    Improved the accuracy of the timer routines and added the callback parameters. Neil Roy (neilroy@cogeco.ca).
    Suggested many improvements to the documentation. Neil Walker.
    Implemented a hardware accelerated stretch_blit() for the Windows DX port, and fixed a bug with draw_sprite and sub-bitmaps. Nicholas Davies (master_goodbytes@hotmail.com).
    Made the fix class not trigger warnings with gcc -Weffc++ and contributed to the skater demo. Nick Kochakian (nickk@worldnet.att.net).
    Wrote the DirectSound input driver. Ole Laursen (98zOLaw@aalborghus.dk).
    Contributed the Danish keyboard mapping table and system message translation, and made the Unicode utolower() and utoupper() functions understand the entire 16 bit character set. Olivier Blin (oblin@mandriva.com).
    Fixed compilation problems for the ModeX driver. Olly Betts (olly@muscat.co.uk).
    Modified the djgpp makefile to support cross-compiling on a Linux machine. Omar Cornut (cornut@noos.fr).
    Spotted an asm locking bug under Windows, bumped the maximum number of buttons per joystick to 32, fixed the Windows joystick driver to handle a weird peculiarity of the DirectInput API and improved the handling of KEY_COLON2 on Japanese keyboards. Oscar Giner (O_giner@hotmail.com).
    Added the Catalan translation, corrected the Spanish translation, fixed a bug with binary data exporting in the grabber and fixed a conflict between the magic main and the MFC. Owen Embury (owen@gememail.demon.co.uk).
    Wrote part of the translucency/lighting code. Owen Rudge (alleg@orudge.freeuk.com).
    Contributed a DLL version resource script and the mkdata.bat script. Ove Kaaven (ovek@arcticnet.no).
    Fixed a bug in the ATI mach64 driver (now available as part of the FreeBE/AF project), added native truecolor and linear framebuffer support to the ATI driver, contributed the Norwegian keyboard mapping, and added MIDI and sample input features to the MPU and SB drivers respectively. Paavo Ahola (email unknown).
    Helped fix a problem with BCC and the C implementations of fixmul. Patrick Hogan (patter@iname.com).
    Wrote the draw_gouraud_sprite() function, and made Windows audiostreams work properly. Paul Bartrum (bartrum@xtra.co.nz).
    Contributed the ellipse drawing functions. Paul Eipper.
    Reported a bug where libdir from autotools was not used for the modules path. Paul Furber (paul@sprintlink.co.za).
    Provided the floating point apply_matrix_f() function. Paul Hampson (Paul.Hampson@Pobox.Com).
    Improved and fixed some problems in the SNES gamepad driver. Paul Pinault (diskaleg@infonie.fr).
    Translated the system error messages into French. Pavlos Touboulidis (gtoub@otenet.gr).
    Made file_select() able to include or exclude files based on their attributes. Pedro Cardoso (pcardoso@viriato.ipv.pt).
    Contributed the tweaked 80x80 VGA mode. Peter Cech (7cech@nw.fmph.uniba.sk).
    Added grabber support for the 8x8 BIOS font format, support for hot-swapping between a custom keyboard layout and the standard US mapping, optimised the alpha sprite blending routines and added non-ASCII space recognition to uisspace(). Peter De Wachter.
    Made the ALSA driver work for hardware which does not support unsigned samples. Peter Hull (peterhull90@users.sourceforge.net).
    Made the file selector work with directories that have more than 2048 files, solved some compiling issues on MacOS X, fixed a bug in rest() that caused it to wait too long on that platform, fixed several problems with the hardware mouse cursor, fixed a deadlock in the software mouse updating code, fixed compilation problems under MacOS X tiger, added a MacOS X helpfile and did plenty of other things too. Peter Johansson (email unknown).
    Reported a problem with system cursors not working in Windows. Peter Monks (pmonks@iname.com).
    Wrote the Video-7 graphics driver (now available as part of the FreeBE/AF project) and showed me how to set up the unchained 640x400 mode. Peter Palotas (blizzar@hem1.passagen.se).
    Added the keyboard callback routine. Peter Pavlovic (Peter.Pavlovic@st.fmph.uniba.sk).
    Added the Slovak keyboard mapping and message translation, stopped the DOS file selector from listing virtual drives, did the same for the Windows file selector, improved the support for accented character maps in the keyboard driver and made aesthetic modifications to the GUI menu system. Peter Puck (zaqhaq@netscape.net).
    Helped with the Mingw32 native build. Peter Wang (tjaden@users.sourceforge.net).
    Added the mouse_z wheel input support to the Linux code, fixed problems with the ESD sound driver, wrote the ALSA sound driver, wrote the BeOS sound driver, added OSS MIDI and sample input support, added banked mode support to the SVGAlib driver, wrote the X DGA mode switching code, improved the Linux joystick driver, X11 fullscreen, DGA2 and DGA driver, added pthread timers under Linux/Unix and did loads of other things too. Phil Frisbie, Jr. (pfrisbie@geocities.com).
    Wrote the CPU type detection code. Phil Krylov.
    Fixed a bug in load_bios_font(). Phil Shenk (email unknown).
    Improved the MSVC build instructions. Philipp Thomas (pthomas@suse.de).
    Fixed all comparisons between signed and unsigned types, fixed compilation on x86-64, fixed all function prototypes, converted the configure machinery to autoconf 2.53 or later and added multi-arch support, DESTDIR support and the German translation to the RPM spec file. Przemek Podsiadly (ppodsiad@elka.pw.edu.pl).
    Added hicolor versions of the 3d polygon code. Revin Guillen (revin@phylo.com).
    Added the position_dialog() function. Richard Davies (richard@debaser.force9.co.uk).
    Added support for PSX and N64 joypads. Richard Mitton (100740.1271@compuserve.com).
    Added support for 6-button joysticks, and wrote the 12-bit color example program (ex12bit.c). Richard Reeve (r.e.reeve@stir.ac.uk).
    Fixed a silly mistake with gcc 3.0.x detection. Rikard Peterson.
    Fixed a small problem with the Mac OS X joystick driver. Robert J. Ragno (rjr@mit.edu).
    Wrote the Gravis GrIP driver, made some improvements to the Wingman, PSX and throttle input code. Robert J. Ohannessian (voidstar@ifrance.com).
    Added MMX optimisation for the 8 and 16-bit clear() functions, fixed bad clearing of subbitmaps, added SSE detection and optimised some masked blits with SSE instructions, added some routines to the unified color convertor and made some of them more robust, fixed the docs for pivot_scaled_sprite_v_flip(), revamped the retrieval mechanism of CPU capabilities, separated the CSS file and did plenty of other things too. Robert Riebisch.
    Fixed some warnings from gcc 4.x on VESA and VBE/AF drivers. Roberto Alfonso (rpgrca@labint.frba.utn.edu.ar).
    Fixed a couple of memory problems in the dat2c utility, added an srand() call in the demo game, made the MSVC port call `link /lib' rather than `lib', fixed several warnings with GCC 4 under DJGPP and fixed a grabber crash when importing a font range in an existing font. Robin Burrows (rburrows@bigfoot.com).
    Provided a new page flipping code for the DirectDraw subsytem, added a Windows sound driver using the Allegro mixer and another using waveOut, fixed two glitches in the DirectDraw code. Romano Signorelli (romanos@bigfoot.com).
    Added an arc plotting routine. Ron Novy
    Made several improvements to the test program. Ronaldo Hideki Yamada (r.yamada@uol.com.br).
    Contributed the MacOS 9 port of Allegro. Ryan Patterson.
    Made various documentation fixes and fixed a crash in free_config_entries. S.Sakamaki (emt@geocities.co.jp).
    Added the VESA 3.0 refresh rate control code. S.Suzuki (s-suz@sunfield.ne.jp).
    Wrote the IF-SEGA /PCI, /PCI2, and /ISA joystick interface drivers. Salvador Eduardo Tropea (salvador@inti.edu.ar).
    Improved the keyboard routines (better handling of extended scancodes, keyboard LED support, capslock and numlock, and alt+numpad input), contributed the 320x100 VGA graphics mode, added support for proper 16 bit sample mixing, fixed compilation on gcc 3.x and made numerous other useful suggestions, contributions and bugfixes. Sam Hocevar (sam@zoy.org).
    Fixed a Bashism in fix.sh that makes Solaris' sh choke, a race condition in the mixer under Unix w/ threads, Windows, BeOS and MacOS X, a crash in makedoc, made it possible to put functions from .s sources in a shared library under Unix and removed deprecated use of several functions. Santeri Saarimaa (gridle@mbnet.fi).
    Made the Finnish keyboard mapping. Sask Allegro (sask_allegro@iespana.es).
    Added support for more than two joysticks in the Windows port. Scott Harrison (scotth@calderauk.com).
    Added the OpenDOS detection code. Sean Gugler (sean@epal.com).
    Added the set_leds() function. Seunghwan Ji (email unknown).
    Made makedoc output correct html and rtf files for Korean. Serge Semashko (serge@lxnt.info).
    Fixed a bug with the letter P in the Russian keyboard configuration file, added Enter as a fire key to the demo game, fixed some problems with Allegro working on Nokia 770, and fixed a crash in _linear_draw_trans_rgba_rle_sprite24. Seymour Shlien (seymour@dgbt.doc.ca).
    Contributed the Windows BMP file reader, bezier spline drawer, and justified text plotting function. Shawn Hargreaves (shawn@talula.demon.co.uk).
    Progenitor. Wrote everything that wasn't written by somebody else. Shawn Walker (binarycrusader@gmail.com).
    Several fixes to the .spec file, made get_executable_name use getexecname() under Solaris, fixed a bug in the keyboard driver that caused crashes on the same system, worked around errors with some versions of GNU AS and fixed errors in the configure script when not using GCC StApostol (stapostol@gmail.com).
    Fixed a bug in the exflame example and updated the FAQ to use rest(0) instead of yield_timeslice(). Stefan Eilert (seilert@rz.Uni-Osnabrueck.DE).
    Added support for a second joystick. Stefan Schimanski (1Stein@gmx.de).
    Wrote the original Windows version pretty much single-handedly. Stefan T. Boettner (virtual.man@t-online.de).
    Wrote the Linux SVGAlib driver. Stepan Roh (src@srnet.cz).
    Added a Czech keyboard mapping and system message translation, the Latin Extended-A characters in the default font, the codepage support in the textconv utility, fixed some problems with the ESD sound driver, helped make Allegro build better on some Unix platforms, fixed const related problems in C versions of routines and added support for a automake-style DESTDIR variable in the Unix makefile. Stephan Brauss (sbrauss@optronic.ch).
    Made a few fixes to let the Linux port compile again on Linux 2.2.x, corrected a few nits in the Swiss keyboard configuration file and added new keysyms to the X11-to-BIOS conversion table in order to catch missing keycodes for the keypad when NumLock is on. Stephen Kittelson (stickman2000@juno.com).
    Made bugfixes and tweaks to the keyboard system. Stijn Wolters.
    Clarified the documentation of init_dialog. Sveinung Kvilhaugsvik(email unknown).
    Pointed out that Allegro should respect DESTDIR under MacOS X. Sven Sandberg (svens@it.uu.se).
    Fixed a problem with save_bitmap() rounding the image widths, optimised the create_light_table() function, optimised the fixed point trigonometric routines, provided the Swedish message translations, improved the file selector sorting algorithm, optimised the spline routines, added ustrrchr(), improved the usprintf() handling of floats, changed the Z-buffer API, and did plenty of other things too. TBD/FeR (tbd@usa.net).
    Added the 320x600 and 360x600 resolutions to the mode-X driver. Teijo Hakala (teijo.hakala@imnetti.fi).
    Added wheel support to the Windows mouse driver. Tero Parvinen (Tero.Parvinen@hut.fi).
    Designed most of the new sound API. Theuzifan Sumachingun (uzi@simauria.upv.es).
    Improved the cpu detection for Cyrix chips and made the file selector only list valid drive letters. Thomas Fjellstrom (tfjellstrom@home.com).
    Wrote the ALSA 0.5.x MIDI driver and added support for ALSA 0.9.x. Thomas Harte (email unknown).
    Helped fix a bug in show_video_bitmap() on MacOS X, helped optimise fixmul(), helped find many bugs in the MacOS X port, like better support for user-supplied Nibs, implemented a hardware accelerated stretch_blit under DirectX, fixed a bug with draw_sprite and sub-bitmaps and contributed to the skater demo. Thomas Klausner (wiz@danbala.ifoer.tuwien.ac.at).
    Added NetBSD detection and fixed a problem with the allegro.m4 macro and automake 1.8+. Thomas Wolf (two@chello.at).
    Corrected some errors in the German keyboard mapping and added the German translation of the system messages. Tim Bird (tbird@caldera.com).
    Worked on the Linux console port. Tim Gunn (timgunn@eastwind.com.au).
    Wrote the TGA reading/writing routines. Timothy Terriberry (sundance@sprintmail.com).
    Fixed several bugs in the RGB <-> HSV conversion routines. Tobi Vollebregt (email unknown).
    Spotted a bug in ustrerror(), which was not returning a pointer to a static buffer, reported a problem with shutdown_dialog() when a menu was open, helped port the Windows keyboard driver to Windows 98 and fixed a bug with hardware cursor detection in X11. Tobias Dammers.
    Fixed a problem with the DirectSound input driver. Tom Breton (tob@world.std.com).
    Added the functionality selection #ifndefs to allegro.h. Tom Novelli (tnovelli@cyber3.servtech.com).
    Wrote the original version of the digital MIDI driver. Tom St Denis (tomstdenis@yahoo.com).
    Fixed clipping of transparent objects. Tomohiko Sugiura (tmsugi@d4.dion.ne.jp).
    Added the KEY_ABNT_C1, KEY_YEN, KEY_KANA, KEY_CONVERT, KEY_NOCONVERT and other keys to the input handler, organised getting the IF-SEGA joystick drivers by S.Suzuki merged into my codebase and added a more aggressive Sidewinder joystick driver. Tore Halse (gnolam@gmail.com).
    Made Allegro windows always popup centred in Windows and made fixes to the documentation. torhu.
    Fixed an out-of-bounds error in akaitest. Trent Gamblin.
    Implemented set_mouse_speed under X11, fixed the C version of stretch_blit and made the fullscreen DirectX driver save and restore the palette on switching away. V Karthik Kumar (karthikkumar@gmail.com).
    Added a Tamil language greeting to exunicode, added switches to use the Intel compiler in Windows and added a password option to the Windows screensaver example. Also fixed a problem with allegro-config. Victor Williams Stafusa da Silva (vwss1984@yahoo.com.br).
    Changed a few occurences of "256" to PAL_SIZE and made OS type detection handle Windows 2003 and Windows Vista. Ville Skyttä (scop@users.sourceforge.net).
    Fixed a problem with make install libdir= and modules on Unix systems. Vincent Penquerc'h (lyrian@kezako.net).
    Added the D_DIRTY flag and mouse button press/release events to the GUI system, optimised the 256 to truecolor blitting code to avoid repeated conversions of the palette table, added scare_mouse_area(), added the yield_timeslice() function, added the update selection function to the grabber, added the XCRP and YCRP properties to datafiles in general, implemented the big header split and did plenty of other things too. Vitaliy Chetverikov (email unknown).
    Fixed a bug in the GUI where the return value of MSG_IDLE was ignored. VolkerOth (VolkerOth@aol.com).
    Integrated the concepts of scrolling and edit_proc objects. @endoutput AUTHORS @startoutput THANKS @heading Thanks! First, a big thank you to all the people who help me test and debug this code. It sometimes gets frustrating to receive hundreds of messages saying "it doesn't work!", but they are useful all the same... Andre Baresel (baresel@informatik.hu-berlin.de), and Craig Jackson (Craig.Jackson@launchpad.unc.edu), provided a tremendous amount of information about SB hardware. Benji York (Benji@cookeville.com).
    Provided hardware information for the Gravis GamePad Pro. Charles Mac Donald (cgfm2@hooked.net).
    Showed me how to set some cool tweaked VGA and mode-X resolutions. Charles Sandmann (sandmann@clio.rice.edu), DJ Delorie (dj@delorie.com), Eli Zaretskii (eliz@is.elta.co.il), and everyone else who has contributed to djgpp. I love it. C. Schwerdtfeger (schwerdt@physics.ubc.ca), for his help (and enourmous patience!) in getting the SB Pro-I MIDI driver to work. Finn Thoegersen, Nordbanevej 3 C, DK-7800 Skive, Denmark.
    Most of my SVGA hardware information came from his VGADOC package. Eric Jorgensen (smeagol@rt66.com).
    Varmint's Audio Tools (VAT) gave me many useful ideas about how to play MIDI files. Jamie O'Connell (JamieOConnell@msn.com).
    Several of the new Adlib drum patches, and the specifications for the .IBK file format, came from his SBTimbre package. Jean-Paul Mikkers (mikmak@stack.urc.tue.nl).
    MikMod was the source of a lot of information about programming the SB, and also gave me the idea of dynamically reprogramming the PIT to get a really high resolution timer. Joel H. Hunter (jhunter@kendaco.telebyte.com).
    His SB library for djgpp is excellent, and helped me a lot. John Pollard (74723.1626@compuserve.com).
    The FM instrument definitions are based on his MID-KIT library. Kendall Bennett and all the other cool people at SciTech Software.
    These guys gave the world UniVBE, the VBE/AF API, and a lot of free information and example code. Plus they very kindly sent me a copy of the VBE/AF spec when I wanted one. Kris Heidenstrom (kheidens@actrix.gen.nz).
    His PC timing FAQ was a big help. Mark Feldman.
    It goes without saying that the PCGPE was an invaluable resource. Michael Abrash.
    You just gotta love that man... Paul Fenwick (bg914@freenet.carleton.ca).
    Various bits of the mode-X code (notably the split screen stuff) came from his XLIBDJ library. powerjaw (powerjaw@dnai.com).
    Sent me a Sidewinder gamepad so I could fix some problems with the driver for it. What a cool thing to do... Robert Grubbs (rwgrubbs@vt.edu).
    Provided hardware information for the Sidewinder joypad. Robert Schmidt (robert@stud.unit.no).
    The register values for the 400x* mode-X resolutions came from his TWEAK program. Sourceforge.net (http://sourceforge.net/).
    The Allegro community has been using their services (web, mailing lists, CVS, Subversion, etc) since 3.9.x WIP versions. Tom Grandgent (tgrand@canvaslink.com).
    Organised and hosted the original Allegro mailing lists for many years. Hurrah! Vladimir Arnost (xarnos00@dcse.fee.vutbr.cz).
    Provided hardware specs for the OPL3 chip. Frank Zappa, Mike Keneally, Pink Floyd, the Doors, Tori Amos, and all the other great musicians who provide me with things to listen to while I am programming. My parents, John and Nancy.
    I would never have made it through all those late night coding sessions without the cafetiere they gave me last Christmas :-) By Shawn Hargreaves, Allegro creator. @endoutput THANKS allegro4.4-4.4.2/docs/texi/000077500000000000000000000000001173507505700153075ustar00rootroot00000000000000allegro4.4-4.4.2/docs/texi/tmpfile.txt000066400000000000000000000001101173507505700175000ustar00rootroot00000000000000This file is needed because some unzip programs skip empty directories. allegro4.4-4.4.2/docs/txt/000077500000000000000000000000001173507505700151555ustar00rootroot00000000000000allegro4.4-4.4.2/docs/txt/abi.txt000066400000000000000000000107431173507505700164560ustar00rootroot00000000000000 ______ ___ ___ /\ _ \ /\_ \ /\_ \ \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ /\____/ \_/__/ ABI compatibility information. See readme.txt for a more general overview. ====================================== ============ Introduction ============ ====================================== We plan to maintain backward compatibility at the Application Binary Interface level for the subsequent releases of the 4.4.x series. For example, that means you will be able to use an executable compiled using version 4.4.0 with version 4.4.5 or 4.4.41 of the dynamically linked library. However, there are some guidelines you should follow. Note: ABI compatibility will only be _actively_ maintained for: Windows on x86 / x86-64 Linux on x86 / x86-64 MacOS X on PowerPC / x86 We will not be maintaining "forwards compatibility", meaning that programs compiled with a newer release of Allegro may not necessarily run on a target system which has an older release of Allegro installed. You would have to upgrade the Allegro DLL on the target system. While we will try to minimise these kinds of forced upgrades, it should give us more flexibility within the stable series. ======================================= ============ Windows notes ============ ======================================= If you don't need a modified version of Allegro then just link your program against an official stable version. Don't disable any features in the DLL. If you require a modified version of Allegro, then please either statically link, or pick a non-standard name for the Allegro DLL. For example, don't distribute a modified version of Allegro under a name such as all44.dll or alleg44.dll. For the people who use vanilla Allegro, we will provide a set of "reference" DLLs. If your binary works with those then everything is fine. If you want to distribute Allegro DLLs with your program (usually a good idea), we recommend you distribute our DLLs instead of ones you compiled yourself. ===================================== ============ Linux notes ============ ===================================== When you are ready to distribute your binary, run "ldd ". It should say something like: liballeg.so.4.4 => /usr/local/lib/liballeg.so.4.4 (0xdeadbeaf) It should NOT say: liballeg.so.4.4.0 => /usr/local/lib/liballeg.so.4.4.0 (0xdeadbeaf) If you see the latter, that would mean users with later versions of Allegro would not be able to run your binary. See also the Windows section if you need to use a modified version of Allegro. For people packaging Allegro for redistribution: you should try to ensure that a program built against a copy of Allegro with the default configuration will work with your version of the library. ======================================= ============ MacOS X notes ============ ======================================= On OSX there are two 'styles' of linking - Unix style and Mac style. For the Unix style linking, you would use `allegro-config --libs` on the link line. For versioning, follow the advice given in the Linux section above, using the command `otool -L' instead of `ldd'. For example, otool -L should give liballeg.4.4.dylib (compatibility version 4.4.0, current version 4.4.0) For the Mac style, use `allegro-config --frameworks` on the link line, or add `Allegro.framework' to your project if you are using XCode. In this case, the versioning is done inside the framework itself. Apple recommends that an application should be entirely self- contained. To achieve this in Allegro, static-link the executable and use `fixbundle' to bind all its resources together. In this way, you will not need to worry about incompatible versions of the library. This is useful if you are distributing an application. There is a known compatibility problem when using gcc 4 on MacOS X 10.4 that prevents binaries from working on older versions of MacOS X. While it is anticipated that a future update from Apple will fix this problem, you can use gcc 3 to work around it. allegro4.4-4.4.2/docs/txt/addons.txt000066400000000000000000000101611173507505700171650ustar00rootroot00000000000000 Addon libraries This document contains general information about addon libraries that are distributed with Allegro. For more detailed info on API, usage and updates, refer to the documentation and web site of the specific addon library. ========================================= ============ Building addons ============ ========================================= All available addons are built automatically if all the required dependencies are found. To disable building of the specific addon, set the appropriate CMake variables to off. You can use ccmake to browse the list of options. ========================================== ============ Available addons ============ ========================================== Since Allegro 4.4, several addon libraries are bundled in the Allegro package. These are some of the most commonly used addons because they contain some handy features that Allegro lacks. Hopefully, with these addons you will need less additional libraries for your game. One advantage of bundled addons is that their build system is integrated with Allegro's build system. Addons are automatically configured, built, installed and uninstalled with Allegro. However, you can perform these operations separately for each addon, if that will better suit your needs. Finally, if you think that some addons, in your opinion, should be included, feel free to contact Allegro developers and we will consider your proposal. AllegroGL AllegroGL is an Allegro add-on that allows you to use OpenGL alongside Allegro -- you use OpenGL for your rendering to the screen, and Allegro for miscellaneous tasks like gathering input, doing timers, getting cross-platform portability, loading data, and drawing your textures. So this library fills the same hole that things like GLUT do. AllegroGL also automatically exposes most, if not all, OpenGL extensions available to user programs. This means you no longer have to manually load them; extension management is already done for you. License: dual-licensed under GPL and zlib. More info: website: http://allegrogl.sf.net/ docs: http://allegrogl.sourceforge.net/wiki/Documentation http://wiki.allegro.cc/AllegroGL From allegro directory: addons/allegrogl/docs/html/index.html examples: From allegro directory: addon/allegrogl/examples/ loadpng PNG (Portable Network Graphics) is a cool raster image file format. libpng is the reference library for working with PNG files. loadpng is some glue that makes it easy to use libpng to load and save bitmaps from Allegro programs. loadpng depends on zlib and libpng libraries. Instructions for getting and installing these can be found on loadpng webiste. License: public domain More info: website: http://tjaden.strangesoft.net/loadpng/ docs: http://tjaden.strangesoft.net/loadpng/README.txt From allegro directory: addons/loadpng/README.txt examples: From allegro directory: addon/loadpng/examples/ logg LOGG is an Allegro add-on library for playing OGG/Vorbis audio files. It can load OGG/Vorbis files as Allegro SAMPLE's, or it can stream them from disk to save memory. It depends on libogg and libvorbis, available from vorbis.com. License: MIT License. See addons/logg/LICENSE.TXT More info: website: http://trent.gamblin.ca/logg/ examples: From allegro directory: addon/loadpng/ jpgalleg This addon library lets you load baseline and progressive encoded JPG images, and to save baseline JPGs. It is standalone (no dependencies except for Allegro), compact (compiled lib weights 40K!) fast and standard compliant (it'll load almost any JPG you'll throw at it!). Ships with sources, documentation, examples and a Grabber plugin, and supports any platform supported by Allegro. License: zlib/libpng. See addons/jpgalleg/license.txt. More info: website: http://www.ecplusplus.com/index.php?page=projects&pid=1 docs: From allegro directory: addons/jpgalleg/readme.txt examples: From allegro directory: addon/jpgalleg/examples/ allegro4.4-4.4.2/docs/txt/ahack.txt000066400000000000000000000704101173507505700167670ustar00rootroot00000000000000 The Allegro Hacker's Guide This is a guide to some of the internal workings of Allegro, for people who are interested in hacking on it. This document is far from complete, and may not always be 100% accurate. Remember that when in doubt, the sources are always the definitive reference. Suggestions for what to include in this document will be very welcome: there is far too much code for me to go over it all in any kind of detail, so I want to concentrate on the things that people find most confusing... ====================================== ============ Coding Style ============ ====================================== I'm not going to be a fascist about this, but it does make life easier if all the code uses a consistent layout. If you are going to write and maintain more than one complete source file of your own, I think you are entitled to do that however you like, but for smaller contributions, I will probably reformat your code to fit in with my existing style. It will obviously save me time if you write it this way in the first place, hence this description: Basic Allegro style: K&R, with 3 space indentation. On disk, though, tab stops are 8 spaces, so if for example a line was indented by 12 spaces, this would be saved out as either 12 space characters or 1 tab and 4 spaces, not as 4 tabs. Because this format always will lead to code display looking broken in place or another, new patches should now always use spaces only and no longer contain tabs. The indent.pro file included with the Allegro distribution comes close to getting this layout right, but doesn't quite manage it, so some things still need to be cleaned up by hand. Preprocessor defines and structure names are UPPER_CASE. Function and variable names are lower_case. MixedCaseNames are evil and should not be used. That silly m_pHungarian notation is _really_ evil and should not even be thought about. All symbols should be declared as static unless that is absolutely not possible, in which case they should be prefixed with an underscore. Functions look like this: /* foobar: * Description of what it does. */ void foobar(int foo, int bar) { /* do some stuff */ } Three blank lines between functions. Conditionals look like: if (foo) { /* stuff */ } else { /* stuff */ } The only time when something comes on the same line after a closing brace is at the end of a do/while loop, eg: do { /* stuff */ } while (foo); Case statements look like this: switch (foo) { case bar: /* stuff */ break; default: /* stuff */ break; } Examples of where to put spaces: char *p; if (condition) { } for (x=0; x<10; x++) { } function(foo, bar); (BITMAP *)data[id].dat; All sources should begin with the standard header: /* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Brief description of what this file does. * * By Author. * * Cool stuff added by Someone Else. * * Stupid bug fixed by a Third Person. * * See readme.txt for copyright information. */ Author credits should be added in chronological order, and email addresses should not be included: those can be found in the main credits file, and if they only exist in one place, it is easier to update them when people change address. People only need to be listed in the source file header if they've made a significant contribution to it (one-line fixes don't count), but no matter how small their addition, they must be added to the docs/thanks._tx file. This is sorted alphabetically by name. If they are already in it, update the text to describe the new addition, otherwise make a new entry for the new contributor. Also, anything more than very tiny modifications should be added to the docs/changes._tx file, which grows from the top in reverse chronological order. This file should briefly describe both the nature of the modification and who did it. ======================================= ============ Build Process ============ ======================================= [This is outdated. Now we use CMake.] This is very different depending on whether you are using autoconf or a fixed makefile. For most platforms, though, the fixup script (eg. fixdjgpp.bat), will create a small makefile, which defines MAKEFILE_INC to the make of another file (eg. makefile.dj), and then includes makefile.all. This contains a lot of generic rules, and includes the file named in MAKEFILE_INC to provide additional platform-specific information. The actual source files are listed in makefile.lst. There are three library targets: alleg (release), alld (debugging), and allp (profiling). Objects go in obj/compiler/version/, where version is one of alleg, alld, or allp. Libraries go in lib/compiler/. A few generated things (asmdefs.inc, mmxtest.s, etc), go in the root of obj/compiler/. Dependencies are generated by "make depend", and go in obj/compiler/version/makefile.dep, which is included by makefile.all. When you run "make clean", this only deletes harmless generated files like the objects. "make distclean" strips you right back to the original distribution, including getting rid of the test executables and the library itself. For the ultimate in personal hygene, run "make veryclean", which will wipe absolutely all generated files. After doing this, you will have to run "make depend" before you can build the library, and also "fixdll.bat" if you are working on a Windows platform. To pass long commandlines to the MSVC and Watcom linkers, the program runner.exe is compiled using gcc, so make can pass it a decent number of arguments. This just saves the parameters into a temporary file, and then invokes the real command using that as an argument file. All the makefiles currently use gcc for dependency generation, because this is easier than trying to get MSVC or Watcom to output the right info. The symbol LIBRARY_VERSION, defined at the top of the makefile.ver, is used for including a version number in things like the DLL filename. ====================================== ============ Header Files ============ ====================================== allegro.h lives in the include/ directory. It is only a placeholder which includes other headers which live in the include/allegro/ tree. The reason for this slightly odd approach is that allegro.h can include things like "allegro/keyboard.h", which will work both in-situ within the build directory, and if we copy allegro.h to the system include directory and the other headers into system_include/allegro/. This avoids cluttering the system directories with lots of our headers, while still allowing programs to just #include , and also makes it possible for people to access keyboard stuff with #include . base.h includes alconfig.h, which checks the current platform and includes a helper header for this compiler (aldjgpp.h, almsvc.h, alwatcom.h, etc). That helper header defines a bunch of macros describing the system, emulates whatever things are needed to make the code compile properly, and optionally defines ALLEGRO_EXTRA_HEADER and ALLEGRO_INTERNAL_HEADER if it is going to need any other platform-specific includes. After including the platform header, the rest of alconfig.h defines a lot of generic helper macros to their default values, but only if the platform header hasn't already overridden these to something specific. Every module-specific header contains structure definitions and function prototypes. At the end of the file, it may include a header from the include/allegro/inline/ directory which defines related inline routines. If inline asm is supported, this can include in turn asm.inl which imports routines from one of the compiler-specific files al386gcc.h, al386vc.h and al386wat.h; otherwise C versions are used instead. The header alinline.h is a placeholder which includes all the headers defining inline functions. If ALLEGRO_EXTRA_HEADER is defined, allegro.h includes this at the very end. This is used to include one of the files aldos.h, alwin.h, etc, which define platform-specific things like ID values for the hardware drivers. Unlike the platform files included from the top of allegro.h, these are specific per-OS rather than per-compiler, so the same alwin.h can be used by both MSVC and MinGW. They describe library functions that relate to this platform, while the earlier header described the basic language syntax. aintern.h is like the internal.h in earlier Allegro versions, defining routines that are shared between multiple sources, but that we don't generally want user programs to see. On platforms which have specific, non-portable API routines of their own, these should go in a special header in the root of the include directory, eg. winalleg.h. This can be included by user programs that want to access these routines, while making it very clear to them that by including this header, they are writing non-portable code. ===================================== ============ Definitions ============ ===================================== All header function prototypes should use the macro AL_FUNC(). Inline routines use the macro AL_INLINE(). Global variables use AL_VAR() or AL_ARRAY(). Global pointers to functions use AL_FUNCPTR(). Pointers to functions which are passed as parameters to other routines or stored in a structure typedef use AL_METHOD(). This may seem like something of an overkill, but it gives us a lot of flexibility to add DLL import/export specifiers, calling convention markers like __cdecl, and even to mangle symbol names on some compilers. If you forget to use these macros, your code won't work on some platforms. This only applies to header files, though: you can write normal code in the C sources. The symbol ALLEGRO_SRC is defined while compiling library source files. If you want to inline a function in one of your sources, use the INLINE macro. To declare a zero-sized array in terminal position inside a structure, use the ZERO_SIZE_ARRAY(type, name) macro. To use 64 bit integers, declare a LONG_LONG variable (this won't be defined on all platforms). To do things with filenames, check the macros ALLEGRO_LFN, OTHER_PATH_SEPARATOR, and DEVICE_SEPARATOR. See the headers for details. ========================================= ============ Unicode Support ============ ========================================= Do not assume that strings are ASCII. They aren't. If you assume they are, your code might work for a while as long as people are only using it with UTF-8 data, but it will die horribly as soon as someone tries to run it with 16 bit Unicode strings, or Chinese GB-code, or some strange MIME format, etc. Whenever you see a char * being passed around, you must be aware that this will actually contain text in whatever format is currently selected, so you have to be damn careful when manipulating strings. Don't ever forget and call a regular libc routine on them! Use the Unicode functions for all your text manipulation: see the docs for details. When allocating a scratch string on the stack, assume that each character will occupy at most four bytes: this will give you more than enough space for any of the current encoding schemes. If you want to specify a constant string, use the function uconvert_ascii("my string", buf) to obtain a copy of "my string" in the current encoding format. If buf is NULL, this will use an internal static buffer, but the converted string will be overwritten by the next call to any format conversion routines, so you shouldn't pass it down into other library functions. Normally you should provide the conversion space yourself, allocating buf as a temporary object on the stack. To convert the other way (eg. before passing an Allegro string to an OS routine that expects ASCII data), call uconvert_toascii(mystring, buf). For any messages that may be seen by the user, you can call get_config_text("my ascii string") instead of uconvert_ascii(). This will return a pointer to persistent memory (so it is ok to keep the string around indefinitely), after converting into the current text encoding format. This function is cool because it saves you having to bother allocating space for the converted data, and because it allows the string to be replaced by the translations in language.dat. You should be sure to always pass a constant string to get_config_text(), rather than any generated text or data from other string variables: this is so that the findtext.sh script can easily locate all the strings that need to be translated. Hardware drivers should initialise their name and desc fields to the global empty_string, and store an ASCII driver name in their ascii_name field. The framework code will automatically translate and convert this value, storing the result in both the name and desc fields. For most drivers this will be enough, but if you want to provide a more detailed description, it is up to your driver to set this up from their init routine, and take care of all the required conversions. ====================================== ============ Asm Routines ============ ====================================== [We don't use hand written asm any more.] Structure offsets are defined in asmdef.inc, which is generated by asmdef.c. This allows the asm code to use human readable names for the structure members, and to automatically adjust whenever new fields are added, so it will always exactly match the layout of the C structures. Asm code should use the macro FUNC(name) to declare the start of a routine, and GLOBL(name) whenever it wants to refer to an external symbol (eg. a C variable or function). This is to handle name mangling in a portable way (COFF requires an underscore prefix, ELF does not). You can modify %ds and %es from asm, as long as you put them back. If USE_FS and FSEG are defined, you can also change %fs, otherwise this is not required and you can safely use nearptr access for everything. Don't assume that the MMX opcodes will be supported: not every assembler version knows about these. Check the ALLEGRO_MMX macro, and be sure to give up gracefully if these instructions are not available. ======================================= ============ Documentation ============ ======================================= One of the nicest features of Allegro is its excellent manual, that you can read in several formats, ranging from plain text to compiled HTML. All API functions of the library have to be documented in docs/src/allegro._tx in the appropriate section. Note that, whatever you write in the file, you shouldn't exceed a line width of 78 characters, except for lines which contain tags. This rule is needed in order to produce correct plain text documentation that doesn't extend beyond the standard 80 column screen/terminal. All the other formats are less strict about line width and will probably reformat the text anyway. If the function you are documenting returns a value, use the @retval command to start the chunk of text that describes the return value or how it is used. If the function takes parameters, document if they are required to follow a specific format (e.g. string encoding), what they are for, and their range of values (if any). The latter is particularly important for boolean parameters, because there's no way to tell the user that an integer must be either `true' or `false' in the C programming language. Parameters are always referred to between single quotes, left and right. These are tt-ized in the HTML version, but only if there are no space characters between the left and right quote. If it is possible to include a little fragment of code which demonstrates the usage of the function, do it just before the @retval command if there is one, or at the end of the block. This is very welcome for functions that don't have example references (@eref). You don't need to include the declaration of the variables unless you really think it can help newbies. Usually a single line will be enough, but don't hesitate to add whatever comments you might think of as useful for newbies. Also, if you are writing such a one liner, try to use verbose variable names to indicate where they come from or what they should contain. Compare the following lines, where the second is more likely to be found in `real life' code, but should be avoided in these little code fragments taken out of context: blit(source_bitmap, destination_bitmap, source_x, source_y, destination_x, destination_y, bitmap_width, bitmap_height); ... blit(spr[3]->bmp, screen, x, y, s_x, s_y, spr[3]->bmp->w, spr[3]->bmp->h); Whatever coding style applies to Allegro's code also applies to these examples (e.g. 8 characters tab, 3 spaces indentation). If you are having trouble documenting a particular function because you don't know how to approach the task (this tends to happen when you have used the function so much that you have learnt it by heart), here is a checklist you can follow: What is the purpose of the function? Why would the user want to call it? Can you call it at any time or is any other function required to have been called before (excluding install_allegro/allegro_init)? What do the parameters mean? Do they have a precisely defined type? Do they have a range (like boolean integers)? If the function returns a value, what is it? What can it be used for? Is it likely to be the input of another Allegro function? Does the return value have a range (e.g. positive numbers mean success, negative ones failure)? Is this function supported across all platforms that Allegro runs on? What does it do if it is not supported? Does it require a more thorough explanation in the platform-specific section of the documentation? Should the description say whether the function is reentrant or not? Do you think users would like to use it concurrently in multithreaded environments? Don't bother about existing example references (@eref). These are generated automatically by a script. The person in charge of releasing Allegro will most surely do this for you. If you know how to run it, you are very welcome to update these tags though, to avoid piling extra work on the maintainer's shoulders. Of course, all said about documenting functions applies to macros and variables too. =========================================== ============ Debugging helpers ============ =========================================== As a developer you are encouraged to spill as many ASSERT and TRACE macros as you consider necessary. ASSERT macros are a very good way of enforcing documented limitations in input parameters which should never happen during a perfect (ie. bugless) version of your game. They are good for things like verifying some Allegro subsystem was initialised at the entry point of a function which depends on it, or passing NULL pointers where the documentation explicitly says the user is not allowed to do so. The TRACE macro is very good for things which are not very repetitive, mainly initialisation functions. The problem with C code is that usually error reporting to the user programmer layer is done through a simple integer or NULL pointer, and the error description (if any) stored in allegro_error. This is clearly insufficient for functions like set_gfx_mode() which test many graphic drivers before bailing out. What should be the error code in such case? How could you preserve a coherent error message to the user in driver A when driver B later overwrites it with some other error which may not interest the user trying to run driver A? Developers have made plans to include better logging facilities in future Allegro releases. In the meantime, it is good if opaque systems like drivers use TRACE both to indicate success and failure. For this reason there is a TRACE convention for Allegro code using this macro. At the top of the source file you want to use TRACE define three macros: PREFIX_I, PREFIX_W, PREFIX_E. Each of this should be a string in the format "al-SYSTEM LEVEL: " where SYSTEM is usually the filename creating the TRACE (but doesn't have to) and LEVEL is either INFO, WARNING or ERROR respectively. Later you can use them like this: if (some_error_in_a_deep_obscure_function) { TRACE(PREFIX_E "Couldn't init obscure driver because %s", something); return -1; } TRACE(PREFIX_I "Obscure system initialised with option %s", switch); Thanks to this prefix convention a user can use the TRACE macro too and grep Allegro's messages if there is no interest in them. ===================================== ============ Other Stuff ============ ===================================== Any portable routines that run inside a timer handler or input callback must be sure to lock all the code and data that they touch. This is done by placing an END_OF_FUNCTION(x) or END_OF_STATIC_FUNCTION(x) after each function definition (this is not required if you declare the function as INLINE, though), and then calling LOCK_FUNCTION() somewhere in your init code. Use LOCK_VARIABLE() to lock global variables, and LOCK_DATA() to lock allocated memory. Any modules that have cleanup code should register their exit function by calling _add_exit_func(). This will ensure that they are closed down gracefully no matter whether the user calls allegro_exit(), falls off the bottom of main(), or the program dies suddenly due to a runtime error. You must call _remove_exit_func() from inside your shutdown routine, or you will find yourself stuck in an endless loop. =================================================== ============ How to contribute patches ============ =================================================== Once you are willing to contribute that beautiful hack which does what everybody has been waiting for, the fix for that hideous bug which has been driving you mad for several nights, the nice improved documentation you would have liked to read in the manual for the first time, etc, you have already done the hardest part. Now you only need a way to let the Allegro developers merge your changes in the main distribution. You could probably send your patch to one of the people working on Allegro, but this is not very safe, it depends on the person you chose being available and willing to do the work for you. The best you can do is to send your patch to the Allegro Developers mailing list. Read the readme.txt file for information on how to subscribe to this list. Alternatively, updated subscription instructions should always be available at http://alleg.sourceforge.net/maillist.html. Sending your patches to the mailing list instead of a single person is good, because all the subscribed developers can take a look at your modifications, suggest improvements, or find problems, which you can discuss on the same mailing list, letting other developers join the conversation when they consider appropriate. If the modifications are good, they will probably be accepted and merged in the WIP version for the next release. If you aren't lucky, or your patch still needs some work, you will be told why it's not accepted, or what you have to do to improve it. If you aren't subscribed to the list, remember to say this in your message as, by default, replies are irected to the list. You can also use SourceForge's issue web trackers, which you can find at http://sourceforge.net/tracker/?group_id=5665. This doesn't require you to subscribe to any mailing list and you can verify every now and then the status of your contribution. Building your patch against an existent release ----------------------------------------------- If you have obtained Allegro from an existent release, stable or unstable, you will have all the source code contained in some archive format. You will need it, because to create a patch you need two versions of each modified file, the original version, and your modified version. You will also need the diff tool, which is used to create the patches. This tool is usually packaged as a standalone package in most GNU/Linux distributions with the same name. For DOS, you can get a port from http://www.delorie.com/djgpp/. Just choose a mirror from http://www.delorie.com/djgpp/getting.html, enter the v2gnu directory and download the difxxb.zip package. While you are at it, you can also get a tool named patch (patxxb.zip), which is used to apply patches generated by diff, in case you have to apply the patches somebody else sends to you. Install the binaries in some directory of your path, so that you can use them from anywhere. If you are planing to modify only one file, you will usually copy this file to the same name in the same directory with the appended extension '.old' before starting to work on it. After you have made your modifications to the file, and verified that they please you, go to the directory containing the modified and original files and type at the prompt: diff -u file.c.old file.c > patch This command will generate a text file which contains the differences between both files in unified output format. Open it with your prefered editor and verify that it contains the modifications you wanted to do: lines you have added will be marked with a plus sign '+', lines you have removed will be marked with a minus sign '-'. If the file is bigger than a few kilobytes, compress it before sending to the developers mailing list, and of course remember to add an explanation of what the patch is meant to do, why it's needed, and any other information you consider relevant. If the modifications you want to do are scattered through several files and/or directories, this form of patch generation is very tiresome for both ends (you, and the developers). So unpack a fresh copy of the Allegro source somewhere and move it to the parent directory where your current version is, after giving it another name of course, so as to obtain two complete sources trees side by side. Modify the files you wish in your working directory. Once you are finished, go back to the parent directory housing the two source trees and type: diff -ur fresh_original_directory working_directory > patch The '-r' switch makes diff compare directories recursively. Again, do the previous steps of verifying your patch, compressing and sending with correct instructions. If your patch adds or removes files, you will have to add the '-N' switch, because by default diff will ignore files which are only in one of the trees. Of course, you might want to run a 'make clean' in your working directory before running this command, or you will include lots of generated files which have nothing to do with your patch. Or you could edit the resulting patch, but that can be error prone. Building your patch against a SVN version ----------------------------------------- If you are working with the SVN version of Allegro which you can get from Sourceforge (http://sourceforge.net/projects/alleg/), you won't need to copy any files at all. Just modify the files you want, go to the root directory of the SVN copy and type: svn diff > patch Unlike the standalone diff, the svn diff command will work recursively through the Allegro source tree, comparing each file against the Sourceforge repository. The patch will have slightly different headers, but that's ok, once you have it follow the previous process to send it to the developers mailing list. Of course, check the Subversion manual for more information and options. Online patch creation --------------------- Sometimes you don't have the diff tool around, or don't have the SVN tool to check out the bleeding edge version of Allegro, or you are too lazy to care how to actually make the patch yourself. For any of those cases, you can use the online Allegro patcher at http://www.allegro.cc/dev/make-diff.php. To use it, first you have to get one of the source files of Allegro and make your changes to it. Then, go to that URL and supply the local path on your computer to the modified file. Then, you write the path of this file relative to Allegro's root. If everything goes well, you will end up with a patch you can send to the Allegro developers mailing list or post on SourceForge's patch submission page. allegro4.4-4.4.2/docs/txt/allegro.txt000066400000000000000000023123511173507505700173520ustar00rootroot00000000000000 ______ ___ ___ /\ _ \ /\_ \ /\_ \ \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ /\____/ \_/__/ Version 4.4.2 A game programming library. By Shawn Hargreaves, May 19, 2011. See the AUTHORS file for a complete list of contributors. #include "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." ======================================= ============ 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)()); 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); 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(); Macro which initialises the Allegro library. This is the same thing as calling install_allegro(SYSTEM_AUTODETECT, &errno, atexit). void allegro_exit(); Closes down the Allegro system. This includes returning the system to text mode and removing whatever mouse, keyboard, and timer routines have been installed. You don't normally need to bother making an explicit call to this function, because allegro_init() installs it as an atexit() routine so it will be called automatically when your program exits. Note that after you call this function, other functions like destroy_bitmap() will most likely crash. This is a problem for C++ global destructors, which usually get called after atexit(), so don't put Allegro calls in them. You can write the destructor code in another method which you can manually call before your program exits, avoiding this problem. Macro END_OF_MAIN() In order to maintain cross-platform compatibility, you have to put this macro at the very end of your main function. This macro uses some `magic' to mangle your main procedure on platforms that need it like Windows, some flavours of UNIX or MacOS X. On the other platforms this macro compiles to nothing, so you don't have to #ifdef around it. Example: int main(void) { allegro_init(); /* more stuff goes here */ ... return 0; } END_OF_MAIN() extern char allegro_id[]; 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]; 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 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 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 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 Defined to a text string containing all version numbers and maybe some additional text. This could be `4.2.1 (SVN)' for an Allegro version obtained straight from the SVN repository. #define ALLEGRO_DATE_STR Defined to a text string containing the year this version of Allegro was released, like `2004'. #define ALLEGRO_DATE 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) 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) 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; 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_WIN2003 - Windows 2003 OSTYPE_WINVISTA - Windows Vista OSTYPE_OS2 - OS/2 OSTYPE_WARP - OS/2 Warp 3 OSTYPE_DOSEMU - Linux DOSEMU OSTYPE_OPENDOS - Caldera OpenDOS OSTYPE_LINUX - Linux OSTYPE_SUNOS - SunOS/Solaris OSTYPE_FREEBSD - FreeBSD OSTYPE_NETBSD - NetBSD OSTYPE_IRIX - IRIX OSTYPE_DARWIN - Darwin OSTYPE_QNX - QNX OSTYPE_UNIX - Unknown Unix variant OSTYPE_BEOS - BeOS OSTYPE_MACOS - MacOS OSTYPE_MACOSX - MacOS X extern int os_version; extern int os_revision; The major and minor version of the Operating System currently running. Set by allegro_init(). If Allegro for some reason was not able to retrieve the version of the Operating System, os_version and os_revision will be set to -1. For example: Under Win98 SE (v4.10.2222) os_version will be set to 4 and os_revision to 10. extern int os_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, ...); Outputs a message, using a printf() format string. Usually you want to use this to report messages to the user in an OS independent way when some Allegro subsystem cannot be initialised. But you must not use this function if you are in a graphic mode, only before calling set_gfx_mode(), or after a set_gfx_mode(GFX_TEXT). Also, this function depends on a system driver being installed, which means that it won't display the message at all on some platforms if Allegro has not been initialised correctly. On platforms featuring a windowing system, it will bring up a blocking GUI message box. If there is no windowing system, it will try to print the string to a text console, attempting to work around codepage differences by reducing any accented characters to 7-bit ASCII approximations. Example: 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); 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)); 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(); Returns zero on success and non-zero on failure (e.g. the feature is not supported by the platform). int desktop_color_depth(); Finds out the currently selected desktop color depth. You can use this information to make your program use the same color depth as the desktop, which will likely make it run faster because the graphic driver won't be doing unnecessary color conversions behind your back. Under some OSes, switching to a full screen graphics mode may automatically change the desktop color depth. You have, therefore, to call this function before setting any graphics mode in order to retrieve the real desktop color depth. Example: allegro_init(); ... if ((depth = desktop_color_depth()) != 0) { set_color_depth(depth); } 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); 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 */ } 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(); 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[]; 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; 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; 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; 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()). ================================================================= ============ Structures and types defined by Allegro ============ ================================================================= There are several structures and types defined by Allegro which are used in many functions (like the BITMAP structure). This section of the manual describes their useful content from a user point of view when they don't fit very well any of the existing manual sections, and redirects you to the appropriate section when it's already described there. Note that unless stated otherwise, the contents shown here are just for read only purposes, there might be other internal flags, but you shouldn't depend on them being available in past/future versions of Allegro. typedef long fixed This is a fixed point integer which can replace float with similar results and is faster than float on low end machines. Read chapter "Fixed point math routines" for the full explanation. typedef struct 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 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 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 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 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 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 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 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 int width, height, bpp; Structure contained in GFX_MODE_LIST. #define PAL_SIZE Preprocessor constant equal to 256. typedef PALETTE RGB[PAL_SIZE] Allegro palettes are arrays of PAL_SIZE RGB entries. typedef struct RGB 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 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 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 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 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 int attrib; - actual attributes of the file found time_t time; - modification time 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 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 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 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 float w, x, y, z; Read chapter "Quaternion math routines" for a description on how to obtain/use this structure. typedef struct DIALOG 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 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 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 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 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 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 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 A structure holding MIDI data. Read chapter "Music routines (MIDI)" for a description on how to obtain/use this structure. typedef struct 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 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 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 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 Opaque structure for handling LZSS decompression. Read chapter "File and compression routines for a description on how to obtain/use this structure. ========================================== ============ 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); 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); 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; ... } 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)); 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); 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); 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 */ } Returns non-zero if any conversion is required or zero otherwise. int uconvert_size(const char *s, int type, int newtype); Finds out how many bytes are required to store the specified string `s' after a conversion from `type' to `newtype', including the mandatory zero terminator of the string. You can use U_CURRENT for either `type' or `newtype' as a shortcut to represent whatever text encoding format is currently selected. Example: length = uconvert_size(old_string, U_CURRENT, U_UNICODE); new_string = malloc(length); ustrcpy(new_string, old_string); 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); 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); 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); 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[]); 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[]); 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[]; 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); Low level helper function for reading Unicode text data. Example: int first_unicode_letter = ugetc(text_string); Returns the character pointed to by `s' in the current encoding format. int ugetx(char **s); int ugetxc(const char **s); Low level helper function for reading Unicode text data. ugetxc is provided for working with pointer-to-pointer-to-const char data. Example: char *p = string; int first_letter, second_letter, third_letter; first_letter = ugetx(&p); second_letter = ugetx(&p); third_letter = ugetx(&p); 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); Low level helper function for writing Unicode text data. Writes the character `c' to the address pointed to by `s'. Returns the number of bytes written, which is equal to the width of the character in the current encoding format. int uwidth(const char *s); Low level helper function for testing Unicode text data. Returns the number of bytes occupied by the first character of the specified string, in the current encoding format. int ucwidth(int c); Low level helper function for testing Unicode text data. Returns the number of bytes that would be occupied by the specified character value, when encoded in the current format. int uisok(int c); Low level helper function for testing Unicode text data. Finds out if the character value `c' can be encoded correctly in the current format, which can be useful if you are converting from Unicode to ASCII or another encoding format where the range of valid characters is limited. Returns non-zero if the value can be correctly encoded, zero otherwise. int uoffset(const char *s, int index); Finds out the offset (in bytes from the start of the string) of the character at the specified `index' in the string `s'. A zero `index' parameter will return the first character of the string. If `index' is negative, it counts backward from the end of the string, so an `index' of `-1' will return an offset to the last character. Example: int from_third_letter = uoffset(text_string, 2); Returns the offset in bytes to the specified character. int ugetat(const char *s, int index); Finds out the character value at the specified `index' in the string. A zero `index' parameter will return the first character of the string. If `index' is negative, it counts backward from the end of the string, so an `index' of `-1' will return the last character of the string. Example: int third_letter = ugetat(text_string, 2); Returns the character value at the specified index in the string. int usetat(char *s, int index, int c); Replaces the character at the specified index in the string with value `c', handling any adjustments for variable width data (ie. if `c' encodes to a different width than the previous value at that location). If `index' is negative, it counts backward from the end of the string. Example: usetat(text_string, 2, letter_a); 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); 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); Returns the number of bytes by which the trailing part of the string was moved. int uremove(char *s, int index); Removes the character at the specified `index' within the string, sliding the rest of the data back to fill the gap. If `index' is negative, it counts backward from the end of the string. Example: int length_in_bytes = ustrsizez(text_string); ... length_in_bytes -= uremove(text_string, -1); Returns the number of bytes by which the trailing part of the string was moved. int ustrsize(const char *s); Returns the size of the specified string in bytes, not including the trailing null character. int ustrsizez(const char *s); Returns the size of the specified string in bytes, including the trailing null character. int uwidth_max(int type); Low level helper function for working with Unicode text data. Returns the largest number of bytes that one character can occupy in the given encoding format. Pass U_CURRENT to represent the current format. Example: char *temp_buffer = malloc(256 * uwidth_max(U_UTF8)); int utolower(int c); This function returns `c', converting it to lower case if it is upper case. int utoupper(int c); This function returns `c', converting it to upper case if it is lower case. int uisspace(int c); 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); 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) 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 */ ... 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)) Does the same as ustrdup(), but allows the user to specify a custom memory allocator function. char *ustrcpy(char *dest, const char *src); This function copies `src' (including the terminating null character into `dest'. You should try to avoid this function because it is very easy to overflow the destination buffer. Use ustrzcpy instead. Returns the value of dest. char *ustrzcpy(char *dest, int size, const char *src); This function copies `src' (including the terminating null character) into `dest', whose length in bytes is specified by `size' and which is guaranteed to be null-terminated even if `src' is bigger than `size'. Note that, even for empty strings, your destination string must have at least enough bytes to store the terminating null character of the string, and your parameter `size' must reflect this. Otherwise, the debug version of Allegro will abort at an assertion, and the release version of Allegro will overrun the destination buffer. Returns the value of `dest'. char *ustrcat(char *dest, const char *src); This function concatenates `src' to the end of `dest`'. You should try to avoid this function because it is very easy to overflow the destination buffer, use ustrzcat instead. Returns the value of `dest'. char *ustrzcat(char *dest, int size, const char *src); This function concatenates `src' to the end of `dest', whose length in bytes is specified by `size' and which is guaranteed to be null-terminated even when `src' is bigger than `size'. Note that, even for empty strings, your destination string must have at least enough bytes to store the terminating null character of the string, and your parameter `size' must reflect this. Otherwise, the debug version of Allegro will abort at an assertion, and the release version of Allegro will overrun the destination buffer. Returns the value of `dest'. int ustrlen(const char *s); This function returns the number of characters in `s'. Note that this doesn't have to equal the string's size in bytes. int ustrcmp(const char *s1, const char *s2); This function compares `s1' and `s2'. Returns zero if the strings are equal, a positive number if `s1' comes after `s2' in the ASCII collating sequence, else a negative number. char *ustrncpy(char *dest, const char *src, int n); This function is like ustrcpy() except that no more than `n' characters from `src' are copied into `dest'. If `src' is shorter than `n' characters, null characters are appended to `dest' as padding until `n' characters have been written. Note that if `src' is longer than `n' characters, `dest' will not be null-terminated. The return value is the value of `dest'. char *ustrzncpy(char *dest, int size, const char *src, int n); This function is like ustrzcpy() except that no more than `n' characters from `src' are copied into `dest' whose length in bytes is specified by `size' and which is guaranteed to be null-terminated even if `src' is bigger than `size'. If `src' is shorter than `n' characters, null characters are appended to `dest' as padding until `n' characters have been written. In any case, `dest' is guaranteed to be null-terminated. Note that, even for empty strings, your destination string must have at least enough bytes to store the terminating null character of the string, and your parameter `size' must reflect this. Otherwise, the debug version of Allegro will abort at an assertion, and the release version of Allegro will overrun the destination buffer. The return value is the value of `dest'. char *ustrncat(char *dest, const char *src, int n); This function is like ustrcat() except that no more than `n' characters from `src' are appended to the end of `dest'. If the terminating null character in `src' is reached before `n' characters have been written, the null character is copied, but no other characters are written. If `n' characters are written before a terminating null is encountered, the function appends its own null character to `dest', so that `n+1' characters are written. You should try to avoid this function because it is very easy to overflow the destination buffer. Use ustrzncat instead. The return value is the value of `dest'. char *ustrzncat(char *dest, int size, const char *src, int n); This function is like ustrzcat() except that no more than `n' characters from `src' are appended to the end of `dest'. If the terminating null character in `src' is reached before `n' characters have been written, the null character is copied, but no other characters are written. Note that `dest' is guaranteed to be null-terminated. The return value is the value of `dest'. int ustrncmp(const char *s1, const char *s2, int n); 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 */ } 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); This function compares `s1' and `s2', ignoring case. Example: if (ustricmp(string, user_input) == 0) { /* string and user_input are equal (ignoring case) */ } 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); 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) */ } 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); This function replaces all upper case letters in `s' with lower case letters. Example: char buffer[] = "UPPER CASE STRING"; allegro_message(ustrlwr(buffer)); The return value is the value of `s'. char *ustrupr(char *s); This function replaces all lower case letters in `s' with upper case letters. Example: char buffer[] = "lower case string"; allegro_message(ustrupr(buffer)); The return value is the value of `s'. char *ustrchr(const char *s, int c); Finds the first occurrence of the character `c' in the string `s'. Example: char *p = ustrchr("one,two,three,four", ','); 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); Finds the last occurrence of the character `c' in the string `s'. Example: char *p = ustrrchr("one,two,three,four", ','); Returns a pointer for the last occurrence of `c' in `s', or NULL if no match was found. char *ustrstr(const char *s1, const char *s2); This function finds the first occurrence of string `s2' in string `s1'. Example: char *p = ustrstr("hello world", "world"); Returns a pointer within `s1', or NULL if `s2' wasn't found. char *ustrpbrk(const char *s, const char *set); This function finds the first character in `s' that matches any character in `set'. Example: char *p = ustrpbrk("one,two-three.four", "-. "); Returns a pointer to the first match, or NULL if none are found. char *ustrtok(char *s, const char *set); This function retrieves tokens from `s' which are delimited by characters from `set'. To initiate the search, pass the string to be searched as `s'. For the remaining tokens, pass NULL instead. Warning: Since ustrtok alters the string it is parsing, you should always copy the string to a temporary buffer before parsing it. Also, this function is not re-entrant (ie. you cannot parse two strings at the same time). Example: 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); Returns a pointer to the token, or NULL if no more are found. char *ustrtok_r(char *s, const char *set, char **last); Reentrant version of ustrtok. The `last' parameter is used to keep track of where the parsing is up to and must be a pointer to a char * variable allocated by the user that remains the same while parsing the same string. Example: 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); 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); Convert as much of the string as possible to an equivalent double precision real number. This function is almost like `ustrtod(s, NULL)'. Returns the equivalent value, or zero if the string does not represent a number. long ustrtol(const char *s, char **endp, int base); This function converts the initial part of `s' to a signed integer, setting `*endp' to point to the first unused character, if `endp' is not a NULL pointer. The `base' argument indicates what base the digits (or letters) should be treated as. If `base' is zero, the base is determined by looking for `0x', `0X', or `0' as the first part of the string, and sets the base used to 16, 16, or 8 if it finds one. The default base is 10 if none of those prefixes are found. Example: char *endp, *string = "456.203 askdfg"; int number = ustrtol(string, &endp, 10); 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); 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); 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); 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)); 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, ...); This function writes formatted data into the output buffer. A NULL character is written to mark the end of the string. You should try to avoid this function because it is very easy to overflow the destination buffer. Use uszprintf instead. Returns the number of characters written, not including the terminating null character. int uszprintf(char *buf, int size, const char *format, ...); This function writes formatted data into the output buffer, whose length in bytes is specified by `size' and which is guaranteed to be NULL terminated. Example: char buffer[10]; int player_score; ... uszprintf(buffer, sizeof(buffer), "Your score is: %d", player_score); 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); This is like usprintf(), but you pass the variable argument list directly, instead of the arguments themselves. You can use this function to implement printf like functions, also called variadic functions. You should try to avoid this function because it is very easy to overflow the destination buffer. Use uvszprintf instead. Returns the number of characters written, not including the terminating null character. int uvszprintf(char *buf, int size, const char *format, va_list args); This is like uszprintf(), but you pass the variable argument list directly, instead of the arguments themselves. Example: #include 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); } Returns the number of characters that would have been written without eventual truncation (like with uvsprintf), not including the terminating null character. ================================================ ============ Configuration routines ============ ================================================ Various parts of Allegro, such as the sound routines and the load_joystick_data() function, require some configuration information. This data is stored in text files as a collection of `variable=value' lines, along with comments that begin with a `#' character and continue to the end of the line. The configuration file may optionally be divided into sections, which begin with a `[sectionname]' line. Each section has a unique namespace, to prevent variable name conflicts, but any variables that aren't in a section are considered to belong to all the sections simultaneously. Note that variable and section names cannot contain spaces. By default the configuration data is read from a file called `allegro.cfg', which can be located either in the same directory as the program executable, or the directory pointed to by the ALLEGRO environment variable. Under Unix, it also checks for `~/allegro.cfg', `~/.allegrorc', `/etc/allegro.cfg', and `/etc/allegrorc', in that order; under BeOS only the last two are also checked. MacOS X also checks in the Contents/Resources directory of the application bundle, if any, before doing the checks above. If you don't like this approach, you can specify any filename you like, or use a block of binary configuration data provided by your program (which could for example be loaded from a datafile). You can also extend the paths searched for allegro resources with set_allegro_resource_path(). You can store whatever custom information you like in the config file, along with the standard variables that are used by Allegro (see below). Allegro comes with a setup directory where you can find configuration programs. The standalone setup program is likely to be of interest to final users. It allows any user to create an `allegro.cfg' file without the need to touch a text editor and enter values by hand. It also provides a few basic tests like sound playing for sound card testing. You are welcome to include the setup program with your game, either as is or with modified graphics to fit better your game. void set_config_file(const char *filename); Sets the configuration file to be used by all subsequent config functions. (Allegro will not search for this file in other locations as it does with allegro.cfg at the time of initialization.) 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); 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); 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); 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(); 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(); Pops a configuration state previously stored by push_config_state(), replacing the current config source with it. void flush_config_file(); Writes the current config file to disk if the contents have changed since it was loaded or since the latest call to the function. void reload_config_texts(const char *new_language); Reloads the translated strings returned by get_config_text(). This is useful to switch to another language in your program at runtime. If you want to modify the `[system]' language configuration variable yourself, or you have switched configuration files, you will want to pass NULL to just reload whatever language is currently selected. Or you can pass a string containing the two letter code of the language you desire to switch to, and the function will modify the language variable. After you call this function, the previously returned pointers of get_config_text() will be invalid. Example: ... /* 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)); 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); 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); 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"); 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); 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); 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); 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); 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); Reads a token list (words separated by spaces) from the current config file. The token list is stored in a temporary buffer that will be clobbered by the next call to get_config_argv(), so the data should not be expected to persist. Returns an argv style argument list and sets `argc' to the number of retrieved tokens. If the variable is not present, returns NULL and sets argc to zero. const char *get_config_text(const char *msg); This function is primarily intended for use by internal library code, but it may perhaps be helpful to application programmers as well. It uses the `language.dat' or `XXtext.cfg' files (where XX is a language code) to look up a translated version of the parameter in the currently selected language. This is basically the same thing as calling get_config_string() with `[language]' as the section, `msg' as the variable name, and `msg' as the default value, but it contains some special code to handle Unicode format conversions. The `msg' parameter is always given in ASCII format, but the returned string will be converted into the current text encoding, with memory being allocated as required, so you can assume that this pointer will persist without having to manually allocate storage space for each string. Note that if you are planning on distributing your game on the Unix platform there is a special issue with how to deal with the `language.dat' file. Read section "Files shared by Allegro" of the chapter "Unix specifics" to learn more about this. Returns a suitable translation if one can be found or a copy of the parameter if nothing else is available. void set_config_string(const char *section, const char *name, const char *val); Writes a string variable to the current config file, replacing any existing value it may have, or removes the variable if `val' is NULL. The section name may be set to NULL to write the variable to the root of the file, or used to control which section the variable is inserted into. The altered file will be cached in memory, and not actually written to disk until you call allegro_exit(). Note that you can only write to files in this way, so the function will have no effect if the current config source was specified with set_config_data() rather than set_config_file(). As a special case, variable or section names that begin with a '#' character are treated specially and will not be read from or written to the disk. Addon packages can use this to store version info or other status information into the config module, from where it can be read with the get_config_string() function. void set_config_int(const char *section, const char *name, int val); Writes an integer variable to the current config file. See the comments about set_config_string(). void set_config_hex(const char *section, const char *name, int val); Writes an integer variable to the current config file, in hexadecimal format. See the comments about set_config_string(). void set_config_float(const char *section, const char *name, float val); Writes a floating point variable to the current config file. See the comments about set_config_string(). void set_config_id(const char *section, const char *name, int val); Writes a 4-letter driver ID variable to the current config file. See the comments about set_config_string(). int list_config_entries(const char *section, const char ***names); This function can be used to get a list of all entries in the given config section. The names parameter is a pointer to an array of strings. If it points to a NULL pointer, the list will be allocated, else it will be re-allocated. You should free the list again with free_config_entries if you don't need it anymore, or you can pass it again to list_config_entries and the memory will be re-used. See the following example for how you can use it, it will print out the complete contents of the current configuration: int i, n; char const **sections = NULL; char const **entries = NULL; /* List all entries not in any section. */ n = list_config_entries(NULL, &entries); for (i = 0; i printf(" %s=\"%s\"\n", entries[i], get_config_string( NULL, entries[i], "-")); /* List all sections (and entries in them). */ n = list_config_sections(§ions); /* loop through all section names */ for (i = 0; i { int j, m; printf("%s\n", sections[i]); m = list_config_entries(sections[i], &entries); /* loop through all entries in the section */ for (j = 0; j { printf(" %s=\"%s\"\n", entries[j], get_config_string( sections[i], entries[j], "-")); } } /* It is enough to free the arrays once at the end. */ free_config_entries(§ions); free_config_entries(&entries); Returns the number of valid strings in the names array. int list_config_sections(const char ***names); The names parameter is a pointer to an array of strings. If it points to a NULL pointer, the list will be allocated, else it will be re-allocated. After the function returns, it will contain the names of all sections in the current configuration. Use free_config_entries to free the allocated memory again. See list_config_entries for more information and an example how to use it. Returns the number of valid strings in the names array. int free_config_entries(const char ***names); Once you are done with the string arrays filled in by list_config_entries and list_config_sections, you can free them again with this function. The passed array pointer will be set to NULL, and you directly can pass the same pointer again to list_config_entries or list_config_sections later - but you also could pass them again without freeing first, since the memory is re-allocated when the pointer is not NULL. See list_config_entries for an example of how to use it. Standard config variables ------------------------- Allegro uses these standard variables from the configuration file: [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 X-Windows ("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 base name like `us' or `uk'. If the latter, Allegro will look first for a separate config file with that name (eg. `uk.cfg') and then for an object with that name in the `keyboard.dat' file (eg. `UK_CFG'). The config file or `keyboard.dat' file can be stored in the same directory as the program, or in the location pointed to by the ALLEGRO environment variable. Look in the `keyboard.dat' file to see what mappings are currently available. language = x Specifies which language file to use for error messages and other bits of system text. The parameter is the name of a translation file, and can either be a fully qualified file path or a base name like `en' or `es'. If the latter, Allegro will look first for a separate config file with a name in the form `entext.cfg', and then for an object with that name in the `language.dat' file (eg. `ENTEXT_CFG'). The config file or `language.dat' file can be stored in the same directory as the program, or in the location pointed to by the ALLEGRO environment variable. Look in the `language.dat' file to see which mappings are currently available. If there is none for your language, you can create it using the English one as model, and even send it to the Allegro development team to include it in future releases. 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. XInitThreads = x If this is set to 0, the X11 port will not call XInitThreads. This can have slight performance advantages and was required on some broken X11 servers, but it makes Allegro incompatible with other X11 libraries like Mesa. [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 additional 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. If you want to use only part of a tablet, you need to set the entries for X and Y axis by hand. ev_abs_to_rel_x = x ev_abs_to_rel_y = x ev_abs_to_rel_z = x Linux only: scaling factor for tablet mouse speed. Defaults to 1. This is used only when the input sends absolute events (tablet, joystick, etc.) and the cursor should behave like a mouse. If you are using a mouse on a tablet, you need to set these entries for X and Y axis (try numbers between 1 and 40). 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 sound card) 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 sound card port address (this is usually 220). sound_dma = x DOS only: sets the sound card DMA channel (this is usually 1). sound_irq = x DOS only: sets the sound card 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 [:,], 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 = 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. ======================================== ============ 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 up to a certain size. Allegro will fall back on its own cursor drawing if it cannot let the OS handle this. On some platforms, the hardware cursor is incompatible with get_mouse_mickeys() and it is therefor disabled by default. In such cases you need to call enable_hardware_cursor() to enable it explicitly. 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(); Installs the Allegro mouse handler. You must do this before using any other mouse functions. Returns -1 on failure, zero if the mouse handler is already installed (in which case this function does nothing) and the number of buttons on the mouse if the mouse handler has successfully been installed (ie. this is the first time a handler is installed or you have removed the previous one). Note that the number of mouse buttons returned by this function is more an indication than a physical reality. With most devices there is no way of telling how many buttons there are, and any user can override the number of mouse buttons returned by this function with a custom configuration file and the variable num_buttons. Even if this value is overridden by the user, the global mouse variables will still report whatever the hardware is sending. void remove_mouse(); Removes the mouse handler. You don't normally need to bother calling this, because allegro_exit() will do it for you. int poll_mouse(); Wherever possible, Allegro will read the mouse input asynchronously (ie. from inside an interrupt handler), but on some platforms that may not be possible, in which case you must call this routine at regular intervals to update the mouse state variables. To help you test your mouse polling code even if you are programming on a platform that doesn't require it, after the first time that you call this function Allegro will switch into polling mode, so from that point onwards you will have to call this routine in order to get any mouse input at all, regardless of whether the current driver actually needs to be polled or not. Returns zero on success, or a negative number on failure (ie. no mouse driver installed). int mouse_needs_poll(); Returns TRUE if the current mouse driver is operating in polling mode. void enable_hardware_cursor(void); After calling this function, Allegro will let the operating system draw the mouse cursor instead of doing it itself. This is not possible with all graphics drivers though: you'll need to check the gfx_capabilities flags after calling show_mouse() to see if this works. On some platforms, enabling the hardware cursor causes get_mouse_mickeys() to return only a limited range of values, so you should not call this function if you need mouse mickeys. void disable_hardware_cursor(void); After calling this function, Allegro will be responsible for drawing the mouse cursor rather than the operating system. On some platforms calling enable_hardware_cursor() makes the return values of get_mouse_mickeys() unreliable. After calling this function, get_mouse_mickeys() returns reliable results again. void select_mouse_cursor(int cursor); This function allows you to use the operating system's native mouse cursors rather than some custom cursor. You will need to enable this functionality by calling enable_hardware_cursor() beforehand. If the operating system does not support this functionality, or if it has not been enabled, then Allegro will substitute its own cursor images. You can change these substitute images using set_mouse_cursor_bitmap(). Note that the effects of this function are not apparent until show_mouse() is called. To know whether the operating system's native cursor is being used, or if Allegro has made a substitution, you can check the GFX_SYSTEM_CURSOR flag in gfx_capabilities after calling show_mouse(). The cursor argument selects the type of cursor to be displayed: MOUSE_CURSOR_NONE Selects an invisible mouse cursor. In that sense, it is similar to calling show_mouse(NULL); MOUSE_CURSOR_ALLEGRO Selects the custom Allegro cursor, i.e. the one that you set with set_mouse_sprite(). MOUSE_CURSOR_ARROW The operating system default arrow cursor. MOUSE_CURSOR_BUSY The operating system default `busy' cursor (hourglass). MOUSE_CURSOR_QUESTION The operating system default `question' cursor (arrow with question mark). MOUSE_CURSOR_EDIT The operating system default `edit' cursor (vertical bar). Example: /* 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); This function changes the cursor image Allegro uses if select_mouse_cursor() is called but no native operating system cursor can be used, e.g. because you did not call enable_hardware_cursor(). The cursor argument can be one of: MOUSE_CURSOR_ALLEGRO MOUSE_CURSOR_ARROW MOUSE_CURSOR_BUSY MOUSE_CURSOR_QUESTION MOUSE_CURSOR_EDIT but not MOUSE_CURSOR_NONE. The bmp argument can either point to a valid bitmap or it can be NULL. Passing a bitmap makes Allegro use that image in place of its own default substitution (should the operating system's native cursor be unavailable). The bitmap must remain available for the duration in which it could be used. Passing NULL lets Allegro revert to its default substitutions. The effect of this function will not be apparent until show_mouse() is called. extern volatile int mouse_x; extern volatile int mouse_y; extern volatile int mouse_z; extern volatile int mouse_w; extern volatile int mouse_b; extern volatile int mouse_pos; Global variables containing the current mouse position and button state. Wherever possible these values will be updated asynchronously, but if mouse_needs_poll() returns TRUE, you must manually call poll_mouse() to update them with the current input state. The `mouse_x' and `mouse_y' positions are integers ranging from zero to the bottom right corner of the screen. The `mouse_z' and `mouse_w' variables hold the current vertical and horizontal wheel position, when using an input driver that supports wheel mice. The `mouse_b' variable is a bitfield indicating the state of each button: bit 0 is the left button, bit 1 the right, and bit 2 the middle button. Additional non standard mouse buttons might be available as higher bits in this variable. Usage example: 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; 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); Tells Allegro to display a mouse pointer on the screen. This will only work if the timer module has been installed. The mouse pointer will be drawn onto the specified bitmap, which should normally be `screen' (see later for information about bitmaps). To hide the mouse pointer, call show_mouse(NULL). Warning: if you draw anything onto the screen while the pointer is visible, a mouse movement interrupt could occur in the middle of your drawing operation. If this happens the mouse buffering and graphics drawing code will get confused and will leave 'mouse droppings' all over the screen. To prevent this, you must make sure you turn off the mouse pointer whenever you draw onto the screen. This is not needed if you are using a hardware cursor. Note: you must not be showing a mouse pointer on a bitmap at the time that the bitmap is destroyed with destroy_bitmap(), e.g. call show_mouse(NULL); before destroying the bitmap. This does not apply to `screen' since you never destroy `screen' with destroy_bitmap(). void scare_mouse(); Helper for hiding the mouse pointer prior to a drawing operation. This will temporarily get rid of the pointer, but only if that is really required (ie. the mouse is visible, and is displayed on the physical screen rather than some other memory surface, and it is not a hardware or OS cursor). The previous mouse state is stored for subsequent calls to unscare_mouse(). void scare_mouse_area(int x, int y, int w, int h); Like scare_mouse(), but will only hide the cursor if it is inside the specified rectangle. Otherwise the cursor will simply be frozen in place until you call unscare_mouse(), so it cannot interfere with your drawing. void unscare_mouse(); 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); In case you do not need Allegro's mouse cursor API, which automatically emulates a cursor in software if no other cursor is available, you can use this low level function to try to display or hide the system cursor directly. The cursor parameter takes the same values as select_mouse_cursor. This function is very similar to calling enable_hardware_cursor, select_mouse_cursor and show_mouse, but will not try to do anything if no system cursor is available. The most common use for this function is to just call it once at the beginning of the program to tell it to display the system cursor inside the Allegro window. The return value can be used to see if this succeeded or not. On some systems (e.g. DirectX fullscreen) this is not supported and the function will always fail, and in other cases only some of the cursors will work, or in the case of MOUSE_CURSOR_ALLEGRO, only certain bitmap sizes may be supported. You never should use show_os_cursor together with the function show_mouse and other functions affecting it (select_mouse_cursor, enable_hardware_cursor, disable_hardware_cursor, scare_mouse, unscare_mouse). They implement the standard high level mouse API, and don't work together with this low level function. Returns 0 if a system cursor is being displayed after the function returns, or -1 otherwise. extern volatile int freeze_mouse_flag; If this flag is set, the mouse pointer won't be redrawn when the mouse moves. This can avoid the need to hide the pointer every time you draw to the screen, as long as you make sure your drawing doesn't overlap with the current pointer position. void position_mouse(int x, int y); Moves the mouse to the specified screen position. It is safe to call even when a mouse pointer is being displayed. void position_mouse_z(int z); Sets the mouse wheel position variable to the specified value. void position_mouse_w(int w); Sets the horizontal mouse wheel position to the specified value. void set_mouse_range(int x1, int y1, int x2, int y2); Sets the area of the screen within which the mouse can move. Pass the top left corner and the bottom right corner (inclusive). If you don't call this function the range defaults to (0, 0, SCREEN_W-1, SCREEN_H-1). void set_mouse_speed(int xspeed, int yspeed); Sets the mouse speed. Larger values of xspeed and yspeed represent slower mouse movement: the default for both is 2. void set_mouse_sprite(BITMAP *sprite); You don't like Allegro's mouse pointer? No problem. Use this function to supply an alternative of your own. If you change the pointer and then want to get Allegro's lovely arrow back again, call set_mouse_sprite(NULL). As a bonus, set_mouse_sprite(NULL) uses the current palette in choosing colors for the arrow. So if your arrow mouse sprite looks ugly after changing the palette, call set_mouse_sprite(NULL). void set_mouse_sprite_focus(int x, int y); The mouse focus is the bit of the pointer that represents the actual mouse position, ie. the (mouse_x, mouse_y) position. By default this is the top left corner of the arrow, but if you are using a different mouse pointer you might need to alter it. void get_mouse_mickeys(int *mickeyx, int *mickeyy); Measures how far the mouse has moved since the last call to this function. The values of mickeyx and mickeyy will become negative if the mouse is moved left or up, respectively. The mouse will continue to generate movement mickeys even when it reaches the edge of the screen, so this form of input can be useful for games that require an infinite range of mouse movement. Note that the infinite movement may not work in windowed mode, since under some platforms the mouse would leave the window, and may not work at all if the hardware cursor is in use. extern void (*mouse_callback)(int flags); Called by the interrupt handler whenever the mouse moves or one of the buttons changes state. This function must be in locked memory, and must execute _very_ quickly! It is passed the event flags that triggered the call, which is a bitmask containing any of the values MOUSE_FLAG_MOVE, MOUSE_FLAG_LEFT_DOWN, MOUSE_FLAG_LEFT_UP, MOUSE_FLAG_RIGHT_DOWN, MOUSE_FLAG_RIGHT_UP, MOUSE_FLAG_MIDDLE_DOWN, MOUSE_FLAG_MIDDLE_UP, and MOUSE_FLAG_MOVE_Z. Note that even if the mouse has more than three buttons, only the first three can be trapped using a callback. int mouse_on_screen(); This function can be useful to prevent having two mouse pointers on the screen at the same time when running your program in windowed mode and drawing the mouse pointer yourself. Other possible uses include the ability to pause your game when the mouse goes off of the window, or only scrolling the view when the pointer is near the edge of the window, but not while off of the window. Example : if (mouse_on_screen()) {draw_sprite(buffer , mouse_sprite , mouse_x , mouse_y);} Returns 0 if the mouse pointer is off of the screen, or non-zero otherwise. ======================================== ============ 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(); Installs the Allegro timer interrupt handler. You must do this before installing any user timer routines, and also before displaying a mouse pointer, playing FLI animations or MIDI music, and using any of the GUI routines. Returns zero on success, or a negative number on failure (but you may decide not to check the return value as this function is very unlikely to fail). void remove_timer(); Removes the Allegro timer handler (and, under DOS, passes control of the clock back to the operating system). You don't normally need to bother calling this, because allegro_exit() will do it for you. int install_int(void (*proc)(), int speed); Installs a user timer handler, with the speed given as the number of milliseconds between ticks. This is the same thing as install_int_ex(proc, MSEC_TO_TIMER(speed)). If you call this routine without having first installed the timer module, install_timer() will be called automatically. Calling again this routine with the same timer handler as parameter allows you to adjust its speed. Returns zero on success, or a negative number if there is no room to add a new user timer. int install_int_ex(void (*proc)(), int speed); Adds a function to the list of user timer handlers or, if it is already installed, retroactively adjusts its speed (i.e makes as though the speed change occurred precisely at the last tick). The speed is given in hardware clock ticks, of which there are 1193181 a second. You can convert from other time formats to hardware clock ticks with the macros: 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. Returns zero on success, or a negative number if there is no room to add a new user timer. Macro LOCK_VARIABLE(variable_name); Due to interrupts, you are required to lock all the memory used by your timer routines. See the description of install_int_ex() for a more detailed explanation and usage example. Macro LOCK_FUNCTION(function_name); Due to interrupts, you are required to lock all the memory used by your timer routines. See the description of install_int_ex() for a more detailed explanation and usage example. Macro END_OF_FUNCTION(function_name); Due to interrupts, you are required to lock all the code used by your timer routines. See the description of install_int_ex() for a more detailed explanation and usage example. void remove_int(void (*proc)()); 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); 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); 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); 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; 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); 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)()) 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(). =========================================== ============ Keyboard routines ============ =========================================== The Allegro keyboard handler provides both buffered input and a set of flags storing the current state of each key. Note that it is not possible to correctly detect every combination of keys, due to the design of the PC keyboard. Up to two or three keys at a time will work fine, but if you press more than that the extras are likely to be ignored (exactly which combinations are possible seems to vary from one keyboard to another). On DOS, Allegro requires the user to specify the language of the keyboard mapping because it is impossible to obtain this information from the OS, otherwise the default US keyboard mapping will be used. Allegro comes with a prepackaged `keyboard.dat' file which you can put along with your binary. If this file is present, Allegro will be able to extract the keyboard mapping information stored there. However, the end user still needs to select which keyboard mapping to use. This can be accomplished through the keyboard variable of the system section in a standard `allegro.cfg' configuration file. Read chapter "Configuration routines" for more information about this. int install_keyboard(); Installs the Allegro keyboard interrupt handler. You must call this before using any of the keyboard input routines. Once you have set up the Allegro handler, you can no longer use operating system calls or C library functions to access the keyboard. Note that on some platforms the keyboard won't work unless you have set a graphics mode, even if this function returns a success value before calling set_gfx_mode. This can happen in environments with graphic windowed modes, since Allegro usually reads the keyboard through the graphical window (which appears after the set_gfx_mode call). Example: 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(); 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(); 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)()); 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(); Wherever possible, Allegro will read the keyboard input asynchronously (ie. from inside an interrupt handler), but on some platforms that may not be possible, in which case you must call this routine at regular intervals to update the keyboard state variables. To help you test your keyboard polling code even if you are programming on a platform that doesn't require it, after the first time that you call this function Allegro will switch into polling mode, so from that point onwards you will have to call this routine in order to get any keyboard input at all, regardless of whether the current driver actually needs to be polled or not. The keypressed(), readkey(), and ureadkey() functions call poll_keyboard() automatically, so you only need to use this function when accessing the key[] array and key_shifts variable. Returns zero on success, or a negative number on failure (ie. no keyboard driver installed). int keyboard_needs_poll(); Returns TRUE if the current keyboard driver is operating in polling mode. extern volatile char key[KEY_MAX]; Array of flags indicating the state of each key, ordered by scancode. Wherever possible these values will be updated asynchronously, but if keyboard_needs_poll() returns TRUE, you must manually call poll_keyboard() to update them with the current input state. The scancodes are defined in allegro/keyboard.h as a series of KEY_* constants (and are also listed below). For example, you could write: 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; 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(); 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(); 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); 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); 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); 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); 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); 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); 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) } 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); 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); 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); 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); Sets the keyboard repeat rate. Times are given in milliseconds. Passing zero times will disable the key repeat. void clear_keybuf(); Empties the keyboard buffer. Usually you want to use this in your program before reading keys to avoid previously buffered keys to be returned by calls to readkey() or ureadkey(). extern int three_finger_flag; The DJGPP keyboard handler provides an 'emergency exit' sequence which you can use to kill off your program. If you are running under DOS this is the three finger salute, ctrl+alt+del. Most multitasking OS's will trap this combination before it reaches the Allegro handler, in which case you can use the alternative ctrl+alt+end. If you want to disable this behaviour in release versions of your program, set this flag to FALSE. extern int key_led_flag; By default, the capslock, numlock, and scroll-lock keys toggle the keyboard LED indicators when they are pressed. If you are using these keys for input in your game (eg. capslock to fire) this may not be desirable, so you can clear this flag to prevent the LED's being updated. =========================================== ============ 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); Installs Allegro's joystick handler, and calibrates the centre position values. The type parameter should usually be JOY_TYPE_AUTODETECT, or see the platform specific documentation for a list of the available drivers. You must call this routine before using any other joystick functions, and you should make sure that all joysticks are in the middle position at the time. Example: 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!"); 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(); Removes the joystick handler. You don't normally need to bother calling this, because allegro_exit() will do it for you. int poll_joystick(); The joystick handler is not interrupt driven, so you need to call this function every now and again to update the global position values. Example: 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); Returns zero on success or a negative number on failure (usually because no joystick driver was installed). extern int num_joysticks; Global variable containing the number of active joystick devices. The current drivers support a maximum of eight controllers. extern JOYSTICK_INFO joy[n]; Global array of joystick state information, which is updated by the poll_joystick() function. Only the first num_joysticks elements will contain meaningful information. The JOYSTICK_INFO structure is defined as: 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); Pass the number of the joystick you want to calibrate as the parameter. Returns a text description for the next type of calibration that will be done on the specified joystick, or NULL if no more calibration is required. int calibrate_joystick(int n); Most joysticks need to be calibrated before they can provide full analogue input. This function performs the next operation in the calibration series for the specified stick, assuming that the joystick has been positioned in the manner described by a previous call to calibrate_joystick_name(), returning zero on success. For example, a simple routine to fully calibrate all the joysticks might look like: 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); } } } Returns zero on success, non-zero if the calibration could not be performed successfully. int save_joystick_data(const char *filename); After all the headache of calibrating the joystick, you may not want to make your poor users repeat the process every time they run your program. Call this function to save the joystick calibration data into the specified configuration file, from which it can later be read by load_joystick_data(). Pass a NULL filename to write the data to the currently selected configuration file. Returns zero on success, non-zero if the data could not be saved. int load_joystick_data(const char *filename); Restores calibration data previously stored by save_joystick_data() or the setup utility. This sets up all aspects of the joystick code: you don't even need to call install_joystick() if you are using this function. Pass a NULL filename to read the data from the currently selected configuration file. Returns zero on success: if it fails the joystick state is undefined and you must reinitialise it from scratch. int initialise_joystick(); Deprecated. Use install_joystick() instead. ======================================== ============ 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 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: 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); 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); 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); 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); 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); 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. 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); 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); Switches into graphics mode. The card parameter should usually be one of the Allegro magic drivers (read introduction of chapter "Graphics modes") or see the platform specific documentation for a list of the available drivers. The w and h parameters specify what screen resolution you want. The color depth of the graphic mode has to be specified before calling this function with set_color_depth(). The v_w and v_h parameters specify the minimum virtual screen size, in case you need a large virtual screen for hardware scrolling or page flipping. You should set them to zero if you don't care about the virtual screen size. When you call set_gfx_mode(), the v_w and v_h parameters represent the minimum size of virtual screen that is acceptable for your program. The range of possible sizes is usually very restricted, and Allegro may end up creating a virtual screen much larger than the one you request. Allowed sizes are driver dependent and some drivers do not allow virtual screens that are larger than the visible screen at all: don't assume that whatever you pass will always work. In mode-X the virtual width can be any multiple of eight greater than or equal to the physical screen width, and the virtual height will be set accordingly (the VGA has 256k of vram, so the virtual height will be 256*1024/virtual_width). Currently, using a big virtual screen for page flipping is considered bad practice. There are platforms which don't support virtual screens bigger than the physical screen but can create different video pages to flip back and forth. This means that, if you want page flipping and aren't going to use hardware scrolling, you should call set_gfx_mode() with (0,0) as the virtual screen size and later create the different video pages with create_video_bitmap(). Otherwise your program will be limited to the platforms supporting hardware scrolling. After you select a graphics mode, the physical and virtual screen sizes can be checked with the macros SCREEN_W, SCREEN_H, VIRTUAL_W, and VIRTUAL_H. Returns zero on success. On failure returns a negative number and stores a description of the problem in allegro_error. int set_display_switch_mode(int mode); Sets how the program should handle being switched into the background, if the user tabs away from it. Not all of the possible modes will be supported by every graphics driver on every platform. The available modes are: 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. 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)()); Installs a notification callback for the switching mode that was previously selected by calling set_display_switch_mode(). The direction parameter can either be SWITCH_IN or SWITCH_OUT, depending whether you want to be notified about switches away from your program or back to your program. You can sometimes install callbacks for both directions at the same time, but not every platform supports this. You can install several switch callbacks, but no more than eight on any platform. Returns zero on success, decreasing the number of empty callback slots by one. Returns -1 if the request is impossible for the current platform or you have reached the maximum number of allowed callbacks. void remove_display_switch_callback(void (*cb)()); Removes a notification callback that was previously installed by calling set_display_switch_callback(). All the callbacks will automatically be removed when you call set_display_switch_mode(). You can safely call this function even if the callback you want to remove is not installed. int get_display_switch_mode(); Returns the current display switching mode, in the same format passed to set_display_switch_mode(). int is_windowed_mode(void); This function can be used to detect whether 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. */ } 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. int get_gfx_mode_type(int graphics_card); This function lets you determine the types of operating modes that a specific graphics card driver operates in. It will tell you whether it is a windowed, fullscreen, definitely windowed or fullscreen, and/or a magic driver. The value returned is a bitfield consisting of these fields: GFX_TYPE_UNKNOWN GFX_TYPE_WINDOWED GFX_TYPE_FULLSCREEN GFX_TYPE_DEFINITE GFX_TYPE_MAGIC The return value will only be equivalent to GFX_TYPE_UNKNOWN when it is a driver unrecognized on that platform, or it is a bogus value. Test for the other types by using a bitwise AND. If the driver is windowed or fullscreen, it will also have the definite flag set. For example, int gfx_type = get_gfx_mode_type(GFX_AUTODETECT_WINDOWED); gfx_type would have the GFX_TYPE_WINDOWED, GFX_TYPE_DEFINITE, and GFX_TYPE_MAGIC flags set. Allegro needs to be initialized first. Example: /* Accept the use of only windowed drivers in our selection dialog */ int accept_windowed(int card , int w , int h , int color_depth) { if (get_gfx_mode_type(card) & GFX_TYPE_WINDOWED) return 0; return 1; } /* In main: */ gfx_mode_select_filter(&card, &w, &h, &color_depth, accept_windowed); Returns a bitfield describing the graphics mode type. int get_gfx_mode(); This function will let you determine which graphics driver is currently set by allegro. If no graphics driver is set, it will return GFX_NONE. Returns the id of the current graphics driver if there is one, or GFX_NONE if none is set. extern int gfx_capabilities; Bitfield describing the capabilities of the current graphics driver and video hardware. This may contain combination any of the flags: GFX_CAN_SCROLL: Indicates that the scroll_screen() function may be used with this driver. GFX_CAN_TRIPLE_BUFFER: Indicates that the request_scroll() and poll_scroll() functions may be used with this driver. If this flag is not set, it is possible that the enable_triple_buffer() function may be able to activate it. GFX_HW_CURSOR: Indicates that a hardware mouse cursor is in use. When this flag is set, it is safe to draw onto the screen without hiding the mouse pointer first. Note that not every cursor graphic can be implemented in hardware: in particular VBE/AF only supports 2-color images up to 32x32 in size, where the second color is an exact inverse of the first. This means that Allegro may need to switch between hardware and software cursors at any point during the execution of your program, so you should not assume that this flag will remain constant for long periods of time. It only tells you whether a hardware cursor is in use at the current time, and may change whenever you hide/redisplay the pointer. GFX_SYSTEM_CURSOR Indicates that the mouse cursor is the default system cursor, not Allegro's custom cursor. GFX_HW_HLINE: Indicates that the normal opaque version of the hline() function is implemented using a hardware accelerator. This will improve the performance not only of hline() itself, but also of many other functions that use it as a workhorse, for example circlefill(), triangle(), and floodfill(). GFX_HW_HLINE_XOR: Indicates that the XOR version of the hline() function, and any other functions that use it as a workhorse, are implemented using a hardware accelerator. GFX_HW_HLINE_SOLID_PATTERN: Indicates that the solid and masked pattern modes of the hline() function, and any other functions that use it as a workhorse, are implemented using a hardware accelerator (see note below). GFX_HW_HLINE_COPY_PATTERN: Indicates that the copy pattern mode of the hline() function, and any other functions that use it as a workhorse, are implemented using a hardware accelerator (see note below). GFX_HW_FILL: Indicates that the opaque version of the rectfill() function, the clear_bitmap() routine, and clear_to_color(), are implemented using a hardware accelerator. GFX_HW_FILL_XOR: Indicates that the XOR version of the rectfill() function is implemented using a hardware accelerator. GFX_HW_FILL_SOLID_PATTERN: Indicates that the solid and masked pattern modes of the rectfill() function are implemented using a hardware accelerator (see note below). GFX_HW_FILL_COPY_PATTERN: Indicates that the copy pattern mode of the rectfill() function is implemented using a hardware accelerator (see note below). GFX_HW_LINE: Indicates that the opaque mode line() and vline() functions are implemented using a hardware accelerator. GFX_HW_LINE_XOR: Indicates that the XOR version of the line() and vline() functions are implemented using a hardware accelerator. GFX_HW_TRIANGLE: Indicates that the opaque mode triangle() function is implemented using a hardware accelerator. GFX_HW_TRIANGLE_XOR: Indicates that the XOR version of the triangle() function is implemented using a hardware accelerator. GFX_HW_GLYPH: Indicates that monochrome character expansion (for text drawing) is implemented using a hardware accelerator. GFX_HW_VRAM_BLIT: Indicates that blitting from one part of the screen to another is implemented using a hardware accelerator. If this flag is set, blitting within the video memory will almost certainly be the fastest possible way to display an image, so it may be worth storing some of your more frequently used graphics in an offscreen portion of the video memory. GFX_HW_VRAM_BLIT_MASKED: Indicates that the masked_blit() routine is capable of a hardware accelerated copy from one part of video memory to another, and that draw_sprite() will use a hardware copy when given a sub-bitmap of the screen or a video memory bitmap as the source image. If this flag is set, copying within the video memory will almost certainly be the fastest possible way to display an image, so it may be worth storing some of your more frequently used sprites in an offscreen portion of the video memory. Warning: if this flag is not set, masked_blit() and draw_sprite() will not work correctly when used with a video memory source image! You must only try to use these functions to copy within the video memory if they are supported in hardware. GFX_HW_MEM_BLIT: Indicates that blitting from a memory bitmap onto the screen is being accelerated in hardware. GFX_HW_MEM_BLIT_MASKED: Indicates that the masked_blit() and draw_sprite() functions are being accelerated in hardware when the source image is a memory bitmap and the destination is the physical screen. GFX_HW_SYS_TO_VRAM_BLIT: Indicates that blitting from a system bitmap onto the screen is being accelerated in hardware. Note that some acceleration may be present even if this flag is not set, because system bitmaps can benefit from normal memory to screen blitting as well. This flag will only be set if system bitmaps have further acceleration above and beyond what is provided by GFX_HW_MEM_BLIT. GFX_HW_SYS_TO_VRAM_BLIT_MASKED: Indicates that the masked_blit() and draw_sprite() functions are being accelerated in hardware when the source image is a system bitmap and the destination is the physical screen. Note that some acceleration may be present even if this flag is not set, because system bitmaps can benefit from normal memory to screen blitting as well. This flag will only be set if system bitmaps have further acceleration above and beyond what is provided by GFX_HW_MEM_BLIT_MASKED. GFX_HW_VRAM_STRETCH_BLIT: Indicates that stretched blitting of video bitmaps onto the screen is implemented using hardware acceleration. GFX_HW_SYS_STRETCH_BLIT: Indicates that stretched blitting of system bitmaps onto the screen is implemented using hardware acceleration. GFX_HW_VRAM_STRETCH_BLIT_MASKED: Indicates that masked stretched blitting (including stretch_sprite) of video bitmaps onto the screen is implemented using hardware acceleration. NOTE: some display drivers may show artifacts when this function is used. If the image does not look correct try updating your video drivers. GFX_HW_SYS_STRETCH_BLIT_MASKED: Indicates that masked stretched blitting (including stretch_sprite) of system bitmaps onto the screen is implemented using hardware acceleration. NOTE: some display drivers may show artefact's when this function is used. If the image does not look correct try updating your video drivers. Note: even if the capabilities information says that patterned drawing is supported by the hardware, it will not be possible for every size of pattern. VBE/AF only supports patterns up to 8x8 in size, so Allegro will fall back on the original non-accelerated drawing routines whenever you use a pattern larger than this. Note2: these hardware acceleration features will only take effect when you are drawing directly onto the screen bitmap, a video memory bitmap, or a sub-bitmap thereof. Accelerated hardware is most useful in a page flipping or triple buffering setup, and is unlikely to make any difference to the classic "draw onto a memory bitmap, then blit to the screen" system. int enable_triple_buffer(); If the GFX_CAN_TRIPLE_BUFFER bit of the gfx_capabilities field is not set, you can attempt to enable it by calling this function. In particular if you are running in mode-X in a clean DOS environment, this routine will enable the timer retrace simulator, which will activate the triple buffering functions. Returns zero if triple buffering is enabled, -1 otherwise. int scroll_screen(int x, int y); Attempts to scroll the hardware screen to display a different part of the virtual screen (initially it will be positioned at 0, 0, which is the top left corner). You can use this to move the screen display around in a large virtual screen space, or to page flip back and forth between two non-overlapping areas of the virtual screen. Note that to draw outside the original position in the screen bitmap you will have to alter the clipping rectangle with set_clip_rect(). Mode-X scrolling is reliable and will work on any card, other drivers may not work or not work reliably. See the platform-specific section of the docs for more information. Allegro will handle any necessary vertical retrace synchronisation when scrolling the screen, so you don't need to call vsync() before it. This means that scroll_screen() has the same time delay effects as vsync(). Returns zero on success. Returns non-zero if the graphics driver can't handle hardware scrolling or the virtual screen is not large enough. int request_scroll(int x, int y); This function is used for triple buffering. It requests a hardware scroll to the specified position, but returns immediately rather than waiting for a retrace. The scroll will then take place during the next vertical retrace, but you can carry on running other code in the meantime and use the poll_scroll() routine to detect when the flip has actually taken place. Triple buffering is only possible with certain drivers: you can look at the GFX_CAN_TRIPLE_BUFFER bit in the gfx_capabilities flag to see if it will work with the current driver. This function returns zero on success, non-zero otherwise. int poll_scroll(); This function is used for triple buffering. It checks the status of a hardware scroll previously initiated by the request_scroll() routine. Returns non-zero if it is still waiting to take place, and zero if the requested scroll has already happened. int show_video_bitmap(BITMAP *bitmap); Attempts to page flip the hardware screen to display the specified video bitmap object, which must be the same size as the physical screen, and should have been obtained by calling the create_video_bitmap() function. Allegro will handle any necessary vertical retrace synchronisation when page flipping, so you don't need to call vsync() before it. This means that show_video_bitmap() has the same time delay effects as vsync() by default. This can be adjusted with the "disable_vsync" config key in the [graphics] section of allegro.cfg. Example: 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; ... Returns zero on success and non-zero on failure. int request_video_bitmap(BITMAP *bitmap); This function is used for triple buffering. It requests a page flip to display the specified video bitmap object, but returns immediately rather than waiting for a retrace. The flip will then take place during the next vertical retrace, but you can carry on running other code in the meantime and use the poll_scroll() routine to detect when the flip has actually taken place. Triple buffering is only possible on certain hardware: see the comments about request_scroll(). Example: 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; ... Returns zero on success and non-zero on failure. void vsync(); Waits for a vertical retrace to begin. The retrace happens when the electron beam in your monitor has reached the bottom of the screen and is moving back to the top ready for another scan. During this short period the graphics card isn't sending any data to the monitor, so you can do things to it that aren't possible at other times, such as altering the palette without causing flickering (snow). Allegro will automatically wait for a retrace before altering the palette or doing any hardware scrolling, though, so you don't normally need to bother with this function. ======================================== ============ 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; 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; 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; 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); 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); 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); 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); 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); Creates a sub-bitmap, ie. a bitmap sharing drawing memory with a pre-existing bitmap, but possibly with a different size and clipping settings. When creating a sub-bitmap of the mode-X screen, the x position must be a multiple of four. The sub-bitmap width and height can extend beyond the right and bottom edges of the parent (they will be clipped), but the origin point must lie within the parent region. Returns a pointer to the created sub bitmap, or NULL if the sub bitmap could not be created. Remember to free the sub bitmap before freeing the parent bitmap to avoid memory leaks and potential crashes accessing memory which has been freed. BITMAP *create_video_bitmap(int width, int height); Allocates a video memory bitmap of the specified size. This can be used to allocate offscreen video memory for storing source graphics ready for a hardware accelerated blitting operation, or to create multiple video memory pages which can then be displayed by calling show_video_bitmap(). Read the introduction of this chapter for a comparison with other types of bitmaps and other specific details. Warning: video memory bitmaps are usually allocated from the same space as the screen bitmap, so they may overlap with it; it is therefore not a good idea to use the global screen at the same time as any surfaces returned by this function. Returns a pointer to the bitmap on success, or NULL if you have run out of video ram. Remember to destroy this bitmap before any subsequent call to set_gfx_mode(). BITMAP *create_system_bitmap(int width, int height); Allocates a system memory bitmap of the specified size. Read the introduction of this chapter for a comparison with other types of bitmaps and other specific details. Returns a pointer to the bitmap on success, NULL otherwise. Remember to destroy this bitmap before any subsequent call to set_gfx_mode(). void destroy_bitmap(BITMAP *bitmap); Destroys a memory bitmap, sub-bitmap, video memory bitmap, or system bitmap when you are finished with it. If you pass a NULL pointer this function won't do anything. See above for the restrictions as to when you are allowed to destroy the various types of bitmaps. The bitmap must not have a mouse cursor shown on it at the time it is destroyed. void lock_bitmap(BITMAP *bitmap); Under DOS, locks all the memory used by a bitmap. You don't normally need to call this function unless you are doing very weird things in your program. int bitmap_color_depth(BITMAP *bmp); 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); 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 h; y++) for (x = 0; x 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); 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); Returns TRUE if bmp is a planar (mode-X or Xtended mode) screen bitmap. int is_linear_bitmap(BITMAP *bmp); Returns TRUE if bmp is a linear bitmap, i.e. a bitmap that can be accessed linearly within each scanline (for example a memory bitmap, the DOS VGA or SVGA screen, Windows bitmaps, etc). Linear bitmaps can be used with the _putpixel(), _getpixel(), bmp_write_line(), and bmp_read_line() functions. Historically there were only linear and planar bitmaps for Allegro, so is_linear_bitmap() is actually an alias for !is_planar_bitmap(). int is_memory_bitmap(BITMAP *bmp); Returns TRUE if bmp is a memory bitmap, ie. it was created by calling create_bitmap() or loaded from a grabber datafile or image file. Memory bitmaps can be accessed directly via the line pointers in the bitmap structure, eg. bmp->line[y][x] = color. int is_screen_bitmap(BITMAP *bmp); Returns TRUE if bmp is the screen bitmap, or a sub-bitmap of the screen. int is_video_bitmap(BITMAP *bmp); Returns TRUE if bmp is the screen bitmap, a video memory bitmap, or a sub-bitmap of either. int is_system_bitmap(BITMAP *bmp); Returns TRUE if bmp is a system bitmap object, or a sub-bitmap of one. int is_sub_bitmap(BITMAP *bmp); Returns TRUE if bmp is a sub-bitmap. void acquire_bitmap(BITMAP *bmp); Acquires the specified video bitmap prior to drawing onto it. You never need to call the function explicitly as it is low level, and will only give you a speed up if you know what you are doing. Using it wrongly may cause slowdown, or even lock up your program. Note: You do never need to use acquire_bitmap on a memory bitmap, i.e. a normal bitmap created with create_bitmap. It will simply do nothing in that case. It still can be useful, because e.g. under the current DirectDraw driver of Allegro, most drawing functions need to lock a video bitmap before drawing to it. But doing this is very slow, so you will get much better performance if you acquire the screen just once at the start of your main redraw function, then call multiple drawing operations which need the bitmap locked, and only release it when done. Multiple acquire calls may be nested, but you must make sure to match up the acquire_bitmap and release_bitmap calls. Be warned that DirectX and X11 programs activate a mutex lock whenever a surface is locked, which prevents them from getting any input messages, so you must be sure to release all your bitmaps before using any timer, keyboard, or other non-graphics routines! Note that if you are using hardware accelerated VRAM->VRAM functions, you should not call acquire_bitmap(). Such functions need an unlocked target bitmap under DirectX, so there is now just the opposite case from before - if the bitmap is already locked with acquire_bitmap, the drawing operation has to unlock it. Note: For backwards compatibility, the unlocking behavior of such functions is permanent. That is, if you call acquire_bitmap first, then call e.g. an accelerated blit, the DirectX bitmap will be unlocked internally (it won't affect the nesting counter of acquire/release calls). There is no clear cross-platform way in this Allegro version to know which drawing operations need a locked/unlocked state. For example a normal rectfill most probably is accelerated under DirectX, and therefore needs the screen unlocked, but an XOR rectfill, or one with blending activated, most probably is not, and therefore locks the screen. And while the DirectX driver will do automatic unlocking, there is no such thing under X11, where the function is used to synchronize X11 calls from different threads. Your best bet is to never use acquire_bitmap - changes are you are doing something in the wrong way if you think you need it. Warning: This function can be very dangerous to use, since the whole program may get locked while the bitmap is locked. So the lock should only be held for a short time, and you should not call anything but drawing operations onto the locked video bitmap while a lock is in place. Especially don't call things like show_mouse (or scare_mouse which calls that) or readkey, since it will most likely deadlock your entire program. void release_bitmap(BITMAP *bmp); Releases a bitmap that was previously locked by calling acquire_bitmap(). If the bitmap was locked multiple times, you must release it the same number of times before it will truly be unlocked. void acquire_screen(); Shortcut version of acquire_bitmap(screen); void release_screen(); Shortcut version of release_bitmap(screen); void set_clip_rect(BITMAP *bitmap, int x1, int y1, int x2, int y2); Each bitmap has an associated clipping rectangle, which is the area of the image that it is OK to draw onto. Nothing will be drawn to positions outside this space. This function sets the clipping rectangle for the specified bitmap. Pass the coordinates of the top-left and bottom-right corners of the clipping rectangle in this order; these are both inclusive, i.e. set_clip_rect(bitmap, 16, 16, 32, 32) will allow drawing to (16, 16) and (32, 32), but not to (15, 15) and (33, 33). Drawing operations will be performed (at least partially) on the bitmap as long as the first coordinates of its clipping rectangle are not greater than the second coordinates and its intersection with the actual image is non-empty. If either condition is not fulfilled, drawing will be turned off for the bitmap, e.g. 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); Returns the clipping rectangle for the specified bitmap. void add_clip_rect(BITMAP *bitmap, int x1, int y1, int x2, int y2); Sets the clipping rectangle of the specified bitmap as the intersection of its current clipping rectangle and the rectangle described by the four coordinates. void set_clip_state(BITMAP *bitmap, int state) Turns on (if state is non-zero) or off (if state is zero) clipping for the specified bitmap. Turning clipping off may slightly speed up some drawing operations (usually a negligible difference, although every little helps) but will result in your program dying a horrible death if you try to draw beyond the edges of the bitmap. int get_clip_state(BITMAP *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); 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. ============================================= ============ 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); 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); 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); Loads an 8-bit, 16-bit, 24-bit or 32-bit Windows or OS/2 BMP file. Returns a pointer to the bitmap or NULL on error. Remember that you are responsible for destroying the bitmap when you are finished with it to avoid memory leaks. BITMAP *load_bmp_pf(PACKFILE *f, RGB *pal); 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"); 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); Loads a 256-color IFF ILBM/PBM file. Returns a pointer to the bitmap or NULL on error. Remember that you are responsible for destroying the bitmap when you are finished with it to avoid memory leaks. BITMAP *load_pcx(const char *filename, RGB *pal); Loads a 256-color or 24-bit truecolor PCX file. Returns a pointer to the bitmap or NULL on error. Remember that you are responsible for destroying the bitmap when you are finished with it to avoid memory leaks. BITMAP *load_pcx_pf(PACKFILE *f, RGB *pal); 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"); 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); Loads a 256-color, 15-bit hicolor, 24-bit truecolor, or 32-bit truecolor+alpha TGA file. Returns a pointer to the bitmap or NULL on error. Remember that you are responsible for destroying the bitmap when you are finished with it to avoid memory leaks. BITMAP *load_tga_pf(PACKFILE *f, RGB *pal); 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"); 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); 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); Returns non-zero on error. int save_bmp(const char *filename, BITMAP *bmp, const RGB *pal); Writes a bitmap into a 256-color or 24-bit truecolor BMP file. Returns non-zero on error. int save_bmp_pf(PACKFILE *f, BITMAP *bmp, RGB *pal); A version of save_bmp which writes to a packfile. int save_pcx(const char *filename, BITMAP *bmp, const RGB *pal); Writes a bitmap into a 256-color or 24-bit truecolor PCX file. Returns non-zero on error. int save_pcx_pf(PACKFILE *f, BITMAP *bmp, RGB *pal); A version of save_pcx which writes to a packfile. int save_tga(const char *filename, BITMAP *bmp, const RGB *pal); Writes a bitmap into a 256-color, 15-bit hicolor, 24-bit truecolor, or 32-bit truecolor+alpha TGA file. Returns non-zero on error. int save_tga_pf(PACKFILE *f, BITMAP *bmp, RGB *pal); 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)); 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); 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(); Returns the current color conversion mode. ========================================== ============ 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); 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); 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); 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); 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); Retrieves the specified palette entry. Example: RGB color; ... get_color(11, &color); void get_palette(PALETTE p); Retrieves the entire palette of 256 colors. You should provide an array of 256 RGB structures to store it in. Example: PALETTE pal; ... get_palette(pal); void get_palette_range(PALETTE p, int from, int to); Retrieves the palette entries between from and to (inclusive: pass 0 and 255 to get the entire palette). void fade_interpolate(const PALETTE source, const PALETTE dest, PALETTE output, int pos, int from, int to); Calculates a temporary palette part way between source and dest, returning it in the output parameter. The position between the two extremes is specified by the pos value: 0 returns an exact copy of source, 64 returns dest, 32 returns a palette half way between the two, etc. This routine only affects colors between from and to (inclusive: pass 0 and 255 to interpolate the entire palette). void fade_from_range(const PALETTE source, const PALETTE dest, int speed, int from, int to); Gradually fades a part of the palette from the source palette to the dest palette. The speed is from 1 (the slowest) up to 64 (instantaneous). This routine only affects colors between from and to (inclusive: pass 0 and 255 to fade the entire palette). Note that this function will block your game while the fade is in effect, and it won't work right visually if you are not in an 8 bit color depth resolution. void fade_in_range(const PALETTE p, int speed, int from, int to); Gradually fades a part of the palette from a black screen to the specified palette. The speed is from 1 (the slowest) up to 64 (instantaneous). This routine only affects colors between from and to (inclusive: pass 0 and 255 to fade the entire palette). Note that this function will block your game while the fade is in effect, and it won't work right visually if you are not in an 8 bit color depth resolution. void fade_out_range(int speed, int from, int to); Gradually fades a part of the palette from the current palette to a black screen. The speed is from 1 (the slowest) up to 64 (instantaneous). This routine only affects colors between from and to (inclusive: pass 0 and 255 to fade the entire palette). Note that this function will block your game while the fade is in effect, and it won't work right visually if you are not in an 8 bit color depth resolution. void fade_from(const PALETTE source, const PALETTE dest, int speed); Fades gradually from the source palette to the dest palette. The speed is from 1 (the slowest) up to 64 (instantaneous). Note that this function will block your game while the fade is in effect, and it won't work right visually if you are not in an 8 bit color depth resolution. void fade_in(const PALETTE p, int speed); Fades gradually from a black screen to the specified palette. The speed is from 1 (the slowest) up to 64 (instantaneous). Note that this function will block your game while the fade is in effect, and it won't work right visually if you are not in an 8 bit color depth resolution. void fade_out(int speed); Fades gradually from the current palette to a black screen. The speed is from 1 (the slowest) up to 64 (instantaneous). Note that this function will block your game while the fade is in effect, and it won't work right visually if you are not in an 8 bit color depth resolution. void select_palette(const PALETTE p); Ugly hack for use in various dodgy situations where you need to convert between paletted and truecolor image formats. Sets the internal palette table in the same way as the set_palette() function, so the conversion will use the specified palette, but without affecting the display hardware in any way. The previous palette settings are stored in an internal buffer, and can be restored by calling unselect_palette(). If you call select_palette() again, however, the internal buffer will be overwritten. void unselect_palette(); Restores the palette tables that were in use before the last call to select_palette(). void generate_332_palette(PALETTE pal); Constructs a fake truecolor palette, using three bits for red and green and two for the blue. The load_bitmap() function fills the palette parameter with this if the file does not contain a palette itself (ie. you are reading a truecolor bitmap). int generate_optimized_palette(BITMAP *bmp, PALETTE pal, const char rsvd[PAL_SIZE]); Generates a 256-color palette suitable for making a reduced color version of the specified truecolor image. The rsvd parameter points to a table indicating which colors it is allowed to modify: zero for free colors which may be set to whatever the optimiser likes, negative values for reserved colors which cannot be used, and positive values for fixed palette entries that must not be changed, but can be used in the optimisation. Returns the number of different colors recognised in the provided bitmap, zero if the bitmap is not a truecolor image or there wasn't enough memory to perform the operation, and negative if there was any internal error in the color reduction code. extern PALETTE default_palette; The default IBM BIOS palette. This will be automatically selected whenever you set a new graphics mode. The palette contains 16 basic colors plus many gradients between them. If you want to see the values, you can write a small Allegro program which saves a screenshot with this palette, or open the grabber tool provided with Allegro and create a new palette object, which will use this palette by default. extern PALETTE black_palette; A palette containing solid black colors, used by the fade routines. extern PALETTE desktop_palette; The palette used by the Atari ST low resolution desktop. I'm not quite sure why this is still here, except that the grabber and test programs use it. It is probably the only Atari legacy code left in Allegro, and it would be a shame to remove it :-) The contents of this palette are 16 colors repeated 16 times. Color entry zero is equal to color entry 16, which is equal to color entry 24, etc. 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 ================================================= ============ 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); 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); Returns the requested RGB triplet in the specified color depth. int makeacol32(int r, int g, int b, int a); Converts an RGBA color into a 32-bit display pixel format, which includes an alpha (transparency) value. There are no versions of this routine for other color depths, because only the 32-bit format has enough room to store a proper alpha channel. You should only use RGBA format colors as the input to draw_trans_sprite() or draw_trans_rle_sprite() after calling set_alpha_blender(), rather than drawing them directly to the screen. int makecol(int r, int g, int b); Converts colors from a hardware independent format (red, green, and blue values ranging 0-255) to the pixel format required by the current video mode, calling the preceding 8, 15, 16, 24, or 32-bit makecol functions as appropriate. Example: /* Regardless of color depth, this will look green. */ int green_color = makecol(0, 255, 0); Returns the requested RGB triplet in the current color depth. int makecol_depth(int color_depth, int r, int g, int b); Converts colors from a hardware independent format (red, green, and blue values ranging 0-255) to the pixel format required by the specified color depth. Example: /* Compose the green color for 15 bit color depth. */ int green_15bit = makecol_depth(15, 0, 255, 0); 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); Convert RGBA colors into display dependent pixel formats. In anything less than a 32-bit mode, these are the same as calling makecol() or makecol_depth(), but by using these routines it is possible to create 32-bit color values that contain a true 8 bit alpha channel along with the red, green, and blue components. You should only use RGBA format colors as the input to draw_trans_sprite() or draw_trans_rle_sprite() after calling set_alpha_blender(), rather than drawing them directly to the screen. Returns the requested RGBA quadruplet. 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); 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); 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); 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); 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); 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); 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]; 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) 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). ============================================ ============ 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); Clears the bitmap to color 0. void clear_to_color(BITMAP *bitmap, int 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); 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); 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); Reads a pixel from point (x, y) in the bitmap. Returns -1 if the point lies outside the bitmap (ignoring the clipping rectangle), otherwise the value of the pixel in the color format of the bitmap. Warning: -1 is also a valid value for pixels contained in 32-bit bitmaps with alpha channel (when R,G,B,A are all equal to 255) so you can't use the test against -1 as a predicate for such bitmaps. In this cases, the only reliable predicate is is_inside_bitmap(). To extract the individual color components, use the getr() / getg() / getb() / geta() family of functions. 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); Faster inline versions of getpixel() for specific color depths. These won't work in mode-X, and don't do any clipping, so you must make sure the point lies inside the bitmap. Returns the value of the pixel in the color format you specified. void vline(BITMAP *bmp, int x, int y1, int y2, int color); Draws a vertical line onto the bitmap, from point (x, y1) to (x, y2). Note: vline() is implemented as an alias to another function. See ALLEGRO_NO_VHLINE_ALIAS in the `Differences between platforms' section for details. void hline(BITMAP *bmp, int x1, int y, int x2, int color); Draws a horizontal line onto the bitmap, from point (x1, y) to (x2, y). Note: hline() is implemented as an alias to another function. See ALLEGRO_NO_VHLINE_ALIAS in the `Differences between platforms' section for details. void do_line(BITMAP *bmp, int x1, y1, x2, y2, int d, void (*proc)(BITMAP *bmp, int x, int y, int d)); Calculates all the points along a line from point (x1, y1) to (x2, y2), calling the supplied function for each one. This will be passed a copy of the bmp parameter, the x and y position, and a copy of the d parameter, so it is suitable for use with putpixel(). Example: 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); 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); 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); Draws a filled triangle between the three points. void polygon(BITMAP *bmp, int vertices, const int *points, int color); Draws a filled polygon with an arbitrary number of corners. Pass the number of vertices and an array containing a series of x, y points (a total of vertices*2 values). Example: 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); 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); 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)); 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); Draws a circle with the specified centre and radius. void circlefill(BITMAP *bmp, int x, int y, int radius, int color); 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)); 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); Draws an ellipse with the specified centre and radius. void ellipsefill(BITMAP *bmp, int x, int y, int rx, int ry, int color); 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)); 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) { ... } do_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); 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); 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); 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); Floodfills an enclosed area, starting at point (x, y), with the specified color. ============================================== ============ Blitting and sprites ============ ============================================== As far as Allegro is concerned, a bitmap and a sprite are the same thing, but to many people the two words imply slightly different things. The function draw_sprite() is called so rather than draw_bitmap() partly because it indicates that it uses a masked drawing mode (if it existed, you could expect draw_bitmap() to be a simple block copy), and partly for historical reasons. In Allegro 1.0 there were actually different structures for sprites and bitmaps, each with their own set of abilities. Allegro 2.0 merged these into a single more flexible structure, but retained some names like draw_sprite(). In wider (non-Allegro) terms, the two words can mean quite different things. Generally you can say that sprites are a subset of bitmaps, but even that isn't true in 100% of cases. BITMAP: a widely accepted term that will be understood by anyone even remotely connected with computer graphics. It simply means an image built up from a grid of pixels, ie. just about any picture that you are likely to come across on a computer (vector graphics formats are the exception, but those must be rendered into a bitmap format before they can be displayed by most hardware). A more accurate term but slightly rarer term with the same meaning is "pixmap" (pixel-map). SPRITE: a particular usage of bitmapped images, restricted to video games (other types of programmer probably won't be familiar with this term). Originally on machines like the C64, sprites were a hardware feature that allowed a number of small bitmap images to be loaded into special registers, and they could then be superimposed over the main graphics display and moved around just by modifying the position register. They were used for the moving objects (player and enemy characters), and enabled the C64 to do much more impressive things than would have been possible if all the drawing had to be done directly by the puny CPU. Later on, a lot of old C64 programmers upgraded to machines like the Atari ST, which didn't have any special sprite hardware, but they carried on referring to their main moving objects as sprites (the routine to draw such a thing would obviously be called draw_sprite()). A sprite is really just a bitmap graphic which is drawn onto the screen, but when you call it a sprite rather than a bitmap, this suggests it is a gameplay element that can move freely around the world rather than being a static part of the environment, and that it will be drawn in a masked overlay mode rather than as a solid rectangle (there is also a strong implication that a sprite will be animated by cycling through a number of frames, but that isn't always the case). In recent years some people have started using "sprite" to refer to any character graphics, even if they are not in fact drawn as 2d bitmaps, eg. "this game uses 3d polygonal player sprites". This is a confusing misuse of the word (Doom uses sprites, Quake does not), but it does happen. The origin of the term "blit" is also rather interesting. This was originally BitBlt, an abbreviation of BITmap BLock Transfer, which was a function designed (possibly) by the people at Xerox who did so much of the pioneering work on graphics display systems, and subsequently copied by virtually everybody doing computer graphics (the Microsoft Windows GDI still provides a BitBlt function with identical functionality to the original). This routine was a workhorse for all sorts of drawing operations, basically copying bitmap graphics from one place to another, but including a number of different ROP modes (Raster OPerations) for doing things like XOR, inverting pixels, etc. A whole family of related words grew up around the BitBlt function, but "blt" is impossible to speak (try saying "bltter" or "bltting" :-) so people added the vowel to make it easier to pronounce. Therefore, the act of calling the BitBlt function came to be known as "doing a blit". The obvious next step was to rename the function itself to blit(), which generally took place at the same time as people decided to simplify the original, removing the different ROP modes on the grounds that they aren't needed for games coding and don't work well with anything higher than monochrome images in any case. This leaves us with a function called blit(), which is an abbreviation for "block transfer". A strong case could be made for calling this blot() instead, but somehow that just doesn't sound the same! Anyway, all the routines in this chapter are affected by the clipping rectangle of the destination bitmap. void blit(BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height); Copies a rectangular area of the source bitmap to the destination bitmap. The source_x and source_y parameters are the top left corner of the area to copy from the source bitmap, and dest_x and dest_y are the corresponding position in the destination bitmap. This routine respects the destination clipping rectangle, and it will also clip if you try to blit from areas outside the source bitmap. Example: 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); 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); 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); 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_ex(BITMAP *bmp, BITMAP *sprite, int x, int y, int mode, int flip); Draws the sprite image onto the destination bitmap using the specified mode argument, optionally flipping the sprite in the orientation specified by flip argument. The mode argument defines how is sprite going to be drawn on the destination bitmap: DRAW_SPRITE_NORMAL - draws a masked sprite, like draw_sprite() DRAW_SPRITE_LIT - draws a tinted sprite, like draw_lit_sprite() DRAW_SPRITE_TRANS - draws a blended sprite, like draw_trans_sprite() The flip argument defines the flipping orientation: DRAW_SPRITE_NO_FLIP = 0 - do not perform flipping DRAW_SPRITE_H_FLIP - flip horizontally DRAW_SPRITE_V_FLIP - flip vertically DRAW_SPRITE_VH_FLIP - flip both vertically and horizontally void draw_sprite(BITMAP *bmp, BITMAP *sprite, int x, int y); Draws a copy of the sprite bitmap onto the destination bitmap at the specified position. This is almost the same as blit(sprite, bmp, 0, 0, x, y, sprite->w, sprite->h), but it uses a masked drawing mode where transparent pixels are skipped, so the background image will show through the masked parts of the sprite. Transparent pixels are marked by a zero in 256-color modes or bright pink for truecolor data (maximum red and blue, zero green). Example: 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); 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 int width = SCREEN_W / step; int height = SCREEN_H / step; stretch_sprite(screen, image, SCREEN_W / 2 - width / 2, SCREEN_H / 2 - height / 2, width, height); } 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); 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_sprite_h_flip(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); 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); 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, 64); void draw_gouraud_sprite(BITMAP *bmp, BITMAP *sprite, int x, int y, int c1, int c2, int c3, int c4); More sophisticated version of draw_lit_sprite(): the 'color' parameter is not constant across the sprite image anymore but interpolated between the four specified corner colors. The corner values passed to this function indicate the strength of the color applied on them, ranging from 0 (no strength) to 255 (full strength). Example: /* 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); 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); 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); 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); 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); 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); 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); 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); 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); 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. void rotate_sprite_trans(BITMAP *bmp, BITMAP *sprite, int x, int y, fixed angle); Draws the sprite image onto the bitmap. It is placed with its top left corner at the specified position, then rotated by the specified angle around its centre. The angle is a fixed point 16.16 number in the same format used by the fixed point trig routines, with 256 equal to a full circle, 64 a right angle, etc. All rotation functions can draw between any two bitmaps, even screen bitmaps or bitmaps of different color depth. Positive increments of the angle will make the sprite rotate clockwise on the screen, as demonstrated by the Allegro example. void rotate_sprite_v_flip_trans(BITMAP *bmp, BITMAP *sprite, int x, int y, fixed angle); Like rotate_sprite_trans, 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_trans(BITMAP *bmp, BITMAP *sprite, int x, int y, fixed angle, fixed scale); Like rotate_sprite_trans(), but stretches or shrinks the image at the same time as rotating it. void rotate_scaled_sprite_v_flip_trans(BITMAP *bmp, BITMAP *sprite, int x, int y, fixed angle, fixed scale); Draws the sprite, similar to rotate_scaled_sprite_trans() except that it flips the sprite vertically first. void pivot_sprite_trans(BITMAP *bmp, BITMAP *sprite, int x, int y, int cx, int cy, fixed angle); Like rotate_sprite_trans(), 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_trans(BITMAP *bmp, BITMAP *sprite, int x, int y, int cx, int cy, fixed angle); Like rotate_sprite_v_flip_trans(), 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_trans(BITMAP *bmp, BITMAP *sprite, int x, int y, int cx, int cy, fixed angle, fixed scale); Like rotate_scaled_sprite_trans(), 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_trans(BITMAP *bmp, BITMAP *sprite, int x, int y, int cx, int cy, fixed angle, fixed scale); Like rotate_scaled_sprite_v_flip_trans(), 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 rotate_sprite_lit(BITMAP *bmp, BITMAP *sprite, int x, int y, fixed angle); Draws the sprite image onto the bitmap. It is placed with its top left corner at the specified position, then rotated by the specified angle around its centre. The angle is a fixed point 16.16 number in the same format used by the fixed point trig routines, with 256 equal to a full circle, 64 a right angle, etc. All rotation functions can draw between any two bitmaps, even screen bitmaps or bitmaps of different color depth. Positive increments of the angle will make the sprite rotate clockwise on the screen, as demonstrated by the Allegro example. void rotate_sprite_v_flip_lit(BITMAP *bmp, BITMAP *sprite, int x, int y, fixed angle); Like rotate_sprite_lit, 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_lit(BITMAP *bmp, BITMAP *sprite, int x, int y, fixed angle, fixed scale); Like rotate_sprite_lit(), but stretches or shrinks the image at the same time as rotating it. void rotate_scaled_sprite_v_flip_lit(BITMAP *bmp, BITMAP *sprite, int x, int y, fixed angle, fixed scale); Draws the sprite, similar to rotate_scaled_sprite_lit() except that it flips the sprite vertically first. void pivot_sprite_lit(BITMAP *bmp, BITMAP *sprite, int x, int y, int cx, int cy, fixed angle); Like rotate_sprite_lit(), 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_lit(BITMAP *bmp, BITMAP *sprite, int x, int y, int cx, int cy, fixed angle); Like rotate_sprite_v_flip_lit(), 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_lit(BITMAP *bmp, BITMAP *sprite, int x, int y, int cx, int cy, fixed angle, fixed scale); Like rotate_scaled_sprite_lit(), 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_lit(BITMAP *bmp, BITMAP *sprite, int x, int y, int cx, int cy, fixed angle, fixed scale); Like rotate_scaled_sprite_v_flip_lit(), but aligns the point in the sprite given by (cx, cy) to (x, y) in the bitmap, then rotates and scales around this point. ===================================== ============ 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); 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); 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); 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); 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); 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); 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, 64); ========================================== ============ 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); 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); 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); 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... =============================== ============ 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)); 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); 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(myfont); 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); 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. void make_trans_font(FONT *f); This function converts a font to use transparency for drawing. That is, each glyph in the font will be drawn with draw_trans_sprite, so you can use the same blenders as with draw_trans_sprite to draw the font. One common use of this is to load a bitmap font with an alpha channel, and therefore get anti-aliased text output by using Allegro's alpha blender. Here's an example how to do that: FONT *f = load_font("alphafont.tga", NULL, NULL); make_trans_font(f); set_alpha_blender(); textprintf_centre_ex(screen, f, 320, 240, -1, -1, "Anti-aliased Font!"); int is_trans_font(FONT *f) This function checks if the given font is a color font using draw_trans_sprite to render glyphs. Returns TRUE if the font uses transparency, FALSE if it does not. int is_color_font(FONT *f) This function checks if the given font is a color font, as opposed to a monochrome font. Returns TRUE if the font is a color font, FALSE if it is not. int is_mono_font(FONT *f) This function checks if the given font is a mono font, as opposed to a color font. Returns TRUE if the font is a monochrome font, FALSE if it is not. int font_has_alpha(FONT *f) This function goes through all pixels of all glyphs in the font and looks for alpha values. Returns TRUE if any alpha pixels are found, else FALSE. int *is_compatible_font(FONT *f1, FONT *f2) This function compares the two fonts, which you can use to find out if Allegro is capable of merging them. Returns TRUE if the two fonts are of the same general type (both are color fonts or both are monochrome fonts, for instance). int get_font_ranges(FONT *f) Use this function to find out the number of character ranges in a font. You should query each of these ranges with get_font_range_begin() and get_font_range_end() to find out what characters are available in the font. Example: 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)); 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) 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)); 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) 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)); 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) 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); 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) 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); Returns 0 on success, -1 on failure. FONT *merge_fonts(FONT *f1, FONT *f2) This function merges the character ranges from two fonts and returns a new font containing all characters in the old fonts. In general, you cannot merge fonts of different types (eg, TrueType fonts and bitmapped fonts), but as a special case, this function can promote a monochrome bitmapped font to a color font and merge those. Example: FONT *myfont; FONT *myfancy_font; FONT *lower_range; FONT *upper_range; FONT *capitals; FONT *combined_font; FONT *tempfont; ... /* Create a font that contains the capitals from */ /* the fancy font but other characters from myfont */ lower_range = extract_font_range(myfont, -1, 'A'-1); upper_range = extract_font_range(myfont, 'Z'+1, -1); capitals = extract_font_range(myfancy_font, 'A', 'Z'); tempfont = merge_fonts(lower_range, capitals); combined_font = merge_fonts(tempfont, upper_range); /* Clean up temporary fonts */ destroy_font(lower_range); destroy_font(upper_range); destroy_font(capitals); destroy_font(tempfont); 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) 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); 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) Loads a 8x8 or 8x16 BIOS format font. You shouldn't normally call this routine directly. Returns a pointer to the font or NULL on error. Remember that you are responsible for destroying the font when you are finished with it to avoid memory leaks. FONT *load_grx_font(const char *filename, RGB *pal, void *param) Loads a GRX format font. You shouldn't normally call this routine directly. Returns a pointer to the font or NULL on error. Remember that you are responsible for destroying the font when you are finished with it to avoid memory leaks. FONT *load_grx_or_bios_font(const char *filename, RGB *pal, void *param) Loads either a BIOS or GRX format font. You shouldn't normally call this routine directly. Returns a pointer to the font or NULL on error. Remember that you are responsible for destroying the font when you are finished with it to avoid memory leaks. FONT *load_bitmap_font(const char *filename, RGB *pal, void *param) Tries to grab a font from a bitmap. The bitmap can be in any format that load_bitmap understands. The size of each character is determined by the layout of the image, which should be a rectangular grid containing all the ASCII characters from space (32) up to the tilde (126). The way the characters are separated depends on the color depth of the image file: 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 color depth when you load the font. If you try to use a font on a bitmap with a different color depth Allegro will do color conversions on the fly, which will be rather slow. For optimal performance you should set the color depth to the color depth you want to use before loading any fonts. Returns a pointer to the font or NULL on error. Remember that you are responsible for destroying the font when you are finished with it to avoid memory leaks. FONT *grab_font_from_bitmap(BITMAP *bmp) This function is the work-horse of load_bitmap_font, and can be used to grab a font from a bitmap in memory. You can use this if you want to generate or modify a font at runtime. The bitmap should follow the layout described for load_bitmap_font. Returns a pointer to the font or NULL on error. Remember that you are responsible for destroying the font when you are finished with it to avoid memory leaks. FONT *load_txt_font(const char *filename, RGB *pal, void *param) This function can be used to load scripted fonts. The script file contains a number of lines in the format "filename start end", which specify the source file for that range of characters, the Unicode value of the first character in the range, and the end character in the range (optional, if left out, the entire input file will be grabbed). If the filename is replaced by a hyphen, more characters will be grabbed from the previous input file. For example, the script: 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. Returns a pointer to the font or NULL on error. Remember that you are responsible for destroying the font when you are finished with it to avoid memory leaks. ===================================== ============ Text 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; 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; 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); 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) 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); 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); 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); 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); 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, ...); 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, ...); 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, ...); 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, ...); 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); =========================================== ============ 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 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 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 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 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 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 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 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 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 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 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[]); 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); 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); 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[]); 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